diff --git a/cyassl/internal.h b/cyassl/internal.h index ccd7c8138..3225f418c 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1969,6 +1969,10 @@ struct CYASSL { byte hsInfoOn; /* track handshake info */ byte toInfoOn; /* track timeout info */ #endif +#ifdef HAVE_FUZZER + CallbackFuzzer fuzzerCb; /* for testing with using fuzzer */ + void* fuzzerCtx; /* user defined pointer */ +#endif #ifdef KEEP_PEER_CERT CYASSL_X509 peerCert; /* X509 peer cert */ #endif diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 7109b0726..f8976d0f5 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -930,6 +930,21 @@ CYASSL_API int CyaSSL_set_group_messages(CYASSL*); typedef int (*CallbackIORecv)(CYASSL *ssl, char *buf, int sz, void *ctx); typedef int (*CallbackIOSend)(CYASSL *ssl, char *buf, int sz, void *ctx); +#ifdef HAVE_FUZZER +enum fuzzer_type { + FUZZ_HMAC = 0, + FUZZ_ENCRYPT = 1, + FUZZ_SIGNATURE = 2, + FUZZ_HASH = 3, + FUZZ_HEAD = 4 +}; + +typedef int (*CallbackFuzzer)(CYASSL* ssl, const unsigned char* buf, int sz, + int type, void* fuzzCtx); + +CYASSL_API void CyaSSL_SetFuzzerCb(CYASSL* ssl, CallbackFuzzer cbf, void* fCtx); +#endif + CYASSL_API void CyaSSL_SetIORecv(CYASSL_CTX*, CallbackIORecv); CYASSL_API void CyaSSL_SetIOSend(CYASSL_CTX*, CallbackIOSend); diff --git a/src/internal.c b/src/internal.c index fb7b42217..8fd2972b6 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1752,6 +1752,10 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->MacEncryptCtx = NULL; ssl->DecryptVerifyCtx = NULL; #endif +#ifdef HAVE_FUZZER + ssl->fuzzerCb = NULL; + ssl->fuzzerCtx = NULL; +#endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC ssl->EccSignCtx = NULL; @@ -2529,6 +2533,10 @@ static int HashOutput(CYASSL* ssl, const byte* output, int sz, int ivSz) const byte* adj = output + RECORD_HEADER_SZ + ivSz; sz -= RECORD_HEADER_SZ; +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx); +#endif #ifdef CYASSL_DTLS if (ssl->options.dtls) { adj += DTLS_RECORD_EXTRA; @@ -2954,6 +2962,11 @@ static int GetRecordHeader(CYASSL* ssl, const byte* input, word32* inOutIdx, RecordLayerHeader* rh, word16 *size) { if (!ssl->options.dtls) { +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input + *inOutIdx, RECORD_HEADER_SZ, FUZZ_HEAD, + ssl->fuzzerCtx); +#endif XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ); *inOutIdx += RECORD_HEADER_SZ; ato16(rh->length, size); @@ -2969,6 +2982,12 @@ static int GetRecordHeader(CYASSL* ssl, const byte* input, word32* inOutIdx, *inOutIdx += 4; /* advance past rest of seq */ ato16(input + *inOutIdx, size); *inOutIdx += LENGTH_SZ; +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input + *inOutIdx - LENGTH_SZ - 8 - ENUM_LEN - + VERSION_SZ, ENUM_LEN + VERSION_SZ + 8 + LENGTH_SZ, + FUZZ_HEAD, ssl->fuzzerCtx); +#endif #endif } @@ -5115,6 +5134,11 @@ static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word16 sz) return ENCRYPT_ERROR; } +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); +#endif + switch (ssl->specs.bulk_cipher_algorithm) { #ifdef BUILD_ARC4 case cyassl_rc4: @@ -6392,6 +6416,11 @@ static int SSL_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz, byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */ const byte* macSecret = CyaSSL_GetMacSecret(ssl, verify); +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); +#endif + XMEMSET(seq, 0, SEQ_SZ); conLen[0] = (byte)content; c16toa((word16)sz, &conLen[ENUM_LEN]); @@ -10545,6 +10574,12 @@ static void PickHashSigAlgo(CYASSL* ssl, /* Signtaure length will be written later, when we're sure what it is */ +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, FUZZ_SIGNATURE, + ssl->fuzzerCtx); +#endif + /* do signature */ { #ifndef NO_OLD_TLS @@ -10897,6 +10932,12 @@ static void PickHashSigAlgo(CYASSL* ssl, c16toa((word16)sigSz, output + idx); idx += LENGTH_SZ; +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, FUZZ_SIGNATURE, + ssl->fuzzerCtx); +#endif + /* do signature */ { #ifndef NO_OLD_TLS diff --git a/src/ssl.c b/src/ssl.c index 1b99e98fd..e630a847a 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -11501,6 +11501,15 @@ const byte* CyaSSL_get_sessionID(const CYASSL_SESSION* session) #endif /* SESSION_CERTS */ +#ifdef HAVE_FUZZER +void CyaSSL_SetFuzzerCb(CYASSL* ssl, CallbackFuzzer cbf, void* fCtx) +{ + if (ssl) { + ssl->fuzzerCb = cbf; + ssl->fuzzerCtx = fCtx; + } +} +#endif #ifndef NO_CERTS #ifdef HAVE_PK_CALLBACKS diff --git a/src/tls.c b/src/tls.c index a569f064e..30feb6129 100644 --- a/src/tls.c +++ b/src/tls.c @@ -677,6 +677,11 @@ int TLS_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz, if (ssl == NULL) return BAD_FUNC_ARG; +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); +#endif + CyaSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); ret = HmacSetKey(&hmac, CyaSSL_GetHmacType(ssl),