-
-
Save kayrus/096e129bd4f6a5cf9f41bff06c7eeb83 to your computer and use it in GitHub Desktop.
tls v1.3 client auth bug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/tls" | |
"crypto/x509" | |
"errors" | |
"io" | |
"log" | |
"net" | |
"os" | |
"sync" | |
) | |
const ( | |
listenAddr = ":1025" | |
caCert = `-----BEGIN CERTIFICATE----- | |
MIIDbTCCAlWgAwIBAgIUVwNm5lbANEdm2vAdgvghqryM49gwDQYJKoZIhvcNAQEL | |
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM | |
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMjEwMjExMDIyNTVaGA8yMDUw | |
MDMwODEwMjI1NVowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx | |
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN | |
AQEBBQADggEPADCCAQoCggEBAJmqwNp4DPcK+APrULug5CsvOwmdFAtINUsVOXVC | |
3n3cVn0HVkBB5xEcFfw/2XM+4CY9HgQVYkxcQGnIH+54EYbBZdMf+JE/KmTinGIM | |
lSyweWlkH2vV+5X1qvmEKTXFnDnR3xH+X8yKhvmhq8jaLzSrIP7NWWVxaBwFCeiU | |
sRuwAckpyXhSADEtpNAWmual65zTLaWfwpzPU1Ho9eRQaJWRl74KkehtYQEAngcH | |
zTTyCgVD/ULa7EqNMWenQI7M0N7lytALLfbXMtYzPdYuZlffXxvoGVSrdSe5903H | |
bTmYSS32Rjnj+cAiZhGh7KiW82Pt5fqylff9vOo7x3Dq5OkCAwEAAaNTMFEwHQYD | |
VR0OBBYEFPIPJCcn8mekXQzKGGZQyrlEyypxMB8GA1UdIwQYMBaAFPIPJCcn8mek | |
XQzKGGZQyrlEyypxMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB | |
ACLhdtiLhFxBRczbFW74fYpMf44wBCgBmqotTJ7hww4DRvhAiZqGQTrYlcwufdVj | |
j2HInGixHPj3otxk03fZ8AMuixcPQX+hJJSR1cPLcbvI5l0QByXR/3phXc4OyaTO | |
F5LtFbsLmpMLWT0lEIzE5aya+YrSH5K664LaUrz4tGEcjvLdYDF/ygio9z14ebln | |
6bOGqp3QdlN9OXIgWePoSNhev+5oRIAuaXFTshl05eD///u1F0q02JfZAoawibCI | |
JRvsH79Mc88j6AUUMhTCqvusNIfFpVgXQP74Ykx1ftNcHBJUGbT1T6LuTbm8Rjax | |
ThtF6M/HK0OR3kCGJ87B/6g= | |
-----END CERTIFICATE-----` | |
srvCert = `-----BEGIN CERTIFICATE----- | |
MIIDETCCAfkCFAECsFNXgt6VOgMMnSTpM7hLDw49MA0GCSqGSIb3DQEBCwUAMEUx | |
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl | |
cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjIxMDIxMTAyMzMzWhcNMjMxMDIxMTAy | |
MzMzWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE | |
CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOC | |
AQ8AMIIBCgKCAQEAyPMnCCmzh+E9b6gW4Gr5cknrWXA0JZOpdT6j2ThMRDpMAUwC | |
J480Y/RZ9tOR/LHf54SI34ROKpyS1jk4PTzKZg2jwwQCgqMlyFMEXt8AeydbCF8E | |
pNttIK6T/fCGdHq3SfuOVfaJNNG+trBiZjJQzsRFotuHFXEXzQ6kZ6tAuEbGLf5Z | |
fwXS6r0vKrBNHQWsZVdhfGQh0qzbDJFUdFpMtNiIMQsxZ8EVETOqyvgGs4yLsbP3 | |
0IRL8Te7dc+oJhasd1nZWoKqx5v7nUY6JiJIx8HnrpHE4BnLCrzLJXMJeTF6KsQj | |
VplKYrPwzJZb2VH0sCwakWM3/4xOWNcUczMU1QIDAQABMA0GCSqGSIb3DQEBCwUA | |
A4IBAQBL9kOzZSCMGJW49d8ixh50+FKurKmNmxYNpWAywpxqAIj+lYrJvTfIhCth | |
xBO3FRE0K2yD2nFZn4SMwMNwjkU73u+7rkroCzts2o+hw3PZzAmLIF+Jn4yP/bfR | |
7mn+C1gBktBqRyImwwsK7CE62ekK6t74ZmBo7xa+ieHRsYT2d5+ntWGuXdYjIGKv | |
+sr2rnoAqj87fapOmFoF0vzLvgKyxa/pJR1YQa64LsKoboIHJB/xHSa6hHrjOr0/ | |
PefwirsdmZvFOh9blI6wItCshdkv52pLqKjqBzIkvckuagQAHNlEusFHq2CW5ew7 | |
a0bpzEdBaA834btqaeAIsV0RtxZU | |
-----END CERTIFICATE-----` | |
srvKey = `-----BEGIN PRIVATE KEY----- | |
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDI8ycIKbOH4T1v | |
qBbgavlySetZcDQlk6l1PqPZOExEOkwBTAInjzRj9Fn205H8sd/nhIjfhE4qnJLW | |
OTg9PMpmDaPDBAKCoyXIUwRe3wB7J1sIXwSk220grpP98IZ0erdJ+45V9ok00b62 | |
sGJmMlDOxEWi24cVcRfNDqRnq0C4RsYt/ll/BdLqvS8qsE0dBaxlV2F8ZCHSrNsM | |
kVR0Wky02IgxCzFnwRURM6rK+AazjIuxs/fQhEvxN7t1z6gmFqx3WdlagqrHm/ud | |
RjomIkjHweeukcTgGcsKvMslcwl5MXoqxCNWmUpis/DMllvZUfSwLBqRYzf/jE5Y | |
1xRzMxTVAgMBAAECggEAHFW05kDDEODgwdLIzwImhEgKCIV6xOWqWl7nyaRXlLNH | |
rlMiZqOZtpJo8RXqGuCV+tZEWogUYYvMZKqS1Iey3msD8WaqV/NbS4DxN9NoBPWK | |
r4Z+aCSMobQcKA13WAtJtwPikRp/RFRi+O2sIk7r+AvS6eDcjlhxC7gJ1JhgOtt3 | |
8bscD4J7INkGn4NxDbVUwMgEItTvR85a3FA0h2fU5Xw4qcOBS3xrjg26dkBu3mPi | |
pchnB3COysx4wXcTN+osJlwIebZX0cikyoQsGarC1fXFfscxtgIznNTk3tf7LL3g | |
iFcPOR5D9h7ofgSZQB5h1TJA4N76G+dmnhObqgGhjQKBgQDn1+HoHT8mo5sV6ISj | |
r5IaXwzVNyr4Nyuy8Sjt/srtbrbKFbTUMboZw9LokYMZfADhAmTQQbDMoTI1OojB | |
46rGMnqdV4xoTgKJCa0Qja7Ih7PDKGT2aaC3gsfb8jEnUPt35JUnnuRmIzEUnfnW | |
MIcxkSoLabY1zsmiI5DHBEI/+wKBgQDd4zoQErm32TRz1MVlTXjSNV1G9m9fm2df | |
7+KZ1Kc3PCC9vz/I60shBSY8iDfd3+a5Z3J7B8J0Ko9wvG5pg8nyuHE7WpAMyKZe | |
Z5RvmsEcHOlXSa5br2d+4LrLeJnk6EWZDbWMCxsOgvh/BSpvbAXMPzlL0f7e0Uh2 | |
QgL27cFVbwKBgQDCqcYZsazbkZVe8Mul8H3ZPKO2xsqCfTho2ApIwp26fDJoPY+G | |
d3ZNudl1wu/zzuWiB/OD1RRQzKwue0ZmnfU+0xWW1PKkhZOlYoV4l64A28g4/crA | |
B3KVgu6yo4lX/KwYP8po6QXXKIdGS1qB2F87ZCqMSKdgSI+OXxRptg62TwKBgQCX | |
UCGEXICx0zll1C9YyeAe2a1mex+wPzXbwqbw6Ievrx1UyFsjFPIC7pQIq4wNjma1 | |
AMqdA8mjlnKDGrzgz7KkBwuQwk2BqkNqFZCwGwSdu0mU8PYqKA+YAoDfyLqJ06vC | |
mAq6Gci1uLLlTAyIN04s3uCfx/Da2jVkD9gdtD0nmQKBgQCH1udMp9ciPhruDe3r | |
ZY+usGKWKKzK540m7YfLoGgyhlmy9K6Ez5QsXlYYsFXlceP63arJ/7UmyLYUmxxx | |
NQ6jOLn6gYfWWll4m8/n0NI3ij7XrDCccV6US0zX6D/IZIwYQfmyvblLFpok6Rtx | |
iYROpm24XSpv5/4Nmtza+TbKgg== | |
-----END PRIVATE KEY-----` | |
clientCert = `-----BEGIN CERTIFICATE----- | |
MIIDETCCAfkCFF8MC134iR9ul6JL/pmcmo5TdH9CMA0GCSqGSIb3DQEBCwUAMEUx | |
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl | |
cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjIxMDIxMTA1MTQ2WhcNMjIxMDIxMTA1 | |
MTQ2WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE | |
CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOC | |
AQ8AMIIBCgKCAQEAz1UeOZBl69tMPbJokG/a9QBrVqExWBuiwunzajHq9i6aQ/I3 | |
/Nyn/EmYr4BDJlITSVKsWLuAp/tDl+LFS8ws0ufy0hy0nAnWaVFg4b4DlsUO2CgW | |
SciWf6VZD3q8wGSkOADzOne/KROPUykOycYcWqcETti5TPqvTYm3yd2YxLeMqje1 | |
TQ821QzC5W7iH5kvpCDAxM8BfushAuF4wYJYQWlsuWAY+uxVvjMWK6uJaOYKiQOf | |
oWElnwjJu/ll9wAdt/VCkh3iNguxKSvO/sWAS2tUlb4aOIh11iM9h0+tNQXPqr4x | |
3WxAphp3qrKS3xnnNVwS6kEGOjyQ7MeZj3Z1kwIDAQABMA0GCSqGSIb3DQEBCwUA | |
A4IBAQAfm9rVN/ISlDnrZstDBODMvgVZoz4bxriqL95uSKqrEAEtQdvjTdIiopC7 | |
xfJ0wnWdENL+7TiVjM0i01HX73RNgpM7fR+XwT1Gk9yWnTzvyKgk/59WEDAihxIO | |
nokCmy+BvWQhl+E05ZVWq4u4GBOXrC+6vc+SgiTBbvGy6l7zCQntEimAI40M6x08 | |
SGoiUDy3H3t6OlL4QloAzbwwdhxquj969S0x2BrApzfh9r9GrUwjYw898lh7g3ER | |
U1T0+AhuI9TUcx6WgrYQDbYS0nI4hqTpXS9MfVpnWJHUcOiuRRHdcT1f52Uue5O6 | |
Dz1++jEtjLi/5EeOxzu7xb9EwHSd | |
-----END CERTIFICATE-----` | |
clientKey = `-----BEGIN PRIVATE KEY----- | |
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPVR45kGXr20w9 | |
smiQb9r1AGtWoTFYG6LC6fNqMer2LppD8jf83Kf8SZivgEMmUhNJUqxYu4Cn+0OX | |
4sVLzCzS5/LSHLScCdZpUWDhvgOWxQ7YKBZJyJZ/pVkPerzAZKQ4APM6d78pE49T | |
KQ7JxhxapwRO2LlM+q9NibfJ3ZjEt4yqN7VNDzbVDMLlbuIfmS+kIMDEzwF+6yEC | |
4XjBglhBaWy5YBj67FW+MxYrq4lo5gqJA5+hYSWfCMm7+WX3AB239UKSHeI2C7Ep | |
K87+xYBLa1SVvho4iHXWIz2HT601Bc+qvjHdbECmGneqspLfGec1XBLqQQY6PJDs | |
x5mPdnWTAgMBAAECggEAHm1tfCE29ABBFiTit5/S0HX5SsNpTHbx0g0njgQ5aVu5 | |
hBM+KDvx41Kht8/pCuysq+wYIwWRghWb++Rp9A/I3ELyHefckbHX56jrwPVz7WKK | |
JSrs6nMnsx//DAiFPu8GMrng+EmuokaemCPEadRLQPqV5URlHWkE5So68MM2slfB | |
wIW+juddu73qmV3KWDM8bFEXv9MM6qBavoJtAkWC92rqcDPxEg1QhOlh1Bbm/TAK | |
PinPEohHAM3rpXtGleKwww1854dOZY0H9M7YZWunlMqTaqi02mvpvnxacqIP8Y0x | |
/MylDszUJ+wnV7yCOJupaTP1olCD9Xq+j2NvWQH5IQKBgQDR4EF8/VkaevvILAMR | |
xohpEeYm3KZCesG5Te+bOtlxSmueTg/yOCMHwwSAqWB7OrMlU8DDHRBIN6mF1JEV | |
hiDLKuhJ7Lpdl07WsLrGDnFXQs82g19sMOrBGLG7taV+99DqhSRpMMIS2WLSIXO/ | |
zDi9M8UKNRzCvm+oP0XzVd8gWwKBgQD85cNaarPpRXlqG6BqkM/rr9byQAbDcXg1 | |
HKpwU1Qsuq5VH5rbfSWLCLS2eX199+0ssfxmitPiieVm105w4egJGHZtkrK7RKDr | |
PkoJMqgHl1Mg93vPv/F9vTpVE5uGq5UnUPgeE2iR29PTo6c3cUQEqp+HcwWKZAog | |
W0LCzLGFKQKBgQDFuQ45YL0HM4HtLXmez3lH83LufcWsr9W+a+wmRCUClGga9dQU | |
EEsATvv48plQvxZzPhpGNyVVxArTaFVe/8P5Y+z/aCSTc670l/7+BDFHUkvBQbcu | |
SE+Bp3AaNaE6ouGRb+nDqAnOlDqDWLyhnxZ9OT6SxULZPWwYB7Qw8V+KLQKBgQCU | |
WYObCnS3JhXu9H3JhWEydFe2i3BsPaeyIDqq4XbDNk8FiCCjGGppgJXhZKsEtebf | |
DRluXYmlnhZ/mVVeSmZ+z2bJKADIcZ2j4Uo00w5WRaJx+Dscxw+2HsaVGYdmHEjG | |
Y2zo16HDzhwYTivNDhhEVIJ4RjS91alLCb3D36dS4QKBgHiQIt0dL07WfBNtwUvy | |
COKyV6t5Qi3AwHGAlzUHEL96Eflv/6qK7r+34ALezSCZkqgBJiC+VRG0e2w3HlxG | |
iqdOa6i0bfH7Vi6tuiu39zJKMrABdBSs9yu2iTUC+h65/6JehVMZ3gelRJp3vWMV | |
vghzfjn9k1NJpZWCusI17Sng | |
-----END PRIVATE KEY-----` | |
) | |
var ( | |
serverLog = log.New(os.Stderr, "SERVER: ", log.LstdFlags|log.Lmsgprefix|log.Lmicroseconds) | |
clientLog = log.New(os.Stderr, "CLIENT: ", log.LstdFlags|log.Lmsgprefix|log.Lmicroseconds) | |
) | |
func main() { | |
caCertPool := x509.NewCertPool() | |
caCertPool.AppendCertsFromPEM([]byte(caCert)) | |
serverCert, err := tls.X509KeyPair([]byte(srvCert), []byte(srvKey)) | |
if err != nil { | |
log.Fatal(err) | |
} | |
clientCert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey)) | |
if err != nil { | |
log.Fatal(err) | |
} | |
tlsConfig := &tls.Config{ | |
MinVersion: tls.VersionTLS12, | |
ClientCAs: caCertPool, | |
ClientAuth: tls.VerifyClientCertIfGiven, | |
Certificates: []tls.Certificate{serverCert}, | |
} | |
listener, err := tls.Listen("tcp", listenAddr, tlsConfig) | |
if err != nil { | |
log.Fatalf("Could not listen on %s: %v\n", listenAddr, err) | |
} | |
wg := sync.WaitGroup{} | |
// run TLS server | |
go func() { | |
for { | |
c, err := listener.Accept() | |
if err != nil { | |
if errors.Is(err, net.ErrClosed) { | |
return | |
} | |
serverLog.Printf("cannot accept: %v", err) | |
continue | |
} | |
wg.Add(1) | |
go func(c net.Conn) { | |
defer wg.Done() | |
if tlsConn, ok := c.(*tls.Conn); ok { | |
err := tlsConn.Handshake() | |
if err != nil { | |
serverLog.Printf("tls handshake failed: %v", err) | |
c.Close() | |
return | |
} | |
b, err := io.ReadAll(tlsConn) | |
if err != nil { | |
serverLog.Fatalf("tls read failed: %v", err) | |
} | |
serverLog.Printf("server read: %s", b) | |
} else { | |
serverLog.Fatalf("non TLS conn") | |
} | |
c.Close() | |
}(c) | |
} | |
}() | |
tests := []uint16{ | |
tls.VersionTLS12, | |
tls.VersionTLS13, | |
} | |
for i, version := range tests { | |
clientLog.Printf("calling: TLSv1.%d", i+2) | |
err = tlsTest(version, []tls.Certificate{clientCert}) | |
wg.Wait() | |
if err == nil { | |
clientLog.Fatalf("ERROR: server must return a handshake error") | |
} | |
} | |
if err := listener.Close(); err != nil && !errors.Is(err, net.ErrClosed) { | |
clientLog.Fatalf("failed to close listener: %v", err) | |
} | |
} | |
func tlsTest(tlsVersion uint16, cert []tls.Certificate) error { | |
tlsConfig := &tls.Config{ | |
MinVersion: tlsVersion, | |
MaxVersion: tlsVersion, | |
Certificates: cert, | |
InsecureSkipVerify: true, | |
} | |
conn, err := net.Dial("tcp", listenAddr) | |
if err != nil { | |
return err | |
} | |
defer conn.Close() | |
tlsConn := tls.Client(conn, tlsConfig) | |
err = tlsConn.Handshake() | |
if err != nil { | |
clientLog.Printf("TLS client Handshake failed: %v", err) | |
} | |
return err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment