wolfSSL 3.11.1 for TLS1.3 beta
Fork of wolfSSL by
Revision 4:1b0d80432c79, committed 2016-04-28
- Comitter:
- wolfSSL
- Date:
- Thu Apr 28 00:57:21 2016 +0000
- Parent:
- 3:6f956bdb3073
- Child:
- 5:dc26f46317d3
- Child:
- 6:fa3bd0ca5896
- Commit message:
- wolfSSL 3.9.0
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/crl.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,901 @@ +/* crl.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + +#ifndef NO_FILESYSTEM + #include <dirent.h> + #include <sys/stat.h> +#endif + +#include <string.h> + +#ifdef HAVE_CRL_MONITOR + static int StopMonitor(int mfd); +#endif + + +/* Initialize CRL members */ +int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("InitCRL"); + + 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 (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) +{ + 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; + + return 0; +} + + +/* Free all CRL Entry resources */ +static void FreeCRL_Entry(CRL_Entry* crle) +{ + RevokedCert* tmp = crle->certs; + + WOLFSSL_ENTER("FreeCRL_Entry"); + + while(tmp) { + RevokedCert* next = tmp->next; + XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED); + tmp = next; + } +} + + + +/* 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, NULL, DYNAMIC_TYPE_CRL_MONITOR); + + if (crl->monitors[1].path) + XFREE(crl->monitors[1].path, NULL, DYNAMIC_TYPE_CRL_MONITOR); + + while(tmp) { + CRL_Entry* next = tmp->next; + FreeCRL_Entry(tmp); + XFREE(tmp, NULL, 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 + FreeMutex(&crl->crlLock); + if (dynamic) /* free self */ + XFREE(crl, NULL, DYNAMIC_TYPE_CRL); +} + + +/* Is the cert ok with CRL, return 0 on success */ +int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +{ + CRL_Entry* crle; + int foundEntry = 0; + int ret = 0; + + WOLFSSL_ENTER("CheckCertCRL"); + + if (LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("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"); + WOLFSSL_MSG("Checking next date validity"); + + #ifdef WOLFSSL_NO_CRL_NEXT_DATE + if (crle->nextDateFormat == ASN_OTHER_TYPE) + doNextDate = 0; /* skip */ + #endif + + if (doNextDate && !ValidateDate(crle->nextDate, + crle->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + ret = ASN_AFTER_DATE_E; + } + else + foundEntry = 1; + break; + } + crle = crle->next; + } + + if (foundEntry) { + RevokedCert* rc = crle->certs; + + while (rc) { + if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) { + WOLFSSL_MSG("Cert revoked"); + ret = CRL_CERT_REVOKED; + break; + } + rc = rc->next; + } + } + + UnLockMutex(&crl->crlLock); + + 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->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) +{ + CRL_Entry* crle; + + WOLFSSL_ENTER("AddCRL"); + + crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY); + if (crle == NULL) { + WOLFSSL_MSG("alloc CRL Entry failed"); + return -1; + } + + if (InitCRL_Entry(crle, dcrl) < 0) { + WOLFSSL_MSG("Init CRL Entry failed"); + XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY); + return -1; + } + + if (LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("LockMutex failed"); + FreeCRL_Entry(crle); + XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY); + return BAD_MUTEX_E; + } + crle->next = crl->crlList; + crl->crlList = crle; + UnLockMutex(&crl->crlLock); + + return 0; +} + + +/* Load CRL File of type, SSL_SUCCESS on ok */ +int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) +{ + int ret = SSL_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 == SSL_FILETYPE_PEM) { + int eccKey = 0; /* not used */ + EncryptedInfo info; + info.ctx = NULL; + + ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey); + if (ret == 0) { + myBuffer = der->buffer; + sz = der->length; + } + else { + WOLFSSL_MSG("Pem to Der failed"); + FreeDer(&der); + return -1; + } + } + +#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); + ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); + if (ret != 0) { + WOLFSSL_MSG("ParseCRL error"); + } + else { + ret = AddCRL(crl, dcrl); + 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 : SSL_SUCCESS; /* convert 0 to SSL_SUCCESS */ +} + + +#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 (LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("LockMutex crlLock failed"); + return BAD_MUTEX_E; + } + + crl->setup = status; + ret = pthread_cond_signal(&crl->cond); + + 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, SSL_FILETYPE_PEM, 0); + if (ret != SSL_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, SSL_FILETYPE_ASN1, 0); + if (ret != SSL_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 (LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("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; + + 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 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; +} + + +#else + +#error "CRL monitor only currently supported on linux or mach" + +#endif /* MACH or linux */ + + +/* Start Monitoring the CRL path(s) in a thread */ +static int StartMonitorCRL(WOLFSSL_CRL* crl) +{ + int ret = SSL_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 (LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("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 */ + + 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 */ + +#ifndef NO_FILESYSTEM + +/* Load CRL path files of type, SSL_SUCCESS on ok */ +int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) +{ + struct dirent* entry; + DIR* dir; + int ret = SSL_SUCCESS; +#ifdef WOLFSSL_SMALL_STACK + char* name; +#else + char name[MAX_FILENAME_SZ]; +#endif + + WOLFSSL_ENTER("LoadCRL"); + if (crl == NULL) + return BAD_FUNC_ARG; + + dir = opendir(path); + if (dir == NULL) { + WOLFSSL_MSG("opendir path crl load failed"); + return BAD_PATH_ERROR; + } + +#ifdef WOLFSSL_SMALL_STACK + name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (name == NULL) + return MEMORY_E; +#endif + + while ( (entry = readdir(dir)) != NULL) { + struct stat s; + + XMEMSET(name, 0, MAX_FILENAME_SZ); + XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); + XSTRNCAT(name, "/", 1); + XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); + + if (stat(name, &s) != 0) { + WOLFSSL_MSG("stat on name failed"); + continue; + } + if (s.st_mode & S_IFREG) { + + if (type == SSL_FILETYPE_PEM) { + if (XSTRSTR(entry->d_name, ".pem") == NULL) { + WOLFSSL_MSG("not .pem file, skipping"); + continue; + } + } + else { + if (XSTRSTR(entry->d_name, ".der") == NULL && + XSTRSTR(entry->d_name, ".crl") == NULL) { + + WOLFSSL_MSG("not .der or .crl file, skipping"); + continue; + } + } + + if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) + != SSL_SUCCESS) { + WOLFSSL_MSG("CRL file load failed, continuing"); + } + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(name, NULL, 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, NULL, DYNAMIC_TYPE_CRL_MONITOR); + if (pathBuf) { + XSTRNCPY(pathBuf, path, pathLen); + pathBuf[pathLen] = '\0'; /* Null Terminate */ + + if (type == SSL_FILETYPE_PEM) { + crl->monitors[0].path = pathBuf; + crl->monitors[0].type = SSL_FILETYPE_PEM; + } else { + crl->monitors[1].path = pathBuf; + crl->monitors[1].type = SSL_FILETYPE_ASN1; + } + + if (monitor & WOLFSSL_CRL_START_MON) { + WOLFSSL_MSG("start monitoring requested"); + + ret = StartMonitorCRL(crl); + } + } + else { + ret = MEMORY_E; + } + } + + closedir(dir); + + return ret; +} + +#endif /* NO_FILESYSTEM */ + +#endif /* HAVE_CRL */ +#endif /* !WOLFCRYPT_ONLY */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internal.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,17730 @@ +/* internal.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #include <wolfcrypt/src/misc.c> +#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) + #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 + +#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 + +static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, + const byte* input, int inSz, int type, int hashOutput); + +#ifndef NO_WOLFSSL_CLIENT + static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*, + word32); + static int DoServerHello(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 DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32); + static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32); + #if !defined(NO_RSA) || defined(HAVE_ECC) + static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32); + #endif + #ifdef HAVE_STUNNEL + static int SNI_Callback(WOLFSSL* ssl); + #endif + #ifdef WOLFSSL_DTLS + static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte); + #endif /* WOLFSSL_DTLS */ +#endif + + +#ifdef WOLFSSL_DTLS + static INLINE int DtlsCheckWindow(DtlsState* state); + static INLINE int DtlsUpdateWindow(DtlsState* state); +#endif + + +typedef enum { + doProcessInit = 0, +#ifndef NO_WOLFSSL_SERVER + runProcessOldClientHello, +#endif + getRecordLayerHeader, + getData, + runProcessingOneMessage +} processReply; + +#ifndef NO_OLD_TLS +static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, + int content, int verify); + +#endif + +#ifndef NO_CERTS +static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); +#endif + +#ifdef HAVE_QSH + int QSH_Init(WOLFSSL* ssl); +#endif + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +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; + if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR) + return 1; + + return 0; +} + + +static 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.dtls_state.curEpoch == 0) + return 0; + #endif /* WOLFSSL_DTLS */ + + return ssl->keys.encryptionOn; +} + + +#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_TMP_ARRAY); + } + if (key->pub.buffer) + XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + key = (QSHKey*)key->next; + + /* free struct */ + XFREE(preKey, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + } + 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_TMP_ARRAY); + } + if (key->pub.buffer) + XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + key = (QSHKey*)key->next; + + /* free struct */ + XFREE(preKey, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + } + 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_TMP_ARRAY); + list = (QSHScheme*)list->next; + XFREE(preList, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + } + + /* 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_TMP_ARRAY); + } + XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + } + 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_TMP_ARRAY); + } + XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + } + } + XFREE(secret, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + 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_TLSX)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitRng(rng); + } + + if (rngMutex == NULL) { + if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), 0, + DYNAMIC_TYPE_TLSX)) == NULL) + return DRBG_OUT_OF_MEMORY; + InitMutex(rngMutex); + } + + ret |= LockMutex(rngMutex); + ret |= wc_RNG_GenerateBlock(rng, out, num_bytes); + ret |= UnLockMutex(rngMutex); + + if (ret != 0) + return DRBG_ENTROPY_FAIL; + + return DRBG_OK; +} +#endif /* HAVE_NTRU */ + +/* used by ssl.c too */ +void c32to24(word32 in, word24 out) +{ + out[0] = (in >> 16) & 0xff; + out[1] = (in >> 8) & 0xff; + out[2] = in & 0xff; +} + + +#ifdef WOLFSSL_DTLS + +static INLINE void c32to48(word32 in, byte out[6]) +{ + out[0] = 0; + out[1] = 0; + out[2] = (in >> 24) & 0xff; + out[3] = (in >> 16) & 0xff; + out[4] = (in >> 8) & 0xff; + out[5] = in & 0xff; +} + +#endif /* WOLFSSL_DTLS */ + + +/* convert 16 bit integer to opaque */ +static INLINE void c16toa(word16 u16, byte* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} + + +#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \ + || defined(HAVE_AESGCM) +/* convert 32 bit integer to opaque */ +static INLINE void c32toa(word32 u32, byte* c) +{ + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} +#endif + + +/* convert a 24 bit integer into a 32 bit one */ +static INLINE void c24to32(const word24 u24, word32* u32) +{ + *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; +} + + +/* convert opaque to 16 bit integer */ +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (word16) ((c[0] << 8) | (c[1])); +} + + +#if defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET) + +/* convert opaque to 32 bit integer */ +static INLINE void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} + +#endif /* WOLFSSL_DTLS */ + + +#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 */ + + +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) +{ + 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 = TLSv1_MINOR; /* current default */ + + if (InitMutex(&ctx->countMutex) < 0) { + WOLFSSL_MSG("Mutex error on CTX init"); + return BAD_MUTEX_E; + } + +#ifndef NO_DH + ctx->minDhKeySz = MIN_DHKEY_SZ; +#endif + +#ifdef HAVE_ECC + ctx->eccTempKeySz = ECDHE_SIZE; +#endif + +#ifndef WOLFSSL_USER_IO + ctx->CBIORecv = EmbedReceive; + ctx->CBIOSend = EmbedSend; + #ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) { + ctx->CBIORecv = EmbedReceiveFrom; + ctx->CBIOSend = EmbedSendTo; + } + #endif +#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 cliet side */ + /* server can turn on by loading key */ +#endif +#ifdef HAVE_ECC + if (method->side == WOLFSSL_CLIENT_END) { + ctx->haveECDSAsig = 1; /* always on cliet side */ + ctx->haveECC = 1; /* server turns on with ECC key cert */ + ctx->haveStaticECC = 1; /* server can turn on by loading key */ + } +#endif + +#ifdef HAVE_CAVIUM + ctx->devId = NO_CAVIUM_DEVICE; +#endif + +#ifndef NO_CERTS + ctx->cm = wolfSSL_CertManagerNew(); + if (ctx->cm == NULL) { + WOLFSSL_MSG("Bad Cert Manager New"); + return BAD_CERT_MANAGER_ERROR; + } +#endif + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) + ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT; +#endif + + return 0; +} + + +/* In case contexts are held in array and don't want to free actual ctx */ +void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) +{ + int i; + + (void)i; + + 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_DH); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); +#endif + +#ifndef NO_CERTS + FreeDer(&ctx->privateKey); + FreeDer(&ctx->certificate); + FreeDer(&ctx->certChain); + wolfSSL_CertManagerFree(ctx->cm); +#endif + +#ifdef HAVE_TLS_EXTENSIONS + TLSX_FreeAll(ctx->extensions); + +#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, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + } +#endif + +#if defined(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], NULL, DYNAMIC_TYPE_OCSP_REQUEST); + } + } +#endif + +#endif /* NO_WOLFSSL_SERVER */ + +#endif /* HAVE_TLS_EXTENSIONS */ +} + + +void FreeSSL_Ctx(WOLFSSL_CTX* ctx) +{ + int doFree = 0; + + if (LockMutex(&ctx->countMutex) != 0) { + WOLFSSL_MSG("Couldn't lock count mutex"); + return; + } + ctx->refCount--; + if (ctx->refCount == 0) + doFree = 1; + UnLockMutex(&ctx->countMutex); + + if (doFree) { + WOLFSSL_MSG("CTX ref count down to 0, doing full free"); + SSL_CtxResourceFree(ctx); + 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 + #ifdef HAVE_CAVIUM + if (ssl->devId != NO_CAVIUM_DEVICE) { + wc_Arc4FreeCavium(ssl->encrypt.arc4); + wc_Arc4FreeCavium(ssl->decrypt.arc4); + } + #endif + XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef BUILD_DES3 + #ifdef HAVE_CAVIUM + if (ssl->devId != NO_CAVIUM_DEVICE) { + wc_Des3_FreeCavium(ssl->encrypt.des3); + wc_Des3_FreeCavium(ssl->decrypt.des3); + } + #endif + XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef BUILD_AES + #ifdef HAVE_CAVIUM + if (ssl->devId != NO_CAVIUM_DEVICE) { + wc_AesFreeCavium(ssl->encrypt.aes); + wc_AesFreeCavium(ssl->decrypt.aes); + } + #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) +{ + 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; + + cs->hash_size = 0; + cs->static_ecdh = 0; + cs->key_size = 0; + cs->iv_size = 0; + cs->block_size = 0; +} + +static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, + int haveRSAsig, int haveAnon) +{ + int idx = 0; + + if (haveECDSAsig) { + #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 + #ifndef NO_SHA + suites->hashSigAlgo[idx++] = sha_mac; + suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; + #endif + } + + if (haveRSAsig) { + #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 + #ifndef NO_SHA + suites->hashSigAlgo[idx++] = sha_mac; + suites->hashSigAlgo[idx++] = rsa_sa_algo; + #endif + } + + if (haveAnon) { + #ifdef HAVE_ANON + suites->hashSigAlgo[idx++] = sha_mac; + suites->hashSigAlgo[idx++] = anonymous_sa_algo; + #endif + } + + suites->hashSigAlgoSz = (word16)idx; +} + +void InitSuites(Suites* suites, ProtocolVersion pv, 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; + 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; + + if (suites == NULL) { + WOLFSSL_MSG("InitSuites pointer error"); + return; + } + + if (suites->setSuites) + return; /* trust user settings, don't override */ + + if (side == WOLFSSL_SERVER_END && haveStaticECC) { + haveRSA = 0; /* can't do RSA with ECDSA key */ + (void)haveRSA; /* some builds won't read */ + } + + if (side == WOLFSSL_SERVER_END && haveECDSAsig) { + haveRSAsig = 0; /* can't have RSA sig if signed by ECDSA */ + (void)haveRSAsig; /* non ecc builds won't read */ + } + +#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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveDH && havePSK) { + suites->suites[idx++] = 0; + 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++] = 0; + 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++] = 0; + 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 + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + if (tls1_2 && haveRSAsig) { + 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 && haveRSAsig) { + 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_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 (tls1_2 && haveDH && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + if (tls1_2 && haveDH && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 + if (tls && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + if (tls && havePSK) { + suites->suites[idx++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 + if (tls && havePSK) { + suites->suites[idx++] = 0; + 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++] = 0; + suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 + if (tls && havePSK) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA + if (tls && havePSK) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA; + } +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA + if (!dtls && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA; + } +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 + if (!dtls && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5; + } +#endif + +#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + if (haveRSA ) { + suites->suites[idx++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + if (tls && haveRSA) { + suites->suites[idx++] = 0; + 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++] = 0; + 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++] = 0; + suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DHE_WITH_RSA_CAMELLIA_256_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + 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++] = 0; + suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA; + } +#endif + + suites->suiteSz = idx; + + InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0); +} + + +#ifndef NO_CERTS + + +void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag) +{ + (void)dynamicFlag; + + if (name != NULL) { + name->name = name->staticName; + name->dynamicName = 0; +#ifdef OPENSSL_EXTRA + XMEMSET(&name->fullName, 0, sizeof(DecodedName)); +#endif /* OPENSSL_EXTRA */ + } +} + + +void FreeX509Name(WOLFSSL_X509_NAME* name) +{ + if (name != NULL) { + if (name->dynamicName) + XFREE(name->name, NULL, DYNAMIC_TYPE_SUBJECT_CN); +#ifdef OPENSSL_EXTRA + if (name->fullName.fullName != NULL) + XFREE(name->fullName.fullName, NULL, DYNAMIC_TYPE_X509); +#endif /* OPENSSL_EXTRA */ + } +} + + +/* Initialize wolfSSL X509 type */ +void InitX509(WOLFSSL_X509* x509, int dynamicFlag) +{ + InitX509Name(&x509->issuer, 0); + InitX509Name(&x509->subject, 0); + x509->version = 0; + x509->pubKey.buffer = NULL; + x509->sig.buffer = NULL; + x509->derCert = NULL; + x509->altNames = NULL; + x509->altNamesNext = NULL; + x509->dynamicMemory = (byte)dynamicFlag; + x509->isCa = 0; +#ifdef HAVE_ECC + x509->pkCurveOID = 0; +#endif /* HAVE_ECC */ +#ifdef OPENSSL_EXTRA + x509->pathLength = 0; + x509->basicConstSet = 0; + x509->basicConstCrit = 0; + x509->basicConstPlSet = 0; + x509->subjAltNameSet = 0; + x509->subjAltNameCrit = 0; + x509->authKeyIdSet = 0; + x509->authKeyIdCrit = 0; + x509->authKeyId = NULL; + x509->authKeyIdSz = 0; + x509->subjKeyIdSet = 0; + x509->subjKeyIdCrit = 0; + x509->subjKeyId = NULL; + x509->subjKeyIdSz = 0; + x509->keyUsageSet = 0; + x509->keyUsageCrit = 0; + x509->keyUsage = 0; + #ifdef WOLFSSL_SEP + x509->certPolicySet = 0; + x509->certPolicyCrit = 0; + #endif /* WOLFSSL_SEP */ +#endif /* OPENSSL_EXTRA */ +} + + +/* Free wolfSSL X509 type */ +void FreeX509(WOLFSSL_X509* x509) +{ + if (x509 == NULL) + return; + + FreeX509Name(&x509->issuer); + FreeX509Name(&x509->subject); + if (x509->pubKey.buffer) + XFREE(x509->pubKey.buffer, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + FreeDer(&x509->derCert); + XFREE(x509->sig.buffer, NULL, DYNAMIC_TYPE_SIGNATURE); + #ifdef OPENSSL_EXTRA + XFREE(x509->authKeyId, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(x509->subjKeyId, NULL, DYNAMIC_TYPE_X509_EXT); + #endif /* OPENSSL_EXTRA */ + if (x509->altNames) + FreeAltNames(x509->altNames, NULL); +} + + +#ifndef NO_RSA + +/* Verify RSA signature, 0 on success */ +int VerifyRsaSign(const byte* sig, word32 sigSz, + const byte* plain, word32 plainSz, RsaKey* key) +{ + #ifdef WOLFSSL_SMALL_STACK + byte* verifySig = NULL; + #else + byte verifySig[ENCRYPT_LEN]; + #endif + byte* out = NULL; /* inline result */ + int ret; + + WOLFSSL_ENTER("VerifyRsaSign"); + + if (sig == NULL || plain == NULL || key == NULL) { + WOLFSSL_MSG("Null pointer input"); + return BAD_FUNC_ARG; + } + + if (sigSz > ENCRYPT_LEN) { + WOLFSSL_MSG("Signature buffer too big"); + return BUFFER_E; + } + + #ifdef WOLFSSL_SMALL_STACK + verifySig = (byte*)XMALLOC(ENCRYPT_LEN, NULL, + DYNAMIC_TYPE_SIGNATURE); + if (verifySig == NULL) + return MEMORY_ERROR; + #endif + + XMEMCPY(verifySig, sig, sigSz); + ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key); + + 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 */ + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(verifySig, NULL, DYNAMIC_TYPE_SIGNATURE); + #endif + + return ret; +} + +#endif /* NO_RSA */ + +#endif /* NO_CERTS */ + + +/* 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 + SSL_SUCCESS return value on success */ +int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +{ + byte havePSK = 0; + byte haveAnon = 0; + byte newSSL; + byte haveRSA = 0; + (void) haveAnon; /* Squash unused var warnings */ + + if(!ssl || !ctx || ssl->suites == NULL) + return BAD_FUNC_ARG; + + newSSL = ssl->ctx == NULL; /* Assign after null check */ + +#ifndef NO_PSK + if (ctx->server_hint[0] && ssl->arrays == NULL) { + 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*/ + + /* 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 (LockMutex(&ctx->countMutex) != 0) { + WOLFSSL_MSG("Couldn't lock CTX count mutex"); + return BAD_MUTEX_E; + } + ctx->refCount++; + 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->pkCurveOID = ctx->pkCurveOID; +#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; + + if (ssl->options.side == WOLFSSL_SERVER_END) + 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 HAVE_ANON + ssl->options.haveAnon = ctx->haveAnon; +#endif +#ifndef NO_DH + ssl->options.minDhKeySz = ctx->minDhKeySz; +#endif + + ssl->options.sessionCacheOff = ctx->sessionCacheOff; + ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff; + + 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->heap = ctx->heap; /* defaults to self */ + ssl->options.partialWrite = ctx->partialWrite; + ssl->options.quietShutdown = ctx->quietShutdown; + ssl->options.groupMessages = ctx->groupMessages; + +#ifndef NO_DH + if (ssl->options.side == WOLFSSL_SERVER_END) { + 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; + ssl->buffers.key = ctx->privateKey; +#endif + +#ifdef HAVE_CAVIUM + ssl->devId = ctx->devId; +#endif + +#ifndef NO_PSK + if (ctx->server_hint[0]) { /* set in CTX */ + XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, MAX_PSK_ID_LEN); + ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + } +#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, 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, haveRSA, havePSK, TRUE, + ssl->options.haveNTRU, ssl->options.haveECDSAsig, + ssl->options.haveECC, ssl->options.haveStaticECC, + ssl->options.side); + +#ifndef NO_CERTS + /* make sure server has cert and key unless using PSK or Anon + * This should be true even if just switching ssl ctx */ + if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon) + if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer || + !ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("Server missing certificate and/or private key"); + return NO_PRIVATE_KEY; + } +#endif + + return SSL_SUCCESS; +} + + +/* init everything to 0, NULL, default values before calling anything that may + fail so that destructor has a "good" state to cleanup + 0 on success */ +int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +{ + int ret; + + XMEMSET(ssl, 0, sizeof(WOLFSSL)); + + 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; + +#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS) + InitX509(&ssl->peerCert, 0); +#endif + + ssl->rfd = -1; /* set to invalid descriptor */ + ssl->wfd = -1; + + 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 +#ifdef WOLFSSL_DTLS + ssl->dtls_expected_rx = MAX_MTU; +#endif + + 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; + +#ifdef WOLFSSL_DTLS + ssl->dtls_timeout_init = DTLS_TIMEOUT_INIT; + ssl->dtls_timeout_max = DTLS_TIMEOUT_MAX; + ssl->dtls_timeout = ssl->dtls_timeout_init; +#endif + + #ifndef NO_OLD_TLS + ssl->hmac = SSL_hmac; /* default to SSLv3 */ + #else + ssl->hmac = TLS_hmac; + #endif + + +#ifdef WOLFSSL_DTLS + ssl->buffers.dtlsCtx.fd = -1; +#endif + + ssl->cipher.ssl = ssl; + +#ifdef HAVE_TLS_EXTENSIONS +#ifdef HAVE_MAX_FRAGMENT + ssl->max_fragment = MAX_RECORD_SIZE; +#endif +#ifdef HAVE_ALPN + ssl->alpn_client_list = NULL; +#endif +#endif + + /* 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; + + InitCiphers(ssl); + InitCipherSpecs(&ssl->specs); + + /* all done with init, now can return errors, call other stuff */ + + /* 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)); + + /* 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 */ + if((ret = SetSSL_CTX(ssl, ctx)) != SSL_SUCCESS) + return ret; + + ssl->options.dtls = ssl->version.major == DTLS_MAJOR; + + /* hsHashes */ + 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; + } + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + wc_InitMd5(&ssl->hsHashes->hashMd5); +#endif +#ifndef NO_SHA + ret = wc_InitSha(&ssl->hsHashes->hashSha); + if (ret != 0) { + return ret; + } +#endif +#endif +#ifndef NO_SHA256 + ret = wc_InitSha256(&ssl->hsHashes->hashSha256); + if (ret != 0) { + return ret; + } +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384(&ssl->hsHashes->hashSha384); + if (ret != 0) { + return ret; + } +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512(&ssl->hsHashes->hashSha512); + if (ret != 0) { + return ret; + } +#endif + + /* 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; + } + + if ( (ret = wc_InitRng(ssl->rng)) != 0) { + WOLFSSL_MSG("RNG Init error"); + 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 + return 0; +} + + +/* free use of temporary arrays */ +void FreeArrays(WOLFSSL* ssl, int keep) +{ + if (ssl->arrays && 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) { + 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; +} + + +/* 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); + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); + XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + 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_DH); + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); + /* parameters (p,g) may be owned by ctx */ + if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + } +#endif +#ifndef NO_CERTS + wolfSSL_UnloadCertsKeys(ssl); +#endif +#ifndef NO_RSA + if (ssl->peerRsaKey) { + wc_FreeRsaKey(ssl->peerRsaKey); + XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); + } +#endif + if (ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, FORCED_FREE); + if (ssl->buffers.outputBuffer.dynamicFlag) + ShrinkOutputBuffer(ssl); +#ifdef WOLFSSL_DTLS + DtlsPoolDelete(ssl); + if (ssl->dtls_msg_list != NULL) { + DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap); + ssl->dtls_msg_list = NULL; + } + 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 */ +#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) + 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 + if (ssl->peerEccKey) { + if (ssl->peerEccKeyPresent) + wc_ecc_free(ssl->peerEccKey); + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + } + if (ssl->peerEccDsaKey) { + if (ssl->peerEccDsaKeyPresent) + wc_ecc_free(ssl->peerEccDsaKey); + XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); + } + if (ssl->eccTempKey) { + if (ssl->eccTempKeyPresent) + wc_ecc_free(ssl->eccTempKey); + XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); + } +#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); + +#ifdef HAVE_ALPN + if (ssl->alpn_client_list != NULL) { + XFREE(ssl->alpn_client_list, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ssl->alpn_client_list = NULL; + } +#endif +#endif /* HAVE_TLS_EXTENSIONS */ +#ifdef HAVE_NETX + if (ssl->nxCtx.nxPacket) + nx_packet_release(ssl->nxCtx.nxPacket); +#endif +#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS) + FreeX509(&ssl->peerCert); +#endif +} + +#ifdef WOLFSSL_TI_HASH +static void HashFinal(WOLFSSL * ssl) { + byte dummyHash[32] ; +#ifndef NO_MD5 + wc_Md5Final(&(ssl->hsHashes->hashMd5), dummyHash) ; +#endif +#ifndef NO_SHA + wc_ShaFinal(&(ssl->hsHashes->hashSha), dummyHash) ; +#endif +#ifndef NO_SHA256 + wc_Sha256Final(&(ssl->hsHashes->hashSha256), dummyHash) ; +#endif +} +#else + + #define HashFinal(ssl) + +#endif + +/* Free any handshake resources no longer needed */ +void FreeHandshakeResources(WOLFSSL* ssl) +{ + + HashFinal(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 */ + XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes = NULL; + + /* RNG */ + if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + ssl->rng = NULL; + } + +#ifdef WOLFSSL_DTLS + /* DTLS_POOL */ + if (ssl->options.dtls) { + DtlsPoolDelete(ssl); + DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap); + ssl->dtls_msg_list = NULL; + } +#endif + + /* arrays */ + if (ssl->options.saveArrays == 0) + FreeArrays(ssl, 1); + +#ifndef NO_RSA + /* peerRsaKey */ + if (ssl->peerRsaKey) { + wc_FreeRsaKey(ssl->peerRsaKey); + XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); + ssl->peerRsaKey = NULL; + } +#endif + +#ifdef HAVE_ECC + if (ssl->peerEccKey) + { + if (ssl->peerEccKeyPresent) { + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccKey = NULL; + } + if (ssl->peerEccDsaKey) + { + if (ssl->peerEccDsaKeyPresent) { + wc_ecc_free(ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } + XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccDsaKey = NULL; + } + if (ssl->eccTempKey) + { + if (ssl->eccTempKeyPresent) { + wc_ecc_free(ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; + } + XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->eccTempKey = NULL; + } +#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_DH); + ssl->buffers.serverDH_Priv.buffer = NULL; + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_Pub.buffer = NULL; + /* parameters (p,g) may be owned by ctx */ + if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_G.buffer = NULL; + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_P.buffer = NULL; + } +#endif +#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 */ +#endif /* HAVE_PK_CALLBACKS */ + +#ifdef HAVE_QSH + QSH_FreeAll(ssl); +#endif +} + + +void FreeSSL(WOLFSSL* ssl) +{ + FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */ + SSL_ResourceFree(ssl); + XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL); +} + + +#ifdef WOLFSSL_DTLS + +int DtlsPoolInit(WOLFSSL* ssl) +{ + if (ssl->dtls_pool == NULL) { + DtlsPool *pool = (DtlsPool*)XMALLOC(sizeof(DtlsPool), + ssl->heap, DYNAMIC_TYPE_DTLS_POOL); + if (pool == NULL) { + WOLFSSL_MSG("DTLS Buffer Pool Memory error"); + return MEMORY_E; + } + else { + int i; + + for (i = 0; i < DTLS_POOL_SZ; i++) { + pool->buf[i].length = 0; + pool->buf[i].buffer = NULL; + } + pool->used = 0; + ssl->dtls_pool = pool; + } + } + return 0; +} + + +int DtlsPoolSave(WOLFSSL* ssl, const byte *src, int sz) +{ + DtlsPool *pool = ssl->dtls_pool; + if (pool != NULL && pool->used < DTLS_POOL_SZ) { + buffer *pBuf = &pool->buf[pool->used]; + pBuf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); + if (pBuf->buffer == NULL) { + WOLFSSL_MSG("DTLS Buffer Memory error"); + return MEMORY_ERROR; + } + XMEMCPY(pBuf->buffer, src, sz); + pool->epoch[pool->used] = ssl->keys.dtls_epoch; + pBuf->length = (word32)sz; + pool->used++; + } + return 0; +} + + +void DtlsPoolReset(WOLFSSL* ssl) +{ + DtlsPool *pool = ssl->dtls_pool; + if (pool != NULL) { + buffer *pBuf; + int i, used; + + used = pool->used; + for (i = 0, pBuf = &pool->buf[0]; i < used; i++, pBuf++) { + XFREE(pBuf->buffer, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); + pBuf->buffer = NULL; + pBuf->length = 0; + } + pool->used = 0; + } + ssl->dtls_timeout = ssl->dtls_timeout_init; +} + + +void DtlsPoolDelete(WOLFSSL* ssl) +{ + if (ssl->dtls_pool != NULL) { + DtlsPoolReset(ssl); + XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); + ssl->dtls_pool = NULL; + } +} + + +int DtlsPoolTimeout(WOLFSSL* ssl) +{ + int result = -1; + if (ssl->dtls_timeout < ssl->dtls_timeout_max) { + ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER; + result = 0; + } + return result; +} + + +int DtlsPoolSend(WOLFSSL* ssl) +{ + DtlsPool* pool = ssl->dtls_pool; + + if (pool != NULL && pool->used > 0) { + int ret = 0; + int i; + buffer* buf; + + for (i = 0, buf = pool->buf; i < pool->used; i++, buf++) { + if (pool->epoch[i] == 0) { + DtlsRecordLayerHeader* dtls; + word32* seqNumber; + + dtls = (DtlsRecordLayerHeader*)buf->buffer; + seqNumber = (ssl->keys.dtls_epoch == 0) ? + &ssl->keys.dtls_sequence_number : + &ssl->keys.dtls_prev_sequence_number; + c32to48((*seqNumber)++, dtls->sequence_number); + if ((ret = CheckAvailableSize(ssl, buf->length)) != 0) + return ret; + + XMEMCPY(ssl->buffers.outputBuffer.buffer, + buf->buffer, buf->length); + ssl->buffers.outputBuffer.idx = 0; + ssl->buffers.outputBuffer.length = buf->length; + } + else if (pool->epoch[i] == ssl->keys.dtls_epoch) { + byte* input; + byte* output; + int inputSz, sendSz; + + input = buf->buffer; + inputSz = buf->length; + 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); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + ssl->buffers.outputBuffer.length += sendSz; + } + + ret = SendBuffered(ssl); + if (ret < 0) { + return ret; + } + } + } + return 0; +} + + +/* 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; + + 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; + + 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; +} + + +DtlsMsg* DtlsMsgStore(DtlsMsg* head, 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. + */ + + 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); + return head; + } + 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); + return NULL; + } + } + + return 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; +} + +#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; +} + +ProtocolVersion MakeDTLSv1_2(void) +{ + ProtocolVersion pv; + pv.major = DTLS_MAJOR; + pv.minor = DTLSv1_2_MINOR; + + return pv; +} + +#endif /* WOLFSSL_DTLS */ + + + + +#ifdef 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) + { + NET_SECURE_OS_TICK clk = 0; + + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + clk = NetSecure_OS_TimeGet(); + #endif + return (word32)clk; + } + + +#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_KSDK_BM) || defined(FREESCALE_FREE_RTOS) + + #include "fsl_pit_driver.h" + + word32 LowResTimer(void) + { + return PIT_DRV_GetUs(); + } + +#elif defined(WOLFSSL_TIRTOS) + + word32 LowResTimer(void) + { + return (word32) Seconds_get(); + } + +#elif 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); + } + +#else /* !USE_WINDOWS_API && !HAVE_RTP_SYS && !MICRIUM && !USER_TICKS */ + + #include <time.h> + + word32 LowResTimer(void) + { + return (word32)time(0); + } + + +#endif /* USE_WINDOWS_API */ + + +#ifndef NO_CERTS +static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) +{ +#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 + + if (IsAtLeastTLSv1_2(ssl)) { + int ret; + +#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 + } + + return 0; +} +#endif /* NO_CERTS */ + + +/* add output to md5 and sha handshake hashes, exclude record header */ +static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) +{ + const byte* 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)) { + int ret; + +#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 + } + + return 0; +} + + +/* add input to md5 and sha handshake hashes, include handshake header */ +static int HashInput(WOLFSSL* ssl, const byte* input, int sz) +{ + const byte* adj = input - HANDSHAKE_HEADER_SZ; + sz += HANDSHAKE_HEADER_SZ; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + adj -= DTLS_HANDSHAKE_EXTRA; + sz += DTLS_HANDSHAKE_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)) { + int ret; + +#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 + } + + return 0; +} + + +/* 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; + rl->type = type; + rl->pvMajor = ssl->version.major; /* type and version same in each */ + 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; + c16toa(ssl->keys.dtls_epoch, dtls->epoch); + c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number); + c16toa((word16)length, dtls->length); +#endif + } +} + + +/* 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; + 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); +} + + +#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 */ + + +/* return bytes received, -1 on error */ +static int Receive(WOLFSSL* ssl, byte* buf, word32 sz) +{ + int recvd; + + if (ssl->ctx->CBIORecv == NULL) { + WOLFSSL_MSG("Your IO Recv callback is null, please set"); + return -1; + } + +retry: + recvd = ssl->ctx->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); + 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; + + case WOLFSSL_CBIO_ERR_TIMEOUT: +#ifdef WOLFSSL_DTLS + if (DtlsPoolTimeout(ssl) == 0 && DtlsPoolSend(ssl) == 0) + goto retry; + else +#endif + return -1; + + 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) + 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->ctx->CBIOSend == NULL) { + WOLFSSL_MSG("Your IO Send callback is null, please set"); + return SOCKET_ERROR_E; + } + + while (ssl->buffers.outputBuffer.length > 0) { + int sent = ssl->ctx->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); + 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 INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) +{ + byte* tmp; + byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ : + RECORD_HEADER_SZ; + byte align = WOLFSSL_GENERAL_ALIGNMENT; + /* 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; + } + + tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length + align, + ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + WOLFSSL_MSG("growing output buffer\n"); + + if (!tmp) return MEMORY_E; + if (align) + tmp += align - hdrSz; + + 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 (align) + ssl->buffers.outputBuffer.offset = align - hdrSz; + else + 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; + byte hdrSz = DTLS_RECORD_HEADER_SZ; + byte align = ssl->options.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; + } + tmp = (byte*) XMALLOC(size + usedLength + align, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + WOLFSSL_MSG("growing input buffer\n"); + + if (!tmp) return MEMORY_E; + if (align) + tmp += align - hdrSz; + + 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 (align) + ssl->buffers.inputBuffer.offset = align - hdrSz; + else + 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 + /* type and version in same sport */ + XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ); + *inOutIdx += ENUM_LEN + VERSION_SZ; + ato16(input + *inOutIdx, &ssl->keys.dtls_state.curEpoch); + *inOutIdx += 4; /* advance past epoch, skip first 2 seq bytes for now */ + ato32(input + *inOutIdx, &ssl->keys.dtls_state.curSeq); + *inOutIdx += 4; /* advance past rest of seq */ + ato16(input + *inOutIdx, size); + *inOutIdx += LENGTH_SZ; +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input + *inOutIdx - LENGTH_SZ - 8 - ENUM_LEN - + VERSION_SZ, ENUM_LEN + VERSION_SZ + 8 + LENGTH_SZ, + FUZZ_HEAD, ssl->fuzzerCtx); +#endif +#endif + } + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls && + (!DtlsCheckWindow(&ssl->keys.dtls_state) || + (ssl->options.handShakeDone && ssl->keys.dtls_state.curEpoch == 0))) { + return SEQUENCE_ERROR; + } +#endif + + /* catch version mismatch */ + if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor){ + 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 + && (ssl->options.acceptState == ACCEPT_BEGIN + || ssl->options.acceptState == CLIENT_HELLO_SENT)) + /* Do not check version until Server Hello or Hello Again (2) */ + WOLFSSL_MSG("Use version for formatting only in DTLS till "); + 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; +} + + +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; +} + + +#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 += BYTE3_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); + + return 0; +} +#endif + + +#ifndef NO_OLD_TLS +/* 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 + }; + +/* calculate MD5 hash for finished */ +#ifdef WOLFSSL_TI_HASH +#include <wolfssl/wolfcrypt/hash.h> +#endif + +static void BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + + byte md5_result[MD5_DIGEST_SIZE]; + +#ifdef WOLFSSL_SMALL_STACK + Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + Md5 md5[1]; + Md5 md5_2[1]; +#endif + + /* make md5 inner */ + md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */ + + wc_Md5Update(&ssl->hsHashes->hashMd5, sender, SIZEOF_SENDER); + wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN); + wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5); + wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result); + wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */ + + /* make md5 outer */ + wc_InitMd5(md5_2) ; + wc_Md5Update(md5_2, ssl->arrays->masterSecret,SECRET_LEN); + wc_Md5Update(md5_2, PAD2, PAD_MD5); + wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE); + wc_Md5Final(md5_2, hashes->md5); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + +} + + +/* calculate SHA hash for finished */ +static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + byte sha_result[SHA_DIGEST_SIZE]; + +#ifdef WOLFSSL_SMALL_STACK + Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + Sha sha[1]; + Sha sha2[1] ; +#endif + /* make sha inner */ + sha[0] = ssl->hsHashes->hashSha ; /* Save current position */ + + wc_ShaUpdate(&ssl->hsHashes->hashSha, sender, SIZEOF_SENDER); + wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN); + wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA); + wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result); + wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */ + + /* make sha outer */ + wc_InitSha(sha2) ; + wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN); + wc_ShaUpdate(sha2, PAD2, PAD_SHA); + wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE); + wc_ShaFinal(sha2, hashes->sha); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + +} +#endif + +/* Finished doesn't support SHA512, not SHA512 cipher suites yet */ +static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SHA384 + Sha384* sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif +#else + #ifdef WOLFSSL_SHA384 + Sha384 sha384[1]; + #endif +#endif + +#ifdef WOLFSSL_SMALL_STACK + if (ssl == NULL + #ifdef WOLFSSL_SHA384 + || sha384 == NULL + #endif + ) { + #ifdef WOLFSSL_SHA384 + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } +#endif + + /* store current states, building requires get_digest which resets state */ +#ifdef WOLFSSL_SHA384 + sha384[0] = ssl->hsHashes->hashSha384; +#endif + +#ifndef NO_TLS + if (ssl->options.tls) { + ret = BuildTlsFinished(ssl, hashes, sender); + } +#endif +#ifndef NO_OLD_TLS + if (!ssl->options.tls) { + BuildMD5(ssl, hashes, sender); + BuildSHA(ssl, hashes, sender); + } +#endif + + /* restore */ + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_SHA384 + ssl->hsHashes->hashSha384 = sha384[0]; + #endif + } + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SHA384 + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif +#endif + + return ret; +} + + + /* 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) + { + + 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; + } + } + + /* ECC extensions */ + if (first == ECC_BYTE) { + + switch (second) { + +#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 + +#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 +#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 +#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 +#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 + + 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; + +#ifndef NO_RSA + 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; + + 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; + + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_RSA_SIG) + 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 + + 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; + + 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; + + 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; + + default: + WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC"); + return 0; + } /* switch */ + } /* if */ + if (first != ECC_BYTE && first != CHACHA_BYTE) { /* normal suites */ + switch (second) { + +#ifndef NO_RSA + 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; + + case SSL_RSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_NTRU_RSA_WITH_RC4_128_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + + 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; + + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + + case TLS_RSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + + 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; + + case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + + case SSL_RSA_WITH_IDEA_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; +#endif + + 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; + +#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; + + 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; + + case TLS_RSA_WITH_AES_128_CBC_B2B256: + case TLS_RSA_WITH_AES_256_CBC_B2B256: + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_RSA_WITH_RABBIT_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + 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; + + 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 +#ifdef HAVE_ANON + case TLS_DH_anon_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_DHE) + return 1; + break; +#endif + + default: + WOLFSSL_MSG("Unsupported cipher suite, CipherRequires"); + return 0; + } /* switch */ + } /* if ECC / Normal suites else */ + + return 0; + } + + +#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 */ +static int MatchDomainName(const char* pattern, int len, const char* str) +{ + 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 (*str != '\0') + str++; + + if (len > 0) + len--; + } + + return *str == '\0'; +} + + +/* try to find an altName match to domain, return 1 on success */ +static 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(" individual AltName check"); + + if (MatchDomainName(altName->name,(int)XSTRLEN(altName->name), domain)){ + match = 1; + break; + } + + altName = altName->next; + } + + return match; +} + + +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) + +/* 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) + 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; +#ifdef OPENSSL_EXTRA + if (dCert->issuerName.fullName != NULL) { + XMEMCPY(&x509->issuer.fullName, + &dCert->issuerName, sizeof(DecodedName)); + x509->issuer.fullName.fullName = (char*)XMALLOC( + dCert->issuerName.fullNameLen, NULL, DYNAMIC_TYPE_X509); + if (x509->issuer.fullName.fullName != NULL) + XMEMCPY(x509->issuer.fullName.fullName, + dCert->issuerName.fullName, dCert->issuerName.fullNameLen); + } +#endif /* OPENSSL_EXTRA */ + + 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; +#ifdef OPENSSL_EXTRA + if (dCert->subjectName.fullName != NULL) { + XMEMCPY(&x509->subject.fullName, + &dCert->subjectName, sizeof(DecodedName)); + x509->subject.fullName.fullName = (char*)XMALLOC( + dCert->subjectName.fullNameLen, NULL, DYNAMIC_TYPE_X509); + if (x509->subject.fullName.fullName != NULL) + XMEMCPY(x509->subject.fullName.fullName, + dCert->subjectName.fullName, dCert->subjectName.fullNameLen); + } +#endif /* OPENSSL_EXTRA */ + + XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE); + x509->serialSz = dCert->serialSz; + if (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, NULL, 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) { + x509->sig.buffer = (byte*)XMALLOC( + dCert->sigLength, NULL, 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, NULL) == 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 */ + + x509->isCa = dCert->isCA; +#ifdef OPENSSL_EXTRA + x509->pathLength = dCert->pathLength; + x509->keyUsage = dCert->extKeyUsage; + + x509->basicConstSet = dCert->extBasicConstSet; + x509->basicConstCrit = dCert->extBasicConstCrit; + x509->basicConstPlSet = dCert->extBasicConstPlSet; + 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, NULL, + 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, NULL, + 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; + #ifdef WOLFSSL_SEP + x509->certPolicySet = dCert->extCertPolicySet; + x509->certPolicyCrit = dCert->extCertPolicyCrit; + #endif /* WOLFSSL_SEP */ +#endif /* OPENSSL_EXTRA */ +#ifdef HAVE_ECC + x509->pkCurveOID = dCert->pkCurveOID; +#endif /* HAVE_ECC */ + + return ret; +} + +#endif /* KEEP_PEER_CERT || SESSION_CERTS */ + + +static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + word32 listSz; + word32 begin = *inOutIdx; + int ret = 0; + int anyError = 0; + int totalCerts = 0; /* number of certs in certs buffer */ + int count; + buffer certs[MAX_CHAIN_DEPTH]; + +#ifdef WOLFSSL_SMALL_STACK + char* domain = NULL; + DecodedCert* dCert = NULL; + WOLFSSL_X509_STORE_CTX* store = NULL; +#else + char domain[ASN_NAME_MAX]; + DecodedCert dCert[1]; + WOLFSSL_X509_STORE_CTX store[1]; +#endif + +#ifdef WOLFSSL_TRUST_PEER_CERT + byte haveTrustPeer = 0; /* was cert verified by loaded trusted peer cert */ +#endif + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo); + #endif + + if ((*inOutIdx - begin) + OPAQUE24_LEN > size) + return BUFFER_ERROR; + + c24to32(input + *inOutIdx, &listSz); + *inOutIdx += OPAQUE24_LEN; + + if (listSz > MAX_RECORD_SIZE) + return BUFFER_E; + + if ((*inOutIdx - begin) + listSz != size) + return BUFFER_ERROR; + + 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; + + if (totalCerts >= MAX_CHAIN_DEPTH) + return MAX_CHAIN_ERROR; + + if ((*inOutIdx - begin) + OPAQUE24_LEN > size) + return BUFFER_ERROR; + + c24to32(input + *inOutIdx, &certSz); + *inOutIdx += OPAQUE24_LEN; + + if ((*inOutIdx - begin) + certSz > size) + return BUFFER_ERROR; + + certs[totalCerts].length = certSz; + certs[totalCerts].buffer = input + *inOutIdx; + +#ifdef SESSION_CERTS + if (ssl->session.chain.count < MAX_CHAIN_DEPTH && + certSz < MAX_X509_SIZE) { + ssl->session.chain.certs[ssl->session.chain.count].length = certSz; + XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer, + input + *inOutIdx, certSz); + ssl->session.chain.count++; + } else { + WOLFSSL_MSG("Couldn't store chain cert for session"); + } +#endif + + *inOutIdx += certSz; + listSz -= certSz + CERT_HEADER_SZ; + + totalCerts++; + WOLFSSL_MSG(" Put another cert into chain"); + } + + count = totalCerts; + +#ifdef WOLFSSL_SMALL_STACK + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (dCert == NULL) + return MEMORY_E; +#endif + +#ifdef WOLFSSL_TRUST_PEER_CERT + /* if using trusted peer certs check before verify chain and CA test */ + if (count > 0) { + TrustedPeerCert* tp = NULL; + + InitDecodedCert(dCert, certs[0].buffer, certs[0].length, ssl->heap); + ret = ParseCertRelative(dCert, CERT_TYPE, 0, ssl->ctx->cm); + #ifndef NO_SKID + if (dCert->extAuthKeyIdSet) { + tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId, + WC_MATCH_SKID); + } + else { /* if the cert has no SKID try to match by name */ + tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, + WC_MATCH_NAME); + } + #else /* NO_SKID */ + tp = GetTrustedPeer(ssl->ctx->cm, 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(dCert); + } else if (MatchTrustedPeer(tp, dCert)){ + WOLFSSL_MSG("Found matching trusted peer cert"); + haveTrustPeer = 1; + } else { + WOLFSSL_MSG("Trusted peer cert did not match!"); + FreeDecodedCert(dCert); + } + } + if (!haveTrustPeer) { /* do not verify chain if trusted peer cert found */ +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + /* verify up to peer's first */ + while (count > 1) { + buffer myCert = certs[count - 1]; + byte* subjectHash; + + InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); + ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, + ssl->ctx->cm); + #ifndef NO_SKID + subjectHash = dCert->extSubjKeyId; + #else + subjectHash = dCert->subjectHash; + #endif + + if (ret == 0 && 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, myCert.length, CA_TYPE, ssl->heap); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + WOLFSSL_MSG("Adding CA from chain"); + + XMEMCPY(add->buffer, myCert.buffer, myCert.length); + + /* already verified above */ + ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0); + if (ret == 1) ret = 0; /* SSL_SUCCESS for external */ + } + else if (ret != 0) { + WOLFSSL_MSG("Failed to verify CA from chain"); + } + else { + WOLFSSL_MSG("Verified CA from chain and already had it"); + } + +#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, dCert, 0); + else /* skips OCSP and force CRL check */ + #endif + if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) { + WOLFSSL_MSG("Doing Non Leaf OCSP check"); + ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL); + 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, dCert); + + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + } + } +#else + (void)doCrlLookup; +#endif /* HAVE_CRL */ + } +#endif /* HAVE_OCSP || HAVE_CRL */ + + if (ret != 0 && anyError == 0) + anyError = ret; /* save error from last time */ + + FreeDecodedCert(dCert); + count--; + } + +#ifdef WOLFSSL_TRUST_PEER_CERT + } /* end of if (haveTrustPeer) -- a check for if already verified */ +#endif + + /* peer's, may not have one if blank client cert sent by TLSv1.2 */ + if (count) { + buffer myCert = certs[0]; + int fatal = 0; + + WOLFSSL_MSG("Verifying Peer's cert"); + +#ifdef WOLFSSL_TRUST_PEER_CERT + if (!haveTrustPeer) { /* do not parse again if previously verified */ +#endif + InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); + ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, + ssl->ctx->cm); +#ifdef WOLFSSL_TRUST_PEER_CERT + } +#endif + + if (ret == 0) { + WOLFSSL_MSG("Verified Peer's cert"); + fatal = 0; + } + else if (ret == ASN_PARSE_E) { + WOLFSSL_MSG("Got Peer cert ASN PARSE ERROR, fatal"); + fatal = 1; + } + else { + WOLFSSL_MSG("Failed to verify Peer's cert"); + if (ssl->verifyCallback) { + WOLFSSL_MSG("\tCallback override available, will continue"); + fatal = 0; + } + else { + WOLFSSL_MSG("\tNo callback override available, fatal"); + fatal = 1; + } + } + +#ifdef HAVE_SECURE_RENEGOTIATION + if (fatal == 0 && ssl->secure_renegotiation + && ssl->secure_renegotiation->enabled) { + + if (IsEncryptionOn(ssl, 0)) { + /* compare against previous time */ + if (XMEMCMP(dCert->subjectHash, + ssl->secure_renegotiation->subject_hash, + SHA_DIGEST_SIZE) != 0) { + WOLFSSL_MSG("Peer sent different cert during scr, fatal"); + fatal = 1; + ret = SCR_DIFFERENT_CERT_E; + } + } + + /* cache peer's hash */ + if (fatal == 0) { + XMEMCPY(ssl->secure_renegotiation->subject_hash, + dCert->subjectHash, SHA_DIGEST_SIZE); + } + } +#endif + +#if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (fatal == 0) { + int doLookup = 1; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert); + doLookup = 0; + } +#endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + fatal = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 1); + doLookup = 0; + } +#endif + } + +#ifdef HAVE_OCSP + if (doLookup && ssl->ctx->cm->ocspEnabled) { + WOLFSSL_MSG("Doing Leaf OCSP check"); + ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL); + doLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + WOLFSSL_MSG("\tOCSP Lookup not ok"); + fatal = 0; + } + } +#endif /* HAVE_OCSP */ + +#ifdef HAVE_CRL + if (doLookup && ssl->ctx->cm->crlEnabled) { + WOLFSSL_MSG("Doing Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + fatal = 0; + } + } +#endif /* HAVE_CRL */ + (void)doLookup; + } +#endif /* HAVE_OCSP || HAVE_CRL */ + +#ifdef KEEP_PEER_CERT + { + /* set X509 format for peer cert even if fatal */ + int copyRet = CopyDecodedToX509(&ssl->peerCert, dCert); + if (copyRet == MEMORY_E) + fatal = 1; + } +#endif + +#ifndef IGNORE_KEY_EXTENSIONS + if (dCert->extKeyUsageSet) { + if ((ssl->specs.kea == rsa_kea) && + (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)) && + (dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { + WOLFSSL_MSG("KeyUse Digital Sig not set"); + ret = KEYUSE_SIGNATURE_E; + } + } + + if (dCert->extExtKeyUsageSet) { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ((dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Server Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + else { + if ((dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Client Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + } +#endif /* IGNORE_KEY_EXTENSIONS */ + + if (fatal) { + FreeDecodedCert(dCert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + ssl->error = ret; + return ret; + } + ssl->options.havePeerCert = 1; + +#ifdef WOLFSSL_SMALL_STACK + domain = (char*)XMALLOC(ASN_NAME_MAX, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (domain == NULL) { + FreeDecodedCert(dCert); + XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + /* store for callback use */ + if (dCert->subjectCNLen < ASN_NAME_MAX) { + XMEMCPY(domain, dCert->subjectCN, dCert->subjectCNLen); + domain[dCert->subjectCNLen] = '\0'; + } + else + domain[0] = '\0'; + + if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { + if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, + (char*)ssl->buffers.domainName.buffer) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + if (CheckAltNames(dCert, + (char*)ssl->buffers.domainName.buffer) == 0 ) { + WOLFSSL_MSG("DomainName match on alt names failed too"); + ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */ + } + } + } + + /* decode peer key */ + switch (dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 idx = 0; + int keyRet = 0; + + if (ssl->peerRsaKey == NULL) { + ssl->peerRsaKey = (RsaKey*)XMALLOC(sizeof(RsaKey), + ssl->heap, DYNAMIC_TYPE_RSA); + if (ssl->peerRsaKey == NULL) { + WOLFSSL_MSG("PeerRsaKey Memory error"); + keyRet = MEMORY_E; + } else { + keyRet = wc_InitRsaKey(ssl->peerRsaKey, + ssl->ctx->heap); + } + } else if (ssl->peerRsaKeyPresent) { + /* don't leak on reuse */ + wc_FreeRsaKey(ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; + keyRet = wc_InitRsaKey(ssl->peerRsaKey, ssl->heap); + } + + if (keyRet != 0 || wc_RsaPublicKeyDecode(dCert->publicKey, + &idx, ssl->peerRsaKey, dCert->pubKeySize) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerRsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + ssl->buffers.peerRsaKey.buffer = + (byte*)XMALLOC(dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_RSA); + if (ssl->buffers.peerRsaKey.buffer == NULL) + ret = MEMORY_ERROR; + else { + XMEMCPY(ssl->buffers.peerRsaKey.buffer, + dCert->publicKey, dCert->pubKeySize); + ssl->buffers.peerRsaKey.length = + dCert->pubKeySize; + } + #endif /* NO_RSA */ + #endif /*HAVE_PK_CALLBACKS */ + } + } + break; + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + { + if (dCert->pubKeySize > sizeof(ssl->peerNtruKey)) { + ret = PEER_KEY_ERROR; + } + else { + XMEMCPY(ssl->peerNtruKey, dCert->publicKey, + dCert->pubKeySize); + ssl->peerNtruKeyLen = (word16)dCert->pubKeySize; + ssl->peerNtruKeyPresent = 1; + } + } + break; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + { + if (ssl->peerEccDsaKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccDsaKey == NULL) { + WOLFSSL_MSG("PeerEccDsaKey Memory error"); + return MEMORY_E; + } + wc_ecc_init(ssl->peerEccDsaKey); + } else if (ssl->peerEccDsaKeyPresent) { + /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + wc_ecc_init(ssl->peerEccDsaKey); + } + if (wc_ecc_import_x963(dCert->publicKey, dCert->pubKeySize, + ssl->peerEccDsaKey) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEccDsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + ssl->buffers.peerEccDsaKey.buffer = + (byte*)XMALLOC(dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->buffers.peerEccDsaKey.buffer == NULL) + ret = MEMORY_ERROR; + else { + XMEMCPY(ssl->buffers.peerEccDsaKey.buffer, + dCert->publicKey, dCert->pubKeySize); + ssl->buffers.peerEccDsaKey.length = + dCert->pubKeySize; + } + #endif /* HAVE_ECC */ + #endif /*HAVE_PK_CALLBACKS */ + } + } + break; + #endif /* HAVE_ECC */ + default: + break; + } + + FreeDecodedCert(dCert); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (store == NULL) { + XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (anyError != 0 && ret == 0) + ret = anyError; + + 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 = totalCerts; + store->discardSessionCerts = 0; + store->domain = domain; + store->userCtx = ssl->verifyCbCtx; +#ifdef KEEP_PEER_CERT + store->current_cert = &ssl->peerCert; +#else + store->current_cert = NULL; +#endif +#if defined(HAVE_FORTRESS) || defined(HAVE_STUNNEL) + store->ex_data = ssl; +#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; + } + #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; + + store->error = ret; + store->error_depth = totalCerts; + store->discardSessionCerts = 0; + store->domain = domain; + store->userCtx = ssl->verifyCbCtx; +#ifdef KEEP_PEER_CERT + store->current_cert = &ssl->peerCert; +#endif + store->ex_data = ssl; + + 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; + } + #endif + } + } +#endif + + 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)) { + *inOutIdx += ssl->keys.padSz; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(store, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + int ret = 0; + byte status_type; + word32 status_length; + + 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: { + 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 = TLSX_CSR_GetRequest(ssl->extensions); + ssl->status_request = 0; + break; + } + #endif + + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + request = TLSX_CSR2_GetRequest(ssl->extensions, + status_type, 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), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (status == NULL || response == NULL) { + if (status) + XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response) + XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return MEMORY_ERROR; + } + #endif + + InitOcspResponse(response, status, input +*inOutIdx, status_length); + + if ((OcspResponseDecode(response, ssl->ctx->cm) != 0) + || (response->responseStatus != OCSP_SUCCESSFUL) + || (response->status->status != CERT_GOOD) + || (CompareOcspReqResp(request, response) != 0)) + ret = BAD_CERTIFICATE_STATUS_ERROR; + + *inOutIdx += status_length; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + } + break; + + #endif + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + + case WOLFSSL_CSR2_OCSP_MULTI: { + OcspRequest* request; + word32 list_length = status_length; + byte index = 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), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (status == NULL || response == NULL) { + if (status) + XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response) + XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + 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) != 0) + || (response->responseStatus != OCSP_SUCCESSFUL) + || (response->status->status != CERT_GOOD)) + ret = BAD_CERTIFICATE_STATUS_ERROR; + + while (ret == 0) { + request = TLSX_CSR2_GetRequest(ssl->extensions, + status_type, index++); + + if (request == NULL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) == 0) + break; + else if (index == 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_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + } + break; + + #endif + + default: + ret = BUFFER_ERROR; + } + + if (ret != 0) + SendAlert(ssl, alert_fatal, bad_certificate_status_response); + + return ret; +} + +#endif /* !NO_CERTS */ + + +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); + + 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("Finished", &ssl->handShakeInfo); + 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; + if (!ssl->options.resuming) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + else { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + if (ssl->options.resuming) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + + 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; + } + 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; + } + } +#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; + } + } +#endif + + 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; + (void)totalSz; + + WOLFSSL_ENTER("DoHandShakeMsgType"); + + /* make sure can read the message */ + if (*inOutIdx + size > totalSz) + return INCOMPLETE_DATA; + + /* sanity check msg received */ + if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) { + WOLFSSL_MSG("Sanity Check on handshake message type received failed"); + 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(0, &ssl->timeoutInfo, input + *inOutIdx - add, + size + add, ssl->heap); + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + } +#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 && !(ssl->options.dtls && type == client_hello)) { + ret = HashInput(ssl, input + *inOutIdx, size); + if (ret != 0) return ret; + } + + 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); + 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("ServerHelloDone", &ssl->handShakeInfo); + 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); + 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) + case certificate_verify: + WOLFSSL_MSG("processing certificate verify"); + ret = DoCertificateVerify(ssl, input, inOutIdx, size); + break; +#endif /* !NO_RSA || HAVE_ECC */ + +#endif /* !NO_WOLFSSL_SERVER */ + + default: + WOLFSSL_MSG("Unknown handshake message type"); + ret = UNKNOWN_HANDSHAKE_TYPE; + break; + } + + 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; + + 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; + } + else { + 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); + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ssl->arrays->pendingMsgSz = 0; + } + } + + WOLFSSL_LEAVE("DoHandShakeMsg()", ret); + return ret; +} + + +#ifdef WOLFSSL_DTLS + +static INLINE int DtlsCheckWindow(DtlsState* state) +{ + word32 cur; + word32 next; + DtlsSeq window; + + if (state->curEpoch == state->nextEpoch) { + next = state->nextSeq; + window = state->window; + } + else if (state->curEpoch < state->nextEpoch) { + next = state->prevSeq; + window = state->prevWindow; + } + else { + return 0; + } + + cur = state->curSeq; + + if ((next > DTLS_SEQ_BITS) && (cur < next - DTLS_SEQ_BITS)) { + return 0; + } + else if ((cur < next) && (window & ((DtlsSeq)1 << (next - cur - 1)))) { + return 0; + } + + return 1; +} + + +static INLINE int DtlsUpdateWindow(DtlsState* state) +{ + word32 cur; + word32* next; + DtlsSeq* window; + + if (state->curEpoch == state->nextEpoch) { + next = &state->nextSeq; + window = &state->window; + } + else { + next = &state->prevSeq; + window = &state->prevWindow; + } + + cur = state->curSeq; + + if (cur < *next) { + *window |= ((DtlsSeq)1 << (*next - cur - 1)); + } + else { + *window <<= (1 + cur - *next); + *window |= 1; + *next = cur + 1; + } + + return 1; +} + + +static int DtlsMsgDrain(WOLFSSL* ssl) +{ + DtlsMsg* item = ssl->dtls_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); + ssl->dtls_msg_list = item->next; + DtlsMsgDelete(item, ssl->heap); + item = ssl->dtls_msg_list; + } + + 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()"); + if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type, + &size, &fragOffset, &fragSz, totalSz) != 0) + return PARSE_ERROR; + + 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) { + ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list, + 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 ) + *inOutIdx += ssl->keys.padSz; + ret = DtlsPoolSend(ssl); + } + else if (fragSz < size) { + /* Since this branch is in order, but fragmented, dtls_msg_list will be + * pointing to the message with this fragment in it. Check it to see + * if it is completed. */ + ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list, + ssl->keys.dtls_peer_handshake_number, input + *inOutIdx, + size, type, fragOffset, fragSz, ssl->heap); + *inOutIdx += fragSz; + ret = 0; + if (ssl->dtls_msg_list != NULL && + ssl->dtls_msg_list->fragSz >= ssl->dtls_msg_list->sz) + ret = DtlsMsgDrain(ssl); + } + else { + /* This branch is in order next, and a complete message. */ + ssl->keys.dtls_expected_peer_handshake_number++; + ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + if (ret == 0 && ssl->dtls_msg_list != NULL) + ret = DtlsMsgDrain(ssl); + } + + WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret); + return ret; +} +#endif + + +#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \ + || defined(HAVE_AESGCM) +static INLINE word32 GetSEQIncrement(WOLFSSL* ssl, int verify) +{ +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if (verify) + return ssl->keys.dtls_state.curSeq; /* explicit from peer */ + else + return ssl->keys.dtls_sequence_number - 1; /* already incremented */ + } +#endif + if (verify) + return ssl->keys.peer_sequence_number++; + else + return ssl->keys.sequence_number++; +} +#endif + + +#ifdef HAVE_AEAD +static 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; +} + + +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)); + + if (ssl->options.oldPoly != 0) { + /* get nonce */ + c32toa(ssl->keys.sequence_number, nonce + CHACHA20_OLD_OFFSET); + } + + /* opaque SEQ number stored for AD */ + c32toa(GetSEQIncrement(ssl, 0), add + AEAD_SEQ_OFFSET); + + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + c16toa(ssl->keys.dtls_epoch, add); + additionalSrc -= DTLS_HANDSHAKE_EXTRA; + } + #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; +} + + +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)); + + if (ssl->options.oldPoly != 0) { + /* get nonce */ + c32toa(ssl->keys.peer_sequence_number, nonce + CHACHA20_OLD_OFFSET); + } + + /* sequence number field is 64-bits, we only use 32-bits */ + c32toa(GetSEQIncrement(ssl, 1), add + AEAD_SEQ_OFFSET); + + /* get AD info */ + add[AEAD_TYPE_OFFSET] = ssl->curRL.type; + add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + + /* Store the type, version. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + c16toa(ssl->keys.dtls_state.curEpoch, add); + #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; + + #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"); + 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 INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz) +{ + int ret = 0; + + (void)out; + (void)input; + (void)sz; + + 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 + + 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: + ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); + break; + #endif + + #ifdef BUILD_AES + case wolfssl_aes: + ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); + break; + #endif + + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + { + byte additional[AEAD_AUTH_DATA_SZ]; + byte nonce[AESGCM_NONCE_SZ]; + const byte* additionalSrc = input - 5; + + XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits, we only use 32-bits */ + c32toa(GetSEQIncrement(ssl, 0), + additional + AEAD_SEQ_OFFSET); + + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + c16toa(ssl->keys.dtls_epoch, additional); + additionalSrc -= DTLS_HANDSHAKE_EXTRA; + } + #endif + XMEMCPY(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, + additional + AEAD_LEN_OFFSET); + XMEMCPY(nonce, + ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(nonce + AESGCM_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + ret = wc_AesGcmEncrypt(ssl->encrypt.aes, + out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + nonce, AESGCM_NONCE_SZ, + out + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + additional, AEAD_AUTH_DATA_SZ); + AeadIncrementExpIV(ssl); + ForceZero(nonce, AESGCM_NONCE_SZ); + } + break; + #endif + + #ifdef HAVE_AESCCM + /* AEAD CCM uses same size as macros for AESGCM */ + case wolfssl_aes_ccm: + { + byte additional[AEAD_AUTH_DATA_SZ]; + byte nonce[AESGCM_NONCE_SZ]; + const byte* additionalSrc = input - 5; + + XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits, we only use 32-bits */ + c32toa(GetSEQIncrement(ssl, 0), + additional + AEAD_SEQ_OFFSET); + + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + c16toa(ssl->keys.dtls_epoch, additional); + additionalSrc -= DTLS_HANDSHAKE_EXTRA; + } + #endif + XMEMCPY(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, + additional + AEAD_LEN_OFFSET); + XMEMCPY(nonce, + ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(nonce + AESGCM_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + ret = wc_AesCcmEncrypt(ssl->encrypt.aes, + out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + nonce, AESGCM_NONCE_SZ, + out + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + additional, AEAD_AUTH_DATA_SZ); + AeadIncrementExpIV(ssl); + ForceZero(nonce, AESGCM_NONCE_SZ); + } + break; + #endif + + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + 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; + } + + return ret; +} + + + +static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, + word16 sz) +{ + int ret = 0; + + (void)plain; + (void)input; + (void)sz; + + if (ssl->decrypt.setup == 0) { + WOLFSSL_MSG("Decrypt ciphers not setup"); + return DECRYPT_ERROR; + } + + 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: + ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); + break; + #endif + + #ifdef BUILD_AES + case wolfssl_aes: + ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); + break; + #endif + + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + { + byte additional[AEAD_AUTH_DATA_SZ]; + byte nonce[AESGCM_NONCE_SZ]; + + XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits, we only use 32-bits */ + c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + c16toa(ssl->keys.dtls_state.curEpoch, additional); + #endif + + additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; + additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + additional + AEAD_LEN_OFFSET); + 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_AesGcmDecrypt(ssl->decrypt.aes, + plain + AESGCM_EXP_IV_SZ, + input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + nonce, AESGCM_NONCE_SZ, + input + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + additional, AEAD_AUTH_DATA_SZ) < 0) { + SendAlert(ssl, alert_fatal, bad_record_mac); + ret = VERIFY_MAC_ERROR; + } + ForceZero(nonce, AESGCM_NONCE_SZ); + } + break; + #endif + + #ifdef HAVE_AESCCM + /* AESGCM AEAD macros use same size as AESCCM */ + case wolfssl_aes_ccm: + { + byte additional[AEAD_AUTH_DATA_SZ]; + byte nonce[AESGCM_NONCE_SZ]; + + XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits, we only use 32-bits */ + c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + c16toa(ssl->keys.dtls_state.curEpoch, additional); + #endif + + additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; + additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + additional + AEAD_LEN_OFFSET); + 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_AesCcmDecrypt(ssl->decrypt.aes, + plain + AESGCM_EXP_IV_SZ, + input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + nonce, AESGCM_NONCE_SZ, + input + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + additional, AEAD_AUTH_DATA_SZ) < 0) { + SendAlert(ssl, alert_fatal, bad_record_mac); + ret = VERIFY_MAC_ERROR; + } + ForceZero(nonce, AESGCM_NONCE_SZ); + } + break; + #endif + + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + 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; +} + + +/* check cipher text size for sanity */ +static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) +{ +#ifdef HAVE_TRUNCATED_HMAC + word32 minLength = ssl->truncated_hmac ? 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 (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ + } + + if (encryptSz < minLength) { + WOLFSSL_MSG("Ciphertext not minimum size"); + return SANITY_CIPHER_E; + } + + return 0; +} + + +#ifndef NO_OLD_TLS + +static INLINE void Md5Rounds(int rounds, const byte* data, int sz) +{ + Md5 md5; + int i; + + wc_InitMd5(&md5); + + for (i = 0; i < rounds; i++) + wc_Md5Update(&md5, data, sz); + wc_Md5Free(&md5) ; /* in case needed to release resources */ +} + + + +/* do a dummy sha round */ +static INLINE void ShaRounds(int rounds, const byte* data, int sz) +{ + Sha sha; + int i; + + wc_InitSha(&sha); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) + wc_ShaUpdate(&sha, data, sz); + wc_ShaFree(&sha) ; /* in case needed to release resources */ +} +#endif + + +#ifndef NO_SHA256 + +static INLINE void Sha256Rounds(int rounds, const byte* data, int sz) +{ + Sha256 sha256; + int i; + + wc_InitSha256(&sha256); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) { + wc_Sha256Update(&sha256, data, sz); + /* no error check on purpose, dummy round */ + } + wc_Sha256Free(&sha256) ; /* in case needed to release resources */ +} + +#endif + + +#ifdef WOLFSSL_SHA384 + +static INLINE void Sha384Rounds(int rounds, const byte* data, int sz) +{ + Sha384 sha384; + int i; + + wc_InitSha384(&sha384); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) { + wc_Sha384Update(&sha384, data, sz); + /* no error check on purpose, dummy round */ + } + wc_Sha384Free(&sha384) ; /* in case needed to release resources */ +} + +#endif + + +#ifdef WOLFSSL_SHA512 + +static INLINE void Sha512Rounds(int rounds, const byte* data, int sz) +{ + Sha512 sha512; + int i; + + wc_InitSha512(&sha512); /* no error check on purpose, dummy round */ + + for (i = 0; i < rounds; i++) { + wc_Sha512Update(&sha512, data, sz); + /* no error check on purpose, dummy round */ + } + wc_Sha512Free(&sha512) ; /* in case needed to release resources */ +} + +#endif + + +#ifdef WOLFSSL_RIPEMD + +static INLINE void RmdRounds(int rounds, const byte* data, int sz) +{ + RipeMd ripemd; + int i; + + wc_InitRipeMd(&ripemd); + + for (i = 0; i < rounds; i++) + wc_RipeMdUpdate(&ripemd, data, sz); +} + +#endif + + +/* Do dummy rounds */ +static INLINE void DoRounds(int type, int rounds, const byte* data, int sz) +{ + switch (type) { + + case no_mac : + break; + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + case md5_mac : + Md5Rounds(rounds, data, sz); + break; +#endif + +#ifndef NO_SHA + case sha_mac : + ShaRounds(rounds, data, sz); + break; +#endif +#endif + +#ifndef NO_SHA256 + case sha256_mac : + Sha256Rounds(rounds, data, sz); + break; +#endif + +#ifdef WOLFSSL_SHA384 + case sha384_mac : + Sha384Rounds(rounds, data, sz); + break; +#endif + +#ifdef WOLFSSL_SHA512 + case sha512_mac : + Sha512Rounds(rounds, data, sz); + break; +#endif + +#ifdef WOLFSSL_RIPEMD + case rmd_mac : + RmdRounds(rounds, data, sz); + break; +#endif + + default: + WOLFSSL_MSG("Bad round type"); + break; + } +} + + +/* do number of compression rounds on dummy data */ +static INLINE void CompressRounds(WOLFSSL* ssl, int rounds, const byte* dummy) +{ + if (rounds) + DoRounds(ssl->specs.mac_algorithm, rounds, dummy, COMPRESS_LOWER); +} + + +/* 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; +} + + +/* get compression extra rounds */ +static INLINE int GetRounds(int pLen, int padLen, int t) +{ + int roundL1 = 1; /* round up flags */ + int roundL2 = 1; + + int L1 = COMPRESS_CONSTANT + pLen - t; + int L2 = COMPRESS_CONSTANT + pLen - padLen - 1 - t; + + L1 -= COMPRESS_UPPER; + L2 -= COMPRESS_UPPER; + + if ( (L1 % COMPRESS_LOWER) == 0) + roundL1 = 0; + if ( (L2 % COMPRESS_LOWER) == 0) + roundL2 = 0; + + L1 /= COMPRESS_LOWER; + L2 /= COMPRESS_LOWER; + + L1 += roundL1; + L2 += roundL2; + + return L1 - L2; +} + + +/* timing resistant pad/verify check, return 0 on success */ +static int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, + int pLen, int content) +{ + byte verify[MAX_DIGEST_SIZE]; + byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0}; + byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy; + int ret = 0; + + (void)dmy; + + if ( (t + padLen + 1) > pLen) { + WOLFSSL_MSG("Plain Len not long enough for pad/mac"); + PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE); + ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */ + ConstantCompare(verify, input + pLen - t, t); + + return VERIFY_MAC_ERROR; + } + + if (PadCheck(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) { + WOLFSSL_MSG("PadCheck failed"); + PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); + ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */ + ConstantCompare(verify, input + pLen - t, t); + + return VERIFY_MAC_ERROR; + } + + PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); + ret = ssl->hmac(ssl, verify, input, pLen - padLen - 1 - t, content, 1); + + CompressRounds(ssl, GetRounds(pLen, padLen, t), dummy); + + if (ConstantCompare(verify, input + (pLen - padLen - 1 - t), t) != 0) { + WOLFSSL_MSG("Verify MAC compare failed"); + return VERIFY_MAC_ERROR; + } + + if (ret != 0) + return VERIFY_MAC_ERROR; + return 0; +} + + +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 + + 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 (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + 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; + } + + /* 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; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Alert", &ssl->handShakeInfo); + if (ssl->toInfoOn) + /* add record header back on to info + 2 byte level, data */ + AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx - + RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap); + #endif + + /* 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(" close notify"); + ssl->options.closeNotify = 1; + } + 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 + + if (inSz > maxLength) { + if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0) + return MEMORY_E; + } + + if (inSz <= 0) + return BUFFER_ERROR; + + /* 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 = Receive(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); + + return 0; +} + + +static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, + int content, word32* padSz) +{ + int ivExtra = 0; + int ret; + word32 pad = 0; + word32 padByte = 0; +#ifdef HAVE_TRUNCATED_HMAC + word32 digestSz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 digestSz = ssl->specs.hash_size; +#endif + byte verify[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, + 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, content, 1); + if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){ + return VERIFY_MAC_ERROR; + } + if (ret != 0) + return VERIFY_MAC_ERROR; + } + + if (ssl->specs.cipher_type == aead) { + *padSz = ssl->specs.aead_mac_size; + } + else { + *padSz = digestSz + pad + padByte; + } + + 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; +#ifdef 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){ + 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 + 2] != OLD_HELLO_ID) { + WOLFSSL_MSG("Not a valid old client hello"); + return PARSE_ERROR; + } + + if (ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.idx + 3] != SSLv3_MAJOR && + ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.idx + 3] != 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; + } + + /* 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 */ + + /* 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; + continue; + } +#endif + if (ret != 0) + return ret; + + ssl->options.processReply = getData; + + /* 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 = runProcessingOneMessage; + startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */ + + /* the record layer is here */ + case runProcessingOneMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) + { + ret = SanityCheckCipherText(ssl, ssl->curSize); + if (ret < 0) + return ret; + + if (atomicUser) { + #ifdef ATOMIC_USER + ret = ssl->ctx->DecryptVerifyCb(ssl, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->curSize, ssl->curRL.type, 1, + &ssl->keys.padSz, ssl->DecryptVerifyCtx); + if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) + ssl->buffers.inputBuffer.idx += ssl->specs.block_size; + /* go past TLSv1.1 IV */ + if (ssl->specs.cipher_type == aead && + ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; + #endif /* ATOMIC_USER */ + } + else { + ret = Decrypt(ssl, ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->curSize); + if (ret < 0) { + WOLFSSL_MSG("Decrypt failed"); + WOLFSSL_ERROR(ret); + return DECRYPT_ERROR; + } + if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) + ssl->buffers.inputBuffer.idx += ssl->specs.block_size; + /* go past TLSv1.1 IV */ + if (ssl->specs.cipher_type == aead && + ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; + + ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->curSize, ssl->curRL.type, + &ssl->keys.padSz); + } + if (ret < 0) { + WOLFSSL_MSG("VerifyMac failed"); + WOLFSSL_ERROR(ret); + return DECRYPT_ERROR; + } + ssl->keys.encryptSz = ssl->curSize; + ssl->keys.decryptedCur = 1; + } + + if (ssl->options.dtls) { + #ifdef WOLFSSL_DTLS + DtlsUpdateWindow(&ssl->keys.dtls_state); + #endif /* WOLFSSL_DTLS */ + } + + WOLFSSL_MSG("received record layer msg"); + + switch (ssl->curRL.type) { + case handshake : + /* debugging in DoHandShakeMsg */ + if (!ssl->options.dtls) { + ret = DoHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); + } + else { +#ifdef WOLFSSL_DTLS + ret = DoDtlsHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); +#endif + } + if (ret != 0) + return ret; + break; + + case change_cipher_spec: + WOLFSSL_MSG("got CHANGE CIPHER SPEC"); + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ChangeCipher", &ssl->handShakeInfo); + /* add record header back on info */ + if (ssl->toInfoOn) { + AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ, + 1 + RECORD_HEADER_SZ, ssl->heap); + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + } + #endif + +#ifdef WOLFSSL_DTLS + /* Check for duplicate CCS message in DTLS mode. + * DTLS allows for duplicate messages, and it should be + * skipped. */ + if (ssl->options.dtls && + ssl->msgsReceived.got_change_cipher) { + + WOLFSSL_MSG("Duplicate ChangeCipher msg"); + ret = DtlsPoolSend(ssl); + 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 + + ret = SanityCheckMsgReceived(ssl, change_cipher_hs); + if (ret != 0) + return ret; + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->expect_session_ticket) { + WOLFSSL_MSG("Expected session ticket missing"); + return SESSION_TICKET_EXPECT_E; + } +#endif + + 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; + } + #ifndef NO_CERTS + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.verifyPeer && + ssl->options.havePeerCert) + if (!ssl->options.havePeerVerify) { + WOLFSSL_MSG("client didn't send cert verify"); + return NO_PEER_VERIFY; + } + #endif + + + ssl->buffers.inputBuffer.idx++; + ssl->keys.encryptionOn = 1; + + /* setup decrypt keys for following messages */ + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsPoolReset(ssl); + ssl->keys.dtls_state.nextEpoch++; + ssl->keys.dtls_state.nextSeq = 0; + } + #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; + 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 + 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"); + #ifdef WOLFSSL_DTLS + /* read-ahead but dtls doesn't bundle messages per record */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + continue; + } + #endif + ssl->options.processReply = runProcessingOneMessage; + + if (IsEncryptionOn(ssl, 0)) { + WOLFSSL_MSG("Bundled encrypted messages, remove middle pad"); + ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + } + + 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 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); + if (sendSz < 0) + return sendSz; + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, output, sendSz, + 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 content, int verify) +{ + byte result[MAX_DIGEST_SIZE]; + word32 digestSz = ssl->specs.hash_size; /* actual sizes */ + word32 padSz = ssl->specs.pad_size; + int ret = 0; + + Md5 md5; + Sha sha; + + /* data */ + byte seq[SEQ_SZ]; + byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */ + const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify); + +#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]); + c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]); + + if (ssl->specs.mac_algorithm == md5_mac) { + wc_InitMd5(&md5); + /* inner */ + wc_Md5Update(&md5, macSecret, digestSz); + wc_Md5Update(&md5, PAD1, padSz); + wc_Md5Update(&md5, seq, SEQ_SZ); + wc_Md5Update(&md5, conLen, sizeof(conLen)); + /* in buffer */ + wc_Md5Update(&md5, in, sz); + wc_Md5Final(&md5, result); + /* outer */ + wc_Md5Update(&md5, macSecret, digestSz); + wc_Md5Update(&md5, PAD2, padSz); + wc_Md5Update(&md5, result, digestSz); + wc_Md5Final(&md5, digest); + } + else { + ret = wc_InitSha(&sha); + if (ret != 0) + return ret; + /* inner */ + wc_ShaUpdate(&sha, macSecret, digestSz); + wc_ShaUpdate(&sha, PAD1, padSz); + wc_ShaUpdate(&sha, seq, SEQ_SZ); + wc_ShaUpdate(&sha, conLen, sizeof(conLen)); + /* in buffer */ + wc_ShaUpdate(&sha, in, sz); + wc_ShaFinal(&sha, result); + /* outer */ + wc_ShaUpdate(&sha, macSecret, digestSz); + wc_ShaUpdate(&sha, PAD2, padSz); + wc_ShaUpdate(&sha, result, digestSz); + wc_ShaFinal(&sha, digest); + } + return 0; +} + +#ifndef NO_CERTS +static void BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) +{ + byte md5_result[MD5_DIGEST_SIZE]; + +#ifdef WOLFSSL_SMALL_STACK + Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + Md5 md5[1]; + Md5 md5_2[1]; +#endif + + /* make md5 inner */ + md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */ + wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN); + wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5); + wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result); + wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */ + + /* make md5 outer */ + wc_InitMd5(md5_2) ; + wc_Md5Update(md5_2, ssl->arrays->masterSecret, SECRET_LEN); + wc_Md5Update(md5_2, PAD2, PAD_MD5); + wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE); + + wc_Md5Final(md5_2, digest); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif +} + + +static void BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) +{ + byte sha_result[SHA_DIGEST_SIZE]; + +#ifdef WOLFSSL_SMALL_STACK + Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + Sha sha[1]; + Sha sha2[1]; +#endif + + /* make sha inner */ + sha[0] = ssl->hsHashes->hashSha ; /* Save current position */ + wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN); + wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA); + wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result); + wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */ + + /* make sha outer */ + wc_InitSha(sha2) ; + wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN); + wc_ShaUpdate(sha2, PAD2, PAD_SHA); + wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE); + + wc_ShaFinal(sha2, digest); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + +} +#endif /* NO_CERTS */ +#endif /* NO_OLD_TLS */ + + +#ifndef NO_CERTS + +static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) +{ + /* store current states, building requires get_digest which resets state */ + #ifdef WOLFSSL_SHA384 + Sha384 sha384 = ssl->hsHashes->hashSha384; + #endif + #ifdef WOLFSSL_SHA512 + Sha512 sha512 = ssl->hsHashes->hashSha512; + #endif + + if (ssl->options.tls) { +#if ! defined( NO_OLD_TLS ) + wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); + wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); +#endif + if (IsAtLeastTLSv1_2(ssl)) { + int ret; + + #ifndef NO_SHA256 + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,hashes->sha256); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA384 + ret = wc_Sha384Final(&ssl->hsHashes->hashSha384,hashes->sha384); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA512 + ret = wc_Sha512Final(&ssl->hsHashes->hashSha512,hashes->sha512); + if (ret != 0) + return ret; + #endif + } + } +#if ! defined( NO_OLD_TLS ) + else { + BuildMD5_CertVerify(ssl, hashes->md5); + BuildSHA_CertVerify(ssl, hashes->sha); + } + + /* restore */ +#endif + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_SHA384 + ssl->hsHashes->hashSha384 = sha384; + #endif + #ifdef WOLFSSL_SHA512 + ssl->hsHashes->hashSha512 = sha512; + #endif + } + + return 0; +} + +#endif /* WOLFSSL_LEANPSK */ + +/* Build SSL Message, encrypted */ +static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, + const byte* input, int inSz, int type, int hashOutput) +{ +#ifdef HAVE_TRUNCATED_HMAC + word32 digestSz = min(ssl->specs.hash_size, + ssl->truncated_hmac ? TRUNCATED_HMAC_SZ : ssl->specs.hash_size); +#else + word32 digestSz = ssl->specs.hash_size; +#endif + word32 sz = RECORD_HEADER_SZ + inSz + digestSz; + word32 pad = 0, i; + word32 idx = RECORD_HEADER_SZ; + word32 ivSz = 0; /* TLSv1.1 IV */ + word32 headerSz = RECORD_HEADER_SZ; + word16 size; + byte iv[AES_BLOCK_SIZE]; /* max size */ + int ret = 0; + int atomicUser = 0; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + sz += DTLS_RECORD_EXTRA; + idx += DTLS_RECORD_EXTRA; + headerSz += DTLS_RECORD_EXTRA; + } +#endif + +#ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) + atomicUser = 1; +#endif + + if (ssl->specs.cipher_type == block) { + word32 blockSz = ssl->specs.block_size; + if (ssl->options.tls1_1) { + ivSz = blockSz; + sz += ivSz; + + if (ivSz > (word32)sizeof(iv)) + return BUFFER_E; + + ret = wc_RNG_GenerateBlock(ssl->rng, iv, ivSz); + if (ret != 0) + return ret; + + } + sz += 1; /* pad byte */ + pad = (sz - headerSz) % blockSz; + pad = blockSz - pad; + sz += pad; + } + +#ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + ivSz = AESGCM_EXP_IV_SZ; + + sz += (ivSz + ssl->specs.aead_mac_size - digestSz); + XMEMCPY(iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + } +#endif + if (sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + return BUFFER_E; + } + size = (word16)(sz - headerSz); /* include mac and digest */ + AddRecordHeader(output, size, (byte)type, ssl); + + /* write to output */ + if (ivSz) { + XMEMCPY(output + idx, iv, min(ivSz, sizeof(iv))); + idx += ivSz; + } + XMEMCPY(output + idx, input, inSz); + idx += inSz; + + if (type == handshake && hashOutput) { + ret = HashOutput(ssl, output, headerSz + inSz, ivSz); + if (ret != 0) + return ret; + } + + if (ssl->specs.cipher_type == block) { + word32 tmpIdx = idx + digestSz; + + for (i = 0; i <= pad; i++) + output[tmpIdx++] = (byte)pad; /* pad byte gets pad value too */ + } + + if (atomicUser) { /* User Record Layer Callback handling */ +#ifdef ATOMIC_USER + if ( (ret = ssl->ctx->MacEncryptCb(ssl, output + idx, + output + headerSz + ivSz, inSz, type, 0, + output + headerSz, output + headerSz, size, + ssl->MacEncryptCtx)) != 0) + return ret; +#endif + } + else { + if (ssl->specs.cipher_type != aead) { +#ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && ssl->specs.hash_size > digestSz) { + #ifdef WOLFSSL_SMALL_STACK + byte* hmac = NULL; + #else + byte hmac[MAX_DIGEST_SIZE]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (hmac == NULL) + return MEMORY_E; + #endif + + ret = ssl->hmac(ssl, hmac, output + headerSz + ivSz, inSz, + type, 0); + XMEMCPY(output + idx, hmac, digestSz); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } else +#endif + ret = ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, + type, 0); + } + if (ret != 0) + return ret; + + if ( (ret = Encrypt(ssl, output + headerSz, output+headerSz,size)) != 0) + return ret; + } + + return sz; +} + + +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; + + /* 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 = + ssl->keys.dtls_sequence_number; + ssl->keys.dtls_sequence_number = 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 (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, input, headerSz + finishedSz)) != 0) + return ret; + } + #endif + + sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz, + handshake, 1); + 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) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + else { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); +} + + +#ifndef NO_CERTS +int SendCertificate(WOLFSSL* ssl) +{ + int ret = 0; + word32 certSz, certChainSz, headerSz, listSz, payloadSz; + word32 length, maxFragment; + + if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) + return 0; /* not needed */ + + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + certSz = 0; + certChainSz = 0; + headerSz = CERT_HEADER_SZ; + length = CERT_HEADER_SZ; + listSz = 0; + } + 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 + maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ + - DTLS_HANDSHAKE_HEADER_SZ - 100; + #endif /* WOLFSSL_DTLS */ + } + + #ifdef HAVE_MAX_FRAGMENT + if (ssl->max_fragment != 0 && maxFragment >= ssl->max_fragment) + maxFragment = ssl->max_fragment; + #endif /* HAVE_MAX_FRAGMENT */ + + 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_sequence_number--; + 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_TMP_BUFFER); + if (input == NULL) + return MEMORY_E; + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + } + + sendSz = BuildMessage(ssl, output,sendSz,input,inputSz,handshake,1); + XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (sendSz < 0) + return sendSz; + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, + 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; + } + + return ret; +} + + +int SendCertificateRequest(WOLFSSL* ssl) +{ + byte *output; + int ret; + int sendSz; + word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + int typeTotal = 1; /* only 1 for now */ + int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */ + + if (IsAtLeastTLSv1_2(ssl)) + reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; + + 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->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 += LENGTH_SZ; + + XMEMCPY(&output[i], + ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); + i += ssl->suites->hashSigAlgoSz; + } + + c16toa(0, &output[i]); /* auth's */ + /* if add more to output, adjust i + i += REQ_HEADER_SZ; */ + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output, + sendSz, ssl->heap); + #endif + ssl->buffers.outputBuffer.length += sendSz; + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); +} + + +#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; + /* 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_TMP_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1); + XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (sendSz < 0) + ret = sendSz; + } + else + ret = HashOutput(ssl, output, sendSz, 0); + + #ifdef WOLFSSL_DTLS + if (ret == 0 && ssl->options.dtls) + ret = DtlsPoolSave(ssl, output, sendSz); + #endif + + #ifdef WOLFSSL_CALLBACKS + if (ret == 0 && ssl->hsInfoOn) + AddPacketName("CertificateStatus", &ssl->handShakeInfo); + if (ret == 0 && ssl->toInfoOn) + AddPacketInfo("CertificateStatus", &ssl->timeoutInfo, output, + sendSz, 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 + + +int SendCertificateStatus(WOLFSSL* ssl) +{ + int ret = 0; + byte status_type = 0; + + 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) { + + #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; + + XMEMSET(&response, 0, sizeof(response)); + + /* unable to fetch status. skip. */ + if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) + return 0; + + if (!request || 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), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif + + InitDecodedCert(cert, der->buffer, der->length, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, + ssl->ctx->cm)) != 0) { + WOLFSSL_MSG("ParseCert failed"); + } + else { + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) { + FreeDecodedCert(cert); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return MEMORY_E; + } + + ret = InitOcspRequest(request, cert, 0); + if (ret != 0) { + XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + } + else if (!ssl->buffers.weOwnCert && 0 == LockMutex( + &ssl->ctx->cm->ocsp_stapling->ocspLock)) { + if (!ssl->ctx->certOcspRequest) + ssl->ctx->certOcspRequest = request; + UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock); + } + } + + FreeDecodedCert(cert); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + + if (ret == 0) { + 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; + + if (response.buffer) { + if (ret == 0) + ret = BuildCertificateStatus(ssl, status_type, + &response, 1); + + XFREE(response.buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + } + + if (request != ssl->ctx->certOcspRequest) + XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + } + 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)); + + /* unable to fetch status. skip. */ + if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) + return 0; + + if (!request || 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), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif + + InitDecodedCert(cert, der->buffer, der->length, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, + ssl->ctx->cm)) != 0) { + WOLFSSL_MSG("ParseCert failed"); + } + else { + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) { + FreeDecodedCert(cert); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return MEMORY_E; + } + + ret = InitOcspRequest(request, cert, 0); + if (ret != 0) { + XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + } + else if (!ssl->buffers.weOwnCert && 0 == LockMutex( + &ssl->ctx->cm->ocsp_stapling->ocspLock)) { + if (!ssl->ctx->certOcspRequest) + ssl->ctx->certOcspRequest = request; + + UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock); + } + } + + FreeDecodedCert(cert); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + + if (ret == 0) { + ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, + &responses[0]); + + /* Suppressing, not critical */ + if (ret == OCSP_CERT_REVOKED + || ret == OCSP_CERT_UNKNOWN + || ret == OCSP_LOOKUP_FAIL) + ret = 0; + } + + if (request != ssl->ctx->certOcspRequest) + XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + + 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 + + XMEMSET(&der, 0, sizeof(buffer)); + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif + + 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; + + InitDecodedCert(cert, der.buffer, der.length, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, + ssl->ctx->cm)) != 0) { + WOLFSSL_MSG("ParseCert failed"); + break; + } + else { + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), + NULL, DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) { + ret = MEMORY_E; + break; + } + + ret = InitOcspRequest(request, cert, 0); + if (ret != 0) { + XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + break; + } + else if (!ssl->buffers.weOwnCertChain && 0 == + LockMutex( + &ssl->ctx->cm->ocsp_stapling->ocspLock)) { + if (!ssl->ctx->chainOcspRequest[i]) + ssl->ctx->chainOcspRequest[i] = request; + + UnLockMutex( + &ssl->ctx->cm->ocsp_stapling->ocspLock); + } + + 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; + + if (request != ssl->ctx->chainOcspRequest[i]) + XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + + i++; + } + + FreeDecodedCert(cert); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + else { + while (ret == 0 && + NULL != (request = ssl->ctx->chainOcspRequest[i])) { + 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, i + 1); + + for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) + if (responses[i].buffer) + XFREE(responses[i].buffer, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + } + } + break; + + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + + default: + break; + } + + return ret; +} + +#endif /* !NO_CERTS */ + + +int SendData(WOLFSSL* ssl, const void* data, int sz) +{ + int sent = 0, /* plainText size */ + sendSz, + ret, + dtlsExtra = 0; + + if (ssl->error == WANT_WRITE) + ssl->error = 0; + + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + int err; + WOLFSSL_MSG("handshake not complete, trying to finish"); + if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) + 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) + return 0; /* peer reset */ + 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 (;;) { +#ifdef HAVE_MAX_FRAGMENT + int len = min(sz - sent, min(ssl->max_fragment, OUTPUT_RECORD_SIZE)); +#else + int len = min(sz - sent, OUTPUT_RECORD_SIZE); +#endif + byte* out; + byte* sendBuffer = (byte*)data + sent; /* may switch on comp */ + int buffSz = len; /* may switch on comp */ + int outputSz; +#ifdef HAVE_LIBZ + byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; +#endif + + if (sent == sz) break; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + len = min(len, MAX_UDP_SIZE); + buffSz = len; + } +#endif + + /* 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 + sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + ssl->buffers.outputBuffer.length += sendSz; + + if ( (ret = SendBuffered(ssl)) < 0) { + WOLFSSL_ERROR(ret); + /* 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 (ret == SOCKET_ERROR_E && ssl->options.connReset) + return 0; /* peer reset */ + return ssl->error = ret; + } + + 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()"); + + if (ssl->error == WANT_READ) + ssl->error = 0; + + if (ssl->error != 0 && ssl->error != WANT_WRITE) { + WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed"); + return ssl->error; + } + + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + int err; + WOLFSSL_MSG("Handshake not complete, trying to finish"); + if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) + 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)) != SSL_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; + + /* 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 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; + + /* 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); + 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; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Alert", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Alert", &ssl->timeoutInfo, output, sendSz,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) { + + 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 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 SSL_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 PMS_VERSION_ERROR : + return "premaster secret version mismatch error"; + + case VERSION_ERROR : + return "record layer version error"; + + case WANT_WRITE : + case SSL_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 SSL_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 BAD_PATH_ERROR: + return "Bad path for opendir error"; + + 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 SSL_NO_PEM_HEADER: + return "No PEM Header 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"; + + 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); +} + + +/* be sure to add to cipher_name_idx too !!!! */ +static const char* const cipher_names[] = +{ +#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA + "RC4-SHA", +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 + "RC4-MD5", +#endif + +#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + "DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + "AES128-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + "AES256-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA + "NULL-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 + "NULL-SHA256", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + "DHE-RSA-AES128-SHA", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + "DHE-RSA-AES256-SHA", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + "DHE-PSK-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + "DHE-PSK-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 + "PSK-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 + "PSK-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + "DHE-PSK-AES256-CBC-SHA384", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + "DHE-PSK-AES128-CBC-SHA256", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 + "PSK-AES256-CBC-SHA384", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + "PSK-AES128-CBC-SHA256", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + "PSK-AES128-CBC-SHA", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + "PSK-AES256-CBC-SHA", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM + "DHE-PSK-AES128-CCM", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + "DHE-PSK-AES256-CCM", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM + "PSK-AES128-CCM", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM + "PSK-AES256-CCM", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8 + "PSK-AES128-CCM-8", +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8 + "PSK-AES256-CCM-8", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 + "DHE-PSK-NULL-SHA384", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 + "DHE-PSK-NULL-SHA256", +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 + "PSK-NULL-SHA384", +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 + "PSK-NULL-SHA256", +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA + "PSK-NULL-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5 + "HC128-MD5", +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA + "HC128-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 + "HC128-B2B256", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 + "AES128-B2B256", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 + "AES256-B2B256", +#endif + +#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA + "RABBIT-SHA", +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + "NTRU-RC4-SHA", +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + "NTRU-DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + "NTRU-AES128-SHA", +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + "NTRU-AES256-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 + "AES128-CCM-8", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8 + "AES256-CCM-8", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + "ECDHE-ECDSA-AES128-CCM-8", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + "ECDHE-ECDSA-AES256-CCM-8", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + "ECDHE-RSA-AES128-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + "ECDHE-RSA-AES256-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + "ECDHE-ECDSA-AES128-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + "ECDHE-ECDSA-AES256-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA + "ECDHE-RSA-RC4-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + "ECDHE-RSA-DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + "ECDHE-ECDSA-RC4-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + "ECDHE-ECDSA-DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + "AES128-SHA256", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + "AES256-SHA256", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + "DHE-RSA-AES128-SHA256", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + "DHE-RSA-AES256-SHA256", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + "ECDH-RSA-AES128-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + "ECDH-RSA-AES256-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + "ECDH-ECDSA-AES128-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + "ECDH-ECDSA-AES256-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + "ECDH-RSA-RC4-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + "ECDH-RSA-DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + "ECDH-ECDSA-RC4-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + "ECDH-ECDSA-DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + "AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + "AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + "DHE-RSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + "DHE-RSA-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + "ECDHE-RSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + "ECDHE-RSA-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + "ECDHE-ECDSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + "ECDHE-ECDSA-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + "ECDH-RSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + "ECDH-RSA-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + "ECDH-ECDSA-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + "ECDH-ECDSA-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + "CAMELLIA128-SHA", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + "DHE-RSA-CAMELLIA128-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + "CAMELLIA256-SHA", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + "DHE-RSA-CAMELLIA256-SHA", +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + "CAMELLIA128-SHA256", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + "DHE-RSA-CAMELLIA128-SHA256", +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + "CAMELLIA256-SHA256", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + "DHE-RSA-CAMELLIA256-SHA256", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + "ECDHE-RSA-AES128-SHA256", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + "ECDHE-ECDSA-AES128-SHA256", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + "ECDH-RSA-AES128-SHA256", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + "ECDH-ECDSA-AES128-SHA256", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + "ECDHE-RSA-AES256-SHA384", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + "ECDHE-ECDSA-AES256-SHA384", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + "ECDH-RSA-AES256-SHA384", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + "ECDH-ECDSA-AES256-SHA384", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + "ECDHE-RSA-CHACHA20-POLY1305", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + "ECDHE-ECDSA-CHACHA20-POLY1305", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + "DHE-RSA-CHACHA20-POLY1305", +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + "ECDHE-RSA-CHACHA20-POLY1305-OLD", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + "ECDHE-ECDSA-CHACHA20-POLY1305-OLD", +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + "DHE-RSA-CHACHA20-POLY1305-OLD", +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + "ADH-AES128-SHA", +#endif + +#ifdef BUILD_TLS_QSH + "QSH", +#endif + +#ifdef HAVE_RENEGOTIATION_INDICATION + "RENEGOTIATION-INFO", +#endif + +#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + "IDEA-CBC-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + "ECDHE-ECDSA-NULL-SHA", +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + "ECDHE-PSK-NULL-SHA256", +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + "ECDHE-PSK-AES128-CBC-SHA256", +#endif + +#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 + "PSK-CHACHA20-POLY1305", +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + "ECDHE-PSK-CHACHA20-POLY1305", +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + "DHE-PSK-CHACHA20-POLY1305", +#endif +}; + + +/* cipher suite number that matches above name table */ +static int cipher_name_idx[] = +{ + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA + SSL_RSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 + SSL_RSA_WITH_RC4_128_MD5, +#endif + +#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + SSL_RSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + TLS_RSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + TLS_RSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA + TLS_RSA_WITH_NULL_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 + TLS_RSA_WITH_NULL_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + TLS_DHE_RSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + TLS_DHE_RSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 + TLS_PSK_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 + TLS_PSK_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 + TLS_PSK_WITH_AES_256_CBC_SHA384, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + TLS_PSK_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + TLS_PSK_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + TLS_PSK_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM + TLS_DHE_PSK_WITH_AES_128_CCM, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + TLS_DHE_PSK_WITH_AES_256_CCM, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM + TLS_PSK_WITH_AES_128_CCM, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM + TLS_PSK_WITH_AES_256_CCM, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8 + TLS_PSK_WITH_AES_128_CCM_8, +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8 + TLS_PSK_WITH_AES_256_CCM_8, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 + TLS_DHE_PSK_WITH_NULL_SHA384, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 + TLS_DHE_PSK_WITH_NULL_SHA256, +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 + TLS_PSK_WITH_NULL_SHA384, +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 + TLS_PSK_WITH_NULL_SHA256, +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA + TLS_PSK_WITH_NULL_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5 + TLS_RSA_WITH_HC_128_MD5, +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA + TLS_RSA_WITH_HC_128_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 + TLS_RSA_WITH_HC_128_B2B256, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 + TLS_RSA_WITH_AES_128_CBC_B2B256, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 + TLS_RSA_WITH_AES_256_CBC_B2B256, +#endif + +#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA + TLS_RSA_WITH_RABBIT_SHA, +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + TLS_NTRU_RSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + TLS_NTRU_RSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + TLS_NTRU_RSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 + TLS_RSA_WITH_AES_128_CCM_8, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8 + TLS_RSA_WITH_AES_256_CCM_8, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA + TLS_ECDHE_RSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + TLS_RSA_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + TLS_RSA_WITH_AES_256_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + TLS_ECDH_RSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + TLS_RSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + TLS_RSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + TLS_DH_anon_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_QSH + TLS_QSH, +#endif + +#ifdef HAVE_RENEGOTIATION_INDICATION + TLS_EMPTY_RENEGOTIATION_INFO_SCSV, +#endif + +#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + SSL_RSA_WITH_IDEA_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + TLS_ECDHE_ECDSA_WITH_NULL_SHA, +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + TLS_ECDHE_PSK_WITH_NULL_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, +#endif + +#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 + TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, +#endif +}; + + +/* returns the cipher_names array */ +const char* const* GetCipherNames(void) +{ + return cipher_names; +} + + +/* returns the size of the cipher_names array */ +int GetCipherNamesSize(void) +{ + return (int)(sizeof(cipher_names) / sizeof(char*)); +} + + +/** +Set the enabled cipher suites. + +@param [out] suites Suites structure. +@param [in] list List of cipher suites, only supports full name from + cipher_name[] delimited by ':'. + +@return true on success, else false. +*/ +int SetCipherList(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) + 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], sizeof(name)) == 0) { + suites->suites[idx++] = (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE + : (XSTRSTR(name, "QSH")) ? QSH_BYTE + : (XSTRSTR(name, "EC")) ? ECC_BYTE + : (XSTRSTR(name, "CCM")) ? ECC_BYTE + : 0x00; /* normal */ + + suites->suites[idx++] = (byte)cipher_name_idx[i]; + + /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA + * suites don't necessarily have RSA in the name. */ + if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) + haveECDSAsig = 1; + else if (XSTRSTR(name, "ADH")) + haveAnon = 1; + else if ((haveRSAsig == 0) && (XSTRSTR(name, "PSK") == NULL)) + haveRSAsig = 1; + + ret = 1; /* found at least one */ + break; + } + } + } + while (next++); /* ++ needed to skip ':' */ + + if (ret) { + suites->setSuites = 1; + suites->suiteSz = (word16)idx; + InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon); + } + + return ret; +} + +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) +static void PickHashSigAlgo(WOLFSSL* ssl, + const byte* hashSigAlgo, word32 hashSigAlgoSz) +{ + word32 i; + + ssl->suites->sigAlgo = ssl->specs.sig_algo; + ssl->suites->hashAlgo = sha_mac; + + /* i+1 since peek a byte ahead for type */ + for (i = 0; (i+1) < hashSigAlgoSz; i += 2) { + if (hashSigAlgo[i+1] == ssl->specs.sig_algo) { + if (hashSigAlgo[i] == sha_mac) { + break; + } + #ifndef NO_SHA256 + else if (hashSigAlgo[i] == sha256_mac) { + ssl->suites->hashAlgo = sha256_mac; + break; + } + #endif + #ifdef WOLFSSL_SHA384 + else if (hashSigAlgo[i] == sha384_mac) { + ssl->suites->hashAlgo = sha384_mac; + break; + } + #endif + #ifdef WOLFSSL_SHA512 + else if (hashSigAlgo[i] == sha512_mac) { + ssl->suites->hashAlgo = sha512_mac; + break; + } + #endif + } + } +} +#endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */ + +#ifdef WOLFSSL_CALLBACKS + + /* Initialisze HandShakeInfo */ + void InitHandShakeInfo(HandShakeInfo* info) + { + int i; + + 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, const WOLFSSL* ssl) + { + int i; + int sz = sizeof(cipher_name_idx)/sizeof(int); + + for (i = 0; i < sz; i++) + if (ssl->options.cipherSuite == (byte)cipher_name_idx[i]) { + if (ssl->options.cipherSuite0 == ECC_BYTE) + continue; /* ECC suites at end */ + XSTRNCPY(info->cipherName, cipher_names[i], MAX_CIPHERNAME_SZ); + break; + } + + /* error max and min are negative numbers */ + if (ssl->error <= MIN_PARAM_ERR && ssl->error >= MAX_PARAM_ERR) + info->negotiationError = ssl->error; + } + + + /* Add name to info packet names, increase packet name count */ + void AddPacketName(const char* name, HandShakeInfo* info) + { + if (info->numberPackets < MAX_PACKETS_HANDSHAKE) { + XSTRNCPY(info->packetNames[info->numberPackets++], name, + MAX_PACKETNAME_SZ); + } + } + + + /* 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 PacketInfo to TimeoutInfo */ + void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data, + int sz, void* heap) + { + if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) { + Timeval currTime; + + /* may add name after */ + if (name) + XSTRNCPY(info->packets[info->numberPackets].packetName, name, + MAX_PACKETNAME_SZ); + + /* 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 = + 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++; + } + } + + + /* 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) { + XSTRNCPY(info->packets[info->numberPackets - 1].packetName, name, + MAX_PACKETNAME_SZ); + } + } + + /* 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 */ + + + +/* client only parts */ +#ifndef NO_WOLFSSL_CLIENT + + 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; + + 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); + if (ticket == NULL) return MEMORY_E; + + ret = TLSX_UseSessionTicket(&ssl->extensions, ticket); + if (ret != SSL_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 + length += TLSX_GetRequestSize(ssl); +#else + if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) { + length += ssl->suites->hashSigAlgoSz + HELLO_EXT_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); +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsRecordLayerHeader* rh = (DtlsRecordLayerHeader*)output; + rh->pvMajor = DTLS_MAJOR; + rh->pvMinor = DTLS_MINOR; + } +#endif /* WOLFSSL_DTLS */ + + /* 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 += 2; + 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 + idx += TLSX_WriteRequest(ssl, output + idx); + + (void)idx; /* suppress analyzer warning, keep idx current */ +#else + if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) + { + int i; + /* add in the extensions length */ + c16toa((word16)(HELLO_EXT_LEN + ssl->suites->hashSigAlgoSz), + output + idx); + idx += 2; + + c16toa(HELLO_EXT_SIG_ALGO, output + idx); + idx += 2; + c16toa((word16)(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz), + output+idx); + idx += 2; + c16toa(ssl->suites->hashSigAlgoSz, output + idx); + idx += 2; + for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) { + output[idx] = ssl->suites->hashSigAlgo[i]; + } + } +#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_TMP_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output,sendSz,input,inputSz,handshake,1); + XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz, + ssl->heap); +#endif + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); + } + + + 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("HelloVerifyRequest", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo); +#endif + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsPoolReset(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 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; + } + + static 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; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); + 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; + + if (pv.minor > ssl->version.minor) { + WOLFSSL_MSG("Server using higher version, fatal error"); + return VERSION_ERROR; + } + else if (pv.minor < ssl->version.minor) { + WOLFSSL_MSG("server using lower version"); + + if (!ssl->options.downgrade) { + WOLFSSL_MSG(" no downgrade allowed, fatal error"); + return VERSION_ERROR; + } + if (pv.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG(" version 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 + + if (pv.minor == SSLv3_MINOR) { + /* turn off tls */ + WOLFSSL_MSG(" downgrading 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(" downgrading to TLSv1"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + } + else if (pv.minor == TLSv1_1_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.1"); + ssl->version.minor = TLSv1_1_MINOR; + } + } + + /* 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 != ZLIB_COMPRESSION && ssl->options.usingCompression) { + WOLFSSL_MSG("Server refused compression, turning off"); + ssl->options.usingCompression = 0; /* turn off if server refused */ + } + + *inOutIdx = i; + + + if ( (i - begin) < helloSz) { +#ifdef HAVE_TLS_EXTENSIONS + if (TLSX_SupportExtensions(ssl)) { + int ret = 0; + 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 +#endif + *inOutIdx = begin + helloSz; /* skip extensions */ + } + + 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; + 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 */ + + if (ssl->options.resuming) { + if (DSH_CheckSessionId(ssl)) { + if (SetCipherSpecs(ssl) == 0) { + int ret = -1; + + XMEMCPY(ssl->arrays->masterSecret, + ssl->session.masterSecret, SECRET_LEN); + #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.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) { + DtlsPoolReset(ssl); + } + #endif + + return SetCipherSpecs(ssl); + } + + + /* 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 NO_CERTS + /* just read in and ignore for now TODO: */ + static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32* + inOutIdx, word32 size) + { + word16 len; + word32 begin = *inOutIdx; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateRequest", &ssl->handShakeInfo); + 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; + } + + /* 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 && + ssl->buffers.key && ssl->buffers.key->buffer) + ssl->options.sendVerify = SEND_CERT; + else if (IsTLS(ssl)) + ssl->options.sendVerify = SEND_BLANK_CERT; + + if (IsEncryptionOn(ssl, 0)) + *inOutIdx += ssl->keys.padSz; + + return 0; + } +#endif /* !NO_CERTS */ + + +#ifdef HAVE_ECC + + static int CheckCurveId(int oid) + { + int ret = 0; + + switch (oid) { +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) + case WOLFSSL_ECC_SECP160R1: +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) + case WOLFSSL_ECC_SECP192R1: +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) + case WOLFSSL_ECC_SECP224R1: +#endif +#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) + case WOLFSSL_ECC_SECP256R1: +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) + case WOLFSSL_ECC_SECP384R1: +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) + case WOLFSSL_ECC_SECP521R1: +#endif + break; + + default: + ret = -1; + } + + return ret; + } + +#endif /* HAVE_ECC */ + + static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) + { + #ifdef HAVE_QSH + word16 name; + int qshSz; + #endif + word16 length = 0; + word32 begin = *inOutIdx; + int ret = 0; + #define ERROR_OUT(err, eLabel) do { ret = err; goto eLabel; } while(0) + + (void)length; /* shut up compiler warnings */ + (void)begin; + (void)ssl; + (void)input; + (void)size; + (void)ret; + + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("ServerKeyExchange", &ssl->timeoutInfo); + #endif + + switch (ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx, + min(length, MAX_PSK_ID_LEN)); + + ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0; + *inOutIdx += length; + + /* QSH extensions */ + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + *inOutIdx, + size, 0)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent server ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + + return 0; + } + #endif + #ifndef NO_DH + case diffie_hellman_kea: + { + /* p */ + 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 (length < ssl->options.minDhKeySz) { + WOLFSSL_MSG("Server using a DH key that is too small"); + SendAlert(ssl, alert_fatal, handshake_failure); + return DH_KEY_SIZE_E; + } + + ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap, + DYNAMIC_TYPE_DH); + + if (ssl->buffers.serverDH_P.buffer) { + ssl->buffers.serverDH_P.length = length; + } + else { + return MEMORY_ERROR; + } + + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length); + *inOutIdx += length; + + ssl->options.dhKeySz = length; + + /* g */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap, + DYNAMIC_TYPE_DH); + + if (ssl->buffers.serverDH_G.buffer) { + ssl->buffers.serverDH_G.length = length; + } + else { + return MEMORY_ERROR; + } + + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length); + *inOutIdx += length; + + /* pub */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + ssl->buffers.serverDH_Pub.buffer = + (byte*) XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + + if (ssl->buffers.serverDH_Pub.buffer) { + ssl->buffers.serverDH_Pub.length = length; + } + else { + return MEMORY_ERROR; + } + + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, + length); + *inOutIdx += length; + break; + } /* dh_kea */ + #endif /* NO_DH */ + + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + byte b; + + if ((*inOutIdx - begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { + return BUFFER_ERROR; + } + + b = input[(*inOutIdx)++]; + + if (b != named_curve) { + return ECC_CURVETYPE_ERROR; + } + + *inOutIdx += 1; /* curve type, eat leading 0 */ + b = input[(*inOutIdx)++]; + + if (CheckCurveId(b) != 0) { + return ECC_CURVE_ERROR; + } + + length = input[(*inOutIdx)++]; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_E; + } + wc_ecc_init(ssl->peerEccKey); + } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + wc_ecc_init(ssl->peerEccKey); + } + + if (wc_ecc_import_x963(input + *inOutIdx, length, + ssl->peerEccKey) != 0) { + return ECC_PEERKEY_ERROR; + } + + *inOutIdx += length; + ssl->peerEccKeyPresent = 1; + + break; + } + #endif /* HAVE_ECC */ + + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx, + min(length, MAX_PSK_ID_LEN)); + + ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0; + *inOutIdx += length; + + /* p */ + 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 (length < ssl->options.minDhKeySz) { + WOLFSSL_MSG("Server using a DH key that is too small"); + SendAlert(ssl, alert_fatal, handshake_failure); + return DH_KEY_SIZE_E; + } + + ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap, + DYNAMIC_TYPE_DH); + + if (ssl->buffers.serverDH_P.buffer) { + ssl->buffers.serverDH_P.length = length; + } + else { + return MEMORY_ERROR; + } + + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length); + *inOutIdx += length; + + ssl->options.dhKeySz = length; + + /* g */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap, + DYNAMIC_TYPE_DH); + + if (ssl->buffers.serverDH_G.buffer) { + ssl->buffers.serverDH_G.length = length; + } + else { + return MEMORY_ERROR; + } + + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length); + *inOutIdx += length; + + /* pub */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap, + DYNAMIC_TYPE_DH); + + if (ssl->buffers.serverDH_Pub.buffer) { + ssl->buffers.serverDH_Pub.length = length; + } + else { + return MEMORY_ERROR; + } + + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, length); + *inOutIdx += length; + + break; + } + #endif /* !NO_DH || !NO_PSK */ + + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + byte b; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + /* get PSK server hint from the wire */ + XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx, + min(length, MAX_PSK_ID_LEN)); + + ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0; + *inOutIdx += length; + + + if ((*inOutIdx - begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { + return BUFFER_ERROR; + } + + /* Check curve name and ID */ + b = input[(*inOutIdx)++]; + if (b != named_curve) { + return ECC_CURVETYPE_ERROR; + } + + *inOutIdx += 1; /* curve type, eat leading 0 */ + b = input[(*inOutIdx)++]; + if (CheckCurveId(b) != 0) { + return ECC_CURVE_ERROR; + } + + length = input[(*inOutIdx)++]; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_E; + } + wc_ecc_init(ssl->peerEccKey); + } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + wc_ecc_init(ssl->peerEccKey); + } + + if (wc_ecc_import_x963(input + *inOutIdx, length, + ssl->peerEccKey) != 0) { + return ECC_PEERKEY_ERROR; + } + + *inOutIdx += length; + ssl->peerEccKeyPresent = 1; + + break; + } + #endif /* HAVE_ECC || !NO_PSK */ + } /* switch() */ + + #if !defined(NO_DH) || defined(HAVE_ECC) + if (!ssl->options.usingAnon_cipher && + (ssl->specs.kea == ecc_diffie_hellman_kea || + ssl->specs.kea == diffie_hellman_kea)) + { +#ifndef NO_OLD_TLS +#ifdef WOLFSSL_SMALL_STACK + Md5* md5 = NULL; + Sha* sha = NULL; +#else + Md5 md5[1]; + Sha sha[1]; +#endif +#endif +#ifndef NO_SHA256 +#ifdef WOLFSSL_SMALL_STACK + Sha256* sha256 = NULL; + byte* hash256 = NULL; +#else + Sha256 sha256[1]; + byte hash256[SHA256_DIGEST_SIZE]; +#endif +#endif +#ifdef WOLFSSL_SHA384 +#ifdef WOLFSSL_SMALL_STACK + Sha384* sha384 = NULL; + byte* hash384 = NULL; +#else + Sha384 sha384[1]; + byte hash384[SHA384_DIGEST_SIZE]; +#endif +#endif +#ifdef WOLFSSL_SHA512 +#ifdef WOLFSSL_SMALL_STACK + Sha512* sha512 = NULL; + byte* hash512 = NULL; +#else + Sha512 sha512[1]; + byte hash512[SHA512_DIGEST_SIZE]; +#endif +#endif +#ifdef WOLFSSL_SMALL_STACK + byte* hash = NULL; + byte* messageVerify = NULL; +#else + byte hash[FINISHED_SZ]; + byte messageVerify[MAX_DH_SZ]; +#endif + byte hashAlgo = sha_mac; + byte sigAlgo = ssl->specs.sig_algo; + word16 verifySz = (word16) (*inOutIdx - begin); + +#ifndef NO_OLD_TLS + byte doMd5 = 0; + byte doSha = 0; +#endif +#ifndef NO_SHA256 + byte doSha256 = 0; +#endif +#ifdef WOLFSSL_SHA384 + byte doSha384 = 0; +#endif +#ifdef WOLFSSL_SHA512 + byte doSha512 = 0; +#endif + + (void)hash; + (void)sigAlgo; + (void)hashAlgo; + + /* save message for hash verify */ + if (verifySz > MAX_DH_SZ) { + ERROR_OUT(BUFFER_ERROR, done); + } + + #ifdef WOLFSSL_SMALL_STACK + messageVerify = (byte*)XMALLOC(MAX_DH_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (messageVerify == NULL) { + ERROR_OUT(MEMORY_E, done); + } + #endif + + XMEMCPY(messageVerify, input + begin, verifySz); + + if (IsAtLeastTLSv1_2(ssl)) { + byte setHash = 0; + if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size) { + ERROR_OUT(BUFFER_ERROR, done); + } + + hashAlgo = input[(*inOutIdx)++]; + sigAlgo = input[(*inOutIdx)++]; + + switch (hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + doSha512 = 1; + setHash = 1; + #endif + break; + + case sha384_mac: + #ifdef WOLFSSL_SHA384 + doSha384 = 1; + setHash = 1; + #endif + break; + + case sha256_mac: + #ifndef NO_SHA256 + doSha256 = 1; + setHash = 1; + #endif + break; + + case sha_mac: + #ifndef NO_OLD_TLS + doSha = 1; + setHash = 1; + #endif + break; + + default: + ERROR_OUT(ALGO_ID_E, done); + } + + if (setHash == 0) { + ERROR_OUT(ALGO_ID_E, done); + } + + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + doSha = 1; + if (sigAlgo == rsa_sa_algo) { + doMd5 = 1; + } + #else + ERROR_OUT(ALGO_ID_E, done); + #endif + } + + /* signature */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, done); + } + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, done); + } + + /* inOutIdx updated at the end of the function */ + + /* verify signature */ + #ifdef WOLFSSL_SMALL_STACK + hash = (byte*)XMALLOC(FINISHED_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hash == NULL) { + ERROR_OUT(MEMORY_E, done); + } + #endif + +#ifndef NO_OLD_TLS + /* md5 */ + #ifdef WOLFSSL_SMALL_STACK + if (doMd5) { + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) { + ERROR_OUT(MEMORY_E, done); + } + } + #endif + if (doMd5) { + wc_InitMd5(md5); + wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN); + wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN); + wc_Md5Update(md5, messageVerify, verifySz); + wc_Md5Final(md5, hash); + } + /* sha */ + #ifdef WOLFSSL_SMALL_STACK + if (doSha) { + sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) { + ERROR_OUT(MEMORY_E, done); + } + } + #endif + if (doSha) { + ret = wc_InitSha(sha); + if (ret != 0) { + goto done; + } + wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN); + wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN); + wc_ShaUpdate(sha, messageVerify, verifySz); + wc_ShaFinal(sha, hash + MD5_DIGEST_SIZE); + } +#endif + +#ifndef NO_SHA256 + #ifdef WOLFSSL_SMALL_STACK + if (doSha256) { + sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL || hash256 == NULL) { + ERROR_OUT(MEMORY_E, done); + } + } + #endif + if (doSha256) { + if (!(ret = wc_InitSha256(sha256)) + && !(ret = wc_Sha256Update(sha256, ssl->arrays->clientRandom, + RAN_LEN)) + && !(ret = wc_Sha256Update(sha256, ssl->arrays->serverRandom, + RAN_LEN)) + && !(ret = wc_Sha256Update(sha256, messageVerify, verifySz))) { + ret = wc_Sha256Final(sha256, hash256); + } + if (ret != 0) { + goto done; + } + } +#endif + +#ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SMALL_STACK + if (doSha384) { + sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL || hash384 == NULL) { + ERROR_OUT(MEMORY_E, done); + } + } + #endif + if (doSha384) { + if (!(ret = wc_InitSha384(sha384)) + && !(ret = wc_Sha384Update(sha384, ssl->arrays->clientRandom, + RAN_LEN)) + && !(ret = wc_Sha384Update(sha384, ssl->arrays->serverRandom, + RAN_LEN)) + && !(ret = wc_Sha384Update(sha384, messageVerify, verifySz))) { + ret = wc_Sha384Final(sha384, hash384); + } + if (ret != 0) { + goto done; + } + } +#endif + +#ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SMALL_STACK + if (doSha512) { + sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha512 == NULL || hash512 == NULL) { + ERROR_OUT(MEMORY_E, done); + } + } + #endif + if (doSha512) { + if (!(ret = wc_InitSha512(sha512)) + && !(ret = wc_Sha512Update(sha512, ssl->arrays->clientRandom, + RAN_LEN)) + && !(ret = wc_Sha512Update(sha512, ssl->arrays->serverRandom, + RAN_LEN)) + && !(ret = wc_Sha512Update(sha512, messageVerify, verifySz))) { + ret = wc_Sha512Final(sha512, hash512); + } + if (ret != 0) { + goto done; + } + } +#endif + + switch (sigAlgo) + { +#ifndef NO_RSA + /* rsa */ + case rsa_sa_algo: + { + byte* out = NULL; + byte doUserRsa = 0; + word32 verifiedSz = 0; + + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaVerifyCb) + doUserRsa = 1; + #endif /*HAVE_PK_CALLBACKS */ + + if (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent) { + ERROR_OUT(NO_PEER_KEY, done); + } + + if (doUserRsa) { + #ifdef HAVE_PK_CALLBACKS + verifiedSz = ssl->ctx->RsaVerifyCb(ssl, + (byte *)input + *inOutIdx, + length, &out, + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaVerifyCtx); + #endif /*HAVE_PK_CALLBACKS */ + } + else { + verifiedSz = wc_RsaSSL_VerifyInline((byte *)input + *inOutIdx, + length, &out, ssl->peerRsaKey); + } + + if (IsAtLeastTLSv1_2(ssl)) { + word32 encSigSz; +#ifndef NO_OLD_TLS + byte* digest = &hash[MD5_DIGEST_SIZE]; + int typeH = SHAh; + int digestSz = SHA_DIGEST_SIZE; +#else + byte* digest = hash256; + int typeH = SHA256h; + int digestSz = SHA256_DIGEST_SIZE; +#endif +#ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; +#else + byte encodedSig[MAX_ENCODED_SIG_SZ]; +#endif + + if (hashAlgo == sha_mac) { + #ifndef NO_SHA + digest = &hash[MD5_DIGEST_SIZE]; + typeH = SHAh; + digestSz = SHA_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = hash384; + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = hash512; + typeH = SHA512h; + digestSz = SHA512_DIGEST_SIZE; + #endif + } + + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, done); + } + #endif + + if (digest == NULL) { + ERROR_OUT(ALGO_ID_E, done); + } + encSigSz = wc_EncodeSignature(encodedSig, digest, digestSz, + typeH); + if (encSigSz != verifiedSz || !out || XMEMCMP(out, encodedSig, + min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { + ret = VERIFY_SIGN_ERROR; + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + if (ret != 0) { + goto done; + } + } + else if (verifiedSz != FINISHED_SZ || !out || XMEMCMP(out, + hash, FINISHED_SZ) != 0) { + ERROR_OUT(VERIFY_SIGN_ERROR, done); + } + break; + } +#endif +#ifdef HAVE_ECC + /* ecdsa */ + case ecc_dsa_sa_algo: + { + int verify = 0; +#ifndef NO_OLD_TLS + byte* digest = &hash[MD5_DIGEST_SIZE]; + word32 digestSz = SHA_DIGEST_SIZE; +#else + byte* digest = hash256; + word32 digestSz = SHA256_DIGEST_SIZE; +#endif + byte doUserEcc = 0; + + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccVerifyCb) { + doUserEcc = 1; + } + #endif + + if (!ssl->peerEccDsaKeyPresent) + ERROR_OUT(NO_PEER_KEY, done); + + if (IsAtLeastTLSv1_2(ssl)) { + if (hashAlgo == sha_mac) { + #ifndef NO_SHA + digest = &hash[MD5_DIGEST_SIZE]; + digestSz = SHA_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = hash384; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = hash512; + digestSz = SHA512_DIGEST_SIZE; + #endif + } + } + if (doUserEcc) { + #ifdef HAVE_PK_CALLBACKS + ret = ssl->ctx->EccVerifyCb(ssl, input + *inOutIdx, length, + digest, digestSz, + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + &verify, ssl->EccVerifyCtx); + #endif + } + else { + ret = wc_ecc_verify_hash(input + *inOutIdx, length, + digest, digestSz, &verify, ssl->peerEccDsaKey); + } + if (ret != 0 || verify == 0) { + ERROR_OUT(VERIFY_SIGN_ERROR, done); + } + break; + } +#endif /* HAVE_ECC */ + default: + ERROR_OUT(ALGO_ID_E, done); + } /* switch (sigAlgo) */ + + /* signature length */ + *inOutIdx += length; + + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + + done: +#ifdef WOLFSSL_SMALL_STACK + #ifndef NO_OLD_TLS + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifndef NO_SHA256 + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifdef WOLFSSL_SHA384 + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifdef WOLFSSL_SHA512 + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + if (ret != 0) { + return ret; + } + } + + if (IsEncryptionOn(ssl, 0)) { + *inOutIdx += ssl->keys.padSz; + } + + + /* QSH extensions */ +#ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + *inOutIdx, + size, 0)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent server ignored + handshake */ + return BUFFER_ERROR; + } + } +#endif + + return 0; +#else /* !NO_DH or HAVE_ECC */ + return NOT_COMPILED_IN; /* not supported by build */ +#endif /* !NO_DH or HAVE_ECC */ + + #undef ERROR_OUT + } + + +#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), NULL, + DYNAMIC_TYPE_TMP_BUFFER)) == NULL) + return MEMORY_E; + + ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->QSH_secret->CliSi == NULL) + return MEMORY_E; + + ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + 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; + + 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; + + 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) +{ + byte isNtru = 0; + word16 inSz = 48; + word16 outSz; + DRBG_HANDLE drbg = 0; + byte bufIn[48]; + int ret = 0; + + 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; + } + + 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); + return outSz; + } + + return 0; +} + +/* 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, buf->buffer, DYNAMIC_TYPE_TMP_BUFFER); + if (buf->buffer == NULL) { + WOLFSSL_ERROR(MEMORY_E); + } + + /* create secret information */ + sz = 0; + current = ssl->peerQSHKey; + while (current) { + schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + 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, 0, + DYNAMIC_TYPE_TMP_BUFFER)) == 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 */ + + + int SendClientKeyExchange(WOLFSSL* ssl) + { +#ifdef WOLFSSL_SMALL_STACK + byte* encSecret = NULL; +#else + byte encSecret[MAX_ENCRYPT_SZ]; +#endif + word32 encSz = 0; + word32 idx = 0; + int ret = 0; + byte doUserRsa = 0; + + #ifdef HAVE_QSH + word32 qshSz = 0; + if (ssl->peerQSHKeyPresent) { + qshSz = QSH_KeyGetSize(ssl); + } + #endif + + (void)doUserRsa; + +#ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + if (ssl->ctx->RsaEncCb) + doUserRsa = 1; + #endif /* NO_RSA */ +#endif /*HAVE_PK_CALLBACKS */ + + #ifdef WOLFSSL_SMALL_STACK + encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encSecret == NULL) + return MEMORY_E; + #endif + + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret, + SECRET_LEN); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; + ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; + ssl->arrays->preMasterSz = SECRET_LEN; + + if (ssl->peerRsaKey == NULL || ssl->peerRsaKeyPresent == 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + + if (doUserRsa) { + #ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + encSz = MAX_ENCRYPT_SZ; + ret = ssl->ctx->RsaEncCb(ssl, + ssl->arrays->preMasterSecret, + SECRET_LEN, + encSecret, &encSz, + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaEncCtx); + #endif /* NO_RSA */ + #endif /*HAVE_PK_CALLBACKS */ + } + else { + ret = wc_RsaPublicEncrypt(ssl->arrays->preMasterSecret, + SECRET_LEN, encSecret, MAX_ENCRYPT_SZ, + ssl->peerRsaKey, ssl->rng); + if (ret > 0) { + encSz = ret; + ret = 0; /* set success to 0 */ + } + } + break; + #endif + #ifndef NO_DH + case diffie_hellman_kea: + { + buffer serverP = ssl->buffers.serverDH_P; + buffer serverG = ssl->buffers.serverDH_G; + buffer serverPub = ssl->buffers.serverDH_Pub; + #ifdef WOLFSSL_SMALL_STACK + byte* priv = NULL; + #else + byte priv[ENCRYPT_LEN]; + #endif + word32 privSz = 0; + DhKey key; + + if (serverP.buffer == 0 || serverG.buffer == 0 || + serverPub.buffer == 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + + #ifdef WOLFSSL_SMALL_STACK + priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + #endif + + wc_InitDhKey(&key); + ret = wc_DhSetKey(&key, serverP.buffer, serverP.length, + serverG.buffer, serverG.length); + if (ret == 0) + /* for DH, encSecret is Yc, agree is pre-master */ + ret = wc_DhGenerateKeyPair(&key, ssl->rng, priv, &privSz, + encSecret, &encSz); + if (ret == 0) + ret = wc_DhAgree(&key, ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, priv, privSz, + serverPub.buffer, serverPub.length); + #ifdef WOLFSSL_SMALL_STACK + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + wc_FreeDhKey(&key); + } + break; + #endif /* NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + return PSK_KEY_ERROR; + } + 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) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return PSK_KEY_ERROR; + } + encSz = (word32)XSTRLEN(ssl->arrays->client_identity); + if (encSz > MAX_PSK_ID_LEN) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return CLIENT_ID_ERROR; + } + XMEMCPY(encSecret, ssl->arrays->client_identity, encSz); + + /* make psk pre master secret */ + /* length of key + length 0s + length of key + key */ + c16toa((word16)ssl->arrays->psk_keySz, pms); + pms += 2; + XMEMSET(pms, 0, ssl->arrays->psk_keySz); + pms += ssl->arrays->psk_keySz; + c16toa((word16)ssl->arrays->psk_keySz, pms); + pms += 2; + XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; + 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: + { + byte* pms = ssl->arrays->preMasterSecret; + byte* es = encSecret; + buffer serverP = ssl->buffers.serverDH_P; + buffer serverG = ssl->buffers.serverDH_G; + buffer serverPub = ssl->buffers.serverDH_Pub; + #ifdef WOLFSSL_SMALL_STACK + byte* priv = NULL; + #else + byte priv[ENCRYPT_LEN]; + #endif + word32 privSz = 0; + word32 pubSz = 0; + word32 esSz = 0; + DhKey key; + + if (serverP.buffer == 0 || serverG.buffer == 0 || + serverPub.buffer == 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + return PSK_KEY_ERROR; + } + 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) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return PSK_KEY_ERROR; + } + esSz = (word32)XSTRLEN(ssl->arrays->client_identity); + + if (esSz > MAX_PSK_ID_LEN) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return CLIENT_ID_ERROR; + } + + #ifdef WOLFSSL_SMALL_STACK + priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + #endif + c16toa((word16)esSz, es); + es += OPAQUE16_LEN; + XMEMCPY(es, ssl->arrays->client_identity, esSz); + es += esSz; + encSz = esSz + OPAQUE16_LEN; + + wc_InitDhKey(&key); + ret = wc_DhSetKey(&key, serverP.buffer, serverP.length, + serverG.buffer, serverG.length); + if (ret == 0) + /* for DH, encSecret is Yc, agree is pre-master */ + ret = wc_DhGenerateKeyPair(&key, ssl->rng, priv, &privSz, + es + OPAQUE16_LEN, &pubSz); + if (ret == 0) + ret = wc_DhAgree(&key, pms + OPAQUE16_LEN, + &ssl->arrays->preMasterSz, priv, privSz, + serverPub.buffer, serverPub.length); + wc_FreeDhKey(&key); + #ifdef WOLFSSL_SMALL_STACK + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + c16toa((word16)pubSz, es); + encSz += pubSz + 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(NO_PSK) + case ecdhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + byte* es = encSecret; + ecc_key myKey; + ecc_key* peerKey = NULL; + word32 size = MAX_ENCRYPT_SZ; + word32 esSz = 0; + + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + return PSK_KEY_ERROR; + } + + /* 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) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return PSK_KEY_ERROR; + } + esSz = (word32)XSTRLEN(ssl->arrays->client_identity); + + if (esSz > MAX_PSK_ID_LEN) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return CLIENT_ID_ERROR; + } + + /* place size and identity in output buffer sz:identity */ + c16toa((word16)esSz, es); + es += OPAQUE16_LEN; + XMEMCPY(es, ssl->arrays->client_identity, esSz); + es += esSz; + encSz = esSz + OPAQUE16_LEN; + + /* Send Client ECC public key */ + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + peerKey = ssl->peerEccKey; + + if (peerKey == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + + wc_ecc_init(&myKey); + ret = wc_ecc_make_key(ssl->rng, peerKey->dp->size, &myKey); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ECC_MAKEKEY_ERROR; + } + + /* Place ECC key in output buffer, leaving room for size */ + ret = wc_ecc_export_x963(&myKey, es + 1, &size); + *es = (byte)size; /* place size of key in output buffer */ + encSz += size + 1; + + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + ret = ECC_EXPORT_ERROR; + } + else { + /* Create shared ECC key leaveing room at the begining + of buffer for size of shared key. Note sizeof + preMasterSecret is ENCRYPT_LEN currently 512 */ + size = sizeof(ssl->arrays->preMasterSecret) + - OPAQUE16_LEN; + ret = wc_ecc_shared_secret(&myKey, peerKey, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, &size); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + ret = ECC_SHARED_ERROR; + } + } + + wc_ecc_free(&myKey); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + /* Create pre master secret is the concatination of + eccSize + eccSharedKey + pskSize + pskKey */ + c16toa((word16)size, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN + size; + 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 && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + word32 rc; + word16 cipherLen = MAX_ENCRYPT_SZ; + DRBG_HANDLE drbg; + + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->arrays->preMasterSecret, SECRET_LEN); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + ssl->arrays->preMasterSz = SECRET_LEN; + + if (ssl->peerNtruKeyPresent == 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + + rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (rc != DRBG_OK) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NTRU_DRBG_ERROR; + } + + rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen, + ssl->peerNtruKey, + ssl->arrays->preMasterSz, + ssl->arrays->preMasterSecret, + &cipherLen, encSecret); + ntru_crypto_drbg_uninstantiate(drbg); + if (rc != NTRU_OK) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NTRU_ENCRYPT_ERROR; + } + + encSz = cipherLen; + ret = 0; + } + break; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + ecc_key myKey; + ecc_key* peerKey = NULL; + word32 size = MAX_ENCRYPT_SZ; + + if (ssl->specs.static_ecdh) { + /* TODO: EccDsa is really fixed Ecc change naming */ + if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + peerKey = ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + peerKey = ssl->peerEccKey; + } + + if (peerKey == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + + wc_ecc_init(&myKey); + ret = wc_ecc_make_key(ssl->rng, peerKey->dp->size, &myKey); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ECC_MAKEKEY_ERROR; + } + + /* precede export with 1 byte length */ + ret = wc_ecc_export_x963(&myKey, encSecret + 1, &size); + encSecret[0] = (byte)size; + encSz = size + 1; + + if (ret != 0) + ret = ECC_EXPORT_ERROR; + else { + size = sizeof(ssl->arrays->preMasterSecret); + ret = wc_ecc_shared_secret(&myKey, peerKey, + ssl->arrays->preMasterSecret, &size); + if (ret != 0) + ret = ECC_SHARED_ERROR; + } + + ssl->arrays->preMasterSz = size; + wc_ecc_free(&myKey); + } + break; + #endif /* HAVE_ECC */ + default: + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ALGO_ID_E; /* unsupported kea */ + } + + if (ret == 0) { + byte *output; + int sendSz; + word32 tlsSz = 0; + + 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; + + sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + #ifdef HAVE_QSH + encSz += qshSz; + sendSz += qshSz; + #endif + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + +#ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + byte idxSave = idx; + idx = sendSz - qshSz; + + if (QSH_KeyExchangeWrite(ssl, 0) != 0) + return MEMORY_E; + + /* extension type */ + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) + > qshSz - OPAQUE16_LEN) + return MEMORY_E; + + idx = idxSave; + } +#endif + + AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl); + +#ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + encSz -= qshSz; + } +#endif + if (tlsSz) { + c16toa((word16)encSz, &output[idx]); + idx += 2; + } + XMEMCPY(output + idx, encSecret, encSz); + idx += encSz; + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = idx-RECORD_HEADER_SZ; /* buildmsg adds rechdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1); + XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (sendSz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return sendSz; + } + } else { + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + } + #endif + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo, + output, sendSz, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + if (ssl->options.groupMessages) + ret = 0; + else + ret = SendBuffered(ssl); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + 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; + } + /* No further need for PMS */ + ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + ssl->arrays->preMasterSz = 0; + + return ret; + } + +#ifndef NO_CERTS + + + int SendCertificateVerify(WOLFSSL* ssl) + { + byte *output; + int sendSz = MAX_CERT_VERIFY_SZ, length, ret; + word32 idx = 0; + word32 sigOutSz = 0; +#ifndef NO_RSA + RsaKey key; + int initRsaKey = 0; +#endif + int usingEcc = 0; +#ifdef HAVE_ECC + ecc_key eccKey; +#endif + + (void)idx; + + if (ssl->options.sendVerify == SEND_BLANK_CERT) + return 0; /* sent blank cert, can't verify */ + + 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; + + ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); + if (ret != 0) + return ret; + +#ifdef HAVE_ECC + wc_ecc_init(&eccKey); +#endif +#ifndef NO_RSA + ret = wc_InitRsaKey(&key, ssl->heap); + if (ret == 0) initRsaKey = 1; + if (ret == 0) + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key, + ssl->buffers.key->length); + if (ret == 0) + sigOutSz = wc_RsaEncryptSize(&key); + else +#endif + { + #ifdef HAVE_ECC + WOLFSSL_MSG("Trying ECC client cert, RSA didn't work"); + + if (ssl->buffers.key == NULL) { + WOLFSSL_MSG("ECC Key missing"); + return NO_PRIVATE_KEY; + } + + idx = 0; + ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &eccKey, + ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ECC client cert"); + usingEcc = 1; + sigOutSz = MAX_ENCODED_SIG_SZ; + } + else { + WOLFSSL_MSG("Bad client cert type"); + } + #endif + } + if (ret == 0) { + byte* verify = (byte*)&output[RECORD_HEADER_SZ + + HANDSHAKE_HEADER_SZ]; +#ifndef NO_OLD_TLS + byte* signBuffer = ssl->hsHashes->certHashes.md5; +#else + byte* signBuffer = NULL; +#endif + word32 signSz = FINISHED_SZ; + word32 extraSz = 0; /* tls 1.2 hash/sig */ +#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, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + #ifndef NO_RSA + if (initRsaKey) + wc_FreeRsaKey(&key); + #endif + #ifdef HAVE_ECC + wc_ecc_free(&eccKey); + #endif + return MEMORY_E; + } +#endif + + (void)encodedSig; + (void)signSz; + (void)signBuffer; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif + length = sigOutSz; + if (IsAtLeastTLSv1_2(ssl)) { + verify[0] = ssl->suites->hashAlgo; + verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo; + extraSz = HASH_SIG_SIZE; + } + + if (usingEcc) { +#ifdef HAVE_ECC + word32 localSz = MAX_ENCODED_SIG_SZ; + word32 digestSz; + byte* digest; + byte doUserEcc = 0; +#ifndef NO_OLD_TLS + /* old tls default */ + digestSz = SHA_DIGEST_SIZE; + digest = ssl->hsHashes->certHashes.sha; +#else + /* new tls default */ + digestSz = SHA256_DIGEST_SIZE; + digest = ssl->hsHashes->certHashes.sha256; +#endif + + #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + if (ssl->ctx->EccSignCb) + doUserEcc = 1; + #endif /* HAVE_ECC */ + #endif /*HAVE_PK_CALLBACKS */ + + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->suites->hashAlgo == sha_mac) { + #ifndef NO_SHA + digest = ssl->hsHashes->certHashes.sha; + digestSz = SHA_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = ssl->hsHashes->certHashes.sha256; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = ssl->hsHashes->certHashes.sha384; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = ssl->hsHashes->certHashes.sha512; + digestSz = SHA512_DIGEST_SIZE; + #endif + } + } + + if (doUserEcc) { + #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + ret = ssl->ctx->EccSignCb(ssl, digest, digestSz, + encodedSig, &localSz, + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->EccSignCtx); + #endif /* HAVE_ECC */ + #endif /*HAVE_PK_CALLBACKS */ + } + else { + ret = wc_ecc_sign_hash(digest, digestSz, encodedSig, + &localSz, ssl->rng, &eccKey); + } + if (ret == 0) { + length = localSz; + c16toa((word16)length, verify + extraSz); /* prepend hdr */ + XMEMCPY(verify + extraSz + VERIFY_HEADER,encodedSig,length); + } +#endif + } +#ifndef NO_RSA + else { + byte doUserRsa = 0; + + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaSignCb) + doUserRsa = 1; + #endif /*HAVE_PK_CALLBACKS */ + + if (IsAtLeastTLSv1_2(ssl)) { + /* + * MSVC Compiler complains because it can not + * guarantee any of the conditionals will succeed in + * assigning a value before wc_EncodeSignature executes. + */ + byte* digest = NULL; + int digestSz = 0; + int typeH = 0; + int didSet = 0; + + if (ssl->suites->hashAlgo == sha_mac) { + #ifndef NO_SHA + digest = ssl->hsHashes->certHashes.sha; + typeH = SHAh; + digestSz = SHA_DIGEST_SIZE; + didSet = 1; + #endif + } + else if (ssl->suites->hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = ssl->hsHashes->certHashes.sha256; + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + didSet = 1; + #endif + } + else if (ssl->suites->hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = ssl->hsHashes->certHashes.sha384; + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + didSet = 1; + #endif + } + else if (ssl->suites->hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = ssl->hsHashes->certHashes.sha512; + typeH = SHA512h; + digestSz = SHA512_DIGEST_SIZE; + didSet = 1; + #endif + } + + if (didSet == 0) { + /* defaults */ + #ifndef NO_OLD_TLS + digest = ssl->hsHashes->certHashes.sha; + digestSz = SHA_DIGEST_SIZE; + typeH = SHAh; + #else + digest = ssl->hsHashes->certHashes.sha256; + digestSz = SHA256_DIGEST_SIZE; + typeH = SHA256h; + #endif + } + + signSz = wc_EncodeSignature(encodedSig, digest,digestSz,typeH); + signBuffer = encodedSig; + } + + c16toa((word16)length, verify + extraSz); /* prepend hdr */ + if (doUserRsa) { + #ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + word32 ioLen = ENCRYPT_LEN; + ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz, + verify + extraSz + VERIFY_HEADER, + &ioLen, + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->RsaSignCtx); + #endif /* NO_RSA */ + #endif /*HAVE_PK_CALLBACKS */ + } + else { + ret = wc_RsaSSL_Sign(signBuffer, signSz, verify + extraSz + + VERIFY_HEADER, ENCRYPT_LEN, &key, ssl->rng); + } + + if (ret > 0) { + /* check for signature faults */ + ret = VerifyRsaSign(verify + extraSz + VERIFY_HEADER, ret, + signBuffer, signSz, &key); + } + } +#endif +#ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret == 0) { + AddHeaders(output, length + extraSz + VERIFY_HEADER, + certificate_verify, ssl); + + sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length + + extraSz + VERIFY_HEADER; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = sendSz - RECORD_HEADER_SZ; + /* build msg adds rec hdr */ + input = (byte*)XMALLOC(inputSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL) + ret = MEMORY_E; + else { + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, + MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA, + input, inputSz, handshake, 1); + XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (sendSz < 0) + ret = sendSz; + } + } else { + ret = HashOutput(ssl, output, sendSz, 0); + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + } + } +#ifndef NO_RSA + if (initRsaKey) + wc_FreeRsaKey(&key); +#endif +#ifdef HAVE_ECC + wc_ecc_free(&eccKey); +#endif + + if (ret == 0) { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateVerify", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, + output, sendSz, ssl->heap); + #endif + ssl->buffers.outputBuffer.length += sendSz; + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); + } + else + return ret; + } +#endif /* NO_CERTS */ + +#ifdef HAVE_SESSION_TICKET +int DoSessionTicket(WOLFSSL* ssl, + const byte* input, word32* inOutIdx, word32 size) +{ + word32 begin = *inOutIdx; + word32 lifetime; + word16 length; + + 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 (length > sizeof(ssl->session.ticket)) + return SESSION_TICKET_LEN_E; + + if ((*inOutIdx - begin) + length > size) + return BUFFER_ERROR; + + /* If the received ticket including its length is greater than + * a length value, the save it. Otherwise, don't save it. */ + if (length > 0) { + XMEMCPY(ssl->session.ticket, input + *inOutIdx, length); + *inOutIdx += length; + ssl->session.ticketLen = length; + ssl->timeout = lifetime; + 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); +#ifndef NO_SESSION_CACHE + AddSession(ssl); +#endif + + } + else { + ssl->session.ticketLen = 0; + } + + if (IsEncryptionOn(ssl, 0)) { + *inOutIdx += ssl->keys.padSz; + } + + ssl->expect_session_ticket = 0; + + return 0; +} +#endif /* HAVE_SESSION_TICKET */ + +#endif /* NO_WOLFSSL_CLIENT */ + + +#ifndef NO_WOLFSSL_SERVER + + int SendServerHello(WOLFSSL* ssl) + { + byte *output; + word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + byte sessIdSz = ID_LEN; + + length = VERSION_SZ + RAN_LEN + + ID_LEN + ENUM_LEN + + SUITE_LEN + + ENUM_LEN; + +#ifdef HAVE_TLS_EXTENSIONS + length += TLSX_GetResponseSize(ssl); + #ifdef HAVE_SESSION_TICKET + if (ssl->options.useTicket && ssl->arrays->sessionIDSz == 0) { + /* no session id */ + length -= ID_LEN; + sessIdSz = 0; + } + #endif /* HAVE_SESSION_TICKET */ +#endif + + /* check for avalaible size */ + if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + 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 = ssl->keys.dtls_state.curSeq; + idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif /* WOLFSSL_DTLS */ + AddHeaders(output, length, server_hello, ssl); + + /* now write to output */ + /* first version */ + output[idx++] = ssl->version.major; + output[idx++] = 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; + + /* 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); + } + 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 + TLSX_WriteResponse(ssl, output + idx); +#endif + + ssl->buffers.outputBuffer.length += sendSz; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); + } + + +#ifdef HAVE_ECC + + static byte SetCurveId(int size) + { + switch(size) { +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) + case 20: + return WOLFSSL_ECC_SECP160R1; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) + case 24: + return WOLFSSL_ECC_SECP192R1; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) + case 28: + return WOLFSSL_ECC_SECP224R1; +#endif +#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) + case 32: + return WOLFSSL_ECC_SECP256R1; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) + case 48: + return WOLFSSL_ECC_SECP384R1; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) + case 66: + return WOLFSSL_ECC_SECP521R1; +#endif + default: + return 0; + } + } + +#endif /* HAVE_ECC */ + + + int SendServerKeyExchange(WOLFSSL* ssl) + { + int ret = 0; + #ifdef HAVE_QSH + word32 qshSz = 0; + #endif + (void)ssl; + #define ERROR_OUT(err, eLabel) do { ret = err; goto eLabel; } while(0) + + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) { + qshSz = QSH_KeyGetSize(ssl); + } + #endif + + + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + byte *output; + word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + if (ssl->arrays->server_hint[0] == 0) return 0; /* don't send */ + + /* include size part */ + length = (word32)XSTRLEN(ssl->arrays->server_hint); + if (length > MAX_PSK_ID_LEN) { + return SERVER_HINT_ERROR; + } + + length += HINT_LEN_SZ; + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + length += qshSz; + sendSz += qshSz; + #endif + + #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, server_key_exchange, ssl); + + /* key data */ + #ifdef HAVE_QSH + c16toa((word16)(length - qshSz - HINT_LEN_SZ), output + idx); + #else + c16toa((word16)(length - HINT_LEN_SZ), output + idx); + #endif + idx += HINT_LEN_SZ; + XMEMCPY(output + idx, ssl->arrays->server_hint,length -HINT_LEN_SZ); + + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + if (qshSz > 0) { + idx = sendSz - qshSz; + if (QSH_KeyExchangeWrite(ssl, 1) != 0) { + return MEMORY_E; + } + + /* extension type */ + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) + > qshSz - OPAQUE16_LEN) { + return MEMORY_E; + } + } + } + #endif + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + return ret; + } + } + #endif + + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) { + return ret; + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) { + AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); + } + if (ssl->toInfoOn) { + AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output, + sendSz, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (ssl->options.groupMessages) { + ret = 0; + } + else { + ret = SendBuffered(ssl); + } + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + #endif /*NO_PSK */ + + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + byte *output; + word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + word32 hintLen; + int sendSz; + DhKey dhKey; + + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL) { + return NO_DH_PARAMS; + } + + if (ssl->buffers.serverDH_Pub.buffer == NULL) { + ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( + ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap, + DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_Pub.buffer == NULL) { + return MEMORY_E; + } + } + + if (ssl->buffers.serverDH_Priv.buffer == NULL) { + ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( + ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap, + DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_Priv.buffer == NULL) { + return MEMORY_E; + } + } + + wc_InitDhKey(&dhKey); + ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret == 0) { + ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, + ssl->buffers.serverDH_Priv.buffer, + &ssl->buffers.serverDH_Priv.length, + ssl->buffers.serverDH_Pub.buffer, + &ssl->buffers.serverDH_Pub.length); + } + wc_FreeDhKey(&dhKey); + if (ret != 0) { + return ret; + } + + 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) { + return SERVER_HINT_ERROR; + } + length += hintLen + HINT_LEN_SZ; + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + length += qshSz; + sendSz += qshSz; + #endif + #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, server_key_exchange, ssl); + + /* key data */ + c16toa((word16)hintLen, output + idx); + idx += HINT_LEN_SZ; + XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen); + idx += hintLen; + + /* add p, g, pub */ + c16toa((word16)ssl->buffers.serverDH_P.length, output + idx); + idx += LENGTH_SZ; + XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); + idx += ssl->buffers.serverDH_P.length; + + /* g */ + c16toa((word16)ssl->buffers.serverDH_G.length, output + idx); + idx += LENGTH_SZ; + XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + idx += ssl->buffers.serverDH_G.length; + + /* pub */ + c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx); + idx += LENGTH_SZ; + XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length); + idx += ssl->buffers.serverDH_Pub.length; + (void)idx; /* suppress analyzer warning, and keep idx current */ + + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + if (qshSz > 0) { + idx = sendSz - qshSz; + QSH_KeyExchangeWrite(ssl, 1); + + /* extension type */ + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) + > qshSz - OPAQUE16_LEN) { + return MEMORY_E; + } + } + } + #endif + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + return ret; + } + } + #endif + + ret = HashOutput(ssl, output, sendSz, 0); + + if (ret != 0) { + return ret; + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) { + AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); + } + if (ssl->toInfoOn) { + AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output, + sendSz, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (ssl->options.groupMessages) { + ret = 0; + } + else { + ret = SendBuffered(ssl); + } + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + #endif /* !NO_DH && !NO_PSK */ + + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + word32 hintLen; + word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + byte *output; + ecc_key dsaKey; + #ifdef WOLFSSL_SMALL_STACK + byte* exportBuf = NULL; + #else + byte exportBuf[MAX_EXPORT_ECC_SZ]; + #endif + word32 expSz = MAX_EXPORT_ECC_SZ; + + /* curve type, named curve, length(1) */ + length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + /* pub key size */ + WOLFSSL_MSG("Using ephemeral ECDH"); + + /* need ephemeral key now, create it if missing */ + if (ssl->eccTempKey == NULL) { + /* alloc/init on demand */ + ssl->eccTempKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->eccTempKey == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + wc_ecc_init(ssl->eccTempKey); + } + if (ssl->eccTempKeyPresent == 0) { + if (wc_ecc_make_key(ssl->rng, ssl->eccTempKeySz, + ssl->eccTempKey) != 0) { + return ECC_MAKEKEY_ERROR; + } + ssl->eccTempKeyPresent = 1; + } + + #ifdef WOLFSSL_SMALL_STACK + exportBuf = (byte*)XMALLOC(MAX_EXPORT_ECC_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (exportBuf == NULL) { + return MEMORY_E; + } + #endif + + if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &expSz) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(exportBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ECC_EXPORT_ERROR; + } + length += expSz; + + /* include size part */ + hintLen = (word32)XSTRLEN(ssl->arrays->server_hint); + if (hintLen > MAX_PSK_ID_LEN) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(exportBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return SERVER_HINT_ERROR; + } + length += hintLen + HINT_LEN_SZ; + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + length += qshSz; + sendSz += qshSz; + #endif + #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) { + wc_ecc_free(&dsaKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(exportBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* key data */ + c16toa((word16)hintLen, output + idx); + idx += HINT_LEN_SZ; + XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen); + idx += hintLen; + + /* ECC key exchange data */ + output[idx++] = named_curve; + output[idx++] = 0x00; /* leading zero */ + output[idx++] = SetCurveId(wc_ecc_size(ssl->eccTempKey)); + output[idx++] = (byte)expSz; + XMEMCPY(output + idx, exportBuf, expSz); + #ifdef WOLFSSL_SMALL_STACK + XFREE(exportBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + if (qshSz > 0) { + idx = sendSz - qshSz; + QSH_KeyExchangeWrite(ssl, 1); + + /* extension type */ + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) + > qshSz - OPAQUE16_LEN) { + return MEMORY_E; + } + } + } + #endif + + + AddHeaders(output, length, server_key_exchange, ssl); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + return ret; + } + } + #endif + + ret = HashOutput(ssl, output, sendSz, 0); + + if (ret != 0) { + return ret; + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) { + AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); + } + if (ssl->toInfoOn) { + AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output, + sendSz, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (ssl->options.groupMessages) { + ret = 0; + } + else { + ret = SendBuffered(ssl); + } + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + #endif /* HAVE_ECC && !NO_PSK */ + + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + byte *output; + word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + word32 sigSz; + word32 preSigSz, preSigIdx; + #ifndef NO_RSA + RsaKey rsaKey; + #endif + ecc_key dsaKey; + #ifdef WOLFSSL_SMALL_STACK + byte* exportBuf = NULL; + #else + byte exportBuf[MAX_EXPORT_ECC_SZ]; + #endif + word32 expSz = MAX_EXPORT_ECC_SZ; + + #ifndef NO_OLD_TLS + byte doMd5 = 0; + byte doSha = 0; + #endif + #ifndef NO_SHA256 + byte doSha256 = 0; + #endif + #ifdef WOLFSSL_SHA384 + byte doSha384 = 0; + #endif + #ifdef WOLFSSL_SHA512 + byte doSha512 = 0; + #endif + + if (ssl->specs.static_ecdh) { + WOLFSSL_MSG("Using Static ECDH, not sending ServerKeyExchange"); + return 0; + } + + /* curve type, named curve, length(1) */ + length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + /* pub key size */ + WOLFSSL_MSG("Using ephemeral ECDH"); + + /* need ephemeral key now, create it if missing */ + if (ssl->eccTempKey == NULL) { + /* alloc/init on demand */ + ssl->eccTempKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->eccTempKey == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + wc_ecc_init(ssl->eccTempKey); + } + if (ssl->eccTempKeyPresent == 0) { + if (wc_ecc_make_key(ssl->rng, ssl->eccTempKeySz, + ssl->eccTempKey) != 0) { + return ECC_MAKEKEY_ERROR; + } + ssl->eccTempKeyPresent = 1; + } + + #ifdef WOLFSSL_SMALL_STACK + exportBuf = (byte*)XMALLOC(MAX_EXPORT_ECC_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (exportBuf == NULL) { + return MEMORY_E; + } + #endif + + if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &expSz) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, done_a); + } + length += expSz; + + preSigSz = length; + preSigIdx = idx; + + #ifndef NO_RSA + ret = wc_InitRsaKey(&rsaKey, ssl->heap); + if (ret != 0) { + goto done_a; + } + #endif + + wc_ecc_init(&dsaKey); + + /* sig length */ + length += LENGTH_SZ; + + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + #ifndef NO_RSA + wc_FreeRsaKey(&rsaKey); + #endif + wc_ecc_free(&dsaKey); + ERROR_OUT(NO_PRIVATE_KEY, done_a); + } + + #ifndef NO_RSA + if (ssl->specs.sig_algo == rsa_sa_algo) { + /* rsa sig size */ + word32 i = 0; + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &i, + &rsaKey, ssl->buffers.key->length); + if (ret != 0) { + goto done_a; + } + sigSz = wc_RsaEncryptSize(&rsaKey); + } else + #endif + + if (ssl->specs.sig_algo == ecc_dsa_sa_algo) { + /* ecdsa sig size */ + word32 i = 0; + ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &i, + &dsaKey, ssl->buffers.key->length); + if (ret != 0) { + goto done_a; + } + sigSz = wc_ecc_sig_size(&dsaKey); /* worst case estimate */ + } + else { + #ifndef NO_RSA + wc_FreeRsaKey(&rsaKey); + #endif + wc_ecc_free(&dsaKey); + ERROR_OUT(ALGO_ID_E, done_a); /* unsupported type */ + } + length += sigSz; + + if (IsAtLeastTLSv1_2(ssl)) { + length += HASH_SIG_SIZE; + } + + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + length += qshSz; + sendSz += qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = idx; + } + #endif + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + #ifndef NO_RSA + wc_FreeRsaKey(&rsaKey); + #endif + wc_ecc_free(&dsaKey); + goto done_a; + } + + /* get output buffer */ + 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 */ + output[idx++] = named_curve; + output[idx++] = 0x00; /* leading zero */ + output[idx++] = SetCurveId(wc_ecc_size(ssl->eccTempKey)); + output[idx++] = (byte)expSz; + XMEMCPY(output + idx, exportBuf, expSz); + idx += expSz; + if (IsAtLeastTLSv1_2(ssl)) { + byte setHash = 0; + + output[idx++] = ssl->suites->hashAlgo; + output[idx++] = ssl->suites->sigAlgo; + + switch (ssl->suites->hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + doSha512 = 1; + setHash = 1; + #endif + break; + + case sha384_mac: + #ifdef WOLFSSL_SHA384 + doSha384 = 1; + setHash = 1; + #endif + break; + + case sha256_mac: + #ifndef NO_SHA256 + doSha256 = 1; + setHash = 1; + #endif + break; + + case sha_mac: + #ifndef NO_OLD_TLS + doSha = 1; + setHash = 1; + #endif + break; + + default: + WOLFSSL_MSG("Bad hash sig algo"); + break; + } + + if (setHash == 0) { + #ifndef NO_RSA + wc_FreeRsaKey(&rsaKey); + #endif + wc_ecc_free(&dsaKey); + ERROR_OUT(ALGO_ID_E, done_a); + } + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + doSha = 1; + if (ssl->suites->sigAlgo == rsa_sa_algo) { + doMd5 = 1; + } + #else + #ifndef NO_RSA + wc_FreeRsaKey(&rsaKey); + #endif + wc_ecc_free(&dsaKey); + ERROR_OUT(ALGO_ID_E, done_a); + #endif + } + + /* Signtaure length will be written later, when we're sure what it + is */ + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) { + ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, + FUZZ_SIGNATURE, ssl->fuzzerCtx); + } + #endif + + /* do signature */ + { + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_SMALL_STACK + Md5* md5 = NULL; + Sha* sha = NULL; + #else + Md5 md5[1]; + Sha sha[1]; + #endif + #endif + #ifdef WOLFSSL_SMALL_STACK + byte* hash = NULL; + #else + byte hash[FINISHED_SZ]; + #endif + #ifndef NO_SHA256 + #ifdef WOLFSSL_SMALL_STACK + Sha256* sha256 = NULL; + byte* hash256 = NULL; + #else + Sha256 sha256[1]; + byte hash256[SHA256_DIGEST_SIZE]; + #endif + #endif + #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SMALL_STACK + Sha384* sha384 = NULL; + byte* hash384 = NULL; + #else + Sha384 sha384[1]; + byte hash384[SHA384_DIGEST_SIZE]; + #endif + #endif + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SMALL_STACK + Sha512* sha512 = NULL; + byte* hash512 = NULL; + #else + Sha512 sha512[1]; + byte hash512[SHA512_DIGEST_SIZE]; + #endif + #endif + + #ifdef WOLFSSL_SMALL_STACK + hash = (byte*)XMALLOC(FINISHED_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (hash == NULL) { + ERROR_OUT(MEMORY_E, done_a); + } + #endif + + #ifndef NO_OLD_TLS + /* md5 */ + #ifdef WOLFSSL_SMALL_STACK + if (doMd5) { + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) { + ERROR_OUT(MEMORY_E, done_a2); + } + } + #endif + if (doMd5) { + wc_InitMd5(md5); + wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN); + wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN); + wc_Md5Update(md5, output + preSigIdx, preSigSz); + wc_Md5Final(md5, hash); + } + /* sha */ + #ifdef WOLFSSL_SMALL_STACK + if (doSha) { + sha = (Sha*)XMALLOC(sizeof(Sha), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) { + ERROR_OUT(MEMORY_E, done_a2); + } + } + #endif + if (doSha) { + ret = wc_InitSha(sha); + if (ret != 0) { + goto done_a2; + } + wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN); + wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN); + wc_ShaUpdate(sha, output + preSigIdx, preSigSz); + wc_ShaFinal(sha, &hash[MD5_DIGEST_SIZE]); + } + #endif + + #ifndef NO_SHA256 + #ifdef WOLFSSL_SMALL_STACK + if (doSha256) { + sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL || hash256 == NULL) { + ERROR_OUT(MEMORY_E, done_a2); + } + } + #endif + + if (doSha256) { + if (!(ret = wc_InitSha256(sha256)) + && !(ret = wc_Sha256Update(sha256, + ssl->arrays->clientRandom, RAN_LEN)) + && !(ret = wc_Sha256Update(sha256, + ssl->arrays->serverRandom, RAN_LEN)) + && !(ret = wc_Sha256Update(sha256, + output + preSigIdx, preSigSz))) { + ret = wc_Sha256Final(sha256, hash256); + } + if (ret != 0) { + goto done_a2; + } + } + #endif + + #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SMALL_STACK + if (doSha384) { + sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL || hash384 == NULL) { + ERROR_OUT(MEMORY_E, done_a2); + } + } + #endif + + if (doSha384) { + if (!(ret = wc_InitSha384(sha384)) + && !(ret = wc_Sha384Update(sha384, + ssl->arrays->clientRandom, RAN_LEN)) + && !(ret = wc_Sha384Update(sha384, + ssl->arrays->serverRandom, RAN_LEN)) + && !(ret = wc_Sha384Update(sha384, + output + preSigIdx, preSigSz))) { + ret = wc_Sha384Final(sha384, hash384); + } + if (ret != 0) { + goto done_a2; + } + } + #endif + + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SMALL_STACK + if (doSha512) { + sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha512 == NULL || hash512 == NULL) { + ERROR_OUT(MEMORY_E, done_a2); + } + } + #endif + + if (doSha512) { + if (!(ret = wc_InitSha512(sha512)) + && !(ret = wc_Sha512Update(sha512, + ssl->arrays->clientRandom, RAN_LEN)) + && !(ret = wc_Sha512Update(sha512, + ssl->arrays->serverRandom, RAN_LEN)) + && !(ret = wc_Sha512Update(sha512, + output + preSigIdx, preSigSz))) { + ret = wc_Sha512Final(sha512, hash512); + } + if (ret != 0) { + goto done_a2; + } + } + #endif + + #ifndef NO_RSA + if (ssl->suites->sigAlgo == rsa_sa_algo) { + byte* signBuffer = hash; + word32 signSz = FINISHED_SZ; + byte doUserRsa = 0; + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaSignCb) + doUserRsa = 1; + #endif + + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, done_a2); + } + #endif + + if (IsAtLeastTLSv1_2(ssl)) { + byte* digest = &hash[MD5_DIGEST_SIZE]; + int typeH = SHAh; + int digestSz = SHA_DIGEST_SIZE; + + if (ssl->suites->hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = hash384; + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = hash512; + typeH = SHA512h; + digestSz = SHA512_DIGEST_SIZE; + #endif + } + + if (digest == NULL) { + #ifndef NO_RSA + wc_FreeRsaKey(&rsaKey); + #endif + wc_ecc_free(&dsaKey); + ERROR_OUT(ALGO_ID_E, done_a2); + } + signSz = wc_EncodeSignature(encodedSig, digest, + digestSz, typeH); + signBuffer = encodedSig; + } + /* write sig size here */ + c16toa((word16)sigSz, output + idx); + idx += LENGTH_SZ; + + if (doUserRsa) { + #ifdef HAVE_PK_CALLBACKS + word32 ioLen = sigSz; + ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz, + output + idx, &ioLen, + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->RsaSignCtx); + #endif /*HAVE_PK_CALLBACKS */ + } + else { + ret = wc_RsaSSL_Sign(signBuffer, signSz, output + idx, + sigSz, &rsaKey, ssl->rng); + } + + if (ret > 0) { + /* check for signature faults */ + ret = VerifyRsaSign(output + idx, ret, + signBuffer, signSz, &rsaKey); + } + wc_FreeRsaKey(&rsaKey); + wc_ecc_free(&dsaKey); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + if (ret < 0) { + goto done_a2; + } + } else + #endif + + if (ssl->suites->sigAlgo == ecc_dsa_sa_algo) { + #ifndef NO_OLD_TLS + byte* digest = &hash[MD5_DIGEST_SIZE]; + word32 digestSz = SHA_DIGEST_SIZE; + #else + byte* digest = hash256; + word32 digestSz = SHA256_DIGEST_SIZE; + #endif + word32 sz = sigSz; + byte doUserEcc = 0; + + #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) + if (ssl->ctx->EccSignCb) { + doUserEcc = 1; + } + #endif + + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->suites->hashAlgo == sha_mac) { + #ifndef NO_SHA + digest = &hash[MD5_DIGEST_SIZE]; + digestSz = SHA_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = hash384; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = hash512; + digestSz = SHA512_DIGEST_SIZE; + #endif + } + } + + if (doUserEcc) { + #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) + ret = ssl->ctx->EccSignCb(ssl, digest, digestSz, + output + LENGTH_SZ + idx, + &sz, + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->EccSignCtx); + #endif + } + else { + ret = wc_ecc_sign_hash(digest, digestSz, + output + LENGTH_SZ + idx, &sz, ssl->rng, &dsaKey); + } + #ifndef NO_RSA + wc_FreeRsaKey(&rsaKey); + #endif + wc_ecc_free(&dsaKey); + + if (ret < 0) { + goto done_a2; + } + + /* Now that we know the real sig size, write it. */ + c16toa((word16)sz, output + idx); + + /* And adjust length and sendSz from estimates */ + length += sz - sigSz; + sendSz += sz - sigSz; + } + + done_a2: + #ifdef WOLFSSL_SMALL_STACK + #ifndef NO_OLD_TLS + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #ifndef NO_SHA256 + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifdef WOLFSSL_SHA384 + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifdef WOLFSSL_SHA512 + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #endif + + if (ret < 0) + goto done_a; + } + +#ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + if (qshSz > 0) { + idx = sendSz - qshSz; + QSH_KeyExchangeWrite(ssl, 1); + + /* extension type */ + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) + > qshSz - OPAQUE16_LEN) { + return MEMORY_E; + } + } + } +#endif + + + AddHeaders(output, length, server_key_exchange, ssl); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + goto done_a; + } + } + #endif + + if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) { + goto done_a; + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) { + AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); + } + if (ssl->toInfoOn) { + AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, + output, sendSz, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (ssl->options.groupMessages) { + ret = 0; + } + else { + ret = SendBuffered(ssl); + } + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + + done_a: + #ifdef WOLFSSL_SMALL_STACK + XFREE(exportBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } + #endif /* HAVE_ECC */ + + #if !defined(NO_DH) && !defined(NO_RSA) + case diffie_hellman_kea: + { + byte *output; + word32 length = 0, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + word32 sigSz = 0, i = 0; + word32 preSigSz = 0, preSigIdx = 0; + RsaKey rsaKey; + DhKey dhKey; + + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL) { + return NO_DH_PARAMS; + } + + if (ssl->buffers.serverDH_Pub.buffer == NULL) { + ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( + ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap, + DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_Pub.buffer == NULL) { + return MEMORY_E; + } + } + + if (ssl->buffers.serverDH_Priv.buffer == NULL) { + ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( + ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap, + DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_Priv.buffer == NULL) { + return MEMORY_E; + } + } + + wc_InitDhKey(&dhKey); + ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret == 0) { + ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, + ssl->buffers.serverDH_Priv.buffer, + &ssl->buffers.serverDH_Priv.length, + ssl->buffers.serverDH_Pub.buffer, + &ssl->buffers.serverDH_Pub.length); + } + wc_FreeDhKey(&dhKey); + + if (ret != 0) { + return ret; + } + + length = LENGTH_SZ * 3; /* p, g, pub */ + length += ssl->buffers.serverDH_P.length + + ssl->buffers.serverDH_G.length + + ssl->buffers.serverDH_Pub.length; + + preSigIdx = idx; + preSigSz = length; + + if (!ssl->options.usingAnon_cipher) { + ret = wc_InitRsaKey(&rsaKey, ssl->heap); + if (ret != 0) { + return ret; + } + + /* sig length */ + length += LENGTH_SZ; + + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + return NO_PRIVATE_KEY; + } + + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &i, + &rsaKey, ssl->buffers.key->length); + if (ret == 0) { + sigSz = wc_RsaEncryptSize(&rsaKey); + length += sigSz; + } + else { + wc_FreeRsaKey(&rsaKey); + return ret; + } + + if (IsAtLeastTLSv1_2(ssl)) { + length += HASH_SIG_SIZE; + } + } + + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + length += qshSz; + sendSz += qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = idx; + } + #endif + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if (!ssl->options.usingAnon_cipher) { + wc_FreeRsaKey(&rsaKey); + } + return ret; + } + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, length, server_key_exchange, ssl); + + /* add p, g, pub */ + c16toa((word16)ssl->buffers.serverDH_P.length, output + idx); + idx += LENGTH_SZ; + XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); + idx += ssl->buffers.serverDH_P.length; + + /* g */ + c16toa((word16)ssl->buffers.serverDH_G.length, output + idx); + idx += LENGTH_SZ; + XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + idx += ssl->buffers.serverDH_G.length; + + /* pub */ + c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx); + idx += LENGTH_SZ; + XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length); + idx += ssl->buffers.serverDH_Pub.length; + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) { + ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, + FUZZ_SIGNATURE, ssl->fuzzerCtx); + } + #endif + + /* Add signature */ + if (!ssl->options.usingAnon_cipher) { + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_SMALL_STACK + Md5* md5 = NULL; + Sha* sha = NULL; + #else + Md5 md5[1]; + Sha sha[1]; + #endif + #endif + #ifdef WOLFSSL_SMALL_STACK + byte* hash = NULL; + #else + byte hash[FINISHED_SZ]; + #endif + #ifndef NO_SHA256 + #ifdef WOLFSSL_SMALL_STACK + Sha256* sha256 = NULL; + byte* hash256 = NULL; + #else + Sha256 sha256[1]; + byte hash256[SHA256_DIGEST_SIZE]; + #endif + #endif + #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SMALL_STACK + Sha384* sha384 = NULL; + byte* hash384 = NULL; + #else + Sha384 sha384[1]; + byte hash384[SHA384_DIGEST_SIZE]; + #endif + #endif + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SMALL_STACK + Sha512* sha512 = NULL; + byte* hash512 = NULL; + #else + Sha512 sha512[1]; + byte hash512[SHA512_DIGEST_SIZE]; + #endif + #endif + + #ifndef NO_OLD_TLS + byte doMd5 = 0; + byte doSha = 0; + #endif + #ifndef NO_SHA256 + byte doSha256 = 0; + #endif + #ifdef WOLFSSL_SHA384 + byte doSha384 = 0; + #endif + #ifdef WOLFSSL_SHA512 + byte doSha512 = 0; + #endif + + /* Add hash/signature algo ID */ + if (IsAtLeastTLSv1_2(ssl)) { + byte setHash = 0; + + output[idx++] = ssl->suites->hashAlgo; + output[idx++] = ssl->suites->sigAlgo; + + switch (ssl->suites->hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + doSha512 = 1; + setHash = 1; + #endif + break; + + case sha384_mac: + #ifdef WOLFSSL_SHA384 + doSha384 = 1; + setHash = 1; + #endif + break; + + case sha256_mac: + #ifndef NO_SHA256 + doSha256 = 1; + setHash = 1; + #endif + break; + + case sha_mac: + #ifndef NO_OLD_TLS + doSha = 1; + setHash = 1; + #endif + break; + + default: + WOLFSSL_MSG("Bad hash sig algo"); + break; + } + + if (setHash == 0) { + wc_FreeRsaKey(&rsaKey); + return ALGO_ID_E; + } + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + doSha = 1; + if (ssl->suites->sigAlgo == rsa_sa_algo) { + doMd5 = 1; + } + #else + wc_FreeRsaKey(&rsaKey); + return ALGO_ID_E; + #endif + } + + /* signature size */ + c16toa((word16)sigSz, output + idx); + idx += LENGTH_SZ; + + /* do signature */ + #ifdef WOLFSSL_SMALL_STACK + hash = (byte*)XMALLOC(FINISHED_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (hash == NULL) { + return MEMORY_E; /* No heap commitment before this point, + from now on, the resources are freed + at done_b. */ + } + #endif + + #ifndef NO_OLD_TLS + /* md5 */ + #ifdef WOLFSSL_SMALL_STACK + if (doMd5) { + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) { + ERROR_OUT(MEMORY_E, done_b); + } + } + #endif + if (doMd5) { + wc_InitMd5(md5); + wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN); + wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN); + wc_Md5Update(md5, output + preSigIdx, preSigSz); + wc_Md5Final(md5, hash); + } + + /* sha */ + #ifdef WOLFSSL_SMALL_STACK + if (doSha) { + sha = (Sha*)XMALLOC(sizeof(Sha), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) { + ERROR_OUT(MEMORY_E, done_b); + } + } + #endif + + if (doSha) { + if ((ret = wc_InitSha(sha)) != 0) { + goto done_b; + } + wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN); + wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN); + wc_ShaUpdate(sha, output + preSigIdx, preSigSz); + wc_ShaFinal(sha, &hash[MD5_DIGEST_SIZE]); + } + #endif + + #ifndef NO_SHA256 + #ifdef WOLFSSL_SMALL_STACK + if (doSha256) { + sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL || hash256 == NULL) { + ERROR_OUT(MEMORY_E, done_b); + } + } + #endif + + if (doSha256) { + if (!(ret = wc_InitSha256(sha256)) + && !(ret = wc_Sha256Update(sha256, + ssl->arrays->clientRandom, RAN_LEN)) + && !(ret = wc_Sha256Update(sha256, + ssl->arrays->serverRandom, RAN_LEN)) + && !(ret = wc_Sha256Update(sha256, + output + preSigIdx, preSigSz))) { + ret = wc_Sha256Final(sha256, hash256); + } + if (ret != 0) { + goto done_b; + } + } + #endif + + #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SMALL_STACK + if (doSha384) { + sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL || hash384 == NULL) { + ERROR_OUT(MEMORY_E, done_b); + } + } + #endif + + if (doSha384) { + if (!(ret = wc_InitSha384(sha384)) + && !(ret = wc_Sha384Update(sha384, + ssl->arrays->clientRandom, RAN_LEN)) + && !(ret = wc_Sha384Update(sha384, + ssl->arrays->serverRandom, RAN_LEN)) + && !(ret = wc_Sha384Update(sha384, + output + preSigIdx, preSigSz))) { + ret = wc_Sha384Final(sha384, hash384); + } + if (ret != 0) { + goto done_b; + } + } + #endif + + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SMALL_STACK + if (doSha512) { + sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha512 == NULL || hash512 == NULL) { + ERROR_OUT(MEMORY_E, done_b); + } + } + #endif + + if (doSha512) { + if (!(ret = wc_InitSha512(sha512)) + && !(ret = wc_Sha512Update(sha512, + ssl->arrays->clientRandom, RAN_LEN)) + && !(ret = wc_Sha512Update(sha512, + ssl->arrays->serverRandom, RAN_LEN)) + && !(ret = wc_Sha512Update(sha512, + output + preSigIdx, preSigSz))) { + ret = wc_Sha512Final(sha512, hash512); + } + if (ret != 0) { + goto done_b; + } + } + #endif + + #ifndef NO_RSA + if (ssl->suites->sigAlgo == rsa_sa_algo) { + byte* signBuffer = hash; + word32 signSz = FINISHED_SZ; + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + byte doUserRsa = 0; + + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaSignCb) { + doUserRsa = 1; + } + #endif + + if (IsAtLeastTLSv1_2(ssl)) { + byte* digest = &hash[MD5_DIGEST_SIZE]; + int typeH = SHAh; + int digestSz = SHA_DIGEST_SIZE; + + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) + ERROR_OUT(MEMORY_E, done_b); + #endif + + if (ssl->suites->hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = hash384; + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + else if (ssl->suites->hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = hash512; + typeH = SHA512h; + digestSz = SHA512_DIGEST_SIZE; + #endif + } + + if (digest == NULL) { + ret = ALGO_ID_E; + } else { + signSz = wc_EncodeSignature(encodedSig, digest, + digestSz, typeH); + signBuffer = encodedSig; + } + } + if (doUserRsa && ret == 0) { + #ifdef HAVE_PK_CALLBACKS + word32 ioLen = sigSz; + ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz, + output + idx, &ioLen, + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->RsaSignCtx); + #endif + } else if (ret == 0) { + ret = wc_RsaSSL_Sign(signBuffer, signSz, output + idx, + sigSz, &rsaKey, ssl->rng); + } + + if (ret > 0) { + /* check for signature faults */ + ret = VerifyRsaSign(output + idx, ret, + signBuffer, signSz, &rsaKey); + } + + wc_FreeRsaKey(&rsaKey); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + #endif + + done_b: + #ifdef WOLFSSL_SMALL_STACK + #ifndef NO_OLD_TLS + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #ifndef NO_SHA256 + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifdef WOLFSSL_SHA384 + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifdef WOLFSSL_SHA512 + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #endif + + if (ret < 0) { + return ret; + } + } + + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + if (qshSz > 0) { + idx = sendSz - qshSz; + QSH_KeyExchangeWrite(ssl, 1); + + /* extension type */ + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) + > qshSz - OPAQUE16_LEN) { + return MEMORY_E; + } + } + } + #endif + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + return ret; + } + } + #endif + + if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) { + return ret; + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) { + AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); + } + if (ssl->toInfoOn) { + AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, + output, sendSz, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (ssl->options.groupMessages) { + ret = 0; + } + else { + ret = SendBuffered(ssl); + } + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + #endif /* NO_DH */ + default: + break; + } /* switch(ssl->specs.kea) */ + + return ret; + #undef ERROR_OUT + } + + + /* 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; + } + } + +#ifdef HAVE_SUPPORTED_CURVES + if (!TLSX_ValidateEllipticCurves(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 + + return 1; + } + +#ifndef NO_WOLFSSL_SERVER + static int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + { + 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; + /* start with best, if a match we are good */ + for (i = 0; i < ssl->suites->suiteSz; i += 2) + for (j = 0; j < peerSuites->suiteSz; j += 2) + 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; + } +#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; + + (void)inSz; + WOLFSSL_MSG("Got old format client hello"); +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ClientHello", &ssl->handShakeInfo); + 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; + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Client trying to connect with lesser version"); + return VERSION_ERROR; + } + if (pv.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG(" version below minimum allowed, fatal error"); + return VERSION_ERROR; + } + if (pv.minor == SSLv3_MINOR) { + /* turn off tls */ + WOLFSSL_MSG(" downgrading to SSLv3"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + } + else if (pv.minor == TLSv1_MINOR) { + WOLFSSL_MSG(" downgrading 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(" downgrading to TLSv1.1"); + ssl->version.minor = TLSv1_1_MINOR; + } +#ifndef NO_RSA + haveRSA = 1; +#endif +#ifndef NO_PSK + havePSK = ssl->options.havePSK; +#endif + + InitSuites(ssl->suites, ssl->version, 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 += 2; + + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + return BUFFER_ERROR; + clSuites.hashSigAlgoSz = 0; + + /* session size */ + ato16(&input[idx], &sessionSz); + idx += 2; + + if (sessionSz > ID_LEN) + return BUFFER_ERROR; + + /* random size */ + ato16(&input[idx], &randomSz); + idx += 2; + + 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], 2); + j += 2; + } + idx += 2; + } + 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; + *inOutIdx = idx; + + ssl->options.haveSessionId = 1; + /* DoClientHello uses same resume code */ + if (ssl->options.resuming) { /* let's try */ + int ret = -1; + WOLFSSL_SESSION* session = GetSession(ssl, + ssl->arrays->masterSecret); + #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 { + if (MatchSuite(ssl, &clSuites) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, OldClientHello"); + return UNSUPPORTED_SUITE; + } + #ifdef SESSION_CERTS + ssl->session = *session; /* restore session certs. */ + #endif + + 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; + } + } + + return MatchSuite(ssl, &clSuites); + } + +#endif /* OLD_HELLO_ALLOWED */ + + + static int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) + { + byte b; + ProtocolVersion pv; + Suites clSuites; + word32 i = *inOutIdx; + word32 begin = i; +#ifdef WOLFSSL_DTLS + Hmac cookieHmac; + byte peerCookie[MAX_COOKIE_LEN]; + byte peerCookieSz = 0; + byte cookieType; + byte cookieSz; +#endif /* WOLFSSL_DTLS */ + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + 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 (ssl->options.dtls) { + int ret; + #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 = SHA; + cookieSz = SHA_DIGEST_SIZE; + #endif /* NO_SHA */ + #ifndef NO_SHA256 + cookieType = SHA256; + cookieSz = 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, + 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; + + 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; + + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Client trying to connect with lesser version"); + return VERSION_ERROR; + } + if (pv.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG(" version below minimum allowed, fatal error"); + return VERSION_ERROR; + } + + if (pv.minor == SSLv3_MINOR) { + /* turn off tls */ + WOLFSSL_MSG(" downgrading 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(" downgrading to TLSv1"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + } + else if (pv.minor == TLSv1_1_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.1"); + ssl->version.minor = TLSv1_1_MINOR; + } +#ifndef NO_RSA + haveRSA = 1; +#endif +#ifndef NO_PSK + havePSK = ssl->options.havePSK; +#endif + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + + /* random */ + XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + int 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++]; + + if (b == ID_LEN) { + if ((i - begin) + ID_LEN > helloSz) + return BUFFER_ERROR; + + XMEMCPY(ssl->arrays->sessionID, input + i, ID_LEN); +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + int ret = wc_HmacUpdate(&cookieHmac, input + i - 1, ID_LEN + 1); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ + ssl->arrays->sessionIDSz = ID_LEN; + i += ID_LEN; + 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 WOLFSSL_DTLS + if (ssl->options.dtls) { + int 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; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + byte newCookie[MAX_COOKIE_LEN]; + int ret; + + 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 */ + + if (ssl->options.usingCompression) { + int match = 0; + + while (b--) { + byte comp = input[i++]; + + if (comp == ZLIB_COMPRESSION) + match = 1; + } + + if (!match) { + WOLFSSL_MSG("Not matching compression, turning off"); + ssl->options.usingCompression = 0; /* turn off */ + } + } + else + i += b; /* ignore, since we're not on */ + + *inOutIdx = i; + + /* tls extensions */ + if ((i - begin) < helloSz) { +#ifdef HAVE_TLS_EXTENSIONS + #ifdef HAVE_QSH + QSH_Init(ssl); + #endif + if (TLSX_SupportExtensions(ssl)) { + int ret = 0; +#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, 1, &clSuites))) + return ret; +#ifdef HAVE_STUNNEL + if((ret=SNI_Callback(ssl))) + return ret; +#endif /*HAVE_STUNNEL*/ + + 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) { + ato16(&input[i], &clSuites.hashSigAlgoSz); + i += OPAQUE16_LEN; + + if (OPAQUE16_LEN + clSuites.hashSigAlgoSz > extSz) + return BUFFER_ERROR; + + XMEMCPY(clSuites.hashSigAlgo, &input[i], + min(clSuites.hashSigAlgoSz, HELLO_EXT_SIGALGO_MAX)); + i += clSuites.hashSigAlgoSz; + + if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX) + clSuites.hashSigAlgoSz = HELLO_EXT_SIGALGO_MAX; + } + 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) { + int ret = -1; + WOLFSSL_SESSION* session = GetSession(ssl, + ssl->arrays->masterSecret); + #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 { + if (MatchSuite(ssl, &clSuites) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + return UNSUPPORTED_SUITE; + } + #ifdef SESSION_CERTS + ssl->session = *session; /* restore session certs. */ + #endif + + 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; + } + } + return MatchSuite(ssl, &clSuites); + } + +#if !defined(NO_RSA) || defined(HAVE_ECC) + static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) + { + word16 sz = 0; + int ret = VERIFY_CERT_ERROR; /* start in error state */ + byte hashAlgo = sha_mac; + byte sigAlgo = anonymous_sa_algo; + word32 begin = *inOutIdx; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateVerify", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("CertificateVerify", &ssl->timeoutInfo); + #endif + + + if (IsAtLeastTLSv1_2(ssl)) { + if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size) + return BUFFER_ERROR; + + hashAlgo = input[(*inOutIdx)++]; + sigAlgo = input[(*inOutIdx)++]; + } + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &sz); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + sz > size || sz > ENCRYPT_LEN) + return BUFFER_ERROR; + + /* RSA */ +#ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + byte* out = NULL; + int outLen = 0; + byte doUserRsa = 0; + + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaVerifyCb) + doUserRsa = 1; + #endif /*HAVE_PK_CALLBACKS */ + + WOLFSSL_MSG("Doing RSA peer cert verify"); + + if (doUserRsa) { + #ifdef HAVE_PK_CALLBACKS + outLen = ssl->ctx->RsaVerifyCb(ssl, input + *inOutIdx, sz, + &out, + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaVerifyCtx); + #endif /*HAVE_PK_CALLBACKS */ + } + else { + outLen = wc_RsaSSL_VerifyInline(input + *inOutIdx, sz, &out, + ssl->peerRsaKey); + } + + if (IsAtLeastTLSv1_2(ssl)) { +#ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; +#else + byte encodedSig[MAX_ENCODED_SIG_SZ]; +#endif + word32 sigSz; + byte* digest = ssl->hsHashes->certHashes.sha; + int typeH = SHAh; + int digestSz = SHA_DIGEST_SIZE; + +#ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) + return MEMORY_E; +#endif + + if (sigAlgo != rsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + } + + if (hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = ssl->hsHashes->certHashes.sha256; + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = ssl->hsHashes->certHashes.sha384; + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = ssl->hsHashes->certHashes.sha512; + typeH = SHA512h; + digestSz = SHA512_DIGEST_SIZE; + #endif + } + + sigSz = wc_EncodeSignature(encodedSig, digest, digestSz, typeH); + + if (outLen == (int)sigSz && out && XMEMCMP(out, encodedSig, + min(sigSz, MAX_ENCODED_SIG_SZ)) == 0) + ret = 0; /* verified */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + else { + if (outLen == FINISHED_SZ && out && XMEMCMP(out, + &ssl->hsHashes->certHashes, + FINISHED_SZ) == 0) { + ret = 0; /* verified */ + } + } + } +#endif +#ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + int verify = 0; + int err = -1; + byte* digest = ssl->hsHashes->certHashes.sha; + word32 digestSz = SHA_DIGEST_SIZE; + byte doUserEcc = 0; + + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccVerifyCb) + doUserEcc = 1; + #endif + + WOLFSSL_MSG("Doing ECC peer cert verify"); + + if (IsAtLeastTLSv1_2(ssl)) { + if (sigAlgo != ecc_dsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); + } + + if (hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + digest = ssl->hsHashes->certHashes.sha256; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + digest = ssl->hsHashes->certHashes.sha384; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + digest = ssl->hsHashes->certHashes.sha512; + digestSz = SHA512_DIGEST_SIZE; + #endif + } + } + + if (doUserEcc) { + #ifdef HAVE_PK_CALLBACKS + ret = ssl->ctx->EccVerifyCb(ssl, input + *inOutIdx, sz, digest, + digestSz, + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + &verify, ssl->EccVerifyCtx); + #endif + } + else { + err = wc_ecc_verify_hash(input + *inOutIdx, sz, digest, + digestSz, &verify, ssl->peerEccDsaKey); + } + + if (err == 0 && verify == 1) + ret = 0; /* verified */ + } +#endif + *inOutIdx += sz; + + if (ret == 0) + ssl->options.havePeerVerify = 1; + + return ret; + } +#endif /* !NO_RSA || HAVE_ECC */ + + int SendServerHelloDone(WOLFSSL* ssl) + { + byte *output; + int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int ret; + + #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 (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + return 0; + } + #endif + + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerHelloDone", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz, + ssl->heap); +#endif + ssl->options.serverState = SERVER_HELLODONE_COMPLETE; + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); + } + + +#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 */ + } 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 */ + static 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 */ + + /* 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; + + XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); + c32toa(LowResTimer(), (byte*)&it.timestamp); + + /* 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; + + 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) + XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); + + 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; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + length += DTLS_RECORD_EXTRA; + idx += DTLS_RECORD_EXTRA; + } + #endif + + if (ssl->options.createTicket) { + ret = CreateTicket(ssl); + if (ret != 0) return ret; + } + + length += ssl->session.ticketLen; + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + /* 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; */ + + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) return ret; + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); + } + +#endif /* HAVE_SESSION_TICKET */ + + +#ifdef WOLFSSL_DTLS + 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 = ssl->keys.dtls_state.curSeq; + AddHeaders(output, length, hello_verify_request, ssl); + { + DtlsRecordLayerHeader* rh = (DtlsRecordLayerHeader*)output; + rh->pvMajor = DTLS_MAJOR; + rh->pvMinor = DTLS_MINOR; + } + + output[idx++] = DTLS_MAJOR; + output[idx++] = DTLS_MINOR; + + output[idx++] = cookieSz; + if (cookie == NULL || cookieSz == 0) + return COOKIE_ERROR; + + XMEMCPY(output + idx, cookie, cookieSz); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("HelloVerifyRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output, + sendSz, ssl->heap); +#endif + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); + } +#endif + + static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) + { + #ifdef HAVE_QSH + word16 name; + int qshSz; + #endif + int ret = 0; + word32 length = 0; + byte* out = NULL; + word32 begin = *inOutIdx; + + (void)length; /* shut up compiler warnings */ + (void)out; + (void)input; + (void)size; + (void)begin; + + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_MSG("Client received client keyexchange, attack?"); + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return SSL_FATAL_ERROR; + } + + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Client sending keyexchange at wrong time"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + #ifndef NO_CERTS + if (ssl->options.verifyPeer && ssl->options.failNoCert) { + if (!ssl->options.havePeerCert) { + WOLFSSL_MSG("client didn't present peer cert"); + return NO_PEER_CERT; + } + } + + 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 + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) { + AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); + } + if (ssl->toInfoOn) { + AddLateName("ClientKeyExchange", &ssl->timeoutInfo); + } + #endif + + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + word32 idx = 0; + RsaKey key; + byte doUserRsa = 0; + + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaDecCb) { + doUserRsa = 1; + } + #endif + + ret = wc_InitRsaKey(&key, ssl->heap); + if (ret != 0) { + return ret; + } + + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + return NO_PRIVATE_KEY; + } + + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + &key, ssl->buffers.key->length); + + if (ret == 0) { + length = wc_RsaEncryptSize(&key); + ssl->arrays->preMasterSz = SECRET_LEN; + + if (ssl->options.tls) { + word16 check; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &check); + *inOutIdx += OPAQUE16_LEN; + + if ((word32) check != length) { + WOLFSSL_MSG("RSA explicit size doesn't match"); + wc_FreeRsaKey(&key); + return RSA_PRIVATE_ERROR; + } + } + + if ((*inOutIdx - begin) + length > size) { + WOLFSSL_MSG("RSA message too big"); + wc_FreeRsaKey(&key); + return BUFFER_ERROR; + } + + if (doUserRsa) { + #ifdef HAVE_PK_CALLBACKS + ret = ssl->ctx->RsaDecCb(ssl, + input + *inOutIdx, length, &out, + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->RsaDecCtx); + #endif + } + else { + ret = wc_RsaPrivateDecryptInline(input + *inOutIdx, length, + &out, &key); + } + + *inOutIdx += length; + + if (ret == SECRET_LEN) { + XMEMCPY(ssl->arrays->preMasterSecret, out, SECRET_LEN); + if (ssl->arrays->preMasterSecret[0] != + ssl->chVersion.major + || ssl->arrays->preMasterSecret[1] != + ssl->chVersion.minor) { + ret = PMS_VERSION_ERROR; + } + else + { + #ifdef HAVE_QSH + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + + *inOutIdx, size - *inOutIdx + + begin, 1)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent client ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + ret = MakeMasterSecret(ssl); + } + } + else { + ret = RSA_PRIVATE_ERROR; + } + } + + wc_FreeRsaKey(&key); + } + break; + #endif + #ifndef NO_PSK + case psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 ci_sz; + + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + return PSK_KEY_ERROR; + } + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &ci_sz); + *inOutIdx += OPAQUE16_LEN; + + if (ci_sz > MAX_PSK_ID_LEN) { + return CLIENT_ID_ERROR; + } + + if ((*inOutIdx - begin) + ci_sz > size) { + return BUFFER_ERROR; + } + + XMEMCPY(ssl->arrays->client_identity, input + *inOutIdx, ci_sz); + *inOutIdx += ci_sz; + + ssl->arrays->client_identity[min(ci_sz, MAX_PSK_ID_LEN-1)] = 0; + 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) { + return PSK_KEY_ERROR; + } + + /* 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 + 4; + + #ifdef HAVE_QSH + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + *inOutIdx, + size - *inOutIdx + begin, 1)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent client ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + ret = MakeMasterSecret(ssl); + + /* No further need for PSK */ + ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->psk_keySz = 0; + } + break; + #endif /* NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + word16 cipherLen; + word16 plainLen = sizeof(ssl->arrays->preMasterSecret); + + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + return NO_PRIVATE_KEY; + } + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &cipherLen); + *inOutIdx += OPAQUE16_LEN; + + if (cipherLen > MAX_NTRU_ENCRYPT_SZ) { + return NTRU_KEY_ERROR; + } + + if ((*inOutIdx - begin) + cipherLen > size) { + return BUFFER_ERROR; + } + + if (NTRU_OK != ntru_crypto_ntru_decrypt( + (word16) ssl->buffers.key->length, + ssl->buffers.key->buffer, cipherLen, + input + *inOutIdx, &plainLen, + ssl->arrays->preMasterSecret)) { + return NTRU_DECRYPT_ERROR; + } + + if (plainLen != SECRET_LEN) { + return NTRU_DECRYPT_ERROR; + } + + *inOutIdx += cipherLen; + + #ifdef HAVE_QSH + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + *inOutIdx, + size - *inOutIdx + begin, 1)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent client ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + ssl->arrays->preMasterSz = plainLen; + ret = MakeMasterSecret(ssl); + } + break; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + if ((*inOutIdx - begin) + OPAQUE8_LEN > size) { + return BUFFER_ERROR; + } + + length = input[(*inOutIdx)++]; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_E; + } + wc_ecc_init(ssl->peerEccKey); + } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + wc_ecc_init(ssl->peerEccKey); + } + + if (wc_ecc_import_x963(input + *inOutIdx, length, ssl->peerEccKey)) { + return ECC_PEERKEY_ERROR; + } + + *inOutIdx += length; + ssl->peerEccKeyPresent = 1; + + length = sizeof(ssl->arrays->preMasterSecret); + + if (ssl->specs.static_ecdh) { + ecc_key staticKey; + word32 i = 0; + + wc_ecc_init(&staticKey); + ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &i, + &staticKey, ssl->buffers.key->length); + + if (ret == 0) { + ret = wc_ecc_shared_secret(&staticKey, ssl->peerEccKey, + ssl->arrays->preMasterSecret, &length); + } + + wc_ecc_free(&staticKey); + } + else { + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ret = ECC_MAKEKEY_ERROR; + } else { + ret = wc_ecc_shared_secret(ssl->eccTempKey,ssl->peerEccKey, + ssl->arrays->preMasterSecret, &length); + } + } + + if (ret != 0) { + return ECC_SHARED_ERROR; + } + + ssl->arrays->preMasterSz = length; + #ifdef HAVE_QSH + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + *inOutIdx, + size - *inOutIdx + begin, 1)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent client ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + ret = MakeMasterSecret(ssl); + } + break; + #endif /* HAVE_ECC */ + #ifndef NO_DH + case diffie_hellman_kea: + { + word16 clientPubSz; + DhKey dhKey; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &clientPubSz); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + clientPubSz > size) { + return BUFFER_ERROR; + } + + wc_InitDhKey(&dhKey); + ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret == 0) { + ret = wc_DhAgree(&dhKey, ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_Priv.buffer, + ssl->buffers.serverDH_Priv.length, + input + *inOutIdx, clientPubSz); + } + wc_FreeDhKey(&dhKey); + + *inOutIdx += clientPubSz; + + #ifdef HAVE_QSH + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + *inOutIdx, + size - *inOutIdx + begin, 1)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent client ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + if (ret == 0) { + ret = MakeMasterSecret(ssl); + } + } + break; + #endif /* NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz; + DhKey dhKey; + + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + return PSK_KEY_ERROR; + } + + /* Read in the PSK hint */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &clientSz); + *inOutIdx += OPAQUE16_LEN; + if (clientSz > MAX_PSK_ID_LEN) { + return CLIENT_ID_ERROR; + } + + if ((*inOutIdx - begin) + clientSz > size) { + return BUFFER_ERROR; + } + + XMEMCPY(ssl->arrays->client_identity, + input + *inOutIdx, clientSz); + *inOutIdx += clientSz; + ssl->arrays->client_identity[min(clientSz, MAX_PSK_ID_LEN-1)] = + 0; + + /* Read in the DHE business */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &clientSz); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + clientSz > size) { + return BUFFER_ERROR; + } + + wc_InitDhKey(&dhKey); + ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret == 0) { + ret = wc_DhAgree(&dhKey, pms + OPAQUE16_LEN, + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_Priv.buffer, + ssl->buffers.serverDH_Priv.length, + input + *inOutIdx, clientSz); + } + wc_FreeDhKey(&dhKey); + + *inOutIdx += 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) { + return PSK_KEY_ERROR; + } + + 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; + #ifdef HAVE_QSH + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + *inOutIdx, + size - *inOutIdx + begin, 1)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent client ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + if (ret == 0) + ret = MakeMasterSecret(ssl); + + /* No further need for PSK */ + ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->psk_keySz = 0; + } + break; + #endif /* !NO_DH && !NO_PSK */ + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz; + + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + return PSK_KEY_ERROR; + } + + /* Read in the PSK hint */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { + return BUFFER_ERROR; + } + + ato16(input + *inOutIdx, &clientSz); + *inOutIdx += OPAQUE16_LEN; + if (clientSz > MAX_PSK_ID_LEN) { + return CLIENT_ID_ERROR; + } + + if ((*inOutIdx - begin) + clientSz > size) { + return BUFFER_ERROR; + } + + XMEMCPY(ssl->arrays->client_identity, + input + *inOutIdx, clientSz); + *inOutIdx += clientSz; + ssl->arrays->client_identity[min(clientSz, MAX_PSK_ID_LEN-1)] = + 0; + + /* ECC key */ + if ((*inOutIdx - begin) + OPAQUE8_LEN > size) { + return BUFFER_ERROR; + } + + length = input[(*inOutIdx)++]; + + if ((*inOutIdx - begin) + length > size) { + return BUFFER_ERROR; + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->ctx->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_E; + } + wc_ecc_init(ssl->peerEccKey); + } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + wc_ecc_init(ssl->peerEccKey); + } + + if (wc_ecc_import_x963(input + *inOutIdx, length, + ssl->peerEccKey)) { + return ECC_PEERKEY_ERROR; + } + + *inOutIdx += length; + ssl->peerEccKeyPresent = 1; + + /* Note sizeof preMasterSecret is ENCRYPT_LEN currently 512 */ + length = sizeof(ssl->arrays->preMasterSecret); + + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ret = ECC_MAKEKEY_ERROR; + } else { + ret = wc_ecc_shared_secret(ssl->eccTempKey, + ssl->peerEccKey, ssl->arrays->preMasterSecret + + OPAQUE16_LEN, &length); + } + + if (ret != 0) { + return ECC_SHARED_ERROR; + } + + c16toa((word16)length, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN + length; + 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) { + return PSK_KEY_ERROR; + } + + 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; + + #ifdef HAVE_QSH + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += 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 + *inOutIdx, + size - *inOutIdx + begin, 1)) < 0) { + return qshSz; + } + *inOutIdx += qshSz; + } + else { + /* unknown extension sent client ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + if (ret == 0) + ret = MakeMasterSecret(ssl); + + /* No further need for PSK */ + ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->psk_keySz = 0; + } + break; + #endif /* HAVE_ECC && !NO_PSK */ + default: + { + WOLFSSL_MSG("Bad kea type"); + ret = BAD_KEA_TYPE_E; + } + break; + } + + /* No further need for PMS */ + ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + ssl->arrays->preMasterSz = 0; + + if (ret == 0) { + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + #ifndef NO_CERTS + if (ssl->options.verifyPeer) { + ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); + } + #endif + } + + return ret; + } + +#ifdef HAVE_STUNNEL + static 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 /* HAVE_STUNNEL */ +#endif /* NO_WOLFSSL_SERVER */ +#endif /* WOLFCRYPT_ONLY */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/io.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1181 @@ +/* io.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + + +/* 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 +*/ +#ifndef WOLFSSL_USER_IO + +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + +#ifndef USE_WINDOWS_API + #ifdef WOLFSSL_LWIP + /* lwIP needs to be configured to use sockets API in this mode */ + /* LWIP_SOCKET 1 in lwip/opt.h or in build */ + #include "lwip/sockets.h" + #include <errno.h> + #ifndef LWIP_PROVIDE_ERRNO + #define LWIP_PROVIDE_ERRNO 1 + #endif + #elif defined(FREESCALE_MQX) + #include <posix.h> + #include <rtcs.h> + #elif defined(FREESCALE_KSDK_MQX) + #include <rtcs.h> + #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #if !defined(WOLFSSL_MDK_ARM) + #include "cmsis_os.h" + #include "rl_net.h" + #else + #include <rtl.h> + #endif + #include "errno.h" + #define SOCKET_T int + #elif defined(WOLFSSL_TIRTOS) + #include <sys/socket.h> + #elif defined(FREERTOS_TCP) + #include "FreeRTOS_Sockets.h" + #elif defined(WOLFSSL_IAR_ARM) + /* nothing */ + #elif defined(WOLFSSL_VXWORKS) + #include <sockLib.h> + #include <errno.h> + #else + #include <sys/types.h> + #include <errno.h> + #ifndef EBSNET + #include <unistd.h> + #endif + #include <fcntl.h> + + #if defined(HAVE_RTP_SYS) + #include <socket.h> + #elif defined(EBSNET) + #include "rtipapi.h" /* errno */ + #include "socket.h" + #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) + #include <sys/socket.h> + #include <arpa/inet.h> + #include <netinet/in.h> + #include <netdb.h> + #ifdef __PPU + #include <netex/errno.h> + #else + #include <sys/ioctl.h> + #endif + #endif + #endif +#endif /* USE_WINDOWS_API */ + +#ifdef __sun + #include <sys/filio.h> +#endif + +#ifdef USE_WINDOWS_API + /* no epipe yet */ + #ifndef WSAEPIPE + #define WSAEPIPE -12345 + #endif + #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK + #define SOCKET_EAGAIN WSAETIMEDOUT + #define SOCKET_ECONNRESET WSAECONNRESET + #define SOCKET_EINTR WSAEINTR + #define SOCKET_EPIPE WSAEPIPE + #define SOCKET_ECONNREFUSED WSAENOTCONN + #define SOCKET_ECONNABORTED WSAECONNABORTED + #define close(s) closesocket(s) +#elif defined(__PPU) + #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK + #define SOCKET_EAGAIN SYS_NET_EAGAIN + #define SOCKET_ECONNRESET SYS_NET_ECONNRESET + #define SOCKET_EINTR SYS_NET_EINTR + #define SOCKET_EPIPE SYS_NET_EPIPE + #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED + #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + /* RTCS old I/O doesn't have an EWOULDBLOCK */ + #define SOCKET_EWOULDBLOCK EAGAIN + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED + #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED + #else + #define SOCKET_EWOULDBLOCK NIO_EWOULDBLOCK + #define SOCKET_EAGAIN NIO_EAGAIN + #define SOCKET_ECONNRESET NIO_ECONNRESET + #define SOCKET_EINTR NIO_EINTR + #define SOCKET_EPIPE NIO_EPIPE + #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED + #define SOCKET_ECONNABORTED NIO_ECONNABORTED + #endif +#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) + #if !defined(WOLFSSL_MDK_ARM) + #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK + #define SOCKET_EAGAIN BSD_ERROR_LOCKED + #define SOCKET_ECONNRESET BSD_ERROR_CLOSED + #define SOCKET_EINTR BSD_ERROR + #define SOCKET_EPIPE BSD_ERROR + #define SOCKET_ECONNREFUSED BSD_ERROR + #define SOCKET_ECONNABORTED BSD_ERROR + #else + #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK + #define SOCKET_EAGAIN SCK_ELOCKED + #define SOCKET_ECONNRESET SCK_ECLOSED + #define SOCKET_EINTR SCK_ERROR + #define SOCKET_EPIPE SCK_ERROR + #define SOCKET_ECONNREFUSED SCK_ERROR + #define SOCKET_ECONNABORTED SCK_ERROR + #endif +#elif defined(WOLFSSL_PICOTCP) + #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN + #define SOCKET_EAGAIN PICO_ERR_EAGAIN + #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET + #define SOCKET_EINTR PICO_ERR_EINTR + #define SOCKET_EPIPE PICO_ERR_EIO + #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED + #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN +#elif defined(FREERTOS_TCP) + #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK + #define SOCKET_EAGAIN FREERTOS_EWOULDBLOCK + #define SOCKET_ECONNRESET FREERTOS_SOCKET_ERROR + #define SOCKET_EINTR FREERTOS_SOCKET_ERROR + #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR + #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR + #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR +#else + #define SOCKET_EWOULDBLOCK EWOULDBLOCK + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET ECONNRESET + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED ECONNREFUSED + #define SOCKET_ECONNABORTED ECONNABORTED +#endif /* USE_WINDOWS_API */ + + +#ifdef DEVKITPRO + /* from network.h */ + int net_send(int, const void*, int, unsigned int); + int net_recv(int, void*, int, unsigned int); + #define SEND_FUNCTION net_send + #define RECV_FUNCTION net_recv +#elif defined(WOLFSSL_LWIP) + #define SEND_FUNCTION lwip_send + #define RECV_FUNCTION lwip_recv +#elif defined(WOLFSSL_PICOTCP) + #define SEND_FUNCTION pico_send + #define RECV_FUNCTION pico_recv +#elif defined(FREERTOS_TCP) + #define RECV_FUNCTION(a,b,c,d) FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) + #define SEND_FUNCTION(a,b,c,d) FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) +#else + #define SEND_FUNCTION send + #define RECV_FUNCTION recv +#endif + + +/* Translates return codes returned from + * send() and recv() if need be. + */ +static 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 INLINE int LastError(void) +{ +#ifdef USE_WINDOWS_API + return WSAGetLastError(); +#elif defined(EBSNET) + return xn_getlasterror(); +#else + return errno; +#endif +} + +/* The receive embedded callback + * return : nb bytes read, or error + */ +int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + int recvd; + int err; + int sd = *(int*)ctx; + +#ifdef WOLFSSL_DTLS + { + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + if (wolfSSL_dtls(ssl) + && !wolfSSL_get_using_nonblock(ssl) + && dtls_timeout != 0) { + #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"); + } + } + } +#endif + + recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags); + + recvd = TranslateReturnCode(recvd, sd); + + if (recvd < 0) { + err = LastError(); + WOLFSSL_MSG("Embed Receive error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) { + WOLFSSL_MSG(" Would block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG(" Socket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG(" Connection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG(" Socket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNREFUSED) { + WOLFSSL_MSG(" Connection refused"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else if (err == SOCKET_ECONNABORTED) { + WOLFSSL_MSG(" Connection aborted"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG(" General 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; + int len = sz; + int err; + + sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags); + + sent = TranslateReturnCode(sent, sd); + + if (sent < 0) { + err = LastError(); + WOLFSSL_MSG("Embed Send error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + WOLFSSL_MSG(" Would Block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG(" Connection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG(" Socket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_EPIPE) { + WOLFSSL_MSG(" Socket EPIPE"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG(" General error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return sent; +} + + +#ifdef WOLFSSL_DTLS + +#include <wolfssl/wolfcrypt/sha.h> + +#ifdef USE_WINDOWS_API + #define XSOCKLENT int +#else + #define XSOCKLENT socklen_t +#endif + +#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->fd; + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + struct sockaddr_storage 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, + (struct sockaddr*)&peer, &peerSz); + + recvd = TranslateReturnCode(recvd, sd); + + if (recvd < 0) { + err = LastError(); + WOLFSSL_MSG("Embed Receive From error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (wolfSSL_get_using_nonblock(ssl)) { + WOLFSSL_MSG(" Would block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG(" Socket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG(" Connection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG(" Socket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNREFUSED) { + WOLFSSL_MSG(" Connection refused"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG(" General error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else { + if (dtlsCtx->peer.sz > 0 + && peerSz != (XSOCKLENT)dtlsCtx->peer.sz + && memcmp(&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->fd; + int sent; + int len = sz; + int err; + + WOLFSSL_ENTER("EmbedSendTo()"); + + sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, + (const struct sockaddr*)dtlsCtx->peer.sa, + dtlsCtx->peer.sz); + + sent = TranslateReturnCode(sent, sd); + + if (sent < 0) { + err = LastError(); + WOLFSSL_MSG("Embed Send To error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + WOLFSSL_MSG(" Would Block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG(" Connection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG(" Socket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_EPIPE) { + WOLFSSL_MSG(" Socket EPIPE"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG(" General error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return sent; +} + + +/* 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; + struct sockaddr_storage peer; + XSOCKLENT peerSz = sizeof(peer); + byte digest[SHA_DIGEST_SIZE]; + int ret = 0; + + (void)ctx; + + XMEMSET(&peer, 0, sizeof(peer)); + if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) { + WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie"); + return GEN_COOKIE_E; + } + + ret = wc_ShaHash((byte*)&peer, peerSz, digest); + if (ret != 0) + return ret; + + if (sz > SHA_DIGEST_SIZE) + sz = SHA_DIGEST_SIZE; + XMEMCPY(buf, digest, sz); + + return sz; +} + +#endif /* WOLFSSL_DTLS */ + +#ifdef HAVE_OCSP + +#include <stdlib.h> /* atoi() */ + + +static int Word16ToString(char* d, word16 number) +{ + int i = 0; + + if (d != NULL) { + word16 order = 10000; + word16 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; +} + + +static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) +{ + struct sockaddr_storage addr; + int sockaddr_len = sizeof(struct sockaddr_in); + XMEMSET(&addr, 0, sizeof(addr)); + + #ifdef HAVE_GETADDRINFO + { + struct addrinfo hints; + struct addrinfo* answer = NULL; + char strPort[6]; + + XMEMSET(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (Word16ToString(strPort, port) == 0) { + WOLFSSL_MSG("invalid port number for OCSP responder"); + return -1; + } + + if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { + WOLFSSL_MSG("no addr info for OCSP responder"); + return -1; + } + + sockaddr_len = answer->ai_addrlen; + XMEMCPY(&addr, answer->ai_addr, sockaddr_len); + freeaddrinfo(answer); + + } + #else /* HAVE_GETADDRINFO */ + { + struct hostent* entry = gethostbyname(ip); + struct sockaddr_in *sin = (struct sockaddr_in *)&addr; + + if (entry) { + sin->sin_family = AF_INET; + sin->sin_port = htons(port); + XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], + entry->h_length); + } + else { + WOLFSSL_MSG("no addr info for OCSP responder"); + return -1; + } + } + #endif /* HAVE_GETADDRINFO */ + + *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 + + if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) { + WOLFSSL_MSG("OCSP responder tcp connect failed"); + return -1; + } + + return 0; +} + + +static int build_http_request(const char* domainName, const char* path, + int ocspReqSz, byte* buf, int bufSize) +{ + word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen; + char ocspReqSzStr[6]; + + domainNameLen = (word32)XSTRLEN(domainName); + pathLen = (word32)XSTRLEN(path); + ocspReqSzStrLen = Word16ToString(ocspReqSzStr, (word16)ocspReqSz); + + completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84; + if (completeLen > (word32)bufSize) + return 0; + + XSTRNCPY((char*)buf, "POST ", 5); + buf += 5; + XSTRNCPY((char*)buf, path, pathLen); + buf += pathLen; + XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17); + buf += 17; + XSTRNCPY((char*)buf, domainName, domainNameLen); + buf += domainNameLen; + XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18); + buf += 18; + XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen); + buf += ocspReqSzStrLen; + XSTRNCPY((char*)buf, + "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44); + + return completeLen; +} + + +static int decode_url(const char* url, int urlSz, + char* outName, char* outPath, word16* outPort) +{ + int result = -1; + + if (outName != NULL && outPath != NULL && outPort != NULL) + { + if (url == NULL || urlSz == 0) + { + *outName = 0; + *outPath = 0; + *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) { + outName[i++] = url[cur++]; + } + cur++; /* skip ']' */ + } + else { + while (url[cur] != 0 && url[cur] != ':' && + url[cur] != '/' && cur < urlSz) { + outName[i++] = url[cur++]; + } + } + 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'); + } + *outPort = (word16)bigPort; + } + else + *outPort = 80; + + if (cur < urlSz && url[cur] == '/') { + i = 0; + while (cur < urlSz && url[cur] != 0 && i < 80) { + outPath[i++] = url[cur++]; + } + outPath[i] = 0; + } + else { + outPath[0] = '/'; + outPath[1] = 0; + } + result = 0; + } + } + + return result; +} + + +/* return: >0 OCSP Response Size + * -1 error */ +static int process_http_response(int sfd, byte** respBuf, + byte* httpBuf, int httpBufSz) +{ + int result; + int len = 0; + char *start, *end; + byte *recvBuf = NULL; + int recvBufSz = 0; + enum phr_state { phr_init, phr_http_start, phr_have_length, + phr_have_type, phr_wait_end, phr_http_end + } state = phr_init; + + start = end = NULL; + do { + if (end == NULL) { + result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); + if (result > 0) { + len += result; + start = (char*)httpBuf; + start[len] = 0; + } + else { + WOLFSSL_MSG("process_http_response recv http from peer failed"); + return -1; + } + } + end = XSTRSTR(start, "\r\n"); + + if (end == NULL) { + if (len != 0) + XMEMMOVE(httpBuf, start, len); + start = end = NULL; + } + else if (end == start) { + if (state == phr_wait_end) { + state = phr_http_end; + len -= 2; + start += 2; + } + else { + WOLFSSL_MSG("process_http_response header ended early"); + return -1; + } + } + else { + *end = 0; + len -= (int)(end - start) + 2; + /* adjust len to remove the first line including the /r/n */ + + if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { + start += 9; + if (XSTRNCASECMP(start, "200 OK", 6) != 0 || + state != phr_init) { + WOLFSSL_MSG("process_http_response not OK"); + return -1; + } + state = phr_http_start; + } + else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { + start += 13; + while (*start == ' ' && *start != '\0') start++; + if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) { + WOLFSSL_MSG("process_http_response not ocsp-response"); + return -1; + } + + if (state == phr_http_start) state = phr_have_type; + else if (state == phr_have_length) state = phr_wait_end; + else { + WOLFSSL_MSG("process_http_response type invalid state"); + return -1; + } + } + else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { + start += 15; + while (*start == ' ' && *start != '\0') start++; + recvBufSz = atoi(start); + + if (state == phr_http_start) state = phr_have_length; + else if (state == phr_have_type) state = phr_wait_end; + else { + WOLFSSL_MSG("process_http_response length invalid state"); + return -1; + } + } + + start = end + 2; + } + } while (state != phr_http_end); + + recvBuf = (byte*)XMALLOC(recvBufSz, NULL, DYNAMIC_TYPE_OCSP); + if (recvBuf == NULL) { + WOLFSSL_MSG("process_http_response couldn't create response buffer"); + return -1; + } + + /* copy the remainder of the httpBuf into the respBuf */ + if (len != 0) + XMEMCPY(recvBuf, start, len); + + /* receive the OCSP response data */ + do { + result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0); + if (result > 0) + len += result; + else { + WOLFSSL_MSG("process_http_response recv ocsp from peer failed"); + return -1; + } + } while (len != recvBufSz); + + *respBuf = recvBuf; + return recvBufSz; +} + + +#define SCRATCH_BUFFER_SIZE 512 + +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[80]; + char domainName[80]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (path == NULL) + return -1; + + domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (domainName == NULL) { + XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1; + } +#endif + + (void)ctx; + + 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 (decode_url(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 = SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, NULL, + DYNAMIC_TYPE_OCSP); + + if (httpBuf == NULL) { + WOLFSSL_MSG("Unable to create OCSP response buffer"); + } + else { + httpBufSz = build_http_request(domainName, path, ocspReqSz, + httpBuf, httpBufSz); + + if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) { + WOLFSSL_MSG("OCSP Responder connection failed"); + } + else if ((int)send(sfd, (char*)httpBuf, httpBufSz, 0) != + httpBufSz) { + WOLFSSL_MSG("OCSP http request failed"); + } + else if ((int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != + ocspReqSz) { + WOLFSSL_MSG("OCSP ocsp request failed"); + } + else { + ret = process_http_response(sfd, ocspRespBuf, httpBuf, + SCRATCH_BUFFER_SIZE); + } + + close(sfd); + XFREE(httpBuf, NULL, DYNAMIC_TYPE_OCSP); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +void EmbedOcspRespFree(void* ctx, byte *resp) +{ + (void)ctx; + + if (resp) + XFREE(resp, NULL, DYNAMIC_TYPE_OCSP); +} + + +#endif + +#endif /* WOLFSSL_USER_IO */ + +WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv) +{ + ctx->CBIORecv = CBIORecv; +} + + +WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend) +{ + ctx->CBIOSend = CBIOSend; +} + + +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; +} + +#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; + + 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; + + 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 */ +#endif /* WOLFCRYPT_ONLY */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/keys.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,3093 @@ +/* keys.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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) { + +#ifdef HAVE_ECC + +#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 = 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_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 = 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_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 = 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 = 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_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 = 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_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 = 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_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 = 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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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_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 = 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 = 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_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 = 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 = 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_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 = 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 = 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 = 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 = 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_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 = 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 = 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 = 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_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 = 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 = 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 */ + +#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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 */ + if (ssl->options.cipherSuite0 != ECC_BYTE && + ssl->options.cipherSuite0 != CHACHA_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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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_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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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_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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 + + 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; + ssl->hmac = TLS_hmac; + if (ssl->version.minor >= 2) + ssl->options.tls1_1 = 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; +#ifdef HAVE_CAVIUM + if (devId != NO_CAVIUM_DEVICE) { + if (enc) { + if (wc_Arc4InitCavium(enc->arc4, devId) != 0) { + WOLFSSL_MSG("Arc4InitCavium failed in SetKeys"); + return CAVIUM_INIT_E; + } + } + if (dec) { + if (wc_Arc4InitCavium(dec->arc4, devId) != 0) { + WOLFSSL_MSG("Arc4InitCavium failed in SetKeys"); + return CAVIUM_INIT_E; + } + } + } +#endif + 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 + + +#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 + +#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 + +#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 + +#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 && enc->des3 == NULL) + enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->des3 == NULL) + return MEMORY_E; + if (dec && dec->des3 == NULL) + dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->des3 == NULL) + return MEMORY_E; +#ifdef HAVE_CAVIUM + if (devId != NO_CAVIUM_DEVICE) { + if (enc) { + if (wc_Des3_InitCavium(enc->des3, devId) != 0) { + WOLFSSL_MSG("Des3_InitCavium failed in SetKeys"); + return CAVIUM_INIT_E; + } + } + if (dec) { + if (wc_Des3_InitCavium(dec->des3, devId) != 0) { + WOLFSSL_MSG("Des3_InitCavium failed in SetKeys"); + return CAVIUM_INIT_E; + } + } + } +#endif + 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 + +#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 && enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->aes == NULL) + return MEMORY_E; + if (dec && dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->aes == NULL) + return MEMORY_E; +#ifdef HAVE_CAVIUM + if (devId != NO_CAVIUM_DEVICE) { + if (enc) { + if (wc_AesInitCavium(enc->aes, devId) != 0) { + WOLFSSL_MSG("AesInitCavium failed in SetKeys"); + return CAVIUM_INIT_E; + } + } + if (dec) { + if (wc_AesInitCavium(dec->aes, devId) != 0) { + WOLFSSL_MSG("AesInitCavium failed in SetKeys"); + return CAVIUM_INIT_E; + } + } + } +#endif + 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 + +#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 && enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->aes == NULL) + return MEMORY_E; + if (dec && dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->aes == NULL) + return MEMORY_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, + AESGCM_IMP_IV_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, + AESGCM_IMP_IV_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, + AESGCM_IMP_IV_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, + AESGCM_IMP_IV_SZ); + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif + +#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) { + if (enc && enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->aes == NULL) + return MEMORY_E; + if (dec && dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->aes == NULL) + return MEMORY_E; + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + wc_AesCcmSetKey(enc->aes, keys->client_write_key, specs->key_size); + XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, + AESGCM_IMP_IV_SZ); + } + if (dec) { + wc_AesCcmSetKey(dec->aes, keys->server_write_key, specs->key_size); + XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, + AESGCM_IMP_IV_SZ); + } + } + else { + if (enc) { + wc_AesCcmSetKey(enc->aes, keys->server_write_key, specs->key_size); + XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, + AESGCM_IMP_IV_SZ); + } + if (dec) { + wc_AesCcmSetKey(dec->aes, keys->client_write_key, specs->key_size); + XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, + AESGCM_IMP_IV_SZ); + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif + +#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 + +#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 + +#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 = 0; + if (dec) + keys->peer_sequence_number = 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)heap; + (void)keys; + (void)specs; + (void)devId; + + return 0; +} +#endif /* HAVE_ONE_TIME_AUTH */ + + +/* 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 = NO_CAVIUM_DEVICE, ret, copy = 0; + Ciphers* wc_encrypt = NULL; + Ciphers* wc_decrypt = NULL; + Keys* keys = &ssl->keys; + + (void)copy; + +#ifdef HAVE_CAVIUM + 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: + wc_encrypt = &ssl->encrypt; + break; + + case DECRYPT_SIDE_ONLY: + wc_decrypt = &ssl->decrypt; + break; + + case ENCRYPT_AND_DECRYPT_SIDE: + 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, 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, 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 = keys->sequence_number; + #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 = keys->peer_sequence_number; + #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 + } + ssl->secure_renegotiation->cache_status++; + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + + return ret; +} + + +/* TLS can call too */ +int StoreKeys(WOLFSSL* ssl, const byte* keyData) +{ + 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; + ssl->secure_renegotiation->cache_status++; + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + + if (ssl->specs.cipher_type != aead) { + sz = ssl->specs.hash_size; + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); + 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); + 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); + 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 + + 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 + MD5_DIGEST_SIZE - 1 ) / MD5_DIGEST_SIZE, i; + int ret = 0; + +#ifdef WOLFSSL_SMALL_STACK + byte* shaOutput; + byte* md5Input; + byte* shaInput; + byte* keyData; + Md5* md5; + Sha* sha; +#else + byte shaOutput[SHA_DIGEST_SIZE]; + byte md5Input[SECRET_LEN + SHA_DIGEST_SIZE]; + byte shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN]; + byte keyData[KEY_PREFIX * MD5_DIGEST_SIZE]; + Md5 md5[1]; + Sha sha[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + shaOutput = (byte*)XMALLOC(SHA_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5Input = (byte*)XMALLOC(SECRET_LEN + 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 * MD5_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha = (Sha*)XMALLOC(sizeof(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 + + wc_InitMd5(md5); + + 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); + + wc_ShaUpdate(sha, shaInput, (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) + - KEY_PREFIX + j); + wc_ShaFinal(sha, shaOutput); + + XMEMCPY(md5Input + SECRET_LEN, shaOutput, SHA_DIGEST_SIZE); + wc_Md5Update(md5, md5Input, SECRET_LEN + SHA_DIGEST_SIZE); + wc_Md5Final(md5, keyData + i * MD5_DIGEST_SIZE); + } + + if (ret == 0) + ret = StoreKeys(ssl, keyData); + } + +#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; + Md5* md5; + Sha* sha; +#else + byte shaOutput[SHA_DIGEST_SIZE]; + byte md5Input[ENCRYPT_LEN + SHA_DIGEST_SIZE]; + byte shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN]; + Md5 md5[1]; + 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(SHA_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5Input = (byte*)XMALLOC(ENCRYPT_LEN + SHA_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + shaInput = (byte*)XMALLOC(PREFIX + ENCRYPT_LEN + 2 * RAN_LEN, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha = (Sha*)XMALLOC(sizeof(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 + + wc_InitMd5(md5); + + 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; + wc_ShaUpdate(sha, shaInput, idx); + wc_ShaFinal(sha, shaOutput); + + idx = pmsSz; /* preSz */ + XMEMCPY(md5Input + idx, shaOutput, SHA_DIGEST_SIZE); + idx += SHA_DIGEST_SIZE; + wc_Md5Update(md5, md5Input, idx); + wc_Md5Final(md5, &ssl->arrays->masterSecret[i * 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 + +#ifdef NO_OLD_TLS + return MakeTlsMasterSecret(ssl); +#elif !defined(NO_TLS) + if (ssl->options.tls) return MakeTlsMasterSecret(ssl); +#endif + +#ifndef NO_OLD_TLS + return MakeSslMasterSecret(ssl); +#endif +} + +#endif /* WOLFCRYPT_ONLY */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ocsp.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,415 @@ +/* ocsp.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #include <wolfcrypt/src/misc.c> +#endif + + +int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("InitOCSP"); + + ForceZero(ocsp, sizeof(WOLFSSL_OCSP)); + + if (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) +{ + CertStatus *status, *next; + + WOLFSSL_ENTER("FreeOcspEntry"); + + for (status = entry->status; status; status = next) { + next = status->next; + + if (status->rawOcspResponse) + XFREE(status->rawOcspResponse, NULL, DYNAMIC_TYPE_OCSP_STATUS); + + XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); + } +} + + +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); + XFREE(entry, NULL, DYNAMIC_TYPE_OCSP_ENTRY); + } + + FreeMutex(&ocsp->ocspLock); + + if (dynamic) + XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP); +} + + +static int xstat2err(int stat) +{ + switch (stat) { + case CERT_GOOD: + return 0; + case CERT_REVOKED: + return OCSP_CERT_REVOKED; + default: + return OCSP_CERT_UNKNOWN; + } +} + + +int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer) +{ + 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) == 0) { + 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; +} + +static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request, + OcspEntry** entry) +{ + WOLFSSL_ENTER("GetOcspEntry"); + + *entry = NULL; + + if (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), + NULL, DYNAMIC_TYPE_OCSP_ENTRY); + if (*entry) { + InitOcspEntry(*entry, request); + (*entry)->next = ocsp->ocspList; + ocsp->ocspList = *entry; + } + } + + 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 (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) { + if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE) + && ((*status)->nextDate[0] != 0) + && ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER)) + { + 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); + } + } + } + } + + UnLockMutex(&ocsp->ocspLock); + + return ret; +} + +int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, + buffer* responseBuffer) +{ + OcspEntry* entry = NULL; + CertStatus* status = NULL; + byte* request = NULL; + int requestSz = 2048; + byte* response = NULL; + const char* url = NULL; + int urlSz = 0; + int ret = -1; + +#ifdef WOLFSSL_SMALL_STACK + CertStatus* newStatus; + OcspResponse* ocspResponse; +#else + CertStatus newStatus[1]; + OcspResponse ocspResponse[1]; +#endif + + WOLFSSL_ENTER("CheckOcspRequest"); + + 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; + + 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, NULL, DYNAMIC_TYPE_OCSP); + if (request == NULL) { + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_ERROR; + } + +#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); + + XFREE(request, NULL, DYNAMIC_TYPE_OCSP); + + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + + requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); + + if (ocsp->cm->ocspIOCb) + ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, + request, requestSz, &response); + + if (ret >= 0 && response) { + XMEMSET(newStatus, 0, sizeof(CertStatus)); + + InitOcspResponse(ocspResponse, newStatus, response, ret); + OcspResponseDecode(ocspResponse, ocsp->cm); + + if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) + ret = OCSP_LOOKUP_FAIL; + else { + if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { + if (responseBuffer) { + responseBuffer->buffer = (byte*)XMALLOC(ret, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (responseBuffer->buffer) { + responseBuffer->length = ret; + XMEMCPY(responseBuffer->buffer, response, ret); + } + } + + ret = xstat2err(ocspResponse->status->status); + + if (LockMutex(&ocsp->ocspLock) != 0) + ret = BAD_MUTEX_E; + else { + if (status != NULL) { + if (status->rawOcspResponse) + XFREE(status->rawOcspResponse, NULL, + 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), + NULL, 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, NULL, + DYNAMIC_TYPE_OCSP_STATUS); + + if (status->rawOcspResponse) { + status->rawOcspResponseSz = responseBuffer->length; + XMEMCPY(status->rawOcspResponse, + responseBuffer->buffer, + responseBuffer->length); + } + } + + UnLockMutex(&ocsp->ocspLock); + } + } + else + ret = OCSP_LOOKUP_FAIL; + } + } + else + ret = OCSP_LOOKUP_FAIL; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (response != NULL && ocsp->cm->ocspRespFreeCb) + ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); + + WOLFSSL_LEAVE("CheckOcspRequest", ret); + return ret; +} + + +#else /* HAVE_OCSP */ + + +#ifdef _MSC_VER + /* 4206 warning for blank file */ + #pragma warning(disable: 4206) +#endif + + +#endif /* HAVE_OCSP */ +#endif /* WOLFCRYPT_ONLY */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sniffer.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,3337 @@ +/* sniffer.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #include <wolfcrypt/src/misc.c> +#endif + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + +static INLINE word32 min(word32 a, word32 b) +{ + return a > b ? b : a; +} + +#endif /* WOLFSSL_HAVE_MIN */ + +#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 */ + 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" +}; + + +/* *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 */ +} 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; + + +/* 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 */ +} 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) +{ + LockMutex(&RecoveryMutex); + MissedDataSessions += 1; + UnLockMutex(&RecoveryMutex); +} + + +/* Initialize overall Sniffer */ +void ssl_InitSniffer(void) +{ + wolfSSL_Init(); + InitMutex(&ServerListMutex); + InitMutex(&SessionMutex); + 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 + LockMutex(&srv->namedKeysMutex); + FreeNamedKeyList(srv->namedKeys); + UnLockMutex(&srv->namedKeysMutex); + 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); + } + free(session); +} + + +/* Free overall Sniffer */ +void ssl_FreeSniffer(void) +{ + SnifferServer* srv; + SnifferServer* removeServer; + SnifferSession* session; + SnifferSession* removeSession; + int i; + + LockMutex(&ServerListMutex); + 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); + } + } + + UnLockMutex(&SessionMutex); + UnLockMutex(&ServerListMutex); + + FreeMutex(&RecoveryMutex); + FreeMutex(&SessionMutex); + FreeMutex(&ServerListMutex); + + if (TraceFile) { + TraceOn = 0; + fclose(TraceFile); + TraceFile = NULL; + } + + wolfSSL_Cleanup(); +} + + +/* 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; + 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; +} + + +/* 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); +} + + +/* 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; + + LockMutex(&ServerListMutex); + + sniffer = ServerList; + while (sniffer) { + if (sniffer->server == addr) { + ret = 1; + break; + } + sniffer = sniffer->next; + } + + 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; + + LockMutex(&ServerListMutex); + + sniffer = ServerList; + while (sniffer) { + if (sniffer->port == (int)port) { + ret = 1; + break; + } + sniffer = sniffer->next; + } + + UnLockMutex(&ServerListMutex); + + return ret; +} + + +/* Get SnifferServer from IP and Port */ +static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) +{ + SnifferServer* sniffer; + + 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; + } + + 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); + + 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 */ + 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, fileSz, 1, file); + XFCLOSE(file); + + if (typeKey == SSL_FILETYPE_PEM) { + byte* saveBuf = (byte*)malloc(fileSz); + int saveBufSz = 0; + + ret = -1; + if (saveBuf != NULL) { + saveBufSz = wolfSSL_KeyPemToDer(loadBuf, (int)fileSz, + saveBuf, (int)fileSz, password); + if (saveBufSz < 0) { + saveBufSz = 0; + free(saveBuf); + } + else + ret = 0; + } + + free(loadBuf); + + *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) ? SSL_FILETYPE_PEM : + SSL_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); + XSTRNCPY(namedKey->name, name, sizeof(namedKey->name)); + if (namedKey->nameSz >= sizeof(namedKey->name)) { + namedKey->nameSz = sizeof(namedKey->name) - 1; + namedKey->name[namedKey->nameSz] = '\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_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) { + SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword); + SSL_CTX_set_default_passwd_cb_userdata( + sniffer->ctx, (void*)password); + } + ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type); + if (ret != SSL_SUCCESS) { + SetError(KEY_FILE_STR, error, NULL, 0); + if (isNew) + FreeSnifferServer(sniffer); + return -1; + } + } +#ifdef HAVE_SNI + else { + LockMutex(&sniffer->namedKeysMutex); + namedKey->next = sniffer->namedKeys; + sniffer->namedKeys = namedKey; + 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); + + LockMutex(&ServerListMutex); + ret = SetNamedPrivateKey(name, address, port, keyFile, + typeKey, password, error); + 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); + + LockMutex(&ServerListMutex); + ret = SetNamedPrivateKey(NULL, address, port, keyFile, + typeKey, password, error); + 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; + } + ret = wc_RsaPrivateDecrypt(input, length, + session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key); + + 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(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + ProtocolVersion pv; + byte b; + int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN; + int doResume = 0; + + /* 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; + } + + 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); + 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 == SSL_SUCCESS) { + NamedKey* namedKey; + + if (nameSz >= sizeof(name)) + nameSz = sizeof(name) - 1; + name[nameSz] = 0; + 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, + SSL_FILETYPE_ASN1) != SSL_SUCCESS) { + UnLockMutex(&session->context->namedKeysMutex); + SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + break; + } + else + namedKey = namedKey->next; + } + 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); + 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; + } + + 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(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); + 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; + + 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)) + { + 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, + NULL, 0, + 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) + 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) + 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); + 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 */ + LockMutex(&SessionMutex); + + session->next = SessionTable[row]; + SessionTable[row] = session; + + SessionCount++; + + if ( (SessionCount % HASH_SIZE) == 0) { + TraceFindingStale(); + RemoveStaleSessions(); + } + + 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) + wc_AesSetIV(ssl->decrypt.aes, + curr->data + curr->end - curr->begin + - ssl->specs.block_size + 1); + else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) + wc_Des3_SetIV(ssl->decrypt.des3, + curr->data + curr->end - curr->begin + - ssl->specs.block_size + 1); + } + + 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) { + 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) +{ + (void)error; + + if (data != NULL) { + 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) { + LockMutex(&RecoveryMutex); + *missedData = MissedDataSessions; + UnLockMutex(&RecoveryMutex); + } + + if (reassemblyMem) { + SnifferSession* session; + int i; + + *reassemblyMem = 0; + LockMutex(&SessionMutex); + for (i = 0; i < HASH_SIZE; i++) { + session = SessionTable[i]; + while (session) { + *reassemblyMem += session->cliReassemblyMemory; + *reassemblyMem += session->srvReassemblyMemory; + session = session->next; + } + } + UnLockMutex(&SessionMutex); + } + + ret = wolfSSL_get_session_stats(active, total, peak, maxSessions); + + if (ret == SSL_SUCCESS) + return 0; + else { + SetError(BAD_SESSION_STATS, error, NULL, 0); + return -1; + } +} + + + +#endif /* WOLFSSL_SNIFFER */ +#endif /* WOLFCRYPT_ONLY */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ssl.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,17831 @@ +/* ssl.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #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) + #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(HAVE_WEBSERVER) || \ + defined(WOLFSSL_KEY_GEN) + #include <wolfssl/openssl/evp.h> + /* openssl headers end, wolfssl internal headers next */ + #include <wolfssl/wolfcrypt/wc_encrypt.h> +#endif + +#ifdef OPENSSL_EXTRA + /* openssl headers begin */ + #include <wolfssl/openssl/hmac.h> + #include <wolfssl/openssl/crypto.h> + #include <wolfssl/openssl/des.h> + #include <wolfssl/openssl/bn.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> + /* 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> + #ifdef HAVE_STUNNEL + #include <wolfssl/openssl/ocsp.h> + #endif /* WITH_STUNNEL */ + #ifdef WOLFSSL_SHA512 + #include <wolfssl/wolfcrypt/sha512.h> + #endif +#endif + +#ifndef NO_FILESYSTEM + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) \ + && !defined(EBSNET) + #include <dirent.h> + #include <sys/stat.h> + #endif + #ifdef EBSNET + #include "vfapi.h" + #include "vfile.h" + #endif +#endif /* NO_FILESYSTEM */ + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSSL_HAVE_MIN */ + +#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_HAVE_MAX) +#define WOLFSSL_HAVE_MAX + + static INLINE word32 max(word32 a, word32 b) + { + return a > b ? a : b; + } + +#endif /* WOLFSSL_DTLS && !WOLFSSL_HAVE_MAX */ + + +#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 + + +/* prevent multiple mutex initializations */ +static volatile int initRefCount = 0; +static wolfSSL_Mutex count_mutex; /* init ref count mutex */ + + +WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method) +{ + WOLFSSL_CTX* ctx = NULL; + + WOLFSSL_ENTER("WOLFSSL_CTX_new"); + + if (initRefCount == 0) { + /* user no longer forced to call Init themselves */ + int ret = wolfSSL_Init(); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_Init failed"); + WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0); + return NULL; + } + } + + if (method == NULL) + return ctx; + + ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), 0, DYNAMIC_TYPE_CTX); + if (ctx) { + if (InitSSL_Ctx(ctx, method) < 0) { + WOLFSSL_MSG("Init CTX failed"); + wolfSSL_CTX_free(ctx); + ctx = NULL; + } + } + else { + WOLFSSL_MSG("Alloc CTX failed, method freed"); + XFREE(method, NULL, DYNAMIC_TYPE_METHOD); + } + + WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0); + return ctx; +} + + +void wolfSSL_CTX_free(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("SSL_CTX_free"); + if (ctx) + FreeSSL_Ctx(ctx); + WOLFSSL_LEAVE("SSL_CTX_free", 0); +} + + +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) { + FreeSSL(ssl); + ssl = 0; + } + + WOLFSSL_LEAVE("SSL_new", ret); + return ssl; +} + + +void wolfSSL_free(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_free"); + if (ssl) + FreeSSL(ssl); + WOLFSSL_LEAVE("SSL_free", 0); +} + +#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) +{ + 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); + return 0; +} +#endif + +int wolfSSL_set_fd(WOLFSSL* ssl, int fd) +{ + WOLFSSL_ENTER("SSL_set_fd"); + ssl->rfd = fd; /* not used directly to allow IO callbacks */ + ssl->wfd = fd; + + ssl->IOCB_ReadCtx = &ssl->rfd; + ssl->IOCB_WriteCtx = &ssl->wfd; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; + ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx; + ssl->buffers.dtlsCtx.fd = fd; + } + #endif + + WOLFSSL_LEAVE("SSL_set_fd", SSL_SUCCESS); + return SSL_SUCCESS; +} + + +/** + * Get the name of cipher at priority level passed in. + */ +char* wolfSSL_get_cipher_list(int priority) +{ + const char* const* ciphers = GetCipherNames(); + + if (priority >= GetCipherNamesSize() || priority < 0) { + return 0; + } + + return (char*)ciphers[priority]; +} + + +int wolfSSL_get_ciphers(char* buf, int len) +{ + const char* const* 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]) + 1); /* delimiter */ + totalInc += step; + + /* Check to make sure buf is large enough and will not overflow */ + if (totalInc < len) { + XSTRNCPY(buf, ciphers[i], XSTRLEN(ciphers[i])); + buf += XSTRLEN(ciphers[i]); + + if (i < size - 1) + *buf++ = delim; + else + *buf++ = '\0'; + } + else + return BUFFER_E; + } + return SSL_SUCCESS; +} + + +int wolfSSL_get_fd(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_get_fd"); + WOLFSSL_LEAVE("SSL_get_fd", ssl->rfd); + return ssl->rfd; +} + + +int wolfSSL_get_using_nonblock(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_using_nonblock"); + WOLFSSL_LEAVE("wolfSSL_get_using_nonblock", ssl->options.usingNonblock); + return ssl->options.usingNonblock; +} + + +int wolfSSL_dtls(WOLFSSL* ssl) +{ + return ssl->options.dtls; +} + + +#ifndef WOLFSSL_LEANPSK +void wolfSSL_set_using_nonblock(WOLFSSL* ssl, int nonblock) +{ + WOLFSSL_ENTER("wolfSSL_set_using_nonblock"); + ssl->options.usingNonblock = (nonblock != 0); +} + + +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 SSL_SUCCESS; + } + return SSL_FAILURE; +#else + (void)ssl; + (void)peer; + (void)peerSz; + return SSL_NOT_IMPLEMENTED; +#endif +} + +int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz) +{ +#ifdef WOLFSSL_DTLS + if (peer != NULL && peerSz != NULL + && *peerSz >= ssl->buffers.dtlsCtx.peer.sz) { + *peerSz = ssl->buffers.dtlsCtx.peer.sz; + XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz); + return SSL_SUCCESS; + } + return SSL_FAILURE; +#else + (void)ssl; + (void)peer; + (void)peerSz; + return SSL_NOT_IMPLEMENTED; +#endif +} +#endif /* WOLFSSL_LEANPSK */ + + +/* return underlying connect or accept, SSL_SUCCESS on ok */ +int wolfSSL_negotiate(WOLFSSL* ssl) +{ + int err = SSL_FATAL_ERROR; + + WOLFSSL_ENTER("wolfSSL_negotiate"); +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) + err = wolfSSL_accept(ssl); +#endif + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) + err = wolfSSL_connect(ssl); +#endif + + WOLFSSL_LEAVE("wolfSSL_negotiate", err); + + return err; +} + + +#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(" sizeof arc4 = %lu\n", sizeof(Arc4)); +#endif + printf(" sizeof aes = %lu\n", sizeof(Aes)); +#ifndef NO_DES3 + printf(" sizeof des3 = %lu\n", sizeof(Des3)); +#endif +#ifndef NO_RABBIT + printf(" sizeof rabbit = %lu\n", sizeof(Rabbit)); +#endif +#ifdef HAVE_CHACHA + printf(" sizeof 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(" sizeof MD5 = %lu\n", sizeof(Md5)); +#endif +#ifndef NO_SHA + printf(" sizeof SHA = %lu\n", sizeof(Sha)); +#endif +#ifndef NO_SHA256 + printf(" sizeof SHA256 = %lu\n", sizeof(Sha256)); +#endif +#ifdef WOLFSSL_SHA384 + printf(" sizeof SHA384 = %lu\n", sizeof(Sha384)); +#endif +#ifdef WOLFSSL_SHA384 + printf(" sizeof SHA512 = %lu\n", sizeof(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); +} +#endif + + +#ifndef NO_DH +/* server Diffie-Hellman parameters, SSL_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; + + 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 (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->ctx->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) + XFREE(ssl->buffers.serverDH_G.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH); + + ssl->buffers.weOwnDH = 1; /* SSL owns now */ + ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->ctx->heap, + DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_P.buffer == NULL) + return MEMORY_E; + + ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->ctx->heap, + DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_G.buffer == NULL) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH); + 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 + InitSuites(ssl->suites, ssl->version, 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 SSL_SUCCESS; +} + +/* server ctx Diffie-Hellman parameters, SSL_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; + + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); + + ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap,DYNAMIC_TYPE_DH); + if (ctx->serverDH_P.buffer == NULL) + return MEMORY_E; + + ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap,DYNAMIC_TYPE_DH); + if (ctx->serverDH_G.buffer == NULL) { + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); + 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 SSL_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 SSL_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 SSL_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 HAVE_ERRNO_H + errno = 0; +#endif + + ret = SendData(ssl, data, sz); + + WOLFSSL_LEAVE("SSL_write()", ret); + + if (ret < 0) + return SSL_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_ERRNO_H + errno = 0; +#endif +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + ssl->dtls_expected_rx = max(sz + 100, MAX_MTU); +#endif + +#ifdef HAVE_MAX_FRAGMENT + ret = ReceiveData(ssl, (byte*)data, + min(sz, min(ssl->max_fragment, OUTPUT_RECORD_SIZE)),peek); +#else + ret = ReceiveData(ssl, (byte*)data, min(sz, OUTPUT_RECORD_SIZE), peek); +#endif + + WOLFSSL_LEAVE("wolfSSL_read_internal()", ret); + + if (ret < 0) + return SSL_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()"); + + return wolfSSL_read_internal(ssl, data, sz, FALSE); +} + + +#ifdef HAVE_CAVIUM + +/* let's use cavium, SSL_SUCCESS on ok */ +int wolfSSL_UseCavium(WOLFSSL* ssl, int devId) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->devId = devId; + + return SSL_SUCCESS; +} + + +/* let's use cavium, SSL_SUCCESS on ok */ +int wolfSSL_CTX_UseCavium(WOLFSSL_CTX* ctx, int devId) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->devId = devId; + + return SSL_SUCCESS; +} + + +#endif /* HAVE_CAVIUM */ + +#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); +} + + +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); +} + +#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); +} + + +int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseMaxFragment(&ctx->extensions, mfl); +} + +#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); +} + + +int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseTruncatedHMAC(&ctx->extensions); +} + +#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); +} + + +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); +} + +#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); +} + + +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); +} + +#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_SECP160R1: + case WOLFSSL_ECC_SECP192R1: + case WOLFSSL_ECC_SECP224R1: + case WOLFSSL_ECC_SECP256R1: + case WOLFSSL_ECC_SECP384R1: + case WOLFSSL_ECC_SECP521R1: + break; + + default: + return BAD_FUNC_ARG; + } + + return TLSX_UseSupportedCurve(&ssl->extensions, name); +} + + +int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + switch (name) { + case WOLFSSL_ECC_SECP160R1: + case WOLFSSL_ECC_SECP192R1: + case WOLFSSL_ECC_SECP224R1: + case WOLFSSL_ECC_SECP256R1: + case WOLFSSL_ECC_SECP384R1: + case WOLFSSL_ECC_SECP521R1: + break; + + default: + return BAD_FUNC_ARG; + } + + return TLSX_UseSupportedCurve(&ctx->extensions, name); +} + +#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); +} + +#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 = SSL_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, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (list == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_ERROR; + } + + XMEMSET(list, 0, protocol_name_listSz+1); + XSTRNCPY(list, protocol_name_list, protocol_name_listSz); + + /* 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); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("TLSX_UseALPN failure"); + break; + } + } + + XFREE(list, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + 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, NULL, DYNAMIC_TYPE_TLSX); + if (*list == NULL) + return MEMORY_ERROR; + + XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1); + (*list)[*listSz] = 0; + + return SSL_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); + + if (ret == SSL_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; + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + wc_InitMd5(&ssl->hsHashes->hashMd5); +#endif +#ifndef NO_SHA + ret = wc_InitSha(&ssl->hsHashes->hashSha); + if (ret !=0) + return ret; +#endif +#endif /* NO_OLD_TLS */ +#ifndef NO_SHA256 + ret = wc_InitSha256(&ssl->hsHashes->hashSha256); + if (ret !=0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384(&ssl->hsHashes->hashSha384); + if (ret !=0) + return ret; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512(&ssl->hsHashes->hashSha512); + if (ret !=0) + return ret; +#endif + + ret = wolfSSL_negotiate(ssl); + return ret; +} + +#endif /* HAVE_SECURE_RENEGOTIATION */ + +/* Session Ticket */ +#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET) +/* SSL_SUCCESS on ok */ +int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->ticketEncCb = cb; + + return SSL_SUCCESS; +} + +/* set hint interval, SSL_SUCCESS on ok */ +int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->ticketHint = hint; + + return SSL_SUCCESS; +} + +/* set user context, SSL_SUCCESS on ok */ +int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->ticketEncCtx = userCtx; + + return SSL_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); +} + +int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseSessionTicket(&ctx->extensions, NULL); +} + +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 SSL_SUCCESS; +} + +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz) +{ + if (ssl == NULL || (buf == NULL && bufSz > 0)) + return BAD_FUNC_ARG; + + if (bufSz > 0) + XMEMCPY(ssl->session.ticket, buf, bufSz); + ssl->session.ticketLen = (word16)bufSz; + + return SSL_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 SSL_SUCCESS; +} +#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 + + +/* SSL_SUCCESS on ok */ +int wolfSSL_shutdown(WOLFSSL* ssl) +{ + int ret = SSL_FATAL_ERROR; + byte tmp; + WOLFSSL_ENTER("SSL_shutdown()"); + + if (ssl == NULL) + return SSL_FATAL_ERROR; + + if (ssl->options.quietShutdown) { + WOLFSSL_MSG("quiet shutdown, no close notify sent"); + return SSL_SUCCESS; + } + + /* 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 SSL_FATAL_ERROR; + } + ssl->options.sentNotify = 1; /* don't send close_notify twice */ + if (ssl->options.closeNotify) + ret = SSL_SUCCESS; + else + ret = SSL_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 = SSL_FATAL_ERROR; + } else if (ssl->options.closeNotify) { + ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */ + ret = SSL_SUCCESS; + } + } + + WOLFSSL_LEAVE("SSL_shutdown()", ret); + + return ret; +} + + +int wolfSSL_get_error(WOLFSSL* ssl, int ret) +{ + WOLFSSL_ENTER("SSL_get_error"); + + if (ret > 0) + return SSL_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 SSL_ERROR_WANT_READ; /* convert to OpenSSL type */ + else if (ssl->error == WANT_WRITE) + return SSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */ + else if (ssl->error == ZERO_RETURN) + return SSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */ + return ssl->error; +} + + +/* retrive alert history, SSL_SUCCESS on ok */ +int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h) +{ + if (ssl && h) { + *h = ssl->alert_history; + } + return SSL_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* 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); + } +} + + +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 + +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_ERROR; + } + + 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; + } +} + +WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void) +{ + WOLFSSL_CERT_MANAGER* cm = NULL; + + WOLFSSL_ENTER("wolfSSL_CertManagerNew"); + + cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), 0, + DYNAMIC_TYPE_CERT_MANAGER); + if (cm) { + XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER)); + + if (InitMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("Bad mutex init"); + wolfSSL_CertManagerFree(cm); + return NULL; + } + + #ifdef WOLFSSL_TRUST_PEER_CERT + if (InitMutex(&cm->tpLock) != 0) { + WOLFSSL_MSG("Bad mutex init"); + wolfSSL_CertManagerFree(cm); + return NULL; + } + #endif + } + + return cm; +} + + +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); + #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, NULL); + FreeMutex(&cm->caLock); + + #ifdef WOLFSSL_TRUST_PEER_CERT + FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, NULL); + FreeMutex(&cm->tpLock); + #endif + + XFREE(cm, NULL, 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 (LockMutex(&cm->caLock) != 0) + return BAD_MUTEX_E; + + FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL); + + UnLockMutex(&cm->caLock); + + + return SSL_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 (LockMutex(&cm->tpLock) != 0) + return BAD_MUTEX_E; + + FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, NULL); + + UnLockMutex(&cm->tpLock); + + + return SSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* Return bytes written to buff or < 0 for error */ +int wolfSSL_CertPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz, int type) +{ + int eccKey = 0; + int ret; + DerBuffer* der = NULL; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_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; + } + +#ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) + return MEMORY_E; +#endif + + info->set = 0; + info->ctx = NULL; + info->consumed = 0; + + ret = PemToDer(pem, pemSz, type, &der, NULL, info, &eccKey); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#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; +} + + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + +static const char *EVP_AES_128_CBC = "AES-128-CBC"; +static const char *EVP_AES_192_CBC = "AES-192-CBC"; +static const char *EVP_AES_256_CBC = "AES-256-CBC"; +#if defined(OPENSSL_EXTRA) + static const char *EVP_AES_128_CTR = "AES-128-CTR"; + static const char *EVP_AES_192_CTR = "AES-192-CTR"; + static const char *EVP_AES_256_CTR = "AES-256-CTR"; +#endif +static const int EVP_AES_SIZE = 11; + +static const char *EVP_DES_CBC = "DES-CBC"; +static const int EVP_DES_SIZE = 7; + +static const char *EVP_DES_EDE3_CBC = "DES-EDE3-CBC"; +static const int EVP_DES_EDE3_SIZE = 12; + +#ifdef HAVE_IDEA +static const char *EVP_IDEA_CBC = "IDEA-CBC"; +static const int EVP_IDEA_SIZE = 8; +#endif + +/* our KeyPemToDer password callback, password in userData */ +static 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)); +} + +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ + + +/* Return bytes written to buff or < 0 for error */ +int wolfSSL_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("wolfSSL_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_TMP_BUFFER); + if (info == NULL) + return MEMORY_E; +#endif + + info->set = 0; + info->ctx = NULL; + info->consumed = 0; + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if (pass) { + info->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + if (info->ctx == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + + wolfSSL_CTX_set_default_passwd_cb(info->ctx, OurPasswordCb); + wolfSSL_CTX_set_default_passwd_cb_userdata(info->ctx, (void*)pass); + } +#else + (void)pass; +#endif + + ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey); + + if (info->ctx) + wolfSSL_CTX_free(info->ctx); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#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; +} + +#endif /* !NO_CERTS */ + + + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) + +void wolfSSL_ERR_print_errors_fp(FILE* fp, int err) +{ + char data[WOLFSSL_MAX_ERROR_SZ + 1]; + + WOLFSSL_ENTER("wolfSSL_ERR_print_errors_fp"); + SetErrorString(err, data); + fprintf(fp, "%s", data); +} + +#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 SSL_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 SSL_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 SSL_SUCCESS; +} + + +/* make minVersion the internal equivalent SSL version */ +static int SetMinVersionHelper(byte* minVersion, int version) +{ + 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 + case WOLFSSL_TLSV1_2: + *minVersion = TLSv1_2_MINOR; + break; +#endif + + default: + WOLFSSL_MSG("Bad function argument"); + return BAD_FUNC_ARG; + } + + return SSL_SUCCESS; +} + + +/* Set minimum downgrade version allowed, SSL_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, SSL_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); +} + + +int wolfSSL_SetVersion(WOLFSSL* ssl, int version) +{ + word16 haveRSA = 1; + word16 havePSK = 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 + case WOLFSSL_TLSV1: + ssl->version = MakeTLSv1(); + break; + + case WOLFSSL_TLSV1_1: + ssl->version = MakeTLSv1_1(); + break; + #endif + case WOLFSSL_TLSV1_2: + ssl->version = MakeTLSv1_2(); + 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 + + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, ssl->options.haveDH, + ssl->options.haveNTRU, ssl->options.haveECDSAsig, + ssl->options.haveECC, ssl->options.haveStaticECC, + ssl->options.side); + + return SSL_SUCCESS; +} +#endif /* !leanpsk */ + + +#if !defined(NO_CERTS) || !defined(NO_SESSION_CACHE) + +/* Make a work from the front of random hash */ +static INLINE word32 MakeWordFromHash(const byte* hashID) +{ + return (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 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 = HashSigner(hash); + + if (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; + break; + } + signers = signers->next; + } + 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 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 (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; + } + 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 (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"); + UnLockMutex(&cm->tpLock); + return NULL; + } + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = tp; + break; + } + tp = tp->next; + } + 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 SSL_FAILURE; + } + } + else { + return SSL_FAILURE; + } + + return SSL_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 (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; + } + 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 (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; + } + } + 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), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + 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_TMP_BUFFER); + return ret; + } + WOLFSSL_MSG(" Parsed new trusted peer cert"); + + peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), NULL, + DYNAMIC_TYPE_CERT); + if (peerCert == NULL) { + FreeDecodedCert(cert); + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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(" Already 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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 (LockMutex(&cm->tpLock) == 0) { + peerCert->next = cm->tpTable[row]; + cm->tpTable[row] = peerCert; /* takes ownership */ + UnLockMutex(&cm->tpLock); + } + else { + WOLFSSL_MSG(" Trusted Peer Cert Mutex Lock failed"); + FreeDecodedCert(cert); + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + FreeTrustedPeer(peerCert, cm->heap); + return BAD_MUTEX_E; + } + } + + WOLFSSL_MSG(" Freeing parsed trusted peer cert"); + FreeDecodedCert(cert); + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG(" Freeing der trusted peer cert"); + FreeDer(&der); + WOLFSSL_MSG(" OK Freeing der trusted peer cert"); + WOLFSSL_LEAVE("AddTrustedPeer", ret); + + return SSL_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 = 0; + 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_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(cert, der->buffer, der->length, cm->heap); + ret = ParseCert(cert, CA_TYPE, verify, cm); + WOLFSSL_MSG(" Parsed new CA"); + +#ifndef NO_SKID + subjectHash = cert->extSubjKeyId; +#else + subjectHash = cert->subjectHash; +#endif + + if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) { + WOLFSSL_MSG(" Can'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(" Doesn't have key usage certificate signing"); + ret = NOT_CA_ERROR; + } +#endif + else if (ret == 0 && AlreadySigner(cm, subjectHash)) { + WOLFSSL_MSG(" Already 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; + else { + signer->keyOID = cert->keyOID; + signer->publicKey = cert->publicKey; + signer->pubKeySize = cert->pubKeySize; + signer->nameLen = cert->subjectCNLen; + signer->name = cert->subjectCN; + #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 (LockMutex(&cm->caLock) == 0) { + signer->next = cm->caTable[row]; + cm->caTable[row] = signer; /* takes ownership */ + UnLockMutex(&cm->caLock); + if (cm->caCacheCallback) + cm->caCacheCallback(der->buffer, (int)der->length, type); + } + else { + WOLFSSL_MSG(" CA Mutex Lock failed"); + ret = BAD_MUTEX_E; + FreeSigner(signer, cm->heap); + } + } + } + + WOLFSSL_MSG(" Freeing Parsed CA"); + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + WOLFSSL_MSG(" Freeing der CA"); + FreeDer(pDer); + WOLFSSL_MSG(" OK Freeing der CA"); + + WOLFSSL_LEAVE("AddCA", ret); + + return ret == 0 ? SSL_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 (InitMutex(&session_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex session"); + return BAD_MUTEX_E; + } +#endif + if (InitMutex(&count_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex count"); + return BAD_MUTEX_E; + } + } + + if (LockMutex(&count_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex count"); + return BAD_MUTEX_E; + } + + initRefCount++; + UnLockMutex(&count_mutex); + + return SSL_SUCCESS; +} + + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + +/* SSL_SUCCESS if ok, <= 0 else */ +static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, + int passwordSz, EncryptedInfo* info) +{ + int ret = SSL_BAD_FILE; + +#ifdef WOLFSSL_SMALL_STACK + byte* key = NULL; +#else + byte key[AES_256_KEY_SIZE]; +#endif + + WOLFSSL_ENTER("wolfssl_decrypt_buffer_key"); + + if (der == NULL || password == NULL || info == NULL) { + WOLFSSL_MSG("bad arguments"); + return SSL_FATAL_ERROR; + } + + /* use file's salt for key derivation, hex decode first */ + if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz) != 0) { + WOLFSSL_MSG("base16 decode failed"); + return SSL_FATAL_ERROR; + } + +#ifndef NO_MD5 + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(AES_256_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + WOLFSSL_MSG("memory failure"); + return SSL_FATAL_ERROR; + } +#endif /* WOLFSSL_SMALL_STACK */ + + if ((ret = wolfSSL_EVP_BytesToKey(info->name, "MD5", info->iv, + password, passwordSz, 1, key, NULL)) <= 0) { + WOLFSSL_MSG("bytes to key failure"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_FATAL_ERROR; + } +#else + (void) passwordSz; +#endif /* NO_MD5 */ + +#ifndef NO_DES3 + if (XSTRNCMP(info->name, EVP_DES_CBC, EVP_DES_SIZE) == 0) + ret = wc_Des_CbcDecryptWithKey(der->buffer, der->buffer, der->length, + key, info->iv); + else if (XSTRNCMP(info->name, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0) + ret = wc_Des3_CbcDecryptWithKey(der->buffer, der->buffer, der->length, + key, info->iv); +#endif /* NO_DES3 */ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + if (XSTRNCMP(info->name, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) + ret = wc_AesCbcDecryptWithKey(der->buffer, der->buffer, der->length, + key, AES_128_KEY_SIZE, info->iv); + else if (XSTRNCMP(info->name, EVP_AES_192_CBC, EVP_AES_SIZE) == 0) + ret = wc_AesCbcDecryptWithKey(der->buffer, der->buffer, der->length, + key, AES_192_KEY_SIZE, info->iv); + else if (XSTRNCMP(info->name, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) + ret = wc_AesCbcDecryptWithKey(der->buffer, der->buffer, der->length, + key, AES_256_KEY_SIZE, info->iv); +#endif /* !NO_AES && HAVE_AES_CBC */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret == MP_OKAY) + return SSL_SUCCESS; + else if (ret == SSL_BAD_FILE) + return SSL_BAD_FILE; + + return SSL_FATAL_ERROR; +} +#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) */ + + +#if defined(WOLFSSL_KEY_GEN) && defined(OPENSSL_EXTRA) +static int wolfssl_encrypt_buffer_key(byte* der, word32 derSz, byte* password, + int passwordSz, EncryptedInfo* info) +{ + int ret = SSL_BAD_FILE; + +#ifdef WOLFSSL_SMALL_STACK + byte* key = NULL; +#else + byte key[AES_256_KEY_SIZE]; +#endif + + WOLFSSL_ENTER("wolfssl_encrypt_buffer_key"); + + if (der == NULL || password == NULL || info == NULL || info->ivSz == 0) { + WOLFSSL_MSG("bad arguments"); + return SSL_FATAL_ERROR; + } + +#ifndef NO_MD5 + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(AES_256_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + WOLFSSL_MSG("memory failure"); + return SSL_FATAL_ERROR; + } +#endif /* WOLFSSL_SMALL_STACK */ + + if ((ret = wolfSSL_EVP_BytesToKey(info->name, "MD5", info->iv, + password, passwordSz, 1, key, NULL)) <= 0) { + WOLFSSL_MSG("bytes to key failure"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_FATAL_ERROR; + } +#else + (void) passwordSz; +#endif /* NO_MD5 */ + +#ifndef NO_DES3 + if (XSTRNCMP(info->name, EVP_DES_CBC, EVP_DES_SIZE) == 0) + ret = wc_Des_CbcEncryptWithKey(der, der, derSz, key, info->iv); + else if (XSTRNCMP(info->name, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0) + ret = wc_Des3_CbcEncryptWithKey(der, der, derSz, key, info->iv); +#endif /* NO_DES3 */ +#ifndef NO_AES + if (XSTRNCMP(info->name, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) + ret = wc_AesCbcEncryptWithKey(der, der, derSz, + key, AES_128_KEY_SIZE, info->iv); + else if (XSTRNCMP(info->name, EVP_AES_192_CBC, EVP_AES_SIZE) == 0) + ret = wc_AesCbcEncryptWithKey(der, der, derSz, + key, AES_192_KEY_SIZE, info->iv); + else if (XSTRNCMP(info->name, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) + ret = wc_AesCbcEncryptWithKey(der, der, derSz, + key, AES_256_KEY_SIZE, info->iv); +#endif /* NO_AES */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret == MP_OKAY) + return SSL_SUCCESS; + else if (ret == SSL_BAD_FILE) + return SSL_BAD_FILE; + + return SSL_FATAL_ERROR; +} +#endif /* defined(WOLFSSL_KEY_GEN) */ + + +#ifndef NO_CERTS + +/* 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"); + + switch (type) { + case CA_TYPE: /* same as below */ + case TRUSTED_PEER_TYPE: + case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; + case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; + case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; + case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break; + case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break; + case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; break; + case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; + case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY; break; + default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; + } + + /* find header */ + 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 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 + break; + } + + if (!headerEnd) { + WOLFSSL_MSG("Couldn't find PEM header"); + return SSL_NO_PEM_HEADER; + } + + headerEnd += XSTRLEN(header); + + /* 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 SSL_BAD_FILE; + } + + if (type == PRIVATEKEY_TYPE) { + if (eccKey) + *eccKey = header == BEGIN_EC_PRIV; + } + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + { + /* remove encrypted header if there */ + char encHeader[] = "Proc-Type"; + char* line = XSTRNSTR(headerEnd, encHeader, PEM_LINE_LEN); + if (line) { + char* newline; + char* finish; + char* start = XSTRNSTR(line, "DES", PEM_LINE_LEN); + + if (!start) + start = XSTRNSTR(line, "AES", PEM_LINE_LEN); + + if (!start) return SSL_BAD_FILE; + if (!info) return SSL_BAD_FILE; + + finish = XSTRNSTR(start, ",", PEM_LINE_LEN); + + if (start && finish && (start < finish)) { + newline = XSTRNSTR(finish, "\r", PEM_LINE_LEN); + + if (XMEMCPY(info->name, start, finish - start) == NULL) + return SSL_FATAL_ERROR; + info->name[finish - start] = 0; + if (XMEMCPY(info->iv, finish + 1, sizeof(info->iv)) == NULL) + return SSL_FATAL_ERROR; + + if (!newline) newline = XSTRNSTR(finish, "\n", PEM_LINE_LEN); + if (newline && (newline > finish)) { + info->ivSz = (word32)(newline - (finish + 1)); + info->set = 1; + } + else + return SSL_BAD_FILE; + } + else + return SSL_BAD_FILE; + + /* eat blank line */ + while (*newline == '\r' || *newline == '\n') + newline++; + headerEnd = newline; + + encrypted_key = 1; + } + } +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ + + /* find footer */ + footerEnd = XSTRNSTR((char*)buff, footer, sz); + if (!footerEnd) { + if (info) + info->consumed = longSz; /* No more certs if no footer */ + return SSL_BAD_FILE; + } + + 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] == '\n') + consumedEnd += 2; + else { + if (info) + info->consumed = (long)(consumedEnd+2 - (char*)buff); + return SSL_BAD_FILE; + } + } + + if (info) + info->consumed = (long)(consumedEnd - (char*)buff); + + /* set up der buffer */ + neededSz = (long)(footerEnd - headerEnd); + if (neededSz > sz || neededSz < 0) + return SSL_BAD_FILE; + + 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 SSL_BAD_FILE; + + 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; + } + +#if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) && !defined(NO_PWDBASED) + if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) { + int passwordSz; + #ifdef WOLFSSL_SMALL_STACK + char* password = NULL; + #else + char password[80]; + #endif + + if (!info || !info->ctx || !info->ctx->passwd_cb) + return SSL_BAD_FILE; /* no callback error */ + + #ifdef WOLFSSL_SMALL_STACK + password = (char*)XMALLOC(80, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (password == NULL) + return MEMORY_E; + #endif + passwordSz = info->ctx->passwd_cb(password, sizeof(password), 0, + info->ctx->userdata); + /* convert and adjust length */ + if (header == BEGIN_ENC_PRIV_KEY) { + ret = ToTraditionalEnc(der->buffer, der->length, + password, passwordSz); + #ifdef WOLFSSL_SMALL_STACK + XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + if (ret < 0) { + return ret; + } + + der->length = ret; + } + /* decrypt the key */ + else { + ret = wolfssl_decrypt_buffer_key(der, (byte*)password, + passwordSz, info); + #ifdef WOLFSSL_SMALL_STACK + XFREE(password, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + if (ret != SSL_SUCCESS) { + return ret; + } + } + } +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER || NO_PWDBASED */ + + return 0; +} + + +/* 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 */ +static 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; + int eccKey = 0; + int rsaKey = 0; + void* heap = ctx ? ctx->heap : NULL; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + (void)rsaKey; + + if (used) + *used = sz; /* used bytes default to sz, PEM chain may shorten*/ + + if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM + && format != SSL_FILETYPE_RAW) + return SSL_BAD_FILETYPE; + + if (ctx == NULL && ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) + return MEMORY_E; +#endif + + info->set = 0; + info->ctx = ctx; + info->consumed = 0; + + if (format == SSL_FILETYPE_PEM) { + ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey); + + if (used) + *used = info->consumed; + + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + FreeDer(&der); + return ret; + } + + /* we may have a user cert chain, try to consume */ + if (userChain && 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 = sizeof(staticBuffer); + long consumed = info->consumed; + word32 idx = 0; + int gotOne = 0; + + if ( (sz - consumed) > (int)bufferSz) { + WOLFSSL_MSG("Growing Tmp Chain Buffer"); + bufferSz = (word32)(sz - consumed); + /* will shrink to actual size */ + chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE); + if (chainBuffer == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + FreeDer(&der); + return MEMORY_E; + } + dynamicBuffer = 1; + } + + WOLFSSL_MSG("Processing Cert Chain"); + while (consumed < sz) { + DerBuffer* part = NULL; + info->consumed = 0; + + ret = PemToDer(buff + consumed, sz - consumed, type, &part, + heap, info, &eccKey); + if (ret == 0) { + gotOne = 1; + if ( (idx + part->length) > 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 == SSL_NO_PEM_HEADER && gotOne) { + WOLFSSL_MSG("We got one good PEM so stuff at end ok"); + break; + } + + if (ret < 0) { + WOLFSSL_MSG(" Error in Cert in Chain"); + if (dynamicBuffer) + XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + FreeDer(&der); + 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; + } + } else if (ctx) { + FreeDer(&ctx->certChain); + ret = AllocDer(&ctx->certChain, idx, type, heap); + if (ret == 0) { + XMEMCPY(ctx->certChain->buffer, chainBuffer, idx); + } + } + } + + if (dynamicBuffer) + XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); + + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + FreeDer(&der); + return ret; + } + } + } + else { /* ASN1 (DER) or RAW (NTRU) */ + ret = AllocDer(&der, (word32)sz, type, heap); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + XMEMCPY(der->buffer, buff, sz); + } + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + /* for SSL_FILETYPE_PEM, PemToDer manage the decryption if required */ + if (info->set && (format != SSL_FILETYPE_PEM)) { + /* decrypt */ + int passwordSz; +#ifdef WOLFSSL_SMALL_STACK + char* password = NULL; +#else + char password[80]; +#endif + + #ifdef WOLFSSL_SMALL_STACK + password = (char*)XMALLOC(80, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (password == NULL) + ret = MEMORY_E; + else + #endif + if (!ctx || !ctx->passwd_cb) { + ret = NO_PASSWORD; + } + else { + passwordSz = ctx->passwd_cb(password, sizeof(password), + 0, ctx->userdata); + + /* decrypt the key */ + ret = wolfssl_decrypt_buffer_key(der, (byte*)password, + passwordSz, info); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(password, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + if (ret != SSL_SUCCESS) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + FreeDer(&der); + return ret; + } + } +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* 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); + } + XMEMCPY(&ssl->buffers.certificate, &der, sizeof(der)); + ssl->buffers.weOwnCert = 1; + } + else if (ctx) { + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + XMEMCPY(&ctx->certificate, &der, sizeof(der)); + } + } + else if (type == PRIVATEKEY_TYPE) { + if (ssl) { + /* Make sure previous is free'd */ + if (ssl->buffers.weOwnKey) { + FreeDer(&ssl->buffers.key); + } + XMEMCPY(&ssl->buffers.key, &der, sizeof(der)); + ssl->buffers.weOwnKey = 1; + } + else if (ctx) { + FreeDer(&ctx->privateKey); + XMEMCPY(&ctx->privateKey, &der, sizeof(der)); + } + } + else { + FreeDer(&der); + return SSL_BAD_CERTTYPE; + } + + if (type == PRIVATEKEY_TYPE && format != SSL_FILETYPE_RAW) { + #ifndef NO_RSA + if (!eccKey) { + /* 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_TMP_BUFFER); + if (key == NULL) + return MEMORY_E; + #endif + + ret = wc_InitRsaKey(key, 0); + 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; /* so try it out */ + #endif + if (!eccKey) + ret = SSL_BAD_FILE; + } else { + rsaKey = 1; + (void)rsaKey; /* for no ecc builds */ + } + } + + wc_FreeRsaKey(key); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + if (ret != 0) + return ret; + } + #endif + #ifdef HAVE_ECC + if (!rsaKey) { + /* make sure ECC key can be used */ + word32 idx = 0; + ecc_key key; + + wc_ecc_init(&key); + if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, + der->length) != 0) { + wc_ecc_free(&key); + return SSL_BAD_FILE; + } + wc_ecc_free(&key); + eccKey = 1; + if (ctx) + ctx->haveStaticECC = 1; + if (ssl) + ssl->options.haveStaticECC = 1; + } + #endif /* HAVE_ECC */ + } + else if (type == CERT_TYPE) { + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, + DYNAMIC_TYPE_TMP_BUFFER); + 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"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return SSL_BAD_FILE; + } + switch (cert->signatureOID) { + case CTC_SHAwECDSA: + case CTC_SHA256wECDSA: + case CTC_SHA384wECDSA: + case CTC_SHA512wECDSA: + WOLFSSL_MSG("ECDSA cert signature"); + if (ctx) + ctx->haveECDSAsig = 1; + if (ssl) + ssl->options.haveECDSAsig = 1; + break; + default: + WOLFSSL_MSG("Not ECDSA cert signature"); + break; + } + + #ifdef HAVE_ECC + if (ctx) { + ctx->pkCurveOID = cert->pkCurveOID; + #ifndef WC_STRICT_SIG + if (cert->keyOID == ECDSAk) { + ctx->haveECC = 1; + } + #else + ctx->haveECC = ctx->haveECDSAsig; + #endif + } + if (ssl) { + ssl->pkCurveOID = cert->pkCurveOID; + #ifndef WC_STRICT_SIG + if (cert->keyOID == ECDSAk) { + ssl->options.haveECC = 1; + } + #else + ssl->options.haveECC = ssl->options.haveECDSAsig; + #endif + } + #endif + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + + return SSL_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); + + 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 SSL_SUCCESS; + } + return ret; +} + + +static INLINE WOLFSSL_METHOD* cm_pick_method(void) +{ + #ifndef NO_WOLFSSL_CLIENT + #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + return wolfSSLv3_client_method(); + #else + return wolfTLSv1_2_client_method(); + #endif + #elif !defined(NO_WOLFSSL_SERVER) + #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + return wolfSSLv3_server_method(); + #else + return wolfTLSv1_2_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 = SSL_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) != SSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + return SSL_FATAL_ERROR; + } + } + + return BufferLoadCRL(cm->crl, 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 = SSL_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 SSL_FAILURE; + } + } + 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 SSL_SUCCESS; +} +/* Verify the certificate, SSL_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_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; +#endif + + if (format == SSL_FILETYPE_PEM) { + int eccKey = 0; /* not used */ + #ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; + #else + EncryptedInfo info[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), cm->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) { + XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + #endif + + info->set = 0; + info->ctx = NULL; + info->consumed = 0; + + ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, info, &eccKey); + InitDecodedCert(cert, der->buffer, der->length, cm->heap); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + #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_TMP_BUFFER); +#endif + + return ret == 0 ? SSL_SUCCESS : ret; +} + + +/* turn on OCSP if off and compiled in, set options */ +int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options) +{ + int ret = SSL_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 SSL_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; + #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 SSL_SUCCESS; +} + +/* turn on OCSP Stapling if off and compiled in, set options */ +int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm) +{ + int ret = SSL_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 SSL_FAILURE; + } + } + cm->ocspStaplingEnabled = 1; + + #ifndef WOLFSSL_USER_IO + cm->ocspIOCb = EmbedOcspLookup; + cm->ocspRespFreeCb = EmbedOcspRespFree; + #endif /* WOLFSSL_USER_IO */ + #else + ret = NOT_COMPILED_IN; + #endif + + return ret; +} + + +#ifdef HAVE_OCSP + + +/* check CRL if enabled, SSL_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 SSL_SUCCESS; + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(cert, der, sz, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, 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_TMP_BUFFER); +#endif + + return ret == 0 ? SSL_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 SSL_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 SSL_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_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) + return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm, + ioCb, respFreeCb, ioCbCtx); + 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; +} +#endif + +#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 = ctx ? ctx->heap : NULL; + + (void)crl; + (void)heapHint; + + if (fname == NULL) return SSL_BAD_FILE; + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) return SSL_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 SSL_BAD_FILE; + } + dynamic = 1; + } + else if (sz < 0) { + XFCLOSE(file); + return SSL_BAD_FILE; + } + + if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + ret = SSL_BAD_FILE; + else { + if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) + && format == SSL_FILETYPE_PEM) + ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl); +#ifdef HAVE_CRL + else if (type == CRL_TYPE) + ret = BufferLoadCRL(crl, myBuffer, sz, format); +#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 = SSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_CTX_load_verify_locations"); + (void)path; + + if (ctx == NULL || (file == NULL && path == NULL) ) + return SSL_FAILURE; + + if (file) + ret = ProcessFile(ctx, file, SSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL); + + if (ret == SSL_SUCCESS && path) { + /* try to load each regular file in path */ + #ifdef USE_WINDOWS_API + WIN32_FIND_DATAA FindFileData; + HANDLE hFind; + #ifdef WOLFSSL_SMALL_STACK + char* name = NULL; + #else + char name[MAX_FILENAME_SZ]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (name == NULL) + return MEMORY_E; + #endif + + XMEMSET(name, 0, MAX_FILENAME_SZ); + XSTRNCPY(name, path, MAX_FILENAME_SZ - 4); + XSTRNCAT(name, "\\*", 3); + + hFind = FindFirstFileA(name, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) { + WOLFSSL_MSG("FindFirstFile for path verify locations failed"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BAD_PATH_ERROR; + } + + do { + if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { + XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 3); + XSTRNCAT(name, "\\", 2); + XSTRNCAT(name, FindFileData.cFileName, MAX_FILENAME_SZ/2); + + ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, + NULL, 0, NULL); + } + } while (ret == SSL_SUCCESS && FindNextFileA(hFind, &FindFileData)); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + FindClose(hFind); + #elif !defined(NO_WOLFSSL_DIR) + struct dirent* entry; + DIR* dir = opendir(path); + #ifdef WOLFSSL_SMALL_STACK + char* name = NULL; + #else + char name[MAX_FILENAME_SZ]; + #endif + + if (dir == NULL) { + WOLFSSL_MSG("opendir path verify locations failed"); + return BAD_PATH_ERROR; + } + + #ifdef WOLFSSL_SMALL_STACK + name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (name == NULL) { + closedir(dir); + return MEMORY_E; + } + #endif + + while ( ret == SSL_SUCCESS && (entry = readdir(dir)) != NULL) { + struct stat s; + + XMEMSET(name, 0, MAX_FILENAME_SZ); + XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); + XSTRNCAT(name, "/", 1); + XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); + + if (stat(name, &s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + } else if (s.st_mode & S_IFREG) + ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, + NULL, 0, NULL); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + closedir(dir); + #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 SSL_FAILURE; + } + + return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL); +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* Verify the certificate, SSL_SUCCESS for ok, < 0 for error */ +int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, + int format) +{ + int ret = SSL_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 SSL_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 SSL_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 SSL_BAD_FILE; + } + dynamic = 1; + } + + if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + ret = SSL_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 = SSL_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; +} + + + + +int wolfSSL_CTX_check_private_key(WOLFSSL_CTX* ctx) +{ + /* TODO: check private against public for RSA match */ + (void)ctx; + WOLFSSL_ENTER("SSL_CTX_check_private_key"); + return SSL_SUCCESS; +} + + +#ifdef HAVE_CRL + + +/* check CRL if enabled, SSL_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 SSL_SUCCESS; + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(cert, der, sz, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, 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_TMP_BUFFER); +#endif + + return ret == 0 ? SSL_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 SSL_SUCCESS; +} + + +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) != SSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + return SSL_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; +} + + +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; +} + + +#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 SSL_FAILURE; + + if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL) == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_FAILURE; +} + +#endif /* WOLFSSL_DER_LOAD */ + + +#ifdef WOLFSSL_CERT_GEN + +/* load pem cert from file into der buffer, return der size or error */ +int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) +{ +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; + byte staticBuffer[1]; /* force XMALLOC */ +#else + EncryptedInfo info[1]; + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* fileBuf = staticBuffer; + int dynamic = 0; + int ret = 0; + int ecc = 0; + long sz = 0; + XFILE file = XFOPEN(fileName, "rb"); + DerBuffer* converted = NULL; + + WOLFSSL_ENTER("wolfSSL_PemCertToDer"); + + if (file == XBADFILE) { + ret = SSL_BAD_FILE; + } + else { + XFSEEK(file, 0, XSEEK_END); + sz = XFTELL(file); + XREWIND(file); + + if (sz < 0) { + ret = SSL_BAD_FILE; + } + else if (sz > (long)sizeof(staticBuffer)) { + fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE); + if (fileBuf == NULL) + ret = MEMORY_E; + else + dynamic = 1; + } + + if (ret == 0) { + if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) { + ret = SSL_BAD_FILE; + } + else { + #ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) + ret = MEMORY_E; + else + #endif + { + ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, + 0, info, &ecc); + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #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, 0, DYNAMIC_TYPE_FILE); + } + + return ret; +} + +#endif /* WOLFSSL_CERT_GEN */ + +#ifdef WOLFSSL_CERT_EXT +#ifndef NO_FILESYSTEM +/* load pem public key from file into der buffer, return der size or error */ +int wolfSSL_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("wolfSSL_PemPubKeyToDer"); + + if (file == XBADFILE) { + ret = SSL_BAD_FILE; + } + else { + XFSEEK(file, 0, XSEEK_END); + sz = XFTELL(file); + XREWIND(file); + + if (sz < 0) { + ret = SSL_BAD_FILE; + } + else if (sz > (long)sizeof(staticBuffer)) { + fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE); + if (fileBuf == NULL) + ret = MEMORY_E; + else + dynamic = 1; + } + if (ret == 0) { + if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) + ret = SSL_BAD_FILE; + else + ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted, + 0, NULL, NULL); + + 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, 0, DYNAMIC_TYPE_FILE); + } + + return ret; +} +#endif /* NO_FILESYSTEM */ + +/* Return bytes written to buff or < 0 for error */ +int wolfSSL_PubKeyPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz) +{ + int ret; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wolfSSL_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 */ + +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) == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_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) + == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_FAILURE; +} + + +/* get cert chaining depth using ssl struct */ +long wolfSSL_get_verify_depth(WOLFSSL* ssl) +{ + if(ssl == NULL) { + return BAD_FUNC_ARG; + } + return MAX_CHAIN_DEPTH; +} + + +/* get cert chaining depth using ctx struct */ +long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) +{ + if(ctx == NULL) { + return BAD_FUNC_ARG; + } + return MAX_CHAIN_DEPTH; +} + + +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, SSL_FILETYPE_PEM,CERT_TYPE,NULL,1, NULL) + == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_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 SSL_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 SSL_BAD_FILE; + } + dynamic = 1; + } + else if (sz < 0) { + XFCLOSE(file); + return SSL_BAD_FILE; + } + + if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + ret = SSL_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 */ + + +#ifdef OPENSSL_EXTRA +/* put SSL type in extra for now, not very common */ + +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) == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_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) == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_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, SSL_FILETYPE_PEM, CERT_TYPE, + ssl, 1, NULL) == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_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 SSL_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 SSL_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 /* OPENSSL_EXTRA */ + +#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 SSL_FAILURE; + + if (ProcessFile(ctx, file, SSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL) + == SSL_SUCCESS) { + ctx->haveNTRU = 1; + return SSL_SUCCESS; + } + + return SSL_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 & SSL_VERIFY_PEER) { + ctx->verifyPeer = 1; + ctx->verifyNone = 0; /* in case previously set */ + } + + if (mode == SSL_VERIFY_NONE) { + ctx->verifyNone = 1; + ctx->verifyPeer = 0; /* in case previously set */ + } + + if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + ctx->failNoCert = 1; + + if (mode & SSL_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 & SSL_VERIFY_PEER) { + ssl->options.verifyPeer = 1; + ssl->options.verifyNone = 0; /* in case previously set */ + } + + if (mode == SSL_VERIFY_NONE) { + ssl->options.verifyNone = 1; + ssl->options.verifyPeer = 0; /* in case previously set */ + } + + if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + ssl->options.failNoCert = 1; + + if (mode & SSL_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 /* PERSISTE_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); + + return NULL; +} + + +int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("SSL_set_session"); + if (session) + return SetSession(ssl, session); + + return SSL_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 + SSL_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) != SSL_SUCCESS) { + 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); + } + + return SSL_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 (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 + + UnLockMutex(&session_mutex); + + WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", SSL_SUCCESS); + + return SSL_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 (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 + + UnLockMutex(&session_mutex); + + WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", SSL_SUCCESS); + + return SSL_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 = SSL_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 SSL_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 (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 */ + + 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 = SSL_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 SSL_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 (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 */ + + 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() == SSL_SUCCESS) + return SSL_SUCCESS; + else + return SSL_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 SSL_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 SSL_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 == SSL_SESS_CACHE_OFF) + ctx->sessionCacheOff = 1; + + if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR) + ctx->sessionCacheFlushOff = 1; + + return SSL_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 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 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 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 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 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 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 INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, + void* mem, int sz) +{ + int realSz; + int ret = SSL_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 = SSL_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 SSL_BAD_FILE; + } + + if (LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("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 == SSL_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); + } + + 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 = SSL_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 SSL_BAD_FILE; + } + + XFSEEK(file, 0, XSEEK_END); + memSz = (int)XFTELL(file); + XREWIND(file); + + if (memSz <= 0) { + WOLFSSL_MSG("Bad file size"); + XFCLOSE(file); + return SSL_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 != SSL_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 = SSL_SUCCESS; + + WOLFSSL_ENTER("CM_MemSaveCertCache"); + + if (LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("LockMutex on caLock failed"); + return BAD_MUTEX_E; + } + + ret = DoMemSaveCertCache(cm, mem, sz); + if (ret == SSL_SUCCESS) + *used = GetCertCacheMemSize(cm); + + UnLockMutex(&cm->caLock); + + return ret; +} + + +/* Restore cert cache from memory */ +int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz) +{ + int ret = SSL_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 (LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("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; + } + + 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 (LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("LockMutex on caLock failed"); + return BAD_MUTEX_E; + } + + sz = GetCertCacheMemSize(cm); + + 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 SSL_FAILURE; + } + XMEMSET(ctx->suites, 0, sizeof(Suites)); + } + + return (SetCipherList(ctx->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; +} + + +int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) +{ + WOLFSSL_ENTER("wolfSSL_set_cipher_list"); + return (SetCipherList(ssl->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; +} + + +#ifndef WOLFSSL_LEANPSK +#ifdef WOLFSSL_DTLS + +int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl) +{ + (void)ssl; + + return ssl->dtls_timeout; +} + + +/* user may need to alter init dtls recv timeout, SSL_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 SSL_SUCCESS; +} + + +/* user may need to alter max dtls recv timeout, SSL_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 SSL_SUCCESS; +} + + +int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) +{ + int result = SSL_SUCCESS; + + DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap); + ssl->dtls_msg_list = NULL; + if (DtlsPoolTimeout(ssl) < 0 || DtlsPoolSend(ssl) < 0) { + result = SSL_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) +{ + 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) + 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 0; +} + +#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ + + +/* client only parts */ +#ifndef NO_WOLFSSL_CLIENT + + #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + WOLFSSL_METHOD* wolfSSLv3_client_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + 0, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("SSLv3_client_method"); + if (method) + InitSSL_Method(method, MakeSSLv3()); + return method; + } + #endif + + #ifdef WOLFSSL_DTLS + + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_client_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + 0, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("DTLSv1_client_method"); + if (method) + InitSSL_Method(method, MakeDTLSv1()); + return method; + } + #endif /* NO_OLD_TLS */ + + WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + 0, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("DTLSv1_2_client_method"); + if (method) + InitSSL_Method(method, MakeDTLSv1_2()); + return method; + } + #endif + + + /* please see note at top of README if you get an error from connect */ + int wolfSSL_connect(WOLFSSL* ssl) + { + int neededState; + + WOLFSSL_ENTER("SSL_connect()"); + + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + + if (ssl->options.side != WOLFSSL_CLIENT_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return SSL_FATAL_ERROR; + } + + #ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + + if (DtlsPoolInit(ssl) != 0) { + ssl->error = MEMORY_ERROR; + WOLFSSL_ERROR(ssl->error); + return SSL_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.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 SSL_FATAL_ERROR; + } + } + + switch (ssl->options.connectState) { + + case CONNECT_BEGIN : + /* always send client hello first */ + if ( (ssl->error = SendClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.connectState = CLIENT_HELLO_SENT; + WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + + 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 (ssl->options.dtls) + neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; + #endif + /* get response */ + while (ssl->options.serverState < neededState) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + else if (neededState == SERVER_FINISHED_COMPLETE) + if (!ssl->options.resuming) { + if (!ssl->options.dtls) + neededState = SERVER_HELLODONE_COMPLETE; + else + neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; + } + } + + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + + case HELLO_AGAIN : + if (ssl->options.certOnly) + return SSL_SUCCESS; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + /* re-init hashes, exclude first hello and verify request */ +#ifndef NO_OLD_TLS + wc_InitMd5(&ssl->hsHashes->hashMd5); + if ( (ssl->error = wc_InitSha(&ssl->hsHashes->hashSha)) + != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } +#endif + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + if ( (ssl->error = wc_InitSha256( + &ssl->hsHashes->hashSha256)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + #endif + #ifdef WOLFSSL_SHA384 + if ( (ssl->error = wc_InitSha384( + &ssl->hsHashes->hashSha384)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + #endif + #ifdef WOLFSSL_SHA512 + if ( (ssl->error = wc_InitSha512( + &ssl->hsHashes->hashSha512)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + #endif + } + if ( (ssl->error = SendClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + #endif + + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + + case HELLO_AGAIN_REPLY : + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + 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 SSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + else 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"); + + case FIRST_REPLY_DONE : + #ifndef NO_CERTS + if (ssl->options.sendVerify) { + if ( (ssl->error = SendCertificate(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate"); + } + + #endif + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + + case FIRST_REPLY_FIRST : + if (!ssl->options.resuming) { + if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: client key exchange"); + } + + ssl->options.connectState = FIRST_REPLY_SECOND; + WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + + case FIRST_REPLY_SECOND : + #ifndef NO_CERTS + if (ssl->options.sendVerify) { + if ( (ssl->error = SendCertificateVerify(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate verify"); + } + #endif + ssl->options.connectState = FIRST_REPLY_THIRD; + WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + + case FIRST_REPLY_THIRD : + if ( (ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: change cipher spec"); + ssl->options.connectState = FIRST_REPLY_FOURTH; + WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + + case FIRST_REPLY_FOURTH : + if ( (ssl->error = SendFinished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: finished"); + ssl->options.connectState = FINISHED_DONE; + WOLFSSL_MSG("connect state: FINISHED_DONE"); + + case FINISHED_DONE : + /* get response */ + while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.connectState = SECOND_REPLY_DONE; + WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); + + 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 SSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + + if (!ssl->options.dtls) { + FreeHandshakeResources(ssl); + } +#ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } +#endif /* WOLFSSL_DTLS */ + + WOLFSSL_LEAVE("SSL_connect()", SSL_SUCCESS); + return SSL_SUCCESS; + + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return SSL_FATAL_ERROR; /* unknown connect state */ + } + } + +#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_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + 0, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("SSLv3_server_method"); + 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(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + 0, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("DTLSv1_server_method"); + if (method) { + InitSSL_Method(method, MakeDTLSv1()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #endif /* NO_OLD_TLS */ + + WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + 0, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("DTLSv1_2_server_method"); + if (method) { + InitSSL_Method(method, MakeDTLSv1_2()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #endif + + + int wolfSSL_accept(WOLFSSL* ssl) + { + word16 havePSK = 0; + word16 haveAnon = 0; + 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; + + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return SSL_FATAL_ERROR; + } + + #ifndef NO_CERTS + /* in case used set_accept_state after init */ + if (!havePSK && !haveAnon && + (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer || + !ssl->buffers.key || + !ssl->buffers.key->buffer)) { + WOLFSSL_MSG("accept error: don't have server cert and key"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return SSL_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; + + if (DtlsPoolInit(ssl) != 0) { + ssl->error = MEMORY_ERROR; + WOLFSSL_ERROR(ssl->error); + return SSL_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 SSL_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 SSL_FATAL_ERROR; + } + ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; + WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + + case ACCEPT_CLIENT_HELLO_DONE : + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + + case ACCEPT_FIRST_REPLY_DONE : + if ( (ssl->error = SendServerHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_SENT; + WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + + case SERVER_HELLO_SENT : + #ifndef NO_CERTS + if (!ssl->options.resuming) + if ( (ssl->error = SendCertificate(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + #endif + ssl->options.acceptState = CERT_SENT; + WOLFSSL_MSG("accept state CERT_SENT"); + + case CERT_SENT : + #ifndef NO_CERTS + if (!ssl->options.resuming) + if ( (ssl->error = SendCertificateStatus(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + #endif + ssl->options.acceptState = CERT_STATUS_SENT; + WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + + case CERT_STATUS_SENT : + if (!ssl->options.resuming) + if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.acceptState = KEY_EXCHANGE_SENT; + WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT"); + + 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 SSL_FATAL_ERROR; + } + #endif + ssl->options.acceptState = CERT_REQ_SENT; + WOLFSSL_MSG("accept state CERT_REQ_SENT"); + + case CERT_REQ_SENT : + if (!ssl->options.resuming) + if ( (ssl->error = SendServerHelloDone(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_DONE; + WOLFSSL_MSG("accept state SERVER_HELLO_DONE"); + + 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 SSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + + case ACCEPT_SECOND_REPLY_DONE : +#ifdef HAVE_SESSION_TICKET + if (ssl->options.createTicket) { + if ( (ssl->error = SendTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + + case TICKET_SENT: + if ( (ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.acceptState = CHANGE_CIPHER_SENT; + WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT"); + + case CHANGE_CIPHER_SENT : + if ( (ssl->error = SendFinished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + + 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 SSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + + 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 SSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + + if (!ssl->options.dtls) { + FreeHandshakeResources(ssl); + } +#ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } +#endif /* WOLFSSL_DTLS */ + + WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS); + return SSL_SUCCESS; + + default : + WOLFSSL_MSG("Unknown accept state ERROR"); + return SSL_FATAL_ERROR; + } + } + +#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 SSL_SUCCESS; +} + +#endif /* NO_HANDSHAKE_DONE_CB */ + + +int wolfSSL_Cleanup(void) +{ + int ret = SSL_SUCCESS; + int release = 0; + + WOLFSSL_ENTER("wolfSSL_Cleanup"); + + if (initRefCount == 0) + return ret; /* possibly no init yet, but not failure either way */ + + if (LockMutex(&count_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex count"); + return BAD_MUTEX_E; + } + + release = initRefCount-- == 1; + if (initRefCount < 0) + initRefCount = 0; + + UnLockMutex(&count_mutex); + + if (!release) + return ret; + +#ifndef NO_SESSION_CACHE + if (FreeMutex(&session_mutex) != 0) + ret = BAD_MUTEX_E; +#endif + if (FreeMutex(&count_mutex) != 0) + ret = BAD_MUTEX_E; + +#if defined(HAVE_ECC) && defined(FP_ECC) + wc_ecc_fp_free(); +#endif + + return ret; +} + + +#ifndef NO_SESSION_CACHE + + +/* some session IDs aren't random after all, let's make them random */ +static INLINE word32 HashSession(const byte* sessionID, word32 len, int* error) +{ + byte digest[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; + + ssl->timeout = to; + + return SSL_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; + + ctx->timeout = to; + + return SSL_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->options.side == WOLFSSL_SERVER_END) + return NULL; + + len = min(SERVER_ID_LEN, (word32)len); + row = HashSession(id, len, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + return NULL; + } + + if (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"); + } + } + + UnLockMutex(&session_mutex); + + return ret; +} + +#endif /* NO_CLIENT_CACHE */ + + +WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret) +{ + WOLFSSL_SESSION* ret = 0; + const byte* id = NULL; + word32 row; + int idx; + int count; + int error = 0; + + 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; + + row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + return NULL; + } + + if (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; + if (masterSecret) + XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN); + } 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"); + } + } + + UnLockMutex(&session_mutex); + + return ret; +} + + +int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + if (ssl->options.sessionCacheOff) + return SSL_FAILURE; + + if (LowResTimer() < (session->bornOn + session->timeout)) { + ssl->session = *session; + ssl->options.resuming = 1; + +#ifdef SESSION_CERTS + ssl->version = session->version; + ssl->options.cipherSuite0 = session->cipherSuite0; + ssl->options.cipherSuite = session->cipherSuite; +#endif + + return SSL_SUCCESS; + } + return SSL_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, idx; + int error = 0; + + 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 + + row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + return error; + } + + if (LockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + + idx = SessionCache[row].nextIdx++; +#ifdef SESSION_INDEX + ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; +#endif + + XMEMCPY(SessionCache[row].Sessions[idx].masterSecret, + ssl->arrays->masterSecret, SECRET_LEN); + XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID, + ID_LEN); + SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz; + + SessionCache[row].Sessions[idx].timeout = ssl->timeout; + SessionCache[row].Sessions[idx].bornOn = LowResTimer(); + +#ifdef HAVE_SESSION_TICKET + SessionCache[row].Sessions[idx].ticketLen = ssl->session.ticketLen; + XMEMCPY(SessionCache[row].Sessions[idx].ticket, + ssl->session.ticket, ssl->session.ticketLen); +#endif + +#ifdef SESSION_CERTS + SessionCache[row].Sessions[idx].chain.count = ssl->session.chain.count; + XMEMCPY(SessionCache[row].Sessions[idx].chain.certs, + ssl->session.chain.certs, sizeof(x509_buffer) * MAX_CHAIN_DEPTH); + + SessionCache[row].Sessions[idx].version = ssl->version; + SessionCache[row].Sessions[idx].cipherSuite0 = ssl->options.cipherSuite0; + SessionCache[row].Sessions[idx].cipherSuite = ssl->options.cipherSuite; +#endif /* SESSION_CERTS */ + + SessionCache[row].totalCount++; + if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) + SessionCache[row].nextIdx = 0; + +#ifndef NO_CLIENT_CACHE + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) { + word32 clientRow, clientIdx; + + WOLFSSL_MSG("Adding client cache entry"); + + SessionCache[row].Sessions[idx].idLen = ssl->session.idLen; + XMEMCPY(SessionCache[row].Sessions[idx].serverID, ssl->session.serverID, + ssl->session.idLen); + + 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 + SessionCache[row].Sessions[idx].idLen = 0; +#endif /* NO_CLIENT_CACHE */ + +#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) + if (error == 0) { + word32 active = 0; + + error = get_locked_session_stats(&active, NULL, NULL); + if (error == SSL_SUCCESS) { + error = 0; /* back to this function ok */ + + if (active > PeakSessions) + PeakSessions = active; + } + } +#endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */ + + if (UnLockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + + 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 = SSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex"); + + row = idx >> SESSIDX_ROW_SHIFT; + col = idx & SESSIDX_IDX_MASK; + + if (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 = SSL_SUCCESS; + } + + if (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, SSL_SUCCESS on ok */ +static int get_locked_session_stats(word32* active, word32* total, word32* peak) +{ + int result = SSL_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 SSL_SUCCESS on ok */ +int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, + word32* maxSessions) +{ + int result = SSL_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 (LockMutex(&session_mutex) != 0) { + return BAD_MUTEX_E; + } + + result = get_locked_session_stats(active, total, peak); + + if (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 + + /* SSL_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 != SSL_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) +{ + (void)ssl; + (void)masterSecret; + + 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->buffers.domainName.buffer) + XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); + + ssl->buffers.domainName.length = (word32)XSTRLEN(dn) + 1; + ssl->buffers.domainName.buffer = (byte*) XMALLOC( + ssl->buffers.domainName.length, ssl->heap, DYNAMIC_TYPE_DOMAIN); + + if (ssl->buffers.domainName.buffer) { + XSTRNCPY((char*)ssl->buffers.domainName.buffer, dn, + ssl->buffers.domainName.length); + return SSL_SUCCESS; + } + else { + ssl->error = MEMORY_ERROR; + return SSL_FAILURE; + } +} + + +/* turn on wolfSSL zlib compression + returns SSL_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 SSL_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 = SSL_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); + } + 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, ssl); + (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; + + WOLFSSL_ENTER("SSL_set_psk_client_callback"); + ssl->options.havePSK = 1; + ssl->options.client_psk_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + InitSuites(ssl->suites, ssl->version, 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; + + WOLFSSL_ENTER("SSL_set_psk_server_callback"); + ssl->options.havePSK = 1; + ssl->options.server_psk_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + InitSuites(ssl->suites, ssl->version, 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, MAX_PSK_ID_LEN); + ctx->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + } + return SSL_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 SSL_FAILURE; + + if (hint == 0) + ssl->arrays->server_hint[0] = 0; + else { + XSTRNCPY(ssl->arrays->server_hint, hint, MAX_PSK_ID_LEN); + ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + } + return SSL_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 SSL_FAILURE; + + ctx->haveAnon = 1; + + return SSL_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 == SSL_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 == SSL_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(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz) + { + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer"); + return ProcessBuffer(ctx, in, sz, SSL_FILETYPE_PEM, CERT_TYPE, NULL, + NULL, 1); + } + + +#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_TMP_BUFFER); + g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (p == NULL || g == NULL) { + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + #endif + + if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM) + ret = SSL_BAD_FILETYPE; + else { + if (format == SSL_FILETYPE_PEM) { + FreeDer(&der); + ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, + NULL, NULL); + } + + if (ret == 0) { + if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0) + ret = SSL_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_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } + + + /* server Diffie-Hellman parameters, SSL_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, SSL_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(WOLFSSL* ssl, + const unsigned char* in, long sz) + { + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer"); + return ProcessBuffer(ssl->ctx, in, sz, SSL_FILETYPE_PEM, CERT_TYPE, + ssl, NULL, 1); + } + + + /* unload any certs or keys that SSL owns, leave CTX as is + SSL_SUCCESS on ok */ + int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl) + { + if (ssl == NULL) { + WOLFSSL_MSG("Null function arg"); + return BAD_FUNC_ARG; + } + + if (ssl->buffers.weOwnCert) { + WOLFSSL_MSG("Unloading cert"); + FreeDer(&ssl->buffers.certificate); + 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 SSL_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 */ + + +#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) + + + int wolfSSL_add_all_algorithms(void) + { + WOLFSSL_ENTER("wolfSSL_add_all_algorithms"); + if (wolfSSL_Init() == SSL_SUCCESS) + return SSL_SUCCESS; + else + return SSL_FATAL_ERROR; + } + + + long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz) + { + /* cache size fixed at compile time in wolfSSL */ + (void)ctx; + (void)sz; + return 0; + } + + + 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; + } + + + void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr) + { + WOLFSSL_ENTER("SSL_set_bio"); + wolfSSL_set_rfd(ssl, rd->fd); + wolfSSL_set_wfd(ssl, wr->fd); + + ssl->biord = rd; + ssl->biowr = wr; + } + + + void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, + STACK_OF(WOLFSSL_X509_NAME)* names) + { + (void)ctx; + (void)names; + } + + + STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) + { + (void)fname; + return 0; + } + + + int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx) + { + /* TODO:, not needed in goahead */ + (void)ctx; + return SSL_NOT_IMPLEMENTED; + } + + + /* keyblock size in bytes or -1 */ + int wolfSSL_get_keyblock_size(WOLFSSL* ssl) + { + if (ssl == NULL) + return SSL_FATAL_ERROR; + + return 2 * (ssl->specs.key_size + ssl->specs.iv_size + + ssl->specs.hash_size); + } + + + /* store keys returns SSL_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 SSL_FATAL_ERROR; + + *ms = ssl->arrays->masterSecret; + *sr = ssl->arrays->serverRandom; + *cr = ssl->arrays->clientRandom; + + *msLen = SECRET_LEN; + *srLen = RAN_LEN; + *crLen = RAN_LEN; + + return SSL_SUCCESS; + } + + + void wolfSSL_set_accept_state(WOLFSSL* ssl) + { + word16 haveRSA = 1; + word16 havePSK = 0; + + WOLFSSL_ENTER("SSL_set_accept_state"); + 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, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } +#endif + + /* 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; + } + +#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) + 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&SSL_SENT_SHUTDOWN) > 0; + ssl->options.closeNotify = (opt&SSL_RECEIVED_SHUTDOWN) > 0; + } + + + long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) + { + /* goahead calls with 0, do nothing */ + WOLFSSL_ENTER("SSL_CTX_set_options"); + (void)ctx; + return opt; + } + + + 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 SSL_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 SSL_SUCCESS; + } + + + WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long bits, + void(*f)(int, int, void*), void* data) + { + /* no tmp key needed, actual generation not supported */ + WOLFSSL_ENTER("RSA_generate_key"); + (void)len; + (void)bits; + (void)f; + (void)data; + return NULL; + } + + + + 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 SSL_FATAL_ERROR; + } + + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_f_buffer"); + meth.type = BIO_BUFFER; + + return &meth; + } + + + 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"); + (void)bio; + return size; + } + + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_f_ssl"); + meth.type = BIO_SSL; + + return &meth; + } + + + WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF) + { + WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, + DYNAMIC_TYPE_OPENSSL); + + WOLFSSL_ENTER("BIO_new_socket"); + if (bio) { + bio->type = BIO_SOCKET; + bio->close = (byte)closeF; + bio->eof = 0; + bio->ssl = 0; + bio->fd = sfd; + bio->prev = 0; + bio->next = 0; + bio->mem = NULL; + bio->memLen = 0; + } + 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("BIO_set_ssl"); + b->ssl = ssl; + b->close = (byte)closeF; + /* add to ssl for bio free if SSL_free called before/instead of free_all? */ + + return 0; + } + + + WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method) + { + WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, + DYNAMIC_TYPE_OPENSSL); + WOLFSSL_ENTER("BIO_new"); + if (bio) { + bio->type = method->type; + bio->close = 0; + bio->eof = 0; + bio->ssl = NULL; + bio->mem = NULL; + bio->memLen = 0; + bio->fd = 0; + bio->prev = NULL; + bio->next = NULL; + } + return bio; + } + + + int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, const byte** p) + { + if (bio == NULL || p == NULL) + return SSL_FATAL_ERROR; + + *p = bio->mem; + + return bio->memLen; + } + + + WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len) + { + WOLFSSL_BIO* bio = NULL; + if (buf == NULL) + return bio; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + if (bio == NULL) + return bio; + + bio->memLen = len; + bio->mem = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + XMEMCPY(bio->mem, buf, len); + + return bio; + } + + +#ifdef USE_WINDOWS_API + #define CloseSocket(s) closesocket(s) +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #define CloseSocket(s) closesocket(s) + extern int closesocket(int) ; +#else + #define CloseSocket(s) close(s) +#endif + + int wolfSSL_BIO_free(WOLFSSL_BIO* bio) + { + /* unchain?, doesn't matter in goahead since from free all */ + WOLFSSL_ENTER("BIO_free"); + if (bio) { + if (bio->close) { + if (bio->ssl) + wolfSSL_free(bio->ssl); + if (bio->fd) + CloseSocket(bio->fd); + } + if (bio->mem) + XFREE(bio->mem, 0, DYNAMIC_TYPE_OPENSSL); + 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; + } + + + int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) + { + int ret; + WOLFSSL* ssl = 0; + WOLFSSL_BIO* front = bio; + + WOLFSSL_ENTER("BIO_read"); + /* already got eof, again is error */ + if (front->eof) + return SSL_FATAL_ERROR; + + while(bio && ((ssl = bio->ssl) == 0) ) + bio = bio->next; + + if (ssl == 0) return BAD_FUNC_ARG; + + ret = wolfSSL_read(ssl, buf, len); + if (ret == 0) + front->eof = 1; + else if (ret < 0) { + int err = wolfSSL_get_error(ssl, 0); + if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) + front->eof = 1; + } + return ret; + } + + + int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) + { + int ret; + WOLFSSL* ssl = 0; + WOLFSSL_BIO* front = bio; + + WOLFSSL_ENTER("BIO_write"); + /* already got eof, again is error */ + if (front->eof) + return SSL_FATAL_ERROR; + + while(bio && ((ssl = bio->ssl) == 0) ) + bio = bio->next; + + if (ssl == 0) return BAD_FUNC_ARG; + + ret = wolfSSL_write(ssl, data, len); + if (ret == 0) + front->eof = 1; + else if (ret < 0) { + int err = wolfSSL_get_error(ssl, 0); + if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) + front->eof = 1; + } + + return ret; + } + + + 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 || GOAHEAD_WS */ + + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + + void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx, + void* userdata) + { + WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata"); + ctx->userdata = userdata; + } + + + void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx, pem_password_cb cb) + { + WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb"); + ctx->passwd_cb = cb; + } + + int wolfSSL_num_locks(void) + { + return 0; + } + + void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int)) + { + (void)f; + } + + void wolfSSL_set_id_callback(unsigned long (*f)(void)) + { + (void)f; + } + + unsigned long wolfSSL_ERR_get_error(void) + { + /* TODO: */ + return 0; + } + +#ifndef NO_MD5 + + 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 keyLen = 0; + int ivLen = 0; + int j; + int keyLeft; + int ivLeft; + int keyOutput = 0; + byte digest[MD5_DIGEST_SIZE]; + #ifdef WOLFSSL_SMALL_STACK + Md5* md5 = NULL; + #else + Md5 md5[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return 0; + #endif + + WOLFSSL_ENTER("wolfSSL_EVP_BytesToKey"); + wc_InitMd5(md5); + + /* only support MD5 for now */ + if (XSTRNCMP(md, "MD5", 3) != 0) return 0; + + /* only support CBC DES and AES for now */ + if (XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0) { + keyLen = DES_KEY_SIZE; + ivLen = DES_IV_SIZE; + } + else if (XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0) { + keyLen = DES3_KEY_SIZE; + ivLen = DES_IV_SIZE; + } + else if (XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) { + keyLen = AES_128_KEY_SIZE; + ivLen = AES_IV_SIZE; + } + else if (XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0) { + keyLen = AES_192_KEY_SIZE; + ivLen = AES_IV_SIZE; + } + else if (XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) { + keyLen = AES_256_KEY_SIZE; + ivLen = AES_IV_SIZE; + } + else { + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } + + keyLeft = keyLen; + ivLeft = ivLen; + + while (keyOutput < (keyLen + ivLen)) { + int digestLeft = MD5_DIGEST_SIZE; + /* D_(i - 1) */ + if (keyOutput) /* first time D_0 is empty */ + wc_Md5Update(md5, digest, MD5_DIGEST_SIZE); + /* data */ + wc_Md5Update(md5, data, sz); + /* salt */ + if (salt) + wc_Md5Update(md5, salt, EVP_SALT_SIZE); + wc_Md5Final(md5, digest); + /* count */ + for (j = 1; j < count; j++) { + wc_Md5Update(md5, digest, MD5_DIGEST_SIZE); + wc_Md5Final(md5, digest); + } + + if (keyLeft) { + int store = min(keyLeft, MD5_DIGEST_SIZE); + XMEMCPY(&key[keyLen - keyLeft], digest, store); + + keyOutput += store; + keyLeft -= store; + digestLeft -= store; + } + + if (ivLeft && digestLeft) { + int store = min(ivLeft, digestLeft); + if (iv != NULL) + XMEMCPY(&iv[ivLen - ivLeft], + &digest[MD5_DIGEST_SIZE - digestLeft], store); + keyOutput += store; + ivLeft -= store; + } + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return keyOutput == (keyLen + ivLen) ? keyOutput : 0; + } + +#endif /* NO_MD5 */ + +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ + + +#ifdef OPENSSL_EXTRA + + 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 + void wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5) + { + typedef char md5_test[sizeof(MD5_CTX) >= sizeof(Md5) ? 1 : -1]; + (void)sizeof(md5_test); + + WOLFSSL_ENTER("MD5_Init"); + wc_InitMd5((Md5*)md5); + } + + + void wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input, + unsigned long sz) + { + WOLFSSL_ENTER("wolfSSL_MD5_Update"); + wc_Md5Update((Md5*)md5, (const byte*)input, (word32)sz); + } + + + void wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5) + { + WOLFSSL_ENTER("MD5_Final"); + wc_Md5Final((Md5*)md5, input); + } +#endif /* NO_MD5 */ + + +#ifndef NO_SHA + void wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha) + { + typedef char sha_test[sizeof(SHA_CTX) >= sizeof(Sha) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA_Init"); + wc_InitSha((Sha*)sha); /* OpenSSL compat, no ret */ + } + + + void wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input, + unsigned long sz) + { + WOLFSSL_ENTER("SHA_Update"); + wc_ShaUpdate((Sha*)sha, (const byte*)input, (word32)sz); + } + + + void wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha) + { + WOLFSSL_ENTER("SHA_Final"); + wc_ShaFinal((Sha*)sha, input); + } + + + void wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha) + { + WOLFSSL_ENTER("SHA1_Init"); + SHA_Init(sha); + } + + + void wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input, + unsigned long sz) + { + WOLFSSL_ENTER("SHA1_Update"); + SHA_Update(sha, input, sz); + } + + + void wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha) + { + WOLFSSL_ENTER("SHA1_Final"); + SHA_Final(input, sha); + } +#endif /* NO_SHA */ + + + void wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256) + { + typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(Sha256) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA256_Init"); + wc_InitSha256((Sha256*)sha256); /* OpenSSL compat, no error */ + } + + + void wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input, + unsigned long sz) + { + WOLFSSL_ENTER("SHA256_Update"); + wc_Sha256Update((Sha256*)sha, (const byte*)input, (word32)sz); + /* OpenSSL compat, no error */ + } + + + void wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha) + { + WOLFSSL_ENTER("SHA256_Final"); + wc_Sha256Final((Sha256*)sha, input); + /* OpenSSL compat, no error */ + } + + + #ifdef WOLFSSL_SHA384 + + void wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha) + { + typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(Sha384) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA384_Init"); + wc_InitSha384((Sha384*)sha); /* OpenSSL compat, no error */ + } + + + void wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input, + unsigned long sz) + { + WOLFSSL_ENTER("SHA384_Update"); + wc_Sha384Update((Sha384*)sha, (const byte*)input, (word32)sz); + /* OpenSSL compat, no error */ + } + + + void wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha) + { + WOLFSSL_ENTER("SHA384_Final"); + wc_Sha384Final((Sha384*)sha, input); + /* OpenSSL compat, no error */ + } + + #endif /* WOLFSSL_SHA384 */ + + + #ifdef WOLFSSL_SHA512 + + void wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha) + { + typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(Sha512) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA512_Init"); + wc_InitSha512((Sha512*)sha); /* OpenSSL compat, no error */ + } + + + void wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input, + unsigned long sz) + { + WOLFSSL_ENTER("SHA512_Update"); + wc_Sha512Update((Sha512*)sha, (const byte*)input, (word32)sz); + /* OpenSSL compat, no error */ + } + + + void wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha) + { + WOLFSSL_ENTER("SHA512_Final"); + wc_Sha512Final((Sha512*)sha, input); + /* OpenSSL compat, no error */ + } + + #endif /* WOLFSSL_SHA512 */ + + + #ifndef NO_MD5 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void) + { + static const char* type = "MD5"; + WOLFSSL_ENTER("EVP_md5"); + return type; + } + + #endif /* NO_MD5 */ + + +#ifndef NO_SHA + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void) + { + static const char* type = "SHA"; + WOLFSSL_ENTER("EVP_sha1"); + return type; + } +#endif /* NO_SHA */ + + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void) + { + static const char* type = "SHA256"; + WOLFSSL_ENTER("EVP_sha256"); + return type; + } + + #ifdef WOLFSSL_SHA384 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void) + { + static const char* type = "SHA384"; + WOLFSSL_ENTER("EVP_sha384"); + return type; + } + + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void) + { + static const char* type = "SHA512"; + WOLFSSL_ENTER("EVP_sha512"); + return type; + } + + #endif /* WOLFSSL_SHA512 */ + + + void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); + (void)ctx; + /* do nothing */ + } + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc"); + return EVP_AES_128_CBC; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc"); + return EVP_AES_192_CBC; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc"); + return EVP_AES_256_CBC; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr"); + return EVP_AES_128_CTR; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr"); + return EVP_AES_192_CTR; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr"); + return EVP_AES_256_CTR; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_cbc"); + return EVP_DES_CBC; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc"); + return EVP_DES_EDE3_CBC; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void) + { + static const char* type = "ARC4"; + WOLFSSL_ENTER("wolfSSL_EVP_rc4"); + return type; + } + +#ifdef HAVE_IDEA + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_idea_cbc"); + 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"); + (void)ctx; + return 0; + } + + + + 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 */ + } + } + + + /* SSL_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 SSL_SUCCESS; + } + + + /* return SSL_SUCCESS on ok, 0 on failure to match API compatibility */ + int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, byte* key, + byte* iv, int enc) + { + int ret = -1; /* failure local, during function 0 means success + because internal functions work that way */ + (void)iv; + (void)enc; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + if (ctx == NULL) { + WOLFSSL_MSG("no ctx"); + return 0; /* failure */ + } + + if (type == NULL && ctx->cipherType == 0xff) { + WOLFSSL_MSG("no type set"); + return 0; /* failure */ + } + +#ifndef NO_AES + 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->keyLen = 16; + 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; + } + } + else 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->keyLen = 24; + 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; + } + } + else 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->keyLen = 32; + 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; + } + } +#ifdef WOLFSSL_AES_COUNTER + else 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->cipherType = AES_128_CTR_TYPE; + ctx->keyLen = 16; + 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; + } + } + else 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->keyLen = 24; + 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; + } + } + else 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->keyLen = 32; + 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_CTR */ +#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->keyLen = 8; + 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); + } + 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->keyLen = 24; + 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; + } + } +#endif /* NO_DES3 */ +#ifndef NO_RC4 + if (ctx->cipherType == ARC4_TYPE || (type && + XSTRNCMP(type, "ARC4", 4) == 0)) { + WOLFSSL_MSG("ARC4"); + ctx->cipherType = ARC4_TYPE; + 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); + ret = 0; /* success */ + } +#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->keyLen = IDEA_KEY_SIZE; + 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; + ret = 0; /* success */ + } + + if (ret == 0) + return SSL_SUCCESS; + else + return 0; /* overall failure */ + } + + + /* SSL_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 */ + } + + + /* SSL_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 SSL_SUCCESS; + } + + + /* SSL_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 WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + 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; +#endif + +#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; /* failuer */ + } + + WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); + return SSL_SUCCESS; /* success */ + } + + + /* store for external read of iv, SSL_SUCCESS on success */ + int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_StoreExternalIV"); + + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + return SSL_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 SSL_FATAL_ERROR; + } + } + return SSL_SUCCESS; + } + + + /* set internal IV from external, SSL_SUCCESS on success */ + int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + + WOLFSSL_ENTER("wolfSSL_SetInternalIV"); + + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + return SSL_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 SSL_FATAL_ERROR; + } + } + return SSL_SUCCESS; + } + + + /* SSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type) + { + WOLFSSL_ENTER("EVP_DigestInit"); + if (XSTRNCMP(type, "SHA256", 6) == 0) { + ctx->macType = SHA256; + wolfSSL_SHA256_Init((SHA256_CTX*)&ctx->hash); + } + #ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + ctx->macType = SHA384; + wolfSSL_SHA384_Init((SHA384_CTX*)&ctx->hash); + } + #endif + #ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + ctx->macType = SHA512; + wolfSSL_SHA512_Init((SHA512_CTX*)&ctx->hash); + } + #endif + #ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + ctx->macType = MD5; + wolfSSL_MD5_Init((MD5_CTX*)&ctx->hash); + } + #endif + #ifndef NO_SHA + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + ctx->macType = SHA; + wolfSSL_SHA_Init((SHA_CTX*)&ctx->hash); + } + #endif /* NO_SHA */ + else + return BAD_FUNC_ARG; + + return SSL_SUCCESS; + } + + + /* SSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data, + unsigned long sz) + { + WOLFSSL_ENTER("EVP_DigestUpdate"); + + switch (ctx->macType) { +#ifndef NO_MD5 + case MD5: + wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_SHA + case SHA: + wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_SHA256 + case SHA256: + wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384: + wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512: + wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return SSL_SUCCESS; + } + + + /* SSL_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_MD5 + case MD5: + wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash); + if (s) *s = MD5_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA + case SHA: + wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash); + if (s) *s = SHA_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA256 + case SHA256: + wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash); + if (s) *s = SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384: + wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash); + if (s) *s = SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512: + wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash); + if (s) *s = SHA512_DIGEST_SIZE; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return SSL_SUCCESS; + } + + + /* SSL_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; + unsigned char* ret = NULL; +#ifdef WOLFSSL_SMALL_STACK + Hmac* hmac = NULL; +#else + Hmac hmac[1]; +#endif + + WOLFSSL_ENTER("HMAC"); + if (!md) + return NULL; /* no static buffer support */ + + if (XSTRNCMP(evp_md, "MD5", 3) == 0) + type = MD5; + else if (XSTRNCMP(evp_md, "SHA", 3) == 0) + type = SHA; + else + return NULL; + + #ifdef WOLFSSL_SMALL_STACK + hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hmac == NULL) + return NULL; + #endif + + 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 = (type == MD5) ? (int)MD5_DIGEST_SIZE + : (int)SHA_DIGEST_SIZE; + ret = md; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } + + void wolfSSL_ERR_clear_error(void) + { + /* TODO: */ + } + + + int wolfSSL_RAND_status(void) + { + return SSL_SUCCESS; /* wolfCrypt provides enough seed internally */ + } + + + + void wolfSSL_RAND_add(const void* add, int len, double entropy) + { + (void)add; + (void)len; + (void)entropy; + + /* wolfSSL seeds/adds internally, use explicit RNG if you want + to take control */ + } + + +#ifndef NO_DES3 + /* SSL_SUCCESS on ok */ + int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key, + WOLFSSL_DES_key_schedule* schedule) + { + WOLFSSL_ENTER("DES_key_sched"); + XMEMCPY(schedule, key, sizeof(const_DES_cblock)); + return SSL_SUCCESS; + } + + + 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; + + WOLFSSL_ENTER("DES_cbc_encrypt"); + + /* OpenSSL compat, no ret */ + wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc); + + if (enc) + wc_Des_CbcEncrypt(&myDes, output, input, (word32)length); + else + wc_Des_CbcDecrypt(&myDes, output, input, (word32)length); + } + + + /* 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; + + WOLFSSL_ENTER("DES_ncbc_encrypt"); + + /* OpenSSL compat, no ret */ + wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc); + + if (enc) + wc_Des_CbcEncrypt(&myDes, output, input, (word32)length); + else + wc_Des_CbcDecrypt(&myDes, output, input, (word32)length); + + XMEMCPY(ivec, output + length - sizeof(DES_cblock), sizeof(DES_cblock)); + } + +#endif /* NO_DES3 */ + + + void wolfSSL_ERR_free_strings(void) + { + /* handled internally */ + } + + + void wolfSSL_ERR_remove_state(unsigned long state) + { + /* TODO: GetErrors().Remove(); */ + (void)state; + } + + + 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) + { + (void)ssl; + /* TODO: GetErrors().Remove(); */ + return SSL_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 SSL_SUCCESS; + } + + + long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode) + { + /* SSL_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; + } + + + long wolfSSL_SSL_get_mode(WOLFSSL* ssl) + { + /* TODO: */ + (void)ssl; + return 0; + } + + + long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx) + { + /* TODO: */ + (void)ctx; + return 0; + } + + + void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m) + { + /* TODO: maybe? */ + (void)ctx; + (void)m; + } + + + int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx, + const unsigned char* sid_ctx, + unsigned int sid_ctx_len) + { + /* No application specific context needed for wolfSSL */ + (void)ctx; + (void)sid_ctx; + (void)sid_ctx_len; + return SSL_SUCCESS; + } + + + long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx) + { + /* TODO: maybe? */ + (void)ctx; + return (~0); + } + + unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line, + const char** data, int *flags) + { + /* Not implemented */ + (void)file; + (void)line; + (void)data; + (void)flags; + return 0; + } + +#endif /* OPENSSL_EXTRA */ + + +#if defined(KEEP_PEER_CERT) + + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) + { + WOLFSSL_ENTER("SSL_get_peer_certificate"); + if (ssl->peerCert.issuer.sz) + return &ssl->peerCert; + else + return 0; + } + +#endif /* KEEP_PEER_CERT */ + + +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || defined(OPENSSSL_EXTRA) + +/* 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, NULL, DYNAMIC_TYPE_X509); + } else { + WOLFSSL_MSG("free called on non dynamic object, not freeing"); + } + } +} + +#endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSSL_EXTRA */ + +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) + + void wolfSSL_FreeX509(WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_FreeX509"); + ExternalFreeX509(x509); + } + + + /* 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; + } + + + WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert) + { + WOLFSSL_ENTER("X509_get_issuer_name"); + if(cert) + return &cert->issuer; + return NULL; + } + + + WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert) + { + WOLFSSL_ENTER("wolfSSL_X509_get_subject_name"); + if(cert) + return &cert->subject; + return NULL; + } + + + 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; + } + + +#ifdef OPENSSL_EXTRA + 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_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; + default: + break; + } + + if (buf != NULL && text != NULL) { + textSz = min(textSz, len); + XMEMCPY(buf, text, textSz); + buf[textSz] = '\0'; + } + + WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz); + return textSz; + } +#endif + + + /* 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 = min(sz, name->sz); + + WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline"); + if (!name->sz) return in; + + if (!in) { + in = (char*)XMALLOC(name->sz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in ) return in; + copySz = name->sz; + } + + if (copySz == 0) + return in; + + XMEMCPY(in, name->name, copySz - 1); + in[copySz - 1] = 0; + + return in; + } + + + 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; + } + + + 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 SSL_FATAL_ERROR; + + if (buf != NULL) + XMEMCPY(buf, x509->sig.buffer, x509->sig.length); + *bufSz = x509->sig.length; + + return SSL_SUCCESS; + } + + + /* write X509 serial number in unsigned binary to buffer + buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases + return SSL_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 SSL_SUCCESS; + } + + + const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz) + { + WOLFSSL_ENTER("wolfSSL_X509_get_der"); + + if (x509 == 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) { + in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->deviceTypeSz; + } + + 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) { + in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->hwTypeSz; + } + + 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) { + in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->hwSerialNumSz; + } + + XMEMCPY(in, x509->hwSerialNum, copySz); + *inOutSz = copySz; + + return in; +} + +#endif /* WOLFSSL_SEP */ + + +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_TMP_BUFFER); + 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); + if (CopyDecodedToX509(newX509, cert) != 0) { + XFREE(newX509, NULL, DYNAMIC_TYPE_X509); + newX509 = NULL; + } + } + } + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + + if (x509 != NULL) + *x509 = newX509; + + return newX509; +} + + +#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, sz, 1, file); + if (ret > 0) { + 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; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_load_certificate"); + + /* Check the inputs */ + if ((fname == NULL) || + (format != SSL_FILETYPE_ASN1 && format != SSL_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, sz, 1, file); + if (ret < 0) { + XFCLOSE(file); + if (dynamic) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + return NULL; + } + + XFCLOSE(file); + + if (format == SSL_FILETYPE_PEM) { + int ecc = 0; + #ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; + #else + EncryptedInfo info[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) { + if (dynamic) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + + return NULL; + } + #endif + + info->set = 0; + info->ctx = NULL; + info->consumed = 0; + + if (PemToDer(fileBuffer, sz, CERT_TYPE, &der, NULL, info, &ecc) != 0) { + FreeDer(&der); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + else { + ret = AllocDer(&der, (word32)sz, CERT_TYPE, NULL); + if (ret == 0) { + XMEMCPY(der->buffer, fileBuffer, sz); + } + } + + if (dynamic) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + + /* 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_TMP_BUFFER); + 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); + if (CopyDecodedToX509(x509, cert) != 0) { + XFREE(x509, NULL, DYNAMIC_TYPE_X509); + x509 = NULL; + } + } + } + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + + FreeDer(&der); + } + + return x509; +} + +#endif /* NO_FILESYSTEM */ + +#endif /* KEEP_PEER_CERT || SESSION_CERTS */ + + +#ifdef OPENSSL_EXTRA +int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, + unsigned int len) +{ + (void)ssl; + (void)id; + (void)len; + return 0; +} + + +void wolfSSL_set_connect_state(WOLFSSL* ssl) +{ + (void)ssl; + /* client by default */ +} +#endif + +int wolfSSL_get_shutdown(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_shutdown"); + /* in OpenSSL, SSL_SENT_SHUTDOWN = 1, when closeNotifySent * + * SSL_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; +} + +#ifdef OPENSSL_EXTRA +void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) +{ + /* No need to free since cache is static */ + (void)session; +} +#endif + +const char* wolfSSL_get_version(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_get_version"); + if (ssl->version.major == SSLv3_MAJOR) { + switch (ssl->version.minor) { + case SSLv3_MINOR : + return "SSLv3"; + case TLSv1_MINOR : + return "TLSv1"; + case TLSv1_1_MINOR : + return "TLSv1.1"; + case TLSv1_2_MINOR : + return "TLSv1.2"; + default: + return "unknown"; + } + } + 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"; + } + } + 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) +{ + (void)cipher; + + WOLFSSL_ENTER("SSL_CIPHER_get_name"); +#ifndef NO_ERROR_STRINGS + if (cipher) { +#if defined(HAVE_CHACHA) + if (cipher->ssl->options.cipherSuite0 == CHACHA_BYTE) { + /* ChaCha suites */ + switch (cipher->ssl->options.cipherSuite) { +#ifdef HAVE_POLY1305 +#ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; + + case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + return "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; + + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + return "TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256"; + + case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + return "TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256"; +#endif + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : + return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; + + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + return "TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256"; +#ifndef NO_PSK + case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : + return "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"; + case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 : + return "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256"; + case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : + return "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"; +#endif /* NO_PSK */ +#endif /* HAVE_POLY1305 */ + } + } +#endif + +#if defined(HAVE_ECC) || defined(HAVE_AESCCM) + /* Awkwardly, the ECC cipher suites use the ECC_BYTE as expected, + * but the AES-CCM cipher suites also use it, even the ones that + * aren't ECC. */ + if (cipher->ssl->options.cipherSuite0 == ECC_BYTE) { + /* ECC suites */ + switch (cipher->ssl->options.cipherSuite) { +#ifdef HAVE_ECC +#ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; +#endif + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; +#ifndef NO_RSA + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; +#endif + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 : + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; +#ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; +#endif + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 : + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; +#ifndef NO_RSA + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 : + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; +#endif + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 : + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; +#ifndef NO_SHA +#ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA : + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; +#endif + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; +#ifndef NO_RC4 + #ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_RC4_128_SHA : + return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; + #endif + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : + return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; +#endif +#ifndef NO_DES3 + #ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : + return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; + #endif + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : + return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; +#endif + +#ifndef NO_RSA + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; +#endif + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; +#ifndef NO_RC4 + #ifndef NO_RSA + case TLS_ECDH_RSA_WITH_RC4_128_SHA : + return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + #endif + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : + return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; +#endif +#ifndef NO_DES3 + #ifndef NO_RSA + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : + return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + #endif + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : + return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; +#endif +#endif /* NO_SHA */ + +#ifdef HAVE_AESGCM +#ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : + return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : + return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; +#endif + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : + return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : + return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; +#ifndef NO_RSA + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : + return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : + return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; +#endif + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : + return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : + return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; +#endif + case TLS_ECDHE_ECDSA_WITH_NULL_SHA : + return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; +#ifndef NO_PSK + case TLS_ECDHE_PSK_WITH_NULL_SHA256 : + return "TLS_ECDHE_PSK_WITH_NULL_SHA256"; + case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 : + return "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"; +#endif +#endif /* HAVE_ECC */ + +#ifdef HAVE_AESCCM +#ifndef NO_RSA + case TLS_RSA_WITH_AES_128_CCM_8 : + return "TLS_RSA_WITH_AES_128_CCM_8"; + case TLS_RSA_WITH_AES_256_CCM_8 : + return "TLS_RSA_WITH_AES_256_CCM_8"; +#endif +#ifndef NO_PSK + case TLS_PSK_WITH_AES_128_CCM_8 : + return "TLS_PSK_WITH_AES_128_CCM_8"; + case TLS_PSK_WITH_AES_256_CCM_8 : + return "TLS_PSK_WITH_AES_256_CCM_8"; + case TLS_PSK_WITH_AES_128_CCM : + return "TLS_PSK_WITH_AES_128_CCM"; + case TLS_PSK_WITH_AES_256_CCM : + return "TLS_PSK_WITH_AES_256_CCM"; + case TLS_DHE_PSK_WITH_AES_128_CCM : + return "TLS_DHE_PSK_WITH_AES_128_CCM"; + case TLS_DHE_PSK_WITH_AES_256_CCM : + return "TLS_DHE_PSK_WITH_AES_256_CCM"; +#endif +#ifdef HAVE_ECC + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"; + case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 : + return "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"; +#endif +#endif + + default: + return "NONE"; + } + } +#endif /* ECC */ + if (cipher->ssl->options.cipherSuite0 != ECC_BYTE && + cipher->ssl->options.cipherSuite0 != CHACHA_BYTE) { + + /* normal suites */ + switch (cipher->ssl->options.cipherSuite) { +#ifndef NO_RSA +#ifndef NO_RC4 + #ifndef NO_SHA + case SSL_RSA_WITH_RC4_128_SHA : + return "SSL_RSA_WITH_RC4_128_SHA"; + #endif + #ifndef NO_MD5 + case SSL_RSA_WITH_RC4_128_MD5 : + return "SSL_RSA_WITH_RC4_128_MD5"; + #endif +#endif +#ifndef NO_SHA + #ifndef NO_DES3 + case SSL_RSA_WITH_3DES_EDE_CBC_SHA : + return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; + #endif + #ifdef HAVE_IDEA + case SSL_RSA_WITH_IDEA_CBC_SHA : + return "SSL_RSA_WITH_IDEA_CBC_SHA"; + #endif + + case TLS_RSA_WITH_AES_128_CBC_SHA : + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + case TLS_RSA_WITH_AES_256_CBC_SHA : + return "TLS_RSA_WITH_AES_256_CBC_SHA"; +#endif + case TLS_RSA_WITH_AES_128_CBC_SHA256 : + return "TLS_RSA_WITH_AES_128_CBC_SHA256"; + case TLS_RSA_WITH_AES_256_CBC_SHA256 : + return "TLS_RSA_WITH_AES_256_CBC_SHA256"; + #ifdef HAVE_BLAKE2 + case TLS_RSA_WITH_AES_128_CBC_B2B256: + return "TLS_RSA_WITH_AES_128_CBC_B2B256"; + case TLS_RSA_WITH_AES_256_CBC_B2B256: + return "TLS_RSA_WITH_AES_256_CBC_B2B256"; + #endif +#ifndef NO_SHA + case TLS_RSA_WITH_NULL_SHA : + return "TLS_RSA_WITH_NULL_SHA"; +#endif + case TLS_RSA_WITH_NULL_SHA256 : + return "TLS_RSA_WITH_NULL_SHA256"; +#endif /* NO_RSA */ +#ifndef NO_PSK +#ifndef NO_SHA + case TLS_PSK_WITH_AES_128_CBC_SHA : + return "TLS_PSK_WITH_AES_128_CBC_SHA"; + case TLS_PSK_WITH_AES_256_CBC_SHA : + return "TLS_PSK_WITH_AES_256_CBC_SHA"; +#endif +#ifndef NO_SHA256 + case TLS_PSK_WITH_AES_128_CBC_SHA256 : + return "TLS_PSK_WITH_AES_128_CBC_SHA256"; + case TLS_PSK_WITH_NULL_SHA256 : + return "TLS_PSK_WITH_NULL_SHA256"; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 : + return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; + case TLS_DHE_PSK_WITH_NULL_SHA256 : + return "TLS_DHE_PSK_WITH_NULL_SHA256"; + #ifdef HAVE_AESGCM + case TLS_PSK_WITH_AES_128_GCM_SHA256 : + return "TLS_PSK_WITH_AES_128_GCM_SHA256"; + case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 : + return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; + #endif +#endif +#ifdef WOLFSSL_SHA384 + case TLS_PSK_WITH_AES_256_CBC_SHA384 : + return "TLS_PSK_WITH_AES_256_CBC_SHA384"; + case TLS_PSK_WITH_NULL_SHA384 : + return "TLS_PSK_WITH_NULL_SHA384"; + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 : + return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; + case TLS_DHE_PSK_WITH_NULL_SHA384 : + return "TLS_DHE_PSK_WITH_NULL_SHA384"; + #ifdef HAVE_AESGCM + case TLS_PSK_WITH_AES_256_GCM_SHA384 : + return "TLS_PSK_WITH_AES_256_GCM_SHA384"; + case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 : + return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; + #endif +#endif +#ifndef NO_SHA + case TLS_PSK_WITH_NULL_SHA : + return "TLS_PSK_WITH_NULL_SHA"; +#endif +#endif /* NO_PSK */ +#ifndef NO_RSA + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 : + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 : + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; +#ifndef NO_SHA + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA : + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA : + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; +#endif +#ifndef NO_HC128 + #ifndef NO_MD5 + case TLS_RSA_WITH_HC_128_MD5 : + return "TLS_RSA_WITH_HC_128_MD5"; + #endif + #ifndef NO_SHA + case TLS_RSA_WITH_HC_128_SHA : + return "TLS_RSA_WITH_HC_128_SHA"; + #endif + #ifdef HAVE_BLAKE2 + case TLS_RSA_WITH_HC_128_B2B256: + return "TLS_RSA_WITH_HC_128_B2B256"; + #endif +#endif /* NO_HC128 */ +#ifndef NO_SHA + #ifndef NO_RABBIT + case TLS_RSA_WITH_RABBIT_SHA : + return "TLS_RSA_WITH_RABBIT_SHA"; + #endif + #ifdef HAVE_NTRU + #ifndef NO_RC4 + case TLS_NTRU_RSA_WITH_RC4_128_SHA : + return "TLS_NTRU_RSA_WITH_RC4_128_SHA"; + #endif + #ifndef NO_DES3 + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + return "TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA"; + #endif + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA"; + case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : + return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA"; + #endif /* HAVE_NTRU */ + #ifdef HAVE_QSH + case TLS_QSH : + return "TLS_QSH"; + #endif /* HAVE_QSH*/ +#endif /* NO_SHA */ + case TLS_RSA_WITH_AES_128_GCM_SHA256 : + return "TLS_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_RSA_WITH_AES_256_GCM_SHA384 : + return "TLS_RSA_WITH_AES_256_GCM_SHA384"; + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : + return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 : + return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; +#ifndef NO_SHA + case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA : + return "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"; + case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : + return "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"; +#endif + case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 : + return "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"; + case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 : + return "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"; +#ifndef NO_SHA + case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA : + return "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"; + case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA : + return "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"; +#endif + case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 : + return "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"; + case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 : + return "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"; +#endif /* NO_RSA */ +#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + case TLS_DH_anon_WITH_AES_128_CBC_SHA : + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; +#endif + default: + return "NONE"; + } /* switch */ + } /* normal / ECC */ + } +#endif /* NO_ERROR_STRINGS */ + return "NONE"; +} + + +const char* wolfSSL_get_cipher(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_cipher"); + return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)); +} + +#ifdef OPENSSL_EXTRA + + + +char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER* cipher, char* in, int len) +{ + (void)cipher; + (void)in; + (void)len; + return 0; +} + + +WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) +{ + /* sessions are stored statically, no need for reference count */ + return wolfSSL_get_session(ssl); +} + + +void wolfSSL_X509_free(WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("wolfSSL_X509_free"); + ExternalFreeX509(x509); +} + + +/* was do nothing */ +/* +void OPENSSL_free(void* buf) +{ + (void)buf; +} +*/ + + +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; + return 0; +} + + +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 */ + + +WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top) +{ + (void)top; + return 0; +} + + +int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) +{ + (void)bio; + return 0; +} + + + +WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void) +{ + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_s_mem"); + meth.type = BIO_MEMORY; + + return &meth; +} + + +WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void) +{ + return 0; +} + + +void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags) +{ + (void)bio; + (void)flags; +} + + + +void wolfSSL_RAND_screen(void) +{ + +} + + +const char* wolfSSL_RAND_file_name(char* fname, unsigned long len) +{ + (void)fname; + (void)len; + return 0; +} + + +int wolfSSL_RAND_write_file(const char* fname) +{ + (void)fname; + return 0; +} + + +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; +} + + +int wolfSSL_RAND_egd(const char* path) +{ + (void)path; + return 0; +} + + + +WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void) +{ + return 0; +} + + +WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) +{ + return 0; +} + + +int wolfSSL_COMP_add_compression_method(int method, void* data) +{ + (void)method; + (void)data; + return 0; +} + + +void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)( + const char*, int)) +{ + (void)f; +} + + +void wolfSSL_set_dynlock_lock_callback( + void (*f)(int, WOLFSSL_dynlock_value*, const char*, int)) +{ + (void)f; +} + + +void wolfSSL_set_dynlock_destroy_callback( + void (*f)(WOLFSSL_dynlock_value*, const char*, int)) +{ + (void)f; +} + + + +const char* wolfSSL_X509_verify_cert_error_string(long err) +{ + return wolfSSL_ERR_reason_error_string(err); +} + + + +int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, + long len) +{ + (void)lookup; + (void)dir; + (void)len; + return 0; +} + + +int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, + const char* file, long len) +{ + (void)lookup; + (void)file; + (void)len; + return 0; +} + + +WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void) +{ + return 0; +} + + +WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void) +{ + return 0; +} + + + +WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, + WOLFSSL_X509_LOOKUP_METHOD* m) +{ + (void)store; + (void)m; + return 0; +} + + +int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) +{ + int result = SSL_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 != SSL_SUCCESS) { + result = SSL_FATAL_ERROR; + } + + return result; +} + + +WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) +{ + WOLFSSL_X509_STORE* store = NULL; + + store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL, + DYNAMIC_TYPE_X509_STORE); + if (store != NULL) { + store->cm = wolfSSL_CertManagerNew(); + if (store->cm == NULL) { + XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); + store = NULL; + } + } + + return store; +} + + +void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) +{ + if (store != NULL) { + if (store->cm != NULL) + wolfSSL_CertManagerFree(store->cm); + XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); + } +} + + +int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store) +{ + (void)store; + return SSL_SUCCESS; +} + + +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; + return 0; +} + + +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) + 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, 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->domain = NULL; + ctx->ex_data = NULL; + ctx->userCtx = NULL; + ctx->error = 0; + ctx->error_depth = 0; + ctx->discardSessionCerts = 0; + return SSL_SUCCESS; + } + return SSL_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); + XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX); + } +} + + +void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx) +{ + (void)ctx; +} + + +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, + SSL_FILETYPE_ASN1); + } + return SSL_FATAL_ERROR; +} + + +WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl) +{ + (void)crl; + return 0; +} + + +WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl) +{ + (void)crl; + return 0; +} + + + +WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) +{ + WOLFSSL_EVP_PKEY* key = NULL; + if (x509 != NULL) { + key = (WOLFSSL_EVP_PKEY*)XMALLOC( + sizeof(WOLFSSL_EVP_PKEY), NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (key != NULL) { + key->type = x509->pubKeyOID; + key->save_type = 0; + key->pkey.ptr = (char*)XMALLOC( + x509->pubKey.length, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (key->pkey.ptr == NULL) { + XFREE(key, NULL, 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 */ + } + } + return key; +} + + +int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key) +{ + (void)crl; + (void)key; + return 0; +} + + +void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int err) +{ + (void)ctx; + (void)err; +} + + +void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) +{ + (void)obj; +} + + +void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) +{ + if (key != NULL) { + if (key->pkey.ptr != NULL) + XFREE(key->pkey.ptr, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(key, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + } +} + + +int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime) +{ + (void)asnTime; + return 0; +} + + +int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED* revoked) +{ + (void)revoked; + return 0; +} + + + +WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL* crl) +{ + (void)crl; + return 0; +} + + +WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( + WOLFSSL_X509_REVOKED* revoked, int value) +{ + (void)revoked; + (void)value; + return 0; +} + + + +WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) +{ + (void)x509; + return 0; +} + + +int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime) +{ + (void)bio; + (void)asnTime; + return 0; +} + + + +int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a, + const WOLFSSL_ASN1_INTEGER* b) +{ + (void)a; + (void)b; + return 0; +} + + +long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i) +{ + (void)i; + return 0; +} + + + +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(FORTRESS) || defined(HAVE_STUNNEL) + if (ctx != NULL && idx == 0) + return ctx->ex_data; +#else + (void)ctx; + (void)idx; +#endif + return 0; +} + + +int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void) +{ + WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx"); + return 0; +} + + +void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, + void (*f)(const WOLFSSL* ssl, int type, int val)) +{ + (void)ctx; + (void)f; +} + + +unsigned long wolfSSL_ERR_peek_error(void) +{ + return 0; +} + + +int wolfSSL_ERR_GET_REASON(unsigned long err) +{ + (void)err; + return 0; +} + + +char* wolfSSL_alert_type_string_long(int alertID) +{ + (void)alertID; + return 0; +} + + +char* wolfSSL_alert_desc_string_long(int alertID) +{ + (void)alertID; + return 0; +} + + +char* wolfSSL_state_string_long(const WOLFSSL* ssl) +{ + (void)ssl; + return 0; +} + + +int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key) +{ + (void)name; + (void)num; + (void)w; + (void)key; + return 0; +} + + +long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + +#ifndef NO_DES3 + +void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) +{ + (void)myDes; + (void)key; +} + + +void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes) +{ + (void)myDes; +} + + +void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa, + WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int len) +{ + (void)desa; + (void)desb; + (void)key; + (void)len; +} + +#endif /* NO_DES3 */ + +int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...) +{ + (void)bio; + (void)format; + return 0; +} + + +int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) +{ + (void)bio; + (void)a; + return 0; +} + + +int wolfSSL_sk_num(WOLFSSL_X509_REVOKED* rev) +{ + (void)rev; + return 0; +} + + +void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED* rev, int i) +{ + (void)rev; + (void)i; + return 0; +} + + +/* stunnel 4.28 needs */ +void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, + WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)) +{ + (void)ctx; + (void)f; +} + + +void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, + int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) +{ + (void)ctx; + (void)f; +} + + +void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, + WOLFSSL_SESSION*)) +{ + (void)ctx; + (void)f; +} + + +int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) +{ + (void)sess; + (void)p; + return sizeof(WOLFSSL_SESSION); +} + + +WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, + const unsigned char** p, long i) +{ + (void)p; + (void)i; + if (sess) + return *sess; + return NULL; +} + + +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 + +#ifdef FORTRESS +int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) +{ + int ret = SSL_FATAL_ERROR; + + WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file"); + if (ssl != NULL && fname != NULL) + { + #ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; + byte staticBuffer[1]; /* force heap usage */ + #else + EncryptedInfo info[1]; + byte staticBuffer[FILE_BUFFER_SIZE]; + #endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + XFILE file = XBADFILE; + long sz = 0; + int eccKey = 0; + WOLFSSL_CTX* ctx = ssl->ctx; + WOLFSSL_X509* peer_cert = &ssl->peerCert; + DerBuffer* fileDer = NULL; + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) + return SSL_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; + } + + #ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) + ret = MEMORY_E; + else + #endif + { + info->set = 0; + info->ctx = ctx; + info->consumed = 0; + + if ((myBuffer != NULL) && + (sz > 0) && + (XFREAD(myBuffer, sz, 1, file) > 0) && + (PemToDer(myBuffer, sz, CERT_TYPE, + &fileDer, ctx->heap, info, &eccKey) == 0) && + (fileDer->length != 0) && + (fileDer->length == peer_cert->derCert->length) && + (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer, + fileDer->length) == 0)) + { + ret = 0; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + + FreeDer(&fileDer); + + if (dynamic) + XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + + XFCLOSE(file); + } + + return ret; +} +#endif + + +static WC_RNG globalRNG; +static int initGlobalRNG = 0; + +/* SSL_SUCCESS on ok */ +int wolfSSL_RAND_seed(const void* seed, int len) +{ + + WOLFSSL_MSG("wolfSSL_RAND_seed"); + + (void)seed; + (void)len; + + 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_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_TMP_BUFFER); + 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 = SSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + 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 */ +} + + +static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("InitwolfSSL_BigNum"); + if (bn) { + 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_clear((mp_int*)bn->internal); + XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); + bn->internal = NULL; + } + XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); + bn = NULL; + } +} + + +void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_clear_free"); + + wolfSSL_BN_free(bn); +} + + +/* SSL_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 SSL_SUCCESS; + + WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed"); + return 0; +} + + +/* SSL_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 SSL_SUCCESS; + + WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed"); + return 0; +} + + +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) + mp_set_int((mp_int*)bn_one->internal, 1); + } + + 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_MSG("wolfSSL_BN_num_bytes"); + + if (bn == NULL || bn->internal == NULL) + return SSL_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_MSG("wolfSSL_BN_num_bits"); + + if (bn == NULL || bn->internal == NULL) + return SSL_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 SSL_FAILURE; + + if (mp_iszero((mp_int*)bn->internal) == MP_YES) + return SSL_SUCCESS; + + return SSL_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 SSL_FAILURE; + + if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ) + return SSL_SUCCESS; + + return SSL_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 SSL_FAILURE; + + if (mp_isodd((mp_int*)bn->internal) == MP_YES) + return SSL_SUCCESS; + + return SSL_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 SSL_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 SSL_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 SSL_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 */ +int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) +{ + (void)bn; + (void)n; + WOLFSSL_MSG("wolfSSL_BN_mask_bits"); + + return SSL_FAILURE; +} + + +/* SSL_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_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 { + 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 = SSL_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 SSL_FAILURE; + } + + if (n > DIGIT_BIT) { + WOLFSSL_MSG("input bit count too large"); + return SSL_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 SSL_FAILURE; + } + + if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) { + WOLFSSL_MSG("mp_set_int error"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} + + +/* SSL_SUCCESS on ok */ +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 + + WOLFSSL_MSG("wolfSSL_BN_hex2bn"); + +#ifdef WOLFSSL_SMALL_STACK + decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL) + return ret; +#endif + + if (str == NULL) + 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) + WOLFSSL_MSG("BN new failed"); + else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) + WOLFSSL_MSG("Bad bin2bn error"); + else + ret = SSL_SUCCESS; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#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 (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 (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) { + WOLFSSL_MSG("mp_init_set_int error"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * number length in decimal if success, 0 if error + */ +int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + (void)bn; + (void)str; + + WOLFSSL_MSG("wolfSSL_BN_dec2bn"); + + return SSL_FAILURE; +} + + +#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, 10, &len) != MP_OKAY) { + WOLFSSL_MSG("mp_radix_size failure"); + return NULL; + } + + buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC); + if (buf == NULL) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex malloc buffer failure"); + return NULL; + } + + if (mp_toradix((mp_int*)bn->internal, buf, 10) != 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 SSL_FAILURE; + } + + if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_mul_2d error"); + return SSL_FAILURE; + } + + return SSL_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 SSL_FAILURE; + } + + if (mp_div_2d((mp_int*)bn->internal, n, + (mp_int*)r->internal, NULL) != MP_OKAY) { + WOLFSSL_MSG("mp_mul_2d error"); + return SSL_FAILURE; + } + + return SSL_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 SSL_FAILURE; + } + + if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return SSL_FAILURE; + } + + return SSL_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 SSL_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 SSL_FAILURE; + } + + return SSL_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 SSL_FATAL_ERROR; + } + + if (mp_prime_is_prime((mp_int*)bn->internal, nbchecks, &res) != MP_OKAY) { + WOLFSSL_MSG("mp_prime_is_prime error"); + return SSL_FATAL_ERROR; + } + + if (res != MP_YES) { + WOLFSSL_MSG("mp_prime_is_prime not prime"); + return SSL_FAILURE; + } + + return SSL_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)SSL_FATAL_ERROR; + } + + if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return (WOLFSSL_BN_ULONG)SSL_FATAL_ERROR; + } + + return ret; +} +#endif /* #ifdef WOLFSSL_KEY_GEN */ + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) +{ + int len = 0; + char *buf; + + WOLFSSL_MSG("wolfSSL_BN_bn2hex"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; + } + + if (mp_radix_size((mp_int*)bn->internal, 16, &len) != MP_OKAY) { + WOLFSSL_MSG("mp_radix_size failure"); + return NULL; + } + + buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC); + if (buf == NULL) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex malloc buffer failure"); + return NULL; + } + + if (mp_toradix((mp_int*)bn->internal, buf, 16) != MP_OKAY) { + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + + return buf; +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_BN_print_fp(FILE *fp, const WOLFSSL_BIGNUM *bn) +{ + char *buf; + + WOLFSSL_MSG("wolfSSL_BN_print_fp"); + + if (fp == NULL || bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return SSL_FAILURE; + } + + buf = wolfSSL_BN_bn2hex(bn); + if (buf == NULL) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex failure"); + return SSL_FAILURE; + } + + fprintf(fp, "%s", buf); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + + return SSL_SUCCESS; +} +#endif /* !defined(NO_FILESYSTEM) */ + +#else /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ + +char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) +{ + (void)bn; + + WOLFSSL_MSG("wolfSSL_BN_bn2hex not implemented"); + + return (char*)""; +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_BN_print_fp(FILE *fp, const WOLFSSL_BIGNUM *bn) +{ + (void)fp; + (void)bn; + + WOLFSSL_MSG("wolfSSL_BN_print_fp not implemented"); + + return SSL_SUCCESS; +} +#endif /* !defined(NO_FILESYSTEM) */ + +#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ + +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(); +} + +void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_CTX_start"); + WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD"); +} + +#ifndef NO_DH + +static void InitwolfSSL_DH(WOLFSSL_DH* dh) +{ + if (dh) { + dh->p = NULL; + dh->g = 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); + wc_InitDhKey(key); + 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); + InitwolfSSL_DH(dh); /* set back to NULLs for safety */ + + XFREE(dh, NULL, DYNAMIC_TYPE_DH); + } +} + + +static int SetDhInternal(WOLFSSL_DH* dh) +{ + int ret = SSL_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_TMP_BUFFER); + g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (p == NULL || g == NULL) { + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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 = SSL_SUCCESS; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #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 SSL_FATAL_ERROR; + + return wolfSSL_BN_num_bytes(dh->p); +} + + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) +{ + int ret = SSL_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_TMP_BUFFER); + pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (tmpRNG == NULL || pub == NULL || priv == NULL) { + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } +#endif + + if (dh == NULL || dh->p == NULL || dh->g == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (dh->inSet == 0 && SetDhInternal(dh) != SSL_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 = SSL_SUCCESS; + } + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#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 = SSL_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_TMP_BUFFER); + if (pub == NULL) + return ret; + + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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 (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_TMP_BUFFER); + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#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); + InitDsaKey(key); + 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 */ + +#ifndef NO_RSA +static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa) +{ + if (rsa) { + rsa->n = NULL; + rsa->e = NULL; + rsa->d = NULL; + rsa->p = NULL; + rsa->q = NULL; + rsa->dmp1 = NULL; + rsa->dmq1 = NULL; + rsa->iqmp = NULL; + rsa->internal = NULL; + rsa->inSet = 0; + rsa->exSet = 0; + } +} + + +WOLFSSL_RSA* wolfSSL_RSA_new(void) +{ + WOLFSSL_RSA* external; + RsaKey* key; + + WOLFSSL_MSG("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; + } + external->internal = key; + + return external; +} + + +void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) +{ + WOLFSSL_MSG("wolfSSL_RSA_free"); + + if (rsa) { + if (rsa->internal) { + 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); + InitwolfSSL_Rsa(rsa); /* set back to NULLs for safety */ + + XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); + rsa = NULL; + } +} +#endif /* NO_RSA */ + + +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)) \ + || !defined(NO_DSA) || defined(HAVE_ECC) +static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) +{ + WOLFSSL_MSG("Entering SetIndividualExternal"); + + if (mpi == NULL || bn == NULL) { + WOLFSSL_MSG("mpi NULL error"); + return SSL_FATAL_ERROR; + } + + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn == NULL) { + WOLFSSL_MSG("SetIndividualExternal alloc failed"); + return SSL_FATAL_ERROR; + } + } + + if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return SSL_FATAL_ERROR; + } + + return SSL_SUCCESS; +} + +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 SSL_FATAL_ERROR; + } + + if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) { + WOLFSSL_MSG("mpi NULL error"); + return SSL_FATAL_ERROR; + } + + if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return SSL_FATAL_ERROR; + } + + return SSL_SUCCESS; +} +#endif /* !NO_RSA && !NO_DSA */ + + +#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 SSL_FATAL_ERROR; + } + + key = (DsaKey*)dsa->internal; + + if (SetIndividualExternal(&dsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa q key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dsa->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dsa->pub_key, &key->y) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa y key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dsa->priv_key, &key->x) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa x key error"); + return SSL_FATAL_ERROR; + } + + dsa->exSet = 1; + + return SSL_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 SSL_FATAL_ERROR; + } + + key = (DsaKey*)dsa->internal; + + if (dsa->p != NULL && + SetIndividualInternal(dsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return SSL_FATAL_ERROR; + } + + if (dsa->q != NULL && + SetIndividualInternal(dsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return SSL_FATAL_ERROR; + } + + if (dsa->g != NULL && + SetIndividualInternal(dsa->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa g key error"); + return SSL_FATAL_ERROR; + } + + if (dsa->pub_key != NULL) { + if (SetIndividualInternal(dsa->pub_key, &key->y) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa pub_key error"); + return SSL_FATAL_ERROR; + } + + /* public key */ + key->type = DSA_PUBLIC; + } + + if (dsa->priv_key != NULL) { + if (SetIndividualInternal(dsa->priv_key, &key->x) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa priv_key error"); + return SSL_FATAL_ERROR; + } + + /* private key */ + key->type = DSA_PRIVATE; + } + + dsa->inSet = 1; + + return SSL_SUCCESS; +} +#endif /* NO_DSA */ + + +#if !defined(NO_RSA) +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) +/* 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 SSL_FATAL_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualExternal(&rsa->n, &key->n) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa n key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->e, &key->e) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa e key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->d, &key->d) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa d key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->dmp1, &key->dP) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa dP key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa dQ key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->iqmp, &key->u) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa u key error"); + return SSL_FATAL_ERROR; + } + + rsa->exSet = 1; + + return SSL_SUCCESS; +} + +/* 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 SSL_FATAL_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualInternal(rsa->n, &key->n) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa n key error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualInternal(rsa->e, &key->e) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa e key error"); + return SSL_FATAL_ERROR; + } + + /* public key */ + key->type = RSA_PUBLIC; + + if (rsa->d != NULL) { + if (SetIndividualInternal(rsa->d, &key->d) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa d key error"); + return SSL_FATAL_ERROR; + } + + /* private key */ + key->type = RSA_PRIVATE; + } + + if (rsa->p != NULL && + SetIndividualInternal(rsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return SSL_FATAL_ERROR; + } + + if (rsa->q != NULL && + SetIndividualInternal(rsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return SSL_FATAL_ERROR; + } + + if (rsa->dmp1 != NULL && + SetIndividualInternal(rsa->dmp1, &key->dP) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa dP key error"); + return SSL_FATAL_ERROR; + } + + if (rsa->dmq1 != NULL && + SetIndividualInternal(rsa->dmq1, &key->dQ) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa dQ key error"); + return SSL_FATAL_ERROR; + } + + if (rsa->iqmp != NULL && + SetIndividualInternal(rsa->iqmp, &key->u) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa u key error"); + return SSL_FATAL_ERROR; + } + + rsa->inSet = 1; + + return SSL_SUCCESS; +} +#endif /* HAVE_USER_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 = SSL_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 SSL_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_TMP_BUFFER); + if (rng == NULL) + return SSL_FAILURE; + #endif + + if (wc_InitRng(rng) < 0) + WOLFSSL_MSG("RNG init failed"); + else if (wc_MakeRsaKey((RsaKey*)rsa->internal, + bits, 65537, rng) != MP_OKAY) + WOLFSSL_MSG("wc_MakeRsaKey failed"); + else if (SetRsaExternal(rsa) != SSL_SUCCESS) + WOLFSSL_MSG("SetRsaExternal failed"); + else { + rsa->inSet = 1; + ret = SSL_SUCCESS; + } + + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } +#else + WOLFSSL_MSG("No Key Gen built in"); +#endif + return ret; +} + + +/* SSL_SUCCESS on ok */ +int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) +{ + (void)rsa; + (void)bn; + + WOLFSSL_MSG("wolfSSL_RSA_blinding_on"); + + return SSL_SUCCESS; /* on by default */ +} + +/* return compliant with OpenSSL + * size of encrypted data if success , -1 if error + */ +int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + (void)len; + (void)fr; + (void)to; + (void)rsa; + (void)padding; + + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt"); + + return SSL_FATAL_ERROR; +} + +/* return compliant with OpenSSL + * size of plain recovered data if success , -1 if error + */ +int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + (void)len; + (void)fr; + (void)to; + (void)rsa; + (void)padding; + + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt"); + + return SSL_FATAL_ERROR; +} + +/* return compliant with OpenSSL + * RSA modulus size in bytes, -1 if error + */ +int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) +{ + WOLFSSL_MSG("wolfSSL_RSA_size"); + + if (rsa == NULL) + return SSL_FATAL_ERROR; + + return wolfSSL_BN_num_bytes(rsa->n); +} +#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 = SSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_DSA_generate_key"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad arguments"); + return SSL_FAILURE; + } + + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != SSL_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_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_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) != SSL_SUCCESS) + WOLFSSL_MSG("SetDsaExternal failed"); + else + ret = SSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } +#else /* WOLFSSL_KEY_GEN */ + WOLFSSL_MSG("No Key Gen built in"); +#endif + return ret; +} + +/* 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 = SSL_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 SSL_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_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_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) != SSL_SUCCESS) + WOLFSSL_MSG("SetDsaExternal failed"); + else + ret = SSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } +#else /* WOLFSSL_KEY_GEN */ + WOLFSSL_MSG("No Key Gen built in"); +#endif + + return ret; +} + +/* return SSL_SUCCESS on success, < 0 otherwise */ +int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, + WOLFSSL_DSA* dsa) +{ + int ret = SSL_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) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return ret; + } + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_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 = SSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig, + WOLFSSL_DSA* dsa, int *dsacheck) +{ + int ret = SSL_FATAL_ERROR; + + WOLFSSL_ENTER("wolfSSL_DSA_do_verify"); + + if (d == NULL || sig == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FATAL_ERROR; + } + if (dsa->inSet == 0) + { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return SSL_FATAL_ERROR; + } + } + + ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck); + if (ret != 0 || *dsacheck != 1) { + WOLFSSL_MSG("DsaVerify failed"); + return ret; + } + + return SSL_SUCCESS; +} +#endif /* NO_DSA */ + + +#ifndef NO_RSA +/* 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) +{ + 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_MSG("wolfSSL_RSA_sign"); + + if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + 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) != SSL_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_TMP_BUFFER); + if (tmpRNG == NULL) + return 0; + + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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 { + *sigLen = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, + (RsaKey*)rsa->internal, rng); + if (*sigLen <= 0) + WOLFSSL_MSG("Bad Rsa Sign"); + else + ret = SSL_SUCCESS; + } + + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret == SSL_SUCCESS) + WOLFSSL_MSG("wolfSSL_RSA_sign success"); + else { + WOLFSSL_MSG("wolfSSL_RSA_sign failed"); + } + return ret; +} + + +int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + int tlen = 0; + + WOLFSSL_MSG("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) != SSL_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, SSL_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 SSL_FATAL_ERROR; + } + + if (mp_init(&tmp) != MP_OKAY) { + WOLFSSL_MSG("mp_init error"); + return SSL_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 SSL_SUCCESS; + else + return SSL_FATAL_ERROR; +} +#endif /* NO_RSA */ + + +void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, + const EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_HMAC_Init"); + + if (ctx == NULL) { + WOLFSSL_MSG("no ctx on init"); + return; + } + + if (type) { + WOLFSSL_MSG("init has type"); + + if (XSTRNCMP(type, "MD5", 3) == 0) { + WOLFSSL_MSG("md5 hmac"); + ctx->type = MD5; + } + else if (XSTRNCMP(type, "SHA256", 6) == 0) { + WOLFSSL_MSG("sha256 hmac"); + ctx->type = SHA256; + } + + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + WOLFSSL_MSG("sha hmac"); + ctx->type = SHA; + } + else { + WOLFSSL_MSG("bad init type"); + } + } + + if (key && keylen) { + WOLFSSL_MSG("keying hmac"); + wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, (word32)keylen); + /* OpenSSL compat, no error */ + } +} + + +void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, + int len) +{ + WOLFSSL_MSG("wolfSSL_HMAC_Update"); + + if (ctx && data) { + WOLFSSL_MSG("updating hmac"); + wc_HmacUpdate(&ctx->hmac, data, (word32)len); + /* OpenSSL compat, no error */ + } +} + + +void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, + unsigned int* len) +{ + WOLFSSL_MSG("wolfSSL_HMAC_Final"); + + if (ctx && hash) { + WOLFSSL_MSG("final hmac"); + wc_HmacFinal(&ctx->hmac, hash); + /* OpenSSL compat, no error */ + + if (len) { + WOLFSSL_MSG("setting output len"); + switch (ctx->type) { + case MD5: + *len = MD5_DIGEST_SIZE; + break; + + case SHA: + *len = SHA_DIGEST_SIZE; + break; + + case SHA256: + *len = SHA256_DIGEST_SIZE; + break; + + default: + WOLFSSL_MSG("bad hmac type"); + } + } + } +} + + +void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) +{ + (void)ctx; + + WOLFSSL_MSG("wolfSSL_HMAC_cleanup"); +} + + +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; +} + + +WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key) +{ + (void)key; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA not implemented"); + + return NULL; +} + + +WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) +{ + (void)key; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_DSA not implemented"); + + return NULL; +} + + +WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) +{ + (void)key; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_EC_KEY not implemented"); + + return NULL; +} + + +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) + wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */ + else + XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); +} + +#endif /* NO_AES */ + + +const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) +{ + WOLFSSL_MSG("wolfSSL_ripemd160"); + + return NULL; +} + + +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 SHA256_DIGEST_SIZE; + } +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + return MD5_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + return SHA384_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + return 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 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) { + + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + return AES_BLOCK_SIZE; + +#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 + + 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; +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + return IDEA_BLOCK_SIZE; +#endif + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + return 0; + + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + return 0; + + default: { + WOLFSSL_MSG("bad type"); + } + } + return 0; +} + + +void wolfSSL_OPENSSL_free(void* p) +{ + WOLFSSL_MSG("wolfSSL_OPENSSL_free"); + + XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); +} + +#if defined(WOLFSSL_KEY_GEN) + +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_TMP_BUFFER); + if (info == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_FAILURE; + } +#endif + info->set = 0; + info->ctx = NULL; + info->consumed = 0; + + /* set iv size */ + if (XSTRNCMP(cipher, "DES", 3) == 0) + info->ivSz = DES_IV_SIZE; + else if (XSTRNCMP(cipher, "AES", 3) == 0) + info->ivSz = AES_IV_SIZE; + else { + WOLFSSL_MSG("unsupported cipher"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_FAILURE; + } + + /* set the cipher name on info */ + XSTRNCPY(info->name, cipher, NAME_SZ); + + /* Generate a random salt */ + if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != SSL_SUCCESS) { + WOLFSSL_MSG("generate iv failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_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 (wolfssl_encrypt_buffer_key(der, *derSz, + passwd, passwdSz, info) != SSL_SUCCESS) { + WOLFSSL_MSG("encrypt key failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_FAILURE; + } + + /* create cipher info : 'cipher_name,Salt(hex)' */ + cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2); + *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (*cipherInfo == NULL) { + WOLFSSL_MSG("malloc failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_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_TMP_BUFFER); +#endif + if (ret != 0) { + WOLFSSL_MSG("Base16_Encode failed"); + XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} +#endif /* defined(WOLFSSL_KEY_GEN) */ + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) + +/* 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; + + WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey"); + + if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FAILURE; + } + + if (rsa->inSet == 0) { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return SSL_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_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_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_TMP_BUFFER); + return SSL_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 != SSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_RSA_PRIV) + + sizeof(END_RSA_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; + } + else /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_RSA_PRIV) + sizeof(END_RSA_PRIV); + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, PRIVATEKEY_TYPE); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + if (*pem == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_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_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return SSL_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 SSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed"); + return SSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("RSA private key file write failed"); + return SSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return SSL_SUCCESS; +} +#endif /* NO_FILESYSTEM */ + +int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb cb, void* arg) +{ + (void)bio; + (void)rsa; + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + + WOLFSSL_MSG("wolfSSL_PEM_write_bio_RSAPrivateKey not implemented"); + + return SSL_FAILURE; +} +#endif /* defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) */ + +#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 SSL_FATAL_ERROR; + } + + point = (ecc_point*)p->internal; + + if (p->X != NULL && SetIndividualInternal(p->X, point->x) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return SSL_FATAL_ERROR; + } + + if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return SSL_FATAL_ERROR; + } + + if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return SSL_FATAL_ERROR; + } + + p->inSet = 1; + + return SSL_SUCCESS; +} + +/* 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 SSL_FATAL_ERROR; + } + + point = (ecc_point*)p->internal; + + if (SetIndividualExternal(&p->X, point->x) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&p->Y, point->y) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return SSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&p->Z, point->z) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return SSL_FATAL_ERROR; + } + + p->exSet = 1; + + return SSL_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 SSL_FATAL_ERROR; + } + + key = (ecc_key*)eckey->internal; + + /* set group (nid and idx) */ + eckey->group->curve_nid = ecc_sets[key->idx].nid; + 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 SSL_FATAL_ERROR; + } + + /* set the external pubkey (point) */ + if (SetECPointExternal(eckey->pub_key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed"); + return SSL_FATAL_ERROR; + } + } + + /* set the external privkey */ + if (key->type == ECC_PRIVATEKEY) { + if (SetIndividualExternal(&eckey->priv_key, &key->k) != SSL_SUCCESS) { + WOLFSSL_MSG("ec priv key error"); + return SSL_FATAL_ERROR; + } + } + + eckey->exSet = 1; + + return SSL_SUCCESS; +} + +/* 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 SSL_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 SSL_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) != SSL_SUCCESS) { + WOLFSSL_MSG("ec key pub error"); + return SSL_FATAL_ERROR; + } + + /* public key */ + key->type = ECC_PUBLICKEY; + } + + /* set privkey */ + if (eckey->priv_key != NULL) { + if (SetIndividualInternal(eckey->priv_key, &key->k) != SSL_SUCCESS) { + WOLFSSL_MSG("ec key priv error"); + return SSL_FATAL_ERROR; + } + + /* private key */ + key->type = ECC_PRIVATEKEY; + } + + eckey->inSet = 1; + + return SSL_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 SSL_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 SSL_FAILURE; + } + + if (SetECKeyInternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + wolfSSL_BN_free(key->priv_key); + return SSL_FAILURE; + } + + return SSL_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].nid == key->group->curve_nid) { + key->group->curve_idx = x; + break; + } + + return key; +} + +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 = (ecc_point*)&key->pubkey; + + /* 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; + } +} + +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_MSG("wolfSSL_EC_KEY_set_group TBD"); + + return -1; +} + +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_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 (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; + } + + if (wc_ecc_make_key(rng, ecc_sets[key->group->curve_idx].size, + (ecc_key*)key->internal) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (SetECKeyExternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); + return 0; + } + + return 1; +} + +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_MSG("wolfSSL_EC_KEY_set_asn1_flag TBD"); +} + +/* 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 SSL_FAILURE; + } + + if (key->inSet == 0) { + if (SetECKeyInternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return SSL_FAILURE; + } + } + + if (pub->inSet == 0) { + if (SetECPointInternal((WOLFSSL_EC_POINT *)pub) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return SSL_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 SSL_FAILURE; + } + + if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) { + WOLFSSL_MSG("ecc_copy_point failure"); + return SSL_FAILURE; + } + + if (SetECKeyExternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return SSL_FAILURE; + } + +#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) + wolfssl_EC_POINT_dump("pub", pub); + wolfssl_EC_POINT_dump("key->pub_key", key->pub_key); +#endif + return SSL_SUCCESS; +} +/* End EC_KEY */ + +#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) +void wolfssl_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p) +{ + char *num; + + WOLFSSL_ENTER("wolfssl_EC_POINT_dump"); + + if (p == NULL) { + fprintf(stderr, "%s = NULL", msg); + return ; + } + + fprintf(stderr, "%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet); + num = wolfSSL_BN_bn2hex(p->X); + fprintf(stderr, "\tX = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); + num = wolfSSL_BN_bn2hex(p->Y); + fprintf(stderr, "\tY = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); +} +#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 SSL_FATAL_ERROR; + } + + /* ok */ + if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid)) + return 0; + + /* ko */ + return 1; +} + +void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group) +{ + WOLFSSL_ENTER("wolfSSL_EC_GROUP_free"); + + XFREE(group, NULL, DYNAMIC_TYPE_ECC); + group = NULL; +} + +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_MSG("wolfSSL_EC_GROUP_set_asn1_flag TBD"); +} + +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].nid == g->curve_nid) { + g->curve_idx = x; + 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 SSL_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 SSL_FAILURE; + } + + switch(group->curve_nid) { + case NID_X9_62_prime256v1: + return 256; + break; + case NID_secp384r1: + return 384; + break; + case NID_secp521r1: + return 521; + break; + default : + return SSL_FAILURE; + break; + } +} + +/* 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 SSL_FAILURE; + } + + if (mp_init((mp_int*)order->internal) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure"); + return SSL_FAILURE; + } + + if (mp_read_radix((mp_int*)order->internal, + ecc_sets[group->curve_idx].order, 16) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure"); + mp_clear((mp_int*)order->internal); + return SSL_FAILURE; + } + + return SSL_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 SSL_FAILURE; + } + + if (p->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed"); + return SSL_FAILURE; + } + } + +#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) + if (out != NULL) { + wolfssl_EC_POINT_dump("i2d p", p); + } +#endif + 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 SSL_FAILURE; + } + + return SSL_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 SSL_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 SSL_FAILURE; + } + + if (p->exSet == 0) { + WOLFSSL_MSG("No ECPoint external set, do it"); + + if (SetECPointExternal(p) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointExternal failed"); + return SSL_FAILURE; + } + } + +#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) + wolfssl_EC_POINT_dump("d2i p", p); +#endif + return SSL_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 SSL_FAILURE; + } + + if (point->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return SSL_FAILURE; + } + } + + BN_copy(x, point->X); + BN_copy(y, point->Y); + + return SSL_SUCCESS; +} + +/* 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 prime; + + (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 SSL_FAILURE; + } + + if (q->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return SSL_FAILURE; + } + } + + /* compute the prime value of the curve */ + if (mp_init(&prime) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_POINT_mul init BN failed"); + return SSL_FAILURE; + } + + if (mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, 16) != MP_OKAY){ + WOLFSSL_MSG("wolfSSL_EC_POINT_mul read prime curve value failed"); + return SSL_FAILURE; + } + + /* r = q * m % prime */ + if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, + (ecc_point*)r->internal, &prime, 1) != MP_OKAY) { + WOLFSSL_MSG("ecc_mulmod failure"); + mp_clear(&prime); + return SSL_FAILURE; + } + + mp_clear(&prime); + + /* set the external value for the computed point */ + if (SetECPointInternal(r) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} + +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 SSL_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 SSL_FATAL_ERROR; +} + +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); + XFREE(p->internal, NULL, DYNAMIC_TYPE_ECC); + 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; + } +} + +/* 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 SSL_FAILURE; + } + if (point->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return SSL_FAILURE; + } + } + + ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal); + if (ret <= 0) { + WOLFSSL_MSG("ecc_point_is_at_infinity failure"); + return SSL_FAILURE; + } + + return SSL_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) != SSL_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_TMP_BUFFER); + 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)!=SSL_SUCCESS){ + WOLFSSL_MSG("ecdsa r key error"); + wolfSSL_ECDSA_SIG_free(sig); + sig = NULL; + } + else if (SetIndividualExternal(&(sig->s), &sig_s)!=SSL_SUCCESS){ + WOLFSSL_MSG("ecdsa s key error"); + wolfSSL_ECDSA_SIG_free(sig); + sig = NULL; + } + + mp_clear(&sig_r); + mp_clear(&sig_s); + } + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#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 SSL_FATAL_ERROR; + } + + /* set internal key if not done */ + if (key->inSet == 0) + { + WOLFSSL_MSG("No EC key internal set, do it"); + + if (SetECKeyInternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return SSL_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 SSL_FATAL_ERROR; + } + else if (check_sign == 0) { + WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); + return SSL_FAILURE; + } + + return SSL_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 SSL_FATAL_ERROR; + } + + /* set internal key if not done */ + if (ecdh->inSet == 0) + { + WOLFSSL_MSG("No EC key internal set, do it"); + + if (SetECKeyInternal(ecdh) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return SSL_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 SSL_FATAL_ERROR; + } + + return len; +} +/* End ECDH */ + +#if !defined(NO_FILESYSTEM) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *x) +{ + (void)fp; + (void)x; + + WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented"); + + return SSL_FAILURE; +} +#endif /* NO_FILESYSTEM */ + +#if defined(WOLFSSL_KEY_GEN) + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +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_MSG("wolfSSL_PEM_write_bio_ECPrivateKey not implemented"); + + return SSL_FAILURE; +} + +/* 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) +{ + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + + WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey"); + + if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FAILURE; + } + + if (ecc->inSet == 0) { + WOLFSSL_MSG("No ECC internal set, do it"); + + if (SetECKeyInternal(ecc) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return SSL_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_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_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_TMP_BUFFER); + return SSL_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 != SSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_EC_PRIV) + + sizeof(END_EC_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; + } + else /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_EC_PRIV) + sizeof(END_EC_PRIV); + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, ECC_PRIVATEKEY_TYPE); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + if (*pem == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_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_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return SSL_SUCCESS; +} + +#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 SSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed"); + return SSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("ECC private key file write failed"); + return SSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return SSL_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 SSL_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) +{ + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + + WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey"); + + if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FAILURE; + } + + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return SSL_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_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_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_TMP_BUFFER); + return SSL_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 != SSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_DSA_PRIV) + + sizeof(END_DSA_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; + } + else /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_DSA_PRIV) + sizeof(END_DSA_PRIV); + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, DSA_PRIVATEKEY_TYPE); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + if (*pem == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_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_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return SSL_SUCCESS; +} + +#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 SSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed"); + return SSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("DSA private key file write failed"); + return SSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return SSL_SUCCESS; +} + +#endif /* NO_FILESYSTEM */ +#endif /* defined(WOLFSSL_KEY_GEN) */ + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x) +{ + (void)fp; + (void)x; + + WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented"); + + return SSL_FAILURE; +} +#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* arg) +{ + (void)bio; + (void)key; + (void)cb; + (void)arg; + + WOLFSSL_MSG("wolfSSL_PEM_read_bio_PrivateKey not implemented"); + + return NULL; +} + + +int wolfSSL_EVP_PKEY_type(int type) +{ + (void)type; + + WOLFSSL_MSG("wolfSSL_EVP_PKEY_type not implemented"); + + return SSL_FATAL_ERROR; +} + + +#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) +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_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented"); + + return NULL; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_RSAPublicKey(FILE *fp, WOLFSSL_RSA *x) +{ + (void)fp; + (void)x; + + WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented"); + + return SSL_FAILURE; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_RSA_PUBKEY(FILE *fp, WOLFSSL_RSA *x) +{ + (void)fp; + (void)x; + + WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented"); + + return SSL_FAILURE; +} +#endif /* NO_FILESYSTEM */ + +/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ +int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz) +{ + 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 SSL_FATAL_ERROR; + } + + ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); + if (ret < 0) { + WOLFSSL_MSG("RsaPrivateKeyDecode failed"); + return SSL_FATAL_ERROR; + } + + if (SetRsaExternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaExternal failed"); + return SSL_FATAL_ERROR; + } + + rsa->inSet = 1; + + return SSL_SUCCESS; +} +#endif /* NO_RSA */ + + +#ifndef NO_DSA +/* return SSL_SUCCESS if success, SSL_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 SSL_FATAL_ERROR; + } + + ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz); + if (ret < 0) { + WOLFSSL_MSG("DsaPrivateKeyDecode failed"); + return SSL_FATAL_ERROR; + } + + if (SetDsaExternal(dsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaExternal failed"); + return SSL_FATAL_ERROR; + } + + dsa->inSet = 1; + + return SSL_SUCCESS; +} +#endif /* NO_DSA */ + +#ifdef HAVE_ECC +/* return SSL_SUCCESS if success, SSL_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 SSL_FATAL_ERROR; + } + + ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, derSz); + if (ret < 0) { + WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); + return SSL_FATAL_ERROR; + } + + if (SetECKeyExternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal failed"); + return SSL_FATAL_ERROR; + } + + key->inSet = 1; + + return SSL_SUCCESS; +} +#endif /* HAVE_ECC */ + +#endif /* OPENSSL_EXTRA */ + + +#ifdef SESSION_CERTS + + +/* 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_TMP_BUFFER); + 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); + + 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_TMP_BUFFER); + #endif + } + } + + 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 SSL_SUCCESS on ok */ +int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, + unsigned char* buf, int inLen, int* outLen) +{ + const char header[] = "-----BEGIN CERTIFICATE-----\n"; + const char footer[] = "-----END CERTIFICATE-----\n"; + + int headerLen = sizeof(header) - 1; + int footerLen = sizeof(footer) - 1; + 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; + + /* 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 SSL_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 SSL_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 SSL_FATAL_ERROR; + *outLen += headerLen + footerLen; + + return SSL_SUCCESS; +} + + +/* 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_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; +} + +#endif /* HAVE_ECC */ + +#ifndef NO_RSA + +void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) +{ + if (ctx) + ctx->RsaSignCb = 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; +} + +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 */ + + +#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*/ +#ifdef HAVE_LIGHTY + + unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md) + { + (void) *d; (void) n; (void) *md; + WOLFSSL_ENTER("wolfSSL_SHA1"); + WOLFSSL_STUB("wolfssl_SHA1"); + + return NULL; + } + + char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) { + (void)ctx; + (void)x; + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); + WOLFSSL_STUB("wolfSSL_CTX_use_certificate"); + + return 0; + } + + int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) { + (void)ctx; + (void)pkey; + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); + WOLFSSL_STUB("wolfSSL_CTX_use_PrivateKey"); + + return 0; + } + + + int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { + (void)b; + (void)name; + WOLFSSL_ENTER("wolfSSL_BIO_read_filename"); + WOLFSSL_STUB("wolfSSL_BIO_read_filename"); + + return 0; + } + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) { + WOLFSSL_ENTER("wolfSSL_BIO_s_file"); + WOLFSSL_STUB("wolfSSL_BIO_s_file"); + + return NULL; + } + + const char * wolf_OBJ_nid2sn(int n) { + (void)n; + WOLFSSL_ENTER("wolf_OBJ_nid2sn"); + WOLFSSL_STUB("wolf_OBJ_nid2sn"); + + return 0; + } + + int wolf_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) { + (void)o; + WOLFSSL_ENTER("wolf_OBJ_obj2nid"); + WOLFSSL_STUB("wolf_OBJ_obj2nid"); + + return 0; + } + + int wolf_OBJ_sn2nid(const char *sn) { + (void)sn; + WOLFSSL_ENTER("wolf_OBJ_osn2nid"); + WOLFSSL_STUB("wolf_OBJ_osn2nid"); + + return 0; + } + + + WOLFSSL_X509 *PEM_read_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u) { + (void)bp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_ENTER("PEM_read_bio_WOLFSSL_X509"); + WOLFSSL_STUB("PEM_read_bio_WOLFSSL_X509"); + + return NULL; + } + + void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { + (void)ctx; + (void)depth; + WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); + WOLFSSL_STUB("wolfSSL_CTX_set_verify_depth"); + + } + + void* wolfSSL_get_app_data( const WOLFSSL *ssl) + { + /* checkout exdata stuff... */ + (void)ssl; + WOLFSSL_ENTER("wolfSSL_get_app_data"); + WOLFSSL_STUB("wolfSSL_get_app_data"); + + return 0; + } + + void wolfSSL_set_app_data(WOLFSSL *ssl, void *arg) { + (void)ssl; + (void)arg; + WOLFSSL_ENTER("wolfSSL_set_app_data"); + WOLFSSL_STUB("wolfSSL_set_app_data"); + } + + 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("wolfSSL_X509_NAME_ENTRY_get_object"); + + return NULL; + } + + WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc) { + (void)name; + (void)loc; + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry"); + WOLFSSL_STUB("wolfSSL_X509_NAME_get_entry"); + + return NULL; + } + + void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ + FreeX509Name(name); + WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); + WOLFSSL_STUB("wolfSSL_X509_NAME_free"); + } + + void wolfSSL_sk_X509_NAME_pop_free(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("wolfSSL_sk_X509_NAME_pop_free"); + } + + 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("wolfSSL_X509_check_private_key"); + + return SSL_SUCCESS; + } + + STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X509_NAME) *sk ){ + (void) sk; + WOLFSSL_ENTER("wolfSSL_dup_CA_list"); + WOLFSSL_STUB("wolfSSL_dup_CA_list"); + + return NULL; + } + +#endif +#endif + + +#ifdef OPENSSL_EXTRA +void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); + #ifdef HAVE_STUNNEL + 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) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); + (void)idx; + (void)arg; + (void)a; + (void)b; + (void)c; + return 0; +} + + +int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); + #ifdef HAVE_STUNNEL + if (ctx != NULL && idx < MAX_EX_DATA) + { + ctx->ex_data[idx] = data; + return SSL_SUCCESS; + } + #else + (void)ctx; + (void)idx; + (void)data; + #endif + return SSL_FAILURE; +} + + +int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_set_ex_data"); +#if defined(FORTRESS) || defined(HAVE_STUNNEL) + if (ssl != NULL && idx < MAX_EX_DATA) + { + ssl->ex_data[idx] = data; + return SSL_SUCCESS; + } +#else + (void)ssl; + (void)idx; + (void)data; +#endif + return SSL_FAILURE; +} + + +int wolfSSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, + void* cb3) +{ + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); + (void)idx; + (void)data; + (void)cb1; + (void)cb2; + (void)cb3; + return 0; +} + + +void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) +{ + WOLFSSL_ENTER("wolfSSL_get_ex_data"); +#if defined(FORTRESS) || defined(HAVE_STUNNEL) + if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0) + return ssl->ex_data[idx]; +#else + (void)ssl; + (void)idx; +#endif + return 0; +} +#endif /* OPENSSL_EXTRA */ + + +#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) +char * wolf_OBJ_nid2ln(int n) { + (void)n; + WOLFSSL_ENTER("wolf_OBJ_nid2ln"); + WOLFSSL_STUB("wolf_OBJ_nid2ln"); + + return NULL; +} + +int wolf_OBJ_txt2nid(const char* s) { + (void)s; + WOLFSSL_ENTER("wolf_OBJ_txt2nid"); + WOLFSSL_STUB("wolf_OBJ_txt2nid"); + + return 0; +} + + +WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) { + (void)filename; + (void)mode; + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + WOLFSSL_STUB("wolfSSL_BIO_new_file"); + + return NULL; +} + + +WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, WOLFSSL_DH **x, pem_password_cb *cb, void *u) +{ + (void) bp; + (void) x; + (void) cb; + (void) u; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams"); + WOLFSSL_STUB("wolfSSL_PEM_read_bio_DHparams"); + + return NULL; +} + +int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) { + (void)bp; + (void)x; + WOLFSSL_ENTER("PEM_write_bio_WOLFSSL_X509"); + WOLFSSL_STUB("PEM_write_bio_WOLFSSL_X509"); + + return 0; +} + + +#ifndef NO_DH +/* Intialize ctx->dh with dh's params. Return SSL_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 SSL_FATAL_ERROR; + + p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH); + if(!p) + return MEMORY_E; + + g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH); + if(!g) { + XFREE(p, ctx->heap, DYNAMIC_TYPE_DH); + 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_DH); + XFREE(g, ctx->heap, DYNAMIC_TYPE_DH); + + return pSz > 0 && gSz > 0 ? ret : SSL_FATAL_ERROR; +} +#endif /* NO_DH */ +#endif /* HAVE_LIGHTY || HAVE_STUNNEL */ + + +/* stunnel compatibility functions*/ +#if defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL) +void WOLFSSL_ERR_remove_thread_state(void* pid) +{ + (void) pid; + return; +} + + +int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); + if(session != NULL && idx < MAX_EX_DATA) { + session->ex_data[idx] = data; + return SSL_SUCCESS; + } + return SSL_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 SSL_FAILURE; +} + + +void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); + if (session != NULL && idx < MAX_EX_DATA && idx >= 0) + return session->ex_data[idx]; + return NULL; +} + + +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("wolfSSL_CRYPTO_set_mem_ex_functions"); + + return SSL_FAILURE; +} + + +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("wolfSSL_DH_generate_parameters"); + + return NULL; +} + +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("wolfSSL_DH_generate_parameters_ex"); + + return -1; +} + + +void wolfSSL_ERR_load_crypto_strings(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); + WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); + return; +} + + +unsigned long wolfSSL_ERR_peek_last_error(void) +{ + unsigned long l = 0UL; + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); + WOLFSSL_STUB("wolfSSL_ERR_peek_last_error"); + + return l; +} + + +int wolfSSL_FIPS_mode(void) +{ + WOLFSSL_ENTER("wolfSSL_FIPS_mode"); + WOLFSSL_STUB("wolfSSL_FIPS_mode"); + + return SSL_FAILURE; +} + +int wolfSSL_FIPS_mode_set(int r) +{ + (void)r; + WOLFSSL_ENTER("wolfSSL_FIPS_mode_set"); + WOLFSSL_STUB("wolfSSL_FIPS_mode_set"); + + return SSL_FAILURE; +} + + +int wolfSSL_RAND_set_rand_method(const void *meth) +{ + (void) meth; + WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method"); + WOLFSSL_STUB("wolfSSL_RAND_set_rand_method"); + + return SSL_FAILURE; +} + + +int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) +{ + int ret = SSL_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 STACK_OF(WOLFSSL_X509_NAME) *s) +{ + (void) s; + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); + WOLFSSL_STUB("wolfSSL_sk_X509_NAME_num"); + + return SSL_FAILURE; +} + + +int wolfSSL_sk_X509_num(const STACK_OF(WOLFSSL_X509) *s) +{ + (void) s; + WOLFSSL_ENTER("wolfSSL_sk_X509_num"); + WOLFSSL_STUB("wolfSSL_sk_X509_num"); + + return SSL_FAILURE; +} + + +int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* nm, + int indent, unsigned long flags) +{ + (void)bio; + (void)nm; + (void)indent; + (void)flags; + WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex"); + WOLFSSL_STUB("wolfSSL_X509_NAME_print_ex"); + + return SSL_FAILURE; +} + + +WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x) +{ + (void)x; + WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr"); + WOLFSSL_STUB("wolfSSL_X509_get0_pubkey_bitstr"); + + return NULL; +} + + +int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + (void)ctx; + (void)session; + WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + WOLFSSL_STUB("wolfSSL_CTX_add_session"); + + return SSL_SUCCESS; +} + + +int wolfSSL_get_state(const WOLFSSL* ssl) +{ + (void)ssl; + WOLFSSL_ENTER("wolfSSL_get_state"); + WOLFSSL_STUB("wolfSSL_get_state"); + + return SSL_FAILURE; +} + + +void* wolfSSL_sk_X509_NAME_value(STACK_OF(WOLFSSL_X509_NAME)* sk, int i) +{ + (void)sk; + (void)i; + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); + WOLFSSL_STUB("wolfSSL_sk_X509_NAME_value"); + + return NULL; +} + + +void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i) +{ + (void)sk; + (void)i; + WOLFSSL_ENTER("wolfSSL_sk_X509_value"); + WOLFSSL_STUB("wolfSSL_sk_X509_value"); + + return NULL; +} + + +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 : + return TLS1_VERSION; + default: + return SSL_FAILURE; + } + } + else if (ssl->version.major == DTLS_MAJOR) { + switch (ssl->version.minor) { + case DTLS_MINOR : + case DTLSv1_2_MINOR : + return DTLS1_VERSION; + default: + return SSL_FAILURE; + } + } + return SSL_FAILURE; +} + + +STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) +{ + (void)ssl; + WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); + WOLFSSL_STUB("wolfSSL_get_peer_cert_chain"); + + return NULL; +} + + +long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) +{ + (void)ctx; + WOLFSSL_ENTER("wolfSSL_CTX_get_options"); + WOLFSSL_STUB("wolfSSL_CTX_get_options"); + + return 0; +} + + +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; +} + + +const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); + WOLFSSL_STUB("wolfSSL_SESSION_get_id"); + if(!sess || !idLen) { + WOLFSSL_MSG("Bad func args. Please provide idLen"); + return NULL; + } + *idLen = sess->sessionIDSz; + return sess->sessionID; +} + +#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, XSTRLEN(host_name)); + WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret); + return ret; +} + + +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 /* HAVE_SNI */ + + +WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +{ + if (ssl && ctx && SetSSL_CTX(ssl, ctx) == SSL_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; +} + + +void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg"); + if (ctx) + ctx->sniRecvCbArg = arg; +} + + +long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt) +{ + WOLFSSL_ENTER("SSL_CTX_clear_options"); + WOLFSSL_STUB("SSL_CTX_clear_options"); + (void)ctx; + (void)opt; + return opt; +} + +void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*)) +{ + WOLFSSL_ENTER("wolfSSL_THREADID_set_callback"); + WOLFSSL_STUB("wolfSSL_THREADID_set_callback"); + (void)threadid_func; + return; +} + +void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) +{ + WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric"); + WOLFSSL_STUB("wolfSSL_THREADID_set_numeric"); + (void)id; + (void)val; + return; +} + + +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("wolfSSL_X509_STORE_get1_certs"); + (void)ctx; + (void)name; + return NULL; +} + +void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)){ + (void) sk; + (void) f; + WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free"); + WOLFSSL_STUB("wolfSSL_sk_X509_pop_free"); +} + +#endif /* OPENSSL_EXTRA and HAVE_STUNNEL */ + + +#if (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) +int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx) +{ + int mode = 0; + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode"); + + if(!ctx) + return SSL_FATAL_ERROR; + + if (ctx->verifyPeer) + mode |= SSL_VERIFY_PEER; + else if (ctx->verifyNone) + mode |= SSL_VERIFY_NONE; + + if (ctx->failNoCert) + mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + + if (ctx->failNoCertxPSK) + mode |= SSL_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 SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = SSL_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 SSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_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 = SSL_SUCCESS; + + wc_curve25519_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#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 SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = SSL_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 SSL_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 = SSL_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 SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = SSL_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 SSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_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 = SSL_SUCCESS; + + wc_ed25519_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#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 SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed25519_key key; + int ret = SSL_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 SSL_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 = SSL_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 SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed25519_key key; + int ret = SSL_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 SSL_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 = SSL_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 SSL_SUCCESS; + } + return SSL_FAILURE; +} + +void* wolfSSL_get_jobject(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_jobject"); + if (ssl != NULL) + return ssl->jObjectRef; + return NULL; +} + +#endif /* WOLFSSL_JNI */ + +#endif /* WOLFCRYPT_ONLY */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tls.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,4723 @@ +/* tls.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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/ssl.h> +#include <wolfssl/internal.h> +#include <wolfssl/error-ssl.h> +#include <wolfssl/wolfcrypt/hmac.h> +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" + #include <wolfssl/wolfcrypt/random.h> +#endif +#ifdef HAVE_QSH + static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key); + static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name); + static int TLSX_CreateNtruKey(WOLFSSL* ssl, int type); +#endif + + +#ifndef NO_TLS + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +#ifdef WOLFSSL_SHA384 + #define P_HASH_MAX_SIZE SHA384_DIGEST_SIZE +#else + #define P_HASH_MAX_SIZE SHA256_DIGEST_SIZE +#endif + +/* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ +static int p_hash(byte* result, word32 resLen, const byte* secret, + word32 secLen, const byte* seed, word32 seedLen, int hash) +{ + word32 len = P_HASH_MAX_SIZE; + word32 times; + word32 lastLen; + word32 lastTime; + word32 i; + word32 idx = 0; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* previous; + byte* current; + Hmac* hmac; +#else + byte previous[P_HASH_MAX_SIZE]; /* max size */ + byte current[P_HASH_MAX_SIZE]; /* max size */ + Hmac hmac[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + current = (byte*)XMALLOC(P_HASH_MAX_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (previous == NULL || current == NULL || hmac == NULL) { + if (previous) XFREE(previous, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (current) XFREE(current, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hmac) XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return MEMORY_E; + } +#endif + + switch (hash) { + #ifndef NO_MD5 + case md5_mac: + hash = MD5; + len = MD5_DIGEST_SIZE; + break; + #endif + + #ifndef NO_SHA256 + case sha256_mac: + hash = SHA256; + len = SHA256_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hash = SHA384; + len = SHA384_DIGEST_SIZE; + break; + #endif + + #ifndef NO_SHA + case sha_mac: + default: + hash = SHA; + len = SHA_DIGEST_SIZE; + break; + #endif + } + + times = resLen / len; + lastLen = resLen % len; + + if (lastLen) + times += 1; + + lastTime = times - 1; + + if ((ret = wc_HmacSetKey(hmac, hash, secret, secLen)) == 0) { + if ((ret = wc_HmacUpdate(hmac, seed, seedLen)) == 0) { /* A0 = seed */ + if ((ret = wc_HmacFinal(hmac, previous)) == 0) { /* A1 */ + for (i = 0; i < times; i++) { + ret = wc_HmacUpdate(hmac, previous, len); + if (ret != 0) + break; + ret = wc_HmacUpdate(hmac, seed, seedLen); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, current); + if (ret != 0) + break; + + if ((i == lastTime) && lastLen) + XMEMCPY(&result[idx], current, + min(lastLen, P_HASH_MAX_SIZE)); + else { + XMEMCPY(&result[idx], current, len); + idx += len; + ret = wc_HmacUpdate(hmac, previous, len); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, previous); + if (ret != 0) + break; + } + } + } + } + } + + ForceZero(previous, P_HASH_MAX_SIZE); + ForceZero(current, P_HASH_MAX_SIZE); + ForceZero(hmac, sizeof(Hmac)); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(previous, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(current, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#undef P_HASH_MAX_SIZE + + +#ifndef NO_OLD_TLS + +/* calculate XOR for TLSv1 PRF */ +static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha) +{ + word32 i; + + for (i = 0; i < digLen; i++) + digest[i] = md5[i] ^ sha[i]; +} + + +/* compute TLSv1 PRF (pseudo random function using HMAC) */ +static int doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, + const byte* label, word32 labLen, const byte* seed, + word32 seedLen) +{ + int ret = 0; + word32 half = (secLen + 1) / 2; + +#ifdef WOLFSSL_SMALL_STACK + byte* md5_half; + byte* sha_half; + byte* labelSeed; + byte* md5_result; + byte* sha_result; +#else + byte md5_half[MAX_PRF_HALF]; /* half is real size */ + byte sha_half[MAX_PRF_HALF]; /* half is real size */ + byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ + byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ + byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ +#endif + + if (half > MAX_PRF_HALF) + return BUFFER_E; + if (labLen + seedLen > MAX_PRF_LABSEED) + return BUFFER_E; + if (digLen > MAX_PRF_DIG) + return BUFFER_E; + +#ifdef WOLFSSL_SMALL_STACK + md5_half = (byte*)XMALLOC(MAX_PRF_HALF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha_half = (byte*)XMALLOC(MAX_PRF_HALF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + labelSeed = (byte*)XMALLOC(MAX_PRF_LABSEED, NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5_result = (byte*)XMALLOC(MAX_PRF_DIG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha_result = (byte*)XMALLOC(MAX_PRF_DIG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (md5_half == NULL || sha_half == NULL || labelSeed == NULL || + md5_result == NULL || sha_result == NULL) { + if (md5_half) XFREE(md5_half, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha_half) XFREE(sha_half, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (labelSeed) XFREE(labelSeed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5_result) XFREE(md5_result, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha_result) XFREE(sha_result, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return MEMORY_E; + } +#endif + + XMEMSET(md5_result, 0, digLen); + XMEMSET(sha_result, 0, digLen); + + XMEMCPY(md5_half, secret, half); + XMEMCPY(sha_half, secret + half - secLen % 2, half); + + XMEMCPY(labelSeed, label, labLen); + XMEMCPY(labelSeed + labLen, seed, seedLen); + + if ((ret = p_hash(md5_result, digLen, md5_half, half, labelSeed, + labLen + seedLen, md5_mac)) == 0) { + if ((ret = p_hash(sha_result, digLen, sha_half, half, labelSeed, + labLen + seedLen, sha_mac)) == 0) { + get_xor(digest, digLen, md5_result, sha_result); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5_half, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha_half, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(labelSeed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5_result, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha_result, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif + + +/* Wrapper to call straight thru to p_hash in TSL 1.2 cases to remove stack + use */ +static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, + const byte* label, word32 labLen, const byte* seed, word32 seedLen, + int useAtLeastSha256, int hash_type) +{ + int ret = 0; + + if (useAtLeastSha256) { +#ifdef WOLFSSL_SMALL_STACK + byte* labelSeed; +#else + byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ +#endif + + if (labLen + seedLen > MAX_PRF_LABSEED) + return BUFFER_E; + +#ifdef WOLFSSL_SMALL_STACK + labelSeed = (byte*)XMALLOC(MAX_PRF_LABSEED, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (labelSeed == NULL) + return MEMORY_E; +#endif + + XMEMCPY(labelSeed, label, labLen); + XMEMCPY(labelSeed + labLen, seed, seedLen); + + /* If a cipher suite wants an algorithm better than sha256, it + * should use better. */ + if (hash_type < sha256_mac || hash_type == blake2b_mac) + hash_type = sha256_mac; + ret = p_hash(digest, digLen, secret, secLen, labelSeed, + labLen + seedLen, hash_type); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(labelSeed, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } +#ifndef NO_OLD_TLS + else { + ret = doPRF(digest, digLen, secret, secLen, label, labLen, seed, + seedLen); + } +#endif + + return ret; +} + + +#ifdef WOLFSSL_SHA384 + #define HSHASH_SZ SHA384_DIGEST_SIZE +#else + #define HSHASH_SZ FINISHED_SZ +#endif + + +int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + const byte* side; + byte handshake_hash[HSHASH_SZ]; + word32 hashSz = FINISHED_SZ; + +#ifndef NO_OLD_TLS + wc_Md5GetHash(&ssl->hsHashes->hashMd5, handshake_hash); + wc_ShaGetHash(&ssl->hsHashes->hashSha, &handshake_hash[MD5_DIGEST_SIZE]); +#endif + + if (IsAtLeastTLSv1_2(ssl)) { +#ifndef NO_SHA256 + if (ssl->specs.mac_algorithm <= sha256_mac || ssl->specs.mac_algorithm == blake2b_mac) { + int ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,handshake_hash); + + if (ret != 0) + return ret; + + hashSz = SHA256_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + if (ssl->specs.mac_algorithm == sha384_mac) { + int ret = wc_Sha384Final(&ssl->hsHashes->hashSha384,handshake_hash); + + if (ret != 0) + return ret; + + hashSz = SHA384_DIGEST_SIZE; + } +#endif + } + + if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + side = tls_client; + else + side = tls_server; + + return PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, + SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); +} + + +#ifndef NO_OLD_TLS + +ProtocolVersion MakeTLSv1(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_MINOR; + + return pv; +} + + +ProtocolVersion MakeTLSv1_1(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_1_MINOR; + + return pv; +} + +#endif + + +ProtocolVersion MakeTLSv1_2(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_2_MINOR; + + return pv; +} + + +static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret"; +static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion"; + + +/* External facing wrapper so user can call as well, 0 on success */ +int wolfSSL_DeriveTlsKeys(byte* key_data, word32 keyLen, + const byte* ms, word32 msLen, + const byte* sr, const byte* cr, + int tls1_2, int hash_type) +{ + byte seed[SEED_LEN]; + + XMEMCPY(seed, sr, RAN_LEN); + XMEMCPY(seed + RAN_LEN, cr, RAN_LEN); + + return PRF(key_data, keyLen, ms, msLen, key_label, KEY_LABEL_SZ, + seed, SEED_LEN, tls1_2, hash_type); +} + + +int DeriveTlsKeys(WOLFSSL* ssl) +{ + int ret; + int length = 2 * ssl->specs.hash_size + + 2 * ssl->specs.key_size + + 2 * ssl->specs.iv_size; +#ifdef WOLFSSL_SMALL_STACK + byte* key_data; +#else + byte key_data[MAX_PRF_DIG]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + key_data = (byte*)XMALLOC(MAX_PRF_DIG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key_data == NULL) { + return MEMORY_E; + } +#endif + + ret = wolfSSL_DeriveTlsKeys(key_data, length, + ssl->arrays->masterSecret, SECRET_LEN, + ssl->arrays->serverRandom, ssl->arrays->clientRandom, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + if (ret == 0) + ret = StoreKeys(ssl, key_data); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +/* External facing wrapper so user can call as well, 0 on success */ +int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* cr, const byte* sr, + int tls1_2, int hash_type) +{ + byte seed[SEED_LEN]; + + XMEMCPY(seed, cr, RAN_LEN); + XMEMCPY(seed + RAN_LEN, sr, RAN_LEN); + + return PRF(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ, + seed, SEED_LEN, tls1_2, hash_type); +} + + +int MakeTlsMasterSecret(WOLFSSL* ssl) +{ + int ret; + + ret = wolfSSL_MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->arrays->clientRandom, ssl->arrays->serverRandom, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + + if (ret == 0) { + #ifdef SHOW_SECRETS + int i; + + printf("master secret: "); + for (i = 0; i < SECRET_LEN; i++) + printf("%02x", ssl->arrays->masterSecret[i]); + printf("\n"); + #endif + + ret = DeriveTlsKeys(ssl); + } + + return ret; +} + + +/* Used by EAP-TLS and EAP-TTLS to derive keying material from + * the master_secret. */ +int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len, + const char* label) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + byte* seed; +#else + byte seed[SEED_LEN]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + seed = (byte*)XMALLOC(SEED_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (seed == NULL) + return MEMORY_E; +#endif + + /* + * As per RFC-5281, the order of the client and server randoms is reversed + * from that used by the TLS protocol to derive keys. + */ + XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); + + ret = PRF((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN, + (const byte *)label, (word32)strlen(label), seed, SEED_LEN, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +/*** next for static INLINE s copied internal.c ***/ + +/* convert 16 bit integer to opaque */ +static INLINE void c16toa(word16 u16, byte* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} + +#ifdef HAVE_TLS_EXTENSIONS +/* convert opaque to 16 bit integer */ +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (c[0] << 8) | (c[1]); +} + +#if defined(HAVE_SNI) && !defined(NO_WOLFSSL_SERVER) +/* convert a 24 bit integer into a 32 bit one */ +static INLINE void c24to32(const word24 u24, word32* u32) +{ + *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; +} +#endif +#endif + +/* convert 32 bit integer to opaque */ +static INLINE void c32toa(word32 u32, byte* c) +{ + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} + + +static INLINE word32 GetSEQIncrement(WOLFSSL* ssl, int verify) +{ +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if (verify) + return ssl->keys.dtls_state.curSeq; /* explicit from peer */ + else + return ssl->keys.dtls_sequence_number - 1; /* already incremented */ + } +#endif + if (verify) + return ssl->keys.peer_sequence_number++; + else + return ssl->keys.sequence_number++; +} + + +#ifdef WOLFSSL_DTLS + +static INLINE word32 GetEpoch(WOLFSSL* ssl, int verify) +{ + if (verify) + return ssl->keys.dtls_state.curEpoch; + else + return ssl->keys.dtls_epoch; +} + +#endif /* WOLFSSL_DTLS */ + + +/*** end copy ***/ + + +/* return HMAC digest type in wolfSSL format */ +int wolfSSL_GetHmacType(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (ssl->specs.mac_algorithm) { + #ifndef NO_MD5 + case md5_mac: + { + return MD5; + } + #endif + #ifndef NO_SHA256 + case sha256_mac: + { + return SHA256; + } + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + { + return SHA384; + } + + #endif + #ifndef NO_SHA + case sha_mac: + { + return SHA; + } + #endif + #ifdef HAVE_BLAKE2 + case blake2b_mac: + { + return BLAKE2B_ID; + } + #endif + default: + { + return SSL_FATAL_ERROR; + } + } +} + + +int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content, + int verify) +{ + if (ssl == NULL || inner == NULL) + return BAD_FUNC_ARG; + + XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ); + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + c16toa((word16)GetEpoch(ssl, verify), inner); +#endif + c32toa(GetSEQIncrement(ssl, verify), &inner[sizeof(word32)]); + inner[SEQ_SZ] = (byte)content; + inner[SEQ_SZ + ENUM_LEN] = ssl->version.major; + inner[SEQ_SZ + ENUM_LEN + ENUM_LEN] = ssl->version.minor; + c16toa((word16)sz, inner + SEQ_SZ + ENUM_LEN + VERSION_SZ); + + return 0; +} + + +/* TLS type HMAC */ +int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, + int content, int verify) +{ + Hmac hmac; + int ret; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + + if (ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); +#endif + + wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); + + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, verify), ssl->specs.hash_size); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, in, sz); /* content */ + if (ret != 0) + return ret; + ret = wc_HmacFinal(&hmac, digest); + if (ret != 0) + return ret; + + return 0; +} + +#ifdef HAVE_TLS_EXTENSIONS + +/** + * The TLSX semaphore is used to calculate the size of the extensions to be sent + * from one peer to another. + */ + +/** Supports up to 64 flags. Increase as needed. */ +#define SEMAPHORE_SIZE 8 + +/** + * Converts the extension type (id) to an index in the semaphore. + * + * Oficial reference for TLS extension types: + * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml + * + * Motivation: + * Previously, we used the extension type itself as the index of that + * extension in the semaphore as the extension types were declared + * sequentially, but maintain a semaphore as big as the number of available + * extensions is no longer an option since the release of renegotiation_info. + * + * How to update: + * Assign extension types that extrapolate the number of available semaphores + * to the first available index going backwards in the semaphore array. + * When adding a new extension type that don't extrapolate the number of + * available semaphores, check for a possible collision with with a + * 'remapped' extension type. + */ +static INLINE word16 TLSX_ToSemaphore(word16 type) +{ + switch (type) { + + case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */ + return 63; + + default: + if (type > 62) { + /* This message SHOULD only happens during the adding of + new TLS extensions in which its IANA number overflows + the current semaphore's range, or if its number already + is assigned to be used by another extension. + Use this check value for the new extension and decrement + the check value by one. */ + WOLFSSL_MSG("### TLSX semaphore colision or overflow detected!"); + } + } + + return type; +} + +/** Checks if a specific light (tls extension) is not set in the semaphore. */ +#define IS_OFF(semaphore, light) \ + ((semaphore)[(light) / 8] ^ (byte) (0x01 << ((light) % 8))) + +/** Turn on a specific light (tls extension) in the semaphore. */ +#define TURN_ON(semaphore, light) \ + ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8))) + +/** Creates a new extension. */ +static TLSX* TLSX_New(TLSX_Type type, void* data) +{ + TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), NULL, DYNAMIC_TYPE_TLSX); + + if (extension) { + extension->type = type; + extension->data = data; + extension->resp = 0; + extension->next = NULL; + } + + return extension; +} + +/** + * Creates a new extension and pushes it to the provided list. + * Checks for duplicate extensions, keeps the newest. + */ +static int TLSX_Push(TLSX** list, TLSX_Type type, void* data) +{ + TLSX* extension = TLSX_New(type, data); + + if (extension == NULL) + return MEMORY_E; + + /* pushes the new extension on the list. */ + extension->next = *list; + *list = extension; + + /* remove duplicate extensions, there should be only one of each type. */ + do { + if (extension->next && extension->next->type == type) { + TLSX *next = extension->next; + + extension->next = next->next; + next->next = NULL; + + TLSX_FreeAll(next); + + /* there is no way to occur more than */ + /* two extensions of the same type. */ + break; + } + } while ((extension = extension->next)); + + return 0; +} + +#ifndef NO_WOLFSSL_SERVER + +/** Mark an extension to be sent back to the client. */ +void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type); + +void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type) +{ + TLSX *ext = TLSX_Find(ssl->extensions, type); + + if (ext) + ext->resp = 1; +} + +#endif + +/******************************************************************************/ +/* Application-Layer Protocol Negotiation */ +/******************************************************************************/ + +#ifdef HAVE_ALPN +/** Creates a new ALPN object, providing protocol name to use. */ +static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz) +{ + ALPN *alpn; + + WOLFSSL_ENTER("TLSX_ALPN_New"); + + if (protocol_name == NULL || + protocol_nameSz > WOLFSSL_MAX_ALPN_PROTO_NAME_LEN) { + WOLFSSL_MSG("Invalid arguments"); + return NULL; + } + + alpn = (ALPN*)XMALLOC(sizeof(ALPN), 0, DYNAMIC_TYPE_TLSX); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return NULL; + } + + alpn->next = NULL; + alpn->negotiated = 0; + alpn->options = 0; + + alpn->protocol_name = XMALLOC(protocol_nameSz + 1, 0, DYNAMIC_TYPE_TLSX); + if (alpn->protocol_name == NULL) { + WOLFSSL_MSG("Memory failure"); + XFREE(alpn, 0, DYNAMIC_TYPE_TLSX); + return NULL; + } + + XMEMCPY(alpn->protocol_name, protocol_name, protocol_nameSz); + alpn->protocol_name[protocol_nameSz] = 0; + + return alpn; +} + +/** Releases an ALPN object. */ +static void TLSX_ALPN_Free(ALPN *alpn) +{ + if (alpn == NULL) + return; + + XFREE(alpn->protocol_name, 0, DYNAMIC_TYPE_TLSX); + XFREE(alpn, 0, DYNAMIC_TYPE_TLSX); +} + +/** Releases all ALPN objects in the provided list. */ +static void TLSX_ALPN_FreeAll(ALPN *list) +{ + ALPN* alpn; + + while ((alpn = list)) { + list = alpn->next; + TLSX_ALPN_Free(alpn); + } +} + +/** Tells the buffered size of the ALPN objects in a list. */ +static word16 TLSX_ALPN_GetSize(ALPN *list) +{ + ALPN* alpn; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((alpn = list)) { + list = alpn->next; + + length++; /* protocol name length is on one byte */ + length += (word16)XSTRLEN(alpn->protocol_name); + } + + return length; +} + +/** Writes the ALPN objects of a list in a buffer. */ +static word16 TLSX_ALPN_Write(ALPN *list, byte *output) +{ + ALPN* alpn; + word16 length = 0; + word16 offset = OPAQUE16_LEN; /* list length offset */ + + while ((alpn = list)) { + list = alpn->next; + + length = (word16)XSTRLEN(alpn->protocol_name); + + /* protocol name length */ + output[offset++] = (byte)length; + + /* protocol name value */ + XMEMCPY(output + offset, alpn->protocol_name, length); + + offset += length; + } + + /* writing list length */ + c16toa(offset - OPAQUE16_LEN, output); + + return offset; +} + +/** Finds a protocol name in the provided ALPN list */ +static ALPN* TLSX_ALPN_Find(ALPN *list, char *protocol_name, word16 size) +{ + ALPN *alpn; + + if (list == NULL || protocol_name == NULL) + return NULL; + + alpn = list; + while (alpn != NULL && ( + (word16)XSTRLEN(alpn->protocol_name) != size || + XSTRNCMP(alpn->protocol_name, protocol_name, size))) + alpn = alpn->next; + + return alpn; +} + +/** Set the ALPN matching client and server requirements */ +static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size) +{ + ALPN *alpn; + int ret; + + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + alpn = TLSX_ALPN_New((char *)data, size); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_E; + } + + alpn->negotiated = 1; + + ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, (void*)alpn); + if (ret != 0) { + TLSX_ALPN_Free(alpn); + return ret; + } + + return SSL_SUCCESS; +} + +/** Parses a buffer of ALPN extensions and set the first one matching + * client and server requirements */ +static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, + byte isRequest) +{ + word16 size = 0, offset = 0, idx = 0; + int r = BUFFER_ERROR; + byte match = 0; + TLSX *extension; + ALPN *alpn = NULL, *list; + + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) + extension = TLSX_Find(ssl->ctx->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + + if (extension == NULL || extension->data == NULL) { + WOLFSSL_MSG("No ALPN extensions not used or bad"); + return isRequest ? 0 /* not using ALPN */ + : BUFFER_ERROR; /* unexpected ALPN response */ + } + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + + /* validating alpn list length */ + if (length != OPAQUE16_LEN + size) + return BUFFER_ERROR; + + list = (ALPN*)extension->data; + + /* keep the list sent by client */ + if (isRequest) { + if (ssl->alpn_client_list != NULL) + XFREE(ssl->alpn_client_list, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + ssl->alpn_client_list = (char *)XMALLOC(size, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->alpn_client_list == NULL) + return MEMORY_ERROR; + } + + for (size = 0; offset < length; offset += size) { + + size = input[offset++]; + if (offset + size > length) + return BUFFER_ERROR; + + if (isRequest) { + XMEMCPY(ssl->alpn_client_list+idx, (char*)input + offset, size); + idx += size; + ssl->alpn_client_list[idx++] = ','; + } + + if (!match) { + alpn = TLSX_ALPN_Find(list, (char*)input + offset, size); + if (alpn != NULL) { + WOLFSSL_MSG("ALPN protocol match"); + match = 1; + + /* skip reading other values if not required */ + if (!isRequest) + break; + } + } + } + + if (isRequest) + ssl->alpn_client_list[idx-1] = 0; + + if (!match) { + WOLFSSL_MSG("No ALPN protocol match"); + + /* do nothing if no protocol match between client and server and option + is set to continue (like OpenSSL) */ + if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) { + WOLFSSL_MSG("Continue on mismatch"); + return 0; + } + + SendAlert(ssl, alert_fatal, no_application_protocol); + return UNKNOWN_ALPN_PROTOCOL_NAME_E; + } + + /* set the matching negotiated protocol */ + r = TLSX_SetALPN(&ssl->extensions, + alpn->protocol_name, + (word16)XSTRLEN(alpn->protocol_name)); + if (r != SSL_SUCCESS) { + WOLFSSL_MSG("TLSX_UseALPN failed"); + return BUFFER_ERROR; + } + + /* reply to ALPN extension sent from client */ + if (isRequest) { +#ifndef NO_WOLFSSL_SERVER + TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL); +#endif + } + + return 0; +} + +/** Add a protocol name to the list of accepted usable ones */ +int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options) +{ + ALPN *alpn; + TLSX *extension; + int ret; + + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + alpn = TLSX_ALPN_New((char *)data, size); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_E; + } + + /* Set Options of ALPN */ + alpn->options = options; + + extension = TLSX_Find(*extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) { + ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, + (void*)alpn); + if (ret != 0) { + TLSX_ALPN_Free(alpn); + return ret; + } + } + else { + /* push new ALPN object to extension data. */ + alpn->next = (ALPN*)extension->data; + extension->data = (void*)alpn; + } + + return SSL_SUCCESS; +} + +/** Get the protocol name set by the server */ +int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz) +{ + TLSX *extension; + ALPN *alpn; + + if (extensions == NULL || data == NULL || dataSz == NULL) + return BAD_FUNC_ARG; + + extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) { + WOLFSSL_MSG("TLS extension not found"); + return SSL_ALPN_NOT_FOUND; + } + + alpn = (ALPN *)extension->data; + if (alpn == NULL) { + WOLFSSL_MSG("ALPN extension not found"); + *data = NULL; + *dataSz = 0; + return SSL_FATAL_ERROR; + } + + if (alpn->negotiated != 1) { + + /* consider as an error */ + if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) { + WOLFSSL_MSG("No protocol match with peer -> Failed"); + return SSL_FATAL_ERROR; + } + + /* continue without negotiated protocol */ + WOLFSSL_MSG("No protocol match with peer -> Continue"); + return SSL_ALPN_NOT_FOUND; + } + + if (alpn->next != NULL) { + WOLFSSL_MSG("Only one protocol name must be accepted"); + return SSL_FATAL_ERROR; + } + + *data = alpn->protocol_name; + *dataSz = (word16)XSTRLEN(*data); + + return SSL_SUCCESS; +} + +#define ALPN_FREE_ALL TLSX_ALPN_FreeAll +#define ALPN_GET_SIZE TLSX_ALPN_GetSize +#define ALPN_WRITE TLSX_ALPN_Write +#define ALPN_PARSE TLSX_ALPN_ParseAndSet + +#else /* HAVE_ALPN */ + +#define ALPN_FREE_ALL(list) +#define ALPN_GET_SIZE(list) 0 +#define ALPN_WRITE(a, b) 0 +#define ALPN_PARSE(a, b, c, d) 0 + +#endif /* HAVE_ALPN */ + +/******************************************************************************/ +/* Server Name Indication */ +/******************************************************************************/ + +#ifdef HAVE_SNI + +/** Creates a new SNI object. */ +static SNI* TLSX_SNI_New(byte type, const void* data, word16 size) +{ + SNI* sni = (SNI*)XMALLOC(sizeof(SNI), NULL, DYNAMIC_TYPE_TLSX); + + if (sni) { + sni->type = type; + sni->next = NULL; + + #ifndef NO_WOLFSSL_SERVER + sni->options = 0; + sni->status = WOLFSSL_SNI_NO_MATCH; + #endif + + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + sni->data.host_name = XMALLOC(size+1, NULL, DYNAMIC_TYPE_TLSX); + + if (sni->data.host_name) { + XSTRNCPY(sni->data.host_name, (const char*)data, size); + sni->data.host_name[size] = 0; + } else { + XFREE(sni, 0, DYNAMIC_TYPE_TLSX); + sni = NULL; + } + break; + + default: /* invalid type */ + XFREE(sni, 0, DYNAMIC_TYPE_TLSX); + sni = NULL; + } + } + + return sni; +} + +/** Releases a SNI object. */ +static void TLSX_SNI_Free(SNI* sni) +{ + if (sni) { + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + XFREE(sni->data.host_name, 0, DYNAMIC_TYPE_TLSX); + break; + } + + XFREE(sni, 0, DYNAMIC_TYPE_TLSX); + } +} + +/** Releases all SNI objects in the provided list. */ +static void TLSX_SNI_FreeAll(SNI* list) +{ + SNI* sni; + + while ((sni = list)) { + list = sni->next; + TLSX_SNI_Free(sni); + } +} + +/** Tells the buffered size of the SNI objects in a list. */ +static word16 TLSX_SNI_GetSize(SNI* list) +{ + SNI* sni; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((sni = list)) { + list = sni->next; + + length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */ + + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + length += XSTRLEN((char*)sni->data.host_name); + break; + } + } + + return length; +} + +/** Writes the SNI objects of a list in a buffer. */ +static word16 TLSX_SNI_Write(SNI* list, byte* output) +{ + SNI* sni; + word16 length = 0; + word16 offset = OPAQUE16_LEN; /* list length offset */ + + while ((sni = list)) { + list = sni->next; + + output[offset++] = sni->type; /* sni type */ + + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + length = XSTRLEN((char*)sni->data.host_name); + + c16toa(length, output + offset); /* sni length */ + offset += OPAQUE16_LEN; + + XMEMCPY(output + offset, sni->data.host_name, length); + + offset += length; + break; + } + } + + c16toa(offset - OPAQUE16_LEN, output); /* writing list length */ + + return offset; +} + +#ifndef NO_WOLFSSL_SERVER + +/** Finds a SNI object in the provided list. */ +static SNI* TLSX_SNI_Find(SNI *list, byte type) +{ + SNI *sni = list; + + while (sni && sni->type != type) + sni = sni->next; + + return sni; +} + + +/** Sets the status of a SNI object. */ +static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + + if (sni) + sni->status = status; +} + +/** Gets the status of a SNI object. */ +byte TLSX_SNI_Status(TLSX* extensions, byte type) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + + if (sni) + return sni->status; + + return 0; +} + +#endif /* NO_WOLFSSL_SERVER */ + +/** Parses a buffer of SNI extensions. */ +static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ +#ifndef NO_WOLFSSL_SERVER + word16 size = 0; + word16 offset = 0; + int cacheOnly = 0; +#endif + + TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); + + if (!extension) + extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); + + (void)isRequest; + (void)input; + + if (!extension || !extension->data) { +#if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER) + /* This will keep SNI even though TLSX_UseSNI has not been called. + * Enable it so that the received sni is available to functions + * that use a custom callback when SNI is received */ + cacheOnly = 1; + WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); +#else + return isRequest ? 0 /* not using SNI. */ + : BUFFER_ERROR; /* unexpected SNI response. */ +#endif + } + + if (!isRequest) + return length ? BUFFER_ERROR /* SNI response MUST be empty. */ + : 0; /* nothing else to do. */ + +#ifndef NO_WOLFSSL_SERVER + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + + /* validating sni list length */ + if (length != OPAQUE16_LEN + size) + return BUFFER_ERROR; + + for (size = 0; offset < length; offset += size) { + SNI *sni = NULL; + byte type = input[offset++]; + + if (offset + OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN; + + if (offset + size > length) + return BUFFER_ERROR; + + if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type))) + continue; /* not using this type of SNI. */ + + switch(type) { + case WOLFSSL_SNI_HOST_NAME: { + int matchStat; + byte matched = cacheOnly || + ((XSTRLEN(sni->data.host_name) == size) + && (XSTRNCMP(sni->data.host_name, + (const char*)input + offset, size) == 0)); + + if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) { + int r = TLSX_UseSNI(&ssl->extensions, + type, input + offset, size); + + if (r != SSL_SUCCESS) + return r; /* throws error. */ + + if(cacheOnly) { + WOLFSSL_MSG("Forcing storage of SNI, Fake match"); + matchStat = WOLFSSL_SNI_FORCE_KEEP; + } else if(matched) { + WOLFSSL_MSG("SNI did match!"); + matchStat = WOLFSSL_SNI_REAL_MATCH; + } else { + WOLFSSL_MSG("fake SNI match from ANSWER_ON_MISMATCH"); + matchStat = WOLFSSL_SNI_FAKE_MATCH; + } + + TLSX_SNI_SetStatus(ssl->extensions, type, matchStat); + + if(!cacheOnly) + TLSX_SetResponse(ssl, TLSX_SERVER_NAME); + + } else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) { + SendAlert(ssl, alert_fatal, unrecognized_name); + + return UNKNOWN_SNI_HOST_NAME_E; + } + break; + } + } + } + +#endif + + return 0; +} + +static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest) +{ + (void)ssl; + + if (isRequest) { + #ifndef NO_WOLFSSL_SERVER + TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); + TLSX* ssl_ext = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); + SNI* ctx_sni = ctx_ext ? ctx_ext->data : NULL; + SNI* ssl_sni = ssl_ext ? ssl_ext->data : NULL; + SNI* sni = NULL; + + for (; ctx_sni; ctx_sni = ctx_sni->next) { + if (ctx_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) { + sni = TLSX_SNI_Find(ssl_sni, ctx_sni->type); + + if (sni) { + if (sni->status != WOLFSSL_SNI_NO_MATCH) + continue; + + /* if ssl level overrides ctx level, it is ok. */ + if ((sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) == 0) + continue; + } + + SendAlert(ssl, alert_fatal, handshake_failure); + return SNI_ABSENT_ERROR; + } + } + + for (; ssl_sni; ssl_sni = ssl_sni->next) { + if (ssl_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) { + if (ssl_sni->status != WOLFSSL_SNI_NO_MATCH) + continue; + + SendAlert(ssl, alert_fatal, handshake_failure); + return SNI_ABSENT_ERROR; + } + } + #endif /* NO_WOLFSSL_SERVER */ + } + + return 0; +} + +int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) +{ + TLSX* extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); + SNI* sni = NULL; + + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + if ((sni = TLSX_SNI_New(type, data, size)) == NULL) + return MEMORY_E; + + if (!extension) { + int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni); + if (ret != 0) { + TLSX_SNI_Free(sni); + return ret; + } + } + else { + /* push new SNI object to extension data. */ + sni->next = (SNI*)extension->data; + extension->data = (void*)sni; + + /* remove duplicate SNI, there should be only one of each type. */ + do { + if (sni->next && sni->next->type == type) { + SNI *next = sni->next; + + sni->next = next->next; + TLSX_SNI_Free(next); + + /* there is no way to occur more than */ + /* two SNIs of the same type. */ + break; + } + } while ((sni = sni->next)); + } + + return SSL_SUCCESS; +} + +#ifndef NO_WOLFSSL_SERVER + +/** Tells the SNI requested by the client. */ +word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + + if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) { + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + *data = sni->data.host_name; + return XSTRLEN(*data); + } + } + + return 0; +} + +/** Sets the options for a SNI object. */ +void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + + if (sni) + sni->options = options; +} + +/** Retrieves a SNI request from a client hello buffer. */ +int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, + byte type, byte* sni, word32* inOutSz) +{ + word32 offset = 0; + word32 len32 = 0; + word16 len16 = 0; + + if (helloSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST) + return INCOMPLETE_DATA; + + /* TLS record header */ + if ((enum ContentType) clientHello[offset++] != handshake) { + + /* checking for SSLv2.0 client hello according to: */ + /* http://tools.ietf.org/html/rfc4346#appendix-E.1 */ + if ((enum HandShakeType) clientHello[++offset] == client_hello) { + offset += ENUM_LEN + VERSION_SZ; /* skip version */ + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (len16 % 3) /* cipher_spec_length must be multiple of 3 */ + return BUFFER_ERROR; + + ato16(clientHello + offset, &len16); + /* Returning SNI_UNSUPPORTED do not increment offset here */ + + if (len16 != 0) /* session_id_length must be 0 */ + return BUFFER_ERROR; + + return SNI_UNSUPPORTED; + } + + return BUFFER_ERROR; + } + + if (clientHello[offset++] != SSLv3_MAJOR) + return BUFFER_ERROR; + + if (clientHello[offset++] < TLSv1_MINOR) + return SNI_UNSUPPORTED; + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (offset + len16 > helloSz) + return INCOMPLETE_DATA; + + /* Handshake header */ + if ((enum HandShakeType) clientHello[offset] != client_hello) + return BUFFER_ERROR; + + c24to32(clientHello + offset + 1, &len32); + offset += HANDSHAKE_HEADER_SZ; + + if (offset + len32 > helloSz) + return BUFFER_ERROR; + + /* client hello */ + offset += VERSION_SZ + RAN_LEN; /* version, random */ + + if (helloSz < offset + clientHello[offset]) + return BUFFER_ERROR; + + offset += ENUM_LEN + clientHello[offset]; /* skip session id */ + + /* cypher suites */ + if (helloSz < offset + OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (helloSz < offset + len16) + return BUFFER_ERROR; + + offset += len16; /* skip cypher suites */ + + /* compression methods */ + if (helloSz < offset + 1) + return BUFFER_ERROR; + + if (helloSz < offset + clientHello[offset]) + return BUFFER_ERROR; + + offset += ENUM_LEN + clientHello[offset]; /* skip compression methods */ + + /* extensions */ + if (helloSz < offset + OPAQUE16_LEN) + return 0; /* no extensions in client hello. */ + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (helloSz < offset + len16) + return BUFFER_ERROR; + + while (len16 >= OPAQUE16_LEN + OPAQUE16_LEN) { + word16 extType; + word16 extLen; + + ato16(clientHello + offset, &extType); + offset += OPAQUE16_LEN; + + ato16(clientHello + offset, &extLen); + offset += OPAQUE16_LEN; + + if (helloSz < offset + extLen) + return BUFFER_ERROR; + + if (extType != TLSX_SERVER_NAME) { + offset += extLen; /* skip extension */ + } else { + word16 listLen; + + ato16(clientHello + offset, &listLen); + offset += OPAQUE16_LEN; + + if (helloSz < offset + listLen) + return BUFFER_ERROR; + + while (listLen > ENUM_LEN + OPAQUE16_LEN) { + byte sniType = clientHello[offset++]; + word16 sniLen; + + ato16(clientHello + offset, &sniLen); + offset += OPAQUE16_LEN; + + if (helloSz < offset + sniLen) + return BUFFER_ERROR; + + if (sniType != type) { + offset += sniLen; + listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen); + continue; + } + + *inOutSz = min(sniLen, *inOutSz); + XMEMCPY(sni, clientHello + offset, *inOutSz); + + return SSL_SUCCESS; + } + } + + len16 -= min(2 * OPAQUE16_LEN + extLen, len16); + } + + return len16 ? BUFFER_ERROR : 0; +} + +#endif + +#define SNI_FREE_ALL TLSX_SNI_FreeAll +#define SNI_GET_SIZE TLSX_SNI_GetSize +#define SNI_WRITE TLSX_SNI_Write +#define SNI_PARSE TLSX_SNI_Parse +#define SNI_VERIFY_PARSE TLSX_SNI_VerifyParse + +#else + +#define SNI_FREE_ALL(list) +#define SNI_GET_SIZE(list) 0 +#define SNI_WRITE(a, b) 0 +#define SNI_PARSE(a, b, c, d) 0 +#define SNI_VERIFY_PARSE(a, b) 0 + +#endif /* HAVE_SNI */ + +/******************************************************************************/ +/* Max Fragment Length Negotiation */ +/******************************************************************************/ + +#ifdef HAVE_MAX_FRAGMENT + +static word16 TLSX_MFL_Write(byte* data, byte* output) +{ + output[0] = data[0]; + + return ENUM_LEN; +} + +static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + (void)isRequest; + + if (length != ENUM_LEN) + return BUFFER_ERROR; + + switch (*input) { + case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; + case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; + case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break; + case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break; + case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break; + + default: + SendAlert(ssl, alert_fatal, illegal_parameter); + + return UNKNOWN_MAX_FRAG_LEN_E; + } + +#ifndef NO_WOLFSSL_SERVER + if (isRequest) { + int r = TLSX_UseMaxFragment(&ssl->extensions, *input); + + if (r != SSL_SUCCESS) return r; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH); + } +#endif + + return 0; +} + +int TLSX_UseMaxFragment(TLSX** extensions, byte mfl) +{ + byte* data = NULL; + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + if (mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) + return BAD_FUNC_ARG; + + if ((data = XMALLOC(ENUM_LEN, NULL, DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + + data[0] = mfl; + + /* push new MFL extension. */ + if ((ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data)) != 0) { + XFREE(data, 0, DYNAMIC_TYPE_TLSX); + return ret; + } + + return SSL_SUCCESS; +} + + +#define MFL_FREE_ALL(data) XFREE(data, 0, DYNAMIC_TYPE_TLSX) +#define MFL_GET_SIZE(data) ENUM_LEN +#define MFL_WRITE TLSX_MFL_Write +#define MFL_PARSE TLSX_MFL_Parse + +#else + +#define MFL_FREE_ALL(a) +#define MFL_GET_SIZE(a) 0 +#define MFL_WRITE(a, b) 0 +#define MFL_PARSE(a, b, c, d) 0 + +#endif /* HAVE_MAX_FRAGMENT */ + +/******************************************************************************/ +/* Truncated HMAC */ +/******************************************************************************/ + +#ifdef HAVE_TRUNCATED_HMAC + +static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + (void)isRequest; + + if (length != 0 || input == NULL) + return BUFFER_ERROR; + +#ifndef NO_WOLFSSL_SERVER + if (isRequest) { + int r = TLSX_UseTruncatedHMAC(&ssl->extensions); + + if (r != SSL_SUCCESS) + return r; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC); + } +#endif + + ssl->truncated_hmac = 1; + + return 0; +} + +int TLSX_UseTruncatedHMAC(TLSX** extensions) +{ + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + if ((ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL)) != 0) + return ret; + + return SSL_SUCCESS; +} + +#define THM_PARSE TLSX_THM_Parse + +#else + +#define THM_PARSE(a, b, c, d) 0 + +#endif /* HAVE_TRUNCATED_HMAC */ + +/******************************************************************************/ +/* Certificate Status Request */ +/******************************************************************************/ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +static void TLSX_CSR_Free(CertificateStatusRequest* csr) +{ + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + FreeOcspRequest(&csr->request.ocsp); + break; + } + + XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); +} + +static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest) +{ + word16 size = 0; + + /* shut up compiler warnings */ + (void) csr; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + size += ENUM_LEN + 2 * OPAQUE16_LEN; + + if (csr->request.ocsp.nonceSz) + size += OCSP_NONCE_EXT_SZ; + break; + } + } +#endif + + return size; +} + +static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, + byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr; (void) output; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + word16 offset = 0; + word16 length = 0; + + /* type */ + output[offset++] = csr->status_type; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* responder id list */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + + /* request extensions */ + if (csr->request.ocsp.nonceSz) + length = EncodeOcspRequestExtensions( + &csr->request.ocsp, + output + offset + OPAQUE16_LEN, + OCSP_NONCE_EXT_SZ); + + c16toa(length, output + offset); + offset += OPAQUE16_LEN + length; + + break; + } + + return offset; + } +#endif + + return 0; +} + +static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* shut up compiler warnings */ + (void) ssl; (void) input; + + if (!isRequest) { +#ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? extension->data : NULL; + + if (!csr) { + /* look at context level */ + + extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); + csr = extension ? extension->data : NULL; + + if (!csr) + return BUFFER_ERROR; /* unexpected extension */ + + /* enable extension at ssl level */ + ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, + csr->status_type, csr->options); + if (ret != SSL_SUCCESS) + return ret; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* propagate nonce */ + if (csr->request.ocsp.nonceSz) { + OcspRequest* request = + TLSX_CSR_GetRequest(ssl->extensions); + + if (request) { + XMEMCPY(request->nonce, csr->request.ocsp.nonce, + csr->request.ocsp.nonceSz); + request->nonceSz = csr->request.ocsp.nonceSz; + } + } + break; + } + } + + ssl->status_request = 1; + + return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ +#endif + } + else { +#ifndef NO_WOLFSSL_SERVER + byte status_type; + word16 offset = 0; + word16 size = 0; + + if (length < ENUM_LEN) + return BUFFER_ERROR; + + status_type = input[offset++]; + + switch (status_type) { + case WOLFSSL_CSR_OCSP: { + + /* skip responder_id_list */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + /* skip request_extensions */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + if (offset > length) + return BUFFER_ERROR; + + /* is able to send OCSP response? */ + if (ssl->ctx->cm == NULL || !ssl->ctx->cm->ocspStaplingEnabled) + return 0; + } + break; + } + + /* if using status_request and already sending it, skip this one */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) + return 0; + #endif + + /* accept the first good status_type and return */ + ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, + 0); + if (ret != SSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); + ssl->status_request = status_type; + +#endif + } + + return 0; +} + +int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? extension->data : NULL; + int ret = 0; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: { + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz = csr->request.ocsp.nonceSz; + + /* preserve nonce */ + XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz); + + if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0)) != 0) + return ret; + + /* restore nonce */ + XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz); + csr->request.ocsp.nonceSz = nonceSz; + } + break; + } + } + + return ret; +} + +void* TLSX_CSR_GetRequest(TLSX* extensions) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + return &csr->request.ocsp; + break; + } + } + + return NULL; +} + +int TLSX_CSR_ForceRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + if (ssl->ctx->cm->ocspEnabled) + return CheckOcspRequest(ssl->ctx->cm->ocsp, + &csr->request.ocsp, NULL); + else + return OCSP_LOOKUP_FAIL; + } + } + + return 0; +} + +int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, + byte options) +{ + CertificateStatusRequest* csr = NULL; + int ret = 0; + + if (!extensions || status_type != WOLFSSL_CSR_OCSP) + return BAD_FUNC_ARG; + + csr = (CertificateStatusRequest*) + XMALLOC(sizeof(CertificateStatusRequest), NULL, DYNAMIC_TYPE_TLSX); + if (!csr) + return MEMORY_E; + + ForceZero(csr, sizeof(CertificateStatusRequest)); + + csr->status_type = status_type; + csr->options = options; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + if (options & WOLFSSL_CSR_OCSP_USE_NONCE) { + WC_RNG rng; + + if (wc_InitRng(&rng) == 0) { + if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce, + MAX_OCSP_NONCE_SZ) == 0) + csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } + break; + } + + if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr)) != 0) { + XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); + return ret; + } + + return SSL_SUCCESS; +} + +#define CSR_FREE_ALL TLSX_CSR_Free +#define CSR_GET_SIZE TLSX_CSR_GetSize +#define CSR_WRITE TLSX_CSR_Write +#define CSR_PARSE TLSX_CSR_Parse + +#else + +#define CSR_FREE_ALL(data) +#define CSR_GET_SIZE(a, b) 0 +#define CSR_WRITE(a, b, c) 0 +#define CSR_PARSE(a, b, c, d) 0 + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + +/******************************************************************************/ +/* Certificate Status Request v2 */ +/******************************************************************************/ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2) +{ + CertificateStatusRequestItemV2* next; + + for (; csr2; csr2 = next) { + next = csr2->next; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + while(csr2->requests--) + FreeOcspRequest(&csr2->request.ocsp[csr2->requests]); + break; + } + + XFREE(csr2, NULL, DYNAMIC_TYPE_TLSX); + } +} + +static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2, + byte isRequest) +{ + word16 size = 0; + + /* shut up compiler warnings */ + (void) csr2; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + CertificateStatusRequestItemV2* next; + + for (size = OPAQUE16_LEN; csr2; csr2 = next) { + next = csr2->next; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + size += ENUM_LEN + 3 * OPAQUE16_LEN; + + if (csr2->request.ocsp[0].nonceSz) + size += OCSP_NONCE_EXT_SZ; + break; + } + } + } +#endif + + return size; +} + +static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2, + byte* output, byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr2; (void) output; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + word16 offset; + word16 length; + + for (offset = OPAQUE16_LEN; csr2 != NULL; csr2 = csr2->next) { + /* status_type */ + output[offset++] = csr2->status_type; + + /* request */ + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + /* request_length */ + length = 2 * OPAQUE16_LEN; + + if (csr2->request.ocsp[0].nonceSz) + length += OCSP_NONCE_EXT_SZ; + + c16toa(length, output + offset); + offset += OPAQUE16_LEN; + + /* responder id list */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + + /* request extensions */ + length = 0; + + if (csr2->request.ocsp[0].nonceSz) + length = EncodeOcspRequestExtensions( + &csr2->request.ocsp[0], + output + offset + OPAQUE16_LEN, + OCSP_NONCE_EXT_SZ); + + c16toa(length, output + offset); + offset += OPAQUE16_LEN + length; + break; + } + } + + /* list size */ + c16toa(offset - OPAQUE16_LEN, output); + + return offset; + } +#endif + + return 0; +} + +static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* shut up compiler warnings */ + (void) ssl; (void) input; + + if (!isRequest) { +#ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? extension->data + : NULL; + + if (!csr2) { + /* look at context level */ + + extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2); + csr2 = extension ? extension->data : NULL; + + if (!csr2) + return BUFFER_ERROR; /* unexpected extension */ + + /* enable extension at ssl level */ + for (; csr2; csr2 = csr2->next) { + ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, + csr2->status_type, csr2->options); + if (ret != SSL_SUCCESS) + return ret; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + case WOLFSSL_CSR2_OCSP_MULTI: + /* propagate nonce */ + if (csr2->request.ocsp[0].nonceSz) { + OcspRequest* request = + TLSX_CSR2_GetRequest(ssl->extensions, + csr2->status_type, 0); + + if (request) { + XMEMCPY(request->nonce, + csr2->request.ocsp[0].nonce, + csr2->request.ocsp[0].nonceSz); + + request->nonceSz = + csr2->request.ocsp[0].nonceSz; + } + } + break; + } + } + + } + + ssl->status_request_v2 = 1; + + return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ +#endif + } + else { +#ifndef NO_WOLFSSL_SERVER + byte status_type; + word16 request_length; + word16 offset = 0; + word16 size = 0; + + /* list size */ + ato16(input + offset, &request_length); + offset += OPAQUE16_LEN; + + if (length - OPAQUE16_LEN != request_length) + return BUFFER_ERROR; + + while (length > offset) { + if (length - offset < ENUM_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + + status_type = input[offset++]; + + ato16(input + offset, &request_length); + offset += OPAQUE16_LEN; + + if (length - offset < request_length) + return BUFFER_ERROR; + + switch (status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + /* skip responder_id_list */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + /* skip request_extensions */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + if (offset > length) + return BUFFER_ERROR; + + /* is able to send OCSP response? */ + if (ssl->ctx->cm == NULL + || !ssl->ctx->cm->ocspStaplingEnabled) + continue; + break; + + default: + /* unknown status type, skipping! */ + offset += request_length; + continue; + } + + /* if using status_request and already sending it, skip this one */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) + return 0; + #endif + + /* accept the first good status_type and return */ + ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, + status_type, 0); + if (ret != SSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2); + ssl->status_request_v2 = status_type; + + return 0; + } +#endif + } + + return 0; +} + +int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + int ret = 0; + + for (; csr2; csr2 = csr2->next) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + if (!isPeer || csr2->requests != 0) + break; + + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: { + if (csr2->requests < 1 + MAX_CHAIN_DEPTH) { + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz = csr2->request.ocsp[0].nonceSz; + + /* preserve nonce, replicating nonce of ocsp[0] */ + XMEMCPY(nonce, csr2->request.ocsp[0].nonce, nonceSz); + + if ((ret = InitOcspRequest( + &csr2->request.ocsp[csr2->requests], cert, 0)) != 0) + return ret; + + /* restore nonce */ + XMEMCPY(csr2->request.ocsp[csr2->requests].nonce, + nonce, nonceSz); + csr2->request.ocsp[csr2->requests].nonceSz = nonceSz; + csr2->requests++; + } + } + break; + } + } + + return ret; +} + +void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + + for (; csr2; csr2 = csr2->next) { + if (csr2->status_type == status_type) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: + /* requests are initialized in the reverse order */ + return index < csr2->requests + ? &csr2->request.ocsp[csr2->requests - index - 1] + : NULL; + break; + } + } + } + + return NULL; +} + +int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + + /* forces only the first one */ + if (csr2) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: + if (ssl->ctx->cm->ocspEnabled) + return CheckOcspRequest(ssl->ctx->cm->ocsp, + &csr2->request.ocsp[0], NULL); + else + return OCSP_LOOKUP_FAIL; + } + } + + return 0; +} + +int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, + byte options) +{ + TLSX* extension = NULL; + CertificateStatusRequestItemV2* csr2 = NULL; + int ret = 0; + + if (!extensions) + return BAD_FUNC_ARG; + + if (status_type != WOLFSSL_CSR2_OCSP + && status_type != WOLFSSL_CSR2_OCSP_MULTI) + return BAD_FUNC_ARG; + + csr2 = (CertificateStatusRequestItemV2*) + XMALLOC(sizeof(CertificateStatusRequestItemV2), NULL, DYNAMIC_TYPE_TLSX); + if (!csr2) + return MEMORY_E; + + ForceZero(csr2, sizeof(CertificateStatusRequestItemV2)); + + csr2->status_type = status_type; + csr2->options = options; + csr2->next = NULL; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) { + WC_RNG rng; + + if (wc_InitRng(&rng) == 0) { + if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce, + MAX_OCSP_NONCE_SZ) == 0) + csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } + break; + } + + /* append new item */ + if ((extension = TLSX_Find(*extensions, TLSX_STATUS_REQUEST_V2))) { + CertificateStatusRequestItemV2* last = + (CertificateStatusRequestItemV2*)extension->data; + + for (; last->next; last = last->next); + + last->next = csr2; + } + else if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST_V2, csr2))) { + XFREE(csr2, NULL, DYNAMIC_TYPE_TLSX); + return ret; + } + + return SSL_SUCCESS; +} + +#define CSR2_FREE_ALL TLSX_CSR2_FreeAll +#define CSR2_GET_SIZE TLSX_CSR2_GetSize +#define CSR2_WRITE TLSX_CSR2_Write +#define CSR2_PARSE TLSX_CSR2_Parse + +#else + +#define CSR2_FREE_ALL(data) +#define CSR2_GET_SIZE(a, b) 0 +#define CSR2_WRITE(a, b, c) 0 +#define CSR2_PARSE(a, b, c, d) 0 + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + +/******************************************************************************/ +/* Supported Elliptic Curves */ +/******************************************************************************/ + +#ifdef HAVE_SUPPORTED_CURVES + +#ifndef HAVE_ECC +#error Elliptic Curves Extension requires Elliptic Curve Cryptography. \ + Use --enable-ecc in the configure script or define HAVE_ECC. +#endif + +static void TLSX_EllipticCurve_FreeAll(EllipticCurve* list) +{ + EllipticCurve* curve; + + while ((curve = list)) { + list = curve->next; + XFREE(curve, 0, DYNAMIC_TYPE_TLSX); + } +} + +static int TLSX_EllipticCurve_Append(EllipticCurve** list, word16 name) +{ + EllipticCurve* curve = NULL; + + if (list == NULL) + return BAD_FUNC_ARG; + + curve = (EllipticCurve*)XMALLOC(sizeof(EllipticCurve), NULL, + DYNAMIC_TYPE_TLSX); + if (curve == NULL) + return MEMORY_E; + + curve->name = name; + curve->next = *list; + + *list = curve; + + return 0; +} + +#ifndef NO_WOLFSSL_CLIENT + +static void TLSX_EllipticCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +{ + int i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) + if (ssl->suites->suites[i] == ECC_BYTE || + ssl->suites->suites[i] == CHACHA_BYTE) + return; + + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS)); +} + +static word16 TLSX_EllipticCurve_GetSize(EllipticCurve* list) +{ + EllipticCurve* curve; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((curve = list)) { + list = curve->next; + length += OPAQUE16_LEN; /* curve length */ + } + + return length; +} + +static word16 TLSX_EllipticCurve_WriteR(EllipticCurve* curve, byte* output); +static word16 TLSX_EllipticCurve_WriteR(EllipticCurve* curve, byte* output) +{ + word16 offset = 0; + + if (!curve) + return offset; + + offset = TLSX_EllipticCurve_WriteR(curve->next, output); + c16toa(curve->name, output + offset); + + return OPAQUE16_LEN + offset; +} + +static word16 TLSX_EllipticCurve_Write(EllipticCurve* list, byte* output) +{ + word16 length = TLSX_EllipticCurve_WriteR(list, output + OPAQUE16_LEN); + + c16toa(length, output); /* writing list length */ + + return OPAQUE16_LEN + length; +} + +#endif /* NO_WOLFSSL_CLIENT */ +#ifndef NO_WOLFSSL_SERVER + +static int TLSX_EllipticCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + word16 offset; + word16 name; + int r; + + (void) isRequest; /* shut up compiler! */ + + if (OPAQUE16_LEN > length || length % OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input, &offset); + + /* validating curve list length */ + if (length != OPAQUE16_LEN + offset) + return BUFFER_ERROR; + + while (offset) { + ato16(input + offset, &name); + offset -= OPAQUE16_LEN; + + r = TLSX_UseSupportedCurve(&ssl->extensions, name); + + if (r != SSL_SUCCESS) return r; /* throw error */ + } + + return 0; +} + +int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { + TLSX* extension = (first == ECC_BYTE || first == CHACHA_BYTE) + ? TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) + : NULL; + EllipticCurve* curve = NULL; + word32 oid = 0; + word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ + int sig = 0; /* validate signature */ + int key = 0; /* validate key */ + + (void)oid; + (void)octets; + + if (!extension) + return 1; /* no suite restriction */ + + for (curve = extension->data; curve && !(sig && key); curve = curve->next) { + + switch (curve->name) { +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) + case WOLFSSL_ECC_SECP160R1: oid = ECC_160R1; octets = 20; break; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) + case WOLFSSL_ECC_SECP192R1: oid = ECC_192R1; octets = 24; break; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) + case WOLFSSL_ECC_SECP224R1: oid = ECC_224R1; octets = 28; break; +#endif +#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) + case WOLFSSL_ECC_SECP256R1: oid = ECC_256R1; octets = 32; break; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) + case WOLFSSL_ECC_SECP384R1: oid = ECC_384R1; octets = 48; break; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) + case WOLFSSL_ECC_SECP521R1: oid = ECC_521R1; octets = 66; break; +#endif + default: continue; /* unsupported curve */ + } + + if (first == ECC_BYTE) { + switch (second) { +#ifndef NO_DSA + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + sig |= ssl->pkCurveOID == oid; + key |= ssl->eccTempKeySz == octets; + break; + + /* ECDH_ECDSA */ + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + sig |= ssl->pkCurveOID == oid; + key |= ssl->pkCurveOID == oid; + break; +#endif +#ifndef NO_RSA + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + sig = 1; + key |= ssl->eccTempKeySz == octets; + break; + + /* ECDH_RSA */ + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + sig = 1; + key |= ssl->pkCurveOID == oid; + break; +#endif + default: + sig = 1; + key = 1; + break; + } + } + + /* ChaCha20-Poly1305 ECC cipher suites */ + if (first == CHACHA_BYTE) { + switch (second) { +#ifndef NO_DSA + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig |= ssl->pkCurveOID == oid; + key |= ssl->eccTempKeySz == octets; + break; +#endif +#ifndef NO_RSA + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig = 1; + key |= ssl->eccTempKeySz == octets; + break; +#endif + default: + sig = 1; + key = 1; + break; + } + } + } + + return sig && key; +} + +#endif /* NO_WOLFSSL_SERVER */ + +int TLSX_UseSupportedCurve(TLSX** extensions, word16 name) +{ + TLSX* extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); + EllipticCurve* curve = NULL; + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + if ((ret = TLSX_EllipticCurve_Append(&curve, name)) != 0) + return ret; + + if (!extension) { + if ((ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve)) != 0) { + XFREE(curve, 0, DYNAMIC_TYPE_TLSX); + return ret; + } + } + else { + /* push new EllipticCurve object to extension data. */ + curve->next = (EllipticCurve*)extension->data; + extension->data = (void*)curve; + + /* look for another curve of the same name to remove (replacement) */ + do { + if (curve->next && curve->next->name == name) { + EllipticCurve *next = curve->next; + + curve->next = next->next; + XFREE(next, 0, DYNAMIC_TYPE_TLSX); + + break; + } + } while ((curve = curve->next)); + } + + return SSL_SUCCESS; +} + +#define EC_FREE_ALL TLSX_EllipticCurve_FreeAll +#define EC_VALIDATE_REQUEST TLSX_EllipticCurve_ValidateRequest + +#ifndef NO_WOLFSSL_CLIENT +#define EC_GET_SIZE TLSX_EllipticCurve_GetSize +#define EC_WRITE TLSX_EllipticCurve_Write +#else +#define EC_GET_SIZE(list) 0 +#define EC_WRITE(a, b) 0 +#endif + +#ifndef NO_WOLFSSL_SERVER +#define EC_PARSE TLSX_EllipticCurve_Parse +#else +#define EC_PARSE(a, b, c, d) 0 +#endif + +#else + +#define EC_FREE_ALL(list) +#define EC_GET_SIZE(list) 0 +#define EC_WRITE(a, b) 0 +#define EC_PARSE(a, b, c, d) 0 +#define EC_VALIDATE_REQUEST(a, b) + +#endif /* HAVE_SUPPORTED_CURVES */ + +/******************************************************************************/ +/* Renegotiation Indication */ +/******************************************************************************/ + +#ifdef HAVE_SECURE_RENEGOTIATION + +static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data, + int isRequest) +{ + byte length = OPAQUE8_LEN; /* empty info length */ + + if (data->enabled) { + /* client sends client_verify_data only */ + length += TLS_FINISHED_SZ; + + /* server also sends server_verify_data */ + if (!isRequest) + length += TLS_FINISHED_SZ; + } + + return length; +} + +static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data, + byte* output, int isRequest) +{ + word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */ + + if (data->enabled) { + /* client sends client_verify_data only */ + XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ); + offset += TLS_FINISHED_SZ; + + /* server also sends server_verify_data */ + if (!isRequest) { + XMEMCPY(output + offset, data->server_verify_data, TLS_FINISHED_SZ); + offset += TLS_FINISHED_SZ; + } + } + + output[0] = offset - 1; /* info length - self */ + + return offset; +} + +static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, + word16 length, byte isRequest) +{ + int ret = SECURE_RENEGOTIATION_E; + + if (length >= OPAQUE8_LEN) { + if (ssl->secure_renegotiation == NULL) { + #ifndef NO_WOLFSSL_SERVER + if (isRequest && *input == 0) { + ret = 0; /* don't reply, user didn't enable */ + } + #endif + } + else if (isRequest) { + #ifndef NO_WOLFSSL_SERVER + if (*input == TLS_FINISHED_SZ) { + /* TODO compare client_verify_data */ + ret = 0; + } + #endif + } + else { + #ifndef NO_WOLFSSL_CLIENT + if (!ssl->secure_renegotiation->enabled) { + if (*input == 0) { + ssl->secure_renegotiation->enabled = 1; + ret = 0; + } + } + else if (*input == 2 * TLS_FINISHED_SZ) { + /* TODO compare client_verify_data and server_verify_data */ + ret = 0; + } + #endif + } + } + + if (ret != 0) { + /* TODO: turn on fatal error at ssl level too */ + SendAlert(ssl, alert_fatal, handshake_failure); + } + + return ret; +} + +int TLSX_UseSecureRenegotiation(TLSX** extensions) +{ + int ret = 0; + SecureRenegotiation* data = NULL; + + data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), NULL, + DYNAMIC_TYPE_TLSX); + if (data == NULL) + return MEMORY_E; + + XMEMSET(data, 0, sizeof(SecureRenegotiation)); + + ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, data); + if (ret != 0) { + XFREE(data, 0, DYNAMIC_TYPE_TLSX); + return ret; + } + + return SSL_SUCCESS; +} + + +#define SCR_FREE_ALL(data) XFREE(data, NULL, DYNAMIC_TYPE_TLSX) +#define SCR_GET_SIZE TLSX_SecureRenegotiation_GetSize +#define SCR_WRITE TLSX_SecureRenegotiation_Write +#define SCR_PARSE TLSX_SecureRenegotiation_Parse + +#else + +#define SCR_FREE_ALL(a) +#define SCR_GET_SIZE(a, b) 0 +#define SCR_WRITE(a, b, c) 0 +#define SCR_PARSE(a, b, c, d) 0 + +#endif /* HAVE_SECURE_RENEGOTIATION */ + +/******************************************************************************/ +/* Session Tickets */ +/******************************************************************************/ + +#ifdef HAVE_SESSION_TICKET + +static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET); + SessionTicket* ticket = extension ? extension->data : NULL; + + if (ticket) { + /* TODO validate ticket timeout here! */ + if (ticket->lifetime == 0xfffffff) { + /* send empty ticket on timeout */ + TLSX_UseSessionTicket(&ssl->extensions, NULL); + } + } +} + + +static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) +{ + (void)isRequest; + return ticket ? ticket->size : 0; +} + +static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output, + int isRequest) +{ + word16 offset = 0; /* empty ticket */ + + if (isRequest && ticket) { + XMEMCPY(output + offset, ticket->data, ticket->size); + offset += ticket->size; + } + + return offset; +} + + +static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret = 0; + + if (!isRequest) { + /* client side */ + if (length != 0) + return BUFFER_ERROR; + + ssl->expect_session_ticket = 1; + } +#ifndef NO_WOLFSSL_SERVER + else { + /* server side */ + if (ssl->ctx->ticketEncCb == NULL) { + WOLFSSL_MSG("Client sent session ticket, server has no callback"); + return 0; + } + + if (length == 0) { + /* blank ticket */ + ret = TLSX_UseSessionTicket(&ssl->extensions, NULL); + if (ret == SSL_SUCCESS) { + ret = 0; + TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */ + ssl->options.createTicket = 1; /* will send ticket msg */ + ssl->options.useTicket = 1; + } + } else { + /* got actual ticket from client */ + ret = DoClientTicket(ssl, input, length); + if (ret == WOLFSSL_TICKET_RET_OK) { /* use ticket to resume */ + WOLFSSL_MSG("Using exisitng client ticket"); + ssl->options.useTicket = 1; + ssl->options.resuming = 1; + } else if (ret == WOLFSSL_TICKET_RET_CREATE) { + WOLFSSL_MSG("Using existing client ticket, creating new one"); + ret = TLSX_UseSessionTicket(&ssl->extensions, NULL); + if (ret == SSL_SUCCESS) { + ret = 0; + TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); + /* send blank ticket */ + ssl->options.createTicket = 1; /* will send ticket msg */ + ssl->options.useTicket = 1; + ssl->options.resuming = 1; + } + } else if (ret == WOLFSSL_TICKET_RET_REJECT) { + WOLFSSL_MSG("Process client ticket rejected, not using"); + ret = 0; /* not fatal */ + } else if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) { + WOLFSSL_MSG("Process client ticket fatal error, not using"); + } + } + } +#endif /* NO_WOLFSSL_SERVER */ + + return ret; +} + +WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime, + byte* data, word16 size) +{ + SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket), + NULL, DYNAMIC_TYPE_TLSX); + if (ticket) { + ticket->data = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TLSX); + if (ticket->data == NULL) { + XFREE(ticket, NULL, DYNAMIC_TYPE_TLSX); + return NULL; + } + + XMEMCPY(ticket->data, data, size); + ticket->size = size; + ticket->lifetime = lifetime; + } + + return ticket; +} +WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket) +{ + if (ticket) { + XFREE(ticket->data, NULL, DYNAMIC_TYPE_TLSX); + XFREE(ticket, NULL, DYNAMIC_TYPE_TLSX); + } +} + +int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket) +{ + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + /* If the ticket is NULL, the client will request a new ticket from the + server. Otherwise, the client will use it in the next client hello. */ + if ((ret = TLSX_Push(extensions, TLSX_SESSION_TICKET, (void*)ticket)) != 0) + return ret; + + return SSL_SUCCESS; +} + +#define STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest +#define STK_GET_SIZE TLSX_SessionTicket_GetSize +#define STK_WRITE TLSX_SessionTicket_Write +#define STK_PARSE TLSX_SessionTicket_Parse + +#else + +#define STK_VALIDATE_REQUEST(a) +#define STK_GET_SIZE(a, b) 0 +#define STK_WRITE(a, b, c) 0 +#define STK_PARSE(a, b, c, d) 0 + +#endif /* HAVE_SESSION_TICKET */ + +/******************************************************************************/ +/* Quantum-Safe-Hybrid */ +/******************************************************************************/ + +#ifdef HAVE_QSH +static WC_RNG* rng; +static wolfSSL_Mutex* rngMutex; + +static void TLSX_QSH_FreeAll(QSHScheme* list) +{ + QSHScheme* current; + + while ((current = list)) { + list = current->next; + XFREE(current, 0, DYNAMIC_TYPE_TLSX); + } +} + +static int TLSX_QSH_Append(QSHScheme** list, word16 name, byte* pub, + word16 pubLen) +{ + QSHScheme* temp; + + if (list == NULL) + return BAD_FUNC_ARG; + + if ((temp = (QSHScheme*)XMALLOC(sizeof(QSHScheme), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + + temp->name = name; + temp->PK = pub; + temp->PKLen = pubLen; + temp->next = *list; + + *list = temp; + + return 0; +} + + +/* request for server's public key : 02 indicates 0-2 requested */ +static byte TLSX_QSH_SerPKReq(byte* output, byte isRequest) +{ + if (isRequest) { + /* only request one public key from the server */ + output[0] = 0x01; + + return OPAQUE8_LEN; + } + else { + return 0; + } +} + +#ifndef NO_WOLFSSL_CLIENT + +/* check for TLS_QSH suite */ +static void TLSX_QSH_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +{ + int i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) + if (ssl->suites->suites[i] == QSH_BYTE) + return; + + /* No QSH suite found */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_QUANTUM_SAFE_HYBRID)); +} + + +/* return the size of the QSH hello extension + list the list of QSHScheme structs containing id and key + isRequest if 1 then is being sent to the server + */ +word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest) +{ + QSHScheme* temp = list; + word16 length = 0; + + /* account for size of scheme list and public key list */ + if (isRequest) + length = OPAQUE16_LEN; + length += OPAQUE24_LEN; + + /* for each non null element in list add size */ + while ((temp)) { + /* add public key info Scheme | Key Length | Key */ + length += OPAQUE16_LEN; + length += OPAQUE16_LEN; + length += temp->PKLen; + + /* if client add name size for scheme list + advance to next QSHScheme struct in list */ + if (isRequest) + length += OPAQUE16_LEN; + temp = temp->next; + } + + /* add length for request server public keys */ + if (isRequest) + length += OPAQUE8_LEN; + + return length; +} + + +/* write out a list of QSHScheme IDs */ +static word16 TLSX_QSH_Write(QSHScheme* list, byte* output) +{ + QSHScheme* current = list; + word16 length = 0; + + length += OPAQUE16_LEN; + + while (current) { + c16toa(current->name, output + length); + length += OPAQUE16_LEN; + current = (QSHScheme*)current->next; + } + + c16toa(length - OPAQUE16_LEN, output); /* writing list length */ + + return length; +} + + +/* write public key list in extension */ +static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output); +static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output) +{ + word32 offset = 0; + word16 public_len = 0; + + if (!format) + return offset; + + /* write scheme ID */ + c16toa(format->name, output + offset); + offset += OPAQUE16_LEN; + + /* write public key matching scheme */ + public_len = format->PKLen; + c16toa(public_len, output + offset); + offset += OPAQUE16_LEN; + if (format->PK) { + XMEMCPY(output+offset, format->PK, public_len); + } + + return public_len + offset; +} + +word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output) +{ + QSHScheme* current = list; + word32 length = 0; + word24 toWire; + + length += OPAQUE24_LEN; + + while (current) { + length += TLSX_QSHPK_WriteR(current, output + length); + current = (QSHScheme*)current->next; + } + /* length of public keys sent */ + c32to24(length - OPAQUE24_LEN, toWire); + output[0] = toWire[0]; + output[1] = toWire[1]; + output[2] = toWire[2]; + + return length; +} + +#endif /* NO_WOLFSSL_CLIENT */ +#ifndef NO_WOLFSSL_SERVER + +static void TLSX_QSHAgreement(TLSX** extensions) +{ + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + QSHScheme* format = NULL; + QSHScheme* del = NULL; + QSHScheme* prev = NULL; + + if (extension == NULL) + return; + + format = (QSHScheme*)extension->data; + while (format) { + if (format->PKLen == 0) { + /* case of head */ + if (format == extension->data) { + extension->data = format->next; + } + if (prev) + prev->next = format->next; + del = format; + format = format->next; + XFREE(del, 0, DYNAMIC_TYPE_TMP_ARRAY); + del = NULL; + } else { + prev = format; + format = format->next; + } + } +} + + +/* Parse in hello extension + input the byte stream to process + length length of total extension found + isRequest set to 1 if being sent to the server + */ +static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + byte numKeys = 0; + word16 offset = 0; + word16 schemSz = 0; + word16 offset_len = 0; + word32 offset_pk = 0; + word16 name = 0; + word16 PKLen = 0; + byte* PK = NULL; + int r; + + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + if (isRequest) { + ato16(input, &schemSz); + + /* list of public keys available for QSH schemes */ + offset_len = schemSz + OPAQUE16_LEN; + } + + offset_pk = ((input[offset_len] << 16) & 0xFF00000) | + (((input[offset_len + 1]) << 8) & 0xFF00) | + (input[offset_len + 2] & 0xFF); + offset_len += OPAQUE24_LEN; + + /* check buffer size */ + if (offset_pk > length) + return BUFFER_ERROR; + + /* set maximum number of keys the client will accept */ + if (!isRequest) + numKeys = (ssl->maxRequest < 1)? 1 : ssl->maxRequest; + + /* hello extension read list of scheme ids */ + if (isRequest) { + + /* read in request for public keys */ + ssl->minRequest = (input[length -1] >> 4) & 0xFF; + ssl->maxRequest = input[length -1] & 0x0F; + + /* choose the min between min requested by client and 1 */ + numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1; + + if (ssl->minRequest > ssl->maxRequest) + return BAD_FUNC_ARG; + + offset += OPAQUE16_LEN; + schemSz += offset; + + /* check buffer size */ + if (schemSz > length) + return BUFFER_ERROR; + + while ((offset < schemSz) && numKeys) { + /* Scheme ID list */ + ato16(input + offset, &name); + offset += OPAQUE16_LEN; + + /* validate we have scheme id */ + if (ssl->user_set_QSHSchemes && + !TLSX_ValidateQSHScheme(&ssl->extensions, name)) { + continue; + } + + /* server create keys on demand */ + if ((r = TLSX_CreateNtruKey(ssl, name)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return r; + } + + /* peer sent an agreed upon scheme */ + r = TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0); + + if (r != SSL_SUCCESS) return r; /* throw error */ + + numKeys--; + } + + /* choose the min between min requested by client and 1 */ + numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1; + } + + /* QSHPK struct */ + offset_pk += offset_len; + while ((offset_len < offset_pk) && numKeys) { + QSHKey * temp; + + if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + + /* initialize */ + temp->next = NULL; + temp->pub.buffer = NULL; + temp->pub.length = 0; + temp->pri.buffer = NULL; + temp->pri.length = 0; + + /* scheme id */ + ato16(input + offset_len, &(temp->name)); + offset_len += OPAQUE16_LEN; + + /* public key length */ + ato16(input + offset_len, &PKLen); + temp->pub.length = PKLen; + offset_len += OPAQUE16_LEN; + + + if (isRequest) { + /* validate we have scheme id */ + if (ssl->user_set_QSHSchemes && + (!TLSX_ValidateQSHScheme(&ssl->extensions, temp->name))) { + offset_len += PKLen; + XFREE(temp, 0, DYNAMIC_TYPE_TLSX); + continue; + } + } + + /* read in public key */ + if (PKLen > 0) { + temp->pub.buffer = (byte*)XMALLOC(temp->pub.length, + NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XMEMCPY(temp->pub.buffer, input + offset_len, temp->pub.length); + offset_len += PKLen; + } + else { + PK = NULL; + } + + /* use own key when adding to extensions list for sending reply */ + PKLen = 0; + PK = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, &PKLen, temp->name); + r = TLSX_UseQSHScheme(&ssl->extensions, temp->name, PK, PKLen); + + /* store peers key */ + ssl->peerQSHKeyPresent = 1; + if (TLSX_AddQSHKey(&ssl->peerQSHKey, temp) != 0) + return MEMORY_E; + + if (temp->pub.length == 0) { + XFREE(temp, 0, DYNAMIC_TYPE_TLSX); + } + + if (r != SSL_SUCCESS) {return r;} /* throw error */ + + numKeys--; + } + + /* reply to a QSH extension sent from client */ + if (isRequest) { + TLSX_SetResponse(ssl, TLSX_QUANTUM_SAFE_HYBRID); + /* only use schemes we have key generated for -- free the rest */ + TLSX_QSHAgreement(&ssl->extensions); + } + + return 0; +} + + +/* Used for parsing in QSHCipher structs on Key Exchange */ +int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isServer) +{ + QSHKey* key; + word16 Max_Secret_Len = 48; + word16 offset = 0; + word16 offset_len = 0; + word32 offset_pk = 0; + word16 name = 0; + word16 secretLen = 0; + byte* secret = NULL; + word16 buffLen = 0; + byte buff[145]; /* size enough for 3 secrets */ + buffer* buf; + + /* pointer to location where secret should be stored */ + if (isServer) { + buf = ssl->QSH_secret->CliSi; + } + else { + buf = ssl->QSH_secret->SerSi; + } + + offset_pk = ((input[offset_len] << 16) & 0xFF0000) | + (((input[offset_len + 1]) << 8) & 0xFF00) | + (input[offset_len + 2] & 0xFF); + offset_len += OPAQUE24_LEN; + + /* validating extension list length -- check if trying to read over edge + of buffer */ + if (length < (offset_pk + OPAQUE24_LEN)) { + return BUFFER_ERROR; + } + + /* QSHCipherList struct */ + offset_pk += offset_len; + while (offset_len < offset_pk) { + + /* scheme id */ + ato16(input + offset_len, &name); + offset_len += OPAQUE16_LEN; + + /* public key length */ + ato16(input + offset_len, &secretLen); + offset_len += OPAQUE16_LEN; + + /* read in public key */ + if (secretLen > 0) { + secret = (byte*)(input + offset_len); + offset_len += secretLen; + } + else { + secret = NULL; + } + + /* no secret sent */ + if (secret == NULL) + continue; + + /* find corresponding key */ + key = ssl->QSH_Key; + while (key) { + if (key->name == name) + break; + else + key = (QSHKey*)key->next; + } + + /* if we do not have the key than there was a big issue negotiation */ + if (key == NULL) { + WOLFSSL_MSG("key was null for decryption!!!\n"); + return MEMORY_E; + } + + /* Decrypt sent secret */ + buffLen = Max_Secret_Len; + QSH_Decrypt(key, secret, secretLen, buff + offset, &buffLen); + offset += buffLen; + } + + /* allocate memory for buffer */ + buf->length = offset; + buf->buffer = (byte*)XMALLOC(offset, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf->buffer == NULL) + return MEMORY_E; + + /* store secrets */ + XMEMCPY(buf->buffer, buff, offset); + ForceZero(buff, offset); + + return offset_len; +} + + +/* return 1 on success */ +int TLSX_ValidateQSHScheme(TLSX** extensions, word16 theirs) { + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + QSHScheme* format = NULL; + + /* if no extension is sent then do not use QSH */ + if (!extension) { + WOLFSSL_MSG("No QSH Extension"); + return 0; + } + + for (format = (QSHScheme*)extension->data; format; format = format->next) { + if (format->name == theirs) { + WOLFSSL_MSG("Found Matching QSH Scheme"); + return 1; /* have QSH */ + } + } + + return 0; +} +#endif /* NO_WOLFSSL_SERVER */ + +/* test if the QSH Scheme is implemented + return 1 if yes 0 if no */ +static int TLSX_HaveQSHScheme(word16 name) +{ + switch(name) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + return 1; + #endif + case WOLFSSL_LWE_XXX: + case WOLFSSL_HFE_XXX: + return 0; /* not supported yet */ + + default: + return 0; + } +} + + +/* Add a QSHScheme struct to list of usable ones */ +int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz) +{ + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + QSHScheme* format = NULL; + int ret = 0; + + /* sanity check */ + if (extensions == NULL || (pKey == NULL && pkeySz != 0)) + return BAD_FUNC_ARG; + + /* if scheme is implemented than add */ + if (TLSX_HaveQSHScheme(name)) { + if ((ret = TLSX_QSH_Append(&format, name, pKey, pkeySz)) != 0) + return ret; + + if (!extension) { + if ((ret = TLSX_Push(extensions, TLSX_QUANTUM_SAFE_HYBRID, format)) + != 0) { + XFREE(format, 0, DYNAMIC_TYPE_TLSX); + return ret; + } + } + else { + /* push new QSH object to extension data. */ + format->next = (QSHScheme*)extension->data; + extension->data = (void*)format; + + /* look for another format of the same name to remove (replacement) */ + do { + if (format->next && (format->next->name == name)) { + QSHScheme* next = format->next; + + format->next = next->next; + XFREE(next, 0, DYNAMIC_TYPE_TLSX); + + break; + } + } while ((format = format->next)); + } + } + return SSL_SUCCESS; +} + +#define QSH_FREE_ALL TLSX_QSH_FreeAll +#define QSH_VALIDATE_REQUEST TLSX_QSH_ValidateRequest + +#ifndef NO_WOLFSSL_CLIENT +#define QSH_GET_SIZE TLSX_QSH_GetSize +#define QSH_WRITE TLSX_QSH_Write +#else +#define QSH_GET_SIZE(list) 0 +#define QSH_WRITE(a, b) 0 +#endif + +#ifndef NO_WOLFSSL_SERVER +#define QSH_PARSE TLSX_QSH_Parse +#else +#define QSH_PARSE(a, b, c, d) 0 +#endif + +#define QSHPK_WRITE TLSX_QSHPK_Write +#define QSH_SERREQ TLSX_QSH_SerPKReq +#else + +#define QSH_FREE_ALL(list) +#define QSH_GET_SIZE(list, a) 0 +#define QSH_WRITE(a, b) 0 +#define QSH_PARSE(a, b, c, d) 0 +#define QSHPK_WRITE(a, b) 0 +#define QSH_SERREQ(a, b) 0 +#define QSH_VALIDATE_REQUEST(a, b) + +#endif /* HAVE_QSH */ + +/******************************************************************************/ +/* TLS Extensions Framework */ +/******************************************************************************/ + +/** Finds an extension in the provided list. */ +TLSX* TLSX_Find(TLSX* list, TLSX_Type type) +{ + TLSX* extension = list; + + while (extension && extension->type != type) + extension = extension->next; + + return extension; +} + +/** Releases all extensions in the provided list. */ +void TLSX_FreeAll(TLSX* list) +{ + TLSX* extension; + + while ((extension = list)) { + list = extension->next; + + switch (extension->type) { + + case TLSX_SERVER_NAME: + SNI_FREE_ALL((SNI*)extension->data); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + MFL_FREE_ALL(extension->data); + break; + + case TLSX_TRUNCATED_HMAC: + /* Nothing to do. */ + break; + + case TLSX_SUPPORTED_GROUPS: + EC_FREE_ALL(extension->data); + break; + + case TLSX_STATUS_REQUEST: + CSR_FREE_ALL(extension->data); + break; + + case TLSX_STATUS_REQUEST_V2: + CSR2_FREE_ALL(extension->data); + break; + + case TLSX_RENEGOTIATION_INFO: + SCR_FREE_ALL(extension->data); + break; + + case TLSX_SESSION_TICKET: + /* Nothing to do. */ + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + QSH_FREE_ALL((QSHScheme*)extension->data); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + ALPN_FREE_ALL((ALPN*)extension->data); + break; + } + + XFREE(extension, 0, DYNAMIC_TYPE_TLSX); + } +} + +/** Checks if the tls extensions are supported based on the protocol version. */ +int TLSX_SupportExtensions(WOLFSSL* ssl) { + return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR); +} + +/** Tells the buffered size of the extensions in a list. */ +static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) +{ + TLSX* extension; + word16 length = 0; + + while ((extension = list)) { + list = extension->next; + + /* only extensions marked as response are sent back to the client. */ + if (!isRequest && !extension->resp) + continue; /* skip! */ + + /* ssl level extensions are expected to override ctx level ones. */ + if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type))) + continue; /* skip! */ + + /* extension type + extension data length. */ + length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; + + + switch (extension->type) { + + case TLSX_SERVER_NAME: + /* SNI only sends the name on the request. */ + if (isRequest) + length += SNI_GET_SIZE(extension->data); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + length += MFL_GET_SIZE(extension->data); + break; + + case TLSX_TRUNCATED_HMAC: + /* always empty. */ + break; + + case TLSX_SUPPORTED_GROUPS: + length += EC_GET_SIZE(extension->data); + break; + + case TLSX_STATUS_REQUEST: + length += CSR_GET_SIZE(extension->data, isRequest); + break; + + case TLSX_STATUS_REQUEST_V2: + length += CSR2_GET_SIZE(extension->data, isRequest); + break; + + case TLSX_RENEGOTIATION_INFO: + length += SCR_GET_SIZE(extension->data, isRequest); + break; + + case TLSX_SESSION_TICKET: + length += STK_GET_SIZE(extension->data, isRequest); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + length += QSH_GET_SIZE((QSHScheme*)extension->data, isRequest); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + length += ALPN_GET_SIZE(extension->data); + break; + + } + + /* marks the extension as processed so ctx level */ + /* extensions don't overlap with ssl level ones. */ + TURN_ON(semaphore, TLSX_ToSemaphore(extension->type)); + } + + return length; +} + +/** Writes the extensions of a list in a buffer. */ +static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, + byte isRequest) +{ + TLSX* extension; + word16 offset = 0; + word16 length_offset = 0; + + while ((extension = list)) { + list = extension->next; + + /* only extensions marked as response are written in a response. */ + if (!isRequest && !extension->resp) + continue; /* skip! */ + + /* ssl level extensions are expected to override ctx level ones. */ + if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type))) + continue; /* skip! */ + + /* writes extension type. */ + c16toa(extension->type, output + offset); + offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; + length_offset = offset; + + /* extension data should be written internally. */ + switch (extension->type) { + case TLSX_SERVER_NAME: + if (isRequest) + offset += SNI_WRITE(extension->data, output + offset); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + offset += MFL_WRITE(extension->data, output + offset); + break; + + case TLSX_TRUNCATED_HMAC: + /* always empty. */ + break; + + case TLSX_SUPPORTED_GROUPS: + offset += EC_WRITE(extension->data, output + offset); + break; + + case TLSX_STATUS_REQUEST: + offset += CSR_WRITE(extension->data, output + offset, + isRequest); + break; + + case TLSX_STATUS_REQUEST_V2: + offset += CSR2_WRITE(extension->data, output + offset, + isRequest); + break; + + case TLSX_RENEGOTIATION_INFO: + offset += SCR_WRITE(extension->data, output + offset, + isRequest); + break; + + case TLSX_SESSION_TICKET: + offset += STK_WRITE(extension->data, output + offset, + isRequest); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + if (isRequest) { + offset += QSH_WRITE((QSHScheme*)extension->data, output + offset); + } + offset += QSHPK_WRITE((QSHScheme*)extension->data, output + offset); + offset += QSH_SERREQ(output + offset, isRequest); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + offset += ALPN_WRITE(extension->data, output + offset); + break; + } + + /* writes extension data length. */ + c16toa(offset - length_offset, output + length_offset - OPAQUE16_LEN); + + /* marks the extension as processed so ctx level */ + /* extensions don't overlap with ssl level ones. */ + TURN_ON(semaphore, TLSX_ToSemaphore(extension->type)); + } + + return offset; +} + + +#ifdef HAVE_NTRU + +static word32 GetEntropy(unsigned char* out, word32 num_bytes) +{ + int ret = 0; + + if (rng == NULL) { + if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitRng(rng); + } + + if (rngMutex == NULL) { + if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return DRBG_OUT_OF_MEMORY; + InitMutex(rngMutex); + } + + ret |= LockMutex(rngMutex); + ret |= wc_RNG_GenerateBlock(rng, out, num_bytes); + ret |= UnLockMutex(rngMutex); + + if (ret != 0) + return DRBG_ENTROPY_FAIL; + + return DRBG_OK; +} +#endif + + +#ifdef HAVE_QSH +static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type) +{ + int ret; + + switch (type) { +#ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + ret = TLSX_CreateNtruKey(ssl, type); + break; +#endif + default: + WOLFSSL_MSG("Unknown type for creating NTRU key"); + return -1; + } + + return ret; +} + + +static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key) +{ + QSHKey* current; + + if (key == NULL) + return BAD_FUNC_ARG; + + /* if no public key stored in key then do not add */ + if (key->pub.length == 0 || key->pub.buffer == NULL) + return 0; + + /* first element to be added to the list */ + current = *list; + if (current == NULL) { + *list = key; + return 0; + } + + while (current->next) { + /* can only have one of the key in the list */ + if (current->name == key->name) + return -1; + current = (QSHKey*)current->next; + } + + current->next = (struct QSHKey*)key; + + return 0; +} + + +#ifdef HAVE_NTRU +int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) +{ + int ret; + int ntruType; + + /* variable declarations for NTRU*/ + QSHKey* temp = NULL; + byte public_key[1027]; + word16 public_key_len = sizeof(public_key); + byte private_key[1120]; + word16 private_key_len = sizeof(private_key); + DRBG_HANDLE drbg; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WOLFSSL_NTRU_EESS439: + ntruType = NTRU_EES439EP1; + break; + case WOLFSSL_NTRU_EESS593: + ntruType = NTRU_EES593EP1; + break; + case WOLFSSL_NTRU_EESS743: + ntruType = NTRU_EES743EP1; + break; + default: + WOLFSSL_MSG("Unknown type for creating NTRU key"); + return -1; + } + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) { + WOLFSSL_MSG("NTRU drbg instantiate failed\n"); + return ret; + } + + if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType, + &public_key_len, NULL, &private_key_len, NULL)) != NTRU_OK) + return ret; + + if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType, + &public_key_len, public_key, &private_key_len, private_key)) != NTRU_OK) + return ret; + + ret = ntru_crypto_drbg_uninstantiate(drbg); + if (ret != NTRU_OK) { + WOLFSSL_MSG("NTRU drbg uninstantiate failed\n"); + return ret; + } + + if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + temp->name = type; + temp->pub.length = public_key_len; + temp->pub.buffer = (byte*)XMALLOC(public_key_len, public_key, + DYNAMIC_TYPE_PUBLIC_KEY); + XMEMCPY(temp->pub.buffer, public_key, public_key_len); + temp->pri.length = private_key_len; + temp->pri.buffer = (byte*)XMALLOC(private_key_len, private_key, + DYNAMIC_TYPE_ARRAYS); + XMEMCPY(temp->pri.buffer, private_key, private_key_len); + temp->next = NULL; + + TLSX_AddQSHKey(&ssl->QSH_Key, temp); + + return ret; +} +#endif + + +/* + Used to find a public key from the list of keys + pubLen length of array + name input the name of the scheme looking for ie WOLFSSL_NTRU_ESSXXX + + returns a pointer to public key byte* or NULL if not found + */ +static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name) +{ + QSHKey* current = qsh; + + if (qsh == NULL || pubLen == NULL) + return NULL; + + *pubLen = 0; + + while(current) { + if (current->name == name) { + *pubLen = current->pub.length; + return current->pub.buffer; + } + current = (QSHKey*)current->next; + } + + return NULL; +} +#endif /* HAVE_QSH */ + + +int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) +{ + byte* public_key = NULL; + word16 public_key_len = 0; + #ifdef HAVE_QSH + TLSX* extension; + QSHScheme* qsh; + QSHScheme* next; + #endif + int ret = 0; + + #ifdef HAVE_QSH + /* add supported QSHSchemes */ + WOLFSSL_MSG("Adding supported QSH Schemes"); + + /* server will add extension depending on whats parsed from client */ + if (!isServer) { + + /* test if user has set a specific scheme already */ + if (!ssl->user_set_QSHSchemes) { + if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + + /* add NTRU 256 */ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS743); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743, + public_key, public_key_len) != SSL_SUCCESS) + ret = -1; + + /* add NTRU 196 */ + if (ssl->sendQSHKeys) { + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS593); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593, + public_key, public_key_len) != SSL_SUCCESS) + ret = -1; + + /* add NTRU 128 */ + if (ssl->sendQSHKeys) { + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS439); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439, + public_key, public_key_len) != SSL_SUCCESS) + ret = -1; + } + else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + /* for each scheme make a client key */ + extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (extension) { + qsh = (QSHScheme*)extension->data; + + while (qsh) { + if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0) + return ret; + + /* get next now because qsh could be freed */ + next = qsh->next; + + /* find the public key created and add to extension*/ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, qsh->name); + if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name, + public_key, public_key_len) != SSL_SUCCESS) + ret = -1; + qsh = next; + } + } + } + } /* is not server */ + #endif + + (void)isServer; + (void)public_key; + (void)public_key_len; + (void)ssl; + + return ret; +} + + +#ifndef NO_WOLFSSL_CLIENT + +/** Tells the buffered size of extensions to be sent into the client hello. */ +word16 TLSX_GetRequestSize(WOLFSSL* ssl) +{ + word16 length = 0; + + if (TLSX_SupportExtensions(ssl)) { + byte semaphore[SEMAPHORE_SIZE] = {0}; + + EC_VALIDATE_REQUEST(ssl, semaphore); + QSH_VALIDATE_REQUEST(ssl, semaphore); + STK_VALIDATE_REQUEST(ssl); + + if (ssl->extensions) + length += TLSX_GetSize(ssl->extensions, semaphore, 1); + + if (ssl->ctx && ssl->ctx->extensions) + length += TLSX_GetSize(ssl->ctx->extensions, semaphore, 1); + + if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) + length += ssl->suites->hashSigAlgoSz + HELLO_EXT_LEN; + } + + if (length) + length += OPAQUE16_LEN; /* for total length storage. */ + + return length; +} + +/** Writes the extensions to be sent into the client hello. */ +word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) +{ + word16 offset = 0; + + if (TLSX_SupportExtensions(ssl) && output) { + byte semaphore[SEMAPHORE_SIZE] = {0}; + + offset += OPAQUE16_LEN; /* extensions length */ + + EC_VALIDATE_REQUEST(ssl, semaphore); + STK_VALIDATE_REQUEST(ssl); + QSH_VALIDATE_REQUEST(ssl, semaphore); + + if (ssl->extensions) + offset += TLSX_Write(ssl->extensions, output + offset, + semaphore, 1); + + if (ssl->ctx && ssl->ctx->extensions) + offset += TLSX_Write(ssl->ctx->extensions, output + offset, + semaphore, 1); + + if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) + { + int i; + /* extension type */ + c16toa(HELLO_EXT_SIG_ALGO, output + offset); + offset += HELLO_EXT_TYPE_SZ; + + /* extension data length */ + c16toa(OPAQUE16_LEN + ssl->suites->hashSigAlgoSz, output + offset); + offset += OPAQUE16_LEN; + + /* sig algos length */ + c16toa(ssl->suites->hashSigAlgoSz, output + offset); + offset += OPAQUE16_LEN; + + /* sig algos */ + for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++) + output[offset] = ssl->suites->hashSigAlgo[i]; + } + + if (offset > OPAQUE16_LEN) + c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ + } + + return offset; +} + +#endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + +/** Tells the buffered size of extensions to be sent into the server hello. */ +word16 TLSX_GetResponseSize(WOLFSSL* ssl) +{ + word16 length = 0; + byte semaphore[SEMAPHORE_SIZE] = {0}; + + #ifdef HAVE_QSH + /* change response if not using TLS_QSH */ + if (!ssl->options.haveQSH) { + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (ext) + ext->resp = 0; + } + #endif + + if (TLSX_SupportExtensions(ssl)) + length += TLSX_GetSize(ssl->extensions, semaphore, 0); + + /* All the response data is set at the ssl object only, so no ctx here. */ + + if (length) + length += OPAQUE16_LEN; /* for total length storage */ + + return length; +} + +/** Writes the server hello extensions into a buffer. */ +word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) +{ + word16 offset = 0; + + if (TLSX_SupportExtensions(ssl) && output) { + byte semaphore[SEMAPHORE_SIZE] = {0}; + + offset += OPAQUE16_LEN; /* extensions length */ + + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, 0); + + if (offset > OPAQUE16_LEN) + c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ + } + + return offset; +} + +#endif /* NO_WOLFSSL_SERVER */ + +/** Parses a buffer of TLS extensions. */ +int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, + Suites *suites) +{ + int ret = 0; + word16 offset = 0; + + if (!ssl || !input || (isRequest && !suites)) + return BAD_FUNC_ARG; + + while (ret == 0 && offset < length) { + word16 type; + word16 size; + + if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &type); + offset += HELLO_EXT_TYPE_SZ; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN; + + if (offset + size > length) + return BUFFER_ERROR; + + switch (type) { + case TLSX_SERVER_NAME: + WOLFSSL_MSG("SNI extension received"); + + ret = SNI_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + WOLFSSL_MSG("Max Fragment Length extension received"); + + ret = MFL_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_TRUNCATED_HMAC: + WOLFSSL_MSG("Truncated HMAC extension received"); + + ret = THM_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_SUPPORTED_GROUPS: + WOLFSSL_MSG("Elliptic Curves extension received"); + + ret = EC_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_STATUS_REQUEST: + WOLFSSL_MSG("Certificate Status Request extension received"); + + ret = CSR_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_STATUS_REQUEST_V2: + WOLFSSL_MSG("Certificate Status Request v2 extension received"); + + ret = CSR2_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_RENEGOTIATION_INFO: + WOLFSSL_MSG("Secure Renegotiation extension received"); + + ret = SCR_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_SESSION_TICKET: + WOLFSSL_MSG("Session Ticket extension received"); + + ret = STK_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); + + ret = QSH_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + WOLFSSL_MSG("ALPN extension received"); + + ret = ALPN_PARSE(ssl, input + offset, size, isRequest); + break; + + case HELLO_EXT_SIG_ALGO: + if (isRequest) { + /* do not mess with offset inside the switch! */ + if (IsAtLeastTLSv1_2(ssl)) { + ato16(input + offset, &suites->hashSigAlgoSz); + + if (suites->hashSigAlgoSz > size - OPAQUE16_LEN) + return BUFFER_ERROR; + + XMEMCPY(suites->hashSigAlgo, + input + offset + OPAQUE16_LEN, + min(suites->hashSigAlgoSz, + HELLO_EXT_SIGALGO_MAX)); + } + } else { + WOLFSSL_MSG("Servers MUST NOT send SIG ALGO extension."); + } + + break; + } + + /* offset should be updated here! */ + offset += size; + } + + if (ret == 0) + ret = SNI_VERIFY_PARSE(ssl, isRequest); + + return ret; +} + +/* undefining semaphore macros */ +#undef IS_OFF +#undef TURN_ON +#undef SEMAPHORE_SIZE + +#endif /* HAVE_TLS_EXTENSIONS */ + +#ifndef NO_WOLFSSL_CLIENT + +#ifndef NO_OLD_TLS + + WOLFSSL_METHOD* wolfTLSv1_client_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + if (method) + InitSSL_Method(method, MakeTLSv1()); + return method; + } + + + WOLFSSL_METHOD* wolfTLSv1_1_client_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + if (method) + InitSSL_Method(method, MakeTLSv1_1()); + return method; + } + +#endif /* !NO_OLD_TLS */ + +#ifndef NO_SHA256 /* can't use without SHA256 */ + + WOLFSSL_METHOD* wolfTLSv1_2_client_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + if (method) + InitSSL_Method(method, MakeTLSv1_2()); + return method; + } + +#endif + + + WOLFSSL_METHOD* wolfSSLv23_client_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + if (method) { +#ifndef NO_SHA256 /* 1.2 requires SHA256 */ + InitSSL_Method(method, MakeTLSv1_2()); +#else + InitSSL_Method(method, MakeTLSv1_1()); +#endif +#ifndef NO_OLD_TLS + method->downgrade = 1; +#endif + } + return method; + } + + +#endif /* NO_WOLFSSL_CLIENT */ + + + +#ifndef NO_WOLFSSL_SERVER + +#ifndef NO_OLD_TLS + + WOLFSSL_METHOD* wolfTLSv1_server_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + if (method) { + InitSSL_Method(method, MakeTLSv1()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + + + WOLFSSL_METHOD* wolfTLSv1_1_server_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + if (method) { + InitSSL_Method(method, MakeTLSv1_1()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + +#endif /* !NO_OLD_TLS */ + +#ifndef NO_SHA256 /* can't use without SHA256 */ + + WOLFSSL_METHOD* wolfTLSv1_2_server_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + if (method) { + InitSSL_Method(method, MakeTLSv1_2()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + +#endif + + + WOLFSSL_METHOD* wolfSSLv23_server_method(void) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, + DYNAMIC_TYPE_METHOD); + if (method) { +#ifndef NO_SHA256 /* 1.2 requires SHA256 */ + InitSSL_Method(method, MakeTLSv1_2()); +#else + InitSSL_Method(method, MakeTLSv1_1()); +#endif + method->side = WOLFSSL_SERVER_END; +#ifndef NO_OLD_TLS + method->downgrade = 1; +#endif /* !NO_OLD_TLS */ + } + return method; + } + + + +#endif /* NO_WOLFSSL_SERVER */ +#endif /* NO_TLS */ +#endif /* WOLFCRYPT_ONLY */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/aes.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,4344 @@ +/* aes.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_AES + +#include <wolfssl/wolfcrypt/aes.h> + +#ifdef HAVE_FIPS +int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, + int dir) +{ + return AesSetKey_fips(aes, key, len, iv, dir); +} + + +int wc_AesSetIV(Aes* aes, const byte* iv) +{ + return AesSetIV_fips(aes, iv); +} + + +#ifdef HAVE_AES_CBC +int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return AesCbcEncrypt_fips(aes, out, in, sz); +} + +#ifdef HAVE_AES_DECRYPT +int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return AesCbcDecrypt_fips(aes, out, in, sz); +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC */ + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER +void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + 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 + + +#ifdef HAVE_AESGCM +int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) +{ + 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) +{ + 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) +{ + 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) +{ + return GmacSetKey(gmac, key, len); +} + + +int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz) +{ + return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, + authTag, authTagSz); +} + +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM +void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +{ + 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) +{ + return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, + authIn, authInSz); +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AESCCM */ + +#ifdef HAVE_CAVIUM +int wc_AesInitCavium(Aes* aes, int i) +{ + return AesInitCavium(aes, i); +} + + +void wc_AesFreeCavium(Aes* aes) +{ + AesFreeCavium(aes); +} +#endif +#else /* HAVE_FIPS */ + +#ifdef WOLFSSL_TI_CRYPT +#include <wolfcrypt/src/port/ti/ti-aes.c> +#else + +#include <wolfssl/wolfcrypt/error-crypt.h> +#include <wolfssl/wolfcrypt/logging.h> +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#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(STM32F2_CRYPTO) + /* STM32F2 hardware AES support for CBC, CTR modes through the STM32F2 + * Standard Peripheral Library. Documentation located in STM32F2xx + * Standard Peripheral Library document (See note in README). + * NOTE: no support for AES-GCM/CCM/Direct */ + #include "stm32f2xx.h" + #include "stm32f2xx_cryp.h" +#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_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). + * NOTE: no support for AES-CTR */ + #include "cau_api.h" + + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + cau_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + #ifdef HAVE_AES_DECRYPT + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + cau_aes_decrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + #endif /* HAVE_AES_DECRYPT */ +#elif defined(WOLFSSL_PIC32MZ_CRYPT) + /* NOTE: no support for AES-CCM/Direct */ + #define DEBUG_WOLFSSL + #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" +#elif defined(HAVE_CAVIUM) + #include <wolfssl/wolfcrypt/logging.h> + #include "cavium_common.h" + + /* still leave SW crypto available */ + #define NEED_AES_TABLES + + static int wc_AesCaviumSetKey(Aes* aes, const byte* key, word32 length, + const byte* iv); + #ifdef HAVE_AES_CBC + static int wc_AesCaviumCbcEncrypt(Aes* aes, byte* out, const byte* in, + word32 length); + #ifdef HAVE_AES_DECRYPT + static int wc_AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, + word32 length); + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ +#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 */ + +#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[5][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, +}, +{ + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +} +}; + +static const word32 Td[5][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, +}, +{ + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +} +}; + +#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) + + +#ifdef WOLFSSL_AESNI + +/* 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, func)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (func)); + + #define XASM_LINK(f) asm(f) +#else + + #include <intrin.h> + #define cpuid(a,b) __cpuid((int*)a,b) + + #define XASM_LINK(f) + +#endif /* _MSC_VER */ + + +static int Check_CPU_support_AES(void) +{ + unsigned int reg[4]; /* put a,b,c,d into 0,1,2,3 */ + cpuid(reg, 1); /* query info 1 */ + + if (reg[2] & 0x2000000) + return 1; + + return 0; +} + +static int checkAESNI = 0; +static int haveAESNI = 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 +void AES_CBC_decrypt(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt"); +#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) +{ + if (!userKey || !aes) + return BAD_FUNC_ARG; + + if (bits == 128) { + AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; + return 0; + } + else if (bits == 192) { + AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; + return 0; + } + else if (bits == 256) { + AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; + return 0; + } + return BAD_FUNC_ARG; +} + +#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 */ +#endif /* WOLFSSL_AESNI */ + +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) ||\ + defined(HAVE_AESGCM) + +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 % 16) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp = (byte*)XMALLOC(AES_BLOCK_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) return; + + XMEMCPY(tmp, inBlock, AES_BLOCK_SIZE); + AES_ECB_encrypt(tmp, tmp, AES_BLOCK_SIZE, (byte*)aes->key, + aes->rounds); + XMEMCPY(outBlock, tmp, AES_BLOCK_SIZE); + XFREE(tmp, NULL, 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]; + + /* + * 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[4][GETBYTE(t0, 3)] & 0xff000000) ^ + (Te[4][GETBYTE(t1, 2)] & 0x00ff0000) ^ + (Te[4][GETBYTE(t2, 1)] & 0x0000ff00) ^ + (Te[4][GETBYTE(t3, 0)] & 0x000000ff) ^ + rk[0]; + s1 = + (Te[4][GETBYTE(t1, 3)] & 0xff000000) ^ + (Te[4][GETBYTE(t2, 2)] & 0x00ff0000) ^ + (Te[4][GETBYTE(t3, 1)] & 0x0000ff00) ^ + (Te[4][GETBYTE(t0, 0)] & 0x000000ff) ^ + rk[1]; + s2 = + (Te[4][GETBYTE(t2, 3)] & 0xff000000) ^ + (Te[4][GETBYTE(t3, 2)] & 0x00ff0000) ^ + (Te[4][GETBYTE(t0, 1)] & 0x0000ff00) ^ + (Te[4][GETBYTE(t1, 0)] & 0x000000ff) ^ + rk[2]; + s3 = + (Te[4][GETBYTE(t3, 3)] & 0xff000000) ^ + (Te[4][GETBYTE(t0, 2)] & 0x00ff0000) ^ + (Te[4][GETBYTE(t1, 1)] & 0x0000ff00) ^ + (Te[4][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 */ + +#ifdef HAVE_AES_DECRYPT +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) +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 + + /* + * 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]; + + /* + * 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: + */ + s0 = + (Td[4][GETBYTE(t0, 3)] & 0xff000000) ^ + (Td[4][GETBYTE(t3, 2)] & 0x00ff0000) ^ + (Td[4][GETBYTE(t2, 1)] & 0x0000ff00) ^ + (Td[4][GETBYTE(t1, 0)] & 0x000000ff) ^ + rk[0]; + s1 = + (Td[4][GETBYTE(t1, 3)] & 0xff000000) ^ + (Td[4][GETBYTE(t0, 2)] & 0x00ff0000) ^ + (Td[4][GETBYTE(t3, 1)] & 0x0000ff00) ^ + (Td[4][GETBYTE(t2, 0)] & 0x000000ff) ^ + rk[1]; + s2 = + (Td[4][GETBYTE(t2, 3)] & 0xff000000) ^ + (Td[4][GETBYTE(t1, 2)] & 0x00ff0000) ^ + (Td[4][GETBYTE(t0, 1)] & 0x0000ff00) ^ + (Td[4][GETBYTE(t3, 0)] & 0x000000ff) ^ + rk[2]; + s3 = + (Td[4][GETBYTE(t3, 3)] & 0xff000000) ^ + (Td[4][GETBYTE(t2, 2)] & 0x00ff0000) ^ + (Td[4][GETBYTE(t1, 1)] & 0x0000ff00) ^ + (Td[4][GETBYTE(t0, 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_DECRYPT */ +#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ + +#endif /* NEED_AES_TABLES */ + + +/* wc_AesSetKey */ +#ifdef STM32F2_CRYPTO + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, + int dir) + { + word32 *rk = aes->key; + + if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + return BAD_FUNC_ARG; + + aes->rounds = keylen/4 + 6; + XMEMCPY(rk, userKey, keylen); + ByteReverseWords(rk, rk, keylen); + + 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(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 + + InitMutex(&Mutex_AesSEC); + } + + if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + return BAD_FUNC_ARG; + + if (aes == NULL) + return BAD_FUNC_ARG; + + aes->rounds = keylen/4 + 6; + XMEMCPY(aes->key, userKey, keylen); + + if (iv) + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + + return 0; + } +#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; + + aes->rounds = keylen/4 + 6; + + ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + cau_aes_set_key(userKey, keylen*8, rk); + 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->rounds = keylen/4 + 6; + ret = nrf51_aes_set_key(userKey); + + 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); + } +#else + static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + word32 temp, *rk = aes->key; + unsigned int i = 0; + + #ifdef WOLFSSL_AESNI + aes->use_aesni = 0; + #endif /* WOLFSSL_AESNI */ + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ + + aes->rounds = keylen/4 + 6; + + XMEMCPY(rk, userKey, keylen); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(rk, rk, keylen); + #endif + + #ifdef WOLFSSL_PIC32MZ_CRYPT + { + word32 *akey1 = aes->key_ce; + word32 *areg = aes->iv_ce ; + aes->keylen = keylen ; + XMEMCPY(akey1, userKey, keylen); + if (iv) + XMEMCPY(areg, iv, AES_BLOCK_SIZE); + else + XMEMSET(areg, 0, AES_BLOCK_SIZE); + } + #endif + + switch(keylen) + { +#if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 + case 16: + while (1) + { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[4][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 + case 24: + /* for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack */ + while (1) + { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[4][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 + case 32: + while (1) + { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[4][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[4][GETBYTE(temp, 3)] & 0xff000000) ^ + (Te[4][GETBYTE(temp, 2)] & 0x00ff0000) ^ + (Te[4][GETBYTE(temp, 1)] & 0x0000ff00) ^ + (Te[4][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; + } + +#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[4][GETBYTE(rk[0], 3)] & 0xff] ^ + Td[1][Te[4][GETBYTE(rk[0], 2)] & 0xff] ^ + Td[2][Te[4][GETBYTE(rk[0], 1)] & 0xff] ^ + Td[3][Te[4][GETBYTE(rk[0], 0)] & 0xff]; + rk[1] = + Td[0][Te[4][GETBYTE(rk[1], 3)] & 0xff] ^ + Td[1][Te[4][GETBYTE(rk[1], 2)] & 0xff] ^ + Td[2][Te[4][GETBYTE(rk[1], 1)] & 0xff] ^ + Td[3][Te[4][GETBYTE(rk[1], 0)] & 0xff]; + rk[2] = + Td[0][Te[4][GETBYTE(rk[2], 3)] & 0xff] ^ + Td[1][Te[4][GETBYTE(rk[2], 2)] & 0xff] ^ + Td[2][Te[4][GETBYTE(rk[2], 1)] & 0xff] ^ + Td[3][Te[4][GETBYTE(rk[2], 0)] & 0xff]; + rk[3] = + Td[0][Te[4][GETBYTE(rk[3], 3)] & 0xff] ^ + Td[1][Te[4][GETBYTE(rk[3], 2)] & 0xff] ^ + Td[2][Te[4][GETBYTE(rk[3], 1)] & 0xff] ^ + Td[3][Te[4][GETBYTE(rk[3], 0)] & 0xff]; + } + } +#endif /* HAVE_AES_DECRYPT */ + + return wc_AesSetIV(aes, iv); + } + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, + int dir) + { + #if defined(AES_MAX_KEY_SIZE) + const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); + #endif + + if (!((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 + + #ifdef HAVE_CAVIUM + if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) + return wc_AesCaviumSetKey(aes, userKey, keylen, iv); + #endif + + #ifdef WOLFSSL_AESNI + if (checkAESNI == 0) { + haveAESNI = Check_CPU_support_AES(); + checkAESNI = 1; + } + if (haveAESNI) { + 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 */ + + return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + } + + #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) + { + return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + } + + #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */ +#endif /* STM32F2_CRYPTO, 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(STM32F2_CRYPTO) + #error "STM32F2 crypto doesn't yet support AES direct" + + #elif defined(HAVE_COLDFIRE_SEC) + #error "Coldfire SEC doesn't yet support AES direct" + + #elif defined(WOLFSSL_PIC32MZ_CRYPT) + #error "PIC32MZ doesn't yet support AES direct" + + #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 +#ifdef STM32F2_CRYPTO + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + 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 */ + 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 (sz > 0) + { + /* 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 -= 16; + in += 16; + out += 16; + } + + /* 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; + 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 (sz > 0) + { + /* 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); + + sz -= 16; + in += 16; + out += 16; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + + return 0; + } + #endif /* HAVE_AES_DECRYPT */ +#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*/ + + 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; + } + + 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_MMCAU) + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int i; + int offset = 0; + int len = sz; + + byte *iv; + byte temp_block[AES_BLOCK_SIZE]; + + iv = (byte*)aes->reg; + + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_aes_encrypt alignment"); + return BAD_ALIGN_E; + } + + while (len > 0) + { + 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); + + len -= AES_BLOCK_SIZE; + 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; + int len = sz; + + byte* iv; + byte temp_block[AES_BLOCK_SIZE]; + + iv = (byte*)aes->reg; + + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_aes_decrypt alignment"); + return BAD_ALIGN_E; + } + + while (len > 0) + { + 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); + + len -= AES_BLOCK_SIZE; + offset += AES_BLOCK_SIZE; + } + + return 0; + } + #endif /* HAVE_AES_DECRYPT */ +#elif defined(WOLFSSL_PIC32MZ_CRYPT) + /* core hardware crypt engine driver */ + static void wc_AesCrypt(Aes *aes, byte* out, const byte* in, word32 sz, + int dir, int algo, int cryptoalgo) + { + securityAssociation *sa_p ; + bufferDescriptor *bd_p ; + + volatile securityAssociation sa __attribute__((aligned (8))); + volatile bufferDescriptor bd __attribute__((aligned (8))); + volatile int k ; + + /* get uncached address */ + sa_p = KVA0_TO_KVA1(&sa) ; + bd_p = KVA0_TO_KVA1(&bd) ; + + /* Sync cache and physical memory */ + if(PIC32MZ_IF_RAM(in)) { + XMEMCPY((void *)KVA0_TO_KVA1(in), (void *)in, sz); + } + XMEMSET((void *)KVA0_TO_KVA1(out), 0, sz); + /* Set up the Security Association */ + XMEMSET((byte *)KVA0_TO_KVA1(&sa), 0, sizeof(sa)); + sa_p->SA_CTRL.ALGO = algo ; /* AES */ + sa_p->SA_CTRL.LNC = 1; + sa_p->SA_CTRL.LOADIV = 1; + sa_p->SA_CTRL.FB = 1; + sa_p->SA_CTRL.ENCTYPE = dir ; /* Encryption/Decryption */ + sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; + + if(cryptoalgo == PIC32_CRYPTOALGO_AES_GCM){ + switch(aes->keylen) { + case 32: + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_256 ; + break ; + case 24: + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_192 ; + break ; + case 16: + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128 ; + break ; + } + } else + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128 ; + + ByteReverseWords( + (word32 *)KVA0_TO_KVA1(sa.SA_ENCKEY + 8 - aes->keylen/sizeof(word32)), + (word32 *)aes->key_ce, aes->keylen); + ByteReverseWords( + (word32*)KVA0_TO_KVA1(sa.SA_ENCIV), (word32 *)aes->iv_ce, 16); + + XMEMSET((byte *)KVA0_TO_KVA1(&bd), 0, sizeof(bd)); + /* Set up the Buffer Descriptor */ + bd_p->BD_CTRL.BUFLEN = sz; + if(cryptoalgo == PIC32_CRYPTOALGO_AES_GCM) { + if(sz % 0x10) + bd_p->BD_CTRL.BUFLEN = (sz/0x10 + 1) * 0x10 ; + } + bd_p->BD_CTRL.LIFM = 1; + bd_p->BD_CTRL.SA_FETCH_EN = 1; + bd_p->BD_CTRL.LAST_BD = 1; + bd_p->BD_CTRL.DESC_EN = 1; + + bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa) ; + bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in) ; + bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); + bd_p->MSGLEN = sz ; + + CECON = 1 << 6; + while (CECON); + + /* Run the engine */ + CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; + CEINTEN = 0x07; + CECON = 0x27; + + WAIT_ENGINE ; + + if((cryptoalgo == PIC32_CRYPTOALGO_CBC) || + (cryptoalgo == PIC32_CRYPTOALGO_TCBC)|| + (cryptoalgo == PIC32_CRYPTOALGO_RCBC)) { + /* set iv for the next call */ + if(dir == PIC32_ENCRYPTION) { + XMEMCPY((void *)aes->iv_ce, + (void*)KVA0_TO_KVA1(out + sz - AES_BLOCK_SIZE), + AES_BLOCK_SIZE) ; + } else { + ByteReverseWords((word32*)aes->iv_ce, + (word32 *)KVA0_TO_KVA1(in + sz - AES_BLOCK_SIZE), + AES_BLOCK_SIZE); + } + } + XMEMCPY((byte *)out, (byte *)KVA0_TO_KVA1(out), sz) ; + ByteReverseWords((word32*)out, (word32 *)out, sz); + } + + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + wc_AesCrypt(aes, out, in, sz, PIC32_ENCRYPTION, PIC32_ALGO_AES, + PIC32_CRYPTOALGO_RCBC ); + return 0 ; + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + wc_AesCrypt(aes, out, in, sz, PIC32_DECRYPTION, PIC32_ALGO_AES, + PIC32_CRYPTOALGO_RCBC); + return 0 ; + } + #endif /* HAVE_AES_DECRYPT */ + +#else + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / AES_BLOCK_SIZE; + + #ifdef HAVE_CAVIUM + if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) + return wc_AesCaviumCbcEncrypt(aes, out, in, sz); + #endif + + #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 % 16) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("AES-CBC encrypt with bad alignment"); + if (tmp == NULL) return MEMORY_E; + + XMEMCPY(tmp, in, sz); + AES_CBC_encrypt(tmp, tmp, (byte*)aes->reg, sz, (byte*)aes->key, + aes->rounds); + /* store iv for next call */ + XMEMCPY(aes->reg, tmp + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + XMEMCPY(out, tmp, sz); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return 0; + #else + 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 = sz / AES_BLOCK_SIZE; + + #ifdef HAVE_CAVIUM + if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) + return wc_AesCaviumCbcDecrypt(aes, out, in, sz); + #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); + AES_CBC_decrypt(in, out, (byte*)aes->reg, sz, (byte*)aes->key, + aes->rounds); + /* store iv for next call */ + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + return 0; + } + #endif + + 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 /* STM32F2_CRYPTO, AES-CBC block */ +#endif /* HAVE_AES_CBC */ + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER + + #ifdef STM32F2_CRYPTO + void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + 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 */ + 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_CTR; + AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&AES_CRYP_InitStructure); + + /* 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]); + 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 -= 16; + in += 16; + out += 16; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + } + + #elif defined(WOLFSSL_PIC32MZ_CRYPT) + void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int i ; + char out_block[AES_BLOCK_SIZE] ; + int odd ; + int even ; + char *tmp ; /* (char *)aes->tmp, for short */ + + tmp = (char *)aes->tmp ; + if(aes->left) { + if((aes->left + sz) >= AES_BLOCK_SIZE){ + odd = AES_BLOCK_SIZE - aes->left ; + } else { + odd = sz ; + } + XMEMCPY(tmp+aes->left, in, odd) ; + if((odd+aes->left) == AES_BLOCK_SIZE){ + wc_AesCrypt(aes, out_block, tmp, AES_BLOCK_SIZE, + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); + XMEMCPY(out, out_block+aes->left, odd) ; + aes->left = 0 ; + XMEMSET(tmp, 0x0, AES_BLOCK_SIZE) ; + /* Increment IV */ + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++((byte *)aes->iv_ce)[i]) + break ; + } + } + in += odd ; + out+= odd ; + sz -= odd ; + } + odd = sz % AES_BLOCK_SIZE ; /* if there is tail fragment */ + if(sz / AES_BLOCK_SIZE) { + even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE ; + wc_AesCrypt(aes, out, in, even, PIC32_ENCRYPTION, PIC32_ALGO_AES, + PIC32_CRYPTOALGO_RCTR); + out += even ; + in += even ; + do { /* Increment IV */ + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++((byte *)aes->iv_ce)[i]) + break ; + } + even -= AES_BLOCK_SIZE ; + } while((int)even > 0) ; + } + if(odd) { + XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left) ; + XMEMCPY(tmp+aes->left, in, odd) ; + wc_AesCrypt(aes, out_block, tmp, AES_BLOCK_SIZE, + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); + XMEMCPY(out, out_block+aes->left,odd) ; + aes->left += odd ; + } + } + + #elif defined(HAVE_COLDFIRE_SEC) + #error "Coldfire SEC doesn't currently support AES-CTR mode" + + #elif defined(FREESCALE_MMCAU) + #error "Freescale mmCAU doesn't currently support AES-CTR mode" + + #else + /* Increment AES counter */ + static INLINE void IncrementAesCounter(byte* inOutCtr) + { + int i; + + /* in network byte order so start at end and work back */ + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } + } + + void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + byte* tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + + /* consume any unused bytes left in aes->tmp */ + while (aes->left && sz) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + sz--; + } + + /* do as many block size ops as possible */ + while (sz >= AES_BLOCK_SIZE) { + wc_AesEncrypt(aes, (byte*)aes->reg, out); + IncrementAesCounter((byte*)aes->reg); + xorbuf(out, in, AES_BLOCK_SIZE); + + 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--; + } + } + } + + #endif /* STM32F2_CRYPTO, AES-CTR block */ + +#endif /* WOLFSSL_AES_COUNTER */ + +#ifdef HAVE_AESGCM + +/* + * The IV for AES GCM, stored in struct Aes's member reg, is comprised of + * three parts in order: + * 1. The implicit IV. This is generated from the PRF using the shared + * secrets between endpoints. It is 4 bytes long. + * 2. The explicit IV. This is set by the user of the AES. It needs to be + * unique for each call to encrypt. The explicit IV is shared with the + * other end of the transaction in the clear. + * 3. The counter. Each block of data is encrypted with its own sequence + * number counter. + */ + +#ifdef STM32F2_CRYPTO + #error "STM32F2 crypto doesn't currently support AES-GCM mode" + +#elif 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 + +enum { + NONCE_SZ = 12, + CTR_SZ = 4 +}; + + +static 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; + } +} + + +#if defined(GCM_SMALL) || defined(GCM_TABLE) + +static 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 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]; + + 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 (ret == 0) { + wc_AesEncrypt(aes, iv, aes->H); + #ifdef GCM_TABLE + GenerateM0(aes); + #endif /* GCM_TABLE */ + } + + return ret; +} + + +#ifdef WOLFSSL_AESNI + +void gfmul(__m128i a, __m128i b, __m128i* out) XASM_LINK("gfmul"); + + +/* 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 void AES_GCM_encrypt(const unsigned char *in, + unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + unsigned char *tag, + int nbytes, int abytes, int ibytes, + const unsigned char* key, int nr) +{ + int i, j ,k; + __m128i tmp1, tmp2, tmp3, tmp4; + __m128i H, Y, T; + __m128i *KEY = (__m128i*)key; + __m128i ctr1, ctr2, ctr3, ctr4; + __m128i last_block = _mm_setzero_si128(); + __m128i ONE = _mm_set_epi32(0, 1, 0, 0); + __m128i FOUR = _mm_set_epi32(0, 4, 0, 0); + __m128i BSWAP_EPI64 = _mm_set_epi8(8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7); + __m128i BSWAP_MASK = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); + __m128i X = _mm_setzero_si128(); + + if(ibytes == 96/8) { + Y = _mm_loadu_si128((__m128i*)ivec); + Y = _mm_insert_epi32(Y, 0x1000000, 3); + /* (Compute E[ZERO, KS] and E[Y0, KS] together */ + tmp1 = _mm_xor_si128(X, KEY[0]); + tmp2 = _mm_xor_si128(Y, KEY[0]); + for(j=1; j < nr-1; j+=2) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[j+1]); + } + tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[nr-1]); + H = _mm_aesenclast_si128(tmp1, KEY[nr]); + T = _mm_aesenclast_si128(tmp2, KEY[nr]); + H = _mm_shuffle_epi8(H, BSWAP_MASK); + } + else { + tmp1 = _mm_xor_si128(X, KEY[0]); + for(j=1; j <nr; j++) + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + H = _mm_aesenclast_si128(tmp1, KEY[nr]); + H = _mm_shuffle_epi8(H, BSWAP_MASK); + Y = _mm_setzero_si128(); + for(i=0; i < ibytes/16; i++) { + tmp1 = _mm_loadu_si128(&((__m128i*)ivec)[i]); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + Y = _mm_xor_si128(Y, tmp1); + gfmul(Y, H, &Y); + } + if(ibytes%16) { + for(j=0; j < ibytes%16; j++) + ((unsigned char*)&last_block)[j] = ivec[i*16+j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + Y = _mm_xor_si128(Y, tmp1); + gfmul(Y, H, &Y); + } + tmp1 = _mm_insert_epi64(tmp1, ibytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, 0, 1); + Y = _mm_xor_si128(Y, tmp1); + gfmul(Y, H, &Y); + Y = _mm_shuffle_epi8(Y, BSWAP_MASK); /* Compute E(K, Y0) */ + tmp1 = _mm_xor_si128(Y, KEY[0]); + for(j=1; j < nr; j++) + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + T = _mm_aesenclast_si128(tmp1, KEY[nr]); + } + + 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); + gfmul(X, H, &X); + } + 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); + gfmul(X, H, &X); + } + + ctr1 = _mm_shuffle_epi8(Y, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + ctr2 = _mm_add_epi32(ctr1, ONE); + ctr3 = _mm_add_epi32(ctr2, ONE); + ctr4 = _mm_add_epi32(ctr3, ONE); + + for(i=0; i < nbytes/16/4; i++){ + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp2 = _mm_shuffle_epi8(ctr2, BSWAP_EPI64); + tmp3 = _mm_shuffle_epi8(ctr3, BSWAP_EPI64); + tmp4 = _mm_shuffle_epi8(ctr4, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, FOUR); + ctr2 = _mm_add_epi32(ctr2, FOUR); + ctr3 = _mm_add_epi32(ctr3, FOUR); + ctr4 = _mm_add_epi32(ctr4, FOUR); + 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]); + for(j=1; j < nr-1; j+=2){ + 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]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[j+1]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[j+1]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[j+1]); + } + tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[nr-1]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[nr-1]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[nr-1]); + tmp1 =_mm_aesenclast_si128(tmp1, KEY[nr]); + tmp2 =_mm_aesenclast_si128(tmp2, KEY[nr]); + tmp3 =_mm_aesenclast_si128(tmp3, KEY[nr]); + tmp4 =_mm_aesenclast_si128(tmp4, KEY[nr]); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[i*4+0])); + tmp2 = _mm_xor_si128(tmp2, _mm_loadu_si128(&((__m128i*)in)[i*4+1])); + tmp3 = _mm_xor_si128(tmp3, _mm_loadu_si128(&((__m128i*)in)[i*4+2])); + tmp4 = _mm_xor_si128(tmp4, _mm_loadu_si128(&((__m128i*)in)[i*4+3])); + _mm_storeu_si128(&((__m128i*)out)[i*4+0], tmp1); + _mm_storeu_si128(&((__m128i*)out)[i*4+1], tmp2); + _mm_storeu_si128(&((__m128i*)out)[i*4+2], tmp3); + _mm_storeu_si128(&((__m128i*)out)[i*4+3], tmp4); + 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); + X = _mm_xor_si128(X, tmp1); + gfmul(X, H, &X); + X = _mm_xor_si128(X, tmp2); + gfmul(X, H, &X); + X = _mm_xor_si128(X, tmp3); + gfmul(X, H, &X); + X = _mm_xor_si128(X, tmp4); + gfmul(X, H, &X); + } + for(k = i*4; k < nbytes/16; k++){ + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + for(j=1; j<nr-1; j+=2){ + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); + } + tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); + tmp1 = _mm_aesenclast_si128(tmp1, KEY[nr]); + 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); + gfmul(X, H, &X); + } + /* If one partial block remains */ + if(nbytes%16){ + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + for(j=1; j<nr-1; j+=2){ + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); + } + tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); + tmp1 = _mm_aesenclast_si128(tmp1, KEY[nr]); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); + last_block = tmp1; + for(j=0; j < nbytes%16; j++) + out[k*16+j]=((unsigned char*)&last_block)[j]; + for(; j<16; j++) + ((unsigned char*)&last_block)[j]=0; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + gfmul(X, H, &X); + } + tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); + X = _mm_xor_si128(X, tmp1); + gfmul(X, H, &X); + X = _mm_shuffle_epi8(X, BSWAP_MASK); + T = _mm_xor_si128(X, T); + _mm_storeu_si128((__m128i*)tag, T); +} + + +#ifdef HAVE_AES_DECRYPT +/* Figure 10. AES-GCM â Decrypt With Single Block Ghash at a Time */ + +static int 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, const unsigned char* key, int nr) +{ + int i, j ,k; + __m128i tmp1, tmp2, tmp3, tmp4; + __m128i H, Y, T; + __m128i *KEY = (__m128i*)key; + __m128i ctr1, ctr2, ctr3, ctr4; + __m128i last_block = _mm_setzero_si128(); + __m128i ONE = _mm_set_epi32(0, 1, 0, 0); + __m128i FOUR = _mm_set_epi32(0, 4, 0, 0); + __m128i BSWAP_EPI64 = _mm_set_epi8(8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7); + __m128i BSWAP_MASK = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); + __m128i X = _mm_setzero_si128(); + + if (ibytes == 96/8) { + Y = _mm_loadu_si128((__m128i*)ivec); + Y = _mm_insert_epi32(Y, 0x1000000, 3); + /* (Compute E[ZERO, KS] and E[Y0, KS] together */ + tmp1 = _mm_xor_si128(X, KEY[0]); + tmp2 = _mm_xor_si128(Y, KEY[0]); + for (j = 1; j < nr - 1; j += 2) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[j+1]); + } + tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[nr-1]); + H = _mm_aesenclast_si128(tmp1, KEY[nr]); + T = _mm_aesenclast_si128(tmp2, KEY[nr]); + H = _mm_shuffle_epi8(H, BSWAP_MASK); + } + else { + tmp1 = _mm_xor_si128(X, KEY[0]); + for (j = 1; j < nr; j++) + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + H = _mm_aesenclast_si128(tmp1, KEY[nr]); + H = _mm_shuffle_epi8(H, BSWAP_MASK); + Y = _mm_setzero_si128(); + + for (i = 0; i < ibytes / 16; i++) { + tmp1 = _mm_loadu_si128(&((__m128i*)ivec)[i]); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + Y = _mm_xor_si128(Y, tmp1); + gfmul(Y, H, &Y); + } + + if (ibytes % 16) { + for(j = 0; j < ibytes % 16; j++) + ((unsigned char*)&last_block)[j] = ivec[i*16+j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + Y = _mm_xor_si128(Y, tmp1); + gfmul(Y, H, &Y); + } + + tmp1 = _mm_insert_epi64(tmp1, ibytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, 0, 1); + Y = _mm_xor_si128(Y, tmp1); + gfmul(Y, H, &Y); + Y = _mm_shuffle_epi8(Y, BSWAP_MASK); + /* Compute E(K, Y0) */ + tmp1 = _mm_xor_si128(Y, KEY[0]); + for(j=1; j < nr; j++) + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + T = _mm_aesenclast_si128(tmp1, KEY[nr]); + } + + 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); + gfmul(X, H, &X); + } + + 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); + gfmul(X, H, &X); + } + + for (i = 0; i < nbytes / 16; i++) { + tmp1 = _mm_loadu_si128(&((__m128i*)in)[i]); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X = _mm_xor_si128(X, tmp1); + gfmul(X, H, &X); + } + + if (nbytes % 16) { + last_block = _mm_setzero_si128(); + for(j = 0; j < nbytes % 16; j++) + ((unsigned char*)&last_block)[j] = in[i*16+j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X = _mm_xor_si128(X, tmp1); + gfmul(X, H, &X); + } + + tmp1 = _mm_insert_epi64(tmp1, nbytes * 8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes * 8, 1); + X = _mm_xor_si128(X, tmp1); + gfmul(X, H, &X); + 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)))) + return 0; /* in case the authentication failed */ + + ctr1 = _mm_shuffle_epi8(Y, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + ctr2 = _mm_add_epi32(ctr1, ONE); + ctr3 = _mm_add_epi32(ctr2, ONE); + ctr4 = _mm_add_epi32(ctr3, ONE); + + for (i=0; i < nbytes/16/4; i++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp2 = _mm_shuffle_epi8(ctr2, BSWAP_EPI64); + tmp3 = _mm_shuffle_epi8(ctr3, BSWAP_EPI64); + tmp4 = _mm_shuffle_epi8(ctr4, BSWAP_EPI64); + + ctr1 = _mm_add_epi32(ctr1, FOUR); + ctr2 = _mm_add_epi32(ctr2, FOUR); + ctr3 = _mm_add_epi32(ctr3, FOUR); + ctr4 = _mm_add_epi32(ctr4, FOUR); + + 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]); + + for (j = 1; j < nr - 1; j += 2) { + 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]); + + tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[j+1]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[j+1]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[j+1]); + } + + tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[nr-1]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[nr-1]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[nr-1]); + + tmp1 =_mm_aesenclast_si128(tmp1, KEY[nr]); + tmp2 =_mm_aesenclast_si128(tmp2, KEY[nr]); + tmp3 =_mm_aesenclast_si128(tmp3, KEY[nr]); + tmp4 =_mm_aesenclast_si128(tmp4, KEY[nr]); + + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[i*4+0])); + tmp2 = _mm_xor_si128(tmp2, _mm_loadu_si128(&((__m128i*)in)[i*4+1])); + tmp3 = _mm_xor_si128(tmp3, _mm_loadu_si128(&((__m128i*)in)[i*4+2])); + tmp4 = _mm_xor_si128(tmp4, _mm_loadu_si128(&((__m128i*)in)[i*4+3])); + + _mm_storeu_si128(&((__m128i*)out)[i*4+0], tmp1); + _mm_storeu_si128(&((__m128i*)out)[i*4+1], tmp2); + _mm_storeu_si128(&((__m128i*)out)[i*4+2], tmp3); + _mm_storeu_si128(&((__m128i*)out)[i*4+3], tmp4); + + 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); + } + + /* Acknowledge the dead store and continue */ + (void) tmp1; + (void) tmp2; + (void) tmp3; + (void) tmp4; + + for (k = i*4; k < nbytes/16; k++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + for (j = 1; j < nr-1; j += 2) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[j+1]); + } + tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); + tmp1 = _mm_aesenclast_si128(tmp1, KEY[nr]); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); + _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]); + for (j = 1; j < nr-1; j += 2) { + tmp1 =_mm_aesenc_si128(tmp1, KEY[j]); + tmp1 =_mm_aesenc_si128(tmp1, KEY[j+1]); + } + tmp1 = _mm_aesenc_si128(tmp1, KEY[nr-1]); + tmp1 = _mm_aesenclast_si128(tmp1, KEY[nr]); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); + last_block = tmp1; + for (j = 0; j < nbytes % 16; j++) + out[k*16+j]=((unsigned char*)&last_block)[j]; + } + + return 1; /* when successful returns 1 */ +} +#endif /* HAVE_AES_DECRYPT */ +#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); +} + + +static 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); +} + + +static 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) + +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]; +} + + +static 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); +} + +/* 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]; +} + + +static 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 */ + + +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) +{ + 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]; + + WOLFSSL_ENTER("AesGcmEncrypt"); + +#ifdef WOLFSSL_AESNI + if (haveAESNI) { + AES_GCM_encrypt((void*)in, out, (void*)authIn, (void*)iv, authTag, + sz, authInSz, ivSz, (byte*)aes->key, aes->rounds); + return 0; + } +#endif + +#ifdef WOLFSSL_PIC32MZ_CRYPT + ctr = (char *)aes->iv_ce ; +#else + ctr = counter ; +#endif + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == NONCE_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) + wc_AesCrypt(aes, out, in, blocks*AES_BLOCK_SIZE, + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM ); +#endif + 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 0; +} + + +#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) +{ + 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]; + + WOLFSSL_ENTER("AesGcmDecrypt"); + +#ifdef WOLFSSL_AESNI + if (haveAESNI) { + if (AES_GCM_decrypt(in, out, authIn, iv, authTag, + sz, authInSz, ivSz, (byte*)aes->key, aes->rounds) == 0) + return AES_GCM_AUTH_E; + return 0; + } +#endif + +#ifdef WOLFSSL_PIC32MZ_CRYPT + ctr = (char *)aes->iv_ce ; +#else + ctr = counter ; +#endif + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == NONCE_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); + + /* Calculate the authTag again using the received auth data and the + * cipher text. */ + { + byte Tprime[AES_BLOCK_SIZE]; + byte EKY0[AES_BLOCK_SIZE]; + + 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) + wc_AesCrypt(aes, out, in, blocks*AES_BLOCK_SIZE, + PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM ); +#endif + + 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 0; +} + +#endif /* HAVE_AES_DECRYPT */ + +WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) +{ + 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 + +#ifdef STM32F2_CRYPTO + #error "STM32F2 crypto doesn't currently support AES-CCM mode" + +#elif defined(HAVE_COLDFIRE_SEC) + #error "Coldfire SEC doesn't currently support AES-CCM mode" + +#elif defined(WOLFSSL_PIC32MZ_CRYPT) + #error "PIC32MZ doesn't currently support AES-CCM mode" + +#endif + +void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +{ + byte nonce[AES_BLOCK_SIZE]; + + if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) + return; + + XMEMSET(nonce, 0, sizeof(nonce)); + wc_AesSetKey(aes, key, keySz, nonce, AES_ENCRYPTION); +} + + +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 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; + word32 wordSz = (word32)sizeof(word32); + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + 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; + word32 wordSz = (word32)sizeof(word32); + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + 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 /* HAVE_AESCCM */ + + +#ifdef HAVE_CAVIUM + +#include <wolfssl/wolfcrypt/logging.h> +#include "cavium_common.h" + +/* Initialize Aes for use with Nitrox device */ +int wc_AesInitCavium(Aes* aes, int devId) +{ + if (aes == NULL) + return -1; + + if (CspAllocContext(CONTEXT_SSL, &aes->contextHandle, devId) != 0) + return -1; + + aes->devId = devId; + aes->magic = WOLFSSL_AES_CAVIUM_MAGIC; + + return 0; +} + + +/* Free Aes from use with Nitrox device */ +void wc_AesFreeCavium(Aes* aes) +{ + if (aes == NULL) + return; + + if (aes->magic != WOLFSSL_AES_CAVIUM_MAGIC) + return; + + CspFreeContext(CONTEXT_SSL, aes->contextHandle, aes->devId); + aes->magic = 0; +} + + +static int wc_AesCaviumSetKey(Aes* aes, const byte* key, word32 length, + const byte* iv) +{ + if (aes == NULL) + return -1; + + XMEMCPY(aes->key, key, length); /* key still holds key, iv still in reg */ + if (length == 16) + aes->type = AES_128; + else if (length == 24) + aes->type = AES_192; + else if (length == 32) + aes->type = AES_256; + + return wc_AesSetIV(aes, iv); +} + +#ifdef HAVE_AES_CBC +static int wc_AesCaviumCbcEncrypt(Aes* aes, byte* out, const byte* in, + word32 length) +{ + wolfssl_word offset = 0; + word32 requestId; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + if (CspEncryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, + aes->type, slen, (byte*)in + offset, out + offset, + (byte*)aes->reg, (byte*)aes->key, &requestId, + aes->devId) != 0) { + WOLFSSL_MSG("Bad Cavium Aes Encrypt"); + return -1; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + XMEMCPY(aes->reg, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + if (length) { + word16 slen = (word16)length; + if (CspEncryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, + aes->type, slen, (byte*)in + offset, out + offset, + (byte*)aes->reg, (byte*)aes->key, &requestId, + aes->devId) != 0) { + WOLFSSL_MSG("Bad Cavium Aes Encrypt"); + return -1; + } + XMEMCPY(aes->reg, out + offset+length - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + return 0; +} + +#ifdef HAVE_AES_DECRYPT +static int wc_AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, + word32 length) +{ + word32 requestId; + wolfssl_word offset = 0; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (CspDecryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, + aes->type, slen, (byte*)in + offset, out + offset, + (byte*)aes->reg, (byte*)aes->key, &requestId, + aes->devId) != 0) { + WOLFSSL_MSG("Bad Cavium Aes Decrypt"); + return -1; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + if (length) { + word16 slen = (word16)length; + XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (CspDecryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, + aes->type, slen, (byte*)in + offset, out + offset, + (byte*)aes->reg, (byte*)aes->key, &requestId, + aes->devId) != 0) { + WOLFSSL_MSG("Bad Cavium Aes Decrypt"); + return -1; + } + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + return 0; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC */ + +#endif /* HAVE_CAVIUM */ + +#endif /* WOLFSSL_TI_CRYPT */ + +#endif /* HAVE_FIPS */ + +#endif /* NO_AES */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/arc4.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,180 @@ +/* arc4.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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/arc4.h> + +#ifdef HAVE_CAVIUM + static void wc_Arc4CaviumSetKey(Arc4* arc4, const byte* key, word32 length); + static void wc_Arc4CaviumProcess(Arc4* arc4, byte* out, const byte* in, + word32 length); +#endif + + +void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) +{ + word32 i; + word32 keyIndex = 0, stateIndex = 0; + +#ifdef HAVE_CAVIUM + if (arc4->magic == WOLFSSL_ARC4_CAVIUM_MAGIC) + return wc_Arc4CaviumSetKey(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; + } +} + + +static 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]; +} + + +void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) +{ + word32 x; + word32 y; + +#ifdef HAVE_CAVIUM + if (arc4->magic == WOLFSSL_ARC4_CAVIUM_MAGIC) + return wc_Arc4CaviumProcess(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; +} + + +#ifdef HAVE_CAVIUM + +#include <wolfssl/wolfcrypt/logging.h> +#include "cavium_common.h" + +/* Initialize Arc4 for use with Nitrox device */ +int wc_Arc4InitCavium(Arc4* arc4, int devId) +{ + if (arc4 == NULL) + return -1; + + if (CspAllocContext(CONTEXT_SSL, &arc4->contextHandle, devId) != 0) + return -1; + + arc4->devId = devId; + arc4->magic = WOLFSSL_ARC4_CAVIUM_MAGIC; + + return 0; +} + + +/* Free Arc4 from use with Nitrox device */ +void wc_Arc4FreeCavium(Arc4* arc4) +{ + if (arc4 == NULL) + return; + + if (arc4->magic != WOLFSSL_ARC4_CAVIUM_MAGIC) + return; + + CspFreeContext(CONTEXT_SSL, arc4->contextHandle, arc4->devId); + arc4->magic = 0; +} + + +static void wc_Arc4CaviumSetKey(Arc4* arc4, const byte* key, word32 length) +{ + word32 requestId; + + if (CspInitializeRc4(CAVIUM_BLOCKING, arc4->contextHandle, length, + (byte*)key, &requestId, arc4->devId) != 0) { + WOLFSSL_MSG("Bad Cavium Arc4 Init"); + } +} + + +static void wc_Arc4CaviumProcess(Arc4* arc4, byte* out, const byte* in, + word32 length) +{ + wolfssl_word offset = 0; + word32 requestId; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + if (CspEncryptRc4(CAVIUM_BLOCKING, arc4->contextHandle,CAVIUM_UPDATE, + slen, (byte*)in + offset, out + offset, &requestId, + arc4->devId) != 0) { + WOLFSSL_MSG("Bad Cavium Arc4 Encrypt"); + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + } + if (length) { + word16 slen = (word16)length; + if (CspEncryptRc4(CAVIUM_BLOCKING, arc4->contextHandle,CAVIUM_UPDATE, + slen, (byte*)in + offset, out + offset, &requestId, + arc4->devId) != 0) { + WOLFSSL_MSG("Bad Cavium Arc4 Encrypt"); + } + } +} + +#endif /* HAVE_CAVIUM */ + +#endif /* NO_RC4 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/asm.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1620 @@ +/* asm.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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) __cpuid((int*)a,b) + + #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; + unsigned int reg[5]; + + reg[4] = '\0' ; + cpuid(reg, 0, 0); + 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; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return((reg[num]>>bit)&0x1) ; + } + return 0 ; +} + +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), "g"(mu), "g"(*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_INIT(a0, c0, cy)\ + __asm__ volatile( \ + "xorq %%r10, %%r10\n\t" \ + "movq %1,%%rdx\n\t" \ + "addq %2, %0\n\t" /* c0+=cy; Set CF, OF */ \ + "adoxq %%r10, %%r10\n\t" /* Reset OF */ \ + :"+m"(c0):"r"(a0),"r"(cy):"%r8","%r9", "%r10","%r11","%r12","%rdx") ; \ + +#define MULX_INNERMUL_R1(c0, c1, pre, rdx)\ + { \ + __asm__ volatile ( \ + "movq %3, %%rdx\n\t" \ + "mulx %%r11,%%r9, %%r8 \n\t" \ + "movq %2, %%r12\n\t" \ + "adoxq %%r9,%0 \n\t" \ + "adcxq %%r8,%1 \n\t" \ + :"+r"(c0),"+r"(c1):"m"(pre),"r"(rdx):"%r8","%r9", "%r10", "%r11","%r12","%rdx" \ + ); } + + +#define MULX_INNERMUL_R2(c0, c1, pre, rdx)\ + { \ + __asm__ volatile ( \ + "movq %3, %%rdx\n\t" \ + "mulx %%r12,%%r9, %%r8 \n\t" \ + "movq %2, %%r11\n\t" \ + "adoxq %%r9,%0 \n\t" \ + "adcxq %%r8,%1 \n\t" \ + :"+r"(c0),"+r"(c1):"m"(pre),"r"(rdx):"%r8","%r9", "%r10", "%r11","%r12","%rdx" \ + ); } + +#define MULX_LOAD_R1(val)\ + __asm__ volatile ( \ + "movq %0, %%r11\n\t"\ + ::"m"(val):"%r8","%r9", "%r10", "%r11","%r12","%rdx"\ +) ; + +#define MULX_INNERMUL_LAST(c0, c1, rdx)\ + { \ + __asm__ volatile ( \ + "movq %2, %%rdx\n\t" \ + "mulx %%r12,%%r9, %%r8 \n\t" \ + "movq $0, %%r10 \n\t" \ + "adoxq %%r10, %%r9 \n\t" \ + "adcq $0,%%r8 \n\t" \ + "addq %%r9,%0 \n\t" \ + "adcq $0,%%r8 \n\t" \ + "movq %%r8,%1 \n\t" \ + :"+m"(c0),"=m"(c1):"r"(rdx):"%r8","%r9","%r10", "%r11", "%r12","%rdx"\ + ); } + +#define MULX_INNERMUL8(x,y,z,cy)\ +{ word64 rdx = y ;\ + MULX_LOAD_R1(x[0]) ;\ + MULX_INIT(y, _c0, cy) ; /* rdx=y; z0+=cy; */ \ + MULX_INNERMUL_R1(_c0, _c1, x[1], rdx) ;\ + MULX_INNERMUL_R2(_c1, _c2, x[2], rdx) ;\ + MULX_INNERMUL_R1(_c2, _c3, x[3], rdx) ;\ + MULX_INNERMUL_R2(_c3, _c4, x[4], rdx) ;\ + MULX_INNERMUL_R1(_c4, _c5, x[5], rdx) ;\ + MULX_INNERMUL_R2(_c5, _c6, x[6], rdx) ;\ + MULX_INNERMUL_R1(_c6, _c7, x[7], rdx) ;\ + MULX_INNERMUL_LAST(_c7, cy, rdx) ;\ +} +#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,%0 \n\t" \ + " addze 17,17 \n\t" \ + " lwz 18,%1 \n\t" \ + " addc 16,16,18 \n\t" \ + " addze %0,17 \n\t" \ + " stw 16,%1 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "18","cc"); ++tmpm; + +#define PROPCARRY \ +__asm__( \ + " lwz 16,%1 \n\t" \ + " addc 16,16,%0 \n\t" \ + " stw 16,%1 \n\t" \ + " xor %0,%0,%0 \n\t" \ + " addze %0,%0 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"16","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 16,%3,%4 \n\t" \ + " mulhdu 17,%3,%4 \n\t" \ + " addc 16,16,%0 \n\t" \ + " addze 17,17 \n\t" \ + " ldx 18,0,%1 \n\t" \ + " addc 16,16,18 \n\t" \ + " addze %0,17 \n\t" \ + " sdx 16,0,%1 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "18","cc"); ++tmpm; + +#define PROPCARRY \ +__asm__( \ + " ldx 16,0,%1 \n\t" \ + " addc 16,16,%0 \n\t" \ + " sdx 16,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]):"16","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"); + +#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"); + +/* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */ + +#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), "g"(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"); + +/* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */ + +#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 16,%6,%6 \n\t" \ + " addc %0,%0,16 \n\t" \ + " mulhdu 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__( \ + " mulld 16,%6,%7 \n\t" \ + " mulhdu 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__( \ + " 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 16,%6,%7 \n\t" \ + " addc %0,%0,16 \n\t" \ + " mulhdu 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_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"); + + +#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) + #include "fp_sqr_comba_3.i" +#endif +#if defined(TFM_SQR4) + #include "fp_sqr_comba_4.i" +#endif +#if defined(TFM_SQR6) + #include "fp_sqr_comba_6.i" +#endif +#if defined(TFM_SQR7) + #include "fp_sqr_comba_7.i" +#endif +#if defined(TFM_SQR8) + #include "fp_sqr_comba_8.i" +#endif +#if defined(TFM_SQR9) + #include "fp_sqr_comba_9.i" +#endif +#if defined(TFM_SQR12) + #include "fp_sqr_comba_12.i" +#endif +#if defined(TFM_SQR17) + #include "fp_sqr_comba_17.i" +#endif +#if defined(TFM_SQR20) + #include "fp_sqr_comba_20.i" +#endif +#if defined(TFM_SQR24) + #include "fp_sqr_comba_24.i" +#endif +#if defined(TFM_SQR28) + #include "fp_sqr_comba_28.i" +#endif +#if defined(TFM_SQR32) + #include "fp_sqr_comba_32.i" +#endif +#if defined(TFM_SQR48) + #include "fp_sqr_comba_48.i" +#endif +#if defined(TFM_SQR64) + #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_MULX(b0, c0, c1, rdx)\ + __asm__ volatile ( \ + "movq %3, %%rdx\n\t" \ + "mulx %2,%%r9, %%r8 \n\t" \ + "adoxq %%r9,%0 \n\t" \ + "adcxq %%r8,%1 \n\t" \ + :"+r"(c0),"+r"(c1):"r"(b0), "r"(rdx):"%r8","%r9","%r10","%rdx"\ + ) + + +#define MULADD_MULX_ADD_CARRY(c0, c1)\ + __asm__ volatile(\ + "mov $0, %%r10\n\t"\ + "movq %1, %%r8\n\t"\ + "adox %%r10, %0\n\t"\ + "adcx %%r10, %1\n\t"\ + :"+r"(c0),"+r"(c1)::"%r8","%r9","%r10","%rdx") ; + +#define MULADD_SET_A(a0)\ + __asm__ volatile("add $0, %%r8\n\t" \ + "movq %0,%%rdx\n\t" \ + ::"r"(a0):"%r8","%r9","%r10","%rdx") ; + +#define MULADD_BODY(a,b,c)\ + { word64 rdx = a->dp[ix] ; \ + cp = &(c->dp[iz]) ; \ + c0 = cp[0] ; c1 = cp[1]; \ + MULADD_SET_A(rdx) ; \ + MULADD_MULX(b0, c0, c1, rdx) ;\ + cp[0]=c0; c0=cp[2]; \ + MULADD_MULX(b1, c1, c0, rdx) ;\ + cp[1]=c1; c1=cp[3]; \ + MULADD_MULX(b2, c0, c1, rdx) ;\ + cp[2]=c0; c0=cp[4]; \ + MULADD_MULX(b3, c1, c0, rdx) ;\ + cp[3]=c1; c1=cp[5]; \ + MULADD_MULX_ADD_CARRY(c0, c1);\ + cp[4]=c0; cp[5]=c1; \ + } + +#define TFM_INTEL_MUL_COMBA(a, b, c)\ + for(ix=0; ix<pa; ix++)c->dp[ix]=0 ; \ + for(iy=0; (iy<b->used); iy+=4) { \ + fp_digit *bp ; \ + bp = &(b->dp[iy+0]) ; \ + fp_digit b0 = bp[0] , b1= bp[1], \ + b2= bp[2], b3= bp[3]; \ + ix=0, iz=iy; \ + while(ix<a->used) { \ + fp_digit c0, c1; \ + fp_digit *cp ; \ + MULADD_BODY(a,b,c); \ + ix++ ; iz++ ; \ + } \ +}; +#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 mulhwu change the flags? Docs say no */ +#define MULADD(i, j) \ +____asm__( \ + " mulld 16,%6,%7 \n\t" \ + " addc %0,%0,16 \n\t" \ + " mulhdu 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_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"); + +#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) + #include "fp_mul_comba_3.i" +#endif +#if defined(TFM_MUL4) + #include "fp_mul_comba_4.i" +#endif +#if defined(TFM_MUL6) + #include "fp_mul_comba_6.i" +#endif +#if defined(TFM_MUL7) + #include "fp_mul_comba_7.i" +#endif +#if defined(TFM_MUL8) + #include "fp_mul_comba_8.i" +#endif +#if defined(TFM_MUL9) + #include "fp_mul_comba_9.i" +#endif +#if defined(TFM_MUL12) + #include "fp_mul_comba_12.i" +#endif +#if defined(TFM_MUL17) + #include "fp_mul_comba_17.i" +#endif +#if defined(TFM_MUL20) + #include "fp_mul_comba_20.i" +#endif +#if defined(TFM_MUL24) + #include "fp_mul_comba_24.i" +#endif +#if defined(TFM_MUL28) + #include "fp_mul_comba_28.i" +#endif +#if defined(TFM_MUL32) + #include "fp_mul_comba_32.i" +#endif +#if defined(TFM_MUL48) + #include "fp_mul_comba_48.i" +#endif +#if defined(TFM_MUL64) + #include "fp_mul_comba_64.i" +#endif + +/* end fp_mul_comba.c asm */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/asn.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,9703 @@ +/* asn.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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. +*/ + +#ifndef NO_ASN + +#ifdef HAVE_RTP_SYS + #include "os.h" /* dc_rtc_api needs */ + #include "dc_rtc_api.h" /* to get current time */ +#endif + +#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/logging.h> + +#include <wolfssl/wolfcrypt/random.h> +#include <wolfssl/wolfcrypt/hash.h> +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#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 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 + + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef NO_ASN_TIME +#if defined(HAVE_RTP_SYS) + /* uses parital <time.h> structures */ + #define XTIME(tl) (0) + #define XGMTIME(c, t) rtpsys_gmtime((c)) + +#elif defined(MICRIUM) + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + #define XVALIDATE_DATE(d, f, t) NetSecure_ValidateDateHandler((d), (f), (t)) + #else + #define XVALIDATE_DATE(d, f, t) (0) + #endif + #define NO_TIME_H + /* since Micrium not defining XTIME or XGMTIME, CERT_GEN not available */ + +#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) + #define XTIME(t1) mqx_time((t1)) + #define HAVE_GMTIME_R + +#elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) + #include <time.h> + #define XTIME(t1) ksdk_time((t1)) + #define XGMTIME(c, t) gmtime((c)) + +#elif defined(USER_TIME) + /* user time, and gmtime compatible functions, there is a gmtime + implementation here that WINCE uses, so really just need some ticks + since the EPOCH + */ + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#elif defined(TIME_OVERRIDES) + /* user would like to override time() and gmtime() functionality */ + #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(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> +#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) + #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 + +/* 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); +#endif + + +#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 */ + + +#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 */ + +#if defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) + +#include "fsl_pit_driver.h" + +time_t ksdk_time(time_t* timer) +{ + time_t localTime; + + if (timer == NULL) + timer = &localTime; + + *timer = (PIT_DRV_ReadTimerUs(PIT_INSTANCE, PIT_CHANNEL)) / 1000000; + return *timer; +} + +#endif /* FREESCALE_KSDK_BM */ + +#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 */ + + +static INLINE word32 btoi(byte b) +{ + return b - 0x30; +} + + +/* two byte date/time, add to value */ +static INLINE void GetTime(int* value, const byte* date, int* idx) +{ + int i = *idx; + + *value += btoi(date[i++]) * 10; + *value += btoi(date[i++]); + + *idx = i; +} + + +#if defined(MICRIUM) + +CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format, + CPU_INT08U dateType) +{ + CPU_BOOLEAN rtn_code; + CPU_INT32S i; + CPU_INT32S val; + CPU_INT16U year; + CPU_INT08U month; + CPU_INT16U day; + CPU_INT08U hour; + CPU_INT08U min; + CPU_INT08U sec; + + i = 0; + year = 0u; + + if (format == ASN_UTC_TIME) { + if (btoi(date[0]) >= 5) + year = 1900; + else + year = 2000; + } + else { /* format == GENERALIZED_TIME */ + year += btoi(date[i++]) * 1000; + year += btoi(date[i++]) * 100; + } + + val = year; + GetTime(&val, date, &i); + year = (CPU_INT16U)val; + + val = 0; + GetTime(&val, date, &i); + month = (CPU_INT08U)val; + + val = 0; + GetTime(&val, date, &i); + day = (CPU_INT16U)val; + + val = 0; + GetTime(&val, date, &i); + hour = (CPU_INT08U)val; + + val = 0; + GetTime(&val, date, &i); + min = (CPU_INT08U)val; + + val = 0; + GetTime(&val, date, &i); + sec = (CPU_INT08U)val; + + return NetSecure_ValidateDate(year, month, day, hour, min, sec, dateType); +} + +#endif /* MICRIUM */ + +#if defined(IDIRECT_DEV_TIME) + +extern time_t getTimestamp(); + +time_t idirect_time(time_t * timer) +{ + time_t sec = getTimestamp(); + + if (timer != NULL) + *timer = sec; + + return sec; +} + +#endif /* IDIRECT_DEV_TIME */ + +#endif /* !NO_ASN_TIME */ + +WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = 0; + word32 i = *inOutIdx; + byte b; + + *len = 0; /* default length */ + + if ( (i+1) > maxIdx) { /* for first read */ + WOLFSSL_MSG("GetLength bad index on input"); + return BUFFER_E; + } + + b = input[i++]; + if (b >= ASN_LONG_LENGTH) { + word32 bytes = b & 0x7F; + + if ( (i+bytes) > maxIdx) { /* for reading bytes */ + WOLFSSL_MSG("GetLength bad long length"); + return BUFFER_E; + } + + while (bytes--) { + b = input[i++]; + length = (length << 8) | b; + } + } + else + length = b; + + if ( (i+length) > maxIdx) { /* for user of length */ + WOLFSSL_MSG("GetLength value exceeds buffer length"); + return BUFFER_E; + } + + *inOutIdx = i; + if (length > 0) + *len = length; + + return length; +} + + +WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = -1; + word32 idx = *inOutIdx; + + if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) || + GetLength(input, &idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + + return length; +} + + +WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = -1; + word32 idx = *inOutIdx; + + if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) || + GetLength(input, &idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + + return length; +} + + +/* Windows header clash for WinCE using GetVersion */ +WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, + int* version) +{ + word32 idx = *inOutIdx; + + WOLFSSL_ENTER("GetMyVersion"); + + 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 */ +static int GetShortInt(const byte* input, word32* inOutIdx, int* number) +{ + word32 idx = *inOutIdx; + word32 len; + + *number = 0; + + if (input[idx++] != ASN_INTEGER) + return ASN_PARSE_E; + + len = input[idx++]; + if (len > 4) + return ASN_PARSE_E; + + while (len--) { + *number = *number << 8 | input[idx++]; + } + + *inOutIdx = idx; + + return *number; +} +#endif /* !NO_PWDBASED */ + +#ifndef NO_ASN_TIME +/* May not have one, not an error */ +static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version) +{ + word32 idx = *inOutIdx; + + WOLFSSL_ENTER("GetExplicitVersion"); + if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + *inOutIdx = ++idx; /* eat header */ + return GetMyVersion(input, inOutIdx, version); + } + + /* go back as is */ + *version = 0; + + return 0; +} +#endif /* !NO_ASN_TIME */ + +WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, + word32 maxIdx) +{ + word32 i = *inOutIdx; + byte b = input[i++]; + int length; + + if (b != ASN_INTEGER) + return ASN_PARSE_E; + + if (GetLength(input, &i, &length, maxIdx) < 0) + return ASN_PARSE_E; + + if ( (b = input[i++]) == 0x00) + length--; + else + i--; + + if (mp_init(mpi) != MP_OKAY) + return MP_INIT_E; + + if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } + + *inOutIdx = i + length; + return 0; +} + + +/* hashType */ +static const byte hashMd2hOid[] = {42, 134, 72, 134, 247, 13, 2, 2}; +static const byte hashMd5hOid[] = {42, 134, 72, 134, 247, 13, 2, 5}; +static const byte hashSha1hOid[] = {43, 14, 3, 2, 26}; +static const byte hashSha256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 1}; +static const byte hashSha384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 2}; +static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; + +/* sigType */ +#ifndef NO_DSA + static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3}; +#endif /* NO_DSA */ +#ifndef NO_RSA + static const byte sigMd2wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 2}; + static const byte sigMd5wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 4}; + static const byte sigSha1wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 5}; + static const byte sigSha256wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,11}; + static const byte sigSha384wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,12}; + static const byte sigSha512wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,13}; +#endif /* NO_RSA */ +#ifdef HAVE_ECC + static const byte sigSha1wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 1}; + static const byte sigSha256wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 2}; + static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3}; + static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4}; +#endif /* HAVE_ECC */ + +/* 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 */ + +/* curveType */ +#ifdef HAVE_ECC + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) + static const byte curve192v1Oid[] = {42, 134, 72, 206, 61, 3, 1, 1}; + #endif /* HAVE_ALL_CURVES || HAVE_ECC192 */ + #if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) + static const byte curve256v1Oid[] = {42, 134, 72, 206, 61, 3, 1, 7}; + #endif /* HAVE_ALL_CURVES || HAVE_ECC256 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) + static const byte curve160r1Oid[] = {43, 129, 4, 0, 2}; + #endif /* HAVE_ALL_CURVES || HAVE_ECC160 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) + static const byte curve224r1Oid[] = {43, 129, 4, 0, 33}; + #endif /* HAVE_ALL_CURVES || HAVE_ECC224 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) + static const byte curve384r1Oid[] = {43, 129, 4, 0, 34}; + #endif /* HAVE_ALL_CURVES || HAVE_ECC384 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) + static const byte curve521r1Oid[] = {43, 129, 4, 0, 35}; + #endif /* HAVE_ALL_CURVES || HAVE_ECC521 */ +#endif /* HAVE_ECC */ + +/* blkType */ +static const byte blkDesCbcOid[] = {43, 14, 3, 2, 7}; +static const byte blkDes3CbcOid[] = {42, 134, 72, 134, 247, 13, 3, 7}; + +/* 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}; +static const byte extNameConsOid[] = {85, 29, 30}; + +/* certAuthInfoType */ +static const byte extAuthInfoOcspOid[] = {43, 6, 1, 5, 5, 7, 48, 1}; +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 extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9}; + +/* kdfType */ +static const byte pbkdf2Oid[] = {42, 134, 72, 134, 247, 13, 1, 5, 12}; + +static const byte* OidFromId(word32 id, word32 type, word32* oidSz) +{ + const byte* oid = NULL; + + *oidSz = 0; + + switch (type) { + + case hashType: + switch (id) { + case MD2h: + oid = hashMd2hOid; + *oidSz = sizeof(hashMd2hOid); + break; + case MD5h: + oid = hashMd5hOid; + *oidSz = sizeof(hashMd5hOid); + break; + case SHAh: + oid = hashSha1hOid; + *oidSz = sizeof(hashSha1hOid); + break; + case SHA256h: + oid = hashSha256hOid; + *oidSz = sizeof(hashSha256hOid); + break; + case SHA384h: + oid = hashSha384hOid; + *oidSz = sizeof(hashSha384hOid); + break; + case SHA512h: + oid = hashSha512hOid; + *oidSz = sizeof(hashSha512hOid); + break; + } + break; + + case sigType: + switch (id) { + #ifndef NO_DSA + case CTC_SHAwDSA: + oid = sigSha1wDsaOid; + *oidSz = sizeof(sigSha1wDsaOid); + break; + #endif /* NO_DSA */ + #ifndef NO_RSA + case CTC_MD2wRSA: + oid = sigMd2wRsaOid; + *oidSz = sizeof(sigMd2wRsaOid); + break; + case CTC_MD5wRSA: + oid = sigMd5wRsaOid; + *oidSz = sizeof(sigMd5wRsaOid); + break; + case CTC_SHAwRSA: + oid = sigSha1wRsaOid; + *oidSz = sizeof(sigSha1wRsaOid); + break; + case CTC_SHA256wRSA: + oid = sigSha256wRsaOid; + *oidSz = sizeof(sigSha256wRsaOid); + break; + case CTC_SHA384wRSA: + oid = sigSha384wRsaOid; + *oidSz = sizeof(sigSha384wRsaOid); + break; + case CTC_SHA512wRSA: + oid = sigSha512wRsaOid; + *oidSz = sizeof(sigSha512wRsaOid); + break; + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case CTC_SHAwECDSA: + oid = sigSha1wEcdsaOid; + *oidSz = sizeof(sigSha1wEcdsaOid); + break; + case CTC_SHA256wECDSA: + oid = sigSha256wEcdsaOid; + *oidSz = sizeof(sigSha256wEcdsaOid); + break; + case CTC_SHA384wECDSA: + oid = sigSha384wEcdsaOid; + *oidSz = sizeof(sigSha384wEcdsaOid); + break; + case CTC_SHA512wECDSA: + oid = sigSha512wEcdsaOid; + *oidSz = sizeof(sigSha512wEcdsaOid); + break; + #endif /* HAVE_ECC */ + default: + break; + } + break; + + case keyType: + 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 */ + default: + break; + } + break; + + #ifdef HAVE_ECC + case curveType: + switch (id) { + #if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) + case ECC_256R1: + oid = curve256v1Oid; + *oidSz = sizeof(curve256v1Oid); + break; + #endif /* HAVE_ALL_CURVES || HAVE_ECC256 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) + case ECC_384R1: + oid = curve384r1Oid; + *oidSz = sizeof(curve384r1Oid); + break; + #endif /* HAVE_ALL_CURVES || HAVE_ECC384 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) + case ECC_521R1: + oid = curve521r1Oid; + *oidSz = sizeof(curve521r1Oid); + break; + #endif /* HAVE_ALL_CURVES || HAVE_ECC521 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) + case ECC_160R1: + oid = curve160r1Oid; + *oidSz = sizeof(curve160r1Oid); + break; + #endif /* HAVE_ALL_CURVES || HAVE_ECC160 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) + case ECC_192R1: + oid = curve192v1Oid; + *oidSz = sizeof(curve192v1Oid); + break; + #endif /* HAVE_ALL_CURVES || HAVE_ECC192 */ + #if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) + case ECC_224R1: + oid = curve224r1Oid; + *oidSz = sizeof(curve224r1Oid); + break; + #endif /* HAVE_ALL_CURVES || HAVE_ECC224 */ + default: + break; + } + break; + #endif /* HAVE_ECC */ + + case blkType: + switch (id) { + case DESb: + oid = blkDesCbcOid; + *oidSz = sizeof(blkDesCbcOid); + break; + case DES3b: + oid = blkDes3CbcOid; + *oidSz = sizeof(blkDes3CbcOid); + break; + } + break; + + #ifdef HAVE_OCSP + case ocspType: + 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 certExtType: + 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; + case NAME_CONS_OID: + oid = extNameConsOid; + *oidSz = sizeof(extNameConsOid); + break; + } + break; + + case certAuthInfoType: + switch (id) { + case AIA_OCSP_OID: + oid = extAuthInfoOcspOid; + *oidSz = sizeof(extAuthInfoOcspOid); + break; + case AIA_CA_ISSUER_OID: + oid = extAuthInfoCaIssuerOid; + *oidSz = sizeof(extAuthInfoCaIssuerOid); + break; + } + break; + + case certPolicyType: + switch (id) { + case CP_ANY_OID: + oid = extCertPolicyAnyOid; + *oidSz = sizeof(extCertPolicyAnyOid); + break; + } + break; + + case certAltNameType: + switch (id) { + case HW_NAME_OID: + oid = extAltNamesHwNameOid; + *oidSz = sizeof(extAltNamesHwNameOid); + break; + } + break; + + case certKeyUseType: + 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_OCSP_SIGN_OID: + oid = extExtKeyUsageOcspSignOid; + *oidSz = sizeof(extExtKeyUsageOcspSignOid); + break; + } + + case kdfType: + switch (id) { + case PBKDF2_OID: + oid = pbkdf2Oid; + *oidSz = sizeof(pbkdf2Oid); + break; + } + break; + + case ignoreType: + default: + break; + } + + return oid; +} + + +WOLFSSL_LOCAL int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, + word32 oidType, word32 maxIdx) +{ + int length; + word32 i = *inOutIdx; +#ifndef NO_VERIFY_OID + word32 actualOidSz = 0; + const byte* actualOid; +#endif /* NO_VERIFY_OID */ + byte b; + + (void)oidType; + WOLFSSL_ENTER("GetObjectId()"); + *oid = 0; + + b = input[i++]; + if (b != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(input, &i, &length, maxIdx) < 0) + return ASN_PARSE_E; + +#ifndef NO_VERIFY_OID + actualOid = &input[i]; + if (length > 0) + actualOidSz = (word32)length; +#endif /* NO_VERIFY_OID */ + + while(length--) { + /* odd HC08 compiler behavior here when input[i++] */ + *oid += input[i]; + i++; + } + /* just sum it up for now */ + + *inOutIdx = i; + +#ifndef NO_VERIFY_OID + { + const byte* checkOid = NULL; + word32 checkOidSz; + + if (oidType != ignoreType) { + checkOid = OidFromId(*oid, oidType, &checkOidSz); + + 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 0; +} + + +#ifndef NO_RSA +#ifndef HAVE_USER_RSA +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) +static int SkipObjectId(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + int length; + + if (input[(*inOutIdx)++] != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(input, inOutIdx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + *inOutIdx += length; + + return 0; +} +#endif /* OPENSSL_EXTRA || RSA_DECODE_EXTRA */ +#endif /* !HAVE_USER_RSA */ +#endif /* !NO_RSA */ + +WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, + word32 oidType, word32 maxIdx) +{ + int length; + word32 i = *inOutIdx; + byte b; + *oid = 0; + + WOLFSSL_ENTER("GetAlgoId"); + + if (GetSequence(input, &i, &length, maxIdx) < 0) + return ASN_PARSE_E; + + if (GetObjectId(input, &i, oid, oidType, maxIdx) < 0) + return ASN_OBJECT_ID_E; + + /* could have NULL tag and 0 terminator, but may not */ + b = input[i]; + + if (b == ASN_TAG_NULL) { + i++; + b = input[i++]; + if (b != 0) + return ASN_EXPECT_0_E; + } + + *inOutIdx = i; + + return 0; +} + +#ifndef NO_RSA + + +#ifdef HAVE_CAVIUM + +static int GetCaviumInt(byte** buff, word16* buffSz, const byte* input, + word32* inOutIdx, word32 maxIdx, void* heap) +{ + word32 i = *inOutIdx; + byte b = input[i++]; + int length; + + if (b != ASN_INTEGER) + return ASN_PARSE_E; + + if (GetLength(input, &i, &length, maxIdx) < 0) + return ASN_PARSE_E; + + if ( (b = input[i++]) == 0x00) + length--; + else + i--; + + *buffSz = (word16)length; + *buff = XMALLOC(*buffSz, heap, DYNAMIC_TYPE_CAVIUM_RSA); + if (*buff == NULL) + return MEMORY_E; + + XMEMCPY(*buff, input + i, *buffSz); + + *inOutIdx = i + length; + return 0; +} + +static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + RsaKey* key, word32 inSz) +{ + int version, length; + void* h = key->heap; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, inOutIdx, &version) < 0) + return ASN_PARSE_E; + + key->type = RSA_PRIVATE; + + if (GetCaviumInt(&key->c_n, &key->c_nSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_e, &key->c_eSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_d, &key->c_dSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_p, &key->c_pSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_q, &key->c_qSz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_dP, &key->c_dP_Sz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_dQ, &key->c_dQ_Sz, input, inOutIdx, inSz, h) < 0 || + GetCaviumInt(&key->c_u, &key->c_uSz, input, inOutIdx, inSz, h) < 0 ) + return ASN_RSA_KEY_E; + + return 0; +} + + +#endif /* HAVE_CAVIUM */ + +#ifndef HAVE_USER_RSA +int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int version, length; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return CaviumRsaPrivateKeyDecode(input, inOutIdx, key, inSz); +#endif + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, inOutIdx, &version) < 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 || + 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; + + return 0; +} +#endif /* HAVE_USER_RSA */ +#endif /* NO_RSA */ + +/* Remove PKCS8 header, move beginning of traditional to beginning of input */ +int ToTraditional(byte* input, word32 sz) +{ + word32 inOutIdx = 0, oid; + int version, length; + + if (GetSequence(input, &inOutIdx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, &inOutIdx, &version) < 0) + return ASN_PARSE_E; + + if (GetAlgoId(input, &inOutIdx, &oid, sigType, sz) < 0) + return ASN_PARSE_E; + + if (input[inOutIdx] == ASN_OBJECT_ID) { + /* pkcs8 ecc uses slightly different format */ + inOutIdx++; /* past id */ + if (GetLength(input, &inOutIdx, &length, sz) < 0) + return ASN_PARSE_E; + inOutIdx += length; /* over sub id, key input will verify */ + } + + if (input[inOutIdx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(input, &inOutIdx, &length, sz) < 0) + return ASN_PARSE_E; + + XMEMMOVE(input, input + inOutIdx, length); + + return length; +} + + +#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) { + case 1: + *id = PBE_SHA1_RC4_128; + *version = PKCS12; + return 0; + case 3: + *id = PBE_SHA1_DES3; + *version = PKCS12; + return 0; + default: + return ALGO_ID_E; + } + } + + if (first != PKCS5) + return ASN_INPUT_E; /* VERSION ERROR */ + + if (second == PBES2) { + *version = PKCS5v2; + return 0; + } + + switch (second) { + case 3: /* see RFC 2898 for ids */ + *id = PBE_MD5_DES; + return 0; + case 10: + *id = PBE_SHA1_DES; + return 0; + 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) +{ + switch (oid) { + case 69: + *id = PBE_SHA1_DES; + return 0; + case 652: + *id = PBE_SHA1_DES3; + return 0; + default: + return ALGO_ID_E; + + } +} + + +/* Decrypt input in place from parameters based on id */ +static int DecryptKey(const char* password, int passwordSz, byte* salt, + int saltSz, int iterations, int id, byte* input, + int length, int version, byte* cbcIv) +{ + int typeH; + int derivedLen; + int decryptionType; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* key; +#else + byte key[MAX_KEY_SIZE]; +#endif + + (void)input; + (void)length; + + switch (id) { + case PBE_MD5_DES: + typeH = MD5; + derivedLen = 16; /* may need iv for v1.5 */ + decryptionType = DES_TYPE; + break; + + case PBE_SHA1_DES: + typeH = SHA; + derivedLen = 16; /* may need iv for v1.5 */ + decryptionType = DES_TYPE; + break; + + case PBE_SHA1_DES3: + typeH = SHA; + derivedLen = 32; /* may need iv for v1.5 */ + decryptionType = DES3_TYPE; + break; + + case PBE_SHA1_RC4_128: + typeH = SHA; + derivedLen = 16; + decryptionType = RC4_TYPE; + break; + + default: + 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 == PKCS12) { + 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 (decryptionType != RC4_TYPE) + 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 + return ALGO_ID_E; + } + + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + switch (decryptionType) { +#ifndef NO_DES3 + case DES_TYPE: + { + Des dec; + byte* desIv = key + 8; + + if (version == PKCS5v2 || version == PKCS12) + desIv = cbcIv; + + ret = wc_Des_SetKey(&dec, key, desIv, DES_DECRYPTION); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + wc_Des_CbcDecrypt(&dec, input, input, length); + break; + } + + case DES3_TYPE: + { + Des3 dec; + byte* desIv = key + 24; + + if (version == PKCS5v2 || version == PKCS12) + desIv = cbcIv; + ret = wc_Des3_SetKey(&dec, key, desIv, DES_DECRYPTION); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + ret = wc_Des3_CbcDecrypt(&dec, input, input, length); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + break; + } +#endif +#ifndef NO_RC4 + case RC4_TYPE: + { + Arc4 dec; + + wc_Arc4SetKey(&dec, key, derivedLen); + wc_Arc4Process(&dec, input, input, length); + break; + } +#endif + + default: +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ALGO_ID_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + + +/* 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, oid; + int first, second, length, version, saltSz, id; + int iterations = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* salt = NULL; + byte* cbcIv = NULL; +#else + byte salt[MAX_SALT_SIZE]; + byte cbcIv[MAX_IV_SIZE]; +#endif + + if (GetSequence(input, &inOutIdx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetAlgoId(input, &inOutIdx, &oid, sigType, sz) < 0) + return ASN_PARSE_E; + + 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) + return ASN_INPUT_E; /* Algo ID error */ + + if (version == PKCS5v2) { + + if (GetSequence(input, &inOutIdx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetAlgoId(input, &inOutIdx, &oid, kdfType, sz) < 0) + return ASN_PARSE_E; + + if (oid != PBKDF2_OID) + return ASN_PARSE_E; + } + + if (GetSequence(input, &inOutIdx, &length, sz) < 0) + return ASN_PARSE_E; + + if (input[inOutIdx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(input, &inOutIdx, &saltSz, sz) < 0) + return ASN_PARSE_E; + + if (saltSz > MAX_SALT_SIZE) + return ASN_PARSE_E; + +#ifdef WOLFSSL_SMALL_STACK + salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (salt == NULL) + return MEMORY_E; +#endif + + XMEMCPY(salt, &input[inOutIdx], saltSz); + inOutIdx += saltSz; + + if (GetShortInt(input, &inOutIdx, &iterations) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + +#ifdef WOLFSSL_SMALL_STACK + cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv == NULL) { + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (version == PKCS5v2) { + /* get encryption algo */ + /* JOHN: New type. Need a little more research. */ + if (GetAlgoId(input, &inOutIdx, &oid, blkType, sz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (CheckAlgoV2(oid, &id) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; /* PKCS v2 algo id error */ + } + + if (input[inOutIdx++] != ASN_OCTET_STRING) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (GetLength(input, &inOutIdx, &length, sz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + XMEMCPY(cbcIv, &input[inOutIdx], length); + inOutIdx += length; + } + + if (input[inOutIdx++] != ASN_OCTET_STRING) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (GetLength(input, &inOutIdx, &length, sz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (DecryptKey(password, passwordSz, salt, saltSz, iterations, id, + input + inOutIdx, length, version, cbcIv) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_INPUT_E; /* decrypt failure */ + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + XMEMMOVE(input, input + inOutIdx, length); + return ToTraditional(input, length); +} + +#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 (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + key->type = RSA_PUBLIC; + +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + { + byte 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; + + /* could have NULL tag and 0 terminator, but may not */ + b = input[(*inOutIdx)++]; + + if (b == ASN_TAG_NULL) { + b = input[(*inOutIdx)++]; + if (b != 0) + return ASN_EXPECT_0_E; + } + else + /* go back, didn't have it */ + (*inOutIdx)--; + + /* should have bit tag length and seq next */ + b = input[(*inOutIdx)++]; + if (b != ASN_BIT_STRING) + return ASN_BITSTR_E; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + /* could have 0 */ + b = input[(*inOutIdx)++]; + if (b != 0) + (*inOutIdx)--; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + } /* end if */ + } /* openssl var block */ +#endif /* OPENSSL_EXTRA */ + + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + + 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; + } + + 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 i = 0; + byte b; + int length; + + if (GetSequence(input, &i, &length, inSz) < 0) + return ASN_PARSE_E; + + b = input[i++]; + if (b != ASN_INTEGER) + return ASN_PARSE_E; + + if (GetLength(input, &i, &length, inSz) < 0) + return ASN_PARSE_E; + + if ( (b = input[i++]) == 0x00) + length--; + else + i--; + + if (length <= (int)*pInOutSz) { + XMEMCPY(p, &input[i], length); + *pInOutSz = length; + } + else + return BUFFER_E; + + i += length; + + b = input[i++]; + if (b != ASN_INTEGER) + return ASN_PARSE_E; + + if (GetLength(input, &i, &length, inSz) < 0) + return ASN_PARSE_E; + + if (length <= (int)*gInOutSz) { + XMEMCPY(g, &input[i], 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 (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; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, inOutIdx, &version) < 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 INLINE void FreeTmpDsas(byte** tmps) +{ + int i; + + for (i = 0; i < DSA_INTS; i++) + XFREE(tmps[i], NULL, DYNAMIC_TYPE_DSA); +} + +/* 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, lbit; + + 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); + + /* leading zero */ + lbit = mp_leading_bit(keyInt); + rawLen = mp_unsigned_bin_size(keyInt) + lbit; + + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, NULL, DYNAMIC_TYPE_DSA); + if (tmps[i] == NULL) { + ret = MEMORY_E; + break; + } + + tmps[i][0] = ASN_INTEGER; + sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ + + if (sizes[i] <= MAX_SEQ_SZ) { + int err; + + /* leading zero */ + if (lbit) + tmps[i][sizes[i]-1] = 0x00; + + err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); + if (err == MP_OKAY) { + sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ + intTotalLen += sizes[i]; + } + else { + ret = err; + break; + } + } + else { + ret = ASN_INPUT_E; + break; + } + } + + if (ret != 0) { + FreeTmpDsas(tmps); + 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); + + return outLen; +} + +#endif /* NO_DSA */ + + +void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) +{ + cert->publicKey = 0; + cert->pubKeySize = 0; + cert->pubKeyStored = 0; + cert->version = 0; + cert->signature = 0; + cert->subjectCN = 0; + cert->subjectCNLen = 0; + cert->subjectCNEnc = CTC_UTF8; + cert->subjectCNStored = 0; + cert->weOwnAltNames = 0; + cert->altNames = NULL; +#ifndef IGNORE_NAME_CONSTRAINTS + cert->altEmailNames = NULL; + cert->permittedNames = NULL; + cert->excludedNames = NULL; +#endif /* IGNORE_NAME_CONSTRAINTS */ + cert->issuer[0] = '\0'; + cert->subject[0] = '\0'; + cert->source = source; /* don't own */ + cert->srcIdx = 0; + cert->maxIdx = inSz; /* can't go over this index */ + cert->heap = heap; + XMEMSET(cert->serial, 0, EXTERNAL_SERIAL_SIZE); + cert->serialSz = 0; + cert->extensions = 0; + cert->extensionsSz = 0; + cert->extensionsIdx = 0; + cert->extAuthInfo = NULL; + cert->extAuthInfoSz = 0; + cert->extCrlInfo = NULL; + cert->extCrlInfoSz = 0; + XMEMSET(cert->extSubjKeyId, 0, KEYID_SIZE); + cert->extSubjKeyIdSet = 0; + XMEMSET(cert->extAuthKeyId, 0, KEYID_SIZE); + cert->extAuthKeyIdSet = 0; + cert->extKeyUsageSet = 0; + cert->extKeyUsage = 0; + cert->extExtKeyUsageSet = 0; + cert->extExtKeyUsage = 0; + cert->isCA = 0; +#ifdef HAVE_PKCS7 + cert->issuerRaw = NULL; + cert->issuerRawLen = 0; +#endif +#ifdef WOLFSSL_CERT_GEN + cert->subjectSN = 0; + cert->subjectSNLen = 0; + cert->subjectSNEnc = CTC_UTF8; + cert->subjectC = 0; + cert->subjectCLen = 0; + cert->subjectCEnc = CTC_PRINTABLE; + cert->subjectL = 0; + cert->subjectLLen = 0; + cert->subjectLEnc = CTC_UTF8; + cert->subjectST = 0; + cert->subjectSTLen = 0; + cert->subjectSTEnc = CTC_UTF8; + cert->subjectO = 0; + cert->subjectOLen = 0; + cert->subjectOEnc = CTC_UTF8; + cert->subjectOU = 0; + cert->subjectOULen = 0; + cert->subjectOUEnc = CTC_UTF8; + cert->subjectEmail = 0; + cert->subjectEmailLen = 0; +#endif /* WOLFSSL_CERT_GEN */ + cert->beforeDate = NULL; + cert->beforeDateLen = 0; + cert->afterDate = NULL; + cert->afterDateLen = 0; +#ifdef OPENSSL_EXTRA + XMEMSET(&cert->issuerName, 0, sizeof(DecodedName)); + XMEMSET(&cert->subjectName, 0, sizeof(DecodedName)); + cert->extBasicConstSet = 0; + cert->extBasicConstCrit = 0; + cert->extBasicConstPlSet = 0; + cert->pathLength = 0; + cert->extSubjAltNameSet = 0; + cert->extSubjAltNameCrit = 0; + cert->extAuthKeyIdCrit = 0; + cert->extSubjKeyIdCrit = 0; + cert->extKeyUsageCrit = 0; + cert->extExtKeyUsageCrit = 0; + cert->extExtKeyUsageSrc = NULL; + cert->extExtKeyUsageSz = 0; + cert->extExtKeyUsageCount = 0; + cert->extAuthKeyIdSrc = NULL; + cert->extAuthKeyIdSz = 0; + cert->extSubjKeyIdSrc = NULL; + cert->extSubjKeyIdSz = 0; +#endif /* OPENSSL_EXTRA */ +#if defined(OPENSSL_EXTRA) || !defined(IGNORE_NAME_CONSTRAINTS) + cert->extNameConstraintSet = 0; +#endif /* OPENSSL_EXTRA || !IGNORE_NAME_CONSTRAINTS */ +#ifdef HAVE_ECC + cert->pkCurveOID = 0; +#endif /* HAVE_ECC */ +#ifdef WOLFSSL_SEP + cert->deviceTypeSz = 0; + cert->deviceType = NULL; + cert->hwTypeSz = 0; + cert->hwType = NULL; + cert->hwSerialNumSz = 0; + cert->hwSerialNum = NULL; + #ifdef OPENSSL_EXTRA + cert->extCertPolicySet = 0; + cert->extCertPolicyCrit = 0; + #endif /* OPENSSL_EXTRA */ +#endif /* WOLFSSL_SEP */ +#ifdef WOLFSSL_CERT_EXT + XMEMSET(cert->extCertPolicies, 0, MAX_CERTPOL_NB*MAX_CERTPOL_SZ); + cert->extCertPoliciesNb = 0; +#endif +} + + +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 */ +#ifdef OPENSSL_EXTRA + if (cert->issuerName.fullName != NULL) + XFREE(cert->issuerName.fullName, NULL, DYNAMIC_TYPE_X509); + if (cert->subjectName.fullName != NULL) + XFREE(cert->subjectName.fullName, NULL, DYNAMIC_TYPE_X509); +#endif /* OPENSSL_EXTRA */ +} + +#ifndef NO_ASN_TIME +static int GetCertHeader(DecodedCert* cert) +{ + int ret = 0, len; + byte serialTmp[EXTERNAL_SERIAL_SIZE]; +#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH) + mp_int* mpi = NULL; +#else + mp_int stack_mpi; + mp_int* mpi = &stack_mpi; +#endif + + 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) < 0) + return ASN_PARSE_E; + +#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH) + mpi = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (mpi == NULL) + return MEMORY_E; +#endif + + if (GetInt(mpi, cert->source, &cert->srcIdx, cert->maxIdx) < 0) { +#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH) + XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + len = mp_unsigned_bin_size(mpi); + if (len < (int)sizeof(serialTmp)) { + if ( (ret = mp_to_unsigned_bin(mpi, serialTmp)) == MP_OKAY) { + XMEMCPY(cert->serial, serialTmp, len); + cert->serialSz = len; + } + } + mp_clear(mpi); + +#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH) + XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + 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 +#endif /* !NO_ASN_TIME */ + + +#ifdef HAVE_ECC + + /* return 0 on success if the ECC curve oid sum is supported */ + static int CheckCurve(word32 oid) + { + int ret = 0; + + switch (oid) { +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) + case ECC_160R1: +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) + case ECC_192R1: +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) + case ECC_224R1: +#endif +#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) + case ECC_256R1: +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) + case ECC_384R1: +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) + case ECC_521R1: +#endif + break; + + default: + ret = ALGO_ID_E; + } + + return ret; + } + +#endif /* HAVE_ECC */ + +#ifndef NO_ASN_TIME +static int GetKey(DecodedCert* cert) +{ + int length; +#ifdef 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, keyType, cert->maxIdx) < 0) + return ASN_PARSE_E; + + switch (cert->keyOID) { + #ifndef NO_RSA + case RSAk: + { + byte b = cert->source[cert->srcIdx++]; + if (b != ASN_BIT_STRING) + return ASN_BITSTR_E; + + if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0) + return ASN_PARSE_E; + b = cert->source[cert->srcIdx++]; + if (b != 0x00) + return ASN_EXPECT_0_E; + + 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, NULL, + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_NTRU_KEY_E; + } + + if ( (next - key) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(keyBlob, NULL, 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, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; + } + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + { + byte b; + + if (GetObjectId(cert->source, &cert->srcIdx, + &cert->pkCurveOID, curveType, cert->maxIdx) < 0) + return ASN_PARSE_E; + + if (CheckCurve(cert->pkCurveOID) < 0) + return ECC_CURVE_OID_E; + + /* key header */ + b = cert->source[cert->srcIdx++]; + if (b != ASN_BIT_STRING) + return ASN_BITSTR_E; + + if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0) + return ASN_PARSE_E; + b = cert->source[cert->srcIdx++]; + if (b != 0x00) + return ASN_EXPECT_0_E; + + /* actual key, use length - 1 since ate preceding 0 */ + length -= 1; + + 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_ECC */ + 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; + #ifdef OPENSSL_EXTRA + DecodedName* dName = + (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName; + #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->source[cert->srcIdx] == ASN_OBJECT_ID) { + WOLFSSL_MSG("Trying optional prefix..."); + + if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + return ASN_PARSE_E; + + cert->srcIdx += 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. */ + 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; + + b = cert->source[cert->srcIdx++]; + if (b != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0) + return ASN_PARSE_E; + + XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint)); + + /* v1 name types */ + if (joint[0] == 0x55 && joint[1] == 0x04) { + byte id; + byte copy = FALSE; + int strLen; + + 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; + } + + if (!tooBig) { + XMEMCPY(&full[idx], "/CN=", 4); + idx += 4; + copy = TRUE; + } + #ifdef OPENSSL_EXTRA + dName->cnIdx = cert->srcIdx; + dName->cnLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_SUR_NAME) { + if (!tooBig) { + XMEMCPY(&full[idx], "/SN=", 4); + idx += 4; + copy = TRUE; + } + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectSN = (char*)&cert->source[cert->srcIdx]; + cert->subjectSNLen = strLen; + cert->subjectSNEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->snIdx = cert->srcIdx; + dName->snLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_COUNTRY_NAME) { + if (!tooBig) { + XMEMCPY(&full[idx], "/C=", 3); + idx += 3; + copy = TRUE; + } + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectC = (char*)&cert->source[cert->srcIdx]; + cert->subjectCLen = strLen; + cert->subjectCEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->cIdx = cert->srcIdx; + dName->cLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_LOCALITY_NAME) { + if (!tooBig) { + XMEMCPY(&full[idx], "/L=", 3); + idx += 3; + copy = TRUE; + } + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectL = (char*)&cert->source[cert->srcIdx]; + cert->subjectLLen = strLen; + cert->subjectLEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->lIdx = cert->srcIdx; + dName->lLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_STATE_NAME) { + if (!tooBig) { + XMEMCPY(&full[idx], "/ST=", 4); + idx += 4; + copy = TRUE; + } + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectST = (char*)&cert->source[cert->srcIdx]; + cert->subjectSTLen = strLen; + cert->subjectSTEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->stIdx = cert->srcIdx; + dName->stLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_ORG_NAME) { + if (!tooBig) { + XMEMCPY(&full[idx], "/O=", 3); + idx += 3; + copy = TRUE; + } + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectO = (char*)&cert->source[cert->srcIdx]; + cert->subjectOLen = strLen; + cert->subjectOEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->oIdx = cert->srcIdx; + dName->oLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_ORGUNIT_NAME) { + if (!tooBig) { + XMEMCPY(&full[idx], "/OU=", 4); + idx += 4; + copy = TRUE; + } + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectOU = (char*)&cert->source[cert->srcIdx]; + cert->subjectOULen = strLen; + cert->subjectOUEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->ouIdx = cert->srcIdx; + dName->ouLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_SERIAL_NUMBER) { + if (!tooBig) { + XMEMCPY(&full[idx], "/serialNumber=", 14); + idx += 14; + copy = TRUE; + } + #ifdef OPENSSL_EXTRA + dName->snIdx = cert->srcIdx; + dName->snLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + + if (copy && !tooBig) { + XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen); + idx += strLen; + } + + cert->srcIdx += strLen; + } + else { + /* skip */ + byte email = FALSE; + byte uid = FALSE; + int adv; + + if (joint[0] == 0x2a && joint[1] == 0x86) /* email id hdr */ + email = TRUE; + + if (joint[0] == 0x9 && joint[1] == 0x92) /* uid id hdr */ + uid = 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 */ + #ifdef OPENSSL_EXTRA + 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->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; + } + 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 (uid) { + if ( (5 + adv) > (int)(ASN_NAME_MAX - idx)) { + WOLFSSL_MSG("ASN name too big, skipping"); + tooBig = TRUE; + } + if (!tooBig) { + XMEMCPY(&full[idx], "/UID=", 5); + idx += 5; + + XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv); + idx += adv; + } + #ifdef OPENSSL_EXTRA + dName->uidIdx = cert->srcIdx; + dName->uidLen = adv; + #endif /* OPENSSL_EXTRA */ + } + + cert->srcIdx += adv; + } + } + full[idx++] = 0; + + #ifdef OPENSSL_EXTRA + { + int totalLen = 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; + + dName->fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509); + if (dName->fullName != NULL) { + idx = 0; + + if (dName->cnLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/CN=", 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], "/SN=", 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], "/C=", 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], "/L=", 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], "/ST=", 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], "/O=", 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], "/OU=", 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; + } + 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], "/serialNumber=", 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; +} + + +#if !defined(NO_TIME_H) && 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 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); + 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[i++]) * 1000; + certTime.tm_year += btoi(date[i++]) * 100; + } + + /* adjust tm_year, tm_mon */ + GetTime((int*)&certTime.tm_year, date, &i); certTime.tm_year -= 1900; + GetTime((int*)&certTime.tm_mon, date, &i); certTime.tm_mon -= 1; + GetTime((int*)&certTime.tm_mday, date, &i); + GetTime((int*)&certTime.tm_hour, date, &i); + GetTime((int*)&certTime.tm_min, date, &i); + GetTime((int*)&certTime.tm_sec, date, &i); + + 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)) + return 0; + } + else + if (DateGreaterThan(localTime, &certTime)) + return 0; + + return 1; +} +#endif /* !NO_TIME_H && USE_WOLF_VALIDDATE */ + + +static int GetDate(DecodedCert* cert, int dateType) +{ + int length; + byte date[MAX_DATE_SIZE]; + byte b; + word32 startIdx = 0; + + if (dateType == BEFORE) + cert->beforeDate = &cert->source[cert->srcIdx]; + else + cert->afterDate = &cert->source[cert->srcIdx]; + startIdx = cert->srcIdx; + + b = cert->source[cert->srcIdx++]; + if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) + return ASN_TIME_E; + + if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + return ASN_PARSE_E; + + if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE) + return ASN_DATE_SZ_E; + + XMEMCPY(date, &cert->source[cert->srcIdx], length); + cert->srcIdx += length; + + if (dateType == BEFORE) + cert->beforeDateLen = cert->srcIdx - startIdx; + else + cert->afterDateLen = cert->srcIdx - startIdx; + + if (!XVALIDATE_DATE(date, b, dateType)) { + if (dateType == BEFORE) + return ASN_BEFORE_DATE_E; + else + return ASN_AFTER_DATE_E; + } + + 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) < 0 && verify) + badDate = ASN_BEFORE_DATE_E; /* continue parsing */ + + if (GetDate(cert, AFTER) < 0 && verify) + return ASN_AFTER_DATE_E; + + if (badDate != 0) + return badDate; + + return 0; +} + + +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, + sigType, 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; + byte b = cert->source[cert->srcIdx++]; + + if (b != ASN_BIT_STRING) + return ASN_BITSTR_E; + + if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + return ASN_PARSE_E; + + cert->sigLength = length; + + b = cert->source[cert->srcIdx++]; + if (b != 0x00) + return ASN_EXPECT_0_E; + + cert->sigLength--; + cert->signature = &cert->source[cert->srcIdx]; + cert->srcIdx += cert->sigLength; + + return 0; +} +#endif /* !NO_ASN_TIME */ + +static word32 SetDigest(const byte* digest, word32 digSz, byte* output) +{ + output[0] = ASN_OCTET_STRING; + output[1] = (byte)digSz; + XMEMCPY(&output[2], digest, digSz); + + return digSz + 2; +} + + +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) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) + +static int SetCurve(ecc_key* key, byte* output) +{ + + /* curve types */ +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) + static const byte ECC_192v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, + 0x03, 0x01, 0x01}; +#endif +#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) + static const byte ECC_256v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, + 0x03, 0x01, 0x07}; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) + static const byte ECC_160r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00, + 0x02}; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) + static const byte ECC_224r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00, + 0x21}; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) + static const byte ECC_384r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00, + 0x22}; +#endif +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) + static const byte ECC_521r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00, + 0x23}; +#endif + + int oidSz = 0; + int idx = 0; + int lenSz = 0; + const byte* oid = 0; + + output[0] = ASN_OBJECT_ID; + idx++; + + switch (key->dp->size) { +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) + case 20: + oidSz = sizeof(ECC_160r1_AlgoID); + oid = ECC_160r1_AlgoID; + break; +#endif + +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) + case 24: + oidSz = sizeof(ECC_192v1_AlgoID); + oid = ECC_192v1_AlgoID; + break; +#endif + +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) + case 28: + oidSz = sizeof(ECC_224r1_AlgoID); + oid = ECC_224r1_AlgoID; + break; +#endif + +#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) + case 32: + oidSz = sizeof(ECC_256v1_AlgoID); + oid = ECC_256v1_AlgoID; + break; +#endif + +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) + case 48: + oidSz = sizeof(ECC_384r1_AlgoID); + oid = ECC_384r1_AlgoID; + break; +#endif + +#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) + case 66: + oidSz = sizeof(ECC_521r1_AlgoID); + oid = ECC_521r1_AlgoID; + break; +#endif + + default: + return ASN_UNKNOWN_OID_E; + } + lenSz = SetLength(oidSz, output+idx); + idx += lenSz; + + XMEMCPY(output+idx, oid, oidSz); + idx += oidSz; + + return idx; +} + +#endif /* HAVE_ECC && WOLFSSL_CERT_GEN */ + + +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[MAX_LENGTH_SZ]; + byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ + + tagSz = (type == hashType || type == sigType || + (type == keyType && algoOID == RSAk)) ? 2 : 0; + + algoName = OidFromId(algoOID, type, &algoSz); + + if (algoName == NULL) { + WOLFSSL_MSG("Unknown Algorithm"); + return 0; + } + + idSz = SetLength(algoSz, ID_Length); + seqSz = SetSequence(idSz + algoSz + 1 + tagSz + curveSz, seqArray); + /* +1 for object id, curveID of curveSz follows for ecc */ + seqArray[seqSz++] = ASN_OBJECT_ID; + + XMEMCPY(output, seqArray, seqSz); + XMEMCPY(output + seqSz, ID_Length, idSz); + XMEMCPY(output + seqSz + idSz, algoName, algoSz); + if (tagSz == 2) { + output[seqSz + idSz + algoSz] = ASN_TAG_NULL; + output[seqSz + idSz + algoSz + 1] = 0; + } + + 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, hashType, 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) +{ + switch (type) { +#ifdef WOLFSSL_MD2 + case MD2: + return MD2h; +#endif +#ifndef NO_MD5 + case MD5: + return MD5h; +#endif +#ifndef NO_SHA + case SHA: + return SHAh; +#endif +#ifndef NO_SHA256 + case SHA256: + return SHA256h; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384: + return SHA384h; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512: + return SHA512h; +#endif + default: + return 0; + }; +} + +#ifndef NO_ASN_TIME +/* return true (1) or false (0) for Confirmation */ +static int ConfirmSignature(const byte* buf, word32 bufSz, + const byte* key, word32 keySz, word32 keyOID, + const byte* sig, word32 sigSz, word32 sigOID, + void* heap) +{ + int typeH = 0, digestSz = 0, ret = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; +#else + byte digest[MAX_DIGEST_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digest == NULL) + return 0; /* not confirmed */ +#endif + + (void)key; + (void)keySz; + (void)sig; + (void)sigSz; + (void)heap; + + switch (sigOID) { + #ifndef NO_MD5 + case CTC_MD5wRSA: + if (wc_Md5Hash(buf, bufSz, digest) == 0) { + typeH = MD5h; + digestSz = MD5_DIGEST_SIZE; + } + break; + #endif + #if defined(WOLFSSL_MD2) + case CTC_MD2wRSA: + if (wc_Md2Hash(buf, bufSz, digest) == 0) { + typeH = MD2h; + digestSz = MD2_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwDSA: + case CTC_SHAwECDSA: + if (wc_ShaHash(buf, bufSz, digest) == 0) { + typeH = SHAh; + digestSz = SHA_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if (wc_Sha256Hash(buf, bufSz, digest) == 0) { + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if (wc_Sha512Hash(buf, bufSz, digest) == 0) { + typeH = SHA512h; + digestSz = SHA512_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + case CTC_SHA384wECDSA: + if (wc_Sha384Hash(buf, bufSz, digest) == 0) { + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + } + break; + #endif + default: + WOLFSSL_MSG("Verify Signature has unsupported type"); + } + + if (typeH == 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; /* not confirmed */ + } + + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 idx = 0; + int encodedSigSz, verifySz; + byte* out; +#ifdef WOLFSSL_SMALL_STACK + RsaKey* pubKey; + byte* plain; + byte* encodedSig; +#else + RsaKey pubKey[1]; + byte plain[MAX_ENCODED_SIG_SZ]; + byte encodedSig[MAX_ENCODED_SIG_SZ]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (pubKey == NULL || plain == NULL || encodedSig == NULL) { + WOLFSSL_MSG("Failed to allocate memory at ConfirmSignature"); + + if (pubKey) + XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (plain) + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig) + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + break; /* not confirmed */ + } +#endif + if (wc_InitRsaKey(pubKey, heap) != 0) { + WOLFSSL_MSG("InitRsaKey failed"); + } + else if (sigSz > MAX_ENCODED_SIG_SZ) { + WOLFSSL_MSG("Verify Signature is too big"); + } + else if (wc_RsaPublicKeyDecode(key, &idx, pubKey, keySz) < 0) { + WOLFSSL_MSG("ASN Key decode error RSA"); + } + else { + XMEMCPY(plain, sig, sigSz); + + if ((verifySz = wc_RsaSSL_VerifyInline(plain, sigSz, &out, + pubKey)) < 0) { + WOLFSSL_MSG("Rsa SSL verify error"); + } + else { + /* make sure we're right justified */ + encodedSigSz = + wc_EncodeSignature(encodedSig, digest, digestSz, typeH); + if (encodedSigSz != verifySz || + XMEMCMP(out, encodedSig, encodedSigSz) != 0) { + WOLFSSL_MSG("Rsa SSL verify match encode error"); + } + else + ret = 1; /* match */ + + #ifdef WOLFSSL_DEBUG_ENCODING + { + int x; + + printf("wolfssl encodedSig:\n"); + + for (x = 0; x < encodedSigSz; x++) { + printf("%02x ", encodedSig[x]); + if ( (x % 16) == 15) + printf("\n"); + } + + printf("\n"); + printf("actual digest:\n"); + + for (x = 0; x < verifySz; x++) { + printf("%02x ", out[x]); + if ( (x % 16) == 15) + printf("\n"); + } + + printf("\n"); + } + #endif /* WOLFSSL_DEBUG_ENCODING */ + + } + + } + + wc_FreeRsaKey(pubKey); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + break; + } + + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + int verify = 0; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* pubKey; +#else + ecc_key pubKey[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + pubKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (pubKey == NULL) { + WOLFSSL_MSG("Failed to allocate pubKey"); + break; /* not confirmed */ + } +#endif + + if (wc_ecc_init(pubKey) < 0) { + WOLFSSL_MSG("Failed to initialize key"); + break; /* not confirmed */ + } + if (wc_ecc_import_x963(key, keySz, pubKey) < 0) { + WOLFSSL_MSG("ASN Key import error ECC"); + } + else { + if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify, + pubKey) != 0) { + WOLFSSL_MSG("ECC verify hash error"); + } + else if (1 != verify) { + WOLFSSL_MSG("ECC Verify didn't match"); + } else + ret = 1; /* match */ + + } + wc_ecc_free(pubKey); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + break; + } + #endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Verify Key type unknown"); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + 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) { + if (base->type == ASN_DNS_TYPE) { + DNS_entry* name = cert->altNames; + while (name != NULL) { + if (MatchBaseName(ASN_DNS_TYPE, + name->name, (int)XSTRLEN(name->name), + base->name, base->nameSz)) + return 0; + name = name->next; + } + } + else if (base->type == ASN_RFC822_TYPE) { + DNS_entry* name = cert->altEmailNames; + while (name != NULL) { + if (MatchBaseName(ASN_RFC822_TYPE, + name->name, (int)XSTRLEN(name->name), + base->name, base->nameSz)) + return 0; + + name = name->next; + } + } + else if (base->type == ASN_DIR_TYPE) { + if (cert->subjectRawLen == base->nameSz && + XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) { + + return 0; + } + } + 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) { + if (base->type == ASN_DNS_TYPE) { + DNS_entry* name = cert->altNames; + + if (name != NULL) + needDns = 1; + + while (name != NULL) { + matchDns = MatchBaseName(ASN_DNS_TYPE, + name->name, (int)XSTRLEN(name->name), + base->name, base->nameSz); + name = name->next; + } + } + else if (base->type == ASN_RFC822_TYPE) { + DNS_entry* name = cert->altEmailNames; + + if (name != NULL) + needEmail = 1; + + while (name != NULL) { + matchEmail = MatchBaseName(ASN_DNS_TYPE, + name->name, (int)XSTRLEN(name->name), + base->name, base->nameSz); + name = name->next; + } + } + else if (base->type == ASN_DIR_TYPE) { + needDir = 1; + if (cert->subjectRaw != NULL && + cert->subjectRawLen == base->nameSz && + XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) { + + matchDir = 1; + } + } + 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 ASN_PARSE_E; + } + + 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 ASN_PARSE_E; + } + + 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 ASN_PARSE_E; + } + + 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 ASN_PARSE_E; + } + + XMEMCPY(emailEntry->name, &input[idx], strLen); + emailEntry->name[strLen] = '\0'; + + emailEntry->next = cert->altEmailNames; + cert->altEmailNames = emailEntry; + + 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; + + 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, certAltNameType, 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; + } + + if (input[idx++] != ASN_OBJECT_ID) { + WOLFSSL_MSG("\texpected OID"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfailed: str len"); + return ASN_PARSE_E; + } + + 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; + + if (input[idx++] != ASN_OCTET_STRING) { + WOLFSSL_MSG("\texpected Octet String"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfailed: str len"); + return ASN_PARSE_E; + } + + 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; + + 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. */ + + if (input[idx++] != ASN_BOOLEAN) + { + WOLFSSL_MSG("\tfail: constraint not BOOLEAN"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &length, sz) < 0) + { + WOLFSSL_MSG("\tfail: length"); + return ASN_PARSE_E; + } + + if (input[idx++]) + cert->isCA = 1; + + #ifdef OPENSSL_EXTRA + /* If there isn't any more data, return. */ + if (idx >= (word32)sz) + return 0; + + /* Anything left should be the optional pathlength */ + if (input[idx++] != ASN_INTEGER) { + WOLFSSL_MSG("\tfail: pathlen not INTEGER"); + return ASN_PARSE_E; + } + + if (input[idx++] != 1) { + WOLFSSL_MSG("\tfail: pathlen too long"); + return ASN_PARSE_E; + } + + cert->pathLength = input[idx]; + cert->extBasicConstPlSet = 1; + #endif /* OPENSSL_EXTRA */ + + 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, certAuthInfoType, 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; + } + + #ifdef OPENSSL_EXTRA + 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 (input[idx++] != ASN_OCTET_STRING) { + WOLFSSL_MSG("\tfail: should be an OCTET STRING"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: extension data length"); + return ASN_PARSE_E; + } + + #ifdef OPENSSL_EXTRA + 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; + WOLFSSL_ENTER("DecodeKeyUsage"); + + if (input[idx++] != ASN_BIT_STRING) { + WOLFSSL_MSG("\tfail: key usage expected bit string"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: key usage bad length"); + return ASN_PARSE_E; + } + + /* pass the unusedBits value */ + idx++; length--; + + 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; + } + + #ifdef OPENSSL_EXTRA + cert->extExtKeyUsageSrc = input + idx; + cert->extExtKeyUsageSz = length; + #endif + + while (idx < (word32)sz) { + if (GetObjectId(input, &idx, &oid, certKeyUseType, 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_OCSP_SIGN_OID: + cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN; + break; + } + + #ifdef OPENSSL_EXTRA + cert->extExtKeyUsageCount++; + #endif + } + + return 0; +} + + +#ifndef IGNORE_NAME_CONSTRAINTS +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; + + 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; + } + + if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE) || + b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE) || + b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_DIR_TYPE)) { + + Base_entry* 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 = b & 0x0F; + + 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 */ +#endif /* NO_ASN_TIME */ + +#if defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP) + +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 */ +static 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 0; +} +#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; + int total_length = 0, policy_length = 0, length = 0; + + 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 (2 is the CERT_POLICY_OID+SEQ) */ + if ((total_length + 2) != sz) { + 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; + } + + if (input[idx++] != ASN_OBJECT_ID) { + WOLFSSL_MSG("\tCertPolicy isn't OID"); + return ASN_PARSE_E; + } + policy_length--; + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tGet CertPolicy length failed"); + return ASN_PARSE_E; + } + policy_length--; + + 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; + } + 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 */ + +#ifndef NO_ASN_TIME +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. + */ +{ + 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 (GetObjectId(input, &idx, &oid, certExtType, sz) < 0) { + WOLFSSL_MSG("\tfail: OBJECT ID"); + return ASN_PARSE_E; + } + + /* check for critical flag */ + critical = 0; + if (input[idx] == ASN_BOOLEAN) { + int boolLength = 0; + idx++; + if (GetLength(input, &idx, &boolLength, sz) < 0) { + WOLFSSL_MSG("\tfail: critical boolean length"); + return ASN_PARSE_E; + } + if (input[idx++]) + critical = 1; + } + + /* process the extension based on the OID */ + if (input[idx++] != ASN_OCTET_STRING) { + WOLFSSL_MSG("\tfail: should be an OCTET STRING"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: extension data length"); + return ASN_PARSE_E; + } + + switch (oid) { + case BASIC_CA_OID: + #ifdef OPENSSL_EXTRA + cert->extBasicConstSet = 1; + cert->extBasicConstCrit = critical; + #endif + if (DecodeBasicCaConstraint(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case CRL_DIST_OID: + if (DecodeCrlDist(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case AUTH_INFO_OID: + if (DecodeAuthInfo(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case ALT_NAMES_OID: + #ifdef OPENSSL_EXTRA + cert->extSubjAltNameSet = 1; + cert->extSubjAltNameCrit = critical; + #endif + if (DecodeAltNames(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case AUTH_KEY_OID: + cert->extAuthKeyIdSet = 1; + #ifdef OPENSSL_EXTRA + cert->extAuthKeyIdCrit = critical; + #endif + if (DecodeAuthKeyId(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case SUBJ_KEY_OID: + cert->extSubjKeyIdSet = 1; + #ifdef OPENSSL_EXTRA + cert->extSubjKeyIdCrit = critical; + #endif + if (DecodeSubjKeyId(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case CERT_POLICY_OID: + #ifdef WOLFSSL_SEP + #ifdef OPENSSL_EXTRA + cert->extCertPolicySet = 1; + 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: + cert->extKeyUsageSet = 1; + #ifdef OPENSSL_EXTRA + cert->extKeyUsageCrit = critical; + #endif + if (DecodeKeyUsage(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case EXT_KEY_USAGE_OID: + cert->extExtKeyUsageSet = 1; + #ifdef OPENSSL_EXTRA + cert->extExtKeyUsageCrit = critical; + #endif + if (DecodeExtKeyUsage(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + #ifndef IGNORE_NAME_CONSTRAINTS + case NAME_CONS_OID: + cert->extNameConstraintSet = 1; + #ifdef OPENSSL_EXTRA + cert->extNameConstraintCrit = critical; + #endif + if (DecodeNameConstraints(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + #endif /* IGNORE_NAME_CONSTRAINTS */ + + case INHIBIT_ANY_OID: + 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; +} +#endif /* !NO_ASN_TIME */ + + +/* 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 */ + +#ifndef NO_ASN_TIME +int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) +{ + word32 confirmOID; + int ret; + int badDate = 0; + int criticalExt = 0; + + 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(" v1 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, + sigType, 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 + if (ret != 0) + return ret; + } + #endif + + if (verify && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + Signer* ca = NULL; + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + ca = GetCA(cm, cert->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(cm, cert->issuerHash); + #else /* NO_SKID */ + ca = GetCA(cm, cert->issuerHash); + #endif /* NO SKID */ + WOLFSSL_MSG("About to verify certificate signature"); + + if (ca) { +#ifdef HAVE_OCSP + /* Need the ca's public key hash for OCSP */ + #ifdef NO_SHA + ret = wc_Sha256Hash(ca->publicKey, ca->pubKeySize, + cert->issuerKeyHash); + #else /* NO_SHA */ + ret = wc_ShaHash(ca->publicKey, ca->pubKeySize, + cert->issuerKeyHash); + #endif /* NO_SHA */ + if (ret != 0) + return ret; +#endif /* HAVE_OCSP */ + /* try to confirm/verify signature */ + if (!ConfirmSignature(cert->source + cert->certBegin, + cert->sigIndex - cert->certBegin, + ca->publicKey, ca->pubKeySize, ca->keyOID, + cert->signature, cert->sigLength, cert->signatureOID, + cert->heap)) { + WOLFSSL_MSG("Confirm signature failed"); + return ASN_SIG_CONFIRM_E; + } +#ifndef IGNORE_NAME_CONSTRAINTS + /* check that this cert's name is permitted by the signer's + * name constraints */ + if (!ConfirmNameConstraints(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 (badDate != 0) + return badDate; + + if (criticalExt != 0) + return criticalExt; + + return 0; +} +#endif /* !NO_ASN_TIME */ + +/* 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->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 + 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++] = ASN_BIT_STRING; + } + 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 result = 0; + + WOLFSSL_ENTER("SetSerialNumber"); + + if (sn == NULL || output == NULL) + return BAD_FUNC_ARG; + + if (snSz <= EXTERNAL_SERIAL_SIZE) { + output[0] = ASN_INTEGER; + /* The serial number is always positive. When encoding the + * INTEGER, if the MSB is 1, add a padding zero to keep the + * number positive. */ + if (sn[0] & 0x80) { + output[1] = (byte)snSz + 1; + output[2] = 0; + XMEMCPY(&output[3], sn, snSz); + result = snSz + 3; + } + else { + output[1] = (byte)snSz; + XMEMCPY(&output[2], sn, snSz); + result = snSz + 2; + } + } + return result; +} + + + +const char* BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; +const char* END_CERT = "-----END CERTIFICATE-----"; +const char* BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----"; +const char* END_CERT_REQ = "-----END CERTIFICATE REQUEST-----"; +const char* BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----"; +const char* END_DH_PARAM = "-----END DH PARAMETERS-----"; +const char* BEGIN_X509_CRL = "-----BEGIN X509 CRL-----"; +const char* END_X509_CRL = "-----END X509 CRL-----"; +const char* BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----"; +const char* END_RSA_PRIV = "-----END RSA PRIVATE KEY-----"; +const char* BEGIN_PRIV_KEY = "-----BEGIN PRIVATE KEY-----"; +const char* END_PRIV_KEY = "-----END PRIVATE KEY-----"; +const char* BEGIN_ENC_PRIV_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; +const char* END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----"; +const char* BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----"; +const char* END_EC_PRIV = "-----END EC PRIVATE KEY-----"; +const char* BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; +const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; +const char* BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; +const char* END_PUB_KEY = "-----END PUBLIC KEY-----"; + +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) + +/* 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) +{ +#ifdef WOLFSSL_SMALL_STACK + char* header = NULL; + char* footer = NULL; +#else + char header[40 + HEADER_ENCRYPTED_KEY_SIZE]; + char footer[40]; +#endif + + int headerLen = 40 + HEADER_ENCRYPTED_KEY_SIZE; + int footerLen = 40; + int i; + int err; + int outLen; /* return length or error */ + + if (der == output) /* no in place conversion */ + return BAD_FUNC_ARG; + +#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 + if (type == CERT_TYPE) { + XSTRNCPY(header, BEGIN_CERT, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_CERT, footerLen); + XSTRNCAT(footer, "\n", 1); + } + else if (type == PRIVATEKEY_TYPE) { + XSTRNCPY(header, BEGIN_RSA_PRIV, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_RSA_PRIV, footerLen); + XSTRNCAT(footer, "\n", 1); + } +#ifndef NO_DSA + else if (type == DSA_PRIVATEKEY_TYPE) { + XSTRNCPY(header, BEGIN_DSA_PRIV, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_DSA_PRIV, footerLen); + XSTRNCAT(footer, "\n", 1); + } +#endif +#ifdef HAVE_ECC + else if (type == ECC_PRIVATEKEY_TYPE) { + XSTRNCPY(header, BEGIN_EC_PRIV, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_EC_PRIV, footerLen); + XSTRNCAT(footer, "\n", 1); + } +#endif +#ifdef WOLFSSL_CERT_REQ + else if (type == CERTREQ_TYPE) + { + XSTRNCPY(header, BEGIN_CERT_REQ, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_CERT_REQ, footerLen); + XSTRNCAT(footer, "\n", 1); + } +#endif + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + /* extra header information for encrypted key */ + if (cipher_info != NULL) { + XSTRNCAT(header, "Proc-Type: 4,ENCRYPTED\n", 23); + XSTRNCAT(header, "DEK-Info: ", 10); + XSTRNCAT(header, (char*)cipher_info, XSTRLEN((char*)cipher_info)); + XSTRNCAT(header, "\n\n", 2); + } + + headerLen = (int)XSTRLEN(header); + footerLen = (int)XSTRLEN(footer); + + 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_KEY_GEN || WOLFSSL_CERT_GEN */ + +#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || (defined(WOLFSSL_KEY_GEN) && !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 len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + int nSz; + int eSz; + int seqSz; + int lenSz; + int idx; + int rawLen; + int leadingBit; + int err; + + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (n == NULL) + return MEMORY_E; +#endif + +#ifdef HAVE_USER_RSA + leadingBit = wc_Rsa_leading_bit(key->n); + rawLen = wc_Rsa_unsigned_bin_size(key->n) + leadingBit; +#else + leadingBit = mp_leading_bit(&key->n); + rawLen = mp_unsigned_bin_size(&key->n) + leadingBit; +#endif + n[0] = ASN_INTEGER; + nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ + + if ( (nSz + rawLen) < MAX_RSA_INT_SZ) { + if (leadingBit) + n[nSz] = 0; +#ifdef HAVE_USER_RSA + err = wc_Rsa_to_unsigned_bin(key->n, n + nSz, rawLen); +#else + err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit); +#endif + if (err == MP_OKAY) + nSz += rawLen; + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MP_TO_E; + } + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + + /* e */ +#ifdef WOLFSSL_SMALL_STACK + e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (e == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } +#endif + +#ifdef HAVE_USER_RSA + leadingBit = wc_Rsa_leading_bit(key->e); + rawLen = wc_Rsa_unsigned_bin_size(key->e) + leadingBit; +#else + leadingBit = mp_leading_bit(&key->e); + rawLen = mp_unsigned_bin_size(&key->e) + leadingBit; +#endif + e[0] = ASN_INTEGER; + eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ + + if ( (eSz + rawLen) < MAX_RSA_E_SZ) { + if (leadingBit) + e[eSz] = 0; +#ifdef HAVE_USER_RSA + err = wc_Rsa_to_unsigned_bin(key->e, e + eSz, rawLen); +#else + err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit); +#endif + if (err == MP_OKAY) + eSz += rawLen; + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MP_TO_E; + } + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + + seqSz = SetSequence(nSz + eSz, seq); + + /* check output size */ + if ( (seqSz + nSz + eSz) > outLen) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#else + byte algo[MAX_ALGO_SZ]; +#endif + algoSz = SetAlgoID(RSAk, algo, keyType, 0); + lenSz = SetLength(seqSz + nSz + eSz + 1, len); + len[lenSz++] = 0; /* trailing 0 */ + + /* write, 1 is for ASN_BIT_STRING */ + idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); + + /* check output size */ + if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return BUFFER_E; + } + + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + output[idx++] = ASN_BIT_STRING; + /* length */ + XMEMCPY(output + idx, len, lenSz); + idx += lenSz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(algo, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} +#endif /* !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || + defined(WOLFSSL_KEY_GEN)) */ + + +#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 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, lbit; + + 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); + + /* leading zero */ + lbit = mp_leading_bit(keyInt); + rawLen = mp_unsigned_bin_size(keyInt) + lbit; + + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, + DYNAMIC_TYPE_RSA); + if (tmps[i] == NULL) { + ret = MEMORY_E; + break; + } + + tmps[i][0] = ASN_INTEGER; + sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ + + if (sizes[i] <= MAX_SEQ_SZ) { + int err; + + /* leading zero */ + if (lbit) + tmps[i][sizes[i]-1] = 0x00; + + err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); + if (err == MP_OKAY) { + sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ + intTotalLen += sizes[i]; + } + else { + ret = err; + break; + } + } + else { + ret = ASN_INPUT_E; + break; + } + } + + 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) + 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; +} + + +/* 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 */ + + +#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +/* 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 +*/ +void wc_InitCert(Cert* cert) +{ + cert->version = 2; /* version 3 is hex 2 */ + cert->sigType = CTC_SHAwRSA; + cert->daysValid = 500; + cert->selfSigned = 1; + cert->isCA = 0; + cert->bodySz = 0; +#ifdef WOLFSSL_ALT_NAMES + cert->altNamesSz = 0; + cert->beforeDateSz = 0; + cert->afterDateSz = 0; +#endif +#ifdef WOLFSSL_CERT_EXT + cert->skidSz = 0; + cert->akidSz = 0; + cert->keyUsage = 0; + cert->certPoliciesNb = 0; + XMEMSET(cert->akid, 0, CTC_MAX_AKID_SIZE); + XMEMSET(cert->skid, 0, CTC_MAX_SKID_SIZE); + XMEMSET(cert->certPolicies, 0, CTC_MAX_CERTPOL_NB*CTC_MAX_CERTPOL_SZ); +#endif + cert->keyType = RSA_KEY; + XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE); + + cert->issuer.country[0] = '\0'; + cert->issuer.countryEnc = CTC_PRINTABLE; + cert->issuer.state[0] = '\0'; + cert->issuer.stateEnc = CTC_UTF8; + cert->issuer.locality[0] = '\0'; + cert->issuer.localityEnc = CTC_UTF8; + cert->issuer.sur[0] = '\0'; + cert->issuer.surEnc = CTC_UTF8; + cert->issuer.org[0] = '\0'; + cert->issuer.orgEnc = CTC_UTF8; + cert->issuer.unit[0] = '\0'; + cert->issuer.unitEnc = CTC_UTF8; + cert->issuer.commonName[0] = '\0'; + cert->issuer.commonNameEnc = CTC_UTF8; + cert->issuer.email[0] = '\0'; + + cert->subject.country[0] = '\0'; + cert->subject.countryEnc = CTC_PRINTABLE; + cert->subject.state[0] = '\0'; + cert->subject.stateEnc = CTC_UTF8; + cert->subject.locality[0] = '\0'; + cert->subject.localityEnc = CTC_UTF8; + cert->subject.sur[0] = '\0'; + cert->subject.surEnc = CTC_UTF8; + cert->subject.org[0] = '\0'; + cert->subject.orgEnc = CTC_UTF8; + cert->subject.unit[0] = '\0'; + cert->subject.unitEnc = CTC_UTF8; + cert->subject.commonName[0] = '\0'; + cert->subject.commonNameEnc = CTC_UTF8; + cert->subject.email[0] = '\0'; + +#ifdef WOLFSSL_CERT_REQ + cert->challengePw[0] ='\0'; +#endif +} + + +/* DER encoded x509 Certificate */ +typedef struct DerCert { + byte size[MAX_LENGTH_SZ]; /* length encoded */ + byte version[MAX_VERSION_SZ]; /* version encoded */ + byte serial[CTC_SERIAL_SIZE + 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 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 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 */ + + +/* Write a serial number to output */ +static int SetSerial(const byte* serial, byte* output) +{ + int length = 0; + + output[length++] = ASN_INTEGER; + length += SetLength(CTC_SERIAL_SIZE, &output[length]); + XMEMCPY(&output[length], serial, CTC_SERIAL_SIZE); + + return length + CTC_SERIAL_SIZE; +} + + +#ifdef HAVE_ECC + + +/* Write a public ECC key to output */ +static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) +{ + byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + int algoSz; + int curveSz; + int lenSz; + 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 + +#ifdef WOLFSSL_SMALL_STACK + pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) + return MEMORY_E; +#endif + + int ret = wc_ecc_export_x963(key, pub, &pubSz); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* headers */ + if (with_header) { +#ifdef WOLFSSL_SMALL_STACK + curve = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (curve == NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + curveSz = SetCurve(key, curve); + if (curveSz <= 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return curveSz; + } + +#ifdef WOLFSSL_SMALL_STACK + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + algoSz = SetAlgoID(ECDSAk, algo, keyType, curveSz); + + lenSz = SetLength(pubSz + 1, len); + len[lenSz++] = 0; /* trailing 0 */ + + /* write, 1 is for ASN_BIT_STRING */ + idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output); + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* curve */ + XMEMCPY(output + idx, curve, curveSz); + idx += curveSz; + /* bit string */ + output[idx++] = ASN_BIT_STRING; + /* length */ + XMEMCPY(output + idx, len, lenSz); + idx += lenSz; + } + 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(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + + +#endif /* HAVE_ECC */ + + +static 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 + + +/* for systems where mktime() doesn't normalize fully */ +static void RebuildTime(time_t* in, struct tm* out) +{ + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + out = localtime_r(in, out); + #else + (void)in; + (void)out; + #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 ticks; + time_t normalTime; + struct tm* now; + struct tm* tmpTime = NULL; + struct tm local; + +#if defined(NEED_TMP_TIME) + /* for use with gmtime_r */ + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + + ticks = XTIME(0); + now = XGMTIME(&ticks, tmpTime); + + if (now == NULL) { + WOLFSSL_MSG("XGMTIME failed"); + return 0; /* error */ + } + + /* before now */ + local = *now; + before[0] = ASN_GENERALIZED_TIME; + beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */ + + /* subtract 1 day for more compliance */ + local.tm_mday -= 1; + normalTime = mktime(&local); + RebuildTime(&normalTime, &local); + + /* adjust */ + local.tm_year += 1900; + local.tm_mon += 1; + + SetTime(&local, before + beforeSz); + beforeSz += ASN_GEN_TIME_SZ; + + /* after now + daysValid */ + local = *now; + after[0] = ASN_GENERALIZED_TIME; + afterSz = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1; /* gen tag */ + + /* add daysValid */ + local.tm_mday += daysValid; + normalTime = mktime(&local); + RebuildTime(&normalTime, &local); + + /* adjust */ + local.tm_year += 1900; + local.tm_mon += 1; + + SetTime(&local, 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: + /* email uses different id type */ + return 0; + + 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 (outSz < idx + inSz + oidSz + 1) + 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, byte *input, word32 length) +{ + byte skid_len[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; + + /* length of value */ + skid_lenSz = SetLength(length, skid_len); + + /* length of encoded value */ + skid_enc_lenSz = SetLength(length + skid_lenSz + 1, skid_enc_len); + + if (outSz < 3) + return BUFFER_E; + + /* sequence, + 1 => byte to put type size */ + idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz+1, + output); + + if (outSz < length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz + 1) + 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 type */ + output[idx++] = ASN_OCTET_STRING; + + /* put value len */ + 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) +{ + 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_val = (byte *)XMALLOC(length+3+sizeof(akid_cs), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (enc_val == NULL) + return MEMORY_E; + + /* sequence for ContentSpec & value */ + enc_valSz = SetOidValue(enc_val, length+3+sizeof(akid_cs), + akid_cs, sizeof(akid_cs), input, length); + if (enc_valSz == 0) { + XFREE(enc_val, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return 0; + } + + ret = SetOidValue(output, outSz, akid_oid, + sizeof(akid_oid), enc_val, enc_valSz); + + XFREE(enc_val, NULL, 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 unusedBits = 0; + static const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04}; + + if (output == NULL) + return BAD_FUNC_ARG; + + /* Key Usage is a BitString */ + ku[0] = ASN_BIT_STRING; + + /* put the Bit String size */ + if (input > 255) { + ku[1] = (byte)3; + + /* compute unused bits */ + while (((((input >> 8) & 0xff) >> unusedBits) & 0x01) == 0) + unusedBits++; + } + else { + ku[1] = (byte)2; + + /* compute unused bits */ + while (((input >> unusedBits) & 0x01) == 0) + unusedBits++; + } + + /* put unused bits value */ + ku[2] = (byte)unusedBits; + + /* compute byte value */ + ku[3] = (byte)(input & 0xff); + if (input > 255) + ku[4] = (byte)((input >> 8) & 0xff); + + return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid), + ku, (int)ku[1]+2); +} + +/* Encode OID string representation to ITU-T X.690 format */ +static int EncodePolicyOID(byte *out, word32 *outSz, const char *in) +{ + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + + XSTRNCPY(str, in, len); + str[len] = 0x00; + + 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, NUL, DYNAMIC_TYPE_TMP_BUFFER); + return ASN_OBJECT_ID_E; + } + + out[idx] = (byte)(40 * val); + } + else if (nb_val == 1) { + if (val > 127) { + XFREE(str, NUL, DYNAMIC_TYPE_TMP_BUFFER); + return ASN_OBJECT_ID_E; + } + + if (idx > *outSz) { + XFREE(str, NUL, 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, NUL, 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, NUL, 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) +{ + 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]); + 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 */ + + +/* encode CertName into output, return total bytes written */ +static 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 + + 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++) { + const char* nameStr = GetOneName(name, i); + if (nameStr) { + /* bottom up */ + byte firstLen[MAX_LENGTH_SZ]; + byte secondLen[MAX_LENGTH_SZ]; + byte sequence[MAX_SEQ_SZ]; + byte set[MAX_SET_SZ]; + + int email = i == (NAME_ENTRIES - 1) ? 1 : 0; + int strLen = (int)XSTRLEN(nameStr); + int thisLen = strLen; + int firstSz, secondSz, seqSz, setSz; + + if (strLen == 0) { /* no user data for this item */ + names[i].used = 0; + continue; + } + + secondSz = SetLength(strLen, secondLen); + thisLen += secondSz; + if (email) { + thisLen += EMAIL_JOINT_LEN; + thisLen ++; /* id type */ + firstSz = SetLength(EMAIL_JOINT_LEN, firstLen); + } + else { + thisLen++; /* str type */ + thisLen++; /* id type */ + thisLen += JOINT_LEN; + firstSz = SetLength(JOINT_LEN + 1, firstLen); + } + thisLen += firstSz; + thisLen++; /* object id */ + + seqSz = SetSequence(thisLen, sequence); + thisLen += seqSz; + setSz = SetSet(thisLen, set); + thisLen += setSz; + + if (thisLen > (int)sizeof(names[i].encoded)) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + + /* store it */ + idx = 0; + /* set */ + XMEMCPY(names[i].encoded, set, setSz); + idx += setSz; + /* seq */ + XMEMCPY(names[i].encoded + idx, sequence, seqSz); + idx += seqSz; + /* asn object id */ + names[i].encoded[idx++] = ASN_OBJECT_ID; + /* first length */ + XMEMCPY(names[i].encoded + idx, firstLen, firstSz); + idx += firstSz; + if (email) { + const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x01, 0x16 }; + /* email joint id */ + XMEMCPY(names[i].encoded + idx, EMAIL_OID, sizeof(EMAIL_OID)); + idx += (int)sizeof(EMAIL_OID); + } + else { + /* joint id */ + byte bType = GetNameId(i); + names[i].encoded[idx++] = 0x55; + names[i].encoded[idx++] = 0x04; + /* id type */ + names[i].encoded[idx++] = bType; + /* str type */ + names[i].encoded[idx++] = GetNameType(name, i); + } + /* second length */ + XMEMCPY(names[i].encoded + idx, secondLen, secondSz); + idx += secondSz; + /* str value */ + XMEMCPY(names[i].encoded + idx, nameStr, strLen); + idx += strLen; + + totalBytes += idx; + names[i].totalLen = idx; + names[i].used = 1; + } + else + names[i].used = 0; + } + + /* 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++) { + 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) +{ + int ret; + + (void)eccKey; + (void)ntruKey; + (void)ntruSz; + + if (cert == NULL || der == NULL || rng == NULL) + return BAD_FUNC_ARG; + + /* init */ + XMEMSET(der, 0, sizeof(DerCert)); + + /* version */ + der->versionSz = SetMyVersion(cert->version, der->version, TRUE); + + /* serial number */ + ret = wc_RNG_GenerateBlock(rng, cert->serial, CTC_SERIAL_SIZE); + if (ret != 0) + return ret; + + cert->serial[0] = 0x01; /* ensure positive */ + der->serialSz = SetSerial(cert->serial, der->serial); + + /* signature algo */ + der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType, 0); + if (der->sigAlgoSz == 0) + return ALGO_ID_E; + + /* public key */ + if (cert->keyType == RSA_KEY) { + if (rsaKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, + sizeof(der->publicKey), 1); + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + } + +#ifdef HAVE_ECC + if (cert->keyType == ECC_KEY) { + if (eccKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + } +#endif /* HAVE_ECC */ + +#ifdef HAVE_NTRU + if (cert->keyType == NTRU_KEY) { + word32 rc; + word16 encodedSz; + + 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; + } +#endif /* HAVE_NTRU */ + + 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)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; + + /* AKID */ + if (cert->akidSz) { + /* check the provided AKID size */ + if (cert->akidSz > (int)sizeof(der->akid)) + return AKID_E; + + der->akidSz = SetAKID(der->akid, sizeof(der->akid), + cert->akid, cert->akidSz); + 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; + + /* Certificate Policies */ + if (cert->certPoliciesNb != 0) { + der->certPoliciesSz = SetCertificatePolicies(der->certPolicies, + sizeof(der->certPolicies), + cert->certPolicies, + cert->certPoliciesNb); + 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 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, + sizeof(der->extensions))); + idx += der->extensionsSz; + } + + return idx; +} + + +/* Make RSA signature from buffer (sz), write to sig (sigSz) */ +static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, + int sigAlgoType) +{ + int encSigSz, digestSz, typeH = 0, ret = 0; + byte digest[MAX_DIGEST_SIZE]; /* max size */ +#ifdef WOLFSSL_SMALL_STACK + byte* encSig; +#else + byte encSig[MAX_DER_DIGEST_SZ]; +#endif + + (void)digest; + (void)digestSz; + (void)encSig; + (void)encSigSz; + (void)typeH; + + (void)buffer; + (void)sz; + (void)sig; + (void)sigSz; + (void)rsaKey; + (void)eccKey; + (void)rng; + + switch (sigAlgoType) { + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buffer, sz, digest)) == 0) { + typeH = MD5h; + digestSz = MD5_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwECDSA: + if ((ret = wc_ShaHash(buffer, sz, digest)) == 0) { + typeH = SHAh; + digestSz = SHA_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if ((ret = wc_Sha256Hash(buffer, sz, digest)) == 0) { + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buffer, sz, digest)) == 0) { + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + default: + WOLFSSL_MSG("MakeSignautre called with unsupported type"); + ret = ALGO_ID_E; + } + + if (ret != 0) + return ret; + +#ifdef WOLFSSL_SMALL_STACK + encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encSig == NULL) + return MEMORY_E; +#endif + + ret = ALGO_ID_E; + +#ifndef NO_RSA + if (rsaKey) { + /* signature */ + encSigSz = wc_EncodeSignature(encSig, digest, digestSz, typeH); + ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng); + } +#endif + +#ifdef HAVE_ECC + if (!rsaKey && eccKey) { + word32 outSz = sigSz; + ret = wc_ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey); + + if (ret == 0) + ret = outSz; + } +#endif + +#ifdef WOLFSSL_SMALL_STACK + XFREE(encSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + 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, sigType, 0); + /* bit string */ + buffer[idx++] = ASN_BIT_STRING; + /* length */ + idx += SetLength(sigSz + 1, buffer + idx); + buffer[idx++] = 0; /* trailing 0 */ + /* 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) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DerCert* der; +#else + DerCert der[1]; +#endif + + cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : NTRU_KEY); + +#ifdef WOLFSSL_SMALL_STACK + der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) + return MEMORY_E; +#endif + + ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz); + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +/* 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); +} + + +#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); +} + +#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) +{ + (void)eccKey; + + if (cert == NULL || der == NULL) + return BAD_FUNC_ARG; + + /* 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 */ + if (cert->keyType == RSA_KEY) { + if (rsaKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, + sizeof(der->publicKey), 1); + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + } + +#ifdef HAVE_ECC + if (cert->keyType == ECC_KEY) { + if (eccKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + } +#endif /* HAVE_ECC */ + + /* 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)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; +#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; + } + +#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, + sizeof(der->extensions))); + idx += der->extensionsSz; + } + + return idx; +} + + +int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DerCert* der; +#else + DerCert der[1]; +#endif + + cert->keyType = eccKey ? ECC_KEY : RSA_KEY; + +#ifdef WOLFSSL_SMALL_STACK + der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) + return MEMORY_E; +#endif + + ret = EncodeCertReq(cert, der, rsaKey, eccKey); + + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* WOLFSSL_CERT_REQ */ + + +int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +{ + int sigSz; +#ifdef WOLFSSL_SMALL_STACK + byte* sig; +#else + byte sig[MAX_ENCODED_SIG_SZ]; +#endif + + if (requestSz < 0) + return requestSz; + +#ifdef WOLFSSL_SMALL_STACK + sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sig == NULL) + return MEMORY_E; +#endif + + sigSz = MakeSignature(buffer, requestSz, sig, MAX_ENCODED_SIG_SZ, rsaKey, + eccKey, rng, sType); + + if (sigSz >= 0) { + if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz) + sigSz = BUFFER_E; + else + sigSz = AddSignature(buffer, requestSz, sig, sigSz, sType); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return sigSz; +} + + +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 RSA or ECC public key */ +static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, + byte *ntruKey, word16 ntruKeySz, int kid_type) +{ + byte *buffer; + int bufferSz, ret; + +#ifndef HAVE_NTRU + (void)ntruKeySz; +#endif + + if (cert == NULL || (rsakey == NULL && eckey == NULL && ntruKey == NULL) || + (rsakey != NULL && eckey != NULL) || + (rsakey != NULL && ntruKey != NULL) || + (ntruKey != NULL && eckey != NULL) || + (kid_type != SKID_TYPE && kid_type != AKID_TYPE)) + return BAD_FUNC_ARG; + + buffer = (byte *)XMALLOC(MAX_PUBLIC_KEY_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) + return MEMORY_E; + + /* RSA public key */ + if (rsakey != NULL) + bufferSz = SetRsaPublicKey(buffer, rsakey, MAX_PUBLIC_KEY_SZ, 0); +#ifdef HAVE_ECC + /* ECC public key */ + else if (eckey != NULL) + bufferSz = SetEccPublicKey(buffer, eckey, 0); +#endif /* HAVE_ECC */ +#ifdef HAVE_NTRU + /* NTRU public key */ + else 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; + } +#endif + else + bufferSz = -1; + + if (bufferSz <= 0) { + XFREE(buffer, NULL, 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 = SHA256_DIGEST_SIZE; + } + else if (kid_type == AKID_TYPE) { + ret = wc_Sha256Hash(buffer, bufferSz, cert->akid); + cert->akidSz = 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 = SHA_DIGEST_SIZE; + } + else if (kid_type == AKID_TYPE) { + ret = wc_ShaHash(buffer, bufferSz, cert->akid); + cert->akidSz = SHA_DIGEST_SIZE; + } + else + ret = BAD_FUNC_ARG; +#endif /* NO_SHA */ + + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +/* 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, 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, SKID_TYPE); +} +#endif + +/* 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, 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, NULL, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetSubjectKeyId memory Problem"); + return MEMORY_E; + } + + derSz = wolfSSL_PemPubKeyToDer(file, der, MAX_PUBLIC_KEY_SZ); + if (derSz <= 0) + { + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + return derSz; + } + + /* Load PubKey in internal structure */ + rsakey = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (rsakey == NULL) { + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + if (wc_InitRsaKey(rsakey, NULL) != 0) { + WOLFSSL_MSG("wc_InitRsaKey failure"); + XFREE(rsakey, NULL, DYNAMIC_TYPE_RSA); + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + idx = 0; + ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz); + if (ret != 0) { + WOLFSSL_MSG("wc_RsaPublicKeyDecode failed"); + wc_FreeRsaKey(rsakey); + XFREE(rsakey, NULL, DYNAMIC_TYPE_RSA); + rsakey = NULL; +#ifdef HAVE_ECC + /* Check to load ecc public key */ + eckey = (ecc_key*) XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (eckey == NULL) { + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + if (wc_ecc_init(eckey) != 0) { + WOLFSSL_MSG("wc_ecc_init failure"); + wc_ecc_free(eckey); + XFREE(eckey, NULL, DYNAMIC_TYPE_ECC); + XFREE(der, NULL, 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, NULL, DYNAMIC_TYPE_CERT); + wc_ecc_free(eckey); + return PUBLIC_KEY_E; + } +#else + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + return PUBLIC_KEY_E; +#endif /* HAVE_ECC */ + } + + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + + ret = wc_SetSubjectKeyIdFromPublicKey(cert, rsakey, eckey); + + wc_FreeRsaKey(rsakey); + XFREE(rsakey, NULL, DYNAMIC_TYPE_RSA); +#ifdef HAVE_ECC + wc_ecc_free(eckey); + XFREE(eckey, NULL, 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), + NULL, 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, 0); + ret = ParseCert(decoded, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) { + FreeDecodedCert(decoded); + return ret; + } + + /* Subject Key Id not found !! */ + if (decoded->extSubjKeyIdSet == 0) { + FreeDecodedCert(decoded); + return ASN_NO_SKID; + } + + /* SKID invalid size */ + if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) { + FreeDecodedCert(decoded); + 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); + 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, NULL, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetAuthKeyId OOF Problem"); + return MEMORY_E; + } + + derSz = wolfSSL_PemCertToDer(file, der, EIGHTK_BUF); + if (derSz <= 0) + { + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + return derSz; + } + + ret = wc_SetAuthKeyIdFromCert(cert, der, derSz); + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + + return ret; +} + +#endif /* NO_FILESYSTEM */ + +/* Set KeyUsage from human readable string */ +int wc_SetKeyUsage(Cert *cert, const char *value) +{ + char *token, *str, *ptr; + word32 len; + + if (cert == NULL || value == NULL) + return BAD_FUNC_ARG; + + cert->keyUsage = 0; + + str = (char *)XMALLOC(XSTRLEN(value)+1, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + + XMEMSET(str, 0, XSTRLEN(value)+1); + XSTRNCPY(str, value, XSTRLEN(value)); + + /* parse value, and set corresponding Key Usage value */ + token = XSTRTOK(str, ",", &ptr); + 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 + return KEYUSAGE_E; + + token = XSTRTOK(NULL, ",", &ptr); + } + + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +} +#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), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(decoded, (byte*)der, derSz, 0); + 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, + certExtType, 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, NULL, 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), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(decoded, (byte*)der, derSz, 0); + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret < 0 ? ret : 0; +} + + +#endif /* WOLFSSL_ALT_NAMES && !NO_RSA */ + + +/* 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, 0); + 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; + strncpy(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; + strncpy(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; + strncpy(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; + strncpy(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; + strncpy(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; + strncpy(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; + strncpy(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; + strncpy(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, NULL, DYNAMIC_TYPE_CERT); + + if (der == NULL) { + WOLFSSL_MSG("wc_SetIssuer OOF Problem"); + return MEMORY_E; + } + derSz = wolfSSL_PemCertToDer(issuerFile, der, EIGHTK_BUF); + cert->selfSigned = 0; + ret = SetNameFromCert(&cert->issuer, der, derSz); + XFREE(der, NULL, 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, NULL, DYNAMIC_TYPE_CERT); + + if (der == NULL) { + WOLFSSL_MSG("wc_SetSubject OOF Problem"); + return MEMORY_E; + } + derSz = wolfSSL_PemCertToDer(subjectFile, der, EIGHTK_BUF); + ret = SetNameFromCert(&cert->subject, der, derSz); + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + + return ret; +} + + +#ifdef WOLFSSL_ALT_NAMES + +/* Set atl names from file in PEM */ +int wc_SetAltNames(Cert* cert, const char* file) +{ + int ret; + int derSz; + byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT); + + if (der == NULL) { + WOLFSSL_MSG("wc_SetAltNames OOF Problem"); + return MEMORY_E; + } + derSz = wolfSSL_PemCertToDer(file, der, EIGHTK_BUF); + ret = SetAltNamesFromCert(cert, der, derSz); + XFREE(der, NULL, 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; + word32 rSz; /* encoding size */ + word32 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); + int err; + + if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero + + headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */ + return BAD_FUNC_ARG; + + idx = SetSequence(rLen+rLeadingZero+sLen+sLeadingZero+headerSz, out); + + /* store r */ + out[idx++] = ASN_INTEGER; + rSz = SetLength(rLen + rLeadingZero, &out[idx]); + idx += rSz; + if (rLeadingZero) + out[idx++] = 0; + err = mp_to_unsigned_bin(r, &out[idx]); + if (err != MP_OKAY) return err; + idx += rLen; + + /* store s */ + out[idx++] = ASN_INTEGER; + sSz = SetLength(sLen + sLeadingZero, &out[idx]); + idx += sSz; + if (sLeadingZero) + out[idx++] = 0; + err = mp_to_unsigned_bin(s, &out[idx]); + if (err != MP_OKAY) return err; + idx += sLen; + + *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 oid = 0; + int version, length; + int privSz, pubSz; + byte b; + int ret = 0; +#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 + + 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) < 0) + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) + return MEMORY_E; + + pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + /* priv key */ + privSz = length; + XMEMCPY(priv, &input[*inOutIdx], privSz); + *inOutIdx += length; + + /* 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 { + /* object id */ + b = input[*inOutIdx]; + *inOutIdx += 1; + + if (b != ASN_OBJECT_ID) { + ret = ASN_OBJECT_ID_E; + } + else if (GetLength(input, inOutIdx, &length, inSz) < 0) { + ret = ASN_PARSE_E; + } + else { + while(length--) { + oid += input[*inOutIdx]; + *inOutIdx += 1; + } + if (CheckCurve(oid) < 0) + ret = ECC_CURVE_OID_E; + } + } + } + + if (ret == 0) { + /* 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 */ + b = input[*inOutIdx]; + *inOutIdx += 1; + + if (b != ASN_BIT_STRING) { + ret = ASN_BITSTR_E; + } + else if (GetLength(input, inOutIdx, &length, inSz) < 0) { + ret = ASN_PARSE_E; + } + else if (length <= 0) { + /* pubkey needs some size */ + ret = ASN_INPUT_E; + } + else { + b = input[*inOutIdx]; + *inOutIdx += 1; + + if (b != 0x00) { + ret = ASN_EXPECT_0_E; + } + else { + /* pub key */ + pubSz = length - 1; /* null prefix */ + if (pubSz < 2*(ECC_MAXSIZE+1)) { + XMEMCPY(pub, &input[*inOutIdx], pubSz); + *inOutIdx += length; + ret = wc_ecc_import_private_key(priv, privSz, pub, pubSz, + key); + } else + ret = BUFFER_E; + } + } + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, + ecc_key* key, word32 inSz) +{ + int length; + int ret = 0; + + 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 defined(OPENSSL_EXTRA) || defined(ECC_DECODE_EXTRA) + { + byte 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; + + b = input[(*inOutIdx)++]; + if (b != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + *inOutIdx += length; /* skip past */ + + /* ecc params information */ + b = input[(*inOutIdx)++]; + if (b != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + *inOutIdx += length; /* skip past */ + + /* key header */ + b = input[*inOutIdx]; + *inOutIdx += 1; + + if (b != ASN_BIT_STRING) + ret = ASN_BITSTR_E; + else if (GetLength(input, inOutIdx, &length, inSz) < 0) + ret = ASN_PARSE_E; + else { + b = input[*inOutIdx]; + *inOutIdx += 1; + + if (b != 0x00) + ret = ASN_EXPECT_0_E; + } + } + } /* openssl var block */ +#endif /* OPENSSL_EXTRA */ + + if (wc_ecc_import_x963(input+*inOutIdx, inSz - *inOutIdx, key) != 0) + return ASN_ECC_KEY_E; + + return ret; +} + + +#ifdef WOLFSSL_KEY_GEN + +/* Write a Private ecc key to DER format, length on success else < 0 */ +int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + byte curve[MAX_ALGO_SZ+2]; + byte ver[MAX_VERSION_SZ]; + byte seq[MAX_SEQ_SZ]; + byte *prv, *pub; + 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, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (prv == NULL) { + return MEMORY_E; + } + prv[prvidx++] = ASN_OCTET_STRING; + prv[prvidx++] = (byte)key->dp->size; + ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz); + if (ret < 0) { + XFREE(prv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + prvidx += privSz; + + /* public */ + ret = wc_ecc_export_x963(key, NULL, &pubSz); + if (ret != LENGTH_ONLY_E) { + XFREE(prv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(prv, NULL, 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); + pub[pubidx++] = ASN_BIT_STRING; + pubidx += SetLength(pubSz + 1, pub+pubidx); + pub[pubidx++] = (byte)0; /* leading zero */ + ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); + if (ret != 0) { + XFREE(prv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* curve */ + XMEMCPY(output + idx, curve, curveidx); + idx += curveidx; + + /* public */ + XMEMCPY(output + idx, pub, pubidx); + /* idx += pubidx; not used after write, if more data remove comment */ + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return totalSz; +} + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* HAVE_ECC */ + + +#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 length; + + WOLFSSL_ENTER("GetBasicDate"); + + *format = source[*idx]; + *idx += 1; + if (*format != ASN_UTC_TIME && *format != ASN_GENERALIZED_TIME) + return ASN_TIME_E; + + 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; + + XMEMCPY(date, &source[*idx], length); + *idx += 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; + + 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, ignoreType, size) < 0) + return ASN_PARSE_E; + /* Save reference to the hash of CN */ + if (source[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + resp->issuerHash = source + idx; + idx += length; + /* Save reference to the hash of the issuer public key */ + if (source[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + resp->issuerKeyHash = source + idx; + idx += length; + + /* Read the serial number, it is handled as a string, not as a + * proper number. Just XMEMCPY the data over, rather than load it + * as an mp_int. */ + if (source[idx++] != ASN_INTEGER) + return ASN_PARSE_E; + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + if (length <= EXTERNAL_SERIAL_SIZE) + { + if (source[idx] == 0) + { + idx++; + length--; + } + XMEMCPY(cs->serial, source + idx, length); + cs->serialSz = length; + } + else + { + return ASN_GETINT_E; + } + idx += length; + + /* 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 (GetBasicDate(source, &idx, cs->thisDate, + &cs->thisDateFormat, size) < 0) + return ASN_PARSE_E; + if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) + return ASN_BEFORE_DATE_E; + + /* 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 (GetBasicDate(source, &idx, cs->nextDate, + &cs->nextDateFormat, size) < 0) + return ASN_PARSE_E; + if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER)) + return ASN_AFTER_DATE_E; + } + 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; + + WOLFSSL_ENTER("DecodeOcspRespExtensions"); + + 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, ocspType, 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"); + idx += (ASN_BOOL_SIZE + 1); + } + + /* process the extension based on the OID */ + if (source[idx++] != ASN_OCTET_STRING) { + WOLFSSL_MSG("\tfail: should be an OCTET STRING"); + return ASN_PARSE_E; + } + + if (GetLength(source, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: extension data length"); + return ASN_PARSE_E; + } + + if (oid == OCSP_NONCE_OID) { + /* get data inside extra OCTET_STRING */ + if (source[idx++] != ASN_OCTET_STRING) { + WOLFSSL_MSG("\tfail: should be an OCTET STRING"); + return ASN_PARSE_E; + } + + if (GetLength(source, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: extension data length"); + return ASN_PARSE_E; + } + + 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) < 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; +} + + +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; +} + +static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, + OcspResponse* resp, word32 size, void* cm) +{ + int length; + word32 idx = *ioIndex; + word32 end_index; + int ret = -1; + + WOLFSSL_ENTER("DecodeBasicOcspResponse"); + + 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, sigType, size) < 0) + return ASN_PARSE_E; + + /* Obtain pointer to the start of the signature, and save the size */ + if (source[idx++] == ASN_BIT_STRING) + { + int sigLength = 0; + if (GetLength(source, &idx, &sigLength, size) < 0) + return ASN_PARSE_E; + 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. + */ + if (idx < end_index) + { + DecodedCert cert; + + if (DecodeCerts(source, &idx, resp, size) < 0) + return ASN_PARSE_E; + + InitDecodedCert(&cert, resp->cert, resp->certSz, 0); + ret = ParseCertRelative(&cert, CERT_TYPE, VERIFY, cm); + if (ret < 0) + return ret; + + ret = ConfirmSignature(resp->response, resp->responseSz, + cert.publicKey, cert.pubKeySize, cert.keyOID, + resp->sig, resp->sigSz, resp->sigOID, NULL); + FreeDecodedCert(&cert); + + if (ret == 0) + { + WOLFSSL_MSG("\tOCSP Confirm signature failed"); + return ASN_OCSP_CONFIRM_E; + } + } + else { + Signer* ca = GetCA(cm, resp->issuerHash); + + if (!ca || !ConfirmSignature(resp->response, resp->responseSz, + ca->publicKey, ca->pubKeySize, ca->keyOID, + resp->sig, resp->sigSz, resp->sigOID, NULL)) { + WOLFSSL_MSG("\tOCSP Confirm signature failed"); + return ASN_OCSP_CONFIRM_E; + } + } + + *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) +{ + 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, ocspType, size) < 0) + return ASN_PARSE_E; + if (oid != OCSP_BASIC_OID) + return ASN_PARSE_E; + if (source[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + + if (DecodeBasicOcspResponse(source, &idx, resp, size, cm) < 0) + return ASN_PARSE_E; + + 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[6][MAX_SEQ_SZ]; + word32 seqSz[6], 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]); + seqArray[2][0] = ASN_OBJECT_ID; + totalSz += seqSz[2] = 1 + SetLength(sizeof(NonceObjId), &seqArray[2][1]); + totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]); + totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]); + totalSz += seqSz[5] = SetExplicit(2, totalSz, seqArray[5]); + + if (totalSz > size) + return 0; + + totalSz = 0; + + XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); + totalSz += seqSz[5]; + + 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, snSz, extSz, totalSz; + int i; + + WOLFSSL_ENTER("EncodeOcspRequest"); + +#ifdef NO_SHA + algoSz = SetAlgoID(SHA256h, algoArray, hashType, 0); +#else + algoSz = SetAlgoID(SHAh, algoArray, hashType, 0); +#endif + + issuerSz = SetDigest(req->issuerHash, KEYID_SIZE, issuerArray); + issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE, issuerKeyArray); + snSz = SetSerialNumber(req->serial, req->serialSz, snArray); + extSz = 0; + + if (req->nonceSz) + extSz = EncodeOcspRequestExtensions(req, extArray, OCSP_NONCE_EXT_SZ); + + 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 (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) +{ + WOLFSSL_ENTER("InitOcspRequest"); + + if (req == NULL) + return BAD_FUNC_ARG; + + ForceZero(req, sizeof(OcspRequest)); + + if (cert) { + XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE); + XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE); + + req->serial = (byte*)XMALLOC(cert->serialSz, NULL, + 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, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + if (req->url == NULL) { + XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP); + return MEMORY_E; + } + + XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz); + req->urlSz = cert->extAuthInfoSz; + } + + } + + if (useNonce) { + WC_RNG rng; + + if (wc_InitRng(&rng) != 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, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + + if (req->url) + XFREE(req->url, NULL, 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 (req->nonceSz && 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 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) +{ + WOLFSSL_MSG("InitDecodedCRL"); + + dcrl->certBegin = 0; + dcrl->sigIndex = 0; + dcrl->sigLength = 0; + dcrl->signatureOID = 0; + dcrl->certs = NULL; + dcrl->totalCerts = 0; +} + + +/* free decoded CRL resources */ +void FreeDecodedCRL(DecodedCRL* dcrl) +{ + RevokedCert* tmp = dcrl->certs; + + WOLFSSL_MSG("FreeDecodedCRL"); + + while(tmp) { + RevokedCert* next = tmp->next; + XFREE(tmp, NULL, 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 len; + word32 end; + byte b; + RevokedCert* rc; + + WOLFSSL_ENTER("GetRevoked"); + + if (GetSequence(buff, idx, &len, maxIdx) < 0) + return ASN_PARSE_E; + + end = *idx + len; + + /* get serial number */ + b = buff[*idx]; + *idx += 1; + + if (b != ASN_INTEGER) { + WOLFSSL_MSG("Expecting Integer"); + return ASN_PARSE_E; + } + + if (GetLength(buff, idx, &len, maxIdx) < 0) + return ASN_PARSE_E; + + if (len > EXTERNAL_SERIAL_SIZE) { + WOLFSSL_MSG("Serial Size too big"); + return ASN_PARSE_E; + } + + rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), NULL, DYNAMIC_TYPE_CRL); + if (rc == NULL) { + WOLFSSL_MSG("Alloc Revoked Cert failed"); + return MEMORY_E; + } + + XMEMCPY(rc->serialNumber, &buff[*idx], len); + rc->serialSz = len; + + /* add to list */ + rc->next = dcrl->certs; + dcrl->certs = rc; + dcrl->totalCerts++; + + *idx += len; + + /* get date */ + b = buff[*idx]; + *idx += 1; + + if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) { + WOLFSSL_MSG("Expecting Date"); + return ASN_PARSE_E; + } + + if (GetLength(buff, idx, &len, maxIdx) < 0) + return ASN_PARSE_E; + + /* skip for now */ + *idx += len; + + 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; + byte b; + + WOLFSSL_ENTER("GetCRL_Signature"); + + b = source[*idx]; + *idx += 1; + if (b != ASN_BIT_STRING) + return ASN_BITSTR_E; + + if (GetLength(source, idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + dcrl->sigLength = length; + + b = source[*idx]; + *idx += 1; + if (b != 0x00) + return ASN_EXPECT_0_E; + + dcrl->sigLength--; + dcrl->signature = (byte*)&source[*idx]; + + *idx += dcrl->sigLength; + + 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; + + WOLFSSL_MSG("ParseCRL"); + + /* raw crl hash */ + /* hash here if needed for optimized comparisons + * 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) < 0) + return ASN_PARSE_E; + } + + if (GetAlgoId(buff, &idx, &oid, ignoreType, 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 && !XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, + AFTER)) { + WOLFSSL_MSG("CRL after date is no longer valid"); + return ASN_AFTER_DATE_E; + } + + 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, sigType, 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 /* NO_SKID */ + ca = GetCA(cm, dcrl->issuerHash); + #endif /* NO_SKID */ + WOLFSSL_MSG("About to verify CRL signature"); + + if (ca) { + WOLFSSL_MSG("Found CRL issuer CA"); + /* 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 */ + if (!ConfirmSignature(buff + dcrl->certBegin, + dcrl->sigIndex - dcrl->certBegin, + ca->publicKey, ca->pubKeySize, ca->keyOID, + dcrl->signature, dcrl->sigLength, dcrl->signatureOID, NULL)) { + WOLFSSL_MSG("CRL Confirm signature failed"); + return ASN_CRL_CONFIRM_E; + } + } + else { + WOLFSSL_MSG("Did NOT find CRL issuer CA"); + return ASN_CRL_NO_SIGNER_E; + } + + return 0; +} + +#endif /* HAVE_CRL */ +#endif /* !NO_ASN */ + +#ifdef WOLFSSL_SEP + + + +#endif /* WOLFSSL_SEP */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/blake2b.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,436 @@ +/* + 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-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 INLINE int blake2b_set_lastnode( blake2b_state *S ) +{ + S->f[1] = ~0ULL; + return 0; +} + +/* Some helper functions, not necessarily useful */ +static INLINE int blake2b_set_lastblock( blake2b_state *S ) +{ + if( S->last_node ) blake2b_set_lastnode( S ); + + S->f[0] = ~0ULL; + return 0; +} + +static 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 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; + + 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 ) ); + 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; + + 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 ) ); + + 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 != memcmp( 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) +{ + 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/camellia.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1622 @@ +/* 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-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #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; +} + + +void wc_CamelliaEncryptDirect(Camellia* cam, byte* out, const byte* in) +{ + Camellia_EncryptBlock(cam->keySz, in, cam->key, out); +} + + +void wc_CamelliaDecryptDirect(Camellia* cam, byte* out, const byte* in) +{ + Camellia_DecryptBlock(cam->keySz, in, cam->key, out); +} + + +void wc_CamelliaCbcEncrypt(Camellia* cam, byte* out, const byte* in, word32 sz) +{ + word32 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; + } +} + + +void wc_CamelliaCbcDecrypt(Camellia* cam, byte* out, const byte* in, word32 sz) +{ + word32 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; + } +} + + +#endif /* HAVE_CAMELLIA */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/chacha.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,253 @@ +/* chacha.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + +#ifdef CHACHA_AEAD_TEST + #include <stdio.h> +#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); + + +/** + * 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[3]; /* used for alignment of memory */ + +#ifdef CHACHA_AEAD_TEST + word32 i; + printf("NONCE : "); + for (i = 0; i < 12; i++) { + printf("%02x", inIv[i]); + } + printf("\n\n"); +#endif + + if (ctx == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(temp, inIv, 12); + + ctx->X[12] = counter; /* block counter */ + ctx->X[13] = LITTLE32(temp[0]); /* fixed variable from nonce */ + ctx->X[14] = LITTLE32(temp[1]); /* counter from nonce */ + ctx->X[15] = 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 != 16 && keySz != 32) + 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 == 32) { + 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 INLINE void wc_Chacha_wordtobyte(word32 output[16], const word32 input[16]) +{ + word32 x[16]; + word32 i; + + for (i = 0; i < 16; 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 < 16; i++) { + x[i] = PLUS(x[i], input[i]); + } + + for (i = 0; i < 16; i++) { + output[i] = LITTLE32(x[i]); + } +} + +/** + * Encrypt a stream of bytes + */ +static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, + word32 bytes) +{ + byte* output; + word32 temp[16]; /* used to make sure aligned */ + word32 i; + + output = (byte*)temp; + + if (!bytes) return; + for (;;) { + wc_Chacha_wordtobyte(temp, ctx->X); + ctx->X[12] = PLUSONE(ctx->X[12]); + if (bytes <= 64) { + for (i = 0; i < bytes; ++i) { + c[i] = m[i] ^ output[i]; + } + return; + } + for (i = 0; i < 64; ++i) { + c[i] = m[i] ^ output[i]; + } + bytes -= 64; + c += 64; + m += 64; + } +} + +/** + * 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; + + wc_Chacha_encrypt_bytes(ctx, input, output, msglen); + + return 0; +} + +#endif /* HAVE_CHACHA*/ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/chacha20_poly1305.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,276 @@ +/* chacha.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 +#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[8]; + + 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); + + err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); + if (err) + { + return err; + } + + /* -- Ciphertext length as a 64-bit little endian integer */ + + word32ToLittle64(inCiphertextLen, little64); + + 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]) +{ + XMEMSET(outLittle64, 0, 8); + + outLittle64[0] = (byte)(inLittle32 & 0x000000FF); + outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8); + outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16); + outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24); +} + + +#endif /* HAVE_CHACHA && HAVE_POLY1305 */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/coding.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,453 @@ +/* coding.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 /* defined(WOLFSSL_BASE64_ENCODE) */ + + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) + +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 (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 (*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 /* (OPENSSL_EXTRA) || (HAVE_WEBSERVER) || (HAVE_FIPS) */ + +#endif /* NO_CODING */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/compress.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,171 @@ +/* compress.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/curve25519.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,410 @@ +/* curve25519.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #include <wolfcrypt/src/misc.c> +#endif + +const curve25519_set_type curve25519_sets[] = { + { + 32, + "CURVE25519", + } +}; + + +int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key) +{ + unsigned char basepoint[CURVE25519_KEYSIZE] = {9}; + 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; + + /* 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 */ + ret = curve25519(key->p.point, key->k.point, basepoint); + 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) +{ + unsigned char o[CURVE25519_KEYSIZE]; + 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; + + ret = curve25519(o, private_key->k.point, public_key->p.point); + if (ret != 0) { + ForceZero(o, CURVE25519_KEYSIZE); + return ret; + } + + if (endian == EC25519_BIG_ENDIAN) { + int i; + /* put shared secret key in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + out[i] = o[CURVE25519_KEYSIZE - i -1]; + } + else /* put shared secret key in Little Endian format */ + XMEMCPY(out, o, CURVE25519_KEYSIZE); + + *outlen = CURVE25519_KEYSIZE; + + ForceZero(o, sizeof(o)); + + 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) +{ + word32 keySz; + + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + /* check size of outgoing key */ + keySz = wc_curve25519_size(key); + + /* check and set outgoing key size */ + if (*outLen < keySz) { + *outLen = keySz; + return ECC_BAD_ARG_E; + } + *outLen = keySz; + + 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, keySz); + + 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) +{ + word32 keySz; + + /* sanity check */ + if (key == NULL || in == NULL) + return BAD_FUNC_ARG; + + /* check size of incoming keys */ + keySz = wc_curve25519_size(key); + if (inLen != keySz) + 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]; + + 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) +{ + word32 keySz; + + /* sanity check */ + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + /* check size of outgoing buffer */ + keySz = wc_curve25519_size(key); + if (*outLen < keySz) { + *outLen = keySz; + return ECC_BAD_ARG_E; + } + *outLen = keySz; + + 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, keySz); + + 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 != wc_curve25519_size(key)) + 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, privSz); + + 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; + + /* currently the format for curve25519 */ + key->dp = &curve25519_sets[0]; + + XMEMSET(key->k.point, 0, key->dp->size); + XMEMSET(key->p.point, 0, key->dp->size); + + 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)); +} + + +/* get key size */ +int wc_curve25519_size(curve25519_key* key) +{ + if (key == NULL) + return 0; + + return key->dp->size; +} + +#endif /*HAVE_CURVE25519*/ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/des3.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1630 @@ +/* des3.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_DES3 + +#include <wolfssl/wolfcrypt/des3.h> + +#ifdef HAVE_FIPS +#ifdef HAVE_CAVIUM + static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv); + static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, + word32 length); + static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, + word32 length); +#endif + +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) +{ + 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) +{ + return Des3_CbcEncrypt_fips(des, out, in, sz); +} + + +int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) +{ + 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); +} + +#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); +} + + +#ifdef HAVE_CAVIUM + +/* Initialize Des3 for use with Nitrox device */ +int wc_Des3_InitCavium(Des3* des3, int devId) +{ + return Des3_InitCavium(des3, devId); +} + + +/* Free Des3 from use with Nitrox device */ +void wc_Des3_FreeCavium(Des3* des3) +{ + Des3_FreeCavium(des3); +} + + +#endif /* HAVE_CAVIUM */ +#else /* build without fips */ + +#if defined(WOLFSSL_TI_CRYPT) + #include <wolfcrypt/src/port/ti/ti-des3.c> +#else + +#include <wolfssl/wolfcrypt/error-crypt.h> +#include <wolfssl/wolfcrypt/logging.h> + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + + +#ifdef HAVE_CAVIUM + static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv); + static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, + word32 length); + static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, + word32 length); +#endif + + + + +#ifdef STM32F2_CRYPTO + /* + * STM32F2 hardware DES/3DES support through the STM32F2 standard + * peripheral library. Documentation located in STM32F2xx Standard + * Peripheral Library document (See note in README). + */ + #include "stm32f2xx.h" + #include "stm32f2xx_cryp.h" + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + word32 *dkey = des->key; + + XMEMCPY(dkey, key, 8); + ByteReverseWords(dkey, dkey, 8); + + wc_Des_SetIV(des, iv); + + return 0; + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + word32 *dkey1 = des->key[0]; + word32 *dkey2 = des->key[1]; + word32 *dkey3 = 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 */ + + ByteReverseWords(dkey1, dkey1, 8); + ByteReverseWords(dkey2, dkey2, 8); + ByteReverseWords(dkey3, dkey3, 8); + + return wc_Des3_SetIV(des, iv); + } + + void DesCrypt(Des* des, byte* out, const byte* in, word32 sz, + int dir, int mode) + { + 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); + } + + 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; + } + + void Des3Crypt(Des3* des, byte* out, const byte* in, word32 sz, + int dir) + { + 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); + + } + + 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 ; + + 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 ; + + } + 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_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). + */ + #include "cau_api.h" + + 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; + + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_des_encrypt alignment"); + return BAD_ALIGN_E; + } + + 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; + } + cau_des_encrypt(temp_block, (byte*)des->key, out + offset); + 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; + + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_des_decrypt alignment"); + return BAD_ALIGN_E; + } + + while (len > 0) + { + XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); + + ret = wolfSSL_CryptHwMutexLock(); + if(ret != 0) { + return ret; + } + cau_des_decrypt(in + offset, (byte*)des->key, out + offset); + 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; + + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad 3ede cau_des_encrypt alignment"); + return BAD_ALIGN_E; + } + + 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; + } + 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); + 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; + + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad 3ede cau_des_decrypt alignment"); + return BAD_ALIGN_E; + } + + while (len > 0) + { + XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); + + ret = wolfSSL_CryptHwMutexLock(); + if(ret != 0) { + return ret; + } + 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); + 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) + + #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" + +void wc_Des_SetIV(Des* des, const byte* iv); +int wc_Des3_SetIV(Des3* des, const byte* iv); + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + word32 *dkey = des->key ; + word32 *dreg = des->reg ; + + XMEMCPY((byte *)dkey, (byte *)key, 8); + ByteReverseWords(dkey, dkey, 8); + XMEMCPY((byte *)dreg, (byte *)iv, 8); + ByteReverseWords(dreg, dreg, 8); + + return 0; + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + word32 *dkey1 = des->key[0]; + word32 *dreg = des->reg ; + + XMEMCPY(dkey1, key, 24); + ByteReverseWords(dkey1, dkey1, 24); + XMEMCPY(dreg, iv, 8); + ByteReverseWords(dreg, dreg, 8) ; + + return 0; + } + + void DesCrypt(word32 *key, word32 *iv, byte* out, const byte* in, word32 sz, + int dir, int algo, int cryptoalgo) + { + securityAssociation *sa_p ; + bufferDescriptor *bd_p ; + const byte *in_p, *in_l ; + byte *out_p, *out_l ; + volatile securityAssociation sa __attribute__((aligned (8))); + volatile bufferDescriptor bd __attribute__((aligned (8))); + volatile int k ; + + /* get uncached address */ + + in_l = in; + out_l = out ; + sa_p = KVA0_TO_KVA1(&sa) ; + bd_p = KVA0_TO_KVA1(&bd) ; + in_p = KVA0_TO_KVA1(in_l) ; + out_p= KVA0_TO_KVA1(out_l); + + if(PIC32MZ_IF_RAM(in_p)) + XMEMCPY((void *)in_p, (void *)in, sz); + XMEMSET((void *)out_p, 0, sz); + + /* Set up the Security Association */ + XMEMSET((byte *)KVA0_TO_KVA1(&sa), 0, sizeof(sa)); + sa_p->SA_CTRL.ALGO = algo ; + sa_p->SA_CTRL.LNC = 1; + sa_p->SA_CTRL.LOADIV = 1; + sa_p->SA_CTRL.FB = 1; + sa_p->SA_CTRL.ENCTYPE = dir ; /* Encryption/Decryption */ + sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; + sa_p->SA_CTRL.KEYSIZE = 1 ; /* KEY is 192 bits */ + XMEMCPY((byte *)KVA0_TO_KVA1(&sa.SA_ENCKEY[algo==PIC32_ALGO_TDES ? 2 : 6]), + (byte *)key, algo==PIC32_ALGO_TDES ? 24 : 8); + XMEMCPY((byte *)KVA0_TO_KVA1(&sa.SA_ENCIV[2]), (byte *)iv, 8); + + XMEMSET((byte *)KVA0_TO_KVA1(&bd), 0, sizeof(bd)); + /* Set up the Buffer Descriptor */ + bd_p->BD_CTRL.BUFLEN = sz; + bd_p->BD_CTRL.LIFM = 1; + bd_p->BD_CTRL.SA_FETCH_EN = 1; + bd_p->BD_CTRL.LAST_BD = 1; + bd_p->BD_CTRL.DESC_EN = 1; + + bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa) ; /* (unsigned int)sa_p; */ + bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in) ; /* (unsigned int)in_p; */ + bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); /* (unsigned int)out_p; */ + bd_p->NXTPTR = (unsigned int)KVA_TO_PA(&bd); + bd_p->MSGLEN = sz ; + + /* Fire in the hole! */ + CECON = 1 << 6; + while (CECON); + + /* Run the engine */ + CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; /* (unsigned int)bd_p ; */ + CEINTEN = 0x07; + CECON = 0x27; + + WAIT_ENGINE ; + + if((cryptoalgo == PIC32_CRYPTOALGO_CBC) || + (cryptoalgo == PIC32_CRYPTOALGO_TCBC)|| + (cryptoalgo == PIC32_CRYPTOALGO_RCBC)) { + /* set iv for the next call */ + if(dir == PIC32_ENCRYPTION) { + XMEMCPY((void *)iv, (void*)&(out_p[sz-DES_IVLEN]), DES_IVLEN) ; + } else { + ByteReverseWords((word32*)iv, (word32 *)&(in_p[sz-DES_IVLEN]), + DES_IVLEN); + } + + } + + ByteReverseWords((word32*)out, (word32 *)KVA0_TO_KVA1(out), sz); + } + + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des->key, des->reg, out, in, sz, + PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC ); + return 0; + } + + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des->key, des->reg, out, in, sz, + PIC32_DECRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC); + return 0; + } + + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des->key[0], des->reg, out, in, sz, + PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); + return 0; + } + + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des->key[0], des->reg, out, in, sz, + PIC32_DECRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); + return 0; + } + +#else /* CTaoCrypt software implementation */ + +/* 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 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 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) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* buffer = (byte*)XMALLOC(56+56+8, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (buffer == NULL) + return MEMORY_E; +#else + byte buffer[56+56+8]; +#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; +} + + +static INLINE int Reverse(int dir) +{ + return !dir; +} + + +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; + +#ifdef HAVE_CAVIUM + if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) + return wc_Des3_CaviumSetKey(des, key, iv); +#endif + + ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); + if (ret != 0) + return ret; + + ret = DesSetKey(key + 8, Reverse(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; + +#ifdef HAVE_CAVIUM + if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) + return wc_Des3_CaviumCbcEncrypt(des, out, in, sz); +#endif + + 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; + +#ifdef HAVE_CAVIUM + if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) + return wc_Des3_CaviumCbcDecrypt(des, out, in, sz); +#endif + + 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; + + while (blocks--) { + DesProcessBlock(des, in, out); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; +} + +#endif /* WOLFSSL_DES_ECB */ + +#endif /* STM32F2_CRYPTO */ + +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 && iv) + XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); + else if (des) + XMEMSET(des->reg, 0, DES_BLOCK_SIZE); + + return 0; +} + + +#ifdef HAVE_CAVIUM + +#include "cavium_common.h" + +/* Initialize Des3 for use with Nitrox device */ +int wc_Des3_InitCavium(Des3* des3, int devId) +{ + if (des3 == NULL) + return -1; + + if (CspAllocContext(CONTEXT_SSL, &des3->contextHandle, devId) != 0) + return -1; + + des3->devId = devId; + des3->magic = WOLFSSL_3DES_CAVIUM_MAGIC; + + return 0; +} + + +/* Free Des3 from use with Nitrox device */ +void wc_Des3_FreeCavium(Des3* des3) +{ + if (des3 == NULL) + return; + + if (des3->magic != WOLFSSL_3DES_CAVIUM_MAGIC) + return; + + CspFreeContext(CONTEXT_SSL, des3->contextHandle, des3->devId); + des3->magic = 0; +} + + +static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv) +{ + if (des3 == NULL) + return -1; + + /* key[0] holds key, iv in reg */ + XMEMCPY(des3->key[0], key, DES_BLOCK_SIZE*3); + + return wc_Des3_SetIV(des3, iv); +} + + +static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, + word32 length) +{ + wolfssl_word offset = 0; + word32 requestId; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + if (CspEncrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, + CAVIUM_NO_UPDATE, slen, (byte*)in + offset, + out + offset, (byte*)des3->reg, (byte*)des3->key[0], + &requestId, des3->devId) != 0) { + WOLFSSL_MSG("Bad Cavium 3DES Cbc Encrypt"); + return -1; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + XMEMCPY(des3->reg, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + } + if (length) { + word16 slen = (word16)length; + + if (CspEncrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, + CAVIUM_NO_UPDATE, slen, (byte*)in + offset, + out + offset, (byte*)des3->reg, (byte*)des3->key[0], + &requestId, des3->devId) != 0) { + WOLFSSL_MSG("Bad Cavium 3DES Cbc Encrypt"); + return -1; + } + XMEMCPY(des3->reg, out+offset+length - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + } + return 0; +} + +static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, + word32 length) +{ + word32 requestId; + wolfssl_word offset = 0; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + if (CspDecrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, + CAVIUM_NO_UPDATE, slen, (byte*)in+offset, out+offset, + (byte*)des3->reg, (byte*)des3->key[0], &requestId, + des3->devId) != 0) { + WOLFSSL_MSG("Bad Cavium 3Des Decrypt"); + return -1; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); + } + if (length) { + word16 slen = (word16)length; + XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE,DES_BLOCK_SIZE); + if (CspDecrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, + CAVIUM_NO_UPDATE, slen, (byte*)in+offset, out+offset, + (byte*)des3->reg, (byte*)des3->key[0], &requestId, + des3->devId) != 0) { + WOLFSSL_MSG("Bad Cavium 3Des Decrypt"); + return -1; + } + XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); + } + return 0; +} + +#endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_TI_CRYPT */ +#endif /* HAVE_FIPS */ +#endif /* NO_DES3 */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/dh.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,260 @@ +/* dh.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + +#include <wolfssl/wolfcrypt/dh.h> +#include <wolfssl/wolfcrypt/error-crypt.h> + +#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 + + +#if !defined(WOLFSSL_HAVE_MIN) && !defined(WOLFSSL_DH_CONST) +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +void wc_InitDhKey(DhKey* key) +{ + (void)key; +/* TomsFastMath doesn't use memory allocation */ +#ifndef USE_FAST_MATH + key->p.dp = 0; + key->g.dp = 0; +#endif +} + + +void wc_FreeDhKey(DhKey* key) +{ + (void)key; +/* TomsFastMath doesn't use memory allocation */ +#ifndef USE_FAST_MATH + mp_clear(&key->p); + mp_clear(&key->g); +#endif +} + + +/* 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 + + +static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) +{ + int ret; + word32 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) + return ret; + + priv[0] |= 0x0C; + + *privSz = sz; + + return 0; +} + + +static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, + byte* pub, word32* pubSz) +{ + int ret = 0; + + mp_int x; + mp_int y; + + 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); + + return ret; +} + + +int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz, + byte* pub, word32* pubSz) +{ + int ret = GeneratePrivate(key, rng, priv, privSz); + + return (ret != 0) ? ret : GeneratePublic(key, priv, *privSz, pub, pubSz); +} + +int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, + word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; + + mp_int x; + mp_int y; + mp_int z; + + 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; + + 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_clear(&x); + + 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) +{ + if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) + return BAD_FUNC_ARG; + + /* may have leading 0 */ + if (p[0] == 0) { + pSz--; p++; + } + + if (g[0] == 0) { + gSz--; g++; + } + + if (mp_init(&key->p) != MP_OKAY) + return MP_INIT_E; + if (mp_read_unsigned_bin(&key->p, p, pSz) != 0) { + mp_clear(&key->p); + return ASN_DH_KEY_E; + } + + if (mp_init(&key->g) != MP_OKAY) { + mp_clear(&key->p); + return MP_INIT_E; + } + if (mp_read_unsigned_bin(&key->g, g, gSz) != 0) { + mp_clear(&key->g); + mp_clear(&key->p); + return ASN_DH_KEY_E; + } + + return 0; +} + + +#endif /* NO_DH */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/dsa.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,493 @@ +/* dsa.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + + +enum { + DSA_HALF_SIZE = 20, /* r and s size */ + DSA_SIG_SIZE = 40 /* signature size */ +}; + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +void wc_InitDsaKey(DsaKey* key) +{ + key->type = -1; /* haven't decided yet */ + +/* TomsFastMath doesn't use memory allocation */ +#ifndef USE_FAST_MATH + key->p.dp = 0; /* public alloc parts */ + key->q.dp = 0; + key->g.dp = 0; + key->y.dp = 0; + + key->x.dp = 0; /* private alloc parts */ +#endif +} + + +void wc_FreeDsaKey(DsaKey* key) +{ + (void)key; +/* TomsFastMath doesn't use memory allocation */ +#ifndef USE_FAST_MATH + if (key->type == DSA_PRIVATE) + mp_clear(&key->x); + mp_clear(&key->y); + mp_clear(&key->g); + mp_clear(&key->q); + mp_clear(&key->p); +#endif +} + +#ifdef WOLFSSL_KEY_GEN + +int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa) +{ + unsigned char *buf; + int qsize, err; + + if (rng == NULL || dsa == NULL) + return BAD_FUNC_ARG; + + qsize = mp_unsigned_bin_size(&dsa->q); + if (qsize == 0) + return BAD_FUNC_ARG; + + /* allocate ram */ + buf = (unsigned char *)XMALLOC(qsize, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) + return MEMORY_E; + + if (mp_init(&dsa->x) != MP_OKAY) { + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MP_INIT_E; + } + + do { + /* make a random exponent mod q */ + err = wc_RNG_GenerateBlock(rng, buf, qsize); + if (err != MP_OKAY) { + mp_clear(&dsa->x); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + + err = mp_read_unsigned_bin(&dsa->x, buf, qsize); + if (err != MP_OKAY) { + mp_clear(&dsa->x); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + } while (mp_cmp_d(&dsa->x, 1) != MP_GT); + + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (mp_init(&dsa->y) != MP_OKAY) { + mp_clear(&dsa->x); + return MP_INIT_E; + } + + /* public key : y = g^x mod p */ + err = mp_exptmod(&dsa->g, &dsa->x, &dsa->p, &dsa->y); + if (err != MP_OKAY) { + mp_clear(&dsa->x); + mp_clear(&dsa->y); + return err; + } + + dsa->type = DSA_PRIVATE; + + return MP_OKAY; +} + +/* 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 / 8; + + /* allocate ram */ + buf = (unsigned char *)XMALLOC(msize - qsize, + NULL, 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, NULL, 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, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + XFREE(buf, NULL, 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 */ + mp_set(&dsa->g, 1); + + 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 */ + + +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]; + + sz = min(sizeof(buffer), mp_unsigned_bin_size(&key->q)); + + /* generate k */ + ret = wc_RNG_GenerateBlock(rng, buffer, sz); + if (ret != 0) + return ret; + + buffer[0] |= 0x0C; + + if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) + return MP_INIT_E; + + if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY) + ret = MP_READ_E; + + 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,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; + + /* write out */ + if (ret == 0) { + int rSz = mp_unsigned_bin_size(&r); + int sSz = mp_unsigned_bin_size(&s); + + if (rSz == DSA_HALF_SIZE - 1) { + out[0] = 0; + out++; + } + + if (mp_to_unsigned_bin(&r, out) != MP_OKAY) + ret = MP_TO_E; + else { + if (sSz == DSA_HALF_SIZE - 1) { + out[rSz] = 0; + out++; + } + ret = mp_to_unsigned_bin(&s, out + rSz); + } + } + + 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 (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,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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/ecc_fp.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,2 @@ +/* dummy ecc_fp.c for dist */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/ed25519.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,484 @@ +/* ed25519.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #include <wolfcrypt/src/misc.c> +#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; + ge_p3 A; + + 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; + + ge_scalarmult_base(&A, az); + ge_p3_tobytes(key->p, &A); + + /* put public key after private key, on the same buffer */ + XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); + + 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) +{ + ge_p3 R; + byte nonce[SHA512_DIGEST_SIZE]; + byte hram[SHA512_DIGEST_SIZE]; + byte az[ED25519_PRV_KEY_SIZE]; + Sha512 sha; + int ret; + + /* sanity check on arguments */ + if (in == NULL || out == NULL || outLen == NULL || key == NULL) + 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) + return ret; + ret = wc_Sha512Update(&sha, in, inlen); + if (ret != 0) + return ret; + ret = wc_Sha512Final(&sha, nonce); + if (ret != 0) + return ret; + + 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); + + /* 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) + return ret; + ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); + if (ret != 0) + return ret; + ret = wc_Sha512Update(&sha, in, inlen); + if (ret != 0) + return ret; + ret = wc_Sha512Final(&sha, hram); + if (ret != 0) + return ret; + + sc_reduce(hram); + sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); + + 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 + stat will be 1 on successful verify and 0 on unsuccessful + return 0 and stat of 1 on success +*/ +int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, + word32 msglen, int* stat, ed25519_key* key) +{ + byte rcheck[ED25519_KEY_SIZE]; + byte h[SHA512_DIGEST_SIZE]; + ge_p3 A; + ge_p2 R; + int ret; + Sha512 sha; + + /* sanity check on arguments */ + if (sig == NULL || msg == NULL || stat == NULL || key == NULL) + return BAD_FUNC_ARG; + + /* set verification failed by default */ + *stat = 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 */ + if (ge_frombytes_negate_vartime(&A, key->p) != 0) + return BAD_FUNC_ARG; + + /* 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) + return ret; + ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); + if (ret != 0) + return ret; + ret = wc_Sha512Update(&sha, msg, msglen); + if (ret != 0) + return ret; + ret = wc_Sha512Final(&sha, h); + if (ret != 0) + return ret; + + 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); + + /* 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 */ + *stat = 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)); + + 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); + return 0; + } + + /* importing uncompressed public key */ + if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) { + /* 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); + 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); + return 0; + } + + /* bad public key format */ + return BAD_FUNC_ARG; +} + + +/* + 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 */ + + +/* 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/error.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,390 @@ +/* error.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + +const char* wc_GetErrorString(int error) +{ +#ifdef NO_ERROR_STRINGS + + (void)error; + return "no support for error strings built in"; + +#else + + 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 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 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"; + + 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 CAVIUM_INIT_E: + return "Cavium Init type 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 BAD_ENC_STATE_E: + return "Bad ecc encrypt 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_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 "Bad 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"; + + default: + return "unknown error number"; + + } + +#endif /* NO_ERROR_STRINGS */ + +} + +void wc_ErrorString(int error, char* buffer) +{ + XSTRNCPY(buffer, wc_GetErrorString(error), WOLFSSL_MAX_ERROR_SZ); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/fe_low_mem.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,599 @@ +/* fe_low_mem.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 word. */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <wolfssl/wolfcrypt/settings.h> + +#if defined(CURVED25519_SMALL) /* use slower code that takes less memory */ +#if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) + +#include <wolfssl/wolfcrypt/fe_operations.h> + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #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 fe_copy(fe x, const fe a) +{ + int i; + for (i = 0; i < F25519_SIZE; i++) + x[i] = a[i]; +} + + +/* 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); + + fe_sub(a, x1sq, z1sq); + fe_mul__distinct(x3, a, a); + + fe_mul_c(a, x1z1, 486662); + fe_add(a, x1sq, a); + fe_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]; + + fe_add(a, x2, z2); + fe_sub(b, x3, z3); /* D */ + fe_mul__distinct(da, a, b); + + fe_sub(b, x2, z2); + fe_add(a, x3, z3); /* C */ + fe_mul__distinct(cb, a, b); + + fe_add(a, da, cb); + fe_mul__distinct(b, a, a); + fe_mul__distinct(x5, z1, b); + + fe_sub(a, da, cb); + fe_mul__distinct(b, a, a); + fe_mul__distinct(z5, x1, b); +} + + +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 */ + fe_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; +} + + +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] = 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] = c; + c = (c >> 8) & 1; + } + + fprime_select(x, minusp, x, 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] = 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] = 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] = c; + c >>= 8; + } + + c += ((word16)x[i]) - 128; + minusp[31] = 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 fe_add(fe r, const fe a, const fe 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] = 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] = c; + c >>= 8; + } +} + + +void fe_sub(fe r, const fe a, const fe 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 fe_neg(fe r, const fe 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 fe_mul(fe r, const fe a, const fe b) +{ + byte tmp[F25519_SIZE]; + + fe_mul__distinct(tmp, a, b); + fe_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 fe_invert(fe r, const fe x) +{ + byte tmp[F25519_SIZE]; + + fe_inv__distinct(tmp, x); + fe_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); + fe_sub(i, i, y); + + /* r = avi */ + fe_mul__distinct(x, v, a); + fe_mul__distinct(r, x, i); +} + +#endif /* HAVE_CURVE25519 or HAVE_ED25519 */ +#endif /* CURVED25519_SMALL */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/fe_operations.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1412 @@ +/* fe_operations.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + +#ifndef CURVED25519_SMALL /* run when not defined to use small memory math */ +#if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) + +#include <wolfssl/wolfcrypt/fe_operations.h> +#include <stdint.h> + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#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. +*/ + +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; +} + + +/* +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; +} + + +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; +} + + +/* +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] = h0 >> 0; + s[1] = h0 >> 8; + s[2] = h0 >> 16; + s[3] = (h0 >> 24) | (h1 << 2); + s[4] = h1 >> 6; + s[5] = h1 >> 14; + s[6] = (h1 >> 22) | (h2 << 3); + s[7] = h2 >> 5; + s[8] = h2 >> 13; + s[9] = (h2 >> 21) | (h3 << 5); + s[10] = h3 >> 3; + s[11] = h3 >> 11; + s[12] = (h3 >> 19) | (h4 << 6); + s[13] = h4 >> 2; + s[14] = h4 >> 10; + s[15] = h4 >> 18; + s[16] = h5 >> 0; + s[17] = h5 >> 8; + s[18] = h5 >> 16; + s[19] = (h5 >> 24) | (h6 << 1); + s[20] = h6 >> 7; + s[21] = h6 >> 15; + s[22] = (h6 >> 23) | (h7 << 3); + s[23] = h7 >> 5; + s[24] = h7 >> 13; + s[25] = (h7 >> 21) | (h8 << 4); + s[26] = h8 >> 4; + s[27] = h8 >> 12; + s[28] = (h8 >> 20) | (h9 << 6); + s[29] = h9 >> 2; + s[30] = h9 >> 10; + s[31] = 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; +} + + +/* +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; +} + + +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,unsigned 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,unsigned 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 /* HAVE ED25519 or CURVE25519 */ +#endif /* not defined CURVED25519_SMALL */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/ge_low_mem.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,564 @@ +/* ge_low_mem.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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(CURVED25519_SMALL) /* use slower code that takes less memory */ +#if defined(HAVE_ED25519) + +#include <wolfssl/wolfcrypt/ge_operations.h> +#include <wolfssl/wolfcrypt/error-crypt.h> +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #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; + + fe_copy(tmp, xIn); + parity = (tmp[0] & 1) << 7; + + fe_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) */ + fe_sub(c, p1->Y, p1->X); + fe_sub(d, p2->Y, p2->X); + fe_mul__distinct(a, c, d); + + /* B = (Y1+X1)(Y2+X2) */ + fe_add(c, p1->Y, p1->X); + fe_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); + fe_add(d, d, d); + + /* E = B - A */ + fe_sub(e, b, a); + + /* F = D - C */ + fe_sub(f, d, c); + + /* G = D + C */ + fe_add(g, d, c); + + /* H = B + A */ + fe_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); + fe_add(c, c, c); + + /* D = a A (alter sign) */ + /* E = (X1+Y1)^2-A-B */ + fe_add(f, p->X, p->Y); + fe_mul__distinct(e, f, f); + fe_sub(e, e, a); + fe_sub(e, e, b); + + /* G = D + B */ + fe_sub(g, b, a); + + /* F = G - C */ + fe_sub(f, g, c); + + /* H = D - B */ + fe_neg(h, b); + fe_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; + fe_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; + fe_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; + fe_copy(y, s); + y[31] &= 127; + + fe_mul__distinct(c, y, y); + fe_mul__distinct(b, c, ed25519_d); + fe_add(a, b, f25519_one); + fe_inv__distinct(b, a); + fe_sub(a, c, f25519_one); + fe_mul__distinct(c, a, b); + fe_sqrt(a, c); + fe_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 */ + fe_copy(p->X, x); + fe_copy(p->Y, y); + fe_load(p->Z, 1); + fe_mul__distinct(p->T, x, y); + + /* negate, the point becomes (-X,Y,Z,-T) */ + fe_neg(p->X,p->X); + fe_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); + + fe_copy(R->X, A.X); + fe_copy(R->Y, A.Y); + fe_copy(R->Z, A.Z); + + return ret; +} + +#endif /* HAVE_ED25519 */ +#endif /* CURVED25519_SMALL */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/ge_operations.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,2608 @@ +/* ge_operations.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + +#ifndef CURVED25519_SMALL /* run when not defined to use small memory math */ +#ifdef HAVE_ED25519 + +#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 + #include <wolfcrypt/src/misc.c> +#endif + +/* +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) +*/ + + +/* +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 s0 = 2097151 & load_3(s); + int64_t s1 = 2097151 & (load_4(s + 2) >> 5); + int64_t s2 = 2097151 & (load_3(s + 5) >> 2); + int64_t s3 = 2097151 & (load_4(s + 7) >> 7); + int64_t s4 = 2097151 & (load_4(s + 10) >> 4); + int64_t s5 = 2097151 & (load_3(s + 13) >> 1); + int64_t s6 = 2097151 & (load_4(s + 15) >> 6); + int64_t s7 = 2097151 & (load_3(s + 18) >> 3); + int64_t s8 = 2097151 & load_3(s + 21); + int64_t s9 = 2097151 & (load_4(s + 23) >> 5); + int64_t s10 = 2097151 & (load_3(s + 26) >> 2); + int64_t s11 = 2097151 & (load_4(s + 28) >> 7); + int64_t s12 = 2097151 & (load_4(s + 31) >> 4); + int64_t s13 = 2097151 & (load_3(s + 34) >> 1); + int64_t s14 = 2097151 & (load_4(s + 36) >> 6); + int64_t s15 = 2097151 & (load_3(s + 39) >> 3); + int64_t s16 = 2097151 & load_3(s + 42); + int64_t s17 = 2097151 & (load_4(s + 44) >> 5); + int64_t s18 = 2097151 & (load_3(s + 47) >> 2); + int64_t s19 = 2097151 & (load_4(s + 49) >> 7); + int64_t s20 = 2097151 & (load_4(s + 52) >> 4); + int64_t s21 = 2097151 & (load_3(s + 55) >> 1); + int64_t s22 = 2097151 & (load_4(s + 57) >> 6); + int64_t s23 = (load_4(s + 60) >> 3); + 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; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 << 5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 << 2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 << 7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 << 4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 << 1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 << 6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 << 3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 << 5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 << 2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 << 7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; + + /* hush warnings after setting values to 0 */ + (void)s12; + (void)s13; + (void)s14; + (void)s15; + (void)s16; + (void)s17; + (void)s18; + (void)s19; + (void)s20; + (void)s21; + (void)s22; + (void)s23; +} + + +/* +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) +{ + int64_t a0 = 2097151 & load_3(a); + int64_t a1 = 2097151 & (load_4(a + 2) >> 5); + int64_t a2 = 2097151 & (load_3(a + 5) >> 2); + int64_t a3 = 2097151 & (load_4(a + 7) >> 7); + int64_t a4 = 2097151 & (load_4(a + 10) >> 4); + int64_t a5 = 2097151 & (load_3(a + 13) >> 1); + int64_t a6 = 2097151 & (load_4(a + 15) >> 6); + int64_t a7 = 2097151 & (load_3(a + 18) >> 3); + int64_t a8 = 2097151 & load_3(a + 21); + int64_t a9 = 2097151 & (load_4(a + 23) >> 5); + int64_t a10 = 2097151 & (load_3(a + 26) >> 2); + int64_t a11 = (load_4(a + 28) >> 7); + int64_t b0 = 2097151 & load_3(b); + int64_t b1 = 2097151 & (load_4(b + 2) >> 5); + int64_t b2 = 2097151 & (load_3(b + 5) >> 2); + int64_t b3 = 2097151 & (load_4(b + 7) >> 7); + int64_t b4 = 2097151 & (load_4(b + 10) >> 4); + int64_t b5 = 2097151 & (load_3(b + 13) >> 1); + int64_t b6 = 2097151 & (load_4(b + 15) >> 6); + int64_t b7 = 2097151 & (load_3(b + 18) >> 3); + int64_t b8 = 2097151 & load_3(b + 21); + int64_t b9 = 2097151 & (load_4(b + 23) >> 5); + int64_t b10 = 2097151 & (load_3(b + 26) >> 2); + int64_t b11 = (load_4(b + 28) >> 7); + int64_t c0 = 2097151 & load_3(c); + int64_t c1 = 2097151 & (load_4(c + 2) >> 5); + int64_t c2 = 2097151 & (load_3(c + 5) >> 2); + int64_t c3 = 2097151 & (load_4(c + 7) >> 7); + int64_t c4 = 2097151 & (load_4(c + 10) >> 4); + int64_t c5 = 2097151 & (load_3(c + 13) >> 1); + int64_t c6 = 2097151 & (load_4(c + 15) >> 6); + int64_t c7 = 2097151 & (load_3(c + 18) >> 3); + int64_t c8 = 2097151 & load_3(c + 21); + int64_t c9 = 2097151 & (load_4(c + 23) >> 5); + int64_t c10 = 2097151 & (load_3(c + 26) >> 2); + int64_t c11 = (load_4(c + 28) >> 7); + int64_t s0; + int64_t s1; + int64_t s2; + int64_t s3; + int64_t s4; + int64_t s5; + int64_t s6; + int64_t s7; + int64_t s8; + int64_t s9; + int64_t s10; + int64_t s11; + int64_t s12; + int64_t s13; + int64_t s14; + int64_t s15; + int64_t s16; + int64_t s17; + int64_t s18; + int64_t s19; + int64_t s20; + int64_t s21; + int64_t s22; + int64_t s23; + 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; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + int64_t carry17; + int64_t carry18; + int64_t carry19; + int64_t carry20; + int64_t carry21; + int64_t carry22; + + s0 = c0 + a0*b0; + s1 = c1 + a0*b1 + a1*b0; + s2 = c2 + a0*b2 + a1*b1 + a2*b0; + s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0; + s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0; + s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0; + s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0; + s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0; + s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + + a8*b0; + s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + + a8*b1 + a9*b0; + s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + + a8*b2 + a9*b1 + a10*b0; + s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + + a8*b3 + a9*b2 + a10*b1 + a11*b0; + s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + + a10*b2 + a11*b1; + s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + + a11*b2; + s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + + a11*b3; + s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4; + s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5; + s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6; + s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7; + s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8; + s20 = a9*b11 + a10*b10 + a11*b9; + s21 = a10*b11 + a11*b10; + s22 = a11*b11; + s23 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21; + carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21; + carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21; + carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21; + carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21; + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 << 5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 << 2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 << 7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 << 4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 << 1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 << 6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 << 3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 << 5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 << 2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 << 7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; + + /* hush warnings after setting values to 0 */ + (void)s12; + (void)s13; + (void)s14; + (void)s15; + (void)s16; + (void)s17; + (void)s18; + (void)s19; + (void)s20; + (void)s21; + (void)s22; + (void)s23; +} + + +int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, word32 keySz) +{ + fe 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 +*/ +void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) +{ + fe 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); +} + + +/* 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 y; +} + + +static unsigned char negative(signed char b) +{ + unsigned long long x = b; /* 18446744073709551361..18446744073709551615: + yes; 0..255: no */ + x >>= 63; /* 1: yes; 0: no */ + return x; +} + + +static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b) +{ + fe_cmov(t->yplusx,u->yplusx,b); + fe_cmov(t->yminusx,u->yminusx,b); + fe_cmov(t->xy2d,u->xy2d,b); +} + + +/* base[i][j] = (j+1)*256^i*B */ +static 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 }, + }, +}, +} ; + + +static void ge_select(ge_precomp *t,int pos,signed char b) +{ + ge_precomp minust; + unsigned char bnegative = negative(b); + unsigned char babs = b - (((-bnegative) & b) << 1); + + ge_precomp_0(t); + cmov(t,&base[pos][0],equal(babs,1)); + cmov(t,&base[pos][1],equal(babs,2)); + cmov(t,&base[pos][2],equal(babs,3)); + cmov(t,&base[pos][3],equal(babs,4)); + cmov(t,&base[pos][4],equal(babs,5)); + cmov(t,&base[pos][5],equal(babs,6)); + cmov(t,&base[pos][6],equal(babs,7)); + cmov(t,&base[pos][7],equal(babs,8)); + fe_copy(minust.yplusx,t->yminusx); + fe_copy(minust.yminusx,t->yplusx); + fe_neg(minust.xy2d,t->xy2d); + cmov(t,&minust,bnegative); +} + + +/* +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; + ge_p2 s; + 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 */ + + ge_p3_0(h); + for (i = 1;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); + } +} + + +/* 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; + } + } + } +} + + +static 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 }, + }, +} ; + + +/* +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; +} + + +static const fe d = { +-10913610,13857413,-15372611,6949391,114729, +-8787816,-6275908,-3247719,-18696448,-12055116 +} ; + + +static const fe sqrtm1 = { +-32595792,-7943725,9377950,3500415,12389472, +-272473,-25146209,-2005654,326686,11406482 +} ; + + +int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) +{ + fe u; + fe v; + fe v3; + fe vxx; + fe 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 +*/ + +void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) +{ + fe 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); +} + + +/* ge msub */ + +/* +r = p - q +*/ + +void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) +{ + fe 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); +} + + +/* ge p1p1 to p2 */ +/* +r = p +*/ + +extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) +{ + fe_mul(r->X,p->X,p->T); + fe_mul(r->Y,p->Y,p->Z); + fe_mul(r->Z,p->Z,p->T); +} + + +/* ge p1p1 to p3 */ + +/* +r = p +*/ + +extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) +{ + 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); +} + + +/* ge p2 0 */ + +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 +*/ + +void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) +{ + fe 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); +} + + +/* ge p3 0 */ + +void ge_p3_0(ge_p3 *h) +{ + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); + fe_0(h->T); +} + + +/* ge p3 dble */ + +/* +r = 2 * p +*/ + +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 +*/ + +static const fe d2 = { +-21827239,-5839606,-30745221,13898782,229458, +15978800,-12551817,-6495438,29715968,9444199 +} ; + + +extern 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 +*/ + +extern 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) +{ + fe recip; + fe x; + fe 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; +} + + +/* ge_precomp_0 */ +void ge_precomp_0(ge_precomp *h) +{ + fe_1(h->yplusx); + fe_1(h->yminusx); + fe_0(h->xy2d); +} + + +/* ge_sub */ +/* +r = p - q +*/ + +void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) +{ + fe 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); +} + + +/* ge tobytes */ +void ge_tobytes(unsigned char *s,const ge_p2 *h) +{ + fe recip; + fe x; + fe 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 /* HAVE_ED25519 */ +#endif /* not defined CURVED25519_SMALL */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/hash.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,368 @@ +/* hash.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + + +#ifndef NO_ASN +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: +#ifndef NO_MD5 + oid = MD5h; +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + oid = SHAh; +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + oid = SHA256h; +#endif + break; + case WC_HASH_TYPE_SHA384: +#if defined(WOLFSSL_SHA512) && defined(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_NONE: + default: + oid = BAD_FUNC_ARG; + break; + } + return oid; +} +#endif + +/* 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_MD5: +#ifndef NO_MD5 + dig_size = MD5_DIGEST_SIZE; +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + dig_size = SHA_DIGEST_SIZE; +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + dig_size = SHA256_DIGEST_SIZE; +#endif + break; + case WC_HASH_TYPE_SHA384: +#if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) + dig_size = SHA384_DIGEST_SIZE; +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + dig_size = SHA512_DIGEST_SIZE; +#endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_NONE: + default: + dig_size = BAD_FUNC_ARG; + break; + } + return dig_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_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA384: +#if defined(WOLFSSL_SHA512) && defined(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; + + /* Not Supported */ + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + break; + } + return ret; +} + + +#if !defined(WOLFSSL_TI_HASH) + +#if !defined(NO_MD5) +void wc_Md5GetHash(Md5* md5, byte* hash) +{ + Md5 save = *md5 ; + wc_Md5Final(md5, hash) ; + *md5 = save ; +} + +WOLFSSL_API void wc_Md5RestorePos(Md5* m1, Md5* m2) { + *m1 = *m2 ; +} + +#endif + +#if !defined(NO_SHA) +int wc_ShaGetHash(Sha* sha, byte* hash) +{ + int ret ; + Sha save = *sha ; + ret = wc_ShaFinal(sha, hash) ; + *sha = save ; + return ret ; +} + +void wc_ShaRestorePos(Sha* s1, Sha* s2) { + *s1 = *s2 ; +} + +int wc_ShaHash(const byte* data, word32 len, byte* hash) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Sha* sha; +#else + Sha sha[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + sha = (Sha*)XMALLOC(sizeof(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 /* !defined(NO_SHA) */ + +#if !defined(NO_SHA256) +int wc_Sha256GetHash(Sha256* sha256, byte* hash) +{ + int ret ; + Sha256 save = *sha256 ; + ret = wc_Sha256Final(sha256, hash) ; + *sha256 = save ; + return ret ; +} + +void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { + *s1 = *s2 ; +} + +int wc_Sha256Hash(const byte* data, word32 len, byte* hash) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Sha256* sha256; +#else + Sha256 sha256[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + sha256 = (Sha256*)XMALLOC(sizeof(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"); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* !defined(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 + Sha512* sha512; +#else + Sha512 sha512[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + sha512 = (Sha512*)XMALLOC(sizeof(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"); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#if defined(WOLFSSL_SHA384) +int wc_Sha384Hash(const byte* data, word32 len, byte* hash) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Sha384* sha384; +#else + Sha384 sha384[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + sha384 = (Sha384*)XMALLOC(sizeof(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"); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* defined(WOLFSSL_SHA384) */ +#endif /* defined(WOLFSSL_SHA512) */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/hc128.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,401 @@ +/* hc128.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #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 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; +} + + +/* Key setup */ +int wc_Hc128_SetKey(HC128* ctx, const byte* key, const byte* iv) +{ +#ifdef XSTREAM_ALIGN + 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 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) +{ +#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, NULL, 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, NULL, 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 */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/hmac.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,880 @@ +/* hmac.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_HMAC + +#include <wolfssl/wolfcrypt/hmac.h> + +#ifdef HAVE_FIPS +/* does init */ +int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) +{ + return HmacSetKey_fips(hmac, type, key, keySz); +} + + +int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) +{ + return HmacUpdate_fips(hmac, in, sz); +} + + +int wc_HmacFinal(Hmac* hmac, byte* out) +{ + return HmacFinal_fips(hmac, out); +} + + +#ifdef HAVE_CAVIUM + int wc_HmacInitCavium(Hmac* hmac, int i) + { + return HmacInitCavium(hmac, i); + } + + + void wc_HmacFreeCavium(Hmac* hmac) + { + HmacFreeCavium(hmac); + } +#endif + +int wolfSSL_GetHmacMaxSize(void) +{ + return CyaSSL_GetHmacMaxSize(); +} + +#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 */ +#ifdef WOLFSSL_PIC32MZ_HASH + +#define wc_InitMd5 wc_InitMd5_sw +#define wc_Md5Update wc_Md5Update_sw +#define wc_Md5Final wc_Md5Final_sw + +#define wc_InitSha wc_InitSha_sw +#define wc_ShaUpdate wc_ShaUpdate_sw +#define wc_ShaFinal wc_ShaFinal_sw + +#define wc_InitSha256 wc_InitSha256_sw +#define wc_Sha256Update wc_Sha256Update_sw +#define wc_Sha256Final wc_Sha256Final_sw + +#endif + +#ifdef HAVE_FIPS + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif + +#include <wolfssl/wolfcrypt/error-crypt.h> + + +#ifdef HAVE_CAVIUM + static int HmacCaviumFinal(Hmac* hmac, byte* hash); + static int HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length); + static int HmacCaviumSetKey(Hmac* hmac, int type, const byte* key, + word32 length); +#endif + +static int InitHmac(Hmac* hmac, int type) +{ + int ret = 0; + + hmac->innerHashKeyed = 0; + hmac->macType = (byte)type; + + if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 + || type == SHA512 || type == BLAKE2B_ID)) + return BAD_FUNC_ARG; + + switch (type) { + #ifndef NO_MD5 + case MD5: + wc_InitMd5(&hmac->hash.md5); + break; + #endif + + #ifndef NO_SHA + case SHA: + ret = wc_InitSha(&hmac->hash.sha); + break; + #endif + + #ifndef NO_SHA256 + case SHA256: + ret = wc_InitSha256(&hmac->hash.sha256); + break; + #endif + + #ifdef WOLFSSL_SHA384 + case SHA384: + ret = wc_InitSha384(&hmac->hash.sha384); + break; + #endif + + #ifdef WOLFSSL_SHA512 + case SHA512: + ret = wc_InitSha512(&hmac->hash.sha512); + break; + #endif + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); + break; + #endif + + default: + return BAD_FUNC_ARG; + } + + return ret; +} + + +int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) +{ + byte* ip = (byte*) hmac->ipad; + byte* op = (byte*) hmac->opad; + word32 i, hmac_block_size = 0; + int ret; + +#ifdef HAVE_CAVIUM + if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) + return HmacCaviumSetKey(hmac, type, key, length); +#endif + + ret = InitHmac(hmac, type); + if (ret != 0) + return ret; + +#ifdef HAVE_FIPS + if (length < HMAC_FIPS_MIN_KEY) + return HMAC_MIN_KEYLEN_E; +#endif + + switch (hmac->macType) { + #ifndef NO_MD5 + case MD5: + { + hmac_block_size = MD5_BLOCK_SIZE; + if (length <= MD5_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { + wc_Md5Update(&hmac->hash.md5, key, length); + wc_Md5Final(&hmac->hash.md5, ip); + length = MD5_DIGEST_SIZE; + } + } + break; + #endif + + #ifndef NO_SHA + case SHA: + { + hmac_block_size = SHA_BLOCK_SIZE; + if (length <= SHA_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { + wc_ShaUpdate(&hmac->hash.sha, key, length); + wc_ShaFinal(&hmac->hash.sha, ip); + length = SHA_DIGEST_SIZE; + } + } + break; + #endif + + #ifndef NO_SHA256 + case SHA256: + { + hmac_block_size = SHA256_BLOCK_SIZE; + if (length <= SHA256_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { + ret = wc_Sha256Update(&hmac->hash.sha256, key, length); + if (ret != 0) + return ret; + + ret = wc_Sha256Final(&hmac->hash.sha256, ip); + if (ret != 0) + return ret; + + length = SHA256_DIGEST_SIZE; + } + } + break; + #endif + + #ifdef WOLFSSL_SHA384 + case SHA384: + { + hmac_block_size = SHA384_BLOCK_SIZE; + if (length <= SHA384_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { + ret = wc_Sha384Update(&hmac->hash.sha384, key, length); + if (ret != 0) + return ret; + + ret = wc_Sha384Final(&hmac->hash.sha384, ip); + if (ret != 0) + return ret; + + length = SHA384_DIGEST_SIZE; + } + } + break; + #endif + + #ifdef WOLFSSL_SHA512 + case SHA512: + { + hmac_block_size = SHA512_BLOCK_SIZE; + if (length <= SHA512_BLOCK_SIZE) { + XMEMCPY(ip, key, length); + } + else { + ret = wc_Sha512Update(&hmac->hash.sha512, key, length); + if (ret != 0) + return ret; + + ret = wc_Sha512Final(&hmac->hash.sha512, ip); + if (ret != 0) + return ret; + + length = SHA512_DIGEST_SIZE; + } + } + break; + #endif + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + { + hmac_block_size = BLAKE2B_BLOCKBYTES; + if (length <= BLAKE2B_BLOCKBYTES) { + XMEMCPY(ip, key, length); + } + else { + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length); + if (ret != 0) + return ret; + + ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); + if (ret != 0) + return ret; + + length = BLAKE2B_256; + } + } + break; + #endif + + default: + return BAD_FUNC_ARG; + } + 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 0; +} + + +static int HmacKeyInnerHash(Hmac* hmac) +{ + int ret = 0; + + switch (hmac->macType) { + #ifndef NO_MD5 + case MD5: + wc_Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE); + break; + #endif + + #ifndef NO_SHA + case SHA: + wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE); + break; + #endif + + #ifndef NO_SHA256 + case SHA256: + ret = wc_Sha256Update(&hmac->hash.sha256, + (byte*) hmac->ipad, SHA256_BLOCK_SIZE); + if (ret != 0) + return ret; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case SHA384: + ret = wc_Sha384Update(&hmac->hash.sha384, + (byte*) hmac->ipad, SHA384_BLOCK_SIZE); + if (ret != 0) + return ret; + break; + #endif + + #ifdef WOLFSSL_SHA512 + case SHA512: + ret = wc_Sha512Update(&hmac->hash.sha512, + (byte*) hmac->ipad, SHA512_BLOCK_SIZE); + if (ret != 0) + return ret; + break; + #endif + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, + (byte*) hmac->ipad,BLAKE2B_BLOCKBYTES); + if (ret != 0) + return ret; + break; + #endif + + default: + break; + } + + hmac->innerHashKeyed = 1; + + return ret; +} + + +int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) +{ + int ret; + +#ifdef HAVE_CAVIUM + if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) + return HmacCaviumUpdate(hmac, msg, length); +#endif + + if (!hmac->innerHashKeyed) { + ret = HmacKeyInnerHash(hmac); + if (ret != 0) + return ret; + } + + switch (hmac->macType) { + #ifndef NO_MD5 + case MD5: + wc_Md5Update(&hmac->hash.md5, msg, length); + break; + #endif + + #ifndef NO_SHA + case SHA: + wc_ShaUpdate(&hmac->hash.sha, msg, length); + break; + #endif + + #ifndef NO_SHA256 + case SHA256: + ret = wc_Sha256Update(&hmac->hash.sha256, msg, length); + if (ret != 0) + return ret; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case SHA384: + ret = wc_Sha384Update(&hmac->hash.sha384, msg, length); + if (ret != 0) + return ret; + break; + #endif + + #ifdef WOLFSSL_SHA512 + case SHA512: + ret = wc_Sha512Update(&hmac->hash.sha512, msg, length); + if (ret != 0) + return ret; + break; + #endif + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length); + if (ret != 0) + return ret; + break; + #endif + + default: + break; + } + + return 0; +} + + +int wc_HmacFinal(Hmac* hmac, byte* hash) +{ + int ret; + +#ifdef HAVE_CAVIUM + if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) + return HmacCaviumFinal(hmac, hash); +#endif + + if (!hmac->innerHashKeyed) { + ret = HmacKeyInnerHash(hmac); + if (ret != 0) + return ret; + } + + switch (hmac->macType) { + #ifndef NO_MD5 + case MD5: + { + wc_Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash); + + wc_Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE); + wc_Md5Update(&hmac->hash.md5, + (byte*) hmac->innerHash, MD5_DIGEST_SIZE); + + wc_Md5Final(&hmac->hash.md5, hash); + } + break; + #endif + + #ifndef NO_SHA + case SHA: + { + wc_ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash); + + wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE); + wc_ShaUpdate(&hmac->hash.sha, + (byte*) hmac->innerHash, SHA_DIGEST_SIZE); + + wc_ShaFinal(&hmac->hash.sha, hash); + } + break; + #endif + + #ifndef NO_SHA256 + case SHA256: + { + ret = wc_Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash); + if (ret != 0) + return ret; + + ret = wc_Sha256Update(&hmac->hash.sha256, + (byte*) hmac->opad, SHA256_BLOCK_SIZE); + if (ret != 0) + return ret; + + ret = wc_Sha256Update(&hmac->hash.sha256, + (byte*) hmac->innerHash, SHA256_DIGEST_SIZE); + if (ret != 0) + return ret; + + ret = wc_Sha256Final(&hmac->hash.sha256, hash); + if (ret != 0) + return ret; + } + break; + #endif + + #ifdef WOLFSSL_SHA384 + case SHA384: + { + ret = wc_Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash); + if (ret != 0) + return ret; + + ret = wc_Sha384Update(&hmac->hash.sha384, + (byte*) hmac->opad, SHA384_BLOCK_SIZE); + if (ret != 0) + return ret; + + ret = wc_Sha384Update(&hmac->hash.sha384, + (byte*) hmac->innerHash, SHA384_DIGEST_SIZE); + if (ret != 0) + return ret; + + ret = wc_Sha384Final(&hmac->hash.sha384, hash); + if (ret != 0) + return ret; + } + break; + #endif + + #ifdef WOLFSSL_SHA512 + case SHA512: + { + ret = wc_Sha512Final(&hmac->hash.sha512, (byte*) hmac->innerHash); + if (ret != 0) + return ret; + + ret = wc_Sha512Update(&hmac->hash.sha512, + (byte*) hmac->opad, SHA512_BLOCK_SIZE); + if (ret != 0) + return ret; + + ret = wc_Sha512Update(&hmac->hash.sha512, + (byte*) hmac->innerHash, SHA512_DIGEST_SIZE); + if (ret != 0) + return ret; + + ret = wc_Sha512Final(&hmac->hash.sha512, hash); + if (ret != 0) + return ret; + } + break; + #endif + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + { + ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*) hmac->innerHash, + BLAKE2B_256); + if (ret != 0) + return ret; + + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, + (byte*) hmac->opad, BLAKE2B_BLOCKBYTES); + if (ret != 0) + return ret; + + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, + (byte*) hmac->innerHash, BLAKE2B_256); + if (ret != 0) + return ret; + + ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256); + if (ret != 0) + return ret; + } + break; + #endif + + default: + break; + } + + hmac->innerHashKeyed = 0; + + return 0; +} + + +#ifdef HAVE_CAVIUM + +/* Initialize Hmac for use with Nitrox device */ +int wc_HmacInitCavium(Hmac* hmac, int devId) +{ + if (hmac == NULL) + return -1; + + if (CspAllocContext(CONTEXT_SSL, &hmac->contextHandle, devId) != 0) + return -1; + + hmac->keyLen = 0; + hmac->dataLen = 0; + hmac->type = 0; + hmac->devId = devId; + hmac->magic = WOLFSSL_HMAC_CAVIUM_MAGIC; + hmac->data = NULL; /* buffered input data */ + + hmac->innerHashKeyed = 0; + + return 0; +} + + +/* Free Hmac from use with Nitrox device */ +void wc_HmacFreeCavium(Hmac* hmac) +{ + if (hmac == NULL) + return; + + CspFreeContext(CONTEXT_SSL, hmac->contextHandle, hmac->devId); + hmac->magic = 0; + XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP); + hmac->data = NULL; +} + + +static int HmacCaviumFinal(Hmac* hmac, byte* hash) +{ + word32 requestId; + + if (CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen, + (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, &requestId, + hmac->devId) != 0) { + WOLFSSL_MSG("Cavium Hmac failed"); + return -1; + } + hmac->innerHashKeyed = 0; /* tell update to start over if used again */ + + return 0; +} + + +static int HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length) +{ + word16 add = (word16)length; + word32 total; + byte* tmp; + + if (length > WOLFSSL_MAX_16BIT) { + WOLFSSL_MSG("Too big msg for cavium hmac"); + return -1; + } + + if (hmac->innerHashKeyed == 0) { /* starting new */ + hmac->dataLen = 0; + hmac->innerHashKeyed = 1; + } + + total = add + hmac->dataLen; + if (total > WOLFSSL_MAX_16BIT) { + WOLFSSL_MSG("Too big msg for cavium hmac"); + return -1; + } + + tmp = XMALLOC(hmac->dataLen + add, NULL,DYNAMIC_TYPE_CAVIUM_TMP); + if (tmp == NULL) { + WOLFSSL_MSG("Out of memory for cavium update"); + return -1; + } + if (hmac->dataLen) + XMEMCPY(tmp, hmac->data, hmac->dataLen); + XMEMCPY(tmp + hmac->dataLen, msg, add); + + hmac->dataLen += add; + XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP); + hmac->data = tmp; + + return 0; +} + + +static int HmacCaviumSetKey(Hmac* hmac, int type, const byte* key, + word32 length) +{ + hmac->macType = (byte)type; + if (type == MD5) + hmac->type = MD5_TYPE; + else if (type == SHA) + hmac->type = SHA1_TYPE; + else if (type == SHA256) + hmac->type = SHA256_TYPE; + else { + WOLFSSL_MSG("unsupported cavium hmac type"); + } + + hmac->innerHashKeyed = 0; /* should we key Startup flag */ + + hmac->keyLen = (word16)length; + /* store key in ipad */ + XMEMCPY(hmac->ipad, key, length); + + return 0; +} + +#endif /* HAVE_CAVIUM */ + +int wolfSSL_GetHmacMaxSize(void) +{ + return MAX_DIGEST_SIZE; +} + +#ifdef HAVE_HKDF + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +static INLINE int GetHashSizeByType(int type) +{ + if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 + || type == SHA512 || type == BLAKE2B_ID)) + return BAD_FUNC_ARG; + + switch (type) { + #ifndef NO_MD5 + case MD5: + return MD5_DIGEST_SIZE; + #endif + + #ifndef NO_SHA + case SHA: + return SHA_DIGEST_SIZE; + #endif + + #ifndef NO_SHA256 + case SHA256: + return SHA256_DIGEST_SIZE; + #endif + + #ifdef WOLFSSL_SHA384 + case SHA384: + return SHA384_DIGEST_SIZE; + #endif + + #ifdef WOLFSSL_SHA512 + case SHA512: + return SHA512_DIGEST_SIZE; + #endif + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + return BLAKE2B_OUTBYTES; + #endif + + default: + return BAD_FUNC_ARG; + } +} + + +/* HMAC-KDF with hash type, optional salt and info, return 0 on success */ +int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + const byte* salt, word32 saltSz, + const byte* info, word32 infoSz, + byte* out, word32 outSz) +{ + Hmac myHmac; +#ifdef WOLFSSL_SMALL_STACK + byte* tmp; + byte* prk; +#else + byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper and T */ + byte prk[MAX_DIGEST_SIZE]; +#endif + const byte* localSalt; /* either points to user input or tmp */ + int hashSz = GetHashSizeByType(type); + word32 outIdx = 0; + byte n = 0x1; + int ret; + + if (hashSz < 0) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return MEMORY_E; + + prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (prk == NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + localSalt = salt; + if (localSalt == NULL) { + XMEMSET(tmp, 0, hashSz); + localSalt = tmp; + saltSz = hashSz; + } + + do { + ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); + if (ret != 0) + break; + ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); + if (ret != 0) + break; + ret = wc_HmacFinal(&myHmac, prk); + } while (0); + + if (ret == 0) { + while (outIdx < outSz) { + int tmpSz = (n == 1) ? 0 : hashSz; + word32 left = outSz - outIdx; + + ret = wc_HmacSetKey(&myHmac, type, prk, hashSz); + 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, (word32)hashSz); + XMEMCPY(out+outIdx, tmp, left); + + outIdx += hashSz; + n++; + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prk, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_HKDF */ + +#endif /* HAVE_FIPS */ +#endif /* NO_HMAC */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/integer.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,4748 @@ +/* integer.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + +#ifndef NO_BIG_INT + +#ifndef USE_FAST_MATH + +#include <wolfssl/wolfcrypt/integer.h> + +#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 && ((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) +{ + int i; + + /* Safeguard against passing in a null pointer */ + if (a == NULL) + return MP_VAL; + + /* allocate memory required and clear it */ + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC, 0, + DYNAMIC_TYPE_BIGINT); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the digits to zero */ + for (i = 0; i < MP_PREC; i++) { + a->dp[i] = 0; + } + + /* set the used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = MP_PREC; + a->sign = MP_ZPOS; + + 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 */ + XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } +} + + +/* 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) == 0) { +#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; +} + + +/* 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 = 0; + while (mp_iszero (&t) == 0) { +#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) { + mp_clear (&t); + return res; + } + } + bn_reverse (b, x); + mp_clear (&t); + return MP_OKAY; +} + + +/* creates "a" then copies b into it */ +int mp_init_copy (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_init (a)) != MP_OKAY) { + return res; + } + return mp_copy (b, a); +} + + +/* 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) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + /* zero b and copy the parameters over */ + { + register 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; 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) { + /* 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, 0, + 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; + + 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) +{ + register 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; + } +} + + +/* 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; + } + + { + register 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) { + register mp_digit *tmpc, shift, mask, r, rr; + register 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; + } + } + + { + register 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) + */ +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + 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) == 1 || 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 */ +int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == 1) { + 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) == 1) { + return fast_mp_invmod (a, b, c); + } +#endif + +#ifdef BN_MP_INVMOD_SLOW_C + return mp_invmod_slow(a, b, c); +#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) == 1) { + 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; + } + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 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) == 1) { + 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) == 1) { + /* 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) == 1) { + /* 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) == 0) { + if (++loop_check > 4096) { + 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) == 1) { + 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) { + 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) == 1 && mp_iseven (&y) == 1) { + 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; + } + mp_set (&A, 1); + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 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) == 1 || mp_isodd (&B) == 1) { + /* 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) == 1) { + /* 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) == 1 || mp_isodd (&D) == 1) { + /* 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) == 0) + 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) +{ + /* compare based on sign */ + if (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 */ +void mp_set (mp_int * a, mp_digit b) +{ + mp_zero (a); + a->dp[0] = (mp_digit)(b & MP_MASK); + a->used = (a->dp[0] != 0) ? 1 : 0; +} + +/* 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 */ +int +mp_mod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int t; + int res; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + if (t.sign != b->sign) { + res = mp_add (b, &t, c); + } else { + res = MP_OKAY; + mp_exch (&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) == 1) { + 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; + } + + + mp_set(&tq, 1); + 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; + { + register 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, max; + + /* 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 = b->used; + max = a->used; + x = a; + } else { + min = a->used; + max = b->used; + x = b; + } + + /* init result */ + if (c->alloc < max + 1) { + if ((res = mp_grow (c, max + 1)) != MP_OKAY) { + return res; + } + } + + /* get old used digit count and set new one */ + olduse = c->used; + c->used = max + 1; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register 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; 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 != max) { + for (; i < max; 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, max; + + /* find sizes */ + min = b->used; + max = a->used; + + /* init result */ + if (c->alloc < max) { + if ((res = mp_grow (c, max)) != MP_OKAY) { + return res; + } + } + olduse = c->used; + c->used = max; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register 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; 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; 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(&M[1])) != 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(&M[x])) != 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 (&res)) != 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; + } +#else + err = MP_VAL; + goto LBL_RES; +#endif + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { + goto LBL_RES; + } + } else { + mp_set(&res, 1); + 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, 0, 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[...] + */ + { + register mp_word *_W; + register 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) + */ + register 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 + */ + { + register int iy; + register mp_digit *tmpn; + register 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]. + */ + { + register mp_digit *tmpx; + register 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, 0, 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 */ + { + register int iy; + register mp_digit *tmpn, *tmpx, u; + register 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) { + s_mp_sub(x, n, x); + 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) { + s_mp_sub(a, n, a); + 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) */ +int mp_mulmod (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; + } + + if ((res = mp_mul (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + 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) */ +int mp_mul (mp_int * a, mp_int * b, mp_int * c) +{ + 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; + + { + register 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, 0, + DYNAMIC_TYPE_BIGINT); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the members */ + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; + + /* 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, 0, 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, 0, 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 + register 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, 0, 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; + + { + register mp_digit *tmpc; + tmpc = c->dp; + for (ix = 0; ix < pa+1; ix++) { + /* 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, 0, 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 { + mp_set(a, 1); + 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; + } + mp_set (&res, 1); + + /* 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) { + mp_set (&q, 1); + 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) { + s_mp_sub(a, n, a); + 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; 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; + + /* 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, 0, 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++) { + 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; + + { + register 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, 0, DYNAMIC_TYPE_BIGINT); +#endif + + return MP_OKAY; +} + + +/* set a 32-bit const */ +int mp_set_int (mp_int * a, unsigned long b) +{ + int x, res; + + mp_zero (a); + + /* set four bits at a time */ + for (x = 0; x < 8; x++) { + /* shift the number up four bits */ + if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { + return res; + } + + /* OR in the top four bits of the source */ + a->dp[0] |= (b >> 28) & 15; + + /* shift the source up to the next four bits */ + b <<= 4; + + /* 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) + +/* 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) + +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, qq; + + /* easy out */ + if (mp_iszero(a) == 1) { + 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(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) == 1) { + 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; + } + + 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 /* defined(WOLFSSL_KEY_GEN)||defined(HAVE_COMP_KEY)||defined(HAVE_ECC) */ + +#ifdef WOLFSSL_KEY_GEN + +const mp_digit ltm_prime_tab[] = { + 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 */ + mp_set (&b, ltm_prime_tab[ix]); + + 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) == 0) { + /* 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(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) + +/* chars used in radix conversions */ +const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz+/"; +#endif + +#ifdef 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 < 2 || radix > 64) { + 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) { + /* 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 == 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; + } + + /* set the sign only if a != 0 */ + if (mp_iszero(a) != 1) { + a->sign = neg; + } + return MP_OKAY; +} +#endif /* HAVE_ECC */ + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) + +/* 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 == 2) { + *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; + return MP_OKAY; + } + + /* make sure the radix is in range */ + if (radix < 2 || radix > 64) { + 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 < 2 || radix > 64) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a) == 1) { + *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) == 0) { + 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; +} + +#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ + +#endif /* USE_FAST_MATH */ + +#endif /* NO_BIG_INT */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/logging.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,208 @@ +/* logging.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + + +#ifdef __cplusplus + extern "C" { +#endif + WOLFSSL_API int wolfSSL_Debugging_ON(void); + WOLFSSL_API void wolfSSL_Debugging_OFF(void); +#ifdef __cplusplus + } +#endif + + +#ifdef DEBUG_WOLFSSL + +/* Set these to default values initially. */ +static wolfSSL_Logging_cb log_function = 0; +static int loggingEnabled = 0; + +#endif /* DEBUG_WOLFSSL */ + + +int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f) +{ +#ifdef DEBUG_WOLFSSL + int res = 0; + + if (f) + log_function = f; + else + res = BAD_FUNC_ARG; + + return res; +#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 DEBUG_WOLFSSL + +#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> /* for default printf stuff */ +#endif + +#ifdef THREADX + 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 (loggingEnabled) { +#ifdef THREADX + dc_log_printf("%s\n", logMessage); +#elif defined(MICRIUM) + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + NetSecure_TraceOut((CPU_CHAR *)logMessage); + #endif +#elif defined(WOLFSSL_MDK_ARM) + fflush(stdout) ; + printf("%s\n", logMessage); + fflush(stdout) ; +#elif defined(WOLFSSL_LOG_PRINTF) + printf("%s\n", logMessage); +#else + fprintf(stderr, "%s\n", logMessage); +#endif + } + } +} + + +void WOLFSSL_MSG(const char* msg) +{ + if (loggingEnabled) + wolfssl_log(INFO_LOG , msg); +} + + +void WOLFSSL_BUFFER(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[80]; + sprintf(buffer, "wolfSSL Entering %s", msg); + wolfssl_log(ENTER_LOG , buffer); + } +} + + +void WOLFSSL_LEAVE(const char* msg, int ret) +{ + if (loggingEnabled) { + char buffer[80]; + sprintf(buffer, "wolfSSL Leaving %s, return %d", msg, ret); + wolfssl_log(LEAVE_LOG , buffer); + } +} + + +void WOLFSSL_ERROR(int error) +{ + if (loggingEnabled) { + char buffer[80]; + sprintf(buffer, "wolfSSL error occurred, error = %d", error); + wolfssl_log(ERROR_LOG , buffer); + } +} + +#endif /* DEBUG_WOLFSSL */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/md2.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,162 @@ +/* md2.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/md4.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,222 @@ +/* md4.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #include <wolfcrypt/src/misc.c> +#endif + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +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 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/md5.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,411 @@ +/* md5.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitMd5 wc_InitMd5_sw +#define wc_Md5Update wc_Md5Update_sw +#define wc_Md5Final wc_Md5Final_sw +#endif + +#include <wolfssl/wolfcrypt/md5.h> +#include <wolfssl/wolfcrypt/error-crypt.h> + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" + #define XTRANSFORM(S,B) Transform((S), (B)) +#else + #define XTRANSFORM(S,B) Transform((S)) +#endif + + +#ifdef STM32F2_HASH + /* + * STM32F2 hardware MD5 support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ + #include "stm32f2xx.h" + + void wc_InitMd5(Md5* md5) + { + /* STM32F2 struct notes: + * md5->buffer = first 4 bytes used to hold partial block if needed + * md5->buffLen = num bytes currently stored in md5->buffer + * md5->loLen = num bytes that have been written to STM32 FIFO + */ + XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + + md5->buffLen = 0; + md5->loLen = 0; + + /* initialize HASH peripheral */ + HASH_DeInit(); + + /* configure algo used, algo mode, datatype */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + } + + void wc_Md5Update(Md5* md5, const byte* data, word32 len) + { + word32 i = 0; + word32 fill = 0; + word32 diff = 0; + + /* if saved partial block is available */ + if (md5->buffLen > 0) { + fill = 4 - md5->buffLen; + + /* if enough data to fill, fill and push to FIFO */ + if (fill <= len) { + XMEMCPY((byte*)md5->buffer + md5->buffLen, data, fill); + HASH_DataIn(*(uint32_t*)md5->buffer); + + data += fill; + len -= fill; + md5->loLen += 4; + md5->buffLen = 0; + } else { + /* append partial to existing stored block */ + XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); + md5->buffLen += len; + return; + } + } + + /* write input block in the IN FIFO */ + for (i = 0; i < len; i += 4) + { + diff = len - i; + if (diff < 4) { + /* store incomplete last block, not yet in FIFO */ + XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + XMEMCPY((byte*)md5->buffer, data, diff); + md5->buffLen = diff; + } else { + HASH_DataIn(*(uint32_t*)data); + data+=4; + } + } + + /* keep track of total data length thus far */ + md5->loLen += (len - md5->buffLen); + } + + void wc_Md5Final(Md5* md5, byte* hash) + { + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (md5->buffLen > 0) { + HASH_DataIn(*(uint32_t*)md5->buffer); + md5->loLen += md5->buffLen; + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (md5->loLen % MD5_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + md5->digest[0] = HASH->HR[0]; + md5->digest[1] = HASH->HR[1]; + md5->digest[2] = HASH->HR[2]; + md5->digest[3] = HASH->HR[3]; + + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); + + XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); + + wc_InitMd5(md5); /* reset state */ + } + +#else /* CTaoCrypt software implementation */ + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + +void wc_InitMd5(Md5* md5) +{ + 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; +} + +#ifdef FREESCALE_MMCAU +static int Transform(Md5* md5, byte* data) +{ + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + cau_md5_hash_n(data, 1, (unsigned char*)md5->digest); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; +} +#endif /* FREESCALE_MMCAU */ + +#ifndef FREESCALE_MMCAU + +static void Transform(Md5* md5) +{ +#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 + + /* 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; +} + +#endif /* FREESCALE_MMCAU */ + + +static INLINE void AddLength(Md5* md5, word32 len) +{ + word32 tmp = md5->loLen; + if ( (md5->loLen += len) < tmp) + md5->hiLen++; /* carry low to high */ +} + + +void wc_Md5Update(Md5* md5, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)md5->buffer; + + while (len) { + word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); + XMEMCPY(&local[md5->buffLen], data, add); + + md5->buffLen += add; + data += add; + len -= add; + + if (md5->buffLen == MD5_BLOCK_SIZE) { + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + XTRANSFORM(md5, local); + AddLength(md5, MD5_BLOCK_SIZE); + md5->buffLen = 0; + } + } +} + + +void wc_Md5Final(Md5* md5, byte* hash) +{ + byte* local = (byte*)md5->buffer; + + AddLength(md5, md5->buffLen); /* before adding pads */ + + local[md5->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (md5->buffLen > MD5_PAD_SIZE) { + XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); + md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; + + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + XTRANSFORM(md5, local); + md5->buffLen = 0; + } + XMEMSET(&local[md5->buffLen], 0, MD5_PAD_SIZE - md5->buffLen); + + /* put lengths in bits */ + md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) + + (md5->hiLen << 3); + md5->loLen = md5->loLen << 3; + + /* store lengths */ + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); + XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); + + XTRANSFORM(md5, local); + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); + #endif + XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); + + wc_InitMd5(md5); /* reset state */ +} + +#endif /* STM32F2_HASH */ + + +int wc_Md5Hash(const byte* data, word32 len, byte* hash) +{ +#ifdef WOLFSSL_SMALL_STACK + Md5* md5; +#else + Md5 md5[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; +#endif + + wc_InitMd5(md5); + wc_Md5Update(md5, data, len); + wc_Md5Final(md5, hash); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +#endif /* WOLFSSL_TI_HASH */ + +#endif /* NO_MD5 */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/memory.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,193 @@ +/* memory.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + +#ifdef WOLFSSL_MALLOC_CHECK + #include <stdio.h> +#endif + +/* Set these to default values initially. */ +static wolfSSL_Malloc_cb malloc_function = 0; +static wolfSSL_Free_cb free_function = 0; +static wolfSSL_Realloc_cb realloc_function = 0; + +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; +} + + +void* wolfSSL_Malloc(size_t size) +{ + void* res = 0; + + if (malloc_function) + res = malloc_function(size); + else + res = malloc(size); + + #ifdef WOLFSSL_MALLOC_CHECK + if (res == NULL) + puts("wolfSSL_malloc failed"); + #endif + + return res; +} + +void wolfSSL_Free(void *ptr) +{ + if (free_function) + free_function(ptr); + else + free(ptr); +} + +void* wolfSSL_Realloc(void *ptr, size_t size) +{ + void* res = 0; + + if (realloc_function) + res = realloc_function(ptr, size); + else + res = realloc(ptr, size); + + return res; +} + +#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 sense 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); +} + + +/* unit api calls, let's make sure visible with WOLFSSL_API */ +WOLFSSL_API 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/misc.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,203 @@ +/* misc.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + + +#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 INLINE word32 rotlFixed(word32 x, word32 y) + { + return y ? _lrotl(x, y) : x; + } + + STATIC INLINE word32 rotrFixed(word32 x, word32 y) + { + return y ? _lrotr(x, y) : x; + } + +#else /* generic */ + + STATIC INLINE word32 rotlFixed(word32 x, word32 y) + { + return (x << y) | (x >> (sizeof(y) * 8 - y)); + } + + + STATIC INLINE word32 rotrFixed(word32 x, word32 y) + { + return (x >> y) | (x << (sizeof(y) * 8 - y)); + } + +#endif + + +STATIC INLINE word32 ByteReverseWord32(word32 value) +{ +#ifdef PPC_INTRINSICS + /* PPC: load reverse indexed instruction */ + return (word32)__lwbrx(&value,0); +#elif defined(KEIL_INTRINSICS) + return (word32)__rev(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 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 INLINE word64 rotlFixed64(word64 x, word64 y) +{ + return (x << y) | (x >> (sizeof(y) * 8 - y)); +} + + +STATIC INLINE word64 rotrFixed64(word64 x, word64 y) +{ + return (x >> y) | (x << (sizeof(y) * 8 - y)); +} + + +STATIC INLINE word64 ByteReverseWord64(word64 value) +{ +#ifdef WOLFCRYPT_SLOW_WORD64 + return (word64)(ByteReverseWord32((word32)value)) << 32 | + 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 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 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 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 INLINE void ForceZero(const void* mem, word32 len) +{ + volatile byte* z = (volatile byte*)mem; + + while (len--) *z++ = 0; +} + + +/* check all length bytes for equality, return 0 on success */ +STATIC 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; +} + +#undef STATIC + +#endif /* WOLF_CRYPT_MISC_C */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/pkcs7.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1834 @@ +/* pkcs7.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +/* placed ASN.1 contentType OID into *output, return idx on success, + * 0 upon failure */ +WOLFSSL_LOCAL 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 }; + const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07, 0x06 }; + + 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; + + case ENCRYPTED_DATA: + typeSz = sizeof(encryptedData); + typeName = encryptedData; + break; + + 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 */ +int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid, + word32 maxIdx) +{ + WOLFSSL_ENTER("wc_GetContentType"); + if (GetObjectId(input, inOutIdx, oid, ignoreType, maxIdx) < 0) + return ASN_PARSE_E; + + return 0; +} + + +/* init PKCS7 struct with recipient cert, decode into DecodedCert */ +int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) +{ + int ret = 0; + + XMEMSET(pkcs7, 0, sizeof(PKCS7)); + if (cert != NULL && certSz > 0) { +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* dCert; + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + 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, 0); + + ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + FreeDecodedCert(dCert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize); + pkcs7->publicKeySz = dCert->pubKeySize; + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + + return ret; +} + + +/* releases any memory allocated by a PKCS7 initializer */ +void wc_PKCS7_Free(PKCS7* pkcs7) +{ + (void)pkcs7; +} + + +/* 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; + + 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 { + Sha sha; + byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ + byte contentAttribsDigest[SHA_DIGEST_SIZE]; + byte encContentDigest[512]; + + 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; +} + + +/* 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 }; + +#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; + 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 || + pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 || + output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + esd = (ESD*)XMALLOC(sizeof(ESD), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (esd == NULL) + return MEMORY_E; +#endif + + XMEMSET(esd, 0, sizeof(ESD)); + ret = wc_InitSha(&esd->sha); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (pkcs7->contentSz != 0) + { + wc_ShaUpdate(&esd->sha, pkcs7->content, pkcs7->contentSz); + esd->contentDigest[0] = ASN_OCTET_STRING; + esd->contentDigest[1] = SHA_DIGEST_SIZE; + wc_ShaFinal(&esd->sha, &esd->contentDigest[2]); + } + + 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); + 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, + hashType, 0); + signerInfoSz += esd->signerDigAlgoIdSz; + esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId, + keyType, 0); + signerInfoSz += esd->digEncAlgoIdSz; + + if (pkcs7->signedAttribsSz != 0) { + 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 }; + + PKCS7Attrib cannedAttribs[2] ; + + word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); + cannedAttribs[0].oid = contentTypeOid ; + cannedAttribs[0].oidSz = sizeof(contentTypeOid) ; + cannedAttribs[0].value = contentType ; + cannedAttribs[0].valueSz = sizeof(contentType) ; + cannedAttribs[1].oid = messageDigestOid ; + cannedAttribs[1].oidSz = sizeof(messageDigestOid) ; + cannedAttribs[1].value = esd->contentDigest ; + cannedAttribs[1].valueSz = sizeof(esd->contentDigest) ; + + 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); + + flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, 0, NULL); + flatSignedAttribsSz = esd->signedAttribsSz; + if (flatSignedAttribs == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, 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. */ + { + int result; + word32 scratch = 0; + +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; + RsaKey* privKey; +#else + RsaKey stack_privKey; + RsaKey* privKey = &stack_privKey; + byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ + + MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE]; +#endif + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + word32 digestInfoSeqSz, digestStrSz; + int digIdx = 0; + + if (pkcs7->signedAttribsSz != 0) { + byte attribSet[MAX_SET_SZ]; + word32 attribSetSz; + + attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + + ret = wc_InitSha(&esd->sha); + if (ret < 0) { + XFREE(flatSignedAttribs, 0, NULL); +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + wc_ShaUpdate(&esd->sha, attribSet, attribSetSz); + wc_ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz); + } + wc_ShaFinal(&esd->sha, esd->contentAttribsDigest); + + digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr); + digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz + + digestStrSz + SHA_DIGEST_SIZE, + digestInfoSeq); + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(MAX_SEQ_SZ + MAX_ALGO_SZ + + MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, 0, NULL); + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, + esd->signerDigAlgoId, esd->signerDigAlgoIdSz); + digIdx += esd->signerDigAlgoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, + SHA_DIGEST_SIZE); + digIdx += SHA_DIGEST_SIZE; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, 0, NULL); + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + result = wc_InitRsaKey(privKey, NULL); + if (result == 0) + result = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey, + pkcs7->privateKeySz); + if (result < 0) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, 0, NULL); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + result = wc_RsaSSL_Sign(digestInfo, digIdx, + esd->encContentDigest, + sizeof(esd->encContentDigest), + privKey, pkcs7->rng); + + wc_FreeRsaKey(privKey); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (result < 0) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, 0, NULL); +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return result; + } + esd->encContentDigestSz = (word32)result; + } + 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, + hashType, 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, 0, NULL); +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, 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 (pkcs7->signedAttribsSz != 0) { + XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz); + idx += esd->signedAttribSetSz; + XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); + idx += flatSignedAttribsSz; + XFREE(flatSignedAttribs, 0, NULL); + } + + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + + +/* Finds the certificates in the message and saves it. */ +int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) +{ + word32 idx, contentType; + int length, version, ret; + byte* content = NULL; + byte* sig = NULL; + byte* cert = NULL; + int contentSz = 0, sigSz = 0, certSz = 0; + + 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; + + /* 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) < 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; + + /* 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; + } + + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (pkiMsg[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Save the inner data as the content. */ + if (length > 0) { + /* Local pointer for calculating hashes later */ + pkcs7->content = content = &pkiMsg[idx]; + pkcs7->contentSz = contentSz = length; + idx += length; + } + + /* 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); + } + wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + } + idx += length; + } + + /* 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) < 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 (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Skip it */ + idx += length; + + /* 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; + + idx += length; + } + + /* Get the sequence of digestEncryptionAlgorithm */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Skip it */ + idx += length; + + /* 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; + + { + word32 scratch = 0; + int plainSz = 0; + #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\ + MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE) + +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + RsaKey* key; + + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + RsaKey stack_key; + RsaKey* key = &stack_key; +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_InitRsaKey(key, NULL); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, + pkcs7->publicKeySz) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + plainSz = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, + key); + wc_FreeRsaKey(key); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (plainSz < 0) + return plainSz; + } + } + + return 0; +} + + +/* create ASN.1 formatted RecipientInfo structure, returns sequence size */ +WOLFSSL_LOCAL 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) +{ + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (decoded == NULL || serial == NULL || keyAlgArray == NULL) { + if (serial) XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (keyAlgArray) XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded) XFREE(decoded, NULL, 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, 0); + ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return -1; + } + snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial); + + issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, + issuerSerialSeq); + + /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ + if (keyEncAlgo != RSAk) { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ALGO_ID_E; + } + + keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0); + if (keyEncAlgSz == 0) { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pubKey == NULL) { + FreeDecodedCert(decoded); + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + /* EncryptedKey */ + ret = wc_InitRsaKey(pubKey, 0); + if (ret != 0) { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (*keyEncSz < 0) { + WOLFSSL_MSG("RSA Public Encrypt failed"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return totalSz; +} + + +/* build PKCS#7 envelopedData content type, return enveloped size */ +int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + int i, ret, idx = 0; + int totalSz, padSz, desOutSz; + + 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, 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[DES_BLOCK_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) + return BAD_FUNC_ARG; + + if (output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + /* PKCS#7 only supports DES, 3DES for now */ + switch (pkcs7->encryptOID) { + case DESb: + blockKeySz = DES_KEYLEN; + break; + + case DES3b: + blockKeySz = DES3_KEYLEN; + break; + + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + + /* outer content type */ + outerContentTypeSz = wc_SetContentType(ENVELOPED_DATA, outerContentType); + + /* version, defined as 0 in RFC 2315 */ + verSz = SetMyVersion(0, ver, 0); + + /* generate random content encryption key */ + ret = wc_InitRng(&rng); + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + contentKeyEnc = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (contentKeyEnc == NULL || recip == NULL) { + if (recip) XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (contentKeyEnc) XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRng(&rng); + return MEMORY_E; + } + +#endif + + /* build RecipientInfo, only handle 1 for now */ + recipSz = wc_CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk, + blockKeySz, &rng, contentKeyPlain, + contentKeyEnc, &contentKeyEncSz, recip, + MAX_RECIP_SZ); + + ForceZero(contentKeyEnc, MAX_ENCRYPTED_KEY_SZ); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (recipSz < 0) { + WOLFSSL_MSG("Failed to create RecipientInfo"); + wc_FreeRng(&rng); +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + return recipSz; + } + recipSetSz = SetSet(recipSz, recipSet); + + /* generate IV for block cipher */ + ret = wc_RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE); + wc_FreeRng(&rng); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* EncryptedContentInfo */ + contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); + if (contentTypeSz == 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + /* allocate encrypted content buffer and PKCS#7 padding */ + padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE); + desOutSz = pkcs7->contentSz + padSz; + + plain = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (plain == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + XMEMCPY(plain, pkcs7->content, pkcs7->contentSz); + + for (i = 0; i < padSz; i++) { + plain[pkcs7->contentSz + i] = (byte)padSz; + } + + encryptedContent = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedContent == NULL) { + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString); + + /* build up our ContentEncryptionAlgorithmIdentifier sequence, + * adding (ivOctetStringSz + DES_BLOCK_SIZE) for IV OCTET STRING */ + contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + blkType, ivOctetStringSz + DES_BLOCK_SIZE); + + if (contentEncAlgoSz == 0) { + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + /* encrypt content */ + if (pkcs7->encryptOID == DESb) { + Des des; + + ret = wc_Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION); + + if (ret == 0) + wc_Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz); + + if (ret != 0) { + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + } + else if (pkcs7->encryptOID == DES3b) { + Des3 des3; + + ret = wc_Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION); + + if (ret == 0) + ret = wc_Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz); + + if (ret != 0) { + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + } + + encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, + desOutSz, encContentOctet); + + encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + ivOctetStringSz + DES_BLOCK_SIZE + + encContentOctetSz + desOutSz, encContentSeq); + + /* keep track of sizes for outer wrapper layering */ + totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + + contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE + + encContentOctetSz + desOutSz; + + /* 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_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, DES_BLOCK_SIZE); + idx += DES_BLOCK_SIZE; + XMEMCPY(output + idx, encContentOctet, encContentOctetSz); + idx += encContentOctetSz; + XMEMCPY(output + idx, encryptedContent, desOutSz); + idx += desOutSz; + + ForceZero(contentKeyPlain, MAX_CONTENT_KEY_LEN); + + XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + +/* 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 savedIdx = 0, idx = 0; + word32 contentType, encOID; + byte issuerHash[SHA_DIGEST_SIZE]; + + int encryptedKeySz, keySz; + byte tmpIv[DES_BLOCK_SIZE]; + byte* decryptedKey = NULL; + +#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 + int encryptedContentSz; + byte padLen; + byte* encryptedContent = NULL; + + if (pkcs7 == NULL || pkcs7->singleCert == NULL || + pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL || + pkcs7->privateKeySz == 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 (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) < 0) + return ASN_PARSE_E; + + if (version != 0) { + 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 + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey == NULL) + return MEMORY_E; +#endif + + savedIdx = idx; + recipFound = 0; + + /* 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) { + idx = savedIdx; + break; + } + + if (GetMyVersion(pkiMsg, &idx, &version) < 0) { + idx = savedIdx; + break; + } + + if (version != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_VERSION_E; + } + + /* remove IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + /* if we found correct recipient, issuer hashes will match */ + if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) { + recipFound = 1; + } + +#ifdef WOLFSSL_SMALL_STACK + serialNum = (mp_int*)XMALLOC(sizeof(mp_int), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (serialNum == NULL) { + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (GetInt(serialNum, pkiMsg, &idx, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serialNum, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + mp_clear(serialNum); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(serialNum, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (GetAlgoId(pkiMsg, &idx, &encOID, keyType, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + /* key encryption algorithm must be RSA for now */ + if (encOID != RSAk) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ALGO_ID_E; + } + + /* read encryptedKey */ + if (pkiMsg[idx++] != ASN_OCTET_STRING) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (recipFound == 1) + XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz); + idx += encryptedKeySz; + + /* update good idx */ + savedIdx = idx; + } + + if (recipFound == 0) { + WOLFSSL_MSG("No recipient found in envelopedData that matches input"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PKCS7_RECIP_E; + } + + /* remove EncryptedContentInfo */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (GetAlgoId(pkiMsg, &idx, &encOID, blkType, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if (pkiMsg[idx++] != ASN_OCTET_STRING) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (length != DES_BLOCK_SIZE) { + WOLFSSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + XMEMCPY(tmpIv, &pkiMsg[idx], length); + idx += length; + + /* read encryptedContent, cont[0] */ + if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + encryptedContent = (byte*)XMALLOC(encryptedContentSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedContent == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + + /* load private key */ +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) { + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; + } +#endif + + ret = wc_InitRsaKey(privKey, 0); + if (ret != 0) { + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + idx = 0; + + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + if (ret != 0) { + WOLFSSL_MSG("Failed to decode RSA private key"); + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* decrypt encryptedKey */ + keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, + &decryptedKey, privKey); + wc_FreeRsaKey(privKey); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (keySz <= 0) { + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return keySz; + } + + /* decrypt encryptedContent */ + if (encOID == DESb) { + Des des; + ret = wc_Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); + + if (ret == 0) + wc_Des_CbcDecrypt(&des, encryptedContent, encryptedContent, + encryptedContentSz); + + if (ret != 0) { + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + } + else if (encOID == DES3b) { + Des3 des; + ret = wc_Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); + if (ret == 0) + ret = wc_Des3_CbcDecrypt(&des, encryptedContent, encryptedContent, + encryptedContentSz); + + if (ret != 0) { + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + } else { + WOLFSSL_MSG("Unsupported content encryption OID type"); + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ALGO_ID_E; + } + + padLen = encryptedContent[encryptedContentSz-1]; + + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); + + /* free memory, zero out keys */ + ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return encryptedContentSz - padLen; +} + + +#else /* HAVE_PKCS7 */ + + +#ifdef _MSC_VER + /* 4206 warning for blank file */ + #pragma warning(disable: 4206) +#endif + + +#endif /* HAVE_PKCS7 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/poly1305.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,643 @@ +/* poly1305.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #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 + +#if 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 + + 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 POLY130564 + + const word64 hibit = (ctx->final) ? 0 : ((word64)1 << 40); /* 1 << 128 */ + word64 r0,r1,r2; + word64 s1,s2; + word64 h0,h1,h2; + word64 c; + word128 d0,d1,d2,d; + +#else + + const word32 hibit = (ctx->final) ? 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; + +#endif + +#ifdef POLY130564 + + 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 */ + + 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 */ +} + + +int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { + +#if defined(POLY130564) + word64 t0,t1; +#endif + +#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; + +#if 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); + +#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); + +#endif + + ctx->leftover = 0; + ctx->final = 0; + + return 0; +} + + +int wc_Poly1305Final(Poly1305* ctx, byte* mac) { + +#if 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; + +#if 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->final = 1; + poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); + } + + /* 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->final = 1; + poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); + } + + /* 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; + + /* 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_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE); + 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[8]; + + 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; + } + + if (additional == NULL && addSz > 0) { + return BAD_FUNC_ARG; + } + + /* additional data plus padding */ + if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { + return ret; + } + paddingLen = -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 = -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); + ret = wc_Poly1305Update(ctx, little64, sizeof(little64)); + if (ret) + { + return ret; + } + + U32TO64(sz, little64); + 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/pwdbased.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,564 @@ +/* pwdbased.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + +#ifdef WOLFSSL_PIC32MZ_HASH + #ifndef NO_MD5 + #define wc_InitMd5 wc_InitMd5_sw + #define wc_Md5Update wc_Md5Update_sw + #define wc_Md5Final wc_Md5Final_sw + #endif /* NO_MD5 */ + + #define wc_InitSha wc_InitSha_sw + #define wc_ShaUpdate wc_ShaUpdate_sw + #define wc_ShaFinal wc_ShaFinal_sw + + #define wc_InitSha256 wc_InitSha256_sw + #define wc_Sha256Update wc_Sha256Update_sw + #define wc_Sha256Final wc_Sha256Final_sw +#endif + +#include <wolfssl/wolfcrypt/pwdbased.h> +#include <wolfssl/wolfcrypt/hmac.h> +#include <wolfssl/wolfcrypt/integer.h> +#include <wolfssl/wolfcrypt/error-crypt.h> +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + #include <wolfssl/wolfcrypt/sha512.h> +#endif + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +#ifndef NO_SHA +/* PBKDF1 needs at least SHA available */ +int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, + int sLen, int iterations, int kLen, int hashType) +{ + Sha sha; +#ifndef NO_MD5 + Md5 md5; +#endif + int hLen = (int)SHA_DIGEST_SIZE; + int i, ret = 0; + byte buffer[SHA_DIGEST_SIZE]; /* max size */ + + if (hashType != MD5 && hashType != SHA) + return BAD_FUNC_ARG; + +#ifndef NO_MD5 + if (hashType == MD5) + hLen = (int)MD5_DIGEST_SIZE; +#endif + + if (kLen > hLen) + return BAD_FUNC_ARG; + + if (iterations < 1) + return BAD_FUNC_ARG; + + switch (hashType) { +#ifndef NO_MD5 + case MD5: + wc_InitMd5(&md5); + wc_Md5Update(&md5, passwd, pLen); + wc_Md5Update(&md5, salt, sLen); + wc_Md5Final(&md5, buffer); + break; +#endif /* NO_MD5 */ + case SHA: + default: + ret = wc_InitSha(&sha); + if (ret != 0) + return ret; + wc_ShaUpdate(&sha, passwd, pLen); + wc_ShaUpdate(&sha, salt, sLen); + wc_ShaFinal(&sha, buffer); + break; + } + + for (i = 1; i < iterations; i++) { + if (hashType == SHA) { + wc_ShaUpdate(&sha, buffer, hLen); + wc_ShaFinal(&sha, buffer); + } +#ifndef NO_MD5 + else { + wc_Md5Update(&md5, buffer, hLen); + wc_Md5Final(&md5, buffer); + } +#endif + } + XMEMCPY(output, buffer, kLen); + + return 0; +} +#endif /* NO_SHA */ + + +int GetDigestSize(int hashType) +{ + int hLen; + + switch (hashType) { +#ifndef NO_MD5 + case MD5: + hLen = MD5_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA + case SHA: + hLen = SHA_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA256 + case SHA256: + hLen = SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512: + hLen = SHA512_DIGEST_SIZE; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return hLen; +} + + +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; + Hmac hmac; +#ifdef WOLFSSL_SMALL_STACK + byte* buffer; +#else + byte buffer[MAX_DIGEST_SIZE]; +#endif + + hLen = GetDigestSize(hashType); + if (hLen < 0) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) + return MEMORY_E; +#endif + + ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); + + if (ret == 0) { + while (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++; + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#ifdef WOLFSSL_SHA512 + #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE +#elif !defined(NO_SHA256) + #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE +#else + #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE +#endif + +/* helper for wc_PKCS12_PBKDF(), sets block and digest sizes */ +int GetPKCS12HashSizes(int hashType, word32* v, word32* u) +{ + if (!v || !u) + return BAD_FUNC_ARG; + + switch (hashType) { +#ifndef NO_MD5 + case MD5: + *v = MD5_BLOCK_SIZE; + *u = MD5_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA + case SHA: + *v = SHA_BLOCK_SIZE; + *u = SHA_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA256 + case SHA256: + *v = SHA256_BLOCK_SIZE; + *u = SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512: + *v = SHA512_BLOCK_SIZE; + *u = SHA512_DIGEST_SIZE; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return 0; +} + +/* helper for PKCS12_PBKDF(), does hash operation */ +int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, + byte* Ai, word32 u, int iterations) +{ + int i; + int ret = 0; + + if (buffer == NULL || Ai == NULL) + return BAD_FUNC_ARG; + + switch (hashType) { +#ifndef NO_MD5 + case MD5: + { + Md5 md5; + wc_InitMd5(&md5); + wc_Md5Update(&md5, buffer, totalLen); + wc_Md5Final(&md5, Ai); + + for (i = 1; i < iterations; i++) { + wc_Md5Update(&md5, Ai, u); + wc_Md5Final(&md5, Ai); + } + } + break; +#endif /* NO_MD5 */ +#ifndef NO_SHA + case SHA: + { + Sha sha; + ret = wc_InitSha(&sha); + if (ret != 0) + break; + wc_ShaUpdate(&sha, buffer, totalLen); + wc_ShaFinal(&sha, Ai); + + for (i = 1; i < iterations; i++) { + wc_ShaUpdate(&sha, Ai, u); + wc_ShaFinal(&sha, Ai); + } + } + break; +#endif /* NO_SHA */ +#ifndef NO_SHA256 + case SHA256: + { + Sha256 sha256; + ret = wc_InitSha256(&sha256); + if (ret != 0) + break; + + ret = wc_Sha256Update(&sha256, buffer, totalLen); + if (ret != 0) + break; + + ret = wc_Sha256Final(&sha256, Ai); + if (ret != 0) + break; + + for (i = 1; i < iterations; i++) { + ret = wc_Sha256Update(&sha256, Ai, u); + if (ret != 0) + break; + + ret = wc_Sha256Final(&sha256, Ai); + if (ret != 0) + break; + } + } + break; +#endif /* NO_SHA256 */ +#ifdef WOLFSSL_SHA512 + case SHA512: + { + Sha512 sha512; + ret = wc_InitSha512(&sha512); + if (ret != 0) + break; + + ret = wc_Sha512Update(&sha512, buffer, totalLen); + if (ret != 0) + break; + + ret = wc_Sha512Final(&sha512, Ai); + if (ret != 0) + break; + + for (i = 1; i < iterations; i++) { + ret = wc_Sha512Update(&sha512, Ai, u); + if (ret != 0) + break; + + ret = wc_Sha512Final(&sha512, Ai); + if (ret != 0) + break; + } + } + break; +#endif /* WOLFSSL_SHA512 */ + + default: + ret = BAD_FUNC_ARG; + break; + } + + 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) +{ + /* 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[PBKDF_DIGEST_SIZE]; + byte B[PBKDF_DIGEST_SIZE]; +#endif + + if (!iterations) + iterations = 1; + + ret = GetPKCS12HashSizes(hashType, &v, &u); + if (ret < 0) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (Ai == NULL) + return MEMORY_E; + + B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (B == NULL) { + XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(Ai, 0, PBKDF_DIGEST_SIZE); + XMEMSET(B, 0, PBKDF_DIGEST_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, 0, DYNAMIC_TYPE_KEY); + if (buffer == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(B, NULL, 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, 0, DYNAMIC_TYPE_KEY); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#undef PBKDF_DIGEST_SIZE + +#endif /* NO_PWDBASED */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/rabbit.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,312 @@ +/* rabbit.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #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 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; +} + + +/* Key setup */ +int wc_RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv) +{ +#ifdef XSTREAM_ALIGN + 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 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) +{ +#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, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return 0; + #else + return BAD_ALIGN_E; + #endif + } +#endif /* XSTREAM_ALIGN */ + + return DoProcess(ctx, output, input, msglen); +} + + +#endif /* NO_RABBIT */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/random.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1513 @@ +/* random.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + +/* on HPUX 11 you may need to install /dev/random see + http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I + +*/ + +#include <wolfssl/wolfcrypt/random.h> + +#if defined(CUSTOM_RAND_GENERATE) && !defined(CUSTOM_RAND_TYPE) +/* To maintain compatibility the default return value from CUSTOM_RAND_GENERATE is byte */ +#define CUSTOM_RAND_TYPE byte +#endif + + +#ifdef HAVE_FIPS +int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) +{ + return GenerateSeed(os, seed, sz); +} + +#ifdef HAVE_CAVIUM + int wc_InitRngCavium(WC_RNG* rng, int i) + { + return InitRngCavium(rng, i); + } +#endif + + +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); +} + +#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + + 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 || NO_RC4 */ +#else /* else build without fips */ +#include <wolfssl/wolfcrypt/error-crypt.h> + +/* Allow custom RNG system */ +#ifdef CUSTOM_RAND_GENERATE_BLOCK + +int wc_InitRng(WC_RNG* rng) +{ + (void)rng; + return 0; +} + +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) +{ + (void)rng; + XMEMSET(output, 0, sz); + return CUSTOM_RAND_GENERATE_BLOCK(output, sz); +} + + +int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) +{ + return wc_RNG_GenerateBlock(rng, b, 1); +} + + +int wc_FreeRng(WC_RNG* rng) +{ + (void)rng; + return 0; +} + +#else + +/* Use HASHDRGB with SHA256 */ +#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + + #include <wolfssl/wolfcrypt/sha256.h> + + #ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> + #else + #include <wolfcrypt/src/misc.c> + #endif +#endif /* HAVE_HASHDRBG || NO_RC4 */ + +#if defined(USE_WINDOWS_API) + #ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0400 + #endif + #include <windows.h> + #include <wincrypt.h> +#else + #if !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ + !defined(WOLFSSL_GENSEED_FORTEST) && !defined(WOLFSSL_MDK_ARM) && \ + !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) + #include <fcntl.h> + #ifndef EBSNET + #include <unistd.h> + #endif + #else + /* include headers that may be needed to get good seed */ + #endif +#endif /* USE_WINDOWS_API */ + +#ifdef HAVE_INTEL_RDGEN + static int wc_InitRng_IntelRD(void) ; + #if defined(HAVE_HASHDRBG) || defined(NO_RC4) + static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz) ; + #else + static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) ; + #endif + static word32 cpuid_check = 0 ; + static word32 cpuid_flags = 0 ; + #define CPUID_RDRAND 0x4 + #define CPUID_RDSEED 0x8 + #define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) + #define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) +#endif + +#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + +/* Start NIST DRBG code */ + +#define OUTPUT_BLOCK_LEN (SHA256_DIGEST_SIZE) +#define MAX_REQUEST_LEN (0x10000) +#define RESEED_INTERVAL (1000000) +#define SECURITY_STRENGTH (256) +#define ENTROPY_SZ (SECURITY_STRENGTH/8) +#define NONCE_SZ (ENTROPY_SZ/2) +#define ENTROPY_NONCE_SZ (ENTROPY_SZ+NONCE_SZ) + +/* Internal return codes */ +#define DRBG_SUCCESS 0 +#define DRBG_ERROR 1 +#define DRBG_FAILURE 2 +#define DRBG_NEED_RESEED 3 +#define DRBG_CONT_FAILURE 4 + +/* RNG health states */ +#define DRBG_NOT_INIT 0 +#define DRBG_OK 1 +#define DRBG_FAILED 2 +#define DRBG_CONT_FAILED 3 + + +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]; + byte matchCount; +} 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) +{ + byte ctr; + int i; + int len; + word32 bits = (outSz * 8); /* reverse byte order */ + Sha256 sha; + byte digest[SHA256_DIGEST_SIZE]; + + (void)drbg; + #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++) + { + if (wc_InitSha256(&sha) != 0) + return DRBG_FAILURE; + + if (wc_Sha256Update(&sha, &ctr, sizeof(ctr)) != 0) + return DRBG_FAILURE; + + if (wc_Sha256Update(&sha, (byte*)&bits, sizeof(bits)) != 0) + return DRBG_FAILURE; + + /* churning V is the only string that doesn't have the type added */ + if (type != drbgInitV) + if (wc_Sha256Update(&sha, &type, sizeof(type)) != 0) + return DRBG_FAILURE; + + if (wc_Sha256Update(&sha, inA, inASz) != 0) + return DRBG_FAILURE; + + if (inB != NULL && inBSz > 0) + if (wc_Sha256Update(&sha, inB, inBSz) != 0) + return DRBG_FAILURE; + + if (wc_Sha256Final(&sha, digest) != 0) + return DRBG_FAILURE; + + 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, sizeof(digest)); + + return DRBG_SUCCESS; +} + + +/* 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; +} + +static 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) +{ + byte data[DRBG_SEED_LEN]; + int i; + int len; + word32 checkBlock; + Sha256 sha; + byte digest[SHA256_DIGEST_SIZE]; + + /* 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++) { + if (wc_InitSha256(&sha) != 0 || + wc_Sha256Update(&sha, data, sizeof(data)) != 0 || + wc_Sha256Final(&sha, digest) != 0) { + + return DRBG_FAILURE; + } + + 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 (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 if (out != NULL && outSz != 0) { + XMEMCPY(out, digest, outSz); + outSz = 0; + } + } + ForceZero(data, sizeof(data)); + + return DRBG_SUCCESS; +} + + +static 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 = DRBG_NEED_RESEED; + Sha256 sha; + byte digest[SHA256_DIGEST_SIZE]; + + if (drbg->reseedCtr != RESEED_INTERVAL) { + byte type = drbgGenerateH; + word32 reseedCtr = drbg->reseedCtr; + + ret = Hash_gen(drbg, out, outSz, drbg->V); + if (ret == DRBG_SUCCESS) { + if (wc_InitSha256(&sha) != 0 || + wc_Sha256Update(&sha, &type, sizeof(type)) != 0 || + wc_Sha256Update(&sha, drbg->V, sizeof(drbg->V)) != 0 || + wc_Sha256Final(&sha, digest) != 0) { + + ret = DRBG_FAILURE; + } + else { + array_add(drbg->V, sizeof(drbg->V), digest, sizeof(digest)); + 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, sizeof(digest)); + + return ret; +} + + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, + const byte* nonce, word32 nonceSz) +{ + int ret = DRBG_FAILURE; + + XMEMSET(drbg, 0, sizeof(DRBG)); + + 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; + + ForceZero(drbg, sizeof(DRBG)); + + for (i = 0; i < sizeof(DRBG); i++) + compareSum |= compareDrbg[i] ^ 0; + + return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + +/* End NIST DRBG Code */ + + +/* Get seed and key cipher */ +int wc_InitRng(WC_RNG* rng) +{ + int ret = BAD_FUNC_ARG; + + if (rng != NULL) { + if (wc_RNG_HealthTestLocal(0) == 0) { + byte entropy[ENTROPY_NONCE_SZ]; + + rng->drbg = + (struct DRBG*)XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG); + if (rng->drbg == NULL) { + ret = MEMORY_E; + } + /* This doesn't use a separate nonce. The entropy input will be + * the default size plus the size of the nonce making the seed + * size. */ + else if (wc_GenerateSeed(&rng->seed, + entropy, ENTROPY_NONCE_SZ) == 0 && + Hash_DRBG_Instantiate(rng->drbg, + entropy, ENTROPY_NONCE_SZ, NULL, 0) == DRBG_SUCCESS) { + + ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); + } + else + ret = DRBG_FAILURE; + + ForceZero(entropy, ENTROPY_NONCE_SZ); + } + 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; + } + } + + return ret; +} + + +/* place a generated block in output */ +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) +{ + int ret; + + if (rng == NULL || output == NULL || sz > MAX_REQUEST_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; + } + + 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 = BAD_FUNC_ARG; + + if (rng != NULL) { + if (rng->drbg != NULL) { + if (Hash_DRBG_Uninstantiate(rng->drbg) == DRBG_SUCCESS) + ret = 0; + else + ret = RNG_FAILURE_E; + + XFREE(rng->drbg, NULL, DYNAMIC_TYPE_RNG); + rng->drbg = NULL; + } + + rng->status = DRBG_NOT_INIT; + } + + return ret; +} + + +int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, + const byte* entropyB, word32 entropyBSz, + byte* output, word32 outputSz) +{ + DRBG drbg; + + if (entropyA == NULL || output == NULL) + return BAD_FUNC_ARG; + + if (reseed != 0 && entropyB == NULL) + return BAD_FUNC_ARG; + + if (outputSz != (SHA256_DIGEST_SIZE * 4)) + return -1; + + if (Hash_DRBG_Instantiate(&drbg, entropyA, entropyASz, NULL, 0) != 0) + return -1; + + if (reseed) { + if (Hash_DRBG_Reseed(&drbg, entropyB, entropyBSz) != 0) { + Hash_DRBG_Uninstantiate(&drbg); + return -1; + } + } + + if (Hash_DRBG_Generate(&drbg, output, outputSz) != 0) { + Hash_DRBG_Uninstantiate(&drbg); + return -1; + } + + if (Hash_DRBG_Generate(&drbg, output, outputSz) != 0) { + Hash_DRBG_Uninstantiate(&drbg); + return -1; + } + + if (Hash_DRBG_Uninstantiate(&drbg) != 0) { + return -1; + } + + return 0; +} + + +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, 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; + byte check[SHA256_DIGEST_SIZE * 4]; + + if (reseed) { + ret = wc_RNG_HealthTest(1, entropyA, sizeof(entropyA), + reseedEntropyA, sizeof(reseedEntropyA), + check, sizeof(check)); + if (ret == 0) { + if (ConstantCompare(check, outputA, sizeof(check)) != 0) + ret = -1; + } + } + else { + ret = wc_RNG_HealthTest(0, entropyB, sizeof(entropyB), + NULL, 0, + check, sizeof(check)); + if (ret == 0) { + if (ConstantCompare(check, outputB, sizeof(check)) != 0) + ret = -1; + } + } + + return ret; +} + + +#else /* HAVE_HASHDRBG || NO_RC4 */ + +/* Get seed and key cipher */ +int wc_InitRng(WC_RNG* rng) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + byte* key; + byte* junk; +#else + byte key[32]; + byte junk[256]; +#endif + +#ifdef HAVE_INTEL_RDGEN + wc_InitRng_IntelRD() ; + if(IS_INTEL_RDRAND)return 0 ; +#endif +#ifdef HAVE_CAVIUM + if (rng->magic == WOLFSSL_RNG_CAVIUM_MAGIC) + return 0; +#endif + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) + return MEMORY_E; + + junk = (byte*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (junk == NULL) { + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + ret = wc_GenerateSeed(&rng->seed, key, 32); + + if (ret == 0) { + wc_Arc4SetKey(&rng->cipher, key, sizeof(key)); + + ret = wc_RNG_GenerateBlock(rng, junk, 256); /*rid initial state*/ + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(junk, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#ifdef HAVE_CAVIUM + static void CaviumRNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz); +#endif + +/* place a generated block in output */ +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) +{ +#ifdef HAVE_INTEL_RDGEN + if(IS_INTEL_RDRAND) + return wc_GenerateRand_IntelRD(NULL, output, sz) ; +#endif +#ifdef HAVE_CAVIUM + if (rng->magic == WOLFSSL_RNG_CAVIUM_MAGIC) + return CaviumRNG_GenerateBlock(rng, output, sz); +#endif + XMEMSET(output, 0, sz); + wc_Arc4Process(&rng->cipher, output, output, sz); + + return 0; +} + + +int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) +{ + return wc_RNG_GenerateBlock(rng, b, 1); +} + + +int wc_FreeRng(WC_RNG* rng) +{ + (void)rng; + return 0; +} + + +#ifdef HAVE_CAVIUM + +#include <wolfssl/ctaocrypt/logging.h> +#include "cavium_common.h" + +/* Initialize RNG for use with Nitrox device */ +int wc_InitRngCavium(WC_RNG* rng, int devId) +{ + if (rng == NULL) + return -1; + + rng->devId = devId; + rng->magic = WOLFSSL_RNG_CAVIUM_MAGIC; + + return 0; +} + + +static void CaviumRNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) +{ + wolfssl_word offset = 0; + word32 requestId; + + while (sz > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, + rng->devId) != 0) { + WOLFSSL_MSG("Cavium RNG failed"); + } + sz -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + } + if (sz) { + word16 slen = (word16)sz; + if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, + rng->devId) != 0) { + WOLFSSL_MSG("Cavium RNG failed"); + } + } +} + +#endif /* HAVE_CAVIUM */ + +#endif /* HAVE_HASHDRBG || NO_RC4 */ + + +#if defined(HAVE_INTEL_RDGEN) + +#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) __cpuid((int*)a,b) + + #define XASM_LINK(f) + +#endif /* _MSC_VER */ + +#define EAX 0 +#define EBX 1 +#define ECX 2 +#define EDX 3 + +static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { + int got_intel_cpu=0; + unsigned int reg[5]; + + reg[4] = '\0' ; + cpuid(reg, 0, 0); + 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; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return((reg[num]>>bit)&0x1) ; + } + return 0 ; +} + +static int wc_InitRng_IntelRD() +{ + if(cpuid_check==0) { + if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ;} + if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ;} + cpuid_check = 1 ; + } + return 1 ; +} + +#define INTELRD_RETRY 10 + +#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + +/* return 0 on success */ +static INLINE int IntelRDseed32(unsigned int *seed) +{ + int rdseed; unsigned char ok ; + + __asm__ volatile("rdseed %0; setc %1":"=r"(rdseed), "=qm"(ok)); + if(ok){ + *seed = rdseed ; + return 0 ; + } else + return 1; +} + +/* return 0 on success */ +static INLINE int IntelRDseed32_r(unsigned int *rnd) +{ + int i ; + for(i=0; i<INTELRD_RETRY;i++) { + if(IntelRDseed32(rnd) == 0) return 0 ; + } + return 1 ; +} + +/* return 0 on success */ +static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz) +{ + (void) os ; + int ret ; + unsigned int rndTmp ; + + for( ; sz/4 > 0; sz-=4, output+=4) { + if(IS_INTEL_RDSEED)ret = IntelRDseed32_r((word32 *)output) ; + else return 1 ; + if(ret) + return 1 ; + } + if(sz == 0)return 0 ; + + if(IS_INTEL_RDSEED)ret = IntelRDseed32_r(&rndTmp) ; + else return 1 ; + if(ret) + return 1 ; + XMEMCPY(output, &rndTmp, sz) ; + return 0; +} + +#else + +/* return 0 on success */ +static INLINE int IntelRDrand32(unsigned int *rnd) +{ + int rdrand; unsigned char ok ; + __asm__ volatile("rdrand %0; setc %1":"=r"(rdrand), "=qm"(ok)); + if(ok){ + *rnd = rdrand; + return 0 ; + } else + return 1; +} + +/* return 0 on success */ +static INLINE int IntelRDrand32_r(unsigned int *rnd) +{ + int i ; + for(i=0; i<INTELRD_RETRY;i++) { + if(IntelRDrand32(rnd) == 0) return 0 ; + } + return 1 ; +} + +/* return 0 on success */ +static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) +{ + (void) os ; + int ret ; + unsigned int rndTmp; + + for( ; sz/4 > 0; sz-=4, output+=4) { + if(IS_INTEL_RDRAND)ret = IntelRDrand32_r((word32 *)output); + else return 1 ; + if(ret) + return 1 ; + } + if(sz == 0)return 0 ; + + if(IS_INTEL_RDRAND)ret = IntelRDrand32_r(&rndTmp); + else return 1 ; + if(ret) + return 1 ; + XMEMCPY(output, &rndTmp, sz) ; + return 0; +} +#endif /* defined(HAVE_HASHDRBG) || defined(NO_RC4) */ + +#endif /* HAVE_INTEL_RDGEN */ + + +/* 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(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(MICRIUM) + +int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) +{ + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + NetSecure_InitSeed(output, sz); + #endif + 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 + #define PIC32_SEED_COUNT ReadCoreTimer +#endif + #ifdef WOLFSSL_MIC32MZ_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 ; + + /* This part has to be replaced with better random seed */ + RNGNUMGEN1 = ReadCoreTimer(); + RNGPOLY1 = ReadCoreTimer(); + RNGPOLY2 = ReadCoreTimer(); + RNGNUMGEN2 = ReadCoreTimer(); +#ifdef DEBUG_WOLFSSL + printf("GenerateSeed::Seed=%08x, %08x\n", RNGNUMGEN1, RNGNUMGEN2) ; +#endif + RNGCONbits.PLEN = 0x40; + RNGCONbits.PRNGEN = 1; + for(i=0; i<5; i++) { /* wait for RNGNUMGEN ready */ + volatile int x ; + x = RNGNUMGEN1 ; + x = RNGNUMGEN2 ; + } + 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_MIC32MZ_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_MIC32MZ_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) + { + int 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_TRNG) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + TRNG_DRV_GetRandomData(TRNG_INSTANCE, output, sz); + return 0; + } + + + #elif defined(FREESCALE_RNGA) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz); + return 0; + } + + #else + #warning "write a real random seed!!!!, just for testing now" + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + for (i = 0; i < sz; i++ ) + output[i] = i; + + return 0; + } + #endif /* FREESCALE_K70_RNGA */ + +#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) \ + || defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) \ + || defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2)\ + || defined(WOLFSSL_GENSEED_FORTEST) + +#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; +} + +#elif defined(STM32F2_RNG) + #undef RNG + #include "stm32f2xx_rng.h" + #include "stm32f2xx_rcc.h" + /* + * wc_Generate a RNG seed using the hardware random number generator + * on the STM32F2. Documentation located in STM32F2xx Standard Peripheral + * Library document (See note in README). + */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + + /* enable RNG clock source */ + RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE); + + /* enable RNG peripheral */ + RNG_Cmd(ENABLE); + + for (i = 0; i < sz; i++) { + /* wait until RNG number is ready */ + while(RNG_GetFlagStatus(RNG_FLAG_DRDY)== RESET) { } + + /* get value */ + output[i] = RNG_GetRandomNumber(); + } + + return 0; + } +#elif defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || defined(MBED) + + #warning "write a real random seed!!!!, just for testing now" + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + + for (i = 0; i < sz; i++ ) + output[i] = i; + + return 0; + } + +#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_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(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(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; +} +*/ + + +#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; +} + + +#else /* !USE_WINDOWS_API && !HAVE_RPT_SYS && !MICRIUM && !NO_DEV_RANDOM */ + +/* may block */ +int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) +{ + int ret = 0; + + +#if defined(HAVE_INTEL_RDGEN) && (defined(HAVE_HASHDRBG) || defined(NO_RC4)) + wc_InitRng_IntelRD() ; /* set cpuid_flags if not yet */ + if(IS_INTEL_RDSEED) + return wc_GenerateSeed_IntelRD(NULL, output, sz) ; +#endif + + os->fd = open("/dev/urandom",O_RDONLY); + if (os->fd == -1) { + /* 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) { +#ifdef BLOCKING + sleep(0); /* context switch */ +#else + ret = RAN_BLOCK_E; + break; +#endif + } + } + close(os->fd); + + return ret; +} + +#endif /* USE_WINDOWS_API */ +#endif /* CUSTOM_RAND_GENERATE_BLOCK */ +#endif /* HAVE_FIPS */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/ripemd.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,356 @@ +/* ripemd.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + #include <wolfcrypt/src/misc.c> +#endif + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + +void wc_InitRipeMd(RipeMd* ripemd) +{ + 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; +} + + +/* 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 INLINE void AddLength(RipeMd* ripemd, word32 len) +{ + word32 tmp = ripemd->loLen; + if ( (ripemd->loLen += len) < tmp) + ripemd->hiLen++; /* carry low to high */ +} + + +void wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len) +{ + /* do block size increments */ + byte* 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; + } + } +} + + +void wc_RipeMdFinal(RipeMd* ripemd, byte* hash) +{ + byte* 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); + + wc_InitRipeMd(ripemd); /* reset state */ +} + + +#endif /* WOLFSSL_RIPEMD */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/rsa.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1525 @@ +/* rsa.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_RSA + +#include <wolfssl/wolfcrypt/rsa.h> + +#ifdef HAVE_FIPS +int wc_InitRsaKey(RsaKey* key, void* ptr) +{ + 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) +{ + return RsaPublicEncrypt_fips(in, inLen, out, outLen, key, rng); +} + + +int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, + RsaKey* key) +{ + return RsaPrivateDecryptInline_fips(in, inLen, out, key); +} + + +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + 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) +{ + return RsaSSL_Sign_fips(in, inLen, out, outLen, key, rng); +} + + +int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + return RsaSSL_VerifyInline_fips(in, inLen, out, key); +} + + +int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + return RsaSSL_Verify_fips(in, inLen, out, outLen, key); +} + + +int wc_RsaEncryptSize(RsaKey* key) +{ + 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 + + +#ifdef HAVE_CAVIUM + int wc_RsaInitCavium(RsaKey* key, int i) + { + return RsaInitCavium(key, i); + } + + + void wc_RsaFreeCavium(RsaKey* key) + { + RsaFreeCavium(key); + } +#endif + +/* these are functions in asn and are routed to wolfssl/wolfcrypt/asn.c +* wc_RsaPrivateKeyDecode +* wc_RsaPublicKeyDecode +*/ + +#else /* else build without fips */ +#include <wolfssl/wolfcrypt/random.h> +#include <wolfssl/wolfcrypt/error-crypt.h> +#include <wolfssl/wolfcrypt/logging.h> +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + +#ifdef HAVE_CAVIUM + static int InitCaviumRsaKey(RsaKey* key, void* heap); + static int FreeCaviumRsaKey(RsaKey* key); + static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); + static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); + static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); + static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); +#endif + +enum { + 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 */ +}; + + +int wc_InitRsaKey(RsaKey* key, void* heap) +{ +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return InitCaviumRsaKey(key, heap); +#endif + + key->type = -1; /* haven't decided yet */ + key->heap = heap; + +/* TomsFastMath doesn't use memory allocation */ +#ifndef USE_FAST_MATH + key->n.dp = key->e.dp = 0; /* public alloc parts */ + + key->d.dp = key->p.dp = 0; /* private alloc parts */ + key->q.dp = key->dP.dp = 0; + key->u.dp = key->dQ.dp = 0; +#else + mp_init(&key->n); + mp_init(&key->e); + mp_init(&key->d); + mp_init(&key->p); + mp_init(&key->q); + mp_init(&key->dP); + mp_init(&key->dQ); + mp_init(&key->u); +#endif + + return 0; +} + + +int wc_FreeRsaKey(RsaKey* key) +{ + (void)key; + + if (key == NULL) + return 0; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return FreeCaviumRsaKey(key); +#endif + +/* TomsFastMath doesn't use memory allocation */ +#ifndef USE_FAST_MATH + if (key->type == RSA_PRIVATE) { + mp_clear(&key->u); + mp_clear(&key->dQ); + mp_clear(&key->dP); + mp_clear(&key->q); + mp_clear(&key->p); + mp_clear(&key->d); + } + mp_clear(&key->e); + mp_clear(&key->n); +#else + /* still clear private key memory information when free'd */ + if (key->type == RSA_PRIVATE) { + mp_clear(&key->u); + mp_clear(&key->dQ); + mp_clear(&key->u); + mp_clear(&key->dP); + mp_clear(&key->q); + mp_clear(&key->p); + mp_clear(&key->d); + } +#endif + + return 0; +} + + +#ifndef WC_NO_RSA_OAEP +/* 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 wc_MGF1(enum wc_HashType hType, byte* seed, word32 seedSz, + byte* out, word32 outSz) +{ + 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; + + /* 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, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return 0; +} + + +/* helper function to direct which mask generation function is used + switeched on type input + */ +static int wc_MGF(int type, byte* seed, word32 seedSz, + byte* out, word32 outSz) +{ + int ret; + + switch(type) { + #ifndef NO_SHA + case WC_MGF1SHA1: + ret = wc_MGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz); + break; + #endif + #ifndef NO_SHA256 + case WC_MGF1SHA256: + ret = wc_MGF1(WC_HASH_TYPE_SHA256, seed, seedSz, out, outSz); + break; + #endif + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_MGF1SHA384: + ret = wc_MGF1(WC_HASH_TYPE_SHA384, seed, seedSz, out, outSz); + break; + #endif + case WC_MGF1SHA512: + ret = wc_MGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz); + break; + #endif + default: + WOLFSSL_MSG("Unknown MGF function: check build options"); + ret = BAD_FUNC_ARG; + } + + /* in case of default avoid unused warning */ + (void)seed; + (void)seedSz; + (void)out; + (void)outSz; + + return ret; +} + + +static int wc_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) +{ + 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 + + /* can use with no lable but catch if no lable provided while having + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (lHash == NULL) { + return MEMORY_E; + } + seed = (byte*)XMALLOC(hLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (seed == NULL) { + XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_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 aproaches 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + /* create maskedDB from dbMask */ + dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, NULL, DYNAMIC_TYPE_RSA); + if (dbMask == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + XMEMSET(dbMask, 0, pkcsBlockLen - hLen - 1); /* help static analyzer */ + + ret = wc_MGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1); + if (ret != 0) { + XFREE(dbMask, NULL, DYNAMIC_TYPE_RSA); + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_RSA); + + + /* create maskedSeed from seedMask */ + idx = 0; + pkcsBlock[idx++] = 0x00; + /* create seedMask inline */ + if ((ret = wc_MGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1, + pkcsBlock + 1, hLen)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + (void)padValue; + + return 0; +} +#endif /* WC_NO_RSA_OAEP */ + + +static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng) +{ + if (inputLen == 0) + return 0; + + pkcsBlock[0] = 0x0; /* set first byte to zero and advance */ + pkcsBlock++; pkcsBlockLen--; + pkcsBlock[0] = padValue; /* insert padValue */ + + if (padValue == RSA_BLOCK_TYPE_1) + /* pad with 0xff bytes */ + XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); + else { + /* pad with non-zero random bytes */ + word32 padLen = pkcsBlockLen - inputLen - 1, i; + int 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; +} + + +#ifndef WC_NO_RSA_OAEP +/* 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 ret; + + switch (padType) + { + case WC_RSA_PKCSV15_PAD: + WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + ret = wc_RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen, + padValue, rng); + break; + + case WC_RSA_OAEP_PAD: + WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + ret = wc_RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen, + padValue, rng, hType, mgf, optLabel, labelLen); + break; + + default: + WOLFSSL_MSG("Unknown RSA Pad Type"); + ret = RSA_PAD_E; + } + + /* silence warning if not used with padding scheme */ + (void)padType; + (void)hType; + (void)mgf; + (void)optLabel; + (void)labelLen; + + return ret; +} + + +/* UnPad plaintext, set start to *output, return length of plaintext, + * < 0 on error */ +static int wc_RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, enum wc_HashType hType, int mgf, + byte* optLabel, word32 labelLen) +{ + int hLen; + int ret; + byte h[WC_MAX_DIGEST_SIZE]; /* max digest size */ + byte* tmp; + word32 idx; + + hLen = wc_HashGetDigestSize(hType); + if ((hLen < 0) || (pkcsBlockLen < (2 * (word32)hLen + 2))) { + return BAD_FUNC_ARG; + } + + tmp = (byte*)XMALLOC(pkcsBlockLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + XMEMSET(tmp, 0, pkcsBlockLen); + + /* find seedMask value */ + if ((ret = wc_MGF(mgf, (byte*)(pkcsBlock + (hLen + 1)), + pkcsBlockLen - hLen - 1, tmp, hLen)) != 0) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_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 = wc_MGF(mgf, tmp, hLen, tmp + hLen, + pkcsBlockLen - hLen - 1)) != 0) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* advance idx to index of PS and msg separator */ + idx = hLen + 2 + hLen; + while (idx < pkcsBlockLen && pkcsBlock[idx] == 0) {idx++;} + + /* create hash of label for comparision 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) { + 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 */ + + +/* 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, + invalid = 0, + i = 1, + outputLen; + + 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, bad formatting"); + return RSA_PAD_E; + } + + *output = (byte *)(pkcsBlock + i); + return outputLen; +} + + +#ifndef WC_NO_RSA_OAEP +/* helper function to direct unpadding */ +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 ret; + + switch (padType) + { + case WC_RSA_PKCSV15_PAD: + WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue); + break; + + case WC_RSA_OAEP_PAD: + WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + ret = wc_RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, + hType, mgf, optLabel, labelLen); + break; + + default: + WOLFSSL_MSG("Unknown RSA Pad Type"); + ret = RSA_PAD_E; + } + + /* silence warning if not used with padding scheme */ + (void)padType; + (void)hType; + (void)mgf; + (void)optLabel; + (void)labelLen; + + return ret; +} +#endif /* WC_NO_RSA_OAEP */ + + +static int wc_RsaFunction(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key) +{ + #define ERROR_OUT(x) { ret = (x); goto done;} + + mp_int tmp; + int ret = 0; + word32 keyLen, len; + + if (mp_init(&tmp) != MP_OKAY) + return MP_INIT_E; + + if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY) + ERROR_OUT(MP_READ_E); + + if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { + #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ + if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY) + ERROR_OUT(MP_EXPTMOD_E); + #else + #define INNER_ERROR_OUT(x) { ret = (x); goto inner_done; } + + mp_int tmpa, tmpb; + + if (mp_init(&tmpa) != MP_OKAY) + ERROR_OUT(MP_INIT_E); + + if (mp_init(&tmpb) != MP_OKAY) { + mp_clear(&tmpa); + ERROR_OUT(MP_INIT_E); + } + + /* tmpa = tmp^dP mod p */ + if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY) + INNER_ERROR_OUT(MP_EXPTMOD_E); + + /* tmpb = tmp^dQ mod q */ + if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY) + INNER_ERROR_OUT(MP_EXPTMOD_E); + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY) + INNER_ERROR_OUT(MP_SUB_E); + + if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY) + INNER_ERROR_OUT(MP_MULMOD_E); + + /* tmp = tmpb + q * tmp */ + if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY) + INNER_ERROR_OUT(MP_MUL_E); + + if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY) + INNER_ERROR_OUT(MP_ADD_E); + + inner_done: + mp_clear(&tmpa); + mp_clear(&tmpb); + + if (ret != 0) return ret; + + #endif /* RSA_LOW_MEM */ + } + else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) { + if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY) + ERROR_OUT(MP_EXPTMOD_E); + } + else + ERROR_OUT(RSA_WRONG_TYPE_E); + + keyLen = mp_unsigned_bin_size(&key->n); + if (keyLen > *outLen) + ERROR_OUT(RSA_BUFFER_E); + + 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) + ERROR_OUT(MP_TO_E); + +done: + mp_clear(&tmp); + if (ret == MP_EXPTMOD_E) { + WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); + } + return ret; +} + + +int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + int sz, ret; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key); +#endif + + sz = mp_unsigned_bin_size(&key->n); + if (sz > (int)outLen) + return RSA_BUFFER_E; + + if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) + return RSA_BUFFER_E; + + ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng); + if (ret != 0) + return ret; + + if ((ret = wc_RsaFunction(out, sz, out, &outLen, + RSA_PUBLIC_ENCRYPT, key)) < 0) + sz = ret; + + return sz; +} + + +#ifndef WC_NO_RSA_OAEP +/* 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 + type : type of padding to use ie WC_RSA_OAEP_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 */ +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) +{ + int sz, ret; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key); +#endif + + sz = mp_unsigned_bin_size(&key->n); + if (sz > (int)outLen) + return RSA_BUFFER_E; + + if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) + return RSA_BUFFER_E; + + ret = wc_RsaPad_ex(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng, + type, hash, mgf, label, labelSz); + if (ret != 0) + return ret; + + if ((ret = wc_RsaFunction(out, sz, out, &outLen, + RSA_PUBLIC_ENCRYPT, key)) < 0) + sz = ret; + + return sz; +} +#endif /* WC_NO_RSA_OAEP */ + + +int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + int ret; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { + ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key); + if (ret > 0) + *out = in; + return ret; + } +#endif + + if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key)) + < 0) { + return ret; + } + + return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2); +} + + +#ifndef WC_NO_RSA_OAEP +/* Gives the option of choosing padding type + in : input to be decrypted + inLen: length of input buffer + out: pointer to place of decrypted message + key : wolfSSL initialized RSA key struct + type : type of padding to use ie WC_RSA_OAEP_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 */ +int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out, + RsaKey* key, int type, enum wc_HashType hash, int mgf, + byte* label, word32 labelSz) +{ + int ret; + + /* sanity check on arguments */ + if (in == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + /* check if given a label size but not given a label buffer */ + if (label == NULL && labelSz > 0) { + return BAD_FUNC_ARG; + } + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { + ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key); + if (ret > 0) + *out = in; + return ret; + } +#endif + + if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key)) + < 0) { + return ret; + } + + return wc_RsaUnPad_ex(in, inLen, out, RSA_BLOCK_TYPE_2, type, hash, mgf, + label, labelSz); +} +#endif /* WC_NO_RSA_OAEP */ + + +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + int plainLen; + byte* tmp; + byte* pad = 0; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); +#endif + + tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); + if (tmp == NULL) { + return MEMORY_E; + } + + XMEMCPY(tmp, in, inLen); + + if ( (plainLen = wc_RsaPrivateDecryptInline(tmp, inLen, &pad, key) ) < 0) { + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + return plainLen; + } + if (plainLen > (int)outLen) + plainLen = BAD_FUNC_ARG; + else + XMEMCPY(out, pad, plainLen); + + ForceZero(tmp, inLen); + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + + return plainLen; +} + + +#ifndef WC_NO_RSA_OAEP +/* 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 + key : wolfSSL initialized RSA key struct + type : type of padding to use ie WC_RSA_OAEP_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 */ +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) +{ + int plainLen; + byte* tmp; + byte* pad = 0; + + /* sanity check on arguments */ + if (out == NULL || in == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + /* check if given a label size but not given a label buffer */ + if (label == NULL && labelSz > 0) { + return BAD_FUNC_ARG; + } + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); +#endif + + tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); + if (tmp == NULL) { + return MEMORY_E; + } + + XMEMCPY(tmp, in, inLen); + + if ( (plainLen = wc_RsaPrivateDecryptInline_ex(tmp, inLen, &pad, key, + type, hash, mgf, label, labelSz) ) < 0) { + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + return plainLen; + } + if (plainLen > (int)outLen || pad == NULL) + plainLen = BAD_FUNC_ARG; + else + XMEMCPY(out, pad, plainLen); + + ForceZero(tmp, inLen); + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + + return plainLen; +} +#endif /* WC_NO_RSA_OAEP */ + + +/* for Rsa Verify */ +int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + int ret; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { + ret = CaviumRsaSSL_Verify(in, inLen, in, inLen, key); + if (ret > 0) + *out = in; + return ret; + } +#endif + + if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key)) + < 0) { + return ret; + } + + return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1); +} + + +int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + int plainLen; + byte* tmp; + byte* pad = 0; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return CaviumRsaSSL_Verify(in, inLen, out, outLen, key); +#endif + + tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); + if (tmp == NULL) { + return MEMORY_E; + } + + XMEMCPY(tmp, in, inLen); + + if ( (plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key) ) < 0) { + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + return plainLen; + } + + if (plainLen > (int)outLen) + plainLen = BAD_FUNC_ARG; + else + XMEMCPY(out, pad, plainLen); + + ForceZero(tmp, inLen); + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + + return plainLen; +} + + +/* for Rsa Sign */ +int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + int sz, ret; + +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return CaviumRsaSSL_Sign(in, inLen, out, outLen, key); +#endif + + sz = mp_unsigned_bin_size(&key->n); + if (sz > (int)outLen) + return RSA_BUFFER_E; + + if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) + return RSA_BUFFER_E; + + ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng); + if (ret != 0) + return ret; + + if ((ret = wc_RsaFunction(out, sz, out, &outLen, + RSA_PRIVATE_ENCRYPT,key)) < 0) + sz = ret; + + return sz; +} + + +int wc_RsaEncryptSize(RsaKey* key) +{ +#ifdef HAVE_CAVIUM + if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) + return key->c_nSz; +#endif + return mp_unsigned_bin_size(&key->n); +} + +/* 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 > *nSz) + return RSA_BUFFER_E; + ret = mp_to_unsigned_bin(&key->e, e); + if (ret != MP_OKAY) + return ret; + *eSz = (word32)sz; + + sz = mp_unsigned_bin_size(&key->n); + 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; +} + +#ifdef WOLFSSL_KEY_GEN +/* 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; + + if (key == NULL || rng == NULL) + return BAD_FUNC_ARG; + + if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) + return BAD_FUNC_ARG; + + if (e < 3 || (e & 1) == 0) + return BAD_FUNC_ARG; + + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) + return err; + + err = mp_set_int(&tmp3, e); + + /* make p */ + if (err == MP_OKAY) { + do { + err = mp_rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */ + + if (err == MP_OKAY) + err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */ + + if (err == MP_OKAY) + err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(p-1, e) */ + } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divides p-1 */ + } + + /* make q */ + if (err == MP_OKAY) { + do { + err = mp_rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */ + + if (err == MP_OKAY) + err = mp_sub_d(&q, 1, &tmp1); /* tmp1 = q-1 */ + + if (err == MP_OKAY) + err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(q-1, e) */ + } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divides q-1 */ + } + + 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, &tmp2); /* tmp2 = p-1 */ + + if (err == MP_OKAY) + err = mp_lcm(&tmp1, &tmp2, &tmp1); /* tmp1 = lcm(p-1, q-1),last loop */ + + /* make key */ + if (err == MP_OKAY) + err = mp_set_int(&key->e, e); /* key->e = e */ + + if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */ + err = mp_invmod(&key->e, &tmp1, &key->d); + + if (err == MP_OKAY) + err = mp_mul(&p, &q, &key->n); /* key->n = pq */ + + if (err == MP_OKAY) + err = mp_sub_d(&p, 1, &tmp1); + + if (err == MP_OKAY) + err = mp_sub_d(&q, 1, &tmp2); + + if (err == MP_OKAY) + err = mp_mod(&key->d, &tmp1, &key->dP); + + if (err == MP_OKAY) + err = mp_mod(&key->d, &tmp2, &key->dQ); + + if (err == MP_OKAY) + err = mp_invmod(&q, &p, &key->u); + + 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(&tmp3); + mp_clear(&tmp2); + mp_clear(&tmp1); + mp_clear(&q); + mp_clear(&p); + + if (err != MP_OKAY) { + wc_FreeRsaKey(key); + return err; + } + + return 0; +} + + +#endif /* WOLFSSL_KEY_GEN */ + + +#ifdef HAVE_CAVIUM + +#include <wolfssl/wolfcrypt/logging.h> +#include "cavium_common.h" + +/* Initialize RSA for use with Nitrox device */ +int wc_RsaInitCavium(RsaKey* rsa, int devId) +{ + if (rsa == NULL) + return -1; + + if (CspAllocContext(CONTEXT_SSL, &rsa->contextHandle, devId) != 0) + return -1; + + rsa->devId = devId; + rsa->magic = WOLFSSL_RSA_CAVIUM_MAGIC; + + return 0; +} + + +/* Free RSA from use with Nitrox device */ +void wc_RsaFreeCavium(RsaKey* rsa) +{ + if (rsa == NULL) + return; + + CspFreeContext(CONTEXT_SSL, rsa->contextHandle, rsa->devId); + rsa->magic = 0; +} + + +/* Initialize cavium RSA key */ +static int InitCaviumRsaKey(RsaKey* key, void* heap) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + key->heap = heap; + key->type = -1; /* don't know yet */ + + key->c_n = NULL; + key->c_e = NULL; + key->c_d = NULL; + key->c_p = NULL; + key->c_q = NULL; + key->c_dP = NULL; + key->c_dQ = NULL; + key->c_u = NULL; + + key->c_nSz = 0; + key->c_eSz = 0; + key->c_dSz = 0; + key->c_pSz = 0; + key->c_qSz = 0; + key->c_dP_Sz = 0; + key->c_dQ_Sz = 0; + key->c_uSz = 0; + + return 0; +} + + +/* Free cavium RSA key */ +static int FreeCaviumRsaKey(RsaKey* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + XFREE(key->c_n, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_e, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_d, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_p, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_q, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_dP, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_dQ, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + XFREE(key->c_u, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); + + return InitCaviumRsaKey(key, key->heap); /* reset pointers */ +} + + +static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 requestId; + word32 ret; + + if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->c_nSz) + return -1; + + ret = CspPkcs1v15Enc(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_eSz, + (word16)inLen, key->c_n, key->c_e, (byte*)in, out, + &requestId, key->devId); + if (ret != 0) { + WOLFSSL_MSG("Cavium Enc BT2 failed"); + return -1; + } + return key->c_nSz; +} + + +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (c[0] << 8) | (c[1]); +} + + +static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 requestId; + word32 ret; + word16 outSz = (word16)outLen; + + if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) + return -1; + + ret = CspPkcs1v15CrtDec(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_q, + key->c_dQ, key->c_p, key->c_dP, key->c_u, + (byte*)in, &outSz, out, &requestId, key->devId); + if (ret != 0) { + WOLFSSL_MSG("Cavium CRT Dec BT2 failed"); + return -1; + } + ato16((const byte*)&outSz, &outSz); + + return outSz; +} + + +static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 requestId; + word32 ret; + + if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen < + (word32)key->c_nSz) + return -1; + + ret = CspPkcs1v15CrtEnc(CAVIUM_BLOCKING, BT1, key->c_nSz, (word16)inLen, + key->c_q, key->c_dQ, key->c_p, key->c_dP, key->c_u, + (byte*)in, out, &requestId, key->devId); + if (ret != 0) { + WOLFSSL_MSG("Cavium CRT Enc BT1 failed"); + return -1; + } + return key->c_nSz; +} + + +static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 requestId; + word32 ret; + word16 outSz = (word16)outLen; + + if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) + return -1; + + ret = CspPkcs1v15Dec(CAVIUM_BLOCKING, BT1, key->c_nSz, key->c_eSz, + key->c_n, key->c_e, (byte*)in, &outSz, out, + &requestId, key->devId); + if (ret != 0) { + WOLFSSL_MSG("Cavium Dec BT1 failed"); + return -1; + } + outSz = ntohs(outSz); + + return outSz; +} + + +#endif /* HAVE_CAVIUM */ + +#endif /* HAVE_FIPS */ +#endif /* NO_RSA */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/sha.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,443 @@ +/* sha.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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) + +#include <wolfssl/wolfcrypt/sha.h> +#include <wolfssl/wolfcrypt/logging.h> +#include <wolfssl/wolfcrypt/error-crypt.h> + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + int wc_InitSha(Sha* sha) + { + return InitSha_fips(sha); + } + + + int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) + { + return ShaUpdate_fips(sha, data, len); + } + + + int wc_ShaFinal(Sha* sha, byte* out) + { + return ShaFinal_fips(sha,out); + } + +#else /* else build without fips */ + +#if defined(WOLFSSL_TI_HASH) + /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */ +#else + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitSha wc_InitSha_sw +#define wc_ShaUpdate wc_ShaUpdate_sw +#define wc_ShaFinal wc_ShaFinal_sw +#endif + + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" + #define XTRANSFORM(S,B) Transform((S), (B)) +#else + #define XTRANSFORM(S,B) Transform((S)) +#endif + +#ifdef STM32F2_HASH +/* + * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ +#include "stm32f2xx.h" +#include "stm32f2xx_hash.h" + +int wc_InitSha(Sha* sha) +{ + /* STM32F2 struct notes: + * sha->buffer = first 4 bytes used to hold partial block if needed + * sha->buffLen = num bytes currently stored in sha->buffer + * sha->loLen = num bytes that have been written to STM32 FIFO + */ + XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + sha->buffLen = 0; + sha->loLen = 0; + + /* initialize HASH peripheral */ + HASH_DeInit(); + + /* configure algo used, algo mode, datatype */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + + return 0; +} + +int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +{ + word32 i = 0; + word32 fill = 0; + word32 diff = 0; + + /* if saved partial block is available */ + if (sha->buffLen) { + fill = 4 - sha->buffLen; + + /* if enough data to fill, fill and push to FIFO */ + if (fill <= len) { + XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); + HASH_DataIn(*(uint32_t*)sha->buffer); + + data += fill; + len -= fill; + sha->loLen += 4; + sha->buffLen = 0; + } else { + /* append partial to existing stored block */ + XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); + sha->buffLen += len; + return; + } + } + + /* write input block in the IN FIFO */ + for(i = 0; i < len; i += 4) + { + diff = len - i; + if ( diff < 4) { + /* store incomplete last block, not yet in FIFO */ + XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + XMEMCPY((byte*)sha->buffer, data, diff); + sha->buffLen = diff; + } else { + HASH_DataIn(*(uint32_t*)data); + data+=4; + } + } + + /* keep track of total data length thus far */ + sha->loLen += (len - sha->buffLen); + + return 0; +} + +int wc_ShaFinal(Sha* sha, byte* hash) +{ + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (sha->buffLen) { + HASH_DataIn(*(uint32_t*)sha->buffer); + sha->loLen += sha->buffLen; + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + sha->digest[0] = HASH->HR[0]; + sha->digest[1] = HASH->HR[1]; + sha->digest[2] = HASH->HR[2]; + sha->digest[3] = HASH->HR[3]; + sha->digest[4] = HASH->HR[4]; + + ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); + + XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + + return wc_InitSha(sha); /* reset state */ +} + +#else /* wc_ software implementation */ + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +int wc_InitSha(Sha* sha) +{ + int ret = 0; +#ifdef FREESCALE_MMCAU + ret = wolfSSL_CryptHwMutexLock(); + if(ret != 0) { + return ret; + } + cau_sha1_initialize_output(sha->digest); + wolfSSL_CryptHwMutexUnLock(); +#else + sha->digest[0] = 0x67452301L; + sha->digest[1] = 0xEFCDAB89L; + sha->digest[2] = 0x98BADCFEL; + sha->digest[3] = 0x10325476L; + sha->digest[4] = 0xC3D2E1F0L; +#endif + + sha->buffLen = 0; + sha->loLen = 0; + sha->hiLen = 0; + + return ret; +} + +#ifdef FREESCALE_MMCAU +static int Transform(Sha* sha, byte* data) +{ + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + cau_sha1_hash_n(data, 1, sha->digest); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; +} +#endif /* FREESCALE_MMCAU */ + +#ifndef FREESCALE_MMCAU + +#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)) + +/* (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(Sha* sha) +{ + word32 W[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; +} + +#endif /* FREESCALE_MMCAU */ + + +static INLINE void AddLength(Sha* sha, word32 len) +{ + word32 tmp = sha->loLen; + if ( (sha->loLen += len) < tmp) + sha->hiLen++; /* carry low to high */ +} + + +int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)sha->buffer; + + while (len) { + word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + + sha->buffLen += add; + data += add; + len -= add; + + if (sha->buffLen == SHA_BLOCK_SIZE) { +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + XTRANSFORM(sha, local); + AddLength(sha, SHA_BLOCK_SIZE); + sha->buffLen = 0; + } + } + + return 0; +} + + +int wc_ShaFinal(Sha* sha, byte* hash) +{ + byte* local = (byte*)sha->buffer; + + AddLength(sha, sha->buffLen); /* before adding pads */ + + local[sha->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha->buffLen > SHA_PAD_SIZE) { + XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen); + sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen; + +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + XTRANSFORM(sha, local); + sha->buffLen = 0; + } + XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen); + + /* put lengths in bits */ + sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + + (sha->hiLen << 3); + sha->loLen = sha->loLen << 3; + + /* store lengths */ +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); +#endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); + XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); + +#ifdef FREESCALE_MMCAU + /* Kinetis requires only these bytes reversed */ + ByteReverseWords(&sha->buffer[SHA_PAD_SIZE/sizeof(word32)], + &sha->buffer[SHA_PAD_SIZE/sizeof(word32)], + 2 * sizeof(word32)); +#endif + + XTRANSFORM(sha, local); +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); +#endif + XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + + return wc_InitSha(sha); /* reset state */ +} + +#endif /* STM32F2_HASH */ + + + +#endif /* HAVE_FIPS */ +#endif /* WOLFSSL_TI_HASH */ +#endif /* NO_SHA */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/sha256.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1741 @@ +/* sha256.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> +#include <wolfssl/wolfcrypt/sha256.h> + +#if !defined(NO_SHA256) +#ifdef HAVE_FIPS + +int wc_InitSha256(Sha256* sha) +{ + return InitSha256_fips(sha); +} + + +int wc_Sha256Update(Sha256* sha, const byte* data, word32 len) +{ + return Sha256Update_fips(sha, data, len); +} + + +int wc_Sha256Final(Sha256* sha, byte* out) +{ + return Sha256Final_fips(sha, out); +} + + +#else /* else build without fips */ + +#if !defined(NO_SHA256) && defined(WOLFSSL_TI_HASH) + /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */ +#else + +#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 + +#ifdef WOLFSSL_PIC32MZ_HASH +#define wc_InitSha256 wc_InitSha256_sw +#define wc_Sha256Update wc_Sha256Update_sw +#define wc_Sha256Final wc_Sha256Final_sw +#endif + +#ifdef HAVE_FIPS + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif + +#if defined(USE_INTEL_SPEEDUP) +#define HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX2 + +#if defined(DEBUG_XMM) +#include "stdio.h" +#endif + +#endif + +#if defined(HAVE_INTEL_AVX2) +#define HAVE_INTEL_RORX +#endif + + +/***** +Intel AVX1/AVX2 Macro Control Structure + +#define HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX2 + +#define HAVE_INTEL_RORX + + +int InitSha256(Sha256* sha256) { + Save/Recover XMM, YMM + ... +} + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform() ; Function prototype +#else + Transform() { } + 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() { + Stitched Message Sched/Round + } + +#elif defined(HAVE_INTEL_AVX2) + + #define YMM Instructions/inline asm + + int Transform() { + More granural Stitched Message Sched/Round + } + +*/ + + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +/* 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) __cpuid((int*)a,b) + + #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 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_RDRAND (cpuid_flags&CPUID_RDRAND) +#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) + +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; + unsigned int reg[5]; + + reg[4] = '\0' ; + cpuid(reg, 0, 0); + 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; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return((reg[num]>>bit)&0x1) ; + } + return 0 ; +} + +static int set_cpuid_flags(void) { + if(cpuid_check==0) { + 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 ; } + cpuid_check = 1 ; + return 0 ; + } + return 1 ; +} + + +/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ +static int Transform(Sha256* sha256); + +#if defined(HAVE_INTEL_AVX1) +static int Transform_AVX1(Sha256 *sha256) ; +#endif +#if defined(HAVE_INTEL_AVX2) +static int Transform_AVX2(Sha256 *sha256) ; +static int Transform_AVX1_RORX(Sha256 *sha256) ; +#endif + +static int (*Transform_p)(Sha256* sha256) /* = _Transform */; + +#define XTRANSFORM(sha256, B) (*Transform_p)(sha256) + +static void set_Transform(void) { + if(set_cpuid_flags())return ; + +#if defined(HAVE_INTEL_AVX2) + if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ + Transform_p = Transform_AVX1_RORX; return ; + Transform_p = Transform_AVX2 ; + /* for avoiding warning,"not used" */ + } +#endif +#if defined(HAVE_INTEL_AVX1) + Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : Transform) ; return ; +#endif + Transform_p = Transform ; return ; +} + +#else + #if defined(FREESCALE_MMCAU) + #define XTRANSFORM(sha256, B) Transform(sha256, B) + #else + #define XTRANSFORM(sha256, B) Transform(sha256) + #endif +#endif + +/* Dummy for saving MM_REGs on behalf of Transform */ +#if defined(HAVE_INTEL_AVX2)&& !defined(HAVE_INTEL_AVX1) +#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ + "%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15") +#elif defined(HAVE_INTEL_AVX1) +#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ + "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10",\ + "xmm11","xmm12","xmm13","xmm14","xmm15") +#else +#define SAVE_XMM_YMM +#endif + +#ifdef WOLFSSL_PIC32MZ_HASH +#define InitSha256 InitSha256_sw +#define Sha256Update Sha256Update_sw +#define Sha256Final Sha256Final_sw +#endif + +#include <wolfssl/wolfcrypt/logging.h> +#include <wolfssl/wolfcrypt/error-crypt.h> + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + +#ifdef FREESCALE_MMCAU + #include "cau_api.h" +#endif + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + + +int wc_InitSha256(Sha256* sha256) +{ + int ret = 0; + #ifdef FREESCALE_MMCAU + ret = wolfSSL_CryptHwMutexLock(); + if(ret != 0) { + return ret; + } + cau_sha256_initialize_output(sha256->digest); + wolfSSL_CryptHwMutexUnLock(); + #else + 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; + #endif + + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + set_Transform() ; /* choose best Transform function under this runtime environment */ +#endif + + return ret; +} + + +#if !defined(FREESCALE_MMCAU) +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 +}; + +#endif + +#if defined(FREESCALE_MMCAU) + +static int Transform(Sha256* sha256, byte* buf) +{ + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + cau_sha256_hash_n(buf, 1, sha256->digest); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; +} + +#endif /* FREESCALE_MMCAU */ + +#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 RND(a,b,c,d,e,f,g,h,i) \ + t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \ + t1 = Sigma0((a)) + Maj((a), (b), (c)); \ + (d) += t0; \ + (h) = t0 + t1; + +#if !defined(FREESCALE_MMCAU) +static int Transform(Sha256* sha256) +{ + word32 S[8], t0, t1; + int i; + +#ifdef WOLFSSL_SMALL_STACK + word32* W; + + W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; +#else + word32 W[64]; +#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 < 64; i++) + W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; + + for (i = 0; i < 64; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } + + /* Add the working vars back into digest state[] */ + for (i = 0; i < 8; i++) { + sha256->digest[i] += S[i]; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +#endif /* #if !defined(FREESCALE_MMCAU) */ + +static INLINE void AddLength(Sha256* sha256, word32 len) +{ + word32 tmp = sha256->loLen; + if ( (sha256->loLen += len) < tmp) + sha256->hiLen++; /* carry low to high */ +} + +int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) +{ + + /* do block size increments */ + byte* local = (byte*)sha256->buffer; + + SAVE_XMM_YMM ; /* for Intel AVX */ + + while (len) { + word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(&local[sha256->buffLen], data, add); + + sha256->buffLen += add; + data += add; + len -= add; + + if (sha256->buffLen == SHA256_BLOCK_SIZE) { + int ret; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, + SHA256_BLOCK_SIZE); + #endif + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + AddLength(sha256, SHA256_BLOCK_SIZE); + sha256->buffLen = 0; + } + } + + return 0; +} + +int wc_Sha256Final(Sha256* sha256, byte* hash) +{ + byte* local = (byte*)sha256->buffer; + int ret; + + SAVE_XMM_YMM ; /* for Intel AVX */ + + AddLength(sha256, sha256->buffLen); /* before adding pads */ + + local[sha256->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha256->buffLen > SHA256_PAD_SIZE) { + XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); + sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + #endif + + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + sha256->buffLen = 0; + } + XMEMSET(&local[sha256->buffLen], 0, 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) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); + XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, + sizeof(word32)); + + #if defined(FREESCALE_MMCAU) || 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 || IS_INTEL_AVX2) + #endif + ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], + &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], + 2 * sizeof(word32)); + #endif + + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + #if defined(LITTLE_ENDIAN_ORDER) + ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); + + return wc_InitSha256(sha256); /* reset state */ +} + + + + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +#define _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ;\ + d = sha256->digest[0]; __asm__ volatile("movl %0, %"#S_0::"r"(d):SSE_REGs) ;\ + d = sha256->digest[1]; __asm__ volatile("movl %0, %"#S_1::"r"(d):SSE_REGs) ;\ + d = sha256->digest[2]; __asm__ volatile("movl %0, %"#S_2::"r"(d):SSE_REGs) ;\ + d = sha256->digest[3]; __asm__ volatile("movl %0, %"#S_3::"r"(d):SSE_REGs) ;\ + d = sha256->digest[4]; __asm__ volatile("movl %0, %"#S_4::"r"(d):SSE_REGs) ;\ + d = sha256->digest[5]; __asm__ volatile("movl %0, %"#S_5::"r"(d):SSE_REGs) ;\ + d = sha256->digest[6]; __asm__ volatile("movl %0, %"#S_6::"r"(d):SSE_REGs) ;\ + d = sha256->digest[7]; __asm__ volatile("movl %0, %"#S_7::"r"(d):SSE_REGs) ;\ +} + +#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ; \ + __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ; sha256->digest[0] += d;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ; sha256->digest[1] += d;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ; sha256->digest[2] += d;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ; sha256->digest[3] += d;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ; sha256->digest[4] += d;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ; sha256->digest[5] += d;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ; sha256->digest[6] += d;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ; sha256->digest[7] += d;\ +} + + +#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + + + + +#define S_0 %r15d +#define S_1 %r10d +#define S_2 %r11d +#define S_3 %r12d +#define S_4 %r13d +#define S_5 %r14d +#define S_6 %ebx +#define S_7 %r9d + +#define SSE_REGs "%edi", "%ecx", "%esi", "%edx", "%ebx","%r8","%r9","%r10","%r11","%r12","%r13","%r14","%r15" + +#if defined(HAVE_INTEL_RORX) +#define RND_STEP_RORX_1(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $6, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ + +#define RND_STEP_RORX_2(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $11, %"#e",%%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ +__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ +__asm__ volatile("rorx $25, %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ + +#define RND_STEP_RORX_3(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ +__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ + +#define RND_STEP_RORX_4(a,b,c,d,e,f,g,h,i)\ +/*__asm__ volatile("movl %0, %%edx\n\t"::"m"(w_k):"%edx");*/\ +__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ +__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ +__asm__ volatile("rorx $2, %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ +__asm__ volatile("rorx $13, %"#a", %%edi\n\t":::"%edi",SSE_REGs);/* edi = a>>13 */\ + +#define RND_STEP_RORX_5(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("rorx $22, %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ +__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs);/* edi = (a>>2) ^ (a>>13) */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma0(a) */\ + +#define RND_STEP_RORX_6(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ +__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ +__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c*/\ +__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ + +#define RND_STEP_RORX_7(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ +__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ +__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ + +#define RND_STEP_RORX_8(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ +__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ +__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs); \ +__asm__ volatile("movl %r8d, "#h"\n\t"); + +#endif + +#define RND_STEP_1(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs);\ +__asm__ volatile("roll $26, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>6 */\ +__asm__ volatile("movl %"#e", %%edi\n\t":::"%edi",SSE_REGs);\ + +#define RND_STEP_2(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("roll $21, %%edi\n\t":::"%edi",SSE_REGs); /* edi = e>>11 */\ +__asm__ volatile("xorl %%edx, %%edi\n\t":::"%edx","%edi",SSE_REGs); /* edi = (e>>11) ^ (e>>6) */\ +__asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs); /* edx = e */\ +__asm__ volatile("roll $7, %%edx\n\t":::"%edx",SSE_REGs); /* edx = e>>25 */\ + +#define RND_STEP_3(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#f", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = f ^ g */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma1(e) */\ +__asm__ volatile("andl %"#e", %%esi\n\t":::"%esi",SSE_REGs); /* esi = (f ^ g) & e */\ +__asm__ volatile("xorl %"#g", %%esi\n\t":::"%esi",SSE_REGs); /* esi = Ch(e,f,g) */\ + +#define RND_STEP_4(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %0, %"#h"\n\t"::"r"(W_K[i]):SSE_REGs); /* h += w_k */\ +__asm__ volatile("addl %%edx, %"#h"\n\t":::"%edx",SSE_REGs); /* h = h + w_k + Sigma1(e) */\ +__asm__ volatile("movl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a */\ +__asm__ volatile("roll $30, %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = a>>2 */\ +__asm__ volatile("movl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a */\ +__asm__ volatile("roll $19, %%edi\n\t":::"%edi",SSE_REGs); /* edi = a>>13 */\ +__asm__ volatile("movl %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a */\ + +#define RND_STEP_5(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("roll $10, %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ +__asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs); /* edi = (a>>2) ^ (a>>13) */\ +__asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs);/* edx = Sigma0(a) */\ + +#define RND_STEP_6(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ +__asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ +__asm__ volatile("andl %"#c", %%edi\n\t":::"%edi",SSE_REGs); /* edi = (a | b) & c */\ +__asm__ volatile("movl %"#b", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b */\ + +#define RND_STEP_7(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl %%esi, %"#h"\n\t":::"%esi",SSE_REGs); /* h += Ch(e,f,g) */\ +__asm__ volatile("andl %"#a", %%r8d\n\t":::"%r8",SSE_REGs); /* r8d = b & a */\ +__asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj(a,b,c) */\ + +#define RND_STEP_8(a,b,c,d,e,f,g,h,i)\ +__asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ +__asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ + /* r8b = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */\ +__asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs);\ + /* r8b = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */\ +__asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ + /* h = h + w_k + Sigma1(e) + Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */ \ + +#define RND_X(a,b,c,d,e,f,g,h,i) \ + RND_STEP_1(a,b,c,d,e,f,g,h,i); \ + RND_STEP_2(a,b,c,d,e,f,g,h,i); \ + RND_STEP_3(a,b,c,d,e,f,g,h,i); \ + RND_STEP_4(a,b,c,d,e,f,g,h,i); \ + RND_STEP_5(a,b,c,d,e,f,g,h,i); \ + RND_STEP_6(a,b,c,d,e,f,g,h,i); \ + RND_STEP_7(a,b,c,d,e,f,g,h,i); \ + RND_STEP_8(a,b,c,d,e,f,g,h,i); + +#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + + +#define RND_1_3(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_1(a,b,c,d,e,f,g,h,i); \ + RND_STEP_2(a,b,c,d,e,f,g,h,i); \ + RND_STEP_3(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_4_6(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_4(a,b,c,d,e,f,g,h,i); \ + RND_STEP_5(a,b,c,d,e,f,g,h,i); \ + RND_STEP_6(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_7_8(a,b,c,d,e,f,g,h,i) {\ + RND_STEP_7(a,b,c,d,e,f,g,h,i); \ + RND_STEP_8(a,b,c,d,e,f,g,h,i); \ +} + +#define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + + +#define RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_1_3(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_4_6(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); +#define RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); +#define RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_6,S_7,S_0,S_1,S_2,S_3,S_4,S_5,_i); +#define RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_5,S_6,S_7,S_0,S_1,S_2,S_3,S_4,_i); +#define RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,_i); +#define RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_3,S_4,S_5,S_6,S_7,S_0,S_1,S_2,_i); +#define RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_2,S_3,S_4,S_5,S_6,S_7,S_0,S_1,_i); +#define RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); + +#define FOR(cnt, init, max, inc, loop) \ + __asm__ volatile("movl $"#init", %0\n\t"#loop":"::"m"(cnt):) +#define END(cnt, init, max, inc, loop) \ + __asm__ volatile("addl $"#inc", %0\n\tcmpl $"#max", %0\n\tjle "#loop"\n\t":"=m"(cnt)::) ; + +#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) __asm__ volatile("vpalignr $"#op4", %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPADDD(op1,op2,op3) __asm__ volatile("vpaddd %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSRLD(op1,op2,op3) __asm__ volatile("vpsrld $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSRLQ(op1,op2,op3) __asm__ volatile("vpsrlq $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSLLD(op1,op2,op3) __asm__ volatile("vpslld $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPOR(op1,op2,op3) __asm__ volatile("vpor %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPXOR(op1,op2,op3) __asm__ volatile("vpxor %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSHUFD(op1,op2,op3) __asm__ volatile("vpshufd $"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPSHUFB(op1,op2,op3) __asm__ volatile("vpshufb %"#op3", %"#op2", %"#op1:::XMM_REGs) + +#define MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, SHUF_00BA, SHUF_DC00,\ + a,b,c,d,e,f,g,h,_i)\ + RND_STEP_1(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP0, X3, X2, 4) ;\ + RND_STEP_2(a,b,c,d,e,f,g,h,_i);\ + VPADDD (XTMP0, XTMP0, X0) ;\ + RND_STEP_3(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ + RND_STEP_4(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1, 7) ;\ + RND_STEP_5(a,b,c,d,e,f,g,h,_i);\ + VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ + RND_STEP_6(a,b,c,d,e,f,g,h,_i);\ + VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ + RND_STEP_7(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1,18) ;\ + RND_STEP_8(a,b,c,d,e,f,g,h,_i);\ +\ + RND_STEP_1(h,a,b,c,d,e,f,g,_i+1);\ + VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ + RND_STEP_2(h,a,b,c,d,e,f,g,_i+1);\ + VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ + RND_STEP_3(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP1) ;\ + RND_STEP_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_5(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ + RND_STEP_6(h,a,b,c,d,e,f,g,_i+1);\ + VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ + RND_STEP_7(h,a,b,c,d,e,f,g,_i+1);\ + VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ + RND_STEP_8(h,a,b,c,d,e,f,g,_i+1);\ +\ + RND_STEP_1(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ + RND_STEP_2(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ + RND_STEP_3(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ + RND_STEP_4(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_5(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ + RND_STEP_6(g,h,a,b,c,d,e,f,_i+2);\ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ + RND_STEP_7(g,h,a,b,c,d,e,f,_i+2);\ + VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ + RND_STEP_8(g,h,a,b,c,d,e,f,_i+2);\ +\ + RND_STEP_1(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ + RND_STEP_2(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ + RND_STEP_3(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ + RND_STEP_4(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ + RND_STEP_5(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_6(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ + RND_STEP_7(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ + RND_STEP_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 MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, \ + XFER, SHUF_00BA, SHUF_DC00,a,b,c,d,e,f,g,h,_i)\ + RND_STEP_RORX_1(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP0, X3, X2, 4) ;\ + RND_STEP_RORX_2(a,b,c,d,e,f,g,h,_i);\ + VPADDD (XTMP0, XTMP0, X0) ;\ + RND_STEP_RORX_3(a,b,c,d,e,f,g,h,_i);\ + VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ + RND_STEP_RORX_4(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1, 7) ;\ + RND_STEP_RORX_5(a,b,c,d,e,f,g,h,_i);\ + VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ + RND_STEP_RORX_6(a,b,c,d,e,f,g,h,_i);\ + VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ + RND_STEP_RORX_7(a,b,c,d,e,f,g,h,_i);\ + VPSRLD (XTMP2, XTMP1,18) ;\ + RND_STEP_RORX_8(a,b,c,d,e,f,g,h,_i);\ +\ + RND_STEP_RORX_1(h,a,b,c,d,e,f,g,_i+1);\ + VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ + RND_STEP_RORX_2(h,a,b,c,d,e,f,g,_i+1);\ + VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ + RND_STEP_RORX_3(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP3, XTMP3, XTMP1) ;\ + RND_STEP_RORX_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_5(h,a,b,c,d,e,f,g,_i+1);\ + VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ + RND_STEP_RORX_6(h,a,b,c,d,e,f,g,_i+1);\ + VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ + RND_STEP_RORX_7(h,a,b,c,d,e,f,g,_i+1);\ + VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ + RND_STEP_RORX_8(h,a,b,c,d,e,f,g,_i+1);\ +\ + RND_STEP_RORX_1(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ + RND_STEP_RORX_2(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ + RND_STEP_RORX_3(g,h,a,b,c,d,e,f,_i+2);\ + VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ + RND_STEP_RORX_4(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_RORX_5(g,h,a,b,c,d,e,f,_i+2);\ + VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ + RND_STEP_RORX_6(g,h,a,b,c,d,e,f,_i+2);\ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ + RND_STEP_RORX_7(g,h,a,b,c,d,e,f,_i+2);\ + VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ + RND_STEP_RORX_8(g,h,a,b,c,d,e,f,_i+2);\ +\ + RND_STEP_RORX_1(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ + RND_STEP_RORX_2(f,g,h,a,b,c,d,e,_i+3);\ + VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ + RND_STEP_RORX_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_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_5(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP2, XTMP2, XTMP3) ;\ + RND_STEP_RORX_6(f,g,h,a,b,c,d,e,_i+3);\ + VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ + RND_STEP_RORX_7(f,g,h,a,b,c,d,e,_i+3);\ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ + RND_STEP_RORX_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 + + +#define W_K_from_buff\ + __asm__ volatile("vmovdqu %0, %%xmm4\n\t"\ + "vpshufb %%xmm13, %%xmm4, %%xmm4\n\t"\ + :: "m"(sha256->buffer[0]):"%xmm4") ;\ + __asm__ volatile("vmovdqu %0, %%xmm5\n\t"\ + "vpshufb %%xmm13, %%xmm5, %%xmm5\n\t"\ + ::"m"(sha256->buffer[4]):"%xmm5") ;\ + __asm__ volatile("vmovdqu %0, %%xmm6\n\t"\ + "vpshufb %%xmm13, %%xmm6, %%xmm6\n\t"\ + ::"m"(sha256->buffer[8]):"%xmm6") ;\ + __asm__ volatile("vmovdqu %0, %%xmm7\n\t"\ + "vpshufb %%xmm13, %%xmm7, %%xmm7\n\t"\ + ::"m"(sha256->buffer[12]):"%xmm7") ;\ + +#define _SET_W_K_XFER(reg, i)\ + __asm__ volatile("vpaddd %0, %"#reg", %%xmm9"::"m"(K[i]):XMM_REGs) ;\ + __asm__ volatile("vmovdqa %%xmm9, %0":"=m"(W_K[i])::XMM_REGs) ; + +#define SET_W_K_XFER(reg, i) _SET_W_K_XFER(reg, 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)\ +__asm__ volatile("vmovdqu %0, %"#mask1 ::"m"(mBYTE_FLIP_MASK[0])) ;\ +__asm__ volatile("vmovdqu %0, %"#mask2 ::"m"(mSHUF_00BA[0])) ;\ +__asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; + +#define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)\ + _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) + +#define X0 %xmm4 +#define X1 %xmm5 +#define X2 %xmm6 +#define X3 %xmm7 +#define X_ X0 + +#define XTMP0 %xmm0 +#define XTMP1 %xmm1 +#define XTMP2 %xmm2 +#define XTMP3 %xmm3 +#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 + +#define XMM_REGs /* Registers are saved in Sha256Update/Finel */ + /*"xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13" */ + +static int Transform_AVX1(Sha256* sha256) +{ + + word32 W_K[64] ; /* temp for W+K */ + + #if defined(DEBUG_XMM) + int i, j ; + word32 xmm[29][4*15] ; + #endif + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; + W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + SET_W_K_XFER(X0, 0) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + SET_W_K_XFER(X1, 4) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; + SET_W_K_XFER(X2, 8) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + SET_W_K_XFER(X3, 12) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; + SET_W_K_XFER(X0, 16) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + SET_W_K_XFER(X1, 20) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; + SET_W_K_XFER(X2, 24) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + SET_W_K_XFER(X3, 28) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; + SET_W_K_XFER(X0, 32) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + SET_W_K_XFER(X1, 36) ; + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; + SET_W_K_XFER(X2, 40) ; + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + SET_W_K_XFER(X3, 44) ; + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; + + SET_W_K_XFER(X0, 48) ; + SET_W_K_XFER(X1, 52) ; + SET_W_K_XFER(X2, 56) ; + SET_W_K_XFER(X3, 60) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #if defined(DEBUG_XMM) + for(i=0; i<29; i++) { + for(j=0; j<4*14; j+=4) + printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, + xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; + printf("\n") ; + } + + for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; + #endif + + return 0; +} + +#if defined(HAVE_INTEL_RORX) +static int Transform_AVX1_RORX(Sha256* sha256) +{ + + word32 W_K[64] ; /* temp for W+K */ + + #if defined(DEBUG_XMM) + int i, j ; + word32 xmm[29][4*15] ; + #endif + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; + W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + SET_W_K_XFER(X0, 0) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + SET_W_K_XFER(X1, 4) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; + SET_W_K_XFER(X2, 8) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + SET_W_K_XFER(X3, 12) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; + SET_W_K_XFER(X0, 16) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + SET_W_K_XFER(X1, 20) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; + SET_W_K_XFER(X2, 24) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + SET_W_K_XFER(X3, 28) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; + SET_W_K_XFER(X0, 32) ; + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + SET_W_K_XFER(X1, 36) ; + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; + SET_W_K_XFER(X2, 40) ; + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + SET_W_K_XFER(X3, 44) ; + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; + + SET_W_K_XFER(X0, 48) ; + SET_W_K_XFER(X1, 52) ; + SET_W_K_XFER(X2, 56) ; + SET_W_K_XFER(X3, 60) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #if defined(DEBUG_XMM) + for(i=0; i<29; i++) { + for(j=0; j<4*14; j+=4) + printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, + xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; + printf("\n") ; + } + + for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; + #endif + + return 0; +} +#endif /* HAVE_INTEL_RORX */ + +#endif /* HAVE_INTEL_AVX1 */ + + +#if defined(HAVE_INTEL_AVX2) + +#define _MOVE_to_REG(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" ":: "m"(mem):YMM_REGs) ; +#define _MOVE_to_MEM(mem, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" : "=m"(mem)::YMM_REGs) ; +#define _BYTE_SWAP(ymm, map) __asm__ volatile("vpshufb %0, %%"#ymm", %%"#ymm"\n\t"\ + :: "m"(map):YMM_REGs) ; +#define _MOVE_128(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"#map", %%"\ + #ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; +#define _MOVE_BYTE(ymm0, ymm1, map) __asm__ volatile("vpshufb %0, %%"#ymm1", %%"\ + #ymm0"\n\t":: "m"(map):YMM_REGs) ; +#define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrld $"#bits", %%"\ + #src", %%"#dest"\n\tvpslld $32-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ + #temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; +#define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrld $"#bits", %%"\ + #src", %%"#dest" ":::YMM_REGs) ; +#define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _ADD(dest, src1, src2) __asm__ volatile("vpaddd %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddd %0, %%"#src1", %%"\ + #dest" "::"m"(mem):YMM_REGs) ; +#define _BLEND(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ + #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; + +#define _EXTRACT_XMM_0(xmm, mem) __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_1(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_2(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_3(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_4(ymm, xmm, mem)\ + __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ;\ + __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_5(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_6(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_7(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; + +#define _SWAP_YMM_HL(ymm) __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ; +#define SWAP_YMM_HL(ymm) _SWAP_YMM_HL(ymm) + +#define MOVE_to_REG(ymm, mem) _MOVE_to_REG(ymm, mem) +#define MOVE_to_MEM(mem, ymm) _MOVE_to_MEM(mem, ymm) +#define BYTE_SWAP(ymm, map) _BYTE_SWAP(ymm, map) +#define MOVE_128(ymm0, ymm1, ymm2, map) _MOVE_128(ymm0, ymm1, ymm2, map) +#define MOVE_BYTE(ymm0, ymm1, map) _MOVE_BYTE(ymm0, ymm1, map) +#define XOR(dest, src1, src2) _XOR(dest, src1, src2) +#define OR(dest, src1, src2) _OR(dest, src1, src2) +#define ADD(dest, src1, src2) _ADD(dest, src1, src2) +#define ADD_MEM(dest, src1, mem) _ADD_MEM(dest, src1, mem) +#define BLEND(map, dest, src1, src2) _BLEND(map, dest, src1, src2) + +#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); +#define AVX2_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) +#define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) + +#define GAMMA0(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); \ + XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); XOR(dest, G_TEMP, dest) ; +#define GAMMA0_1(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); +#define GAMMA0_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); \ + XOR(dest, G_TEMP, dest) ; + +#define GAMMA1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); \ + XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); XOR(dest, G_TEMP, dest) ; +#define GAMMA1_1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); +#define GAMMA1_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); \ + XOR(dest, G_TEMP, dest) ; + +#define FEEDBACK1_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP1toW_I_2[0]) ; \ + BLEND(0x0c, W_I_2, YMM_TEMP0, W_I_2) ; +#define FEEDBACK2_to_W_I_2 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ; \ + MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAP2toW_I_2[0]) ; BLEND(0x30, W_I_2, YMM_TEMP0, W_I_2) ; +#define FEEDBACK3_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP3toW_I_2[0]) ; \ + BLEND(0xc0, W_I_2, YMM_TEMP0, W_I_2) ; + +#define FEEDBACK_to_W_I_7 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ;\ + MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAPtoW_I_7[0]) ; BLEND(0x80, W_I_7, YMM_TEMP0, W_I_7) ; + +#undef voitle + +#define W_I_16 ymm8 +#define W_I_15 ymm9 +#define W_I_7 ymm10 +#define W_I_2 ymm11 +#define W_I ymm12 +#define G_TEMP ymm13 +#define S_TEMP ymm14 +#define YMM_TEMP0 ymm15 +#define YMM_TEMP0x xmm15 +#define W_I_TEMP ymm7 +#define W_K_TEMP ymm15 +#define W_K_TEMPx xmm15 + +#define YMM_REGs /* Registers are saved in Sha256Update/Finel */ + /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ + + +#define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + +#define MOVE_7_to_15(w_i_15, w_i_7)\ + __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + +#define MOVE_I_to_7(w_i_7, w_i)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ + +#define MOVE_I_to_2(w_i_2, w_i)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ + +#define ROTATE_W(w_i_16, w_i_15, w_i_7, w_i_2, w_i)\ + MOVE_15_to_16(w_i_16, w_i_15, w_i_7) ; \ + MOVE_7_to_15(w_i_15, w_i_7) ; \ + MOVE_I_to_7(w_i_7, w_i) ; \ + MOVE_I_to_2(w_i_2, w_i) ;\ + +#define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d ;\ + __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[0] += d;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[1] += d;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[2] += d;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[3] += d;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[4] += d;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[5] += d;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[6] += d;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ;\ + sha256->digest[7] += d;\ +} + +#define _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + { word32 d[8] ;\ + __asm__ volatile("movl %"#S_0", %0":"=r"(d[0])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d[1])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d[2])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d[3])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d[4])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d[5])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d[6])::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d[7])::SSE_REGs) ;\ + printf("S[0..7]=%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);\ + __asm__ volatile("movl %0, %"#S_0::"r"(d[0]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_1::"r"(d[1]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_2::"r"(d[2]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_3::"r"(d[3]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_4::"r"(d[4]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_5::"r"(d[5]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_6::"r"(d[6]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_7::"r"(d[7]):SSE_REGs) ;\ +} + + +#define DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + +#define DumS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ + _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) + + + /* Byte swap Masks to ensure that rest of the words are filled with zero's. */ + static const unsigned long mBYTE_FLIP_MASK_16[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_15[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_7 [] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x8080808008090a0b } ; + static const unsigned long mBYTE_FLIP_MASK_2 [] = + { 0x0405060700010203, 0x8080808080808080, 0x8080808080808080, 0x8080808080808080 } ; + + static const unsigned long mMAPtoW_I_7[] = + { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0302010080808080 } ; + static const unsigned long mMAP1toW_I_2[] = + { 0x8080808080808080, 0x0706050403020100, 0x8080808080808080, 0x8080808080808080 } ; + static const unsigned long mMAP2toW_I_2[] = + { 0x8080808080808080, 0x8080808080808080, 0x0f0e0d0c0b0a0908, 0x8080808080808080 } ; + static const unsigned long mMAP3toW_I_2[] = + { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0706050403020100 } ; + +static int Transform_AVX2(Sha256* sha256) +{ + + #ifdef WOLFSSL_SMALL_STACK + word32* W_K; + W_K = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (W_K == NULL) + return MEMORY_E; + #else + word32 W_K[64] ; + #endif + + MOVE_to_REG(W_I_16, sha256->buffer[0]); BYTE_SWAP(W_I_16, mBYTE_FLIP_MASK_16[0]) ; + MOVE_to_REG(W_I_15, sha256->buffer[1]); BYTE_SWAP(W_I_15, mBYTE_FLIP_MASK_15[0]) ; + MOVE_to_REG(W_I, sha256->buffer[8]) ; BYTE_SWAP(W_I, mBYTE_FLIP_MASK_16[0]) ; + MOVE_to_REG(W_I_7, sha256->buffer[16-7]) ; BYTE_SWAP(W_I_7, mBYTE_FLIP_MASK_7[0]) ; + MOVE_to_REG(W_I_2, sha256->buffer[16-2]) ; BYTE_SWAP(W_I_2, mBYTE_FLIP_MASK_2[0]) ; + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + ADD_MEM(W_K_TEMP, W_I_16, K[0]) ; + MOVE_to_MEM(W_K[0], W_K_TEMP) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,1) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,2) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,3) ; + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,4) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,5) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,6) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,7) ; + + ADD_MEM(YMM_TEMP0, W_I, K[8]) ; + MOVE_to_MEM(W_K[8], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + + MOVE_to_REG(YMM_TEMP0, K[16]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[16], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + + MOVE_to_REG(YMM_TEMP0, K[24]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[24], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + GAMMA1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + + MOVE_to_REG(YMM_TEMP0, K[32]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[32], YMM_TEMP0) ; + + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + + MOVE_to_REG(YMM_TEMP0, K[40]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[40], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + + MOVE_to_REG(YMM_TEMP0, K[48]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[48], YMM_TEMP0) ; + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + GAMMA0_1(W_I_TEMP, W_I_15) ; + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + GAMMA0_2(W_I_TEMP, W_I_15) ; + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; + ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + FEEDBACK1_to_W_I_2 ; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; + FEEDBACK_to_W_I_7 ; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + FEEDBACK2_to_W_I_2 ; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; + FEEDBACK3_to_W_I_2 ; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + GAMMA1_1(YMM_TEMP0, W_I_2) ; + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + GAMMA1_2(YMM_TEMP0, W_I_2) ; + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; + ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + + MOVE_to_REG(YMM_TEMP0, K[56]) ; + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; + ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; + MOVE_to_MEM(W_K[56], YMM_TEMP0) ; + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return 0; +} + +#endif /* HAVE_INTEL_AVX2 */ + +#endif /* HAVE_FIPS */ + +#endif /* WOLFSSL_TI_HAHS */ + +#endif /* NO_SHA256 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/sha512.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1736 @@ +/* sha512.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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/sha512.h> + +#ifdef WOLFSSL_SHA512 + +#ifdef HAVE_FIPS +int wc_InitSha512(Sha512* sha) +{ + return InitSha512_fips(sha); +} + + +int wc_Sha512Update(Sha512* sha, const byte* data, word32 len) +{ + return Sha512Update_fips(sha, data, len); +} + + +int wc_Sha512Final(Sha512* sha, byte* out) +{ + return Sha512Final_fips(sha, out); +} + + +#if defined(WOLFSSL_SHA384) || defined(HAVE_AESGCM) + +int wc_InitSha384(Sha384* sha) +{ + return InitSha384_fips(sha); +} + + +int wc_Sha384Update(Sha384* sha, const byte* data, word32 len) +{ + return Sha384Update_fips(sha, data, len); +} + + +int wc_Sha384Final(Sha384* sha, byte* out) +{ + return Sha384Final_fips(sha, out); +} + + +#endif /* WOLFSSL_SHA384 */ +#else /* else build without using fips */ +#include <wolfssl/wolfcrypt/logging.h> +#include <wolfssl/wolfcrypt/error-crypt.h> + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #include <wolfcrypt/src/misc.c> +#endif + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN + + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } + +#endif /* WOLFSSL_HAVE_MIN */ + +#if defined(USE_INTEL_SPEEDUP) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#endif + +#if defined(HAVE_INTEL_AVX1) +/* #define DEBUG_XMM */ +#endif + +#if defined(HAVE_INTEL_AVX2) +#define HAVE_INTEL_RORX +/* #define DEBUG_YMM */ +#endif + +/***** +Intel AVX1/AVX2 Macro Control Structure + +#if defined(HAVE_INteL_SPEEDUP) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#endif + +int InitSha512(Sha512* sha512) { + Save/Recover XMM, YMM + ... + + Check Intel AVX cpuid flags +} + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform_AVX1() ; # Function prototype + Transform_AVX2() ; # +#endif + + _Transform() { # 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_AVX1() { + Stitched Message Sched/Round + } + +#endif + +#if defnied(HAVE_INTEL_AVX2) + + int Transform_AVX2() { + Stitched Message Sched/Round + } +#endif + + +*/ + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + + +/* 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) __cpuid((int*)a,b) + + #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 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_RDRAND (cpuid_flags&CPUID_RDRAND) +#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) + +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; + unsigned int reg[5]; + + reg[4] = '\0' ; + cpuid(reg, 0, 0); + 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; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return((reg[num]>>bit)&0x1) ; + } + return 0 ; +} + +#define CHECK_SHA512 0x1 +#define CHECK_SHA384 0x2 + +static int set_cpuid_flags(int sha) { + if((cpuid_check & sha) ==0) { + 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 ; } + cpuid_check |= sha ; + return 0 ; + } + return 1 ; +} + + +/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ + +#if defined(HAVE_INTEL_AVX1) +static int Transform_AVX1(Sha512 *sha512) ; +#endif + +#if defined(HAVE_INTEL_AVX2) +static int Transform_AVX2(Sha512 *sha512) ; + +#if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX) +static int Transform_AVX1_RORX(Sha512 *sha512) ; +#endif + +#endif + +static int _Transform(Sha512 *sha512) ; + +static int (*Transform_p)(Sha512* sha512) = _Transform ; + +#define Transform(sha512) (*Transform_p)(sha512) + +static void set_Transform(void) { + if(set_cpuid_flags(CHECK_SHA512)) return ; + +#if defined(HAVE_INTEL_AVX2) + if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ + Transform_p = Transform_AVX1_RORX; return ; + Transform_p = Transform_AVX2 ; + /* for avoiding warning,"not used" */ + } +#endif +#if defined(HAVE_INTEL_AVX1) + Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : _Transform) ; return ; +#endif + Transform_p = _Transform ; return ; +} + +#else + #define Transform(sha512) _Transform(sha512) +#endif + +/* Dummy for saving MM_REGs on behalf of Transform */ +/* #if defined(HAVE_INTEL_AVX2) + #define SAVE_XMM_YMM __asm__ volatile("orq %%r8, %%r8":::\ + "%ymm0","%ymm1","%ymm2","%ymm3","%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11",\ + "%ymm12","%ymm13","%ymm14","%ymm15") +*/ +#if defined(HAVE_INTEL_AVX1) + #define SAVE_XMM_YMM __asm__ volatile("orq %%r8, %%r8":::\ + "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13","xmm14","xmm15") +#else +#define SAVE_XMM_YMM +#endif + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + +#include <string.h> + +#endif /* defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) */ + + +#if defined(HAVE_INTEL_RORX) +#define ROTR(func, bits, x) \ +word64 func(word64 x) { word64 ret ;\ + __asm__ ("rorx $"#bits", %1, %0\n\t":"=r"(ret):"r"(x):) ;\ + return ret ;\ +} + +static INLINE ROTR(rotrFixed64_28, 28, x) +static INLINE ROTR(rotrFixed64_34, 34, x) +static INLINE ROTR(rotrFixed64_39, 39, x) +static INLINE ROTR(rotrFixed64_14, 14, x) +static INLINE ROTR(rotrFixed64_18, 18, x) +static INLINE ROTR(rotrFixed64_41, 41, x) + +#define S0_RORX(x) (rotrFixed64_28(x)^rotrFixed64_34(x)^rotrFixed64_39(x)) +#define S1_RORX(x) (rotrFixed64_14(x)^rotrFixed64_18(x)^rotrFixed64_41(x)) +#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 + + +int wc_InitSha512(Sha512* sha512) +{ + 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; + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + set_Transform() ; /* choose best Transform function under this runtime environment */ +#endif + + return 0 ; +} + + +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)) + +#define blk384(i) (W[i] = sha384->buffer[i]) + +#define R2(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk384(i));\ + d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) + +static int _Transform(Sha512* sha512) +{ + const word64* K = K512; + + word32 j; + word64 T[8]; + + +#ifdef 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_SHA2 + /* 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_SHA2 */ + + /* 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)); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + + +static INLINE void AddLength(Sha512* sha512, word32 len) +{ + word32 tmp = sha512->loLen; + if ( (sha512->loLen += len) < tmp) + sha512->hiLen++; /* carry low to high */ +} + +int wc_Sha512Update(Sha512* sha512, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)sha512->buffer; + SAVE_XMM_YMM ; /* for Intel AVX */ + + while (len) { + word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen); + XMEMCPY(&local[sha512->buffLen], data, add); + + sha512->buffLen += add; + data += add; + len -= add; + + if (sha512->buffLen == SHA512_BLOCK_SIZE) { + int ret; + #if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords64(sha512->buffer, sha512->buffer, + SHA512_BLOCK_SIZE); + #endif + ret = Transform(sha512); + if (ret != 0) + return ret; + + AddLength(sha512, SHA512_BLOCK_SIZE); + sha512->buffLen = 0; + } + } + return 0; +} + + +int wc_Sha512Final(Sha512* sha512, byte* hash) +{ + byte* local = (byte*)sha512->buffer; + int ret; + + SAVE_XMM_YMM ; /* for Intel AVX */ + AddLength(sha512, sha512->buffLen); /* before adding pads */ + + local[sha512->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha512->buffLen > SHA512_PAD_SIZE) { + XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen); + sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen; + #if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE); + #endif + ret = Transform(sha512); + if (ret != 0) + return ret; + + sha512->buffLen = 0; + } + XMEMSET(&local[sha512->buffLen], 0, 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 && !IS_INTEL_AVX2) + #endif + ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + + sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; + sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(IS_INTEL_AVX1 || IS_INTEL_AVX2) + ByteReverseWords64(&(sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2]), + &(sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2]), + SHA512_BLOCK_SIZE - SHA512_PAD_SIZE); + #endif + ret = Transform(sha512); + if (ret != 0) + return ret; + + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE); + + return wc_InitSha512(sha512); /* reset state */ +} + + + +#if defined(HAVE_INTEL_AVX1) + +#define Rx_1(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + W_X[i] ; +#define Rx_2(i) d(i)+=h(i); +#define Rx_3(i) h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); + +#if defined(HAVE_INTEL_RORX) +#define Rx_RORX_1(i) h(i)+=S1_RORX(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + W_X[i] ; +#define Rx_RORX_2(i) d(i)+=h(i); +#define Rx_RORX_3(i) h(i)+=S0_RORX(a(i))+Maj(a(i),b(i),c(i)); +#endif + +#endif + +#if defined(HAVE_INTEL_AVX2) +#define Ry_1(i, w) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + w ; +#define Ry_2(i, w) d(i)+=h(i); +#define Ry_3(i, w) h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); +#endif + +#if defined(HAVE_INTEL_AVX1) /* INLINE Assember for Intel AVX1 instructions */ +#if defined(DEBUG_XMM) + +#define SAVE_REG(i) __asm__ volatile("vmovdqu %%xmm"#i", %0 \n\t":"=m"(reg[i][0])::XMM_REGs); +#define RECV_REG(i) __asm__ volatile("vmovdqu %0, %%xmm"#i" \n\t"::"m"(reg[i][0]):XMM_REGs); + +#define _DUMP_REG(REG, name)\ + { word64 buf[16] ;word64 reg[16][2];int k ;\ + SAVE_REG(0); SAVE_REG(1); SAVE_REG(2); SAVE_REG(3); SAVE_REG(4); \ + SAVE_REG(5); SAVE_REG(6); SAVE_REG(7);SAVE_REG(8); SAVE_REG(9); SAVE_REG(10);\ + SAVE_REG(11); SAVE_REG(12); SAVE_REG(13); SAVE_REG(14); SAVE_REG(15); \ + __asm__ volatile("vmovdqu %%"#REG", %0 \n\t":"=m"(buf[0])::XMM_REGs);\ + printf(" "#name":\t") ; for(k=0; k<2; k++) printf("%016lx.", (word64)(buf[k])); printf("\n") ; \ + RECV_REG(0); RECV_REG(1); RECV_REG(2); RECV_REG(3); RECV_REG(4);\ + RECV_REG(5); RECV_REG(6); RECV_REG(7); RECV_REG(8); RECV_REG(9);\ + RECV_REG(10); RECV_REG(11); RECV_REG(12); RECV_REG(13); RECV_REG(14); RECV_REG(15);\ + } + +#define DUMP_REG(REG) _DUMP_REG(REG, #REG) +#define PRINTF(fmt, ...) + +#else + +#define DUMP_REG(REG) +#define PRINTF(fmt, ...) + +#endif + +#define _MOVE_to_REG(xymm, mem) __asm__ volatile("vmovdqu %0, %%"#xymm" "\ + :: "m"(mem):XMM_REGs) ; +#define _MOVE_to_MEM(mem,i, xymm) __asm__ volatile("vmovdqu %%"#xymm", %0" :\ + "=m"(mem[i]),"=m"(mem[i+1]),"=m"(mem[i+2]),"=m"(mem[i+3])::XMM_REGs) ; +#define _MOVE(dest, src) __asm__ volatile("vmovdqu %%"#src", %%"\ + #dest" ":::XMM_REGs) ; + +#define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrlq $"#bits", %%"\ + #src", %%"#dest"\n\tvpsllq $64-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ + #temp",%%"#dest", %%"#dest" ":::XMM_REGs) ; +#define _AVX1_R(dest, src, bits) __asm__ volatile("vpsrlq $"#bits", %%"\ + #src", %%"#dest" ":::XMM_REGs) ; +#define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ + #src2", %%"#dest" ":::XMM_REGs) ; +#define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ + #src2", %%"#dest" ":::XMM_REGs) ; +#define _ADD(dest, src1, src2) __asm__ volatile("vpaddq %%"#src1", %%"\ + #src2", %%"#dest" ":::XMM_REGs) ; +#define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddq %0, %%"#src1", %%"\ + #dest" "::"m"(mem):XMM_REGs) ; + +#define MOVE_to_REG(xymm, mem) _MOVE_to_REG(xymm, mem) +#define MOVE_to_MEM(mem, i, xymm) _MOVE_to_MEM(mem, i, xymm) +#define MOVE(dest, src) _MOVE(dest, src) + +#define XOR(dest, src1, src2) _XOR(dest, src1, src2) +#define OR(dest, src1, src2) _OR(dest, src1, src2) +#define ADD(dest, src1, src2) _ADD(dest, src1, src2) + +#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); +#define AVX1_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) +#define AVX1_R(dest, src, bits) _AVX1_R(dest, src, bits) + +#define Init_Mask(mask) \ + __asm__ volatile("vmovdqu %0, %%xmm1\n\t"::"m"(mask):"%xmm1") ; + +#define _W_from_buff1(w, buff, xmm) \ + /* X0..3(xmm4..7), W[0..15] = sha512->buffer[0.15]; */\ + __asm__ volatile("vmovdqu %1, %%"#xmm"\n\t"\ + "vpshufb %%xmm1, %%"#xmm", %%"#xmm"\n\t"\ + "vmovdqu %%"#xmm", %0"\ + :"=m"(w): "m"(buff):"%xmm0") ; + +#define W_from_buff1(w, buff, xmm) _W_from_buff1(w, buff, xmm) + +#define W_from_buff(w, buff)\ + Init_Mask(mBYTE_FLIP_MASK[0]) ;\ + W_from_buff1(w[0], buff[0], W_0);\ + W_from_buff1(w[2], buff[2], W_2);\ + W_from_buff1(w[4], buff[4], W_4);\ + W_from_buff1(w[6], buff[6], W_6);\ + W_from_buff1(w[8], buff[8], W_8);\ + W_from_buff1(w[10],buff[10],W_10);\ + W_from_buff1(w[12],buff[12],W_12);\ + W_from_buff1(w[14],buff[14],W_14); + +static word64 mBYTE_FLIP_MASK[] = { 0x0001020304050607, 0x08090a0b0c0d0e0f } ; + +#define W_I_15 xmm14 +#define W_I_7 xmm11 +#define W_I_2 xmm13 +#define W_I xmm12 +#define G_TEMP xmm0 +#define S_TEMP xmm1 +#define XMM_TEMP0 xmm2 + +#define W_0 xmm12 +#define W_2 xmm3 +#define W_4 xmm4 +#define W_6 xmm5 +#define W_8 xmm6 +#define W_10 xmm7 +#define W_12 xmm8 +#define W_14 xmm9 + +#define XMM_REGs + +#define s0_1(dest, src) AVX1_S(dest, src, 1); +#define s0_2(dest, src) AVX1_S(G_TEMP, src, 8); XOR(dest, G_TEMP, dest) ; +#define s0_3(dest, src) AVX1_R(G_TEMP, src, 7); XOR(dest, G_TEMP, dest) ; + +#define s1_1(dest, src) AVX1_S(dest, src, 19); +#define s1_2(dest, src) AVX1_S(G_TEMP, src, 61); XOR(dest, G_TEMP, dest) ; +#define s1_3(dest, src) AVX1_R(G_TEMP, src, 6); XOR(dest, G_TEMP, dest) ; + +#define s0_(dest, src) s0_1(dest, src) ; s0_2(dest, src) ; s0_3(dest, src) +#define s1_(dest, src) s1_1(dest, src) ; s1_2(dest, src) ; s1_3(dest, src) + +#define Block_xx_1(i) \ + MOVE_to_REG(W_I_15, W_X[(i-15)&15]) ;\ + MOVE_to_REG(W_I_7, W_X[(i- 7)&15]) ;\ + +#define Block_xx_2(i) \ + MOVE_to_REG(W_I_2, W_X[(i- 2)&15]) ;\ + MOVE_to_REG(W_I, W_X[(i)]) ;\ + +#define Block_xx_3(i) \ + s0_ (XMM_TEMP0, W_I_15) ;\ + +#define Block_xx_4(i) \ + ADD(W_I, W_I, XMM_TEMP0) ;\ + ADD(W_I, W_I, W_I_7) ;\ + +#define Block_xx_5(i) \ + s1_ (XMM_TEMP0, W_I_2) ;\ + +#define Block_xx_6(i) \ + ADD(W_I, W_I, XMM_TEMP0) ;\ + MOVE_to_MEM(W_X,i, W_I) ;\ + if(i==0)\ + MOVE_to_MEM(W_X,16, W_I) ;\ + +#define Block_xx_7(i) \ + MOVE_to_REG(W_I_15, W_X[(i-15)&15]) ;\ + MOVE_to_REG(W_I_7, W_X[(i- 7)&15]) ;\ + +#define Block_xx_8(i) \ + MOVE_to_REG(W_I_2, W_X[(i- 2)&15]) ;\ + MOVE_to_REG(W_I, W_X[(i)]) ;\ + +#define Block_xx_9(i) \ + s0_ (XMM_TEMP0, W_I_15) ;\ + +#define Block_xx_10(i) \ + ADD(W_I, W_I, XMM_TEMP0) ;\ + ADD(W_I, W_I, W_I_7) ;\ + +#define Block_xx_11(i) \ + s1_ (XMM_TEMP0, W_I_2) ;\ + +#define Block_xx_12(i) \ + ADD(W_I, W_I, XMM_TEMP0) ;\ + MOVE_to_MEM(W_X,i, W_I) ;\ + if((i)==0)\ + MOVE_to_MEM(W_X,16, W_I) ;\ + +static INLINE void Block_0_1(word64 *W_X) { Block_xx_1(0) ; } +static INLINE void Block_0_2(word64 *W_X) { Block_xx_2(0) ; } +static INLINE void Block_0_3(void) { Block_xx_3(0) ; } +static INLINE void Block_0_4(void) { Block_xx_4(0) ; } +static INLINE void Block_0_5(void) { Block_xx_5(0) ; } +static INLINE void Block_0_6(word64 *W_X) { Block_xx_6(0) ; } +static INLINE void Block_0_7(word64 *W_X) { Block_xx_7(2) ; } +static INLINE void Block_0_8(word64 *W_X) { Block_xx_8(2) ; } +static INLINE void Block_0_9(void) { Block_xx_9(2) ; } +static INLINE void Block_0_10(void){ Block_xx_10(2) ; } +static INLINE void Block_0_11(void){ Block_xx_11(2) ; } +static INLINE void Block_0_12(word64 *W_X){ Block_xx_12(2) ; } + +static INLINE void Block_4_1(word64 *W_X) { Block_xx_1(4) ; } +static INLINE void Block_4_2(word64 *W_X) { Block_xx_2(4) ; } +static INLINE void Block_4_3(void) { Block_xx_3(4) ; } +static INLINE void Block_4_4(void) { Block_xx_4(4) ; } +static INLINE void Block_4_5(void) { Block_xx_5(4) ; } +static INLINE void Block_4_6(word64 *W_X) { Block_xx_6(4) ; } +static INLINE void Block_4_7(word64 *W_X) { Block_xx_7(6) ; } +static INLINE void Block_4_8(word64 *W_X) { Block_xx_8(6) ; } +static INLINE void Block_4_9(void) { Block_xx_9(6) ; } +static INLINE void Block_4_10(void){ Block_xx_10(6) ; } +static INLINE void Block_4_11(void){ Block_xx_11(6) ; } +static INLINE void Block_4_12(word64 *W_X){ Block_xx_12(6) ; } + +static INLINE void Block_8_1(word64 *W_X) { Block_xx_1(8) ; } +static INLINE void Block_8_2(word64 *W_X) { Block_xx_2(8) ; } +static INLINE void Block_8_3(void) { Block_xx_3(8) ; } +static INLINE void Block_8_4(void) { Block_xx_4(8) ; } +static INLINE void Block_8_5(void) { Block_xx_5(8) ; } +static INLINE void Block_8_6(word64 *W_X) { Block_xx_6(8) ; } +static INLINE void Block_8_7(word64 *W_X) { Block_xx_7(10) ; } +static INLINE void Block_8_8(word64 *W_X) { Block_xx_8(10) ; } +static INLINE void Block_8_9(void) { Block_xx_9(10) ; } +static INLINE void Block_8_10(void){ Block_xx_10(10) ; } +static INLINE void Block_8_11(void){ Block_xx_11(10) ; } +static INLINE void Block_8_12(word64 *W_X){ Block_xx_12(10) ; } + +static INLINE void Block_12_1(word64 *W_X) { Block_xx_1(12) ; } +static INLINE void Block_12_2(word64 *W_X) { Block_xx_2(12) ; } +static INLINE void Block_12_3(void) { Block_xx_3(12) ; } +static INLINE void Block_12_4(void) { Block_xx_4(12) ; } +static INLINE void Block_12_5(void) { Block_xx_5(12) ; } +static INLINE void Block_12_6(word64 *W_X) { Block_xx_6(12) ; } +static INLINE void Block_12_7(word64 *W_X) { Block_xx_7(14) ; } +static INLINE void Block_12_8(word64 *W_X) { Block_xx_8(14) ; } +static INLINE void Block_12_9(void) { Block_xx_9(14) ; } +static INLINE void Block_12_10(void){ Block_xx_10(14) ; } +static INLINE void Block_12_11(void){ Block_xx_11(14) ; } +static INLINE void Block_12_12(word64 *W_X){ Block_xx_12(14) ; } + +#endif + +#if defined(HAVE_INTEL_AVX2) +static const unsigned long mBYTE_FLIP_MASK_Y[] = + { 0x0001020304050607, 0x08090a0b0c0d0e0f, 0x0001020304050607, 0x08090a0b0c0d0e0f } ; + +#define W_from_buff_Y(buff)\ + { /* X0..3(ymm9..12), W_X[0..15] = sha512->buffer[0.15]; */\ + __asm__ volatile("vmovdqu %0, %%ymm8\n\t"::"m"(mBYTE_FLIP_MASK_Y[0]):YMM_REGs) ;\ + __asm__ volatile("vmovdqu %0, %%ymm12\n\t"\ + "vmovdqu %1, %%ymm4\n\t"\ + "vpshufb %%ymm8, %%ymm12, %%ymm12\n\t"\ + "vpshufb %%ymm8, %%ymm4, %%ymm4\n\t"\ + :: "m"(buff[0]), "m"(buff[4]):YMM_REGs) ;\ + __asm__ volatile("vmovdqu %0, %%ymm5\n\t"\ + "vmovdqu %1, %%ymm6\n\t"\ + "vpshufb %%ymm8, %%ymm5, %%ymm5\n\t"\ + "vpshufb %%ymm8, %%ymm6, %%ymm6\n\t"\ + :: "m"(buff[8]), "m"(buff[12]):YMM_REGs) ;\ + } + +#if defined(DEBUG_YMM) + +#define SAVE_REG_Y(i) __asm__ volatile("vmovdqu %%ymm"#i", %0 \n\t":"=m"(reg[i-4][0])::YMM_REGs); +#define RECV_REG_Y(i) __asm__ volatile("vmovdqu %0, %%ymm"#i" \n\t"::"m"(reg[i-4][0]):YMM_REGs); + +#define _DUMP_REG_Y(REG, name)\ + { word64 buf[16] ;word64 reg[16][2];int k ;\ + SAVE_REG_Y(4); SAVE_REG_Y(5); SAVE_REG_Y(6); SAVE_REG_Y(7); \ + SAVE_REG_Y(8); SAVE_REG_Y(9); SAVE_REG_Y(10); SAVE_REG_Y(11); SAVE_REG_Y(12);\ + SAVE_REG_Y(13); SAVE_REG_Y(14); SAVE_REG_Y(15); \ + __asm__ volatile("vmovdqu %%"#REG", %0 \n\t":"=m"(buf[0])::YMM_REGs);\ + printf(" "#name":\t") ; for(k=0; k<4; k++) printf("%016lx.", (word64)buf[k]) ; printf("\n") ; \ + RECV_REG_Y(4); RECV_REG_Y(5); RECV_REG_Y(6); RECV_REG_Y(7); \ + RECV_REG_Y(8); RECV_REG_Y(9); RECV_REG_Y(10); RECV_REG_Y(11); RECV_REG_Y(12); \ + RECV_REG_Y(13); RECV_REG_Y(14); RECV_REG_Y(15);\ + } + +#define DUMP_REG_Y(REG) _DUMP_REG_Y(REG, #REG) +#define DUMP_REG2_Y(REG) _DUMP_REG_Y(REG, #REG) +#define PRINTF_Y(fmt, ...) + +#else + +#define DUMP_REG_Y(REG) +#define DUMP_REG2_Y(REG) +#define PRINTF_Y(fmt, ...) + +#endif + +#define _MOVE_to_REGy(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" "\ + :: "m"(mem):YMM_REGs) ; +#define _MOVE_to_MEMy(mem,i, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" \ + : "=m"(mem[i]),"=m"(mem[i+1]),"=m"(mem[i+2]),"=m"(mem[i+3])::YMM_REGs) ; +#define _MOVE_128y(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"\ + #map", %%"#ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; +#define _S_TEMPy(dest, src, bits, temp) \ + __asm__ volatile("vpsrlq $"#bits", %%"#src", %%"#dest"\n\tvpsllq $64-"#bits\ + ", %%"#src", %%"#temp"\n\tvpor %%"#temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; +#define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrlq $"#bits", %%"\ + #src", %%"#dest" ":::YMM_REGs) ; +#define _XORy(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _ADDy(dest, src1, src2) __asm__ volatile("vpaddq %%"#src1", %%"\ + #src2", %%"#dest" ":::YMM_REGs) ; +#define _BLENDy(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ + #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; +#define _BLENDQy(map, dest, src1, src2) __asm__ volatile("vblendpd $"#map", %%"\ + #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; +#define _PERMQy(map, dest, src) __asm__ volatile("vpermq $"#map", %%"\ + #src", %%"#dest" ":::YMM_REGs) ; + +#define MOVE_to_REGy(ymm, mem) _MOVE_to_REGy(ymm, mem) +#define MOVE_to_MEMy(mem, i, ymm) _MOVE_to_MEMy(mem, i, ymm) + +#define MOVE_128y(ymm0, ymm1, ymm2, map) _MOVE_128y(ymm0, ymm1, ymm2, map) +#define XORy(dest, src1, src2) _XORy(dest, src1, src2) +#define ADDy(dest, src1, src2) _ADDy(dest, src1, src2) +#define BLENDy(map, dest, src1, src2) _BLENDy(map, dest, src1, src2) +#define BLENDQy(map, dest, src1, src2) _BLENDQy(map, dest, src1, src2) +#define PERMQy(map, dest, src) _PERMQy(map, dest, src) + + +#define S_TMPy(dest, src, bits, temp) _S_TEMPy(dest, src, bits, temp); +#define AVX2_S(dest, src, bits) S_TMPy(dest, src, bits, S_TEMPy) +#define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) + + +#define FEEDBACK1_to_W_I_2(w_i_2, w_i) MOVE_128y(YMM_TEMP0, w_i, w_i, 0x08) ;\ + BLENDy(0xf0, w_i_2, YMM_TEMP0, w_i_2) ; + +#define MOVE_W_to_W_I_15(w_i_15, w_0, w_4) BLENDQy(0x1, w_i_15, w_4, w_0) ;\ + PERMQy(0x39, w_i_15, w_i_15) ; +#define MOVE_W_to_W_I_7(w_i_7, w_8, w_12) BLENDQy(0x1, w_i_7, w_12, w_8) ;\ + PERMQy(0x39, w_i_7, w_i_7) ; +#define MOVE_W_to_W_I_2(w_i_2, w_12) BLENDQy(0xc, w_i_2, w_12, w_i_2) ;\ + PERMQy(0x0e, w_i_2, w_i_2) ; + + +#define W_I_16y ymm8 +#define W_I_15y ymm9 +#define W_I_7y ymm10 +#define W_I_2y ymm11 +#define W_Iy ymm12 +#define G_TEMPy ymm13 +#define S_TEMPy ymm14 +#define YMM_TEMP0 ymm15 +#define YMM_TEMP0x xmm15 +#define W_I_TEMPy ymm7 +#define W_K_TEMPy ymm15 +#define W_K_TEMPx xmm15 +#define W_0y ymm12 +#define W_4y ymm4 +#define W_8y ymm5 +#define W_12y ymm6 + +#define YMM_REGs +/* Registers are saved in Sha512Update/Final */ + /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ + +#define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + +#define MOVE_7_to_15(w_i_15, w_i_7)\ + __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + +#define MOVE_I_to_7(w_i_7, w_i)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ + +#define MOVE_I_to_2(w_i_2, w_i)\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ + __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ + +#endif + + +/*** Transform Body ***/ +#if defined(HAVE_INTEL_AVX1) + +static int Transform_AVX1(Sha512* sha512) +{ + const word64* K = K512; + word64 W_X[16+4]; + word32 j; + word64 T[8]; + /* Copy digest to working vars */ + XMEMCPY(T, sha512->digest, sizeof(T)); + + W_from_buff(W_X, sha512->buffer) ; + for (j = 0; j < 80; j += 16) { + Rx_1( 0); Block_0_1(W_X); Rx_2( 0); Block_0_2(W_X); Rx_3( 0); Block_0_3(); + Rx_1( 1); Block_0_4(); Rx_2( 1); Block_0_5(); Rx_3( 1); Block_0_6(W_X); + Rx_1( 2); Block_0_7(W_X); Rx_2( 2); Block_0_8(W_X); Rx_3( 2); Block_0_9(); + Rx_1( 3); Block_0_10();Rx_2( 3); Block_0_11();Rx_3( 3); Block_0_12(W_X); + + Rx_1( 4); Block_4_1(W_X); Rx_2( 4); Block_4_2(W_X); Rx_3( 4); Block_4_3(); + Rx_1( 5); Block_4_4(); Rx_2( 5); Block_4_5(); Rx_3( 5); Block_4_6(W_X); + Rx_1( 6); Block_4_7(W_X); Rx_2( 6); Block_4_8(W_X); Rx_3( 6); Block_4_9(); + Rx_1( 7); Block_4_10();Rx_2( 7); Block_4_11();Rx_3( 7); Block_4_12(W_X); + + Rx_1( 8); Block_8_1(W_X); Rx_2( 8); Block_8_2(W_X); Rx_3( 8); Block_8_3(); + Rx_1( 9); Block_8_4(); Rx_2( 9); Block_8_5(); Rx_3( 9); Block_8_6(W_X); + Rx_1(10); Block_8_7(W_X); Rx_2(10); Block_8_8(W_X); Rx_3(10); Block_8_9(); + Rx_1(11); Block_8_10();Rx_2(11); Block_8_11();Rx_3(11); Block_8_12(W_X); + + Rx_1(12); Block_12_1(W_X); Rx_2(12); Block_12_2(W_X); Rx_3(12); Block_12_3(); + Rx_1(13); Block_12_4(); Rx_2(13); Block_12_5(); Rx_3(13); Block_12_6(W_X); + Rx_1(14); Block_12_7(W_X); Rx_2(14); Block_12_8(W_X); Rx_3(14); Block_12_9(); + Rx_1(15); Block_12_10();Rx_2(15); Block_12_11();Rx_3(15); Block_12_12(W_X); + } + + /* 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 */ + #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) + XMEMSET(W_X, 0, sizeof(word64) * 16); + #endif + XMEMSET(T, 0, sizeof(T)); + + return 0; +} + +#endif + +#if defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_RORX) + +static int Transform_AVX1_RORX(Sha512* sha512) +{ + const word64* K = K512; + word64 W_X[16+4]; + word32 j; + word64 T[8]; + /* Copy digest to working vars */ + XMEMCPY(T, sha512->digest, sizeof(T)); + + W_from_buff(W_X, sha512->buffer) ; + for (j = 0; j < 80; j += 16) { + Rx_RORX_1( 0); Block_0_1(W_X); Rx_RORX_2( 0); Block_0_2(W_X); + Rx_RORX_3( 0); Block_0_3(); + Rx_RORX_1( 1); Block_0_4(); Rx_RORX_2( 1); Block_0_5(); + Rx_RORX_3( 1); Block_0_6(W_X); + Rx_RORX_1( 2); Block_0_7(W_X); Rx_RORX_2( 2); Block_0_8(W_X); + Rx_RORX_3( 2); Block_0_9(); + Rx_RORX_1( 3); Block_0_10();Rx_RORX_2( 3); Block_0_11(); + Rx_RORX_3( 3); Block_0_12(W_X); + + Rx_RORX_1( 4); Block_4_1(W_X); Rx_RORX_2( 4); Block_4_2(W_X); + Rx_RORX_3( 4); Block_4_3(); + Rx_RORX_1( 5); Block_4_4(); Rx_RORX_2( 5); Block_4_5(); + Rx_RORX_3( 5); Block_4_6(W_X); + Rx_RORX_1( 6); Block_4_7(W_X); Rx_RORX_2( 6); Block_4_8(W_X); + Rx_RORX_3( 6); Block_4_9(); + Rx_RORX_1( 7); Block_4_10();Rx_RORX_2( 7); Block_4_11(); + Rx_RORX_3( 7); Block_4_12(W_X); + + Rx_RORX_1( 8); Block_8_1(W_X); Rx_RORX_2( 8); Block_8_2(W_X); + Rx_RORX_3( 8); Block_8_3(); + Rx_RORX_1( 9); Block_8_4(); Rx_RORX_2( 9); Block_8_5(); + Rx_RORX_3( 9); Block_8_6(W_X); + Rx_RORX_1(10); Block_8_7(W_X); Rx_RORX_2(10); Block_8_8(W_X); + Rx_RORX_3(10); Block_8_9(); + Rx_RORX_1(11); Block_8_10();Rx_RORX_2(11); Block_8_11(); + Rx_RORX_3(11); Block_8_12(W_X); + + Rx_RORX_1(12); Block_12_1(W_X); Rx_RORX_2(12); Block_12_2(W_X); + Rx_RORX_3(12); Block_12_3(); + Rx_RORX_1(13); Block_12_4(); Rx_RORX_2(13); Block_12_5(); + Rx_RORX_3(13); Block_12_6(W_X); + Rx_RORX_1(14); Block_12_7(W_X); Rx_RORX_2(14); Block_12_8(W_X); + Rx_RORX_3(14); Block_12_9(); + Rx_RORX_1(15); Block_12_10();Rx_RORX_2(15); Block_12_11(); + Rx_RORX_3(15); Block_12_12(W_X); + } + /* 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 */ + #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) + XMEMSET(W_X, 0, sizeof(word64) * 16); + #endif + XMEMSET(T, 0, sizeof(T)); + + return 0; +} +#endif + +#if defined(HAVE_INTEL_AVX2) + +#define s0_1y(dest, src) AVX2_S(dest, src, 1); +#define s0_2y(dest, src) AVX2_S(G_TEMPy, src, 8); XORy(dest, G_TEMPy, dest) ; +#define s0_3y(dest, src) AVX2_R(G_TEMPy, src, 7); XORy(dest, G_TEMPy, dest) ; + +#define s1_1y(dest, src) AVX2_S(dest, src, 19); +#define s1_2y(dest, src) AVX2_S(G_TEMPy, src, 61); XORy(dest, G_TEMPy, dest) ; +#define s1_3y(dest, src) AVX2_R(G_TEMPy, src, 6); XORy(dest, G_TEMPy, dest) ; + +#define s0_y(dest, src) s0_1y(dest, src) ; s0_2y(dest, src) ; s0_3y(dest, src) +#define s1_y(dest, src) s1_1y(dest, src) ; s1_2y(dest, src) ; s1_3y(dest, src) + +#define blk384(i) (W[i] = sha384->buffer[i]) + + +#define Block_Y_xx_1(i, w_0, w_4, w_8, w_12)\ + MOVE_W_to_W_I_15(W_I_15y, w_0, w_4) ;\ + MOVE_W_to_W_I_7 (W_I_7y, w_8, w_12) ;\ + MOVE_W_to_W_I_2 (W_I_2y, w_12) ;\ + +#define Block_Y_xx_2(i, w_0, w_4, w_8, w_12)\ + s0_1y (YMM_TEMP0, W_I_15y) ;\ + +#define Block_Y_xx_3(i, w_0, w_4, w_8, w_12)\ + s0_2y (YMM_TEMP0, W_I_15y) ;\ + +#define Block_Y_xx_4(i, w_0, w_4, w_8, w_12)\ + s0_3y (YMM_TEMP0, W_I_15y) ;\ + +#define Block_Y_xx_5(i, w_0, w_4, w_8, w_12)\ + ADDy(W_I_TEMPy, w_0, YMM_TEMP0) ;\ + +#define Block_Y_xx_6(i, w_0, w_4, w_8, w_12)\ + ADDy(W_I_TEMPy, W_I_TEMPy, W_I_7y) ;\ + s1_1y (YMM_TEMP0, W_I_2y) ;\ + +#define Block_Y_xx_7(i, w_0, w_4, w_8, w_12)\ + s1_2y (YMM_TEMP0, W_I_2y) ;\ + +#define Block_Y_xx_8(i, w_0, w_4, w_8, w_12)\ + s1_3y (YMM_TEMP0, W_I_2y) ;\ + ADDy(w_0, W_I_TEMPy, YMM_TEMP0) ;\ + +#define Block_Y_xx_9(i, w_0, w_4, w_8, w_12)\ + FEEDBACK1_to_W_I_2(W_I_2y, w_0) ;\ + +#define Block_Y_xx_10(i, w_0, w_4, w_8, w_12) \ + s1_1y (YMM_TEMP0, W_I_2y) ;\ + +#define Block_Y_xx_11(i, w_0, w_4, w_8, w_12) \ + s1_2y (YMM_TEMP0, W_I_2y) ;\ + +#define Block_Y_xx_12(i, w_0, w_4, w_8, w_12)\ + s1_3y (YMM_TEMP0, W_I_2y) ;\ + ADDy(w_0, W_I_TEMPy, YMM_TEMP0) ;\ + MOVE_to_MEMy(w,0, w_4) ;\ + + +static INLINE void Block_Y_0_1(void) { Block_Y_xx_1(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_2(void) { Block_Y_xx_2(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_3(void) { Block_Y_xx_3(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_4(void) { Block_Y_xx_4(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_5(void) { Block_Y_xx_5(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_6(void) { Block_Y_xx_6(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_7(void) { Block_Y_xx_7(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_8(void) { Block_Y_xx_8(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_9(void) { Block_Y_xx_9(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_10(void){ Block_Y_xx_10(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_11(void){ Block_Y_xx_11(0, W_0y, W_4y, W_8y, W_12y) ; } +static INLINE void Block_Y_0_12(word64 *w){ Block_Y_xx_12(0, W_0y, W_4y, W_8y, W_12y) ; } + +static INLINE void Block_Y_4_1(void) { Block_Y_xx_1(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_2(void) { Block_Y_xx_2(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_3(void) { Block_Y_xx_3(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_4(void) { Block_Y_xx_4(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_5(void) { Block_Y_xx_5(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_6(void) { Block_Y_xx_6(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_7(void) { Block_Y_xx_7(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_8(void) { Block_Y_xx_8(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_9(void) { Block_Y_xx_9(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_10(void) { Block_Y_xx_10(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_11(void) { Block_Y_xx_11(4, W_4y, W_8y, W_12y, W_0y) ; } +static INLINE void Block_Y_4_12(word64 *w) { Block_Y_xx_12(4, W_4y, W_8y, W_12y, W_0y) ; } + +static INLINE void Block_Y_8_1(void) { Block_Y_xx_1(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_2(void) { Block_Y_xx_2(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_3(void) { Block_Y_xx_3(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_4(void) { Block_Y_xx_4(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_5(void) { Block_Y_xx_5(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_6(void) { Block_Y_xx_6(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_7(void) { Block_Y_xx_7(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_8(void) { Block_Y_xx_8(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_9(void) { Block_Y_xx_9(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_10(void) { Block_Y_xx_10(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_11(void) { Block_Y_xx_11(8, W_8y, W_12y, W_0y, W_4y) ; } +static INLINE void Block_Y_8_12(word64 *w) { Block_Y_xx_12(8, W_8y, W_12y, W_0y, W_4y) ; } + +static INLINE void Block_Y_12_1(void) { Block_Y_xx_1(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_2(void) { Block_Y_xx_2(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_3(void) { Block_Y_xx_3(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_4(void) { Block_Y_xx_4(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_5(void) { Block_Y_xx_5(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_6(void) { Block_Y_xx_6(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_7(void) { Block_Y_xx_7(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_8(void) { Block_Y_xx_8(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_9(void) { Block_Y_xx_9(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_10(void) { Block_Y_xx_10(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_11(void) { Block_Y_xx_11(12, W_12y, W_0y, W_4y, W_8y) ; } +static INLINE void Block_Y_12_12(word64 *w) { Block_Y_xx_12(12, W_12y, W_0y, W_4y, W_8y) ; } + + +static int Transform_AVX2(Sha512* sha512) +{ + const word64* K = K512; + word64 w[4] ; + word32 j /*, k*/; + word64 T[8]; + /* Copy digest to working vars */ + XMEMCPY(T, sha512->digest, sizeof(T)); + + W_from_buff_Y(sha512->buffer) ; + MOVE_to_MEMy(w,0, W_0y) ; + for (j = 0; j < 80; j += 16) { + Ry_1( 0, w[0]); Block_Y_0_1(); Ry_2( 0, w[0]); Block_Y_0_2(); + Ry_3( 0, w[0]); Block_Y_0_3(); + Ry_1( 1, w[1]); Block_Y_0_4(); Ry_2( 1, w[1]); Block_Y_0_5(); + Ry_3( 1, w[1]); Block_Y_0_6(); + Ry_1( 2, w[2]); Block_Y_0_7(); Ry_2( 2, w[2]); Block_Y_0_8(); + Ry_3( 2, w[2]); Block_Y_0_9(); + Ry_1( 3, w[3]); Block_Y_0_10();Ry_2( 3, w[3]); Block_Y_0_11(); + Ry_3( 3, w[3]); Block_Y_0_12(w); + + Ry_1( 4, w[0]); Block_Y_4_1(); Ry_2( 4, w[0]); Block_Y_4_2(); + Ry_3( 4, w[0]); Block_Y_4_3(); + Ry_1( 5, w[1]); Block_Y_4_4(); Ry_2( 5, w[1]); Block_Y_4_5(); + Ry_3( 5, w[1]); Block_Y_4_6(); + Ry_1( 6, w[2]); Block_Y_4_7(); Ry_2( 6, w[2]); Block_Y_4_8(); + Ry_3( 6, w[2]); Block_Y_4_9(); + Ry_1( 7, w[3]); Block_Y_4_10(); Ry_2( 7, w[3]);Block_Y_4_11(); + Ry_3( 7, w[3]);Block_Y_4_12(w); + + Ry_1( 8, w[0]); Block_Y_8_1(); Ry_2( 8, w[0]); Block_Y_8_2(); + Ry_3( 8, w[0]); Block_Y_8_3(); + Ry_1( 9, w[1]); Block_Y_8_4(); Ry_2( 9, w[1]); Block_Y_8_5(); + Ry_3( 9, w[1]); Block_Y_8_6(); + Ry_1(10, w[2]); Block_Y_8_7(); Ry_2(10, w[2]); Block_Y_8_8(); + Ry_3(10, w[2]); Block_Y_8_9(); + Ry_1(11, w[3]); Block_Y_8_10();Ry_2(11, w[3]); Block_Y_8_11(); + Ry_3(11, w[3]); Block_Y_8_12(w); + + Ry_1(12, w[0]); Block_Y_12_1(); Ry_2(12, w[0]); Block_Y_12_2(); + Ry_3(12, w[0]); Block_Y_12_3(); + Ry_1(13, w[1]); Block_Y_12_4(); Ry_2(13, w[1]); Block_Y_12_5(); + Ry_3(13, w[1]); Block_Y_12_6(); + Ry_1(14, w[2]); Block_Y_12_7(); Ry_2(14, w[2]); Block_Y_12_8(); + Ry_3(14, w[2]); Block_Y_12_9(); + Ry_1(15, w[3]); Block_Y_12_10();Ry_2(15, w[3]); Block_Y_12_11(); + Ry_3(15, w[3]);Block_Y_12_12(w); + } + + /* 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 */ + #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) + XMEMSET(W, 0, sizeof(word64) * 16); + #endif + XMEMSET(T, 0, sizeof(T)); + + return 0; +} + +#endif + + +#ifdef WOLFSSL_SHA384 + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +#if defined(HAVE_INTEL_AVX1) +static int Transform384_AVX1(Sha384 *sha384) ; +#endif +#if defined(HAVE_INTEL_AVX2) +static int Transform384_AVX2(Sha384 *sha384) ; +#endif + +#if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_AVX2) &&defined(HAVE_INTEL_RORX) +static int Transform384_AVX1_RORX(Sha384 *sha384) ; +#endif + +static int _Transform384(Sha384 *sha384) ; +static int (*Transform384_p)(Sha384* sha384) = _Transform384 ; + +#define Transform384(sha384) (*Transform384_p)(sha384) +static void set_Transform384(void) { + if(set_cpuid_flags(CHECK_SHA384))return ; + +#if defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) + Transform384_p = ((IS_INTEL_AVX1) ? Transform384_AVX1 : _Transform384) ; +#elif defined(HAVE_INTEL_AVX2) + #if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_RORX) + if(IS_INTEL_AVX2 && IS_INTEL_BMI2) { Transform384_p = Transform384_AVX1_RORX ; return ; } + #endif + if(IS_INTEL_AVX2) { Transform384_p = Transform384_AVX2 ; return ; } + #if defined(HAVE_INTEL_AVX1) + Transform384_p = ((IS_INTEL_AVX1) ? Transform384_AVX1 : _Transform384) ; + #endif +#else + Transform384_p = ((IS_INTEL_AVX1) ? Transform384_AVX1 : _Transform384) ; +#endif +} + +#else + #define Transform384(sha512) _Transform384(sha512) +#endif + +int wc_InitSha384(Sha384* sha384) +{ + 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; + +#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + set_Transform384() ; +#endif + + return 0; +} + +static int _Transform384(Sha384* sha384) +{ + const word64* K = K512; + + word32 j; + word64 T[8]; + +#ifdef 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, sha384->digest, sizeof(T)); + +#ifdef USE_SLOW_SHA2 + /* 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 for macros {} */ + R2(m); + } + } +#else + /* 80 operations, partially loop unrolled */ + for (j = 0; j < 80; j += 16) { + R2( 0); R2( 1); R2( 2); R2( 3); + R2( 4); R2( 5); R2( 6); R2( 7); + R2( 8); R2( 9); R2(10); R2(11); + R2(12); R2(13); R2(14); R2(15); + } +#endif /* USE_SLOW_SHA2 */ + + /* Add the working vars back into digest */ + + sha384->digest[0] += a(0); + sha384->digest[1] += b(0); + sha384->digest[2] += c(0); + sha384->digest[3] += d(0); + sha384->digest[4] += e(0); + sha384->digest[5] += f(0); + sha384->digest[6] += g(0); + sha384->digest[7] += h(0); + + /* Wipe variables */ + XMEMSET(W, 0, sizeof(word64) * 16); + XMEMSET(T, 0, sizeof(T)); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +static INLINE void AddLength384(Sha384* sha384, word32 len) +{ + word32 tmp = sha384->loLen; + if ( (sha384->loLen += len) < tmp) + sha384->hiLen++; /* carry low to high */ +} + +int wc_Sha384Update(Sha384* sha384, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)sha384->buffer; + + SAVE_XMM_YMM ; /* for Intel AVX */ + + while (len) { + word32 add = min(len, SHA384_BLOCK_SIZE - sha384->buffLen); + XMEMCPY(&local[sha384->buffLen], data, add); + + sha384->buffLen += add; + data += add; + len -= add; + + if (sha384->buffLen == SHA384_BLOCK_SIZE) { + int ret; + + #if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords64(sha384->buffer, sha384->buffer, + SHA384_BLOCK_SIZE); + #endif + ret = Transform384(sha384); + if (ret != 0) + return ret; + + AddLength384(sha384, SHA384_BLOCK_SIZE); + sha384->buffLen = 0; + } + } + return 0; +} + + +int wc_Sha384Final(Sha384* sha384, byte* hash) +{ + byte* local = (byte*)sha384->buffer; + int ret; + + SAVE_XMM_YMM ; /* for Intel AVX */ + AddLength384(sha384, sha384->buffLen); /* before adding pads */ + + local[sha384->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha384->buffLen > SHA384_PAD_SIZE) { + XMEMSET(&local[sha384->buffLen], 0, SHA384_BLOCK_SIZE -sha384->buffLen); + sha384->buffLen += SHA384_BLOCK_SIZE - sha384->buffLen; + + #if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords64(sha384->buffer, sha384->buffer, + SHA384_BLOCK_SIZE); + #endif + ret = Transform384(sha384); + if (ret != 0) + return ret; + + sha384->buffLen = 0; + } + XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen); + + /* put lengths in bits */ + sha384->hiLen = (sha384->loLen >> (8*sizeof(sha384->loLen) - 3)) + + (sha384->hiLen << 3); + sha384->loLen = sha384->loLen << 3; + + /* store lengths */ + #if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords64(sha384->buffer, sha384->buffer, + SHA384_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen; + sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen; + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(IS_INTEL_AVX1 || IS_INTEL_AVX2) + ByteReverseWords64(&(sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2]), + &(sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2]), + SHA384_BLOCK_SIZE - SHA384_PAD_SIZE); + #endif + ret = Transform384(sha384); + if (ret != 0) + return ret; + + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE); + + return wc_InitSha384(sha384); /* reset state */ +} + + + +#if defined(HAVE_INTEL_AVX1) + +static int Transform384_AVX1(Sha384* sha384) +{ + const word64* K = K512; + word64 W_X[16+4]; + word32 j; + word64 T[8]; + + /* Copy digest to working vars */ + XMEMCPY(T, sha384->digest, sizeof(T)); + W_from_buff(W_X, sha384->buffer) ; + for (j = 0; j < 80; j += 16) { + Rx_1( 0); Block_0_1(W_X); Rx_2( 0); Block_0_2(W_X); Rx_3( 0); Block_0_3(); + Rx_1( 1); Block_0_4(); Rx_2( 1); Block_0_5(); Rx_3( 1); Block_0_6(W_X); + Rx_1( 2); Block_0_7(W_X); Rx_2( 2); Block_0_8(W_X); Rx_3( 2); Block_0_9(); + Rx_1( 3); Block_0_10();Rx_2( 3); Block_0_11();Rx_3( 3); Block_0_12(W_X); + + Rx_1( 4); Block_4_1(W_X); Rx_2( 4); Block_4_2(W_X); Rx_3( 4); Block_4_3(); + Rx_1( 5); Block_4_4(); Rx_2( 5); Block_4_5(); Rx_3( 5); Block_4_6(W_X); + Rx_1( 6); Block_4_7(W_X); Rx_2( 6); Block_4_8(W_X); Rx_3( 6); Block_4_9(); + Rx_1( 7); Block_4_10();Rx_2( 7); Block_4_11();Rx_3( 7); Block_4_12(W_X); + + Rx_1( 8); Block_8_1(W_X); Rx_2( 8); Block_8_2(W_X); Rx_3( 8); Block_8_3(); + Rx_1( 9); Block_8_4(); Rx_2( 9); Block_8_5(); Rx_3( 9); Block_8_6(W_X); + Rx_1(10); Block_8_7(W_X); Rx_2(10); Block_8_8(W_X); Rx_3(10); Block_8_9(); + Rx_1(11); Block_8_10();Rx_2(11); Block_8_11();Rx_3(11); Block_8_12(W_X); + + Rx_1(12); Block_12_1(W_X); Rx_2(12); Block_12_2(W_X); Rx_3(12); Block_12_3(); + Rx_1(13); Block_12_4(); Rx_2(13); Block_12_5(); Rx_3(13); Block_12_6(W_X); + Rx_1(14); Block_12_7(W_X); Rx_2(14); Block_12_8(W_X); Rx_3(14); Block_12_9(); + Rx_1(15); Block_12_10();Rx_2(15); Block_12_11();Rx_3(15); Block_12_12(W_X); + } + + /* Add the working vars back into digest */ + + sha384->digest[0] += a(0); + sha384->digest[1] += b(0); + sha384->digest[2] += c(0); + sha384->digest[3] += d(0); + sha384->digest[4] += e(0); + sha384->digest[5] += f(0); + sha384->digest[6] += g(0); + sha384->digest[7] += h(0); + + /* Wipe variables */ + #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) + XMEMSET(W, 0, sizeof(word64) * 16); + #endif + XMEMSET(T, 0, sizeof(T)); + + return 0; +} + +#endif + +#if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX) +static int Transform384_AVX1_RORX(Sha384* sha384) +{ + const word64* K = K512; + word64 W_X[16+4]; + word32 j; + word64 T[8]; + + /* Copy digest to working vars */ + XMEMCPY(T, sha384->digest, sizeof(T)); + + W_from_buff(W_X, sha384->buffer) ; + for (j = 0; j < 80; j += 16) { + Rx_RORX_1( 0); Block_0_1(W_X); Rx_RORX_2( 0); + Block_0_2(W_X); Rx_RORX_3( 0); Block_0_3(); + Rx_RORX_1( 1); Block_0_4(); Rx_RORX_2( 1); + Block_0_5(); Rx_RORX_3( 1); Block_0_6(W_X); + Rx_RORX_1( 2); Block_0_7(W_X); Rx_RORX_2( 2); + Block_0_8(W_X); Rx_RORX_3( 2); Block_0_9(); + Rx_RORX_1( 3); Block_0_10();Rx_RORX_2( 3); + Block_0_11();Rx_RORX_3( 3); Block_0_12(W_X); + + Rx_RORX_1( 4); Block_4_1(W_X); Rx_RORX_2( 4); + Block_4_2(W_X); Rx_RORX_3( 4); Block_4_3(); + Rx_RORX_1( 5); Block_4_4(); Rx_RORX_2( 5); + Block_4_5(); Rx_RORX_3( 5); Block_4_6(W_X); + Rx_RORX_1( 6); Block_4_7(W_X); Rx_RORX_2( 6); + Block_4_8(W_X); Rx_RORX_3( 6); Block_4_9(); + Rx_RORX_1( 7); Block_4_10();Rx_RORX_2( 7); + Block_4_11();Rx_RORX_3( 7); Block_4_12(W_X); + + Rx_RORX_1( 8); Block_8_1(W_X); Rx_RORX_2( 8); + Block_8_2(W_X); Rx_RORX_3( 8); Block_8_3(); + Rx_RORX_1( 9); Block_8_4(); Rx_RORX_2( 9); + Block_8_5(); Rx_RORX_3( 9); Block_8_6(W_X); + Rx_RORX_1(10); Block_8_7(W_X); Rx_RORX_2(10); + Block_8_8(W_X); Rx_RORX_3(10); Block_8_9(); + Rx_RORX_1(11); Block_8_10();Rx_RORX_2(11); + Block_8_11();Rx_RORX_3(11); Block_8_12(W_X); + + Rx_RORX_1(12); Block_12_1(W_X); Rx_RORX_2(12); + Block_12_2(W_X); Rx_RORX_3(12); Block_12_3(); + Rx_RORX_1(13); Block_12_4(); Rx_RORX_2(13); + Block_12_5(); Rx_RORX_3(13); Block_12_6(W_X); + Rx_RORX_1(14); Block_12_7(W_X); Rx_RORX_2(14); + Block_12_8(W_X); Rx_RORX_3(14); Block_12_9(); + Rx_RORX_1(15); Block_12_10();Rx_RORX_2(15); + Block_12_11();Rx_RORX_3(15); Block_12_12(W_X); + } + + /* Add the working vars back into digest */ + + sha384->digest[0] += a(0); + sha384->digest[1] += b(0); + sha384->digest[2] += c(0); + sha384->digest[3] += d(0); + sha384->digest[4] += e(0); + sha384->digest[5] += f(0); + sha384->digest[6] += g(0); + sha384->digest[7] += h(0); + + /* Wipe variables */ + #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) + XMEMSET(W, 0, sizeof(word64) * 16); + #endif + XMEMSET(T, 0, sizeof(T)); + + return 0; +} +#endif + +#if defined(HAVE_INTEL_AVX2) + +static int Transform384_AVX2(Sha384* sha384) +{ + const word64* K = K512; + word64 w[4] ; + word32 j; + word64 T[8]; + + /* Copy digest to working vars */ + XMEMCPY(T, sha384->digest, sizeof(T)); + + /* over twice as small, but 50% slower */ + /* 80 operations, not unrolled */ + + W_from_buff_Y(sha384->buffer) ; + + MOVE_to_MEMy(w,0, W_0y) ; + for (j = 0; j < 80; j += 16) { + Ry_1( 0, w[0]); Block_Y_0_1(); Ry_2( 0, w[0]); + Block_Y_0_2(); Ry_3( 0, w[0]); Block_Y_0_3(); + Ry_1( 1, w[1]); Block_Y_0_4(); Ry_2( 1, w[1]); + Block_Y_0_5(); Ry_3( 1, w[1]); Block_Y_0_6(); + Ry_1( 2, w[2]); Block_Y_0_7(); Ry_2( 2, w[2]); + Block_Y_0_8(); Ry_3( 2, w[2]); Block_Y_0_9(); + Ry_1( 3, w[3]); Block_Y_0_10();Ry_2( 3, w[3]); + Block_Y_0_11();Ry_3( 3, w[3]); Block_Y_0_12(w); + + Ry_1( 4, w[0]); Block_Y_4_1(); Ry_2( 4, w[0]); + Block_Y_4_2(); Ry_3( 4, w[0]); Block_Y_4_3(); + Ry_1( 5, w[1]); Block_Y_4_4(); Ry_2( 5, w[1]); + Block_Y_4_5(); Ry_3( 5, w[1]); Block_Y_4_6(); + Ry_1( 6, w[2]); Block_Y_4_7(); Ry_2( 6, w[2]); + Block_Y_4_8(); Ry_3( 6, w[2]); Block_Y_4_9(); + Ry_1( 7, w[3]); Block_Y_4_10(); Ry_2( 7, w[3]); + Block_Y_4_11(); Ry_3( 7, w[3]);Block_Y_4_12(w); + + Ry_1( 8, w[0]); Block_Y_8_1(); Ry_2( 8, w[0]); + Block_Y_8_2(); Ry_3( 8, w[0]); Block_Y_8_3(); + Ry_1( 9, w[1]); Block_Y_8_4(); Ry_2( 9, w[1]); + Block_Y_8_5(); Ry_3( 9, w[1]); Block_Y_8_6(); + Ry_1(10, w[2]); Block_Y_8_7(); Ry_2(10, w[2]); + Block_Y_8_8(); Ry_3(10, w[2]); Block_Y_8_9(); + Ry_1(11, w[3]); Block_Y_8_10();Ry_2(11, w[3]); + Block_Y_8_11();Ry_3(11, w[3]); Block_Y_8_12(w); + + Ry_1(12, w[0]); Block_Y_12_1(); Ry_2(12, w[0]); + Block_Y_12_2(); Ry_3(12, w[0]); Block_Y_12_3(); + Ry_1(13, w[1]); Block_Y_12_4(); Ry_2(13, w[1]); + Block_Y_12_5(); Ry_3(13, w[1]); Block_Y_12_6(); + Ry_1(14, w[2]); Block_Y_12_7(); Ry_2(14, w[2]); + Block_Y_12_8(); Ry_3(14, w[2]); Block_Y_12_9(); + Ry_1(15, w[3]); Block_Y_12_10();Ry_2(15, w[3]); + Block_Y_12_11();Ry_3(15, w[3]); Block_Y_12_12(w); + } + + /* Add the working vars back into digest */ + + sha384->digest[0] += a(0); + sha384->digest[1] += b(0); + sha384->digest[2] += c(0); + sha384->digest[3] += d(0); + sha384->digest[4] += e(0); + sha384->digest[5] += f(0); + sha384->digest[6] += g(0); + sha384->digest[7] += h(0); + + /* Wipe variables */ + XMEMSET(T, 0, sizeof(T)); + + return 0; +} + +#endif + +#endif /* WOLFSSL_SHA384 */ + +#endif /* HAVE_FIPS */ + +#endif /* WOLFSSL_SHA512 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/tfm.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,2986 @@ +/* tfm.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 (moisesguimaraesm@gmail.com) + * to fit CyaSSL'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 + #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 */ + + +/* 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; + register 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; + 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; + } + 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; + + 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); + return ; + } + + /* 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 + */ + +#ifdef TFM_MUL3 + if (y <= 3) { + fp_mul_comba3(A,B,C); + return; + } +#endif +#ifdef TFM_MUL4 + if (y == 4) { + fp_mul_comba4(A,B,C); + return; + } +#endif +#ifdef TFM_MUL6 + if (y <= 6) { + fp_mul_comba6(A,B,C); + return; + } +#endif +#ifdef TFM_MUL7 + if (y == 7) { + fp_mul_comba7(A,B,C); + return; + } +#endif +#ifdef TFM_MUL8 + if (y == 8) { + fp_mul_comba8(A,B,C); + return; + } +#endif +#ifdef TFM_MUL9 + if (y == 9) { + fp_mul_comba9(A,B,C); + return; + } +#endif +#ifdef TFM_MUL12 + if (y <= 12) { + fp_mul_comba12(A,B,C); + return; + } +#endif +#ifdef TFM_MUL17 + if (y <= 17) { + fp_mul_comba17(A,B,C); + return; + } +#endif + +#ifdef TFM_SMALL_SET + if (y <= 16) { + fp_mul_comba_small(A,B,C); + return; + } +#endif +#if defined(TFM_MUL20) + if (y <= 20) { + fp_mul_comba20(A,B,C); + return; + } +#endif +#if defined(TFM_MUL24) + if (yy >= 16 && y <= 24) { + fp_mul_comba24(A,B,C); + return; + } +#endif +#if defined(TFM_MUL28) + if (yy >= 20 && y <= 28) { + fp_mul_comba28(A,B,C); + return; + } +#endif +#if defined(TFM_MUL32) + if (yy >= 24 && y <= 32) { + fp_mul_comba32(A,B,C); + return; + } +#endif +#if defined(TFM_MUL48) + if (yy >= 40 && y <= 48) { + fp_mul_comba48(A,B,C); + return; + } +#endif +#if defined(TFM_MUL64) + if (yy >= 56 && y <= 64) { + fp_mul_comba64(A,B,C); + return; + } +#endif + fp_mul_comba(A,B,C); +} + +void fp_mul_2(fp_int * a, fp_int * b) +{ + int x, oldused; + + oldused = b->used; + b->used = a->used; + + { + register 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); + } + + /* 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; +} + +/* 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; + } + 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) + +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; + } + + if (A == C || B == C) { + fp_init(&tmp); + dst = &tmp; + } else { + fp_zero(C); + dst = C; + } + + 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; + } + + if (A == C || B == C) { + fp_init(&tmp); + dst = &tmp; + } else { + fp_zero(C); + dst = C; + } + + for (ix = 0; ix < pa; ix++) { + /* get offsets into the two bignums */ + ty = MIN(ix, B->used-1); + 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) { + /* TAO change COMBA_ADD back to MULADD */ + 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) == 1) { + 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); + +/* the following is a kludge, essentially we were seeing the right remainder but + with excess digits that should have been zero + */ + 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; + { + register 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 excess digits */ + 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) == 1) { + 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) == 1 && fp_iseven (&y) == 1) { + 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) == 1) { + /* 4.1 u = u/2 */ + fp_div_2 (&u, &u); + + /* 4.2 if A or B is odd then */ + if (fp_isodd (&A) == 1 || fp_isodd (&B) == 1) { + /* 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) == 1) { + /* 5.1 v = v/2 */ + fp_div_2 (&v, &v); + + /* 5.2 if C or D is odd then */ + if (fp_isodd (&C) == 1 || fp_isodd (&D) == 1) { + /* 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) == 0) + 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, loop_check = 0; + + /* 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) { + if (++loop_check > 4096) /* bad input */ + return FP_VAL; + 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) +{ + fp_int tmp; + fp_init(&tmp); + fp_mul(a, b, &tmp); + return fp_mod(&tmp, c, d); +} + +#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) +{ + fp_int R[2]; + 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]); + + /* 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); + fp_sqr(&R[y], &R[y]); fp_montgomery_reduce(&R[y], P, mp); + } + + fp_montgomery_reduce(&R[0], P, mp); + fp_copy(&R[0], Y); + return FP_OKAY; +} + +#else + +/* 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 M[64], res; + fp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + + /* 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; + } + + /* init M array */ + for(x = 0; x < (int)(sizeof(M)/sizeof(fp_int)); x++) + fp_init(&M[x]); + + /* now setup montgomery */ + if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { + return err; + } + + /* 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 accept 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); + return FP_OKAY; +} + +#endif + +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 = A->used; + + /* call generic if we're out of range */ + if (y + y > FP_SIZE) { + fp_sqr_comba(A, B); + return ; + } + +#if defined(TFM_SQR3) + if (y <= 3) { + fp_sqr_comba3(A,B); + return; + } +#endif +#if defined(TFM_SQR4) + if (y == 4) { + fp_sqr_comba4(A,B); + return; + } +#endif +#if defined(TFM_SQR6) + if (y <= 6) { + fp_sqr_comba6(A,B); + return; + } +#endif +#if defined(TFM_SQR7) + if (y == 7) { + fp_sqr_comba7(A,B); + return; + } +#endif +#if defined(TFM_SQR8) + if (y == 8) { + fp_sqr_comba8(A,B); + return; + } +#endif +#if defined(TFM_SQR9) + if (y == 9) { + fp_sqr_comba9(A,B); + return; + } +#endif +#if defined(TFM_SQR12) + if (y <= 12) { + fp_sqr_comba12(A,B); + return; + } +#endif +#if defined(TFM_SQR17) + if (y <= 17) { + fp_sqr_comba17(A,B); + return; + } +#endif +#if defined(TFM_SMALL_SET) + if (y <= 16) { + fp_sqr_comba_small(A,B); + return; + } +#endif +#if defined(TFM_SQR20) + if (y <= 20) { + fp_sqr_comba20(A,B); + return; + } +#endif +#if defined(TFM_SQR24) + if (y <= 24) { + fp_sqr_comba24(A,B); + return; + } +#endif +#if defined(TFM_SQR28) + if (y <= 28) { + fp_sqr_comba28(A,B); + return; + } +#endif +#if defined(TFM_SQR32) + if (y <= 32) { + fp_sqr_comba32(A,B); + return; + } +#endif +#if defined(TFM_SQR48) + if (y <= 48) { + fp_sqr_comba48(A,B); + return; + } +#endif +#if defined(TFM_SQR64) + if (y <= 64) { + fp_sqr_comba64(A,B); + return; + } +#endif + fp_sqr_comba(A, B); +} + +/* 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; +} + +/* setups 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 INLINE void innermul8_mulx(fp_digit *c_mulx, fp_digit *cy_mulx, fp_digit *tmpm, fp_digit mu) +{ + fp_digit _c0, _c1, _c2, _c3, _c4, _c5, _c6, _c7, cy ; + + cy = *cy_mulx ; + _c0=c_mulx[0]; _c1=c_mulx[1]; _c2=c_mulx[2]; _c3=c_mulx[3]; _c4=c_mulx[4]; _c5=c_mulx[5]; _c6=c_mulx[6]; _c7=c_mulx[7]; + INNERMUL8_MULX ; + c_mulx[0]=_c0; c_mulx[1]=_c1; c_mulx[2]=_c2; c_mulx[3]=_c3; c_mulx[4]=_c4; c_mulx[5]=_c5; c_mulx[6]=_c6; c_mulx[7]=_c7; + *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++; + } + + 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(TFM_SSE2) || defined(TFM_X86_64)) + 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++; + } + + 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, unsigned char *b, int c) +{ + /* zero the int */ + fp_zero (a); + + /* 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; + + if ((unsigned)c > (FP_SIZE * sizeof(fp_digit))) { + int excess = c - (FP_SIZE * sizeof(fp_digit)); + c -= excess; + b += excess; + } + 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++; + a->used += 1; + } +#endif + fp_clamp (a); +} + +void fp_to_unsigned_bin(fp_int *a, unsigned char *b) +{ + int x; + fp_int t; + + fp_init_copy(&t, a); + + x = 0; + while (fp_iszero (&t) == FP_NO) { + b[x++] = (unsigned char) (t.dp[0] & 255); + fp_div_2d (&t, 8, &t, NULL); + } + 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; +} + +/* chek 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) +{ + register 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; + } +} + + +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); + 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; +} + +#ifdef ALT_ECC_SIZE +void fp_init(fp_int *a) +{ + a->size = FP_SIZE; + fp_zero(a); +} + +void fp_zero(fp_int *a) +{ + a->used = 0; + a->sign = FP_ZPOS; + XMEMSET(a->dp, 0, a->size * sizeof(fp_digit)); +} + +void fp_clear(fp_int *a) +{ + a->used = 0; + a->sign = FP_ZPOS; + ForceZero(a->dp, a->size * sizeof(fp_digit)); +} +#endif + + +/* clear one (frees) */ +void mp_clear (mp_int * a) +{ + fp_clear(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) */ +int mp_mul (mp_int * a, mp_int * b, mp_int * c) +{ + fp_mul(a, b, c); + return MP_OKAY; +} + +/* d = a * b (mod c) */ +int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + return fp_mulmod(a, b, c, d); +} + +/* c = a mod b, 0 <= c < b */ +int mp_mod (mp_int * a, mp_int * b, mp_int * c) +{ + return fp_mod (a, b, c); +} + +/* hac 14.61, pp608 */ +int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + 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) + */ +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + 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); +} + +/* 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, (unsigned char *)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_div_2d(fp_int* a, int b, fp_int* c, fp_int* d) +{ + fp_div_2d(a, b, c, d); + return MP_OKAY; +} + +#ifdef ALT_ECC_SIZE +void fp_copy(fp_int *a, fp_int* b) +{ + if (a != b && b->size >= a->used) { + b->used = a->used; + b->sign = a->sign; + + XMEMCPY(b->dp, a->dp, a->used * sizeof(fp_digit)); + } +} + +void fp_init_copy(fp_int *a, fp_int* b) +{ + if (a != b) { + fp_init(a); + fp_copy(b, a); + } +} +#endif + +/* fast math conversion */ +int mp_copy(fp_int* a, fp_int* b) +{ + fp_copy(a, b); + return MP_OKAY; +} + + +/* fast math conversion */ +int mp_isodd(mp_int* a) +{ + return fp_isodd(a); +} + + +/* fast math conversion */ +int mp_iszero(mp_int* a) +{ + return fp_iszero(a); +} + + +/* fast math conversion */ +int mp_count_bits (mp_int* a) +{ + return fp_count_bits(a); +} + + +int mp_leading_bit (mp_int* a) +{ + return fp_leading_bit(a); +} + + +/* fast math conversion */ +void mp_rshb (mp_int* a, int x) +{ + fp_rshb(a, x); +} + + +/* fast math wrappers */ +int mp_set_int(mp_int *a, mp_digit b) +{ + fp_set(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) +{ + fp_int tmp; + fp_init(&tmp); + fp_sqr(a, &tmp); + return fp_mod(&tmp, b, c); +} + +/* 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) + +static const int lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +#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 + +/* 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) == 1) { + 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 0; + } + + for (x = 0; x < DIGIT_BIT; x++) { + if (b == (((fp_digit)1)<<x)) { + *p = x; + return 1; + } + } + return 0; +} + +/* 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; + + /* cannot divide by zero */ + if (b == 0) { + return FP_VAL; + } + + /* quick outs */ + if (b == 1 || fp_iszero(a) == 1) { + 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) == 1) { + 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) { + /* no easy answer [c'est la vie]. Just division */ + fp_init(&q); + + 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) */ + +#ifdef WOLFSSL_KEY_GEN + +void fp_gcd(fp_int *a, fp_int *b, fp_int *c); +void fp_lcm(fp_int *a, fp_int *b, fp_int *c); +int fp_isprime(fp_int *a); +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; + break; + case FP_MEM: + return MP_MEM; + break; + 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[256] = { + 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(fp_int *a) +{ + fp_int b; + fp_digit d = 0; + int r, res; + + /* do trial division */ + for (r = 0; r < 256; r++) { + fp_mod_d(a, primes[r], &d); + if (d == 0) { + return FP_NO; + } + } + + /* now do 8 miller rabins */ + fp_init(&b); + for (r = 0; r < 8; 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_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) == 1 && fp_iszero (b) == 0) { + fp_abs (b, c); + return; + } + if (fp_iszero (a) == 0 && fp_iszero (b) == 1) { + fp_abs (a, c); + return; + } + + /* optimized. At this point if a == 0 then + * b must equal zero too + */ + if (fp_iszero (a) == 1) { + 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) +/* 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(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) + +/* chars used in radix conversions */ +static const char *fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz+/"; +#endif + +#ifdef HAVE_ECC +static int fp_read_radix(fp_int *a, const char *str, int radix) +{ + int y, neg; + char ch; + + /* 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; + } + + /* set the integer to the default of zero */ + fp_zero (a); + + /* 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); +} + +/* fast math conversion */ +void mp_set(fp_int *a, fp_digit b) +{ + fp_set(a,b); +} + +/* 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) +{ + fp_cnt_lsb(a); + return MP_OKAY; +} + +#endif /* HAVE_COMP_KEY */ + +#endif /* HAVE_ECC */ + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) + +/* 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) == 1) { + *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) == 0) { + 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; +} + +#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ + +#endif /* USE_FAST_MATH */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/wc_port.c Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,735 @@ +/* port.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> + +/* IPP header files for library initialization */ +#ifdef HAVE_FAST_RSA +#include <ipp.h> +#include <ippcp.h> +#endif + +#ifdef _MSC_VER + /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ + #pragma warning(disable: 4996) +#endif + + +/* Used to initialize state for wolfcrypt + return 0 on success + */ +int wolfCrypt_Init() +{ + int ret = 0; + #if WOLFSSL_CRYPT_HW_MUTEX + /* If crypto hardware mutex protection is enabled, then initialize it */ + wolfSSL_CryptHwMutexInit(); + #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; + } + #endif + + return ret; +} + + +#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 = 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 = LockMutex(&wcCryptHwMutex); + } + return ret; +} + +int wolfSSL_CryptHwMutexUnLock(void) { + int ret = BAD_MUTEX_E; + + if(wcCryptHwMutexInit) { + ret = UnLockMutex(&wcCryptHwMutex); + } + return ret; +} +#endif /* WOLFSSL_CRYPT_HW_MUTEX */ + + +#ifdef SINGLE_THREADED + +int InitMutex(wolfSSL_Mutex* m) +{ + (void)m; + return 0; +} + + +int FreeMutex(wolfSSL_Mutex *m) +{ + (void)m; + return 0; +} + + +int LockMutex(wolfSSL_Mutex *m) +{ + (void)m; + return 0; +} + + +int UnLockMutex(wolfSSL_Mutex *m) +{ + (void)m; + return 0; +} + +#else /* MULTI_THREAD */ + + #if defined(FREERTOS) || defined(FREERTOS_TCP) || \ + defined(FREESCALE_FREE_RTOS) + + int InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + + *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); + if( *m != NULL ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; + + return iReturn; + } + + int FreeMutex(wolfSSL_Mutex* m) + { + vSemaphoreDelete( *m ); + return 0; + } + + int LockMutex(wolfSSL_Mutex* m) + { + /* Assume an infinite block, or should there be zero block? */ + xSemaphoreTake( *m, portMAX_DELAY ); + return 0; + } + + int UnLockMutex(wolfSSL_Mutex* m) + { + xSemaphoreGive( *m ); + return 0; + } + + #elif defined(WOLFSSL_SAFERTOS) + + int InitMutex(wolfSSL_Mutex* m) + { + vSemaphoreCreateBinary(m->mutexBuffer, m->mutex); + if (m->mutex == NULL) + return BAD_MUTEX_E; + + return 0; + } + + int FreeMutex(wolfSSL_Mutex* m) + { + (void)m; + return 0; + } + + int LockMutex(wolfSSL_Mutex* m) + { + /* Assume an infinite block */ + xSemaphoreTake(m->mutex, portMAX_DELAY); + return 0; + } + + int UnLockMutex(wolfSSL_Mutex* m) + { + xSemaphoreGive(m->mutex); + return 0; + } + + + #elif defined(USE_WINDOWS_API) + + int InitMutex(wolfSSL_Mutex* m) + { + InitializeCriticalSection(m); + return 0; + } + + + int FreeMutex(wolfSSL_Mutex* m) + { + DeleteCriticalSection(m); + return 0; + } + + + int LockMutex(wolfSSL_Mutex* m) + { + EnterCriticalSection(m); + return 0; + } + + + int UnLockMutex(wolfSSL_Mutex* m) + { + LeaveCriticalSection(m); + return 0; + } + + #elif defined(WOLFSSL_PTHREADS) + + int InitMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_init(m, 0) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int FreeMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_destroy(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int LockMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_lock(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int UnLockMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_unlock(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + #elif defined(THREADX) + + int InitMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int FreeMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_delete(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int LockMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int UnLockMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_put(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + #elif defined(MICRIUM) + + int InitMutex(wolfSSL_Mutex* m) + { + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + if (NetSecure_OS_MutexCreate(m) == 0) + return 0; + else + return BAD_MUTEX_E; + #else + return 0; + #endif + } + + + int FreeMutex(wolfSSL_Mutex* m) + { + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + if (NetSecure_OS_FreeMutex(m) == 0) + return 0; + else + return BAD_MUTEX_E; + #else + return 0; + #endif + } + + + int LockMutex(wolfSSL_Mutex* m) + { + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + if (NetSecure_OS_LockMutex(m) == 0) + return 0; + else + return BAD_MUTEX_E; + #else + return 0; + #endif + } + + + int UnLockMutex(wolfSSL_Mutex* m) + { + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + if (NetSecure_OS_UnLockMutex(m) == 0) + return 0; + else + return BAD_MUTEX_E; + #else + return 0; + #endif + + } + + #elif defined(EBSNET) + + int InitMutex(wolfSSL_Mutex* m) + { + if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1) + return BAD_MUTEX_E; + else + return 0; + } + + int FreeMutex(wolfSSL_Mutex* m) + { + rtp_sig_mutex_free(*m); + return 0; + } + + int LockMutex(wolfSSL_Mutex* m) + { + if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + int UnLockMutex(wolfSSL_Mutex* m) + { + rtp_sig_mutex_release(*m); + return 0; + } + + #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + + int InitMutex(wolfSSL_Mutex* m) + { + if (_mutex_init(m, NULL) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int FreeMutex(wolfSSL_Mutex* m) + { + if (_mutex_destroy(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int LockMutex(wolfSSL_Mutex* m) + { + if (_mutex_lock(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int 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 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); + } else return 0; + } + + int FreeMutex(wolfSSL_Mutex* m) + { + Semaphore_delete(m); + + return 0; + } + + int LockMutex(wolfSSL_Mutex* m) + { + Semaphore_pend(*m, BIOS_WAIT_FOREVER); + + return 0; + } + + int UnLockMutex(wolfSSL_Mutex* m) + { + Semaphore_post(*m); + + return 0; + } + + #elif defined(WOLFSSL_uITRON4) + #include "stddef.h" + #include "kernel.h" + int 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 FreeMutex(wolfSSL_Mutex* m) + { + del_sem( m->id ); + return 0; + } + + int LockMutex(wolfSSL_Mutex* m) + { + wai_sem(m->id); + return 0; + } + + int 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) + #include "tk/tkernel.h" + int 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 FreeMutex(wolfSSL_Mutex* m) + { + tk_del_sem( m->id ); + return 0; + } + + int LockMutex(wolfSSL_Mutex* m) + { + tk_wai_sem(m->id, 1, TMO_FEVR); + return 0; + } + + int 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 = + {(void *)NULL, + TA_TFIFO , 0, "wolfSSL_MPOOL"}; + + 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 -1; + } + } + + 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_MDK_ARM)|| defined(WOLFSSL_CMSIS_RTOS) + + #if defined(WOLFSSL_CMSIS_RTOS) + #include "cmsis_os.h" + #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 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 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 LockMutex(wolfSSL_Mutex* m) + { + osMutexWait(*m, osWaitForever) ; + return(0) ; + } + + int UnLockMutex(wolfSSL_Mutex* m) + { + osMutexRelease (*m); + return 0; + } + #else + int InitMutex(wolfSSL_Mutex* m) + { + os_mut_init (m); + return 0; + } + + int FreeMutex(wolfSSL_Mutex* m) + { + return(0) ; + } + + int LockMutex(wolfSSL_Mutex* m) + { + os_mut_wait (m, 0xffff); + return(0) ; + } + + int UnLockMutex(wolfSSL_Mutex* m) + { + os_mut_release (m); + return 0; + } + #endif + #endif /* USE_WINDOWS_API */ + +#endif /* SINGLE_THREADED */ + +#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 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/callbacks.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,82 @@ +/* callbacks.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_CALLBACKS_H +#define WOLFSSL_CALLBACKS_H + +#include <sys/time.h> + +#ifdef __cplusplus + extern "C" { +#endif + + +enum { /* CALLBACK CONTSTANTS */ + MAX_PACKETNAME_SZ = 24, + MAX_CIPHERNAME_SZ = 24, + MAX_TIMEOUT_NAME_SZ = 24, + MAX_PACKETS_HANDSHAKE = 14, /* 12 for client auth plus 2 alerts */ + MAX_VALUE_SZ = 128, /* all handshake packets but Cert should + fit here */ +}; + + +typedef struct handShakeInfo_st { + char cipherName[MAX_CIPHERNAME_SZ + 1]; /* negotiated cipher */ + char packetNames[MAX_PACKETS_HANDSHAKE][MAX_PACKETNAME_SZ + 1]; + /* SSL packet names */ + int numberPackets; /* actual # of packets */ + int negotiationError; /* cipher/parameter err */ +} HandShakeInfo; + + +typedef struct timeval Timeval; + + +typedef struct packetInfo_st { + char packetName[MAX_PACKETNAME_SZ + 1]; /* SSL packet name */ + Timeval timestamp; /* when it occurred */ + unsigned char value[MAX_VALUE_SZ]; /* if fits, it's here */ + unsigned char* bufferValue; /* otherwise here (non 0) */ + int valueSz; /* sz of value or buffer */ +} PacketInfo; + + +typedef struct timeoutInfo_st { + char timeoutName[MAX_TIMEOUT_NAME_SZ + 1]; /* timeout Name */ + int flags; /* for future use */ + int numberPackets; /* actual # of packets */ + PacketInfo packets[MAX_PACKETS_HANDSHAKE]; /* list of all packets */ + Timeval timeoutValue; /* timer that caused it */ +} TimeoutInfo; + + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFSSL_CALLBACKS_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/certs_test.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1580 @@ +/* certs_test.h */ + +#ifndef WOLFSSL_CERTS_TEST_H +#define WOLFSSL_CERTS_TEST_H + +#ifdef USE_CERT_BUFFERS_1024 + +/* ./certs/1024/client-key.der, 1024-bit */ +static const unsigned char client_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5C, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xBC, 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, 0xA9, + 0xEF, 0x18, 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, 0xEC, + 0xB3, 0x6D, 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, 0xEC, + 0xD1, 0x61, 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, 0x94, + 0xCA, 0xC1, 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, 0x4D, + 0xC4, 0x61, 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, 0x25, + 0xBB, 0x8D, 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, 0xCC, + 0x39, 0xA2, 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, 0xDA, + 0x4D, 0x02, 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, 0x77, + 0xC9, 0x28, 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, 0x4C, + 0xE8, 0xC1, 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, 0xAE, + 0xF6, 0x90, 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, 0x67, + 0xC8, 0xDC, 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x13, 0x97, 0xEA, + 0xE8, 0x38, 0x78, 0x25, 0xA2, 0x5C, 0x04, 0xCE, 0x0D, 0x40, + 0x7C, 0x31, 0xE5, 0xC4, 0x70, 0xCD, 0x9B, 0x82, 0x3B, 0x58, + 0x09, 0x86, 0x3B, 0x66, 0x5F, 0xDC, 0x31, 0x90, 0xF1, 0x4F, + 0xD5, 0xDB, 0x15, 0xDD, 0xDE, 0xD7, 0x3B, 0x95, 0x93, 0x31, + 0x18, 0x31, 0x0E, 0x5E, 0xA3, 0xD6, 0xA2, 0x1A, 0x71, 0x6E, + 0x81, 0x48, 0x1C, 0x4B, 0xCF, 0xDB, 0x8E, 0x7A, 0x86, 0x61, + 0x32, 0xDC, 0xFB, 0x55, 0xC1, 0x16, 0x6D, 0x27, 0x92, 0x24, + 0x45, 0x8B, 0xF1, 0xB8, 0x48, 0xB1, 0x4B, 0x1D, 0xAC, 0xDE, + 0xDA, 0xDD, 0x8E, 0x2F, 0xC2, 0x91, 0xFB, 0xA5, 0xA9, 0x6E, + 0xF8, 0x3A, 0x6A, 0xF1, 0xFD, 0x50, 0x18, 0xEF, 0x9F, 0xE7, + 0xC3, 0xCA, 0x78, 0xEA, 0x56, 0xD3, 0xD3, 0x72, 0x5B, 0x96, + 0xDD, 0x4E, 0x06, 0x4E, 0x3A, 0xC3, 0xD9, 0xBE, 0x72, 0xB6, + 0x65, 0x07, 0x07, 0x4C, 0x01, 0x02, 0x41, 0x00, 0xFA, 0x47, + 0xD4, 0x7A, 0x7C, 0x92, 0x3C, 0x55, 0xEF, 0x81, 0xF0, 0x41, + 0x30, 0x2D, 0xA3, 0xCF, 0x8F, 0x1C, 0xE6, 0x87, 0x27, 0x05, + 0x70, 0x0D, 0xDF, 0x98, 0x35, 0xD6, 0xF1, 0x8B, 0x38, 0x2F, + 0x24, 0xB5, 0xD0, 0x84, 0xB6, 0x79, 0x4F, 0x71, 0x29, 0x94, + 0x5A, 0xF0, 0x64, 0x6A, 0xAC, 0xE7, 0x72, 0xC6, 0xED, 0x4D, + 0x59, 0x98, 0x3E, 0x67, 0x3A, 0xF3, 0x74, 0x2C, 0xF9, 0x61, + 0x17, 0x69, 0x02, 0x41, 0x00, 0xC0, 0xC1, 0x82, 0x0D, 0x0C, + 0xEB, 0xC6, 0x2F, 0xDC, 0x92, 0xF9, 0x9D, 0x82, 0x1A, 0x31, + 0xE9, 0xE9, 0xF7, 0x4B, 0xF2, 0x82, 0x87, 0x1C, 0xEE, 0x16, + 0x6A, 0xD1, 0x1D, 0x18, 0x82, 0x70, 0xF3, 0xC0, 0xB6, 0x2F, + 0xF6, 0xF3, 0xF7, 0x1D, 0xF1, 0x86, 0x23, 0xC8, 0x4E, 0xEB, + 0x8F, 0x56, 0x8E, 0x8F, 0xF5, 0xBF, 0xF1, 0xF7, 0x2B, 0xB5, + 0xCC, 0x3D, 0xC6, 0x57, 0x39, 0x0C, 0x1B, 0x54, 0x41, 0x02, + 0x41, 0x00, 0x9D, 0x7E, 0x05, 0xDE, 0xED, 0xF4, 0xB7, 0xB2, + 0xFB, 0xFC, 0x30, 0x4B, 0x55, 0x1D, 0xE3, 0x2F, 0x01, 0x47, + 0x96, 0x69, 0x05, 0xCD, 0x0E, 0x2E, 0x2C, 0xBD, 0x83, 0x63, + 0xB6, 0xAB, 0x7C, 0xB7, 0x6D, 0xCA, 0x5B, 0x64, 0xA7, 0xCE, + 0xBE, 0x86, 0xDF, 0x3B, 0x53, 0xDE, 0x61, 0xD2, 0x1E, 0xEB, + 0xA5, 0xF6, 0x37, 0xED, 0xAC, 0xAB, 0x78, 0xD9, 0x4C, 0xE7, + 0x55, 0xFB, 0xD7, 0x11, 0x99, 0xC1, 0x02, 0x40, 0x18, 0x98, + 0x18, 0x29, 0xE6, 0x1E, 0x27, 0x39, 0x70, 0x21, 0x68, 0xAC, + 0x0A, 0x2F, 0xA1, 0x72, 0xC1, 0x21, 0x86, 0x95, 0x38, 0xC6, + 0x58, 0x90, 0xA0, 0x57, 0x9C, 0xBA, 0xE3, 0xA7, 0xB1, 0x15, + 0xC8, 0xDE, 0xF6, 0x1B, 0xC2, 0x61, 0x23, 0x76, 0xEF, 0xB0, + 0x9D, 0x1C, 0x44, 0xBE, 0x13, 0x43, 0x39, 0x67, 0x17, 0xC8, + 0x9D, 0xCA, 0xFB, 0xF5, 0x45, 0x64, 0x8B, 0x38, 0x82, 0x2C, + 0xF2, 0x81, 0x02, 0x40, 0x39, 0x89, 0xE5, 0x9C, 0x19, 0x55, + 0x30, 0xBA, 0xB7, 0x48, 0x8C, 0x48, 0x14, 0x0E, 0xF4, 0x9F, + 0x7E, 0x77, 0x97, 0x43, 0xE1, 0xB4, 0x19, 0x35, 0x31, 0x23, + 0x75, 0x9C, 0x3B, 0x44, 0xAD, 0x69, 0x12, 0x56, 0xEE, 0x00, + 0x61, 0x64, 0x16, 0x66, 0xD3, 0x7C, 0x74, 0x2B, 0x15, 0xB4, + 0xA2, 0xFE, 0xBF, 0x08, 0x6B, 0x1A, 0x5D, 0x3F, 0x90, 0x12, + 0xB1, 0x05, 0x86, 0x31, 0x29, 0xDB, 0xD9, 0xE2 +}; +static const int sizeof_client_key_der_1024 = sizeof(client_key_der_1024); + +/* ./certs/1024/client-keyPub.der, 1024-bit */ +static const unsigned char client_keypub_der_1024[] = +{ + 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, + 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xBC, + 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, 0xA9, 0xEF, 0x18, + 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, 0xEC, 0xB3, 0x6D, + 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, 0xEC, 0xD1, 0x61, + 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, 0x94, 0xCA, 0xC1, + 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, 0x4D, 0xC4, 0x61, + 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, 0x25, 0xBB, 0x8D, + 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, 0xCC, 0x39, 0xA2, + 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, 0xDA, 0x4D, 0x02, + 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, 0x77, 0xC9, 0x28, + 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, 0x4C, 0xE8, 0xC1, + 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, 0xAE, 0xF6, 0x90, + 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, 0x67, 0xC8, 0xDC, + 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, 0x02, 0x03, 0x01, + 0x00, 0x01 +}; +static const int sizeof_client_keypub_der_1024 = sizeof(client_keypub_der_1024); + +/* ./certs/1024/client-cert.der, 1024-bit */ +static const unsigned char client_cert_der_1024[] = +{ + 0x30, 0x82, 0x03, 0xF9, 0x30, 0x82, 0x03, 0x62, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xD3, 0xDF, 0x98, 0xC4, + 0x80, 0x1F, 0x1F, 0x6F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, + 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, + 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, + 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x31, 0x31, 0x32, 0x33, + 0x31, 0x32, 0x34, 0x39, 0x33, 0x37, 0x5A, 0x17, 0x0D, 0x31, + 0x38, 0x30, 0x38, 0x31, 0x39, 0x31, 0x32, 0x34, 0x39, 0x33, + 0x37, 0x5A, 0x30, 0x81, 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, + 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, + 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, + 0x53, 0x4C, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, + 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, + 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xBC, 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, + 0xA9, 0xEF, 0x18, 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, + 0xEC, 0xB3, 0x6D, 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, + 0xEC, 0xD1, 0x61, 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, + 0x94, 0xCA, 0xC1, 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, + 0x4D, 0xC4, 0x61, 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, + 0x25, 0xBB, 0x8D, 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, + 0xCC, 0x39, 0xA2, 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, + 0xDA, 0x4D, 0x02, 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, + 0x77, 0xC9, 0x28, 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, + 0x4C, 0xE8, 0xC1, 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, + 0xAE, 0xF6, 0x90, 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, + 0x67, 0xC8, 0xDC, 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x3B, 0x30, + 0x82, 0x01, 0x37, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0x81, 0x69, 0x0F, 0xF8, 0xDF, 0xDD, + 0xCF, 0x34, 0x29, 0xD5, 0x67, 0x75, 0x71, 0x85, 0xC7, 0x75, + 0x10, 0x69, 0x59, 0xEC, 0x30, 0x81, 0xD3, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x81, 0xCB, 0x30, 0x81, 0xC8, 0x80, 0x14, + 0x81, 0x69, 0x0F, 0xF8, 0xDF, 0xDD, 0xCF, 0x34, 0x29, 0xD5, + 0x67, 0x75, 0x71, 0x85, 0xC7, 0x75, 0x10, 0x69, 0x59, 0xEC, + 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, 0x9E, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, + 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x31, 0x30, 0x32, + 0x34, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, + 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, + 0xD3, 0xDF, 0x98, 0xC4, 0x80, 0x1F, 0x1F, 0x6F, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x32, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30, 0x24, 0x30, 0x22, + 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, + 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6C, + 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, 0x3A, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x81, 0x81, 0x00, 0x71, 0x39, 0xFA, 0x86, 0xC3, 0x54, 0xE5, + 0x98, 0xB5, 0xE8, 0xC3, 0xCB, 0x97, 0x2F, 0x86, 0xBF, 0xE8, + 0xBC, 0xFB, 0xEB, 0xD8, 0x73, 0x97, 0x34, 0x9A, 0x16, 0xBF, + 0xE0, 0xB2, 0xBD, 0xBE, 0x7D, 0xFF, 0xA0, 0xD7, 0xE6, 0xDB, + 0xA3, 0x52, 0x43, 0x41, 0x60, 0xF1, 0xD7, 0xC3, 0x63, 0xC0, + 0x9B, 0xE2, 0xB2, 0x28, 0x87, 0x70, 0x60, 0x5D, 0x2B, 0x5D, + 0x56, 0x15, 0x3C, 0xB1, 0x1E, 0x03, 0x53, 0x72, 0x39, 0x32, + 0xE2, 0x47, 0x85, 0xF7, 0x8B, 0xE8, 0x38, 0x50, 0xA9, 0xC9, + 0xD3, 0x52, 0x75, 0x0E, 0x16, 0x14, 0xA5, 0xA5, 0xC4, 0x9F, + 0x3E, 0x73, 0xD8, 0x38, 0x79, 0xBF, 0xF7, 0x9B, 0x4D, 0x0D, + 0xF3, 0xAA, 0xCE, 0xA2, 0x03, 0x84, 0x66, 0x14, 0xC9, 0x01, + 0xF5, 0x86, 0xA5, 0x66, 0xA1, 0xCA, 0x6A, 0x71, 0x5F, 0x2D, + 0x31, 0x8E, 0x1C, 0xCC, 0x0C, 0xE6, 0x46, 0x99, 0x5D, 0x0A, + 0x4C +}; +static const int sizeof_client_cert_der_1024 = sizeof(client_cert_der_1024); + +/* ./certs/1024/dh1024.der, 1024-bit */ +static const unsigned char dh_key_der_1024[] = +{ + 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xA4, 0xD2, 0xB8, + 0x6E, 0x78, 0xF5, 0xD9, 0xED, 0x2D, 0x7C, 0xDD, 0xB6, 0x16, + 0x86, 0x5A, 0x4B, 0x05, 0x76, 0x90, 0xDD, 0x66, 0x61, 0xB9, + 0x6D, 0x52, 0xA7, 0x1C, 0xAF, 0x62, 0xC6, 0x69, 0x47, 0x7B, + 0x39, 0xF2, 0xFB, 0x94, 0xEC, 0xBC, 0x79, 0xFF, 0x24, 0x5E, + 0xEF, 0x79, 0xBB, 0x59, 0xB2, 0xFC, 0xCA, 0x07, 0xD6, 0xF4, + 0xE9, 0x34, 0xF7, 0xE8, 0x38, 0xE7, 0xD7, 0x33, 0x44, 0x1D, + 0xA3, 0x64, 0x76, 0x1A, 0x84, 0x97, 0x54, 0x74, 0x40, 0x84, + 0x1F, 0x15, 0xFE, 0x7C, 0x25, 0x2A, 0x2B, 0x25, 0xFD, 0x9E, + 0xC1, 0x89, 0x33, 0x8C, 0x39, 0x25, 0x2B, 0x40, 0xE6, 0xCD, + 0xF8, 0xA8, 0xA1, 0x8A, 0x53, 0xC6, 0x47, 0xB2, 0xA0, 0xD7, + 0x8F, 0xEB, 0x2E, 0x60, 0x0A, 0x0D, 0x4B, 0xF8, 0xB4, 0x94, + 0x8C, 0x63, 0x0A, 0xAD, 0xC7, 0x10, 0xEA, 0xC7, 0xA1, 0xB9, + 0x9D, 0xF2, 0xA8, 0x37, 0x73, 0x02, 0x01, 0x02 +}; +static const int sizeof_dh_key_der_1024 = sizeof(dh_key_der_1024); + +/* ./certs/1024/dsa1024.der, 1024-bit */ +static const unsigned char dsa_key_der_1024[] = +{ + 0x30, 0x82, 0x01, 0xBC, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xF7, 0x4B, 0xF9, 0xBB, 0x15, 0x98, 0xEB, 0xDD, 0xDE, + 0x1E, 0x4E, 0x71, 0x88, 0x85, 0xF2, 0xB7, 0xBA, 0xE2, 0x4A, + 0xDA, 0x76, 0x40, 0xCD, 0x69, 0x48, 0x9E, 0x83, 0x7C, 0x11, + 0xF7, 0x65, 0x31, 0x78, 0xF5, 0x25, 0x2D, 0xF7, 0xB7, 0xF8, + 0x52, 0x3F, 0xBE, 0xD8, 0xB6, 0xC5, 0xFE, 0x18, 0x15, 0x5B, + 0xB9, 0xD5, 0x92, 0x86, 0xBC, 0xB2, 0x17, 0x7C, 0xD8, 0xB0, + 0xBE, 0xA0, 0x7C, 0xF2, 0xD5, 0x73, 0x7A, 0x58, 0x8F, 0x8D, + 0xE5, 0x4A, 0x00, 0x99, 0x83, 0x4A, 0xC0, 0x9E, 0x16, 0x09, + 0xA1, 0x10, 0x34, 0xD5, 0x19, 0xBB, 0x63, 0xE3, 0xDD, 0x83, + 0x74, 0x7F, 0x10, 0xCA, 0x73, 0x75, 0xEE, 0x31, 0x4A, 0xDD, + 0x9F, 0xE0, 0x02, 0x6A, 0x9D, 0xEE, 0xB2, 0x4B, 0xA7, 0x6B, + 0x2A, 0x6C, 0xC7, 0x86, 0x77, 0xE8, 0x04, 0x15, 0xDC, 0x92, + 0xB4, 0x7A, 0x29, 0x1F, 0x4E, 0x83, 0x63, 0x85, 0x55, 0x02, + 0x15, 0x00, 0xD2, 0x05, 0xE4, 0x73, 0xFB, 0xC1, 0x99, 0xC5, + 0xDC, 0x68, 0xA4, 0x8D, 0x92, 0x27, 0x3D, 0xE2, 0x52, 0x5F, + 0x89, 0x8B, 0x02, 0x81, 0x81, 0x00, 0xAA, 0x21, 0x02, 0x09, + 0x43, 0x6E, 0xFB, 0xA2, 0x54, 0x14, 0x85, 0x0A, 0xF4, 0x28, + 0x7C, 0xCB, 0xCC, 0xDB, 0xF5, 0x1E, 0xA2, 0x18, 0xA9, 0x21, + 0xDE, 0x88, 0x88, 0x33, 0x8C, 0x2E, 0xEB, 0x8D, 0xA3, 0xF0, + 0x1D, 0xC8, 0x8F, 0xF6, 0x7E, 0xF8, 0xCF, 0x12, 0xF5, 0xB4, + 0xA1, 0x11, 0x6F, 0x0C, 0xD4, 0xF0, 0x06, 0xAD, 0xC4, 0xFC, + 0x14, 0x45, 0xC7, 0x94, 0x15, 0xBC, 0x19, 0x4B, 0xAE, 0xEF, + 0x93, 0x6A, 0x4F, 0xCC, 0x14, 0xD8, 0x47, 0x8B, 0x39, 0x66, + 0x87, 0x02, 0xD4, 0x28, 0x0A, 0xB8, 0xEE, 0x09, 0x37, 0xF4, + 0x00, 0xA0, 0x04, 0xA7, 0x79, 0xA7, 0xD2, 0x3C, 0xF7, 0x34, + 0x43, 0x56, 0x8E, 0xD0, 0x7C, 0xC2, 0xD8, 0x4D, 0x0F, 0x89, + 0xED, 0x14, 0xC1, 0x2C, 0x9C, 0x4C, 0x19, 0x9B, 0x9E, 0xDC, + 0x53, 0x09, 0x9F, 0xDF, 0x2D, 0xF0, 0x0C, 0x27, 0x54, 0x3A, + 0x77, 0x14, 0x2D, 0xDE, 0x02, 0x81, 0x81, 0x00, 0xE8, 0x1F, + 0x7C, 0xB7, 0xC0, 0x54, 0x51, 0xA7, 0x28, 0x2D, 0x58, 0x7C, + 0xDE, 0xD4, 0x5C, 0xDD, 0xD5, 0x76, 0x84, 0x3C, 0x36, 0x20, + 0xC0, 0xC3, 0x25, 0xD7, 0x3A, 0x38, 0xE1, 0x54, 0xC8, 0xFD, + 0x40, 0x68, 0x1A, 0x21, 0x54, 0x26, 0x39, 0x14, 0xBF, 0xF6, + 0xA3, 0x9C, 0x5E, 0xD9, 0x2B, 0xF7, 0xC9, 0x25, 0xBA, 0x00, + 0x09, 0xCB, 0x7F, 0x0C, 0x4A, 0x24, 0xFD, 0x15, 0x16, 0x15, + 0x48, 0xCD, 0x0B, 0x52, 0x44, 0x40, 0x7B, 0x90, 0x63, 0x2B, + 0x90, 0x22, 0xC5, 0x18, 0x05, 0x80, 0x53, 0xAF, 0x83, 0x1F, + 0x54, 0xE2, 0xB0, 0xA2, 0x0B, 0x5A, 0x92, 0x24, 0xE1, 0x62, + 0x28, 0x3F, 0xB7, 0xCA, 0xB9, 0x89, 0xD6, 0xA0, 0xB7, 0xAD, + 0xAE, 0x05, 0xE1, 0xC1, 0x59, 0x40, 0xED, 0x4A, 0x1B, 0x68, + 0xA7, 0x7B, 0xFB, 0xC3, 0x20, 0x81, 0xEF, 0x4B, 0xF3, 0x69, + 0x91, 0xB0, 0xCE, 0x3A, 0xB0, 0x38, 0x02, 0x14, 0x25, 0x38, + 0x3B, 0xA1, 0x19, 0x75, 0xDF, 0x9B, 0xF5, 0x72, 0x53, 0x4F, + 0x39, 0xE1, 0x1C, 0xEC, 0x13, 0x84, 0x82, 0x18 +}; +static const int sizeof_dsa_key_der_1024 = sizeof(dsa_key_der_1024); + +/* ./certs/1024/rsa1024.der, 1024-bit */ +static const unsigned char rsa_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5D, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xBE, 0x70, 0x70, 0xB8, 0x04, 0x18, 0xE5, 0x28, 0xFE, + 0x66, 0xD8, 0x90, 0x88, 0xE0, 0xF1, 0xB7, 0xC3, 0xD0, 0xD2, + 0x3E, 0xE6, 0x4B, 0x94, 0x74, 0xB0, 0xFF, 0xB0, 0xF7, 0x63, + 0xA5, 0xAB, 0x7E, 0xAF, 0xB6, 0x2B, 0xB7, 0x38, 0x16, 0x1A, + 0x50, 0xBF, 0xF1, 0xCA, 0x87, 0x3A, 0xD5, 0xB0, 0xDA, 0xF8, + 0x43, 0x7A, 0x15, 0xB9, 0x7E, 0xEA, 0x2A, 0x80, 0xD2, 0x51, + 0xB0, 0x35, 0xAF, 0x07, 0xF3, 0xF2, 0x5D, 0x24, 0x3A, 0x4B, + 0x87, 0x56, 0x48, 0x1B, 0x3C, 0x24, 0x9A, 0xDA, 0x70, 0x80, + 0xBD, 0x3C, 0x8B, 0x03, 0x4A, 0x0C, 0x83, 0x71, 0xDE, 0xE3, + 0x03, 0x70, 0xA2, 0xB7, 0x60, 0x09, 0x1B, 0x5E, 0xC7, 0x3D, + 0xA0, 0x64, 0x60, 0xE3, 0xA9, 0x06, 0x8D, 0xD3, 0xFF, 0x42, + 0xBB, 0x0A, 0x94, 0x27, 0x2D, 0x57, 0x42, 0x0D, 0xB0, 0x2D, + 0xE0, 0xBA, 0x18, 0x25, 0x60, 0x92, 0x11, 0x92, 0xF3, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x0E, 0xEE, 0x1D, + 0xC8, 0x2F, 0x7A, 0x0C, 0x2D, 0x44, 0x94, 0xA7, 0x91, 0xDD, + 0x49, 0x55, 0x6A, 0x04, 0xCE, 0x10, 0x4D, 0xA2, 0x1C, 0x76, + 0xCD, 0x17, 0x3B, 0x54, 0x92, 0x70, 0x9B, 0x82, 0x70, 0x72, + 0x32, 0x24, 0x07, 0x3F, 0x3C, 0x6C, 0x5F, 0xBC, 0x4C, 0xA6, + 0x86, 0x27, 0x94, 0xAD, 0x42, 0xDD, 0x87, 0xDC, 0xC0, 0x6B, + 0x44, 0x89, 0xF3, 0x3F, 0x1A, 0x3E, 0x11, 0x44, 0x84, 0x2E, + 0x69, 0x4C, 0xBB, 0x4A, 0x71, 0x1A, 0xBB, 0x9A, 0x52, 0x3C, + 0x6B, 0xDE, 0xBC, 0xB2, 0x7C, 0x51, 0xEF, 0x4F, 0x8F, 0x3A, + 0xDC, 0x50, 0x04, 0x4E, 0xB6, 0x31, 0x66, 0xA8, 0x8E, 0x06, + 0x3B, 0x51, 0xA9, 0xC1, 0x8A, 0xCB, 0xC4, 0x81, 0xCA, 0x2D, + 0x69, 0xEC, 0x88, 0xFC, 0x33, 0x88, 0xD1, 0xD4, 0x29, 0x47, + 0x87, 0x37, 0xF9, 0x6A, 0x22, 0x69, 0xB9, 0xC9, 0xFE, 0xEB, + 0x8C, 0xC5, 0x21, 0x41, 0x71, 0x02, 0x41, 0x00, 0xFD, 0x17, + 0x98, 0x42, 0x54, 0x1C, 0x23, 0xF8, 0xD7, 0x5D, 0xEF, 0x49, + 0x4F, 0xAF, 0xD9, 0x35, 0x6F, 0x08, 0xC6, 0xC7, 0x40, 0x5C, + 0x7E, 0x58, 0x86, 0xC2, 0xB2, 0x16, 0x39, 0x24, 0xC5, 0x06, + 0xB0, 0x3D, 0xAF, 0x02, 0xD2, 0x87, 0x77, 0xD2, 0x76, 0xBA, + 0xE3, 0x59, 0x60, 0x42, 0xF1, 0x16, 0xEF, 0x33, 0x0B, 0xF2, + 0x0B, 0xBA, 0x99, 0xCC, 0xB6, 0x4C, 0x46, 0x3F, 0x33, 0xE4, + 0xD4, 0x67, 0x02, 0x41, 0x00, 0xC0, 0xA0, 0x91, 0x6D, 0xFE, + 0x28, 0xE0, 0x81, 0x5A, 0x15, 0xA7, 0xC9, 0xA8, 0x98, 0xC6, + 0x0A, 0xAB, 0x00, 0xC5, 0x40, 0xC9, 0x21, 0xBB, 0xB2, 0x33, + 0x5A, 0xA7, 0xCB, 0x6E, 0xB8, 0x08, 0x56, 0x4A, 0x76, 0x28, + 0xE8, 0x6D, 0xBD, 0xF5, 0x26, 0x7B, 0xBF, 0xC5, 0x46, 0x45, + 0x0D, 0xEC, 0x7D, 0xEE, 0x82, 0xD6, 0xCA, 0x5F, 0x3D, 0x6E, + 0xCC, 0x94, 0x73, 0xCD, 0xCE, 0x86, 0x6E, 0x95, 0x95, 0x02, + 0x40, 0x38, 0xFD, 0x28, 0x1E, 0xBF, 0x5B, 0xBA, 0xC9, 0xDC, + 0x8C, 0xDD, 0x45, 0xAF, 0xB8, 0xD3, 0xFB, 0x11, 0x2E, 0x73, + 0xBC, 0x08, 0x05, 0x0B, 0xBA, 0x19, 0x56, 0x1B, 0xCD, 0x9F, + 0x3E, 0x65, 0x53, 0x15, 0x3A, 0x3E, 0x7F, 0x2F, 0x32, 0xAB, + 0xCB, 0x6B, 0x4A, 0xB7, 0xC8, 0xB7, 0x41, 0x3B, 0x92, 0x43, + 0x78, 0x46, 0x17, 0x51, 0x86, 0xC9, 0xFC, 0xEB, 0x8B, 0x8F, + 0x41, 0xCA, 0x08, 0x9B, 0xBF, 0x02, 0x41, 0x00, 0xAD, 0x9B, + 0x89, 0xB6, 0xF2, 0x8C, 0x70, 0xDA, 0xE4, 0x10, 0x04, 0x6B, + 0x11, 0x92, 0xAF, 0x5A, 0xCA, 0x08, 0x25, 0xBF, 0x60, 0x07, + 0x11, 0x1D, 0x68, 0x7F, 0x5A, 0x1F, 0x55, 0x28, 0x74, 0x0B, + 0x21, 0x8D, 0x21, 0x0D, 0x6A, 0x6A, 0xFB, 0xD9, 0xB5, 0x4A, + 0x7F, 0x47, 0xF7, 0xD0, 0xB6, 0xC6, 0x41, 0x02, 0x97, 0x07, + 0x49, 0x93, 0x1A, 0x9B, 0x33, 0x68, 0xB3, 0xA2, 0x61, 0x32, + 0xA5, 0x89, 0x02, 0x41, 0x00, 0x8F, 0xEF, 0xAD, 0xB5, 0xB0, + 0xB0, 0x7E, 0x86, 0x03, 0x43, 0x93, 0x6E, 0xDD, 0x3C, 0x2D, + 0x9B, 0x6A, 0x55, 0xFF, 0x6F, 0x3E, 0x70, 0x2A, 0xD4, 0xBF, + 0x1F, 0x8C, 0x93, 0x60, 0x9E, 0x6D, 0x2F, 0x18, 0x6C, 0x11, + 0x36, 0x98, 0x3F, 0x10, 0x78, 0xE8, 0x3E, 0x8F, 0xFE, 0x55, + 0xB9, 0x9E, 0xD5, 0x5B, 0x2E, 0x87, 0x1C, 0x58, 0xD0, 0x37, + 0x89, 0x96, 0xEC, 0x48, 0x54, 0xF5, 0x9F, 0x0F, 0xB3 +}; +static const int sizeof_rsa_key_der_1024 = sizeof(rsa_key_der_1024); + +/* ./certs/1024/ca-cert.der, 1024-bit */ +static const unsigned char ca_cert_der_1024[] = +{ + 0x30, 0x82, 0x03, 0xB5, 0x30, 0x82, 0x03, 0x1E, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x8F, 0x44, 0x26, 0xFF, + 0xB7, 0x43, 0xE1, 0x9A, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x81, 0x99, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, + 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, + 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, + 0x35, 0x30, 0x39, 0x32, 0x33, 0x31, 0x39, 0x32, 0x33, 0x33, + 0x38, 0x5A, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x36, 0x31, 0x39, + 0x31, 0x39, 0x32, 0x33, 0x33, 0x38, 0x5A, 0x30, 0x81, 0x99, + 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, + 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, + 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, + 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, + 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xCD, 0xAC, 0xDD, 0x47, 0xEC, 0xBE, 0xB7, 0x24, + 0xC3, 0x63, 0x1B, 0x54, 0x98, 0x79, 0xE1, 0xC7, 0x31, 0x16, + 0x59, 0xD6, 0x9D, 0x77, 0x9D, 0x8D, 0xE2, 0x8B, 0xED, 0x04, + 0x17, 0xB2, 0xC6, 0xEB, 0xE4, 0x9B, 0x91, 0xBE, 0x31, 0x50, + 0x62, 0x97, 0x58, 0xB5, 0x7F, 0x29, 0xDE, 0xB3, 0x71, 0x24, + 0x0B, 0xBF, 0x97, 0x09, 0x7F, 0x26, 0xDC, 0x2D, 0xEC, 0xA8, + 0x2E, 0xB2, 0x64, 0x2B, 0x7A, 0x2B, 0x35, 0x19, 0x2D, 0xA2, + 0x80, 0xCB, 0x99, 0xFD, 0x94, 0x71, 0x1B, 0x23, 0x8D, 0x54, + 0xDB, 0x2E, 0x62, 0x8D, 0x81, 0x08, 0x2D, 0xF4, 0x24, 0x72, + 0x27, 0x6C, 0xF9, 0xC9, 0x8E, 0xDB, 0x4C, 0x75, 0xBA, 0x9B, + 0x01, 0xF8, 0x3F, 0x18, 0xF4, 0xE6, 0x7F, 0xFB, 0x57, 0x94, + 0x92, 0xCC, 0x88, 0xC4, 0xB4, 0x00, 0xC2, 0xAA, 0xD4, 0xE5, + 0x88, 0x18, 0xB3, 0x11, 0x2F, 0x73, 0xC0, 0xD6, 0x29, 0x09, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x01, 0x30, + 0x81, 0xFE, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + 0x16, 0x04, 0x14, 0xD3, 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, + 0xEE, 0xD3, 0xED, 0xC3, 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, + 0x1D, 0xBF, 0xA8, 0x30, 0x81, 0xCE, 0x06, 0x03, 0x55, 0x1D, + 0x23, 0x04, 0x81, 0xC6, 0x30, 0x81, 0xC3, 0x80, 0x14, 0xD3, + 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, 0xEE, 0xD3, 0xED, 0xC3, + 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, 0x1D, 0xBF, 0xA8, 0xA1, + 0x81, 0x9F, 0xA4, 0x81, 0x9C, 0x30, 0x81, 0x99, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, + 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, + 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, + 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, + 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x82, 0x09, 0x00, 0x8F, 0x44, 0x26, 0xFF, 0xB7, 0x43, + 0xE1, 0x9A, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x03, 0x81, 0x81, 0x00, 0x0E, 0x46, 0xAC, 0xD8, 0x29, + 0x1D, 0x12, 0x12, 0x06, 0x0C, 0xD3, 0x3F, 0x7D, 0x58, 0x2E, + 0x0D, 0x11, 0x5E, 0x5D, 0x0D, 0xDD, 0x17, 0xC0, 0x0F, 0xAA, + 0x01, 0x4D, 0xA4, 0xC4, 0x84, 0x81, 0x6E, 0x64, 0xAE, 0xD1, + 0x5D, 0x58, 0xCD, 0x19, 0x6A, 0x74, 0xA4, 0x46, 0x2F, 0xC8, + 0x43, 0x79, 0x39, 0xC0, 0x91, 0x4B, 0x7C, 0x71, 0xEA, 0x4E, + 0x63, 0x44, 0x66, 0x15, 0x41, 0x15, 0xDE, 0x50, 0x82, 0xE3, + 0xE9, 0xD1, 0x55, 0x55, 0xCC, 0x5A, 0x38, 0x1E, 0x3A, 0x59, + 0xB3, 0x0E, 0xEE, 0x0E, 0x54, 0x4D, 0x93, 0xE7, 0xE0, 0x8E, + 0x27, 0xA5, 0x6E, 0x08, 0xB8, 0x6A, 0x39, 0xDA, 0x2D, 0x47, + 0x62, 0xC4, 0x5B, 0x89, 0xC0, 0x48, 0x48, 0x2A, 0xD5, 0xF0, + 0x55, 0x74, 0xFD, 0xA6, 0xB1, 0x68, 0x3C, 0x70, 0xA4, 0x52, + 0x24, 0x81, 0xEC, 0x4C, 0x57, 0xE0, 0xE8, 0x18, 0x73, 0x9D, + 0x0A, 0x4D, 0xD8 +}; +static const int sizeof_ca_cert_der_1024 = sizeof(ca_cert_der_1024); + +/* ./certs/1024/server-key.der, 1024-bit */ +static const unsigned char server_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5D, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xAA, 0x3E, 0xA5, 0x9C, 0xD3, 0x17, 0x49, 0x65, 0x43, + 0xDE, 0xD0, 0xF3, 0x4B, 0x1C, 0xDB, 0x49, 0x0C, 0xFC, 0x7A, + 0x65, 0x05, 0x6D, 0xDE, 0x6A, 0xC4, 0xE4, 0x73, 0x2C, 0x8A, + 0x96, 0x82, 0x8F, 0x23, 0xA5, 0x06, 0x71, 0x1C, 0x06, 0x3E, + 0x2F, 0x92, 0x8D, 0x0B, 0x29, 0x34, 0x45, 0x59, 0xE9, 0xA9, + 0xBC, 0x61, 0xD7, 0x24, 0x37, 0x5D, 0xB5, 0xC4, 0x37, 0x8D, + 0xBA, 0x67, 0xB2, 0xEF, 0x03, 0x27, 0xFA, 0xC1, 0xB4, 0xCD, + 0x6B, 0x00, 0x66, 0xB4, 0xD6, 0x73, 0x70, 0x1F, 0x08, 0x3A, + 0xCC, 0x77, 0xAD, 0xE9, 0xF9, 0x34, 0xD4, 0xF3, 0xA0, 0x2D, + 0xA9, 0xE7, 0x58, 0xA9, 0xC0, 0x61, 0x84, 0xB6, 0xEC, 0x3D, + 0x0A, 0xAD, 0xFD, 0x5C, 0x86, 0x73, 0xAA, 0x6B, 0x47, 0xD8, + 0x8B, 0x2E, 0x58, 0x4B, 0x69, 0x12, 0x82, 0x26, 0x55, 0xE6, + 0x14, 0xBF, 0x55, 0x70, 0x88, 0xFE, 0xF9, 0x75, 0xE1, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x0A, 0x4C, 0xC1, + 0xFE, 0x4B, 0xF3, 0x23, 0xB8, 0xA1, 0xB3, 0x90, 0x56, 0xB7, + 0xDB, 0xA6, 0x14, 0xB4, 0x59, 0x6E, 0x1A, 0x40, 0x8A, 0xD6, + 0x23, 0x05, 0x88, 0x80, 0xC3, 0x58, 0x1B, 0x25, 0x08, 0xFD, + 0xF2, 0x15, 0x02, 0xB0, 0xDC, 0x5B, 0xD4, 0xCA, 0xFC, 0x07, + 0x89, 0xD5, 0xA4, 0xC0, 0x7C, 0xD7, 0x8D, 0x13, 0x2A, 0x4E, + 0x01, 0x9F, 0x84, 0xC8, 0xBB, 0x47, 0xB2, 0xD8, 0x65, 0x45, + 0xFA, 0x84, 0x9F, 0x88, 0xD0, 0xF4, 0xF5, 0x22, 0x35, 0x77, + 0x11, 0x67, 0x1C, 0xDE, 0x5F, 0x85, 0x6D, 0x55, 0xD8, 0xA7, + 0x07, 0x15, 0x8C, 0xE1, 0xB0, 0xA7, 0x79, 0xB4, 0x47, 0x9D, + 0x70, 0xB3, 0xD2, 0xF1, 0x1F, 0x41, 0x4C, 0x65, 0x72, 0x26, + 0xEB, 0x66, 0xC8, 0x95, 0xF6, 0x6D, 0x87, 0x35, 0x53, 0xFE, + 0xB1, 0x52, 0x4D, 0x76, 0x5B, 0x61, 0x53, 0x89, 0xB1, 0x20, + 0x1A, 0x8B, 0xE4, 0x7D, 0xF1, 0x02, 0x41, 0x00, 0xD9, 0x6E, + 0xE1, 0xD9, 0x06, 0x56, 0xA1, 0xF6, 0xDF, 0x54, 0x45, 0xC5, + 0xEC, 0x6A, 0xC8, 0x2A, 0x38, 0x4E, 0x6B, 0xC6, 0xE8, 0xEA, + 0xFB, 0x6F, 0x65, 0x2D, 0xBA, 0xDE, 0x27, 0x63, 0x37, 0x21, + 0x2E, 0xA4, 0x55, 0xAB, 0xE7, 0xDB, 0xCE, 0x71, 0xE1, 0x08, + 0xFC, 0xF2, 0xCA, 0x52, 0x33, 0x55, 0xE8, 0x39, 0xB3, 0xDA, + 0xC5, 0xB0, 0x69, 0x84, 0x6E, 0xE3, 0xCF, 0x47, 0x80, 0xA6, + 0xB6, 0x85, 0x02, 0x41, 0x00, 0xC8, 0x71, 0x0D, 0x37, 0x47, + 0xE1, 0x7B, 0x21, 0x2D, 0x11, 0x2D, 0x95, 0x2E, 0xC7, 0xD0, + 0xB6, 0xD3, 0x7C, 0x5C, 0x93, 0x3C, 0x5B, 0x22, 0xE5, 0xE0, + 0x8B, 0x6D, 0x47, 0xF9, 0x14, 0x0F, 0x9E, 0x08, 0x1B, 0x53, + 0xAB, 0x0A, 0xA9, 0xE4, 0x7F, 0x40, 0xD3, 0xDF, 0x62, 0x74, + 0x10, 0xA2, 0xFE, 0x83, 0x1F, 0xCF, 0x55, 0x66, 0xEB, 0x5D, + 0xC5, 0x83, 0xBA, 0xEC, 0x9F, 0xD2, 0xB5, 0x06, 0xAD, 0x02, + 0x41, 0x00, 0xB7, 0x68, 0x19, 0xA7, 0xC7, 0xF9, 0xF1, 0x9A, + 0xDD, 0x5D, 0x27, 0x91, 0xC1, 0x4F, 0x7D, 0x52, 0x67, 0xB6, + 0x76, 0xA1, 0x0D, 0x3D, 0x91, 0x23, 0xB0, 0xB3, 0xF7, 0x49, + 0x86, 0xED, 0xE0, 0xC5, 0xE3, 0xA3, 0x09, 0x04, 0xFD, 0x89, + 0xE2, 0xC5, 0x1A, 0x6E, 0x4B, 0x77, 0xBD, 0x03, 0xC3, 0x7B, + 0xB6, 0x6C, 0x5D, 0xF2, 0xAF, 0x08, 0x94, 0xA8, 0xFA, 0x24, + 0xBD, 0x66, 0x71, 0xF5, 0xAE, 0x45, 0x02, 0x40, 0x15, 0x52, + 0xD1, 0x91, 0x1B, 0xF8, 0x84, 0xDC, 0xD6, 0xAA, 0x89, 0x2A, + 0xE1, 0xBB, 0x28, 0x1D, 0x0B, 0x0A, 0xA3, 0xDE, 0x96, 0x01, + 0x2C, 0x09, 0x40, 0x86, 0x14, 0xAE, 0x1F, 0x75, 0x5E, 0xE3, + 0xF5, 0x00, 0xD3, 0x39, 0xD2, 0xFC, 0x97, 0xEE, 0x61, 0xBB, + 0x28, 0x7C, 0x94, 0xD4, 0x60, 0x42, 0xAB, 0x38, 0x6B, 0x1A, + 0x2E, 0xC4, 0xC3, 0x49, 0x0B, 0xE6, 0x8A, 0xDD, 0xC5, 0xD0, + 0xB4, 0x51, 0x02, 0x41, 0x00, 0xA9, 0x8B, 0xA7, 0xA9, 0xEE, + 0xAE, 0xBB, 0x17, 0xCB, 0x72, 0xF2, 0x50, 0x22, 0x9D, 0xB3, + 0xDF, 0xE0, 0x40, 0x37, 0x08, 0xD5, 0x7F, 0x19, 0x58, 0x80, + 0x70, 0x79, 0x69, 0x99, 0xDF, 0x62, 0x0D, 0x21, 0xAB, 0xDD, + 0xB2, 0xCE, 0x68, 0xB3, 0x9F, 0x87, 0xAF, 0x55, 0xF4, 0xAA, + 0xE1, 0x00, 0x72, 0xBE, 0x6E, 0xC3, 0x94, 0x49, 0xDC, 0xBB, + 0x8E, 0x1A, 0x78, 0xE5, 0x49, 0x1F, 0x55, 0x41, 0xA1 +}; +static const int sizeof_server_key_der_1024 = sizeof(server_key_der_1024); + +/* ./certs/1024/server-cert.der, 1024-bit */ +static const unsigned char server_cert_der_1024[] = +{ + 0x30, 0x82, 0x03, 0xA9, 0x30, 0x82, 0x03, 0x12, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x99, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, + 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, + 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, + 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x1E, 0x17, + 0x0D, 0x31, 0x35, 0x30, 0x39, 0x32, 0x33, 0x31, 0x39, 0x32, + 0x33, 0x33, 0x38, 0x5A, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x36, + 0x31, 0x39, 0x31, 0x39, 0x32, 0x33, 0x33, 0x38, 0x5A, 0x30, + 0x81, 0x95, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0C, + 0x53, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x31, 0x30, + 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, + 0xAA, 0x3E, 0xA5, 0x9C, 0xD3, 0x17, 0x49, 0x65, 0x43, 0xDE, + 0xD0, 0xF3, 0x4B, 0x1C, 0xDB, 0x49, 0x0C, 0xFC, 0x7A, 0x65, + 0x05, 0x6D, 0xDE, 0x6A, 0xC4, 0xE4, 0x73, 0x2C, 0x8A, 0x96, + 0x82, 0x8F, 0x23, 0xA5, 0x06, 0x71, 0x1C, 0x06, 0x3E, 0x2F, + 0x92, 0x8D, 0x0B, 0x29, 0x34, 0x45, 0x59, 0xE9, 0xA9, 0xBC, + 0x61, 0xD7, 0x24, 0x37, 0x5D, 0xB5, 0xC4, 0x37, 0x8D, 0xBA, + 0x67, 0xB2, 0xEF, 0x03, 0x27, 0xFA, 0xC1, 0xB4, 0xCD, 0x6B, + 0x00, 0x66, 0xB4, 0xD6, 0x73, 0x70, 0x1F, 0x08, 0x3A, 0xCC, + 0x77, 0xAD, 0xE9, 0xF9, 0x34, 0xD4, 0xF3, 0xA0, 0x2D, 0xA9, + 0xE7, 0x58, 0xA9, 0xC0, 0x61, 0x84, 0xB6, 0xEC, 0x3D, 0x0A, + 0xAD, 0xFD, 0x5C, 0x86, 0x73, 0xAA, 0x6B, 0x47, 0xD8, 0x8B, + 0x2E, 0x58, 0x4B, 0x69, 0x12, 0x82, 0x26, 0x55, 0xE6, 0x14, + 0xBF, 0x55, 0x70, 0x88, 0xFE, 0xF9, 0x75, 0xE1, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x01, 0x30, 0x81, 0xFE, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xD9, 0x3C, 0x35, 0xEA, 0x74, 0x0E, 0x23, 0xBE, 0x9C, + 0xFC, 0xFA, 0x29, 0x90, 0x09, 0xC1, 0xE7, 0x84, 0x16, 0x9F, + 0x7C, 0x30, 0x81, 0xCE, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, + 0x81, 0xC6, 0x30, 0x81, 0xC3, 0x80, 0x14, 0xD3, 0x22, 0x8F, + 0x28, 0x2C, 0xE0, 0x05, 0xEE, 0xD3, 0xED, 0xC3, 0x71, 0x3D, + 0xC9, 0xB2, 0x36, 0x3A, 0x1D, 0xBF, 0xA8, 0xA1, 0x81, 0x9F, + 0xA4, 0x81, 0x9C, 0x30, 0x81, 0x99, 0x31, 0x0B, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, + 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, + 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, + 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, + 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, + 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, + 0x09, 0x00, 0x8F, 0x44, 0x26, 0xFF, 0xB7, 0x43, 0xE1, 0x9A, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, + 0x81, 0x81, 0x00, 0x0A, 0x04, 0xC7, 0x9A, 0xC4, 0xF6, 0x46, + 0xDB, 0xE4, 0x85, 0xD4, 0x22, 0x02, 0x12, 0x3E, 0x53, 0x27, + 0x25, 0x24, 0x8A, 0x9B, 0x2F, 0x93, 0x7F, 0xDE, 0x70, 0x94, + 0xC5, 0x6C, 0x4C, 0x26, 0x25, 0x25, 0x7A, 0xD7, 0x0F, 0x33, + 0xB9, 0x9C, 0xD2, 0x5A, 0x94, 0x7F, 0x8D, 0x30, 0x75, 0xAD, + 0x82, 0xC9, 0xBF, 0x4B, 0x6C, 0x91, 0x58, 0x7C, 0x45, 0x1A, + 0x89, 0xDF, 0x8E, 0xCA, 0x31, 0x9F, 0xAB, 0x38, 0xB3, 0xAE, + 0xC2, 0x8F, 0x14, 0x87, 0xE6, 0x1C, 0xAB, 0x12, 0x4E, 0xDF, + 0x82, 0x36, 0xC9, 0x41, 0x46, 0xC4, 0x05, 0x95, 0x88, 0x62, + 0x09, 0x72, 0x57, 0x66, 0x31, 0x80, 0xB8, 0x9C, 0x55, 0xA8, + 0xFB, 0x74, 0x01, 0x32, 0xE7, 0x5A, 0x40, 0xDF, 0x9B, 0xE4, + 0x98, 0xD7, 0x5B, 0xEA, 0x69, 0x5C, 0x14, 0x1B, 0x9B, 0x8B, + 0x08, 0x2D, 0xD9, 0x58, 0x28, 0xBE, 0xC9, 0x01, 0xE0, 0xE1, + 0xA9 +}; +static const int sizeof_server_cert_der_1024 = sizeof(server_cert_der_1024); + +#endif /* USE_CERT_BUFFERS_1024 */ + +#ifdef USE_CERT_BUFFERS_2048 + +/* ./certs/client-key.der, 2048-bit */ +static const unsigned char client_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, 0xFE, 0x39, 0xA4, 0x32, + 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, 0x2A, 0x7C, 0x74, 0x9A, + 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, 0xD6, 0xA6, 0x36, 0xB2, + 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, 0x7B, 0xC6, 0xC3, 0x44, + 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, 0x68, 0xA2, 0x8B, 0x67, + 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, 0x4A, 0xD2, 0x1B, 0xF7, + 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, 0xEC, 0xF1, 0x81, 0x1E, + 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, 0x65, 0xCC, 0x7F, 0x65, + 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, 0x5B, 0xE4, 0x34, 0xF7, + 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, 0x7B, 0x3A, 0x7A, 0x78, + 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, 0x13, 0x42, 0x8D, 0xD2, + 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, 0x86, 0xDF, 0x37, 0x51, + 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, 0xA3, 0x4A, 0x35, 0xE4, + 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, 0xBF, 0x4E, 0x97, 0xD0, + 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, 0xAF, 0x20, 0x0B, 0x43, + 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, 0x82, 0x6F, 0x8D, 0x86, + 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, 0xBA, 0x1E, 0x40, 0x72, + 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, 0x73, 0xB0, 0xCE, 0xEF, + 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, 0x7B, 0xC0, 0x12, 0x03, + 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, 0x3B, 0xA3, 0x3B, 0xA3, + 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, 0x85, 0xB3, 0xD9, 0x8A, + 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, 0xAC, 0xBB, 0xFF, 0x25, + 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, 0xD3, 0x86, 0x40, 0x18, + 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, 0x30, 0xC4, 0x97, 0x84, + 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, 0xF7, 0x7F, 0xC0, 0xAE, + 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, 0xBA, 0xD3, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA2, 0xE6, + 0xD8, 0x5F, 0x10, 0x71, 0x64, 0x08, 0x9E, 0x2E, 0x6D, 0xD1, + 0x6D, 0x1E, 0x85, 0xD2, 0x0A, 0xB1, 0x8C, 0x47, 0xCE, 0x2C, + 0x51, 0x6A, 0xA0, 0x12, 0x9E, 0x53, 0xDE, 0x91, 0x4C, 0x1D, + 0x6D, 0xEA, 0x59, 0x7B, 0xF2, 0x77, 0xAA, 0xD9, 0xC6, 0xD9, + 0x8A, 0xAB, 0xD8, 0xE1, 0x16, 0xE4, 0x63, 0x26, 0xFF, 0xB5, + 0x6C, 0x13, 0x59, 0xB8, 0xE3, 0xA5, 0xC8, 0x72, 0x17, 0x2E, + 0x0C, 0x9F, 0x6F, 0xE5, 0x59, 0x3F, 0x76, 0x6F, 0x49, 0xB1, + 0x11, 0xC2, 0x5A, 0x2E, 0x16, 0x29, 0x0D, 0xDE, 0xB7, 0x8E, + 0xDC, 0x40, 0xD5, 0xA2, 0xEE, 0xE0, 0x1E, 0xA1, 0xF4, 0xBE, + 0x97, 0xDB, 0x86, 0x63, 0x96, 0x14, 0xCD, 0x98, 0x09, 0x60, + 0x2D, 0x30, 0x76, 0x9C, 0x3C, 0xCD, 0xE6, 0x88, 0xEE, 0x47, + 0x92, 0x79, 0x0B, 0x5A, 0x00, 0xE2, 0x5E, 0x5F, 0x11, 0x7C, + 0x7D, 0xF9, 0x08, 0xB7, 0x20, 0x06, 0x89, 0x2A, 0x5D, 0xFD, + 0x00, 0xAB, 0x22, 0xE1, 0xF0, 0xB3, 0xBC, 0x24, 0xA9, 0x5E, + 0x26, 0x0E, 0x1F, 0x00, 0x2D, 0xFE, 0x21, 0x9A, 0x53, 0x5B, + 0x6D, 0xD3, 0x2B, 0xAB, 0x94, 0x82, 0x68, 0x43, 0x36, 0xD8, + 0xF6, 0x2F, 0xC6, 0x22, 0xFC, 0xB5, 0x41, 0x5D, 0x0D, 0x33, + 0x60, 0xEA, 0xA4, 0x7D, 0x7E, 0xE8, 0x4B, 0x55, 0x91, 0x56, + 0xD3, 0x5C, 0x57, 0x8F, 0x1F, 0x94, 0x17, 0x2F, 0xAA, 0xDE, + 0xE9, 0x9E, 0xA8, 0xF4, 0xCF, 0x8A, 0x4C, 0x8E, 0xA0, 0xE4, + 0x56, 0x73, 0xB2, 0xCF, 0x4F, 0x86, 0xC5, 0x69, 0x3C, 0xF3, + 0x24, 0x20, 0x8B, 0x5C, 0x96, 0x0C, 0xFA, 0x6B, 0x12, 0x3B, + 0x9A, 0x67, 0xC1, 0xDF, 0xC6, 0x96, 0xB2, 0xA5, 0xD5, 0x92, + 0x0D, 0x9B, 0x09, 0x42, 0x68, 0x24, 0x10, 0x45, 0xD4, 0x50, + 0xE4, 0x17, 0x39, 0x48, 0xD0, 0x35, 0x8B, 0x94, 0x6D, 0x11, + 0xDE, 0x8F, 0xCA, 0x59, 0x02, 0x81, 0x81, 0x00, 0xEA, 0x24, + 0xA7, 0xF9, 0x69, 0x33, 0xE9, 0x71, 0xDC, 0x52, 0x7D, 0x88, + 0x21, 0x28, 0x2F, 0x49, 0xDE, 0xBA, 0x72, 0x16, 0xE9, 0xCC, + 0x47, 0x7A, 0x88, 0x0D, 0x94, 0x57, 0x84, 0x58, 0x16, 0x3A, + 0x81, 0xB0, 0x3F, 0xA2, 0xCF, 0xA6, 0x6C, 0x1E, 0xB0, 0x06, + 0x29, 0x00, 0x8F, 0xE7, 0x77, 0x76, 0xAC, 0xDB, 0xCA, 0xC7, + 0xD9, 0x5E, 0x9B, 0x3F, 0x26, 0x90, 0x52, 0xAE, 0xFC, 0x38, + 0x90, 0x00, 0x14, 0xBB, 0xB4, 0x0F, 0x58, 0x94, 0xE7, 0x2F, + 0x6A, 0x7E, 0x1C, 0x4F, 0x41, 0x21, 0xD4, 0x31, 0x59, 0x1F, + 0x4E, 0x8A, 0x1A, 0x8D, 0xA7, 0x57, 0x6C, 0x22, 0xD8, 0xE5, + 0xF4, 0x7E, 0x32, 0xA6, 0x10, 0xCB, 0x64, 0xA5, 0x55, 0x03, + 0x87, 0xA6, 0x27, 0x05, 0x8C, 0xC3, 0xD7, 0xB6, 0x27, 0xB2, + 0x4D, 0xBA, 0x30, 0xDA, 0x47, 0x8F, 0x54, 0xD3, 0x3D, 0x8B, + 0x84, 0x8D, 0x94, 0x98, 0x58, 0xA5, 0x02, 0x81, 0x81, 0x00, + 0xD5, 0x38, 0x1B, 0xC3, 0x8F, 0xC5, 0x93, 0x0C, 0x47, 0x0B, + 0x6F, 0x35, 0x92, 0xC5, 0xB0, 0x8D, 0x46, 0xC8, 0x92, 0x18, + 0x8F, 0xF5, 0x80, 0x0A, 0xF7, 0xEF, 0xA1, 0xFE, 0x80, 0xB9, + 0xB5, 0x2A, 0xBA, 0xCA, 0x18, 0xB0, 0x5D, 0xA5, 0x07, 0xD0, + 0x93, 0x8D, 0xD8, 0x9C, 0x04, 0x1C, 0xD4, 0x62, 0x8E, 0xA6, + 0x26, 0x81, 0x01, 0xFF, 0xCE, 0x8A, 0x2A, 0x63, 0x34, 0x35, + 0x40, 0xAA, 0x6D, 0x80, 0xDE, 0x89, 0x23, 0x6A, 0x57, 0x4D, + 0x9E, 0x6E, 0xAD, 0x93, 0x4E, 0x56, 0x90, 0x0B, 0x6D, 0x9D, + 0x73, 0x8B, 0x0C, 0xAE, 0x27, 0x3D, 0xDE, 0x4E, 0xF0, 0xAA, + 0xC5, 0x6C, 0x78, 0x67, 0x6C, 0x94, 0x52, 0x9C, 0x37, 0x67, + 0x6C, 0x2D, 0xEF, 0xBB, 0xAF, 0xDF, 0xA6, 0x90, 0x3C, 0xC4, + 0x47, 0xCF, 0x8D, 0x96, 0x9E, 0x98, 0xA9, 0xB4, 0x9F, 0xC5, + 0xA6, 0x50, 0xDC, 0xB3, 0xF0, 0xFB, 0x74, 0x17, 0x02, 0x81, + 0x80, 0x5E, 0x83, 0x09, 0x62, 0xBD, 0xBA, 0x7C, 0xA2, 0xBF, + 0x42, 0x74, 0xF5, 0x7C, 0x1C, 0xD2, 0x69, 0xC9, 0x04, 0x0D, + 0x85, 0x7E, 0x3E, 0x3D, 0x24, 0x12, 0xC3, 0x18, 0x7B, 0xF3, + 0x29, 0xF3, 0x5F, 0x0E, 0x76, 0x6C, 0x59, 0x75, 0xE4, 0x41, + 0x84, 0x69, 0x9D, 0x32, 0xF3, 0xCD, 0x22, 0xAB, 0xB0, 0x35, + 0xBA, 0x4A, 0xB2, 0x3C, 0xE5, 0xD9, 0x58, 0xB6, 0x62, 0x4F, + 0x5D, 0xDE, 0xE5, 0x9E, 0x0A, 0xCA, 0x53, 0xB2, 0x2C, 0xF7, + 0x9E, 0xB3, 0x6B, 0x0A, 0x5B, 0x79, 0x65, 0xEC, 0x6E, 0x91, + 0x4E, 0x92, 0x20, 0xF6, 0xFC, 0xFC, 0x16, 0xED, 0xD3, 0x76, + 0x0C, 0xE2, 0xEC, 0x7F, 0xB2, 0x69, 0x13, 0x6B, 0x78, 0x0E, + 0x5A, 0x46, 0x64, 0xB4, 0x5E, 0xB7, 0x25, 0xA0, 0x5A, 0x75, + 0x3A, 0x4B, 0xEF, 0xC7, 0x3C, 0x3E, 0xF7, 0xFD, 0x26, 0xB8, + 0x20, 0xC4, 0x99, 0x0A, 0x9A, 0x73, 0xBE, 0xC3, 0x19, 0x02, + 0x81, 0x81, 0x00, 0xBA, 0x44, 0x93, 0x14, 0xAC, 0x34, 0x19, + 0x3B, 0x5F, 0x91, 0x60, 0xAC, 0xF7, 0xB4, 0xD6, 0x81, 0x05, + 0x36, 0x51, 0x53, 0x3D, 0xE8, 0x65, 0xDC, 0xAF, 0x2E, 0xDC, + 0x61, 0x3E, 0xC9, 0x7D, 0xB8, 0x7F, 0x87, 0xF0, 0x3B, 0x9B, + 0x03, 0x82, 0x29, 0x37, 0xCE, 0x72, 0x4E, 0x11, 0xD5, 0xB1, + 0xC1, 0x0C, 0x07, 0xA0, 0x99, 0x91, 0x4A, 0x8D, 0x7F, 0xEC, + 0x79, 0xCF, 0xF1, 0x39, 0xB5, 0xE9, 0x85, 0xEC, 0x62, 0xF7, + 0xDA, 0x7D, 0xBC, 0x64, 0x4D, 0x22, 0x3C, 0x0E, 0xF2, 0xD6, + 0x51, 0xF5, 0x87, 0xD8, 0x99, 0xC0, 0x11, 0x20, 0x5D, 0x0F, + 0x29, 0xFD, 0x5B, 0xE2, 0xAE, 0xD9, 0x1C, 0xD9, 0x21, 0x56, + 0x6D, 0xFC, 0x84, 0xD0, 0x5F, 0xED, 0x10, 0x15, 0x1C, 0x18, + 0x21, 0xE7, 0xC4, 0x3D, 0x4B, 0xD7, 0xD0, 0x9E, 0x6A, 0x95, + 0xCF, 0x22, 0xC9, 0x03, 0x7B, 0x9E, 0xE3, 0x60, 0x01, 0xFC, + 0x2F, 0x02, 0x81, 0x80, 0x11, 0xD0, 0x4B, 0xCF, 0x1B, 0x67, + 0xB9, 0x9F, 0x10, 0x75, 0x47, 0x86, 0x65, 0xAE, 0x31, 0xC2, + 0xC6, 0x30, 0xAC, 0x59, 0x06, 0x50, 0xD9, 0x0F, 0xB5, 0x70, + 0x06, 0xF7, 0xF0, 0xD3, 0xC8, 0x62, 0x7C, 0xA8, 0xDA, 0x6E, + 0xF6, 0x21, 0x3F, 0xD3, 0x7F, 0x5F, 0xEA, 0x8A, 0xAB, 0x3F, + 0xD9, 0x2A, 0x5E, 0xF3, 0x51, 0xD2, 0xC2, 0x30, 0x37, 0xE3, + 0x2D, 0xA3, 0x75, 0x0D, 0x1E, 0x4D, 0x21, 0x34, 0xD5, 0x57, + 0x70, 0x5C, 0x89, 0xBF, 0x72, 0xEC, 0x4A, 0x6E, 0x68, 0xD5, + 0xCD, 0x18, 0x74, 0x33, 0x4E, 0x8C, 0x3A, 0x45, 0x8F, 0xE6, + 0x96, 0x40, 0xEB, 0x63, 0xF9, 0x19, 0x86, 0x3A, 0x51, 0xDD, + 0x89, 0x4B, 0xB0, 0xF3, 0xF9, 0x9F, 0x5D, 0x28, 0x95, 0x38, + 0xBE, 0x35, 0xAB, 0xCA, 0x5C, 0xE7, 0x93, 0x53, 0x34, 0xA1, + 0x45, 0x5D, 0x13, 0x39, 0x65, 0x42, 0x46, 0xA1, 0x9F, 0xCD, + 0xF5, 0xBF +}; +static const int sizeof_client_key_der_2048 = sizeof(client_key_der_2048); + +/* ./certs/client-keyPub.der, 2048-bit */ +static const unsigned char client_keypub_der_2048[] = +{ + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, + 0x01, 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, 0xFE, 0x39, 0xA4, + 0x32, 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, 0x2A, 0x7C, 0x74, + 0x9A, 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, 0xD6, 0xA6, 0x36, + 0xB2, 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, 0x7B, 0xC6, 0xC3, + 0x44, 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, 0x68, 0xA2, 0x8B, + 0x67, 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, 0x4A, 0xD2, 0x1B, + 0xF7, 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, 0xEC, 0xF1, 0x81, + 0x1E, 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, 0x65, 0xCC, 0x7F, + 0x65, 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, 0x5B, 0xE4, 0x34, + 0xF7, 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, 0x7B, 0x3A, 0x7A, + 0x78, 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, 0x13, 0x42, 0x8D, + 0xD2, 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, 0x86, 0xDF, 0x37, + 0x51, 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, 0xA3, 0x4A, 0x35, + 0xE4, 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, 0xBF, 0x4E, 0x97, + 0xD0, 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, 0xAF, 0x20, 0x0B, + 0x43, 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, 0x82, 0x6F, 0x8D, + 0x86, 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, 0xBA, 0x1E, 0x40, + 0x72, 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, 0x73, 0xB0, 0xCE, + 0xEF, 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, 0x7B, 0xC0, 0x12, + 0x03, 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, 0x3B, 0xA3, 0x3B, + 0xA3, 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, 0x85, 0xB3, 0xD9, + 0x8A, 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, 0xAC, 0xBB, 0xFF, + 0x25, 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, 0xD3, 0x86, 0x40, + 0x18, 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, 0x30, 0xC4, 0x97, + 0x84, 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, 0xF7, 0x7F, 0xC0, + 0xAE, 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, 0xBA, 0xD3, 0x02, + 0x03, 0x01, 0x00, 0x01 +}; +static const int sizeof_client_keypub_der_2048 = sizeof(client_keypub_der_2048); + +/* ./certs/client-cert.der, 2048-bit */ +static const unsigned char client_cert_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xFE, 0x30, 0x82, 0x03, 0xE6, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x95, 0x90, 0x12, 0x9B, + 0x22, 0xA1, 0x50, 0x40, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, + 0x32, 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, + 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x32, 0x30, 0x34, + 0x38, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x31, 0x31, 0x32, 0x33, + 0x31, 0x32, 0x34, 0x39, 0x33, 0x37, 0x5A, 0x17, 0x0D, 0x31, + 0x38, 0x30, 0x38, 0x31, 0x39, 0x31, 0x32, 0x34, 0x39, 0x33, + 0x37, 0x5A, 0x30, 0x81, 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, + 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, + 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, + 0x53, 0x4C, 0x5F, 0x32, 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, + 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, + 0x32, 0x30, 0x34, 0x38, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, + 0xFE, 0x39, 0xA4, 0x32, 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, + 0x2A, 0x7C, 0x74, 0x9A, 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, + 0xD6, 0xA6, 0x36, 0xB2, 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, + 0x7B, 0xC6, 0xC3, 0x44, 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, + 0x68, 0xA2, 0x8B, 0x67, 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, + 0x4A, 0xD2, 0x1B, 0xF7, 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, + 0xEC, 0xF1, 0x81, 0x1E, 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, + 0x65, 0xCC, 0x7F, 0x65, 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, + 0x5B, 0xE4, 0x34, 0xF7, 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, + 0x7B, 0x3A, 0x7A, 0x78, 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, + 0x13, 0x42, 0x8D, 0xD2, 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, + 0x86, 0xDF, 0x37, 0x51, 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, + 0xA3, 0x4A, 0x35, 0xE4, 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, + 0xBF, 0x4E, 0x97, 0xD0, 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, + 0xAF, 0x20, 0x0B, 0x43, 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, + 0x82, 0x6F, 0x8D, 0x86, 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, + 0xBA, 0x1E, 0x40, 0x72, 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, + 0x73, 0xB0, 0xCE, 0xEF, 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, + 0x7B, 0xC0, 0x12, 0x03, 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, + 0x3B, 0xA3, 0x3B, 0xA3, 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, + 0x85, 0xB3, 0xD9, 0x8A, 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, + 0xAC, 0xBB, 0xFF, 0x25, 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, + 0xD3, 0x86, 0x40, 0x18, 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, + 0x30, 0xC4, 0x97, 0x84, 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, + 0xF7, 0x7F, 0xC0, 0xAE, 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, + 0xBA, 0xD3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + 0x3B, 0x30, 0x82, 0x01, 0x37, 0x30, 0x1D, 0x06, 0x03, 0x55, + 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x33, 0xD8, 0x45, 0x66, + 0xD7, 0x68, 0x87, 0x18, 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, + 0xC7, 0x26, 0xD7, 0x85, 0x65, 0xC0, 0x30, 0x81, 0xD3, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xCB, 0x30, 0x81, 0xC8, + 0x80, 0x14, 0x33, 0xD8, 0x45, 0x66, 0xD7, 0x68, 0x87, 0x18, + 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, 0xC7, 0x26, 0xD7, 0x85, + 0x65, 0xC0, 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, + 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x32, + 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, + 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x32, 0x30, 0x34, 0x38, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, + 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, + 0x09, 0x00, 0x95, 0x90, 0x12, 0x9B, 0x22, 0xA1, 0x50, 0x40, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x32, 0x06, 0x08, 0x2B, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30, 0x24, + 0x30, 0x22, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, + 0x2F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, + 0x3A, 0x32, 0x32, 0x32, 0x32, 0x32, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7B, 0x91, 0x63, 0x8D, + 0x39, 0x54, 0x64, 0x3C, 0xB4, 0x3F, 0xD5, 0xC8, 0x4F, 0xBF, + 0x0B, 0xBF, 0xAF, 0x5C, 0x9C, 0x41, 0xC7, 0x0B, 0x52, 0x6D, + 0xC6, 0xF0, 0xDE, 0x7C, 0xFF, 0x9B, 0x4E, 0xFE, 0xF3, 0x22, + 0xA5, 0x00, 0x13, 0x9F, 0x81, 0xE4, 0x6D, 0x70, 0x2C, 0xF9, + 0x7A, 0xF4, 0xD8, 0x50, 0xBE, 0x72, 0xE1, 0x04, 0x8B, 0xB0, + 0x05, 0xE3, 0x61, 0x82, 0x3F, 0x65, 0xDE, 0xF9, 0xE9, 0xD3, + 0x3D, 0x97, 0x7D, 0x88, 0xB7, 0x99, 0x85, 0xC1, 0xE5, 0x5C, + 0x57, 0xA7, 0x9C, 0x1F, 0xF2, 0xB8, 0xCE, 0xEC, 0xD7, 0xD1, + 0x9B, 0xEC, 0xFB, 0x0E, 0x6F, 0x02, 0xAD, 0x51, 0xC0, 0x76, + 0xDD, 0x66, 0x0A, 0xCE, 0x0D, 0x09, 0xE6, 0xA8, 0x42, 0xB0, + 0x06, 0xC3, 0x04, 0xE7, 0x1C, 0xC7, 0x10, 0x83, 0x07, 0xF2, + 0xE6, 0x11, 0x1A, 0xCD, 0xA7, 0xB9, 0x7E, 0x17, 0xEF, 0xEA, + 0x63, 0x9C, 0xF2, 0xA5, 0xBE, 0x6B, 0xB6, 0xDF, 0xEB, 0x5A, + 0x75, 0x01, 0x59, 0x05, 0xF7, 0xEC, 0x49, 0x75, 0x10, 0xDD, + 0x40, 0x1A, 0x25, 0x25, 0x4F, 0x78, 0x6E, 0xE1, 0x92, 0x21, + 0xB5, 0xB8, 0x82, 0x2F, 0x33, 0xB3, 0x5B, 0xB6, 0x81, 0xB8, + 0xB1, 0xA4, 0x0C, 0x8D, 0x98, 0x74, 0x74, 0xDA, 0x0D, 0x90, + 0x33, 0xC8, 0xA7, 0xAA, 0x0D, 0x06, 0x5A, 0x04, 0xEB, 0x37, + 0xD3, 0xE4, 0x55, 0x0C, 0x93, 0xB6, 0xC8, 0x3A, 0xE8, 0xA7, + 0x2B, 0x4E, 0xB8, 0x90, 0xBB, 0x36, 0x0B, 0xDB, 0x7F, 0x2E, + 0x99, 0x23, 0x76, 0x68, 0x81, 0xA8, 0x73, 0x74, 0xE7, 0x68, + 0xFB, 0x1D, 0xFF, 0x5B, 0xEC, 0xB5, 0x6B, 0x30, 0xD1, 0xD0, + 0x2B, 0x89, 0xA6, 0xC6, 0xA9, 0xFC, 0x03, 0x66, 0xFE, 0xB5, + 0x8C, 0xAF, 0xDE, 0x8E, 0x2A, 0xB4, 0x78, 0x9C, 0xD7, 0x4A, + 0xFC, 0x9C, 0xC4, 0x7C, 0x19, 0x20, 0x83, 0x0E, 0xFD, 0x3F, + 0x4D, 0xA7 +}; +static const int sizeof_client_cert_der_2048 = sizeof(client_cert_der_2048); + +/* ./certs/dh2048.der, 2048-bit */ +static const unsigned char dh_key_der_2048[] = +{ + 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB0, + 0xA1, 0x08, 0x06, 0x9C, 0x08, 0x13, 0xBA, 0x59, 0x06, 0x3C, + 0xBC, 0x30, 0xD5, 0xF5, 0x00, 0xC1, 0x4F, 0x44, 0xA7, 0xD6, + 0xEF, 0x4A, 0xC6, 0x25, 0x27, 0x1C, 0xE8, 0xD2, 0x96, 0x53, + 0x0A, 0x5C, 0x91, 0xDD, 0xA2, 0xC2, 0x94, 0x84, 0xBF, 0x7D, + 0xB2, 0x44, 0x9F, 0x9B, 0xD2, 0xC1, 0x8A, 0xC5, 0xBE, 0x72, + 0x5C, 0xA7, 0xE7, 0x91, 0xE6, 0xD4, 0x9F, 0x73, 0x07, 0x85, + 0x5B, 0x66, 0x48, 0xC7, 0x70, 0xFA, 0xB4, 0xEE, 0x02, 0xC9, + 0x3D, 0x9A, 0x4A, 0xDA, 0x3D, 0xC1, 0x46, 0x3E, 0x19, 0x69, + 0xD1, 0x17, 0x46, 0x07, 0xA3, 0x4D, 0x9F, 0x2B, 0x96, 0x17, + 0x39, 0x6D, 0x30, 0x8D, 0x2A, 0xF3, 0x94, 0xD3, 0x75, 0xCF, + 0xA0, 0x75, 0xE6, 0xF2, 0x92, 0x1F, 0x1A, 0x70, 0x05, 0xAA, + 0x04, 0x83, 0x57, 0x30, 0xFB, 0xDA, 0x76, 0x93, 0x38, 0x50, + 0xE8, 0x27, 0xFD, 0x63, 0xEE, 0x3C, 0xE5, 0xB7, 0xC8, 0x09, + 0xAE, 0x6F, 0x50, 0x35, 0x8E, 0x84, 0xCE, 0x4A, 0x00, 0xE9, + 0x12, 0x7E, 0x5A, 0x31, 0xD7, 0x33, 0xFC, 0x21, 0x13, 0x76, + 0xCC, 0x16, 0x30, 0xDB, 0x0C, 0xFC, 0xC5, 0x62, 0xA7, 0x35, + 0xB8, 0xEF, 0xB7, 0xB0, 0xAC, 0xC0, 0x36, 0xF6, 0xD9, 0xC9, + 0x46, 0x48, 0xF9, 0x40, 0x90, 0x00, 0x2B, 0x1B, 0xAA, 0x6C, + 0xE3, 0x1A, 0xC3, 0x0B, 0x03, 0x9E, 0x1B, 0xC2, 0x46, 0xE4, + 0x48, 0x4E, 0x22, 0x73, 0x6F, 0xC3, 0x5F, 0xD4, 0x9A, 0xD6, + 0x30, 0x07, 0x48, 0xD6, 0x8C, 0x90, 0xAB, 0xD4, 0xF6, 0xF1, + 0xE3, 0x48, 0xD3, 0x58, 0x4B, 0xA6, 0xB9, 0xCD, 0x29, 0xBF, + 0x68, 0x1F, 0x08, 0x4B, 0x63, 0x86, 0x2F, 0x5C, 0x6B, 0xD6, + 0xB6, 0x06, 0x65, 0xF7, 0xA6, 0xDC, 0x00, 0x67, 0x6B, 0xBB, + 0xC3, 0xA9, 0x41, 0x83, 0xFB, 0xC7, 0xFA, 0xC8, 0xE2, 0x1E, + 0x7E, 0xAF, 0x00, 0x3F, 0x93, 0x02, 0x01, 0x02 +}; +static const int sizeof_dh_key_der_2048 = sizeof(dh_key_der_2048); + +/* ./certs/dsa2048.der, 2048-bit */ +static const unsigned char dsa_key_der_2048[] = +{ + 0x30, 0x82, 0x03, 0x3F, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xCC, 0x8E, 0xC9, 0xA0, 0xD5, 0x9A, 0x27, 0x1C, + 0xDA, 0x52, 0xDF, 0xC7, 0xC0, 0xE6, 0x06, 0xA4, 0x3E, 0x8A, + 0x66, 0x49, 0xD0, 0x59, 0x33, 0x51, 0x69, 0xC4, 0x9C, 0x5E, + 0x64, 0x85, 0xC7, 0xF1, 0xAB, 0xD5, 0xD9, 0x62, 0xAC, 0xFD, + 0xA1, 0xE0, 0x1B, 0x57, 0xFF, 0x96, 0xEF, 0x0C, 0x9F, 0xC8, + 0x44, 0x87, 0xEB, 0x5C, 0x91, 0xD0, 0x46, 0x42, 0x09, 0x50, + 0x6A, 0x23, 0xCB, 0x89, 0x6F, 0x55, 0xE9, 0x6A, 0x11, 0xA9, + 0xA8, 0x32, 0xAB, 0x33, 0x0D, 0x51, 0xB5, 0x79, 0x51, 0xB4, + 0xAB, 0xA2, 0x25, 0x11, 0x8D, 0xE5, 0x24, 0xBE, 0xD8, 0xF1, + 0x9D, 0x4E, 0x12, 0x6F, 0xAC, 0x44, 0x54, 0x80, 0xA9, 0xB4, + 0x81, 0x68, 0x4E, 0x44, 0x0E, 0xB8, 0x39, 0xF3, 0xBE, 0x83, + 0x08, 0x74, 0xA2, 0xC6, 0x7A, 0xD7, 0x6A, 0x7D, 0x0A, 0x88, + 0x57, 0x83, 0x48, 0xDC, 0xCF, 0x5E, 0x6F, 0xEE, 0x68, 0x0C, + 0xF7, 0xFF, 0x03, 0x04, 0x90, 0xAA, 0xF7, 0x07, 0x98, 0xF8, + 0x67, 0x5A, 0x83, 0x23, 0x66, 0x47, 0x60, 0xC3, 0x43, 0x6E, + 0x03, 0x91, 0xAC, 0x28, 0x66, 0xCB, 0xF0, 0xD3, 0x05, 0xC8, + 0x09, 0x97, 0xB5, 0xAE, 0x01, 0x5E, 0x80, 0x3B, 0x9D, 0x4F, + 0xDE, 0x3E, 0x94, 0xFE, 0xCB, 0x82, 0xB0, 0xB1, 0xFC, 0x91, + 0x8B, 0x1D, 0x8A, 0xEE, 0xC6, 0x06, 0x1F, 0x37, 0x91, 0x48, + 0xD2, 0xF8, 0x6C, 0x5D, 0x60, 0x13, 0x83, 0xA7, 0x81, 0xAC, + 0xCA, 0x8D, 0xD0, 0x6A, 0x04, 0x0A, 0xEA, 0x3E, 0x22, 0x4E, + 0x13, 0xF1, 0x0D, 0xBB, 0x60, 0x6B, 0xCD, 0xBC, 0x5C, 0x87, + 0xA3, 0x67, 0x2B, 0x42, 0xA1, 0x9F, 0xCD, 0x39, 0x58, 0xBE, + 0x55, 0xB1, 0x93, 0x84, 0xCE, 0xB2, 0x10, 0x4E, 0xE4, 0xC3, + 0x9F, 0xB2, 0x53, 0x61, 0x01, 0x29, 0xAA, 0x96, 0xCB, 0x20, + 0x60, 0x42, 0x1D, 0xBA, 0x75, 0x4B, 0x63, 0xC1, 0x02, 0x15, + 0x00, 0xE7, 0xA5, 0x39, 0xD4, 0x6A, 0x37, 0x5E, 0x95, 0x06, + 0x39, 0x07, 0x77, 0x0A, 0xEB, 0xA0, 0x03, 0xEB, 0x78, 0x82, + 0x9B, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9A, 0xD4, 0x4C, 0x71, + 0x2F, 0xEC, 0xFA, 0x32, 0xB2, 0x80, 0x7E, 0x61, 0x4A, 0x6B, + 0x5F, 0x18, 0x76, 0x43, 0xC3, 0x69, 0xBA, 0x41, 0xC7, 0xA7, + 0x1D, 0x79, 0x01, 0xEC, 0xAF, 0x34, 0x87, 0x67, 0x4F, 0x29, + 0x80, 0xA8, 0x3B, 0x87, 0xF6, 0xE8, 0xA1, 0xE8, 0xCD, 0x1B, + 0x1C, 0x86, 0x38, 0xF6, 0xD1, 0x0C, 0x46, 0x2E, 0xC8, 0xE0, + 0xC9, 0x30, 0x26, 0xD5, 0x2C, 0x7F, 0xC1, 0x08, 0xBF, 0xCC, + 0x5A, 0x82, 0x8E, 0xD4, 0xD4, 0x49, 0xAA, 0xA2, 0xFA, 0xE6, + 0xC1, 0x9D, 0xF0, 0xD9, 0x96, 0xB0, 0xFF, 0x0C, 0x5B, 0x33, + 0x8E, 0x06, 0xDD, 0x9D, 0x28, 0xA9, 0xE9, 0x80, 0x41, 0x3B, + 0xD8, 0x7A, 0x94, 0x21, 0x8F, 0x56, 0xF1, 0xA2, 0xB4, 0x2B, + 0x89, 0x1C, 0x74, 0xFF, 0x7E, 0x91, 0xDC, 0x1F, 0x91, 0x13, + 0x98, 0xAF, 0xC7, 0x06, 0xD2, 0x4C, 0x90, 0xA2, 0xBD, 0xDA, + 0x16, 0xBA, 0x65, 0xB0, 0x2D, 0x68, 0x87, 0x3C, 0x6E, 0x25, + 0x8D, 0x90, 0xC7, 0xBC, 0x0D, 0xA9, 0x43, 0x03, 0xC9, 0xBE, + 0xCF, 0x85, 0x6F, 0xDB, 0x07, 0x7B, 0x8C, 0xF8, 0xB1, 0xC2, + 0x49, 0x10, 0x69, 0x63, 0x56, 0x37, 0xC5, 0x30, 0xD2, 0xFB, + 0x71, 0x9A, 0xE8, 0x82, 0x07, 0x2E, 0x3E, 0x95, 0x50, 0xF3, + 0x73, 0xCF, 0x34, 0x5B, 0xD5, 0xAB, 0x02, 0x15, 0xF2, 0xCC, + 0xD7, 0x52, 0xC5, 0x28, 0xD8, 0x41, 0x19, 0x55, 0x6F, 0xB8, + 0x5F, 0xF1, 0x99, 0xB3, 0xC7, 0xD9, 0xB3, 0x71, 0xF4, 0x2D, + 0xDF, 0x22, 0x59, 0x35, 0x86, 0xDB, 0x39, 0xCA, 0x1B, 0x4D, + 0x35, 0x90, 0x19, 0x6B, 0x31, 0xE3, 0xC8, 0xC6, 0x09, 0xBF, + 0x7C, 0xED, 0x01, 0xB4, 0xB2, 0xF5, 0x6E, 0xDA, 0x63, 0x41, + 0x3C, 0xE6, 0x3A, 0x72, 0x2D, 0x65, 0x48, 0xF6, 0x07, 0xCD, + 0x92, 0x84, 0x8B, 0x1D, 0xA7, 0x31, 0x6B, 0xD6, 0xF0, 0xFB, + 0xD9, 0xF4, 0x02, 0x82, 0x01, 0x00, 0x66, 0x4B, 0xBB, 0xB7, + 0xC9, 0x48, 0x95, 0x0D, 0x5A, 0xA6, 0x2D, 0xA1, 0x7F, 0xDF, + 0x1F, 0x67, 0x6D, 0xED, 0x52, 0x4B, 0x16, 0x6C, 0x17, 0xC6, + 0xAE, 0xF8, 0x6A, 0xC4, 0x57, 0xED, 0x2F, 0xB3, 0xF0, 0x2A, + 0x55, 0xAB, 0xBA, 0xCA, 0xEA, 0x17, 0xE8, 0x35, 0x7C, 0xE5, + 0x31, 0x0D, 0x4A, 0x95, 0xFC, 0x43, 0x6F, 0x97, 0x3C, 0x5C, + 0x67, 0xAC, 0xBE, 0x67, 0x7F, 0xE9, 0x4E, 0xAA, 0x48, 0xB3, + 0x92, 0xA1, 0x76, 0x75, 0xEA, 0x04, 0x34, 0x7F, 0x87, 0x33, + 0x2D, 0x24, 0xB6, 0x29, 0x97, 0xE3, 0x04, 0x77, 0x93, 0x89, + 0x13, 0xDB, 0x1B, 0x93, 0xB8, 0x2C, 0x90, 0x1A, 0x09, 0x3B, + 0x26, 0xD9, 0x59, 0xF3, 0x2A, 0x09, 0x58, 0xDC, 0xAC, 0x25, + 0xB4, 0xA9, 0x45, 0x3B, 0xA2, 0x3A, 0x6C, 0x61, 0x84, 0xBF, + 0x68, 0xD4, 0xEA, 0x9B, 0xC5, 0x29, 0x48, 0x60, 0x15, 0x10, + 0x35, 0x2C, 0x44, 0x1D, 0xB5, 0x9A, 0xEE, 0xAC, 0xC1, 0x68, + 0xE8, 0x47, 0xB7, 0x41, 0x34, 0x39, 0x9A, 0xF8, 0xA5, 0x20, + 0xE9, 0x24, 0xC4, 0x2C, 0x58, 0x3F, 0x4C, 0x41, 0x30, 0x3A, + 0x14, 0x6E, 0x8D, 0xEA, 0xAD, 0xBA, 0x9B, 0x43, 0xD3, 0x98, + 0x2F, 0x83, 0xD8, 0x14, 0x67, 0xE8, 0xF8, 0xD5, 0x4F, 0xAC, + 0xE0, 0x3B, 0xBF, 0xA7, 0x54, 0x16, 0x5E, 0x49, 0x64, 0x26, + 0x54, 0xA4, 0x6B, 0x69, 0x7C, 0xBA, 0x8A, 0x83, 0xD9, 0x2E, + 0x65, 0x0A, 0xA2, 0x27, 0xEF, 0x99, 0x99, 0x08, 0xD7, 0xB5, + 0x9F, 0xA0, 0x01, 0xEF, 0x7E, 0x17, 0xBF, 0x83, 0x6B, 0x2E, + 0xDD, 0xC0, 0x39, 0x38, 0x23, 0x68, 0xB4, 0x76, 0x6B, 0xE5, + 0xCA, 0xF7, 0x7C, 0xEE, 0xC0, 0x52, 0xE2, 0xDD, 0xAD, 0x59, + 0x3A, 0x42, 0x06, 0x45, 0xB0, 0xC7, 0xC1, 0x77, 0x05, 0xB2, + 0x0C, 0x32, 0x40, 0x46, 0xAA, 0xDA, 0x79, 0x77, 0x04, 0x71, + 0xDF, 0x7A, 0x02, 0x15, 0x00, 0x98, 0xEE, 0xB9, 0x51, 0x37, + 0x3E, 0x75, 0x13, 0x13, 0x06, 0x8F, 0x94, 0xD3, 0xE6, 0xE9, + 0x00, 0xCB, 0x62, 0x6D, 0x9A +}; +static const int sizeof_dsa_key_der_2048 = sizeof(dsa_key_der_2048); + +/* ./certs/rsa2048.der, 2048-bit */ +static const unsigned char rsa_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xE9, 0x8A, 0x5D, 0x15, 0xA4, 0xD4, 0x34, 0xB9, + 0x59, 0xA2, 0xDA, 0xAF, 0x74, 0xC8, 0xC9, 0x03, 0x26, 0x38, + 0xFA, 0x48, 0xFC, 0x4D, 0x30, 0x6E, 0xEA, 0x76, 0x89, 0xCE, + 0x4F, 0xF6, 0x87, 0xDE, 0x32, 0x3A, 0x46, 0x6E, 0x38, 0x12, + 0x58, 0x37, 0x22, 0x0D, 0x80, 0xAC, 0x2D, 0xAF, 0x2F, 0x12, + 0x3E, 0x62, 0x73, 0x60, 0x66, 0x68, 0x90, 0xB2, 0x6F, 0x47, + 0x17, 0x04, 0x2B, 0xCA, 0xB7, 0x26, 0xB7, 0x10, 0xC2, 0x13, + 0xF9, 0x7A, 0x62, 0x0A, 0x93, 0x32, 0x90, 0x42, 0x0D, 0x16, + 0x2E, 0xFA, 0xD7, 0x29, 0xD7, 0x9F, 0x54, 0xE4, 0xFC, 0x65, + 0x74, 0xF8, 0xF6, 0x43, 0x6B, 0x4E, 0x9E, 0x34, 0x7F, 0xCB, + 0x6B, 0x1C, 0x1A, 0xDE, 0x82, 0x81, 0xBF, 0x08, 0x5D, 0x3F, + 0xC0, 0xB6, 0xB1, 0xA8, 0xA5, 0x9C, 0x81, 0x70, 0xA7, 0x4E, + 0x32, 0x87, 0x15, 0x1C, 0x78, 0x0E, 0xF0, 0x18, 0xFE, 0xEB, + 0x4B, 0x37, 0x2B, 0xE9, 0xE1, 0xF7, 0xFA, 0x51, 0xC6, 0x58, + 0xB9, 0xD8, 0x06, 0x03, 0xED, 0xC0, 0x03, 0x18, 0x55, 0x8B, + 0x98, 0xFE, 0xB1, 0xF6, 0xD0, 0x3D, 0xFA, 0x63, 0xC0, 0x38, + 0x19, 0xC7, 0x00, 0xEF, 0x4D, 0x99, 0x60, 0xB4, 0xBA, 0xCE, + 0xE3, 0xCE, 0xD9, 0x6B, 0x2D, 0x76, 0x94, 0xFF, 0xFB, 0x77, + 0x18, 0x4A, 0xFE, 0x65, 0xF0, 0x0A, 0x91, 0x5C, 0x3B, 0x22, + 0x94, 0x85, 0xD0, 0x20, 0x18, 0x59, 0x2E, 0xA5, 0x33, 0x03, + 0xAC, 0x1B, 0x5F, 0x78, 0x32, 0x11, 0x25, 0xEE, 0x7F, 0x96, + 0x21, 0xA9, 0xD6, 0x76, 0x97, 0x8D, 0x66, 0x7E, 0xB2, 0x91, + 0xD0, 0x36, 0x2E, 0xA3, 0x1D, 0xBF, 0xF1, 0x85, 0xED, 0xC0, + 0x3E, 0x60, 0xB8, 0x5A, 0x9F, 0xAB, 0x80, 0xE0, 0xEA, 0x5D, + 0x5F, 0x75, 0x56, 0xC7, 0x4D, 0x51, 0x8E, 0xD4, 0x1F, 0x34, + 0xA6, 0x36, 0xF1, 0x30, 0x1F, 0x51, 0x99, 0x2F, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x52, 0x11, 0x33, + 0x40, 0xC5, 0xD9, 0x64, 0x65, 0xB5, 0xE0, 0x0A, 0xA5, 0x19, + 0x8E, 0xED, 0x44, 0x54, 0x0C, 0x35, 0xB7, 0xAC, 0x21, 0x9B, + 0xE1, 0x7E, 0x37, 0x05, 0x9A, 0x20, 0x73, 0x6B, 0xAF, 0x63, + 0x4B, 0x23, 0x30, 0xDC, 0x37, 0x66, 0x14, 0x89, 0xBC, 0xE0, + 0xF8, 0xA0, 0x5D, 0x2D, 0x57, 0x65, 0xE0, 0xC6, 0xD6, 0x9B, + 0x66, 0x27, 0x62, 0xEC, 0xC3, 0xB8, 0x8C, 0xD8, 0xAE, 0xB5, + 0xC9, 0xBF, 0x0E, 0xFE, 0x84, 0x72, 0x68, 0xD5, 0x47, 0x0E, + 0x0E, 0xF8, 0xAE, 0x9D, 0x56, 0xAC, 0x4F, 0xAD, 0x88, 0xA0, + 0xA2, 0xF6, 0xFC, 0x38, 0xCD, 0x96, 0x5B, 0x5E, 0x7E, 0xB6, + 0x98, 0xBB, 0xF3, 0x8A, 0xEC, 0xFA, 0xC8, 0xB7, 0x90, 0x75, + 0xA0, 0x0E, 0x77, 0x6B, 0xFD, 0x59, 0x45, 0x5A, 0x0C, 0xFF, + 0x95, 0x8D, 0xCE, 0xFE, 0x9B, 0xF6, 0x19, 0x8E, 0x0B, 0xA1, + 0x0C, 0xEE, 0xC6, 0x79, 0xDD, 0x9D, 0x61, 0x85, 0x5C, 0x19, + 0x6C, 0x47, 0xCC, 0x08, 0xFF, 0xA5, 0x62, 0xDB, 0xE4, 0x2D, + 0x2D, 0xDD, 0x14, 0x67, 0xD6, 0x4A, 0x64, 0x2A, 0x66, 0x49, + 0x54, 0x9C, 0xE3, 0x85, 0x18, 0xE7, 0x31, 0x42, 0xE2, 0xD0, + 0x2C, 0x20, 0xA0, 0x74, 0x0F, 0x1F, 0x20, 0x89, 0xBA, 0xAB, + 0x80, 0xD8, 0x38, 0xD9, 0x46, 0x69, 0xBB, 0xEF, 0xCC, 0x8B, + 0xA1, 0x73, 0xA7, 0xF2, 0xE4, 0x38, 0x5D, 0xD6, 0x75, 0x9F, + 0x88, 0x0E, 0x56, 0xCD, 0xD8, 0x84, 0x59, 0x29, 0x73, 0xF5, + 0xA1, 0x79, 0xDA, 0x7A, 0x1F, 0xBF, 0x73, 0x83, 0xC0, 0x6D, + 0x9F, 0x8B, 0x34, 0x15, 0xC0, 0x6D, 0x69, 0x6A, 0x20, 0xE6, + 0x51, 0xCF, 0x45, 0x6E, 0xCC, 0x05, 0xC4, 0x3A, 0xC0, 0x9E, + 0xAA, 0xC1, 0x06, 0x2F, 0xAB, 0x99, 0x30, 0xE1, 0x6E, 0x9D, + 0x45, 0x7A, 0xFF, 0xA9, 0xCE, 0x70, 0xB8, 0x16, 0x1A, 0x0E, + 0x20, 0xFA, 0xC1, 0x02, 0x81, 0x81, 0x00, 0xFF, 0x30, 0x11, + 0xC2, 0x3C, 0x6B, 0xB4, 0xD6, 0x9E, 0x6B, 0xC1, 0x93, 0xD1, + 0x48, 0xCE, 0x80, 0x2D, 0xBE, 0xAF, 0xF7, 0xBA, 0xB2, 0xD7, + 0xC3, 0xC4, 0x53, 0x6E, 0x15, 0x02, 0xAA, 0x61, 0xB9, 0xEA, + 0x05, 0x9B, 0x79, 0x67, 0x0B, 0xCE, 0xD9, 0xFB, 0x98, 0x8C, + 0x1D, 0x6B, 0xF4, 0x5A, 0xA7, 0xA0, 0x5E, 0x54, 0x18, 0xE9, + 0x31, 0x44, 0x7C, 0xC7, 0x52, 0xD8, 0x6D, 0xA0, 0x3E, 0xD6, + 0x14, 0x2D, 0x7B, 0x15, 0x9D, 0x1E, 0x39, 0x87, 0x96, 0xDD, + 0xA8, 0x33, 0x55, 0x2A, 0x8E, 0x32, 0xC0, 0xC4, 0xE5, 0xB8, + 0xCB, 0xCD, 0x32, 0x8D, 0xAD, 0x7B, 0xE5, 0xC6, 0x7E, 0x4D, + 0x6F, 0xF3, 0xA4, 0xC5, 0xA6, 0x40, 0xBE, 0x90, 0x3A, 0x33, + 0x6A, 0x24, 0xB2, 0x80, 0x81, 0x12, 0xAC, 0xE3, 0x7B, 0x26, + 0x63, 0xCF, 0x88, 0xB9, 0xFF, 0x74, 0x23, 0x37, 0x52, 0xF0, + 0xC4, 0x27, 0x5D, 0x45, 0x1F, 0x02, 0x81, 0x81, 0x00, 0xEA, + 0x48, 0xA7, 0xDD, 0x73, 0x41, 0x56, 0x21, 0x15, 0xF7, 0x42, + 0x45, 0x4D, 0xA9, 0xE1, 0x66, 0x5B, 0xBD, 0x25, 0x7D, 0xF7, + 0xA8, 0x65, 0x13, 0xAE, 0x2D, 0x38, 0x11, 0xCD, 0x93, 0xFC, + 0x30, 0xA3, 0x2C, 0x44, 0xBB, 0xCF, 0xD0, 0x21, 0x8F, 0xFB, + 0xC1, 0xF9, 0xAD, 0x1D, 0xEE, 0x96, 0xCF, 0x97, 0x49, 0x60, + 0x53, 0x80, 0xA5, 0xA2, 0xF8, 0xEE, 0xB9, 0xD5, 0x77, 0x44, + 0xDD, 0xFD, 0x19, 0x2A, 0xF1, 0x81, 0xF4, 0xD9, 0x3C, 0xEC, + 0x73, 0xD0, 0x2A, 0xD8, 0x3C, 0x27, 0x87, 0x79, 0x12, 0x86, + 0xE7, 0x57, 0x0C, 0x59, 0xD1, 0x44, 0x55, 0xAE, 0xC3, 0x4D, + 0x42, 0xAD, 0xA9, 0xB3, 0x28, 0x61, 0xB4, 0x9C, 0xA6, 0x63, + 0xD3, 0x96, 0xB1, 0x75, 0x9F, 0x2A, 0x78, 0x99, 0xE3, 0x1E, + 0x71, 0x47, 0x39, 0xF4, 0x52, 0xE3, 0x66, 0xF1, 0xEB, 0x7F, + 0xEF, 0xC6, 0x81, 0x93, 0x4C, 0x99, 0xF1, 0x02, 0x81, 0x81, + 0x00, 0xC5, 0xB6, 0x20, 0x8C, 0x34, 0xF3, 0xDD, 0xF0, 0x4A, + 0x5D, 0x82, 0x65, 0x5C, 0x48, 0xE4, 0x75, 0x3A, 0xFB, 0xFA, + 0xAA, 0x1C, 0xE4, 0x63, 0x77, 0x31, 0xAC, 0xD2, 0x25, 0x45, + 0x23, 0x6D, 0x03, 0xF5, 0xE4, 0xD2, 0x48, 0x85, 0x26, 0x08, + 0xE5, 0xAA, 0xA0, 0xCE, 0x2E, 0x1D, 0x6D, 0xFC, 0xAE, 0xD2, + 0xF9, 0x42, 0x7E, 0xEA, 0x6D, 0x59, 0x7A, 0xB3, 0x93, 0xE4, + 0x4B, 0x4B, 0x54, 0x63, 0xD8, 0xCE, 0x44, 0x06, 0xC2, 0xEC, + 0x9F, 0xF6, 0x05, 0x55, 0x46, 0xF4, 0x3E, 0x8F, 0xF2, 0x0C, + 0x30, 0x7E, 0x5C, 0xDD, 0x88, 0x49, 0x3B, 0x59, 0xB9, 0x87, + 0xBC, 0xC6, 0xC5, 0x24, 0x8A, 0x10, 0x63, 0x21, 0x1F, 0x66, + 0x1A, 0x3E, 0xF4, 0x58, 0xD1, 0x6C, 0x0D, 0x40, 0xB2, 0xC0, + 0x1D, 0x63, 0x42, 0x0E, 0xC4, 0x56, 0x0E, 0xC0, 0xCC, 0xC2, + 0xD6, 0x66, 0x0E, 0xC4, 0xAB, 0xB5, 0x33, 0xF6, 0x51, 0x02, + 0x81, 0x80, 0x19, 0x7E, 0xE6, 0xA5, 0xB6, 0xD1, 0x39, 0x6A, + 0x48, 0x55, 0xAC, 0x24, 0x96, 0x9B, 0x12, 0x28, 0x6D, 0x7B, + 0x5C, 0x05, 0x25, 0x5A, 0x72, 0x05, 0x7E, 0x42, 0xF5, 0x83, + 0x1A, 0x78, 0x2C, 0x4D, 0xAE, 0xB4, 0x36, 0x96, 0xA9, 0xBA, + 0xE0, 0xAC, 0x26, 0x9D, 0xA9, 0x6A, 0x29, 0x83, 0xB9, 0x6D, + 0xC5, 0xEC, 0xFA, 0x4A, 0x9C, 0x09, 0x6A, 0x7E, 0xE4, 0x9B, + 0xDC, 0x9B, 0x2A, 0x27, 0x6E, 0x4F, 0xBA, 0xD8, 0xA5, 0x67, + 0xDB, 0xEC, 0x41, 0x5F, 0x29, 0x1C, 0x40, 0x83, 0xEB, 0x59, + 0x56, 0xD7, 0xA9, 0x4E, 0xAB, 0xAE, 0x70, 0x67, 0xD1, 0xA3, + 0xF1, 0x6C, 0xD7, 0x8F, 0x96, 0x0E, 0x8D, 0xAC, 0xAB, 0x55, + 0x58, 0x66, 0xD3, 0x1E, 0x47, 0x9B, 0xF0, 0x4C, 0xED, 0xF6, + 0x49, 0xE8, 0xE9, 0x7B, 0x32, 0x61, 0x20, 0x31, 0x95, 0x05, + 0xB2, 0xF6, 0x09, 0xEA, 0x32, 0x14, 0x0F, 0xCF, 0x9A, 0x41, + 0x02, 0x81, 0x80, 0x77, 0x3F, 0xB6, 0x14, 0x8D, 0xC5, 0x13, + 0x08, 0x7E, 0xC9, 0xC4, 0xEA, 0xD4, 0xBA, 0x0D, 0xA4, 0x9E, + 0xB3, 0x6E, 0xDE, 0x1A, 0x7A, 0xF8, 0x89, 0x88, 0xEF, 0x36, + 0x3C, 0x11, 0xBC, 0x83, 0xE8, 0x30, 0x6C, 0x81, 0x7C, 0x47, + 0xF3, 0x4D, 0xCA, 0xEA, 0x56, 0x01, 0x62, 0x55, 0x2E, 0x4B, + 0x89, 0xA9, 0xBD, 0x6F, 0x01, 0xF6, 0x74, 0x02, 0xAA, 0xE3, + 0x84, 0x66, 0x06, 0x95, 0x34, 0xA1, 0xE2, 0xCA, 0x65, 0xFE, + 0xA3, 0x2D, 0x43, 0x97, 0x95, 0x6C, 0x6F, 0xD5, 0xB4, 0x38, + 0xF6, 0xF9, 0x95, 0x30, 0xFA, 0xF8, 0x9C, 0x25, 0x2B, 0xB6, + 0x14, 0x51, 0xCC, 0x2E, 0xB3, 0x5B, 0xD6, 0xDC, 0x1A, 0xEC, + 0x2D, 0x09, 0x5B, 0x3F, 0x3A, 0xD0, 0xB8, 0x4E, 0x27, 0x1F, + 0xDC, 0x2A, 0xEE, 0xAC, 0xA9, 0x59, 0x5D, 0x07, 0x63, 0x11, + 0x83, 0x0B, 0xD4, 0x74, 0x80, 0xB6, 0x7D, 0x62, 0x45, 0xBF, + 0x56 +}; +static const int sizeof_rsa_key_der_2048 = sizeof(rsa_key_der_2048); + +/* ./certs/ca-cert.der, 2048-bit */ +static const unsigned char ca_cert_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xE0, 0x30, 0x82, 0x03, 0xC8, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xA6, 0x66, 0x38, 0x49, + 0x45, 0x9B, 0xDC, 0x81, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x31, 0x31, 0x32, 0x33, + 0x31, 0x32, 0x34, 0x39, 0x33, 0x37, 0x5A, 0x17, 0x0D, 0x31, + 0x38, 0x30, 0x38, 0x31, 0x39, 0x31, 0x32, 0x34, 0x39, 0x33, + 0x37, 0x5A, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, + 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, + 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, + 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, + 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBF, 0x0C, 0xCA, 0x2D, + 0x14, 0xB2, 0x1E, 0x84, 0x42, 0x5B, 0xCD, 0x38, 0x1F, 0x4A, + 0xF2, 0x4D, 0x75, 0x10, 0xF1, 0xB6, 0x35, 0x9F, 0xDF, 0xCA, + 0x7D, 0x03, 0x98, 0xD3, 0xAC, 0xDE, 0x03, 0x66, 0xEE, 0x2A, + 0xF1, 0xD8, 0xB0, 0x7D, 0x6E, 0x07, 0x54, 0x0B, 0x10, 0x98, + 0x21, 0x4D, 0x80, 0xCB, 0x12, 0x20, 0xE7, 0xCC, 0x4F, 0xDE, + 0x45, 0x7D, 0xC9, 0x72, 0x77, 0x32, 0xEA, 0xCA, 0x90, 0xBB, + 0x69, 0x52, 0x10, 0x03, 0x2F, 0xA8, 0xF3, 0x95, 0xC5, 0xF1, + 0x8B, 0x62, 0x56, 0x1B, 0xEF, 0x67, 0x6F, 0xA4, 0x10, 0x41, + 0x95, 0xAD, 0x0A, 0x9B, 0xE3, 0xA5, 0xC0, 0xB0, 0xD2, 0x70, + 0x76, 0x50, 0x30, 0x5B, 0xA8, 0xE8, 0x08, 0x2C, 0x7C, 0xED, + 0xA7, 0xA2, 0x7A, 0x8D, 0x38, 0x29, 0x1C, 0xAC, 0xC7, 0xED, + 0xF2, 0x7C, 0x95, 0xB0, 0x95, 0x82, 0x7D, 0x49, 0x5C, 0x38, + 0xCD, 0x77, 0x25, 0xEF, 0xBD, 0x80, 0x75, 0x53, 0x94, 0x3C, + 0x3D, 0xCA, 0x63, 0x5B, 0x9F, 0x15, 0xB5, 0xD3, 0x1D, 0x13, + 0x2F, 0x19, 0xD1, 0x3C, 0xDB, 0x76, 0x3A, 0xCC, 0xB8, 0x7D, + 0xC9, 0xE5, 0xC2, 0xD7, 0xDA, 0x40, 0x6F, 0xD8, 0x21, 0xDC, + 0x73, 0x1B, 0x42, 0x2D, 0x53, 0x9C, 0xFE, 0x1A, 0xFC, 0x7D, + 0xAB, 0x7A, 0x36, 0x3F, 0x98, 0xDE, 0x84, 0x7C, 0x05, 0x67, + 0xCE, 0x6A, 0x14, 0x38, 0x87, 0xA9, 0xF1, 0x8C, 0xB5, 0x68, + 0xCB, 0x68, 0x7F, 0x71, 0x20, 0x2B, 0xF5, 0xA0, 0x63, 0xF5, + 0x56, 0x2F, 0xA3, 0x26, 0xD2, 0xB7, 0x6F, 0xB1, 0x5A, 0x17, + 0xD7, 0x38, 0x99, 0x08, 0xFE, 0x93, 0x58, 0x6F, 0xFE, 0xC3, + 0x13, 0x49, 0x08, 0x16, 0x0B, 0xA7, 0x4D, 0x67, 0x00, 0x52, + 0x31, 0x67, 0x23, 0x4E, 0x98, 0xED, 0x51, 0x45, 0x1D, 0xB9, + 0x04, 0xD9, 0x0B, 0xEC, 0xD8, 0x28, 0xB3, 0x4B, 0xBD, 0xED, + 0x36, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + 0x31, 0x30, 0x82, 0x01, 0x2D, 0x30, 0x1D, 0x06, 0x03, 0x55, + 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x27, 0x8E, 0x67, 0x11, + 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, + 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0x30, 0x81, 0xC9, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, + 0x80, 0x14, 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, + 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, + 0xE8, 0xD5, 0xA1, 0x81, 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, + 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, + 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, + 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, + 0x09, 0x00, 0xA6, 0x66, 0x38, 0x49, 0x45, 0x9B, 0xDC, 0x81, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x32, 0x06, 0x08, 0x2B, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30, 0x24, + 0x30, 0x22, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, + 0x2F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, + 0x3A, 0x32, 0x32, 0x32, 0x32, 0x32, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x41, 0x8F, 0xFB, 0x6B, + 0x65, 0x6B, 0x36, 0xF2, 0x56, 0x4F, 0x0C, 0x48, 0xB0, 0x4D, + 0x8C, 0xC2, 0xCB, 0xD6, 0x58, 0x7A, 0x83, 0x3A, 0x30, 0x7D, + 0x62, 0x7B, 0x86, 0xF1, 0x15, 0x26, 0xB3, 0x26, 0x02, 0x77, + 0xF2, 0xC8, 0x57, 0xE5, 0x1E, 0x60, 0x68, 0x8B, 0xA4, 0xE8, + 0xF3, 0xA8, 0xB2, 0x88, 0xA4, 0x2F, 0xE8, 0x6E, 0x25, 0x8D, + 0x6B, 0xDC, 0x53, 0xAB, 0x2F, 0xD3, 0x47, 0x8C, 0xD6, 0x27, + 0xAB, 0x39, 0xBC, 0xD3, 0xCA, 0xD8, 0x01, 0x96, 0xA4, 0x44, + 0x57, 0x38, 0x93, 0xAB, 0xC3, 0xF3, 0x95, 0x67, 0x7F, 0xCF, + 0x25, 0x1D, 0xB7, 0x04, 0xDC, 0x06, 0xC9, 0x5D, 0x24, 0xC1, + 0x54, 0x13, 0x71, 0x81, 0x21, 0x31, 0xEE, 0x9F, 0xB4, 0x9D, + 0xCE, 0x98, 0x66, 0xA4, 0xA0, 0x77, 0xC1, 0x88, 0x18, 0xA4, + 0xD1, 0x36, 0xEE, 0xCD, 0xD8, 0xC1, 0x1B, 0xBC, 0x03, 0xD6, + 0x85, 0x9A, 0x2E, 0x21, 0x82, 0x95, 0x4C, 0xB2, 0x2A, 0xFE, + 0x69, 0xDB, 0xAC, 0xE4, 0x97, 0xE1, 0xE9, 0x0E, 0xF1, 0xD3, + 0xEF, 0x20, 0x86, 0x03, 0x01, 0x66, 0x6B, 0xF0, 0x26, 0x0F, + 0x39, 0x04, 0x26, 0xF5, 0x42, 0x98, 0x3F, 0x95, 0x48, 0x5F, + 0xB5, 0x5D, 0xBC, 0x49, 0x4C, 0x81, 0x38, 0xD5, 0xE9, 0x72, + 0x32, 0x1C, 0x66, 0x1B, 0x12, 0x80, 0x0F, 0xDB, 0x99, 0xF0, + 0x97, 0x67, 0x61, 0x79, 0xAD, 0xAB, 0xBE, 0x6A, 0xEA, 0xAA, + 0xCC, 0x3D, 0xF9, 0x40, 0x99, 0x00, 0x93, 0xBB, 0xDF, 0x4B, + 0x41, 0xD4, 0x7F, 0xF1, 0x93, 0xB2, 0x70, 0x83, 0x3A, 0xE3, + 0x6B, 0x44, 0x4B, 0x1F, 0x9F, 0x77, 0x53, 0xEA, 0x5D, 0xE6, + 0x59, 0x1E, 0xC0, 0x2D, 0x4B, 0x83, 0xD6, 0xF4, 0xA3, 0xD4, + 0xA9, 0xC3, 0x91, 0x12, 0xE7, 0x61, 0x3F, 0x56, 0x9D, 0x8F, + 0xB8, 0x19, 0x29, 0x62, 0x1B, 0x58, 0xDF, 0x73, 0x99, 0x1F, + 0x49, 0x63 +}; +static const int sizeof_ca_cert_der_2048 = sizeof(ca_cert_der_2048); + +/* ./certs/server-key.der, 2048-bit */ +static const unsigned char server_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xC0, 0x95, 0x08, 0xE1, 0x57, 0x41, 0xF2, 0x71, + 0x6D, 0xB7, 0xD2, 0x45, 0x41, 0x27, 0x01, 0x65, 0xC6, 0x45, + 0xAE, 0xF2, 0xBC, 0x24, 0x30, 0xB8, 0x95, 0xCE, 0x2F, 0x4E, + 0xD6, 0xF6, 0x1C, 0x88, 0xBC, 0x7C, 0x9F, 0xFB, 0xA8, 0x67, + 0x7F, 0xFE, 0x5C, 0x9C, 0x51, 0x75, 0xF7, 0x8A, 0xCA, 0x07, + 0xE7, 0x35, 0x2F, 0x8F, 0xE1, 0xBD, 0x7B, 0xC0, 0x2F, 0x7C, + 0xAB, 0x64, 0xA8, 0x17, 0xFC, 0xCA, 0x5D, 0x7B, 0xBA, 0xE0, + 0x21, 0xE5, 0x72, 0x2E, 0x6F, 0x2E, 0x86, 0xD8, 0x95, 0x73, + 0xDA, 0xAC, 0x1B, 0x53, 0xB9, 0x5F, 0x3F, 0xD7, 0x19, 0x0D, + 0x25, 0x4F, 0xE1, 0x63, 0x63, 0x51, 0x8B, 0x0B, 0x64, 0x3F, + 0xAD, 0x43, 0xB8, 0xA5, 0x1C, 0x5C, 0x34, 0xB3, 0xAE, 0x00, + 0xA0, 0x63, 0xC5, 0xF6, 0x7F, 0x0B, 0x59, 0x68, 0x78, 0x73, + 0xA6, 0x8C, 0x18, 0xA9, 0x02, 0x6D, 0xAF, 0xC3, 0x19, 0x01, + 0x2E, 0xB8, 0x10, 0xE3, 0xC6, 0xCC, 0x40, 0xB4, 0x69, 0xA3, + 0x46, 0x33, 0x69, 0x87, 0x6E, 0xC4, 0xBB, 0x17, 0xA6, 0xF3, + 0xE8, 0xDD, 0xAD, 0x73, 0xBC, 0x7B, 0x2F, 0x21, 0xB5, 0xFD, + 0x66, 0x51, 0x0C, 0xBD, 0x54, 0xB3, 0xE1, 0x6D, 0x5F, 0x1C, + 0xBC, 0x23, 0x73, 0xD1, 0x09, 0x03, 0x89, 0x14, 0xD2, 0x10, + 0xB9, 0x64, 0xC3, 0x2A, 0xD0, 0xA1, 0x96, 0x4A, 0xBC, 0xE1, + 0xD4, 0x1A, 0x5B, 0xC7, 0xA0, 0xC0, 0xC1, 0x63, 0x78, 0x0F, + 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, 0x32, 0x23, 0x95, 0xA1, + 0x77, 0xBA, 0x13, 0xD2, 0x97, 0x73, 0xE2, 0x5D, 0x25, 0xC9, + 0x6A, 0x0D, 0xC3, 0x39, 0x60, 0xA4, 0xB4, 0xB0, 0x69, 0x42, + 0x42, 0x09, 0xE9, 0xD8, 0x08, 0xBC, 0x33, 0x20, 0xB3, 0x58, + 0x22, 0xA7, 0xAA, 0xEB, 0xC4, 0xE1, 0xE6, 0x61, 0x83, 0xC5, + 0xD2, 0x96, 0xDF, 0xD9, 0xD0, 0x4F, 0xAD, 0xD7, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9A, 0xD0, + 0x34, 0x0F, 0x52, 0x62, 0x05, 0x50, 0x01, 0xEF, 0x9F, 0xED, + 0x64, 0x6E, 0xC2, 0xC4, 0xDA, 0x1A, 0xF2, 0x84, 0xD7, 0x92, + 0x10, 0x48, 0x92, 0xC4, 0xE9, 0x6A, 0xEB, 0x8B, 0x75, 0x6C, + 0xC6, 0x79, 0x38, 0xF2, 0xC9, 0x72, 0x4A, 0x86, 0x64, 0x54, + 0x95, 0x77, 0xCB, 0xC3, 0x9A, 0x9D, 0xB7, 0xD4, 0x1D, 0xA4, + 0x00, 0xC8, 0x9E, 0x4E, 0xE4, 0xDD, 0xC7, 0xBA, 0x67, 0x16, + 0xC1, 0x74, 0xBC, 0xA9, 0xD6, 0x94, 0x8F, 0x2B, 0x30, 0x1A, + 0xFB, 0xED, 0xDF, 0x21, 0x05, 0x23, 0xD9, 0x4A, 0x39, 0xBD, + 0x98, 0x6B, 0x65, 0x9A, 0xB8, 0xDC, 0xC4, 0x7D, 0xEE, 0xA6, + 0x43, 0x15, 0x2E, 0x3D, 0xBE, 0x1D, 0x22, 0x60, 0x2A, 0x73, + 0x30, 0xD5, 0x3E, 0xD8, 0xA2, 0xAC, 0x86, 0x43, 0x2E, 0xC4, + 0xF5, 0x64, 0x5E, 0x3F, 0x89, 0x75, 0x0F, 0x11, 0xD8, 0x51, + 0x25, 0x4E, 0x9F, 0xD8, 0xAA, 0xA3, 0xCE, 0x60, 0xB3, 0xE2, + 0x8A, 0xD9, 0x7E, 0x1B, 0xF0, 0x64, 0xCA, 0x9A, 0x5B, 0x05, + 0x0B, 0x5B, 0xAA, 0xCB, 0xE5, 0xE3, 0x3F, 0x6E, 0x32, 0x22, + 0x05, 0xF3, 0xD0, 0xFA, 0xEF, 0x74, 0x52, 0x81, 0xE2, 0x5F, + 0x74, 0xD3, 0xBD, 0xFF, 0x31, 0x83, 0x45, 0x75, 0xFA, 0x63, + 0x7A, 0x97, 0x2E, 0xD6, 0xB6, 0x19, 0xC6, 0x92, 0x26, 0xE4, + 0x28, 0x06, 0x50, 0x50, 0x0E, 0x78, 0x2E, 0xA9, 0x78, 0x0D, + 0x14, 0x97, 0xB4, 0x12, 0xD8, 0x31, 0x40, 0xAB, 0xA1, 0x01, + 0x41, 0xC2, 0x30, 0xF8, 0x07, 0x5F, 0x16, 0xE4, 0x61, 0x77, + 0xD2, 0x60, 0xF2, 0x9F, 0x8D, 0xE8, 0xF4, 0xBA, 0xEB, 0x63, + 0xDE, 0x2A, 0x97, 0x81, 0xEF, 0x4C, 0x6C, 0xE6, 0x55, 0x34, + 0x51, 0x2B, 0x28, 0x34, 0xF4, 0x53, 0x1C, 0xC4, 0x58, 0x0A, + 0x3F, 0xBB, 0xAF, 0xB5, 0xF7, 0x4A, 0x85, 0x43, 0x2D, 0x3C, + 0xF1, 0x58, 0x58, 0x81, 0x02, 0x81, 0x81, 0x00, 0xF2, 0x2C, + 0x54, 0x76, 0x39, 0x23, 0x63, 0xC9, 0x10, 0x32, 0xB7, 0x93, + 0xAD, 0xAF, 0xBE, 0x19, 0x75, 0x96, 0x81, 0x64, 0xE6, 0xB5, + 0xB8, 0x89, 0x42, 0x41, 0xD1, 0x6D, 0xD0, 0x1C, 0x1B, 0xF8, + 0x1B, 0xAC, 0x69, 0xCB, 0x36, 0x3C, 0x64, 0x7D, 0xDC, 0xF4, + 0x19, 0xB8, 0xC3, 0x60, 0xB1, 0x57, 0x48, 0x5F, 0x52, 0x4F, + 0x59, 0x3A, 0x55, 0x7F, 0x32, 0xC0, 0x19, 0x43, 0x50, 0x3F, + 0xAE, 0xCE, 0x6F, 0x17, 0xF3, 0x0E, 0x9F, 0x40, 0xCA, 0x4E, + 0xAD, 0x15, 0x3B, 0xC9, 0x79, 0xE9, 0xC0, 0x59, 0x38, 0x73, + 0x70, 0x9C, 0x0A, 0x7C, 0xC9, 0x3A, 0x48, 0x32, 0xA7, 0xD8, + 0x49, 0x75, 0x0A, 0x85, 0xC2, 0xC2, 0xFD, 0x15, 0x73, 0xDA, + 0x99, 0x09, 0x2A, 0x69, 0x9A, 0x9F, 0x0A, 0x71, 0xBF, 0xB0, + 0x04, 0xA6, 0x8C, 0x7A, 0x5A, 0x6F, 0x48, 0x5A, 0x54, 0x3B, + 0xC6, 0xB1, 0x53, 0x17, 0xDF, 0xE7, 0x02, 0x81, 0x81, 0x00, + 0xCB, 0x93, 0xDE, 0x77, 0x15, 0x5D, 0xB7, 0x5C, 0x5C, 0x7C, + 0xD8, 0x90, 0xA9, 0x98, 0x2D, 0xD6, 0x69, 0x0E, 0x63, 0xB3, + 0xA3, 0xDC, 0xA6, 0xCC, 0x8B, 0x6A, 0xA4, 0xA2, 0x12, 0x8C, + 0x8E, 0x7B, 0x48, 0x2C, 0xB2, 0x4B, 0x37, 0xDC, 0x06, 0x18, + 0x7D, 0xEA, 0xFE, 0x76, 0xA1, 0xD4, 0xA1, 0xE9, 0x3F, 0x0D, + 0xCD, 0x1B, 0x5F, 0xAF, 0x5F, 0x9E, 0x96, 0x5B, 0x5B, 0x0F, + 0xA1, 0x7C, 0xAF, 0xB3, 0x9B, 0x90, 0xDB, 0x57, 0x73, 0x3A, + 0xED, 0xB0, 0x23, 0x44, 0xAE, 0x41, 0x4F, 0x1F, 0x07, 0x42, + 0x13, 0x23, 0x4C, 0xCB, 0xFA, 0xF4, 0x14, 0xA4, 0xD5, 0xF7, + 0x9E, 0x36, 0x7C, 0x5B, 0x9F, 0xA8, 0x3C, 0xC1, 0x85, 0x5F, + 0x74, 0xD2, 0x39, 0x2D, 0xFF, 0xD0, 0x84, 0xDF, 0xFB, 0xB3, + 0x20, 0x7A, 0x2E, 0x9B, 0x17, 0xAE, 0xE6, 0xBA, 0x0B, 0xAE, + 0x5F, 0x53, 0xA4, 0x52, 0xED, 0x1B, 0xC4, 0x91, 0x02, 0x81, + 0x81, 0x00, 0xEC, 0x98, 0xDA, 0xBB, 0xD5, 0xFE, 0xF9, 0x52, + 0x4A, 0x7D, 0x02, 0x55, 0x49, 0x6F, 0x55, 0x6E, 0x52, 0x2F, + 0x84, 0xA3, 0x2B, 0xB3, 0x86, 0x62, 0xB3, 0x54, 0xD2, 0x63, + 0x52, 0xDA, 0xE3, 0x88, 0x76, 0xA0, 0xEF, 0x8B, 0x15, 0xA5, + 0xD3, 0x18, 0x14, 0x72, 0x77, 0x5E, 0xC7, 0xA3, 0x04, 0x1F, + 0x9E, 0x19, 0x62, 0xB5, 0x1B, 0x1B, 0x9E, 0xC3, 0xF2, 0xB5, + 0x32, 0xF9, 0x4C, 0xC1, 0xAA, 0xEB, 0x0C, 0x26, 0x7D, 0xD4, + 0x5F, 0x4A, 0x51, 0x5C, 0xA4, 0x45, 0x06, 0x70, 0x44, 0xA7, + 0x56, 0xC0, 0xD4, 0x22, 0x14, 0x76, 0x9E, 0xD8, 0x63, 0x50, + 0x89, 0x90, 0xD3, 0xE2, 0xBF, 0x81, 0x95, 0x92, 0x31, 0x41, + 0x87, 0x39, 0x1A, 0x43, 0x0B, 0x18, 0xA5, 0x53, 0x1F, 0x39, + 0x1A, 0x5F, 0x1F, 0x43, 0xBC, 0x87, 0x6A, 0xDF, 0x6E, 0xD3, + 0x22, 0x00, 0xFE, 0x22, 0x98, 0x70, 0x4E, 0x1A, 0x19, 0x29, + 0x02, 0x81, 0x81, 0x00, 0x8A, 0x41, 0x56, 0x28, 0x51, 0x9E, + 0x5F, 0xD4, 0x9E, 0x0B, 0x3B, 0x98, 0xA3, 0x54, 0xF2, 0x6C, + 0x56, 0xD4, 0xAA, 0xE9, 0x69, 0x33, 0x85, 0x24, 0x0C, 0xDA, + 0xD4, 0x0C, 0x2D, 0xC4, 0xBF, 0x4F, 0x02, 0x69, 0x38, 0x7C, + 0xD4, 0xE6, 0xDC, 0x4C, 0xED, 0xD7, 0x16, 0x11, 0xC3, 0x3E, + 0x00, 0xE7, 0xC3, 0x26, 0xC0, 0x51, 0x02, 0xDE, 0xBB, 0x75, + 0x9C, 0x6F, 0x56, 0x9C, 0x7A, 0xF3, 0x8E, 0xEF, 0xCF, 0x8A, + 0xC5, 0x2B, 0xD2, 0xDA, 0x06, 0x6A, 0x44, 0xC9, 0x73, 0xFE, + 0x6E, 0x99, 0x87, 0xF8, 0x5B, 0xBE, 0xF1, 0x7C, 0xE6, 0x65, + 0xB5, 0x4F, 0x6C, 0xF0, 0xC9, 0xC5, 0xFF, 0x16, 0xCA, 0x8B, + 0x1B, 0x17, 0xE2, 0x58, 0x3D, 0xA2, 0x37, 0xAB, 0x01, 0xBC, + 0xBF, 0x40, 0xCE, 0x53, 0x8C, 0x8E, 0xED, 0xEF, 0xEE, 0x59, + 0x9D, 0xE0, 0x63, 0xE6, 0x7C, 0x5E, 0xF5, 0x8E, 0x4B, 0xF1, + 0x3B, 0xC1, 0x02, 0x81, 0x80, 0x4D, 0x45, 0xF9, 0x40, 0x8C, + 0xC5, 0x5B, 0xF4, 0x2A, 0x1A, 0x8A, 0xB4, 0xF2, 0x1C, 0xAC, + 0x6B, 0xE9, 0x0C, 0x56, 0x36, 0xB7, 0x4E, 0x72, 0x96, 0xD5, + 0xE5, 0x8A, 0xD2, 0xE2, 0xFF, 0xF1, 0xF1, 0x18, 0x13, 0x3D, + 0x86, 0x09, 0xB8, 0xD8, 0x76, 0xA7, 0xC9, 0x1C, 0x71, 0x52, + 0x94, 0x30, 0x43, 0xE0, 0xF1, 0x78, 0x74, 0xFD, 0x61, 0x1B, + 0x4C, 0x09, 0xCC, 0xE6, 0x68, 0x2A, 0x71, 0xAD, 0x1C, 0xDF, + 0x43, 0xBC, 0x56, 0xDB, 0xA5, 0xA4, 0xBE, 0x35, 0x70, 0xA4, + 0x5E, 0xCF, 0x4F, 0xFC, 0x00, 0x55, 0x99, 0x3A, 0x3D, 0x23, + 0xCF, 0x67, 0x5A, 0xF5, 0x22, 0xF8, 0xB5, 0x29, 0xD0, 0x44, + 0x11, 0xEB, 0x35, 0x2E, 0x46, 0xBE, 0xFD, 0x8E, 0x18, 0xB2, + 0x5F, 0xA8, 0xBF, 0x19, 0x32, 0xA1, 0xF5, 0xDC, 0x03, 0xE6, + 0x7C, 0x9A, 0x1F, 0x0C, 0x7C, 0xA9, 0xB0, 0x0E, 0x21, 0x37, + 0x3B, 0xF1, 0xB0 +}; +static const int sizeof_server_key_der_2048 = sizeof(server_key_der_2048); + +/* ./certs/server-cert.der, 2048-bit */ +static const unsigned char server_cert_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xD4, 0x30, 0x82, 0x03, 0xBC, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, + 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, + 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, + 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x31, 0x31, + 0x32, 0x33, 0x31, 0x32, 0x34, 0x39, 0x33, 0x37, 0x5A, 0x17, + 0x0D, 0x31, 0x38, 0x30, 0x38, 0x31, 0x39, 0x31, 0x32, 0x34, + 0x39, 0x33, 0x37, 0x5A, 0x30, 0x81, 0x90, 0x31, 0x0B, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, + 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, + 0x66, 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x53, 0x75, 0x70, 0x70, 0x6F, + 0x72, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, + 0x82, 0x01, 0x01, 0x00, 0xC0, 0x95, 0x08, 0xE1, 0x57, 0x41, + 0xF2, 0x71, 0x6D, 0xB7, 0xD2, 0x45, 0x41, 0x27, 0x01, 0x65, + 0xC6, 0x45, 0xAE, 0xF2, 0xBC, 0x24, 0x30, 0xB8, 0x95, 0xCE, + 0x2F, 0x4E, 0xD6, 0xF6, 0x1C, 0x88, 0xBC, 0x7C, 0x9F, 0xFB, + 0xA8, 0x67, 0x7F, 0xFE, 0x5C, 0x9C, 0x51, 0x75, 0xF7, 0x8A, + 0xCA, 0x07, 0xE7, 0x35, 0x2F, 0x8F, 0xE1, 0xBD, 0x7B, 0xC0, + 0x2F, 0x7C, 0xAB, 0x64, 0xA8, 0x17, 0xFC, 0xCA, 0x5D, 0x7B, + 0xBA, 0xE0, 0x21, 0xE5, 0x72, 0x2E, 0x6F, 0x2E, 0x86, 0xD8, + 0x95, 0x73, 0xDA, 0xAC, 0x1B, 0x53, 0xB9, 0x5F, 0x3F, 0xD7, + 0x19, 0x0D, 0x25, 0x4F, 0xE1, 0x63, 0x63, 0x51, 0x8B, 0x0B, + 0x64, 0x3F, 0xAD, 0x43, 0xB8, 0xA5, 0x1C, 0x5C, 0x34, 0xB3, + 0xAE, 0x00, 0xA0, 0x63, 0xC5, 0xF6, 0x7F, 0x0B, 0x59, 0x68, + 0x78, 0x73, 0xA6, 0x8C, 0x18, 0xA9, 0x02, 0x6D, 0xAF, 0xC3, + 0x19, 0x01, 0x2E, 0xB8, 0x10, 0xE3, 0xC6, 0xCC, 0x40, 0xB4, + 0x69, 0xA3, 0x46, 0x33, 0x69, 0x87, 0x6E, 0xC4, 0xBB, 0x17, + 0xA6, 0xF3, 0xE8, 0xDD, 0xAD, 0x73, 0xBC, 0x7B, 0x2F, 0x21, + 0xB5, 0xFD, 0x66, 0x51, 0x0C, 0xBD, 0x54, 0xB3, 0xE1, 0x6D, + 0x5F, 0x1C, 0xBC, 0x23, 0x73, 0xD1, 0x09, 0x03, 0x89, 0x14, + 0xD2, 0x10, 0xB9, 0x64, 0xC3, 0x2A, 0xD0, 0xA1, 0x96, 0x4A, + 0xBC, 0xE1, 0xD4, 0x1A, 0x5B, 0xC7, 0xA0, 0xC0, 0xC1, 0x63, + 0x78, 0x0F, 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, 0x32, 0x23, + 0x95, 0xA1, 0x77, 0xBA, 0x13, 0xD2, 0x97, 0x73, 0xE2, 0x5D, + 0x25, 0xC9, 0x6A, 0x0D, 0xC3, 0x39, 0x60, 0xA4, 0xB4, 0xB0, + 0x69, 0x42, 0x42, 0x09, 0xE9, 0xD8, 0x08, 0xBC, 0x33, 0x20, + 0xB3, 0x58, 0x22, 0xA7, 0xAA, 0xEB, 0xC4, 0xE1, 0xE6, 0x61, + 0x83, 0xC5, 0xD2, 0x96, 0xDF, 0xD9, 0xD0, 0x4F, 0xAD, 0xD7, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x31, 0x30, + 0x82, 0x01, 0x2D, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0xB3, 0x11, 0x32, 0xC9, 0x92, 0x98, + 0x84, 0xE2, 0xC9, 0xF8, 0xD0, 0x3B, 0x6E, 0x03, 0x42, 0xCA, + 0x1F, 0x0E, 0x8E, 0x3C, 0x30, 0x81, 0xC9, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, + 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, + 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, + 0xA1, 0x81, 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, + 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, + 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, + 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, + 0xA6, 0x66, 0x38, 0x49, 0x45, 0x9B, 0xDC, 0x81, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x32, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30, 0x24, 0x30, 0x22, + 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, + 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6C, + 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, 0x3A, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x71, 0x17, 0x8F, 0x6F, 0x7D, 0xD6, + 0x11, 0x01, 0x79, 0xAC, 0xE9, 0xC2, 0xFB, 0x71, 0x69, 0x6B, + 0x0C, 0x64, 0x91, 0xC1, 0x32, 0x8B, 0x9C, 0x62, 0x72, 0xB5, + 0x62, 0xBB, 0xF8, 0xCF, 0x6C, 0x27, 0xDF, 0xF0, 0x64, 0xD6, + 0x4A, 0x55, 0x4F, 0x7F, 0x4A, 0x8B, 0x7B, 0x80, 0x5B, 0x3C, + 0xA0, 0x31, 0xB0, 0x25, 0x92, 0x02, 0x02, 0x9C, 0x99, 0xA5, + 0x8E, 0x0C, 0x61, 0xEF, 0xB4, 0x1E, 0x01, 0x2E, 0x1C, 0xE9, + 0x9C, 0x59, 0x2D, 0xEF, 0x6E, 0x03, 0x4D, 0xF1, 0x59, 0xE5, + 0x5F, 0x69, 0x66, 0x5C, 0x0A, 0xE6, 0xCD, 0xF6, 0x74, 0x20, + 0x86, 0x4C, 0xF6, 0x8F, 0x22, 0x86, 0x68, 0x7E, 0xFE, 0x67, + 0x3F, 0x3D, 0x19, 0xB8, 0x61, 0xEF, 0xC5, 0xA5, 0x58, 0xA8, + 0x2A, 0xCE, 0xD3, 0x2C, 0xA7, 0x1B, 0xDD, 0xC8, 0x59, 0xC7, + 0xE7, 0xCF, 0x42, 0x42, 0xDB, 0xAF, 0xFE, 0x15, 0x82, 0xC9, + 0xE5, 0x53, 0xFA, 0xB4, 0x37, 0x55, 0x67, 0x47, 0x0F, 0xE7, + 0x24, 0x88, 0x14, 0xA3, 0x6C, 0xBE, 0x5F, 0x72, 0x05, 0x5F, + 0x56, 0x33, 0xAA, 0x7F, 0xAC, 0x2E, 0x10, 0x92, 0xB7, 0xA2, + 0xF9, 0xC1, 0x62, 0x0C, 0x3B, 0x0C, 0x69, 0x9A, 0x71, 0x15, + 0x11, 0xBC, 0x37, 0xBF, 0x8E, 0x23, 0x14, 0xC2, 0xB1, 0x0D, + 0xDF, 0x89, 0x45, 0x1E, 0xDF, 0x14, 0xE8, 0x95, 0x35, 0x88, + 0x27, 0xA8, 0xAB, 0xDD, 0x7C, 0x23, 0x3F, 0xBB, 0xFE, 0x4E, + 0x0E, 0xEA, 0xA6, 0xEE, 0xF5, 0x77, 0xFB, 0xAA, 0xB8, 0x28, + 0x33, 0xF9, 0x61, 0xB0, 0xD2, 0x79, 0x46, 0xA4, 0xBA, 0xA0, + 0x90, 0xC8, 0xE7, 0x96, 0x8F, 0x27, 0xE9, 0x1E, 0xD0, 0x92, + 0x43, 0xBB, 0x84, 0xC7, 0xF3, 0x28, 0x0C, 0x41, 0xAA, 0x77, + 0x39, 0x65, 0xAA, 0x0D, 0x02, 0xB0, 0xE0, 0x4D, 0xB1, 0x17, + 0x41, 0xC9, 0xF0, 0xD4, 0x47, 0x87, 0xFB, 0x0F, 0xF0, 0x40 + +}; +static const int sizeof_server_cert_der_2048 = sizeof(server_cert_der_2048); + +#endif /* USE_CERT_BUFFERS_2048 */ + +/* dh1024 p */ +static const unsigned char dh_p[] = +{ + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, +}; + +/* dh1024 g */ +static const unsigned char dh_g[] = +{ + 0x02, +}; + +#endif /* WOLFSSL_CERTS_TEST_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/crl.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,53 @@ +/* crl.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_CRL_H +#define WOLFSSL_CRL_H + + +#ifdef HAVE_CRL + +#include <wolfssl/ssl.h> +#include <wolfssl/wolfcrypt/asn.h> + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct WOLFSSL_CRL WOLFSSL_CRL; + +WOLFSSL_LOCAL int InitCRL(WOLFSSL_CRL*, WOLFSSL_CERT_MANAGER*); +WOLFSSL_LOCAL void FreeCRL(WOLFSSL_CRL*, int dynamic); + +WOLFSSL_LOCAL int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int mon); +WOLFSSL_LOCAL int BufferLoadCRL(WOLFSSL_CRL*, const byte*, long, int); +WOLFSSL_LOCAL int CheckCertCRL(WOLFSSL_CRL*, DecodedCert*); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CRL */ +#endif /* WOLFSSL_CRL_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/error-ssl.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,176 @@ +/* error-ssl.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 */ + PMS_VERSION_ERROR = -325, /* pre m secret version error */ + 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_PATH_ERROR = -358, /* Bad path for opendir */ + 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 */ + SSL_NO_PEM_HEADER = -372, /* no PEM header found */ + 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 */ + + /* 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 */ + /* 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 !!!! */ +}; + + +#ifdef WOLFSSL_CALLBACKS + 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 */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/internal.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,2937 @@ +/* internal.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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> +#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 +#ifdef HAVE_ECC + #include <wolfssl/wolfcrypt/ecc.h> +#endif +#ifndef NO_SHA256 + #include <wolfssl/wolfcrypt/sha256.h> +#endif +#ifdef HAVE_OCSP + #include <wolfssl/ocsp.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 + +#include <wolfssl/wolfcrypt/hash.h> + +#ifdef WOLFSSL_CALLBACKS + #include <wolfssl/callbacks.h> + #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_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 */ +#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 + + +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + +#ifdef _MSC_VER + /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ + #pragma warning(disable: 4996) +#endif + +#ifdef NO_AES + #if !defined (ALIGN16) + #define ALIGN16 + #endif +#endif + +#ifdef NO_SHA + #define SHA_DIGEST_SIZE 20 +#endif + +#ifdef NO_SHA256 + #define SHA256_DIGEST_SIZE 32 +#endif + +#ifdef NO_MD5 + #define MD5_DIGEST_SIZE 16 +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef USE_WINDOWS_API + typedef unsigned int SOCKET_T; +#else + typedef int SOCKET_T; +#endif + + +typedef byte word24[3]; + +/* 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) + #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + #endif + #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA) + #define BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + #endif + #endif + #if defined(WOLFSSL_STATIC_RSA) + #if !defined (NO_SHA256) + #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + #endif + #if defined (HAVE_AESGCM) + #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + #if defined (WOLFSSL_SHA384) + #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + #endif + #endif + #if defined (HAVE_AESCCM) + #define BUILD_TLS_RSA_WITH_AES_128_CCM_8 + #define BUILD_TLS_RSA_WITH_AES_256_CCM_8 + #endif + #if defined(HAVE_BLAKE2) + #define BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 + #define BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 + #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) + #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + #endif + #ifndef NO_SHA256 + #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + #ifdef HAVE_AESGCM + #define BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 + #endif + #ifdef HAVE_AESCCM + #define BUILD_TLS_PSK_WITH_AES_128_CCM_8 + #define BUILD_TLS_PSK_WITH_AES_256_CCM_8 + #define BUILD_TLS_PSK_WITH_AES_128_CCM + #define BUILD_TLS_PSK_WITH_AES_256_CCM + #endif + #endif + #ifdef WOLFSSL_SHA384 + #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) + #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + #endif + #if !defined(NO_SHA256) + #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + #endif + #endif + + #if defined(HAVE_ANON) && !defined(NO_TLS) && !defined(NO_DH) && \ + !defined(NO_AES) && !defined(NO_SHA) + #define BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + #endif + + #if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS) + #ifndef NO_SHA256 + #ifndef NO_AES + #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 + #ifndef NO_AES + #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(NO_TLS) + #if !defined(NO_AES) + #if !defined(NO_SHA) + #if !defined(NO_RSA) + #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + #if defined(WOLFSSL_STATIC_DH) + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + #endif + #endif + + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + + #if defined(WOLFSSL_STATIC_DH) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + #endif + #endif /* NO_SHA */ + #ifndef NO_SHA256 + #if !defined(NO_RSA) + #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + #if defined(WOLFSSL_STATIC_DH) + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + #endif + #endif + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + #if defined(WOLFSSL_STATIC_DH) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + #endif + #endif + + #ifdef WOLFSSL_SHA384 + #if !defined(NO_RSA) + #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + #if defined(WOLFSSL_STATIC_DH) + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + #endif + #endif + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + #if defined(WOLFSSL_STATIC_DH) + #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) + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + #endif + #if defined(WOLFSSL_SHA384) + #if defined(WOLFSSL_STATIC_DH) + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + #endif + #endif + #endif + + #if defined(WOLFSSL_STATIC_DH) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + #endif + + #if defined(WOLFSSL_SHA384) + #if defined(WOLFSSL_STATIC_DH) + #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) + #define BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + #endif + #endif + + #define BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + #if defined(WOLFSSL_STATIC_DH) + #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) + #define BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + #endif + #endif + + #define BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + #if defined(WOLFSSL_STATIC_DH) + #define BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + #endif + #endif /* NO_SHA */ + #endif + #if defined(HAVE_NULL_CIPHER) + #if !defined(NO_SHA) + #define BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + #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) + #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) + #ifdef HAVE_ECC + #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + #ifndef NO_RSA + #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + #endif + #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 + #ifdef HAVE_ECC + #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) + + #ifndef NO_SHA256 + #define BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + #endif + + #ifdef WOLFSSL_SHA384 + #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 + #ifdef HAVE_AESGCM + #define BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + #endif + #ifdef HAVE_AESCCM + #define BUILD_TLS_DHE_PSK_WITH_AES_128_CCM + #define BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + #endif + #endif + #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) + #define BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + #endif +#endif + +#if defined(HAVE_ECC) && !defined(NO_TLS) && !defined(NO_AES) + #ifdef HAVE_AESGCM + #ifndef NO_SHA256 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + #ifndef NO_RSA + #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + #endif + #endif + #ifdef WOLFSSL_SHA384 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + #ifndef NO_RSA + #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + #endif + #endif + #endif + #if defined(HAVE_AESCCM) && !defined(NO_SHA256) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + #endif +#endif + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) + #ifdef HAVE_ECC + #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + #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(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) + #define BUILD_AESGCM +#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 + +#ifdef NO_AES + #define AES_BLOCK_SIZE 16 +#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(HAVE_AESCCM) || \ + (defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) + + #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_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, + + /* 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_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_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, + + /* 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 + + +enum Misc { + ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ + QSH_BYTE = 0xD0, /* Quantum-safe Handshake cipher suite */ + CHACHA_BYTE = 0xCC, /* ChaCha first 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 */ + 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 */ + SECRET_LEN = 48, /* pre RSA and all master */ + ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */ + SIZEOF_SENDER = 4, /* clnt or srvr */ + FINISHED_SZ = 36, /* MD5_DIGEST_SIZE + SHA_DIGEST_SIZE */ + MAX_RECORD_SIZE = 16384, /* 2^14, max size by standard */ + MAX_MSG_EXTRA = 38 + 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 = 1500, /* max expected MTU */ + MAX_UDP_SIZE = 8192 - 100, /* was MAX_MTU - 100 */ + MAX_DH_SZ = 1036, /* 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 */ + COMPRESS_DUMMY_SIZE = 64, /* compression dummy round size */ + COMPRESS_CONSTANT = 13, /* compression calc constant */ + COMPRESS_UPPER = 55, /* compression calc numerator */ + COMPRESS_LOWER = 64, /* compression calc denominator */ + + PEM_LINE_LEN = 80, /* PEM line max + fudge */ + LENGTH_SZ = 2, /* length field for HMAC, data only */ + VERSION_SZ = 2, /* length of proctocol version */ + SEQ_SZ = 8, /* 64 bit sequence number */ + BYTE3_LEN = 3, /* up to 24 bit byte lengths */ + ALERT_SIZE = 2, /* level + description */ + VERIFY_HEADER = 2, /* always use 2 bytes */ + EXT_ID_SZ = 2, /* always use 2 bytes */ + MAX_DH_SIZE = 513, /* 4096 bit plus possible leading 0 */ + SESSION_HINT_SZ = 4, /* session timeout hint */ + + 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 */ + COMP_LEN = 1, /* compression length */ + CURVE_LEN = 2, /* ecc named curve 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_TYPE_SZ = 2, /* length of a hello extension type */ + HELLO_EXT_SZ = 8, /* total length of the lazy hello extensions */ + HELLO_EXT_LEN = 6, /* length of the lazy hello extensions */ + HELLO_EXT_SIGALGO_SZ = 2, /* length of signature algo extension */ + HELLO_EXT_SIGALGO_MAX = 32, /* number of items in the signature algo 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 = 5, /* buffers to hold in the retry pool */ + + FINISHED_LABEL_SZ = 15, /* TLS finished label size */ + TLS_FINISHED_SZ = 12, /* TLS has a shorter size */ + 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 */ + MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */ + SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */ + + RC4_KEY_SIZE = 16, /* always 128bit */ + DES_KEY_SIZE = 8, /* des */ + DES3_KEY_SIZE = 24, /* 3 des ede */ + DES_IV_SIZE = DES_BLOCK_SIZE, + AES_256_KEY_SIZE = 32, /* for 256 bit */ + AES_192_KEY_SIZE = 24, /* for 192 bit */ + AES_IV_SIZE = 16, /* always block size */ + AES_128_KEY_SIZE = 16, /* for 128 bit */ + + 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 */ + 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 = 8, /* 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 */ + + 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 */ + +#ifdef HAVE_QSH + /* qsh handshake sends 600+ size keys over hello extensions */ + MAX_HELLO_SZ = 2048, /* max client or server hello */ +#else + MAX_HELLO_SZ = 128, /* max client or server hello */ +#endif + 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 */ + MAX_PSK_KEY_LEN = 64, /* max psk key supported */ + + MAX_WOLFSSL_FILE_SIZE = 1024 * 1024 * 4, /* 4 mb file size alloc limit */ + +#if defined(FORTRESS) || defined (HAVE_STUNNEL) + MAX_EX_DATA = 3, /* allow for three 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_FILENAME_SZ = 256, /* max file name length */ + FILE_BUFFER_SIZE = 1024, /* default static file buffer size for input, + will use dynamic buffer if not big enough */ + + 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_CAVIUM_DEVICE = -2, /* invalid cavium device id */ + + NO_COPY = 0, /* should we copy static buffer for write */ + COPY = 1 /* should we copy static buffer for write */ +}; + + +/* Set max implicit IV size for AEAD cipher suites */ +#ifdef HAVE_CHACHA + #define AEAD_MAX_IMP_SZ 12 +#else + #define AEAD_MAX_IMP_SZ 4 +#endif + +/* 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 + + +#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) + + +#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_COMPLETE, + SERVER_CERT_COMPLETE, + SERVER_KEYEXCHANGE_COMPLETE, + SERVER_HELLODONE_COMPLETE, + SERVER_FINISHED_COMPLETE, + + CLIENT_HELLO_COMPLETE, + CLIENT_KEYEXCHANGE_COMPLETE, + CLIENT_FINISHED_COMPLETE, + + HANDSHAKE_DONE +}; + + +#if defined(__GNUC__) + #define WOLFSSL_PACK __attribute__ ((packed)) +#else + #define WOLFSSL_PACK +#endif + +/* 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); + +#ifdef WOLFSSL_DTLS + WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void); + WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void); +#endif + + +enum BIO_TYPE { + BIO_BUFFER = 1, + BIO_SOCKET = 2, + BIO_SSL = 3, + BIO_MEMORY = 4 +}; + + +/* wolfSSL BIO_METHOD type */ +struct WOLFSSL_BIO_METHOD { + byte type; /* method type */ +}; + + +/* wolfSSL BIO type */ +struct WOLFSSL_BIO { + byte type; /* method type */ + byte close; /* close flag */ + byte eof; /* eof flag */ + WOLFSSL* ssl; /* possible associated ssl */ + byte* mem; /* memory buffer */ + int memLen; /* memory buffer length */ + int fd; /* possible file descriptor */ + WOLFSSL_BIO* prev; /* previous in chain */ + WOLFSSL_BIO* next; /* next in chain */ +}; + + +/* wolfSSL method type */ +struct WOLFSSL_METHOD { + ProtocolVersion version; + byte side; /* connection side, server or client */ + byte downgrade; /* whether to downgrade version, default no */ +}; + + +/* 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); + + +/* wolfSSL buffer type */ +typedef struct buffer { + byte* buffer; + word32 length; +} buffer; + +#ifndef NO_CERTS + /* wolfSSL DER buffer */ + typedef struct DerBuffer { + byte* buffer; + void* heap; + word32 length; + int type; /* enum CertType */ + int dynType; /* DYNAMIC_TYPE_* */ + } DerBuffer; +#endif /* !NO_CERTS */ + + +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 */ +typedef struct Suites { + word16 suiteSz; /* suite length in bytes */ + word16 hashSigAlgoSz; /* SigAlgo extension length in bytes */ + byte suites[WOLFSSL_MAX_SUITE_SZ]; + byte hashSigAlgo[HELLO_EXT_SIGALGO_MAX]; /* sig/algo to offer */ + byte setSuites; /* user set suites from default */ + byte hashAlgo; /* selected hash algorithm */ + byte sigAlgo; /* selected sig algorithm */ +} Suites; + + +WOLFSSL_LOCAL +void InitSuites(Suites*, ProtocolVersion, word16, word16, word16, word16, + word16, word16, word16, int); +WOLFSSL_LOCAL +int SetCipherList(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 */ + + +#ifdef HAVE_NETX + WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); + WOLFSSL_LOCAL int NetX_Send(WOLFSSL *ssl, char *buf, int sz, void *ctx); +#endif /* HAVE_NETX */ + + +/* wolfSSL Cipher type just points back to SSL */ +struct WOLFSSL_CIPHER { + WOLFSSL* ssl; +}; + + +typedef struct OcspEntry OcspEntry; + +#ifdef NO_SHA + #define OCSP_DIGEST_SIZE SHA256_DIGEST_SIZE +#else + #define OCSP_DIGEST_SIZE 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 */ +}; + +#ifndef MAX_DATE_SIZE +#define MAX_DATE_SIZE 32 +#endif + +typedef struct CRL_Entry CRL_Entry; + +#ifdef NO_SHA + #define CRL_DIGEST_SIZE SHA256_DIGEST_SIZE +#else + #define CRL_DIGEST_SIZE 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 */ +}; + + +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 */ +}; + + +#ifndef HAVE_CRL + typedef struct WOLFSSL_CRL WOLFSSL_CRL; +#endif + +#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 */ + 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 +}; + + +#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_SEVER) && (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 ? */ +}; + +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 fd; +} WOLFSSL_DTLS_CTX; + + +#ifdef WOLFSSL_DTLS + + #ifdef WORD64_AVAILABLE + typedef word64 DtlsSeq; + #else + typedef word32 DtlsSeq; + #endif + #define DTLS_SEQ_BITS (sizeof(DtlsSeq) * CHAR_BIT) + + typedef struct DtlsState { + DtlsSeq window; /* Sliding window for current epoch */ + word16 nextEpoch; /* Expected epoch in next record */ + word32 nextSeq; /* Expected sequence in next record */ + + word16 curEpoch; /* Received epoch in current record */ + word32 curSeq; /* Received sequence in current record */ + + DtlsSeq prevWindow; /* Sliding window for old epoch */ + word32 prevSeq; /* Next sequence in allowed old epoch */ + } DtlsState; + +#endif /* WOLFSSL_DTLS */ + + +#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */ + +/* keys and secrets */ +typedef struct Keys { + byte client_write_MAC_secret[MAX_DIGEST_SIZE]; /* max sizes */ + byte server_write_MAC_secret[MAX_DIGEST_SIZE]; + byte client_write_key[AES_256_KEY_SIZE]; /* max sizes */ + byte server_write_key[AES_256_KEY_SIZE]; + byte client_write_IV[MAX_WRITE_IV_SZ]; /* max sizes */ + byte server_write_IV[MAX_WRITE_IV_SZ]; +#ifdef HAVE_AEAD + 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; + word32 sequence_number; + +#ifdef WOLFSSL_DTLS + DtlsState dtls_state; /* Peer's state */ + word16 dtls_peer_handshake_number; + word16 dtls_expected_peer_handshake_number; + + word32 dtls_sequence_number; /* Current tx sequence */ + word32 dtls_prev_sequence_number; /* Previous epoch's seq number*/ + word16 dtls_epoch; /* Current tx epoch */ + 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 */ +} 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_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, + TLSX_RENEGOTIATION_INFO = 0xff01 +} TLSX_Type; + +typedef struct TLSX { + TLSX_Type type; /* Extension Type */ + void* data; /* Extension Data */ + byte resp; /* IsResponse Flag */ + struct TLSX* next; /* List Behavior */ +} TLSX; + +WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type); +WOLFSSL_LOCAL void TLSX_FreeAll(TLSX* list); +WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest); + +#ifndef NO_WOLFSSL_CLIENT +WOLFSSL_LOCAL word16 TLSX_GetRequestSize(WOLFSSL* ssl); +WOLFSSL_LOCAL word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output); +#endif + +#ifndef NO_WOLFSSL_SERVER +WOLFSSL_LOCAL word16 TLSX_GetResponseSize(WOLFSSL* ssl); +WOLFSSL_LOCAL word16 TLSX_WriteResponse(WOLFSSL* ssl, byte* output); +#endif + +WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest, 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) + +#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 */ +#ifndef NO_WOLFSSL_SERVER + byte options; /* Behavior options */ + byte status; /* Matching result */ +#endif +} SNI; + +WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, + word16 size); + +#ifndef NO_WOLFSSL_SERVER +WOLFSSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type, + byte options); +WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type); +WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, + void** data); +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); + +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); + +#endif /* HAVE_MAX_FRAGMENT */ + +/** Truncated HMAC - RFC 6066 (session 7) */ +#ifdef HAVE_TRUNCATED_HMAC + +WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions); + +#endif /* HAVE_TRUNCATED_HMAC */ + +/** Certificate Status Request - RFC 6066 (session 8) */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +typedef struct { + byte status_type; + byte options; + union { + OcspRequest ocsp; + } request; +} CertificateStatusRequest; + +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, + byte status_type, byte options); +WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert); +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); +WOLFSSL_LOCAL int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer); +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 EllipticCurve { + word16 name; /* CurveNames */ + struct EllipticCurve* next; /* List Behavior */ +} EllipticCurve; + +WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name); + +#ifndef NO_WOLFSSL_SERVER +WOLFSSL_LOCAL int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, + byte second); +#endif + +#endif /* HAVE_SUPPORTED_CURVES */ + +/** Renegotiation Indication - RFC 5746 */ +#ifdef HAVE_SECURE_RENEGOTIATION + +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[SHA_DIGEST_SIZE]; /* peer cert hash */ + Keys tmp_keys; /* can't overwrite real keys yet */ +} SecureRenegotiation; + +WOLFSSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions); + +#endif /* HAVE_SECURE_RENEGOTIATION */ + +/** Session Ticket - RFC 5077 (session 3.2) */ +#ifdef HAVE_SESSION_TICKET + +typedef struct SessionTicket { + word32 lifetime; + byte* data; + word16 size; +} SessionTicket; + +WOLFSSL_LOCAL int TLSX_UseSessionTicket(TLSX** extensions, + SessionTicket* ticket); +WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime, + byte* data, word16 size); +WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket); + +#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); + +/* 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 */ + +/* wolfSSL context type */ +struct WOLFSSL_CTX { + WOLFSSL_METHOD* method; + wolfSSL_Mutex countMutex; /* reference count mutex */ + int refCount; /* reference count */ +#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 */ + DerBuffer* privateKey; + WOLFSSL_CERT_MANAGER* cm; /* our cert manager, ctx owns SSL will use */ +#endif + Suites* suites; /* make dynamic, user may not need/set */ + void* heap; /* for user memory overrides */ + byte verifyPeer; + byte verifyNone; + byte failNoCert; + byte failNoCertxPSK; /* fail if no cert with the exception of PSK*/ + byte sessionCacheOff; + byte sessionCacheFlushOff; + byte sendVerify; /* for client side */ + byte haveRSA; /* RSA available */ + byte haveECC; /* ECC available */ + byte haveDH; /* server DH parms set by user */ + byte haveNTRU; /* server private NTRU key loaded */ + byte haveECDSAsig; /* server cert signed w/ ECDSA */ + byte haveStaticECC; /* static server ECC private key */ + byte partialWrite; /* only one msg per write call */ + byte quietShutdown; /* don't send close notify */ + byte groupMessages; /* group handshake messages before sending */ + byte minDowngrade; /* minimum downgrade version */ +#ifndef NO_DH + word16 minDhKeySz; /* minimum DH key size */ +#endif + CallbackIORecv CBIORecv; + CallbackIOSend CBIOSend; +#ifdef WOLFSSL_DTLS + CallbackGenCookie CBIOCookie; /* gen cookie callback */ +#endif + VerifyCallback verifyCallback; /* cert verification callback */ + word32 timeout; /* session timeout */ +#ifdef HAVE_ECC + word16 eccTempKeySz; /* in octets 20 - 66 */ + word32 pkCurveOID; /* curve Ecc_Sum */ +#endif +#ifndef 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]; +#endif /* NO_PSK */ +#ifdef HAVE_ANON + byte haveAnon; /* User wants to allow Anon suites */ +#endif /* HAVE_ANON */ +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + pem_password_cb passwd_cb; + void* userdata; +#endif /* OPENSSL_EXTRA */ +#ifdef HAVE_STUNNEL + void* ex_data[MAX_EX_DATA]; + CallbackSniRecv sniRecvCb; + void* sniRecvCbArg; +#endif +#ifdef HAVE_OCSP + WOLFSSL_OCSP ocsp; +#endif +#ifdef HAVE_CAVIUM + int devId; /* cavium device id to use */ +#endif +#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_SEVER) + SessionTicketEncCb ticketEncCb; /* enc/dec session ticket Cb */ + void* ticketEncCtx; /* session encrypt context */ + int ticketHint; /* ticket hint in seconds */ + #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 + CallbackEccSign EccSignCb; /* User EccSign Callback handler */ + CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */ + #endif /* HAVE_ECC */ + #ifndef NO_RSA + CallbackRsaSign RsaSignCb; /* User RsaSign Callback handler */ + CallbackRsaVerify RsaVerifyCb; /* User RsaVerify Callback handler */ + CallbackRsaEnc RsaEncCb; /* User Rsa Public Encrypt handler */ + CallbackRsaDec RsaDecCb; /* User Rsa Private Decrypt handler */ + #endif /* NO_RSA */ +#endif /* HAVE_PK_CALLBACKS */ +}; + + +WOLFSSL_LOCAL +int InitSSL_Ctx(WOLFSSL_CTX*, WOLFSSL_METHOD*); +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 */ +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, + rsa_sa_algo, + dsa_sa_algo, + ecc_dsa_sa_algo +}; + + +/* 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; +#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 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 { + #ifndef NO_OLD_TLS + byte md5[MD5_DIGEST_SIZE]; + #endif + byte sha[SHA_DIGEST_SIZE]; + #ifndef NO_SHA256 + byte sha256[SHA256_DIGEST_SIZE]; + #endif + #ifdef WOLFSSL_SHA384 + byte sha384[SHA384_DIGEST_SIZE]; + #endif + #ifdef WOLFSSL_SHA512 + byte sha512[SHA512_DIGEST_SIZE]; + #endif +} Hashes; + + +/* 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 */ +#ifdef SESSION_CERTS + WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ + 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 HAVE_SESSION_TICKET + word16 ticketLen; + byte ticket[SESSION_TICKET_LEN]; +#endif +#ifdef HAVE_STUNNEL + void* ex_data[MAX_EX_DATA]; +#endif +}; + + +WOLFSSL_LOCAL +WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*); +WOLFSSL_LOCAL +int SetSession(WOLFSSL*, WOLFSSL_SESSION*); + +typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, 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_FIRST_REPLY_DONE, + SERVER_HELLO_SENT, + CERT_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 +}; + + +typedef struct Buffers { + bufferStatic inputBuffer; + bufferStatic outputBuffer; + buffer domainName; /* for client check */ + buffer clearOutputBuffer; + 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; +#endif +#ifndef NO_CERTS + DerBuffer* certificate; /* WOLFSSL_CTX owns, unless we own */ + DerBuffer* key; /* WOLFSSL_CTX owns, unless we own */ + DerBuffer* certChain; /* WOLFSSL_CTX owns, unless we own */ + /* chain after self, in DER, with leading size for each cert */ +#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 */ + #ifndef NO_RSA + buffer peerRsaKey; /* we own for Rsa Verify Callbacks */ + #endif /* NO_RSA */ +#endif /* HAVE_PK_CALLBACKS */ +} Buffers; + +typedef struct Options { +#ifndef NO_PSK + wc_psk_client_callback client_psk_cb; + wc_psk_server_callback server_psk_cb; + word16 havePSK:1; /* psk key set by user */ +#endif /* NO_PSK */ + + /* on/off or small bit flags, optimize layout */ + word16 sendVerify:2; /* false = 0, true = 1, sendBlank = 2 */ + word16 sessionCacheOff:1; + word16 sessionCacheFlushOff:1; + 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 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 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 usingNonblock:1; /* are we using nonblocking socket */ + word16 saveArrays:1; /* save array Memory for user get keys + or psk */ +#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 */ +#endif +#ifdef WOLFSSL_DTLS + word16 dtlsHsRetain:1; /* DTLS retaining HS data */ +#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 */ +#ifndef NO_DH + word16 minDhKeySz; /* minimum DH key size */ + word16 dhKeySz; /* actual DH key size */ +#endif + +} Options; + +typedef struct Arrays { + byte* pendingMsg; /* defrag buffer */ + word32 preMasterSz; /* differs for DH, actual size */ + word32 pendingMsgSz; /* defrag buffer size */ + word32 pendingMsgOffset; /* current offset into defrag buffer */ +#ifndef NO_PSK + word32 psk_keySz; /* actual size */ + char client_identity[MAX_PSK_ID_LEN]; + char server_hint[MAX_PSK_ID_LEN]; + byte psk_key[MAX_PSK_KEY_LEN]; +#endif + byte clientRandom[RAN_LEN]; + byte serverRandom[RAN_LEN]; + byte sessionID[ID_LEN]; + byte sessionIDSz; + byte preMasterSecret[ENCRYPT_LEN]; + 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_X509_NAME { + char *name; + char staticName[ASN_NAME_MAX]; + int dynamicName; + int sz; +#ifdef OPENSSL_EXTRA + DecodedName fullName; +#endif /* OPENSSL_EXTRA */ +}; + +#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; + WOLFSSL_X509_NAME issuer; + WOLFSSL_X509_NAME subject; + int serialSz; + byte serial[EXTERNAL_SERIAL_SIZE]; + char subjectCN[ASN_NAME_MAX]; /* common name short cut */ +#ifdef WOLFSSL_SEP + int deviceTypeSz; + byte deviceType[EXTERNAL_SERIAL_SIZE]; + int hwTypeSz; + byte hwType[EXTERNAL_SERIAL_SIZE]; + int hwSerialNumSz; + byte hwSerialNum[EXTERNAL_SERIAL_SIZE]; + #ifdef OPENSSL_EXTRA + byte certPolicySet; + byte certPolicyCrit; + #endif /* OPENSSL_EXTRA */ +#endif + int notBeforeSz; + byte notBefore[MAX_DATE_SZ]; + int notAfterSz; + byte notAfter[MAX_DATE_SZ]; + int sigOID; + buffer sig; + int pubKeyOID; + buffer pubKey; + #ifdef HAVE_ECC + word32 pkCurveOID; + #endif /* HAVE_ECC */ + #ifndef NO_CERTS + DerBuffer* derCert; /* may need */ + #endif + DNS_entry* altNames; /* alt names list */ + DNS_entry* altNamesNext; /* hint for retrieval */ + byte dynamicMemory; /* dynamic memory flag */ + byte isCa; +#ifdef OPENSSL_EXTRA + word32 pathLength; + word16 keyUsage; + byte basicConstSet; + byte basicConstCrit; + byte basicConstPlSet; + byte subjAltNameSet; + byte subjAltNameCrit; + byte authKeyIdSet; + byte authKeyIdCrit; + byte* authKeyId; + word32 authKeyIdSz; + byte subjKeyIdSet; + byte subjKeyIdCrit; + byte* subjKeyId; + word32 subjKeyIdSz; + byte keyUsageSet; + byte keyUsageCrit; +#endif /* OPENSSL_EXTRA */ +}; + + +/* 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 epoch[2]; /* increment on cipher state change */ + byte sequence_number[6]; /* per record */ + byte length[2]; +} DtlsRecordLayerHeader; + + +typedef struct DtlsPool { + buffer buf[DTLS_POOL_SZ]; + word16 epoch[DTLS_POOL_SZ]; + int used; +} DtlsPool; + + +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:1; + word16 got_server_hello:1; + word16 got_hello_verify_request:1; + word16 got_session_ticket: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_change_cipher:1; +} MsgsReceived; + + +/* Handshake hashes */ +typedef struct HS_Hashes { + Hashes verifyHashes; + Hashes certHashes; /* for cert verify */ +#ifndef NO_OLD_TLS +#ifndef NO_SHA + Sha hashSha; /* sha hash of handshake msgs */ +#endif +#ifndef NO_MD5 + Md5 hashMd5; /* md5 hash of handshake msgs */ +#endif +#endif /* NO_OLD_TLS */ +#ifndef NO_SHA256 + Sha256 hashSha256; /* sha256 hash of handshake msgs */ +#endif +#ifdef WOLFSSL_SHA384 + Sha384 hashSha384; /* sha384 hash of handshake msgs */ +#endif +#ifdef WOLFSSL_SHA512 + Sha512 hashSha512; /* sha512 hash of handshake msgs */ +#endif +} HS_Hashes; + + +/* 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 */ +#ifndef NO_HANDSHAKE_DONE_CB + HandShakeDoneCb hsDoneCb; /* notify user handshake done */ + void* hsDoneCtx; /* user handshake cb context */ +#endif + WOLFSSL_CIPHER cipher; + hmacfp hmac; + Ciphers encrypt; + Ciphers decrypt; + Buffers buffers; + WOLFSSL_SESSION session; + 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; + 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 + WOLFSSL_BIO* biord; /* socket bio read to free/close */ + WOLFSSL_BIO* biowr; /* socket bio write to free/close */ +#endif +#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 HAVE_NTRU + word16 peerNtruKeyLen; + byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ]; + byte peerNtruKeyPresent; +#endif +#ifdef HAVE_ECC + ecc_key* peerEccKey; /* peer's ECDHE key */ + ecc_key* peerEccDsaKey; /* peer's ECDSA key */ + ecc_key* eccTempKey; /* private ECDHE key */ + word32 pkCurveOID; /* curve Ecc_Sum */ + word16 eccTempKeySz; /* in octets 20 - 66 */ + byte peerEccKeyPresent; + byte peerEccDsaKeyPresent; + byte eccTempKeyPresent; +#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 */ + DtlsPool* dtls_pool; + DtlsMsg* dtls_msg_list; + void* IOCB_CookieCtx; /* gen cookie ctx */ + word32 dtls_expected_rx; +#endif +#ifdef WOLFSSL_CALLBACKS + HandShakeInfo handShakeInfo; /* info saved during handshake */ + TimeoutInfo timeoutInfo; /* info saved during handshake */ + 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 +#ifdef KEEP_PEER_CERT + WOLFSSL_X509 peerCert; /* X509 peer cert */ +#endif +#if defined(FORTRESS) || defined(HAVE_STUNNEL) + void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ +#endif +#ifdef HAVE_CAVIUM + int devId; /* cavium device id to use */ +#endif +#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 + #ifdef HAVE_SECURE_RENEGOTIATION + SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */ + #endif /* user turned on */ + #ifdef HAVE_ALPN + char* alpn_client_list; /* keep the client's list */ + #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_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* EccSignCtx; /* Ecc Sign Callback Context */ + void* EccVerifyCtx; /* Ecc Verify Callback Context */ + #endif /* HAVE_ECC */ + #ifndef NO_RSA + void* RsaSignCtx; /* Rsa Sign Callback Context */ + void* RsaVerifyCtx; /* Rsa Verify Callback Context */ + 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 */ +}; + + +WOLFSSL_LOCAL +int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*); +WOLFSSL_LOCAL +int InitSSL(WOLFSSL*, WOLFSSL_CTX*); +WOLFSSL_LOCAL +void FreeSSL(WOLFSSL*); +WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */ + + +enum { + IV_SZ = 32, /* max iv sz */ + NAME_SZ = 80 /* max one line */ +}; + + +typedef struct EncryptedInfo { + char name[NAME_SZ]; /* encryption name */ + byte iv[IV_SZ]; /* encrypted IV */ + word32 ivSz; /* encrypted IV size */ + long consumed; /* tracks PEM bytes consumed */ + byte set; /* if encryption set */ + WOLFSSL_CTX* ctx; /* CTX owner */ +} EncryptedInfo; + + +#ifndef NO_CERTS + + WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap); + WOLFSSL_LOCAL void FreeDer(DerBuffer** der); + + WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, + int* eccKey); + + WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, + int type, WOLFSSL* ssl, int userChain, + WOLFSSL_CRL* crl); +#endif + + +#ifdef WOLFSSL_CALLBACKS + WOLFSSL_LOCAL + void InitHandShakeInfo(HandShakeInfo*); + WOLFSSL_LOCAL + void FinishHandShakeInfo(HandShakeInfo*, const WOLFSSL*); + WOLFSSL_LOCAL + void AddPacketName(const char*, HandShakeInfo*); + + WOLFSSL_LOCAL + void InitTimeoutInfo(TimeoutInfo*); + WOLFSSL_LOCAL + void FreeTimeoutInfo(TimeoutInfo*, void*); + WOLFSSL_LOCAL + void AddPacketInfo(const char*, TimeoutInfo*, const byte*, int, void*); + 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, + 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, + change_cipher_hs = 55, /* simulate unique handshake type for sanity + checks. record layer change_cipher + conflicts with handshake finished */ + no_shake = 255 /* used to initialize the DtlsMsg record */ +}; + + +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); +WOLFSSL_LOCAL int SendCertificate(WOLFSSL*); +WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*); +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); + +WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl); +WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl); + +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); +#ifndef NO_CERTS + #ifndef NO_RSA + WOLFSSL_LOCAL int VerifyRsaSign(const byte* sig, word32 sigSz, + const byte* plain, word32 plainSz, + RsaKey* key); + #endif + #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 +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 content, int verify); +#endif + +#ifndef NO_WOLFSSL_CLIENT + WOLFSSL_LOCAL int SendClientHello(WOLFSSL*); + 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 int DtlsPoolInit(WOLFSSL*); + WOLFSSL_LOCAL int DtlsPoolSave(WOLFSSL*, const byte*, int); + WOLFSSL_LOCAL int DtlsPoolTimeout(WOLFSSL*); + WOLFSSL_LOCAL int DtlsPoolSend(WOLFSSL*); + WOLFSSL_LOCAL void DtlsPoolReset(WOLFSSL*); + WOLFSSL_LOCAL void DtlsPoolDelete(WOLFSSL*); + + 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 DtlsMsg* DtlsMsgStore(DtlsMsg*, word32, const byte*, word32, + byte, word32, word32, void*); + WOLFSSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*); +#endif /* WOLFSSL_DTLS */ + +#ifndef NO_TLS + + +#endif /* NO_TLS */ + + +WOLFSSL_LOCAL word32 LowResTimer(void); + +WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME*, int); +WOLFSSL_LOCAL void FreeX509Name(WOLFSSL_X509_NAME* name); +WOLFSSL_LOCAL void InitX509(WOLFSSL_X509*, int); +WOLFSSL_LOCAL void FreeX509(WOLFSSL_X509*); +#ifndef NO_CERTS + WOLFSSL_LOCAL int CopyDecodedToX509(WOLFSSL_X509*, DecodedCert*); +#endif + +/* used by ssl.c and wolfssl_int.c */ +WOLFSSL_LOCAL void c32to24(word32 in, word24 out); + +WOLFSSL_LOCAL const char* const* GetCipherNames(void); +WOLFSSL_LOCAL int GetCipherNamesSize(void); + + +enum encrypt_side { + ENCRYPT_SIDE_ONLY = 1, + DECRYPT_SIDE_ONLY, + ENCRYPT_AND_DECRYPT_SIDE +}; + +WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* wolfSSL_INT_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/ocsp.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,58 @@ +/* ocsp.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +/* wolfSSL OCSP API */ + +#ifndef WOLFSSL_OCSP_H +#define WOLFSSL_OCSP_H + +#ifdef HAVE_OCSP + +#include <wolfssl/ssl.h> +#include <wolfssl/wolfcrypt/asn.h> + +#ifdef __cplusplus + extern "C" { +#endif + +struct buffer; +typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; + +WOLFSSL_LOCAL int InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*); +WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic); + +WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*, + struct buffer* responseBuffer); +WOLFSSL_LOCAL int CheckOcspRequest(WOLFSSL_OCSP* ocsp, + OcspRequest* ocspRequest, struct buffer* responseBuffer); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* HAVE_OCSP */ +#endif /* WOLFSSL_OCSP_H */ + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/options.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,41 @@ +/* options.h.in + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* default blank options for autoconf */ + +#ifndef WOLFSSL_OPTIONS_H +#define WOLFSSL_OPTIONS_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* WOLFSSL_OPTIONS_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/sniffer.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,98 @@ +/* sniffer.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_SNIFFER_H +#define WOLFSSL_SNIFFER_H + +#include <wolfssl/wolfcrypt/settings.h> + +#ifdef _WIN32 + #ifdef SSL_SNIFFER_EXPORTS + #define SSL_SNIFFER_API __declspec(dllexport) + #else + #define SSL_SNIFFER_API __declspec(dllimport) + #endif +#else + #define SSL_SNIFFER_API +#endif /* _WIN32 */ + + +#ifdef __cplusplus + extern "C" { +#endif + +/* @param typeK: (formerly keyType) was shadowing a global declaration in + * wolfssl/wolfcrypt/asn.h line 175 + */ +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetPrivateKey(const char* address, int port, + const char* keyFile, int typeK, + const char* password, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetNamedPrivateKey(const char* name, + const char* address, int port, + const char* keyFile, int typeK, + const char* password, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacket(const unsigned char* packet, int length, + unsigned char** data, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_FreeDecodeBuffer(unsigned char** data, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_Trace(const char* traceFile, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_EnableRecovery(int onOff, int maxMemory, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_GetSessionStats(unsigned int* active, + unsigned int* total, + unsigned int* peak, + unsigned int* maxSessions, + unsigned int* missedData, + unsigned int* reassemblyMemory, + char* error); + +WOLFSSL_API void ssl_InitSniffer(void); + +WOLFSSL_API void ssl_FreeSniffer(void); + + +/* ssl_SetPrivateKey typeKs */ +enum { + FILETYPE_PEM = 1, + FILETYPE_DER = 2, +}; + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* wolfSSL_SNIFFER_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/sniffer_error.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,125 @@ +/* sniffer_error.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_SNIFFER_ERROR_H +#define WOLFSSL_SNIFFER_ERROR_H + +/* need to have errors as #defines since .rc files can't handle enums */ +/* need to start at 1 and go in order for same reason */ + +#define MEMORY_STR 1 +#define NEW_SERVER_STR 2 +#define IP_CHECK_STR 3 +#define SERVER_NOT_REG_STR 4 +#define TCP_CHECK_STR 5 +#define SERVER_PORT_NOT_REG_STR 6 +#define RSA_DECRYPT_STR 7 +#define RSA_DECODE_STR 8 +#define BAD_CIPHER_SPEC_STR 9 +#define SERVER_HELLO_INPUT_STR 10 + +#define BAD_SESSION_RESUME_STR 11 +#define SERVER_DID_RESUMPTION_STR 12 +#define CLIENT_HELLO_INPUT_STR 13 +#define CLIENT_RESUME_TRY_STR 14 +#define HANDSHAKE_INPUT_STR 15 +#define GOT_HELLO_VERIFY_STR 16 +#define GOT_SERVER_HELLO_STR 17 +#define GOT_CERT_REQ_STR 18 +#define GOT_SERVER_KEY_EX_STR 19 +#define GOT_CERT_STR 20 + +#define GOT_SERVER_HELLO_DONE_STR 21 +#define GOT_FINISHED_STR 22 +#define GOT_CLIENT_HELLO_STR 23 +#define GOT_CLIENT_KEY_EX_STR 24 +#define GOT_CERT_VER_STR 25 +#define GOT_UNKNOWN_HANDSHAKE_STR 26 +#define NEW_SESSION_STR 27 +#define BAD_NEW_SSL_STR 28 +#define GOT_PACKET_STR 29 +#define NO_DATA_STR 30 + +#define BAD_SESSION_STR 31 +#define GOT_OLD_CLIENT_HELLO_STR 32 +#define OLD_CLIENT_INPUT_STR 33 +#define OLD_CLIENT_OK_STR 34 +#define BAD_OLD_CLIENT_STR 35 +#define BAD_RECORD_HDR_STR 36 +#define RECORD_INPUT_STR 37 +#define GOT_HANDSHAKE_STR 38 +#define BAD_HANDSHAKE_STR 39 +#define GOT_CHANGE_CIPHER_STR 40 + +#define GOT_APP_DATA_STR 41 +#define BAD_APP_DATA_STR 42 +#define GOT_ALERT_STR 43 +#define ANOTHER_MSG_STR 44 +#define REMOVE_SESSION_STR 45 +#define KEY_FILE_STR 46 +#define BAD_IPVER_STR 47 +#define BAD_PROTO_STR 48 +#define PACKET_HDR_SHORT_STR 49 +#define GOT_UNKNOWN_RECORD_STR 50 + +#define BAD_TRACE_FILE_STR 51 +#define FATAL_ERROR_STR 52 +#define PARTIAL_INPUT_STR 53 +#define BUFFER_ERROR_STR 54 +#define PARTIAL_ADD_STR 55 +#define DUPLICATE_STR 56 +#define OUT_OF_ORDER_STR 57 +#define OVERLAP_DUPLICATE_STR 58 +#define OVERLAP_REASSEMBLY_BEGIN_STR 59 +#define OVERLAP_REASSEMBLY_END_STR 60 + +#define MISSED_CLIENT_HELLO_STR 61 +#define GOT_HELLO_REQUEST_STR 62 +#define GOT_SESSION_TICKET_STR 63 +#define BAD_INPUT_STR 64 +#define BAD_DECRYPT_TYPE 65 +#define BAD_FINISHED_MSG 66 +#define BAD_COMPRESSION_STR 67 +#define BAD_DERIVE_STR 68 +#define ACK_MISSED_STR 69 +#define BAD_DECRYPT 70 + +#define DECRYPT_KEYS_NOT_SETUP 71 +#define CLIENT_HELLO_LATE_KEY_STR 72 +#define GOT_CERT_STATUS_STR 73 +#define RSA_KEY_MISSING_STR 74 +#define NO_SECURE_RENEGOTIATION 75 + +#define BAD_SESSION_STATS 76 +#define REASSEMBLY_MAX_STR 77 +#define DROPPING_LOST_FRAG_STR 78 +#define DROPPING_PARTIAL_RECORD 79 +#define CLEAR_ACK_FAULT 80 + +#define BAD_DECRYPT_SIZE 81 +/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ + + +#endif /* wolfSSL_SNIFFER_ERROR_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/ssl.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1790 @@ +/* ssl.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +/* 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> + +#ifndef NO_FILESYSTEM + #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> /* ERR_printf */ + #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 __cplusplus + extern "C" { +#endif + +typedef struct WOLFSSL WOLFSSL; +typedef struct WOLFSSL_SESSION WOLFSSL_SESSION; +typedef struct WOLFSSL_METHOD WOLFSSL_METHOD; +typedef struct WOLFSSL_CTX WOLFSSL_CTX; + +typedef struct WOLFSSL_X509 WOLFSSL_X509; +typedef struct WOLFSSL_X509_NAME WOLFSSL_X509_NAME; +typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN; + +typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER; +typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; + +/* redeclare guard */ +#define WOLFSSL_TYPES_DEFINED + + +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + +typedef struct WOLFSSL_DSA WOLFSSL_DSA; +typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; +typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +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_X509_CRL WOLFSSL_X509_CRL; +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 + +typedef struct WOLFSSL_EVP_PKEY { + int type; /* openssh dereference */ + int save_type; /* openssh dereference */ + int pkey_sz; + union { + char* ptr; + } pkey; + #ifdef HAVE_ECC + int pkey_curve; + #endif +} WOLFSSL_EVP_PKEY; + +typedef struct WOLFSSL_MD4_CTX { + int buffer[32]; /* big enough to hold, check size in Init */ +} WOLFSSL_MD4_CTX; + + +typedef struct WOLFSSL_COMP_METHOD { + int type; /* stunnel dereference */ +} WOLFSSL_COMP_METHOD; + + +typedef struct WOLFSSL_X509_STORE { + int cache; /* stunnel dereference */ + WOLFSSL_CERT_MANAGER* cm; +} WOLFSSL_X509_STORE; + +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_X509_STORE_CTX { + WOLFSSL_X509_STORE* store; /* Store full of a CA cert chain */ + WOLFSSL_X509* current_cert; /* stunnel dereference */ + 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; /* cert depth for this error */ + int discardSessionCerts; /* so verify callback can flag for discard */ +} WOLFSSL_X509_STORE_CTX; + + +/* Valid Alert types from page 16/17 */ +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, + 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, + unrecognized_name = 112, /**< RFC 6066, section 3 */ + bad_certificate_status_response = 113, /**< RFC 6066, section 8 */ + no_application_protocol = 120 +}; + + +enum AlertLevel { + alert_warning = 1, + alert_fatal = 2 +}; + + +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_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_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); + +#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 + +#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_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 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_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 + +#ifndef WOLFSSL_PEMCERT_TODER_DEFINED + WOLFSSL_API int wolfSSL_PemCertToDer(const char*, unsigned char*, int); + #define WOLFSSL_PEMCERT_TODER_DEFINED +#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_set_fd (WOLFSSL*, int); +WOLFSSL_API char* wolfSSL_get_cipher_list(int priority); +WOLFSSL_API int wolfSSL_get_ciphers(char*, int); +WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL*); +WOLFSSL_API void wolfSSL_set_using_nonblock(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_get_using_nonblock(WOLFSSL*); +WOLFSSL_API int wolfSSL_connect(WOLFSSL*); /* please see note at top of README + if you get an error from connect */ +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*); +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* ssl,WOLFSSL_SESSION* session); +WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* session, long t); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl); +WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX *ctx, long tm); +WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL* ssl, const unsigned char*, + int, int); + +#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*); +typedef int (*pem_password_cb)(char*, int, int, void*); + +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 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_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 */ + +#define STACK_OF(x) x + +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(WOLFSSL_CIPHER*, char*, int); +WOLFSSL_API const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher); +WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); + /* what's ref count */ + +WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509*); +WOLFSSL_API void wolfSSL_OPENSSL_free(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 void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX*); +WOLFSSL_API void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX*, const void*, unsigned long); +WOLFSSL_API void wolfSSL_MD4_Final(unsigned char*, WOLFSSL_MD4_CTX*); + + +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_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,const unsigned char** 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 void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); + +WOLFSSL_API int wolfSSL_add_all_algorithms(void); + +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_add(const void*, int, double); + +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 int wolfSSL_get_ex_new_index(long, void*, void*, void*, 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 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_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 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*, 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_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX*, + int); +WOLFSSL_API void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*); +WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*); +WOLFSSL_API int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*); +WOLFSSL_API int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*); + +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 int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_TIME*); + +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*); + +WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); + +WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, + 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_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 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 char* wolfSSL_alert_type_string_long(int); +WOLFSSL_API char* wolfSSL_alert_desc_string_long(int); +WOLFSSL_API 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 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_sess_get_cache_size(WOLFSSL_CTX*); + +#define WOLFSSL_DEFAULT_CIPHER_LIST "" /* default all */ +#define WOLFSSL_RSA_F4 0x10001L + +enum { + 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_CERTID = 2, + OCSP_REQUEST = 4, + OCSP_RESPONSE = 8, + OCSP_BASICRESP = 16, + + WOLFSSL_OCSP_URL_OVERRIDE = 1, + WOLFSSL_OCSP_NO_NONCE = 2, + WOLFSSL_OCSP_CHECKALL = 4, + + WOLFSSL_CRL_CHECKALL = 1, + + ASN1_GENERALIZEDTIME = 4, + + SSL_OP_MICROSOFT_SESS_ID_BUG = 1, + SSL_OP_NETSCAPE_CHALLENGE_BUG = 2, + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 3, + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 4, + SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 5, + SSL_OP_MSIE_SSLV2_RSA_PADDING = 6, + SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 7, + SSL_OP_TLS_D5_BUG = 8, + SSL_OP_TLS_BLOCK_PADDING_BUG = 9, + SSL_OP_TLS_ROLLBACK_BUG = 10, + SSL_OP_ALL = 11, + SSL_OP_EPHEMERAL_RSA = 12, + SSL_OP_NO_SSLv3 = 13, + SSL_OP_NO_TLSv1 = 14, + SSL_OP_PKCS1_CHECK_1 = 15, + SSL_OP_PKCS1_CHECK_2 = 16, + SSL_OP_NETSCAPE_CA_DN_BUG = 17, + SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 18, + SSL_OP_SINGLE_DH_USE = 19, + SSL_OP_NO_TICKET = 20, + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 21, + SSL_OP_NO_QUERY_MTU = 22, + SSL_OP_COOKIE_EXCHANGE = 23, + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 24, + SSL_OP_SINGLE_ECDH_USE = 25, + SSL_OP_CIPHER_SERVER_PREFERENCE = 26, + + SSL_MAX_SSL_SESSION_ID_LENGTH = 32, + + EVP_R_BAD_DECRYPT = 2, + + SSL_CB_LOOP = 4, + SSL_ST_CONNECT = 5, + SSL_ST_ACCEPT = 6, + SSL_CB_ALERT = 7, + SSL_CB_READ = 8, + SSL_CB_HANDSHAKE_DONE = 9, + + 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_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, + X509_V_OK = 0, + + XN_FLAG_SPC_EQ = (1 << 23), + XN_FLAG_ONELINE = 0, + + CRYPTO_LOCK = 1, + CRYPTO_NUM_LOCKS = 10, + + ASN1_STRFLGS_ESC_MSB = 4 +}; + +/* 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 */ +WOLFSSL_API void wolfSSL_ERR_print_errors_fp(FILE*, int err); +#endif + +enum { /* ssl Constants */ + SSL_ERROR_NONE = 0, /* for most functions */ + SSL_FAILURE = 0, /* for some functions */ + SSL_SUCCESS = 1, + SSL_SHUTDOWN_NOT_DONE = 2, /* call wolfSSL_shutdown again to complete */ + + SSL_ALPN_NOT_FOUND = -9, + SSL_BAD_CERTTYPE = -8, + SSL_BAD_STAT = -7, + SSL_BAD_PATH = -6, + SSL_BAD_FILETYPE = -5, + SSL_BAD_FILE = -4, + SSL_NOT_IMPLEMENTED = -3, + SSL_UNKNOWN = -2, + SSL_FATAL_ERROR = -1, + + SSL_FILETYPE_ASN1 = 2, + SSL_FILETYPE_PEM = 1, + SSL_FILETYPE_DEFAULT = 2, /* ASN1 */ + SSL_FILETYPE_RAW = 3, /* NTRU raw key blob */ + + SSL_VERIFY_NONE = 0, + SSL_VERIFY_PEER = 1, + SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2, + SSL_VERIFY_CLIENT_ONCE = 4, + SSL_VERIFY_FAIL_EXCEPT_PSK = 8, + + SSL_SESS_CACHE_OFF = 30, + SSL_SESS_CACHE_CLIENT = 31, + SSL_SESS_CACHE_SERVER = 32, + SSL_SESS_CACHE_BOTH = 33, + SSL_SESS_CACHE_NO_AUTO_CLEAR = 34, + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35, + + SSL_ERROR_WANT_READ = 2, + SSL_ERROR_WANT_WRITE = 3, + SSL_ERROR_WANT_CONNECT = 7, + SSL_ERROR_WANT_ACCEPT = 8, + SSL_ERROR_SYSCALL = 5, + SSL_ERROR_WANT_X509_LOOKUP = 83, + SSL_ERROR_ZERO_RETURN = 6, + SSL_ERROR_SSL = 85, + + SSL_SENT_SHUTDOWN = 1, + SSL_RECEIVED_SHUTDOWN = 2, + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4, + SSL_OP_NO_SSLv2 = 8, + + SSL_R_SSL_HANDSHAKE_FAILURE = 101, + SSL_R_TLSV1_ALERT_UNKNOWN_CA = 102, + SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103, + SSL_R_SSLV3_ALERT_BAD_CERTIFICATE = 104, + + 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 */ + +enum { /* ERR Constants */ + ERR_TXT_STRING = 1 +}; + +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_bytes(unsigned char* buf, int num); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method(void); +WOLFSSL_API long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long); +#ifndef NO_CERTS + WOLFSSL_API int wolfSSL_CTX_check_private_key(WOLFSSL_CTX*); +#endif /* !NO_CERTS */ + +WOLFSSL_API void wolfSSL_ERR_free_strings(void); +WOLFSSL_API void wolfSSL_ERR_remove_state(unsigned long); +WOLFSSL_API void wolfSSL_EVP_cleanup(void); +WOLFSSL_API int wolfSSL_clear(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 long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long); + +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 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_sk_num(WOLFSSL_X509_REVOKED*); +WOLFSSL_API void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED*, 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); + +/* turn logging on, only if compiled in */ +WOLFSSL_API int wolfSSL_Debugging_ON(void); +/* turn logging off */ +WOLFSSL_API void wolfSSL_Debugging_OFF(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); +/* 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 */ +WOLFSSL_API void wolfSSL_FreeX509(WOLFSSL_X509*); +/* get index cert in PEM */ +WOLFSSL_API int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN*, int idx, + unsigned char* buffer, 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_X509_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len); +#ifndef NO_FILESYSTEM + #ifndef NO_STDIO_FILESYSTEM + WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, FILE* file); + #endif +WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_load_certificate_file(const char* fname, int format); +#endif + +#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); + +#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_GetDhKey_Sz(WOLFSSL*); +#endif /* NO_DH */ + +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) + #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(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(WOLFSSL*, + const unsigned char*, long); + WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL*); +#endif + +WOLFSSL_API int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_set_group_messages(WOLFSSL*); + +/* I/O callbacks */ +typedef int (*CallbackIORecv)(WOLFSSL *ssl, char *buf, int sz, void *ctx); +typedef int (*CallbackIOSend)(WOLFSSL *ssl, char *buf, int sz, void *ctx); + +#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 void wolfSSL_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); +WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); + +WOLFSSL_API void wolfSSL_SetIOReadCtx( WOLFSSL* ssl, void *ctx); +WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *ctx); + +WOLFSSL_API void* wolfSSL_GetIOReadCtx( WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl); + +WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags); +WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); + + +#ifndef WOLFSSL_USER_IO + /* default IO callbacks */ + WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_API int EmbedSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + + #ifdef HAVE_OCSP + WOLFSSL_API int EmbedOcspLookup(void*, const char*, int, unsigned char*, + int, unsigned char**); + WOLFSSL_API void EmbedOcspRespFree(void*, unsigned char*); + #endif + + #ifdef WOLFSSL_DTLS + WOLFSSL_API int EmbedReceiveFrom(WOLFSSL* ssl, char* buf, int sz, void*); + WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf, + int sz, void*); + #endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_USER_IO */ + + +#ifdef HAVE_NETX + WOLFSSL_API void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, + ULONG waitoption); +#endif + +typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX*, CallbackGenCookie); +WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl); +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_USER_CA = 1, /* user added as trusted */ + WOLFSSL_CHAIN_CA = 2 /* added to cache from trusted chain */ +}; + +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_SetVersion(WOLFSSL* ssl, int version); +WOLFSSL_API int wolfSSL_KeyPemToDer(const unsigned char*, int, + unsigned char*, int, const char*); +WOLFSSL_API int wolfSSL_CertPemToDer(const unsigned char*, int, + unsigned char*, int, int); +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) + #ifndef WOLFSSL_PEMPUBKEY_TODER_DEFINED + #ifndef NO_FILESYSTEM + WOLFSSL_API int wolfSSL_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif + WOLFSSL_API int wolfSSL_PubKeyPemToDer(const unsigned char*, int, + unsigned char*, int); + #define WOLFSSL_PEMPUBKEY_TODER_DEFINED + #endif /* WOLFSSL_PEMPUBKEY_TODER_DEFINED */ +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER*/ + +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*); + +/* 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_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, + wolfssl_idea, + 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 */ +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 (*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_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl); + +/* 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); + + +#ifndef NO_CERTS + WOLFSSL_API void wolfSSL_CTX_SetCACb(WOLFSSL_CTX*, CallbackCACache); + + 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); + 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_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_SetCRL_Cb(WOLFSSL*, CbMissingCRL); + 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_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_SetCRL_Cb(WOLFSSL_CTX*, CbMissingCRL); + 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*); +#endif /* !NO_CERTS */ + +/* 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*); + + +/* cavium additions */ +WOLFSSL_API int wolfSSL_UseCavium(WOLFSSL*, int devId); +WOLFSSL_API int wolfSSL_CTX_UseCavium(WOLFSSL_CTX*, int devId); + +/* 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); + +/* 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); +WOLFSSL_API int wolfSSL_SNI_GetFromBuffer( + const unsigned char* clientHello, unsigned int helloSz, + unsigned char type, unsigned char* sni, unsigned int* inOutSz); + +#endif +#endif + +/* 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 +}; + +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); +#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 + +/* Elliptic Curves */ +enum { + WOLFSSL_ECC_SECP160R1 = 0x10, + WOLFSSL_ECC_SECP192R1 = 0x13, + WOLFSSL_ECC_SECP224R1 = 0x15, + WOLFSSL_ECC_SECP256R1 = 0x17, + WOLFSSL_ECC_SECP384R1 = 0x18, + WOLFSSL_ECC_SECP521R1 = 0x19 +}; + +#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 + + +/* 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*, 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 */ + +#ifndef NO_WOLFSSL_SERVER + +#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 */ +}; + +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 + +#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_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 + + +#ifdef OPENSSL_EXTRA /*lighttp compatibility */ +#ifdef HAVE_LIGHTY + +typedef struct WOLFSSL_X509_NAME_ENTRY { + WOLFSSL_ASN1_OBJECT* object; + WOLFSSL_ASN1_STRING* value; + int set; + int size; +} WOLFSSL_X509_NAME_ENTRY; + + +#include <wolfssl/openssl/dh.h> +#include <wolfssl/openssl/asn1.h> + +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_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void); +/* These are to be merged shortly */ +WOLFSSL_API const char * wolf_OBJ_nid2sn(int n); +WOLFSSL_API int wolf_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o); +WOLFSSL_API int wolf_OBJ_sn2nid(const char *sn); +WOLFSSL_API WOLFSSL_X509 *PEM_read_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); +WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl); +WOLFSSL_API void 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(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 int wolfSSL_X509_check_private_key(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*); +WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X509_NAME) *sk ); + +/* end lighttpd*/ +#endif +#endif + +#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) + +WOLFSSL_API char * wolf_OBJ_nid2ln(int n); +WOLFSSL_API int wolf_OBJ_txt2nid(const char *sn); +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 int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x); + + +#endif /* HAVE_STUNNEL || HAVE_LIGHTY */ + + +#ifdef HAVE_STUNNEL + +#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 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 STACK_OF(WOLFSSL_X509_NAME) *s); + +WOLFSSL_API int wolfSSL_sk_X509_num(const 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(STACK_OF(WOLFSSL_X509_NAME)*, int); + +WOLFSSL_API void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)*, int); + +WOLFSSL_API STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*); + +WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); + +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 void wolfSSL_CTX_set_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*); + +WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long); + +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 WOLFSSL_X509* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX*, + WOLFSSL_X509_NAME*); + +WOLFSSL_API void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)); +#endif /* HAVE_STUNNEL */ + +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) + +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 __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFSSL_SSL_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/test.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1911 @@ +/* test.h */ + +#ifndef wolfSSL_TEST_H +#define wolfSSL_TEST_H + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <ctype.h> +#include <wolfssl/wolfcrypt/types.h> +#include <wolfssl/wolfcrypt/error-crypt.h> +#include <wolfssl/wolfcrypt/random.h> +#include <wolfssl/mem_track.h> + +#ifdef ATOMIC_USER + #include <wolfssl/wolfcrypt/aes.h> + #include <wolfssl/wolfcrypt/arc4.h> + #include <wolfssl/wolfcrypt/hmac.h> +#endif +#ifdef HAVE_PK_CALLBACKS + #include <wolfssl/wolfcrypt/asn.h> + #ifdef HAVE_ECC + #include <wolfssl/wolfcrypt/ecc.h> + #endif /* HAVE_ECC */ +#endif /*HAVE_PK_CALLBACKS */ + +#ifdef USE_WINDOWS_API + #include <winsock2.h> + #include <process.h> + #ifdef TEST_IPV6 /* don't require newer SDK for IPV4 */ + #include <ws2tcpip.h> + #include <wspiapi.h> + #endif + #define SOCKET_T SOCKET + #define SNPRINTF _snprintf +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #include <string.h> + #include "rl_net.h" + #define SOCKET_T int + typedef int socklen_t ; + static unsigned long inet_addr(const char *cp) + { + unsigned int a[4] ; unsigned long ret ; + sscanf(cp, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) ; + ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; + return(ret) ; + } + #if defined(HAVE_KEIL_RTX) + #define sleep(t) os_dly_wait(t/1000+1) ; + #elif defined (WOLFSSL_CMSIS_RTOS) + #define sleep(t) osDelay(t/1000+1) ; + #endif + + static int wolfssl_tcp_select(int sd, int timeout) + { return 0 ; } + #define tcp_select(sd,t) wolfssl_tcp_select(sd, t) /* avoid conflicting Keil TCP tcp_select */ +#elif defined(WOLFSSL_TIRTOS) + #include <string.h> + #include <netdb.h> + #include <sys/types.h> + #include <arpa/inet.h> + #include <sys/socket.h> + #include <ti/sysbios/knl/Task.h> + struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ + }; + #define SOCKET_T int +#elif defined(WOLFSSL_VXWORKS) + #include <hostLib.h> + #include <sockLib.h> + #include <arpa/inet.h> + #include <string.h> + #include <selectLib.h> + #include <sys/types.h> + #include <netinet/in.h> + #include <fcntl.h> + #include <sys/time.h> + #include <netdb.h> + #include <pthread.h> + #define SOCKET_T int +#else + #include <string.h> + #include <sys/types.h> +#ifndef WOLFSSL_LEANPSK + #include <unistd.h> + #include <netdb.h> + #include <netinet/in.h> + #include <netinet/tcp.h> + #include <arpa/inet.h> + #include <sys/ioctl.h> + #include <sys/time.h> + #include <sys/socket.h> + #include <pthread.h> + #include <fcntl.h> + #ifdef TEST_IPV6 + #include <netdb.h> + #endif +#endif + #define SOCKET_T int + #ifndef SO_NOSIGPIPE + #include <signal.h> /* ignore SIGPIPE */ + #endif + #define SNPRINTF snprintf +#endif /* USE_WINDOWS_API */ + +#ifdef HAVE_CAVIUM + #include "cavium_sysdep.h" + #include "cavium_common.h" + #include "cavium_ioctl.h" +#endif + +#ifdef _MSC_VER + /* disable conversion warning */ + /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ + #pragma warning(disable:4244 4996) +#endif + +/* Buffer for benchmark tests */ +#ifndef TEST_BUFFER_SIZE +#define TEST_BUFFER_SIZE 16384 +#endif + +#ifndef WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MIN + static INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } +#endif /* WOLFSSL_HAVE_MIN */ + +/* Socket Handling */ +#ifndef WOLFSSL_SOCKET_INVALID +#ifdef USE_WINDOWS_API + #define WOLFSSL_SOCKET_INVALID ((SOCKET_T)INVALID_SOCKET) +#elif defined(WOLFSSL_TIRTOS) + #define WOLFSSL_SOCKET_INVALID ((SOCKET_T)-1) +#else + #define WOLFSSL_SOCKET_INVALID (SOCKET_T)(0) +#endif +#endif /* WOLFSSL_SOCKET_INVALID */ + +#ifndef WOLFSSL_SOCKET_IS_INVALID +#if defined(USE_WINDOWS_API) || defined(WOLFSSL_TIRTOS) + #define WOLFSSL_SOCKET_IS_INVALID(s) ((SOCKET_T)(s) == WOLFSSL_SOCKET_INVALID) +#else + #define WOLFSSL_SOCKET_IS_INVALID(s) ((SOCKET_T)(s) < WOLFSSL_SOCKET_INVALID) +#endif +#endif /* WOLFSSL_SOCKET_IS_INVALID */ + +#if defined(__MACH__) || defined(USE_WINDOWS_API) + #ifndef _SOCKLEN_T + typedef int socklen_t; + #endif +#endif + + +/* HPUX doesn't use socklent_t for third parameter to accept, unless + _XOPEN_SOURCE_EXTENDED is defined */ +#if !defined(__hpux__) && !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM)\ + && !defined(WOLFSSL_ROWLEY_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) + typedef socklen_t* ACCEPT_THIRD_T; +#else + #if defined _XOPEN_SOURCE_EXTENDED + typedef socklen_t* ACCEPT_THIRD_T; + #else + typedef int* ACCEPT_THIRD_T; + #endif +#endif + + +#ifdef USE_WINDOWS_API + #define CloseSocket(s) closesocket(s) + #define StartTCP() { WSADATA wsd; WSAStartup(0x0002, &wsd); } +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #define CloseSocket(s) closesocket(s) + #define StartTCP() +#else + #define CloseSocket(s) close(s) + #define StartTCP() +#endif + + +#ifdef SINGLE_THREADED + typedef unsigned int THREAD_RETURN; + typedef void* THREAD_TYPE; + #define WOLFSSL_THREAD +#else + #if defined(_POSIX_THREADS) && !defined(__MINGW32__) + typedef void* THREAD_RETURN; + typedef pthread_t THREAD_TYPE; + #define WOLFSSL_THREAD + #define INFINITE -1 + #define WAIT_OBJECT_0 0L + #elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) + typedef unsigned int THREAD_RETURN; + typedef int THREAD_TYPE; + #define WOLFSSL_THREAD + #elif defined(WOLFSSL_TIRTOS) + typedef void THREAD_RETURN; + typedef Task_Handle THREAD_TYPE; + #define WOLFSSL_THREAD + #else + typedef unsigned int THREAD_RETURN; + typedef intptr_t THREAD_TYPE; + #define WOLFSSL_THREAD __stdcall + #endif +#endif + + +#ifdef TEST_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN_T; + #define AF_INET_V AF_INET6 +#else + typedef struct sockaddr_in SOCKADDR_IN_T; + #define AF_INET_V AF_INET +#endif + + +#define SERVER_DEFAULT_VERSION 3 +#define SERVER_DTLS_DEFAULT_VERSION (-2) +#define SERVER_INVALID_VERSION (-99) +#define CLIENT_DEFAULT_VERSION 3 +#define CLIENT_DTLS_DEFAULT_VERSION (-2) +#define CLIENT_INVALID_VERSION (-99) +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH) + #define DEFAULT_MIN_DHKEY_BITS 2048 +#else + #define DEFAULT_MIN_DHKEY_BITS 1024 +#endif + +/* all certs relative to wolfSSL home directory now */ +#if defined(WOLFSSL_NO_CURRDIR) || defined(WOLFSSL_MDK_SHELL) +#define caCert "certs/ca-cert.pem" +#define eccCert "certs/server-ecc.pem" +#define eccKey "certs/ecc-key.pem" +#define svrCert "certs/server-cert.pem" +#define svrKey "certs/server-key.pem" +#define cliCert "certs/client-cert.pem" +#define cliKey "certs/client-key.pem" +#define ntruCert "certs/ntru-cert.pem" +#define ntruKey "certs/ntru-key.raw" +#define dhParam "certs/dh2048.pem" +#define cliEccKey "certs/ecc-client-key.pem" +#define cliEccCert "certs/client-ecc-cert.pem" +#define crlPemDir "certs/crl" +#else +#define caCert "./certs/ca-cert.pem" +#define eccCert "./certs/server-ecc.pem" +#define eccKey "./certs/ecc-key.pem" +#define svrCert "./certs/server-cert.pem" +#define svrKey "./certs/server-key.pem" +#define cliCert "./certs/client-cert.pem" +#define cliKey "./certs/client-key.pem" +#define ntruCert "./certs/ntru-cert.pem" +#define ntruKey "./certs/ntru-key.raw" +#define dhParam "./certs/dh2048.pem" +#define cliEccKey "./certs/ecc-client-key.pem" +#define cliEccCert "./certs/client-ecc-cert.pem" +#define crlPemDir "./certs/crl" +#endif + +typedef struct tcp_ready { + word16 ready; /* predicate */ + word16 port; + char* srfName; /* server ready file name */ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_t mutex; + pthread_cond_t cond; +#endif +} tcp_ready; + + +static INLINE void InitTcpReady(tcp_ready* ready) +{ + ready->ready = 0; + ready->port = 0; + ready->srfName = NULL; +#ifdef SINGLE_THREADED +#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_init(&ready->mutex, 0); + pthread_cond_init(&ready->cond, 0); +#endif +} + + +static INLINE void FreeTcpReady(tcp_ready* ready) +{ +#ifdef SINGLE_THREADED + (void)ready; +#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_destroy(&ready->mutex); + pthread_cond_destroy(&ready->cond); +#else + (void)ready; +#endif +} + +typedef WOLFSSL_METHOD* (*method_provider)(void); +typedef void (*ctx_callback)(WOLFSSL_CTX* ctx); +typedef void (*ssl_callback)(WOLFSSL* ssl); + +typedef struct callback_functions { + method_provider method; + ctx_callback ctx_ready; + ssl_callback ssl_ready; + ssl_callback on_result; +} callback_functions; + +typedef struct func_args { + int argc; + char** argv; + int return_code; + tcp_ready* signal; + callback_functions *callbacks; +} func_args; + + + + +void wait_tcp_ready(func_args*); + +typedef THREAD_RETURN WOLFSSL_THREAD THREAD_FUNC(void*); + +void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*); +void join_thread(THREAD_TYPE); + +/* wolfSSL */ +#ifndef TEST_IPV6 + static const char* const wolfSSLIP = "127.0.0.1"; +#else + static const char* const wolfSSLIP = "::1"; +#endif +static const word16 wolfSSLPort = 11111; + +static INLINE void err_sys(const char* msg) +{ + printf("wolfSSL error: %s\n", msg); + if (msg) + exit(EXIT_FAILURE); +} + + +#define MY_EX_USAGE 2 + +extern int myoptind; +extern char* myoptarg; + +static INLINE int mygetopt(int argc, char** argv, const char* optstring) +{ + static char* next = NULL; + + char c; + char* cp; + + if (myoptind == 0) + next = NULL; /* we're starting new/over */ + + if (next == NULL || *next == '\0') { + if (myoptind == 0) + myoptind++; + + if (myoptind >= argc || argv[myoptind][0] != '-' || + argv[myoptind][1] == '\0') { + myoptarg = NULL; + if (myoptind < argc) + myoptarg = argv[myoptind]; + + return -1; + } + + if (strcmp(argv[myoptind], "--") == 0) { + myoptind++; + myoptarg = NULL; + + if (myoptind < argc) + myoptarg = argv[myoptind]; + + return -1; + } + + next = argv[myoptind]; + next++; /* skip - */ + myoptind++; + } + + c = *next++; + /* The C++ strchr can return a different value */ + cp = (char*)strchr(optstring, c); + + if (cp == NULL || c == ':') + return '?'; + + cp++; + + if (*cp == ':') { + if (*next != '\0') { + myoptarg = next; + next = NULL; + } + else if (myoptind < argc) { + myoptarg = argv[myoptind]; + myoptind++; + } + else + return '?'; + } + + return c; +} + + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + +static INLINE int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) +{ + (void)rw; + (void)userdata; + strncpy(passwd, "yassl123", sz); + return 8; +} + +#endif + + +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) + +static INLINE void ShowX509(WOLFSSL_X509* x509, const char* hdr) +{ + char* altName; + char* issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(x509), 0, 0); + char* subject = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_subject_name(x509), 0, 0); + byte serial[32]; + int ret; + int sz = sizeof(serial); + + printf("%s\n issuer : %s\n subject: %s\n", hdr, issuer, subject); + + while ( (altName = wolfSSL_X509_get_next_altname(x509)) != NULL) + printf(" altname = %s\n", altName); + + ret = wolfSSL_X509_get_serial_number(x509, serial, &sz); + if (ret == SSL_SUCCESS) { + int i; + int strLen; + char serialMsg[80]; + + /* testsuite has multiple threads writing to stdout, get output + message ready to write once */ + strLen = sprintf(serialMsg, " serial number"); + for (i = 0; i < sz; i++) + sprintf(serialMsg + strLen + (i*3), ":%02x ", serial[i]); + printf("%s\n", serialMsg); + } + + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); +} + +#endif /* KEEP_PEER_CERT || SESSION_CERTS */ + + +static INLINE void showPeer(WOLFSSL* ssl) +{ + + WOLFSSL_CIPHER* cipher; +#ifdef KEEP_PEER_CERT + WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); + if (peer) + ShowX509(peer, "peer's cert info:"); + else + printf("peer has no cert!\n"); + wolfSSL_FreeX509(peer); +#endif + printf("SSL version is %s\n", wolfSSL_get_version(ssl)); + + cipher = wolfSSL_get_current_cipher(ssl); +#ifdef HAVE_QSH + printf("SSL cipher suite is %s%s\n", (wolfSSL_isQSH(ssl))? "QSH:": "", + wolfSSL_CIPHER_get_name(cipher)); +#else + printf("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher)); +#endif + +#if defined(SESSION_CERTS) && defined(SHOW_CERTS) + { + WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl); + int count = wolfSSL_get_chain_count(chain); + int i; + + for (i = 0; i < count; i++) { + int length; + unsigned char buffer[3072]; + WOLFSSL_X509* chainX509; + + wolfSSL_get_chain_cert_pem(chain,i,buffer, sizeof(buffer), &length); + buffer[length] = 0; + printf("cert %d has length %d data = \n%s\n", i, length, buffer); + + chainX509 = wolfSSL_get_chain_X509(chain, i); + if (chainX509) + ShowX509(chainX509, "session cert info:"); + else + printf("get_chain_X509 failed\n"); + wolfSSL_FreeX509(chainX509); + } + } +#endif + (void)ssl; +} + + +static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port, int udp) +{ + int useLookup = 0; + (void)useLookup; + (void)udp; + + if (addr == NULL) + err_sys("invalid argument to build_addr, addr is NULL"); + + memset(addr, 0, sizeof(SOCKADDR_IN_T)); + +#ifndef TEST_IPV6 + /* peer could be in human readable form */ + if ( (peer != INADDR_ANY) && isalpha((int)peer[0])) { + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + int err; + struct hostent* entry = gethostbyname(peer, &err); + #elif defined(WOLFSSL_TIRTOS) + struct hostent* entry = DNSGetHostByName(peer); + #elif defined(WOLFSSL_VXWORKS) + struct hostent* entry = (struct hostent*)hostGetByName((char*)peer); + #else + struct hostent* entry = gethostbyname(peer); + #endif + + if (entry) { + memcpy(&addr->sin_addr.s_addr, entry->h_addr_list[0], + entry->h_length); + useLookup = 1; + } + else + err_sys("no entry for host"); + } +#endif + + +#ifndef TEST_IPV6 + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + addr->sin_family = PF_INET; + #else + addr->sin_family = AF_INET_V; + #endif + addr->sin_port = htons(port); + if (peer == INADDR_ANY) + addr->sin_addr.s_addr = INADDR_ANY; + else { + if (!useLookup) + addr->sin_addr.s_addr = inet_addr(peer); + } +#else + addr->sin6_family = AF_INET_V; + addr->sin6_port = htons(port); + if (peer == INADDR_ANY) + addr->sin6_addr = in6addr_any; + else { + #ifdef HAVE_GETADDRINFO + struct addrinfo hints; + struct addrinfo* answer = NULL; + int ret; + char strPort[80]; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_INET_V; + hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP; + + SNPRINTF(strPort, sizeof(strPort), "%d", port); + strPort[79] = '\0'; + + ret = getaddrinfo(peer, strPort, &hints, &answer); + if (ret < 0 || answer == NULL) + err_sys("getaddrinfo failed"); + + memcpy(addr, answer->ai_addr, answer->ai_addrlen); + freeaddrinfo(answer); + #else + printf("no ipv6 getaddrinfo, loopback only tests/examples\n"); + addr->sin6_addr = in6addr_loopback; + #endif + } +#endif +} + + +static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) +{ + if (udp) + *sockfd = socket(AF_INET_V, SOCK_DGRAM, 0); + else + *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); + + if(WOLFSSL_SOCKET_IS_INVALID(*sockfd)) { + err_sys("socket failed\n"); + } + +#ifndef USE_WINDOWS_API +#ifdef SO_NOSIGPIPE + { + int on = 1; + socklen_t len = sizeof(on); + int res = setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len); + if (res < 0) + err_sys("setsockopt SO_NOSIGPIPE failed\n"); + } +#elif defined(WOLFSSL_MDK_ARM) || defined (WOLFSSL_TIRTOS) ||\ + defined(WOLFSSL_KEIL_TCP_NET) + /* nothing to define */ +#else /* no S_NOSIGPIPE */ + signal(SIGPIPE, SIG_IGN); +#endif /* S_NOSIGPIPE */ + +#if defined(TCP_NODELAY) + if (!udp) + { + int on = 1; + socklen_t len = sizeof(on); + int res = setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len); + if (res < 0) + err_sys("setsockopt TCP_NODELAY failed\n"); + } +#endif +#endif /* USE_WINDOWS_API */ +} + +static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, + int udp, WOLFSSL* ssl) +{ + SOCKADDR_IN_T addr; + build_addr(&addr, ip, port, udp); + if(udp) { + wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); + } + tcp_socket(sockfd, udp); + + if (!udp) { + if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp connect failed"); + } +} + + +static INLINE void udp_connect(SOCKET_T* sockfd, void* addr, int addrSz) +{ + if (connect(*sockfd, (const struct sockaddr*)addr, addrSz) != 0) + err_sys("tcp connect failed"); +} + + +enum { + TEST_SELECT_FAIL, + TEST_TIMEOUT, + TEST_RECV_READY, + TEST_ERROR_READY +}; + + +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) && \ + !defined(WOLFSSL_TIRTOS) +static INLINE int tcp_select(SOCKET_T socketfd, int to_sec) +{ + fd_set recvfds, errfds; + SOCKET_T nfds = socketfd + 1; + struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; + int result; + + FD_ZERO(&recvfds); + FD_SET(socketfd, &recvfds); + FD_ZERO(&errfds); + FD_SET(socketfd, &errfds); + + result = select(nfds, &recvfds, NULL, &errfds, &timeout); + + if (result == 0) + return TEST_TIMEOUT; + else if (result > 0) { + if (FD_ISSET(socketfd, &recvfds)) + return TEST_RECV_READY; + else if(FD_ISSET(socketfd, &errfds)) + return TEST_ERROR_READY; + } + + return TEST_SELECT_FAIL; +} +#elif defined(WOLFSSL_TIRTOS) +static INLINE int tcp_select(SOCKET_T socketfd, int to_sec) +{ + return TEST_RECV_READY; +} +#endif /* !WOLFSSL_MDK_ARM */ + + +static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, + int udp) +{ + SOCKADDR_IN_T addr; + + /* don't use INADDR_ANY by default, firewall may block, make user switch + on */ + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp); + tcp_socket(sockfd, udp); + +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\ + && !defined(WOLFSSL_KEIL_TCP_NET) + { + int res, on = 1; + socklen_t len = sizeof(on); + res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); + if (res < 0) + err_sys("setsockopt SO_REUSEADDR failed\n"); + } +#endif + + if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp bind failed"); + if (!udp) { + if (listen(*sockfd, 5) != 0) + err_sys("tcp listen failed"); + } + #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) + if (*port == 0) { + socklen_t len = sizeof(addr); + if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { + #ifndef TEST_IPV6 + *port = ntohs(addr.sin_port); + #else + *port = ntohs(addr.sin6_port); + #endif + } + } + #endif +} + + +#if 0 +static INLINE int udp_read_connect(SOCKET_T sockfd) +{ + SOCKADDR_IN_T cliaddr; + byte b[1500]; + int n; + socklen_t len = sizeof(cliaddr); + + n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK, + (struct sockaddr*)&cliaddr, &len); + if (n > 0) { + if (connect(sockfd, (const struct sockaddr*)&cliaddr, + sizeof(cliaddr)) != 0) + err_sys("udp connect failed"); + } + else + err_sys("recvfrom failed"); + + return sockfd; +} +#endif + +static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, + int useAnyAddr, word16 port, func_args* args) +{ + SOCKADDR_IN_T addr; + + (void)args; + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1); + tcp_socket(sockfd, 1); + + +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) \ + && !defined(WOLFSSL_KEIL_TCP_NET) + { + int res, on = 1; + socklen_t len = sizeof(on); + res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); + if (res < 0) + err_sys("setsockopt SO_REUSEADDR failed\n"); + } +#endif + + if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp bind failed"); + + #if (defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API)) && !defined(WOLFSSL_TIRTOS) + if (port == 0) { + socklen_t len = sizeof(addr); + if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { + #ifndef TEST_IPV6 + port = ntohs(addr.sin_port); + #else + port = ntohs(addr.sin6_port); + #endif + } + } + #endif + +#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__) + /* signal ready to accept data */ + { + tcp_ready* ready = args->signal; + pthread_mutex_lock(&ready->mutex); + ready->ready = 1; + ready->port = port; + pthread_cond_signal(&ready->cond); + pthread_mutex_unlock(&ready->mutex); + } +#elif defined (WOLFSSL_TIRTOS) + /* Need mutex? */ + tcp_ready* ready = args->signal; + ready->ready = 1; + ready->port = port; +#endif + + *clientfd = *sockfd; +} + +static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, + func_args* args, word16 port, int useAnyAddr, + int udp, int ready_file, int do_listen) +{ + SOCKADDR_IN_T client; + socklen_t client_len = sizeof(client); + tcp_ready* ready = NULL; + + (void) ready; /* Account for case when "ready" is not used */ + + if (udp) { + udp_accept(sockfd, clientfd, useAnyAddr, port, args); + return; + } + + if(do_listen) { + tcp_listen(sockfd, &port, useAnyAddr, udp); + + #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__) + /* signal ready to tcp_accept */ + if (args) + ready = args->signal; + if (ready) { + pthread_mutex_lock(&ready->mutex); + ready->ready = 1; + ready->port = port; + pthread_cond_signal(&ready->cond); + pthread_mutex_unlock(&ready->mutex); + } + #elif defined (WOLFSSL_TIRTOS) + /* Need mutex? */ + if (args) + ready = args->signal; + if (ready) { + ready->ready = 1; + ready->port = port; + } + #endif + + if (ready_file) { + #ifndef NO_FILESYSTEM + FILE* srf = NULL; + if (args) + ready = args->signal; + + if (ready) { + srf = fopen(ready->srfName, "w"); + + if (srf) { + /* let's write port sever is listening on to ready file + external monitor can then do ephemeral ports by passing + -p 0 to server on supported platforms with -R ready_file + client can then wait for existence of ready_file and see + which port the server is listening on. */ + fprintf(srf, "%d\n", (int)port); + fclose(srf); + } + } + #endif + } + } + + *clientfd = accept(*sockfd, (struct sockaddr*)&client, + (ACCEPT_THIRD_T)&client_len); + if(WOLFSSL_SOCKET_IS_INVALID(*clientfd)) { + err_sys("tcp accept failed"); + } +} + + +static INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) +{ + #ifdef USE_WINDOWS_API + unsigned long blocking = 1; + int ret = ioctlsocket(*sockfd, FIONBIO, &blocking); + if (ret == SOCKET_ERROR) + err_sys("ioctlsocket failed"); + #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) \ + || defined (WOLFSSL_TIRTOS)|| defined(WOLFSSL_VXWORKS) + /* non blocking not supported, for now */ + #else + int flags = fcntl(*sockfd, F_GETFL, 0); + if (flags < 0) + err_sys("fcntl get failed"); + flags = fcntl(*sockfd, F_SETFL, flags | O_NONBLOCK); + if (flags < 0) + err_sys("fcntl set failed"); + #endif +} + + +#ifndef NO_PSK + +static INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, unsigned char* key, + unsigned int key_max_len) +{ + (void)ssl; + (void)hint; + (void)key_max_len; + + /* identity is OpenSSL testing default for openssl s_client, keep same */ + strncpy(identity, "Client_identity", id_max_len); + + + /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using + unsigned binary */ + key[0] = 26; + key[1] = 43; + key[2] = 60; + key[3] = 77; + + return 4; /* length of key in octets or 0 for error */ +} + + +static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, + unsigned char* key, unsigned int key_max_len) +{ + (void)ssl; + (void)key_max_len; + + /* identity is OpenSSL testing default for openssl s_client, keep same */ + if (strncmp(identity, "Client_identity", 15) != 0) + return 0; + + /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using + unsigned binary */ + key[0] = 26; + key[1] = 43; + key[2] = 60; + key[3] = 77; + + return 4; /* length of key in octets or 0 for error */ +} + +#endif /* NO_PSK */ + + +#ifdef USE_WINDOWS_API + + #define WIN32_LEAN_AND_MEAN + #include <windows.h> + + static INLINE double current_time() + { + static int init = 0; + static LARGE_INTEGER freq; + + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + return (double)count.QuadPart / freq.QuadPart; + } + +#elif defined(WOLFSSL_TIRTOS) + extern double current_time(); +#else + +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) + #include <sys/time.h> + + static INLINE double current_time(void) + { + struct timeval tv; + gettimeofday(&tv, 0); + + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; + } + +#endif +#endif /* USE_WINDOWS_API */ + + +#if defined(NO_FILESYSTEM) && !defined(NO_CERTS) + + enum { + WOLFSSL_CA = 1, + WOLFSSL_CERT = 2, + WOLFSSL_KEY = 3 + }; + + static INLINE void load_buffer(WOLFSSL_CTX* ctx, const char* fname, int type) + { + /* test buffer load */ + long sz = 0; + byte buff[10000]; + FILE* file = fopen(fname, "rb"); + + if (!file) + err_sys("can't open file for buffer load " + "Please run from wolfSSL home directory if not"); + fseek(file, 0, SEEK_END); + sz = ftell(file); + rewind(file); + fread(buff, sizeof(buff), 1, file); + + if (type == WOLFSSL_CA) { + if (wolfSSL_CTX_load_verify_buffer(ctx, buff, sz, SSL_FILETYPE_PEM) + != SSL_SUCCESS) + err_sys("can't load buffer ca file"); + } + else if (type == WOLFSSL_CERT) { + if (wolfSSL_CTX_use_certificate_buffer(ctx, buff, sz, + SSL_FILETYPE_PEM) != SSL_SUCCESS) + err_sys("can't load buffer cert file"); + } + else if (type == WOLFSSL_KEY) { + if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, sz, + SSL_FILETYPE_PEM) != SSL_SUCCESS) + err_sys("can't load buffer key file"); + } + fclose(file); + } + +#endif /* NO_FILESYSTEM */ + +#ifdef VERIFY_CALLBACK + +static INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) +{ + (void)preverify; + char buffer[WOLFSSL_MAX_ERROR_SZ]; + +#ifdef OPENSSL_EXTRA + WOLFSSL_X509* peer; +#endif + + printf("In verification callback, error = %d, %s\n", store->error, + wolfSSL_ERR_error_string(store->error, buffer)); +#ifdef OPENSSL_EXTRA + peer = store->current_cert; + if (peer) { + char* issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(peer), 0, 0); + char* subject = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_subject_name(peer), 0, 0); + printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer, + subject); + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); + } + else + printf("peer has no cert!\n"); +#endif + printf("Subject's domain name is %s\n", store->domain); + + printf("Allowing to continue anyway (shouldn't do this, EVER!!!)\n"); + return 1; +} + +#endif /* VERIFY_CALLBACK */ + + +static INLINE int myDateCb(int preverify, WOLFSSL_X509_STORE_CTX* store) +{ + char buffer[WOLFSSL_MAX_ERROR_SZ]; + (void)preverify; + + printf("In verification callback, error = %d, %s\n", store->error, + wolfSSL_ERR_error_string(store->error, buffer)); + printf("Subject's domain name is %s\n", store->domain); + + if (store->error == ASN_BEFORE_DATE_E || store->error == ASN_AFTER_DATE_E) { + printf("Overriding cert date error as example for bad clock testing\n"); + return 1; + } + printf("Cert error is not date error, not overriding\n"); + + return 0; +} + + +#ifdef HAVE_CRL + +static INLINE void CRL_CallBack(const char* url) +{ + printf("CRL callback url = %s\n", url); +} + +#endif + +#ifndef NO_DH +static INLINE void SetDH(WOLFSSL* ssl) +{ + /* dh1024 p */ + static unsigned char p[] = + { + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, + }; + + /* dh1024 g */ + static unsigned char g[] = + { + 0x02, + }; + + wolfSSL_SetTmpDH(ssl, p, sizeof(p), g, sizeof(g)); +} + +static INLINE void SetDHCtx(WOLFSSL_CTX* ctx) +{ + /* dh1024 p */ + static unsigned char p[] = + { + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, + }; + + /* dh1024 g */ + static unsigned char g[] = + { + 0x02, + }; + + wolfSSL_CTX_SetTmpDH(ctx, p, sizeof(p), g, sizeof(g)); +} +#endif /* NO_DH */ + +#ifndef NO_CERTS + +static INLINE void CaCb(unsigned char* der, int sz, int type) +{ + (void)der; + printf("Got CA cache add callback, derSz = %d, type = %d\n", sz, type); +} + +#endif /* !NO_CERTS */ + +#ifdef HAVE_CAVIUM + +static INLINE int OpenNitroxDevice(int dma_mode,int dev_id) +{ + Csp1CoreAssignment core_assign; + Uint32 device; + + if (CspInitialize(CAVIUM_DIRECT,CAVIUM_DEV_ID)) + return -1; + if (Csp1GetDevType(&device)) + return -1; + if (device != NPX_DEVICE) { + if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT, + (Uint32 *)&core_assign)!= 0) + return -1; + } + CspShutdown(CAVIUM_DEV_ID); + + return CspInitialize(dma_mode, dev_id); +} + +#endif /* HAVE_CAVIUM */ + + +/* Wolf Root Directory Helper */ +/* KEIL-RL File System does not support relative directory */ +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) + #ifndef MAX_PATH + #define MAX_PATH 256 + #endif + + /* Maximum depth to search for WolfSSL root */ + #define MAX_WOLF_ROOT_DEPTH 5 + + static INLINE int ChangeToWolfRoot(void) + { + #if !defined(NO_FILESYSTEM) + int depth, res; + XFILE file; + for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) { + file = XFOPEN(ntruKey, "rb"); + if (file != XBADFILE) { + XFCLOSE(file); + return depth; + } + #ifdef USE_WINDOWS_API + res = SetCurrentDirectoryA("..\\"); + #else + res = chdir("../"); + #endif + if (res < 0) { + printf("chdir to ../ failed!\n"); + break; + } + } + + err_sys("wolf root not found"); + return -1; + #else + return 0; + #endif + } +#endif /* !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) */ + +#ifdef HAVE_STACK_SIZE + +typedef THREAD_RETURN WOLFSSL_THREAD (*thread_func)(void* args); + + +static INLINE void StackSizeCheck(func_args* args, thread_func tf) +{ + int ret, i, used; + unsigned char* myStack = NULL; + int stackSize = 1024*128; + pthread_attr_t myAttr; + pthread_t threadId; + +#ifdef PTHREAD_STACK_MIN + if (stackSize < PTHREAD_STACK_MIN) + stackSize = PTHREAD_STACK_MIN; +#endif + + ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); + if (ret != 0 || myStack == NULL) + err_sys("posix_memalign failed\n"); + + XMEMSET(myStack, 0x01, stackSize); + + ret = pthread_attr_init(&myAttr); + if (ret != 0) + err_sys("attr_init failed"); + + ret = pthread_attr_setstack(&myAttr, myStack, stackSize); + if (ret != 0) + err_sys("attr_setstackaddr failed"); + + ret = pthread_create(&threadId, &myAttr, tf, args); + if (ret != 0) { + perror("pthread_create failed"); + exit(EXIT_FAILURE); + } + + ret = pthread_join(threadId, NULL); + if (ret != 0) + err_sys("pthread_join failed"); + + for (i = 0; i < stackSize; i++) { + if (myStack[i] != 0x01) { + break; + } + } + + used = stackSize - i; + printf("stack used = %d\n", used); +} + + +#endif /* HAVE_STACK_SIZE */ + + +#ifdef STACK_TRAP + +/* good settings + --enable-debug --disable-shared C_EXTRA_FLAGS="-DUSER_TIME -DTFM_TIMING_RESISTANT -DPOSITIVE_EXP_ONLY -DSTACK_TRAP" + +*/ + +#ifdef HAVE_STACK_SIZE + /* client only for now, setrlimit will fail if pthread_create() called */ + /* STACK_SIZE does pthread_create() on client */ + #error "can't use STACK_TRAP with STACK_SIZE, setrlimit will fail" +#endif /* HAVE_STACK_SIZE */ + +static INLINE void StackTrap(void) +{ + struct rlimit rl; + if (getrlimit(RLIMIT_STACK, &rl) != 0) + err_sys("getrlimit failed"); + printf("rlim_cur = %llu\n", rl.rlim_cur); + rl.rlim_cur = 1024*21; /* adjust trap size here */ + if (setrlimit(RLIMIT_STACK, &rl) != 0) { + perror("setrlimit"); + err_sys("setrlimit failed"); + } +} + +#else /* STACK_TRAP */ + +static INLINE void StackTrap(void) +{ +} + +#endif /* STACK_TRAP */ + + +#ifdef ATOMIC_USER + +/* Atomic Encrypt Context example */ +typedef struct AtomicEncCtx { + int keySetup; /* have we done key setup yet */ + Aes aes; /* for aes example */ +} AtomicEncCtx; + + +/* Atomic Decrypt Context example */ +typedef struct AtomicDecCtx { + int keySetup; /* have we done key setup yet */ + Aes aes; /* for aes example */ +} AtomicDecCtx; + + +static INLINE int myMacEncryptCb(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) +{ + int ret; + Hmac hmac; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + AtomicEncCtx* encCtx = (AtomicEncCtx*)ctx; + const char* tlsStr = "TLS"; + + /* example supports (d)tls aes */ + if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) { + printf("myMacEncryptCb not using AES\n"); + return -1; + } + + if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) { + printf("myMacEncryptCb not using (D)TLS\n"); + return -1; + } + + /* hmac, not needed if aead mode */ + wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify); + + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, macIn, macInSz); + if (ret != 0) + return ret; + ret = wc_HmacFinal(&hmac, macOut); + if (ret != 0) + return ret; + + + /* encrypt setup on first time */ + if (encCtx->keySetup == 0) { + int keyLen = wolfSSL_GetKeySize(ssl); + const byte* key; + const byte* iv; + + if (wolfSSL_GetSide(ssl) == WOLFSSL_CLIENT_END) { + key = wolfSSL_GetClientWriteKey(ssl); + iv = wolfSSL_GetClientWriteIV(ssl); + } + else { + key = wolfSSL_GetServerWriteKey(ssl); + iv = wolfSSL_GetServerWriteIV(ssl); + } + + ret = wc_AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed in myMacEncryptCb\n"); + return ret; + } + encCtx->keySetup = 1; + } + + /* encrypt */ + return wc_AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz); +} + + +static INLINE int myDecryptVerifyCb(WOLFSSL* ssl, + unsigned char* decOut, const unsigned char* decIn, + unsigned int decSz, int macContent, int macVerify, + unsigned int* padSz, void* ctx) +{ + AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx; + int ret = 0; + int macInSz = 0; + int ivExtra = 0; + int digestSz = wolfSSL_GetHmacSize(ssl); + unsigned int pad = 0; + unsigned int padByte = 0; + Hmac hmac; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + byte verify[MAX_DIGEST_SIZE]; + const char* tlsStr = "TLS"; + + /* example supports (d)tls aes */ + if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) { + printf("myMacEncryptCb not using AES\n"); + return -1; + } + + if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) { + printf("myMacEncryptCb not using (D)TLS\n"); + return -1; + } + + /*decrypt */ + if (decCtx->keySetup == 0) { + int keyLen = wolfSSL_GetKeySize(ssl); + const byte* key; + const byte* iv; + + /* decrypt is from other side (peer) */ + if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) { + key = wolfSSL_GetClientWriteKey(ssl); + iv = wolfSSL_GetClientWriteIV(ssl); + } + else { + key = wolfSSL_GetServerWriteKey(ssl); + iv = wolfSSL_GetServerWriteIV(ssl); + } + + ret = wc_AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION); + if (ret != 0) { + printf("AesSetKey failed in myDecryptVerifyCb\n"); + return ret; + } + decCtx->keySetup = 1; + } + + /* decrypt */ + ret = wc_AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz); + if (ret != 0) + return ret; + + if (wolfSSL_GetCipherType(ssl) == WOLFSSL_AEAD_TYPE) { + *padSz = wolfSSL_GetAeadMacSize(ssl); + return 0; /* hmac, not needed if aead mode */ + } + + if (wolfSSL_GetCipherType(ssl) == WOLFSSL_BLOCK_TYPE) { + pad = *(decOut + decSz - 1); + padByte = 1; + if (wolfSSL_IsTLSv1_1(ssl)) + ivExtra = wolfSSL_GetCipherBlockSize(ssl); + } + + *padSz = wolfSSL_GetHmacSize(ssl) + pad + padByte; + macInSz = decSz - ivExtra - digestSz - pad - padByte; + + wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify); + + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, macVerify), digestSz); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, decOut + ivExtra, macInSz); + if (ret != 0) + return ret; + ret = wc_HmacFinal(&hmac, verify); + if (ret != 0) + return ret; + + if (memcmp(verify, decOut + decSz - digestSz - pad - padByte, + digestSz) != 0) { + printf("myDecryptVerify verify failed\n"); + return -1; + } + + return ret; +} + + +static INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + AtomicEncCtx* encCtx; + AtomicDecCtx* decCtx; + + encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx)); + if (encCtx == NULL) + err_sys("AtomicEncCtx malloc failed"); + memset(encCtx, 0, sizeof(AtomicEncCtx)); + + decCtx = (AtomicDecCtx*)malloc(sizeof(AtomicDecCtx)); + if (decCtx == NULL) { + free(encCtx); + err_sys("AtomicDecCtx malloc failed"); + } + memset(decCtx, 0, sizeof(AtomicDecCtx)); + + wolfSSL_CTX_SetMacEncryptCb(ctx, myMacEncryptCb); + wolfSSL_SetMacEncryptCtx(ssl, encCtx); + + wolfSSL_CTX_SetDecryptVerifyCb(ctx, myDecryptVerifyCb); + wolfSSL_SetDecryptVerifyCtx(ssl, decCtx); +} + + +static INLINE void FreeAtomicUser(WOLFSSL* ssl) +{ + AtomicEncCtx* encCtx = (AtomicEncCtx*)wolfSSL_GetMacEncryptCtx(ssl); + AtomicDecCtx* decCtx = (AtomicDecCtx*)wolfSSL_GetDecryptVerifyCtx(ssl); + + free(decCtx); + free(encCtx); +} + +#endif /* ATOMIC_USER */ + + +#ifdef HAVE_PK_CALLBACKS + +#ifdef HAVE_ECC + +static INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + WC_RNG rng; + int ret; + word32 idx = 0; + ecc_key myKey; + + (void)ssl; + (void)ctx; + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + wc_ecc_init(&myKey); + + ret = wc_EccPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey); + wc_ecc_free(&myKey); + wc_FreeRng(&rng); + + return ret; +} + + +static INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz, + const byte* hash, word32 hashSz, const byte* key, word32 keySz, + int* result, void* ctx) +{ + int ret; + ecc_key myKey; + + (void)ssl; + (void)ctx; + + wc_ecc_init(&myKey); + + ret = wc_ecc_import_x963(key, keySz, &myKey); + if (ret == 0) + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey); + wc_ecc_free(&myKey); + + return ret; +} + +#endif /* HAVE_ECC */ + +#ifndef NO_RSA + +static INLINE int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + WC_RNG rng; + int ret; + word32 idx = 0; + RsaKey myKey; + + (void)ssl; + (void)ctx; + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + wc_InitRsaKey(&myKey, NULL); + + ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng); + if (ret > 0) { /* save and convert to 0 success */ + *outSz = ret; + ret = 0; + } + wc_FreeRsaKey(&myKey); + wc_FreeRng(&rng); + + return ret; +} + + +static INLINE int myRsaVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, + const byte* key, word32 keySz, + void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + + (void)ssl; + (void)ctx; + + wc_InitRsaKey(&myKey, NULL); + + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey); + wc_FreeRsaKey(&myKey); + + return ret; +} + + +static INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, + word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + WC_RNG rng; + + (void)ssl; + (void)ctx; + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + wc_InitRsaKey(&myKey, NULL); + + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng); + if (ret > 0) { + *outSz = ret; + ret = 0; /* reset to success */ + } + } + wc_FreeRsaKey(&myKey); + wc_FreeRng(&rng); + + return ret; +} + +static INLINE int myRsaDec(WOLFSSL* ssl, byte* in, word32 inSz, + byte** out, + const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + + (void)ssl; + (void)ctx; + + wc_InitRsaKey(&myKey, NULL); + + ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey); + } + wc_FreeRsaKey(&myKey); + + return ret; +} + +#endif /* NO_RSA */ + +static INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + (void)ctx; + (void)ssl; + + #ifdef HAVE_ECC + wolfSSL_CTX_SetEccSignCb(ctx, myEccSign); + wolfSSL_CTX_SetEccVerifyCb(ctx, myEccVerify); + #endif /* HAVE_ECC */ + #ifndef NO_RSA + wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign); + wolfSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify); + wolfSSL_CTX_SetRsaEncCb(ctx, myRsaEnc); + wolfSSL_CTX_SetRsaDecCb(ctx, myRsaDec); + #endif /* NO_RSA */ +} + +#endif /* HAVE_PK_CALLBACKS */ + + + + + +#if defined(__hpux__) || defined(__MINGW32__) || defined (WOLFSSL_TIRTOS) \ + || defined(_MSC_VER) + +/* HP/UX doesn't have strsep, needed by test/suites.c */ +static INLINE char* strsep(char **stringp, const char *delim) +{ + char* start; + char* end; + + start = *stringp; + if (start == NULL) + return NULL; + + if ((end = strpbrk(start, delim))) { + *end++ = '\0'; + *stringp = end; + } else { + *stringp = NULL; + } + + return start; +} + +#endif /* __hpux__ and others */ + +/* Create unique filename, len is length of tempfn name, assuming + len does not include null terminating character, + num is number of characters in tempfn name to randomize */ +static INLINE const char* mymktemp(char *tempfn, int len, int num) +{ + int x, size; + static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + WC_RNG rng; + byte out; + + if (tempfn == NULL || len < 1 || num < 1 || len <= num) { + printf("Bad input\n"); + return NULL; + } + + size = len - 1; + + if (wc_InitRng(&rng) != 0) { + printf("InitRng failed\n"); + return NULL; + } + + for (x = size; x > size - num; x--) { + if (wc_RNG_GenerateBlock(&rng,(byte*)&out, sizeof(out)) != 0) { + printf("RNG_GenerateBlock failed\n"); + return NULL; + } + tempfn[x] = alphanum[out % (sizeof(alphanum) - 1)]; + } + tempfn[len] = '\0'; + + wc_FreeRng(&rng); + + return tempfn; +} + + + +#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ + defined(HAVE_POLY1305) + + #include <wolfssl/wolfcrypt/chacha20_poly1305.h> + + typedef struct key_ctx { + byte name[WOLFSSL_TICKET_NAME_SZ]; /* name for this context */ + byte key[16]; /* cipher key */ + } key_ctx; + + static key_ctx myKey_ctx; + static WC_RNG myKey_rng; + + static INLINE int TicketInit(void) + { + int ret = wc_InitRng(&myKey_rng); + if (ret != 0) return ret; + + ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.key, sizeof(myKey_ctx.key)); + if (ret != 0) return ret; + + ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.name,sizeof(myKey_ctx.name)); + if (ret != 0) return ret; + + return 0; + } + + static INLINE void TicketCleanup(void) + { + wc_FreeRng(&myKey_rng); + } + + static INLINE int myTicketEncCb(WOLFSSL* ssl, + byte key_name[WOLFSSL_TICKET_NAME_SZ], + byte iv[WOLFSSL_TICKET_IV_SZ], + byte mac[WOLFSSL_TICKET_MAC_SZ], + int enc, byte* ticket, int inLen, int* outLen, + void* userCtx) + { + (void)ssl; + (void)userCtx; + + int ret; + word16 sLen = htons(inLen); + byte aad[WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2]; + int aadSz = WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2; + byte* tmp = aad; + + if (enc) { + XMEMCPY(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ); + + ret = wc_RNG_GenerateBlock(&myKey_rng, iv, WOLFSSL_TICKET_IV_SZ); + if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; + + /* build aad from key name, iv, and length */ + XMEMCPY(tmp, key_name, WOLFSSL_TICKET_NAME_SZ); + tmp += WOLFSSL_TICKET_NAME_SZ; + XMEMCPY(tmp, iv, WOLFSSL_TICKET_IV_SZ); + tmp += WOLFSSL_TICKET_IV_SZ; + XMEMCPY(tmp, &sLen, 2); + + ret = wc_ChaCha20Poly1305_Encrypt(myKey_ctx.key, iv, + aad, aadSz, + ticket, inLen, + ticket, + mac); + if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; + *outLen = inLen; /* no padding in this mode */ + } else { + /* decrypt */ + + /* see if we know this key */ + if (XMEMCMP(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ) != 0){ + printf("client presented unknown ticket key name "); + return WOLFSSL_TICKET_RET_FATAL; + } + + /* build aad from key name, iv, and length */ + XMEMCPY(tmp, key_name, WOLFSSL_TICKET_NAME_SZ); + tmp += WOLFSSL_TICKET_NAME_SZ; + XMEMCPY(tmp, iv, WOLFSSL_TICKET_IV_SZ); + tmp += WOLFSSL_TICKET_IV_SZ; + XMEMCPY(tmp, &sLen, 2); + + ret = wc_ChaCha20Poly1305_Decrypt(myKey_ctx.key, iv, + aad, aadSz, + ticket, inLen, + mac, + ticket); + if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; + *outLen = inLen; /* no padding in this mode */ + } + + return WOLFSSL_TICKET_RET_OK; + } + +#endif /* HAVE_SESSION_TICKET && CHACHA20 && POLY1305 */ + +#endif /* wolfSSL_TEST_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/version.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,41 @@ +/* wolfssl_version.h.in + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_VERSION_H +#define WOLFSSL_VERSION_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBWOLFSSL_VERSION_STRING "3.9.0" +#define LIBWOLFSSL_VERSION_HEX 0x03009000 + +#ifdef __cplusplus +} +#endif + + +#endif /* WOLFSSL_VERSION_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/aes.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,197 @@ +/* aes.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_AES_H +#define WOLF_CRYPT_AES_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_AES + +/* included for fips @wc_fips */ +#ifdef HAVE_FIPS +#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 + +#ifndef HAVE_FIPS /* to avoid redefinition of macros */ +#ifdef HAVE_CAVIUM + #include <wolfssl/wolfcrypt/logging.h> + #include "cavium_common.h" +#endif + +#ifdef WOLFSSL_AESNI + +#include <wmmintrin.h> +#include <emmintrin.h> +#include <smmintrin.h> + +#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 + +#endif /* WOLFSSL_AESNI */ + +#if !defined (ALIGN16) + #define ALIGN16 +#endif +#endif /* HAVE_FIPS */ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* to avoid redefinition of structures */ +#define WOLFSSL_AES_CAVIUM_MAGIC 0xBEEF0002 + +enum { + AES_ENC_TYPE = 1, /* cipher unique type */ + AES_ENCRYPTION = 0, + AES_DECRYPTION = 1, + AES_BLOCK_SIZE = 16 +}; + + +typedef struct Aes { + /* AESNI needs key first, rounds 2nd, not sure why yet */ + ALIGN16 word32 key[60]; + word32 rounds; + + ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ + +#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 HAVE_CAVIUM + AesType type; /* aes key type */ + int devId; /* nitrox device id */ + word32 magic; /* using cavium magic */ + word64 contextHandle; /* nitrox context memory handle */ +#endif +#ifdef WOLFSSL_AES_COUNTER + word32 left; /* unused bytes left from last call */ +#endif +#ifdef WOLFSSL_PIC32MZ_CRYPT + word32 key_ce[AES_BLOCK_SIZE*2/sizeof(word32)] ; + word32 iv_ce [AES_BLOCK_SIZE /sizeof(word32)] ; + int keylen ; +#endif +#ifdef WOLFSSL_TI_CRYPT + int keylen ; +#endif +} Aes; + + +#ifdef HAVE_AESGCM +typedef struct Gmac { + Aes aes; +} Gmac; +#endif /* HAVE_AESGCM */ +#endif /* HAVE_FIPS */ + +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); + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER + WOLFSSL_API void 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 + 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); + + 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); +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + WOLFSSL_API void 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); +#endif /* HAVE_AESCCM */ + +#ifdef HAVE_CAVIUM + WOLFSSL_API int wc_AesInitCavium(Aes*, int); + WOLFSSL_API void wc_AesFreeCavium(Aes*); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* NO_AES */ +#endif /* WOLF_CRYPT_AES_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/arc4.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,67 @@ +/* arc4.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_ARC4_H +#define WOLF_CRYPT_ARC4_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifdef __cplusplus + extern "C" { +#endif + +#define WOLFSSL_ARC4_CAVIUM_MAGIC 0xBEEF0001 + +enum { + ARC4_ENC_TYPE = 4, /* cipher unique type */ + ARC4_STATE_SIZE = 256 +}; + +/* ARC4 encryption and decryption */ +typedef struct Arc4 { + byte x; + byte y; + byte state[ARC4_STATE_SIZE]; +#ifdef HAVE_CAVIUM + int devId; /* nitrox device id */ + word32 magic; /* using cavium magic */ + word64 contextHandle; /* nitrox context memory handle */ +#endif +} Arc4; + +WOLFSSL_API void wc_Arc4Process(Arc4*, byte*, const byte*, word32); +WOLFSSL_API void wc_Arc4SetKey(Arc4*, const byte*, word32); + +#ifdef HAVE_CAVIUM + WOLFSSL_API int wc_Arc4InitCavium(Arc4*, int); + WOLFSSL_API void wc_Arc4FreeCavium(Arc4*); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLF_CRYPT_ARC4_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/asn.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,823 @@ +/* asn.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_ASN_H +#define WOLF_CRYPT_ASN_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_ASN + +#include <wolfssl/wolfcrypt/integer.h> +#ifndef NO_RSA + #include <wolfssl/wolfcrypt/rsa.h> +#endif + +/* fips declare of RsaPrivateKeyDecode @wc_fips */ +#if defined(HAVE_FIPS) && !defined(NO_RSA) + #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 HAVE_ECC + #include <wolfssl/wolfcrypt/ecc.h> +#endif + +#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_GENERALIZED_TIME = 0x18, + CRL_EXTENSIONS = 0xa0, + ASN_EXTENSIONS = 0xa3, + ASN_LONG_LENGTH = 0x80 +}; + +enum ASN_Flags{ + ASN_CONSTRUCTED = 0x20, + ASN_CONTEXT_SPECIFIC = 0x80 +}; + +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 */ +}; + +enum PBES { + PBE_MD5_DES = 0, + PBE_SHA1_DES = 1, + PBE_SHA1_DES3 = 2, + PBE_SHA1_RC4_128 = 3, + PBES2 = 13 /* algo ID */ +}; + +enum ENCRYPTION_TYPES { + DES_TYPE = 0, + DES3_TYPE = 1, + RC4_TYPE = 2 +}; + +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 */ + MAX_KEY_SIZE = 64, /* MAX PKCS Key length */ + PKCS5 = 5, /* PKCS oid tag */ + PKCS5v2 = 6, /* PKCS #5 v2.0 */ + PKCS12 = 12, /* PKCS #12 */ + MAX_UNICODE_SZ = 256, + 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 = SHA256_DIGEST_SIZE, +#else + KEYID_SIZE = 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_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 +#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_OID_SZ = 32, /* Max DER length of OID*/ + MAX_OID_STRING_SZ = 64, /* Max string length representation of OID*/ + MAX_CERTPOL_NB = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */ + MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, +#endif + OCSP_NONCE_EXT_SZ = 37, /* 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 */ + HEADER_ENCRYPTED_KEY_SIZE = 88 /* Extra header size for encrypted key */ +}; + + +enum Oid_Types { + hashType = 0, + sigType = 1, + keyType = 2, + curveType = 3, + blkType = 4, + ocspType = 5, + certExtType = 6, + certAuthInfoType = 7, + certPolicyType = 8, + certAltNameType = 9, + certKeyUseType = 10, + kdfType = 11, + ignoreType +}; + + +enum Hash_Sum { + MD2h = 646, + MD5h = 649, + SHAh = 88, + SHA256h = 414, + SHA384h = 415, + SHA512h = 416 +}; + + +enum Block_Sum { + DESb = 69, + DES3b = 652 +}; + + +enum Key_Sum { + DSAk = 515, + RSAk = 645, + NTRUk = 274, + ECDSAk = 518 +}; + + +enum Ecc_Sum { + ECC_256R1 = 526, + ECC_384R1 = 210, + ECC_521R1 = 211, + ECC_160R1 = 184, + ECC_192R1 = 520, + ECC_224R1 = 209 +}; + + +enum KDF_Sum { + PBKDF2_OID = 660 +}; + + +enum Extensions_Sum { + BASIC_CA_OID = 133, + ALT_NAMES_OID = 131, + CRL_DIST_OID = 145, + AUTH_INFO_OID = 69, + 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 */ +}; + +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_OCSP_SIGN_OID = 79 /* 1.3.6.1.5.5.7.3.9, OCSPSigning */ +}; + + +enum VerifyType { + NO_VERIFY = 0, + VERIFY = 1 +}; + +#ifdef WOLFSSL_CERT_EXT +enum KeyIdType { + SKID_TYPE = 0, + AKID_TYPE = 1 +}; +#endif + +/* Key usage extension bits */ +#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 + +#define EXTKEYUSE_ANY 0x08 +#define EXTKEYUSE_OCSP_SIGN 0x04 +#define EXTKEYUSE_CLIENT_AUTH 0x02 +#define EXTKEYUSE_SERVER_AUTH 0x01 + +typedef struct DNS_entry DNS_entry; + +struct DNS_entry { + DNS_entry* next; /* next on DNS list */ + 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) */ +}; + + +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; +}; + + +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 */ + + +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 */ + int subjectCNStored; /* have we saved a copy we own */ + 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 extSubjKeyIdSet; /* Set when the SKID was read from cert */ + byte extAuthKeyId[KEYID_SIZE]; /* Authority Key ID */ + byte extAuthKeyIdSet; /* Set when the AKID was read from cert */ +#ifndef IGNORE_NAME_CONSTRAINTS + byte extNameConstraintSet; +#endif /* IGNORE_NAME_CONSTRAINTS */ + byte isCA; /* CA basic constraint true */ + byte weOwnAltNames; /* altNames haven't been given to copy */ + byte extKeyUsageSet; + word16 extKeyUsage; /* Key usage bitfield */ + byte extExtKeyUsageSet; /* Extended Key Usage */ + byte extExtKeyUsage; /* Extended Key usage bitfield */ +#ifdef OPENSSL_EXTRA + byte extBasicConstSet; + byte extBasicConstCrit; + byte extBasicConstPlSet; + word32 pathLength; /* CA basic constraint path length, opt */ + byte extSubjAltNameSet; + byte extSubjAltNameCrit; + byte extAuthKeyIdCrit; +#ifndef IGNORE_NAME_CONSTRAINTS + byte extNameConstraintCrit; +#endif /* IGNORE_NAME_CONSTRAINTS */ + byte extSubjKeyIdCrit; + byte extKeyUsageCrit; + byte extExtKeyUsageCrit; + byte* extExtKeyUsageSrc; + word32 extExtKeyUsageSz; + word32 extExtKeyUsageCount; + byte* extAuthKeyIdSrc; + word32 extAuthKeyIdSz; + byte* extSubjKeyIdSrc; + word32 extSubjKeyIdSz; +#endif +#ifdef HAVE_ECC + 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 +#if defined(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 */ +#ifdef OPENSSL_EXTRA + DecodedName issuerName; + DecodedName subjectName; +#endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_SEP + int deviceTypeSz; + byte* deviceType; + int hwTypeSz; + byte* hwType; + int hwSerialNumSz; + byte* hwSerialNum; + #ifdef OPENSSL_EXTRA + byte extCertPolicySet; + byte extCertPolicyCrit; + #endif /* OPENSSL_EXTRA */ +#endif /* WOLFSSL_SEP */ +#ifdef WOLFSSL_CERT_EXT + char extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; + int extCertPoliciesNb; +#endif /* WOLFSSL_CERT_EXT */ +}; + +extern const char* BEGIN_CERT; +extern const char* END_CERT; +extern const char* BEGIN_CERT_REQ; +extern const char* END_CERT_REQ; +extern const char* BEGIN_DH_PARAM; +extern const char* END_DH_PARAM; +extern const char* BEGIN_X509_CRL; +extern const char* END_X509_CRL; +extern const char* BEGIN_RSA_PRIV; +extern const char* END_RSA_PRIV; +extern const char* BEGIN_PRIV_KEY; +extern const char* END_PRIV_KEY; +extern const char* BEGIN_ENC_PRIV_KEY; +extern const char* END_ENC_PRIV_KEY; +extern const char* BEGIN_EC_PRIV; +extern const char* END_EC_PRIV; +extern const char* BEGIN_DSA_PRIV; +extern const char* END_DSA_PRIV; +extern const char* BEGIN_PUB_KEY; +extern const char* END_PUB_KEY; + +#ifdef NO_SHA + #define SIGNER_DIGEST_SIZE SHA256_DIGEST_SIZE +#else + #define SIGNER_DIGEST_SIZE 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* 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 + 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 */ + + +/* not for public consumption but may use for testing sometimes */ +#ifdef WOLFSSL_TEST_CERT + #define WOLFSSL_TEST_API WOLFSSL_API +#else + #define WOLFSSL_TEST_API WOLFSSL_LOCAL +#endif + +WOLFSSL_TEST_API void FreeAltNames(DNS_entry*, void*); +#ifndef IGNORE_NAME_CONSTRAINTS + WOLFSSL_TEST_API void FreeNameSubtrees(Base_entry*, void*); +#endif /* IGNORE_NAME_CONSTRAINTS */ +WOLFSSL_TEST_API void InitDecodedCert(DecodedCert*, byte*, word32, void*); +WOLFSSL_TEST_API void FreeDecodedCert(DecodedCert*); +WOLFSSL_TEST_API int ParseCert(DecodedCert*, int type, int verify, void* cm); + +WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm); +WOLFSSL_LOCAL int DecodeToKey(DecodedCert*, int verify); + +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_LOCAL int ToTraditional(byte* buffer, word32 length); +WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int); + +WOLFSSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType); + +/* ASN.1 helper functions */ +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); +WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, + word32 maxIdx); +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); +WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, + int maxIdx); + +#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 + +#ifdef WOLFSSL_CERT_GEN + +enum cert_enums { + NAME_ENTRIES = 8, + JOINT_LEN = 2, + EMAIL_JOINT_LEN = 9, + RSA_KEY = 10, + NTRU_KEY = 11, + ECC_KEY = 12 +}; + +#ifndef WOLFSSL_PEMCERT_TODER_DEFINED +#ifndef NO_FILESYSTEM +/* forward from wolfSSL */ +WOLFSSL_API +int wolfSSL_PemCertToDer(const char* fileName,unsigned char* derBuf,int derSz); +#define WOLFSSL_PEMCERT_TODER_DEFINED +#endif +#endif + +#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 +}; + + +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; + + 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 */ +}; + + +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; +}; + + +WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); +WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*); + +WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte); +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 */ +}; + +WOLFSSL_LOCAL void InitDecodedCRL(DecodedCRL*); +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 */ +#endif /* WOLF_CRYPT_ASN_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/asn_public.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,275 @@ +/* asn_public.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_ASN_PUBLIC_H +#define WOLF_CRYPT_ASN_PUBLIC_H + +#include <wolfssl/wolfcrypt/types.h> +#ifdef HAVE_ECC + #include <wolfssl/wolfcrypt/ecc.h> +#endif +#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) + #include <wolfssl/wolfcrypt/rsa.h> +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* Certificate file Type */ +enum CertType { + CERT_TYPE = 0, + PRIVATEKEY_TYPE, + DH_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 +}; + + +/* Signature type, by OID sum */ +enum Ctc_SigType { + CTC_SHAwDSA = 517, + CTC_MD2wRSA = 646, + CTC_MD5wRSA = 648, + CTC_SHAwRSA = 649, + CTC_SHAwECDSA = 520, + CTC_SHA256wRSA = 655, + CTC_SHA256wECDSA = 524, + CTC_SHA384wRSA = 656, + CTC_SHA384wECDSA = 525, + CTC_SHA512wRSA = 657, + CTC_SHA512wECDSA = 526 +}; + +enum Ctc_Encoding { + CTC_UTF8 = 0x0c, /* utf8 */ + CTC_PRINTABLE = 0x13 /* printable */ +}; + +enum Ctc_Misc { + CTC_NAME_SIZE = 64, + CTC_DATE_SIZE = 32, + CTC_MAX_ALT_SIZE = 16384, /* may be huge */ + CTC_SERIAL_SIZE = 8, +#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 */ +}; + +#ifdef WOLFSSL_CERT_GEN + +#ifndef HAVE_ECC + typedef struct ecc_key ecc_key; +#endif + +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 !!!! */ +} CertName; + + +/* for user to fill for certificate generation */ +typedef struct Cert { + int version; /* x509 version */ + byte serial[CTC_SERIAL_SIZE]; /* serial number */ + 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 */ + 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 +} Cert; +#endif /* WOLFSSL_CERT_GEN */ + + +#ifdef WOLFSSL_CERT_GEN + + + +/* 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 void wc_InitCert(Cert*); +WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, + ecc_key*, WC_RNG*); +#ifdef WOLFSSL_CERT_REQ + WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz, + RsaKey*, ecc_key*); +#endif +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); + +#ifdef WOLFSSL_CERT_EXT +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(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); + +/* 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 */ +WOLFSSL_API int wc_SetCertificatePolicies(Cert *cert, const char **input); + +#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 */ + +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) + #ifndef WOLFSSL_PEMPUBKEY_TODER_DEFINED + #ifndef NO_FILESYSTEM + /* forward from wolfssl */ + WOLFSSL_API int wolfSSL_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif + + /* forward from wolfssl */ + WOLFSSL_API int wolfSSL_PubKeyPemToDer(const unsigned char*, int, + unsigned char*, int); + #define WOLFSSL_PEMPUBKEY_TODER_DEFINED + #endif /* WOLFSSL_PEMPUBKEY_TODER_DEFINED */ +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ + +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || !defined(NO_DSA) + 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); + + /* public key helper */ + WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*, + ecc_key*, word32); +#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); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_ASN_PUBLIC_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/blake2-impl.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,156 @@ +/* + 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-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 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 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 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 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 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 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 INLINE word32 rotl32( const word32 w, const unsigned c ) +{ + return ( w << c ) | ( w >> ( 32 - c ) ); +} + +static INLINE word64 rotl64( const word64 w, const unsigned c ) +{ + return ( w << c ) | ( w >> ( 64 - c ) ); +} + +static INLINE word32 rotr32( const word32 w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 32 - c ) ); +} + +static INLINE word64 rotr64( const word64 w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 64 - c ) ); +} + +/* prevents compiler optimizing out memset() */ +static INLINE void secure_zero_memory( void *v, word64 n ) +{ + volatile byte *p = ( volatile byte * )v; + + while( n-- ) *p++ = 0; +} + +#endif /* WOLFCRYPT_BLAKE2_IMPL_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/blake2-int.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,185 @@ +/* + 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-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/blake2.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,73 @@ +/* blake2.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 = 7, /* hash type unique */ + 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/camellia.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,98 @@ +/* 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-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 void wc_CamelliaEncryptDirect(Camellia* cam, byte* out, + const byte* in); +WOLFSSL_API void wc_CamelliaDecryptDirect(Camellia* cam, byte* out, + const byte* in); +WOLFSSL_API void wc_CamelliaCbcEncrypt(Camellia* cam, + byte* out, const byte* in, word32 sz); +WOLFSSL_API void wc_CamelliaCbcDecrypt(Camellia* cam, + byte* out, const byte* in, word32 sz); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CAMELLIA */ +#endif /* WOLF_CRYPT_CAMELLIA_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/chacha.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,59 @@ +/* chacha.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_CHACHA_H +#define WOLF_CRYPT_CHACHA_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifdef HAVE_CHACHA + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + CHACHA_ENC_TYPE = 7 /* cipher unique type */ +}; + +typedef struct ChaCha { + word32 X[16]; /* state of cipher */ +} 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/chacha20_poly1305.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,81 @@ +/* chacha20_poly1305.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + */ + +#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 */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/coding.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,78 @@ +/* coding.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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(HAVE_WEBSERVER) || defined(HAVE_FIPS) + 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/compress.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,50 @@ +/* compress.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/curve25519.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,143 @@ +/* curve25519.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 __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]; +}ECPoint; + +/* A CURVE25519 Key */ +typedef struct { + 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 */ +} 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/des3.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,117 @@ +/* des3.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_DES3_H +#define WOLF_CRYPT_DES3_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_DES3 + +#ifdef HAVE_FIPS +/* included for fips @wc_fips */ +#include <cyassl/ctaocrypt/des3.h> +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* to avoid redefinition of macros */ +#define WOLFSSL_3DES_CAVIUM_MAGIC 0xBEEF0003 + +enum { + DES_ENC_TYPE = 2, /* cipher unique type */ + DES3_ENC_TYPE = 3, /* cipher unique type */ + DES_BLOCK_SIZE = 8, + DES_KS_SIZE = 32, + + DES_ENCRYPTION = 0, + DES_DECRYPTION = 1 +}; + +#define DES_IVLEN 8 +#define DES_KEYLEN 8 +#define DES3_IVLEN 8 +#define DES3_KEYLEN 24 + + +#ifdef STM32F2_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 HAVE_CAVIUM + int devId; /* nitrox device id */ + word32 magic; /* using cavium magic */ + word64 contextHandle; /* nitrox context memory handle */ +#endif +} 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_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); + +#ifdef HAVE_CAVIUM + WOLFSSL_API int wc_Des3_InitCavium(Des3*, int); + WOLFSSL_API void wc_Des3_FreeCavium(Des3*); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_DES3 */ +#endif /* WOLF_CRYPT_DES3_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/dh.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,68 @@ +/* dh.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_DH_H +#define WOLF_CRYPT_DH_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_DH + +#include <wolfssl/wolfcrypt/integer.h> +#include <wolfssl/wolfcrypt/random.h> + +#ifdef __cplusplus + extern "C" { +#endif + + +/* Diffie-Hellman Key */ +typedef struct DhKey { + mp_int p, g; /* group parameters */ +} DhKey; + + +WOLFSSL_API void wc_InitDhKey(DhKey* key); +WOLFSSL_API void 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_DhParamsLoad(const byte* input, word32 inSz, byte* p, + word32* pInOutSz, byte* g, word32* gInOutSz); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_DH */ +#endif /* WOLF_CRYPT_DH_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/dsa.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,82 @@ +/* dsa.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 */ +} DsaKey; + +WOLFSSL_API void wc_InitDsaKey(DsaKey* key); +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 + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_DSA */ +#endif /* WOLF_CRYPT_DSA_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/ecc.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,306 @@ +/* ecc.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_ECC_H +#define WOLF_CRYPT_ECC_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifdef HAVE_ECC + +#include <wolfssl/wolfcrypt/integer.h> +#include <wolfssl/wolfcrypt/random.h> + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + ECC_PUBLICKEY = 1, + ECC_PRIVATEKEY = 2, + 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 set type defined a NIST GF(p) curve */ +typedef struct { + int size; /* The size of the curve in octets */ + int nid; /* 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) */ +} ecc_set_type; + + +#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 + +#ifndef FP_MAX_BITS_ECC + #define FP_MAX_BITS_ECC 528 +#endif +#define FP_MAX_SIZE_ECC (FP_MAX_BITS_ECC+(8*DIGIT_BIT)) +#if FP_MAX_BITS_ECC % CHAR_BIT + #error FP_MAX_BITS_ECC must be a multiple of CHAR_BIT +#endif +#define FP_SIZE_ECC (FP_MAX_SIZE_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 + +/* 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 +} ecc_point; + + +/* An ECC Key */ +typedef struct { + 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 */ + const ecc_set_type* dp; /* domain parameters, either points to NIST + curves (idx >= 0) or user supplied */ + ecc_point pubkey; /* public key */ + mp_int k; /* private key */ +} ecc_key; + + +/* ECC predefined curve sets */ +extern const ecc_set_type ecc_sets[]; + + +WOLFSSL_API +int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key); +WOLFSSL_API +int wc_ecc_check_key(ecc_key* key); + +#ifdef HAVE_ECC_DHE +WOLFSSL_API +int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, + word32* outlen); +WOLFSSL_API +int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen); +#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 +void wc_ecc_free(ecc_key* key); +WOLFSSL_API +void wc_ecc_fp_free(void); + +WOLFSSL_API +ecc_point* wc_ecc_new_point(void); +WOLFSSL_API +void wc_ecc_del_point(ecc_point* p); +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); +WOLFSSL_API +int wc_ecc_is_valid_idx(int n); +WOLFSSL_API +int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, + mp_int* modulus, int map); + +#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_private_key(const byte* priv, word32 privSz, const byte* pub, + word32 pubSz, ecc_key* key); +WOLFSSL_API +int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen); +WOLFSSL_API +int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, + const char* d, const char* curveName); +#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_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(ecc_key* key); + + +#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 +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 __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_ECC */ +#endif /* WOLF_CRYPT_ECC_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/ed25519.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,109 @@ +/* ed25519.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 __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) + +/* An ED25519 Key */ +typedef struct { + byte p[ED25519_PUB_KEY_SIZE]; /* compressed public key */ + byte k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */ +} ed25519_key; + + +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(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_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); + +/* 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/error-crypt.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,186 @@ +/* error-crypt.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 */ + + 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 */ + + 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 */ + + 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 */ + + AES_GCM_AUTH_E = -180, /* AES-GCM Authentication check failure */ + AES_CCM_AUTH_E = -181, /* AES-CCM Authentication check failure */ + + CAVIUM_INIT_E = -182, /* Cavium 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_ENC_STATE_E = -192, /* Bad ecc enc 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 */ + + SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */ + SRP_VERIFY_E = -218, /* SRP proof verification failed. */ + SRP_BAD_KEY_E = -219, /* SRP bad ephemeral values. */ + + ASN_NO_SKID = -220, /* ASN no Subject Key Identifier found */ + ASN_NO_AKID = -221, /* 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 */ + + MIN_CODE_E = -300 /* errors -101 - -299 */ + + /* add new companion error id strings for any new error codes + wolfcrypt/src/error.c !!! */ +}; + + +WOLFSSL_API void wc_ErrorString(int err, char* buff); +WOLFSSL_API const char* wc_GetErrorString(int error); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif +#endif /* WOLF_CRYPT_ERROR_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/fe_operations.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,134 @@ +/* fe_operations.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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) + +#ifndef CURVED25519_SMALL + #include <stdint.h> +#endif +#include <wolfssl/wolfcrypt/types.h> + +/* +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. +*/ + +#ifdef CURVED25519_SMALL + #define F25519_SIZE 32 + typedef byte fe[32]; +#else + typedef int32_t fe[10]; +#endif + +WOLFSSL_LOCAL int curve25519(byte * q, byte * n, byte * p); +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); + +/* default to be faster but take more memory */ +#ifndef CURVED25519_SMALL + +/* 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,unsigned int); +WOLFSSL_LOCAL void fe_mul121666(fe,fe); +WOLFSSL_LOCAL void fe_cmov(fe,const fe,unsigned 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); +#endif /* not defined CURVED25519_SMALL */ + +/* Use less memory and only 32bit types or less, but is slower + Based on Daniel Beer's public domain work. */ +#ifdef CURVED25519_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 /* CURVED25519_SMALL */ +#endif /* HAVE_CURVE25519 or HAVE_ED25519 */ +#endif /* WOLF_CRYPT_FE_OPERATIONS_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/fips_test.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,60 @@ +/* fips_test.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 <cyassl/ctaocrypt/types.h> + + +#ifdef __cplusplus + extern "C" { +#endif + +/* Known Answer Test string inputs are hex, internal */ +CYASSL_LOCAL int DoKnownAnswerTests(char*, int); + + +/* FIPS failure callback */ +typedef void(*wolfCrypt_fips_cb)(int ok, int err, const char* hash); + +/* Public set function */ +CYASSL_API int wolfCrypt_SetCb_fips(wolfCrypt_fips_cb cbf); + +/* Public get status functions */ +CYASSL_API int wolfCrypt_GetStatus_fips(void); +CYASSL_API const char* wolfCrypt_GetCoreHash_fips(void); + +#ifdef HAVE_FORCE_FIPS_FAILURE + /* Public function to force failure mode for operational testing */ + CYASSL_API int wolfCrypt_SetStatus_fips(int); +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_FIPS_TEST_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/ge_operations.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,117 @@ +/* ge_operations.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + +#ifndef CURVED25519_SMALL + #include <stdint.h> +#endif +#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) +*/ + + +typedef struct { + fe X; + fe Y; + fe Z; +} ge_p2; + +typedef struct { + fe X; + fe Y; + fe Z; + fe 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 CURVED25519_SMALL +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p1p1; + +typedef struct { + fe yplusx; + fe yminusx; + fe xy2d; +} ge_precomp; + +typedef struct { + fe YplusX; + fe YminusX; + fe Z; + fe T2d; +} ge_cached; + +WOLFSSL_LOCAL void ge_p2_0(ge_p2 *); +WOLFSSL_LOCAL void ge_p3_0(ge_p3 *); +WOLFSSL_LOCAL void ge_precomp_0(ge_precomp *); +WOLFSSL_LOCAL void ge_p3_to_p2(ge_p2 *,const ge_p3 *); +WOLFSSL_LOCAL void ge_p3_to_cached(ge_cached *,const ge_p3 *); +WOLFSSL_LOCAL void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *); +WOLFSSL_LOCAL void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *); +WOLFSSL_LOCAL void ge_p2_dbl(ge_p1p1 *,const ge_p2 *); +WOLFSSL_LOCAL void ge_p3_dbl(ge_p1p1 *,const ge_p3 *); + +WOLFSSL_LOCAL void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *); +WOLFSSL_LOCAL void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *); +WOLFSSL_LOCAL void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *); +WOLFSSL_LOCAL void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *); +#endif /* no CURVED25519_SMALL */ +#endif /* HAVE_ED25519 */ +#endif /* WOLF_CRYPT_GE_OPERATIONS_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/hash.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,129 @@ +/* hash.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_HASH_H +#define WOLF_CRYPT_HASH_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifdef __cplusplus + extern "C" { +#endif + +/* 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_SHA256 = 5, + WC_HASH_TYPE_SHA384 = 6, + WC_HASH_TYPE_SHA512 = 7, +}; + +/* Find largest possible digest size + Note if this gets up to the size of 80 or over check smallstack build */ +#if defined(WOLFSSL_SHA512) + #define WC_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE +#elif defined(WOLFSSL_SHA384) + #define WC_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE +#elif !defined(NO_SHA256) + #define WC_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE +#elif !defined(NO_SHA) + #define WC_MAX_DIGEST_SIZE SHA_DIGEST_SIZE +#elif !defined(NO_MD5) + #define WC_MAX_DIGEST_SIZE MD5_DIGEST_SIZE +#else + #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */ +#endif + +#ifndef NO_ASN +WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type); +#endif + +WOLFSSL_API int wc_HashGetDigestSize(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); + + +#ifndef NO_MD5 +#include <wolfssl/wolfcrypt/md5.h> +WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); +WOLFSSL_API void wc_Md5RestorePos(Md5*, Md5*); +#if defined(WOLFSSL_TI_HASH) + WOLFSSL_API void wc_Md5Free(Md5*); +#else + #define wc_Md5Free(d) +#endif +#endif + +#ifndef NO_SHA +#include <wolfssl/wolfcrypt/sha.h> +WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); +WOLFSSL_API void wc_ShaRestorePos(Sha*, Sha*); +WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); +#if defined(WOLFSSL_TI_HASH) + WOLFSSL_API void wc_ShaFree(Sha*); +#else + #define wc_ShaFree(d) +#endif +#endif + +#ifndef NO_SHA256 +#include <wolfssl/wolfcrypt/sha256.h> +WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); +WOLFSSL_API void wc_Sha256RestorePos(Sha256*, Sha256*); +WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); +#if defined(WOLFSSL_TI_HASH) + WOLFSSL_API void wc_Sha256Free(Sha256*); +#else + #define wc_Sha256Free(d) +#endif +#endif + +#ifdef WOLFSSL_SHA512 +#include <wolfssl/wolfcrypt/sha512.h> +WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*); +#if defined(WOLFSSL_TI_HASH) + WOLFSSL_API void wc_Sha512Free(Sha512*); +#else + #define wc_Sha512Free(d) +#endif + #if defined(WOLFSSL_SHA384) + WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*); + #if defined(WOLFSSL_TI_HASH) + WOLFSSL_API void wc_Sha384Free(Sha384*); + #else + #define wc_Sha384Free(d) + #endif + #endif /* defined(WOLFSSL_SHA384) */ +#endif /* WOLFSSL_SHA512 */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_HASH_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/hc128.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,60 @@ +/* hc128.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_HC128_H +#define WOLF_CRYPT_HC128_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_HC128 + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + HC128_ENC_TYPE = 6 /* 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]; +} 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); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_HC128 */ +#endif /* WOLF_CRYPT_HC128_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/hmac.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,192 @@ +/* hmac.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 NO_HMAC + +#ifndef WOLF_CRYPT_HMAC_H +#define WOLF_CRYPT_HMAC_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_MD5 + #include <wolfssl/wolfcrypt/md5.h> +#endif + +#ifndef NO_SHA + #include <wolfssl/wolfcrypt/sha.h> +#endif + +#ifndef NO_SHA256 + #include <wolfssl/wolfcrypt/sha256.h> +#endif + +#ifdef WOLFSSL_SHA512 + #include <wolfssl/wolfcrypt/sha512.h> +#endif + +#ifdef HAVE_BLAKE2 + #include <wolfssl/wolfcrypt/blake2.h> +#endif + +#ifdef HAVE_FIPS +/* for fips */ + #include <cyassl/ctaocrypt/hmac.h> +#endif + +#ifdef HAVE_CAVIUM + #include <wolfssl/wolfcrypt/logging.h> + #include "cavium_common.h" +#endif + + +#ifdef __cplusplus + extern "C" { +#endif +#ifndef HAVE_FIPS +#define WOLFSSL_HMAC_CAVIUM_MAGIC 0xBEEF0005 + +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 + MD5 = 0, +#endif +#ifdef NO_SHA + SHA = 1, +#endif +#ifdef NO_SHA256 + SHA256 = 2, +#endif +#ifndef WOLFSSL_SHA512 + SHA512 = 4, +#endif +#ifndef WOLFSSL_SHA384 + SHA384 = 5, +#endif +#ifndef HAVE_BLAKE2 + BLAKE2B_ID = 7, +#endif + +/* Select the largest available hash for the buffer size. */ +#if defined(WOLFSSL_SHA512) + MAX_DIGEST_SIZE = SHA512_DIGEST_SIZE, + HMAC_BLOCK_SIZE = SHA512_BLOCK_SIZE +#elif defined(HAVE_BLAKE2) + MAX_DIGEST_SIZE = BLAKE2B_OUTBYTES, + HMAC_BLOCK_SIZE = BLAKE2B_BLOCKBYTES, +#elif defined(WOLFSSL_SHA384) + MAX_DIGEST_SIZE = SHA384_DIGEST_SIZE, + HMAC_BLOCK_SIZE = SHA384_BLOCK_SIZE +#elif !defined(NO_SHA256) + MAX_DIGEST_SIZE = SHA256_DIGEST_SIZE, + HMAC_BLOCK_SIZE = SHA256_BLOCK_SIZE +#elif !defined(NO_SHA) + MAX_DIGEST_SIZE = SHA_DIGEST_SIZE, + HMAC_BLOCK_SIZE = SHA_BLOCK_SIZE +#elif !defined(NO_MD5) + MAX_DIGEST_SIZE = MD5_DIGEST_SIZE, + HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE +#else + #error "You have to have some kind of hash if you want to use HMAC." +#endif +}; + + +/* hash union */ +typedef union { + #ifndef NO_MD5 + Md5 md5; + #endif + #ifndef NO_SHA + Sha sha; + #endif + #ifndef NO_SHA256 + Sha256 sha256; + #endif + #ifdef WOLFSSL_SHA384 + Sha384 sha384; + #endif + #ifdef WOLFSSL_SHA512 + Sha512 sha512; + #endif + #ifdef HAVE_BLAKE2 + Blake2b blake2b; + #endif +} Hash; + +/* Hmac digest */ +typedef struct Hmac { + Hash hash; + word32 ipad[HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ + word32 opad[HMAC_BLOCK_SIZE / sizeof(word32)]; + word32 innerHash[MAX_DIGEST_SIZE / sizeof(word32)]; + byte macType; /* md5 sha or sha256 */ + byte innerHashKeyed; /* keyed flag */ +#ifdef HAVE_CAVIUM + word16 keyLen; /* hmac key length */ + word16 dataLen; + HashType type; /* hmac key type */ + int devId; /* nitrox device id */ + word32 magic; /* using cavium magic */ + word64 contextHandle; /* nitrox context memory handle */ + byte* data; /* buffered input data for one call */ +#endif +} 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*); + +#ifdef HAVE_CAVIUM + WOLFSSL_API int wc_HmacInitCavium(Hmac*, int); + WOLFSSL_API void wc_HmacFreeCavium(Hmac*); +#endif + +WOLFSSL_API int wolfSSL_GetHmacMaxSize(void); + + +#ifdef HAVE_HKDF + +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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/integer.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,339 @@ +/* integer.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 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> + +#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 *) + +#else + +/* C on the other hand doesn't care */ +#define OPT_CAST(x) + +#endif + + +/* 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; +#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)) + +/* the infamous mp_int structure */ +typedef struct { + int used, alloc, sign; + mp_digit *dp; +} mp_int; + +/* 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_iseven(a) \ + (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) +#define mp_isodd(a) \ + (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) + + +/* number of primes */ +#ifdef MP_8BIT + #define PRIME_SIZE 31 +#else + #define PRIME_SIZE 256 +#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_tobinary(M, S) mp_toradix((M), (S), 2) +#define mp_tooctal(M, S) mp_toradix((M), (S), 8) +#define mp_todecimal(M, S) mp_toradix((M), (S), 10) +#define mp_tohex(M, S) mp_toradix((M), (S), 16) + +#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) + +extern const char *mp_s_rmap; + +/* 6 functions needed by Rsa */ +int mp_init (mp_int * a); +void mp_clear (mp_int * a); +int mp_unsigned_bin_size(mp_int * a); +int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +int mp_to_unsigned_bin (mp_int * a, unsigned char *b); +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 */ +int mp_count_bits (mp_int * a); +int mp_leading_bit (mp_int * a); +int mp_init_copy (mp_int * a, mp_int * b); +int mp_copy (mp_int * a, mp_int * b); +int mp_grow (mp_int * a, int size); +int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); +void mp_zero (mp_int * a); +void mp_clamp (mp_int * a); +void mp_exch (mp_int * a, mp_int * b); +void mp_rshd (mp_int * a, int b); +void mp_rshb (mp_int * a, int b); +int mp_mod_2d (mp_int * a, int b, mp_int * c); +int mp_mul_2d (mp_int * a, int b, mp_int * c); +int mp_lshd (mp_int * a, int b); +int mp_abs (mp_int * a, mp_int * b); +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); +int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); +int mp_cmp_mag (mp_int * a, mp_int * b); +int mp_cmp (mp_int * a, mp_int * b); +int mp_cmp_d(mp_int * a, mp_digit b); +void mp_set (mp_int * a, mp_digit b); +int mp_is_bit_set (mp_int * a, mp_digit b); +int mp_mod (mp_int * a, mp_int * b, mp_int * c); +int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); +int mp_div_2(mp_int * a, mp_int * b); +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); +int mp_sub (mp_int * a, mp_int * b, mp_int * c); +int mp_reduce_is_2k_l(mp_int *a); +int mp_reduce_is_2k(mp_int *a); +int mp_dr_is_modulus(mp_int *a); +int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int); +int mp_montgomery_setup (mp_int * n, mp_digit * rho); +int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); +int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); +void mp_dr_setup(mp_int *a, mp_digit *d); +int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k); +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); +int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); +int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); +int mp_reduce (mp_int * x, mp_int * m, mp_int * mu); +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); +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); +int mp_init_size (mp_int * a, int size); +int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d); +int mp_mul_2(mp_int * a, mp_int * b); +int mp_mul (mp_int * a, mp_int * b, mp_int * c); +int mp_sqr (mp_int * a, mp_int * b); +int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); +int mp_2expt (mp_int * a, int b); +int mp_set_bit (mp_int * a, int b); +int mp_reduce_2k_setup(mp_int *a, mp_digit *d); +int mp_add_d (mp_int* a, mp_digit b, mp_int* c); +int mp_set_int (mp_int * a, unsigned long b); +int mp_sub_d (mp_int * a, mp_digit b, mp_int * c); +/* end support added functions */ + +/* added */ +int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, + mp_int* f); +int mp_toradix (mp_int *a, char *str, int radix); +int mp_radix_size (mp_int * a, int radix, int *size); + +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) + int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); +#endif +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) + int mp_read_radix(mp_int* a, const char* str, int radix); +#endif + +#ifdef WOLFSSL_KEY_GEN + int mp_prime_is_prime (mp_int * a, int t, int *result); + int mp_gcd (mp_int * a, mp_int * b, mp_int * c); + int mp_lcm (mp_int * a, mp_int * b, mp_int * c); + int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); +#endif + +int mp_cnt_lsb(mp_int *a); +int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c); + +#ifdef __cplusplus + } +#endif + + +#endif /* USE_FAST_MATH */ + +#endif /* WOLF_CRYPT_INTEGER_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/logging.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,79 @@ +/* logging.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 */ + + +#ifndef WOLFSSL_LOGGING_H +#define WOLFSSL_LOGGING_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifdef __cplusplus + extern "C" { +#endif + + +enum CYA_Log_Levels { + ERROR_LOG = 0, + INFO_LOG, + ENTER_LOG, + LEAVE_LOG, + OTHER_LOG +}; + +typedef void (*wolfSSL_Logging_cb)(const int logLevel, + const char *const logMessage); + +WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); + +#ifdef DEBUG_WOLFSSL + /* 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 + + void WOLFSSL_ENTER(const char* msg); + void WOLFSSL_LEAVE(const char* msg, int ret); + #define WOLFSSL_STUB(m) \ + WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented)) + + void WOLFSSL_ERROR(int); + void WOLFSSL_MSG(const char* msg); + void WOLFSSL_BUFFER(byte* buffer, word32 length); + +#else /* DEBUG_WOLFSSL */ + + #define WOLFSSL_ENTER(m) + #define WOLFSSL_LEAVE(m, r) + #define WOLFSSL_STUB(m) + + #define WOLFSSL_ERROR(e) + #define WOLFSSL_MSG(m) + #define WOLFSSL_BUFFER(b, l) + +#endif /* DEBUG_WOLFSSL */ + +#ifdef __cplusplus +} +#endif +#endif /* WOLFSSL_LOGGING_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/md2.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,66 @@ +/* md2.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_MD2_H +#define WOLF_CRYPT_MD2_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifdef WOLFSSL_MD2 + +#ifdef __cplusplus + extern "C" { +#endif + +/* in bytes */ +enum { + MD2 = 6, /* hash type unique */ + 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/md4.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,64 @@ +/* md4.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_MD4_H +#define WOLF_CRYPT_MD4_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_MD4 + +#ifdef __cplusplus + extern "C" { +#endif + +/* in bytes */ +enum { + 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/md5.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,87 @@ +/* md5.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 + +/* in bytes */ +enum { +#ifdef STM32F2_HASH + MD5_REG_SIZE = 4, /* STM32 register size, bytes */ +#endif + MD5 = 0, /* hash type unique */ + MD5_BLOCK_SIZE = 64, + MD5_DIGEST_SIZE = 16, + MD5_PAD_SIZE = 56 +}; + +#if defined(WOLFSSL_PIC32MZ_HASH) +#include "port/pic32/pic32mz-crypt.h" +#endif + +#ifndef WOLFSSL_TI_HASH + +/* MD5 digest */ +typedef struct Md5 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[MD5_BLOCK_SIZE / sizeof(word32)]; + #if !defined(WOLFSSL_PIC32MZ_HASH) + word32 digest[MD5_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; + pic32mz_desc desc ; /* Crypt Engine descriptor */ + #endif +} Md5; + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +WOLFSSL_API void wc_InitMd5(Md5*); +WOLFSSL_API void wc_Md5Update(Md5*, const byte*, word32); +WOLFSSL_API void wc_Md5Final(Md5*, byte*); +WOLFSSL_API int wc_Md5Hash(const byte*, word32, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_MD5 */ +#endif /* WOLF_CRYPT_MD5_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/memory.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,58 @@ +/* memory.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 */ + + +#ifndef WOLFSSL_MEMORY_H +#define WOLFSSL_MEMORY_H + +#include <stdlib.h> +#include <wolfssl/wolfcrypt/types.h> + +#ifdef __cplusplus + extern "C" { +#endif + +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 set function */ +WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, + wolfSSL_Free_cb free_function, + wolfSSL_Realloc_cb realloc_function); + +/* 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); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_MEMORY_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/misc.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,80 @@ +/* misc.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 */ + +#endif /* NO_INLINE */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLF_CRYPT_MISC_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/mpi_class.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,1020 @@ +/* mpi_class.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/mpi_superclass.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,97 @@ +/* mpi_superclass.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/pkcs7.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,128 @@ +/* pkcs7.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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_DES3 + #include <wolfssl/wolfcrypt/des3.h> +#endif + +#ifdef __cplusplus + extern "C" { +#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 = DES3_KEYLEN, /* highest current cipher is 3DES */ + 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 PKCS7 { + byte* content; /* inner content, not owner */ + word32 contentSz; /* content size */ + int contentOID; /* PKCS#7 content type OID sum */ + + WC_RNG* rng; + + int hashOID; + int encryptOID; /* key encryption algorithm OID */ + + byte* singleCert; /* recipient cert, DER, not owner */ + word32 singleCertSz; /* size of recipient cert buffer, bytes */ + byte issuerHash[KEYID_SIZE]; /* hash of all alt Names */ + byte* issuer; /* issuer name of singleCert */ + word32 issuerSz; /* length of issuer name */ + byte issuerSn[MAX_SN_SZ]; /* singleCert's serial number */ + word32 issuerSnSz; /* length of serial number */ + byte publicKey[512]; + word32 publicKeySz; + byte* privateKey; /* private key, DER, not owner */ + word32 privateKeySz; /* size of private key buffer, bytes */ + + PKCS7Attrib* signedAttribs; + word32 signedAttribsSz; +} PKCS7; + + +WOLFSSL_LOCAL int wc_SetContentType(int pkcs7TypeOID, byte* output); +WOLFSSL_LOCAL int wc_GetContentType(const byte* input, word32* inOutIdx, + word32* oid, word32 maxIdx); +WOLFSSL_LOCAL 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); + +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_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); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_PKCS7 */ +#endif /* WOLF_CRYPT_PKCS7_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/poly1305.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,86 @@ +/* poly1305.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 */ +#define HAS_SIZEOF_INT128_64BIT (defined(__SIZEOF_INT128__) && defined(__LP64__)) +#define HAS_MSVC_64BIT (defined(_MSC_VER) && defined(_M_X64)) +#define HAS_GCC_4_4_64BIT (defined(__GNUC__) && defined(__LP64__) && \ + ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)))) + +#if (HAS_SIZEOF_INT128_64BIT || HAS_MSVC_64BIT || 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 { +#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 final; +} 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/pwdbased.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,67 @@ +/* pwdbased.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_PWDBASED_H +#define WOLF_CRYPT_PWDBASED_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_PWDBASED + +#ifndef NO_MD5 + #include <wolfssl/wolfcrypt/md5.h> /* for hash type */ +#endif + +#include <wolfssl/wolfcrypt/sha.h> + +#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(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); + +/* helper functions */ +WOLFSSL_LOCAL int GetDigestSize(int typeH); +WOLFSSL_LOCAL int GetPKCS12HashSizes(int typeH, word32* v, word32* u); +WOLFSSL_LOCAL int DoPKCS12Hash(int typeH, byte* buffer, word32 totalLen, + byte* Ai, word32 u, int iterations); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_PWDBASED */ +#endif /* WOLF_CRYPT_PWDBASED_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/rabbit.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,66 @@ +/* rabbit.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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; +} Rabbit; + + +WOLFSSL_API int wc_RabbitProcess(Rabbit*, byte*, const byte*, word32); +WOLFSSL_API int wc_RabbitSetKey(Rabbit*, const byte* key, const byte* iv); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_RABBIT */ +#endif /* WOLF_CRYPT_RABBIT_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/random.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,149 @@ +/* random.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_RANDOM_H +#define WOLF_CRYPT_RANDOM_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifdef HAVE_FIPS +/* for fips @wc_fips */ +#include <cyassl/ctaocrypt/random.h> +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefining structs and macros */ +#if defined(WOLFSSL_FORCE_RC4_DRBG) && defined(NO_RC4) + #error Cannot have WOLFSSL_FORCE_RC4_DRBG and NO_RC4 defined. +#endif /* WOLFSSL_FORCE_RC4_DRBG && NO_RC4 */ +#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + #ifdef NO_SHA256 + #error "Hash DRBG requires SHA-256." + #endif /* NO_SHA256 */ + + #include <wolfssl/wolfcrypt/sha256.h> +#else /* HAVE_HASHDRBG || NO_RC4 */ + #include <wolfssl/wolfcrypt/arc4.h> +#endif /* HAVE_HASHDRBG || NO_RC4 */ + +#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; + + +#if (defined(HAVE_HASHDRBG) || defined(NO_RC4)) && !defined(CUSTOM_RAND_GENERATE_BLOCK) + +#define DRBG_SEED_LEN (440/8) + + +struct DRBG; /* Private DRBG state */ + + +/* Hash-based Deterministic Random Bit Generator */ +typedef struct WC_RNG { + struct DRBG* drbg; + OS_Seed seed; + byte status; +} WC_RNG; + + + +#else /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ + +#define WOLFSSL_RNG_CAVIUM_MAGIC 0xBEEF0004 + +/* secure Random Number Generator */ + + +typedef struct WC_RNG { + OS_Seed seed; +#ifndef NO_RC4 + Arc4 cipher; +#endif +#ifdef HAVE_CAVIUM + int devId; /* nitrox device id */ + word32 magic; /* using cavium magic */ +#endif +} WC_RNG; + + + +#endif /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#endif /* HAVE_FIPS */ + +/* 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); + +#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + +#ifdef HAVE_CAVIUM + WOLFSSL_API int wc_InitRngCavium(WC_RNG*, int); +#endif + +#endif /* HAVE_HASH_DRBG || NO_RC4 */ + + +WOLFSSL_API int wc_InitRng(WC_RNG*); +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*); + + +#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + WOLFSSL_API int wc_RNG_HealthTest(int reseed, + const byte* entropyA, word32 entropyASz, + const byte* entropyB, word32 entropyBSz, + byte* output, word32 outputSz); +#endif /* HAVE_HASHDRBG || NO_RC4 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_RANDOM_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/ripemd.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,65 @@ +/* ripemd.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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 void wc_InitRipeMd(RipeMd*); +WOLFSSL_API void wc_RipeMdUpdate(RipeMd*, const byte*, word32); +WOLFSSL_API void wc_RipeMdFinal(RipeMd*, byte*); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_RIPEMD */ +#endif /* WOLF_CRYPT_RIPEMD_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/rsa.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,157 @@ +/* rsa.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_RSA_H +#define WOLF_CRYPT_RSA_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_RSA + +/* 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 + +#ifdef HAVE_FIPS +/* 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 */ + +/* header file needed for OAEP padding */ +#include <wolfssl/wolfcrypt/hash.h> + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) +#define WOLFSSL_RSA_CAVIUM_MAGIC 0xBEEF0006 + +enum { + RSA_PUBLIC = 0, + RSA_PRIVATE = 1, +}; + + +/* RSA */ +typedef struct RsaKey { + mp_int n, e, d, p, q, dP, dQ, u; + int type; /* public or private */ + void* heap; /* for user memory overrides */ +#ifdef HAVE_CAVIUM + int devId; /* nitrox device id */ + word32 magic; /* using cavium magic */ + word64 contextHandle; /* nitrox context memory handle */ + byte* c_n; /* cavium byte buffers for key parts */ + byte* c_e; + byte* c_d; + byte* c_p; + byte* c_q; + byte* c_dP; + byte* c_dQ; + byte* c_u; /* sizes in bytes */ + word16 c_nSz, c_eSz, c_dSz, c_pSz, c_qSz, c_dP_Sz, c_dQ_Sz, c_uSz; +#endif +} RsaKey; +#endif /*HAVE_FIPS */ + +WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*); +WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); + +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_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_RsaEncryptSize(RsaKey* key); + +#ifndef HAVE_FIPS /* 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 + +/* + choice of padding added after fips, so not available when using fips RSA + */ + +/* Mask Generation Function Identifiers */ +#define WC_MGF1SHA1 26 +#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 + +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); +#endif /* HAVE_FIPS*/ +WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, + word32*); + +#ifdef WOLFSSL_KEY_GEN + WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); + WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); +#endif + +#ifdef HAVE_CAVIUM + WOLFSSL_API int wc_RsaInitCavium(RsaKey*, int); + WOLFSSL_API void wc_RsaFreeCavium(RsaKey*); +#endif +#endif /* HAVE_USER_RSA */ +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_RSA */ +#endif /* WOLF_CRYPT_RSA_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/sha.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,88 @@ +/* sha.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_SHA_H +#define WOLF_CRYPT_SHA_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_SHA + +#ifdef HAVE_FIPS +/* for fips @wc_fips */ +#include <cyassl/ctaocrypt/sha.h> +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefining structs */ +/* in bytes */ +enum { +#ifdef STM32F2_HASH + SHA_REG_SIZE = 4, /* STM32 register size, bytes */ +#endif + SHA = 1, /* hash type unique */ + SHA_BLOCK_SIZE = 64, + SHA_DIGEST_SIZE = 20, + SHA_PAD_SIZE = 56 +}; + +#ifdef WOLFSSL_PIC32MZ_HASH +#include "port/pic32/pic32mz-crypt.h" +#endif + +#ifndef WOLFSSL_TI_HASH + +/* Sha digest */ +typedef struct Sha { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[SHA_BLOCK_SIZE / sizeof(word32)]; + #ifndef WOLFSSL_PIC32MZ_HASH + word32 digest[SHA_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; + pic32mz_desc desc; /* Crypt Engine descriptor */ + #endif +} Sha; + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha(Sha*); +WOLFSSL_API int wc_ShaUpdate(Sha*, const byte*, word32); +WOLFSSL_API int wc_ShaFinal(Sha*, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA */ +#endif /* WOLF_CRYPT_SHA_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/sha256.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,86 @@ +/* sha256.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 */ + +#ifndef WOLF_CRYPT_SHA256_H +#define WOLF_CRYPT_SHA256_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifndef NO_SHA256 + +#ifdef HAVE_FIPS + /* for fips @wc_fips */ + #include <cyassl/ctaocrypt/sha256.h> +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefinition of structs */ +#ifdef WOLFSSL_PIC32MZ_HASH + #include "port/pic32/pic32mz-crypt.h" +#endif + +/* in bytes */ +enum { + SHA256 = 2, /* hash type unique */ + SHA256_BLOCK_SIZE = 64, + SHA256_DIGEST_SIZE = 32, + SHA256_PAD_SIZE = 56 +}; + +#ifndef WOLFSSL_TI_HASH + +/* Sha256 digest */ +typedef struct Sha256 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; + word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; + #ifdef WOLFSSL_PIC32MZ_HASH + pic32mz_desc desc ; /* Crypt Engine descriptor */ + #endif +} Sha256; + +#else /* WOLFSSL_TI_HASH */ + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha256(Sha256*); +WOLFSSL_API int wc_Sha256Update(Sha256*, const byte*, word32); +WOLFSSL_API int wc_Sha256Final(Sha256*, byte*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA256 */ +#endif /* WOLF_CRYPT_SHA256_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/sha512.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,104 @@ +/* sha512.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_SHA512_H +#define WOLF_CRYPT_SHA512_H + +#include <wolfssl/wolfcrypt/types.h> + +#ifdef WOLFSSL_SHA512 + +/* for fips @wc_fips */ +#ifdef HAVE_FIPS + #define CYASSL_SHA512 + #if defined(WOLFSSL_SHA384) + #define CYASSL_SHA384 + #endif + #include <cyassl/ctaocrypt/sha512.h> +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefinition of structs */ + +/* in bytes */ +enum { + SHA512 = 4, /* hash type unique */ + SHA512_BLOCK_SIZE = 128, + SHA512_DIGEST_SIZE = 64, + SHA512_PAD_SIZE = 112 +}; + + +/* Sha512 digest */ +typedef struct Sha512 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word64 digest[SHA512_DIGEST_SIZE / sizeof(word64)]; + word64 buffer[SHA512_BLOCK_SIZE / sizeof(word64)]; +} Sha512; + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha512(Sha512*); +WOLFSSL_API int wc_Sha512Update(Sha512*, const byte*, word32); +WOLFSSL_API int wc_Sha512Final(Sha512*, byte*); + +#if defined(WOLFSSL_SHA384) + +#ifndef HAVE_FIPS /* avoid redefinition of structs */ +/* in bytes */ +enum { + SHA384 = 5, /* hash type unique */ + SHA384_BLOCK_SIZE = 128, + SHA384_DIGEST_SIZE = 48, + SHA384_PAD_SIZE = 112 +}; + + +/* Sha384 digest */ +typedef struct Sha384 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word64 digest[SHA512_DIGEST_SIZE / sizeof(word64)]; /* for transform 512 */ + word64 buffer[SHA384_BLOCK_SIZE / sizeof(word64)]; +} Sha384; +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha384(Sha384*); +WOLFSSL_API int wc_Sha384Update(Sha384*, const byte*, word32); +WOLFSSL_API int wc_Sha384Final(Sha384*, byte*); + +#endif /* WOLFSSL_SHA384 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA512 */ +#endif /* WOLF_CRYPT_SHA512_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/tfm.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,748 @@ +/* tfm.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 Moisés Guimarães (moises.guimaraes@phoebus.com.br) + * to fit CyaSSL's needs. + */ + + +#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> + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef MIN + #define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +#ifndef MAX + #define MAX(x,y) ((x)>(y)?(x):(y)) +#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 */ + typedef unsigned long fp_word __attribute__ ((mode(TI))); +#else + #if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 ulong64; + #else + typedef unsigned long long ulong64; + #endif + + #ifndef NO_64BIT + typedef unsigned int fp_digit; + 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; + typedef unsigned int fp_word; + #endif +#endif + +#endif /* WOLFSSL_BIGINT_TYPES */ + +/* # of digits this is */ +#define DIGIT_BIT (int)((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_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 */ + +/* a FP type */ +typedef struct { + int used, + sign; +#ifdef ALT_ECC_SIZE + int size; +#endif + fp_digit dp[FP_SIZE]; +} 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 + +/* do we want some overflow checks + Not required if you make sure your numbers are within range (e.g. by default a modulus for fp_exptmod() can only be up to 2048 bits long) + */ +/* #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 */ +#ifdef ALT_ECC_SIZE + void fp_init(fp_int *a); + void fp_zero(fp_int *a); + void fp_clear(fp_int *a); /* uses ForceZero to clear sensitive memory */ +#else + #define fp_init(a) (void)XMEMSET((a), 0, sizeof(fp_int)) + #define fp_zero(a) fp_init(a) + #define fp_clear(a) ForceZero((a), sizeof(fp_int)); +#endif + +/* zero/even/odd ? */ +#define fp_iszero(a) (((a)->used == 0) ? 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) + +/* set to a small digit */ +void fp_set(fp_int *a, fp_digit 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 */ +#ifndef ALT_ECC_SIZE + #define fp_copy(a, b) (void)(((a) != (b)) ? ((void)XMEMCPY((b), (a), sizeof(fp_int))) : (void)0) + #define fp_init_copy(a, b) fp_copy(b, a) +#else + void fp_copy(fp_int *a, fp_int *b); + void fp_init_copy(fp_int *a, fp_int *b); +#endif + +/* 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; } + +/* 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); + +/* 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);*/ + +/* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime */ +/*int fp_isprime(fp_int *a);*/ + +/* 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 conersions */ +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, unsigned char *b, int c); +void fp_to_unsigned_bin(fp_int *a, unsigned char *b); + +/*int fp_signed_bin_size(fp_int *a);*/ +/*void fp_read_signed_bin(fp_int *a, 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); + +#ifdef TFM_SMALL_SET +void fp_mul_comba_small(fp_int *a, fp_int *b, fp_int *c); +#endif + +#ifdef TFM_MUL3 +void fp_mul_comba3(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL4 +void fp_mul_comba4(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL6 +void fp_mul_comba6(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL7 +void fp_mul_comba7(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL8 +void fp_mul_comba8(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL9 +void fp_mul_comba9(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL12 +void fp_mul_comba12(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL17 +void fp_mul_comba17(fp_int *a, fp_int *b, fp_int *c); +#endif + +#ifdef TFM_MUL20 +void fp_mul_comba20(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL24 +void fp_mul_comba24(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL28 +void fp_mul_comba28(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL32 +void fp_mul_comba32(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL48 +void fp_mul_comba48(fp_int *a, fp_int *b, fp_int *c); +#endif +#ifdef TFM_MUL64 +void fp_mul_comba64(fp_int *a, fp_int *b, fp_int *c); +#endif + +void fp_sqr_comba(fp_int *a, fp_int *b); + +#ifdef TFM_SMALL_SET +void fp_sqr_comba_small(fp_int *a, fp_int *b); +#endif + +#ifdef TFM_SQR3 +void fp_sqr_comba3(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR4 +void fp_sqr_comba4(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR6 +void fp_sqr_comba6(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR7 +void fp_sqr_comba7(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR8 +void fp_sqr_comba8(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR9 +void fp_sqr_comba9(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR12 +void fp_sqr_comba12(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR17 +void fp_sqr_comba17(fp_int *a, fp_int *b); +#endif + +#ifdef TFM_SQR20 +void fp_sqr_comba20(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR24 +void fp_sqr_comba24(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR28 +void fp_sqr_comba28(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR32 +void fp_sqr_comba32(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR48 +void fp_sqr_comba48(fp_int *a, fp_int *b); +#endif +#ifdef TFM_SQR64 +void fp_sqr_comba64(fp_int *a, fp_int *b); +#endif +/*extern const char *fp_s_rmap;*/ + + +/** + * Used by wolfSSL + */ + +/* Types */ + typedef fp_digit mp_digit; + typedef fp_word mp_word; + typedef fp_int mp_int; + +/* 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 */ + +/* Prototypes */ +#define mp_zero(a) fp_zero(a) +#define mp_iseven(a) fp_iseven(a) +int mp_init (mp_int * a); +void mp_clear (mp_int * a); +int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, mp_int* f); + +int mp_add (mp_int * a, mp_int * b, mp_int * c); +int mp_sub (mp_int * a, mp_int * b, mp_int * c); +int mp_add_d (mp_int * a, mp_digit b, mp_int * c); + +int mp_mul (mp_int * a, mp_int * b, mp_int * c); +int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +int mp_mod(mp_int *a, mp_int *b, mp_int *c); +int mp_invmod(mp_int *a, mp_int *b, mp_int *c); +int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); +int mp_mul_2d(mp_int *a, int b, mp_int *c); + + +int mp_cmp(mp_int *a, mp_int *b); +int mp_cmp_d(mp_int *a, mp_digit b); + +int mp_unsigned_bin_size(mp_int * a); +int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +int mp_to_unsigned_bin (mp_int * a, unsigned char *b); + +int mp_sub_d(fp_int *a, fp_digit b, fp_int *c); +int mp_copy(fp_int* a, fp_int* b); +int mp_isodd(mp_int* a); +int mp_iszero(mp_int* a); +int mp_count_bits(mp_int *a); +int mp_leading_bit(mp_int *a); +int mp_set_int(mp_int *a, mp_digit b); +int mp_is_bit_set (mp_int * a, mp_digit b); +int mp_set_bit (mp_int * a, mp_digit b); +void mp_rshb(mp_int *a, int x); +int mp_toradix (mp_int *a, char *str, int radix); +int mp_radix_size (mp_int * a, int radix, int *size); + +#ifdef HAVE_ECC + int mp_read_radix(mp_int* a, const char* str, int radix); + void mp_set(fp_int *a, fp_digit b); + int mp_sqr(fp_int *a, fp_int *b); + int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); + int mp_montgomery_setup(fp_int *a, fp_digit *rho); + int mp_div_2(fp_int * a, fp_int * b); + int mp_init_copy(fp_int * a, fp_int * b); +#endif + +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) + int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); + int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); +#endif + +#ifdef WOLFSSL_KEY_GEN +int mp_gcd(fp_int *a, fp_int *b, fp_int *c); +int mp_lcm(fp_int *a, fp_int *b, fp_int *c); +int mp_prime_is_prime(mp_int* a, int t, int* result); +int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); +int mp_exch(mp_int *a, mp_int *b); +#endif /* WOLFSSL_KEY_GEN */ + +int mp_cnt_lsb(fp_int *a); +int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); +int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); + +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()) +#ifdef __cplusplus + } +#endif + +#endif /* WOLF_CRYPT_TFM_H */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/types.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,350 @@ +/* types.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_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; + #endif + + + /* try to set SIZEOF_LONG or LONG_LONG if user didn't */ + #if !defined(_MSC_VER) && !defined(__BCPLUSPLUS__) + #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG) + #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) \ + || defined(__mips64) || defined(__x86_64__)) + /* 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(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; + #else + #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 + + + /* These platforms have 64-bit CPU registers. */ + #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \ + defined(__mips64) || defined(__x86_64__) || defined(_M_X64)) + typedef word64 wolfssl_word; + #else + typedef word32 wolfssl_word; + #ifdef WORD64_AVAILABLE + #define WOLFCRYPT_SLOW_WORD64 + #endif + #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 INLINE + #ifndef NO_INLINE + #ifdef _MSC_VER + #define INLINE __inline + #elif defined(__GNUC__) + #ifdef WOLFSSL_VXWORKS + #define INLINE __inline__ + #else + #define INLINE inline + #endif + #elif defined(__IAR_SYSTEMS_ICC__) + #define INLINE inline + #elif defined(THREADX) + #define INLINE _Inline + #else + #define INLINE + #endif + #else + #define INLINE + #endif + #endif + + + /* set up rotate style */ + #if defined(_MSC_VER) || defined(__BCPLUSPLUS__) + #define INTEL_INTRINSICS + #define FAST_ROTATE + #elif defined(__MWERKS__) && TARGET_CPU_PPC + #define PPC_INTRINSICS + #define FAST_ROTATE + #elif defined(__GNUC__) && defined(__i386__) + /* 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) + #define THREAD_LS_T + #else + #define THREAD_LS_T __thread + #endif + #else + #define THREAD_LS_T + #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) + #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 embeded systems doesn't like free(0) so test */ + #if 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(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(FREERTOS) && !defined(FREERTOS_TCP)\ + && !defined(WOLFSSL_uITRON4) && !defined(WOLFSSL_uTKERNEL2) + /* default C runtime, can install different routines at runtime via cbs */ + #include <wolfssl/wolfcrypt/memory.h> + #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 + + #ifndef STRING_USER + #include <string.h> + char* mystrnstr(const char* s1, const char* s2, unsigned int n); + + #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)) + #ifndef USE_WINDOWS_API + #define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n)) + #else + #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) + #endif + + #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN) + /* use only Thread Safe version of strtok */ + #ifndef USE_WINDOWS_API + #define XSTRTOK strtok_r + #else + #define XSTRTOK strtok_s + #endif + #endif + #endif + + #ifndef CTYPE_USER + #include <ctype.h> + #if defined(HAVE_ECC) || defined(HAVE_OCSP) || defined(WOLFSSL_KEY_GEN) + #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_CAVIUM_TMP = 40, + DYNAMIC_TYPE_CAVIUM_RSA = 41, + DYNAMIC_TYPE_X509 = 42, + DYNAMIC_TYPE_TLSX = 43, + DYNAMIC_TYPE_OCSP = 44, + DYNAMIC_TYPE_SIGNATURE = 45, + DYNAMIC_TYPE_HASHES = 46, + DYNAMIC_TYPE_SRP = 47, + DYNAMIC_TYPE_COOKIE_PWD = 48, + DYNAMIC_TYPE_USER_CRYPTO = 49, + DYNAMIC_TYPE_OCSP_REQUEST = 50, + DYNAMIC_TYPE_X509_EXT = 51, + DYNAMIC_TYPE_X509_STORE = 52, + DYNAMIC_TYPE_X509_CTX = 53, + DYNAMIC_TYPE_URL = 54, + DYNAMIC_TYPE_DTLS_FRAG = 55, + DYNAMIC_TYPE_DTLS_BUFFER = 56 + }; + + /* max error buffer string size */ + enum { + WOLFSSL_MAX_ERROR_SZ = 80 + }; + + /* stack protection */ + enum { + MIN_STACK_BUFFER = 8 + }; + + + + /* 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()) + + + #ifdef __cplusplus + } /* extern "C" */ + #endif + +#endif /* WOLF_CRYPT_TYPES_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/visibility.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,77 @@ +/* visibility.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 */ +#ifdef HAVE_FIPS + #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) + #ifdef 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) + #ifdef 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 */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssl/wolfcrypt/wc_port.h Thu Apr 28 00:57:21 2016 +0000 @@ -0,0 +1,265 @@ +/* wc_port.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_PORT_H +#define WOLF_CRYPT_PORT_H + +#include <wolfssl/wolfcrypt/visibility.h> + +#ifdef __cplusplus + extern "C" { +#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 + #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) + #include "kernel.h" +#elif defined(WOLFSSL_uTKERNEL2) + #include "tk/tkernel.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> +#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 + + +#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; + #else + #error Need a mutex type in multithreaded mode + #endif /* USE_WINDOWS_API */ +#endif /* SINGLE_THREADED */ + +/* Enable crypt HW mutex for Freescale MMCAU */ +#if defined(FREESCALE_MMCAU) + #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() 0 /* Success */ +#endif /* WOLFSSL_CRYPT_HW_MUTEX */ + +/* Mutex functions */ +WOLFSSL_LOCAL int InitMutex(wolfSSL_Mutex*); +WOLFSSL_LOCAL int FreeMutex(wolfSSL_Mutex*); +WOLFSSL_LOCAL int LockMutex(wolfSSL_Mutex*); +WOLFSSL_LOCAL int UnLockMutex(wolfSSL_Mutex*); + +/* main crypto initialization function */ +WOLFSSL_API int wolfCrypt_Init(void); + +/* filesystem abstraction layer, used by ssl.c */ +#ifndef NO_FILESYSTEM + +#if defined(EBSNET) + #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 +#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 +#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 +#elif defined(MICRIUM) + #include <fs.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 +#else + /* stdio, default case */ + #define XFILE FILE* + #if defined(WOLFSSL_MDK_ARM) + #include <stdio.h> + 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 +#endif + +#endif /* NO_FILESYSTEM */ + + +/* Windows API defines its own min() macro. */ +#if defined(USE_WINDOWS_API) + #ifdef min + #define WOLFSSL_HAVE_MIN + #endif /* min */ + #ifdef max + #define WOLFSSL_HAVE_MAX + #endif /* max */ +#endif /* USE_WINDOWS_API */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_PORT_H */ + +