mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 17:48:33 -04:00
Prepare for V7.2.0 release.
This commit is contained in:
parent
73ad4387e2
commit
e0bab5981a
1071 changed files with 8726 additions and 2457 deletions
|
@ -36,41 +36,48 @@
|
|||
/* Initialze CRL members */
|
||||
int InitCRL(CYASSL_CRL* crl, CYASSL_CERT_MANAGER* cm)
|
||||
{
|
||||
CYASSL_ENTER("InitCRL");
|
||||
CYASSL_ENTER("InitCRL");
|
||||
|
||||
crl->cm = cm;
|
||||
crl->crlList = NULL;
|
||||
if (InitMutex(&crl->crlLock) != 0)
|
||||
return BAD_MUTEX_ERROR;
|
||||
crl->cm = cm;
|
||||
crl->crlList = NULL;
|
||||
crl->monitors[0].path = NULL;
|
||||
crl->monitors[1].path = NULL;
|
||||
#ifdef HAVE_CRL_MONITOR
|
||||
crl->tid = 0;
|
||||
#endif
|
||||
if (InitMutex(&crl->crlLock) != 0)
|
||||
return BAD_MUTEX_ERROR;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Initialze CRL Entry */
|
||||
static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl)
|
||||
{
|
||||
CYASSL_ENTER("FreeCRL_Entry");
|
||||
CYASSL_ENTER("InitCRL_Entry");
|
||||
|
||||
XMEMCPY(crle->issuerHash, dcrl->issuerHash, SHA_DIGEST_SIZE);
|
||||
XMEMCPY(crle->crlHash, dcrl->crlHash, MD5_DIGEST_SIZE);
|
||||
XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
|
||||
XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
|
||||
XMEMCPY(crle->issuerHash, dcrl->issuerHash, SHA_DIGEST_SIZE);
|
||||
XMEMCPY(crle->crlHash, dcrl->crlHash, MD5_DIGEST_SIZE);
|
||||
XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
|
||||
XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
|
||||
crle->lastDateFormat = dcrl->lastDateFormat;
|
||||
crle->nextDateFormat = dcrl->nextDateFormat;
|
||||
|
||||
crle->certs = dcrl->certs; /* take ownsership */
|
||||
dcrl->certs = NULL;
|
||||
crle->totalCerts = dcrl->totalCerts;
|
||||
crle->certs = dcrl->certs; /* take ownsership */
|
||||
dcrl->certs = NULL;
|
||||
crle->totalCerts = dcrl->totalCerts;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Free all CRL Entry resources */
|
||||
static void FreeCRL_Entry(CRL_Entry* crle)
|
||||
{
|
||||
RevokedCert* tmp = crle->certs;
|
||||
RevokedCert* tmp = crle->certs;
|
||||
|
||||
CYASSL_ENTER("FreeCRL_Entry");
|
||||
CYASSL_ENTER("FreeCRL_Entry");
|
||||
|
||||
while(tmp) {
|
||||
RevokedCert* next = tmp->next;
|
||||
|
@ -84,9 +91,15 @@ static void FreeCRL_Entry(CRL_Entry* crle)
|
|||
/* Free all CRL resources */
|
||||
void FreeCRL(CYASSL_CRL* crl)
|
||||
{
|
||||
CRL_Entry* tmp = crl->crlList;
|
||||
CRL_Entry* tmp = crl->crlList;
|
||||
|
||||
CYASSL_ENTER("FreeCRL");
|
||||
CYASSL_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;
|
||||
|
@ -95,6 +108,12 @@ void FreeCRL(CYASSL_CRL* crl)
|
|||
tmp = next;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CRL_MONITOR
|
||||
if (crl->tid != 0) {
|
||||
CYASSL_MSG("Canceling monitor thread");
|
||||
pthread_cancel(crl->tid);
|
||||
}
|
||||
#endif
|
||||
FreeMutex(&crl->crlLock);
|
||||
}
|
||||
|
||||
|
@ -102,202 +121,456 @@ void FreeCRL(CYASSL_CRL* crl)
|
|||
/* Is the cert ok with CRL, return 0 on success */
|
||||
int CheckCertCRL(CYASSL_CRL* crl, DecodedCert* cert)
|
||||
{
|
||||
CRL_Entry* crle;
|
||||
int foundEntry = 0;
|
||||
int revoked = 0;
|
||||
int ret = 0;
|
||||
CRL_Entry* crle;
|
||||
int foundEntry = 0;
|
||||
int revoked = 0;
|
||||
int ret = 0;
|
||||
|
||||
CYASSL_ENTER("CheckCertCRL");
|
||||
CYASSL_ENTER("CheckCertCRL");
|
||||
|
||||
if (LockMutex(&crl->crlLock) != 0) {
|
||||
CYASSL_MSG("LockMutex failed");
|
||||
return BAD_MUTEX_ERROR;
|
||||
}
|
||||
if (LockMutex(&crl->crlLock) != 0) {
|
||||
CYASSL_MSG("LockMutex failed");
|
||||
return BAD_MUTEX_ERROR;
|
||||
}
|
||||
|
||||
crle = crl->crlList;
|
||||
crle = crl->crlList;
|
||||
|
||||
while (crle) {
|
||||
if (XMEMCMP(crle->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0) {
|
||||
CYASSL_MSG("Found CRL Entry on list");
|
||||
foundEntry = 1;
|
||||
break;
|
||||
}
|
||||
crle = crle->next;
|
||||
}
|
||||
while (crle) {
|
||||
if (XMEMCMP(crle->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0) {
|
||||
CYASSL_MSG("Found CRL Entry on list");
|
||||
CYASSL_MSG("Checking next date validity");
|
||||
|
||||
if (foundEntry) {
|
||||
RevokedCert* rc = crle->certs;
|
||||
|
||||
while (rc) {
|
||||
if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
|
||||
CYASSL_MSG("Cert revoked");
|
||||
revoked = 1;
|
||||
ret = CRL_CERT_REVOKED;
|
||||
break;
|
||||
}
|
||||
rc = rc->next;
|
||||
}
|
||||
}
|
||||
|
||||
UnLockMutex(&crl->crlLock);
|
||||
|
||||
if (foundEntry == 0) {
|
||||
CYASSL_MSG("Couldn't find CRL for status check");
|
||||
ret = CRL_MISSING;
|
||||
if (crl->cm->cbMissingCRL) {
|
||||
char url[256];
|
||||
|
||||
CYASSL_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 {
|
||||
CYASSL_MSG("CRL url too long");
|
||||
if (!ValidateDate(crle->nextDate, crle->nextDateFormat, AFTER)) {
|
||||
CYASSL_MSG("CRL next date is no longer valid");
|
||||
ret = ASN_AFTER_DATE_E;
|
||||
}
|
||||
crl->cm->cbMissingCRL(url);
|
||||
}
|
||||
}
|
||||
else
|
||||
foundEntry = 1;
|
||||
break;
|
||||
}
|
||||
crle = crle->next;
|
||||
}
|
||||
|
||||
if (foundEntry) {
|
||||
RevokedCert* rc = crle->certs;
|
||||
|
||||
while (rc) {
|
||||
if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
|
||||
CYASSL_MSG("Cert revoked");
|
||||
revoked = 1;
|
||||
ret = CRL_CERT_REVOKED;
|
||||
break;
|
||||
}
|
||||
rc = rc->next;
|
||||
}
|
||||
}
|
||||
|
||||
UnLockMutex(&crl->crlLock);
|
||||
|
||||
if (foundEntry == 0) {
|
||||
CYASSL_MSG("Couldn't find CRL for status check");
|
||||
ret = CRL_MISSING;
|
||||
if (crl->cm->cbMissingCRL) {
|
||||
char url[256];
|
||||
|
||||
CYASSL_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 {
|
||||
CYASSL_MSG("CRL url too long");
|
||||
}
|
||||
crl->cm->cbMissingCRL(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Add Decoded CRL, 0 on success */
|
||||
static int AddCRL(CYASSL_CRL* crl, DecodedCRL* dcrl)
|
||||
{
|
||||
CRL_Entry* crle;
|
||||
CRL_Entry* crle;
|
||||
|
||||
CYASSL_ENTER("AddCRL");
|
||||
CYASSL_ENTER("AddCRL");
|
||||
|
||||
crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY);
|
||||
if (crle == NULL) {
|
||||
CYASSL_MSG("alloc CRL Entry failed");
|
||||
return -1;
|
||||
}
|
||||
crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY);
|
||||
if (crle == NULL) {
|
||||
CYASSL_MSG("alloc CRL Entry failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (InitCRL_Entry(crle, dcrl) < 0) {
|
||||
CYASSL_MSG("Init CRL Entry failed");
|
||||
return -1;
|
||||
}
|
||||
if (InitCRL_Entry(crle, dcrl) < 0) {
|
||||
CYASSL_MSG("Init CRL Entry failed");
|
||||
XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (LockMutex(&crl->crlLock) != 0) {
|
||||
CYASSL_MSG("LockMutex failed");
|
||||
FreeCRL_Entry(crle);
|
||||
return BAD_MUTEX_ERROR;
|
||||
}
|
||||
crle->next = crl->crlList;
|
||||
crl->crlList = crle;
|
||||
UnLockMutex(&crl->crlLock);
|
||||
if (LockMutex(&crl->crlLock) != 0) {
|
||||
CYASSL_MSG("LockMutex failed");
|
||||
FreeCRL_Entry(crle);
|
||||
XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY);
|
||||
return BAD_MUTEX_ERROR;
|
||||
}
|
||||
crle->next = crl->crlList;
|
||||
crl->crlList = crle;
|
||||
UnLockMutex(&crl->crlLock);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Load CRL File of type, SSL_SUCCESS on ok */
|
||||
int BufferLoadCRL(CYASSL_CRL* crl, const byte* buff, long sz, int type)
|
||||
{
|
||||
int ret = SSL_SUCCESS;
|
||||
const byte* myBuffer = buff; /* if DER ok, otherwise switch */
|
||||
buffer der;
|
||||
DecodedCRL dcrl;
|
||||
int ret = SSL_SUCCESS;
|
||||
const byte* myBuffer = buff; /* if DER ok, otherwise switch */
|
||||
buffer der;
|
||||
DecodedCRL dcrl;
|
||||
|
||||
der.buffer = NULL;
|
||||
der.buffer = NULL;
|
||||
|
||||
CYASSL_ENTER("BufferLoadCRL");
|
||||
CYASSL_ENTER("BufferLoadCRL");
|
||||
|
||||
if (crl == NULL || buff == NULL || sz == 0)
|
||||
return BAD_FUNC_ARG;
|
||||
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;
|
||||
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 {
|
||||
CYASSL_MSG("Pem to Der failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
InitDecodedCRL(&dcrl);
|
||||
ret = ParseCRL(&dcrl, myBuffer, sz);
|
||||
if (ret != 0) {
|
||||
CYASSL_MSG("ParseCRL error");
|
||||
}
|
||||
else {
|
||||
ret = AddCRL(crl, &dcrl);
|
||||
if (ret != 0) {
|
||||
CYASSL_MSG("AddCRL error");
|
||||
ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey);
|
||||
if (ret == 0) {
|
||||
myBuffer = der.buffer;
|
||||
sz = der.length;
|
||||
}
|
||||
}
|
||||
FreeDecodedCRL(&dcrl);
|
||||
else {
|
||||
CYASSL_MSG("Pem to Der failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (der.buffer)
|
||||
XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL);
|
||||
InitDecodedCRL(&dcrl);
|
||||
ret = ParseCRL(&dcrl, myBuffer, sz, crl->cm);
|
||||
if (ret != 0) {
|
||||
CYASSL_MSG("ParseCRL error");
|
||||
}
|
||||
else {
|
||||
ret = AddCRL(crl, &dcrl);
|
||||
if (ret != 0) {
|
||||
CYASSL_MSG("AddCRL error");
|
||||
}
|
||||
}
|
||||
FreeDecodedCRL(&dcrl);
|
||||
|
||||
if (ret == 0)
|
||||
return SSL_SUCCESS; /* convert */
|
||||
return ret;
|
||||
if (der.buffer)
|
||||
XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL);
|
||||
|
||||
if (ret == 0)
|
||||
return SSL_SUCCESS; /* convert */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_CRL_MONITOR
|
||||
|
||||
|
||||
/* read in new CRL entries and save new list */
|
||||
static int SwapLists(CYASSL_CRL* crl)
|
||||
{
|
||||
int ret;
|
||||
CYASSL_CRL tmp;
|
||||
CRL_Entry* newList;
|
||||
|
||||
if (InitCRL(&tmp, crl->cm) < 0) {
|
||||
CYASSL_MSG("Init tmp CRL failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (crl->monitors[0].path) {
|
||||
ret = LoadCRL(&tmp, crl->monitors[0].path, SSL_FILETYPE_PEM, 0);
|
||||
if (ret != SSL_SUCCESS) {
|
||||
CYASSL_MSG("PEM LoadCRL on dir change failed");
|
||||
FreeCRL(&tmp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (crl->monitors[1].path) {
|
||||
ret = LoadCRL(&tmp, crl->monitors[1].path, SSL_FILETYPE_ASN1, 0);
|
||||
if (ret != SSL_SUCCESS) {
|
||||
CYASSL_MSG("DER LoadCRL on dir change failed");
|
||||
FreeCRL(&tmp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (LockMutex(&crl->crlLock) != 0) {
|
||||
CYASSL_MSG("LockMutex failed");
|
||||
FreeCRL(&tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
newList = tmp.crlList;
|
||||
|
||||
/* swap lists */
|
||||
tmp.crlList = crl->crlList;
|
||||
crl->crlList = newList;
|
||||
|
||||
UnLockMutex(&crl->crlLock);
|
||||
|
||||
FreeCRL(&tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __MACH__
|
||||
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* OS X monitoring */
|
||||
static void* DoMonitor(void* arg)
|
||||
{
|
||||
int fPEM, fDER, kq;
|
||||
struct kevent change;
|
||||
|
||||
CYASSL_CRL* crl = (CYASSL_CRL*)arg;
|
||||
|
||||
CYASSL_ENTER("DoMonitor");
|
||||
|
||||
kq = kqueue();
|
||||
if (kq == -1) {
|
||||
CYASSL_MSG("kqueue failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fPEM = -1;
|
||||
fDER = -1;
|
||||
|
||||
if (crl->monitors[0].path) {
|
||||
fPEM = open(crl->monitors[0].path, O_EVTONLY);
|
||||
if (fPEM == -1) {
|
||||
CYASSL_MSG("PEM event dir open failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (crl->monitors[1].path) {
|
||||
fDER = open(crl->monitors[1].path, O_EVTONLY);
|
||||
if (fDER == -1) {
|
||||
CYASSL_MSG("DER event dir open failed");
|
||||
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);
|
||||
|
||||
for (;;) {
|
||||
struct kevent event;
|
||||
int numEvents = kevent(kq, &change, 1, &event, 1, NULL);
|
||||
|
||||
CYASSL_MSG("Got kevent");
|
||||
|
||||
if (numEvents == -1) {
|
||||
CYASSL_MSG("kevent problem, continue");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SwapLists(crl) < 0) {
|
||||
CYASSL_MSG("SwapLists problem, continue");
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#elif __linux__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* linux monitoring */
|
||||
static void* DoMonitor(void* arg)
|
||||
{
|
||||
int notifyFd;
|
||||
int wd;
|
||||
CYASSL_CRL* crl = (CYASSL_CRL*)arg;
|
||||
|
||||
CYASSL_ENTER("DoMonitor");
|
||||
|
||||
notifyFd = inotify_init();
|
||||
if (notifyFd < 0) {
|
||||
CYASSL_MSG("inotify failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (crl->monitors[0].path) {
|
||||
wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
|
||||
IN_DELETE);
|
||||
if (wd < 0) {
|
||||
CYASSL_MSG("PEM notify add watch failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (crl->monitors[1].path) {
|
||||
wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
|
||||
IN_DELETE);
|
||||
if (wd < 0) {
|
||||
CYASSL_MSG("DER notify add watch failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
char buffer[8192];
|
||||
int length = read(notifyFd, buffer, sizeof(buffer));
|
||||
|
||||
CYASSL_MSG("Got notify event");
|
||||
|
||||
if (length < 0) {
|
||||
CYASSL_MSG("notify read problem, continue");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SwapLists(crl) < 0) {
|
||||
CYASSL_MSG("SwapLists problem, continue");
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* MACH or linux */
|
||||
|
||||
|
||||
/* Start Monitoring the CRL path(s) in a thread */
|
||||
static int StartMonitorCRL(CYASSL_CRL* crl)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
|
||||
CYASSL_ENTER("StartMonitorCRL");
|
||||
|
||||
if (crl == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (crl->tid != 0) {
|
||||
CYASSL_MSG("Monitor thread already running");
|
||||
return MONITOR_RUNNING_E;
|
||||
}
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
if (pthread_create(&crl->tid, &attr, DoMonitor, crl) != 0) {
|
||||
CYASSL_MSG("Thread creation error");
|
||||
return THREAD_CREATE_E;
|
||||
}
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#else /* HAVE_CRL_MONITOR */
|
||||
|
||||
static int StartMonitorCRL(CYASSL_CRL* crl)
|
||||
{
|
||||
CYASSL_ENTER("StartMonitorCRL");
|
||||
CYASSL_MSG("Not compiled in");
|
||||
|
||||
return NOT_COMPILED_IN;
|
||||
}
|
||||
|
||||
#endif /* HAVE_CRL_MONITOR */
|
||||
|
||||
|
||||
/* Load CRL path files of type, SSL_SUCCESS on ok */
|
||||
int LoadCRL(CYASSL_CRL* crl, const char* path, int type, int monitor)
|
||||
{
|
||||
struct dirent* entry;
|
||||
DIR* dir;
|
||||
int ret = SSL_SUCCESS;
|
||||
struct dirent* entry;
|
||||
DIR* dir;
|
||||
int ret = SSL_SUCCESS;
|
||||
|
||||
CYASSL_ENTER("LoadCRL");
|
||||
if (crl == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
CYASSL_ENTER("LoadCRL");
|
||||
if (crl == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
dir = opendir(path);
|
||||
if (dir == NULL) {
|
||||
CYASSL_MSG("opendir path crl load failed");
|
||||
return BAD_PATH_ERROR;
|
||||
}
|
||||
while ( ret == SSL_SUCCESS && (entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_type & DT_REG) {
|
||||
char name[MAX_FILENAME_SZ];
|
||||
dir = opendir(path);
|
||||
if (dir == NULL) {
|
||||
CYASSL_MSG("opendir path crl load failed");
|
||||
return BAD_PATH_ERROR;
|
||||
}
|
||||
while ( (entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_type & DT_REG) {
|
||||
char name[MAX_FILENAME_SZ];
|
||||
|
||||
if (type == SSL_FILETYPE_PEM) {
|
||||
if (strstr(entry->d_name, ".pem") == NULL) {
|
||||
CYASSL_MSG("not .pem file, skipping");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (strstr(entry->d_name, ".der") == NULL &&
|
||||
strstr(entry->d_name, ".crl") == NULL) {
|
||||
if (type == SSL_FILETYPE_PEM) {
|
||||
if (strstr(entry->d_name, ".pem") == NULL) {
|
||||
CYASSL_MSG("not .pem file, skipping");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (strstr(entry->d_name, ".der") == NULL &&
|
||||
strstr(entry->d_name, ".crl") == NULL) {
|
||||
|
||||
CYASSL_MSG("not .der or .crl file, skipping");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
CYASSL_MSG("not .der or .crl file, skipping");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
XMEMSET(name, 0, sizeof(name));
|
||||
XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2);
|
||||
XSTRNCAT(name, "/", 1);
|
||||
XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2);
|
||||
XMEMSET(name, 0, sizeof(name));
|
||||
XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2);
|
||||
XSTRNCAT(name, "/", 1);
|
||||
XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2);
|
||||
|
||||
ret = ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl);
|
||||
}
|
||||
}
|
||||
|
||||
if (monitor) {
|
||||
CYASSL_MSG("monitor path requested");
|
||||
if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl)
|
||||
!= SSL_SUCCESS) {
|
||||
CYASSL_MSG("CRL file load failed, continuing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SSL_SUCCESS;
|
||||
if (monitor & CYASSL_CRL_MONITOR) {
|
||||
CYASSL_MSG("monitor path requested");
|
||||
|
||||
if (type == SSL_FILETYPE_PEM) {
|
||||
crl->monitors[0].path = strdup(path);
|
||||
crl->monitors[0].type = SSL_FILETYPE_PEM;
|
||||
if (crl->monitors[0].path == NULL)
|
||||
ret = MEMORY_E;
|
||||
} else {
|
||||
crl->monitors[1].path = strdup(path);
|
||||
crl->monitors[1].type = SSL_FILETYPE_ASN1;
|
||||
if (crl->monitors[1].path == NULL)
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
|
||||
if (monitor & CYASSL_CRL_START_MON) {
|
||||
CYASSL_MSG("start monitoring requested");
|
||||
|
||||
ret = StartMonitorCRL(crl);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* HAVE_CRL */
|
||||
|
|
|
@ -36,6 +36,10 @@ if BUILD_AESNI
|
|||
src_libcyassl_la_SOURCES += ctaocrypt/src/aes_asm.s
|
||||
endif
|
||||
|
||||
if BUILD_MD2
|
||||
src_libcyassl_la_SOURCES += ctaocrypt/src/md2.c
|
||||
endif
|
||||
|
||||
if BUILD_RIPEMD
|
||||
src_libcyassl_la_SOURCES += ctaocrypt/src/ripemd.c
|
||||
endif
|
||||
|
@ -74,3 +78,8 @@ if BUILD_CRL
|
|||
src_libcyassl_la_SOURCES += src/crl.c
|
||||
endif
|
||||
|
||||
if BUILD_CRL_MONITOR
|
||||
src_libcyassl_la_CFLAGS += $(PTHREAD_CFLAGS)
|
||||
src_libcyassl_la_LIBADD += $(PTHREAD_LIBS)
|
||||
endif
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -200,6 +200,52 @@ int EmbedSend(char *buf, int sz, void *ctx)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CYASSL_DTLS
|
||||
|
||||
#include <cyassl/ctaocrypt/sha.h>
|
||||
|
||||
/* The DTLS Generate Cookie callback
|
||||
* return : number of bytes copied into buf, or error
|
||||
*/
|
||||
int EmbedGenerateCookie(byte *buf, int sz, void *ctx)
|
||||
{
|
||||
CYASSL* ssl = (CYASSL*)ctx;
|
||||
int sd = ssl->wfd;
|
||||
struct sockaddr_storage peer;
|
||||
socklen_t peerSz = sizeof(peer);
|
||||
byte cookieSrc[sizeof(struct in6_addr) + sizeof(int)];
|
||||
int cookieSrcSz = 0;
|
||||
Sha sha;
|
||||
|
||||
getpeername(sd, (struct sockaddr*)&peer, &peerSz);
|
||||
|
||||
if (peer.ss_family == AF_INET) {
|
||||
struct sockaddr_in *s = (struct sockaddr_in*)&peer;
|
||||
|
||||
cookieSrcSz = sizeof(struct in_addr) + sizeof(s->sin_port);
|
||||
XMEMCPY(cookieSrc, &s->sin_port, sizeof(s->sin_port));
|
||||
XMEMCPY(cookieSrc + sizeof(s->sin_port),
|
||||
&s->sin_addr, sizeof(struct in_addr));
|
||||
}
|
||||
else if (peer.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *s = (struct sockaddr_in6*)&peer;
|
||||
|
||||
cookieSrcSz = sizeof(struct in6_addr) + sizeof(s->sin6_port);
|
||||
XMEMCPY(cookieSrc, &s->sin6_port, sizeof(s->sin6_port));
|
||||
XMEMCPY(cookieSrc + sizeof(s->sin6_port),
|
||||
&s->sin6_addr, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
InitSha(&sha);
|
||||
ShaUpdate(&sha, cookieSrc, cookieSrcSz);
|
||||
ShaFinal(&sha, buf);
|
||||
|
||||
return SHA_DIGEST_SIZE;
|
||||
}
|
||||
|
||||
#endif /* CYASSL_DTLS */
|
||||
|
||||
|
||||
#endif /* CYASSL_USER_IO */
|
||||
|
||||
CYASSL_API void CyaSSL_SetIORecv(CYASSL_CTX *ctx, CallbackIORecv CBIORecv)
|
||||
|
|
|
@ -311,6 +311,142 @@ int SetCipherSpecs(CYASSL* ssl)
|
|||
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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_SZ;
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC");
|
||||
return UNSUPPORTED_SUITE;
|
||||
|
@ -646,6 +782,74 @@ int SetCipherSpecs(CYASSL* ssl)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
case TLS_RSA_WITH_AES_128_GCM_SHA256 :
|
||||
ssl->specs.bulk_cipher_algorithm = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_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 = 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 = AES_GCM_IMP_IV_SZ;
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs");
|
||||
return UNSUPPORTED_SUITE;
|
||||
|
@ -802,6 +1006,23 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_AESGCM
|
||||
if (specs->bulk_cipher_algorithm == aes_gcm) {
|
||||
if (side == CLIENT_END) {
|
||||
AesGcmSetKey(&enc->aes, keys->client_write_key, specs->key_size,
|
||||
keys->client_write_IV);
|
||||
AesGcmSetKey(&dec->aes, keys->server_write_key, specs->key_size,
|
||||
keys->server_write_IV);
|
||||
}
|
||||
else {
|
||||
AesGcmSetKey(&enc->aes, keys->server_write_key, specs->key_size,
|
||||
keys->server_write_IV);
|
||||
AesGcmSetKey(&dec->aes, keys->client_write_key, specs->key_size,
|
||||
keys->client_write_IV);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
keys->sequence_number = 0;
|
||||
keys->peer_sequence_number = 0;
|
||||
keys->encryptionOn = 0;
|
||||
|
@ -813,12 +1034,24 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
|
|||
/* TLS can call too */
|
||||
int StoreKeys(CYASSL* ssl, const byte* keyData)
|
||||
{
|
||||
int sz = ssl->specs.hash_size, i;
|
||||
int sz, i = 0;
|
||||
|
||||
XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz);
|
||||
i = sz;
|
||||
XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
|
||||
i += sz;
|
||||
if (ssl->specs.cipher_type != aead) {
|
||||
sz = ssl->specs.hash_size;
|
||||
XMEMCPY(ssl->keys.client_write_MAC_secret,&keyData[i], sz);
|
||||
i += sz;
|
||||
XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
|
||||
i += sz;
|
||||
}
|
||||
#ifdef BUILD_AESGCM
|
||||
else if (ssl->specs.bulk_cipher_algorithm == aes_gcm) {
|
||||
byte iv[AES_GCM_EXP_IV_SZ];
|
||||
|
||||
/* Initialize the AES-GCM explicit IV to a random number. */
|
||||
RNG_GenerateBlock(&ssl->rng, iv, sizeof(iv));
|
||||
AesGcmSetExpIV(&ssl->encrypt.aes, iv);
|
||||
}
|
||||
#endif
|
||||
|
||||
sz = ssl->specs.key_size;
|
||||
XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz);
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
|
||||
#include <cyassl/error.h>
|
||||
#include <cyassl/ocsp.h>
|
||||
#include <cyassl/internal.h>
|
||||
|
@ -40,7 +42,6 @@
|
|||
#include <sys/socket.h>
|
||||
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
CYASSL_API int ocsp_test(unsigned char* buf, int sz);
|
||||
#define CYASSL_OCSP_ENABLE 0x0001 /* Enable OCSP lookups */
|
||||
#define CYASSL_OCSP_URL_OVERRIDE 0x0002 /* Use the override URL instead of URL
|
||||
|
@ -51,29 +52,6 @@ typedef struct sockaddr_in SOCKADDR_IN_T;
|
|||
#define SOCKET_T unsigned int
|
||||
|
||||
|
||||
int ocsp_test(unsigned char* buf, int sz)
|
||||
{
|
||||
CYASSL_OCSP ocsp;
|
||||
OcspResponse resp;
|
||||
int result;
|
||||
|
||||
CyaSSL_OCSP_Init(&ocsp);
|
||||
InitOcspResponse(&resp, buf, sz, NULL);
|
||||
|
||||
ocsp.enabled = 1;
|
||||
ocsp.useOverrideUrl = 1;
|
||||
CyaSSL_OCSP_set_override_url(&ocsp, "http://ocsp.example.com:8080/bob");
|
||||
CyaSSL_OCSP_Lookup_Cert(&ocsp, NULL);
|
||||
|
||||
result = OcspResponseDecode(&resp);
|
||||
|
||||
FreeOcspResponse(&resp);
|
||||
CyaSSL_OCSP_Cleanup(&ocsp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_OCSP_Init(CYASSL_OCSP* ocsp)
|
||||
{
|
||||
if (ocsp != NULL) {
|
||||
|
@ -85,62 +63,105 @@ int CyaSSL_OCSP_Init(CYASSL_OCSP* ocsp)
|
|||
}
|
||||
|
||||
|
||||
static void FreeOCSP_Entry(OCSP_Entry* ocspe)
|
||||
{
|
||||
CertStatus* tmp = ocspe->status;
|
||||
|
||||
CYASSL_ENTER("FreeOCSP_Entry");
|
||||
|
||||
while (tmp) {
|
||||
CertStatus* next = tmp->next;
|
||||
XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
|
||||
tmp = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CyaSSL_OCSP_Cleanup(CYASSL_OCSP* ocsp)
|
||||
{
|
||||
OCSP_Entry* tmp = ocsp->ocspList;
|
||||
|
||||
ocsp->enabled = 0;
|
||||
while (tmp) {
|
||||
OCSP_Entry* next = tmp->next;
|
||||
FreeOCSP_Entry(tmp);
|
||||
XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
||||
tmp = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int decode_url(const char* url, int urlSz,
|
||||
char* outName, char* outPath, int* outPort)
|
||||
{
|
||||
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/" */
|
||||
if (XSTRNCMP(url, "http://", 7) == 0) {
|
||||
cur = 7;
|
||||
} else cur = 0;
|
||||
|
||||
i = 0;
|
||||
while (url[cur] != 0 && url[cur] != ':' && url[cur] != '/') {
|
||||
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;
|
||||
i = 0;
|
||||
cur++;
|
||||
while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
|
||||
i < 6) {
|
||||
port[i++] = url[cur++];
|
||||
}
|
||||
|
||||
*outPort = 0;
|
||||
for (j = 0; j < i; j++) {
|
||||
if (port[j] < '0' || port[j] > '9') return -1;
|
||||
*outPort = (*outPort * 10) + (port[j] - '0');
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_OCSP_set_override_url(CYASSL_OCSP* ocsp, const char* url)
|
||||
{
|
||||
if (ocsp != NULL && url != NULL) {
|
||||
int i, cur, hostname;
|
||||
|
||||
/* need to break the url down into scheme, address, and port */
|
||||
/* "http://example.com:8080/" */
|
||||
if (XSTRNCMP(url, "http://", 7) == 0) {
|
||||
cur = 7;
|
||||
} else cur = 0;
|
||||
|
||||
i = 0;
|
||||
while (url[cur] != 0 && url[cur] != ':' && url[cur] != '/') {
|
||||
ocsp->overrideName[i++] = url[cur++];
|
||||
}
|
||||
ocsp->overrideName[i] = 0;
|
||||
/* Need to pick out the path after the domain name */
|
||||
|
||||
if (url[cur] == ':') {
|
||||
char port[6];
|
||||
int j;
|
||||
i = 0;
|
||||
cur++;
|
||||
while (url[cur] != 0 && url[cur] != '/' && i < 6) {
|
||||
port[i++] = url[cur++];
|
||||
}
|
||||
|
||||
ocsp->overridePort = 0;
|
||||
for (j = 0; j < i; j++) {
|
||||
if (port[j] < '0' || port[j] > '9') return -1;
|
||||
ocsp->overridePort =
|
||||
(ocsp->overridePort * 10) + (port[j] - '0');
|
||||
}
|
||||
}
|
||||
else
|
||||
ocsp->overridePort = 80;
|
||||
|
||||
if (url[cur] == '/') {
|
||||
i = 0;
|
||||
while (url[cur] != 0 && i < 80) {
|
||||
ocsp->overridePath[i++] = url[cur++];
|
||||
}
|
||||
ocsp->overridePath[i] = 0;
|
||||
}
|
||||
else {
|
||||
ocsp->overridePath[0] = '/';
|
||||
ocsp->overridePath[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
if (ocsp != NULL) {
|
||||
int urlSz = strlen(url);
|
||||
decode_url(url, urlSz,
|
||||
ocsp->overrideName, ocsp->overridePath, &ocsp->overridePort);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -164,8 +185,9 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, SOCKADDR_IN_T* addr,
|
|||
entry->h_length);
|
||||
host = inet_ntoa(tmp.sin_addr);
|
||||
}
|
||||
else
|
||||
else {
|
||||
CYASSL_MSG("no entry for host");
|
||||
}
|
||||
}
|
||||
|
||||
*sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
|
||||
|
@ -185,13 +207,14 @@ static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port)
|
|||
SOCKADDR_IN_T addr;
|
||||
tcp_socket(sockfd, &addr, ip, port);
|
||||
|
||||
if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
|
||||
if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) {
|
||||
CYASSL_MSG("tcp connect failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int build_http_request(CYASSL_OCSP* ocsp, int ocspReqSz,
|
||||
byte* buf, int bufSize)
|
||||
static int build_http_request(const char* domainName, const char* path,
|
||||
int ocspReqSz, byte* buf, int bufSize)
|
||||
{
|
||||
return snprintf((char*)buf, bufSize,
|
||||
"POST %s HTTP/1.1\r\n"
|
||||
|
@ -199,47 +222,27 @@ static int build_http_request(CYASSL_OCSP* ocsp, int ocspReqSz,
|
|||
"Content-Length: %d\r\n"
|
||||
"Content-Type: application/ocsp-request\r\n"
|
||||
"\r\n",
|
||||
ocsp->overridePath, ocsp->overrideName, ocspReqSz);
|
||||
path, domainName, ocspReqSz);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const char foo[] = \
|
||||
"\x30\x81\xB7\x30\x81\xB4\x30\x81\x8C\x30\x44\x30\x42\x30\x09\x06\x05\x2B\x0E\x03" \
|
||||
"\x02\x1A\x05\x00\x04\x14\x49\x2D\x52\x83\x4B\x40\x37\xF5\xA9\x9E\x26\xA2\x3E\x48" \
|
||||
"\x2F\x2E\x37\x34\xC9\x54\x04\x14\x21\xA2\x25\xEE\x57\x38\x34\x5A\x24\x9D\xF3\x7C" \
|
||||
"\x18\x60\x59\x7A\x04\x3D\xF5\x69\x02\x09\x00\x89\x5A\xA2\xBD\xFE\x26\x8B\xEE\x30" \
|
||||
"\x44\x30\x42\x30\x09\x06\x05\x2B\x0E\x03\x02\x1A\x05\x00\x04\x14\x49\x2D\x52\x83" \
|
||||
"\x4B\x40\x37\xF5\xA9\x9E\x26\xA2\x3E\x48\x2F\x2E\x37\x34\xC9\x54\x04\x14\x21\xA2" \
|
||||
"\x25\xEE\x57\x38\x34\x5A\x24\x9D\xF3\x7C\x18\x60\x59\x7A\x04\x3D\xF5\x69\x02\x09" \
|
||||
"\x00\x89\x5A\xA2\xBD\xFE\x26\x8B\xEF\xA2\x23\x30\x21\x30\x1F\x06\x09\x2B\x06\x01" \
|
||||
"\x05\x05\x07\x30\x01\x02\x04\x12\x04\x10\x20\x56\x47\x19\x65\x33\xB6\xB5\xAD\x39" \
|
||||
"\x1F\x21\x65\xE0\x44\x1E";
|
||||
|
||||
|
||||
static int build_ocsp_request(CYASSL_OCSP* ocsp, byte* buf, int bufSz)
|
||||
{
|
||||
memcpy(buf, foo, sizeof(foo));
|
||||
return sizeof(foo) - 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static byte* decode_http_response(byte* httpBuf, int httpBufSz, int* ocspRespSz)
|
||||
static int decode_http_response(byte* httpBuf, int httpBufSz, byte** dst)
|
||||
{
|
||||
int idx = 0;
|
||||
int stop = 0;
|
||||
int len = 0;
|
||||
byte* contentType = NULL;
|
||||
byte* contentLength = NULL;
|
||||
byte* content = NULL;
|
||||
char* buf = (char*)httpBuf; /* kludge so I'm not constantly casting */
|
||||
|
||||
if (strncasecmp(buf, "HTTP/1", 6) != 0)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
idx = 9; /* sets to the first byte after "HTTP/1.X ", which should be the
|
||||
* HTTP result code */
|
||||
|
||||
if (strncasecmp(&buf[idx], "200 OK", 6) != 0)
|
||||
return NULL;
|
||||
return 0;
|
||||
|
||||
idx += 8;
|
||||
|
||||
|
@ -254,18 +257,16 @@ static byte* decode_http_response(byte* httpBuf, int httpBufSz, int* ocspRespSz)
|
|||
idx += 13;
|
||||
if (buf[idx] == ' ') idx++;
|
||||
if (strncasecmp(&buf[idx], "application/ocsp-response", 25) != 0)
|
||||
return NULL;
|
||||
return 0;
|
||||
idx += 27;
|
||||
} else if (contentLength == NULL &&
|
||||
strncasecmp(&buf[idx], "Content-Length:", 15) == 0) {
|
||||
int len = 0;
|
||||
idx += 15;
|
||||
if (buf[idx] == ' ') idx++;
|
||||
while (buf[idx] > '0' && buf[idx] < '9' && idx < httpBufSz) {
|
||||
while (buf[idx] >= '0' && buf[idx] <= '9' && idx < httpBufSz) {
|
||||
len = (len * 10) + (buf[idx] - '0');
|
||||
idx++;
|
||||
}
|
||||
*ocspRespSz = len;
|
||||
idx += 2; /* skip the crlf */
|
||||
} else {
|
||||
/* Advance idx past the next \r\n */
|
||||
|
@ -275,78 +276,251 @@ static byte* decode_http_response(byte* httpBuf, int httpBufSz, int* ocspRespSz)
|
|||
}
|
||||
}
|
||||
}
|
||||
return &httpBuf[idx];
|
||||
|
||||
if (len > 0) {
|
||||
*dst = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_IN_BUFFER);
|
||||
XMEMCPY(*dst, httpBuf + idx, len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
|
||||
{
|
||||
CYASSL_ENTER("InitOCSP_Entry");
|
||||
|
||||
ocspe->next = NULL;
|
||||
XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
|
||||
XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
|
||||
ocspe->status = NULL;
|
||||
ocspe->totalStatus = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static OCSP_Entry* find_ocsp_entry(CYASSL_OCSP* ocsp, DecodedCert* cert)
|
||||
{
|
||||
OCSP_Entry* entry = ocsp->ocspList;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
if (XMEMCMP(entry->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
|
||||
&& XMEMCMP(entry->issuerKeyHash, cert->issuerKeyHash,
|
||||
SHA_DIGEST_SIZE) == 0)
|
||||
{
|
||||
CYASSL_MSG("Found OCSP responder");
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
CYASSL_MSG("Add a new OCSP entry");
|
||||
entry = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
|
||||
NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
||||
if (entry != NULL)
|
||||
{
|
||||
InitOCSP_Entry(entry, cert);
|
||||
entry->next = ocsp->ocspList;
|
||||
ocsp->ocspList = entry;
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
static CertStatus* find_cert_status(OCSP_Entry* ocspe, DecodedCert* cert)
|
||||
{
|
||||
CertStatus* stat = ocspe->status;
|
||||
|
||||
while (stat)
|
||||
{
|
||||
if(stat->serialSz == cert->serialSz &&
|
||||
(XMEMCMP(stat->serial, cert->serial, cert->serialSz) == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
stat = stat->next;
|
||||
}
|
||||
}
|
||||
if (stat == NULL)
|
||||
{
|
||||
stat = (CertStatus*)XMALLOC(sizeof(CertStatus),
|
||||
NULL, DYNAMIC_TYPE_OCSP_STATUS);
|
||||
if (stat != NULL)
|
||||
{
|
||||
XMEMCPY(stat->serial, cert->serial, cert->serialSz);
|
||||
stat->serialSz = cert->serialSz;
|
||||
stat->status = -1;
|
||||
stat->nextDate[0] = 0;
|
||||
ocspe->totalStatus++;
|
||||
|
||||
stat->next = ocspe->status;
|
||||
ocspe->status = stat;
|
||||
}
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
#define SCRATCH_BUFFER_SIZE 2048
|
||||
|
||||
int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert)
|
||||
static int http_ocsp_transaction(CYASSL_OCSP* ocsp, DecodedCert* cert,
|
||||
byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
|
||||
{
|
||||
SOCKET_T sfd = -1;
|
||||
byte buf[SCRATCH_BUFFER_SIZE];
|
||||
byte* httpBuf = &buf[0];
|
||||
int httpBufSz = SCRATCH_BUFFER_SIZE/4;
|
||||
byte* ocspReqBuf = &buf[httpBufSz];
|
||||
int ocspReqSz = SCRATCH_BUFFER_SIZE - httpBufSz;
|
||||
OcspResponse ocspResponse;
|
||||
int result = CERT_UNKNOWN;
|
||||
byte httpBuf[SCRATCH_BUFFER_SIZE];
|
||||
int httpBufSz = SCRATCH_BUFFER_SIZE;
|
||||
char domainName[80], path[80];
|
||||
int port, ocspRespSz;
|
||||
|
||||
/* If OCSP lookups are disabled, return success. */
|
||||
if (!ocsp->enabled) {
|
||||
CYASSL_MSG("OCSP lookup disabled, assuming CERT_GOOD");
|
||||
return CERT_GOOD;
|
||||
if (ocsp->useOverrideUrl || cert->extAuthInfo == NULL) {
|
||||
if (ocsp->overrideName != NULL) {
|
||||
XMEMCPY(domainName, ocsp->overrideName, 80);
|
||||
XMEMCPY(path, ocsp->overridePath, 80);
|
||||
port = ocsp->overridePort;
|
||||
} else
|
||||
return OCSP_NEED_URL;
|
||||
} else {
|
||||
if (!decode_url((const char*)cert->extAuthInfo, cert->extAuthInfoSz,
|
||||
domainName, path, &port))
|
||||
return OCSP_NEED_URL;
|
||||
}
|
||||
|
||||
/* If OCSP lookups are enabled, but URL Override is disabled, return
|
||||
** a failure. Need to have an override URL for right now. */
|
||||
if (!ocsp->useOverrideUrl || cert == NULL) {
|
||||
CYASSL_MSG("OCSP lookup enabled, but URL Override disabled");
|
||||
return CERT_UNKNOWN;
|
||||
}
|
||||
httpBufSz = build_http_request(domainName, path, ocspReqSz,
|
||||
httpBuf, httpBufSz);
|
||||
|
||||
XMEMCPY(ocsp->status[0].issuerHash, cert->issuerHash, SHA_SIZE);
|
||||
XMEMCPY(ocsp->status[0].issuerKeyHash, cert->issuerKeyHash, SHA_SIZE);
|
||||
XMEMCPY(ocsp->status[0].serial, cert->serial, cert->serialSz);
|
||||
ocsp->status[0].serialSz = cert->serialSz;
|
||||
ocsp->statusLen = 1;
|
||||
|
||||
/*ocspReqSz = build_ocsp_request(ocsp, ocspReqBuf, ocspReqSz);*/
|
||||
ocspReqSz = EncodeOcspRequest(cert, ocspReqBuf, ocspReqSz);
|
||||
httpBufSz = build_http_request(ocsp, ocspReqSz, httpBuf, httpBufSz);
|
||||
|
||||
tcp_connect(&sfd, ocsp->overrideName, ocsp->overridePort);
|
||||
tcp_connect(&sfd, domainName, port);
|
||||
if (sfd > 0) {
|
||||
int written;
|
||||
written = write(sfd, httpBuf, httpBufSz);
|
||||
if (written == httpBufSz) {
|
||||
written = write(sfd, ocspReqBuf, ocspReqSz);
|
||||
if (written == ocspReqSz) {
|
||||
httpBufSz = read(sfd, buf, SCRATCH_BUFFER_SIZE);
|
||||
httpBufSz = read(sfd, httpBuf, SCRATCH_BUFFER_SIZE);
|
||||
if (httpBufSz > 0) {
|
||||
ocspReqBuf = decode_http_response(buf, httpBufSz,
|
||||
&ocspReqSz);
|
||||
ocspRespSz = decode_http_response(httpBuf, httpBufSz,
|
||||
ocspRespBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
close(sfd);
|
||||
if (ocspReqBuf == NULL) {
|
||||
if (ocspRespSz == 0) {
|
||||
CYASSL_MSG("HTTP response was not OK, no OCSP response");
|
||||
return CERT_UNKNOWN;
|
||||
return OCSP_LOOKUP_FAIL;
|
||||
}
|
||||
} else {
|
||||
CYASSL_MSG("OCSP Responder connection failed");
|
||||
return CERT_UNKNOWN;
|
||||
return OCSP_LOOKUP_FAIL;
|
||||
}
|
||||
|
||||
InitOcspResponse(&ocspResponse, ocspReqBuf, ocspReqSz, NULL);
|
||||
return ocspRespSz;
|
||||
}
|
||||
|
||||
|
||||
static int xstat2err(int stat)
|
||||
{
|
||||
switch (stat) {
|
||||
case CERT_GOOD:
|
||||
return 0;
|
||||
break;
|
||||
case CERT_REVOKED:
|
||||
return OCSP_CERT_REVOKED;
|
||||
break;
|
||||
default:
|
||||
return OCSP_CERT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert)
|
||||
{
|
||||
byte ocspReqBuf[SCRATCH_BUFFER_SIZE];
|
||||
int ocspReqSz = SCRATCH_BUFFER_SIZE;
|
||||
byte* ocspRespBuf = NULL;
|
||||
int ocspRespSz;
|
||||
OcspRequest ocspRequest;
|
||||
OcspResponse ocspResponse;
|
||||
int result = 0;
|
||||
OCSP_Entry* ocspe;
|
||||
CertStatus* certStatus;
|
||||
|
||||
/* If OCSP lookups are disabled, return success. */
|
||||
if (!ocsp->enabled) {
|
||||
CYASSL_MSG("OCSP lookup disabled, assuming CERT_GOOD");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ocspe = find_ocsp_entry(ocsp, cert);
|
||||
if (ocspe == NULL) {
|
||||
CYASSL_MSG("alloc OCSP entry failed");
|
||||
return MEMORY_ERROR;
|
||||
}
|
||||
|
||||
certStatus = find_cert_status(ocspe, cert);
|
||||
if (certStatus == NULL)
|
||||
{
|
||||
CYASSL_MSG("alloc OCSP cert status failed");
|
||||
return MEMORY_ERROR;
|
||||
}
|
||||
|
||||
if (certStatus->status != -1)
|
||||
{
|
||||
if (!ValidateDate(certStatus->thisDate,
|
||||
certStatus->thisDateFormat, BEFORE) ||
|
||||
(certStatus->nextDate[0] == 0) ||
|
||||
!ValidateDate(certStatus->nextDate,
|
||||
certStatus->nextDateFormat, AFTER))
|
||||
{
|
||||
CYASSL_MSG("\tinvalid status date, looking up cert");
|
||||
certStatus->status = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
CYASSL_MSG("\tusing cached status");
|
||||
result = xstat2err(certStatus->status);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
InitOcspRequest(&ocspRequest, cert, ocspReqBuf, ocspReqSz);
|
||||
ocspReqSz = EncodeOcspRequest(&ocspRequest);
|
||||
result = http_ocsp_transaction(ocsp, cert,
|
||||
ocspReqBuf, ocspReqSz, &ocspRespBuf);
|
||||
if (result < 0) return result;
|
||||
/* If the transaction failed, return that result. */
|
||||
|
||||
InitOcspResponse(&ocspResponse, certStatus, ocspRespBuf, ocspRespSz);
|
||||
OcspResponseDecode(&ocspResponse);
|
||||
|
||||
if (ocspResponse.responseStatus != OCSP_SUCCESSFUL) {
|
||||
CYASSL_MSG("OCSP Responder failure");
|
||||
result = OCSP_LOOKUP_FAIL;
|
||||
} else {
|
||||
result = ocspResponse.certStatus[0];
|
||||
if (CompareOcspReqResp(&ocspRequest, &ocspResponse) == 0)
|
||||
{
|
||||
result = xstat2err(ocspResponse.status->status);
|
||||
}
|
||||
else
|
||||
{
|
||||
CYASSL_MSG("OCSP Response incorrect for Request");
|
||||
result = OCSP_LOOKUP_FAIL;
|
||||
}
|
||||
}
|
||||
if (ocspReqBuf != NULL) {
|
||||
XFREE(ocspRespBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
|
||||
}
|
||||
FreeOcspResponse(&ocspResponse);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,17 @@
|
|||
#include <cyassl/sniffer.h>
|
||||
#include <cyassl/sniffer_error.h>
|
||||
|
||||
|
||||
#ifndef min
|
||||
|
||||
static INLINE word32 min(word32 a, word32 b)
|
||||
{
|
||||
return a > b ? b : a;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Misc constants */
|
||||
enum {
|
||||
MAX_SERVER_ADDRESS = 128, /* maximum server address length */
|
||||
|
@ -61,6 +72,9 @@ enum {
|
|||
PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */
|
||||
FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */
|
||||
SNIFFER_TIMEOUT = 900, /* Cache unclosed Sessions for 15 minutes */
|
||||
TICKET_HINT_LEN = 4, /* Session Ticket Hint length */
|
||||
EXT_TYPE_SZ = 2, /* Extension length */
|
||||
TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */
|
||||
};
|
||||
|
||||
|
||||
|
@ -196,6 +210,14 @@ static const char* const msgTable[] =
|
|||
|
||||
/* 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"
|
||||
};
|
||||
|
||||
|
||||
|
@ -248,7 +270,7 @@ typedef struct Flags {
|
|||
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 fatalError; /* fatal error state */
|
||||
} Flags;
|
||||
|
||||
|
||||
|
@ -279,7 +301,8 @@ typedef struct SnifferSession {
|
|||
time_t bornOn; /* born on ticks */
|
||||
PacketBuffer* cliReassemblyList; /* client out of order packets */
|
||||
PacketBuffer* srvReassemblyList; /* server out of order packets */
|
||||
struct SnifferSession* next; /* for hash table list */
|
||||
struct SnifferSession* next; /* for hash table list */
|
||||
byte* ticketID; /* mac ID of session ticket */
|
||||
} SnifferSession;
|
||||
|
||||
|
||||
|
@ -347,6 +370,8 @@ static void FreeSnifferSession(SnifferSession* session)
|
|||
|
||||
FreePacketList(session->cliReassemblyList);
|
||||
FreePacketList(session->srvReassemblyList);
|
||||
|
||||
free(session->ticketID);
|
||||
}
|
||||
free(session);
|
||||
}
|
||||
|
@ -442,6 +467,7 @@ static void InitSession(SnifferSession* session)
|
|||
session->cliReassemblyList = 0;
|
||||
session->srvReassemblyList = 0;
|
||||
session->next = 0;
|
||||
session->ticketID = 0;
|
||||
|
||||
InitFlags(&session->flags);
|
||||
InitFinCapture(&session->finCaputre);
|
||||
|
@ -1041,7 +1067,7 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
|
|||
FreeRsaKey(&key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
MakeMasterSecret(session->sslServer);
|
||||
MakeMasterSecret(session->sslClient);
|
||||
#ifdef SHOW_SECRETS
|
||||
|
@ -1067,6 +1093,39 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
|
|||
}
|
||||
|
||||
|
||||
/* 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 = (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)
|
||||
|
@ -1074,6 +1133,7 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
|
|||
ProtocolVersion pv;
|
||||
byte b;
|
||||
int toRead = sizeof(ProtocolVersion) + RAN_LEN + ENUM_LEN;
|
||||
int doResume = 0;
|
||||
|
||||
/* make sure we didn't miss ClientHello */
|
||||
if (session->flags.clientHello == 0) {
|
||||
|
@ -1107,19 +1167,44 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
|
|||
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
XMEMCPY(session->sslServer->arrays.sessionID, input, ID_LEN);
|
||||
if (b) {
|
||||
XMEMCPY(session->sslServer->arrays.sessionID, input, ID_LEN);
|
||||
session->sslServer->options.haveSessionId = 1;
|
||||
}
|
||||
input += b;
|
||||
*sslBytes -= b;
|
||||
|
||||
|
||||
/* cipher suite */
|
||||
(void)*input++; /* eat first byte, always 0 */
|
||||
b = *input++;
|
||||
session->sslServer->options.cipherSuite = b;
|
||||
session->sslClient->options.cipherSuite = b;
|
||||
*sslBytes -= SUITE_LEN;
|
||||
|
||||
if (XMEMCMP(session->sslServer->arrays.sessionID,
|
||||
session->sslClient->arrays.sessionID, ID_LEN) == 0) {
|
||||
/* resuming */
|
||||
|
||||
/* 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 */
|
||||
XMEMCPY(session->sslServer->arrays.sessionID, session->ticketID,ID_LEN);
|
||||
}
|
||||
|
||||
if (doResume ) {
|
||||
SSL_SESSION* resume = GetSession(session->sslServer,
|
||||
session->sslServer->arrays.masterSecret);
|
||||
if (resume == NULL) {
|
||||
|
@ -1170,8 +1255,9 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
|
|||
static int ProcessClientHello(const byte* input, int* sslBytes,
|
||||
SnifferSession* session, char* error)
|
||||
{
|
||||
byte sessionLen;
|
||||
int toRead = sizeof(ProtocolVersion) + RAN_LEN + ENUM_LEN;
|
||||
byte bLen;
|
||||
word16 len;
|
||||
int toRead = sizeof(ProtocolVersion) + RAN_LEN + ENUM_LEN;
|
||||
|
||||
session->flags.clientHello = 1; /* don't process again */
|
||||
|
||||
|
@ -1192,14 +1278,16 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
|
|||
*sslBytes -= RAN_LEN;
|
||||
|
||||
/* store session in case trying to resume */
|
||||
sessionLen = *input++;
|
||||
if (sessionLen) {
|
||||
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
|
||||
{
|
||||
|
@ -1210,11 +1298,142 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
|
|||
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 = (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 = (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 = (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* sslBytes,
|
||||
SnifferSession* session, char* error)
|
||||
{
|
||||
SSL* ssl;
|
||||
word32 inOutIdx = 0;
|
||||
int ret;
|
||||
|
||||
if (session->flags.side == SERVER_END)
|
||||
ssl = session->sslServer;
|
||||
else
|
||||
ssl = session->sslClient;
|
||||
ret = DoFinished(ssl, input, &inOutIdx, 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) {
|
||||
CYASSL_SESSION* sess = GetSession(session->sslServer, NULL);
|
||||
if (sess == NULL)
|
||||
AddSession(session->sslServer); /* don't re add */
|
||||
session->flags.cached = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Process HandShake input */
|
||||
static int DoHandShake(const byte* input, int* sslBytes,
|
||||
SnifferSession* session, char* error)
|
||||
|
@ -1242,6 +1461,13 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
|||
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);
|
||||
|
@ -1251,6 +1477,9 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
|||
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);
|
||||
|
@ -1260,21 +1489,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
|||
break;
|
||||
case finished:
|
||||
Trace(GOT_FINISHED_STR);
|
||||
{
|
||||
SSL* ssl;
|
||||
word32 inOutIdx = 0;
|
||||
|
||||
if (session->flags.side == SERVER_END)
|
||||
ssl = session->sslServer;
|
||||
else
|
||||
ssl = session->sslClient;
|
||||
ret = DoFinished(ssl, input, &inOutIdx, SNIFF);
|
||||
|
||||
if (ret == 0 && session->flags.cached == 0) {
|
||||
AddSession(session->sslServer);
|
||||
session->flags.cached = 1;
|
||||
}
|
||||
}
|
||||
ret = ProcessFinished(input, sslBytes, session, error);
|
||||
break;
|
||||
case client_hello:
|
||||
Trace(GOT_CLIENT_HELLO_STR);
|
||||
|
@ -1329,6 +1544,10 @@ static void Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
|
|||
RabbitProcess(&ssl->decrypt.rabbit, output, input, sz);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
Trace(BAD_DECRYPT_TYPE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1644,16 +1863,6 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
|
|||
}
|
||||
|
||||
|
||||
#ifndef min
|
||||
|
||||
static INLINE word32 min(word32 a, word32 b)
|
||||
{
|
||||
return a > b ? b : a;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
|
||||
static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
|
||||
int* bytesLeft)
|
||||
|
|
|
@ -77,6 +77,24 @@
|
|||
#endif /* min */
|
||||
|
||||
|
||||
char* mystrnstr(const char* s1, const char* s2, unsigned int n)
|
||||
{
|
||||
unsigned int s2_len = 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;
|
||||
}
|
||||
|
||||
|
||||
CYASSL_CTX* CyaSSL_CTX_new(CYASSL_METHOD* method)
|
||||
{
|
||||
|
@ -227,8 +245,8 @@ int CyaSSL_SetTmpDH(CYASSL* ssl, const unsigned char* p, int pSz,
|
|||
havePSK = ssl->options.havePSK;
|
||||
#endif
|
||||
InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH,
|
||||
havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA,
|
||||
ssl->options.haveStaticECC, ssl->ctx->method->side);
|
||||
havePSK, ssl->options.haveNTRU, ssl->options.haveECDSAsig,
|
||||
ssl->options.haveStaticECC, ssl->options.side);
|
||||
|
||||
CYASSL_LEAVE("CyaSSL_SetTmpDH", 0);
|
||||
return 0;
|
||||
|
@ -473,6 +491,53 @@ int CyaSSL_set_group_messages(CYASSL* ssl)
|
|||
}
|
||||
|
||||
|
||||
int CyaSSL_SetVersion(CYASSL* ssl, int version)
|
||||
{
|
||||
byte havePSK = 0;
|
||||
|
||||
CYASSL_ENTER("CyaSSL_SetVersion");
|
||||
|
||||
if (ssl == NULL) {
|
||||
CYASSL_MSG("Bad function argument");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (version) {
|
||||
case CYASSL_SSLV3:
|
||||
ssl->version = MakeSSLv3();
|
||||
break;
|
||||
|
||||
#ifndef NO_TLS
|
||||
case CYASSL_TLSV1:
|
||||
ssl->version = MakeTLSv1();
|
||||
break;
|
||||
|
||||
case CYASSL_TLSV1_1:
|
||||
ssl->version = MakeTLSv1_1();
|
||||
break;
|
||||
|
||||
case CYASSL_TLSV1_2:
|
||||
ssl->version = MakeTLSv1_2();
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
CYASSL_MSG("Bad function argument");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifndef NO_PSK
|
||||
havePSK = ssl->options.havePSK;
|
||||
#endif
|
||||
|
||||
InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK,
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSAsig,
|
||||
ssl->options.haveStaticECC, ssl->options.side);
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* does CA already exist on signer list */
|
||||
int AlreadySigner(CYASSL_CERT_MANAGER* cm, byte* hash)
|
||||
{
|
||||
|
@ -674,12 +739,12 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify)
|
|||
}
|
||||
|
||||
/* find header */
|
||||
headerEnd = XSTRSTR((char*)buff, header);
|
||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
||||
if (!headerEnd && type == PRIVATEKEY_TYPE) { /* may be pkcs8 */
|
||||
XSTRNCPY(header, "-----BEGIN PRIVATE KEY-----", sizeof(header));
|
||||
XSTRNCPY(footer, "-----END PRIVATE KEY-----", sizeof(footer));
|
||||
|
||||
headerEnd = XSTRSTR((char*)buff, header);
|
||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
||||
if (headerEnd)
|
||||
pkcs8 = 1;
|
||||
else {
|
||||
|
@ -688,7 +753,7 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify)
|
|||
XSTRNCPY(footer, "-----END ENCRYPTED PRIVATE KEY-----",
|
||||
sizeof(footer));
|
||||
|
||||
headerEnd = XSTRSTR((char*)buff, header);
|
||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
||||
if (headerEnd)
|
||||
pkcs8Enc = 1;
|
||||
}
|
||||
|
@ -697,7 +762,7 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify)
|
|||
XSTRNCPY(header, "-----BEGIN EC PRIVATE KEY-----", sizeof(header));
|
||||
XSTRNCPY(footer, "-----END EC PRIVATE KEY-----", sizeof(footer));
|
||||
|
||||
headerEnd = XSTRSTR((char*)buff, header);
|
||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
||||
if (headerEnd)
|
||||
*eccKey = 1;
|
||||
}
|
||||
|
@ -705,7 +770,7 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify)
|
|||
XSTRNCPY(header, "-----BEGIN DSA PRIVATE KEY-----", sizeof(header));
|
||||
XSTRNCPY(footer, "-----END DSA PRIVATE KEY-----", sizeof(footer));
|
||||
|
||||
headerEnd = XSTRSTR((char*)buff, header);
|
||||
headerEnd = XSTRNSTR((char*)buff, header, sz);
|
||||
}
|
||||
if (!headerEnd)
|
||||
return SSL_BAD_FILE;
|
||||
|
@ -723,28 +788,28 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify)
|
|||
{
|
||||
/* remove encrypted header if there */
|
||||
char encHeader[] = "Proc-Type";
|
||||
char* line = XSTRSTR((char*)buff, encHeader);
|
||||
char* line = XSTRNSTR((char*)buff, encHeader, PEM_LINE_LEN);
|
||||
if (line) {
|
||||
char* newline;
|
||||
char* finish;
|
||||
char* start = XSTRSTR(line, "DES");
|
||||
char* start = XSTRNSTR(line, "DES", PEM_LINE_LEN);
|
||||
|
||||
if (!start)
|
||||
start = XSTRSTR(line, "AES");
|
||||
start = XSTRNSTR(line, "AES", PEM_LINE_LEN);
|
||||
|
||||
if (!start) return SSL_BAD_FILE;
|
||||
if (!info) return SSL_BAD_FILE;
|
||||
|
||||
finish = XSTRSTR(start, ",");
|
||||
finish = XSTRNSTR(start, ",", PEM_LINE_LEN);
|
||||
|
||||
if (start && finish && (start < finish)) {
|
||||
newline = XSTRSTR(finish, "\r");
|
||||
newline = XSTRNSTR(finish, "\r", PEM_LINE_LEN);
|
||||
|
||||
XMEMCPY(info->name, start, finish - start);
|
||||
info->name[finish - start] = 0;
|
||||
XMEMCPY(info->iv, finish + 1, sizeof(info->iv));
|
||||
|
||||
if (!newline) newline = XSTRSTR(finish, "\n");
|
||||
if (!newline) newline = XSTRNSTR(finish, "\n", PEM_LINE_LEN);
|
||||
if (newline && (newline > finish)) {
|
||||
info->ivSz = (word32)(newline - (finish + 1));
|
||||
info->set = 1;
|
||||
|
@ -764,7 +829,7 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify)
|
|||
#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
|
||||
|
||||
/* find footer */
|
||||
footerEnd = XSTRSTR((char*)buff, footer);
|
||||
footerEnd = XSTRNSTR((char*)buff, footer, sz);
|
||||
if (!footerEnd) return SSL_BAD_FILE;
|
||||
|
||||
consumedEnd = footerEnd + XSTRLEN(footer);
|
||||
|
@ -1085,9 +1150,9 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify)
|
|||
case CTC_SHA384wECDSA:
|
||||
case CTC_SHA512wECDSA:
|
||||
CYASSL_MSG("ECDSA cert signature");
|
||||
ctx->haveECDSA = 1;
|
||||
ctx->haveECDSAsig = 1;
|
||||
if (ssl)
|
||||
ssl->options.haveECDSA = 1;
|
||||
ssl->options.haveECDSAsig = 1;
|
||||
break;
|
||||
default:
|
||||
CYASSL_MSG("Not ECDSA cert signature");
|
||||
|
@ -1280,28 +1345,64 @@ int CyaSSL_CTX_load_verify_locations(CYASSL_CTX* ctx, const char* file,
|
|||
}
|
||||
|
||||
|
||||
/* Verify the ceritficate, 1 for success, < 0 for error */
|
||||
int CyaSSL_CertManagerVerifyBuffer(CYASSL_CERT_MANAGER* cm, const byte* buff,
|
||||
int sz, int format)
|
||||
{
|
||||
int ret = 0;
|
||||
int eccKey = 0; /* not used */
|
||||
|
||||
DecodedCert cert;
|
||||
buffer der;
|
||||
|
||||
CYASSL_ENTER("CyaSSL_CertManagerVerifyBuffer");
|
||||
|
||||
der.buffer = NULL;
|
||||
|
||||
if (format == SSL_FILETYPE_PEM) {
|
||||
EncryptedInfo info;
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
InitDecodedCert(&cert, (byte*)buff, 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);
|
||||
XFREE(der.buffer, cm->heap, DYNAMIC_TYPE_CERT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Verify the ceritficate, 1 for success, < 0 for error */
|
||||
int CyaSSL_CertManagerVerify(CYASSL_CERT_MANAGER* cm, const char* fname,
|
||||
int format)
|
||||
{
|
||||
int ret = SSL_FATAL_ERROR;
|
||||
int eccKey = 0; /* not used */
|
||||
DecodedCert cert;
|
||||
|
||||
int ret = SSL_FATAL_ERROR;
|
||||
byte staticBuffer[FILE_BUFFER_SIZE];
|
||||
byte* myBuffer = staticBuffer;
|
||||
int dynamic = 0;
|
||||
long sz = 0;
|
||||
buffer der;
|
||||
XFILE* file = XFOPEN(fname, "rb");
|
||||
|
||||
CYASSL_ENTER("CyaSSL_CertManagerVerify");
|
||||
|
||||
if (!file) return SSL_BAD_FILE;
|
||||
XFSEEK(file, 0, XSEEK_END);
|
||||
sz = XFTELL(file);
|
||||
XREWIND(file);
|
||||
|
||||
der.buffer = NULL;
|
||||
|
||||
if (sz > (long)sizeof(staticBuffer)) {
|
||||
CYASSL_MSG("Getting dynamic buffer");
|
||||
myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE);
|
||||
|
@ -1314,32 +1415,9 @@ int CyaSSL_CertManagerVerify(CYASSL_CERT_MANAGER* cm, const char* fname,
|
|||
|
||||
if ( (ret = XFREAD(myBuffer, sz, 1, file)) < 0)
|
||||
ret = SSL_BAD_FILE;
|
||||
else {
|
||||
ret = 0; /* ok */
|
||||
if (format == SSL_FILETYPE_PEM) {
|
||||
EncryptedInfo info;
|
||||
|
||||
info.set = 0;
|
||||
info.ctx = NULL;
|
||||
info.consumed = 0;
|
||||
ret = PemToDer(myBuffer, sz, CERT_TYPE, &der, cm->heap, &info,
|
||||
&eccKey);
|
||||
InitDecodedCert(&cert, der.buffer, der.length, cm->heap);
|
||||
else
|
||||
ret = CyaSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format);
|
||||
|
||||
}
|
||||
else
|
||||
InitDecodedCert(&cert, myBuffer, 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);
|
||||
XFREE(der.buffer, cm->heap, DYNAMIC_TYPE_CERT);
|
||||
XFCLOSE(file);
|
||||
if (dynamic) XFREE(myBuffer, cm->heap, DYNAMIC_TYPE_FILE);
|
||||
|
||||
|
@ -1432,6 +1510,15 @@ int CyaSSL_CertManagerDisableCRL(CYASSL_CERT_MANAGER* cm)
|
|||
}
|
||||
|
||||
|
||||
int CyaSSL_CTX_check_private_key(CYASSL_CTX* ctx)
|
||||
{
|
||||
/* TODO: check private against public for RSA match */
|
||||
(void)ctx;
|
||||
CYASSL_ENTER("SSL_CTX_check_private_key");
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_CRL
|
||||
|
||||
|
||||
|
@ -1474,7 +1561,7 @@ int CyaSSL_CertManagerCheckCRL(CYASSL_CERT_MANAGER* cm, byte* der, int sz)
|
|||
|
||||
int CyaSSL_CertManagerSetCRL_Cb(CYASSL_CERT_MANAGER* cm, CbMissingCRL cb)
|
||||
{
|
||||
CYASSL_ENTER("CyaSSL_CertManagerLoadCRL");
|
||||
CYASSL_ENTER("CyaSSL_CertManagerSetCRL_Cb");
|
||||
if (cm == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
|
@ -2050,8 +2137,8 @@ int CyaSSL_set_cipher_list(CYASSL* ssl, const char* list)
|
|||
#endif
|
||||
|
||||
InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK,
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSA,
|
||||
ssl->options.haveStaticECC, ssl->ctx->method->side);
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSAsig,
|
||||
ssl->options.haveStaticECC, ssl->options.side);
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
@ -3074,8 +3161,8 @@ int CyaSSL_set_compression(CYASSL* ssl)
|
|||
ssl->options.client_psk_cb = cb;
|
||||
|
||||
InitSuites(&ssl->suites, ssl->version,TRUE,TRUE, ssl->options.haveNTRU,
|
||||
ssl->options.haveECDSA, ssl->options.haveStaticECC,
|
||||
ssl->ctx->method->side);
|
||||
ssl->options.haveECDSAsig, ssl->options.haveStaticECC,
|
||||
ssl->options.side);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3095,8 +3182,8 @@ int CyaSSL_set_compression(CYASSL* ssl)
|
|||
ssl->options.server_psk_cb = cb;
|
||||
|
||||
InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, TRUE,
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSA,
|
||||
ssl->options.haveStaticECC, ssl->ctx->method->side);
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSAsig,
|
||||
ssl->options.haveStaticECC, ssl->options.side);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3244,15 +3331,6 @@ int CyaSSL_set_compression(CYASSL* ssl)
|
|||
}
|
||||
|
||||
|
||||
int CyaSSL_CTX_check_private_key(CYASSL_CTX* ctx)
|
||||
{
|
||||
/* TODO: check private against public for RSA match */
|
||||
(void)ctx;
|
||||
CYASSL_ENTER("SSL_CTX_check_private_key");
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void CyaSSL_set_bio(CYASSL* ssl, CYASSL_BIO* rd, CYASSL_BIO* wr)
|
||||
{
|
||||
CYASSL_ENTER("SSL_set_bio");
|
||||
|
@ -3329,8 +3407,8 @@ int CyaSSL_set_compression(CYASSL* ssl)
|
|||
havePSK = ssl->options.havePSK;
|
||||
#endif
|
||||
InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK,
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSA,
|
||||
ssl->options.haveStaticECC, ssl->ctx->method->side);
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSAsig,
|
||||
ssl->options.haveStaticECC, ssl->options.side);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3407,6 +3485,27 @@ int CyaSSL_set_compression(CYASSL* ssl)
|
|||
}
|
||||
|
||||
|
||||
/* return the next, if any, altname from the peer cert */
|
||||
char* CyaSSL_X509_get_next_altname(CYASSL_X509* cert)
|
||||
{
|
||||
char* ret = NULL;
|
||||
CYASSL_ENTER("CyaSSL_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;
|
||||
}
|
||||
|
||||
|
||||
CYASSL_X509_NAME* CyaSSL_X509_get_issuer_name(CYASSL_X509* cert)
|
||||
{
|
||||
CYASSL_ENTER("X509_get_issuer_name");
|
||||
|
@ -4942,6 +5041,23 @@ int CyaSSL_set_compression(CYASSL* ssl)
|
|||
case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
|
||||
return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
|
||||
|
||||
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";
|
||||
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";
|
||||
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";
|
||||
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";
|
||||
|
||||
default:
|
||||
return "NONE";
|
||||
}
|
||||
|
@ -4990,6 +5106,14 @@ int CyaSSL_set_compression(CYASSL* ssl)
|
|||
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";
|
||||
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";
|
||||
default:
|
||||
return "NONE";
|
||||
} /* switch */
|
||||
|
@ -7695,25 +7819,34 @@ const byte* CyaSSL_get_sessionID(const CYASSL_SESSION* session)
|
|||
#endif /* SESSION_CERTS */
|
||||
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
|
||||
long CyaSSL_CTX_OCSP_set_options(CYASSL_CTX* ctx, long options)
|
||||
{
|
||||
CYASSL_ENTER("CyaSSL_CTX_OCSP_set_options");
|
||||
#ifdef HAVE_OCSP
|
||||
if (ctx != NULL) {
|
||||
ctx->ocsp.enabled = (options && CYASSL_OCSP_ENABLE) != 0;
|
||||
ctx->ocsp.useOverrideUrl = (options && CYASSL_OCSP_URL_OVERRIDE) != 0;
|
||||
ctx->ocsp.enabled = (options & CYASSL_OCSP_ENABLE) != 0;
|
||||
ctx->ocsp.useOverrideUrl = (options & CYASSL_OCSP_URL_OVERRIDE) != 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
(void)ctx;
|
||||
(void)options;
|
||||
return NOT_COMPILED_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_CTX_OCSP_set_override_url(CYASSL_CTX* ctx, const char* url)
|
||||
{
|
||||
CYASSL_ENTER("CyaSSL_CTX_OCSP_set_override_url");
|
||||
#ifdef HAVE_OCSP
|
||||
return CyaSSL_OCSP_set_override_url(&ctx->ocsp, url);
|
||||
#else
|
||||
(void)ctx;
|
||||
(void)url;
|
||||
return NOT_COMPILED_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -33,6 +33,16 @@
|
|||
#ifndef NO_TLS
|
||||
|
||||
|
||||
#ifndef min
|
||||
|
||||
static INLINE word32 min(word32 a, word32 b)
|
||||
{
|
||||
return a > b ? b : a;
|
||||
}
|
||||
|
||||
#endif /* min */
|
||||
|
||||
|
||||
/* calculate XOR for TLSv1 PRF */
|
||||
static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
|
||||
{
|
||||
|
@ -43,28 +53,51 @@ static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CYASSL_SHA384
|
||||
#define PHASH_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE
|
||||
#else
|
||||
#define PHASH_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
|
||||
#endif
|
||||
|
||||
/* compute p_hash for MD5, SHA-1, or SHA-256 for TLSv1 PRF */
|
||||
/* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */
|
||||
static void p_hash(byte* result, word32 resLen, const byte* secret,
|
||||
word32 secLen, const byte* seed, word32 seedLen, int hash)
|
||||
{
|
||||
word32 len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ?
|
||||
SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE;
|
||||
word32 times = resLen / len;
|
||||
word32 lastLen = resLen % len;
|
||||
word32 len = MD5_DIGEST_SIZE;
|
||||
word32 times;
|
||||
word32 lastLen;
|
||||
word32 lastTime;
|
||||
word32 i;
|
||||
word32 idx = 0;
|
||||
byte previous[SHA256_DIGEST_SIZE]; /* max size */
|
||||
byte current[SHA256_DIGEST_SIZE]; /* max size */
|
||||
byte previous[PHASH_MAX_DIGEST_SIZE]; /* max size */
|
||||
byte current[PHASH_MAX_DIGEST_SIZE]; /* max size */
|
||||
|
||||
Hmac hmac;
|
||||
|
||||
if (hash == md5_mac) {
|
||||
hash = MD5;
|
||||
}
|
||||
else if (hash == sha_mac) {
|
||||
len = SHA_DIGEST_SIZE;
|
||||
hash = SHA;
|
||||
} else if (hash == sha256_mac) {
|
||||
len = SHA256_DIGEST_SIZE;
|
||||
hash = SHA256;
|
||||
}
|
||||
#ifdef CYASSL_SHA384
|
||||
else if (hash == sha384_mac)
|
||||
{
|
||||
len = SHA384_DIGEST_SIZE;
|
||||
hash = SHA384;
|
||||
}
|
||||
#endif
|
||||
|
||||
times = resLen / len;
|
||||
lastLen = resLen % len;
|
||||
if (lastLen) times += 1;
|
||||
lastTime = times - 1;
|
||||
|
||||
HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256,
|
||||
secret, secLen);
|
||||
HmacSetKey(&hmac, hash, secret, secLen);
|
||||
HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */
|
||||
HmacFinal(&hmac, previous); /* A1 */
|
||||
|
||||
|
@ -74,7 +107,7 @@ static void p_hash(byte* result, word32 resLen, const byte* secret,
|
|||
HmacFinal(&hmac, current);
|
||||
|
||||
if ( (i == lastTime) && lastLen)
|
||||
XMEMCPY(&result[idx], current, lastLen);
|
||||
XMEMCPY(&result[idx], current, min(lastLen, sizeof(current)));
|
||||
else {
|
||||
XMEMCPY(&result[idx], current, len);
|
||||
idx += len;
|
||||
|
@ -89,7 +122,7 @@ static void p_hash(byte* result, word32 resLen, const byte* secret,
|
|||
/* compute TLSv1 PRF (pseudo random function using HMAC) */
|
||||
static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
|
||||
const byte* label, word32 labLen, const byte* seed, word32 seedLen,
|
||||
int useSha256)
|
||||
int useAtLeastSha256, int hash_type)
|
||||
{
|
||||
word32 half = (secLen + 1) / 2;
|
||||
|
||||
|
@ -112,9 +145,13 @@ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
|
|||
XMEMCPY(labelSeed, label, labLen);
|
||||
XMEMCPY(labelSeed + labLen, seed, seedLen);
|
||||
|
||||
if (useSha256) {
|
||||
if (useAtLeastSha256) {
|
||||
/* If a cipher suite wants an algorithm better than sha256, it
|
||||
* should use better. */
|
||||
if (hash_type < sha256_mac)
|
||||
hash_type = sha256_mac;
|
||||
p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen,
|
||||
sha256_mac);
|
||||
hash_type);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -126,20 +163,35 @@ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CYASSL_SHA384
|
||||
#define HSHASH_SZ SHA384_DIGEST_SIZE
|
||||
#else
|
||||
#define HSHASH_SZ FINISHED_SZ
|
||||
#endif
|
||||
|
||||
|
||||
void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
|
||||
{
|
||||
const byte* side;
|
||||
byte handshake_hash[FINISHED_SZ];
|
||||
byte handshake_hash[HSHASH_SZ];
|
||||
word32 hashSz = FINISHED_SZ;
|
||||
|
||||
Md5Final(&ssl->hashMd5, handshake_hash);
|
||||
ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
|
||||
#ifndef NO_SHA256
|
||||
if (IsAtLeastTLSv1_2(ssl)) {
|
||||
Sha256Final(&ssl->hashSha256, handshake_hash);
|
||||
hashSz = SHA256_DIGEST_SIZE;
|
||||
}
|
||||
#ifndef NO_SHA256
|
||||
if (ssl->specs.mac_algorithm <= sha256_mac) {
|
||||
Sha256Final(&ssl->hashSha256, handshake_hash);
|
||||
hashSz = SHA256_DIGEST_SIZE;
|
||||
}
|
||||
#endif
|
||||
#ifdef CYASSL_SHA384
|
||||
if (ssl->specs.mac_algorithm == sha384_mac) {
|
||||
Sha384Final(&ssl->hashSha384, handshake_hash);
|
||||
hashSz = SHA384_DIGEST_SIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
|
||||
side = tls_client;
|
||||
|
@ -147,7 +199,8 @@ void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
|
|||
side = tls_server;
|
||||
|
||||
PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN,
|
||||
side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl));
|
||||
side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl),
|
||||
ssl->specs.mac_algorithm);
|
||||
}
|
||||
|
||||
|
||||
|
@ -197,7 +250,8 @@ int DeriveTlsKeys(CYASSL* ssl)
|
|||
XMEMCPY(&seed[RAN_LEN], ssl->arrays.clientRandom, RAN_LEN);
|
||||
|
||||
PRF(key_data, length, ssl->arrays.masterSecret, SECRET_LEN, key_label,
|
||||
KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
|
||||
KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl),
|
||||
ssl->specs.mac_algorithm);
|
||||
|
||||
return StoreKeys(ssl, key_data);
|
||||
}
|
||||
|
@ -213,7 +267,7 @@ int MakeTlsMasterSecret(CYASSL* ssl)
|
|||
PRF(ssl->arrays.masterSecret, SECRET_LEN,
|
||||
ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz,
|
||||
master_label, MASTER_LABEL_SZ,
|
||||
seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
|
||||
seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm);
|
||||
|
||||
#ifdef SHOW_SECRETS
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue