diff --git a/cyassl/internal.h b/cyassl/internal.h index ca87b5ba4..d9ce4cf91 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -376,7 +376,11 @@ enum Misc { HASH_SIG_SIZE = 2, /* default SHA1 RSA */ NO_COPY = 0, /* should we copy static buffer for write */ - COPY = 1 /* should we copy static buffer for write */ + COPY = 1, /* should we copy static buffer for write */ + +#ifdef FORTRESS + MAX_EX_DATA = 3, /* allow for three items of ex_data */ +#endif }; @@ -1067,6 +1071,9 @@ struct CYASSL { #ifdef OPENSSL_EXTRA CYASSL_X509 peerCert; /* X509 peer cert */ #endif +#ifdef FORTRESS + void* ex_data[MAX_EX_DATA]; +#endif }; diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 4d3035c06..da0e831ea 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -120,6 +120,7 @@ typedef struct CYASSL_X509_STORE_CTX { int error_depth; CYASSL_X509* current_cert; /* stunnel dereference */ char* domain; /* subject CN domain name */ + void* ex_data; /* For fortress build */ /* in internal.h too, change there !! */ } CYASSL_X509_STORE_CTX; @@ -673,6 +674,8 @@ CYASSL_API int CyaSSL_X509_get_serial_number(CYASSL_X509*,unsigned char*,int*); CYASSL_API char* CyaSSL_X509_get_subjectCN(CYASSL_X509*); CYASSL_API const unsigned char* CyaSSL_X509_get_der(CYASSL_X509*, int*); +CYASSL_API int CyaSSL_cmp_peer_cert_to_file(CYASSL*, const char*); + /* connect enough to get peer cert */ CYASSL_API int CyaSSL_connect_cert(CYASSL* ssl); diff --git a/src/internal.c b/src/internal.c index 7ccf42c50..036f5543d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -855,6 +855,12 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->cipher.ssl = ssl; +#ifdef FORTRESS + ssl->ex_data[0] = 0; + ssl->ex_data[1] = 0; + ssl->ex_data[2] = 0; +#endif + return 0; } @@ -1725,6 +1731,9 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) store.current_cert = &ssl->peerCert; #else store.current_cert = NULL; +#endif +#ifdef FORTRESS + store.ex_data = ssl; #endif ok = ssl->verifyCallback(0, &store); if (ok) { @@ -1739,6 +1748,28 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) } ssl->error = ret; } +#ifdef FORTRESS + else { + if (ssl->verifyCallback) { + int ok; + CYASSL_X509_STORE_CTX store; + + store.error = ret; + store.error_depth = totalCerts; + store.domain = domain; + store.current_cert = &ssl->peerCert; + store.ex_data = ssl; + + ok = ssl->verifyCallback(1, &store); + if (!ok) { + CYASSL_MSG("Verify callback overriding valid certificate!"); + ret = -1; + SendAlert(ssl, alert_fatal, bad_certificate); + ssl->options.isClosed = 1; + } + } + } +#endif *inOutIdx = i; return ret; diff --git a/src/ssl.c b/src/ssl.c index e6a2553a7..830895832 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3707,9 +3707,17 @@ int CyaSSL_set_compression(CYASSL* ssl) int CyaSSL_set_ex_data(CYASSL* ssl, int idx, void* data) { +#ifdef FORTRESS + if (ssl != NULL && idx < MAX_EX_DATA && data != NULL) + { + ssl->ex_data[idx] = data; + return 1; + } +#else (void)ssl; (void)idx; (void)data; +#endif return 0; } @@ -4321,8 +4329,13 @@ int CyaSSL_set_compression(CYASSL* ssl) void* CyaSSL_X509_STORE_CTX_get_ex_data(CYASSL_X509_STORE_CTX* ctx, int idx) { +#ifdef FORTRESS + if (ctx != NULL && idx == 0) + return ctx->ex_data; +#else (void)ctx; (void)idx; +#endif return 0; } @@ -4335,8 +4348,13 @@ int CyaSSL_set_compression(CYASSL* ssl) void* CyaSSL_get_ex_data(const CYASSL* ssl, int idx) { +#ifdef FORTRESS + if (ssl != NULL && idx < MAX_EX_DATA) + return ssl->ex_data[idx]; +#else (void)ssl; (void)idx; +#endif return 0; } @@ -4659,6 +4677,70 @@ int CyaSSL_set_compression(CYASSL* ssl) return x509->subjectCN; } + +#ifdef FORTRESS + int CyaSSL_cmp_peer_cert_to_file(CYASSL* ssl, const char *fname) + { + int ret = -1; + + CYASSL_ENTER("CyaSSL_cmp_peer_cert_to_file"); + if (ssl != NULL && fname != NULL) + { + XFILE* file = NULL; + int sz = 0; + byte staticBuffer[FILE_BUFFER_SIZE]; + byte* myBuffer = staticBuffer; + CYASSL_CTX* ctx = ssl->ctx; + EncryptedInfo info; + buffer fileDer; + int eccKey = 0; + CYASSL_X509* peer_cert = &ssl->peerCert; + + info.set = 0; + info.ctx = ctx; + info.consumed = 0; + fileDer.buffer = 0; + + file = XFOPEN(fname, "rb"); + if (!file) return SSL_BAD_FILE; + XFSEEK(file, 0, XSEEK_END); + sz = XFTELL(file); + XREWIND(file); + if (sz > (long)sizeof(staticBuffer)) { + CYASSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); + } + + if ((myBuffer != NULL) && + (XFREAD(myBuffer, sz, 1, file) > 0) && + (PemToDer(myBuffer, sz, CERT_TYPE, + &fileDer, ctx->heap, &info, &eccKey) == 0) && + (fileDer.length != 0) && + (fileDer.length == peer_cert->derCert.length) && + (XMEMCMP(peer_cert->derCert.buffer, fileDer.buffer, + fileDer.length) == 0)) + { + ret = 0; + } + + XFCLOSE(file); + if (fileDer.buffer) + XFREE(fileDer.buffer, ctx->heap, DYNAMIC_TYPE_CERT); + if (myBuffer && (myBuffer != staticBuffer)) + XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + } + + return ret; + } +#else + int CyaSSL_cmp_peer_cert_to_file(CYASSL* ssl, const char *fname) + { + (void)ssl; + (void)fname; + return -1; + } +#endif + #endif /* OPENSSL_EXTRA */