Prepare for V7.2.0 release.

This commit is contained in:
Richard Barry 2012-08-14 12:14:48 +00:00
parent 73ad4387e2
commit e0bab5981a
1071 changed files with 8726 additions and 2457 deletions

View file

@ -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 */

View file

@ -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

View file

@ -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)

View file

@ -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);

View file

@ -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;
}

View file

@ -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)

View file

@ -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

View file

@ -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
{