Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 17:ff9d1e86ad5f, committed 2019-11-20
- Comitter:
- sPymbed
- Date:
- Wed Nov 20 13:27:48 2019 +0000
- Parent:
- 16:048e5e270a58
- Commit message:
- removed: wolfcrypt
Changed in this revision
--- 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, ©);
- 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, ©);
- 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(©Into->ticketNonce, ©From->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, ©);
+ 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, ©);
+ 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(©Into->ticketNonce, ©From->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, ¤t->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, ¤t->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*)§or;
- 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*)§or;
- 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(<ime, 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(<cPoint);
- #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, <cPoint, kLTC_Ed25519 /* result on Ed25519 */);
- LTC_PKHA_Ed25519_Compress(<cPoint, 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(¶ms);
- params.mode = Semaphore_Mode_BINARY;
-
- *m = Semaphore_create(1, ¶ms, &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 */
-