Skip to content

Commit 5960393

Browse files
authored
Merge pull request #425 from Hedgehog5040/dsa_server_support
DSA signatures in SKE
2 parents a6cde37 + 88d9c81 commit 5960393

18 files changed

+1025
-90
lines changed

tests/serverDSACert.pem

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
Certificate:
2+
Data:
3+
Version: 3 (0x2)
4+
Serial Number: 2 (0x2)
5+
Signature Algorithm: dsa_with_SHA256
6+
Issuer: O=Example CA
7+
Validity
8+
Not Before: Feb 8 14:15:57 2021 GMT
9+
Not After : Feb 8 14:15:57 2022 GMT
10+
Subject: O=dsa server, CN=localhost
11+
Subject Public Key Info:
12+
Public Key Algorithm: dsaEncryption
13+
pub:
14+
58:7d:8d:91:6b:69:46:d6:4e:02:2f:e4:c5:c5:da:
15+
62:1b:0f:c6:96:ba:e6:6c:ba:c5:d9:20:b4:9c:4e:
16+
e9:97:53:44:05:50:01:d1:a4:d5:ad:2e:80:14:77:
17+
05:65:a2:ce:8b:c7:ae:a4:40:45:0f:4e:24:d9:c9:
18+
e7:3e:1f:8a:1b:7d:90:24:38:f2:fe:a0:16:08:2a:
19+
aa:b5:bd:79:bb:1f:04:e2:f1:be:e6:01:18:8b:27:
20+
d5:b4:9e:96:81:7a:df:99:4e:4c:2a:25:c6:15:ef:
21+
33:09:f7:b2:b2:bb:84:42:b4:23:78:fa:52:76:61:
22+
12:b6:09:06:e0:84:e3:55:58:df:97:83:77:be:6f:
23+
5a:b4:96:77:96:f9:50:fe:1e:78:68:fc:8f:69:37:
24+
84:0b:6a:9e:d4:5e:13:f5:f2:fc:4c:89:66:44:24:
25+
46:7f:5c:d3:c1:48:84:63:5a:1d:27:26:1c:dc:24:
26+
fd:c0:43:18:51:6b:1b:e7:72:73:29:dd:99:d4:f6:
27+
38:90:d5:9b:b2:86:bc:67:35:3a:27:35:eb:56:97:
28+
98:e9:26:78:86:e3:a2:f7:f1:c3:cf:88:77:92:fe:
29+
4d:cf:44:9f:2b:67:f7:8d:1c:99:37:df:89:f9:fb:
30+
de:9e:1c:a6:c1:d6:cf:13:16:92:cf:af:00:60:3c:
31+
e1
32+
P:
33+
00:95:c5:2e:aa:36:d7:2d:29:20:29:26:a5:17:1b:
34+
1f:c3:9e:09:8d:7f:f1:7a:57:e0:3a:5e:da:0b:f6:
35+
b9:14:5e:2a:7b:6d:aa:6f:e6:6e:eb:6c:0f:f2:5c:
36+
ad:0e:ce:d5:ae:6a:b2:a1:bf:18:a0:96:d8:b0:b0:
37+
00:c9:e5:97:81:b6:41:af:e0:6f:cf:18:cf:91:3a:
38+
3b:de:04:20:f5:36:9c:55:52:72:06:cb:77:45:9d:
39+
83:64:f5:dc:a3:17:3d:69:51:28:2a:d1:47:8a:6a:
40+
b3:d2:72:8a:2b:d8:b5:36:fb:4f:e7:ab:1c:85:c3:
41+
a6:a4:46:9a:33:19:f6:2a:c3:af:e7:50:44:ff:b8:
42+
06:46:ce:c2:f5:94:09:bd:c3:0a:31:8e:32:8b:a4:
43+
3f:82:0c:df:0a:f5:a9:8a:2a:7a:5e:75:f1:a3:fc:
44+
7d:5d:6e:0a:2e:18:8a:3b:4f:90:8f:c9:36:63:42:
45+
d1:3e:6e:19:cd:22:76:09:e4:49:57:3f:51:95:f7:
46+
9b:4b:df:32:26:c0:ba:b8:da:ea:e2:9d:b2:11:ab:
47+
a1:fe:a4:df:ca:73:8c:1e:7d:2e:8e:e3:8a:ca:6a:
48+
bf:45:47:0d:0d:82:1c:d0:51:58:d4:25:dc:3d:fa:
49+
5c:e6:ef:27:86:b0:02:8f:30:51:41:78:fb:27:9b:
50+
af:33
51+
Q:
52+
00:9a:13:45:eb:94:f3:58:b7:82:7b:3b:67:16:4d:
53+
03:54:f8:aa:aa:8d:71:ca:83:3c:7a:e2:b5:2e:5d:
54+
bc:f2:e1
55+
G:
56+
20:ad:7e:c1:9b:e4:ba:7d:ca:7b:5b:cd:d6:97:48:
57+
e8:bf:6b:a3:ea:bc:ab:c1:05:7a:8f:7b:11:dd:9d:
58+
a7:f2:5d:08:5e:fd:b1:ad:a0:d6:e8:87:58:75:bf:
59+
5b:f7:3a:70:45:a4:95:a3:00:04:2b:c1:73:dd:f5:
60+
fb:67:01:4b:81:67:61:47:25:0b:6f:ea:2d:25:a2:
61+
66:53:1b:2f:2e:54:8b:c4:6c:0b:da:cd:f6:58:02:
62+
37:02:ef:f9:42:d8:97:55:a0:13:ba:25:19:aa:5e:
63+
50:53:00:a2:0e:ac:64:62:12:01:c5:7a:02:27:de:
64+
3d:de:dc:85:12:bb:8f:04:6f:c2:b9:92:40:b8:92:
65+
0d:37:d5:90:b5:22:91:63:7e:c7:8d:0f:cd:67:fe:
66+
85:25:b6:3b:5e:14:c4:7f:8b:09:21:d6:b1:da:fb:
67+
5f:6b:f7:23:76:22:93:0a:ef:45:a4:00:2f:4c:fa:
68+
ce:b9:ee:66:4f:92:9f:e7:ee:5f:09:67:59:5c:62:
69+
17:92:16:28:fc:7d:8e:8b:61:c7:d3:d5:a9:98:9a:
70+
7d:bf:3e:7c:1e:d8:c0:ca:a9:46:fe:b4:78:cb:b3:
71+
11:ce:23:c8:96:32:55:f8:46:f1:ea:6a:7e:4a:8f:
72+
f0:88:7c:67:7d:bb:3b:1d:6c:af:81:54:9e:75:09:
73+
73
74+
X509v3 extensions:
75+
X509v3 Key Usage: critical
76+
Digital Signature, Key Encipherment, Key Agreement
77+
X509v3 Extended Key Usage:
78+
TLS Web Server Authentication
79+
X509v3 Subject Key Identifier:
80+
DC:23:24:9D:CD:AA:94:15:82:E7:8F:D8:31:E9:0C:71:33:83:EA:4A
81+
X509v3 Authority Key Identifier:
82+
keyid:EE:29:FB:C3:3C:CF:14:4D:99:D1:A1:3C:09:D4:95:F4:52:CA:DB:42
83+
DirName:/O=Example CA
84+
serial:01
85+
86+
Signature Algorithm: dsa_with_SHA256
87+
r:
88+
73:8f:48:44:e7:69:0e:e3:ea:cd:04:2c:cf:41:08:
89+
e0:9e:46:ee:ee:2d:c1:6e:16:9e:ca:71:ab:0d:d5:
90+
a6:c3
91+
s:
92+
1f:92:62:3b:02:8e:eb:6a:08:dd:40:9b:d5:84:11:
93+
6a:8c:8a:73:06:03:85:a9:e8:f4:18:0c:11:35:db:
94+
b5:4b
95+
-----BEGIN CERTIFICATE-----
96+
MIIEpDCCBEqgAwIBAgIBAjALBglghkgBZQMEAwIwFTETMBEGA1UECgwKRXhhbXBs
97+
ZSBDQTAeFw0yMTAyMDgxNDE1NTdaFw0yMjAyMDgxNDE1NTdaMCkxEzARBgNVBAoM
98+
CmRzYSBzZXJ2ZXIxEjAQBgNVBAMMCWxvY2FsaG9zdDCCA0YwggI5BgcqhkjOOAQB
99+
MIICLAKCAQEAlcUuqjbXLSkgKSalFxsfw54JjX/xelfgOl7aC/a5FF4qe22qb+Zu
100+
62wP8lytDs7Vrmqyob8YoJbYsLAAyeWXgbZBr+BvzxjPkTo73gQg9TacVVJyBst3
101+
RZ2DZPXcoxc9aVEoKtFHimqz0nKKK9i1NvtP56schcOmpEaaMxn2KsOv51BE/7gG
102+
Rs7C9ZQJvcMKMY4yi6Q/ggzfCvWpiip6XnXxo/x9XW4KLhiKO0+Qj8k2Y0LRPm4Z
103+
zSJ2CeRJVz9RlfebS98yJsC6uNrq4p2yEauh/qTfynOMHn0ujuOKymq/RUcNDYIc
104+
0FFY1CXcPfpc5u8nhrACjzBRQXj7J5uvMwIhAJoTReuU81i3gns7ZxZNA1T4qqqN
105+
ccqDPHritS5dvPLhAoIBACCtfsGb5Lp9yntbzdaXSOi/a6PqvKvBBXqPexHdnafy
106+
XQhe/bGtoNboh1h1v1v3OnBFpJWjAAQrwXPd9ftnAUuBZ2FHJQtv6i0lomZTGy8u
107+
VIvEbAvazfZYAjcC7/lC2JdVoBO6JRmqXlBTAKIOrGRiEgHFegIn3j3e3IUSu48E
108+
b8K5kkC4kg031ZC1IpFjfseND81n/oUltjteFMR/iwkh1rHa+19r9yN2IpMK70Wk
109+
AC9M+s657mZPkp/n7l8JZ1lcYheSFij8fY6LYcfT1amYmn2/Pnwe2MDKqUb+tHjL
110+
sxHOI8iWMlX4RvHqan5Kj/CIfGd9uzsdbK+BVJ51CXMDggEFAAKCAQBYfY2Ra2lG
111+
1k4CL+TFxdpiGw/GlrrmbLrF2SC0nE7pl1NEBVAB0aTVrS6AFHcFZaLOi8eupEBF
112+
D04k2cnnPh+KG32QJDjy/qAWCCqqtb15ux8E4vG+5gEYiyfVtJ6WgXrfmU5MKiXG
113+
Fe8zCfeysruEQrQjePpSdmEStgkG4ITjVVjfl4N3vm9atJZ3lvlQ/h54aPyPaTeE
114+
C2qe1F4T9fL8TIlmRCRGf1zTwUiEY1odJyYc3CT9wEMYUWsb53JzKd2Z1PY4kNWb
115+
soa8ZzU6JzXrVpeY6SZ4huOi9/HDz4h3kv5Nz0SfK2f3jRyZN9+J+fvenhymwdbP
116+
ExaSz68AYDzho4GGMIGDMA4GA1UdDwEB/wQEAwIDqDATBgNVHSUEDDAKBggrBgEF
117+
BQcDATAdBgNVHQ4EFgQU3CMknc2qlBWC54/YMekMcTOD6kowPQYDVR0jBDYwNIAU
118+
7in7wzzPFE2Z0aE8CdSV9FLK20KhGaQXMBUxEzARBgNVBAoMCkV4YW1wbGUgQ0GC
119+
AQEwCwYJYIZIAWUDBAMCA0cAMEQCIHOPSETnaQ7j6s0ELM9BCOCeRu7uLcFuFp7K
120+
casN1abDAiAfkmI7Ao7ragjdQJvVhBFqjIpzBgOFqej0GAwRNdu1Sw==
121+
-----END CERTIFICATE-----

tests/serverDSAKey.pem

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN DSA PRIVATE KEY-----
2+
MIIDVQIBAAKCAQEAlcUuqjbXLSkgKSalFxsfw54JjX/xelfgOl7aC/a5FF4qe22q
3+
b+Zu62wP8lytDs7Vrmqyob8YoJbYsLAAyeWXgbZBr+BvzxjPkTo73gQg9TacVVJy
4+
Bst3RZ2DZPXcoxc9aVEoKtFHimqz0nKKK9i1NvtP56schcOmpEaaMxn2KsOv51BE
5+
/7gGRs7C9ZQJvcMKMY4yi6Q/ggzfCvWpiip6XnXxo/x9XW4KLhiKO0+Qj8k2Y0LR
6+
Pm4ZzSJ2CeRJVz9RlfebS98yJsC6uNrq4p2yEauh/qTfynOMHn0ujuOKymq/RUcN
7+
DYIc0FFY1CXcPfpc5u8nhrACjzBRQXj7J5uvMwIhAJoTReuU81i3gns7ZxZNA1T4
8+
qqqNccqDPHritS5dvPLhAoIBACCtfsGb5Lp9yntbzdaXSOi/a6PqvKvBBXqPexHd
9+
nafyXQhe/bGtoNboh1h1v1v3OnBFpJWjAAQrwXPd9ftnAUuBZ2FHJQtv6i0lomZT
10+
Gy8uVIvEbAvazfZYAjcC7/lC2JdVoBO6JRmqXlBTAKIOrGRiEgHFegIn3j3e3IUS
11+
u48Eb8K5kkC4kg031ZC1IpFjfseND81n/oUltjteFMR/iwkh1rHa+19r9yN2IpMK
12+
70WkAC9M+s657mZPkp/n7l8JZ1lcYheSFij8fY6LYcfT1amYmn2/Pnwe2MDKqUb+
13+
tHjLsxHOI8iWMlX4RvHqan5Kj/CIfGd9uzsdbK+BVJ51CXMCggEAWH2NkWtpRtZO
14+
Ai/kxcXaYhsPxpa65my6xdkgtJxO6ZdTRAVQAdGk1a0ugBR3BWWizovHrqRARQ9O
15+
JNnJ5z4fiht9kCQ48v6gFggqqrW9ebsfBOLxvuYBGIsn1bSeloF635lOTColxhXv
16+
Mwn3srK7hEK0I3j6UnZhErYJBuCE41VY35eDd75vWrSWd5b5UP4eeGj8j2k3hAtq
17+
ntReE/Xy/EyJZkQkRn9c08FIhGNaHScmHNwk/cBDGFFrG+dycyndmdT2OJDVm7KG
18+
vGc1Oic161aXmOkmeIbjovfxw8+Id5L+Tc9Enytn940cmTffifn73p4cpsHWzxMW
19+
ks+vAGA84QIgDR0eOWXgG++QAwl7Lsm1QDQEAL2XvHMGL978OfObntM=
20+
-----END DSA PRIVATE KEY-----

tests/tlstest.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,34 @@ def connect():
849849

850850
test_no += 1
851851

852+
print("Test {0} - good X.509 DSA, SSLv3".format(test_no))
853+
synchro.recv(1)
854+
connection = connect()
855+
settings = HandshakeSettings()
856+
settings.minVersion = (3, 0)
857+
settings.maxVersion = (3, 0)
858+
connection.handshakeClientCert(settings=settings)
859+
testConnClient(connection)
860+
assert connection.session.cipherSuite in\
861+
constants.CipherSuite.dheDsaSuites
862+
assert isinstance(connection.session.serverCertChain, X509CertChain)
863+
connection.close()
864+
865+
test_no += 1
866+
867+
print("Test {0} - good X.509 DSA, TLSv1.2".format(test_no))
868+
synchro.recv(1)
869+
connection = connect()
870+
settings = HandshakeSettings()
871+
settings.minVersion = (3, 3)
872+
settings.maxVersion = (3, 3)
873+
connection.handshakeClientCert(settings=settings)
874+
testConnClient(connection)
875+
assert connection.session.cipherSuite in\
876+
constants.CipherSuite.dheDsaSuites
877+
assert isinstance(connection.session.serverCertChain, X509CertChain)
878+
connection.close()
879+
852880
print("Test {0} - good mutual X.509, TLSv1.3 no certs".format(test_no))
853881
synchro.recv(1)
854882
connection = connect()
@@ -1704,6 +1732,13 @@ def connect():
17041732
x509KeyECDSANonCA = parsePEMKey(f.read(), private=True,
17051733
implementations=["python"])
17061734

1735+
with open(os.path.join(dir, "serverDSACert.pem")) as f:
1736+
x509CertDSA = X509().parse(f.read())
1737+
x509ChainDSA = X509CertChain([x509CertDSA])
1738+
assert x509CertDSA.certAlg == "dsa"
1739+
with open(os.path.join(dir, "serverDSAKey.pem")) as f:
1740+
x509KeyDSA = parsePEMKey(f.read(), private=True,
1741+
implementations=["python"])
17071742
test_no = 0
17081743

17091744
print("Test {0} - Anonymous server handshake".format(test_no))
@@ -1819,6 +1854,7 @@ def connect():
18191854

18201855
test_no += 1
18211856

1857+
18221858
print("Test {0} - good X.509 ECDSA, SSLv3".format(test_no))
18231859
synchro.send(b'R')
18241860
connection = connect()
@@ -2284,6 +2320,33 @@ def connect():
22842320

22852321
test_no += 1
22862322

2323+
print("Test {0} - good X.509 DSA, SSLv3".format(test_no))
2324+
synchro.send(b'R')
2325+
connection = connect()
2326+
settings = HandshakeSettings()
2327+
settings.minVersion = (3, 0)
2328+
settings.maxVersion = (3, 0)
2329+
connection.handshakeServer(certChain=x509ChainDSA,
2330+
privateKey=x509KeyDSA, settings=settings)
2331+
assert not connection.extendedMasterSecret
2332+
testConnServer(connection)
2333+
connection.close()
2334+
2335+
test_no += 1
2336+
2337+
print("Test {0} - good X.509 DSA, TLSv1.2".format(test_no))
2338+
synchro.send(b'R')
2339+
connection = connect()
2340+
settings = HandshakeSettings()
2341+
settings.minVersion = (3, 3)
2342+
settings.maxVersion = (3, 3)
2343+
connection.handshakeServer(certChain=x509ChainDSA,
2344+
privateKey=x509KeyDSA, settings=settings)
2345+
testConnServer(connection)
2346+
connection.close()
2347+
2348+
test_no += 1
2349+
22872350
print("Test {0} - good mutual X.509, TLSv1.3 no certs".format(test_no))
22882351
synchro.send(b'R')
22892352
connection = connect()

tlslite/constants.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ def getHash(scheme):
304304
kType, _, hName = vals
305305
else:
306306
kType, _, _, hName = vals
307-
assert kType in ('rsa', 'ecdsa')
307+
assert kType in ('rsa', 'ecdsa', 'dsa')
308308
return hName
309309

310310

@@ -960,6 +960,7 @@ class CipherSuite:
960960
tripleDESSuites.append(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) # unsupported
961961
tripleDESSuites.append(TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) # unsupp
962962

963+
963964
#: AES-128 CBC ciphers
964965
aes128Suites = []
965966
aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
@@ -1258,6 +1259,8 @@ def filter_for_certificate(suites, cert_chain):
12581259
CipherSuite.certSuites)
12591260
if cert_chain.x509List[0].certAlg == "ecdsa":
12601261
includeSuites.update(CipherSuite.ecdheEcdsaSuites)
1262+
if cert_chain.x509List[0].certAlg == "dsa":
1263+
includeSuites.update(CipherSuite.dheDsaSuites)
12611264
else:
12621265
includeSuites.update(CipherSuite.srpSuites)
12631266
includeSuites.update(CipherSuite.anonSuites)
@@ -1318,6 +1321,8 @@ def _filterSuites(suites, settings, version=None):
13181321
keyExchangeSuites += CipherSuite.certSuites
13191322
if "dhe_rsa" in keyExchangeNames:
13201323
keyExchangeSuites += CipherSuite.dheCertSuites
1324+
if "dhe_dsa" in keyExchangeNames:
1325+
keyExchangeSuites += CipherSuite.dheDsaSuites
13211326
if "ecdhe_rsa" in keyExchangeNames:
13221327
keyExchangeSuites += CipherSuite.ecdheCertSuites
13231328
if "ecdhe_ecdsa" in keyExchangeNames:
@@ -1361,6 +1366,17 @@ def getSrpCertSuites(cls, settings, version=None):
13611366
"""Return SRP cipher suites that use server certificates"""
13621367
return cls._filterSuites(CipherSuite.srpCertSuites, settings, version)
13631368

1369+
#: SRP key exchange, DSA authentication
1370+
srpDsaSuites = []
1371+
srpDsaSuites.append(TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) # unsupported
1372+
srpDsaSuites.append(TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) # unsupported
1373+
srpDsaSuites.append(TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) # unsupported
1374+
1375+
@classmethod
1376+
def getSrpDsaSuites(cls, settings, version=None):
1377+
"""Return SRP DSA cipher suites that use server certificates"""
1378+
return cls._filterSuites(CipherSuite.srpCertSuites, settings, version)
1379+
13641380
#: All that use SRP key exchange
13651381
srpAllSuites = srpSuites + srpCertSuites
13661382

@@ -1460,6 +1476,22 @@ def getEcdsaSuites(cls, settings, version=None):
14601476
return cls._filterSuites(CipherSuite.ecdheEcdsaSuites,
14611477
settings, version)
14621478

1479+
#: DHE key exchange, DSA authentication
1480+
dheDsaSuites = []
1481+
dheDsaSuites.append(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA)
1482+
dheDsaSuites.append(TLS_DHE_DSS_WITH_AES_128_CBC_SHA)
1483+
dheDsaSuites.append(TLS_DHE_DSS_WITH_AES_256_CBC_SHA)
1484+
dheDsaSuites.append(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256)
1485+
dheDsaSuites.append(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256)
1486+
dheDsaSuites.append(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256)
1487+
dheDsaSuites.append(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384)
1488+
1489+
@classmethod
1490+
def getDheDsaSuites(cls, settings, version=None):
1491+
"""Provide DSA authenticated ciphersuites matching settings"""
1492+
return cls._filterSuites(CipherSuite.dheDsaSuites,
1493+
settings, version)
1494+
14631495
#: anon FFDHE key exchange
14641496
anonSuites = []
14651497
anonSuites.append(TLS_DH_ANON_WITH_AES_256_GCM_SHA384)
@@ -1476,7 +1508,7 @@ def getAnonSuites(cls, settings, version=None):
14761508
"""Provide anonymous DH ciphersuites matching settings"""
14771509
return cls._filterSuites(CipherSuite.anonSuites, settings, version)
14781510

1479-
dhAllSuites = dheCertSuites + anonSuites
1511+
dhAllSuites = dheCertSuites + anonSuites + dheDsaSuites
14801512

14811513
#: anon ECDHE key exchange
14821514
ecdhAnonSuites = []

tlslite/handshakesettings.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@
2424
MAC_NAMES = ["sha", "sha256", "sha384", "aead"]
2525
ALL_MAC_NAMES = MAC_NAMES + ["md5"]
2626
KEY_EXCHANGE_NAMES = ["ecdhe_ecdsa", "rsa", "dhe_rsa", "ecdhe_rsa", "srp_sha",
27-
"srp_sha_rsa", "ecdh_anon", "dh_anon"]
27+
"srp_sha_rsa", "ecdh_anon", "dh_anon", "dhe_dsa"]
2828
CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
2929
CERTIFICATE_TYPES = ["x509"]
3030
RSA_SIGNATURE_HASHES = ["sha512", "sha384", "sha256", "sha224", "sha1"]
31+
DSA_SIGNATURE_HASHES = ["sha512", "sha384", "sha256", "sha224", "sha1"]
3132
ECDSA_SIGNATURE_HASHES = ["sha512", "sha384", "sha256", "sha224", "sha1"]
3233
ALL_RSA_SIGNATURE_HASHES = RSA_SIGNATURE_HASHES + ["md5"]
3334
RSA_SCHEMES = ["pss", "pkcs1"]
@@ -143,15 +144,15 @@ class HandshakeSettings(object):
143144
:vartype minKeySize: int
144145
:ivar minKeySize: The minimum bit length for asymmetric keys.
145146
146-
If the other party tries to use SRP, RSA, or Diffie-Hellman
147+
If the other party tries to use SRP, RSA, DSA, or Diffie-Hellman
147148
parameters smaller than this length, an alert will be
148149
signalled. The default is 1023.
149150
150151
151152
:vartype maxKeySize: int
152153
:ivar maxKeySize: The maximum bit length for asymmetric keys.
153154
154-
If the other party tries to use SRP, RSA, or Diffie-Hellman
155+
If the other party tries to use SRP, RSA, DSA, or Diffie-Hellman
155156
parameters larger than this length, an alert will be signalled.
156157
The default is 8193.
157158
@@ -234,6 +235,16 @@ class HandshakeSettings(object):
234235
The allowed hashes are: "md5", "sha1", "sha224", "sha256",
235236
"sha384" and "sha512". The default list does not include md5.
236237
238+
:vartype dsaSigHashes: list(str)
239+
:ivar dsaSigHashes: List of hashes supported (and advertised as such) for
240+
TLS 1.2 signatures over Server Key Exchange or Certificate Verify with
241+
DSA signature algorithm.
242+
243+
The list is sorted from most wanted to least wanted algorithm.
244+
245+
The allowed hashes are: "sha1", "sha224", "sha256",
246+
"sha384" and "sha512".
247+
237248
:vartype ecdsaSigHashes: list(str)
238249
:ivar ecdsaSigHashes: List of hashes supported (and advertised as such) for
239250
TLS 1.2 signatures over Server Key Exchange or Certificate Verify with
@@ -337,6 +348,7 @@ def _init_key_settings(self):
337348
self.maxKeySize = 8193
338349
self.rsaSigHashes = list(RSA_SIGNATURE_HASHES)
339350
self.rsaSchemes = list(RSA_SCHEMES)
351+
self.dsaSigHashes = list(DSA_SIGNATURE_HASHES)
340352
self.virtual_hosts = []
341353
# DH key settings
342354
self.eccCurves = list(CURVE_NAMES)
@@ -510,8 +522,14 @@ def _sanityCheckPrimitivesNames(other):
510522
raise ValueError("Unknown RSA padding mode: '{0}'"
511523
.format(unknownRSAPad))
512524

525+
unknownSigHash = not_matching(other.dsaSigHashes,
526+
DSA_SIGNATURE_HASHES)
527+
if unknownSigHash:
528+
raise ValueError("Unknown DSA signature hash: '{0}'"
529+
.format(unknownSigHash))
530+
513531
if not other.rsaSigHashes and not other.ecdsaSigHashes and \
514-
other.maxVersion >= (3, 3):
532+
not other.dsaSigHashes and other.maxVersion >= (3, 3):
515533
raise ValueError("TLS 1.2 requires signature algorithms to be set")
516534

517535
@staticmethod
@@ -668,6 +686,7 @@ def _copy_key_settings(self, other):
668686
other.certificateTypes = self.certificateTypes
669687
other.rsaSigHashes = self.rsaSigHashes
670688
other.rsaSchemes = self.rsaSchemes
689+
other.dsaSigHashes = self.dsaSigHashes
671690
other.ecdsaSigHashes = self.ecdsaSigHashes
672691
other.virtual_hosts = self.virtual_hosts
673692
# DH key params

0 commit comments

Comments
 (0)