eclipse / tinydtls Goto Github PK
View Code? Open in Web Editor NEWEclipse tinydtls
Home Page: https://projects.eclipse.org/projects/iot.tinydtls
License: Other
Eclipse tinydtls
Home Page: https://projects.eclipse.org/projects/iot.tinydtls
License: Other
when i make it in the tests, the error happen:/usr/bin/ld: cannot find -ltinydtls, my os is ubuntu 20.04
how can i solve it
thanks
sudo make uninstall
Making uninstall in ext/tinydtls
make[1]: Verzeichnis „..../libcoap/ext/tinydtls“ wird betreten
make[1]: *** Keine Regel, um „uninstall“ zu erstellen. Schluss.
make[1]: Verzeichnis „..../libcoap/ext/tinydtls“ wird verlassen
Makefile:1070: recipe for target 'uninstall-recursive' failed
make: *** [uninstall-recursive] Error 1
Seems, that tinydtls provides "install", but has no target to "uninstall".
commit 7f8c86e in the tinydtls repository.
Greetings. Over a week ago I attempted to reach out to [email protected] to report a serious cryptography security issue in this library and I have received no response. Please advise me of the correct contact point.
Version: development branch
Expected behavior
The DTLS RFC specifies the following requirement regarding the message sequence number
:
The first message each side transmits in each handshake always has message_seq = 0. Whenever each new message is generated, the message_seq value is incremented by one.
Actual behavior
One can complete a handshake with the following values for the message sequence:
CH0.sequence_number = 255
CH2.sequence_number = 191
CKE.sequence_number = 192
Finished.sequence_number = 193
The problem also exists when the server sends records with non-compliant sequence numbers.
I have attached the handshake trace for the mentioned non-conformance. You clearly see that the handshake proceeds while the message_sequence is invalid.
capture.zip
We generated models for eclipse's TinyDTLS server application (dtls-server) using state fuzzing. On analyzing the models, one of the glaring problems we could identify was that the application can crash on receiving an unexpected ChangeCipherSpec. By unexpected, I mean that it is received at the wrong point in the handshake.
For example, it crashes if it receives ChangeCipherSpec (CCS) while listening, or any time before the ClientHello - ServerHello exchange. It does not crash afterwards. While you wouldn't expect to receive such messages from conforming DTLS clients, I think the behavior is still problematic, as it allows any adversary to crash the server application.
Attached at the end of this message is a .zip archive containing a raw CCS and a pcap version of it which can be viewed in Wireshark.
Just start the server:
./tests/dtls-server -p 20000
Then send the raw CCS packet via bash:
cat < ccs > /dev/udp/127.0.0.1/20000
The server should crash.
Hi,
I'm working with embedded devices and CoAP (libCoap) with RPK. Using your library I made a working prototype.
Now I'm working on an optimization: I would like to configure public server key on device memory so It hasn't to be exchange on every handshake. Is it possible? Right now I made it work by manually editing dtls.c:
case DTLS_HT_SERVER_KEY_EXCHANGE:
if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
//return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
}
..... add check_server_certificate with my server public key ....
err = check_server_key_exchange_ecdsa(ctx, peer, data, data_length);
}
Thanks a lot,
Flavio
How is the retransmission of handshake messages done in tinydtls? Based on my testing (by dropping a handshake message manually on the client), there is currently no retransmission done automatically.
Do I need to call dtls_check_retransmit()
after a certain period after sending the handshake message?
Also, I found the following in dtls.c
. Does this mean that retransmitting handshake messages is still not supported?
Lines 1649 to 1651 in d99fb8c
How to trigger
During a handshake, when a client expects a server hello
message, if a maliciously crafted message with the handshake type 0x0c
(server key exchange) is sent to the client followed by a server hello done
, the client first processes the message as a server key exchange
. This successful processing of the server key exchange
message changes the state of the client to DTLS_STATE_WAIT_SERVERHELLODONE
. Later, when the server hello done
message is processed, the dtls_send_client_key_exchange
function is invoked. In this step, based on the handshake->cipher
, different functionalities are activated. Since the client and server did not agree on any cipher (no server hello is received by the client), the assertion under the case TLS_NULL_WITH_NULL_NULL
will be failed.
Take the following maliciously crafted message:
This message was originally a server hello
message. We only changed the handshake type to 0x0c
(server key exchange). This modification will trigger the assertion.
I attached the maliciously crafted message in the following:
malicious-message2.zip
Hello again,
The bug occurs in the part that is responsible for checking the validity of the record sequence number
. This bug is found by employing symbolic execution technique. When a packet is being processed (in dtls_handle_message()
), if a peer is initialized (dtls_peer_t *peer
), TinyDTLS checks for the validity of the record sequence number
. In the case that (pkt_seq_nr > security->cseq.cseq
), we have shift operations as the following:
security->cseq.bitfield <<= (pkt_seq_nr-security->cseq.cseq);
security->cseq.bitfield |= 1<<((pkt_seq_nr-security->cseq.cseq)-1);
we know that cseq.bitfield
is an unsigned long (64-bit) and 1 is an unsigned integer (32-bit). Therefore, if the value of pkt_seq_nr-security->cseq.cseq
is greater equal to 64 there is an over-shift for the first statement and for the values of pkt_seq_nr-security->cseq.cseq
greater equal to 32 there is an over-shift for the second statement. Finally, since pkt_seq_nr-security->cseq.cseq
refers to the Record Sequence Number
in a dtls record, for the Record Sequence Number > 32
, we will have an over-shift.
I have attached the means to reproduce the mentioned bug. To do so, after downloading the suite, in tinydtls-master-witness/tests
, execute the script setupserver.sh
to compile TinyDTLS with Undefined Behavior Sanitizor
. Note that, I have de-randomized TinyDTLS for this demonstration and the patch is available in tinydtls-master-witness/tests/patches
. Successful execution of setupserver.sh
will run the dtls-server
on port 20220. Now, executing ./reproduce.sh
in tinydtls-master-witness/tests
should result in the following run-time error from the sanitizer:
I hope I could explain it understandably. I appreciate the confirmation of the bug.
tinydtls-master-witness.zip
Best,
Hooman Asadian
Hi,
We reported a use-after-free bug by sending an email to [email protected] over a month ago.
However, we have not gotten any responses yet.
Any suggestions for reporting security bugs of the tinydtls project?
Thanks,
nop
In handle_handshake_msg(), the variable peer is checked in:
if (peer) {
dtls_stop_retransmission(ctx, peer);
}
This indicates that peer can be NULL.
If so, some null-dereference bugs will occur in handle_handshake_msg().
peer is also checked in line 3436:
if (peer && !peer->handshake_params)
and it is dereferenced in line 3451:
peer->state = DTLS_STATE_CLIENTHELLO;
RIOT-OS/RIOT#16422 correctly states that calling dtls_close()
may result in a session held in state DTLS_STATE_CLOSING
forever if no alert messages from the peer are received. Reasons for this might be dropped packets or a crashed/gone peer. A viable solution could include triggering cleanup (either through dtls_reset_peer()
or dtls_destroy_peer()
) after some timeout.
The docs of dtls_decrypt say that "Unlike dtls_encrypt(), the source and destination of dtls_decrypt() may overlap".
Given that dtls_encrypt doesn't say anything about that, and the code contains explicit provisions for src=buf, that remark is likely to be outdated.
@boaks has proposed a new development process which I support. The changes will include renaming the master branch to main
.
main
will contain contributions that have been reviewed by two different team members.main
branch.Renaming the default branch will need a slight change on your local working copies as described here. You can do the change at your convenience as for the time being a redirect will be in place.
Analyzing recent comment on issue #79, I realized, that there is no protection from processing Application Data before the Finish is processed and verified successful.
application_records_before_finish.pcapng.gz
Logs:
Dec 22 15:00:48 DEBG client_random: (32 bytes): 61C32F903B60B0299900EAEA040FD2FDD729B5E40288958F478AC4574926B658
Dec 22 15:00:48 DEBG server_random: (32 bytes): 000000009EA0AE8BC1941D81E2098E2303FEA853190F79F98FB564DB8CE4F395
Dec 22 15:00:48 DEBG pre_master_secret: (22 bytes): 0009000000000000000000000973656372657450534B
Dec 22 15:00:48 DEBG extended_master_secret: (48 bytes): 9676115C2189E53D285E460A6C34D02477EFB693DAC29E104FF4BD80A42377072C7F8860931717D782113CC67D6D0157
Dec 22 15:00:48 DEBG key_block (40 bytes):
Dec 22 15:00:48 DEBG client_MAC_secret: (0 bytes):
Dec 22 15:00:48 DEBG server_MAC_secret: (0 bytes):
Dec 22 15:00:48 DEBG client_write_key: (16 bytes): C1E640D693A53D39DEB4CE7FE50527C6
Dec 22 15:00:48 DEBG server_write_key: (16 bytes): 4DDFF99804421A14FA431852E450100F
Dec 22 15:00:48 DEBG client_IV: (4 bytes): 18B4A717
Dec 22 15:00:48 DEBG server_IV: (4 bytes): B4ECA47FDec 22 15:00:48.227 DEBG * [::ffff:127.0.0.1]:5684 <-> [::ffff:127.0.0.1]:58926 (if1) DTLS: received 56 bytes
Dec 22 15:00:48 INFO received message of type 23, epoch 1
Dec 22 15:00:48 DEBG dtls_handle_message: FOUND PEER
Dec 22 15:00:48 DEBG got 'application_data' epoch 1 sequence 1 (56 bytes)
Dec 22 15:00:48 DEBG nonce: (16 bytes): 18B4A717000100000000000100000000
Dec 22 15:00:48 DEBG key: (16 bytes): C1E640D693A53D39DEB4CE7FE50527C6
Dec 22 15:00:48 DEBG ciphertext: (35 bytes): EC9D188E8376AE0A198B5A49CEC58F5FAF95C4E212B786A5E3B452A4AB9AAA0AE30E88
Dec 22 15:00:48 DEBG decrypt_verify(): found 27 bytes cleartext
Dec 22 15:00:48 DEBG cleartext: (27 bytes): 4801FCB65074B39ACC7951E9396C6F63616C686F73748474696D65
Dec 22 15:00:48 DEBG new bitfield is 1 sequence base 1
Dec 22 15:00:48 DEBG receive header: (13 bytes):
00000000 17 FE FD 00 01 00 00 00 00 00 01 00 2B
Dec 22 15:00:48 DEBG receive unencrypted: (27 bytes):
00000000 48 01 FC B6 50 74 B3 9A CC 79 51 E9 39 6C 6F 63
00000010 61 6C 68 6F 73 74 84 74 69 6D 65
Dec 22 15:00:48 INFO ** application data:
v:1 t:CON c:GET i:fcb6 {5074b39acc7951e9} [ Uri-Host:localhost, Uri-Path:time ]
Dec 22 15:00:48.227 DEBG call custom handler for resource 'time'
Sending data back is blocked, but for me, the received Application Data must be dropped as well.
The same applies to Alert, that receiving an Alert after CCS before Finish should be dropped.
According RFC6347, 4.2.1. Denial-of-Service Countermeasures, page 17
When the second ClientHello is received, the server can verify that
the Cookie is valid and that the client can receive packets at the
given IP address. In order to avoid sequence number duplication in
case of multiple cookie exchanges, the server MUST use the record
sequence number in the ClientHello as the record sequence number in
its initial ServerHello. Subsequent ServerHellos will only be sent
after the server has created state and MUST increment normally.
The implementation in dtls.c, handle_handshake_msg, line 3631
uses
peer->handshake_params->hs_state.mseq_r = dtls_uint16_to_int(hs_header->message_seq);
peer->handshake_params->hs_state.mseq_s = 1;
I think, the initial value for hs_state.mseq_s
value should be also dtls_uint16_to_int(hs_header->message_seq)
. A test, with an expired cookie and second hello_verify should demonstrate, if my assumption is right.
It has been a very long time since tinydtls has an official release (0.8.2 was released in 2015: https://sourceforge.net/projects/tinydtls/files/r5/tinydtls-0.8.2.tar.gz/download).
tinydtls eclipse website states that 0.9 was released in November 2017: https://projects.eclipse.org/projects/iot.tinydtls. However, I can't find this version anywhere.
From my understanding, develop branch fixes CVE-2017-7243 (#12) as well as other security issues:
68a1cda, 494a40d and 2d9f0a8
So it would be really nice to have a new version to be able to use it in distros (buildroot being one of those).
OS
Linux, Ubuntu 20
develop branch, commit c20c632
Affects both clients and servers
Non-conformance
According to the RFC, decrypt_error alerts should be generated when:
A handshake cryptographic operation failed, including being unable
to correctly verify a signature or validate a Finished message.
None of these happen in the below capture. Therein, the client receives an unencrypted HelloVerifyRequest with epoch 1 is received. The message is unencrypted. The fact that it has epoch 1 should mean that it should not be processed/should instead be discarded/ rejected.
The issue also affects servers. In the capture below, an ClientKeyExchange with epoch 1 elicits a decrypt_error response from the server for no good reason.
Abruptly terminating the handshake on receiving a record with an epoch for which a session has not been established has a more severe implication. In case Finished (epoch 1) is received before ChangeCipherSpec (epoch 0) or ClientKeyExchange (epoch 0), the TinyDTLS client/server will abruptly terminate the handshake. This can happen in real world due to reordering. A capture of this is shown below exposing the problem on clients. Notice that the ChangeCipherSpec of the server is sent before Finished, to mimic this scenario. Finished appears as an "Encrypted Handshake Message" in the capture, as it cannot be decrypted by Wireshark.
Steps to Reproduce
I attached files necessary for reproduction using DTLS-Fuzzer, a Java-based tool for testing DTLS libraries. Also included in the archive the captures of the interaction show above. DTLS-Fuzzer requires the JDK for Java 8. On Ubuntu, this can be installed by running:
sudo apt-get install openjdk-8-jdk
Unpack the archive, cd
to resulting folder and run bash reproduce.sh test_sequence_decrypt
or bash reproduce.sh test_sequence_reorder
, while running an instance of Wireshark on the side. The reproduction script will:
I also added the test sequence 'test_sequence_handshake'. This is similar to the reordering sequence, but without the reordering. By executing this sequence via bash reproduce.sh test_sequence_handshake
, you should complete the handshake with the client.
Note that the problems affect both clients and servers. On request, I can provide reproduction scripts also for servers. I am guessing fixing the problem for clients will also do it for servers.
Thanks!
branch: development
commit: 290c48d with PR #52 and PR #53 cherry picked
(I assume, this is not related to this exact version.)
Running Eclipse Californium Interoperability Tests continuously, I faced rare failures using RPK.
Starting with one of the reported failure:
Mar 23 01:17:48 DEBG got packet 22 (98 bytes)
Mar 23 01:17:48 DEBG new packet arrived with seq_nr: 4
Mar 23 01:17:48 DEBG new bitfield is : b
Mar 23 01:17:48 DEBG receive header: (13 bytes):
00000000 16 FE FD 00 00 00 00 00 00 00 04 00 55
Mar 23 01:17:48 DEBG receive unencrypted: (85 bytes):
00000000 0F 00 00 49 00 04 00 00 00 00 00 49 04 03 00 45
00000010 30 43 02 1F 4C E9 93 20 8C B2 18 B2 33 C2 CF 99
00000020 C8 C1 AA 16 FA FA 86 8C 9C 23 3D DA 4C 8D 70 B7
00000030 16 ED 5D 02 20 67 0F B5 2A 8B 58 BE 31 96 D5 D6
00000040 BB 19 02 EA 52 9C 5B 4D F1 47 72 28 8E F1 EC BC
00000050 96 2F FF A2 DC
Mar 23 01:17:48 DEBG received handshake packet of type: certificate_verify (15)
Mar 23 01:17:48 DEBG handle handshake packet of type: certificate_verify (15)
Mar 23 01:17:48 ALRT the packet length does not match the expected
Mar 23 01:17:48 WARN error in check_client_certificate_verify err: -562
I recognized, that tinydtls seems to assume, that the SHA256-ECDSA signature has a fixed length (86 bytes).
According Shouldn't a signature using ECDSA be exactly 96 bytes, not 102 or 103? the length of such a signature may be encoded in a variable way.
I got additionally faced similar failures:
Mar 21 11:22:28 DEBG got packet 22 (99 bytes)
Mar 21 11:22:28 DEBG new packet arrived with seq_nr: 4
Mar 21 11:22:28 DEBG new bitfield is : b
Mar 21 11:22:28 DEBG receive header: (13 bytes):
00000000 16 FE FD 00 00 00 00 00 00 00 04 00 56
Mar 21 11:22:28 DEBG receive unencrypted: (86 bytes):
00000000 0F 00 00 4A 00 04 00 00 00 00 00 4A 04 03 00 46
00000010 30 44 02 1F 22 1A F7 1E EE 84 DB 50 51 4A DC C9
00000020 16 67 A9 16 56 CC B0 79 73 A2 80 7B 6C C4 74 44
00000030 A1 C3 D7 02 21 00 99 AC 0A 91 80 09 6B 8A D2 DA
00000040 32 7A E0 C0 2F 1D 9F 92 4C EA 2B BE 89 9F D7 09
00000050 3F E6 AE 7C 91 37
Mar 21 11:22:28 DEBG received handshake packet of type: certificate_verify (15)
Mar 21 11:22:28 DEBG handle handshake packet of type: certificate_verify (15)
Mar 21 11:22:28 ALRT wrong signature err: -1
Mar 21 11:22:28 WARN error in check_client_certificate_verify err: -552
where the total length is 86, but the keys have different lengths. Generally, zero-bytes seems to be removed, if the next byte has less than 0x7f. Otherwise one 0x00 is kept for values 0x80 and larger.
I encountered this when testing PR #19 with the latest develop branch. Using the RIOT dtls-echo example, sending a packet from a client to a server will fail.
Apply the diff to the RIOT repository and run the dtls-echo example.
Use latest develop tinydtls branch on RIOT and enable debug by applying this diff:
diff --git a/examples/dtls-echo/Makefile b/examples/dtls-echo/Makefile
index 325078eac..91a51bc93 100644
--- a/examples/dtls-echo/Makefile
+++ b/examples/dtls-echo/Makefile
@@ -42,7 +42,7 @@ CFLAGS += -DDTLS_DEFAULT_PORT=$(DTLS_PORT)
# NOTE: If not cipher suite is selected, DTLS_PSK is used by default.
# This adds support for TLS_PSK_WITH_AES_128_CCM_8
-# CFLAGS += -DDTLS_PSK
+CFLAGS += -DDTLS_PSK
# This adds support for TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
# CFLAGS += -DDTLS_ECC
@@ -52,7 +52,7 @@ TINYDTLS_LOG ?= 0
# Enable this line for setting tinyDTLS in debug mode.
# This overrides TINYDTLS_LOG to 6
-# CFLAGS += -DTINYDTLS_DEBUG
+CFLAGS += -DTINYDTLS_DEBUG
# FIXME: This is a temporary patch
# TinyDTLS <= 0.8.6 requires around 426 bytes in RAM.
diff --git a/pkg/tinydtls/Makefile b/pkg/tinydtls/Makefile
index e1a8483d0..802c5bc70 100644
--- a/pkg/tinydtls/Makefile
+++ b/pkg/tinydtls/Makefile
@@ -1,6 +1,6 @@
PKG_NAME=tinydtls
PKG_URL=https://github.com/eclipse/tinydtls.git
-PKG_VERSION=dcac93f1b38e74f0a57b5df47647943f3df005c2
+PKG_VERSION=494a40dfbb174930ca616e560532d52549736b42
PKG_LICENSE=EPL-1.0,EDL-1.0
CFLAGS += -Wno-implicit-fallthrough
> dtlss start
dtlss start
> Oct 02 15:31:34 DEBG dtls_handle_message: PEER NOT FOUND
Oct 02 15:31:34 DEBG got packet 22 (95 bytes)
Oct 02 15:31:34 DEBG receive header: (13 bytes):
00000000 16 FE FF 00 00 00 00 00 00 00 00 00 52
Oct 02 15:31:34 DEBG receive unencrypted: (82 bytes):
00000000 01 00 00 46 00 00 00 00 00 00 00 46 FE FD 00 00
00000010 00 05 E9 CC A0 AC 1C C1 EB E4 52 EB 47 70 CC 83
00000020 A1 0C C9 D1 C9 69 5E 0D 28 01 1F F1 C6 05 00 00
00000030 00 02 C0 AE 01 00 00 1A 00 13 00 02 01 02 00 14
00000040 00 02 01 02 00 0A 00 04 00 02 00 17 00 0B 00 02
00000050 01 00
Oct 02 15:31:34 DEBG received handshake packet of type: client_hello (1)
Oct 02 15:31:34 DEBG handle handshake packet of type: client_hello (1)
Oct 02 15:31:34 WARN error in dtls_verify_peer err: -552
Oct 02 15:31:34 WARN error while handling handshake packet
Oct 02 15:33:24 DEBG dtls_handle_message: PEER NOT FOUND
Oct 02 15:33:24 DEBG got packet 21 (15 bytes)
Oct 02 15:33:24 DEBG receive header: (13 bytes):
00000000 15 FE FD 00 00 00 00 00 00 00 01 00 02
Oct 02 15:33:24 DEBG receive unencrypted: (2 bytes):
00000000 02 00
Oct 02 15:33:24 INFO ** Alert: level 2, description 0
Oct 02 15:33:24 WARN got an alert for an unknown peer, we probably already removed it, ignore it
> dtlsc fe80::2051:47ff:fec8:edcf heyyy
dtlsc fe80::2051:47ff:fec8:edcf heyyy
Oct 02 15:31:34 DEBG DTLSv12: initialize HASH_SHA256
Oct 02 15:31:34 DEBG send handshake packet of type: client_hello (1)
Oct 02 15:31:34 DEBG send header: (13 bytes):
00000000 16 FE FF 00 00 00 00 00 00 00 00 00 52
Oct 02 15:31:34 DEBG send unencrypted: (12 bytes):
00000000 01 00 00 46 00 00 00 00 00 00 00 46
Oct 02 15:31:34 DEBG send unencrypted: (70 bytes):
00000000 FE FD 00 00 00 05 E9 CC A0 AC 1C C1 EB E4 52 EB
00000010 47 70 CC 83 A1 0C C9 D1 C9 69 5E 0D 28 01 1F F1
00000020 C6 05 00 00 00 02 C0 AE 01 00 00 1A 00 13 00 02
00000030 01 02 00 14 00 02 01 02 00 0A 00 04 00 02 00 17
00000040 00 0B 00 02 01 00
Oct 02 15:33:24 DEBG send header: (13 bytes):
00000000 15 FE FD 00 00 00 00 00 00 00 01 00 02
Oct 02 15:33:24 DEBG send unencrypted: (2 bytes):
00000000 02 00
Does tinydtls support the dtls connection id extension? (See https://datatracker.ietf.org/doc/draft-ietf-tls-dtls-connection-id/ for details)
If not, does anyone familiar with the project have an idea of how much effort it would be to add support?
Version: development branch
Expected behavior
The DTLS RFC specifies the following requirement regarding the fragment offset
and fragment length
when fragmentation is not present:
An unfragmented message is a degenerate case with fragment_offset=0 and fragment_length=length
Actual behavior
One can complete a handshake with the following values for the fragment_offset
and fragment_length
:
CKE.message_length = 17
CKE.fragment_length = 16777198
CKE.fragment_offset = 255
The problem also exists when the server sends records with non-compliant Fragment_offset
and fragment_length
.
I have attached the handshake trace for the mentioned non-conformance. You clearly see that the handshake proceeds while the Fragment_offset
and fragment_length
are invalid.
capture.zip
Hello,
In both the master branch and develop branch, an illegal over-read bug has been found when the server handles a malicious message with the following values for the mentioned fields:
After the server handles this message in the normal way as follows(in the master branch), we enter into the function dtls_ccm_decrypt_message() at ccm.c:264.
1. 0x4e4b33 in dtls_ccm_decrypt_message /home/Research/benchmarks/tinydtls/ccm.c:264:5
2. 0x4dd76a in dtls_ccm_decrypt /home/Research/benchmarks/tinydtls/crypto.c:301:9
3. 0x4dd76a in dtls_decrypt /home/Research/benchmarks/tinydtls/crypto.c:561:9
4. 0x4cbfe7 in decrypt_verify /home/Research/benchmarks/tinydtls/dtls.c:3035:12
5. 0x4c9bbc in dtls_handle_message /home/Research/benchmarks/tinydtls/dtls.c:3746:25
6. 0x4c67bc in dtls_handle_read /home/Research/benchmarks/tinydtls/tests/dtls-server.c:177:10
7. 0x4c67bc in main /home/Research/benchmarks/tinydtls/tests/dtls-server.c:352:2
8. 0x7f8454dbb0b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
9. 0x41c3bd in _start (/home/Research/benchmarks/tinydtls/tests/dtls-server+0x41c3bd)
In the function dtls_ccm_decrypt_message(), the value of variable lm is larger than the length of the current packet, whose value is less than 1400. Hence, an illegal memory access bug appears, which leads to the server crashing, memory leak and other effects.
From DTLS12 RFC, the server should have the ability to fragment large packets. If not, over-large packets should be refused.
In current both master and develop branches, this bug could be reproduced with this packet: ReproduciablePacket.
Could you kindly have a check? Thanks a lot.
Hello,
I have tried to submit this through Eclipse Bugzilla. However, apparently, the dedicated page for TinyDTLS has been removed or I did not have access to it. The following over-read has been found by using symbolic execution technique. Suppose you have a Client Key Exchange
message with the following values for the mentioned fields:
length
in the record layer = 25length
in the handshake layer = 51fragment length
= 16fragment offset
= 0When we are handling the message (in dtls_handle_message()
), data_length = decrypt_verify(peer, msg, rlen, &data)
is called. It returns a pointer to the first offset of the handshake layer (uint8 *data
) and the real size of the handshake layer (data_length = 25
). Later, as we have packet_length=51 > fragment_length=16
, we start the reassembling process. the message also pass fragment_offset=0 + fragment_length=16 <= packet_length=51
check. Finally, after allocating memory on the heap (peer->handshake_params->reassemble_buf->data
), when we are going to copy the message (memcpy) into the newly allocated buffer, we use the combination of fragment offset
and fragment length
to derive the size of the handshake message and the pointer (data
) as it points to the first offset of the handshake layer. Let me remind you that the valid range for data
is 25 (=data_length
). However, in this scenario, the size (fragment_length=16 + handshake_header_size=12) is 28. Therefore, there is a 3-byte overread happening.
I have attached the means to reproduce the mentioned bug. To do so, after downloading the suite, in tinydtls-witness/tests
, execute the script setupserver.sh
to compile TinyDTLS
. Note that, I have de-randomized TinyDTLS for this demonstration and the patch is available in tinydtls-witness/tests/patches
. Successful execution of setupserver.sh
will run dtls-server
on port 20220. Now, executing ./reproduce.sh
in tinydtls-witness/tests
should cause dtls-server
to crash.
The malformed Client Key Exchange
can be found in tinydtls-witness/tests/testcases
.
I hope I could explain it understandably.
tinydtls-witness.zip
Best wishes,
Hooman Asadian
dtls_time.h seems to be uint32_t aware:
Line 64 in 68b2521
but these lines may produce problems with 32bit overflow:
these calculate possibly overflowing time stamps:
Line 1763 in 68b2521
Line 4534 in 68b2521
these do not deal with overflowing timestamps:
calculating if the timeout happend: (timestamp passed by)
Line 4596 in 68b2521
inserting (sorted) into the netq
Line 96 in 68b2521
In #123 @boaks and me pointed that out
reference / line number are current develop branch
Hello,
In this case, the server sends a server_hello
to the client where the record_length
is smaller than the value it is supposed to be like the following (24 instead of 50):
Therefore, data_length
will wrap-around here and later is used to read the extensions
here which causes the client to crash.
I have attached the means to reproduce the mentioned bug. To do so, after downloading the suite, in tinydtls-develop/tests
, execute the script setupserver.sh
to compile TinyDTLS and simple-udp-server
. Note that, I have de-randomized TinyDTLS for this demonstration. Successful execution of setupserver.sh
will run simple-udp-server
on port 20220. Now, if you execute reproduce.sh
, it will initiate a handshake with simple-udp-server
and crashes the client.
Best,
Hooman Asadian
The dtls-server application will complete a handshake wherein the first two ClientHello carrying records sent by the client have epochs 1, while the rest have regular epochs (ClientKeyExchange and ChangeCipherSpec have epochs 0, Finished has epoch 1).
Attached at the end of the message is an archive containing a Wireshark capture of the invalid handshake. I am also posting an image of how this capture looks like, so that the interaction becomes clear.
Note that the server was configured to use the PSK password 1234 (you can input this in wireshark in order to decrypt the last finished messages).
Cheers, Paul.
Using tinydtls "develop" branch as binding for libcoap, I receive the CLOSE_NOTIFY
alert with level FATAL
.
AFAIK, that should be WARNING
.
So, is the FATAL
intended?
Hello,
In the project master branch, an infinite loop bug had been found during handling ClientHello Handshake message. Suppose you have a malicious ClientHello message with the following values for the mentioned fields:
1. Cipher Suites Length is an odd number like 3 (this is a malicious number)
2. Two Suites whose length is 4 bytes
3. Extension Length whose length is not zero like 26 bytes
After handling this message in the normal handling way as follows, we enter into the function dtls_update_parameters() at the dtls.c:980.
1. 0x4e2b02 in dtls_update_parameters /home/etinydtls/dtls.c:1024:22
2. 0x4e2b02 in handle_handshake_msg /home/etinydtls/dtls.c:3403:11
3. 0x4cb1ce in handle_handshake /home/etinydtls/dtls.c:3493:14
4. 0x4cb1ce in dtls_handle_message /home/etinydtls/dtls.c:3881:13
5. 0x4c4efc in dtls_handle_read /home/etinydtls/tests/dtls-server.c:177:10
6. 0x4c4efc in main /home/etinydtls/tests/dtls-server.c:352:2
7. 0x7fb176ab10b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
8. 0x41c45d in _start (/home/etinydtls/tests/dtls-server+0x41c45d)
When coming to dtls.c:1005 in the function dtls_update_parameters(), variable i is assigned to a int number, which stands for all cipher suites' length 3 in this message. After that, the condition data_length < i + sizeof(uint16) cannot refuse this packet cannot exclude this packet, as 4+26 < 3+2 is no satisfied. Hence, we come to the loop of confirming suites at the dtls.c:1023, where i is decreased by 2 each loop. The ending loop condition includes (i == 0), while the initial value of i is 3 thereby this condition will not be satisfied. Unfortunately, one infinite loop incurs, which lets the server loop forever until consuming all resources.
Here is a message packet to reproduce this bug: [https://github.com/jerrytesting/dtls-infiniteLoop.git]
I hope I could explain it clearly. Could you kindly have a check? Thanks a lot.
Kind Regards,
Jerry
Hi,
This bug occurs when the server is unable to retrieve the cookie from a ClientHello
.
Suppose that we send the following ClientHello
to the server:
As you can see, the Handshake version has an invalid value. This causes the server to fail to fetch the cookie here. The problem is that the server returns the err
here instead of the len
and the value for err
is zero (because of here). returning zero short circuits the cookie check and causes the server to proceed with the handshake by sending the ServerHello
and ServerHelloDone
. This makes TinyDTLS servers susceptible to Denial of Service attack.
I have attached the handshake trace in which we bypassed the cookie exchange mechanism by providing invalid values for the Handshake version.
Hello again,
This bug occurs when the server receives a malformed Client Hello
to initialize a handshake and it affects the master branch. This bug is found by employing symbolic execution technique. Suppose you have a malformed Client Hello
where the length
field in the handshake layer is 0. When the mentioned Client Hello
is received by the server, dtls_verify_peer()
calls dtls_create_cookie()
for cookie generation. Inside dtls_create_cookie()
, TinyDTLS defines e
which is unsigned (size_t
). Later, when we call the following update function:
dtls_hmac_update(&hmac_context,
msg + DTLS_HS_LENGTH + e,
dtls_get_fragment_length(DTLS_HANDSHAKE_HEADER(msg)) - e);
the macro dtls_get_fragment_length(DTLS_HANDSHAKE_HEADER(msg))
will return 0. Therefore, since e
is unsigned, dtls_get_fragment_length(DTLS_HANDSHAKE_HEADER(msg)) - e
will wrap around and evaluates to a very huge number(e.g 18446744073709551580). This huge value, in turns will cause a memory over-read in the memcpy in sha2.c.
I have attached the means to reproduce the mentioned bug. To do so, after downloading the suite, in tinydtls-master-witness/tests
, execute the script setupserver.sh
to compile TinyDTLS. I have not changed anything in the code for the sake of this demonstration. Successful execution of setupserver.sh will run the dtls-server on port 20220. Now, executing ./reproduce.sh
in tinydtls-master-witness/tests
should crash the server as shown in the following figure:
I hope I could explain it understandably and I appreciate your confirmation of the bug.
tinydtls-master-witness.zip
Best,
Hooman Asadian
Just to mention: the HELLO_EXTENSIONs are also including lengths
.
Did you already checked that?
I really appreciate tinydtls gets hardened.
The PSK authentication with ciphersuite TLS_PSK_WITH_AES_128_CCM_8, carries PSK ID:
memcpy(p, handshake->keyx.psk.identity, handshake->keyx.psk.id_length);
p += handshake->keyx.psk.id_length;
So does i mean it serves as client authentication ?? -- If server posses the psk mapped to that psk_id it goes on with handshake, if not reports error.
Or is it server authentication by client which checks if server has the psk mapped to that psk_id, client can verify if the server is indeed in possession of psk mapped to the psk_id it sent, if and only if server sends a finished message, which client can authenticate correctly.
Version: development branch
Expected behavior
The DTLS RFC specifies the following regarding the record sequence number:
For each received record, the receiver MUST verify that the record contains a sequence number that does not duplicate the sequence number of any other record received during the life of this session. Duplicates are rejected through the use of a sliding receive window. The "right" edge of the window represents the highest validated sequence number value received on this session. Records that contain sequence numbers lower than the "left" edge of the window are rejected.
Actual behavior
One can complete a handshake with the following values for the record sequence number:
CH0.sequence_number = 0
CH2.sequence_number = 68
CKE.sequence_number = 0
CCC.sequence_number = 0
The problem also exists when the server sends records with non-unique record sequence numbers.
I have attached the completed handshake trace for the mentioned non-conformance.
OS
Linux, Ubuntu 20
develop branch, commit c20c632
Expected behavior
The client should not proceed with a handshake where it receives distinct consecutive CertificateRequest messages.
Actual Behavior
Our testing shows that the client upon receiving these messages proceeds with the handshake as normal; upon receiving ServerHelloDone, it generates the next flight of messages as can be seen in the capture below taken on my machine.
Note that the later CertificateRequest is not a retransmission of the former. Its message_sequence value differs, so it should have been processed as a distinct handshake message.
Steps to Reproduce
I attached files necessary for reproduction using DTLS-Fuzzer, a Java-based tool for testing DTLS libraries. Also included in the archive is a capture of the interaction show above. DTLS-Fuzzer requires the JDK for Java 8. On Ubuntu, this can be installed by running:
sudo apt-get install openjdk-8-jdk
Unpack the archive, cd
to resulting folder and run bash reproduce.sh
, while running an instance of Wireshark on the side. The reproduction script will:
Thanks!
Adapting Eclipse Californium to my interpretation of RFC 6347 - Section 4.2.1 using 1.0 for the protocol version in the record header and in the server_version field of the hello_verify_request, that caused trouble with not compliant clients.
Investigating, it seems that RFC6347 is ambiguous about that. I wrote a e-mail to the IETF TLS mailing list,
see RFC 6347 - Section 4.2.1 - used version in a HelloVerifyRequest.
As far as I understand, tinydtls is using 1.0 for the record protocol version and 1.2 for the server_version in the hello_verify_request. There is a comment in dtls.c
Signal DTLS version 1.0 in the record layer of ClientHello and
HelloVerifyRequest handshake messages according to Section 4.2.1
of RFC 6347.This does not apply to a renegotation Client Hello
Are there any additional references about that?
Just to mention:
openssl: 1.0 for both
gnutls: 1.0 for both
mbedtls: 1.2 for both.
in develop-branch, dtls.c, dtls_update_parameters:
/* Looks like we do not have a cipher nor compression. This is ok
* for renegotiation, but not for the initial handshake. */
Logical/functional it seems to be OK for me.
But do you have also a RFC cite for that?
RFC5246 - 7.4.1.2. Client Hello
CipherSuite cipher_suites<2..2^16-2>;
CompressionMethod compression_methods<1..2^8-1>;
FMPOV, that implies at least 2 and 1 byte must be used, empty would be <0..
.
If the
session_id field is not empty (implying a session resumption
request), this vector MUST include at least the cipher_suite from
that session.
...
If the session_id field is not empty
(implying a session resumption request), it MUST include the
compression_method from that session. This vector MUST contain,
and all implementations MUST support, CompressionMethod.null.
Thus, a client and server will always be able to agree on a
compression method.
That refers to a resumption, so it may not apply. But I miss similar statements for renegotiation.
How to trigger
When the server is expecting a change cipher spec
record during the handshake, if a maliciously crafted record with the content type 0x15
(Alert) is sent to the server, the server identifies it as an Alert
record. the server then processes the record as an Alert
and based on the output value of the handle_alert
and the type of the Alert
, shows a warning. Accessing the out-of-bound pointer occurs when the server accesses the type of the Alert
.
Take the following maliciously crafted record:
This record was originally a change cipher spec
record. We only changed the content type to 0x15
(Alert). Notice that there is only one byte in the record (Length = 1). When this record is sent to the server, after the server processes it as an Alert
, it attempts to identify the type of Alert by accessing data[1]
that is out-of-bound access.
I attached the maliciously crafted message in the following:
malicious-message3.zip
Hello again,
The following over-read happens when you send a fragmented Server Hello message to the client. The bug is found employing symbolic execution technique. Suppose you have a Server Hello
message with the following values for certain fields:
length
in the record layer = 46length
in the handshake layer = 0fragment length
= 128When we are handling the message (in dtls_handle_message()
), data_length = decrypt_verify(peer, msg, rlen, &data)
is called. It returns a pointer to the first offset of the handshake layer (uint8 *data
) and the real size of the handshake layer (data_length
= 46). Later inside check_server_hello(ctx, peer, data, data_length)
, Tiny tries to read different fields of the Server Hello
message. It happens by advancing the pointer data
and deducting the data_length
. As I previously mentioned, the Server Hello
is fragmented and it contains only up to the random
field (handshake header = 12
bytes + handshake version = 2
bytes + random = 32
bytes). Therefore, after advancing the pointer (data
) for 46 bytes, Tiny tries to skip the Session ID
by calling the Macro (SKIP_VAR_FIELD(data, data_length, uint8)
). However, Tiny already has advanced the pointer (data
) for 46 bytes, and the pointer (data
) is currently pointing to invalid memory. Therefore, here we have a one-byte over-read. I have added the assertion (assert(data_length > 0)
) before SKIP_VAR_FIELD(data, data_length, uint8)
to reveal the invalid read. For reproducing the bug, I have written a small UDP server that plays the role of a DTLS-server.
I have attached the means to reproduce the mentioned bug. To do so, after downloading the suite, in tinydtls-witness/tests, execute the script setupserver.sh
to compile TinyDTLS and simple-udp-server
. Note that, I have de-randomized TinyDTLS for this demonstration and the patch is available in tinydtls-witness/tests/patches
. Successful execution of setupserver.sh
will run simple-udp-server
on port 20220. Now, if you execute reproduce.sh
, it will initiate a handshake with simple-udp-server
and when it gets the Server Hello, the assertion that I added will fail.
I hope I could explain it understandably. I appreciate the confirmation of the reported bugs.
Best,
Hooman Asadian
tinydtls-witness.zip
current version make prf_label_client = tinydtls, while californium makes it as "client", they can not work together.
and https://tools.ietf.org/html/rfc5246#section-7.4.9 tells it shoud be "client", why don't you follow them.
Hello,
The dtls-server application allows completing the second handshake without indicating renegotiation options in the first handshake message, which is prohibited according to RFC 5746.
We could use Wireshark to capture these two handshake processes shown as follows.
This creates the opportunity for an attack in which the attacker who can intercept a client's transport layer connection can inject traffic of his own as a prefix to the client's interaction with the server(cited from RFC 5746).
Could you kindly have a check? Thanks a lot.
Kind Regards,
Jerry
Hi,
In this case, a Hello_verify_request
contains a 16-byte cookie but the cookie_length
is specified 32.
When the Hello_verify_request
is received, we use the cookie_length
to read from the memory in here. It means we have a 16-byte memory over-read. I have attached the malformed Hello_verify_request
for further investigations.
Best,
Hooman Asadian
I currently implement the RFC7627/"extended master secret" for Eclipse/Californium.
First interoperability tests shows, that the tinydtls client of the "develop" branch uses the "extended_master_secret" only for rpk, not for psk. The tinydtls server responses to that extension for both rpk and psk.
Is this behavior, that the client only send "extended_master_secret" for rpk intended?
Hello
I am currently implementing the tinyDTLS in 6lbr with the Sensortag CC2650. Has anyone had success with doing this?
How to compiling and configuring tinyDTLS in 6lbr and Sensortag CC2650?
How to flash the tinyDTLS in Sensortag CC2650?
I am really confused about where to start.
Thank you!
According hs_attempt_with_existing_peer
a DTLS_HT_HELLO_REQUEST is processed for epoch 0 (mean unencrypted, maybe spoofed). Is that really wanted/intended?
If so, I would prefer a "compile-time switch", because in my opinion such a function makes DTLS vulnerable.
How to trigger
During the handshake, when the client expects a handshake message (hello_verify_request, server_hello, server_hello_done), if the server sends a maliciously crafted message with the handshake type 0x01
(client_hello), the client attempts to handle the message by invoking the function handle_0_client_hello
. Later, to verify the peer, the function dtls_0_verify_peer
is called. Notice that the client has mistaken the message as a client hello message at this point; therefore, dtls_create_cookie
is called for cookie generation. Inside this function, the variable e
is initialized to DTLS_CH_LENGTH
. Since the length of this message can be shorter than a legitimate client hello message, in the next line, msg + DTLS_HS_LENGTH + e
points to an out of bound address.
Take the following maliciously crafted message:
This message was originally a hello verify request
message. We only changed the handshake type to 0x01
(client hello). As you notice, all other values such as fragment_length
, record_length
, and handshake_length
are correct. Therefore, all the checks will be successfully passed. When it comes to cookie generation, as it is explained, a memory error occurs. Notice that the check here is too late. I attached the maliciously crafted message in the following.
The description of dtls_connect_peer()
states that it returns 0 when the channel already exists:
Line 269 in 7068882
dtls_renegotiate()
is called which then tries to do a new handshake, but only when the session is established. So either the function would have to check if the connection exists and return 0, or the description doesn't fit, and it needs to be change that it does a re-connect in this case.Line 4010 in 7068882
if (peer->state == DTLS_STATE_CONNECTED) {
return 0;
}
Or am I misunderstanding something here?
Using the given dtls-client
and dtls-server
program in tests/
, the server will fail when the client sends client:renegotiate
.
Snippet from the server debug log (full log):
Dec 18 17:27:48 WARN decryption failed
Dec 18 17:27:48 INFO decrypt_verify() failed
After sending the command, the client also does not react anymore to new inputs from stdin.
In dtls_encrypt and dtls_decrypt, key and nonce are declared mutable (not const). That is unusual for AEAD operations as to my understanding.
Please consider clarifying this, descendingly preferably by
I was trying to send CKE with some additional data[21000] which is obviously very large. Fragmentation at IP layer doesnt work properly and CKE is never exchanged.
Do you have a code with supported fragmentation in tinyDTLS.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.