From 8cc9c62911d60c2a1ca90b0b01d12d3ce707274d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 13 Aug 2015 14:29:56 -0700 Subject: [PATCH 1/3] skip past the pad and mac when skipping a finished message in DTLS --- src/internal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/internal.c b/src/internal.c index bd04bdbec..25cbf17f0 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5193,6 +5193,8 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, ssl->keys.dtls_expected_peer_handshake_number) { /* Already saw this message and processed it. It can be ignored. */ *inOutIdx += fragSz; + if(type == finished ) + *inOutIdx += ssl->keys.padSz; ret = 0; } else if (fragSz < size) { From 0f9f4ea7e08fc2f06e66d5cd5ffdfe47c759b7c2 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 14 Aug 2015 09:58:44 -0600 Subject: [PATCH 2/3] add macro blocks to make it easier on embedded devices and fix declaration after executable code --- wolfcrypt/src/fe_low_mem.c | 3 ++- wolfcrypt/src/fe_operations.c | 2 ++ wolfcrypt/src/ge_low_mem.c | 6 ++++-- wolfcrypt/src/ge_operations.c | 2 ++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/wolfcrypt/src/fe_low_mem.c b/wolfcrypt/src/fe_low_mem.c index 80834f54c..2dc914c81 100644 --- a/wolfcrypt/src/fe_low_mem.c +++ b/wolfcrypt/src/fe_low_mem.c @@ -27,6 +27,7 @@ #include +#if defined(CURVED25519_SMALL) /* use slower code that takes less memory */ #if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) #include @@ -593,4 +594,4 @@ void fe_sqrt(byte *r, const byte *a) } #endif /* HAVE_CURVE25519 or HAVE_ED25519 */ - +#endif /* CURVED25519_SMALL */ diff --git a/wolfcrypt/src/fe_operations.c b/wolfcrypt/src/fe_operations.c index d78467e21..9259403ec 100644 --- a/wolfcrypt/src/fe_operations.c +++ b/wolfcrypt/src/fe_operations.c @@ -27,6 +27,7 @@ #include +#ifndef CURVED25519_SMALL /* run when not defined to use small memory math */ #if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) #include @@ -1405,4 +1406,5 @@ void fe_cmov(fe f,const fe g,unsigned int b) f[9] = f9 ^ x9; } #endif /* HAVE ED25519 or CURVE25519 */ +#endif /* not defined CURVED25519_SMALL */ diff --git a/wolfcrypt/src/ge_low_mem.c b/wolfcrypt/src/ge_low_mem.c index 43c533c69..f8dba9266 100644 --- a/wolfcrypt/src/ge_low_mem.c +++ b/wolfcrypt/src/ge_low_mem.c @@ -27,7 +27,8 @@ #include -#ifdef HAVE_ED25519 +#if defined(CURVED25519_SMALL) /* use slower code that takes less memory */ +#if defined(HAVE_ED25519) #include #include @@ -71,12 +72,12 @@ int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, { byte tmp[F25519_SIZE]; byte parity; + byte pt[32]; int i; fe_copy(tmp, xIn); parity = (tmp[0] & 1) << 7; - byte pt[32]; fe_copy(pt, yIn); pt[31] |= parity; @@ -555,4 +556,5 @@ int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h, } #endif /* HAVE_ED25519 */ +#endif /* CURVED25519_SMALL */ diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index 665cfe89b..259b5b144 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -28,6 +28,7 @@ #include +#ifndef CURVED25519_SMALL /* run when not defined to use small memory math */ #ifdef HAVE_ED25519 #include @@ -2600,4 +2601,5 @@ void ge_tobytes(unsigned char *s,const ge_p2 *h) s[31] ^= fe_isnegative(x) << 7; } #endif /* HAVE_ED25519 */ +#endif /* not defined CURVED25519_SMALL */ From d12308a05325750d01dd806fbb4bd34a4a606d09 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 14 Aug 2015 11:06:42 -0700 Subject: [PATCH 3/3] SendCertificate fragments the message based on max_fragment setting for TLS and DTLS. --- src/internal.c | 365 ++++++++++++++++++++++++++++++++------------- src/ssl.c | 12 +- wolfssl/internal.h | 1 + 3 files changed, 274 insertions(+), 104 deletions(-) diff --git a/src/internal.c b/src/internal.c index 25cbf17f0..0755a9496 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2277,7 +2277,7 @@ void DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type, XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ, fragSz + DTLS_HANDSHAKE_HEADER_SZ); else { - /* If fragOffet is non-zero, this is an additional fragment that + /* If fragOffset is non-zero, this is an additional fragment that * needs to be copied to its location in the message buffer. Also * copy the total size of the message over the fragment size. The * hash routines look at a defragmented message if it had actually @@ -2535,6 +2535,45 @@ ProtocolVersion MakeDTLSv1_2(void) #endif /* USE_WINDOWS_API */ +static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) +{ +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx); +#endif +#ifndef NO_OLD_TLS +#ifndef NO_SHA + wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz); +#endif +#ifndef NO_MD5 + wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz); +#endif +#endif + + if (IsAtLeastTLSv1_2(ssl)) { + int ret; + +#ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz); + if (ret != 0) + return ret; +#endif + } + + return 0; +} + + /* add output to md5 and sha handshake hashes, exclude record header */ static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) { @@ -2658,10 +2697,13 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl /* add handshake header for message */ -static void AddHandShakeHeader(byte* output, word32 length, byte type, - WOLFSSL* ssl) +static void AddHandShakeHeader(byte* output, word32 length, + word32 fragOffset, word32 fragLength, + byte type, WOLFSSL* ssl) { HandShakeHeader* hs; + (void)fragOffset; + (void)fragLength; (void)ssl; /* handshake header */ @@ -2675,8 +2717,8 @@ static void AddHandShakeHeader(byte* output, word32 length, byte type, /* dtls handshake header extensions */ dtls = (DtlsHandShakeHeader*)output; c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq); - c32to24(0, dtls->fragment_offset); - c32to24(length, dtls->fragment_length); + c32to24(fragOffset, dtls->fragment_offset); + c32to24(fragLength, dtls->fragment_length); } #endif } @@ -2685,16 +2727,37 @@ static void AddHandShakeHeader(byte* output, word32 length, byte type, /* add both headers for handshake message */ static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl) { - if (!ssl->options.dtls) { - AddRecordHeader(output, length + HANDSHAKE_HEADER_SZ, handshake, ssl); - AddHandShakeHeader(output + RECORD_HEADER_SZ, length, type, ssl); - } + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + #ifdef WOLFSSL_DTLS - else { - AddRecordHeader(output, length+DTLS_HANDSHAKE_HEADER_SZ, handshake,ssl); - AddHandShakeHeader(output + DTLS_RECORD_HEADER_SZ, length, type, ssl); + if (ssl->options.dtls) { + lengthAdj += DTLS_HANDSHAKE_EXTRA; + outputAdj += DTLS_RECORD_EXTRA; } #endif + + AddRecordHeader(output, length + lengthAdj, handshake, ssl); + AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl); +} + + +static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset, + word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + (void)fragSz; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + lengthAdj += DTLS_HANDSHAKE_EXTRA; + outputAdj += DTLS_RECORD_EXTRA; + } +#endif + + AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl); + AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl); } @@ -4018,15 +4081,8 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, c24to32(input + *inOutIdx, &listSz); *inOutIdx += OPAQUE24_LEN; -#ifdef HAVE_MAX_FRAGMENT - if (listSz > ssl->max_fragment) { - SendAlert(ssl, alert_fatal, record_overflow); - return BUFFER_E; - } -#else if (listSz > MAX_RECORD_SIZE) return BUFFER_E; -#endif if ((*inOutIdx - begin) + listSz != size) return BUFFER_ERROR; @@ -7281,7 +7337,7 @@ int SendFinished(WOLFSSL* ssl) output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; - AddHandShakeHeader(input, finishedSz, finished, ssl); + AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); /* make finished hashes */ hashes = (Hashes*)&input[headerSz]; @@ -7362,117 +7418,226 @@ int SendFinished(WOLFSSL* ssl) return SendBuffered(ssl); } + #ifndef NO_CERTS int SendCertificate(WOLFSSL* ssl) { - int sendSz, length, ret = 0; - word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - word32 certSz, listSz; - byte* output = 0; + int length, ret = 0; + word32 certSz, certChainSz, headerSz, listSz, maxFragment, payloadSz; if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) return 0; /* not needed */ if (ssl->options.sendVerify == SEND_BLANK_CERT) { certSz = 0; + certChainSz = 0; + headerSz = CERT_HEADER_SZ; length = CERT_HEADER_SZ; listSz = 0; } else { certSz = ssl->buffers.certificate.length; + headerSz = 2 * CERT_HEADER_SZ; /* list + cert size */ - length = certSz + 2 * CERT_HEADER_SZ; + length = certSz + headerSz; listSz = certSz + CERT_HEADER_SZ; /* may need to send rest of chain, already has leading size(s) */ - if (ssl->buffers.certChain.buffer) { - length += ssl->buffers.certChain.length; - listSz += ssl->buffers.certChain.length; + if (certSz) { + certChainSz = ssl->buffers.certChain.length; + length += certChainSz; + listSz += certChainSz; } } - sendSz = length + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + payloadSz = length; + + if (ssl->fragOffset != 0) + length -= (ssl->fragOffset + headerSz); + + if (!ssl->options.dtls) { + maxFragment = MAX_RECORD_SIZE; + } + else { #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } - #endif - - if (ssl->keys.encryptionOn) - sendSz += MAX_MSG_EXTRA; - - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) - return ret; - - /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; - - AddHeaders(output, length, certificate, ssl); - - /* list total */ - c32to24(listSz, output + i); - i += CERT_HEADER_SZ; - - /* member */ - if (certSz) { - c32to24(certSz, output + i); - i += CERT_HEADER_SZ; - XMEMCPY(output + i, ssl->buffers.certificate.buffer, certSz); - i += certSz; - - /* send rest of chain? */ - if (ssl->buffers.certChain.buffer) { - XMEMCPY(output + i, ssl->buffers.certChain.buffer, - ssl->buffers.certChain.length); - i += ssl->buffers.certChain.length; - } + maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ + - DTLS_HANDSHAKE_HEADER_SZ - 100; + #endif /* WOLFSSL_DTLS */ } - if (ssl->keys.encryptionOn) { - byte* input; - int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + #ifdef HAVE_MAX_FRAGMENT + if (ssl->max_fragment != 0 && maxFragment >= ssl->max_fragment) + maxFragment = ssl->max_fragment; + #endif /* HAVE_MAX_FRAGMENT */ - input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) - return MEMORY_E; + while (length > 0 && ret == 0) { + byte* output = NULL; + word32 fragSz; /* How much of the certificate data are we copying? */ + word32 i = RECORD_HEADER_SZ; + int sendSz = RECORD_HEADER_SZ; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); - sendSz = BuildMessage(ssl, output, sendSz, input,inputSz,handshake); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (!ssl->options.dtls) { + if (ssl->fragOffset == 0) { + if (headerSz + certSz + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { - if (sendSz < 0) - return sendSz; - } else { - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) + fragSz = headerSz + certSz + certChainSz; + } + else { + fragSz = maxFragment - HANDSHAKE_HEADER_SZ; + } + sendSz += fragSz + HANDSHAKE_HEADER_SZ; + i += HANDSHAKE_HEADER_SZ; + } + else { + fragSz = min(length, maxFragment); + sendSz += fragSz; + } + + if (ssl->keys.encryptionOn) + sendSz += MAX_MSG_EXTRA; + } + else { + #ifdef WOLFSSL_DTLS + fragSz = min(length, maxFragment); + sendSz += fragSz + DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA + + HANDSHAKE_HEADER_SZ; + i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA + + HANDSHAKE_HEADER_SZ; + #endif + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; + + /* get ouput buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + if (ssl->fragOffset == 0) { + if (!ssl->options.dtls) { + AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + HashOutputRaw(ssl, output + RECORD_HEADER_SZ, + HANDSHAKE_HEADER_SZ); + } + else { + #ifdef WOLFSSL_DTLS + AddHeaders(output, payloadSz, certificate, ssl); + HashOutputRaw(ssl, + output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA, + HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA); + /* Adding the headers increments these, decrement them for + * actual message header. */ + ssl->keys.dtls_sequence_number--; + ssl->keys.dtls_handshake_number--; + AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + ssl->keys.dtls_handshake_number--; + #endif /* WOLFSSL_DTLS */ + } + + /* list total */ + c32to24(listSz, output + i); + HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + if (certSz) { + c32to24(certSz, output + i); + HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + + HashOutputRaw(ssl, ssl->buffers.certificate.buffer, certSz); + if (certChainSz) { + HashOutputRaw(ssl, + ssl->buffers.certChain.buffer, certChainSz); + } + } + } + else { + if (!ssl->options.dtls) { + AddRecordHeader(output, fragSz, handshake, ssl); + } + else { + #ifdef WOLFSSL_DTLS + AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz, + payloadSz, certificate, ssl); + ssl->keys.dtls_handshake_number--; + #endif /* WOLFSSL_DTLS */ + } + } + + /* member */ + if (certSz && ssl->fragOffset < certSz) { + word32 copySz = min(certSz - ssl->fragOffset, fragSz); + XMEMCPY(output + i, + ssl->buffers.certificate.buffer + ssl->fragOffset, copySz); + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + } + if (certChainSz && fragSz) { + word32 copySz = min(certChainSz + certSz - ssl->fragOffset, fragSz); + XMEMCPY(output + i, + ssl->buffers.certChain.buffer + ssl->fragOffset - certSz, + copySz); + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + } + + if (ssl->keys.encryptionOn) { + byte* input; + int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input,inputSz,handshake); + XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (sendSz < 0) + return sendSz; + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); } - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif + if (ret != WANT_WRITE) { + /* Clean up the fragment offset. */ + ssl->fragOffset = 0; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + ssl->keys.dtls_handshake_number++; + #endif + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.serverState = SERVER_CERT_COMPLETE; + } - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, - ssl->heap); - #endif - - if (ssl->options.side == WOLFSSL_SERVER_END) - ssl->options.serverState = SERVER_CERT_COMPLETE; - - ssl->buffers.outputBuffer.length += sendSz; - if (ssl->options.groupMessages) - return 0; - else - return SendBuffered(ssl); + return ret; } diff --git a/src/ssl.c b/src/ssl.c index 2b34f41dc..b30e97537 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5408,8 +5408,10 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) if (ssl->buffers.outputBuffer.length > 0) { if ( (ssl->error = SendBuffered(ssl)) == 0) { - ssl->options.connectState++; - WOLFSSL_MSG("connect state: Advanced from buffered send"); + if (ssl->fragOffset == 0) { + ssl->options.connectState++; + WOLFSSL_MSG("connect state: Advanced from buffered send"); + } } else { WOLFSSL_ERROR(ssl->error); @@ -5724,8 +5726,10 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) if (ssl->buffers.outputBuffer.length > 0) { if ( (ssl->error = SendBuffered(ssl)) == 0) { - ssl->options.acceptState++; - WOLFSSL_MSG("accept state: Advanced from buffered send"); + if (ssl->fragOffset == 0) { + ssl->options.acceptState++; + WOLFSSL_MSG("accept state: Advanced from buffered send"); + } } else { WOLFSSL_ERROR(ssl->error); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 87162e935..dcada77e5 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2284,6 +2284,7 @@ struct WOLFSSL { int rflags; /* user read flags */ int wflags; /* user write flags */ word32 timeout; /* session timeout */ + word32 fragOffset; /* fragment offset */ word16 curSize; RecordLayerHeader curRL; MsgsReceived msgsReceived; /* peer messages received */