Skip to content

Commit 64f2a92

Browse files
gpotter2rperez
authored andcommitted
[TLS 1.3] x448 support (secdev#2633)
* Add support for curve x448 * Add x448 tests * Credit Romain Perez Co-authored-by: rperez <rperez@debian>
1 parent e7489dd commit 64f2a92

File tree

10 files changed

+36
-15
lines changed

10 files changed

+36
-15
lines changed

scapy/layers/tls/automaton_cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# This file is part of Scapy
22
# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
33
# 2015, 2016, 2017 Maxence Tury
4+
# 2019 Romain Perez
45
# This program is published under a GPLv2 license
56

67
"""
78
TLS client automaton. This makes for a primitive TLS stack.
89
Obviously you need rights for network access.
910
10-
We support versions SSLv2 to TLS 1.2, along with many features.
11-
There is no session resumption mechanism for now.
11+
We support versions SSLv2 to TLS 1.3, along with many features.
1212
1313
In order to run a client to tcp/50000 with one cipher suite of your choice:
1414
> from scapy.all import *
@@ -981,7 +981,7 @@ def TLS13_START(self):
981981
@ATMT.condition(TLS13_START)
982982
def tls13_should_add_ClientHello(self):
983983
# we have to use the legacy, plaintext TLS record here
984-
supported_groups = ["secp256r1", "secp384r1"]
984+
supported_groups = ["secp256r1", "secp384r1", "x448"]
985985
if conf.crypto_valid_advanced:
986986
supported_groups.append("x25519")
987987
self.add_record(is_tls13=False)

scapy/layers/tls/automaton_srv.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# This file is part of Scapy
22
# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
33
# 2015, 2016, 2017 Maxence Tury
4+
# 2019 Romain Perez
45
# This program is published under a GPLv2 license
56

67
"""
78
TLS server automaton. This makes for a primitive TLS stack.
89
Obviously you need rights for network access.
910
10-
We support versions SSLv2 to TLS 1.2, along with many features.
11-
There is no session resumption mechanism for now.
11+
We support versions SSLv2 to TLS 1.3, along with many features.
1212
1313
In order to run a server listening on tcp/4433:
1414
> from scapy.all import *

scapy/layers/tls/handshake.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# This file is part of Scapy
22
# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
33
# 2015, 2016, 2017 Maxence Tury
4+
# 2019 Romain Perez
45
# This program is published under a GPLv2 license
56

67
"""

scapy/layers/tls/keyexchange.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# This file is part of Scapy
22
# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
33
# 2015, 2016, 2017 Maxence Tury
4+
# 2019 Romain Perez
45
# This program is published under a GPLv2 license
56

67
"""

scapy/layers/tls/keyexchange_tls13.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# This file is part of Scapy
22
# Copyright (C) 2017 Maxence Tury
3+
# 2019 Romain Perez
34
# This program is published under a GPLv2 license
45

56
"""
@@ -26,6 +27,7 @@
2627
from cryptography.hazmat.primitives.asymmetric import dh, ec
2728
if conf.crypto_valid_advanced:
2829
from cryptography.hazmat.primitives.asymmetric import x25519
30+
from cryptography.hazmat.primitives.asymmetric import x448
2931

3032

3133
class KeyShareEntry(Packet):
@@ -67,16 +69,19 @@ def create_privkey(self):
6769
pubkey = privkey.public_key()
6870
self.key_exchange = pubkey.public_numbers().y
6971
elif self.group in _tls_named_curves:
70-
if _tls_named_curves[self.group] == "x25519":
72+
if _tls_named_curves[self.group] in ["x25519", "x448"]:
7173
if conf.crypto_valid_advanced:
72-
privkey = x25519.X25519PrivateKey.generate()
74+
if _tls_named_curves[self.group] == "x25519":
75+
privkey = x25519.X25519PrivateKey.generate()
76+
else:
77+
privkey = x448.X448PrivateKey.generate()
7378
self.privkey = privkey
7479
pubkey = privkey.public_key()
7580
self.key_exchange = pubkey.public_bytes(
7681
serialization.Encoding.Raw,
7782
serialization.PublicFormat.Raw
7883
)
79-
elif _tls_named_curves[self.group] != "x448":
84+
else:
8085
curve = ec._CURVE_TYPES[_tls_named_curves[self.group]]()
8186
privkey = ec.generate_private_key(curve, default_backend())
8287
self.privkey = privkey
@@ -116,11 +121,14 @@ def register_pubkey(self):
116121
public_numbers = dh.DHPublicNumbers(self.key_exchange, pn)
117122
self.pubkey = public_numbers.public_key(default_backend())
118123
elif self.group in _tls_named_curves:
119-
if _tls_named_curves[self.group] == "x25519":
124+
if _tls_named_curves[self.group] in ["x25519", "x448"]:
120125
if conf.crypto_valid_advanced:
121-
import_point = x25519.X25519PublicKey.from_public_bytes
126+
if _tls_named_curves[self.group] == "x25519":
127+
import_point = x25519.X25519PublicKey.from_public_bytes
128+
else:
129+
import_point = x448.X448PublicKey.from_public_bytes
122130
self.pubkey = import_point(self.key_exchange)
123-
elif _tls_named_curves[self.group] != "x448":
131+
else:
124132
curve = ec._CURVE_TYPES[_tls_named_curves[self.group]]()
125133
try: # cryptography >= 2.5
126134
import_point = ec.EllipticCurvePublicKey.from_encoded_point # noqa: E501
@@ -203,7 +211,7 @@ def post_build(self, pkt, pay):
203211
if group_name in six.itervalues(_tls_named_ffdh_groups):
204212
pms = privkey.exchange(pubkey)
205213
elif group_name in six.itervalues(_tls_named_curves):
206-
if group_name == "x25519":
214+
if group_name in ["x25519", "x448"]:
207215
pms = privkey.exchange(pubkey)
208216
else:
209217
pms = privkey.exchange(ec.ECDH(), pubkey)
@@ -226,7 +234,7 @@ def post_dissection(self, r):
226234
if group_name in six.itervalues(_tls_named_ffdh_groups):
227235
pms = privkey.exchange(pubkey)
228236
elif group_name in six.itervalues(_tls_named_curves):
229-
if group_name == "x25519":
237+
if group_name in ["x25519", "x448"]:
230238
pms = privkey.exchange(pubkey)
231239
else:
232240
pms = privkey.exchange(ec.ECDH(), pubkey)
@@ -237,7 +245,7 @@ def post_dissection(self, r):
237245
if group_name in six.itervalues(_tls_named_ffdh_groups):
238246
pms = privkey.exchange(pubkey)
239247
elif group_name in six.itervalues(_tls_named_curves):
240-
if group_name == "x25519":
248+
if group_name in ["x25519", "x448"]:
241249
pms = privkey.exchange(pubkey)
242250
else:
243251
pms = privkey.exchange(ec.ECDH(), pubkey)

scapy/layers/tls/record.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# This file is part of Scapy
22
# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
3-
# 2015, 2016, 2017 Maxence Tury
3+
# 2015, 2016, 2017 Maxence Tury
4+
# 2019 Romain Perez
5+
# 2019 Gabriel Potter
46
# This program is published under a GPLv2 license
57

68
"""

scapy/layers/tls/record_tls13.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# This file is part of Scapy
22
# Copyright (C) 2017 Maxence Tury
3+
# 2019 Romain Perez
34
# This program is published under a GPLv2 license
45

56
"""

scapy/layers/tls/session.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# This file is part of Scapy
22
# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
33
# 2015, 2016, 2017 Maxence Tury
4+
# 2019 Romain Perez
45
# This program is published under a GPLv2 license
56

67
"""

test/tls/example_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
help="Resumption master secret (for TLS 1.3)")
4444
parser.add_argument("--sni",
4545
help="Server Name Indication")
46+
parser.add_argument("--curve", help="ECC group to advertise")
4647
parser.add_argument("--debug", action="store_const", const=5, default=0,
4748
help="Enter debug mode")
4849
parser.add_argument("server", nargs="?", default="127.0.0.1",
@@ -94,6 +95,7 @@
9495
resumption_master_secret=args.res_master,
9596
session_ticket_file_in=args.session_ticket_file_in,
9697
session_ticket_file_out=args.session_ticket_file_out,
98+
curve=args.curve,
9799
debug=args.debug)
98100
t.run()
99101

test/tls/tests_tls_netaccess.uts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ test_tls_client("1303", "0304")
322322

323323
test_tls_client("1305", "0304")
324324

325+
= Testing TLS server and client with TLS 1.3 and TLS_AES_128_CCM_8_SHA256 and x448
326+
~ crypto_advanced
327+
328+
test_tls_client("1305", "0304", curve="x448")
329+
325330
= Testing TLS server and client with TLS 1.3 and a retry
326331
~ crypto_advanced
327332

0 commit comments

Comments
 (0)