Skip to content

Commit 6342bda

Browse files
authored
Merge pull request #530 from tlsfuzzer/ml-kem
support for ML-KEM hybrid key exchange groups
2 parents ba52c6b + bfae6e1 commit 6342bda

File tree

8 files changed

+460
-39
lines changed

8 files changed

+460
-39
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,26 @@ jobs:
180180
os: ubuntu-latest
181181
python-version: '3.11'
182182
opt-deps: ['brotli', 'zstd']
183-
- name: py3.12with brotli and zstandard
183+
- name: py3.12 with brotli and zstandard
184184
os: ubuntu-latest
185185
python-version: '3.12'
186186
opt-deps: ['brotli', 'zstd']
187+
- name: py3.9 with kyber-py
188+
os: ubuntu-latest
189+
python-version: "3.9"
190+
opt-deps: ["kyber_py"]
191+
- name: py3.10 with kyber-py
192+
os: ubuntu-latest
193+
python-version: "3.10"
194+
opt-deps: ["kyber_py"]
195+
- name: py3.11 with kyber-py
196+
os: ubuntu-latest
197+
python-version: "3.11"
198+
opt-deps: ["kyber_py"]
199+
- name: py3.12 with kyber-py
200+
os: ubuntu-latest
201+
python-version: "3.12"
202+
opt-deps: ["kyber_py"]
187203
# finally test with multiple dependencies installed at the same time
188204
- name: py2.7 with m2crypto, pycrypto, gmpy, gmpy2, and brotli
189205
os: ubuntu-20.04
@@ -204,22 +220,22 @@ jobs:
204220
- name: py3.9 with m2crypto, gmpy, gmpy2, brotli, and zstandard
205221
os: ubuntu-latest
206222
python-version: 3.9
207-
opt-deps: ['m2crypto', 'gmpy', 'gmpy2', 'brotli', 'zstd']
223+
opt-deps: ['m2crypto', 'gmpy', 'gmpy2', 'brotli', 'zstd', 'kyber_py']
208224
- name: py3.10 with m2crypto, gmpy, gmpy2, brotli, and zstandard
209225
os: ubuntu-latest
210226
python-version: '3.10'
211-
opt-deps: ['m2crypto', 'gmpy', 'gmpy2', 'brotli', 'zstd']
227+
opt-deps: ['m2crypto', 'gmpy', 'gmpy2', 'brotli', 'zstd', 'kyber_py']
212228
- name: py3.11 with m2crypto, gmpy, gmpy2, brotli, and zstandard
213229
os: ubuntu-latest
214230
python-version: '3.11'
215231
# gmpy doesn't build with 3.11
216-
opt-deps: ['m2crypto', 'gmpy2', 'brotli', 'zstd']
232+
opt-deps: ['m2crypto', 'gmpy2', 'brotli', 'zstd', 'kyber_py']
217233
- name: py3.12 with m2crypto, gmpy, gmpy2, brotli, and zstandard
218234
os: ubuntu-latest
219235
python-version: '3.12'
220236
# gmpy doesn't build with 3.12
221237
# coverage to codeclimate can be submitted just once
222-
opt-deps: ['m2crypto', 'gmpy2', 'codeclimate', 'brotli', 'zstd']
238+
opt-deps: ['m2crypto', 'gmpy2', 'codeclimate', 'brotli', 'zstd', 'kyber_py']
223239
steps:
224240
- uses: actions/checkout@v2
225241
if: ${{ !matrix.container }}
@@ -346,6 +362,9 @@ jobs:
346362
- name: Install zstandard for py3.8 and after
347363
if: ${{ contains(matrix.opt-deps, 'zstd') }}
348364
run: pip install zstandard
365+
- name: Install kyber_py
366+
if: ${{ contains(matrix.opt-deps, 'kyber_py') }}
367+
run: pip install "https://github.com/GiacomoPope/kyber-py/archive/b187189a514b3327578928c1d4c901d34592678e.zip"
349368
- name: Install build dependencies (2.6)
350369
if: ${{ matrix.python-version == '2.6' }}
351370
run: |

scripts/tls.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
GroupName, SignatureScheme
3535
from tlslite.handshakesettings import Keypair, VirtualHost
3636
from tlslite import __version__
37-
from tlslite.utils.compat import b2a_hex, a2b_hex, time_stamp
37+
from tlslite.utils.compat import b2a_hex, a2b_hex, time_stamp, \
38+
ML_KEM_AVAILABLE
3839
from tlslite.utils.dns_utils import is_valid_hostname
3940
from tlslite.utils.cryptomath import getRandomBytes
4041
from tlslite.constants import KeyUpdateMessageType
@@ -76,6 +77,10 @@ def printUsage(s=None):
7677
print(" GMPY2 : Loaded")
7778
else:
7879
print(" GMPY2 : Not Loaded")
80+
if ML_KEM_AVAILABLE:
81+
print(" Kyber-py : Loaded")
82+
else:
83+
print(" Kyber-py : Not Loaded")
7984

8085
print("")
8186
print("Certificate compression algorithms:")

tlslite/constants.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,13 @@ class GroupName(TLSEnum):
438438
brainpoolP512r1tls13 = 33
439439
allEC.extend(list(range(31, 34)))
440440

441-
all = allEC + allFF
441+
# draft-kwiatkowski-tls-ecdhe-mlkem
442+
secp256r1mlkem768 = 0x11EB
443+
x25519mlkem768 = 0x11EC
444+
secp384r1mlkem1024 = 0x11ED
445+
allKEM = [0x11EB, 0x11EC, 0x11ED]
446+
447+
all = allEC + allFF + allKEM
442448

443449
@classmethod
444450
def toRepr(cls, value, blacklist=None):

tlslite/handshakesettings.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from .constants import CertificateType
1111
from .utils import cryptomath
1212
from .utils import cipherfactory
13-
from .utils.compat import ecdsaAllCurves, int_types
13+
from .utils.compat import ecdsaAllCurves, int_types, ML_KEM_AVAILABLE
1414
from .utils.compression import compression_algo_impls
1515

1616
CIPHER_NAMES = ["chacha20-poly1305",
@@ -34,10 +34,14 @@
3434
ALL_RSA_SIGNATURE_HASHES = RSA_SIGNATURE_HASHES + ["md5"]
3535
SIGNATURE_SCHEMES = ["Ed25519", "Ed448"]
3636
RSA_SCHEMES = ["pss", "pkcs1"]
37+
CURVE_NAMES = []
38+
if ML_KEM_AVAILABLE:
39+
CURVE_NAMES += ["secp256r1mlkem768", "x25519mlkem768",
40+
"secp384r1mlkem1024"]
3741
# while secp521r1 is the most secure, it's also much slower than the others
3842
# so place it as the last one
39-
CURVE_NAMES = ["x25519", "x448", "secp384r1", "secp256r1",
40-
"secp521r1"]
43+
CURVE_NAMES += ["x25519", "x448", "secp384r1", "secp256r1",
44+
"secp521r1"]
4145
ALL_CURVE_NAMES = CURVE_NAMES + ["secp256k1", "brainpoolP512r1",
4246
"brainpoolP384r1", "brainpoolP256r1"]
4347
if ecdsaAllCurves:
@@ -57,7 +61,8 @@
5761
TLS13_PERMITTED_GROUPS = ["secp256r1", "secp384r1", "secp521r1",
5862
"x25519", "x448", "ffdhe2048",
5963
"ffdhe3072", "ffdhe4096", "ffdhe6144",
60-
"ffdhe8192"]
64+
"ffdhe8192", "secp256r1mlkem768", "x25519mlkem768",
65+
"secp384r1mlkem1024"]
6166
KNOWN_VERSIONS = ((3, 0), (3, 1), (3, 2), (3, 3), (3, 4))
6267
TICKET_CIPHERS = ["chacha20-poly1305", "aes256gcm", "aes128gcm", "aes128ccm",
6368
"aes128ccm_8", "aes256ccm", "aes256ccm_8"]
@@ -395,7 +400,11 @@ def _init_key_settings(self):
395400
self.dhParams = None
396401
self.dhGroups = list(ALL_DH_GROUP_NAMES)
397402
self.defaultCurve = "secp256r1"
398-
self.keyShares = ["secp256r1", "x25519"]
403+
if ML_KEM_AVAILABLE:
404+
self.keyShares = ["x25519mlkem768"]
405+
else:
406+
self.keyShares = []
407+
self.keyShares += ["secp256r1", "x25519"]
399408
self.padding_cb = None
400409
self.use_heartbeat_extension = True
401410
self.heartbeat_response_callback = None

0 commit comments

Comments
 (0)