diff --git a/scripts/tls.py b/scripts/tls.py index 3159cbc3..50a4f1aa 100755 --- a/scripts/tls.py +++ b/scripts/tls.py @@ -109,7 +109,7 @@ def printUsage(s=None): [-c CERT] [-k KEY] [-t TACK] [-v VERIFIERDB] [-d DIR] [-l LABEL] [-L LENGTH] [--reqcert] [--param DHFILE] [--psk PSK] [--psk-ident IDENTITY] [--psk-sha384] [--ssl3] [--max-ver VER] [--tickets COUNT] [--cipherlist] - [--request-pha] [--require-pha] [--echo] + [--request-pha] [--require-pha] [--echo] [--groups GROUPS] HOST:PORT client @@ -137,6 +137,8 @@ def printUsage(s=None): --require-pha - abort connection if client didn't provide certificate in post-handshake authentication --echo - function as an echo server + --groups - specify what key exchange groups should be supported + GROUPS - comma-separated list of enabled key exchange groups CERT, KEY - the file with key and certificates that will be used by client or server. The server can accept multiple pairs of `-c` and `-k` options to configure different certificates (like RSA and ECDSA) @@ -197,6 +199,7 @@ def handleArgs(argv, argString, flagsList=[]): request_pha = False require_pha = False echo = False + groups = None for opt, arg in opts: if opt == "-k": @@ -270,6 +273,8 @@ def handleArgs(argv, argString, flagsList=[]): tickets = int(arg) elif opt == "--cipherlist": ciphers.append(arg) + elif opt == "--groups": + groups = arg.split(',') elif opt == "--request-pha": request_pha = True elif opt == "--require-pha": @@ -344,6 +349,8 @@ def handleArgs(argv, argString, flagsList=[]): retList.append(require_pha) if "echo" in flagsList: retList.append(echo) + if "groups=" in flagsList: + retList.append(groups) return retList @@ -547,12 +554,13 @@ def serverCmd(argv): (address, privateKey, cert_chain, virtual_hosts, tacks, verifierDB, directory, reqCert, expLabel, expLength, dhparam, psk, psk_ident, psk_hash, ssl3, - max_ver, tickets, cipherlist, request_pha, require_pha, echo) = \ + max_ver, tickets, cipherlist, request_pha, require_pha, echo, + groups) = \ handleArgs(argv, "kctbvdlL", ["reqcert", "param=", "psk=", "psk-ident=", "psk-sha384", "ssl3", "max-ver=", "tickets=", "cipherlist=", "request-pha", "require-pha", - "echo"]) + "echo", "groups="]) if (cert_chain and not privateKey) or (not cert_chain and privateKey): @@ -599,6 +607,17 @@ def serverCmd(argv): if cipherlist: settings.cipherNames = [item for cipher in cipherlist for item in cipher.split(',')] + if groups: + dh_groups = [] + ecc_groups = [] + for item in groups: + if "ffdh" in item: + dh_groups.append(item) + else: + ecc_groups.append(item) + settings.dhGroups = dh_groups + settings.eccCurves = ecc_groups + settings.keyShares = [] class MySimpleEchoHandler(BaseRequestHandler): def handle(self): diff --git a/tests/tlstest.py b/tests/tlstest.py index 9ce40f4d..d87e81e0 100755 --- a/tests/tlstest.py +++ b/tests/tlstest.py @@ -44,7 +44,7 @@ from xmlrpc import client as xmlrpclib import ssl from tlslite import * -from tlslite.constants import KeyUpdateMessageType +from tlslite.constants import KeyUpdateMessageType, SignatureScheme try: from tack.structures.Tack import Tack @@ -340,6 +340,32 @@ def connect(): test_no += 1 + for curve, keySize, exp_sig_alg in ( + ("brainpoolP256r1tls13", 256, + SignatureScheme.ecdsa_brainpoolP256r1tls13_sha256), + ("brainpoolP384r1tls13", 384, + SignatureScheme.ecdsa_brainpoolP384r1tls13_sha384), + ("brainpoolP512r1tls13", 512, + SignatureScheme.ecdsa_brainpoolP512r1tls13_sha512)): + print("Test {0} - Two good ECDSA certs - {1}, TLSv1.3".format(test_no, curve)) + synchro.recv(1) + connection = connect() + settings = HandshakeSettings() + settings.minVersion = (3, 4) + settings.maxVersion = (3, 4) + settings.eccCurves = [curve] + settings.keyShares = [] + connection.handshakeClientCert(settings=settings) + testConnClient(connection) + assert connection.serverSigAlg == exp_sig_alg, \ + connection.serverSigAlg + assert isinstance(connection.session.serverCertChain, X509CertChain) + assert len(connection.session.serverCertChain.getEndEntityPublicKey()) \ + == keySize + connection.close() + + test_no += 1 + print("Test {0} - Two good ECDSA certs - secp256r1, TLSv1.2".format(test_no)) synchro.recv(1) connection = connect() @@ -431,7 +457,7 @@ def connect(): test_no += 1 - print("Test {0} - good X509 RSA and ECDSA, correct RSA and ECDSA sigalgs, RSA, TLSv1.3" + print("Test {0} - good X509 RSA and ECDSA, correct RSA and ECDSA sigalgs, ECDSA, TLSv1.3" .format(test_no)) synchro.recv(1) connection = connect() @@ -444,7 +470,7 @@ def connect(): testConnClient(connection) assert isinstance(connection.session.serverCertChain, X509CertChain) assert connection.session.serverCertChain.getEndEntityPublicKey().key_type\ - == "rsa" + == "ecdsa" assert connection.version == (3, 4) connection.close() @@ -2233,6 +2259,29 @@ def connect(): test_no += 1 + for curve, certChain, key in (("brainpoolP256r1tls13", x509ecdsaBrainpoolP256r1Chain, x509ecdsaBrainpoolP256r1Key), + ("brainpoolP384r1tls13", x509ecdsaBrainpoolP384r1Chain, x509ecdsaBrainpoolP384r1Key), + ("brainpoolP512r1tls13", x509ecdsaBrainpoolP512r1Chain, x509ecdsaBrainpoolP512r1Key)): + print("Test {0} - Two good ECDSA certs - {1}, TLSv1.3".format(test_no, curve)) + synchro.send(b'R') + connection = connect() + settings = HandshakeSettings() + settings.minVersion = (3, 4) + settings.maxVersion = (3, 4) + settings.eccCurves = [curve, "secp256r1"] + settings.keyShares = [] + v_host = VirtualHost() + v_host.keys = [Keypair(x509ecdsaKey, x509ecdsaChain.x509List)] + settings.virtual_hosts = [v_host] + connection.handshakeServer(certChain=certChain, + privateKey=key, settings=settings) + assert connection.extendedMasterSecret + #XXX assert connection.session.serverCertChain == certChain + testConnServer(connection) + connection.close() + + test_no += 1 + for curve, exp_chain in (("secp256r1", x509ecdsaChain), ("secp384r1", x509ecdsaP384Chain)): print("Test {0} - Two good ECDSA certs - {1}, TLSv1.2" @@ -2254,10 +2303,14 @@ def connect(): test_no += 1 - for tls_ver in ("TLSv1.2", "TLSv1,3"): + for tls_ver in ("TLSv1.2", "TLSv1.3"): - print("Test {0} - good X509 RSA and ECDSA, correct RSA and ECDSA sigalgs, RSA, {1}" - .format(test_no, tls_ver)) + if tls_ver == "TLSv1.2": + expected = "RSA" + else: + expected = "ECDSA" + print("Test {0} - good X509 RSA and ECDSA, correct RSA and ECDSA sigalgs, {2}, {1}" + .format(test_no, tls_ver, expected)) synchro.send(b'R') connection = connect() settings = HandshakeSettings() @@ -2270,13 +2323,19 @@ def connect(): privateKey=x509KeyRSANonCA, settings=settings) assert connection.extendedMasterSecret - assert connection.session.serverCertChain == x509ChainRSANonCA + if tls_ver == "TLSv1.2": + # because in TLS 1.2 we don't send the signature_algorithms_cert + # extension, but send sig_algs with PKCS#1v1.5 sigalgs, RSA can be picked + # in TLS 1.3 we filter out PKCS#v1.5 so RSA cert will be picked only + # as a fallback + assert connection.session.serverCertChain == x509ChainRSANonCA, connection.session.serverCertChain.getEndEntityPublicKey().key_type + else: + assert connection.session.serverCertChain == x509ChainECDSANonCA, connection.session.serverCertChain.getEndEntityPublicKey().key_type testConnServer(connection) connection.close() test_no += 1 - print("Test {0} - good X509 RSA and ECDSA, bad RSA and good ECDSA sigalgs, ECDSA, {1}" .format(test_no, tls_ver)) synchro.send(b'R') diff --git a/tlslite/constants.py b/tlslite/constants.py index 49617655..3395c4ba 100644 --- a/tlslite/constants.py +++ b/tlslite/constants.py @@ -321,6 +321,14 @@ def getHash(scheme): return hName +# set of TLS 1.3 specific schemes for Brainpool curves +TLS_1_3_BRAINPOOL_SIG_SCHEMES = set([ + SignatureScheme.ecdsa_brainpoolP256r1tls13_sha256, + SignatureScheme.ecdsa_brainpoolP384r1tls13_sha384, + SignatureScheme.ecdsa_brainpoolP512r1tls13_sha512, +]) + + class AlgorithmOID(TLSEnum): """ Algorithm OIDs as defined in rfc5758(ecdsa), diff --git a/tlslite/handshakesettings.py b/tlslite/handshakesettings.py index 2ccb0841..bcebbc5f 100644 --- a/tlslite/handshakesettings.py +++ b/tlslite/handshakesettings.py @@ -32,7 +32,10 @@ DSA_SIGNATURE_HASHES = ["sha512", "sha384", "sha256", "sha224", "sha1"] ECDSA_SIGNATURE_HASHES = ["sha512", "sha384", "sha256", "sha224", "sha1"] ALL_RSA_SIGNATURE_HASHES = RSA_SIGNATURE_HASHES + ["md5"] -SIGNATURE_SCHEMES = ["Ed25519", "Ed448"] +SIGNATURE_SCHEMES = ["Ed25519", "Ed448", + "ecdsa_brainpoolP512r1tls13_sha512", + "ecdsa_brainpoolP384r1tls13_sha384", + "ecdsa_brainpoolP256r1tls13_sha256"] RSA_SCHEMES = ["pss", "pkcs1"] CURVE_NAMES = [] if ML_KEM_AVAILABLE: @@ -41,9 +44,12 @@ # while secp521r1 is the most secure, it's also much slower than the others # so place it as the last one CURVE_NAMES += ["x25519", "x448", "secp384r1", "secp256r1", - "secp521r1"] -ALL_CURVE_NAMES = CURVE_NAMES + ["secp256k1", "brainpoolP512r1", - "brainpoolP384r1", "brainpoolP256r1"] + "secp521r1", "brainpoolP512r1", + "brainpoolP384r1", "brainpoolP256r1", + "brainpoolP256r1tls13", + "brainpoolP384r1tls13", + "brainpoolP512r1tls13"] +ALL_CURVE_NAMES = CURVE_NAMES + ["secp256k1"] if ecdsaAllCurves: ALL_CURVE_NAMES += ["secp224r1", "secp192r1"] ALL_DH_GROUP_NAMES = ["ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", @@ -62,7 +68,8 @@ "x25519", "x448", "ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", "ffdhe8192", "secp256r1mlkem768", "x25519mlkem768", - "secp384r1mlkem1024"] + "secp384r1mlkem1024", "brainpoolP256r1tls13", + "brainpoolP384r1tls13", "brainpoolP512r1tls13"] KNOWN_VERSIONS = ((3, 0), (3, 1), (3, 2), (3, 3), (3, 4)) TICKET_CIPHERS = ["chacha20-poly1305", "aes256gcm", "aes128gcm", "aes128ccm", "aes128ccm_8", "aes256ccm", "aes256ccm_8"] @@ -278,7 +285,10 @@ class HandshakeSettings(object): :ivar more_sig_schemes: List of additional signatures schemes (ones that don't use RSA-PKCS#1 v1.5, RSA-PSS, DSA, or ECDSA) to advertise as supported. - Currently supported are: "Ed25519", and "Ed448". + Currently supported are: "Ed25519", "Ed448", + "ecdsa_brainpoolP256r1tls13_sha256", + "ecdsa_brainpoolP384r1tls13_sha384", + "ecdsa_brainpoolP512r1tls13_sha512". :vartype eccCurves: list(str) :ivar eccCurves: List of named curves that are to be advertised as @@ -534,7 +544,7 @@ def _sanityCheckECDHSettings(other): .format(unknownDHGroup)) # TLS 1.3 limits the allowed groups (RFC 8446,ch. 4.2.7.) - if other.maxVersion == (3, 4): + if (3, 3) not in other.versions and (3, 4) in other.versions: forbiddenGroup = HandshakeSettings._not_matching(other.eccCurves, TLS13_PERMITTED_GROUPS) if forbiddenGroup: raise ValueError("The following enabled groups are forbidden in TLS 1.3: {0}" diff --git a/tlslite/tlsconnection.py b/tlslite/tlsconnection.py index abb7ce83..7cf59ffc 100644 --- a/tlslite/tlsconnection.py +++ b/tlslite/tlsconnection.py @@ -730,10 +730,28 @@ def _clientSendClientHello(self, settings, session, srpUsername, bytearray(0))) # In TLS1.2 advertise support for additional signature types if settings.maxVersion >= (3, 3): - sigList = self._sigHashesToList(settings) - assert len(sigList) > 0 + sig_list = [] + if settings.maxVersion >= (3, 4) and \ + settings.minVersion <= (3, 4): + tls13_sig_list = self._sigHashesToList( + settings, + version=(3, 4)) + sig_list.extend(tls13_sig_list) + if settings.maxVersion >= (3, 3) and \ + settings.minVersion <= (3, 3): + tls12_sig_list = self._sigHashesToList( + settings, + version=(3, 3)) + # add elements from tls12 signature algorithms set + # not yet in the list of algorithms while preserving order + sig_list_set = set(sig_list) + tls12_sig_list_set = set(tls12_sig_list) + not_in_sig_list = tls12_sig_list_set.difference(sig_list_set) + sig_list.extend(i for i in tls12_sig_list if i in not_in_sig_list) + + assert sig_list extensions.append(SignatureAlgorithmsExtension().\ - create(sigList)) + create(sig_list)) # if we know any protocols for ALPN, advertise them if alpn: extensions.append(ALPNExtension().create(alpn)) @@ -1430,6 +1448,12 @@ def _clientTLS13Handshake(self, settings, session, clientHello, "server selected signature method invalid for the " "certificate it presented (curve mismatch)") + salt_len = None + method = publicKey.verify + elif signature_scheme in TLS_1_3_BRAINPOOL_SIG_SCHEMES: + scheme = SignatureScheme.toRepr(signature_scheme) + pad_type = None + hash_name = SignatureScheme.getHash(scheme) salt_len = None method = publicKey.verify else: @@ -1536,6 +1560,12 @@ def _clientTLS13Handshake(self, settings, session, clientHello, salt_len = None sig_func = privateKey.sign ver_func = privateKey.verify + elif signature_scheme in TLS_1_3_BRAINPOOL_SIG_SCHEMES: + pad_type = None + hash_name = SignatureScheme.getHash(scheme) + salt_len = None + sig_func = privateKey.sign + ver_func = privateKey.verify else: pad_type = SignatureScheme.getPadding(scheme) hash_name = SignatureScheme.getHash(scheme) @@ -1976,7 +2006,9 @@ def _check_certchain_with_settings(self, cert_chain, settings): "advertise support for: {0}".format(curve_name)): yield result if self.version >= (3, 4): - if curve_name not in ('secp256r1', 'secp384r1', 'secp521r1'): + if curve_name not in ('secp256r1', 'secp384r1', 'secp521r1', + 'brainpoolP256r1', 'brainpoolP384r1', + 'brainpoolP512r1'): for result in self._sendError( AlertDescription.illegal_parameter, "Peer sent certificate with curve not supported " @@ -1986,8 +2018,14 @@ def _check_certchain_with_settings(self, cert_chain, settings): sig_alg_for_curve = 'sha256' elif curve_name == 'secp384r1': sig_alg_for_curve = 'sha384' + elif curve_name == 'secp521r1': + sig_alg_for_curve = 'sha512' + elif curve_name == 'brainpoolP256r1': + sig_alg_for_curve = 'sha256' + elif curve_name == 'brainpoolP384r1': + sig_alg_for_curve = 'sha384' else: - assert curve_name == 'secp521r1' + assert curve_name == 'brainpoolP512r1' sig_alg_for_curve = 'sha512' if sig_alg_for_curve not in settings.ecdsaSigHashes: for result in self._sendError( @@ -2944,7 +2982,9 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite, # DSA is not supported for TLS 1.3 cr_settings = settings.validate() cr_settings.dsaSigHashes = [] - valid_sig_algs = self._sigHashesToList(cr_settings) + valid_sig_algs = self._sigHashesToList( + cr_settings, + version=self.version) assert valid_sig_algs extensions = [] @@ -2973,6 +3013,7 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite, certificate_verify = CertificateVerify(self.version) signature_scheme = getattr(SignatureScheme, scheme) + self.serverSigAlg = signature_scheme signature_context = \ KeyExchange.calcVerifyBytes((3, 4), self._handshake_hash, @@ -2992,6 +3033,12 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite, saltLen = None sig_func = privateKey.sign ver_func = privateKey.verify + elif signature_scheme in TLS_1_3_BRAINPOOL_SIG_SCHEMES: + hashName = SignatureScheme.getHash(scheme) + padType = None + saltLen = None + sig_func = privateKey.sign + ver_func = privateKey.verify else: padType = SignatureScheme.getPadding(scheme) hashName = SignatureScheme.getHash(scheme) @@ -3113,6 +3160,11 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite, pad_type = None salt_len = None ver_func = public_key.verify + elif signature_scheme in TLS_1_3_BRAINPOOL_SIG_SCHEMES: + pad_type = None + salt_len = None + hash_name = SignatureScheme.getHash(scheme) + ver_func = public_key.verify else: scheme = SignatureScheme.toRepr(signature_scheme) pad_type = SignatureScheme.getPadding(scheme) @@ -3445,11 +3497,13 @@ def _serverGetClientHello(self, settings, private_key, cert_chain, yield result # check supported_groups - if TLS_1_3_FORBIDDEN_GROUPS.intersection(sup_groups.groups): + if TLS_1_3_FORBIDDEN_GROUPS.intersection(sup_groups.groups) \ + and (3, 3) not in ver_ext.versions: for result in self._sendError( AlertDescription.illegal_parameter, "Client advertised in TLS 1.3 Client Hello a key " - "exchange group forbidden in TLS 1.3"): + "exchange group forbidden in TLS 1.3 without " + "advertising support for TLS 1.2"): yield result # Check key_share @@ -4223,7 +4277,7 @@ def _server_select_certificate(self, settings, client_hello, last_cert = True # Mandatory checks. If any one of these checks fail, the certificate - # is not usuable. + # is not usable. try: # Find a suitable ciphersuite based on the certificate ciphers = CipherSuite.filter_for_certificate(cipher_suites, cert) @@ -4284,10 +4338,14 @@ def _server_select_certificate(self, settings, client_hello, if version >= (3, 4): if GroupName.toRepr(curve) not in \ - ('secp256r1', 'secp384r1', 'secp521r1'): + ('secp256r1', 'secp384r1', 'secp521r1', + 'brainpoolP256r1', 'brainpoolP384r1', + 'brainpoolP512r1'): raise TLSIllegalParameterException( - "Curve in public key is not supported " - "in TLS1.3") + "Curve in public key ({0}) is not " + "supported " + "in TLS1.3".format( + GroupName.toRepr(curve))) # If all mandatory checks passed add # this as possible certificate we can use. @@ -4383,8 +4441,8 @@ def _serverCertKeyExchange(self, clientHello, serverHello, sigHashAlg, if not reqCAs: reqCAs = [] cr_settings = settings.validate() - valid_sig_algs = self._sigHashesToList(cr_settings) - + valid_sig_algs = self._sigHashesToList(cr_settings, + version=self.version) cert_types = [] if cr_settings.rsaSigHashes: cert_types.append(ClientCertificateType.rsa_sign) @@ -4483,7 +4541,8 @@ def _serverCertKeyExchange(self, clientHello, serverHello, sigHashAlg, if self.version == (3, 3): valid_sig_algs = \ self._sigHashesToList(settings, - certList=clientCertChain) + certList=clientCertChain, + version=self.version) if certificateVerify.signatureAlgorithm not in valid_sig_algs: for result in self._sendError( AlertDescription.illegal_parameter, @@ -4839,7 +4898,6 @@ def _pickServerKeyExchangeSig(settings, clientHello, certList=None, supported = TLSConnection._sigHashesToList(settings, certList=certs, version=version) - for schemeID in supported: if schemeID in hashAndAlgsExt.sigalgs: name = SignatureScheme.toRepr(schemeID) @@ -4873,24 +4931,47 @@ def _sigHashesToList(settings, privateKey=None, certList=None, continue if certType and sig_scheme != certType: continue - sigAlgs.append(getattr(SignatureScheme, sig_scheme.lower())) - - if not certType or certType == "ecdsa": - for hashName in settings.ecdsaSigHashes: - # only SHA256, SHA384 and SHA512 are allowed in TLS 1.3 - if version > (3, 3) and hashName in ("sha1", "sha224"): + # the special brainpool sig schemes are TLS 1.3 only + # in TLS 1.2 we use general "ECDSA" sig schemes + if version < (3, 4) and 'brainpool' in sig_scheme: continue + try: + sigAlgs.append(getattr(SignatureScheme, sig_scheme)) + except AttributeError: + sigAlgs.append( + getattr(SignatureScheme, sig_scheme.lower())) - # in TLS 1.3 ECDSA key curve is bound to hash - if publicKey and version > (3, 3): - curve = publicKey.curve_name - matching_hash = TLSConnection._curve_name_to_hash_name( - curve) - if hashName != matching_hash: + if not certType or certType == "ecdsa": + if version > (3, 3) and publicKey and \ + "BRAINPOOL" in publicKey.curve_name: + # brainpool in TLS 1.3 uses special signature schemes + curve = publicKey.curve_name + if curve == "BRAINPOOLP256r1": + sigAlgs.append( + SignatureScheme.ecdsa_brainpoolP256r1tls13_sha256) + elif curve == "BRAINPOOLP384r1": + sigAlgs.append( + SignatureScheme.ecdsa_brainpoolP384r1tls13_sha384) + else: + assert curve == "BRAINPOOLP512r1" + sigAlgs.append( + SignatureScheme.ecdsa_brainpoolP512r1tls13_sha512) + else: + for hashName in settings.ecdsaSigHashes: + # only SHA256, SHA384 and SHA512 are allowed in TLS 1.3 + if version > (3, 3) and hashName in ("sha1", "sha224"): continue - sigAlgs.append((getattr(HashAlgorithm, hashName), - SignatureAlgorithm.ecdsa)) + # in TLS 1.3 ECDSA key curve is bound to hash + if publicKey and version > (3, 3): + curve = publicKey.curve_name + matching_hash = TLSConnection._curve_name_to_hash_name( + curve) + if hashName != matching_hash: + continue + + sigAlgs.append((getattr(HashAlgorithm, hashName), + SignatureAlgorithm.ecdsa)) if not certType or certType == "dsa": for hashName in settings.dsaSigHashes: @@ -4961,5 +5042,11 @@ def _curve_name_to_hash_name(curve_name): return "sha384" if curve_name == "NIST521p": return "sha512" + if curve_name == "BRAINPOOLP256r1": + return "sha256" + if curve_name == "BRAINPOOLP384r1": + return "sha384" + if curve_name == "BRAINPOOLP512r1": + return "sha512" raise TLSIllegalParameterException( "Curve {0} is not supported in TLS 1.3".format(curve_name)) diff --git a/tlslite/utils/ecc.py b/tlslite/utils/ecc.py index 1b026859..4e478111 100644 --- a/tlslite/utils/ecc.py +++ b/tlslite/utils/ecc.py @@ -15,7 +15,10 @@ def getCurveByName(curveName): 'secp256k1':ecdsa.SECP256k1, 'brainpoolP256r1': ecdsa.BRAINPOOLP256r1, 'brainpoolP384r1': ecdsa.BRAINPOOLP384r1, - 'brainpoolP512r1': ecdsa.BRAINPOOLP512r1} + 'brainpoolP512r1': ecdsa.BRAINPOOLP512r1, + 'brainpoolP256r1tls13': ecdsa.BRAINPOOLP256r1, + 'brainpoolP384r1tls13': ecdsa.BRAINPOOLP384r1, + 'brainpoolP512r1tls13': ecdsa.BRAINPOOLP512r1} if ecdsaAllCurves: curveMap['secp224r1'] = ecdsa.NIST224p curveMap['secp192r1'] = ecdsa.NIST192p