Skip to content

Commit

Permalink
Merge 9c50325 into 3ea78db
Browse files Browse the repository at this point in the history
  • Loading branch information
inikolcev committed Nov 11, 2019
2 parents 3ea78db + 9c50325 commit 0d796e3
Show file tree
Hide file tree
Showing 10 changed files with 767 additions and 10 deletions.
69 changes: 64 additions & 5 deletions tests/tlstest.py
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,8 @@ def connect():

print("Test {0} - throughput test".format(test_no))
for implementation in implementations:
for cipher in ["aes128gcm", "aes256gcm", "aes128", "aes256", "3des",
for cipher in ["aes128ccm", "aes128ccm_8", "aes256ccm", "aes256ccm_8",
"aes128gcm", "aes256gcm", "aes128", "aes256", "3des",
"rc4", "chacha20-poly1305_draft00",
"chacha20-poly1305"]:
# skip tests with implementations that don't support them
Expand All @@ -778,7 +779,8 @@ def connect():
implementation not in ("pycrypto",
"python"):
continue
if cipher in ("chacha20-poly1305_draft00", "chacha20-poly1305") \
if cipher in ("chacha20-poly1305_draft00", "chacha20-poly1305",
"aes128ccm", "aes128ccm_8", "aes256ccm", "aes256ccm_8") \
and implementation not in ("python", ):
continue

Expand All @@ -791,7 +793,8 @@ def connect():
settings = HandshakeSettings()
settings.cipherNames = [cipher]
settings.cipherImplementations = [implementation, "python"]
if cipher not in ("aes128gcm", "aes256gcm", "chacha20-poly1305"):
if cipher not in ("aes128ccm", "aes128ccm_8", "aes128gcm",
"aes256gcm", "chacha20-poly1305"):
settings.maxVersion = (3, 3)
connection.handshakeClientCert(settings=settings)
print("%s %s:" % (connection.getCipherName(), connection.getCipherImplementation()), end=' ')
Expand Down Expand Up @@ -1086,6 +1089,37 @@ def connect():

test_no += 1

print("Test {0} - resumption in TLSv1.3 with AES-CCM tickets".format(test_no))
synchro.recv(1)
connection = connect()
settings = HandshakeSettings()
settings.minVersion = (3,4)
# force HRR
settings.keyShares = []
settings.ticketCipher = "aes128ccm"
connection.handshakeClientCert(serverName=address[0], settings=settings)
testConnClient(connection)
assert isinstance(connection.session.serverCertChain, X509CertChain)
assert connection.session.serverName == address[0]
assert not connection.resumed
assert connection.session.tickets
connection.close()
session = connection.session

# resume
synchro.recv(1)
settings = HandshakeSettings()
settings.minVersion = (3,4)
settings.keyShares = []
connection = connect()
connection.handshakeClientCert(serverName=address[0], session=session,
settings=settings)
testConnClient(connection)
assert connection.resumed
connection.close()

test_no += 1

print("Test {0} - Heartbeat extension response callback in TLSv1.2".format(test_no))
heartbeat_payload = os.urandom(50)
def heartbeat_response_check(message):
Expand Down Expand Up @@ -1885,7 +1919,8 @@ def server_bind(self):

print("Test {0} - throughput test".format(test_no))
for implementation in implementations:
for cipher in ["aes128gcm", "aes256gcm", "aes128", "aes256", "3des",
for cipher in ["aes128ccm", "aes128ccm_8", "aes256ccm", "aes256ccm_8",
"aes128gcm", "aes256gcm", "aes128", "aes256", "3des",
"rc4", "chacha20-poly1305_draft00",
"chacha20-poly1305"]:
# skip tests with implementations that don't support them
Expand All @@ -1896,7 +1931,9 @@ def server_bind(self):
implementation not in ("pycrypto",
"python"):
continue
if cipher in ("chacha20-poly1305_draft00", "chacha20-poly1305") \
if cipher in ("chacha20-poly1305_draft00", "chacha20-poly1305",
"aes128ccm", "aes128ccm_8",
"aes256ccm", "aes256ccm_8") \
and implementation not in ("python", ):
continue

Expand Down Expand Up @@ -2133,6 +2170,28 @@ def server_bind(self):

test_no += 1

print("Test {0} - resumption in TLSv1.3 with AES-CCM tickets".format(test_no))
synchro.send(b'R')
connection = connect()
settings = HandshakeSettings()
settings.minVersion = (3,4)
settings.ticketKeys = [getRandomBytes(32)]
settings.ticketCipher = "aes128ccm"
connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
settings=settings)
testConnServer(connection)
connection.close()

# resume
synchro.send(b'R')
connection = connect()
connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
settings=settings)
testConnServer(connection)
connection.close()

test_no += 1

print("Test {0} - Heartbeat extension response callback in TLSv1.2".format(test_no))
heartbeat_payload = os.urandom(50)
def heartbeat_response_check(message):
Expand Down
95 changes: 95 additions & 0 deletions tlslite/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,25 @@ class CipherSuite:
TLS_DH_ANON_WITH_AES_256_GCM_SHA384 = 0x00A7
ietfNames[0x00A7] = 'TLS_DH_ANON_WITH_AES_256_GCM_SHA384'

# RFC 6655 - AES-CCM ciphers for TLSv1.2
TLS_RSA_WITH_AES_128_CCM = 0xC09C
ietfNames[0xC09C] = 'TLS_RSA_WITH_AES_128_CCM'
TLS_RSA_WITH_AES_256_CCM = 0xC09D
ietfNames[0xC09D] = 'TLS_RSA_WITH_AES_256_CCM'
TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E
ietfNames[0xC09E] = 'TLS_DHE_RSA_WITH_AES_128_CCM'
TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F
ietfNames[0xC09F] = 'TLS_DHE_RSA_WITH_AES_256_CCM'
TLS_RSA_WITH_AES_128_CCM_8 = 0xC0A0
ietfNames[0xC0A0] = 'TLS_RSA_WITH_AES_128_CCM_8'
TLS_RSA_WITH_AES_256_CCM_8 = 0xC0A1
ietfNames[0xC0A1] = 'TLS_RSA_WITH_AES_256_CCM_8'
TLS_DHE_RSA_WITH_AES_128_CCM_8 = 0xC0A2
ietfNames[0xC0A2] = 'TLS_DHE_RSA_WITH_AES_128_CCM_8'
TLS_DHE_RSA_WITH_AES_256_CCM_8 = 0xC0A3
ietfNames[0xC0A3] = 'TLS_DHE_RSA_WITH_AES_256_CCM_8'


# Weird pseudo-ciphersuite from RFC 5746
# Signals that "secure renegotiation" is supported
# We actually don't do any renegotiation, but this
Expand All @@ -657,6 +676,10 @@ class CipherSuite:
ietfNames[0x1302] = 'TLS_AES_256_GCM_SHA384'
TLS_CHACHA20_POLY1305_SHA256 = 0x1303
ietfNames[0x1303] = 'TLS_CHACHA20_POLY1305_SHA256'
TLS_AES_128_CCM_SHA256 = 0x1304
ietfNames[0x1304] = 'TLS_AES_128_CCM_SHA256'
TLS_AES_128_CCM_8_SHA256 = 0x1305
ietfNames[0x1305] = 'TLS_AES_128_CCM_8_SHA256'

# RFC 7507 - Fallback Signaling Cipher Suite Value for Preventing Protocol
# Downgrade Attacks
Expand Down Expand Up @@ -794,6 +817,16 @@ class CipherSuite:
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA
ietfNames[0xCCAA] = 'TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256'

# RFC 7251 - AES-CCM ECC Ciphers for TLS
TLS_ECDHE_ECDSA_WITH_AES_128_CCM = 0xC0AC
ietfNames[0xC0AC] = 'TLS_ECDHE_ECDSA_WITH_AES_128_CCM'
TLS_ECDHE_ECDSA_WITH_AES_256_CCM = 0xC0AD
ietfNames[0xC0AD] = 'TLS_ECDHE_ECDSA_WITH_AES_256_CCM'
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE
ietfNames[0xC0AE] = 'TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8'
TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xC0AF
ietfNames[0xC0AF] = 'TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8'

#pylint: enable = invalid-name
#
# Define cipher suite families below
Expand Down Expand Up @@ -874,6 +907,32 @@ class CipherSuite:
aes256GcmSuites.append(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
aes256GcmSuites.append(TLS_AES_256_GCM_SHA384)

#: AES-128 CCM_8 ciphers
aes128Ccm_8Suites = []
aes128Ccm_8Suites.append(TLS_RSA_WITH_AES_128_CCM_8)
aes128Ccm_8Suites.append(TLS_DHE_RSA_WITH_AES_128_CCM_8)
aes128Ccm_8Suites.append(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8)
aes128Ccm_8Suites.append(TLS_AES_128_CCM_8_SHA256)

#: AES-128 CCM ciphers
aes128CcmSuites = []
aes128CcmSuites.append(TLS_RSA_WITH_AES_128_CCM)
aes128CcmSuites.append(TLS_DHE_RSA_WITH_AES_128_CCM)
aes128CcmSuites.append(TLS_ECDHE_ECDSA_WITH_AES_128_CCM)
aes128CcmSuites.append(TLS_AES_128_CCM_SHA256)

#: AES-256 CCM_8 ciphers
aes256Ccm_8Suites = []
aes256Ccm_8Suites.append(TLS_RSA_WITH_AES_256_CCM_8)
aes256Ccm_8Suites.append(TLS_DHE_RSA_WITH_AES_256_CCM_8)
aes256Ccm_8Suites.append(TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8)

# AES-256 CCM ciphers
aes256CcmSuites = []
aes256CcmSuites.append(TLS_RSA_WITH_AES_256_CCM)
aes256CcmSuites.append(TLS_DHE_RSA_WITH_AES_256_CCM)
aes256CcmSuites.append(TLS_ECDHE_ECDSA_WITH_AES_256_CCM)

#: CHACHA20 cipher, 00'th IETF draft (implicit POLY1305 authenticator)
chacha20draft00Suites = []
chacha20draft00Suites.append(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_draft_00)
Expand Down Expand Up @@ -985,6 +1044,10 @@ class CipherSuite:
aeadSuites = []
aeadSuites.extend(aes128GcmSuites)
aeadSuites.extend(aes256GcmSuites)
aeadSuites.extend(aes128CcmSuites)
aeadSuites.extend(aes128Ccm_8Suites)
aeadSuites.extend(aes256CcmSuites)
aeadSuites.extend(aes256Ccm_8Suites)
aeadSuites.extend(chacha20Suites)
aeadSuites.extend(chacha20draft00Suites)

Expand Down Expand Up @@ -1022,6 +1085,10 @@ class CipherSuite:
tls12Suites.remove(TLS_AES_128_GCM_SHA256)
tls13Suites.append(TLS_CHACHA20_POLY1305_SHA256)
tls12Suites.remove(TLS_CHACHA20_POLY1305_SHA256)
tls13Suites.append(TLS_AES_128_CCM_SHA256)
tls12Suites.remove(TLS_AES_128_CCM_SHA256)
tls13Suites.append(TLS_AES_128_CCM_8_SHA256)
tls12Suites.remove(TLS_AES_128_CCM_8_SHA256)

@staticmethod
def filterForVersion(suites, minVersion, maxVersion):
Expand Down Expand Up @@ -1085,6 +1152,14 @@ def _filterSuites(suites, settings, version=None):
cipherSuites += CipherSuite.aes128GcmSuites
if "aes256gcm" in cipherNames and version >= (3, 3):
cipherSuites += CipherSuite.aes256GcmSuites
if "aes128ccm" in cipherNames and version >= (3, 3):
cipherSuites += CipherSuite.aes128CcmSuites
if "aes128ccm_8" in cipherNames and version >= (3, 3):
cipherSuites += CipherSuite.aes128Ccm_8Suites
if "aes256ccm" in cipherNames and version >= (3, 3):
cipherSuites += CipherSuite.aes256CcmSuites
if "aes256ccm_8" in cipherNames and version >= (3, 3):
cipherSuites += CipherSuite.aes256Ccm_8Suites
if "aes128" in cipherNames:
cipherSuites += CipherSuite.aes128Suites
if "aes256" in cipherNames:
Expand Down Expand Up @@ -1158,10 +1233,14 @@ def getSrpAllSuites(cls, settings, version=None):
certSuites = []
certSuites.append(TLS_RSA_WITH_AES_256_GCM_SHA384)
certSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
certSuites.append(TLS_RSA_WITH_AES_256_CCM)
certSuites.append(TLS_RSA_WITH_AES_128_CCM)
certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
certSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
certSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
certSuites.append(TLS_RSA_WITH_AES_256_CCM_8)
certSuites.append(TLS_RSA_WITH_AES_128_CCM_8)
certSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
certSuites.append(TLS_RSA_WITH_RC4_128_SHA)
certSuites.append(TLS_RSA_WITH_RC4_128_MD5)
Expand All @@ -1180,10 +1259,14 @@ def getCertSuites(cls, settings, version=None):
dheCertSuites.append(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_draft_00)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CCM)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CCM)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CCM_8)
dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CCM_8)
dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)

@classmethod
Expand Down Expand Up @@ -1219,11 +1302,15 @@ def getEcdheCertSuites(cls, settings, version=None):
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_draft_00)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_256_CCM)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_128_CCM)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA)
ecdheEcdsaSuites.append(TLS_ECDHE_ECDSA_WITH_NULL_SHA)

Expand Down Expand Up @@ -1274,6 +1361,14 @@ def canonicalCipherName(ciphersuite):
return "aes128gcm"
elif ciphersuite in CipherSuite.aes256GcmSuites:
return "aes256gcm"
elif ciphersuite in CipherSuite.aes128Ccm_8Suites:
return "aes128ccm_8"
elif ciphersuite in CipherSuite.aes128CcmSuites:
return "aes128ccm"
elif ciphersuite in CipherSuite.aes256CcmSuites:
return "aes256ccm"
elif ciphersuite in CipherSuite.aes256Ccm_8Suites:
return "aes256ccm_8"
elif ciphersuite in CipherSuite.aes128Suites:
return "aes128"
elif ciphersuite in CipherSuite.aes256Suites:
Expand Down
5 changes: 4 additions & 1 deletion tlslite/handshakesettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@

CIPHER_NAMES = ["chacha20-poly1305",
"aes256gcm", "aes128gcm",
"aes256ccm", "aes128ccm",
"aes256", "aes128",
"3des"]
ALL_CIPHER_NAMES = CIPHER_NAMES + ["chacha20-poly1305_draft00",
"aes128ccm_8", "aes256ccm_8",
"rc4", "null"]
# Don't allow "md5" by default
MAC_NAMES = ["sha", "sha256", "sha384", "aead"]
Expand Down Expand Up @@ -45,7 +47,8 @@
"secp192r1": ('NIST192p', 'P-192'),
"secp224r1": ('NIST224p', 'P-224')}
KNOWN_VERSIONS = ((3, 0), (3, 1), (3, 2), (3, 3), (3, 4))
TICKET_CIPHERS = ["chacha20-poly1305", "aes256gcm", "aes128gcm"]
TICKET_CIPHERS = ["chacha20-poly1305", "aes256gcm", "aes128gcm", "aes128ccm",
"aes128ccm_8", "aes256ccm", "aes256ccm_8"]
PSK_MODES = ["psk_dhe_ke", "psk_ke"]


Expand Down
20 changes: 18 additions & 2 deletions tlslite/recordlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
from .utils import tlshashlib as hashlib
from .constants import ContentType, CipherSuite
from .messages import RecordHeader3, RecordHeader2, Message
from .utils.cipherfactory import createAESGCM, createAES, createRC4, \
createTripleDES, createCHACHA20
from .utils.cipherfactory import createAESCCM, createAESCCM_8, createAESGCM,\
createAES, createRC4, createTripleDES, createCHACHA20
from .utils.codec import Parser, Writer
from .utils.compat import compatHMAC
from .utils.cryptomath import getRandomBytes, MD5, HKDF_expand_label
Expand Down Expand Up @@ -1014,6 +1014,22 @@ def _getCipherSettings(cipherSuite):
keyLength = 16
ivLength = 4
createCipherFunc = createAESGCM
elif cipherSuite in CipherSuite.aes256Ccm_8Suites:
keyLength = 32
ivLength = 4
createCipherFunc = createAESCCM_8
elif cipherSuite in CipherSuite.aes256CcmSuites:
keyLength = 32
ivLength = 4
createCipherFunc = createAESCCM
elif cipherSuite in CipherSuite.aes128Ccm_8Suites:
keyLength = 16
ivLength = 4
createCipherFunc = createAESCCM_8
elif cipherSuite in CipherSuite.aes128CcmSuites:
keyLength = 16
ivLength = 4
createCipherFunc = createAESCCM
elif cipherSuite in CipherSuite.chacha20Suites:
keyLength = 32
ivLength = 12
Expand Down
11 changes: 10 additions & 1 deletion tlslite/tlsconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
ECDHE_RSAKeyExchange, SRPKeyExchange, ADHKeyExchange, \
AECDHKeyExchange, FFDHKeyExchange, ECDHKeyExchange
from .handshakehelpers import HandshakeHelpers
from .utils.cipherfactory import createAESGCM, createCHACHA20
from .utils.cipherfactory import createAESCCM, createAESCCM_8, \
createAESGCM, createCHACHA20

class TLSConnection(TLSRecordLayer):
"""
Expand Down Expand Up @@ -2348,6 +2349,10 @@ def _serverSendTickets(self, settings):
if settings.ticketCipher in ("aes128gcm", "aes256gcm"):
cipher = createAESGCM(key,
settings.cipherImplementations)
elif settings.ticketCipher in ("aes128ccm", "aes256ccm"):
cipher = createAESCCM(key, settings.cipherImplementations)
elif settings.ticketCipher in ("aes128ccm_8", "aes256ccm_8"):
cipher = createAESCCM_8(key, settings.cipherImplementations)
else:
assert settings.ticketCipher == "chacha20-poly1305"
cipher = createCHACHA20(key,
Expand Down Expand Up @@ -2382,6 +2387,10 @@ def _tryDecrypt(self, settings, identity):
key, iv = self._derive_key_iv(nonce, user_key, settings)
if settings.ticketCipher in ("aes128gcm", "aes256gcm"):
cipher = createAESGCM(key, settings.cipherImplementations)
elif settings.ticketCipher in ("aes128ccm", "aes256ccm"):
cipher = createAESCCM(key, settings.cipherImplementations)
elif settings.ticketCipher in ("aes128ccm_8", "aes256ccm_8"):
cipher = createAESCCM_8(key, settings.cipherImplementations)
else:
assert settings.ticketCipher == "chacha20-poly1305"
cipher = createCHACHA20(key, settings.cipherImplementations)
Expand Down
Loading

0 comments on commit 0d796e3

Please sign in to comment.