From 82539ad8d59729fb45b0bb0edda8f2bddb719eb1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 15:15:26 +0200 Subject: Adding upstream version 1.17.13. Signed-off-by: Daniel Baumann --- src/crypto/aes/aes_gcm.go | 194 + src/crypto/aes/aes_test.go | 383 ++ src/crypto/aes/asm_amd64.s | 274 ++ src/crypto/aes/asm_arm64.s | 281 ++ src/crypto/aes/asm_ppc64le.s | 501 ++ src/crypto/aes/asm_s390x.s | 191 + src/crypto/aes/block.go | 182 + src/crypto/aes/cbc_s390x.go | 65 + src/crypto/aes/cipher.go | 78 + src/crypto/aes/cipher_asm.go | 100 + src/crypto/aes/cipher_generic.go | 27 + src/crypto/aes/cipher_ppc64le.go | 82 + src/crypto/aes/cipher_s390x.go | 95 + src/crypto/aes/const.go | 365 ++ src/crypto/aes/ctr_s390x.go | 83 + src/crypto/aes/gcm_amd64.s | 1286 ++++++ src/crypto/aes/gcm_arm64.s | 1021 ++++ src/crypto/aes/gcm_ppc64le.go | 258 ++ src/crypto/aes/gcm_ppc64le.s | 563 +++ src/crypto/aes/gcm_s390x.go | 368 ++ src/crypto/aes/modes.go | 37 + src/crypto/aes/modes_test.go | 112 + src/crypto/cipher/benchmark_test.go | 137 + src/crypto/cipher/cbc.go | 163 + src/crypto/cipher/cbc_aes_test.go | 104 + src/crypto/cipher/cfb.go | 80 + src/crypto/cipher/cfb_test.go | 113 + src/crypto/cipher/cipher.go | 69 + src/crypto/cipher/cipher_test.go | 90 + src/crypto/cipher/common_test.go | 28 + src/crypto/cipher/ctr.go | 91 + src/crypto/cipher/ctr_aes_test.go | 102 + src/crypto/cipher/ctr_test.go | 55 + src/crypto/cipher/example_test.go | 363 ++ src/crypto/cipher/export_test.go | 8 + src/crypto/cipher/gcm.go | 426 ++ src/crypto/cipher/gcm_test.go | 511 ++ src/crypto/cipher/io.go | 53 + src/crypto/cipher/ofb.go | 74 + src/crypto/cipher/ofb_test.go | 102 + src/crypto/cipher/xor_amd64.go | 27 + src/crypto/cipher/xor_amd64.s | 54 + src/crypto/cipher/xor_arm64.go | 29 + src/crypto/cipher/xor_arm64.s | 67 + src/crypto/cipher/xor_generic.go | 92 + src/crypto/cipher/xor_ppc64x.go | 30 + src/crypto/cipher/xor_ppc64x.s | 88 + src/crypto/cipher/xor_test.go | 75 + src/crypto/crypto.go | 203 + src/crypto/des/block.go | 263 ++ src/crypto/des/cipher.go | 155 + src/crypto/des/const.go | 142 + src/crypto/des/des_test.go | 1583 +++++++ src/crypto/des/example_test.go | 25 + src/crypto/dsa/dsa.go | 309 ++ src/crypto/dsa/dsa_test.go | 143 + src/crypto/ecdsa/ecdsa.go | 367 ++ src/crypto/ecdsa/ecdsa_noasm.go | 22 + src/crypto/ecdsa/ecdsa_s390x.go | 163 + src/crypto/ecdsa/ecdsa_s390x.s | 28 + src/crypto/ecdsa/ecdsa_s390x_test.go | 33 + src/crypto/ecdsa/ecdsa_test.go | 401 ++ src/crypto/ecdsa/equal_test.go | 75 + src/crypto/ecdsa/example_test.go | 32 + src/crypto/ecdsa/testdata/SigVer.rsp.bz2 | Bin 0 -> 95485 bytes src/crypto/ed25519/ed25519.go | 215 + src/crypto/ed25519/ed25519_test.go | 247 + src/crypto/ed25519/ed25519vectors_test.go | 109 + src/crypto/ed25519/internal/edwards25519/doc.go | 22 + .../ed25519/internal/edwards25519/edwards25519.go | 427 ++ .../internal/edwards25519/edwards25519_test.go | 304 ++ .../edwards25519/field/_asm/fe_amd64_asm.go | 294 ++ .../internal/edwards25519/field/_asm/go.mod | 5 + .../internal/edwards25519/field/_asm/go.sum | 31 + .../ed25519/internal/edwards25519/field/fe.go | 416 ++ .../internal/edwards25519/field/fe_alias_test.go | 126 + .../internal/edwards25519/field/fe_amd64.go | 14 + .../ed25519/internal/edwards25519/field/fe_amd64.s | 378 ++ .../internal/edwards25519/field/fe_amd64_noasm.go | 12 + .../internal/edwards25519/field/fe_arm64.go | 16 + .../ed25519/internal/edwards25519/field/fe_arm64.s | 42 + .../internal/edwards25519/field/fe_arm64_noasm.go | 12 + .../internal/edwards25519/field/fe_bench_test.go | 36 + .../internal/edwards25519/field/fe_generic.go | 264 ++ .../ed25519/internal/edwards25519/field/fe_test.go | 558 +++ src/crypto/ed25519/internal/edwards25519/scalar.go | 1025 ++++ .../internal/edwards25519/scalar_alias_test.go | 93 + .../ed25519/internal/edwards25519/scalar_test.go | 233 + .../ed25519/internal/edwards25519/scalarmult.go | 214 + .../internal/edwards25519/scalarmult_test.go | 209 + src/crypto/ed25519/internal/edwards25519/tables.go | 129 + .../ed25519/internal/edwards25519/tables_test.go | 119 + src/crypto/ed25519/testdata/sign.input.gz | Bin 0 -> 50330 bytes src/crypto/elliptic/elliptic.go | 491 ++ src/crypto/elliptic/elliptic_test.go | 331 ++ src/crypto/elliptic/fuzz_test.go | 54 + src/crypto/elliptic/internal/fiat/Dockerfile | 12 + src/crypto/elliptic/internal/fiat/README | 39 + src/crypto/elliptic/internal/fiat/p521.go | 197 + src/crypto/elliptic/internal/fiat/p521_fiat64.go | 1856 ++++++++ src/crypto/elliptic/internal/fiat/p521_test.go | 37 + src/crypto/elliptic/p224.go | 783 ++++ src/crypto/elliptic/p224_test.go | 629 +++ src/crypto/elliptic/p256.go | 1193 +++++ src/crypto/elliptic/p256_asm.go | 539 +++ src/crypto/elliptic/p256_asm_amd64.s | 2347 ++++++++++ src/crypto/elliptic/p256_asm_arm64.s | 1529 ++++++ src/crypto/elliptic/p256_asm_ppc64le.s | 2494 ++++++++++ src/crypto/elliptic/p256_asm_s390x.s | 2714 +++++++++++ src/crypto/elliptic/p256_asm_table.go | 1473 ++++++ src/crypto/elliptic/p256_asm_table_test.go | 59 + src/crypto/elliptic/p256_generic.go | 15 + src/crypto/elliptic/p256_ppc64le.go | 522 +++ src/crypto/elliptic/p256_s390x.go | 577 +++ src/crypto/elliptic/p256_test.go | 169 + src/crypto/elliptic/p521.go | 264 ++ src/crypto/hmac/hmac.go | 172 + src/crypto/hmac/hmac_test.go | 629 +++ src/crypto/internal/randutil/randutil.go | 38 + src/crypto/internal/subtle/aliasing.go | 35 + src/crypto/internal/subtle/aliasing_appengine.go | 38 + src/crypto/internal/subtle/aliasing_test.go | 50 + src/crypto/issue21104_test.go | 61 + src/crypto/md5/example_test.go | 42 + src/crypto/md5/gen.go | 260 ++ src/crypto/md5/md5.go | 195 + src/crypto/md5/md5_test.go | 280 ++ src/crypto/md5/md5block.go | 125 + src/crypto/md5/md5block_386.s | 182 + src/crypto/md5/md5block_amd64.s | 179 + src/crypto/md5/md5block_arm.s | 299 ++ src/crypto/md5/md5block_arm64.s | 167 + src/crypto/md5/md5block_decl.go | 14 + src/crypto/md5/md5block_generic.go | 12 + src/crypto/md5/md5block_ppc64x.s | 213 + src/crypto/md5/md5block_s390x.s | 175 + src/crypto/rand/eagain.go | 28 + src/crypto/rand/example_test.go | 28 + src/crypto/rand/rand.go | 43 + src/crypto/rand/rand_batched.go | 33 + src/crypto/rand/rand_batched_test.go | 46 + src/crypto/rand/rand_dragonfly.go | 9 + src/crypto/rand/rand_freebsd.go | 9 + src/crypto/rand/rand_getentropy.go | 31 + src/crypto/rand/rand_js.go | 29 + src/crypto/rand/rand_linux.go | 14 + src/crypto/rand/rand_solaris.go | 10 + src/crypto/rand/rand_test.go | 43 + src/crypto/rand/rand_unix.go | 170 + src/crypto/rand/rand_windows.go | 26 + src/crypto/rand/util.go | 143 + src/crypto/rand/util_test.go | 130 + src/crypto/rc4/rc4.go | 80 + src/crypto/rc4/rc4_test.go | 162 + src/crypto/rsa/equal_test.go | 51 + src/crypto/rsa/example_test.go | 169 + src/crypto/rsa/pkcs1v15.go | 323 ++ src/crypto/rsa/pkcs1v15_test.go | 316 ++ src/crypto/rsa/pss.go | 303 ++ src/crypto/rsa/pss_test.go | 276 ++ src/crypto/rsa/rsa.go | 659 +++ src/crypto/rsa/rsa_test.go | 420 ++ src/crypto/rsa/testdata/pss-vect.txt.bz2 | Bin 0 -> 28526 bytes src/crypto/sha1/example_test.go | 42 + src/crypto/sha1/fallback_test.go | 35 + src/crypto/sha1/issue15617_test.go | 29 + src/crypto/sha1/sha1.go | 266 ++ src/crypto/sha1/sha1_test.go | 240 + src/crypto/sha1/sha1block.go | 83 + src/crypto/sha1/sha1block_386.s | 233 + src/crypto/sha1/sha1block_amd64.go | 34 + src/crypto/sha1/sha1block_amd64.s | 1500 ++++++ src/crypto/sha1/sha1block_arm.s | 217 + src/crypto/sha1/sha1block_arm64.go | 26 + src/crypto/sha1/sha1block_arm64.s | 152 + src/crypto/sha1/sha1block_decl.go | 12 + src/crypto/sha1/sha1block_generic.go | 10 + src/crypto/sha1/sha1block_s390x.go | 9 + src/crypto/sha1/sha1block_s390x.s | 20 + src/crypto/sha256/example_test.go | 41 + src/crypto/sha256/fallback_test.go | 36 + src/crypto/sha256/sha256.go | 270 ++ src/crypto/sha256/sha256_test.go | 315 ++ src/crypto/sha256/sha256block.go | 128 + src/crypto/sha256/sha256block_386.s | 283 ++ src/crypto/sha256/sha256block_amd64.go | 9 + src/crypto/sha256/sha256block_amd64.s | 1031 +++++ src/crypto/sha256/sha256block_arm64.go | 21 + src/crypto/sha256/sha256block_arm64.s | 119 + src/crypto/sha256/sha256block_decl.go | 12 + src/crypto/sha256/sha256block_generic.go | 10 + src/crypto/sha256/sha256block_ppc64le.s | 419 ++ src/crypto/sha256/sha256block_s390x.go | 9 + src/crypto/sha256/sha256block_s390x.s | 20 + src/crypto/sha512/fallback_test.go | 38 + src/crypto/sha512/sha512.go | 367 ++ src/crypto/sha512/sha512_test.go | 914 ++++ src/crypto/sha512/sha512block.go | 144 + src/crypto/sha512/sha512block_amd64.go | 26 + src/crypto/sha512/sha512block_amd64.s | 1468 ++++++ src/crypto/sha512/sha512block_decl.go | 12 + src/crypto/sha512/sha512block_generic.go | 12 + src/crypto/sha512/sha512block_ppc64le.s | 451 ++ src/crypto/sha512/sha512block_s390x.go | 9 + src/crypto/sha512/sha512block_s390x.s | 20 + src/crypto/subtle/constant_time.go | 61 + src/crypto/subtle/constant_time_test.go | 159 + src/crypto/tls/alert.go | 99 + src/crypto/tls/auth.go | 289 ++ src/crypto/tls/auth_test.go | 168 + src/crypto/tls/cipher_suites.go | 689 +++ src/crypto/tls/common.go | 1458 ++++++ src/crypto/tls/common_string.go | 116 + src/crypto/tls/conn.go | 1536 ++++++ src/crypto/tls/conn_test.go | 287 ++ src/crypto/tls/example_test.go | 232 + src/crypto/tls/generate_cert.go | 173 + src/crypto/tls/handshake_client.go | 1011 ++++ src/crypto/tls/handshake_client_test.go | 2597 +++++++++++ src/crypto/tls/handshake_client_tls13.go | 682 +++ src/crypto/tls/handshake_messages.go | 1809 ++++++++ src/crypto/tls/handshake_messages_test.go | 465 ++ src/crypto/tls/handshake_server.go | 875 ++++ src/crypto/tls/handshake_server_test.go | 2028 ++++++++ src/crypto/tls/handshake_server_tls13.go | 872 ++++ src/crypto/tls/handshake_test.go | 529 +++ src/crypto/tls/handshake_unix_test.go | 19 + src/crypto/tls/key_agreement.go | 357 ++ src/crypto/tls/key_schedule.go | 199 + src/crypto/tls/key_schedule_test.go | 175 + src/crypto/tls/link_test.go | 107 + src/crypto/tls/prf.go | 283 ++ src/crypto/tls/prf_test.go | 140 + .../testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA | 134 + .../testdata/Client-TLSv10-ClientCert-ECDSA-RSA | 138 + .../tls/testdata/Client-TLSv10-ClientCert-Ed25519 | 110 + .../testdata/Client-TLSv10-ClientCert-RSA-ECDSA | 133 + .../tls/testdata/Client-TLSv10-ClientCert-RSA-RSA | 137 + .../tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES | 91 + .../tls/testdata/Client-TLSv10-ECDHE-RSA-AES | 95 + src/crypto/tls/testdata/Client-TLSv10-Ed25519 | 0 .../testdata/Client-TLSv10-ExportKeyingMaterial | 95 + src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 | 84 + .../tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES | 93 + .../tls/testdata/Client-TLSv11-ECDHE-RSA-AES | 97 + src/crypto/tls/testdata/Client-TLSv11-Ed25519 | 0 src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 | 84 + .../tls/testdata/Client-TLSv12-AES128-GCM-SHA256 | 86 + .../tls/testdata/Client-TLSv12-AES128-SHA256 | 95 + .../tls/testdata/Client-TLSv12-AES256-GCM-SHA384 | 86 + src/crypto/tls/testdata/Client-TLSv12-ALPN | 93 + src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch | 91 + .../testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA | 139 + .../testdata/Client-TLSv12-ClientCert-ECDSA-RSA | 139 + .../tls/testdata/Client-TLSv12-ClientCert-Ed25519 | 119 + .../Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 | 137 + .../testdata/Client-TLSv12-ClientCert-RSA-ECDSA | 138 + .../tls/testdata/Client-TLSv12-ClientCert-RSA-RSA | 137 + .../Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 | 134 + .../testdata/Client-TLSv12-ClientCert-RSA-RSAPSS | 142 + .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES | 93 + .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM | 88 + .../Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 | 97 + .../Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 | 88 + .../Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 | 84 + .../tls/testdata/Client-TLSv12-ECDHE-RSA-AES | 97 + .../testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 | 101 + .../Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 | 88 + src/crypto/tls/testdata/Client-TLSv12-Ed25519 | 68 + .../testdata/Client-TLSv12-ExportKeyingMaterial | 90 + src/crypto/tls/testdata/Client-TLSv12-P256-ECDHE | 98 + src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 | 84 + .../tls/testdata/Client-TLSv12-RenegotiateOnce | 244 + .../tls/testdata/Client-TLSv12-RenegotiateTwice | 343 ++ .../Client-TLSv12-RenegotiateTwiceRejected | 247 + .../testdata/Client-TLSv12-RenegotiationRejected | 95 + src/crypto/tls/testdata/Client-TLSv12-SCT | 113 + src/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE | 92 + .../tls/testdata/Client-TLSv13-AES128-SHA256 | 90 + .../tls/testdata/Client-TLSv13-AES256-SHA384 | 92 + src/crypto/tls/testdata/Client-TLSv13-ALPN | 93 + .../tls/testdata/Client-TLSv13-CHACHA20-SHA256 | 90 + .../testdata/Client-TLSv13-ClientCert-ECDSA-RSA | 139 + .../tls/testdata/Client-TLSv13-ClientCert-Ed25519 | 122 + .../testdata/Client-TLSv13-ClientCert-RSA-ECDSA | 134 + .../testdata/Client-TLSv13-ClientCert-RSA-RSAPSS | 143 + src/crypto/tls/testdata/Client-TLSv13-ECDSA | 86 + src/crypto/tls/testdata/Client-TLSv13-Ed25519 | 68 + .../testdata/Client-TLSv13-ExportKeyingMaterial | 90 + .../tls/testdata/Client-TLSv13-HelloRetryRequest | 119 + src/crypto/tls/testdata/Client-TLSv13-KeyUpdate | 102 + src/crypto/tls/testdata/Client-TLSv13-P256-ECDHE | 94 + src/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE | 90 + .../tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES | 80 + .../testdata/Server-TLSv10-ExportKeyingMaterial | 93 + src/crypto/tls/testdata/Server-TLSv10-RSA-3DES | 76 + src/crypto/tls/testdata/Server-TLSv10-RSA-AES | 79 + src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 | 73 + src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV | 11 + src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 | 73 + src/crypto/tls/testdata/Server-TLSv12-ALPN | 92 + .../tls/testdata/Server-TLSv12-ALPN-Fallback | 91 + src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch | 14 + .../tls/testdata/Server-TLSv12-ALPN-NotConfigured | 91 + .../Server-TLSv12-ClientAuthRequestedAndECDSAGiven | 126 + ...erver-TLSv12-ClientAuthRequestedAndEd25519Given | 109 + .../Server-TLSv12-ClientAuthRequestedAndGiven | 125 + ...rver-TLSv12-ClientAuthRequestedAndPKCS1v15Given | 125 + .../Server-TLSv12-ClientAuthRequestedNotGiven | 85 + .../tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES | 85 + src/crypto/tls/testdata/Server-TLSv12-Ed25519 | 58 + .../testdata/Server-TLSv12-ExportKeyingMaterial | 89 + src/crypto/tls/testdata/Server-TLSv12-IssueTicket | 91 + .../testdata/Server-TLSv12-IssueTicketPreDisable | 91 + src/crypto/tls/testdata/Server-TLSv12-P256 | 86 + src/crypto/tls/testdata/Server-TLSv12-RSA-3DES | 80 + src/crypto/tls/testdata/Server-TLSv12-RSA-AES | 84 + src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM | 82 + .../testdata/Server-TLSv12-RSA-AES256-GCM-SHA384 | 82 + src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 | 76 + .../tls/testdata/Server-TLSv12-RSA-RSAPKCS1v15 | 77 + src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPSS | 77 + src/crypto/tls/testdata/Server-TLSv12-Resume | 46 + .../tls/testdata/Server-TLSv12-ResumeDisabled | 91 + src/crypto/tls/testdata/Server-TLSv12-SNI | 84 + .../tls/testdata/Server-TLSv12-SNI-GetCertificate | 84 + .../Server-TLSv12-SNI-GetCertificateNotFound | 84 + src/crypto/tls/testdata/Server-TLSv12-X25519 | 82 + .../tls/testdata/Server-TLSv13-AES128-SHA256 | 100 + .../tls/testdata/Server-TLSv13-AES256-SHA384 | 103 + src/crypto/tls/testdata/Server-TLSv13-ALPN | 100 + .../tls/testdata/Server-TLSv13-ALPN-Fallback | 100 + src/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch | 27 + .../tls/testdata/Server-TLSv13-ALPN-NotConfigured | 100 + .../tls/testdata/Server-TLSv13-CHACHA20-SHA256 | 100 + .../Server-TLSv13-ClientAuthRequestedAndECDSAGiven | 179 + ...erver-TLSv13-ClientAuthRequestedAndEd25519Given | 149 + .../Server-TLSv13-ClientAuthRequestedAndGiven | 177 + .../Server-TLSv13-ClientAuthRequestedNotGiven | 104 + .../tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES | 96 + src/crypto/tls/testdata/Server-TLSv13-Ed25519 | 76 + .../testdata/Server-TLSv13-ExportKeyingMaterial | 99 + .../tls/testdata/Server-TLSv13-HelloRetryRequest | 123 + src/crypto/tls/testdata/Server-TLSv13-IssueTicket | 99 + .../testdata/Server-TLSv13-IssueTicketPreDisable | 99 + src/crypto/tls/testdata/Server-TLSv13-P256 | 102 + src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS | 97 + .../tls/testdata/Server-TLSv13-RSA-RSAPSS-TooSmall | 15 + src/crypto/tls/testdata/Server-TLSv13-Resume | 60 + .../Server-TLSv13-Resume-HelloRetryRequest | 96 + .../tls/testdata/Server-TLSv13-ResumeDisabled | 99 + src/crypto/tls/testdata/Server-TLSv13-X25519 | 98 + src/crypto/tls/testdata/example-cert.pem | 11 + src/crypto/tls/testdata/example-key.pem | 5 + src/crypto/tls/ticket.go | 185 + src/crypto/tls/tls.go | 356 ++ src/crypto/tls/tls_test.go | 1611 +++++++ src/crypto/x509/cert_pool.go | 248 + src/crypto/x509/example_test.go | 137 + src/crypto/x509/internal/macos/corefoundation.go | 131 + src/crypto/x509/internal/macos/corefoundation.s | 30 + src/crypto/x509/internal/macos/security.go | 118 + src/crypto/x509/internal/macos/security.s | 20 + src/crypto/x509/name_constraints_test.go | 2160 +++++++++ src/crypto/x509/parser.go | 1013 ++++ src/crypto/x509/parser_test.go | 102 + src/crypto/x509/pem_decrypt.go | 253 + src/crypto/x509/pem_decrypt_test.go | 249 + src/crypto/x509/pkcs1.go | 173 + src/crypto/x509/pkcs8.go | 136 + src/crypto/x509/pkcs8_test.go | 140 + src/crypto/x509/pkix/pkix.go | 316 ++ src/crypto/x509/root.go | 31 + src/crypto/x509/root_aix.go | 16 + src/crypto/x509/root_bsd.go | 24 + src/crypto/x509/root_darwin.go | 240 + src/crypto/x509/root_darwin_test.go | 39 + src/crypto/x509/root_ios.go | 4873 ++++++++++++++++++++ src/crypto/x509/root_ios_gen.go | 181 + src/crypto/x509/root_js.go | 15 + src/crypto/x509/root_linux.go | 23 + src/crypto/x509/root_omit.go | 27 + src/crypto/x509/root_omit_test.go | 24 + src/crypto/x509/root_plan9.go | 40 + src/crypto/x509/root_solaris.go | 18 + src/crypto/x509/root_unix.go | 109 + src/crypto/x509/root_unix_test.go | 229 + src/crypto/x509/root_windows.go | 322 ++ src/crypto/x509/sec1.go | 120 + src/crypto/x509/sec1_test.go | 66 + src/crypto/x509/test-file.crt | 32 + src/crypto/x509/testdata/test-dir.crt | 31 + src/crypto/x509/verify.go | 1108 +++++ src/crypto/x509/verify_test.go | 1970 ++++++++ src/crypto/x509/x509.go | 2203 +++++++++ src/crypto/x509/x509_test.go | 3361 ++++++++++++++ src/crypto/x509/x509_test_import.go | 57 + 397 files changed, 105031 insertions(+) create mode 100644 src/crypto/aes/aes_gcm.go create mode 100644 src/crypto/aes/aes_test.go create mode 100644 src/crypto/aes/asm_amd64.s create mode 100644 src/crypto/aes/asm_arm64.s create mode 100644 src/crypto/aes/asm_ppc64le.s create mode 100644 src/crypto/aes/asm_s390x.s create mode 100644 src/crypto/aes/block.go create mode 100644 src/crypto/aes/cbc_s390x.go create mode 100644 src/crypto/aes/cipher.go create mode 100644 src/crypto/aes/cipher_asm.go create mode 100644 src/crypto/aes/cipher_generic.go create mode 100644 src/crypto/aes/cipher_ppc64le.go create mode 100644 src/crypto/aes/cipher_s390x.go create mode 100644 src/crypto/aes/const.go create mode 100644 src/crypto/aes/ctr_s390x.go create mode 100644 src/crypto/aes/gcm_amd64.s create mode 100644 src/crypto/aes/gcm_arm64.s create mode 100644 src/crypto/aes/gcm_ppc64le.go create mode 100644 src/crypto/aes/gcm_ppc64le.s create mode 100644 src/crypto/aes/gcm_s390x.go create mode 100644 src/crypto/aes/modes.go create mode 100644 src/crypto/aes/modes_test.go create mode 100644 src/crypto/cipher/benchmark_test.go create mode 100644 src/crypto/cipher/cbc.go create mode 100644 src/crypto/cipher/cbc_aes_test.go create mode 100644 src/crypto/cipher/cfb.go create mode 100644 src/crypto/cipher/cfb_test.go create mode 100644 src/crypto/cipher/cipher.go create mode 100644 src/crypto/cipher/cipher_test.go create mode 100644 src/crypto/cipher/common_test.go create mode 100644 src/crypto/cipher/ctr.go create mode 100644 src/crypto/cipher/ctr_aes_test.go create mode 100644 src/crypto/cipher/ctr_test.go create mode 100644 src/crypto/cipher/example_test.go create mode 100644 src/crypto/cipher/export_test.go create mode 100644 src/crypto/cipher/gcm.go create mode 100644 src/crypto/cipher/gcm_test.go create mode 100644 src/crypto/cipher/io.go create mode 100644 src/crypto/cipher/ofb.go create mode 100644 src/crypto/cipher/ofb_test.go create mode 100644 src/crypto/cipher/xor_amd64.go create mode 100644 src/crypto/cipher/xor_amd64.s create mode 100644 src/crypto/cipher/xor_arm64.go create mode 100644 src/crypto/cipher/xor_arm64.s create mode 100644 src/crypto/cipher/xor_generic.go create mode 100644 src/crypto/cipher/xor_ppc64x.go create mode 100644 src/crypto/cipher/xor_ppc64x.s create mode 100644 src/crypto/cipher/xor_test.go create mode 100644 src/crypto/crypto.go create mode 100644 src/crypto/des/block.go create mode 100644 src/crypto/des/cipher.go create mode 100644 src/crypto/des/const.go create mode 100644 src/crypto/des/des_test.go create mode 100644 src/crypto/des/example_test.go create mode 100644 src/crypto/dsa/dsa.go create mode 100644 src/crypto/dsa/dsa_test.go create mode 100644 src/crypto/ecdsa/ecdsa.go create mode 100644 src/crypto/ecdsa/ecdsa_noasm.go create mode 100644 src/crypto/ecdsa/ecdsa_s390x.go create mode 100644 src/crypto/ecdsa/ecdsa_s390x.s create mode 100644 src/crypto/ecdsa/ecdsa_s390x_test.go create mode 100644 src/crypto/ecdsa/ecdsa_test.go create mode 100644 src/crypto/ecdsa/equal_test.go create mode 100644 src/crypto/ecdsa/example_test.go create mode 100644 src/crypto/ecdsa/testdata/SigVer.rsp.bz2 create mode 100644 src/crypto/ed25519/ed25519.go create mode 100644 src/crypto/ed25519/ed25519_test.go create mode 100644 src/crypto/ed25519/ed25519vectors_test.go create mode 100644 src/crypto/ed25519/internal/edwards25519/doc.go create mode 100644 src/crypto/ed25519/internal/edwards25519/edwards25519.go create mode 100644 src/crypto/ed25519/internal/edwards25519/edwards25519_test.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/_asm/go.mod create mode 100644 src/crypto/ed25519/internal/edwards25519/field/_asm/go.sum create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_amd64.s create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_arm64.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_arm64.s create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_generic.go create mode 100644 src/crypto/ed25519/internal/edwards25519/field/fe_test.go create mode 100644 src/crypto/ed25519/internal/edwards25519/scalar.go create mode 100644 src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go create mode 100644 src/crypto/ed25519/internal/edwards25519/scalar_test.go create mode 100644 src/crypto/ed25519/internal/edwards25519/scalarmult.go create mode 100644 src/crypto/ed25519/internal/edwards25519/scalarmult_test.go create mode 100644 src/crypto/ed25519/internal/edwards25519/tables.go create mode 100644 src/crypto/ed25519/internal/edwards25519/tables_test.go create mode 100644 src/crypto/ed25519/testdata/sign.input.gz create mode 100644 src/crypto/elliptic/elliptic.go create mode 100644 src/crypto/elliptic/elliptic_test.go create mode 100644 src/crypto/elliptic/fuzz_test.go create mode 100644 src/crypto/elliptic/internal/fiat/Dockerfile create mode 100644 src/crypto/elliptic/internal/fiat/README create mode 100644 src/crypto/elliptic/internal/fiat/p521.go create mode 100644 src/crypto/elliptic/internal/fiat/p521_fiat64.go create mode 100644 src/crypto/elliptic/internal/fiat/p521_test.go create mode 100644 src/crypto/elliptic/p224.go create mode 100644 src/crypto/elliptic/p224_test.go create mode 100644 src/crypto/elliptic/p256.go create mode 100644 src/crypto/elliptic/p256_asm.go create mode 100644 src/crypto/elliptic/p256_asm_amd64.s create mode 100644 src/crypto/elliptic/p256_asm_arm64.s create mode 100644 src/crypto/elliptic/p256_asm_ppc64le.s create mode 100644 src/crypto/elliptic/p256_asm_s390x.s create mode 100644 src/crypto/elliptic/p256_asm_table.go create mode 100644 src/crypto/elliptic/p256_asm_table_test.go create mode 100644 src/crypto/elliptic/p256_generic.go create mode 100644 src/crypto/elliptic/p256_ppc64le.go create mode 100644 src/crypto/elliptic/p256_s390x.go create mode 100644 src/crypto/elliptic/p256_test.go create mode 100644 src/crypto/elliptic/p521.go create mode 100644 src/crypto/hmac/hmac.go create mode 100644 src/crypto/hmac/hmac_test.go create mode 100644 src/crypto/internal/randutil/randutil.go create mode 100644 src/crypto/internal/subtle/aliasing.go create mode 100644 src/crypto/internal/subtle/aliasing_appengine.go create mode 100644 src/crypto/internal/subtle/aliasing_test.go create mode 100644 src/crypto/issue21104_test.go create mode 100644 src/crypto/md5/example_test.go create mode 100644 src/crypto/md5/gen.go create mode 100644 src/crypto/md5/md5.go create mode 100644 src/crypto/md5/md5_test.go create mode 100644 src/crypto/md5/md5block.go create mode 100644 src/crypto/md5/md5block_386.s create mode 100644 src/crypto/md5/md5block_amd64.s create mode 100644 src/crypto/md5/md5block_arm.s create mode 100644 src/crypto/md5/md5block_arm64.s create mode 100644 src/crypto/md5/md5block_decl.go create mode 100644 src/crypto/md5/md5block_generic.go create mode 100644 src/crypto/md5/md5block_ppc64x.s create mode 100644 src/crypto/md5/md5block_s390x.s create mode 100644 src/crypto/rand/eagain.go create mode 100644 src/crypto/rand/example_test.go create mode 100644 src/crypto/rand/rand.go create mode 100644 src/crypto/rand/rand_batched.go create mode 100644 src/crypto/rand/rand_batched_test.go create mode 100644 src/crypto/rand/rand_dragonfly.go create mode 100644 src/crypto/rand/rand_freebsd.go create mode 100644 src/crypto/rand/rand_getentropy.go create mode 100644 src/crypto/rand/rand_js.go create mode 100644 src/crypto/rand/rand_linux.go create mode 100644 src/crypto/rand/rand_solaris.go create mode 100644 src/crypto/rand/rand_test.go create mode 100644 src/crypto/rand/rand_unix.go create mode 100644 src/crypto/rand/rand_windows.go create mode 100644 src/crypto/rand/util.go create mode 100644 src/crypto/rand/util_test.go create mode 100644 src/crypto/rc4/rc4.go create mode 100644 src/crypto/rc4/rc4_test.go create mode 100644 src/crypto/rsa/equal_test.go create mode 100644 src/crypto/rsa/example_test.go create mode 100644 src/crypto/rsa/pkcs1v15.go create mode 100644 src/crypto/rsa/pkcs1v15_test.go create mode 100644 src/crypto/rsa/pss.go create mode 100644 src/crypto/rsa/pss_test.go create mode 100644 src/crypto/rsa/rsa.go create mode 100644 src/crypto/rsa/rsa_test.go create mode 100644 src/crypto/rsa/testdata/pss-vect.txt.bz2 create mode 100644 src/crypto/sha1/example_test.go create mode 100644 src/crypto/sha1/fallback_test.go create mode 100644 src/crypto/sha1/issue15617_test.go create mode 100644 src/crypto/sha1/sha1.go create mode 100644 src/crypto/sha1/sha1_test.go create mode 100644 src/crypto/sha1/sha1block.go create mode 100644 src/crypto/sha1/sha1block_386.s create mode 100644 src/crypto/sha1/sha1block_amd64.go create mode 100644 src/crypto/sha1/sha1block_amd64.s create mode 100644 src/crypto/sha1/sha1block_arm.s create mode 100644 src/crypto/sha1/sha1block_arm64.go create mode 100644 src/crypto/sha1/sha1block_arm64.s create mode 100644 src/crypto/sha1/sha1block_decl.go create mode 100644 src/crypto/sha1/sha1block_generic.go create mode 100644 src/crypto/sha1/sha1block_s390x.go create mode 100644 src/crypto/sha1/sha1block_s390x.s create mode 100644 src/crypto/sha256/example_test.go create mode 100644 src/crypto/sha256/fallback_test.go create mode 100644 src/crypto/sha256/sha256.go create mode 100644 src/crypto/sha256/sha256_test.go create mode 100644 src/crypto/sha256/sha256block.go create mode 100644 src/crypto/sha256/sha256block_386.s create mode 100644 src/crypto/sha256/sha256block_amd64.go create mode 100644 src/crypto/sha256/sha256block_amd64.s create mode 100644 src/crypto/sha256/sha256block_arm64.go create mode 100644 src/crypto/sha256/sha256block_arm64.s create mode 100644 src/crypto/sha256/sha256block_decl.go create mode 100644 src/crypto/sha256/sha256block_generic.go create mode 100644 src/crypto/sha256/sha256block_ppc64le.s create mode 100644 src/crypto/sha256/sha256block_s390x.go create mode 100644 src/crypto/sha256/sha256block_s390x.s create mode 100644 src/crypto/sha512/fallback_test.go create mode 100644 src/crypto/sha512/sha512.go create mode 100644 src/crypto/sha512/sha512_test.go create mode 100644 src/crypto/sha512/sha512block.go create mode 100644 src/crypto/sha512/sha512block_amd64.go create mode 100644 src/crypto/sha512/sha512block_amd64.s create mode 100644 src/crypto/sha512/sha512block_decl.go create mode 100644 src/crypto/sha512/sha512block_generic.go create mode 100644 src/crypto/sha512/sha512block_ppc64le.s create mode 100644 src/crypto/sha512/sha512block_s390x.go create mode 100644 src/crypto/sha512/sha512block_s390x.s create mode 100644 src/crypto/subtle/constant_time.go create mode 100644 src/crypto/subtle/constant_time_test.go create mode 100644 src/crypto/tls/alert.go create mode 100644 src/crypto/tls/auth.go create mode 100644 src/crypto/tls/auth_test.go create mode 100644 src/crypto/tls/cipher_suites.go create mode 100644 src/crypto/tls/common.go create mode 100644 src/crypto/tls/common_string.go create mode 100644 src/crypto/tls/conn.go create mode 100644 src/crypto/tls/conn_test.go create mode 100644 src/crypto/tls/example_test.go create mode 100644 src/crypto/tls/generate_cert.go create mode 100644 src/crypto/tls/handshake_client.go create mode 100644 src/crypto/tls/handshake_client_test.go create mode 100644 src/crypto/tls/handshake_client_tls13.go create mode 100644 src/crypto/tls/handshake_messages.go create mode 100644 src/crypto/tls/handshake_messages_test.go create mode 100644 src/crypto/tls/handshake_server.go create mode 100644 src/crypto/tls/handshake_server_test.go create mode 100644 src/crypto/tls/handshake_server_tls13.go create mode 100644 src/crypto/tls/handshake_test.go create mode 100644 src/crypto/tls/handshake_unix_test.go create mode 100644 src/crypto/tls/key_agreement.go create mode 100644 src/crypto/tls/key_schedule.go create mode 100644 src/crypto/tls/key_schedule_test.go create mode 100644 src/crypto/tls/link_test.go create mode 100644 src/crypto/tls/prf.go create mode 100644 src/crypto/tls/prf_test.go create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-Ed25519 create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv10-Ed25519 create mode 100644 src/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial create mode 100644 src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv11-Ed25519 create mode 100644 src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ALPN create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-Ed25519 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial create mode 100644 src/crypto/tls/testdata/Client-TLSv12-P256-ECDHE create mode 100644 src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce create mode 100644 src/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice create mode 100644 src/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected create mode 100644 src/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected create mode 100644 src/crypto/tls/testdata/Client-TLSv12-SCT create mode 100644 src/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE create mode 100644 src/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 create mode 100644 src/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 create mode 100644 src/crypto/tls/testdata/Client-TLSv13-ALPN create mode 100644 src/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256 create mode 100644 src/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA create mode 100644 src/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 create mode 100644 src/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS create mode 100644 src/crypto/tls/testdata/Client-TLSv13-ECDSA create mode 100644 src/crypto/tls/testdata/Client-TLSv13-Ed25519 create mode 100644 src/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial create mode 100644 src/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest create mode 100644 src/crypto/tls/testdata/Client-TLSv13-KeyUpdate create mode 100644 src/crypto/tls/testdata/Client-TLSv13-P256-ECDHE create mode 100644 src/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE create mode 100644 src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial create mode 100644 src/crypto/tls/testdata/Server-TLSv10-RSA-3DES create mode 100644 src/crypto/tls/testdata/Server-TLSv10-RSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV create mode 100644 src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ALPN create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndEd25519Given create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv12-Ed25519 create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial create mode 100644 src/crypto/tls/testdata/Server-TLSv12-IssueTicket create mode 100644 src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable create mode 100644 src/crypto/tls/testdata/Server-TLSv12-P256 create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-3DES create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384 create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPKCS1v15 create mode 100644 src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPSS create mode 100644 src/crypto/tls/testdata/Server-TLSv12-Resume create mode 100644 src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled create mode 100644 src/crypto/tls/testdata/Server-TLSv12-SNI create mode 100644 src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate create mode 100644 src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound create mode 100644 src/crypto/tls/testdata/Server-TLSv12-X25519 create mode 100644 src/crypto/tls/testdata/Server-TLSv13-AES128-SHA256 create mode 100644 src/crypto/tls/testdata/Server-TLSv13-AES256-SHA384 create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ALPN create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured create mode 100644 src/crypto/tls/testdata/Server-TLSv13-CHACHA20-SHA256 create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndECDSAGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndEd25519Given create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedNotGiven create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES create mode 100644 src/crypto/tls/testdata/Server-TLSv13-Ed25519 create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ExportKeyingMaterial create mode 100644 src/crypto/tls/testdata/Server-TLSv13-HelloRetryRequest create mode 100644 src/crypto/tls/testdata/Server-TLSv13-IssueTicket create mode 100644 src/crypto/tls/testdata/Server-TLSv13-IssueTicketPreDisable create mode 100644 src/crypto/tls/testdata/Server-TLSv13-P256 create mode 100644 src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS create mode 100644 src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS-TooSmall create mode 100644 src/crypto/tls/testdata/Server-TLSv13-Resume create mode 100644 src/crypto/tls/testdata/Server-TLSv13-Resume-HelloRetryRequest create mode 100644 src/crypto/tls/testdata/Server-TLSv13-ResumeDisabled create mode 100644 src/crypto/tls/testdata/Server-TLSv13-X25519 create mode 100644 src/crypto/tls/testdata/example-cert.pem create mode 100644 src/crypto/tls/testdata/example-key.pem create mode 100644 src/crypto/tls/ticket.go create mode 100644 src/crypto/tls/tls.go create mode 100644 src/crypto/tls/tls_test.go create mode 100644 src/crypto/x509/cert_pool.go create mode 100644 src/crypto/x509/example_test.go create mode 100644 src/crypto/x509/internal/macos/corefoundation.go create mode 100644 src/crypto/x509/internal/macos/corefoundation.s create mode 100644 src/crypto/x509/internal/macos/security.go create mode 100644 src/crypto/x509/internal/macos/security.s create mode 100644 src/crypto/x509/name_constraints_test.go create mode 100644 src/crypto/x509/parser.go create mode 100644 src/crypto/x509/parser_test.go create mode 100644 src/crypto/x509/pem_decrypt.go create mode 100644 src/crypto/x509/pem_decrypt_test.go create mode 100644 src/crypto/x509/pkcs1.go create mode 100644 src/crypto/x509/pkcs8.go create mode 100644 src/crypto/x509/pkcs8_test.go create mode 100644 src/crypto/x509/pkix/pkix.go create mode 100644 src/crypto/x509/root.go create mode 100644 src/crypto/x509/root_aix.go create mode 100644 src/crypto/x509/root_bsd.go create mode 100644 src/crypto/x509/root_darwin.go create mode 100644 src/crypto/x509/root_darwin_test.go create mode 100644 src/crypto/x509/root_ios.go create mode 100644 src/crypto/x509/root_ios_gen.go create mode 100644 src/crypto/x509/root_js.go create mode 100644 src/crypto/x509/root_linux.go create mode 100644 src/crypto/x509/root_omit.go create mode 100644 src/crypto/x509/root_omit_test.go create mode 100644 src/crypto/x509/root_plan9.go create mode 100644 src/crypto/x509/root_solaris.go create mode 100644 src/crypto/x509/root_unix.go create mode 100644 src/crypto/x509/root_unix_test.go create mode 100644 src/crypto/x509/root_windows.go create mode 100644 src/crypto/x509/sec1.go create mode 100644 src/crypto/x509/sec1_test.go create mode 100644 src/crypto/x509/test-file.crt create mode 100644 src/crypto/x509/testdata/test-dir.crt create mode 100644 src/crypto/x509/verify.go create mode 100644 src/crypto/x509/verify_test.go create mode 100644 src/crypto/x509/x509.go create mode 100644 src/crypto/x509/x509_test.go create mode 100644 src/crypto/x509/x509_test_import.go (limited to 'src/crypto') diff --git a/src/crypto/aes/aes_gcm.go b/src/crypto/aes/aes_gcm.go new file mode 100644 index 0000000..1de0e45 --- /dev/null +++ b/src/crypto/aes/aes_gcm.go @@ -0,0 +1,194 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 || arm64 +// +build amd64 arm64 + +package aes + +import ( + "crypto/cipher" + subtleoverlap "crypto/internal/subtle" + "crypto/subtle" + "errors" +) + +// The following functions are defined in gcm_*.s. + +//go:noescape +func gcmAesInit(productTable *[256]byte, ks []uint32) + +//go:noescape +func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte) + +//go:noescape +func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) + +//go:noescape +func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) + +//go:noescape +func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64) + +const ( + gcmBlockSize = 16 + gcmTagSize = 16 + gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. + gcmStandardNonceSize = 12 +) + +var errOpen = errors.New("cipher: message authentication failed") + +// aesCipherGCM implements crypto/cipher.gcmAble so that crypto/cipher.NewGCM +// will use the optimised implementation in this file when possible. Instances +// of this type only exist when hasGCMAsm returns true. +type aesCipherGCM struct { + aesCipherAsm +} + +// Assert that aesCipherGCM implements the gcmAble interface. +var _ gcmAble = (*aesCipherGCM)(nil) + +// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only +// called by crypto/cipher.NewGCM via the gcmAble interface. +func (c *aesCipherGCM) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { + g := &gcmAsm{ks: c.enc, nonceSize: nonceSize, tagSize: tagSize} + gcmAesInit(&g.productTable, g.ks) + return g, nil +} + +type gcmAsm struct { + // ks is the key schedule, the length of which depends on the size of + // the AES key. + ks []uint32 + // productTable contains pre-computed multiples of the binary-field + // element used in GHASH. + productTable [256]byte + // nonceSize contains the expected size of the nonce, in bytes. + nonceSize int + // tagSize contains the size of the tag, in bytes. + tagSize int +} + +func (g *gcmAsm) NonceSize() int { + return g.nonceSize +} + +func (g *gcmAsm) Overhead() int { + return g.tagSize +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +// Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for +// details. +func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { + panic("crypto/cipher: message too large for GCM") + } + + var counter, tagMask [gcmBlockSize]byte + + if len(nonce) == gcmStandardNonceSize { + // Init counter to nonce||1 + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + // Otherwise counter = GHASH(nonce) + gcmAesData(&g.productTable, nonce, &counter) + gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) + } + + encryptBlockAsm(len(g.ks)/4-1, &g.ks[0], &tagMask[0], &counter[0]) + + var tagOut [gcmTagSize]byte + gcmAesData(&g.productTable, data, &tagOut) + + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) { + panic("crypto/cipher: invalid buffer overlap") + } + if len(plaintext) > 0 { + gcmAesEnc(&g.productTable, out, plaintext, &counter, &tagOut, g.ks) + } + gcmAesFinish(&g.productTable, &tagMask, &tagOut, uint64(len(plaintext)), uint64(len(data))) + copy(out[len(plaintext):], tagOut[:]) + + return ret +} + +// Open authenticates and decrypts ciphertext. See the cipher.AEAD interface +// for details. +func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + // Sanity check to prevent the authentication from always succeeding if an implementation + // leaves tagSize uninitialized, for example. + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") + } + + if len(ciphertext) < g.tagSize { + return nil, errOpen + } + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { + return nil, errOpen + } + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + // See GCM spec, section 7.1. + var counter, tagMask [gcmBlockSize]byte + + if len(nonce) == gcmStandardNonceSize { + // Init counter to nonce||1 + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + // Otherwise counter = GHASH(nonce) + gcmAesData(&g.productTable, nonce, &counter) + gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) + } + + encryptBlockAsm(len(g.ks)/4-1, &g.ks[0], &tagMask[0], &counter[0]) + + var expectedTag [gcmTagSize]byte + gcmAesData(&g.productTable, data, &expectedTag) + + ret, out := sliceForAppend(dst, len(ciphertext)) + if subtleoverlap.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap") + } + if len(ciphertext) > 0 { + gcmAesDec(&g.productTable, out, ciphertext, &counter, &expectedTag, g.ks) + } + gcmAesFinish(&g.productTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data))) + + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + for i := range out { + out[i] = 0 + } + return nil, errOpen + } + + return ret, nil +} diff --git a/src/crypto/aes/aes_test.go b/src/crypto/aes/aes_test.go new file mode 100644 index 0000000..1e8bac4 --- /dev/null +++ b/src/crypto/aes/aes_test.go @@ -0,0 +1,383 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "testing" +) + +// See const.go for overview of math here. + +// Test that powx is initialized correctly. +// (Can adapt this code to generate it too.) +func TestPowx(t *testing.T) { + p := 1 + for i := 0; i < len(powx); i++ { + if powx[i] != byte(p) { + t.Errorf("powx[%d] = %#x, want %#x", i, powx[i], p) + } + p <<= 1 + if p&0x100 != 0 { + p ^= poly + } + } +} + +// Multiply b and c as GF(2) polynomials modulo poly +func mul(b, c uint32) uint32 { + i := b + j := c + s := uint32(0) + for k := uint32(1); k < 0x100 && j != 0; k <<= 1 { + // Invariant: k == 1<>8 + } + } +} + +// Test that decryption tables are correct. +// (Can adapt this code to generate them too.) +func TestTd(t *testing.T) { + for i := 0; i < 256; i++ { + s := uint32(sbox1[i]) + s9 := mul(s, 0x9) + sb := mul(s, 0xb) + sd := mul(s, 0xd) + se := mul(s, 0xe) + w := se<<24 | s9<<16 | sd<<8 | sb + td := [][256]uint32{td0, td1, td2, td3} + for j := 0; j < 4; j++ { + if x := td[j][i]; x != w { + t.Fatalf("td[%d][%d] = %#x, want %#x", j, i, x, w) + } + w = w<<24 | w>>8 + } + } +} + +// Test vectors are from FIPS 197: +// https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + +// Appendix A of FIPS 197: Key expansion examples +type KeyTest struct { + key []byte + enc []uint32 + dec []uint32 // decryption expansion; not in FIPS 197, computed from C implementation. +} + +var keyTests = []KeyTest{ + { + // A.1. Expansion of a 128-bit Cipher Key + []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}, + []uint32{ + 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c, + 0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605, + 0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f, + 0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b, + 0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00, + 0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc, + 0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd, + 0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f, + 0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f, + 0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e, + 0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6, + }, + []uint32{ + 0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6, + 0xc7b5a63, 0x1319eafe, 0xb0398890, 0x664cfbb4, + 0xdf7d925a, 0x1f62b09d, 0xa320626e, 0xd6757324, + 0x12c07647, 0xc01f22c7, 0xbc42d2f3, 0x7555114a, + 0x6efcd876, 0xd2df5480, 0x7c5df034, 0xc917c3b9, + 0x6ea30afc, 0xbc238cf6, 0xae82a4b4, 0xb54a338d, + 0x90884413, 0xd280860a, 0x12a12842, 0x1bc89739, + 0x7c1f13f7, 0x4208c219, 0xc021ae48, 0x969bf7b, + 0xcc7505eb, 0x3e17d1ee, 0x82296c51, 0xc9481133, + 0x2b3708a7, 0xf262d405, 0xbc3ebdbf, 0x4b617d62, + 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x9cf4f3c, + }, + }, + { + // A.2. Expansion of a 192-bit Cipher Key + []byte{ + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b, + }, + []uint32{ + 0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5, + 0x62f8ead2, 0x522c6b7b, 0xfe0c91f7, 0x2402f5a5, + 0xec12068e, 0x6c827f6b, 0x0e7a95b9, 0x5c56fec2, + 0x4db7b4bd, 0x69b54118, 0x85a74796, 0xe92538fd, + 0xe75fad44, 0xbb095386, 0x485af057, 0x21efb14f, + 0xa448f6d9, 0x4d6dce24, 0xaa326360, 0x113b30e6, + 0xa25e7ed5, 0x83b1cf9a, 0x27f93943, 0x6a94f767, + 0xc0a69407, 0xd19da4e1, 0xec1786eb, 0x6fa64971, + 0x485f7032, 0x22cb8755, 0xe26d1352, 0x33f0b7b3, + 0x40beeb28, 0x2f18a259, 0x6747d26b, 0x458c553e, + 0xa7e1466c, 0x9411f1df, 0x821f750a, 0xad07d753, + 0xca400538, 0x8fcc5006, 0x282d166a, 0xbc3ce7b5, + 0xe98ba06f, 0x448c773c, 0x8ecc7204, 0x01002202, + }, + nil, + }, + { + // A.3. Expansion of a 256-bit Cipher Key + []byte{ + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4, + }, + []uint32{ + 0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781, + 0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4, + 0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde, + 0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a, + 0xd59aecb8, 0x5bf3c917, 0xfee94248, 0xde8ebe96, + 0xb5a9328a, 0x2678a647, 0x98312229, 0x2f6c79b3, + 0x812c81ad, 0xdadf48ba, 0x24360af2, 0xfab8b464, + 0x98c5bfc9, 0xbebd198e, 0x268c3ba7, 0x09e04214, + 0x68007bac, 0xb2df3316, 0x96e939e4, 0x6c518d80, + 0xc814e204, 0x76a9fb8a, 0x5025c02d, 0x59c58239, + 0xde136967, 0x6ccc5a71, 0xfa256395, 0x9674ee15, + 0x5886ca5d, 0x2e2f31d7, 0x7e0af1fa, 0x27cf73c3, + 0x749c47ab, 0x18501dda, 0xe2757e4f, 0x7401905a, + 0xcafaaae3, 0xe4d59b34, 0x9adf6ace, 0xbd10190d, + 0xfe4890d1, 0xe6188d0b, 0x046df344, 0x706c631e, + }, + nil, + }, +} + +// Test key expansion against FIPS 197 examples. +func TestExpandKey(t *testing.T) { +L: + for i, tt := range keyTests { + enc := make([]uint32, len(tt.enc)) + var dec []uint32 + if tt.dec != nil { + dec = make([]uint32, len(tt.dec)) + } + // This test could only test Go version of expandKey because asm + // version might use different memory layout for expanded keys + // This is OK because we don't expose expanded keys to the outside + expandKeyGo(tt.key, enc, dec) + for j, v := range enc { + if v != tt.enc[j] { + t.Errorf("key %d: enc[%d] = %#x, want %#x", i, j, v, tt.enc[j]) + continue L + } + } + for j, v := range dec { + if v != tt.dec[j] { + t.Errorf("key %d: dec[%d] = %#x, want %#x", i, j, v, tt.dec[j]) + continue L + } + } + } +} + +// Appendix B, C of FIPS 197: Cipher examples, Example vectors. +type CryptTest struct { + key []byte + in []byte + out []byte +} + +var encryptTests = []CryptTest{ + { + // Appendix B. + []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}, + []byte{0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34}, + []byte{0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32}, + }, + { + // Appendix C.1. AES-128 + []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, + []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, + []byte{0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a}, + }, + { + // Appendix C.2. AES-192 + []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + }, + []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, + []byte{0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91}, + }, + { + // Appendix C.3. AES-256 + []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + }, + []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, + []byte{0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89}, + }, +} + +// Test Cipher Encrypt method against FIPS 197 examples. +func TestCipherEncrypt(t *testing.T) { + for i, tt := range encryptTests { + c, err := NewCipher(tt.key) + if err != nil { + t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err) + continue + } + out := make([]byte, len(tt.in)) + c.Encrypt(out, tt.in) + for j, v := range out { + if v != tt.out[j] { + t.Errorf("Cipher.Encrypt %d: out[%d] = %#x, want %#x", i, j, v, tt.out[j]) + break + } + } + } +} + +// Test Cipher Decrypt against FIPS 197 examples. +func TestCipherDecrypt(t *testing.T) { + for i, tt := range encryptTests { + c, err := NewCipher(tt.key) + if err != nil { + t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err) + continue + } + plain := make([]byte, len(tt.in)) + c.Decrypt(plain, tt.out) + for j, v := range plain { + if v != tt.in[j] { + t.Errorf("decryptBlock %d: plain[%d] = %#x, want %#x", i, j, v, tt.in[j]) + break + } + } + } +} + +// Test short input/output. +// Assembly used to not notice. +// See issue 7928. +func TestShortBlocks(t *testing.T) { + bytes := func(n int) []byte { return make([]byte, n) } + + c, _ := NewCipher(bytes(16)) + + mustPanic(t, "crypto/aes: input not full block", func() { c.Encrypt(bytes(1), bytes(1)) }) + mustPanic(t, "crypto/aes: input not full block", func() { c.Decrypt(bytes(1), bytes(1)) }) + mustPanic(t, "crypto/aes: input not full block", func() { c.Encrypt(bytes(100), bytes(1)) }) + mustPanic(t, "crypto/aes: input not full block", func() { c.Decrypt(bytes(100), bytes(1)) }) + mustPanic(t, "crypto/aes: output not full block", func() { c.Encrypt(bytes(1), bytes(100)) }) + mustPanic(t, "crypto/aes: output not full block", func() { c.Decrypt(bytes(1), bytes(100)) }) +} + +func mustPanic(t *testing.T, msg string, f func()) { + defer func() { + err := recover() + if err == nil { + t.Errorf("function did not panic, wanted %q", msg) + } else if err != msg { + t.Errorf("got panic %v, wanted %q", err, msg) + } + }() + f() +} + +func BenchmarkEncrypt(b *testing.B) { + tt := encryptTests[0] + c, err := NewCipher(tt.key) + if err != nil { + b.Fatal("NewCipher:", err) + } + out := make([]byte, len(tt.in)) + b.SetBytes(int64(len(out))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + c.Encrypt(out, tt.in) + } +} + +func BenchmarkDecrypt(b *testing.B) { + tt := encryptTests[0] + c, err := NewCipher(tt.key) + if err != nil { + b.Fatal("NewCipher:", err) + } + out := make([]byte, len(tt.out)) + b.SetBytes(int64(len(out))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + c.Decrypt(out, tt.out) + } +} + +func BenchmarkExpand(b *testing.B) { + tt := encryptTests[0] + n := len(tt.key) + 28 + c := &aesCipher{make([]uint32, n), make([]uint32, n)} + b.ResetTimer() + for i := 0; i < b.N; i++ { + expandKey(tt.key, c.enc, c.dec) + } +} diff --git a/src/crypto/aes/asm_amd64.s b/src/crypto/aes/asm_amd64.s new file mode 100644 index 0000000..ad871ec --- /dev/null +++ b/src/crypto/aes/asm_amd64.s @@ -0,0 +1,274 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) +TEXT ·encryptBlockAsm(SB),NOSPLIT,$0 + MOVQ nr+0(FP), CX + MOVQ xk+8(FP), AX + MOVQ dst+16(FP), DX + MOVQ src+24(FP), BX + MOVUPS 0(AX), X1 + MOVUPS 0(BX), X0 + ADDQ $16, AX + PXOR X1, X0 + SUBQ $12, CX + JE Lenc196 + JB Lenc128 +Lenc256: + MOVUPS 0(AX), X1 + AESENC X1, X0 + MOVUPS 16(AX), X1 + AESENC X1, X0 + ADDQ $32, AX +Lenc196: + MOVUPS 0(AX), X1 + AESENC X1, X0 + MOVUPS 16(AX), X1 + AESENC X1, X0 + ADDQ $32, AX +Lenc128: + MOVUPS 0(AX), X1 + AESENC X1, X0 + MOVUPS 16(AX), X1 + AESENC X1, X0 + MOVUPS 32(AX), X1 + AESENC X1, X0 + MOVUPS 48(AX), X1 + AESENC X1, X0 + MOVUPS 64(AX), X1 + AESENC X1, X0 + MOVUPS 80(AX), X1 + AESENC X1, X0 + MOVUPS 96(AX), X1 + AESENC X1, X0 + MOVUPS 112(AX), X1 + AESENC X1, X0 + MOVUPS 128(AX), X1 + AESENC X1, X0 + MOVUPS 144(AX), X1 + AESENCLAST X1, X0 + MOVUPS X0, 0(DX) + RET + +// func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) +TEXT ·decryptBlockAsm(SB),NOSPLIT,$0 + MOVQ nr+0(FP), CX + MOVQ xk+8(FP), AX + MOVQ dst+16(FP), DX + MOVQ src+24(FP), BX + MOVUPS 0(AX), X1 + MOVUPS 0(BX), X0 + ADDQ $16, AX + PXOR X1, X0 + SUBQ $12, CX + JE Ldec196 + JB Ldec128 +Ldec256: + MOVUPS 0(AX), X1 + AESDEC X1, X0 + MOVUPS 16(AX), X1 + AESDEC X1, X0 + ADDQ $32, AX +Ldec196: + MOVUPS 0(AX), X1 + AESDEC X1, X0 + MOVUPS 16(AX), X1 + AESDEC X1, X0 + ADDQ $32, AX +Ldec128: + MOVUPS 0(AX), X1 + AESDEC X1, X0 + MOVUPS 16(AX), X1 + AESDEC X1, X0 + MOVUPS 32(AX), X1 + AESDEC X1, X0 + MOVUPS 48(AX), X1 + AESDEC X1, X0 + MOVUPS 64(AX), X1 + AESDEC X1, X0 + MOVUPS 80(AX), X1 + AESDEC X1, X0 + MOVUPS 96(AX), X1 + AESDEC X1, X0 + MOVUPS 112(AX), X1 + AESDEC X1, X0 + MOVUPS 128(AX), X1 + AESDEC X1, X0 + MOVUPS 144(AX), X1 + AESDECLAST X1, X0 + MOVUPS X0, 0(DX) + RET + +// func expandKeyAsm(nr int, key *byte, enc, dec *uint32) { +// Note that round keys are stored in uint128 format, not uint32 +TEXT ·expandKeyAsm(SB),NOSPLIT,$0 + MOVQ nr+0(FP), CX + MOVQ key+8(FP), AX + MOVQ enc+16(FP), BX + MOVQ dec+24(FP), DX + MOVUPS (AX), X0 + // enc + MOVUPS X0, (BX) + ADDQ $16, BX + PXOR X4, X4 // _expand_key_* expect X4 to be zero + CMPL CX, $12 + JE Lexp_enc196 + JB Lexp_enc128 +Lexp_enc256: + MOVUPS 16(AX), X2 + MOVUPS X2, (BX) + ADDQ $16, BX + AESKEYGENASSIST $0x01, X2, X1 + CALL _expand_key_256a<>(SB) + AESKEYGENASSIST $0x01, X0, X1 + CALL _expand_key_256b<>(SB) + AESKEYGENASSIST $0x02, X2, X1 + CALL _expand_key_256a<>(SB) + AESKEYGENASSIST $0x02, X0, X1 + CALL _expand_key_256b<>(SB) + AESKEYGENASSIST $0x04, X2, X1 + CALL _expand_key_256a<>(SB) + AESKEYGENASSIST $0x04, X0, X1 + CALL _expand_key_256b<>(SB) + AESKEYGENASSIST $0x08, X2, X1 + CALL _expand_key_256a<>(SB) + AESKEYGENASSIST $0x08, X0, X1 + CALL _expand_key_256b<>(SB) + AESKEYGENASSIST $0x10, X2, X1 + CALL _expand_key_256a<>(SB) + AESKEYGENASSIST $0x10, X0, X1 + CALL _expand_key_256b<>(SB) + AESKEYGENASSIST $0x20, X2, X1 + CALL _expand_key_256a<>(SB) + AESKEYGENASSIST $0x20, X0, X1 + CALL _expand_key_256b<>(SB) + AESKEYGENASSIST $0x40, X2, X1 + CALL _expand_key_256a<>(SB) + JMP Lexp_dec +Lexp_enc196: + MOVQ 16(AX), X2 + AESKEYGENASSIST $0x01, X2, X1 + CALL _expand_key_192a<>(SB) + AESKEYGENASSIST $0x02, X2, X1 + CALL _expand_key_192b<>(SB) + AESKEYGENASSIST $0x04, X2, X1 + CALL _expand_key_192a<>(SB) + AESKEYGENASSIST $0x08, X2, X1 + CALL _expand_key_192b<>(SB) + AESKEYGENASSIST $0x10, X2, X1 + CALL _expand_key_192a<>(SB) + AESKEYGENASSIST $0x20, X2, X1 + CALL _expand_key_192b<>(SB) + AESKEYGENASSIST $0x40, X2, X1 + CALL _expand_key_192a<>(SB) + AESKEYGENASSIST $0x80, X2, X1 + CALL _expand_key_192b<>(SB) + JMP Lexp_dec +Lexp_enc128: + AESKEYGENASSIST $0x01, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x02, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x04, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x08, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x10, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x20, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x40, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x80, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x1b, X0, X1 + CALL _expand_key_128<>(SB) + AESKEYGENASSIST $0x36, X0, X1 + CALL _expand_key_128<>(SB) +Lexp_dec: + // dec + SUBQ $16, BX + MOVUPS (BX), X1 + MOVUPS X1, (DX) + DECQ CX +Lexp_dec_loop: + MOVUPS -16(BX), X1 + AESIMC X1, X0 + MOVUPS X0, 16(DX) + SUBQ $16, BX + ADDQ $16, DX + DECQ CX + JNZ Lexp_dec_loop + MOVUPS -16(BX), X0 + MOVUPS X0, 16(DX) + RET + +TEXT _expand_key_128<>(SB),NOSPLIT,$0 + PSHUFD $0xff, X1, X1 + SHUFPS $0x10, X0, X4 + PXOR X4, X0 + SHUFPS $0x8c, X0, X4 + PXOR X4, X0 + PXOR X1, X0 + MOVUPS X0, (BX) + ADDQ $16, BX + RET + +TEXT _expand_key_192a<>(SB),NOSPLIT,$0 + PSHUFD $0x55, X1, X1 + SHUFPS $0x10, X0, X4 + PXOR X4, X0 + SHUFPS $0x8c, X0, X4 + PXOR X4, X0 + PXOR X1, X0 + + MOVAPS X2, X5 + MOVAPS X2, X6 + PSLLDQ $0x4, X5 + PSHUFD $0xff, X0, X3 + PXOR X3, X2 + PXOR X5, X2 + + MOVAPS X0, X1 + SHUFPS $0x44, X0, X6 + MOVUPS X6, (BX) + SHUFPS $0x4e, X2, X1 + MOVUPS X1, 16(BX) + ADDQ $32, BX + RET + +TEXT _expand_key_192b<>(SB),NOSPLIT,$0 + PSHUFD $0x55, X1, X1 + SHUFPS $0x10, X0, X4 + PXOR X4, X0 + SHUFPS $0x8c, X0, X4 + PXOR X4, X0 + PXOR X1, X0 + + MOVAPS X2, X5 + PSLLDQ $0x4, X5 + PSHUFD $0xff, X0, X3 + PXOR X3, X2 + PXOR X5, X2 + + MOVUPS X0, (BX) + ADDQ $16, BX + RET + +TEXT _expand_key_256a<>(SB),NOSPLIT,$0 + JMP _expand_key_128<>(SB) + +TEXT _expand_key_256b<>(SB),NOSPLIT,$0 + PSHUFD $0xaa, X1, X1 + SHUFPS $0x10, X2, X4 + PXOR X4, X2 + SHUFPS $0x8c, X2, X4 + PXOR X4, X2 + PXOR X1, X2 + + MOVUPS X2, (BX) + ADDQ $16, BX + RET diff --git a/src/crypto/aes/asm_arm64.s b/src/crypto/aes/asm_arm64.s new file mode 100644 index 0000000..13aee5c --- /dev/null +++ b/src/crypto/aes/asm_arm64.s @@ -0,0 +1,281 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" +DATA rotInvSRows<>+0x00(SB)/8, $0x080f0205040b0e01 +DATA rotInvSRows<>+0x08(SB)/8, $0x00070a0d0c030609 +GLOBL rotInvSRows<>(SB), (NOPTR+RODATA), $16 +DATA invSRows<>+0x00(SB)/8, $0x0b0e0104070a0d00 +DATA invSRows<>+0x08(SB)/8, $0x0306090c0f020508 +GLOBL invSRows<>(SB), (NOPTR+RODATA), $16 +// func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) +TEXT ·encryptBlockAsm(SB),NOSPLIT,$0 + MOVD nr+0(FP), R9 + MOVD xk+8(FP), R10 + MOVD dst+16(FP), R11 + MOVD src+24(FP), R12 + + VLD1 (R12), [V0.B16] + + CMP $12, R9 + BLT enc128 + BEQ enc196 +enc256: + VLD1.P 32(R10), [V1.B16, V2.B16] + AESE V1.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V2.B16, V0.B16 + AESMC V0.B16, V0.B16 +enc196: + VLD1.P 32(R10), [V3.B16, V4.B16] + AESE V3.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V4.B16, V0.B16 + AESMC V0.B16, V0.B16 +enc128: + VLD1.P 64(R10), [V5.B16, V6.B16, V7.B16, V8.B16] + VLD1.P 64(R10), [V9.B16, V10.B16, V11.B16, V12.B16] + VLD1.P 48(R10), [V13.B16, V14.B16, V15.B16] + AESE V5.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V6.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V7.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V8.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V9.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V10.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V11.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V12.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V13.B16, V0.B16 + AESMC V0.B16, V0.B16 + AESE V14.B16, V0.B16 + VEOR V0.B16, V15.B16, V0.B16 + VST1 [V0.B16], (R11) + RET + +// func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) +TEXT ·decryptBlockAsm(SB),NOSPLIT,$0 + MOVD nr+0(FP), R9 + MOVD xk+8(FP), R10 + MOVD dst+16(FP), R11 + MOVD src+24(FP), R12 + + VLD1 (R12), [V0.B16] + + CMP $12, R9 + BLT dec128 + BEQ dec196 +dec256: + VLD1.P 32(R10), [V1.B16, V2.B16] + AESD V1.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V2.B16, V0.B16 + AESIMC V0.B16, V0.B16 +dec196: + VLD1.P 32(R10), [V3.B16, V4.B16] + AESD V3.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V4.B16, V0.B16 + AESIMC V0.B16, V0.B16 +dec128: + VLD1.P 64(R10), [V5.B16, V6.B16, V7.B16, V8.B16] + VLD1.P 64(R10), [V9.B16, V10.B16, V11.B16, V12.B16] + VLD1.P 48(R10), [V13.B16, V14.B16, V15.B16] + AESD V5.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V6.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V7.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V8.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V9.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V10.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V11.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V12.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V13.B16, V0.B16 + AESIMC V0.B16, V0.B16 + AESD V14.B16, V0.B16 + VEOR V0.B16, V15.B16, V0.B16 + VST1 [V0.B16], (R11) + RET + +// func expandKeyAsm(nr int, key *byte, enc, dec *uint32) { +// Note that round keys are stored in uint128 format, not uint32 +TEXT ·expandKeyAsm(SB),NOSPLIT,$0 + MOVD nr+0(FP), R8 + MOVD key+8(FP), R9 + MOVD enc+16(FP), R10 + MOVD dec+24(FP), R11 + LDP rotInvSRows<>(SB), (R0, R1) + VMOV R0, V3.D[0] + VMOV R1, V3.D[1] + VEOR V0.B16, V0.B16, V0.B16 // All zeroes + MOVW $1, R13 + TBZ $1, R8, ks192 + TBNZ $2, R8, ks256 + LDPW (R9), (R4, R5) + LDPW 8(R9), (R6, R7) + STPW.P (R4, R5), 8(R10) + STPW.P (R6, R7), 8(R10) + MOVW $0x1b, R14 +ks128Loop: + VMOV R7, V2.S[0] + WORD $0x4E030042 // TBL V3.B16, [V2.B16], V2.B16 + AESE V0.B16, V2.B16 // Use AES to compute the SBOX + EORW R13, R4 + LSLW $1, R13 // Compute next Rcon + ANDSW $0x100, R13, ZR + CSELW NE, R14, R13, R13 // Fake modulo + SUBS $1, R8 + VMOV V2.S[0], R0 + EORW R0, R4 + EORW R4, R5 + EORW R5, R6 + EORW R6, R7 + STPW.P (R4, R5), 8(R10) + STPW.P (R6, R7), 8(R10) + BNE ks128Loop + CBZ R11, ksDone // If dec is nil we are done + SUB $176, R10 + // Decryption keys are encryption keys with InverseMixColumns applied + VLD1.P 64(R10), [V0.B16, V1.B16, V2.B16, V3.B16] + VMOV V0.B16, V7.B16 + AESIMC V1.B16, V6.B16 + AESIMC V2.B16, V5.B16 + AESIMC V3.B16, V4.B16 + VLD1.P 64(R10), [V0.B16, V1.B16, V2.B16, V3.B16] + AESIMC V0.B16, V11.B16 + AESIMC V1.B16, V10.B16 + AESIMC V2.B16, V9.B16 + AESIMC V3.B16, V8.B16 + VLD1 (R10), [V0.B16, V1.B16, V2.B16] + AESIMC V0.B16, V14.B16 + AESIMC V1.B16, V13.B16 + VMOV V2.B16, V12.B16 + VST1.P [V12.B16, V13.B16, V14.B16], 48(R11) + VST1.P [V8.B16, V9.B16, V10.B16, V11.B16], 64(R11) + VST1 [V4.B16, V5.B16, V6.B16, V7.B16], (R11) + B ksDone +ks192: + LDPW (R9), (R2, R3) + LDPW 8(R9), (R4, R5) + LDPW 16(R9), (R6, R7) + STPW.P (R2, R3), 8(R10) + STPW.P (R4, R5), 8(R10) + SUB $4, R8 +ks192Loop: + STPW.P (R6, R7), 8(R10) + VMOV R7, V2.S[0] + WORD $0x4E030042 //TBL V3.B16, [V2.B16], V2.B16 + AESE V0.B16, V2.B16 + EORW R13, R2 + LSLW $1, R13 + SUBS $1, R8 + VMOV V2.S[0], R0 + EORW R0, R2 + EORW R2, R3 + EORW R3, R4 + EORW R4, R5 + EORW R5, R6 + EORW R6, R7 + STPW.P (R2, R3), 8(R10) + STPW.P (R4, R5), 8(R10) + BNE ks192Loop + CBZ R11, ksDone + SUB $208, R10 + VLD1.P 64(R10), [V0.B16, V1.B16, V2.B16, V3.B16] + VMOV V0.B16, V7.B16 + AESIMC V1.B16, V6.B16 + AESIMC V2.B16, V5.B16 + AESIMC V3.B16, V4.B16 + VLD1.P 64(R10), [V0.B16, V1.B16, V2.B16, V3.B16] + AESIMC V0.B16, V11.B16 + AESIMC V1.B16, V10.B16 + AESIMC V2.B16, V9.B16 + AESIMC V3.B16, V8.B16 + VLD1.P 64(R10), [V0.B16, V1.B16, V2.B16, V3.B16] + AESIMC V0.B16, V15.B16 + AESIMC V1.B16, V14.B16 + AESIMC V2.B16, V13.B16 + AESIMC V3.B16, V12.B16 + VLD1 (R10), [V0.B16] + VST1.P [V0.B16], 16(R11) + VST1.P [V12.B16, V13.B16, V14.B16, V15.B16], 64(R11) + VST1.P [V8.B16, V9.B16, V10.B16, V11.B16], 64(R11) + VST1 [V4.B16, V5.B16, V6.B16, V7.B16], (R11) + B ksDone +ks256: + LDP invSRows<>(SB), (R0, R1) + VMOV R0, V4.D[0] + VMOV R1, V4.D[1] + LDPW (R9), (R0, R1) + LDPW 8(R9), (R2, R3) + LDPW 16(R9), (R4, R5) + LDPW 24(R9), (R6, R7) + STPW.P (R0, R1), 8(R10) + STPW.P (R2, R3), 8(R10) + SUB $7, R8 +ks256Loop: + STPW.P (R4, R5), 8(R10) + STPW.P (R6, R7), 8(R10) + VMOV R7, V2.S[0] + WORD $0x4E030042 //TBL V3.B16, [V2.B16], V2.B16 + AESE V0.B16, V2.B16 + EORW R13, R0 + LSLW $1, R13 + SUBS $1, R8 + VMOV V2.S[0], R9 + EORW R9, R0 + EORW R0, R1 + EORW R1, R2 + EORW R2, R3 + VMOV R3, V2.S[0] + WORD $0x4E040042 //TBL V3.B16, [V2.B16], V2.B16 + AESE V0.B16, V2.B16 + VMOV V2.S[0], R9 + EORW R9, R4 + EORW R4, R5 + EORW R5, R6 + EORW R6, R7 + STPW.P (R0, R1), 8(R10) + STPW.P (R2, R3), 8(R10) + BNE ks256Loop + CBZ R11, ksDone + SUB $240, R10 + VLD1.P 64(R10), [V0.B16, V1.B16, V2.B16, V3.B16] + VMOV V0.B16, V7.B16 + AESIMC V1.B16, V6.B16 + AESIMC V2.B16, V5.B16 + AESIMC V3.B16, V4.B16 + VLD1.P 64(R10), [V0.B16, V1.B16, V2.B16, V3.B16] + AESIMC V0.B16, V11.B16 + AESIMC V1.B16, V10.B16 + AESIMC V2.B16, V9.B16 + AESIMC V3.B16, V8.B16 + VLD1.P 64(R10), [V0.B16, V1.B16, V2.B16, V3.B16] + AESIMC V0.B16, V15.B16 + AESIMC V1.B16, V14.B16 + AESIMC V2.B16, V13.B16 + AESIMC V3.B16, V12.B16 + VLD1 (R10), [V0.B16, V1.B16, V2.B16] + AESIMC V0.B16, V18.B16 + AESIMC V1.B16, V17.B16 + VMOV V2.B16, V16.B16 + VST1.P [V16.B16, V17.B16, V18.B16], 48(R11) + VST1.P [V12.B16, V13.B16, V14.B16, V15.B16], 64(R11) + VST1.P [V8.B16, V9.B16, V10.B16, V11.B16], 64(R11) + VST1 [V4.B16, V5.B16, V6.B16, V7.B16], (R11) +ksDone: + RET diff --git a/src/crypto/aes/asm_ppc64le.s b/src/crypto/aes/asm_ppc64le.s new file mode 100644 index 0000000..a69cb78 --- /dev/null +++ b/src/crypto/aes/asm_ppc64le.s @@ -0,0 +1,501 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on CRYPTOGAMS code with the following comment: +// # ==================================================================== +// # Written by Andy Polyakov for the OpenSSL +// # project. The module is, however, dual licensed under OpenSSL and +// # CRYPTOGAMS licenses depending on where you obtain it. For further +// # details see http://www.openssl.org/~appro/cryptogams/. +// # ==================================================================== + +// Original code can be found at the link below: +// https://github.com/dot-asm/cryptogams/blob/master/ppc/aesp8-ppc.pl + +// I changed some function names in order to be more likely to go standards. +// For instance, function aes_p8_set_{en,de}crypt_key become +// set{En,De}cryptKeyAsm. I also split setEncryptKeyAsm in two parts +// and a new session was created (doEncryptKeyAsm). This was necessary to +// avoid arguments overwriting when setDecryptKeyAsm calls setEncryptKeyAsm. +// There were other modifications as well but kept the same functionality. + +#include "textflag.h" + +// For set{En,De}cryptKeyAsm +#define INP R3 +#define BITS R4 +#define OUT R5 +#define PTR R6 +#define CNT R7 +#define ROUNDS R8 +#define TEMP R19 +#define ZERO V0 +#define IN0 V1 +#define IN1 V2 +#define KEY V3 +#define RCON V4 +#define MASK V5 +#define TMP V6 +#define STAGE V7 +#define OUTPERM V8 +#define OUTMASK V9 +#define OUTHEAD V10 +#define OUTTAIL V11 + +// For {en,de}cryptBlockAsm +#define BLK_INP R3 +#define BLK_OUT R4 +#define BLK_KEY R5 +#define BLK_ROUNDS R6 +#define BLK_IDX R7 + +DATA ·rcon+0x00(SB)/8, $0x0100000001000000 // RCON +DATA ·rcon+0x08(SB)/8, $0x0100000001000000 // RCON +DATA ·rcon+0x10(SB)/8, $0x1b0000001b000000 +DATA ·rcon+0x18(SB)/8, $0x1b0000001b000000 +DATA ·rcon+0x20(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK +DATA ·rcon+0x28(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK +DATA ·rcon+0x30(SB)/8, $0x0000000000000000 +DATA ·rcon+0x38(SB)/8, $0x0000000000000000 +GLOBL ·rcon(SB), RODATA, $64 + +// func setEncryptKeyAsm(key *byte, keylen int, enc *uint32) int +TEXT ·setEncryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 + // Load the arguments inside the registers + MOVD key+0(FP), INP + MOVD keylen+8(FP), BITS + MOVD enc+16(FP), OUT + JMP ·doEncryptKeyAsm(SB) + +// This text is used both setEncryptKeyAsm and setDecryptKeyAsm +TEXT ·doEncryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 + // Do not change R10 since it's storing the LR value in setDecryptKeyAsm + + // Check arguments + MOVD $-1, PTR // li 6,-1 exit code to -1 (255) + CMPU INP, $0 // cmpldi r3,0 input key pointer set? + BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort + CMPU OUT, $0 // cmpldi r5,0 output key pointer set? + BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort + MOVD $-2, PTR // li 6,-2 exit code to -2 (254) + CMPW BITS, $128 // cmpwi 4,128 greater or equal to 128 + BC 0x0E, 0, enc_key_abort // blt- .Lenc_key_abort + CMPW BITS, $256 // cmpwi 4,256 lesser or equal to 256 + BC 0x0E, 1, enc_key_abort // bgt- .Lenc_key_abort + ANDCC $0x3f, BITS, TEMP // andi. 0,4,0x3f multiple of 64 + BC 0x06, 2, enc_key_abort // bne- .Lenc_key_abort + + MOVD $·rcon(SB), PTR // PTR point to rcon addr + + // Get key from memory and write aligned into VR + NEG INP, R9 // neg 9,3 R9 is ~INP + 1 + LVX (INP)(R0), IN0 // lvx 1,0,3 Load key inside IN0 + ADD $15, INP, INP // addi 3,3,15 Add 15B to INP addr + LVSR (R9)(R0), KEY // lvsr 3,0,9 + MOVD $0x20, R8 // li 8,0x20 R8 = 32 + CMPW BITS, $192 // cmpwi 4,192 Key size == 192? + LVX (INP)(R0), IN1 // lvx 2,0,3 + VSPLTISB $0x0f, MASK // vspltisb 5,0x0f 0x0f0f0f0f... mask + LVX (PTR)(R0), RCON // lvx 4,0,6 Load first 16 bytes into RCON + VXOR KEY, MASK, KEY // vxor 3,3,5 Adjust for byte swap + LVX (PTR)(R8), MASK // lvx 5,8,6 + ADD $0x10, PTR, PTR // addi 6,6,0x10 PTR to next 16 bytes of RCON + VPERM IN0, IN1, KEY, IN0 // vperm 1,1,2,3 Align + MOVD $8, CNT // li 7,8 CNT = 8 + VXOR ZERO, ZERO, ZERO // vxor 0,0,0 Zero to be zero :) + MOVD CNT, CTR // mtctr 7 Set the counter to 8 (rounds) + + LVSL (OUT)(R0), OUTPERM // lvsl 8,0,5 + VSPLTISB $-1, OUTMASK // vspltisb 9,-1 + LVX (OUT)(R0), OUTHEAD // lvx 10,0,5 + VPERM OUTMASK, ZERO, OUTPERM, OUTMASK // vperm 9,9,0,8 + + BLT loop128 // blt .Loop128 + ADD $8, INP, INP // addi 3,3,8 + BEQ l192 // beq .L192 + ADD $8, INP, INP // addi 3,3,8 + JMP l256 // b .L256 + +loop128: + // Key schedule (Round 1 to 8) + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Write to output + ADD $16, OUT, OUT // addi 5,5,16 Point to the next round + + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + BC 0x10, 0, loop128 // bdnz .Loop128 + + LVX (PTR)(R0), RCON // lvx 4,0,6 Last two round keys + + // Key schedule (Round 9) + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-spat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 9 + ADD $16, OUT, OUT // addi 5,5,16 + + // Key schedule (Round 10) + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 10 + ADD $16, OUT, OUT // addi 5,5,16 + + // Key schedule (Round 11) + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 11 + + ADD $15, OUT, INP // addi 3,5,15 + ADD $0x50, OUT, OUT // addi 5,5,0x50 + + MOVD $10, ROUNDS // li 8,10 + JMP done // b .Ldone + +l192: + LVX (INP)(R0), TMP // lvx 6,0,3 + MOVD $4, CNT // li 7,4 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 + VSPLTISB $8, KEY // vspltisb 3,8 + MOVD CNT, CTR // mtctr 7 + VSUBUBM MASK, KEY, MASK // vsububm 5,5,3 + +loop192: + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + + VSLDOI $8, ZERO, IN1, STAGE // vsldoi 7,0,2,8 + VSPLTW $3, IN0, TMP // vspltw 6,1,3 + VXOR TMP, IN1, TMP // vxor 6,6,2 + VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VXOR IN1, KEY, IN1 // vxor 2,2,3 + VSLDOI $8, STAGE, IN0, STAGE // vsldoi 7,7,1,8 + + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + + VSLDOI $8, IN0, IN1, STAGE // vsldoi 7,1,2,8 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + + VSPLTW $3, IN0, TMP // vspltw 6,1,3 + VXOR TMP, IN1, TMP // vxor 6,6,2 + VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VXOR IN1, KEY, IN1 // vxor 2,2,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $15, OUT, INP // addi 3,5,15 + ADD $16, OUT, OUT // addi 5,5,16 + BC 0x10, 0, loop192 // bdnz .Loop192 + + MOVD $12, ROUNDS // li 8,12 + ADD $0x20, OUT, OUT // addi 5,5,0x20 + JMP done // b .Ldone + +l256: + LVX (INP)(R0), TMP // lvx 6,0,3 + MOVD $7, CNT // li 7,7 + MOVD $14, ROUNDS // li 8,14 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 + MOVD CNT, CTR // mtctr 7 + +loop256: + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN1, IN1, OUTPERM, OUTTAIL // vperm 11,2,2,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $15, OUT, INP // addi 3,5,15 + ADD $16, OUT, OUT // addi 5,5,16 + BC 0x12, 0, done // bdz .Ldone + + VSPLTW $3, IN0, KEY // vspltw 3,1,3 + VSLDOI $12, ZERO, IN1, TMP // vsldoi 6,0,2,12 + VSBOX KEY, KEY // vsbox 3,3 + + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + + VXOR IN1, KEY, IN1 // vxor 2,2,3 + JMP loop256 // b .Loop256 + +done: + LVX (INP)(R0), IN1 // lvx 2,0,3 + VSEL OUTHEAD, IN1, OUTMASK, IN1 // vsel 2,10,2,9 + STVX IN1, (INP+R0) // stvx 2,0,3 + MOVD $0, PTR // li 6,0 set PTR to 0 (exit code 0) + MOVW ROUNDS, 0(OUT) // stw 8,0(5) + +enc_key_abort: + MOVD PTR, INP // mr 3,6 set exit code with PTR value + MOVD INP, ret+24(FP) // Put return value into the FP + RET // blr + +// func setDecryptKeyAsm(key *byte, keylen int, dec *uint32) int +TEXT ·setDecryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 + // Load the arguments inside the registers + MOVD key+0(FP), INP + MOVD keylen+8(FP), BITS + MOVD dec+16(FP), OUT + + MOVD LR, R10 // mflr 10 + CALL ·doEncryptKeyAsm(SB) + MOVD R10, LR // mtlr 10 + + CMPW INP, $0 // cmpwi 3,0 exit 0 = ok + BC 0x06, 2, dec_key_abort // bne- .Ldec_key_abort + + // doEncryptKeyAsm set ROUNDS (R8) with the proper value for each mode + SLW $4, ROUNDS, CNT // slwi 7,8,4 + SUB $240, OUT, INP // subi 3,5,240 + SRW $1, ROUNDS, ROUNDS // srwi 8,8,1 + ADD R7, INP, OUT // add 5,3,7 + MOVD ROUNDS, CTR // mtctr 8 + +// dec_key will invert the key sequence in order to be used for decrypt +dec_key: + MOVWZ 0(INP), TEMP // lwz 0, 0(3) + MOVWZ 4(INP), R6 // lwz 6, 4(3) + MOVWZ 8(INP), R7 // lwz 7, 8(3) + MOVWZ 12(INP), R8 // lwz 8, 12(3) + ADD $16, INP, INP // addi 3,3,16 + MOVWZ 0(OUT), R9 // lwz 9, 0(5) + MOVWZ 4(OUT), R10 // lwz 10,4(5) + MOVWZ 8(OUT), R11 // lwz 11,8(5) + MOVWZ 12(OUT), R12 // lwz 12,12(5) + MOVW TEMP, 0(OUT) // stw 0, 0(5) + MOVW R6, 4(OUT) // stw 6, 4(5) + MOVW R7, 8(OUT) // stw 7, 8(5) + MOVW R8, 12(OUT) // stw 8, 12(5) + SUB $16, OUT, OUT // subi 5,5,16 + MOVW R9, -16(INP) // stw 9, -16(3) + MOVW R10, -12(INP) // stw 10,-12(3) + MOVW R11, -8(INP) // stw 11,-8(3) + MOVW R12, -4(INP) // stw 12,-4(3) + BC 0x10, 0, dec_key // bdnz .Ldeckey + + XOR R3, R3, R3 // xor 3,3,3 Clean R3 + +dec_key_abort: + MOVD R3, ret+24(FP) // Put return value into the FP + RET // blr + + +// func encryptBlockAsm(dst, src *byte, enc *uint32) +TEXT ·encryptBlockAsm(SB),NOSPLIT|NOFRAME,$0 + // Load the arguments inside the registers + MOVD dst+0(FP), BLK_OUT + MOVD src+8(FP), BLK_INP + MOVD enc+16(FP), BLK_KEY + + MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) + MOVD $15, BLK_IDX // li 7,15 + + LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 + NEG BLK_OUT, R11 // neg 11,4 + LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 + LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 + VSPLTISB $0x0f, RCON // vspltisb 4,0x0f + LVSR (R11)(R0), KEY // lvsr 3,0,11 + VXOR IN1, RCON, IN1 // vxor 2,2,4 + MOVD $16, BLK_IDX // li 7,16 + VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 + LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 + LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 + SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + + VXOR ZERO, IN0, ZERO // vxor 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + MOVD BLK_ROUNDS, CTR // mtctr 6 + +loop_enc: + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VCIPHER ZERO, IN0, ZERO // vcipher 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + BC 0x10, 0, loop_enc // bdnz .Loop_enc + + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VCIPHERLAST ZERO, IN0, ZERO // vcipherlast 0,0,1 + + VSPLTISB $-1, IN1 // vspltisb 2,-1 + VXOR IN0, IN0, IN0 // vxor 1,1,1 + MOVD $15, BLK_IDX // li 7,15 + VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 + VXOR KEY, RCON, KEY // vxor 3,3,4 + LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 + VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 + VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 + LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 + STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 + VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 + STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 + + RET // blr + + +// func decryptBlockAsm(dst, src *byte, dec *uint32) +TEXT ·decryptBlockAsm(SB),NOSPLIT|NOFRAME,$0 + // Load the arguments inside the registers + MOVD dst+0(FP), BLK_OUT + MOVD src+8(FP), BLK_INP + MOVD dec+16(FP), BLK_KEY + + MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) + MOVD $15, BLK_IDX // li 7,15 + + LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 + NEG BLK_OUT, R11 // neg 11,4 + LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 + LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 + VSPLTISB $0x0f, RCON // vspltisb 4,0x0f + LVSR (R11)(R0), KEY // lvsr 3,0,11 + VXOR IN1, RCON, IN1 // vxor 2,2,4 + MOVD $16, BLK_IDX // li 7,16 + VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 + LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 + LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 + SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + + VXOR ZERO, IN0, ZERO // vxor 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + MOVD BLK_ROUNDS, CTR // mtctr 6 + +loop_dec: + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VNCIPHER ZERO, IN0, ZERO // vncipher 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + BC 0x10, 0, loop_dec // bdnz .Loop_dec + + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VNCIPHERLAST ZERO, IN0, ZERO // vncipherlast 0,0,1 + + VSPLTISB $-1, IN1 // vspltisb 2,-1 + VXOR IN0, IN0, IN0 // vxor 1,1,1 + MOVD $15, BLK_IDX // li 7,15 + VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 + VXOR KEY, RCON, KEY // vxor 3,3,4 + LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 + VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 + VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 + LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 + STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 + VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 + STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 + + RET // blr diff --git a/src/crypto/aes/asm_s390x.s b/src/crypto/aes/asm_s390x.s new file mode 100644 index 0000000..0c60ac2 --- /dev/null +++ b/src/crypto/aes/asm_s390x.s @@ -0,0 +1,191 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func cryptBlocks(c code, key, dst, src *byte, length int) +TEXT ·cryptBlocks(SB),NOSPLIT,$0-40 + MOVD key+8(FP), R1 + MOVD dst+16(FP), R2 + MOVD src+24(FP), R4 + MOVD length+32(FP), R5 + MOVD c+0(FP), R0 +loop: + WORD $0xB92E0024 // cipher message (KM) + BVS loop // branch back if interrupted + XOR R0, R0 + RET + +// func cryptBlocksChain(c code, iv, key, dst, src *byte, length int) +TEXT ·cryptBlocksChain(SB),NOSPLIT,$48-48 + LA params-48(SP), R1 + MOVD iv+8(FP), R8 + MOVD key+16(FP), R9 + MVC $16, 0(R8), 0(R1) // move iv into params + MVC $32, 0(R9), 16(R1) // move key into params + MOVD dst+24(FP), R2 + MOVD src+32(FP), R4 + MOVD length+40(FP), R5 + MOVD c+0(FP), R0 +loop: + WORD $0xB92F0024 // cipher message with chaining (KMC) + BVS loop // branch back if interrupted + XOR R0, R0 + MVC $16, 0(R1), 0(R8) // update iv + RET + +// func xorBytes(dst, a, b []byte) int +TEXT ·xorBytes(SB),NOSPLIT,$0-80 + MOVD dst_base+0(FP), R1 + MOVD a_base+24(FP), R2 + MOVD b_base+48(FP), R3 + MOVD a_len+32(FP), R4 + MOVD b_len+56(FP), R5 + CMPBLE R4, R5, skip + MOVD R5, R4 +skip: + MOVD R4, ret+72(FP) + MOVD $0, R5 + CMPBLT R4, $8, tail +loop: + MOVD 0(R2)(R5*1), R7 + MOVD 0(R3)(R5*1), R8 + XOR R7, R8 + MOVD R8, 0(R1)(R5*1) + LAY 8(R5), R5 + SUB $8, R4 + CMPBGE R4, $8, loop +tail: + CMPBEQ R4, $0, done + MOVB 0(R2)(R5*1), R7 + MOVB 0(R3)(R5*1), R8 + XOR R7, R8 + MOVB R8, 0(R1)(R5*1) + LAY 1(R5), R5 + SUB $1, R4 + BR tail +done: + RET + +// func cryptBlocksGCM(fn code, key, dst, src, buf []byte, cnt *[16]byte) +TEXT ·cryptBlocksGCM(SB),NOSPLIT,$0-112 + MOVD src_len+64(FP), R0 + MOVD buf_base+80(FP), R1 + MOVD cnt+104(FP), R12 + LMG (R12), R2, R3 + + // Check that the src size is less than or equal to the buffer size. + MOVD buf_len+88(FP), R4 + CMP R0, R4 + BGT crash + + // Check that the src size is a multiple of 16-bytes. + MOVD R0, R4 + AND $0xf, R4 + BLT crash // non-zero + + // Check that the src size is less than or equal to the dst size. + MOVD dst_len+40(FP), R4 + CMP R0, R4 + BGT crash + + MOVD R2, R4 + MOVD R2, R6 + MOVD R2, R8 + MOVD R3, R5 + MOVD R3, R7 + MOVD R3, R9 + ADDW $1, R5 + ADDW $2, R7 + ADDW $3, R9 +incr: + CMP R0, $64 + BLT tail + STMG R2, R9, (R1) + ADDW $4, R3 + ADDW $4, R5 + ADDW $4, R7 + ADDW $4, R9 + MOVD $64(R1), R1 + SUB $64, R0 + BR incr +tail: + CMP R0, $0 + BEQ crypt + STMG R2, R3, (R1) + ADDW $1, R3 + MOVD $16(R1), R1 + SUB $16, R0 + BR tail +crypt: + STMG R2, R3, (R12) // update next counter value + MOVD fn+0(FP), R0 // function code (encryption) + MOVD key_base+8(FP), R1 // key + MOVD buf_base+80(FP), R2 // counter values + MOVD dst_base+32(FP), R4 // dst + MOVD src_base+56(FP), R6 // src + MOVD src_len+64(FP), R7 // len +loop: + WORD $0xB92D2046 // cipher message with counter (KMCTR) + BVS loop // branch back if interrupted + RET +crash: + MOVD $0, (R0) + RET + +// func ghash(key *gcmHashKey, hash *[16]byte, data []byte) +TEXT ·ghash(SB),NOSPLIT,$32-40 + MOVD $65, R0 // GHASH function code + MOVD key+0(FP), R2 + LMG (R2), R6, R7 + MOVD hash+8(FP), R8 + LMG (R8), R4, R5 + MOVD $params-32(SP), R1 + STMG R4, R7, (R1) + LMG data+16(FP), R2, R3 // R2=base, R3=len +loop: + WORD $0xB93E0002 // compute intermediate message digest (KIMD) + BVS loop // branch back if interrupted + MVC $16, (R1), (R8) + MOVD $0, R0 + RET + +// func kmaGCM(fn code, key, dst, src, aad []byte, tag *[16]byte, cnt *gcmCount) +TEXT ·kmaGCM(SB),NOSPLIT,$112-120 + MOVD fn+0(FP), R0 + MOVD $params-112(SP), R1 + + // load ptr/len pairs + LMG dst+32(FP), R2, R3 // R2=base R3=len + LMG src+56(FP), R4, R5 // R4=base R5=len + LMG aad+80(FP), R6, R7 // R6=base R7=len + + // setup parameters + MOVD cnt+112(FP), R8 + XC $12, (R1), (R1) // reserved + MVC $4, 12(R8), 12(R1) // set chain value + MVC $16, (R8), 64(R1) // set initial counter value + XC $32, 16(R1), 16(R1) // set hash subkey and tag + SLD $3, R7, R12 + MOVD R12, 48(R1) // set total AAD length + SLD $3, R5, R12 + MOVD R12, 56(R1) // set total plaintext/ciphertext length + + LMG key+8(FP), R8, R9 // R8=base R9=len + MVC $16, (R8), 80(R1) // set key + CMPBEQ R9, $16, kma + MVC $8, 16(R8), 96(R1) + CMPBEQ R9, $24, kma + MVC $8, 24(R8), 104(R1) + +kma: + WORD $0xb9296024 // kma %r6,%r2,%r4 + BVS kma + + MOVD tag+104(FP), R2 + MVC $16, 16(R1), 0(R2) // copy tag to output + MOVD cnt+112(FP), R8 + MVC $4, 12(R1), 12(R8) // update counter value + + RET diff --git a/src/crypto/aes/block.go b/src/crypto/aes/block.go new file mode 100644 index 0000000..53308ae --- /dev/null +++ b/src/crypto/aes/block.go @@ -0,0 +1,182 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This Go implementation is derived in part from the reference +// ANSI C implementation, which carries the following notice: +// +// rijndael-alg-fst.c +// +// @version 3.0 (December 2000) +// +// Optimised ANSI C code for the Rijndael cipher (now AES) +// +// @author Vincent Rijmen +// @author Antoon Bosselaers +// @author Paulo Barreto +// +// This code is hereby placed in the public domain. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS +// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// See FIPS 197 for specification, and see Daemen and Rijmen's Rijndael submission +// for implementation details. +// https://csrc.nist.gov/csrc/media/publications/fips/197/final/documents/fips-197.pdf +// https://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf + +package aes + +import ( + "encoding/binary" +) + +// Encrypt one block from src into dst, using the expanded key xk. +func encryptBlockGo(xk []uint32, dst, src []byte) { + _ = src[15] // early bounds check + s0 := binary.BigEndian.Uint32(src[0:4]) + s1 := binary.BigEndian.Uint32(src[4:8]) + s2 := binary.BigEndian.Uint32(src[8:12]) + s3 := binary.BigEndian.Uint32(src[12:16]) + + // First round just XORs input with key. + s0 ^= xk[0] + s1 ^= xk[1] + s2 ^= xk[2] + s3 ^= xk[3] + + // Middle rounds shuffle using tables. + // Number of rounds is set by length of expanded key. + nr := len(xk)/4 - 2 // - 2: one above, one more below + k := 4 + var t0, t1, t2, t3 uint32 + for r := 0; r < nr; r++ { + t0 = xk[k+0] ^ te0[uint8(s0>>24)] ^ te1[uint8(s1>>16)] ^ te2[uint8(s2>>8)] ^ te3[uint8(s3)] + t1 = xk[k+1] ^ te0[uint8(s1>>24)] ^ te1[uint8(s2>>16)] ^ te2[uint8(s3>>8)] ^ te3[uint8(s0)] + t2 = xk[k+2] ^ te0[uint8(s2>>24)] ^ te1[uint8(s3>>16)] ^ te2[uint8(s0>>8)] ^ te3[uint8(s1)] + t3 = xk[k+3] ^ te0[uint8(s3>>24)] ^ te1[uint8(s0>>16)] ^ te2[uint8(s1>>8)] ^ te3[uint8(s2)] + k += 4 + s0, s1, s2, s3 = t0, t1, t2, t3 + } + + // Last round uses s-box directly and XORs to produce output. + s0 = uint32(sbox0[t0>>24])<<24 | uint32(sbox0[t1>>16&0xff])<<16 | uint32(sbox0[t2>>8&0xff])<<8 | uint32(sbox0[t3&0xff]) + s1 = uint32(sbox0[t1>>24])<<24 | uint32(sbox0[t2>>16&0xff])<<16 | uint32(sbox0[t3>>8&0xff])<<8 | uint32(sbox0[t0&0xff]) + s2 = uint32(sbox0[t2>>24])<<24 | uint32(sbox0[t3>>16&0xff])<<16 | uint32(sbox0[t0>>8&0xff])<<8 | uint32(sbox0[t1&0xff]) + s3 = uint32(sbox0[t3>>24])<<24 | uint32(sbox0[t0>>16&0xff])<<16 | uint32(sbox0[t1>>8&0xff])<<8 | uint32(sbox0[t2&0xff]) + + s0 ^= xk[k+0] + s1 ^= xk[k+1] + s2 ^= xk[k+2] + s3 ^= xk[k+3] + + _ = dst[15] // early bounds check + binary.BigEndian.PutUint32(dst[0:4], s0) + binary.BigEndian.PutUint32(dst[4:8], s1) + binary.BigEndian.PutUint32(dst[8:12], s2) + binary.BigEndian.PutUint32(dst[12:16], s3) +} + +// Decrypt one block from src into dst, using the expanded key xk. +func decryptBlockGo(xk []uint32, dst, src []byte) { + _ = src[15] // early bounds check + s0 := binary.BigEndian.Uint32(src[0:4]) + s1 := binary.BigEndian.Uint32(src[4:8]) + s2 := binary.BigEndian.Uint32(src[8:12]) + s3 := binary.BigEndian.Uint32(src[12:16]) + + // First round just XORs input with key. + s0 ^= xk[0] + s1 ^= xk[1] + s2 ^= xk[2] + s3 ^= xk[3] + + // Middle rounds shuffle using tables. + // Number of rounds is set by length of expanded key. + nr := len(xk)/4 - 2 // - 2: one above, one more below + k := 4 + var t0, t1, t2, t3 uint32 + for r := 0; r < nr; r++ { + t0 = xk[k+0] ^ td0[uint8(s0>>24)] ^ td1[uint8(s3>>16)] ^ td2[uint8(s2>>8)] ^ td3[uint8(s1)] + t1 = xk[k+1] ^ td0[uint8(s1>>24)] ^ td1[uint8(s0>>16)] ^ td2[uint8(s3>>8)] ^ td3[uint8(s2)] + t2 = xk[k+2] ^ td0[uint8(s2>>24)] ^ td1[uint8(s1>>16)] ^ td2[uint8(s0>>8)] ^ td3[uint8(s3)] + t3 = xk[k+3] ^ td0[uint8(s3>>24)] ^ td1[uint8(s2>>16)] ^ td2[uint8(s1>>8)] ^ td3[uint8(s0)] + k += 4 + s0, s1, s2, s3 = t0, t1, t2, t3 + } + + // Last round uses s-box directly and XORs to produce output. + s0 = uint32(sbox1[t0>>24])<<24 | uint32(sbox1[t3>>16&0xff])<<16 | uint32(sbox1[t2>>8&0xff])<<8 | uint32(sbox1[t1&0xff]) + s1 = uint32(sbox1[t1>>24])<<24 | uint32(sbox1[t0>>16&0xff])<<16 | uint32(sbox1[t3>>8&0xff])<<8 | uint32(sbox1[t2&0xff]) + s2 = uint32(sbox1[t2>>24])<<24 | uint32(sbox1[t1>>16&0xff])<<16 | uint32(sbox1[t0>>8&0xff])<<8 | uint32(sbox1[t3&0xff]) + s3 = uint32(sbox1[t3>>24])<<24 | uint32(sbox1[t2>>16&0xff])<<16 | uint32(sbox1[t1>>8&0xff])<<8 | uint32(sbox1[t0&0xff]) + + s0 ^= xk[k+0] + s1 ^= xk[k+1] + s2 ^= xk[k+2] + s3 ^= xk[k+3] + + _ = dst[15] // early bounds check + binary.BigEndian.PutUint32(dst[0:4], s0) + binary.BigEndian.PutUint32(dst[4:8], s1) + binary.BigEndian.PutUint32(dst[8:12], s2) + binary.BigEndian.PutUint32(dst[12:16], s3) +} + +// Apply sbox0 to each byte in w. +func subw(w uint32) uint32 { + return uint32(sbox0[w>>24])<<24 | + uint32(sbox0[w>>16&0xff])<<16 | + uint32(sbox0[w>>8&0xff])<<8 | + uint32(sbox0[w&0xff]) +} + +// Rotate +func rotw(w uint32) uint32 { return w<<8 | w>>24 } + +// Key expansion algorithm. See FIPS-197, Figure 11. +// Their rcon[i] is our powx[i-1] << 24. +func expandKeyGo(key []byte, enc, dec []uint32) { + // Encryption key setup. + var i int + nk := len(key) / 4 + for i = 0; i < nk; i++ { + enc[i] = binary.BigEndian.Uint32(key[4*i:]) + } + for ; i < len(enc); i++ { + t := enc[i-1] + if i%nk == 0 { + t = subw(rotw(t)) ^ (uint32(powx[i/nk-1]) << 24) + } else if nk > 6 && i%nk == 4 { + t = subw(t) + } + enc[i] = enc[i-nk] ^ t + } + + // Derive decryption key from encryption key. + // Reverse the 4-word round key sets from enc to produce dec. + // All sets but the first and last get the MixColumn transform applied. + if dec == nil { + return + } + n := len(enc) + for i := 0; i < n; i += 4 { + ei := n - i - 4 + for j := 0; j < 4; j++ { + x := enc[ei+j] + if i > 0 && i+4 < n { + x = td0[sbox0[x>>24]] ^ td1[sbox0[x>>16&0xff]] ^ td2[sbox0[x>>8&0xff]] ^ td3[sbox0[x&0xff]] + } + dec[i+j] = x + } + } +} diff --git a/src/crypto/aes/cbc_s390x.go b/src/crypto/aes/cbc_s390x.go new file mode 100644 index 0000000..28a6b1d --- /dev/null +++ b/src/crypto/aes/cbc_s390x.go @@ -0,0 +1,65 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "crypto/cipher" + "crypto/internal/subtle" +) + +// Assert that aesCipherAsm implements the cbcEncAble and cbcDecAble interfaces. +var _ cbcEncAble = (*aesCipherAsm)(nil) +var _ cbcDecAble = (*aesCipherAsm)(nil) + +type cbc struct { + b *aesCipherAsm + c code + iv [BlockSize]byte +} + +func (b *aesCipherAsm) NewCBCEncrypter(iv []byte) cipher.BlockMode { + var c cbc + c.b = b + c.c = b.function + copy(c.iv[:], iv) + return &c +} + +func (b *aesCipherAsm) NewCBCDecrypter(iv []byte) cipher.BlockMode { + var c cbc + c.b = b + c.c = b.function + 128 // decrypt function code is encrypt + 128 + copy(c.iv[:], iv) + return &c +} + +func (x *cbc) BlockSize() int { return BlockSize } + +// cryptBlocksChain invokes the cipher message with chaining (KMC) instruction +// with the given function code. The length must be a multiple of BlockSize (16). +//go:noescape +func cryptBlocksChain(c code, iv, key, dst, src *byte, length int) + +func (x *cbc) CryptBlocks(dst, src []byte) { + if len(src)%BlockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + if len(src) > 0 { + cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src)) + } +} + +func (x *cbc) SetIV(iv []byte) { + if len(iv) != BlockSize { + panic("cipher: incorrect length IV") + } + copy(x.iv[:], iv) +} diff --git a/src/crypto/aes/cipher.go b/src/crypto/aes/cipher.go new file mode 100644 index 0000000..bb93fbb --- /dev/null +++ b/src/crypto/aes/cipher.go @@ -0,0 +1,78 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "crypto/cipher" + "crypto/internal/subtle" + "strconv" +) + +// The AES block size in bytes. +const BlockSize = 16 + +// A cipher is an instance of AES encryption using a particular key. +type aesCipher struct { + enc []uint32 + dec []uint32 +} + +type KeySizeError int + +func (k KeySizeError) Error() string { + return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) +} + +// NewCipher creates and returns a new cipher.Block. +// The key argument should be the AES key, +// either 16, 24, or 32 bytes to select +// AES-128, AES-192, or AES-256. +func NewCipher(key []byte) (cipher.Block, error) { + k := len(key) + switch k { + default: + return nil, KeySizeError(k) + case 16, 24, 32: + break + } + return newCipher(key) +} + +// newCipherGeneric creates and returns a new cipher.Block +// implemented in pure Go. +func newCipherGeneric(key []byte) (cipher.Block, error) { + n := len(key) + 28 + c := aesCipher{make([]uint32, n), make([]uint32, n)} + expandKeyGo(key, c.enc, c.dec) + return &c, nil +} + +func (c *aesCipher) BlockSize() int { return BlockSize } + +func (c *aesCipher) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + encryptBlockGo(c.enc, dst, src) +} + +func (c *aesCipher) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + decryptBlockGo(c.dec, dst, src) +} diff --git a/src/crypto/aes/cipher_asm.go b/src/crypto/aes/cipher_asm.go new file mode 100644 index 0000000..4251805 --- /dev/null +++ b/src/crypto/aes/cipher_asm.go @@ -0,0 +1,100 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 || arm64 +// +build amd64 arm64 + +package aes + +import ( + "crypto/cipher" + "crypto/internal/subtle" + "internal/cpu" +) + +// defined in asm_*.s + +//go:noescape +func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) + +//go:noescape +func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) + +//go:noescape +func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) + +type aesCipherAsm struct { + aesCipher +} + +var supportsAES = cpu.X86.HasAES || cpu.ARM64.HasAES +var supportsGFMUL = cpu.X86.HasPCLMULQDQ || cpu.ARM64.HasPMULL + +func newCipher(key []byte) (cipher.Block, error) { + if !supportsAES { + return newCipherGeneric(key) + } + n := len(key) + 28 + c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}} + var rounds int + switch len(key) { + case 128 / 8: + rounds = 10 + case 192 / 8: + rounds = 12 + case 256 / 8: + rounds = 14 + } + + expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0]) + if supportsAES && supportsGFMUL { + return &aesCipherGCM{c}, nil + } + return &c, nil +} + +func (c *aesCipherAsm) BlockSize() int { return BlockSize } + +func (c *aesCipherAsm) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0]) +} + +func (c *aesCipherAsm) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0]) +} + +// expandKey is used by BenchmarkExpand to ensure that the asm implementation +// of key expansion is used for the benchmark when it is available. +func expandKey(key []byte, enc, dec []uint32) { + if supportsAES { + rounds := 10 // rounds needed for AES128 + switch len(key) { + case 192 / 8: + rounds = 12 + case 256 / 8: + rounds = 14 + } + expandKeyAsm(rounds, &key[0], &enc[0], &dec[0]) + } else { + expandKeyGo(key, enc, dec) + } +} diff --git a/src/crypto/aes/cipher_generic.go b/src/crypto/aes/cipher_generic.go new file mode 100644 index 0000000..22ce3be --- /dev/null +++ b/src/crypto/aes/cipher_generic.go @@ -0,0 +1,27 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 && !s390x && !ppc64le && !arm64 +// +build !amd64,!s390x,!ppc64le,!arm64 + +package aes + +import ( + "crypto/cipher" +) + +// newCipher calls the newCipherGeneric function +// directly. Platforms with hardware accelerated +// implementations of AES should implement their +// own version of newCipher (which may then call +// newCipherGeneric if needed). +func newCipher(key []byte) (cipher.Block, error) { + return newCipherGeneric(key) +} + +// expandKey is used by BenchmarkExpand and should +// call an assembly implementation if one is available. +func expandKey(key []byte, enc, dec []uint32) { + expandKeyGo(key, enc, dec) +} diff --git a/src/crypto/aes/cipher_ppc64le.go b/src/crypto/aes/cipher_ppc64le.go new file mode 100644 index 0000000..b788ea7 --- /dev/null +++ b/src/crypto/aes/cipher_ppc64le.go @@ -0,0 +1,82 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "crypto/cipher" + "crypto/internal/subtle" +) + +// defined in asm_ppc64le.s + +//go:noescape +func setEncryptKeyAsm(key *byte, keylen int, enc *uint32) int + +//go:noescape +func setDecryptKeyAsm(key *byte, keylen int, dec *uint32) int + +//go:noescape +func doEncryptKeyAsm(key *byte, keylen int, dec *uint32) int + +//go:noescape +func encryptBlockAsm(dst, src *byte, enc *uint32) + +//go:noescape +func decryptBlockAsm(dst, src *byte, dec *uint32) + +type aesCipherAsm struct { + aesCipher +} + +func newCipher(key []byte) (cipher.Block, error) { + n := 64 // size is fixed for all and round value is stored inside it too + c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}} + k := len(key) + + ret := 0 + ret += setEncryptKeyAsm(&key[0], k*8, &c.enc[0]) + ret += setDecryptKeyAsm(&key[0], k*8, &c.dec[0]) + + if ret > 0 { + return nil, KeySizeError(k) + } + + return &c, nil +} + +func (c *aesCipherAsm) BlockSize() int { return BlockSize } + +func (c *aesCipherAsm) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + encryptBlockAsm(&dst[0], &src[0], &c.enc[0]) +} + +func (c *aesCipherAsm) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + decryptBlockAsm(&dst[0], &src[0], &c.dec[0]) +} + +// expandKey is used by BenchmarkExpand to ensure that the asm implementation +// of key expansion is used for the benchmark when it is available. +func expandKey(key []byte, enc, dec []uint32) { + setEncryptKeyAsm(&key[0], len(key)*8, &enc[0]) + setDecryptKeyAsm(&key[0], len(key)*8, &dec[0]) +} diff --git a/src/crypto/aes/cipher_s390x.go b/src/crypto/aes/cipher_s390x.go new file mode 100644 index 0000000..65b6b2f --- /dev/null +++ b/src/crypto/aes/cipher_s390x.go @@ -0,0 +1,95 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "crypto/cipher" + "crypto/internal/subtle" + "internal/cpu" +) + +type code int + +// Function codes for the cipher message family of instructions. +const ( + aes128 code = 18 + aes192 = 19 + aes256 = 20 +) + +type aesCipherAsm struct { + function code // code for cipher message instruction + key []byte // key (128, 192 or 256 bits) + storage [32]byte // array backing key slice +} + +// cryptBlocks invokes the cipher message (KM) instruction with +// the given function code. This is equivalent to AES in ECB +// mode. The length must be a multiple of BlockSize (16). +//go:noescape +func cryptBlocks(c code, key, dst, src *byte, length int) + +func newCipher(key []byte) (cipher.Block, error) { + // The aesCipherAsm type implements the cbcEncAble, cbcDecAble, + // ctrAble and gcmAble interfaces. We therefore need to check + // for all the features required to implement these modes. + // Keep in sync with crypto/tls/common.go. + if !(cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)) { + return newCipherGeneric(key) + } + + var function code + switch len(key) { + case 128 / 8: + function = aes128 + case 192 / 8: + function = aes192 + case 256 / 8: + function = aes256 + default: + return nil, KeySizeError(len(key)) + } + + var c aesCipherAsm + c.function = function + c.key = c.storage[:len(key)] + copy(c.key, key) + return &c, nil +} + +func (c *aesCipherAsm) BlockSize() int { return BlockSize } + +func (c *aesCipherAsm) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize) +} + +func (c *aesCipherAsm) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } + // The decrypt function code is equal to the function code + 128. + cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize) +} + +// expandKey is used by BenchmarkExpand. cipher message (KM) does not need key +// expansion so there is no assembly equivalent. +func expandKey(key []byte, enc, dec []uint32) { + expandKeyGo(key, enc, dec) +} diff --git a/src/crypto/aes/const.go b/src/crypto/aes/const.go new file mode 100644 index 0000000..4eca4b9 --- /dev/null +++ b/src/crypto/aes/const.go @@ -0,0 +1,365 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package aes implements AES encryption (formerly Rijndael), as defined in +// U.S. Federal Information Processing Standards Publication 197. +// +// The AES operations in this package are not implemented using constant-time algorithms. +// An exception is when running on systems with enabled hardware support for AES +// that makes these operations constant-time. Examples include amd64 systems using AES-NI +// extensions and s390x systems using Message-Security-Assist extensions. +// On such systems, when the result of NewCipher is passed to cipher.NewGCM, +// the GHASH operation used by GCM is also constant-time. +package aes + +// This file contains AES constants - 8720 bytes of initialized data. + +// https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + +// AES is based on the mathematical behavior of binary polynomials +// (polynomials over GF(2)) modulo the irreducible polynomial x⁸ + x⁴ + x³ + x + 1. +// Addition of these binary polynomials corresponds to binary xor. +// Reducing mod poly corresponds to binary xor with poly every +// time a 0x100 bit appears. +const poly = 1<<8 | 1<<4 | 1<<3 | 1<<1 | 1<<0 // x⁸ + x⁴ + x³ + x + 1 + +// Powers of x mod poly in GF(2). +var powx = [16]byte{ + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, +} + +// FIPS-197 Figure 7. S-box substitution values in hexadecimal format. +var sbox0 = [256]byte{ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, +} + +// FIPS-197 Figure 14. Inverse S-box substitution values in hexadecimal format. +var sbox1 = [256]byte{ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, +} + +// Lookup tables for encryption. +// These can be recomputed by adapting the tests in aes_test.go. + +var te0 = [256]uint32{ + 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, + 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, + 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, + 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, + 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, + 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, + 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, + 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, + 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, + 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, + 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, + 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, + 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, + 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, + 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, + 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, + 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, + 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, + 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, + 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, + 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, + 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, + 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, + 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, + 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, + 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, + 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, + 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, + 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, + 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, + 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, + 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, +} +var te1 = [256]uint32{ + 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, + 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, + 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, + 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, + 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, + 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, + 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, + 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, + 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, + 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, + 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, + 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, + 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, + 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, + 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, + 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, + 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, + 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, + 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, + 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, + 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, + 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, + 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, + 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, + 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, + 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, + 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, + 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, + 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, + 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, + 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, + 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, +} +var te2 = [256]uint32{ + 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, + 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, + 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, + 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, + 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, + 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, + 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, + 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, + 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, + 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, + 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, + 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, + 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, + 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, + 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, + 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, + 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, + 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, + 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, + 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, + 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, + 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, + 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, + 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, + 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, + 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, + 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, + 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, + 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, + 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, + 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, + 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, +} +var te3 = [256]uint32{ + 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, + 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, + 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, + 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, + 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, + 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, + 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, + 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, + 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, + 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, + 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, + 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, + 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, + 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, + 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, + 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, + 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, + 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, + 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, + 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, + 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, + 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, + 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, + 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, + 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, + 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, + 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, + 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, + 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, + 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, + 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, + 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, +} + +// Lookup tables for decryption. +// These can be recomputed by adapting the tests in aes_test.go. + +var td0 = [256]uint32{ + 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, + 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, + 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, + 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, + 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, + 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, + 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, + 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, + 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, + 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, + 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, + 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, + 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, + 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, + 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, + 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, + 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, + 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, + 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, + 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, + 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, + 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, + 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, + 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, + 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, + 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, + 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, + 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, + 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, + 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, + 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, + 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, +} +var td1 = [256]uint32{ + 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, + 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, + 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, + 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, + 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, + 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, + 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, + 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, + 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, + 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, + 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, + 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, + 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, + 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, + 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, + 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, + 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, + 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, + 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, + 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, + 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, + 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, + 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, + 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, + 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, + 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, + 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, + 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, + 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, + 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, + 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, + 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, +} +var td2 = [256]uint32{ + 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, + 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, + 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, + 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, + 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, + 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, + 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, + 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, + 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, + 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, + 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, + 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, + 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, + 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, + 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, + 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, + 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, + 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, + 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, + 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, + 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, + 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, + 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, + 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, + 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, + 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, + 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, + 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, + 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, + 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, + 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, + 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, +} +var td3 = [256]uint32{ + 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, + 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, + 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, + 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, + 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, + 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, + 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, + 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, + 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, + 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, + 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, + 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, + 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, + 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, + 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, + 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, + 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, + 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, + 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, + 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, + 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, + 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, + 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, + 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, + 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, + 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, + 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, + 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, + 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, + 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, + 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, + 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0, +} diff --git a/src/crypto/aes/ctr_s390x.go b/src/crypto/aes/ctr_s390x.go new file mode 100644 index 0000000..bfa8cbb --- /dev/null +++ b/src/crypto/aes/ctr_s390x.go @@ -0,0 +1,83 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "crypto/cipher" + "crypto/internal/subtle" + "encoding/binary" +) + +// Assert that aesCipherAsm implements the ctrAble interface. +var _ ctrAble = (*aesCipherAsm)(nil) + +// xorBytes xors the contents of a and b and places the resulting values into +// dst. If a and b are not the same length then the number of bytes processed +// will be equal to the length of shorter of the two. Returns the number +// of bytes processed. +//go:noescape +func xorBytes(dst, a, b []byte) int + +// streamBufferSize is the number of bytes of encrypted counter values to cache. +const streamBufferSize = 32 * BlockSize + +type aesctr struct { + block *aesCipherAsm // block cipher + ctr [2]uint64 // next value of the counter (big endian) + buffer []byte // buffer for the encrypted counter values + storage [streamBufferSize]byte // array backing buffer slice +} + +// NewCTR returns a Stream which encrypts/decrypts using the AES block +// cipher in counter mode. The length of iv must be the same as BlockSize. +func (c *aesCipherAsm) NewCTR(iv []byte) cipher.Stream { + if len(iv) != BlockSize { + panic("cipher.NewCTR: IV length must equal block size") + } + var ac aesctr + ac.block = c + ac.ctr[0] = binary.BigEndian.Uint64(iv[0:]) // high bits + ac.ctr[1] = binary.BigEndian.Uint64(iv[8:]) // low bits + ac.buffer = ac.storage[:0] + return &ac +} + +func (c *aesctr) refill() { + // Fill up the buffer with an incrementing count. + c.buffer = c.storage[:streamBufferSize] + c0, c1 := c.ctr[0], c.ctr[1] + for i := 0; i < streamBufferSize; i += 16 { + binary.BigEndian.PutUint64(c.buffer[i+0:], c0) + binary.BigEndian.PutUint64(c.buffer[i+8:], c1) + + // Increment in big endian: c0 is high, c1 is low. + c1++ + if c1 == 0 { + // add carry + c0++ + } + } + c.ctr[0], c.ctr[1] = c0, c1 + // Encrypt the buffer using AES in ECB mode. + cryptBlocks(c.block.function, &c.block.key[0], &c.buffer[0], &c.buffer[0], streamBufferSize) +} + +func (c *aesctr) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + for len(src) > 0 { + if len(c.buffer) == 0 { + c.refill() + } + n := xorBytes(dst, src, c.buffer) + c.buffer = c.buffer[n:] + src = src[n:] + dst = dst[n:] + } +} diff --git a/src/crypto/aes/gcm_amd64.s b/src/crypto/aes/gcm_amd64.s new file mode 100644 index 0000000..e6eedf3 --- /dev/null +++ b/src/crypto/aes/gcm_amd64.s @@ -0,0 +1,1286 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This is an optimized implementation of AES-GCM using AES-NI and CLMUL-NI +// The implementation uses some optimization as described in: +// [1] Gueron, S., Kounavis, M.E.: Intel® Carry-Less Multiplication +// Instruction and its Usage for Computing the GCM Mode rev. 2.02 +// [2] Gueron, S., Krasnov, V.: Speeding up Counter Mode in Software and +// Hardware + +#include "textflag.h" + +#define B0 X0 +#define B1 X1 +#define B2 X2 +#define B3 X3 +#define B4 X4 +#define B5 X5 +#define B6 X6 +#define B7 X7 + +#define ACC0 X8 +#define ACC1 X9 +#define ACCM X10 + +#define T0 X11 +#define T1 X12 +#define T2 X13 +#define POLY X14 +#define BSWAP X15 + +DATA bswapMask<>+0x00(SB)/8, $0x08090a0b0c0d0e0f +DATA bswapMask<>+0x08(SB)/8, $0x0001020304050607 + +DATA gcmPoly<>+0x00(SB)/8, $0x0000000000000001 +DATA gcmPoly<>+0x08(SB)/8, $0xc200000000000000 + +DATA andMask<>+0x00(SB)/8, $0x00000000000000ff +DATA andMask<>+0x08(SB)/8, $0x0000000000000000 +DATA andMask<>+0x10(SB)/8, $0x000000000000ffff +DATA andMask<>+0x18(SB)/8, $0x0000000000000000 +DATA andMask<>+0x20(SB)/8, $0x0000000000ffffff +DATA andMask<>+0x28(SB)/8, $0x0000000000000000 +DATA andMask<>+0x30(SB)/8, $0x00000000ffffffff +DATA andMask<>+0x38(SB)/8, $0x0000000000000000 +DATA andMask<>+0x40(SB)/8, $0x000000ffffffffff +DATA andMask<>+0x48(SB)/8, $0x0000000000000000 +DATA andMask<>+0x50(SB)/8, $0x0000ffffffffffff +DATA andMask<>+0x58(SB)/8, $0x0000000000000000 +DATA andMask<>+0x60(SB)/8, $0x00ffffffffffffff +DATA andMask<>+0x68(SB)/8, $0x0000000000000000 +DATA andMask<>+0x70(SB)/8, $0xffffffffffffffff +DATA andMask<>+0x78(SB)/8, $0x0000000000000000 +DATA andMask<>+0x80(SB)/8, $0xffffffffffffffff +DATA andMask<>+0x88(SB)/8, $0x00000000000000ff +DATA andMask<>+0x90(SB)/8, $0xffffffffffffffff +DATA andMask<>+0x98(SB)/8, $0x000000000000ffff +DATA andMask<>+0xa0(SB)/8, $0xffffffffffffffff +DATA andMask<>+0xa8(SB)/8, $0x0000000000ffffff +DATA andMask<>+0xb0(SB)/8, $0xffffffffffffffff +DATA andMask<>+0xb8(SB)/8, $0x00000000ffffffff +DATA andMask<>+0xc0(SB)/8, $0xffffffffffffffff +DATA andMask<>+0xc8(SB)/8, $0x000000ffffffffff +DATA andMask<>+0xd0(SB)/8, $0xffffffffffffffff +DATA andMask<>+0xd8(SB)/8, $0x0000ffffffffffff +DATA andMask<>+0xe0(SB)/8, $0xffffffffffffffff +DATA andMask<>+0xe8(SB)/8, $0x00ffffffffffffff + +GLOBL bswapMask<>(SB), (NOPTR+RODATA), $16 +GLOBL gcmPoly<>(SB), (NOPTR+RODATA), $16 +GLOBL andMask<>(SB), (NOPTR+RODATA), $240 + +// func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64) +TEXT ·gcmAesFinish(SB),NOSPLIT,$0 +#define pTbl DI +#define tMsk SI +#define tPtr DX +#define plen AX +#define dlen CX + + MOVQ productTable+0(FP), pTbl + MOVQ tagMask+8(FP), tMsk + MOVQ T+16(FP), tPtr + MOVQ pLen+24(FP), plen + MOVQ dLen+32(FP), dlen + + MOVOU (tPtr), ACC0 + MOVOU (tMsk), T2 + + MOVOU bswapMask<>(SB), BSWAP + MOVOU gcmPoly<>(SB), POLY + + SHLQ $3, plen + SHLQ $3, dlen + + MOVQ plen, B0 + PINSRQ $1, dlen, B0 + + PXOR ACC0, B0 + + MOVOU (16*14)(pTbl), ACC0 + MOVOU (16*15)(pTbl), ACCM + MOVOU ACC0, ACC1 + + PCLMULQDQ $0x00, B0, ACC0 + PCLMULQDQ $0x11, B0, ACC1 + PSHUFD $78, B0, T0 + PXOR B0, T0 + PCLMULQDQ $0x00, T0, ACCM + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + MOVOU POLY, T0 + PCLMULQDQ $0x01, ACC0, T0 + PSHUFD $78, ACC0, ACC0 + PXOR T0, ACC0 + + MOVOU POLY, T0 + PCLMULQDQ $0x01, ACC0, T0 + PSHUFD $78, ACC0, ACC0 + PXOR T0, ACC0 + + PXOR ACC1, ACC0 + + PSHUFB BSWAP, ACC0 + PXOR T2, ACC0 + MOVOU ACC0, (tPtr) + + RET +#undef pTbl +#undef tMsk +#undef tPtr +#undef plen +#undef dlen + +// func gcmAesInit(productTable *[256]byte, ks []uint32) +TEXT ·gcmAesInit(SB),NOSPLIT,$0 +#define dst DI +#define KS SI +#define NR DX + + MOVQ productTable+0(FP), dst + MOVQ ks_base+8(FP), KS + MOVQ ks_len+16(FP), NR + + SHRQ $2, NR + DECQ NR + + MOVOU bswapMask<>(SB), BSWAP + MOVOU gcmPoly<>(SB), POLY + + // Encrypt block 0, with the AES key to generate the hash key H + MOVOU (16*0)(KS), B0 + MOVOU (16*1)(KS), T0 + AESENC T0, B0 + MOVOU (16*2)(KS), T0 + AESENC T0, B0 + MOVOU (16*3)(KS), T0 + AESENC T0, B0 + MOVOU (16*4)(KS), T0 + AESENC T0, B0 + MOVOU (16*5)(KS), T0 + AESENC T0, B0 + MOVOU (16*6)(KS), T0 + AESENC T0, B0 + MOVOU (16*7)(KS), T0 + AESENC T0, B0 + MOVOU (16*8)(KS), T0 + AESENC T0, B0 + MOVOU (16*9)(KS), T0 + AESENC T0, B0 + MOVOU (16*10)(KS), T0 + CMPQ NR, $12 + JB initEncLast + AESENC T0, B0 + MOVOU (16*11)(KS), T0 + AESENC T0, B0 + MOVOU (16*12)(KS), T0 + JE initEncLast + AESENC T0, B0 + MOVOU (16*13)(KS), T0 + AESENC T0, B0 + MOVOU (16*14)(KS), T0 +initEncLast: + AESENCLAST T0, B0 + + PSHUFB BSWAP, B0 + // H * 2 + PSHUFD $0xff, B0, T0 + MOVOU B0, T1 + PSRAL $31, T0 + PAND POLY, T0 + PSRLL $31, T1 + PSLLDQ $4, T1 + PSLLL $1, B0 + PXOR T0, B0 + PXOR T1, B0 + // Karatsuba pre-computations + MOVOU B0, (16*14)(dst) + PSHUFD $78, B0, B1 + PXOR B0, B1 + MOVOU B1, (16*15)(dst) + + MOVOU B0, B2 + MOVOU B1, B3 + // Now prepare powers of H and pre-computations for them + MOVQ $7, AX + +initLoop: + MOVOU B2, T0 + MOVOU B2, T1 + MOVOU B3, T2 + PCLMULQDQ $0x00, B0, T0 + PCLMULQDQ $0x11, B0, T1 + PCLMULQDQ $0x00, B1, T2 + + PXOR T0, T2 + PXOR T1, T2 + MOVOU T2, B4 + PSLLDQ $8, B4 + PSRLDQ $8, T2 + PXOR B4, T0 + PXOR T2, T1 + + MOVOU POLY, B2 + PCLMULQDQ $0x01, T0, B2 + PSHUFD $78, T0, T0 + PXOR B2, T0 + MOVOU POLY, B2 + PCLMULQDQ $0x01, T0, B2 + PSHUFD $78, T0, T0 + PXOR T0, B2 + PXOR T1, B2 + + MOVOU B2, (16*12)(dst) + PSHUFD $78, B2, B3 + PXOR B2, B3 + MOVOU B3, (16*13)(dst) + + DECQ AX + LEAQ (-16*2)(dst), dst + JNE initLoop + + RET +#undef NR +#undef KS +#undef dst + +// func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte) +TEXT ·gcmAesData(SB),NOSPLIT,$0 +#define pTbl DI +#define aut SI +#define tPtr CX +#define autLen DX + +#define reduceRound(a) MOVOU POLY, T0; PCLMULQDQ $0x01, a, T0; PSHUFD $78, a, a; PXOR T0, a +#define mulRoundAAD(X ,i) \ + MOVOU (16*(i*2))(pTbl), T1;\ + MOVOU T1, T2;\ + PCLMULQDQ $0x00, X, T1;\ + PXOR T1, ACC0;\ + PCLMULQDQ $0x11, X, T2;\ + PXOR T2, ACC1;\ + PSHUFD $78, X, T1;\ + PXOR T1, X;\ + MOVOU (16*(i*2+1))(pTbl), T1;\ + PCLMULQDQ $0x00, X, T1;\ + PXOR T1, ACCM + + MOVQ productTable+0(FP), pTbl + MOVQ data_base+8(FP), aut + MOVQ data_len+16(FP), autLen + MOVQ T+32(FP), tPtr + + PXOR ACC0, ACC0 + MOVOU bswapMask<>(SB), BSWAP + MOVOU gcmPoly<>(SB), POLY + + TESTQ autLen, autLen + JEQ dataBail + + CMPQ autLen, $13 // optimize the TLS case + JE dataTLS + CMPQ autLen, $128 + JB startSinglesLoop + JMP dataOctaLoop + +dataTLS: + MOVOU (16*14)(pTbl), T1 + MOVOU (16*15)(pTbl), T2 + PXOR B0, B0 + MOVQ (aut), B0 + PINSRD $2, 8(aut), B0 + PINSRB $12, 12(aut), B0 + XORQ autLen, autLen + JMP dataMul + +dataOctaLoop: + CMPQ autLen, $128 + JB startSinglesLoop + SUBQ $128, autLen + + MOVOU (16*0)(aut), X0 + MOVOU (16*1)(aut), X1 + MOVOU (16*2)(aut), X2 + MOVOU (16*3)(aut), X3 + MOVOU (16*4)(aut), X4 + MOVOU (16*5)(aut), X5 + MOVOU (16*6)(aut), X6 + MOVOU (16*7)(aut), X7 + LEAQ (16*8)(aut), aut + PSHUFB BSWAP, X0 + PSHUFB BSWAP, X1 + PSHUFB BSWAP, X2 + PSHUFB BSWAP, X3 + PSHUFB BSWAP, X4 + PSHUFB BSWAP, X5 + PSHUFB BSWAP, X6 + PSHUFB BSWAP, X7 + PXOR ACC0, X0 + + MOVOU (16*0)(pTbl), ACC0 + MOVOU (16*1)(pTbl), ACCM + MOVOU ACC0, ACC1 + PSHUFD $78, X0, T1 + PXOR X0, T1 + PCLMULQDQ $0x00, X0, ACC0 + PCLMULQDQ $0x11, X0, ACC1 + PCLMULQDQ $0x00, T1, ACCM + + mulRoundAAD(X1, 1) + mulRoundAAD(X2, 2) + mulRoundAAD(X3, 3) + mulRoundAAD(X4, 4) + mulRoundAAD(X5, 5) + mulRoundAAD(X6, 6) + mulRoundAAD(X7, 7) + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + reduceRound(ACC0) + reduceRound(ACC0) + PXOR ACC1, ACC0 + JMP dataOctaLoop + +startSinglesLoop: + MOVOU (16*14)(pTbl), T1 + MOVOU (16*15)(pTbl), T2 + +dataSinglesLoop: + + CMPQ autLen, $16 + JB dataEnd + SUBQ $16, autLen + + MOVOU (aut), B0 +dataMul: + PSHUFB BSWAP, B0 + PXOR ACC0, B0 + + MOVOU T1, ACC0 + MOVOU T2, ACCM + MOVOU T1, ACC1 + + PSHUFD $78, B0, T0 + PXOR B0, T0 + PCLMULQDQ $0x00, B0, ACC0 + PCLMULQDQ $0x11, B0, ACC1 + PCLMULQDQ $0x00, T0, ACCM + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + MOVOU POLY, T0 + PCLMULQDQ $0x01, ACC0, T0 + PSHUFD $78, ACC0, ACC0 + PXOR T0, ACC0 + + MOVOU POLY, T0 + PCLMULQDQ $0x01, ACC0, T0 + PSHUFD $78, ACC0, ACC0 + PXOR T0, ACC0 + PXOR ACC1, ACC0 + + LEAQ 16(aut), aut + + JMP dataSinglesLoop + +dataEnd: + + TESTQ autLen, autLen + JEQ dataBail + + PXOR B0, B0 + LEAQ -1(aut)(autLen*1), aut + +dataLoadLoop: + + PSLLDQ $1, B0 + PINSRB $0, (aut), B0 + + LEAQ -1(aut), aut + DECQ autLen + JNE dataLoadLoop + + JMP dataMul + +dataBail: + MOVOU ACC0, (tPtr) + RET +#undef pTbl +#undef aut +#undef tPtr +#undef autLen + +// func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) +TEXT ·gcmAesEnc(SB),0,$256-96 +#define pTbl DI +#define ctx DX +#define ctrPtr CX +#define ptx SI +#define ks AX +#define tPtr R8 +#define ptxLen R9 +#define aluCTR R10 +#define aluTMP R11 +#define aluK R12 +#define NR R13 + +#define increment(i) ADDL $1, aluCTR; MOVL aluCTR, aluTMP; XORL aluK, aluTMP; BSWAPL aluTMP; MOVL aluTMP, (3*4 + 8*16 + i*16)(SP) +#define aesRnd(k) AESENC k, B0; AESENC k, B1; AESENC k, B2; AESENC k, B3; AESENC k, B4; AESENC k, B5; AESENC k, B6; AESENC k, B7 +#define aesRound(i) MOVOU (16*i)(ks), T0;AESENC T0, B0; AESENC T0, B1; AESENC T0, B2; AESENC T0, B3; AESENC T0, B4; AESENC T0, B5; AESENC T0, B6; AESENC T0, B7 +#define aesRndLast(k) AESENCLAST k, B0; AESENCLAST k, B1; AESENCLAST k, B2; AESENCLAST k, B3; AESENCLAST k, B4; AESENCLAST k, B5; AESENCLAST k, B6; AESENCLAST k, B7 +#define combinedRound(i) \ + MOVOU (16*i)(ks), T0;\ + AESENC T0, B0;\ + AESENC T0, B1;\ + AESENC T0, B2;\ + AESENC T0, B3;\ + MOVOU (16*(i*2))(pTbl), T1;\ + MOVOU T1, T2;\ + AESENC T0, B4;\ + AESENC T0, B5;\ + AESENC T0, B6;\ + AESENC T0, B7;\ + MOVOU (16*i)(SP), T0;\ + PCLMULQDQ $0x00, T0, T1;\ + PXOR T1, ACC0;\ + PSHUFD $78, T0, T1;\ + PCLMULQDQ $0x11, T0, T2;\ + PXOR T1, T0;\ + PXOR T2, ACC1;\ + MOVOU (16*(i*2+1))(pTbl), T2;\ + PCLMULQDQ $0x00, T2, T0;\ + PXOR T0, ACCM +#define mulRound(i) \ + MOVOU (16*i)(SP), T0;\ + MOVOU (16*(i*2))(pTbl), T1;\ + MOVOU T1, T2;\ + PCLMULQDQ $0x00, T0, T1;\ + PXOR T1, ACC0;\ + PCLMULQDQ $0x11, T0, T2;\ + PXOR T2, ACC1;\ + PSHUFD $78, T0, T1;\ + PXOR T1, T0;\ + MOVOU (16*(i*2+1))(pTbl), T1;\ + PCLMULQDQ $0x00, T0, T1;\ + PXOR T1, ACCM + + MOVQ productTable+0(FP), pTbl + MOVQ dst+8(FP), ctx + MOVQ src_base+32(FP), ptx + MOVQ src_len+40(FP), ptxLen + MOVQ ctr+56(FP), ctrPtr + MOVQ T+64(FP), tPtr + MOVQ ks_base+72(FP), ks + MOVQ ks_len+80(FP), NR + + SHRQ $2, NR + DECQ NR + + MOVOU bswapMask<>(SB), BSWAP + MOVOU gcmPoly<>(SB), POLY + + MOVOU (tPtr), ACC0 + PXOR ACC1, ACC1 + PXOR ACCM, ACCM + MOVOU (ctrPtr), B0 + MOVL (3*4)(ctrPtr), aluCTR + MOVOU (ks), T0 + MOVL (3*4)(ks), aluK + BSWAPL aluCTR + BSWAPL aluK + + PXOR B0, T0 + MOVOU T0, (8*16 + 0*16)(SP) + increment(0) + + CMPQ ptxLen, $128 + JB gcmAesEncSingles + SUBQ $128, ptxLen + + // We have at least 8 blocks to encrypt, prepare the rest of the counters + MOVOU T0, (8*16 + 1*16)(SP) + increment(1) + MOVOU T0, (8*16 + 2*16)(SP) + increment(2) + MOVOU T0, (8*16 + 3*16)(SP) + increment(3) + MOVOU T0, (8*16 + 4*16)(SP) + increment(4) + MOVOU T0, (8*16 + 5*16)(SP) + increment(5) + MOVOU T0, (8*16 + 6*16)(SP) + increment(6) + MOVOU T0, (8*16 + 7*16)(SP) + increment(7) + + MOVOU (8*16 + 0*16)(SP), B0 + MOVOU (8*16 + 1*16)(SP), B1 + MOVOU (8*16 + 2*16)(SP), B2 + MOVOU (8*16 + 3*16)(SP), B3 + MOVOU (8*16 + 4*16)(SP), B4 + MOVOU (8*16 + 5*16)(SP), B5 + MOVOU (8*16 + 6*16)(SP), B6 + MOVOU (8*16 + 7*16)(SP), B7 + + aesRound(1) + increment(0) + aesRound(2) + increment(1) + aesRound(3) + increment(2) + aesRound(4) + increment(3) + aesRound(5) + increment(4) + aesRound(6) + increment(5) + aesRound(7) + increment(6) + aesRound(8) + increment(7) + aesRound(9) + MOVOU (16*10)(ks), T0 + CMPQ NR, $12 + JB encLast1 + aesRnd(T0) + aesRound(11) + MOVOU (16*12)(ks), T0 + JE encLast1 + aesRnd(T0) + aesRound(13) + MOVOU (16*14)(ks), T0 +encLast1: + aesRndLast(T0) + + MOVOU (16*0)(ptx), T0 + PXOR T0, B0 + MOVOU (16*1)(ptx), T0 + PXOR T0, B1 + MOVOU (16*2)(ptx), T0 + PXOR T0, B2 + MOVOU (16*3)(ptx), T0 + PXOR T0, B3 + MOVOU (16*4)(ptx), T0 + PXOR T0, B4 + MOVOU (16*5)(ptx), T0 + PXOR T0, B5 + MOVOU (16*6)(ptx), T0 + PXOR T0, B6 + MOVOU (16*7)(ptx), T0 + PXOR T0, B7 + + MOVOU B0, (16*0)(ctx) + PSHUFB BSWAP, B0 + PXOR ACC0, B0 + MOVOU B1, (16*1)(ctx) + PSHUFB BSWAP, B1 + MOVOU B2, (16*2)(ctx) + PSHUFB BSWAP, B2 + MOVOU B3, (16*3)(ctx) + PSHUFB BSWAP, B3 + MOVOU B4, (16*4)(ctx) + PSHUFB BSWAP, B4 + MOVOU B5, (16*5)(ctx) + PSHUFB BSWAP, B5 + MOVOU B6, (16*6)(ctx) + PSHUFB BSWAP, B6 + MOVOU B7, (16*7)(ctx) + PSHUFB BSWAP, B7 + + MOVOU B0, (16*0)(SP) + MOVOU B1, (16*1)(SP) + MOVOU B2, (16*2)(SP) + MOVOU B3, (16*3)(SP) + MOVOU B4, (16*4)(SP) + MOVOU B5, (16*5)(SP) + MOVOU B6, (16*6)(SP) + MOVOU B7, (16*7)(SP) + + LEAQ 128(ptx), ptx + LEAQ 128(ctx), ctx + +gcmAesEncOctetsLoop: + + CMPQ ptxLen, $128 + JB gcmAesEncOctetsEnd + SUBQ $128, ptxLen + + MOVOU (8*16 + 0*16)(SP), B0 + MOVOU (8*16 + 1*16)(SP), B1 + MOVOU (8*16 + 2*16)(SP), B2 + MOVOU (8*16 + 3*16)(SP), B3 + MOVOU (8*16 + 4*16)(SP), B4 + MOVOU (8*16 + 5*16)(SP), B5 + MOVOU (8*16 + 6*16)(SP), B6 + MOVOU (8*16 + 7*16)(SP), B7 + + MOVOU (16*0)(SP), T0 + PSHUFD $78, T0, T1 + PXOR T0, T1 + + MOVOU (16*0)(pTbl), ACC0 + MOVOU (16*1)(pTbl), ACCM + MOVOU ACC0, ACC1 + + PCLMULQDQ $0x00, T1, ACCM + PCLMULQDQ $0x00, T0, ACC0 + PCLMULQDQ $0x11, T0, ACC1 + + combinedRound(1) + increment(0) + combinedRound(2) + increment(1) + combinedRound(3) + increment(2) + combinedRound(4) + increment(3) + combinedRound(5) + increment(4) + combinedRound(6) + increment(5) + combinedRound(7) + increment(6) + + aesRound(8) + increment(7) + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + reduceRound(ACC0) + aesRound(9) + + reduceRound(ACC0) + PXOR ACC1, ACC0 + + MOVOU (16*10)(ks), T0 + CMPQ NR, $12 + JB encLast2 + aesRnd(T0) + aesRound(11) + MOVOU (16*12)(ks), T0 + JE encLast2 + aesRnd(T0) + aesRound(13) + MOVOU (16*14)(ks), T0 +encLast2: + aesRndLast(T0) + + MOVOU (16*0)(ptx), T0 + PXOR T0, B0 + MOVOU (16*1)(ptx), T0 + PXOR T0, B1 + MOVOU (16*2)(ptx), T0 + PXOR T0, B2 + MOVOU (16*3)(ptx), T0 + PXOR T0, B3 + MOVOU (16*4)(ptx), T0 + PXOR T0, B4 + MOVOU (16*5)(ptx), T0 + PXOR T0, B5 + MOVOU (16*6)(ptx), T0 + PXOR T0, B6 + MOVOU (16*7)(ptx), T0 + PXOR T0, B7 + + MOVOU B0, (16*0)(ctx) + PSHUFB BSWAP, B0 + PXOR ACC0, B0 + MOVOU B1, (16*1)(ctx) + PSHUFB BSWAP, B1 + MOVOU B2, (16*2)(ctx) + PSHUFB BSWAP, B2 + MOVOU B3, (16*3)(ctx) + PSHUFB BSWAP, B3 + MOVOU B4, (16*4)(ctx) + PSHUFB BSWAP, B4 + MOVOU B5, (16*5)(ctx) + PSHUFB BSWAP, B5 + MOVOU B6, (16*6)(ctx) + PSHUFB BSWAP, B6 + MOVOU B7, (16*7)(ctx) + PSHUFB BSWAP, B7 + + MOVOU B0, (16*0)(SP) + MOVOU B1, (16*1)(SP) + MOVOU B2, (16*2)(SP) + MOVOU B3, (16*3)(SP) + MOVOU B4, (16*4)(SP) + MOVOU B5, (16*5)(SP) + MOVOU B6, (16*6)(SP) + MOVOU B7, (16*7)(SP) + + LEAQ 128(ptx), ptx + LEAQ 128(ctx), ctx + + JMP gcmAesEncOctetsLoop + +gcmAesEncOctetsEnd: + + MOVOU (16*0)(SP), T0 + MOVOU (16*0)(pTbl), ACC0 + MOVOU (16*1)(pTbl), ACCM + MOVOU ACC0, ACC1 + PSHUFD $78, T0, T1 + PXOR T0, T1 + PCLMULQDQ $0x00, T0, ACC0 + PCLMULQDQ $0x11, T0, ACC1 + PCLMULQDQ $0x00, T1, ACCM + + mulRound(1) + mulRound(2) + mulRound(3) + mulRound(4) + mulRound(5) + mulRound(6) + mulRound(7) + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + reduceRound(ACC0) + reduceRound(ACC0) + PXOR ACC1, ACC0 + + TESTQ ptxLen, ptxLen + JE gcmAesEncDone + + SUBQ $7, aluCTR + +gcmAesEncSingles: + + MOVOU (16*1)(ks), B1 + MOVOU (16*2)(ks), B2 + MOVOU (16*3)(ks), B3 + MOVOU (16*4)(ks), B4 + MOVOU (16*5)(ks), B5 + MOVOU (16*6)(ks), B6 + MOVOU (16*7)(ks), B7 + + MOVOU (16*14)(pTbl), T2 + +gcmAesEncSinglesLoop: + + CMPQ ptxLen, $16 + JB gcmAesEncTail + SUBQ $16, ptxLen + + MOVOU (8*16 + 0*16)(SP), B0 + increment(0) + + AESENC B1, B0 + AESENC B2, B0 + AESENC B3, B0 + AESENC B4, B0 + AESENC B5, B0 + AESENC B6, B0 + AESENC B7, B0 + MOVOU (16*8)(ks), T0 + AESENC T0, B0 + MOVOU (16*9)(ks), T0 + AESENC T0, B0 + MOVOU (16*10)(ks), T0 + CMPQ NR, $12 + JB encLast3 + AESENC T0, B0 + MOVOU (16*11)(ks), T0 + AESENC T0, B0 + MOVOU (16*12)(ks), T0 + JE encLast3 + AESENC T0, B0 + MOVOU (16*13)(ks), T0 + AESENC T0, B0 + MOVOU (16*14)(ks), T0 +encLast3: + AESENCLAST T0, B0 + + MOVOU (ptx), T0 + PXOR T0, B0 + MOVOU B0, (ctx) + + PSHUFB BSWAP, B0 + PXOR ACC0, B0 + + MOVOU T2, ACC0 + MOVOU T2, ACC1 + MOVOU (16*15)(pTbl), ACCM + + PSHUFD $78, B0, T0 + PXOR B0, T0 + PCLMULQDQ $0x00, B0, ACC0 + PCLMULQDQ $0x11, B0, ACC1 + PCLMULQDQ $0x00, T0, ACCM + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + reduceRound(ACC0) + reduceRound(ACC0) + PXOR ACC1, ACC0 + + LEAQ (16*1)(ptx), ptx + LEAQ (16*1)(ctx), ctx + + JMP gcmAesEncSinglesLoop + +gcmAesEncTail: + TESTQ ptxLen, ptxLen + JE gcmAesEncDone + + MOVOU (8*16 + 0*16)(SP), B0 + AESENC B1, B0 + AESENC B2, B0 + AESENC B3, B0 + AESENC B4, B0 + AESENC B5, B0 + AESENC B6, B0 + AESENC B7, B0 + MOVOU (16*8)(ks), T0 + AESENC T0, B0 + MOVOU (16*9)(ks), T0 + AESENC T0, B0 + MOVOU (16*10)(ks), T0 + CMPQ NR, $12 + JB encLast4 + AESENC T0, B0 + MOVOU (16*11)(ks), T0 + AESENC T0, B0 + MOVOU (16*12)(ks), T0 + JE encLast4 + AESENC T0, B0 + MOVOU (16*13)(ks), T0 + AESENC T0, B0 + MOVOU (16*14)(ks), T0 +encLast4: + AESENCLAST T0, B0 + MOVOU B0, T0 + + LEAQ -1(ptx)(ptxLen*1), ptx + + MOVQ ptxLen, aluTMP + SHLQ $4, aluTMP + + LEAQ andMask<>(SB), aluCTR + MOVOU -16(aluCTR)(aluTMP*1), T1 + + PXOR B0, B0 +ptxLoadLoop: + PSLLDQ $1, B0 + PINSRB $0, (ptx), B0 + LEAQ -1(ptx), ptx + DECQ ptxLen + JNE ptxLoadLoop + + PXOR T0, B0 + PAND T1, B0 + MOVOU B0, (ctx) // I assume there is always space, due to TAG in the end of the CT + + PSHUFB BSWAP, B0 + PXOR ACC0, B0 + + MOVOU T2, ACC0 + MOVOU T2, ACC1 + MOVOU (16*15)(pTbl), ACCM + + PSHUFD $78, B0, T0 + PXOR B0, T0 + PCLMULQDQ $0x00, B0, ACC0 + PCLMULQDQ $0x11, B0, ACC1 + PCLMULQDQ $0x00, T0, ACCM + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + reduceRound(ACC0) + reduceRound(ACC0) + PXOR ACC1, ACC0 + +gcmAesEncDone: + MOVOU ACC0, (tPtr) + RET +#undef increment + +// func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) +TEXT ·gcmAesDec(SB),0,$128-96 +#define increment(i) ADDL $1, aluCTR; MOVL aluCTR, aluTMP; XORL aluK, aluTMP; BSWAPL aluTMP; MOVL aluTMP, (3*4 + i*16)(SP) +#define combinedDecRound(i) \ + MOVOU (16*i)(ks), T0;\ + AESENC T0, B0;\ + AESENC T0, B1;\ + AESENC T0, B2;\ + AESENC T0, B3;\ + MOVOU (16*(i*2))(pTbl), T1;\ + MOVOU T1, T2;\ + AESENC T0, B4;\ + AESENC T0, B5;\ + AESENC T0, B6;\ + AESENC T0, B7;\ + MOVOU (16*i)(ctx), T0;\ + PSHUFB BSWAP, T0;\ + PCLMULQDQ $0x00, T0, T1;\ + PXOR T1, ACC0;\ + PSHUFD $78, T0, T1;\ + PCLMULQDQ $0x11, T0, T2;\ + PXOR T1, T0;\ + PXOR T2, ACC1;\ + MOVOU (16*(i*2+1))(pTbl), T2;\ + PCLMULQDQ $0x00, T2, T0;\ + PXOR T0, ACCM + + MOVQ productTable+0(FP), pTbl + MOVQ dst+8(FP), ptx + MOVQ src_base+32(FP), ctx + MOVQ src_len+40(FP), ptxLen + MOVQ ctr+56(FP), ctrPtr + MOVQ T+64(FP), tPtr + MOVQ ks_base+72(FP), ks + MOVQ ks_len+80(FP), NR + + SHRQ $2, NR + DECQ NR + + MOVOU bswapMask<>(SB), BSWAP + MOVOU gcmPoly<>(SB), POLY + + MOVOU (tPtr), ACC0 + PXOR ACC1, ACC1 + PXOR ACCM, ACCM + MOVOU (ctrPtr), B0 + MOVL (3*4)(ctrPtr), aluCTR + MOVOU (ks), T0 + MOVL (3*4)(ks), aluK + BSWAPL aluCTR + BSWAPL aluK + + PXOR B0, T0 + MOVOU T0, (0*16)(SP) + increment(0) + + CMPQ ptxLen, $128 + JB gcmAesDecSingles + + MOVOU T0, (1*16)(SP) + increment(1) + MOVOU T0, (2*16)(SP) + increment(2) + MOVOU T0, (3*16)(SP) + increment(3) + MOVOU T0, (4*16)(SP) + increment(4) + MOVOU T0, (5*16)(SP) + increment(5) + MOVOU T0, (6*16)(SP) + increment(6) + MOVOU T0, (7*16)(SP) + increment(7) + +gcmAesDecOctetsLoop: + + CMPQ ptxLen, $128 + JB gcmAesDecEndOctets + SUBQ $128, ptxLen + + MOVOU (0*16)(SP), B0 + MOVOU (1*16)(SP), B1 + MOVOU (2*16)(SP), B2 + MOVOU (3*16)(SP), B3 + MOVOU (4*16)(SP), B4 + MOVOU (5*16)(SP), B5 + MOVOU (6*16)(SP), B6 + MOVOU (7*16)(SP), B7 + + MOVOU (16*0)(ctx), T0 + PSHUFB BSWAP, T0 + PXOR ACC0, T0 + PSHUFD $78, T0, T1 + PXOR T0, T1 + + MOVOU (16*0)(pTbl), ACC0 + MOVOU (16*1)(pTbl), ACCM + MOVOU ACC0, ACC1 + + PCLMULQDQ $0x00, T1, ACCM + PCLMULQDQ $0x00, T0, ACC0 + PCLMULQDQ $0x11, T0, ACC1 + + combinedDecRound(1) + increment(0) + combinedDecRound(2) + increment(1) + combinedDecRound(3) + increment(2) + combinedDecRound(4) + increment(3) + combinedDecRound(5) + increment(4) + combinedDecRound(6) + increment(5) + combinedDecRound(7) + increment(6) + + aesRound(8) + increment(7) + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + reduceRound(ACC0) + aesRound(9) + + reduceRound(ACC0) + PXOR ACC1, ACC0 + + MOVOU (16*10)(ks), T0 + CMPQ NR, $12 + JB decLast1 + aesRnd(T0) + aesRound(11) + MOVOU (16*12)(ks), T0 + JE decLast1 + aesRnd(T0) + aesRound(13) + MOVOU (16*14)(ks), T0 +decLast1: + aesRndLast(T0) + + MOVOU (16*0)(ctx), T0 + PXOR T0, B0 + MOVOU (16*1)(ctx), T0 + PXOR T0, B1 + MOVOU (16*2)(ctx), T0 + PXOR T0, B2 + MOVOU (16*3)(ctx), T0 + PXOR T0, B3 + MOVOU (16*4)(ctx), T0 + PXOR T0, B4 + MOVOU (16*5)(ctx), T0 + PXOR T0, B5 + MOVOU (16*6)(ctx), T0 + PXOR T0, B6 + MOVOU (16*7)(ctx), T0 + PXOR T0, B7 + + MOVOU B0, (16*0)(ptx) + MOVOU B1, (16*1)(ptx) + MOVOU B2, (16*2)(ptx) + MOVOU B3, (16*3)(ptx) + MOVOU B4, (16*4)(ptx) + MOVOU B5, (16*5)(ptx) + MOVOU B6, (16*6)(ptx) + MOVOU B7, (16*7)(ptx) + + LEAQ 128(ptx), ptx + LEAQ 128(ctx), ctx + + JMP gcmAesDecOctetsLoop + +gcmAesDecEndOctets: + + SUBQ $7, aluCTR + +gcmAesDecSingles: + + MOVOU (16*1)(ks), B1 + MOVOU (16*2)(ks), B2 + MOVOU (16*3)(ks), B3 + MOVOU (16*4)(ks), B4 + MOVOU (16*5)(ks), B5 + MOVOU (16*6)(ks), B6 + MOVOU (16*7)(ks), B7 + + MOVOU (16*14)(pTbl), T2 + +gcmAesDecSinglesLoop: + + CMPQ ptxLen, $16 + JB gcmAesDecTail + SUBQ $16, ptxLen + + MOVOU (ctx), B0 + MOVOU B0, T1 + PSHUFB BSWAP, B0 + PXOR ACC0, B0 + + MOVOU T2, ACC0 + MOVOU T2, ACC1 + MOVOU (16*15)(pTbl), ACCM + + PCLMULQDQ $0x00, B0, ACC0 + PCLMULQDQ $0x11, B0, ACC1 + PSHUFD $78, B0, T0 + PXOR B0, T0 + PCLMULQDQ $0x00, T0, ACCM + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + reduceRound(ACC0) + reduceRound(ACC0) + PXOR ACC1, ACC0 + + MOVOU (0*16)(SP), B0 + increment(0) + AESENC B1, B0 + AESENC B2, B0 + AESENC B3, B0 + AESENC B4, B0 + AESENC B5, B0 + AESENC B6, B0 + AESENC B7, B0 + MOVOU (16*8)(ks), T0 + AESENC T0, B0 + MOVOU (16*9)(ks), T0 + AESENC T0, B0 + MOVOU (16*10)(ks), T0 + CMPQ NR, $12 + JB decLast2 + AESENC T0, B0 + MOVOU (16*11)(ks), T0 + AESENC T0, B0 + MOVOU (16*12)(ks), T0 + JE decLast2 + AESENC T0, B0 + MOVOU (16*13)(ks), T0 + AESENC T0, B0 + MOVOU (16*14)(ks), T0 +decLast2: + AESENCLAST T0, B0 + + PXOR T1, B0 + MOVOU B0, (ptx) + + LEAQ (16*1)(ptx), ptx + LEAQ (16*1)(ctx), ctx + + JMP gcmAesDecSinglesLoop + +gcmAesDecTail: + + TESTQ ptxLen, ptxLen + JE gcmAesDecDone + + MOVQ ptxLen, aluTMP + SHLQ $4, aluTMP + LEAQ andMask<>(SB), aluCTR + MOVOU -16(aluCTR)(aluTMP*1), T1 + + MOVOU (ctx), B0 // I assume there is TAG attached to the ctx, and there is no read overflow + PAND T1, B0 + + MOVOU B0, T1 + PSHUFB BSWAP, B0 + PXOR ACC0, B0 + + MOVOU (16*14)(pTbl), ACC0 + MOVOU (16*15)(pTbl), ACCM + MOVOU ACC0, ACC1 + + PCLMULQDQ $0x00, B0, ACC0 + PCLMULQDQ $0x11, B0, ACC1 + PSHUFD $78, B0, T0 + PXOR B0, T0 + PCLMULQDQ $0x00, T0, ACCM + + PXOR ACC0, ACCM + PXOR ACC1, ACCM + MOVOU ACCM, T0 + PSRLDQ $8, ACCM + PSLLDQ $8, T0 + PXOR ACCM, ACC1 + PXOR T0, ACC0 + + reduceRound(ACC0) + reduceRound(ACC0) + PXOR ACC1, ACC0 + + MOVOU (0*16)(SP), B0 + increment(0) + AESENC B1, B0 + AESENC B2, B0 + AESENC B3, B0 + AESENC B4, B0 + AESENC B5, B0 + AESENC B6, B0 + AESENC B7, B0 + MOVOU (16*8)(ks), T0 + AESENC T0, B0 + MOVOU (16*9)(ks), T0 + AESENC T0, B0 + MOVOU (16*10)(ks), T0 + CMPQ NR, $12 + JB decLast3 + AESENC T0, B0 + MOVOU (16*11)(ks), T0 + AESENC T0, B0 + MOVOU (16*12)(ks), T0 + JE decLast3 + AESENC T0, B0 + MOVOU (16*13)(ks), T0 + AESENC T0, B0 + MOVOU (16*14)(ks), T0 +decLast3: + AESENCLAST T0, B0 + PXOR T1, B0 + +ptxStoreLoop: + PEXTRB $0, B0, (ptx) + PSRLDQ $1, B0 + LEAQ 1(ptx), ptx + DECQ ptxLen + + JNE ptxStoreLoop + +gcmAesDecDone: + + MOVOU ACC0, (tPtr) + RET diff --git a/src/crypto/aes/gcm_arm64.s b/src/crypto/aes/gcm_arm64.s new file mode 100644 index 0000000..61c868c --- /dev/null +++ b/src/crypto/aes/gcm_arm64.s @@ -0,0 +1,1021 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +#define B0 V0 +#define B1 V1 +#define B2 V2 +#define B3 V3 +#define B4 V4 +#define B5 V5 +#define B6 V6 +#define B7 V7 + +#define ACC0 V8 +#define ACC1 V9 +#define ACCM V10 + +#define T0 V11 +#define T1 V12 +#define T2 V13 +#define T3 V14 + +#define POLY V15 +#define ZERO V16 +#define INC V17 +#define CTR V18 + +#define K0 V19 +#define K1 V20 +#define K2 V21 +#define K3 V22 +#define K4 V23 +#define K5 V24 +#define K6 V25 +#define K7 V26 +#define K8 V27 +#define K9 V28 +#define K10 V29 +#define K11 V30 +#define KLAST V31 + +#define reduce() \ + VEOR ACC0.B16, ACCM.B16, ACCM.B16 \ + VEOR ACC1.B16, ACCM.B16, ACCM.B16 \ + VEXT $8, ZERO.B16, ACCM.B16, T0.B16 \ + VEXT $8, ACCM.B16, ZERO.B16, ACCM.B16 \ + VEOR ACCM.B16, ACC0.B16, ACC0.B16 \ + VEOR T0.B16, ACC1.B16, ACC1.B16 \ + VPMULL POLY.D1, ACC0.D1, T0.Q1 \ + VEXT $8, ACC0.B16, ACC0.B16, ACC0.B16 \ + VEOR T0.B16, ACC0.B16, ACC0.B16 \ + VPMULL POLY.D1, ACC0.D1, T0.Q1 \ + VEOR T0.B16, ACC1.B16, ACC1.B16 \ + VEXT $8, ACC1.B16, ACC1.B16, ACC1.B16 \ + VEOR ACC1.B16, ACC0.B16, ACC0.B16 \ + +// func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64) +TEXT ·gcmAesFinish(SB),NOSPLIT,$0 +#define pTbl R0 +#define tMsk R1 +#define tPtr R2 +#define plen R3 +#define dlen R4 + + MOVD $0xC2, R1 + LSL $56, R1 + MOVD $1, R0 + VMOV R1, POLY.D[0] + VMOV R0, POLY.D[1] + VEOR ZERO.B16, ZERO.B16, ZERO.B16 + + MOVD productTable+0(FP), pTbl + MOVD tagMask+8(FP), tMsk + MOVD T+16(FP), tPtr + MOVD pLen+24(FP), plen + MOVD dLen+32(FP), dlen + + VLD1 (tPtr), [ACC0.B16] + VLD1 (tMsk), [B1.B16] + + LSL $3, plen + LSL $3, dlen + + VMOV dlen, B0.D[0] + VMOV plen, B0.D[1] + + ADD $14*16, pTbl + VLD1.P (pTbl), [T1.B16, T2.B16] + + VEOR ACC0.B16, B0.B16, B0.B16 + + VEXT $8, B0.B16, B0.B16, T0.B16 + VEOR B0.B16, T0.B16, T0.B16 + VPMULL B0.D1, T1.D1, ACC1.Q1 + VPMULL2 B0.D2, T1.D2, ACC0.Q1 + VPMULL T0.D1, T2.D1, ACCM.Q1 + + reduce() + + VREV64 ACC0.B16, ACC0.B16 + VEOR B1.B16, ACC0.B16, ACC0.B16 + + VST1 [ACC0.B16], (tPtr) + RET +#undef pTbl +#undef tMsk +#undef tPtr +#undef plen +#undef dlen + +// func gcmAesInit(productTable *[256]byte, ks []uint32) +TEXT ·gcmAesInit(SB),NOSPLIT,$0 +#define pTbl R0 +#define KS R1 +#define NR R2 +#define I R3 + MOVD productTable+0(FP), pTbl + MOVD ks_base+8(FP), KS + MOVD ks_len+16(FP), NR + + MOVD $0xC2, I + LSL $56, I + VMOV I, POLY.D[0] + MOVD $1, I + VMOV I, POLY.D[1] + VEOR ZERO.B16, ZERO.B16, ZERO.B16 + + // Encrypt block 0 with the AES key to generate the hash key H + VLD1.P 64(KS), [T0.B16, T1.B16, T2.B16, T3.B16] + VEOR B0.B16, B0.B16, B0.B16 + AESE T0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T1.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T3.B16, B0.B16 + AESMC B0.B16, B0.B16 + VLD1.P 64(KS), [T0.B16, T1.B16, T2.B16, T3.B16] + AESE T0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T1.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T3.B16, B0.B16 + AESMC B0.B16, B0.B16 + TBZ $4, NR, initEncFinish + VLD1.P 32(KS), [T0.B16, T1.B16] + AESE T0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T1.B16, B0.B16 + AESMC B0.B16, B0.B16 + TBZ $3, NR, initEncFinish + VLD1.P 32(KS), [T0.B16, T1.B16] + AESE T0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T1.B16, B0.B16 + AESMC B0.B16, B0.B16 +initEncFinish: + VLD1 (KS), [T0.B16, T1.B16, T2.B16] + AESE T0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE T1.B16, B0.B16 + VEOR T2.B16, B0.B16, B0.B16 + + VREV64 B0.B16, B0.B16 + + // Multiply by 2 modulo P + VMOV B0.D[0], I + ASR $63, I + VMOV I, T1.D[0] + VMOV I, T1.D[1] + VAND POLY.B16, T1.B16, T1.B16 + VUSHR $63, B0.D2, T2.D2 + VEXT $8, ZERO.B16, T2.B16, T2.B16 + VSHL $1, B0.D2, B0.D2 + VEOR T1.B16, B0.B16, B0.B16 + VEOR T2.B16, B0.B16, B0.B16 // Can avoid this when VSLI is available + + // Karatsuba pre-computation + VEXT $8, B0.B16, B0.B16, B1.B16 + VEOR B0.B16, B1.B16, B1.B16 + + ADD $14*16, pTbl + VST1 [B0.B16, B1.B16], (pTbl) + SUB $2*16, pTbl + + VMOV B0.B16, B2.B16 + VMOV B1.B16, B3.B16 + + MOVD $7, I + +initLoop: + // Compute powers of H + SUBS $1, I + + VPMULL B0.D1, B2.D1, T1.Q1 + VPMULL2 B0.D2, B2.D2, T0.Q1 + VPMULL B1.D1, B3.D1, T2.Q1 + VEOR T0.B16, T2.B16, T2.B16 + VEOR T1.B16, T2.B16, T2.B16 + VEXT $8, ZERO.B16, T2.B16, T3.B16 + VEXT $8, T2.B16, ZERO.B16, T2.B16 + VEOR T2.B16, T0.B16, T0.B16 + VEOR T3.B16, T1.B16, T1.B16 + VPMULL POLY.D1, T0.D1, T2.Q1 + VEXT $8, T0.B16, T0.B16, T0.B16 + VEOR T2.B16, T0.B16, T0.B16 + VPMULL POLY.D1, T0.D1, T2.Q1 + VEXT $8, T0.B16, T0.B16, T0.B16 + VEOR T2.B16, T0.B16, T0.B16 + VEOR T1.B16, T0.B16, B2.B16 + VMOV B2.B16, B3.B16 + VEXT $8, B2.B16, B2.B16, B2.B16 + VEOR B2.B16, B3.B16, B3.B16 + + VST1 [B2.B16, B3.B16], (pTbl) + SUB $2*16, pTbl + + BNE initLoop + RET +#undef I +#undef NR +#undef KS +#undef pTbl + +// func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte) +TEXT ·gcmAesData(SB),NOSPLIT,$0 +#define pTbl R0 +#define aut R1 +#define tPtr R2 +#define autLen R3 +#define H0 R4 +#define pTblSave R5 + +#define mulRound(X) \ + VLD1.P 32(pTbl), [T1.B16, T2.B16] \ + VREV64 X.B16, X.B16 \ + VEXT $8, X.B16, X.B16, T0.B16 \ + VEOR X.B16, T0.B16, T0.B16 \ + VPMULL X.D1, T1.D1, T3.Q1 \ + VEOR T3.B16, ACC1.B16, ACC1.B16 \ + VPMULL2 X.D2, T1.D2, T3.Q1 \ + VEOR T3.B16, ACC0.B16, ACC0.B16 \ + VPMULL T0.D1, T2.D1, T3.Q1 \ + VEOR T3.B16, ACCM.B16, ACCM.B16 + + MOVD productTable+0(FP), pTbl + MOVD data_base+8(FP), aut + MOVD data_len+16(FP), autLen + MOVD T+32(FP), tPtr + + VEOR ACC0.B16, ACC0.B16, ACC0.B16 + CBZ autLen, dataBail + + MOVD $0xC2, H0 + LSL $56, H0 + VMOV H0, POLY.D[0] + MOVD $1, H0 + VMOV H0, POLY.D[1] + VEOR ZERO.B16, ZERO.B16, ZERO.B16 + MOVD pTbl, pTblSave + + CMP $13, autLen + BEQ dataTLS + CMP $128, autLen + BLT startSinglesLoop + B octetsLoop + +dataTLS: + ADD $14*16, pTbl + VLD1.P (pTbl), [T1.B16, T2.B16] + VEOR B0.B16, B0.B16, B0.B16 + + MOVD (aut), H0 + VMOV H0, B0.D[0] + MOVW 8(aut), H0 + VMOV H0, B0.S[2] + MOVB 12(aut), H0 + VMOV H0, B0.B[12] + + MOVD $0, autLen + B dataMul + +octetsLoop: + CMP $128, autLen + BLT startSinglesLoop + SUB $128, autLen + + VLD1.P 32(aut), [B0.B16, B1.B16] + + VLD1.P 32(pTbl), [T1.B16, T2.B16] + VREV64 B0.B16, B0.B16 + VEOR ACC0.B16, B0.B16, B0.B16 + VEXT $8, B0.B16, B0.B16, T0.B16 + VEOR B0.B16, T0.B16, T0.B16 + VPMULL B0.D1, T1.D1, ACC1.Q1 + VPMULL2 B0.D2, T1.D2, ACC0.Q1 + VPMULL T0.D1, T2.D1, ACCM.Q1 + + mulRound(B1) + VLD1.P 32(aut), [B2.B16, B3.B16] + mulRound(B2) + mulRound(B3) + VLD1.P 32(aut), [B4.B16, B5.B16] + mulRound(B4) + mulRound(B5) + VLD1.P 32(aut), [B6.B16, B7.B16] + mulRound(B6) + mulRound(B7) + + MOVD pTblSave, pTbl + reduce() + B octetsLoop + +startSinglesLoop: + + ADD $14*16, pTbl + VLD1.P (pTbl), [T1.B16, T2.B16] + +singlesLoop: + + CMP $16, autLen + BLT dataEnd + SUB $16, autLen + + VLD1.P 16(aut), [B0.B16] +dataMul: + VREV64 B0.B16, B0.B16 + VEOR ACC0.B16, B0.B16, B0.B16 + + VEXT $8, B0.B16, B0.B16, T0.B16 + VEOR B0.B16, T0.B16, T0.B16 + VPMULL B0.D1, T1.D1, ACC1.Q1 + VPMULL2 B0.D2, T1.D2, ACC0.Q1 + VPMULL T0.D1, T2.D1, ACCM.Q1 + + reduce() + + B singlesLoop + +dataEnd: + + CBZ autLen, dataBail + VEOR B0.B16, B0.B16, B0.B16 + ADD autLen, aut + +dataLoadLoop: + MOVB.W -1(aut), H0 + VEXT $15, B0.B16, ZERO.B16, B0.B16 + VMOV H0, B0.B[0] + SUBS $1, autLen + BNE dataLoadLoop + B dataMul + +dataBail: + VST1 [ACC0.B16], (tPtr) + RET + +#undef pTbl +#undef aut +#undef tPtr +#undef autLen +#undef H0 +#undef pTblSave + +// func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) +TEXT ·gcmAesEnc(SB),NOSPLIT,$0 +#define pTbl R0 +#define dstPtr R1 +#define ctrPtr R2 +#define srcPtr R3 +#define ks R4 +#define tPtr R5 +#define srcPtrLen R6 +#define aluCTR R7 +#define aluTMP R8 +#define aluK R9 +#define NR R10 +#define H0 R11 +#define H1 R12 +#define curK R13 +#define pTblSave R14 + +#define aesrndx8(K) \ + AESE K.B16, B0.B16 \ + AESMC B0.B16, B0.B16 \ + AESE K.B16, B1.B16 \ + AESMC B1.B16, B1.B16 \ + AESE K.B16, B2.B16 \ + AESMC B2.B16, B2.B16 \ + AESE K.B16, B3.B16 \ + AESMC B3.B16, B3.B16 \ + AESE K.B16, B4.B16 \ + AESMC B4.B16, B4.B16 \ + AESE K.B16, B5.B16 \ + AESMC B5.B16, B5.B16 \ + AESE K.B16, B6.B16 \ + AESMC B6.B16, B6.B16 \ + AESE K.B16, B7.B16 \ + AESMC B7.B16, B7.B16 + +#define aesrndlastx8(K) \ + AESE K.B16, B0.B16 \ + AESE K.B16, B1.B16 \ + AESE K.B16, B2.B16 \ + AESE K.B16, B3.B16 \ + AESE K.B16, B4.B16 \ + AESE K.B16, B5.B16 \ + AESE K.B16, B6.B16 \ + AESE K.B16, B7.B16 + + MOVD productTable+0(FP), pTbl + MOVD dst+8(FP), dstPtr + MOVD src_base+32(FP), srcPtr + MOVD src_len+40(FP), srcPtrLen + MOVD ctr+56(FP), ctrPtr + MOVD T+64(FP), tPtr + MOVD ks_base+72(FP), ks + MOVD ks_len+80(FP), NR + + MOVD $0xC2, H1 + LSL $56, H1 + MOVD $1, H0 + VMOV H1, POLY.D[0] + VMOV H0, POLY.D[1] + VEOR ZERO.B16, ZERO.B16, ZERO.B16 + // Compute NR from len(ks) + MOVD pTbl, pTblSave + // Current tag, after AAD + VLD1 (tPtr), [ACC0.B16] + VEOR ACC1.B16, ACC1.B16, ACC1.B16 + VEOR ACCM.B16, ACCM.B16, ACCM.B16 + // Prepare initial counter, and the increment vector + VLD1 (ctrPtr), [CTR.B16] + VEOR INC.B16, INC.B16, INC.B16 + MOVD $1, H0 + VMOV H0, INC.S[3] + VREV32 CTR.B16, CTR.B16 + VADD CTR.S4, INC.S4, CTR.S4 + // Skip to <8 blocks loop + CMP $128, srcPtrLen + + MOVD ks, H0 + // For AES-128 round keys are stored in: K0 .. K10, KLAST + VLD1.P 64(H0), [K0.B16, K1.B16, K2.B16, K3.B16] + VLD1.P 64(H0), [K4.B16, K5.B16, K6.B16, K7.B16] + VLD1.P 48(H0), [K8.B16, K9.B16, K10.B16] + VMOV K10.B16, KLAST.B16 + + BLT startSingles + // There are at least 8 blocks to encrypt + TBZ $4, NR, octetsLoop + + // For AES-192 round keys occupy: K0 .. K7, K10, K11, K8, K9, KLAST + VMOV K8.B16, K10.B16 + VMOV K9.B16, K11.B16 + VMOV KLAST.B16, K8.B16 + VLD1.P 16(H0), [K9.B16] + VLD1.P 16(H0), [KLAST.B16] + TBZ $3, NR, octetsLoop + // For AES-256 round keys occupy: K0 .. K7, K10, K11, mem, mem, K8, K9, KLAST + VMOV KLAST.B16, K8.B16 + VLD1.P 16(H0), [K9.B16] + VLD1.P 16(H0), [KLAST.B16] + ADD $10*16, ks, H0 + MOVD H0, curK + +octetsLoop: + SUB $128, srcPtrLen + + VMOV CTR.B16, B0.B16 + VADD B0.S4, INC.S4, B1.S4 + VREV32 B0.B16, B0.B16 + VADD B1.S4, INC.S4, B2.S4 + VREV32 B1.B16, B1.B16 + VADD B2.S4, INC.S4, B3.S4 + VREV32 B2.B16, B2.B16 + VADD B3.S4, INC.S4, B4.S4 + VREV32 B3.B16, B3.B16 + VADD B4.S4, INC.S4, B5.S4 + VREV32 B4.B16, B4.B16 + VADD B5.S4, INC.S4, B6.S4 + VREV32 B5.B16, B5.B16 + VADD B6.S4, INC.S4, B7.S4 + VREV32 B6.B16, B6.B16 + VADD B7.S4, INC.S4, CTR.S4 + VREV32 B7.B16, B7.B16 + + aesrndx8(K0) + aesrndx8(K1) + aesrndx8(K2) + aesrndx8(K3) + aesrndx8(K4) + aesrndx8(K5) + aesrndx8(K6) + aesrndx8(K7) + TBZ $4, NR, octetsFinish + aesrndx8(K10) + aesrndx8(K11) + TBZ $3, NR, octetsFinish + VLD1.P 32(curK), [T1.B16, T2.B16] + aesrndx8(T1) + aesrndx8(T2) + MOVD H0, curK +octetsFinish: + aesrndx8(K8) + aesrndlastx8(K9) + + VEOR KLAST.B16, B0.B16, B0.B16 + VEOR KLAST.B16, B1.B16, B1.B16 + VEOR KLAST.B16, B2.B16, B2.B16 + VEOR KLAST.B16, B3.B16, B3.B16 + VEOR KLAST.B16, B4.B16, B4.B16 + VEOR KLAST.B16, B5.B16, B5.B16 + VEOR KLAST.B16, B6.B16, B6.B16 + VEOR KLAST.B16, B7.B16, B7.B16 + + VLD1.P 32(srcPtr), [T1.B16, T2.B16] + VEOR B0.B16, T1.B16, B0.B16 + VEOR B1.B16, T2.B16, B1.B16 + VST1.P [B0.B16, B1.B16], 32(dstPtr) + VLD1.P 32(srcPtr), [T1.B16, T2.B16] + VEOR B2.B16, T1.B16, B2.B16 + VEOR B3.B16, T2.B16, B3.B16 + VST1.P [B2.B16, B3.B16], 32(dstPtr) + VLD1.P 32(srcPtr), [T1.B16, T2.B16] + VEOR B4.B16, T1.B16, B4.B16 + VEOR B5.B16, T2.B16, B5.B16 + VST1.P [B4.B16, B5.B16], 32(dstPtr) + VLD1.P 32(srcPtr), [T1.B16, T2.B16] + VEOR B6.B16, T1.B16, B6.B16 + VEOR B7.B16, T2.B16, B7.B16 + VST1.P [B6.B16, B7.B16], 32(dstPtr) + + VLD1.P 32(pTbl), [T1.B16, T2.B16] + VREV64 B0.B16, B0.B16 + VEOR ACC0.B16, B0.B16, B0.B16 + VEXT $8, B0.B16, B0.B16, T0.B16 + VEOR B0.B16, T0.B16, T0.B16 + VPMULL B0.D1, T1.D1, ACC1.Q1 + VPMULL2 B0.D2, T1.D2, ACC0.Q1 + VPMULL T0.D1, T2.D1, ACCM.Q1 + + mulRound(B1) + mulRound(B2) + mulRound(B3) + mulRound(B4) + mulRound(B5) + mulRound(B6) + mulRound(B7) + MOVD pTblSave, pTbl + reduce() + + CMP $128, srcPtrLen + BGE octetsLoop + +startSingles: + CBZ srcPtrLen, done + ADD $14*16, pTbl + // Preload H and its Karatsuba precomp + VLD1.P (pTbl), [T1.B16, T2.B16] + // Preload AES round keys + ADD $128, ks + VLD1.P 48(ks), [K8.B16, K9.B16, K10.B16] + VMOV K10.B16, KLAST.B16 + TBZ $4, NR, singlesLoop + VLD1.P 32(ks), [B1.B16, B2.B16] + VMOV B2.B16, KLAST.B16 + TBZ $3, NR, singlesLoop + VLD1.P 32(ks), [B3.B16, B4.B16] + VMOV B4.B16, KLAST.B16 + +singlesLoop: + CMP $16, srcPtrLen + BLT tail + SUB $16, srcPtrLen + + VLD1.P 16(srcPtr), [T0.B16] + VEOR KLAST.B16, T0.B16, T0.B16 + + VREV32 CTR.B16, B0.B16 + VADD CTR.S4, INC.S4, CTR.S4 + + AESE K0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K1.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K3.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K4.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K5.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K6.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K7.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K8.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K9.B16, B0.B16 + TBZ $4, NR, singlesLast + AESMC B0.B16, B0.B16 + AESE K10.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE B1.B16, B0.B16 + TBZ $3, NR, singlesLast + AESMC B0.B16, B0.B16 + AESE B2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE B3.B16, B0.B16 +singlesLast: + VEOR T0.B16, B0.B16, B0.B16 +encReduce: + VST1.P [B0.B16], 16(dstPtr) + + VREV64 B0.B16, B0.B16 + VEOR ACC0.B16, B0.B16, B0.B16 + + VEXT $8, B0.B16, B0.B16, T0.B16 + VEOR B0.B16, T0.B16, T0.B16 + VPMULL B0.D1, T1.D1, ACC1.Q1 + VPMULL2 B0.D2, T1.D2, ACC0.Q1 + VPMULL T0.D1, T2.D1, ACCM.Q1 + + reduce() + + B singlesLoop +tail: + CBZ srcPtrLen, done + + VEOR T0.B16, T0.B16, T0.B16 + VEOR T3.B16, T3.B16, T3.B16 + MOVD $0, H1 + SUB $1, H1 + ADD srcPtrLen, srcPtr + + TBZ $3, srcPtrLen, ld4 + MOVD.W -8(srcPtr), H0 + VMOV H0, T0.D[0] + VMOV H1, T3.D[0] +ld4: + TBZ $2, srcPtrLen, ld2 + MOVW.W -4(srcPtr), H0 + VEXT $12, T0.B16, ZERO.B16, T0.B16 + VEXT $12, T3.B16, ZERO.B16, T3.B16 + VMOV H0, T0.S[0] + VMOV H1, T3.S[0] +ld2: + TBZ $1, srcPtrLen, ld1 + MOVH.W -2(srcPtr), H0 + VEXT $14, T0.B16, ZERO.B16, T0.B16 + VEXT $14, T3.B16, ZERO.B16, T3.B16 + VMOV H0, T0.H[0] + VMOV H1, T3.H[0] +ld1: + TBZ $0, srcPtrLen, ld0 + MOVB.W -1(srcPtr), H0 + VEXT $15, T0.B16, ZERO.B16, T0.B16 + VEXT $15, T3.B16, ZERO.B16, T3.B16 + VMOV H0, T0.B[0] + VMOV H1, T3.B[0] +ld0: + + MOVD ZR, srcPtrLen + VEOR KLAST.B16, T0.B16, T0.B16 + VREV32 CTR.B16, B0.B16 + + AESE K0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K1.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K3.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K4.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K5.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K6.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K7.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K8.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K9.B16, B0.B16 + TBZ $4, NR, tailLast + AESMC B0.B16, B0.B16 + AESE K10.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE B1.B16, B0.B16 + TBZ $3, NR, tailLast + AESMC B0.B16, B0.B16 + AESE B2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE B3.B16, B0.B16 + +tailLast: + VEOR T0.B16, B0.B16, B0.B16 + VAND T3.B16, B0.B16, B0.B16 + B encReduce + +done: + VST1 [ACC0.B16], (tPtr) + RET + +// func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32) +TEXT ·gcmAesDec(SB),NOSPLIT,$0 + MOVD productTable+0(FP), pTbl + MOVD dst+8(FP), dstPtr + MOVD src_base+32(FP), srcPtr + MOVD src_len+40(FP), srcPtrLen + MOVD ctr+56(FP), ctrPtr + MOVD T+64(FP), tPtr + MOVD ks_base+72(FP), ks + MOVD ks_len+80(FP), NR + + MOVD $0xC2, H1 + LSL $56, H1 + MOVD $1, H0 + VMOV H1, POLY.D[0] + VMOV H0, POLY.D[1] + VEOR ZERO.B16, ZERO.B16, ZERO.B16 + // Compute NR from len(ks) + MOVD pTbl, pTblSave + // Current tag, after AAD + VLD1 (tPtr), [ACC0.B16] + VEOR ACC1.B16, ACC1.B16, ACC1.B16 + VEOR ACCM.B16, ACCM.B16, ACCM.B16 + // Prepare initial counter, and the increment vector + VLD1 (ctrPtr), [CTR.B16] + VEOR INC.B16, INC.B16, INC.B16 + MOVD $1, H0 + VMOV H0, INC.S[3] + VREV32 CTR.B16, CTR.B16 + VADD CTR.S4, INC.S4, CTR.S4 + + MOVD ks, H0 + // For AES-128 round keys are stored in: K0 .. K10, KLAST + VLD1.P 64(H0), [K0.B16, K1.B16, K2.B16, K3.B16] + VLD1.P 64(H0), [K4.B16, K5.B16, K6.B16, K7.B16] + VLD1.P 48(H0), [K8.B16, K9.B16, K10.B16] + VMOV K10.B16, KLAST.B16 + + // Skip to <8 blocks loop + CMP $128, srcPtrLen + BLT startSingles + // There are at least 8 blocks to encrypt + TBZ $4, NR, octetsLoop + + // For AES-192 round keys occupy: K0 .. K7, K10, K11, K8, K9, KLAST + VMOV K8.B16, K10.B16 + VMOV K9.B16, K11.B16 + VMOV KLAST.B16, K8.B16 + VLD1.P 16(H0), [K9.B16] + VLD1.P 16(H0), [KLAST.B16] + TBZ $3, NR, octetsLoop + // For AES-256 round keys occupy: K0 .. K7, K10, K11, mem, mem, K8, K9, KLAST + VMOV KLAST.B16, K8.B16 + VLD1.P 16(H0), [K9.B16] + VLD1.P 16(H0), [KLAST.B16] + ADD $10*16, ks, H0 + MOVD H0, curK + +octetsLoop: + SUB $128, srcPtrLen + + VMOV CTR.B16, B0.B16 + VADD B0.S4, INC.S4, B1.S4 + VREV32 B0.B16, B0.B16 + VADD B1.S4, INC.S4, B2.S4 + VREV32 B1.B16, B1.B16 + VADD B2.S4, INC.S4, B3.S4 + VREV32 B2.B16, B2.B16 + VADD B3.S4, INC.S4, B4.S4 + VREV32 B3.B16, B3.B16 + VADD B4.S4, INC.S4, B5.S4 + VREV32 B4.B16, B4.B16 + VADD B5.S4, INC.S4, B6.S4 + VREV32 B5.B16, B5.B16 + VADD B6.S4, INC.S4, B7.S4 + VREV32 B6.B16, B6.B16 + VADD B7.S4, INC.S4, CTR.S4 + VREV32 B7.B16, B7.B16 + + aesrndx8(K0) + aesrndx8(K1) + aesrndx8(K2) + aesrndx8(K3) + aesrndx8(K4) + aesrndx8(K5) + aesrndx8(K6) + aesrndx8(K7) + TBZ $4, NR, octetsFinish + aesrndx8(K10) + aesrndx8(K11) + TBZ $3, NR, octetsFinish + VLD1.P 32(curK), [T1.B16, T2.B16] + aesrndx8(T1) + aesrndx8(T2) + MOVD H0, curK +octetsFinish: + aesrndx8(K8) + aesrndlastx8(K9) + + VEOR KLAST.B16, B0.B16, T1.B16 + VEOR KLAST.B16, B1.B16, T2.B16 + VEOR KLAST.B16, B2.B16, B2.B16 + VEOR KLAST.B16, B3.B16, B3.B16 + VEOR KLAST.B16, B4.B16, B4.B16 + VEOR KLAST.B16, B5.B16, B5.B16 + VEOR KLAST.B16, B6.B16, B6.B16 + VEOR KLAST.B16, B7.B16, B7.B16 + + VLD1.P 32(srcPtr), [B0.B16, B1.B16] + VEOR B0.B16, T1.B16, T1.B16 + VEOR B1.B16, T2.B16, T2.B16 + VST1.P [T1.B16, T2.B16], 32(dstPtr) + + VLD1.P 32(pTbl), [T1.B16, T2.B16] + VREV64 B0.B16, B0.B16 + VEOR ACC0.B16, B0.B16, B0.B16 + VEXT $8, B0.B16, B0.B16, T0.B16 + VEOR B0.B16, T0.B16, T0.B16 + VPMULL B0.D1, T1.D1, ACC1.Q1 + VPMULL2 B0.D2, T1.D2, ACC0.Q1 + VPMULL T0.D1, T2.D1, ACCM.Q1 + mulRound(B1) + + VLD1.P 32(srcPtr), [B0.B16, B1.B16] + VEOR B2.B16, B0.B16, T1.B16 + VEOR B3.B16, B1.B16, T2.B16 + VST1.P [T1.B16, T2.B16], 32(dstPtr) + mulRound(B0) + mulRound(B1) + + VLD1.P 32(srcPtr), [B0.B16, B1.B16] + VEOR B4.B16, B0.B16, T1.B16 + VEOR B5.B16, B1.B16, T2.B16 + VST1.P [T1.B16, T2.B16], 32(dstPtr) + mulRound(B0) + mulRound(B1) + + VLD1.P 32(srcPtr), [B0.B16, B1.B16] + VEOR B6.B16, B0.B16, T1.B16 + VEOR B7.B16, B1.B16, T2.B16 + VST1.P [T1.B16, T2.B16], 32(dstPtr) + mulRound(B0) + mulRound(B1) + + MOVD pTblSave, pTbl + reduce() + + CMP $128, srcPtrLen + BGE octetsLoop + +startSingles: + CBZ srcPtrLen, done + ADD $14*16, pTbl + // Preload H and its Karatsuba precomp + VLD1.P (pTbl), [T1.B16, T2.B16] + // Preload AES round keys + ADD $128, ks + VLD1.P 48(ks), [K8.B16, K9.B16, K10.B16] + VMOV K10.B16, KLAST.B16 + TBZ $4, NR, singlesLoop + VLD1.P 32(ks), [B1.B16, B2.B16] + VMOV B2.B16, KLAST.B16 + TBZ $3, NR, singlesLoop + VLD1.P 32(ks), [B3.B16, B4.B16] + VMOV B4.B16, KLAST.B16 + +singlesLoop: + CMP $16, srcPtrLen + BLT tail + SUB $16, srcPtrLen + + VLD1.P 16(srcPtr), [T0.B16] + VREV64 T0.B16, B5.B16 + VEOR KLAST.B16, T0.B16, T0.B16 + + VREV32 CTR.B16, B0.B16 + VADD CTR.S4, INC.S4, CTR.S4 + + AESE K0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K1.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K3.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K4.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K5.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K6.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K7.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K8.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K9.B16, B0.B16 + TBZ $4, NR, singlesLast + AESMC B0.B16, B0.B16 + AESE K10.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE B1.B16, B0.B16 + TBZ $3, NR, singlesLast + AESMC B0.B16, B0.B16 + AESE B2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE B3.B16, B0.B16 +singlesLast: + VEOR T0.B16, B0.B16, B0.B16 + + VST1.P [B0.B16], 16(dstPtr) + + VEOR ACC0.B16, B5.B16, B5.B16 + VEXT $8, B5.B16, B5.B16, T0.B16 + VEOR B5.B16, T0.B16, T0.B16 + VPMULL B5.D1, T1.D1, ACC1.Q1 + VPMULL2 B5.D2, T1.D2, ACC0.Q1 + VPMULL T0.D1, T2.D1, ACCM.Q1 + reduce() + + B singlesLoop +tail: + CBZ srcPtrLen, done + + VREV32 CTR.B16, B0.B16 + VADD CTR.S4, INC.S4, CTR.S4 + + AESE K0.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K1.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K3.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K4.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K5.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K6.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K7.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K8.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE K9.B16, B0.B16 + TBZ $4, NR, tailLast + AESMC B0.B16, B0.B16 + AESE K10.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE B1.B16, B0.B16 + TBZ $3, NR, tailLast + AESMC B0.B16, B0.B16 + AESE B2.B16, B0.B16 + AESMC B0.B16, B0.B16 + AESE B3.B16, B0.B16 +tailLast: + VEOR KLAST.B16, B0.B16, B0.B16 + + // Assuming it is safe to load past dstPtr due to the presence of the tag + VLD1 (srcPtr), [B5.B16] + + VEOR B5.B16, B0.B16, B0.B16 + + VEOR T3.B16, T3.B16, T3.B16 + MOVD $0, H1 + SUB $1, H1 + + TBZ $3, srcPtrLen, ld4 + VMOV B0.D[0], H0 + MOVD.P H0, 8(dstPtr) + VMOV H1, T3.D[0] + VEXT $8, ZERO.B16, B0.B16, B0.B16 +ld4: + TBZ $2, srcPtrLen, ld2 + VMOV B0.S[0], H0 + MOVW.P H0, 4(dstPtr) + VEXT $12, T3.B16, ZERO.B16, T3.B16 + VMOV H1, T3.S[0] + VEXT $4, ZERO.B16, B0.B16, B0.B16 +ld2: + TBZ $1, srcPtrLen, ld1 + VMOV B0.H[0], H0 + MOVH.P H0, 2(dstPtr) + VEXT $14, T3.B16, ZERO.B16, T3.B16 + VMOV H1, T3.H[0] + VEXT $2, ZERO.B16, B0.B16, B0.B16 +ld1: + TBZ $0, srcPtrLen, ld0 + VMOV B0.B[0], H0 + MOVB.P H0, 1(dstPtr) + VEXT $15, T3.B16, ZERO.B16, T3.B16 + VMOV H1, T3.B[0] +ld0: + + VAND T3.B16, B5.B16, B5.B16 + VREV64 B5.B16, B5.B16 + + VEOR ACC0.B16, B5.B16, B5.B16 + VEXT $8, B5.B16, B5.B16, T0.B16 + VEOR B5.B16, T0.B16, T0.B16 + VPMULL B5.D1, T1.D1, ACC1.Q1 + VPMULL2 B5.D2, T1.D2, ACC0.Q1 + VPMULL T0.D1, T2.D1, ACCM.Q1 + reduce() +done: + VST1 [ACC0.B16], (tPtr) + + RET diff --git a/src/crypto/aes/gcm_ppc64le.go b/src/crypto/aes/gcm_ppc64le.go new file mode 100644 index 0000000..01b4e08 --- /dev/null +++ b/src/crypto/aes/gcm_ppc64le.go @@ -0,0 +1,258 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ppc64le +// +build ppc64le + +package aes + +import ( + "crypto/cipher" + "crypto/subtle" + "encoding/binary" + "errors" +) + +// This file implements GCM using an optimized GHASH function. + +//go:noescape +func gcmInit(productTable *[256]byte, h []byte) + +//go:noescape +func gcmHash(output []byte, productTable *[256]byte, inp []byte, len int) + +//go:noescape +func gcmMul(output []byte, productTable *[256]byte) + +const ( + gcmCounterSize = 16 + gcmBlockSize = 16 + gcmTagSize = 16 + gcmStandardNonceSize = 12 +) + +var errOpen = errors.New("cipher: message authentication failed") + +// Assert that aesCipherGCM implements the gcmAble interface. +var _ gcmAble = (*aesCipherAsm)(nil) + +type gcmAsm struct { + cipher *aesCipherAsm + // ks is the key schedule, the length of which depends on the size of + // the AES key. + ks []uint32 + // productTable contains pre-computed multiples of the binary-field + // element used in GHASH. + productTable [256]byte + // nonceSize contains the expected size of the nonce, in bytes. + nonceSize int + // tagSize contains the size of the tag, in bytes. + tagSize int +} + +// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only +// called by crypto/cipher.NewGCM via the gcmAble interface. +func (c *aesCipherAsm) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { + g := &gcmAsm{cipher: c, ks: c.enc, nonceSize: nonceSize, tagSize: tagSize} + + hle := make([]byte, gcmBlockSize) + c.Encrypt(hle, hle) + + // Reverse the bytes in each 8 byte chunk + // Load little endian, store big endian + h1 := binary.LittleEndian.Uint64(hle[:8]) + h2 := binary.LittleEndian.Uint64(hle[8:]) + binary.BigEndian.PutUint64(hle[:8], h1) + binary.BigEndian.PutUint64(hle[8:], h2) + gcmInit(&g.productTable, hle) + + return g, nil +} + +func (g *gcmAsm) NonceSize() int { + return g.nonceSize +} + +func (g *gcmAsm) Overhead() int { + return g.tagSize +} + +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +// deriveCounter computes the initial GCM counter state from the given nonce. +func (g *gcmAsm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) { + if len(nonce) == gcmStandardNonceSize { + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + var hash [16]byte + g.paddedGHASH(&hash, nonce) + lens := gcmLengths(0, uint64(len(nonce))*8) + g.paddedGHASH(&hash, lens[:]) + copy(counter[:], hash[:]) + } +} + +// counterCrypt encrypts in using AES in counter mode and places the result +// into out. counter is the initial count value and will be updated with the next +// count value. The length of out must be greater than or equal to the length +// of in. +func (g *gcmAsm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { + var mask [gcmBlockSize]byte + + for len(in) >= gcmBlockSize { + // Hint to avoid bounds check + _, _ = in[15], out[15] + g.cipher.Encrypt(mask[:], counter[:]) + gcmInc32(counter) + + // XOR 16 bytes each loop iteration in 8 byte chunks + in0 := binary.LittleEndian.Uint64(in[0:]) + in1 := binary.LittleEndian.Uint64(in[8:]) + m0 := binary.LittleEndian.Uint64(mask[:8]) + m1 := binary.LittleEndian.Uint64(mask[8:]) + binary.LittleEndian.PutUint64(out[:8], in0^m0) + binary.LittleEndian.PutUint64(out[8:], in1^m1) + out = out[16:] + in = in[16:] + } + + if len(in) > 0 { + g.cipher.Encrypt(mask[:], counter[:]) + gcmInc32(counter) + // XOR leftover bytes + for i, inb := range in { + out[i] = inb ^ mask[i] + } + } +} + +// increments the rightmost 32-bits of the count value by 1. +func gcmInc32(counterBlock *[16]byte) { + c := counterBlock[len(counterBlock)-4:] + x := binary.BigEndian.Uint32(c) + 1 + binary.BigEndian.PutUint32(c, x) +} + +// paddedGHASH pads data with zeroes until its length is a multiple of +// 16-bytes. It then calculates a new value for hash using the ghash +// algorithm. +func (g *gcmAsm) paddedGHASH(hash *[16]byte, data []byte) { + if siz := len(data) - (len(data) % gcmBlockSize); siz > 0 { + gcmHash(hash[:], &g.productTable, data[:], siz) + data = data[siz:] + } + if len(data) > 0 { + var s [16]byte + copy(s[:], data) + gcmHash(hash[:], &g.productTable, s[:], len(s)) + } +} + +// auth calculates GHASH(ciphertext, additionalData), masks the result with +// tagMask and writes the result to out. +func (g *gcmAsm) auth(out, ciphertext, aad []byte, tagMask *[gcmTagSize]byte) { + var hash [16]byte + g.paddedGHASH(&hash, aad) + g.paddedGHASH(&hash, ciphertext) + lens := gcmLengths(uint64(len(aad))*8, uint64(len(ciphertext))*8) + g.paddedGHASH(&hash, lens[:]) + + copy(out, hash[:]) + for i := range out { + out[i] ^= tagMask[i] + } +} + +// Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for +// details. +func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != g.nonceSize { + panic("cipher: incorrect nonce length given to GCM") + } + if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { + panic("cipher: message too large for GCM") + } + + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + + var counter, tagMask [gcmBlockSize]byte + g.deriveCounter(&counter, nonce) + + g.cipher.Encrypt(tagMask[:], counter[:]) + gcmInc32(&counter) + + g.counterCrypt(out, plaintext, &counter) + g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask) + + return ret +} + +// Open authenticates and decrypts ciphertext. See the cipher.AEAD interface +// for details. +func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + if len(nonce) != g.nonceSize { + panic("cipher: incorrect nonce length given to GCM") + } + if len(ciphertext) < g.tagSize { + return nil, errOpen + } + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { + return nil, errOpen + } + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + var counter, tagMask [gcmBlockSize]byte + g.deriveCounter(&counter, nonce) + + g.cipher.Encrypt(tagMask[:], counter[:]) + gcmInc32(&counter) + + var expectedTag [gcmTagSize]byte + g.auth(expectedTag[:], ciphertext, data, &tagMask) + + ret, out := sliceForAppend(dst, len(ciphertext)) + + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + for i := range out { + out[i] = 0 + } + return nil, errOpen + } + + g.counterCrypt(out, ciphertext, &counter) + return ret, nil +} + +func gcmLengths(len0, len1 uint64) [16]byte { + return [16]byte{ + byte(len0 >> 56), + byte(len0 >> 48), + byte(len0 >> 40), + byte(len0 >> 32), + byte(len0 >> 24), + byte(len0 >> 16), + byte(len0 >> 8), + byte(len0), + byte(len1 >> 56), + byte(len1 >> 48), + byte(len1 >> 40), + byte(len1 >> 32), + byte(len1 >> 24), + byte(len1 >> 16), + byte(len1 >> 8), + byte(len1), + } +} diff --git a/src/crypto/aes/gcm_ppc64le.s b/src/crypto/aes/gcm_ppc64le.s new file mode 100644 index 0000000..3945fc9 --- /dev/null +++ b/src/crypto/aes/gcm_ppc64le.s @@ -0,0 +1,563 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on CRYPTOGAMS code with the following comment: +// # ==================================================================== +// # Written by Andy Polyakov for the OpenSSL +// # project. The module is, however, dual licensed under OpenSSL and +// # CRYPTOGAMS licenses depending on where you obtain it. For further +// # details see http://www.openssl.org/~appro/cryptogams/. +// # ==================================================================== + +// This implementation is based on the ppc64 asm generated by the +// script https://github.com/dot-asm/cryptogams/blob/master/ppc/ghashp8-ppc.pl +// from commit d47afb3c. + +// Changes were made due to differences in the ABI and some register usage. +// Some arguments were changed due to the way the Go code passes them. + +#include "textflag.h" + +#define XIP R3 +#define HTBL R4 +#define INP R5 +#define LEN R6 + +#define XL V0 +#define XM V1 +#define XH V2 +#define IN V3 +#define ZERO V4 +#define T0 V5 +#define T1 V6 +#define T2 V7 +#define XC2 V8 +#define H V9 +#define HH V10 +#define HL V11 +#define LEMASK V12 +#define XL1 V13 +#define XM1 V14 +#define XH1 V15 +#define IN1 V16 +#define H2 V17 +#define H2H V18 +#define H2L V19 +#define XL3 V20 +#define XM2 V21 +#define IN2 V22 +#define H3L V23 +#define H3 V24 +#define H3H V25 +#define XH3 V26 +#define XM3 V27 +#define IN3 V28 +#define H4L V29 +#define H4 V30 +#define H4H V31 + +#define IN0 IN +#define H21L HL +#define H21H HH +#define LOPERM H2L +#define HIPERM H2H + +#define VXL VS32 +#define VIN VS35 +#define VXC2 VS40 +#define VH VS41 +#define VHH VS42 +#define VHL VS43 +#define VIN1 VS48 +#define VH2 VS49 +#define VH2H VS50 +#define VH2L VS51 + +#define VIN2 VS54 +#define VH3L VS55 +#define VH3 VS56 +#define VH3H VS57 +#define VIN3 VS60 +#define VH4L VS61 +#define VH4 VS62 +#define VH4H VS63 + +#define VIN0 VIN + +// func gcmInit(productTable *[256]byte, h []byte) +TEXT ·gcmInit(SB), NOSPLIT, $0-32 + MOVD productTable+0(FP), XIP + MOVD h+8(FP), HTBL + + MOVD $0x10, R8 + MOVD $0x20, R9 + MOVD $0x30, R10 + LXVD2X (HTBL)(R0), VH // Load H + + VSPLTISB $-16, XC2 // 0xf0 + VSPLTISB $1, T0 // one + VADDUBM XC2, XC2, XC2 // 0xe0 + VXOR ZERO, ZERO, ZERO + VOR XC2, T0, XC2 // 0xe1 + VSLDOI $15, XC2, ZERO, XC2 // 0xe1... + VSLDOI $1, ZERO, T0, T1 // ...1 + VADDUBM XC2, XC2, XC2 // 0xc2... + VSPLTISB $7, T2 + VOR XC2, T1, XC2 // 0xc2....01 + VSPLTB $0, H, T1 // most significant byte + VSL H, T0, H // H<<=1 + VSRAB T1, T2, T1 // broadcast carry bit + VAND T1, XC2, T1 + VXOR H, T1, IN // twisted H + + VSLDOI $8, IN, IN, H // twist even more ... + VSLDOI $8, ZERO, XC2, XC2 // 0xc2.0 + VSLDOI $8, ZERO, H, HL // ... and split + VSLDOI $8, H, ZERO, HH + + STXVD2X VXC2, (XIP+R0) // save pre-computed table + STXVD2X VHL, (XIP+R8) + MOVD $0x40, R8 + STXVD2X VH, (XIP+R9) + MOVD $0x50, R9 + STXVD2X VHH, (XIP+R10) + MOVD $0x60, R10 + + VPMSUMD IN, HL, XL // H.lo·H.lo + VPMSUMD IN, H, XM // H.hi·H.lo+H.lo·H.hi + VPMSUMD IN, HH, XH // H.hi·H.hi + + VPMSUMD XL, XC2, T2 // 1st reduction phase + + VSLDOI $8, XM, ZERO, T0 + VSLDOI $8, ZERO, XM, T1 + VXOR XL, T0, XL + VXOR XH, T1, XH + + VSLDOI $8, XL, XL, XL + VXOR XL, T2, XL + + VSLDOI $8, XL, XL, T1 // 2nd reduction phase + VPMSUMD XL, XC2, XL + VXOR T1, XH, T1 + VXOR XL, T1, IN1 + + VSLDOI $8, IN1, IN1, H2 + VSLDOI $8, ZERO, H2, H2L + VSLDOI $8, H2, ZERO, H2H + + STXVD2X VH2L, (XIP+R8) // save H^2 + MOVD $0x70, R8 + STXVD2X VH2, (XIP+R9) + MOVD $0x80, R9 + STXVD2X VH2H, (XIP+R10) + MOVD $0x90, R10 + + VPMSUMD IN, H2L, XL // H.lo·H^2.lo + VPMSUMD IN1, H2L, XL1 // H^2.lo·H^2.lo + VPMSUMD IN, H2, XM // H.hi·H^2.lo+H.lo·H^2.hi + VPMSUMD IN1, H2, XM1 // H^2.hi·H^2.lo+H^2.lo·H^2.hi + VPMSUMD IN, H2H, XH // H.hi·H^2.hi + VPMSUMD IN1, H2H, XH1 // H^2.hi·H^2.hi + + VPMSUMD XL, XC2, T2 // 1st reduction phase + VPMSUMD XL1, XC2, HH // 1st reduction phase + + VSLDOI $8, XM, ZERO, T0 + VSLDOI $8, ZERO, XM, T1 + VSLDOI $8, XM1, ZERO, HL + VSLDOI $8, ZERO, XM1, H + VXOR XL, T0, XL + VXOR XH, T1, XH + VXOR XL1, HL, XL1 + VXOR XH1, H, XH1 + + VSLDOI $8, XL, XL, XL + VSLDOI $8, XL1, XL1, XL1 + VXOR XL, T2, XL + VXOR XL1, HH, XL1 + + VSLDOI $8, XL, XL, T1 // 2nd reduction phase + VSLDOI $8, XL1, XL1, H // 2nd reduction phase + VPMSUMD XL, XC2, XL + VPMSUMD XL1, XC2, XL1 + VXOR T1, XH, T1 + VXOR H, XH1, H + VXOR XL, T1, XL + VXOR XL1, H, XL1 + + VSLDOI $8, XL, XL, H + VSLDOI $8, XL1, XL1, H2 + VSLDOI $8, ZERO, H, HL + VSLDOI $8, H, ZERO, HH + VSLDOI $8, ZERO, H2, H2L + VSLDOI $8, H2, ZERO, H2H + + STXVD2X VHL, (XIP+R8) // save H^3 + MOVD $0xa0, R8 + STXVD2X VH, (XIP+R9) + MOVD $0xb0, R9 + STXVD2X VHH, (XIP+R10) + MOVD $0xc0, R10 + STXVD2X VH2L, (XIP+R8) // save H^4 + STXVD2X VH2, (XIP+R9) + STXVD2X VH2H, (XIP+R10) + + RET + +// func gcmHash(output []byte, productTable *[256]byte, inp []byte, len int) +TEXT ·gcmHash(SB), NOSPLIT, $0-64 + MOVD output+0(FP), XIP + MOVD productTable+24(FP), HTBL + MOVD inp+32(FP), INP + MOVD len+56(FP), LEN + + MOVD $0x10, R8 + MOVD $0x20, R9 + MOVD $0x30, R10 + LXVD2X (XIP)(R0), VXL // load Xi + + LXVD2X (HTBL)(R8), VHL // load pre-computed table + MOVD $0x40, R8 + LVSL (R0)(R0), LEMASK + LXVD2X (HTBL)(R9), VH + MOVD $0x50, R9 + VSPLTISB $0x07, T0 + LXVD2X (HTBL)(R10), VHH + MOVD $0x60, R10 + VXOR LEMASK, T0, LEMASK + LXVD2X (HTBL)(R0), VXC2 + VPERM XL, XL, LEMASK, XL + VXOR ZERO, ZERO, ZERO + + CMPU LEN, $64 + BGE gcm_ghash_p8_4x + + LXVD2X (INP)(R0), VIN + ADD $16, INP, INP + SUBCCC $16, LEN, LEN + VPERM IN, IN, LEMASK, IN + VXOR IN, XL, IN + BEQ short + + LXVD2X (HTBL)(R8), VH2L // load H^2 + MOVD $16, R8 + LXVD2X (HTBL)(R9), VH2 + ADD LEN, INP, R9 // end of input + LXVD2X (HTBL)(R10), VH2H + +loop_2x: + LXVD2X (INP)(R0), VIN1 + VPERM IN1, IN1, LEMASK, IN1 + + SUBC $32, LEN, LEN + VPMSUMD IN, H2L, XL // H^2.lo·Xi.lo + VPMSUMD IN1, HL, XL1 // H.lo·Xi+1.lo + SUBE R11, R11, R11 // borrow?-1:0 + VPMSUMD IN, H2, XM // H^2.hi·Xi.lo+H^2.lo·Xi.hi + VPMSUMD IN1, H, XM1 // H.hi·Xi+1.lo+H.lo·Xi+1.hi + AND LEN, R11, R11 + VPMSUMD IN, H2H, XH // H^2.hi·Xi.hi + VPMSUMD IN1, HH, XH1 // H.hi·Xi+1.hi + ADD R11, INP, INP + + VXOR XL, XL1, XL + VXOR XM, XM1, XM + + VPMSUMD XL, XC2, T2 // 1st reduction phase + + VSLDOI $8, XM, ZERO, T0 + VSLDOI $8, ZERO, XM, T1 + VXOR XH, XH1, XH + VXOR XL, T0, XL + VXOR XH, T1, XH + + VSLDOI $8, XL, XL, XL + VXOR XL, T2, XL + LXVD2X (INP)(R8), VIN + ADD $32, INP, INP + + VSLDOI $8, XL, XL, T1 // 2nd reduction phase + VPMSUMD XL, XC2, XL + VPERM IN, IN, LEMASK, IN + VXOR T1, XH, T1 + VXOR IN, T1, IN + VXOR IN, XL, IN + CMP R9, INP + BGT loop_2x // done yet? + + CMPWU LEN, $0 + BNE even + +short: + VPMSUMD IN, HL, XL // H.lo·Xi.lo + VPMSUMD IN, H, XM // H.hi·Xi.lo+H.lo·Xi.hi + VPMSUMD IN, HH, XH // H.hi·Xi.hi + + VPMSUMD XL, XC2, T2 // 1st reduction phase + + VSLDOI $8, XM, ZERO, T0 + VSLDOI $8, ZERO, XM, T1 + VXOR XL, T0, XL + VXOR XH, T1, XH + + VSLDOI $8, XL, XL, XL + VXOR XL, T2, XL + + VSLDOI $8, XL, XL, T1 // 2nd reduction phase + VPMSUMD XL, XC2, XL + VXOR T1, XH, T1 + +even: + VXOR XL, T1, XL + VPERM XL, XL, LEMASK, XL + STXVD2X VXL, (XIP+R0) + + OR R12, R12, R12 // write out Xi + RET + +gcm_ghash_p8_4x: + LVSL (R8)(R0), T0 // 0x0001..0e0f + MOVD $0x70, R8 + LXVD2X (HTBL)(R9), VH2 + MOVD $0x80, R9 + VSPLTISB $8, T1 // 0x0808..0808 + MOVD $0x90, R10 + LXVD2X (HTBL)(R8), VH3L // load H^3 + MOVD $0xa0, R8 + LXVD2X (HTBL)(R9), VH3 + MOVD $0xb0, R9 + LXVD2X (HTBL)(R10), VH3H + MOVD $0xc0, R10 + LXVD2X (HTBL)(R8), VH4L // load H^4 + MOVD $0x10, R8 + LXVD2X (HTBL)(R9), VH4 + MOVD $0x20, R9 + LXVD2X (HTBL)(R10), VH4H + MOVD $0x30, R10 + + VSLDOI $8, ZERO, T1, T2 // 0x0000..0808 + VADDUBM T0, T2, HIPERM // 0x0001..1617 + VADDUBM T1, HIPERM, LOPERM // 0x0809..1e1f + + SRD $4, LEN, LEN // this allows to use sign bit as carry + + LXVD2X (INP)(R0), VIN0 // load input + LXVD2X (INP)(R8), VIN1 + SUBCCC $8, LEN, LEN + LXVD2X (INP)(R9), VIN2 + LXVD2X (INP)(R10), VIN3 + ADD $0x40, INP, INP + VPERM IN0, IN0, LEMASK, IN0 + VPERM IN1, IN1, LEMASK, IN1 + VPERM IN2, IN2, LEMASK, IN2 + VPERM IN3, IN3, LEMASK, IN3 + + VXOR IN0, XL, XH + + VPMSUMD IN1, H3L, XL1 + VPMSUMD IN1, H3, XM1 + VPMSUMD IN1, H3H, XH1 + + VPERM H2, H, HIPERM, H21L + VPERM IN2, IN3, LOPERM, T0 + VPERM H2, H, LOPERM, H21H + VPERM IN2, IN3, HIPERM, T1 + VPMSUMD IN2, H2, XM2 // H^2.lo·Xi+2.hi+H^2.hi·Xi+2.lo + VPMSUMD T0, H21L, XL3 // H^2.lo·Xi+2.lo+H.lo·Xi+3.lo + VPMSUMD IN3, H, XM3 // H.hi·Xi+3.lo +H.lo·Xi+3.hi + VPMSUMD T1, H21H, XH3 // H^2.hi·Xi+2.hi+H.hi·Xi+3.hi + + VXOR XM2, XM1, XM2 + VXOR XL3, XL1, XL3 + VXOR XM3, XM2, XM3 + VXOR XH3, XH1, XH3 + + BLT tail_4x + +loop_4x: + LXVD2X (INP)(R0), VIN0 + LXVD2X (INP)(R8), VIN1 + SUBCCC $4, LEN, LEN + LXVD2X (INP)(R9), VIN2 + LXVD2X (INP)(R10), VIN3 + ADD $0x40, INP, INP + VPERM IN1, IN1, LEMASK, IN1 + VPERM IN2, IN2, LEMASK, IN2 + VPERM IN3, IN3, LEMASK, IN3 + VPERM IN0, IN0, LEMASK, IN0 + + VPMSUMD XH, H4L, XL // H^4.lo·Xi.lo + VPMSUMD XH, H4, XM // H^4.hi·Xi.lo+H^4.lo·Xi.hi + VPMSUMD XH, H4H, XH // H^4.hi·Xi.hi + VPMSUMD IN1, H3L, XL1 + VPMSUMD IN1, H3, XM1 + VPMSUMD IN1, H3H, XH1 + + VXOR XL, XL3, XL + VXOR XM, XM3, XM + VXOR XH, XH3, XH + VPERM IN2, IN3, LOPERM, T0 + VPERM IN2, IN3, HIPERM, T1 + + VPMSUMD XL, XC2, T2 // 1st reduction phase + VPMSUMD T0, H21L, XL3 // H.lo·Xi+3.lo +H^2.lo·Xi+2.lo + VPMSUMD T1, H21H, XH3 // H.hi·Xi+3.hi +H^2.hi·Xi+2.hi + + VSLDOI $8, XM, ZERO, T0 + VSLDOI $8, ZERO, XM, T1 + VXOR XL, T0, XL + VXOR XH, T1, XH + + VSLDOI $8, XL, XL, XL + VXOR XL, T2, XL + + VSLDOI $8, XL, XL, T1 // 2nd reduction phase + VPMSUMD IN2, H2, XM2 // H^2.hi·Xi+2.lo+H^2.lo·Xi+2.hi + VPMSUMD IN3, H, XM3 // H.hi·Xi+3.lo +H.lo·Xi+3.hi + VPMSUMD XL, XC2, XL + + VXOR XL3, XL1, XL3 + VXOR XH3, XH1, XH3 + VXOR XH, IN0, XH + VXOR XM2, XM1, XM2 + VXOR XH, T1, XH + VXOR XM3, XM2, XM3 + VXOR XH, XL, XH + BGE loop_4x + +tail_4x: + VPMSUMD XH, H4L, XL // H^4.lo·Xi.lo + VPMSUMD XH, H4, XM // H^4.hi·Xi.lo+H^4.lo·Xi.hi + VPMSUMD XH, H4H, XH // H^4.hi·Xi.hi + + VXOR XL, XL3, XL + VXOR XM, XM3, XM + + VPMSUMD XL, XC2, T2 // 1st reduction phase + + VSLDOI $8, XM, ZERO, T0 + VSLDOI $8, ZERO, XM, T1 + VXOR XH, XH3, XH + VXOR XL, T0, XL + VXOR XH, T1, XH + + VSLDOI $8, XL, XL, XL + VXOR XL, T2, XL + + VSLDOI $8, XL, XL, T1 // 2nd reduction phase + VPMSUMD XL, XC2, XL + VXOR T1, XH, T1 + VXOR XL, T1, XL + + ADDCCC $4, LEN, LEN + BEQ done_4x + + LXVD2X (INP)(R0), VIN0 + CMPU LEN, $2 + MOVD $-4, LEN + BLT one + LXVD2X (INP)(R8), VIN1 + BEQ two + +three: + LXVD2X (INP)(R9), VIN2 + VPERM IN0, IN0, LEMASK, IN0 + VPERM IN1, IN1, LEMASK, IN1 + VPERM IN2, IN2, LEMASK, IN2 + + VXOR IN0, XL, XH + VOR H3L, H3L, H4L + VOR H3, H3, H4 + VOR H3H, H3H, H4H + + VPERM IN1, IN2, LOPERM, T0 + VPERM IN1, IN2, HIPERM, T1 + VPMSUMD IN1, H2, XM2 // H^2.lo·Xi+1.hi+H^2.hi·Xi+1.lo + VPMSUMD IN2, H, XM3 // H.hi·Xi+2.lo +H.lo·Xi+2.hi + VPMSUMD T0, H21L, XL3 // H^2.lo·Xi+1.lo+H.lo·Xi+2.lo + VPMSUMD T1, H21H, XH3 // H^2.hi·Xi+1.hi+H.hi·Xi+2.hi + + VXOR XM3, XM2, XM3 + JMP tail_4x + +two: + VPERM IN0, IN0, LEMASK, IN0 + VPERM IN1, IN1, LEMASK, IN1 + + VXOR IN, XL, XH + VPERM ZERO, IN1, LOPERM, T0 + VPERM ZERO, IN1, HIPERM, T1 + + VSLDOI $8, ZERO, H2, H4L + VOR H2, H2, H4 + VSLDOI $8, H2, ZERO, H4H + + VPMSUMD T0, H21L, XL3 // H.lo·Xi+1.lo + VPMSUMD IN1, H, XM3 // H.hi·Xi+1.lo+H.lo·Xi+2.hi + VPMSUMD T1, H21H, XH3 // H.hi·Xi+1.hi + + JMP tail_4x + +one: + VPERM IN0, IN0, LEMASK, IN0 + + VSLDOI $8, ZERO, H, H4L + VOR H, H, H4 + VSLDOI $8, H, ZERO, H4H + + VXOR IN0, XL, XH + VXOR XL3, XL3, XL3 + VXOR XM3, XM3, XM3 + VXOR XH3, XH3, XH3 + + JMP tail_4x + +done_4x: + VPERM XL, XL, LEMASK, XL + STXVD2X VXL, (XIP+R0) // write out Xi + RET + +// func gcmMul(output []byte, productTable *[256]byte) +TEXT ·gcmMul(SB), NOSPLIT, $0-32 + MOVD output+0(FP), XIP + MOVD productTable+24(FP), HTBL + + MOVD $0x10, R8 + MOVD $0x20, R9 + MOVD $0x30, R10 + LXVD2X (XIP)(R0), VIN // load Xi + + LXVD2X (HTBL)(R8), VHL // Load pre-computed table + LVSL (R0)(R0), LEMASK + LXVD2X (HTBL)(R9), VH + VSPLTISB $0x07, T0 + LXVD2X (HTBL)(R10), VHH + VXOR LEMASK, T0, LEMASK + LXVD2X (HTBL)(R0), VXC2 + VPERM IN, IN, LEMASK, IN + VXOR ZERO, ZERO, ZERO + + VPMSUMD IN, HL, XL // H.lo·Xi.lo + VPMSUMD IN, H, XM // H.hi·Xi.lo+H.lo·Xi.hi + VPMSUMD IN, HH, XH // H.hi·Xi.hi + + VPMSUMD XL, XC2, T2 // 1st reduction phase + + VSLDOI $8, XM, ZERO, T0 + VSLDOI $8, ZERO, XM, T1 + VXOR XL, T0, XL + VXOR XH, T1, XH + + VSLDOI $8, XL, XL, XL + VXOR XL, T2, XL + + VSLDOI $8, XL, XL, T1 // 2nd reduction phase + VPMSUMD XL, XC2, XL + VXOR T1, XH, T1 + VXOR XL, T1, XL + + VPERM XL, XL, LEMASK, XL + STXVD2X VXL, (XIP+R0) // write out Xi + RET diff --git a/src/crypto/aes/gcm_s390x.go b/src/crypto/aes/gcm_s390x.go new file mode 100644 index 0000000..c58aa2c --- /dev/null +++ b/src/crypto/aes/gcm_s390x.go @@ -0,0 +1,368 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "crypto/cipher" + subtleoverlap "crypto/internal/subtle" + "crypto/subtle" + "encoding/binary" + "errors" + "internal/cpu" +) + +// This file contains two implementations of AES-GCM. The first implementation +// (gcmAsm) uses the KMCTR instruction to encrypt using AES in counter mode and +// the KIMD instruction for GHASH. The second implementation (gcmKMA) uses the +// newer KMA instruction which performs both operations. + +// gcmCount represents a 16-byte big-endian count value. +type gcmCount [16]byte + +// inc increments the rightmost 32-bits of the count value by 1. +func (x *gcmCount) inc() { + binary.BigEndian.PutUint32(x[len(x)-4:], binary.BigEndian.Uint32(x[len(x)-4:])+1) +} + +// gcmLengths writes len0 || len1 as big-endian values to a 16-byte array. +func gcmLengths(len0, len1 uint64) [16]byte { + v := [16]byte{} + binary.BigEndian.PutUint64(v[0:], len0) + binary.BigEndian.PutUint64(v[8:], len1) + return v +} + +// gcmHashKey represents the 16-byte hash key required by the GHASH algorithm. +type gcmHashKey [16]byte + +type gcmAsm struct { + block *aesCipherAsm + hashKey gcmHashKey + nonceSize int + tagSize int +} + +const ( + gcmBlockSize = 16 + gcmTagSize = 16 + gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. + gcmStandardNonceSize = 12 +) + +var errOpen = errors.New("cipher: message authentication failed") + +// Assert that aesCipherAsm implements the gcmAble interface. +var _ gcmAble = (*aesCipherAsm)(nil) + +// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only +// called by crypto/cipher.NewGCM via the gcmAble interface. +func (c *aesCipherAsm) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { + var hk gcmHashKey + c.Encrypt(hk[:], hk[:]) + g := gcmAsm{ + block: c, + hashKey: hk, + nonceSize: nonceSize, + tagSize: tagSize, + } + if cpu.S390X.HasAESGCM { + g := gcmKMA{g} + return &g, nil + } + return &g, nil +} + +func (g *gcmAsm) NonceSize() int { + return g.nonceSize +} + +func (g *gcmAsm) Overhead() int { + return g.tagSize +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +// ghash uses the GHASH algorithm to hash data with the given key. The initial +// hash value is given by hash which will be updated with the new hash value. +// The length of data must be a multiple of 16-bytes. +//go:noescape +func ghash(key *gcmHashKey, hash *[16]byte, data []byte) + +// paddedGHASH pads data with zeroes until its length is a multiple of +// 16-bytes. It then calculates a new value for hash using the GHASH algorithm. +func (g *gcmAsm) paddedGHASH(hash *[16]byte, data []byte) { + siz := len(data) &^ 0xf // align size to 16-bytes + if siz > 0 { + ghash(&g.hashKey, hash, data[:siz]) + data = data[siz:] + } + if len(data) > 0 { + var s [16]byte + copy(s[:], data) + ghash(&g.hashKey, hash, s[:]) + } +} + +// cryptBlocksGCM encrypts src using AES in counter mode using the given +// function code and key. The rightmost 32-bits of the counter are incremented +// between each block as required by the GCM spec. The initial counter value +// is given by cnt, which is updated with the value of the next counter value +// to use. +// +// The lengths of both dst and buf must be greater than or equal to the length +// of src. buf may be partially or completely overwritten during the execution +// of the function. +//go:noescape +func cryptBlocksGCM(fn code, key, dst, src, buf []byte, cnt *gcmCount) + +// counterCrypt encrypts src using AES in counter mode and places the result +// into dst. cnt is the initial count value and will be updated with the next +// count value. The length of dst must be greater than or equal to the length +// of src. +func (g *gcmAsm) counterCrypt(dst, src []byte, cnt *gcmCount) { + // Copying src into a buffer improves performance on some models when + // src and dst point to the same underlying array. We also need a + // buffer for counter values. + var ctrbuf, srcbuf [2048]byte + for len(src) >= 16 { + siz := len(src) + if len(src) > len(ctrbuf) { + siz = len(ctrbuf) + } + siz &^= 0xf // align siz to 16-bytes + copy(srcbuf[:], src[:siz]) + cryptBlocksGCM(g.block.function, g.block.key, dst[:siz], srcbuf[:siz], ctrbuf[:], cnt) + src = src[siz:] + dst = dst[siz:] + } + if len(src) > 0 { + var x [16]byte + g.block.Encrypt(x[:], cnt[:]) + for i := range src { + dst[i] = src[i] ^ x[i] + } + cnt.inc() + } +} + +// deriveCounter computes the initial GCM counter state from the given nonce. +// See NIST SP 800-38D, section 7.1. +func (g *gcmAsm) deriveCounter(nonce []byte) gcmCount { + // GCM has two modes of operation with respect to the initial counter + // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path" + // for nonces of other lengths. For a 96-bit nonce, the nonce, along + // with a four-byte big-endian counter starting at one, is used + // directly as the starting counter. For other nonce sizes, the counter + // is computed by passing it through the GHASH function. + var counter gcmCount + if len(nonce) == gcmStandardNonceSize { + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + var hash [16]byte + g.paddedGHASH(&hash, nonce) + lens := gcmLengths(0, uint64(len(nonce))*8) + g.paddedGHASH(&hash, lens[:]) + copy(counter[:], hash[:]) + } + return counter +} + +// auth calculates GHASH(ciphertext, additionalData), masks the result with +// tagMask and writes the result to out. +func (g *gcmAsm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) { + var hash [16]byte + g.paddedGHASH(&hash, additionalData) + g.paddedGHASH(&hash, ciphertext) + lens := gcmLengths(uint64(len(additionalData))*8, uint64(len(ciphertext))*8) + g.paddedGHASH(&hash, lens[:]) + + copy(out, hash[:]) + for i := range out { + out[i] ^= tagMask[i] + } +} + +// Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for +// details. +func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { + panic("crypto/cipher: message too large for GCM") + } + + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) { + panic("crypto/cipher: invalid buffer overlap") + } + + counter := g.deriveCounter(nonce) + + var tagMask [gcmBlockSize]byte + g.block.Encrypt(tagMask[:], counter[:]) + counter.inc() + + var tagOut [gcmTagSize]byte + g.counterCrypt(out, plaintext, &counter) + g.auth(tagOut[:], out[:len(plaintext)], data, &tagMask) + copy(out[len(plaintext):], tagOut[:]) + + return ret +} + +// Open authenticates and decrypts ciphertext. See the cipher.AEAD interface +// for details. +func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + // Sanity check to prevent the authentication from always succeeding if an implementation + // leaves tagSize uninitialized, for example. + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") + } + if len(ciphertext) < g.tagSize { + return nil, errOpen + } + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { + return nil, errOpen + } + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + counter := g.deriveCounter(nonce) + + var tagMask [gcmBlockSize]byte + g.block.Encrypt(tagMask[:], counter[:]) + counter.inc() + + var expectedTag [gcmTagSize]byte + g.auth(expectedTag[:], ciphertext, data, &tagMask) + + ret, out := sliceForAppend(dst, len(ciphertext)) + if subtleoverlap.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap") + } + + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + // The AESNI code decrypts and authenticates concurrently, and + // so overwrites dst in the event of a tag mismatch. That + // behavior is mimicked here in order to be consistent across + // platforms. + for i := range out { + out[i] = 0 + } + return nil, errOpen + } + + g.counterCrypt(out, ciphertext, &counter) + return ret, nil +} + +// gcmKMA implements the cipher.AEAD interface using the KMA instruction. It should +// only be used if hasKMA is true. +type gcmKMA struct { + gcmAsm +} + +// flags for the KMA instruction +const ( + kmaHS = 1 << 10 // hash subkey supplied + kmaLAAD = 1 << 9 // last series of additional authenticated data + kmaLPC = 1 << 8 // last series of plaintext or ciphertext blocks + kmaDecrypt = 1 << 7 // decrypt +) + +// kmaGCM executes the encryption or decryption operation given by fn. The tag +// will be calculated and written to tag. cnt should contain the current +// counter state and will be overwritten with the updated counter state. +// TODO(mundaym): could pass in hash subkey +//go:noescape +func kmaGCM(fn code, key, dst, src, aad []byte, tag *[16]byte, cnt *gcmCount) + +// Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for +// details. +func (g *gcmKMA) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { + panic("crypto/cipher: message too large for GCM") + } + + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) { + panic("crypto/cipher: invalid buffer overlap") + } + + counter := g.deriveCounter(nonce) + fc := g.block.function | kmaLAAD | kmaLPC + + var tag [gcmTagSize]byte + kmaGCM(fc, g.block.key, out[:len(plaintext)], plaintext, data, &tag, &counter) + copy(out[len(plaintext):], tag[:]) + + return ret +} + +// Open authenticates and decrypts ciphertext. See the cipher.AEAD interface +// for details. +func (g *gcmKMA) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + if len(ciphertext) < g.tagSize { + return nil, errOpen + } + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { + return nil, errOpen + } + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + ret, out := sliceForAppend(dst, len(ciphertext)) + if subtleoverlap.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap") + } + + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") + } + + counter := g.deriveCounter(nonce) + fc := g.block.function | kmaLAAD | kmaLPC | kmaDecrypt + + var expectedTag [gcmTagSize]byte + kmaGCM(fc, g.block.key, out[:len(ciphertext)], ciphertext, data, &expectedTag, &counter) + + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + // The AESNI code decrypts and authenticates concurrently, and + // so overwrites dst in the event of a tag mismatch. That + // behavior is mimicked here in order to be consistent across + // platforms. + for i := range out { + out[i] = 0 + } + return nil, errOpen + } + + return ret, nil +} diff --git a/src/crypto/aes/modes.go b/src/crypto/aes/modes.go new file mode 100644 index 0000000..5c0b08e --- /dev/null +++ b/src/crypto/aes/modes.go @@ -0,0 +1,37 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "crypto/cipher" +) + +// gcmAble is implemented by cipher.Blocks that can provide an optimized +// implementation of GCM through the AEAD interface. +// See crypto/cipher/gcm.go. +type gcmAble interface { + NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) +} + +// cbcEncAble is implemented by cipher.Blocks that can provide an optimized +// implementation of CBC encryption through the cipher.BlockMode interface. +// See crypto/cipher/cbc.go. +type cbcEncAble interface { + NewCBCEncrypter(iv []byte) cipher.BlockMode +} + +// cbcDecAble is implemented by cipher.Blocks that can provide an optimized +// implementation of CBC decryption through the cipher.BlockMode interface. +// See crypto/cipher/cbc.go. +type cbcDecAble interface { + NewCBCDecrypter(iv []byte) cipher.BlockMode +} + +// ctrAble is implemented by cipher.Blocks that can provide an optimized +// implementation of CTR through the cipher.Stream interface. +// See crypto/cipher/ctr.go. +type ctrAble interface { + NewCTR(iv []byte) cipher.Stream +} diff --git a/src/crypto/aes/modes_test.go b/src/crypto/aes/modes_test.go new file mode 100644 index 0000000..a3364c9 --- /dev/null +++ b/src/crypto/aes/modes_test.go @@ -0,0 +1,112 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aes + +import ( + "crypto/cipher" + "testing" +) + +// Check that the optimized implementations of cipher modes will +// be picked up correctly. + +// testInterface can be asserted to check that a type originates +// from this test group. +type testInterface interface { + InAESPackage() bool +} + +// testBlock implements the cipher.Block interface and any *Able +// interfaces that need to be tested. +type testBlock struct{} + +func (*testBlock) BlockSize() int { return 0 } +func (*testBlock) Encrypt(a, b []byte) {} +func (*testBlock) Decrypt(a, b []byte) {} +func (*testBlock) NewGCM(int, int) (cipher.AEAD, error) { + return &testAEAD{}, nil +} +func (*testBlock) NewCBCEncrypter([]byte) cipher.BlockMode { + return &testBlockMode{} +} +func (*testBlock) NewCBCDecrypter([]byte) cipher.BlockMode { + return &testBlockMode{} +} +func (*testBlock) NewCTR([]byte) cipher.Stream { + return &testStream{} +} + +// testAEAD implements the cipher.AEAD interface. +type testAEAD struct{} + +func (*testAEAD) NonceSize() int { return 0 } +func (*testAEAD) Overhead() int { return 0 } +func (*testAEAD) Seal(a, b, c, d []byte) []byte { return []byte{} } +func (*testAEAD) Open(a, b, c, d []byte) ([]byte, error) { return []byte{}, nil } +func (*testAEAD) InAESPackage() bool { return true } + +// Test the gcmAble interface is detected correctly by the cipher package. +func TestGCMAble(t *testing.T) { + b := cipher.Block(&testBlock{}) + if _, ok := b.(gcmAble); !ok { + t.Fatalf("testBlock does not implement the gcmAble interface") + } + aead, err := cipher.NewGCM(b) + if err != nil { + t.Fatalf("%v", err) + } + if _, ok := aead.(testInterface); !ok { + t.Fatalf("cipher.NewGCM did not use gcmAble interface") + } +} + +// testBlockMode implements the cipher.BlockMode interface. +type testBlockMode struct{} + +func (*testBlockMode) BlockSize() int { return 0 } +func (*testBlockMode) CryptBlocks(a, b []byte) {} +func (*testBlockMode) InAESPackage() bool { return true } + +// Test the cbcEncAble interface is detected correctly by the cipher package. +func TestCBCEncAble(t *testing.T) { + b := cipher.Block(&testBlock{}) + if _, ok := b.(cbcEncAble); !ok { + t.Fatalf("testBlock does not implement the cbcEncAble interface") + } + bm := cipher.NewCBCEncrypter(b, []byte{}) + if _, ok := bm.(testInterface); !ok { + t.Fatalf("cipher.NewCBCEncrypter did not use cbcEncAble interface") + } +} + +// Test the cbcDecAble interface is detected correctly by the cipher package. +func TestCBCDecAble(t *testing.T) { + b := cipher.Block(&testBlock{}) + if _, ok := b.(cbcDecAble); !ok { + t.Fatalf("testBlock does not implement the cbcDecAble interface") + } + bm := cipher.NewCBCDecrypter(b, []byte{}) + if _, ok := bm.(testInterface); !ok { + t.Fatalf("cipher.NewCBCDecrypter did not use cbcDecAble interface") + } +} + +// testStream implements the cipher.Stream interface. +type testStream struct{} + +func (*testStream) XORKeyStream(a, b []byte) {} +func (*testStream) InAESPackage() bool { return true } + +// Test the ctrAble interface is detected correctly by the cipher package. +func TestCTRAble(t *testing.T) { + b := cipher.Block(&testBlock{}) + if _, ok := b.(ctrAble); !ok { + t.Fatalf("testBlock does not implement the ctrAble interface") + } + s := cipher.NewCTR(b, []byte{}) + if _, ok := s.(testInterface); !ok { + t.Fatalf("cipher.NewCTR did not use ctrAble interface") + } +} diff --git a/src/crypto/cipher/benchmark_test.go b/src/crypto/cipher/benchmark_test.go new file mode 100644 index 0000000..eb02cd0 --- /dev/null +++ b/src/crypto/cipher/benchmark_test.go @@ -0,0 +1,137 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +import ( + "crypto/aes" + "crypto/cipher" + "strconv" + "testing" +) + +func benchmarkAESGCMSeal(b *testing.B, buf []byte, keySize int) { + b.ReportAllocs() + b.SetBytes(int64(len(buf))) + + var key = make([]byte, keySize) + var nonce [12]byte + var ad [13]byte + aes, _ := aes.NewCipher(key[:]) + aesgcm, _ := cipher.NewGCM(aes) + var out []byte + + b.ResetTimer() + for i := 0; i < b.N; i++ { + out = aesgcm.Seal(out[:0], nonce[:], buf, ad[:]) + } +} + +func benchmarkAESGCMOpen(b *testing.B, buf []byte, keySize int) { + b.ReportAllocs() + b.SetBytes(int64(len(buf))) + + var key = make([]byte, keySize) + var nonce [12]byte + var ad [13]byte + aes, _ := aes.NewCipher(key[:]) + aesgcm, _ := cipher.NewGCM(aes) + var out []byte + + ct := aesgcm.Seal(nil, nonce[:], buf[:], ad[:]) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + out, _ = aesgcm.Open(out[:0], nonce[:], ct, ad[:]) + } +} + +func BenchmarkAESGCM(b *testing.B) { + for _, length := range []int{64, 1350, 8 * 1024} { + b.Run("Open-128-"+strconv.Itoa(length), func(b *testing.B) { + benchmarkAESGCMOpen(b, make([]byte, length), 128/8) + }) + b.Run("Seal-128-"+strconv.Itoa(length), func(b *testing.B) { + benchmarkAESGCMSeal(b, make([]byte, length), 128/8) + }) + + b.Run("Open-256-"+strconv.Itoa(length), func(b *testing.B) { + benchmarkAESGCMOpen(b, make([]byte, length), 256/8) + }) + b.Run("Seal-256-"+strconv.Itoa(length), func(b *testing.B) { + benchmarkAESGCMSeal(b, make([]byte, length), 256/8) + }) + } +} + +func benchmarkAESStream(b *testing.B, mode func(cipher.Block, []byte) cipher.Stream, buf []byte) { + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + stream := mode(aes, iv[:]) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + stream.XORKeyStream(buf, buf) + } +} + +// If we test exactly 1K blocks, we would generate exact multiples of +// the cipher's block size, and the cipher stream fragments would +// always be wordsize aligned, whereas non-aligned is a more typical +// use-case. +const almost1K = 1024 - 5 +const almost8K = 8*1024 - 5 + +func BenchmarkAESCFBEncrypt1K(b *testing.B) { + benchmarkAESStream(b, cipher.NewCFBEncrypter, make([]byte, almost1K)) +} + +func BenchmarkAESCFBDecrypt1K(b *testing.B) { + benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost1K)) +} + +func BenchmarkAESCFBDecrypt8K(b *testing.B) { + benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost8K)) +} + +func BenchmarkAESOFB1K(b *testing.B) { + benchmarkAESStream(b, cipher.NewOFB, make([]byte, almost1K)) +} + +func BenchmarkAESCTR1K(b *testing.B) { + benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost1K)) +} + +func BenchmarkAESCTR8K(b *testing.B) { + benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost8K)) +} + +func BenchmarkAESCBCEncrypt1K(b *testing.B) { + buf := make([]byte, 1024) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + cbc := cipher.NewCBCEncrypter(aes, iv[:]) + for i := 0; i < b.N; i++ { + cbc.CryptBlocks(buf, buf) + } +} + +func BenchmarkAESCBCDecrypt1K(b *testing.B) { + buf := make([]byte, 1024) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + cbc := cipher.NewCBCDecrypter(aes, iv[:]) + for i := 0; i < b.N; i++ { + cbc.CryptBlocks(buf, buf) + } +} diff --git a/src/crypto/cipher/cbc.go b/src/crypto/cipher/cbc.go new file mode 100644 index 0000000..0d07192 --- /dev/null +++ b/src/crypto/cipher/cbc.go @@ -0,0 +1,163 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Cipher block chaining (CBC) mode. + +// CBC provides confidentiality by xoring (chaining) each plaintext block +// with the previous ciphertext block before applying the block cipher. + +// See NIST SP 800-38A, pp 10-11 + +package cipher + +import "crypto/internal/subtle" + +type cbc struct { + b Block + blockSize int + iv []byte + tmp []byte +} + +func newCBC(b Block, iv []byte) *cbc { + return &cbc{ + b: b, + blockSize: b.BlockSize(), + iv: dup(iv), + tmp: make([]byte, b.BlockSize()), + } +} + +type cbcEncrypter cbc + +// cbcEncAble is an interface implemented by ciphers that have a specific +// optimized implementation of CBC encryption, like crypto/aes. +// NewCBCEncrypter will check for this interface and return the specific +// BlockMode if found. +type cbcEncAble interface { + NewCBCEncrypter(iv []byte) BlockMode +} + +// NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining +// mode, using the given Block. The length of iv must be the same as the +// Block's block size. +func NewCBCEncrypter(b Block, iv []byte) BlockMode { + if len(iv) != b.BlockSize() { + panic("cipher.NewCBCEncrypter: IV length must equal block size") + } + if cbc, ok := b.(cbcEncAble); ok { + return cbc.NewCBCEncrypter(iv) + } + return (*cbcEncrypter)(newCBC(b, iv)) +} + +func (x *cbcEncrypter) BlockSize() int { return x.blockSize } + +func (x *cbcEncrypter) CryptBlocks(dst, src []byte) { + if len(src)%x.blockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + + iv := x.iv + + for len(src) > 0 { + // Write the xor to dst, then encrypt in place. + xorBytes(dst[:x.blockSize], src[:x.blockSize], iv) + x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize]) + + // Move to the next block with this block as the next iv. + iv = dst[:x.blockSize] + src = src[x.blockSize:] + dst = dst[x.blockSize:] + } + + // Save the iv for the next CryptBlocks call. + copy(x.iv, iv) +} + +func (x *cbcEncrypter) SetIV(iv []byte) { + if len(iv) != len(x.iv) { + panic("cipher: incorrect length IV") + } + copy(x.iv, iv) +} + +type cbcDecrypter cbc + +// cbcDecAble is an interface implemented by ciphers that have a specific +// optimized implementation of CBC decryption, like crypto/aes. +// NewCBCDecrypter will check for this interface and return the specific +// BlockMode if found. +type cbcDecAble interface { + NewCBCDecrypter(iv []byte) BlockMode +} + +// NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining +// mode, using the given Block. The length of iv must be the same as the +// Block's block size and must match the iv used to encrypt the data. +func NewCBCDecrypter(b Block, iv []byte) BlockMode { + if len(iv) != b.BlockSize() { + panic("cipher.NewCBCDecrypter: IV length must equal block size") + } + if cbc, ok := b.(cbcDecAble); ok { + return cbc.NewCBCDecrypter(iv) + } + return (*cbcDecrypter)(newCBC(b, iv)) +} + +func (x *cbcDecrypter) BlockSize() int { return x.blockSize } + +func (x *cbcDecrypter) CryptBlocks(dst, src []byte) { + if len(src)%x.blockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + if len(src) == 0 { + return + } + + // For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv). + // To avoid making a copy each time, we loop over the blocks BACKWARDS. + end := len(src) + start := end - x.blockSize + prev := start - x.blockSize + + // Copy the last block of ciphertext in preparation as the new iv. + copy(x.tmp, src[start:end]) + + // Loop over all but the first block. + for start > 0 { + x.b.Decrypt(dst[start:end], src[start:end]) + xorBytes(dst[start:end], dst[start:end], src[prev:start]) + + end = start + start = prev + prev -= x.blockSize + } + + // The first block is special because it uses the saved iv. + x.b.Decrypt(dst[start:end], src[start:end]) + xorBytes(dst[start:end], dst[start:end], x.iv) + + // Set the new iv to the first block we copied earlier. + x.iv, x.tmp = x.tmp, x.iv +} + +func (x *cbcDecrypter) SetIV(iv []byte) { + if len(iv) != len(x.iv) { + panic("cipher: incorrect length IV") + } + copy(x.iv, iv) +} diff --git a/src/crypto/cipher/cbc_aes_test.go b/src/crypto/cipher/cbc_aes_test.go new file mode 100644 index 0000000..bf9e7ad --- /dev/null +++ b/src/crypto/cipher/cbc_aes_test.go @@ -0,0 +1,104 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// CBC AES test vectors. + +// See U.S. National Institute of Standards and Technology (NIST) +// Special Publication 800-38A, ``Recommendation for Block Cipher +// Modes of Operation,'' 2001 Edition, pp. 24-29. + +package cipher_test + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "testing" +) + +var cbcAESTests = []struct { + name string + key []byte + iv []byte + in []byte + out []byte +}{ + // NIST SP 800-38A pp 27-29 + { + "CBC-AES128", + commonKey128, + commonIV, + commonInput, + []byte{ + 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7, + }, + }, + { + "CBC-AES192", + commonKey192, + commonIV, + commonInput, + []byte{ + 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8, + 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a, + 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0, + 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81, 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd, + }, + }, + { + "CBC-AES256", + commonKey256, + commonIV, + commonInput, + []byte{ + 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, + 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, + 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b, + }, + }, +} + +func TestCBCEncrypterAES(t *testing.T) { + for _, test := range cbcAESTests { + c, err := aes.NewCipher(test.key) + if err != nil { + t.Errorf("%s: NewCipher(%d bytes) = %s", test.name, len(test.key), err) + continue + } + + encrypter := cipher.NewCBCEncrypter(c, test.iv) + + data := make([]byte, len(test.in)) + copy(data, test.in) + + encrypter.CryptBlocks(data, data) + if !bytes.Equal(test.out, data) { + t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test.name, data, test.out) + } + } +} + +func TestCBCDecrypterAES(t *testing.T) { + for _, test := range cbcAESTests { + c, err := aes.NewCipher(test.key) + if err != nil { + t.Errorf("%s: NewCipher(%d bytes) = %s", test.name, len(test.key), err) + continue + } + + decrypter := cipher.NewCBCDecrypter(c, test.iv) + + data := make([]byte, len(test.out)) + copy(data, test.out) + + decrypter.CryptBlocks(data, data) + if !bytes.Equal(test.in, data) { + t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test.name, data, test.in) + } + } +} diff --git a/src/crypto/cipher/cfb.go b/src/crypto/cipher/cfb.go new file mode 100644 index 0000000..80c9bc2 --- /dev/null +++ b/src/crypto/cipher/cfb.go @@ -0,0 +1,80 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// CFB (Cipher Feedback) Mode. + +package cipher + +import "crypto/internal/subtle" + +type cfb struct { + b Block + next []byte + out []byte + outUsed int + + decrypt bool +} + +func (x *cfb) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + for len(src) > 0 { + if x.outUsed == len(x.out) { + x.b.Encrypt(x.out, x.next) + x.outUsed = 0 + } + + if x.decrypt { + // We can precompute a larger segment of the + // keystream on decryption. This will allow + // larger batches for xor, and we should be + // able to match CTR/OFB performance. + copy(x.next[x.outUsed:], src) + } + n := xorBytes(dst, src, x.out[x.outUsed:]) + if !x.decrypt { + copy(x.next[x.outUsed:], dst) + } + dst = dst[n:] + src = src[n:] + x.outUsed += n + } +} + +// NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode, +// using the given Block. The iv must be the same length as the Block's block +// size. +func NewCFBEncrypter(block Block, iv []byte) Stream { + return newCFB(block, iv, false) +} + +// NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode, +// using the given Block. The iv must be the same length as the Block's block +// size. +func NewCFBDecrypter(block Block, iv []byte) Stream { + return newCFB(block, iv, true) +} + +func newCFB(block Block, iv []byte, decrypt bool) Stream { + blockSize := block.BlockSize() + if len(iv) != blockSize { + // stack trace will indicate whether it was de or encryption + panic("cipher.newCFB: IV length must equal block size") + } + x := &cfb{ + b: block, + out: make([]byte, blockSize), + next: make([]byte, blockSize), + outUsed: blockSize, + decrypt: decrypt, + } + copy(x.next, iv) + + return x +} diff --git a/src/crypto/cipher/cfb_test.go b/src/crypto/cipher/cfb_test.go new file mode 100644 index 0000000..72f62e6 --- /dev/null +++ b/src/crypto/cipher/cfb_test.go @@ -0,0 +1,113 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/hex" + "testing" +) + +// cfbTests contains the test vectors from +// https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section +// F.3.13. +var cfbTests = []struct { + key, iv, plaintext, ciphertext string +}{ + { + "2b7e151628aed2a6abf7158809cf4f3c", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172a", + "3b3fd92eb72dad20333449f8e83cfb4a", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", + "3B3FD92EB72DAD20333449F8E83CFB4A", + "ae2d8a571e03ac9c9eb76fac45af8e51", + "c8a64537a0b3a93fcde3cdad9f1ce58b", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", + "C8A64537A0B3A93FCDE3CDAD9F1CE58B", + "30c81c46a35ce411e5fbc1191a0a52ef", + "26751f67a3cbb140b1808cf187a4f4df", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", + "26751F67A3CBB140B1808CF187A4F4DF", + "f69f2445df4f9b17ad2b417be66c3710", + "c04b05357c5d1c0eeac4c66f9ff7f2e6", + }, +} + +func TestCFBVectors(t *testing.T) { + for i, test := range cfbTests { + key, err := hex.DecodeString(test.key) + if err != nil { + t.Fatal(err) + } + iv, err := hex.DecodeString(test.iv) + if err != nil { + t.Fatal(err) + } + plaintext, err := hex.DecodeString(test.plaintext) + if err != nil { + t.Fatal(err) + } + expected, err := hex.DecodeString(test.ciphertext) + if err != nil { + t.Fatal(err) + } + + block, err := aes.NewCipher(key) + if err != nil { + t.Fatal(err) + } + + ciphertext := make([]byte, len(plaintext)) + cfb := cipher.NewCFBEncrypter(block, iv) + cfb.XORKeyStream(ciphertext, plaintext) + + if !bytes.Equal(ciphertext, expected) { + t.Errorf("#%d: wrong output: got %x, expected %x", i, ciphertext, expected) + } + + cfbdec := cipher.NewCFBDecrypter(block, iv) + plaintextCopy := make([]byte, len(ciphertext)) + cfbdec.XORKeyStream(plaintextCopy, ciphertext) + + if !bytes.Equal(plaintextCopy, plaintext) { + t.Errorf("#%d: wrong plaintext: got %x, expected %x", i, plaintextCopy, plaintext) + } + } +} + +func TestCFBInverse(t *testing.T) { + block, err := aes.NewCipher(commonKey128) + if err != nil { + t.Error(err) + return + } + + plaintext := []byte("this is the plaintext. this is the plaintext.") + iv := make([]byte, block.BlockSize()) + rand.Reader.Read(iv) + cfb := cipher.NewCFBEncrypter(block, iv) + ciphertext := make([]byte, len(plaintext)) + copy(ciphertext, plaintext) + cfb.XORKeyStream(ciphertext, ciphertext) + + cfbdec := cipher.NewCFBDecrypter(block, iv) + plaintextCopy := make([]byte, len(plaintext)) + copy(plaintextCopy, ciphertext) + cfbdec.XORKeyStream(plaintextCopy, plaintextCopy) + + if !bytes.Equal(plaintextCopy, plaintext) { + t.Errorf("got: %x, want: %x", plaintextCopy, plaintext) + } +} diff --git a/src/crypto/cipher/cipher.go b/src/crypto/cipher/cipher.go new file mode 100644 index 0000000..7e1a4de --- /dev/null +++ b/src/crypto/cipher/cipher.go @@ -0,0 +1,69 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cipher implements standard block cipher modes that can be wrapped +// around low-level block cipher implementations. +// See https://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html +// and NIST Special Publication 800-38A. +package cipher + +// A Block represents an implementation of block cipher +// using a given key. It provides the capability to encrypt +// or decrypt individual blocks. The mode implementations +// extend that capability to streams of blocks. +type Block interface { + // BlockSize returns the cipher's block size. + BlockSize() int + + // Encrypt encrypts the first block in src into dst. + // Dst and src must overlap entirely or not at all. + Encrypt(dst, src []byte) + + // Decrypt decrypts the first block in src into dst. + // Dst and src must overlap entirely or not at all. + Decrypt(dst, src []byte) +} + +// A Stream represents a stream cipher. +type Stream interface { + // XORKeyStream XORs each byte in the given slice with a byte from the + // cipher's key stream. Dst and src must overlap entirely or not at all. + // + // If len(dst) < len(src), XORKeyStream should panic. It is acceptable + // to pass a dst bigger than src, and in that case, XORKeyStream will + // only update dst[:len(src)] and will not touch the rest of dst. + // + // Multiple calls to XORKeyStream behave as if the concatenation of + // the src buffers was passed in a single run. That is, Stream + // maintains state and does not reset at each XORKeyStream call. + XORKeyStream(dst, src []byte) +} + +// A BlockMode represents a block cipher running in a block-based mode (CBC, +// ECB etc). +type BlockMode interface { + // BlockSize returns the mode's block size. + BlockSize() int + + // CryptBlocks encrypts or decrypts a number of blocks. The length of + // src must be a multiple of the block size. Dst and src must overlap + // entirely or not at all. + // + // If len(dst) < len(src), CryptBlocks should panic. It is acceptable + // to pass a dst bigger than src, and in that case, CryptBlocks will + // only update dst[:len(src)] and will not touch the rest of dst. + // + // Multiple calls to CryptBlocks behave as if the concatenation of + // the src buffers was passed in a single run. That is, BlockMode + // maintains state and does not reset at each CryptBlocks call. + CryptBlocks(dst, src []byte) +} + +// Utility routines + +func dup(p []byte) []byte { + q := make([]byte, len(p)) + copy(q, p) + return q +} diff --git a/src/crypto/cipher/cipher_test.go b/src/crypto/cipher/cipher_test.go new file mode 100644 index 0000000..4d7cd6b --- /dev/null +++ b/src/crypto/cipher/cipher_test.go @@ -0,0 +1,90 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/des" + "testing" +) + +func TestCryptBlocks(t *testing.T) { + buf := make([]byte, 16) + block, _ := aes.NewCipher(buf) + + mode := cipher.NewCBCDecrypter(block, buf) + mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) }) + mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) }) + + mode = cipher.NewCBCEncrypter(block, buf) + mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) }) + mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) }) +} + +func mustPanic(t *testing.T, msg string, f func()) { + defer func() { + err := recover() + if err == nil { + t.Errorf("function did not panic, wanted %q", msg) + } else if err != msg { + t.Errorf("got panic %v, wanted %q", err, msg) + } + }() + f() +} + +func TestEmptyPlaintext(t *testing.T) { + var key [16]byte + a, err := aes.NewCipher(key[:16]) + if err != nil { + t.Fatal(err) + } + d, err := des.NewCipher(key[:8]) + if err != nil { + t.Fatal(err) + } + + s := 16 + pt := make([]byte, s) + ct := make([]byte, s) + for i := 0; i < 16; i++ { + pt[i], ct[i] = byte(i), byte(i) + } + + assertEqual := func(name string, got, want []byte) { + if !bytes.Equal(got, want) { + t.Fatalf("%s: got %v, want %v", name, got, want) + } + } + + for _, b := range []cipher.Block{a, d} { + iv := make([]byte, b.BlockSize()) + cbce := cipher.NewCBCEncrypter(b, iv) + cbce.CryptBlocks(ct, pt[:0]) + assertEqual("CBC encrypt", ct, pt) + + cbcd := cipher.NewCBCDecrypter(b, iv) + cbcd.CryptBlocks(ct, pt[:0]) + assertEqual("CBC decrypt", ct, pt) + + cfbe := cipher.NewCFBEncrypter(b, iv) + cfbe.XORKeyStream(ct, pt[:0]) + assertEqual("CFB encrypt", ct, pt) + + cfbd := cipher.NewCFBDecrypter(b, iv) + cfbd.XORKeyStream(ct, pt[:0]) + assertEqual("CFB decrypt", ct, pt) + + ctr := cipher.NewCTR(b, iv) + ctr.XORKeyStream(ct, pt[:0]) + assertEqual("CTR", ct, pt) + + ofb := cipher.NewOFB(b, iv) + ofb.XORKeyStream(ct, pt[:0]) + assertEqual("OFB", ct, pt) + } +} diff --git a/src/crypto/cipher/common_test.go b/src/crypto/cipher/common_test.go new file mode 100644 index 0000000..c75c919 --- /dev/null +++ b/src/crypto/cipher/common_test.go @@ -0,0 +1,28 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +// Common values for tests. + +var commonInput = []byte{ + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, +} + +var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c} + +var commonKey192 = []byte{ + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b, +} + +var commonKey256 = []byte{ + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4, +} + +var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f} diff --git a/src/crypto/cipher/ctr.go b/src/crypto/cipher/ctr.go new file mode 100644 index 0000000..cba028d --- /dev/null +++ b/src/crypto/cipher/ctr.go @@ -0,0 +1,91 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Counter (CTR) mode. + +// CTR converts a block cipher into a stream cipher by +// repeatedly encrypting an incrementing counter and +// xoring the resulting stream of data with the input. + +// See NIST SP 800-38A, pp 13-15 + +package cipher + +import "crypto/internal/subtle" + +type ctr struct { + b Block + ctr []byte + out []byte + outUsed int +} + +const streamBufferSize = 512 + +// ctrAble is an interface implemented by ciphers that have a specific optimized +// implementation of CTR, like crypto/aes. NewCTR will check for this interface +// and return the specific Stream if found. +type ctrAble interface { + NewCTR(iv []byte) Stream +} + +// NewCTR returns a Stream which encrypts/decrypts using the given Block in +// counter mode. The length of iv must be the same as the Block's block size. +func NewCTR(block Block, iv []byte) Stream { + if ctr, ok := block.(ctrAble); ok { + return ctr.NewCTR(iv) + } + if len(iv) != block.BlockSize() { + panic("cipher.NewCTR: IV length must equal block size") + } + bufSize := streamBufferSize + if bufSize < block.BlockSize() { + bufSize = block.BlockSize() + } + return &ctr{ + b: block, + ctr: dup(iv), + out: make([]byte, 0, bufSize), + outUsed: 0, + } +} + +func (x *ctr) refill() { + remain := len(x.out) - x.outUsed + copy(x.out, x.out[x.outUsed:]) + x.out = x.out[:cap(x.out)] + bs := x.b.BlockSize() + for remain <= len(x.out)-bs { + x.b.Encrypt(x.out[remain:], x.ctr) + remain += bs + + // Increment counter + for i := len(x.ctr) - 1; i >= 0; i-- { + x.ctr[i]++ + if x.ctr[i] != 0 { + break + } + } + } + x.out = x.out[:remain] + x.outUsed = 0 +} + +func (x *ctr) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + for len(src) > 0 { + if x.outUsed >= len(x.out)-x.b.BlockSize() { + x.refill() + } + n := xorBytes(dst, src, x.out[x.outUsed:]) + dst = dst[n:] + src = src[n:] + x.outUsed += n + } +} diff --git a/src/crypto/cipher/ctr_aes_test.go b/src/crypto/cipher/ctr_aes_test.go new file mode 100644 index 0000000..d019ae0 --- /dev/null +++ b/src/crypto/cipher/ctr_aes_test.go @@ -0,0 +1,102 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// CTR AES test vectors. + +// See U.S. National Institute of Standards and Technology (NIST) +// Special Publication 800-38A, ``Recommendation for Block Cipher +// Modes of Operation,'' 2001 Edition, pp. 55-58. + +package cipher_test + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "testing" +) + +var commonCounter = []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff} + +var ctrAESTests = []struct { + name string + key []byte + iv []byte + in []byte + out []byte +}{ + // NIST SP 800-38A pp 55-58 + { + "CTR-AES128", + commonKey128, + commonCounter, + commonInput, + []byte{ + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, + 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, + 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, + 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee, + }, + }, + { + "CTR-AES192", + commonKey192, + commonCounter, + commonInput, + []byte{ + 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b, + 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94, + 0x1e, 0x36, 0xb2, 0x6b, 0xd1, 0xeb, 0xc6, 0x70, 0xd1, 0xbd, 0x1d, 0x66, 0x56, 0x20, 0xab, 0xf7, + 0x4f, 0x78, 0xa7, 0xf6, 0xd2, 0x98, 0x09, 0x58, 0x5a, 0x97, 0xda, 0xec, 0x58, 0xc6, 0xb0, 0x50, + }, + }, + { + "CTR-AES256", + commonKey256, + commonCounter, + commonInput, + []byte{ + 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, + 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5, + 0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d, + 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6, + }, + }, +} + +func TestCTR_AES(t *testing.T) { + for _, tt := range ctrAESTests { + test := tt.name + + c, err := aes.NewCipher(tt.key) + if err != nil { + t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err) + continue + } + + for j := 0; j <= 5; j += 5 { + in := tt.in[0 : len(tt.in)-j] + ctr := cipher.NewCTR(c, tt.iv) + encrypted := make([]byte, len(in)) + ctr.XORKeyStream(encrypted, in) + if out := tt.out[0:len(in)]; !bytes.Equal(out, encrypted) { + t.Errorf("%s/%d: CTR\ninpt %x\nhave %x\nwant %x", test, len(in), in, encrypted, out) + } + } + + for j := 0; j <= 7; j += 7 { + in := tt.out[0 : len(tt.out)-j] + ctr := cipher.NewCTR(c, tt.iv) + plain := make([]byte, len(in)) + ctr.XORKeyStream(plain, in) + if out := tt.in[0:len(in)]; !bytes.Equal(out, plain) { + t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), plain, out) + } + } + + if t.Failed() { + break + } + } +} diff --git a/src/crypto/cipher/ctr_test.go b/src/crypto/cipher/ctr_test.go new file mode 100644 index 0000000..e5cce57 --- /dev/null +++ b/src/crypto/cipher/ctr_test.go @@ -0,0 +1,55 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +import ( + "bytes" + "crypto/cipher" + "testing" +) + +type noopBlock int + +func (b noopBlock) BlockSize() int { return int(b) } +func (noopBlock) Encrypt(dst, src []byte) { copy(dst, src) } +func (noopBlock) Decrypt(dst, src []byte) { copy(dst, src) } + +func inc(b []byte) { + for i := len(b) - 1; i >= 0; i++ { + b[i]++ + if b[i] != 0 { + break + } + } +} + +func xor(a, b []byte) { + for i := range a { + a[i] ^= b[i] + } +} + +func TestCTR(t *testing.T) { + for size := 64; size <= 1024; size *= 2 { + iv := make([]byte, size) + ctr := cipher.NewCTR(noopBlock(size), iv) + src := make([]byte, 1024) + for i := range src { + src[i] = 0xff + } + want := make([]byte, 1024) + copy(want, src) + counter := make([]byte, size) + for i := 1; i < len(want)/size; i++ { + inc(counter) + xor(want[i*size:(i+1)*size], counter) + } + dst := make([]byte, 1024) + ctr.XORKeyStream(dst, src) + if !bytes.Equal(dst, want) { + t.Errorf("for size %d\nhave %x\nwant %x", size, dst, want) + } + } +} diff --git a/src/crypto/cipher/example_test.go b/src/crypto/cipher/example_test.go new file mode 100644 index 0000000..9c32d6a --- /dev/null +++ b/src/crypto/cipher/example_test.go @@ -0,0 +1,363 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/hex" + "fmt" + "io" + "os" +) + +func ExampleNewGCM_encrypt() { + // Load your secret key from a safe place and reuse it across multiple + // Seal/Open calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + // When decoded the key should be 16 bytes (AES-128) or 32 (AES-256). + key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574") + plaintext := []byte("exampleplaintext") + + block, err := aes.NewCipher(key) + if err != nil { + panic(err.Error()) + } + + // Never use more than 2^32 random nonces with a given key because of the risk of a repeat. + nonce := make([]byte, 12) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + panic(err.Error()) + } + + aesgcm, err := cipher.NewGCM(block) + if err != nil { + panic(err.Error()) + } + + ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil) + fmt.Printf("%x\n", ciphertext) +} + +func ExampleNewGCM_decrypt() { + // Load your secret key from a safe place and reuse it across multiple + // Seal/Open calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + // When decoded the key should be 16 bytes (AES-128) or 32 (AES-256). + key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574") + ciphertext, _ := hex.DecodeString("c3aaa29f002ca75870806e44086700f62ce4d43e902b3888e23ceff797a7a471") + nonce, _ := hex.DecodeString("64a9433eae7ccceee2fc0eda") + + block, err := aes.NewCipher(key) + if err != nil { + panic(err.Error()) + } + + aesgcm, err := cipher.NewGCM(block) + if err != nil { + panic(err.Error()) + } + + plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil) + if err != nil { + panic(err.Error()) + } + + fmt.Printf("%s\n", plaintext) + // Output: exampleplaintext +} + +func ExampleNewCBCDecrypter() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + ciphertext, _ := hex.DecodeString("73c86d43a9d700a253a96c85b0f6b03ac9792e0e757f869cca306bd3cba1c62b") + + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + + // The IV needs to be unique, but not secure. Therefore it's common to + // include it at the beginning of the ciphertext. + if len(ciphertext) < aes.BlockSize { + panic("ciphertext too short") + } + iv := ciphertext[:aes.BlockSize] + ciphertext = ciphertext[aes.BlockSize:] + + // CBC mode always works in whole blocks. + if len(ciphertext)%aes.BlockSize != 0 { + panic("ciphertext is not a multiple of the block size") + } + + mode := cipher.NewCBCDecrypter(block, iv) + + // CryptBlocks can work in-place if the two arguments are the same. + mode.CryptBlocks(ciphertext, ciphertext) + + // If the original plaintext lengths are not a multiple of the block + // size, padding would have to be added when encrypting, which would be + // removed at this point. For an example, see + // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's + // critical to note that ciphertexts must be authenticated (i.e. by + // using crypto/hmac) before being decrypted in order to avoid creating + // a padding oracle. + + fmt.Printf("%s\n", ciphertext) + // Output: exampleplaintext +} + +func ExampleNewCBCEncrypter() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + plaintext := []byte("exampleplaintext") + + // CBC mode works on blocks so plaintexts may need to be padded to the + // next whole block. For an example of such padding, see + // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll + // assume that the plaintext is already of the correct length. + if len(plaintext)%aes.BlockSize != 0 { + panic("plaintext is not a multiple of the block size") + } + + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + + // The IV needs to be unique, but not secure. Therefore it's common to + // include it at the beginning of the ciphertext. + ciphertext := make([]byte, aes.BlockSize+len(plaintext)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + panic(err) + } + + mode := cipher.NewCBCEncrypter(block, iv) + mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) + + // It's important to remember that ciphertexts must be authenticated + // (i.e. by using crypto/hmac) as well as being encrypted in order to + // be secure. + + fmt.Printf("%x\n", ciphertext) +} + +func ExampleNewCFBDecrypter() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + ciphertext, _ := hex.DecodeString("7dd015f06bec7f1b8f6559dad89f4131da62261786845100056b353194ad") + + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + + // The IV needs to be unique, but not secure. Therefore it's common to + // include it at the beginning of the ciphertext. + if len(ciphertext) < aes.BlockSize { + panic("ciphertext too short") + } + iv := ciphertext[:aes.BlockSize] + ciphertext = ciphertext[aes.BlockSize:] + + stream := cipher.NewCFBDecrypter(block, iv) + + // XORKeyStream can work in-place if the two arguments are the same. + stream.XORKeyStream(ciphertext, ciphertext) + fmt.Printf("%s", ciphertext) + // Output: some plaintext +} + +func ExampleNewCFBEncrypter() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + plaintext := []byte("some plaintext") + + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + + // The IV needs to be unique, but not secure. Therefore it's common to + // include it at the beginning of the ciphertext. + ciphertext := make([]byte, aes.BlockSize+len(plaintext)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + panic(err) + } + + stream := cipher.NewCFBEncrypter(block, iv) + stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) + + // It's important to remember that ciphertexts must be authenticated + // (i.e. by using crypto/hmac) as well as being encrypted in order to + // be secure. + fmt.Printf("%x\n", ciphertext) +} + +func ExampleNewCTR() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + plaintext := []byte("some plaintext") + + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + + // The IV needs to be unique, but not secure. Therefore it's common to + // include it at the beginning of the ciphertext. + ciphertext := make([]byte, aes.BlockSize+len(plaintext)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + panic(err) + } + + stream := cipher.NewCTR(block, iv) + stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) + + // It's important to remember that ciphertexts must be authenticated + // (i.e. by using crypto/hmac) as well as being encrypted in order to + // be secure. + + // CTR mode is the same for both encryption and decryption, so we can + // also decrypt that ciphertext with NewCTR. + + plaintext2 := make([]byte, len(plaintext)) + stream = cipher.NewCTR(block, iv) + stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:]) + + fmt.Printf("%s\n", plaintext2) + // Output: some plaintext +} + +func ExampleNewOFB() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + plaintext := []byte("some plaintext") + + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + + // The IV needs to be unique, but not secure. Therefore it's common to + // include it at the beginning of the ciphertext. + ciphertext := make([]byte, aes.BlockSize+len(plaintext)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + panic(err) + } + + stream := cipher.NewOFB(block, iv) + stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) + + // It's important to remember that ciphertexts must be authenticated + // (i.e. by using crypto/hmac) as well as being encrypted in order to + // be secure. + + // OFB mode is the same for both encryption and decryption, so we can + // also decrypt that ciphertext with NewOFB. + + plaintext2 := make([]byte, len(plaintext)) + stream = cipher.NewOFB(block, iv) + stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:]) + + fmt.Printf("%s\n", plaintext2) + // Output: some plaintext +} + +func ExampleStreamReader() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + + encrypted, _ := hex.DecodeString("cf0495cc6f75dafc23948538e79904a9") + bReader := bytes.NewReader(encrypted) + + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + + // If the key is unique for each ciphertext, then it's ok to use a zero + // IV. + var iv [aes.BlockSize]byte + stream := cipher.NewOFB(block, iv[:]) + + reader := &cipher.StreamReader{S: stream, R: bReader} + // Copy the input to the output stream, decrypting as we go. + if _, err := io.Copy(os.Stdout, reader); err != nil { + panic(err) + } + + // Note that this example is simplistic in that it omits any + // authentication of the encrypted data. If you were actually to use + // StreamReader in this manner, an attacker could flip arbitrary bits in + // the output. + + // Output: some secret text +} + +func ExampleStreamWriter() { + // Load your secret key from a safe place and reuse it across multiple + // NewCipher calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + key, _ := hex.DecodeString("6368616e676520746869732070617373") + + bReader := bytes.NewReader([]byte("some secret text")) + + block, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + + // If the key is unique for each ciphertext, then it's ok to use a zero + // IV. + var iv [aes.BlockSize]byte + stream := cipher.NewOFB(block, iv[:]) + + var out bytes.Buffer + + writer := &cipher.StreamWriter{S: stream, W: &out} + // Copy the input to the output buffer, encrypting as we go. + if _, err := io.Copy(writer, bReader); err != nil { + panic(err) + } + + // Note that this example is simplistic in that it omits any + // authentication of the encrypted data. If you were actually to use + // StreamReader in this manner, an attacker could flip arbitrary bits in + // the decrypted result. + + fmt.Printf("%x\n", out.Bytes()) + // Output: cf0495cc6f75dafc23948538e79904a9 +} diff --git a/src/crypto/cipher/export_test.go b/src/crypto/cipher/export_test.go new file mode 100644 index 0000000..cf8007a --- /dev/null +++ b/src/crypto/cipher/export_test.go @@ -0,0 +1,8 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher + +// Export internal functions for testing. +var XorBytes = xorBytes diff --git a/src/crypto/cipher/gcm.go b/src/crypto/cipher/gcm.go new file mode 100644 index 0000000..ba0af84 --- /dev/null +++ b/src/crypto/cipher/gcm.go @@ -0,0 +1,426 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher + +import ( + subtleoverlap "crypto/internal/subtle" + "crypto/subtle" + "encoding/binary" + "errors" +) + +// AEAD is a cipher mode providing authenticated encryption with associated +// data. For a description of the methodology, see +// https://en.wikipedia.org/wiki/Authenticated_encryption +type AEAD interface { + // NonceSize returns the size of the nonce that must be passed to Seal + // and Open. + NonceSize() int + + // Overhead returns the maximum difference between the lengths of a + // plaintext and its ciphertext. + Overhead() int + + // Seal encrypts and authenticates plaintext, authenticates the + // additional data and appends the result to dst, returning the updated + // slice. The nonce must be NonceSize() bytes long and unique for all + // time, for a given key. + // + // To reuse plaintext's storage for the encrypted output, use plaintext[:0] + // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext. + Seal(dst, nonce, plaintext, additionalData []byte) []byte + + // Open decrypts and authenticates ciphertext, authenticates the + // additional data and, if successful, appends the resulting plaintext + // to dst, returning the updated slice. The nonce must be NonceSize() + // bytes long and both it and the additional data must match the + // value passed to Seal. + // + // To reuse ciphertext's storage for the decrypted output, use ciphertext[:0] + // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext. + // + // Even if the function fails, the contents of dst, up to its capacity, + // may be overwritten. + Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) +} + +// gcmAble is an interface implemented by ciphers that have a specific optimized +// implementation of GCM, like crypto/aes. NewGCM will check for this interface +// and return the specific AEAD if found. +type gcmAble interface { + NewGCM(nonceSize, tagSize int) (AEAD, error) +} + +// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM +// standard and make binary.BigEndian suitable for marshaling these values, the +// bits are stored in big endian order. For example: +// the coefficient of x⁰ can be obtained by v.low >> 63. +// the coefficient of x⁶³ can be obtained by v.low & 1. +// the coefficient of x⁶⁴ can be obtained by v.high >> 63. +// the coefficient of x¹²⁷ can be obtained by v.high & 1. +type gcmFieldElement struct { + low, high uint64 +} + +// gcm represents a Galois Counter Mode with a specific key. See +// https://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf +type gcm struct { + cipher Block + nonceSize int + tagSize int + // productTable contains the first sixteen powers of the key, H. + // However, they are in bit reversed order. See NewGCMWithNonceSize. + productTable [16]gcmFieldElement +} + +// NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode +// with the standard nonce length. +// +// In general, the GHASH operation performed by this implementation of GCM is not constant-time. +// An exception is when the underlying Block was created by aes.NewCipher +// on systems with hardware support for AES. See the crypto/aes package documentation for details. +func NewGCM(cipher Block) (AEAD, error) { + return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, gcmTagSize) +} + +// NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois +// Counter Mode, which accepts nonces of the given length. The length must not +// be zero. +// +// Only use this function if you require compatibility with an existing +// cryptosystem that uses non-standard nonce lengths. All other users should use +// NewGCM, which is faster and more resistant to misuse. +func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) { + return newGCMWithNonceAndTagSize(cipher, size, gcmTagSize) +} + +// NewGCMWithTagSize returns the given 128-bit, block cipher wrapped in Galois +// Counter Mode, which generates tags with the given length. +// +// Tag sizes between 12 and 16 bytes are allowed. +// +// Only use this function if you require compatibility with an existing +// cryptosystem that uses non-standard tag lengths. All other users should use +// NewGCM, which is more resistant to misuse. +func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error) { + return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, tagSize) +} + +func newGCMWithNonceAndTagSize(cipher Block, nonceSize, tagSize int) (AEAD, error) { + if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize { + return nil, errors.New("cipher: incorrect tag size given to GCM") + } + + if nonceSize <= 0 { + return nil, errors.New("cipher: the nonce can't have zero length, or the security of the key will be immediately compromised") + } + + if cipher, ok := cipher.(gcmAble); ok { + return cipher.NewGCM(nonceSize, tagSize) + } + + if cipher.BlockSize() != gcmBlockSize { + return nil, errors.New("cipher: NewGCM requires 128-bit block cipher") + } + + var key [gcmBlockSize]byte + cipher.Encrypt(key[:], key[:]) + + g := &gcm{cipher: cipher, nonceSize: nonceSize, tagSize: tagSize} + + // We precompute 16 multiples of |key|. However, when we do lookups + // into this table we'll be using bits from a field element and + // therefore the bits will be in the reverse order. So normally one + // would expect, say, 4*key to be in index 4 of the table but due to + // this bit ordering it will actually be in index 0010 (base 2) = 2. + x := gcmFieldElement{ + binary.BigEndian.Uint64(key[:8]), + binary.BigEndian.Uint64(key[8:]), + } + g.productTable[reverseBits(1)] = x + + for i := 2; i < 16; i += 2 { + g.productTable[reverseBits(i)] = gcmDouble(&g.productTable[reverseBits(i/2)]) + g.productTable[reverseBits(i+1)] = gcmAdd(&g.productTable[reverseBits(i)], &x) + } + + return g, nil +} + +const ( + gcmBlockSize = 16 + gcmTagSize = 16 + gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. + gcmStandardNonceSize = 12 +) + +func (g *gcm) NonceSize() int { + return g.nonceSize +} + +func (g *gcm) Overhead() int { + return g.tagSize +} + +func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + if uint64(len(plaintext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize()) { + panic("crypto/cipher: message too large for GCM") + } + + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if subtleoverlap.InexactOverlap(out, plaintext) { + panic("crypto/cipher: invalid buffer overlap") + } + + var counter, tagMask [gcmBlockSize]byte + g.deriveCounter(&counter, nonce) + + g.cipher.Encrypt(tagMask[:], counter[:]) + gcmInc32(&counter) + + g.counterCrypt(out, plaintext, &counter) + + var tag [gcmTagSize]byte + g.auth(tag[:], out[:len(plaintext)], data, &tagMask) + copy(out[len(plaintext):], tag[:]) + + return ret +} + +var errOpen = errors.New("cipher: message authentication failed") + +func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + if len(nonce) != g.nonceSize { + panic("crypto/cipher: incorrect nonce length given to GCM") + } + // Sanity check to prevent the authentication from always succeeding if an implementation + // leaves tagSize uninitialized, for example. + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") + } + + if len(ciphertext) < g.tagSize { + return nil, errOpen + } + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize())+uint64(g.tagSize) { + return nil, errOpen + } + + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] + + var counter, tagMask [gcmBlockSize]byte + g.deriveCounter(&counter, nonce) + + g.cipher.Encrypt(tagMask[:], counter[:]) + gcmInc32(&counter) + + var expectedTag [gcmTagSize]byte + g.auth(expectedTag[:], ciphertext, data, &tagMask) + + ret, out := sliceForAppend(dst, len(ciphertext)) + if subtleoverlap.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap") + } + + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { + // The AESNI code decrypts and authenticates concurrently, and + // so overwrites dst in the event of a tag mismatch. That + // behavior is mimicked here in order to be consistent across + // platforms. + for i := range out { + out[i] = 0 + } + return nil, errOpen + } + + g.counterCrypt(out, ciphertext, &counter) + + return ret, nil +} + +// reverseBits reverses the order of the bits of 4-bit number in i. +func reverseBits(i int) int { + i = ((i << 2) & 0xc) | ((i >> 2) & 0x3) + i = ((i << 1) & 0xa) | ((i >> 1) & 0x5) + return i +} + +// gcmAdd adds two elements of GF(2¹²⁸) and returns the sum. +func gcmAdd(x, y *gcmFieldElement) gcmFieldElement { + // Addition in a characteristic 2 field is just XOR. + return gcmFieldElement{x.low ^ y.low, x.high ^ y.high} +} + +// gcmDouble returns the result of doubling an element of GF(2¹²⁸). +func gcmDouble(x *gcmFieldElement) (double gcmFieldElement) { + msbSet := x.high&1 == 1 + + // Because of the bit-ordering, doubling is actually a right shift. + double.high = x.high >> 1 + double.high |= x.low << 63 + double.low = x.low >> 1 + + // If the most-significant bit was set before shifting then it, + // conceptually, becomes a term of x^128. This is greater than the + // irreducible polynomial so the result has to be reduced. The + // irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to + // eliminate the term at x^128 which also means subtracting the other + // four terms. In characteristic 2 fields, subtraction == addition == + // XOR. + if msbSet { + double.low ^= 0xe100000000000000 + } + + return +} + +var gcmReductionTable = []uint16{ + 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0, +} + +// mul sets y to y*H, where H is the GCM key, fixed during NewGCMWithNonceSize. +func (g *gcm) mul(y *gcmFieldElement) { + var z gcmFieldElement + + for i := 0; i < 2; i++ { + word := y.high + if i == 1 { + word = y.low + } + + // Multiplication works by multiplying z by 16 and adding in + // one of the precomputed multiples of H. + for j := 0; j < 64; j += 4 { + msw := z.high & 0xf + z.high >>= 4 + z.high |= z.low << 60 + z.low >>= 4 + z.low ^= uint64(gcmReductionTable[msw]) << 48 + + // the values in |table| are ordered for + // little-endian bit positions. See the comment + // in NewGCMWithNonceSize. + t := &g.productTable[word&0xf] + + z.low ^= t.low + z.high ^= t.high + word >>= 4 + } + } + + *y = z +} + +// updateBlocks extends y with more polynomial terms from blocks, based on +// Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks. +func (g *gcm) updateBlocks(y *gcmFieldElement, blocks []byte) { + for len(blocks) > 0 { + y.low ^= binary.BigEndian.Uint64(blocks) + y.high ^= binary.BigEndian.Uint64(blocks[8:]) + g.mul(y) + blocks = blocks[gcmBlockSize:] + } +} + +// update extends y with more polynomial terms from data. If data is not a +// multiple of gcmBlockSize bytes long then the remainder is zero padded. +func (g *gcm) update(y *gcmFieldElement, data []byte) { + fullBlocks := (len(data) >> 4) << 4 + g.updateBlocks(y, data[:fullBlocks]) + + if len(data) != fullBlocks { + var partialBlock [gcmBlockSize]byte + copy(partialBlock[:], data[fullBlocks:]) + g.updateBlocks(y, partialBlock[:]) + } +} + +// gcmInc32 treats the final four bytes of counterBlock as a big-endian value +// and increments it. +func gcmInc32(counterBlock *[16]byte) { + ctr := counterBlock[len(counterBlock)-4:] + binary.BigEndian.PutUint32(ctr, binary.BigEndian.Uint32(ctr)+1) +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +// counterCrypt crypts in to out using g.cipher in counter mode. +func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { + var mask [gcmBlockSize]byte + + for len(in) >= gcmBlockSize { + g.cipher.Encrypt(mask[:], counter[:]) + gcmInc32(counter) + + xorWords(out, in, mask[:]) + out = out[gcmBlockSize:] + in = in[gcmBlockSize:] + } + + if len(in) > 0 { + g.cipher.Encrypt(mask[:], counter[:]) + gcmInc32(counter) + xorBytes(out, in, mask[:]) + } +} + +// deriveCounter computes the initial GCM counter state from the given nonce. +// See NIST SP 800-38D, section 7.1. This assumes that counter is filled with +// zeros on entry. +func (g *gcm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) { + // GCM has two modes of operation with respect to the initial counter + // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path" + // for nonces of other lengths. For a 96-bit nonce, the nonce, along + // with a four-byte big-endian counter starting at one, is used + // directly as the starting counter. For other nonce sizes, the counter + // is computed by passing it through the GHASH function. + if len(nonce) == gcmStandardNonceSize { + copy(counter[:], nonce) + counter[gcmBlockSize-1] = 1 + } else { + var y gcmFieldElement + g.update(&y, nonce) + y.high ^= uint64(len(nonce)) * 8 + g.mul(&y) + binary.BigEndian.PutUint64(counter[:8], y.low) + binary.BigEndian.PutUint64(counter[8:], y.high) + } +} + +// auth calculates GHASH(ciphertext, additionalData), masks the result with +// tagMask and writes the result to out. +func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) { + var y gcmFieldElement + g.update(&y, additionalData) + g.update(&y, ciphertext) + + y.low ^= uint64(len(additionalData)) * 8 + y.high ^= uint64(len(ciphertext)) * 8 + + g.mul(&y) + + binary.BigEndian.PutUint64(out, y.low) + binary.BigEndian.PutUint64(out[8:], y.high) + + xorWords(out, out, tagMask[:]) +} diff --git a/src/crypto/cipher/gcm_test.go b/src/crypto/cipher/gcm_test.go new file mode 100644 index 0000000..0d53e47 --- /dev/null +++ b/src/crypto/cipher/gcm_test.go @@ -0,0 +1,511 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/hex" + "errors" + "io" + "reflect" + "testing" +) + +var aesGCMTests = []struct { + key, nonce, plaintext, ad, result string +}{ + { + "11754cd72aec309bf52f7687212e8957", + "3c819d9a9bed087615030b65", + "", + "", + "250327c674aaf477aef2675748cf6971", + }, + { + "ca47248ac0b6f8372a97ac43508308ed", + "ffd2b598feabc9019262d2be", + "", + "", + "60d20404af527d248d893ae495707d1a", + }, + { + "fbe3467cc254f81be8e78d765a2e6333", + "c6697351ff4aec29cdbaabf2", + "", + "67", + "3659cdc25288bf499ac736c03bfc1159", + }, + { + "8a7f9d80d08ad0bd5a20fb689c88f9fc", + "88b7b27d800937fda4f47301", + "", + "50edd0503e0d7b8c91608eb5a1", + "ed6f65322a4740011f91d2aae22dd44e", + }, + { + "051758e95ed4abb2cdc69bb454110e82", + "c99a66320db73158a35a255d", + "", + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339f", + "6ce77f1a5616c505b6aec09420234036", + }, + { + "77be63708971c4e240d1cb79e8d77feb", + "e0e00f19fed7ba0136a797f3", + "", + "7a43ec1d9c0a5a78a0b16533a6213cab", + "209fcc8d3675ed938e9c7166709dd946", + }, + { + "7680c5d3ca6154758e510f4d25b98820", + "f8f105f9c3df4965780321f8", + "", + "c94c410194c765e3dcc7964379758ed3", + "94dca8edfcf90bb74b153c8d48a17930", + }, + { + "7fddb57453c241d03efbed3ac44e371c", + "ee283a3fc75575e33efd4887", + "d5de42b461646c255c87bd2962d3b9a2", + "", + "2ccda4a5415cb91e135c2a0f78c9b2fdb36d1df9b9d5e596f83e8b7f52971cb3", + }, + { + "ab72c77b97cb5fe9a382d9fe81ffdbed", + "54cc7dc2c37ec006bcc6d1da", + "007c5e5b3e59df24a7c355584fc1518d", + "", + "0e1bde206a07a9c2c1b65300f8c649972b4401346697138c7a4891ee59867d0c", + }, + { + "fe47fcce5fc32665d2ae399e4eec72ba", + "5adb9609dbaeb58cbd6e7275", + "7c0e88c88899a779228465074797cd4c2e1498d259b54390b85e3eef1c02df60e743f1b840382c4bccaf3bafb4ca8429bea063", + "88319d6e1d3ffa5f987199166c8a9b56c2aeba5a", + "98f4826f05a265e6dd2be82db241c0fbbbf9ffb1c173aa83964b7cf5393043736365253ddbc5db8778371495da76d269e5db3e291ef1982e4defedaa2249f898556b47", + }, + { + "ec0c2ba17aa95cd6afffe949da9cc3a8", + "296bce5b50b7d66096d627ef", + "b85b3753535b825cbe5f632c0b843c741351f18aa484281aebec2f45bb9eea2d79d987b764b9611f6c0f8641843d5d58f3a242", + "f8d00f05d22bf68599bcdeb131292ad6e2df5d14", + "a7443d31c26bdf2a1c945e29ee4bd344a99cfaf3aa71f8b3f191f83c2adfc7a07162995506fde6309ffc19e716eddf1a828c5a890147971946b627c40016da1ecf3e77", + }, + { + "2c1f21cf0f6fb3661943155c3e3d8492", + "23cb5ff362e22426984d1907", + "42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d68b5615ba7c1220ff6510e259f06655d8", + "5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f4488f33cfb5e979e42b6e1cfc0a60238982a7aec", + "81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222b6ad57af43e1895df9dca2a5344a62cc57a3ee28136e94c74838997ae9823f3a", + }, + { + "d9f7d2411091f947b4d6f1e2d1f0fb2e", + "e1934f5db57cc983e6b180e7", + "73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490c2c6f6166f4a59431e182663fcaea05a", + "0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a20115d2e51398344b16bee1ed7c499b353d6c597af8", + "aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d573c7891c2a91fbc48db29967ec9542b2321b51ca862cb637cdd03b99a0f93b134", + }, + { + "fe9bb47deb3a61e423c2231841cfd1fb", + "4d328eb776f500a2f7fb47aa", + "f1cc3818e421876bb6b8bbd6c9", + "", + "b88c5c1977b35b517b0aeae96743fd4727fe5cdb4b5b42818dea7ef8c9", + }, + { + "6703df3701a7f54911ca72e24dca046a", + "12823ab601c350ea4bc2488c", + "793cd125b0b84a043e3ac67717", + "", + "b2051c80014f42f08735a7b0cd38e6bcd29962e5f2c13626b85a877101", + }, + // These cases test non-standard nonce sizes. + { + "1672c3537afa82004c6b8a46f6f0d026", + "05", + "", + "", + "8e2ad721f9455f74d8b53d3141f27e8e", + }, + { + "9a4fea86a621a91ab371e492457796c0", + "75", + "ca6131faf0ff210e4e693d6c31c109fc5b6f54224eb120f37de31dc59ec669b6", + "4f6e2585c161f05a9ae1f2f894e9f0ab52b45d0f", + "5698c0a384241d30004290aac56bb3ece6fe8eacc5c4be98954deb9c3ff6aebf5d50e1af100509e1fba2a5e8a0af9670", + }, + { + "d0f1f4defa1e8c08b4b26d576392027c", + "42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac", + "", + "", + "7ab49b57ddf5f62c427950111c5c4f0d", + }, + { + "4a0c00a3d284dea9d4bf8b8dde86685e", + "f8cbe82588e784bcacbe092cd9089b51e01527297f635bf294b3aa787d91057ef23869789698ac960707857f163ecb242135a228ad93964f5dc4a4d7f88fd7b3b07dd0a5b37f9768fb05a523639f108c34c661498a56879e501a2321c8a4a94d7e1b89db255ac1f685e185263368e99735ebe62a7f2931b47282be8eb165e4d7", + "6d4bf87640a6a48a50d28797b7", + "8d8c7ffc55086d539b5a8f0d1232654c", + "0d803ec309482f35b8e6226f2b56303239298e06b281c2d51aaba3c125", + }, + { + "0e18a844ac5bf38e4cd72d9b0942e506", + "0870d4b28a2954489a0abcd5", + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b3", + "05eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea9", + "cace28f4976afd72e3c5128167eb788fbf6634dda0a2f53148d00f6fa557f5e9e8f736c12e450894af56cb67f7d99e1027258c8571bd91ee3b7360e0d508aa1f382411a16115f9c05251cc326d4016f62e0eb8151c048465b0c6c8ff12558d43310e18b2cb1889eec91557ce21ba05955cf4c1d4847aadfb1b0a83f3a3b82b7efa62a5f03c5d6eda381a85dd78dbc55c", + }, + { + "1f6c3a3bc0542aabba4ef8f6c7169e73", + "f3584606472b260e0dd2ebb2", + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d8def4f89d4b66335c1c7e4248367d8ed9612ec453902d8e50af89d7709d1a596c1f41f", + "95aa82ca6c49ae90cd1668baac7aa6f2b4a8ca99b2c2372acb08cf61c9c3805e6e0328da4cd76a19edd2d3994c798b0022569ad418d1fee4d9cd45a391c601ffc92ad91501432fee150287617c13629e69fc7281cd7165a63eab49cf714bce3a75a74f76ea7e64ff81eb61fdfec39b67bf0de98c7e4e32bdf97c8c6ac75ba43c02f4b2ed7216ecf3014df000108b67cf99505b179f8ed4980a6103d1bca70dbe9bbfab0ed59801d6e5f2d6f67d3ec5168e212e2daf02c6b963c98a1f7097de0c56891a2b211b01070dd8fd8b16c2a1a4e3cfd292d2984b3561d555d16c33ddc2bcf7edde13efe520c7e2abdda44d81881c531aeeeb66244c3b791ea8acfb6a68", + "55864065117e07650ca650a0f0d9ef4b02aee7c58928462fddb49045bf85355b4653fa26158210a7f3ef5b3ca48612e8b7adf5c025c1b821960af770d935df1c9a1dd25077d6b1c7f937b2e20ce981b07980880214698f3fad72fa370b3b7da257ce1d0cf352bc5304fada3e0f8927bd4e5c1abbffa563bdedcb567daa64faaed748cb361732200ba3506836a3c1c82aafa14c76dc07f6c4277ff2c61325f91fdbd6c1883e745fcaadd5a6d692eeaa5ad56eead6a9d74a595d22757ed89532a4b8831e2b9e2315baea70a9b95d228f09d491a5ed5ab7076766703457e3159bbb9b17b329525669863153079448c68cd2f200c0be9d43061a60639cb59d50993d276c05caaa565db8ce633b2673e4012bebbca02b1a64d779d04066f3e949ece173825885ec816468c819a8129007cc05d8785c48077d09eb1abcba14508dde85a6f16a744bc95faef24888d53a8020515ab20307efaecbdf143a26563c67989bceedc2d6d2bb9699bb6c615d93767e4158c1124e3b6c723aaa47796e59a60d3696cd85adfae9a62f2c02c22009f80ed494bdc587f31dd892c253b5c6d6b7db078fa72d23474ee54f8144d6561182d71c862941dbc0b2cb37a4d4b23cbad5637e6be901cc73f16d5aec39c60dddee631511e57b47520b61ae1892d2d1bd2b486e30faec892f171b6de98d96108016fac805604761f8e74742b3bb7dc8a290a46bf697c3e4446e6e65832cbae7cf1aaad1", + }, + { + "0795d80bc7f40f4d41c280271a2e4f7f", + "ff824c906594aff365d3cb1f", + "1ad4e74d127f935beee57cff920665babe7ce56227377afe570ba786193ded3412d4812453157f42fafc418c02a746c1232c234a639d49baa8f041c12e2ef540027764568ce49886e0d913e28059a3a485c6eee96337a30b28e4cd5612c2961539fa6bc5de034cbedc5fa15db844013e0bef276e27ca7a4faf47a5c1093bd643354108144454d221b3737e6cb87faac36ed131959babe44af2890cfcc4e23ffa24470e689ce0894f5407bb0c8665cff536008ad2ac6f1c9ef8289abd0bd9b72f21c597bda5210cf928c805af2dd4a464d52e36819d521f967bba5386930ab5b4cf4c71746d7e6e964673457348e9d71d170d9eb560bd4bdb779e610ba816bf776231ebd0af5966f5cdab6815944032ab4dd060ad8dab880549e910f1ffcf6862005432afad", + "98a47a430d8fd74dc1829a91e3481f8ed024d8ba34c9b903321b04864db333e558ae28653dffb2", + "3b8f91443480e647473a0a0b03d571c622b7e70e4309a02c9bb7980053010d865e6aec161354dc9f481b2cd5213e09432b57ec4e58fbd0a8549dd15c8c4e74a6529f75fad0ce5a9e20e2beeb2f91eb638bf88999968de438d2f1cedbfb0a1c81f9e8e7362c738e0fddd963692a4f4df9276b7f040979ce874cf6fa3de26da0713784bdb25e4efcb840554ef5b38b5fe8380549a496bd8e423a7456df6f4ae78a07ebe2276a8e22fc2243ec4f78abe0c99c733fd67c8c492699fa5ee2289cdd0a8d469bf883520ee74efb854bfadc7366a49ee65ca4e894e3335e2b672618d362eee12a577dd8dc2ba55c49c1fc3ad68180e9b112d0234d4aa28f5661f1e036450ca6f18be0166676bd80f8a4890c6ddea306fabb7ff3cb2860aa32a827e3a312912a2dfa70f6bc1c07de238448f2d751bd0cf15bf7", + }, + { + "e2e001a36c60d2bf40d69ff5b2b1161ea218db263be16a4e", + "84230643130d05425826641e", + "adb034f3f4a7ca45e2993812d113a9821d50df151af978bccc6d3bc113e15bc0918fb385377dca1916022ce816d56a332649484043c0fc0f2d37d040182b00a9bbb42ef231f80b48fb3730110d9a4433e38c73264c703579a705b9c031b969ec6d98de9f90e9e78b21179c2eb1e061946cd4bbb844f031ecf6eaac27a4151311adf1b03eda97c9fbae66295f468af4b35faf6ba39f9d8f95873bbc2b51cf3dfec0ed3c9b850696336cc093b24a8765a936d14dd56edc6bf518272169f75e67b74ba452d0aae90416a997c8f31e2e9d54ffea296dc69462debc8347b3e1af6a2d53bdfdfda601134f98db42b609df0a08c9347590c8d86e845bb6373d65a26ab85f67b50569c85401a396b8ad76c2b53ff62bcfbf033e435ef47b9b591d05117c6dc681d68e", + "d5d7316b8fdee152942148bff007c22e4b2022c6bc7be3c18c5f2e52e004e0b5dc12206bf002bd", + "f2c39423ee630dfe961da81909159dba018ce09b1073a12a477108316af5b7a31f86be6a0548b572d604bd115ea737dde899e0bd7f7ac9b23e38910dc457551ecc15c814a9f46d8432a1a36097dc1afe2712d1ba0838fa88cb55d9f65a2e9bece0dbf8999562503989041a2c87d7eb80ef649769d2f4978ce5cf9664f2bd0849646aa81cb976e45e1ade2f17a8126219e917aadbb4bae5e2c4b3f57bbc7f13fcc807df7842d9727a1b389e0b749e5191482adacabd812627c6eae2c7a30caf0844ad2a22e08f39edddf0ae10413e47db433dfe3febbb5a5cec9ade21fbba1e548247579395880b747669a8eb7e2ec0c1bff7fed2defdb92b07a14edf07b1bde29c31ab052ff1214e6b5ebbefcb8f21b5d6f8f6e07ee57ad6e14d4e142cb3f51bb465ab3a28a2a12f01b7514ad0463f2bde0d71d221", + }, + { + "5394e890d37ba55ec9d5f327f15680f6a63ef5279c79331643ad0af6d2623525", + "815e840b7aca7af3b324583f", + "8e63067cd15359f796b43c68f093f55fdf3589fc5f2fdfad5f9d156668a617f7091d73da71cdd207810e6f71a165d0809a597df9885ca6e8f9bb4e616166586b83cc45f49917fc1a256b8bc7d05c476ab5c4633e20092619c4747b26dad3915e9fd65238ee4e5213badeda8a3a22f5efe6582d0762532026c89b4ca26fdd000eb45347a2a199b55b7790e6b1b2dba19833ce9f9522c0bcea5b088ccae68dd99ae0203c81b9f1dd3181c3e2339e83ccd1526b67742b235e872bea5111772aab574ae7d904d9b6355a79178e179b5ae8edc54f61f172bf789ea9c9af21f45b783e4251421b077776808f04972a5e801723cf781442378ce0e0568f014aea7a882dcbcb48d342be53d1c2ebfb206b12443a8a587cc1e55ca23beca385d61d0d03e9d84cbc1b0a", + "0feccdfae8ed65fa31a0858a1c466f79e8aa658c2f3ba93c3f92158b4e30955e1c62580450beff", + "b69a7e17bb5af688883274550a4ded0d1aff49a0b18343f4b382f745c163f7f714c9206a32a1ff012427e19431951edd0a755e5f491b0eedfd7df68bbc6085dd2888607a2f998c3e881eb1694109250db28291e71f4ad344a125624fb92e16ea9815047cd1111cabfdc9cb8c3b4b0f40aa91d31774009781231400789ed545404af6c3f76d07ddc984a7bd8f52728159782832e298cc4d529be96d17be898efd83e44dc7b0e2efc645849fd2bba61fef0ae7be0dcab233cc4e2b7ba4e887de9c64b97f2a1818aa54371a8d629dae37975f7784e5e3cc77055ed6e975b1e5f55e6bbacdc9f295ce4ada2c16113cd5b323cf78b7dde39f4a87aa8c141a31174e3584ccbd380cf5ec6d1dba539928b084fa9683e9c0953acf47cc3ac384a2c38914f1da01fb2cfd78905c2b58d36b2574b9df15535d82", + }, + // These cases test non-standard tag sizes. + { + "89c54b0d3bc3c397d5039058c220685f", + "bc7f45c00868758d62d4bb4d", + "582670b0baf5540a3775b6615605bd05", + "48d16cda0337105a50e2ed76fd18e114", + "fc2d4c4eee2209ddbba6663c02765e6955e783b00156f5da0446e2970b877f", + }, + { + "bad6049678bf75c9087b3e3ae7e72c13", + "a0a017b83a67d8f1b883e561", + "a1be93012f05a1958440f74a5311f4a1", + "f7c27b51d5367161dc2ff1e9e3edc6f2", + "36f032f7e3dc3275ca22aedcdc68436b99a2227f8bb69d45ea5d8842cd08", + }, + { + "66a3c722ccf9709525650973ecc100a9", + "1621d42d3a6d42a2d2bf9494", + "61fa9dbbed2190fbc2ffabf5d2ea4ff8", + "d7a9b6523b8827068a6354a6d166c6b9", + "fef3b20f40e08a49637cc82f4c89b8603fd5c0132acfab97b5fff651c4", + }, + { + "562ae8aadb8d23e0f271a99a7d1bd4d1", + "f7a5e2399413b89b6ad31aff", + "bbdc3504d803682aa08a773cde5f231a", + "2b9680b886b3efb7c6354b38c63b5373", + "e2b7e5ed5ff27fc8664148f5a628a46dcbf2015184fffb82f2651c36", + }, + { + "11754cd72aec309bf52f7687212e8957", + "", + "", + "", + "250327c674aaf477aef2675748cf6971", + }, +} + +func TestAESGCM(t *testing.T) { + for i, test := range aesGCMTests { + key, _ := hex.DecodeString(test.key) + aes, err := aes.NewCipher(key) + if err != nil { + t.Fatal(err) + } + + nonce, _ := hex.DecodeString(test.nonce) + plaintext, _ := hex.DecodeString(test.plaintext) + ad, _ := hex.DecodeString(test.ad) + tagSize := (len(test.result) - len(test.plaintext)) / 2 + + var aesgcm cipher.AEAD + switch { + // Handle non-standard tag sizes + case tagSize != 16: + aesgcm, err = cipher.NewGCMWithTagSize(aes, tagSize) + if err != nil { + t.Fatal(err) + } + + // Handle 0 nonce size (expect error and continue) + case len(nonce) == 0: + aesgcm, err = cipher.NewGCMWithNonceSize(aes, 0) + if err == nil { + t.Fatal("expected error for zero nonce size") + } + continue + + // Handle non-standard nonce sizes + case len(nonce) != 12: + aesgcm, err = cipher.NewGCMWithNonceSize(aes, len(nonce)) + if err != nil { + t.Fatal(err) + } + + default: + aesgcm, err = cipher.NewGCM(aes) + if err != nil { + t.Fatal(err) + } + } + + ct := aesgcm.Seal(nil, nonce, plaintext, ad) + if ctHex := hex.EncodeToString(ct); ctHex != test.result { + t.Errorf("#%d: got %s, want %s", i, ctHex, test.result) + continue + } + + plaintext2, err := aesgcm.Open(nil, nonce, ct, ad) + if err != nil { + t.Errorf("#%d: Open failed", i) + continue + } + + if !bytes.Equal(plaintext, plaintext2) { + t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) + continue + } + + if len(ad) > 0 { + ad[0] ^= 0x80 + if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil { + t.Errorf("#%d: Open was successful after altering additional data", i) + } + ad[0] ^= 0x80 + } + + nonce[0] ^= 0x80 + if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil { + t.Errorf("#%d: Open was successful after altering nonce", i) + } + nonce[0] ^= 0x80 + + ct[0] ^= 0x80 + if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil { + t.Errorf("#%d: Open was successful after altering ciphertext", i) + } + ct[0] ^= 0x80 + } +} + +func TestGCMInvalidTagSize(t *testing.T) { + key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed") + + aes, _ := aes.NewCipher(key) + + for _, tagSize := range []int{0, 1, aes.BlockSize() + 1} { + aesgcm, err := cipher.NewGCMWithTagSize(aes, tagSize) + if aesgcm != nil || err == nil { + t.Fatalf("NewGCMWithNonceAndTagSize was successful with an invalid %d-byte tag size", tagSize) + } + } +} + +func TestTagFailureOverwrite(t *testing.T) { + // The AESNI GCM code decrypts and authenticates concurrently and so + // overwrites the output buffer before checking the authentication tag. + // In order to be consistent across platforms, all implementations + // should do this and this test checks that. + + key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed") + nonce, _ := hex.DecodeString("54cc7dc2c37ec006bcc6d1db") + ciphertext, _ := hex.DecodeString("0e1bde206a07a9c2c1b65300f8c649972b4401346697138c7a4891ee59867d0c") + + aes, _ := aes.NewCipher(key) + aesgcm, _ := cipher.NewGCM(aes) + + dst := make([]byte, len(ciphertext)-16) + for i := range dst { + dst[i] = 42 + } + + result, err := aesgcm.Open(dst[:0], nonce, ciphertext, nil) + if err == nil { + t.Fatal("Bad Open still resulted in nil error.") + } + + if result != nil { + t.Fatal("Failed Open returned non-nil result.") + } + + for i := range dst { + if dst[i] != 0 { + t.Fatal("Failed Open didn't zero dst buffer") + } + } +} + +func TestGCMCounterWrap(t *testing.T) { + // Test that the last 32-bits of the counter wrap correctly. + tests := []struct { + nonce, tag string + }{ + {"0fa72e25", "37e1948cdfff09fbde0c40ad99fee4a7"}, // counter: 7eb59e4d961dad0dfdd75aaffffffff0 + {"afe05cc1", "438f3aa9fee5e54903b1927bca26bbdf"}, // counter: 75d492a7e6e6bfc979ad3a8ffffffff4 + {"9ffecbef", "7b88ca424df9703e9e8611071ec7e16e"}, // counter: c8bb108b0ecdc71747b9d57ffffffff5 + {"ffc3e5b3", "38d49c86e0abe853ac250e66da54c01a"}, // counter: 706414d2de9b36ab3b900a9ffffffff6 + {"cfdd729d", "e08402eaac36a1a402e09b1bd56500e8"}, // counter: cd0b96fe36b04e750584e56ffffffff7 + {"010ae3d486", "5405bb490b1f95d01e2ba735687154bc"}, // counter: e36c18e69406c49722808104fffffff8 + {"01b1107a9d", "939a585f342e01e17844627492d44dbf"}, // counter: e6d56eaf9127912b6d62c6dcffffffff + } + key, err := aes.NewCipher(make([]byte, 16)) + if err != nil { + t.Fatal(err) + } + plaintext := make([]byte, 16*17+1) + for i, test := range tests { + nonce, _ := hex.DecodeString(test.nonce) + want, _ := hex.DecodeString(test.tag) + aead, err := cipher.NewGCMWithNonceSize(key, len(nonce)) + if err != nil { + t.Fatal(err) + } + got := aead.Seal(nil, nonce, plaintext, nil) + if !bytes.Equal(got[len(plaintext):], want) { + t.Errorf("test[%v]: got: %x, want: %x", i, got[len(plaintext):], want) + } + _, err = aead.Open(nil, nonce, got, nil) + if err != nil { + t.Errorf("test[%v]: authentication failed", i) + } + } +} + +var _ cipher.Block = (*wrapper)(nil) + +type wrapper struct { + block cipher.Block +} + +func (w *wrapper) BlockSize() int { return w.block.BlockSize() } +func (w *wrapper) Encrypt(dst, src []byte) { w.block.Encrypt(dst, src) } +func (w *wrapper) Decrypt(dst, src []byte) { w.block.Decrypt(dst, src) } + +// wrap wraps the Block interface so that it does not fulfill +// any optimizing interfaces such as gcmAble. +func wrap(b cipher.Block) cipher.Block { + return &wrapper{b} +} + +func TestGCMAsm(t *testing.T) { + // Create a new pair of AEADs, one using the assembly implementation + // and one using the generic Go implementation. + newAESGCM := func(key []byte) (asm, generic cipher.AEAD, err error) { + block, err := aes.NewCipher(key[:]) + if err != nil { + return nil, nil, err + } + asm, err = cipher.NewGCM(block) + if err != nil { + return nil, nil, err + } + generic, err = cipher.NewGCM(wrap(block)) + if err != nil { + return nil, nil, err + } + return asm, generic, nil + } + + // check for assembly implementation + var key [16]byte + asm, generic, err := newAESGCM(key[:]) + if err != nil { + t.Fatal(err) + } + if reflect.TypeOf(asm) == reflect.TypeOf(generic) { + t.Skipf("no assembly implementation of GCM") + } + + // generate permutations + type pair struct{ align, length int } + lengths := []int{0, 156, 8192, 8193, 8208} + keySizes := []int{16, 24, 32} + alignments := []int{0, 1, 2, 3} + if testing.Short() { + keySizes = []int{16} + alignments = []int{1} + } + perms := make([]pair, 0) + for _, l := range lengths { + for _, a := range alignments { + if a != 0 && l == 0 { + continue + } + perms = append(perms, pair{align: a, length: l}) + } + } + + // run test for all permutations + test := func(ks int, pt, ad []byte) error { + key := make([]byte, ks) + if _, err := io.ReadFull(rand.Reader, key); err != nil { + return err + } + asm, generic, err := newAESGCM(key) + if err != nil { + return err + } + if _, err := io.ReadFull(rand.Reader, pt); err != nil { + return err + } + if _, err := io.ReadFull(rand.Reader, ad); err != nil { + return err + } + nonce := make([]byte, 12) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return err + } + want := generic.Seal(nil, nonce, pt, ad) + got := asm.Seal(nil, nonce, pt, ad) + if !bytes.Equal(want, got) { + return errors.New("incorrect Seal output") + } + got, err = asm.Open(nil, nonce, want, ad) + if err != nil { + return errors.New("authentication failed") + } + if !bytes.Equal(pt, got) { + return errors.New("incorrect Open output") + } + return nil + } + for _, a := range perms { + ad := make([]byte, a.align+a.length) + ad = ad[a.align:] + for _, p := range perms { + pt := make([]byte, p.align+p.length) + pt = pt[p.align:] + for _, ks := range keySizes { + if err := test(ks, pt, ad); err != nil { + t.Error(err) + t.Errorf(" key size: %v", ks) + t.Errorf(" plaintext alignment: %v", p.align) + t.Errorf(" plaintext length: %v", p.length) + t.Errorf(" additionalData alignment: %v", a.align) + t.Fatalf(" additionalData length: %v", a.length) + } + } + } + } +} diff --git a/src/crypto/cipher/io.go b/src/crypto/cipher/io.go new file mode 100644 index 0000000..0974ac7 --- /dev/null +++ b/src/crypto/cipher/io.go @@ -0,0 +1,53 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher + +import "io" + +// The Stream* objects are so simple that all their members are public. Users +// can create them themselves. + +// StreamReader wraps a Stream into an io.Reader. It calls XORKeyStream +// to process each slice of data which passes through. +type StreamReader struct { + S Stream + R io.Reader +} + +func (r StreamReader) Read(dst []byte) (n int, err error) { + n, err = r.R.Read(dst) + r.S.XORKeyStream(dst[:n], dst[:n]) + return +} + +// StreamWriter wraps a Stream into an io.Writer. It calls XORKeyStream +// to process each slice of data which passes through. If any Write call +// returns short then the StreamWriter is out of sync and must be discarded. +// A StreamWriter has no internal buffering; Close does not need +// to be called to flush write data. +type StreamWriter struct { + S Stream + W io.Writer + Err error // unused +} + +func (w StreamWriter) Write(src []byte) (n int, err error) { + c := make([]byte, len(src)) + w.S.XORKeyStream(c, src) + n, err = w.W.Write(c) + if n != len(src) && err == nil { // should never happen + err = io.ErrShortWrite + } + return +} + +// Close closes the underlying Writer and returns its Close return value, if the Writer +// is also an io.Closer. Otherwise it returns nil. +func (w StreamWriter) Close() error { + if c, ok := w.W.(io.Closer); ok { + return c.Close() + } + return nil +} diff --git a/src/crypto/cipher/ofb.go b/src/crypto/cipher/ofb.go new file mode 100644 index 0000000..fc47724 --- /dev/null +++ b/src/crypto/cipher/ofb.go @@ -0,0 +1,74 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// OFB (Output Feedback) Mode. + +package cipher + +import "crypto/internal/subtle" + +type ofb struct { + b Block + cipher []byte + out []byte + outUsed int +} + +// NewOFB returns a Stream that encrypts or decrypts using the block cipher b +// in output feedback mode. The initialization vector iv's length must be equal +// to b's block size. +func NewOFB(b Block, iv []byte) Stream { + blockSize := b.BlockSize() + if len(iv) != blockSize { + panic("cipher.NewOFB: IV length must equal block size") + } + bufSize := streamBufferSize + if bufSize < blockSize { + bufSize = blockSize + } + x := &ofb{ + b: b, + cipher: make([]byte, blockSize), + out: make([]byte, 0, bufSize), + outUsed: 0, + } + + copy(x.cipher, iv) + return x +} + +func (x *ofb) refill() { + bs := x.b.BlockSize() + remain := len(x.out) - x.outUsed + if remain > x.outUsed { + return + } + copy(x.out, x.out[x.outUsed:]) + x.out = x.out[:cap(x.out)] + for remain < len(x.out)-bs { + x.b.Encrypt(x.cipher, x.cipher) + copy(x.out[remain:], x.cipher) + remain += bs + } + x.out = x.out[:remain] + x.outUsed = 0 +} + +func (x *ofb) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } + for len(src) > 0 { + if x.outUsed >= len(x.out)-x.b.BlockSize() { + x.refill() + } + n := xorBytes(dst, src, x.out[x.outUsed:]) + dst = dst[n:] + src = src[n:] + x.outUsed += n + } +} diff --git a/src/crypto/cipher/ofb_test.go b/src/crypto/cipher/ofb_test.go new file mode 100644 index 0000000..8d3c5d3 --- /dev/null +++ b/src/crypto/cipher/ofb_test.go @@ -0,0 +1,102 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// OFB AES test vectors. + +// See U.S. National Institute of Standards and Technology (NIST) +// Special Publication 800-38A, ``Recommendation for Block Cipher +// Modes of Operation,'' 2001 Edition, pp. 52-55. + +package cipher_test + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "testing" +) + +type ofbTest struct { + name string + key []byte + iv []byte + in []byte + out []byte +} + +var ofbTests = []ofbTest{ + // NIST SP 800-38A pp 52-55 + { + "OFB-AES128", + commonKey128, + commonIV, + commonInput, + []byte{ + 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e, + }, + }, + { + "OFB-AES192", + commonKey192, + commonIV, + commonInput, + []byte{ + 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a, + }, + }, + { + "OFB-AES256", + commonKey256, + commonIV, + commonInput, + []byte{ + 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84, + }, + }, +} + +func TestOFB(t *testing.T) { + for _, tt := range ofbTests { + test := tt.name + + c, err := aes.NewCipher(tt.key) + if err != nil { + t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err) + continue + } + + for j := 0; j <= 5; j += 5 { + plaintext := tt.in[0 : len(tt.in)-j] + ofb := cipher.NewOFB(c, tt.iv) + ciphertext := make([]byte, len(plaintext)) + ofb.XORKeyStream(ciphertext, plaintext) + if !bytes.Equal(ciphertext, tt.out[:len(plaintext)]) { + t.Errorf("%s/%d: encrypting\ninput % x\nhave % x\nwant % x", test, len(plaintext), plaintext, ciphertext, tt.out) + } + } + + for j := 0; j <= 5; j += 5 { + ciphertext := tt.out[0 : len(tt.in)-j] + ofb := cipher.NewOFB(c, tt.iv) + plaintext := make([]byte, len(ciphertext)) + ofb.XORKeyStream(plaintext, ciphertext) + if !bytes.Equal(plaintext, tt.in[:len(ciphertext)]) { + t.Errorf("%s/%d: decrypting\nhave % x\nwant % x", test, len(ciphertext), plaintext, tt.in) + } + } + + if t.Failed() { + break + } + } +} diff --git a/src/crypto/cipher/xor_amd64.go b/src/crypto/cipher/xor_amd64.go new file mode 100644 index 0000000..a595acc --- /dev/null +++ b/src/crypto/cipher/xor_amd64.go @@ -0,0 +1,27 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher + +// xorBytes xors the bytes in a and b. The destination should have enough +// space, otherwise xorBytes will panic. Returns the number of bytes xor'd. +func xorBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + if n == 0 { + return 0 + } + _ = dst[n-1] + xorBytesSSE2(&dst[0], &a[0], &b[0], n) // amd64 must have SSE2 + return n +} + +func xorWords(dst, a, b []byte) { + xorBytes(dst, a, b) +} + +//go:noescape +func xorBytesSSE2(dst, a, b *byte, n int) diff --git a/src/crypto/cipher/xor_amd64.s b/src/crypto/cipher/xor_amd64.s new file mode 100644 index 0000000..780d37a --- /dev/null +++ b/src/crypto/cipher/xor_amd64.s @@ -0,0 +1,54 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func xorBytesSSE2(dst, a, b *byte, n int) +TEXT ·xorBytesSSE2(SB), NOSPLIT, $0 + MOVQ dst+0(FP), BX + MOVQ a+8(FP), SI + MOVQ b+16(FP), CX + MOVQ n+24(FP), DX + TESTQ $15, DX // AND 15 & len, if not zero jump to not_aligned. + JNZ not_aligned + +aligned: + MOVQ $0, AX // position in slices + +loop16b: + MOVOU (SI)(AX*1), X0 // XOR 16byte forwards. + MOVOU (CX)(AX*1), X1 + PXOR X1, X0 + MOVOU X0, (BX)(AX*1) + ADDQ $16, AX + CMPQ DX, AX + JNE loop16b + RET + +loop_1b: + SUBQ $1, DX // XOR 1byte backwards. + MOVB (SI)(DX*1), DI + MOVB (CX)(DX*1), AX + XORB AX, DI + MOVB DI, (BX)(DX*1) + TESTQ $7, DX // AND 7 & len, if not zero jump to loop_1b. + JNZ loop_1b + CMPQ DX, $0 // if len is 0, ret. + JE ret + TESTQ $15, DX // AND 15 & len, if zero jump to aligned. + JZ aligned + +not_aligned: + TESTQ $7, DX // AND $7 & len, if not zero jump to loop_1b. + JNE loop_1b + SUBQ $8, DX // XOR 8bytes backwards. + MOVQ (SI)(DX*1), DI + MOVQ (CX)(DX*1), AX + XORQ AX, DI + MOVQ DI, (BX)(DX*1) + CMPQ DX, $16 // if len is greater or equal 16 here, it must be aligned. + JGE aligned + +ret: + RET diff --git a/src/crypto/cipher/xor_arm64.go b/src/crypto/cipher/xor_arm64.go new file mode 100644 index 0000000..35a785a --- /dev/null +++ b/src/crypto/cipher/xor_arm64.go @@ -0,0 +1,29 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher + +// xorBytes xors the bytes in a and b. The destination should have enough +// space, otherwise xorBytes will panic. Returns the number of bytes xor'd. +func xorBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + if n == 0 { + return 0 + } + // make sure dst has enough space + _ = dst[n-1] + + xorBytesARM64(&dst[0], &a[0], &b[0], n) + return n +} + +func xorWords(dst, a, b []byte) { + xorBytes(dst, a, b) +} + +//go:noescape +func xorBytesARM64(dst, a, b *byte, n int) diff --git a/src/crypto/cipher/xor_arm64.s b/src/crypto/cipher/xor_arm64.s new file mode 100644 index 0000000..669852d --- /dev/null +++ b/src/crypto/cipher/xor_arm64.s @@ -0,0 +1,67 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func xorBytesARM64(dst, a, b *byte, n int) +TEXT ·xorBytesARM64(SB), NOSPLIT|NOFRAME, $0 + MOVD dst+0(FP), R0 + MOVD a+8(FP), R1 + MOVD b+16(FP), R2 + MOVD n+24(FP), R3 + CMP $64, R3 + BLT tail +loop_64: + VLD1.P 64(R1), [V0.B16, V1.B16, V2.B16, V3.B16] + VLD1.P 64(R2), [V4.B16, V5.B16, V6.B16, V7.B16] + VEOR V0.B16, V4.B16, V4.B16 + VEOR V1.B16, V5.B16, V5.B16 + VEOR V2.B16, V6.B16, V6.B16 + VEOR V3.B16, V7.B16, V7.B16 + VST1.P [V4.B16, V5.B16, V6.B16, V7.B16], 64(R0) + SUBS $64, R3 + CMP $64, R3 + BGE loop_64 +tail: + // quick end + CBZ R3, end + TBZ $5, R3, less_than32 + VLD1.P 32(R1), [V0.B16, V1.B16] + VLD1.P 32(R2), [V2.B16, V3.B16] + VEOR V0.B16, V2.B16, V2.B16 + VEOR V1.B16, V3.B16, V3.B16 + VST1.P [V2.B16, V3.B16], 32(R0) +less_than32: + TBZ $4, R3, less_than16 + LDP.P 16(R1), (R11, R12) + LDP.P 16(R2), (R13, R14) + EOR R11, R13, R13 + EOR R12, R14, R14 + STP.P (R13, R14), 16(R0) +less_than16: + TBZ $3, R3, less_than8 + MOVD.P 8(R1), R11 + MOVD.P 8(R2), R12 + EOR R11, R12, R12 + MOVD.P R12, 8(R0) +less_than8: + TBZ $2, R3, less_than4 + MOVWU.P 4(R1), R13 + MOVWU.P 4(R2), R14 + EORW R13, R14, R14 + MOVWU.P R14, 4(R0) +less_than4: + TBZ $1, R3, less_than2 + MOVHU.P 2(R1), R15 + MOVHU.P 2(R2), R16 + EORW R15, R16, R16 + MOVHU.P R16, 2(R0) +less_than2: + TBZ $0, R3, end + MOVBU (R1), R17 + MOVBU (R2), R19 + EORW R17, R19, R19 + MOVBU R19, (R0) +end: + RET diff --git a/src/crypto/cipher/xor_generic.go b/src/crypto/cipher/xor_generic.go new file mode 100644 index 0000000..0320840 --- /dev/null +++ b/src/crypto/cipher/xor_generic.go @@ -0,0 +1,92 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 && !ppc64 && !ppc64le && !arm64 +// +build !amd64,!ppc64,!ppc64le,!arm64 + +package cipher + +import ( + "runtime" + "unsafe" +) + +// xorBytes xors the bytes in a and b. The destination should have enough +// space, otherwise xorBytes will panic. Returns the number of bytes xor'd. +func xorBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + if n == 0 { + return 0 + } + + switch { + case supportsUnaligned: + fastXORBytes(dst, a, b, n) + default: + // TODO(hanwen): if (dst, a, b) have common alignment + // we could still try fastXORBytes. It is not clear + // how often this happens, and it's only worth it if + // the block encryption itself is hardware + // accelerated. + safeXORBytes(dst, a, b, n) + } + return n +} + +const wordSize = int(unsafe.Sizeof(uintptr(0))) +const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" + +// fastXORBytes xors in bulk. It only works on architectures that +// support unaligned read/writes. +// n needs to be smaller or equal than the length of a and b. +func fastXORBytes(dst, a, b []byte, n int) { + // Assert dst has enough space + _ = dst[n-1] + + w := n / wordSize + if w > 0 { + dw := *(*[]uintptr)(unsafe.Pointer(&dst)) + aw := *(*[]uintptr)(unsafe.Pointer(&a)) + bw := *(*[]uintptr)(unsafe.Pointer(&b)) + for i := 0; i < w; i++ { + dw[i] = aw[i] ^ bw[i] + } + } + + for i := (n - n%wordSize); i < n; i++ { + dst[i] = a[i] ^ b[i] + } +} + +// n needs to be smaller or equal than the length of a and b. +func safeXORBytes(dst, a, b []byte, n int) { + for i := 0; i < n; i++ { + dst[i] = a[i] ^ b[i] + } +} + +// fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.) +// The arguments are assumed to be of equal length. +func fastXORWords(dst, a, b []byte) { + dw := *(*[]uintptr)(unsafe.Pointer(&dst)) + aw := *(*[]uintptr)(unsafe.Pointer(&a)) + bw := *(*[]uintptr)(unsafe.Pointer(&b)) + n := len(b) / wordSize + for i := 0; i < n; i++ { + dw[i] = aw[i] ^ bw[i] + } +} + +// fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.) +// The slice arguments a and b are assumed to be of equal length. +func xorWords(dst, a, b []byte) { + if supportsUnaligned { + fastXORWords(dst, a, b) + } else { + safeXORBytes(dst, a, b, len(b)) + } +} diff --git a/src/crypto/cipher/xor_ppc64x.go b/src/crypto/cipher/xor_ppc64x.go new file mode 100644 index 0000000..f520208 --- /dev/null +++ b/src/crypto/cipher/xor_ppc64x.go @@ -0,0 +1,30 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ppc64 || ppc64le +// +build ppc64 ppc64le + +package cipher + +// xorBytes xors the bytes in a and b. The destination should have enough +// space, otherwise xorBytes will panic. Returns the number of bytes xor'd. +func xorBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + if n == 0 { + return 0 + } + _ = dst[n-1] + xorBytesVSX(&dst[0], &a[0], &b[0], n) + return n +} + +func xorWords(dst, a, b []byte) { + xorBytes(dst, a, b) +} + +//go:noescape +func xorBytesVSX(dst, a, b *byte, n int) diff --git a/src/crypto/cipher/xor_ppc64x.s b/src/crypto/cipher/xor_ppc64x.s new file mode 100644 index 0000000..2ba6d96 --- /dev/null +++ b/src/crypto/cipher/xor_ppc64x.s @@ -0,0 +1,88 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ppc64 || ppc64le +// +build ppc64 ppc64le + +#include "textflag.h" + +// func xorBytesVSX(dst, a, b *byte, n int) +TEXT ·xorBytesVSX(SB), NOSPLIT, $0 + MOVD dst+0(FP), R3 // R3 = dst + MOVD a+8(FP), R4 // R4 = a + MOVD b+16(FP), R5 // R5 = b + MOVD n+24(FP), R6 // R6 = n + + CMPU R6, $32, CR7 // Check if n ≥ 32 bytes + MOVD R0, R8 // R8 = index + CMPU R6, $8, CR6 // Check if 8 ≤ n < 32 bytes + BLT CR6, small // Smaller than 8 + BLT CR7, xor16 // Case for 16 ≤ n < 32 bytes + + // Case for n ≥ 32 bytes +preloop32: + SRD $5, R6, R7 // Setup loop counter + MOVD R7, CTR + MOVD $16, R10 + ANDCC $31, R6, R9 // Check for tailing bytes for later +loop32: + LXVD2X (R4)(R8), VS32 // VS32 = a[i,...,i+15] + LXVD2X (R4)(R10), VS34 + LXVD2X (R5)(R8), VS33 // VS33 = b[i,...,i+15] + LXVD2X (R5)(R10), VS35 + XXLXOR VS32, VS33, VS32 // VS34 = a[] ^ b[] + XXLXOR VS34, VS35, VS34 + STXVD2X VS32, (R3)(R8) // Store to dst + STXVD2X VS34, (R3)(R10) + ADD $32, R8 // Update index + ADD $32, R10 + BC 16, 0, loop32 // bdnz loop16 + + BEQ CR0, done + + MOVD R9, R6 + CMP R6, $8 + BLT small +xor16: + CMP R6, $16 + BLT xor8 + LXVD2X (R4)(R8), VS32 + LXVD2X (R5)(R8), VS33 + XXLXOR VS32, VS33, VS32 + STXVD2X VS32, (R3)(R8) + ADD $16, R8 + ADD $-16, R6 + CMP R6, $8 + BLT small +xor8: + // Case for 8 ≤ n < 16 bytes + MOVD (R4)(R8), R14 // R14 = a[i,...,i+7] + MOVD (R5)(R8), R15 // R15 = b[i,...,i+7] + XOR R14, R15, R16 // R16 = a[] ^ b[] + SUB $8, R6 // n = n - 8 + MOVD R16, (R3)(R8) // Store to dst + ADD $8, R8 + + // Check if we're finished + CMP R6, R0 + BGT small + RET + + // Case for n < 8 bytes and tailing bytes from the + // previous cases. +small: + CMP R6, R0 + BEQ done + MOVD R6, CTR // Setup loop counter + +loop: + MOVBZ (R4)(R8), R14 // R14 = a[i] + MOVBZ (R5)(R8), R15 // R15 = b[i] + XOR R14, R15, R16 // R16 = a[i] ^ b[i] + MOVB R16, (R3)(R8) // Store to dst + ADD $1, R8 + BC 16, 0, loop // bdnz loop + +done: + RET diff --git a/src/crypto/cipher/xor_test.go b/src/crypto/cipher/xor_test.go new file mode 100644 index 0000000..4f829e9 --- /dev/null +++ b/src/crypto/cipher/xor_test.go @@ -0,0 +1,75 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cipher_test + +import ( + "bytes" + "crypto/cipher" + "crypto/rand" + "fmt" + "io" + "testing" +) + +func TestXOR(t *testing.T) { + for j := 1; j <= 1024; j++ { + if testing.Short() && j > 16 { + break + } + for alignP := 0; alignP < 2; alignP++ { + for alignQ := 0; alignQ < 2; alignQ++ { + for alignD := 0; alignD < 2; alignD++ { + p := make([]byte, j)[alignP:] + q := make([]byte, j)[alignQ:] + d1 := make([]byte, j+alignD)[alignD:] + d2 := make([]byte, j+alignD)[alignD:] + if _, err := io.ReadFull(rand.Reader, p); err != nil { + t.Fatal(err) + } + if _, err := io.ReadFull(rand.Reader, q); err != nil { + t.Fatal(err) + } + cipher.XorBytes(d1, p, q) + n := min(p, q) + for i := 0; i < n; i++ { + d2[i] = p[i] ^ q[i] + } + if !bytes.Equal(d1, d2) { + t.Logf("p: %#v", p) + t.Logf("q: %#v", q) + t.Logf("expect: %#v", d2) + t.Logf("result: %#v", d1) + t.Fatal("not equal") + } + } + } + } + } +} + +func min(a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + return n +} + +func BenchmarkXORBytes(b *testing.B) { + dst := make([]byte, 1<<15) + data0 := make([]byte, 1<<15) + data1 := make([]byte, 1<<15) + sizes := []int64{1 << 3, 1 << 7, 1 << 11, 1 << 15} + for _, size := range sizes { + b.Run(fmt.Sprintf("%dBytes", size), func(b *testing.B) { + s0 := data0[:size] + s1 := data1[:size] + b.SetBytes(int64(size)) + for i := 0; i < b.N; i++ { + cipher.XorBytes(dst, s0, s1) + } + }) + } +} diff --git a/src/crypto/crypto.go b/src/crypto/crypto.go new file mode 100644 index 0000000..ce473b5 --- /dev/null +++ b/src/crypto/crypto.go @@ -0,0 +1,203 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package crypto collects common cryptographic constants. +package crypto + +import ( + "hash" + "io" + "strconv" +) + +// Hash identifies a cryptographic hash function that is implemented in another +// package. +type Hash uint + +// HashFunc simply returns the value of h so that Hash implements SignerOpts. +func (h Hash) HashFunc() Hash { + return h +} + +func (h Hash) String() string { + switch h { + case MD4: + return "MD4" + case MD5: + return "MD5" + case SHA1: + return "SHA-1" + case SHA224: + return "SHA-224" + case SHA256: + return "SHA-256" + case SHA384: + return "SHA-384" + case SHA512: + return "SHA-512" + case MD5SHA1: + return "MD5+SHA1" + case RIPEMD160: + return "RIPEMD-160" + case SHA3_224: + return "SHA3-224" + case SHA3_256: + return "SHA3-256" + case SHA3_384: + return "SHA3-384" + case SHA3_512: + return "SHA3-512" + case SHA512_224: + return "SHA-512/224" + case SHA512_256: + return "SHA-512/256" + case BLAKE2s_256: + return "BLAKE2s-256" + case BLAKE2b_256: + return "BLAKE2b-256" + case BLAKE2b_384: + return "BLAKE2b-384" + case BLAKE2b_512: + return "BLAKE2b-512" + default: + return "unknown hash value " + strconv.Itoa(int(h)) + } +} + +const ( + MD4 Hash = 1 + iota // import golang.org/x/crypto/md4 + MD5 // import crypto/md5 + SHA1 // import crypto/sha1 + SHA224 // import crypto/sha256 + SHA256 // import crypto/sha256 + SHA384 // import crypto/sha512 + SHA512 // import crypto/sha512 + MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA + RIPEMD160 // import golang.org/x/crypto/ripemd160 + SHA3_224 // import golang.org/x/crypto/sha3 + SHA3_256 // import golang.org/x/crypto/sha3 + SHA3_384 // import golang.org/x/crypto/sha3 + SHA3_512 // import golang.org/x/crypto/sha3 + SHA512_224 // import crypto/sha512 + SHA512_256 // import crypto/sha512 + BLAKE2s_256 // import golang.org/x/crypto/blake2s + BLAKE2b_256 // import golang.org/x/crypto/blake2b + BLAKE2b_384 // import golang.org/x/crypto/blake2b + BLAKE2b_512 // import golang.org/x/crypto/blake2b + maxHash +) + +var digestSizes = []uint8{ + MD4: 16, + MD5: 16, + SHA1: 20, + SHA224: 28, + SHA256: 32, + SHA384: 48, + SHA512: 64, + SHA512_224: 28, + SHA512_256: 32, + SHA3_224: 28, + SHA3_256: 32, + SHA3_384: 48, + SHA3_512: 64, + MD5SHA1: 36, + RIPEMD160: 20, + BLAKE2s_256: 32, + BLAKE2b_256: 32, + BLAKE2b_384: 48, + BLAKE2b_512: 64, +} + +// Size returns the length, in bytes, of a digest resulting from the given hash +// function. It doesn't require that the hash function in question be linked +// into the program. +func (h Hash) Size() int { + if h > 0 && h < maxHash { + return int(digestSizes[h]) + } + panic("crypto: Size of unknown hash function") +} + +var hashes = make([]func() hash.Hash, maxHash) + +// New returns a new hash.Hash calculating the given hash function. New panics +// if the hash function is not linked into the binary. +func (h Hash) New() hash.Hash { + if h > 0 && h < maxHash { + f := hashes[h] + if f != nil { + return f() + } + } + panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable") +} + +// Available reports whether the given hash function is linked into the binary. +func (h Hash) Available() bool { + return h < maxHash && hashes[h] != nil +} + +// RegisterHash registers a function that returns a new instance of the given +// hash function. This is intended to be called from the init function in +// packages that implement hash functions. +func RegisterHash(h Hash, f func() hash.Hash) { + if h >= maxHash { + panic("crypto: RegisterHash of unknown hash function") + } + hashes[h] = f +} + +// PublicKey represents a public key using an unspecified algorithm. +type PublicKey interface{} + +// PrivateKey represents a private key using an unspecified algorithm. +type PrivateKey interface{} + +// Signer is an interface for an opaque private key that can be used for +// signing operations. For example, an RSA key kept in a hardware module. +type Signer interface { + // Public returns the public key corresponding to the opaque, + // private key. + Public() PublicKey + + // Sign signs digest with the private key, possibly using entropy from + // rand. For an RSA key, the resulting signature should be either a + // PKCS #1 v1.5 or PSS signature (as indicated by opts). For an (EC)DSA + // key, it should be a DER-serialised, ASN.1 signature structure. + // + // Hash implements the SignerOpts interface and, in most cases, one can + // simply pass in the hash function used as opts. Sign may also attempt + // to type assert opts to other types in order to obtain algorithm + // specific values. See the documentation in each package for details. + // + // Note that when a signature of a hash of a larger message is needed, + // the caller is responsible for hashing the larger message and passing + // the hash (as digest) and the hash function (as opts) to Sign. + Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error) +} + +// SignerOpts contains options for signing with a Signer. +type SignerOpts interface { + // HashFunc returns an identifier for the hash function used to produce + // the message passed to Signer.Sign, or else zero to indicate that no + // hashing was done. + HashFunc() Hash +} + +// Decrypter is an interface for an opaque private key that can be used for +// asymmetric decryption operations. An example would be an RSA key +// kept in a hardware module. +type Decrypter interface { + // Public returns the public key corresponding to the opaque, + // private key. + Public() PublicKey + + // Decrypt decrypts msg. The opts argument should be appropriate for + // the primitive used. See the documentation in each implementation for + // details. + Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error) +} + +type DecrypterOpts interface{} diff --git a/src/crypto/des/block.go b/src/crypto/des/block.go new file mode 100644 index 0000000..cc2888e --- /dev/null +++ b/src/crypto/des/block.go @@ -0,0 +1,263 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package des + +import ( + "encoding/binary" + "sync" +) + +func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) { + b := binary.BigEndian.Uint64(src) + b = permuteInitialBlock(b) + left, right := uint32(b>>32), uint32(b) + + left = (left << 1) | (left >> 31) + right = (right << 1) | (right >> 31) + + if decrypt { + for i := 0; i < 8; i++ { + left, right = feistel(left, right, subkeys[15-2*i], subkeys[15-(2*i+1)]) + } + } else { + for i := 0; i < 8; i++ { + left, right = feistel(left, right, subkeys[2*i], subkeys[2*i+1]) + } + } + + left = (left << 31) | (left >> 1) + right = (right << 31) | (right >> 1) + + // switch left & right and perform final permutation + preOutput := (uint64(right) << 32) | uint64(left) + binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput)) +} + +// Encrypt one block from src into dst, using the subkeys. +func encryptBlock(subkeys []uint64, dst, src []byte) { + cryptBlock(subkeys, dst, src, false) +} + +// Decrypt one block from src into dst, using the subkeys. +func decryptBlock(subkeys []uint64, dst, src []byte) { + cryptBlock(subkeys, dst, src, true) +} + +// DES Feistel function. feistelBox must be initialized via +// feistelBoxOnce.Do(initFeistelBox) first. +func feistel(l, r uint32, k0, k1 uint64) (lout, rout uint32) { + var t uint32 + + t = r ^ uint32(k0>>32) + l ^= feistelBox[7][t&0x3f] ^ + feistelBox[5][(t>>8)&0x3f] ^ + feistelBox[3][(t>>16)&0x3f] ^ + feistelBox[1][(t>>24)&0x3f] + + t = ((r << 28) | (r >> 4)) ^ uint32(k0) + l ^= feistelBox[6][(t)&0x3f] ^ + feistelBox[4][(t>>8)&0x3f] ^ + feistelBox[2][(t>>16)&0x3f] ^ + feistelBox[0][(t>>24)&0x3f] + + t = l ^ uint32(k1>>32) + r ^= feistelBox[7][t&0x3f] ^ + feistelBox[5][(t>>8)&0x3f] ^ + feistelBox[3][(t>>16)&0x3f] ^ + feistelBox[1][(t>>24)&0x3f] + + t = ((l << 28) | (l >> 4)) ^ uint32(k1) + r ^= feistelBox[6][(t)&0x3f] ^ + feistelBox[4][(t>>8)&0x3f] ^ + feistelBox[2][(t>>16)&0x3f] ^ + feistelBox[0][(t>>24)&0x3f] + + return l, r +} + +// feistelBox[s][16*i+j] contains the output of permutationFunction +// for sBoxes[s][i][j] << 4*(7-s) +var feistelBox [8][64]uint32 + +var feistelBoxOnce sync.Once + +// general purpose function to perform DES block permutations +func permuteBlock(src uint64, permutation []uint8) (block uint64) { + for position, n := range permutation { + bit := (src >> n) & 1 + block |= bit << uint((len(permutation)-1)-position) + } + return +} + +func initFeistelBox() { + for s := range sBoxes { + for i := 0; i < 4; i++ { + for j := 0; j < 16; j++ { + f := uint64(sBoxes[s][i][j]) << (4 * (7 - uint(s))) + f = permuteBlock(f, permutationFunction[:]) + + // Row is determined by the 1st and 6th bit. + // Column is the middle four bits. + row := uint8(((i & 2) << 4) | i&1) + col := uint8(j << 1) + t := row | col + + // The rotation was performed in the feistel rounds, being factored out and now mixed into the feistelBox. + f = (f << 1) | (f >> 31) + + feistelBox[s][t] = uint32(f) + } + } + } +} + +// permuteInitialBlock is equivalent to the permutation defined +// by initialPermutation. +func permuteInitialBlock(block uint64) uint64 { + // block = b7 b6 b5 b4 b3 b2 b1 b0 (8 bytes) + b1 := block >> 48 + b2 := block << 48 + block ^= b1 ^ b2 ^ b1<<48 ^ b2>>48 + + // block = b1 b0 b5 b4 b3 b2 b7 b6 + b1 = block >> 32 & 0xff00ff + b2 = (block & 0xff00ff00) + block ^= b1<<32 ^ b2 ^ b1<<8 ^ b2<<24 // exchange b0 b4 with b3 b7 + + // block is now b1 b3 b5 b7 b0 b2 b4 b6, the permutation: + // ... 8 + // ... 24 + // ... 40 + // ... 56 + // 7 6 5 4 3 2 1 0 + // 23 22 21 20 19 18 17 16 + // ... 32 + // ... 48 + + // exchange 4,5,6,7 with 32,33,34,35 etc. + b1 = block & 0x0f0f00000f0f0000 + b2 = block & 0x0000f0f00000f0f0 + block ^= b1 ^ b2 ^ b1>>12 ^ b2<<12 + + // block is the permutation: + // + // [+8] [+40] + // + // 7 6 5 4 + // 23 22 21 20 + // 3 2 1 0 + // 19 18 17 16 [+32] + + // exchange 0,1,4,5 with 18,19,22,23 + b1 = block & 0x3300330033003300 + b2 = block & 0x00cc00cc00cc00cc + block ^= b1 ^ b2 ^ b1>>6 ^ b2<<6 + + // block is the permutation: + // 15 14 + // 13 12 + // 11 10 + // 9 8 + // 7 6 + // 5 4 + // 3 2 + // 1 0 [+16] [+32] [+64] + + // exchange 0,2,4,6 with 9,11,13,15: + b1 = block & 0xaaaaaaaa55555555 + block ^= b1 ^ b1>>33 ^ b1<<33 + + // block is the permutation: + // 6 14 22 30 38 46 54 62 + // 4 12 20 28 36 44 52 60 + // 2 10 18 26 34 42 50 58 + // 0 8 16 24 32 40 48 56 + // 7 15 23 31 39 47 55 63 + // 5 13 21 29 37 45 53 61 + // 3 11 19 27 35 43 51 59 + // 1 9 17 25 33 41 49 57 + return block +} + +// permuteInitialBlock is equivalent to the permutation defined +// by finalPermutation. +func permuteFinalBlock(block uint64) uint64 { + // Perform the same bit exchanges as permuteInitialBlock + // but in reverse order. + b1 := block & 0xaaaaaaaa55555555 + block ^= b1 ^ b1>>33 ^ b1<<33 + + b1 = block & 0x3300330033003300 + b2 := block & 0x00cc00cc00cc00cc + block ^= b1 ^ b2 ^ b1>>6 ^ b2<<6 + + b1 = block & 0x0f0f00000f0f0000 + b2 = block & 0x0000f0f00000f0f0 + block ^= b1 ^ b2 ^ b1>>12 ^ b2<<12 + + b1 = block >> 32 & 0xff00ff + b2 = (block & 0xff00ff00) + block ^= b1<<32 ^ b2 ^ b1<<8 ^ b2<<24 + + b1 = block >> 48 + b2 = block << 48 + block ^= b1 ^ b2 ^ b1<<48 ^ b2>>48 + return block +} + +// creates 16 28-bit blocks rotated according +// to the rotation schedule +func ksRotate(in uint32) (out []uint32) { + out = make([]uint32, 16) + last := in + for i := 0; i < 16; i++ { + // 28-bit circular left shift + left := (last << (4 + ksRotations[i])) >> 4 + right := (last << 4) >> (32 - ksRotations[i]) + out[i] = left | right + last = out[i] + } + return +} + +// creates 16 56-bit subkeys from the original key +func (c *desCipher) generateSubkeys(keyBytes []byte) { + feistelBoxOnce.Do(initFeistelBox) + + // apply PC1 permutation to key + key := binary.BigEndian.Uint64(keyBytes) + permutedKey := permuteBlock(key, permutedChoice1[:]) + + // rotate halves of permuted key according to the rotation schedule + leftRotations := ksRotate(uint32(permutedKey >> 28)) + rightRotations := ksRotate(uint32(permutedKey<<4) >> 4) + + // generate subkeys + for i := 0; i < 16; i++ { + // combine halves to form 56-bit input to PC2 + pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i]) + // apply PC2 permutation to 7 byte input + c.subkeys[i] = unpack(permuteBlock(pc2Input, permutedChoice2[:])) + } +} + +// Expand 48-bit input to 64-bit, with each 6-bit block padded by extra two bits at the top. +// By doing so, we can have the input blocks (four bits each), and the key blocks (six bits each) well-aligned without +// extra shifts/rotations for alignments. +func unpack(x uint64) uint64 { + var result uint64 + + result = ((x>>(6*1))&0xff)<<(8*0) | + ((x>>(6*3))&0xff)<<(8*1) | + ((x>>(6*5))&0xff)<<(8*2) | + ((x>>(6*7))&0xff)<<(8*3) | + ((x>>(6*0))&0xff)<<(8*4) | + ((x>>(6*2))&0xff)<<(8*5) | + ((x>>(6*4))&0xff)<<(8*6) | + ((x>>(6*6))&0xff)<<(8*7) + + return result +} diff --git a/src/crypto/des/cipher.go b/src/crypto/des/cipher.go new file mode 100644 index 0000000..9e6779c --- /dev/null +++ b/src/crypto/des/cipher.go @@ -0,0 +1,155 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package des + +import ( + "crypto/cipher" + "crypto/internal/subtle" + "encoding/binary" + "strconv" +) + +// The DES block size in bytes. +const BlockSize = 8 + +type KeySizeError int + +func (k KeySizeError) Error() string { + return "crypto/des: invalid key size " + strconv.Itoa(int(k)) +} + +// desCipher is an instance of DES encryption. +type desCipher struct { + subkeys [16]uint64 +} + +// NewCipher creates and returns a new cipher.Block. +func NewCipher(key []byte) (cipher.Block, error) { + if len(key) != 8 { + return nil, KeySizeError(len(key)) + } + + c := new(desCipher) + c.generateSubkeys(key) + return c, nil +} + +func (c *desCipher) BlockSize() int { return BlockSize } + +func (c *desCipher) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/des: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/des: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/des: invalid buffer overlap") + } + encryptBlock(c.subkeys[:], dst, src) +} + +func (c *desCipher) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/des: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/des: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/des: invalid buffer overlap") + } + decryptBlock(c.subkeys[:], dst, src) +} + +// A tripleDESCipher is an instance of TripleDES encryption. +type tripleDESCipher struct { + cipher1, cipher2, cipher3 desCipher +} + +// NewTripleDESCipher creates and returns a new cipher.Block. +func NewTripleDESCipher(key []byte) (cipher.Block, error) { + if len(key) != 24 { + return nil, KeySizeError(len(key)) + } + + c := new(tripleDESCipher) + c.cipher1.generateSubkeys(key[:8]) + c.cipher2.generateSubkeys(key[8:16]) + c.cipher3.generateSubkeys(key[16:]) + return c, nil +} + +func (c *tripleDESCipher) BlockSize() int { return BlockSize } + +func (c *tripleDESCipher) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/des: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/des: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/des: invalid buffer overlap") + } + + b := binary.BigEndian.Uint64(src) + b = permuteInitialBlock(b) + left, right := uint32(b>>32), uint32(b) + + left = (left << 1) | (left >> 31) + right = (right << 1) | (right >> 31) + + for i := 0; i < 8; i++ { + left, right = feistel(left, right, c.cipher1.subkeys[2*i], c.cipher1.subkeys[2*i+1]) + } + for i := 0; i < 8; i++ { + right, left = feistel(right, left, c.cipher2.subkeys[15-2*i], c.cipher2.subkeys[15-(2*i+1)]) + } + for i := 0; i < 8; i++ { + left, right = feistel(left, right, c.cipher3.subkeys[2*i], c.cipher3.subkeys[2*i+1]) + } + + left = (left << 31) | (left >> 1) + right = (right << 31) | (right >> 1) + + preOutput := (uint64(right) << 32) | uint64(left) + binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput)) +} + +func (c *tripleDESCipher) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/des: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/des: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/des: invalid buffer overlap") + } + + b := binary.BigEndian.Uint64(src) + b = permuteInitialBlock(b) + left, right := uint32(b>>32), uint32(b) + + left = (left << 1) | (left >> 31) + right = (right << 1) | (right >> 31) + + for i := 0; i < 8; i++ { + left, right = feistel(left, right, c.cipher3.subkeys[15-2*i], c.cipher3.subkeys[15-(2*i+1)]) + } + for i := 0; i < 8; i++ { + right, left = feistel(right, left, c.cipher2.subkeys[2*i], c.cipher2.subkeys[2*i+1]) + } + for i := 0; i < 8; i++ { + left, right = feistel(left, right, c.cipher1.subkeys[15-2*i], c.cipher1.subkeys[15-(2*i+1)]) + } + + left = (left << 31) | (left >> 1) + right = (right << 31) | (right >> 1) + + preOutput := (uint64(right) << 32) | uint64(left) + binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput)) +} diff --git a/src/crypto/des/const.go b/src/crypto/des/const.go new file mode 100644 index 0000000..a20879d --- /dev/null +++ b/src/crypto/des/const.go @@ -0,0 +1,142 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package des implements the Data Encryption Standard (DES) and the +// Triple Data Encryption Algorithm (TDEA) as defined +// in U.S. Federal Information Processing Standards Publication 46-3. +// +// DES is cryptographically broken and should not be used for secure +// applications. +package des + +// Used to perform an initial permutation of a 64-bit input block. +var initialPermutation = [64]byte{ + 6, 14, 22, 30, 38, 46, 54, 62, + 4, 12, 20, 28, 36, 44, 52, 60, + 2, 10, 18, 26, 34, 42, 50, 58, + 0, 8, 16, 24, 32, 40, 48, 56, + 7, 15, 23, 31, 39, 47, 55, 63, + 5, 13, 21, 29, 37, 45, 53, 61, + 3, 11, 19, 27, 35, 43, 51, 59, + 1, 9, 17, 25, 33, 41, 49, 57, +} + +// Used to perform a final permutation of a 4-bit preoutput block. This is the +// inverse of initialPermutation +var finalPermutation = [64]byte{ + 24, 56, 16, 48, 8, 40, 0, 32, + 25, 57, 17, 49, 9, 41, 1, 33, + 26, 58, 18, 50, 10, 42, 2, 34, + 27, 59, 19, 51, 11, 43, 3, 35, + 28, 60, 20, 52, 12, 44, 4, 36, + 29, 61, 21, 53, 13, 45, 5, 37, + 30, 62, 22, 54, 14, 46, 6, 38, + 31, 63, 23, 55, 15, 47, 7, 39, +} + +// Used to expand an input block of 32 bits, producing an output block of 48 +// bits. +var expansionFunction = [48]byte{ + 0, 31, 30, 29, 28, 27, 28, 27, + 26, 25, 24, 23, 24, 23, 22, 21, + 20, 19, 20, 19, 18, 17, 16, 15, + 16, 15, 14, 13, 12, 11, 12, 11, + 10, 9, 8, 7, 8, 7, 6, 5, + 4, 3, 4, 3, 2, 1, 0, 31, +} + +// Yields a 32-bit output from a 32-bit input +var permutationFunction = [32]byte{ + 16, 25, 12, 11, 3, 20, 4, 15, + 31, 17, 9, 6, 27, 14, 1, 22, + 30, 24, 8, 18, 0, 5, 29, 23, + 13, 19, 2, 26, 10, 21, 28, 7, +} + +// Used in the key schedule to select 56 bits +// from a 64-bit input. +var permutedChoice1 = [56]byte{ + 7, 15, 23, 31, 39, 47, 55, 63, + 6, 14, 22, 30, 38, 46, 54, 62, + 5, 13, 21, 29, 37, 45, 53, 61, + 4, 12, 20, 28, 1, 9, 17, 25, + 33, 41, 49, 57, 2, 10, 18, 26, + 34, 42, 50, 58, 3, 11, 19, 27, + 35, 43, 51, 59, 36, 44, 52, 60, +} + +// Used in the key schedule to produce each subkey by selecting 48 bits from +// the 56-bit input +var permutedChoice2 = [48]byte{ + 42, 39, 45, 32, 55, 51, 53, 28, + 41, 50, 35, 46, 33, 37, 44, 52, + 30, 48, 40, 49, 29, 36, 43, 54, + 15, 4, 25, 19, 9, 1, 26, 16, + 5, 11, 23, 8, 12, 7, 17, 0, + 22, 3, 10, 14, 6, 20, 27, 24, +} + +// 8 S-boxes composed of 4 rows and 16 columns +// Used in the DES cipher function +var sBoxes = [8][4][16]uint8{ + // S-box 1 + { + {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, + {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, + {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, + {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}, + }, + // S-box 2 + { + {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, + {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, + {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, + {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}, + }, + // S-box 3 + { + {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, + {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, + {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, + {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}, + }, + // S-box 4 + { + {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, + {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, + {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, + {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}, + }, + // S-box 5 + { + {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, + {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, + {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, + {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}, + }, + // S-box 6 + { + {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, + {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, + {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, + {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}, + }, + // S-box 7 + { + {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, + {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, + {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, + {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}, + }, + // S-box 8 + { + {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, + {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, + {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, + {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}, + }, +} + +// Size of left rotation per round in each half of the key schedule +var ksRotations = [16]uint8{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1} diff --git a/src/crypto/des/des_test.go b/src/crypto/des/des_test.go new file mode 100644 index 0000000..690a49f --- /dev/null +++ b/src/crypto/des/des_test.go @@ -0,0 +1,1583 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package des + +import ( + "bytes" + "testing" +) + +type CryptTest struct { + key []byte + in []byte + out []byte +} + +// some custom tests for DES +var encryptDESTests = []CryptTest{ + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7}}, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x35, 0x55, 0x50, 0xb2, 0x15, 0x0e, 0x24, 0x51}}, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0x61, 0x7b, 0x3a, 0x0c, 0xe8, 0xf0, 0x71, 0x00}}, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + []byte{0x92, 0x31, 0xf2, 0x36, 0xff, 0x9a, 0xa9, 0x5c}}, + { + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xca, 0xaa, 0xaf, 0x4d, 0xea, 0xf1, 0xdb, 0xae}}, + { + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x73, 0x59, 0xb2, 0x16, 0x3e, 0x4e, 0xdc, 0x58}}, + { + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0x6d, 0xce, 0x0d, 0xc9, 0x00, 0x65, 0x56, 0xa3}}, + { + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + []byte{0x9e, 0x84, 0xc5, 0xf3, 0x17, 0x0f, 0x8e, 0xff}}, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xd5, 0xd4, 0x4f, 0xf7, 0x20, 0x68, 0x3d, 0x0d}}, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x59, 0x73, 0x23, 0x56, 0xf3, 0x6f, 0xde, 0x06}}, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0x56, 0xcc, 0x09, 0xe7, 0xcf, 0xdc, 0x4c, 0xef}}, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + []byte{0x12, 0xc6, 0x26, 0xaf, 0x05, 0x8b, 0x43, 0x3b}}, + { + []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xa6, 0x8c, 0xdc, 0xa9, 0x0c, 0x90, 0x21, 0xf9}}, + { + []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x2a, 0x2b, 0xb0, 0x08, 0xdf, 0x97, 0xc2, 0xf2}}, + { + []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0xed, 0x39, 0xd9, 0x50, 0xfa, 0x74, 0xbc, 0xc4}}, + { + []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, + []byte{0xa9, 0x33, 0xf6, 0x18, 0x30, 0x23, 0xb3, 0x10}}, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, + []byte{0x17, 0x66, 0x8d, 0xfc, 0x72, 0x92, 0x53, 0x2d}}, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + []byte{0xb4, 0xfd, 0x23, 0x16, 0x47, 0xa5, 0xbe, 0xc0}}, + { + []byte{0x0e, 0x32, 0x92, 0x32, 0xea, 0x6d, 0x0d, 0x73}, + []byte{0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + { + []byte{0x73, 0x65, 0x63, 0x52, 0x33, 0x74, 0x24, 0x3b}, // "secR3t$;" + []byte{0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x31, 0x32}, // "a test12" + []byte{0x37, 0x0d, 0xee, 0x2c, 0x1f, 0xb4, 0xf7, 0xa5}}, + { + []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh" + []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh" + []byte{0x2a, 0x8d, 0x69, 0xde, 0x9d, 0x5f, 0xdf, 0xf9}}, + { + []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh" + []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678" + []byte{0x21, 0xc6, 0x0d, 0xa5, 0x34, 0x24, 0x8b, 0xce}}, + { + []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678" + []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh" + []byte{0x94, 0xd4, 0x43, 0x6b, 0xc3, 0xb5, 0xb6, 0x93}}, + { + []byte{0x1f, 0x79, 0x90, 0x5f, 0x88, 0x01, 0xc8, 0x88}, // random + []byte{0xc7, 0x46, 0x18, 0x73, 0xaf, 0x48, 0x5f, 0xb3}, // random + []byte{0xb0, 0x93, 0x50, 0x88, 0xf9, 0x92, 0x44, 0x6a}}, + { + []byte{0xe6, 0xf4, 0xf2, 0xdb, 0x31, 0x42, 0x53, 0x01}, // random + []byte{0xff, 0x3d, 0x25, 0x50, 0x12, 0xe3, 0x4a, 0xc5}, // random + []byte{0x86, 0x08, 0xd3, 0xd1, 0x6c, 0x2f, 0xd2, 0x55}}, + { + []byte{0x69, 0xc1, 0x9d, 0xc1, 0x15, 0xc5, 0xfb, 0x2b}, // random + []byte{0x1a, 0x22, 0x5c, 0xaf, 0x1f, 0x1d, 0xa3, 0xf9}, // random + []byte{0x64, 0xba, 0x31, 0x67, 0x56, 0x91, 0x1e, 0xa7}}, + { + []byte{0x6e, 0x5e, 0xe2, 0x47, 0xc4, 0xbf, 0xf6, 0x51}, // random + []byte{0x11, 0xc9, 0x57, 0xff, 0x66, 0x89, 0x0e, 0xf0}, // random + []byte{0x94, 0xc5, 0x35, 0xb2, 0xc5, 0x8b, 0x39, 0x72}}, +} + +var weakKeyTests = []CryptTest{ + { + []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + []byte{0x55, 0x74, 0xc0, 0xbd, 0x7c, 0xdf, 0xf7, 0x39}, // random + nil}, + { + []byte{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe}, + []byte{0xe8, 0xe1, 0xa7, 0xc1, 0xde, 0x11, 0x89, 0xaa}, // random + nil}, + { + []byte{0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1}, + []byte{0x50, 0x6a, 0x4b, 0x94, 0x3b, 0xed, 0x7d, 0xdc}, // random + nil}, + { + []byte{0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e}, + []byte{0x88, 0x81, 0x56, 0x38, 0xec, 0x3b, 0x1c, 0x97}, // random + nil}, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x17, 0xa0, 0x83, 0x62, 0x32, 0xfe, 0x9a, 0x0b}, // random + nil}, + { + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0xca, 0x8f, 0xca, 0x1f, 0x50, 0xc5, 0x7b, 0x49}, // random + nil}, + { + []byte{0xe1, 0xe1, 0xe1, 0xe1, 0xf0, 0xf0, 0xf0, 0xf0}, + []byte{0xb1, 0xea, 0xad, 0x7d, 0xe7, 0xc3, 0x7a, 0x43}, // random + nil}, + { + []byte{0x1e, 0x1e, 0x1e, 0x1e, 0x0f, 0x0f, 0x0f, 0x0f}, + []byte{0xae, 0x74, 0x7d, 0x6f, 0xef, 0x16, 0xbb, 0x81}, // random + nil}, +} + +var semiWeakKeyTests = []CryptTest{ + // key and out contain the semi-weak key pair + { + []byte{0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e}, + []byte{0x12, 0xfa, 0x31, 0x16, 0xf9, 0xc5, 0x0a, 0xe4}, // random + []byte{0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01}}, + { + []byte{0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1}, + []byte{0xb0, 0x4c, 0x7a, 0xee, 0xd2, 0xe5, 0x4d, 0xb7}, // random + []byte{0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01}}, + { + []byte{0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe}, + []byte{0xa4, 0x81, 0xcd, 0xb1, 0x64, 0x6f, 0xd3, 0xbc}, // random + []byte{0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01}}, + { + []byte{0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1}, + []byte{0xee, 0x27, 0xdd, 0x88, 0x4c, 0x22, 0xcd, 0xce}, // random + []byte{0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e}}, + { + []byte{0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe}, + []byte{0x19, 0x3d, 0xcf, 0x97, 0x70, 0xfb, 0xab, 0xe1}, // random + []byte{0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e}}, + { + []byte{0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe}, + []byte{0x7c, 0x82, 0x69, 0xe4, 0x1e, 0x86, 0x99, 0xd7}, // random + []byte{0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1}}, +} + +// some custom tests for TripleDES +var encryptTripleDESTests = []CryptTest{ + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x92, 0x95, 0xb5, 0x9b, 0xb3, 0x84, 0x73, 0x6e}}, + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0xc1, 0x97, 0xf5, 0x58, 0x74, 0x8a, 0x20, 0xe7}}, + { + []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x3e, 0x68, 0x0a, 0xa7, 0x8b, 0x75, 0xdf, 0x18}}, + { + []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x6d, 0x6a, 0x4a, 0x64, 0x4c, 0x7b, 0x8c, 0x91}}, + { + []byte{ // "abcdefgh12345678ABCDEFGH" + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, + []byte{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, // "00000000" + []byte{0xe4, 0x61, 0xb7, 0x59, 0x68, 0x8b, 0xff, 0x66}}, + { + []byte{ // "abcdefgh12345678ABCDEFGH" + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, + []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678" + []byte{0xdb, 0xd0, 0x92, 0xde, 0xf8, 0x34, 0xff, 0x58}}, + { + []byte{ // "abcdefgh12345678ABCDEFGH" + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, + []byte{0xf0, 0xc5, 0x82, 0x22, 0xd3, 0xe6, 0x12, 0xd2}, // random + []byte{0xba, 0xe4, 0x41, 0xb1, 0x3c, 0x37, 0x4d, 0xf4}}, + { + []byte{ // random + 0xd3, 0x7d, 0x45, 0xee, 0x22, 0xe9, 0xcf, 0x52, + 0xf4, 0x65, 0xa2, 0x4f, 0x70, 0xd1, 0x81, 0x8a, + 0x3d, 0xbe, 0x2f, 0x39, 0xc7, 0x71, 0xd2, 0xe9}, + []byte{0x49, 0x53, 0xc3, 0xe9, 0x78, 0xdf, 0x9f, 0xaf}, // random + []byte{0x53, 0x40, 0x51, 0x24, 0xd8, 0x3c, 0xf9, 0x88}}, + { + []byte{ // random + 0xcb, 0x10, 0x7d, 0xda, 0x7e, 0x96, 0x57, 0x0a, + 0xe8, 0xeb, 0xe8, 0x07, 0x8e, 0x87, 0xd3, 0x57, + 0xb2, 0x61, 0x12, 0xb8, 0x2a, 0x90, 0xb7, 0x2f}, + []byte{0xa3, 0xc2, 0x60, 0xb1, 0x0b, 0xb7, 0x28, 0x6e}, // random + []byte{0x56, 0x73, 0x7d, 0xfb, 0xb5, 0xa1, 0xc3, 0xde}}, +} + +// NIST Special Publication 800-20, Appendix A +// Key for use with Table A.1 tests +var tableA1Key = []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +} + +// Table A.1 Resulting Ciphertext from the Variable Plaintext Known Answer Test +var tableA1Tests = []CryptTest{ + {nil, // 0 + []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x95, 0xf8, 0xa5, 0xe5, 0xdd, 0x31, 0xd9, 0x00}}, + {nil, // 1 + []byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xdd, 0x7f, 0x12, 0x1c, 0xa5, 0x01, 0x56, 0x19}}, + {nil, // 2 + []byte{0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x2e, 0x86, 0x53, 0x10, 0x4f, 0x38, 0x34, 0xea}}, + {nil, // 3 + []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x4b, 0xd3, 0x88, 0xff, 0x6c, 0xd8, 0x1d, 0x4f}}, + {nil, // 4 + []byte{0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x20, 0xb9, 0xe7, 0x67, 0xb2, 0xfb, 0x14, 0x56}}, + {nil, // 5 + []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x55, 0x57, 0x93, 0x80, 0xd7, 0x71, 0x38, 0xef}}, + {nil, // 6 + []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x6c, 0xc5, 0xde, 0xfa, 0xaf, 0x04, 0x51, 0x2f}}, + {nil, // 7 + []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x0d, 0x9f, 0x27, 0x9b, 0xa5, 0xd8, 0x72, 0x60}}, + {nil, // 8 + []byte{0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xd9, 0x03, 0x1b, 0x02, 0x71, 0xbd, 0x5a, 0x0a}}, + {nil, // 9 + []byte{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x42, 0x42, 0x50, 0xb3, 0x7c, 0x3d, 0xd9, 0x51}}, + {nil, // 10 + []byte{0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xb8, 0x06, 0x1b, 0x7e, 0xcd, 0x9a, 0x21, 0xe5}}, + {nil, // 11 + []byte{0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xf1, 0x5d, 0x0f, 0x28, 0x6b, 0x65, 0xbd, 0x28}}, + {nil, // 12 + []byte{0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xad, 0xd0, 0xcc, 0x8d, 0x6e, 0x5d, 0xeb, 0xa1}}, + {nil, // 13 + []byte{0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xe6, 0xd5, 0xf8, 0x27, 0x52, 0xad, 0x63, 0xd1}}, + {nil, // 14 + []byte{0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xec, 0xbf, 0xe3, 0xbd, 0x3f, 0x59, 0x1a, 0x5e}}, + {nil, // 15 + []byte{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xf3, 0x56, 0x83, 0x43, 0x79, 0xd1, 0x65, 0xcd}}, + {nil, // 16 + []byte{0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x2b, 0x9f, 0x98, 0x2f, 0x20, 0x03, 0x7f, 0xa9}}, + {nil, // 17 + []byte{0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x88, 0x9d, 0xe0, 0x68, 0xa1, 0x6f, 0x0b, 0xe6}}, + {nil, // 18 + []byte{0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xe1, 0x9e, 0x27, 0x5d, 0x84, 0x6a, 0x12, 0x98}}, + {nil, // 19 + []byte{0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x32, 0x9a, 0x8e, 0xd5, 0x23, 0xd7, 0x1a, 0xec}}, + {nil, // 20 + []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xe7, 0xfc, 0xe2, 0x25, 0x57, 0xd2, 0x3c, 0x97}}, + {nil, // 21 + []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x12, 0xa9, 0xf5, 0x81, 0x7f, 0xf2, 0xd6, 0x5d}}, + {nil, // 22 + []byte{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xa4, 0x84, 0xc3, 0xad, 0x38, 0xdc, 0x9c, 0x19}}, + {nil, // 23 + []byte{0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xfb, 0xe0, 0x0a, 0x8a, 0x1e, 0xf8, 0xad, 0x72}}, + {nil, // 24 + []byte{0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00}, + []byte{0x75, 0x0d, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63}}, + {nil, // 25 + []byte{0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00}, + []byte{0x64, 0xfe, 0xed, 0x9c, 0x72, 0x4c, 0x2f, 0xaf}}, + {nil, // 26 + []byte{0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00}, + []byte{0xf0, 0x2b, 0x26, 0x3b, 0x32, 0x8e, 0x2b, 0x60}}, + {nil, // 27 + []byte{0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}, + []byte{0x9d, 0x64, 0x55, 0x5a, 0x9a, 0x10, 0xb8, 0x52}}, + {nil, // 28 + []byte{0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, + []byte{0xd1, 0x06, 0xff, 0x0b, 0xed, 0x52, 0x55, 0xd7}}, + {nil, // 29 + []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, + []byte{0xe1, 0x65, 0x2c, 0x6b, 0x13, 0x8c, 0x64, 0xa5}}, + {nil, // 30 + []byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}, + []byte{0xe4, 0x28, 0x58, 0x11, 0x86, 0xec, 0x8f, 0x46}}, + {nil, // 31 + []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, + []byte{0xae, 0xb5, 0xf5, 0xed, 0xe2, 0x2d, 0x1a, 0x36}}, + {nil, // 32 + []byte{0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00}, + []byte{0xe9, 0x43, 0xd7, 0x56, 0x8a, 0xec, 0x0c, 0x5c}}, + {nil, // 33 + []byte{0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00}, + []byte{0xdf, 0x98, 0xc8, 0x27, 0x6f, 0x54, 0xb0, 0x4b}}, + {nil, // 34 + []byte{0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}, + []byte{0xb1, 0x60, 0xe4, 0x68, 0x0f, 0x6c, 0x69, 0x6f}}, + {nil, // 35 + []byte{0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00}, + []byte{0xfa, 0x07, 0x52, 0xb0, 0x7d, 0x9c, 0x4a, 0xb8}}, + {nil, // 36 + []byte{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00}, + []byte{0xca, 0x3a, 0x2b, 0x03, 0x6d, 0xbc, 0x85, 0x02}}, + {nil, // 37 + []byte{0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}, + []byte{0x5e, 0x09, 0x05, 0x51, 0x7b, 0xb5, 0x9b, 0xcf}}, + {nil, // 38 + []byte{0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, + []byte{0x81, 0x4e, 0xeb, 0x3b, 0x91, 0xd9, 0x07, 0x26}}, + {nil, // 39 + []byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, + []byte{0x4d, 0x49, 0xdb, 0x15, 0x32, 0x91, 0x9c, 0x9f}}, + {nil, // 40 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00}, + []byte{0x25, 0xeb, 0x5f, 0xc3, 0xf8, 0xcf, 0x06, 0x21}}, + {nil, // 41 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00}, + []byte{0xab, 0x6a, 0x20, 0xc0, 0x62, 0x0d, 0x1c, 0x6f}}, + {nil, // 42 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00}, + []byte{0x79, 0xe9, 0x0d, 0xbc, 0x98, 0xf9, 0x2c, 0xca}}, + {nil, // 43 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}, + []byte{0x86, 0x6e, 0xce, 0xdd, 0x80, 0x72, 0xbb, 0x0e}}, + {nil, // 44 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00}, + []byte{0x8b, 0x54, 0x53, 0x6f, 0x2f, 0x3e, 0x64, 0xa8}}, + {nil, // 45 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}, + []byte{0xea, 0x51, 0xd3, 0x97, 0x55, 0x95, 0xb8, 0x6b}}, + {nil, // 46 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, + []byte{0xca, 0xff, 0xc6, 0xac, 0x45, 0x42, 0xde, 0x31}}, + {nil, // 47 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, + []byte{0x8d, 0xd4, 0x5a, 0x2d, 0xdf, 0x90, 0x79, 0x6c}}, + {nil, // 48 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00}, + []byte{0x10, 0x29, 0xd5, 0x5e, 0x88, 0x0e, 0xc2, 0xd0}}, + {nil, // 49 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00}, + []byte{0x5d, 0x86, 0xcb, 0x23, 0x63, 0x9d, 0xbe, 0xa9}}, + {nil, // 50 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00}, + []byte{0x1d, 0x1c, 0xa8, 0x53, 0xae, 0x7c, 0x0c, 0x5f}}, + {nil, // 51 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00}, + []byte{0xce, 0x33, 0x23, 0x29, 0x24, 0x8f, 0x32, 0x28}}, + {nil, // 52 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00}, + []byte{0x84, 0x05, 0xd1, 0xab, 0xe2, 0x4f, 0xb9, 0x42}}, + {nil, // 53 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00}, + []byte{0xe6, 0x43, 0xd7, 0x80, 0x90, 0xca, 0x42, 0x07}}, + {nil, // 54 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, + []byte{0x48, 0x22, 0x1b, 0x99, 0x37, 0x74, 0x8a, 0x23}}, + {nil, // 55 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + []byte{0xdd, 0x7c, 0x0b, 0xbd, 0x61, 0xfa, 0xfd, 0x54}}, + {nil, // 56 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + []byte{0x2f, 0xbc, 0x29, 0x1a, 0x57, 0x0d, 0xb5, 0xc4}}, + {nil, // 57 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}, + []byte{0xe0, 0x7c, 0x30, 0xd7, 0xe4, 0xe2, 0x6e, 0x12}}, + {nil, // 58 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20}, + []byte{0x09, 0x53, 0xe2, 0x25, 0x8e, 0x8e, 0x90, 0xa1}}, + {nil, // 59 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + []byte{0x5b, 0x71, 0x1b, 0xc4, 0xce, 0xeb, 0xf2, 0xee}}, + {nil, // 60 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, + []byte{0xcc, 0x08, 0x3f, 0x1e, 0x6d, 0x9e, 0x85, 0xf6}}, + {nil, // 61 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, + []byte{0xd2, 0xfd, 0x88, 0x67, 0xd5, 0x0d, 0x2d, 0xfe}}, + {nil, // 62 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + []byte{0x06, 0xe7, 0xea, 0x22, 0xce, 0x92, 0x70, 0x8f}}, + {nil, // 63 + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + []byte{0x16, 0x6b, 0x40, 0xb4, 0x4a, 0xba, 0x4b, 0xd6}}, +} + +// Plaintext for use with Table A.2 tests +var tableA2Plaintext = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + +// Table A.2 Resulting Ciphertext from the Variable Key Known Answer Test +var tableA2Tests = []CryptTest{ + { // 0 + []byte{ + 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x95, 0xa8, 0xd7, 0x28, 0x13, 0xda, 0xa9, 0x4d}}, + { // 1 + []byte{ + 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x0e, 0xec, 0x14, 0x87, 0xdd, 0x8c, 0x26, 0xd5}}, + { // 2 + []byte{ + 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x7a, 0xd1, 0x6f, 0xfb, 0x79, 0xc4, 0x59, 0x26}}, + { // 3 + []byte{ + 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xd3, 0x74, 0x62, 0x94, 0xca, 0x6a, 0x6c, 0xf3}}, + { // 4 + []byte{ + 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x80, 0x9f, 0x5f, 0x87, 0x3c, 0x1f, 0xd7, 0x61}}, + { // 5 + []byte{ + 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xc0, 0x2f, 0xaf, 0xfe, 0xc9, 0x89, 0xd1, 0xfc}}, + { // 6 + []byte{ + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x46, 0x15, 0xaa, 0x1d, 0x33, 0xe7, 0x2f, 0x10}}, + { // 7 + []byte{ + 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x20, 0x55, 0x12, 0x33, 0x50, 0xc0, 0x08, 0x58}}, + { // 8 + []byte{ + 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xdf, 0x3b, 0x99, 0xd6, 0x57, 0x73, 0x97, 0xc8}}, + { // 9 + []byte{ + 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x31, 0xfe, 0x17, 0x36, 0x9b, 0x52, 0x88, 0xc9}}, + { // 10 + []byte{ + 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xdf, 0xdd, 0x3c, 0xc6, 0x4d, 0xae, 0x16, 0x42}}, + { // 11 + []byte{ + 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x17, 0x8c, 0x83, 0xce, 0x2b, 0x39, 0x9d, 0x94}}, + { // 12 + []byte{ + 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x50, 0xf6, 0x36, 0x32, 0x4a, 0x9b, 0x7f, 0x80}}, + { // 13 + []byte{ + 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xa8, 0x46, 0x8e, 0xe3, 0xbc, 0x18, 0xf0, 0x6d}}, + { // 14 + []byte{ + 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xa2, 0xdc, 0x9e, 0x92, 0xfd, 0x3c, 0xde, 0x92}}, + { // 15 + []byte{ + 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xca, 0xc0, 0x9f, 0x79, 0x7d, 0x03, 0x12, 0x87}}, + { // 16 + []byte{ + 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x90, 0xba, 0x68, 0x0b, 0x22, 0xae, 0xb5, 0x25}}, + { // 17 + []byte{ + 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xce, 0x7a, 0x24, 0xf3, 0x50, 0xe2, 0x80, 0xb6}}, + { // 18 + []byte{ + 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x88, 0x2b, 0xff, 0x0a, 0xa0, 0x1a, 0x0b, 0x87}}, + { // 19 + []byte{ + 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xc2}}, + { // 20 + []byte{ + 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xc7, 0x15, 0x16, 0xc2, 0x9c, 0x75, 0xd1, 0x70}}, + { // 21 + []byte{ + 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x51, 0x99, 0xc2, 0x9a, 0x52, 0xc9, 0xf0, 0x59}}, + { // 22 + []byte{ + 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xc2, 0x2f, 0x0a, 0x29, 0x4a, 0x71, 0xf2, 0x9f}}, + { // 23 + []byte{ + 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xee, 0x37, 0x14, 0x83, 0x71, 0x4c, 0x02, 0xea}}, + { // 24 + []byte{ + 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xa8, 0x1f, 0xbd, 0x44, 0x8f, 0x9e, 0x52, 0x2f}}, + { // 25 + []byte{ + 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x4f, 0x64, 0x4c, 0x92, 0xe1, 0x92, 0xdf, 0xed}}, + { // 26 + []byte{ + 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0x1a, 0xfa, 0x9a, 0x66, 0xa6, 0xdf, 0x92, 0xae}}, + { // 27 + []byte{ + 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01}, + nil, + []byte{0xb3, 0xc1, 0xcc, 0x71, 0x5c, 0xb8, 0x79, 0xd8}}, + { // 28 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01}, + nil, + []byte{0x19, 0xd0, 0x32, 0xe6, 0x4a, 0xb0, 0xbd, 0x8b}}, + { // 29 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01}, + nil, + []byte{0x3c, 0xfa, 0xa7, 0xa7, 0xdc, 0x87, 0x20, 0xdc}}, + { // 30 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01}, + nil, + []byte{0xb7, 0x26, 0x5f, 0x7f, 0x44, 0x7a, 0xc6, 0xf3}}, + { // 31 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01}, + nil, + []byte{0x9d, 0xb7, 0x3b, 0x3c, 0x0d, 0x16, 0x3f, 0x54}}, + { // 32 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01}, + nil, + []byte{0x81, 0x81, 0xb6, 0x5b, 0xab, 0xf4, 0xa9, 0x75}}, + { // 33 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01}, + nil, + []byte{0x93, 0xc9, 0xb6, 0x40, 0x42, 0xea, 0xa2, 0x40}}, + { // 34 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01}, + nil, + []byte{0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92}}, + { // 35 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01}, + nil, + []byte{0x86, 0x38, 0x80, 0x9e, 0x87, 0x87, 0x87, 0xa0}}, + { // 36 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01}, + nil, + []byte{0x41, 0xb9, 0xa7, 0x9a, 0xf7, 0x9a, 0xc2, 0x08}}, + { // 37 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01}, + nil, + []byte{0x7a, 0x9b, 0xe4, 0x2f, 0x20, 0x09, 0xa8, 0x92}}, + { // 38 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01}, + nil, + []byte{0x29, 0x03, 0x8d, 0x56, 0xba, 0x6d, 0x27, 0x45}}, + { // 39 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01}, + nil, + []byte{0x54, 0x95, 0xc6, 0xab, 0xf1, 0xe5, 0xdf, 0x51}}, + { // 40 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01}, + nil, + []byte{0xae, 0x13, 0xdb, 0xd5, 0x61, 0x48, 0x89, 0x33}}, + { // 41 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01}, + nil, + []byte{0x02, 0x4d, 0x1f, 0xfa, 0x89, 0x04, 0xe3, 0x89}}, + { // 42 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01}, + nil, + []byte{0xd1, 0x39, 0x97, 0x12, 0xf9, 0x9b, 0xf0, 0x2e}}, + { // 43 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01}, + nil, + []byte{0x14, 0xc1, 0xd7, 0xc1, 0xcf, 0xfe, 0xc7, 0x9e}}, + { // 44 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01}, + nil, + []byte{0x1d, 0xe5, 0x27, 0x9d, 0xae, 0x3b, 0xed, 0x6f}}, + { // 45 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01}, + nil, + []byte{0xe9, 0x41, 0xa3, 0x3f, 0x85, 0x50, 0x13, 0x03}}, + { // 46 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01}, + nil, + []byte{0xda, 0x99, 0xdb, 0xbc, 0x9a, 0x03, 0xf3, 0x79}}, + { // 47 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01}, + nil, + []byte{0xb7, 0xfc, 0x92, 0xf9, 0x1d, 0x8e, 0x92, 0xe9}}, + { // 48 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01}, + nil, + []byte{0xae, 0x8e, 0x5c, 0xaa, 0x3c, 0xa0, 0x4e, 0x85}}, + { // 49 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80}, + nil, + []byte{0x9c, 0xc6, 0x2d, 0xf4, 0x3b, 0x6e, 0xed, 0x74}}, + { // 50 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40}, + nil, + []byte{0xd8, 0x63, 0xdb, 0xb5, 0xc5, 0x9a, 0x91, 0xa0}}, + { // 50 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20}, + nil, + []byte{0xa1, 0xab, 0x21, 0x90, 0x54, 0x5b, 0x91, 0xd7}}, + { // 52 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10}, + nil, + []byte{0x08, 0x75, 0x04, 0x1e, 0x64, 0xc5, 0x70, 0xf7}}, + { // 53 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08}, + nil, + []byte{0x5a, 0x59, 0x45, 0x28, 0xbe, 0xbe, 0xf1, 0xcc}}, + { // 54 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04}, + nil, + []byte{0xfc, 0xdb, 0x32, 0x91, 0xde, 0x21, 0xf0, 0xc0}}, + { // 55 + []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02}, + nil, + []byte{0x86, 0x9e, 0xfd, 0x7f, 0x9f, 0x26, 0x5a, 0x09}}, +} + +// Plaintext for use with Table A.3 tests +var tableA3Plaintext = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + +// Table A.3 Values To Be Used for the Permutation Operation Known Answer Test +var tableA3Tests = []CryptTest{ + { // 0 + []byte{ + 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31, + 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31, + 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31, + }, + nil, + []byte{0x88, 0xd5, 0x5e, 0x54, 0xf5, 0x4c, 0x97, 0xb4}}, + { // 1 + []byte{ + 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20, + 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20, + 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20, + }, + nil, + []byte{0x0c, 0x0c, 0xc0, 0x0c, 0x83, 0xea, 0x48, 0xfd}}, + { // 2 + []byte{ + 0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20, + 0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20, + 0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20, + }, + nil, + []byte{0x83, 0xbc, 0x8e, 0xf3, 0xa6, 0x57, 0x01, 0x83}}, + { // 3 + []byte{ + 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20, + 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20, + 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20, + }, + nil, + []byte{0xdf, 0x72, 0x5d, 0xca, 0xd9, 0x4e, 0xa2, 0xe9}}, + { // 4 + []byte{ + 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01, + 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01, + 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01, + }, + nil, + []byte{0xe6, 0x52, 0xb5, 0x3b, 0x55, 0x0b, 0xe8, 0xb0}}, + { // 5 + []byte{ + 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01, + 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01, + 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01, + }, + nil, + []byte{0xaf, 0x52, 0x71, 0x20, 0xc4, 0x85, 0xcb, 0xb0}}, + { // 6 + []byte{ + 0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01, + 0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01, + 0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01, + }, + nil, + []byte{0x0f, 0x04, 0xce, 0x39, 0x3d, 0xb9, 0x26, 0xd5}}, + { // 7 + []byte{ + 0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01, + 0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01, + 0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01, + }, + nil, + []byte{0xc9, 0xf0, 0x0f, 0xfc, 0x74, 0x07, 0x90, 0x67}}, + { // 8 + []byte{ + 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01, + 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01, + 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01, + }, + nil, + []byte{0x7c, 0xfd, 0x82, 0xa5, 0x93, 0x25, 0x2b, 0x4e}}, + { // 9 + []byte{ + 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01, + 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01, + 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01, + }, + nil, + []byte{0xcb, 0x49, 0xa2, 0xf9, 0xe9, 0x13, 0x63, 0xe3}}, + { // 10 + []byte{ + 0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40, + 0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40, + 0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40, + }, + nil, + []byte{0x00, 0xb5, 0x88, 0xbe, 0x70, 0xd2, 0x3f, 0x56}}, + { // 11 + []byte{ + 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40, + 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40, + 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40, + }, + nil, + []byte{0x40, 0x6a, 0x9a, 0x6a, 0xb4, 0x33, 0x99, 0xae}}, + { // 12 + []byte{ + 0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01, + 0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01, + 0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01, + }, + nil, + []byte{0x6c, 0xb7, 0x73, 0x61, 0x1d, 0xca, 0x9a, 0xda}}, + { // 13 + []byte{ + 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01, + 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01, + 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01, + }, + nil, + []byte{0x67, 0xfd, 0x21, 0xc1, 0x7d, 0xbb, 0x5d, 0x70}}, + { // 14 + []byte{ + 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01, + 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01, + 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01, + }, + nil, + []byte{0x95, 0x92, 0xcb, 0x41, 0x10, 0x43, 0x07, 0x87}}, + { // 15 + []byte{ + 0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20, + 0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20, + 0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20, + }, + nil, + []byte{0xa6, 0xb7, 0xff, 0x68, 0xa3, 0x18, 0xdd, 0xd3}}, + { // 16 + []byte{ + 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01, + 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01, + 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01, + }, + nil, + []byte{0x4d, 0x10, 0x21, 0x96, 0xc9, 0x14, 0xca, 0x16}}, + { // 17 + []byte{ + 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01, + 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01, + 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01, + }, + nil, + []byte{0x2d, 0xfa, 0x9f, 0x45, 0x73, 0x59, 0x49, 0x65}}, + { // 18 + []byte{ + 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01, + 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01, + 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01, + }, + nil, + []byte{0xb4, 0x66, 0x04, 0x81, 0x6c, 0x0e, 0x07, 0x74}}, + { // 19 + []byte{ + 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01, + 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01, + 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01, + }, + nil, + []byte{0x6e, 0x7e, 0x62, 0x21, 0xa4, 0xf3, 0x4e, 0x87}}, + { // 20 + []byte{ + 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01, + 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01, + 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01, + }, + nil, + []byte{0xaa, 0x85, 0xe7, 0x46, 0x43, 0x23, 0x31, 0x99}}, + { // 21 + []byte{ + 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01, + 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01, + 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01, + }, + nil, + []byte{0x2e, 0x5a, 0x19, 0xdb, 0x4d, 0x19, 0x62, 0xd6}}, + { // 22 + []byte{ + 0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01, + 0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01, + 0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01, + }, + nil, + []byte{0x23, 0xa8, 0x66, 0xa8, 0x09, 0xd3, 0x08, 0x94}}, + { // 23 + []byte{ + 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01, + 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01, + 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01, + }, + nil, + []byte{0xd8, 0x12, 0xd9, 0x61, 0xf0, 0x17, 0xd3, 0x20}}, + { // 24 + []byte{ + 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b, + 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b, + 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b, + }, + nil, + []byte{0x05, 0x56, 0x05, 0x81, 0x6e, 0x58, 0x60, 0x8f}}, + { // 25 + []byte{ + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01, + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01, + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01, + }, + nil, + []byte{0xab, 0xd8, 0x8e, 0x8b, 0x1b, 0x77, 0x16, 0xf1}}, + { // 26 + []byte{ + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02, + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02, + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02, + }, + nil, + []byte{0x53, 0x7a, 0xc9, 0x5b, 0xe6, 0x9d, 0xa1, 0xe1}}, + { // 27 + []byte{ + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08, + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08, + 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08, + }, + nil, + []byte{0xae, 0xd0, 0xf6, 0xae, 0x3c, 0x25, 0xcd, 0xd8}}, + { // 28 + []byte{ + 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04, + 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04, + 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04, + }, + nil, + []byte{0xb3, 0xe3, 0x5a, 0x5e, 0xe5, 0x3e, 0x7b, 0x8d}}, + { // 29 + []byte{ + 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04, + 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04, + 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04, + }, + nil, + []byte{0x61, 0xc7, 0x9c, 0x71, 0x92, 0x1a, 0x2e, 0xf8}}, + { // 30 + []byte{ + 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01, + 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01, + 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01, + }, + nil, + []byte{0xe2, 0xf5, 0x72, 0x8f, 0x09, 0x95, 0x01, 0x3c}}, + { // 31 + []byte{ + 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01, + 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01, + 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01, + }, + nil, + []byte{0x1a, 0xea, 0xc3, 0x9a, 0x61, 0xf0, 0xa4, 0x64}}, +} + +// Table A.4 Values To Be Used for the Substitution Table Known Answer Test +var tableA4Tests = []CryptTest{ + { // 0 + []byte{ + 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57, + 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57, + 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57}, + []byte{0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42}, + []byte{0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b}}, + { // 1 + []byte{ + 0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e, + 0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e, + 0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e}, + []byte{0x5c, 0xd5, 0x4c, 0xa8, 0x3d, 0xef, 0x57, 0xda}, + []byte{0x7a, 0x38, 0x9d, 0x10, 0x35, 0x4b, 0xd2, 0x71}}, + { // 2 + []byte{ + 0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86, + 0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86, + 0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86}, + []byte{0x02, 0x48, 0xd4, 0x38, 0x06, 0xf6, 0x71, 0x72}, + []byte{0x86, 0x8e, 0xbb, 0x51, 0xca, 0xb4, 0x59, 0x9a}}, + { // 3 + []byte{ + 0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e, + 0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e, + 0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e}, + []byte{0x51, 0x45, 0x4b, 0x58, 0x2d, 0xdf, 0x44, 0x0a}, + []byte{0x71, 0x78, 0x87, 0x6e, 0x01, 0xf1, 0x9b, 0x2a}}, + { // 4 + []byte{ + 0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6, + 0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6, + 0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6}, + []byte{0x42, 0xfd, 0x44, 0x30, 0x59, 0x57, 0x7f, 0xa2}, + []byte{0xaf, 0x37, 0xfb, 0x42, 0x1f, 0x8c, 0x40, 0x95}}, + { // 5 + []byte{ + 0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce, + 0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce, + 0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce}, + []byte{0x05, 0x9b, 0x5e, 0x08, 0x51, 0xcf, 0x14, 0x3a}, + []byte{0x86, 0xa5, 0x60, 0xf1, 0x0e, 0xc6, 0xd8, 0x5b}}, + { // 6 + []byte{ + 0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6, + 0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6, + 0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6}, + []byte{0x07, 0x56, 0xd8, 0xe0, 0x77, 0x47, 0x61, 0xd2}, + []byte{0x0c, 0xd3, 0xda, 0x02, 0x00, 0x21, 0xdc, 0x09}}, + { // 7 + []byte{ + 0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe, + 0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe, + 0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe}, + []byte{0x76, 0x25, 0x14, 0xb8, 0x29, 0xbf, 0x48, 0x6a}, + []byte{0xea, 0x67, 0x6b, 0x2c, 0xb7, 0xdb, 0x2b, 0x7a}}, + { // 8 + []byte{ + 0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16, + 0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16, + 0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16}, + []byte{0x3b, 0xdd, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02}, + []byte{0xdf, 0xd6, 0x4a, 0x81, 0x5c, 0xaf, 0x1a, 0x0f}}, + { // 9 + []byte{ + 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f, + 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f, + 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f}, + []byte{0x26, 0x95, 0x5f, 0x68, 0x35, 0xaf, 0x60, 0x9a}, + []byte{0x5c, 0x51, 0x3c, 0x9c, 0x48, 0x86, 0xc0, 0x88}}, + { // 10 + []byte{ + 0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46, + 0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46, + 0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46}, + []byte{0x16, 0x4d, 0x5e, 0x40, 0x4f, 0x27, 0x52, 0x32}, + []byte{0x0a, 0x2a, 0xee, 0xae, 0x3f, 0xf4, 0xab, 0x77}}, + { // 11 + []byte{ + 0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e, + 0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e, + 0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e}, + []byte{0x6b, 0x05, 0x6e, 0x18, 0x75, 0x9f, 0x5c, 0xca}, + []byte{0xef, 0x1b, 0xf0, 0x3e, 0x5d, 0xfa, 0x57, 0x5a}}, + { // 12 + []byte{ + 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76, + 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76, + 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76}, + []byte{0x00, 0x4b, 0xd6, 0xef, 0x09, 0x17, 0x60, 0x62}, + []byte{0x88, 0xbf, 0x0d, 0xb6, 0xd7, 0x0d, 0xee, 0x56}}, + { // 13 + []byte{ + 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07, + 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07, + 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07}, + []byte{0x48, 0x0d, 0x39, 0x00, 0x6e, 0xe7, 0x62, 0xf2}, + []byte{0xa1, 0xf9, 0x91, 0x55, 0x41, 0x02, 0x0b, 0x56}}, + { // 14 + []byte{ + 0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f, + 0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f, + 0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f}, + []byte{0x43, 0x75, 0x40, 0xc8, 0x69, 0x8f, 0x3c, 0xfa}, + []byte{0x6f, 0xbf, 0x1c, 0xaf, 0xcf, 0xfd, 0x05, 0x56}}, + { // 15 + []byte{ + 0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7, + 0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7, + 0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7}, + []byte{0x07, 0x2d, 0x43, 0xa0, 0x77, 0x07, 0x52, 0x92}, + []byte{0x2f, 0x22, 0xe4, 0x9b, 0xab, 0x7c, 0xa1, 0xac}}, + { // 16 + []byte{ + 0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf, + 0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf, + 0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf}, + []byte{0x02, 0xfe, 0x55, 0x77, 0x81, 0x17, 0xf1, 0x2a}, + []byte{0x5a, 0x6b, 0x61, 0x2c, 0xc2, 0x6c, 0xce, 0x4a}}, + { // 17 + []byte{ + 0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6, + 0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6, + 0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6}, + []byte{0x1d, 0x9d, 0x5c, 0x50, 0x18, 0xf7, 0x28, 0xc2}, + []byte{0x5f, 0x4c, 0x03, 0x8e, 0xd1, 0x2b, 0x2e, 0x41}}, + { // 18 + []byte{ + 0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef, + 0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef, + 0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef}, + []byte{0x30, 0x55, 0x32, 0x28, 0x6d, 0x6f, 0x29, 0x5a}, + []byte{0x63, 0xfa, 0xc0, 0xd0, 0x34, 0xd9, 0xf7, 0x93}}, +} + +func newCipher(key []byte) *desCipher { + c, err := NewCipher(key) + if err != nil { + panic("NewCipher failed: " + err.Error()) + } + return c.(*desCipher) +} + +// Use the known weak keys to test DES implementation +func TestWeakKeys(t *testing.T) { + for i, tt := range weakKeyTests { + var encrypt = func(in []byte) (out []byte) { + c := newCipher(tt.key) + out = make([]byte, len(in)) + encryptBlock(c.subkeys[:], out, in) + return + } + + // Encrypting twice with a DES weak + // key should reproduce the original input + result := encrypt(tt.in) + result = encrypt(result) + + if !bytes.Equal(result, tt.in) { + t.Errorf("#%d: result: %x want: %x", i, result, tt.in) + } + } +} + +// Use the known semi-weak key pairs to test DES implementation +func TestSemiWeakKeyPairs(t *testing.T) { + for i, tt := range semiWeakKeyTests { + var encrypt = func(key, in []byte) (out []byte) { + c := newCipher(key) + out = make([]byte, len(in)) + encryptBlock(c.subkeys[:], out, in) + return + } + + // Encrypting with one member of the semi-weak pair + // and then encrypting the result with the other member + // should reproduce the original input. + result := encrypt(tt.key, tt.in) + result = encrypt(tt.out, result) + + if !bytes.Equal(result, tt.in) { + t.Errorf("#%d: result: %x want: %x", i, result, tt.in) + } + } +} + +func TestDESEncryptBlock(t *testing.T) { + for i, tt := range encryptDESTests { + c := newCipher(tt.key) + out := make([]byte, len(tt.in)) + encryptBlock(c.subkeys[:], out, tt.in) + + if !bytes.Equal(out, tt.out) { + t.Errorf("#%d: result: %x want: %x", i, out, tt.out) + } + } +} + +func TestDESDecryptBlock(t *testing.T) { + for i, tt := range encryptDESTests { + c := newCipher(tt.key) + plain := make([]byte, len(tt.in)) + decryptBlock(c.subkeys[:], plain, tt.out) + + if !bytes.Equal(plain, tt.in) { + t.Errorf("#%d: result: %x want: %x", i, plain, tt.in) + } + } +} + +func TestEncryptTripleDES(t *testing.T) { + for i, tt := range encryptTripleDESTests { + c, _ := NewTripleDESCipher(tt.key) + out := make([]byte, len(tt.in)) + c.Encrypt(out, tt.in) + + if !bytes.Equal(out, tt.out) { + t.Errorf("#%d: result: %x want: %x", i, out, tt.out) + } + } +} + +func TestDecryptTripleDES(t *testing.T) { + for i, tt := range encryptTripleDESTests { + c, _ := NewTripleDESCipher(tt.key) + + plain := make([]byte, len(tt.in)) + c.Decrypt(plain, tt.out) + + if !bytes.Equal(plain, tt.in) { + t.Errorf("#%d: result: %x want: %x", i, plain, tt.in) + } + } +} + +// Defined in Pub 800-20 +func TestVariablePlaintextKnownAnswer(t *testing.T) { + for i, tt := range tableA1Tests { + c, _ := NewTripleDESCipher(tableA1Key) + + out := make([]byte, len(tt.in)) + c.Encrypt(out, tt.in) + + if !bytes.Equal(out, tt.out) { + t.Errorf("#%d: result: %x want: %x", i, out, tt.out) + } + } +} + +// Defined in Pub 800-20 +func TestVariableCiphertextKnownAnswer(t *testing.T) { + for i, tt := range tableA1Tests { + c, _ := NewTripleDESCipher(tableA1Key) + + plain := make([]byte, len(tt.out)) + c.Decrypt(plain, tt.out) + + if !bytes.Equal(plain, tt.in) { + t.Errorf("#%d: result: %x want: %x", i, plain, tt.in) + } + } +} + +// Defined in Pub 800-20 +// Encrypting the Table A.1 ciphertext with the +// 0x01... key produces the original plaintext +func TestInversePermutationKnownAnswer(t *testing.T) { + for i, tt := range tableA1Tests { + c, _ := NewTripleDESCipher(tableA1Key) + + plain := make([]byte, len(tt.in)) + c.Encrypt(plain, tt.out) + + if !bytes.Equal(plain, tt.in) { + t.Errorf("#%d: result: %x want: %x", i, plain, tt.in) + } + } +} + +// Defined in Pub 800-20 +// Decrypting the Table A.1 plaintext with the +// 0x01... key produces the corresponding ciphertext +func TestInitialPermutationKnownAnswer(t *testing.T) { + for i, tt := range tableA1Tests { + c, _ := NewTripleDESCipher(tableA1Key) + + out := make([]byte, len(tt.in)) + c.Decrypt(out, tt.in) + + if !bytes.Equal(out, tt.out) { + t.Errorf("#%d: result: %x want: %x", i, out, tt.out) + } + } +} + +// Defined in Pub 800-20 +func TestVariableKeyKnownAnswerEncrypt(t *testing.T) { + for i, tt := range tableA2Tests { + c, _ := NewTripleDESCipher(tt.key) + + out := make([]byte, len(tableA2Plaintext)) + c.Encrypt(out, tableA2Plaintext) + + if !bytes.Equal(out, tt.out) { + t.Errorf("#%d: result: %x want: %x", i, out, tt.out) + } + } +} + +// Defined in Pub 800-20 +func TestVariableKeyKnownAnswerDecrypt(t *testing.T) { + for i, tt := range tableA2Tests { + c, _ := NewTripleDESCipher(tt.key) + + out := make([]byte, len(tt.out)) + c.Decrypt(out, tt.out) + + if !bytes.Equal(out, tableA2Plaintext) { + t.Errorf("#%d: result: %x want: %x", i, out, tableA2Plaintext) + } + } +} + +// Defined in Pub 800-20 +func TestPermutationOperationKnownAnswerEncrypt(t *testing.T) { + for i, tt := range tableA3Tests { + c, _ := NewTripleDESCipher(tt.key) + + out := make([]byte, len(tableA3Plaintext)) + c.Encrypt(out, tableA3Plaintext) + + if !bytes.Equal(out, tt.out) { + t.Errorf("#%d: result: %x want: %x", i, out, tt.out) + } + } +} + +// Defined in Pub 800-20 +func TestPermutationOperationKnownAnswerDecrypt(t *testing.T) { + for i, tt := range tableA3Tests { + c, _ := NewTripleDESCipher(tt.key) + + out := make([]byte, len(tt.out)) + c.Decrypt(out, tt.out) + + if !bytes.Equal(out, tableA3Plaintext) { + t.Errorf("#%d: result: %x want: %x", i, out, tableA3Plaintext) + } + } +} + +// Defined in Pub 800-20 +func TestSubstitutionTableKnownAnswerEncrypt(t *testing.T) { + for i, tt := range tableA4Tests { + c, _ := NewTripleDESCipher(tt.key) + + out := make([]byte, len(tt.in)) + c.Encrypt(out, tt.in) + + if !bytes.Equal(out, tt.out) { + t.Errorf("#%d: result: %x want: %x", i, out, tt.out) + } + } +} + +// Defined in Pub 800-20 +func TestSubstitutionTableKnownAnswerDecrypt(t *testing.T) { + for i, tt := range tableA4Tests { + c, _ := NewTripleDESCipher(tt.key) + + out := make([]byte, len(tt.out)) + c.Decrypt(out, tt.out) + + if !bytes.Equal(out, tt.in) { + t.Errorf("#%d: result: %x want: %x", i, out, tt.in) + } + } +} + +func TestInitialPermute(t *testing.T) { + for i := uint(0); i < 64; i++ { + bit := uint64(1) << i + got := permuteInitialBlock(bit) + want := uint64(1) << finalPermutation[63-i] + if got != want { + t.Errorf("permute(%x) = %x, want %x", bit, got, want) + } + } +} + +func TestFinalPermute(t *testing.T) { + for i := uint(0); i < 64; i++ { + bit := uint64(1) << i + got := permuteFinalBlock(bit) + want := uint64(1) << initialPermutation[63-i] + if got != want { + t.Errorf("permute(%x) = %x, want %x", bit, got, want) + } + } +} + +func BenchmarkEncrypt(b *testing.B) { + tt := encryptDESTests[0] + c, err := NewCipher(tt.key) + if err != nil { + b.Fatal("NewCipher:", err) + } + out := make([]byte, len(tt.in)) + b.SetBytes(int64(len(out))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + c.Encrypt(out, tt.in) + } +} + +func BenchmarkDecrypt(b *testing.B) { + tt := encryptDESTests[0] + c, err := NewCipher(tt.key) + if err != nil { + b.Fatal("NewCipher:", err) + } + out := make([]byte, len(tt.out)) + b.SetBytes(int64(len(out))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + c.Decrypt(out, tt.out) + } +} + +func BenchmarkTDESEncrypt(b *testing.B) { + tt := encryptTripleDESTests[0] + c, err := NewTripleDESCipher(tt.key) + if err != nil { + b.Fatal("NewCipher:", err) + } + out := make([]byte, len(tt.in)) + b.SetBytes(int64(len(out))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + c.Encrypt(out, tt.in) + } +} + +func BenchmarkTDESDecrypt(b *testing.B) { + tt := encryptTripleDESTests[0] + c, err := NewTripleDESCipher(tt.key) + if err != nil { + b.Fatal("NewCipher:", err) + } + out := make([]byte, len(tt.out)) + b.SetBytes(int64(len(out))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + c.Decrypt(out, tt.out) + } +} diff --git a/src/crypto/des/example_test.go b/src/crypto/des/example_test.go new file mode 100644 index 0000000..336b593 --- /dev/null +++ b/src/crypto/des/example_test.go @@ -0,0 +1,25 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package des_test + +import "crypto/des" + +func ExampleNewTripleDESCipher() { + // NewTripleDESCipher can also be used when EDE2 is required by + // duplicating the first 8 bytes of the 16-byte key. + ede2Key := []byte("example key 1234") + + var tripleDESKey []byte + tripleDESKey = append(tripleDESKey, ede2Key[:16]...) + tripleDESKey = append(tripleDESKey, ede2Key[:8]...) + + _, err := des.NewTripleDESCipher(tripleDESKey) + if err != nil { + panic(err) + } + + // See crypto/cipher for how to use a cipher.Block for encryption and + // decryption. +} diff --git a/src/crypto/dsa/dsa.go b/src/crypto/dsa/dsa.go new file mode 100644 index 0000000..a833599 --- /dev/null +++ b/src/crypto/dsa/dsa.go @@ -0,0 +1,309 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3. +// +// The DSA operations in this package are not implemented using constant-time algorithms. +// +// Deprecated: DSA is a legacy algorithm, and modern alternatives such as +// Ed25519 (implemented by package crypto/ed25519) should be used instead. Keys +// with 1024-bit moduli (L1024N160 parameters) are cryptographically weak, while +// bigger keys are not widely supported. Note that FIPS 186-5 no longer approves +// DSA for signature generation. +package dsa + +import ( + "errors" + "io" + "math/big" + + "crypto/internal/randutil" +) + +// Parameters represents the domain parameters for a key. These parameters can +// be shared across many keys. The bit length of Q must be a multiple of 8. +type Parameters struct { + P, Q, G *big.Int +} + +// PublicKey represents a DSA public key. +type PublicKey struct { + Parameters + Y *big.Int +} + +// PrivateKey represents a DSA private key. +type PrivateKey struct { + PublicKey + X *big.Int +} + +// ErrInvalidPublicKey results when a public key is not usable by this code. +// FIPS is quite strict about the format of DSA keys, but other code may be +// less so. Thus, when using keys which may have been generated by other code, +// this error must be handled. +var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key") + +// ParameterSizes is an enumeration of the acceptable bit lengths of the primes +// in a set of DSA parameters. See FIPS 186-3, section 4.2. +type ParameterSizes int + +const ( + L1024N160 ParameterSizes = iota + L2048N224 + L2048N256 + L3072N256 +) + +// numMRTests is the number of Miller-Rabin primality tests that we perform. We +// pick the largest recommended number from table C.1 of FIPS 186-3. +const numMRTests = 64 + +// GenerateParameters puts a random, valid set of DSA parameters into params. +// This function can take many seconds, even on fast machines. +func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error { + // This function doesn't follow FIPS 186-3 exactly in that it doesn't + // use a verification seed to generate the primes. The verification + // seed doesn't appear to be exported or used by other code and + // omitting it makes the code cleaner. + + var L, N int + switch sizes { + case L1024N160: + L = 1024 + N = 160 + case L2048N224: + L = 2048 + N = 224 + case L2048N256: + L = 2048 + N = 256 + case L3072N256: + L = 3072 + N = 256 + default: + return errors.New("crypto/dsa: invalid ParameterSizes") + } + + qBytes := make([]byte, N/8) + pBytes := make([]byte, L/8) + + q := new(big.Int) + p := new(big.Int) + rem := new(big.Int) + one := new(big.Int) + one.SetInt64(1) + +GeneratePrimes: + for { + if _, err := io.ReadFull(rand, qBytes); err != nil { + return err + } + + qBytes[len(qBytes)-1] |= 1 + qBytes[0] |= 0x80 + q.SetBytes(qBytes) + + if !q.ProbablyPrime(numMRTests) { + continue + } + + for i := 0; i < 4*L; i++ { + if _, err := io.ReadFull(rand, pBytes); err != nil { + return err + } + + pBytes[len(pBytes)-1] |= 1 + pBytes[0] |= 0x80 + + p.SetBytes(pBytes) + rem.Mod(p, q) + rem.Sub(rem, one) + p.Sub(p, rem) + if p.BitLen() < L { + continue + } + + if !p.ProbablyPrime(numMRTests) { + continue + } + + params.P = p + params.Q = q + break GeneratePrimes + } + } + + h := new(big.Int) + h.SetInt64(2) + g := new(big.Int) + + pm1 := new(big.Int).Sub(p, one) + e := new(big.Int).Div(pm1, q) + + for { + g.Exp(h, e, p) + if g.Cmp(one) == 0 { + h.Add(h, one) + continue + } + + params.G = g + return nil + } +} + +// GenerateKey generates a public&private key pair. The Parameters of the +// PrivateKey must already be valid (see GenerateParameters). +func GenerateKey(priv *PrivateKey, rand io.Reader) error { + if priv.P == nil || priv.Q == nil || priv.G == nil { + return errors.New("crypto/dsa: parameters not set up before generating key") + } + + x := new(big.Int) + xBytes := make([]byte, priv.Q.BitLen()/8) + + for { + _, err := io.ReadFull(rand, xBytes) + if err != nil { + return err + } + x.SetBytes(xBytes) + if x.Sign() != 0 && x.Cmp(priv.Q) < 0 { + break + } + } + + priv.X = x + priv.Y = new(big.Int) + priv.Y.Exp(priv.G, x, priv.P) + return nil +} + +// fermatInverse calculates the inverse of k in GF(P) using Fermat's method. +// This has better constant-time properties than Euclid's method (implemented +// in math/big.Int.ModInverse) although math/big itself isn't strictly +// constant-time so it's not perfect. +func fermatInverse(k, P *big.Int) *big.Int { + two := big.NewInt(2) + pMinus2 := new(big.Int).Sub(P, two) + return new(big.Int).Exp(k, pMinus2, P) +} + +// Sign signs an arbitrary length hash (which should be the result of hashing a +// larger message) using the private key, priv. It returns the signature as a +// pair of integers. The security of the private key depends on the entropy of +// rand. +// +// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated +// to the byte-length of the subgroup. This function does not perform that +// truncation itself. +// +// Be aware that calling Sign with an attacker-controlled PrivateKey may +// require an arbitrary amount of CPU. +func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { + randutil.MaybeReadByte(rand) + + // FIPS 186-3, section 4.6 + + n := priv.Q.BitLen() + if priv.Q.Sign() <= 0 || priv.P.Sign() <= 0 || priv.G.Sign() <= 0 || priv.X.Sign() <= 0 || n%8 != 0 { + err = ErrInvalidPublicKey + return + } + n >>= 3 + + var attempts int + for attempts = 10; attempts > 0; attempts-- { + k := new(big.Int) + buf := make([]byte, n) + for { + _, err = io.ReadFull(rand, buf) + if err != nil { + return + } + k.SetBytes(buf) + // priv.Q must be >= 128 because the test above + // requires it to be > 0 and that + // ceil(log_2(Q)) mod 8 = 0 + // Thus this loop will quickly terminate. + if k.Sign() > 0 && k.Cmp(priv.Q) < 0 { + break + } + } + + kInv := fermatInverse(k, priv.Q) + + r = new(big.Int).Exp(priv.G, k, priv.P) + r.Mod(r, priv.Q) + + if r.Sign() == 0 { + continue + } + + z := k.SetBytes(hash) + + s = new(big.Int).Mul(priv.X, r) + s.Add(s, z) + s.Mod(s, priv.Q) + s.Mul(s, kInv) + s.Mod(s, priv.Q) + + if s.Sign() != 0 { + break + } + } + + // Only degenerate private keys will require more than a handful of + // attempts. + if attempts == 0 { + return nil, nil, ErrInvalidPublicKey + } + + return +} + +// Verify verifies the signature in r, s of hash using the public key, pub. It +// reports whether the signature is valid. +// +// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated +// to the byte-length of the subgroup. This function does not perform that +// truncation itself. +func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { + // FIPS 186-3, section 4.7 + + if pub.P.Sign() == 0 { + return false + } + + if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 { + return false + } + if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 { + return false + } + + w := new(big.Int).ModInverse(s, pub.Q) + if w == nil { + return false + } + + n := pub.Q.BitLen() + if n%8 != 0 { + return false + } + z := new(big.Int).SetBytes(hash) + + u1 := new(big.Int).Mul(z, w) + u1.Mod(u1, pub.Q) + u2 := w.Mul(r, w) + u2.Mod(u2, pub.Q) + v := u1.Exp(pub.G, u1, pub.P) + u2.Exp(pub.Y, u2, pub.P) + v.Mul(v, u2) + v.Mod(v, pub.P) + v.Mod(v, pub.Q) + + return v.Cmp(r) == 0 +} diff --git a/src/crypto/dsa/dsa_test.go b/src/crypto/dsa/dsa_test.go new file mode 100644 index 0000000..28ac00e --- /dev/null +++ b/src/crypto/dsa/dsa_test.go @@ -0,0 +1,143 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dsa + +import ( + "crypto/rand" + "math/big" + "testing" +) + +func testSignAndVerify(t *testing.T, i int, priv *PrivateKey) { + hashed := []byte("testing") + r, s, err := Sign(rand.Reader, priv, hashed) + if err != nil { + t.Errorf("%d: error signing: %s", i, err) + return + } + + if !Verify(&priv.PublicKey, hashed, r, s) { + t.Errorf("%d: Verify failed", i) + } +} + +func testParameterGeneration(t *testing.T, sizes ParameterSizes, L, N int) { + var priv PrivateKey + params := &priv.Parameters + + err := GenerateParameters(params, rand.Reader, sizes) + if err != nil { + t.Errorf("%d: %s", int(sizes), err) + return + } + + if params.P.BitLen() != L { + t.Errorf("%d: params.BitLen got:%d want:%d", int(sizes), params.P.BitLen(), L) + } + + if params.Q.BitLen() != N { + t.Errorf("%d: q.BitLen got:%d want:%d", int(sizes), params.Q.BitLen(), L) + } + + one := new(big.Int) + one.SetInt64(1) + pm1 := new(big.Int).Sub(params.P, one) + quo, rem := new(big.Int).DivMod(pm1, params.Q, new(big.Int)) + if rem.Sign() != 0 { + t.Errorf("%d: p-1 mod q != 0", int(sizes)) + } + x := new(big.Int).Exp(params.G, quo, params.P) + if x.Cmp(one) == 0 { + t.Errorf("%d: invalid generator", int(sizes)) + } + + err = GenerateKey(&priv, rand.Reader) + if err != nil { + t.Errorf("error generating key: %s", err) + return + } + + testSignAndVerify(t, int(sizes), &priv) +} + +func TestParameterGeneration(t *testing.T) { + if testing.Short() { + t.Skip("skipping parameter generation test in short mode") + } + + testParameterGeneration(t, L1024N160, 1024, 160) + testParameterGeneration(t, L2048N224, 2048, 224) + testParameterGeneration(t, L2048N256, 2048, 256) + testParameterGeneration(t, L3072N256, 3072, 256) +} + +func fromHex(s string) *big.Int { + result, ok := new(big.Int).SetString(s, 16) + if !ok { + panic(s) + } + return result +} + +func TestSignAndVerify(t *testing.T) { + priv := PrivateKey{ + PublicKey: PublicKey{ + Parameters: Parameters{ + P: fromHex("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF"), + Q: fromHex("E1D3391245933D68A0714ED34BBCB7A1F422B9C1"), + G: fromHex("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA"), + }, + Y: fromHex("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2"), + }, + X: fromHex("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A"), + } + + testSignAndVerify(t, 0, &priv) +} + +func TestSignAndVerifyWithBadPublicKey(t *testing.T) { + pub := PublicKey{ + Parameters: Parameters{ + P: fromHex("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF"), + Q: fromHex("FA"), + G: fromHex("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA"), + }, + Y: fromHex("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2"), + } + + if Verify(&pub, []byte("testing"), fromHex("2"), fromHex("4")) { + t.Errorf("Verify unexpected success with non-existent mod inverse of Q") + } +} + +func TestSigningWithDegenerateKeys(t *testing.T) { + // Signing with degenerate private keys should not cause an infinite + // loop. + badKeys := []struct { + p, q, g, y, x string + }{ + {"00", "01", "00", "00", "00"}, + {"01", "ff", "00", "00", "00"}, + } + + for i, test := range badKeys { + priv := PrivateKey{ + PublicKey: PublicKey{ + Parameters: Parameters{ + P: fromHex(test.p), + Q: fromHex(test.q), + G: fromHex(test.g), + }, + Y: fromHex(test.y), + }, + X: fromHex(test.x), + } + + hashed := []byte("testing") + if _, _, err := Sign(rand.Reader, &priv, hashed); err == nil { + t.Errorf("#%d: unexpected success", i) + } + } +} diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go new file mode 100644 index 0000000..2194369 --- /dev/null +++ b/src/crypto/ecdsa/ecdsa.go @@ -0,0 +1,367 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as +// defined in FIPS 186-3. +// +// This implementation derives the nonce from an AES-CTR CSPRNG keyed by: +// +// SHA2-512(priv.D || entropy || hash)[:32] +// +// The CSPRNG key is indifferentiable from a random oracle as shown in +// [Coron], the AES-CTR stream is indifferentiable from a random oracle +// under standard cryptographic assumptions (see [Larsson] for examples). +// +// References: +// [Coron] +// https://cs.nyu.edu/~dodis/ps/merkle.pdf +// [Larsson] +// https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf +package ecdsa + +// Further references: +// [NSA]: Suite B implementer's guide to FIPS 186-3 +// https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/suite-b-implementers-guide-to-fips-186-3-ecdsa.cfm +// [SECG]: SECG, SEC1 +// http://www.secg.org/sec1-v2.pdf + +import ( + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/elliptic" + "crypto/internal/randutil" + "crypto/sha512" + "errors" + "io" + "math/big" + + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" +) + +// A invertible implements fast inverse mod Curve.Params().N +type invertible interface { + // Inverse returns the inverse of k in GF(P) + Inverse(k *big.Int) *big.Int +} + +// combinedMult implements fast multiplication S1*g + S2*p (g - generator, p - arbitrary point) +type combinedMult interface { + CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) +} + +const ( + aesIV = "IV for ECDSA CTR" +) + +// PublicKey represents an ECDSA public key. +type PublicKey struct { + elliptic.Curve + X, Y *big.Int +} + +// Any methods implemented on PublicKey might need to also be implemented on +// PrivateKey, as the latter embeds the former and will expose its methods. + +// Equal reports whether pub and x have the same value. +// +// Two keys are only considered to have the same value if they have the same Curve value. +// Note that for example elliptic.P256() and elliptic.P256().Params() are different +// values, as the latter is a generic not constant time implementation. +func (pub *PublicKey) Equal(x crypto.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + return pub.X.Cmp(xx.X) == 0 && pub.Y.Cmp(xx.Y) == 0 && + // Standard library Curve implementations are singletons, so this check + // will work for those. Other Curves might be equivalent even if not + // singletons, but there is no definitive way to check for that, and + // better to err on the side of safety. + pub.Curve == xx.Curve +} + +// PrivateKey represents an ECDSA private key. +type PrivateKey struct { + PublicKey + D *big.Int +} + +// Public returns the public key corresponding to priv. +func (priv *PrivateKey) Public() crypto.PublicKey { + return &priv.PublicKey +} + +// Equal reports whether priv and x have the same value. +// +// See PublicKey.Equal for details on how Curve is compared. +func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool { + xx, ok := x.(*PrivateKey) + if !ok { + return false + } + return priv.PublicKey.Equal(&xx.PublicKey) && priv.D.Cmp(xx.D) == 0 +} + +// Sign signs digest with priv, reading randomness from rand. The opts argument +// is not currently used but, in keeping with the crypto.Signer interface, +// should be the hash function used to digest the message. +// +// This method implements crypto.Signer, which is an interface to support keys +// where the private part is kept in, for example, a hardware module. Common +// uses should use the Sign function in this package directly. +func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { + r, s, err := Sign(rand, priv, digest) + if err != nil { + return nil, err + } + + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1BigInt(r) + b.AddASN1BigInt(s) + }) + return b.Bytes() +} + +var one = new(big.Int).SetInt64(1) + +// randFieldElement returns a random element of the field underlying the given +// curve using the procedure given in [NSA] A.2.1. +func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) { + params := c.Params() + b := make([]byte, params.BitSize/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(params.N, one) + k.Mod(k, n) + k.Add(k, one) + return +} + +// GenerateKey generates a public and private key pair. +func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { + k, err := randFieldElement(c, rand) + if err != nil { + return nil, err + } + + priv := new(PrivateKey) + priv.PublicKey.Curve = c + priv.D = k + priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) + return priv, nil +} + +// hashToInt converts a hash value to an integer. There is some disagreement +// about how this is done. [NSA] suggests that this is done in the obvious +// manner, but [SECG] truncates the hash to the bit-length of the curve order +// first. We follow [SECG] because that's what OpenSSL does. Additionally, +// OpenSSL right shifts excess bits from the number if the hash is too large +// and we mirror that too. +func hashToInt(hash []byte, c elliptic.Curve) *big.Int { + orderBits := c.Params().N.BitLen() + orderBytes := (orderBits + 7) / 8 + if len(hash) > orderBytes { + hash = hash[:orderBytes] + } + + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - orderBits + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +// fermatInverse calculates the inverse of k in GF(P) using Fermat's method. +// This has better constant-time properties than Euclid's method (implemented +// in math/big.Int.ModInverse) although math/big itself isn't strictly +// constant-time so it's not perfect. +func fermatInverse(k, N *big.Int) *big.Int { + two := big.NewInt(2) + nMinus2 := new(big.Int).Sub(N, two) + return new(big.Int).Exp(k, nMinus2, N) +} + +var errZeroParam = errors.New("zero parameter") + +// Sign signs a hash (which should be the result of hashing a larger message) +// using the private key, priv. If the hash is longer than the bit-length of the +// private key's curve order, the hash will be truncated to that length. It +// returns the signature as a pair of integers. The security of the private key +// depends on the entropy of rand. +func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { + randutil.MaybeReadByte(rand) + + // Get min(log2(q) / 2, 256) bits of entropy from rand. + entropylen := (priv.Curve.Params().BitSize + 7) / 16 + if entropylen > 32 { + entropylen = 32 + } + entropy := make([]byte, entropylen) + _, err = io.ReadFull(rand, entropy) + if err != nil { + return + } + + // Initialize an SHA-512 hash context; digest ... + md := sha512.New() + md.Write(priv.D.Bytes()) // the private key, + md.Write(entropy) // the entropy, + md.Write(hash) // and the input hash; + key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), + // which is an indifferentiable MAC. + + // Create an AES-CTR instance to use as a CSPRNG. + block, err := aes.NewCipher(key) + if err != nil { + return nil, nil, err + } + + // Create a CSPRNG that xors a stream of zeros with + // the output of the AES-CTR instance. + csprng := cipher.StreamReader{ + R: zeroReader, + S: cipher.NewCTR(block, []byte(aesIV)), + } + + // See [NSA] 3.4.1 + c := priv.PublicKey.Curve + return sign(priv, &csprng, c, hash) +} + +func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) { + N := c.Params().N + if N.Sign() == 0 { + return nil, nil, errZeroParam + } + var k, kInv *big.Int + for { + for { + k, err = randFieldElement(c, *csprng) + if err != nil { + r = nil + return + } + + if in, ok := priv.Curve.(invertible); ok { + kInv = in.Inverse(k) + } else { + kInv = fermatInverse(k, N) // N != 0 + } + + r, _ = priv.Curve.ScalarBaseMult(k.Bytes()) + r.Mod(r, N) + if r.Sign() != 0 { + break + } + } + + e := hashToInt(hash, c) + s = new(big.Int).Mul(priv.D, r) + s.Add(s, e) + s.Mul(s, kInv) + s.Mod(s, N) // N != 0 + if s.Sign() != 0 { + break + } + } + + return +} + +// SignASN1 signs a hash (which should be the result of hashing a larger message) +// using the private key, priv. If the hash is longer than the bit-length of the +// private key's curve order, the hash will be truncated to that length. It +// returns the ASN.1 encoded signature. The security of the private key +// depends on the entropy of rand. +func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { + return priv.Sign(rand, hash, nil) +} + +// Verify verifies the signature in r, s of hash using the public key, pub. Its +// return value records whether the signature is valid. +func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { + // See [NSA] 3.4.2 + c := pub.Curve + N := c.Params().N + + if r.Sign() <= 0 || s.Sign() <= 0 { + return false + } + if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 { + return false + } + return verify(pub, c, hash, r, s) +} + +func verifyGeneric(pub *PublicKey, c elliptic.Curve, hash []byte, r, s *big.Int) bool { + e := hashToInt(hash, c) + var w *big.Int + N := c.Params().N + if in, ok := c.(invertible); ok { + w = in.Inverse(s) + } else { + w = new(big.Int).ModInverse(s, N) + } + + u1 := e.Mul(e, w) + u1.Mod(u1, N) + u2 := w.Mul(r, w) + u2.Mod(u2, N) + + // Check if implements S1*g + S2*p + var x, y *big.Int + if opt, ok := c.(combinedMult); ok { + x, y = opt.CombinedMult(pub.X, pub.Y, u1.Bytes(), u2.Bytes()) + } else { + x1, y1 := c.ScalarBaseMult(u1.Bytes()) + x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes()) + x, y = c.Add(x1, y1, x2, y2) + } + + if x.Sign() == 0 && y.Sign() == 0 { + return false + } + x.Mod(x, N) + return x.Cmp(r) == 0 +} + +// VerifyASN1 verifies the ASN.1 encoded signature, sig, of hash using the +// public key, pub. Its return value records whether the signature is valid. +func VerifyASN1(pub *PublicKey, hash, sig []byte) bool { + var ( + r, s = &big.Int{}, &big.Int{} + inner cryptobyte.String + ) + input := cryptobyte.String(sig) + if !input.ReadASN1(&inner, asn1.SEQUENCE) || + !input.Empty() || + !inner.ReadASN1Integer(r) || + !inner.ReadASN1Integer(s) || + !inner.Empty() { + return false + } + return Verify(pub, hash, r, s) +} + +type zr struct { + io.Reader +} + +// Read replaces the contents of dst with zeros. +func (z *zr) Read(dst []byte) (n int, err error) { + for i := range dst { + dst[i] = 0 + } + return len(dst), nil +} + +var zeroReader = &zr{} diff --git a/src/crypto/ecdsa/ecdsa_noasm.go b/src/crypto/ecdsa/ecdsa_noasm.go new file mode 100644 index 0000000..68670a4 --- /dev/null +++ b/src/crypto/ecdsa/ecdsa_noasm.go @@ -0,0 +1,22 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !s390x +// +build !s390x + +package ecdsa + +import ( + "crypto/cipher" + "crypto/elliptic" + "math/big" +) + +func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) { + return signGeneric(priv, csprng, c, hash) +} + +func verify(pub *PublicKey, c elliptic.Curve, hash []byte, r, s *big.Int) bool { + return verifyGeneric(pub, c, hash, r, s) +} diff --git a/src/crypto/ecdsa/ecdsa_s390x.go b/src/crypto/ecdsa/ecdsa_s390x.go new file mode 100644 index 0000000..1480d1b --- /dev/null +++ b/src/crypto/ecdsa/ecdsa_s390x.go @@ -0,0 +1,163 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdsa + +import ( + "crypto/cipher" + "crypto/elliptic" + "internal/cpu" + "math/big" +) + +// kdsa invokes the "compute digital signature authentication" +// instruction with the given function code and 4096 byte +// parameter block. +// +// The return value corresponds to the condition code set by the +// instruction. Interrupted invocations are handled by the +// function. +//go:noescape +func kdsa(fc uint64, params *[4096]byte) (errn uint64) + +// testingDisableKDSA forces the generic fallback path. It must only be set in tests. +var testingDisableKDSA bool + +// canUseKDSA checks if KDSA instruction is available, and if it is, it checks +// the name of the curve to see if it matches the curves supported(P-256, P-384, P-521). +// Then, based on the curve name, a function code and a block size will be assigned. +// If KDSA instruction is not available or if the curve is not supported, canUseKDSA +// will set ok to false. +func canUseKDSA(c elliptic.Curve) (functionCode uint64, blockSize int, ok bool) { + if testingDisableKDSA { + return 0, 0, false + } + if !cpu.S390X.HasECDSA { + return 0, 0, false + } + switch c.Params().Name { + case "P-256": + return 1, 32, true + case "P-384": + return 2, 48, true + case "P-521": + return 3, 80, true + } + return 0, 0, false // A mismatch +} + +func hashToBytes(dst, hash []byte, c elliptic.Curve) { + l := len(dst) + if n := c.Params().N.BitLen(); n == l*8 { + // allocation free path for curves with a length that is a whole number of bytes + if len(hash) >= l { + // truncate hash + copy(dst, hash[:l]) + return + } + // pad hash with leading zeros + p := l - len(hash) + for i := 0; i < p; i++ { + dst[i] = 0 + } + copy(dst[p:], hash) + return + } + // TODO(mundaym): avoid hashToInt call here + hashToInt(hash, c).FillBytes(dst) +} + +func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) { + if functionCode, blockSize, ok := canUseKDSA(c); ok { + for { + var k *big.Int + k, err = randFieldElement(c, *csprng) + if err != nil { + return nil, nil, err + } + + // The parameter block looks like the following for sign. + // +---------------------+ + // | Signature(R) | + // +---------------------+ + // | Signature(S) | + // +---------------------+ + // | Hashed Message | + // +---------------------+ + // | Private Key | + // +---------------------+ + // | Random Number | + // +---------------------+ + // | | + // | ... | + // | | + // +---------------------+ + // The common components(signatureR, signatureS, hashedMessage, privateKey and + // random number) each takes block size of bytes. The block size is different for + // different curves and is set by canUseKDSA function. + var params [4096]byte + + // Copy content into the parameter block. In the sign case, + // we copy hashed message, private key and random number into + // the parameter block. + hashToBytes(params[2*blockSize:3*blockSize], hash, c) + priv.D.FillBytes(params[3*blockSize : 4*blockSize]) + k.FillBytes(params[4*blockSize : 5*blockSize]) + // Convert verify function code into a sign function code by adding 8. + // We also need to set the 'deterministic' bit in the function code, by + // adding 128, in order to stop the instruction using its own random number + // generator in addition to the random number we supply. + switch kdsa(functionCode+136, ¶ms) { + case 0: // success + r = new(big.Int) + r.SetBytes(params[:blockSize]) + s = new(big.Int) + s.SetBytes(params[blockSize : 2*blockSize]) + return + case 1: // error + return nil, nil, errZeroParam + case 2: // retry + continue + } + panic("unreachable") + } + } + return signGeneric(priv, csprng, c, hash) +} + +func verify(pub *PublicKey, c elliptic.Curve, hash []byte, r, s *big.Int) bool { + if functionCode, blockSize, ok := canUseKDSA(c); ok { + // The parameter block looks like the following for verify: + // +---------------------+ + // | Signature(R) | + // +---------------------+ + // | Signature(S) | + // +---------------------+ + // | Hashed Message | + // +---------------------+ + // | Public Key X | + // +---------------------+ + // | Public Key Y | + // +---------------------+ + // | | + // | ... | + // | | + // +---------------------+ + // The common components(signatureR, signatureS, hashed message, public key X, + // and public key Y) each takes block size of bytes. The block size is different for + // different curves and is set by canUseKDSA function. + var params [4096]byte + + // Copy content into the parameter block. In the verify case, + // we copy signature (r), signature(s), hashed message, public key x component, + // and public key y component into the parameter block. + r.FillBytes(params[0*blockSize : 1*blockSize]) + s.FillBytes(params[1*blockSize : 2*blockSize]) + hashToBytes(params[2*blockSize:3*blockSize], hash, c) + pub.X.FillBytes(params[3*blockSize : 4*blockSize]) + pub.Y.FillBytes(params[4*blockSize : 5*blockSize]) + return kdsa(functionCode, ¶ms) == 0 + } + return verifyGeneric(pub, c, hash, r, s) +} diff --git a/src/crypto/ecdsa/ecdsa_s390x.s b/src/crypto/ecdsa/ecdsa_s390x.s new file mode 100644 index 0000000..ba5b3bf --- /dev/null +++ b/src/crypto/ecdsa/ecdsa_s390x.s @@ -0,0 +1,28 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func kdsa(fc uint64, params *[4096]byte) (errn uint64) +TEXT ·kdsa(SB), NOSPLIT|NOFRAME, $0-24 + MOVD fc+0(FP), R0 // function code + MOVD params+8(FP), R1 // address parameter block + +loop: + WORD $0xB93A0008 // compute digital signature authentication + BVS loop // branch back if interrupted + BGT retry // signing unsuccessful, but retry with new CSPRN + BLT error // condition code of 1 indicates a failure + +success: + MOVD $0, errn+16(FP) // return 0 - sign/verify was successful + RET + +error: + MOVD $1, errn+16(FP) // return 1 - sign/verify failed + RET + +retry: + MOVD $2, errn+16(FP) // return 2 - sign/verify was unsuccessful -- if sign, retry with new RN + RET diff --git a/src/crypto/ecdsa/ecdsa_s390x_test.go b/src/crypto/ecdsa/ecdsa_s390x_test.go new file mode 100644 index 0000000..f5633fb --- /dev/null +++ b/src/crypto/ecdsa/ecdsa_s390x_test.go @@ -0,0 +1,33 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build s390x +// +build s390x + +package ecdsa + +import ( + "crypto/elliptic" + "testing" +) + +func TestNoAsm(t *testing.T) { + testingDisableKDSA = true + defer func() { testingDisableKDSA = false }() + + curves := [...]elliptic.Curve{ + elliptic.P256(), + elliptic.P384(), + elliptic.P521(), + } + + for _, curve := range curves { + name := curve.Params().Name + t.Run(name, func(t *testing.T) { testKeyGeneration(t, curve) }) + t.Run(name, func(t *testing.T) { testSignAndVerify(t, curve) }) + t.Run(name, func(t *testing.T) { testNonceSafety(t, curve) }) + t.Run(name, func(t *testing.T) { testINDCCA(t, curve) }) + t.Run(name, func(t *testing.T) { testNegativeInputs(t, curve) }) + } +} diff --git a/src/crypto/ecdsa/ecdsa_test.go b/src/crypto/ecdsa/ecdsa_test.go new file mode 100644 index 0000000..556818a --- /dev/null +++ b/src/crypto/ecdsa/ecdsa_test.go @@ -0,0 +1,401 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdsa + +import ( + "bufio" + "compress/bzip2" + "crypto/elliptic" + "crypto/rand" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "hash" + "io" + "math/big" + "os" + "strings" + "testing" +) + +func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) { + tests := []struct { + name string + curve elliptic.Curve + }{ + {"P256", elliptic.P256()}, + {"P224", elliptic.P224()}, + {"P384", elliptic.P384()}, + {"P521", elliptic.P521()}, + } + if testing.Short() { + tests = tests[:1] + } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.T) { + t.Parallel() + f(t, curve) + }) + } +} + +func TestKeyGeneration(t *testing.T) { + testAllCurves(t, testKeyGeneration) +} + +func testKeyGeneration(t *testing.T, c elliptic.Curve) { + priv, err := GenerateKey(c, rand.Reader) + if err != nil { + t.Fatal(err) + } + if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) { + t.Errorf("public key invalid: %s", err) + } +} + +func TestSignAndVerify(t *testing.T) { + testAllCurves(t, testSignAndVerify) +} + +func testSignAndVerify(t *testing.T, c elliptic.Curve) { + priv, _ := GenerateKey(c, rand.Reader) + + hashed := []byte("testing") + r, s, err := Sign(rand.Reader, priv, hashed) + if err != nil { + t.Errorf("error signing: %s", err) + return + } + + if !Verify(&priv.PublicKey, hashed, r, s) { + t.Errorf("Verify failed") + } + + hashed[0] ^= 0xff + if Verify(&priv.PublicKey, hashed, r, s) { + t.Errorf("Verify always works!") + } +} + +func TestSignAndVerifyASN1(t *testing.T) { + testAllCurves(t, testSignAndVerifyASN1) +} + +func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) { + priv, _ := GenerateKey(c, rand.Reader) + + hashed := []byte("testing") + sig, err := SignASN1(rand.Reader, priv, hashed) + if err != nil { + t.Errorf("error signing: %s", err) + return + } + + if !VerifyASN1(&priv.PublicKey, hashed, sig) { + t.Errorf("VerifyASN1 failed") + } + + hashed[0] ^= 0xff + if VerifyASN1(&priv.PublicKey, hashed, sig) { + t.Errorf("VerifyASN1 always works!") + } +} + +func TestNonceSafety(t *testing.T) { + testAllCurves(t, testNonceSafety) +} + +func testNonceSafety(t *testing.T, c elliptic.Curve) { + priv, _ := GenerateKey(c, rand.Reader) + + hashed := []byte("testing") + r0, s0, err := Sign(zeroReader, priv, hashed) + if err != nil { + t.Errorf("error signing: %s", err) + return + } + + hashed = []byte("testing...") + r1, s1, err := Sign(zeroReader, priv, hashed) + if err != nil { + t.Errorf("error signing: %s", err) + return + } + + if s0.Cmp(s1) == 0 { + // This should never happen. + t.Errorf("the signatures on two different messages were the same") + } + + if r0.Cmp(r1) == 0 { + t.Errorf("the nonce used for two different messages was the same") + } +} + +func TestINDCCA(t *testing.T) { + testAllCurves(t, testINDCCA) +} + +func testINDCCA(t *testing.T, c elliptic.Curve) { + priv, _ := GenerateKey(c, rand.Reader) + + hashed := []byte("testing") + r0, s0, err := Sign(rand.Reader, priv, hashed) + if err != nil { + t.Errorf("error signing: %s", err) + return + } + + r1, s1, err := Sign(rand.Reader, priv, hashed) + if err != nil { + t.Errorf("error signing: %s", err) + return + } + + if s0.Cmp(s1) == 0 { + t.Errorf("two signatures of the same message produced the same result") + } + + if r0.Cmp(r1) == 0 { + t.Errorf("two signatures of the same message produced the same nonce") + } +} + +func fromHex(s string) *big.Int { + r, ok := new(big.Int).SetString(s, 16) + if !ok { + panic("bad hex") + } + return r +} + +func TestVectors(t *testing.T) { + // This test runs the full set of NIST test vectors from + // https://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip + // + // The SigVer.rsp file has been edited to remove test vectors for + // unsupported algorithms and has been compressed. + + if testing.Short() { + return + } + + f, err := os.Open("testdata/SigVer.rsp.bz2") + if err != nil { + t.Fatal(err) + } + + buf := bufio.NewReader(bzip2.NewReader(f)) + + lineNo := 1 + var h hash.Hash + var msg []byte + var hashed []byte + var r, s *big.Int + pub := new(PublicKey) + + for { + line, err := buf.ReadString('\n') + if len(line) == 0 { + if err == io.EOF { + break + } + t.Fatalf("error reading from input: %s", err) + } + lineNo++ + // Need to remove \r\n from the end of the line. + if !strings.HasSuffix(line, "\r\n") { + t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo) + } + line = line[:len(line)-2] + + if len(line) == 0 || line[0] == '#' { + continue + } + + if line[0] == '[' { + line = line[1 : len(line)-1] + parts := strings.SplitN(line, ",", 2) + + switch parts[0] { + case "P-224": + pub.Curve = elliptic.P224() + case "P-256": + pub.Curve = elliptic.P256() + case "P-384": + pub.Curve = elliptic.P384() + case "P-521": + pub.Curve = elliptic.P521() + default: + pub.Curve = nil + } + + switch parts[1] { + case "SHA-1": + h = sha1.New() + case "SHA-224": + h = sha256.New224() + case "SHA-256": + h = sha256.New() + case "SHA-384": + h = sha512.New384() + case "SHA-512": + h = sha512.New() + default: + h = nil + } + + continue + } + + if h == nil || pub.Curve == nil { + continue + } + + switch { + case strings.HasPrefix(line, "Msg = "): + if msg, err = hex.DecodeString(line[6:]); err != nil { + t.Fatalf("failed to decode message on line %d: %s", lineNo, err) + } + case strings.HasPrefix(line, "Qx = "): + pub.X = fromHex(line[5:]) + case strings.HasPrefix(line, "Qy = "): + pub.Y = fromHex(line[5:]) + case strings.HasPrefix(line, "R = "): + r = fromHex(line[4:]) + case strings.HasPrefix(line, "S = "): + s = fromHex(line[4:]) + case strings.HasPrefix(line, "Result = "): + expected := line[9] == 'P' + h.Reset() + h.Write(msg) + hashed := h.Sum(hashed[:0]) + if Verify(pub, hashed, r, s) != expected { + t.Fatalf("incorrect result on line %d", lineNo) + } + default: + t.Fatalf("unknown variable on line %d: %s", lineNo, line) + } + } +} + +func TestNegativeInputs(t *testing.T) { + testAllCurves(t, testNegativeInputs) +} + +func testNegativeInputs(t *testing.T, curve elliptic.Curve) { + key, err := GenerateKey(curve, rand.Reader) + if err != nil { + t.Errorf("failed to generate key") + } + + var hash [32]byte + r := new(big.Int).SetInt64(1) + r.Lsh(r, 550 /* larger than any supported curve */) + r.Neg(r) + + if Verify(&key.PublicKey, hash[:], r, r) { + t.Errorf("bogus signature accepted") + } +} + +func TestZeroHashSignature(t *testing.T) { + testAllCurves(t, testZeroHashSignature) +} + +func testZeroHashSignature(t *testing.T, curve elliptic.Curve) { + zeroHash := make([]byte, 64) + + privKey, err := GenerateKey(curve, rand.Reader) + if err != nil { + panic(err) + } + + // Sign a hash consisting of all zeros. + r, s, err := Sign(rand.Reader, privKey, zeroHash) + if err != nil { + panic(err) + } + + // Confirm that it can be verified. + if !Verify(&privKey.PublicKey, zeroHash, r, s) { + t.Errorf("zero hash signature verify failed for %T", curve) + } +} + +func benchmarkAllCurves(t *testing.B, f func(*testing.B, elliptic.Curve)) { + tests := []struct { + name string + curve elliptic.Curve + }{ + {"P256", elliptic.P256()}, + {"P224", elliptic.P224()}, + {"P384", elliptic.P384()}, + {"P521", elliptic.P521()}, + } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.B) { + f(t, curve) + }) + } +} + +func BenchmarkSign(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { + priv, err := GenerateKey(curve, rand.Reader) + if err != nil { + b.Fatal(err) + } + hashed := []byte("testing") + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + sig, err := SignASN1(rand.Reader, priv, hashed) + if err != nil { + b.Fatal(err) + } + // Prevent the compiler from optimizing out the operation. + hashed[0] = sig[0] + } + }) +} + +func BenchmarkVerify(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { + priv, err := GenerateKey(curve, rand.Reader) + if err != nil { + b.Fatal(err) + } + hashed := []byte("testing") + r, s, err := Sign(rand.Reader, priv, hashed) + if err != nil { + b.Fatal(err) + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if !Verify(&priv.PublicKey, hashed, r, s) { + b.Fatal("verify failed") + } + } + }) +} + +func BenchmarkGenerateKey(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := GenerateKey(curve, rand.Reader); err != nil { + b.Fatal(err) + } + } + }) +} diff --git a/src/crypto/ecdsa/equal_test.go b/src/crypto/ecdsa/equal_test.go new file mode 100644 index 0000000..53ac850 --- /dev/null +++ b/src/crypto/ecdsa/equal_test.go @@ -0,0 +1,75 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdsa_test + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "testing" +) + +func testEqual(t *testing.T, c elliptic.Curve) { + private, _ := ecdsa.GenerateKey(c, rand.Reader) + public := &private.PublicKey + + if !public.Equal(public) { + t.Errorf("public key is not equal to itself: %v", public) + } + if !public.Equal(crypto.Signer(private).Public().(*ecdsa.PublicKey)) { + t.Errorf("private.Public() is not Equal to public: %q", public) + } + if !private.Equal(private) { + t.Errorf("private key is not equal to itself: %v", private) + } + + enc, err := x509.MarshalPKCS8PrivateKey(private) + if err != nil { + t.Fatal(err) + } + decoded, err := x509.ParsePKCS8PrivateKey(enc) + if err != nil { + t.Fatal(err) + } + if !public.Equal(decoded.(crypto.Signer).Public()) { + t.Errorf("public key is not equal to itself after decoding: %v", public) + } + if !private.Equal(decoded) { + t.Errorf("private key is not equal to itself after decoding: %v", private) + } + + other, _ := ecdsa.GenerateKey(c, rand.Reader) + if public.Equal(other.Public()) { + t.Errorf("different public keys are Equal") + } + if private.Equal(other) { + t.Errorf("different private keys are Equal") + } + + // Ensure that keys with the same coordinates but on different curves + // aren't considered Equal. + differentCurve := &ecdsa.PublicKey{} + *differentCurve = *public // make a copy of the public key + if differentCurve.Curve == elliptic.P256() { + differentCurve.Curve = elliptic.P224() + } else { + differentCurve.Curve = elliptic.P256() + } + if public.Equal(differentCurve) { + t.Errorf("public keys with different curves are Equal") + } +} + +func TestEqual(t *testing.T) { + t.Run("P224", func(t *testing.T) { testEqual(t, elliptic.P224()) }) + if testing.Short() { + return + } + t.Run("P256", func(t *testing.T) { testEqual(t, elliptic.P256()) }) + t.Run("P384", func(t *testing.T) { testEqual(t, elliptic.P384()) }) + t.Run("P521", func(t *testing.T) { testEqual(t, elliptic.P521()) }) +} diff --git a/src/crypto/ecdsa/example_test.go b/src/crypto/ecdsa/example_test.go new file mode 100644 index 0000000..652c165 --- /dev/null +++ b/src/crypto/ecdsa/example_test.go @@ -0,0 +1,32 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ecdsa_test + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "fmt" +) + +func Example() { + privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(err) + } + + msg := "hello, world" + hash := sha256.Sum256([]byte(msg)) + + sig, err := ecdsa.SignASN1(rand.Reader, privateKey, hash[:]) + if err != nil { + panic(err) + } + fmt.Printf("signature: %x\n", sig) + + valid := ecdsa.VerifyASN1(&privateKey.PublicKey, hash[:], sig) + fmt.Println("signature verified:", valid) +} diff --git a/src/crypto/ecdsa/testdata/SigVer.rsp.bz2 b/src/crypto/ecdsa/testdata/SigVer.rsp.bz2 new file mode 100644 index 0000000..09fe2b4 Binary files /dev/null and b/src/crypto/ecdsa/testdata/SigVer.rsp.bz2 differ diff --git a/src/crypto/ed25519/ed25519.go b/src/crypto/ed25519/ed25519.go new file mode 100644 index 0000000..09c5269 --- /dev/null +++ b/src/crypto/ed25519/ed25519.go @@ -0,0 +1,215 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ed25519 implements the Ed25519 signature algorithm. See +// https://ed25519.cr.yp.to/. +// +// These functions are also compatible with the “Ed25519” function defined in +// RFC 8032. However, unlike RFC 8032's formulation, this package's private key +// representation includes a public key suffix to make multiple signing +// operations with the same key more efficient. This package refers to the RFC +// 8032 private key as the “seed”. +package ed25519 + +import ( + "bytes" + "crypto" + "crypto/ed25519/internal/edwards25519" + cryptorand "crypto/rand" + "crypto/sha512" + "errors" + "io" + "strconv" +) + +const ( + // PublicKeySize is the size, in bytes, of public keys as used in this package. + PublicKeySize = 32 + // PrivateKeySize is the size, in bytes, of private keys as used in this package. + PrivateKeySize = 64 + // SignatureSize is the size, in bytes, of signatures generated and verified by this package. + SignatureSize = 64 + // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. + SeedSize = 32 +) + +// PublicKey is the type of Ed25519 public keys. +type PublicKey []byte + +// Any methods implemented on PublicKey might need to also be implemented on +// PrivateKey, as the latter embeds the former and will expose its methods. + +// Equal reports whether pub and x have the same value. +func (pub PublicKey) Equal(x crypto.PublicKey) bool { + xx, ok := x.(PublicKey) + if !ok { + return false + } + return bytes.Equal(pub, xx) +} + +// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. +type PrivateKey []byte + +// Public returns the PublicKey corresponding to priv. +func (priv PrivateKey) Public() crypto.PublicKey { + publicKey := make([]byte, PublicKeySize) + copy(publicKey, priv[32:]) + return PublicKey(publicKey) +} + +// Equal reports whether priv and x have the same value. +func (priv PrivateKey) Equal(x crypto.PrivateKey) bool { + xx, ok := x.(PrivateKey) + if !ok { + return false + } + return bytes.Equal(priv, xx) +} + +// Seed returns the private key seed corresponding to priv. It is provided for +// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds +// in this package. +func (priv PrivateKey) Seed() []byte { + seed := make([]byte, SeedSize) + copy(seed, priv[:32]) + return seed +} + +// Sign signs the given message with priv. +// Ed25519 performs two passes over messages to be signed and therefore cannot +// handle pre-hashed messages. Thus opts.HashFunc() must return zero to +// indicate the message hasn't been hashed. This can be achieved by passing +// crypto.Hash(0) as the value for opts. +func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { + if opts.HashFunc() != crypto.Hash(0) { + return nil, errors.New("ed25519: cannot sign hashed message") + } + + return Sign(priv, message), nil +} + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { + if rand == nil { + rand = cryptorand.Reader + } + + seed := make([]byte, SeedSize) + if _, err := io.ReadFull(rand, seed); err != nil { + return nil, nil, err + } + + privateKey := NewKeyFromSeed(seed) + publicKey := make([]byte, PublicKeySize) + copy(publicKey, privateKey[32:]) + + return publicKey, privateKey, nil +} + +// NewKeyFromSeed calculates a private key from a seed. It will panic if +// len(seed) is not SeedSize. This function is provided for interoperability +// with RFC 8032. RFC 8032's private keys correspond to seeds in this +// package. +func NewKeyFromSeed(seed []byte) PrivateKey { + // Outline the function body so that the returned key can be stack-allocated. + privateKey := make([]byte, PrivateKeySize) + newKeyFromSeed(privateKey, seed) + return privateKey +} + +func newKeyFromSeed(privateKey, seed []byte) { + if l := len(seed); l != SeedSize { + panic("ed25519: bad seed length: " + strconv.Itoa(l)) + } + + h := sha512.Sum512(seed) + s := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) + A := (&edwards25519.Point{}).ScalarBaseMult(s) + + publicKey := A.Bytes() + + copy(privateKey, seed) + copy(privateKey[32:], publicKey) +} + +// Sign signs the message with privateKey and returns a signature. It will +// panic if len(privateKey) is not PrivateKeySize. +func Sign(privateKey PrivateKey, message []byte) []byte { + // Outline the function body so that the returned signature can be + // stack-allocated. + signature := make([]byte, SignatureSize) + sign(signature, privateKey, message) + return signature +} + +func sign(signature, privateKey, message []byte) { + if l := len(privateKey); l != PrivateKeySize { + panic("ed25519: bad private key length: " + strconv.Itoa(l)) + } + seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:] + + h := sha512.Sum512(seed) + s := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) + prefix := h[32:] + + mh := sha512.New() + mh.Write(prefix) + mh.Write(message) + messageDigest := make([]byte, 0, sha512.Size) + messageDigest = mh.Sum(messageDigest) + r := edwards25519.NewScalar().SetUniformBytes(messageDigest) + + R := (&edwards25519.Point{}).ScalarBaseMult(r) + + kh := sha512.New() + kh.Write(R.Bytes()) + kh.Write(publicKey) + kh.Write(message) + hramDigest := make([]byte, 0, sha512.Size) + hramDigest = kh.Sum(hramDigest) + k := edwards25519.NewScalar().SetUniformBytes(hramDigest) + + S := edwards25519.NewScalar().MultiplyAdd(k, s, r) + + copy(signature[:32], R.Bytes()) + copy(signature[32:], S.Bytes()) +} + +// Verify reports whether sig is a valid signature of message by publicKey. It +// will panic if len(publicKey) is not PublicKeySize. +func Verify(publicKey PublicKey, message, sig []byte) bool { + if l := len(publicKey); l != PublicKeySize { + panic("ed25519: bad public key length: " + strconv.Itoa(l)) + } + + if len(sig) != SignatureSize || sig[63]&224 != 0 { + return false + } + + A, err := (&edwards25519.Point{}).SetBytes(publicKey) + if err != nil { + return false + } + + kh := sha512.New() + kh.Write(sig[:32]) + kh.Write(publicKey) + kh.Write(message) + hramDigest := make([]byte, 0, sha512.Size) + hramDigest = kh.Sum(hramDigest) + k := edwards25519.NewScalar().SetUniformBytes(hramDigest) + + S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:]) + if err != nil { + return false + } + + // [S]B = R + [k]A --> [k](-A) + [S]B = R + minusA := (&edwards25519.Point{}).Negate(A) + R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S) + + return bytes.Equal(sig[:32], R.Bytes()) +} diff --git a/src/crypto/ed25519/ed25519_test.go b/src/crypto/ed25519/ed25519_test.go new file mode 100644 index 0000000..8a973b3 --- /dev/null +++ b/src/crypto/ed25519/ed25519_test.go @@ -0,0 +1,247 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ed25519 + +import ( + "bufio" + "bytes" + "compress/gzip" + "crypto" + "crypto/rand" + "encoding/hex" + "os" + "strings" + "testing" +) + +type zeroReader struct{} + +func (zeroReader) Read(buf []byte) (int, error) { + for i := range buf { + buf[i] = 0 + } + return len(buf), nil +} + +func TestSignVerify(t *testing.T) { + var zero zeroReader + public, private, _ := GenerateKey(zero) + + message := []byte("test message") + sig := Sign(private, message) + if !Verify(public, message, sig) { + t.Errorf("valid signature rejected") + } + + wrongMessage := []byte("wrong message") + if Verify(public, wrongMessage, sig) { + t.Errorf("signature of different message accepted") + } +} + +func TestCryptoSigner(t *testing.T) { + var zero zeroReader + public, private, _ := GenerateKey(zero) + + signer := crypto.Signer(private) + + publicInterface := signer.Public() + public2, ok := publicInterface.(PublicKey) + if !ok { + t.Fatalf("expected PublicKey from Public() but got %T", publicInterface) + } + + if !bytes.Equal(public, public2) { + t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2) + } + + message := []byte("message") + var noHash crypto.Hash + signature, err := signer.Sign(zero, message, noHash) + if err != nil { + t.Fatalf("error from Sign(): %s", err) + } + + if !Verify(public, message, signature) { + t.Errorf("Verify failed on signature from Sign()") + } +} + +func TestEqual(t *testing.T) { + public, private, _ := GenerateKey(rand.Reader) + + if !public.Equal(public) { + t.Errorf("public key is not equal to itself: %q", public) + } + if !public.Equal(crypto.Signer(private).Public()) { + t.Errorf("private.Public() is not Equal to public: %q", public) + } + if !private.Equal(private) { + t.Errorf("private key is not equal to itself: %q", private) + } + + otherPub, otherPriv, _ := GenerateKey(rand.Reader) + if public.Equal(otherPub) { + t.Errorf("different public keys are Equal") + } + if private.Equal(otherPriv) { + t.Errorf("different private keys are Equal") + } +} + +func TestGolden(t *testing.T) { + // sign.input.gz is a selection of test cases from + // https://ed25519.cr.yp.to/python/sign.input + testDataZ, err := os.Open("testdata/sign.input.gz") + if err != nil { + t.Fatal(err) + } + defer testDataZ.Close() + testData, err := gzip.NewReader(testDataZ) + if err != nil { + t.Fatal(err) + } + defer testData.Close() + + scanner := bufio.NewScanner(testData) + lineNo := 0 + + for scanner.Scan() { + lineNo++ + + line := scanner.Text() + parts := strings.Split(line, ":") + if len(parts) != 5 { + t.Fatalf("bad number of parts on line %d", lineNo) + } + + privBytes, _ := hex.DecodeString(parts[0]) + pubKey, _ := hex.DecodeString(parts[1]) + msg, _ := hex.DecodeString(parts[2]) + sig, _ := hex.DecodeString(parts[3]) + // The signatures in the test vectors also include the message + // at the end, but we just want R and S. + sig = sig[:SignatureSize] + + if l := len(pubKey); l != PublicKeySize { + t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l) + } + + var priv [PrivateKeySize]byte + copy(priv[:], privBytes) + copy(priv[32:], pubKey) + + sig2 := Sign(priv[:], msg) + if !bytes.Equal(sig, sig2[:]) { + t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) + } + + if !Verify(pubKey, msg, sig2) { + t.Errorf("signature failed to verify on line %d", lineNo) + } + + priv2 := NewKeyFromSeed(priv[:32]) + if !bytes.Equal(priv[:], priv2) { + t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2) + } + + if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) { + t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2) + } + + if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) { + t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed) + } + } + + if err := scanner.Err(); err != nil { + t.Fatalf("error reading test data: %s", err) + } +} + +func TestMalleability(t *testing.T) { + // https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test + // that s be in [0, order). This prevents someone from adding a multiple of + // order to s and obtaining a second valid signature for the same message. + msg := []byte{0x54, 0x65, 0x73, 0x74} + sig := []byte{ + 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a, + 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b, + 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67, + 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, + 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, + 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d, + } + publicKey := []byte{ + 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5, + 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34, + 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, + } + + if Verify(publicKey, msg, sig) { + t.Fatal("non-canonical signature accepted") + } +} + +func TestAllocations(t *testing.T) { + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + if allocs := testing.AllocsPerRun(100, func() { + seed := make([]byte, SeedSize) + message := []byte("Hello, world!") + priv := NewKeyFromSeed(seed) + pub := priv.Public().(PublicKey) + signature := Sign(priv, message) + if !Verify(pub, message, signature) { + t.Fatal("signature didn't verify") + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1v", allocs) + } +} + +func BenchmarkKeyGeneration(b *testing.B) { + var zero zeroReader + for i := 0; i < b.N; i++ { + if _, _, err := GenerateKey(zero); err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkNewKeyFromSeed(b *testing.B) { + seed := make([]byte, SeedSize) + for i := 0; i < b.N; i++ { + _ = NewKeyFromSeed(seed) + } +} + +func BenchmarkSigning(b *testing.B) { + var zero zeroReader + _, priv, err := GenerateKey(zero) + if err != nil { + b.Fatal(err) + } + message := []byte("Hello, world!") + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sign(priv, message) + } +} + +func BenchmarkVerification(b *testing.B) { + var zero zeroReader + pub, priv, err := GenerateKey(zero) + if err != nil { + b.Fatal(err) + } + message := []byte("Hello, world!") + signature := Sign(priv, message) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Verify(pub, message, signature) + } +} diff --git a/src/crypto/ed25519/ed25519vectors_test.go b/src/crypto/ed25519/ed25519vectors_test.go new file mode 100644 index 0000000..74fcdcd --- /dev/null +++ b/src/crypto/ed25519/ed25519vectors_test.go @@ -0,0 +1,109 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ed25519_test + +import ( + "crypto/ed25519" + "encoding/hex" + "encoding/json" + "internal/testenv" + "os" + "os/exec" + "path/filepath" + "testing" +) + +// TestEd25519Vectors runs a very large set of test vectors that exercise all +// combinations of low-order points, low-order components, and non-canonical +// encodings. These vectors lock in unspecified and spec-divergent behaviors in +// edge cases that are not security relevant in most contexts, but that can +// cause issues in consensus applications if changed. +// +// Our behavior matches the "classic" unwritten verification rules of the +// "ref10" reference implementation. +// +// Note that although we test for these edge cases, they are not covered by the +// Go 1 Compatibility Promise. Applications that need stable verification rules +// should use github.com/hdevalence/ed25519consensus. +// +// See https://hdevalence.ca/blog/2020-10-04-its-25519am for more details. +func TestEd25519Vectors(t *testing.T) { + jsonVectors := downloadEd25519Vectors(t) + var vectors []struct { + A, R, S, M string + Flags []string + } + if err := json.Unmarshal(jsonVectors, &vectors); err != nil { + t.Fatal(err) + } + for i, v := range vectors { + expectedToVerify := true + for _, f := range v.Flags { + switch f { + // We use the simplified verification formula that doesn't multiply + // by the cofactor, so any low order residue will cause the + // signature not to verify. + // + // This is allowed, but not required, by RFC 8032. + case "LowOrderResidue": + expectedToVerify = false + // Our point decoding allows non-canonical encodings (in violation + // of RFC 8032) but R is not decoded: instead, R is recomputed and + // compared bytewise against the canonical encoding. + case "NonCanonicalR": + expectedToVerify = false + } + } + + publicKey := decodeHex(t, v.A) + signature := append(decodeHex(t, v.R), decodeHex(t, v.S)...) + message := []byte(v.M) + + didVerify := ed25519.Verify(publicKey, message, signature) + if didVerify && !expectedToVerify { + t.Errorf("#%d: vector with flags %s unexpectedly verified", i, v.Flags) + } + if !didVerify && expectedToVerify { + t.Errorf("#%d: vector with flags %s unexpectedly rejected", i, v.Flags) + } + } +} + +func downloadEd25519Vectors(t *testing.T) []byte { + testenv.MustHaveExternalNetwork(t) + + // Download the JSON test file from the GOPROXY with `go mod download`, + // pinning the version so test and module caching works as expected. + goTool := testenv.GoToolPath(t) + path := "filippo.io/mostly-harmless/ed25519vectors@v0.0.0-20210322192420-30a2d7243a94" + cmd := exec.Command(goTool, "mod", "download", "-json", path) + // TODO: enable the sumdb once the TryBots proxy supports it. + cmd.Env = append(os.Environ(), "GONOSUMDB=*") + output, err := cmd.Output() + if err != nil { + t.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output) + } + var dm struct { + Dir string // absolute path to cached source root directory + } + if err := json.Unmarshal(output, &dm); err != nil { + t.Fatal(err) + } + + jsonVectors, err := os.ReadFile(filepath.Join(dm.Dir, "ed25519vectors.json")) + if err != nil { + t.Fatalf("failed to read ed25519vectors.json: %v", err) + } + return jsonVectors +} + +func decodeHex(t *testing.T, s string) []byte { + t.Helper() + b, err := hex.DecodeString(s) + if err != nil { + t.Errorf("invalid hex: %v", err) + } + return b +} diff --git a/src/crypto/ed25519/internal/edwards25519/doc.go b/src/crypto/ed25519/internal/edwards25519/doc.go new file mode 100644 index 0000000..ff31cd2 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/doc.go @@ -0,0 +1,22 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package edwards25519 implements group logic for the twisted Edwards curve +// +// -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2 +// +// This is better known as the Edwards curve equivalent to Curve25519, and is +// the curve used by the Ed25519 signature scheme. +// +// Most users don't need this package, and should instead use crypto/ed25519 for +// signatures, golang.org/x/crypto/curve25519 for Diffie-Hellman, or +// github.com/gtank/ristretto255 for prime order group logic. +// +// However, developers who do need to interact with low-level edwards25519 +// operations can use filippo.io/edwards25519, an extended version of this +// package repackaged as an importable module. +// +// (Note that filippo.io/edwards25519 and github.com/gtank/ristretto255 are not +// maintained by the Go team and are not covered by the Go 1 Compatibility Promise.) +package edwards25519 diff --git a/src/crypto/ed25519/internal/edwards25519/edwards25519.go b/src/crypto/ed25519/internal/edwards25519/edwards25519.go new file mode 100644 index 0000000..313e6c2 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/edwards25519.go @@ -0,0 +1,427 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "crypto/ed25519/internal/edwards25519/field" + "errors" +) + +// Point types. + +type projP1xP1 struct { + X, Y, Z, T field.Element +} + +type projP2 struct { + X, Y, Z field.Element +} + +// Point represents a point on the edwards25519 curve. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is NOT valid, and it may be used only as a receiver. +type Point struct { + // The point is internally represented in extended coordinates (X, Y, Z, T) + // where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522. + x, y, z, t field.Element + + // Make the type not comparable (i.e. used with == or as a map key), as + // equivalent points can be represented by different Go values. + _ incomparable +} + +type incomparable [0]func() + +func checkInitialized(points ...*Point) { + for _, p := range points { + if p.x == (field.Element{}) && p.y == (field.Element{}) { + panic("edwards25519: use of uninitialized Point") + } + } +} + +type projCached struct { + YplusX, YminusX, Z, T2d field.Element +} + +type affineCached struct { + YplusX, YminusX, T2d field.Element +} + +// Constructors. + +func (v *projP2) Zero() *projP2 { + v.X.Zero() + v.Y.One() + v.Z.One() + return v +} + +// identity is the point at infinity. +var identity, _ = new(Point).SetBytes([]byte{ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) + +// NewIdentityPoint returns a new Point set to the identity. +func NewIdentityPoint() *Point { + return new(Point).Set(identity) +} + +// generator is the canonical curve basepoint. See TestGenerator for the +// correspondence of this encoding with the values in RFC 8032. +var generator, _ = new(Point).SetBytes([]byte{ + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}) + +// NewGeneratorPoint returns a new Point set to the canonical generator. +func NewGeneratorPoint() *Point { + return new(Point).Set(generator) +} + +func (v *projCached) Zero() *projCached { + v.YplusX.One() + v.YminusX.One() + v.Z.One() + v.T2d.Zero() + return v +} + +func (v *affineCached) Zero() *affineCached { + v.YplusX.One() + v.YminusX.One() + v.T2d.Zero() + return v +} + +// Assignments. + +// Set sets v = u, and returns v. +func (v *Point) Set(u *Point) *Point { + *v = *u + return v +} + +// Encoding. + +// Bytes returns the canonical 32-byte encoding of v, according to RFC 8032, +// Section 5.1.2. +func (v *Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var buf [32]byte + return v.bytes(&buf) +} + +func (v *Point) bytes(buf *[32]byte) []byte { + checkInitialized(v) + + var zInv, x, y field.Element + zInv.Invert(&v.z) // zInv = 1 / Z + x.Multiply(&v.x, &zInv) // x = X / Z + y.Multiply(&v.y, &zInv) // y = Y / Z + + out := copyFieldElement(buf, &y) + out[31] |= byte(x.IsNegative() << 7) + return out +} + +var feOne = new(field.Element).One() + +// SetBytes sets v = x, where x is a 32-byte encoding of v. If x does not +// represent a valid point on the curve, SetBytes returns nil and an error and +// the receiver is unchanged. Otherwise, SetBytes returns v. +// +// Note that SetBytes accepts all non-canonical encodings of valid points. +// That is, it follows decoding rules that match most implementations in +// the ecosystem rather than RFC 8032. +func (v *Point) SetBytes(x []byte) (*Point, error) { + // Specifically, the non-canonical encodings that are accepted are + // 1) the ones where the field element is not reduced (see the + // (*field.Element).SetBytes docs) and + // 2) the ones where the x-coordinate is zero and the sign bit is set. + // + // This is consistent with crypto/ed25519/internal/edwards25519. Read more + // at https://hdevalence.ca/blog/2020-10-04-its-25519am, specifically the + // "Canonical A, R" section. + + if len(x) != 32 { + return nil, errors.New("edwards25519: invalid point encoding length") + } + y := new(field.Element).SetBytes(x) + + // -x² + y² = 1 + dx²y² + // x² + dx²y² = x²(dy² + 1) = y² - 1 + // x² = (y² - 1) / (dy² + 1) + + // u = y² - 1 + y2 := new(field.Element).Square(y) + u := new(field.Element).Subtract(y2, feOne) + + // v = dy² + 1 + vv := new(field.Element).Multiply(y2, d) + vv = vv.Add(vv, feOne) + + // x = +√(u/v) + xx, wasSquare := new(field.Element).SqrtRatio(u, vv) + if wasSquare == 0 { + return nil, errors.New("edwards25519: invalid point encoding") + } + + // Select the negative square root if the sign bit is set. + xxNeg := new(field.Element).Negate(xx) + xx = xx.Select(xxNeg, xx, int(x[31]>>7)) + + v.x.Set(xx) + v.y.Set(y) + v.z.One() + v.t.Multiply(xx, y) // xy = T / Z + + return v, nil +} + +func copyFieldElement(buf *[32]byte, v *field.Element) []byte { + copy(buf[:], v.Bytes()) + return buf[:] +} + +// Conversions. + +func (v *projP2) FromP1xP1(p *projP1xP1) *projP2 { + v.X.Multiply(&p.X, &p.T) + v.Y.Multiply(&p.Y, &p.Z) + v.Z.Multiply(&p.Z, &p.T) + return v +} + +func (v *projP2) FromP3(p *Point) *projP2 { + v.X.Set(&p.x) + v.Y.Set(&p.y) + v.Z.Set(&p.z) + return v +} + +func (v *Point) fromP1xP1(p *projP1xP1) *Point { + v.x.Multiply(&p.X, &p.T) + v.y.Multiply(&p.Y, &p.Z) + v.z.Multiply(&p.Z, &p.T) + v.t.Multiply(&p.X, &p.Y) + return v +} + +func (v *Point) fromP2(p *projP2) *Point { + v.x.Multiply(&p.X, &p.Z) + v.y.Multiply(&p.Y, &p.Z) + v.z.Square(&p.Z) + v.t.Multiply(&p.X, &p.Y) + return v +} + +// d is a constant in the curve equation. +var d = new(field.Element).SetBytes([]byte{ + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52}) +var d2 = new(field.Element).Add(d, d) + +func (v *projCached) FromP3(p *Point) *projCached { + v.YplusX.Add(&p.y, &p.x) + v.YminusX.Subtract(&p.y, &p.x) + v.Z.Set(&p.z) + v.T2d.Multiply(&p.t, d2) + return v +} + +func (v *affineCached) FromP3(p *Point) *affineCached { + v.YplusX.Add(&p.y, &p.x) + v.YminusX.Subtract(&p.y, &p.x) + v.T2d.Multiply(&p.t, d2) + + var invZ field.Element + invZ.Invert(&p.z) + v.YplusX.Multiply(&v.YplusX, &invZ) + v.YminusX.Multiply(&v.YminusX, &invZ) + v.T2d.Multiply(&v.T2d, &invZ) + return v +} + +// (Re)addition and subtraction. + +// Add sets v = p + q, and returns v. +func (v *Point) Add(p, q *Point) *Point { + checkInitialized(p, q) + qCached := new(projCached).FromP3(q) + result := new(projP1xP1).Add(p, qCached) + return v.fromP1xP1(result) +} + +// Subtract sets v = p - q, and returns v. +func (v *Point) Subtract(p, q *Point) *Point { + checkInitialized(p, q) + qCached := new(projCached).FromP3(q) + result := new(projP1xP1).Sub(p, qCached) + return v.fromP1xP1(result) +} + +func (v *projP1xP1) Add(p *Point, q *projCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YplusX) + MM.Multiply(&YminusX, &q.YminusX) + TT2d.Multiply(&p.t, &q.T2d) + ZZ2.Multiply(&p.z, &q.Z) + + ZZ2.Add(&ZZ2, &ZZ2) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Add(&ZZ2, &TT2d) + v.T.Subtract(&ZZ2, &TT2d) + return v +} + +func (v *projP1xP1) Sub(p *Point, q *projCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YminusX) // flipped sign + MM.Multiply(&YminusX, &q.YplusX) // flipped sign + TT2d.Multiply(&p.t, &q.T2d) + ZZ2.Multiply(&p.z, &q.Z) + + ZZ2.Add(&ZZ2, &ZZ2) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Subtract(&ZZ2, &TT2d) // flipped sign + v.T.Add(&ZZ2, &TT2d) // flipped sign + return v +} + +func (v *projP1xP1) AddAffine(p *Point, q *affineCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YplusX) + MM.Multiply(&YminusX, &q.YminusX) + TT2d.Multiply(&p.t, &q.T2d) + + Z2.Add(&p.z, &p.z) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Add(&Z2, &TT2d) + v.T.Subtract(&Z2, &TT2d) + return v +} + +func (v *projP1xP1) SubAffine(p *Point, q *affineCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YminusX) // flipped sign + MM.Multiply(&YminusX, &q.YplusX) // flipped sign + TT2d.Multiply(&p.t, &q.T2d) + + Z2.Add(&p.z, &p.z) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Subtract(&Z2, &TT2d) // flipped sign + v.T.Add(&Z2, &TT2d) // flipped sign + return v +} + +// Doubling. + +func (v *projP1xP1) Double(p *projP2) *projP1xP1 { + var XX, YY, ZZ2, XplusYsq field.Element + + XX.Square(&p.X) + YY.Square(&p.Y) + ZZ2.Square(&p.Z) + ZZ2.Add(&ZZ2, &ZZ2) + XplusYsq.Add(&p.X, &p.Y) + XplusYsq.Square(&XplusYsq) + + v.Y.Add(&YY, &XX) + v.Z.Subtract(&YY, &XX) + + v.X.Subtract(&XplusYsq, &v.Y) + v.T.Subtract(&ZZ2, &v.Z) + return v +} + +// Negation. + +// Negate sets v = -p, and returns v. +func (v *Point) Negate(p *Point) *Point { + checkInitialized(p) + v.x.Negate(&p.x) + v.y.Set(&p.y) + v.z.Set(&p.z) + v.t.Negate(&p.t) + return v +} + +// Equal returns 1 if v is equivalent to u, and 0 otherwise. +func (v *Point) Equal(u *Point) int { + checkInitialized(v, u) + + var t1, t2, t3, t4 field.Element + t1.Multiply(&v.x, &u.z) + t2.Multiply(&u.x, &v.z) + t3.Multiply(&v.y, &u.z) + t4.Multiply(&u.y, &v.z) + + return t1.Equal(&t2) & t3.Equal(&t4) +} + +// Constant-time operations + +// Select sets v to a if cond == 1 and to b if cond == 0. +func (v *projCached) Select(a, b *projCached, cond int) *projCached { + v.YplusX.Select(&a.YplusX, &b.YplusX, cond) + v.YminusX.Select(&a.YminusX, &b.YminusX, cond) + v.Z.Select(&a.Z, &b.Z, cond) + v.T2d.Select(&a.T2d, &b.T2d, cond) + return v +} + +// Select sets v to a if cond == 1 and to b if cond == 0. +func (v *affineCached) Select(a, b *affineCached, cond int) *affineCached { + v.YplusX.Select(&a.YplusX, &b.YplusX, cond) + v.YminusX.Select(&a.YminusX, &b.YminusX, cond) + v.T2d.Select(&a.T2d, &b.T2d, cond) + return v +} + +// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. +func (v *projCached) CondNeg(cond int) *projCached { + v.YplusX.Swap(&v.YminusX, cond) + v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond) + return v +} + +// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. +func (v *affineCached) CondNeg(cond int) *affineCached { + v.YplusX.Swap(&v.YminusX, cond) + v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond) + return v +} diff --git a/src/crypto/ed25519/internal/edwards25519/edwards25519_test.go b/src/crypto/ed25519/internal/edwards25519/edwards25519_test.go new file mode 100644 index 0000000..8031256 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/edwards25519_test.go @@ -0,0 +1,304 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "crypto/ed25519/internal/edwards25519/field" + "encoding/hex" + "os" + "reflect" + "strings" + "testing" +) + +var B = NewGeneratorPoint() +var I = NewIdentityPoint() + +func checkOnCurve(t *testing.T, points ...*Point) { + t.Helper() + for i, p := range points { + var XX, YY, ZZ, ZZZZ field.Element + XX.Square(&p.x) + YY.Square(&p.y) + ZZ.Square(&p.z) + ZZZZ.Square(&ZZ) + // -x² + y² = 1 + dx²y² + // -(X/Z)² + (Y/Z)² = 1 + d(X/Z)²(Y/Z)² + // (-X² + Y²)/Z² = 1 + (dX²Y²)/Z⁴ + // (-X² + Y²)*Z² = Z⁴ + dX²Y² + var lhs, rhs field.Element + lhs.Subtract(&YY, &XX).Multiply(&lhs, &ZZ) + rhs.Multiply(d, &XX).Multiply(&rhs, &YY).Add(&rhs, &ZZZZ) + if lhs.Equal(&rhs) != 1 { + t.Errorf("X, Y, and Z do not specify a point on the curve\nX = %v\nY = %v\nZ = %v", p.x, p.y, p.z) + } + // xy = T/Z + lhs.Multiply(&p.x, &p.y) + rhs.Multiply(&p.z, &p.t) + if lhs.Equal(&rhs) != 1 { + t.Errorf("point %d is not valid\nX = %v\nY = %v\nZ = %v", i, p.x, p.y, p.z) + } + } +} + +func TestGenerator(t *testing.T) { + // These are the coordinates of B from RFC 8032, Section 5.1, converted to + // little endian hex. + x := "1ad5258f602d56c9b2a7259560c72c695cdcd6fd31e2a4c0fe536ecdd3366921" + y := "5866666666666666666666666666666666666666666666666666666666666666" + if got := hex.EncodeToString(B.x.Bytes()); got != x { + t.Errorf("wrong B.x: got %s, expected %s", got, x) + } + if got := hex.EncodeToString(B.y.Bytes()); got != y { + t.Errorf("wrong B.y: got %s, expected %s", got, y) + } + if B.z.Equal(feOne) != 1 { + t.Errorf("wrong B.z: got %v, expected 1", B.z) + } + // Check that t is correct. + checkOnCurve(t, B) +} + +func TestAddSubNegOnBasePoint(t *testing.T) { + checkLhs, checkRhs := &Point{}, &Point{} + + checkLhs.Add(B, B) + tmpP2 := new(projP2).FromP3(B) + tmpP1xP1 := new(projP1xP1).Double(tmpP2) + checkRhs.fromP1xP1(tmpP1xP1) + if checkLhs.Equal(checkRhs) != 1 { + t.Error("B + B != [2]B") + } + checkOnCurve(t, checkLhs, checkRhs) + + checkLhs.Subtract(B, B) + Bneg := new(Point).Negate(B) + checkRhs.Add(B, Bneg) + if checkLhs.Equal(checkRhs) != 1 { + t.Error("B - B != B + (-B)") + } + if I.Equal(checkLhs) != 1 { + t.Error("B - B != 0") + } + if I.Equal(checkRhs) != 1 { + t.Error("B + (-B) != 0") + } + checkOnCurve(t, checkLhs, checkRhs, Bneg) +} + +func TestComparable(t *testing.T) { + if reflect.TypeOf(Point{}).Comparable() { + t.Error("Point is unexpectedly comparable") + } +} + +func TestInvalidEncodings(t *testing.T) { + // An invalid point, that also happens to have y > p. + invalid := "efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f" + p := NewGeneratorPoint() + if out, err := p.SetBytes(decodeHex(invalid)); err == nil { + t.Error("expected error for invalid point") + } else if out != nil { + t.Error("SetBytes did not return nil on an invalid encoding") + } else if p.Equal(B) != 1 { + t.Error("the Point was modified while decoding an invalid encoding") + } + checkOnCurve(t, p) +} + +func TestNonCanonicalPoints(t *testing.T) { + type test struct { + name string + encoding, canonical string + } + tests := []test{ + // Points with x = 0 and the sign bit set. With x = 0 the curve equation + // gives y² = 1, so y = ±1. 1 has two valid encodings. + { + "y=1,sign-", + "0100000000000000000000000000000000000000000000000000000000000080", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+1,sign-", + "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p-1,sign-", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + }, + + // Non-canonical y encodings with values 2²⁵⁵-19 (p) to 2²⁵⁵-1 (p+18). + { + "y=p,sign+", + "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0000000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p,sign-", + "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0000000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+1,sign+", + "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + // "y=p+1,sign-" is already tested above. + // p+2 is not a valid y-coordinate. + { + "y=p+3,sign+", + "f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0300000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+3,sign-", + "f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0300000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+4,sign+", + "f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0400000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+4,sign-", + "f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0400000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+5,sign+", + "f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0500000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+5,sign-", + "f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0500000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+6,sign+", + "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0600000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+6,sign-", + "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0600000000000000000000000000000000000000000000000000000000000080", + }, + // p+7 is not a valid y-coordinate. + // p+8 is not a valid y-coordinate. + { + "y=p+9,sign+", + "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0900000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+9,sign-", + "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0900000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+10,sign+", + "f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0a00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+10,sign-", + "f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0a00000000000000000000000000000000000000000000000000000000000080", + }, + // p+11 is not a valid y-coordinate. + // p+12 is not a valid y-coordinate. + // p+13 is not a valid y-coordinate. + { + "y=p+14,sign+", + "fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0e00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+14,sign-", + "fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0e00000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+15,sign+", + "fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0f00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+15,sign-", + "fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0f00000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+16,sign+", + "fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "1000000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+16,sign-", + "fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "1000000000000000000000000000000000000000000000000000000000000080", + }, + // p+17 is not a valid y-coordinate. + { + "y=p+18,sign+", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "1200000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+18,sign-", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "1200000000000000000000000000000000000000000000000000000000000080", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p1, err := new(Point).SetBytes(decodeHex(tt.encoding)) + if err != nil { + t.Fatalf("error decoding non-canonical point: %v", err) + } + p2, err := new(Point).SetBytes(decodeHex(tt.canonical)) + if err != nil { + t.Fatalf("error decoding canonical point: %v", err) + } + if p1.Equal(p2) != 1 { + t.Errorf("equivalent points are not equal: %v, %v", p1, p2) + } + if encoding := hex.EncodeToString(p1.Bytes()); encoding != tt.canonical { + t.Errorf("re-encoding does not match canonical; got %q, expected %q", encoding, tt.canonical) + } + checkOnCurve(t, p1, p2) + }) + } +} + +var testAllocationsSink byte + +func TestAllocations(t *testing.T) { + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + if allocs := testing.AllocsPerRun(100, func() { + p := NewIdentityPoint() + p.Add(p, NewGeneratorPoint()) + s := NewScalar() + testAllocationsSink ^= s.Bytes()[0] + testAllocationsSink ^= p.Bytes()[0] + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1v", allocs) + } +} + +func decodeHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} diff --git a/src/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go b/src/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go new file mode 100644 index 0000000..fbc0cce --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go @@ -0,0 +1,294 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/gotypes" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" +) + +//go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field + +func main() { + Package("crypto/ed25519/internal/edwards25519/field") + ConstraintExpr("amd64,gc,!purego") + feMul() + feSquare() + Generate() +} + +type namedComponent struct { + Component + name string +} + +func (c namedComponent) String() string { return c.name } + +type uint128 struct { + name string + hi, lo GPVirtual +} + +func (c uint128) String() string { return c.name } + +func feSquare() { + TEXT("feSquare", NOSPLIT, "func(out, a *Element)") + Doc("feSquare sets out = a * a. It works like feSquareGeneric.") + Pragma("noescape") + + a := Dereference(Param("a")) + l0 := namedComponent{a.Field("l0"), "l0"} + l1 := namedComponent{a.Field("l1"), "l1"} + l2 := namedComponent{a.Field("l2"), "l2"} + l3 := namedComponent{a.Field("l3"), "l3"} + l4 := namedComponent{a.Field("l4"), "l4"} + + // r0 = l0×l0 + 19×2×(l1×l4 + l2×l3) + r0 := uint128{"r0", GP64(), GP64()} + mul64(r0, 1, l0, l0) + addMul64(r0, 38, l1, l4) + addMul64(r0, 38, l2, l3) + + // r1 = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 + r1 := uint128{"r1", GP64(), GP64()} + mul64(r1, 2, l0, l1) + addMul64(r1, 38, l2, l4) + addMul64(r1, 19, l3, l3) + + // r2 = = 2×l0×l2 + l1×l1 + 19×2×l3×l4 + r2 := uint128{"r2", GP64(), GP64()} + mul64(r2, 2, l0, l2) + addMul64(r2, 1, l1, l1) + addMul64(r2, 38, l3, l4) + + // r3 = = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 + r3 := uint128{"r3", GP64(), GP64()} + mul64(r3, 2, l0, l3) + addMul64(r3, 2, l1, l2) + addMul64(r3, 19, l4, l4) + + // r4 = = 2×l0×l4 + 2×l1×l3 + l2×l2 + r4 := uint128{"r4", GP64(), GP64()} + mul64(r4, 2, l0, l4) + addMul64(r4, 2, l1, l3) + addMul64(r4, 1, l2, l2) + + Comment("First reduction chain") + maskLow51Bits := GP64() + MOVQ(Imm((1<<51)-1), maskLow51Bits) + c0, r0lo := shiftRightBy51(&r0) + c1, r1lo := shiftRightBy51(&r1) + c2, r2lo := shiftRightBy51(&r2) + c3, r3lo := shiftRightBy51(&r3) + c4, r4lo := shiftRightBy51(&r4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Second reduction chain (carryPropagate)") + // c0 = r0 >> 51 + MOVQ(r0lo, c0) + SHRQ(Imm(51), c0) + // c1 = r1 >> 51 + MOVQ(r1lo, c1) + SHRQ(Imm(51), c1) + // c2 = r2 >> 51 + MOVQ(r2lo, c2) + SHRQ(Imm(51), c2) + // c3 = r3 >> 51 + MOVQ(r3lo, c3) + SHRQ(Imm(51), c3) + // c4 = r4 >> 51 + MOVQ(r4lo, c4) + SHRQ(Imm(51), c4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Store output") + out := Dereference(Param("out")) + Store(r0lo, out.Field("l0")) + Store(r1lo, out.Field("l1")) + Store(r2lo, out.Field("l2")) + Store(r3lo, out.Field("l3")) + Store(r4lo, out.Field("l4")) + + RET() +} + +func feMul() { + TEXT("feMul", NOSPLIT, "func(out, a, b *Element)") + Doc("feMul sets out = a * b. It works like feMulGeneric.") + Pragma("noescape") + + a := Dereference(Param("a")) + a0 := namedComponent{a.Field("l0"), "a0"} + a1 := namedComponent{a.Field("l1"), "a1"} + a2 := namedComponent{a.Field("l2"), "a2"} + a3 := namedComponent{a.Field("l3"), "a3"} + a4 := namedComponent{a.Field("l4"), "a4"} + + b := Dereference(Param("b")) + b0 := namedComponent{b.Field("l0"), "b0"} + b1 := namedComponent{b.Field("l1"), "b1"} + b2 := namedComponent{b.Field("l2"), "b2"} + b3 := namedComponent{b.Field("l3"), "b3"} + b4 := namedComponent{b.Field("l4"), "b4"} + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + r0 := uint128{"r0", GP64(), GP64()} + mul64(r0, 1, a0, b0) + addMul64(r0, 19, a1, b4) + addMul64(r0, 19, a2, b3) + addMul64(r0, 19, a3, b2) + addMul64(r0, 19, a4, b1) + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + r1 := uint128{"r1", GP64(), GP64()} + mul64(r1, 1, a0, b1) + addMul64(r1, 1, a1, b0) + addMul64(r1, 19, a2, b4) + addMul64(r1, 19, a3, b3) + addMul64(r1, 19, a4, b2) + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + r2 := uint128{"r2", GP64(), GP64()} + mul64(r2, 1, a0, b2) + addMul64(r2, 1, a1, b1) + addMul64(r2, 1, a2, b0) + addMul64(r2, 19, a3, b4) + addMul64(r2, 19, a4, b3) + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + r3 := uint128{"r3", GP64(), GP64()} + mul64(r3, 1, a0, b3) + addMul64(r3, 1, a1, b2) + addMul64(r3, 1, a2, b1) + addMul64(r3, 1, a3, b0) + addMul64(r3, 19, a4, b4) + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + r4 := uint128{"r4", GP64(), GP64()} + mul64(r4, 1, a0, b4) + addMul64(r4, 1, a1, b3) + addMul64(r4, 1, a2, b2) + addMul64(r4, 1, a3, b1) + addMul64(r4, 1, a4, b0) + + Comment("First reduction chain") + maskLow51Bits := GP64() + MOVQ(Imm((1<<51)-1), maskLow51Bits) + c0, r0lo := shiftRightBy51(&r0) + c1, r1lo := shiftRightBy51(&r1) + c2, r2lo := shiftRightBy51(&r2) + c3, r3lo := shiftRightBy51(&r3) + c4, r4lo := shiftRightBy51(&r4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Second reduction chain (carryPropagate)") + // c0 = r0 >> 51 + MOVQ(r0lo, c0) + SHRQ(Imm(51), c0) + // c1 = r1 >> 51 + MOVQ(r1lo, c1) + SHRQ(Imm(51), c1) + // c2 = r2 >> 51 + MOVQ(r2lo, c2) + SHRQ(Imm(51), c2) + // c3 = r3 >> 51 + MOVQ(r3lo, c3) + SHRQ(Imm(51), c3) + // c4 = r4 >> 51 + MOVQ(r4lo, c4) + SHRQ(Imm(51), c4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Store output") + out := Dereference(Param("out")) + Store(r0lo, out.Field("l0")) + Store(r1lo, out.Field("l1")) + Store(r2lo, out.Field("l2")) + Store(r3lo, out.Field("l3")) + Store(r4lo, out.Field("l4")) + + RET() +} + +// mul64 sets r to i * aX * bX. +func mul64(r uint128, i int, aX, bX namedComponent) { + switch i { + case 1: + Comment(fmt.Sprintf("%s = %s×%s", r, aX, bX)) + Load(aX, RAX) + case 2: + Comment(fmt.Sprintf("%s = 2×%s×%s", r, aX, bX)) + Load(aX, RAX) + SHLQ(Imm(1), RAX) + default: + panic("unsupported i value") + } + MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX + MOVQ(RAX, r.lo) + MOVQ(RDX, r.hi) +} + +// addMul64 sets r to r + i * aX * bX. +func addMul64(r uint128, i uint64, aX, bX namedComponent) { + switch i { + case 1: + Comment(fmt.Sprintf("%s += %s×%s", r, aX, bX)) + Load(aX, RAX) + default: + Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX)) + IMUL3Q(Imm(i), Load(aX, GP64()), RAX) + } + MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX + ADDQ(RAX, r.lo) + ADCQ(RDX, r.hi) +} + +// shiftRightBy51 returns r >> 51 and r.lo. +// +// After this function is called, the uint128 may not be used anymore. +func shiftRightBy51(r *uint128) (out, lo GPVirtual) { + out = r.hi + lo = r.lo + SHLQ(Imm(64-51), r.lo, r.hi) + r.lo, r.hi = nil, nil // make sure the uint128 is unusable + return +} + +// maskAndAdd sets r = r&mask + c*i. +func maskAndAdd(r, mask, c GPVirtual, i uint64) { + ANDQ(mask, r) + if i != 1 { + IMUL3Q(Imm(i), c, c) + } + ADDQ(c, r) +} + +func mustAddr(c Component) Op { + b, err := c.Resolve() + if err != nil { + panic(err) + } + return b.Addr +} diff --git a/src/crypto/ed25519/internal/edwards25519/field/_asm/go.mod b/src/crypto/ed25519/internal/edwards25519/field/_asm/go.mod new file mode 100644 index 0000000..1127ade --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/_asm/go.mod @@ -0,0 +1,5 @@ +module asm + +go 1.16 + +require github.com/mmcloughlin/avo v0.2.0 diff --git a/src/crypto/ed25519/internal/edwards25519/field/_asm/go.sum b/src/crypto/ed25519/internal/edwards25519/field/_asm/go.sum new file mode 100644 index 0000000..dae4777 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/_asm/go.sum @@ -0,0 +1,31 @@ +github.com/mmcloughlin/avo v0.2.0 h1:6vhoSaKtxb6f4RiH+LK2qL6GSMpFzhEwJYTTSZNy09w= +github.com/mmcloughlin/avo v0.2.0/go.mod h1:5tidO2Z9Z7N6X7UMcGg+1KTj51O8OxYDCMHxCZTVpEA= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/arch v0.0.0-20210405154355-08b684f594a5/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe.go b/src/crypto/ed25519/internal/edwards25519/field/fe.go new file mode 100644 index 0000000..dbe8659 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe.go @@ -0,0 +1,416 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package field implements fast arithmetic modulo 2^255-19. +package field + +import ( + "crypto/subtle" + "encoding/binary" + "math/bits" +) + +// Element represents an element of the field GF(2^255-19). Note that this +// is not a cryptographically secure group, and should only be used to interact +// with edwards25519.Point coordinates. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is a valid zero element. +type Element struct { + // An element t represents the integer + // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 + // + // Between operations, all limbs are expected to be lower than 2^52. + l0 uint64 + l1 uint64 + l2 uint64 + l3 uint64 + l4 uint64 +} + +const maskLow51Bits uint64 = (1 << 51) - 1 + +var feZero = &Element{0, 0, 0, 0, 0} + +// Zero sets v = 0, and returns v. +func (v *Element) Zero() *Element { + *v = *feZero + return v +} + +var feOne = &Element{1, 0, 0, 0, 0} + +// One sets v = 1, and returns v. +func (v *Element) One() *Element { + *v = *feOne + return v +} + +// reduce reduces v modulo 2^255 - 19 and returns it. +func (v *Element) reduce() *Element { + v.carryPropagate() + + // After the light reduction we now have a field element representation + // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. + + // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, + // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. + c := (v.l0 + 19) >> 51 + c = (v.l1 + c) >> 51 + c = (v.l2 + c) >> 51 + c = (v.l3 + c) >> 51 + c = (v.l4 + c) >> 51 + + // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's + // effectively applying the reduction identity to the carry. + v.l0 += 19 * c + + v.l1 += v.l0 >> 51 + v.l0 = v.l0 & maskLow51Bits + v.l2 += v.l1 >> 51 + v.l1 = v.l1 & maskLow51Bits + v.l3 += v.l2 >> 51 + v.l2 = v.l2 & maskLow51Bits + v.l4 += v.l3 >> 51 + v.l3 = v.l3 & maskLow51Bits + // no additional carry + v.l4 = v.l4 & maskLow51Bits + + return v +} + +// Add sets v = a + b, and returns v. +func (v *Element) Add(a, b *Element) *Element { + v.l0 = a.l0 + b.l0 + v.l1 = a.l1 + b.l1 + v.l2 = a.l2 + b.l2 + v.l3 = a.l3 + b.l3 + v.l4 = a.l4 + b.l4 + // Using the generic implementation here is actually faster than the + // assembly. Probably because the body of this function is so simple that + // the compiler can figure out better optimizations by inlining the carry + // propagation. + return v.carryPropagateGeneric() +} + +// Subtract sets v = a - b, and returns v. +func (v *Element) Subtract(a, b *Element) *Element { + // We first add 2 * p, to guarantee the subtraction won't underflow, and + // then subtract b (which can be up to 2^255 + 2^13 * 19). + v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 + v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 + v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 + v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 + v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 + return v.carryPropagate() +} + +// Negate sets v = -a, and returns v. +func (v *Element) Negate(a *Element) *Element { + return v.Subtract(feZero, a) +} + +// Invert sets v = 1/z mod p, and returns v. +// +// If z == 0, Invert returns v = 0. +func (v *Element) Invert(z *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. It uses the + // same sequence of 255 squarings and 11 multiplications as [Curve25519]. + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element + + z2.Square(z) // 2 + t.Square(&z2) // 4 + t.Square(&t) // 8 + z9.Multiply(&t, z) // 9 + z11.Multiply(&z9, &z2) // 11 + t.Square(&z11) // 22 + z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 + + t.Square(&z2_5_0) // 2^6 - 2^1 + for i := 0; i < 4; i++ { + t.Square(&t) // 2^10 - 2^5 + } + z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 + + t.Square(&z2_10_0) // 2^11 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^20 - 2^10 + } + z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 + + t.Square(&z2_20_0) // 2^21 - 2^1 + for i := 0; i < 19; i++ { + t.Square(&t) // 2^40 - 2^20 + } + t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 + + t.Square(&t) // 2^41 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^50 - 2^10 + } + z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 + + t.Square(&z2_50_0) // 2^51 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^100 - 2^50 + } + z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 + + t.Square(&z2_100_0) // 2^101 - 2^1 + for i := 0; i < 99; i++ { + t.Square(&t) // 2^200 - 2^100 + } + t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 + + t.Square(&t) // 2^201 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^250 - 2^50 + } + t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 + + t.Square(&t) // 2^251 - 2^1 + t.Square(&t) // 2^252 - 2^2 + t.Square(&t) // 2^253 - 2^3 + t.Square(&t) // 2^254 - 2^4 + t.Square(&t) // 2^255 - 2^5 + + return v.Multiply(&t, &z11) // 2^255 - 21 +} + +// Set sets v = a, and returns v. +func (v *Element) Set(a *Element) *Element { + *v = *a + return v +} + +// SetBytes sets v to x, which must be a 32-byte little-endian encoding. +// +// Consistent with RFC 7748, the most significant bit (the high bit of the +// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) +// are accepted. Note that this is laxer than specified by RFC 8032. +func (v *Element) SetBytes(x []byte) *Element { + if len(x) != 32 { + panic("edwards25519: invalid field element input size") + } + + // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). + v.l0 = binary.LittleEndian.Uint64(x[0:8]) + v.l0 &= maskLow51Bits + // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). + v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3 + v.l1 &= maskLow51Bits + // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). + v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6 + v.l2 &= maskLow51Bits + // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). + v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 + v.l3 &= maskLow51Bits + // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). + // Note: not bytes 25:33, shift 4, to avoid overread. + v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 + v.l4 &= maskLow51Bits + + return v +} + +// Bytes returns the canonical 32-byte little-endian encoding of v. +func (v *Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [32]byte + return v.bytes(&out) +} + +func (v *Element) bytes(out *[32]byte) []byte { + t := *v + t.reduce() + + var buf [8]byte + for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { + bitsOffset := i * 51 + binary.LittleEndian.PutUint64(buf[:], l<= len(out) { + break + } + out[off] |= bb + } + } + + return out[:] +} + +// Equal returns 1 if v and u are equal, and 0 otherwise. +func (v *Element) Equal(u *Element) int { + sa, sv := u.Bytes(), v.Bytes() + return subtle.ConstantTimeCompare(sa, sv) +} + +// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. +func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *Element) Select(a, b *Element, cond int) *Element { + m := mask64Bits(cond) + v.l0 = (m & a.l0) | (^m & b.l0) + v.l1 = (m & a.l1) | (^m & b.l1) + v.l2 = (m & a.l2) | (^m & b.l2) + v.l3 = (m & a.l3) | (^m & b.l3) + v.l4 = (m & a.l4) | (^m & b.l4) + return v +} + +// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. +func (v *Element) Swap(u *Element, cond int) { + m := mask64Bits(cond) + t := m & (v.l0 ^ u.l0) + v.l0 ^= t + u.l0 ^= t + t = m & (v.l1 ^ u.l1) + v.l1 ^= t + u.l1 ^= t + t = m & (v.l2 ^ u.l2) + v.l2 ^= t + u.l2 ^= t + t = m & (v.l3 ^ u.l3) + v.l3 ^= t + u.l3 ^= t + t = m & (v.l4 ^ u.l4) + v.l4 ^= t + u.l4 ^= t +} + +// IsNegative returns 1 if v is negative, and 0 otherwise. +func (v *Element) IsNegative() int { + return int(v.Bytes()[0] & 1) +} + +// Absolute sets v to |u|, and returns v. +func (v *Element) Absolute(u *Element) *Element { + return v.Select(new(Element).Negate(u), u, u.IsNegative()) +} + +// Multiply sets v = x * y, and returns v. +func (v *Element) Multiply(x, y *Element) *Element { + feMul(v, x, y) + return v +} + +// Square sets v = x * x, and returns v. +func (v *Element) Square(x *Element) *Element { + feSquare(v, x) + return v +} + +// Mult32 sets v = x * y, and returns v. +func (v *Element) Mult32(x *Element, y uint32) *Element { + x0lo, x0hi := mul51(x.l0, y) + x1lo, x1hi := mul51(x.l1, y) + x2lo, x2hi := mul51(x.l2, y) + x3lo, x3hi := mul51(x.l3, y) + x4lo, x4hi := mul51(x.l4, y) + v.l0 = x0lo + 19*x4hi // carried over per the reduction identity + v.l1 = x1lo + x0hi + v.l2 = x2lo + x1hi + v.l3 = x3lo + x2hi + v.l4 = x4lo + x3hi + // The hi portions are going to be only 32 bits, plus any previous excess, + // so we can skip the carry propagation. + return v +} + +// mul51 returns lo + hi * 2⁵¹ = a * b. +func mul51(a uint64, b uint32) (lo uint64, hi uint64) { + mh, ml := bits.Mul64(a, uint64(b)) + lo = ml & maskLow51Bits + hi = (mh << 13) | (ml >> 51) + return +} + +// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. +func (v *Element) Pow22523(x *Element) *Element { + var t0, t1, t2 Element + + t0.Square(x) // x^2 + t1.Square(&t0) // x^4 + t1.Square(&t1) // x^8 + t1.Multiply(x, &t1) // x^9 + t0.Multiply(&t0, &t1) // x^11 + t0.Square(&t0) // x^22 + t0.Multiply(&t1, &t0) // x^31 + t1.Square(&t0) // x^62 + for i := 1; i < 5; i++ { // x^992 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 + t1.Square(&t0) // 2^11 - 2 + for i := 1; i < 10; i++ { // 2^20 - 2^10 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^20 - 1 + t2.Square(&t1) // 2^21 - 2 + for i := 1; i < 20; i++ { // 2^40 - 2^20 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^40 - 1 + t1.Square(&t1) // 2^41 - 2 + for i := 1; i < 10; i++ { // 2^50 - 2^10 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^50 - 1 + t1.Square(&t0) // 2^51 - 2 + for i := 1; i < 50; i++ { // 2^100 - 2^50 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^100 - 1 + t2.Square(&t1) // 2^101 - 2 + for i := 1; i < 100; i++ { // 2^200 - 2^100 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^200 - 1 + t1.Square(&t1) // 2^201 - 2 + for i := 1; i < 50; i++ { // 2^250 - 2^50 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^250 - 1 + t0.Square(&t0) // 2^251 - 2 + t0.Square(&t0) // 2^252 - 4 + return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) +} + +// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. +var sqrtM1 = &Element{1718705420411056, 234908883556509, + 2233514472574048, 2117202627021982, 765476049583133} + +// SqrtRatio sets r to the non-negative square root of the ratio of u and v. +// +// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio +// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, +// and returns r and 0. +func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { + var a, b Element + + // r = (u * v3) * (u * v7)^((p-5)/8) + v2 := a.Square(v) + uv3 := b.Multiply(u, b.Multiply(v2, v)) + uv7 := a.Multiply(uv3, a.Square(v2)) + r.Multiply(uv3, r.Pow22523(uv7)) + + check := a.Multiply(v, a.Square(r)) // check = v * r^2 + + uNeg := b.Negate(u) + correctSignSqrt := check.Equal(u) + flippedSignSqrt := check.Equal(uNeg) + flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) + + rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r + // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) + r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) + + r.Absolute(r) // Choose the nonnegative square root. + return r, correctSignSqrt | flippedSignSqrt +} diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go b/src/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go new file mode 100644 index 0000000..5ad81df --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go @@ -0,0 +1,126 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import ( + "testing" + "testing/quick" +) + +func checkAliasingOneArg(f func(v, x *Element) *Element) func(v, x Element) bool { + return func(v, x Element) bool { + x1, v1 := x, x + + // Calculate a reference f(x) without aliasing. + if out := f(&v, &x); out != &v && isInBounds(out) { + return false + } + + // Test aliasing the argument and the receiver. + if out := f(&v1, &v1); out != &v1 || v1 != v { + return false + } + + // Ensure the arguments was not modified. + return x == x1 + } +} + +func checkAliasingTwoArgs(f func(v, x, y *Element) *Element) func(v, x, y Element) bool { + return func(v, x, y Element) bool { + x1, y1, v1 := x, y, Element{} + + // Calculate a reference f(x, y) without aliasing. + if out := f(&v, &x, &y); out != &v && isInBounds(out) { + return false + } + + // Test aliasing the first argument and the receiver. + v1 = x + if out := f(&v1, &v1, &y); out != &v1 || v1 != v { + return false + } + // Test aliasing the second argument and the receiver. + v1 = y + if out := f(&v1, &x, &v1); out != &v1 || v1 != v { + return false + } + + // Calculate a reference f(x, x) without aliasing. + if out := f(&v, &x, &x); out != &v { + return false + } + + // Test aliasing the first argument and the receiver. + v1 = x + if out := f(&v1, &v1, &x); out != &v1 || v1 != v { + return false + } + // Test aliasing the second argument and the receiver. + v1 = x + if out := f(&v1, &x, &v1); out != &v1 || v1 != v { + return false + } + // Test aliasing both arguments and the receiver. + v1 = x + if out := f(&v1, &v1, &v1); out != &v1 || v1 != v { + return false + } + + // Ensure the arguments were not modified. + return x == x1 && y == y1 + } +} + +// TestAliasing checks that receivers and arguments can alias each other without +// leading to incorrect results. That is, it ensures that it's safe to write +// +// v.Invert(v) +// +// or +// +// v.Add(v, v) +// +// without any of the inputs getting clobbered by the output being written. +func TestAliasing(t *testing.T) { + type target struct { + name string + oneArgF func(v, x *Element) *Element + twoArgsF func(v, x, y *Element) *Element + } + for _, tt := range []target{ + {name: "Absolute", oneArgF: (*Element).Absolute}, + {name: "Invert", oneArgF: (*Element).Invert}, + {name: "Negate", oneArgF: (*Element).Negate}, + {name: "Set", oneArgF: (*Element).Set}, + {name: "Square", oneArgF: (*Element).Square}, + {name: "Multiply", twoArgsF: (*Element).Multiply}, + {name: "Add", twoArgsF: (*Element).Add}, + {name: "Subtract", twoArgsF: (*Element).Subtract}, + { + name: "Select0", + twoArgsF: func(v, x, y *Element) *Element { + return (*Element).Select(v, x, y, 0) + }, + }, + { + name: "Select1", + twoArgsF: func(v, x, y *Element) *Element { + return (*Element).Select(v, x, y, 1) + }, + }, + } { + var err error + switch { + case tt.oneArgF != nil: + err = quick.Check(checkAliasingOneArg(tt.oneArgF), &quick.Config{MaxCountScale: 1 << 8}) + case tt.twoArgsF != nil: + err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), &quick.Config{MaxCountScale: 1 << 8}) + } + if err != nil { + t.Errorf("%v: %v", tt.name, err) + } + } +} diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go new file mode 100644 index 0000000..8fe5839 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go @@ -0,0 +1,14 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +//go:build amd64 && gc && !purego +// +build amd64,gc,!purego + +package field + +// feMul sets out = a * b. It works like feMulGeneric. +//go:noescape +func feMul(out *Element, a *Element, b *Element) + +// feSquare sets out = a * a. It works like feSquareGeneric. +//go:noescape +func feSquare(out *Element, a *Element) diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.s b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.s new file mode 100644 index 0000000..0aa1e86 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.s @@ -0,0 +1,378 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +// +build amd64,gc,!purego + +#include "textflag.h" + +// func feMul(out *Element, a *Element, b *Element) +TEXT ·feMul(SB), NOSPLIT, $0-24 + MOVQ a+8(FP), CX + MOVQ b+16(FP), BX + + // r0 = a0×b0 + MOVQ (CX), AX + MULQ (BX) + MOVQ AX, DI + MOVQ DX, SI + + // r0 += 19×a1×b4 + MOVQ 8(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a2×b3 + MOVQ 16(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a3×b2 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 16(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a4×b1 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 8(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r1 = a0×b1 + MOVQ (CX), AX + MULQ 8(BX) + MOVQ AX, R9 + MOVQ DX, R8 + + // r1 += a1×b0 + MOVQ 8(CX), AX + MULQ (BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a2×b4 + MOVQ 16(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a3×b3 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a4×b2 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 16(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r2 = a0×b2 + MOVQ (CX), AX + MULQ 16(BX) + MOVQ AX, R11 + MOVQ DX, R10 + + // r2 += a1×b1 + MOVQ 8(CX), AX + MULQ 8(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += a2×b0 + MOVQ 16(CX), AX + MULQ (BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += 19×a3×b4 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += 19×a4×b3 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r3 = a0×b3 + MOVQ (CX), AX + MULQ 24(BX) + MOVQ AX, R13 + MOVQ DX, R12 + + // r3 += a1×b2 + MOVQ 8(CX), AX + MULQ 16(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += a2×b1 + MOVQ 16(CX), AX + MULQ 8(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += a3×b0 + MOVQ 24(CX), AX + MULQ (BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += 19×a4×b4 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r4 = a0×b4 + MOVQ (CX), AX + MULQ 32(BX) + MOVQ AX, R15 + MOVQ DX, R14 + + // r4 += a1×b3 + MOVQ 8(CX), AX + MULQ 24(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a2×b2 + MOVQ 16(CX), AX + MULQ 16(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a3×b1 + MOVQ 24(CX), AX + MULQ 8(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a4×b0 + MOVQ 32(CX), AX + MULQ (BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // First reduction chain + MOVQ $0x0007ffffffffffff, AX + SHLQ $0x0d, DI, SI + SHLQ $0x0d, R9, R8 + SHLQ $0x0d, R11, R10 + SHLQ $0x0d, R13, R12 + SHLQ $0x0d, R15, R14 + ANDQ AX, DI + IMUL3Q $0x13, R14, R14 + ADDQ R14, DI + ANDQ AX, R9 + ADDQ SI, R9 + ANDQ AX, R11 + ADDQ R8, R11 + ANDQ AX, R13 + ADDQ R10, R13 + ANDQ AX, R15 + ADDQ R12, R15 + + // Second reduction chain (carryPropagate) + MOVQ DI, SI + SHRQ $0x33, SI + MOVQ R9, R8 + SHRQ $0x33, R8 + MOVQ R11, R10 + SHRQ $0x33, R10 + MOVQ R13, R12 + SHRQ $0x33, R12 + MOVQ R15, R14 + SHRQ $0x33, R14 + ANDQ AX, DI + IMUL3Q $0x13, R14, R14 + ADDQ R14, DI + ANDQ AX, R9 + ADDQ SI, R9 + ANDQ AX, R11 + ADDQ R8, R11 + ANDQ AX, R13 + ADDQ R10, R13 + ANDQ AX, R15 + ADDQ R12, R15 + + // Store output + MOVQ out+0(FP), AX + MOVQ DI, (AX) + MOVQ R9, 8(AX) + MOVQ R11, 16(AX) + MOVQ R13, 24(AX) + MOVQ R15, 32(AX) + RET + +// func feSquare(out *Element, a *Element) +TEXT ·feSquare(SB), NOSPLIT, $0-16 + MOVQ a+8(FP), CX + + // r0 = l0×l0 + MOVQ (CX), AX + MULQ (CX) + MOVQ AX, SI + MOVQ DX, BX + + // r0 += 38×l1×l4 + MOVQ 8(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, SI + ADCQ DX, BX + + // r0 += 38×l2×l3 + MOVQ 16(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 24(CX) + ADDQ AX, SI + ADCQ DX, BX + + // r1 = 2×l0×l1 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 8(CX) + MOVQ AX, R8 + MOVQ DX, DI + + // r1 += 38×l2×l4 + MOVQ 16(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, R8 + ADCQ DX, DI + + // r1 += 19×l3×l3 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(CX) + ADDQ AX, R8 + ADCQ DX, DI + + // r2 = 2×l0×l2 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 16(CX) + MOVQ AX, R10 + MOVQ DX, R9 + + // r2 += l1×l1 + MOVQ 8(CX), AX + MULQ 8(CX) + ADDQ AX, R10 + ADCQ DX, R9 + + // r2 += 38×l3×l4 + MOVQ 24(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, R10 + ADCQ DX, R9 + + // r3 = 2×l0×l3 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 24(CX) + MOVQ AX, R12 + MOVQ DX, R11 + + // r3 += 2×l1×l2 + MOVQ 8(CX), AX + IMUL3Q $0x02, AX, AX + MULQ 16(CX) + ADDQ AX, R12 + ADCQ DX, R11 + + // r3 += 19×l4×l4 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(CX) + ADDQ AX, R12 + ADCQ DX, R11 + + // r4 = 2×l0×l4 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 32(CX) + MOVQ AX, R14 + MOVQ DX, R13 + + // r4 += 2×l1×l3 + MOVQ 8(CX), AX + IMUL3Q $0x02, AX, AX + MULQ 24(CX) + ADDQ AX, R14 + ADCQ DX, R13 + + // r4 += l2×l2 + MOVQ 16(CX), AX + MULQ 16(CX) + ADDQ AX, R14 + ADCQ DX, R13 + + // First reduction chain + MOVQ $0x0007ffffffffffff, AX + SHLQ $0x0d, SI, BX + SHLQ $0x0d, R8, DI + SHLQ $0x0d, R10, R9 + SHLQ $0x0d, R12, R11 + SHLQ $0x0d, R14, R13 + ANDQ AX, SI + IMUL3Q $0x13, R13, R13 + ADDQ R13, SI + ANDQ AX, R8 + ADDQ BX, R8 + ANDQ AX, R10 + ADDQ DI, R10 + ANDQ AX, R12 + ADDQ R9, R12 + ANDQ AX, R14 + ADDQ R11, R14 + + // Second reduction chain (carryPropagate) + MOVQ SI, BX + SHRQ $0x33, BX + MOVQ R8, DI + SHRQ $0x33, DI + MOVQ R10, R9 + SHRQ $0x33, R9 + MOVQ R12, R11 + SHRQ $0x33, R11 + MOVQ R14, R13 + SHRQ $0x33, R13 + ANDQ AX, SI + IMUL3Q $0x13, R13, R13 + ADDQ R13, SI + ANDQ AX, R8 + ADDQ BX, R8 + ANDQ AX, R10 + ADDQ DI, R10 + ANDQ AX, R12 + ADDQ R9, R12 + ANDQ AX, R14 + ADDQ R11, R14 + + // Store output + MOVQ out+0(FP), AX + MOVQ SI, (AX) + MOVQ R8, 8(AX) + MOVQ R10, 16(AX) + MOVQ R12, 24(AX) + MOVQ R14, 32(AX) + RET diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go new file mode 100644 index 0000000..ddb6c9b --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go @@ -0,0 +1,12 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 || !gc || purego +// +build !amd64 !gc purego + +package field + +func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } + +func feSquare(v, x *Element) { feSquareGeneric(v, x) } diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.go b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.go new file mode 100644 index 0000000..af459ef --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.go @@ -0,0 +1,16 @@ +// Copyright (c) 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build arm64 && gc && !purego +// +build arm64,gc,!purego + +package field + +//go:noescape +func carryPropagate(v *Element) + +func (v *Element) carryPropagate() *Element { + carryPropagate(v) + return v +} diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.s b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.s new file mode 100644 index 0000000..751ab2a --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.s @@ -0,0 +1,42 @@ +// Copyright (c) 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build arm64,gc,!purego + +#include "textflag.h" + +// carryPropagate works exactly like carryPropagateGeneric and uses the +// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but +// avoids loading R0-R4 twice and uses LDP and STP. +// +// See https://golang.org/issues/43145 for the main compiler issue. +// +// func carryPropagate(v *Element) +TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 + MOVD v+0(FP), R20 + + LDP 0(R20), (R0, R1) + LDP 16(R20), (R2, R3) + MOVD 32(R20), R4 + + AND $0x7ffffffffffff, R0, R10 + AND $0x7ffffffffffff, R1, R11 + AND $0x7ffffffffffff, R2, R12 + AND $0x7ffffffffffff, R3, R13 + AND $0x7ffffffffffff, R4, R14 + + ADD R0>>51, R11, R11 + ADD R1>>51, R12, R12 + ADD R2>>51, R13, R13 + ADD R3>>51, R14, R14 + // R4>>51 * 19 + R10 -> R10 + LSR $51, R4, R21 + MOVD $19, R22 + MADD R22, R10, R21, R10 + + STP (R10, R11), 0(R20) + STP (R12, R13), 16(R20) + MOVD R14, 32(R20) + + RET diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go new file mode 100644 index 0000000..234a5b2 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go @@ -0,0 +1,12 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !arm64 || !gc || purego +// +build !arm64 !gc purego + +package field + +func (v *Element) carryPropagate() *Element { + return v.carryPropagateGeneric() +} diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go b/src/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go new file mode 100644 index 0000000..77dc06c --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go @@ -0,0 +1,36 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import "testing" + +func BenchmarkAdd(b *testing.B) { + var x, y Element + x.One() + y.Add(feOne, feOne) + b.ResetTimer() + for i := 0; i < b.N; i++ { + x.Add(&x, &y) + } +} + +func BenchmarkMultiply(b *testing.B) { + var x, y Element + x.One() + y.Add(feOne, feOne) + b.ResetTimer() + for i := 0; i < b.N; i++ { + x.Multiply(&x, &y) + } +} + +func BenchmarkMult32(b *testing.B) { + var x Element + x.One() + b.ResetTimer() + for i := 0; i < b.N; i++ { + x.Mult32(&x, 0xaa42aa42) + } +} diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_generic.go b/src/crypto/ed25519/internal/edwards25519/field/fe_generic.go new file mode 100644 index 0000000..bccf851 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_generic.go @@ -0,0 +1,264 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import "math/bits" + +// uint128 holds a 128-bit number as two 64-bit limbs, for use with the +// bits.Mul64 and bits.Add64 intrinsics. +type uint128 struct { + lo, hi uint64 +} + +// mul64 returns a * b. +func mul64(a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + return uint128{lo, hi} +} + +// addMul64 returns v + a * b. +func addMul64(v uint128, a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + lo, c := bits.Add64(lo, v.lo, 0) + hi, _ = bits.Add64(hi, v.hi, c) + return uint128{lo, hi} +} + +// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. +func shiftRightBy51(a uint128) uint64 { + return (a.hi << (64 - 51)) | (a.lo >> 51) +} + +func feMulGeneric(v, a, b *Element) { + a0 := a.l0 + a1 := a.l1 + a2 := a.l2 + a3 := a.l3 + a4 := a.l4 + + b0 := b.l0 + b1 := b.l1 + b2 := b.l2 + b3 := b.l3 + b4 := b.l4 + + // Limb multiplication works like pen-and-paper columnar multiplication, but + // with 51-bit limbs instead of digits. + // + // a4 a3 a2 a1 a0 x + // b4 b3 b2 b1 b0 = + // ------------------------ + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a4b1 a3b1 a2b1 a1b1 a0b1 + + // a4b2 a3b2 a2b2 a1b2 a0b2 + + // a4b3 a3b3 a2b3 a1b3 a0b3 + + // a4b4 a3b4 a2b4 a1b4 a0b4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to + // reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5, + // r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc. + // + // Reduction can be carried out simultaneously to multiplication. For + // example, we do not compute r5: whenever the result of a multiplication + // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. + // + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a3b1 a2b1 a1b1 a0b1 19×a4b1 + + // a2b2 a1b2 a0b2 19×a4b2 19×a3b2 + + // a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 + + // a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // Finally we add up the columns into wide, overlapping limbs. + + a1_19 := a1 * 19 + a2_19 := a2 * 19 + a3_19 := a3 * 19 + a4_19 := a4 * 19 + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + r0 := mul64(a0, b0) + r0 = addMul64(r0, a1_19, b4) + r0 = addMul64(r0, a2_19, b3) + r0 = addMul64(r0, a3_19, b2) + r0 = addMul64(r0, a4_19, b1) + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + r1 := mul64(a0, b1) + r1 = addMul64(r1, a1, b0) + r1 = addMul64(r1, a2_19, b4) + r1 = addMul64(r1, a3_19, b3) + r1 = addMul64(r1, a4_19, b2) + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + r2 := mul64(a0, b2) + r2 = addMul64(r2, a1, b1) + r2 = addMul64(r2, a2, b0) + r2 = addMul64(r2, a3_19, b4) + r2 = addMul64(r2, a4_19, b3) + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + r3 := mul64(a0, b3) + r3 = addMul64(r3, a1, b2) + r3 = addMul64(r3, a2, b1) + r3 = addMul64(r3, a3, b0) + r3 = addMul64(r3, a4_19, b4) + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + r4 := mul64(a0, b4) + r4 = addMul64(r4, a1, b3) + r4 = addMul64(r4, a2, b2) + r4 = addMul64(r4, a3, b1) + r4 = addMul64(r4, a4, b0) + + // After the multiplication, we need to reduce (carry) the five coefficients + // to obtain a result with limbs that are at most slightly larger than 2⁵¹, + // to respect the Element invariant. + // + // Overall, the reduction works the same as carryPropagate, except with + // wider inputs: we take the carry for each coefficient by shifting it right + // by 51, and add it to the limb above it. The top carry is multiplied by 19 + // according to the reduction identity and added to the lowest limb. + // + // The largest coefficient (r0) will be at most 111 bits, which guarantees + // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. + // + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + // r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²) + // r0 < (1 + 19 × 4) × 2⁵² × 2⁵² + // r0 < 2⁷ × 2⁵² × 2⁵² + // r0 < 2¹¹¹ + // + // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most + // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and + // allows us to easily apply the reduction identity. + // + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + // r4 < 5 × 2⁵² × 2⁵² + // r4 < 2¹⁰⁷ + // + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + // Now all coefficients fit into 64-bit registers but are still too large to + // be passed around as a Element. We therefore do one last carry chain, + // where the carries will be small enough to fit in the wiggle room above 2⁵¹. + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +func feSquareGeneric(v, a *Element) { + l0 := a.l0 + l1 := a.l1 + l2 := a.l2 + l3 := a.l3 + l4 := a.l4 + + // Squaring works precisely like multiplication above, but thanks to its + // symmetry we get to group a few terms together. + // + // l4 l3 l2 l1 l0 x + // l4 l3 l2 l1 l0 = + // ------------------------ + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l4l1 l3l1 l2l1 l1l1 l0l1 + + // l4l2 l3l2 l2l2 l1l2 l0l2 + + // l4l3 l3l3 l2l3 l1l3 l0l3 + + // l4l4 l3l4 l2l4 l1l4 l0l4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l3l1 l2l1 l1l1 l0l1 19×l4l1 + + // l2l2 l1l2 l0l2 19×l4l2 19×l3l2 + + // l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 + + // l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with + // only three Mul64 and four Add64, instead of five and eight. + + l0_2 := l0 * 2 + l1_2 := l1 * 2 + + l1_38 := l1 * 38 + l2_38 := l2 * 38 + l3_38 := l3 * 38 + + l3_19 := l3 * 19 + l4_19 := l4 * 19 + + // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3) + r0 := mul64(l0, l0) + r0 = addMul64(r0, l1_38, l4) + r0 = addMul64(r0, l2_38, l3) + + // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 + r1 := mul64(l0_2, l1) + r1 = addMul64(r1, l2_38, l4) + r1 = addMul64(r1, l3_19, l3) + + // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4 + r2 := mul64(l0_2, l2) + r2 = addMul64(r2, l1, l1) + r2 = addMul64(r2, l3_38, l4) + + // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 + r3 := mul64(l0_2, l3) + r3 = addMul64(r3, l1_2, l2) + r3 = addMul64(r3, l4_19, l4) + + // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2 + r4 := mul64(l0_2, l4) + r4 = addMul64(r4, l1_2, l3) + r4 = addMul64(r4, l2, l2) + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +// carryPropagate brings the limbs below 52 bits by applying the reduction +// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. +func (v *Element) carryPropagateGeneric() *Element { + c0 := v.l0 >> 51 + c1 := v.l1 >> 51 + c2 := v.l2 >> 51 + c3 := v.l3 >> 51 + c4 := v.l4 >> 51 + + v.l0 = v.l0&maskLow51Bits + c4*19 + v.l1 = v.l1&maskLow51Bits + c0 + v.l2 = v.l2&maskLow51Bits + c1 + v.l3 = v.l3&maskLow51Bits + c2 + v.l4 = v.l4&maskLow51Bits + c3 + + return v +} diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_test.go b/src/crypto/ed25519/internal/edwards25519/field/fe_test.go new file mode 100644 index 0000000..b484459 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_test.go @@ -0,0 +1,558 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "io" + "math/big" + "math/bits" + mathrand "math/rand" + "reflect" + "testing" + "testing/quick" +) + +func (v Element) String() string { + return hex.EncodeToString(v.Bytes()) +} + +// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks) +// times. The default value of -quickchecks is 100. +var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10} + +func generateFieldElement(rand *mathrand.Rand) Element { + const maskLow52Bits = (1 << 52) - 1 + return Element{ + rand.Uint64() & maskLow52Bits, + rand.Uint64() & maskLow52Bits, + rand.Uint64() & maskLow52Bits, + rand.Uint64() & maskLow52Bits, + rand.Uint64() & maskLow52Bits, + } +} + +// weirdLimbs can be combined to generate a range of edge-case field elements. +// 0 and -1 are intentionally more weighted, as they combine well. +var ( + weirdLimbs51 = []uint64{ + 0, 0, 0, 0, + 1, + 19 - 1, + 19, + 0x2aaaaaaaaaaaa, + 0x5555555555555, + (1 << 51) - 20, + (1 << 51) - 19, + (1 << 51) - 1, (1 << 51) - 1, + (1 << 51) - 1, (1 << 51) - 1, + } + weirdLimbs52 = []uint64{ + 0, 0, 0, 0, 0, 0, + 1, + 19 - 1, + 19, + 0x2aaaaaaaaaaaa, + 0x5555555555555, + (1 << 51) - 20, + (1 << 51) - 19, + (1 << 51) - 1, (1 << 51) - 1, + (1 << 51) - 1, (1 << 51) - 1, + (1 << 51) - 1, (1 << 51) - 1, + 1 << 51, + (1 << 51) + 1, + (1 << 52) - 19, + (1 << 52) - 1, + } +) + +func generateWeirdFieldElement(rand *mathrand.Rand) Element { + return Element{ + weirdLimbs52[rand.Intn(len(weirdLimbs52))], + weirdLimbs51[rand.Intn(len(weirdLimbs51))], + weirdLimbs51[rand.Intn(len(weirdLimbs51))], + weirdLimbs51[rand.Intn(len(weirdLimbs51))], + weirdLimbs51[rand.Intn(len(weirdLimbs51))], + } +} + +func (Element) Generate(rand *mathrand.Rand, size int) reflect.Value { + if rand.Intn(2) == 0 { + return reflect.ValueOf(generateWeirdFieldElement(rand)) + } + return reflect.ValueOf(generateFieldElement(rand)) +} + +// isInBounds returns whether the element is within the expected bit size bounds +// after a light reduction. +func isInBounds(x *Element) bool { + return bits.Len64(x.l0) <= 52 && + bits.Len64(x.l1) <= 52 && + bits.Len64(x.l2) <= 52 && + bits.Len64(x.l3) <= 52 && + bits.Len64(x.l4) <= 52 +} + +func TestMultiplyDistributesOverAdd(t *testing.T) { + multiplyDistributesOverAdd := func(x, y, z Element) bool { + // Compute t1 = (x+y)*z + t1 := new(Element) + t1.Add(&x, &y) + t1.Multiply(t1, &z) + + // Compute t2 = x*z + y*z + t2 := new(Element) + t3 := new(Element) + t2.Multiply(&x, &z) + t3.Multiply(&y, &z) + t2.Add(t2, t3) + + return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) + } + + if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestMul64to128(t *testing.T) { + a := uint64(5) + b := uint64(5) + r := mul64(a, b) + if r.lo != 0x19 || r.hi != 0 { + t.Errorf("lo-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) + } + + a = uint64(18014398509481983) // 2^54 - 1 + b = uint64(18014398509481983) // 2^54 - 1 + r = mul64(a, b) + if r.lo != 0xff80000000000001 || r.hi != 0xfffffffffff { + t.Errorf("hi-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) + } + + a = uint64(1125899906842661) + b = uint64(2097155) + r = mul64(a, b) + r = addMul64(r, a, b) + r = addMul64(r, a, b) + r = addMul64(r, a, b) + r = addMul64(r, a, b) + if r.lo != 16888498990613035 || r.hi != 640 { + t.Errorf("wrong answer: %d + %d*(2**64)", r.lo, r.hi) + } +} + +func TestSetBytesRoundTrip(t *testing.T) { + f1 := func(in [32]byte, fe Element) bool { + fe.SetBytes(in[:]) + + // Mask the most significant bit as it's ignored by SetBytes. (Now + // instead of earlier so we check the masking in SetBytes is working.) + in[len(in)-1] &= (1 << 7) - 1 + + return bytes.Equal(in[:], fe.Bytes()) && isInBounds(&fe) + } + if err := quick.Check(f1, nil); err != nil { + t.Errorf("failed bytes->FE->bytes round-trip: %v", err) + } + + f2 := func(fe, r Element) bool { + r.SetBytes(fe.Bytes()) + + // Intentionally not using Equal not to go through Bytes again. + // Calling reduce because both Generate and SetBytes can produce + // non-canonical representations. + fe.reduce() + r.reduce() + return fe == r + } + if err := quick.Check(f2, nil); err != nil { + t.Errorf("failed FE->bytes->FE round-trip: %v", err) + } + + // Check some fixed vectors from dalek + type feRTTest struct { + fe Element + b []byte + } + var tests = []feRTTest{ + { + fe: Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}, + b: []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31}, + }, + { + fe: Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}, + b: []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122}, + }, + } + + for _, tt := range tests { + b := tt.fe.Bytes() + if !bytes.Equal(b, tt.b) || new(Element).SetBytes(tt.b).Equal(&tt.fe) != 1 { + t.Errorf("Failed fixed roundtrip: %v", tt) + } + } +} + +func swapEndianness(buf []byte) []byte { + for i := 0; i < len(buf)/2; i++ { + buf[i], buf[len(buf)-i-1] = buf[len(buf)-i-1], buf[i] + } + return buf +} + +func TestBytesBigEquivalence(t *testing.T) { + f1 := func(in [32]byte, fe, fe1 Element) bool { + fe.SetBytes(in[:]) + + in[len(in)-1] &= (1 << 7) - 1 // mask the most significant bit + b := new(big.Int).SetBytes(swapEndianness(in[:])) + fe1.fromBig(b) + + if fe != fe1 { + return false + } + + buf := make([]byte, 32) // pad with zeroes + copy(buf, swapEndianness(fe1.toBig().Bytes())) + + return bytes.Equal(fe.Bytes(), buf) && isInBounds(&fe) && isInBounds(&fe1) + } + if err := quick.Check(f1, nil); err != nil { + t.Error(err) + } +} + +// fromBig sets v = n, and returns v. The bit length of n must not exceed 256. +func (v *Element) fromBig(n *big.Int) *Element { + if n.BitLen() > 32*8 { + panic("edwards25519: invalid field element input size") + } + + buf := make([]byte, 0, 32) + for _, word := range n.Bits() { + for i := 0; i < bits.UintSize; i += 8 { + if len(buf) >= cap(buf) { + break + } + buf = append(buf, byte(word)) + word >>= 8 + } + } + + return v.SetBytes(buf[:32]) +} + +func (v *Element) fromDecimal(s string) *Element { + n, ok := new(big.Int).SetString(s, 10) + if !ok { + panic("not a valid decimal: " + s) + } + return v.fromBig(n) +} + +// toBig returns v as a big.Int. +func (v *Element) toBig() *big.Int { + buf := v.Bytes() + + words := make([]big.Word, 32*8/bits.UintSize) + for n := range words { + for i := 0; i < bits.UintSize; i += 8 { + if len(buf) == 0 { + break + } + words[n] |= big.Word(buf[0]) << big.Word(i) + buf = buf[1:] + } + } + + return new(big.Int).SetBits(words) +} + +func TestDecimalConstants(t *testing.T) { + sqrtM1String := "19681161376707505956807079304988542015446066515923890162744021073123829784752" + if exp := new(Element).fromDecimal(sqrtM1String); sqrtM1.Equal(exp) != 1 { + t.Errorf("sqrtM1 is %v, expected %v", sqrtM1, exp) + } + // d is in the parent package, and we don't want to expose d or fromDecimal. + // dString := "37095705934669439343138083508754565189542113879843219016388785533085940283555" + // if exp := new(Element).fromDecimal(dString); d.Equal(exp) != 1 { + // t.Errorf("d is %v, expected %v", d, exp) + // } +} + +func TestSetBytesRoundTripEdgeCases(t *testing.T) { + // TODO: values close to 0, close to 2^255-19, between 2^255-19 and 2^255-1, + // and between 2^255 and 2^256-1. Test both the documented SetBytes + // behavior, and that Bytes reduces them. +} + +// Tests self-consistency between Multiply and Square. +func TestConsistency(t *testing.T) { + var x Element + var x2, x2sq Element + + x = Element{1, 1, 1, 1, 1} + x2.Multiply(&x, &x) + x2sq.Square(&x) + + if x2 != x2sq { + t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) + } + + var bytes [32]byte + + _, err := io.ReadFull(rand.Reader, bytes[:]) + if err != nil { + t.Fatal(err) + } + x.SetBytes(bytes[:]) + + x2.Multiply(&x, &x) + x2sq.Square(&x) + + if x2 != x2sq { + t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) + } +} + +func TestEqual(t *testing.T) { + x := Element{1, 1, 1, 1, 1} + y := Element{5, 4, 3, 2, 1} + + eq := x.Equal(&x) + if eq != 1 { + t.Errorf("wrong about equality") + } + + eq = x.Equal(&y) + if eq != 0 { + t.Errorf("wrong about inequality") + } +} + +func TestInvert(t *testing.T) { + x := Element{1, 1, 1, 1, 1} + one := Element{1, 0, 0, 0, 0} + var xinv, r Element + + xinv.Invert(&x) + r.Multiply(&x, &xinv) + r.reduce() + + if one != r { + t.Errorf("inversion identity failed, got: %x", r) + } + + var bytes [32]byte + + _, err := io.ReadFull(rand.Reader, bytes[:]) + if err != nil { + t.Fatal(err) + } + x.SetBytes(bytes[:]) + + xinv.Invert(&x) + r.Multiply(&x, &xinv) + r.reduce() + + if one != r { + t.Errorf("random inversion identity failed, got: %x for field element %x", r, x) + } + + zero := Element{} + x.Set(&zero) + if xx := xinv.Invert(&x); xx != &xinv { + t.Errorf("inverting zero did not return the receiver") + } else if xinv.Equal(&zero) != 1 { + t.Errorf("inverting zero did not return zero") + } +} + +func TestSelectSwap(t *testing.T) { + a := Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676} + b := Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972} + + var c, d Element + + c.Select(&a, &b, 1) + d.Select(&a, &b, 0) + + if c.Equal(&a) != 1 || d.Equal(&b) != 1 { + t.Errorf("Select failed") + } + + c.Swap(&d, 0) + + if c.Equal(&a) != 1 || d.Equal(&b) != 1 { + t.Errorf("Swap failed") + } + + c.Swap(&d, 1) + + if c.Equal(&b) != 1 || d.Equal(&a) != 1 { + t.Errorf("Swap failed") + } +} + +func TestMult32(t *testing.T) { + mult32EquivalentToMul := func(x Element, y uint32) bool { + t1 := new(Element) + for i := 0; i < 100; i++ { + t1.Mult32(&x, y) + } + + ty := new(Element) + ty.l0 = uint64(y) + + t2 := new(Element) + for i := 0; i < 100; i++ { + t2.Multiply(&x, ty) + } + + return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) + } + + if err := quick.Check(mult32EquivalentToMul, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestSqrtRatio(t *testing.T) { + // From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4. + type test struct { + u, v string + wasSquare int + r string + } + var tests = []test{ + // If u is 0, the function is defined to return (0, TRUE), even if v + // is zero. Note that where used in this package, the denominator v + // is never zero. + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + 1, "0000000000000000000000000000000000000000000000000000000000000000", + }, + // 0/1 == 0² + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + 1, "0000000000000000000000000000000000000000000000000000000000000000", + }, + // If u is non-zero and v is zero, defined to return (0, FALSE). + { + "0100000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + 0, "0000000000000000000000000000000000000000000000000000000000000000", + }, + // 2/1 is not square in this field. + { + "0200000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + 0, "3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54", + }, + // 4/1 == 2² + { + "0400000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + 1, "0200000000000000000000000000000000000000000000000000000000000000", + }, + // 1/4 == (2⁻¹)² == (2^(p-2))² per Euler's theorem + { + "0100000000000000000000000000000000000000000000000000000000000000", + "0400000000000000000000000000000000000000000000000000000000000000", + 1, "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f", + }, + } + + for i, tt := range tests { + u := new(Element).SetBytes(decodeHex(tt.u)) + v := new(Element).SetBytes(decodeHex(tt.v)) + want := new(Element).SetBytes(decodeHex(tt.r)) + got, wasSquare := new(Element).SqrtRatio(u, v) + if got.Equal(want) == 0 || wasSquare != tt.wasSquare { + t.Errorf("%d: got (%v, %v), want (%v, %v)", i, got, wasSquare, want, tt.wasSquare) + } + } +} + +func TestCarryPropagate(t *testing.T) { + asmLikeGeneric := func(a [5]uint64) bool { + t1 := &Element{a[0], a[1], a[2], a[3], a[4]} + t2 := &Element{a[0], a[1], a[2], a[3], a[4]} + + t1.carryPropagate() + t2.carryPropagateGeneric() + + if *t1 != *t2 { + t.Logf("got: %#v,\nexpected: %#v", t1, t2) + } + + return *t1 == *t2 && isInBounds(t2) + } + + if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { + t.Error(err) + } + + if !asmLikeGeneric([5]uint64{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}) { + t.Errorf("failed for {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}") + } +} + +func TestFeSquare(t *testing.T) { + asmLikeGeneric := func(a Element) bool { + t1 := a + t2 := a + + feSquareGeneric(&t1, &t1) + feSquare(&t2, &t2) + + if t1 != t2 { + t.Logf("got: %#v,\nexpected: %#v", t1, t2) + } + + return t1 == t2 && isInBounds(&t2) + } + + if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestFeMul(t *testing.T) { + asmLikeGeneric := func(a, b Element) bool { + a1 := a + a2 := a + b1 := b + b2 := b + + feMulGeneric(&a1, &a1, &b1) + feMul(&a2, &a2, &b2) + + if a1 != a2 || b1 != b2 { + t.Logf("got: %#v,\nexpected: %#v", a1, a2) + t.Logf("got: %#v,\nexpected: %#v", b1, b2) + } + + return a1 == a2 && isInBounds(&a2) && + b1 == b2 && isInBounds(&b2) + } + + if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func decodeHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} diff --git a/src/crypto/ed25519/internal/edwards25519/scalar.go b/src/crypto/ed25519/internal/edwards25519/scalar.go new file mode 100644 index 0000000..889acaa --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/scalar.go @@ -0,0 +1,1025 @@ +// Copyright (c) 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "crypto/subtle" + "encoding/binary" + "errors" +) + +// A Scalar is an integer modulo +// +// l = 2^252 + 27742317777372353535851937790883648493 +// +// which is the prime order of the edwards25519 group. +// +// This type works similarly to math/big.Int, and all arguments and +// receivers are allowed to alias. +// +// The zero value is a valid zero element. +type Scalar struct { + // s is the Scalar value in little-endian. The value is always reduced + // between operations. + s [32]byte +} + +var ( + scZero = Scalar{[32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} + + scOne = Scalar{[32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} + + scMinusOne = Scalar{[32]byte{236, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}} +) + +// NewScalar returns a new zero Scalar. +func NewScalar() *Scalar { + return &Scalar{} +} + +// MultiplyAdd sets s = x * y + z mod l, and returns s. +func (s *Scalar) MultiplyAdd(x, y, z *Scalar) *Scalar { + scMulAdd(&s.s, &x.s, &y.s, &z.s) + return s +} + +// Add sets s = x + y mod l, and returns s. +func (s *Scalar) Add(x, y *Scalar) *Scalar { + // s = 1 * x + y mod l + scMulAdd(&s.s, &scOne.s, &x.s, &y.s) + return s +} + +// Subtract sets s = x - y mod l, and returns s. +func (s *Scalar) Subtract(x, y *Scalar) *Scalar { + // s = -1 * y + x mod l + scMulAdd(&s.s, &scMinusOne.s, &y.s, &x.s) + return s +} + +// Negate sets s = -x mod l, and returns s. +func (s *Scalar) Negate(x *Scalar) *Scalar { + // s = -1 * x + 0 mod l + scMulAdd(&s.s, &scMinusOne.s, &x.s, &scZero.s) + return s +} + +// Multiply sets s = x * y mod l, and returns s. +func (s *Scalar) Multiply(x, y *Scalar) *Scalar { + // s = x * y + 0 mod l + scMulAdd(&s.s, &x.s, &y.s, &scZero.s) + return s +} + +// Set sets s = x, and returns s. +func (s *Scalar) Set(x *Scalar) *Scalar { + *s = *x + return s +} + +// SetUniformBytes sets s to an uniformly distributed value given 64 uniformly +// distributed random bytes. +func (s *Scalar) SetUniformBytes(x []byte) *Scalar { + if len(x) != 64 { + panic("edwards25519: invalid SetUniformBytes input length") + } + var wideBytes [64]byte + copy(wideBytes[:], x[:]) + scReduce(&s.s, &wideBytes) + return s +} + +// SetCanonicalBytes sets s = x, where x is a 32-byte little-endian encoding of +// s, and returns s. If x is not a canonical encoding of s, SetCanonicalBytes +// returns nil and an error, and the receiver is unchanged. +func (s *Scalar) SetCanonicalBytes(x []byte) (*Scalar, error) { + if len(x) != 32 { + return nil, errors.New("invalid scalar length") + } + ss := &Scalar{} + copy(ss.s[:], x) + if !isReduced(ss) { + return nil, errors.New("invalid scalar encoding") + } + s.s = ss.s + return s, nil +} + +// isReduced returns whether the given scalar is reduced modulo l. +func isReduced(s *Scalar) bool { + for i := len(s.s) - 1; i >= 0; i-- { + switch { + case s.s[i] > scMinusOne.s[i]: + return false + case s.s[i] < scMinusOne.s[i]: + return true + } + } + return true +} + +// SetBytesWithClamping applies the buffer pruning described in RFC 8032, +// Section 5.1.5 (also known as clamping) and sets s to the result. The input +// must be 32 bytes, and it is not modified. +// +// Note that since Scalar values are always reduced modulo the prime order of +// the curve, the resulting value will not preserve any of the cofactor-clearing +// properties that clamping is meant to provide. It will however work as +// expected as long as it is applied to points on the prime order subgroup, like +// in Ed25519. In fact, it is lost to history why RFC 8032 adopted the +// irrelevant RFC 7748 clamping, but it is now required for compatibility. +func (s *Scalar) SetBytesWithClamping(x []byte) *Scalar { + // The description above omits the purpose of the high bits of the clamping + // for brevity, but those are also lost to reductions, and are also + // irrelevant to edwards25519 as they protect against a specific + // implementation bug that was once observed in a generic Montgomery ladder. + if len(x) != 32 { + panic("edwards25519: invalid SetBytesWithClamping input length") + } + var wideBytes [64]byte + copy(wideBytes[:], x[:]) + wideBytes[0] &= 248 + wideBytes[31] &= 63 + wideBytes[31] |= 64 + scReduce(&s.s, &wideBytes) + return s +} + +// Bytes returns the canonical 32-byte little-endian encoding of s. +func (s *Scalar) Bytes() []byte { + buf := make([]byte, 32) + copy(buf, s.s[:]) + return buf +} + +// Equal returns 1 if s and t are equal, and 0 otherwise. +func (s *Scalar) Equal(t *Scalar) int { + return subtle.ConstantTimeCompare(s.s[:], t.s[:]) +} + +// scMulAdd and scReduce are ported from the public domain, “ref10” +// implementation of ed25519 from SUPERCOP. + +func load3(in []byte) int64 { + r := int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + return r +} + +func load4(in []byte) int64 { + r := int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + r |= int64(in[3]) << 24 + return r +} + +// Input: +// a[0]+256*a[1]+...+256^31*a[31] = a +// b[0]+256*b[1]+...+256^31*b[31] = b +// c[0]+256*c[1]+...+256^31*c[31] = c +// +// Output: +// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l +// where l = 2^252 + 27742317777372353535851937790883648493. +func scMulAdd(s, a, b, c *[32]byte) { + a0 := 2097151 & load3(a[:]) + a1 := 2097151 & (load4(a[2:]) >> 5) + a2 := 2097151 & (load3(a[5:]) >> 2) + a3 := 2097151 & (load4(a[7:]) >> 7) + a4 := 2097151 & (load4(a[10:]) >> 4) + a5 := 2097151 & (load3(a[13:]) >> 1) + a6 := 2097151 & (load4(a[15:]) >> 6) + a7 := 2097151 & (load3(a[18:]) >> 3) + a8 := 2097151 & load3(a[21:]) + a9 := 2097151 & (load4(a[23:]) >> 5) + a10 := 2097151 & (load3(a[26:]) >> 2) + a11 := (load4(a[28:]) >> 7) + b0 := 2097151 & load3(b[:]) + b1 := 2097151 & (load4(b[2:]) >> 5) + b2 := 2097151 & (load3(b[5:]) >> 2) + b3 := 2097151 & (load4(b[7:]) >> 7) + b4 := 2097151 & (load4(b[10:]) >> 4) + b5 := 2097151 & (load3(b[13:]) >> 1) + b6 := 2097151 & (load4(b[15:]) >> 6) + b7 := 2097151 & (load3(b[18:]) >> 3) + b8 := 2097151 & load3(b[21:]) + b9 := 2097151 & (load4(b[23:]) >> 5) + b10 := 2097151 & (load3(b[26:]) >> 2) + b11 := (load4(b[28:]) >> 7) + c0 := 2097151 & load3(c[:]) + c1 := 2097151 & (load4(c[2:]) >> 5) + c2 := 2097151 & (load3(c[5:]) >> 2) + c3 := 2097151 & (load4(c[7:]) >> 7) + c4 := 2097151 & (load4(c[10:]) >> 4) + c5 := 2097151 & (load3(c[13:]) >> 1) + c6 := 2097151 & (load4(c[15:]) >> 6) + c7 := 2097151 & (load3(c[18:]) >> 3) + c8 := 2097151 & load3(c[21:]) + c9 := 2097151 & (load4(c[23:]) >> 5) + c10 := 2097151 & (load3(c[26:]) >> 2) + c11 := (load4(c[28:]) >> 7) + var carry [23]int64 + + s0 := c0 + a0*b0 + s1 := c1 + a0*b1 + a1*b0 + s2 := c2 + a0*b2 + a1*b1 + a2*b0 + s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0 + s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 + s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 + s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0 + s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 + s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0 + s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 + s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0 + s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0 + s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1 + s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2 + s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3 + s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4 + s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5 + s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6 + s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7 + s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8 + s20 := a9*b11 + a10*b10 + a11*b9 + s21 := a10*b11 + a11*b10 + s22 := a11 * b11 + s23 := int64(0) + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + carry[18] = (s18 + (1 << 20)) >> 21 + s19 += carry[18] + s18 -= carry[18] << 21 + carry[20] = (s20 + (1 << 20)) >> 21 + s21 += carry[20] + s20 -= carry[20] << 21 + carry[22] = (s22 + (1 << 20)) >> 21 + s23 += carry[22] + s22 -= carry[22] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + carry[17] = (s17 + (1 << 20)) >> 21 + s18 += carry[17] + s17 -= carry[17] << 21 + carry[19] = (s19 + (1 << 20)) >> 21 + s20 += carry[19] + s19 -= carry[19] << 21 + carry[21] = (s21 + (1 << 20)) >> 21 + s22 += carry[21] + s21 -= carry[21] << 21 + + s11 += s23 * 666643 + s12 += s23 * 470296 + s13 += s23 * 654183 + s14 -= s23 * 997805 + s15 += s23 * 136657 + s16 -= s23 * 683901 + s23 = 0 + + s10 += s22 * 666643 + s11 += s22 * 470296 + s12 += s22 * 654183 + s13 -= s22 * 997805 + s14 += s22 * 136657 + s15 -= s22 * 683901 + s22 = 0 + + s9 += s21 * 666643 + s10 += s21 * 470296 + s11 += s21 * 654183 + s12 -= s21 * 997805 + s13 += s21 * 136657 + s14 -= s21 * 683901 + s21 = 0 + + s8 += s20 * 666643 + s9 += s20 * 470296 + s10 += s20 * 654183 + s11 -= s20 * 997805 + s12 += s20 * 136657 + s13 -= s20 * 683901 + s20 = 0 + + s7 += s19 * 666643 + s8 += s19 * 470296 + s9 += s19 * 654183 + s10 -= s19 * 997805 + s11 += s19 * 136657 + s12 -= s19 * 683901 + s19 = 0 + + s6 += s18 * 666643 + s7 += s18 * 470296 + s8 += s18 * 654183 + s9 -= s18 * 997805 + s10 += s18 * 136657 + s11 -= s18 * 683901 + s18 = 0 + + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + + s5 += s17 * 666643 + s6 += s17 * 470296 + s7 += s17 * 654183 + s8 -= s17 * 997805 + s9 += s17 * 136657 + s10 -= s17 * 683901 + s17 = 0 + + s4 += s16 * 666643 + s5 += s16 * 470296 + s6 += s16 * 654183 + s7 -= s16 * 997805 + s8 += s16 * 136657 + s9 -= s16 * 683901 + s16 = 0 + + s3 += s15 * 666643 + s4 += s15 * 470296 + s5 += s15 * 654183 + s6 -= s15 * 997805 + s7 += s15 * 136657 + s8 -= s15 * 683901 + s15 = 0 + + s2 += s14 * 666643 + s3 += s14 * 470296 + s4 += s14 * 654183 + s5 -= s14 * 997805 + s6 += s14 * 136657 + s7 -= s14 * 683901 + s14 = 0 + + s1 += s13 * 666643 + s2 += s13 * 470296 + s3 += s13 * 654183 + s4 -= s13 * 997805 + s5 += s13 * 136657 + s6 -= s13 * 683901 + s13 = 0 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[11] = s11 >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + s[0] = byte(s0 >> 0) + s[1] = byte(s0 >> 8) + s[2] = byte((s0 >> 16) | (s1 << 5)) + s[3] = byte(s1 >> 3) + s[4] = byte(s1 >> 11) + s[5] = byte((s1 >> 19) | (s2 << 2)) + s[6] = byte(s2 >> 6) + s[7] = byte((s2 >> 14) | (s3 << 7)) + s[8] = byte(s3 >> 1) + s[9] = byte(s3 >> 9) + s[10] = byte((s3 >> 17) | (s4 << 4)) + s[11] = byte(s4 >> 4) + s[12] = byte(s4 >> 12) + s[13] = byte((s4 >> 20) | (s5 << 1)) + s[14] = byte(s5 >> 7) + s[15] = byte((s5 >> 15) | (s6 << 6)) + s[16] = byte(s6 >> 2) + s[17] = byte(s6 >> 10) + s[18] = byte((s6 >> 18) | (s7 << 3)) + s[19] = byte(s7 >> 5) + s[20] = byte(s7 >> 13) + s[21] = byte(s8 >> 0) + s[22] = byte(s8 >> 8) + s[23] = byte((s8 >> 16) | (s9 << 5)) + s[24] = byte(s9 >> 3) + s[25] = byte(s9 >> 11) + s[26] = byte((s9 >> 19) | (s10 << 2)) + s[27] = byte(s10 >> 6) + s[28] = byte((s10 >> 14) | (s11 << 7)) + s[29] = byte(s11 >> 1) + s[30] = byte(s11 >> 9) + s[31] = byte(s11 >> 17) +} + +// Input: +// s[0]+256*s[1]+...+256^63*s[63] = s +// +// Output: +// s[0]+256*s[1]+...+256^31*s[31] = s mod l +// where l = 2^252 + 27742317777372353535851937790883648493. +func scReduce(out *[32]byte, s *[64]byte) { + s0 := 2097151 & load3(s[:]) + s1 := 2097151 & (load4(s[2:]) >> 5) + s2 := 2097151 & (load3(s[5:]) >> 2) + s3 := 2097151 & (load4(s[7:]) >> 7) + s4 := 2097151 & (load4(s[10:]) >> 4) + s5 := 2097151 & (load3(s[13:]) >> 1) + s6 := 2097151 & (load4(s[15:]) >> 6) + s7 := 2097151 & (load3(s[18:]) >> 3) + s8 := 2097151 & load3(s[21:]) + s9 := 2097151 & (load4(s[23:]) >> 5) + s10 := 2097151 & (load3(s[26:]) >> 2) + s11 := 2097151 & (load4(s[28:]) >> 7) + s12 := 2097151 & (load4(s[31:]) >> 4) + s13 := 2097151 & (load3(s[34:]) >> 1) + s14 := 2097151 & (load4(s[36:]) >> 6) + s15 := 2097151 & (load3(s[39:]) >> 3) + s16 := 2097151 & load3(s[42:]) + s17 := 2097151 & (load4(s[44:]) >> 5) + s18 := 2097151 & (load3(s[47:]) >> 2) + s19 := 2097151 & (load4(s[49:]) >> 7) + s20 := 2097151 & (load4(s[52:]) >> 4) + s21 := 2097151 & (load3(s[55:]) >> 1) + s22 := 2097151 & (load4(s[57:]) >> 6) + s23 := (load4(s[60:]) >> 3) + + s11 += s23 * 666643 + s12 += s23 * 470296 + s13 += s23 * 654183 + s14 -= s23 * 997805 + s15 += s23 * 136657 + s16 -= s23 * 683901 + s23 = 0 + + s10 += s22 * 666643 + s11 += s22 * 470296 + s12 += s22 * 654183 + s13 -= s22 * 997805 + s14 += s22 * 136657 + s15 -= s22 * 683901 + s22 = 0 + + s9 += s21 * 666643 + s10 += s21 * 470296 + s11 += s21 * 654183 + s12 -= s21 * 997805 + s13 += s21 * 136657 + s14 -= s21 * 683901 + s21 = 0 + + s8 += s20 * 666643 + s9 += s20 * 470296 + s10 += s20 * 654183 + s11 -= s20 * 997805 + s12 += s20 * 136657 + s13 -= s20 * 683901 + s20 = 0 + + s7 += s19 * 666643 + s8 += s19 * 470296 + s9 += s19 * 654183 + s10 -= s19 * 997805 + s11 += s19 * 136657 + s12 -= s19 * 683901 + s19 = 0 + + s6 += s18 * 666643 + s7 += s18 * 470296 + s8 += s18 * 654183 + s9 -= s18 * 997805 + s10 += s18 * 136657 + s11 -= s18 * 683901 + s18 = 0 + + var carry [17]int64 + + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + + s5 += s17 * 666643 + s6 += s17 * 470296 + s7 += s17 * 654183 + s8 -= s17 * 997805 + s9 += s17 * 136657 + s10 -= s17 * 683901 + s17 = 0 + + s4 += s16 * 666643 + s5 += s16 * 470296 + s6 += s16 * 654183 + s7 -= s16 * 997805 + s8 += s16 * 136657 + s9 -= s16 * 683901 + s16 = 0 + + s3 += s15 * 666643 + s4 += s15 * 470296 + s5 += s15 * 654183 + s6 -= s15 * 997805 + s7 += s15 * 136657 + s8 -= s15 * 683901 + s15 = 0 + + s2 += s14 * 666643 + s3 += s14 * 470296 + s4 += s14 * 654183 + s5 -= s14 * 997805 + s6 += s14 * 136657 + s7 -= s14 * 683901 + s14 = 0 + + s1 += s13 * 666643 + s2 += s13 * 470296 + s3 += s13 * 654183 + s4 -= s13 * 997805 + s5 += s13 * 136657 + s6 -= s13 * 683901 + s13 = 0 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[11] = s11 >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + out[0] = byte(s0 >> 0) + out[1] = byte(s0 >> 8) + out[2] = byte((s0 >> 16) | (s1 << 5)) + out[3] = byte(s1 >> 3) + out[4] = byte(s1 >> 11) + out[5] = byte((s1 >> 19) | (s2 << 2)) + out[6] = byte(s2 >> 6) + out[7] = byte((s2 >> 14) | (s3 << 7)) + out[8] = byte(s3 >> 1) + out[9] = byte(s3 >> 9) + out[10] = byte((s3 >> 17) | (s4 << 4)) + out[11] = byte(s4 >> 4) + out[12] = byte(s4 >> 12) + out[13] = byte((s4 >> 20) | (s5 << 1)) + out[14] = byte(s5 >> 7) + out[15] = byte((s5 >> 15) | (s6 << 6)) + out[16] = byte(s6 >> 2) + out[17] = byte(s6 >> 10) + out[18] = byte((s6 >> 18) | (s7 << 3)) + out[19] = byte(s7 >> 5) + out[20] = byte(s7 >> 13) + out[21] = byte(s8 >> 0) + out[22] = byte(s8 >> 8) + out[23] = byte((s8 >> 16) | (s9 << 5)) + out[24] = byte(s9 >> 3) + out[25] = byte(s9 >> 11) + out[26] = byte((s9 >> 19) | (s10 << 2)) + out[27] = byte(s10 >> 6) + out[28] = byte((s10 >> 14) | (s11 << 7)) + out[29] = byte(s11 >> 1) + out[30] = byte(s11 >> 9) + out[31] = byte(s11 >> 17) +} + +// nonAdjacentForm computes a width-w non-adjacent form for this scalar. +// +// w must be between 2 and 8, or nonAdjacentForm will panic. +func (s *Scalar) nonAdjacentForm(w uint) [256]int8 { + // This implementation is adapted from the one + // in curve25519-dalek and is documented there: + // https://github.com/dalek-cryptography/curve25519-dalek/blob/f630041af28e9a405255f98a8a93adca18e4315b/src/scalar.rs#L800-L871 + if s.s[31] > 127 { + panic("scalar has high bit set illegally") + } + if w < 2 { + panic("w must be at least 2 by the definition of NAF") + } else if w > 8 { + panic("NAF digits must fit in int8") + } + + var naf [256]int8 + var digits [5]uint64 + + for i := 0; i < 4; i++ { + digits[i] = binary.LittleEndian.Uint64(s.s[i*8:]) + } + + width := uint64(1 << w) + windowMask := uint64(width - 1) + + pos := uint(0) + carry := uint64(0) + for pos < 256 { + indexU64 := pos / 64 + indexBit := pos % 64 + var bitBuf uint64 + if indexBit < 64-w { + // This window's bits are contained in a single u64 + bitBuf = digits[indexU64] >> indexBit + } else { + // Combine the current 64 bits with bits from the next 64 + bitBuf = (digits[indexU64] >> indexBit) | (digits[1+indexU64] << (64 - indexBit)) + } + + // Add carry into the current window + window := carry + (bitBuf & windowMask) + + if window&1 == 0 { + // If the window value is even, preserve the carry and continue. + // Why is the carry preserved? + // If carry == 0 and window & 1 == 0, + // then the next carry should be 0 + // If carry == 1 and window & 1 == 0, + // then bit_buf & 1 == 1 so the next carry should be 1 + pos += 1 + continue + } + + if window < width/2 { + carry = 0 + naf[pos] = int8(window) + } else { + carry = 1 + naf[pos] = int8(window) - int8(width) + } + + pos += w + } + return naf +} + +func (s *Scalar) signedRadix16() [64]int8 { + if s.s[31] > 127 { + panic("scalar has high bit set illegally") + } + + var digits [64]int8 + + // Compute unsigned radix-16 digits: + for i := 0; i < 32; i++ { + digits[2*i] = int8(s.s[i] & 15) + digits[2*i+1] = int8((s.s[i] >> 4) & 15) + } + + // Recenter coefficients: + for i := 0; i < 63; i++ { + carry := (digits[i] + 8) >> 4 + digits[i] -= carry << 4 + digits[i+1] += carry + } + + return digits +} diff --git a/src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go b/src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go new file mode 100644 index 0000000..18d800d --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go @@ -0,0 +1,93 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "testing" + "testing/quick" +) + +func TestScalarAliasing(t *testing.T) { + checkAliasingOneArg := func(f func(v, x *Scalar) *Scalar, v, x Scalar) bool { + x1, v1 := x, x + + // Calculate a reference f(x) without aliasing. + if out := f(&v, &x); out != &v || !isReduced(out) { + return false + } + + // Test aliasing the argument and the receiver. + if out := f(&v1, &v1); out != &v1 || v1 != v || !isReduced(out) { + return false + } + + // Ensure the arguments was not modified. + return x == x1 + } + + checkAliasingTwoArgs := func(f func(v, x, y *Scalar) *Scalar, v, x, y Scalar) bool { + x1, y1, v1 := x, y, Scalar{} + + // Calculate a reference f(x, y) without aliasing. + if out := f(&v, &x, &y); out != &v || !isReduced(out) { + return false + } + + // Test aliasing the first argument and the receiver. + v1 = x + if out := f(&v1, &v1, &y); out != &v1 || v1 != v || !isReduced(out) { + return false + } + // Test aliasing the second argument and the receiver. + v1 = y + if out := f(&v1, &x, &v1); out != &v1 || v1 != v || !isReduced(out) { + return false + } + + // Calculate a reference f(x, x) without aliasing. + if out := f(&v, &x, &x); out != &v || !isReduced(out) { + return false + } + + // Test aliasing the first argument and the receiver. + v1 = x + if out := f(&v1, &v1, &x); out != &v1 || v1 != v || !isReduced(out) { + return false + } + // Test aliasing the second argument and the receiver. + v1 = x + if out := f(&v1, &x, &v1); out != &v1 || v1 != v || !isReduced(out) { + return false + } + // Test aliasing both arguments and the receiver. + v1 = x + if out := f(&v1, &v1, &v1); out != &v1 || v1 != v || !isReduced(out) { + return false + } + + // Ensure the arguments were not modified. + return x == x1 && y == y1 + } + + for name, f := range map[string]interface{}{ + "Negate": func(v, x Scalar) bool { + return checkAliasingOneArg((*Scalar).Negate, v, x) + }, + "Multiply": func(v, x, y Scalar) bool { + return checkAliasingTwoArgs((*Scalar).Multiply, v, x, y) + }, + "Add": func(v, x, y Scalar) bool { + return checkAliasingTwoArgs((*Scalar).Add, v, x, y) + }, + "Subtract": func(v, x, y Scalar) bool { + return checkAliasingTwoArgs((*Scalar).Subtract, v, x, y) + }, + } { + err := quick.Check(f, &quick.Config{MaxCountScale: 1 << 5}) + if err != nil { + t.Errorf("%v: %v", name, err) + } + } +} diff --git a/src/crypto/ed25519/internal/edwards25519/scalar_test.go b/src/crypto/ed25519/internal/edwards25519/scalar_test.go new file mode 100644 index 0000000..704caff --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/scalar_test.go @@ -0,0 +1,233 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "bytes" + "encoding/hex" + "math/big" + mathrand "math/rand" + "reflect" + "testing" + "testing/quick" +) + +// Generate returns a valid (reduced modulo l) Scalar with a distribution +// weighted towards high, low, and edge values. +func (Scalar) Generate(rand *mathrand.Rand, size int) reflect.Value { + s := scZero + diceRoll := rand.Intn(100) + switch { + case diceRoll == 0: + case diceRoll == 1: + s = scOne + case diceRoll == 2: + s = scMinusOne + case diceRoll < 5: + // Generate a low scalar in [0, 2^125). + rand.Read(s.s[:16]) + s.s[15] &= (1 << 5) - 1 + case diceRoll < 10: + // Generate a high scalar in [2^252, 2^252 + 2^124). + s.s[31] = 1 << 4 + rand.Read(s.s[:16]) + s.s[15] &= (1 << 4) - 1 + default: + // Generate a valid scalar in [0, l) by returning [0, 2^252) which has a + // negligibly different distribution (the former has a 2^-127.6 chance + // of being out of the latter range). + rand.Read(s.s[:]) + s.s[31] &= (1 << 4) - 1 + } + return reflect.ValueOf(s) +} + +// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks) +// times. The default value of -quickchecks is 100. +var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10} + +func TestScalarGenerate(t *testing.T) { + f := func(sc Scalar) bool { + return isReduced(&sc) + } + if err := quick.Check(f, quickCheckConfig1024); err != nil { + t.Errorf("generated unreduced scalar: %v", err) + } +} + +func TestScalarSetCanonicalBytes(t *testing.T) { + f1 := func(in [32]byte, sc Scalar) bool { + // Mask out top 4 bits to guarantee value falls in [0, l). + in[len(in)-1] &= (1 << 4) - 1 + if _, err := sc.SetCanonicalBytes(in[:]); err != nil { + return false + } + return bytes.Equal(in[:], sc.Bytes()) && isReduced(&sc) + } + if err := quick.Check(f1, quickCheckConfig1024); err != nil { + t.Errorf("failed bytes->scalar->bytes round-trip: %v", err) + } + + f2 := func(sc1, sc2 Scalar) bool { + if _, err := sc2.SetCanonicalBytes(sc1.Bytes()); err != nil { + return false + } + return sc1 == sc2 + } + if err := quick.Check(f2, quickCheckConfig1024); err != nil { + t.Errorf("failed scalar->bytes->scalar round-trip: %v", err) + } + + b := scMinusOne.s + b[31] += 1 + s := scOne + if out, err := s.SetCanonicalBytes(b[:]); err == nil { + t.Errorf("SetCanonicalBytes worked on a non-canonical value") + } else if s != scOne { + t.Errorf("SetCanonicalBytes modified its receiver") + } else if out != nil { + t.Errorf("SetCanonicalBytes did not return nil with an error") + } +} + +func TestScalarSetUniformBytes(t *testing.T) { + mod, _ := new(big.Int).SetString("27742317777372353535851937790883648493", 10) + mod.Add(mod, new(big.Int).Lsh(big.NewInt(1), 252)) + f := func(in [64]byte, sc Scalar) bool { + sc.SetUniformBytes(in[:]) + if !isReduced(&sc) { + return false + } + scBig := bigIntFromLittleEndianBytes(sc.s[:]) + inBig := bigIntFromLittleEndianBytes(in[:]) + return inBig.Mod(inBig, mod).Cmp(scBig) == 0 + } + if err := quick.Check(f, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestScalarSetBytesWithClamping(t *testing.T) { + // Generated with libsodium.js 1.0.18 crypto_scalarmult_ed25519_base. + + random := "633d368491364dc9cd4c1bf891b1d59460face1644813240a313e61f2c88216e" + s := new(Scalar).SetBytesWithClamping(decodeHex(random)) + p := new(Point).ScalarBaseMult(s) + want := "1d87a9026fd0126a5736fe1628c95dd419172b5b618457e041c9c861b2494a94" + if got := hex.EncodeToString(p.Bytes()); got != want { + t.Errorf("random: got %q, want %q", got, want) + } + + zero := "0000000000000000000000000000000000000000000000000000000000000000" + s = new(Scalar).SetBytesWithClamping(decodeHex(zero)) + p = new(Point).ScalarBaseMult(s) + want = "693e47972caf527c7883ad1b39822f026f47db2ab0e1919955b8993aa04411d1" + if got := hex.EncodeToString(p.Bytes()); got != want { + t.Errorf("zero: got %q, want %q", got, want) + } + + one := "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + s = new(Scalar).SetBytesWithClamping(decodeHex(one)) + p = new(Point).ScalarBaseMult(s) + want = "12e9a68b73fd5aacdbcaf3e88c46fea6ebedb1aa84eed1842f07f8edab65e3a7" + if got := hex.EncodeToString(p.Bytes()); got != want { + t.Errorf("one: got %q, want %q", got, want) + } +} + +func bigIntFromLittleEndianBytes(b []byte) *big.Int { + bb := make([]byte, len(b)) + for i := range b { + bb[i] = b[len(b)-i-1] + } + return new(big.Int).SetBytes(bb) +} + +func TestScalarMultiplyDistributesOverAdd(t *testing.T) { + multiplyDistributesOverAdd := func(x, y, z Scalar) bool { + // Compute t1 = (x+y)*z + var t1 Scalar + t1.Add(&x, &y) + t1.Multiply(&t1, &z) + + // Compute t2 = x*z + y*z + var t2 Scalar + var t3 Scalar + t2.Multiply(&x, &z) + t3.Multiply(&y, &z) + t2.Add(&t2, &t3) + + return t1 == t2 && isReduced(&t1) && isReduced(&t3) + } + + if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestScalarAddLikeSubNeg(t *testing.T) { + addLikeSubNeg := func(x, y Scalar) bool { + // Compute t1 = x - y + var t1 Scalar + t1.Subtract(&x, &y) + + // Compute t2 = -y + x + var t2 Scalar + t2.Negate(&y) + t2.Add(&t2, &x) + + return t1 == t2 && isReduced(&t1) + } + + if err := quick.Check(addLikeSubNeg, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestScalarNonAdjacentForm(t *testing.T) { + s := Scalar{[32]byte{ + 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, + 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, + 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, + 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09, + }} + expectedNaf := [256]int8{ + 0, 13, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, -11, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 9, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, + -9, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 9, 0, + 0, 0, 0, -15, 0, 0, 0, 0, -7, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, -3, 0, + 0, 0, 0, -11, 0, 0, 0, 0, -7, 0, 0, 0, 0, -13, 0, 0, 0, 0, 11, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, -15, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 13, 0, 0, 0, + 0, 0, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + } + + sNaf := s.nonAdjacentForm(5) + + for i := 0; i < 256; i++ { + if expectedNaf[i] != sNaf[i] { + t.Errorf("Wrong digit at position %d, got %d, expected %d", i, sNaf[i], expectedNaf[i]) + } + } +} + +type notZeroScalar Scalar + +func (notZeroScalar) Generate(rand *mathrand.Rand, size int) reflect.Value { + var s Scalar + for s == scZero { + s = Scalar{}.Generate(rand, size).Interface().(Scalar) + } + return reflect.ValueOf(notZeroScalar(s)) +} + +func TestScalarEqual(t *testing.T) { + if scOne.Equal(&scMinusOne) == 1 { + t.Errorf("scOne.Equal(&scMinusOne) is true") + } + if scMinusOne.Equal(&scMinusOne) == 0 { + t.Errorf("scMinusOne.Equal(&scMinusOne) is false") + } +} diff --git a/src/crypto/ed25519/internal/edwards25519/scalarmult.go b/src/crypto/ed25519/internal/edwards25519/scalarmult.go new file mode 100644 index 0000000..f7ca3ce --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/scalarmult.go @@ -0,0 +1,214 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import "sync" + +// basepointTable is a set of 32 affineLookupTables, where table i is generated +// from 256i * basepoint. It is precomputed the first time it's used. +func basepointTable() *[32]affineLookupTable { + basepointTablePrecomp.initOnce.Do(func() { + p := NewGeneratorPoint() + for i := 0; i < 32; i++ { + basepointTablePrecomp.table[i].FromP3(p) + for j := 0; j < 8; j++ { + p.Add(p, p) + } + } + }) + return &basepointTablePrecomp.table +} + +var basepointTablePrecomp struct { + table [32]affineLookupTable + initOnce sync.Once +} + +// ScalarBaseMult sets v = x * B, where B is the canonical generator, and +// returns v. +// +// The scalar multiplication is done in constant time. +func (v *Point) ScalarBaseMult(x *Scalar) *Point { + basepointTable := basepointTable() + + // Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i ) + // as described in the Ed25519 paper + // + // Group even and odd coefficients + // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B + // + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B + // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B + // + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B) + // + // We use a lookup table for each i to get x_i*16^(2*i)*B + // and do four doublings to multiply by 16. + digits := x.signedRadix16() + + multiple := &affineCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + + // Accumulate the odd components first + v.Set(NewIdentityPoint()) + for i := 1; i < 64; i += 2 { + basepointTable[i/2].SelectInto(multiple, digits[i]) + tmp1.AddAffine(v, multiple) + v.fromP1xP1(tmp1) + } + + // Multiply by 16 + tmp2.FromP3(v) // tmp2 = v in P2 coords + tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords + v.fromP1xP1(tmp1) // now v = 16*(odd components) + + // Accumulate the even components + for i := 0; i < 64; i += 2 { + basepointTable[i/2].SelectInto(multiple, digits[i]) + tmp1.AddAffine(v, multiple) + v.fromP1xP1(tmp1) + } + + return v +} + +// ScalarMult sets v = x * q, and returns v. +// +// The scalar multiplication is done in constant time. +func (v *Point) ScalarMult(x *Scalar, q *Point) *Point { + checkInitialized(q) + + var table projLookupTable + table.FromP3(q) + + // Write x = sum(x_i * 16^i) + // so x*Q = sum( Q*x_i*16^i ) + // = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... ) + // <------compute inside out--------- + // + // We use the lookup table to get the x_i*Q values + // and do four doublings to compute 16*Q + digits := x.signedRadix16() + + // Unwrap first loop iteration to save computing 16*identity + multiple := &projCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + table.SelectInto(multiple, digits[63]) + + v.Set(NewIdentityPoint()) + tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords + for i := 62; i >= 0; i-- { + tmp2.FromP1xP1(tmp1) // tmp2 = (prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords + v.fromP1xP1(tmp1) // v = 16*(prev) in P3 coords + table.SelectInto(multiple, digits[i]) + tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords + } + v.fromP1xP1(tmp1) + return v +} + +// basepointNafTable is the nafLookupTable8 for the basepoint. +// It is precomputed the first time it's used. +func basepointNafTable() *nafLookupTable8 { + basepointNafTablePrecomp.initOnce.Do(func() { + basepointNafTablePrecomp.table.FromP3(NewGeneratorPoint()) + }) + return &basepointNafTablePrecomp.table +} + +var basepointNafTablePrecomp struct { + table nafLookupTable8 + initOnce sync.Once +} + +// VarTimeDoubleScalarBaseMult sets v = a * A + b * B, where B is the canonical +// generator, and returns v. +// +// Execution time depends on the inputs. +func (v *Point) VarTimeDoubleScalarBaseMult(a *Scalar, A *Point, b *Scalar) *Point { + checkInitialized(A) + + // Similarly to the single variable-base approach, we compute + // digits and use them with a lookup table. However, because + // we are allowed to do variable-time operations, we don't + // need constant-time lookups or constant-time digit + // computations. + // + // So we use a non-adjacent form of some width w instead of + // radix 16. This is like a binary representation (one digit + // for each binary place) but we allow the digits to grow in + // magnitude up to 2^{w-1} so that the nonzero digits are as + // sparse as possible. Intuitively, this "condenses" the + // "mass" of the scalar onto sparse coefficients (meaning + // fewer additions). + + basepointNafTable := basepointNafTable() + var aTable nafLookupTable5 + aTable.FromP3(A) + // Because the basepoint is fixed, we can use a wider NAF + // corresponding to a bigger table. + aNaf := a.nonAdjacentForm(5) + bNaf := b.nonAdjacentForm(8) + + // Find the first nonzero coefficient. + i := 255 + for j := i; j >= 0; j-- { + if aNaf[j] != 0 || bNaf[j] != 0 { + break + } + } + + multA := &projCached{} + multB := &affineCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + tmp2.Zero() + + // Move from high to low bits, doubling the accumulator + // at each iteration and checking whether there is a nonzero + // coefficient to look up a multiple of. + for ; i >= 0; i-- { + tmp1.Double(tmp2) + + // Only update v if we have a nonzero coeff to add in. + if aNaf[i] > 0 { + v.fromP1xP1(tmp1) + aTable.SelectInto(multA, aNaf[i]) + tmp1.Add(v, multA) + } else if aNaf[i] < 0 { + v.fromP1xP1(tmp1) + aTable.SelectInto(multA, -aNaf[i]) + tmp1.Sub(v, multA) + } + + if bNaf[i] > 0 { + v.fromP1xP1(tmp1) + basepointNafTable.SelectInto(multB, bNaf[i]) + tmp1.AddAffine(v, multB) + } else if bNaf[i] < 0 { + v.fromP1xP1(tmp1) + basepointNafTable.SelectInto(multB, -bNaf[i]) + tmp1.SubAffine(v, multB) + } + + tmp2.FromP1xP1(tmp1) + } + + v.fromP2(tmp2) + return v +} diff --git a/src/crypto/ed25519/internal/edwards25519/scalarmult_test.go b/src/crypto/ed25519/internal/edwards25519/scalarmult_test.go new file mode 100644 index 0000000..c2027f5 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/scalarmult_test.go @@ -0,0 +1,209 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "testing" + "testing/quick" +) + +var ( + // quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks) + // times. The default value of -quickchecks is 100. + quickCheckConfig32 = &quick.Config{MaxCountScale: 1 << 5} + + // a random scalar generated using dalek. + dalekScalar = Scalar{[32]byte{219, 106, 114, 9, 174, 249, 155, 89, 69, 203, 201, 93, 92, 116, 234, 187, 78, 115, 103, 172, 182, 98, 62, 103, 187, 136, 13, 100, 248, 110, 12, 4}} + // the above, times the edwards25519 basepoint. + dalekScalarBasepoint, _ = new(Point).SetBytes([]byte{0xf4, 0xef, 0x7c, 0xa, 0x34, 0x55, 0x7b, 0x9f, 0x72, 0x3b, 0xb6, 0x1e, 0xf9, 0x46, 0x9, 0x91, 0x1c, 0xb9, 0xc0, 0x6c, 0x17, 0x28, 0x2d, 0x8b, 0x43, 0x2b, 0x5, 0x18, 0x6a, 0x54, 0x3e, 0x48}) +) + +func TestScalarMultSmallScalars(t *testing.T) { + var z Scalar + var p Point + p.ScalarMult(&z, B) + if I.Equal(&p) != 1 { + t.Error("0*B != 0") + } + checkOnCurve(t, &p) + + z = Scalar{[32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} + p.ScalarMult(&z, B) + if B.Equal(&p) != 1 { + t.Error("1*B != 1") + } + checkOnCurve(t, &p) +} + +func TestScalarMultVsDalek(t *testing.T) { + var p Point + p.ScalarMult(&dalekScalar, B) + if dalekScalarBasepoint.Equal(&p) != 1 { + t.Error("Scalar mul does not match dalek") + } + checkOnCurve(t, &p) +} + +func TestBaseMultVsDalek(t *testing.T) { + var p Point + p.ScalarBaseMult(&dalekScalar) + if dalekScalarBasepoint.Equal(&p) != 1 { + t.Error("Scalar mul does not match dalek") + } + checkOnCurve(t, &p) +} + +func TestVarTimeDoubleBaseMultVsDalek(t *testing.T) { + var p Point + var z Scalar + p.VarTimeDoubleScalarBaseMult(&dalekScalar, B, &z) + if dalekScalarBasepoint.Equal(&p) != 1 { + t.Error("VarTimeDoubleScalarBaseMult fails with b=0") + } + checkOnCurve(t, &p) + p.VarTimeDoubleScalarBaseMult(&z, B, &dalekScalar) + if dalekScalarBasepoint.Equal(&p) != 1 { + t.Error("VarTimeDoubleScalarBaseMult fails with a=0") + } + checkOnCurve(t, &p) +} + +func TestScalarMultDistributesOverAdd(t *testing.T) { + scalarMultDistributesOverAdd := func(x, y Scalar) bool { + var z Scalar + z.Add(&x, &y) + var p, q, r, check Point + p.ScalarMult(&x, B) + q.ScalarMult(&y, B) + r.ScalarMult(&z, B) + check.Add(&p, &q) + checkOnCurve(t, &p, &q, &r, &check) + return check.Equal(&r) == 1 + } + + if err := quick.Check(scalarMultDistributesOverAdd, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestScalarMultNonIdentityPoint(t *testing.T) { + // Check whether p.ScalarMult and q.ScalaBaseMult give the same, + // when p and q are originally set to the base point. + + scalarMultNonIdentityPoint := func(x Scalar) bool { + var p, q Point + p.Set(B) + q.Set(B) + + p.ScalarMult(&x, B) + q.ScalarBaseMult(&x) + + checkOnCurve(t, &p, &q) + + return p.Equal(&q) == 1 + } + + if err := quick.Check(scalarMultNonIdentityPoint, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestBasepointTableGeneration(t *testing.T) { + // The basepoint table is 32 affineLookupTables, + // corresponding to (16^2i)*B for table i. + basepointTable := basepointTable() + + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + tmp3 := &Point{} + tmp3.Set(B) + table := make([]affineLookupTable, 32) + for i := 0; i < 32; i++ { + // Build the table + table[i].FromP3(tmp3) + // Assert equality with the hardcoded one + if table[i] != basepointTable[i] { + t.Errorf("Basepoint table %d does not match", i) + } + + // Set p = (16^2)*p = 256*p = 2^8*p + tmp2.FromP3(tmp3) + for j := 0; j < 7; j++ { + tmp1.Double(tmp2) + tmp2.FromP1xP1(tmp1) + } + tmp1.Double(tmp2) + tmp3.fromP1xP1(tmp1) + checkOnCurve(t, tmp3) + } +} + +func TestScalarMultMatchesBaseMult(t *testing.T) { + scalarMultMatchesBaseMult := func(x Scalar) bool { + var p, q Point + p.ScalarMult(&x, B) + q.ScalarBaseMult(&x) + checkOnCurve(t, &p, &q) + return p.Equal(&q) == 1 + } + + if err := quick.Check(scalarMultMatchesBaseMult, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestBasepointNafTableGeneration(t *testing.T) { + var table nafLookupTable8 + table.FromP3(B) + + if table != *basepointNafTable() { + t.Error("BasepointNafTable does not match") + } +} + +func TestVarTimeDoubleBaseMultMatchesBaseMult(t *testing.T) { + varTimeDoubleBaseMultMatchesBaseMult := func(x, y Scalar) bool { + var p, q1, q2, check Point + + p.VarTimeDoubleScalarBaseMult(&x, B, &y) + + q1.ScalarBaseMult(&x) + q2.ScalarBaseMult(&y) + check.Add(&q1, &q2) + + checkOnCurve(t, &p, &check, &q1, &q2) + return p.Equal(&check) == 1 + } + + if err := quick.Check(varTimeDoubleBaseMultMatchesBaseMult, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +// Benchmarks. + +func BenchmarkScalarBaseMult(t *testing.B) { + var p Point + + for i := 0; i < t.N; i++ { + p.ScalarBaseMult(&dalekScalar) + } +} + +func BenchmarkScalarMult(t *testing.B) { + var p Point + + for i := 0; i < t.N; i++ { + p.ScalarMult(&dalekScalar, B) + } +} + +func BenchmarkVarTimeDoubleScalarBaseMult(t *testing.B) { + var p Point + + for i := 0; i < t.N; i++ { + p.VarTimeDoubleScalarBaseMult(&dalekScalar, B, &dalekScalar) + } +} diff --git a/src/crypto/ed25519/internal/edwards25519/tables.go b/src/crypto/ed25519/internal/edwards25519/tables.go new file mode 100644 index 0000000..beec956 --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/tables.go @@ -0,0 +1,129 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "crypto/subtle" +) + +// A dynamic lookup table for variable-base, constant-time scalar muls. +type projLookupTable struct { + points [8]projCached +} + +// A precomputed lookup table for fixed-base, constant-time scalar muls. +type affineLookupTable struct { + points [8]affineCached +} + +// A dynamic lookup table for variable-base, variable-time scalar muls. +type nafLookupTable5 struct { + points [8]projCached +} + +// A precomputed lookup table for fixed-base, variable-time scalar muls. +type nafLookupTable8 struct { + points [64]affineCached +} + +// Constructors. + +// Builds a lookup table at runtime. Fast. +func (v *projLookupTable) FromP3(q *Point) { + // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q + // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q + v.points[0].FromP3(q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + // Compute (i+1)*Q as Q + i*Q and convert to a ProjCached + // This is needlessly complicated because the API has explicit + // recievers instead of creating stack objects and relying on RVO + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(q, &v.points[i]))) + } +} + +// This is not optimised for speed; fixed-base tables should be precomputed. +func (v *affineLookupTable) FromP3(q *Point) { + // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q + // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q + v.points[0].FromP3(q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + // Compute (i+1)*Q as Q + i*Q and convert to AffineCached + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(q, &v.points[i]))) + } +} + +// Builds a lookup table at runtime. Fast. +func (v *nafLookupTable5) FromP3(q *Point) { + // Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q + // This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q + v.points[0].FromP3(q) + q2 := Point{} + q2.Add(q, q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(&q2, &v.points[i]))) + } +} + +// This is not optimised for speed; fixed-base tables should be precomputed. +func (v *nafLookupTable8) FromP3(q *Point) { + v.points[0].FromP3(q) + q2 := Point{} + q2.Add(q, q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 63; i++ { + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(&q2, &v.points[i]))) + } +} + +// Selectors. + +// Set dest to x*Q, where -8 <= x <= 8, in constant time. +func (v *projLookupTable) SelectInto(dest *projCached, x int8) { + // Compute xabs = |x| + xmask := x >> 7 + xabs := uint8((x + xmask) ^ xmask) + + dest.Zero() + for j := 1; j <= 8; j++ { + // Set dest = j*Q if |x| = j + cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) + dest.Select(&v.points[j-1], dest, cond) + } + // Now dest = |x|*Q, conditionally negate to get x*Q + dest.CondNeg(int(xmask & 1)) +} + +// Set dest to x*Q, where -8 <= x <= 8, in constant time. +func (v *affineLookupTable) SelectInto(dest *affineCached, x int8) { + // Compute xabs = |x| + xmask := x >> 7 + xabs := uint8((x + xmask) ^ xmask) + + dest.Zero() + for j := 1; j <= 8; j++ { + // Set dest = j*Q if |x| = j + cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) + dest.Select(&v.points[j-1], dest, cond) + } + // Now dest = |x|*Q, conditionally negate to get x*Q + dest.CondNeg(int(xmask & 1)) +} + +// Given odd x with 0 < x < 2^4, return x*Q (in variable time). +func (v *nafLookupTable5) SelectInto(dest *projCached, x int8) { + *dest = v.points[x/2] +} + +// Given odd x with 0 < x < 2^7, return x*Q (in variable time). +func (v *nafLookupTable8) SelectInto(dest *affineCached, x int8) { + *dest = v.points[x/2] +} diff --git a/src/crypto/ed25519/internal/edwards25519/tables_test.go b/src/crypto/ed25519/internal/edwards25519/tables_test.go new file mode 100644 index 0000000..b5d161a --- /dev/null +++ b/src/crypto/ed25519/internal/edwards25519/tables_test.go @@ -0,0 +1,119 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "testing" +) + +func TestProjLookupTable(t *testing.T) { + var table projLookupTable + table.FromP3(B) + + var tmp1, tmp2, tmp3 projCached + table.SelectInto(&tmp1, 6) + table.SelectInto(&tmp2, -2) + table.SelectInto(&tmp3, -4) + // Expect T1 + T2 + T3 = identity + + var accP1xP1 projP1xP1 + accP3 := NewIdentityPoint() + + accP1xP1.Add(accP3, &tmp1) + accP3.fromP1xP1(&accP1xP1) + accP1xP1.Add(accP3, &tmp2) + accP3.fromP1xP1(&accP1xP1) + accP1xP1.Add(accP3, &tmp3) + accP3.fromP1xP1(&accP1xP1) + + if accP3.Equal(I) != 1 { + t.Errorf("Consistency check on ProjLookupTable.SelectInto failed! %x %x %x", tmp1, tmp2, tmp3) + } +} + +func TestAffineLookupTable(t *testing.T) { + var table affineLookupTable + table.FromP3(B) + + var tmp1, tmp2, tmp3 affineCached + table.SelectInto(&tmp1, 3) + table.SelectInto(&tmp2, -7) + table.SelectInto(&tmp3, 4) + // Expect T1 + T2 + T3 = identity + + var accP1xP1 projP1xP1 + accP3 := NewIdentityPoint() + + accP1xP1.AddAffine(accP3, &tmp1) + accP3.fromP1xP1(&accP1xP1) + accP1xP1.AddAffine(accP3, &tmp2) + accP3.fromP1xP1(&accP1xP1) + accP1xP1.AddAffine(accP3, &tmp3) + accP3.fromP1xP1(&accP1xP1) + + if accP3.Equal(I) != 1 { + t.Errorf("Consistency check on ProjLookupTable.SelectInto failed! %x %x %x", tmp1, tmp2, tmp3) + } +} + +func TestNafLookupTable5(t *testing.T) { + var table nafLookupTable5 + table.FromP3(B) + + var tmp1, tmp2, tmp3, tmp4 projCached + table.SelectInto(&tmp1, 9) + table.SelectInto(&tmp2, 11) + table.SelectInto(&tmp3, 7) + table.SelectInto(&tmp4, 13) + // Expect T1 + T2 = T3 + T4 + + var accP1xP1 projP1xP1 + lhs := NewIdentityPoint() + rhs := NewIdentityPoint() + + accP1xP1.Add(lhs, &tmp1) + lhs.fromP1xP1(&accP1xP1) + accP1xP1.Add(lhs, &tmp2) + lhs.fromP1xP1(&accP1xP1) + + accP1xP1.Add(rhs, &tmp3) + rhs.fromP1xP1(&accP1xP1) + accP1xP1.Add(rhs, &tmp4) + rhs.fromP1xP1(&accP1xP1) + + if lhs.Equal(rhs) != 1 { + t.Errorf("Consistency check on nafLookupTable5 failed") + } +} + +func TestNafLookupTable8(t *testing.T) { + var table nafLookupTable8 + table.FromP3(B) + + var tmp1, tmp2, tmp3, tmp4 affineCached + table.SelectInto(&tmp1, 49) + table.SelectInto(&tmp2, 11) + table.SelectInto(&tmp3, 35) + table.SelectInto(&tmp4, 25) + // Expect T1 + T2 = T3 + T4 + + var accP1xP1 projP1xP1 + lhs := NewIdentityPoint() + rhs := NewIdentityPoint() + + accP1xP1.AddAffine(lhs, &tmp1) + lhs.fromP1xP1(&accP1xP1) + accP1xP1.AddAffine(lhs, &tmp2) + lhs.fromP1xP1(&accP1xP1) + + accP1xP1.AddAffine(rhs, &tmp3) + rhs.fromP1xP1(&accP1xP1) + accP1xP1.AddAffine(rhs, &tmp4) + rhs.fromP1xP1(&accP1xP1) + + if lhs.Equal(rhs) != 1 { + t.Errorf("Consistency check on nafLookupTable8 failed") + } +} diff --git a/src/crypto/ed25519/testdata/sign.input.gz b/src/crypto/ed25519/testdata/sign.input.gz new file mode 100644 index 0000000..e6dc728 Binary files /dev/null and b/src/crypto/ed25519/testdata/sign.input.gz differ diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go new file mode 100644 index 0000000..b84339e --- /dev/null +++ b/src/crypto/elliptic/elliptic.go @@ -0,0 +1,491 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package elliptic implements several standard elliptic curves over prime +// fields. +package elliptic + +// This package operates, internally, on Jacobian coordinates. For a given +// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1) +// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole +// calculation can be performed within the transform (as in ScalarMult and +// ScalarBaseMult). But even for Add and Double, it's faster to apply and +// reverse the transform than to operate in affine coordinates. + +import ( + "io" + "math/big" + "sync" +) + +// A Curve represents a short-form Weierstrass curve with a=-3. +// +// Note that the point at infinity (0, 0) is not considered on the curve, and +// although it can be returned by Add, Double, ScalarMult, or ScalarBaseMult, it +// can't be marshaled or unmarshaled, and IsOnCurve will return false for it. +type Curve interface { + // Params returns the parameters for the curve. + Params() *CurveParams + // IsOnCurve reports whether the given (x,y) lies on the curve. + IsOnCurve(x, y *big.Int) bool + // Add returns the sum of (x1,y1) and (x2,y2) + Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) + // Double returns 2*(x,y) + Double(x1, y1 *big.Int) (x, y *big.Int) + // ScalarMult returns k*(Bx,By) where k is a number in big-endian form. + ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int) + // ScalarBaseMult returns k*G, where G is the base point of the group + // and k is an integer in big-endian form. + ScalarBaseMult(k []byte) (x, y *big.Int) +} + +func matchesSpecificCurve(params *CurveParams, available ...Curve) (Curve, bool) { + for _, c := range available { + if params == c.Params() { + return c, true + } + } + return nil, false +} + +// CurveParams contains the parameters of an elliptic curve and also provides +// a generic, non-constant time implementation of Curve. +type CurveParams struct { + P *big.Int // the order of the underlying field + N *big.Int // the order of the base point + B *big.Int // the constant of the curve equation + Gx, Gy *big.Int // (x,y) of the base point + BitSize int // the size of the underlying field + Name string // the canonical name of the curve +} + +func (curve *CurveParams) Params() *CurveParams { + return curve +} + +// polynomial returns x³ - 3x + b. +func (curve *CurveParams) polynomial(x *big.Int) *big.Int { + x3 := new(big.Int).Mul(x, x) + x3.Mul(x3, x) + + threeX := new(big.Int).Lsh(x, 1) + threeX.Add(threeX, x) + + x3.Sub(x3, threeX) + x3.Add(x3, curve.B) + x3.Mod(x3, curve.P) + + return x3 +} + +func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + return specific.IsOnCurve(x, y) + } + + if x.Sign() < 0 || x.Cmp(curve.P) >= 0 || + y.Sign() < 0 || y.Cmp(curve.P) >= 0 { + return false + } + + // y² = x³ - 3x + b + y2 := new(big.Int).Mul(y, y) + y2.Mod(y2, curve.P) + + return curve.polynomial(x).Cmp(y2) == 0 +} + +// zForAffine returns a Jacobian Z value for the affine point (x, y). If x and +// y are zero, it assumes that they represent the point at infinity because (0, +// 0) is not on the any of the curves handled here. +func zForAffine(x, y *big.Int) *big.Int { + z := new(big.Int) + if x.Sign() != 0 || y.Sign() != 0 { + z.SetInt64(1) + } + return z +} + +// affineFromJacobian reverses the Jacobian transform. See the comment at the +// top of the file. If the point is ∞ it returns 0, 0. +func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) { + if z.Sign() == 0 { + return new(big.Int), new(big.Int) + } + + zinv := new(big.Int).ModInverse(z, curve.P) + zinvsq := new(big.Int).Mul(zinv, zinv) + + xOut = new(big.Int).Mul(x, zinvsq) + xOut.Mod(xOut, curve.P) + zinvsq.Mul(zinvsq, zinv) + yOut = new(big.Int).Mul(y, zinvsq) + yOut.Mod(yOut, curve.P) + return +} + +func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + return specific.Add(x1, y1, x2, y2) + } + + z1 := zForAffine(x1, y1) + z2 := zForAffine(x2, y2) + return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2)) +} + +// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and +// (x2, y2, z2) and returns their sum, also in Jacobian form. +func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { + // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl + x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int) + if z1.Sign() == 0 { + x3.Set(x2) + y3.Set(y2) + z3.Set(z2) + return x3, y3, z3 + } + if z2.Sign() == 0 { + x3.Set(x1) + y3.Set(y1) + z3.Set(z1) + return x3, y3, z3 + } + + z1z1 := new(big.Int).Mul(z1, z1) + z1z1.Mod(z1z1, curve.P) + z2z2 := new(big.Int).Mul(z2, z2) + z2z2.Mod(z2z2, curve.P) + + u1 := new(big.Int).Mul(x1, z2z2) + u1.Mod(u1, curve.P) + u2 := new(big.Int).Mul(x2, z1z1) + u2.Mod(u2, curve.P) + h := new(big.Int).Sub(u2, u1) + xEqual := h.Sign() == 0 + if h.Sign() == -1 { + h.Add(h, curve.P) + } + i := new(big.Int).Lsh(h, 1) + i.Mul(i, i) + j := new(big.Int).Mul(h, i) + + s1 := new(big.Int).Mul(y1, z2) + s1.Mul(s1, z2z2) + s1.Mod(s1, curve.P) + s2 := new(big.Int).Mul(y2, z1) + s2.Mul(s2, z1z1) + s2.Mod(s2, curve.P) + r := new(big.Int).Sub(s2, s1) + if r.Sign() == -1 { + r.Add(r, curve.P) + } + yEqual := r.Sign() == 0 + if xEqual && yEqual { + return curve.doubleJacobian(x1, y1, z1) + } + r.Lsh(r, 1) + v := new(big.Int).Mul(u1, i) + + x3.Set(r) + x3.Mul(x3, x3) + x3.Sub(x3, j) + x3.Sub(x3, v) + x3.Sub(x3, v) + x3.Mod(x3, curve.P) + + y3.Set(r) + v.Sub(v, x3) + y3.Mul(y3, v) + s1.Mul(s1, j) + s1.Lsh(s1, 1) + y3.Sub(y3, s1) + y3.Mod(y3, curve.P) + + z3.Add(z1, z2) + z3.Mul(z3, z3) + z3.Sub(z3, z1z1) + z3.Sub(z3, z2z2) + z3.Mul(z3, h) + z3.Mod(z3, curve.P) + + return x3, y3, z3 +} + +func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + return specific.Double(x1, y1) + } + + z1 := zForAffine(x1, y1) + return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1)) +} + +// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and +// returns its double, also in Jacobian form. +func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { + // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + delta := new(big.Int).Mul(z, z) + delta.Mod(delta, curve.P) + gamma := new(big.Int).Mul(y, y) + gamma.Mod(gamma, curve.P) + alpha := new(big.Int).Sub(x, delta) + if alpha.Sign() == -1 { + alpha.Add(alpha, curve.P) + } + alpha2 := new(big.Int).Add(x, delta) + alpha.Mul(alpha, alpha2) + alpha2.Set(alpha) + alpha.Lsh(alpha, 1) + alpha.Add(alpha, alpha2) + + beta := alpha2.Mul(x, gamma) + + x3 := new(big.Int).Mul(alpha, alpha) + beta8 := new(big.Int).Lsh(beta, 3) + beta8.Mod(beta8, curve.P) + x3.Sub(x3, beta8) + if x3.Sign() == -1 { + x3.Add(x3, curve.P) + } + x3.Mod(x3, curve.P) + + z3 := new(big.Int).Add(y, z) + z3.Mul(z3, z3) + z3.Sub(z3, gamma) + if z3.Sign() == -1 { + z3.Add(z3, curve.P) + } + z3.Sub(z3, delta) + if z3.Sign() == -1 { + z3.Add(z3, curve.P) + } + z3.Mod(z3, curve.P) + + beta.Lsh(beta, 2) + beta.Sub(beta, x3) + if beta.Sign() == -1 { + beta.Add(beta, curve.P) + } + y3 := alpha.Mul(alpha, beta) + + gamma.Mul(gamma, gamma) + gamma.Lsh(gamma, 3) + gamma.Mod(gamma, curve.P) + + y3.Sub(y3, gamma) + if y3.Sign() == -1 { + y3.Add(y3, curve.P) + } + y3.Mod(y3, curve.P) + + return x3, y3, z3 +} + +func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok { + return specific.ScalarMult(Bx, By, k) + } + + Bz := new(big.Int).SetInt64(1) + x, y, z := new(big.Int), new(big.Int), new(big.Int) + + for _, byte := range k { + for bitNum := 0; bitNum < 8; bitNum++ { + x, y, z = curve.doubleJacobian(x, y, z) + if byte&0x80 == 0x80 { + x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z) + } + byte <<= 1 + } + } + + return curve.affineFromJacobian(x, y, z) +} + +func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok { + return specific.ScalarBaseMult(k) + } + + return curve.ScalarMult(curve.Gx, curve.Gy, k) +} + +var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f} + +// GenerateKey returns a public/private key pair. The private key is +// generated using the given reader, which must return random data. +func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) { + N := curve.Params().N + bitSize := N.BitLen() + byteLen := (bitSize + 7) / 8 + priv = make([]byte, byteLen) + + for x == nil { + _, err = io.ReadFull(rand, priv) + if err != nil { + return + } + // We have to mask off any excess bits in the case that the size of the + // underlying field is not a whole number of bytes. + priv[0] &= mask[bitSize%8] + // This is because, in tests, rand will return all zeros and we don't + // want to get the point at infinity and loop forever. + priv[1] ^= 0x42 + + // If the scalar is out of range, sample another random number. + if new(big.Int).SetBytes(priv).Cmp(N) >= 0 { + continue + } + + x, y = curve.ScalarBaseMult(priv) + } + return +} + +// Marshal converts a point on the curve into the uncompressed form specified in +// section 4.3.6 of ANSI X9.62. +func Marshal(curve Curve, x, y *big.Int) []byte { + byteLen := (curve.Params().BitSize + 7) / 8 + + ret := make([]byte, 1+2*byteLen) + ret[0] = 4 // uncompressed point + + x.FillBytes(ret[1 : 1+byteLen]) + y.FillBytes(ret[1+byteLen : 1+2*byteLen]) + + return ret +} + +// MarshalCompressed converts a point on the curve into the compressed form +// specified in section 4.3.6 of ANSI X9.62. +func MarshalCompressed(curve Curve, x, y *big.Int) []byte { + byteLen := (curve.Params().BitSize + 7) / 8 + compressed := make([]byte, 1+byteLen) + compressed[0] = byte(y.Bit(0)) | 2 + x.FillBytes(compressed[1:]) + return compressed +} + +// Unmarshal converts a point, serialized by Marshal, into an x, y pair. +// It is an error if the point is not in uncompressed form or is not on the curve. +// On error, x = nil. +func Unmarshal(curve Curve, data []byte) (x, y *big.Int) { + byteLen := (curve.Params().BitSize + 7) / 8 + if len(data) != 1+2*byteLen { + return nil, nil + } + if data[0] != 4 { // uncompressed form + return nil, nil + } + p := curve.Params().P + x = new(big.Int).SetBytes(data[1 : 1+byteLen]) + y = new(big.Int).SetBytes(data[1+byteLen:]) + if x.Cmp(p) >= 0 || y.Cmp(p) >= 0 { + return nil, nil + } + if !curve.IsOnCurve(x, y) { + return nil, nil + } + return +} + +// UnmarshalCompressed converts a point, serialized by MarshalCompressed, into an x, y pair. +// It is an error if the point is not in compressed form or is not on the curve. +// On error, x = nil. +func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) { + byteLen := (curve.Params().BitSize + 7) / 8 + if len(data) != 1+byteLen { + return nil, nil + } + if data[0] != 2 && data[0] != 3 { // compressed form + return nil, nil + } + p := curve.Params().P + x = new(big.Int).SetBytes(data[1:]) + if x.Cmp(p) >= 0 { + return nil, nil + } + // y² = x³ - 3x + b + y = curve.Params().polynomial(x) + y = y.ModSqrt(y, p) + if y == nil { + return nil, nil + } + if byte(y.Bit(0)) != data[0]&1 { + y.Neg(y).Mod(y, p) + } + if !curve.IsOnCurve(x, y) { + return nil, nil + } + return +} + +var initonce sync.Once +var p384 *CurveParams + +func initAll() { + initP224() + initP256() + initP384() + initP521() +} + +func initP384() { + // See FIPS 186-3, section D.2.4 + p384 = &CurveParams{Name: "P-384"} + p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10) + p384.N, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10) + p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16) + p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16) + p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16) + p384.BitSize = 384 +} + +// P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3), +// also known as secp256r1 or prime256v1. The CurveParams.Name of this Curve is +// "P-256". +// +// Multiple invocations of this function will return the same value, so it can +// be used for equality checks and switch statements. +// +// ScalarMult and ScalarBaseMult are implemented using constant-time algorithms. +func P256() Curve { + initonce.Do(initAll) + return p256 +} + +// P384 returns a Curve which implements NIST P-384 (FIPS 186-3, section D.2.4), +// also known as secp384r1. The CurveParams.Name of this Curve is "P-384". +// +// Multiple invocations of this function will return the same value, so it can +// be used for equality checks and switch statements. +// +// The cryptographic operations do not use constant-time algorithms. +func P384() Curve { + initonce.Do(initAll) + return p384 +} + +// P521 returns a Curve which implements NIST P-521 (FIPS 186-3, section D.2.5), +// also known as secp521r1. The CurveParams.Name of this Curve is "P-521". +// +// Multiple invocations of this function will return the same value, so it can +// be used for equality checks and switch statements. +// +// The cryptographic operations are implemented using constant-time algorithms. +func P521() Curve { + initonce.Do(initAll) + return p521 +} diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go new file mode 100644 index 0000000..3fe53c5 --- /dev/null +++ b/src/crypto/elliptic/elliptic_test.go @@ -0,0 +1,331 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "math/big" + "testing" +) + +// genericParamsForCurve returns the dereferenced CurveParams for +// the specified curve. This is used to avoid the logic for +// upgrading a curve to it's specific implementation, forcing +// usage of the generic implementation. This is only relevant +// for the P224, P256, and P521 curves. +func genericParamsForCurve(c Curve) *CurveParams { + d := *(c.Params()) + return &d +} + +func testAllCurves(t *testing.T, f func(*testing.T, Curve)) { + tests := []struct { + name string + curve Curve + }{ + {"P256", P256()}, + {"P256/Params", genericParamsForCurve(P256())}, + {"P224", P224()}, + {"P224/Params", genericParamsForCurve(P224())}, + {"P384", P384()}, + {"P384/Params", genericParamsForCurve(P384())}, + {"P521", P521()}, + {"P521/Params", genericParamsForCurve(P521())}, + } + if testing.Short() { + tests = tests[:1] + } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.T) { + t.Parallel() + f(t, curve) + }) + } +} + +func TestOnCurve(t *testing.T) { + testAllCurves(t, func(t *testing.T, curve Curve) { + if !curve.IsOnCurve(curve.Params().Gx, curve.Params().Gy) { + t.Error("basepoint is not on the curve") + } + }) +} + +func TestOffCurve(t *testing.T) { + testAllCurves(t, func(t *testing.T, curve Curve) { + x, y := new(big.Int).SetInt64(1), new(big.Int).SetInt64(1) + if curve.IsOnCurve(x, y) { + t.Errorf("point off curve is claimed to be on the curve") + } + b := Marshal(curve, x, y) + x1, y1 := Unmarshal(curve, b) + if x1 != nil || y1 != nil { + t.Errorf("unmarshaling a point not on the curve succeeded") + } + }) +} + +func TestInfinity(t *testing.T) { + testAllCurves(t, testInfinity) +} + +func testInfinity(t *testing.T, curve Curve) { + _, x, y, _ := GenerateKey(curve, rand.Reader) + x, y = curve.ScalarMult(x, y, curve.Params().N.Bytes()) + if x.Sign() != 0 || y.Sign() != 0 { + t.Errorf("x^q != ∞") + } + + x, y = curve.ScalarBaseMult([]byte{0}) + if x.Sign() != 0 || y.Sign() != 0 { + t.Errorf("b^0 != ∞") + x.SetInt64(0) + y.SetInt64(0) + } + + x2, y2 := curve.Double(x, y) + if x2.Sign() != 0 || y2.Sign() != 0 { + t.Errorf("2∞ != ∞") + } + + baseX := curve.Params().Gx + baseY := curve.Params().Gy + + x3, y3 := curve.Add(baseX, baseY, x, y) + if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 { + t.Errorf("x+∞ != x") + } + + x4, y4 := curve.Add(x, y, baseX, baseY) + if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 { + t.Errorf("∞+x != x") + } + + if curve.IsOnCurve(x, y) { + t.Errorf("IsOnCurve(∞) == true") + } +} + +func TestMarshal(t *testing.T) { + testAllCurves(t, func(t *testing.T, curve Curve) { + _, x, y, err := GenerateKey(curve, rand.Reader) + if err != nil { + t.Fatal(err) + } + serialized := Marshal(curve, x, y) + xx, yy := Unmarshal(curve, serialized) + if xx == nil { + t.Fatal("failed to unmarshal") + } + if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 { + t.Fatal("unmarshal returned different values") + } + }) +} + +func TestUnmarshalToLargeCoordinates(t *testing.T) { + // See https://golang.org/issues/20482. + testAllCurves(t, testUnmarshalToLargeCoordinates) +} + +func testUnmarshalToLargeCoordinates(t *testing.T, curve Curve) { + p := curve.Params().P + byteLen := (p.BitLen() + 7) / 8 + + // Set x to be greater than curve's parameter P – specifically, to P+5. + // Set y to mod_sqrt(x^3 - 3x + B)) so that (x mod P = 5 , y) is on the + // curve. + x := new(big.Int).Add(p, big.NewInt(5)) + y := curve.Params().polynomial(x) + y.ModSqrt(y, p) + + invalid := make([]byte, byteLen*2+1) + invalid[0] = 4 // uncompressed encoding + x.FillBytes(invalid[1 : 1+byteLen]) + y.FillBytes(invalid[1+byteLen:]) + + if X, Y := Unmarshal(curve, invalid); X != nil || Y != nil { + t.Errorf("Unmarshal accepts invalid X coordinate") + } + + if curve == p256 { + // This is a point on the curve with a small y value, small enough that + // we can add p and still be within 32 bytes. + x, _ = new(big.Int).SetString("31931927535157963707678568152204072984517581467226068221761862915403492091210", 10) + y, _ = new(big.Int).SetString("5208467867388784005506817585327037698770365050895731383201516607147", 10) + y.Add(y, p) + + if p.Cmp(y) > 0 || y.BitLen() != 256 { + t.Fatal("y not within expected range") + } + + // marshal + x.FillBytes(invalid[1 : 1+byteLen]) + y.FillBytes(invalid[1+byteLen:]) + + if X, Y := Unmarshal(curve, invalid); X != nil || Y != nil { + t.Errorf("Unmarshal accepts invalid Y coordinate") + } + } +} + +// TestInvalidCoordinates tests big.Int values that are not valid field elements +// (negative or bigger than P). They are expected to return false from +// IsOnCurve, all other behavior is undefined. +func TestInvalidCoordinates(t *testing.T) { + testAllCurves(t, testInvalidCoordinates) +} + +func testInvalidCoordinates(t *testing.T, curve Curve) { + checkIsOnCurveFalse := func(name string, x, y *big.Int) { + if curve.IsOnCurve(x, y) { + t.Errorf("IsOnCurve(%s) unexpectedly returned true", name) + } + } + + p := curve.Params().P + _, x, y, _ := GenerateKey(curve, rand.Reader) + xx, yy := new(big.Int), new(big.Int) + + // Check if the sign is getting dropped. + xx.Neg(x) + checkIsOnCurveFalse("-x, y", xx, y) + yy.Neg(y) + checkIsOnCurveFalse("x, -y", x, yy) + + // Check if negative values are reduced modulo P. + xx.Sub(x, p) + checkIsOnCurveFalse("x-P, y", xx, y) + yy.Sub(y, p) + checkIsOnCurveFalse("x, y-P", x, yy) + + // Check if positive values are reduced modulo P. + xx.Add(x, p) + checkIsOnCurveFalse("x+P, y", xx, y) + yy.Add(y, p) + checkIsOnCurveFalse("x, y+P", x, yy) + + // Check if the overflow is dropped. + xx.Add(x, new(big.Int).Lsh(big.NewInt(1), 535)) + checkIsOnCurveFalse("x+2⁵³⁵, y", xx, y) + yy.Add(y, new(big.Int).Lsh(big.NewInt(1), 535)) + checkIsOnCurveFalse("x, y+2⁵³⁵", x, yy) + + // Check if P is treated like zero (if possible). + // y^2 = x^3 - 3x + B + // y = mod_sqrt(x^3 - 3x + B) + // y = mod_sqrt(B) if x = 0 + // If there is no modsqrt, there is no point with x = 0, can't test x = P. + if yy := new(big.Int).ModSqrt(curve.Params().B, p); yy != nil { + if !curve.IsOnCurve(big.NewInt(0), yy) { + t.Fatal("(0, mod_sqrt(B)) is not on the curve?") + } + checkIsOnCurveFalse("P, y", p, yy) + } +} + +func TestMarshalCompressed(t *testing.T) { + t.Run("P-256/03", func(t *testing.T) { + data, _ := hex.DecodeString("031e3987d9f9ea9d7dd7155a56a86b2009e1e0ab332f962d10d8beb6406ab1ad79") + x, _ := new(big.Int).SetString("13671033352574878777044637384712060483119675368076128232297328793087057702265", 10) + y, _ := new(big.Int).SetString("66200849279091436748794323380043701364391950689352563629885086590854940586447", 10) + testMarshalCompressed(t, P256(), x, y, data) + }) + t.Run("P-256/02", func(t *testing.T) { + data, _ := hex.DecodeString("021e3987d9f9ea9d7dd7155a56a86b2009e1e0ab332f962d10d8beb6406ab1ad79") + x, _ := new(big.Int).SetString("13671033352574878777044637384712060483119675368076128232297328793087057702265", 10) + y, _ := new(big.Int).SetString("49591239931264812013903123569363872165694192725937750565648544718012157267504", 10) + testMarshalCompressed(t, P256(), x, y, data) + }) + + t.Run("Invalid", func(t *testing.T) { + data, _ := hex.DecodeString("02fd4bf61763b46581fd9174d623516cf3c81edd40e29ffa2777fb6cb0ae3ce535") + X, Y := UnmarshalCompressed(P256(), data) + if X != nil || Y != nil { + t.Error("expected an error for invalid encoding") + } + }) + + if testing.Short() { + t.Skip("skipping other curves on short test") + } + + testAllCurves(t, func(t *testing.T, curve Curve) { + _, x, y, err := GenerateKey(curve, rand.Reader) + if err != nil { + t.Fatal(err) + } + testMarshalCompressed(t, curve, x, y, nil) + }) + +} + +func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte) { + if !curve.IsOnCurve(x, y) { + t.Fatal("invalid test point") + } + got := MarshalCompressed(curve, x, y) + if want != nil && !bytes.Equal(got, want) { + t.Errorf("got unexpected MarshalCompressed result: got %x, want %x", got, want) + } + + X, Y := UnmarshalCompressed(curve, got) + if X == nil || Y == nil { + t.Fatalf("UnmarshalCompressed failed unexpectedly") + } + + if !curve.IsOnCurve(X, Y) { + t.Error("UnmarshalCompressed returned a point not on the curve") + } + if X.Cmp(x) != 0 || Y.Cmp(y) != 0 { + t.Errorf("point did not round-trip correctly: got (%v, %v), want (%v, %v)", X, Y, x, y) + } +} + +func benchmarkAllCurves(t *testing.B, f func(*testing.B, Curve)) { + tests := []struct { + name string + curve Curve + }{ + {"P256", P256()}, + {"P224", P224()}, + {"P384", P384()}, + {"P521", P521()}, + } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.B) { + f(t, curve) + }) + } +} + +func BenchmarkScalarBaseMult(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve Curve) { + priv, _, _, _ := GenerateKey(curve, rand.Reader) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + x, _ := curve.ScalarBaseMult(priv) + // Prevent the compiler from optimizing out the operation. + priv[0] ^= byte(x.Bits()[0]) + } + }) +} + +func BenchmarkScalarMult(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve Curve) { + _, x, y, _ := GenerateKey(curve, rand.Reader) + priv, _, _, _ := GenerateKey(curve, rand.Reader) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + x, y = curve.ScalarMult(x, y, priv) + } + }) +} diff --git a/src/crypto/elliptic/fuzz_test.go b/src/crypto/elliptic/fuzz_test.go new file mode 100644 index 0000000..8ff3bf3 --- /dev/null +++ b/src/crypto/elliptic/fuzz_test.go @@ -0,0 +1,54 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 || arm64 || ppc64le +// +build amd64 arm64 ppc64le + +package elliptic + +import ( + "crypto/rand" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + p256 := P256() + p256Generic := p256.Params() + + var scalar1 [32]byte + var scalar2 [32]byte + var timeout *time.Timer + + if testing.Short() { + timeout = time.NewTimer(10 * time.Millisecond) + } else { + timeout = time.NewTimer(2 * time.Second) + } + + for { + select { + case <-timeout.C: + return + default: + } + + rand.Read(scalar1[:]) + rand.Read(scalar2[:]) + + x, y := p256.ScalarBaseMult(scalar1[:]) + x2, y2 := p256Generic.ScalarBaseMult(scalar1[:]) + + xx, yy := p256.ScalarMult(x, y, scalar2[:]) + xx2, yy2 := p256Generic.ScalarMult(x2, y2, scalar2[:]) + + if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 { + t.Fatalf("ScalarBaseMult does not match reference result with scalar: %x, please report this error to security@golang.org", scalar1) + } + + if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 { + t.Fatalf("ScalarMult does not match reference result with scalars: %x and %x, please report this error to security@golang.org", scalar1, scalar2) + } + } +} diff --git a/src/crypto/elliptic/internal/fiat/Dockerfile b/src/crypto/elliptic/internal/fiat/Dockerfile new file mode 100644 index 0000000..7b5ece0 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/Dockerfile @@ -0,0 +1,12 @@ +# Copyright 2021 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +FROM coqorg/coq:8.13.2 + +RUN git clone https://github.com/mit-plv/fiat-crypto +RUN cd fiat-crypto && git checkout c076f3550bea2bb7f4cb5766a32594b9e67694f2 +RUN cd fiat-crypto && git submodule update --init --recursive +RUN cd fiat-crypto && eval $(opam env) && make -j4 standalone-ocaml SKIP_BEDROCK2=1 + +ENTRYPOINT ["fiat-crypto/src/ExtractionOCaml/unsaturated_solinas"] diff --git a/src/crypto/elliptic/internal/fiat/README b/src/crypto/elliptic/internal/fiat/README new file mode 100644 index 0000000..171f57a --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/README @@ -0,0 +1,39 @@ +The code in this package was autogenerated by the fiat-crypto project +at commit c076f3550 from a formally verified model. + + docker build -t fiat-crypto:c076f3550 . + docker run fiat-crypto:c076f3550 --lang Go --no-wide-int --cmovznz-by-mul \ + --internal-static --public-function-case camelCase --public-type-case camelCase \ + --private-function-case camelCase --private-type-case camelCase \ + --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' \ + --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' \ + --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' \ + carry_mul carry_square carry add sub to_bytes from_bytes selectznz \ + > p521_fiat64.go + +It comes under the following license. + + Copyright (c) 2015-2020 The fiat-crypto Authors. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, + Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The authors are listed at + + https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS diff --git a/src/crypto/elliptic/internal/fiat/p521.go b/src/crypto/elliptic/internal/fiat/p521.go new file mode 100644 index 0000000..dc67732 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p521.go @@ -0,0 +1,197 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package fiat implements prime order fields using formally verified algorithms +// from the Fiat Cryptography project. +package fiat + +import ( + "crypto/subtle" + "errors" +) + +// P521Element is an integer modulo 2^521 - 1. +// +// The zero value is a valid zero element. +type P521Element struct { + // This element has the following bounds, which are tighter than + // the output bounds of some operations. Those operations must be + // followed by a carry. + // + // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], + // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], + // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000] + x [9]uint64 +} + +// One sets e = 1, and returns e. +func (e *P521Element) One() *P521Element { + *e = P521Element{} + e.x[0] = 1 + return e +} + +// Equal returns 1 if e == t, and zero otherwise. +func (e *P521Element) Equal(t *P521Element) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} + +var p521ZeroEncoding = new(P521Element).Bytes() + +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *P521Element) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, p521ZeroEncoding) +} + +// Set sets e = t, and returns e. +func (e *P521Element) Set(t *P521Element) *P521Element { + e.x = t.x + return e +} + +// Bytes returns the 66-byte little-endian encoding of e. +func (e *P521Element) Bytes() []byte { + // This function must be inlined to move the allocation to the parent and + // save it from escaping to the heap. + var out [66]byte + p521ToBytes(&out, &e.x) + return out[:] +} + +// SetBytes sets e = v, where v is a little-endian 66-byte encoding, and returns +// e. If v is not 66 bytes or it encodes a value higher than 2^521 - 1, SetBytes +// returns nil and an error, and e is unchanged. +func (e *P521Element) SetBytes(v []byte) (*P521Element, error) { + if len(v) != 66 || v[65] > 1 { + return nil, errors.New("invalid P-521 field encoding") + } + var in [66]byte + copy(in[:], v) + p521FromBytes(&e.x, &in) + return e, nil +} + +// Add sets e = t1 + t2, and returns e. +func (e *P521Element) Add(t1, t2 *P521Element) *P521Element { + p521Add(&e.x, &t1.x, &t2.x) + p521Carry(&e.x, &e.x) + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *P521Element) Sub(t1, t2 *P521Element) *P521Element { + p521Sub(&e.x, &t1.x, &t2.x) + p521Carry(&e.x, &e.x) + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *P521Element) Mul(t1, t2 *P521Element) *P521Element { + p521CarryMul(&e.x, &t1.x, &t2.x) + return e +} + +// Square sets e = t * t, and returns e. +func (e *P521Element) Square(t *P521Element) *P521Element { + p521CarrySquare(&e.x, &t.x) + return e +} + +// Select sets e to a if cond == 1, and to b if cond == 0. +func (v *P521Element) Select(a, b *P521Element, cond int) *P521Element { + p521Selectznz(&v.x, p521Uint1(cond), &b.x, &a.x) + return v +} + +// Invert sets e = 1/t, and returns e. +// +// If t == 0, Invert returns e = 0. +func (e *P521Element) Invert(t *P521Element) *P521Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of multiplications and squarings was generated with + // github.com/mmcloughlin/addchain v0.2.0. + + var t1, t2 = new(P521Element), new(P521Element) + + // _10 = 2 * 1 + t1.Square(t) + + // _11 = 1 + _10 + t1.Mul(t, t1) + + // _1100 = _11 << 2 + t2.Square(t1) + t2.Square(t2) + + // _1111 = _11 + _1100 + t1.Mul(t1, t2) + + // _11110000 = _1111 << 4 + t2.Square(t1) + for i := 0; i < 3; i++ { + t2.Square(t2) + } + + // _11111111 = _1111 + _11110000 + t1.Mul(t1, t2) + + // x16 = _11111111<<8 + _11111111 + t2.Square(t1) + for i := 0; i < 7; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x32 = x16<<16 + x16 + t2.Square(t1) + for i := 0; i < 15; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x64 = x32<<32 + x32 + t2.Square(t1) + for i := 0; i < 31; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x65 = 2*x64 + 1 + t2.Square(t1) + t2.Mul(t2, t) + + // x129 = x65<<64 + x64 + for i := 0; i < 64; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x130 = 2*x129 + 1 + t2.Square(t1) + t2.Mul(t2, t) + + // x259 = x130<<129 + x129 + for i := 0; i < 129; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x260 = 2*x259 + 1 + t2.Square(t1) + t2.Mul(t2, t) + + // x519 = x260<<259 + x259 + for i := 0; i < 259; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // return x519<<2 + 1 + t1.Square(t1) + t1.Square(t1) + return e.Mul(t1, t) +} diff --git a/src/crypto/elliptic/internal/fiat/p521_fiat64.go b/src/crypto/elliptic/internal/fiat/p521_fiat64.go new file mode 100644 index 0000000..f86283b --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p521_fiat64.go @@ -0,0 +1,1856 @@ +// Code generated by Fiat Cryptography. DO NOT EDIT. +// +// Autogenerated: 'fiat-crypto/src/ExtractionOCaml/unsaturated_solinas' --lang Go --no-wide-int --cmovznz-by-mul --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' carry_mul carry_square carry add sub to_bytes from_bytes selectznz +// +// curve description: p521 +// +// machine_wordsize = 64 (from "64") +// +// requested operations: carry_mul, carry_square, carry, add, sub, to_bytes, from_bytes, selectznz +// +// n = 9 (from "9") +// +// s-c = 2^521 - [(1, 1)] (from "2^521 - 1") +// +// tight_bounds_multiplier = 1 (from "") +// +// +// +// Computed values: +// +// carry_chain = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1] +// +// eval z = z[0] + (z[1] << 58) + (z[2] << 116) + (z[3] << 174) + (z[4] << 232) + (z[5] << 0x122) + (z[6] << 0x15c) + (z[7] << 0x196) + (z[8] << 0x1d0) +// +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) + (z[48] << 0x180) + (z[49] << 0x188) + (z[50] << 0x190) + (z[51] << 0x198) + (z[52] << 0x1a0) + (z[53] << 0x1a8) + (z[54] << 0x1b0) + (z[55] << 0x1b8) + (z[56] << 0x1c0) + (z[57] << 0x1c8) + (z[58] << 0x1d0) + (z[59] << 0x1d8) + (z[60] << 0x1e0) + (z[61] << 0x1e8) + (z[62] << 0x1f0) + (z[63] << 0x1f8) + (z[64] << 2^9) + (z[65] << 0x208) +// +// balance = [0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x3fffffffffffffe] + +package fiat + +import "math/bits" + +type p521Uint1 uint8 +type p521Int1 int8 + +// p521AddcarryxU64 is a thin wrapper around bits.Add64 that uses p521Uint1 rather than uint64 +func p521AddcarryxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) { + sum, carryOut := bits.Add64(x, y, uint64(carry)) + return sum, p521Uint1(carryOut) +} + +// p521SubborrowxU64 is a thin wrapper around bits.Sub64 that uses p521Uint1 rather than uint64 +func p521SubborrowxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) { + sum, carryOut := bits.Sub64(x, y, uint64(carry)) + return sum, p521Uint1(carryOut) +} + +// p521AddcarryxU58 is an addition with carry. +// +// Postconditions: +// out1 = (arg1 + arg2 + arg3) mod 2^58 +// out2 = ⌊(arg1 + arg2 + arg3) / 2^58⌋ +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0x3ffffffffffffff] +// arg3: [0x0 ~> 0x3ffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0x3ffffffffffffff] +// out2: [0x0 ~> 0x1] +func p521AddcarryxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := ((uint64(arg1) + arg2) + arg3) + x2 := (x1 & 0x3ffffffffffffff) + x3 := p521Uint1((x1 >> 58)) + *out1 = x2 + *out2 = x3 +} + +// p521SubborrowxU58 is a subtraction with borrow. +// +// Postconditions: +// out1 = (-arg1 + arg2 + -arg3) mod 2^58 +// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^58⌋ +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0x3ffffffffffffff] +// arg3: [0x0 ~> 0x3ffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0x3ffffffffffffff] +// out2: [0x0 ~> 0x1] +func p521SubborrowxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := ((int64(arg2) - int64(arg1)) - int64(arg3)) + x2 := p521Int1((x1 >> 58)) + x3 := (uint64(x1) & 0x3ffffffffffffff) + *out1 = x3 + *out2 = (0x0 - p521Uint1(x2)) +} + +// p521AddcarryxU57 is an addition with carry. +// +// Postconditions: +// out1 = (arg1 + arg2 + arg3) mod 2^57 +// out2 = ⌊(arg1 + arg2 + arg3) / 2^57⌋ +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0x1ffffffffffffff] +// arg3: [0x0 ~> 0x1ffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0x1ffffffffffffff] +// out2: [0x0 ~> 0x1] +func p521AddcarryxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := ((uint64(arg1) + arg2) + arg3) + x2 := (x1 & 0x1ffffffffffffff) + x3 := p521Uint1((x1 >> 57)) + *out1 = x2 + *out2 = x3 +} + +// p521SubborrowxU57 is a subtraction with borrow. +// +// Postconditions: +// out1 = (-arg1 + arg2 + -arg3) mod 2^57 +// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^57⌋ +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0x1ffffffffffffff] +// arg3: [0x0 ~> 0x1ffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0x1ffffffffffffff] +// out2: [0x0 ~> 0x1] +func p521SubborrowxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := ((int64(arg2) - int64(arg1)) - int64(arg3)) + x2 := p521Int1((x1 >> 57)) + x3 := (uint64(x1) & 0x1ffffffffffffff) + *out1 = x3 + *out2 = (0x0 - p521Uint1(x2)) +} + +// p521CmovznzU64 is a single-word conditional move. +// +// Postconditions: +// out1 = (if arg1 = 0 then arg2 else arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0xffffffffffffffff] +// arg3: [0x0 ~> 0xffffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0xffffffffffffffff] +func p521CmovznzU64(out1 *uint64, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// p521CarryMul multiplies two field elements and reduces the result. +// +// Postconditions: +// eval out1 mod m = (eval arg1 * eval arg2) mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +// arg2: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +func p521CarryMul(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { + var x1 uint64 + var x2 uint64 + x2, x1 = bits.Mul64(arg1[8], (arg2[8] * 0x2)) + var x3 uint64 + var x4 uint64 + x4, x3 = bits.Mul64(arg1[8], (arg2[7] * 0x2)) + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(arg1[8], (arg2[6] * 0x2)) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(arg1[8], (arg2[5] * 0x2)) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(arg1[8], (arg2[4] * 0x2)) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(arg1[8], (arg2[3] * 0x2)) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(arg1[8], (arg2[2] * 0x2)) + var x15 uint64 + var x16 uint64 + x16, x15 = bits.Mul64(arg1[8], (arg2[1] * 0x2)) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(arg1[7], (arg2[8] * 0x2)) + var x19 uint64 + var x20 uint64 + x20, x19 = bits.Mul64(arg1[7], (arg2[7] * 0x2)) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(arg1[7], (arg2[6] * 0x2)) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(arg1[7], (arg2[5] * 0x2)) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(arg1[7], (arg2[4] * 0x2)) + var x27 uint64 + var x28 uint64 + x28, x27 = bits.Mul64(arg1[7], (arg2[3] * 0x2)) + var x29 uint64 + var x30 uint64 + x30, x29 = bits.Mul64(arg1[7], (arg2[2] * 0x2)) + var x31 uint64 + var x32 uint64 + x32, x31 = bits.Mul64(arg1[6], (arg2[8] * 0x2)) + var x33 uint64 + var x34 uint64 + x34, x33 = bits.Mul64(arg1[6], (arg2[7] * 0x2)) + var x35 uint64 + var x36 uint64 + x36, x35 = bits.Mul64(arg1[6], (arg2[6] * 0x2)) + var x37 uint64 + var x38 uint64 + x38, x37 = bits.Mul64(arg1[6], (arg2[5] * 0x2)) + var x39 uint64 + var x40 uint64 + x40, x39 = bits.Mul64(arg1[6], (arg2[4] * 0x2)) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(arg1[6], (arg2[3] * 0x2)) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(arg1[5], (arg2[8] * 0x2)) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(arg1[5], (arg2[7] * 0x2)) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(arg1[5], (arg2[6] * 0x2)) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(arg1[5], (arg2[5] * 0x2)) + var x51 uint64 + var x52 uint64 + x52, x51 = bits.Mul64(arg1[5], (arg2[4] * 0x2)) + var x53 uint64 + var x54 uint64 + x54, x53 = bits.Mul64(arg1[4], (arg2[8] * 0x2)) + var x55 uint64 + var x56 uint64 + x56, x55 = bits.Mul64(arg1[4], (arg2[7] * 0x2)) + var x57 uint64 + var x58 uint64 + x58, x57 = bits.Mul64(arg1[4], (arg2[6] * 0x2)) + var x59 uint64 + var x60 uint64 + x60, x59 = bits.Mul64(arg1[4], (arg2[5] * 0x2)) + var x61 uint64 + var x62 uint64 + x62, x61 = bits.Mul64(arg1[3], (arg2[8] * 0x2)) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(arg1[3], (arg2[7] * 0x2)) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(arg1[3], (arg2[6] * 0x2)) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(arg1[2], (arg2[8] * 0x2)) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(arg1[2], (arg2[7] * 0x2)) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(arg1[1], (arg2[8] * 0x2)) + var x73 uint64 + var x74 uint64 + x74, x73 = bits.Mul64(arg1[8], arg2[0]) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(arg1[7], arg2[1]) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(arg1[7], arg2[0]) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(arg1[6], arg2[2]) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(arg1[6], arg2[1]) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(arg1[6], arg2[0]) + var x85 uint64 + var x86 uint64 + x86, x85 = bits.Mul64(arg1[5], arg2[3]) + var x87 uint64 + var x88 uint64 + x88, x87 = bits.Mul64(arg1[5], arg2[2]) + var x89 uint64 + var x90 uint64 + x90, x89 = bits.Mul64(arg1[5], arg2[1]) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(arg1[5], arg2[0]) + var x93 uint64 + var x94 uint64 + x94, x93 = bits.Mul64(arg1[4], arg2[4]) + var x95 uint64 + var x96 uint64 + x96, x95 = bits.Mul64(arg1[4], arg2[3]) + var x97 uint64 + var x98 uint64 + x98, x97 = bits.Mul64(arg1[4], arg2[2]) + var x99 uint64 + var x100 uint64 + x100, x99 = bits.Mul64(arg1[4], arg2[1]) + var x101 uint64 + var x102 uint64 + x102, x101 = bits.Mul64(arg1[4], arg2[0]) + var x103 uint64 + var x104 uint64 + x104, x103 = bits.Mul64(arg1[3], arg2[5]) + var x105 uint64 + var x106 uint64 + x106, x105 = bits.Mul64(arg1[3], arg2[4]) + var x107 uint64 + var x108 uint64 + x108, x107 = bits.Mul64(arg1[3], arg2[3]) + var x109 uint64 + var x110 uint64 + x110, x109 = bits.Mul64(arg1[3], arg2[2]) + var x111 uint64 + var x112 uint64 + x112, x111 = bits.Mul64(arg1[3], arg2[1]) + var x113 uint64 + var x114 uint64 + x114, x113 = bits.Mul64(arg1[3], arg2[0]) + var x115 uint64 + var x116 uint64 + x116, x115 = bits.Mul64(arg1[2], arg2[6]) + var x117 uint64 + var x118 uint64 + x118, x117 = bits.Mul64(arg1[2], arg2[5]) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(arg1[2], arg2[4]) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(arg1[2], arg2[3]) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(arg1[2], arg2[2]) + var x125 uint64 + var x126 uint64 + x126, x125 = bits.Mul64(arg1[2], arg2[1]) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(arg1[2], arg2[0]) + var x129 uint64 + var x130 uint64 + x130, x129 = bits.Mul64(arg1[1], arg2[7]) + var x131 uint64 + var x132 uint64 + x132, x131 = bits.Mul64(arg1[1], arg2[6]) + var x133 uint64 + var x134 uint64 + x134, x133 = bits.Mul64(arg1[1], arg2[5]) + var x135 uint64 + var x136 uint64 + x136, x135 = bits.Mul64(arg1[1], arg2[4]) + var x137 uint64 + var x138 uint64 + x138, x137 = bits.Mul64(arg1[1], arg2[3]) + var x139 uint64 + var x140 uint64 + x140, x139 = bits.Mul64(arg1[1], arg2[2]) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(arg1[1], arg2[1]) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(arg1[1], arg2[0]) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(arg1[0], arg2[8]) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(arg1[0], arg2[7]) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(arg1[0], arg2[6]) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(arg1[0], arg2[5]) + var x153 uint64 + var x154 uint64 + x154, x153 = bits.Mul64(arg1[0], arg2[4]) + var x155 uint64 + var x156 uint64 + x156, x155 = bits.Mul64(arg1[0], arg2[3]) + var x157 uint64 + var x158 uint64 + x158, x157 = bits.Mul64(arg1[0], arg2[2]) + var x159 uint64 + var x160 uint64 + x160, x159 = bits.Mul64(arg1[0], arg2[1]) + var x161 uint64 + var x162 uint64 + x162, x161 = bits.Mul64(arg1[0], arg2[0]) + var x163 uint64 + var x164 p521Uint1 + x163, x164 = p521AddcarryxU64(x29, x15, 0x0) + var x165 uint64 + x165, _ = p521AddcarryxU64(x30, x16, x164) + var x167 uint64 + var x168 p521Uint1 + x167, x168 = p521AddcarryxU64(x41, x163, 0x0) + var x169 uint64 + x169, _ = p521AddcarryxU64(x42, x165, x168) + var x171 uint64 + var x172 p521Uint1 + x171, x172 = p521AddcarryxU64(x51, x167, 0x0) + var x173 uint64 + x173, _ = p521AddcarryxU64(x52, x169, x172) + var x175 uint64 + var x176 p521Uint1 + x175, x176 = p521AddcarryxU64(x59, x171, 0x0) + var x177 uint64 + x177, _ = p521AddcarryxU64(x60, x173, x176) + var x179 uint64 + var x180 p521Uint1 + x179, x180 = p521AddcarryxU64(x65, x175, 0x0) + var x181 uint64 + x181, _ = p521AddcarryxU64(x66, x177, x180) + var x183 uint64 + var x184 p521Uint1 + x183, x184 = p521AddcarryxU64(x69, x179, 0x0) + var x185 uint64 + x185, _ = p521AddcarryxU64(x70, x181, x184) + var x187 uint64 + var x188 p521Uint1 + x187, x188 = p521AddcarryxU64(x71, x183, 0x0) + var x189 uint64 + x189, _ = p521AddcarryxU64(x72, x185, x188) + var x191 uint64 + var x192 p521Uint1 + x191, x192 = p521AddcarryxU64(x161, x187, 0x0) + var x193 uint64 + x193, _ = p521AddcarryxU64(x162, x189, x192) + x195 := ((x191 >> 58) | ((x193 << 6) & 0xffffffffffffffff)) + x196 := (x193 >> 58) + x197 := (x191 & 0x3ffffffffffffff) + var x198 uint64 + var x199 p521Uint1 + x198, x199 = p521AddcarryxU64(x75, x73, 0x0) + var x200 uint64 + x200, _ = p521AddcarryxU64(x76, x74, x199) + var x202 uint64 + var x203 p521Uint1 + x202, x203 = p521AddcarryxU64(x79, x198, 0x0) + var x204 uint64 + x204, _ = p521AddcarryxU64(x80, x200, x203) + var x206 uint64 + var x207 p521Uint1 + x206, x207 = p521AddcarryxU64(x85, x202, 0x0) + var x208 uint64 + x208, _ = p521AddcarryxU64(x86, x204, x207) + var x210 uint64 + var x211 p521Uint1 + x210, x211 = p521AddcarryxU64(x93, x206, 0x0) + var x212 uint64 + x212, _ = p521AddcarryxU64(x94, x208, x211) + var x214 uint64 + var x215 p521Uint1 + x214, x215 = p521AddcarryxU64(x103, x210, 0x0) + var x216 uint64 + x216, _ = p521AddcarryxU64(x104, x212, x215) + var x218 uint64 + var x219 p521Uint1 + x218, x219 = p521AddcarryxU64(x115, x214, 0x0) + var x220 uint64 + x220, _ = p521AddcarryxU64(x116, x216, x219) + var x222 uint64 + var x223 p521Uint1 + x222, x223 = p521AddcarryxU64(x129, x218, 0x0) + var x224 uint64 + x224, _ = p521AddcarryxU64(x130, x220, x223) + var x226 uint64 + var x227 p521Uint1 + x226, x227 = p521AddcarryxU64(x145, x222, 0x0) + var x228 uint64 + x228, _ = p521AddcarryxU64(x146, x224, x227) + var x230 uint64 + var x231 p521Uint1 + x230, x231 = p521AddcarryxU64(x77, x1, 0x0) + var x232 uint64 + x232, _ = p521AddcarryxU64(x78, x2, x231) + var x234 uint64 + var x235 p521Uint1 + x234, x235 = p521AddcarryxU64(x81, x230, 0x0) + var x236 uint64 + x236, _ = p521AddcarryxU64(x82, x232, x235) + var x238 uint64 + var x239 p521Uint1 + x238, x239 = p521AddcarryxU64(x87, x234, 0x0) + var x240 uint64 + x240, _ = p521AddcarryxU64(x88, x236, x239) + var x242 uint64 + var x243 p521Uint1 + x242, x243 = p521AddcarryxU64(x95, x238, 0x0) + var x244 uint64 + x244, _ = p521AddcarryxU64(x96, x240, x243) + var x246 uint64 + var x247 p521Uint1 + x246, x247 = p521AddcarryxU64(x105, x242, 0x0) + var x248 uint64 + x248, _ = p521AddcarryxU64(x106, x244, x247) + var x250 uint64 + var x251 p521Uint1 + x250, x251 = p521AddcarryxU64(x117, x246, 0x0) + var x252 uint64 + x252, _ = p521AddcarryxU64(x118, x248, x251) + var x254 uint64 + var x255 p521Uint1 + x254, x255 = p521AddcarryxU64(x131, x250, 0x0) + var x256 uint64 + x256, _ = p521AddcarryxU64(x132, x252, x255) + var x258 uint64 + var x259 p521Uint1 + x258, x259 = p521AddcarryxU64(x147, x254, 0x0) + var x260 uint64 + x260, _ = p521AddcarryxU64(x148, x256, x259) + var x262 uint64 + var x263 p521Uint1 + x262, x263 = p521AddcarryxU64(x17, x3, 0x0) + var x264 uint64 + x264, _ = p521AddcarryxU64(x18, x4, x263) + var x266 uint64 + var x267 p521Uint1 + x266, x267 = p521AddcarryxU64(x83, x262, 0x0) + var x268 uint64 + x268, _ = p521AddcarryxU64(x84, x264, x267) + var x270 uint64 + var x271 p521Uint1 + x270, x271 = p521AddcarryxU64(x89, x266, 0x0) + var x272 uint64 + x272, _ = p521AddcarryxU64(x90, x268, x271) + var x274 uint64 + var x275 p521Uint1 + x274, x275 = p521AddcarryxU64(x97, x270, 0x0) + var x276 uint64 + x276, _ = p521AddcarryxU64(x98, x272, x275) + var x278 uint64 + var x279 p521Uint1 + x278, x279 = p521AddcarryxU64(x107, x274, 0x0) + var x280 uint64 + x280, _ = p521AddcarryxU64(x108, x276, x279) + var x282 uint64 + var x283 p521Uint1 + x282, x283 = p521AddcarryxU64(x119, x278, 0x0) + var x284 uint64 + x284, _ = p521AddcarryxU64(x120, x280, x283) + var x286 uint64 + var x287 p521Uint1 + x286, x287 = p521AddcarryxU64(x133, x282, 0x0) + var x288 uint64 + x288, _ = p521AddcarryxU64(x134, x284, x287) + var x290 uint64 + var x291 p521Uint1 + x290, x291 = p521AddcarryxU64(x149, x286, 0x0) + var x292 uint64 + x292, _ = p521AddcarryxU64(x150, x288, x291) + var x294 uint64 + var x295 p521Uint1 + x294, x295 = p521AddcarryxU64(x19, x5, 0x0) + var x296 uint64 + x296, _ = p521AddcarryxU64(x20, x6, x295) + var x298 uint64 + var x299 p521Uint1 + x298, x299 = p521AddcarryxU64(x31, x294, 0x0) + var x300 uint64 + x300, _ = p521AddcarryxU64(x32, x296, x299) + var x302 uint64 + var x303 p521Uint1 + x302, x303 = p521AddcarryxU64(x91, x298, 0x0) + var x304 uint64 + x304, _ = p521AddcarryxU64(x92, x300, x303) + var x306 uint64 + var x307 p521Uint1 + x306, x307 = p521AddcarryxU64(x99, x302, 0x0) + var x308 uint64 + x308, _ = p521AddcarryxU64(x100, x304, x307) + var x310 uint64 + var x311 p521Uint1 + x310, x311 = p521AddcarryxU64(x109, x306, 0x0) + var x312 uint64 + x312, _ = p521AddcarryxU64(x110, x308, x311) + var x314 uint64 + var x315 p521Uint1 + x314, x315 = p521AddcarryxU64(x121, x310, 0x0) + var x316 uint64 + x316, _ = p521AddcarryxU64(x122, x312, x315) + var x318 uint64 + var x319 p521Uint1 + x318, x319 = p521AddcarryxU64(x135, x314, 0x0) + var x320 uint64 + x320, _ = p521AddcarryxU64(x136, x316, x319) + var x322 uint64 + var x323 p521Uint1 + x322, x323 = p521AddcarryxU64(x151, x318, 0x0) + var x324 uint64 + x324, _ = p521AddcarryxU64(x152, x320, x323) + var x326 uint64 + var x327 p521Uint1 + x326, x327 = p521AddcarryxU64(x21, x7, 0x0) + var x328 uint64 + x328, _ = p521AddcarryxU64(x22, x8, x327) + var x330 uint64 + var x331 p521Uint1 + x330, x331 = p521AddcarryxU64(x33, x326, 0x0) + var x332 uint64 + x332, _ = p521AddcarryxU64(x34, x328, x331) + var x334 uint64 + var x335 p521Uint1 + x334, x335 = p521AddcarryxU64(x43, x330, 0x0) + var x336 uint64 + x336, _ = p521AddcarryxU64(x44, x332, x335) + var x338 uint64 + var x339 p521Uint1 + x338, x339 = p521AddcarryxU64(x101, x334, 0x0) + var x340 uint64 + x340, _ = p521AddcarryxU64(x102, x336, x339) + var x342 uint64 + var x343 p521Uint1 + x342, x343 = p521AddcarryxU64(x111, x338, 0x0) + var x344 uint64 + x344, _ = p521AddcarryxU64(x112, x340, x343) + var x346 uint64 + var x347 p521Uint1 + x346, x347 = p521AddcarryxU64(x123, x342, 0x0) + var x348 uint64 + x348, _ = p521AddcarryxU64(x124, x344, x347) + var x350 uint64 + var x351 p521Uint1 + x350, x351 = p521AddcarryxU64(x137, x346, 0x0) + var x352 uint64 + x352, _ = p521AddcarryxU64(x138, x348, x351) + var x354 uint64 + var x355 p521Uint1 + x354, x355 = p521AddcarryxU64(x153, x350, 0x0) + var x356 uint64 + x356, _ = p521AddcarryxU64(x154, x352, x355) + var x358 uint64 + var x359 p521Uint1 + x358, x359 = p521AddcarryxU64(x23, x9, 0x0) + var x360 uint64 + x360, _ = p521AddcarryxU64(x24, x10, x359) + var x362 uint64 + var x363 p521Uint1 + x362, x363 = p521AddcarryxU64(x35, x358, 0x0) + var x364 uint64 + x364, _ = p521AddcarryxU64(x36, x360, x363) + var x366 uint64 + var x367 p521Uint1 + x366, x367 = p521AddcarryxU64(x45, x362, 0x0) + var x368 uint64 + x368, _ = p521AddcarryxU64(x46, x364, x367) + var x370 uint64 + var x371 p521Uint1 + x370, x371 = p521AddcarryxU64(x53, x366, 0x0) + var x372 uint64 + x372, _ = p521AddcarryxU64(x54, x368, x371) + var x374 uint64 + var x375 p521Uint1 + x374, x375 = p521AddcarryxU64(x113, x370, 0x0) + var x376 uint64 + x376, _ = p521AddcarryxU64(x114, x372, x375) + var x378 uint64 + var x379 p521Uint1 + x378, x379 = p521AddcarryxU64(x125, x374, 0x0) + var x380 uint64 + x380, _ = p521AddcarryxU64(x126, x376, x379) + var x382 uint64 + var x383 p521Uint1 + x382, x383 = p521AddcarryxU64(x139, x378, 0x0) + var x384 uint64 + x384, _ = p521AddcarryxU64(x140, x380, x383) + var x386 uint64 + var x387 p521Uint1 + x386, x387 = p521AddcarryxU64(x155, x382, 0x0) + var x388 uint64 + x388, _ = p521AddcarryxU64(x156, x384, x387) + var x390 uint64 + var x391 p521Uint1 + x390, x391 = p521AddcarryxU64(x25, x11, 0x0) + var x392 uint64 + x392, _ = p521AddcarryxU64(x26, x12, x391) + var x394 uint64 + var x395 p521Uint1 + x394, x395 = p521AddcarryxU64(x37, x390, 0x0) + var x396 uint64 + x396, _ = p521AddcarryxU64(x38, x392, x395) + var x398 uint64 + var x399 p521Uint1 + x398, x399 = p521AddcarryxU64(x47, x394, 0x0) + var x400 uint64 + x400, _ = p521AddcarryxU64(x48, x396, x399) + var x402 uint64 + var x403 p521Uint1 + x402, x403 = p521AddcarryxU64(x55, x398, 0x0) + var x404 uint64 + x404, _ = p521AddcarryxU64(x56, x400, x403) + var x406 uint64 + var x407 p521Uint1 + x406, x407 = p521AddcarryxU64(x61, x402, 0x0) + var x408 uint64 + x408, _ = p521AddcarryxU64(x62, x404, x407) + var x410 uint64 + var x411 p521Uint1 + x410, x411 = p521AddcarryxU64(x127, x406, 0x0) + var x412 uint64 + x412, _ = p521AddcarryxU64(x128, x408, x411) + var x414 uint64 + var x415 p521Uint1 + x414, x415 = p521AddcarryxU64(x141, x410, 0x0) + var x416 uint64 + x416, _ = p521AddcarryxU64(x142, x412, x415) + var x418 uint64 + var x419 p521Uint1 + x418, x419 = p521AddcarryxU64(x157, x414, 0x0) + var x420 uint64 + x420, _ = p521AddcarryxU64(x158, x416, x419) + var x422 uint64 + var x423 p521Uint1 + x422, x423 = p521AddcarryxU64(x27, x13, 0x0) + var x424 uint64 + x424, _ = p521AddcarryxU64(x28, x14, x423) + var x426 uint64 + var x427 p521Uint1 + x426, x427 = p521AddcarryxU64(x39, x422, 0x0) + var x428 uint64 + x428, _ = p521AddcarryxU64(x40, x424, x427) + var x430 uint64 + var x431 p521Uint1 + x430, x431 = p521AddcarryxU64(x49, x426, 0x0) + var x432 uint64 + x432, _ = p521AddcarryxU64(x50, x428, x431) + var x434 uint64 + var x435 p521Uint1 + x434, x435 = p521AddcarryxU64(x57, x430, 0x0) + var x436 uint64 + x436, _ = p521AddcarryxU64(x58, x432, x435) + var x438 uint64 + var x439 p521Uint1 + x438, x439 = p521AddcarryxU64(x63, x434, 0x0) + var x440 uint64 + x440, _ = p521AddcarryxU64(x64, x436, x439) + var x442 uint64 + var x443 p521Uint1 + x442, x443 = p521AddcarryxU64(x67, x438, 0x0) + var x444 uint64 + x444, _ = p521AddcarryxU64(x68, x440, x443) + var x446 uint64 + var x447 p521Uint1 + x446, x447 = p521AddcarryxU64(x143, x442, 0x0) + var x448 uint64 + x448, _ = p521AddcarryxU64(x144, x444, x447) + var x450 uint64 + var x451 p521Uint1 + x450, x451 = p521AddcarryxU64(x159, x446, 0x0) + var x452 uint64 + x452, _ = p521AddcarryxU64(x160, x448, x451) + var x454 uint64 + var x455 p521Uint1 + x454, x455 = p521AddcarryxU64(x195, x450, 0x0) + var x456 uint64 + x456, _ = p521AddcarryxU64(x196, x452, x455) + x458 := ((x454 >> 58) | ((x456 << 6) & 0xffffffffffffffff)) + x459 := (x456 >> 58) + x460 := (x454 & 0x3ffffffffffffff) + var x461 uint64 + var x462 p521Uint1 + x461, x462 = p521AddcarryxU64(x458, x418, 0x0) + var x463 uint64 + x463, _ = p521AddcarryxU64(x459, x420, x462) + x465 := ((x461 >> 58) | ((x463 << 6) & 0xffffffffffffffff)) + x466 := (x463 >> 58) + x467 := (x461 & 0x3ffffffffffffff) + var x468 uint64 + var x469 p521Uint1 + x468, x469 = p521AddcarryxU64(x465, x386, 0x0) + var x470 uint64 + x470, _ = p521AddcarryxU64(x466, x388, x469) + x472 := ((x468 >> 58) | ((x470 << 6) & 0xffffffffffffffff)) + x473 := (x470 >> 58) + x474 := (x468 & 0x3ffffffffffffff) + var x475 uint64 + var x476 p521Uint1 + x475, x476 = p521AddcarryxU64(x472, x354, 0x0) + var x477 uint64 + x477, _ = p521AddcarryxU64(x473, x356, x476) + x479 := ((x475 >> 58) | ((x477 << 6) & 0xffffffffffffffff)) + x480 := (x477 >> 58) + x481 := (x475 & 0x3ffffffffffffff) + var x482 uint64 + var x483 p521Uint1 + x482, x483 = p521AddcarryxU64(x479, x322, 0x0) + var x484 uint64 + x484, _ = p521AddcarryxU64(x480, x324, x483) + x486 := ((x482 >> 58) | ((x484 << 6) & 0xffffffffffffffff)) + x487 := (x484 >> 58) + x488 := (x482 & 0x3ffffffffffffff) + var x489 uint64 + var x490 p521Uint1 + x489, x490 = p521AddcarryxU64(x486, x290, 0x0) + var x491 uint64 + x491, _ = p521AddcarryxU64(x487, x292, x490) + x493 := ((x489 >> 58) | ((x491 << 6) & 0xffffffffffffffff)) + x494 := (x491 >> 58) + x495 := (x489 & 0x3ffffffffffffff) + var x496 uint64 + var x497 p521Uint1 + x496, x497 = p521AddcarryxU64(x493, x258, 0x0) + var x498 uint64 + x498, _ = p521AddcarryxU64(x494, x260, x497) + x500 := ((x496 >> 58) | ((x498 << 6) & 0xffffffffffffffff)) + x501 := (x498 >> 58) + x502 := (x496 & 0x3ffffffffffffff) + var x503 uint64 + var x504 p521Uint1 + x503, x504 = p521AddcarryxU64(x500, x226, 0x0) + var x505 uint64 + x505, _ = p521AddcarryxU64(x501, x228, x504) + x507 := ((x503 >> 57) | ((x505 << 7) & 0xffffffffffffffff)) + x508 := (x505 >> 57) + x509 := (x503 & 0x1ffffffffffffff) + var x510 uint64 + var x511 p521Uint1 + x510, x511 = p521AddcarryxU64(x197, x507, 0x0) + x512 := (uint64(x511) + x508) + x513 := ((x510 >> 58) | ((x512 << 6) & 0xffffffffffffffff)) + x514 := (x510 & 0x3ffffffffffffff) + x515 := (x513 + x460) + x516 := p521Uint1((x515 >> 58)) + x517 := (x515 & 0x3ffffffffffffff) + x518 := (uint64(x516) + x467) + out1[0] = x514 + out1[1] = x517 + out1[2] = x518 + out1[3] = x474 + out1[4] = x481 + out1[5] = x488 + out1[6] = x495 + out1[7] = x502 + out1[8] = x509 +} + +// p521CarrySquare squares a field element and reduces the result. +// +// Postconditions: +// eval out1 mod m = (eval arg1 * eval arg1) mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +func p521CarrySquare(out1 *[9]uint64, arg1 *[9]uint64) { + x1 := arg1[8] + x2 := (x1 * 0x2) + x3 := (arg1[8] * 0x2) + x4 := arg1[7] + x5 := (x4 * 0x2) + x6 := (arg1[7] * 0x2) + x7 := arg1[6] + x8 := (x7 * 0x2) + x9 := (arg1[6] * 0x2) + x10 := arg1[5] + x11 := (x10 * 0x2) + x12 := (arg1[5] * 0x2) + x13 := (arg1[4] * 0x2) + x14 := (arg1[3] * 0x2) + x15 := (arg1[2] * 0x2) + x16 := (arg1[1] * 0x2) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(arg1[8], (x1 * 0x2)) + var x19 uint64 + var x20 uint64 + x20, x19 = bits.Mul64(arg1[7], (x2 * 0x2)) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(arg1[7], (x4 * 0x2)) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(arg1[6], (x2 * 0x2)) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(arg1[6], (x5 * 0x2)) + var x27 uint64 + var x28 uint64 + x28, x27 = bits.Mul64(arg1[6], (x7 * 0x2)) + var x29 uint64 + var x30 uint64 + x30, x29 = bits.Mul64(arg1[5], (x2 * 0x2)) + var x31 uint64 + var x32 uint64 + x32, x31 = bits.Mul64(arg1[5], (x5 * 0x2)) + var x33 uint64 + var x34 uint64 + x34, x33 = bits.Mul64(arg1[5], (x8 * 0x2)) + var x35 uint64 + var x36 uint64 + x36, x35 = bits.Mul64(arg1[5], (x10 * 0x2)) + var x37 uint64 + var x38 uint64 + x38, x37 = bits.Mul64(arg1[4], (x2 * 0x2)) + var x39 uint64 + var x40 uint64 + x40, x39 = bits.Mul64(arg1[4], (x5 * 0x2)) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(arg1[4], (x8 * 0x2)) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(arg1[4], (x11 * 0x2)) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(arg1[4], arg1[4]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(arg1[3], (x2 * 0x2)) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(arg1[3], (x5 * 0x2)) + var x51 uint64 + var x52 uint64 + x52, x51 = bits.Mul64(arg1[3], (x8 * 0x2)) + var x53 uint64 + var x54 uint64 + x54, x53 = bits.Mul64(arg1[3], x12) + var x55 uint64 + var x56 uint64 + x56, x55 = bits.Mul64(arg1[3], x13) + var x57 uint64 + var x58 uint64 + x58, x57 = bits.Mul64(arg1[3], arg1[3]) + var x59 uint64 + var x60 uint64 + x60, x59 = bits.Mul64(arg1[2], (x2 * 0x2)) + var x61 uint64 + var x62 uint64 + x62, x61 = bits.Mul64(arg1[2], (x5 * 0x2)) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(arg1[2], x9) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(arg1[2], x12) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(arg1[2], x13) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(arg1[2], x14) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(arg1[2], arg1[2]) + var x73 uint64 + var x74 uint64 + x74, x73 = bits.Mul64(arg1[1], (x2 * 0x2)) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(arg1[1], x6) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(arg1[1], x9) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(arg1[1], x12) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(arg1[1], x13) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(arg1[1], x14) + var x85 uint64 + var x86 uint64 + x86, x85 = bits.Mul64(arg1[1], x15) + var x87 uint64 + var x88 uint64 + x88, x87 = bits.Mul64(arg1[1], arg1[1]) + var x89 uint64 + var x90 uint64 + x90, x89 = bits.Mul64(arg1[0], x3) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(arg1[0], x6) + var x93 uint64 + var x94 uint64 + x94, x93 = bits.Mul64(arg1[0], x9) + var x95 uint64 + var x96 uint64 + x96, x95 = bits.Mul64(arg1[0], x12) + var x97 uint64 + var x98 uint64 + x98, x97 = bits.Mul64(arg1[0], x13) + var x99 uint64 + var x100 uint64 + x100, x99 = bits.Mul64(arg1[0], x14) + var x101 uint64 + var x102 uint64 + x102, x101 = bits.Mul64(arg1[0], x15) + var x103 uint64 + var x104 uint64 + x104, x103 = bits.Mul64(arg1[0], x16) + var x105 uint64 + var x106 uint64 + x106, x105 = bits.Mul64(arg1[0], arg1[0]) + var x107 uint64 + var x108 p521Uint1 + x107, x108 = p521AddcarryxU64(x51, x43, 0x0) + var x109 uint64 + x109, _ = p521AddcarryxU64(x52, x44, x108) + var x111 uint64 + var x112 p521Uint1 + x111, x112 = p521AddcarryxU64(x61, x107, 0x0) + var x113 uint64 + x113, _ = p521AddcarryxU64(x62, x109, x112) + var x115 uint64 + var x116 p521Uint1 + x115, x116 = p521AddcarryxU64(x73, x111, 0x0) + var x117 uint64 + x117, _ = p521AddcarryxU64(x74, x113, x116) + var x119 uint64 + var x120 p521Uint1 + x119, x120 = p521AddcarryxU64(x105, x115, 0x0) + var x121 uint64 + x121, _ = p521AddcarryxU64(x106, x117, x120) + x123 := ((x119 >> 58) | ((x121 << 6) & 0xffffffffffffffff)) + x124 := (x121 >> 58) + x125 := (x119 & 0x3ffffffffffffff) + var x126 uint64 + var x127 p521Uint1 + x126, x127 = p521AddcarryxU64(x53, x45, 0x0) + var x128 uint64 + x128, _ = p521AddcarryxU64(x54, x46, x127) + var x130 uint64 + var x131 p521Uint1 + x130, x131 = p521AddcarryxU64(x63, x126, 0x0) + var x132 uint64 + x132, _ = p521AddcarryxU64(x64, x128, x131) + var x134 uint64 + var x135 p521Uint1 + x134, x135 = p521AddcarryxU64(x75, x130, 0x0) + var x136 uint64 + x136, _ = p521AddcarryxU64(x76, x132, x135) + var x138 uint64 + var x139 p521Uint1 + x138, x139 = p521AddcarryxU64(x89, x134, 0x0) + var x140 uint64 + x140, _ = p521AddcarryxU64(x90, x136, x139) + var x142 uint64 + var x143 p521Uint1 + x142, x143 = p521AddcarryxU64(x55, x17, 0x0) + var x144 uint64 + x144, _ = p521AddcarryxU64(x56, x18, x143) + var x146 uint64 + var x147 p521Uint1 + x146, x147 = p521AddcarryxU64(x65, x142, 0x0) + var x148 uint64 + x148, _ = p521AddcarryxU64(x66, x144, x147) + var x150 uint64 + var x151 p521Uint1 + x150, x151 = p521AddcarryxU64(x77, x146, 0x0) + var x152 uint64 + x152, _ = p521AddcarryxU64(x78, x148, x151) + var x154 uint64 + var x155 p521Uint1 + x154, x155 = p521AddcarryxU64(x91, x150, 0x0) + var x156 uint64 + x156, _ = p521AddcarryxU64(x92, x152, x155) + var x158 uint64 + var x159 p521Uint1 + x158, x159 = p521AddcarryxU64(x57, x19, 0x0) + var x160 uint64 + x160, _ = p521AddcarryxU64(x58, x20, x159) + var x162 uint64 + var x163 p521Uint1 + x162, x163 = p521AddcarryxU64(x67, x158, 0x0) + var x164 uint64 + x164, _ = p521AddcarryxU64(x68, x160, x163) + var x166 uint64 + var x167 p521Uint1 + x166, x167 = p521AddcarryxU64(x79, x162, 0x0) + var x168 uint64 + x168, _ = p521AddcarryxU64(x80, x164, x167) + var x170 uint64 + var x171 p521Uint1 + x170, x171 = p521AddcarryxU64(x93, x166, 0x0) + var x172 uint64 + x172, _ = p521AddcarryxU64(x94, x168, x171) + var x174 uint64 + var x175 p521Uint1 + x174, x175 = p521AddcarryxU64(x23, x21, 0x0) + var x176 uint64 + x176, _ = p521AddcarryxU64(x24, x22, x175) + var x178 uint64 + var x179 p521Uint1 + x178, x179 = p521AddcarryxU64(x69, x174, 0x0) + var x180 uint64 + x180, _ = p521AddcarryxU64(x70, x176, x179) + var x182 uint64 + var x183 p521Uint1 + x182, x183 = p521AddcarryxU64(x81, x178, 0x0) + var x184 uint64 + x184, _ = p521AddcarryxU64(x82, x180, x183) + var x186 uint64 + var x187 p521Uint1 + x186, x187 = p521AddcarryxU64(x95, x182, 0x0) + var x188 uint64 + x188, _ = p521AddcarryxU64(x96, x184, x187) + var x190 uint64 + var x191 p521Uint1 + x190, x191 = p521AddcarryxU64(x29, x25, 0x0) + var x192 uint64 + x192, _ = p521AddcarryxU64(x30, x26, x191) + var x194 uint64 + var x195 p521Uint1 + x194, x195 = p521AddcarryxU64(x71, x190, 0x0) + var x196 uint64 + x196, _ = p521AddcarryxU64(x72, x192, x195) + var x198 uint64 + var x199 p521Uint1 + x198, x199 = p521AddcarryxU64(x83, x194, 0x0) + var x200 uint64 + x200, _ = p521AddcarryxU64(x84, x196, x199) + var x202 uint64 + var x203 p521Uint1 + x202, x203 = p521AddcarryxU64(x97, x198, 0x0) + var x204 uint64 + x204, _ = p521AddcarryxU64(x98, x200, x203) + var x206 uint64 + var x207 p521Uint1 + x206, x207 = p521AddcarryxU64(x31, x27, 0x0) + var x208 uint64 + x208, _ = p521AddcarryxU64(x32, x28, x207) + var x210 uint64 + var x211 p521Uint1 + x210, x211 = p521AddcarryxU64(x37, x206, 0x0) + var x212 uint64 + x212, _ = p521AddcarryxU64(x38, x208, x211) + var x214 uint64 + var x215 p521Uint1 + x214, x215 = p521AddcarryxU64(x85, x210, 0x0) + var x216 uint64 + x216, _ = p521AddcarryxU64(x86, x212, x215) + var x218 uint64 + var x219 p521Uint1 + x218, x219 = p521AddcarryxU64(x99, x214, 0x0) + var x220 uint64 + x220, _ = p521AddcarryxU64(x100, x216, x219) + var x222 uint64 + var x223 p521Uint1 + x222, x223 = p521AddcarryxU64(x39, x33, 0x0) + var x224 uint64 + x224, _ = p521AddcarryxU64(x40, x34, x223) + var x226 uint64 + var x227 p521Uint1 + x226, x227 = p521AddcarryxU64(x47, x222, 0x0) + var x228 uint64 + x228, _ = p521AddcarryxU64(x48, x224, x227) + var x230 uint64 + var x231 p521Uint1 + x230, x231 = p521AddcarryxU64(x87, x226, 0x0) + var x232 uint64 + x232, _ = p521AddcarryxU64(x88, x228, x231) + var x234 uint64 + var x235 p521Uint1 + x234, x235 = p521AddcarryxU64(x101, x230, 0x0) + var x236 uint64 + x236, _ = p521AddcarryxU64(x102, x232, x235) + var x238 uint64 + var x239 p521Uint1 + x238, x239 = p521AddcarryxU64(x41, x35, 0x0) + var x240 uint64 + x240, _ = p521AddcarryxU64(x42, x36, x239) + var x242 uint64 + var x243 p521Uint1 + x242, x243 = p521AddcarryxU64(x49, x238, 0x0) + var x244 uint64 + x244, _ = p521AddcarryxU64(x50, x240, x243) + var x246 uint64 + var x247 p521Uint1 + x246, x247 = p521AddcarryxU64(x59, x242, 0x0) + var x248 uint64 + x248, _ = p521AddcarryxU64(x60, x244, x247) + var x250 uint64 + var x251 p521Uint1 + x250, x251 = p521AddcarryxU64(x103, x246, 0x0) + var x252 uint64 + x252, _ = p521AddcarryxU64(x104, x248, x251) + var x254 uint64 + var x255 p521Uint1 + x254, x255 = p521AddcarryxU64(x123, x250, 0x0) + var x256 uint64 + x256, _ = p521AddcarryxU64(x124, x252, x255) + x258 := ((x254 >> 58) | ((x256 << 6) & 0xffffffffffffffff)) + x259 := (x256 >> 58) + x260 := (x254 & 0x3ffffffffffffff) + var x261 uint64 + var x262 p521Uint1 + x261, x262 = p521AddcarryxU64(x258, x234, 0x0) + var x263 uint64 + x263, _ = p521AddcarryxU64(x259, x236, x262) + x265 := ((x261 >> 58) | ((x263 << 6) & 0xffffffffffffffff)) + x266 := (x263 >> 58) + x267 := (x261 & 0x3ffffffffffffff) + var x268 uint64 + var x269 p521Uint1 + x268, x269 = p521AddcarryxU64(x265, x218, 0x0) + var x270 uint64 + x270, _ = p521AddcarryxU64(x266, x220, x269) + x272 := ((x268 >> 58) | ((x270 << 6) & 0xffffffffffffffff)) + x273 := (x270 >> 58) + x274 := (x268 & 0x3ffffffffffffff) + var x275 uint64 + var x276 p521Uint1 + x275, x276 = p521AddcarryxU64(x272, x202, 0x0) + var x277 uint64 + x277, _ = p521AddcarryxU64(x273, x204, x276) + x279 := ((x275 >> 58) | ((x277 << 6) & 0xffffffffffffffff)) + x280 := (x277 >> 58) + x281 := (x275 & 0x3ffffffffffffff) + var x282 uint64 + var x283 p521Uint1 + x282, x283 = p521AddcarryxU64(x279, x186, 0x0) + var x284 uint64 + x284, _ = p521AddcarryxU64(x280, x188, x283) + x286 := ((x282 >> 58) | ((x284 << 6) & 0xffffffffffffffff)) + x287 := (x284 >> 58) + x288 := (x282 & 0x3ffffffffffffff) + var x289 uint64 + var x290 p521Uint1 + x289, x290 = p521AddcarryxU64(x286, x170, 0x0) + var x291 uint64 + x291, _ = p521AddcarryxU64(x287, x172, x290) + x293 := ((x289 >> 58) | ((x291 << 6) & 0xffffffffffffffff)) + x294 := (x291 >> 58) + x295 := (x289 & 0x3ffffffffffffff) + var x296 uint64 + var x297 p521Uint1 + x296, x297 = p521AddcarryxU64(x293, x154, 0x0) + var x298 uint64 + x298, _ = p521AddcarryxU64(x294, x156, x297) + x300 := ((x296 >> 58) | ((x298 << 6) & 0xffffffffffffffff)) + x301 := (x298 >> 58) + x302 := (x296 & 0x3ffffffffffffff) + var x303 uint64 + var x304 p521Uint1 + x303, x304 = p521AddcarryxU64(x300, x138, 0x0) + var x305 uint64 + x305, _ = p521AddcarryxU64(x301, x140, x304) + x307 := ((x303 >> 57) | ((x305 << 7) & 0xffffffffffffffff)) + x308 := (x305 >> 57) + x309 := (x303 & 0x1ffffffffffffff) + var x310 uint64 + var x311 p521Uint1 + x310, x311 = p521AddcarryxU64(x125, x307, 0x0) + x312 := (uint64(x311) + x308) + x313 := ((x310 >> 58) | ((x312 << 6) & 0xffffffffffffffff)) + x314 := (x310 & 0x3ffffffffffffff) + x315 := (x313 + x260) + x316 := p521Uint1((x315 >> 58)) + x317 := (x315 & 0x3ffffffffffffff) + x318 := (uint64(x316) + x267) + out1[0] = x314 + out1[1] = x317 + out1[2] = x318 + out1[3] = x274 + out1[4] = x281 + out1[5] = x288 + out1[6] = x295 + out1[7] = x302 + out1[8] = x309 +} + +// p521Carry reduces a field element. +// +// Postconditions: +// eval out1 mod m = eval arg1 mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +func p521Carry(out1 *[9]uint64, arg1 *[9]uint64) { + x1 := arg1[0] + x2 := ((x1 >> 58) + arg1[1]) + x3 := ((x2 >> 58) + arg1[2]) + x4 := ((x3 >> 58) + arg1[3]) + x5 := ((x4 >> 58) + arg1[4]) + x6 := ((x5 >> 58) + arg1[5]) + x7 := ((x6 >> 58) + arg1[6]) + x8 := ((x7 >> 58) + arg1[7]) + x9 := ((x8 >> 58) + arg1[8]) + x10 := ((x1 & 0x3ffffffffffffff) + (x9 >> 57)) + x11 := (uint64(p521Uint1((x10 >> 58))) + (x2 & 0x3ffffffffffffff)) + x12 := (x10 & 0x3ffffffffffffff) + x13 := (x11 & 0x3ffffffffffffff) + x14 := (uint64(p521Uint1((x11 >> 58))) + (x3 & 0x3ffffffffffffff)) + x15 := (x4 & 0x3ffffffffffffff) + x16 := (x5 & 0x3ffffffffffffff) + x17 := (x6 & 0x3ffffffffffffff) + x18 := (x7 & 0x3ffffffffffffff) + x19 := (x8 & 0x3ffffffffffffff) + x20 := (x9 & 0x1ffffffffffffff) + out1[0] = x12 + out1[1] = x13 + out1[2] = x14 + out1[3] = x15 + out1[4] = x16 + out1[5] = x17 + out1[6] = x18 + out1[7] = x19 + out1[8] = x20 +} + +// p521Add adds two field elements. +// +// Postconditions: +// eval out1 mod m = (eval arg1 + eval arg2) mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +func p521Add(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { + x1 := (arg1[0] + arg2[0]) + x2 := (arg1[1] + arg2[1]) + x3 := (arg1[2] + arg2[2]) + x4 := (arg1[3] + arg2[3]) + x5 := (arg1[4] + arg2[4]) + x6 := (arg1[5] + arg2[5]) + x7 := (arg1[6] + arg2[6]) + x8 := (arg1[7] + arg2[7]) + x9 := (arg1[8] + arg2[8]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 + out1[8] = x9 +} + +// p521Sub subtracts two field elements. +// +// Postconditions: +// eval out1 mod m = (eval arg1 - eval arg2) mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { + x1 := ((0x7fffffffffffffe + arg1[0]) - arg2[0]) + x2 := ((0x7fffffffffffffe + arg1[1]) - arg2[1]) + x3 := ((0x7fffffffffffffe + arg1[2]) - arg2[2]) + x4 := ((0x7fffffffffffffe + arg1[3]) - arg2[3]) + x5 := ((0x7fffffffffffffe + arg1[4]) - arg2[4]) + x6 := ((0x7fffffffffffffe + arg1[5]) - arg2[5]) + x7 := ((0x7fffffffffffffe + arg1[6]) - arg2[6]) + x8 := ((0x7fffffffffffffe + arg1[7]) - arg2[7]) + x9 := ((0x3fffffffffffffe + arg1[8]) - arg2[8]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 + out1[8] = x9 +} + +// p521ToBytes serializes a field element to bytes in little-endian order. +// +// Postconditions: +// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..65] +// +// Input Bounds: +// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] +func p521ToBytes(out1 *[66]uint8, arg1 *[9]uint64) { + var x1 uint64 + var x2 p521Uint1 + p521SubborrowxU58(&x1, &x2, 0x0, arg1[0], 0x3ffffffffffffff) + var x3 uint64 + var x4 p521Uint1 + p521SubborrowxU58(&x3, &x4, x2, arg1[1], 0x3ffffffffffffff) + var x5 uint64 + var x6 p521Uint1 + p521SubborrowxU58(&x5, &x6, x4, arg1[2], 0x3ffffffffffffff) + var x7 uint64 + var x8 p521Uint1 + p521SubborrowxU58(&x7, &x8, x6, arg1[3], 0x3ffffffffffffff) + var x9 uint64 + var x10 p521Uint1 + p521SubborrowxU58(&x9, &x10, x8, arg1[4], 0x3ffffffffffffff) + var x11 uint64 + var x12 p521Uint1 + p521SubborrowxU58(&x11, &x12, x10, arg1[5], 0x3ffffffffffffff) + var x13 uint64 + var x14 p521Uint1 + p521SubborrowxU58(&x13, &x14, x12, arg1[6], 0x3ffffffffffffff) + var x15 uint64 + var x16 p521Uint1 + p521SubborrowxU58(&x15, &x16, x14, arg1[7], 0x3ffffffffffffff) + var x17 uint64 + var x18 p521Uint1 + p521SubborrowxU57(&x17, &x18, x16, arg1[8], 0x1ffffffffffffff) + var x19 uint64 + p521CmovznzU64(&x19, x18, uint64(0x0), 0xffffffffffffffff) + var x20 uint64 + var x21 p521Uint1 + p521AddcarryxU58(&x20, &x21, 0x0, x1, (x19 & 0x3ffffffffffffff)) + var x22 uint64 + var x23 p521Uint1 + p521AddcarryxU58(&x22, &x23, x21, x3, (x19 & 0x3ffffffffffffff)) + var x24 uint64 + var x25 p521Uint1 + p521AddcarryxU58(&x24, &x25, x23, x5, (x19 & 0x3ffffffffffffff)) + var x26 uint64 + var x27 p521Uint1 + p521AddcarryxU58(&x26, &x27, x25, x7, (x19 & 0x3ffffffffffffff)) + var x28 uint64 + var x29 p521Uint1 + p521AddcarryxU58(&x28, &x29, x27, x9, (x19 & 0x3ffffffffffffff)) + var x30 uint64 + var x31 p521Uint1 + p521AddcarryxU58(&x30, &x31, x29, x11, (x19 & 0x3ffffffffffffff)) + var x32 uint64 + var x33 p521Uint1 + p521AddcarryxU58(&x32, &x33, x31, x13, (x19 & 0x3ffffffffffffff)) + var x34 uint64 + var x35 p521Uint1 + p521AddcarryxU58(&x34, &x35, x33, x15, (x19 & 0x3ffffffffffffff)) + var x36 uint64 + var x37 p521Uint1 + p521AddcarryxU57(&x36, &x37, x35, x17, (x19 & 0x1ffffffffffffff)) + x38 := (x34 << 6) + x39 := (x32 << 4) + x40 := (x30 << 2) + x41 := (x26 << 6) + x42 := (x24 << 4) + x43 := (x22 << 2) + x44 := (uint8(x20) & 0xff) + x45 := (x20 >> 8) + x46 := (uint8(x45) & 0xff) + x47 := (x45 >> 8) + x48 := (uint8(x47) & 0xff) + x49 := (x47 >> 8) + x50 := (uint8(x49) & 0xff) + x51 := (x49 >> 8) + x52 := (uint8(x51) & 0xff) + x53 := (x51 >> 8) + x54 := (uint8(x53) & 0xff) + x55 := (x53 >> 8) + x56 := (uint8(x55) & 0xff) + x57 := uint8((x55 >> 8)) + x58 := (x43 + uint64(x57)) + x59 := (uint8(x58) & 0xff) + x60 := (x58 >> 8) + x61 := (uint8(x60) & 0xff) + x62 := (x60 >> 8) + x63 := (uint8(x62) & 0xff) + x64 := (x62 >> 8) + x65 := (uint8(x64) & 0xff) + x66 := (x64 >> 8) + x67 := (uint8(x66) & 0xff) + x68 := (x66 >> 8) + x69 := (uint8(x68) & 0xff) + x70 := (x68 >> 8) + x71 := (uint8(x70) & 0xff) + x72 := uint8((x70 >> 8)) + x73 := (x42 + uint64(x72)) + x74 := (uint8(x73) & 0xff) + x75 := (x73 >> 8) + x76 := (uint8(x75) & 0xff) + x77 := (x75 >> 8) + x78 := (uint8(x77) & 0xff) + x79 := (x77 >> 8) + x80 := (uint8(x79) & 0xff) + x81 := (x79 >> 8) + x82 := (uint8(x81) & 0xff) + x83 := (x81 >> 8) + x84 := (uint8(x83) & 0xff) + x85 := (x83 >> 8) + x86 := (uint8(x85) & 0xff) + x87 := uint8((x85 >> 8)) + x88 := (x41 + uint64(x87)) + x89 := (uint8(x88) & 0xff) + x90 := (x88 >> 8) + x91 := (uint8(x90) & 0xff) + x92 := (x90 >> 8) + x93 := (uint8(x92) & 0xff) + x94 := (x92 >> 8) + x95 := (uint8(x94) & 0xff) + x96 := (x94 >> 8) + x97 := (uint8(x96) & 0xff) + x98 := (x96 >> 8) + x99 := (uint8(x98) & 0xff) + x100 := (x98 >> 8) + x101 := (uint8(x100) & 0xff) + x102 := uint8((x100 >> 8)) + x103 := (uint8(x28) & 0xff) + x104 := (x28 >> 8) + x105 := (uint8(x104) & 0xff) + x106 := (x104 >> 8) + x107 := (uint8(x106) & 0xff) + x108 := (x106 >> 8) + x109 := (uint8(x108) & 0xff) + x110 := (x108 >> 8) + x111 := (uint8(x110) & 0xff) + x112 := (x110 >> 8) + x113 := (uint8(x112) & 0xff) + x114 := (x112 >> 8) + x115 := (uint8(x114) & 0xff) + x116 := uint8((x114 >> 8)) + x117 := (x40 + uint64(x116)) + x118 := (uint8(x117) & 0xff) + x119 := (x117 >> 8) + x120 := (uint8(x119) & 0xff) + x121 := (x119 >> 8) + x122 := (uint8(x121) & 0xff) + x123 := (x121 >> 8) + x124 := (uint8(x123) & 0xff) + x125 := (x123 >> 8) + x126 := (uint8(x125) & 0xff) + x127 := (x125 >> 8) + x128 := (uint8(x127) & 0xff) + x129 := (x127 >> 8) + x130 := (uint8(x129) & 0xff) + x131 := uint8((x129 >> 8)) + x132 := (x39 + uint64(x131)) + x133 := (uint8(x132) & 0xff) + x134 := (x132 >> 8) + x135 := (uint8(x134) & 0xff) + x136 := (x134 >> 8) + x137 := (uint8(x136) & 0xff) + x138 := (x136 >> 8) + x139 := (uint8(x138) & 0xff) + x140 := (x138 >> 8) + x141 := (uint8(x140) & 0xff) + x142 := (x140 >> 8) + x143 := (uint8(x142) & 0xff) + x144 := (x142 >> 8) + x145 := (uint8(x144) & 0xff) + x146 := uint8((x144 >> 8)) + x147 := (x38 + uint64(x146)) + x148 := (uint8(x147) & 0xff) + x149 := (x147 >> 8) + x150 := (uint8(x149) & 0xff) + x151 := (x149 >> 8) + x152 := (uint8(x151) & 0xff) + x153 := (x151 >> 8) + x154 := (uint8(x153) & 0xff) + x155 := (x153 >> 8) + x156 := (uint8(x155) & 0xff) + x157 := (x155 >> 8) + x158 := (uint8(x157) & 0xff) + x159 := (x157 >> 8) + x160 := (uint8(x159) & 0xff) + x161 := uint8((x159 >> 8)) + x162 := (uint8(x36) & 0xff) + x163 := (x36 >> 8) + x164 := (uint8(x163) & 0xff) + x165 := (x163 >> 8) + x166 := (uint8(x165) & 0xff) + x167 := (x165 >> 8) + x168 := (uint8(x167) & 0xff) + x169 := (x167 >> 8) + x170 := (uint8(x169) & 0xff) + x171 := (x169 >> 8) + x172 := (uint8(x171) & 0xff) + x173 := (x171 >> 8) + x174 := (uint8(x173) & 0xff) + x175 := p521Uint1((x173 >> 8)) + out1[0] = x44 + out1[1] = x46 + out1[2] = x48 + out1[3] = x50 + out1[4] = x52 + out1[5] = x54 + out1[6] = x56 + out1[7] = x59 + out1[8] = x61 + out1[9] = x63 + out1[10] = x65 + out1[11] = x67 + out1[12] = x69 + out1[13] = x71 + out1[14] = x74 + out1[15] = x76 + out1[16] = x78 + out1[17] = x80 + out1[18] = x82 + out1[19] = x84 + out1[20] = x86 + out1[21] = x89 + out1[22] = x91 + out1[23] = x93 + out1[24] = x95 + out1[25] = x97 + out1[26] = x99 + out1[27] = x101 + out1[28] = x102 + out1[29] = x103 + out1[30] = x105 + out1[31] = x107 + out1[32] = x109 + out1[33] = x111 + out1[34] = x113 + out1[35] = x115 + out1[36] = x118 + out1[37] = x120 + out1[38] = x122 + out1[39] = x124 + out1[40] = x126 + out1[41] = x128 + out1[42] = x130 + out1[43] = x133 + out1[44] = x135 + out1[45] = x137 + out1[46] = x139 + out1[47] = x141 + out1[48] = x143 + out1[49] = x145 + out1[50] = x148 + out1[51] = x150 + out1[52] = x152 + out1[53] = x154 + out1[54] = x156 + out1[55] = x158 + out1[56] = x160 + out1[57] = x161 + out1[58] = x162 + out1[59] = x164 + out1[60] = x166 + out1[61] = x168 + out1[62] = x170 + out1[63] = x172 + out1[64] = x174 + out1[65] = uint8(x175) +} + +// p521FromBytes deserializes a field element from bytes in little-endian order. +// +// Postconditions: +// eval out1 mod m = bytes_eval arg1 mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] +// Output Bounds: +// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) { + x1 := (uint64(p521Uint1(arg1[65])) << 56) + x2 := (uint64(arg1[64]) << 48) + x3 := (uint64(arg1[63]) << 40) + x4 := (uint64(arg1[62]) << 32) + x5 := (uint64(arg1[61]) << 24) + x6 := (uint64(arg1[60]) << 16) + x7 := (uint64(arg1[59]) << 8) + x8 := arg1[58] + x9 := (uint64(arg1[57]) << 50) + x10 := (uint64(arg1[56]) << 42) + x11 := (uint64(arg1[55]) << 34) + x12 := (uint64(arg1[54]) << 26) + x13 := (uint64(arg1[53]) << 18) + x14 := (uint64(arg1[52]) << 10) + x15 := (uint64(arg1[51]) << 2) + x16 := (uint64(arg1[50]) << 52) + x17 := (uint64(arg1[49]) << 44) + x18 := (uint64(arg1[48]) << 36) + x19 := (uint64(arg1[47]) << 28) + x20 := (uint64(arg1[46]) << 20) + x21 := (uint64(arg1[45]) << 12) + x22 := (uint64(arg1[44]) << 4) + x23 := (uint64(arg1[43]) << 54) + x24 := (uint64(arg1[42]) << 46) + x25 := (uint64(arg1[41]) << 38) + x26 := (uint64(arg1[40]) << 30) + x27 := (uint64(arg1[39]) << 22) + x28 := (uint64(arg1[38]) << 14) + x29 := (uint64(arg1[37]) << 6) + x30 := (uint64(arg1[36]) << 56) + x31 := (uint64(arg1[35]) << 48) + x32 := (uint64(arg1[34]) << 40) + x33 := (uint64(arg1[33]) << 32) + x34 := (uint64(arg1[32]) << 24) + x35 := (uint64(arg1[31]) << 16) + x36 := (uint64(arg1[30]) << 8) + x37 := arg1[29] + x38 := (uint64(arg1[28]) << 50) + x39 := (uint64(arg1[27]) << 42) + x40 := (uint64(arg1[26]) << 34) + x41 := (uint64(arg1[25]) << 26) + x42 := (uint64(arg1[24]) << 18) + x43 := (uint64(arg1[23]) << 10) + x44 := (uint64(arg1[22]) << 2) + x45 := (uint64(arg1[21]) << 52) + x46 := (uint64(arg1[20]) << 44) + x47 := (uint64(arg1[19]) << 36) + x48 := (uint64(arg1[18]) << 28) + x49 := (uint64(arg1[17]) << 20) + x50 := (uint64(arg1[16]) << 12) + x51 := (uint64(arg1[15]) << 4) + x52 := (uint64(arg1[14]) << 54) + x53 := (uint64(arg1[13]) << 46) + x54 := (uint64(arg1[12]) << 38) + x55 := (uint64(arg1[11]) << 30) + x56 := (uint64(arg1[10]) << 22) + x57 := (uint64(arg1[9]) << 14) + x58 := (uint64(arg1[8]) << 6) + x59 := (uint64(arg1[7]) << 56) + x60 := (uint64(arg1[6]) << 48) + x61 := (uint64(arg1[5]) << 40) + x62 := (uint64(arg1[4]) << 32) + x63 := (uint64(arg1[3]) << 24) + x64 := (uint64(arg1[2]) << 16) + x65 := (uint64(arg1[1]) << 8) + x66 := arg1[0] + x67 := (x65 + uint64(x66)) + x68 := (x64 + x67) + x69 := (x63 + x68) + x70 := (x62 + x69) + x71 := (x61 + x70) + x72 := (x60 + x71) + x73 := (x59 + x72) + x74 := (x73 & 0x3ffffffffffffff) + x75 := uint8((x73 >> 58)) + x76 := (x58 + uint64(x75)) + x77 := (x57 + x76) + x78 := (x56 + x77) + x79 := (x55 + x78) + x80 := (x54 + x79) + x81 := (x53 + x80) + x82 := (x52 + x81) + x83 := (x82 & 0x3ffffffffffffff) + x84 := uint8((x82 >> 58)) + x85 := (x51 + uint64(x84)) + x86 := (x50 + x85) + x87 := (x49 + x86) + x88 := (x48 + x87) + x89 := (x47 + x88) + x90 := (x46 + x89) + x91 := (x45 + x90) + x92 := (x91 & 0x3ffffffffffffff) + x93 := uint8((x91 >> 58)) + x94 := (x44 + uint64(x93)) + x95 := (x43 + x94) + x96 := (x42 + x95) + x97 := (x41 + x96) + x98 := (x40 + x97) + x99 := (x39 + x98) + x100 := (x38 + x99) + x101 := (x36 + uint64(x37)) + x102 := (x35 + x101) + x103 := (x34 + x102) + x104 := (x33 + x103) + x105 := (x32 + x104) + x106 := (x31 + x105) + x107 := (x30 + x106) + x108 := (x107 & 0x3ffffffffffffff) + x109 := uint8((x107 >> 58)) + x110 := (x29 + uint64(x109)) + x111 := (x28 + x110) + x112 := (x27 + x111) + x113 := (x26 + x112) + x114 := (x25 + x113) + x115 := (x24 + x114) + x116 := (x23 + x115) + x117 := (x116 & 0x3ffffffffffffff) + x118 := uint8((x116 >> 58)) + x119 := (x22 + uint64(x118)) + x120 := (x21 + x119) + x121 := (x20 + x120) + x122 := (x19 + x121) + x123 := (x18 + x122) + x124 := (x17 + x123) + x125 := (x16 + x124) + x126 := (x125 & 0x3ffffffffffffff) + x127 := uint8((x125 >> 58)) + x128 := (x15 + uint64(x127)) + x129 := (x14 + x128) + x130 := (x13 + x129) + x131 := (x12 + x130) + x132 := (x11 + x131) + x133 := (x10 + x132) + x134 := (x9 + x133) + x135 := (x7 + uint64(x8)) + x136 := (x6 + x135) + x137 := (x5 + x136) + x138 := (x4 + x137) + x139 := (x3 + x138) + x140 := (x2 + x139) + x141 := (x1 + x140) + out1[0] = x74 + out1[1] = x83 + out1[2] = x92 + out1[3] = x100 + out1[4] = x108 + out1[5] = x117 + out1[6] = x126 + out1[7] = x134 + out1[8] = x141 +} + +// p521Selectznz is a multi-limb conditional select. +// +// Postconditions: +// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) { + var x1 uint64 + p521CmovznzU64(&x1, arg1, arg2[0], arg3[0]) + var x2 uint64 + p521CmovznzU64(&x2, arg1, arg2[1], arg3[1]) + var x3 uint64 + p521CmovznzU64(&x3, arg1, arg2[2], arg3[2]) + var x4 uint64 + p521CmovznzU64(&x4, arg1, arg2[3], arg3[3]) + var x5 uint64 + p521CmovznzU64(&x5, arg1, arg2[4], arg3[4]) + var x6 uint64 + p521CmovznzU64(&x6, arg1, arg2[5], arg3[5]) + var x7 uint64 + p521CmovznzU64(&x7, arg1, arg2[6], arg3[6]) + var x8 uint64 + p521CmovznzU64(&x8, arg1, arg2[7], arg3[7]) + var x9 uint64 + p521CmovznzU64(&x9, arg1, arg2[8], arg3[8]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 + out1[8] = x9 +} diff --git a/src/crypto/elliptic/internal/fiat/p521_test.go b/src/crypto/elliptic/internal/fiat/p521_test.go new file mode 100644 index 0000000..661bde3 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p521_test.go @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fiat_test + +import ( + "crypto/elliptic/internal/fiat" + "crypto/rand" + "testing" +) + +func p521Random(t *testing.T) *fiat.P521Element { + buf := make([]byte, 66) + if _, err := rand.Read(buf); err != nil { + t.Fatal(err) + } + buf[65] &= 1 + e, err := new(fiat.P521Element).SetBytes(buf) + if err != nil { + t.Fatal(err) + } + return e +} + +func TestP521Invert(t *testing.T) { + a := p521Random(t) + inv := new(fiat.P521Element).Invert(a) + one := new(fiat.P521Element).Mul(a, inv) + if new(fiat.P521Element).One().Equal(one) != 1 { + t.Errorf("a * 1/a != 1; got %x for %x", one.Bytes(), a.Bytes()) + } + inv.Invert(new(fiat.P521Element)) + if new(fiat.P521Element).Equal(inv) != 1 { + t.Errorf("1/0 != 0; got %x", inv.Bytes()) + } +} diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go new file mode 100644 index 0000000..ff5c834 --- /dev/null +++ b/src/crypto/elliptic/p224.go @@ -0,0 +1,783 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +// This is a constant-time, 32-bit implementation of P224. See FIPS 186-3, +// section D.2.2. +// +// See https://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. + +import ( + "math/big" +) + +var p224 p224Curve + +type p224Curve struct { + *CurveParams + gx, gy, b p224FieldElement +} + +func initP224() { + // See FIPS 186-3, section D.2.2 + p224.CurveParams = &CurveParams{Name: "P-224"} + p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10) + p224.N, _ = new(big.Int).SetString("26959946667150639794667015087019625940457807714424391721682722368061", 10) + p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16) + p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16) + p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16) + p224.BitSize = 224 + + p224FromBig(&p224.gx, p224.Gx) + p224FromBig(&p224.gy, p224.Gy) + p224FromBig(&p224.b, p224.B) +} + +// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2). +// +// The cryptographic operations are implemented using constant-time algorithms. +func P224() Curve { + initonce.Do(initAll) + return p224 +} + +func (curve p224Curve) Params() *CurveParams { + return curve.CurveParams +} + +func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool { + if bigX.Sign() < 0 || bigX.Cmp(curve.P) >= 0 || + bigY.Sign() < 0 || bigY.Cmp(curve.P) >= 0 { + return false + } + + var x, y p224FieldElement + p224FromBig(&x, bigX) + p224FromBig(&y, bigY) + + // y² = x³ - 3x + b + var tmp p224LargeFieldElement + var x3 p224FieldElement + p224Square(&x3, &x, &tmp) + p224Mul(&x3, &x3, &x, &tmp) + + for i := 0; i < 8; i++ { + x[i] *= 3 + } + p224Sub(&x3, &x3, &x) + p224Reduce(&x3) + p224Add(&x3, &x3, &curve.b) + p224Contract(&x3, &x3) + + p224Square(&y, &y, &tmp) + p224Contract(&y, &y) + + for i := 0; i < 8; i++ { + if y[i] != x3[i] { + return false + } + } + return true +} + +func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) { + var x1, y1, z1, x2, y2, z2, x3, y3, z3 p224FieldElement + + p224FromBig(&x1, bigX1) + p224FromBig(&y1, bigY1) + if bigX1.Sign() != 0 || bigY1.Sign() != 0 { + z1[0] = 1 + } + p224FromBig(&x2, bigX2) + p224FromBig(&y2, bigY2) + if bigX2.Sign() != 0 || bigY2.Sign() != 0 { + z2[0] = 1 + } + + p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2) + return p224ToAffine(&x3, &y3, &z3) +} + +func (p224Curve) Double(bigX1, bigY1 *big.Int) (x, y *big.Int) { + var x1, y1, z1, x2, y2, z2 p224FieldElement + + p224FromBig(&x1, bigX1) + p224FromBig(&y1, bigY1) + z1[0] = 1 + + p224DoubleJacobian(&x2, &y2, &z2, &x1, &y1, &z1) + return p224ToAffine(&x2, &y2, &z2) +} + +func (p224Curve) ScalarMult(bigX1, bigY1 *big.Int, scalar []byte) (x, y *big.Int) { + var x1, y1, z1, x2, y2, z2 p224FieldElement + + p224FromBig(&x1, bigX1) + p224FromBig(&y1, bigY1) + z1[0] = 1 + + p224ScalarMult(&x2, &y2, &z2, &x1, &y1, &z1, scalar) + return p224ToAffine(&x2, &y2, &z2) +} + +func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) { + var z1, x2, y2, z2 p224FieldElement + + z1[0] = 1 + p224ScalarMult(&x2, &y2, &z2, &curve.gx, &curve.gy, &z1, scalar) + return p224ToAffine(&x2, &y2, &z2) +} + +// Field element functions. +// +// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1. +// +// Field elements are represented by a FieldElement, which is a typedef to an +// array of 8 uint32's. The value of a FieldElement, a, is: +// a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7] +// +// Using 28-bit limbs means that there's only 4 bits of headroom, which is less +// than we would really like. But it has the useful feature that we hit 2**224 +// exactly, making the reflections during a reduce much nicer. +type p224FieldElement [8]uint32 + +// p224P is the order of the field, represented as a p224FieldElement. +var p224P = [8]uint32{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} + +// p224IsZero returns 1 if a == 0 mod p and 0 otherwise. +// +// a[i] < 2**29 +func p224IsZero(a *p224FieldElement) uint32 { + // Since a p224FieldElement contains 224 bits there are two possible + // representations of 0: 0 and p. + var minimal p224FieldElement + p224Contract(&minimal, a) + + var isZero, isP uint32 + for i, v := range minimal { + isZero |= v + isP |= v - p224P[i] + } + + // If either isZero or isP is 0, then we should return 1. + isZero |= isZero >> 16 + isZero |= isZero >> 8 + isZero |= isZero >> 4 + isZero |= isZero >> 2 + isZero |= isZero >> 1 + + isP |= isP >> 16 + isP |= isP >> 8 + isP |= isP >> 4 + isP |= isP >> 2 + isP |= isP >> 1 + + // For isZero and isP, the LSB is 0 iff all the bits are zero. + result := isZero & isP + result = (^result) & 1 + + return result +} + +// p224Add computes *out = a+b +// +// a[i] + b[i] < 2**32 +func p224Add(out, a, b *p224FieldElement) { + for i := 0; i < 8; i++ { + out[i] = a[i] + b[i] + } +} + +const two31p3 = 1<<31 + 1<<3 +const two31m3 = 1<<31 - 1<<3 +const two31m15m3 = 1<<31 - 1<<15 - 1<<3 + +// p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can +// subtract smaller amounts without underflow. See the section "Subtraction" in +// [1] for reasoning. +var p224ZeroModP31 = []uint32{two31p3, two31m3, two31m3, two31m15m3, two31m3, two31m3, two31m3, two31m3} + +// p224Sub computes *out = a-b +// +// a[i], b[i] < 2**30 +// out[i] < 2**32 +func p224Sub(out, a, b *p224FieldElement) { + for i := 0; i < 8; i++ { + out[i] = a[i] + p224ZeroModP31[i] - b[i] + } +} + +// LargeFieldElement also represents an element of the field. The limbs are +// still spaced 28-bits apart and in little-endian order. So the limbs are at +// 0, 28, 56, ..., 392 bits, each 64-bits wide. +type p224LargeFieldElement [15]uint64 + +const two63p35 = 1<<63 + 1<<35 +const two63m35 = 1<<63 - 1<<35 +const two63m35m19 = 1<<63 - 1<<35 - 1<<19 + +// p224ZeroModP63 is 0 mod p where bit 63 is set in all limbs. See the section +// "Subtraction" in [1] for why. +var p224ZeroModP63 = [8]uint64{two63p35, two63m35, two63m35, two63m35, two63m35m19, two63m35, two63m35, two63m35} + +const bottom12Bits = 0xfff +const bottom28Bits = 0xfffffff + +// p224Mul computes *out = a*b +// +// a[i] < 2**29, b[i] < 2**30 (or vice versa) +// out[i] < 2**29 +func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) { + for i := 0; i < 15; i++ { + tmp[i] = 0 + } + + for i := 0; i < 8; i++ { + for j := 0; j < 8; j++ { + tmp[i+j] += uint64(a[i]) * uint64(b[j]) + } + } + + p224ReduceLarge(out, tmp) +} + +// Square computes *out = a*a +// +// a[i] < 2**29 +// out[i] < 2**29 +func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) { + for i := 0; i < 15; i++ { + tmp[i] = 0 + } + + for i := 0; i < 8; i++ { + for j := 0; j <= i; j++ { + r := uint64(a[i]) * uint64(a[j]) + if i == j { + tmp[i+j] += r + } else { + tmp[i+j] += r << 1 + } + } + } + + p224ReduceLarge(out, tmp) +} + +// ReduceLarge converts a p224LargeFieldElement to a p224FieldElement. +// +// in[i] < 2**62 +func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) { + for i := 0; i < 8; i++ { + in[i] += p224ZeroModP63[i] + } + + // Eliminate the coefficients at 2**224 and greater. + for i := 14; i >= 8; i-- { + in[i-8] -= in[i] + in[i-5] += (in[i] & 0xffff) << 12 + in[i-4] += in[i] >> 16 + } + in[8] = 0 + // in[0..8] < 2**64 + + // As the values become small enough, we start to store them in |out| + // and use 32-bit operations. + for i := 1; i < 8; i++ { + in[i+1] += in[i] >> 28 + out[i] = uint32(in[i] & bottom28Bits) + } + in[0] -= in[8] + out[3] += uint32(in[8]&0xffff) << 12 + out[4] += uint32(in[8] >> 16) + // in[0] < 2**64 + // out[3] < 2**29 + // out[4] < 2**29 + // out[1,2,5..7] < 2**28 + + out[0] = uint32(in[0] & bottom28Bits) + out[1] += uint32((in[0] >> 28) & bottom28Bits) + out[2] += uint32(in[0] >> 56) + // out[0] < 2**28 + // out[1..4] < 2**29 + // out[5..7] < 2**28 +} + +// Reduce reduces the coefficients of a to smaller bounds. +// +// On entry: a[i] < 2**31 + 2**30 +// On exit: a[i] < 2**29 +func p224Reduce(a *p224FieldElement) { + for i := 0; i < 7; i++ { + a[i+1] += a[i] >> 28 + a[i] &= bottom28Bits + } + top := a[7] >> 28 + a[7] &= bottom28Bits + + // top < 2**4 + mask := top + mask |= mask >> 2 + mask |= mask >> 1 + mask <<= 31 + mask = uint32(int32(mask) >> 31) + // Mask is all ones if top != 0, all zero otherwise + + a[0] -= top + a[3] += top << 12 + + // We may have just made a[0] negative but, if we did, then we must + // have added something to a[3], this it's > 2**12. Therefore we can + // carry down to a[0]. + a[3] -= 1 & mask + a[2] += mask & (1<<28 - 1) + a[1] += mask & (1<<28 - 1) + a[0] += mask & (1 << 28) +} + +// p224Invert calculates *out = in**-1 by computing in**(2**224 - 2**96 - 1), +// i.e. Fermat's little theorem. +func p224Invert(out, in *p224FieldElement) { + var f1, f2, f3, f4 p224FieldElement + var c p224LargeFieldElement + + p224Square(&f1, in, &c) // 2 + p224Mul(&f1, &f1, in, &c) // 2**2 - 1 + p224Square(&f1, &f1, &c) // 2**3 - 2 + p224Mul(&f1, &f1, in, &c) // 2**3 - 1 + p224Square(&f2, &f1, &c) // 2**4 - 2 + p224Square(&f2, &f2, &c) // 2**5 - 4 + p224Square(&f2, &f2, &c) // 2**6 - 8 + p224Mul(&f1, &f1, &f2, &c) // 2**6 - 1 + p224Square(&f2, &f1, &c) // 2**7 - 2 + for i := 0; i < 5; i++ { // 2**12 - 2**6 + p224Square(&f2, &f2, &c) + } + p224Mul(&f2, &f2, &f1, &c) // 2**12 - 1 + p224Square(&f3, &f2, &c) // 2**13 - 2 + for i := 0; i < 11; i++ { // 2**24 - 2**12 + p224Square(&f3, &f3, &c) + } + p224Mul(&f2, &f3, &f2, &c) // 2**24 - 1 + p224Square(&f3, &f2, &c) // 2**25 - 2 + for i := 0; i < 23; i++ { // 2**48 - 2**24 + p224Square(&f3, &f3, &c) + } + p224Mul(&f3, &f3, &f2, &c) // 2**48 - 1 + p224Square(&f4, &f3, &c) // 2**49 - 2 + for i := 0; i < 47; i++ { // 2**96 - 2**48 + p224Square(&f4, &f4, &c) + } + p224Mul(&f3, &f3, &f4, &c) // 2**96 - 1 + p224Square(&f4, &f3, &c) // 2**97 - 2 + for i := 0; i < 23; i++ { // 2**120 - 2**24 + p224Square(&f4, &f4, &c) + } + p224Mul(&f2, &f4, &f2, &c) // 2**120 - 1 + for i := 0; i < 6; i++ { // 2**126 - 2**6 + p224Square(&f2, &f2, &c) + } + p224Mul(&f1, &f1, &f2, &c) // 2**126 - 1 + p224Square(&f1, &f1, &c) // 2**127 - 2 + p224Mul(&f1, &f1, in, &c) // 2**127 - 1 + for i := 0; i < 97; i++ { // 2**224 - 2**97 + p224Square(&f1, &f1, &c) + } + p224Mul(out, &f1, &f3, &c) // 2**224 - 2**96 - 1 +} + +// p224Contract converts a FieldElement to its unique, minimal form. +// +// On entry, in[i] < 2**29 +// On exit, out[i] < 2**28 and out < p +func p224Contract(out, in *p224FieldElement) { + copy(out[:], in[:]) + + // First, carry the bits above 28 to the higher limb. + for i := 0; i < 7; i++ { + out[i+1] += out[i] >> 28 + out[i] &= bottom28Bits + } + top := out[7] >> 28 + out[7] &= bottom28Bits + + // Use the reduction identity to carry the overflow. + // + // a + top * 2²²⁴ = a + top * 2⁹⁶ - top + out[0] -= top + out[3] += top << 12 + + // We may just have made out[0] negative. So we carry down. If we made + // out[0] negative then we know that out[3] is sufficiently positive + // because we just added to it. + for i := 0; i < 3; i++ { + mask := uint32(int32(out[i]) >> 31) + out[i] += (1 << 28) & mask + out[i+1] -= 1 & mask + } + + // We might have pushed out[3] over 2**28 so we perform another, partial, + // carry chain. + for i := 3; i < 7; i++ { + out[i+1] += out[i] >> 28 + out[i] &= bottom28Bits + } + top = out[7] >> 28 + out[7] &= bottom28Bits + + // Eliminate top while maintaining the same value mod p. + out[0] -= top + out[3] += top << 12 + + // There are two cases to consider for out[3]: + // 1) The first time that we eliminated top, we didn't push out[3] over + // 2**28. In this case, the partial carry chain didn't change any values + // and top is now zero. + // 2) We did push out[3] over 2**28 the first time that we eliminated top. + // The first value of top was in [0..2], therefore, after overflowing + // and being reduced by the second carry chain, out[3] <= 2<<12 - 1. + // In both cases, out[3] cannot have overflowed when we eliminated top for + // the second time. + + // Again, we may just have made out[0] negative, so do the same carry down. + // As before, if we made out[0] negative then we know that out[3] is + // sufficiently positive. + for i := 0; i < 3; i++ { + mask := uint32(int32(out[i]) >> 31) + out[i] += (1 << 28) & mask + out[i+1] -= 1 & mask + } + + // Now we see if the value is >= p and, if so, subtract p. + + // First we build a mask from the top four limbs, which must all be + // equal to bottom28Bits if the whole value is >= p. If top4AllOnes + // ends up with any zero bits in the bottom 28 bits, then this wasn't + // true. + top4AllOnes := uint32(0xffffffff) + for i := 4; i < 8; i++ { + top4AllOnes &= out[i] + } + top4AllOnes |= 0xf0000000 + // Now we replicate any zero bits to all the bits in top4AllOnes. + top4AllOnes &= top4AllOnes >> 16 + top4AllOnes &= top4AllOnes >> 8 + top4AllOnes &= top4AllOnes >> 4 + top4AllOnes &= top4AllOnes >> 2 + top4AllOnes &= top4AllOnes >> 1 + top4AllOnes = uint32(int32(top4AllOnes<<31) >> 31) + + // Now we test whether the bottom three limbs are non-zero. + bottom3NonZero := out[0] | out[1] | out[2] + bottom3NonZero |= bottom3NonZero >> 16 + bottom3NonZero |= bottom3NonZero >> 8 + bottom3NonZero |= bottom3NonZero >> 4 + bottom3NonZero |= bottom3NonZero >> 2 + bottom3NonZero |= bottom3NonZero >> 1 + bottom3NonZero = uint32(int32(bottom3NonZero<<31) >> 31) + + // Assuming top4AllOnes != 0, everything depends on the value of out[3]. + // If it's > 0xffff000 then the whole value is > p + // If it's = 0xffff000 and bottom3NonZero != 0, then the whole value is >= p + // If it's < 0xffff000, then the whole value is < p + n := 0xffff000 - out[3] + out3Equal := n + out3Equal |= out3Equal >> 16 + out3Equal |= out3Equal >> 8 + out3Equal |= out3Equal >> 4 + out3Equal |= out3Equal >> 2 + out3Equal |= out3Equal >> 1 + out3Equal = ^uint32(int32(out3Equal<<31) >> 31) + + // If out[3] > 0xffff000 then n's MSB will be one. + out3GT := uint32(int32(n) >> 31) + + mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT) + out[0] -= 1 & mask + out[3] -= 0xffff000 & mask + out[4] -= 0xfffffff & mask + out[5] -= 0xfffffff & mask + out[6] -= 0xfffffff & mask + out[7] -= 0xfffffff & mask + + // Do one final carry down, in case we made out[0] negative. One of + // out[0..3] needs to be positive and able to absorb the -1 or the value + // would have been < p, and the subtraction wouldn't have happened. + for i := 0; i < 3; i++ { + mask := uint32(int32(out[i]) >> 31) + out[i] += (1 << 28) & mask + out[i+1] -= 1 & mask + } +} + +// Group element functions. +// +// These functions deal with group elements. The group is an elliptic curve +// group with a = -3 defined in FIPS 186-3, section D.2.2. + +// p224AddJacobian computes *out = a+b where a != b. +func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) { + // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl + var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement + var c p224LargeFieldElement + + z1IsZero := p224IsZero(z1) + z2IsZero := p224IsZero(z2) + + // Z1Z1 = Z1² + p224Square(&z1z1, z1, &c) + // Z2Z2 = Z2² + p224Square(&z2z2, z2, &c) + // U1 = X1*Z2Z2 + p224Mul(&u1, x1, &z2z2, &c) + // U2 = X2*Z1Z1 + p224Mul(&u2, x2, &z1z1, &c) + // S1 = Y1*Z2*Z2Z2 + p224Mul(&s1, z2, &z2z2, &c) + p224Mul(&s1, y1, &s1, &c) + // S2 = Y2*Z1*Z1Z1 + p224Mul(&s2, z1, &z1z1, &c) + p224Mul(&s2, y2, &s2, &c) + // H = U2-U1 + p224Sub(&h, &u2, &u1) + p224Reduce(&h) + xEqual := p224IsZero(&h) + // I = (2*H)² + for j := 0; j < 8; j++ { + i[j] = h[j] << 1 + } + p224Reduce(&i) + p224Square(&i, &i, &c) + // J = H*I + p224Mul(&j, &h, &i, &c) + // r = 2*(S2-S1) + p224Sub(&r, &s2, &s1) + p224Reduce(&r) + yEqual := p224IsZero(&r) + if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 { + p224DoubleJacobian(x3, y3, z3, x1, y1, z1) + return + } + for i := 0; i < 8; i++ { + r[i] <<= 1 + } + p224Reduce(&r) + // V = U1*I + p224Mul(&v, &u1, &i, &c) + // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H + p224Add(&z1z1, &z1z1, &z2z2) + p224Add(&z2z2, z1, z2) + p224Reduce(&z2z2) + p224Square(&z2z2, &z2z2, &c) + p224Sub(z3, &z2z2, &z1z1) + p224Reduce(z3) + p224Mul(z3, z3, &h, &c) + // X3 = r²-J-2*V + for i := 0; i < 8; i++ { + z1z1[i] = v[i] << 1 + } + p224Add(&z1z1, &j, &z1z1) + p224Reduce(&z1z1) + p224Square(x3, &r, &c) + p224Sub(x3, x3, &z1z1) + p224Reduce(x3) + // Y3 = r*(V-X3)-2*S1*J + for i := 0; i < 8; i++ { + s1[i] <<= 1 + } + p224Mul(&s1, &s1, &j, &c) + p224Sub(&z1z1, &v, x3) + p224Reduce(&z1z1) + p224Mul(&z1z1, &z1z1, &r, &c) + p224Sub(y3, &z1z1, &s1) + p224Reduce(y3) + + p224CopyConditional(x3, x2, z1IsZero) + p224CopyConditional(x3, x1, z2IsZero) + p224CopyConditional(y3, y2, z1IsZero) + p224CopyConditional(y3, y1, z2IsZero) + p224CopyConditional(z3, z2, z1IsZero) + p224CopyConditional(z3, z1, z2IsZero) +} + +// p224DoubleJacobian computes *out = a+a. +func p224DoubleJacobian(x3, y3, z3, x1, y1, z1 *p224FieldElement) { + var delta, gamma, beta, alpha, t p224FieldElement + var c p224LargeFieldElement + + p224Square(&delta, z1, &c) + p224Square(&gamma, y1, &c) + p224Mul(&beta, x1, &gamma, &c) + + // alpha = 3*(X1-delta)*(X1+delta) + p224Add(&t, x1, &delta) + for i := 0; i < 8; i++ { + t[i] += t[i] << 1 + } + p224Reduce(&t) + p224Sub(&alpha, x1, &delta) + p224Reduce(&alpha) + p224Mul(&alpha, &alpha, &t, &c) + + // Z3 = (Y1+Z1)²-gamma-delta + p224Add(z3, y1, z1) + p224Reduce(z3) + p224Square(z3, z3, &c) + p224Sub(z3, z3, &gamma) + p224Reduce(z3) + p224Sub(z3, z3, &delta) + p224Reduce(z3) + + // X3 = alpha²-8*beta + for i := 0; i < 8; i++ { + delta[i] = beta[i] << 3 + } + p224Reduce(&delta) + p224Square(x3, &alpha, &c) + p224Sub(x3, x3, &delta) + p224Reduce(x3) + + // Y3 = alpha*(4*beta-X3)-8*gamma² + for i := 0; i < 8; i++ { + beta[i] <<= 2 + } + p224Sub(&beta, &beta, x3) + p224Reduce(&beta) + p224Square(&gamma, &gamma, &c) + for i := 0; i < 8; i++ { + gamma[i] <<= 3 + } + p224Reduce(&gamma) + p224Mul(y3, &alpha, &beta, &c) + p224Sub(y3, y3, &gamma) + p224Reduce(y3) +} + +// p224CopyConditional sets *out = *in iff the least-significant-bit of control +// is true, and it runs in constant time. +func p224CopyConditional(out, in *p224FieldElement, control uint32) { + control <<= 31 + control = uint32(int32(control) >> 31) + + for i := 0; i < 8; i++ { + out[i] ^= (out[i] ^ in[i]) & control + } +} + +func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) { + var xx, yy, zz p224FieldElement + for i := 0; i < 8; i++ { + outX[i] = 0 + outY[i] = 0 + outZ[i] = 0 + } + + for _, byte := range scalar { + for bitNum := uint(0); bitNum < 8; bitNum++ { + p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ) + bit := uint32((byte >> (7 - bitNum)) & 1) + p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ) + p224CopyConditional(outX, &xx, bit) + p224CopyConditional(outY, &yy, bit) + p224CopyConditional(outZ, &zz, bit) + } + } +} + +// p224ToAffine converts from Jacobian to affine form. +func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) { + var zinv, zinvsq, outx, outy p224FieldElement + var tmp p224LargeFieldElement + + if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 { + return new(big.Int), new(big.Int) + } + + p224Invert(&zinv, z) + p224Square(&zinvsq, &zinv, &tmp) + p224Mul(x, x, &zinvsq, &tmp) + p224Mul(&zinvsq, &zinvsq, &zinv, &tmp) + p224Mul(y, y, &zinvsq, &tmp) + + p224Contract(&outx, x) + p224Contract(&outy, y) + return p224ToBig(&outx), p224ToBig(&outy) +} + +// get28BitsFromEnd returns the least-significant 28 bits from buf>>shift, +// where buf is interpreted as a big-endian number. +func get28BitsFromEnd(buf []byte, shift uint) (uint32, []byte) { + var ret uint32 + + for i := uint(0); i < 4; i++ { + var b byte + if l := len(buf); l > 0 { + b = buf[l-1] + // We don't remove the byte if we're about to return and we're not + // reading all of it. + if i != 3 || shift == 4 { + buf = buf[:l-1] + } + } + ret |= uint32(b) << (8 * i) >> shift + } + ret &= bottom28Bits + return ret, buf +} + +// p224FromBig sets *out = *in. +func p224FromBig(out *p224FieldElement, in *big.Int) { + bytes := in.Bytes() + out[0], bytes = get28BitsFromEnd(bytes, 0) + out[1], bytes = get28BitsFromEnd(bytes, 4) + out[2], bytes = get28BitsFromEnd(bytes, 0) + out[3], bytes = get28BitsFromEnd(bytes, 4) + out[4], bytes = get28BitsFromEnd(bytes, 0) + out[5], bytes = get28BitsFromEnd(bytes, 4) + out[6], bytes = get28BitsFromEnd(bytes, 0) + out[7], bytes = get28BitsFromEnd(bytes, 4) +} + +// p224ToBig returns in as a big.Int. +func p224ToBig(in *p224FieldElement) *big.Int { + var buf [28]byte + buf[27] = byte(in[0]) + buf[26] = byte(in[0] >> 8) + buf[25] = byte(in[0] >> 16) + buf[24] = byte(((in[0] >> 24) & 0x0f) | (in[1]<<4)&0xf0) + + buf[23] = byte(in[1] >> 4) + buf[22] = byte(in[1] >> 12) + buf[21] = byte(in[1] >> 20) + + buf[20] = byte(in[2]) + buf[19] = byte(in[2] >> 8) + buf[18] = byte(in[2] >> 16) + buf[17] = byte(((in[2] >> 24) & 0x0f) | (in[3]<<4)&0xf0) + + buf[16] = byte(in[3] >> 4) + buf[15] = byte(in[3] >> 12) + buf[14] = byte(in[3] >> 20) + + buf[13] = byte(in[4]) + buf[12] = byte(in[4] >> 8) + buf[11] = byte(in[4] >> 16) + buf[10] = byte(((in[4] >> 24) & 0x0f) | (in[5]<<4)&0xf0) + + buf[9] = byte(in[5] >> 4) + buf[8] = byte(in[5] >> 12) + buf[7] = byte(in[5] >> 20) + + buf[6] = byte(in[6]) + buf[5] = byte(in[6] >> 8) + buf[4] = byte(in[6] >> 16) + buf[3] = byte(((in[6] >> 24) & 0x0f) | (in[7]<<4)&0xf0) + + buf[2] = byte(in[7] >> 4) + buf[1] = byte(in[7] >> 12) + buf[0] = byte(in[7] >> 20) + + return new(big.Int).SetBytes(buf[:]) +} diff --git a/src/crypto/elliptic/p224_test.go b/src/crypto/elliptic/p224_test.go new file mode 100644 index 0000000..b213b27 --- /dev/null +++ b/src/crypto/elliptic/p224_test.go @@ -0,0 +1,629 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +import ( + "encoding/hex" + "fmt" + "math/big" + "math/bits" + "math/rand" + "reflect" + "testing" + "testing/quick" +) + +var toFromBigTests = []string{ + "0", + "1", + "23", + "b70e0cb46bb4bf7f321390b94a03c1d356c01122343280d6105c1d21", + "706a46d476dcb76798e6046d89474788d164c18032d268fd10704fa6", +} + +func p224AlternativeToBig(in *p224FieldElement) *big.Int { + ret := new(big.Int) + tmp := new(big.Int) + + for i := len(in) - 1; i >= 0; i-- { + ret.Lsh(ret, 28) + tmp.SetInt64(int64(in[i])) + ret.Add(ret, tmp) + } + ret.Mod(ret, P224().Params().P) + return ret +} + +func TestP224ToFromBig(t *testing.T) { + for i, test := range toFromBigTests { + n, _ := new(big.Int).SetString(test, 16) + var x p224FieldElement + p224FromBig(&x, n) + m := p224ToBig(&x) + if n.Cmp(m) != 0 { + t.Errorf("#%d: %x != %x", i, n, m) + } + q := p224AlternativeToBig(&x) + if n.Cmp(q) != 0 { + t.Errorf("#%d: %x != %x (alternative)", i, n, q) + } + } +} + +// quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks) +// times. The default value of -quickchecks is 100. +var quickCheckConfig32 = &quick.Config{MaxCountScale: 32} + +// weirdLimbs can be combined to generate a range of edge-case field elements. +var weirdLimbs = [...]uint32{ + 0, 1, (1 << 29) - 1, + (1 << 12), (1 << 12) - 1, + (1 << 28), (1 << 28) - 1, +} + +func generateLimb(rand *rand.Rand) uint32 { + const bottom29Bits = 0x1fffffff + n := rand.Intn(len(weirdLimbs) + 3) + switch n { + case len(weirdLimbs): + // Random value. + return uint32(rand.Int31n(1 << 29)) + case len(weirdLimbs) + 1: + // Sum of two values. + k := generateLimb(rand) + generateLimb(rand) + return k & bottom29Bits + case len(weirdLimbs) + 2: + // Difference of two values. + k := generateLimb(rand) - generateLimb(rand) + return k & bottom29Bits + default: + return weirdLimbs[n] + } +} + +func (p224FieldElement) Generate(rand *rand.Rand, size int) reflect.Value { + return reflect.ValueOf(p224FieldElement{ + generateLimb(rand), + generateLimb(rand), + generateLimb(rand), + generateLimb(rand), + generateLimb(rand), + generateLimb(rand), + generateLimb(rand), + generateLimb(rand), + }) +} + +func isInBounds(x *p224FieldElement) bool { + return bits.Len32(x[0]) <= 29 && + bits.Len32(x[1]) <= 29 && + bits.Len32(x[2]) <= 29 && + bits.Len32(x[3]) <= 29 && + bits.Len32(x[4]) <= 29 && + bits.Len32(x[5]) <= 29 && + bits.Len32(x[6]) <= 29 && + bits.Len32(x[7]) <= 29 +} + +func TestP224Mul(t *testing.T) { + mulMatchesBigInt := func(a, b, out p224FieldElement) bool { + var tmp p224LargeFieldElement + p224Mul(&out, &a, &b, &tmp) + + exp := new(big.Int).Mul(p224AlternativeToBig(&a), p224AlternativeToBig(&b)) + exp.Mod(exp, P224().Params().P) + got := p224AlternativeToBig(&out) + if exp.Cmp(got) != 0 || !isInBounds(&out) { + t.Logf("a = %x", a) + t.Logf("b = %x", b) + t.Logf("p224Mul(a, b) = %x = %v", out, got) + t.Logf("a * b = %v", exp) + return false + } + + return true + } + + a := p224FieldElement{0xfffffff, 0xfffffff, 0xf00ffff, 0x20f, 0x0, 0x0, 0x0, 0x0} + b := p224FieldElement{1, 0, 0, 0, 0, 0, 0, 0} + if !mulMatchesBigInt(a, b, p224FieldElement{}) { + t.Fail() + } + + if err := quick.Check(mulMatchesBigInt, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestP224Square(t *testing.T) { + squareMatchesBigInt := func(a, out p224FieldElement) bool { + var tmp p224LargeFieldElement + p224Square(&out, &a, &tmp) + + exp := p224AlternativeToBig(&a) + exp.Mul(exp, exp) + exp.Mod(exp, P224().Params().P) + got := p224AlternativeToBig(&out) + if exp.Cmp(got) != 0 || !isInBounds(&out) { + t.Logf("a = %x", a) + t.Logf("p224Square(a, b) = %x = %v", out, got) + t.Logf("a * a = %v", exp) + return false + } + + return true + } + + if err := quick.Check(squareMatchesBigInt, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestP224Add(t *testing.T) { + addMatchesBigInt := func(a, b, out p224FieldElement) bool { + p224Add(&out, &a, &b) + + exp := new(big.Int).Add(p224AlternativeToBig(&a), p224AlternativeToBig(&b)) + exp.Mod(exp, P224().Params().P) + got := p224AlternativeToBig(&out) + if exp.Cmp(got) != 0 { + t.Logf("a = %x", a) + t.Logf("b = %x", b) + t.Logf("p224Add(a, b) = %x = %v", out, got) + t.Logf("a + b = %v", exp) + return false + } + + return true + } + + if err := quick.Check(addMatchesBigInt, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestP224Reduce(t *testing.T) { + reduceMatchesBigInt := func(a p224FieldElement) bool { + out := a + // TODO: generate higher values for functions like p224Reduce that are + // expected to work with higher input bounds. + p224Reduce(&out) + + exp := p224AlternativeToBig(&a) + got := p224AlternativeToBig(&out) + if exp.Cmp(got) != 0 || !isInBounds(&out) { + t.Logf("a = %x = %v", a, exp) + t.Logf("p224Reduce(a) = %x = %v", out, got) + return false + } + + return true + } + + if err := quick.Check(reduceMatchesBigInt, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestP224Contract(t *testing.T) { + contractMatchesBigInt := func(a, out p224FieldElement) bool { + p224Contract(&out, &a) + + exp := p224AlternativeToBig(&a) + got := p224AlternativeToBig(&out) + if exp.Cmp(got) != 0 { + t.Logf("a = %x = %v", a, exp) + t.Logf("p224Contract(a) = %x = %v", out, got) + return false + } + + // Check that out < P. + for i := range p224P { + k := 8 - i - 1 + if out[k] > p224P[k] { + t.Logf("p224Contract(a) = %x", out) + return false + } + if out[k] < p224P[k] { + return true + } + } + t.Logf("p224Contract(a) = %x", out) + return false + } + + if !contractMatchesBigInt(p224P, p224FieldElement{}) { + t.Error("p224Contract(p) is broken") + } + pMinus1 := p224FieldElement{0, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} + if !contractMatchesBigInt(pMinus1, p224FieldElement{}) { + t.Error("p224Contract(p - 1) is broken") + } + // Check that we can handle input above p, but lowest limb zero. + a := p224FieldElement{0, 1, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} + if !contractMatchesBigInt(a, p224FieldElement{}) { + t.Error("p224Contract(p + 2²⁸) is broken") + } + // Check that we can handle input above p, but lowest three limbs zero. + b := p224FieldElement{0, 0, 0, 0xffff001, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} + if !contractMatchesBigInt(b, p224FieldElement{}) { + t.Error("p224Contract(p + 2⁸⁴) is broken") + } + + if err := quick.Check(contractMatchesBigInt, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestP224IsZero(t *testing.T) { + if got := p224IsZero(&p224FieldElement{}); got != 1 { + t.Errorf("p224IsZero(0) = %d, expected 1", got) + } + if got := p224IsZero((*p224FieldElement)(&p224P)); got != 1 { + t.Errorf("p224IsZero(p) = %d, expected 1", got) + } + if got := p224IsZero(&p224FieldElement{1}); got != 0 { + t.Errorf("p224IsZero(1) = %d, expected 0", got) + } + + isZeroMatchesBigInt := func(a p224FieldElement) bool { + isZero := p224IsZero(&a) + + big := p224AlternativeToBig(&a) + if big.Sign() == 0 && isZero != 1 { + return false + } + if big.Sign() != 0 && isZero != 0 { + return false + } + return true + } + + if err := quick.Check(isZeroMatchesBigInt, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestP224Invert(t *testing.T) { + var out p224FieldElement + + p224Invert(&out, &p224FieldElement{}) + if got := p224IsZero(&out); got != 1 { + t.Errorf("p224Invert(0) = %x, expected 0", out) + } + + p224Invert(&out, (*p224FieldElement)(&p224P)) + if got := p224IsZero(&out); got != 1 { + t.Errorf("p224Invert(p) = %x, expected 0", out) + } + + p224Invert(&out, &p224FieldElement{1}) + p224Contract(&out, &out) + if out != (p224FieldElement{1}) { + t.Errorf("p224Invert(1) = %x, expected 1", out) + } + + var tmp p224LargeFieldElement + a := p224FieldElement{1, 2, 3, 4, 5, 6, 7, 8} + p224Invert(&out, &a) + p224Mul(&out, &out, &a, &tmp) + p224Contract(&out, &out) + if out != (p224FieldElement{1}) { + t.Errorf("p224Invert(a) * a = %x, expected 1", out) + } +} + +type baseMultTest struct { + k string + x, y string +} + +var p224BaseMultTests = []baseMultTest{ + { + "1", + "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", + "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", + }, + { + "2", + "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", + "1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb", + }, + { + "3", + "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", + "a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925", + }, + { + "4", + "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", + "482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9", + }, + { + "5", + "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", + "27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b", + }, + { + "6", + "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", + "89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e", + }, + { + "7", + "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", + "f3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963", + }, + { + "8", + "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", + "46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a", + }, + { + "9", + "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", + "371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463", + }, + { + "10", + "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", + "39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f", + }, + { + "11", + "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", + "20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da", + }, + { + "12", + "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", + "207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13", + }, + { + "13", + "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", + "252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767", + }, + { + "14", + "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", + "d5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf", + }, + { + "15", + "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", + "979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989", + }, + { + "16", + "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", + "3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482", + }, + { + "17", + "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", + "ff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26", + }, + { + "18", + "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", + "ea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002", + }, + { + "19", + "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", + "dcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd", + }, + { + "20", + "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", + "d5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530", + }, + { + "112233445566778899", + "61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e", + "2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4", + }, + { + "112233445566778899112233445566778899", + "29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35", + "3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93", + }, + { + "6950511619965839450988900688150712778015737983940691968051900319680", + "ab689930bcae4a4aa5f5cb085e823e8ae30fd365eb1da4aba9cf0379", + "3345a121bbd233548af0d210654eb40bab788a03666419be6fbd34e7", + }, + { + "13479972933410060327035789020509431695094902435494295338570602119423", + "bdb6a8817c1f89da1c2f3dd8e97feb4494f2ed302a4ce2bc7f5f4025", + "4c7020d57c00411889462d77a5438bb4e97d177700bf7243a07f1680", + }, + { + "13479971751745682581351455311314208093898607229429740618390390702079", + "d58b61aa41c32dd5eba462647dba75c5d67c83606c0af2bd928446a9", + "d24ba6a837be0460dd107ae77725696d211446c5609b4595976b16bd", + }, + { + "13479972931865328106486971546324465392952975980343228160962702868479", + "dc9fa77978a005510980e929a1485f63716df695d7a0c18bb518df03", + "ede2b016f2ddffc2a8c015b134928275ce09e5661b7ab14ce0d1d403", + }, + { + "11795773708834916026404142434151065506931607341523388140225443265536", + "499d8b2829cfb879c901f7d85d357045edab55028824d0f05ba279ba", + "bf929537b06e4015919639d94f57838fa33fc3d952598dcdbb44d638", + }, + { + "784254593043826236572847595991346435467177662189391577090", + "8246c999137186632c5f9eddf3b1b0e1764c5e8bd0e0d8a554b9cb77", + "e80ed8660bc1cb17ac7d845be40a7a022d3306f116ae9f81fea65947", + }, + { + "13479767645505654746623887797783387853576174193480695826442858012671", + "6670c20afcceaea672c97f75e2e9dd5c8460e54bb38538ebb4bd30eb", + "f280d8008d07a4caf54271f993527d46ff3ff46fd1190a3f1faa4f74", + }, + { + "205688069665150753842126177372015544874550518966168735589597183", + "eca934247425cfd949b795cb5ce1eff401550386e28d1a4c5a8eb", + "d4c01040dba19628931bc8855370317c722cbd9ca6156985f1c2e9ce", + }, + { + "13479966930919337728895168462090683249159702977113823384618282123295", + "ef353bf5c73cd551b96d596fbc9a67f16d61dd9fe56af19de1fba9cd", + "21771b9cdce3e8430c09b3838be70b48c21e15bc09ee1f2d7945b91f", + }, + { + "50210731791415612487756441341851895584393717453129007497216", + "4036052a3091eb481046ad3289c95d3ac905ca0023de2c03ecd451cf", + "d768165a38a2b96f812586a9d59d4136035d9c853a5bf2e1c86a4993", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368041", + "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", + "f2a28eefd8b345832116f1e574f2c6b2c895aa8c24941f40d8b80ad1", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368042", + "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", + "230e093c24f638f533dac6e2b6d01da3b5e7f45429315ca93fb8e634", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368043", + "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", + "156729f1a003647030666054e208180f8f7b0df2249e44fba5931fff", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368044", + "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", + "eb610599f95942df1082e4f9426d086fb9c6231ae8b24933aab5db", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368045", + "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", + "cc662b9bcba6f94ee4ff1c9c10bd6ddd0d138df2d099a282152a4b7f", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368046", + "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", + "6865a0b8a607f0b04b13d1cb0aa992a5a97f5ee8ca1849efb9ed8678", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368047", + "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", + "2a7eb328dbe663b5a468b5bc97a040a3745396ba636b964370dc3352", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368048", + "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", + "dad7e608e380480434ea641cc82c82cbc92801469c8db0204f13489a", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368049", + "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", + "df82220fc7a4021549165325725f94c3410ddb56c54e161fc9ef62ee", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368050", + "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", + "df4aefffbf6d1699c930481cd102127c9a3d992048ab05929b6e5927", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368051", + "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", + "c644cf154cc81f5ade49345e541b4d4b5c1adb3eb5c01c14ee949aa2", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368052", + "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", + "c8e8cd1b0be40b0877cfca1958603122f1e6914f84b7e8e968ae8b9e", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368053", + "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", + "fb9232c15a3bc7673a3a03b0253824c53d0fd1411b1cabe2e187fb87", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368054", + "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", + "f0c5cff7ab680d09ee11dae84e9c1072ac48ea2e744b1b7f72fd469e", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368055", + "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", + "76050f3348af2664aac3a8b05281304ebc7a7914c6ad50a4b4eac383", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368056", + "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", + "d817400e8ba9ca13a45f360e3d121eaaeb39af82d6001c8186f5f866", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368057", + "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", + "fb7da7f5f13a43b81774373c879cd32d6934c05fa758eeb14fcfab38", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368058", + "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", + "5c080fc3522f41bbb3f55a97cfecf21f882ce8cbb1e50ca6e67e56dc", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368059", + "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", + "e3d4895843da188fd58fb0567976d7b50359d6b78530c8f62d1b1746", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368060", + "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", + "42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd", + }, +} + +func TestP224BaseMult(t *testing.T) { + p224 := P224() + for i, e := range p224BaseMultTests { + k, ok := new(big.Int).SetString(e.k, 10) + if !ok { + t.Errorf("%d: bad value for k: %s", i, e.k) + } + x, y := p224.ScalarBaseMult(k.Bytes()) + if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y { + t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y) + } + if testing.Short() && i > 5 { + break + } + } +} + +func TestP224GenericBaseMult(t *testing.T) { + // We use the P224 CurveParams directly in order to test the generic implementation. + p224 := P224().Params() + for i, e := range p224BaseMultTests { + k, ok := new(big.Int).SetString(e.k, 10) + if !ok { + t.Errorf("%d: bad value for k: %s", i, e.k) + } + x, y := p224.ScalarBaseMult(k.Bytes()) + if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y { + t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y) + } + if testing.Short() && i > 5 { + break + } + } +} + +func TestP224Overflow(t *testing.T) { + // This tests for a specific bug in the P224 implementation. + p224 := P224() + pointData, _ := hex.DecodeString("049B535B45FB0A2072398A6831834624C7E32CCFD5A4B933BCEAF77F1DD945E08BBE5178F5EDF5E733388F196D2A631D2E075BB16CBFEEA15B") + x, y := Unmarshal(p224, pointData) + if !p224.IsOnCurve(x, y) { + t.Error("P224 failed to validate a correct point") + } +} diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go new file mode 100644 index 0000000..da52837 --- /dev/null +++ b/src/crypto/elliptic/p256.go @@ -0,0 +1,1193 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 && !arm64 +// +build !amd64,!arm64 + +package elliptic + +// This file contains a constant-time, 32-bit implementation of P256. + +import ( + "math/big" +) + +type p256Curve struct { + *CurveParams +} + +var ( + p256Params *CurveParams + + // RInverse contains 1/R mod p - the inverse of the Montgomery constant + // (2**257). + p256RInverse *big.Int +) + +func initP256() { + // See FIPS 186-3, section D.2.3 + p256Params = &CurveParams{Name: "P-256"} + p256Params.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10) + p256Params.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10) + p256Params.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16) + p256Params.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16) + p256Params.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16) + p256Params.BitSize = 256 + + p256RInverse, _ = new(big.Int).SetString("7fffffff00000001fffffffe8000000100000000ffffffff0000000180000000", 16) + + // Arch-specific initialization, i.e. let a platform dynamically pick a P256 implementation + initP256Arch() +} + +func (curve p256Curve) Params() *CurveParams { + return curve.CurveParams +} + +// p256GetScalar endian-swaps the big-endian scalar value from in and writes it +// to out. If the scalar is equal or greater than the order of the group, it's +// reduced modulo that order. +func p256GetScalar(out *[32]byte, in []byte) { + n := new(big.Int).SetBytes(in) + var scalarBytes []byte + + if n.Cmp(p256Params.N) >= 0 || len(in) > len(out) { + n.Mod(n, p256Params.N) + scalarBytes = n.Bytes() + } else { + scalarBytes = in + } + + for i, v := range scalarBytes { + out[len(scalarBytes)-(1+i)] = v + } +} + +func (p256Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) { + var scalarReversed [32]byte + p256GetScalar(&scalarReversed, scalar) + + var x1, y1, z1 [p256Limbs]uint32 + p256ScalarBaseMult(&x1, &y1, &z1, &scalarReversed) + return p256ToAffine(&x1, &y1, &z1) +} + +func (p256Curve) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) { + var scalarReversed [32]byte + p256GetScalar(&scalarReversed, scalar) + + var px, py, x1, y1, z1 [p256Limbs]uint32 + p256FromBig(&px, bigX) + p256FromBig(&py, bigY) + p256ScalarMult(&x1, &y1, &z1, &px, &py, &scalarReversed) + return p256ToAffine(&x1, &y1, &z1) +} + +// Field elements are represented as nine, unsigned 32-bit words. +// +// The value of a field element is: +// x[0] + (x[1] * 2**29) + (x[2] * 2**57) + ... + (x[8] * 2**228) +// +// That is, each limb is alternately 29 or 28-bits wide in little-endian +// order. +// +// This means that a field element hits 2**257, rather than 2**256 as we would +// like. A 28, 29, ... pattern would cause us to hit 2**256, but that causes +// problems when multiplying as terms end up one bit short of a limb which +// would require much bit-shifting to correct. +// +// Finally, the values stored in a field element are in Montgomery form. So the +// value |y| is stored as (y*R) mod p, where p is the P-256 prime and R is +// 2**257. + +const ( + p256Limbs = 9 + bottom29Bits = 0x1fffffff +) + +var ( + // p256One is the number 1 as a field element. + p256One = [p256Limbs]uint32{2, 0, 0, 0xffff800, 0x1fffffff, 0xfffffff, 0x1fbfffff, 0x1ffffff, 0} + p256Zero = [p256Limbs]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0} + // p256P is the prime modulus as a field element. + p256P = [p256Limbs]uint32{0x1fffffff, 0xfffffff, 0x1fffffff, 0x3ff, 0, 0, 0x200000, 0xf000000, 0xfffffff} + // p2562P is the twice prime modulus as a field element. + p2562P = [p256Limbs]uint32{0x1ffffffe, 0xfffffff, 0x1fffffff, 0x7ff, 0, 0, 0x400000, 0xe000000, 0x1fffffff} +) + +// p256Precomputed contains precomputed values to aid the calculation of scalar +// multiples of the base point, G. It's actually two, equal length, tables +// concatenated. +// +// The first table contains (x,y) field element pairs for 16 multiples of the +// base point, G. +// +// Index | Index (binary) | Value +// 0 | 0000 | 0G (all zeros, omitted) +// 1 | 0001 | G +// 2 | 0010 | 2**64G +// 3 | 0011 | 2**64G + G +// 4 | 0100 | 2**128G +// 5 | 0101 | 2**128G + G +// 6 | 0110 | 2**128G + 2**64G +// 7 | 0111 | 2**128G + 2**64G + G +// 8 | 1000 | 2**192G +// 9 | 1001 | 2**192G + G +// 10 | 1010 | 2**192G + 2**64G +// 11 | 1011 | 2**192G + 2**64G + G +// 12 | 1100 | 2**192G + 2**128G +// 13 | 1101 | 2**192G + 2**128G + G +// 14 | 1110 | 2**192G + 2**128G + 2**64G +// 15 | 1111 | 2**192G + 2**128G + 2**64G + G +// +// The second table follows the same style, but the terms are 2**32G, +// 2**96G, 2**160G, 2**224G. +// +// This is ~2KB of data. +var p256Precomputed = [p256Limbs * 2 * 15 * 2]uint32{ + 0x11522878, 0xe730d41, 0xdb60179, 0x4afe2ff, 0x12883add, 0xcaddd88, 0x119e7edc, 0xd4a6eab, 0x3120bee, + 0x1d2aac15, 0xf25357c, 0x19e45cdd, 0x5c721d0, 0x1992c5a5, 0xa237487, 0x154ba21, 0x14b10bb, 0xae3fe3, + 0xd41a576, 0x922fc51, 0x234994f, 0x60b60d3, 0x164586ae, 0xce95f18, 0x1fe49073, 0x3fa36cc, 0x5ebcd2c, + 0xb402f2f, 0x15c70bf, 0x1561925c, 0x5a26704, 0xda91e90, 0xcdc1c7f, 0x1ea12446, 0xe1ade1e, 0xec91f22, + 0x26f7778, 0x566847e, 0xa0bec9e, 0x234f453, 0x1a31f21a, 0xd85e75c, 0x56c7109, 0xa267a00, 0xb57c050, + 0x98fb57, 0xaa837cc, 0x60c0792, 0xcfa5e19, 0x61bab9e, 0x589e39b, 0xa324c5, 0x7d6dee7, 0x2976e4b, + 0x1fc4124a, 0xa8c244b, 0x1ce86762, 0xcd61c7e, 0x1831c8e0, 0x75774e1, 0x1d96a5a9, 0x843a649, 0xc3ab0fa, + 0x6e2e7d5, 0x7673a2a, 0x178b65e8, 0x4003e9b, 0x1a1f11c2, 0x7816ea, 0xf643e11, 0x58c43df, 0xf423fc2, + 0x19633ffa, 0x891f2b2, 0x123c231c, 0x46add8c, 0x54700dd, 0x59e2b17, 0x172db40f, 0x83e277d, 0xb0dd609, + 0xfd1da12, 0x35c6e52, 0x19ede20c, 0xd19e0c0, 0x97d0f40, 0xb015b19, 0x449e3f5, 0xe10c9e, 0x33ab581, + 0x56a67ab, 0x577734d, 0x1dddc062, 0xc57b10d, 0x149b39d, 0x26a9e7b, 0xc35df9f, 0x48764cd, 0x76dbcca, + 0xca4b366, 0xe9303ab, 0x1a7480e7, 0x57e9e81, 0x1e13eb50, 0xf466cf3, 0x6f16b20, 0x4ba3173, 0xc168c33, + 0x15cb5439, 0x6a38e11, 0x73658bd, 0xb29564f, 0x3f6dc5b, 0x53b97e, 0x1322c4c0, 0x65dd7ff, 0x3a1e4f6, + 0x14e614aa, 0x9246317, 0x1bc83aca, 0xad97eed, 0xd38ce4a, 0xf82b006, 0x341f077, 0xa6add89, 0x4894acd, + 0x9f162d5, 0xf8410ef, 0x1b266a56, 0xd7f223, 0x3e0cb92, 0xe39b672, 0x6a2901a, 0x69a8556, 0x7e7c0, + 0x9b7d8d3, 0x309a80, 0x1ad05f7f, 0xc2fb5dd, 0xcbfd41d, 0x9ceb638, 0x1051825c, 0xda0cf5b, 0x812e881, + 0x6f35669, 0x6a56f2c, 0x1df8d184, 0x345820, 0x1477d477, 0x1645db1, 0xbe80c51, 0xc22be3e, 0xe35e65a, + 0x1aeb7aa0, 0xc375315, 0xf67bc99, 0x7fdd7b9, 0x191fc1be, 0x61235d, 0x2c184e9, 0x1c5a839, 0x47a1e26, + 0xb7cb456, 0x93e225d, 0x14f3c6ed, 0xccc1ac9, 0x17fe37f3, 0x4988989, 0x1a90c502, 0x2f32042, 0xa17769b, + 0xafd8c7c, 0x8191c6e, 0x1dcdb237, 0x16200c0, 0x107b32a1, 0x66c08db, 0x10d06a02, 0x3fc93, 0x5620023, + 0x16722b27, 0x68b5c59, 0x270fcfc, 0xfad0ecc, 0xe5de1c2, 0xeab466b, 0x2fc513c, 0x407f75c, 0xbaab133, + 0x9705fe9, 0xb88b8e7, 0x734c993, 0x1e1ff8f, 0x19156970, 0xabd0f00, 0x10469ea7, 0x3293ac0, 0xcdc98aa, + 0x1d843fd, 0xe14bfe8, 0x15be825f, 0x8b5212, 0xeb3fb67, 0x81cbd29, 0xbc62f16, 0x2b6fcc7, 0xf5a4e29, + 0x13560b66, 0xc0b6ac2, 0x51ae690, 0xd41e271, 0xf3e9bd4, 0x1d70aab, 0x1029f72, 0x73e1c35, 0xee70fbc, + 0xad81baf, 0x9ecc49a, 0x86c741e, 0xfe6be30, 0x176752e7, 0x23d416, 0x1f83de85, 0x27de188, 0x66f70b8, + 0x181cd51f, 0x96b6e4c, 0x188f2335, 0xa5df759, 0x17a77eb6, 0xfeb0e73, 0x154ae914, 0x2f3ec51, 0x3826b59, + 0xb91f17d, 0x1c72949, 0x1362bf0a, 0xe23fddf, 0xa5614b0, 0xf7d8f, 0x79061, 0x823d9d2, 0x8213f39, + 0x1128ae0b, 0xd095d05, 0xb85c0c2, 0x1ecb2ef, 0x24ddc84, 0xe35e901, 0x18411a4a, 0xf5ddc3d, 0x3786689, + 0x52260e8, 0x5ae3564, 0x542b10d, 0x8d93a45, 0x19952aa4, 0x996cc41, 0x1051a729, 0x4be3499, 0x52b23aa, + 0x109f307e, 0x6f5b6bb, 0x1f84e1e7, 0x77a0cfa, 0x10c4df3f, 0x25a02ea, 0xb048035, 0xe31de66, 0xc6ecaa3, + 0x28ea335, 0x2886024, 0x1372f020, 0xf55d35, 0x15e4684c, 0xf2a9e17, 0x1a4a7529, 0xcb7beb1, 0xb2a78a1, + 0x1ab21f1f, 0x6361ccf, 0x6c9179d, 0xb135627, 0x1267b974, 0x4408bad, 0x1cbff658, 0xe3d6511, 0xc7d76f, + 0x1cc7a69, 0xe7ee31b, 0x54fab4f, 0x2b914f, 0x1ad27a30, 0xcd3579e, 0xc50124c, 0x50daa90, 0xb13f72, + 0xb06aa75, 0x70f5cc6, 0x1649e5aa, 0x84a5312, 0x329043c, 0x41c4011, 0x13d32411, 0xb04a838, 0xd760d2d, + 0x1713b532, 0xbaa0c03, 0x84022ab, 0x6bcf5c1, 0x2f45379, 0x18ae070, 0x18c9e11e, 0x20bca9a, 0x66f496b, + 0x3eef294, 0x67500d2, 0xd7f613c, 0x2dbbeb, 0xb741038, 0xe04133f, 0x1582968d, 0xbe985f7, 0x1acbc1a, + 0x1a6a939f, 0x33e50f6, 0xd665ed4, 0xb4b7bd6, 0x1e5a3799, 0x6b33847, 0x17fa56ff, 0x65ef930, 0x21dc4a, + 0x2b37659, 0x450fe17, 0xb357b65, 0xdf5efac, 0x15397bef, 0x9d35a7f, 0x112ac15f, 0x624e62e, 0xa90ae2f, + 0x107eecd2, 0x1f69bbe, 0x77d6bce, 0x5741394, 0x13c684fc, 0x950c910, 0x725522b, 0xdc78583, 0x40eeabb, + 0x1fde328a, 0xbd61d96, 0xd28c387, 0x9e77d89, 0x12550c40, 0x759cb7d, 0x367ef34, 0xae2a960, 0x91b8bdc, + 0x93462a9, 0xf469ef, 0xb2e9aef, 0xd2ca771, 0x54e1f42, 0x7aaa49, 0x6316abb, 0x2413c8e, 0x5425bf9, + 0x1bed3e3a, 0xf272274, 0x1f5e7326, 0x6416517, 0xea27072, 0x9cedea7, 0x6e7633, 0x7c91952, 0xd806dce, + 0x8e2a7e1, 0xe421e1a, 0x418c9e1, 0x1dbc890, 0x1b395c36, 0xa1dc175, 0x1dc4ef73, 0x8956f34, 0xe4b5cf2, + 0x1b0d3a18, 0x3194a36, 0x6c2641f, 0xe44124c, 0xa2f4eaa, 0xa8c25ba, 0xf927ed7, 0x627b614, 0x7371cca, + 0xba16694, 0x417bc03, 0x7c0a7e3, 0x9c35c19, 0x1168a205, 0x8b6b00d, 0x10e3edc9, 0x9c19bf2, 0x5882229, + 0x1b2b4162, 0xa5cef1a, 0x1543622b, 0x9bd433e, 0x364e04d, 0x7480792, 0x5c9b5b3, 0xe85ff25, 0x408ef57, + 0x1814cfa4, 0x121b41b, 0xd248a0f, 0x3b05222, 0x39bb16a, 0xc75966d, 0xa038113, 0xa4a1769, 0x11fbc6c, + 0x917e50e, 0xeec3da8, 0x169d6eac, 0x10c1699, 0xa416153, 0xf724912, 0x15cd60b7, 0x4acbad9, 0x5efc5fa, + 0xf150ed7, 0x122b51, 0x1104b40a, 0xcb7f442, 0xfbb28ff, 0x6ac53ca, 0x196142cc, 0x7bf0fa9, 0x957651, + 0x4e0f215, 0xed439f8, 0x3f46bd5, 0x5ace82f, 0x110916b6, 0x6db078, 0xffd7d57, 0xf2ecaac, 0xca86dec, + 0x15d6b2da, 0x965ecc9, 0x1c92b4c2, 0x1f3811, 0x1cb080f5, 0x2d8b804, 0x19d1c12d, 0xf20bd46, 0x1951fa7, + 0xa3656c3, 0x523a425, 0xfcd0692, 0xd44ddc8, 0x131f0f5b, 0xaf80e4a, 0xcd9fc74, 0x99bb618, 0x2db944c, + 0xa673090, 0x1c210e1, 0x178c8d23, 0x1474383, 0x10b8743d, 0x985a55b, 0x2e74779, 0x576138, 0x9587927, + 0x133130fa, 0xbe05516, 0x9f4d619, 0xbb62570, 0x99ec591, 0xd9468fe, 0x1d07782d, 0xfc72e0b, 0x701b298, + 0x1863863b, 0x85954b8, 0x121a0c36, 0x9e7fedf, 0xf64b429, 0x9b9d71e, 0x14e2f5d8, 0xf858d3a, 0x942eea8, + 0xda5b765, 0x6edafff, 0xa9d18cc, 0xc65e4ba, 0x1c747e86, 0xe4ea915, 0x1981d7a1, 0x8395659, 0x52ed4e2, + 0x87d43b7, 0x37ab11b, 0x19d292ce, 0xf8d4692, 0x18c3053f, 0x8863e13, 0x4c146c0, 0x6bdf55a, 0x4e4457d, + 0x16152289, 0xac78ec2, 0x1a59c5a2, 0x2028b97, 0x71c2d01, 0x295851f, 0x404747b, 0x878558d, 0x7d29aa4, + 0x13d8341f, 0x8daefd7, 0x139c972d, 0x6b7ea75, 0xd4a9dde, 0xff163d8, 0x81d55d7, 0xa5bef68, 0xb7b30d8, + 0xbe73d6f, 0xaa88141, 0xd976c81, 0x7e7a9cc, 0x18beb771, 0xd773cbd, 0x13f51951, 0x9d0c177, 0x1c49a78, +} + +// Field element operations: + +// nonZeroToAllOnes returns: +// 0xffffffff for 0 < x <= 2**31 +// 0 for x == 0 or x > 2**31. +func nonZeroToAllOnes(x uint32) uint32 { + return ((x - 1) >> 31) - 1 +} + +// p256ReduceCarry adds a multiple of p in order to cancel |carry|, +// which is a term at 2**257. +// +// On entry: carry < 2**3, inout[0,2,...] < 2**29, inout[1,3,...] < 2**28. +// On exit: inout[0,2,..] < 2**30, inout[1,3,...] < 2**29. +func p256ReduceCarry(inout *[p256Limbs]uint32, carry uint32) { + carry_mask := nonZeroToAllOnes(carry) + + inout[0] += carry << 1 + inout[3] += 0x10000000 & carry_mask + // carry < 2**3 thus (carry << 11) < 2**14 and we added 2**28 in the + // previous line therefore this doesn't underflow. + inout[3] -= carry << 11 + inout[4] += (0x20000000 - 1) & carry_mask + inout[5] += (0x10000000 - 1) & carry_mask + inout[6] += (0x20000000 - 1) & carry_mask + inout[6] -= carry << 22 + // This may underflow if carry is non-zero but, if so, we'll fix it in the + // next line. + inout[7] -= 1 & carry_mask + inout[7] += carry << 25 +} + +// p256Sum sets out = in+in2. +// +// On entry, in[i]+in2[i] must not overflow a 32-bit word. +// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29 +func p256Sum(out, in, in2 *[p256Limbs]uint32) { + carry := uint32(0) + for i := 0; ; i++ { + out[i] = in[i] + in2[i] + out[i] += carry + carry = out[i] >> 29 + out[i] &= bottom29Bits + + i++ + if i == p256Limbs { + break + } + + out[i] = in[i] + in2[i] + out[i] += carry + carry = out[i] >> 28 + out[i] &= bottom28Bits + } + + p256ReduceCarry(out, carry) +} + +const ( + two30m2 = 1<<30 - 1<<2 + two30p13m2 = 1<<30 + 1<<13 - 1<<2 + two31m2 = 1<<31 - 1<<2 + two31p24m2 = 1<<31 + 1<<24 - 1<<2 + two30m27m2 = 1<<30 - 1<<27 - 1<<2 +) + +// p256Zero31 is 0 mod p. +var p256Zero31 = [p256Limbs]uint32{two31m3, two30m2, two31m2, two30p13m2, two31m2, two30m2, two31p24m2, two30m27m2, two31m2} + +// p256Diff sets out = in-in2. +// +// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29 and +// in2[0,2,...] < 2**30, in2[1,3,...] < 2**29. +// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +func p256Diff(out, in, in2 *[p256Limbs]uint32) { + var carry uint32 + + for i := 0; ; i++ { + out[i] = in[i] - in2[i] + out[i] += p256Zero31[i] + out[i] += carry + carry = out[i] >> 29 + out[i] &= bottom29Bits + + i++ + if i == p256Limbs { + break + } + + out[i] = in[i] - in2[i] + out[i] += p256Zero31[i] + out[i] += carry + carry = out[i] >> 28 + out[i] &= bottom28Bits + } + + p256ReduceCarry(out, carry) +} + +// p256ReduceDegree sets out = tmp/R mod p where tmp contains 64-bit words with +// the same 29,28,... bit positions as a field element. +// +// The values in field elements are in Montgomery form: x*R mod p where R = +// 2**257. Since we just multiplied two Montgomery values together, the result +// is x*y*R*R mod p. We wish to divide by R in order for the result also to be +// in Montgomery form. +// +// On entry: tmp[i] < 2**64 +// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29 +func p256ReduceDegree(out *[p256Limbs]uint32, tmp [17]uint64) { + // The following table may be helpful when reading this code: + // + // Limb number: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10... + // Width (bits): 29| 28| 29| 28| 29| 28| 29| 28| 29| 28| 29 + // Start bit: 0 | 29| 57| 86|114|143|171|200|228|257|285 + // (odd phase): 0 | 28| 57| 85|114|142|171|199|228|256|285 + var tmp2 [18]uint32 + var carry, x, xMask uint32 + + // tmp contains 64-bit words with the same 29,28,29-bit positions as a + // field element. So the top of an element of tmp might overlap with + // another element two positions down. The following loop eliminates + // this overlap. + tmp2[0] = uint32(tmp[0]) & bottom29Bits + + tmp2[1] = uint32(tmp[0]) >> 29 + tmp2[1] |= (uint32(tmp[0]>>32) << 3) & bottom28Bits + tmp2[1] += uint32(tmp[1]) & bottom28Bits + carry = tmp2[1] >> 28 + tmp2[1] &= bottom28Bits + + for i := 2; i < 17; i++ { + tmp2[i] = (uint32(tmp[i-2] >> 32)) >> 25 + tmp2[i] += (uint32(tmp[i-1])) >> 28 + tmp2[i] += (uint32(tmp[i-1]>>32) << 4) & bottom29Bits + tmp2[i] += uint32(tmp[i]) & bottom29Bits + tmp2[i] += carry + carry = tmp2[i] >> 29 + tmp2[i] &= bottom29Bits + + i++ + if i == 17 { + break + } + tmp2[i] = uint32(tmp[i-2]>>32) >> 25 + tmp2[i] += uint32(tmp[i-1]) >> 29 + tmp2[i] += ((uint32(tmp[i-1] >> 32)) << 3) & bottom28Bits + tmp2[i] += uint32(tmp[i]) & bottom28Bits + tmp2[i] += carry + carry = tmp2[i] >> 28 + tmp2[i] &= bottom28Bits + } + + tmp2[17] = uint32(tmp[15]>>32) >> 25 + tmp2[17] += uint32(tmp[16]) >> 29 + tmp2[17] += uint32(tmp[16]>>32) << 3 + tmp2[17] += carry + + // Montgomery elimination of terms: + // + // Since R is 2**257, we can divide by R with a bitwise shift if we can + // ensure that the right-most 257 bits are all zero. We can make that true + // by adding multiplies of p without affecting the value. + // + // So we eliminate limbs from right to left. Since the bottom 29 bits of p + // are all ones, then by adding tmp2[0]*p to tmp2 we'll make tmp2[0] == 0. + // We can do that for 8 further limbs and then right shift to eliminate the + // extra factor of R. + for i := 0; ; i += 2 { + tmp2[i+1] += tmp2[i] >> 29 + x = tmp2[i] & bottom29Bits + xMask = nonZeroToAllOnes(x) + tmp2[i] = 0 + + // The bounds calculations for this loop are tricky. Each iteration of + // the loop eliminates two words by adding values to words to their + // right. + // + // The following table contains the amounts added to each word (as an + // offset from the value of i at the top of the loop). The amounts are + // accounted for from the first and second half of the loop separately + // and are written as, for example, 28 to mean a value <2**28. + // + // Word: 3 4 5 6 7 8 9 10 + // Added in top half: 28 11 29 21 29 28 + // 28 29 + // 29 + // Added in bottom half: 29 10 28 21 28 28 + // 29 + // + // The value that is currently offset 7 will be offset 5 for the next + // iteration and then offset 3 for the iteration after that. Therefore + // the total value added will be the values added at 7, 5 and 3. + // + // The following table accumulates these values. The sums at the bottom + // are written as, for example, 29+28, to mean a value < 2**29+2**28. + // + // Word: 3 4 5 6 7 8 9 10 11 12 13 + // 28 11 10 29 21 29 28 28 28 28 28 + // 29 28 11 28 29 28 29 28 29 28 + // 29 28 21 21 29 21 29 21 + // 10 29 28 21 28 21 28 + // 28 29 28 29 28 29 28 + // 11 10 29 10 29 10 + // 29 28 11 28 11 + // 29 29 + // -------------------------------------------- + // 30+ 31+ 30+ 31+ 30+ + // 28+ 29+ 28+ 29+ 21+ + // 21+ 28+ 21+ 28+ 10 + // 10 21+ 10 21+ + // 11 11 + // + // So the greatest amount is added to tmp2[10] and tmp2[12]. If + // tmp2[10/12] has an initial value of <2**29, then the maximum value + // will be < 2**31 + 2**30 + 2**28 + 2**21 + 2**11, which is < 2**32, + // as required. + tmp2[i+3] += (x << 10) & bottom28Bits + tmp2[i+4] += (x >> 18) + + tmp2[i+6] += (x << 21) & bottom29Bits + tmp2[i+7] += x >> 8 + + // At position 200, which is the starting bit position for word 7, we + // have a factor of 0xf000000 = 2**28 - 2**24. + tmp2[i+7] += 0x10000000 & xMask + tmp2[i+8] += (x - 1) & xMask + tmp2[i+7] -= (x << 24) & bottom28Bits + tmp2[i+8] -= x >> 4 + + tmp2[i+8] += 0x20000000 & xMask + tmp2[i+8] -= x + tmp2[i+8] += (x << 28) & bottom29Bits + tmp2[i+9] += ((x >> 1) - 1) & xMask + + if i+1 == p256Limbs { + break + } + tmp2[i+2] += tmp2[i+1] >> 28 + x = tmp2[i+1] & bottom28Bits + xMask = nonZeroToAllOnes(x) + tmp2[i+1] = 0 + + tmp2[i+4] += (x << 11) & bottom29Bits + tmp2[i+5] += (x >> 18) + + tmp2[i+7] += (x << 21) & bottom28Bits + tmp2[i+8] += x >> 7 + + // At position 199, which is the starting bit of the 8th word when + // dealing with a context starting on an odd word, we have a factor of + // 0x1e000000 = 2**29 - 2**25. Since we have not updated i, the 8th + // word from i+1 is i+8. + tmp2[i+8] += 0x20000000 & xMask + tmp2[i+9] += (x - 1) & xMask + tmp2[i+8] -= (x << 25) & bottom29Bits + tmp2[i+9] -= x >> 4 + + tmp2[i+9] += 0x10000000 & xMask + tmp2[i+9] -= x + tmp2[i+10] += (x - 1) & xMask + } + + // We merge the right shift with a carry chain. The words above 2**257 have + // widths of 28,29,... which we need to correct when copying them down. + carry = 0 + for i := 0; i < 8; i++ { + // The maximum value of tmp2[i + 9] occurs on the first iteration and + // is < 2**30+2**29+2**28. Adding 2**29 (from tmp2[i + 10]) is + // therefore safe. + out[i] = tmp2[i+9] + out[i] += carry + out[i] += (tmp2[i+10] << 28) & bottom29Bits + carry = out[i] >> 29 + out[i] &= bottom29Bits + + i++ + out[i] = tmp2[i+9] >> 1 + out[i] += carry + carry = out[i] >> 28 + out[i] &= bottom28Bits + } + + out[8] = tmp2[17] + out[8] += carry + carry = out[8] >> 29 + out[8] &= bottom29Bits + + p256ReduceCarry(out, carry) +} + +// p256Square sets out=in*in. +// +// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29. +// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +func p256Square(out, in *[p256Limbs]uint32) { + var tmp [17]uint64 + + tmp[0] = uint64(in[0]) * uint64(in[0]) + tmp[1] = uint64(in[0]) * (uint64(in[1]) << 1) + tmp[2] = uint64(in[0])*(uint64(in[2])<<1) + + uint64(in[1])*(uint64(in[1])<<1) + tmp[3] = uint64(in[0])*(uint64(in[3])<<1) + + uint64(in[1])*(uint64(in[2])<<1) + tmp[4] = uint64(in[0])*(uint64(in[4])<<1) + + uint64(in[1])*(uint64(in[3])<<2) + + uint64(in[2])*uint64(in[2]) + tmp[5] = uint64(in[0])*(uint64(in[5])<<1) + + uint64(in[1])*(uint64(in[4])<<1) + + uint64(in[2])*(uint64(in[3])<<1) + tmp[6] = uint64(in[0])*(uint64(in[6])<<1) + + uint64(in[1])*(uint64(in[5])<<2) + + uint64(in[2])*(uint64(in[4])<<1) + + uint64(in[3])*(uint64(in[3])<<1) + tmp[7] = uint64(in[0])*(uint64(in[7])<<1) + + uint64(in[1])*(uint64(in[6])<<1) + + uint64(in[2])*(uint64(in[5])<<1) + + uint64(in[3])*(uint64(in[4])<<1) + // tmp[8] has the greatest value of 2**61 + 2**60 + 2**61 + 2**60 + 2**60, + // which is < 2**64 as required. + tmp[8] = uint64(in[0])*(uint64(in[8])<<1) + + uint64(in[1])*(uint64(in[7])<<2) + + uint64(in[2])*(uint64(in[6])<<1) + + uint64(in[3])*(uint64(in[5])<<2) + + uint64(in[4])*uint64(in[4]) + tmp[9] = uint64(in[1])*(uint64(in[8])<<1) + + uint64(in[2])*(uint64(in[7])<<1) + + uint64(in[3])*(uint64(in[6])<<1) + + uint64(in[4])*(uint64(in[5])<<1) + tmp[10] = uint64(in[2])*(uint64(in[8])<<1) + + uint64(in[3])*(uint64(in[7])<<2) + + uint64(in[4])*(uint64(in[6])<<1) + + uint64(in[5])*(uint64(in[5])<<1) + tmp[11] = uint64(in[3])*(uint64(in[8])<<1) + + uint64(in[4])*(uint64(in[7])<<1) + + uint64(in[5])*(uint64(in[6])<<1) + tmp[12] = uint64(in[4])*(uint64(in[8])<<1) + + uint64(in[5])*(uint64(in[7])<<2) + + uint64(in[6])*uint64(in[6]) + tmp[13] = uint64(in[5])*(uint64(in[8])<<1) + + uint64(in[6])*(uint64(in[7])<<1) + tmp[14] = uint64(in[6])*(uint64(in[8])<<1) + + uint64(in[7])*(uint64(in[7])<<1) + tmp[15] = uint64(in[7]) * (uint64(in[8]) << 1) + tmp[16] = uint64(in[8]) * uint64(in[8]) + + p256ReduceDegree(out, tmp) +} + +// p256Mul sets out=in*in2. +// +// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29 and +// in2[0,2,...] < 2**30, in2[1,3,...] < 2**29. +// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +func p256Mul(out, in, in2 *[p256Limbs]uint32) { + var tmp [17]uint64 + + tmp[0] = uint64(in[0]) * uint64(in2[0]) + tmp[1] = uint64(in[0])*(uint64(in2[1])<<0) + + uint64(in[1])*(uint64(in2[0])<<0) + tmp[2] = uint64(in[0])*(uint64(in2[2])<<0) + + uint64(in[1])*(uint64(in2[1])<<1) + + uint64(in[2])*(uint64(in2[0])<<0) + tmp[3] = uint64(in[0])*(uint64(in2[3])<<0) + + uint64(in[1])*(uint64(in2[2])<<0) + + uint64(in[2])*(uint64(in2[1])<<0) + + uint64(in[3])*(uint64(in2[0])<<0) + tmp[4] = uint64(in[0])*(uint64(in2[4])<<0) + + uint64(in[1])*(uint64(in2[3])<<1) + + uint64(in[2])*(uint64(in2[2])<<0) + + uint64(in[3])*(uint64(in2[1])<<1) + + uint64(in[4])*(uint64(in2[0])<<0) + tmp[5] = uint64(in[0])*(uint64(in2[5])<<0) + + uint64(in[1])*(uint64(in2[4])<<0) + + uint64(in[2])*(uint64(in2[3])<<0) + + uint64(in[3])*(uint64(in2[2])<<0) + + uint64(in[4])*(uint64(in2[1])<<0) + + uint64(in[5])*(uint64(in2[0])<<0) + tmp[6] = uint64(in[0])*(uint64(in2[6])<<0) + + uint64(in[1])*(uint64(in2[5])<<1) + + uint64(in[2])*(uint64(in2[4])<<0) + + uint64(in[3])*(uint64(in2[3])<<1) + + uint64(in[4])*(uint64(in2[2])<<0) + + uint64(in[5])*(uint64(in2[1])<<1) + + uint64(in[6])*(uint64(in2[0])<<0) + tmp[7] = uint64(in[0])*(uint64(in2[7])<<0) + + uint64(in[1])*(uint64(in2[6])<<0) + + uint64(in[2])*(uint64(in2[5])<<0) + + uint64(in[3])*(uint64(in2[4])<<0) + + uint64(in[4])*(uint64(in2[3])<<0) + + uint64(in[5])*(uint64(in2[2])<<0) + + uint64(in[6])*(uint64(in2[1])<<0) + + uint64(in[7])*(uint64(in2[0])<<0) + // tmp[8] has the greatest value but doesn't overflow. See logic in + // p256Square. + tmp[8] = uint64(in[0])*(uint64(in2[8])<<0) + + uint64(in[1])*(uint64(in2[7])<<1) + + uint64(in[2])*(uint64(in2[6])<<0) + + uint64(in[3])*(uint64(in2[5])<<1) + + uint64(in[4])*(uint64(in2[4])<<0) + + uint64(in[5])*(uint64(in2[3])<<1) + + uint64(in[6])*(uint64(in2[2])<<0) + + uint64(in[7])*(uint64(in2[1])<<1) + + uint64(in[8])*(uint64(in2[0])<<0) + tmp[9] = uint64(in[1])*(uint64(in2[8])<<0) + + uint64(in[2])*(uint64(in2[7])<<0) + + uint64(in[3])*(uint64(in2[6])<<0) + + uint64(in[4])*(uint64(in2[5])<<0) + + uint64(in[5])*(uint64(in2[4])<<0) + + uint64(in[6])*(uint64(in2[3])<<0) + + uint64(in[7])*(uint64(in2[2])<<0) + + uint64(in[8])*(uint64(in2[1])<<0) + tmp[10] = uint64(in[2])*(uint64(in2[8])<<0) + + uint64(in[3])*(uint64(in2[7])<<1) + + uint64(in[4])*(uint64(in2[6])<<0) + + uint64(in[5])*(uint64(in2[5])<<1) + + uint64(in[6])*(uint64(in2[4])<<0) + + uint64(in[7])*(uint64(in2[3])<<1) + + uint64(in[8])*(uint64(in2[2])<<0) + tmp[11] = uint64(in[3])*(uint64(in2[8])<<0) + + uint64(in[4])*(uint64(in2[7])<<0) + + uint64(in[5])*(uint64(in2[6])<<0) + + uint64(in[6])*(uint64(in2[5])<<0) + + uint64(in[7])*(uint64(in2[4])<<0) + + uint64(in[8])*(uint64(in2[3])<<0) + tmp[12] = uint64(in[4])*(uint64(in2[8])<<0) + + uint64(in[5])*(uint64(in2[7])<<1) + + uint64(in[6])*(uint64(in2[6])<<0) + + uint64(in[7])*(uint64(in2[5])<<1) + + uint64(in[8])*(uint64(in2[4])<<0) + tmp[13] = uint64(in[5])*(uint64(in2[8])<<0) + + uint64(in[6])*(uint64(in2[7])<<0) + + uint64(in[7])*(uint64(in2[6])<<0) + + uint64(in[8])*(uint64(in2[5])<<0) + tmp[14] = uint64(in[6])*(uint64(in2[8])<<0) + + uint64(in[7])*(uint64(in2[7])<<1) + + uint64(in[8])*(uint64(in2[6])<<0) + tmp[15] = uint64(in[7])*(uint64(in2[8])<<0) + + uint64(in[8])*(uint64(in2[7])<<0) + tmp[16] = uint64(in[8]) * (uint64(in2[8]) << 0) + + p256ReduceDegree(out, tmp) +} + +func p256Assign(out, in *[p256Limbs]uint32) { + *out = *in +} + +// p256Invert calculates |out| = |in|^{-1} +// +// Based on Fermat's Little Theorem: +// a^p = a (mod p) +// a^{p-1} = 1 (mod p) +// a^{p-2} = a^{-1} (mod p) +func p256Invert(out, in *[p256Limbs]uint32) { + var ftmp, ftmp2 [p256Limbs]uint32 + + // each e_I will hold |in|^{2^I - 1} + var e2, e4, e8, e16, e32, e64 [p256Limbs]uint32 + + p256Square(&ftmp, in) // 2^1 + p256Mul(&ftmp, in, &ftmp) // 2^2 - 2^0 + p256Assign(&e2, &ftmp) + p256Square(&ftmp, &ftmp) // 2^3 - 2^1 + p256Square(&ftmp, &ftmp) // 2^4 - 2^2 + p256Mul(&ftmp, &ftmp, &e2) // 2^4 - 2^0 + p256Assign(&e4, &ftmp) + p256Square(&ftmp, &ftmp) // 2^5 - 2^1 + p256Square(&ftmp, &ftmp) // 2^6 - 2^2 + p256Square(&ftmp, &ftmp) // 2^7 - 2^3 + p256Square(&ftmp, &ftmp) // 2^8 - 2^4 + p256Mul(&ftmp, &ftmp, &e4) // 2^8 - 2^0 + p256Assign(&e8, &ftmp) + for i := 0; i < 8; i++ { + p256Square(&ftmp, &ftmp) + } // 2^16 - 2^8 + p256Mul(&ftmp, &ftmp, &e8) // 2^16 - 2^0 + p256Assign(&e16, &ftmp) + for i := 0; i < 16; i++ { + p256Square(&ftmp, &ftmp) + } // 2^32 - 2^16 + p256Mul(&ftmp, &ftmp, &e16) // 2^32 - 2^0 + p256Assign(&e32, &ftmp) + for i := 0; i < 32; i++ { + p256Square(&ftmp, &ftmp) + } // 2^64 - 2^32 + p256Assign(&e64, &ftmp) + p256Mul(&ftmp, &ftmp, in) // 2^64 - 2^32 + 2^0 + for i := 0; i < 192; i++ { + p256Square(&ftmp, &ftmp) + } // 2^256 - 2^224 + 2^192 + + p256Mul(&ftmp2, &e64, &e32) // 2^64 - 2^0 + for i := 0; i < 16; i++ { + p256Square(&ftmp2, &ftmp2) + } // 2^80 - 2^16 + p256Mul(&ftmp2, &ftmp2, &e16) // 2^80 - 2^0 + for i := 0; i < 8; i++ { + p256Square(&ftmp2, &ftmp2) + } // 2^88 - 2^8 + p256Mul(&ftmp2, &ftmp2, &e8) // 2^88 - 2^0 + for i := 0; i < 4; i++ { + p256Square(&ftmp2, &ftmp2) + } // 2^92 - 2^4 + p256Mul(&ftmp2, &ftmp2, &e4) // 2^92 - 2^0 + p256Square(&ftmp2, &ftmp2) // 2^93 - 2^1 + p256Square(&ftmp2, &ftmp2) // 2^94 - 2^2 + p256Mul(&ftmp2, &ftmp2, &e2) // 2^94 - 2^0 + p256Square(&ftmp2, &ftmp2) // 2^95 - 2^1 + p256Square(&ftmp2, &ftmp2) // 2^96 - 2^2 + p256Mul(&ftmp2, &ftmp2, in) // 2^96 - 3 + + p256Mul(out, &ftmp2, &ftmp) // 2^256 - 2^224 + 2^192 + 2^96 - 3 +} + +// p256Scalar3 sets out=3*out. +// +// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +func p256Scalar3(out *[p256Limbs]uint32) { + var carry uint32 + + for i := 0; ; i++ { + out[i] *= 3 + out[i] += carry + carry = out[i] >> 29 + out[i] &= bottom29Bits + + i++ + if i == p256Limbs { + break + } + + out[i] *= 3 + out[i] += carry + carry = out[i] >> 28 + out[i] &= bottom28Bits + } + + p256ReduceCarry(out, carry) +} + +// p256Scalar4 sets out=4*out. +// +// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +func p256Scalar4(out *[p256Limbs]uint32) { + var carry, nextCarry uint32 + + for i := 0; ; i++ { + nextCarry = out[i] >> 27 + out[i] <<= 2 + out[i] &= bottom29Bits + out[i] += carry + carry = nextCarry + (out[i] >> 29) + out[i] &= bottom29Bits + + i++ + if i == p256Limbs { + break + } + nextCarry = out[i] >> 26 + out[i] <<= 2 + out[i] &= bottom28Bits + out[i] += carry + carry = nextCarry + (out[i] >> 28) + out[i] &= bottom28Bits + } + + p256ReduceCarry(out, carry) +} + +// p256Scalar8 sets out=8*out. +// +// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. +func p256Scalar8(out *[p256Limbs]uint32) { + var carry, nextCarry uint32 + + for i := 0; ; i++ { + nextCarry = out[i] >> 26 + out[i] <<= 3 + out[i] &= bottom29Bits + out[i] += carry + carry = nextCarry + (out[i] >> 29) + out[i] &= bottom29Bits + + i++ + if i == p256Limbs { + break + } + nextCarry = out[i] >> 25 + out[i] <<= 3 + out[i] &= bottom28Bits + out[i] += carry + carry = nextCarry + (out[i] >> 28) + out[i] &= bottom28Bits + } + + p256ReduceCarry(out, carry) +} + +// Group operations: +// +// Elements of the elliptic curve group are represented in Jacobian +// coordinates: (x, y, z). An affine point (x', y') is x'=x/z**2, y'=y/z**3 in +// Jacobian form. + +// p256PointDouble sets {xOut,yOut,zOut} = 2*{x,y,z}. +// +// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l +func p256PointDouble(xOut, yOut, zOut, x, y, z *[p256Limbs]uint32) { + var delta, gamma, alpha, beta, tmp, tmp2 [p256Limbs]uint32 + + p256Square(&delta, z) + p256Square(&gamma, y) + p256Mul(&beta, x, &gamma) + + p256Sum(&tmp, x, &delta) + p256Diff(&tmp2, x, &delta) + p256Mul(&alpha, &tmp, &tmp2) + p256Scalar3(&alpha) + + p256Sum(&tmp, y, z) + p256Square(&tmp, &tmp) + p256Diff(&tmp, &tmp, &gamma) + p256Diff(zOut, &tmp, &delta) + + p256Scalar4(&beta) + p256Square(xOut, &alpha) + p256Diff(xOut, xOut, &beta) + p256Diff(xOut, xOut, &beta) + + p256Diff(&tmp, &beta, xOut) + p256Mul(&tmp, &alpha, &tmp) + p256Square(&tmp2, &gamma) + p256Scalar8(&tmp2) + p256Diff(yOut, &tmp, &tmp2) +} + +// p256PointAddMixed sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,1}. +// (i.e. the second point is affine.) +// +// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl +// +// Note that this function does not handle P+P, infinity+P nor P+infinity +// correctly. +func p256PointAddMixed(xOut, yOut, zOut, x1, y1, z1, x2, y2 *[p256Limbs]uint32) { + var z1z1, z1z1z1, s2, u2, h, i, j, r, rr, v, tmp [p256Limbs]uint32 + + p256Square(&z1z1, z1) + p256Sum(&tmp, z1, z1) + + p256Mul(&u2, x2, &z1z1) + p256Mul(&z1z1z1, z1, &z1z1) + p256Mul(&s2, y2, &z1z1z1) + p256Diff(&h, &u2, x1) + p256Sum(&i, &h, &h) + p256Square(&i, &i) + p256Mul(&j, &h, &i) + p256Diff(&r, &s2, y1) + p256Sum(&r, &r, &r) + p256Mul(&v, x1, &i) + + p256Mul(zOut, &tmp, &h) + p256Square(&rr, &r) + p256Diff(xOut, &rr, &j) + p256Diff(xOut, xOut, &v) + p256Diff(xOut, xOut, &v) + + p256Diff(&tmp, &v, xOut) + p256Mul(yOut, &tmp, &r) + p256Mul(&tmp, y1, &j) + p256Diff(yOut, yOut, &tmp) + p256Diff(yOut, yOut, &tmp) +} + +// p256PointAdd sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,z2}. +// +// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl +// +// Note that this function does not handle P+P, infinity+P nor P+infinity +// correctly. +func p256PointAdd(xOut, yOut, zOut, x1, y1, z1, x2, y2, z2 *[p256Limbs]uint32) { + var z1z1, z1z1z1, z2z2, z2z2z2, s1, s2, u1, u2, h, i, j, r, rr, v, tmp [p256Limbs]uint32 + + p256Square(&z1z1, z1) + p256Square(&z2z2, z2) + p256Mul(&u1, x1, &z2z2) + + p256Sum(&tmp, z1, z2) + p256Square(&tmp, &tmp) + p256Diff(&tmp, &tmp, &z1z1) + p256Diff(&tmp, &tmp, &z2z2) + + p256Mul(&z2z2z2, z2, &z2z2) + p256Mul(&s1, y1, &z2z2z2) + + p256Mul(&u2, x2, &z1z1) + p256Mul(&z1z1z1, z1, &z1z1) + p256Mul(&s2, y2, &z1z1z1) + p256Diff(&h, &u2, &u1) + p256Sum(&i, &h, &h) + p256Square(&i, &i) + p256Mul(&j, &h, &i) + p256Diff(&r, &s2, &s1) + p256Sum(&r, &r, &r) + p256Mul(&v, &u1, &i) + + p256Mul(zOut, &tmp, &h) + p256Square(&rr, &r) + p256Diff(xOut, &rr, &j) + p256Diff(xOut, xOut, &v) + p256Diff(xOut, xOut, &v) + + p256Diff(&tmp, &v, xOut) + p256Mul(yOut, &tmp, &r) + p256Mul(&tmp, &s1, &j) + p256Diff(yOut, yOut, &tmp) + p256Diff(yOut, yOut, &tmp) +} + +// p256CopyConditional sets out=in if mask = 0xffffffff in constant time. +// +// On entry: mask is either 0 or 0xffffffff. +func p256CopyConditional(out, in *[p256Limbs]uint32, mask uint32) { + for i := 0; i < p256Limbs; i++ { + tmp := mask & (in[i] ^ out[i]) + out[i] ^= tmp + } +} + +// p256SelectAffinePoint sets {out_x,out_y} to the index'th entry of table. +// On entry: index < 16, table[0] must be zero. +func p256SelectAffinePoint(xOut, yOut *[p256Limbs]uint32, table []uint32, index uint32) { + for i := range xOut { + xOut[i] = 0 + } + for i := range yOut { + yOut[i] = 0 + } + + for i := uint32(1); i < 16; i++ { + mask := i ^ index + mask |= mask >> 2 + mask |= mask >> 1 + mask &= 1 + mask-- + for j := range xOut { + xOut[j] |= table[0] & mask + table = table[1:] + } + for j := range yOut { + yOut[j] |= table[0] & mask + table = table[1:] + } + } +} + +// p256SelectJacobianPoint sets {out_x,out_y,out_z} to the index'th entry of +// table. +// On entry: index < 16, table[0] must be zero. +func p256SelectJacobianPoint(xOut, yOut, zOut *[p256Limbs]uint32, table *[16][3][p256Limbs]uint32, index uint32) { + for i := range xOut { + xOut[i] = 0 + } + for i := range yOut { + yOut[i] = 0 + } + for i := range zOut { + zOut[i] = 0 + } + + // The implicit value at index 0 is all zero. We don't need to perform that + // iteration of the loop because we already set out_* to zero. + for i := uint32(1); i < 16; i++ { + mask := i ^ index + mask |= mask >> 2 + mask |= mask >> 1 + mask &= 1 + mask-- + for j := range xOut { + xOut[j] |= table[i][0][j] & mask + } + for j := range yOut { + yOut[j] |= table[i][1][j] & mask + } + for j := range zOut { + zOut[j] |= table[i][2][j] & mask + } + } +} + +// p256GetBit returns the bit'th bit of scalar. +func p256GetBit(scalar *[32]uint8, bit uint) uint32 { + return uint32(((scalar[bit>>3]) >> (bit & 7)) & 1) +} + +// p256ScalarBaseMult sets {xOut,yOut,zOut} = scalar*G where scalar is a +// little-endian number. Note that the value of scalar must be less than the +// order of the group. +func p256ScalarBaseMult(xOut, yOut, zOut *[p256Limbs]uint32, scalar *[32]uint8) { + nIsInfinityMask := ^uint32(0) + var pIsNoninfiniteMask, mask, tableOffset uint32 + var px, py, tx, ty, tz [p256Limbs]uint32 + + for i := range xOut { + xOut[i] = 0 + } + for i := range yOut { + yOut[i] = 0 + } + for i := range zOut { + zOut[i] = 0 + } + + // The loop adds bits at positions 0, 64, 128 and 192, followed by + // positions 32,96,160 and 224 and does this 32 times. + for i := uint(0); i < 32; i++ { + if i != 0 { + p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut) + } + tableOffset = 0 + for j := uint(0); j <= 32; j += 32 { + bit0 := p256GetBit(scalar, 31-i+j) + bit1 := p256GetBit(scalar, 95-i+j) + bit2 := p256GetBit(scalar, 159-i+j) + bit3 := p256GetBit(scalar, 223-i+j) + index := bit0 | (bit1 << 1) | (bit2 << 2) | (bit3 << 3) + + p256SelectAffinePoint(&px, &py, p256Precomputed[tableOffset:], index) + tableOffset += 30 * p256Limbs + + // Since scalar is less than the order of the group, we know that + // {xOut,yOut,zOut} != {px,py,1}, unless both are zero, which we handle + // below. + p256PointAddMixed(&tx, &ty, &tz, xOut, yOut, zOut, &px, &py) + // The result of pointAddMixed is incorrect if {xOut,yOut,zOut} is zero + // (a.k.a. the point at infinity). We handle that situation by + // copying the point from the table. + p256CopyConditional(xOut, &px, nIsInfinityMask) + p256CopyConditional(yOut, &py, nIsInfinityMask) + p256CopyConditional(zOut, &p256One, nIsInfinityMask) + + // Equally, the result is also wrong if the point from the table is + // zero, which happens when the index is zero. We handle that by + // only copying from {tx,ty,tz} to {xOut,yOut,zOut} if index != 0. + pIsNoninfiniteMask = nonZeroToAllOnes(index) + mask = pIsNoninfiniteMask & ^nIsInfinityMask + p256CopyConditional(xOut, &tx, mask) + p256CopyConditional(yOut, &ty, mask) + p256CopyConditional(zOut, &tz, mask) + // If p was not zero, then n is now non-zero. + nIsInfinityMask &^= pIsNoninfiniteMask + } + } +} + +// p256PointToAffine converts a Jacobian point to an affine point. If the input +// is the point at infinity then it returns (0, 0) in constant time. +func p256PointToAffine(xOut, yOut, x, y, z *[p256Limbs]uint32) { + var zInv, zInvSq [p256Limbs]uint32 + + p256Invert(&zInv, z) + p256Square(&zInvSq, &zInv) + p256Mul(xOut, x, &zInvSq) + p256Mul(&zInv, &zInv, &zInvSq) + p256Mul(yOut, y, &zInv) +} + +// p256ToAffine returns a pair of *big.Int containing the affine representation +// of {x,y,z}. +func p256ToAffine(x, y, z *[p256Limbs]uint32) (xOut, yOut *big.Int) { + var xx, yy [p256Limbs]uint32 + p256PointToAffine(&xx, &yy, x, y, z) + return p256ToBig(&xx), p256ToBig(&yy) +} + +// p256ScalarMult sets {xOut,yOut,zOut} = scalar*{x,y}. +func p256ScalarMult(xOut, yOut, zOut, x, y *[p256Limbs]uint32, scalar *[32]uint8) { + var px, py, pz, tx, ty, tz [p256Limbs]uint32 + var precomp [16][3][p256Limbs]uint32 + var nIsInfinityMask, index, pIsNoninfiniteMask, mask uint32 + + // We precompute 0,1,2,... times {x,y}. + precomp[1][0] = *x + precomp[1][1] = *y + precomp[1][2] = p256One + + for i := 2; i < 16; i += 2 { + p256PointDouble(&precomp[i][0], &precomp[i][1], &precomp[i][2], &precomp[i/2][0], &precomp[i/2][1], &precomp[i/2][2]) + p256PointAddMixed(&precomp[i+1][0], &precomp[i+1][1], &precomp[i+1][2], &precomp[i][0], &precomp[i][1], &precomp[i][2], x, y) + } + + for i := range xOut { + xOut[i] = 0 + } + for i := range yOut { + yOut[i] = 0 + } + for i := range zOut { + zOut[i] = 0 + } + nIsInfinityMask = ^uint32(0) + + // We add in a window of four bits each iteration and do this 64 times. + for i := 0; i < 64; i++ { + if i != 0 { + p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut) + p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut) + p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut) + p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut) + } + + index = uint32(scalar[31-i/2]) + if (i & 1) == 1 { + index &= 15 + } else { + index >>= 4 + } + + // See the comments in scalarBaseMult about handling infinities. + p256SelectJacobianPoint(&px, &py, &pz, &precomp, index) + p256PointAdd(&tx, &ty, &tz, xOut, yOut, zOut, &px, &py, &pz) + p256CopyConditional(xOut, &px, nIsInfinityMask) + p256CopyConditional(yOut, &py, nIsInfinityMask) + p256CopyConditional(zOut, &pz, nIsInfinityMask) + + pIsNoninfiniteMask = nonZeroToAllOnes(index) + mask = pIsNoninfiniteMask & ^nIsInfinityMask + p256CopyConditional(xOut, &tx, mask) + p256CopyConditional(yOut, &ty, mask) + p256CopyConditional(zOut, &tz, mask) + nIsInfinityMask &^= pIsNoninfiniteMask + } +} + +// p256FromBig sets out = R*in. +func p256FromBig(out *[p256Limbs]uint32, in *big.Int) { + tmp := new(big.Int).Lsh(in, 257) + tmp.Mod(tmp, p256Params.P) + + for i := 0; i < p256Limbs; i++ { + if bits := tmp.Bits(); len(bits) > 0 { + out[i] = uint32(bits[0]) & bottom29Bits + } else { + out[i] = 0 + } + tmp.Rsh(tmp, 29) + + i++ + if i == p256Limbs { + break + } + + if bits := tmp.Bits(); len(bits) > 0 { + out[i] = uint32(bits[0]) & bottom28Bits + } else { + out[i] = 0 + } + tmp.Rsh(tmp, 28) + } +} + +// p256ToBig returns a *big.Int containing the value of in. +func p256ToBig(in *[p256Limbs]uint32) *big.Int { + result, tmp := new(big.Int), new(big.Int) + + result.SetInt64(int64(in[p256Limbs-1])) + for i := p256Limbs - 2; i >= 0; i-- { + if (i & 1) == 0 { + result.Lsh(result, 29) + } else { + result.Lsh(result, 28) + } + tmp.SetInt64(int64(in[i])) + result.Add(result, tmp) + } + + result.Mul(result, p256RInverse) + result.Mod(result, p256Params.P) + return result +} diff --git a/src/crypto/elliptic/p256_asm.go b/src/crypto/elliptic/p256_asm.go new file mode 100644 index 0000000..9a808f2 --- /dev/null +++ b/src/crypto/elliptic/p256_asm.go @@ -0,0 +1,539 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains the Go wrapper for the constant-time, 64-bit assembly +// implementation of P256. The optimizations performed here are described in +// detail in: +// S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with +// 256-bit primes" +// https://link.springer.com/article/10.1007%2Fs13389-014-0090-x +// https://eprint.iacr.org/2013/816.pdf + +//go:build amd64 || arm64 +// +build amd64 arm64 + +package elliptic + +import ( + "math/big" +) + +type ( + p256Curve struct { + *CurveParams + } + + p256Point struct { + xyz [12]uint64 + } +) + +var p256 p256Curve + +func initP256() { + // See FIPS 186-3, section D.2.3 + p256.CurveParams = &CurveParams{Name: "P-256"} + p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10) + p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10) + p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16) + p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16) + p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16) + p256.BitSize = 256 +} + +func (curve p256Curve) Params() *CurveParams { + return curve.CurveParams +} + +// Functions implemented in p256_asm_*64.s +// Montgomery multiplication modulo P256 +//go:noescape +func p256Mul(res, in1, in2 []uint64) + +// Montgomery square modulo P256, repeated n times (n >= 1) +//go:noescape +func p256Sqr(res, in []uint64, n int) + +// Montgomery multiplication by 1 +//go:noescape +func p256FromMont(res, in []uint64) + +// iff cond == 1 val <- -val +//go:noescape +func p256NegCond(val []uint64, cond int) + +// if cond == 0 res <- b; else res <- a +//go:noescape +func p256MovCond(res, a, b []uint64, cond int) + +// Endianness swap +//go:noescape +func p256BigToLittle(res []uint64, in []byte) + +//go:noescape +func p256LittleToBig(res []byte, in []uint64) + +// Constant time table access +//go:noescape +func p256Select(point, table []uint64, idx int) + +//go:noescape +func p256SelectBase(point, table []uint64, idx int) + +// Montgomery multiplication modulo Ord(G) +//go:noescape +func p256OrdMul(res, in1, in2 []uint64) + +// Montgomery square modulo Ord(G), repeated n times +//go:noescape +func p256OrdSqr(res, in []uint64, n int) + +// Point add with in2 being affine point +// If sign == 1 -> in2 = -in2 +// If sel == 0 -> res = in1 +// if zero == 0 -> res = in2 +//go:noescape +func p256PointAddAffineAsm(res, in1, in2 []uint64, sign, sel, zero int) + +// Point add. Returns one if the two input points were equal and zero +// otherwise. (Note that, due to the way that the equations work out, some +// representations of ∞ are considered equal to everything by this function.) +//go:noescape +func p256PointAddAsm(res, in1, in2 []uint64) int + +// Point double +//go:noescape +func p256PointDoubleAsm(res, in []uint64) + +func (curve p256Curve) Inverse(k *big.Int) *big.Int { + if k.Sign() < 0 { + // This should never happen. + k = new(big.Int).Neg(k) + } + + if k.Cmp(p256.N) >= 0 { + // This should never happen. + k = new(big.Int).Mod(k, p256.N) + } + + // table will store precomputed powers of x. + var table [4 * 9]uint64 + var ( + _1 = table[4*0 : 4*1] + _11 = table[4*1 : 4*2] + _101 = table[4*2 : 4*3] + _111 = table[4*3 : 4*4] + _1111 = table[4*4 : 4*5] + _10101 = table[4*5 : 4*6] + _101111 = table[4*6 : 4*7] + x = table[4*7 : 4*8] + t = table[4*8 : 4*9] + ) + + fromBig(x[:], k) + // This code operates in the Montgomery domain where R = 2^256 mod n + // and n is the order of the scalar field. (See initP256 for the + // value.) Elements in the Montgomery domain take the form a×R and + // multiplication of x and y in the calculates (x × y × R^-1) mod n. RR + // is R×R mod n thus the Montgomery multiplication x and RR gives x×R, + // i.e. converts x into the Montgomery domain. + // Window values borrowed from https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion + RR := []uint64{0x83244c95be79eea2, 0x4699799c49bd6fa6, 0x2845b2392b6bec59, 0x66e12d94f3d95620} + p256OrdMul(_1, x, RR) // _1 + p256OrdSqr(x, _1, 1) // _10 + p256OrdMul(_11, x, _1) // _11 + p256OrdMul(_101, x, _11) // _101 + p256OrdMul(_111, x, _101) // _111 + p256OrdSqr(x, _101, 1) // _1010 + p256OrdMul(_1111, _101, x) // _1111 + + p256OrdSqr(t, x, 1) // _10100 + p256OrdMul(_10101, t, _1) // _10101 + p256OrdSqr(x, _10101, 1) // _101010 + p256OrdMul(_101111, _101, x) // _101111 + p256OrdMul(x, _10101, x) // _111111 = x6 + p256OrdSqr(t, x, 2) // _11111100 + p256OrdMul(t, t, _11) // _11111111 = x8 + p256OrdSqr(x, t, 8) // _ff00 + p256OrdMul(x, x, t) // _ffff = x16 + p256OrdSqr(t, x, 16) // _ffff0000 + p256OrdMul(t, t, x) // _ffffffff = x32 + + p256OrdSqr(x, t, 64) + p256OrdMul(x, x, t) + p256OrdSqr(x, x, 32) + p256OrdMul(x, x, t) + + sqrs := []uint8{ + 6, 5, 4, 5, 5, + 4, 3, 3, 5, 9, + 6, 2, 5, 6, 5, + 4, 5, 5, 3, 10, + 2, 5, 5, 3, 7, 6} + muls := [][]uint64{ + _101111, _111, _11, _1111, _10101, + _101, _101, _101, _111, _101111, + _1111, _1, _1, _1111, _111, + _111, _111, _101, _11, _101111, + _11, _11, _11, _1, _10101, _1111} + + for i, s := range sqrs { + p256OrdSqr(x, x, int(s)) + p256OrdMul(x, x, muls[i]) + } + + // Multiplying by one in the Montgomery domain converts a Montgomery + // value out of the domain. + one := []uint64{1, 0, 0, 0} + p256OrdMul(x, x, one) + + xOut := make([]byte, 32) + p256LittleToBig(xOut, x) + return new(big.Int).SetBytes(xOut) +} + +// fromBig converts a *big.Int into a format used by this code. +func fromBig(out []uint64, big *big.Int) { + for i := range out { + out[i] = 0 + } + + for i, v := range big.Bits() { + out[i] = uint64(v) + } +} + +// p256GetScalar endian-swaps the big-endian scalar value from in and writes it +// to out. If the scalar is equal or greater than the order of the group, it's +// reduced modulo that order. +func p256GetScalar(out []uint64, in []byte) { + n := new(big.Int).SetBytes(in) + + if n.Cmp(p256.N) >= 0 { + n.Mod(n, p256.N) + } + fromBig(out, n) +} + +// p256Mul operates in a Montgomery domain with R = 2^256 mod p, where p is the +// underlying field of the curve. (See initP256 for the value.) Thus rr here is +// R×R mod p. See comment in Inverse about how this is used. +var rr = []uint64{0x0000000000000003, 0xfffffffbffffffff, 0xfffffffffffffffe, 0x00000004fffffffd} + +func maybeReduceModP(in *big.Int) *big.Int { + if in.Cmp(p256.P) < 0 { + return in + } + return new(big.Int).Mod(in, p256.P) +} + +func (curve p256Curve) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) { + scalarReversed := make([]uint64, 4) + var r1, r2 p256Point + p256GetScalar(scalarReversed, baseScalar) + r1IsInfinity := scalarIsZero(scalarReversed) + r1.p256BaseMult(scalarReversed) + + p256GetScalar(scalarReversed, scalar) + r2IsInfinity := scalarIsZero(scalarReversed) + fromBig(r2.xyz[0:4], maybeReduceModP(bigX)) + fromBig(r2.xyz[4:8], maybeReduceModP(bigY)) + p256Mul(r2.xyz[0:4], r2.xyz[0:4], rr[:]) + p256Mul(r2.xyz[4:8], r2.xyz[4:8], rr[:]) + + // This sets r2's Z value to 1, in the Montgomery domain. + r2.xyz[8] = 0x0000000000000001 + r2.xyz[9] = 0xffffffff00000000 + r2.xyz[10] = 0xffffffffffffffff + r2.xyz[11] = 0x00000000fffffffe + + r2.p256ScalarMult(scalarReversed) + + var sum, double p256Point + pointsEqual := p256PointAddAsm(sum.xyz[:], r1.xyz[:], r2.xyz[:]) + p256PointDoubleAsm(double.xyz[:], r1.xyz[:]) + sum.CopyConditional(&double, pointsEqual) + sum.CopyConditional(&r1, r2IsInfinity) + sum.CopyConditional(&r2, r1IsInfinity) + + return sum.p256PointToAffine() +} + +func (curve p256Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) { + scalarReversed := make([]uint64, 4) + p256GetScalar(scalarReversed, scalar) + + var r p256Point + r.p256BaseMult(scalarReversed) + return r.p256PointToAffine() +} + +func (curve p256Curve) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) { + scalarReversed := make([]uint64, 4) + p256GetScalar(scalarReversed, scalar) + + var r p256Point + fromBig(r.xyz[0:4], maybeReduceModP(bigX)) + fromBig(r.xyz[4:8], maybeReduceModP(bigY)) + p256Mul(r.xyz[0:4], r.xyz[0:4], rr[:]) + p256Mul(r.xyz[4:8], r.xyz[4:8], rr[:]) + // This sets r2's Z value to 1, in the Montgomery domain. + r.xyz[8] = 0x0000000000000001 + r.xyz[9] = 0xffffffff00000000 + r.xyz[10] = 0xffffffffffffffff + r.xyz[11] = 0x00000000fffffffe + + r.p256ScalarMult(scalarReversed) + return r.p256PointToAffine() +} + +// uint64IsZero returns 1 if x is zero and zero otherwise. +func uint64IsZero(x uint64) int { + x = ^x + x &= x >> 32 + x &= x >> 16 + x &= x >> 8 + x &= x >> 4 + x &= x >> 2 + x &= x >> 1 + return int(x & 1) +} + +// scalarIsZero returns 1 if scalar represents the zero value, and zero +// otherwise. +func scalarIsZero(scalar []uint64) int { + return uint64IsZero(scalar[0] | scalar[1] | scalar[2] | scalar[3]) +} + +func (p *p256Point) p256PointToAffine() (x, y *big.Int) { + zInv := make([]uint64, 4) + zInvSq := make([]uint64, 4) + p256Inverse(zInv, p.xyz[8:12]) + p256Sqr(zInvSq, zInv, 1) + p256Mul(zInv, zInv, zInvSq) + + p256Mul(zInvSq, p.xyz[0:4], zInvSq) + p256Mul(zInv, p.xyz[4:8], zInv) + + p256FromMont(zInvSq, zInvSq) + p256FromMont(zInv, zInv) + + xOut := make([]byte, 32) + yOut := make([]byte, 32) + p256LittleToBig(xOut, zInvSq) + p256LittleToBig(yOut, zInv) + + return new(big.Int).SetBytes(xOut), new(big.Int).SetBytes(yOut) +} + +// CopyConditional copies overwrites p with src if v == 1, and leaves p +// unchanged if v == 0. +func (p *p256Point) CopyConditional(src *p256Point, v int) { + pMask := uint64(v) - 1 + srcMask := ^pMask + + for i, n := range p.xyz { + p.xyz[i] = (n & pMask) | (src.xyz[i] & srcMask) + } +} + +// p256Inverse sets out to in^-1 mod p. +func p256Inverse(out, in []uint64) { + var stack [6 * 4]uint64 + p2 := stack[4*0 : 4*0+4] + p4 := stack[4*1 : 4*1+4] + p8 := stack[4*2 : 4*2+4] + p16 := stack[4*3 : 4*3+4] + p32 := stack[4*4 : 4*4+4] + + p256Sqr(out, in, 1) + p256Mul(p2, out, in) // 3*p + + p256Sqr(out, p2, 2) + p256Mul(p4, out, p2) // f*p + + p256Sqr(out, p4, 4) + p256Mul(p8, out, p4) // ff*p + + p256Sqr(out, p8, 8) + p256Mul(p16, out, p8) // ffff*p + + p256Sqr(out, p16, 16) + p256Mul(p32, out, p16) // ffffffff*p + + p256Sqr(out, p32, 32) + p256Mul(out, out, in) + + p256Sqr(out, out, 128) + p256Mul(out, out, p32) + + p256Sqr(out, out, 32) + p256Mul(out, out, p32) + + p256Sqr(out, out, 16) + p256Mul(out, out, p16) + + p256Sqr(out, out, 8) + p256Mul(out, out, p8) + + p256Sqr(out, out, 4) + p256Mul(out, out, p4) + + p256Sqr(out, out, 2) + p256Mul(out, out, p2) + + p256Sqr(out, out, 2) + p256Mul(out, out, in) +} + +func (p *p256Point) p256StorePoint(r *[16 * 4 * 3]uint64, index int) { + copy(r[index*12:], p.xyz[:]) +} + +func boothW5(in uint) (int, int) { + var s uint = ^((in >> 5) - 1) + var d uint = (1 << 6) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return int(d), int(s & 1) +} + +func boothW6(in uint) (int, int) { + var s uint = ^((in >> 6) - 1) + var d uint = (1 << 7) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return int(d), int(s & 1) +} + +func (p *p256Point) p256BaseMult(scalar []uint64) { + wvalue := (scalar[0] << 1) & 0x7f + sel, sign := boothW6(uint(wvalue)) + p256SelectBase(p.xyz[0:8], p256Precomputed[0][0:], sel) + p256NegCond(p.xyz[4:8], sign) + + // (This is one, in the Montgomery domain.) + p.xyz[8] = 0x0000000000000001 + p.xyz[9] = 0xffffffff00000000 + p.xyz[10] = 0xffffffffffffffff + p.xyz[11] = 0x00000000fffffffe + + var t0 p256Point + // (This is one, in the Montgomery domain.) + t0.xyz[8] = 0x0000000000000001 + t0.xyz[9] = 0xffffffff00000000 + t0.xyz[10] = 0xffffffffffffffff + t0.xyz[11] = 0x00000000fffffffe + + index := uint(5) + zero := sel + + for i := 1; i < 43; i++ { + if index < 192 { + wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0x7f + } else { + wvalue = (scalar[index/64] >> (index % 64)) & 0x7f + } + index += 6 + sel, sign = boothW6(uint(wvalue)) + p256SelectBase(t0.xyz[0:8], p256Precomputed[i][0:], sel) + p256PointAddAffineAsm(p.xyz[0:12], p.xyz[0:12], t0.xyz[0:8], sign, sel, zero) + zero |= sel + } +} + +func (p *p256Point) p256ScalarMult(scalar []uint64) { + // precomp is a table of precomputed points that stores powers of p + // from p^1 to p^16. + var precomp [16 * 4 * 3]uint64 + var t0, t1, t2, t3 p256Point + + // Prepare the table + p.p256StorePoint(&precomp, 0) // 1 + + p256PointDoubleAsm(t0.xyz[:], p.xyz[:]) + p256PointDoubleAsm(t1.xyz[:], t0.xyz[:]) + p256PointDoubleAsm(t2.xyz[:], t1.xyz[:]) + p256PointDoubleAsm(t3.xyz[:], t2.xyz[:]) + t0.p256StorePoint(&precomp, 1) // 2 + t1.p256StorePoint(&precomp, 3) // 4 + t2.p256StorePoint(&precomp, 7) // 8 + t3.p256StorePoint(&precomp, 15) // 16 + + p256PointAddAsm(t0.xyz[:], t0.xyz[:], p.xyz[:]) + p256PointAddAsm(t1.xyz[:], t1.xyz[:], p.xyz[:]) + p256PointAddAsm(t2.xyz[:], t2.xyz[:], p.xyz[:]) + t0.p256StorePoint(&precomp, 2) // 3 + t1.p256StorePoint(&precomp, 4) // 5 + t2.p256StorePoint(&precomp, 8) // 9 + + p256PointDoubleAsm(t0.xyz[:], t0.xyz[:]) + p256PointDoubleAsm(t1.xyz[:], t1.xyz[:]) + t0.p256StorePoint(&precomp, 5) // 6 + t1.p256StorePoint(&precomp, 9) // 10 + + p256PointAddAsm(t2.xyz[:], t0.xyz[:], p.xyz[:]) + p256PointAddAsm(t1.xyz[:], t1.xyz[:], p.xyz[:]) + t2.p256StorePoint(&precomp, 6) // 7 + t1.p256StorePoint(&precomp, 10) // 11 + + p256PointDoubleAsm(t0.xyz[:], t0.xyz[:]) + p256PointDoubleAsm(t2.xyz[:], t2.xyz[:]) + t0.p256StorePoint(&precomp, 11) // 12 + t2.p256StorePoint(&precomp, 13) // 14 + + p256PointAddAsm(t0.xyz[:], t0.xyz[:], p.xyz[:]) + p256PointAddAsm(t2.xyz[:], t2.xyz[:], p.xyz[:]) + t0.p256StorePoint(&precomp, 12) // 13 + t2.p256StorePoint(&precomp, 14) // 15 + + // Start scanning the window from top bit + index := uint(254) + var sel, sign int + + wvalue := (scalar[index/64] >> (index % 64)) & 0x3f + sel, _ = boothW5(uint(wvalue)) + + p256Select(p.xyz[0:12], precomp[0:], sel) + zero := sel + + for index > 4 { + index -= 5 + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + + if index < 192 { + wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0x3f + } else { + wvalue = (scalar[index/64] >> (index % 64)) & 0x3f + } + + sel, sign = boothW5(uint(wvalue)) + + p256Select(t0.xyz[0:], precomp[0:], sel) + p256NegCond(t0.xyz[4:8], sign) + p256PointAddAsm(t1.xyz[:], p.xyz[:], t0.xyz[:]) + p256MovCond(t1.xyz[0:12], t1.xyz[0:12], p.xyz[0:12], sel) + p256MovCond(p.xyz[0:12], t1.xyz[0:12], t0.xyz[0:12], zero) + zero |= sel + } + + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + p256PointDoubleAsm(p.xyz[:], p.xyz[:]) + + wvalue = (scalar[0] << 1) & 0x3f + sel, sign = boothW5(uint(wvalue)) + + p256Select(t0.xyz[0:], precomp[0:], sel) + p256NegCond(t0.xyz[4:8], sign) + p256PointAddAsm(t1.xyz[:], p.xyz[:], t0.xyz[:]) + p256MovCond(t1.xyz[0:12], t1.xyz[0:12], p.xyz[0:12], sel) + p256MovCond(p.xyz[0:12], t1.xyz[0:12], t0.xyz[0:12], zero) +} diff --git a/src/crypto/elliptic/p256_asm_amd64.s b/src/crypto/elliptic/p256_asm_amd64.s new file mode 100644 index 0000000..c77b11b --- /dev/null +++ b/src/crypto/elliptic/p256_asm_amd64.s @@ -0,0 +1,2347 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains constant-time, 64-bit assembly implementation of +// P256. The optimizations performed here are described in detail in: +// S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with +// 256-bit primes" +// https://link.springer.com/article/10.1007%2Fs13389-014-0090-x +// https://eprint.iacr.org/2013/816.pdf + +#include "textflag.h" + +#define res_ptr DI +#define x_ptr SI +#define y_ptr CX + +#define acc0 R8 +#define acc1 R9 +#define acc2 R10 +#define acc3 R11 +#define acc4 R12 +#define acc5 R13 +#define t0 R14 +#define t1 R15 + +DATA p256const0<>+0x00(SB)/8, $0x00000000ffffffff +DATA p256const1<>+0x00(SB)/8, $0xffffffff00000001 +DATA p256ordK0<>+0x00(SB)/8, $0xccd1c8aaee00bc4f +DATA p256ord<>+0x00(SB)/8, $0xf3b9cac2fc632551 +DATA p256ord<>+0x08(SB)/8, $0xbce6faada7179e84 +DATA p256ord<>+0x10(SB)/8, $0xffffffffffffffff +DATA p256ord<>+0x18(SB)/8, $0xffffffff00000000 +DATA p256one<>+0x00(SB)/8, $0x0000000000000001 +DATA p256one<>+0x08(SB)/8, $0xffffffff00000000 +DATA p256one<>+0x10(SB)/8, $0xffffffffffffffff +DATA p256one<>+0x18(SB)/8, $0x00000000fffffffe +GLOBL p256const0<>(SB), 8, $8 +GLOBL p256const1<>(SB), 8, $8 +GLOBL p256ordK0<>(SB), 8, $8 +GLOBL p256ord<>(SB), 8, $32 +GLOBL p256one<>(SB), 8, $32 + +/* ---------------------------------------*/ +// func p256LittleToBig(res []byte, in []uint64) +TEXT ·p256LittleToBig(SB),NOSPLIT,$0 + JMP ·p256BigToLittle(SB) +/* ---------------------------------------*/ +// func p256BigToLittle(res []uint64, in []byte) +TEXT ·p256BigToLittle(SB),NOSPLIT,$0 + MOVQ res+0(FP), res_ptr + MOVQ in+24(FP), x_ptr + + MOVQ (8*0)(x_ptr), acc0 + MOVQ (8*1)(x_ptr), acc1 + MOVQ (8*2)(x_ptr), acc2 + MOVQ (8*3)(x_ptr), acc3 + + BSWAPQ acc0 + BSWAPQ acc1 + BSWAPQ acc2 + BSWAPQ acc3 + + MOVQ acc3, (8*0)(res_ptr) + MOVQ acc2, (8*1)(res_ptr) + MOVQ acc1, (8*2)(res_ptr) + MOVQ acc0, (8*3)(res_ptr) + + RET +/* ---------------------------------------*/ +// func p256MovCond(res, a, b []uint64, cond int) +// If cond == 0 res=b, else res=a +TEXT ·p256MovCond(SB),NOSPLIT,$0 + MOVQ res+0(FP), res_ptr + MOVQ a+24(FP), x_ptr + MOVQ b+48(FP), y_ptr + MOVQ cond+72(FP), X12 + + PXOR X13, X13 + PSHUFD $0, X12, X12 + PCMPEQL X13, X12 + + MOVOU X12, X0 + MOVOU (16*0)(x_ptr), X6 + PANDN X6, X0 + MOVOU X12, X1 + MOVOU (16*1)(x_ptr), X7 + PANDN X7, X1 + MOVOU X12, X2 + MOVOU (16*2)(x_ptr), X8 + PANDN X8, X2 + MOVOU X12, X3 + MOVOU (16*3)(x_ptr), X9 + PANDN X9, X3 + MOVOU X12, X4 + MOVOU (16*4)(x_ptr), X10 + PANDN X10, X4 + MOVOU X12, X5 + MOVOU (16*5)(x_ptr), X11 + PANDN X11, X5 + + MOVOU (16*0)(y_ptr), X6 + MOVOU (16*1)(y_ptr), X7 + MOVOU (16*2)(y_ptr), X8 + MOVOU (16*3)(y_ptr), X9 + MOVOU (16*4)(y_ptr), X10 + MOVOU (16*5)(y_ptr), X11 + + PAND X12, X6 + PAND X12, X7 + PAND X12, X8 + PAND X12, X9 + PAND X12, X10 + PAND X12, X11 + + PXOR X6, X0 + PXOR X7, X1 + PXOR X8, X2 + PXOR X9, X3 + PXOR X10, X4 + PXOR X11, X5 + + MOVOU X0, (16*0)(res_ptr) + MOVOU X1, (16*1)(res_ptr) + MOVOU X2, (16*2)(res_ptr) + MOVOU X3, (16*3)(res_ptr) + MOVOU X4, (16*4)(res_ptr) + MOVOU X5, (16*5)(res_ptr) + + RET +/* ---------------------------------------*/ +// func p256NegCond(val []uint64, cond int) +TEXT ·p256NegCond(SB),NOSPLIT,$0 + MOVQ val+0(FP), res_ptr + MOVQ cond+24(FP), t0 + // acc = poly + MOVQ $-1, acc0 + MOVQ p256const0<>(SB), acc1 + MOVQ $0, acc2 + MOVQ p256const1<>(SB), acc3 + // Load the original value + MOVQ (8*0)(res_ptr), acc5 + MOVQ (8*1)(res_ptr), x_ptr + MOVQ (8*2)(res_ptr), y_ptr + MOVQ (8*3)(res_ptr), t1 + // Speculatively subtract + SUBQ acc5, acc0 + SBBQ x_ptr, acc1 + SBBQ y_ptr, acc2 + SBBQ t1, acc3 + // If condition is 0, keep original value + TESTQ t0, t0 + CMOVQEQ acc5, acc0 + CMOVQEQ x_ptr, acc1 + CMOVQEQ y_ptr, acc2 + CMOVQEQ t1, acc3 + // Store result + MOVQ acc0, (8*0)(res_ptr) + MOVQ acc1, (8*1)(res_ptr) + MOVQ acc2, (8*2)(res_ptr) + MOVQ acc3, (8*3)(res_ptr) + + RET +/* ---------------------------------------*/ +// func p256Sqr(res, in []uint64, n int) +TEXT ·p256Sqr(SB),NOSPLIT,$0 + MOVQ res+0(FP), res_ptr + MOVQ in+24(FP), x_ptr + MOVQ n+48(FP), BX + +sqrLoop: + + // y[1:] * y[0] + MOVQ (8*0)(x_ptr), t0 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + MOVQ AX, acc1 + MOVQ DX, acc2 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, acc3 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, acc4 + // y[2:] * y[1] + MOVQ (8*1)(x_ptr), t0 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ $0, DX + MOVQ DX, acc5 + // y[3] * y[2] + MOVQ (8*2)(x_ptr), t0 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ AX, acc5 + ADCQ $0, DX + MOVQ DX, y_ptr + XORQ t1, t1 + // *2 + ADDQ acc1, acc1 + ADCQ acc2, acc2 + ADCQ acc3, acc3 + ADCQ acc4, acc4 + ADCQ acc5, acc5 + ADCQ y_ptr, y_ptr + ADCQ $0, t1 + // Missing products + MOVQ (8*0)(x_ptr), AX + MULQ AX + MOVQ AX, acc0 + MOVQ DX, t0 + + MOVQ (8*1)(x_ptr), AX + MULQ AX + ADDQ t0, acc1 + ADCQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t0 + + MOVQ (8*2)(x_ptr), AX + MULQ AX + ADDQ t0, acc3 + ADCQ AX, acc4 + ADCQ $0, DX + MOVQ DX, t0 + + MOVQ (8*3)(x_ptr), AX + MULQ AX + ADDQ t0, acc5 + ADCQ AX, y_ptr + ADCQ DX, t1 + MOVQ t1, x_ptr + // First reduction step + MOVQ acc0, AX + MOVQ acc0, t1 + SHLQ $32, acc0 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc0, acc1 + ADCQ t1, acc2 + ADCQ AX, acc3 + ADCQ $0, DX + MOVQ DX, acc0 + // Second reduction step + MOVQ acc1, AX + MOVQ acc1, t1 + SHLQ $32, acc1 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc1, acc2 + ADCQ t1, acc3 + ADCQ AX, acc0 + ADCQ $0, DX + MOVQ DX, acc1 + // Third reduction step + MOVQ acc2, AX + MOVQ acc2, t1 + SHLQ $32, acc2 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc2, acc3 + ADCQ t1, acc0 + ADCQ AX, acc1 + ADCQ $0, DX + MOVQ DX, acc2 + // Last reduction step + XORQ t0, t0 + MOVQ acc3, AX + MOVQ acc3, t1 + SHLQ $32, acc3 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc3, acc0 + ADCQ t1, acc1 + ADCQ AX, acc2 + ADCQ $0, DX + MOVQ DX, acc3 + // Add bits [511:256] of the sqr result + ADCQ acc4, acc0 + ADCQ acc5, acc1 + ADCQ y_ptr, acc2 + ADCQ x_ptr, acc3 + ADCQ $0, t0 + + MOVQ acc0, acc4 + MOVQ acc1, acc5 + MOVQ acc2, y_ptr + MOVQ acc3, t1 + // Subtract p256 + SUBQ $-1, acc0 + SBBQ p256const0<>(SB) ,acc1 + SBBQ $0, acc2 + SBBQ p256const1<>(SB), acc3 + SBBQ $0, t0 + + CMOVQCS acc4, acc0 + CMOVQCS acc5, acc1 + CMOVQCS y_ptr, acc2 + CMOVQCS t1, acc3 + + MOVQ acc0, (8*0)(res_ptr) + MOVQ acc1, (8*1)(res_ptr) + MOVQ acc2, (8*2)(res_ptr) + MOVQ acc3, (8*3)(res_ptr) + MOVQ res_ptr, x_ptr + DECQ BX + JNE sqrLoop + + RET +/* ---------------------------------------*/ +// func p256Mul(res, in1, in2 []uint64) +TEXT ·p256Mul(SB),NOSPLIT,$0 + MOVQ res+0(FP), res_ptr + MOVQ in1+24(FP), x_ptr + MOVQ in2+48(FP), y_ptr + // x * y[0] + MOVQ (8*0)(y_ptr), t0 + + MOVQ (8*0)(x_ptr), AX + MULQ t0 + MOVQ AX, acc0 + MOVQ DX, acc1 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + ADDQ AX, acc1 + ADCQ $0, DX + MOVQ DX, acc2 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, acc3 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, acc4 + XORQ acc5, acc5 + // First reduction step + MOVQ acc0, AX + MOVQ acc0, t1 + SHLQ $32, acc0 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc0, acc1 + ADCQ t1, acc2 + ADCQ AX, acc3 + ADCQ DX, acc4 + ADCQ $0, acc5 + XORQ acc0, acc0 + // x * y[1] + MOVQ (8*1)(y_ptr), t0 + + MOVQ (8*0)(x_ptr), AX + MULQ t0 + ADDQ AX, acc1 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + ADDQ t1, acc2 + ADCQ $0, DX + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ t1, acc3 + ADCQ $0, DX + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ DX, acc5 + ADCQ $0, acc0 + // Second reduction step + MOVQ acc1, AX + MOVQ acc1, t1 + SHLQ $32, acc1 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc1, acc2 + ADCQ t1, acc3 + ADCQ AX, acc4 + ADCQ DX, acc5 + ADCQ $0, acc0 + XORQ acc1, acc1 + // x * y[2] + MOVQ (8*2)(y_ptr), t0 + + MOVQ (8*0)(x_ptr), AX + MULQ t0 + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + ADDQ t1, acc3 + ADCQ $0, DX + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ t1, acc5 + ADCQ $0, DX + ADDQ AX, acc5 + ADCQ DX, acc0 + ADCQ $0, acc1 + // Third reduction step + MOVQ acc2, AX + MOVQ acc2, t1 + SHLQ $32, acc2 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc2, acc3 + ADCQ t1, acc4 + ADCQ AX, acc5 + ADCQ DX, acc0 + ADCQ $0, acc1 + XORQ acc2, acc2 + // x * y[3] + MOVQ (8*3)(y_ptr), t0 + + MOVQ (8*0)(x_ptr), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ t1, acc5 + ADCQ $0, DX + ADDQ AX, acc5 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ t1, acc0 + ADCQ $0, DX + ADDQ AX, acc0 + ADCQ DX, acc1 + ADCQ $0, acc2 + // Last reduction step + MOVQ acc3, AX + MOVQ acc3, t1 + SHLQ $32, acc3 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc3, acc4 + ADCQ t1, acc5 + ADCQ AX, acc0 + ADCQ DX, acc1 + ADCQ $0, acc2 + // Copy result [255:0] + MOVQ acc4, x_ptr + MOVQ acc5, acc3 + MOVQ acc0, t0 + MOVQ acc1, t1 + // Subtract p256 + SUBQ $-1, acc4 + SBBQ p256const0<>(SB) ,acc5 + SBBQ $0, acc0 + SBBQ p256const1<>(SB), acc1 + SBBQ $0, acc2 + + CMOVQCS x_ptr, acc4 + CMOVQCS acc3, acc5 + CMOVQCS t0, acc0 + CMOVQCS t1, acc1 + + MOVQ acc4, (8*0)(res_ptr) + MOVQ acc5, (8*1)(res_ptr) + MOVQ acc0, (8*2)(res_ptr) + MOVQ acc1, (8*3)(res_ptr) + + RET +/* ---------------------------------------*/ +// func p256FromMont(res, in []uint64) +TEXT ·p256FromMont(SB),NOSPLIT,$0 + MOVQ res+0(FP), res_ptr + MOVQ in+24(FP), x_ptr + + MOVQ (8*0)(x_ptr), acc0 + MOVQ (8*1)(x_ptr), acc1 + MOVQ (8*2)(x_ptr), acc2 + MOVQ (8*3)(x_ptr), acc3 + XORQ acc4, acc4 + + // Only reduce, no multiplications are needed + // First stage + MOVQ acc0, AX + MOVQ acc0, t1 + SHLQ $32, acc0 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc0, acc1 + ADCQ t1, acc2 + ADCQ AX, acc3 + ADCQ DX, acc4 + XORQ acc5, acc5 + // Second stage + MOVQ acc1, AX + MOVQ acc1, t1 + SHLQ $32, acc1 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc1, acc2 + ADCQ t1, acc3 + ADCQ AX, acc4 + ADCQ DX, acc5 + XORQ acc0, acc0 + // Third stage + MOVQ acc2, AX + MOVQ acc2, t1 + SHLQ $32, acc2 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc2, acc3 + ADCQ t1, acc4 + ADCQ AX, acc5 + ADCQ DX, acc0 + XORQ acc1, acc1 + // Last stage + MOVQ acc3, AX + MOVQ acc3, t1 + SHLQ $32, acc3 + MULQ p256const1<>(SB) + SHRQ $32, t1 + ADDQ acc3, acc4 + ADCQ t1, acc5 + ADCQ AX, acc0 + ADCQ DX, acc1 + + MOVQ acc4, x_ptr + MOVQ acc5, acc3 + MOVQ acc0, t0 + MOVQ acc1, t1 + + SUBQ $-1, acc4 + SBBQ p256const0<>(SB), acc5 + SBBQ $0, acc0 + SBBQ p256const1<>(SB), acc1 + + CMOVQCS x_ptr, acc4 + CMOVQCS acc3, acc5 + CMOVQCS t0, acc0 + CMOVQCS t1, acc1 + + MOVQ acc4, (8*0)(res_ptr) + MOVQ acc5, (8*1)(res_ptr) + MOVQ acc0, (8*2)(res_ptr) + MOVQ acc1, (8*3)(res_ptr) + + RET +/* ---------------------------------------*/ +// Constant time point access to arbitrary point table. +// Indexed from 1 to 15, with -1 offset +// (index 0 is implicitly point at infinity) +// func p256Select(point, table []uint64, idx int) +TEXT ·p256Select(SB),NOSPLIT,$0 + MOVQ idx+48(FP),AX + MOVQ table+24(FP),DI + MOVQ point+0(FP),DX + + PXOR X15, X15 // X15 = 0 + PCMPEQL X14, X14 // X14 = -1 + PSUBL X14, X15 // X15 = 1 + MOVL AX, X14 + PSHUFD $0, X14, X14 + + PXOR X0, X0 + PXOR X1, X1 + PXOR X2, X2 + PXOR X3, X3 + PXOR X4, X4 + PXOR X5, X5 + MOVQ $16, AX + + MOVOU X15, X13 + +loop_select: + + MOVOU X13, X12 + PADDL X15, X13 + PCMPEQL X14, X12 + + MOVOU (16*0)(DI), X6 + MOVOU (16*1)(DI), X7 + MOVOU (16*2)(DI), X8 + MOVOU (16*3)(DI), X9 + MOVOU (16*4)(DI), X10 + MOVOU (16*5)(DI), X11 + ADDQ $(16*6), DI + + PAND X12, X6 + PAND X12, X7 + PAND X12, X8 + PAND X12, X9 + PAND X12, X10 + PAND X12, X11 + + PXOR X6, X0 + PXOR X7, X1 + PXOR X8, X2 + PXOR X9, X3 + PXOR X10, X4 + PXOR X11, X5 + + DECQ AX + JNE loop_select + + MOVOU X0, (16*0)(DX) + MOVOU X1, (16*1)(DX) + MOVOU X2, (16*2)(DX) + MOVOU X3, (16*3)(DX) + MOVOU X4, (16*4)(DX) + MOVOU X5, (16*5)(DX) + + RET +/* ---------------------------------------*/ +// Constant time point access to base point table. +// func p256SelectBase(point, table []uint64, idx int) +TEXT ·p256SelectBase(SB),NOSPLIT,$0 + MOVQ idx+48(FP),AX + MOVQ table+24(FP),DI + MOVQ point+0(FP),DX + + PXOR X15, X15 // X15 = 0 + PCMPEQL X14, X14 // X14 = -1 + PSUBL X14, X15 // X15 = 1 + MOVL AX, X14 + PSHUFD $0, X14, X14 + + PXOR X0, X0 + PXOR X1, X1 + PXOR X2, X2 + PXOR X3, X3 + MOVQ $16, AX + + MOVOU X15, X13 + +loop_select_base: + + MOVOU X13, X12 + PADDL X15, X13 + PCMPEQL X14, X12 + + MOVOU (16*0)(DI), X4 + MOVOU (16*1)(DI), X5 + MOVOU (16*2)(DI), X6 + MOVOU (16*3)(DI), X7 + + MOVOU (16*4)(DI), X8 + MOVOU (16*5)(DI), X9 + MOVOU (16*6)(DI), X10 + MOVOU (16*7)(DI), X11 + + ADDQ $(16*8), DI + + PAND X12, X4 + PAND X12, X5 + PAND X12, X6 + PAND X12, X7 + + MOVOU X13, X12 + PADDL X15, X13 + PCMPEQL X14, X12 + + PAND X12, X8 + PAND X12, X9 + PAND X12, X10 + PAND X12, X11 + + PXOR X4, X0 + PXOR X5, X1 + PXOR X6, X2 + PXOR X7, X3 + + PXOR X8, X0 + PXOR X9, X1 + PXOR X10, X2 + PXOR X11, X3 + + DECQ AX + JNE loop_select_base + + MOVOU X0, (16*0)(DX) + MOVOU X1, (16*1)(DX) + MOVOU X2, (16*2)(DX) + MOVOU X3, (16*3)(DX) + + RET +/* ---------------------------------------*/ +// func p256OrdMul(res, in1, in2 []uint64) +TEXT ·p256OrdMul(SB),NOSPLIT,$0 + MOVQ res+0(FP), res_ptr + MOVQ in1+24(FP), x_ptr + MOVQ in2+48(FP), y_ptr + // x * y[0] + MOVQ (8*0)(y_ptr), t0 + + MOVQ (8*0)(x_ptr), AX + MULQ t0 + MOVQ AX, acc0 + MOVQ DX, acc1 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + ADDQ AX, acc1 + ADCQ $0, DX + MOVQ DX, acc2 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, acc3 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, acc4 + XORQ acc5, acc5 + // First reduction step + MOVQ acc0, AX + MULQ p256ordK0<>(SB) + MOVQ AX, t0 + + MOVQ p256ord<>+0x00(SB), AX + MULQ t0 + ADDQ AX, acc0 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x08(SB), AX + MULQ t0 + ADDQ t1, acc1 + ADCQ $0, DX + ADDQ AX, acc1 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x10(SB), AX + MULQ t0 + ADDQ t1, acc2 + ADCQ $0, DX + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x18(SB), AX + MULQ t0 + ADDQ t1, acc3 + ADCQ $0, DX + ADDQ AX, acc3 + ADCQ DX, acc4 + ADCQ $0, acc5 + // x * y[1] + MOVQ (8*1)(y_ptr), t0 + + MOVQ (8*0)(x_ptr), AX + MULQ t0 + ADDQ AX, acc1 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + ADDQ t1, acc2 + ADCQ $0, DX + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ t1, acc3 + ADCQ $0, DX + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ DX, acc5 + ADCQ $0, acc0 + // Second reduction step + MOVQ acc1, AX + MULQ p256ordK0<>(SB) + MOVQ AX, t0 + + MOVQ p256ord<>+0x00(SB), AX + MULQ t0 + ADDQ AX, acc1 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x08(SB), AX + MULQ t0 + ADDQ t1, acc2 + ADCQ $0, DX + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x10(SB), AX + MULQ t0 + ADDQ t1, acc3 + ADCQ $0, DX + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x18(SB), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ DX, acc5 + ADCQ $0, acc0 + // x * y[2] + MOVQ (8*2)(y_ptr), t0 + + MOVQ (8*0)(x_ptr), AX + MULQ t0 + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + ADDQ t1, acc3 + ADCQ $0, DX + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ t1, acc5 + ADCQ $0, DX + ADDQ AX, acc5 + ADCQ DX, acc0 + ADCQ $0, acc1 + // Third reduction step + MOVQ acc2, AX + MULQ p256ordK0<>(SB) + MOVQ AX, t0 + + MOVQ p256ord<>+0x00(SB), AX + MULQ t0 + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x08(SB), AX + MULQ t0 + ADDQ t1, acc3 + ADCQ $0, DX + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x10(SB), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x18(SB), AX + MULQ t0 + ADDQ t1, acc5 + ADCQ $0, DX + ADDQ AX, acc5 + ADCQ DX, acc0 + ADCQ $0, acc1 + // x * y[3] + MOVQ (8*3)(y_ptr), t0 + + MOVQ (8*0)(x_ptr), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ t1, acc5 + ADCQ $0, DX + ADDQ AX, acc5 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ t1, acc0 + ADCQ $0, DX + ADDQ AX, acc0 + ADCQ DX, acc1 + ADCQ $0, acc2 + // Last reduction step + MOVQ acc3, AX + MULQ p256ordK0<>(SB) + MOVQ AX, t0 + + MOVQ p256ord<>+0x00(SB), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x08(SB), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x10(SB), AX + MULQ t0 + ADDQ t1, acc5 + ADCQ $0, DX + ADDQ AX, acc5 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x18(SB), AX + MULQ t0 + ADDQ t1, acc0 + ADCQ $0, DX + ADDQ AX, acc0 + ADCQ DX, acc1 + ADCQ $0, acc2 + // Copy result [255:0] + MOVQ acc4, x_ptr + MOVQ acc5, acc3 + MOVQ acc0, t0 + MOVQ acc1, t1 + // Subtract p256 + SUBQ p256ord<>+0x00(SB), acc4 + SBBQ p256ord<>+0x08(SB) ,acc5 + SBBQ p256ord<>+0x10(SB), acc0 + SBBQ p256ord<>+0x18(SB), acc1 + SBBQ $0, acc2 + + CMOVQCS x_ptr, acc4 + CMOVQCS acc3, acc5 + CMOVQCS t0, acc0 + CMOVQCS t1, acc1 + + MOVQ acc4, (8*0)(res_ptr) + MOVQ acc5, (8*1)(res_ptr) + MOVQ acc0, (8*2)(res_ptr) + MOVQ acc1, (8*3)(res_ptr) + + RET +/* ---------------------------------------*/ +// func p256OrdSqr(res, in []uint64, n int) +TEXT ·p256OrdSqr(SB),NOSPLIT,$0 + MOVQ res+0(FP), res_ptr + MOVQ in+24(FP), x_ptr + MOVQ n+48(FP), BX + +ordSqrLoop: + + // y[1:] * y[0] + MOVQ (8*0)(x_ptr), t0 + + MOVQ (8*1)(x_ptr), AX + MULQ t0 + MOVQ AX, acc1 + MOVQ DX, acc2 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, acc3 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, acc4 + // y[2:] * y[1] + MOVQ (8*1)(x_ptr), t0 + + MOVQ (8*2)(x_ptr), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ t1, acc4 + ADCQ $0, DX + ADDQ AX, acc4 + ADCQ $0, DX + MOVQ DX, acc5 + // y[3] * y[2] + MOVQ (8*2)(x_ptr), t0 + + MOVQ (8*3)(x_ptr), AX + MULQ t0 + ADDQ AX, acc5 + ADCQ $0, DX + MOVQ DX, y_ptr + XORQ t1, t1 + // *2 + ADDQ acc1, acc1 + ADCQ acc2, acc2 + ADCQ acc3, acc3 + ADCQ acc4, acc4 + ADCQ acc5, acc5 + ADCQ y_ptr, y_ptr + ADCQ $0, t1 + // Missing products + MOVQ (8*0)(x_ptr), AX + MULQ AX + MOVQ AX, acc0 + MOVQ DX, t0 + + MOVQ (8*1)(x_ptr), AX + MULQ AX + ADDQ t0, acc1 + ADCQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t0 + + MOVQ (8*2)(x_ptr), AX + MULQ AX + ADDQ t0, acc3 + ADCQ AX, acc4 + ADCQ $0, DX + MOVQ DX, t0 + + MOVQ (8*3)(x_ptr), AX + MULQ AX + ADDQ t0, acc5 + ADCQ AX, y_ptr + ADCQ DX, t1 + MOVQ t1, x_ptr + // First reduction step + MOVQ acc0, AX + MULQ p256ordK0<>(SB) + MOVQ AX, t0 + + MOVQ p256ord<>+0x00(SB), AX + MULQ t0 + ADDQ AX, acc0 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x08(SB), AX + MULQ t0 + ADDQ t1, acc1 + ADCQ $0, DX + ADDQ AX, acc1 + + MOVQ t0, t1 + ADCQ DX, acc2 + ADCQ $0, t1 + SUBQ t0, acc2 + SBBQ $0, t1 + + MOVQ t0, AX + MOVQ t0, DX + MOVQ t0, acc0 + SHLQ $32, AX + SHRQ $32, DX + + ADDQ t1, acc3 + ADCQ $0, acc0 + SUBQ AX, acc3 + SBBQ DX, acc0 + // Second reduction step + MOVQ acc1, AX + MULQ p256ordK0<>(SB) + MOVQ AX, t0 + + MOVQ p256ord<>+0x00(SB), AX + MULQ t0 + ADDQ AX, acc1 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x08(SB), AX + MULQ t0 + ADDQ t1, acc2 + ADCQ $0, DX + ADDQ AX, acc2 + + MOVQ t0, t1 + ADCQ DX, acc3 + ADCQ $0, t1 + SUBQ t0, acc3 + SBBQ $0, t1 + + MOVQ t0, AX + MOVQ t0, DX + MOVQ t0, acc1 + SHLQ $32, AX + SHRQ $32, DX + + ADDQ t1, acc0 + ADCQ $0, acc1 + SUBQ AX, acc0 + SBBQ DX, acc1 + // Third reduction step + MOVQ acc2, AX + MULQ p256ordK0<>(SB) + MOVQ AX, t0 + + MOVQ p256ord<>+0x00(SB), AX + MULQ t0 + ADDQ AX, acc2 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x08(SB), AX + MULQ t0 + ADDQ t1, acc3 + ADCQ $0, DX + ADDQ AX, acc3 + + MOVQ t0, t1 + ADCQ DX, acc0 + ADCQ $0, t1 + SUBQ t0, acc0 + SBBQ $0, t1 + + MOVQ t0, AX + MOVQ t0, DX + MOVQ t0, acc2 + SHLQ $32, AX + SHRQ $32, DX + + ADDQ t1, acc1 + ADCQ $0, acc2 + SUBQ AX, acc1 + SBBQ DX, acc2 + // Last reduction step + MOVQ acc3, AX + MULQ p256ordK0<>(SB) + MOVQ AX, t0 + + MOVQ p256ord<>+0x00(SB), AX + MULQ t0 + ADDQ AX, acc3 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ p256ord<>+0x08(SB), AX + MULQ t0 + ADDQ t1, acc0 + ADCQ $0, DX + ADDQ AX, acc0 + ADCQ $0, DX + MOVQ DX, t1 + + MOVQ t0, t1 + ADCQ DX, acc1 + ADCQ $0, t1 + SUBQ t0, acc1 + SBBQ $0, t1 + + MOVQ t0, AX + MOVQ t0, DX + MOVQ t0, acc3 + SHLQ $32, AX + SHRQ $32, DX + + ADDQ t1, acc2 + ADCQ $0, acc3 + SUBQ AX, acc2 + SBBQ DX, acc3 + XORQ t0, t0 + // Add bits [511:256] of the sqr result + ADCQ acc4, acc0 + ADCQ acc5, acc1 + ADCQ y_ptr, acc2 + ADCQ x_ptr, acc3 + ADCQ $0, t0 + + MOVQ acc0, acc4 + MOVQ acc1, acc5 + MOVQ acc2, y_ptr + MOVQ acc3, t1 + // Subtract p256 + SUBQ p256ord<>+0x00(SB), acc0 + SBBQ p256ord<>+0x08(SB) ,acc1 + SBBQ p256ord<>+0x10(SB), acc2 + SBBQ p256ord<>+0x18(SB), acc3 + SBBQ $0, t0 + + CMOVQCS acc4, acc0 + CMOVQCS acc5, acc1 + CMOVQCS y_ptr, acc2 + CMOVQCS t1, acc3 + + MOVQ acc0, (8*0)(res_ptr) + MOVQ acc1, (8*1)(res_ptr) + MOVQ acc2, (8*2)(res_ptr) + MOVQ acc3, (8*3)(res_ptr) + MOVQ res_ptr, x_ptr + DECQ BX + JNE ordSqrLoop + + RET +/* ---------------------------------------*/ +#undef res_ptr +#undef x_ptr +#undef y_ptr + +#undef acc0 +#undef acc1 +#undef acc2 +#undef acc3 +#undef acc4 +#undef acc5 +#undef t0 +#undef t1 +/* ---------------------------------------*/ +#define mul0 AX +#define mul1 DX +#define acc0 BX +#define acc1 CX +#define acc2 R8 +#define acc3 R9 +#define acc4 R10 +#define acc5 R11 +#define acc6 R12 +#define acc7 R13 +#define t0 R14 +#define t1 R15 +#define t2 DI +#define t3 SI +#define hlp BP +/* ---------------------------------------*/ +TEXT p256SubInternal(SB),NOSPLIT,$0 + XORQ mul0, mul0 + SUBQ t0, acc4 + SBBQ t1, acc5 + SBBQ t2, acc6 + SBBQ t3, acc7 + SBBQ $0, mul0 + + MOVQ acc4, acc0 + MOVQ acc5, acc1 + MOVQ acc6, acc2 + MOVQ acc7, acc3 + + ADDQ $-1, acc4 + ADCQ p256const0<>(SB), acc5 + ADCQ $0, acc6 + ADCQ p256const1<>(SB), acc7 + ANDQ $1, mul0 + + CMOVQEQ acc0, acc4 + CMOVQEQ acc1, acc5 + CMOVQEQ acc2, acc6 + CMOVQEQ acc3, acc7 + + RET +/* ---------------------------------------*/ +TEXT p256MulInternal(SB),NOSPLIT,$8 + MOVQ acc4, mul0 + MULQ t0 + MOVQ mul0, acc0 + MOVQ mul1, acc1 + + MOVQ acc4, mul0 + MULQ t1 + ADDQ mul0, acc1 + ADCQ $0, mul1 + MOVQ mul1, acc2 + + MOVQ acc4, mul0 + MULQ t2 + ADDQ mul0, acc2 + ADCQ $0, mul1 + MOVQ mul1, acc3 + + MOVQ acc4, mul0 + MULQ t3 + ADDQ mul0, acc3 + ADCQ $0, mul1 + MOVQ mul1, acc4 + + MOVQ acc5, mul0 + MULQ t0 + ADDQ mul0, acc1 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc5, mul0 + MULQ t1 + ADDQ hlp, acc2 + ADCQ $0, mul1 + ADDQ mul0, acc2 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc5, mul0 + MULQ t2 + ADDQ hlp, acc3 + ADCQ $0, mul1 + ADDQ mul0, acc3 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc5, mul0 + MULQ t3 + ADDQ hlp, acc4 + ADCQ $0, mul1 + ADDQ mul0, acc4 + ADCQ $0, mul1 + MOVQ mul1, acc5 + + MOVQ acc6, mul0 + MULQ t0 + ADDQ mul0, acc2 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc6, mul0 + MULQ t1 + ADDQ hlp, acc3 + ADCQ $0, mul1 + ADDQ mul0, acc3 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc6, mul0 + MULQ t2 + ADDQ hlp, acc4 + ADCQ $0, mul1 + ADDQ mul0, acc4 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc6, mul0 + MULQ t3 + ADDQ hlp, acc5 + ADCQ $0, mul1 + ADDQ mul0, acc5 + ADCQ $0, mul1 + MOVQ mul1, acc6 + + MOVQ acc7, mul0 + MULQ t0 + ADDQ mul0, acc3 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc7, mul0 + MULQ t1 + ADDQ hlp, acc4 + ADCQ $0, mul1 + ADDQ mul0, acc4 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc7, mul0 + MULQ t2 + ADDQ hlp, acc5 + ADCQ $0, mul1 + ADDQ mul0, acc5 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc7, mul0 + MULQ t3 + ADDQ hlp, acc6 + ADCQ $0, mul1 + ADDQ mul0, acc6 + ADCQ $0, mul1 + MOVQ mul1, acc7 + // First reduction step + MOVQ acc0, mul0 + MOVQ acc0, hlp + SHLQ $32, acc0 + MULQ p256const1<>(SB) + SHRQ $32, hlp + ADDQ acc0, acc1 + ADCQ hlp, acc2 + ADCQ mul0, acc3 + ADCQ $0, mul1 + MOVQ mul1, acc0 + // Second reduction step + MOVQ acc1, mul0 + MOVQ acc1, hlp + SHLQ $32, acc1 + MULQ p256const1<>(SB) + SHRQ $32, hlp + ADDQ acc1, acc2 + ADCQ hlp, acc3 + ADCQ mul0, acc0 + ADCQ $0, mul1 + MOVQ mul1, acc1 + // Third reduction step + MOVQ acc2, mul0 + MOVQ acc2, hlp + SHLQ $32, acc2 + MULQ p256const1<>(SB) + SHRQ $32, hlp + ADDQ acc2, acc3 + ADCQ hlp, acc0 + ADCQ mul0, acc1 + ADCQ $0, mul1 + MOVQ mul1, acc2 + // Last reduction step + MOVQ acc3, mul0 + MOVQ acc3, hlp + SHLQ $32, acc3 + MULQ p256const1<>(SB) + SHRQ $32, hlp + ADDQ acc3, acc0 + ADCQ hlp, acc1 + ADCQ mul0, acc2 + ADCQ $0, mul1 + MOVQ mul1, acc3 + MOVQ $0, BP + // Add bits [511:256] of the result + ADCQ acc0, acc4 + ADCQ acc1, acc5 + ADCQ acc2, acc6 + ADCQ acc3, acc7 + ADCQ $0, hlp + // Copy result + MOVQ acc4, acc0 + MOVQ acc5, acc1 + MOVQ acc6, acc2 + MOVQ acc7, acc3 + // Subtract p256 + SUBQ $-1, acc4 + SBBQ p256const0<>(SB) ,acc5 + SBBQ $0, acc6 + SBBQ p256const1<>(SB), acc7 + SBBQ $0, hlp + // If the result of the subtraction is negative, restore the previous result + CMOVQCS acc0, acc4 + CMOVQCS acc1, acc5 + CMOVQCS acc2, acc6 + CMOVQCS acc3, acc7 + + RET +/* ---------------------------------------*/ +TEXT p256SqrInternal(SB),NOSPLIT,$8 + + MOVQ acc4, mul0 + MULQ acc5 + MOVQ mul0, acc1 + MOVQ mul1, acc2 + + MOVQ acc4, mul0 + MULQ acc6 + ADDQ mul0, acc2 + ADCQ $0, mul1 + MOVQ mul1, acc3 + + MOVQ acc4, mul0 + MULQ acc7 + ADDQ mul0, acc3 + ADCQ $0, mul1 + MOVQ mul1, t0 + + MOVQ acc5, mul0 + MULQ acc6 + ADDQ mul0, acc3 + ADCQ $0, mul1 + MOVQ mul1, hlp + + MOVQ acc5, mul0 + MULQ acc7 + ADDQ hlp, t0 + ADCQ $0, mul1 + ADDQ mul0, t0 + ADCQ $0, mul1 + MOVQ mul1, t1 + + MOVQ acc6, mul0 + MULQ acc7 + ADDQ mul0, t1 + ADCQ $0, mul1 + MOVQ mul1, t2 + XORQ t3, t3 + // *2 + ADDQ acc1, acc1 + ADCQ acc2, acc2 + ADCQ acc3, acc3 + ADCQ t0, t0 + ADCQ t1, t1 + ADCQ t2, t2 + ADCQ $0, t3 + // Missing products + MOVQ acc4, mul0 + MULQ mul0 + MOVQ mul0, acc0 + MOVQ DX, acc4 + + MOVQ acc5, mul0 + MULQ mul0 + ADDQ acc4, acc1 + ADCQ mul0, acc2 + ADCQ $0, DX + MOVQ DX, acc4 + + MOVQ acc6, mul0 + MULQ mul0 + ADDQ acc4, acc3 + ADCQ mul0, t0 + ADCQ $0, DX + MOVQ DX, acc4 + + MOVQ acc7, mul0 + MULQ mul0 + ADDQ acc4, t1 + ADCQ mul0, t2 + ADCQ DX, t3 + // First reduction step + MOVQ acc0, mul0 + MOVQ acc0, hlp + SHLQ $32, acc0 + MULQ p256const1<>(SB) + SHRQ $32, hlp + ADDQ acc0, acc1 + ADCQ hlp, acc2 + ADCQ mul0, acc3 + ADCQ $0, mul1 + MOVQ mul1, acc0 + // Second reduction step + MOVQ acc1, mul0 + MOVQ acc1, hlp + SHLQ $32, acc1 + MULQ p256const1<>(SB) + SHRQ $32, hlp + ADDQ acc1, acc2 + ADCQ hlp, acc3 + ADCQ mul0, acc0 + ADCQ $0, mul1 + MOVQ mul1, acc1 + // Third reduction step + MOVQ acc2, mul0 + MOVQ acc2, hlp + SHLQ $32, acc2 + MULQ p256const1<>(SB) + SHRQ $32, hlp + ADDQ acc2, acc3 + ADCQ hlp, acc0 + ADCQ mul0, acc1 + ADCQ $0, mul1 + MOVQ mul1, acc2 + // Last reduction step + MOVQ acc3, mul0 + MOVQ acc3, hlp + SHLQ $32, acc3 + MULQ p256const1<>(SB) + SHRQ $32, hlp + ADDQ acc3, acc0 + ADCQ hlp, acc1 + ADCQ mul0, acc2 + ADCQ $0, mul1 + MOVQ mul1, acc3 + MOVQ $0, BP + // Add bits [511:256] of the result + ADCQ acc0, t0 + ADCQ acc1, t1 + ADCQ acc2, t2 + ADCQ acc3, t3 + ADCQ $0, hlp + // Copy result + MOVQ t0, acc4 + MOVQ t1, acc5 + MOVQ t2, acc6 + MOVQ t3, acc7 + // Subtract p256 + SUBQ $-1, acc4 + SBBQ p256const0<>(SB) ,acc5 + SBBQ $0, acc6 + SBBQ p256const1<>(SB), acc7 + SBBQ $0, hlp + // If the result of the subtraction is negative, restore the previous result + CMOVQCS t0, acc4 + CMOVQCS t1, acc5 + CMOVQCS t2, acc6 + CMOVQCS t3, acc7 + + RET +/* ---------------------------------------*/ +#define p256MulBy2Inline\ + XORQ mul0, mul0;\ + ADDQ acc4, acc4;\ + ADCQ acc5, acc5;\ + ADCQ acc6, acc6;\ + ADCQ acc7, acc7;\ + ADCQ $0, mul0;\ + MOVQ acc4, t0;\ + MOVQ acc5, t1;\ + MOVQ acc6, t2;\ + MOVQ acc7, t3;\ + SUBQ $-1, t0;\ + SBBQ p256const0<>(SB), t1;\ + SBBQ $0, t2;\ + SBBQ p256const1<>(SB), t3;\ + SBBQ $0, mul0;\ + CMOVQCS acc4, t0;\ + CMOVQCS acc5, t1;\ + CMOVQCS acc6, t2;\ + CMOVQCS acc7, t3; +/* ---------------------------------------*/ +#define p256AddInline \ + XORQ mul0, mul0;\ + ADDQ t0, acc4;\ + ADCQ t1, acc5;\ + ADCQ t2, acc6;\ + ADCQ t3, acc7;\ + ADCQ $0, mul0;\ + MOVQ acc4, t0;\ + MOVQ acc5, t1;\ + MOVQ acc6, t2;\ + MOVQ acc7, t3;\ + SUBQ $-1, t0;\ + SBBQ p256const0<>(SB), t1;\ + SBBQ $0, t2;\ + SBBQ p256const1<>(SB), t3;\ + SBBQ $0, mul0;\ + CMOVQCS acc4, t0;\ + CMOVQCS acc5, t1;\ + CMOVQCS acc6, t2;\ + CMOVQCS acc7, t3; +/* ---------------------------------------*/ +#define LDacc(src) MOVQ src(8*0), acc4; MOVQ src(8*1), acc5; MOVQ src(8*2), acc6; MOVQ src(8*3), acc7 +#define LDt(src) MOVQ src(8*0), t0; MOVQ src(8*1), t1; MOVQ src(8*2), t2; MOVQ src(8*3), t3 +#define ST(dst) MOVQ acc4, dst(8*0); MOVQ acc5, dst(8*1); MOVQ acc6, dst(8*2); MOVQ acc7, dst(8*3) +#define STt(dst) MOVQ t0, dst(8*0); MOVQ t1, dst(8*1); MOVQ t2, dst(8*2); MOVQ t3, dst(8*3) +#define acc2t MOVQ acc4, t0; MOVQ acc5, t1; MOVQ acc6, t2; MOVQ acc7, t3 +#define t2acc MOVQ t0, acc4; MOVQ t1, acc5; MOVQ t2, acc6; MOVQ t3, acc7 +/* ---------------------------------------*/ +#define x1in(off) (32*0 + off)(SP) +#define y1in(off) (32*1 + off)(SP) +#define z1in(off) (32*2 + off)(SP) +#define x2in(off) (32*3 + off)(SP) +#define y2in(off) (32*4 + off)(SP) +#define xout(off) (32*5 + off)(SP) +#define yout(off) (32*6 + off)(SP) +#define zout(off) (32*7 + off)(SP) +#define s2(off) (32*8 + off)(SP) +#define z1sqr(off) (32*9 + off)(SP) +#define h(off) (32*10 + off)(SP) +#define r(off) (32*11 + off)(SP) +#define hsqr(off) (32*12 + off)(SP) +#define rsqr(off) (32*13 + off)(SP) +#define hcub(off) (32*14 + off)(SP) +#define rptr (32*15)(SP) +#define sel_save (32*15 + 8)(SP) +#define zero_save (32*15 + 8 + 4)(SP) + +// func p256PointAddAffineAsm(res, in1, in2 []uint64, sign, sel, zero int) +TEXT ·p256PointAddAffineAsm(SB),0,$512-96 + // Move input to stack in order to free registers + MOVQ res+0(FP), AX + MOVQ in1+24(FP), BX + MOVQ in2+48(FP), CX + MOVQ sign+72(FP), DX + MOVQ sel+80(FP), t1 + MOVQ zero+88(FP), t2 + + MOVOU (16*0)(BX), X0 + MOVOU (16*1)(BX), X1 + MOVOU (16*2)(BX), X2 + MOVOU (16*3)(BX), X3 + MOVOU (16*4)(BX), X4 + MOVOU (16*5)(BX), X5 + + MOVOU X0, x1in(16*0) + MOVOU X1, x1in(16*1) + MOVOU X2, y1in(16*0) + MOVOU X3, y1in(16*1) + MOVOU X4, z1in(16*0) + MOVOU X5, z1in(16*1) + + MOVOU (16*0)(CX), X0 + MOVOU (16*1)(CX), X1 + + MOVOU X0, x2in(16*0) + MOVOU X1, x2in(16*1) + // Store pointer to result + MOVQ mul0, rptr + MOVL t1, sel_save + MOVL t2, zero_save + // Negate y2in based on sign + MOVQ (16*2 + 8*0)(CX), acc4 + MOVQ (16*2 + 8*1)(CX), acc5 + MOVQ (16*2 + 8*2)(CX), acc6 + MOVQ (16*2 + 8*3)(CX), acc7 + MOVQ $-1, acc0 + MOVQ p256const0<>(SB), acc1 + MOVQ $0, acc2 + MOVQ p256const1<>(SB), acc3 + XORQ mul0, mul0 + // Speculatively subtract + SUBQ acc4, acc0 + SBBQ acc5, acc1 + SBBQ acc6, acc2 + SBBQ acc7, acc3 + SBBQ $0, mul0 + MOVQ acc0, t0 + MOVQ acc1, t1 + MOVQ acc2, t2 + MOVQ acc3, t3 + // Add in case the operand was > p256 + ADDQ $-1, acc0 + ADCQ p256const0<>(SB), acc1 + ADCQ $0, acc2 + ADCQ p256const1<>(SB), acc3 + ADCQ $0, mul0 + CMOVQNE t0, acc0 + CMOVQNE t1, acc1 + CMOVQNE t2, acc2 + CMOVQNE t3, acc3 + // If condition is 0, keep original value + TESTQ DX, DX + CMOVQEQ acc4, acc0 + CMOVQEQ acc5, acc1 + CMOVQEQ acc6, acc2 + CMOVQEQ acc7, acc3 + // Store result + MOVQ acc0, y2in(8*0) + MOVQ acc1, y2in(8*1) + MOVQ acc2, y2in(8*2) + MOVQ acc3, y2in(8*3) + // Begin point add + LDacc (z1in) + CALL p256SqrInternal(SB) // z1ˆ2 + ST (z1sqr) + + LDt (x2in) + CALL p256MulInternal(SB) // x2 * z1ˆ2 + + LDt (x1in) + CALL p256SubInternal(SB) // h = u2 - u1 + ST (h) + + LDt (z1in) + CALL p256MulInternal(SB) // z3 = h * z1 + ST (zout) + + LDacc (z1sqr) + CALL p256MulInternal(SB) // z1ˆ3 + + LDt (y2in) + CALL p256MulInternal(SB) // s2 = y2 * z1ˆ3 + ST (s2) + + LDt (y1in) + CALL p256SubInternal(SB) // r = s2 - s1 + ST (r) + + CALL p256SqrInternal(SB) // rsqr = rˆ2 + ST (rsqr) + + LDacc (h) + CALL p256SqrInternal(SB) // hsqr = hˆ2 + ST (hsqr) + + LDt (h) + CALL p256MulInternal(SB) // hcub = hˆ3 + ST (hcub) + + LDt (y1in) + CALL p256MulInternal(SB) // y1 * hˆ3 + ST (s2) + + LDacc (x1in) + LDt (hsqr) + CALL p256MulInternal(SB) // u1 * hˆ2 + ST (h) + + p256MulBy2Inline // u1 * hˆ2 * 2, inline + LDacc (rsqr) + CALL p256SubInternal(SB) // rˆ2 - u1 * hˆ2 * 2 + + LDt (hcub) + CALL p256SubInternal(SB) + ST (xout) + + MOVQ acc4, t0 + MOVQ acc5, t1 + MOVQ acc6, t2 + MOVQ acc7, t3 + LDacc (h) + CALL p256SubInternal(SB) + + LDt (r) + CALL p256MulInternal(SB) + + LDt (s2) + CALL p256SubInternal(SB) + ST (yout) + // Load stored values from stack + MOVQ rptr, AX + MOVL sel_save, BX + MOVL zero_save, CX + // The result is not valid if (sel == 0), conditional choose + MOVOU xout(16*0), X0 + MOVOU xout(16*1), X1 + MOVOU yout(16*0), X2 + MOVOU yout(16*1), X3 + MOVOU zout(16*0), X4 + MOVOU zout(16*1), X5 + + MOVL BX, X6 + MOVL CX, X7 + + PXOR X8, X8 + PCMPEQL X9, X9 + + PSHUFD $0, X6, X6 + PSHUFD $0, X7, X7 + + PCMPEQL X8, X6 + PCMPEQL X8, X7 + + MOVOU X6, X15 + PANDN X9, X15 + + MOVOU x1in(16*0), X9 + MOVOU x1in(16*1), X10 + MOVOU y1in(16*0), X11 + MOVOU y1in(16*1), X12 + MOVOU z1in(16*0), X13 + MOVOU z1in(16*1), X14 + + PAND X15, X0 + PAND X15, X1 + PAND X15, X2 + PAND X15, X3 + PAND X15, X4 + PAND X15, X5 + + PAND X6, X9 + PAND X6, X10 + PAND X6, X11 + PAND X6, X12 + PAND X6, X13 + PAND X6, X14 + + PXOR X9, X0 + PXOR X10, X1 + PXOR X11, X2 + PXOR X12, X3 + PXOR X13, X4 + PXOR X14, X5 + // Similarly if zero == 0 + PCMPEQL X9, X9 + MOVOU X7, X15 + PANDN X9, X15 + + MOVOU x2in(16*0), X9 + MOVOU x2in(16*1), X10 + MOVOU y2in(16*0), X11 + MOVOU y2in(16*1), X12 + MOVOU p256one<>+0x00(SB), X13 + MOVOU p256one<>+0x10(SB), X14 + + PAND X15, X0 + PAND X15, X1 + PAND X15, X2 + PAND X15, X3 + PAND X15, X4 + PAND X15, X5 + + PAND X7, X9 + PAND X7, X10 + PAND X7, X11 + PAND X7, X12 + PAND X7, X13 + PAND X7, X14 + + PXOR X9, X0 + PXOR X10, X1 + PXOR X11, X2 + PXOR X12, X3 + PXOR X13, X4 + PXOR X14, X5 + // Finally output the result + MOVOU X0, (16*0)(AX) + MOVOU X1, (16*1)(AX) + MOVOU X2, (16*2)(AX) + MOVOU X3, (16*3)(AX) + MOVOU X4, (16*4)(AX) + MOVOU X5, (16*5)(AX) + MOVQ $0, rptr + + RET +#undef x1in +#undef y1in +#undef z1in +#undef x2in +#undef y2in +#undef xout +#undef yout +#undef zout +#undef s2 +#undef z1sqr +#undef h +#undef r +#undef hsqr +#undef rsqr +#undef hcub +#undef rptr +#undef sel_save +#undef zero_save + +// p256IsZero returns 1 in AX if [acc4..acc7] represents zero and zero +// otherwise. It writes to [acc4..acc7], t0 and t1. +TEXT p256IsZero(SB),NOSPLIT,$0 + // AX contains a flag that is set if the input is zero. + XORQ AX, AX + MOVQ $1, t1 + + // Check whether [acc4..acc7] are all zero. + MOVQ acc4, t0 + ORQ acc5, t0 + ORQ acc6, t0 + ORQ acc7, t0 + + // Set the zero flag if so. (CMOV of a constant to a register doesn't + // appear to be supported in Go. Thus t1 = 1.) + CMOVQEQ t1, AX + + // XOR [acc4..acc7] with P and compare with zero again. + XORQ $-1, acc4 + XORQ p256const0<>(SB), acc5 + XORQ p256const1<>(SB), acc7 + ORQ acc5, acc4 + ORQ acc6, acc4 + ORQ acc7, acc4 + + // Set the zero flag if so. + CMOVQEQ t1, AX + RET + +/* ---------------------------------------*/ +#define x1in(off) (32*0 + off)(SP) +#define y1in(off) (32*1 + off)(SP) +#define z1in(off) (32*2 + off)(SP) +#define x2in(off) (32*3 + off)(SP) +#define y2in(off) (32*4 + off)(SP) +#define z2in(off) (32*5 + off)(SP) + +#define xout(off) (32*6 + off)(SP) +#define yout(off) (32*7 + off)(SP) +#define zout(off) (32*8 + off)(SP) + +#define u1(off) (32*9 + off)(SP) +#define u2(off) (32*10 + off)(SP) +#define s1(off) (32*11 + off)(SP) +#define s2(off) (32*12 + off)(SP) +#define z1sqr(off) (32*13 + off)(SP) +#define z2sqr(off) (32*14 + off)(SP) +#define h(off) (32*15 + off)(SP) +#define r(off) (32*16 + off)(SP) +#define hsqr(off) (32*17 + off)(SP) +#define rsqr(off) (32*18 + off)(SP) +#define hcub(off) (32*19 + off)(SP) +#define rptr (32*20)(SP) +#define points_eq (32*20+8)(SP) + +//func p256PointAddAsm(res, in1, in2 []uint64) int +TEXT ·p256PointAddAsm(SB),0,$680-80 + // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl + // Move input to stack in order to free registers + MOVQ res+0(FP), AX + MOVQ in1+24(FP), BX + MOVQ in2+48(FP), CX + + MOVOU (16*0)(BX), X0 + MOVOU (16*1)(BX), X1 + MOVOU (16*2)(BX), X2 + MOVOU (16*3)(BX), X3 + MOVOU (16*4)(BX), X4 + MOVOU (16*5)(BX), X5 + + MOVOU X0, x1in(16*0) + MOVOU X1, x1in(16*1) + MOVOU X2, y1in(16*0) + MOVOU X3, y1in(16*1) + MOVOU X4, z1in(16*0) + MOVOU X5, z1in(16*1) + + MOVOU (16*0)(CX), X0 + MOVOU (16*1)(CX), X1 + MOVOU (16*2)(CX), X2 + MOVOU (16*3)(CX), X3 + MOVOU (16*4)(CX), X4 + MOVOU (16*5)(CX), X5 + + MOVOU X0, x2in(16*0) + MOVOU X1, x2in(16*1) + MOVOU X2, y2in(16*0) + MOVOU X3, y2in(16*1) + MOVOU X4, z2in(16*0) + MOVOU X5, z2in(16*1) + // Store pointer to result + MOVQ AX, rptr + // Begin point add + LDacc (z2in) + CALL p256SqrInternal(SB) // z2ˆ2 + ST (z2sqr) + LDt (z2in) + CALL p256MulInternal(SB) // z2ˆ3 + LDt (y1in) + CALL p256MulInternal(SB) // s1 = z2ˆ3*y1 + ST (s1) + + LDacc (z1in) + CALL p256SqrInternal(SB) // z1ˆ2 + ST (z1sqr) + LDt (z1in) + CALL p256MulInternal(SB) // z1ˆ3 + LDt (y2in) + CALL p256MulInternal(SB) // s2 = z1ˆ3*y2 + ST (s2) + + LDt (s1) + CALL p256SubInternal(SB) // r = s2 - s1 + ST (r) + CALL p256IsZero(SB) + MOVQ AX, points_eq + + LDacc (z2sqr) + LDt (x1in) + CALL p256MulInternal(SB) // u1 = x1 * z2ˆ2 + ST (u1) + LDacc (z1sqr) + LDt (x2in) + CALL p256MulInternal(SB) // u2 = x2 * z1ˆ2 + ST (u2) + + LDt (u1) + CALL p256SubInternal(SB) // h = u2 - u1 + ST (h) + CALL p256IsZero(SB) + ANDQ points_eq, AX + MOVQ AX, points_eq + + LDacc (r) + CALL p256SqrInternal(SB) // rsqr = rˆ2 + ST (rsqr) + + LDacc (h) + CALL p256SqrInternal(SB) // hsqr = hˆ2 + ST (hsqr) + + LDt (h) + CALL p256MulInternal(SB) // hcub = hˆ3 + ST (hcub) + + LDt (s1) + CALL p256MulInternal(SB) + ST (s2) + + LDacc (z1in) + LDt (z2in) + CALL p256MulInternal(SB) // z1 * z2 + LDt (h) + CALL p256MulInternal(SB) // z1 * z2 * h + ST (zout) + + LDacc (hsqr) + LDt (u1) + CALL p256MulInternal(SB) // hˆ2 * u1 + ST (u2) + + p256MulBy2Inline // u1 * hˆ2 * 2, inline + LDacc (rsqr) + CALL p256SubInternal(SB) // rˆ2 - u1 * hˆ2 * 2 + + LDt (hcub) + CALL p256SubInternal(SB) + ST (xout) + + MOVQ acc4, t0 + MOVQ acc5, t1 + MOVQ acc6, t2 + MOVQ acc7, t3 + LDacc (u2) + CALL p256SubInternal(SB) + + LDt (r) + CALL p256MulInternal(SB) + + LDt (s2) + CALL p256SubInternal(SB) + ST (yout) + + MOVOU xout(16*0), X0 + MOVOU xout(16*1), X1 + MOVOU yout(16*0), X2 + MOVOU yout(16*1), X3 + MOVOU zout(16*0), X4 + MOVOU zout(16*1), X5 + // Finally output the result + MOVQ rptr, AX + MOVQ $0, rptr + MOVOU X0, (16*0)(AX) + MOVOU X1, (16*1)(AX) + MOVOU X2, (16*2)(AX) + MOVOU X3, (16*3)(AX) + MOVOU X4, (16*4)(AX) + MOVOU X5, (16*5)(AX) + + MOVQ points_eq, AX + MOVQ AX, ret+72(FP) + + RET +#undef x1in +#undef y1in +#undef z1in +#undef x2in +#undef y2in +#undef z2in +#undef xout +#undef yout +#undef zout +#undef s1 +#undef s2 +#undef u1 +#undef u2 +#undef z1sqr +#undef z2sqr +#undef h +#undef r +#undef hsqr +#undef rsqr +#undef hcub +#undef rptr +/* ---------------------------------------*/ +#define x(off) (32*0 + off)(SP) +#define y(off) (32*1 + off)(SP) +#define z(off) (32*2 + off)(SP) + +#define s(off) (32*3 + off)(SP) +#define m(off) (32*4 + off)(SP) +#define zsqr(off) (32*5 + off)(SP) +#define tmp(off) (32*6 + off)(SP) +#define rptr (32*7)(SP) + +//func p256PointDoubleAsm(res, in []uint64) +TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$256-48 + // Move input to stack in order to free registers + MOVQ res+0(FP), AX + MOVQ in+24(FP), BX + + MOVOU (16*0)(BX), X0 + MOVOU (16*1)(BX), X1 + MOVOU (16*2)(BX), X2 + MOVOU (16*3)(BX), X3 + MOVOU (16*4)(BX), X4 + MOVOU (16*5)(BX), X5 + + MOVOU X0, x(16*0) + MOVOU X1, x(16*1) + MOVOU X2, y(16*0) + MOVOU X3, y(16*1) + MOVOU X4, z(16*0) + MOVOU X5, z(16*1) + // Store pointer to result + MOVQ AX, rptr + // Begin point double + LDacc (z) + CALL p256SqrInternal(SB) + ST (zsqr) + + LDt (x) + p256AddInline + STt (m) + + LDacc (z) + LDt (y) + CALL p256MulInternal(SB) + p256MulBy2Inline + MOVQ rptr, AX + // Store z + MOVQ t0, (16*4 + 8*0)(AX) + MOVQ t1, (16*4 + 8*1)(AX) + MOVQ t2, (16*4 + 8*2)(AX) + MOVQ t3, (16*4 + 8*3)(AX) + + LDacc (x) + LDt (zsqr) + CALL p256SubInternal(SB) + LDt (m) + CALL p256MulInternal(SB) + ST (m) + // Multiply by 3 + p256MulBy2Inline + LDacc (m) + p256AddInline + STt (m) + //////////////////////// + LDacc (y) + p256MulBy2Inline + t2acc + CALL p256SqrInternal(SB) + ST (s) + CALL p256SqrInternal(SB) + // Divide by 2 + XORQ mul0, mul0 + MOVQ acc4, t0 + MOVQ acc5, t1 + MOVQ acc6, t2 + MOVQ acc7, t3 + + ADDQ $-1, acc4 + ADCQ p256const0<>(SB), acc5 + ADCQ $0, acc6 + ADCQ p256const1<>(SB), acc7 + ADCQ $0, mul0 + TESTQ $1, t0 + + CMOVQEQ t0, acc4 + CMOVQEQ t1, acc5 + CMOVQEQ t2, acc6 + CMOVQEQ t3, acc7 + ANDQ t0, mul0 + + SHRQ $1, acc5, acc4 + SHRQ $1, acc6, acc5 + SHRQ $1, acc7, acc6 + SHRQ $1, mul0, acc7 + ST (y) + ///////////////////////// + LDacc (x) + LDt (s) + CALL p256MulInternal(SB) + ST (s) + p256MulBy2Inline + STt (tmp) + + LDacc (m) + CALL p256SqrInternal(SB) + LDt (tmp) + CALL p256SubInternal(SB) + + MOVQ rptr, AX + // Store x + MOVQ acc4, (16*0 + 8*0)(AX) + MOVQ acc5, (16*0 + 8*1)(AX) + MOVQ acc6, (16*0 + 8*2)(AX) + MOVQ acc7, (16*0 + 8*3)(AX) + + acc2t + LDacc (s) + CALL p256SubInternal(SB) + + LDt (m) + CALL p256MulInternal(SB) + + LDt (y) + CALL p256SubInternal(SB) + MOVQ rptr, AX + // Store y + MOVQ acc4, (16*2 + 8*0)(AX) + MOVQ acc5, (16*2 + 8*1)(AX) + MOVQ acc6, (16*2 + 8*2)(AX) + MOVQ acc7, (16*2 + 8*3)(AX) + /////////////////////// + MOVQ $0, rptr + + RET +/* ---------------------------------------*/ diff --git a/src/crypto/elliptic/p256_asm_arm64.s b/src/crypto/elliptic/p256_asm_arm64.s new file mode 100644 index 0000000..f571c50 --- /dev/null +++ b/src/crypto/elliptic/p256_asm_arm64.s @@ -0,0 +1,1529 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains constant-time, 64-bit assembly implementation of +// P256. The optimizations performed here are described in detail in: +// S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with +// 256-bit primes" +// http://link.springer.com/article/10.1007%2Fs13389-014-0090-x +// https://eprint.iacr.org/2013/816.pdf + +#include "textflag.h" + +#define res_ptr R0 +#define a_ptr R1 +#define b_ptr R2 + +#define acc0 R3 +#define acc1 R4 +#define acc2 R5 +#define acc3 R6 + +#define acc4 R7 +#define acc5 R8 +#define acc6 R9 +#define acc7 R10 +#define t0 R11 +#define t1 R12 +#define t2 R13 +#define t3 R14 +#define const0 R15 +#define const1 R16 + +#define hlp0 R17 +#define hlp1 res_ptr + +#define x0 R19 +#define x1 R20 +#define x2 R21 +#define x3 R22 +#define y0 R23 +#define y1 R24 +#define y2 R25 +#define y3 R26 + +#define const2 t2 +#define const3 t3 + +DATA p256const0<>+0x00(SB)/8, $0x00000000ffffffff +DATA p256const1<>+0x00(SB)/8, $0xffffffff00000001 +DATA p256ordK0<>+0x00(SB)/8, $0xccd1c8aaee00bc4f +DATA p256ord<>+0x00(SB)/8, $0xf3b9cac2fc632551 +DATA p256ord<>+0x08(SB)/8, $0xbce6faada7179e84 +DATA p256ord<>+0x10(SB)/8, $0xffffffffffffffff +DATA p256ord<>+0x18(SB)/8, $0xffffffff00000000 +DATA p256one<>+0x00(SB)/8, $0x0000000000000001 +DATA p256one<>+0x08(SB)/8, $0xffffffff00000000 +DATA p256one<>+0x10(SB)/8, $0xffffffffffffffff +DATA p256one<>+0x18(SB)/8, $0x00000000fffffffe +GLOBL p256const0<>(SB), 8, $8 +GLOBL p256const1<>(SB), 8, $8 +GLOBL p256ordK0<>(SB), 8, $8 +GLOBL p256ord<>(SB), 8, $32 +GLOBL p256one<>(SB), 8, $32 + +/* ---------------------------------------*/ +// func p256LittleToBig(res []byte, in []uint64) +TEXT ·p256LittleToBig(SB),NOSPLIT,$0 + JMP ·p256BigToLittle(SB) +/* ---------------------------------------*/ +// func p256BigToLittle(res []uint64, in []byte) +TEXT ·p256BigToLittle(SB),NOSPLIT,$0 + MOVD res+0(FP), res_ptr + MOVD in+24(FP), a_ptr + + LDP 0*16(a_ptr), (acc0, acc1) + LDP 1*16(a_ptr), (acc2, acc3) + + REV acc0, acc0 + REV acc1, acc1 + REV acc2, acc2 + REV acc3, acc3 + + STP (acc3, acc2), 0*16(res_ptr) + STP (acc1, acc0), 1*16(res_ptr) + RET +/* ---------------------------------------*/ +// func p256MovCond(res, a, b []uint64, cond int) +// If cond == 0 res=b, else res=a +TEXT ·p256MovCond(SB),NOSPLIT,$0 + MOVD res+0(FP), res_ptr + MOVD a+24(FP), a_ptr + MOVD b+48(FP), b_ptr + MOVD cond+72(FP), R3 + + CMP $0, R3 + // Two remarks: + // 1) Will want to revisit NEON, when support is better + // 2) CSEL might not be constant time on all ARM processors + LDP 0*16(a_ptr), (R4, R5) + LDP 1*16(a_ptr), (R6, R7) + LDP 2*16(a_ptr), (R8, R9) + LDP 0*16(b_ptr), (R16, R17) + LDP 1*16(b_ptr), (R19, R20) + LDP 2*16(b_ptr), (R21, R22) + CSEL EQ, R16, R4, R4 + CSEL EQ, R17, R5, R5 + CSEL EQ, R19, R6, R6 + CSEL EQ, R20, R7, R7 + CSEL EQ, R21, R8, R8 + CSEL EQ, R22, R9, R9 + STP (R4, R5), 0*16(res_ptr) + STP (R6, R7), 1*16(res_ptr) + STP (R8, R9), 2*16(res_ptr) + + LDP 3*16(a_ptr), (R4, R5) + LDP 4*16(a_ptr), (R6, R7) + LDP 5*16(a_ptr), (R8, R9) + LDP 3*16(b_ptr), (R16, R17) + LDP 4*16(b_ptr), (R19, R20) + LDP 5*16(b_ptr), (R21, R22) + CSEL EQ, R16, R4, R4 + CSEL EQ, R17, R5, R5 + CSEL EQ, R19, R6, R6 + CSEL EQ, R20, R7, R7 + CSEL EQ, R21, R8, R8 + CSEL EQ, R22, R9, R9 + STP (R4, R5), 3*16(res_ptr) + STP (R6, R7), 4*16(res_ptr) + STP (R8, R9), 5*16(res_ptr) + + RET +/* ---------------------------------------*/ +// func p256NegCond(val []uint64, cond int) +TEXT ·p256NegCond(SB),NOSPLIT,$0 + MOVD val+0(FP), a_ptr + MOVD cond+24(FP), hlp0 + MOVD a_ptr, res_ptr + // acc = poly + MOVD $-1, acc0 + MOVD p256const0<>(SB), acc1 + MOVD $0, acc2 + MOVD p256const1<>(SB), acc3 + // Load the original value + LDP 0*16(a_ptr), (t0, t1) + LDP 1*16(a_ptr), (t2, t3) + // Speculatively subtract + SUBS t0, acc0 + SBCS t1, acc1 + SBCS t2, acc2 + SBC t3, acc3 + // If condition is 0, keep original value + CMP $0, hlp0 + CSEL EQ, t0, acc0, acc0 + CSEL EQ, t1, acc1, acc1 + CSEL EQ, t2, acc2, acc2 + CSEL EQ, t3, acc3, acc3 + // Store result + STP (acc0, acc1), 0*16(res_ptr) + STP (acc2, acc3), 1*16(res_ptr) + + RET +/* ---------------------------------------*/ +// func p256Sqr(res, in []uint64, n int) +TEXT ·p256Sqr(SB),NOSPLIT,$0 + MOVD res+0(FP), res_ptr + MOVD in+24(FP), a_ptr + MOVD n+48(FP), b_ptr + + MOVD p256const0<>(SB), const0 + MOVD p256const1<>(SB), const1 + + LDP 0*16(a_ptr), (x0, x1) + LDP 1*16(a_ptr), (x2, x3) + +sqrLoop: + SUB $1, b_ptr + CALL p256SqrInternal<>(SB) + MOVD y0, x0 + MOVD y1, x1 + MOVD y2, x2 + MOVD y3, x3 + CBNZ b_ptr, sqrLoop + + STP (y0, y1), 0*16(res_ptr) + STP (y2, y3), 1*16(res_ptr) + RET +/* ---------------------------------------*/ +// func p256Mul(res, in1, in2 []uint64) +TEXT ·p256Mul(SB),NOSPLIT,$0 + MOVD res+0(FP), res_ptr + MOVD in1+24(FP), a_ptr + MOVD in2+48(FP), b_ptr + + MOVD p256const0<>(SB), const0 + MOVD p256const1<>(SB), const1 + + LDP 0*16(a_ptr), (x0, x1) + LDP 1*16(a_ptr), (x2, x3) + + LDP 0*16(b_ptr), (y0, y1) + LDP 1*16(b_ptr), (y2, y3) + + CALL p256MulInternal<>(SB) + + STP (y0, y1), 0*16(res_ptr) + STP (y2, y3), 1*16(res_ptr) + RET +/* ---------------------------------------*/ +// func p256FromMont(res, in []uint64) +TEXT ·p256FromMont(SB),NOSPLIT,$0 + MOVD res+0(FP), res_ptr + MOVD in+24(FP), a_ptr + + MOVD p256const0<>(SB), const0 + MOVD p256const1<>(SB), const1 + + LDP 0*16(a_ptr), (acc0, acc1) + LDP 1*16(a_ptr), (acc2, acc3) + // Only reduce, no multiplications are needed + // First reduction step + ADDS acc0<<32, acc1, acc1 + LSR $32, acc0, t0 + MUL acc0, const1, t1 + UMULH acc0, const1, acc0 + ADCS t0, acc2 + ADCS t1, acc3 + ADC $0, acc0 + // Second reduction step + ADDS acc1<<32, acc2, acc2 + LSR $32, acc1, t0 + MUL acc1, const1, t1 + UMULH acc1, const1, acc1 + ADCS t0, acc3 + ADCS t1, acc0 + ADC $0, acc1 + // Third reduction step + ADDS acc2<<32, acc3, acc3 + LSR $32, acc2, t0 + MUL acc2, const1, t1 + UMULH acc2, const1, acc2 + ADCS t0, acc0 + ADCS t1, acc1 + ADC $0, acc2 + // Last reduction step + ADDS acc3<<32, acc0, acc0 + LSR $32, acc3, t0 + MUL acc3, const1, t1 + UMULH acc3, const1, acc3 + ADCS t0, acc1 + ADCS t1, acc2 + ADC $0, acc3 + + SUBS $-1, acc0, t0 + SBCS const0, acc1, t1 + SBCS $0, acc2, t2 + SBCS const1, acc3, t3 + + CSEL CS, t0, acc0, acc0 + CSEL CS, t1, acc1, acc1 + CSEL CS, t2, acc2, acc2 + CSEL CS, t3, acc3, acc3 + + STP (acc0, acc1), 0*16(res_ptr) + STP (acc2, acc3), 1*16(res_ptr) + + RET +/* ---------------------------------------*/ +// Constant time point access to arbitrary point table. +// Indexed from 1 to 15, with -1 offset +// (index 0 is implicitly point at infinity) +// func p256Select(point, table []uint64, idx int) +TEXT ·p256Select(SB),NOSPLIT,$0 + MOVD idx+48(FP), const0 + MOVD table+24(FP), b_ptr + MOVD point+0(FP), res_ptr + + EOR x0, x0, x0 + EOR x1, x1, x1 + EOR x2, x2, x2 + EOR x3, x3, x3 + EOR y0, y0, y0 + EOR y1, y1, y1 + EOR y2, y2, y2 + EOR y3, y3, y3 + EOR t0, t0, t0 + EOR t1, t1, t1 + EOR t2, t2, t2 + EOR t3, t3, t3 + + MOVD $0, const1 + +loop_select: + ADD $1, const1 + CMP const0, const1 + LDP.P 16(b_ptr), (acc0, acc1) + CSEL EQ, acc0, x0, x0 + CSEL EQ, acc1, x1, x1 + LDP.P 16(b_ptr), (acc2, acc3) + CSEL EQ, acc2, x2, x2 + CSEL EQ, acc3, x3, x3 + LDP.P 16(b_ptr), (acc4, acc5) + CSEL EQ, acc4, y0, y0 + CSEL EQ, acc5, y1, y1 + LDP.P 16(b_ptr), (acc6, acc7) + CSEL EQ, acc6, y2, y2 + CSEL EQ, acc7, y3, y3 + LDP.P 16(b_ptr), (acc0, acc1) + CSEL EQ, acc0, t0, t0 + CSEL EQ, acc1, t1, t1 + LDP.P 16(b_ptr), (acc2, acc3) + CSEL EQ, acc2, t2, t2 + CSEL EQ, acc3, t3, t3 + + CMP $16, const1 + BNE loop_select + + STP (x0, x1), 0*16(res_ptr) + STP (x2, x3), 1*16(res_ptr) + STP (y0, y1), 2*16(res_ptr) + STP (y2, y3), 3*16(res_ptr) + STP (t0, t1), 4*16(res_ptr) + STP (t2, t3), 5*16(res_ptr) + RET +/* ---------------------------------------*/ +// Constant time point access to base point table. +// func p256SelectBase(point, table []uint64, idx int) +TEXT ·p256SelectBase(SB),NOSPLIT,$0 + MOVD idx+48(FP), t0 + MOVD table+24(FP), t1 + MOVD point+0(FP), res_ptr + + EOR x0, x0, x0 + EOR x1, x1, x1 + EOR x2, x2, x2 + EOR x3, x3, x3 + EOR y0, y0, y0 + EOR y1, y1, y1 + EOR y2, y2, y2 + EOR y3, y3, y3 + + MOVD $0, t2 + +loop_select: + ADD $1, t2 + CMP t0, t2 + LDP.P 16(t1), (acc0, acc1) + CSEL EQ, acc0, x0, x0 + CSEL EQ, acc1, x1, x1 + LDP.P 16(t1), (acc2, acc3) + CSEL EQ, acc2, x2, x2 + CSEL EQ, acc3, x3, x3 + LDP.P 16(t1), (acc4, acc5) + CSEL EQ, acc4, y0, y0 + CSEL EQ, acc5, y1, y1 + LDP.P 16(t1), (acc6, acc7) + CSEL EQ, acc6, y2, y2 + CSEL EQ, acc7, y3, y3 + + CMP $32, t2 + BNE loop_select + + STP (x0, x1), 0*16(res_ptr) + STP (x2, x3), 1*16(res_ptr) + STP (y0, y1), 2*16(res_ptr) + STP (y2, y3), 3*16(res_ptr) + RET +/* ---------------------------------------*/ +// func p256OrdSqr(res, in []uint64, n int) +TEXT ·p256OrdSqr(SB),NOSPLIT,$0 + MOVD in+24(FP), a_ptr + MOVD n+48(FP), b_ptr + + MOVD p256ordK0<>(SB), hlp1 + LDP p256ord<>+0x00(SB), (const0, const1) + LDP p256ord<>+0x10(SB), (const2, const3) + + LDP 0*16(a_ptr), (x0, x1) + LDP 1*16(a_ptr), (x2, x3) + +ordSqrLoop: + SUB $1, b_ptr + + // x[1:] * x[0] + MUL x0, x1, acc1 + UMULH x0, x1, acc2 + + MUL x0, x2, t0 + ADDS t0, acc2, acc2 + UMULH x0, x2, acc3 + + MUL x0, x3, t0 + ADCS t0, acc3, acc3 + UMULH x0, x3, acc4 + ADC $0, acc4, acc4 + // x[2:] * x[1] + MUL x1, x2, t0 + ADDS t0, acc3 + UMULH x1, x2, t1 + ADCS t1, acc4 + ADC $0, ZR, acc5 + + MUL x1, x3, t0 + ADDS t0, acc4 + UMULH x1, x3, t1 + ADC t1, acc5 + // x[3] * x[2] + MUL x2, x3, t0 + ADDS t0, acc5 + UMULH x2, x3, acc6 + ADC $0, acc6 + + MOVD $0, acc7 + // *2 + ADDS acc1, acc1 + ADCS acc2, acc2 + ADCS acc3, acc3 + ADCS acc4, acc4 + ADCS acc5, acc5 + ADCS acc6, acc6 + ADC $0, acc7 + // Missing products + MUL x0, x0, acc0 + UMULH x0, x0, t0 + ADDS t0, acc1, acc1 + + MUL x1, x1, t0 + ADCS t0, acc2, acc2 + UMULH x1, x1, t1 + ADCS t1, acc3, acc3 + + MUL x2, x2, t0 + ADCS t0, acc4, acc4 + UMULH x2, x2, t1 + ADCS t1, acc5, acc5 + + MUL x3, x3, t0 + ADCS t0, acc6, acc6 + UMULH x3, x3, t1 + ADC t1, acc7, acc7 + // First reduction step + MUL acc0, hlp1, hlp0 + + MUL const0, hlp1, t0 + ADDS t0, acc0, acc0 + UMULH const0, hlp0, t1 + + MUL const1, hlp0, t0 + ADCS t0, acc1, acc1 + UMULH const1, hlp0, y0 + + MUL const2, hlp0, t0 + ADCS t0, acc2, acc2 + UMULH const2, hlp0, acc0 + + MUL const3, hlp0, t0 + ADCS t0, acc3, acc3 + + UMULH const3, hlp0, hlp0 + ADC $0, hlp0 + + ADDS t1, acc1, acc1 + ADCS y0, acc2, acc2 + ADCS acc0, acc3, acc3 + ADC $0, hlp0, acc0 + // Second reduction step + MUL acc1, hlp1, hlp0 + + MUL const0, hlp1, t0 + ADDS t0, acc1, acc1 + UMULH const0, hlp0, t1 + + MUL const1, hlp0, t0 + ADCS t0, acc2, acc2 + UMULH const1, hlp0, y0 + + MUL const2, hlp0, t0 + ADCS t0, acc3, acc3 + UMULH const2, hlp0, acc1 + + MUL const3, hlp0, t0 + ADCS t0, acc0, acc0 + + UMULH const3, hlp0, hlp0 + ADC $0, hlp0 + + ADDS t1, acc2, acc2 + ADCS y0, acc3, acc3 + ADCS acc1, acc0, acc0 + ADC $0, hlp0, acc1 + // Third reduction step + MUL acc2, hlp1, hlp0 + + MUL const0, hlp1, t0 + ADDS t0, acc2, acc2 + UMULH const0, hlp0, t1 + + MUL const1, hlp0, t0 + ADCS t0, acc3, acc3 + UMULH const1, hlp0, y0 + + MUL const2, hlp0, t0 + ADCS t0, acc0, acc0 + UMULH const2, hlp0, acc2 + + MUL const3, hlp0, t0 + ADCS t0, acc1, acc1 + + UMULH const3, hlp0, hlp0 + ADC $0, hlp0 + + ADDS t1, acc3, acc3 + ADCS y0, acc0, acc0 + ADCS acc2, acc1, acc1 + ADC $0, hlp0, acc2 + + // Last reduction step + MUL acc3, hlp1, hlp0 + + MUL const0, hlp1, t0 + ADDS t0, acc3, acc3 + UMULH const0, hlp0, t1 + + MUL const1, hlp0, t0 + ADCS t0, acc0, acc0 + UMULH const1, hlp0, y0 + + MUL const2, hlp0, t0 + ADCS t0, acc1, acc1 + UMULH const2, hlp0, acc3 + + MUL const3, hlp0, t0 + ADCS t0, acc2, acc2 + + UMULH const3, hlp0, hlp0 + ADC $0, acc7 + + ADDS t1, acc0, acc0 + ADCS y0, acc1, acc1 + ADCS acc3, acc2, acc2 + ADC $0, hlp0, acc3 + + ADDS acc4, acc0, acc0 + ADCS acc5, acc1, acc1 + ADCS acc6, acc2, acc2 + ADCS acc7, acc3, acc3 + ADC $0, ZR, acc4 + + SUBS const0, acc0, y0 + SBCS const1, acc1, y1 + SBCS const2, acc2, y2 + SBCS const3, acc3, y3 + SBCS $0, acc4, acc4 + + CSEL CS, y0, acc0, x0 + CSEL CS, y1, acc1, x1 + CSEL CS, y2, acc2, x2 + CSEL CS, y3, acc3, x3 + + CBNZ b_ptr, ordSqrLoop + + MOVD res+0(FP), res_ptr + STP (x0, x1), 0*16(res_ptr) + STP (x2, x3), 1*16(res_ptr) + + RET +/* ---------------------------------------*/ +// func p256OrdMul(res, in1, in2 []uint64) +TEXT ·p256OrdMul(SB),NOSPLIT,$0 + MOVD in1+24(FP), a_ptr + MOVD in2+48(FP), b_ptr + + MOVD p256ordK0<>(SB), hlp1 + LDP p256ord<>+0x00(SB), (const0, const1) + LDP p256ord<>+0x10(SB), (const2, const3) + + LDP 0*16(a_ptr), (x0, x1) + LDP 1*16(a_ptr), (x2, x3) + LDP 0*16(b_ptr), (y0, y1) + LDP 1*16(b_ptr), (y2, y3) + + // y[0] * x + MUL y0, x0, acc0 + UMULH y0, x0, acc1 + + MUL y0, x1, t0 + ADDS t0, acc1 + UMULH y0, x1, acc2 + + MUL y0, x2, t0 + ADCS t0, acc2 + UMULH y0, x2, acc3 + + MUL y0, x3, t0 + ADCS t0, acc3 + UMULH y0, x3, acc4 + ADC $0, acc4 + // First reduction step + MUL acc0, hlp1, hlp0 + + MUL const0, hlp1, t0 + ADDS t0, acc0, acc0 + UMULH const0, hlp0, t1 + + MUL const1, hlp0, t0 + ADCS t0, acc1, acc1 + UMULH const1, hlp0, y0 + + MUL const2, hlp0, t0 + ADCS t0, acc2, acc2 + UMULH const2, hlp0, acc0 + + MUL const3, hlp0, t0 + ADCS t0, acc3, acc3 + + UMULH const3, hlp0, hlp0 + ADC $0, acc4 + + ADDS t1, acc1, acc1 + ADCS y0, acc2, acc2 + ADCS acc0, acc3, acc3 + ADC $0, hlp0, acc0 + // y[1] * x + MUL y1, x0, t0 + ADDS t0, acc1 + UMULH y1, x0, t1 + + MUL y1, x1, t0 + ADCS t0, acc2 + UMULH y1, x1, hlp0 + + MUL y1, x2, t0 + ADCS t0, acc3 + UMULH y1, x2, y0 + + MUL y1, x3, t0 + ADCS t0, acc4 + UMULH y1, x3, y1 + ADC $0, ZR, acc5 + + ADDS t1, acc2 + ADCS hlp0, acc3 + ADCS y0, acc4 + ADC y1, acc5 + // Second reduction step + MUL acc1, hlp1, hlp0 + + MUL const0, hlp1, t0 + ADDS t0, acc1, acc1 + UMULH const0, hlp0, t1 + + MUL const1, hlp0, t0 + ADCS t0, acc2, acc2 + UMULH const1, hlp0, y0 + + MUL const2, hlp0, t0 + ADCS t0, acc3, acc3 + UMULH const2, hlp0, acc1 + + MUL const3, hlp0, t0 + ADCS t0, acc0, acc0 + + UMULH const3, hlp0, hlp0 + ADC $0, acc5 + + ADDS t1, acc2, acc2 + ADCS y0, acc3, acc3 + ADCS acc1, acc0, acc0 + ADC $0, hlp0, acc1 + // y[2] * x + MUL y2, x0, t0 + ADDS t0, acc2 + UMULH y2, x0, t1 + + MUL y2, x1, t0 + ADCS t0, acc3 + UMULH y2, x1, hlp0 + + MUL y2, x2, t0 + ADCS t0, acc4 + UMULH y2, x2, y0 + + MUL y2, x3, t0 + ADCS t0, acc5 + UMULH y2, x3, y1 + ADC $0, ZR, acc6 + + ADDS t1, acc3 + ADCS hlp0, acc4 + ADCS y0, acc5 + ADC y1, acc6 + // Third reduction step + MUL acc2, hlp1, hlp0 + + MUL const0, hlp1, t0 + ADDS t0, acc2, acc2 + UMULH const0, hlp0, t1 + + MUL const1, hlp0, t0 + ADCS t0, acc3, acc3 + UMULH const1, hlp0, y0 + + MUL const2, hlp0, t0 + ADCS t0, acc0, acc0 + UMULH const2, hlp0, acc2 + + MUL const3, hlp0, t0 + ADCS t0, acc1, acc1 + + UMULH const3, hlp0, hlp0 + ADC $0, acc6 + + ADDS t1, acc3, acc3 + ADCS y0, acc0, acc0 + ADCS acc2, acc1, acc1 + ADC $0, hlp0, acc2 + // y[3] * x + MUL y3, x0, t0 + ADDS t0, acc3 + UMULH y3, x0, t1 + + MUL y3, x1, t0 + ADCS t0, acc4 + UMULH y3, x1, hlp0 + + MUL y3, x2, t0 + ADCS t0, acc5 + UMULH y3, x2, y0 + + MUL y3, x3, t0 + ADCS t0, acc6 + UMULH y3, x3, y1 + ADC $0, ZR, acc7 + + ADDS t1, acc4 + ADCS hlp0, acc5 + ADCS y0, acc6 + ADC y1, acc7 + // Last reduction step + MUL acc3, hlp1, hlp0 + + MUL const0, hlp1, t0 + ADDS t0, acc3, acc3 + UMULH const0, hlp0, t1 + + MUL const1, hlp0, t0 + ADCS t0, acc0, acc0 + UMULH const1, hlp0, y0 + + MUL const2, hlp0, t0 + ADCS t0, acc1, acc1 + UMULH const2, hlp0, acc3 + + MUL const3, hlp0, t0 + ADCS t0, acc2, acc2 + + UMULH const3, hlp0, hlp0 + ADC $0, acc7 + + ADDS t1, acc0, acc0 + ADCS y0, acc1, acc1 + ADCS acc3, acc2, acc2 + ADC $0, hlp0, acc3 + + ADDS acc4, acc0, acc0 + ADCS acc5, acc1, acc1 + ADCS acc6, acc2, acc2 + ADCS acc7, acc3, acc3 + ADC $0, ZR, acc4 + + SUBS const0, acc0, t0 + SBCS const1, acc1, t1 + SBCS const2, acc2, t2 + SBCS const3, acc3, t3 + SBCS $0, acc4, acc4 + + CSEL CS, t0, acc0, acc0 + CSEL CS, t1, acc1, acc1 + CSEL CS, t2, acc2, acc2 + CSEL CS, t3, acc3, acc3 + + MOVD res+0(FP), res_ptr + STP (acc0, acc1), 0*16(res_ptr) + STP (acc2, acc3), 1*16(res_ptr) + + RET +/* ---------------------------------------*/ +TEXT p256SubInternal<>(SB),NOSPLIT,$0 + SUBS x0, y0, acc0 + SBCS x1, y1, acc1 + SBCS x2, y2, acc2 + SBCS x3, y3, acc3 + SBC $0, ZR, t0 + + ADDS $-1, acc0, acc4 + ADCS const0, acc1, acc5 + ADCS $0, acc2, acc6 + ADC const1, acc3, acc7 + + ANDS $1, t0 + CSEL EQ, acc0, acc4, x0 + CSEL EQ, acc1, acc5, x1 + CSEL EQ, acc2, acc6, x2 + CSEL EQ, acc3, acc7, x3 + + RET +/* ---------------------------------------*/ +TEXT p256SqrInternal<>(SB),NOSPLIT,$0 + // x[1:] * x[0] + MUL x0, x1, acc1 + UMULH x0, x1, acc2 + + MUL x0, x2, t0 + ADDS t0, acc2, acc2 + UMULH x0, x2, acc3 + + MUL x0, x3, t0 + ADCS t0, acc3, acc3 + UMULH x0, x3, acc4 + ADC $0, acc4, acc4 + // x[2:] * x[1] + MUL x1, x2, t0 + ADDS t0, acc3 + UMULH x1, x2, t1 + ADCS t1, acc4 + ADC $0, ZR, acc5 + + MUL x1, x3, t0 + ADDS t0, acc4 + UMULH x1, x3, t1 + ADC t1, acc5 + // x[3] * x[2] + MUL x2, x3, t0 + ADDS t0, acc5 + UMULH x2, x3, acc6 + ADC $0, acc6 + + MOVD $0, acc7 + // *2 + ADDS acc1, acc1 + ADCS acc2, acc2 + ADCS acc3, acc3 + ADCS acc4, acc4 + ADCS acc5, acc5 + ADCS acc6, acc6 + ADC $0, acc7 + // Missing products + MUL x0, x0, acc0 + UMULH x0, x0, t0 + ADDS t0, acc1, acc1 + + MUL x1, x1, t0 + ADCS t0, acc2, acc2 + UMULH x1, x1, t1 + ADCS t1, acc3, acc3 + + MUL x2, x2, t0 + ADCS t0, acc4, acc4 + UMULH x2, x2, t1 + ADCS t1, acc5, acc5 + + MUL x3, x3, t0 + ADCS t0, acc6, acc6 + UMULH x3, x3, t1 + ADCS t1, acc7, acc7 + // First reduction step + ADDS acc0<<32, acc1, acc1 + LSR $32, acc0, t0 + MUL acc0, const1, t1 + UMULH acc0, const1, acc0 + ADCS t0, acc2, acc2 + ADCS t1, acc3, acc3 + ADC $0, acc0, acc0 + // Second reduction step + ADDS acc1<<32, acc2, acc2 + LSR $32, acc1, t0 + MUL acc1, const1, t1 + UMULH acc1, const1, acc1 + ADCS t0, acc3, acc3 + ADCS t1, acc0, acc0 + ADC $0, acc1, acc1 + // Third reduction step + ADDS acc2<<32, acc3, acc3 + LSR $32, acc2, t0 + MUL acc2, const1, t1 + UMULH acc2, const1, acc2 + ADCS t0, acc0, acc0 + ADCS t1, acc1, acc1 + ADC $0, acc2, acc2 + // Last reduction step + ADDS acc3<<32, acc0, acc0 + LSR $32, acc3, t0 + MUL acc3, const1, t1 + UMULH acc3, const1, acc3 + ADCS t0, acc1, acc1 + ADCS t1, acc2, acc2 + ADC $0, acc3, acc3 + // Add bits [511:256] of the sqr result + ADDS acc4, acc0, acc0 + ADCS acc5, acc1, acc1 + ADCS acc6, acc2, acc2 + ADCS acc7, acc3, acc3 + ADC $0, ZR, acc4 + + SUBS $-1, acc0, t0 + SBCS const0, acc1, t1 + SBCS $0, acc2, t2 + SBCS const1, acc3, t3 + SBCS $0, acc4, acc4 + + CSEL CS, t0, acc0, y0 + CSEL CS, t1, acc1, y1 + CSEL CS, t2, acc2, y2 + CSEL CS, t3, acc3, y3 + RET +/* ---------------------------------------*/ +TEXT p256MulInternal<>(SB),NOSPLIT,$0 + // y[0] * x + MUL y0, x0, acc0 + UMULH y0, x0, acc1 + + MUL y0, x1, t0 + ADDS t0, acc1 + UMULH y0, x1, acc2 + + MUL y0, x2, t0 + ADCS t0, acc2 + UMULH y0, x2, acc3 + + MUL y0, x3, t0 + ADCS t0, acc3 + UMULH y0, x3, acc4 + ADC $0, acc4 + // First reduction step + ADDS acc0<<32, acc1, acc1 + LSR $32, acc0, t0 + MUL acc0, const1, t1 + UMULH acc0, const1, acc0 + ADCS t0, acc2 + ADCS t1, acc3 + ADC $0, acc0 + // y[1] * x + MUL y1, x0, t0 + ADDS t0, acc1 + UMULH y1, x0, t1 + + MUL y1, x1, t0 + ADCS t0, acc2 + UMULH y1, x1, t2 + + MUL y1, x2, t0 + ADCS t0, acc3 + UMULH y1, x2, t3 + + MUL y1, x3, t0 + ADCS t0, acc4 + UMULH y1, x3, hlp0 + ADC $0, ZR, acc5 + + ADDS t1, acc2 + ADCS t2, acc3 + ADCS t3, acc4 + ADC hlp0, acc5 + // Second reduction step + ADDS acc1<<32, acc2, acc2 + LSR $32, acc1, t0 + MUL acc1, const1, t1 + UMULH acc1, const1, acc1 + ADCS t0, acc3 + ADCS t1, acc0 + ADC $0, acc1 + // y[2] * x + MUL y2, x0, t0 + ADDS t0, acc2 + UMULH y2, x0, t1 + + MUL y2, x1, t0 + ADCS t0, acc3 + UMULH y2, x1, t2 + + MUL y2, x2, t0 + ADCS t0, acc4 + UMULH y2, x2, t3 + + MUL y2, x3, t0 + ADCS t0, acc5 + UMULH y2, x3, hlp0 + ADC $0, ZR, acc6 + + ADDS t1, acc3 + ADCS t2, acc4 + ADCS t3, acc5 + ADC hlp0, acc6 + // Third reduction step + ADDS acc2<<32, acc3, acc3 + LSR $32, acc2, t0 + MUL acc2, const1, t1 + UMULH acc2, const1, acc2 + ADCS t0, acc0 + ADCS t1, acc1 + ADC $0, acc2 + // y[3] * x + MUL y3, x0, t0 + ADDS t0, acc3 + UMULH y3, x0, t1 + + MUL y3, x1, t0 + ADCS t0, acc4 + UMULH y3, x1, t2 + + MUL y3, x2, t0 + ADCS t0, acc5 + UMULH y3, x2, t3 + + MUL y3, x3, t0 + ADCS t0, acc6 + UMULH y3, x3, hlp0 + ADC $0, ZR, acc7 + + ADDS t1, acc4 + ADCS t2, acc5 + ADCS t3, acc6 + ADC hlp0, acc7 + // Last reduction step + ADDS acc3<<32, acc0, acc0 + LSR $32, acc3, t0 + MUL acc3, const1, t1 + UMULH acc3, const1, acc3 + ADCS t0, acc1 + ADCS t1, acc2 + ADC $0, acc3 + // Add bits [511:256] of the mul result + ADDS acc4, acc0, acc0 + ADCS acc5, acc1, acc1 + ADCS acc6, acc2, acc2 + ADCS acc7, acc3, acc3 + ADC $0, ZR, acc4 + + SUBS $-1, acc0, t0 + SBCS const0, acc1, t1 + SBCS $0, acc2, t2 + SBCS const1, acc3, t3 + SBCS $0, acc4, acc4 + + CSEL CS, t0, acc0, y0 + CSEL CS, t1, acc1, y1 + CSEL CS, t2, acc2, y2 + CSEL CS, t3, acc3, y3 + RET +/* ---------------------------------------*/ +#define p256MulBy2Inline \ + ADDS y0, y0, x0; \ + ADCS y1, y1, x1; \ + ADCS y2, y2, x2; \ + ADCS y3, y3, x3; \ + ADC $0, ZR, hlp0; \ + SUBS $-1, x0, t0; \ + SBCS const0, x1, t1;\ + SBCS $0, x2, t2; \ + SBCS const1, x3, t3;\ + SBCS $0, hlp0, hlp0;\ + CSEL CC, x0, t0, x0;\ + CSEL CC, x1, t1, x1;\ + CSEL CC, x2, t2, x2;\ + CSEL CC, x3, t3, x3; +/* ---------------------------------------*/ +#define x1in(off) (off)(a_ptr) +#define y1in(off) (off + 32)(a_ptr) +#define z1in(off) (off + 64)(a_ptr) +#define x2in(off) (off)(b_ptr) +#define z2in(off) (off + 64)(b_ptr) +#define x3out(off) (off)(res_ptr) +#define y3out(off) (off + 32)(res_ptr) +#define z3out(off) (off + 64)(res_ptr) +#define LDx(src) LDP src(0), (x0, x1); LDP src(16), (x2, x3) +#define LDy(src) LDP src(0), (y0, y1); LDP src(16), (y2, y3) +#define STx(src) STP (x0, x1), src(0); STP (x2, x3), src(16) +#define STy(src) STP (y0, y1), src(0); STP (y2, y3), src(16) +/* ---------------------------------------*/ +#define y2in(off) (32*0 + 8 + off)(RSP) +#define s2(off) (32*1 + 8 + off)(RSP) +#define z1sqr(off) (32*2 + 8 + off)(RSP) +#define h(off) (32*3 + 8 + off)(RSP) +#define r(off) (32*4 + 8 + off)(RSP) +#define hsqr(off) (32*5 + 8 + off)(RSP) +#define rsqr(off) (32*6 + 8 + off)(RSP) +#define hcub(off) (32*7 + 8 + off)(RSP) + +#define z2sqr(off) (32*8 + 8 + off)(RSP) +#define s1(off) (32*9 + 8 + off)(RSP) +#define u1(off) (32*10 + 8 + off)(RSP) +#define u2(off) (32*11 + 8 + off)(RSP) + +// func p256PointAddAffineAsm(res, in1, in2 []uint64, sign, sel, zero int) +TEXT ·p256PointAddAffineAsm(SB),0,$264-96 + MOVD in1+24(FP), a_ptr + MOVD in2+48(FP), b_ptr + MOVD sign+72(FP), hlp0 + MOVD sel+80(FP), hlp1 + MOVD zero+88(FP), t2 + + MOVD $1, t0 + CMP $0, t2 + CSEL EQ, ZR, t0, t2 + CMP $0, hlp1 + CSEL EQ, ZR, t0, hlp1 + + MOVD p256const0<>(SB), const0 + MOVD p256const1<>(SB), const1 + EOR t2<<1, hlp1 + + // Negate y2in based on sign + LDP 2*16(b_ptr), (y0, y1) + LDP 3*16(b_ptr), (y2, y3) + MOVD $-1, acc0 + + SUBS y0, acc0, acc0 + SBCS y1, const0, acc1 + SBCS y2, ZR, acc2 + SBCS y3, const1, acc3 + SBC $0, ZR, t0 + + ADDS $-1, acc0, acc4 + ADCS const0, acc1, acc5 + ADCS $0, acc2, acc6 + ADCS const1, acc3, acc7 + ADC $0, t0, t0 + + CMP $0, t0 + CSEL EQ, acc4, acc0, acc0 + CSEL EQ, acc5, acc1, acc1 + CSEL EQ, acc6, acc2, acc2 + CSEL EQ, acc7, acc3, acc3 + // If condition is 0, keep original value + CMP $0, hlp0 + CSEL EQ, y0, acc0, y0 + CSEL EQ, y1, acc1, y1 + CSEL EQ, y2, acc2, y2 + CSEL EQ, y3, acc3, y3 + // Store result + STy(y2in) + // Begin point add + LDx(z1in) + CALL p256SqrInternal<>(SB) // z1ˆ2 + STy(z1sqr) + + LDx(x2in) + CALL p256MulInternal<>(SB) // x2 * z1ˆ2 + + LDx(x1in) + CALL p256SubInternal<>(SB) // h = u2 - u1 + STx(h) + + LDy(z1in) + CALL p256MulInternal<>(SB) // z3 = h * z1 + + LDP 4*16(a_ptr), (acc0, acc1)// iff select[0] == 0, z3 = z1 + LDP 5*16(a_ptr), (acc2, acc3) + ANDS $1, hlp1, ZR + CSEL EQ, acc0, y0, y0 + CSEL EQ, acc1, y1, y1 + CSEL EQ, acc2, y2, y2 + CSEL EQ, acc3, y3, y3 + LDP p256one<>+0x00(SB), (acc0, acc1) + LDP p256one<>+0x10(SB), (acc2, acc3) + ANDS $2, hlp1, ZR // iff select[1] == 0, z3 = 1 + CSEL EQ, acc0, y0, y0 + CSEL EQ, acc1, y1, y1 + CSEL EQ, acc2, y2, y2 + CSEL EQ, acc3, y3, y3 + LDx(z1in) + MOVD res+0(FP), t0 + STP (y0, y1), 4*16(t0) + STP (y2, y3), 5*16(t0) + + LDy(z1sqr) + CALL p256MulInternal<>(SB) // z1 ^ 3 + + LDx(y2in) + CALL p256MulInternal<>(SB) // s2 = y2 * z1ˆ3 + STy(s2) + + LDx(y1in) + CALL p256SubInternal<>(SB) // r = s2 - s1 + STx(r) + + CALL p256SqrInternal<>(SB) // rsqr = rˆ2 + STy (rsqr) + + LDx(h) + CALL p256SqrInternal<>(SB) // hsqr = hˆ2 + STy(hsqr) + + CALL p256MulInternal<>(SB) // hcub = hˆ3 + STy(hcub) + + LDx(y1in) + CALL p256MulInternal<>(SB) // y1 * hˆ3 + STy(s2) + + LDP hsqr(0*8), (x0, x1) + LDP hsqr(2*8), (x2, x3) + LDP 0*16(a_ptr), (y0, y1) + LDP 1*16(a_ptr), (y2, y3) + CALL p256MulInternal<>(SB) // u1 * hˆ2 + STP (y0, y1), h(0*8) + STP (y2, y3), h(2*8) + + p256MulBy2Inline // u1 * hˆ2 * 2, inline + + LDy(rsqr) + CALL p256SubInternal<>(SB) // rˆ2 - u1 * hˆ2 * 2 + + MOVD x0, y0 + MOVD x1, y1 + MOVD x2, y2 + MOVD x3, y3 + LDx(hcub) + CALL p256SubInternal<>(SB) + + LDP 0*16(a_ptr), (acc0, acc1) + LDP 1*16(a_ptr), (acc2, acc3) + ANDS $1, hlp1, ZR // iff select[0] == 0, x3 = x1 + CSEL EQ, acc0, x0, x0 + CSEL EQ, acc1, x1, x1 + CSEL EQ, acc2, x2, x2 + CSEL EQ, acc3, x3, x3 + LDP 0*16(b_ptr), (acc0, acc1) + LDP 1*16(b_ptr), (acc2, acc3) + ANDS $2, hlp1, ZR // iff select[1] == 0, x3 = x2 + CSEL EQ, acc0, x0, x0 + CSEL EQ, acc1, x1, x1 + CSEL EQ, acc2, x2, x2 + CSEL EQ, acc3, x3, x3 + MOVD res+0(FP), t0 + STP (x0, x1), 0*16(t0) + STP (x2, x3), 1*16(t0) + + LDP h(0*8), (y0, y1) + LDP h(2*8), (y2, y3) + CALL p256SubInternal<>(SB) + + LDP r(0*8), (y0, y1) + LDP r(2*8), (y2, y3) + CALL p256MulInternal<>(SB) + + LDP s2(0*8), (x0, x1) + LDP s2(2*8), (x2, x3) + CALL p256SubInternal<>(SB) + LDP 2*16(a_ptr), (acc0, acc1) + LDP 3*16(a_ptr), (acc2, acc3) + ANDS $1, hlp1, ZR // iff select[0] == 0, y3 = y1 + CSEL EQ, acc0, x0, x0 + CSEL EQ, acc1, x1, x1 + CSEL EQ, acc2, x2, x2 + CSEL EQ, acc3, x3, x3 + LDP y2in(0*8), (acc0, acc1) + LDP y2in(2*8), (acc2, acc3) + ANDS $2, hlp1, ZR // iff select[1] == 0, y3 = y2 + CSEL EQ, acc0, x0, x0 + CSEL EQ, acc1, x1, x1 + CSEL EQ, acc2, x2, x2 + CSEL EQ, acc3, x3, x3 + MOVD res+0(FP), t0 + STP (x0, x1), 2*16(t0) + STP (x2, x3), 3*16(t0) + + RET + +#define p256AddInline \ + ADDS y0, x0, x0; \ + ADCS y1, x1, x1; \ + ADCS y2, x2, x2; \ + ADCS y3, x3, x3; \ + ADC $0, ZR, hlp0; \ + SUBS $-1, x0, t0; \ + SBCS const0, x1, t1;\ + SBCS $0, x2, t2; \ + SBCS const1, x3, t3;\ + SBCS $0, hlp0, hlp0;\ + CSEL CC, x0, t0, x0;\ + CSEL CC, x1, t1, x1;\ + CSEL CC, x2, t2, x2;\ + CSEL CC, x3, t3, x3; + +#define s(off) (32*0 + 8 + off)(RSP) +#define m(off) (32*1 + 8 + off)(RSP) +#define zsqr(off) (32*2 + 8 + off)(RSP) +#define tmp(off) (32*3 + 8 + off)(RSP) + +//func p256PointDoubleAsm(res, in []uint64) +TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$136-48 + MOVD res+0(FP), res_ptr + MOVD in+24(FP), a_ptr + + MOVD p256const0<>(SB), const0 + MOVD p256const1<>(SB), const1 + + // Begin point double + LDP 4*16(a_ptr), (x0, x1) + LDP 5*16(a_ptr), (x2, x3) + CALL p256SqrInternal<>(SB) + STP (y0, y1), zsqr(0*8) + STP (y2, y3), zsqr(2*8) + + LDP 0*16(a_ptr), (x0, x1) + LDP 1*16(a_ptr), (x2, x3) + p256AddInline + STx(m) + + LDx(z1in) + LDy(y1in) + CALL p256MulInternal<>(SB) + p256MulBy2Inline + STx(z3out) + + LDy(x1in) + LDx(zsqr) + CALL p256SubInternal<>(SB) + LDy(m) + CALL p256MulInternal<>(SB) + + // Multiply by 3 + p256MulBy2Inline + p256AddInline + STx(m) + + LDy(y1in) + p256MulBy2Inline + CALL p256SqrInternal<>(SB) + STy(s) + MOVD y0, x0 + MOVD y1, x1 + MOVD y2, x2 + MOVD y3, x3 + CALL p256SqrInternal<>(SB) + + // Divide by 2 + ADDS $-1, y0, t0 + ADCS const0, y1, t1 + ADCS $0, y2, t2 + ADCS const1, y3, t3 + ADC $0, ZR, hlp0 + + ANDS $1, y0, ZR + CSEL EQ, y0, t0, t0 + CSEL EQ, y1, t1, t1 + CSEL EQ, y2, t2, t2 + CSEL EQ, y3, t3, t3 + AND y0, hlp0, hlp0 + + EXTR $1, t0, t1, y0 + EXTR $1, t1, t2, y1 + EXTR $1, t2, t3, y2 + EXTR $1, t3, hlp0, y3 + STy(y3out) + + LDx(x1in) + LDy(s) + CALL p256MulInternal<>(SB) + STy(s) + p256MulBy2Inline + STx(tmp) + + LDx(m) + CALL p256SqrInternal<>(SB) + LDx(tmp) + CALL p256SubInternal<>(SB) + + STx(x3out) + + LDy(s) + CALL p256SubInternal<>(SB) + + LDy(m) + CALL p256MulInternal<>(SB) + + LDx(y3out) + CALL p256SubInternal<>(SB) + STx(y3out) + RET +/* ---------------------------------------*/ +#undef y2in +#undef x3out +#undef y3out +#undef z3out +#define y2in(off) (off + 32)(b_ptr) +#define x3out(off) (off)(b_ptr) +#define y3out(off) (off + 32)(b_ptr) +#define z3out(off) (off + 64)(b_ptr) +//func p256PointAddAsm(res, in1, in2 []uint64) int +TEXT ·p256PointAddAsm(SB),0,$392-80 + // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl + // Move input to stack in order to free registers + MOVD in1+24(FP), a_ptr + MOVD in2+48(FP), b_ptr + + MOVD p256const0<>(SB), const0 + MOVD p256const1<>(SB), const1 + + // Begin point add + LDx(z2in) + CALL p256SqrInternal<>(SB) // z2^2 + STy(z2sqr) + + CALL p256MulInternal<>(SB) // z2^3 + + LDx(y1in) + CALL p256MulInternal<>(SB) // s1 = z2ˆ3*y1 + STy(s1) + + LDx(z1in) + CALL p256SqrInternal<>(SB) // z1^2 + STy(z1sqr) + + CALL p256MulInternal<>(SB) // z1^3 + + LDx(y2in) + CALL p256MulInternal<>(SB) // s2 = z1ˆ3*y2 + + LDx(s1) + CALL p256SubInternal<>(SB) // r = s2 - s1 + STx(r) + + MOVD $1, t2 + ORR x0, x1, t0 // Check if zero mod p256 + ORR x2, x3, t1 + ORR t1, t0, t0 + CMP $0, t0 + CSEL EQ, t2, ZR, hlp1 + + EOR $-1, x0, t0 + EOR const0, x1, t1 + EOR const1, x3, t3 + + ORR t0, t1, t0 + ORR x2, t3, t1 + ORR t1, t0, t0 + CMP $0, t0 + CSEL EQ, t2, hlp1, hlp1 + + LDx(z2sqr) + LDy(x1in) + CALL p256MulInternal<>(SB) // u1 = x1 * z2ˆ2 + STy(u1) + + LDx(z1sqr) + LDy(x2in) + CALL p256MulInternal<>(SB) // u2 = x2 * z1ˆ2 + STy(u2) + + LDx(u1) + CALL p256SubInternal<>(SB) // h = u2 - u1 + STx(h) + + MOVD $1, t2 + ORR x0, x1, t0 // Check if zero mod p256 + ORR x2, x3, t1 + ORR t1, t0, t0 + CMP $0, t0 + CSEL EQ, t2, ZR, hlp0 + + EOR $-1, x0, t0 + EOR const0, x1, t1 + EOR const1, x3, t3 + + ORR t0, t1, t0 + ORR x2, t3, t1 + ORR t1, t0, t0 + CMP $0, t0 + CSEL EQ, t2, hlp0, hlp0 + + AND hlp0, hlp1, hlp1 + + LDx(r) + CALL p256SqrInternal<>(SB) // rsqr = rˆ2 + STy(rsqr) + + LDx(h) + CALL p256SqrInternal<>(SB) // hsqr = hˆ2 + STy(hsqr) + + LDx(h) + CALL p256MulInternal<>(SB) // hcub = hˆ3 + STy(hcub) + + LDx(s1) + CALL p256MulInternal<>(SB) + STy(s2) + + LDx(z1in) + LDy(z2in) + CALL p256MulInternal<>(SB) // z1 * z2 + LDx(h) + CALL p256MulInternal<>(SB) // z1 * z2 * h + MOVD res+0(FP), b_ptr + STy(z3out) + + LDx(hsqr) + LDy(u1) + CALL p256MulInternal<>(SB) // hˆ2 * u1 + STy(u2) + + p256MulBy2Inline // u1 * hˆ2 * 2, inline + LDy(rsqr) + CALL p256SubInternal<>(SB) // rˆ2 - u1 * hˆ2 * 2 + + MOVD x0, y0 + MOVD x1, y1 + MOVD x2, y2 + MOVD x3, y3 + LDx(hcub) + CALL p256SubInternal<>(SB) + STx(x3out) + + LDy(u2) + CALL p256SubInternal<>(SB) + + LDy(r) + CALL p256MulInternal<>(SB) + + LDx(s2) + CALL p256SubInternal<>(SB) + STx(y3out) + + MOVD hlp1, R0 + MOVD R0, ret+72(FP) + + RET diff --git a/src/crypto/elliptic/p256_asm_ppc64le.s b/src/crypto/elliptic/p256_asm_ppc64le.s new file mode 100644 index 0000000..69e96e2 --- /dev/null +++ b/src/crypto/elliptic/p256_asm_ppc64le.s @@ -0,0 +1,2494 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// This is a port of the s390x asm implementation. +// to ppc64le. + +// Some changes were needed due to differences in +// the Go opcodes and/or available instructions +// between s390x and ppc64le. + +// 1. There were operand order differences in the +// VSUBUQM, VSUBCUQ, and VSEL instructions. + +// 2. ppc64 does not have a multiply high and low +// like s390x, so those were implemented using +// macros to compute the equivalent values. + +// 3. The LVX, STVX instructions on ppc64 require +// 16 byte alignment of the data. To avoid that +// requirement, data is loaded using LXVD2X and +// STXVD2X with VPERM to reorder bytes correctly. + +// I have identified some areas where I believe +// changes would be needed to make this work for big +// endian; however additional changes beyond what I +// have noted are most likely needed to make it work. +// - The string used with VPERM to swap the byte order +// for loads and stores. +// - The EXTRACT_HI and EXTRACT_LO strings. +// - The constants that are loaded from CPOOL. +// + +// Permute string used by VPERM to reorder bytes +// loaded or stored using LXVD2X or STXVD2X +// on little endian. +DATA byteswap<>+0(SB)/8, $0x08090a0b0c0d0e0f +DATA byteswap<>+8(SB)/8, $0x0001020304050607 + +// The following constants are defined in an order +// that is correct for use with LXVD2X/STXVD2X +// on little endian. +DATA p256<>+0x00(SB)/8, $0xffffffff00000001 // P256 +DATA p256<>+0x08(SB)/8, $0x0000000000000000 // P256 +DATA p256<>+0x10(SB)/8, $0x00000000ffffffff // P256 +DATA p256<>+0x18(SB)/8, $0xffffffffffffffff // P256 +DATA p256<>+0x20(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256<>+0x28(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256<>+0x30(SB)/8, $0x0000000010111213 // SEL 0 d1 d0 0 +DATA p256<>+0x38(SB)/8, $0x1415161700000000 // SEL 0 d1 d0 0 +DATA p256<>+0x40(SB)/8, $0x18191a1b1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256<>+0x48(SB)/8, $0x18191a1b1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256mul<>+0x00(SB)/8, $0x00000000ffffffff // P256 original +DATA p256mul<>+0x08(SB)/8, $0xffffffffffffffff // P256 +DATA p256mul<>+0x10(SB)/8, $0xffffffff00000001 // P256 original +DATA p256mul<>+0x18(SB)/8, $0x0000000000000000 // P256 +DATA p256mul<>+0x20(SB)/8, $0x1c1d1e1f00000000 // SEL d0 0 0 d0 +DATA p256mul<>+0x28(SB)/8, $0x000000001c1d1e1f // SEL d0 0 0 d0 +DATA p256mul<>+0x30(SB)/8, $0x0001020304050607 // SEL d0 0 d1 d0 +DATA p256mul<>+0x38(SB)/8, $0x1c1d1e1f0c0d0e0f // SEL d0 0 d1 d0 +DATA p256mul<>+0x40(SB)/8, $0x040506071c1d1e1f // SEL 0 d1 d0 d1 +DATA p256mul<>+0x48(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL 0 d1 d0 d1 +DATA p256mul<>+0x50(SB)/8, $0x0405060704050607 // SEL 0 0 d1 d0 +DATA p256mul<>+0x58(SB)/8, $0x1c1d1e1f0c0d0e0f // SEL 0 0 d1 d0 +DATA p256mul<>+0x60(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256mul<>+0x68(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256mul<>+0x70(SB)/8, $0x141516170c0d0e0f // SEL 0 d1 d0 0 +DATA p256mul<>+0x78(SB)/8, $0x1c1d1e1f14151617 // SEL 0 d1 d0 0 +DATA p256mul<>+0x80(SB)/8, $0xffffffff00000000 // (1*2^256)%P256 +DATA p256mul<>+0x88(SB)/8, $0x0000000000000001 // (1*2^256)%P256 +DATA p256mul<>+0x90(SB)/8, $0x00000000fffffffe // (1*2^256)%P256 +DATA p256mul<>+0x98(SB)/8, $0xffffffffffffffff // (1*2^256)%P256 + +// The following are used with VPERM to extract the high and low +// values from the intermediate results of a vector multiply. +// They are used in the VMULTxxx macros. These have been tested +// only on little endian, I think they would have to be different +// for big endian. +DATA p256permhilo<>+0x00(SB)/8, $0x0405060714151617 // least significant +DATA p256permhilo<>+0x08(SB)/8, $0x0c0d0e0f1c1d1e1f +DATA p256permhilo<>+0x10(SB)/8, $0x0001020310111213 // most significant +DATA p256permhilo<>+0x18(SB)/8, $0x08090a0b18191A1B + +// External declarations for constants +GLOBL p256ord<>(SB), 8, $32 +GLOBL p256<>(SB), 8, $80 +GLOBL p256mul<>(SB), 8, $160 +GLOBL p256permhilo<>(SB), 8, $32 +GLOBL byteswap<>+0(SB), RODATA, $16 + +// The following macros are used to implement the ppc64le +// equivalent function from the corresponding s390x +// instruction for vector multiply high, low, and add, +// since there aren't exact equivalent instructions. +// The corresponding s390x instructions appear in the +// comments. +// Implementation for big endian would have to be +// investigated, I think it would be different. +// +// Vector multiply low word +// +// VMLF x0, x1, out_low +#define VMULT_LOW(x1, x2, out_low) \ + VMULUWM x1, x2, out_low + +// +// Vector multiply high word +// +// VMLHF x0, x1, out_hi +#define VMULT_HI(x1, x2, out_hi) \ + VMULEUW x1, x2, TMP1; \ + VMULOUW x1, x2, TMP2; \ + VPERM TMP1, TMP2, EXTRACT_HI, out_hi + +// +// Vector multiply word +// +// VMLF x0, x1, out_low +// VMLHF x0, x1, out_hi +#define VMULT(x1, x2, out_low, out_hi) \ + VMULEUW x1, x2, TMP1; \ + VMULOUW x1, x2, TMP2; \ + VPERM TMP1, TMP2, EXTRACT_LO, out_low; \ + VPERM TMP1, TMP2, EXTRACT_HI, out_hi + +// +// Vector multiply add word +// +// VMALF x0, x1, y, out_low +// VMALHF x0, x1, y, out_hi +#define VMULT_ADD(x1, x2, y, out_low, out_hi) \ + VSPLTISW $1, TMP1; \ + VMULEUW y, TMP1, TMP2; \ + VMULOUW y, TMP1, TMP1; \ + VMULEUW x1, x2, out_low; \ + VMULOUW x1, x2, out_hi; \ + VADDUDM TMP1, out_hi, TMP1; \ + VADDUDM TMP2, out_low, TMP2; \ + VPERM TMP2, TMP1, EXTRACT_LO, out_low; \ + VPERM TMP2, TMP1, EXTRACT_HI, out_hi + +// +// Vector multiply add high word +// +// VMALF x0, x1, y, out_low +// VMALHF x0, x1, y, out_hi +#define VMULT_ADD_HI(x1, x2, y, out_low, out_hi) \ + VSPLTISW $1, TMP1; \ + VMULOUW y, TMP1, TMP2; \ + VMULEUW y, TMP1, TMP1; \ + VMULEUW x1, x2, out_hi; \ + VMULOUW x1, x2, out_low; \ + VADDUDM TMP1, out_hi, TMP1; \ + VADDUDM TMP2, out_low, TMP2; \ + VPERM TMP2, TMP1, EXTRACT_HI, out_hi + +// +// Vector multiply add low word +// +// VMALF s0, x1, y, out_low +#define VMULT_ADD_LOW(x1, x2, y, out_low) \ + VMULUWM x1, x2, out_low; \ + VADDUWM out_low, y, out_low + +#define res_ptr R3 +#define a_ptr R4 + +#undef res_ptr +#undef a_ptr + +// func p256NegCond(val *p256Point, cond int) +#define P1ptr R3 +#define CPOOL R7 + +#define Y1L V0 +#define Y1L_ VS32 +#define Y1H V1 +#define Y1H_ VS33 +#define T1L V2 +#define T1L_ VS34 +#define T1H V3 +#define T1H_ VS35 + +#define SWAP V28 +#define SWAP_ VS60 + +#define PL V30 +#define PL_ VS62 +#define PH V31 +#define PH_ VS63 + +#define SEL1 V5 +#define SEL1_ VS37 +#define CAR1 V6 +// +// iff cond == 1 val <- -val +// +TEXT ·p256NegCond(SB), NOSPLIT, $0-16 + MOVD val+0(FP), P1ptr + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $40, R19 + + MOVD cond+8(FP), R6 + CMP $0, R6 + BC 12, 2, LR // just return if cond == 0 + + MOVD $p256mul<>+0x00(SB), CPOOL + + MOVD $byteswap<>+0x00(SB), R8 + LXVD2X (R8)(R0), SWAP_ + + LXVD2X (P1ptr)(R17), Y1L_ + LXVD2X (P1ptr)(R18), Y1H_ + + VPERM Y1H, Y1H, SWAP, Y1H + VPERM Y1L, Y1L, SWAP, Y1L + + LXVD2X (CPOOL)(R0), PL_ + LXVD2X (CPOOL)(R16), PH_ + + VSUBCUQ PL, Y1L, CAR1 // subtract part2 giving carry + VSUBUQM PL, Y1L, T1L // subtract part2 giving result + VSUBEUQM PH, Y1H, CAR1, T1H // subtract part1 using carry from part2 + + VPERM T1H, T1H, SWAP, T1H + VPERM T1L, T1L, SWAP, T1L + + STXVD2X T1L_, (R17+P1ptr) + STXVD2X T1H_, (R18+P1ptr) + RET + +#undef P1ptr +#undef CPOOL +#undef Y1L +#undef Y1L_ +#undef Y1H +#undef Y1H_ +#undef T1L +#undef T1L_ +#undef T1H +#undef T1H_ +#undef PL +#undef PL_ +#undef PH +#undef PH_ +#undef SEL1 +#undef SEL1_ +#undef CAR1 + +// +// if cond == 0 res <-b else res <-a +// +// func p256MovCond(res, a, b *p256Point, cond int) +#define P3ptr R3 +#define P1ptr R4 +#define P2ptr R5 + +#define FROMptr R7 +#define X1L V0 +#define X1H V1 +#define Y1L V2 +#define Y1H V3 +#define Z1L V4 +#define Z1H V5 +#define X1L_ VS32 +#define X1H_ VS33 +#define Y1L_ VS34 +#define Y1H_ VS35 +#define Z1L_ VS36 +#define Z1H_ VS37 + +// This function uses LXVD2X and STXVD2X to avoid the +// data alignment requirement for LVX, STVX. Since +// this code is just moving bytes and not doing arithmetic, +// order of the bytes doesn't matter. +// +TEXT ·p256MovCond(SB), NOSPLIT, $0-32 + MOVD res+0(FP), P3ptr + MOVD a+8(FP), P1ptr + MOVD b+16(FP), P2ptr + MOVD cond+24(FP), R6 + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $56, R21 + MOVD $64, R19 + MOVD $80, R20 + + // Check the condition + CMP $0, R6 + + // If 0, use b as the source + BEQ FROMB + + // Not 0, use a as the source + MOVD P1ptr, FROMptr + BR LOADVALS + +FROMB: + MOVD P2ptr, FROMptr + +LOADVALS: + // Load from a or b depending on the setting + // of FROMptr + LXVW4X (FROMptr+R0), X1H_ + LXVW4X (FROMptr+R16), X1L_ + LXVW4X (FROMptr+R17), Y1H_ + LXVW4X (FROMptr+R18), Y1L_ + LXVW4X (FROMptr+R19), Z1H_ + LXVW4X (FROMptr+R20), Z1L_ + + STXVW4X X1H_, (P3ptr+R0) + STXVW4X X1L_, (P3ptr+R16) + STXVW4X Y1H_, (P3ptr+R17) + STXVW4X Y1L_, (P3ptr+R18) + STXVW4X Z1H_, (P3ptr+R19) + STXVW4X Z1L_, (P3ptr+R20) + + RET + +#undef P3ptr +#undef P1ptr +#undef P2ptr +#undef FROMptr +#undef X1L +#undef X1H +#undef Y1L +#undef Y1H +#undef Z1L +#undef Z1H +#undef X1L_ +#undef X1H_ +#undef Y1L_ +#undef Y1H_ +#undef Z1L_ +#undef Z1H_ +// +// Select the point from the table for idx +// +// func p256Select(point *p256Point, table []p256Point, idx int) +#define P3ptr R3 +#define P1ptr R4 +#define COUNT R5 + +#define X1L V0 +#define X1H V1 +#define Y1L V2 +#define Y1H V3 +#define Z1L V4 +#define Z1H V5 +#define X1L_ VS32 +#define X1H_ VS33 +#define Y1L_ VS34 +#define Y1H_ VS35 +#define Z1L_ VS36 +#define Z1H_ VS37 +#define X2L V6 +#define X2H V7 +#define Y2L V8 +#define Y2H V9 +#define Z2L V10 +#define Z2H V11 +#define X2L_ VS38 +#define X2H_ VS39 +#define Y2L_ VS40 +#define Y2H_ VS41 +#define Z2L_ VS42 +#define Z2H_ VS43 + +#define ONE V18 +#define IDX V19 +#define SEL1 V20 +#define SEL1_ VS52 +#define SEL2 V21 +// +TEXT ·p256Select(SB), NOSPLIT, $0-40 + MOVD point+0(FP), P3ptr + MOVD table+8(FP), P1ptr + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $64, R19 + MOVD $80, R20 + + LXVDSX (R1)(R19), SEL1_ // VLREPG idx+32(FP), SEL1 + VSPLTB $7, SEL1, IDX // splat byte + VSPLTISB $1, ONE // VREPIB $1, ONE + VSPLTISB $1, SEL2 // VREPIB $1, SEL2 + MOVD $17, COUNT + MOVD COUNT, CTR // set up ctr + + VSPLTISB $0, X1H // VZERO X1H + VSPLTISB $0, X1L // VZERO X1L + VSPLTISB $0, Y1H // VZERO Y1H + VSPLTISB $0, Y1L // VZERO Y1L + VSPLTISB $0, Z1H // VZERO Z1H + VSPLTISB $0, Z1L // VZERO Z1L + +loop_select: + + // LVXD2X is used here since data alignment doesn't + // matter. + + LXVD2X (P1ptr+R0), X2H_ + LXVD2X (P1ptr+R16), X2L_ + LXVD2X (P1ptr+R17), Y2H_ + LXVD2X (P1ptr+R18), Y2L_ + LXVD2X (P1ptr+R19), Z2H_ + LXVD2X (P1ptr+R20), Z2L_ + + VCMPEQUD SEL2, IDX, SEL1 // VCEQG SEL2, IDX, SEL1 OK + + // This will result in SEL1 being all 0s or 1s, meaning + // the result is either X1L or X2L, no individual byte + // selection. + + VSEL X1L, X2L, SEL1, X1L + VSEL X1H, X2H, SEL1, X1H + VSEL Y1L, Y2L, SEL1, Y1L + VSEL Y1H, Y2H, SEL1, Y1H + VSEL Z1L, Z2L, SEL1, Z1L + VSEL Z1H, Z2H, SEL1, Z1H + + // Add 1 to all bytes in SEL2 + VADDUBM SEL2, ONE, SEL2 // VAB SEL2, ONE, SEL2 OK + ADD $96, P1ptr + BC 16, 0, loop_select + + // STXVD2X is used here so that alignment doesn't + // need to be verified. Since values were loaded + // using LXVD2X this is OK. + STXVD2X X1H_, (P3ptr+R0) + STXVD2X X1L_, (P3ptr+R16) + STXVD2X Y1H_, (P3ptr+R17) + STXVD2X Y1L_, (P3ptr+R18) + STXVD2X Z1H_, (P3ptr+R19) + STXVD2X Z1L_, (P3ptr+R20) + RET + +#undef P3ptr +#undef P1ptr +#undef COUNT +#undef X1L +#undef X1H +#undef Y1L +#undef Y1H +#undef Z1L +#undef Z1H +#undef X2L +#undef X2H +#undef Y2L +#undef Y2H +#undef Z2L +#undef Z2H +#undef X2L_ +#undef X2H_ +#undef Y2L_ +#undef Y2H_ +#undef Z2L_ +#undef Z2H_ +#undef ONE +#undef IDX +#undef SEL1 +#undef SEL1_ +#undef SEL2 + +// func p256SelectBase(point, table []uint64, idx int) +#define P3ptr R3 +#define P1ptr R4 +#define COUNT R5 + +#define X1L V0 +#define X1H V1 +#define Y1L V2 +#define Y1H V3 +#define Z1L V4 +#define Z1H V5 +#define X2L V6 +#define X2H V7 +#define Y2L V8 +#define Y2H V9 +#define Z2L V10 +#define Z2H V11 +#define X2L_ VS38 +#define X2H_ VS39 +#define Y2L_ VS40 +#define Y2H_ VS41 +#define Z2L_ VS42 +#define Z2H_ VS43 + +#define ONE V18 +#define IDX V19 +#define SEL1 V20 +#define SEL1_ VS52 +#define SEL2 V21 +TEXT ·p256SelectBase(SB), NOSPLIT, $0-40 + MOVD point+0(FP), P3ptr + MOVD table+8(FP), P1ptr + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $64, R19 + MOVD $80, R20 + MOVD $56, R21 + + LXVDSX (R1)(R19), SEL1_ + VSPLTB $7, SEL1, IDX // splat byte + + VSPLTISB $1, ONE // Vector with byte 1s + VSPLTISB $1, SEL2 // Vector with byte 1s + MOVD $65, COUNT + MOVD COUNT, CTR // loop count + + VSPLTISB $0, X1H // VZERO X1H + VSPLTISB $0, X1L // VZERO X1L + VSPLTISB $0, Y1H // VZERO Y1H + VSPLTISB $0, Y1L // VZERO Y1L + VSPLTISB $0, Z1H // VZERO Z1H + VSPLTISB $0, Z1L // VZERO Z1L + +loop_select: + LXVD2X (P1ptr+R0), X2H_ + LXVD2X (P1ptr+R16), X2L_ + LXVD2X (P1ptr+R17), Y2H_ + LXVD2X (P1ptr+R18), Y2L_ + LXVD2X (P1ptr+R19), Z2H_ + LXVD2X (P1ptr+R20), Z2L_ + + VCMPEQUD SEL2, IDX, SEL1 // Compare against idx + + VSEL X1L, X2L, SEL1, X1L // Select if idx matched + VSEL X1H, X2H, SEL1, X1H + VSEL Y1L, Y2L, SEL1, Y1L + VSEL Y1H, Y2H, SEL1, Y1H + VSEL Z1L, Z2L, SEL1, Z1L + VSEL Z1H, Z2H, SEL1, Z1H + + VADDUBM SEL2, ONE, SEL2 // Increment SEL2 bytes by 1 + ADD $96, P1ptr // Next chunk + BC 16, 0, loop_select + + STXVD2X X1H_, (P3ptr+R0) + STXVD2X X1L_, (P3ptr+R16) + STXVD2X Y1H_, (P3ptr+R17) + STXVD2X Y1L_, (P3ptr+R18) + STXVD2X Z1H_, (P3ptr+R19) + STXVD2X Z1L_, (P3ptr+R20) + RET + +#undef P3ptr +#undef P1ptr +#undef COUNT +#undef X1L +#undef X1H +#undef Y1L +#undef Y1H +#undef Z1L +#undef Z1H +#undef X2L +#undef X2H +#undef Y2L +#undef Y2H +#undef Z2L +#undef Z2H +#undef X1L_ +#undef X1H_ +#undef X2L_ +#undef X2H_ +#undef Y1L_ +#undef Y1H_ +#undef Y2L_ +#undef Y2H_ +#undef Z1L_ +#undef Z1H_ +#undef Z2L_ +#undef Z2H_ +#undef ONE +#undef IDX +#undef SEL1 +#undef SEL1_ +#undef SEL2 +#undef SWAP +#undef SWAP_ + +// --------------------------------------- +// func p256FromMont(res, in []byte) +#define res_ptr R3 +#define x_ptr R4 +#define CPOOL R7 + +#define T0 V0 +#define T0_ VS32 +#define T1 V1 +#define T1_ VS33 +#define T2 V2 +#define TT0 V3 +#define TT1 V4 +#define TT0_ VS35 +#define TT1_ VS36 + +#define ZER V6 +#define SEL1 V7 +#define SEL1_ VS39 +#define SEL2 V8 +#define SEL2_ VS40 +#define CAR1 V9 +#define CAR2 V10 +#define RED1 V11 +#define RED2 V12 +#define PL V13 +#define PL_ VS45 +#define PH V14 +#define PH_ VS46 +#define SWAP V28 +#define SWAP_ VS57 + +TEXT ·p256FromMont(SB), NOSPLIT, $0-48 + MOVD res+0(FP), res_ptr + MOVD in+24(FP), x_ptr + + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $64, R19 + MOVD $p256<>+0x00(SB), CPOOL + MOVD $byteswap<>+0x00(SB), R15 + + VSPLTISB $0, T2 // VZERO T2 + VSPLTISB $0, ZER // VZERO ZER + + // Constants are defined so that the LXVD2X is correct + LXVD2X (CPOOL+R0), PH_ + LXVD2X (CPOOL+R16), PL_ + + // VPERM byte selections + LXVD2X (CPOOL+R18), SEL2_ + LXVD2X (CPOOL+R19), SEL1_ + + LXVD2X (R15)(R0), SWAP_ + + LXVD2X (R16)(x_ptr), T1_ + LXVD2X (R0)(x_ptr), T0_ + + // Put in true little endian order + VPERM T0, T0, SWAP, T0 + VPERM T1, T1, SWAP, T1 + + // First round + VPERM T1, T0, SEL1, RED2 // d1 d0 d1 d0 + VPERM ZER, RED2, SEL2, RED1 // 0 d1 d0 0 + VSUBUQM RED2, RED1, RED2 // VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDOI $8, T1, T0, T0 // VSLDB $8, T1, T0, T0 + VSLDOI $8, T2, T1, T1 // VSLDB $8, T2, T1, T1 + + VADDCUQ T0, RED1, CAR1 // VACCQ T0, RED1, CAR1 + VADDUQM T0, RED1, T0 // VAQ T0, RED1, T0 + VADDECUQ T1, RED2, CAR1, CAR2 // VACCCQ T1, RED2, CAR1, CAR2 + VADDEUQM T1, RED2, CAR1, T1 // VACQ T1, RED2, CAR1, T1 + VADDUQM T2, CAR2, T2 // VAQ T2, CAR2, T2 + + // Second round + VPERM T1, T0, SEL1, RED2 // d1 d0 d1 d0 + VPERM ZER, RED2, SEL2, RED1 // 0 d1 d0 0 + VSUBUQM RED2, RED1, RED2 // VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDOI $8, T1, T0, T0 // VSLDB $8, T1, T0, T0 + VSLDOI $8, T2, T1, T1 // VSLDB $8, T2, T1, T1 + + VADDCUQ T0, RED1, CAR1 // VACCQ T0, RED1, CAR1 + VADDUQM T0, RED1, T0 // VAQ T0, RED1, T0 + VADDECUQ T1, RED2, CAR1, CAR2 // VACCCQ T1, RED2, CAR1, CAR2 + VADDEUQM T1, RED2, CAR1, T1 // VACQ T1, RED2, CAR1, T1 + VADDUQM T2, CAR2, T2 // VAQ T2, CAR2, T2 + + // Third round + VPERM T1, T0, SEL1, RED2 // d1 d0 d1 d0 + VPERM ZER, RED2, SEL2, RED1 // 0 d1 d0 0 + VSUBUQM RED2, RED1, RED2 // VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDOI $8, T1, T0, T0 // VSLDB $8, T1, T0, T0 + VSLDOI $8, T2, T1, T1 // VSLDB $8, T2, T1, T1 + + VADDCUQ T0, RED1, CAR1 // VACCQ T0, RED1, CAR1 + VADDUQM T0, RED1, T0 // VAQ T0, RED1, T0 + VADDECUQ T1, RED2, CAR1, CAR2 // VACCCQ T1, RED2, CAR1, CAR2 + VADDEUQM T1, RED2, CAR1, T1 // VACQ T1, RED2, CAR1, T1 + VADDUQM T2, CAR2, T2 // VAQ T2, CAR2, T2 + + // Last round + VPERM T1, T0, SEL1, RED2 // d1 d0 d1 d0 + VPERM ZER, RED2, SEL2, RED1 // 0 d1 d0 0 + VSUBUQM RED2, RED1, RED2 // VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDOI $8, T1, T0, T0 // VSLDB $8, T1, T0, T0 + VSLDOI $8, T2, T1, T1 // VSLDB $8, T2, T1, T1 + + VADDCUQ T0, RED1, CAR1 // VACCQ T0, RED1, CAR1 + VADDUQM T0, RED1, T0 // VAQ T0, RED1, T0 + VADDECUQ T1, RED2, CAR1, CAR2 // VACCCQ T1, RED2, CAR1, CAR2 + VADDEUQM T1, RED2, CAR1, T1 // VACQ T1, RED2, CAR1, T1 + VADDUQM T2, CAR2, T2 // VAQ T2, CAR2, T2 + + // --------------------------------------------------- + + VSUBCUQ T0, PL, CAR1 // VSCBIQ PL, T0, CAR1 + VSUBUQM T0, PL, TT0 // VSQ PL, T0, TT0 + VSUBECUQ T1, PH, CAR1, CAR2 // VSBCBIQ T1, PH, CAR1, CAR2 + VSUBEUQM T1, PH, CAR1, TT1 // VSBIQ T1, PH, CAR1, TT1 + VSUBEUQM T2, ZER, CAR2, T2 // VSBIQ T2, ZER, CAR2, T2 + + VSEL TT0, T0, T2, T0 + VSEL TT1, T1, T2, T1 + + // Reorder the bytes so STXVD2X can be used. + // TT0, TT1 used for VPERM result in case + // the caller expects T0, T1 to be good. + VPERM T0, T0, SWAP, TT0 + VPERM T1, T1, SWAP, TT1 + + STXVD2X TT0_, (R0)(res_ptr) + STXVD2X TT1_, (R16)(res_ptr) + RET + +#undef res_ptr +#undef x_ptr +#undef CPOOL +#undef T0 +#undef T0_ +#undef T1 +#undef T1_ +#undef T2 +#undef TT0 +#undef TT1 +#undef ZER +#undef SEL1 +#undef SEL1_ +#undef SEL2 +#undef SEL2_ +#undef CAR1 +#undef CAR2 +#undef RED1 +#undef RED2 +#undef PL +#undef PL_ +#undef PH +#undef PH_ +#undef SWAP +#undef SWAP_ + +// --------------------------------------- +// p256MulInternal +// V0-V3 V30,V31 - Not Modified +// V4-V15 V27-V29 - Volatile + +#define CPOOL R7 + +// Parameters +#define X0 V0 // Not modified +#define X1 V1 // Not modified +#define Y0 V2 // Not modified +#define Y1 V3 // Not modified +#define T0 V4 // Result +#define T1 V5 // Result +#define P0 V30 // Not modified +#define P1 V31 // Not modified + +// Temporaries: lots of reused vector regs +#define YDIG V6 // Overloaded with CAR2 +#define ADD1H V7 // Overloaded with ADD3H +#define ADD2H V8 // Overloaded with ADD4H +#define ADD3 V9 // Overloaded with SEL2,SEL5 +#define ADD4 V10 // Overloaded with SEL3,SEL6 +#define RED1 V11 // Overloaded with CAR2 +#define RED2 V12 +#define RED3 V13 // Overloaded with SEL1 +#define T2 V14 +// Overloaded temporaries +#define ADD1 V4 // Overloaded with T0 +#define ADD2 V5 // Overloaded with T1 +#define ADD3H V7 // Overloaded with ADD1H +#define ADD4H V8 // Overloaded with ADD2H +#define ZER V28 // Overloaded with TMP1 +#define CAR1 V6 // Overloaded with YDIG +#define CAR2 V11 // Overloaded with RED1 +// Constant Selects +#define SEL1 V13 // Overloaded with RED3 +#define SEL2 V9 // Overloaded with ADD3,SEL5 +#define SEL3 V10 // Overloaded with ADD4,SEL6 +#define SEL4 V6 // Overloaded with YDIG,CAR1 +#define SEL5 V9 // Overloaded with ADD3,SEL2 +#define SEL6 V10 // Overloaded with ADD4,SEL3 +#define SEL1_ VS45 +#define SEL2_ VS41 +#define SEL3_ VS42 +#define SEL4_ VS38 +#define SEL5_ VS41 +#define SEL6_ VS42 + +// TMP1, TMP2, EXTRACT_LO, EXTRACT_HI used in +// VMULT macros +#define TMP1 V13 // Overloaded with RED3 +#define TMP2 V27 +#define EVENODD R5 +#define EXTRACT_LO V28 +#define EXTRACT_LO_ VS60 +#define EXTRACT_HI V29 +#define EXTRACT_HI_ VS61 + +/* * + * To follow the flow of bits, for your own sanity a stiff drink, need you shall. + * Of a single round, a 'helpful' picture, here is. Meaning, column position has. + * With you, SIMD be... + * + * +--------+--------+ + * +--------| RED2 | RED1 | + * | +--------+--------+ + * | ---+--------+--------+ + * | +---- T2| T1 | T0 |--+ + * | | ---+--------+--------+ | + * | | | + * | | ======================= | + * | | | + * | | +--------+--------+<-+ + * | +-------| ADD2 | ADD1 |--|-----+ + * | | +--------+--------+ | | + * | | +--------+--------+<---+ | + * | | | ADD2H | ADD1H |--+ | + * | | +--------+--------+ | | + * | | +--------+--------+<-+ | + * | | | ADD4 | ADD3 |--|-+ | + * | | +--------+--------+ | | | + * | | +--------+--------+<---+ | | + * | | | ADD4H | ADD3H |------|-+ |(+vzero) + * | | +--------+--------+ | | V + * | | ------------------------ | | +--------+ + * | | | | | RED3 | [d0 0 0 d0] + * | | | | +--------+ + * | +---->+--------+--------+ | | | + * (T2[1w]||ADD2[4w]||ADD1[3w]) +--------| T1 | T0 | | | | + * | +--------+--------+ | | | + * +---->---+--------+--------+ | | | + * T2| T1 | T0 |----+ | | + * ---+--------+--------+ | | | + * ---+--------+--------+<---+ | | + * +--- T2| T1 | T0 |----------+ + * | ---+--------+--------+ | | + * | +--------+--------+<-------------+ + * | | RED2 | RED1 |-----+ | | [0 d1 d0 d1] [d0 0 d1 d0] + * | +--------+--------+ | | | + * | +--------+<----------------------+ + * | | RED3 |--------------+ | [0 0 d1 d0] + * | +--------+ | | + * +--->+--------+--------+ | | + * | T1 | T0 |--------+ + * +--------+--------+ | | + * --------------------------- | | + * | | + * +--------+--------+<----+ | + * | RED2 | RED1 | | + * +--------+--------+ | + * ---+--------+--------+<-------+ + * T2| T1 | T0 | (H1P-H1P-H00RRAY!) + * ---+--------+--------+ + * + * *Mi obra de arte de siglo XXI @vpaprots + * + * + * First group is special, doesn't get the two inputs: + * +--------+--------+<-+ + * +-------| ADD2 | ADD1 |--|-----+ + * | +--------+--------+ | | + * | +--------+--------+<---+ | + * | | ADD2H | ADD1H |--+ | + * | +--------+--------+ | | + * | +--------+--------+<-+ | + * | | ADD4 | ADD3 |--|-+ | + * | +--------+--------+ | | | + * | +--------+--------+<---+ | | + * | | ADD4H | ADD3H |------|-+ |(+vzero) + * | +--------+--------+ | | V + * | ------------------------ | | +--------+ + * | | | | RED3 | [d0 0 0 d0] + * | | | +--------+ + * +---->+--------+--------+ | | | + * (T2[1w]||ADD2[4w]||ADD1[3w]) | T1 | T0 |----+ | | + * +--------+--------+ | | | + * ---+--------+--------+<---+ | | + * +--- T2| T1 | T0 |----------+ + * | ---+--------+--------+ | | + * | +--------+--------+<-------------+ + * | | RED2 | RED1 |-----+ | | [0 d1 d0 d1] [d0 0 d1 d0] + * | +--------+--------+ | | | + * | +--------+<----------------------+ + * | | RED3 |--------------+ | [0 0 d1 d0] + * | +--------+ | | + * +--->+--------+--------+ | | + * | T1 | T0 |--------+ + * +--------+--------+ | | + * --------------------------- | | + * | | + * +--------+--------+<----+ | + * | RED2 | RED1 | | + * +--------+--------+ | + * ---+--------+--------+<-------+ + * T2| T1 | T0 | (H1P-H1P-H00RRAY!) + * ---+--------+--------+ + * + * Last 'group' needs to RED2||RED1 shifted less + */ +TEXT p256MulInternal<>(SB), NOSPLIT, $0-16 + // CPOOL loaded from caller + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $64, R19 + MOVD $80, R20 + MOVD $96, R21 + MOVD $112, R22 + + MOVD $p256permhilo<>+0x00(SB), EVENODD + + // These values are used by the VMULTxxx macros to + // extract the high and low portions of the intermediate + // result. + LXVD2X (R0)(EVENODD), EXTRACT_LO_ + LXVD2X (R16)(EVENODD), EXTRACT_HI_ + + // --------------------------------------------------- + + VSPLTW $3, Y0, YDIG // VREPF Y0 is input + + // VMLHF X0, YDIG, ADD1H + // VMLHF X1, YDIG, ADD2H + // VMLF X0, YDIG, ADD1 + // VMLF X1, YDIG, ADD2 + // + VMULT(X0, YDIG, ADD1, ADD1H) + VMULT(X1, YDIG, ADD2, ADD2H) + + VSPLTW $2, Y0, YDIG // VREPF + + // VMALF X0, YDIG, ADD1H, ADD3 + // VMALF X1, YDIG, ADD2H, ADD4 + // VMALHF X0, YDIG, ADD1H, ADD3H // ADD1H Free + // VMALHF X1, YDIG, ADD2H, ADD4H // ADD2H Free + VMULT_ADD(X0, YDIG, ADD1H, ADD3, ADD3H) + VMULT_ADD(X1, YDIG, ADD2H, ADD4, ADD4H) + + LXVD2X (R17)(CPOOL), SEL1_ + VSPLTISB $0, ZER // VZERO ZER + VPERM ZER, ADD1, SEL1, RED3 // [d0 0 0 d0] + + VSLDOI $12, ADD2, ADD1, T0 // ADD1 Free // VSLDB + VSLDOI $12, ZER, ADD2, T1 // ADD2 Free // VSLDB + + VADDCUQ T0, ADD3, CAR1 // VACCQ + VADDUQM T0, ADD3, T0 // ADD3 Free // VAQ + VADDECUQ T1, ADD4, CAR1, T2 // VACCCQ + VADDEUQM T1, ADD4, CAR1, T1 // ADD4 Free // VACQ + + LXVD2X (R18)(CPOOL), SEL2_ + LXVD2X (R19)(CPOOL), SEL3_ + LXVD2X (R20)(CPOOL), SEL4_ + VPERM RED3, T0, SEL2, RED1 // [d0 0 d1 d0] + VPERM RED3, T0, SEL3, RED2 // [ 0 d1 d0 d1] + VPERM RED3, T0, SEL4, RED3 // [ 0 0 d1 d0] + VSUBUQM RED2, RED3, RED2 // Guaranteed not to underflow -->? // VSQ + + VSLDOI $12, T1, T0, T0 // VSLDB + VSLDOI $12, T2, T1, T1 // VSLDB + + VADDCUQ T0, ADD3H, CAR1 // VACCQ + VADDUQM T0, ADD3H, T0 // VAQ + VADDECUQ T1, ADD4H, CAR1, T2 // VACCCQ + VADDEUQM T1, ADD4H, CAR1, T1 // VACQ + + // --------------------------------------------------- + + VSPLTW $1, Y0, YDIG // VREPF + LXVD2X (R0)(EVENODD), EXTRACT_LO_ + LXVD2X (R16)(EVENODD), EXTRACT_HI_ + + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + // VMALF X0, YDIG, T0, ADD1 // T0 Free->ADD1 + // VMALF X1, YDIG, T1, ADD2 // T1 Free->ADD2 + VMULT_ADD(X0, YDIG, T0, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ADD2, ADD2H) + + VSPLTW $0, Y0, YDIG // VREPF + + // VMALF X0, YDIG, ADD1H, ADD3 + // VMALF X1, YDIG, ADD2H, ADD4 + // VMALHF X0, YDIG, ADD1H, ADD3H // ADD1H Free->ADD3H + // VMALHF X1, YDIG, ADD2H, ADD4H // ADD2H Free->ADD4H , YDIG Free->ZER + VMULT_ADD(X0, YDIG, ADD1H, ADD3, ADD3H) + VMULT_ADD(X1, YDIG, ADD2H, ADD4, ADD4H) + + VSPLTISB $0, ZER // VZERO ZER + LXVD2X (R17)(CPOOL), SEL1_ + VPERM ZER, ADD1, SEL1, RED3 // [d0 0 0 d0] + + VSLDOI $12, ADD2, ADD1, T0 // ADD1 Free->T0 // VSLDB + VSLDOI $12, T2, ADD2, T1 // ADD2 Free->T1, T2 Free // VSLDB + + VADDCUQ T0, RED1, CAR1 // VACCQ + VADDUQM T0, RED1, T0 // VAQ + VADDECUQ T1, RED2, CAR1, T2 // VACCCQ + VADDEUQM T1, RED2, CAR1, T1 // VACQ + + VADDCUQ T0, ADD3, CAR1 // VACCQ + VADDUQM T0, ADD3, T0 // VAQ + VADDECUQ T1, ADD4, CAR1, CAR2 // VACCCQ + VADDEUQM T1, ADD4, CAR1, T1 // VACQ + VADDUQM T2, CAR2, T2 // VAQ + + LXVD2X (R18)(CPOOL), SEL2_ + LXVD2X (R19)(CPOOL), SEL3_ + LXVD2X (R20)(CPOOL), SEL4_ + VPERM RED3, T0, SEL2, RED1 // [d0 0 d1 d0] + VPERM RED3, T0, SEL3, RED2 // [ 0 d1 d0 d1] + VPERM RED3, T0, SEL4, RED3 // [ 0 0 d1 d0] + VSUBUQM RED2, RED3, RED2 // Guaranteed not to underflow // VSQ + + VSLDOI $12, T1, T0, T0 // VSLDB + VSLDOI $12, T2, T1, T1 // VSLDB + + VADDCUQ T0, ADD3H, CAR1 // VACCQ + VADDUQM T0, ADD3H, T0 // VAQ + VADDECUQ T1, ADD4H, CAR1, T2 // VACCCQ + VADDEUQM T1, ADD4H, CAR1, T1 // VACQ + + // --------------------------------------------------- + + VSPLTW $3, Y1, YDIG // VREPF + LXVD2X (R0)(EVENODD), EXTRACT_LO_ + LXVD2X (R16)(EVENODD), EXTRACT_HI_ + + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + VMULT_ADD(X0, YDIG, T0, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ADD2, ADD2H) + + VSPLTW $2, Y1, YDIG // VREPF + + // VMALF X0, YDIG, ADD1H, ADD3 + // VMALF X1, YDIG, ADD2H, ADD4 + // VMALHF X0, YDIG, ADD1H, ADD3H // ADD1H Free + // VMALHF X1, YDIG, ADD2H, ADD4H // ADD2H Free + VMULT_ADD(X0, YDIG, ADD1H, ADD3, ADD3H) + VMULT_ADD(X1, YDIG, ADD2H, ADD4, ADD4H) + + LXVD2X (R17)(CPOOL), SEL1_ + VSPLTISB $0, ZER // VZERO ZER + LXVD2X (R17)(CPOOL), SEL1_ + VPERM ZER, ADD1, SEL1, RED3 // [d0 0 0 d0] + + VSLDOI $12, ADD2, ADD1, T0 // ADD1 Free // VSLDB + VSLDOI $12, T2, ADD2, T1 // ADD2 Free // VSLDB + + VADDCUQ T0, RED1, CAR1 // VACCQ + VADDUQM T0, RED1, T0 // VAQ + VADDECUQ T1, RED2, CAR1, T2 // VACCCQ + VADDEUQM T1, RED2, CAR1, T1 // VACQ + + VADDCUQ T0, ADD3, CAR1 // VACCQ + VADDUQM T0, ADD3, T0 // VAQ + VADDECUQ T1, ADD4, CAR1, CAR2 // VACCCQ + VADDEUQM T1, ADD4, CAR1, T1 // VACQ + VADDUQM T2, CAR2, T2 // VAQ + + LXVD2X (R18)(CPOOL), SEL2_ + LXVD2X (R19)(CPOOL), SEL3_ + LXVD2X (R20)(CPOOL), SEL4_ + VPERM RED3, T0, SEL2, RED1 // [d0 0 d1 d0] + VPERM RED3, T0, SEL3, RED2 // [ 0 d1 d0 d1] + VPERM RED3, T0, SEL4, RED3 // [ 0 0 d1 d0] + VSUBUQM RED2, RED3, RED2 // Guaranteed not to underflow // VSQ + + VSLDOI $12, T1, T0, T0 // VSLDB + VSLDOI $12, T2, T1, T1 // VSLDB + + VADDCUQ T0, ADD3H, CAR1 // VACCQ + VADDUQM T0, ADD3H, T0 // VAQ + VADDECUQ T1, ADD4H, CAR1, T2 // VACCCQ + VADDEUQM T1, ADD4H, CAR1, T1 // VACQ + + // --------------------------------------------------- + + VSPLTW $1, Y1, YDIG // VREPF + LXVD2X (R0)(EVENODD), EXTRACT_LO_ + LXVD2X (R16)(EVENODD), EXTRACT_HI_ + + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + VMULT_ADD(X0, YDIG, T0, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ADD2, ADD2H) + + VSPLTW $0, Y1, YDIG // VREPF + + // VMALF X0, YDIG, ADD1H, ADD3 + // VMALF X1, YDIG, ADD2H, ADD4 + // VMALHF X0, YDIG, ADD1H, ADD3H + // VMALHF X1, YDIG, ADD2H, ADD4H + VMULT_ADD(X0, YDIG, ADD1H, ADD3, ADD3H) + VMULT_ADD(X1, YDIG, ADD2H, ADD4, ADD4H) + + VSPLTISB $0, ZER // VZERO ZER + LXVD2X (R17)(CPOOL), SEL1_ + VPERM ZER, ADD1, SEL1, RED3 // [d0 0 0 d0] + + VSLDOI $12, ADD2, ADD1, T0 // VSLDB + VSLDOI $12, T2, ADD2, T1 // VSLDB + + VADDCUQ T0, RED1, CAR1 // VACCQ + VADDUQM T0, RED1, T0 // VAQ + VADDECUQ T1, RED2, CAR1, T2 // VACCCQ + VADDEUQM T1, RED2, CAR1, T1 // VACQ + + VADDCUQ T0, ADD3, CAR1 // VACCQ + VADDUQM T0, ADD3, T0 // VAQ + VADDECUQ T1, ADD4, CAR1, CAR2 // VACCCQ + VADDEUQM T1, ADD4, CAR1, T1 // VACQ + VADDUQM T2, CAR2, T2 // VAQ + + LXVD2X (R21)(CPOOL), SEL5_ + LXVD2X (R22)(CPOOL), SEL6_ + VPERM T0, RED3, SEL5, RED2 // [d1 d0 d1 d0] + VPERM T0, RED3, SEL6, RED1 // [ 0 d1 d0 0] + VSUBUQM RED2, RED1, RED2 // Guaranteed not to underflow // VSQ + + VSLDOI $12, T1, T0, T0 // VSLDB + VSLDOI $12, T2, T1, T1 // VSLDB + + VADDCUQ T0, ADD3H, CAR1 // VACCQ + VADDUQM T0, ADD3H, T0 // VAQ + VADDECUQ T1, ADD4H, CAR1, T2 // VACCCQ + VADDEUQM T1, ADD4H, CAR1, T1 // VACQ + + VADDCUQ T0, RED1, CAR1 // VACCQ + VADDUQM T0, RED1, T0 // VAQ + VADDECUQ T1, RED2, CAR1, CAR2 // VACCCQ + VADDEUQM T1, RED2, CAR1, T1 // VACQ + VADDUQM T2, CAR2, T2 // VAQ + + // --------------------------------------------------- + + VSPLTISB $0, RED3 // VZERO RED3 + VSUBCUQ T0, P0, CAR1 // VSCBIQ + VSUBUQM T0, P0, ADD1H // VSQ + VSUBECUQ T1, P1, CAR1, CAR2 // VSBCBIQ + VSUBEUQM T1, P1, CAR1, ADD2H // VSBIQ + VSUBEUQM T2, RED3, CAR2, T2 // VSBIQ + + // what output to use, ADD2H||ADD1H or T1||T0? + VSEL ADD1H, T0, T2, T0 + VSEL ADD2H, T1, T2, T1 + RET + +#undef CPOOL + +#undef X0 +#undef X1 +#undef Y0 +#undef Y1 +#undef T0 +#undef T1 +#undef P0 +#undef P1 + +#undef SEL1 +#undef SEL2 +#undef SEL3 +#undef SEL4 +#undef SEL5 +#undef SEL6 +#undef SEL1_ +#undef SEL2_ +#undef SEL3_ +#undef SEL4_ +#undef SEL5_ +#undef SEL6_ + +#undef YDIG +#undef ADD1H +#undef ADD2H +#undef ADD3 +#undef ADD4 +#undef RED1 +#undef RED2 +#undef RED3 +#undef T2 +#undef ADD1 +#undef ADD2 +#undef ADD3H +#undef ADD4H +#undef ZER +#undef CAR1 +#undef CAR2 + +#undef TMP1 +#undef TMP2 +#undef EVENODD +#undef EXTRACT_HI +#undef EXTRACT_HI_ +#undef EXTRACT_LO +#undef EXTRACT_LO_ + +#define p256SubInternal(T1, T0, X1, X0, Y1, Y0) \ + VSPLTISB $0, ZER \ // VZERO + VSUBCUQ X0, Y0, CAR1 \ + VSUBUQM X0, Y0, T0 \ + VSUBECUQ X1, Y1, CAR1, SEL1 \ + VSUBEUQM X1, Y1, CAR1, T1 \ + VSUBUQM ZER, SEL1, SEL1 \ // VSQ + \ + VADDCUQ T0, PL, CAR1 \ // VACCQ + VADDUQM T0, PL, TT0 \ // VAQ + VADDEUQM T1, PH, CAR1, TT1 \ // VACQ + \ + VSEL TT0, T0, SEL1, T0 \ + VSEL TT1, T1, SEL1, T1 \ + +#define p256AddInternal(T1, T0, X1, X0, Y1, Y0) \ + VADDCUQ X0, Y0, CAR1 \ + VADDUQM X0, Y0, T0 \ + VADDECUQ X1, Y1, CAR1, T2 \ // VACCCQ + VADDEUQM X1, Y1, CAR1, T1 \ + \ + VSPLTISB $0, ZER \ + VSUBCUQ T0, PL, CAR1 \ // VSCBIQ + VSUBUQM T0, PL, TT0 \ + VSUBECUQ T1, PH, CAR1, CAR2 \ // VSBCBIQ + VSUBEUQM T1, PH, CAR1, TT1 \ // VSBIQ + VSUBEUQM T2, ZER, CAR2, SEL1 \ + \ + VSEL TT0, T0, SEL1, T0 \ + VSEL TT1, T1, SEL1, T1 + +#define p256HalfInternal(T1, T0, X1, X0) \ + VSPLTISB $0, ZER \ + VSUBEUQM ZER, ZER, X0, SEL1 \ + \ + VADDCUQ X0, PL, CAR1 \ + VADDUQM X0, PL, T0 \ + VADDECUQ X1, PH, CAR1, T2 \ + VADDEUQM X1, PH, CAR1, T1 \ + \ + VSEL T0, X0, SEL1, T0 \ + VSEL T1, X1, SEL1, T1 \ + VSEL T2, ZER, SEL1, T2 \ + \ + VSLDOI $15, T2, ZER, TT1 \ + VSLDOI $15, T1, ZER, TT0 \ + VSPLTISB $1, SEL1 \ + VSR T0, SEL1, T0 \ // VSRL + VSR T1, SEL1, T1 \ + VSPLTISB $7, SEL1 \ // VREPIB + VSL TT0, SEL1, TT0 \ + VSL TT1, SEL1, TT1 \ + VOR T0, TT0, T0 \ + VOR T1, TT1, T1 + +// --------------------------------------- +// func p256MulAsm(res, in1, in2 []byte) +#define res_ptr R3 +#define x_ptr R4 +#define y_ptr R5 +#define CPOOL R7 +#define TEMP R8 + +// Parameters +#define X0 V0 +#define X1 V1 +#define Y0 V2 +#define Y1 V3 +#define T0 V4 +#define T1 V5 +#define X0_ VS32 +#define X1_ VS33 +#define Y0_ VS34 +#define Y1_ VS35 +#define T0_ VS36 +#define T1_ VS37 +#define SWAP V28 +#define SWAP_ VS60 + +// Constants +#define P0 V30 +#define P1 V31 +#define P0_ VS62 +#define P1_ VS63 +// +// Montgomery multiplication modulo P256 +// +TEXT ·p256MulAsm(SB), NOSPLIT, $0-72 + MOVD res+0(FP), res_ptr + MOVD in1+24(FP), x_ptr + MOVD in2+48(FP), y_ptr + MOVD $16, R16 + MOVD $32, R17 + + MOVD $p256mul<>+0x00(SB), CPOOL + MOVD $byteswap<>+0x00(SB), R8 + + LXVD2X (R8)(R0), SWAP_ + + LXVD2X (R0)(x_ptr), X0_ + LXVD2X (R16)(x_ptr), X1_ + + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + + LXVD2X (R0)(y_ptr), Y0_ + LXVD2X (R16)(y_ptr), Y1_ + + VPERM Y0, Y0, SWAP, Y0 + VPERM Y1, Y1, SWAP, Y1 + + LXVD2X (R16)(CPOOL), P1_ + LXVD2X (R0)(CPOOL), P0_ + + CALL p256MulInternal<>(SB) + + MOVD $p256mul<>+0x00(SB), CPOOL + MOVD $byteswap<>+0x00(SB), R8 + + LXVD2X (R8)(R0), SWAP_ + + VPERM T0, T0, SWAP, T0 + VPERM T1, T1, SWAP, T1 + STXVD2X T0_, (R0)(res_ptr) + STXVD2X T1_, (R16)(res_ptr) + RET + +#undef res_ptr +#undef x_ptr +#undef y_ptr +#undef CPOOL + +#undef X0 +#undef X1 +#undef Y0 +#undef Y1 +#undef T0 +#undef T1 +#undef P0 +#undef P1 +#undef X0_ +#undef X1_ +#undef Y0_ +#undef Y1_ +#undef T0_ +#undef T1_ +#undef P0_ +#undef P1_ + +// Point add with P2 being affine point +// If sign == 1 -> P2 = -P2 +// If sel == 0 -> P3 = P1 +// if zero == 0 -> P3 = P2 +// p256PointAddAffineAsm(P3, P1, P2 *p256Point, sign, sel, zero int) +#define P3ptr R3 +#define P1ptr R4 +#define P2ptr R5 +#define CPOOL R7 + +// Temporaries in REGs +#define Y2L V15 +#define Y2H V16 +#define Y2L_ VS47 +#define Y2H_ VS48 +#define T1L V17 +#define T1H V18 +#define T2L V19 +#define T2H V20 +#define T3L V21 +#define T3H V22 +#define T4L V23 +#define T4H V24 + +// Temps for Sub and Add +#define TT0 V11 +#define TT1 V12 +#define T2 V13 + +// p256MulAsm Parameters +#define X0 V0 +#define X1 V1 +#define X0_ VS32 +#define X1_ VS33 +#define Y0 V2 +#define Y1 V3 +#define Y0_ VS34 +#define Y1_ VS35 +#define T0 V4 +#define T1 V5 + +#define PL V30 +#define PH V31 +#define PL_ VS62 +#define PH_ VS63 + +// Names for zero/sel selects +#define X1L V0 +#define X1H V1 +#define X1L_ VS32 +#define X1H_ VS33 +#define Y1L V2 // p256MulAsmParmY +#define Y1H V3 // p256MulAsmParmY +#define Y1L_ VS34 +#define Y1H_ VS35 +#define Z1L V4 +#define Z1H V5 +#define Z1L_ VS36 +#define Z1H_ VS37 +#define X2L V0 +#define X2H V1 +#define X2L_ VS32 +#define X2H_ VS33 +#define Z2L V4 +#define Z2H V5 +#define Z2L_ VS36 +#define Z2H_ VS37 +#define X3L V17 // T1L +#define X3H V18 // T1H +#define Y3L V21 // T3L +#define Y3H V22 // T3H +#define Z3L V25 +#define Z3H V26 +#define X3L_ VS49 +#define X3H_ VS50 +#define Y3L_ VS53 +#define Y3H_ VS54 +#define Z3L_ VS57 +#define Z3H_ VS58 + +#define ZER V6 +#define SEL1 V7 +#define SEL1_ VS39 +#define CAR1 V8 +#define CAR2 V9 +/* * + * Three operand formula: + * Source: 2004 Hankerson–Menezes–Vanstone, page 91. + * T1 = Z1² + * T2 = T1*Z1 + * T1 = T1*X2 + * T2 = T2*Y2 + * T1 = T1-X1 + * T2 = T2-Y1 + * Z3 = Z1*T1 + * T3 = T1² + * T4 = T3*T1 + * T3 = T3*X1 + * T1 = 2*T3 + * X3 = T2² + * X3 = X3-T1 + * X3 = X3-T4 + * T3 = T3-X3 + * T3 = T3*T2 + * T4 = T4*Y1 + * Y3 = T3-T4 + + * Three operand formulas, but with MulInternal X,Y used to store temps +X=Z1; Y=Z1; MUL;T- // T1 = Z1² T1 +X=T ; Y- ; MUL;T2=T // T2 = T1*Z1 T1 T2 +X- ; Y=X2; MUL;T1=T // T1 = T1*X2 T1 T2 +X=T2; Y=Y2; MUL;T- // T2 = T2*Y2 T1 T2 +SUB(T2+0x00(SB), CPOOL + + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $64, R19 + MOVD $80, R20 + MOVD $96, R21 + MOVD $112, R22 + MOVD $128, R23 + MOVD $144, R24 + MOVD $160, R25 + MOVD $104, R26 // offset of sign+24(FP) + + MOVD $byteswap<>+0+00(SB), R8 + LXVD2X (R16)(CPOOL), PH_ + LXVD2X (R0)(CPOOL), PL_ + + // if (sign == 1) { + // Y2 = fromBig(new(big.Int).Mod(new(big.Int).Sub(p256.P, new(big.Int).SetBytes(Y2)), p256.P)) // Y2 = P-Y2 + // } + + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R17)(P2ptr), Y2L_ + LXVD2X (R18)(P2ptr), Y2H_ + VPERM Y2H, Y2H, SWAP, Y2H + VPERM Y2L, Y2L, SWAP, Y2L + + // Equivalent of VLREPG sign+24(FP), SEL1 + LXVDSX (R1)(R26), SEL1_ + VSPLTISB $0, ZER + VCMPEQUD SEL1, ZER, SEL1 + + VSUBCUQ PL, Y2L, CAR1 + VSUBUQM PL, Y2L, T1L + VSUBEUQM PH, Y2H, CAR1, T1H + + VSEL T1L, Y2L, SEL1, Y2L + VSEL T1H, Y2H, SEL1, Y2H + +/* * + * Three operand formula: + * Source: 2004 Hankerson–Menezes–Vanstone, page 91. + */ + // X=Z1; Y=Z1; MUL; T- // T1 = Z1² T1 + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R19)(P1ptr), X0_ // Z1H + LXVD2X (R20)(P1ptr), X1_ // Z1L + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + VOR X0, X0, Y0 + VOR X1, X1, Y1 + CALL p256MulInternal<>(SB) + + // X=T ; Y- ; MUL; T2=T // T2 = T1*Z1 T1 T2 + VOR T0, T0, X0 + VOR T1, T1, X1 + CALL p256MulInternal<>(SB) + VOR T0, T0, T2L + VOR T1, T1, T2H + + // X- ; Y=X2; MUL; T1=T // T1 = T1*X2 T1 T2 + MOVD in2+16(FP), P2ptr + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R0)(P2ptr), Y0_ // X2H + LXVD2X (R16)(P2ptr), Y1_ // X2L + VPERM Y0, Y0, SWAP, Y0 + VPERM Y1, Y1, SWAP, Y1 + CALL p256MulInternal<>(SB) + VOR T0, T0, T1L + VOR T1, T1, T1H + + // X=T2; Y=Y2; MUL; T- // T2 = T2*Y2 T1 T2 + VOR T2L, T2L, X0 + VOR T2H, T2H, X1 + VOR Y2L, Y2L, Y0 + VOR Y2H, Y2H, Y1 + CALL p256MulInternal<>(SB) + + // SUB(T2(SB) + + VOR T0, T0, Z3L + VOR T1, T1, Z3H + + // X=Y; Y- ; MUL; X=T // T3 = T1*T1 T2 + VOR Y0, Y0, X0 + VOR Y1, Y1, X1 + CALL p256MulInternal<>(SB) + VOR T0, T0, X0 + VOR T1, T1, X1 + + // X- ; Y- ; MUL; T4=T // T4 = T3*T1 T2 T4 + CALL p256MulInternal<>(SB) + VOR T0, T0, T4L + VOR T1, T1, T4H + + // X- ; Y=X1; MUL; T3=T // T3 = T3*X1 T2 T3 T4 + MOVD in1+8(FP), P1ptr + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R0)(P1ptr), Y0_ // X1H + LXVD2X (R16)(P1ptr), Y1_ // X1L + VPERM Y1, Y1, SWAP, Y1 + VPERM Y0, Y0, SWAP, Y0 + CALL p256MulInternal<>(SB) + VOR T0, T0, T3L + VOR T1, T1, T3H + + // ADD(T1(SB) + + // SUB(T(SB) + VOR T0, T0, T3L + VOR T1, T1, T3H + + // X=T4; Y=Y1; MUL; T- // T4 = T4*Y1 T3 T4 + VOR T4L, T4L, X0 + VOR T4H, T4H, X1 + MOVD in1+8(FP), P1ptr + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R17)(P1ptr), Y0_ // Y1H + LXVD2X (R18)(P1ptr), Y1_ // Y1L + VPERM Y0, Y0, SWAP, Y0 + VPERM Y1, Y1, SWAP, Y1 + CALL p256MulInternal<>(SB) + + // SUB(T+0x00(SB), CPOOL + MOVD $byteswap<>+0x00(SB), R15 + + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $64, R19 + MOVD $80, R20 + + LXVD2X (R16)(CPOOL), PH_ + LXVD2X (R0)(CPOOL), PL_ + + LXVD2X (R15)(R0), SWAP_ + + // X=Z1; Y=Z1; MUL; T- // T1 = Z1² + LXVD2X (R19)(P1ptr), X0_ // Z1H + LXVD2X (R20)(P1ptr), X1_ // Z1L + + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + + VOR X0, X0, Y0 + VOR X1, X1, Y1 + CALL p256MulInternal<>(SB) + + // SUB(X(SB) + + // ADD(T2(SB) + + LXVD2X (R15)(R0), SWAP_ + + // Leave T0, T1 as is. + VPERM T0, T0, SWAP, TT0 + VPERM T1, T1, SWAP, TT1 + STXVD2X TT0_, (R19)(P3ptr) + STXVD2X TT1_, (R20)(P3ptr) + + // X- ; Y=X ; MUL; T- // Y3 = Y3² + VOR X0, X0, Y0 + VOR X1, X1, Y1 + CALL p256MulInternal<>(SB) + + // X=T ; Y=X1; MUL; T3=T // T3 = Y3*X1 + VOR T0, T0, X0 + VOR T1, T1, X1 + LXVD2X (R15)(R0), SWAP_ + LXVD2X (R0)(P1ptr), Y0_ + LXVD2X (R16)(P1ptr), Y1_ + VPERM Y0, Y0, SWAP, Y0 + VPERM Y1, Y1, SWAP, Y1 + CALL p256MulInternal<>(SB) + VOR T0, T0, T3L + VOR T1, T1, T3H + + // X- ; Y=X ; MUL; T- // Y3 = Y3² + VOR X0, X0, Y0 + VOR X1, X1, Y1 + CALL p256MulInternal<>(SB) + + // HAL(Y3(SB) + + // ADD(T1(SB) + + // SUB(Y3+0x00(SB), CPOOL + MOVD $16, R16 + MOVD $32, R17 + MOVD $48, R18 + MOVD $64, R19 + MOVD $80, R20 + + MOVD $byteswap<>+0x00(SB), R8 + LXVD2X (R16)(CPOOL), PH_ + LXVD2X (R0)(CPOOL), PL_ + + // X=Z1; Y=Z1; MUL; T- // T1 = Z1*Z1 + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R19)(P1ptr), X0_ // Z1L + LXVD2X (R20)(P1ptr), X1_ // Z1H + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + VOR X0, X0, Y0 + VOR X1, X1, Y1 + CALL p256MulInternal<>(SB) + + // X- ; Y=T ; MUL; R=T // R = Z1*T1 + VOR T0, T0, Y0 + VOR T1, T1, Y1 + CALL p256MulInternal<>(SB) + VOR T0, T0, RL // SAVE: RL + VOR T1, T1, RH // SAVE: RH + + STXVD2X RH_, (R1)(R17) // V27 has to be saved + + // X=X2; Y- ; MUL; H=T // H = X2*T1 + MOVD in2+16(FP), P2ptr + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R0)(P2ptr), X0_ // X2L + LXVD2X (R16)(P2ptr), X1_ // X2H + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + CALL p256MulInternal<>(SB) + VOR T0, T0, HL // SAVE: HL + VOR T1, T1, HH // SAVE: HH + + // X=Z2; Y=Z2; MUL; T- // T2 = Z2*Z2 + MOVD in2+16(FP), P2ptr + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R19)(P2ptr), X0_ // Z2L + LXVD2X (R20)(P2ptr), X1_ // Z2H + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + VOR X0, X0, Y0 + VOR X1, X1, Y1 + CALL p256MulInternal<>(SB) + + // X- ; Y=T ; MUL; S1=T // S1 = Z2*T2 + VOR T0, T0, Y0 + VOR T1, T1, Y1 + CALL p256MulInternal<>(SB) + VOR T0, T0, S1L // SAVE: S1L + VOR T1, T1, S1H // SAVE: S1H + + // X=X1; Y- ; MUL; U1=T // U1 = X1*T2 + MOVD in1+8(FP), P1ptr + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R0)(P1ptr), X0_ // X1L + LXVD2X (R16)(P1ptr), X1_ // X1H + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + CALL p256MulInternal<>(SB) + VOR T0, T0, U1L // SAVE: U1L + VOR T1, T1, U1H // SAVE: U1H + + // SUB(H+0x00(SB), R8 + MOVD in1+8(FP), P1ptr + MOVD in2+16(FP), P2ptr + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R19)(P1ptr), X0_ // Z1L + LXVD2X (R20)(P1ptr), X1_ // Z1H + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + LXVD2X (R19)(P2ptr), Y0_ // Z2L + LXVD2X (R20)(P2ptr), Y1_ // Z2H + VPERM Y0, Y0, SWAP, Y0 + VPERM Y1, Y1, SWAP, Y1 + CALL p256MulInternal<>(SB) + + // X=T ; Y=H ; MUL; Z3:=T// Z3 = Z3*H + VOR T0, T0, X0 + VOR T1, T1, X1 + VOR HL, HL, Y0 + VOR HH, HH, Y1 + CALL p256MulInternal<>(SB) + MOVD res+0(FP), P3ptr + LXVD2X (R8)(R0), SWAP_ + VPERM T1, T1, SWAP, TT1 + VPERM T0, T0, SWAP, TT0 + STXVD2X TT0_, (R19)(P3ptr) + STXVD2X TT1_, (R20)(P3ptr) + + // X=Y1; Y=S1; MUL; S1=T // S1 = Y1*S1 + MOVD in1+8(FP), P1ptr + LXVD2X (R17)(P1ptr), X0_ + LXVD2X (R18)(P1ptr), X1_ + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + VOR S1L, S1L, Y0 + VOR S1H, S1H, Y1 + CALL p256MulInternal<>(SB) + VOR T0, T0, S1L + VOR T1, T1, S1H + + // X=Y2; Y=R ; MUL; T- // R = Y2*R + MOVD in2+16(FP), P2ptr + LXVD2X (R8)(R0), SWAP_ + LXVD2X (R17)(P2ptr), X0_ + LXVD2X (R18)(P2ptr), X1_ + VPERM X0, X0, SWAP, X0 + VPERM X1, X1, SWAP, X1 + VOR RL, RL, Y0 + + // VOR RH, RH, Y1 RH was saved above in D2X format + LXVD2X (R1)(R17), Y1_ + CALL p256MulInternal<>(SB) + + // SUB(R(SB) + + // X- ; Y=T ; MUL; T2=T // T2 = H*T1 + VOR T0, T0, Y0 + VOR T1, T1, Y1 + CALL p256MulInternal<>(SB) + VOR T0, T0, T2L + VOR T1, T1, T2H + + // X=U1; Y- ; MUL; U1=T // U1 = U1*T1 + VOR U1L, U1L, X0 + VOR U1H, U1H, X1 + CALL p256MulInternal<>(SB) + VOR T0, T0, U1L + VOR T1, T1, U1H + + // X=R ; Y=R ; MUL; T- // X3 = R*R + VOR RL, RL, X0 + + // VOR RH, RH, X1 + VOR RL, RL, Y0 + + // RH was saved above using STXVD2X + LXVD2X (R1)(R17), X1_ + VOR X1, X1, Y1 + + // VOR RH, RH, Y1 + CALL p256MulInternal<>(SB) + + // SUB(T(SB) + VOR T0, T0, U1L + VOR T1, T1, U1H + + // X=S1; Y=T2; MUL; T- // T2 = S1*T2 + VOR S1L, S1L, X0 + VOR S1H, S1H, X1 + VOR T2L, T2L, Y0 + VOR T2H, T2H, Y1 + CALL p256MulInternal<>(SB) + + // SUB(T+0x00(SB)/4, $0xee00bc4f +DATA p256ord<>+0x00(SB)/8, $0xffffffff00000000 +DATA p256ord<>+0x08(SB)/8, $0xffffffffffffffff +DATA p256ord<>+0x10(SB)/8, $0xbce6faada7179e84 +DATA p256ord<>+0x18(SB)/8, $0xf3b9cac2fc632551 +DATA p256<>+0x00(SB)/8, $0xffffffff00000001 // P256 +DATA p256<>+0x08(SB)/8, $0x0000000000000000 // P256 +DATA p256<>+0x10(SB)/8, $0x00000000ffffffff // P256 +DATA p256<>+0x18(SB)/8, $0xffffffffffffffff // P256 +DATA p256<>+0x20(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256<>+0x28(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256<>+0x30(SB)/8, $0x0000000010111213 // SEL 0 d1 d0 0 +DATA p256<>+0x38(SB)/8, $0x1415161700000000 // SEL 0 d1 d0 0 +DATA p256<>+0x40(SB)/8, $0x18191a1b1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256<>+0x48(SB)/8, $0x18191a1b1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256mul<>+0x00(SB)/8, $0xffffffff00000001 // P256 +DATA p256mul<>+0x08(SB)/8, $0x0000000000000000 // P256 +DATA p256mul<>+0x10(SB)/8, $0x00000000ffffffff // P256 +DATA p256mul<>+0x18(SB)/8, $0xffffffffffffffff // P256 +DATA p256mul<>+0x20(SB)/8, $0x1c1d1e1f00000000 // SEL d0 0 0 d0 +DATA p256mul<>+0x28(SB)/8, $0x000000001c1d1e1f // SEL d0 0 0 d0 +DATA p256mul<>+0x30(SB)/8, $0x0001020304050607 // SEL d0 0 d1 d0 +DATA p256mul<>+0x38(SB)/8, $0x1c1d1e1f0c0d0e0f // SEL d0 0 d1 d0 +DATA p256mul<>+0x40(SB)/8, $0x040506071c1d1e1f // SEL 0 d1 d0 d1 +DATA p256mul<>+0x48(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL 0 d1 d0 d1 +DATA p256mul<>+0x50(SB)/8, $0x0405060704050607 // SEL 0 0 d1 d0 +DATA p256mul<>+0x58(SB)/8, $0x1c1d1e1f0c0d0e0f // SEL 0 0 d1 d0 +DATA p256mul<>+0x60(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256mul<>+0x68(SB)/8, $0x0c0d0e0f1c1d1e1f // SEL d1 d0 d1 d0 +DATA p256mul<>+0x70(SB)/8, $0x141516170c0d0e0f // SEL 0 d1 d0 0 +DATA p256mul<>+0x78(SB)/8, $0x1c1d1e1f14151617 // SEL 0 d1 d0 0 +DATA p256mul<>+0x80(SB)/8, $0x00000000fffffffe // (1*2^256)%P256 +DATA p256mul<>+0x88(SB)/8, $0xffffffffffffffff // (1*2^256)%P256 +DATA p256mul<>+0x90(SB)/8, $0xffffffff00000000 // (1*2^256)%P256 +DATA p256mul<>+0x98(SB)/8, $0x0000000000000001 // (1*2^256)%P256 +GLOBL p256ordK0<>(SB), 8, $4 +GLOBL p256ord<>(SB), 8, $32 +GLOBL p256<>(SB), 8, $80 +GLOBL p256mul<>(SB), 8, $160 + +DATA p256vmsl<>+0x0(SB)/8, $0x0012131415161718 +DATA p256vmsl<>+0x8(SB)/8, $0x00191a1b1c1d1e1f +DATA p256vmsl<>+0x10(SB)/8, $0x0012131415161718 +DATA p256vmsl<>+0x18(SB)/8, $0x000b0c0d0e0f1011 +DATA p256vmsl<>+0x20(SB)/8, $0x00191a1b1c1d1e1f +DATA p256vmsl<>+0x28(SB)/8, $0x0012131415161718 +DATA p256vmsl<>+0x30(SB)/8, $0x000b0c0d0e0f1011 +DATA p256vmsl<>+0x38(SB)/8, $0x0012131415161718 +DATA p256vmsl<>+0x40(SB)/8, $0x000405060708090a +DATA p256vmsl<>+0x48(SB)/8, $0x000b0c0d0e0f1011 +DATA p256vmsl<>+0x50(SB)/8, $0x000b0c0d0e0f1011 +DATA p256vmsl<>+0x58(SB)/8, $0x000405060708090a +DATA p256vmsl<>+0x60(SB)/8, $0x1010101000010203 +DATA p256vmsl<>+0x68(SB)/8, $0x100405060708090a +DATA p256vmsl<>+0x70(SB)/8, $0x100405060708090a +DATA p256vmsl<>+0x78(SB)/8, $0x1010101000010203 +GLOBL p256vmsl<>(SB), 8, $128 + +// --------------------------------------- +// iff cond == 1 val <- -val +// func p256NegCond(val *p256Point, cond int) +#define P1ptr R1 +#define CPOOL R4 + +#define Y1L V0 +#define Y1H V1 +#define T1L V2 +#define T1H V3 + +#define PL V30 +#define PH V31 + +#define ZER V4 +#define SEL1 V5 +#define CAR1 V6 +TEXT ·p256NegCond(SB), NOSPLIT, $0 + MOVD val+0(FP), P1ptr + + MOVD $p256mul<>+0x00(SB), CPOOL + VL 16(CPOOL), PL + VL 0(CPOOL), PH + + VL 32(P1ptr), Y1H + VL 48(P1ptr), Y1L + + VLREPG cond+8(FP), SEL1 + VZERO ZER + VCEQG SEL1, ZER, SEL1 + + VSCBIQ Y1L, PL, CAR1 + VSQ Y1L, PL, T1L + VSBIQ PH, Y1H, CAR1, T1H + + VSEL Y1L, T1L, SEL1, Y1L + VSEL Y1H, T1H, SEL1, Y1H + + VST Y1H, 32(P1ptr) + VST Y1L, 48(P1ptr) + RET + +#undef P1ptr +#undef CPOOL +#undef Y1L +#undef Y1H +#undef T1L +#undef T1H +#undef PL +#undef PH +#undef ZER +#undef SEL1 +#undef CAR1 + +// --------------------------------------- +// if cond == 0 res <- b; else res <- a +// func p256MovCond(res, a, b *p256Point, cond int) +#define P3ptr R1 +#define P1ptr R2 +#define P2ptr R3 + +#define X1L V0 +#define X1H V1 +#define Y1L V2 +#define Y1H V3 +#define Z1L V4 +#define Z1H V5 +#define X2L V6 +#define X2H V7 +#define Y2L V8 +#define Y2H V9 +#define Z2L V10 +#define Z2H V11 + +#define ZER V18 +#define SEL1 V19 +TEXT ·p256MovCond(SB), NOSPLIT, $0 + MOVD res+0(FP), P3ptr + MOVD a+8(FP), P1ptr + MOVD b+16(FP), P2ptr + VLREPG cond+24(FP), SEL1 + VZERO ZER + VCEQG SEL1, ZER, SEL1 + + VL 0(P1ptr), X1H + VL 16(P1ptr), X1L + VL 32(P1ptr), Y1H + VL 48(P1ptr), Y1L + VL 64(P1ptr), Z1H + VL 80(P1ptr), Z1L + + VL 0(P2ptr), X2H + VL 16(P2ptr), X2L + VL 32(P2ptr), Y2H + VL 48(P2ptr), Y2L + VL 64(P2ptr), Z2H + VL 80(P2ptr), Z2L + + VSEL X2L, X1L, SEL1, X1L + VSEL X2H, X1H, SEL1, X1H + VSEL Y2L, Y1L, SEL1, Y1L + VSEL Y2H, Y1H, SEL1, Y1H + VSEL Z2L, Z1L, SEL1, Z1L + VSEL Z2H, Z1H, SEL1, Z1H + + VST X1H, 0(P3ptr) + VST X1L, 16(P3ptr) + VST Y1H, 32(P3ptr) + VST Y1L, 48(P3ptr) + VST Z1H, 64(P3ptr) + VST Z1L, 80(P3ptr) + + RET + +#undef P3ptr +#undef P1ptr +#undef P2ptr +#undef X1L +#undef X1H +#undef Y1L +#undef Y1H +#undef Z1L +#undef Z1H +#undef X2L +#undef X2H +#undef Y2L +#undef Y2H +#undef Z2L +#undef Z2H +#undef ZER +#undef SEL1 + +// --------------------------------------- +// Constant time table access +// Indexed from 1 to 15, with -1 offset +// (index 0 is implicitly point at infinity) +// func p256Select(point *p256Point, table []p256Point, idx int) +#define P3ptr R1 +#define P1ptr R2 +#define COUNT R4 + +#define X1L V0 +#define X1H V1 +#define Y1L V2 +#define Y1H V3 +#define Z1L V4 +#define Z1H V5 +#define X2L V6 +#define X2H V7 +#define Y2L V8 +#define Y2H V9 +#define Z2L V10 +#define Z2H V11 + +#define ONE V18 +#define IDX V19 +#define SEL1 V20 +#define SEL2 V21 +TEXT ·p256Select(SB), NOSPLIT, $0 + MOVD point+0(FP), P3ptr + MOVD table+8(FP), P1ptr + VLREPB idx+(32+7)(FP), IDX + VREPIB $1, ONE + VREPIB $1, SEL2 + MOVD $1, COUNT + + VZERO X1H + VZERO X1L + VZERO Y1H + VZERO Y1L + VZERO Z1H + VZERO Z1L + +loop_select: + VL 0(P1ptr), X2H + VL 16(P1ptr), X2L + VL 32(P1ptr), Y2H + VL 48(P1ptr), Y2L + VL 64(P1ptr), Z2H + VL 80(P1ptr), Z2L + + VCEQG SEL2, IDX, SEL1 + + VSEL X2L, X1L, SEL1, X1L + VSEL X2H, X1H, SEL1, X1H + VSEL Y2L, Y1L, SEL1, Y1L + VSEL Y2H, Y1H, SEL1, Y1H + VSEL Z2L, Z1L, SEL1, Z1L + VSEL Z2H, Z1H, SEL1, Z1H + + VAB SEL2, ONE, SEL2 + ADDW $1, COUNT + ADD $96, P1ptr + CMPW COUNT, $17 + BLT loop_select + + VST X1H, 0(P3ptr) + VST X1L, 16(P3ptr) + VST Y1H, 32(P3ptr) + VST Y1L, 48(P3ptr) + VST Z1H, 64(P3ptr) + VST Z1L, 80(P3ptr) + RET + +#undef P3ptr +#undef P1ptr +#undef COUNT +#undef X1L +#undef X1H +#undef Y1L +#undef Y1H +#undef Z1L +#undef Z1H +#undef X2L +#undef X2H +#undef Y2L +#undef Y2H +#undef Z2L +#undef Z2H +#undef ONE +#undef IDX +#undef SEL1 +#undef SEL2 + +// --------------------------------------- +// Constant time table access +// Indexed from 1 to 15, with -1 offset +// (index 0 is implicitly point at infinity) +// func p256SelectBase(point *p256Point, table []p256Point, idx int) +#define P3ptr R1 +#define P1ptr R2 +#define COUNT R4 + +#define X1L V0 +#define X1H V1 +#define Y1L V2 +#define Y1H V3 +#define Z1L V4 +#define Z1H V5 +#define X2L V6 +#define X2H V7 +#define Y2L V8 +#define Y2H V9 +#define Z2L V10 +#define Z2H V11 + +#define ONE V18 +#define IDX V19 +#define SEL1 V20 +#define SEL2 V21 +TEXT ·p256SelectBase(SB), NOSPLIT, $0 + MOVD point+0(FP), P3ptr + MOVD table+8(FP), P1ptr + VLREPB idx+(32+7)(FP), IDX + VREPIB $1, ONE + VREPIB $1, SEL2 + MOVD $1, COUNT + + VZERO X1H + VZERO X1L + VZERO Y1H + VZERO Y1L + VZERO Z1H + VZERO Z1L + +loop_select: + VL 0(P1ptr), X2H + VL 16(P1ptr), X2L + VL 32(P1ptr), Y2H + VL 48(P1ptr), Y2L + VL 64(P1ptr), Z2H + VL 80(P1ptr), Z2L + + VCEQG SEL2, IDX, SEL1 + + VSEL X2L, X1L, SEL1, X1L + VSEL X2H, X1H, SEL1, X1H + VSEL Y2L, Y1L, SEL1, Y1L + VSEL Y2H, Y1H, SEL1, Y1H + VSEL Z2L, Z1L, SEL1, Z1L + VSEL Z2H, Z1H, SEL1, Z1H + + VAB SEL2, ONE, SEL2 + ADDW $1, COUNT + ADD $96, P1ptr + CMPW COUNT, $65 + BLT loop_select + + VST X1H, 0(P3ptr) + VST X1L, 16(P3ptr) + VST Y1H, 32(P3ptr) + VST Y1L, 48(P3ptr) + VST Z1H, 64(P3ptr) + VST Z1L, 80(P3ptr) + RET + +#undef P3ptr +#undef P1ptr +#undef COUNT +#undef X1L +#undef X1H +#undef Y1L +#undef Y1H +#undef Z1L +#undef Z1H +#undef X2L +#undef X2H +#undef Y2L +#undef Y2H +#undef Z2L +#undef Z2H +#undef ONE +#undef IDX +#undef SEL1 +#undef SEL2 + +// --------------------------------------- +// func p256FromMont(res, in []byte) +#define res_ptr R1 +#define x_ptr R2 +#define CPOOL R4 + +#define T0 V0 +#define T1 V1 +#define T2 V2 +#define TT0 V3 +#define TT1 V4 + +#define ZER V6 +#define SEL1 V7 +#define SEL2 V8 +#define CAR1 V9 +#define CAR2 V10 +#define RED1 V11 +#define RED2 V12 +#define PL V13 +#define PH V14 + +TEXT ·p256FromMont(SB), NOSPLIT, $0 + MOVD res+0(FP), res_ptr + MOVD in+24(FP), x_ptr + + VZERO T2 + VZERO ZER + MOVD $p256<>+0x00(SB), CPOOL + VL 16(CPOOL), PL + VL 0(CPOOL), PH + VL 48(CPOOL), SEL2 + VL 64(CPOOL), SEL1 + + VL (1*16)(x_ptr), T0 + VL (0*16)(x_ptr), T1 + + // First round + VPERM T1, T0, SEL1, RED2 // d1 d0 d1 d0 + VPERM ZER, RED2, SEL2, RED1 // 0 d1 d0 0 + VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDB $8, T1, T0, T0 + VSLDB $8, T2, T1, T1 + + VACCQ T0, RED1, CAR1 + VAQ T0, RED1, T0 + VACCCQ T1, RED2, CAR1, CAR2 + VACQ T1, RED2, CAR1, T1 + VAQ T2, CAR2, T2 + + // Second round + VPERM T1, T0, SEL1, RED2 // d1 d0 d1 d0 + VPERM ZER, RED2, SEL2, RED1 // 0 d1 d0 0 + VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDB $8, T1, T0, T0 + VSLDB $8, T2, T1, T1 + + VACCQ T0, RED1, CAR1 + VAQ T0, RED1, T0 + VACCCQ T1, RED2, CAR1, CAR2 + VACQ T1, RED2, CAR1, T1 + VAQ T2, CAR2, T2 + + // Third round + VPERM T1, T0, SEL1, RED2 // d1 d0 d1 d0 + VPERM ZER, RED2, SEL2, RED1 // 0 d1 d0 0 + VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDB $8, T1, T0, T0 + VSLDB $8, T2, T1, T1 + + VACCQ T0, RED1, CAR1 + VAQ T0, RED1, T0 + VACCCQ T1, RED2, CAR1, CAR2 + VACQ T1, RED2, CAR1, T1 + VAQ T2, CAR2, T2 + + // Last round + VPERM T1, T0, SEL1, RED2 // d1 d0 d1 d0 + VPERM ZER, RED2, SEL2, RED1 // 0 d1 d0 0 + VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDB $8, T1, T0, T0 + VSLDB $8, T2, T1, T1 + + VACCQ T0, RED1, CAR1 + VAQ T0, RED1, T0 + VACCCQ T1, RED2, CAR1, CAR2 + VACQ T1, RED2, CAR1, T1 + VAQ T2, CAR2, T2 + + // --------------------------------------------------- + + VSCBIQ PL, T0, CAR1 + VSQ PL, T0, TT0 + VSBCBIQ T1, PH, CAR1, CAR2 + VSBIQ T1, PH, CAR1, TT1 + VSBIQ T2, ZER, CAR2, T2 + + // what output to use, TT1||TT0 or T1||T0? + VSEL T0, TT0, T2, T0 + VSEL T1, TT1, T2, T1 + + VST T0, (1*16)(res_ptr) + VST T1, (0*16)(res_ptr) + RET + +#undef res_ptr +#undef x_ptr +#undef CPOOL +#undef T0 +#undef T1 +#undef T2 +#undef TT0 +#undef TT1 +#undef ZER +#undef SEL1 +#undef SEL2 +#undef CAR1 +#undef CAR2 +#undef RED1 +#undef RED2 +#undef PL +#undef PH + +// --------------------------------------- +// func p256OrdMul(res, in1, in2 []byte) +#define res_ptr R1 +#define x_ptr R2 +#define y_ptr R3 +#define X0 V0 +#define X1 V1 +#define Y0 V2 +#define Y1 V3 +#define M0 V4 +#define M1 V5 +#define T0 V6 +#define T1 V7 +#define T2 V8 +#define YDIG V9 + +#define ADD1 V16 +#define ADD1H V17 +#define ADD2 V18 +#define ADD2H V19 +#define RED1 V20 +#define RED1H V21 +#define RED2 V22 +#define RED2H V23 +#define CAR1 V24 +#define CAR1M V25 + +#define MK0 V30 +#define K0 V31 +TEXT ·p256OrdMul(SB), NOSPLIT, $0 + MOVD res+0(FP), res_ptr + MOVD in1+24(FP), x_ptr + MOVD in2+48(FP), y_ptr + + VZERO T2 + MOVD $p256ordK0<>+0x00(SB), R4 + + // VLEF $3, 0(R4), K0 + WORD $0xE7F40000 + BYTE $0x38 + BYTE $0x03 + MOVD $p256ord<>+0x00(SB), R4 + VL 16(R4), M0 + VL 0(R4), M1 + + VL (1*16)(x_ptr), X0 + VL (0*16)(x_ptr), X1 + VL (1*16)(y_ptr), Y0 + VL (0*16)(y_ptr), Y1 + + // ---------------------------------------------------------------------------/ + VREPF $3, Y0, YDIG + VMLF X0, YDIG, ADD1 + VMLF ADD1, K0, MK0 + VREPF $3, MK0, MK0 + + VMLF X1, YDIG, ADD2 + VMLHF X0, YDIG, ADD1H + VMLHF X1, YDIG, ADD2H + + VMALF M0, MK0, ADD1, RED1 + VMALHF M0, MK0, ADD1, RED1H + VMALF M1, MK0, ADD2, RED2 + VMALHF M1, MK0, ADD2, RED2H + + VSLDB $12, RED2, RED1, RED1 + VSLDB $12, T2, RED2, RED2 + + VACCQ RED1, ADD1H, CAR1 + VAQ RED1, ADD1H, T0 + VACCQ RED1H, T0, CAR1M + VAQ RED1H, T0, T0 + + // << ready for next MK0 + + VACQ RED2, ADD2H, CAR1, T1 + VACCCQ RED2, ADD2H, CAR1, CAR1 + VACCCQ RED2H, T1, CAR1M, T2 + VACQ RED2H, T1, CAR1M, T1 + VAQ CAR1, T2, T2 + + // --------------------------------------------------- +/* * + * ---+--------+--------+ + * T2| T1 | T0 | + * ---+--------+--------+ + * *(add)* + * +--------+--------+ + * | X1 | X0 | + * +--------+--------+ + * *(mul)* + * +--------+--------+ + * | YDIG | YDIG | + * +--------+--------+ + * *(add)* + * +--------+--------+ + * | M1 | M0 | + * +--------+--------+ + * *(mul)* + * +--------+--------+ + * | MK0 | MK0 | + * +--------+--------+ + * + * --------------------- + * + * +--------+--------+ + * | ADD2 | ADD1 | + * +--------+--------+ + * +--------+--------+ + * | ADD2H | ADD1H | + * +--------+--------+ + * +--------+--------+ + * | RED2 | RED1 | + * +--------+--------+ + * +--------+--------+ + * | RED2H | RED1H | + * +--------+--------+ + */ + VREPF $2, Y0, YDIG + VMALF X0, YDIG, T0, ADD1 + VMLF ADD1, K0, MK0 + VREPF $3, MK0, MK0 + + VMALF X1, YDIG, T1, ADD2 + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + + VMALF M0, MK0, ADD1, RED1 + VMALHF M0, MK0, ADD1, RED1H + VMALF M1, MK0, ADD2, RED2 + VMALHF M1, MK0, ADD2, RED2H + + VSLDB $12, RED2, RED1, RED1 + VSLDB $12, T2, RED2, RED2 + + VACCQ RED1, ADD1H, CAR1 + VAQ RED1, ADD1H, T0 + VACCQ RED1H, T0, CAR1M + VAQ RED1H, T0, T0 + + // << ready for next MK0 + + VACQ RED2, ADD2H, CAR1, T1 + VACCCQ RED2, ADD2H, CAR1, CAR1 + VACCCQ RED2H, T1, CAR1M, T2 + VACQ RED2H, T1, CAR1M, T1 + VAQ CAR1, T2, T2 + + // --------------------------------------------------- + VREPF $1, Y0, YDIG + VMALF X0, YDIG, T0, ADD1 + VMLF ADD1, K0, MK0 + VREPF $3, MK0, MK0 + + VMALF X1, YDIG, T1, ADD2 + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + + VMALF M0, MK0, ADD1, RED1 + VMALHF M0, MK0, ADD1, RED1H + VMALF M1, MK0, ADD2, RED2 + VMALHF M1, MK0, ADD2, RED2H + + VSLDB $12, RED2, RED1, RED1 + VSLDB $12, T2, RED2, RED2 + + VACCQ RED1, ADD1H, CAR1 + VAQ RED1, ADD1H, T0 + VACCQ RED1H, T0, CAR1M + VAQ RED1H, T0, T0 + + // << ready for next MK0 + + VACQ RED2, ADD2H, CAR1, T1 + VACCCQ RED2, ADD2H, CAR1, CAR1 + VACCCQ RED2H, T1, CAR1M, T2 + VACQ RED2H, T1, CAR1M, T1 + VAQ CAR1, T2, T2 + + // --------------------------------------------------- + VREPF $0, Y0, YDIG + VMALF X0, YDIG, T0, ADD1 + VMLF ADD1, K0, MK0 + VREPF $3, MK0, MK0 + + VMALF X1, YDIG, T1, ADD2 + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + + VMALF M0, MK0, ADD1, RED1 + VMALHF M0, MK0, ADD1, RED1H + VMALF M1, MK0, ADD2, RED2 + VMALHF M1, MK0, ADD2, RED2H + + VSLDB $12, RED2, RED1, RED1 + VSLDB $12, T2, RED2, RED2 + + VACCQ RED1, ADD1H, CAR1 + VAQ RED1, ADD1H, T0 + VACCQ RED1H, T0, CAR1M + VAQ RED1H, T0, T0 + + // << ready for next MK0 + + VACQ RED2, ADD2H, CAR1, T1 + VACCCQ RED2, ADD2H, CAR1, CAR1 + VACCCQ RED2H, T1, CAR1M, T2 + VACQ RED2H, T1, CAR1M, T1 + VAQ CAR1, T2, T2 + + // --------------------------------------------------- + VREPF $3, Y1, YDIG + VMALF X0, YDIG, T0, ADD1 + VMLF ADD1, K0, MK0 + VREPF $3, MK0, MK0 + + VMALF X1, YDIG, T1, ADD2 + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + + VMALF M0, MK0, ADD1, RED1 + VMALHF M0, MK0, ADD1, RED1H + VMALF M1, MK0, ADD2, RED2 + VMALHF M1, MK0, ADD2, RED2H + + VSLDB $12, RED2, RED1, RED1 + VSLDB $12, T2, RED2, RED2 + + VACCQ RED1, ADD1H, CAR1 + VAQ RED1, ADD1H, T0 + VACCQ RED1H, T0, CAR1M + VAQ RED1H, T0, T0 + + // << ready for next MK0 + + VACQ RED2, ADD2H, CAR1, T1 + VACCCQ RED2, ADD2H, CAR1, CAR1 + VACCCQ RED2H, T1, CAR1M, T2 + VACQ RED2H, T1, CAR1M, T1 + VAQ CAR1, T2, T2 + + // --------------------------------------------------- + VREPF $2, Y1, YDIG + VMALF X0, YDIG, T0, ADD1 + VMLF ADD1, K0, MK0 + VREPF $3, MK0, MK0 + + VMALF X1, YDIG, T1, ADD2 + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + + VMALF M0, MK0, ADD1, RED1 + VMALHF M0, MK0, ADD1, RED1H + VMALF M1, MK0, ADD2, RED2 + VMALHF M1, MK0, ADD2, RED2H + + VSLDB $12, RED2, RED1, RED1 + VSLDB $12, T2, RED2, RED2 + + VACCQ RED1, ADD1H, CAR1 + VAQ RED1, ADD1H, T0 + VACCQ RED1H, T0, CAR1M + VAQ RED1H, T0, T0 + + // << ready for next MK0 + + VACQ RED2, ADD2H, CAR1, T1 + VACCCQ RED2, ADD2H, CAR1, CAR1 + VACCCQ RED2H, T1, CAR1M, T2 + VACQ RED2H, T1, CAR1M, T1 + VAQ CAR1, T2, T2 + + // --------------------------------------------------- + VREPF $1, Y1, YDIG + VMALF X0, YDIG, T0, ADD1 + VMLF ADD1, K0, MK0 + VREPF $3, MK0, MK0 + + VMALF X1, YDIG, T1, ADD2 + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + + VMALF M0, MK0, ADD1, RED1 + VMALHF M0, MK0, ADD1, RED1H + VMALF M1, MK0, ADD2, RED2 + VMALHF M1, MK0, ADD2, RED2H + + VSLDB $12, RED2, RED1, RED1 + VSLDB $12, T2, RED2, RED2 + + VACCQ RED1, ADD1H, CAR1 + VAQ RED1, ADD1H, T0 + VACCQ RED1H, T0, CAR1M + VAQ RED1H, T0, T0 + + // << ready for next MK0 + + VACQ RED2, ADD2H, CAR1, T1 + VACCCQ RED2, ADD2H, CAR1, CAR1 + VACCCQ RED2H, T1, CAR1M, T2 + VACQ RED2H, T1, CAR1M, T1 + VAQ CAR1, T2, T2 + + // --------------------------------------------------- + VREPF $0, Y1, YDIG + VMALF X0, YDIG, T0, ADD1 + VMLF ADD1, K0, MK0 + VREPF $3, MK0, MK0 + + VMALF X1, YDIG, T1, ADD2 + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + + VMALF M0, MK0, ADD1, RED1 + VMALHF M0, MK0, ADD1, RED1H + VMALF M1, MK0, ADD2, RED2 + VMALHF M1, MK0, ADD2, RED2H + + VSLDB $12, RED2, RED1, RED1 + VSLDB $12, T2, RED2, RED2 + + VACCQ RED1, ADD1H, CAR1 + VAQ RED1, ADD1H, T0 + VACCQ RED1H, T0, CAR1M + VAQ RED1H, T0, T0 + + // << ready for next MK0 + + VACQ RED2, ADD2H, CAR1, T1 + VACCCQ RED2, ADD2H, CAR1, CAR1 + VACCCQ RED2H, T1, CAR1M, T2 + VACQ RED2H, T1, CAR1M, T1 + VAQ CAR1, T2, T2 + + // --------------------------------------------------- + + VZERO RED1 + VSCBIQ M0, T0, CAR1 + VSQ M0, T0, ADD1 + VSBCBIQ T1, M1, CAR1, CAR1M + VSBIQ T1, M1, CAR1, ADD2 + VSBIQ T2, RED1, CAR1M, T2 + + // what output to use, ADD2||ADD1 or T1||T0? + VSEL T0, ADD1, T2, T0 + VSEL T1, ADD2, T2, T1 + + VST T0, (1*16)(res_ptr) + VST T1, (0*16)(res_ptr) + RET + +#undef res_ptr +#undef x_ptr +#undef y_ptr +#undef X0 +#undef X1 +#undef Y0 +#undef Y1 +#undef M0 +#undef M1 +#undef T0 +#undef T1 +#undef T2 +#undef YDIG + +#undef ADD1 +#undef ADD1H +#undef ADD2 +#undef ADD2H +#undef RED1 +#undef RED1H +#undef RED2 +#undef RED2H +#undef CAR1 +#undef CAR1M + +#undef MK0 +#undef K0 + +// --------------------------------------- +// p256MulInternalVX +// V0-V3,V30,V31 - Not Modified +// V4-V15 - Volatile + +#define CPOOL R4 + +// Parameters +#define X0 V0 // Not modified +#define X1 V1 // Not modified +#define Y0 V2 // Not modified +#define Y1 V3 // Not modified +#define T0 V4 +#define T1 V5 +#define P0 V30 // Not modified +#define P1 V31 // Not modified + +// Temporaries +#define YDIG V6 // Overloaded with CAR2, ZER +#define ADD1H V7 // Overloaded with ADD3H +#define ADD2H V8 // Overloaded with ADD4H +#define ADD3 V9 // Overloaded with SEL2,SEL5 +#define ADD4 V10 // Overloaded with SEL3,SEL6 +#define RED1 V11 // Overloaded with CAR2 +#define RED2 V12 +#define RED3 V13 // Overloaded with SEL1 +#define T2 V14 +// Overloaded temporaries +#define ADD1 V4 // Overloaded with T0 +#define ADD2 V5 // Overloaded with T1 +#define ADD3H V7 // Overloaded with ADD1H +#define ADD4H V8 // Overloaded with ADD2H +#define ZER V6 // Overloaded with YDIG, CAR2 +#define CAR1 V6 // Overloaded with YDIG, ZER +#define CAR2 V11 // Overloaded with RED1 +// Constant Selects +#define SEL1 V13 // Overloaded with RED3 +#define SEL2 V9 // Overloaded with ADD3,SEL5 +#define SEL3 V10 // Overloaded with ADD4,SEL6 +#define SEL4 V6 // Overloaded with YDIG,CAR2,ZER +#define SEL5 V9 // Overloaded with ADD3,SEL2 +#define SEL6 V10 // Overloaded with ADD4,SEL3 + +/* * + * To follow the flow of bits, for your own sanity a stiff drink, need you shall. + * Of a single round, a 'helpful' picture, here is. Meaning, column position has. + * With you, SIMD be... + * + * +--------+--------+ + * +--------| RED2 | RED1 | + * | +--------+--------+ + * | ---+--------+--------+ + * | +---- T2| T1 | T0 |--+ + * | | ---+--------+--------+ | + * | | | + * | | ======================= | + * | | | + * | | +--------+--------+<-+ + * | +-------| ADD2 | ADD1 |--|-----+ + * | | +--------+--------+ | | + * | | +--------+--------+<---+ | + * | | | ADD2H | ADD1H |--+ | + * | | +--------+--------+ | | + * | | +--------+--------+<-+ | + * | | | ADD4 | ADD3 |--|-+ | + * | | +--------+--------+ | | | + * | | +--------+--------+<---+ | | + * | | | ADD4H | ADD3H |------|-+ |(+vzero) + * | | +--------+--------+ | | V + * | | ------------------------ | | +--------+ + * | | | | | RED3 | [d0 0 0 d0] + * | | | | +--------+ + * | +---->+--------+--------+ | | | + * (T2[1w]||ADD2[4w]||ADD1[3w]) +--------| T1 | T0 | | | | + * | +--------+--------+ | | | + * +---->---+--------+--------+ | | | + * T2| T1 | T0 |----+ | | + * ---+--------+--------+ | | | + * ---+--------+--------+<---+ | | + * +--- T2| T1 | T0 |----------+ + * | ---+--------+--------+ | | + * | +--------+--------+<-------------+ + * | | RED2 | RED1 |-----+ | | [0 d1 d0 d1] [d0 0 d1 d0] + * | +--------+--------+ | | | + * | +--------+<----------------------+ + * | | RED3 |--------------+ | [0 0 d1 d0] + * | +--------+ | | + * +--->+--------+--------+ | | + * | T1 | T0 |--------+ + * +--------+--------+ | | + * --------------------------- | | + * | | + * +--------+--------+<----+ | + * | RED2 | RED1 | | + * +--------+--------+ | + * ---+--------+--------+<-------+ + * T2| T1 | T0 | (H1P-H1P-H00RRAY!) + * ---+--------+--------+ + * + * *Mi obra de arte de siglo XXI @vpaprots + * + * + * First group is special, doesn't get the two inputs: + * +--------+--------+<-+ + * +-------| ADD2 | ADD1 |--|-----+ + * | +--------+--------+ | | + * | +--------+--------+<---+ | + * | | ADD2H | ADD1H |--+ | + * | +--------+--------+ | | + * | +--------+--------+<-+ | + * | | ADD4 | ADD3 |--|-+ | + * | +--------+--------+ | | | + * | +--------+--------+<---+ | | + * | | ADD4H | ADD3H |------|-+ |(+vzero) + * | +--------+--------+ | | V + * | ------------------------ | | +--------+ + * | | | | RED3 | [d0 0 0 d0] + * | | | +--------+ + * +---->+--------+--------+ | | | + * (T2[1w]||ADD2[4w]||ADD1[3w]) | T1 | T0 |----+ | | + * +--------+--------+ | | | + * ---+--------+--------+<---+ | | + * +--- T2| T1 | T0 |----------+ + * | ---+--------+--------+ | | + * | +--------+--------+<-------------+ + * | | RED2 | RED1 |-----+ | | [0 d1 d0 d1] [d0 0 d1 d0] + * | +--------+--------+ | | | + * | +--------+<----------------------+ + * | | RED3 |--------------+ | [0 0 d1 d0] + * | +--------+ | | + * +--->+--------+--------+ | | + * | T1 | T0 |--------+ + * +--------+--------+ | | + * --------------------------- | | + * | | + * +--------+--------+<----+ | + * | RED2 | RED1 | | + * +--------+--------+ | + * ---+--------+--------+<-------+ + * T2| T1 | T0 | (H1P-H1P-H00RRAY!) + * ---+--------+--------+ + * + * Last 'group' needs to RED2||RED1 shifted less + */ +TEXT ·p256MulInternalVX(SB), NOSPLIT, $0-0 + VL 32(CPOOL), SEL1 + VL 48(CPOOL), SEL2 + VL 64(CPOOL), SEL3 + VL 80(CPOOL), SEL4 + + // --------------------------------------------------- + + VREPF $3, Y0, YDIG + VMLHF X0, YDIG, ADD1H + VMLHF X1, YDIG, ADD2H + VMLF X0, YDIG, ADD1 + VMLF X1, YDIG, ADD2 + + VREPF $2, Y0, YDIG + VMALF X0, YDIG, ADD1H, ADD3 + VMALF X1, YDIG, ADD2H, ADD4 + VMALHF X0, YDIG, ADD1H, ADD3H // ADD1H Free + VMALHF X1, YDIG, ADD2H, ADD4H // ADD2H Free + + VZERO ZER + VL 32(CPOOL), SEL1 + VPERM ZER, ADD1, SEL1, RED3 // [d0 0 0 d0] + + VSLDB $12, ADD2, ADD1, T0 // ADD1 Free + VSLDB $12, ZER, ADD2, T1 // ADD2 Free + + VACCQ T0, ADD3, CAR1 + VAQ T0, ADD3, T0 // ADD3 Free + VACCCQ T1, ADD4, CAR1, T2 + VACQ T1, ADD4, CAR1, T1 // ADD4 Free + + VL 48(CPOOL), SEL2 + VL 64(CPOOL), SEL3 + VL 80(CPOOL), SEL4 + VPERM RED3, T0, SEL2, RED1 // [d0 0 d1 d0] + VPERM RED3, T0, SEL3, RED2 // [ 0 d1 d0 d1] + VPERM RED3, T0, SEL4, RED3 // [ 0 0 d1 d0] + VSQ RED3, RED2, RED2 // Guaranteed not to underflow + + VSLDB $12, T1, T0, T0 + VSLDB $12, T2, T1, T1 + + VACCQ T0, ADD3H, CAR1 + VAQ T0, ADD3H, T0 + VACCCQ T1, ADD4H, CAR1, T2 + VACQ T1, ADD4H, CAR1, T1 + + // --------------------------------------------------- + + VREPF $1, Y0, YDIG + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + VMALF X0, YDIG, T0, ADD1 // T0 Free->ADD1 + VMALF X1, YDIG, T1, ADD2 // T1 Free->ADD2 + + VREPF $0, Y0, YDIG + VMALF X0, YDIG, ADD1H, ADD3 + VMALF X1, YDIG, ADD2H, ADD4 + VMALHF X0, YDIG, ADD1H, ADD3H // ADD1H Free->ADD3H + VMALHF X1, YDIG, ADD2H, ADD4H // ADD2H Free->ADD4H , YDIG Free->ZER + + VZERO ZER + VL 32(CPOOL), SEL1 + VPERM ZER, ADD1, SEL1, RED3 // [d0 0 0 d0] + + VSLDB $12, ADD2, ADD1, T0 // ADD1 Free->T0 + VSLDB $12, T2, ADD2, T1 // ADD2 Free->T1, T2 Free + + VACCQ T0, RED1, CAR1 + VAQ T0, RED1, T0 + VACCCQ T1, RED2, CAR1, T2 + VACQ T1, RED2, CAR1, T1 + + VACCQ T0, ADD3, CAR1 + VAQ T0, ADD3, T0 + VACCCQ T1, ADD4, CAR1, CAR2 + VACQ T1, ADD4, CAR1, T1 + VAQ T2, CAR2, T2 + + VL 48(CPOOL), SEL2 + VL 64(CPOOL), SEL3 + VL 80(CPOOL), SEL4 + VPERM RED3, T0, SEL2, RED1 // [d0 0 d1 d0] + VPERM RED3, T0, SEL3, RED2 // [ 0 d1 d0 d1] + VPERM RED3, T0, SEL4, RED3 // [ 0 0 d1 d0] + VSQ RED3, RED2, RED2 // Guaranteed not to underflow + + VSLDB $12, T1, T0, T0 + VSLDB $12, T2, T1, T1 + + VACCQ T0, ADD3H, CAR1 + VAQ T0, ADD3H, T0 + VACCCQ T1, ADD4H, CAR1, T2 + VACQ T1, ADD4H, CAR1, T1 + + // --------------------------------------------------- + + VREPF $3, Y1, YDIG + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + VMALF X0, YDIG, T0, ADD1 + VMALF X1, YDIG, T1, ADD2 + + VREPF $2, Y1, YDIG + VMALF X0, YDIG, ADD1H, ADD3 + VMALF X1, YDIG, ADD2H, ADD4 + VMALHF X0, YDIG, ADD1H, ADD3H // ADD1H Free + VMALHF X1, YDIG, ADD2H, ADD4H // ADD2H Free + + VZERO ZER + VL 32(CPOOL), SEL1 + VPERM ZER, ADD1, SEL1, RED3 // [d0 0 0 d0] + + VSLDB $12, ADD2, ADD1, T0 // ADD1 Free + VSLDB $12, T2, ADD2, T1 // ADD2 Free + + VACCQ T0, RED1, CAR1 + VAQ T0, RED1, T0 + VACCCQ T1, RED2, CAR1, T2 + VACQ T1, RED2, CAR1, T1 + + VACCQ T0, ADD3, CAR1 + VAQ T0, ADD3, T0 + VACCCQ T1, ADD4, CAR1, CAR2 + VACQ T1, ADD4, CAR1, T1 + VAQ T2, CAR2, T2 + + VL 48(CPOOL), SEL2 + VL 64(CPOOL), SEL3 + VL 80(CPOOL), SEL4 + VPERM RED3, T0, SEL2, RED1 // [d0 0 d1 d0] + VPERM RED3, T0, SEL3, RED2 // [ 0 d1 d0 d1] + VPERM RED3, T0, SEL4, RED3 // [ 0 0 d1 d0] + VSQ RED3, RED2, RED2 // Guaranteed not to underflow + + VSLDB $12, T1, T0, T0 + VSLDB $12, T2, T1, T1 + + VACCQ T0, ADD3H, CAR1 + VAQ T0, ADD3H, T0 + VACCCQ T1, ADD4H, CAR1, T2 + VACQ T1, ADD4H, CAR1, T1 + + // --------------------------------------------------- + + VREPF $1, Y1, YDIG + VMALHF X0, YDIG, T0, ADD1H + VMALHF X1, YDIG, T1, ADD2H + VMALF X0, YDIG, T0, ADD1 + VMALF X1, YDIG, T1, ADD2 + + VREPF $0, Y1, YDIG + VMALF X0, YDIG, ADD1H, ADD3 + VMALF X1, YDIG, ADD2H, ADD4 + VMALHF X0, YDIG, ADD1H, ADD3H + VMALHF X1, YDIG, ADD2H, ADD4H + + VZERO ZER + VL 32(CPOOL), SEL1 + VPERM ZER, ADD1, SEL1, RED3 // [d0 0 0 d0] + + VSLDB $12, ADD2, ADD1, T0 + VSLDB $12, T2, ADD2, T1 + + VACCQ T0, RED1, CAR1 + VAQ T0, RED1, T0 + VACCCQ T1, RED2, CAR1, T2 + VACQ T1, RED2, CAR1, T1 + + VACCQ T0, ADD3, CAR1 + VAQ T0, ADD3, T0 + VACCCQ T1, ADD4, CAR1, CAR2 + VACQ T1, ADD4, CAR1, T1 + VAQ T2, CAR2, T2 + + VL 96(CPOOL), SEL5 + VL 112(CPOOL), SEL6 + VPERM T0, RED3, SEL5, RED2 // [d1 d0 d1 d0] + VPERM T0, RED3, SEL6, RED1 // [ 0 d1 d0 0] + VSQ RED1, RED2, RED2 // Guaranteed not to underflow + + VSLDB $12, T1, T0, T0 + VSLDB $12, T2, T1, T1 + + VACCQ T0, ADD3H, CAR1 + VAQ T0, ADD3H, T0 + VACCCQ T1, ADD4H, CAR1, T2 + VACQ T1, ADD4H, CAR1, T1 + + VACCQ T0, RED1, CAR1 + VAQ T0, RED1, T0 + VACCCQ T1, RED2, CAR1, CAR2 + VACQ T1, RED2, CAR1, T1 + VAQ T2, CAR2, T2 + + // --------------------------------------------------- + + VZERO RED3 + VSCBIQ P0, T0, CAR1 + VSQ P0, T0, ADD1H + VSBCBIQ T1, P1, CAR1, CAR2 + VSBIQ T1, P1, CAR1, ADD2H + VSBIQ T2, RED3, CAR2, T2 + + // what output to use, ADD2H||ADD1H or T1||T0? + VSEL T0, ADD1H, T2, T0 + VSEL T1, ADD2H, T2, T1 + RET + +#undef CPOOL + +#undef X0 +#undef X1 +#undef Y0 +#undef Y1 +#undef T0 +#undef T1 +#undef P0 +#undef P1 + +#undef SEL1 +#undef SEL2 +#undef SEL3 +#undef SEL4 +#undef SEL5 +#undef SEL6 + +#undef YDIG +#undef ADD1H +#undef ADD2H +#undef ADD3 +#undef ADD4 +#undef RED1 +#undef RED2 +#undef RED3 +#undef T2 +#undef ADD1 +#undef ADD2 +#undef ADD3H +#undef ADD4H +#undef ZER +#undef CAR1 +#undef CAR2 + +// --------------------------------------- +// p256MulInternalVMSL +// V0-V3,V30,V31 - Not Modified +// V4-V14 - Volatile + +#define CPOOL R4 +#define SCRATCH R9 + +// Parameters +#define X0 V0 // Not modified +#define X1 V1 // Not modified +#define Y0 V2 // Not modified +#define Y1 V3 // Not modified +#define T0 V4 +#define T1 V5 +#define T2 V6 +#define P0 V30 // Not modified +#define P1 V31 // Not modified + +// input: d0 +// output: h0, h1 +// temp: TEMP, ZERO, BORROW +#define OBSERVATION3(d0, h0, h1, TEMP, ZERO, BORROW) \ + VZERO ZERO \ + VSLDB $4, d0, ZERO, h0 \ + VLR h0, BORROW \ + VSLDB $12, ZERO, h0, TEMP \ + VSQ TEMP, h0, h0 \ + VSLDB $12, d0, BORROW, h1 \ + VSLDB $8, ZERO, BORROW, TEMP \ + VAQ TEMP, h0, h0 \ + +#define OBSERVATION3A(d2, h0, h1, TEMP, ZERO) \ + VZERO ZERO \ + VSLDB $8, d2, ZERO, TEMP \ + VSLDB $8, d2, TEMP, h0 \ + VSLDB $12, ZERO, TEMP, h1 \ + VSQ h1, h0, h0 \ + +TEXT ·p256MulInternalVMSL(SB), NOFRAME|NOSPLIT, $0-0 + VSTM V16, V19, (SCRATCH) + + MOVD $p256vmsl<>+0x00(SB), CPOOL + + // Divide input1 into 5 limbs + VGBM $0x007f, V14 + VZERO V12 + VSLDB $2, X1, X0, V13 + VSLDB $2, Y1, Y0, V8 + VSLDB $4, V12, X1, V11 // V11(X1): 4 bytes limb + VSLDB $4, V12, Y1, V6 // V6: 4 bytes limb + + VN V14, X0, V5 // V5: first 7 bytes limb + VN V14, Y0, V10 // V10: first 7 bytes limb + VN V14, V13, V13 // v13: third 7 bytes limb + VN V14, V8, V8 // V8: third 7 bytes limb + + VMSLG V10, V5, V12, V10 // v10: l10 x l5 (column 1) + VMSLG V8, V5, V12, V8 // v8: l8 x l5 + VMSLG V6, V13, V12, V13 // v13: l6 x l3 + VMSLG V6, V11, V12, V11 // v11: l6 x l1 (column 9) + VMSLG V6, V5, V12, V6 // v6: l6 x l5 + + MOVD $p256vmsl<>+0x00(SB), CPOOL + VGBM $0x7f7f, V14 + + VL 0(CPOOL), V4 + VL 16(CPOOL), V7 + VL 32(CPOOL), V9 + VL 48(CPOOL), V5 + VLM 64(CPOOL), V16, V19 + + VPERM V12, X0, V4, V4 // v4: limb4 | limb5 + VPERM Y1, Y0, V7, V7 + VPERM V12, Y0, V9, V9 // v9: limb10 | limb9 + VPERM X1, X0, V5, V5 + VPERM X1, X0, V16, V16 + VPERM Y1, Y0, V17, V17 + VPERM X1, V12, V18, V18 // v18: limb1 | limb2 + VPERM Y1, V12, V19, V19 // v19: limb7 | limb6 + VN V14, V7, V7 // v7: limb9 | limb8 + VN V14, V5, V5 // v5: limb3 | limb4 + VN V14, V16, V16 // v16: limb2 | limb3 + VN V14, V17, V17 // v17: limb8 | limb7 + + VMSLG V9, V4, V12, V14 // v14: l10 x l4 + l9 x l5 (column 2) + VMSLG V9, V5, V8, V8 // v8: l10 x l9 + l3 x l4 + l8 x l5 (column 3) + VMSLG V9, V16, V12, V16 // v16: l10 x l9 + l2 x l3 + VMSLG V9, V18, V12, V9 // v9: l10 x l1 + l9 x l2 + VMSLG V7, V18, V12, V7 // v7: l9 x l1 + l8 x l2 + VMSLG V17, V4, V16, V16 // v16: l8 x l4 + l7 x l5 + l10 x l9 + l2 x l3 (column 4) + VMSLG V17, V5, V9, V9 // v9: l10 x l1 + l9 x l2 + l8 x l3 + l7 x l4 + VMSLG V17, V18, V12, V17 // v18: l8 x l1 + l7 x l2 + VMSLG V19, V5, V7, V7 // v7: l9 x l1 + l8 x l2 + l7 x l3 + l6 x l4 (column 6) + VMSLG V19, V18, V12, V19 // v19: l7 x l1 + l6 x l2 (column 8) + VAQ V9, V6, V9 // v9: l10 x l1 + l9 x l2 + l8 x l3 + l7 x l4 + l6 x l5 (column 5) + VAQ V17, V13, V13 // v13: l8 x l1 + l7 x l2 + l6 x l3 (column 7) + + VSLDB $9, V12, V10, V4 + VSLDB $9, V12, V7, V5 + VAQ V4, V14, V14 + VAQ V5, V13, V13 + + VSLDB $9, V12, V14, V4 + VSLDB $9, V12, V13, V5 + VAQ V4, V8, V8 + VAQ V5, V19, V19 + + VSLDB $9, V12, V8, V4 + VSLDB $9, V12, V19, V5 + VAQ V4, V16, V16 + VAQ V5, V11, V11 + + VSLDB $9, V12, V16, V4 + VAQ V4, V9, V17 + + VGBM $0x007f, V4 + VGBM $0x00ff, V5 + + VN V10, V4, V10 + VN V14, V4, V14 + VN V8, V4, V8 + VN V16, V4, V16 + VN V17, V4, V9 + VN V7, V4, V7 + VN V13, V4, V13 + VN V19, V4, V19 + VN V11, V5, V11 + + VSLDB $7, V14, V14, V14 + VSLDB $14, V8, V12, V4 + VSLDB $14, V12, V8, V8 + VSLDB $5, V16, V16, V16 + VSLDB $12, V9, V12, V5 + + VO V14, V10, V10 + VO V8, V16, V16 + VO V4, V10, V10 // first rightmost 128bits of the multiplication result + VO V5, V16, V16 // second rightmost 128bits of the multiplication result + + // adjust v7, v13, v19, v11 + VSLDB $7, V13, V13, V13 + VSLDB $14, V19, V12, V4 + VSLDB $14, V12, V19, V19 + VSLDB $5, V11, V12, V5 + VO V13, V7, V7 + VO V4, V7, V7 + VO V19, V5, V11 + + VSLDB $9, V12, V17, V14 + VSLDB $12, V12, V9, V9 + VACCQ V7, V14, V13 + VAQ V7, V14, V7 + VAQ V11, V13, V11 + + // First reduction, 96 bits + VSLDB $4, V16, V10, T0 + VSLDB $4, V12, V16, T1 + VSLDB $3, V11, V7, V11 // fourth rightmost 128bits of the multiplication result + VSLDB $3, V7, V12, V7 + OBSERVATION3(V10, V8, T2, V17, V18, V19)// results V8 | T2 + VO V7, V9, V7 // third rightmost 128bits of the multiplication result + VACCQ T0, T2, V9 + VAQ T0, T2, T2 + VACQ T1, V8, V9, V8 + + // Second reduction 96 bits + VSLDB $4, V8, T2, T0 + VSLDB $4, V12, V8, T1 + OBSERVATION3(T2, V9, V8, V17, V18, V19)// results V9 | V8 + VACCQ T0, V8, T2 + VAQ T0, V8, V8 + VACQ T1, V9, T2, V9 + + // Third reduction 64 bits + VSLDB $8, V9, V8, T0 + VSLDB $8, V12, V9, T1 + OBSERVATION3A(V8, V14, V13, V17, V18)// results V14 | V13 + VACCQ T0, V13, V12 + VAQ T0, V13, V13 + VACQ T1, V14, V12, V14 + VACCQ V13, V7, V12 + VAQ V13, V7, T0 + VACCCQ V14, V11, V12, T2 + VACQ V14, V11, V12, T1 // results T2 | T1 | T0 + + // --------------------------------------------------- + MOVD $p256mul<>+0x00(SB), CPOOL + + VZERO V12 + VSCBIQ P0, T0, V8 + VSQ P0, T0, V7 + VSBCBIQ T1, P1, V8, V10 + VSBIQ T1, P1, V8, V9 + VSBIQ T2, V12, V10, T2 + + // what output to use, V9||V7 or T1||T0? + VSEL T0, V7, T2, T0 + VSEL T1, V9, T2, T1 + + VLM (SCRATCH), V16, V19 + + RET + +// --------------------------------------- +// p256SqrInternalVMSL +// V0-V1,V30,V31 - Not Modified +// V4-V14 - Volatile + +TEXT ·p256SqrInternalVMSL(SB), NOFRAME|NOSPLIT, $0-0 + VSTM V16, V18, (SCRATCH) + + MOVD $p256vmsl<>+0x00(SB), CPOOL + // Divide input into limbs + VGBM $0x007f, V14 + VZERO V12 + VSLDB $2, X1, X0, V13 + VSLDB $4, V12, X1, V11 // V11(X1): 4 bytes limb + + VN V14, X0, V10 // V10: first 7 bytes limb + VN V14, V13, V13 // v13: third 7 bytes limb + + VMSLG V10, V10, V12, V10 // v10: l10 x l5 (column 1) + VMSLG V13, V13, V12, V13 // v13: l8 x l3 + VMSLG V11, V11, V12, V11 // v11: l6 x l1 (column 9) + + MOVD $p256vmsl<>+0x00(SB), CPOOL + VGBM $0x7f7f, V14 + + VL 0(CPOOL), V4 + VL 16(CPOOL), V7 + VL 32(CPOOL), V9 + VL 48(CPOOL), V5 + VLM 64(CPOOL), V16, V18 + VL 112(CPOOL), V8 + + VPERM V12, X0, V4, V4 // v4: limb4 | limb5 + VPERM X1, X0, V7, V7 + VPERM V12, X0, V9, V9 // v9: limb10 | limb9 + VPERM X1, X0, V5, V5 + VPERM X1, X0, V16, V16 + VPERM X1, X0, V17, V17 + VPERM X1, V12, V18, V18 // v18: limb1 | limb2 + VPERM X1, V12, V8, V8 // v8: limb7 | limb6 + VN V14, V7, V7 // v7: limb9 | limb8 + VN V14, V5, V5 // v5: limb3 | limb4 + VN V14, V16, V16 // v16: limb2 | limb3 + VN V14, V17, V17 // v17: limb8 | limb7 + + VMSLEOG V9, V18, V13, V6 // v6: l10 x l1 + l9 x l2 + l8 x l3 + l7 x l4 + l6 x l5 (column 5) + VMSLG V9, V4, V12, V14 // v14: l10 x l4 + l9 x l5 (column 2) + VMSLEOG V9, V16, V12, V16 // v16: l10 x l2 + l9 x l3 + l8 x l4 + l7 x l5 (column 4) + VMSLEOG V7, V18, V12, V7 // v7: l9 x l1 + l8 x l2 (column 6) + VMSLEG V17, V18, V12, V13 // v13: l8 x l1 + l7 x l2 + l6 x l3 (column 7) + VMSLG V8, V18, V12, V8 // v8: l7 x l1 + l6 x l2 (column 8) + VMSLEG V9, V5, V12, V18 // v18: l10 x l3 + l9 x l4 + l8 x l5 (column 3) + + VSLDB $9, V12, V10, V4 + VSLDB $9, V12, V7, V5 + VAQ V4, V14, V14 + VAQ V5, V13, V13 + + VSLDB $9, V12, V14, V4 + VSLDB $9, V12, V13, V5 + VAQ V4, V18, V18 + VAQ V5, V8, V8 + + VSLDB $9, V12, V18, V4 + VSLDB $9, V12, V8, V5 + VAQ V4, V16, V16 + VAQ V5, V11, V11 + + VSLDB $9, V12, V16, V4 + VAQ V4, V6, V17 + + VGBM $0x007f, V4 + VGBM $0x00ff, V5 + + VN V10, V4, V10 + VN V14, V4, V14 + VN V18, V4, V18 + VN V16, V4, V16 + VN V17, V4, V9 + VN V7, V4, V7 + VN V13, V4, V13 + VN V8, V4, V8 + VN V11, V5, V11 + + VSLDB $7, V14, V14, V14 + VSLDB $14, V18, V12, V4 + VSLDB $14, V12, V18, V18 + VSLDB $5, V16, V16, V16 + VSLDB $12, V9, V12, V5 + + VO V14, V10, V10 + VO V18, V16, V16 + VO V4, V10, V10 // first rightmost 128bits of the multiplication result + VO V5, V16, V16 // second rightmost 128bits of the multiplication result + + // adjust v7, v13, v8, v11 + VSLDB $7, V13, V13, V13 + VSLDB $14, V8, V12, V4 + VSLDB $14, V12, V8, V8 + VSLDB $5, V11, V12, V5 + VO V13, V7, V7 + VO V4, V7, V7 + VO V8, V5, V11 + + VSLDB $9, V12, V17, V14 + VSLDB $12, V12, V9, V9 + VACCQ V7, V14, V13 + VAQ V7, V14, V7 + VAQ V11, V13, V11 + + // First reduction, 96 bits + VSLDB $4, V16, V10, T0 + VSLDB $4, V12, V16, T1 + VSLDB $3, V11, V7, V11 // fourth rightmost 128bits of the multiplication result + VSLDB $3, V7, V12, V7 + OBSERVATION3(V10, V8, T2, V16, V17, V18)// results V8 | T2 + VO V7, V9, V7 // third rightmost 128bits of the multiplication result + VACCQ T0, T2, V9 + VAQ T0, T2, T2 + VACQ T1, V8, V9, V8 + + // Second reduction 96 bits + VSLDB $4, V8, T2, T0 + VSLDB $4, V12, V8, T1 + OBSERVATION3(T2, V9, V8, V16, V17, V18)// results V9 | V8 + VACCQ T0, V8, T2 + VAQ T0, V8, V8 + VACQ T1, V9, T2, V9 + + // Third reduction 64 bits + VSLDB $8, V9, V8, T0 + VSLDB $8, V12, V9, T1 + OBSERVATION3A(V8, V14, V13, V17, V18)// results V14 | V13 + VACCQ T0, V13, V12 + VAQ T0, V13, V13 + VACQ T1, V14, V12, V14 + VACCQ V13, V7, V12 + VAQ V13, V7, T0 + VACCCQ V14, V11, V12, T2 + VACQ V14, V11, V12, T1 // results T2 | T1 | T0 + + // --------------------------------------------------- + MOVD $p256mul<>+0x00(SB), CPOOL + + VZERO V12 + VSCBIQ P0, T0, V8 + VSQ P0, T0, V7 + VSBCBIQ T1, P1, V8, V10 + VSBIQ T1, P1, V8, V9 + VSBIQ T2, V12, V10, T2 + + // what output to use, V9||V7 or T1||T0? + VSEL T0, V7, T2, T0 + VSEL T1, V9, T2, T1 + + VLM (SCRATCH), V16, V18 + RET + + + +#undef CPOOL +#undef SCRATCH +#undef X0 +#undef X1 +#undef Y0 +#undef Y1 +#undef T0 +#undef T1 +#undef T2 +#undef P0 +#undef P1 + +#define SCRATCH R9 + +TEXT p256MulInternal<>(SB),NOSPLIT,$64-0 + MOVD $scratch-64(SP), SCRATCH + MOVD ·p256MulInternalFacility+0x00(SB),R7 + CALL (R7) + RET + +TEXT ·p256MulInternalTrampolineSetup(SB),NOSPLIT|NOFRAME, $0 + MOVBZ internal∕cpu·S390X+const_offsetS390xHasVE1(SB), R0 + MOVD $·p256MulInternalFacility+0x00(SB), R7 + MOVD $·p256MulInternalVX(SB), R8 + CMPBEQ R0, $0, novmsl // VE1 facility = 1, VMSL supported + MOVD $·p256MulInternalVMSL(SB), R8 +novmsl: + MOVD R8, 0(R7) + BR (R8) + +GLOBL ·p256MulInternalFacility+0x00(SB), NOPTR, $8 +DATA ·p256MulInternalFacility+0x00(SB)/8, $·p256MulInternalTrampolineSetup(SB) + +// Parameters +#define X0 V0 +#define X1 V1 +#define Y0 V2 +#define Y1 V3 + +TEXT ·p256SqrInternalVX(SB), NOFRAME|NOSPLIT, $0 + VLR X0, Y0 + VLR X1, Y1 + BR ·p256MulInternalVX(SB) + +#undef X0 +#undef X1 +#undef Y0 +#undef Y1 + + +TEXT p256SqrInternal<>(SB),NOSPLIT,$48-0 + MOVD $scratch-48(SP), SCRATCH + MOVD ·p256SqrInternalFacility+0x00(SB),R7 + CALL (R7) + RET + +TEXT ·p256SqrInternalTrampolineSetup(SB),NOSPLIT|NOFRAME, $0 + MOVBZ internal∕cpu·S390X+const_offsetS390xHasVE1(SB), R0 + MOVD $·p256SqrInternalFacility+0x00(SB), R7 + MOVD $·p256SqrInternalVX(SB), R8 + CMPBEQ R0, $0, novmsl // VE1 facility = 1, VMSL supported + MOVD $·p256SqrInternalVMSL(SB), R8 +novmsl: + MOVD R8, 0(R7) + BR (R8) + + +GLOBL ·p256SqrInternalFacility+0x00(SB), NOPTR, $8 +DATA ·p256SqrInternalFacility+0x00(SB)/8, $·p256SqrInternalTrampolineSetup(SB) + +#undef SCRATCH + + +#define p256SubInternal(T1, T0, X1, X0, Y1, Y0) \ + VZERO ZER \ + VSCBIQ Y0, X0, CAR1 \ + VSQ Y0, X0, T0 \ + VSBCBIQ X1, Y1, CAR1, SEL1 \ + VSBIQ X1, Y1, CAR1, T1 \ + VSQ SEL1, ZER, SEL1 \ + \ + VACCQ T0, PL, CAR1 \ + VAQ T0, PL, TT0 \ + VACQ T1, PH, CAR1, TT1 \ + \ + VSEL T0, TT0, SEL1, T0 \ + VSEL T1, TT1, SEL1, T1 \ + +#define p256AddInternal(T1, T0, X1, X0, Y1, Y0) \ + VACCQ X0, Y0, CAR1 \ + VAQ X0, Y0, T0 \ + VACCCQ X1, Y1, CAR1, T2 \ + VACQ X1, Y1, CAR1, T1 \ + \ + VZERO ZER \ + VSCBIQ PL, T0, CAR1 \ + VSQ PL, T0, TT0 \ + VSBCBIQ T1, PH, CAR1, CAR2 \ + VSBIQ T1, PH, CAR1, TT1 \ + VSBIQ T2, ZER, CAR2, SEL1 \ + \ + VSEL T0, TT0, SEL1, T0 \ + VSEL T1, TT1, SEL1, T1 + +#define p256HalfInternal(T1, T0, X1, X0) \ + VZERO ZER \ + VSBIQ ZER, ZER, X0, SEL1 \ + \ + VACCQ X0, PL, CAR1 \ + VAQ X0, PL, T0 \ + VACCCQ X1, PH, CAR1, T2 \ + VACQ X1, PH, CAR1, T1 \ + \ + VSEL X0, T0, SEL1, T0 \ + VSEL X1, T1, SEL1, T1 \ + VSEL ZER, T2, SEL1, T2 \ + \ + VSLDB $15, T2, ZER, TT1 \ + VSLDB $15, T1, ZER, TT0 \ + VREPIB $1, SEL1 \ + VSRL SEL1, T0, T0 \ + VSRL SEL1, T1, T1 \ + VREPIB $7, SEL1 \ + VSL SEL1, TT0, TT0 \ + VSL SEL1, TT1, TT1 \ + VO T0, TT0, T0 \ + VO T1, TT1, T1 + +// --------------------------------------- +// func p256MulAsm(res, in1, in2 []byte) +#define res_ptr R1 +#define x_ptr R2 +#define y_ptr R3 +#define CPOOL R4 + +// Parameters +#define X0 V0 +#define X1 V1 +#define Y0 V2 +#define Y1 V3 +#define T0 V4 +#define T1 V5 + +// Constants +#define P0 V30 +#define P1 V31 +TEXT ·p256MulAsm(SB), NOSPLIT, $0 + MOVD res+0(FP), res_ptr + MOVD in1+24(FP), x_ptr + MOVD in2+48(FP), y_ptr + + VL (1*16)(x_ptr), X0 + VL (0*16)(x_ptr), X1 + VL (1*16)(y_ptr), Y0 + VL (0*16)(y_ptr), Y1 + + MOVD $p256mul<>+0x00(SB), CPOOL + VL 16(CPOOL), P0 + VL 0(CPOOL), P1 + + CALL p256MulInternal<>(SB) + + VST T0, (1*16)(res_ptr) + VST T1, (0*16)(res_ptr) + RET + +#undef res_ptr +#undef x_ptr +#undef y_ptr +#undef CPOOL + +#undef X0 +#undef X1 +#undef Y0 +#undef Y1 +#undef T0 +#undef T1 +#undef P0 +#undef P1 + +// --------------------------------------- +// func p256SqrAsm(res, in1 []byte) +#define res_ptr R1 +#define x_ptr R2 +#define y_ptr R3 +#define CPOOL R4 + +// Parameters +#define X0 V0 +#define X1 V1 +#define T0 V4 +#define T1 V5 + +// Constants +#define P0 V30 +#define P1 V31 +TEXT ·p256SqrAsm(SB), NOSPLIT, $0 + MOVD res+0(FP), res_ptr + MOVD in1+24(FP), x_ptr + + VL (1*16)(x_ptr), X0 + VL (0*16)(x_ptr), X1 + + MOVD $p256mul<>+0x00(SB), CPOOL + VL 16(CPOOL), P0 + VL 0(CPOOL), P1 + + CALL p256SqrInternal<>(SB) + + VST T0, (1*16)(res_ptr) + VST T1, (0*16)(res_ptr) + RET + +#undef res_ptr +#undef x_ptr +#undef y_ptr +#undef CPOOL + +#undef X0 +#undef X1 +#undef T0 +#undef T1 +#undef P0 +#undef P1 + + +// Point add with P2 being affine point +// If sign == 1 -> P2 = -P2 +// If sel == 0 -> P3 = P1 +// if zero == 0 -> P3 = P2 +// p256PointAddAffineAsm(P3, P1, P2 *p256Point, sign, sel, zero int) +#define P3ptr R1 +#define P1ptr R2 +#define P2ptr R3 +#define CPOOL R4 + +// Temporaries in REGs +#define Y2L V15 +#define Y2H V16 +#define T1L V17 +#define T1H V18 +#define T2L V19 +#define T2H V20 +#define T3L V21 +#define T3H V22 +#define T4L V23 +#define T4H V24 + +// Temps for Sub and Add +#define TT0 V11 +#define TT1 V12 +#define T2 V13 + +// p256MulAsm Parameters +#define X0 V0 +#define X1 V1 +#define Y0 V2 +#define Y1 V3 +#define T0 V4 +#define T1 V5 + +#define PL V30 +#define PH V31 + +// Names for zero/sel selects +#define X1L V0 +#define X1H V1 +#define Y1L V2 // p256MulAsmParmY +#define Y1H V3 // p256MulAsmParmY +#define Z1L V4 +#define Z1H V5 +#define X2L V0 +#define X2H V1 +#define Z2L V4 +#define Z2H V5 +#define X3L V17 // T1L +#define X3H V18 // T1H +#define Y3L V21 // T3L +#define Y3H V22 // T3H +#define Z3L V28 +#define Z3H V29 + +#define ZER V6 +#define SEL1 V7 +#define CAR1 V8 +#define CAR2 V9 +/* * + * Three operand formula: + * Source: 2004 Hankerson–Menezes–Vanstone, page 91. + * T1 = Z1² + * T2 = T1*Z1 + * T1 = T1*X2 + * T2 = T2*Y2 + * T1 = T1-X1 + * T2 = T2-Y1 + * Z3 = Z1*T1 + * T3 = T1² + * T4 = T3*T1 + * T3 = T3*X1 + * T1 = 2*T3 + * X3 = T2² + * X3 = X3-T1 + * X3 = X3-T4 + * T3 = T3-X3 + * T3 = T3*T2 + * T4 = T4*Y1 + * Y3 = T3-T4 + + * Three operand formulas, but with MulInternal X,Y used to store temps +X=Z1; Y=Z1; MUL;T- // T1 = Z1² T1 +X=T ; Y- ; MUL;T2=T // T2 = T1*Z1 T1 T2 +X- ; Y=X2; MUL;T1=T // T1 = T1*X2 T1 T2 +X=T2; Y=Y2; MUL;T- // T2 = T2*Y2 T1 T2 +SUB(T2+0x00(SB), CPOOL + VL 16(CPOOL), PL + VL 0(CPOOL), PH + + // if (sign == 1) { + // Y2 = fromBig(new(big.Int).Mod(new(big.Int).Sub(p256.P, new(big.Int).SetBytes(Y2)), p256.P)) // Y2 = P-Y2 + // } + + VL 32(P2ptr), Y2H + VL 48(P2ptr), Y2L + + VLREPG sign+24(FP), SEL1 + VZERO ZER + VCEQG SEL1, ZER, SEL1 + + VSCBIQ Y2L, PL, CAR1 + VSQ Y2L, PL, T1L + VSBIQ PH, Y2H, CAR1, T1H + + VSEL Y2L, T1L, SEL1, Y2L + VSEL Y2H, T1H, SEL1, Y2H + +/* * + * Three operand formula: + * Source: 2004 Hankerson–Menezes–Vanstone, page 91. + */ + // X=Z1; Y=Z1; MUL; T- // T1 = Z1² T1 + VL 64(P1ptr), X1 // Z1H + VL 80(P1ptr), X0 // Z1L + VLR X0, Y0 + VLR X1, Y1 + CALL p256SqrInternal<>(SB) + + // X=T ; Y- ; MUL; T2=T // T2 = T1*Z1 T1 T2 + VLR T0, X0 + VLR T1, X1 + CALL p256MulInternal<>(SB) + VLR T0, T2L + VLR T1, T2H + + // X- ; Y=X2; MUL; T1=T // T1 = T1*X2 T1 T2 + VL 0(P2ptr), Y1 // X2H + VL 16(P2ptr), Y0 // X2L + CALL p256MulInternal<>(SB) + VLR T0, T1L + VLR T1, T1H + + // X=T2; Y=Y2; MUL; T- // T2 = T2*Y2 T1 T2 + VLR T2L, X0 + VLR T2H, X1 + VLR Y2L, Y0 + VLR Y2H, Y1 + CALL p256MulInternal<>(SB) + + // SUB(T2(SB) + + // VST T1, 64(P3ptr) + // VST T0, 80(P3ptr) + VLR T0, Z3L + VLR T1, Z3H + + // X=Y; Y- ; MUL; X=T // T3 = T1*T1 T2 + VLR Y0, X0 + VLR Y1, X1 + CALL p256SqrInternal<>(SB) + VLR T0, X0 + VLR T1, X1 + + // X- ; Y- ; MUL; T4=T // T4 = T3*T1 T2 T4 + CALL p256MulInternal<>(SB) + VLR T0, T4L + VLR T1, T4H + + // X- ; Y=X1; MUL; T3=T // T3 = T3*X1 T2 T3 T4 + VL 0(P1ptr), Y1 // X1H + VL 16(P1ptr), Y0 // X1L + CALL p256MulInternal<>(SB) + VLR T0, T3L + VLR T1, T3H + + // ADD(T1(SB) + + // SUB(T(SB) + VLR T0, T3L + VLR T1, T3H + + // X=T4; Y=Y1; MUL; T- // T4 = T4*Y1 T3 T4 + VLR T4L, X0 + VLR T4H, X1 + VL 32(P1ptr), Y1 // Y1H + VL 48(P1ptr), Y0 // Y1L + CALL p256MulInternal<>(SB) + + // SUB(T+0x00(SB), CPOOL + VL 16(CPOOL), PL + VL 0(CPOOL), PH + + // X=Z1; Y=Z1; MUL; T- // T1 = Z1² + VL 64(P1ptr), X1 // Z1H + VL 80(P1ptr), X0 // Z1L + VLR X0, Y0 + VLR X1, Y1 + CALL p256SqrInternal<>(SB) + + // SUB(X(SB) + + // ADD(T2(SB) + VST T1, 64(P3ptr) + VST T0, 80(P3ptr) + + // X- ; Y=X ; MUL; T- // Y3 = Y3² + VLR X0, Y0 + VLR X1, Y1 + CALL p256SqrInternal<>(SB) + + // X=T ; Y=X1; MUL; T3=T // T3 = Y3*X1 + VLR T0, X0 + VLR T1, X1 + VL 0(P1ptr), Y1 + VL 16(P1ptr), Y0 + CALL p256MulInternal<>(SB) + VLR T0, T3L + VLR T1, T3H + + // X- ; Y=X ; MUL; T- // Y3 = Y3² + VLR X0, Y0 + VLR X1, Y1 + CALL p256SqrInternal<>(SB) + + // HAL(Y3(SB) + + // ADD(T1(SB) + + // SUB(Y3+0x00(SB), CPOOL + VL 16(CPOOL), PL + VL 0(CPOOL), PH + + // X=Z1; Y=Z1; MUL; T- // T1 = Z1*Z1 + VL 64(P1ptr), X1 // Z1H + VL 80(P1ptr), X0 // Z1L + VLR X0, Y0 + VLR X1, Y1 + CALL p256SqrInternal<>(SB) + + // X- ; Y=T ; MUL; R=T // R = Z1*T1 + VLR T0, Y0 + VLR T1, Y1 + CALL p256MulInternal<>(SB) + VLR T0, RL + VLR T1, RH + + // X=X2; Y- ; MUL; H=T // H = X2*T1 + VL 0(P2ptr), X1 // X2H + VL 16(P2ptr), X0 // X2L + CALL p256MulInternal<>(SB) + VLR T0, HL + VLR T1, HH + + // X=Z2; Y=Z2; MUL; T- // T2 = Z2*Z2 + VL 64(P2ptr), X1 // Z2H + VL 80(P2ptr), X0 // Z2L + VLR X0, Y0 + VLR X1, Y1 + CALL p256SqrInternal<>(SB) + + // X- ; Y=T ; MUL; S1=T // S1 = Z2*T2 + VLR T0, Y0 + VLR T1, Y1 + CALL p256MulInternal<>(SB) + VLR T0, S1L + VLR T1, S1H + + // X=X1; Y- ; MUL; U1=T // U1 = X1*T2 + VL 0(P1ptr), X1 // X1H + VL 16(P1ptr), X0 // X1L + CALL p256MulInternal<>(SB) + VLR T0, U1L + VLR T1, U1H + + // SUB(H(SB) + + // X=T ; Y=H ; MUL; Z3:=T// Z3 = Z3*H + VLR T0, X0 + VLR T1, X1 + VLR HL, Y0 + VLR HH, Y1 + CALL p256MulInternal<>(SB) + VST T1, 64(P3ptr) + VST T0, 80(P3ptr) + + // X=Y1; Y=S1; MUL; S1=T // S1 = Y1*S1 + VL 32(P1ptr), X1 + VL 48(P1ptr), X0 + VLR S1L, Y0 + VLR S1H, Y1 + CALL p256MulInternal<>(SB) + VLR T0, S1L + VLR T1, S1H + + // X=Y2; Y=R ; MUL; T- // R = Y2*R + VL 32(P2ptr), X1 + VL 48(P2ptr), X0 + VLR RL, Y0 + VLR RH, Y1 + CALL p256MulInternal<>(SB) + + // SUB(R(SB) + + // X- ; Y=T ; MUL; T2=T // T2 = H*T1 + VLR T0, Y0 + VLR T1, Y1 + CALL p256MulInternal<>(SB) + VLR T0, T2L + VLR T1, T2H + + // X=U1; Y- ; MUL; U1=T // U1 = U1*T1 + VLR U1L, X0 + VLR U1H, X1 + CALL p256MulInternal<>(SB) + VLR T0, U1L + VLR T1, U1H + + // X=R ; Y=R ; MUL; T- // X3 = R*R + VLR RL, X0 + VLR RH, X1 + VLR RL, Y0 + VLR RH, Y1 + CALL p256SqrInternal<>(SB) + + // SUB(T(SB) + VLR T0, U1L + VLR T1, U1H + + // X=S1; Y=T2; MUL; T- // T2 = S1*T2 + VLR S1L, X0 + VLR S1H, X1 + VLR T2L, Y0 + VLR T2H, Y1 + CALL p256MulInternal<>(SB) + + // SUB(T P2 = -P2 +// If sel == 0 -> P3 = P1 +// if zero == 0 -> P3 = P2 +// +//go:noescape +func p256PointAddAffineAsm(res, in1, in2 *p256Point, sign, sel, zero int) + +// Point add +// +//go:noescape +func p256PointAddAsm(res, in1, in2 *p256Point) int + +// +//go:noescape +func p256PointDoubleAsm(res, in *p256Point) + +// The result should be a slice in LE order, but the slice +// from big.Bytes is in BE order. +// TODO: For big endian implementation, do not reverse bytes. +// +func fromBig(big *big.Int) []byte { + // This could be done a lot more efficiently... + res := big.Bytes() + t := make([]byte, 32) + if len(res) < 32 { + copy(t[32-len(res):], res) + } else if len(res) == 32 { + copy(t, res) + } else { + copy(t, res[len(res)-32:]) + } + p256ReverseBytes(t, t) + return t +} + +// p256GetMultiplier makes sure byte array will have 32 byte elements, If the scalar +// is equal or greater than the order of the group, it's reduced modulo that order. +func p256GetMultiplier(in []byte) []byte { + n := new(big.Int).SetBytes(in) + + if n.Cmp(p256Params.N) >= 0 { + n.Mod(n, p256Params.N) + } + return fromBig(n) +} + +// p256MulAsm operates in a Montgomery domain with R = 2^256 mod p, where p is the +// underlying field of the curve. (See initP256 for the value.) Thus rr here is +// R×R mod p. See comment in Inverse about how this is used. +// TODO: For big endian implementation, the bytes in these slices should be in reverse order, +// as found in the s390x implementation. +var rr = []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00} + +// (This is one, in the Montgomery domain.) +var one = []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00} + +func maybeReduceModP(in *big.Int) *big.Int { + if in.Cmp(p256Params.P) < 0 { + return in + } + return new(big.Int).Mod(in, p256Params.P) +} + +// p256ReverseBytes copies the first 32 bytes from in to res in reverse order. +func p256ReverseBytes(res, in []byte) { + // remove bounds check + in = in[:32] + res = res[:32] + + // Load in reverse order + a := binary.BigEndian.Uint64(in[0:]) + b := binary.BigEndian.Uint64(in[8:]) + c := binary.BigEndian.Uint64(in[16:]) + d := binary.BigEndian.Uint64(in[24:]) + + // Store in normal order + binary.LittleEndian.PutUint64(res[0:], d) + binary.LittleEndian.PutUint64(res[8:], c) + binary.LittleEndian.PutUint64(res[16:], b) + binary.LittleEndian.PutUint64(res[24:], a) +} + +func (curve p256CurveFast) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) { + var r1, r2 p256Point + + scalarReduced := p256GetMultiplier(baseScalar) + r1IsInfinity := scalarIsZero(scalarReduced) + r1.p256BaseMult(scalarReduced) + + copy(r2.x[:], fromBig(maybeReduceModP(bigX))) + copy(r2.y[:], fromBig(maybeReduceModP(bigY))) + copy(r2.z[:], one) + p256MulAsm(r2.x[:], r2.x[:], rr[:]) + p256MulAsm(r2.y[:], r2.y[:], rr[:]) + + scalarReduced = p256GetMultiplier(scalar) + r2IsInfinity := scalarIsZero(scalarReduced) + r2.p256ScalarMult(scalarReduced) + + var sum, double p256Point + pointsEqual := p256PointAddAsm(&sum, &r1, &r2) + p256PointDoubleAsm(&double, &r1) + p256MovCond(&sum, &double, &sum, pointsEqual) + p256MovCond(&sum, &r1, &sum, r2IsInfinity) + p256MovCond(&sum, &r2, &sum, r1IsInfinity) + return sum.p256PointToAffine() +} + +func (curve p256CurveFast) ScalarBaseMult(scalar []byte) (x, y *big.Int) { + var r p256Point + reducedScalar := p256GetMultiplier(scalar) + r.p256BaseMult(reducedScalar) + return r.p256PointToAffine() +} + +func (curve p256CurveFast) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) { + scalarReduced := p256GetMultiplier(scalar) + var r p256Point + copy(r.x[:], fromBig(maybeReduceModP(bigX))) + copy(r.y[:], fromBig(maybeReduceModP(bigY))) + copy(r.z[:], one) + p256MulAsm(r.x[:], r.x[:], rr[:]) + p256MulAsm(r.y[:], r.y[:], rr[:]) + r.p256ScalarMult(scalarReduced) + return r.p256PointToAffine() +} + +func scalarIsZero(scalar []byte) int { + // If any byte is not zero, return 0. + // Check for -0.... since that appears to compare to 0. + b := byte(0) + for _, s := range scalar { + b |= s + } + return subtle.ConstantTimeByteEq(b, 0) +} + +func (p *p256Point) p256PointToAffine() (x, y *big.Int) { + zInv := make([]byte, 32) + zInvSq := make([]byte, 32) + + p256Inverse(zInv, p.z[:]) + p256Sqr(zInvSq, zInv) + p256MulAsm(zInv, zInv, zInvSq) + + p256MulAsm(zInvSq, p.x[:], zInvSq) + p256MulAsm(zInv, p.y[:], zInv) + + p256FromMont(zInvSq, zInvSq) + p256FromMont(zInv, zInv) + + // SetBytes expects a slice in big endian order, + // since ppc64le is little endian, reverse the bytes. + // TODO: For big endian, bytes don't need to be reversed. + p256ReverseBytes(zInvSq, zInvSq) + p256ReverseBytes(zInv, zInv) + rx := new(big.Int).SetBytes(zInvSq) + ry := new(big.Int).SetBytes(zInv) + return rx, ry +} + +// p256Inverse sets out to in^-1 mod p. +func p256Inverse(out, in []byte) { + var stack [6 * 32]byte + p2 := stack[32*0 : 32*0+32] + p4 := stack[32*1 : 32*1+32] + p8 := stack[32*2 : 32*2+32] + p16 := stack[32*3 : 32*3+32] + p32 := stack[32*4 : 32*4+32] + + p256Sqr(out, in) + p256MulAsm(p2, out, in) // 3*p + + p256Sqr(out, p2) + p256Sqr(out, out) + p256MulAsm(p4, out, p2) // f*p + + p256Sqr(out, p4) + p256Sqr(out, out) + p256Sqr(out, out) + p256Sqr(out, out) + p256MulAsm(p8, out, p4) // ff*p + + p256Sqr(out, p8) + + for i := 0; i < 7; i++ { + p256Sqr(out, out) + } + p256MulAsm(p16, out, p8) // ffff*p + + p256Sqr(out, p16) + for i := 0; i < 15; i++ { + p256Sqr(out, out) + } + p256MulAsm(p32, out, p16) // ffffffff*p + + p256Sqr(out, p32) + + for i := 0; i < 31; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, in) + + for i := 0; i < 32*4; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, p32) + + for i := 0; i < 32; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, p32) + + for i := 0; i < 16; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, p16) + + for i := 0; i < 8; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, p8) + + p256Sqr(out, out) + p256Sqr(out, out) + p256Sqr(out, out) + p256Sqr(out, out) + p256MulAsm(out, out, p4) + + p256Sqr(out, out) + p256Sqr(out, out) + p256MulAsm(out, out, p2) + + p256Sqr(out, out) + p256Sqr(out, out) + p256MulAsm(out, out, in) +} + +func boothW5(in uint) (int, int) { + var s uint = ^((in >> 5) - 1) + var d uint = (1 << 6) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return int(d), int(s & 1) +} + +func boothW6(in uint) (int, int) { + var s uint = ^((in >> 6) - 1) + var d uint = (1 << 7) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return int(d), int(s & 1) +} + +func boothW7(in uint) (int, int) { + var s uint = ^((in >> 7) - 1) + var d uint = (1 << 8) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return int(d), int(s & 1) +} + +func initTable() { + + p256PreFast = new([37][64]p256Point) + + // TODO: For big endian, these slices should be in reverse byte order, + // as found in the s390x implementation. + basePoint := p256Point{ + x: [32]byte{0x3c, 0x14, 0xa9, 0x18, 0xd4, 0x30, 0xe7, 0x79, 0x01, 0xb6, 0xed, 0x5f, 0xfc, 0x95, 0xba, 0x75, + 0x10, 0x25, 0x62, 0x77, 0x2b, 0x73, 0xfb, 0x79, 0xc6, 0x55, 0x37, 0xa5, 0x76, 0x5f, 0x90, 0x18}, //(p256.x*2^256)%p + y: [32]byte{0x0a, 0x56, 0x95, 0xce, 0x57, 0x53, 0xf2, 0xdd, 0x5c, 0xe4, 0x19, 0xba, 0xe4, 0xb8, 0x4a, 0x8b, + 0x25, 0xf3, 0x21, 0xdd, 0x88, 0x86, 0xe8, 0xd2, 0x85, 0x5d, 0x88, 0x25, 0x18, 0xff, 0x71, 0x85}, //(p256.y*2^256)%p + z: [32]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, //(p256.z*2^256)%p + + } + + t1 := new(p256Point) + t2 := new(p256Point) + *t2 = basePoint + + zInv := make([]byte, 32) + zInvSq := make([]byte, 32) + for j := 0; j < 64; j++ { + *t1 = *t2 + for i := 0; i < 37; i++ { + // The window size is 7 so we need to double 7 times. + if i != 0 { + for k := 0; k < 7; k++ { + p256PointDoubleAsm(t1, t1) + } + } + // Convert the point to affine form. (Its values are + // still in Montgomery form however.) + p256Inverse(zInv, t1.z[:]) + p256Sqr(zInvSq, zInv) + p256MulAsm(zInv, zInv, zInvSq) + + p256MulAsm(t1.x[:], t1.x[:], zInvSq) + p256MulAsm(t1.y[:], t1.y[:], zInv) + + copy(t1.z[:], basePoint.z[:]) + // Update the table entry + copy(p256PreFast[i][j].x[:], t1.x[:]) + copy(p256PreFast[i][j].y[:], t1.y[:]) + } + if j == 0 { + p256PointDoubleAsm(t2, &basePoint) + } else { + p256PointAddAsm(t2, t2, &basePoint) + } + } +} + +func (p *p256Point) p256BaseMult(scalar []byte) { + // TODO: For big endian, the index should be 31 not 0. + wvalue := (uint(scalar[0]) << 1) & 0xff + sel, sign := boothW7(uint(wvalue)) + p256SelectBase(p, p256PreFast[0][:], sel) + p256NegCond(p, sign) + + copy(p.z[:], one[:]) + var t0 p256Point + + copy(t0.z[:], one[:]) + + index := uint(6) + zero := sel + for i := 1; i < 37; i++ { + // TODO: For big endian, use the same index values as found + // in the s390x implementation. + if index < 247 { + wvalue = ((uint(scalar[index/8]) >> (index % 8)) + (uint(scalar[index/8+1]) << (8 - (index % 8)))) & 0xff + } else { + wvalue = (uint(scalar[index/8]) >> (index % 8)) & 0xff + } + index += 7 + sel, sign = boothW7(uint(wvalue)) + p256SelectBase(&t0, p256PreFast[i][:], sel) + p256PointAddAffineAsm(p, p, &t0, sign, sel, zero) + zero |= sel + } +} + +func (p *p256Point) p256ScalarMult(scalar []byte) { + // precomp is a table of precomputed points that stores powers of p + // from p^1 to p^16. + var precomp [16]p256Point + var t0, t1, t2, t3 p256Point + + *&precomp[0] = *p + p256PointDoubleAsm(&t0, p) + p256PointDoubleAsm(&t1, &t0) + p256PointDoubleAsm(&t2, &t1) + p256PointDoubleAsm(&t3, &t2) + *&precomp[1] = t0 + *&precomp[3] = t1 + *&precomp[7] = t2 + *&precomp[15] = t3 + + p256PointAddAsm(&t0, &t0, p) + p256PointAddAsm(&t1, &t1, p) + p256PointAddAsm(&t2, &t2, p) + + *&precomp[2] = t0 + *&precomp[4] = t1 + *&precomp[8] = t2 + + p256PointDoubleAsm(&t0, &t0) + p256PointDoubleAsm(&t1, &t1) + *&precomp[5] = t0 + *&precomp[9] = t1 + + p256PointAddAsm(&t2, &t0, p) + p256PointAddAsm(&t1, &t1, p) + *&precomp[6] = t2 + *&precomp[10] = t1 + + p256PointDoubleAsm(&t0, &t0) + p256PointDoubleAsm(&t2, &t2) + *&precomp[11] = t0 + *&precomp[13] = t2 + + p256PointAddAsm(&t0, &t0, p) + p256PointAddAsm(&t2, &t2, p) + *&precomp[12] = t0 + *&precomp[14] = t2 + + // Start scanning the window from top bit + index := uint(254) + var sel, sign int + + // TODO: For big endian, use index found in s390x implementation. + wvalue := (uint(scalar[index/8]) >> (index % 8)) & 0x3f + sel, _ = boothW5(uint(wvalue)) + p256Select(p, precomp[:], sel) + zero := sel + + for index > 4 { + index -= 5 + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + + // TODO: For big endian, use index values as found in s390x implementation. + if index < 247 { + wvalue = ((uint(scalar[index/8]) >> (index % 8)) + (uint(scalar[index/8+1]) << (8 - (index % 8)))) & 0x3f + } else { + wvalue = (uint(scalar[index/8]) >> (index % 8)) & 0x3f + } + + sel, sign = boothW5(uint(wvalue)) + + p256Select(&t0, precomp[:], sel) + p256NegCond(&t0, sign) + p256PointAddAsm(&t1, p, &t0) + p256MovCond(&t1, &t1, p, sel) + p256MovCond(p, &t1, &t0, zero) + zero |= sel + } + + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + + // TODO: Use index for big endian as found in s390x implementation. + wvalue = (uint(scalar[0]) << 1) & 0x3f + sel, sign = boothW5(uint(wvalue)) + + p256Select(&t0, precomp[:], sel) + p256NegCond(&t0, sign) + p256PointAddAsm(&t1, p, &t0) + p256MovCond(&t1, &t1, p, sel) + p256MovCond(p, &t1, &t0, zero) +} diff --git a/src/crypto/elliptic/p256_s390x.go b/src/crypto/elliptic/p256_s390x.go new file mode 100644 index 0000000..91e613b --- /dev/null +++ b/src/crypto/elliptic/p256_s390x.go @@ -0,0 +1,577 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build s390x +// +build s390x + +package elliptic + +import ( + "crypto/subtle" + "internal/cpu" + "math/big" + "unsafe" +) + +const ( + offsetS390xHasVX = unsafe.Offsetof(cpu.S390X.HasVX) + offsetS390xHasVE1 = unsafe.Offsetof(cpu.S390X.HasVXE) +) + +type p256CurveFast struct { + *CurveParams +} + +type p256Point struct { + x [32]byte + y [32]byte + z [32]byte +} + +var ( + p256 Curve + p256PreFast *[37][64]p256Point +) + +//go:noescape +func p256MulInternalTrampolineSetup() + +//go:noescape +func p256SqrInternalTrampolineSetup() + +//go:noescape +func p256MulInternalVX() + +//go:noescape +func p256MulInternalVMSL() + +//go:noescape +func p256SqrInternalVX() + +//go:noescape +func p256SqrInternalVMSL() + +func initP256Arch() { + if cpu.S390X.HasVX { + p256 = p256CurveFast{p256Params} + initTable() + return + } + + // No vector support, use pure Go implementation. + p256 = p256Curve{p256Params} + return +} + +func (curve p256CurveFast) Params() *CurveParams { + return curve.CurveParams +} + +// Functions implemented in p256_asm_s390x.s +// Montgomery multiplication modulo P256 +// +//go:noescape +func p256SqrAsm(res, in1 []byte) + +//go:noescape +func p256MulAsm(res, in1, in2 []byte) + +// Montgomery square modulo P256 +func p256Sqr(res, in []byte) { + p256SqrAsm(res, in) +} + +// Montgomery multiplication by 1 +// +//go:noescape +func p256FromMont(res, in []byte) + +// iff cond == 1 val <- -val +// +//go:noescape +func p256NegCond(val *p256Point, cond int) + +// if cond == 0 res <- b; else res <- a +// +//go:noescape +func p256MovCond(res, a, b *p256Point, cond int) + +// Constant time table access +// +//go:noescape +func p256Select(point *p256Point, table []p256Point, idx int) + +//go:noescape +func p256SelectBase(point *p256Point, table []p256Point, idx int) + +// Montgomery multiplication modulo Ord(G) +// +//go:noescape +func p256OrdMul(res, in1, in2 []byte) + +// Montgomery square modulo Ord(G), repeated n times +func p256OrdSqr(res, in []byte, n int) { + copy(res, in) + for i := 0; i < n; i += 1 { + p256OrdMul(res, res, res) + } +} + +// Point add with P2 being affine point +// If sign == 1 -> P2 = -P2 +// If sel == 0 -> P3 = P1 +// if zero == 0 -> P3 = P2 +// +//go:noescape +func p256PointAddAffineAsm(P3, P1, P2 *p256Point, sign, sel, zero int) + +// Point add +// +//go:noescape +func p256PointAddAsm(P3, P1, P2 *p256Point) int + +//go:noescape +func p256PointDoubleAsm(P3, P1 *p256Point) + +func (curve p256CurveFast) Inverse(k *big.Int) *big.Int { + if k.Cmp(p256Params.N) >= 0 { + // This should never happen. + reducedK := new(big.Int).Mod(k, p256Params.N) + k = reducedK + } + + // table will store precomputed powers of x. The 32 bytes at index + // i store x^(i+1). + var table [15][32]byte + + x := fromBig(k) + // This code operates in the Montgomery domain where R = 2^256 mod n + // and n is the order of the scalar field. (See initP256 for the + // value.) Elements in the Montgomery domain take the form a×R and + // multiplication of x and y in the calculates (x × y × R^-1) mod n. RR + // is R×R mod n thus the Montgomery multiplication x and RR gives x×R, + // i.e. converts x into the Montgomery domain. Stored in BigEndian form + RR := []byte{0x66, 0xe1, 0x2d, 0x94, 0xf3, 0xd9, 0x56, 0x20, 0x28, 0x45, 0xb2, 0x39, 0x2b, 0x6b, 0xec, 0x59, + 0x46, 0x99, 0x79, 0x9c, 0x49, 0xbd, 0x6f, 0xa6, 0x83, 0x24, 0x4c, 0x95, 0xbe, 0x79, 0xee, 0xa2} + + p256OrdMul(table[0][:], x, RR) + + // Prepare the table, no need in constant time access, because the + // power is not a secret. (Entry 0 is never used.) + for i := 2; i < 16; i += 2 { + p256OrdSqr(table[i-1][:], table[(i/2)-1][:], 1) + p256OrdMul(table[i][:], table[i-1][:], table[0][:]) + } + + copy(x, table[14][:]) // f + + p256OrdSqr(x[0:32], x[0:32], 4) + p256OrdMul(x[0:32], x[0:32], table[14][:]) // ff + t := make([]byte, 32) + copy(t, x) + + p256OrdSqr(x, x, 8) + p256OrdMul(x, x, t) // ffff + copy(t, x) + + p256OrdSqr(x, x, 16) + p256OrdMul(x, x, t) // ffffffff + copy(t, x) + + p256OrdSqr(x, x, 64) // ffffffff0000000000000000 + p256OrdMul(x, x, t) // ffffffff00000000ffffffff + p256OrdSqr(x, x, 32) // ffffffff00000000ffffffff00000000 + p256OrdMul(x, x, t) // ffffffff00000000ffffffffffffffff + + // Remaining 32 windows + expLo := [32]byte{0xb, 0xc, 0xe, 0x6, 0xf, 0xa, 0xa, 0xd, 0xa, 0x7, 0x1, 0x7, 0x9, 0xe, 0x8, 0x4, + 0xf, 0x3, 0xb, 0x9, 0xc, 0xa, 0xc, 0x2, 0xf, 0xc, 0x6, 0x3, 0x2, 0x5, 0x4, 0xf} + for i := 0; i < 32; i++ { + p256OrdSqr(x, x, 4) + p256OrdMul(x, x, table[expLo[i]-1][:]) + } + + // Multiplying by one in the Montgomery domain converts a Montgomery + // value out of the domain. + one := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + p256OrdMul(x, x, one) + + return new(big.Int).SetBytes(x) +} + +// fromBig converts a *big.Int into a format used by this code. +func fromBig(big *big.Int) []byte { + // This could be done a lot more efficiently... + res := big.Bytes() + if 32 == len(res) { + return res + } + t := make([]byte, 32) + offset := 32 - len(res) + for i := len(res) - 1; i >= 0; i-- { + t[i+offset] = res[i] + } + return t +} + +// p256GetMultiplier makes sure byte array will have 32 byte elements, If the scalar +// is equal or greater than the order of the group, it's reduced modulo that order. +func p256GetMultiplier(in []byte) []byte { + n := new(big.Int).SetBytes(in) + + if n.Cmp(p256Params.N) >= 0 { + n.Mod(n, p256Params.N) + } + return fromBig(n) +} + +// p256MulAsm operates in a Montgomery domain with R = 2^256 mod p, where p is the +// underlying field of the curve. (See initP256 for the value.) Thus rr here is +// R×R mod p. See comment in Inverse about how this is used. +var rr = []byte{0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + +// (This is one, in the Montgomery domain.) +var one = []byte{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} + +func maybeReduceModP(in *big.Int) *big.Int { + if in.Cmp(p256Params.P) < 0 { + return in + } + return new(big.Int).Mod(in, p256Params.P) +} + +func (curve p256CurveFast) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) { + var r1, r2 p256Point + scalarReduced := p256GetMultiplier(baseScalar) + r1IsInfinity := scalarIsZero(scalarReduced) + r1.p256BaseMult(scalarReduced) + + copy(r2.x[:], fromBig(maybeReduceModP(bigX))) + copy(r2.y[:], fromBig(maybeReduceModP(bigY))) + copy(r2.z[:], one) + p256MulAsm(r2.x[:], r2.x[:], rr[:]) + p256MulAsm(r2.y[:], r2.y[:], rr[:]) + + scalarReduced = p256GetMultiplier(scalar) + r2IsInfinity := scalarIsZero(scalarReduced) + r2.p256ScalarMult(p256GetMultiplier(scalar)) + + var sum, double p256Point + pointsEqual := p256PointAddAsm(&sum, &r1, &r2) + p256PointDoubleAsm(&double, &r1) + p256MovCond(&sum, &double, &sum, pointsEqual) + p256MovCond(&sum, &r1, &sum, r2IsInfinity) + p256MovCond(&sum, &r2, &sum, r1IsInfinity) + return sum.p256PointToAffine() +} + +func (curve p256CurveFast) ScalarBaseMult(scalar []byte) (x, y *big.Int) { + var r p256Point + r.p256BaseMult(p256GetMultiplier(scalar)) + return r.p256PointToAffine() +} + +func (curve p256CurveFast) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) { + var r p256Point + copy(r.x[:], fromBig(maybeReduceModP(bigX))) + copy(r.y[:], fromBig(maybeReduceModP(bigY))) + copy(r.z[:], one) + p256MulAsm(r.x[:], r.x[:], rr[:]) + p256MulAsm(r.y[:], r.y[:], rr[:]) + r.p256ScalarMult(p256GetMultiplier(scalar)) + return r.p256PointToAffine() +} + +// scalarIsZero returns 1 if scalar represents the zero value, and zero +// otherwise. +func scalarIsZero(scalar []byte) int { + b := byte(0) + for _, s := range scalar { + b |= s + } + return subtle.ConstantTimeByteEq(b, 0) +} + +func (p *p256Point) p256PointToAffine() (x, y *big.Int) { + zInv := make([]byte, 32) + zInvSq := make([]byte, 32) + + p256Inverse(zInv, p.z[:]) + p256Sqr(zInvSq, zInv) + p256MulAsm(zInv, zInv, zInvSq) + + p256MulAsm(zInvSq, p.x[:], zInvSq) + p256MulAsm(zInv, p.y[:], zInv) + + p256FromMont(zInvSq, zInvSq) + p256FromMont(zInv, zInv) + + return new(big.Int).SetBytes(zInvSq), new(big.Int).SetBytes(zInv) +} + +// p256Inverse sets out to in^-1 mod p. +func p256Inverse(out, in []byte) { + var stack [6 * 32]byte + p2 := stack[32*0 : 32*0+32] + p4 := stack[32*1 : 32*1+32] + p8 := stack[32*2 : 32*2+32] + p16 := stack[32*3 : 32*3+32] + p32 := stack[32*4 : 32*4+32] + + p256Sqr(out, in) + p256MulAsm(p2, out, in) // 3*p + + p256Sqr(out, p2) + p256Sqr(out, out) + p256MulAsm(p4, out, p2) // f*p + + p256Sqr(out, p4) + p256Sqr(out, out) + p256Sqr(out, out) + p256Sqr(out, out) + p256MulAsm(p8, out, p4) // ff*p + + p256Sqr(out, p8) + + for i := 0; i < 7; i++ { + p256Sqr(out, out) + } + p256MulAsm(p16, out, p8) // ffff*p + + p256Sqr(out, p16) + for i := 0; i < 15; i++ { + p256Sqr(out, out) + } + p256MulAsm(p32, out, p16) // ffffffff*p + + p256Sqr(out, p32) + + for i := 0; i < 31; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, in) + + for i := 0; i < 32*4; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, p32) + + for i := 0; i < 32; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, p32) + + for i := 0; i < 16; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, p16) + + for i := 0; i < 8; i++ { + p256Sqr(out, out) + } + p256MulAsm(out, out, p8) + + p256Sqr(out, out) + p256Sqr(out, out) + p256Sqr(out, out) + p256Sqr(out, out) + p256MulAsm(out, out, p4) + + p256Sqr(out, out) + p256Sqr(out, out) + p256MulAsm(out, out, p2) + + p256Sqr(out, out) + p256Sqr(out, out) + p256MulAsm(out, out, in) +} + +func boothW5(in uint) (int, int) { + var s uint = ^((in >> 5) - 1) + var d uint = (1 << 6) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return int(d), int(s & 1) +} + +func boothW7(in uint) (int, int) { + var s uint = ^((in >> 7) - 1) + var d uint = (1 << 8) - in - 1 + d = (d & s) | (in & (^s)) + d = (d >> 1) + (d & 1) + return int(d), int(s & 1) +} + +func initTable() { + p256PreFast = new([37][64]p256Point) //z coordinate not used + basePoint := p256Point{ + x: [32]byte{0x18, 0x90, 0x5f, 0x76, 0xa5, 0x37, 0x55, 0xc6, 0x79, 0xfb, 0x73, 0x2b, 0x77, 0x62, 0x25, 0x10, + 0x75, 0xba, 0x95, 0xfc, 0x5f, 0xed, 0xb6, 0x01, 0x79, 0xe7, 0x30, 0xd4, 0x18, 0xa9, 0x14, 0x3c}, //(p256.x*2^256)%p + y: [32]byte{0x85, 0x71, 0xff, 0x18, 0x25, 0x88, 0x5d, 0x85, 0xd2, 0xe8, 0x86, 0x88, 0xdd, 0x21, 0xf3, 0x25, + 0x8b, 0x4a, 0xb8, 0xe4, 0xba, 0x19, 0xe4, 0x5c, 0xdd, 0xf2, 0x53, 0x57, 0xce, 0x95, 0x56, 0x0a}, //(p256.y*2^256)%p + z: [32]byte{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, //(p256.z*2^256)%p + } + + t1 := new(p256Point) + t2 := new(p256Point) + *t2 = basePoint + + zInv := make([]byte, 32) + zInvSq := make([]byte, 32) + for j := 0; j < 64; j++ { + *t1 = *t2 + for i := 0; i < 37; i++ { + // The window size is 7 so we need to double 7 times. + if i != 0 { + for k := 0; k < 7; k++ { + p256PointDoubleAsm(t1, t1) + } + } + // Convert the point to affine form. (Its values are + // still in Montgomery form however.) + p256Inverse(zInv, t1.z[:]) + p256Sqr(zInvSq, zInv) + p256MulAsm(zInv, zInv, zInvSq) + + p256MulAsm(t1.x[:], t1.x[:], zInvSq) + p256MulAsm(t1.y[:], t1.y[:], zInv) + + copy(t1.z[:], basePoint.z[:]) + // Update the table entry + copy(p256PreFast[i][j].x[:], t1.x[:]) + copy(p256PreFast[i][j].y[:], t1.y[:]) + } + if j == 0 { + p256PointDoubleAsm(t2, &basePoint) + } else { + p256PointAddAsm(t2, t2, &basePoint) + } + } +} + +func (p *p256Point) p256BaseMult(scalar []byte) { + wvalue := (uint(scalar[31]) << 1) & 0xff + sel, sign := boothW7(uint(wvalue)) + p256SelectBase(p, p256PreFast[0][:], sel) + p256NegCond(p, sign) + + copy(p.z[:], one[:]) + var t0 p256Point + + copy(t0.z[:], one[:]) + + index := uint(6) + zero := sel + + for i := 1; i < 37; i++ { + if index < 247 { + wvalue = ((uint(scalar[31-index/8]) >> (index % 8)) + (uint(scalar[31-index/8-1]) << (8 - (index % 8)))) & 0xff + } else { + wvalue = (uint(scalar[31-index/8]) >> (index % 8)) & 0xff + } + index += 7 + sel, sign = boothW7(uint(wvalue)) + p256SelectBase(&t0, p256PreFast[i][:], sel) + p256PointAddAffineAsm(p, p, &t0, sign, sel, zero) + zero |= sel + } +} + +func (p *p256Point) p256ScalarMult(scalar []byte) { + // precomp is a table of precomputed points that stores powers of p + // from p^1 to p^16. + var precomp [16]p256Point + var t0, t1, t2, t3 p256Point + + // Prepare the table + *&precomp[0] = *p + + p256PointDoubleAsm(&t0, p) + p256PointDoubleAsm(&t1, &t0) + p256PointDoubleAsm(&t2, &t1) + p256PointDoubleAsm(&t3, &t2) + *&precomp[1] = t0 // 2 + *&precomp[3] = t1 // 4 + *&precomp[7] = t2 // 8 + *&precomp[15] = t3 // 16 + + p256PointAddAsm(&t0, &t0, p) + p256PointAddAsm(&t1, &t1, p) + p256PointAddAsm(&t2, &t2, p) + *&precomp[2] = t0 // 3 + *&precomp[4] = t1 // 5 + *&precomp[8] = t2 // 9 + + p256PointDoubleAsm(&t0, &t0) + p256PointDoubleAsm(&t1, &t1) + *&precomp[5] = t0 // 6 + *&precomp[9] = t1 // 10 + + p256PointAddAsm(&t2, &t0, p) + p256PointAddAsm(&t1, &t1, p) + *&precomp[6] = t2 // 7 + *&precomp[10] = t1 // 11 + + p256PointDoubleAsm(&t0, &t0) + p256PointDoubleAsm(&t2, &t2) + *&precomp[11] = t0 // 12 + *&precomp[13] = t2 // 14 + + p256PointAddAsm(&t0, &t0, p) + p256PointAddAsm(&t2, &t2, p) + *&precomp[12] = t0 // 13 + *&precomp[14] = t2 // 15 + + // Start scanning the window from top bit + index := uint(254) + var sel, sign int + + wvalue := (uint(scalar[31-index/8]) >> (index % 8)) & 0x3f + sel, _ = boothW5(uint(wvalue)) + p256Select(p, precomp[:], sel) + zero := sel + + for index > 4 { + index -= 5 + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + + if index < 247 { + wvalue = ((uint(scalar[31-index/8]) >> (index % 8)) + (uint(scalar[31-index/8-1]) << (8 - (index % 8)))) & 0x3f + } else { + wvalue = (uint(scalar[31-index/8]) >> (index % 8)) & 0x3f + } + + sel, sign = boothW5(uint(wvalue)) + + p256Select(&t0, precomp[:], sel) + p256NegCond(&t0, sign) + p256PointAddAsm(&t1, p, &t0) + p256MovCond(&t1, &t1, p, sel) + p256MovCond(p, &t1, &t0, zero) + zero |= sel + } + + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + p256PointDoubleAsm(p, p) + + wvalue = (uint(scalar[31]) << 1) & 0x3f + sel, sign = boothW5(uint(wvalue)) + + p256Select(&t0, precomp[:], sel) + p256NegCond(&t0, sign) + p256PointAddAsm(&t1, p, &t0) + p256MovCond(&t1, &t1, p, sel) + p256MovCond(p, &t1, &t0, zero) +} diff --git a/src/crypto/elliptic/p256_test.go b/src/crypto/elliptic/p256_test.go new file mode 100644 index 0000000..694186d --- /dev/null +++ b/src/crypto/elliptic/p256_test.go @@ -0,0 +1,169 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +import ( + "math/big" + "testing" +) + +type scalarMultTest struct { + k string + xIn, yIn string + xOut, yOut string +} + +var p256MultTests = []scalarMultTest{ + { + "2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737", + "023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882ea", + "f93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad", + "4d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3", + "a22d2b7f7818a3563e0f7a76c9bf0921ac55e06e2e4d11795b233824b1db8cc0", + }, + { + "313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd", + "cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06", + "a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031", + "831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f17991", + "93f90934cd0ef2c698cc471c60a93524e87ab31ca2412252337f364513e43684", + }, +} + +func TestP256BaseMult(t *testing.T) { + p256 := P256() + p256Generic := p256.Params() + + scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1) + for _, e := range p224BaseMultTests { + k, _ := new(big.Int).SetString(e.k, 10) + scalars = append(scalars, k) + } + k := new(big.Int).SetInt64(1) + k.Lsh(k, 500) + scalars = append(scalars, k) + + for i, k := range scalars { + x, y := p256.ScalarBaseMult(k.Bytes()) + x2, y2 := p256Generic.ScalarBaseMult(k.Bytes()) + if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 { + t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, x, y, x2, y2) + } + + if testing.Short() && i > 5 { + break + } + } +} + +func TestP256Mult(t *testing.T) { + p256 := P256() + p256Generic := p256.Params() + + for i, e := range p224BaseMultTests { + x, _ := new(big.Int).SetString(e.x, 16) + y, _ := new(big.Int).SetString(e.y, 16) + k, _ := new(big.Int).SetString(e.k, 10) + + xx, yy := p256.ScalarMult(x, y, k.Bytes()) + xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes()) + if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 { + t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2) + } + if testing.Short() && i > 5 { + break + } + } + + for i, e := range p256MultTests { + x, _ := new(big.Int).SetString(e.xIn, 16) + y, _ := new(big.Int).SetString(e.yIn, 16) + k, _ := new(big.Int).SetString(e.k, 16) + expectedX, _ := new(big.Int).SetString(e.xOut, 16) + expectedY, _ := new(big.Int).SetString(e.yOut, 16) + + xx, yy := p256.ScalarMult(x, y, k.Bytes()) + if xx.Cmp(expectedX) != 0 || yy.Cmp(expectedY) != 0 { + t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, expectedX, expectedY) + } + } +} + +type synthCombinedMult struct { + Curve +} + +func (s synthCombinedMult) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) { + x1, y1 := s.ScalarBaseMult(baseScalar) + x2, y2 := s.ScalarMult(bigX, bigY, scalar) + return s.Add(x1, y1, x2, y2) +} + +func TestP256CombinedMult(t *testing.T) { + type combinedMult interface { + Curve + CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) + } + + p256, ok := P256().(combinedMult) + if !ok { + p256 = &synthCombinedMult{P256()} + } + + gx := p256.Params().Gx + gy := p256.Params().Gy + + zero := make([]byte, 32) + one := make([]byte, 32) + one[31] = 1 + two := make([]byte, 32) + two[31] = 2 + + // 0×G + 0×G = ∞ + x, y := p256.CombinedMult(gx, gy, zero, zero) + if x.Sign() != 0 || y.Sign() != 0 { + t.Errorf("0×G + 0×G = (%d, %d), should be ∞", x, y) + } + + // 1×G + 0×G = G + x, y = p256.CombinedMult(gx, gy, one, zero) + if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 { + t.Errorf("1×G + 0×G = (%d, %d), should be (%d, %d)", x, y, gx, gy) + } + + // 0×G + 1×G = G + x, y = p256.CombinedMult(gx, gy, zero, one) + if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 { + t.Errorf("0×G + 1×G = (%d, %d), should be (%d, %d)", x, y, gx, gy) + } + + // 1×G + 1×G = 2×G + x, y = p256.CombinedMult(gx, gy, one, one) + ggx, ggy := p256.ScalarBaseMult(two) + if x.Cmp(ggx) != 0 || y.Cmp(ggy) != 0 { + t.Errorf("1×G + 1×G = (%d, %d), should be (%d, %d)", x, y, ggx, ggy) + } + + minusOne := new(big.Int).Sub(p256.Params().N, big.NewInt(1)) + // 1×G + (-1)×G = ∞ + x, y = p256.CombinedMult(gx, gy, one, minusOne.Bytes()) + if x.Sign() != 0 || y.Sign() != 0 { + t.Errorf("1×G + (-1)×G = (%d, %d), should be ∞", x, y) + } +} + +func TestIssue52075(t *testing.T) { + Gx, Gy := P256().Params().Gx, P256().Params().Gy + scalar := make([]byte, 33) + scalar[32] = 1 + x, y := P256().ScalarBaseMult(scalar) + if x.Cmp(Gx) != 0 || y.Cmp(Gy) != 0 { + t.Errorf("unexpected output (%v,%v)", x, y) + } + x, y = P256().ScalarMult(Gx, Gy, scalar) + if x.Cmp(Gx) != 0 || y.Cmp(Gy) != 0 { + t.Errorf("unexpected output (%v,%v)", x, y) + } +} diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go new file mode 100644 index 0000000..587991e --- /dev/null +++ b/src/crypto/elliptic/p521.go @@ -0,0 +1,264 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +import ( + "crypto/elliptic/internal/fiat" + "math/big" +) + +type p521Curve struct { + *CurveParams +} + +var p521 p521Curve +var p521Params *CurveParams + +func initP521() { + // See FIPS 186-3, section D.2.5 + p521.CurveParams = &CurveParams{Name: "P-521"} + p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10) + p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10) + p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16) + p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16) + p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16) + p521.BitSize = 521 +} + +func (curve p521Curve) Params() *CurveParams { + return curve.CurveParams +} + +func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { + if x.Sign() < 0 || x.Cmp(curve.P) >= 0 || + y.Sign() < 0 || y.Cmp(curve.P) >= 0 { + return false + } + + x1 := bigIntToFiatP521(x) + y1 := bigIntToFiatP521(y) + b := bigIntToFiatP521(curve.B) // TODO: precompute this value. + + // x³ - 3x + b. + x3 := new(fiat.P521Element).Square(x1) + x3.Mul(x3, x1) + + threeX := new(fiat.P521Element).Add(x1, x1) + threeX.Add(threeX, x1) + + x3.Sub(x3, threeX) + x3.Add(x3, b) + + // y² = x³ - 3x + b + y2 := new(fiat.P521Element).Square(y1) + + return x3.Equal(y2) == 1 +} + +type p521Point struct { + x, y, z *fiat.P521Element +} + +func fiatP521ToBigInt(x *fiat.P521Element) *big.Int { + xBytes := x.Bytes() + for i := range xBytes[:len(xBytes)/2] { + xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i] + } + return new(big.Int).SetBytes(xBytes) +} + +// affineFromJacobian brings a point in Jacobian coordinates back to affine +// coordinates, with (0, 0) representing infinity by convention. It also goes +// back to big.Int values to match the exposed API. +func (curve p521Curve) affineFromJacobian(p *p521Point) (x, y *big.Int) { + if p.z.IsZero() == 1 { + return new(big.Int), new(big.Int) + } + + zinv := new(fiat.P521Element).Invert(p.z) + zinvsq := new(fiat.P521Element).Mul(zinv, zinv) + + xx := new(fiat.P521Element).Mul(p.x, zinvsq) + zinvsq.Mul(zinvsq, zinv) + yy := new(fiat.P521Element).Mul(p.y, zinvsq) + + return fiatP521ToBigInt(xx), fiatP521ToBigInt(yy) +} + +func bigIntToFiatP521(x *big.Int) *fiat.P521Element { + xBytes := new(big.Int).Mod(x, p521.P).FillBytes(make([]byte, 66)) + for i := range xBytes[:len(xBytes)/2] { + xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i] + } + x1, err := new(fiat.P521Element).SetBytes(xBytes) + if err != nil { + // The input is reduced modulo P and encoded in a fixed size bytes + // slice, this should be impossible. + panic("internal error: bigIntToFiatP521") + } + return x1 +} + +// jacobianFromAffine converts (x, y) affine coordinates into (x, y, z) Jacobian +// coordinates. It also converts from big.Int to fiat, which is necessarily a +// messy and variable-time operation, which we can't avoid due to the exposed API. +func (curve p521Curve) jacobianFromAffine(x, y *big.Int) *p521Point { + // (0, 0) is by convention the point at infinity, which can't be represented + // in affine coordinates, but is (0, 0, 0) in Jacobian. + if x.Sign() == 0 && y.Sign() == 0 { + return &p521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + } + } + return &p521Point{ + x: bigIntToFiatP521(x), + y: bigIntToFiatP521(y), + z: new(fiat.P521Element).One(), + } +} + +func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + p1 := curve.jacobianFromAffine(x1, y1) + p2 := curve.jacobianFromAffine(x2, y2) + return curve.affineFromJacobian(p1.addJacobian(p1, p2)) +} + +// addJacobian sets q = p1 + p2, and returns q. The points may overlap. +func (q *p521Point) addJacobian(p1, p2 *p521Point) *p521Point { + // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl + z1IsZero := p1.z.IsZero() + z2IsZero := p2.z.IsZero() + + z1z1 := new(fiat.P521Element).Square(p1.z) + z2z2 := new(fiat.P521Element).Square(p2.z) + + u1 := new(fiat.P521Element).Mul(p1.x, z2z2) + u2 := new(fiat.P521Element).Mul(p2.x, z1z1) + h := new(fiat.P521Element).Sub(u2, u1) + xEqual := h.IsZero() == 1 + i := new(fiat.P521Element).Add(h, h) + i.Square(i) + j := new(fiat.P521Element).Mul(h, i) + + s1 := new(fiat.P521Element).Mul(p1.y, p2.z) + s1.Mul(s1, z2z2) + s2 := new(fiat.P521Element).Mul(p2.y, p1.z) + s2.Mul(s2, z1z1) + r := new(fiat.P521Element).Sub(s2, s1) + yEqual := r.IsZero() == 1 + if xEqual && yEqual && z1IsZero == 0 && z2IsZero == 0 { + return q.doubleJacobian(p1) + } + r.Add(r, r) + v := new(fiat.P521Element).Mul(u1, i) + + x := new(fiat.P521Element).Set(r) + x.Square(x) + x.Sub(x, j) + x.Sub(x, v) + x.Sub(x, v) + + y := new(fiat.P521Element).Set(r) + v.Sub(v, x) + y.Mul(y, v) + s1.Mul(s1, j) + s1.Add(s1, s1) + y.Sub(y, s1) + + z := new(fiat.P521Element).Add(p1.z, p2.z) + z.Square(z) + z.Sub(z, z1z1) + z.Sub(z, z2z2) + z.Mul(z, h) + + x.Select(p2.x, x, z1IsZero) + x.Select(p1.x, x, z2IsZero) + y.Select(p2.y, y, z1IsZero) + y.Select(p1.y, y, z2IsZero) + z.Select(p2.z, z, z1IsZero) + z.Select(p1.z, z, z2IsZero) + + q.x.Set(x) + q.y.Set(y) + q.z.Set(z) + return q +} + +func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + p := curve.jacobianFromAffine(x1, y1) + return curve.affineFromJacobian(p.doubleJacobian(p)) +} + +// doubleJacobian sets q = p + p, and returns q. The points may overlap. +func (q *p521Point) doubleJacobian(p *p521Point) *p521Point { + // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + delta := new(fiat.P521Element).Square(p.z) + gamma := new(fiat.P521Element).Square(p.y) + alpha := new(fiat.P521Element).Sub(p.x, delta) + alpha2 := new(fiat.P521Element).Add(p.x, delta) + alpha.Mul(alpha, alpha2) + alpha2.Set(alpha) + alpha.Add(alpha, alpha) + alpha.Add(alpha, alpha2) + + beta := alpha2.Mul(p.x, gamma) + + q.x.Square(alpha) + beta8 := new(fiat.P521Element).Add(beta, beta) + beta8.Add(beta8, beta8) + beta8.Add(beta8, beta8) + q.x.Sub(q.x, beta8) + + q.z.Add(p.y, p.z) + q.z.Square(q.z) + q.z.Sub(q.z, gamma) + q.z.Sub(q.z, delta) + + beta.Add(beta, beta) + beta.Add(beta, beta) + beta.Sub(beta, q.x) + q.y.Mul(alpha, beta) + + gamma.Square(gamma) + gamma.Add(gamma, gamma) + gamma.Add(gamma, gamma) + gamma.Add(gamma, gamma) + + q.y.Sub(q.y, gamma) + + return q +} + +func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + B := curve.jacobianFromAffine(Bx, By) + p, t := &p521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + }, &p521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + } + + for _, byte := range scalar { + for bitNum := 0; bitNum < 8; bitNum++ { + p.doubleJacobian(p) + bit := (byte >> (7 - bitNum)) & 1 + t.addJacobian(p, B) + p.x.Select(t.x, p.x, int(bit)) + p.y.Select(t.y, p.y, int(bit)) + p.z.Select(t.z, p.z, int(bit)) + } + } + + return curve.affineFromJacobian(p) +} + +func (curve p521Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { + return curve.ScalarMult(curve.Gx, curve.Gy, k) +} diff --git a/src/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go new file mode 100644 index 0000000..cdda33c --- /dev/null +++ b/src/crypto/hmac/hmac.go @@ -0,0 +1,172 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as +defined in U.S. Federal Information Processing Standards Publication 198. +An HMAC is a cryptographic hash that uses a key to sign a message. +The receiver verifies the hash by recomputing it using the same key. + +Receivers should be careful to use Equal to compare MACs in order to avoid +timing side-channels: + + // ValidMAC reports whether messageMAC is a valid HMAC tag for message. + func ValidMAC(message, messageMAC, key []byte) bool { + mac := hmac.New(sha256.New, key) + mac.Write(message) + expectedMAC := mac.Sum(nil) + return hmac.Equal(messageMAC, expectedMAC) + } +*/ +package hmac + +import ( + "crypto/subtle" + "hash" +) + +// FIPS 198-1: +// https://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf + +// key is zero padded to the block size of the hash function +// ipad = 0x36 byte repeated for key length +// opad = 0x5c byte repeated for key length +// hmac = H([key ^ opad] H([key ^ ipad] text)) + +// Marshalable is the combination of encoding.BinaryMarshaler and +// encoding.BinaryUnmarshaler. Their method definitions are repeated here to +// avoid a dependency on the encoding package. +type marshalable interface { + MarshalBinary() ([]byte, error) + UnmarshalBinary([]byte) error +} + +type hmac struct { + opad, ipad []byte + outer, inner hash.Hash + + // If marshaled is true, then opad and ipad do not contain a padded + // copy of the key, but rather the marshaled state of outer/inner after + // opad/ipad has been fed into it. + marshaled bool +} + +func (h *hmac) Sum(in []byte) []byte { + origLen := len(in) + in = h.inner.Sum(in) + + if h.marshaled { + if err := h.outer.(marshalable).UnmarshalBinary(h.opad); err != nil { + panic(err) + } + } else { + h.outer.Reset() + h.outer.Write(h.opad) + } + h.outer.Write(in[origLen:]) + return h.outer.Sum(in[:origLen]) +} + +func (h *hmac) Write(p []byte) (n int, err error) { + return h.inner.Write(p) +} + +func (h *hmac) Size() int { return h.outer.Size() } +func (h *hmac) BlockSize() int { return h.inner.BlockSize() } + +func (h *hmac) Reset() { + if h.marshaled { + if err := h.inner.(marshalable).UnmarshalBinary(h.ipad); err != nil { + panic(err) + } + return + } + + h.inner.Reset() + h.inner.Write(h.ipad) + + // If the underlying hash is marshalable, we can save some time by + // saving a copy of the hash state now, and restoring it on future + // calls to Reset and Sum instead of writing ipad/opad every time. + // + // If either hash is unmarshalable for whatever reason, + // it's safe to bail out here. + marshalableInner, innerOK := h.inner.(marshalable) + if !innerOK { + return + } + marshalableOuter, outerOK := h.outer.(marshalable) + if !outerOK { + return + } + + imarshal, err := marshalableInner.MarshalBinary() + if err != nil { + return + } + + h.outer.Reset() + h.outer.Write(h.opad) + omarshal, err := marshalableOuter.MarshalBinary() + if err != nil { + return + } + + // Marshaling succeeded; save the marshaled state for later + h.ipad = imarshal + h.opad = omarshal + h.marshaled = true +} + +// New returns a new HMAC hash using the given hash.Hash type and key. +// New functions like sha256.New from crypto/sha256 can be used as h. +// h must return a new Hash every time it is called. +// Note that unlike other hash implementations in the standard library, +// the returned Hash does not implement encoding.BinaryMarshaler +// or encoding.BinaryUnmarshaler. +func New(h func() hash.Hash, key []byte) hash.Hash { + hm := new(hmac) + hm.outer = h() + hm.inner = h() + unique := true + func() { + defer func() { + // The comparison might panic if the underlying types are not comparable. + _ = recover() + }() + if hm.outer == hm.inner { + unique = false + } + }() + if !unique { + panic("crypto/hmac: hash generation function does not produce unique values") + } + blocksize := hm.inner.BlockSize() + hm.ipad = make([]byte, blocksize) + hm.opad = make([]byte, blocksize) + if len(key) > blocksize { + // If key is too big, hash it. + hm.outer.Write(key) + key = hm.outer.Sum(nil) + } + copy(hm.ipad, key) + copy(hm.opad, key) + for i := range hm.ipad { + hm.ipad[i] ^= 0x36 + } + for i := range hm.opad { + hm.opad[i] ^= 0x5c + } + hm.inner.Write(hm.ipad) + + return hm +} + +// Equal compares two MACs for equality without leaking timing information. +func Equal(mac1, mac2 []byte) bool { + // We don't have to be constant time if the lengths of the MACs are + // different as that suggests that a completely different hash function + // was used. + return subtle.ConstantTimeCompare(mac1, mac2) == 1 +} diff --git a/src/crypto/hmac/hmac_test.go b/src/crypto/hmac/hmac_test.go new file mode 100644 index 0000000..25e67d7 --- /dev/null +++ b/src/crypto/hmac/hmac_test.go @@ -0,0 +1,629 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hmac + +import ( + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "fmt" + "hash" + "testing" +) + +type hmacTest struct { + hash func() hash.Hash + key []byte + in []byte + out string + size int + blocksize int +} + +var hmacTests = []hmacTest{ + // Tests from US FIPS 198 + // https://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf + { + sha1.New, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + }, + []byte("Sample #1"), + "4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a", + sha1.Size, + sha1.BlockSize, + }, + { + sha1.New, + []byte{ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, + }, + []byte("Sample #2"), + "0922d3405faa3d194f82a45830737d5cc6c75d24", + sha1.Size, + sha1.BlockSize, + }, + { + sha1.New, + []byte{ + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, + }, + []byte("Sample #3"), + "bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aa", + sha1.Size, + sha1.BlockSize, + }, + + // Test from Plan 9. + { + md5.New, + []byte("Jefe"), + []byte("what do ya want for nothing?"), + "750c783e6ab0b503eaa86e310a5db738", + md5.Size, + md5.BlockSize, + }, + + // Tests from RFC 4231 + { + sha256.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, + }, + []byte("Hi There"), + "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", + sha256.Size, + sha256.BlockSize, + }, + { + sha256.New, + []byte("Jefe"), + []byte("what do ya want for nothing?"), + "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843", + sha256.Size, + sha256.BlockSize, + }, + { + sha256.New, + []byte{ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, + }, + []byte{ + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, + }, + "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe", + sha256.Size, + sha256.BlockSize, + }, + { + sha256.New, + []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, + }, + []byte{ + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, + }, + "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b", + sha256.Size, + sha256.BlockSize, + }, + { + sha256.New, + []byte{ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, + }, + []byte("Test Using Larger Than Block-Size Key - Hash Key First"), + "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54", + sha256.Size, + sha256.BlockSize, + }, + { + sha256.New, + []byte{ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, + }, + []byte("This is a test using a larger than block-size key " + + "and a larger than block-size data. The key needs to " + + "be hashed before being used by the HMAC algorithm."), + "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2", + sha256.Size, + sha256.BlockSize, + }, + + // Tests from https://csrc.nist.gov/groups/ST/toolkit/examples.html + // (truncated tag tests are left out) + { + sha1.New, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + }, + []byte("Sample message for keylen=blocklen"), + "5fd596ee78d5553c8ff4e72d266dfd192366da29", + sha1.Size, + sha1.BlockSize, + }, + { + sha1.New, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, + }, + []byte("Sample message for keylen 0 && len(y) > 0 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/src/crypto/internal/subtle/aliasing_appengine.go b/src/crypto/internal/subtle/aliasing_appengine.go new file mode 100644 index 0000000..35b442f --- /dev/null +++ b/src/crypto/internal/subtle/aliasing_appengine.go @@ -0,0 +1,38 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build appengine +// +build appengine + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +// +// This is a mirror of golang.org/x/crypto/internal/subtle. +package subtle // import "crypto/internal/subtle" + +// This is the Google App Engine standard variant based on reflect +// because the unsafe package and cgo are disallowed. + +import "reflect" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && + reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/src/crypto/internal/subtle/aliasing_test.go b/src/crypto/internal/subtle/aliasing_test.go new file mode 100644 index 0000000..f1e7238 --- /dev/null +++ b/src/crypto/internal/subtle/aliasing_test.go @@ -0,0 +1,50 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle_test + +import ( + "testing" + + "crypto/internal/subtle" +) + +var a, b [100]byte + +var aliasingTests = []struct { + x, y []byte + anyOverlap, inexactOverlap bool +}{ + {a[:], b[:], false, false}, + {a[:], b[:0], false, false}, + {a[:], b[:50], false, false}, + {a[40:50], a[50:60], false, false}, + {a[40:50], a[60:70], false, false}, + {a[:51], a[50:], true, true}, + {a[:], a[:], true, false}, + {a[:50], a[:60], true, false}, + {a[:], nil, false, false}, + {nil, nil, false, false}, + {a[:], a[:0], false, false}, + {a[:10], a[:10:20], true, false}, + {a[:10], a[5:10:20], true, true}, +} + +func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) { + any := subtle.AnyOverlap(x, y) + if any != anyOverlap { + t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any) + } + inexact := subtle.InexactOverlap(x, y) + if inexact != inexactOverlap { + t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any) + } +} + +func TestAliasing(t *testing.T) { + for i, tt := range aliasingTests { + testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap) + testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap) + } +} diff --git a/src/crypto/issue21104_test.go b/src/crypto/issue21104_test.go new file mode 100644 index 0000000..b4276df --- /dev/null +++ b/src/crypto/issue21104_test.go @@ -0,0 +1,61 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package crypto + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rc4" + "testing" +) + +func TestRC4OutOfBoundsWrite(t *testing.T) { + // This cipherText is encrypted "0123456789" + cipherText := []byte{238, 41, 187, 114, 151, 2, 107, 13, 178, 63} + cipher, err := rc4.NewCipher([]byte{0}) + if err != nil { + panic(err) + } + test(t, "RC4", cipherText, cipher.XORKeyStream) +} +func TestCTROutOfBoundsWrite(t *testing.T) { + testBlock(t, "CTR", cipher.NewCTR) +} +func TestOFBOutOfBoundsWrite(t *testing.T) { + testBlock(t, "OFB", cipher.NewOFB) +} +func TestCFBEncryptOutOfBoundsWrite(t *testing.T) { + testBlock(t, "CFB Encrypt", cipher.NewCFBEncrypter) +} +func TestCFBDecryptOutOfBoundsWrite(t *testing.T) { + testBlock(t, "CFB Decrypt", cipher.NewCFBDecrypter) +} +func testBlock(t *testing.T, name string, newCipher func(cipher.Block, []byte) cipher.Stream) { + // This cipherText is encrypted "0123456789" + cipherText := []byte{86, 216, 121, 231, 219, 191, 26, 12, 176, 117} + var iv, key [16]byte + block, err := aes.NewCipher(key[:]) + if err != nil { + panic(err) + } + stream := newCipher(block, iv[:]) + test(t, name, cipherText, stream.XORKeyStream) +} +func test(t *testing.T, name string, cipherText []byte, xor func([]byte, []byte)) { + want := "abcdefghij" + plainText := []byte(want) + shorterLen := len(cipherText) / 2 + defer func() { + err := recover() + if err == nil { + t.Errorf("%v XORKeyStream expected to panic on len(dst) < len(src), but didn't", name) + } + const plain = "0123456789" + if plainText[shorterLen] == plain[shorterLen] { + t.Errorf("%v XORKeyStream did out of bounds write, want %v, got %v", name, want, string(plainText)) + } + }() + xor(plainText[:shorterLen], cipherText) +} diff --git a/src/crypto/md5/example_test.go b/src/crypto/md5/example_test.go new file mode 100644 index 0000000..af8c1bf --- /dev/null +++ b/src/crypto/md5/example_test.go @@ -0,0 +1,42 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package md5_test + +import ( + "crypto/md5" + "fmt" + "io" + "log" + "os" +) + +func ExampleNew() { + h := md5.New() + io.WriteString(h, "The fog is getting thicker!") + io.WriteString(h, "And Leon's getting laaarger!") + fmt.Printf("%x", h.Sum(nil)) + // Output: e2c569be17396eca2a2e3c11578123ed +} + +func ExampleSum() { + data := []byte("These pretzels are making me thirsty.") + fmt.Printf("%x", md5.Sum(data)) + // Output: b0804ec967f48520697662a204f5fe72 +} + +func ExampleNew_file() { + f, err := os.Open("file.txt") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + h := md5.New() + if _, err := io.Copy(h, f); err != nil { + log.Fatal(err) + } + + fmt.Printf("%x", h.Sum(nil)) +} diff --git a/src/crypto/md5/gen.go b/src/crypto/md5/gen.go new file mode 100644 index 0000000..29729fa --- /dev/null +++ b/src/crypto/md5/gen.go @@ -0,0 +1,260 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +// This program generates md5block.go +// Invoke as +// +// go run gen.go -output md5block.go + +package main + +import ( + "bytes" + "flag" + "go/format" + "log" + "os" + "strings" + "text/template" +) + +var filename = flag.String("output", "md5block.go", "output file name") + +func main() { + flag.Parse() + + var buf bytes.Buffer + + t := template.Must(template.New("main").Funcs(funcs).Parse(program)) + if err := t.Execute(&buf, data); err != nil { + log.Fatal(err) + } + + data, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + err = os.WriteFile(*filename, data, 0644) + if err != nil { + log.Fatal(err) + } +} + +type Data struct { + a, b, c, d string + Shift1 []int + Shift2 []int + Shift3 []int + Shift4 []int + Table1 []uint32 + Table2 []uint32 + Table3 []uint32 + Table4 []uint32 +} + +var funcs = template.FuncMap{ + "dup": dup, + "relabel": relabel, + "rotate": rotate, + "idx": idx, + "seq": seq, +} + +func dup(count int, x []int) []int { + var out []int + for i := 0; i < count; i++ { + out = append(out, x...) + } + return out +} + +func relabel(s string) string { + return strings.NewReplacer("arg0", data.a, "arg1", data.b, "arg2", data.c, "arg3", data.d).Replace(s) +} + +func rotate() string { + data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c + return "" // no output +} + +func idx(round, index int) int { + v := 0 + switch round { + case 1: + v = index + case 2: + v = (1 + 5*index) & 15 + case 3: + v = (5 + 3*index) & 15 + case 4: + v = (7 * index) & 15 + } + return v +} + +func seq(i int) []int { + s := make([]int, i) + for i := range s { + s[i] = i + } + return s +} + +var data = Data{ + a: "a", + b: "b", + c: "c", + d: "d", + Shift1: []int{7, 12, 17, 22}, + Shift2: []int{5, 9, 14, 20}, + Shift3: []int{4, 11, 16, 23}, + Shift4: []int{6, 10, 15, 21}, + + // table[i] = int((1<<32) * abs(sin(i+1 radians))). + Table1: []uint32{ + // round 1 + 0xd76aa478, + 0xe8c7b756, + 0x242070db, + 0xc1bdceee, + 0xf57c0faf, + 0x4787c62a, + 0xa8304613, + 0xfd469501, + 0x698098d8, + 0x8b44f7af, + 0xffff5bb1, + 0x895cd7be, + 0x6b901122, + 0xfd987193, + 0xa679438e, + 0x49b40821, + }, + Table2: []uint32{ + // round 2 + 0xf61e2562, + 0xc040b340, + 0x265e5a51, + 0xe9b6c7aa, + 0xd62f105d, + 0x2441453, + 0xd8a1e681, + 0xe7d3fbc8, + 0x21e1cde6, + 0xc33707d6, + 0xf4d50d87, + 0x455a14ed, + 0xa9e3e905, + 0xfcefa3f8, + 0x676f02d9, + 0x8d2a4c8a, + }, + Table3: []uint32{ + // round3 + 0xfffa3942, + 0x8771f681, + 0x6d9d6122, + 0xfde5380c, + 0xa4beea44, + 0x4bdecfa9, + 0xf6bb4b60, + 0xbebfbc70, + 0x289b7ec6, + 0xeaa127fa, + 0xd4ef3085, + 0x4881d05, + 0xd9d4d039, + 0xe6db99e5, + 0x1fa27cf8, + 0xc4ac5665, + }, + Table4: []uint32{ + // round 4 + 0xf4292244, + 0x432aff97, + 0xab9423a7, + 0xfc93a039, + 0x655b59c3, + 0x8f0ccc92, + 0xffeff47d, + 0x85845dd1, + 0x6fa87e4f, + 0xfe2ce6e0, + 0xa3014314, + 0x4e0811a1, + 0xf7537e82, + 0xbd3af235, + 0x2ad7d2bb, + 0xeb86d391, + }, +} + +var program = `// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by go run gen.go -output md5block.go; DO NOT EDIT. + +package md5 + +import ( + "encoding/binary" + "math/bits" +) + +func blockGeneric(dig *digest, p []byte) { + // load state + a, b, c, d := dig.s[0], dig.s[1], dig.s[2], dig.s[3] + + for i := 0; i <= len(p)-BlockSize; i += BlockSize { + // eliminate bounds checks on p + q := p[i:] + q = q[:BlockSize:BlockSize] + + // save current state + aa, bb, cc, dd := a, b, c, d + + // load input block + {{range $i := seq 16 -}} + {{printf "x%x := binary.LittleEndian.Uint32(q[4*%#x:])" $i $i}} + {{end}} + + // round 1 + {{range $i, $s := dup 4 .Shift1 -}} + {{printf "arg0 = arg1 + bits.RotateLeft32((((arg2^arg3)&arg1)^arg3)+arg0+x%x+%#08x, %d)" (idx 1 $i) (index $.Table1 $i) $s | relabel}} + {{rotate -}} + {{end}} + + // round 2 + {{range $i, $s := dup 4 .Shift2 -}} + {{printf "arg0 = arg1 + bits.RotateLeft32((((arg1^arg2)&arg3)^arg2)+arg0+x%x+%#08x, %d)" (idx 2 $i) (index $.Table2 $i) $s | relabel}} + {{rotate -}} + {{end}} + + // round 3 + {{range $i, $s := dup 4 .Shift3 -}} + {{printf "arg0 = arg1 + bits.RotateLeft32((arg1^arg2^arg3)+arg0+x%x+%#08x, %d)" (idx 3 $i) (index $.Table3 $i) $s | relabel}} + {{rotate -}} + {{end}} + + // round 4 + {{range $i, $s := dup 4 .Shift4 -}} + {{printf "arg0 = arg1 + bits.RotateLeft32((arg2^(arg1|^arg3))+arg0+x%x+%#08x, %d)" (idx 4 $i) (index $.Table4 $i) $s | relabel}} + {{rotate -}} + {{end}} + + // add saved state + a += aa + b += bb + c += cc + d += dd + } + + // save state + dig.s[0], dig.s[1], dig.s[2], dig.s[3] = a, b, c, d +} +` diff --git a/src/crypto/md5/md5.go b/src/crypto/md5/md5.go new file mode 100644 index 0000000..0115784 --- /dev/null +++ b/src/crypto/md5/md5.go @@ -0,0 +1,195 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go -output md5block.go + +// Package md5 implements the MD5 hash algorithm as defined in RFC 1321. +// +// MD5 is cryptographically broken and should not be used for secure +// applications. +package md5 + +import ( + "crypto" + "encoding/binary" + "errors" + "hash" +) + +func init() { + crypto.RegisterHash(crypto.MD5, New) +} + +// The size of an MD5 checksum in bytes. +const Size = 16 + +// The blocksize of MD5 in bytes. +const BlockSize = 64 + +const ( + init0 = 0x67452301 + init1 = 0xEFCDAB89 + init2 = 0x98BADCFE + init3 = 0x10325476 +) + +// digest represents the partial evaluation of a checksum. +type digest struct { + s [4]uint32 + x [BlockSize]byte + nx int + len uint64 +} + +func (d *digest) Reset() { + d.s[0] = init0 + d.s[1] = init1 + d.s[2] = init2 + d.s[3] = init3 + d.nx = 0 + d.len = 0 +} + +const ( + magic = "md5\x01" + marshaledSize = len(magic) + 4*4 + BlockSize + 8 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + b = appendUint32(b, d.s[0]) + b = appendUint32(b, d.s[1]) + b = appendUint32(b, d.s[2]) + b = appendUint32(b, d.s[3]) + b = append(b, d.x[:d.nx]...) + b = b[:len(b)+len(d.x)-d.nx] // already zero + b = appendUint64(b, d.len) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/md5: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/md5: invalid hash state size") + } + b = b[len(magic):] + b, d.s[0] = consumeUint32(b) + b, d.s[1] = consumeUint32(b) + b, d.s[2] = consumeUint32(b) + b, d.s[3] = consumeUint32(b) + b = b[copy(d.x[:], b):] + b, d.len = consumeUint64(b) + d.nx = int(d.len % BlockSize) + return nil +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + return b[8:], binary.BigEndian.Uint64(b[0:8]) +} + +func consumeUint32(b []byte) ([]byte, uint32) { + return b[4:], binary.BigEndian.Uint32(b[0:4]) +} + +// New returns a new hash.Hash computing the MD5 checksum. The Hash also +// implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to +// marshal and unmarshal the internal state of the hash. +func New() hash.Hash { + d := new(digest) + d.Reset() + return d +} + +func (d *digest) Size() int { return Size } + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Write(p []byte) (nn int, err error) { + // Note that we currently call block or blockGeneric + // directly (guarded using haveAsm) because this allows + // escape analysis to see that p and d don't escape. + nn = len(p) + d.len += uint64(nn) + if d.nx > 0 { + n := copy(d.x[d.nx:], p) + d.nx += n + if d.nx == BlockSize { + if haveAsm { + block(d, d.x[:]) + } else { + blockGeneric(d, d.x[:]) + } + d.nx = 0 + } + p = p[n:] + } + if len(p) >= BlockSize { + n := len(p) &^ (BlockSize - 1) + if haveAsm { + block(d, p[:n]) + } else { + blockGeneric(d, p[:n]) + } + p = p[n:] + } + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d so that caller can keep writing and summing. + d0 := *d + hash := d0.checkSum() + return append(in, hash[:]...) +} + +func (d *digest) checkSum() [Size]byte { + // Append 0x80 to the end of the message and then append zeros + // until the length is a multiple of 56 bytes. Finally append + // 8 bytes representing the message length in bits. + // + // 1 byte end marker :: 0-63 padding bytes :: 8 byte length + tmp := [1 + 63 + 8]byte{0x80} + pad := (55 - d.len) % 64 // calculate number of padding bytes + binary.LittleEndian.PutUint64(tmp[1+pad:], d.len<<3) // append length in bits + d.Write(tmp[:1+pad+8]) + + // The previous write ensures that a whole number of + // blocks (i.e. a multiple of 64 bytes) have been hashed. + if d.nx != 0 { + panic("d.nx != 0") + } + + var digest [Size]byte + binary.LittleEndian.PutUint32(digest[0:], d.s[0]) + binary.LittleEndian.PutUint32(digest[4:], d.s[1]) + binary.LittleEndian.PutUint32(digest[8:], d.s[2]) + binary.LittleEndian.PutUint32(digest[12:], d.s[3]) + return digest +} + +// Sum returns the MD5 checksum of the data. +func Sum(data []byte) [Size]byte { + var d digest + d.Reset() + d.Write(data) + return d.checkSum() +} diff --git a/src/crypto/md5/md5_test.go b/src/crypto/md5/md5_test.go new file mode 100644 index 0000000..acd456a --- /dev/null +++ b/src/crypto/md5/md5_test.go @@ -0,0 +1,280 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package md5 + +import ( + "bytes" + "crypto/rand" + "encoding" + "fmt" + "hash" + "io" + "testing" + "unsafe" +) + +type md5Test struct { + out string + in string + halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal +} + +var golden = []md5Test{ + {"d41d8cd98f00b204e9800998ecf8427e", "", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, + {"0cc175b9c0f1b6a831c399e269772661", "a", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, + {"187ef4436122d1cc2f40dc2b92f0eba0", "ab", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tva\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"}, + {"900150983cd24fb0d6963f7d28e17f72", "abc", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tva\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"}, + {"e2fc714c4727ee9395f324cd2e7f331f", "abcd", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"}, + {"ab56b4d92b40713acc5af89985d4b786", "abcde", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"}, + {"e80b5017098950fc58aad83c8c14978e", "abcdef", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"}, + {"7ac66c0f148de9519b8bd264312c4d64", "abcdefg", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"}, + {"e8dc4081b13434b45189a720b77b6818", "abcdefgh", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"}, + {"8aa99b1f439ff71293e95357bac6fd94", "abcdefghi", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"}, + {"a925576942e94b2ef57a066101b48876", "abcdefghij", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabcde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05"}, + {"d747fc1719c7eacb84058196cfe56d57", "Discard medicine more than two years old.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvDiscard medicine mor\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14"}, + {"bff2dcb37ef3a44ba43ab144768ca837", "He who has a shady past knows that nice guys finish last.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvHe who has a shady past know\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, + {"0441015ecb54a7342d017ed1bcfdbea5", "I wouldn't marry him with a ten foot pole.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvI wouldn't marry him \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15"}, + {"9e3cac8e9e9757a60c3ea391130d3689", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvFree! Free!/A trip/to Mars/f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, + {"a0f04459b031f916a59a35cc482dc039", "The days of the digital watch are numbered. -Tom Stoppard", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvThe days of the digital watch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d"}, + {"e7a48e0fe884faf31475d2a04b1362cc", "Nepal premier won't resign.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvNepal premier\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r"}, + {"637d2fe925c07c113800509964fb0e06", "For every action there is an equal and opposite government program.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvFor every action there is an equa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!"}, + {"834a8d18d5c6562119cf4c7f5086cb71", "His money is twice tainted: 'taint yours and 'taint mine.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvHis money is twice tainted: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, + {"de3a4d2fd6c73ec2db2abad23b444281", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvThere is no reason for any individual to hav\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,"}, + {"acf203f997e2cf74ea3aff86985aefaf", "It's a tiny change to the code and not completely disgusting. - Bob Manchek", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvIt's a tiny change to the code and no\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%"}, + {"e1c1384cb4d2221dfdd7c795a4222c9a", "size: a.out: bad magic", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvsize: a.out\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f"}, + {"c90f3ddecc54f34228c063d7525bf644", "The major problem is with sendmail. -Mark Horton", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvThe major problem is wit\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18"}, + {"cdf7ab6c1fd49bd9933c43f3ea5af185", "Give me a rock, paper and scissors and I will move the world. CCFestoon", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvGive me a rock, paper and scissors a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$"}, + {"83bc85234942fc883c063cbd7f0ad5d0", "If the enemy is within range, then so are you.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvIf the enemy is within \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17"}, + {"277cbe255686b48dd7e8f389394d9299", "It's well we cannot hear the screams/That we create in others' dreams.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvIt's well we cannot hear the scream\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#"}, + {"fd3fb0a7ffb8af16603f3d3af98f8e1f", "You remind me of a TV show, but that's all right: I watch it anyway.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvYou remind me of a TV show, but th\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\""}, + {"469b13a78ebf297ecda64d4723655154", "C is as portable as Stonehedge!!", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvC is as portable\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10"}, + {"63eb3a2f466410104731c4b037600110", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvEven if I could be Shakespeare, I think I sh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,"}, + {"72c2ed7592debca1c90fc0100f931a2f", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule", "md5\x01\xa7\xc9\x18\x9b\xc3E\x18\xf2\x82\xfd\xf3$\x9d_\v\nem\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B"}, + {"132f7619d33b523b1d9e5bd8e0928355", "How can you write a big system without C++? -Paul Glick", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvHow can you write a big syst\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, +} + +func TestGolden(t *testing.T) { + for i := 0; i < len(golden); i++ { + g := golden[i] + s := fmt.Sprintf("%x", Sum([]byte(g.in))) + if s != g.out { + t.Fatalf("Sum function: md5(%s) = %s want %s", g.in, s, g.out) + } + c := New() + buf := make([]byte, len(g.in)+4) + for j := 0; j < 3+4; j++ { + if j < 2 { + io.WriteString(c, g.in) + } else if j == 2 { + io.WriteString(c, g.in[0:len(g.in)/2]) + c.Sum(nil) + io.WriteString(c, g.in[len(g.in)/2:]) + } else if j > 2 { + // test unaligned write + buf = buf[1:] + copy(buf, g.in) + c.Write(buf[:len(g.in)]) + } + s := fmt.Sprintf("%x", c.Sum(nil)) + if s != g.out { + t.Fatalf("md5[%d](%s) = %s want %s", j, g.in, s, g.out) + } + c.Reset() + } + } +} + +func TestGoldenMarshal(t *testing.T) { + for _, g := range golden { + h := New() + h2 := New() + + io.WriteString(h, g.in[:len(g.in)/2]) + + state, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { + t.Errorf("could not marshal: %v", err) + continue + } + + if string(state) != g.halfState { + t.Errorf("md5(%q) state = %q, want %q", g.in, state, g.halfState) + continue + } + + if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil { + t.Errorf("could not unmarshal: %v", err) + continue + } + + io.WriteString(h, g.in[len(g.in)/2:]) + io.WriteString(h2, g.in[len(g.in)/2:]) + + if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) { + t.Errorf("md5(%q) = 0x%x != marshaled 0x%x", g.in, actual, actual2) + } + } +} + +func TestLarge(t *testing.T) { + const N = 10000 + ok := "2bb571599a4180e1d542f76904adc3df" // md5sum of "0123456789" * 1000 + block := make([]byte, 10004) + c := New() + for offset := 0; offset < 4; offset++ { + for i := 0; i < N; i++ { + block[offset+i] = '0' + byte(i%10) + } + for blockSize := 10; blockSize <= N; blockSize *= 10 { + blocks := N / blockSize + b := block[offset : offset+blockSize] + c.Reset() + for i := 0; i < blocks; i++ { + c.Write(b) + } + s := fmt.Sprintf("%x", c.Sum(nil)) + if s != ok { + t.Fatalf("md5 TestLarge offset=%d, blockSize=%d = %s want %s", offset, blockSize, s, ok) + } + } + } +} + +// Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match. +func TestBlockGeneric(t *testing.T) { + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*20) // arbitrary factor + rand.Read(buf) + blockGeneric(gen, buf) + block(asm, buf) + if *gen != *asm { + t.Error("block and blockGeneric resulted in different states") + } +} + +// Tests for unmarshaling hashes that have hashed a large amount of data +// The initial hash generation is omitted from the test, because it takes a long time. +// The test contains some already-generated states, and their expected sums +// Tests a problem that is outlined in GitHub issue #29541 +// The problem is triggered when an amount of data has been hashed for which +// the data length has a 1 in the 32nd bit. When casted to int, this changes +// the sign of the value, and causes the modulus operation to return a +// different result. +type unmarshalTest struct { + state string + sum string +} + +var largeUnmarshalTests = []unmarshalTest{ + // Data length: 7_102_415_735 + { + state: "md5\x01\xa5\xf7\xf0=\xd6S\x85\xd9M\n}\xc3\u0601\x89\xe7@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xa7VCw", + sum: "cddefcf74ffec709a0b45a6a987564d5", + }, + // Data length: 6_565_544_823 + { + state: "md5\x01{\xda\x1a\xc7\xc9'?\x83EX\xe0\x88q\xfeG\x18@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x87VCw", + sum: "fd9f41874ab240698e7bc9c3ae70c8e4", + }, +} + +func safeSum(h hash.Hash) (sum []byte, err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("sum panic: %v", r) + } + }() + + return h.Sum(nil), nil +} + +func TestLargeHashes(t *testing.T) { + for i, test := range largeUnmarshalTests { + + h := New() + if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { + t.Errorf("test %d could not unmarshal: %v", i, err) + continue + } + + sum, err := safeSum(h) + if err != nil { + t.Errorf("test %d could not sum: %v", i, err) + continue + } + + if fmt.Sprintf("%x", sum) != test.sum { + t.Errorf("test %d sum mismatch: expect %s got %x", i, test.sum, sum) + } + } +} + +var bench = New() +var buf = make([]byte, 1024*1024*8+1) +var sum = make([]byte, bench.Size()) + +func benchmarkSize(b *testing.B, size int, unaligned bool) { + b.SetBytes(int64(size)) + buf := buf + if unaligned { + if uintptr(unsafe.Pointer(&buf[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { + buf = buf[1:] + } + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + bench.Reset() + bench.Write(buf[:size]) + bench.Sum(sum[:0]) + } +} + +func BenchmarkHash8Bytes(b *testing.B) { + benchmarkSize(b, 8, false) +} + +func BenchmarkHash64(b *testing.B) { + benchmarkSize(b, 64, false) +} + +func BenchmarkHash128(b *testing.B) { + benchmarkSize(b, 128, false) +} + +func BenchmarkHash256(b *testing.B) { + benchmarkSize(b, 256, false) +} + +func BenchmarkHash512(b *testing.B) { + benchmarkSize(b, 512, false) +} + +func BenchmarkHash1K(b *testing.B) { + benchmarkSize(b, 1024, false) +} + +func BenchmarkHash8K(b *testing.B) { + benchmarkSize(b, 8192, false) +} + +func BenchmarkHash1M(b *testing.B) { + benchmarkSize(b, 1024*1024, false) +} + +func BenchmarkHash8M(b *testing.B) { + benchmarkSize(b, 8*1024*1024, false) +} + +func BenchmarkHash8BytesUnaligned(b *testing.B) { + benchmarkSize(b, 8, true) +} + +func BenchmarkHash1KUnaligned(b *testing.B) { + benchmarkSize(b, 1024, true) +} + +func BenchmarkHash8KUnaligned(b *testing.B) { + benchmarkSize(b, 8192, true) +} diff --git a/src/crypto/md5/md5block.go b/src/crypto/md5/md5block.go new file mode 100644 index 0000000..4ff289e --- /dev/null +++ b/src/crypto/md5/md5block.go @@ -0,0 +1,125 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by go run gen.go -output md5block.go; DO NOT EDIT. + +package md5 + +import ( + "encoding/binary" + "math/bits" +) + +func blockGeneric(dig *digest, p []byte) { + // load state + a, b, c, d := dig.s[0], dig.s[1], dig.s[2], dig.s[3] + + for i := 0; i <= len(p)-BlockSize; i += BlockSize { + // eliminate bounds checks on p + q := p[i:] + q = q[:BlockSize:BlockSize] + + // save current state + aa, bb, cc, dd := a, b, c, d + + // load input block + x0 := binary.LittleEndian.Uint32(q[4*0x0:]) + x1 := binary.LittleEndian.Uint32(q[4*0x1:]) + x2 := binary.LittleEndian.Uint32(q[4*0x2:]) + x3 := binary.LittleEndian.Uint32(q[4*0x3:]) + x4 := binary.LittleEndian.Uint32(q[4*0x4:]) + x5 := binary.LittleEndian.Uint32(q[4*0x5:]) + x6 := binary.LittleEndian.Uint32(q[4*0x6:]) + x7 := binary.LittleEndian.Uint32(q[4*0x7:]) + x8 := binary.LittleEndian.Uint32(q[4*0x8:]) + x9 := binary.LittleEndian.Uint32(q[4*0x9:]) + xa := binary.LittleEndian.Uint32(q[4*0xa:]) + xb := binary.LittleEndian.Uint32(q[4*0xb:]) + xc := binary.LittleEndian.Uint32(q[4*0xc:]) + xd := binary.LittleEndian.Uint32(q[4*0xd:]) + xe := binary.LittleEndian.Uint32(q[4*0xe:]) + xf := binary.LittleEndian.Uint32(q[4*0xf:]) + + // round 1 + a = b + bits.RotateLeft32((((c^d)&b)^d)+a+x0+0xd76aa478, 7) + d = a + bits.RotateLeft32((((b^c)&a)^c)+d+x1+0xe8c7b756, 12) + c = d + bits.RotateLeft32((((a^b)&d)^b)+c+x2+0x242070db, 17) + b = c + bits.RotateLeft32((((d^a)&c)^a)+b+x3+0xc1bdceee, 22) + a = b + bits.RotateLeft32((((c^d)&b)^d)+a+x4+0xf57c0faf, 7) + d = a + bits.RotateLeft32((((b^c)&a)^c)+d+x5+0x4787c62a, 12) + c = d + bits.RotateLeft32((((a^b)&d)^b)+c+x6+0xa8304613, 17) + b = c + bits.RotateLeft32((((d^a)&c)^a)+b+x7+0xfd469501, 22) + a = b + bits.RotateLeft32((((c^d)&b)^d)+a+x8+0x698098d8, 7) + d = a + bits.RotateLeft32((((b^c)&a)^c)+d+x9+0x8b44f7af, 12) + c = d + bits.RotateLeft32((((a^b)&d)^b)+c+xa+0xffff5bb1, 17) + b = c + bits.RotateLeft32((((d^a)&c)^a)+b+xb+0x895cd7be, 22) + a = b + bits.RotateLeft32((((c^d)&b)^d)+a+xc+0x6b901122, 7) + d = a + bits.RotateLeft32((((b^c)&a)^c)+d+xd+0xfd987193, 12) + c = d + bits.RotateLeft32((((a^b)&d)^b)+c+xe+0xa679438e, 17) + b = c + bits.RotateLeft32((((d^a)&c)^a)+b+xf+0x49b40821, 22) + + // round 2 + a = b + bits.RotateLeft32((((b^c)&d)^c)+a+x1+0xf61e2562, 5) + d = a + bits.RotateLeft32((((a^b)&c)^b)+d+x6+0xc040b340, 9) + c = d + bits.RotateLeft32((((d^a)&b)^a)+c+xb+0x265e5a51, 14) + b = c + bits.RotateLeft32((((c^d)&a)^d)+b+x0+0xe9b6c7aa, 20) + a = b + bits.RotateLeft32((((b^c)&d)^c)+a+x5+0xd62f105d, 5) + d = a + bits.RotateLeft32((((a^b)&c)^b)+d+xa+0x02441453, 9) + c = d + bits.RotateLeft32((((d^a)&b)^a)+c+xf+0xd8a1e681, 14) + b = c + bits.RotateLeft32((((c^d)&a)^d)+b+x4+0xe7d3fbc8, 20) + a = b + bits.RotateLeft32((((b^c)&d)^c)+a+x9+0x21e1cde6, 5) + d = a + bits.RotateLeft32((((a^b)&c)^b)+d+xe+0xc33707d6, 9) + c = d + bits.RotateLeft32((((d^a)&b)^a)+c+x3+0xf4d50d87, 14) + b = c + bits.RotateLeft32((((c^d)&a)^d)+b+x8+0x455a14ed, 20) + a = b + bits.RotateLeft32((((b^c)&d)^c)+a+xd+0xa9e3e905, 5) + d = a + bits.RotateLeft32((((a^b)&c)^b)+d+x2+0xfcefa3f8, 9) + c = d + bits.RotateLeft32((((d^a)&b)^a)+c+x7+0x676f02d9, 14) + b = c + bits.RotateLeft32((((c^d)&a)^d)+b+xc+0x8d2a4c8a, 20) + + // round 3 + a = b + bits.RotateLeft32((b^c^d)+a+x5+0xfffa3942, 4) + d = a + bits.RotateLeft32((a^b^c)+d+x8+0x8771f681, 11) + c = d + bits.RotateLeft32((d^a^b)+c+xb+0x6d9d6122, 16) + b = c + bits.RotateLeft32((c^d^a)+b+xe+0xfde5380c, 23) + a = b + bits.RotateLeft32((b^c^d)+a+x1+0xa4beea44, 4) + d = a + bits.RotateLeft32((a^b^c)+d+x4+0x4bdecfa9, 11) + c = d + bits.RotateLeft32((d^a^b)+c+x7+0xf6bb4b60, 16) + b = c + bits.RotateLeft32((c^d^a)+b+xa+0xbebfbc70, 23) + a = b + bits.RotateLeft32((b^c^d)+a+xd+0x289b7ec6, 4) + d = a + bits.RotateLeft32((a^b^c)+d+x0+0xeaa127fa, 11) + c = d + bits.RotateLeft32((d^a^b)+c+x3+0xd4ef3085, 16) + b = c + bits.RotateLeft32((c^d^a)+b+x6+0x04881d05, 23) + a = b + bits.RotateLeft32((b^c^d)+a+x9+0xd9d4d039, 4) + d = a + bits.RotateLeft32((a^b^c)+d+xc+0xe6db99e5, 11) + c = d + bits.RotateLeft32((d^a^b)+c+xf+0x1fa27cf8, 16) + b = c + bits.RotateLeft32((c^d^a)+b+x2+0xc4ac5665, 23) + + // round 4 + a = b + bits.RotateLeft32((c^(b|^d))+a+x0+0xf4292244, 6) + d = a + bits.RotateLeft32((b^(a|^c))+d+x7+0x432aff97, 10) + c = d + bits.RotateLeft32((a^(d|^b))+c+xe+0xab9423a7, 15) + b = c + bits.RotateLeft32((d^(c|^a))+b+x5+0xfc93a039, 21) + a = b + bits.RotateLeft32((c^(b|^d))+a+xc+0x655b59c3, 6) + d = a + bits.RotateLeft32((b^(a|^c))+d+x3+0x8f0ccc92, 10) + c = d + bits.RotateLeft32((a^(d|^b))+c+xa+0xffeff47d, 15) + b = c + bits.RotateLeft32((d^(c|^a))+b+x1+0x85845dd1, 21) + a = b + bits.RotateLeft32((c^(b|^d))+a+x8+0x6fa87e4f, 6) + d = a + bits.RotateLeft32((b^(a|^c))+d+xf+0xfe2ce6e0, 10) + c = d + bits.RotateLeft32((a^(d|^b))+c+x6+0xa3014314, 15) + b = c + bits.RotateLeft32((d^(c|^a))+b+xd+0x4e0811a1, 21) + a = b + bits.RotateLeft32((c^(b|^d))+a+x4+0xf7537e82, 6) + d = a + bits.RotateLeft32((b^(a|^c))+d+xb+0xbd3af235, 10) + c = d + bits.RotateLeft32((a^(d|^b))+c+x2+0x2ad7d2bb, 15) + b = c + bits.RotateLeft32((d^(c|^a))+b+x9+0xeb86d391, 21) + + // add saved state + a += aa + b += bb + c += cc + d += dd + } + + // save state + dig.s[0], dig.s[1], dig.s[2], dig.s[3] = a, b, c, d +} diff --git a/src/crypto/md5/md5block_386.s b/src/crypto/md5/md5block_386.s new file mode 100644 index 0000000..30d4209 --- /dev/null +++ b/src/crypto/md5/md5block_386.s @@ -0,0 +1,182 @@ +// Original source: +// http://www.zorinaq.com/papers/md5-amd64.html +// http://www.zorinaq.com/papers/md5-amd64.tar.bz2 +// +// Translated from Perl generating GNU assembly into +// #defines generating 8a assembly, and adjusted for 386, +// by the Go Authors. + +#include "textflag.h" + +// MD5 optimized for AMD64. +// +// Author: Marc Bevand +// Licence: I hereby disclaim the copyright on this code and place it +// in the public domain. + +#define ROUND1(a, b, c, d, index, const, shift) \ + XORL c, BP; \ + LEAL const(a)(DI*1), a; \ + ANDL b, BP; \ + XORL d, BP; \ + MOVL (index*4)(SI), DI; \ + ADDL BP, a; \ + ROLL $shift, a; \ + MOVL c, BP; \ + ADDL b, a + +#define ROUND2(a, b, c, d, index, const, shift) \ + LEAL const(a)(DI*1),a; \ + MOVL d, DI; \ + ANDL b, DI; \ + MOVL d, BP; \ + NOTL BP; \ + ANDL c, BP; \ + ORL DI, BP; \ + MOVL (index*4)(SI),DI; \ + ADDL BP, a; \ + ROLL $shift, a; \ + ADDL b, a + +#define ROUND3(a, b, c, d, index, const, shift) \ + LEAL const(a)(DI*1),a; \ + MOVL (index*4)(SI),DI; \ + XORL d, BP; \ + XORL b, BP; \ + ADDL BP, a; \ + ROLL $shift, a; \ + MOVL b, BP; \ + ADDL b, a + +#define ROUND4(a, b, c, d, index, const, shift) \ + LEAL const(a)(DI*1),a; \ + ORL b, BP; \ + XORL c, BP; \ + ADDL BP, a; \ + MOVL (index*4)(SI),DI; \ + MOVL $0xffffffff, BP; \ + ROLL $shift, a; \ + XORL c, BP; \ + ADDL b, a + +TEXT ·block(SB),NOSPLIT,$24-16 + MOVL dig+0(FP), BP + MOVL p+4(FP), SI + MOVL p_len+8(FP), DX + SHRL $6, DX + SHLL $6, DX + + LEAL (SI)(DX*1), DI + MOVL (0*4)(BP), AX + MOVL (1*4)(BP), BX + MOVL (2*4)(BP), CX + MOVL (3*4)(BP), DX + + CMPL SI, DI + JEQ end + + MOVL DI, 16(SP) + +loop: + MOVL AX, 0(SP) + MOVL BX, 4(SP) + MOVL CX, 8(SP) + MOVL DX, 12(SP) + + MOVL (0*4)(SI), DI + MOVL DX, BP + + ROUND1(AX,BX,CX,DX, 1,0xd76aa478, 7); + ROUND1(DX,AX,BX,CX, 2,0xe8c7b756,12); + ROUND1(CX,DX,AX,BX, 3,0x242070db,17); + ROUND1(BX,CX,DX,AX, 4,0xc1bdceee,22); + ROUND1(AX,BX,CX,DX, 5,0xf57c0faf, 7); + ROUND1(DX,AX,BX,CX, 6,0x4787c62a,12); + ROUND1(CX,DX,AX,BX, 7,0xa8304613,17); + ROUND1(BX,CX,DX,AX, 8,0xfd469501,22); + ROUND1(AX,BX,CX,DX, 9,0x698098d8, 7); + ROUND1(DX,AX,BX,CX,10,0x8b44f7af,12); + ROUND1(CX,DX,AX,BX,11,0xffff5bb1,17); + ROUND1(BX,CX,DX,AX,12,0x895cd7be,22); + ROUND1(AX,BX,CX,DX,13,0x6b901122, 7); + ROUND1(DX,AX,BX,CX,14,0xfd987193,12); + ROUND1(CX,DX,AX,BX,15,0xa679438e,17); + ROUND1(BX,CX,DX,AX, 0,0x49b40821,22); + + MOVL (1*4)(SI), DI + MOVL DX, BP + + ROUND2(AX,BX,CX,DX, 6,0xf61e2562, 5); + ROUND2(DX,AX,BX,CX,11,0xc040b340, 9); + ROUND2(CX,DX,AX,BX, 0,0x265e5a51,14); + ROUND2(BX,CX,DX,AX, 5,0xe9b6c7aa,20); + ROUND2(AX,BX,CX,DX,10,0xd62f105d, 5); + ROUND2(DX,AX,BX,CX,15, 0x2441453, 9); + ROUND2(CX,DX,AX,BX, 4,0xd8a1e681,14); + ROUND2(BX,CX,DX,AX, 9,0xe7d3fbc8,20); + ROUND2(AX,BX,CX,DX,14,0x21e1cde6, 5); + ROUND2(DX,AX,BX,CX, 3,0xc33707d6, 9); + ROUND2(CX,DX,AX,BX, 8,0xf4d50d87,14); + ROUND2(BX,CX,DX,AX,13,0x455a14ed,20); + ROUND2(AX,BX,CX,DX, 2,0xa9e3e905, 5); + ROUND2(DX,AX,BX,CX, 7,0xfcefa3f8, 9); + ROUND2(CX,DX,AX,BX,12,0x676f02d9,14); + ROUND2(BX,CX,DX,AX, 0,0x8d2a4c8a,20); + + MOVL (5*4)(SI), DI + MOVL CX, BP + + ROUND3(AX,BX,CX,DX, 8,0xfffa3942, 4); + ROUND3(DX,AX,BX,CX,11,0x8771f681,11); + ROUND3(CX,DX,AX,BX,14,0x6d9d6122,16); + ROUND3(BX,CX,DX,AX, 1,0xfde5380c,23); + ROUND3(AX,BX,CX,DX, 4,0xa4beea44, 4); + ROUND3(DX,AX,BX,CX, 7,0x4bdecfa9,11); + ROUND3(CX,DX,AX,BX,10,0xf6bb4b60,16); + ROUND3(BX,CX,DX,AX,13,0xbebfbc70,23); + ROUND3(AX,BX,CX,DX, 0,0x289b7ec6, 4); + ROUND3(DX,AX,BX,CX, 3,0xeaa127fa,11); + ROUND3(CX,DX,AX,BX, 6,0xd4ef3085,16); + ROUND3(BX,CX,DX,AX, 9, 0x4881d05,23); + ROUND3(AX,BX,CX,DX,12,0xd9d4d039, 4); + ROUND3(DX,AX,BX,CX,15,0xe6db99e5,11); + ROUND3(CX,DX,AX,BX, 2,0x1fa27cf8,16); + ROUND3(BX,CX,DX,AX, 0,0xc4ac5665,23); + + MOVL (0*4)(SI), DI + MOVL $0xffffffff, BP + XORL DX, BP + + ROUND4(AX,BX,CX,DX, 7,0xf4292244, 6); + ROUND4(DX,AX,BX,CX,14,0x432aff97,10); + ROUND4(CX,DX,AX,BX, 5,0xab9423a7,15); + ROUND4(BX,CX,DX,AX,12,0xfc93a039,21); + ROUND4(AX,BX,CX,DX, 3,0x655b59c3, 6); + ROUND4(DX,AX,BX,CX,10,0x8f0ccc92,10); + ROUND4(CX,DX,AX,BX, 1,0xffeff47d,15); + ROUND4(BX,CX,DX,AX, 8,0x85845dd1,21); + ROUND4(AX,BX,CX,DX,15,0x6fa87e4f, 6); + ROUND4(DX,AX,BX,CX, 6,0xfe2ce6e0,10); + ROUND4(CX,DX,AX,BX,13,0xa3014314,15); + ROUND4(BX,CX,DX,AX, 4,0x4e0811a1,21); + ROUND4(AX,BX,CX,DX,11,0xf7537e82, 6); + ROUND4(DX,AX,BX,CX, 2,0xbd3af235,10); + ROUND4(CX,DX,AX,BX, 9,0x2ad7d2bb,15); + ROUND4(BX,CX,DX,AX, 0,0xeb86d391,21); + + ADDL 0(SP), AX + ADDL 4(SP), BX + ADDL 8(SP), CX + ADDL 12(SP), DX + + ADDL $64, SI + CMPL SI, 16(SP) + JB loop + +end: + MOVL dig+0(FP), BP + MOVL AX, (0*4)(BP) + MOVL BX, (1*4)(BP) + MOVL CX, (2*4)(BP) + MOVL DX, (3*4)(BP) + RET diff --git a/src/crypto/md5/md5block_amd64.s b/src/crypto/md5/md5block_amd64.s new file mode 100644 index 0000000..7c7d92d --- /dev/null +++ b/src/crypto/md5/md5block_amd64.s @@ -0,0 +1,179 @@ +// Original source: +// http://www.zorinaq.com/papers/md5-amd64.html +// http://www.zorinaq.com/papers/md5-amd64.tar.bz2 +// +// Translated from Perl generating GNU assembly into +// #defines generating 6a assembly by the Go Authors. + +#include "textflag.h" + +// MD5 optimized for AMD64. +// +// Author: Marc Bevand +// Licence: I hereby disclaim the copyright on this code and place it +// in the public domain. + +TEXT ·block(SB),NOSPLIT,$8-32 + MOVQ dig+0(FP), BP + MOVQ p+8(FP), SI + MOVQ p_len+16(FP), DX + SHRQ $6, DX + SHLQ $6, DX + + LEAQ (SI)(DX*1), DI + MOVL (0*4)(BP), AX + MOVL (1*4)(BP), BX + MOVL (2*4)(BP), CX + MOVL (3*4)(BP), DX + + CMPQ SI, DI + JEQ end + +loop: + MOVL AX, R12 + MOVL BX, R13 + MOVL CX, R14 + MOVL DX, R15 + + MOVL (0*4)(SI), R8 + MOVL DX, R9 + +#define ROUND1(a, b, c, d, index, const, shift) \ + XORL c, R9; \ + LEAL const(a)(R8*1), a; \ + ANDL b, R9; \ + XORL d, R9; \ + MOVL (index*4)(SI), R8; \ + ADDL R9, a; \ + ROLL $shift, a; \ + MOVL c, R9; \ + ADDL b, a + + ROUND1(AX,BX,CX,DX, 1,0xd76aa478, 7); + ROUND1(DX,AX,BX,CX, 2,0xe8c7b756,12); + ROUND1(CX,DX,AX,BX, 3,0x242070db,17); + ROUND1(BX,CX,DX,AX, 4,0xc1bdceee,22); + ROUND1(AX,BX,CX,DX, 5,0xf57c0faf, 7); + ROUND1(DX,AX,BX,CX, 6,0x4787c62a,12); + ROUND1(CX,DX,AX,BX, 7,0xa8304613,17); + ROUND1(BX,CX,DX,AX, 8,0xfd469501,22); + ROUND1(AX,BX,CX,DX, 9,0x698098d8, 7); + ROUND1(DX,AX,BX,CX,10,0x8b44f7af,12); + ROUND1(CX,DX,AX,BX,11,0xffff5bb1,17); + ROUND1(BX,CX,DX,AX,12,0x895cd7be,22); + ROUND1(AX,BX,CX,DX,13,0x6b901122, 7); + ROUND1(DX,AX,BX,CX,14,0xfd987193,12); + ROUND1(CX,DX,AX,BX,15,0xa679438e,17); + ROUND1(BX,CX,DX,AX, 0,0x49b40821,22); + + MOVL (1*4)(SI), R8 + MOVL DX, R9 + MOVL DX, R10 + +#define ROUND2(a, b, c, d, index, const, shift) \ + NOTL R9; \ + LEAL const(a)(R8*1),a; \ + ANDL b, R10; \ + ANDL c, R9; \ + MOVL (index*4)(SI),R8; \ + ORL R9, R10; \ + MOVL c, R9; \ + ADDL R10, a; \ + MOVL c, R10; \ + ROLL $shift, a; \ + ADDL b, a + + ROUND2(AX,BX,CX,DX, 6,0xf61e2562, 5); + ROUND2(DX,AX,BX,CX,11,0xc040b340, 9); + ROUND2(CX,DX,AX,BX, 0,0x265e5a51,14); + ROUND2(BX,CX,DX,AX, 5,0xe9b6c7aa,20); + ROUND2(AX,BX,CX,DX,10,0xd62f105d, 5); + ROUND2(DX,AX,BX,CX,15, 0x2441453, 9); + ROUND2(CX,DX,AX,BX, 4,0xd8a1e681,14); + ROUND2(BX,CX,DX,AX, 9,0xe7d3fbc8,20); + ROUND2(AX,BX,CX,DX,14,0x21e1cde6, 5); + ROUND2(DX,AX,BX,CX, 3,0xc33707d6, 9); + ROUND2(CX,DX,AX,BX, 8,0xf4d50d87,14); + ROUND2(BX,CX,DX,AX,13,0x455a14ed,20); + ROUND2(AX,BX,CX,DX, 2,0xa9e3e905, 5); + ROUND2(DX,AX,BX,CX, 7,0xfcefa3f8, 9); + ROUND2(CX,DX,AX,BX,12,0x676f02d9,14); + ROUND2(BX,CX,DX,AX, 0,0x8d2a4c8a,20); + + MOVL (5*4)(SI), R8 + MOVL CX, R9 + +#define ROUND3(a, b, c, d, index, const, shift) \ + LEAL const(a)(R8*1),a; \ + MOVL (index*4)(SI),R8; \ + XORL d, R9; \ + XORL b, R9; \ + ADDL R9, a; \ + ROLL $shift, a; \ + MOVL b, R9; \ + ADDL b, a + + ROUND3(AX,BX,CX,DX, 8,0xfffa3942, 4); + ROUND3(DX,AX,BX,CX,11,0x8771f681,11); + ROUND3(CX,DX,AX,BX,14,0x6d9d6122,16); + ROUND3(BX,CX,DX,AX, 1,0xfde5380c,23); + ROUND3(AX,BX,CX,DX, 4,0xa4beea44, 4); + ROUND3(DX,AX,BX,CX, 7,0x4bdecfa9,11); + ROUND3(CX,DX,AX,BX,10,0xf6bb4b60,16); + ROUND3(BX,CX,DX,AX,13,0xbebfbc70,23); + ROUND3(AX,BX,CX,DX, 0,0x289b7ec6, 4); + ROUND3(DX,AX,BX,CX, 3,0xeaa127fa,11); + ROUND3(CX,DX,AX,BX, 6,0xd4ef3085,16); + ROUND3(BX,CX,DX,AX, 9, 0x4881d05,23); + ROUND3(AX,BX,CX,DX,12,0xd9d4d039, 4); + ROUND3(DX,AX,BX,CX,15,0xe6db99e5,11); + ROUND3(CX,DX,AX,BX, 2,0x1fa27cf8,16); + ROUND3(BX,CX,DX,AX, 0,0xc4ac5665,23); + + MOVL (0*4)(SI), R8 + MOVL $0xffffffff, R9 + XORL DX, R9 + +#define ROUND4(a, b, c, d, index, const, shift) \ + LEAL const(a)(R8*1),a; \ + ORL b, R9; \ + XORL c, R9; \ + ADDL R9, a; \ + MOVL (index*4)(SI),R8; \ + MOVL $0xffffffff, R9; \ + ROLL $shift, a; \ + XORL c, R9; \ + ADDL b, a + + ROUND4(AX,BX,CX,DX, 7,0xf4292244, 6); + ROUND4(DX,AX,BX,CX,14,0x432aff97,10); + ROUND4(CX,DX,AX,BX, 5,0xab9423a7,15); + ROUND4(BX,CX,DX,AX,12,0xfc93a039,21); + ROUND4(AX,BX,CX,DX, 3,0x655b59c3, 6); + ROUND4(DX,AX,BX,CX,10,0x8f0ccc92,10); + ROUND4(CX,DX,AX,BX, 1,0xffeff47d,15); + ROUND4(BX,CX,DX,AX, 8,0x85845dd1,21); + ROUND4(AX,BX,CX,DX,15,0x6fa87e4f, 6); + ROUND4(DX,AX,BX,CX, 6,0xfe2ce6e0,10); + ROUND4(CX,DX,AX,BX,13,0xa3014314,15); + ROUND4(BX,CX,DX,AX, 4,0x4e0811a1,21); + ROUND4(AX,BX,CX,DX,11,0xf7537e82, 6); + ROUND4(DX,AX,BX,CX, 2,0xbd3af235,10); + ROUND4(CX,DX,AX,BX, 9,0x2ad7d2bb,15); + ROUND4(BX,CX,DX,AX, 0,0xeb86d391,21); + + ADDL R12, AX + ADDL R13, BX + ADDL R14, CX + ADDL R15, DX + + ADDQ $64, SI + CMPQ SI, DI + JB loop + +end: + MOVL AX, (0*4)(BP) + MOVL BX, (1*4)(BP) + MOVL CX, (2*4)(BP) + MOVL DX, (3*4)(BP) + RET diff --git a/src/crypto/md5/md5block_arm.s b/src/crypto/md5/md5block_arm.s new file mode 100644 index 0000000..54d02b7 --- /dev/null +++ b/src/crypto/md5/md5block_arm.s @@ -0,0 +1,299 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// ARM version of md5block.go + +#include "textflag.h" + +// Register definitions +#define Rtable R0 // Pointer to MD5 constants table +#define Rdata R1 // Pointer to data to hash +#define Ra R2 // MD5 accumulator +#define Rb R3 // MD5 accumulator +#define Rc R4 // MD5 accumulator +#define Rd R5 // MD5 accumulator +#define Rc0 R6 // MD5 constant +#define Rc1 R7 // MD5 constant +#define Rc2 R8 // MD5 constant +// r9, r10 are forbidden +// r11 is OK provided you check the assembler that no synthetic instructions use it +#define Rc3 R11 // MD5 constant +#define Rt0 R12 // temporary +#define Rt1 R14 // temporary + +// func block(dig *digest, p []byte) +// 0(FP) is *digest +// 4(FP) is p.array (struct Slice) +// 8(FP) is p.len +//12(FP) is p.cap +// +// Stack frame +#define p_end end-4(SP) // pointer to the end of data +#define p_data data-8(SP) // current data pointer +#define buf buffer-(8+4*16)(SP) //16 words temporary buffer + // 3 words at 4..12(R13) for called routine parameters + +TEXT ·block(SB), NOSPLIT, $84-16 + MOVW p+4(FP), Rdata // pointer to the data + MOVW p_len+8(FP), Rt0 // number of bytes + ADD Rdata, Rt0 + MOVW Rt0, p_end // pointer to end of data + +loop: + MOVW Rdata, p_data // Save Rdata + AND.S $3, Rdata, Rt0 // TST $3, Rdata not working see issue 5921 + BEQ aligned // aligned detected - skip copy + + // Copy the unaligned source data into the aligned temporary buffer + // memmove(to=4(R13), from=8(R13), n=12(R13)) - Corrupts all registers + MOVW $buf, Rtable // to + MOVW $64, Rc0 // n + MOVM.IB [Rtable,Rdata,Rc0], (R13) + BL runtime·memmove(SB) + + // Point to the local aligned copy of the data + MOVW $buf, Rdata + +aligned: + // Point to the table of constants + // A PC relative add would be cheaper than this + MOVW $·table(SB), Rtable + + // Load up initial MD5 accumulator + MOVW dig+0(FP), Rc0 + MOVM.IA (Rc0), [Ra,Rb,Rc,Rd] + +// a += (((c^d)&b)^d) + X[index] + const +// a = a<>(32-shift) + b +#define ROUND1(Ra, Rb, Rc, Rd, index, shift, Rconst) \ + EOR Rc, Rd, Rt0 ; \ + AND Rb, Rt0 ; \ + EOR Rd, Rt0 ; \ + MOVW (index<<2)(Rdata), Rt1 ; \ + ADD Rt1, Rt0 ; \ + ADD Rconst, Rt0 ; \ + ADD Rt0, Ra ; \ + ADD Ra@>(32-shift), Rb, Ra ; + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND1(Ra, Rb, Rc, Rd, 0, 7, Rc0) + ROUND1(Rd, Ra, Rb, Rc, 1, 12, Rc1) + ROUND1(Rc, Rd, Ra, Rb, 2, 17, Rc2) + ROUND1(Rb, Rc, Rd, Ra, 3, 22, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND1(Ra, Rb, Rc, Rd, 4, 7, Rc0) + ROUND1(Rd, Ra, Rb, Rc, 5, 12, Rc1) + ROUND1(Rc, Rd, Ra, Rb, 6, 17, Rc2) + ROUND1(Rb, Rc, Rd, Ra, 7, 22, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND1(Ra, Rb, Rc, Rd, 8, 7, Rc0) + ROUND1(Rd, Ra, Rb, Rc, 9, 12, Rc1) + ROUND1(Rc, Rd, Ra, Rb, 10, 17, Rc2) + ROUND1(Rb, Rc, Rd, Ra, 11, 22, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND1(Ra, Rb, Rc, Rd, 12, 7, Rc0) + ROUND1(Rd, Ra, Rb, Rc, 13, 12, Rc1) + ROUND1(Rc, Rd, Ra, Rb, 14, 17, Rc2) + ROUND1(Rb, Rc, Rd, Ra, 15, 22, Rc3) + +// a += (((b^c)&d)^c) + X[index] + const +// a = a<>(32-shift) + b +#define ROUND2(Ra, Rb, Rc, Rd, index, shift, Rconst) \ + EOR Rb, Rc, Rt0 ; \ + AND Rd, Rt0 ; \ + EOR Rc, Rt0 ; \ + MOVW (index<<2)(Rdata), Rt1 ; \ + ADD Rt1, Rt0 ; \ + ADD Rconst, Rt0 ; \ + ADD Rt0, Ra ; \ + ADD Ra@>(32-shift), Rb, Ra ; + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND2(Ra, Rb, Rc, Rd, 1, 5, Rc0) + ROUND2(Rd, Ra, Rb, Rc, 6, 9, Rc1) + ROUND2(Rc, Rd, Ra, Rb, 11, 14, Rc2) + ROUND2(Rb, Rc, Rd, Ra, 0, 20, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND2(Ra, Rb, Rc, Rd, 5, 5, Rc0) + ROUND2(Rd, Ra, Rb, Rc, 10, 9, Rc1) + ROUND2(Rc, Rd, Ra, Rb, 15, 14, Rc2) + ROUND2(Rb, Rc, Rd, Ra, 4, 20, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND2(Ra, Rb, Rc, Rd, 9, 5, Rc0) + ROUND2(Rd, Ra, Rb, Rc, 14, 9, Rc1) + ROUND2(Rc, Rd, Ra, Rb, 3, 14, Rc2) + ROUND2(Rb, Rc, Rd, Ra, 8, 20, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND2(Ra, Rb, Rc, Rd, 13, 5, Rc0) + ROUND2(Rd, Ra, Rb, Rc, 2, 9, Rc1) + ROUND2(Rc, Rd, Ra, Rb, 7, 14, Rc2) + ROUND2(Rb, Rc, Rd, Ra, 12, 20, Rc3) + +// a += (b^c^d) + X[index] + const +// a = a<>(32-shift) + b +#define ROUND3(Ra, Rb, Rc, Rd, index, shift, Rconst) \ + EOR Rb, Rc, Rt0 ; \ + EOR Rd, Rt0 ; \ + MOVW (index<<2)(Rdata), Rt1 ; \ + ADD Rt1, Rt0 ; \ + ADD Rconst, Rt0 ; \ + ADD Rt0, Ra ; \ + ADD Ra@>(32-shift), Rb, Ra ; + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND3(Ra, Rb, Rc, Rd, 5, 4, Rc0) + ROUND3(Rd, Ra, Rb, Rc, 8, 11, Rc1) + ROUND3(Rc, Rd, Ra, Rb, 11, 16, Rc2) + ROUND3(Rb, Rc, Rd, Ra, 14, 23, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND3(Ra, Rb, Rc, Rd, 1, 4, Rc0) + ROUND3(Rd, Ra, Rb, Rc, 4, 11, Rc1) + ROUND3(Rc, Rd, Ra, Rb, 7, 16, Rc2) + ROUND3(Rb, Rc, Rd, Ra, 10, 23, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND3(Ra, Rb, Rc, Rd, 13, 4, Rc0) + ROUND3(Rd, Ra, Rb, Rc, 0, 11, Rc1) + ROUND3(Rc, Rd, Ra, Rb, 3, 16, Rc2) + ROUND3(Rb, Rc, Rd, Ra, 6, 23, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND3(Ra, Rb, Rc, Rd, 9, 4, Rc0) + ROUND3(Rd, Ra, Rb, Rc, 12, 11, Rc1) + ROUND3(Rc, Rd, Ra, Rb, 15, 16, Rc2) + ROUND3(Rb, Rc, Rd, Ra, 2, 23, Rc3) + +// a += (c^(b|^d)) + X[index] + const +// a = a<>(32-shift) + b +#define ROUND4(Ra, Rb, Rc, Rd, index, shift, Rconst) \ + MVN Rd, Rt0 ; \ + ORR Rb, Rt0 ; \ + EOR Rc, Rt0 ; \ + MOVW (index<<2)(Rdata), Rt1 ; \ + ADD Rt1, Rt0 ; \ + ADD Rconst, Rt0 ; \ + ADD Rt0, Ra ; \ + ADD Ra@>(32-shift), Rb, Ra ; + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND4(Ra, Rb, Rc, Rd, 0, 6, Rc0) + ROUND4(Rd, Ra, Rb, Rc, 7, 10, Rc1) + ROUND4(Rc, Rd, Ra, Rb, 14, 15, Rc2) + ROUND4(Rb, Rc, Rd, Ra, 5, 21, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND4(Ra, Rb, Rc, Rd, 12, 6, Rc0) + ROUND4(Rd, Ra, Rb, Rc, 3, 10, Rc1) + ROUND4(Rc, Rd, Ra, Rb, 10, 15, Rc2) + ROUND4(Rb, Rc, Rd, Ra, 1, 21, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND4(Ra, Rb, Rc, Rd, 8, 6, Rc0) + ROUND4(Rd, Ra, Rb, Rc, 15, 10, Rc1) + ROUND4(Rc, Rd, Ra, Rb, 6, 15, Rc2) + ROUND4(Rb, Rc, Rd, Ra, 13, 21, Rc3) + + MOVM.IA.W (Rtable), [Rc0,Rc1,Rc2,Rc3] + ROUND4(Ra, Rb, Rc, Rd, 4, 6, Rc0) + ROUND4(Rd, Ra, Rb, Rc, 11, 10, Rc1) + ROUND4(Rc, Rd, Ra, Rb, 2, 15, Rc2) + ROUND4(Rb, Rc, Rd, Ra, 9, 21, Rc3) + + MOVW dig+0(FP), Rt0 + MOVM.IA (Rt0), [Rc0,Rc1,Rc2,Rc3] + + ADD Rc0, Ra + ADD Rc1, Rb + ADD Rc2, Rc + ADD Rc3, Rd + + MOVM.IA [Ra,Rb,Rc,Rd], (Rt0) + + MOVW p_data, Rdata + MOVW p_end, Rt0 + ADD $64, Rdata + CMP Rt0, Rdata + BLO loop + + RET + +// MD5 constants table + + // Round 1 + DATA ·table+0x00(SB)/4, $0xd76aa478 + DATA ·table+0x04(SB)/4, $0xe8c7b756 + DATA ·table+0x08(SB)/4, $0x242070db + DATA ·table+0x0c(SB)/4, $0xc1bdceee + DATA ·table+0x10(SB)/4, $0xf57c0faf + DATA ·table+0x14(SB)/4, $0x4787c62a + DATA ·table+0x18(SB)/4, $0xa8304613 + DATA ·table+0x1c(SB)/4, $0xfd469501 + DATA ·table+0x20(SB)/4, $0x698098d8 + DATA ·table+0x24(SB)/4, $0x8b44f7af + DATA ·table+0x28(SB)/4, $0xffff5bb1 + DATA ·table+0x2c(SB)/4, $0x895cd7be + DATA ·table+0x30(SB)/4, $0x6b901122 + DATA ·table+0x34(SB)/4, $0xfd987193 + DATA ·table+0x38(SB)/4, $0xa679438e + DATA ·table+0x3c(SB)/4, $0x49b40821 + // Round 2 + DATA ·table+0x40(SB)/4, $0xf61e2562 + DATA ·table+0x44(SB)/4, $0xc040b340 + DATA ·table+0x48(SB)/4, $0x265e5a51 + DATA ·table+0x4c(SB)/4, $0xe9b6c7aa + DATA ·table+0x50(SB)/4, $0xd62f105d + DATA ·table+0x54(SB)/4, $0x02441453 + DATA ·table+0x58(SB)/4, $0xd8a1e681 + DATA ·table+0x5c(SB)/4, $0xe7d3fbc8 + DATA ·table+0x60(SB)/4, $0x21e1cde6 + DATA ·table+0x64(SB)/4, $0xc33707d6 + DATA ·table+0x68(SB)/4, $0xf4d50d87 + DATA ·table+0x6c(SB)/4, $0x455a14ed + DATA ·table+0x70(SB)/4, $0xa9e3e905 + DATA ·table+0x74(SB)/4, $0xfcefa3f8 + DATA ·table+0x78(SB)/4, $0x676f02d9 + DATA ·table+0x7c(SB)/4, $0x8d2a4c8a + // Round 3 + DATA ·table+0x80(SB)/4, $0xfffa3942 + DATA ·table+0x84(SB)/4, $0x8771f681 + DATA ·table+0x88(SB)/4, $0x6d9d6122 + DATA ·table+0x8c(SB)/4, $0xfde5380c + DATA ·table+0x90(SB)/4, $0xa4beea44 + DATA ·table+0x94(SB)/4, $0x4bdecfa9 + DATA ·table+0x98(SB)/4, $0xf6bb4b60 + DATA ·table+0x9c(SB)/4, $0xbebfbc70 + DATA ·table+0xa0(SB)/4, $0x289b7ec6 + DATA ·table+0xa4(SB)/4, $0xeaa127fa + DATA ·table+0xa8(SB)/4, $0xd4ef3085 + DATA ·table+0xac(SB)/4, $0x04881d05 + DATA ·table+0xb0(SB)/4, $0xd9d4d039 + DATA ·table+0xb4(SB)/4, $0xe6db99e5 + DATA ·table+0xb8(SB)/4, $0x1fa27cf8 + DATA ·table+0xbc(SB)/4, $0xc4ac5665 + // Round 4 + DATA ·table+0xc0(SB)/4, $0xf4292244 + DATA ·table+0xc4(SB)/4, $0x432aff97 + DATA ·table+0xc8(SB)/4, $0xab9423a7 + DATA ·table+0xcc(SB)/4, $0xfc93a039 + DATA ·table+0xd0(SB)/4, $0x655b59c3 + DATA ·table+0xd4(SB)/4, $0x8f0ccc92 + DATA ·table+0xd8(SB)/4, $0xffeff47d + DATA ·table+0xdc(SB)/4, $0x85845dd1 + DATA ·table+0xe0(SB)/4, $0x6fa87e4f + DATA ·table+0xe4(SB)/4, $0xfe2ce6e0 + DATA ·table+0xe8(SB)/4, $0xa3014314 + DATA ·table+0xec(SB)/4, $0x4e0811a1 + DATA ·table+0xf0(SB)/4, $0xf7537e82 + DATA ·table+0xf4(SB)/4, $0xbd3af235 + DATA ·table+0xf8(SB)/4, $0x2ad7d2bb + DATA ·table+0xfc(SB)/4, $0xeb86d391 + // Global definition + GLOBL ·table(SB),8,$256 diff --git a/src/crypto/md5/md5block_arm64.s b/src/crypto/md5/md5block_arm64.s new file mode 100644 index 0000000..39b9851 --- /dev/null +++ b/src/crypto/md5/md5block_arm64.s @@ -0,0 +1,167 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// ARM64 version of md5block.go +// derived from crypto/md5/md5block_amd64.s + +#include "textflag.h" + +TEXT ·block(SB),NOSPLIT,$0-32 + MOVD dig+0(FP), R0 + MOVD p+8(FP), R1 + MOVD p_len+16(FP), R2 + AND $~63, R2 + CBZ R2, zero + + ADD R1, R2, R21 + LDPW (0*8)(R0), (R4, R5) + LDPW (1*8)(R0), (R6, R7) + +loop: + MOVW R4, R12 + MOVW R5, R13 + MOVW R6, R14 + MOVW R7, R15 + + MOVW (0*4)(R1), R8 + MOVW R7, R9 + +#define ROUND1(a, b, c, d, index, const, shift) \ + ADDW $const, a; \ + ADDW R8, a; \ + MOVW (index*4)(R1), R8; \ + EORW c, R9; \ + ANDW b, R9; \ + EORW d, R9; \ + ADDW R9, a; \ + RORW $(32-shift), a; \ + MOVW c, R9; \ + ADDW b, a + + ROUND1(R4,R5,R6,R7, 1,0xd76aa478, 7); + ROUND1(R7,R4,R5,R6, 2,0xe8c7b756,12); + ROUND1(R6,R7,R4,R5, 3,0x242070db,17); + ROUND1(R5,R6,R7,R4, 4,0xc1bdceee,22); + ROUND1(R4,R5,R6,R7, 5,0xf57c0faf, 7); + ROUND1(R7,R4,R5,R6, 6,0x4787c62a,12); + ROUND1(R6,R7,R4,R5, 7,0xa8304613,17); + ROUND1(R5,R6,R7,R4, 8,0xfd469501,22); + ROUND1(R4,R5,R6,R7, 9,0x698098d8, 7); + ROUND1(R7,R4,R5,R6,10,0x8b44f7af,12); + ROUND1(R6,R7,R4,R5,11,0xffff5bb1,17); + ROUND1(R5,R6,R7,R4,12,0x895cd7be,22); + ROUND1(R4,R5,R6,R7,13,0x6b901122, 7); + ROUND1(R7,R4,R5,R6,14,0xfd987193,12); + ROUND1(R6,R7,R4,R5,15,0xa679438e,17); + ROUND1(R5,R6,R7,R4, 0,0x49b40821,22); + + MOVW (1*4)(R1), R8 + MOVW R7, R9 + MOVW R7, R10 + +#define ROUND2(a, b, c, d, index, const, shift) \ + ADDW $const, a; \ + ADDW R8, a; \ + MOVW (index*4)(R1), R8; \ + ANDW b, R10; \ + BICW R9, c, R9; \ + ORRW R9, R10; \ + MOVW c, R9; \ + ADDW R10, a; \ + MOVW c, R10; \ + RORW $(32-shift), a; \ + ADDW b, a + + ROUND2(R4,R5,R6,R7, 6,0xf61e2562, 5); + ROUND2(R7,R4,R5,R6,11,0xc040b340, 9); + ROUND2(R6,R7,R4,R5, 0,0x265e5a51,14); + ROUND2(R5,R6,R7,R4, 5,0xe9b6c7aa,20); + ROUND2(R4,R5,R6,R7,10,0xd62f105d, 5); + ROUND2(R7,R4,R5,R6,15, 0x2441453, 9); + ROUND2(R6,R7,R4,R5, 4,0xd8a1e681,14); + ROUND2(R5,R6,R7,R4, 9,0xe7d3fbc8,20); + ROUND2(R4,R5,R6,R7,14,0x21e1cde6, 5); + ROUND2(R7,R4,R5,R6, 3,0xc33707d6, 9); + ROUND2(R6,R7,R4,R5, 8,0xf4d50d87,14); + ROUND2(R5,R6,R7,R4,13,0x455a14ed,20); + ROUND2(R4,R5,R6,R7, 2,0xa9e3e905, 5); + ROUND2(R7,R4,R5,R6, 7,0xfcefa3f8, 9); + ROUND2(R6,R7,R4,R5,12,0x676f02d9,14); + ROUND2(R5,R6,R7,R4, 0,0x8d2a4c8a,20); + + MOVW (5*4)(R1), R8 + MOVW R6, R9 + +#define ROUND3(a, b, c, d, index, const, shift) \ + ADDW $const, a; \ + ADDW R8, a; \ + MOVW (index*4)(R1), R8; \ + EORW d, R9; \ + EORW b, R9; \ + ADDW R9, a; \ + RORW $(32-shift), a; \ + MOVW b, R9; \ + ADDW b, a + + ROUND3(R4,R5,R6,R7, 8,0xfffa3942, 4); + ROUND3(R7,R4,R5,R6,11,0x8771f681,11); + ROUND3(R6,R7,R4,R5,14,0x6d9d6122,16); + ROUND3(R5,R6,R7,R4, 1,0xfde5380c,23); + ROUND3(R4,R5,R6,R7, 4,0xa4beea44, 4); + ROUND3(R7,R4,R5,R6, 7,0x4bdecfa9,11); + ROUND3(R6,R7,R4,R5,10,0xf6bb4b60,16); + ROUND3(R5,R6,R7,R4,13,0xbebfbc70,23); + ROUND3(R4,R5,R6,R7, 0,0x289b7ec6, 4); + ROUND3(R7,R4,R5,R6, 3,0xeaa127fa,11); + ROUND3(R6,R7,R4,R5, 6,0xd4ef3085,16); + ROUND3(R5,R6,R7,R4, 9, 0x4881d05,23); + ROUND3(R4,R5,R6,R7,12,0xd9d4d039, 4); + ROUND3(R7,R4,R5,R6,15,0xe6db99e5,11); + ROUND3(R6,R7,R4,R5, 2,0x1fa27cf8,16); + ROUND3(R5,R6,R7,R4, 0,0xc4ac5665,23); + + MOVW (0*4)(R1), R8 + MVNW R7, R9 + +#define ROUND4(a, b, c, d, index, const, shift) \ + ADDW $const, a; \ + ADDW R8, a; \ + MOVW (index*4)(R1), R8; \ + ORRW b, R9; \ + EORW c, R9; \ + ADDW R9, a; \ + RORW $(32-shift), a; \ + MVNW c, R9; \ + ADDW b, a + + ROUND4(R4,R5,R6,R7, 7,0xf4292244, 6); + ROUND4(R7,R4,R5,R6,14,0x432aff97,10); + ROUND4(R6,R7,R4,R5, 5,0xab9423a7,15); + ROUND4(R5,R6,R7,R4,12,0xfc93a039,21); + ROUND4(R4,R5,R6,R7, 3,0x655b59c3, 6); + ROUND4(R7,R4,R5,R6,10,0x8f0ccc92,10); + ROUND4(R6,R7,R4,R5, 1,0xffeff47d,15); + ROUND4(R5,R6,R7,R4, 8,0x85845dd1,21); + ROUND4(R4,R5,R6,R7,15,0x6fa87e4f, 6); + ROUND4(R7,R4,R5,R6, 6,0xfe2ce6e0,10); + ROUND4(R6,R7,R4,R5,13,0xa3014314,15); + ROUND4(R5,R6,R7,R4, 4,0x4e0811a1,21); + ROUND4(R4,R5,R6,R7,11,0xf7537e82, 6); + ROUND4(R7,R4,R5,R6, 2,0xbd3af235,10); + ROUND4(R6,R7,R4,R5, 9,0x2ad7d2bb,15); + ROUND4(R5,R6,R7,R4, 0,0xeb86d391,21); + + ADDW R12, R4 + ADDW R13, R5 + ADDW R14, R6 + ADDW R15, R7 + + ADD $64, R1 + CMP R1, R21 + BNE loop + + STPW (R4, R5), (0*8)(R0) + STPW (R6, R7), (1*8)(R0) +zero: + RET diff --git a/src/crypto/md5/md5block_decl.go b/src/crypto/md5/md5block_decl.go new file mode 100644 index 0000000..bc2d58c --- /dev/null +++ b/src/crypto/md5/md5block_decl.go @@ -0,0 +1,14 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 || 386 || arm || ppc64le || ppc64 || s390x || arm64 +// +build amd64 386 arm ppc64le ppc64 s390x arm64 + +package md5 + +const haveAsm = true + +//go:noescape + +func block(dig *digest, p []byte) diff --git a/src/crypto/md5/md5block_generic.go b/src/crypto/md5/md5block_generic.go new file mode 100644 index 0000000..ea4fbcd --- /dev/null +++ b/src/crypto/md5/md5block_generic.go @@ -0,0 +1,12 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 && !386 && !arm && !ppc64le && !ppc64 && !s390x && !arm64 +// +build !amd64,!386,!arm,!ppc64le,!ppc64,!s390x,!arm64 + +package md5 + +const haveAsm = false + +var block = blockGeneric diff --git a/src/crypto/md5/md5block_ppc64x.s b/src/crypto/md5/md5block_ppc64x.s new file mode 100644 index 0000000..8c28ec2 --- /dev/null +++ b/src/crypto/md5/md5block_ppc64x.s @@ -0,0 +1,213 @@ +// Original source: +// http://www.zorinaq.com/papers/md5-amd64.html +// http://www.zorinaq.com/papers/md5-amd64.tar.bz2 +// +// MD5 optimized for ppc64le using Go's assembler for +// ppc64le, based on md5block_amd64.s implementation by +// the Go authors. +// +// Author: Marc Bevand +// Licence: I hereby disclaim the copyright on this code and place it +// in the public domain. + +//go:build ppc64 || ppc64le +// +build ppc64 ppc64le + +#include "textflag.h" + +// ENDIAN_MOVE generates the appropriate +// 4 byte load for big or little endian. +// The 4 bytes at ptr+off is loaded into dst. +// The idx reg is only needed for big endian +// and is clobbered when used. +#ifdef GOARCH_ppc64le +#define ENDIAN_MOVE(off, ptr, dst, idx) \ + MOVWZ off(ptr),dst +#else +#define ENDIAN_MOVE(off, ptr, dst, idx) \ + MOVD $off,idx; \ + MOVWBR (idx)(ptr), dst +#endif + +#define M00 R18 +#define M01 R19 +#define M02 R20 +#define M03 R24 +#define M04 R25 +#define M05 R26 +#define M06 R27 +#define M07 R28 +#define M08 R29 +#define M09 R21 +#define M10 R11 +#define M11 R8 +#define M12 R7 +#define M13 R12 +#define M14 R23 +#define M15 R10 + +#define ROUND1(a, b, c, d, index, const, shift) \ + ADD $const, index, R9; \ + ADD R9, a; \ + AND b, c, R9; \ + ANDN b, d, R31; \ + OR R9, R31, R9; \ + ADD R9, a; \ + ROTLW $shift, a; \ + ADD b, a; + +#define ROUND2(a, b, c, d, index, const, shift) \ + ADD $const, index, R9; \ + ADD R9, a; \ + AND b, d, R31; \ + ANDN d, c, R9; \ + OR R9, R31; \ + ADD R31, a; \ + ROTLW $shift, a; \ + ADD b, a; + +#define ROUND3(a, b, c, d, index, const, shift) \ + ADD $const, index, R9; \ + ADD R9, a; \ + XOR d, c, R31; \ + XOR b, R31; \ + ADD R31, a; \ + ROTLW $shift, a; \ + ADD b, a; + +#define ROUND4(a, b, c, d, index, const, shift) \ + ADD $const, index, R9; \ + ADD R9, a; \ + ORN d, b, R31; \ + XOR c, R31; \ + ADD R31, a; \ + ROTLW $shift, a; \ + ADD b, a; + + +TEXT ·block(SB),NOSPLIT,$0-32 + MOVD dig+0(FP), R10 + MOVD p+8(FP), R6 + MOVD p_len+16(FP), R5 + + // We assume p_len >= 64 + SRD $6, R5 + MOVD R5, CTR + + MOVWZ 0(R10), R22 + MOVWZ 4(R10), R3 + MOVWZ 8(R10), R4 + MOVWZ 12(R10), R5 + +loop: + MOVD R22, R14 + MOVD R3, R15 + MOVD R4, R16 + MOVD R5, R17 + + ENDIAN_MOVE( 0,R6,M00,M15) + ENDIAN_MOVE( 4,R6,M01,M15) + ENDIAN_MOVE( 8,R6,M02,M15) + ENDIAN_MOVE(12,R6,M03,M15) + + ROUND1(R22,R3,R4,R5,M00,0xd76aa478, 7); + ROUND1(R5,R22,R3,R4,M01,0xe8c7b756,12); + ROUND1(R4,R5,R22,R3,M02,0x242070db,17); + ROUND1(R3,R4,R5,R22,M03,0xc1bdceee,22); + + ENDIAN_MOVE(16,R6,M04,M15) + ENDIAN_MOVE(20,R6,M05,M15) + ENDIAN_MOVE(24,R6,M06,M15) + ENDIAN_MOVE(28,R6,M07,M15) + + ROUND1(R22,R3,R4,R5,M04,0xf57c0faf, 7); + ROUND1(R5,R22,R3,R4,M05,0x4787c62a,12); + ROUND1(R4,R5,R22,R3,M06,0xa8304613,17); + ROUND1(R3,R4,R5,R22,M07,0xfd469501,22); + + ENDIAN_MOVE(32,R6,M08,M15) + ENDIAN_MOVE(36,R6,M09,M15) + ENDIAN_MOVE(40,R6,M10,M15) + ENDIAN_MOVE(44,R6,M11,M15) + + ROUND1(R22,R3,R4,R5,M08,0x698098d8, 7); + ROUND1(R5,R22,R3,R4,M09,0x8b44f7af,12); + ROUND1(R4,R5,R22,R3,M10,0xffff5bb1,17); + ROUND1(R3,R4,R5,R22,M11,0x895cd7be,22); + + ENDIAN_MOVE(48,R6,M12,M15) + ENDIAN_MOVE(52,R6,M13,M15) + ENDIAN_MOVE(56,R6,M14,M15) + ENDIAN_MOVE(60,R6,M15,M15) + + ROUND1(R22,R3,R4,R5,M12,0x6b901122, 7); + ROUND1(R5,R22,R3,R4,M13,0xfd987193,12); + ROUND1(R4,R5,R22,R3,M14,0xa679438e,17); + ROUND1(R3,R4,R5,R22,M15,0x49b40821,22); + + ROUND2(R22,R3,R4,R5,M01,0xf61e2562, 5); + ROUND2(R5,R22,R3,R4,M06,0xc040b340, 9); + ROUND2(R4,R5,R22,R3,M11,0x265e5a51,14); + ROUND2(R3,R4,R5,R22,M00,0xe9b6c7aa,20); + ROUND2(R22,R3,R4,R5,M05,0xd62f105d, 5); + ROUND2(R5,R22,R3,R4,M10, 0x2441453, 9); + ROUND2(R4,R5,R22,R3,M15,0xd8a1e681,14); + ROUND2(R3,R4,R5,R22,M04,0xe7d3fbc8,20); + ROUND2(R22,R3,R4,R5,M09,0x21e1cde6, 5); + ROUND2(R5,R22,R3,R4,M14,0xc33707d6, 9); + ROUND2(R4,R5,R22,R3,M03,0xf4d50d87,14); + ROUND2(R3,R4,R5,R22,M08,0x455a14ed,20); + ROUND2(R22,R3,R4,R5,M13,0xa9e3e905, 5); + ROUND2(R5,R22,R3,R4,M02,0xfcefa3f8, 9); + ROUND2(R4,R5,R22,R3,M07,0x676f02d9,14); + ROUND2(R3,R4,R5,R22,M12,0x8d2a4c8a,20); + + ROUND3(R22,R3,R4,R5,M05,0xfffa3942, 4); + ROUND3(R5,R22,R3,R4,M08,0x8771f681,11); + ROUND3(R4,R5,R22,R3,M11,0x6d9d6122,16); + ROUND3(R3,R4,R5,R22,M14,0xfde5380c,23); + ROUND3(R22,R3,R4,R5,M01,0xa4beea44, 4); + ROUND3(R5,R22,R3,R4,M04,0x4bdecfa9,11); + ROUND3(R4,R5,R22,R3,M07,0xf6bb4b60,16); + ROUND3(R3,R4,R5,R22,M10,0xbebfbc70,23); + ROUND3(R22,R3,R4,R5,M13,0x289b7ec6, 4); + ROUND3(R5,R22,R3,R4,M00,0xeaa127fa,11); + ROUND3(R4,R5,R22,R3,M03,0xd4ef3085,16); + ROUND3(R3,R4,R5,R22,M06, 0x4881d05,23); + ROUND3(R22,R3,R4,R5,M09,0xd9d4d039, 4); + ROUND3(R5,R22,R3,R4,M12,0xe6db99e5,11); + ROUND3(R4,R5,R22,R3,M15,0x1fa27cf8,16); + ROUND3(R3,R4,R5,R22,M02,0xc4ac5665,23); + + ROUND4(R22,R3,R4,R5,M00,0xf4292244, 6); + ROUND4(R5,R22,R3,R4,M07,0x432aff97,10); + ROUND4(R4,R5,R22,R3,M14,0xab9423a7,15); + ROUND4(R3,R4,R5,R22,M05,0xfc93a039,21); + ROUND4(R22,R3,R4,R5,M12,0x655b59c3, 6); + ROUND4(R5,R22,R3,R4,M03,0x8f0ccc92,10); + ROUND4(R4,R5,R22,R3,M10,0xffeff47d,15); + ROUND4(R3,R4,R5,R22,M01,0x85845dd1,21); + ROUND4(R22,R3,R4,R5,M08,0x6fa87e4f, 6); + ROUND4(R5,R22,R3,R4,M15,0xfe2ce6e0,10); + ROUND4(R4,R5,R22,R3,M06,0xa3014314,15); + ROUND4(R3,R4,R5,R22,M13,0x4e0811a1,21); + ROUND4(R22,R3,R4,R5,M04,0xf7537e82, 6); + ROUND4(R5,R22,R3,R4,M11,0xbd3af235,10); + ROUND4(R4,R5,R22,R3,M02,0x2ad7d2bb,15); + ROUND4(R3,R4,R5,R22,M09,0xeb86d391,21); + + ADD R14, R22 + ADD R15, R3 + ADD R16, R4 + ADD R17, R5 + ADD $64, R6 + BC 16, 0, loop // bdnz + +end: + MOVD dig+0(FP), R10 + MOVWZ R22, 0(R10) + MOVWZ R3, 4(R10) + MOVWZ R4, 8(R10) + MOVWZ R5, 12(R10) + + RET diff --git a/src/crypto/md5/md5block_s390x.s b/src/crypto/md5/md5block_s390x.s new file mode 100644 index 0000000..68f501c --- /dev/null +++ b/src/crypto/md5/md5block_s390x.s @@ -0,0 +1,175 @@ +// Original source: +// http://www.zorinaq.com/papers/md5-amd64.html +// http://www.zorinaq.com/papers/md5-amd64.tar.bz2 +// +// MD5 adapted for s390x using Go's assembler for +// s390x, based on md5block_amd64.s implementation by +// the Go authors. +// +// Author: Marc Bevand +// Licence: I hereby disclaim the copyright on this code and place it +// in the public domain. + +#include "textflag.h" + +// func block(dig *digest, p []byte) +TEXT ·block(SB),NOSPLIT,$16-32 + MOVD dig+0(FP), R1 + MOVD p+8(FP), R6 + MOVD p_len+16(FP), R5 + AND $-64, R5 + LAY (R6)(R5*1), R7 + + LMY 0(R1), R2, R5 + CMPBEQ R6, R7, end + +loop: + STMY R2, R5, tmp-16(SP) + + MOVWBR 0(R6), R8 + MOVWZ R5, R9 + +#define ROUND1(a, b, c, d, index, const, shift) \ + XOR c, R9; \ + ADD $const, a; \ + ADD R8, a; \ + MOVWBR (index*4)(R6), R8; \ + AND b, R9; \ + XOR d, R9; \ + ADD R9, a; \ + RLL $shift, a; \ + MOVWZ c, R9; \ + ADD b, a + + ROUND1(R2,R3,R4,R5, 1,0xd76aa478, 7); + ROUND1(R5,R2,R3,R4, 2,0xe8c7b756,12); + ROUND1(R4,R5,R2,R3, 3,0x242070db,17); + ROUND1(R3,R4,R5,R2, 4,0xc1bdceee,22); + ROUND1(R2,R3,R4,R5, 5,0xf57c0faf, 7); + ROUND1(R5,R2,R3,R4, 6,0x4787c62a,12); + ROUND1(R4,R5,R2,R3, 7,0xa8304613,17); + ROUND1(R3,R4,R5,R2, 8,0xfd469501,22); + ROUND1(R2,R3,R4,R5, 9,0x698098d8, 7); + ROUND1(R5,R2,R3,R4,10,0x8b44f7af,12); + ROUND1(R4,R5,R2,R3,11,0xffff5bb1,17); + ROUND1(R3,R4,R5,R2,12,0x895cd7be,22); + ROUND1(R2,R3,R4,R5,13,0x6b901122, 7); + ROUND1(R5,R2,R3,R4,14,0xfd987193,12); + ROUND1(R4,R5,R2,R3,15,0xa679438e,17); + ROUND1(R3,R4,R5,R2, 0,0x49b40821,22); + + MOVWBR (1*4)(R6), R8 + MOVWZ R5, R9 + MOVWZ R5, R1 + +#define ROUND2(a, b, c, d, index, const, shift) \ + XOR $0xffffffff, R9; \ // NOTW R9 + ADD $const, a; \ + ADD R8, a; \ + MOVWBR (index*4)(R6), R8; \ + AND b, R1; \ + AND c, R9; \ + OR R9, R1; \ + MOVWZ c, R9; \ + ADD R1, a; \ + MOVWZ c, R1; \ + RLL $shift, a; \ + ADD b, a + + ROUND2(R2,R3,R4,R5, 6,0xf61e2562, 5); + ROUND2(R5,R2,R3,R4,11,0xc040b340, 9); + ROUND2(R4,R5,R2,R3, 0,0x265e5a51,14); + ROUND2(R3,R4,R5,R2, 5,0xe9b6c7aa,20); + ROUND2(R2,R3,R4,R5,10,0xd62f105d, 5); + ROUND2(R5,R2,R3,R4,15, 0x2441453, 9); + ROUND2(R4,R5,R2,R3, 4,0xd8a1e681,14); + ROUND2(R3,R4,R5,R2, 9,0xe7d3fbc8,20); + ROUND2(R2,R3,R4,R5,14,0x21e1cde6, 5); + ROUND2(R5,R2,R3,R4, 3,0xc33707d6, 9); + ROUND2(R4,R5,R2,R3, 8,0xf4d50d87,14); + ROUND2(R3,R4,R5,R2,13,0x455a14ed,20); + ROUND2(R2,R3,R4,R5, 2,0xa9e3e905, 5); + ROUND2(R5,R2,R3,R4, 7,0xfcefa3f8, 9); + ROUND2(R4,R5,R2,R3,12,0x676f02d9,14); + ROUND2(R3,R4,R5,R2, 0,0x8d2a4c8a,20); + + MOVWBR (5*4)(R6), R8 + MOVWZ R4, R9 + +#define ROUND3(a, b, c, d, index, const, shift) \ + ADD $const, a; \ + ADD R8, a; \ + MOVWBR (index*4)(R6), R8; \ + XOR d, R9; \ + XOR b, R9; \ + ADD R9, a; \ + RLL $shift, a; \ + MOVWZ b, R9; \ + ADD b, a + + ROUND3(R2,R3,R4,R5, 8,0xfffa3942, 4); + ROUND3(R5,R2,R3,R4,11,0x8771f681,11); + ROUND3(R4,R5,R2,R3,14,0x6d9d6122,16); + ROUND3(R3,R4,R5,R2, 1,0xfde5380c,23); + ROUND3(R2,R3,R4,R5, 4,0xa4beea44, 4); + ROUND3(R5,R2,R3,R4, 7,0x4bdecfa9,11); + ROUND3(R4,R5,R2,R3,10,0xf6bb4b60,16); + ROUND3(R3,R4,R5,R2,13,0xbebfbc70,23); + ROUND3(R2,R3,R4,R5, 0,0x289b7ec6, 4); + ROUND3(R5,R2,R3,R4, 3,0xeaa127fa,11); + ROUND3(R4,R5,R2,R3, 6,0xd4ef3085,16); + ROUND3(R3,R4,R5,R2, 9, 0x4881d05,23); + ROUND3(R2,R3,R4,R5,12,0xd9d4d039, 4); + ROUND3(R5,R2,R3,R4,15,0xe6db99e5,11); + ROUND3(R4,R5,R2,R3, 2,0x1fa27cf8,16); + ROUND3(R3,R4,R5,R2, 0,0xc4ac5665,23); + + MOVWBR (0*4)(R6), R8 + MOVWZ $0xffffffff, R9 + XOR R5, R9 + +#define ROUND4(a, b, c, d, index, const, shift) \ + ADD $const, a; \ + ADD R8, a; \ + MOVWBR (index*4)(R6), R8; \ + OR b, R9; \ + XOR c, R9; \ + ADD R9, a; \ + MOVWZ $0xffffffff, R9; \ + RLL $shift, a; \ + XOR c, R9; \ + ADD b, a + + ROUND4(R2,R3,R4,R5, 7,0xf4292244, 6); + ROUND4(R5,R2,R3,R4,14,0x432aff97,10); + ROUND4(R4,R5,R2,R3, 5,0xab9423a7,15); + ROUND4(R3,R4,R5,R2,12,0xfc93a039,21); + ROUND4(R2,R3,R4,R5, 3,0x655b59c3, 6); + ROUND4(R5,R2,R3,R4,10,0x8f0ccc92,10); + ROUND4(R4,R5,R2,R3, 1,0xffeff47d,15); + ROUND4(R3,R4,R5,R2, 8,0x85845dd1,21); + ROUND4(R2,R3,R4,R5,15,0x6fa87e4f, 6); + ROUND4(R5,R2,R3,R4, 6,0xfe2ce6e0,10); + ROUND4(R4,R5,R2,R3,13,0xa3014314,15); + ROUND4(R3,R4,R5,R2, 4,0x4e0811a1,21); + ROUND4(R2,R3,R4,R5,11,0xf7537e82, 6); + ROUND4(R5,R2,R3,R4, 2,0xbd3af235,10); + ROUND4(R4,R5,R2,R3, 9,0x2ad7d2bb,15); + ROUND4(R3,R4,R5,R2, 0,0xeb86d391,21); + + MOVWZ tmp-16(SP), R1 + ADD R1, R2 + MOVWZ tmp-12(SP), R1 + ADD R1, R3 + MOVWZ tmp-8(SP), R1 + ADD R1, R4 + MOVWZ tmp-4(SP), R1 + ADD R1, R5 + + LA 64(R6), R6 + CMPBLT R6, R7, loop + +end: + MOVD dig+0(FP), R1 + STMY R2, R5, 0(R1) + RET diff --git a/src/crypto/rand/eagain.go b/src/crypto/rand/eagain.go new file mode 100644 index 0000000..85d4d9d --- /dev/null +++ b/src/crypto/rand/eagain.go @@ -0,0 +1,28 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package rand + +import ( + "io/fs" + "syscall" +) + +func init() { + isEAGAIN = unixIsEAGAIN +} + +// unixIsEAGAIN reports whether err is a syscall.EAGAIN wrapped in a PathError. +// See golang.org/issue/9205 +func unixIsEAGAIN(err error) bool { + if pe, ok := err.(*fs.PathError); ok { + if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EAGAIN { + return true + } + } + return false +} diff --git a/src/crypto/rand/example_test.go b/src/crypto/rand/example_test.go new file mode 100644 index 0000000..ed18647 --- /dev/null +++ b/src/crypto/rand/example_test.go @@ -0,0 +1,28 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand_test + +import ( + "bytes" + "crypto/rand" + "fmt" +) + +// This example reads 10 cryptographically secure pseudorandom numbers from +// rand.Reader and writes them to a byte slice. +func ExampleRead() { + c := 10 + b := make([]byte, c) + _, err := rand.Read(b) + if err != nil { + fmt.Println("error:", err) + return + } + // The slice should now contain random bytes instead of only zeroes. + fmt.Println(bytes.Equal(b, make([]byte, c))) + + // Output: + // false +} diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go new file mode 100644 index 0000000..f2c2760 --- /dev/null +++ b/src/crypto/rand/rand.go @@ -0,0 +1,43 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package rand implements a cryptographically secure +// random number generator. +package rand + +import "io" + +// Reader is a global, shared instance of a cryptographically +// secure random number generator. +// +// On Linux and FreeBSD, Reader uses getrandom(2) if available, /dev/urandom otherwise. +// On OpenBSD, Reader uses getentropy(2). +// On other Unix-like systems, Reader reads from /dev/urandom. +// On Windows systems, Reader uses the RtlGenRandom API. +// On Wasm, Reader uses the Web Crypto API. +var Reader io.Reader + +// Read is a helper function that calls Reader.Read using io.ReadFull. +// On return, n == len(b) if and only if err == nil. +func Read(b []byte) (n int, err error) { + return io.ReadFull(Reader, b) +} + +// batched returns a function that calls f to populate a []byte by chunking it +// into subslices of, at most, readMax bytes. +func batched(f func([]byte) error, readMax int) func([]byte) error { + return func(out []byte) error { + for len(out) > 0 { + read := len(out) + if read > readMax { + read = readMax + } + if err := f(out[:read]); err != nil { + return err + } + out = out[read:] + } + return nil + } +} diff --git a/src/crypto/rand/rand_batched.go b/src/crypto/rand/rand_batched.go new file mode 100644 index 0000000..8df715f --- /dev/null +++ b/src/crypto/rand/rand_batched.go @@ -0,0 +1,33 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux || freebsd || dragonfly || solaris +// +build linux freebsd dragonfly solaris + +package rand + +import ( + "errors" + "internal/syscall/unix" +) + +// maxGetRandomRead is platform dependent. +func init() { + altGetRandom = batched(getRandomBatch, maxGetRandomRead) +} + +// If the kernel is too old to support the getrandom syscall(), +// unix.GetRandom will immediately return ENOSYS and we will then fall back to +// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS +// result so we only suffer the syscall overhead once in this case. +// If the kernel supports the getrandom() syscall, unix.GetRandom will block +// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK). +// In this case, unix.GetRandom will not return an error. +func getRandomBatch(p []byte) error { + n, err := unix.GetRandom(p, 0) + if n != len(p) { + return errors.New("short read") + } + return err +} diff --git a/src/crypto/rand/rand_batched_test.go b/src/crypto/rand/rand_batched_test.go new file mode 100644 index 0000000..b56345e --- /dev/null +++ b/src/crypto/rand/rand_batched_test.go @@ -0,0 +1,46 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux || freebsd || dragonfly || solaris +// +build linux freebsd dragonfly solaris + +package rand + +import ( + "bytes" + "errors" + "testing" +) + +func TestBatched(t *testing.T) { + fillBatched := batched(func(p []byte) error { + for i := range p { + p[i] = byte(i) + } + return nil + }, 5) + + p := make([]byte, 13) + if err := fillBatched(p); err != nil { + t.Fatalf("batched function returned error: %s", err) + } + expected := []byte{0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2} + if !bytes.Equal(expected, p) { + t.Errorf("incorrect batch result: got %x, want %x", p, expected) + } +} + +func TestBatchedError(t *testing.T) { + b := batched(func(p []byte) error { return errors.New("") }, 5) + if b(make([]byte, 13)) == nil { + t.Fatal("batched function should have returned an error") + } +} + +func TestBatchedEmpty(t *testing.T) { + b := batched(func(p []byte) error { return errors.New("") }, 5) + if err := b(make([]byte, 0)); err != nil { + t.Fatalf("empty slice should always return nil: %s", err) + } +} diff --git a/src/crypto/rand/rand_dragonfly.go b/src/crypto/rand/rand_dragonfly.go new file mode 100644 index 0000000..8a36fea --- /dev/null +++ b/src/crypto/rand/rand_dragonfly.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +// maxGetRandomRead is the maximum number of bytes to ask for in one call to the +// getrandom() syscall. In DragonFlyBSD at most 256 bytes will be returned per call. +const maxGetRandomRead = 1 << 8 diff --git a/src/crypto/rand/rand_freebsd.go b/src/crypto/rand/rand_freebsd.go new file mode 100644 index 0000000..75f683c --- /dev/null +++ b/src/crypto/rand/rand_freebsd.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +// maxGetRandomRead is the maximum number of bytes to ask for in one call to the +// getrandom() syscall. In FreeBSD at most 256 bytes will be returned per call. +const maxGetRandomRead = 1 << 8 diff --git a/src/crypto/rand/rand_getentropy.go b/src/crypto/rand/rand_getentropy.go new file mode 100644 index 0000000..b1c19f3 --- /dev/null +++ b/src/crypto/rand/rand_getentropy.go @@ -0,0 +1,31 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin && !ios) || openbsd +// +build darwin,!ios openbsd + +package rand + +import ( + "internal/syscall/unix" +) + +func init() { + altGetRandom = getEntropy +} + +func getEntropy(p []byte) error { + // getentropy(2) returns a maximum of 256 bytes per call + for i := 0; i < len(p); i += 256 { + end := i + 256 + if len(p) < end { + end = len(p) + } + err := unix.GetEntropy(p[i:end]) + if err != nil { + return err + } + } + return nil +} diff --git a/src/crypto/rand/rand_js.go b/src/crypto/rand/rand_js.go new file mode 100644 index 0000000..7ddc2b6 --- /dev/null +++ b/src/crypto/rand/rand_js.go @@ -0,0 +1,29 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build js && wasm +// +build js,wasm + +package rand + +import "syscall/js" + +func init() { + Reader = &reader{} +} + +var jsCrypto = js.Global().Get("crypto") +var uint8Array = js.Global().Get("Uint8Array") + +// reader implements a pseudorandom generator +// using JavaScript crypto.getRandomValues method. +// See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues. +type reader struct{} + +func (r *reader) Read(b []byte) (int, error) { + a := uint8Array.New(len(b)) + jsCrypto.Call("getRandomValues", a) + js.CopyBytesToGo(b, a) + return len(b), nil +} diff --git a/src/crypto/rand/rand_linux.go b/src/crypto/rand/rand_linux.go new file mode 100644 index 0000000..26b93c5 --- /dev/null +++ b/src/crypto/rand/rand_linux.go @@ -0,0 +1,14 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +// maxGetRandomRead is the maximum number of bytes to ask for in one call to the +// getrandom() syscall. In linux at most 2^25-1 bytes will be returned per call. +// From the manpage +// +// * When reading from the urandom source, a maximum of 33554431 bytes +// is returned by a single call to getrandom() on systems where int +// has a size of 32 bits. +const maxGetRandomRead = (1 << 25) - 1 diff --git a/src/crypto/rand/rand_solaris.go b/src/crypto/rand/rand_solaris.go new file mode 100644 index 0000000..bbad0fe --- /dev/null +++ b/src/crypto/rand/rand_solaris.go @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +// maxGetRandomRead is the maximum number of bytes to ask for in one call to the +// getrandom() syscall. Across all the Solaris platforms, 256 bytes is the +// lowest number of bytes returned atomically per call. +const maxGetRandomRead = 1 << 8 diff --git a/src/crypto/rand/rand_test.go b/src/crypto/rand/rand_test.go new file mode 100644 index 0000000..e45f58e --- /dev/null +++ b/src/crypto/rand/rand_test.go @@ -0,0 +1,43 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "bytes" + "compress/flate" + "io" + "testing" +) + +func TestRead(t *testing.T) { + var n int = 4e6 + if testing.Short() { + n = 1e5 + } + b := make([]byte, n) + n, err := io.ReadFull(Reader, b) + if n != len(b) || err != nil { + t.Fatalf("ReadFull(buf) = %d, %s", n, err) + } + + var z bytes.Buffer + f, _ := flate.NewWriter(&z, 5) + f.Write(b) + f.Close() + if z.Len() < len(b)*99/100 { + t.Fatalf("Compressed %d -> %d", len(b), z.Len()) + } +} + +func TestReadEmpty(t *testing.T) { + n, err := Reader.Read(make([]byte, 0)) + if n != 0 || err != nil { + t.Fatalf("Read(make([]byte, 0)) = %d, %v", n, err) + } + n, err = Reader.Read(nil) + if n != 0 || err != nil { + t.Fatalf("Read(nil) = %d, %v", n, err) + } +} diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go new file mode 100644 index 0000000..3d11159 --- /dev/null +++ b/src/crypto/rand/rand_unix.go @@ -0,0 +1,170 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || plan9 || solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd plan9 solaris + +// Unix cryptographically secure pseudorandom number +// generator. + +package rand + +import ( + "bufio" + "crypto/aes" + "crypto/cipher" + "encoding/binary" + "io" + "os" + "runtime" + "sync" + "sync/atomic" + "time" +) + +const urandomDevice = "/dev/urandom" + +// Easy implementation: read from /dev/urandom. +// This is sufficient on Linux, OS X, and FreeBSD. + +func init() { + if runtime.GOOS == "plan9" { + Reader = newReader(nil) + } else { + Reader = &devReader{name: urandomDevice} + } +} + +// A devReader satisfies reads by reading the file named name. +type devReader struct { + name string + f io.Reader + mu sync.Mutex + used int32 // atomic; whether this devReader has been used +} + +// altGetRandom if non-nil specifies an OS-specific function to get +// urandom-style randomness. +var altGetRandom func([]byte) (err error) + +func warnBlocked() { + println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel") +} + +func (r *devReader) Read(b []byte) (n int, err error) { + if atomic.CompareAndSwapInt32(&r.used, 0, 1) { + // First use of randomness. Start timer to warn about + // being blocked on entropy not being available. + t := time.AfterFunc(60*time.Second, warnBlocked) + defer t.Stop() + } + if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) == nil { + return len(b), nil + } + r.mu.Lock() + defer r.mu.Unlock() + if r.f == nil { + f, err := os.Open(r.name) + if f == nil { + return 0, err + } + if runtime.GOOS == "plan9" { + r.f = f + } else { + r.f = bufio.NewReader(hideAgainReader{f}) + } + } + return r.f.Read(b) +} + +var isEAGAIN func(error) bool // set by eagain.go on unix systems + +// hideAgainReader masks EAGAIN reads from /dev/urandom. +// See golang.org/issue/9205 +type hideAgainReader struct { + r io.Reader +} + +func (hr hideAgainReader) Read(p []byte) (n int, err error) { + n, err = hr.r.Read(p) + if err != nil && isEAGAIN != nil && isEAGAIN(err) { + err = nil + } + return +} + +// Alternate pseudo-random implementation for use on +// systems without a reliable /dev/urandom. + +// newReader returns a new pseudorandom generator that +// seeds itself by reading from entropy. If entropy == nil, +// the generator seeds itself by reading from the system's +// random number generator, typically /dev/random. +// The Read method on the returned reader always returns +// the full amount asked for, or else it returns an error. +// +// The generator uses the X9.31 algorithm with AES-128, +// reseeding after every 1 MB of generated data. +func newReader(entropy io.Reader) io.Reader { + if entropy == nil { + entropy = &devReader{name: "/dev/random"} + } + return &reader{entropy: entropy} +} + +type reader struct { + mu sync.Mutex + budget int // number of bytes that can be generated + cipher cipher.Block + entropy io.Reader + time, seed, dst, key [aes.BlockSize]byte +} + +func (r *reader) Read(b []byte) (n int, err error) { + r.mu.Lock() + defer r.mu.Unlock() + n = len(b) + + for len(b) > 0 { + if r.budget == 0 { + _, err := io.ReadFull(r.entropy, r.seed[0:]) + if err != nil { + return n - len(b), err + } + _, err = io.ReadFull(r.entropy, r.key[0:]) + if err != nil { + return n - len(b), err + } + r.cipher, err = aes.NewCipher(r.key[0:]) + if err != nil { + return n - len(b), err + } + r.budget = 1 << 20 // reseed after generating 1MB + } + r.budget -= aes.BlockSize + + // ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES. + // + // single block: + // t = encrypt(time) + // dst = encrypt(t^seed) + // seed = encrypt(t^dst) + ns := time.Now().UnixNano() + binary.BigEndian.PutUint64(r.time[:], uint64(ns)) + r.cipher.Encrypt(r.time[0:], r.time[0:]) + for i := 0; i < aes.BlockSize; i++ { + r.dst[i] = r.time[i] ^ r.seed[i] + } + r.cipher.Encrypt(r.dst[0:], r.dst[0:]) + for i := 0; i < aes.BlockSize; i++ { + r.seed[i] = r.time[i] ^ r.dst[i] + } + r.cipher.Encrypt(r.seed[0:], r.seed[0:]) + + m := copy(b, r.dst[0:]) + b = b[m:] + } + + return n, nil +} diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go new file mode 100644 index 0000000..6c0655c --- /dev/null +++ b/src/crypto/rand/rand_windows.go @@ -0,0 +1,26 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Windows cryptographically secure pseudorandom number +// generator. + +package rand + +import ( + "internal/syscall/windows" +) + +func init() { Reader = &rngReader{} } + +type rngReader struct{} + +func (r *rngReader) Read(b []byte) (n int, err error) { + // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at + // most 1<<31-1 bytes at a time so that this works the same on 32-bit + // and 64-bit systems. + if err := batched(windows.RtlGenRandom, 1<<31-1)(b); err != nil { + return 0, err + } + return len(b), nil +} diff --git a/src/crypto/rand/util.go b/src/crypto/rand/util.go new file mode 100644 index 0000000..4dd1711 --- /dev/null +++ b/src/crypto/rand/util.go @@ -0,0 +1,143 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "errors" + "io" + "math/big" +) + +// smallPrimes is a list of small, prime numbers that allows us to rapidly +// exclude some fraction of composite candidates when searching for a random +// prime. This list is truncated at the point where smallPrimesProduct exceeds +// a uint64. It does not include two because we ensure that the candidates are +// odd by construction. +var smallPrimes = []uint8{ + 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, +} + +// smallPrimesProduct is the product of the values in smallPrimes and allows us +// to reduce a candidate prime by this number and then determine whether it's +// coprime to all the elements of smallPrimes without further big.Int +// operations. +var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365) + +// Prime returns a number, p, of the given size, such that p is prime +// with high probability. +// Prime will return error for any error returned by rand.Read or if bits < 2. +func Prime(rand io.Reader, bits int) (p *big.Int, err error) { + if bits < 2 { + err = errors.New("crypto/rand: prime size must be at least 2-bit") + return + } + + b := uint(bits % 8) + if b == 0 { + b = 8 + } + + bytes := make([]byte, (bits+7)/8) + p = new(big.Int) + + bigMod := new(big.Int) + + for { + _, err = io.ReadFull(rand, bytes) + if err != nil { + return nil, err + } + + // Clear bits in the first byte to make sure the candidate has a size <= bits. + bytes[0] &= uint8(int(1<= 2 { + bytes[0] |= 3 << (b - 2) + } else { + // Here b==1, because b cannot be zero. + bytes[0] |= 1 + if len(bytes) > 1 { + bytes[1] |= 0x80 + } + } + // Make the value odd since an even number this large certainly isn't prime. + bytes[len(bytes)-1] |= 1 + + p.SetBytes(bytes) + + // Calculate the value mod the product of smallPrimes. If it's + // a multiple of any of these primes we add two until it isn't. + // The probability of overflowing is minimal and can be ignored + // because we still perform Miller-Rabin tests on the result. + bigMod.Mod(p, smallPrimesProduct) + mod := bigMod.Uint64() + + NextDelta: + for delta := uint64(0); delta < 1<<20; delta += 2 { + m := mod + delta + for _, prime := range smallPrimes { + if m%uint64(prime) == 0 && (bits > 6 || m != uint64(prime)) { + continue NextDelta + } + } + + if delta > 0 { + bigMod.SetUint64(delta) + p.Add(p, bigMod) + } + break + } + + // There is a tiny possibility that, by adding delta, we caused + // the number to be one bit too long. Thus we check BitLen + // here. + if p.ProbablyPrime(20) && p.BitLen() == bits { + return + } + } +} + +// Int returns a uniform random value in [0, max). It panics if max <= 0. +func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) { + if max.Sign() <= 0 { + panic("crypto/rand: argument to Int is <= 0") + } + n = new(big.Int) + n.Sub(max, n.SetUint64(1)) + // bitLen is the maximum bit length needed to encode a value < max. + bitLen := n.BitLen() + if bitLen == 0 { + // the only valid result is 0 + return + } + // k is the maximum byte length needed to encode a value < max. + k := (bitLen + 7) / 8 + // b is the number of bits in the most significant byte of max-1. + b := uint(bitLen % 8) + if b == 0 { + b = 8 + } + + bytes := make([]byte, k) + + for { + _, err = io.ReadFull(rand, bytes) + if err != nil { + return nil, err + } + + // Clear bits in the first byte to increase the probability + // that the candidate is < max. + bytes[0] &= uint8(int(1< 256 { + return nil, KeySizeError(k) + } + var c Cipher + for i := 0; i < 256; i++ { + c.s[i] = uint32(i) + } + var j uint8 = 0 + for i := 0; i < 256; i++ { + j += uint8(c.s[i]) + key[i%k] + c.s[i], c.s[j] = c.s[j], c.s[i] + } + return &c, nil +} + +// Reset zeros the key data and makes the Cipher unusable. +// +// Deprecated: Reset can't guarantee that the key will be entirely removed from +// the process's memory. +func (c *Cipher) Reset() { + for i := range c.s { + c.s[i] = 0 + } + c.i, c.j = 0, 0 +} + +// XORKeyStream sets dst to the result of XORing src with the key stream. +// Dst and src must overlap entirely or not at all. +func (c *Cipher) XORKeyStream(dst, src []byte) { + if len(src) == 0 { + return + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/rc4: invalid buffer overlap") + } + i, j := c.i, c.j + _ = dst[len(src)-1] + dst = dst[:len(src)] // eliminate bounds check from loop + for k, v := range src { + i += 1 + x := c.s[i] + j += uint8(x) + y := c.s[j] + c.s[i], c.s[j] = y, x + dst[k] = v ^ uint8(c.s[uint8(x+y)]) + } + c.i, c.j = i, j +} diff --git a/src/crypto/rc4/rc4_test.go b/src/crypto/rc4/rc4_test.go new file mode 100644 index 0000000..e7356aa --- /dev/null +++ b/src/crypto/rc4/rc4_test.go @@ -0,0 +1,162 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rc4 + +import ( + "bytes" + "fmt" + "testing" +) + +type rc4Test struct { + key, keystream []byte +} + +var golden = []rc4Test{ + // Test vectors from the original cypherpunk posting of ARC4: + // https://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0?pli=1 + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + []byte{0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79}, + }, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a}, + }, + { + []byte{0xef, 0x01, 0x23, 0x45}, + []byte{0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, 0xbd, 0x61}, + }, + + // Test vectors from the Wikipedia page: https://en.wikipedia.org/wiki/RC4 + { + []byte{0x4b, 0x65, 0x79}, + []byte{0xeb, 0x9f, 0x77, 0x81, 0xb7, 0x34, 0xca, 0x72, 0xa7, 0x19}, + }, + { + []byte{0x57, 0x69, 0x6b, 0x69}, + []byte{0x60, 0x44, 0xdb, 0x6d, 0x41, 0xb7}, + }, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{ + 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a, + 0x8a, 0x06, 0x1e, 0x67, 0x57, 0x6e, 0x92, 0x6d, + 0xc7, 0x1a, 0x7f, 0xa3, 0xf0, 0xcc, 0xeb, 0x97, + 0x45, 0x2b, 0x4d, 0x32, 0x27, 0x96, 0x5f, 0x9e, + 0xa8, 0xcc, 0x75, 0x07, 0x6d, 0x9f, 0xb9, 0xc5, + 0x41, 0x7a, 0xa5, 0xcb, 0x30, 0xfc, 0x22, 0x19, + 0x8b, 0x34, 0x98, 0x2d, 0xbb, 0x62, 0x9e, 0xc0, + 0x4b, 0x4f, 0x8b, 0x05, 0xa0, 0x71, 0x08, 0x50, + 0x92, 0xa0, 0xc3, 0x58, 0x4a, 0x48, 0xe4, 0xa3, + 0x0a, 0x39, 0x7b, 0x8a, 0xcd, 0x1d, 0x00, 0x9e, + 0xc8, 0x7d, 0x68, 0x11, 0xf2, 0x2c, 0xf4, 0x9c, + 0xa3, 0xe5, 0x93, 0x54, 0xb9, 0x45, 0x15, 0x35, + 0xa2, 0x18, 0x7a, 0x86, 0x42, 0x6c, 0xca, 0x7d, + 0x5e, 0x82, 0x3e, 0xba, 0x00, 0x44, 0x12, 0x67, + 0x12, 0x57, 0xb8, 0xd8, 0x60, 0xae, 0x4c, 0xbd, + 0x4c, 0x49, 0x06, 0xbb, 0xc5, 0x35, 0xef, 0xe1, + 0x58, 0x7f, 0x08, 0xdb, 0x33, 0x95, 0x5c, 0xdb, + 0xcb, 0xad, 0x9b, 0x10, 0xf5, 0x3f, 0xc4, 0xe5, + 0x2c, 0x59, 0x15, 0x65, 0x51, 0x84, 0x87, 0xfe, + 0x08, 0x4d, 0x0e, 0x3f, 0x03, 0xde, 0xbc, 0xc9, + 0xda, 0x1c, 0xe9, 0x0d, 0x08, 0x5c, 0x2d, 0x8a, + 0x19, 0xd8, 0x37, 0x30, 0x86, 0x16, 0x36, 0x92, + 0x14, 0x2b, 0xd8, 0xfc, 0x5d, 0x7a, 0x73, 0x49, + 0x6a, 0x8e, 0x59, 0xee, 0x7e, 0xcf, 0x6b, 0x94, + 0x06, 0x63, 0xf4, 0xa6, 0xbe, 0xe6, 0x5b, 0xd2, + 0xc8, 0x5c, 0x46, 0x98, 0x6c, 0x1b, 0xef, 0x34, + 0x90, 0xd3, 0x7b, 0x38, 0xda, 0x85, 0xd3, 0x2e, + 0x97, 0x39, 0xcb, 0x23, 0x4a, 0x2b, 0xe7, 0x40, + }, + }, +} + +func testEncrypt(t *testing.T, desc string, c *Cipher, src, expect []byte) { + dst := make([]byte, len(src)) + c.XORKeyStream(dst, src) + for i, v := range dst { + if v != expect[i] { + t.Fatalf("%s: mismatch at byte %d:\nhave %x\nwant %x", desc, i, dst, expect) + } + } +} + +func TestGolden(t *testing.T) { + for gi, g := range golden { + data := make([]byte, len(g.keystream)) + for i := range data { + data[i] = byte(i) + } + + expect := make([]byte, len(g.keystream)) + for i := range expect { + expect[i] = byte(i) ^ g.keystream[i] + } + + for size := 1; size <= len(g.keystream); size++ { + c, err := NewCipher(g.key) + if err != nil { + t.Fatalf("#%d: NewCipher: %v", gi, err) + } + + off := 0 + for off < len(g.keystream) { + n := len(g.keystream) - off + if n > size { + n = size + } + desc := fmt.Sprintf("#%d@[%d:%d]", gi, off, off+n) + testEncrypt(t, desc, c, data[off:off+n], expect[off:off+n]) + off += n + } + } + } +} + +func TestBlock(t *testing.T) { + c1a, _ := NewCipher(golden[0].key) + c1b, _ := NewCipher(golden[1].key) + data1 := make([]byte, 1<<20) + for i := range data1 { + c1a.XORKeyStream(data1[i:i+1], data1[i:i+1]) + c1b.XORKeyStream(data1[i:i+1], data1[i:i+1]) + } + + c2a, _ := NewCipher(golden[0].key) + c2b, _ := NewCipher(golden[1].key) + data2 := make([]byte, 1<<20) + c2a.XORKeyStream(data2, data2) + c2b.XORKeyStream(data2, data2) + + if !bytes.Equal(data1, data2) { + t.Fatalf("bad block") + } +} + +func benchmark(b *testing.B, size int64) { + buf := make([]byte, size) + c, err := NewCipher(golden[0].key) + if err != nil { + panic(err) + } + b.SetBytes(size) + + for i := 0; i < b.N; i++ { + c.XORKeyStream(buf, buf) + } +} + +func BenchmarkRC4_128(b *testing.B) { + benchmark(b, 128) +} + +func BenchmarkRC4_1K(b *testing.B) { + benchmark(b, 1024) +} + +func BenchmarkRC4_8K(b *testing.B) { + benchmark(b, 8096) +} diff --git a/src/crypto/rsa/equal_test.go b/src/crypto/rsa/equal_test.go new file mode 100644 index 0000000..90f4bf9 --- /dev/null +++ b/src/crypto/rsa/equal_test.go @@ -0,0 +1,51 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa_test + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "testing" +) + +func TestEqual(t *testing.T) { + private, _ := rsa.GenerateKey(rand.Reader, 512) + public := &private.PublicKey + + if !public.Equal(public) { + t.Errorf("public key is not equal to itself: %v", public) + } + if !public.Equal(crypto.Signer(private).Public().(*rsa.PublicKey)) { + t.Errorf("private.Public() is not Equal to public: %q", public) + } + if !private.Equal(private) { + t.Errorf("private key is not equal to itself: %v", private) + } + + enc, err := x509.MarshalPKCS8PrivateKey(private) + if err != nil { + t.Fatal(err) + } + decoded, err := x509.ParsePKCS8PrivateKey(enc) + if err != nil { + t.Fatal(err) + } + if !public.Equal(decoded.(crypto.Signer).Public()) { + t.Errorf("public key is not equal to itself after decoding: %v", public) + } + if !private.Equal(decoded) { + t.Errorf("private key is not equal to itself after decoding: %v", private) + } + + other, _ := rsa.GenerateKey(rand.Reader, 512) + if public.Equal(other.Public()) { + t.Errorf("different public keys are Equal") + } + if private.Equal(other) { + t.Errorf("different private keys are Equal") + } +} diff --git a/src/crypto/rsa/example_test.go b/src/crypto/rsa/example_test.go new file mode 100644 index 0000000..ce5c2d9 --- /dev/null +++ b/src/crypto/rsa/example_test.go @@ -0,0 +1,169 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "os" +) + +// RSA is able to encrypt only a very limited amount of data. In order +// to encrypt reasonable amounts of data a hybrid scheme is commonly +// used: RSA is used to encrypt a key for a symmetric primitive like +// AES-GCM. +// +// Before encrypting, data is “padded” by embedding it in a known +// structure. This is done for a number of reasons, but the most +// obvious is to ensure that the value is large enough that the +// exponentiation is larger than the modulus. (Otherwise it could be +// decrypted with a square-root.) +// +// In these designs, when using PKCS #1 v1.5, it's vitally important to +// avoid disclosing whether the received RSA message was well-formed +// (that is, whether the result of decrypting is a correctly padded +// message) because this leaks secret information. +// DecryptPKCS1v15SessionKey is designed for this situation and copies +// the decrypted, symmetric key (if well-formed) in constant-time over +// a buffer that contains a random key. Thus, if the RSA result isn't +// well-formed, the implementation uses a random key in constant time. +func ExampleDecryptPKCS1v15SessionKey() { + // crypto/rand.Reader is a good source of entropy for blinding the RSA + // operation. + rng := rand.Reader + + // The hybrid scheme should use at least a 16-byte symmetric key. Here + // we read the random key that will be used if the RSA decryption isn't + // well-formed. + key := make([]byte, 32) + if _, err := io.ReadFull(rng, key); err != nil { + panic("RNG failure") + } + + rsaCiphertext, _ := hex.DecodeString("aabbccddeeff") + + if err := DecryptPKCS1v15SessionKey(rng, rsaPrivateKey, rsaCiphertext, key); err != nil { + // Any errors that result will be “public” – meaning that they + // can be determined without any secret information. (For + // instance, if the length of key is impossible given the RSA + // public key.) + fmt.Fprintf(os.Stderr, "Error from RSA decryption: %s\n", err) + return + } + + // Given the resulting key, a symmetric scheme can be used to decrypt a + // larger ciphertext. + block, err := aes.NewCipher(key) + if err != nil { + panic("aes.NewCipher failed: " + err.Error()) + } + + // Since the key is random, using a fixed nonce is acceptable as the + // (key, nonce) pair will still be unique, as required. + var zeroNonce [12]byte + aead, err := cipher.NewGCM(block) + if err != nil { + panic("cipher.NewGCM failed: " + err.Error()) + } + ciphertext, _ := hex.DecodeString("00112233445566") + plaintext, err := aead.Open(nil, zeroNonce[:], ciphertext, nil) + if err != nil { + // The RSA ciphertext was badly formed; the decryption will + // fail here because the AES-GCM key will be incorrect. + fmt.Fprintf(os.Stderr, "Error decrypting: %s\n", err) + return + } + + fmt.Printf("Plaintext: %s\n", string(plaintext)) +} + +func ExampleSignPKCS1v15() { + // crypto/rand.Reader is a good source of entropy for blinding the RSA + // operation. + rng := rand.Reader + + message := []byte("message to be signed") + + // Only small messages can be signed directly; thus the hash of a + // message, rather than the message itself, is signed. This requires + // that the hash function be collision resistant. SHA-256 is the + // least-strong hash function that should be used for this at the time + // of writing (2016). + hashed := sha256.Sum256(message) + + signature, err := SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:]) + if err != nil { + fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err) + return + } + + fmt.Printf("Signature: %x\n", signature) +} + +func ExampleVerifyPKCS1v15() { + message := []byte("message to be signed") + signature, _ := hex.DecodeString("ad2766728615cc7a746cc553916380ca7bfa4f8983b990913bc69eb0556539a350ff0f8fe65ddfd3ebe91fe1c299c2fac135bc8c61e26be44ee259f2f80c1530") + + // Only small messages can be signed directly; thus the hash of a + // message, rather than the message itself, is signed. This requires + // that the hash function be collision resistant. SHA-256 is the + // least-strong hash function that should be used for this at the time + // of writing (2016). + hashed := sha256.Sum256(message) + + err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA256, hashed[:], signature) + if err != nil { + fmt.Fprintf(os.Stderr, "Error from verification: %s\n", err) + return + } + + // signature is a valid signature of message from the public key. +} + +func ExampleEncryptOAEP() { + secretMessage := []byte("send reinforcements, we're going to advance") + label := []byte("orders") + + // crypto/rand.Reader is a good source of entropy for randomizing the + // encryption function. + rng := rand.Reader + + ciphertext, err := EncryptOAEP(sha256.New(), rng, &test2048Key.PublicKey, secretMessage, label) + if err != nil { + fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err) + return + } + + // Since encryption is a randomized function, ciphertext will be + // different each time. + fmt.Printf("Ciphertext: %x\n", ciphertext) +} + +func ExampleDecryptOAEP() { + ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460") + label := []byte("orders") + + // crypto/rand.Reader is a good source of entropy for blinding the RSA + // operation. + rng := rand.Reader + + plaintext, err := DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label) + if err != nil { + fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err) + return + } + + fmt.Printf("Plaintext: %s\n", string(plaintext)) + + // Remember that encryption only provides confidentiality. The + // ciphertext should be signed before authenticity is assumed and, even + // then, consider that messages might be reordered. +} diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go new file mode 100644 index 0000000..0cbd6d0 --- /dev/null +++ b/src/crypto/rsa/pkcs1v15.go @@ -0,0 +1,323 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "crypto" + "crypto/subtle" + "errors" + "io" + "math/big" + + "crypto/internal/randutil" +) + +// This file implements encryption and decryption using PKCS #1 v1.5 padding. + +// PKCS1v15DecrypterOpts is for passing options to PKCS #1 v1.5 decryption using +// the crypto.Decrypter interface. +type PKCS1v15DecryptOptions struct { + // SessionKeyLen is the length of the session key that is being + // decrypted. If not zero, then a padding error during decryption will + // cause a random plaintext of this length to be returned rather than + // an error. These alternatives happen in constant time. + SessionKeyLen int +} + +// EncryptPKCS1v15 encrypts the given message with RSA and the padding +// scheme from PKCS #1 v1.5. The message must be no longer than the +// length of the public modulus minus 11 bytes. +// +// The rand parameter is used as a source of entropy to ensure that +// encrypting the same message twice doesn't result in the same +// ciphertext. +// +// WARNING: use of this function to encrypt plaintexts other than +// session keys is dangerous. Use RSA OAEP in new protocols. +func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) { + randutil.MaybeReadByte(rand) + + if err := checkPub(pub); err != nil { + return nil, err + } + k := pub.Size() + if len(msg) > k-11 { + return nil, ErrMessageTooLong + } + + // EM = 0x00 || 0x02 || PS || 0x00 || M + em := make([]byte, k) + em[1] = 2 + ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):] + err := nonZeroRandomBytes(ps, rand) + if err != nil { + return nil, err + } + em[len(em)-len(msg)-1] = 0 + copy(mm, msg) + + m := new(big.Int).SetBytes(em) + c := encrypt(new(big.Int), pub, m) + + return c.FillBytes(em), nil +} + +// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS #1 v1.5. +// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks. +// +// Note that whether this function returns an error or not discloses secret +// information. If an attacker can cause this function to run repeatedly and +// learn whether each instance returned an error then they can decrypt and +// forge signatures as if they had the private key. See +// DecryptPKCS1v15SessionKey for a way of solving this problem. +func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error) { + if err := checkPub(&priv.PublicKey); err != nil { + return nil, err + } + valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext) + if err != nil { + return nil, err + } + if valid == 0 { + return nil, ErrDecryption + } + return out[index:], nil +} + +// DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS #1 v1.5. +// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks. +// It returns an error if the ciphertext is the wrong length or if the +// ciphertext is greater than the public modulus. Otherwise, no error is +// returned. If the padding is valid, the resulting plaintext message is copied +// into key. Otherwise, key is unchanged. These alternatives occur in constant +// time. It is intended that the user of this function generate a random +// session key beforehand and continue the protocol with the resulting value. +// This will remove any possibility that an attacker can learn any information +// about the plaintext. +// See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA +// Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology +// (Crypto '98). +// +// Note that if the session key is too small then it may be possible for an +// attacker to brute-force it. If they can do that then they can learn whether +// a random value was used (because it'll be different for the same ciphertext) +// and thus whether the padding was correct. This defeats the point of this +// function. Using at least a 16-byte key will protect against this attack. +func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error { + if err := checkPub(&priv.PublicKey); err != nil { + return err + } + k := priv.Size() + if k-(len(key)+3+8) < 0 { + return ErrDecryption + } + + valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext) + if err != nil { + return err + } + + if len(em) != k { + // This should be impossible because decryptPKCS1v15 always + // returns the full slice. + return ErrDecryption + } + + valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key))) + subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):]) + return nil +} + +// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if +// rand is not nil. It returns one or zero in valid that indicates whether the +// plaintext was correctly structured. In either case, the plaintext is +// returned in em so that it may be read independently of whether it was valid +// in order to maintain constant memory access patterns. If the plaintext was +// valid then index contains the index of the original message in em. +func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { + k := priv.Size() + if k < 11 { + err = ErrDecryption + return + } + + c := new(big.Int).SetBytes(ciphertext) + m, err := decrypt(rand, priv, c) + if err != nil { + return + } + + em = m.FillBytes(make([]byte, k)) + firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) + secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2) + + // The remainder of the plaintext must be a string of non-zero random + // octets, followed by a 0, followed by the message. + // lookingForIndex: 1 iff we are still looking for the zero. + // index: the offset of the first zero byte. + lookingForIndex := 1 + + for i := 2; i < len(em); i++ { + equals0 := subtle.ConstantTimeByteEq(em[i], 0) + index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) + lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) + } + + // The PS padding must be at least 8 bytes long, and it starts two + // bytes into em. + validPS := subtle.ConstantTimeLessOrEq(2+8, index) + + valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS + index = subtle.ConstantTimeSelect(valid, index+1, 0) + return valid, em, index, nil +} + +// nonZeroRandomBytes fills the given slice with non-zero random octets. +func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { + _, err = io.ReadFull(rand, s) + if err != nil { + return + } + + for i := 0; i < len(s); i++ { + for s[i] == 0 { + _, err = io.ReadFull(rand, s[i:i+1]) + if err != nil { + return + } + // In tests, the PRNG may return all zeros so we do + // this to break the loop. + s[i] ^= 0x42 + } + } + + return +} + +// These are ASN1 DER structures: +// DigestInfo ::= SEQUENCE { +// digestAlgorithm AlgorithmIdentifier, +// digest OCTET STRING +// } +// For performance, we don't use the generic ASN1 encoder. Rather, we +// precompute a prefix of the digest value that makes a valid ASN1 DER string +// with the correct contents. +var hashPrefixes = map[crypto.Hash][]byte{ + crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}, + crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}, + crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}, + crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, + crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, + crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, + crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix. + crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14}, +} + +// SignPKCS1v15 calculates the signature of hashed using +// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must +// be the result of hashing the input message using the given hash +// function. If hash is zero, hashed is signed directly. This isn't +// advisable except for interoperability. +// +// If rand is not nil then RSA blinding will be used to avoid timing +// side-channel attacks. +// +// This function is deterministic. Thus, if the set of possible +// messages is small, an attacker may be able to build a map from +// messages to signatures and identify the signed messages. As ever, +// signatures provide authenticity, not confidentiality. +func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) { + hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) + if err != nil { + return nil, err + } + + tLen := len(prefix) + hashLen + k := priv.Size() + if k < tLen+11 { + return nil, ErrMessageTooLong + } + + // EM = 0x00 || 0x01 || PS || 0x00 || T + em := make([]byte, k) + em[1] = 1 + for i := 2; i < k-tLen-1; i++ { + em[i] = 0xff + } + copy(em[k-tLen:k-hashLen], prefix) + copy(em[k-hashLen:k], hashed) + + m := new(big.Int).SetBytes(em) + c, err := decryptAndCheck(rand, priv, m) + if err != nil { + return nil, err + } + + return c.FillBytes(em), nil +} + +// VerifyPKCS1v15 verifies an RSA PKCS #1 v1.5 signature. +// hashed is the result of hashing the input message using the given hash +// function and sig is the signature. A valid signature is indicated by +// returning a nil error. If hash is zero then hashed is used directly. This +// isn't advisable except for interoperability. +func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error { + hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) + if err != nil { + return err + } + + tLen := len(prefix) + hashLen + k := pub.Size() + if k < tLen+11 { + return ErrVerification + } + + // RFC 8017 Section 8.2.2: If the length of the signature S is not k + // octets (where k is the length in octets of the RSA modulus n), output + // "invalid signature" and stop. + if k != len(sig) { + return ErrVerification + } + + c := new(big.Int).SetBytes(sig) + m := encrypt(new(big.Int), pub, c) + em := m.FillBytes(make([]byte, k)) + // EM = 0x00 || 0x01 || PS || 0x00 || T + + ok := subtle.ConstantTimeByteEq(em[0], 0) + ok &= subtle.ConstantTimeByteEq(em[1], 1) + ok &= subtle.ConstantTimeCompare(em[k-hashLen:k], hashed) + ok &= subtle.ConstantTimeCompare(em[k-tLen:k-hashLen], prefix) + ok &= subtle.ConstantTimeByteEq(em[k-tLen-1], 0) + + for i := 2; i < k-tLen-1; i++ { + ok &= subtle.ConstantTimeByteEq(em[i], 0xff) + } + + if ok != 1 { + return ErrVerification + } + + return nil +} + +func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) { + // Special case: crypto.Hash(0) is used to indicate that the data is + // signed directly. + if hash == 0 { + return inLen, nil, nil + } + + hashLen = hash.Size() + if inLen != hashLen { + return 0, nil, errors.New("crypto/rsa: input must be hashed message") + } + prefix, ok := hashPrefixes[hash] + if !ok { + return 0, nil, errors.New("crypto/rsa: unsupported hash function") + } + return +} diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go new file mode 100644 index 0000000..26b8c5f --- /dev/null +++ b/src/crypto/rsa/pkcs1v15_test.go @@ -0,0 +1,316 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "bytes" + "crypto" + "crypto/rand" + "crypto/sha1" + "crypto/sha256" + "encoding/base64" + "encoding/hex" + "io" + "math/big" + "testing" + "testing/quick" +) + +func decodeBase64(in string) []byte { + out := make([]byte, base64.StdEncoding.DecodedLen(len(in))) + n, err := base64.StdEncoding.Decode(out, []byte(in)) + if err != nil { + return nil + } + return out[0:n] +} + +type DecryptPKCS1v15Test struct { + in, out string +} + +// These test vectors were generated with `openssl rsautl -pkcs -encrypt` +var decryptPKCS1v15Tests = []DecryptPKCS1v15Test{ + { + "gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==", + "x", + }, + { + "Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==", + "testing.", + }, + { + "arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==", + "testing.\n", + }, + { + "WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==", + "01234567890123456789012345678901234567890123456789012", + }, +} + +func TestDecryptPKCS1v15(t *testing.T) { + decryptionFuncs := []func([]byte) ([]byte, error){ + func(ciphertext []byte) (plaintext []byte, err error) { + return DecryptPKCS1v15(nil, rsaPrivateKey, ciphertext) + }, + func(ciphertext []byte) (plaintext []byte, err error) { + return rsaPrivateKey.Decrypt(nil, ciphertext, nil) + }, + } + + for _, decryptFunc := range decryptionFuncs { + for i, test := range decryptPKCS1v15Tests { + out, err := decryptFunc(decodeBase64(test.in)) + if err != nil { + t.Errorf("#%d error decrypting", i) + } + want := []byte(test.out) + if !bytes.Equal(out, want) { + t.Errorf("#%d got:%#v want:%#v", i, out, want) + } + } + } +} + +func TestEncryptPKCS1v15(t *testing.T) { + random := rand.Reader + k := (rsaPrivateKey.N.BitLen() + 7) / 8 + + tryEncryptDecrypt := func(in []byte, blind bool) bool { + if len(in) > k-11 { + in = in[0 : k-11] + } + + ciphertext, err := EncryptPKCS1v15(random, &rsaPrivateKey.PublicKey, in) + if err != nil { + t.Errorf("error encrypting: %s", err) + return false + } + + var rand io.Reader + if !blind { + rand = nil + } else { + rand = random + } + plaintext, err := DecryptPKCS1v15(rand, rsaPrivateKey, ciphertext) + if err != nil { + t.Errorf("error decrypting: %s", err) + return false + } + + if !bytes.Equal(plaintext, in) { + t.Errorf("output mismatch: %#v %#v", plaintext, in) + return false + } + return true + } + + config := new(quick.Config) + if testing.Short() { + config.MaxCount = 10 + } + quick.Check(tryEncryptDecrypt, config) +} + +// These test vectors were generated with `openssl rsautl -pkcs -encrypt` +var decryptPKCS1v15SessionKeyTests = []DecryptPKCS1v15Test{ + { + "e6ukkae6Gykq0fKzYwULpZehX+UPXYzMoB5mHQUDEiclRbOTqas4Y0E6nwns1BBpdvEJcilhl5zsox/6DtGsYg==", + "1234", + }, + { + "Dtis4uk/q/LQGGqGk97P59K03hkCIVFMEFZRgVWOAAhxgYpCRG0MX2adptt92l67IqMki6iVQyyt0TtX3IdtEw==", + "FAIL", + }, + { + "LIyFyCYCptPxrvTxpol8F3M7ZivlMsf53zs0vHRAv+rDIh2YsHS69ePMoPMe3TkOMZ3NupiL3takPxIs1sK+dw==", + "abcd", + }, + { + "bafnobel46bKy76JzqU/RIVOH0uAYvzUtauKmIidKgM0sMlvobYVAVQPeUQ/oTGjbIZ1v/6Gyi5AO4DtHruGdw==", + "FAIL", + }, +} + +func TestEncryptPKCS1v15SessionKey(t *testing.T) { + for i, test := range decryptPKCS1v15SessionKeyTests { + key := []byte("FAIL") + err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, decodeBase64(test.in), key) + if err != nil { + t.Errorf("#%d error decrypting", i) + } + want := []byte(test.out) + if !bytes.Equal(key, want) { + t.Errorf("#%d got:%#v want:%#v", i, key, want) + } + } +} + +func TestEncryptPKCS1v15DecrypterSessionKey(t *testing.T) { + for i, test := range decryptPKCS1v15SessionKeyTests { + plaintext, err := rsaPrivateKey.Decrypt(rand.Reader, decodeBase64(test.in), &PKCS1v15DecryptOptions{SessionKeyLen: 4}) + if err != nil { + t.Fatalf("#%d: error decrypting: %s", i, err) + } + if len(plaintext) != 4 { + t.Fatalf("#%d: incorrect length plaintext: got %d, want 4", i, len(plaintext)) + } + + if test.out != "FAIL" && !bytes.Equal(plaintext, []byte(test.out)) { + t.Errorf("#%d: incorrect plaintext: got %x, want %x", i, plaintext, test.out) + } + } +} + +func TestNonZeroRandomBytes(t *testing.T) { + random := rand.Reader + + b := make([]byte, 512) + err := nonZeroRandomBytes(b, random) + if err != nil { + t.Errorf("returned error: %s", err) + } + for _, b := range b { + if b == 0 { + t.Errorf("Zero octet found") + return + } + } +} + +type signPKCS1v15Test struct { + in, out string +} + +// These vectors have been tested with +// `openssl rsautl -verify -inkey pk -in signature | hexdump -C` +var signPKCS1v15Tests = []signPKCS1v15Test{ + {"Test.\n", "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e336ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"}, +} + +func TestSignPKCS1v15(t *testing.T) { + for i, test := range signPKCS1v15Tests { + h := sha1.New() + h.Write([]byte(test.in)) + digest := h.Sum(nil) + + s, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA1, digest) + if err != nil { + t.Errorf("#%d %s", i, err) + } + + expected, _ := hex.DecodeString(test.out) + if !bytes.Equal(s, expected) { + t.Errorf("#%d got: %x want: %x", i, s, expected) + } + } +} + +func TestVerifyPKCS1v15(t *testing.T) { + for i, test := range signPKCS1v15Tests { + h := sha1.New() + h.Write([]byte(test.in)) + digest := h.Sum(nil) + + sig, _ := hex.DecodeString(test.out) + + err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA1, digest, sig) + if err != nil { + t.Errorf("#%d %s", i, err) + } + } +} + +func TestOverlongMessagePKCS1v15(t *testing.T) { + ciphertext := decodeBase64("fjOVdirUzFoLlukv80dBllMLjXythIf22feqPrNo0YoIjzyzyoMFiLjAc/Y4krkeZ11XFThIrEvw\nkRiZcCq5ng==") + _, err := DecryptPKCS1v15(nil, rsaPrivateKey, ciphertext) + if err == nil { + t.Error("RSA decrypted a message that was too long.") + } +} + +func TestUnpaddedSignature(t *testing.T) { + msg := []byte("Thu Dec 19 18:06:16 EST 2013\n") + // This base64 value was generated with: + // % echo Thu Dec 19 18:06:16 EST 2013 > /tmp/msg + // % openssl rsautl -sign -inkey key -out /tmp/sig -in /tmp/msg + // + // Where "key" contains the RSA private key given at the bottom of this + // file. + expectedSig := decodeBase64("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==") + + sig, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.Hash(0), msg) + if err != nil { + t.Fatalf("SignPKCS1v15 failed: %s", err) + } + if !bytes.Equal(sig, expectedSig) { + t.Fatalf("signature is not expected value: got %x, want %x", sig, expectedSig) + } + if err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.Hash(0), msg, sig); err != nil { + t.Fatalf("signature failed to verify: %s", err) + } +} + +func TestShortSessionKey(t *testing.T) { + // This tests that attempting to decrypt a session key where the + // ciphertext is too small doesn't run outside the array bounds. + ciphertext, err := EncryptPKCS1v15(rand.Reader, &rsaPrivateKey.PublicKey, []byte{1}) + if err != nil { + t.Fatalf("Failed to encrypt short message: %s", err) + } + + var key [32]byte + if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, ciphertext, key[:]); err != nil { + t.Fatalf("Failed to decrypt short message: %s", err) + } + + for _, v := range key { + if v != 0 { + t.Fatal("key was modified when ciphertext was invalid") + } + } +} + +// In order to generate new test vectors you'll need the PEM form of this key (and s/TESTING/PRIVATE/): +// -----BEGIN RSA TESTING KEY----- +// MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 +// fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu +// /ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu +// RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ +// EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A +// IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS +// tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V +// -----END RSA TESTING KEY----- + +var rsaPrivateKey = &PrivateKey{ + PublicKey: PublicKey{ + N: fromBase10("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"), + E: 65537, + }, + D: fromBase10("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"), + Primes: []*big.Int{ + fromBase10("98920366548084643601728869055592650835572950932266967461790948584315647051443"), + fromBase10("94560208308847015747498523884063394671606671904944666360068158221458669711639"), + }, +} + +func TestShortPKCS1v15Signature(t *testing.T) { + pub := &PublicKey{ + E: 65537, + N: fromBase10("8272693557323587081220342447407965471608219912416565371060697606400726784709760494166080686904546560026343451112103559482851304715739629410219358933351333"), + } + sig, err := hex.DecodeString("193a310d0dcf64094c6e3a00c8219b80ded70535473acff72c08e1222974bb24a93a535b1dc4c59fc0e65775df7ba2007dd20e9193f4c4025a18a7070aee93") + if err != nil { + t.Fatalf("failed to decode signature: %s", err) + } + + h := sha256.Sum256([]byte("hello")) + err = VerifyPKCS1v15(pub, crypto.SHA256, h[:], sig) + if err == nil { + t.Fatal("VerifyPKCS1v15 accepted a truncated signature") + } +} diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go new file mode 100644 index 0000000..814522d --- /dev/null +++ b/src/crypto/rsa/pss.go @@ -0,0 +1,303 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +// This file implements the RSASSA-PSS signature scheme according to RFC 8017. + +import ( + "bytes" + "crypto" + "errors" + "hash" + "io" + "math/big" +) + +// Per RFC 8017, Section 9.1 +// +// EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc +// +// where +// +// DB = PS || 0x01 || salt +// +// and PS can be empty so +// +// emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2 +// + +func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) { + // See RFC 8017, Section 9.1.1. + + hLen := hash.Size() + sLen := len(salt) + emLen := (emBits + 7) / 8 + + // 1. If the length of M is greater than the input limitation for the + // hash function (2^61 - 1 octets for SHA-1), output "message too + // long" and stop. + // + // 2. Let mHash = Hash(M), an octet string of length hLen. + + if len(mHash) != hLen { + return nil, errors.New("crypto/rsa: input must be hashed with given hash") + } + + // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. + + if emLen < hLen+sLen+2 { + return nil, errors.New("crypto/rsa: key size too small for PSS signature") + } + + em := make([]byte, emLen) + psLen := emLen - sLen - hLen - 2 + db := em[:psLen+1+sLen] + h := em[psLen+1+sLen : emLen-1] + + // 4. Generate a random octet string salt of length sLen; if sLen = 0, + // then salt is the empty string. + // + // 5. Let + // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; + // + // M' is an octet string of length 8 + hLen + sLen with eight + // initial zero octets. + // + // 6. Let H = Hash(M'), an octet string of length hLen. + + var prefix [8]byte + + hash.Write(prefix[:]) + hash.Write(mHash) + hash.Write(salt) + + h = hash.Sum(h[:0]) + hash.Reset() + + // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 + // zero octets. The length of PS may be 0. + // + // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length + // emLen - hLen - 1. + + db[psLen] = 0x01 + copy(db[psLen+1:], salt) + + // 9. Let dbMask = MGF(H, emLen - hLen - 1). + // + // 10. Let maskedDB = DB \xor dbMask. + + mgf1XOR(db, hash, h) + + // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in + // maskedDB to zero. + + db[0] &= 0xff >> (8*emLen - emBits) + + // 12. Let EM = maskedDB || H || 0xbc. + em[emLen-1] = 0xbc + + // 13. Output EM. + return em, nil +} + +func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { + // See RFC 8017, Section 9.1.2. + + hLen := hash.Size() + if sLen == PSSSaltLengthEqualsHash { + sLen = hLen + } + emLen := (emBits + 7) / 8 + if emLen != len(em) { + return errors.New("rsa: internal error: inconsistent length") + } + + // 1. If the length of M is greater than the input limitation for the + // hash function (2^61 - 1 octets for SHA-1), output "inconsistent" + // and stop. + // + // 2. Let mHash = Hash(M), an octet string of length hLen. + if hLen != len(mHash) { + return ErrVerification + } + + // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. + if emLen < hLen+sLen+2 { + return ErrVerification + } + + // 4. If the rightmost octet of EM does not have hexadecimal value + // 0xbc, output "inconsistent" and stop. + if em[emLen-1] != 0xbc { + return ErrVerification + } + + // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and + // let H be the next hLen octets. + db := em[:emLen-hLen-1] + h := em[emLen-hLen-1 : emLen-1] + + // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in + // maskedDB are not all equal to zero, output "inconsistent" and + // stop. + var bitMask byte = 0xff >> (8*emLen - emBits) + if em[0] & ^bitMask != 0 { + return ErrVerification + } + + // 7. Let dbMask = MGF(H, emLen - hLen - 1). + // + // 8. Let DB = maskedDB \xor dbMask. + mgf1XOR(db, hash, h) + + // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB + // to zero. + db[0] &= bitMask + + // If we don't know the salt length, look for the 0x01 delimiter. + if sLen == PSSSaltLengthAuto { + psLen := bytes.IndexByte(db, 0x01) + if psLen < 0 { + return ErrVerification + } + sLen = len(db) - psLen - 1 + } + + // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero + // or if the octet at position emLen - hLen - sLen - 1 (the leftmost + // position is "position 1") does not have hexadecimal value 0x01, + // output "inconsistent" and stop. + psLen := emLen - hLen - sLen - 2 + for _, e := range db[:psLen] { + if e != 0x00 { + return ErrVerification + } + } + if db[psLen] != 0x01 { + return ErrVerification + } + + // 11. Let salt be the last sLen octets of DB. + salt := db[len(db)-sLen:] + + // 12. Let + // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ; + // M' is an octet string of length 8 + hLen + sLen with eight + // initial zero octets. + // + // 13. Let H' = Hash(M'), an octet string of length hLen. + var prefix [8]byte + hash.Write(prefix[:]) + hash.Write(mHash) + hash.Write(salt) + + h0 := hash.Sum(nil) + + // 14. If H = H', output "consistent." Otherwise, output "inconsistent." + if !bytes.Equal(h0, h) { // TODO: constant time? + return ErrVerification + } + return nil +} + +// signPSSWithSalt calculates the signature of hashed using PSS with specified salt. +// Note that hashed must be the result of hashing the input message using the +// given hash function. salt is a random sequence of bytes whose length will be +// later used to verify the signature. +func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) { + emBits := priv.N.BitLen() - 1 + em, err := emsaPSSEncode(hashed, emBits, salt, hash.New()) + if err != nil { + return nil, err + } + m := new(big.Int).SetBytes(em) + c, err := decryptAndCheck(rand, priv, m) + if err != nil { + return nil, err + } + s := make([]byte, priv.Size()) + return c.FillBytes(s), nil +} + +const ( + // PSSSaltLengthAuto causes the salt in a PSS signature to be as large + // as possible when signing, and to be auto-detected when verifying. + PSSSaltLengthAuto = 0 + // PSSSaltLengthEqualsHash causes the salt length to equal the length + // of the hash used in the signature. + PSSSaltLengthEqualsHash = -1 +) + +// PSSOptions contains options for creating and verifying PSS signatures. +type PSSOptions struct { + // SaltLength controls the length of the salt used in the PSS + // signature. It can either be a number of bytes, or one of the special + // PSSSaltLength constants. + SaltLength int + + // Hash is the hash function used to generate the message digest. If not + // zero, it overrides the hash function passed to SignPSS. It's required + // when using PrivateKey.Sign. + Hash crypto.Hash +} + +// HashFunc returns opts.Hash so that PSSOptions implements crypto.SignerOpts. +func (opts *PSSOptions) HashFunc() crypto.Hash { + return opts.Hash +} + +func (opts *PSSOptions) saltLength() int { + if opts == nil { + return PSSSaltLengthAuto + } + return opts.SaltLength +} + +// SignPSS calculates the signature of digest using PSS. +// +// digest must be the result of hashing the input message using the given hash +// function. The opts argument may be nil, in which case sensible defaults are +// used. If opts.Hash is set, it overrides hash. +func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) { + if opts != nil && opts.Hash != 0 { + hash = opts.Hash + } + + saltLength := opts.saltLength() + switch saltLength { + case PSSSaltLengthAuto: + saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size() + case PSSSaltLengthEqualsHash: + saltLength = hash.Size() + } + + salt := make([]byte, saltLength) + if _, err := io.ReadFull(rand, salt); err != nil { + return nil, err + } + return signPSSWithSalt(rand, priv, hash, digest, salt) +} + +// VerifyPSS verifies a PSS signature. +// +// A valid signature is indicated by returning a nil error. digest must be the +// result of hashing the input message using the given hash function. The opts +// argument may be nil, in which case sensible defaults are used. opts.Hash is +// ignored. +func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error { + if len(sig) != pub.Size() { + return ErrVerification + } + s := new(big.Int).SetBytes(sig) + m := encrypt(new(big.Int), pub, s) + emBits := pub.N.BitLen() - 1 + emLen := (emBits + 7) / 8 + if m.BitLen() > emLen*8 { + return ErrVerification + } + em := m.FillBytes(make([]byte, emLen)) + return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New()) +} diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go new file mode 100644 index 0000000..c3a6d46 --- /dev/null +++ b/src/crypto/rsa/pss_test.go @@ -0,0 +1,276 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "bufio" + "bytes" + "compress/bzip2" + "crypto" + _ "crypto/md5" + "crypto/rand" + "crypto/sha1" + "crypto/sha256" + "encoding/hex" + "math/big" + "os" + "strconv" + "strings" + "testing" +) + +func TestEMSAPSS(t *testing.T) { + // Test vector in file pss-int.txt from: ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + msg := []byte{ + 0x85, 0x9e, 0xef, 0x2f, 0xd7, 0x8a, 0xca, 0x00, 0x30, 0x8b, + 0xdc, 0x47, 0x11, 0x93, 0xbf, 0x55, 0xbf, 0x9d, 0x78, 0xdb, + 0x8f, 0x8a, 0x67, 0x2b, 0x48, 0x46, 0x34, 0xf3, 0xc9, 0xc2, + 0x6e, 0x64, 0x78, 0xae, 0x10, 0x26, 0x0f, 0xe0, 0xdd, 0x8c, + 0x08, 0x2e, 0x53, 0xa5, 0x29, 0x3a, 0xf2, 0x17, 0x3c, 0xd5, + 0x0c, 0x6d, 0x5d, 0x35, 0x4f, 0xeb, 0xf7, 0x8b, 0x26, 0x02, + 0x1c, 0x25, 0xc0, 0x27, 0x12, 0xe7, 0x8c, 0xd4, 0x69, 0x4c, + 0x9f, 0x46, 0x97, 0x77, 0xe4, 0x51, 0xe7, 0xf8, 0xe9, 0xe0, + 0x4c, 0xd3, 0x73, 0x9c, 0x6b, 0xbf, 0xed, 0xae, 0x48, 0x7f, + 0xb5, 0x56, 0x44, 0xe9, 0xca, 0x74, 0xff, 0x77, 0xa5, 0x3c, + 0xb7, 0x29, 0x80, 0x2f, 0x6e, 0xd4, 0xa5, 0xff, 0xa8, 0xba, + 0x15, 0x98, 0x90, 0xfc, + } + salt := []byte{ + 0xe3, 0xb5, 0xd5, 0xd0, 0x02, 0xc1, 0xbc, 0xe5, 0x0c, 0x2b, + 0x65, 0xef, 0x88, 0xa1, 0x88, 0xd8, 0x3b, 0xce, 0x7e, 0x61, + } + expected := []byte{ + 0x66, 0xe4, 0x67, 0x2e, 0x83, 0x6a, 0xd1, 0x21, 0xba, 0x24, + 0x4b, 0xed, 0x65, 0x76, 0xb8, 0x67, 0xd9, 0xa4, 0x47, 0xc2, + 0x8a, 0x6e, 0x66, 0xa5, 0xb8, 0x7d, 0xee, 0x7f, 0xbc, 0x7e, + 0x65, 0xaf, 0x50, 0x57, 0xf8, 0x6f, 0xae, 0x89, 0x84, 0xd9, + 0xba, 0x7f, 0x96, 0x9a, 0xd6, 0xfe, 0x02, 0xa4, 0xd7, 0x5f, + 0x74, 0x45, 0xfe, 0xfd, 0xd8, 0x5b, 0x6d, 0x3a, 0x47, 0x7c, + 0x28, 0xd2, 0x4b, 0xa1, 0xe3, 0x75, 0x6f, 0x79, 0x2d, 0xd1, + 0xdc, 0xe8, 0xca, 0x94, 0x44, 0x0e, 0xcb, 0x52, 0x79, 0xec, + 0xd3, 0x18, 0x3a, 0x31, 0x1f, 0xc8, 0x96, 0xda, 0x1c, 0xb3, + 0x93, 0x11, 0xaf, 0x37, 0xea, 0x4a, 0x75, 0xe2, 0x4b, 0xdb, + 0xfd, 0x5c, 0x1d, 0xa0, 0xde, 0x7c, 0xec, 0xdf, 0x1a, 0x89, + 0x6f, 0x9d, 0x8b, 0xc8, 0x16, 0xd9, 0x7c, 0xd7, 0xa2, 0xc4, + 0x3b, 0xad, 0x54, 0x6f, 0xbe, 0x8c, 0xfe, 0xbc, + } + + hash := sha1.New() + hash.Write(msg) + hashed := hash.Sum(nil) + + encoded, err := emsaPSSEncode(hashed, 1023, salt, sha1.New()) + if err != nil { + t.Errorf("Error from emsaPSSEncode: %s\n", err) + } + if !bytes.Equal(encoded, expected) { + t.Errorf("Bad encoding. got %x, want %x", encoded, expected) + } + + if err = emsaPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil { + t.Errorf("Bad verification: %s", err) + } +} + +// TestPSSGolden tests all the test vectors in pss-vect.txt from +// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip +func TestPSSGolden(t *testing.T) { + inFile, err := os.Open("testdata/pss-vect.txt.bz2") + if err != nil { + t.Fatalf("Failed to open input file: %s", err) + } + defer inFile.Close() + + // The pss-vect.txt file contains RSA keys and then a series of + // signatures. A goroutine is used to preprocess the input by merging + // lines, removing spaces in hex values and identifying the start of + // new keys and signature blocks. + const newKeyMarker = "START NEW KEY" + const newSignatureMarker = "START NEW SIGNATURE" + + values := make(chan string) + + go func() { + defer close(values) + scanner := bufio.NewScanner(bzip2.NewReader(inFile)) + var partialValue string + lastWasValue := true + + for scanner.Scan() { + line := scanner.Text() + switch { + case len(line) == 0: + if len(partialValue) > 0 { + values <- strings.ReplaceAll(partialValue, " ", "") + partialValue = "" + lastWasValue = true + } + continue + case strings.HasPrefix(line, "# ======") && lastWasValue: + values <- newKeyMarker + lastWasValue = false + case strings.HasPrefix(line, "# ------") && lastWasValue: + values <- newSignatureMarker + lastWasValue = false + case strings.HasPrefix(line, "#"): + continue + default: + partialValue += line + } + } + if err := scanner.Err(); err != nil { + panic(err) + } + }() + + var key *PublicKey + var hashed []byte + hash := crypto.SHA1 + h := hash.New() + opts := &PSSOptions{ + SaltLength: PSSSaltLengthEqualsHash, + } + + for marker := range values { + switch marker { + case newKeyMarker: + key = new(PublicKey) + nHex, ok := <-values + if !ok { + continue + } + key.N = bigFromHex(nHex) + key.E = intFromHex(<-values) + // We don't care for d, p, q, dP, dQ or qInv. + for i := 0; i < 6; i++ { + <-values + } + case newSignatureMarker: + msg := fromHex(<-values) + <-values // skip salt + sig := fromHex(<-values) + + h.Reset() + h.Write(msg) + hashed = h.Sum(hashed[:0]) + + if err := VerifyPSS(key, hash, hashed, sig, opts); err != nil { + t.Error(err) + } + default: + t.Fatalf("unknown marker: " + marker) + } + } +} + +// TestPSSOpenSSL ensures that we can verify a PSS signature from OpenSSL with +// the default options. OpenSSL sets the salt length to be maximal. +func TestPSSOpenSSL(t *testing.T) { + hash := crypto.SHA256 + h := hash.New() + h.Write([]byte("testing")) + hashed := h.Sum(nil) + + // Generated with `echo -n testing | openssl dgst -sign key.pem -sigopt rsa_padding_mode:pss -sha256 > sig` + sig := []byte{ + 0x95, 0x59, 0x6f, 0xd3, 0x10, 0xa2, 0xe7, 0xa2, 0x92, 0x9d, + 0x4a, 0x07, 0x2e, 0x2b, 0x27, 0xcc, 0x06, 0xc2, 0x87, 0x2c, + 0x52, 0xf0, 0x4a, 0xcc, 0x05, 0x94, 0xf2, 0xc3, 0x2e, 0x20, + 0xd7, 0x3e, 0x66, 0x62, 0xb5, 0x95, 0x2b, 0xa3, 0x93, 0x9a, + 0x66, 0x64, 0x25, 0xe0, 0x74, 0x66, 0x8c, 0x3e, 0x92, 0xeb, + 0xc6, 0xe6, 0xc0, 0x44, 0xf3, 0xb4, 0xb4, 0x2e, 0x8c, 0x66, + 0x0a, 0x37, 0x9c, 0x69, + } + + if err := VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, nil); err != nil { + t.Error(err) + } +} + +func TestPSSNilOpts(t *testing.T) { + hash := crypto.SHA256 + h := hash.New() + h.Write([]byte("testing")) + hashed := h.Sum(nil) + + SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, nil) +} + +func TestPSSSigning(t *testing.T) { + var saltLengthCombinations = []struct { + signSaltLength, verifySaltLength int + good bool + }{ + {PSSSaltLengthAuto, PSSSaltLengthAuto, true}, + {PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true}, + {PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true}, + {PSSSaltLengthEqualsHash, 8, false}, + {PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false}, + {8, 8, true}, + } + + hash := crypto.MD5 + h := hash.New() + h.Write([]byte("testing")) + hashed := h.Sum(nil) + var opts PSSOptions + + for i, test := range saltLengthCombinations { + opts.SaltLength = test.signSaltLength + sig, err := SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, &opts) + if err != nil { + t.Errorf("#%d: error while signing: %s", i, err) + continue + } + + opts.SaltLength = test.verifySaltLength + err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts) + if (err == nil) != test.good { + t.Errorf("#%d: bad result, wanted: %t, got: %s", i, test.good, err) + } + } +} + +func TestSignWithPSSSaltLengthAuto(t *testing.T) { + key, err := GenerateKey(rand.Reader, 513) + if err != nil { + t.Fatal(err) + } + digest := sha256.Sum256([]byte("message")) + signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{ + SaltLength: PSSSaltLengthAuto, + Hash: crypto.SHA256, + }) + if err != nil { + t.Fatal(err) + } + if len(signature) == 0 { + t.Fatal("empty signature returned") + } +} + +func bigFromHex(hex string) *big.Int { + n, ok := new(big.Int).SetString(hex, 16) + if !ok { + panic("bad hex: " + hex) + } + return n +} + +func intFromHex(hex string) int { + i, err := strconv.ParseInt(hex, 16, 32) + if err != nil { + panic(err) + } + return int(i) +} + +func fromHex(hexStr string) []byte { + s, err := hex.DecodeString(hexStr) + if err != nil { + panic(err) + } + return s +} diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go new file mode 100644 index 0000000..6fd59b3 --- /dev/null +++ b/src/crypto/rsa/rsa.go @@ -0,0 +1,659 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package rsa implements RSA encryption as specified in PKCS #1 and RFC 8017. +// +// RSA is a single, fundamental operation that is used in this package to +// implement either public-key encryption or public-key signatures. +// +// The original specification for encryption and signatures with RSA is PKCS #1 +// and the terms "RSA encryption" and "RSA signatures" by default refer to +// PKCS #1 version 1.5. However, that specification has flaws and new designs +// should use version 2, usually called by just OAEP and PSS, where +// possible. +// +// Two sets of interfaces are included in this package. When a more abstract +// interface isn't necessary, there are functions for encrypting/decrypting +// with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract +// over the public key primitive, the PrivateKey type implements the +// Decrypter and Signer interfaces from the crypto package. +// +// The RSA operations in this package are not implemented using constant-time algorithms. +package rsa + +import ( + "crypto" + "crypto/rand" + "crypto/subtle" + "errors" + "hash" + "io" + "math" + "math/big" + + "crypto/internal/randutil" +) + +var bigZero = big.NewInt(0) +var bigOne = big.NewInt(1) + +// A PublicKey represents the public part of an RSA key. +type PublicKey struct { + N *big.Int // modulus + E int // public exponent +} + +// Any methods implemented on PublicKey might need to also be implemented on +// PrivateKey, as the latter embeds the former and will expose its methods. + +// Size returns the modulus size in bytes. Raw signatures and ciphertexts +// for or by this public key will have the same size. +func (pub *PublicKey) Size() int { + return (pub.N.BitLen() + 7) / 8 +} + +// Equal reports whether pub and x have the same value. +func (pub *PublicKey) Equal(x crypto.PublicKey) bool { + xx, ok := x.(*PublicKey) + if !ok { + return false + } + return pub.N.Cmp(xx.N) == 0 && pub.E == xx.E +} + +// OAEPOptions is an interface for passing options to OAEP decryption using the +// crypto.Decrypter interface. +type OAEPOptions struct { + // Hash is the hash function that will be used when generating the mask. + Hash crypto.Hash + // Label is an arbitrary byte string that must be equal to the value + // used when encrypting. + Label []byte +} + +var ( + errPublicModulus = errors.New("crypto/rsa: missing public modulus") + errPublicExponentSmall = errors.New("crypto/rsa: public exponent too small") + errPublicExponentLarge = errors.New("crypto/rsa: public exponent too large") +) + +// checkPub sanity checks the public key before we use it. +// We require pub.E to fit into a 32-bit integer so that we +// do not have different behavior depending on whether +// int is 32 or 64 bits. See also +// https://www.imperialviolet.org/2012/03/16/rsae.html. +func checkPub(pub *PublicKey) error { + if pub.N == nil { + return errPublicModulus + } + if pub.E < 2 { + return errPublicExponentSmall + } + if pub.E > 1<<31-1 { + return errPublicExponentLarge + } + return nil +} + +// A PrivateKey represents an RSA key +type PrivateKey struct { + PublicKey // public part. + D *big.Int // private exponent + Primes []*big.Int // prime factors of N, has >= 2 elements. + + // Precomputed contains precomputed values that speed up private + // operations, if available. + Precomputed PrecomputedValues +} + +// Public returns the public key corresponding to priv. +func (priv *PrivateKey) Public() crypto.PublicKey { + return &priv.PublicKey +} + +// Equal reports whether priv and x have equivalent values. It ignores +// Precomputed values. +func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool { + xx, ok := x.(*PrivateKey) + if !ok { + return false + } + if !priv.PublicKey.Equal(&xx.PublicKey) || priv.D.Cmp(xx.D) != 0 { + return false + } + if len(priv.Primes) != len(xx.Primes) { + return false + } + for i := range priv.Primes { + if priv.Primes[i].Cmp(xx.Primes[i]) != 0 { + return false + } + } + return true +} + +// Sign signs digest with priv, reading randomness from rand. If opts is a +// *PSSOptions then the PSS algorithm will be used, otherwise PKCS #1 v1.5 will +// be used. digest must be the result of hashing the input message using +// opts.HashFunc(). +// +// This method implements crypto.Signer, which is an interface to support keys +// where the private part is kept in, for example, a hardware module. Common +// uses should use the Sign* functions in this package directly. +func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { + if pssOpts, ok := opts.(*PSSOptions); ok { + return SignPSS(rand, priv, pssOpts.Hash, digest, pssOpts) + } + + return SignPKCS1v15(rand, priv, opts.HashFunc(), digest) +} + +// Decrypt decrypts ciphertext with priv. If opts is nil or of type +// *PKCS1v15DecryptOptions then PKCS #1 v1.5 decryption is performed. Otherwise +// opts must have type *OAEPOptions and OAEP decryption is done. +func (priv *PrivateKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) { + if opts == nil { + return DecryptPKCS1v15(rand, priv, ciphertext) + } + + switch opts := opts.(type) { + case *OAEPOptions: + return DecryptOAEP(opts.Hash.New(), rand, priv, ciphertext, opts.Label) + + case *PKCS1v15DecryptOptions: + if l := opts.SessionKeyLen; l > 0 { + plaintext = make([]byte, l) + if _, err := io.ReadFull(rand, plaintext); err != nil { + return nil, err + } + if err := DecryptPKCS1v15SessionKey(rand, priv, ciphertext, plaintext); err != nil { + return nil, err + } + return plaintext, nil + } else { + return DecryptPKCS1v15(rand, priv, ciphertext) + } + + default: + return nil, errors.New("crypto/rsa: invalid options for Decrypt") + } +} + +type PrecomputedValues struct { + Dp, Dq *big.Int // D mod (P-1) (or mod Q-1) + Qinv *big.Int // Q^-1 mod P + + // CRTValues is used for the 3rd and subsequent primes. Due to a + // historical accident, the CRT for the first two primes is handled + // differently in PKCS #1 and interoperability is sufficiently + // important that we mirror this. + CRTValues []CRTValue +} + +// CRTValue contains the precomputed Chinese remainder theorem values. +type CRTValue struct { + Exp *big.Int // D mod (prime-1). + Coeff *big.Int // R·Coeff ≡ 1 mod Prime. + R *big.Int // product of primes prior to this (inc p and q). +} + +// Validate performs basic sanity checks on the key. +// It returns nil if the key is valid, or else an error describing a problem. +func (priv *PrivateKey) Validate() error { + if err := checkPub(&priv.PublicKey); err != nil { + return err + } + + // Check that Πprimes == n. + modulus := new(big.Int).Set(bigOne) + for _, prime := range priv.Primes { + // Any primes ≤ 1 will cause divide-by-zero panics later. + if prime.Cmp(bigOne) <= 0 { + return errors.New("crypto/rsa: invalid prime value") + } + modulus.Mul(modulus, prime) + } + if modulus.Cmp(priv.N) != 0 { + return errors.New("crypto/rsa: invalid modulus") + } + + // Check that de ≡ 1 mod p-1, for each prime. + // This implies that e is coprime to each p-1 as e has a multiplicative + // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) = + // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 + // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required. + congruence := new(big.Int) + de := new(big.Int).SetInt64(int64(priv.E)) + de.Mul(de, priv.D) + for _, prime := range priv.Primes { + pminus1 := new(big.Int).Sub(prime, bigOne) + congruence.Mod(de, pminus1) + if congruence.Cmp(bigOne) != 0 { + return errors.New("crypto/rsa: invalid exponents") + } + } + return nil +} + +// GenerateKey generates an RSA keypair of the given bit size using the +// random source random (for example, crypto/rand.Reader). +func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) { + return GenerateMultiPrimeKey(random, 2, bits) +} + +// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit +// size and the given random source, as suggested in [1]. Although the public +// keys are compatible (actually, indistinguishable) from the 2-prime case, +// the private keys are not. Thus it may not be possible to export multi-prime +// private keys in certain formats or to subsequently import them into other +// code. +// +// Table 1 in [2] suggests maximum numbers of primes for a given size. +// +// [1] US patent 4405829 (1972, expired) +// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf +func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) { + randutil.MaybeReadByte(random) + + priv := new(PrivateKey) + priv.E = 65537 + + if nprimes < 2 { + return nil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2") + } + + if bits < 64 { + primeLimit := float64(uint64(1) << uint(bits/nprimes)) + // pi approximates the number of primes less than primeLimit + pi := primeLimit / (math.Log(primeLimit) - 1) + // Generated primes start with 11 (in binary) so we can only + // use a quarter of them. + pi /= 4 + // Use a factor of two to ensure that key generation terminates + // in a reasonable amount of time. + pi /= 2 + if pi <= float64(nprimes) { + return nil, errors.New("crypto/rsa: too few primes of given length to generate an RSA key") + } + } + + primes := make([]*big.Int, nprimes) + +NextSetOfPrimes: + for { + todo := bits + // crypto/rand should set the top two bits in each prime. + // Thus each prime has the form + // p_i = 2^bitlen(p_i) × 0.11... (in base 2). + // And the product is: + // P = 2^todo × α + // where α is the product of nprimes numbers of the form 0.11... + // + // If α < 1/2 (which can happen for nprimes > 2), we need to + // shift todo to compensate for lost bits: the mean value of 0.11... + // is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2 + // will give good results. + if nprimes >= 7 { + todo += (nprimes - 2) / 5 + } + for i := 0; i < nprimes; i++ { + var err error + primes[i], err = rand.Prime(random, todo/(nprimes-i)) + if err != nil { + return nil, err + } + todo -= primes[i].BitLen() + } + + // Make sure that primes is pairwise unequal. + for i, prime := range primes { + for j := 0; j < i; j++ { + if prime.Cmp(primes[j]) == 0 { + continue NextSetOfPrimes + } + } + } + + n := new(big.Int).Set(bigOne) + totient := new(big.Int).Set(bigOne) + pminus1 := new(big.Int) + for _, prime := range primes { + n.Mul(n, prime) + pminus1.Sub(prime, bigOne) + totient.Mul(totient, pminus1) + } + if n.BitLen() != bits { + // This should never happen for nprimes == 2 because + // crypto/rand should set the top two bits in each prime. + // For nprimes > 2 we hope it does not happen often. + continue NextSetOfPrimes + } + + priv.D = new(big.Int) + e := big.NewInt(int64(priv.E)) + ok := priv.D.ModInverse(e, totient) + + if ok != nil { + priv.Primes = primes + priv.N = n + break + } + } + + priv.Precompute() + return priv, nil +} + +// incCounter increments a four byte, big-endian counter. +func incCounter(c *[4]byte) { + if c[3]++; c[3] != 0 { + return + } + if c[2]++; c[2] != 0 { + return + } + if c[1]++; c[1] != 0 { + return + } + c[0]++ +} + +// mgf1XOR XORs the bytes in out with a mask generated using the MGF1 function +// specified in PKCS #1 v2.1. +func mgf1XOR(out []byte, hash hash.Hash, seed []byte) { + var counter [4]byte + var digest []byte + + done := 0 + for done < len(out) { + hash.Write(seed) + hash.Write(counter[0:4]) + digest = hash.Sum(digest[:0]) + hash.Reset() + + for i := 0; i < len(digest) && done < len(out); i++ { + out[done] ^= digest[i] + done++ + } + incCounter(&counter) + } +} + +// ErrMessageTooLong is returned when attempting to encrypt a message which is +// too large for the size of the public key. +var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size") + +func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int { + e := big.NewInt(int64(pub.E)) + c.Exp(m, e, pub.N) + return c +} + +// EncryptOAEP encrypts the given message with RSA-OAEP. +// +// OAEP is parameterised by a hash function that is used as a random oracle. +// Encryption and decryption of a given message must use the same hash function +// and sha256.New() is a reasonable choice. +// +// The random parameter is used as a source of entropy to ensure that +// encrypting the same message twice doesn't result in the same ciphertext. +// +// The label parameter may contain arbitrary data that will not be encrypted, +// but which gives important context to the message. For example, if a given +// public key is used to encrypt two types of messages then distinct label +// values could be used to ensure that a ciphertext for one purpose cannot be +// used for another by an attacker. If not required it can be empty. +// +// The message must be no longer than the length of the public modulus minus +// twice the hash length, minus a further 2. +func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) { + if err := checkPub(pub); err != nil { + return nil, err + } + hash.Reset() + k := pub.Size() + if len(msg) > k-2*hash.Size()-2 { + return nil, ErrMessageTooLong + } + + hash.Write(label) + lHash := hash.Sum(nil) + hash.Reset() + + em := make([]byte, k) + seed := em[1 : 1+hash.Size()] + db := em[1+hash.Size():] + + copy(db[0:hash.Size()], lHash) + db[len(db)-len(msg)-1] = 1 + copy(db[len(db)-len(msg):], msg) + + _, err := io.ReadFull(random, seed) + if err != nil { + return nil, err + } + + mgf1XOR(db, hash, seed) + mgf1XOR(seed, hash, db) + + m := new(big.Int) + m.SetBytes(em) + c := encrypt(new(big.Int), pub, m) + + out := make([]byte, k) + return c.FillBytes(out), nil +} + +// ErrDecryption represents a failure to decrypt a message. +// It is deliberately vague to avoid adaptive attacks. +var ErrDecryption = errors.New("crypto/rsa: decryption error") + +// ErrVerification represents a failure to verify a signature. +// It is deliberately vague to avoid adaptive attacks. +var ErrVerification = errors.New("crypto/rsa: verification error") + +// Precompute performs some calculations that speed up private key operations +// in the future. +func (priv *PrivateKey) Precompute() { + if priv.Precomputed.Dp != nil { + return + } + + priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne) + priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp) + + priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne) + priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq) + + priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0]) + + r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1]) + priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2) + for i := 2; i < len(priv.Primes); i++ { + prime := priv.Primes[i] + values := &priv.Precomputed.CRTValues[i-2] + + values.Exp = new(big.Int).Sub(prime, bigOne) + values.Exp.Mod(priv.D, values.Exp) + + values.R = new(big.Int).Set(r) + values.Coeff = new(big.Int).ModInverse(r, prime) + + r.Mul(r, prime) + } +} + +// decrypt performs an RSA decryption, resulting in a plaintext integer. If a +// random source is given, RSA blinding is used. +func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) { + // TODO(agl): can we get away with reusing blinds? + if c.Cmp(priv.N) > 0 { + err = ErrDecryption + return + } + if priv.N.Sign() == 0 { + return nil, ErrDecryption + } + + var ir *big.Int + if random != nil { + randutil.MaybeReadByte(random) + + // Blinding enabled. Blinding involves multiplying c by r^e. + // Then the decryption operation performs (m^e * r^e)^d mod n + // which equals mr mod n. The factor of r can then be removed + // by multiplying by the multiplicative inverse of r. + + var r *big.Int + ir = new(big.Int) + for { + r, err = rand.Int(random, priv.N) + if err != nil { + return + } + if r.Cmp(bigZero) == 0 { + r = bigOne + } + ok := ir.ModInverse(r, priv.N) + if ok != nil { + break + } + } + bigE := big.NewInt(int64(priv.E)) + rpowe := new(big.Int).Exp(r, bigE, priv.N) // N != 0 + cCopy := new(big.Int).Set(c) + cCopy.Mul(cCopy, rpowe) + cCopy.Mod(cCopy, priv.N) + c = cCopy + } + + if priv.Precomputed.Dp == nil { + m = new(big.Int).Exp(c, priv.D, priv.N) + } else { + // We have the precalculated values needed for the CRT. + m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0]) + m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1]) + m.Sub(m, m2) + if m.Sign() < 0 { + m.Add(m, priv.Primes[0]) + } + m.Mul(m, priv.Precomputed.Qinv) + m.Mod(m, priv.Primes[0]) + m.Mul(m, priv.Primes[1]) + m.Add(m, m2) + + for i, values := range priv.Precomputed.CRTValues { + prime := priv.Primes[2+i] + m2.Exp(c, values.Exp, prime) + m2.Sub(m2, m) + m2.Mul(m2, values.Coeff) + m2.Mod(m2, prime) + if m2.Sign() < 0 { + m2.Add(m2, prime) + } + m2.Mul(m2, values.R) + m.Add(m, m2) + } + } + + if ir != nil { + // Unblind. + m.Mul(m, ir) + m.Mod(m, priv.N) + } + + return +} + +func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) { + m, err = decrypt(random, priv, c) + if err != nil { + return nil, err + } + + // In order to defend against errors in the CRT computation, m^e is + // calculated, which should match the original ciphertext. + check := encrypt(new(big.Int), &priv.PublicKey, m) + if c.Cmp(check) != 0 { + return nil, errors.New("rsa: internal error") + } + return m, nil +} + +// DecryptOAEP decrypts ciphertext using RSA-OAEP. +// +// OAEP is parameterised by a hash function that is used as a random oracle. +// Encryption and decryption of a given message must use the same hash function +// and sha256.New() is a reasonable choice. +// +// The random parameter, if not nil, is used to blind the private-key operation +// and avoid timing side-channel attacks. Blinding is purely internal to this +// function – the random data need not match that used when encrypting. +// +// The label parameter must match the value given when encrypting. See +// EncryptOAEP for details. +func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) { + if err := checkPub(&priv.PublicKey); err != nil { + return nil, err + } + k := priv.Size() + if len(ciphertext) > k || + k < hash.Size()*2+2 { + return nil, ErrDecryption + } + + c := new(big.Int).SetBytes(ciphertext) + + m, err := decrypt(random, priv, c) + if err != nil { + return nil, err + } + + hash.Write(label) + lHash := hash.Sum(nil) + hash.Reset() + + // We probably leak the number of leading zeros. + // It's not clear that we can do anything about this. + em := m.FillBytes(make([]byte, k)) + + firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) + + seed := em[1 : hash.Size()+1] + db := em[hash.Size()+1:] + + mgf1XOR(seed, hash, db) + mgf1XOR(db, hash, seed) + + lHash2 := db[0:hash.Size()] + + // We have to validate the plaintext in constant time in order to avoid + // attacks like: J. Manger. A Chosen Ciphertext Attack on RSA Optimal + // Asymmetric Encryption Padding (OAEP) as Standardized in PKCS #1 + // v2.0. In J. Kilian, editor, Advances in Cryptology. + lHash2Good := subtle.ConstantTimeCompare(lHash, lHash2) + + // The remainder of the plaintext must be zero or more 0x00, followed + // by 0x01, followed by the message. + // lookingForIndex: 1 iff we are still looking for the 0x01 + // index: the offset of the first 0x01 byte + // invalid: 1 iff we saw a non-zero byte before the 0x01. + var lookingForIndex, index, invalid int + lookingForIndex = 1 + rest := db[hash.Size():] + + for i := 0; i < len(rest); i++ { + equals0 := subtle.ConstantTimeByteEq(rest[i], 0) + equals1 := subtle.ConstantTimeByteEq(rest[i], 1) + index = subtle.ConstantTimeSelect(lookingForIndex&equals1, i, index) + lookingForIndex = subtle.ConstantTimeSelect(equals1, 0, lookingForIndex) + invalid = subtle.ConstantTimeSelect(lookingForIndex&^equals0, 1, invalid) + } + + if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 { + return nil, ErrDecryption + } + + return rest[index+1:], nil +} diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go new file mode 100644 index 0000000..84b1674 --- /dev/null +++ b/src/crypto/rsa/rsa_test.go @@ -0,0 +1,420 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rsa + +import ( + "bytes" + "crypto" + "crypto/rand" + "crypto/sha1" + "crypto/sha256" + "math/big" + "testing" +) + +func TestKeyGeneration(t *testing.T) { + size := 1024 + if testing.Short() { + size = 128 + } + priv, err := GenerateKey(rand.Reader, size) + if err != nil { + t.Errorf("failed to generate key") + } + if bits := priv.N.BitLen(); bits != size { + t.Errorf("key too short (%d vs %d)", bits, size) + } + testKeyBasics(t, priv) +} + +func Test3PrimeKeyGeneration(t *testing.T) { + size := 768 + if testing.Short() { + size = 256 + } + + priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size) + if err != nil { + t.Errorf("failed to generate key") + } + testKeyBasics(t, priv) +} + +func Test4PrimeKeyGeneration(t *testing.T) { + size := 768 + if testing.Short() { + size = 256 + } + + priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size) + if err != nil { + t.Errorf("failed to generate key") + } + testKeyBasics(t, priv) +} + +func TestNPrimeKeyGeneration(t *testing.T) { + primeSize := 64 + maxN := 24 + if testing.Short() { + primeSize = 16 + maxN = 16 + } + // Test that generation of N-prime keys works for N > 4. + for n := 5; n < maxN; n++ { + priv, err := GenerateMultiPrimeKey(rand.Reader, n, 64+n*primeSize) + if err == nil { + testKeyBasics(t, priv) + } else { + t.Errorf("failed to generate %d-prime key", n) + } + } +} + +func TestImpossibleKeyGeneration(t *testing.T) { + // This test ensures that trying to generate toy RSA keys doesn't enter + // an infinite loop. + for i := 0; i < 32; i++ { + GenerateKey(rand.Reader, i) + GenerateMultiPrimeKey(rand.Reader, 3, i) + GenerateMultiPrimeKey(rand.Reader, 4, i) + GenerateMultiPrimeKey(rand.Reader, 5, i) + } +} + +func TestGnuTLSKey(t *testing.T) { + // This is a key generated by `certtool --generate-privkey --bits 128`. + // It's such that de ≢ 1 mod φ(n), but is congruent mod the order of + // the group. + priv := &PrivateKey{ + PublicKey: PublicKey{ + N: fromBase10("290684273230919398108010081414538931343"), + E: 65537, + }, + D: fromBase10("31877380284581499213530787347443987241"), + Primes: []*big.Int{ + fromBase10("16775196964030542637"), + fromBase10("17328218193455850539"), + }, + } + testKeyBasics(t, priv) +} + +func testKeyBasics(t *testing.T, priv *PrivateKey) { + if err := priv.Validate(); err != nil { + t.Errorf("Validate() failed: %s", err) + } + if priv.D.Cmp(priv.N) > 0 { + t.Errorf("private exponent too large") + } + + pub := &priv.PublicKey + m := big.NewInt(42) + c := encrypt(new(big.Int), pub, m) + + m2, err := decrypt(nil, priv, c) + if err != nil { + t.Errorf("error while decrypting: %s", err) + return + } + if m.Cmp(m2) != 0 { + t.Errorf("got:%v, want:%v (%+v)", m2, m, priv) + } + + m3, err := decrypt(rand.Reader, priv, c) + if err != nil { + t.Errorf("error while decrypting (blind): %s", err) + } + if m.Cmp(m3) != 0 { + t.Errorf("(blind) got:%v, want:%v (%#v)", m3, m, priv) + } +} + +func fromBase10(base10 string) *big.Int { + i, ok := new(big.Int).SetString(base10, 10) + if !ok { + panic("bad number: " + base10) + } + return i +} + +var test2048Key *PrivateKey + +func init() { + test2048Key = &PrivateKey{ + PublicKey: PublicKey{ + N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"), + E: 3, + }, + D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"), + Primes: []*big.Int{ + fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"), + fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"), + }, + } + test2048Key.Precompute() +} + +func BenchmarkRSA2048Decrypt(b *testing.B) { + b.StopTimer() + + c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313") + + b.StartTimer() + + for i := 0; i < b.N; i++ { + decrypt(nil, test2048Key, c) + } +} + +func BenchmarkRSA2048Sign(b *testing.B) { + b.StopTimer() + hashed := sha256.Sum256([]byte("testing")) + b.StartTimer() + + for i := 0; i < b.N; i++ { + SignPKCS1v15(rand.Reader, test2048Key, crypto.SHA256, hashed[:]) + } +} + +func Benchmark3PrimeRSA2048Decrypt(b *testing.B) { + b.StopTimer() + priv := &PrivateKey{ + PublicKey: PublicKey{ + N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"), + E: 3, + }, + D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"), + Primes: []*big.Int{ + fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"), + fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"), + fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"), + }, + } + priv.Precompute() + + c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313") + + b.StartTimer() + + for i := 0; i < b.N; i++ { + decrypt(nil, priv, c) + } +} + +type testEncryptOAEPMessage struct { + in []byte + seed []byte + out []byte +} + +type testEncryptOAEPStruct struct { + modulus string + e int + d string + msgs []testEncryptOAEPMessage +} + +func TestEncryptOAEP(t *testing.T) { + sha1 := sha1.New() + n := new(big.Int) + for i, test := range testEncryptOAEPData { + n.SetString(test.modulus, 16) + public := PublicKey{n, test.e} + + for j, message := range test.msgs { + randomSource := bytes.NewReader(message.seed) + out, err := EncryptOAEP(sha1, randomSource, &public, message.in, nil) + if err != nil { + t.Errorf("#%d,%d error: %s", i, j, err) + } + if !bytes.Equal(out, message.out) { + t.Errorf("#%d,%d bad result: %x (want %x)", i, j, out, message.out) + } + } + } +} + +func TestDecryptOAEP(t *testing.T) { + random := rand.Reader + + sha1 := sha1.New() + n := new(big.Int) + d := new(big.Int) + for i, test := range testEncryptOAEPData { + n.SetString(test.modulus, 16) + d.SetString(test.d, 16) + private := new(PrivateKey) + private.PublicKey = PublicKey{n, test.e} + private.D = d + + for j, message := range test.msgs { + out, err := DecryptOAEP(sha1, nil, private, message.out, nil) + if err != nil { + t.Errorf("#%d,%d error: %s", i, j, err) + } else if !bytes.Equal(out, message.in) { + t.Errorf("#%d,%d bad result: %#v (want %#v)", i, j, out, message.in) + } + + // Decrypt with blinding. + out, err = DecryptOAEP(sha1, random, private, message.out, nil) + if err != nil { + t.Errorf("#%d,%d (blind) error: %s", i, j, err) + } else if !bytes.Equal(out, message.in) { + t.Errorf("#%d,%d (blind) bad result: %#v (want %#v)", i, j, out, message.in) + } + } + if testing.Short() { + break + } + } +} + +// testEncryptOAEPData contains a subset of the vectors from RSA's "Test vectors for RSA-OAEP". +var testEncryptOAEPData = []testEncryptOAEPStruct{ + // Key 1 + {"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb", + 65537, + "53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1", + []testEncryptOAEPMessage{ + // Example 1.1 + { + []byte{0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, + 0x3b, 0xa9, 0x4c, 0xda, 0x9e, 0xf9, 0x53, 0x23, 0x97, + 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, 0x4a, 0xfe, + 0xfe, 0x34, + }, + []byte{0x18, 0xb7, 0x76, 0xea, 0x21, 0x06, 0x9d, 0x69, + 0x77, 0x6a, 0x33, 0xe9, 0x6b, 0xad, 0x48, 0xe1, 0xdd, + 0xa0, 0xa5, 0xef, + }, + []byte{0x35, 0x4f, 0xe6, 0x7b, 0x4a, 0x12, 0x6d, 0x5d, + 0x35, 0xfe, 0x36, 0xc7, 0x77, 0x79, 0x1a, 0x3f, 0x7b, + 0xa1, 0x3d, 0xef, 0x48, 0x4e, 0x2d, 0x39, 0x08, 0xaf, + 0xf7, 0x22, 0xfa, 0xd4, 0x68, 0xfb, 0x21, 0x69, 0x6d, + 0xe9, 0x5d, 0x0b, 0xe9, 0x11, 0xc2, 0xd3, 0x17, 0x4f, + 0x8a, 0xfc, 0xc2, 0x01, 0x03, 0x5f, 0x7b, 0x6d, 0x8e, + 0x69, 0x40, 0x2d, 0xe5, 0x45, 0x16, 0x18, 0xc2, 0x1a, + 0x53, 0x5f, 0xa9, 0xd7, 0xbf, 0xc5, 0xb8, 0xdd, 0x9f, + 0xc2, 0x43, 0xf8, 0xcf, 0x92, 0x7d, 0xb3, 0x13, 0x22, + 0xd6, 0xe8, 0x81, 0xea, 0xa9, 0x1a, 0x99, 0x61, 0x70, + 0xe6, 0x57, 0xa0, 0x5a, 0x26, 0x64, 0x26, 0xd9, 0x8c, + 0x88, 0x00, 0x3f, 0x84, 0x77, 0xc1, 0x22, 0x70, 0x94, + 0xa0, 0xd9, 0xfa, 0x1e, 0x8c, 0x40, 0x24, 0x30, 0x9c, + 0xe1, 0xec, 0xcc, 0xb5, 0x21, 0x00, 0x35, 0xd4, 0x7a, + 0xc7, 0x2e, 0x8a, + }, + }, + // Example 1.2 + { + []byte{0x75, 0x0c, 0x40, 0x47, 0xf5, 0x47, 0xe8, 0xe4, + 0x14, 0x11, 0x85, 0x65, 0x23, 0x29, 0x8a, 0xc9, 0xba, + 0xe2, 0x45, 0xef, 0xaf, 0x13, 0x97, 0xfb, 0xe5, 0x6f, + 0x9d, 0xd5, + }, + []byte{0x0c, 0xc7, 0x42, 0xce, 0x4a, 0x9b, 0x7f, 0x32, + 0xf9, 0x51, 0xbc, 0xb2, 0x51, 0xef, 0xd9, 0x25, 0xfe, + 0x4f, 0xe3, 0x5f, + }, + []byte{0x64, 0x0d, 0xb1, 0xac, 0xc5, 0x8e, 0x05, 0x68, + 0xfe, 0x54, 0x07, 0xe5, 0xf9, 0xb7, 0x01, 0xdf, 0xf8, + 0xc3, 0xc9, 0x1e, 0x71, 0x6c, 0x53, 0x6f, 0xc7, 0xfc, + 0xec, 0x6c, 0xb5, 0xb7, 0x1c, 0x11, 0x65, 0x98, 0x8d, + 0x4a, 0x27, 0x9e, 0x15, 0x77, 0xd7, 0x30, 0xfc, 0x7a, + 0x29, 0x93, 0x2e, 0x3f, 0x00, 0xc8, 0x15, 0x15, 0x23, + 0x6d, 0x8d, 0x8e, 0x31, 0x01, 0x7a, 0x7a, 0x09, 0xdf, + 0x43, 0x52, 0xd9, 0x04, 0xcd, 0xeb, 0x79, 0xaa, 0x58, + 0x3a, 0xdc, 0xc3, 0x1e, 0xa6, 0x98, 0xa4, 0xc0, 0x52, + 0x83, 0xda, 0xba, 0x90, 0x89, 0xbe, 0x54, 0x91, 0xf6, + 0x7c, 0x1a, 0x4e, 0xe4, 0x8d, 0xc7, 0x4b, 0xbb, 0xe6, + 0x64, 0x3a, 0xef, 0x84, 0x66, 0x79, 0xb4, 0xcb, 0x39, + 0x5a, 0x35, 0x2d, 0x5e, 0xd1, 0x15, 0x91, 0x2d, 0xf6, + 0x96, 0xff, 0xe0, 0x70, 0x29, 0x32, 0x94, 0x6d, 0x71, + 0x49, 0x2b, 0x44, + }, + }, + // Example 1.3 + { + []byte{0xd9, 0x4a, 0xe0, 0x83, 0x2e, 0x64, 0x45, 0xce, + 0x42, 0x33, 0x1c, 0xb0, 0x6d, 0x53, 0x1a, 0x82, 0xb1, + 0xdb, 0x4b, 0xaa, 0xd3, 0x0f, 0x74, 0x6d, 0xc9, 0x16, + 0xdf, 0x24, 0xd4, 0xe3, 0xc2, 0x45, 0x1f, 0xff, 0x59, + 0xa6, 0x42, 0x3e, 0xb0, 0xe1, 0xd0, 0x2d, 0x4f, 0xe6, + 0x46, 0xcf, 0x69, 0x9d, 0xfd, 0x81, 0x8c, 0x6e, 0x97, + 0xb0, 0x51, + }, + []byte{0x25, 0x14, 0xdf, 0x46, 0x95, 0x75, 0x5a, 0x67, + 0xb2, 0x88, 0xea, 0xf4, 0x90, 0x5c, 0x36, 0xee, 0xc6, + 0x6f, 0xd2, 0xfd, + }, + []byte{0x42, 0x37, 0x36, 0xed, 0x03, 0x5f, 0x60, 0x26, + 0xaf, 0x27, 0x6c, 0x35, 0xc0, 0xb3, 0x74, 0x1b, 0x36, + 0x5e, 0x5f, 0x76, 0xca, 0x09, 0x1b, 0x4e, 0x8c, 0x29, + 0xe2, 0xf0, 0xbe, 0xfe, 0xe6, 0x03, 0x59, 0x5a, 0xa8, + 0x32, 0x2d, 0x60, 0x2d, 0x2e, 0x62, 0x5e, 0x95, 0xeb, + 0x81, 0xb2, 0xf1, 0xc9, 0x72, 0x4e, 0x82, 0x2e, 0xca, + 0x76, 0xdb, 0x86, 0x18, 0xcf, 0x09, 0xc5, 0x34, 0x35, + 0x03, 0xa4, 0x36, 0x08, 0x35, 0xb5, 0x90, 0x3b, 0xc6, + 0x37, 0xe3, 0x87, 0x9f, 0xb0, 0x5e, 0x0e, 0xf3, 0x26, + 0x85, 0xd5, 0xae, 0xc5, 0x06, 0x7c, 0xd7, 0xcc, 0x96, + 0xfe, 0x4b, 0x26, 0x70, 0xb6, 0xea, 0xc3, 0x06, 0x6b, + 0x1f, 0xcf, 0x56, 0x86, 0xb6, 0x85, 0x89, 0xaa, 0xfb, + 0x7d, 0x62, 0x9b, 0x02, 0xd8, 0xf8, 0x62, 0x5c, 0xa3, + 0x83, 0x36, 0x24, 0xd4, 0x80, 0x0f, 0xb0, 0x81, 0xb1, + 0xcf, 0x94, 0xeb, + }, + }, + }, + }, + // Key 10 + {"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb", + 65537, + "056b04216fe5f354ac77250a4b6b0c8525a85c59b0bd80c56450a22d5f438e596a333aa875e291dd43f48cb88b9d5fc0d499f9fcd1c397f9afc070cd9e398c8d19e61db7c7410a6b2675dfbf5d345b804d201add502d5ce2dfcb091ce9997bbebe57306f383e4d588103f036f7e85d1934d152a323e4a8db451d6f4a5b1b0f102cc150e02feee2b88dea4ad4c1baccb24d84072d14e1d24a6771f7408ee30564fb86d4393a34bcf0b788501d193303f13a2284b001f0f649eaf79328d4ac5c430ab4414920a9460ed1b7bc40ec653e876d09abc509ae45b525190116a0c26101848298509c1c3bf3a483e7274054e15e97075036e989f60932807b5257751e79", + []testEncryptOAEPMessage{ + // Example 10.1 + { + []byte{0x8b, 0xba, 0x6b, 0xf8, 0x2a, 0x6c, 0x0f, 0x86, + 0xd5, 0xf1, 0x75, 0x6e, 0x97, 0x95, 0x68, 0x70, 0xb0, + 0x89, 0x53, 0xb0, 0x6b, 0x4e, 0xb2, 0x05, 0xbc, 0x16, + 0x94, 0xee, + }, + []byte{0x47, 0xe1, 0xab, 0x71, 0x19, 0xfe, 0xe5, 0x6c, + 0x95, 0xee, 0x5e, 0xaa, 0xd8, 0x6f, 0x40, 0xd0, 0xaa, + 0x63, 0xbd, 0x33, + }, + []byte{0x53, 0xea, 0x5d, 0xc0, 0x8c, 0xd2, 0x60, 0xfb, + 0x3b, 0x85, 0x85, 0x67, 0x28, 0x7f, 0xa9, 0x15, 0x52, + 0xc3, 0x0b, 0x2f, 0xeb, 0xfb, 0xa2, 0x13, 0xf0, 0xae, + 0x87, 0x70, 0x2d, 0x06, 0x8d, 0x19, 0xba, 0xb0, 0x7f, + 0xe5, 0x74, 0x52, 0x3d, 0xfb, 0x42, 0x13, 0x9d, 0x68, + 0xc3, 0xc5, 0xaf, 0xee, 0xe0, 0xbf, 0xe4, 0xcb, 0x79, + 0x69, 0xcb, 0xf3, 0x82, 0xb8, 0x04, 0xd6, 0xe6, 0x13, + 0x96, 0x14, 0x4e, 0x2d, 0x0e, 0x60, 0x74, 0x1f, 0x89, + 0x93, 0xc3, 0x01, 0x4b, 0x58, 0xb9, 0xb1, 0x95, 0x7a, + 0x8b, 0xab, 0xcd, 0x23, 0xaf, 0x85, 0x4f, 0x4c, 0x35, + 0x6f, 0xb1, 0x66, 0x2a, 0xa7, 0x2b, 0xfc, 0xc7, 0xe5, + 0x86, 0x55, 0x9d, 0xc4, 0x28, 0x0d, 0x16, 0x0c, 0x12, + 0x67, 0x85, 0xa7, 0x23, 0xeb, 0xee, 0xbe, 0xff, 0x71, + 0xf1, 0x15, 0x94, 0x44, 0x0a, 0xae, 0xf8, 0x7d, 0x10, + 0x79, 0x3a, 0x87, 0x74, 0xa2, 0x39, 0xd4, 0xa0, 0x4c, + 0x87, 0xfe, 0x14, 0x67, 0xb9, 0xda, 0xf8, 0x52, 0x08, + 0xec, 0x6c, 0x72, 0x55, 0x79, 0x4a, 0x96, 0xcc, 0x29, + 0x14, 0x2f, 0x9a, 0x8b, 0xd4, 0x18, 0xe3, 0xc1, 0xfd, + 0x67, 0x34, 0x4b, 0x0c, 0xd0, 0x82, 0x9d, 0xf3, 0xb2, + 0xbe, 0xc6, 0x02, 0x53, 0x19, 0x62, 0x93, 0xc6, 0xb3, + 0x4d, 0x3f, 0x75, 0xd3, 0x2f, 0x21, 0x3d, 0xd4, 0x5c, + 0x62, 0x73, 0xd5, 0x05, 0xad, 0xf4, 0xcc, 0xed, 0x10, + 0x57, 0xcb, 0x75, 0x8f, 0xc2, 0x6a, 0xee, 0xfa, 0x44, + 0x12, 0x55, 0xed, 0x4e, 0x64, 0xc1, 0x99, 0xee, 0x07, + 0x5e, 0x7f, 0x16, 0x64, 0x61, 0x82, 0xfd, 0xb4, 0x64, + 0x73, 0x9b, 0x68, 0xab, 0x5d, 0xaf, 0xf0, 0xe6, 0x3e, + 0x95, 0x52, 0x01, 0x68, 0x24, 0xf0, 0x54, 0xbf, 0x4d, + 0x3c, 0x8c, 0x90, 0xa9, 0x7b, 0xb6, 0xb6, 0x55, 0x32, + 0x84, 0xeb, 0x42, 0x9f, 0xcc, + }, + }, + }, + }, +} diff --git a/src/crypto/rsa/testdata/pss-vect.txt.bz2 b/src/crypto/rsa/testdata/pss-vect.txt.bz2 new file mode 100644 index 0000000..ad3da1a Binary files /dev/null and b/src/crypto/rsa/testdata/pss-vect.txt.bz2 differ diff --git a/src/crypto/sha1/example_test.go b/src/crypto/sha1/example_test.go new file mode 100644 index 0000000..499055c --- /dev/null +++ b/src/crypto/sha1/example_test.go @@ -0,0 +1,42 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha1_test + +import ( + "crypto/sha1" + "fmt" + "io" + "log" + "os" +) + +func ExampleNew() { + h := sha1.New() + io.WriteString(h, "His money is twice tainted:") + io.WriteString(h, " 'taint yours and 'taint mine.") + fmt.Printf("% x", h.Sum(nil)) + // Output: 59 7f 6a 54 00 10 f9 4c 15 d7 18 06 a9 9a 2c 87 10 e7 47 bd +} + +func ExampleSum() { + data := []byte("This page intentionally left blank.") + fmt.Printf("% x", sha1.Sum(data)) + // Output: af 06 49 23 bb f2 30 15 96 aa c4 c2 73 ba 32 17 8e bc 4a 96 +} + +func ExampleNew_file() { + f, err := os.Open("file.txt") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + h := sha1.New() + if _, err := io.Copy(h, f); err != nil { + log.Fatal(err) + } + + fmt.Printf("% x", h.Sum(nil)) +} diff --git a/src/crypto/sha1/fallback_test.go b/src/crypto/sha1/fallback_test.go new file mode 100644 index 0000000..4bb8b33 --- /dev/null +++ b/src/crypto/sha1/fallback_test.go @@ -0,0 +1,35 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build s390x +// +build s390x + +package sha1 + +import ( + "fmt" + "io" + "testing" +) + +// Tests the fallback code path in case the optimized asm +// implementation cannot be used. +// See also TestBlockGeneric. +func TestGenericPath(t *testing.T) { + if useAsm == false { + t.Skipf("assembly implementation unavailable") + } + useAsm = false + defer func() { useAsm = true }() + c := New() + in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" + gold := "0f58c2bb130f8182375f325c18342215255387e5" + if _, err := io.WriteString(c, in); err != nil { + t.Fatalf("could not write to c: %v", err) + } + out := fmt.Sprintf("%x", c.Sum(nil)) + if out != gold { + t.Fatalf("mismatch: got %s, wanted %s", out, gold) + } +} diff --git a/src/crypto/sha1/issue15617_test.go b/src/crypto/sha1/issue15617_test.go new file mode 100644 index 0000000..436f78c --- /dev/null +++ b/src/crypto/sha1/issue15617_test.go @@ -0,0 +1,29 @@ +//go:build amd64 && (linux || darwin) +// +build amd64 +// +build linux darwin + +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha1_test + +import ( + "crypto/sha1" + "syscall" + "testing" +) + +func TestOutOfBoundsRead(t *testing.T) { + const pageSize = 4 << 10 + data, err := syscall.Mmap(0, 0, 2*pageSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) + if err != nil { + panic(err) + } + if err := syscall.Mprotect(data[pageSize:], syscall.PROT_NONE); err != nil { + panic(err) + } + for i := 0; i < pageSize; i++ { + sha1.Sum(data[pageSize-i : pageSize]) + } +} diff --git a/src/crypto/sha1/sha1.go b/src/crypto/sha1/sha1.go new file mode 100644 index 0000000..286a59d --- /dev/null +++ b/src/crypto/sha1/sha1.go @@ -0,0 +1,266 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sha1 implements the SHA-1 hash algorithm as defined in RFC 3174. +// +// SHA-1 is cryptographically broken and should not be used for secure +// applications. +package sha1 + +import ( + "crypto" + "encoding/binary" + "errors" + "hash" +) + +func init() { + crypto.RegisterHash(crypto.SHA1, New) +} + +// The size of a SHA-1 checksum in bytes. +const Size = 20 + +// The blocksize of SHA-1 in bytes. +const BlockSize = 64 + +const ( + chunk = 64 + init0 = 0x67452301 + init1 = 0xEFCDAB89 + init2 = 0x98BADCFE + init3 = 0x10325476 + init4 = 0xC3D2E1F0 +) + +// digest represents the partial evaluation of a checksum. +type digest struct { + h [5]uint32 + x [chunk]byte + nx int + len uint64 +} + +const ( + magic = "sha\x01" + marshaledSize = len(magic) + 5*4 + chunk + 8 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + b = appendUint32(b, d.h[0]) + b = appendUint32(b, d.h[1]) + b = appendUint32(b, d.h[2]) + b = appendUint32(b, d.h[3]) + b = appendUint32(b, d.h[4]) + b = append(b, d.x[:d.nx]...) + b = b[:len(b)+len(d.x)-int(d.nx)] // already zero + b = appendUint64(b, d.len) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/sha1: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/sha1: invalid hash state size") + } + b = b[len(magic):] + b, d.h[0] = consumeUint32(b) + b, d.h[1] = consumeUint32(b) + b, d.h[2] = consumeUint32(b) + b, d.h[3] = consumeUint32(b) + b, d.h[4] = consumeUint32(b) + b = b[copy(d.x[:], b):] + b, d.len = consumeUint64(b) + d.nx = int(d.len % chunk) + return nil +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + _ = b[7] + x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 + return b[8:], x +} + +func consumeUint32(b []byte) ([]byte, uint32) { + _ = b[3] + x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 + return b[4:], x +} + +func (d *digest) Reset() { + d.h[0] = init0 + d.h[1] = init1 + d.h[2] = init2 + d.h[3] = init3 + d.h[4] = init4 + d.nx = 0 + d.len = 0 +} + +// New returns a new hash.Hash computing the SHA1 checksum. The Hash also +// implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to +// marshal and unmarshal the internal state of the hash. +func New() hash.Hash { + d := new(digest) + d.Reset() + return d +} + +func (d *digest) Size() int { return Size } + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Write(p []byte) (nn int, err error) { + nn = len(p) + d.len += uint64(nn) + if d.nx > 0 { + n := copy(d.x[d.nx:], p) + d.nx += n + if d.nx == chunk { + block(d, d.x[:]) + d.nx = 0 + } + p = p[n:] + } + if len(p) >= chunk { + n := len(p) &^ (chunk - 1) + block(d, p[:n]) + p = p[n:] + } + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d so that caller can keep writing and summing. + d0 := *d + hash := d0.checkSum() + return append(in, hash[:]...) +} + +func (d *digest) checkSum() [Size]byte { + len := d.len + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + var tmp [64]byte + tmp[0] = 0x80 + if len%64 < 56 { + d.Write(tmp[0 : 56-len%64]) + } else { + d.Write(tmp[0 : 64+56-len%64]) + } + + // Length in bits. + len <<= 3 + binary.BigEndian.PutUint64(tmp[:], len) + d.Write(tmp[0:8]) + + if d.nx != 0 { + panic("d.nx != 0") + } + + var digest [Size]byte + + binary.BigEndian.PutUint32(digest[0:], d.h[0]) + binary.BigEndian.PutUint32(digest[4:], d.h[1]) + binary.BigEndian.PutUint32(digest[8:], d.h[2]) + binary.BigEndian.PutUint32(digest[12:], d.h[3]) + binary.BigEndian.PutUint32(digest[16:], d.h[4]) + + return digest +} + +// ConstantTimeSum computes the same result of Sum() but in constant time +func (d *digest) ConstantTimeSum(in []byte) []byte { + d0 := *d + hash := d0.constSum() + return append(in, hash[:]...) +} + +func (d *digest) constSum() [Size]byte { + var length [8]byte + l := d.len << 3 + for i := uint(0); i < 8; i++ { + length[i] = byte(l >> (56 - 8*i)) + } + + nx := byte(d.nx) + t := nx - 56 // if nx < 56 then the MSB of t is one + mask1b := byte(int8(t) >> 7) // mask1b is 0xFF iff one block is enough + + separator := byte(0x80) // gets reset to 0x00 once used + for i := byte(0); i < chunk; i++ { + mask := byte(int8(i-nx) >> 7) // 0x00 after the end of data + + // if we reached the end of the data, replace with 0x80 or 0x00 + d.x[i] = (^mask & separator) | (mask & d.x[i]) + + // zero the separator once used + separator &= mask + + if i >= 56 { + // we might have to write the length here if all fit in one block + d.x[i] |= mask1b & length[i-56] + } + } + + // compress, and only keep the digest if all fit in one block + block(d, d.x[:]) + + var digest [Size]byte + for i, s := range d.h { + digest[i*4] = mask1b & byte(s>>24) + digest[i*4+1] = mask1b & byte(s>>16) + digest[i*4+2] = mask1b & byte(s>>8) + digest[i*4+3] = mask1b & byte(s) + } + + for i := byte(0); i < chunk; i++ { + // second block, it's always past the end of data, might start with 0x80 + if i < 56 { + d.x[i] = separator + separator = 0 + } else { + d.x[i] = length[i-56] + } + } + + // compress, and only keep the digest if we actually needed the second block + block(d, d.x[:]) + + for i, s := range d.h { + digest[i*4] |= ^mask1b & byte(s>>24) + digest[i*4+1] |= ^mask1b & byte(s>>16) + digest[i*4+2] |= ^mask1b & byte(s>>8) + digest[i*4+3] |= ^mask1b & byte(s) + } + + return digest +} + +// Sum returns the SHA-1 checksum of the data. +func Sum(data []byte) [Size]byte { + var d digest + d.Reset() + d.Write(data) + return d.checkSum() +} diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go new file mode 100644 index 0000000..c3e6010 --- /dev/null +++ b/src/crypto/sha1/sha1_test.go @@ -0,0 +1,240 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// SHA-1 hash algorithm. See RFC 3174. + +package sha1 + +import ( + "bytes" + "crypto/rand" + "encoding" + "fmt" + "hash" + "io" + "testing" +) + +type sha1Test struct { + out string + in string + halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal +} + +var golden = []sha1Test{ + {"76245dbf96f661bd221046197ab8b9f063f11bad", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n", "sha\x01\v\xa0)I\xdeq(8h\x9ev\xe5\x88[\xf8\x81\x17\xba4Daaaaaaaaaaaaaaaaaaaaaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96"}, + {"da39a3ee5e6b4b0d3255bfef95601890afd80709", "", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, + {"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "a", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, + {"da23614e02469a0d7c7bd1bdab5c9c474b1904dc", "ab", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"}, + {"a9993e364706816aba3e25717850c26c9cd0d89d", "abc", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"}, + {"81fe8bfe87576c3ecb22426f8e57847382917acf", "abcd", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"}, + {"03de6c570bfe24bfc328ccd7ca46b76eadaf4334", "abcde", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"}, + {"1f8ac10f23c5b5bc1167bda84b833e5c057a77d2", "abcdef", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"}, + {"2fb5e13419fc89246865e7a324f476ec624e8740", "abcdefg", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"}, + {"425af12a0743502b322e93a015bcf868e324d56a", "abcdefgh", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"}, + {"c63b19f1e4c8b5f76b25c49b8b87f57d8e4872a1", "abcdefghi", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"}, + {"d68c19a0a345b7eab78d5e11e991c026ec60db63", "abcdefghij", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0abcde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05"}, + {"ebf81ddcbe5bf13aaabdc4d65354fdf2044f38a7", "Discard medicine more than two years old.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0Discard medicine mor\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14"}, + {"e5dea09392dd886ca63531aaa00571dc07554bb6", "He who has a shady past knows that nice guys finish last.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0He who has a shady past know\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, + {"45988f7234467b94e3e9494434c96ee3609d8f8f", "I wouldn't marry him with a ten foot pole.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0I wouldn't marry him \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15"}, + {"55dee037eb7460d5a692d1ce11330b260e40c988", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0Free! Free!/A trip/to Mars/f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, + {"b7bc5fb91080c7de6b582ea281f8a396d7c0aee8", "The days of the digital watch are numbered. -Tom Stoppard", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0The days of the digital watch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d"}, + {"c3aed9358f7c77f523afe86135f06b95b3999797", "Nepal premier won't resign.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0Nepal premier\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r"}, + {"6e29d302bf6e3a5e4305ff318d983197d6906bb9", "For every action there is an equal and opposite government program.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0For every action there is an equa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!"}, + {"597f6a540010f94c15d71806a99a2c8710e747bd", "His money is twice tainted: 'taint yours and 'taint mine.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0His money is twice tainted: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, + {"6859733b2590a8a091cecf50086febc5ceef1e80", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0There is no reason for any individual to hav\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,"}, + {"514b2630ec089b8aee18795fc0cf1f4860cdacad", "It's a tiny change to the code and not completely disgusting. - Bob Manchek", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0It's a tiny change to the code and no\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%"}, + {"c5ca0d4a7b6676fc7aa72caa41cc3d5df567ed69", "size: a.out: bad magic", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0size: a.out\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f"}, + {"74c51fa9a04eadc8c1bbeaa7fc442f834b90a00a", "The major problem is with sendmail. -Mark Horton", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0The major problem is wit\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18"}, + {"0b4c4ce5f52c3ad2821852a8dc00217fa18b8b66", "Give me a rock, paper and scissors and I will move the world. CCFestoon", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0Give me a rock, paper and scissors a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$"}, + {"3ae7937dd790315beb0f48330e8642237c61550a", "If the enemy is within range, then so are you.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0If the enemy is within \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17"}, + {"410a2b296df92b9a47412b13281df8f830a9f44b", "It's well we cannot hear the screams/That we create in others' dreams.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0It's well we cannot hear the scream\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#"}, + {"841e7c85ca1adcddbdd0187f1289acb5c642f7f5", "You remind me of a TV show, but that's all right: I watch it anyway.", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0You remind me of a TV show, but th\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\""}, + {"163173b825d03b952601376b25212df66763e1db", "C is as portable as Stonehedge!!", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0C is as portable\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10"}, + {"32b0377f2687eb88e22106f133c586ab314d5279", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0Even if I could be Shakespeare, I think I sh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,"}, + {"0885aaf99b569542fd165fa44e322718f4a984e0", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule", "sha\x01x}\xf4\r\xeb\xf2\x10\x87\xe8[\xb2JA$D\xb7\u063ax8em\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B"}, + {"6627d6904d71420b0bf3886ab629623538689f45", "How can you write a big system without C++? -Paul Glick", "sha\x01gE#\x01\xef\u036b\x89\x98\xba\xdc\xfe\x102Tv\xc3\xd2\xe1\xf0How can you write a big syst\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, +} + +func TestGolden(t *testing.T) { + for i := 0; i < len(golden); i++ { + g := golden[i] + s := fmt.Sprintf("%x", Sum([]byte(g.in))) + if s != g.out { + t.Fatalf("Sum function: sha1(%s) = %s want %s", g.in, s, g.out) + } + c := New() + for j := 0; j < 4; j++ { + var sum []byte + switch j { + case 0, 1: + io.WriteString(c, g.in) + sum = c.Sum(nil) + case 2: + io.WriteString(c, g.in[0:len(g.in)/2]) + c.Sum(nil) + io.WriteString(c, g.in[len(g.in)/2:]) + sum = c.Sum(nil) + case 3: + io.WriteString(c, g.in[0:len(g.in)/2]) + c.(*digest).ConstantTimeSum(nil) + io.WriteString(c, g.in[len(g.in)/2:]) + sum = c.(*digest).ConstantTimeSum(nil) + } + s := fmt.Sprintf("%x", sum) + if s != g.out { + t.Fatalf("sha1[%d](%s) = %s want %s", j, g.in, s, g.out) + } + c.Reset() + } + } +} + +func TestGoldenMarshal(t *testing.T) { + h := New() + h2 := New() + for _, g := range golden { + h.Reset() + h2.Reset() + + io.WriteString(h, g.in[:len(g.in)/2]) + + state, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { + t.Errorf("could not marshal: %v", err) + continue + } + + if string(state) != g.halfState { + t.Errorf("sha1(%q) state = %+q, want %+q", g.in, state, g.halfState) + continue + } + + if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil { + t.Errorf("could not unmarshal: %v", err) + continue + } + + io.WriteString(h, g.in[len(g.in)/2:]) + io.WriteString(h2, g.in[len(g.in)/2:]) + + if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) { + t.Errorf("sha1(%q) = 0x%x != marshaled 0x%x", g.in, actual, actual2) + } + } +} + +func TestSize(t *testing.T) { + c := New() + if got := c.Size(); got != Size { + t.Errorf("Size = %d; want %d", got, Size) + } +} + +func TestBlockSize(t *testing.T) { + c := New() + if got := c.BlockSize(); got != BlockSize { + t.Errorf("BlockSize = %d; want %d", got, BlockSize) + } +} + +// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. +func TestBlockGeneric(t *testing.T) { + for i := 1; i < 30; i++ { // arbitrary factor + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*i) + rand.Read(buf) + blockGeneric(gen, buf) + block(asm, buf) + if *gen != *asm { + t.Errorf("For %#v block and blockGeneric resulted in different states", buf) + } + } +} + +// Tests for unmarshaling hashes that have hashed a large amount of data +// The initial hash generation is omitted from the test, because it takes a long time. +// The test contains some already-generated states, and their expected sums +// Tests a problem that is outlined in GitHub issue #29543 +// The problem is triggered when an amount of data has been hashed for which +// the data length has a 1 in the 32nd bit. When casted to int, this changes +// the sign of the value, and causes the modulus operation to return a +// different result. +type unmarshalTest struct { + state string + sum string +} + +var largeUnmarshalTests = []unmarshalTest{ + // Data length: 7_102_415_735 + { + state: "sha\x01\x13\xbc\xfe\x83\x8c\xbd\xdfP\x1f\xd8ڿ<\x9eji8t\xe1\xa5@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xa7VCw", + sum: "bc6245c9959cc33e1c2592e5c9ea9b5d0431246c", + }, + // Data length: 6_565_544_823 + { + state: "sha\x01m;\x16\xa6R\xbe@\xa9nĈ\xf9S\x03\x00B\xc2\xdcv\xcf@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x87VCw", + sum: "8f2d1c0e4271768f35feb918bfe21ea1387a2072", + }, +} + +func safeSum(h hash.Hash) (sum []byte, err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("sum panic: %v", r) + } + }() + + return h.Sum(nil), nil +} + +func TestLargeHashes(t *testing.T) { + for i, test := range largeUnmarshalTests { + + h := New() + if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { + t.Errorf("test %d could not unmarshal: %v", i, err) + continue + } + + sum, err := safeSum(h) + if err != nil { + t.Errorf("test %d could not sum: %v", i, err) + continue + } + + if fmt.Sprintf("%x", sum) != test.sum { + t.Errorf("test %d sum mismatch: expect %s got %x", i, test.sum, sum) + } + } +} + +var bench = New() +var buf = make([]byte, 8192) + +func benchmarkSize(b *testing.B, size int) { + b.SetBytes(int64(size)) + sum := make([]byte, bench.Size()) + for i := 0; i < b.N; i++ { + bench.Reset() + bench.Write(buf[:size]) + bench.Sum(sum[:0]) + } +} + +func BenchmarkHash8Bytes(b *testing.B) { + benchmarkSize(b, 8) +} + +func BenchmarkHash320Bytes(b *testing.B) { + benchmarkSize(b, 320) +} + +func BenchmarkHash1K(b *testing.B) { + benchmarkSize(b, 1024) +} + +func BenchmarkHash8K(b *testing.B) { + benchmarkSize(b, 8192) +} diff --git a/src/crypto/sha1/sha1block.go b/src/crypto/sha1/sha1block.go new file mode 100644 index 0000000..321d343 --- /dev/null +++ b/src/crypto/sha1/sha1block.go @@ -0,0 +1,83 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha1 + +import ( + "math/bits" +) + +const ( + _K0 = 0x5A827999 + _K1 = 0x6ED9EBA1 + _K2 = 0x8F1BBCDC + _K3 = 0xCA62C1D6 +) + +// blockGeneric is a portable, pure Go version of the SHA-1 block step. +// It's used by sha1block_generic.go and tests. +func blockGeneric(dig *digest, p []byte) { + var w [16]uint32 + + h0, h1, h2, h3, h4 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] + for len(p) >= chunk { + // Can interlace the computation of w with the + // rounds below if needed for speed. + for i := 0; i < 16; i++ { + j := i * 4 + w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3]) + } + + a, b, c, d, e := h0, h1, h2, h3, h4 + + // Each of the four 20-iteration rounds + // differs only in the computation of f and + // the choice of K (_K0, _K1, etc). + i := 0 + for ; i < 16; i++ { + f := b&c | (^b)&d + t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + _K0 + a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d + } + for ; i < 20; i++ { + tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] + w[i&0xf] = tmp<<1 | tmp>>(32-1) + + f := b&c | (^b)&d + t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + _K0 + a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d + } + for ; i < 40; i++ { + tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] + w[i&0xf] = tmp<<1 | tmp>>(32-1) + f := b ^ c ^ d + t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + _K1 + a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d + } + for ; i < 60; i++ { + tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] + w[i&0xf] = tmp<<1 | tmp>>(32-1) + f := ((b | c) & d) | (b & c) + t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + _K2 + a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d + } + for ; i < 80; i++ { + tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] + w[i&0xf] = tmp<<1 | tmp>>(32-1) + f := b ^ c ^ d + t := bits.RotateLeft32(a, 5) + f + e + w[i&0xf] + _K3 + a, b, c, d, e = t, a, bits.RotateLeft32(b, 30), c, d + } + + h0 += a + h1 += b + h2 += c + h3 += d + h4 += e + + p = p[chunk:] + } + + dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] = h0, h1, h2, h3, h4 +} diff --git a/src/crypto/sha1/sha1block_386.s b/src/crypto/sha1/sha1block_386.s new file mode 100644 index 0000000..34d023d --- /dev/null +++ b/src/crypto/sha1/sha1block_386.s @@ -0,0 +1,233 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// SHA-1 block routine. See sha1block.go for Go equivalent. +// +// There are 80 rounds of 4 types: +// - rounds 0-15 are type 1 and load data (ROUND1 macro). +// - rounds 16-19 are type 1 and do not load data (ROUND1x macro). +// - rounds 20-39 are type 2 and do not load data (ROUND2 macro). +// - rounds 40-59 are type 3 and do not load data (ROUND3 macro). +// - rounds 60-79 are type 4 and do not load data (ROUND4 macro). +// +// Each round loads or shuffles the data, then computes a per-round +// function of b, c, d, and then mixes the result into and rotates the +// five registers a, b, c, d, e holding the intermediate results. +// +// The register rotation is implemented by rotating the arguments to +// the round macros instead of by explicit move instructions. + +// Like sha1block_amd64.s, but we keep the data and limit pointers on the stack. +// To free up the word pointer (R10 on amd64, DI here), we add it to e during +// LOAD/SHUFFLE instead of during MIX. +// +// The stack holds the intermediate word array - 16 uint32s - at 0(SP) up to 64(SP). +// The saved a, b, c, d, e (R11 through R15 on amd64) are at 64(SP) up to 84(SP). +// The saved limit pointer (DI on amd64) is at 84(SP). +// The saved data pointer (SI on amd64) is at 88(SP). + +#define LOAD(index, e) \ + MOVL 88(SP), SI; \ + MOVL (index*4)(SI), DI; \ + BSWAPL DI; \ + MOVL DI, (index*4)(SP); \ + ADDL DI, e + +#define SHUFFLE(index, e) \ + MOVL (((index)&0xf)*4)(SP), DI; \ + XORL (((index-3)&0xf)*4)(SP), DI; \ + XORL (((index-8)&0xf)*4)(SP), DI; \ + XORL (((index-14)&0xf)*4)(SP), DI; \ + ROLL $1, DI; \ + MOVL DI, (((index)&0xf)*4)(SP); \ + ADDL DI, e + +#define FUNC1(a, b, c, d, e) \ + MOVL d, DI; \ + XORL c, DI; \ + ANDL b, DI; \ + XORL d, DI + +#define FUNC2(a, b, c, d, e) \ + MOVL b, DI; \ + XORL c, DI; \ + XORL d, DI + +#define FUNC3(a, b, c, d, e) \ + MOVL b, SI; \ + ORL c, SI; \ + ANDL d, SI; \ + MOVL b, DI; \ + ANDL c, DI; \ + ORL SI, DI + +#define FUNC4 FUNC2 + +#define MIX(a, b, c, d, e, const) \ + ROLL $30, b; \ + ADDL DI, e; \ + MOVL a, SI; \ + ROLL $5, SI; \ + LEAL const(e)(SI*1), e + +#define ROUND1(a, b, c, d, e, index) \ + LOAD(index, e); \ + FUNC1(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0x5A827999) + +#define ROUND1x(a, b, c, d, e, index) \ + SHUFFLE(index, e); \ + FUNC1(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0x5A827999) + +#define ROUND2(a, b, c, d, e, index) \ + SHUFFLE(index, e); \ + FUNC2(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0x6ED9EBA1) + +#define ROUND3(a, b, c, d, e, index) \ + SHUFFLE(index, e); \ + FUNC3(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0x8F1BBCDC) + +#define ROUND4(a, b, c, d, e, index) \ + SHUFFLE(index, e); \ + FUNC4(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0xCA62C1D6) + +// func block(dig *digest, p []byte) +TEXT ·block(SB),NOSPLIT,$92-16 + MOVL dig+0(FP), BP + MOVL p+4(FP), SI + MOVL p_len+8(FP), DX + SHRL $6, DX + SHLL $6, DX + + LEAL (SI)(DX*1), DI + MOVL (0*4)(BP), AX + MOVL (1*4)(BP), BX + MOVL (2*4)(BP), CX + MOVL (3*4)(BP), DX + MOVL (4*4)(BP), BP + + CMPL SI, DI + JEQ end + + MOVL DI, 84(SP) + +loop: + MOVL SI, 88(SP) + + MOVL AX, 64(SP) + MOVL BX, 68(SP) + MOVL CX, 72(SP) + MOVL DX, 76(SP) + MOVL BP, 80(SP) + + ROUND1(AX, BX, CX, DX, BP, 0) + ROUND1(BP, AX, BX, CX, DX, 1) + ROUND1(DX, BP, AX, BX, CX, 2) + ROUND1(CX, DX, BP, AX, BX, 3) + ROUND1(BX, CX, DX, BP, AX, 4) + ROUND1(AX, BX, CX, DX, BP, 5) + ROUND1(BP, AX, BX, CX, DX, 6) + ROUND1(DX, BP, AX, BX, CX, 7) + ROUND1(CX, DX, BP, AX, BX, 8) + ROUND1(BX, CX, DX, BP, AX, 9) + ROUND1(AX, BX, CX, DX, BP, 10) + ROUND1(BP, AX, BX, CX, DX, 11) + ROUND1(DX, BP, AX, BX, CX, 12) + ROUND1(CX, DX, BP, AX, BX, 13) + ROUND1(BX, CX, DX, BP, AX, 14) + ROUND1(AX, BX, CX, DX, BP, 15) + + ROUND1x(BP, AX, BX, CX, DX, 16) + ROUND1x(DX, BP, AX, BX, CX, 17) + ROUND1x(CX, DX, BP, AX, BX, 18) + ROUND1x(BX, CX, DX, BP, AX, 19) + + ROUND2(AX, BX, CX, DX, BP, 20) + ROUND2(BP, AX, BX, CX, DX, 21) + ROUND2(DX, BP, AX, BX, CX, 22) + ROUND2(CX, DX, BP, AX, BX, 23) + ROUND2(BX, CX, DX, BP, AX, 24) + ROUND2(AX, BX, CX, DX, BP, 25) + ROUND2(BP, AX, BX, CX, DX, 26) + ROUND2(DX, BP, AX, BX, CX, 27) + ROUND2(CX, DX, BP, AX, BX, 28) + ROUND2(BX, CX, DX, BP, AX, 29) + ROUND2(AX, BX, CX, DX, BP, 30) + ROUND2(BP, AX, BX, CX, DX, 31) + ROUND2(DX, BP, AX, BX, CX, 32) + ROUND2(CX, DX, BP, AX, BX, 33) + ROUND2(BX, CX, DX, BP, AX, 34) + ROUND2(AX, BX, CX, DX, BP, 35) + ROUND2(BP, AX, BX, CX, DX, 36) + ROUND2(DX, BP, AX, BX, CX, 37) + ROUND2(CX, DX, BP, AX, BX, 38) + ROUND2(BX, CX, DX, BP, AX, 39) + + ROUND3(AX, BX, CX, DX, BP, 40) + ROUND3(BP, AX, BX, CX, DX, 41) + ROUND3(DX, BP, AX, BX, CX, 42) + ROUND3(CX, DX, BP, AX, BX, 43) + ROUND3(BX, CX, DX, BP, AX, 44) + ROUND3(AX, BX, CX, DX, BP, 45) + ROUND3(BP, AX, BX, CX, DX, 46) + ROUND3(DX, BP, AX, BX, CX, 47) + ROUND3(CX, DX, BP, AX, BX, 48) + ROUND3(BX, CX, DX, BP, AX, 49) + ROUND3(AX, BX, CX, DX, BP, 50) + ROUND3(BP, AX, BX, CX, DX, 51) + ROUND3(DX, BP, AX, BX, CX, 52) + ROUND3(CX, DX, BP, AX, BX, 53) + ROUND3(BX, CX, DX, BP, AX, 54) + ROUND3(AX, BX, CX, DX, BP, 55) + ROUND3(BP, AX, BX, CX, DX, 56) + ROUND3(DX, BP, AX, BX, CX, 57) + ROUND3(CX, DX, BP, AX, BX, 58) + ROUND3(BX, CX, DX, BP, AX, 59) + + ROUND4(AX, BX, CX, DX, BP, 60) + ROUND4(BP, AX, BX, CX, DX, 61) + ROUND4(DX, BP, AX, BX, CX, 62) + ROUND4(CX, DX, BP, AX, BX, 63) + ROUND4(BX, CX, DX, BP, AX, 64) + ROUND4(AX, BX, CX, DX, BP, 65) + ROUND4(BP, AX, BX, CX, DX, 66) + ROUND4(DX, BP, AX, BX, CX, 67) + ROUND4(CX, DX, BP, AX, BX, 68) + ROUND4(BX, CX, DX, BP, AX, 69) + ROUND4(AX, BX, CX, DX, BP, 70) + ROUND4(BP, AX, BX, CX, DX, 71) + ROUND4(DX, BP, AX, BX, CX, 72) + ROUND4(CX, DX, BP, AX, BX, 73) + ROUND4(BX, CX, DX, BP, AX, 74) + ROUND4(AX, BX, CX, DX, BP, 75) + ROUND4(BP, AX, BX, CX, DX, 76) + ROUND4(DX, BP, AX, BX, CX, 77) + ROUND4(CX, DX, BP, AX, BX, 78) + ROUND4(BX, CX, DX, BP, AX, 79) + + ADDL 64(SP), AX + ADDL 68(SP), BX + ADDL 72(SP), CX + ADDL 76(SP), DX + ADDL 80(SP), BP + + MOVL 88(SP), SI + ADDL $64, SI + CMPL SI, 84(SP) + JB loop + +end: + MOVL dig+0(FP), DI + MOVL AX, (0*4)(DI) + MOVL BX, (1*4)(DI) + MOVL CX, (2*4)(DI) + MOVL DX, (3*4)(DI) + MOVL BP, (4*4)(DI) + RET diff --git a/src/crypto/sha1/sha1block_amd64.go b/src/crypto/sha1/sha1block_amd64.go new file mode 100644 index 0000000..039813d --- /dev/null +++ b/src/crypto/sha1/sha1block_amd64.go @@ -0,0 +1,34 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha1 + +import "internal/cpu" + +//go:noescape +func blockAVX2(dig *digest, p []byte) + +//go:noescape +func blockAMD64(dig *digest, p []byte) + +var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI1 && cpu.X86.HasBMI2 + +func block(dig *digest, p []byte) { + if useAVX2 && len(p) >= 256 { + // blockAVX2 calculates sha1 for 2 block per iteration + // it also interleaves precalculation for next block. + // So it may read up-to 192 bytes past end of p + // We may add checks inside blockAVX2, but this will + // just turn it into a copy of blockAMD64, + // so call it directly, instead. + safeLen := len(p) - 128 + if safeLen%128 != 0 { + safeLen -= 64 + } + blockAVX2(dig, p[:safeLen]) + blockAMD64(dig, p[safeLen:]) + } else { + blockAMD64(dig, p) + } +} diff --git a/src/crypto/sha1/sha1block_amd64.s b/src/crypto/sha1/sha1block_amd64.s new file mode 100644 index 0000000..42f03fb --- /dev/null +++ b/src/crypto/sha1/sha1block_amd64.s @@ -0,0 +1,1500 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// AVX2 version by Intel, same algorithm as code in Linux kernel: +// https://github.com/torvalds/linux/blob/master/arch/x86/crypto/sha1_avx2_x86_64_asm.S +// Authors: +// Ilya Albrekht +// Maxim Locktyukhin +// Ronen Zohar +// Chandramouli Narayanan + + +#include "textflag.h" + +// SHA-1 block routine. See sha1block.go for Go equivalent. +// +// There are 80 rounds of 4 types: +// - rounds 0-15 are type 1 and load data (ROUND1 macro). +// - rounds 16-19 are type 1 and do not load data (ROUND1x macro). +// - rounds 20-39 are type 2 and do not load data (ROUND2 macro). +// - rounds 40-59 are type 3 and do not load data (ROUND3 macro). +// - rounds 60-79 are type 4 and do not load data (ROUND4 macro). +// +// Each round loads or shuffles the data, then computes a per-round +// function of b, c, d, and then mixes the result into and rotates the +// five registers a, b, c, d, e holding the intermediate results. +// +// The register rotation is implemented by rotating the arguments to +// the round macros instead of by explicit move instructions. + +#define LOAD(index) \ + MOVL (index*4)(SI), R10; \ + BSWAPL R10; \ + MOVL R10, (index*4)(SP) + +#define SHUFFLE(index) \ + MOVL (((index)&0xf)*4)(SP), R10; \ + XORL (((index-3)&0xf)*4)(SP), R10; \ + XORL (((index-8)&0xf)*4)(SP), R10; \ + XORL (((index-14)&0xf)*4)(SP), R10; \ + ROLL $1, R10; \ + MOVL R10, (((index)&0xf)*4)(SP) + +#define FUNC1(a, b, c, d, e) \ + MOVL d, R9; \ + XORL c, R9; \ + ANDL b, R9; \ + XORL d, R9 + +#define FUNC2(a, b, c, d, e) \ + MOVL b, R9; \ + XORL c, R9; \ + XORL d, R9 + +#define FUNC3(a, b, c, d, e) \ + MOVL b, R8; \ + ORL c, R8; \ + ANDL d, R8; \ + MOVL b, R9; \ + ANDL c, R9; \ + ORL R8, R9 + +#define FUNC4 FUNC2 + +#define MIX(a, b, c, d, e, const) \ + ROLL $30, b; \ + ADDL R9, e; \ + MOVL a, R8; \ + ROLL $5, R8; \ + LEAL const(e)(R10*1), e; \ + ADDL R8, e + +#define ROUND1(a, b, c, d, e, index) \ + LOAD(index); \ + FUNC1(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0x5A827999) + +#define ROUND1x(a, b, c, d, e, index) \ + SHUFFLE(index); \ + FUNC1(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0x5A827999) + +#define ROUND2(a, b, c, d, e, index) \ + SHUFFLE(index); \ + FUNC2(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0x6ED9EBA1) + +#define ROUND3(a, b, c, d, e, index) \ + SHUFFLE(index); \ + FUNC3(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0x8F1BBCDC) + +#define ROUND4(a, b, c, d, e, index) \ + SHUFFLE(index); \ + FUNC4(a, b, c, d, e); \ + MIX(a, b, c, d, e, 0xCA62C1D6) + +TEXT ·blockAMD64(SB),NOSPLIT,$64-32 + MOVQ dig+0(FP), BP + MOVQ p_base+8(FP), SI + MOVQ p_len+16(FP), DX + SHRQ $6, DX + SHLQ $6, DX + + LEAQ (SI)(DX*1), DI + MOVL (0*4)(BP), AX + MOVL (1*4)(BP), BX + MOVL (2*4)(BP), CX + MOVL (3*4)(BP), DX + MOVL (4*4)(BP), BP + + CMPQ SI, DI + JEQ end + +loop: + MOVL AX, R11 + MOVL BX, R12 + MOVL CX, R13 + MOVL DX, R14 + MOVL BP, R15 + + ROUND1(AX, BX, CX, DX, BP, 0) + ROUND1(BP, AX, BX, CX, DX, 1) + ROUND1(DX, BP, AX, BX, CX, 2) + ROUND1(CX, DX, BP, AX, BX, 3) + ROUND1(BX, CX, DX, BP, AX, 4) + ROUND1(AX, BX, CX, DX, BP, 5) + ROUND1(BP, AX, BX, CX, DX, 6) + ROUND1(DX, BP, AX, BX, CX, 7) + ROUND1(CX, DX, BP, AX, BX, 8) + ROUND1(BX, CX, DX, BP, AX, 9) + ROUND1(AX, BX, CX, DX, BP, 10) + ROUND1(BP, AX, BX, CX, DX, 11) + ROUND1(DX, BP, AX, BX, CX, 12) + ROUND1(CX, DX, BP, AX, BX, 13) + ROUND1(BX, CX, DX, BP, AX, 14) + ROUND1(AX, BX, CX, DX, BP, 15) + + ROUND1x(BP, AX, BX, CX, DX, 16) + ROUND1x(DX, BP, AX, BX, CX, 17) + ROUND1x(CX, DX, BP, AX, BX, 18) + ROUND1x(BX, CX, DX, BP, AX, 19) + + ROUND2(AX, BX, CX, DX, BP, 20) + ROUND2(BP, AX, BX, CX, DX, 21) + ROUND2(DX, BP, AX, BX, CX, 22) + ROUND2(CX, DX, BP, AX, BX, 23) + ROUND2(BX, CX, DX, BP, AX, 24) + ROUND2(AX, BX, CX, DX, BP, 25) + ROUND2(BP, AX, BX, CX, DX, 26) + ROUND2(DX, BP, AX, BX, CX, 27) + ROUND2(CX, DX, BP, AX, BX, 28) + ROUND2(BX, CX, DX, BP, AX, 29) + ROUND2(AX, BX, CX, DX, BP, 30) + ROUND2(BP, AX, BX, CX, DX, 31) + ROUND2(DX, BP, AX, BX, CX, 32) + ROUND2(CX, DX, BP, AX, BX, 33) + ROUND2(BX, CX, DX, BP, AX, 34) + ROUND2(AX, BX, CX, DX, BP, 35) + ROUND2(BP, AX, BX, CX, DX, 36) + ROUND2(DX, BP, AX, BX, CX, 37) + ROUND2(CX, DX, BP, AX, BX, 38) + ROUND2(BX, CX, DX, BP, AX, 39) + + ROUND3(AX, BX, CX, DX, BP, 40) + ROUND3(BP, AX, BX, CX, DX, 41) + ROUND3(DX, BP, AX, BX, CX, 42) + ROUND3(CX, DX, BP, AX, BX, 43) + ROUND3(BX, CX, DX, BP, AX, 44) + ROUND3(AX, BX, CX, DX, BP, 45) + ROUND3(BP, AX, BX, CX, DX, 46) + ROUND3(DX, BP, AX, BX, CX, 47) + ROUND3(CX, DX, BP, AX, BX, 48) + ROUND3(BX, CX, DX, BP, AX, 49) + ROUND3(AX, BX, CX, DX, BP, 50) + ROUND3(BP, AX, BX, CX, DX, 51) + ROUND3(DX, BP, AX, BX, CX, 52) + ROUND3(CX, DX, BP, AX, BX, 53) + ROUND3(BX, CX, DX, BP, AX, 54) + ROUND3(AX, BX, CX, DX, BP, 55) + ROUND3(BP, AX, BX, CX, DX, 56) + ROUND3(DX, BP, AX, BX, CX, 57) + ROUND3(CX, DX, BP, AX, BX, 58) + ROUND3(BX, CX, DX, BP, AX, 59) + + ROUND4(AX, BX, CX, DX, BP, 60) + ROUND4(BP, AX, BX, CX, DX, 61) + ROUND4(DX, BP, AX, BX, CX, 62) + ROUND4(CX, DX, BP, AX, BX, 63) + ROUND4(BX, CX, DX, BP, AX, 64) + ROUND4(AX, BX, CX, DX, BP, 65) + ROUND4(BP, AX, BX, CX, DX, 66) + ROUND4(DX, BP, AX, BX, CX, 67) + ROUND4(CX, DX, BP, AX, BX, 68) + ROUND4(BX, CX, DX, BP, AX, 69) + ROUND4(AX, BX, CX, DX, BP, 70) + ROUND4(BP, AX, BX, CX, DX, 71) + ROUND4(DX, BP, AX, BX, CX, 72) + ROUND4(CX, DX, BP, AX, BX, 73) + ROUND4(BX, CX, DX, BP, AX, 74) + ROUND4(AX, BX, CX, DX, BP, 75) + ROUND4(BP, AX, BX, CX, DX, 76) + ROUND4(DX, BP, AX, BX, CX, 77) + ROUND4(CX, DX, BP, AX, BX, 78) + ROUND4(BX, CX, DX, BP, AX, 79) + + ADDL R11, AX + ADDL R12, BX + ADDL R13, CX + ADDL R14, DX + ADDL R15, BP + + ADDQ $64, SI + CMPQ SI, DI + JB loop + +end: + MOVQ dig+0(FP), DI + MOVL AX, (0*4)(DI) + MOVL BX, (1*4)(DI) + MOVL CX, (2*4)(DI) + MOVL DX, (3*4)(DI) + MOVL BP, (4*4)(DI) + RET + + +// This is the implementation using AVX2, BMI1 and BMI2. It is based on: +// "SHA-1 implementation with Intel(R) AVX2 instruction set extensions" +// From http://software.intel.com/en-us/articles +// (look for improving-the-performance-of-the-secure-hash-algorithm-1) +// This implementation is 2x unrolled, and interleaves vector instructions, +// used to precompute W, with scalar computation of current round +// for optimal scheduling. + +// Trivial helper macros. +#define UPDATE_HASH(A,TB,C,D,E) \ + ADDL (R9), A \ + MOVL A, (R9) \ + ADDL 4(R9), TB \ + MOVL TB, 4(R9) \ + ADDL 8(R9), C \ + MOVL C, 8(R9) \ + ADDL 12(R9), D \ + MOVL D, 12(R9) \ + ADDL 16(R9), E \ + MOVL E, 16(R9) + + + +// Helper macros for PRECALC, which does precomputations +#define PRECALC_0(OFFSET) \ + VMOVDQU OFFSET(R10),X0 + +#define PRECALC_1(OFFSET) \ + VINSERTI128 $1, OFFSET(R13), Y0, Y0 + +#define PRECALC_2(YREG) \ + VPSHUFB Y10, Y0, YREG + +#define PRECALC_4(YREG,K_OFFSET) \ + VPADDD K_OFFSET(R8), YREG, Y0 + +#define PRECALC_7(OFFSET) \ + VMOVDQU Y0, (OFFSET*2)(R14) + + +// Message scheduling pre-compute for rounds 0-15 +// R13 is a pointer to even 64-byte block +// R10 is a pointer to odd 64-byte block +// R14 is a pointer to temp buffer +// X0 is used as temp register +// YREG is clobbered as part of computation +// OFFSET chooses 16 byte chunk within a block +// R8 is a pointer to constants block +// K_OFFSET chooses K constants relevant to this round +// X10 holds swap mask +#define PRECALC_00_15(OFFSET,YREG) \ + PRECALC_0(OFFSET) \ + PRECALC_1(OFFSET) \ + PRECALC_2(YREG) \ + PRECALC_4(YREG,0x0) \ + PRECALC_7(OFFSET) + + +// Helper macros for PRECALC_16_31 +#define PRECALC_16(REG_SUB_16,REG_SUB_12,REG_SUB_4,REG) \ + VPALIGNR $8, REG_SUB_16, REG_SUB_12, REG \ // w[i-14] + VPSRLDQ $4, REG_SUB_4, Y0 // w[i-3] + +#define PRECALC_17(REG_SUB_16,REG_SUB_8,REG) \ + VPXOR REG_SUB_8, REG, REG \ + VPXOR REG_SUB_16, Y0, Y0 + +#define PRECALC_18(REG) \ + VPXOR Y0, REG, REG \ + VPSLLDQ $12, REG, Y9 + +#define PRECALC_19(REG) \ + VPSLLD $1, REG, Y0 \ + VPSRLD $31, REG, REG + +#define PRECALC_20(REG) \ + VPOR REG, Y0, Y0 \ + VPSLLD $2, Y9, REG + +#define PRECALC_21(REG) \ + VPSRLD $30, Y9, Y9 \ + VPXOR REG, Y0, Y0 + +#define PRECALC_23(REG,K_OFFSET,OFFSET) \ + VPXOR Y9, Y0, REG \ + VPADDD K_OFFSET(R8), REG, Y0 \ + VMOVDQU Y0, (OFFSET)(R14) + +// Message scheduling pre-compute for rounds 16-31 +// calculating last 32 w[i] values in 8 XMM registers +// pre-calculate K+w[i] values and store to mem +// for later load by ALU add instruction. +// "brute force" vectorization for rounds 16-31 only +// due to w[i]->w[i-3] dependency. +// clobbers 5 input ymm registers REG_SUB* +// uses X0 and X9 as temp registers +// As always, R8 is a pointer to constants block +// and R14 is a pointer to temp buffer +#define PRECALC_16_31(REG,REG_SUB_4,REG_SUB_8,REG_SUB_12,REG_SUB_16,K_OFFSET,OFFSET) \ + PRECALC_16(REG_SUB_16,REG_SUB_12,REG_SUB_4,REG) \ + PRECALC_17(REG_SUB_16,REG_SUB_8,REG) \ + PRECALC_18(REG) \ + PRECALC_19(REG) \ + PRECALC_20(REG) \ + PRECALC_21(REG) \ + PRECALC_23(REG,K_OFFSET,OFFSET) + + +// Helper macros for PRECALC_32_79 +#define PRECALC_32(REG_SUB_8,REG_SUB_4) \ + VPALIGNR $8, REG_SUB_8, REG_SUB_4, Y0 + +#define PRECALC_33(REG_SUB_28,REG) \ + VPXOR REG_SUB_28, REG, REG + +#define PRECALC_34(REG_SUB_16) \ + VPXOR REG_SUB_16, Y0, Y0 + +#define PRECALC_35(REG) \ + VPXOR Y0, REG, REG + +#define PRECALC_36(REG) \ + VPSLLD $2, REG, Y0 + +#define PRECALC_37(REG) \ + VPSRLD $30, REG, REG \ + VPOR REG, Y0, REG + +#define PRECALC_39(REG,K_OFFSET,OFFSET) \ + VPADDD K_OFFSET(R8), REG, Y0 \ + VMOVDQU Y0, (OFFSET)(R14) + +// Message scheduling pre-compute for rounds 32-79 +// In SHA-1 specification we have: +// w[i] = (w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) rol 1 +// Which is the same as: +// w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2 +// This allows for more efficient vectorization, +// since w[i]->w[i-3] dependency is broken +#define PRECALC_32_79(REG,REG_SUB_4,REG_SUB_8,REG_SUB_16,REG_SUB_28,K_OFFSET,OFFSET) \ + PRECALC_32(REG_SUB_8,REG_SUB_4) \ + PRECALC_33(REG_SUB_28,REG) \ + PRECALC_34(REG_SUB_16) \ + PRECALC_35(REG) \ + PRECALC_36(REG) \ + PRECALC_37(REG) \ + PRECALC_39(REG,K_OFFSET,OFFSET) + +#define PRECALC \ + PRECALC_00_15(0,Y15) \ + PRECALC_00_15(0x10,Y14) \ + PRECALC_00_15(0x20,Y13) \ + PRECALC_00_15(0x30,Y12) \ + PRECALC_16_31(Y8,Y12,Y13,Y14,Y15,0,0x80) \ + PRECALC_16_31(Y7,Y8,Y12,Y13,Y14,0x20,0xa0) \ + PRECALC_16_31(Y5,Y7,Y8,Y12,Y13,0x20,0xc0) \ + PRECALC_16_31(Y3,Y5,Y7,Y8,Y12,0x20,0xe0) \ + PRECALC_32_79(Y15,Y3,Y5,Y8,Y14,0x20,0x100) \ + PRECALC_32_79(Y14,Y15,Y3,Y7,Y13,0x20,0x120) \ + PRECALC_32_79(Y13,Y14,Y15,Y5,Y12,0x40,0x140) \ + PRECALC_32_79(Y12,Y13,Y14,Y3,Y8,0x40,0x160) \ + PRECALC_32_79(Y8,Y12,Y13,Y15,Y7,0x40,0x180) \ + PRECALC_32_79(Y7,Y8,Y12,Y14,Y5,0x40,0x1a0) \ + PRECALC_32_79(Y5,Y7,Y8,Y13,Y3,0x40,0x1c0) \ + PRECALC_32_79(Y3,Y5,Y7,Y12,Y15,0x60,0x1e0) \ + PRECALC_32_79(Y15,Y3,Y5,Y8,Y14,0x60,0x200) \ + PRECALC_32_79(Y14,Y15,Y3,Y7,Y13,0x60,0x220) \ + PRECALC_32_79(Y13,Y14,Y15,Y5,Y12,0x60,0x240) \ + PRECALC_32_79(Y12,Y13,Y14,Y3,Y8,0x60,0x260) + +// Macros calculating individual rounds have general form +// CALC_ROUND_PRE + PRECALC_ROUND + CALC_ROUND_POST +// CALC_ROUND_{PRE,POST} macros follow + +#define CALC_F1_PRE(OFFSET,REG_A,REG_B,REG_C,REG_E) \ + ADDL OFFSET(R15),REG_E \ + ANDNL REG_C,REG_A,BP \ + LEAL (REG_E)(REG_B*1), REG_E \ // Add F from the previous round + RORXL $0x1b, REG_A, R12 \ + RORXL $2, REG_A, REG_B // for next round + +// Calculate F for the next round +#define CALC_F1_POST(REG_A,REG_B,REG_E) \ + ANDL REG_B,REG_A \ // b&c + XORL BP, REG_A \ // F1 = (b&c) ^ (~b&d) + LEAL (REG_E)(R12*1), REG_E // E += A >>> 5 + + +// Registers are cyclically rotated DX -> AX -> DI -> SI -> BX -> CX +#define CALC_0 \ + MOVL SI, BX \ // Precalculating first round + RORXL $2, SI, SI \ + ANDNL AX, BX, BP \ + ANDL DI, BX \ + XORL BP, BX \ + CALC_F1_PRE(0x0,CX,BX,DI,DX) \ + PRECALC_0(0x80) \ + CALC_F1_POST(CX,SI,DX) + +#define CALC_1 \ + CALC_F1_PRE(0x4,DX,CX,SI,AX) \ + PRECALC_1(0x80) \ + CALC_F1_POST(DX,BX,AX) + +#define CALC_2 \ + CALC_F1_PRE(0x8,AX,DX,BX,DI) \ + PRECALC_2(Y15) \ + CALC_F1_POST(AX,CX,DI) + +#define CALC_3 \ + CALC_F1_PRE(0xc,DI,AX,CX,SI) \ + CALC_F1_POST(DI,DX,SI) + +#define CALC_4 \ + CALC_F1_PRE(0x20,SI,DI,DX,BX) \ + PRECALC_4(Y15,0x0) \ + CALC_F1_POST(SI,AX,BX) + +#define CALC_5 \ + CALC_F1_PRE(0x24,BX,SI,AX,CX) \ + CALC_F1_POST(BX,DI,CX) + +#define CALC_6 \ + CALC_F1_PRE(0x28,CX,BX,DI,DX) \ + CALC_F1_POST(CX,SI,DX) + +#define CALC_7 \ + CALC_F1_PRE(0x2c,DX,CX,SI,AX) \ + PRECALC_7(0x0) \ + CALC_F1_POST(DX,BX,AX) + +#define CALC_8 \ + CALC_F1_PRE(0x40,AX,DX,BX,DI) \ + PRECALC_0(0x90) \ + CALC_F1_POST(AX,CX,DI) + +#define CALC_9 \ + CALC_F1_PRE(0x44,DI,AX,CX,SI) \ + PRECALC_1(0x90) \ + CALC_F1_POST(DI,DX,SI) + +#define CALC_10 \ + CALC_F1_PRE(0x48,SI,DI,DX,BX) \ + PRECALC_2(Y14) \ + CALC_F1_POST(SI,AX,BX) + +#define CALC_11 \ + CALC_F1_PRE(0x4c,BX,SI,AX,CX) \ + CALC_F1_POST(BX,DI,CX) + +#define CALC_12 \ + CALC_F1_PRE(0x60,CX,BX,DI,DX) \ + PRECALC_4(Y14,0x0) \ + CALC_F1_POST(CX,SI,DX) + +#define CALC_13 \ + CALC_F1_PRE(0x64,DX,CX,SI,AX) \ + CALC_F1_POST(DX,BX,AX) + +#define CALC_14 \ + CALC_F1_PRE(0x68,AX,DX,BX,DI) \ + CALC_F1_POST(AX,CX,DI) + +#define CALC_15 \ + CALC_F1_PRE(0x6c,DI,AX,CX,SI) \ + PRECALC_7(0x10) \ + CALC_F1_POST(DI,DX,SI) + +#define CALC_16 \ + CALC_F1_PRE(0x80,SI,DI,DX,BX) \ + PRECALC_0(0xa0) \ + CALC_F1_POST(SI,AX,BX) + +#define CALC_17 \ + CALC_F1_PRE(0x84,BX,SI,AX,CX) \ + PRECALC_1(0xa0) \ + CALC_F1_POST(BX,DI,CX) + +#define CALC_18 \ + CALC_F1_PRE(0x88,CX,BX,DI,DX) \ + PRECALC_2(Y13) \ + CALC_F1_POST(CX,SI,DX) + + +#define CALC_F2_PRE(OFFSET,REG_A,REG_B,REG_E) \ + ADDL OFFSET(R15),REG_E \ + LEAL (REG_E)(REG_B*1), REG_E \ // Add F from the previous round + RORXL $0x1b, REG_A, R12 \ + RORXL $2, REG_A, REG_B // for next round + +#define CALC_F2_POST(REG_A,REG_B,REG_C,REG_E) \ + XORL REG_B, REG_A \ + ADDL R12, REG_E \ + XORL REG_C, REG_A + +#define CALC_19 \ + CALC_F2_PRE(0x8c,DX,CX,AX) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_20 \ + CALC_F2_PRE(0xa0,AX,DX,DI) \ + PRECALC_4(Y13,0x0) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_21 \ + CALC_F2_PRE(0xa4,DI,AX,SI) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_22 \ + CALC_F2_PRE(0xa8,SI,DI,BX) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_23 \ + CALC_F2_PRE(0xac,BX,SI,CX) \ + PRECALC_7(0x20) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_24 \ + CALC_F2_PRE(0xc0,CX,BX,DX) \ + PRECALC_0(0xb0) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_25 \ + CALC_F2_PRE(0xc4,DX,CX,AX) \ + PRECALC_1(0xb0) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_26 \ + CALC_F2_PRE(0xc8,AX,DX,DI) \ + PRECALC_2(Y12) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_27 \ + CALC_F2_PRE(0xcc,DI,AX,SI) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_28 \ + CALC_F2_PRE(0xe0,SI,DI,BX) \ + PRECALC_4(Y12,0x0) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_29 \ + CALC_F2_PRE(0xe4,BX,SI,CX) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_30 \ + CALC_F2_PRE(0xe8,CX,BX,DX) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_31 \ + CALC_F2_PRE(0xec,DX,CX,AX) \ + PRECALC_7(0x30) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_32 \ + CALC_F2_PRE(0x100,AX,DX,DI) \ + PRECALC_16(Y15,Y14,Y12,Y8) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_33 \ + CALC_F2_PRE(0x104,DI,AX,SI) \ + PRECALC_17(Y15,Y13,Y8) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_34 \ + CALC_F2_PRE(0x108,SI,DI,BX) \ + PRECALC_18(Y8) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_35 \ + CALC_F2_PRE(0x10c,BX,SI,CX) \ + PRECALC_19(Y8) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_36 \ + CALC_F2_PRE(0x120,CX,BX,DX) \ + PRECALC_20(Y8) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_37 \ + CALC_F2_PRE(0x124,DX,CX,AX) \ + PRECALC_21(Y8) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_38 \ + CALC_F2_PRE(0x128,AX,DX,DI) \ + CALC_F2_POST(AX,CX,BX,DI) + + +#define CALC_F3_PRE(OFFSET,REG_E) \ + ADDL OFFSET(R15),REG_E + +#define CALC_F3_POST(REG_A,REG_B,REG_C,REG_E,REG_TB) \ + LEAL (REG_E)(REG_TB*1), REG_E \ // Add F from the previous round + MOVL REG_B, BP \ + ORL REG_A, BP \ + RORXL $0x1b, REG_A, R12 \ + RORXL $2, REG_A, REG_TB \ + ANDL REG_C, BP \ // Calculate F for the next round + ANDL REG_B, REG_A \ + ORL BP, REG_A \ + ADDL R12, REG_E + +#define CALC_39 \ + CALC_F3_PRE(0x12c,SI) \ + PRECALC_23(Y8,0x0,0x80) \ + CALC_F3_POST(DI,DX,CX,SI,AX) + +#define CALC_40 \ + CALC_F3_PRE(0x140,BX) \ + PRECALC_16(Y14,Y13,Y8,Y7) \ + CALC_F3_POST(SI,AX,DX,BX,DI) + +#define CALC_41 \ + CALC_F3_PRE(0x144,CX) \ + PRECALC_17(Y14,Y12,Y7) \ + CALC_F3_POST(BX,DI,AX,CX,SI) + +#define CALC_42 \ + CALC_F3_PRE(0x148,DX) \ + PRECALC_18(Y7) \ + CALC_F3_POST(CX,SI,DI,DX,BX) + +#define CALC_43 \ + CALC_F3_PRE(0x14c,AX) \ + PRECALC_19(Y7) \ + CALC_F3_POST(DX,BX,SI,AX,CX) + +#define CALC_44 \ + CALC_F3_PRE(0x160,DI) \ + PRECALC_20(Y7) \ + CALC_F3_POST(AX,CX,BX,DI,DX) + +#define CALC_45 \ + CALC_F3_PRE(0x164,SI) \ + PRECALC_21(Y7) \ + CALC_F3_POST(DI,DX,CX,SI,AX) + +#define CALC_46 \ + CALC_F3_PRE(0x168,BX) \ + CALC_F3_POST(SI,AX,DX,BX,DI) + +#define CALC_47 \ + CALC_F3_PRE(0x16c,CX) \ + VPXOR Y9, Y0, Y7 \ + VPADDD 0x20(R8), Y7, Y0 \ + VMOVDQU Y0, 0xa0(R14) \ + CALC_F3_POST(BX,DI,AX,CX,SI) + +#define CALC_48 \ + CALC_F3_PRE(0x180,DX) \ + PRECALC_16(Y13,Y12,Y7,Y5) \ + CALC_F3_POST(CX,SI,DI,DX,BX) + +#define CALC_49 \ + CALC_F3_PRE(0x184,AX) \ + PRECALC_17(Y13,Y8,Y5) \ + CALC_F3_POST(DX,BX,SI,AX,CX) + +#define CALC_50 \ + CALC_F3_PRE(0x188,DI) \ + PRECALC_18(Y5) \ + CALC_F3_POST(AX,CX,BX,DI,DX) + +#define CALC_51 \ + CALC_F3_PRE(0x18c,SI) \ + PRECALC_19(Y5) \ + CALC_F3_POST(DI,DX,CX,SI,AX) + +#define CALC_52 \ + CALC_F3_PRE(0x1a0,BX) \ + PRECALC_20(Y5) \ + CALC_F3_POST(SI,AX,DX,BX,DI) + +#define CALC_53 \ + CALC_F3_PRE(0x1a4,CX) \ + PRECALC_21(Y5) \ + CALC_F3_POST(BX,DI,AX,CX,SI) + +#define CALC_54 \ + CALC_F3_PRE(0x1a8,DX) \ + CALC_F3_POST(CX,SI,DI,DX,BX) + +#define CALC_55 \ + CALC_F3_PRE(0x1ac,AX) \ + PRECALC_23(Y5,0x20,0xc0) \ + CALC_F3_POST(DX,BX,SI,AX,CX) + +#define CALC_56 \ + CALC_F3_PRE(0x1c0,DI) \ + PRECALC_16(Y12,Y8,Y5,Y3) \ + CALC_F3_POST(AX,CX,BX,DI,DX) + +#define CALC_57 \ + CALC_F3_PRE(0x1c4,SI) \ + PRECALC_17(Y12,Y7,Y3) \ + CALC_F3_POST(DI,DX,CX,SI,AX) + +#define CALC_58 \ + CALC_F3_PRE(0x1c8,BX) \ + PRECALC_18(Y3) \ + CALC_F3_POST(SI,AX,DX,BX,DI) + +#define CALC_59 \ + CALC_F2_PRE(0x1cc,BX,SI,CX) \ + PRECALC_19(Y3) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_60 \ + CALC_F2_PRE(0x1e0,CX,BX,DX) \ + PRECALC_20(Y3) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_61 \ + CALC_F2_PRE(0x1e4,DX,CX,AX) \ + PRECALC_21(Y3) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_62 \ + CALC_F2_PRE(0x1e8,AX,DX,DI) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_63 \ + CALC_F2_PRE(0x1ec,DI,AX,SI) \ + PRECALC_23(Y3,0x20,0xe0) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_64 \ + CALC_F2_PRE(0x200,SI,DI,BX) \ + PRECALC_32(Y5,Y3) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_65 \ + CALC_F2_PRE(0x204,BX,SI,CX) \ + PRECALC_33(Y14,Y15) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_66 \ + CALC_F2_PRE(0x208,CX,BX,DX) \ + PRECALC_34(Y8) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_67 \ + CALC_F2_PRE(0x20c,DX,CX,AX) \ + PRECALC_35(Y15) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_68 \ + CALC_F2_PRE(0x220,AX,DX,DI) \ + PRECALC_36(Y15) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_69 \ + CALC_F2_PRE(0x224,DI,AX,SI) \ + PRECALC_37(Y15) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_70 \ + CALC_F2_PRE(0x228,SI,DI,BX) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_71 \ + CALC_F2_PRE(0x22c,BX,SI,CX) \ + PRECALC_39(Y15,0x20,0x100) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_72 \ + CALC_F2_PRE(0x240,CX,BX,DX) \ + PRECALC_32(Y3,Y15) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_73 \ + CALC_F2_PRE(0x244,DX,CX,AX) \ + PRECALC_33(Y13,Y14) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_74 \ + CALC_F2_PRE(0x248,AX,DX,DI) \ + PRECALC_34(Y7) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_75 \ + CALC_F2_PRE(0x24c,DI,AX,SI) \ + PRECALC_35(Y14) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_76 \ + CALC_F2_PRE(0x260,SI,DI,BX) \ + PRECALC_36(Y14) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_77 \ + CALC_F2_PRE(0x264,BX,SI,CX) \ + PRECALC_37(Y14) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_78 \ + CALC_F2_PRE(0x268,CX,BX,DX) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_79 \ + ADDL 0x26c(R15), AX \ + LEAL (AX)(CX*1), AX \ + RORXL $0x1b, DX, R12 \ + PRECALC_39(Y14,0x20,0x120) \ + ADDL R12, AX + +// Similar to CALC_0 +#define CALC_80 \ + MOVL CX, DX \ + RORXL $2, CX, CX \ + ANDNL SI, DX, BP \ + ANDL BX, DX \ + XORL BP, DX \ + CALC_F1_PRE(0x10,AX,DX,BX,DI) \ + PRECALC_32(Y15,Y14) \ + CALC_F1_POST(AX,CX,DI) + +#define CALC_81 \ + CALC_F1_PRE(0x14,DI,AX,CX,SI) \ + PRECALC_33(Y12,Y13) \ + CALC_F1_POST(DI,DX,SI) + +#define CALC_82 \ + CALC_F1_PRE(0x18,SI,DI,DX,BX) \ + PRECALC_34(Y5) \ + CALC_F1_POST(SI,AX,BX) + +#define CALC_83 \ + CALC_F1_PRE(0x1c,BX,SI,AX,CX) \ + PRECALC_35(Y13) \ + CALC_F1_POST(BX,DI,CX) + +#define CALC_84 \ + CALC_F1_PRE(0x30,CX,BX,DI,DX) \ + PRECALC_36(Y13) \ + CALC_F1_POST(CX,SI,DX) + +#define CALC_85 \ + CALC_F1_PRE(0x34,DX,CX,SI,AX) \ + PRECALC_37(Y13) \ + CALC_F1_POST(DX,BX,AX) + +#define CALC_86 \ + CALC_F1_PRE(0x38,AX,DX,BX,DI) \ + CALC_F1_POST(AX,CX,DI) + +#define CALC_87 \ + CALC_F1_PRE(0x3c,DI,AX,CX,SI) \ + PRECALC_39(Y13,0x40,0x140) \ + CALC_F1_POST(DI,DX,SI) + +#define CALC_88 \ + CALC_F1_PRE(0x50,SI,DI,DX,BX) \ + PRECALC_32(Y14,Y13) \ + CALC_F1_POST(SI,AX,BX) + +#define CALC_89 \ + CALC_F1_PRE(0x54,BX,SI,AX,CX) \ + PRECALC_33(Y8,Y12) \ + CALC_F1_POST(BX,DI,CX) + +#define CALC_90 \ + CALC_F1_PRE(0x58,CX,BX,DI,DX) \ + PRECALC_34(Y3) \ + CALC_F1_POST(CX,SI,DX) + +#define CALC_91 \ + CALC_F1_PRE(0x5c,DX,CX,SI,AX) \ + PRECALC_35(Y12) \ + CALC_F1_POST(DX,BX,AX) + +#define CALC_92 \ + CALC_F1_PRE(0x70,AX,DX,BX,DI) \ + PRECALC_36(Y12) \ + CALC_F1_POST(AX,CX,DI) + +#define CALC_93 \ + CALC_F1_PRE(0x74,DI,AX,CX,SI) \ + PRECALC_37(Y12) \ + CALC_F1_POST(DI,DX,SI) + +#define CALC_94 \ + CALC_F1_PRE(0x78,SI,DI,DX,BX) \ + CALC_F1_POST(SI,AX,BX) + +#define CALC_95 \ + CALC_F1_PRE(0x7c,BX,SI,AX,CX) \ + PRECALC_39(Y12,0x40,0x160) \ + CALC_F1_POST(BX,DI,CX) + +#define CALC_96 \ + CALC_F1_PRE(0x90,CX,BX,DI,DX) \ + PRECALC_32(Y13,Y12) \ + CALC_F1_POST(CX,SI,DX) + +#define CALC_97 \ + CALC_F1_PRE(0x94,DX,CX,SI,AX) \ + PRECALC_33(Y7,Y8) \ + CALC_F1_POST(DX,BX,AX) + +#define CALC_98 \ + CALC_F1_PRE(0x98,AX,DX,BX,DI) \ + PRECALC_34(Y15) \ + CALC_F1_POST(AX,CX,DI) + +#define CALC_99 \ + CALC_F2_PRE(0x9c,DI,AX,SI) \ + PRECALC_35(Y8) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_100 \ + CALC_F2_PRE(0xb0,SI,DI,BX) \ + PRECALC_36(Y8) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_101 \ + CALC_F2_PRE(0xb4,BX,SI,CX) \ + PRECALC_37(Y8) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_102 \ + CALC_F2_PRE(0xb8,CX,BX,DX) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_103 \ + CALC_F2_PRE(0xbc,DX,CX,AX) \ + PRECALC_39(Y8,0x40,0x180) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_104 \ + CALC_F2_PRE(0xd0,AX,DX,DI) \ + PRECALC_32(Y12,Y8) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_105 \ + CALC_F2_PRE(0xd4,DI,AX,SI) \ + PRECALC_33(Y5,Y7) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_106 \ + CALC_F2_PRE(0xd8,SI,DI,BX) \ + PRECALC_34(Y14) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_107 \ + CALC_F2_PRE(0xdc,BX,SI,CX) \ + PRECALC_35(Y7) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_108 \ + CALC_F2_PRE(0xf0,CX,BX,DX) \ + PRECALC_36(Y7) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_109 \ + CALC_F2_PRE(0xf4,DX,CX,AX) \ + PRECALC_37(Y7) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_110 \ + CALC_F2_PRE(0xf8,AX,DX,DI) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_111 \ + CALC_F2_PRE(0xfc,DI,AX,SI) \ + PRECALC_39(Y7,0x40,0x1a0) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_112 \ + CALC_F2_PRE(0x110,SI,DI,BX) \ + PRECALC_32(Y8,Y7) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_113 \ + CALC_F2_PRE(0x114,BX,SI,CX) \ + PRECALC_33(Y3,Y5) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_114 \ + CALC_F2_PRE(0x118,CX,BX,DX) \ + PRECALC_34(Y13) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_115 \ + CALC_F2_PRE(0x11c,DX,CX,AX) \ + PRECALC_35(Y5) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_116 \ + CALC_F2_PRE(0x130,AX,DX,DI) \ + PRECALC_36(Y5) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_117 \ + CALC_F2_PRE(0x134,DI,AX,SI) \ + PRECALC_37(Y5) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_118 \ + CALC_F2_PRE(0x138,SI,DI,BX) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_119 \ + CALC_F3_PRE(0x13c,CX) \ + PRECALC_39(Y5,0x40,0x1c0) \ + CALC_F3_POST(BX,DI,AX,CX,SI) + +#define CALC_120 \ + CALC_F3_PRE(0x150,DX) \ + PRECALC_32(Y7,Y5) \ + CALC_F3_POST(CX,SI,DI,DX,BX) + +#define CALC_121 \ + CALC_F3_PRE(0x154,AX) \ + PRECALC_33(Y15,Y3) \ + CALC_F3_POST(DX,BX,SI,AX,CX) + +#define CALC_122 \ + CALC_F3_PRE(0x158,DI) \ + PRECALC_34(Y12) \ + CALC_F3_POST(AX,CX,BX,DI,DX) + +#define CALC_123 \ + CALC_F3_PRE(0x15c,SI) \ + PRECALC_35(Y3) \ + CALC_F3_POST(DI,DX,CX,SI,AX) + +#define CALC_124 \ + CALC_F3_PRE(0x170,BX) \ + PRECALC_36(Y3) \ + CALC_F3_POST(SI,AX,DX,BX,DI) + +#define CALC_125 \ + CALC_F3_PRE(0x174,CX) \ + PRECALC_37(Y3) \ + CALC_F3_POST(BX,DI,AX,CX,SI) + +#define CALC_126 \ + CALC_F3_PRE(0x178,DX) \ + CALC_F3_POST(CX,SI,DI,DX,BX) + +#define CALC_127 \ + CALC_F3_PRE(0x17c,AX) \ + PRECALC_39(Y3,0x60,0x1e0) \ + CALC_F3_POST(DX,BX,SI,AX,CX) + +#define CALC_128 \ + CALC_F3_PRE(0x190,DI) \ + PRECALC_32(Y5,Y3) \ + CALC_F3_POST(AX,CX,BX,DI,DX) + +#define CALC_129 \ + CALC_F3_PRE(0x194,SI) \ + PRECALC_33(Y14,Y15) \ + CALC_F3_POST(DI,DX,CX,SI,AX) + +#define CALC_130 \ + CALC_F3_PRE(0x198,BX) \ + PRECALC_34(Y8) \ + CALC_F3_POST(SI,AX,DX,BX,DI) + +#define CALC_131 \ + CALC_F3_PRE(0x19c,CX) \ + PRECALC_35(Y15) \ + CALC_F3_POST(BX,DI,AX,CX,SI) + +#define CALC_132 \ + CALC_F3_PRE(0x1b0,DX) \ + PRECALC_36(Y15) \ + CALC_F3_POST(CX,SI,DI,DX,BX) + +#define CALC_133 \ + CALC_F3_PRE(0x1b4,AX) \ + PRECALC_37(Y15) \ + CALC_F3_POST(DX,BX,SI,AX,CX) + +#define CALC_134 \ + CALC_F3_PRE(0x1b8,DI) \ + CALC_F3_POST(AX,CX,BX,DI,DX) + +#define CALC_135 \ + CALC_F3_PRE(0x1bc,SI) \ + PRECALC_39(Y15,0x60,0x200) \ + CALC_F3_POST(DI,DX,CX,SI,AX) + +#define CALC_136 \ + CALC_F3_PRE(0x1d0,BX) \ + PRECALC_32(Y3,Y15) \ + CALC_F3_POST(SI,AX,DX,BX,DI) + +#define CALC_137 \ + CALC_F3_PRE(0x1d4,CX) \ + PRECALC_33(Y13,Y14) \ + CALC_F3_POST(BX,DI,AX,CX,SI) + +#define CALC_138 \ + CALC_F3_PRE(0x1d8,DX) \ + PRECALC_34(Y7) \ + CALC_F3_POST(CX,SI,DI,DX,BX) + +#define CALC_139 \ + CALC_F2_PRE(0x1dc,DX,CX,AX) \ + PRECALC_35(Y14) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_140 \ + CALC_F2_PRE(0x1f0,AX,DX,DI) \ + PRECALC_36(Y14) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_141 \ + CALC_F2_PRE(0x1f4,DI,AX,SI) \ + PRECALC_37(Y14) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_142 \ + CALC_F2_PRE(0x1f8,SI,DI,BX) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_143 \ + CALC_F2_PRE(0x1fc,BX,SI,CX) \ + PRECALC_39(Y14,0x60,0x220) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_144 \ + CALC_F2_PRE(0x210,CX,BX,DX) \ + PRECALC_32(Y15,Y14) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_145 \ + CALC_F2_PRE(0x214,DX,CX,AX) \ + PRECALC_33(Y12,Y13) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_146 \ + CALC_F2_PRE(0x218,AX,DX,DI) \ + PRECALC_34(Y5) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_147 \ + CALC_F2_PRE(0x21c,DI,AX,SI) \ + PRECALC_35(Y13) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_148 \ + CALC_F2_PRE(0x230,SI,DI,BX) \ + PRECALC_36(Y13) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_149 \ + CALC_F2_PRE(0x234,BX,SI,CX) \ + PRECALC_37(Y13) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_150 \ + CALC_F2_PRE(0x238,CX,BX,DX) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_151 \ + CALC_F2_PRE(0x23c,DX,CX,AX) \ + PRECALC_39(Y13,0x60,0x240) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_152 \ + CALC_F2_PRE(0x250,AX,DX,DI) \ + PRECALC_32(Y14,Y13) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_153 \ + CALC_F2_PRE(0x254,DI,AX,SI) \ + PRECALC_33(Y8,Y12) \ + CALC_F2_POST(DI,DX,CX,SI) + +#define CALC_154 \ + CALC_F2_PRE(0x258,SI,DI,BX) \ + PRECALC_34(Y3) \ + CALC_F2_POST(SI,AX,DX,BX) + +#define CALC_155 \ + CALC_F2_PRE(0x25c,BX,SI,CX) \ + PRECALC_35(Y12) \ + CALC_F2_POST(BX,DI,AX,CX) + +#define CALC_156 \ + CALC_F2_PRE(0x270,CX,BX,DX) \ + PRECALC_36(Y12) \ + CALC_F2_POST(CX,SI,DI,DX) + +#define CALC_157 \ + CALC_F2_PRE(0x274,DX,CX,AX) \ + PRECALC_37(Y12) \ + CALC_F2_POST(DX,BX,SI,AX) + +#define CALC_158 \ + CALC_F2_PRE(0x278,AX,DX,DI) \ + CALC_F2_POST(AX,CX,BX,DI) + +#define CALC_159 \ + ADDL 0x27c(R15),SI \ + LEAL (SI)(AX*1), SI \ + RORXL $0x1b, DI, R12 \ + PRECALC_39(Y12,0x60,0x260) \ + ADDL R12, SI + + + +#define CALC \ + MOVL (R9), CX \ + MOVL 4(R9), SI \ + MOVL 8(R9), DI \ + MOVL 12(R9), AX \ + MOVL 16(R9), DX \ + MOVQ SP, R14 \ + LEAQ (2*4*80+32)(SP), R15 \ + PRECALC \ // Precalc WK for first 2 blocks + XCHGQ R15, R14 \ +loop: \ // this loops is unrolled + CMPQ R10, R8 \ // we use R8 value (set below) as a signal of a last block + JNE begin \ + VZEROUPPER \ + RET \ +begin: \ + CALC_0 \ + CALC_1 \ + CALC_2 \ + CALC_3 \ + CALC_4 \ + CALC_5 \ + CALC_6 \ + CALC_7 \ + CALC_8 \ + CALC_9 \ + CALC_10 \ + CALC_11 \ + CALC_12 \ + CALC_13 \ + CALC_14 \ + CALC_15 \ + CALC_16 \ + CALC_17 \ + CALC_18 \ + CALC_19 \ + CALC_20 \ + CALC_21 \ + CALC_22 \ + CALC_23 \ + CALC_24 \ + CALC_25 \ + CALC_26 \ + CALC_27 \ + CALC_28 \ + CALC_29 \ + CALC_30 \ + CALC_31 \ + CALC_32 \ + CALC_33 \ + CALC_34 \ + CALC_35 \ + CALC_36 \ + CALC_37 \ + CALC_38 \ + CALC_39 \ + CALC_40 \ + CALC_41 \ + CALC_42 \ + CALC_43 \ + CALC_44 \ + CALC_45 \ + CALC_46 \ + CALC_47 \ + CALC_48 \ + CALC_49 \ + CALC_50 \ + CALC_51 \ + CALC_52 \ + CALC_53 \ + CALC_54 \ + CALC_55 \ + CALC_56 \ + CALC_57 \ + CALC_58 \ + CALC_59 \ + ADDQ $128, R10 \ // move to next even-64-byte block + CMPQ R10, R11 \ // is current block the last one? + CMOVQCC R8, R10 \ // signal the last iteration smartly + CALC_60 \ + CALC_61 \ + CALC_62 \ + CALC_63 \ + CALC_64 \ + CALC_65 \ + CALC_66 \ + CALC_67 \ + CALC_68 \ + CALC_69 \ + CALC_70 \ + CALC_71 \ + CALC_72 \ + CALC_73 \ + CALC_74 \ + CALC_75 \ + CALC_76 \ + CALC_77 \ + CALC_78 \ + CALC_79 \ + UPDATE_HASH(AX,DX,BX,SI,DI) \ + CMPQ R10, R8 \ // is current block the last one? + JE loop\ + MOVL DX, CX \ + CALC_80 \ + CALC_81 \ + CALC_82 \ + CALC_83 \ + CALC_84 \ + CALC_85 \ + CALC_86 \ + CALC_87 \ + CALC_88 \ + CALC_89 \ + CALC_90 \ + CALC_91 \ + CALC_92 \ + CALC_93 \ + CALC_94 \ + CALC_95 \ + CALC_96 \ + CALC_97 \ + CALC_98 \ + CALC_99 \ + CALC_100 \ + CALC_101 \ + CALC_102 \ + CALC_103 \ + CALC_104 \ + CALC_105 \ + CALC_106 \ + CALC_107 \ + CALC_108 \ + CALC_109 \ + CALC_110 \ + CALC_111 \ + CALC_112 \ + CALC_113 \ + CALC_114 \ + CALC_115 \ + CALC_116 \ + CALC_117 \ + CALC_118 \ + CALC_119 \ + CALC_120 \ + CALC_121 \ + CALC_122 \ + CALC_123 \ + CALC_124 \ + CALC_125 \ + CALC_126 \ + CALC_127 \ + CALC_128 \ + CALC_129 \ + CALC_130 \ + CALC_131 \ + CALC_132 \ + CALC_133 \ + CALC_134 \ + CALC_135 \ + CALC_136 \ + CALC_137 \ + CALC_138 \ + CALC_139 \ + ADDQ $128, R13 \ //move to next even-64-byte block + CMPQ R13, R11 \ //is current block the last one? + CMOVQCC R8, R10 \ + CALC_140 \ + CALC_141 \ + CALC_142 \ + CALC_143 \ + CALC_144 \ + CALC_145 \ + CALC_146 \ + CALC_147 \ + CALC_148 \ + CALC_149 \ + CALC_150 \ + CALC_151 \ + CALC_152 \ + CALC_153 \ + CALC_154 \ + CALC_155 \ + CALC_156 \ + CALC_157 \ + CALC_158 \ + CALC_159 \ + UPDATE_HASH(SI,DI,DX,CX,BX) \ + MOVL SI, R12 \ //Reset state for AVX2 reg permutation + MOVL DI, SI \ + MOVL DX, DI \ + MOVL BX, DX \ + MOVL CX, AX \ + MOVL R12, CX \ + XCHGQ R15, R14 \ + JMP loop + + + +TEXT ·blockAVX2(SB),$1408-32 + + MOVQ dig+0(FP), DI + MOVQ p_base+8(FP), SI + MOVQ p_len+16(FP), DX + SHRQ $6, DX + SHLQ $6, DX + + MOVQ $K_XMM_AR<>(SB), R8 + + MOVQ DI, R9 + MOVQ SI, R10 + LEAQ 64(SI), R13 + + ADDQ SI, DX + ADDQ $64, DX + MOVQ DX, R11 + + CMPQ R13, R11 + CMOVQCC R8, R13 + + VMOVDQU BSWAP_SHUFB_CTL<>(SB), Y10 + + CALC // RET is inside macros + +DATA K_XMM_AR<>+0x00(SB)/4,$0x5a827999 +DATA K_XMM_AR<>+0x04(SB)/4,$0x5a827999 +DATA K_XMM_AR<>+0x08(SB)/4,$0x5a827999 +DATA K_XMM_AR<>+0x0c(SB)/4,$0x5a827999 +DATA K_XMM_AR<>+0x10(SB)/4,$0x5a827999 +DATA K_XMM_AR<>+0x14(SB)/4,$0x5a827999 +DATA K_XMM_AR<>+0x18(SB)/4,$0x5a827999 +DATA K_XMM_AR<>+0x1c(SB)/4,$0x5a827999 +DATA K_XMM_AR<>+0x20(SB)/4,$0x6ed9eba1 +DATA K_XMM_AR<>+0x24(SB)/4,$0x6ed9eba1 +DATA K_XMM_AR<>+0x28(SB)/4,$0x6ed9eba1 +DATA K_XMM_AR<>+0x2c(SB)/4,$0x6ed9eba1 +DATA K_XMM_AR<>+0x30(SB)/4,$0x6ed9eba1 +DATA K_XMM_AR<>+0x34(SB)/4,$0x6ed9eba1 +DATA K_XMM_AR<>+0x38(SB)/4,$0x6ed9eba1 +DATA K_XMM_AR<>+0x3c(SB)/4,$0x6ed9eba1 +DATA K_XMM_AR<>+0x40(SB)/4,$0x8f1bbcdc +DATA K_XMM_AR<>+0x44(SB)/4,$0x8f1bbcdc +DATA K_XMM_AR<>+0x48(SB)/4,$0x8f1bbcdc +DATA K_XMM_AR<>+0x4c(SB)/4,$0x8f1bbcdc +DATA K_XMM_AR<>+0x50(SB)/4,$0x8f1bbcdc +DATA K_XMM_AR<>+0x54(SB)/4,$0x8f1bbcdc +DATA K_XMM_AR<>+0x58(SB)/4,$0x8f1bbcdc +DATA K_XMM_AR<>+0x5c(SB)/4,$0x8f1bbcdc +DATA K_XMM_AR<>+0x60(SB)/4,$0xca62c1d6 +DATA K_XMM_AR<>+0x64(SB)/4,$0xca62c1d6 +DATA K_XMM_AR<>+0x68(SB)/4,$0xca62c1d6 +DATA K_XMM_AR<>+0x6c(SB)/4,$0xca62c1d6 +DATA K_XMM_AR<>+0x70(SB)/4,$0xca62c1d6 +DATA K_XMM_AR<>+0x74(SB)/4,$0xca62c1d6 +DATA K_XMM_AR<>+0x78(SB)/4,$0xca62c1d6 +DATA K_XMM_AR<>+0x7c(SB)/4,$0xca62c1d6 +GLOBL K_XMM_AR<>(SB),RODATA,$128 + +DATA BSWAP_SHUFB_CTL<>+0x00(SB)/4,$0x00010203 +DATA BSWAP_SHUFB_CTL<>+0x04(SB)/4,$0x04050607 +DATA BSWAP_SHUFB_CTL<>+0x08(SB)/4,$0x08090a0b +DATA BSWAP_SHUFB_CTL<>+0x0c(SB)/4,$0x0c0d0e0f +DATA BSWAP_SHUFB_CTL<>+0x10(SB)/4,$0x00010203 +DATA BSWAP_SHUFB_CTL<>+0x14(SB)/4,$0x04050607 +DATA BSWAP_SHUFB_CTL<>+0x18(SB)/4,$0x08090a0b +DATA BSWAP_SHUFB_CTL<>+0x1c(SB)/4,$0x0c0d0e0f +GLOBL BSWAP_SHUFB_CTL<>(SB),RODATA,$32 diff --git a/src/crypto/sha1/sha1block_arm.s b/src/crypto/sha1/sha1block_arm.s new file mode 100644 index 0000000..2236533 --- /dev/null +++ b/src/crypto/sha1/sha1block_arm.s @@ -0,0 +1,217 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// ARM version of md5block.go + +#include "textflag.h" + +// SHA-1 block routine. See sha1block.go for Go equivalent. +// +// There are 80 rounds of 4 types: +// - rounds 0-15 are type 1 and load data (ROUND1 macro). +// - rounds 16-19 are type 1 and do not load data (ROUND1x macro). +// - rounds 20-39 are type 2 and do not load data (ROUND2 macro). +// - rounds 40-59 are type 3 and do not load data (ROUND3 macro). +// - rounds 60-79 are type 4 and do not load data (ROUND4 macro). +// +// Each round loads or shuffles the data, then computes a per-round +// function of b, c, d, and then mixes the result into and rotates the +// five registers a, b, c, d, e holding the intermediate results. +// +// The register rotation is implemented by rotating the arguments to +// the round macros instead of by explicit move instructions. + +// Register definitions +#define Rdata R0 // Pointer to incoming data +#define Rconst R1 // Current constant for SHA round +#define Ra R2 // SHA-1 accumulator +#define Rb R3 // SHA-1 accumulator +#define Rc R4 // SHA-1 accumulator +#define Rd R5 // SHA-1 accumulator +#define Re R6 // SHA-1 accumulator +#define Rt0 R7 // Temporary +#define Rt1 R8 // Temporary +// r9, r10 are forbidden +// r11 is OK provided you check the assembler that no synthetic instructions use it +#define Rt2 R11 // Temporary +#define Rctr R12 // loop counter +#define Rw R14 // point to w buffer + +// func block(dig *digest, p []byte) +// 0(FP) is *digest +// 4(FP) is p.array (struct Slice) +// 8(FP) is p.len +//12(FP) is p.cap +// +// Stack frame +#define p_end end-4(SP) // pointer to the end of data +#define p_data data-8(SP) // current data pointer (unused?) +#define w_buf buf-(8+4*80)(SP) //80 words temporary buffer w uint32[80] +#define saved abcde-(8+4*80+4*5)(SP) // saved sha1 registers a,b,c,d,e - these must be last (unused?) +// Total size +4 for saved LR is 352 + + // w[i] = p[j]<<24 | p[j+1]<<16 | p[j+2]<<8 | p[j+3] + // e += w[i] +#define LOAD(Re) \ + MOVBU 2(Rdata), Rt0 ; \ + MOVBU 3(Rdata), Rt1 ; \ + MOVBU 1(Rdata), Rt2 ; \ + ORR Rt0<<8, Rt1, Rt0 ; \ + MOVBU.P 4(Rdata), Rt1 ; \ + ORR Rt2<<16, Rt0, Rt0 ; \ + ORR Rt1<<24, Rt0, Rt0 ; \ + MOVW.P Rt0, 4(Rw) ; \ + ADD Rt0, Re, Re + + // tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf] + // w[i&0xf] = tmp<<1 | tmp>>(32-1) + // e += w[i&0xf] +#define SHUFFLE(Re) \ + MOVW (-16*4)(Rw), Rt0 ; \ + MOVW (-14*4)(Rw), Rt1 ; \ + MOVW (-8*4)(Rw), Rt2 ; \ + EOR Rt0, Rt1, Rt0 ; \ + MOVW (-3*4)(Rw), Rt1 ; \ + EOR Rt2, Rt0, Rt0 ; \ + EOR Rt0, Rt1, Rt0 ; \ + MOVW Rt0@>(32-1), Rt0 ; \ + MOVW.P Rt0, 4(Rw) ; \ + ADD Rt0, Re, Re + + // t1 = (b & c) | ((~b) & d) +#define FUNC1(Ra, Rb, Rc, Rd, Re) \ + MVN Rb, Rt1 ; \ + AND Rb, Rc, Rt0 ; \ + AND Rd, Rt1, Rt1 ; \ + ORR Rt0, Rt1, Rt1 + + // t1 = b ^ c ^ d +#define FUNC2(Ra, Rb, Rc, Rd, Re) \ + EOR Rb, Rc, Rt1 ; \ + EOR Rd, Rt1, Rt1 + + // t1 = (b & c) | (b & d) | (c & d) = + // t1 = (b & c) | ((b | c) & d) +#define FUNC3(Ra, Rb, Rc, Rd, Re) \ + ORR Rb, Rc, Rt0 ; \ + AND Rb, Rc, Rt1 ; \ + AND Rd, Rt0, Rt0 ; \ + ORR Rt0, Rt1, Rt1 + +#define FUNC4 FUNC2 + + // a5 := a<<5 | a>>(32-5) + // b = b<<30 | b>>(32-30) + // e = a5 + t1 + e + const +#define MIX(Ra, Rb, Rc, Rd, Re) \ + ADD Rt1, Re, Re ; \ + MOVW Rb@>(32-30), Rb ; \ + ADD Ra@>(32-5), Re, Re ; \ + ADD Rconst, Re, Re + +#define ROUND1(Ra, Rb, Rc, Rd, Re) \ + LOAD(Re) ; \ + FUNC1(Ra, Rb, Rc, Rd, Re) ; \ + MIX(Ra, Rb, Rc, Rd, Re) + +#define ROUND1x(Ra, Rb, Rc, Rd, Re) \ + SHUFFLE(Re) ; \ + FUNC1(Ra, Rb, Rc, Rd, Re) ; \ + MIX(Ra, Rb, Rc, Rd, Re) + +#define ROUND2(Ra, Rb, Rc, Rd, Re) \ + SHUFFLE(Re) ; \ + FUNC2(Ra, Rb, Rc, Rd, Re) ; \ + MIX(Ra, Rb, Rc, Rd, Re) + +#define ROUND3(Ra, Rb, Rc, Rd, Re) \ + SHUFFLE(Re) ; \ + FUNC3(Ra, Rb, Rc, Rd, Re) ; \ + MIX(Ra, Rb, Rc, Rd, Re) + +#define ROUND4(Ra, Rb, Rc, Rd, Re) \ + SHUFFLE(Re) ; \ + FUNC4(Ra, Rb, Rc, Rd, Re) ; \ + MIX(Ra, Rb, Rc, Rd, Re) + + +// func block(dig *digest, p []byte) +TEXT ·block(SB), 0, $352-16 + MOVW p+4(FP), Rdata // pointer to the data + MOVW p_len+8(FP), Rt0 // number of bytes + ADD Rdata, Rt0 + MOVW Rt0, p_end // pointer to end of data + + // Load up initial SHA-1 accumulator + MOVW dig+0(FP), Rt0 + MOVM.IA (Rt0), [Ra,Rb,Rc,Rd,Re] + +loop: + // Save registers at SP+4 onwards + MOVM.IB [Ra,Rb,Rc,Rd,Re], (R13) + + MOVW $w_buf, Rw + MOVW $0x5A827999, Rconst + MOVW $3, Rctr +loop1: ROUND1(Ra, Rb, Rc, Rd, Re) + ROUND1(Re, Ra, Rb, Rc, Rd) + ROUND1(Rd, Re, Ra, Rb, Rc) + ROUND1(Rc, Rd, Re, Ra, Rb) + ROUND1(Rb, Rc, Rd, Re, Ra) + SUB.S $1, Rctr + BNE loop1 + + ROUND1(Ra, Rb, Rc, Rd, Re) + ROUND1x(Re, Ra, Rb, Rc, Rd) + ROUND1x(Rd, Re, Ra, Rb, Rc) + ROUND1x(Rc, Rd, Re, Ra, Rb) + ROUND1x(Rb, Rc, Rd, Re, Ra) + + MOVW $0x6ED9EBA1, Rconst + MOVW $4, Rctr +loop2: ROUND2(Ra, Rb, Rc, Rd, Re) + ROUND2(Re, Ra, Rb, Rc, Rd) + ROUND2(Rd, Re, Ra, Rb, Rc) + ROUND2(Rc, Rd, Re, Ra, Rb) + ROUND2(Rb, Rc, Rd, Re, Ra) + SUB.S $1, Rctr + BNE loop2 + + MOVW $0x8F1BBCDC, Rconst + MOVW $4, Rctr +loop3: ROUND3(Ra, Rb, Rc, Rd, Re) + ROUND3(Re, Ra, Rb, Rc, Rd) + ROUND3(Rd, Re, Ra, Rb, Rc) + ROUND3(Rc, Rd, Re, Ra, Rb) + ROUND3(Rb, Rc, Rd, Re, Ra) + SUB.S $1, Rctr + BNE loop3 + + MOVW $0xCA62C1D6, Rconst + MOVW $4, Rctr +loop4: ROUND4(Ra, Rb, Rc, Rd, Re) + ROUND4(Re, Ra, Rb, Rc, Rd) + ROUND4(Rd, Re, Ra, Rb, Rc) + ROUND4(Rc, Rd, Re, Ra, Rb) + ROUND4(Rb, Rc, Rd, Re, Ra) + SUB.S $1, Rctr + BNE loop4 + + // Accumulate - restoring registers from SP+4 + MOVM.IB (R13), [Rt0,Rt1,Rt2,Rctr,Rw] + ADD Rt0, Ra + ADD Rt1, Rb + ADD Rt2, Rc + ADD Rctr, Rd + ADD Rw, Re + + MOVW p_end, Rt0 + CMP Rt0, Rdata + BLO loop + + // Save final SHA-1 accumulator + MOVW dig+0(FP), Rt0 + MOVM.IA [Ra,Rb,Rc,Rd,Re], (Rt0) + + RET diff --git a/src/crypto/sha1/sha1block_arm64.go b/src/crypto/sha1/sha1block_arm64.go new file mode 100644 index 0000000..08d3df0 --- /dev/null +++ b/src/crypto/sha1/sha1block_arm64.go @@ -0,0 +1,26 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha1 + +import "internal/cpu" + +var k = []uint32{ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6, +} + +//go:noescape +func sha1block(h []uint32, p []byte, k []uint32) + +func block(dig *digest, p []byte) { + if !cpu.ARM64.HasSHA1 { + blockGeneric(dig, p) + } else { + h := dig.h[:] + sha1block(h, p, k) + } +} diff --git a/src/crypto/sha1/sha1block_arm64.s b/src/crypto/sha1/sha1block_arm64.s new file mode 100644 index 0000000..d568384 --- /dev/null +++ b/src/crypto/sha1/sha1block_arm64.s @@ -0,0 +1,152 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +#define HASHUPDATECHOOSE \ + SHA1C V16.S4, V1, V2 \ + SHA1H V3, V1 \ + VMOV V2.B16, V3.B16 + +#define HASHUPDATEPARITY \ + SHA1P V16.S4, V1, V2 \ + SHA1H V3, V1 \ + VMOV V2.B16, V3.B16 + +#define HASHUPDATEMAJ \ + SHA1M V16.S4, V1, V2 \ + SHA1H V3, V1 \ + VMOV V2.B16, V3.B16 + +// func sha1block(h []uint32, p []byte, k []uint32) +TEXT ·sha1block(SB),NOSPLIT,$0 + MOVD h_base+0(FP), R0 // hash value first address + MOVD p_base+24(FP), R1 // message first address + MOVD k_base+48(FP), R2 // k constants first address + MOVD p_len+32(FP), R3 // message length + VLD1.P 16(R0), [V0.S4] + FMOVS (R0), F20 + SUB $16, R0, R0 + +blockloop: + + VLD1.P 16(R1), [V4.B16] // load message + VLD1.P 16(R1), [V5.B16] + VLD1.P 16(R1), [V6.B16] + VLD1.P 16(R1), [V7.B16] + VLD1 (R2), [V19.S4] // load constant k0-k79 + VMOV V0.B16, V2.B16 + VMOV V20.S[0], V1 + VMOV V2.B16, V3.B16 + VDUP V19.S[0], V17.S4 + VREV32 V4.B16, V4.B16 // prepare for using message in Byte format + VREV32 V5.B16, V5.B16 + VREV32 V6.B16, V6.B16 + VREV32 V7.B16, V7.B16 + + + VDUP V19.S[1], V18.S4 + VADD V17.S4, V4.S4, V16.S4 + SHA1SU0 V6.S4, V5.S4, V4.S4 + HASHUPDATECHOOSE + SHA1SU1 V7.S4, V4.S4 + + VADD V17.S4, V5.S4, V16.S4 + SHA1SU0 V7.S4, V6.S4, V5.S4 + HASHUPDATECHOOSE + SHA1SU1 V4.S4, V5.S4 + VADD V17.S4, V6.S4, V16.S4 + SHA1SU0 V4.S4, V7.S4, V6.S4 + HASHUPDATECHOOSE + SHA1SU1 V5.S4, V6.S4 + + VADD V17.S4, V7.S4, V16.S4 + SHA1SU0 V5.S4, V4.S4, V7.S4 + HASHUPDATECHOOSE + SHA1SU1 V6.S4, V7.S4 + + VADD V17.S4, V4.S4, V16.S4 + SHA1SU0 V6.S4, V5.S4, V4.S4 + HASHUPDATECHOOSE + SHA1SU1 V7.S4, V4.S4 + + VDUP V19.S[2], V17.S4 + VADD V18.S4, V5.S4, V16.S4 + SHA1SU0 V7.S4, V6.S4, V5.S4 + HASHUPDATEPARITY + SHA1SU1 V4.S4, V5.S4 + + VADD V18.S4, V6.S4, V16.S4 + SHA1SU0 V4.S4, V7.S4, V6.S4 + HASHUPDATEPARITY + SHA1SU1 V5.S4, V6.S4 + + VADD V18.S4, V7.S4, V16.S4 + SHA1SU0 V5.S4, V4.S4, V7.S4 + HASHUPDATEPARITY + SHA1SU1 V6.S4, V7.S4 + + VADD V18.S4, V4.S4, V16.S4 + SHA1SU0 V6.S4, V5.S4, V4.S4 + HASHUPDATEPARITY + SHA1SU1 V7.S4, V4.S4 + + VADD V18.S4, V5.S4, V16.S4 + SHA1SU0 V7.S4, V6.S4, V5.S4 + HASHUPDATEPARITY + SHA1SU1 V4.S4, V5.S4 + + VDUP V19.S[3], V18.S4 + VADD V17.S4, V6.S4, V16.S4 + SHA1SU0 V4.S4, V7.S4, V6.S4 + HASHUPDATEMAJ + SHA1SU1 V5.S4, V6.S4 + + VADD V17.S4, V7.S4, V16.S4 + SHA1SU0 V5.S4, V4.S4, V7.S4 + HASHUPDATEMAJ + SHA1SU1 V6.S4, V7.S4 + + VADD V17.S4, V4.S4, V16.S4 + SHA1SU0 V6.S4, V5.S4, V4.S4 + HASHUPDATEMAJ + SHA1SU1 V7.S4, V4.S4 + + VADD V17.S4, V5.S4, V16.S4 + SHA1SU0 V7.S4, V6.S4, V5.S4 + HASHUPDATEMAJ + SHA1SU1 V4.S4, V5.S4 + + VADD V17.S4, V6.S4, V16.S4 + SHA1SU0 V4.S4, V7.S4, V6.S4 + HASHUPDATEMAJ + SHA1SU1 V5.S4, V6.S4 + + VADD V18.S4, V7.S4, V16.S4 + SHA1SU0 V5.S4, V4.S4, V7.S4 + HASHUPDATEPARITY + SHA1SU1 V6.S4, V7.S4 + + VADD V18.S4, V4.S4, V16.S4 + HASHUPDATEPARITY + + VADD V18.S4, V5.S4, V16.S4 + HASHUPDATEPARITY + + VADD V18.S4, V6.S4, V16.S4 + HASHUPDATEPARITY + + VADD V18.S4, V7.S4, V16.S4 + HASHUPDATEPARITY + + SUB $64, R3, R3 // message length - 64bytes, then compare with 64bytes + VADD V2.S4, V0.S4, V0.S4 + VADD V1.S4, V20.S4, V20.S4 + CBNZ R3, blockloop + +sha1ret: + + VST1.P [V0.S4], 16(R0) // store hash value H(dcba) + FMOVS F20, (R0) // store hash value H(e) + RET diff --git a/src/crypto/sha1/sha1block_decl.go b/src/crypto/sha1/sha1block_decl.go new file mode 100644 index 0000000..93054ef --- /dev/null +++ b/src/crypto/sha1/sha1block_decl.go @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build arm || 386 || s390x +// +build arm 386 s390x + +package sha1 + +//go:noescape + +func block(dig *digest, p []byte) diff --git a/src/crypto/sha1/sha1block_generic.go b/src/crypto/sha1/sha1block_generic.go new file mode 100644 index 0000000..feaba5a --- /dev/null +++ b/src/crypto/sha1/sha1block_generic.go @@ -0,0 +1,10 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 && !386 && !arm && !s390x && !arm64 +// +build !amd64,!386,!arm,!s390x,!arm64 + +package sha1 + +var block = blockGeneric diff --git a/src/crypto/sha1/sha1block_s390x.go b/src/crypto/sha1/sha1block_s390x.go new file mode 100644 index 0000000..446bf5d --- /dev/null +++ b/src/crypto/sha1/sha1block_s390x.go @@ -0,0 +1,9 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha1 + +import "internal/cpu" + +var useAsm = cpu.S390X.HasSHA1 diff --git a/src/crypto/sha1/sha1block_s390x.s b/src/crypto/sha1/sha1block_s390x.s new file mode 100644 index 0000000..6ba6883 --- /dev/null +++ b/src/crypto/sha1/sha1block_s390x.s @@ -0,0 +1,20 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func block(dig *digest, p []byte) +TEXT ·block(SB), NOSPLIT|NOFRAME, $0-32 + MOVBZ ·useAsm(SB), R4 + LMG dig+0(FP), R1, R3 // R2 = &p[0], R3 = len(p) + MOVBZ $1, R0 // SHA-1 function code + CMPBEQ R4, $0, generic + +loop: + WORD $0xB93E0002 // KIMD R2 + BVS loop // continue if interrupted + RET + +generic: + BR ·blockGeneric(SB) diff --git a/src/crypto/sha256/example_test.go b/src/crypto/sha256/example_test.go new file mode 100644 index 0000000..7d73120 --- /dev/null +++ b/src/crypto/sha256/example_test.go @@ -0,0 +1,41 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha256_test + +import ( + "crypto/sha256" + "fmt" + "io" + "log" + "os" +) + +func ExampleSum256() { + sum := sha256.Sum256([]byte("hello world\n")) + fmt.Printf("%x", sum) + // Output: a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447 +} + +func ExampleNew() { + h := sha256.New() + h.Write([]byte("hello world\n")) + fmt.Printf("%x", h.Sum(nil)) + // Output: a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447 +} + +func ExampleNew_file() { + f, err := os.Open("file.txt") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + log.Fatal(err) + } + + fmt.Printf("%x", h.Sum(nil)) +} diff --git a/src/crypto/sha256/fallback_test.go b/src/crypto/sha256/fallback_test.go new file mode 100644 index 0000000..7ce88cb --- /dev/null +++ b/src/crypto/sha256/fallback_test.go @@ -0,0 +1,36 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build s390x +// +build s390x + +package sha256 + +import ( + "fmt" + "io" + "testing" +) + +// Tests the fallback code path in case the optimized asm +// implementation cannot be used. +// See also TestBlockGeneric. +func TestGenericPath(t *testing.T) { + if useAsm == false { + t.Skipf("assembly implementation unavailable") + } + useAsm = false + defer func() { useAsm = true }() + c := New() + in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" + gold := "e93d84ec2b22383123be9f713697fb25" + + "338c86e2f7d8d1ddc2d89d332dd9d76c" + if _, err := io.WriteString(c, in); err != nil { + t.Fatalf("could not write to c: %v", err) + } + out := fmt.Sprintf("%x", c.Sum(nil)) + if out != gold { + t.Fatalf("mismatch: got %s, wanted %s", out, gold) + } +} diff --git a/src/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go new file mode 100644 index 0000000..e1cccf6 --- /dev/null +++ b/src/crypto/sha256/sha256.go @@ -0,0 +1,270 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sha256 implements the SHA224 and SHA256 hash algorithms as defined +// in FIPS 180-4. +package sha256 + +import ( + "crypto" + "encoding/binary" + "errors" + "hash" +) + +func init() { + crypto.RegisterHash(crypto.SHA224, New224) + crypto.RegisterHash(crypto.SHA256, New) +} + +// The size of a SHA256 checksum in bytes. +const Size = 32 + +// The size of a SHA224 checksum in bytes. +const Size224 = 28 + +// The blocksize of SHA256 and SHA224 in bytes. +const BlockSize = 64 + +const ( + chunk = 64 + init0 = 0x6A09E667 + init1 = 0xBB67AE85 + init2 = 0x3C6EF372 + init3 = 0xA54FF53A + init4 = 0x510E527F + init5 = 0x9B05688C + init6 = 0x1F83D9AB + init7 = 0x5BE0CD19 + init0_224 = 0xC1059ED8 + init1_224 = 0x367CD507 + init2_224 = 0x3070DD17 + init3_224 = 0xF70E5939 + init4_224 = 0xFFC00B31 + init5_224 = 0x68581511 + init6_224 = 0x64F98FA7 + init7_224 = 0xBEFA4FA4 +) + +// digest represents the partial evaluation of a checksum. +type digest struct { + h [8]uint32 + x [chunk]byte + nx int + len uint64 + is224 bool // mark if this digest is SHA-224 +} + +const ( + magic224 = "sha\x02" + magic256 = "sha\x03" + marshaledSize = len(magic256) + 8*4 + chunk + 8 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + b := make([]byte, 0, marshaledSize) + if d.is224 { + b = append(b, magic224...) + } else { + b = append(b, magic256...) + } + b = appendUint32(b, d.h[0]) + b = appendUint32(b, d.h[1]) + b = appendUint32(b, d.h[2]) + b = appendUint32(b, d.h[3]) + b = appendUint32(b, d.h[4]) + b = appendUint32(b, d.h[5]) + b = appendUint32(b, d.h[6]) + b = appendUint32(b, d.h[7]) + b = append(b, d.x[:d.nx]...) + b = b[:len(b)+len(d.x)-int(d.nx)] // already zero + b = appendUint64(b, d.len) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) { + return errors.New("crypto/sha256: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/sha256: invalid hash state size") + } + b = b[len(magic224):] + b, d.h[0] = consumeUint32(b) + b, d.h[1] = consumeUint32(b) + b, d.h[2] = consumeUint32(b) + b, d.h[3] = consumeUint32(b) + b, d.h[4] = consumeUint32(b) + b, d.h[5] = consumeUint32(b) + b, d.h[6] = consumeUint32(b) + b, d.h[7] = consumeUint32(b) + b = b[copy(d.x[:], b):] + b, d.len = consumeUint64(b) + d.nx = int(d.len % chunk) + return nil +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + _ = b[7] + x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 + return b[8:], x +} + +func consumeUint32(b []byte) ([]byte, uint32) { + _ = b[3] + x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 + return b[4:], x +} + +func (d *digest) Reset() { + if !d.is224 { + d.h[0] = init0 + d.h[1] = init1 + d.h[2] = init2 + d.h[3] = init3 + d.h[4] = init4 + d.h[5] = init5 + d.h[6] = init6 + d.h[7] = init7 + } else { + d.h[0] = init0_224 + d.h[1] = init1_224 + d.h[2] = init2_224 + d.h[3] = init3_224 + d.h[4] = init4_224 + d.h[5] = init5_224 + d.h[6] = init6_224 + d.h[7] = init7_224 + } + d.nx = 0 + d.len = 0 +} + +// New returns a new hash.Hash computing the SHA256 checksum. The Hash +// also implements encoding.BinaryMarshaler and +// encoding.BinaryUnmarshaler to marshal and unmarshal the internal +// state of the hash. +func New() hash.Hash { + d := new(digest) + d.Reset() + return d +} + +// New224 returns a new hash.Hash computing the SHA224 checksum. +func New224() hash.Hash { + d := new(digest) + d.is224 = true + d.Reset() + return d +} + +func (d *digest) Size() int { + if !d.is224 { + return Size + } + return Size224 +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Write(p []byte) (nn int, err error) { + nn = len(p) + d.len += uint64(nn) + if d.nx > 0 { + n := copy(d.x[d.nx:], p) + d.nx += n + if d.nx == chunk { + block(d, d.x[:]) + d.nx = 0 + } + p = p[n:] + } + if len(p) >= chunk { + n := len(p) &^ (chunk - 1) + block(d, p[:n]) + p = p[n:] + } + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d so that caller can keep writing and summing. + d0 := *d + hash := d0.checkSum() + if d0.is224 { + return append(in, hash[:Size224]...) + } + return append(in, hash[:]...) +} + +func (d *digest) checkSum() [Size]byte { + len := d.len + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + var tmp [64]byte + tmp[0] = 0x80 + if len%64 < 56 { + d.Write(tmp[0 : 56-len%64]) + } else { + d.Write(tmp[0 : 64+56-len%64]) + } + + // Length in bits. + len <<= 3 + binary.BigEndian.PutUint64(tmp[:], len) + d.Write(tmp[0:8]) + + if d.nx != 0 { + panic("d.nx != 0") + } + + var digest [Size]byte + + binary.BigEndian.PutUint32(digest[0:], d.h[0]) + binary.BigEndian.PutUint32(digest[4:], d.h[1]) + binary.BigEndian.PutUint32(digest[8:], d.h[2]) + binary.BigEndian.PutUint32(digest[12:], d.h[3]) + binary.BigEndian.PutUint32(digest[16:], d.h[4]) + binary.BigEndian.PutUint32(digest[20:], d.h[5]) + binary.BigEndian.PutUint32(digest[24:], d.h[6]) + if !d.is224 { + binary.BigEndian.PutUint32(digest[28:], d.h[7]) + } + + return digest +} + +// Sum256 returns the SHA256 checksum of the data. +func Sum256(data []byte) [Size]byte { + var d digest + d.Reset() + d.Write(data) + return d.checkSum() +} + +// Sum224 returns the SHA224 checksum of the data. +func Sum224(data []byte) (sum224 [Size224]byte) { + var d digest + d.is224 = true + d.Reset() + d.Write(data) + sum := d.checkSum() + copy(sum224[:], sum[:Size224]) + return +} diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go new file mode 100644 index 0000000..a2794b0 --- /dev/null +++ b/src/crypto/sha256/sha256_test.go @@ -0,0 +1,315 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// SHA256 hash algorithm. See FIPS 180-2. + +package sha256 + +import ( + "bytes" + "crypto/rand" + "encoding" + "fmt" + "hash" + "io" + "testing" +) + +type sha256Test struct { + out string + in string + halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal +} + +var golden = []sha256Test{ + {"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "", "sha\x03j\t\xe6g\xbbg\xae\x85= chunk { + // Can interlace the computation of w with the + // rounds below if needed for speed. + for i := 0; i < 16; i++ { + j := i * 4 + w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3]) + } + for i := 16; i < 64; i++ { + v1 := w[i-2] + t1 := (bits.RotateLeft32(v1, -17)) ^ (bits.RotateLeft32(v1, -19)) ^ (v1 >> 10) + v2 := w[i-15] + t2 := (bits.RotateLeft32(v2, -7)) ^ (bits.RotateLeft32(v2, -18)) ^ (v2 >> 3) + w[i] = t1 + w[i-7] + t2 + w[i-16] + } + + a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7 + + for i := 0; i < 64; i++ { + t1 := h + ((bits.RotateLeft32(e, -6)) ^ (bits.RotateLeft32(e, -11)) ^ (bits.RotateLeft32(e, -25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i] + + t2 := ((bits.RotateLeft32(a, -2)) ^ (bits.RotateLeft32(a, -13)) ^ (bits.RotateLeft32(a, -22))) + ((a & b) ^ (a & c) ^ (b & c)) + + h = g + g = f + f = e + e = d + t1 + d = c + c = b + b = a + a = t1 + t2 + } + + h0 += a + h1 += b + h2 += c + h3 += d + h4 += e + h5 += f + h6 += g + h7 += h + + p = p[chunk:] + } + + dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7 +} diff --git a/src/crypto/sha256/sha256block_386.s b/src/crypto/sha256/sha256block_386.s new file mode 100644 index 0000000..086a0ab --- /dev/null +++ b/src/crypto/sha256/sha256block_386.s @@ -0,0 +1,283 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// SHA256 block routine. See sha256block.go for Go equivalent. +// +// The algorithm is detailed in FIPS 180-4: +// +// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf +// +// Wt = Mt; for 0 <= t <= 15 +// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 +// +// a = H0 +// b = H1 +// c = H2 +// d = H3 +// e = H4 +// f = H5 +// g = H6 +// h = H7 +// +// for t = 0 to 63 { +// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt +// T2 = BIGSIGMA0(a) + Maj(a,b,c) +// h = g +// g = f +// f = e +// e = d + T1 +// d = c +// c = b +// b = a +// a = T1 + T2 +// } +// +// H0 = a + H0 +// H1 = b + H1 +// H2 = c + H2 +// H3 = d + H3 +// H4 = e + H4 +// H5 = f + H5 +// H6 = g + H6 +// H7 = h + H7 + +// Wt = Mt; for 0 <= t <= 15 +#define MSGSCHEDULE0(index) \ + MOVL (index*4)(SI), AX; \ + BSWAPL AX; \ + MOVL AX, (index*4)(BP) + +// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 +// SIGMA0(x) = ROTR(7,x) XOR ROTR(18,x) XOR SHR(3,x) +// SIGMA1(x) = ROTR(17,x) XOR ROTR(19,x) XOR SHR(10,x) +#define MSGSCHEDULE1(index) \ + MOVL ((index-2)*4)(BP), AX; \ + MOVL AX, CX; \ + RORL $17, AX; \ + MOVL CX, DX; \ + RORL $19, CX; \ + SHRL $10, DX; \ + MOVL ((index-15)*4)(BP), BX; \ + XORL CX, AX; \ + MOVL BX, CX; \ + XORL DX, AX; \ + RORL $7, BX; \ + MOVL CX, DX; \ + SHRL $3, DX; \ + RORL $18, CX; \ + ADDL ((index-7)*4)(BP), AX; \ + XORL CX, BX; \ + XORL DX, BX; \ + ADDL ((index-16)*4)(BP), BX; \ + ADDL BX, AX; \ + MOVL AX, ((index)*4)(BP) + +// Calculate T1 in AX - uses AX, BX, CX and DX registers. +// Wt is passed in AX. +// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt +// BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x) +// Ch(x, y, z) = (x AND y) XOR (NOT x AND z) +#define SHA256T1(const, e, f, g, h) \ + MOVL (h*4)(DI), BX; \ + ADDL AX, BX; \ + MOVL (e*4)(DI), AX; \ + ADDL $const, BX; \ + MOVL (e*4)(DI), CX; \ + RORL $6, AX; \ + MOVL (e*4)(DI), DX; \ + RORL $11, CX; \ + XORL CX, AX; \ + MOVL (e*4)(DI), CX; \ + RORL $25, DX; \ + ANDL (f*4)(DI), CX; \ + XORL AX, DX; \ + MOVL (e*4)(DI), AX; \ + NOTL AX; \ + ADDL DX, BX; \ + ANDL (g*4)(DI), AX; \ + XORL CX, AX; \ + ADDL BX, AX + +// Calculate T2 in BX - uses AX, BX, CX and DX registers. +// T2 = BIGSIGMA0(a) + Maj(a, b, c) +// BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x) +// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) +#define SHA256T2(a, b, c) \ + MOVL (a*4)(DI), AX; \ + MOVL (c*4)(DI), BX; \ + RORL $2, AX; \ + MOVL (a*4)(DI), DX; \ + ANDL (b*4)(DI), BX; \ + RORL $13, DX; \ + MOVL (a*4)(DI), CX; \ + ANDL (c*4)(DI), CX; \ + XORL DX, AX; \ + XORL CX, BX; \ + MOVL (a*4)(DI), DX; \ + MOVL (b*4)(DI), CX; \ + RORL $22, DX; \ + ANDL (a*4)(DI), CX; \ + XORL CX, BX; \ + XORL DX, AX; \ + ADDL AX, BX + +// Calculate T1 and T2, then e = d + T1 and a = T1 + T2. +// The values for e and a are stored in d and h, ready for rotation. +#define SHA256ROUND(index, const, a, b, c, d, e, f, g, h) \ + SHA256T1(const, e, f, g, h); \ + MOVL AX, 292(SP); \ + SHA256T2(a, b, c); \ + MOVL 292(SP), AX; \ + ADDL AX, BX; \ + ADDL AX, (d*4)(DI); \ + MOVL BX, (h*4)(DI) + +#define SHA256ROUND0(index, const, a, b, c, d, e, f, g, h) \ + MSGSCHEDULE0(index); \ + SHA256ROUND(index, const, a, b, c, d, e, f, g, h) + +#define SHA256ROUND1(index, const, a, b, c, d, e, f, g, h) \ + MSGSCHEDULE1(index); \ + SHA256ROUND(index, const, a, b, c, d, e, f, g, h) + +TEXT ·block(SB),0,$296-16 + MOVL p_base+4(FP), SI + MOVL p_len+8(FP), DX + SHRL $6, DX + SHLL $6, DX + + LEAL (SI)(DX*1), DI + MOVL DI, 288(SP) + CMPL SI, DI + JEQ end + + LEAL 256(SP), DI // variables + + MOVL dig+0(FP), BP + MOVL (0*4)(BP), AX // a = H0 + MOVL AX, (0*4)(DI) + MOVL (1*4)(BP), BX // b = H1 + MOVL BX, (1*4)(DI) + MOVL (2*4)(BP), CX // c = H2 + MOVL CX, (2*4)(DI) + MOVL (3*4)(BP), DX // d = H3 + MOVL DX, (3*4)(DI) + MOVL (4*4)(BP), AX // e = H4 + MOVL AX, (4*4)(DI) + MOVL (5*4)(BP), BX // f = H5 + MOVL BX, (5*4)(DI) + MOVL (6*4)(BP), CX // g = H6 + MOVL CX, (6*4)(DI) + MOVL (7*4)(BP), DX // h = H7 + MOVL DX, (7*4)(DI) + +loop: + MOVL SP, BP // message schedule + + SHA256ROUND0(0, 0x428a2f98, 0, 1, 2, 3, 4, 5, 6, 7) + SHA256ROUND0(1, 0x71374491, 7, 0, 1, 2, 3, 4, 5, 6) + SHA256ROUND0(2, 0xb5c0fbcf, 6, 7, 0, 1, 2, 3, 4, 5) + SHA256ROUND0(3, 0xe9b5dba5, 5, 6, 7, 0, 1, 2, 3, 4) + SHA256ROUND0(4, 0x3956c25b, 4, 5, 6, 7, 0, 1, 2, 3) + SHA256ROUND0(5, 0x59f111f1, 3, 4, 5, 6, 7, 0, 1, 2) + SHA256ROUND0(6, 0x923f82a4, 2, 3, 4, 5, 6, 7, 0, 1) + SHA256ROUND0(7, 0xab1c5ed5, 1, 2, 3, 4, 5, 6, 7, 0) + SHA256ROUND0(8, 0xd807aa98, 0, 1, 2, 3, 4, 5, 6, 7) + SHA256ROUND0(9, 0x12835b01, 7, 0, 1, 2, 3, 4, 5, 6) + SHA256ROUND0(10, 0x243185be, 6, 7, 0, 1, 2, 3, 4, 5) + SHA256ROUND0(11, 0x550c7dc3, 5, 6, 7, 0, 1, 2, 3, 4) + SHA256ROUND0(12, 0x72be5d74, 4, 5, 6, 7, 0, 1, 2, 3) + SHA256ROUND0(13, 0x80deb1fe, 3, 4, 5, 6, 7, 0, 1, 2) + SHA256ROUND0(14, 0x9bdc06a7, 2, 3, 4, 5, 6, 7, 0, 1) + SHA256ROUND0(15, 0xc19bf174, 1, 2, 3, 4, 5, 6, 7, 0) + + SHA256ROUND1(16, 0xe49b69c1, 0, 1, 2, 3, 4, 5, 6, 7) + SHA256ROUND1(17, 0xefbe4786, 7, 0, 1, 2, 3, 4, 5, 6) + SHA256ROUND1(18, 0x0fc19dc6, 6, 7, 0, 1, 2, 3, 4, 5) + SHA256ROUND1(19, 0x240ca1cc, 5, 6, 7, 0, 1, 2, 3, 4) + SHA256ROUND1(20, 0x2de92c6f, 4, 5, 6, 7, 0, 1, 2, 3) + SHA256ROUND1(21, 0x4a7484aa, 3, 4, 5, 6, 7, 0, 1, 2) + SHA256ROUND1(22, 0x5cb0a9dc, 2, 3, 4, 5, 6, 7, 0, 1) + SHA256ROUND1(23, 0x76f988da, 1, 2, 3, 4, 5, 6, 7, 0) + SHA256ROUND1(24, 0x983e5152, 0, 1, 2, 3, 4, 5, 6, 7) + SHA256ROUND1(25, 0xa831c66d, 7, 0, 1, 2, 3, 4, 5, 6) + SHA256ROUND1(26, 0xb00327c8, 6, 7, 0, 1, 2, 3, 4, 5) + SHA256ROUND1(27, 0xbf597fc7, 5, 6, 7, 0, 1, 2, 3, 4) + SHA256ROUND1(28, 0xc6e00bf3, 4, 5, 6, 7, 0, 1, 2, 3) + SHA256ROUND1(29, 0xd5a79147, 3, 4, 5, 6, 7, 0, 1, 2) + SHA256ROUND1(30, 0x06ca6351, 2, 3, 4, 5, 6, 7, 0, 1) + SHA256ROUND1(31, 0x14292967, 1, 2, 3, 4, 5, 6, 7, 0) + SHA256ROUND1(32, 0x27b70a85, 0, 1, 2, 3, 4, 5, 6, 7) + SHA256ROUND1(33, 0x2e1b2138, 7, 0, 1, 2, 3, 4, 5, 6) + SHA256ROUND1(34, 0x4d2c6dfc, 6, 7, 0, 1, 2, 3, 4, 5) + SHA256ROUND1(35, 0x53380d13, 5, 6, 7, 0, 1, 2, 3, 4) + SHA256ROUND1(36, 0x650a7354, 4, 5, 6, 7, 0, 1, 2, 3) + SHA256ROUND1(37, 0x766a0abb, 3, 4, 5, 6, 7, 0, 1, 2) + SHA256ROUND1(38, 0x81c2c92e, 2, 3, 4, 5, 6, 7, 0, 1) + SHA256ROUND1(39, 0x92722c85, 1, 2, 3, 4, 5, 6, 7, 0) + SHA256ROUND1(40, 0xa2bfe8a1, 0, 1, 2, 3, 4, 5, 6, 7) + SHA256ROUND1(41, 0xa81a664b, 7, 0, 1, 2, 3, 4, 5, 6) + SHA256ROUND1(42, 0xc24b8b70, 6, 7, 0, 1, 2, 3, 4, 5) + SHA256ROUND1(43, 0xc76c51a3, 5, 6, 7, 0, 1, 2, 3, 4) + SHA256ROUND1(44, 0xd192e819, 4, 5, 6, 7, 0, 1, 2, 3) + SHA256ROUND1(45, 0xd6990624, 3, 4, 5, 6, 7, 0, 1, 2) + SHA256ROUND1(46, 0xf40e3585, 2, 3, 4, 5, 6, 7, 0, 1) + SHA256ROUND1(47, 0x106aa070, 1, 2, 3, 4, 5, 6, 7, 0) + SHA256ROUND1(48, 0x19a4c116, 0, 1, 2, 3, 4, 5, 6, 7) + SHA256ROUND1(49, 0x1e376c08, 7, 0, 1, 2, 3, 4, 5, 6) + SHA256ROUND1(50, 0x2748774c, 6, 7, 0, 1, 2, 3, 4, 5) + SHA256ROUND1(51, 0x34b0bcb5, 5, 6, 7, 0, 1, 2, 3, 4) + SHA256ROUND1(52, 0x391c0cb3, 4, 5, 6, 7, 0, 1, 2, 3) + SHA256ROUND1(53, 0x4ed8aa4a, 3, 4, 5, 6, 7, 0, 1, 2) + SHA256ROUND1(54, 0x5b9cca4f, 2, 3, 4, 5, 6, 7, 0, 1) + SHA256ROUND1(55, 0x682e6ff3, 1, 2, 3, 4, 5, 6, 7, 0) + SHA256ROUND1(56, 0x748f82ee, 0, 1, 2, 3, 4, 5, 6, 7) + SHA256ROUND1(57, 0x78a5636f, 7, 0, 1, 2, 3, 4, 5, 6) + SHA256ROUND1(58, 0x84c87814, 6, 7, 0, 1, 2, 3, 4, 5) + SHA256ROUND1(59, 0x8cc70208, 5, 6, 7, 0, 1, 2, 3, 4) + SHA256ROUND1(60, 0x90befffa, 4, 5, 6, 7, 0, 1, 2, 3) + SHA256ROUND1(61, 0xa4506ceb, 3, 4, 5, 6, 7, 0, 1, 2) + SHA256ROUND1(62, 0xbef9a3f7, 2, 3, 4, 5, 6, 7, 0, 1) + SHA256ROUND1(63, 0xc67178f2, 1, 2, 3, 4, 5, 6, 7, 0) + + MOVL dig+0(FP), BP + MOVL (0*4)(BP), AX // H0 = a + H0 + ADDL (0*4)(DI), AX + MOVL AX, (0*4)(DI) + MOVL AX, (0*4)(BP) + MOVL (1*4)(BP), BX // H1 = b + H1 + ADDL (1*4)(DI), BX + MOVL BX, (1*4)(DI) + MOVL BX, (1*4)(BP) + MOVL (2*4)(BP), CX // H2 = c + H2 + ADDL (2*4)(DI), CX + MOVL CX, (2*4)(DI) + MOVL CX, (2*4)(BP) + MOVL (3*4)(BP), DX // H3 = d + H3 + ADDL (3*4)(DI), DX + MOVL DX, (3*4)(DI) + MOVL DX, (3*4)(BP) + MOVL (4*4)(BP), AX // H4 = e + H4 + ADDL (4*4)(DI), AX + MOVL AX, (4*4)(DI) + MOVL AX, (4*4)(BP) + MOVL (5*4)(BP), BX // H5 = f + H5 + ADDL (5*4)(DI), BX + MOVL BX, (5*4)(DI) + MOVL BX, (5*4)(BP) + MOVL (6*4)(BP), CX // H6 = g + H6 + ADDL (6*4)(DI), CX + MOVL CX, (6*4)(DI) + MOVL CX, (6*4)(BP) + MOVL (7*4)(BP), DX // H7 = h + H7 + ADDL (7*4)(DI), DX + MOVL DX, (7*4)(DI) + MOVL DX, (7*4)(BP) + + ADDL $64, SI + CMPL SI, 288(SP) + JB loop + +end: + RET diff --git a/src/crypto/sha256/sha256block_amd64.go b/src/crypto/sha256/sha256block_amd64.go new file mode 100644 index 0000000..27464e2 --- /dev/null +++ b/src/crypto/sha256/sha256block_amd64.go @@ -0,0 +1,9 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha256 + +import "internal/cpu" + +var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2 diff --git a/src/crypto/sha256/sha256block_amd64.s b/src/crypto/sha256/sha256block_amd64.s new file mode 100644 index 0000000..f6af47c --- /dev/null +++ b/src/crypto/sha256/sha256block_amd64.s @@ -0,0 +1,1031 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// SHA256 block routine. See sha256block.go for Go equivalent. +// +// The algorithm is detailed in FIPS 180-4: +// +// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + +// The avx2-version is described in an Intel White-Paper: +// "Fast SHA-256 Implementations on Intel Architecture Processors" +// To find it, surf to http://www.intel.com/p/en_US/embedded +// and search for that title. +// AVX2 version by Intel, same algorithm as code in Linux kernel: +// https://github.com/torvalds/linux/blob/master/arch/x86/crypto/sha256-avx2-asm.S +// by +// James Guilford +// Kirk Yap +// Tim Chen + +// Wt = Mt; for 0 <= t <= 15 +// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 +// +// a = H0 +// b = H1 +// c = H2 +// d = H3 +// e = H4 +// f = H5 +// g = H6 +// h = H7 +// +// for t = 0 to 63 { +// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt +// T2 = BIGSIGMA0(a) + Maj(a,b,c) +// h = g +// g = f +// f = e +// e = d + T1 +// d = c +// c = b +// b = a +// a = T1 + T2 +// } +// +// H0 = a + H0 +// H1 = b + H1 +// H2 = c + H2 +// H3 = d + H3 +// H4 = e + H4 +// H5 = f + H5 +// H6 = g + H6 +// H7 = h + H7 + +// Wt = Mt; for 0 <= t <= 15 +#define MSGSCHEDULE0(index) \ + MOVL (index*4)(SI), AX; \ + BSWAPL AX; \ + MOVL AX, (index*4)(BP) + +// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 +// SIGMA0(x) = ROTR(7,x) XOR ROTR(18,x) XOR SHR(3,x) +// SIGMA1(x) = ROTR(17,x) XOR ROTR(19,x) XOR SHR(10,x) +#define MSGSCHEDULE1(index) \ + MOVL ((index-2)*4)(BP), AX; \ + MOVL AX, CX; \ + RORL $17, AX; \ + MOVL CX, DX; \ + RORL $19, CX; \ + SHRL $10, DX; \ + MOVL ((index-15)*4)(BP), BX; \ + XORL CX, AX; \ + MOVL BX, CX; \ + XORL DX, AX; \ + RORL $7, BX; \ + MOVL CX, DX; \ + SHRL $3, DX; \ + RORL $18, CX; \ + ADDL ((index-7)*4)(BP), AX; \ + XORL CX, BX; \ + XORL DX, BX; \ + ADDL ((index-16)*4)(BP), BX; \ + ADDL BX, AX; \ + MOVL AX, ((index)*4)(BP) + +// Calculate T1 in AX - uses AX, CX and DX registers. +// h is also used as an accumulator. Wt is passed in AX. +// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt +// BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x) +// Ch(x, y, z) = (x AND y) XOR (NOT x AND z) +#define SHA256T1(const, e, f, g, h) \ + ADDL AX, h; \ + MOVL e, AX; \ + ADDL $const, h; \ + MOVL e, CX; \ + RORL $6, AX; \ + MOVL e, DX; \ + RORL $11, CX; \ + XORL CX, AX; \ + MOVL e, CX; \ + RORL $25, DX; \ + ANDL f, CX; \ + XORL AX, DX; \ + MOVL e, AX; \ + NOTL AX; \ + ADDL DX, h; \ + ANDL g, AX; \ + XORL CX, AX; \ + ADDL h, AX + +// Calculate T2 in BX - uses BX, CX, DX and DI registers. +// T2 = BIGSIGMA0(a) + Maj(a, b, c) +// BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x) +// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) +#define SHA256T2(a, b, c) \ + MOVL a, DI; \ + MOVL c, BX; \ + RORL $2, DI; \ + MOVL a, DX; \ + ANDL b, BX; \ + RORL $13, DX; \ + MOVL a, CX; \ + ANDL c, CX; \ + XORL DX, DI; \ + XORL CX, BX; \ + MOVL a, DX; \ + MOVL b, CX; \ + RORL $22, DX; \ + ANDL a, CX; \ + XORL CX, BX; \ + XORL DX, DI; \ + ADDL DI, BX + +// Calculate T1 and T2, then e = d + T1 and a = T1 + T2. +// The values for e and a are stored in d and h, ready for rotation. +#define SHA256ROUND(index, const, a, b, c, d, e, f, g, h) \ + SHA256T1(const, e, f, g, h); \ + SHA256T2(a, b, c); \ + MOVL BX, h; \ + ADDL AX, d; \ + ADDL AX, h + +#define SHA256ROUND0(index, const, a, b, c, d, e, f, g, h) \ + MSGSCHEDULE0(index); \ + SHA256ROUND(index, const, a, b, c, d, e, f, g, h) + +#define SHA256ROUND1(index, const, a, b, c, d, e, f, g, h) \ + MSGSCHEDULE1(index); \ + SHA256ROUND(index, const, a, b, c, d, e, f, g, h) + + +// Definitions for AVX2 version + +// addm (mem), reg +// Add reg to mem using reg-mem add and store +#define addm(P1, P2) \ + ADDL P2, P1; \ + MOVL P1, P2 + +#define XDWORD0 Y4 +#define XDWORD1 Y5 +#define XDWORD2 Y6 +#define XDWORD3 Y7 + +#define XWORD0 X4 +#define XWORD1 X5 +#define XWORD2 X6 +#define XWORD3 X7 + +#define XTMP0 Y0 +#define XTMP1 Y1 +#define XTMP2 Y2 +#define XTMP3 Y3 +#define XTMP4 Y8 +#define XTMP5 Y11 + +#define XFER Y9 + +#define BYTE_FLIP_MASK Y13 // mask to convert LE -> BE +#define X_BYTE_FLIP_MASK X13 + +#define NUM_BYTES DX +#define INP DI + +#define CTX SI // Beginning of digest in memory (a, b, c, ... , h) + +#define a AX +#define b BX +#define c CX +#define d R8 +#define e DX +#define f R9 +#define g R10 +#define h R11 + +#define old_h R11 + +#define TBL BP + +#define SRND SI // SRND is same register as CTX + +#define T1 R12 + +#define y0 R13 +#define y1 R14 +#define y2 R15 +#define y3 DI + +// Offsets +#define XFER_SIZE 2*64*4 +#define INP_END_SIZE 8 +#define INP_SIZE 8 + +#define _XFER 0 +#define _INP_END _XFER + XFER_SIZE +#define _INP _INP_END + INP_END_SIZE +#define STACK_SIZE _INP + INP_SIZE + +#define ROUND_AND_SCHED_N_0(disp, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) \ + ; \ // ############################# RND N + 0 ############################// + MOVL a, y3; \ // y3 = a // MAJA + RORXL $25, e, y0; \ // y0 = e >> 25 // S1A + RORXL $11, e, y1; \ // y1 = e >> 11 // S1B + ; \ + ADDL (disp + 0*4)(SP)(SRND*1), h; \ // h = k + w + h // disp = k + w + ORL c, y3; \ // y3 = a|c // MAJA + VPALIGNR $4, XDWORD2, XDWORD3, XTMP0; \ // XTMP0 = W[-7] + MOVL f, y2; \ // y2 = f // CH + RORXL $13, a, T1; \ // T1 = a >> 13 // S0B + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1 + XORL g, y2; \ // y2 = f^g // CH + VPADDD XDWORD0, XTMP0, XTMP0; \ // XTMP0 = W[-7] + W[-16] // y1 = (e >> 6) // S1 + RORXL $6, e, y1; \ // y1 = (e >> 6) // S1 + ; \ + ANDL e, y2; \ // y2 = (f^g)&e // CH + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1 + RORXL $22, a, y1; \ // y1 = a >> 22 // S0A + ADDL h, d; \ // d = k + w + h + d // -- + ; \ + ANDL b, y3; \ // y3 = (a|c)&b // MAJA + VPALIGNR $4, XDWORD0, XDWORD1, XTMP1; \ // XTMP1 = W[-15] + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0 + RORXL $2, a, T1; \ // T1 = (a >> 2) // S0 + ; \ + XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH + VPSRLD $7, XTMP1, XTMP2; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0 + MOVL a, T1; \ // T1 = a // MAJB + ANDL c, T1; \ // T1 = a&c // MAJB + ; \ + ADDL y0, y2; \ // y2 = S1 + CH // -- + VPSLLD $(32-7), XTMP1, XTMP3; \ + ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ + ADDL y1, h; \ // h = k + w + h + S0 // -- + ; \ + ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // -- + VPOR XTMP2, XTMP3, XTMP3; \ // XTMP3 = W[-15] ror 7 + ; \ + VPSRLD $18, XTMP1, XTMP2; \ + ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// -- + ADDL y3, h // h = t1 + S0 + MAJ // -- + +#define ROUND_AND_SCHED_N_1(disp, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) \ + ; \ // ################################### RND N + 1 ############################ + ; \ + MOVL a, y3; \ // y3 = a // MAJA + RORXL $25, e, y0; \ // y0 = e >> 25 // S1A + RORXL $11, e, y1; \ // y1 = e >> 11 // S1B + ADDL (disp + 1*4)(SP)(SRND*1), h; \ // h = k + w + h // -- + ORL c, y3; \ // y3 = a|c // MAJA + ; \ + VPSRLD $3, XTMP1, XTMP4; \ // XTMP4 = W[-15] >> 3 + MOVL f, y2; \ // y2 = f // CH + RORXL $13, a, T1; \ // T1 = a >> 13 // S0B + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1 + XORL g, y2; \ // y2 = f^g // CH + ; \ + RORXL $6, e, y1; \ // y1 = (e >> 6) // S1 + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1 + RORXL $22, a, y1; \ // y1 = a >> 22 // S0A + ANDL e, y2; \ // y2 = (f^g)&e // CH + ADDL h, d; \ // d = k + w + h + d // -- + ; \ + VPSLLD $(32-18), XTMP1, XTMP1; \ + ANDL b, y3; \ // y3 = (a|c)&b // MAJA + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0 + ; \ + VPXOR XTMP1, XTMP3, XTMP3; \ + RORXL $2, a, T1; \ // T1 = (a >> 2) // S0 + XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH + ; \ + VPXOR XTMP2, XTMP3, XTMP3; \ // XTMP3 = W[-15] ror 7 ^ W[-15] ror 18 + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0 + MOVL a, T1; \ // T1 = a // MAJB + ANDL c, T1; \ // T1 = a&c // MAJB + ADDL y0, y2; \ // y2 = S1 + CH // -- + ; \ + VPXOR XTMP4, XTMP3, XTMP1; \ // XTMP1 = s0 + VPSHUFD $0xFA, XDWORD3, XTMP2; \ // XTMP2 = W[-2] {BBAA} + ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ + ADDL y1, h; \ // h = k + w + h + S0 // -- + ; \ + VPADDD XTMP1, XTMP0, XTMP0; \ // XTMP0 = W[-16] + W[-7] + s0 + ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // -- + ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// -- + ADDL y3, h; \ // h = t1 + S0 + MAJ // -- + ; \ + VPSRLD $10, XTMP2, XTMP4 // XTMP4 = W[-2] >> 10 {BBAA} + +#define ROUND_AND_SCHED_N_2(disp, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) \ + ; \ // ################################### RND N + 2 ############################ + ; \ + MOVL a, y3; \ // y3 = a // MAJA + RORXL $25, e, y0; \ // y0 = e >> 25 // S1A + ADDL (disp + 2*4)(SP)(SRND*1), h; \ // h = k + w + h // -- + ; \ + VPSRLQ $19, XTMP2, XTMP3; \ // XTMP3 = W[-2] ror 19 {xBxA} + RORXL $11, e, y1; \ // y1 = e >> 11 // S1B + ORL c, y3; \ // y3 = a|c // MAJA + MOVL f, y2; \ // y2 = f // CH + XORL g, y2; \ // y2 = f^g // CH + ; \ + RORXL $13, a, T1; \ // T1 = a >> 13 // S0B + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1 + VPSRLQ $17, XTMP2, XTMP2; \ // XTMP2 = W[-2] ror 17 {xBxA} + ANDL e, y2; \ // y2 = (f^g)&e // CH + ; \ + RORXL $6, e, y1; \ // y1 = (e >> 6) // S1 + VPXOR XTMP3, XTMP2, XTMP2; \ + ADDL h, d; \ // d = k + w + h + d // -- + ANDL b, y3; \ // y3 = (a|c)&b // MAJA + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1 + RORXL $22, a, y1; \ // y1 = a >> 22 // S0A + VPXOR XTMP2, XTMP4, XTMP4; \ // XTMP4 = s1 {xBxA} + XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH + ; \ + VPSHUFB shuff_00BA<>(SB), XTMP4, XTMP4;\ // XTMP4 = s1 {00BA} + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0 + RORXL $2, a, T1; \ // T1 = (a >> 2) // S0 + VPADDD XTMP4, XTMP0, XTMP0; \ // XTMP0 = {..., ..., W[1], W[0]} + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0 + MOVL a, T1; \ // T1 = a // MAJB + ANDL c, T1; \ // T1 = a&c // MAJB + ADDL y0, y2; \ // y2 = S1 + CH // -- + VPSHUFD $80, XTMP0, XTMP2; \ // XTMP2 = W[-2] {DDCC} + ; \ + ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ + ADDL y1, h; \ // h = k + w + h + S0 // -- + ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // -- + ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// -- + ; \ + ADDL y3, h // h = t1 + S0 + MAJ // -- + +#define ROUND_AND_SCHED_N_3(disp, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) \ + ; \ // ################################### RND N + 3 ############################ + ; \ + MOVL a, y3; \ // y3 = a // MAJA + RORXL $25, e, y0; \ // y0 = e >> 25 // S1A + RORXL $11, e, y1; \ // y1 = e >> 11 // S1B + ADDL (disp + 3*4)(SP)(SRND*1), h; \ // h = k + w + h // -- + ORL c, y3; \ // y3 = a|c // MAJA + ; \ + VPSRLD $10, XTMP2, XTMP5; \ // XTMP5 = W[-2] >> 10 {DDCC} + MOVL f, y2; \ // y2 = f // CH + RORXL $13, a, T1; \ // T1 = a >> 13 // S0B + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1 + XORL g, y2; \ // y2 = f^g // CH + ; \ + VPSRLQ $19, XTMP2, XTMP3; \ // XTMP3 = W[-2] ror 19 {xDxC} + RORXL $6, e, y1; \ // y1 = (e >> 6) // S1 + ANDL e, y2; \ // y2 = (f^g)&e // CH + ADDL h, d; \ // d = k + w + h + d // -- + ANDL b, y3; \ // y3 = (a|c)&b // MAJA + ; \ + VPSRLQ $17, XTMP2, XTMP2; \ // XTMP2 = W[-2] ror 17 {xDxC} + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1 + XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH + ; \ + VPXOR XTMP3, XTMP2, XTMP2; \ + RORXL $22, a, y1; \ // y1 = a >> 22 // S0A + ADDL y0, y2; \ // y2 = S1 + CH // -- + ; \ + VPXOR XTMP2, XTMP5, XTMP5; \ // XTMP5 = s1 {xDxC} + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0 + ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // -- + ; \ + RORXL $2, a, T1; \ // T1 = (a >> 2) // S0 + ; \ + VPSHUFB shuff_DC00<>(SB), XTMP5, XTMP5;\ // XTMP5 = s1 {DC00} + ; \ + VPADDD XTMP0, XTMP5, XDWORD0; \ // XDWORD0 = {W[3], W[2], W[1], W[0]} + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0 + MOVL a, T1; \ // T1 = a // MAJB + ANDL c, T1; \ // T1 = a&c // MAJB + ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ + ; \ + ADDL y1, h; \ // h = k + w + h + S0 // -- + ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// -- + ADDL y3, h // h = t1 + S0 + MAJ // -- + +#define DO_ROUND_N_0(disp, a, b, c, d, e, f, g, h, old_h) \ + ; \ // ################################### RND N + 0 ########################### + MOVL f, y2; \ // y2 = f // CH + RORXL $25, e, y0; \ // y0 = e >> 25 // S1A + RORXL $11, e, y1; \ // y1 = e >> 11 // S1B + XORL g, y2; \ // y2 = f^g // CH + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1 + RORXL $6, e, y1; \ // y1 = (e >> 6) // S1 + ANDL e, y2; \ // y2 = (f^g)&e // CH + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1 + RORXL $13, a, T1; \ // T1 = a >> 13 // S0B + XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH + RORXL $22, a, y1; \ // y1 = a >> 22 // S0A + MOVL a, y3; \ // y3 = a // MAJA + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0 + RORXL $2, a, T1; \ // T1 = (a >> 2) // S0 + ADDL (disp + 0*4)(SP)(SRND*1), h; \ // h = k + w + h // -- + ORL c, y3; \ // y3 = a|c // MAJA + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0 + MOVL a, T1; \ // T1 = a // MAJB + ANDL b, y3; \ // y3 = (a|c)&b // MAJA + ANDL c, T1; \ // T1 = a&c // MAJB + ADDL y0, y2; \ // y2 = S1 + CH // -- + ; \ + ADDL h, d; \ // d = k + w + h + d // -- + ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ + ADDL y1, h; \ // h = k + w + h + S0 // -- + ADDL y2, d // d = k + w + h + d + S1 + CH = d + t1 // -- + +#define DO_ROUND_N_1(disp, a, b, c, d, e, f, g, h, old_h) \ + ; \ // ################################### RND N + 1 ########################### + ADDL y2, old_h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0 // -- + MOVL f, y2; \ // y2 = f // CH + RORXL $25, e, y0; \ // y0 = e >> 25 // S1A + RORXL $11, e, y1; \ // y1 = e >> 11 // S1B + XORL g, y2; \ // y2 = f^g // CH + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1 + RORXL $6, e, y1; \ // y1 = (e >> 6) // S1 + ANDL e, y2; \ // y2 = (f^g)&e // CH + ADDL y3, old_h; \ // h = t1 + S0 + MAJ // -- + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1 + RORXL $13, a, T1; \ // T1 = a >> 13 // S0B + XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH + RORXL $22, a, y1; \ // y1 = a >> 22 // S0A + MOVL a, y3; \ // y3 = a // MAJA + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0 + RORXL $2, a, T1; \ // T1 = (a >> 2) // S0 + ADDL (disp + 1*4)(SP)(SRND*1), h; \ // h = k + w + h // -- + ORL c, y3; \ // y3 = a|c // MAJA + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0 + MOVL a, T1; \ // T1 = a // MAJB + ANDL b, y3; \ // y3 = (a|c)&b // MAJA + ANDL c, T1; \ // T1 = a&c // MAJB + ADDL y0, y2; \ // y2 = S1 + CH // -- + ; \ + ADDL h, d; \ // d = k + w + h + d // -- + ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ + ADDL y1, h; \ // h = k + w + h + S0 // -- + ; \ + ADDL y2, d // d = k + w + h + d + S1 + CH = d + t1 // -- + +#define DO_ROUND_N_2(disp, a, b, c, d, e, f, g, h, old_h) \ + ; \ // ################################### RND N + 2 ############################## + ADDL y2, old_h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// -- + MOVL f, y2; \ // y2 = f // CH + RORXL $25, e, y0; \ // y0 = e >> 25 // S1A + RORXL $11, e, y1; \ // y1 = e >> 11 // S1B + XORL g, y2; \ // y2 = f^g // CH + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1 + RORXL $6, e, y1; \ // y1 = (e >> 6) // S1 + ANDL e, y2; \ // y2 = (f^g)&e // CH + ADDL y3, old_h; \ // h = t1 + S0 + MAJ // -- + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1 + RORXL $13, a, T1; \ // T1 = a >> 13 // S0B + XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH + RORXL $22, a, y1; \ // y1 = a >> 22 // S0A + MOVL a, y3; \ // y3 = a // MAJA + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0 + RORXL $2, a, T1; \ // T1 = (a >> 2) // S0 + ADDL (disp + 2*4)(SP)(SRND*1), h; \ // h = k + w + h // -- + ORL c, y3; \ // y3 = a|c // MAJA + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0 + MOVL a, T1; \ // T1 = a // MAJB + ANDL b, y3; \ // y3 = (a|c)&b // MAJA + ANDL c, T1; \ // T1 = a&c // MAJB + ADDL y0, y2; \ // y2 = S1 + CH // -- + ; \ + ADDL h, d; \ // d = k + w + h + d // -- + ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ + ADDL y1, h; \ // h = k + w + h + S0 // -- + ; \ + ADDL y2, d // d = k + w + h + d + S1 + CH = d + t1 // -- + +#define DO_ROUND_N_3(disp, a, b, c, d, e, f, g, h, old_h) \ + ; \ // ################################### RND N + 3 ########################### + ADDL y2, old_h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// -- + MOVL f, y2; \ // y2 = f // CH + RORXL $25, e, y0; \ // y0 = e >> 25 // S1A + RORXL $11, e, y1; \ // y1 = e >> 11 // S1B + XORL g, y2; \ // y2 = f^g // CH + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1 + RORXL $6, e, y1; \ // y1 = (e >> 6) // S1 + ANDL e, y2; \ // y2 = (f^g)&e // CH + ADDL y3, old_h; \ // h = t1 + S0 + MAJ // -- + ; \ + XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1 + RORXL $13, a, T1; \ // T1 = a >> 13 // S0B + XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH + RORXL $22, a, y1; \ // y1 = a >> 22 // S0A + MOVL a, y3; \ // y3 = a // MAJA + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0 + RORXL $2, a, T1; \ // T1 = (a >> 2) // S0 + ADDL (disp + 3*4)(SP)(SRND*1), h; \ // h = k + w + h // -- + ORL c, y3; \ // y3 = a|c // MAJA + ; \ + XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0 + MOVL a, T1; \ // T1 = a // MAJB + ANDL b, y3; \ // y3 = (a|c)&b // MAJA + ANDL c, T1; \ // T1 = a&c // MAJB + ADDL y0, y2; \ // y2 = S1 + CH // -- + ; \ + ADDL h, d; \ // d = k + w + h + d // -- + ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ + ADDL y1, h; \ // h = k + w + h + S0 // -- + ; \ + ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // -- + ; \ + ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// -- + ; \ + ADDL y3, h // h = t1 + S0 + MAJ // -- + +TEXT ·block(SB), 0, $536-32 + CMPB ·useAVX2(SB), $1 + JE avx2 + + MOVQ p_base+8(FP), SI + MOVQ p_len+16(FP), DX + SHRQ $6, DX + SHLQ $6, DX + + LEAQ (SI)(DX*1), DI + MOVQ DI, 256(SP) + CMPQ SI, DI + JEQ end + + MOVQ dig+0(FP), BP + MOVL (0*4)(BP), R8 // a = H0 + MOVL (1*4)(BP), R9 // b = H1 + MOVL (2*4)(BP), R10 // c = H2 + MOVL (3*4)(BP), R11 // d = H3 + MOVL (4*4)(BP), R12 // e = H4 + MOVL (5*4)(BP), R13 // f = H5 + MOVL (6*4)(BP), R14 // g = H6 + MOVL (7*4)(BP), R15 // h = H7 + +loop: + MOVQ SP, BP + + SHA256ROUND0(0, 0x428a2f98, R8, R9, R10, R11, R12, R13, R14, R15) + SHA256ROUND0(1, 0x71374491, R15, R8, R9, R10, R11, R12, R13, R14) + SHA256ROUND0(2, 0xb5c0fbcf, R14, R15, R8, R9, R10, R11, R12, R13) + SHA256ROUND0(3, 0xe9b5dba5, R13, R14, R15, R8, R9, R10, R11, R12) + SHA256ROUND0(4, 0x3956c25b, R12, R13, R14, R15, R8, R9, R10, R11) + SHA256ROUND0(5, 0x59f111f1, R11, R12, R13, R14, R15, R8, R9, R10) + SHA256ROUND0(6, 0x923f82a4, R10, R11, R12, R13, R14, R15, R8, R9) + SHA256ROUND0(7, 0xab1c5ed5, R9, R10, R11, R12, R13, R14, R15, R8) + SHA256ROUND0(8, 0xd807aa98, R8, R9, R10, R11, R12, R13, R14, R15) + SHA256ROUND0(9, 0x12835b01, R15, R8, R9, R10, R11, R12, R13, R14) + SHA256ROUND0(10, 0x243185be, R14, R15, R8, R9, R10, R11, R12, R13) + SHA256ROUND0(11, 0x550c7dc3, R13, R14, R15, R8, R9, R10, R11, R12) + SHA256ROUND0(12, 0x72be5d74, R12, R13, R14, R15, R8, R9, R10, R11) + SHA256ROUND0(13, 0x80deb1fe, R11, R12, R13, R14, R15, R8, R9, R10) + SHA256ROUND0(14, 0x9bdc06a7, R10, R11, R12, R13, R14, R15, R8, R9) + SHA256ROUND0(15, 0xc19bf174, R9, R10, R11, R12, R13, R14, R15, R8) + + SHA256ROUND1(16, 0xe49b69c1, R8, R9, R10, R11, R12, R13, R14, R15) + SHA256ROUND1(17, 0xefbe4786, R15, R8, R9, R10, R11, R12, R13, R14) + SHA256ROUND1(18, 0x0fc19dc6, R14, R15, R8, R9, R10, R11, R12, R13) + SHA256ROUND1(19, 0x240ca1cc, R13, R14, R15, R8, R9, R10, R11, R12) + SHA256ROUND1(20, 0x2de92c6f, R12, R13, R14, R15, R8, R9, R10, R11) + SHA256ROUND1(21, 0x4a7484aa, R11, R12, R13, R14, R15, R8, R9, R10) + SHA256ROUND1(22, 0x5cb0a9dc, R10, R11, R12, R13, R14, R15, R8, R9) + SHA256ROUND1(23, 0x76f988da, R9, R10, R11, R12, R13, R14, R15, R8) + SHA256ROUND1(24, 0x983e5152, R8, R9, R10, R11, R12, R13, R14, R15) + SHA256ROUND1(25, 0xa831c66d, R15, R8, R9, R10, R11, R12, R13, R14) + SHA256ROUND1(26, 0xb00327c8, R14, R15, R8, R9, R10, R11, R12, R13) + SHA256ROUND1(27, 0xbf597fc7, R13, R14, R15, R8, R9, R10, R11, R12) + SHA256ROUND1(28, 0xc6e00bf3, R12, R13, R14, R15, R8, R9, R10, R11) + SHA256ROUND1(29, 0xd5a79147, R11, R12, R13, R14, R15, R8, R9, R10) + SHA256ROUND1(30, 0x06ca6351, R10, R11, R12, R13, R14, R15, R8, R9) + SHA256ROUND1(31, 0x14292967, R9, R10, R11, R12, R13, R14, R15, R8) + SHA256ROUND1(32, 0x27b70a85, R8, R9, R10, R11, R12, R13, R14, R15) + SHA256ROUND1(33, 0x2e1b2138, R15, R8, R9, R10, R11, R12, R13, R14) + SHA256ROUND1(34, 0x4d2c6dfc, R14, R15, R8, R9, R10, R11, R12, R13) + SHA256ROUND1(35, 0x53380d13, R13, R14, R15, R8, R9, R10, R11, R12) + SHA256ROUND1(36, 0x650a7354, R12, R13, R14, R15, R8, R9, R10, R11) + SHA256ROUND1(37, 0x766a0abb, R11, R12, R13, R14, R15, R8, R9, R10) + SHA256ROUND1(38, 0x81c2c92e, R10, R11, R12, R13, R14, R15, R8, R9) + SHA256ROUND1(39, 0x92722c85, R9, R10, R11, R12, R13, R14, R15, R8) + SHA256ROUND1(40, 0xa2bfe8a1, R8, R9, R10, R11, R12, R13, R14, R15) + SHA256ROUND1(41, 0xa81a664b, R15, R8, R9, R10, R11, R12, R13, R14) + SHA256ROUND1(42, 0xc24b8b70, R14, R15, R8, R9, R10, R11, R12, R13) + SHA256ROUND1(43, 0xc76c51a3, R13, R14, R15, R8, R9, R10, R11, R12) + SHA256ROUND1(44, 0xd192e819, R12, R13, R14, R15, R8, R9, R10, R11) + SHA256ROUND1(45, 0xd6990624, R11, R12, R13, R14, R15, R8, R9, R10) + SHA256ROUND1(46, 0xf40e3585, R10, R11, R12, R13, R14, R15, R8, R9) + SHA256ROUND1(47, 0x106aa070, R9, R10, R11, R12, R13, R14, R15, R8) + SHA256ROUND1(48, 0x19a4c116, R8, R9, R10, R11, R12, R13, R14, R15) + SHA256ROUND1(49, 0x1e376c08, R15, R8, R9, R10, R11, R12, R13, R14) + SHA256ROUND1(50, 0x2748774c, R14, R15, R8, R9, R10, R11, R12, R13) + SHA256ROUND1(51, 0x34b0bcb5, R13, R14, R15, R8, R9, R10, R11, R12) + SHA256ROUND1(52, 0x391c0cb3, R12, R13, R14, R15, R8, R9, R10, R11) + SHA256ROUND1(53, 0x4ed8aa4a, R11, R12, R13, R14, R15, R8, R9, R10) + SHA256ROUND1(54, 0x5b9cca4f, R10, R11, R12, R13, R14, R15, R8, R9) + SHA256ROUND1(55, 0x682e6ff3, R9, R10, R11, R12, R13, R14, R15, R8) + SHA256ROUND1(56, 0x748f82ee, R8, R9, R10, R11, R12, R13, R14, R15) + SHA256ROUND1(57, 0x78a5636f, R15, R8, R9, R10, R11, R12, R13, R14) + SHA256ROUND1(58, 0x84c87814, R14, R15, R8, R9, R10, R11, R12, R13) + SHA256ROUND1(59, 0x8cc70208, R13, R14, R15, R8, R9, R10, R11, R12) + SHA256ROUND1(60, 0x90befffa, R12, R13, R14, R15, R8, R9, R10, R11) + SHA256ROUND1(61, 0xa4506ceb, R11, R12, R13, R14, R15, R8, R9, R10) + SHA256ROUND1(62, 0xbef9a3f7, R10, R11, R12, R13, R14, R15, R8, R9) + SHA256ROUND1(63, 0xc67178f2, R9, R10, R11, R12, R13, R14, R15, R8) + + MOVQ dig+0(FP), BP + ADDL (0*4)(BP), R8 // H0 = a + H0 + MOVL R8, (0*4)(BP) + ADDL (1*4)(BP), R9 // H1 = b + H1 + MOVL R9, (1*4)(BP) + ADDL (2*4)(BP), R10 // H2 = c + H2 + MOVL R10, (2*4)(BP) + ADDL (3*4)(BP), R11 // H3 = d + H3 + MOVL R11, (3*4)(BP) + ADDL (4*4)(BP), R12 // H4 = e + H4 + MOVL R12, (4*4)(BP) + ADDL (5*4)(BP), R13 // H5 = f + H5 + MOVL R13, (5*4)(BP) + ADDL (6*4)(BP), R14 // H6 = g + H6 + MOVL R14, (6*4)(BP) + ADDL (7*4)(BP), R15 // H7 = h + H7 + MOVL R15, (7*4)(BP) + + ADDQ $64, SI + CMPQ SI, 256(SP) + JB loop + +end: + RET + +avx2: + MOVQ dig+0(FP), CTX // d.h[8] + MOVQ p_base+8(FP), INP + MOVQ p_len+16(FP), NUM_BYTES + + LEAQ -64(INP)(NUM_BYTES*1), NUM_BYTES // Pointer to the last block + MOVQ NUM_BYTES, _INP_END(SP) + + CMPQ NUM_BYTES, INP + JE avx2_only_one_block + + // Load initial digest + MOVL 0(CTX), a // a = H0 + MOVL 4(CTX), b // b = H1 + MOVL 8(CTX), c // c = H2 + MOVL 12(CTX), d // d = H3 + MOVL 16(CTX), e // e = H4 + MOVL 20(CTX), f // f = H5 + MOVL 24(CTX), g // g = H6 + MOVL 28(CTX), h // h = H7 + +avx2_loop0: // at each iteration works with one block (512 bit) + + VMOVDQU (0*32)(INP), XTMP0 + VMOVDQU (1*32)(INP), XTMP1 + VMOVDQU (2*32)(INP), XTMP2 + VMOVDQU (3*32)(INP), XTMP3 + + VMOVDQU flip_mask<>(SB), BYTE_FLIP_MASK + + // Apply Byte Flip Mask: LE -> BE + VPSHUFB BYTE_FLIP_MASK, XTMP0, XTMP0 + VPSHUFB BYTE_FLIP_MASK, XTMP1, XTMP1 + VPSHUFB BYTE_FLIP_MASK, XTMP2, XTMP2 + VPSHUFB BYTE_FLIP_MASK, XTMP3, XTMP3 + + // Transpose data into high/low parts + VPERM2I128 $0x20, XTMP2, XTMP0, XDWORD0 // w3, w2, w1, w0 + VPERM2I128 $0x31, XTMP2, XTMP0, XDWORD1 // w7, w6, w5, w4 + VPERM2I128 $0x20, XTMP3, XTMP1, XDWORD2 // w11, w10, w9, w8 + VPERM2I128 $0x31, XTMP3, XTMP1, XDWORD3 // w15, w14, w13, w12 + + MOVQ $K256<>(SB), TBL // Loading address of table with round-specific constants + +avx2_last_block_enter: + ADDQ $64, INP + MOVQ INP, _INP(SP) + XORQ SRND, SRND + +avx2_loop1: // for w0 - w47 + // Do 4 rounds and scheduling + VPADDD 0*32(TBL)(SRND*1), XDWORD0, XFER + VMOVDQU XFER, (_XFER + 0*32)(SP)(SRND*1) + ROUND_AND_SCHED_N_0(_XFER + 0*32, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) + ROUND_AND_SCHED_N_1(_XFER + 0*32, h, a, b, c, d, e, f, g, XDWORD0, XDWORD1, XDWORD2, XDWORD3) + ROUND_AND_SCHED_N_2(_XFER + 0*32, g, h, a, b, c, d, e, f, XDWORD0, XDWORD1, XDWORD2, XDWORD3) + ROUND_AND_SCHED_N_3(_XFER + 0*32, f, g, h, a, b, c, d, e, XDWORD0, XDWORD1, XDWORD2, XDWORD3) + + // Do 4 rounds and scheduling + VPADDD 1*32(TBL)(SRND*1), XDWORD1, XFER + VMOVDQU XFER, (_XFER + 1*32)(SP)(SRND*1) + ROUND_AND_SCHED_N_0(_XFER + 1*32, e, f, g, h, a, b, c, d, XDWORD1, XDWORD2, XDWORD3, XDWORD0) + ROUND_AND_SCHED_N_1(_XFER + 1*32, d, e, f, g, h, a, b, c, XDWORD1, XDWORD2, XDWORD3, XDWORD0) + ROUND_AND_SCHED_N_2(_XFER + 1*32, c, d, e, f, g, h, a, b, XDWORD1, XDWORD2, XDWORD3, XDWORD0) + ROUND_AND_SCHED_N_3(_XFER + 1*32, b, c, d, e, f, g, h, a, XDWORD1, XDWORD2, XDWORD3, XDWORD0) + + // Do 4 rounds and scheduling + VPADDD 2*32(TBL)(SRND*1), XDWORD2, XFER + VMOVDQU XFER, (_XFER + 2*32)(SP)(SRND*1) + ROUND_AND_SCHED_N_0(_XFER + 2*32, a, b, c, d, e, f, g, h, XDWORD2, XDWORD3, XDWORD0, XDWORD1) + ROUND_AND_SCHED_N_1(_XFER + 2*32, h, a, b, c, d, e, f, g, XDWORD2, XDWORD3, XDWORD0, XDWORD1) + ROUND_AND_SCHED_N_2(_XFER + 2*32, g, h, a, b, c, d, e, f, XDWORD2, XDWORD3, XDWORD0, XDWORD1) + ROUND_AND_SCHED_N_3(_XFER + 2*32, f, g, h, a, b, c, d, e, XDWORD2, XDWORD3, XDWORD0, XDWORD1) + + // Do 4 rounds and scheduling + VPADDD 3*32(TBL)(SRND*1), XDWORD3, XFER + VMOVDQU XFER, (_XFER + 3*32)(SP)(SRND*1) + ROUND_AND_SCHED_N_0(_XFER + 3*32, e, f, g, h, a, b, c, d, XDWORD3, XDWORD0, XDWORD1, XDWORD2) + ROUND_AND_SCHED_N_1(_XFER + 3*32, d, e, f, g, h, a, b, c, XDWORD3, XDWORD0, XDWORD1, XDWORD2) + ROUND_AND_SCHED_N_2(_XFER + 3*32, c, d, e, f, g, h, a, b, XDWORD3, XDWORD0, XDWORD1, XDWORD2) + ROUND_AND_SCHED_N_3(_XFER + 3*32, b, c, d, e, f, g, h, a, XDWORD3, XDWORD0, XDWORD1, XDWORD2) + + ADDQ $4*32, SRND + CMPQ SRND, $3*4*32 + JB avx2_loop1 + +avx2_loop2: + // w48 - w63 processed with no scheduling (last 16 rounds) + VPADDD 0*32(TBL)(SRND*1), XDWORD0, XFER + VMOVDQU XFER, (_XFER + 0*32)(SP)(SRND*1) + DO_ROUND_N_0(_XFER + 0*32, a, b, c, d, e, f, g, h, h) + DO_ROUND_N_1(_XFER + 0*32, h, a, b, c, d, e, f, g, h) + DO_ROUND_N_2(_XFER + 0*32, g, h, a, b, c, d, e, f, g) + DO_ROUND_N_3(_XFER + 0*32, f, g, h, a, b, c, d, e, f) + + VPADDD 1*32(TBL)(SRND*1), XDWORD1, XFER + VMOVDQU XFER, (_XFER + 1*32)(SP)(SRND*1) + DO_ROUND_N_0(_XFER + 1*32, e, f, g, h, a, b, c, d, e) + DO_ROUND_N_1(_XFER + 1*32, d, e, f, g, h, a, b, c, d) + DO_ROUND_N_2(_XFER + 1*32, c, d, e, f, g, h, a, b, c) + DO_ROUND_N_3(_XFER + 1*32, b, c, d, e, f, g, h, a, b) + + ADDQ $2*32, SRND + + VMOVDQU XDWORD2, XDWORD0 + VMOVDQU XDWORD3, XDWORD1 + + CMPQ SRND, $4*4*32 + JB avx2_loop2 + + MOVQ dig+0(FP), CTX // d.h[8] + MOVQ _INP(SP), INP + + addm( 0(CTX), a) + addm( 4(CTX), b) + addm( 8(CTX), c) + addm( 12(CTX), d) + addm( 16(CTX), e) + addm( 20(CTX), f) + addm( 24(CTX), g) + addm( 28(CTX), h) + + CMPQ _INP_END(SP), INP + JB done_hash + + XORQ SRND, SRND + +avx2_loop3: // Do second block using previously scheduled results + DO_ROUND_N_0(_XFER + 0*32 + 16, a, b, c, d, e, f, g, h, a) + DO_ROUND_N_1(_XFER + 0*32 + 16, h, a, b, c, d, e, f, g, h) + DO_ROUND_N_2(_XFER + 0*32 + 16, g, h, a, b, c, d, e, f, g) + DO_ROUND_N_3(_XFER + 0*32 + 16, f, g, h, a, b, c, d, e, f) + + DO_ROUND_N_0(_XFER + 1*32 + 16, e, f, g, h, a, b, c, d, e) + DO_ROUND_N_1(_XFER + 1*32 + 16, d, e, f, g, h, a, b, c, d) + DO_ROUND_N_2(_XFER + 1*32 + 16, c, d, e, f, g, h, a, b, c) + DO_ROUND_N_3(_XFER + 1*32 + 16, b, c, d, e, f, g, h, a, b) + + ADDQ $2*32, SRND + CMPQ SRND, $4*4*32 + JB avx2_loop3 + + MOVQ dig+0(FP), CTX // d.h[8] + MOVQ _INP(SP), INP + ADDQ $64, INP + + addm( 0(CTX), a) + addm( 4(CTX), b) + addm( 8(CTX), c) + addm( 12(CTX), d) + addm( 16(CTX), e) + addm( 20(CTX), f) + addm( 24(CTX), g) + addm( 28(CTX), h) + + CMPQ _INP_END(SP), INP + JA avx2_loop0 + JB done_hash + +avx2_do_last_block: + + VMOVDQU 0(INP), XWORD0 + VMOVDQU 16(INP), XWORD1 + VMOVDQU 32(INP), XWORD2 + VMOVDQU 48(INP), XWORD3 + + VMOVDQU flip_mask<>(SB), BYTE_FLIP_MASK + + VPSHUFB X_BYTE_FLIP_MASK, XWORD0, XWORD0 + VPSHUFB X_BYTE_FLIP_MASK, XWORD1, XWORD1 + VPSHUFB X_BYTE_FLIP_MASK, XWORD2, XWORD2 + VPSHUFB X_BYTE_FLIP_MASK, XWORD3, XWORD3 + + MOVQ $K256<>(SB), TBL + + JMP avx2_last_block_enter + +avx2_only_one_block: + // Load initial digest + MOVL 0(CTX), a // a = H0 + MOVL 4(CTX), b // b = H1 + MOVL 8(CTX), c // c = H2 + MOVL 12(CTX), d // d = H3 + MOVL 16(CTX), e // e = H4 + MOVL 20(CTX), f // f = H5 + MOVL 24(CTX), g // g = H6 + MOVL 28(CTX), h // h = H7 + + JMP avx2_do_last_block + +done_hash: + VZEROUPPER + RET + +// shuffle byte order from LE to BE +DATA flip_mask<>+0x00(SB)/8, $0x0405060700010203 +DATA flip_mask<>+0x08(SB)/8, $0x0c0d0e0f08090a0b +DATA flip_mask<>+0x10(SB)/8, $0x0405060700010203 +DATA flip_mask<>+0x18(SB)/8, $0x0c0d0e0f08090a0b +GLOBL flip_mask<>(SB), 8, $32 + +// shuffle xBxA -> 00BA +DATA shuff_00BA<>+0x00(SB)/8, $0x0b0a090803020100 +DATA shuff_00BA<>+0x08(SB)/8, $0xFFFFFFFFFFFFFFFF +DATA shuff_00BA<>+0x10(SB)/8, $0x0b0a090803020100 +DATA shuff_00BA<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF +GLOBL shuff_00BA<>(SB), 8, $32 + +// shuffle xDxC -> DC00 +DATA shuff_DC00<>+0x00(SB)/8, $0xFFFFFFFFFFFFFFFF +DATA shuff_DC00<>+0x08(SB)/8, $0x0b0a090803020100 +DATA shuff_DC00<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF +DATA shuff_DC00<>+0x18(SB)/8, $0x0b0a090803020100 +GLOBL shuff_DC00<>(SB), 8, $32 + +// Round specific constants +DATA K256<>+0x00(SB)/4, $0x428a2f98 // k1 +DATA K256<>+0x04(SB)/4, $0x71374491 // k2 +DATA K256<>+0x08(SB)/4, $0xb5c0fbcf // k3 +DATA K256<>+0x0c(SB)/4, $0xe9b5dba5 // k4 +DATA K256<>+0x10(SB)/4, $0x428a2f98 // k1 +DATA K256<>+0x14(SB)/4, $0x71374491 // k2 +DATA K256<>+0x18(SB)/4, $0xb5c0fbcf // k3 +DATA K256<>+0x1c(SB)/4, $0xe9b5dba5 // k4 + +DATA K256<>+0x20(SB)/4, $0x3956c25b // k5 - k8 +DATA K256<>+0x24(SB)/4, $0x59f111f1 +DATA K256<>+0x28(SB)/4, $0x923f82a4 +DATA K256<>+0x2c(SB)/4, $0xab1c5ed5 +DATA K256<>+0x30(SB)/4, $0x3956c25b +DATA K256<>+0x34(SB)/4, $0x59f111f1 +DATA K256<>+0x38(SB)/4, $0x923f82a4 +DATA K256<>+0x3c(SB)/4, $0xab1c5ed5 + +DATA K256<>+0x40(SB)/4, $0xd807aa98 // k9 - k12 +DATA K256<>+0x44(SB)/4, $0x12835b01 +DATA K256<>+0x48(SB)/4, $0x243185be +DATA K256<>+0x4c(SB)/4, $0x550c7dc3 +DATA K256<>+0x50(SB)/4, $0xd807aa98 +DATA K256<>+0x54(SB)/4, $0x12835b01 +DATA K256<>+0x58(SB)/4, $0x243185be +DATA K256<>+0x5c(SB)/4, $0x550c7dc3 + +DATA K256<>+0x60(SB)/4, $0x72be5d74 // k13 - k16 +DATA K256<>+0x64(SB)/4, $0x80deb1fe +DATA K256<>+0x68(SB)/4, $0x9bdc06a7 +DATA K256<>+0x6c(SB)/4, $0xc19bf174 +DATA K256<>+0x70(SB)/4, $0x72be5d74 +DATA K256<>+0x74(SB)/4, $0x80deb1fe +DATA K256<>+0x78(SB)/4, $0x9bdc06a7 +DATA K256<>+0x7c(SB)/4, $0xc19bf174 + +DATA K256<>+0x80(SB)/4, $0xe49b69c1 // k17 - k20 +DATA K256<>+0x84(SB)/4, $0xefbe4786 +DATA K256<>+0x88(SB)/4, $0x0fc19dc6 +DATA K256<>+0x8c(SB)/4, $0x240ca1cc +DATA K256<>+0x90(SB)/4, $0xe49b69c1 +DATA K256<>+0x94(SB)/4, $0xefbe4786 +DATA K256<>+0x98(SB)/4, $0x0fc19dc6 +DATA K256<>+0x9c(SB)/4, $0x240ca1cc + +DATA K256<>+0xa0(SB)/4, $0x2de92c6f // k21 - k24 +DATA K256<>+0xa4(SB)/4, $0x4a7484aa +DATA K256<>+0xa8(SB)/4, $0x5cb0a9dc +DATA K256<>+0xac(SB)/4, $0x76f988da +DATA K256<>+0xb0(SB)/4, $0x2de92c6f +DATA K256<>+0xb4(SB)/4, $0x4a7484aa +DATA K256<>+0xb8(SB)/4, $0x5cb0a9dc +DATA K256<>+0xbc(SB)/4, $0x76f988da + +DATA K256<>+0xc0(SB)/4, $0x983e5152 // k25 - k28 +DATA K256<>+0xc4(SB)/4, $0xa831c66d +DATA K256<>+0xc8(SB)/4, $0xb00327c8 +DATA K256<>+0xcc(SB)/4, $0xbf597fc7 +DATA K256<>+0xd0(SB)/4, $0x983e5152 +DATA K256<>+0xd4(SB)/4, $0xa831c66d +DATA K256<>+0xd8(SB)/4, $0xb00327c8 +DATA K256<>+0xdc(SB)/4, $0xbf597fc7 + +DATA K256<>+0xe0(SB)/4, $0xc6e00bf3 // k29 - k32 +DATA K256<>+0xe4(SB)/4, $0xd5a79147 +DATA K256<>+0xe8(SB)/4, $0x06ca6351 +DATA K256<>+0xec(SB)/4, $0x14292967 +DATA K256<>+0xf0(SB)/4, $0xc6e00bf3 +DATA K256<>+0xf4(SB)/4, $0xd5a79147 +DATA K256<>+0xf8(SB)/4, $0x06ca6351 +DATA K256<>+0xfc(SB)/4, $0x14292967 + +DATA K256<>+0x100(SB)/4, $0x27b70a85 +DATA K256<>+0x104(SB)/4, $0x2e1b2138 +DATA K256<>+0x108(SB)/4, $0x4d2c6dfc +DATA K256<>+0x10c(SB)/4, $0x53380d13 +DATA K256<>+0x110(SB)/4, $0x27b70a85 +DATA K256<>+0x114(SB)/4, $0x2e1b2138 +DATA K256<>+0x118(SB)/4, $0x4d2c6dfc +DATA K256<>+0x11c(SB)/4, $0x53380d13 + +DATA K256<>+0x120(SB)/4, $0x650a7354 +DATA K256<>+0x124(SB)/4, $0x766a0abb +DATA K256<>+0x128(SB)/4, $0x81c2c92e +DATA K256<>+0x12c(SB)/4, $0x92722c85 +DATA K256<>+0x130(SB)/4, $0x650a7354 +DATA K256<>+0x134(SB)/4, $0x766a0abb +DATA K256<>+0x138(SB)/4, $0x81c2c92e +DATA K256<>+0x13c(SB)/4, $0x92722c85 + +DATA K256<>+0x140(SB)/4, $0xa2bfe8a1 +DATA K256<>+0x144(SB)/4, $0xa81a664b +DATA K256<>+0x148(SB)/4, $0xc24b8b70 +DATA K256<>+0x14c(SB)/4, $0xc76c51a3 +DATA K256<>+0x150(SB)/4, $0xa2bfe8a1 +DATA K256<>+0x154(SB)/4, $0xa81a664b +DATA K256<>+0x158(SB)/4, $0xc24b8b70 +DATA K256<>+0x15c(SB)/4, $0xc76c51a3 + +DATA K256<>+0x160(SB)/4, $0xd192e819 +DATA K256<>+0x164(SB)/4, $0xd6990624 +DATA K256<>+0x168(SB)/4, $0xf40e3585 +DATA K256<>+0x16c(SB)/4, $0x106aa070 +DATA K256<>+0x170(SB)/4, $0xd192e819 +DATA K256<>+0x174(SB)/4, $0xd6990624 +DATA K256<>+0x178(SB)/4, $0xf40e3585 +DATA K256<>+0x17c(SB)/4, $0x106aa070 + +DATA K256<>+0x180(SB)/4, $0x19a4c116 +DATA K256<>+0x184(SB)/4, $0x1e376c08 +DATA K256<>+0x188(SB)/4, $0x2748774c +DATA K256<>+0x18c(SB)/4, $0x34b0bcb5 +DATA K256<>+0x190(SB)/4, $0x19a4c116 +DATA K256<>+0x194(SB)/4, $0x1e376c08 +DATA K256<>+0x198(SB)/4, $0x2748774c +DATA K256<>+0x19c(SB)/4, $0x34b0bcb5 + +DATA K256<>+0x1a0(SB)/4, $0x391c0cb3 +DATA K256<>+0x1a4(SB)/4, $0x4ed8aa4a +DATA K256<>+0x1a8(SB)/4, $0x5b9cca4f +DATA K256<>+0x1ac(SB)/4, $0x682e6ff3 +DATA K256<>+0x1b0(SB)/4, $0x391c0cb3 +DATA K256<>+0x1b4(SB)/4, $0x4ed8aa4a +DATA K256<>+0x1b8(SB)/4, $0x5b9cca4f +DATA K256<>+0x1bc(SB)/4, $0x682e6ff3 + +DATA K256<>+0x1c0(SB)/4, $0x748f82ee +DATA K256<>+0x1c4(SB)/4, $0x78a5636f +DATA K256<>+0x1c8(SB)/4, $0x84c87814 +DATA K256<>+0x1cc(SB)/4, $0x8cc70208 +DATA K256<>+0x1d0(SB)/4, $0x748f82ee +DATA K256<>+0x1d4(SB)/4, $0x78a5636f +DATA K256<>+0x1d8(SB)/4, $0x84c87814 +DATA K256<>+0x1dc(SB)/4, $0x8cc70208 + +DATA K256<>+0x1e0(SB)/4, $0x90befffa +DATA K256<>+0x1e4(SB)/4, $0xa4506ceb +DATA K256<>+0x1e8(SB)/4, $0xbef9a3f7 +DATA K256<>+0x1ec(SB)/4, $0xc67178f2 +DATA K256<>+0x1f0(SB)/4, $0x90befffa +DATA K256<>+0x1f4(SB)/4, $0xa4506ceb +DATA K256<>+0x1f8(SB)/4, $0xbef9a3f7 +DATA K256<>+0x1fc(SB)/4, $0xc67178f2 + +GLOBL K256<>(SB), (NOPTR + RODATA), $512 diff --git a/src/crypto/sha256/sha256block_arm64.go b/src/crypto/sha256/sha256block_arm64.go new file mode 100644 index 0000000..e5da566 --- /dev/null +++ b/src/crypto/sha256/sha256block_arm64.go @@ -0,0 +1,21 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha256 + +import "internal/cpu" + +var k = _K + +//go:noescape +func sha256block(h []uint32, p []byte, k []uint32) + +func block(dig *digest, p []byte) { + if !cpu.ARM64.HasSHA2 { + blockGeneric(dig, p) + } else { + h := dig.h[:] + sha256block(h, p, k) + } +} diff --git a/src/crypto/sha256/sha256block_arm64.s b/src/crypto/sha256/sha256block_arm64.s new file mode 100644 index 0000000..d5c1eb0 --- /dev/null +++ b/src/crypto/sha256/sha256block_arm64.s @@ -0,0 +1,119 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +#define HASHUPDATE \ + SHA256H V9.S4, V3, V2 \ + SHA256H2 V9.S4, V8, V3 \ + VMOV V2.B16, V8.B16 + +// func sha256block(h []uint32, p []byte, k []uint32) +TEXT ·sha256block(SB),NOSPLIT,$0 + MOVD h_base+0(FP), R0 // Hash value first address + MOVD p_base+24(FP), R1 // message first address + MOVD k_base+48(FP), R2 // k constants first address + MOVD p_len+32(FP), R3 // message length + VLD1 (R0), [V0.S4, V1.S4] // load h(a,b,c,d,e,f,g,h) + VLD1.P 64(R2), [V16.S4, V17.S4, V18.S4, V19.S4] + VLD1.P 64(R2), [V20.S4, V21.S4, V22.S4, V23.S4] + VLD1.P 64(R2), [V24.S4, V25.S4, V26.S4, V27.S4] + VLD1 (R2), [V28.S4, V29.S4, V30.S4, V31.S4] //load 64*4bytes K constant(K0-K63) + +blockloop: + + VLD1.P 16(R1), [V4.B16] // load 16bytes message + VLD1.P 16(R1), [V5.B16] // load 16bytes message + VLD1.P 16(R1), [V6.B16] // load 16bytes message + VLD1.P 16(R1), [V7.B16] // load 16bytes message + VMOV V0.B16, V2.B16 // backup: VO h(dcba) + VMOV V1.B16, V3.B16 // backup: V1 h(hgfe) + VMOV V2.B16, V8.B16 + VREV32 V4.B16, V4.B16 // prepare for using message in Byte format + VREV32 V5.B16, V5.B16 + VREV32 V6.B16, V6.B16 + VREV32 V7.B16, V7.B16 + + VADD V16.S4, V4.S4, V9.S4 // V18(W0+K0...W3+K3) + SHA256SU0 V5.S4, V4.S4 // V4: (su0(W1)+W0,...,su0(W4)+W3) + HASHUPDATE // H4 + + VADD V17.S4, V5.S4, V9.S4 // V18(W4+K4...W7+K7) + SHA256SU0 V6.S4, V5.S4 // V5: (su0(W5)+W4,...,su0(W8)+W7) + SHA256SU1 V7.S4, V6.S4, V4.S4 // V4: W16-W19 + HASHUPDATE // H8 + + VADD V18.S4, V6.S4, V9.S4 // V18(W8+K8...W11+K11) + SHA256SU0 V7.S4, V6.S4 // V6: (su0(W9)+W8,...,su0(W12)+W11) + SHA256SU1 V4.S4, V7.S4, V5.S4 // V5: W20-W23 + HASHUPDATE // H12 + + VADD V19.S4, V7.S4, V9.S4 // V18(W12+K12...W15+K15) + SHA256SU0 V4.S4, V7.S4 // V7: (su0(W13)+W12,...,su0(W16)+W15) + SHA256SU1 V5.S4, V4.S4, V6.S4 // V6: W24-W27 + HASHUPDATE // H16 + + VADD V20.S4, V4.S4, V9.S4 // V18(W16+K16...W19+K19) + SHA256SU0 V5.S4, V4.S4 // V4: (su0(W17)+W16,...,su0(W20)+W19) + SHA256SU1 V6.S4, V5.S4, V7.S4 // V7: W28-W31 + HASHUPDATE // H20 + + VADD V21.S4, V5.S4, V9.S4 // V18(W20+K20...W23+K23) + SHA256SU0 V6.S4, V5.S4 // V5: (su0(W21)+W20,...,su0(W24)+W23) + SHA256SU1 V7.S4, V6.S4, V4.S4 // V4: W32-W35 + HASHUPDATE // H24 + + VADD V22.S4, V6.S4, V9.S4 // V18(W24+K24...W27+K27) + SHA256SU0 V7.S4, V6.S4 // V6: (su0(W25)+W24,...,su0(W28)+W27) + SHA256SU1 V4.S4, V7.S4, V5.S4 // V5: W36-W39 + HASHUPDATE // H28 + + VADD V23.S4, V7.S4, V9.S4 // V18(W28+K28...W31+K31) + SHA256SU0 V4.S4, V7.S4 // V7: (su0(W29)+W28,...,su0(W32)+W31) + SHA256SU1 V5.S4, V4.S4, V6.S4 // V6: W40-W43 + HASHUPDATE // H32 + + VADD V24.S4, V4.S4, V9.S4 // V18(W32+K32...W35+K35) + SHA256SU0 V5.S4, V4.S4 // V4: (su0(W33)+W32,...,su0(W36)+W35) + SHA256SU1 V6.S4, V5.S4, V7.S4 // V7: W44-W47 + HASHUPDATE // H36 + + VADD V25.S4, V5.S4, V9.S4 // V18(W36+K36...W39+K39) + SHA256SU0 V6.S4, V5.S4 // V5: (su0(W37)+W36,...,su0(W40)+W39) + SHA256SU1 V7.S4, V6.S4, V4.S4 // V4: W48-W51 + HASHUPDATE // H40 + + VADD V26.S4, V6.S4, V9.S4 // V18(W40+K40...W43+K43) + SHA256SU0 V7.S4, V6.S4 // V6: (su0(W41)+W40,...,su0(W44)+W43) + SHA256SU1 V4.S4, V7.S4, V5.S4 // V5: W52-W55 + HASHUPDATE // H44 + + VADD V27.S4, V7.S4, V9.S4 // V18(W44+K44...W47+K47) + SHA256SU0 V4.S4, V7.S4 // V7: (su0(W45)+W44,...,su0(W48)+W47) + SHA256SU1 V5.S4, V4.S4, V6.S4 // V6: W56-W59 + HASHUPDATE // H48 + + VADD V28.S4, V4.S4, V9.S4 // V18(W48+K48,...,W51+K51) + HASHUPDATE // H52 + SHA256SU1 V6.S4, V5.S4, V7.S4 // V7: W60-W63 + + VADD V29.S4, V5.S4, V9.S4 // V18(W52+K52,...,W55+K55) + HASHUPDATE // H56 + + VADD V30.S4, V6.S4, V9.S4 // V18(W59+K59,...,W59+K59) + HASHUPDATE // H60 + + VADD V31.S4, V7.S4, V9.S4 // V18(W60+K60,...,W63+K63) + HASHUPDATE // H64 + + SUB $64, R3, R3 // message length - 64bytes, then compare with 64bytes + VADD V2.S4, V0.S4, V0.S4 + VADD V3.S4, V1.S4, V1.S4 + CBNZ R3, blockloop + +sha256ret: + + VST1 [V0.S4, V1.S4], (R0) // store hash value H + RET + diff --git a/src/crypto/sha256/sha256block_decl.go b/src/crypto/sha256/sha256block_decl.go new file mode 100644 index 0000000..a6bb396 --- /dev/null +++ b/src/crypto/sha256/sha256block_decl.go @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build 386 || amd64 || s390x || ppc64le +// +build 386 amd64 s390x ppc64le + +package sha256 + +//go:noescape + +func block(dig *digest, p []byte) diff --git a/src/crypto/sha256/sha256block_generic.go b/src/crypto/sha256/sha256block_generic.go new file mode 100644 index 0000000..620c048 --- /dev/null +++ b/src/crypto/sha256/sha256block_generic.go @@ -0,0 +1,10 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 && !386 && !s390x && !ppc64le && !arm64 +// +build !amd64,!386,!s390x,!ppc64le,!arm64 + +package sha256 + +var block = blockGeneric diff --git a/src/crypto/sha256/sha256block_ppc64le.s b/src/crypto/sha256/sha256block_ppc64le.s new file mode 100644 index 0000000..77e63c0 --- /dev/null +++ b/src/crypto/sha256/sha256block_ppc64le.s @@ -0,0 +1,419 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on CRYPTOGAMS code with the following comment: +// # ==================================================================== +// # Written by Andy Polyakov for the OpenSSL +// # project. The module is, however, dual licensed under OpenSSL and +// # CRYPTOGAMS licenses depending on where you obtain it. For further +// # details see http://www.openssl.org/~appro/cryptogams/. +// # ==================================================================== + +#include "textflag.h" + +// SHA256 block routine. See sha256block.go for Go equivalent. +// +// The algorithm is detailed in FIPS 180-4: +// +// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf +// +// Wt = Mt; for 0 <= t <= 15 +// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 +// +// a = H0 +// b = H1 +// c = H2 +// d = H3 +// e = H4 +// f = H5 +// g = H6 +// h = H7 +// +// for t = 0 to 63 { +// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt +// T2 = BIGSIGMA0(a) + Maj(a,b,c) +// h = g +// g = f +// f = e +// e = d + T1 +// d = c +// c = b +// b = a +// a = T1 + T2 +// } +// +// H0 = a + H0 +// H1 = b + H1 +// H2 = c + H2 +// H3 = d + H3 +// H4 = e + H4 +// H5 = f + H5 +// H6 = g + H6 +// H7 = h + H7 + +#define CTX R3 +#define INP R4 +#define END R5 +#define TBL R6 +#define IDX R7 +#define CNT R8 +#define LEN R9 +#define OFFLOAD R11 +#define TEMP R12 + +#define HEX00 R0 +#define HEX10 R10 +#define HEX20 R25 +#define HEX30 R26 +#define HEX40 R27 +#define HEX50 R28 +#define HEX60 R29 +#define HEX70 R31 + +// V0-V7 are A-H +// V8-V23 are used for the message schedule +#define KI V24 +#define FUNC V25 +#define S0 V26 +#define S1 V27 +#define s0 V28 +#define s1 V29 +#define LEMASK V31 // Permutation control register for little endian + +// 4 copies of each Kt, to fill all 4 words of a vector register +DATA ·kcon+0x000(SB)/8, $0x428a2f98428a2f98 +DATA ·kcon+0x008(SB)/8, $0x428a2f98428a2f98 +DATA ·kcon+0x010(SB)/8, $0x7137449171374491 +DATA ·kcon+0x018(SB)/8, $0x7137449171374491 +DATA ·kcon+0x020(SB)/8, $0xb5c0fbcfb5c0fbcf +DATA ·kcon+0x028(SB)/8, $0xb5c0fbcfb5c0fbcf +DATA ·kcon+0x030(SB)/8, $0xe9b5dba5e9b5dba5 +DATA ·kcon+0x038(SB)/8, $0xe9b5dba5e9b5dba5 +DATA ·kcon+0x040(SB)/8, $0x3956c25b3956c25b +DATA ·kcon+0x048(SB)/8, $0x3956c25b3956c25b +DATA ·kcon+0x050(SB)/8, $0x59f111f159f111f1 +DATA ·kcon+0x058(SB)/8, $0x59f111f159f111f1 +DATA ·kcon+0x060(SB)/8, $0x923f82a4923f82a4 +DATA ·kcon+0x068(SB)/8, $0x923f82a4923f82a4 +DATA ·kcon+0x070(SB)/8, $0xab1c5ed5ab1c5ed5 +DATA ·kcon+0x078(SB)/8, $0xab1c5ed5ab1c5ed5 +DATA ·kcon+0x080(SB)/8, $0xd807aa98d807aa98 +DATA ·kcon+0x088(SB)/8, $0xd807aa98d807aa98 +DATA ·kcon+0x090(SB)/8, $0x12835b0112835b01 +DATA ·kcon+0x098(SB)/8, $0x12835b0112835b01 +DATA ·kcon+0x0A0(SB)/8, $0x243185be243185be +DATA ·kcon+0x0A8(SB)/8, $0x243185be243185be +DATA ·kcon+0x0B0(SB)/8, $0x550c7dc3550c7dc3 +DATA ·kcon+0x0B8(SB)/8, $0x550c7dc3550c7dc3 +DATA ·kcon+0x0C0(SB)/8, $0x72be5d7472be5d74 +DATA ·kcon+0x0C8(SB)/8, $0x72be5d7472be5d74 +DATA ·kcon+0x0D0(SB)/8, $0x80deb1fe80deb1fe +DATA ·kcon+0x0D8(SB)/8, $0x80deb1fe80deb1fe +DATA ·kcon+0x0E0(SB)/8, $0x9bdc06a79bdc06a7 +DATA ·kcon+0x0E8(SB)/8, $0x9bdc06a79bdc06a7 +DATA ·kcon+0x0F0(SB)/8, $0xc19bf174c19bf174 +DATA ·kcon+0x0F8(SB)/8, $0xc19bf174c19bf174 +DATA ·kcon+0x100(SB)/8, $0xe49b69c1e49b69c1 +DATA ·kcon+0x108(SB)/8, $0xe49b69c1e49b69c1 +DATA ·kcon+0x110(SB)/8, $0xefbe4786efbe4786 +DATA ·kcon+0x118(SB)/8, $0xefbe4786efbe4786 +DATA ·kcon+0x120(SB)/8, $0x0fc19dc60fc19dc6 +DATA ·kcon+0x128(SB)/8, $0x0fc19dc60fc19dc6 +DATA ·kcon+0x130(SB)/8, $0x240ca1cc240ca1cc +DATA ·kcon+0x138(SB)/8, $0x240ca1cc240ca1cc +DATA ·kcon+0x140(SB)/8, $0x2de92c6f2de92c6f +DATA ·kcon+0x148(SB)/8, $0x2de92c6f2de92c6f +DATA ·kcon+0x150(SB)/8, $0x4a7484aa4a7484aa +DATA ·kcon+0x158(SB)/8, $0x4a7484aa4a7484aa +DATA ·kcon+0x160(SB)/8, $0x5cb0a9dc5cb0a9dc +DATA ·kcon+0x168(SB)/8, $0x5cb0a9dc5cb0a9dc +DATA ·kcon+0x170(SB)/8, $0x76f988da76f988da +DATA ·kcon+0x178(SB)/8, $0x76f988da76f988da +DATA ·kcon+0x180(SB)/8, $0x983e5152983e5152 +DATA ·kcon+0x188(SB)/8, $0x983e5152983e5152 +DATA ·kcon+0x190(SB)/8, $0xa831c66da831c66d +DATA ·kcon+0x198(SB)/8, $0xa831c66da831c66d +DATA ·kcon+0x1A0(SB)/8, $0xb00327c8b00327c8 +DATA ·kcon+0x1A8(SB)/8, $0xb00327c8b00327c8 +DATA ·kcon+0x1B0(SB)/8, $0xbf597fc7bf597fc7 +DATA ·kcon+0x1B8(SB)/8, $0xbf597fc7bf597fc7 +DATA ·kcon+0x1C0(SB)/8, $0xc6e00bf3c6e00bf3 +DATA ·kcon+0x1C8(SB)/8, $0xc6e00bf3c6e00bf3 +DATA ·kcon+0x1D0(SB)/8, $0xd5a79147d5a79147 +DATA ·kcon+0x1D8(SB)/8, $0xd5a79147d5a79147 +DATA ·kcon+0x1E0(SB)/8, $0x06ca635106ca6351 +DATA ·kcon+0x1E8(SB)/8, $0x06ca635106ca6351 +DATA ·kcon+0x1F0(SB)/8, $0x1429296714292967 +DATA ·kcon+0x1F8(SB)/8, $0x1429296714292967 +DATA ·kcon+0x200(SB)/8, $0x27b70a8527b70a85 +DATA ·kcon+0x208(SB)/8, $0x27b70a8527b70a85 +DATA ·kcon+0x210(SB)/8, $0x2e1b21382e1b2138 +DATA ·kcon+0x218(SB)/8, $0x2e1b21382e1b2138 +DATA ·kcon+0x220(SB)/8, $0x4d2c6dfc4d2c6dfc +DATA ·kcon+0x228(SB)/8, $0x4d2c6dfc4d2c6dfc +DATA ·kcon+0x230(SB)/8, $0x53380d1353380d13 +DATA ·kcon+0x238(SB)/8, $0x53380d1353380d13 +DATA ·kcon+0x240(SB)/8, $0x650a7354650a7354 +DATA ·kcon+0x248(SB)/8, $0x650a7354650a7354 +DATA ·kcon+0x250(SB)/8, $0x766a0abb766a0abb +DATA ·kcon+0x258(SB)/8, $0x766a0abb766a0abb +DATA ·kcon+0x260(SB)/8, $0x81c2c92e81c2c92e +DATA ·kcon+0x268(SB)/8, $0x81c2c92e81c2c92e +DATA ·kcon+0x270(SB)/8, $0x92722c8592722c85 +DATA ·kcon+0x278(SB)/8, $0x92722c8592722c85 +DATA ·kcon+0x280(SB)/8, $0xa2bfe8a1a2bfe8a1 +DATA ·kcon+0x288(SB)/8, $0xa2bfe8a1a2bfe8a1 +DATA ·kcon+0x290(SB)/8, $0xa81a664ba81a664b +DATA ·kcon+0x298(SB)/8, $0xa81a664ba81a664b +DATA ·kcon+0x2A0(SB)/8, $0xc24b8b70c24b8b70 +DATA ·kcon+0x2A8(SB)/8, $0xc24b8b70c24b8b70 +DATA ·kcon+0x2B0(SB)/8, $0xc76c51a3c76c51a3 +DATA ·kcon+0x2B8(SB)/8, $0xc76c51a3c76c51a3 +DATA ·kcon+0x2C0(SB)/8, $0xd192e819d192e819 +DATA ·kcon+0x2C8(SB)/8, $0xd192e819d192e819 +DATA ·kcon+0x2D0(SB)/8, $0xd6990624d6990624 +DATA ·kcon+0x2D8(SB)/8, $0xd6990624d6990624 +DATA ·kcon+0x2E0(SB)/8, $0xf40e3585f40e3585 +DATA ·kcon+0x2E8(SB)/8, $0xf40e3585f40e3585 +DATA ·kcon+0x2F0(SB)/8, $0x106aa070106aa070 +DATA ·kcon+0x2F8(SB)/8, $0x106aa070106aa070 +DATA ·kcon+0x300(SB)/8, $0x19a4c11619a4c116 +DATA ·kcon+0x308(SB)/8, $0x19a4c11619a4c116 +DATA ·kcon+0x310(SB)/8, $0x1e376c081e376c08 +DATA ·kcon+0x318(SB)/8, $0x1e376c081e376c08 +DATA ·kcon+0x320(SB)/8, $0x2748774c2748774c +DATA ·kcon+0x328(SB)/8, $0x2748774c2748774c +DATA ·kcon+0x330(SB)/8, $0x34b0bcb534b0bcb5 +DATA ·kcon+0x338(SB)/8, $0x34b0bcb534b0bcb5 +DATA ·kcon+0x340(SB)/8, $0x391c0cb3391c0cb3 +DATA ·kcon+0x348(SB)/8, $0x391c0cb3391c0cb3 +DATA ·kcon+0x350(SB)/8, $0x4ed8aa4a4ed8aa4a +DATA ·kcon+0x358(SB)/8, $0x4ed8aa4a4ed8aa4a +DATA ·kcon+0x360(SB)/8, $0x5b9cca4f5b9cca4f +DATA ·kcon+0x368(SB)/8, $0x5b9cca4f5b9cca4f +DATA ·kcon+0x370(SB)/8, $0x682e6ff3682e6ff3 +DATA ·kcon+0x378(SB)/8, $0x682e6ff3682e6ff3 +DATA ·kcon+0x380(SB)/8, $0x748f82ee748f82ee +DATA ·kcon+0x388(SB)/8, $0x748f82ee748f82ee +DATA ·kcon+0x390(SB)/8, $0x78a5636f78a5636f +DATA ·kcon+0x398(SB)/8, $0x78a5636f78a5636f +DATA ·kcon+0x3A0(SB)/8, $0x84c8781484c87814 +DATA ·kcon+0x3A8(SB)/8, $0x84c8781484c87814 +DATA ·kcon+0x3B0(SB)/8, $0x8cc702088cc70208 +DATA ·kcon+0x3B8(SB)/8, $0x8cc702088cc70208 +DATA ·kcon+0x3C0(SB)/8, $0x90befffa90befffa +DATA ·kcon+0x3C8(SB)/8, $0x90befffa90befffa +DATA ·kcon+0x3D0(SB)/8, $0xa4506ceba4506ceb +DATA ·kcon+0x3D8(SB)/8, $0xa4506ceba4506ceb +DATA ·kcon+0x3E0(SB)/8, $0xbef9a3f7bef9a3f7 +DATA ·kcon+0x3E8(SB)/8, $0xbef9a3f7bef9a3f7 +DATA ·kcon+0x3F0(SB)/8, $0xc67178f2c67178f2 +DATA ·kcon+0x3F8(SB)/8, $0xc67178f2c67178f2 +DATA ·kcon+0x400(SB)/8, $0x0000000000000000 +DATA ·kcon+0x408(SB)/8, $0x0000000000000000 +DATA ·kcon+0x410(SB)/8, $0x1011121310111213 // permutation control vectors +DATA ·kcon+0x418(SB)/8, $0x1011121300010203 +DATA ·kcon+0x420(SB)/8, $0x1011121310111213 +DATA ·kcon+0x428(SB)/8, $0x0405060700010203 +DATA ·kcon+0x430(SB)/8, $0x1011121308090a0b +DATA ·kcon+0x438(SB)/8, $0x0405060700010203 +GLOBL ·kcon(SB), RODATA, $1088 + +#define SHA256ROUND0(a, b, c, d, e, f, g, h, xi) \ + VSEL g, f, e, FUNC; \ + VSHASIGMAW $15, e, $1, S1; \ + VADDUWM xi, h, h; \ + VSHASIGMAW $0, a, $1, S0; \ + VADDUWM FUNC, h, h; \ + VXOR b, a, FUNC; \ + VADDUWM S1, h, h; \ + VSEL b, c, FUNC, FUNC; \ + VADDUWM KI, g, g; \ + VADDUWM h, d, d; \ + VADDUWM FUNC, S0, S0; \ + LVX (TBL)(IDX), KI; \ + ADD $16, IDX; \ + VADDUWM S0, h, h + +#define SHA256ROUND1(a, b, c, d, e, f, g, h, xi, xj, xj_1, xj_9, xj_14) \ + VSHASIGMAW $0, xj_1, $0, s0; \ + VSEL g, f, e, FUNC; \ + VSHASIGMAW $15, e, $1, S1; \ + VADDUWM xi, h, h; \ + VSHASIGMAW $0, a, $1, S0; \ + VSHASIGMAW $15, xj_14, $0, s1; \ + VADDUWM FUNC, h, h; \ + VXOR b, a, FUNC; \ + VADDUWM xj_9, xj, xj; \ + VADDUWM S1, h, h; \ + VSEL b, c, FUNC, FUNC; \ + VADDUWM KI, g, g; \ + VADDUWM h, d, d; \ + VADDUWM FUNC, S0, S0; \ + VADDUWM s0, xj, xj; \ + LVX (TBL)(IDX), KI; \ + ADD $16, IDX; \ + VADDUWM S0, h, h; \ + VADDUWM s1, xj, xj + +// func block(dig *digest, p []byte) +TEXT ·block(SB),0,$128-32 + MOVD dig+0(FP), CTX + MOVD p_base+8(FP), INP + MOVD p_len+16(FP), LEN + + SRD $6, LEN + SLD $6, LEN + + ADD INP, LEN, END + + CMP INP, END + BEQ end + + MOVD $·kcon(SB), TBL + MOVD R1, OFFLOAD + + MOVD R0, CNT + MOVWZ $0x10, HEX10 + MOVWZ $0x20, HEX20 + MOVWZ $0x30, HEX30 + MOVWZ $0x40, HEX40 + MOVWZ $0x50, HEX50 + MOVWZ $0x60, HEX60 + MOVWZ $0x70, HEX70 + + MOVWZ $8, IDX + LVSL (IDX)(R0), LEMASK + VSPLTISB $0x0F, KI + VXOR KI, LEMASK, LEMASK + + LXVW4X (CTX)(HEX00), VS32 // v0 = vs32 + LXVW4X (CTX)(HEX10), VS36 // v4 = vs36 + + // unpack the input values into vector registers + VSLDOI $4, V0, V0, V1 + VSLDOI $8, V0, V0, V2 + VSLDOI $12, V0, V0, V3 + VSLDOI $4, V4, V4, V5 + VSLDOI $8, V4, V4, V6 + VSLDOI $12, V4, V4, V7 + +loop: + LVX (TBL)(HEX00), KI + MOVWZ $16, IDX + + LXVD2X (INP)(R0), VS40 // load v8 (=vs40) in advance + ADD $16, INP + + STVX V0, (OFFLOAD+HEX00) + STVX V1, (OFFLOAD+HEX10) + STVX V2, (OFFLOAD+HEX20) + STVX V3, (OFFLOAD+HEX30) + STVX V4, (OFFLOAD+HEX40) + STVX V5, (OFFLOAD+HEX50) + STVX V6, (OFFLOAD+HEX60) + STVX V7, (OFFLOAD+HEX70) + + VADDUWM KI, V7, V7 // h+K[i] + LVX (TBL)(IDX), KI + ADD $16, IDX + + VPERM V8, V8, LEMASK, V8 + SHA256ROUND0(V0, V1, V2, V3, V4, V5, V6, V7, V8) + VSLDOI $4, V8, V8, V9 + SHA256ROUND0(V7, V0, V1, V2, V3, V4, V5, V6, V9) + VSLDOI $4, V9, V9, V10 + SHA256ROUND0(V6, V7, V0, V1, V2, V3, V4, V5, V10) + LXVD2X (INP)(R0), VS44 // load v12 (=vs44) in advance + ADD $16, INP, INP + VSLDOI $4, V10, V10, V11 + SHA256ROUND0(V5, V6, V7, V0, V1, V2, V3, V4, V11) + VPERM V12, V12, LEMASK, V12 + SHA256ROUND0(V4, V5, V6, V7, V0, V1, V2, V3, V12) + VSLDOI $4, V12, V12, V13 + SHA256ROUND0(V3, V4, V5, V6, V7, V0, V1, V2, V13) + VSLDOI $4, V13, V13, V14 + SHA256ROUND0(V2, V3, V4, V5, V6, V7, V0, V1, V14) + LXVD2X (INP)(R0), VS48 // load v16 (=vs48) in advance + ADD $16, INP, INP + VSLDOI $4, V14, V14, V15 + SHA256ROUND0(V1, V2, V3, V4, V5, V6, V7, V0, V15) + VPERM V16, V16, LEMASK, V16 + SHA256ROUND0(V0, V1, V2, V3, V4, V5, V6, V7, V16) + VSLDOI $4, V16, V16, V17 + SHA256ROUND0(V7, V0, V1, V2, V3, V4, V5, V6, V17) + VSLDOI $4, V17, V17, V18 + SHA256ROUND0(V6, V7, V0, V1, V2, V3, V4, V5, V18) + VSLDOI $4, V18, V18, V19 + LXVD2X (INP)(R0), VS52 // load v20 (=vs52) in advance + ADD $16, INP, INP + SHA256ROUND0(V5, V6, V7, V0, V1, V2, V3, V4, V19) + VPERM V20, V20, LEMASK, V20 + SHA256ROUND0(V4, V5, V6, V7, V0, V1, V2, V3, V20) + VSLDOI $4, V20, V20, V21 + SHA256ROUND0(V3, V4, V5, V6, V7, V0, V1, V2, V21) + VSLDOI $4, V21, V21, V22 + SHA256ROUND0(V2, V3, V4, V5, V6, V7, V0, V1, V22) + VSLDOI $4, V22, V22, V23 + SHA256ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V23, V8, V9, V17, V22) + + MOVWZ $3, TEMP + MOVWZ TEMP, CTR + +L16_xx: + SHA256ROUND1(V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V18, V23) + SHA256ROUND1(V7, V0, V1, V2, V3, V4, V5, V6, V9, V10, V11, V19, V8) + SHA256ROUND1(V6, V7, V0, V1, V2, V3, V4, V5, V10, V11, V12, V20, V9) + SHA256ROUND1(V5, V6, V7, V0, V1, V2, V3, V4, V11, V12, V13, V21, V10) + SHA256ROUND1(V4, V5, V6, V7, V0, V1, V2, V3, V12, V13, V14, V22, V11) + SHA256ROUND1(V3, V4, V5, V6, V7, V0, V1, V2, V13, V14, V15, V23, V12) + SHA256ROUND1(V2, V3, V4, V5, V6, V7, V0, V1, V14, V15, V16, V8, V13) + SHA256ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V15, V16, V17, V9, V14) + SHA256ROUND1(V0, V1, V2, V3, V4, V5, V6, V7, V16, V17, V18, V10, V15) + SHA256ROUND1(V7, V0, V1, V2, V3, V4, V5, V6, V17, V18, V19, V11, V16) + SHA256ROUND1(V6, V7, V0, V1, V2, V3, V4, V5, V18, V19, V20, V12, V17) + SHA256ROUND1(V5, V6, V7, V0, V1, V2, V3, V4, V19, V20, V21, V13, V18) + SHA256ROUND1(V4, V5, V6, V7, V0, V1, V2, V3, V20, V21, V22, V14, V19) + SHA256ROUND1(V3, V4, V5, V6, V7, V0, V1, V2, V21, V22, V23, V15, V20) + SHA256ROUND1(V2, V3, V4, V5, V6, V7, V0, V1, V22, V23, V8, V16, V21) + SHA256ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V23, V8, V9, V17, V22) + + BC 0x10, 0, L16_xx // bdnz + + LVX (OFFLOAD)(HEX00), V10 + + LVX (OFFLOAD)(HEX10), V11 + VADDUWM V10, V0, V0 + LVX (OFFLOAD)(HEX20), V12 + VADDUWM V11, V1, V1 + LVX (OFFLOAD)(HEX30), V13 + VADDUWM V12, V2, V2 + LVX (OFFLOAD)(HEX40), V14 + VADDUWM V13, V3, V3 + LVX (OFFLOAD)(HEX50), V15 + VADDUWM V14, V4, V4 + LVX (OFFLOAD)(HEX60), V16 + VADDUWM V15, V5, V5 + LVX (OFFLOAD)(HEX70), V17 + VADDUWM V16, V6, V6 + VADDUWM V17, V7, V7 + + CMPU INP, END + BLT loop + + LVX (TBL)(IDX), V8 + ADD $16, IDX + VPERM V0, V1, KI, V0 + LVX (TBL)(IDX), V9 + VPERM V4, V5, KI, V4 + VPERM V0, V2, V8, V0 + VPERM V4, V6, V8, V4 + VPERM V0, V3, V9, V0 + VPERM V4, V7, V9, V4 + STXVD2X VS32, (CTX+HEX00) // v0 = vs32 + STXVD2X VS36, (CTX+HEX10) // v4 = vs36 + +end: + RET + diff --git a/src/crypto/sha256/sha256block_s390x.go b/src/crypto/sha256/sha256block_s390x.go new file mode 100644 index 0000000..1a376c5 --- /dev/null +++ b/src/crypto/sha256/sha256block_s390x.go @@ -0,0 +1,9 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha256 + +import "internal/cpu" + +var useAsm = cpu.S390X.HasSHA256 diff --git a/src/crypto/sha256/sha256block_s390x.s b/src/crypto/sha256/sha256block_s390x.s new file mode 100644 index 0000000..81b1b38 --- /dev/null +++ b/src/crypto/sha256/sha256block_s390x.s @@ -0,0 +1,20 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func block(dig *digest, p []byte) +TEXT ·block(SB), NOSPLIT|NOFRAME, $0-32 + MOVBZ ·useAsm(SB), R4 + LMG dig+0(FP), R1, R3 // R2 = &p[0], R3 = len(p) + MOVBZ $2, R0 // SHA-256 function code + CMPBEQ R4, $0, generic + +loop: + WORD $0xB93E0002 // KIMD R2 + BVS loop // continue if interrupted + RET + +generic: + BR ·blockGeneric(SB) diff --git a/src/crypto/sha512/fallback_test.go b/src/crypto/sha512/fallback_test.go new file mode 100644 index 0000000..faf7326 --- /dev/null +++ b/src/crypto/sha512/fallback_test.go @@ -0,0 +1,38 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build s390x +// +build s390x + +package sha512 + +import ( + "fmt" + "io" + "testing" +) + +// Tests the fallback code path in case the optimized asm +// implementation cannot be used. +// See also TestBlockGeneric. +func TestGenericPath(t *testing.T) { + if useAsm == false { + t.Skipf("assembly implementation unavailable") + } + useAsm = false + defer func() { useAsm = true }() + c := New() + in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" + gold := "6922e319366d677f34c504af31bfcb29" + + "e531c125ecd08679362bffbd6b6ebfb9" + + "0dcc27dfc1f3d3b16a16c0763cf43b91" + + "40bbf9bbb7233724e9a0c6655b185d76" + if _, err := io.WriteString(c, in); err != nil { + t.Fatalf("could not write to c: %v", err) + } + out := fmt.Sprintf("%x", c.Sum(nil)) + if out != gold { + t.Fatalf("mismatch: got %s, wanted %s", out, gold) + } +} diff --git a/src/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go new file mode 100644 index 0000000..9c143a2 --- /dev/null +++ b/src/crypto/sha512/sha512.go @@ -0,0 +1,367 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256 +// hash algorithms as defined in FIPS 180-4. +// +// All the hash.Hash implementations returned by this package also +// implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to +// marshal and unmarshal the internal state of the hash. +package sha512 + +import ( + "crypto" + "encoding/binary" + "errors" + "hash" +) + +func init() { + crypto.RegisterHash(crypto.SHA384, New384) + crypto.RegisterHash(crypto.SHA512, New) + crypto.RegisterHash(crypto.SHA512_224, New512_224) + crypto.RegisterHash(crypto.SHA512_256, New512_256) +} + +const ( + // Size is the size, in bytes, of a SHA-512 checksum. + Size = 64 + + // Size224 is the size, in bytes, of a SHA-512/224 checksum. + Size224 = 28 + + // Size256 is the size, in bytes, of a SHA-512/256 checksum. + Size256 = 32 + + // Size384 is the size, in bytes, of a SHA-384 checksum. + Size384 = 48 + + // BlockSize is the block size, in bytes, of the SHA-512/224, + // SHA-512/256, SHA-384 and SHA-512 hash functions. + BlockSize = 128 +) + +const ( + chunk = 128 + init0 = 0x6a09e667f3bcc908 + init1 = 0xbb67ae8584caa73b + init2 = 0x3c6ef372fe94f82b + init3 = 0xa54ff53a5f1d36f1 + init4 = 0x510e527fade682d1 + init5 = 0x9b05688c2b3e6c1f + init6 = 0x1f83d9abfb41bd6b + init7 = 0x5be0cd19137e2179 + init0_224 = 0x8c3d37c819544da2 + init1_224 = 0x73e1996689dcd4d6 + init2_224 = 0x1dfab7ae32ff9c82 + init3_224 = 0x679dd514582f9fcf + init4_224 = 0x0f6d2b697bd44da8 + init5_224 = 0x77e36f7304c48942 + init6_224 = 0x3f9d85a86a1d36c8 + init7_224 = 0x1112e6ad91d692a1 + init0_256 = 0x22312194fc2bf72c + init1_256 = 0x9f555fa3c84c64c2 + init2_256 = 0x2393b86b6f53b151 + init3_256 = 0x963877195940eabd + init4_256 = 0x96283ee2a88effe3 + init5_256 = 0xbe5e1e2553863992 + init6_256 = 0x2b0199fc2c85b8aa + init7_256 = 0x0eb72ddc81c52ca2 + init0_384 = 0xcbbb9d5dc1059ed8 + init1_384 = 0x629a292a367cd507 + init2_384 = 0x9159015a3070dd17 + init3_384 = 0x152fecd8f70e5939 + init4_384 = 0x67332667ffc00b31 + init5_384 = 0x8eb44a8768581511 + init6_384 = 0xdb0c2e0d64f98fa7 + init7_384 = 0x47b5481dbefa4fa4 +) + +// digest represents the partial evaluation of a checksum. +type digest struct { + h [8]uint64 + x [chunk]byte + nx int + len uint64 + function crypto.Hash +} + +func (d *digest) Reset() { + switch d.function { + case crypto.SHA384: + d.h[0] = init0_384 + d.h[1] = init1_384 + d.h[2] = init2_384 + d.h[3] = init3_384 + d.h[4] = init4_384 + d.h[5] = init5_384 + d.h[6] = init6_384 + d.h[7] = init7_384 + case crypto.SHA512_224: + d.h[0] = init0_224 + d.h[1] = init1_224 + d.h[2] = init2_224 + d.h[3] = init3_224 + d.h[4] = init4_224 + d.h[5] = init5_224 + d.h[6] = init6_224 + d.h[7] = init7_224 + case crypto.SHA512_256: + d.h[0] = init0_256 + d.h[1] = init1_256 + d.h[2] = init2_256 + d.h[3] = init3_256 + d.h[4] = init4_256 + d.h[5] = init5_256 + d.h[6] = init6_256 + d.h[7] = init7_256 + default: + d.h[0] = init0 + d.h[1] = init1 + d.h[2] = init2 + d.h[3] = init3 + d.h[4] = init4 + d.h[5] = init5 + d.h[6] = init6 + d.h[7] = init7 + } + d.nx = 0 + d.len = 0 +} + +const ( + magic384 = "sha\x04" + magic512_224 = "sha\x05" + magic512_256 = "sha\x06" + magic512 = "sha\x07" + marshaledSize = len(magic512) + 8*8 + chunk + 8 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + b := make([]byte, 0, marshaledSize) + switch d.function { + case crypto.SHA384: + b = append(b, magic384...) + case crypto.SHA512_224: + b = append(b, magic512_224...) + case crypto.SHA512_256: + b = append(b, magic512_256...) + case crypto.SHA512: + b = append(b, magic512...) + default: + return nil, errors.New("crypto/sha512: invalid hash function") + } + b = appendUint64(b, d.h[0]) + b = appendUint64(b, d.h[1]) + b = appendUint64(b, d.h[2]) + b = appendUint64(b, d.h[3]) + b = appendUint64(b, d.h[4]) + b = appendUint64(b, d.h[5]) + b = appendUint64(b, d.h[6]) + b = appendUint64(b, d.h[7]) + b = append(b, d.x[:d.nx]...) + b = b[:len(b)+len(d.x)-int(d.nx)] // already zero + b = appendUint64(b, d.len) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic512) { + return errors.New("crypto/sha512: invalid hash state identifier") + } + switch { + case d.function == crypto.SHA384 && string(b[:len(magic384)]) == magic384: + case d.function == crypto.SHA512_224 && string(b[:len(magic512_224)]) == magic512_224: + case d.function == crypto.SHA512_256 && string(b[:len(magic512_256)]) == magic512_256: + case d.function == crypto.SHA512 && string(b[:len(magic512)]) == magic512: + default: + return errors.New("crypto/sha512: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/sha512: invalid hash state size") + } + b = b[len(magic512):] + b, d.h[0] = consumeUint64(b) + b, d.h[1] = consumeUint64(b) + b, d.h[2] = consumeUint64(b) + b, d.h[3] = consumeUint64(b) + b, d.h[4] = consumeUint64(b) + b, d.h[5] = consumeUint64(b) + b, d.h[6] = consumeUint64(b) + b, d.h[7] = consumeUint64(b) + b = b[copy(d.x[:], b):] + b, d.len = consumeUint64(b) + d.nx = int(d.len % chunk) + return nil +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + _ = b[7] + x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 + return b[8:], x +} + +// New returns a new hash.Hash computing the SHA-512 checksum. +func New() hash.Hash { + d := &digest{function: crypto.SHA512} + d.Reset() + return d +} + +// New512_224 returns a new hash.Hash computing the SHA-512/224 checksum. +func New512_224() hash.Hash { + d := &digest{function: crypto.SHA512_224} + d.Reset() + return d +} + +// New512_256 returns a new hash.Hash computing the SHA-512/256 checksum. +func New512_256() hash.Hash { + d := &digest{function: crypto.SHA512_256} + d.Reset() + return d +} + +// New384 returns a new hash.Hash computing the SHA-384 checksum. +func New384() hash.Hash { + d := &digest{function: crypto.SHA384} + d.Reset() + return d +} + +func (d *digest) Size() int { + switch d.function { + case crypto.SHA512_224: + return Size224 + case crypto.SHA512_256: + return Size256 + case crypto.SHA384: + return Size384 + default: + return Size + } +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Write(p []byte) (nn int, err error) { + nn = len(p) + d.len += uint64(nn) + if d.nx > 0 { + n := copy(d.x[d.nx:], p) + d.nx += n + if d.nx == chunk { + block(d, d.x[:]) + d.nx = 0 + } + p = p[n:] + } + if len(p) >= chunk { + n := len(p) &^ (chunk - 1) + block(d, p[:n]) + p = p[n:] + } + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d so that caller can keep writing and summing. + d0 := new(digest) + *d0 = *d + hash := d0.checkSum() + switch d0.function { + case crypto.SHA384: + return append(in, hash[:Size384]...) + case crypto.SHA512_224: + return append(in, hash[:Size224]...) + case crypto.SHA512_256: + return append(in, hash[:Size256]...) + default: + return append(in, hash[:]...) + } +} + +func (d *digest) checkSum() [Size]byte { + // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. + len := d.len + var tmp [128]byte + tmp[0] = 0x80 + if len%128 < 112 { + d.Write(tmp[0 : 112-len%128]) + } else { + d.Write(tmp[0 : 128+112-len%128]) + } + + // Length in bits. + len <<= 3 + binary.BigEndian.PutUint64(tmp[0:], 0) // upper 64 bits are always zero, because len variable has type uint64 + binary.BigEndian.PutUint64(tmp[8:], len) + d.Write(tmp[0:16]) + + if d.nx != 0 { + panic("d.nx != 0") + } + + var digest [Size]byte + binary.BigEndian.PutUint64(digest[0:], d.h[0]) + binary.BigEndian.PutUint64(digest[8:], d.h[1]) + binary.BigEndian.PutUint64(digest[16:], d.h[2]) + binary.BigEndian.PutUint64(digest[24:], d.h[3]) + binary.BigEndian.PutUint64(digest[32:], d.h[4]) + binary.BigEndian.PutUint64(digest[40:], d.h[5]) + if d.function != crypto.SHA384 { + binary.BigEndian.PutUint64(digest[48:], d.h[6]) + binary.BigEndian.PutUint64(digest[56:], d.h[7]) + } + + return digest +} + +// Sum512 returns the SHA512 checksum of the data. +func Sum512(data []byte) [Size]byte { + d := digest{function: crypto.SHA512} + d.Reset() + d.Write(data) + return d.checkSum() +} + +// Sum384 returns the SHA384 checksum of the data. +func Sum384(data []byte) (sum384 [Size384]byte) { + d := digest{function: crypto.SHA384} + d.Reset() + d.Write(data) + sum := d.checkSum() + copy(sum384[:], sum[:Size384]) + return +} + +// Sum512_224 returns the Sum512/224 checksum of the data. +func Sum512_224(data []byte) (sum224 [Size224]byte) { + d := digest{function: crypto.SHA512_224} + d.Reset() + d.Write(data) + sum := d.checkSum() + copy(sum224[:], sum[:Size224]) + return +} + +// Sum512_256 returns the Sum512/256 checksum of the data. +func Sum512_256(data []byte) (sum256 [Size256]byte) { + d := digest{function: crypto.SHA512_256} + d.Reset() + d.Write(data) + sum := d.checkSum() + copy(sum256[:], sum[:Size256]) + return +} diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go new file mode 100644 index 0000000..0e1528f --- /dev/null +++ b/src/crypto/sha512/sha512_test.go @@ -0,0 +1,914 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// SHA512 hash algorithm. See FIPS 180-4. + +package sha512 + +import ( + "bytes" + "crypto/rand" + "encoding" + "encoding/hex" + "fmt" + "hash" + "io" + "testing" +) + +type sha512Test struct { + out string + in string + halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal +} + +var golden224 = []sha512Test{ + { + "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4", + "", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + }, + { + "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327", + "a", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + }, + { + "b35878d07bfedf39fc638af08547eb5d1072d8546319f247b442fbf5", + "ab", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + }, + { + "4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa", + "abc", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + }, + { + "0c9f157ab030fb06e957c14e3938dc5908962e5dd7b66f04a36fc534", + "abcd", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", + }, + { + "880e79bb0a1d2c9b7528d851edb6b8342c58c831de98123b432a4515", + "abcde", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", + }, + { + "236c829cfea4fd6d4de61ad15fcf34dca62342adaf9f2001c16f29b8", + "abcdef", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + }, + { + "4767af672b3ed107f25018dc22d6fa4b07d156e13b720971e2c4f6bf", + "abcdefg", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + }, + { + "792e25e0ae286d123a38950007e037d3122e76c4ee201668c385edab", + "abcdefgh", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", + }, + { + "56b275d36127dc070cda4019baf2ce2579a25d8c67fa2bc9be61b539", + "abcdefghi", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", + }, + { + "f809423cbb25e81a2a64aecee2cd5fdc7d91d5db583901fbf1db3116", + "abcdefghij", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1abcde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05", + }, + { + "4c46e10b5b72204e509c3c06072cea970bc020cd45a61a0acdfa97ac", + "Discard medicine more than two years old.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1Discard medicine mor\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14", + }, + { + "cb0cef13c1848d91a6d02637c7c520de1914ad4a7aea824671cc328e", + "He who has a shady past knows that nice guys finish last.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1He who has a shady past know\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "6c7bd0f3a6544ea698006c2ea583a85f80ea2913590a186db8bb2f1b", + "I wouldn't marry him with a ten foot pole.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1I wouldn't marry him \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15", + }, + { + "981323be3eca6ccfa598e58dd74ed8cb05d5f7f6653b7604b684f904", + "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1Free! Free!/A trip/to Mars/f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "e6fbf82df5138bf361e826903cadf0612cb2986649ba47a57e1bca99", + "The days of the digital watch are numbered. -Tom Stoppard", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1The days of the digital watch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d", + }, + { + "6ec2cb2ecafc1a9bddaf4caf57344d853e6ded398927d5694fd7714f", + "Nepal premier won't resign.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1Nepal premier\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r", + }, + { + "7f62f36e716e0badaf4a4658da9d09bea26357a1bc6aeb8cf7c3ae35", + "For every action there is an equal and opposite government program.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1For every action there is an equa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!", + }, + { + "45adffcb86a05ee4d91263a6115dda011b805d442c60836963cb8378", + "His money is twice tainted: 'taint yours and 'taint mine.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1His money is twice tainted: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "51cb518f1f68daa901a3075a0a5e1acc755b4e5c82cb47687537f880", + "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1There is no reason for any individual to hav\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,", + }, + { + "3b59c5e64b0da7bfc18d7017bf458d90f2c83601ff1afc6263ac0993", + "It's a tiny change to the code and not completely disgusting. - Bob Manchek", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1It's a tiny change to the code and no\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%", + }, + { + "6a9525c0fac0f91b489bc4f0f539b9ec4a156a4e98bc15b655c2c881", + "size: a.out: bad magic", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1size: a.out\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f", + }, + { + "a1b2b2905b1527d682049c6a76e35c7d8c72551abfe7833ac1be595f", + "The major problem is with sendmail. -Mark Horton", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1The major problem is wit\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18", + }, + { + "76cf045c76a5f2e3d64d56c3cdba6a25479334611bc375460526f8c1", + "Give me a rock, paper and scissors and I will move the world. CCFestoon", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1Give me a rock, paper and scissors a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$", + }, + { + "4473671daeecfdb6f6c5bc06b26374aa5e497cc37119fe14144c430c", + "If the enemy is within range, then so are you.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1If the enemy is within \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17", + }, + { + "6accb6394758523fcd453d47d37ebd10868957a0a9e81c796736abf8", + "It's well we cannot hear the screams/That we create in others' dreams.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1It's well we cannot hear the scream\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#", + }, + { + "6f173f4b6eac7f2a73eaa0833c4563752df2c869dc00b7d30219e12e", + "You remind me of a TV show, but that's all right: I watch it anyway.", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1You remind me of a TV show, but th\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"", + }, + { + "db05bf4d0f73325208755f4af96cfac6cb3db5dbfc323d675d68f938", + "C is as portable as Stonehedge!!", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1C is as portable\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10", + }, + { + "05ffa71bb02e855de1aaee1777b3bdbaf7507646f19c4c6aa29933d0", + "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1Even if I could be Shakespeare, I think I sh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,", + }, + { + "3ad3c89e15b91e6273534c5d18adadbb528e7b840b288f64e81b8c6d", + "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1The fugacity of a constituent in a mixture of gases at a given tem\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B", + }, + { + "e3763669d1b760c1be7bfcb6625f92300a8430419d1dbad57ec9f53c", + "How can you write a big system without C++? -Paul Glick", + "sha\x05\x8c=7\xc8\x19TM\xa2s\xe1\x99f\x89\xdc\xd4\xd6\x1d\xfa\xb7\xae2\xff\x9c\x82g\x9d\xd5\x14X/\x9f\xcf\x0fm+i{\xd4M\xa8w\xe3os\x04ĉB?\x9d\x85\xa8j\x1d6\xc8\x11\x12歑֒\xa1How can you write a big syst\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, +} + +var golden256 = []sha512Test{ + { + "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a", + "", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + }, + { + "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8", + "a", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + }, + { + "22d4d37ec6370571af7109fb12eae79673d5f7c83e6e677083faa3cfac3b2c14", + "ab", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + }, + { + "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23", + "abc", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + }, + { + "d2891c7978be0e24948f37caa415b87cb5cbe2b26b7bad9dc6391b8a6f6ddcc9", + "abcd", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", + }, + { + "de8322b46e78b67d4431997070703e9764e03a1237b896fd8b379ed4576e8363", + "abcde", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", + }, + { + "e4fdcb11d1ac14e698743acd8805174cea5ddc0d312e3e47f6372032571bad84", + "abcdef", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + }, + { + "a8117f680bdceb5d1443617cbdae9255f6900075422326a972fdd2f65ba9bee3", + "abcdefg", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + }, + { + "a29b9645d2a02a8b582888d044199787220e316bf2e89d1422d3df26bf545bbe", + "abcdefgh", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", + }, + { + "b955095330f9c8188d11884ec1679dc44c9c5b25ff9bda700416df9cdd39188f", + "abcdefghi", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", + }, + { + "550762913d51eefbcd1a55068fcfc9b154fd11c1078b996df0d926ea59d2a68d", + "abcdefghij", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2abcde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05", + }, + { + "690c8ad3916cefd3ad29226d9875965e3ee9ec0d4482eacc248f2ff4aa0d8e5b", + "Discard medicine more than two years old.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2Discard medicine mor\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14", + }, + { + "25938ca49f7ef1178ce81620842b65e576245fcaed86026a36b516b80bb86b3b", + "He who has a shady past knows that nice guys finish last.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2He who has a shady past know\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "698e420c3a7038e53d8e73f4be2b02e03b93464ac1a61ebe69f557079921ef65", + "I wouldn't marry him with a ten foot pole.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2I wouldn't marry him \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15", + }, + { + "839b414d7e3900ee243aa3d1f9b6955720e64041f5ab9bedd3eb0a08da5a2ca8", + "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2Free! Free!/A trip/to Mars/f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "5625ecb9d284e54c00b257b67a8cacb25a78db2845c60ef2d29e43c84f236e8e", + "The days of the digital watch are numbered. -Tom Stoppard", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2The days of the digital watch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d", + }, + { + "9b81d06bca2f985e6ad3249096ff3c0f2a9ec5bb16ef530d738d19d81e7806f2", + "Nepal premier won't resign.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2Nepal premier\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r", + }, + { + "08241df8d91edfcd68bb1a1dada6e0ae1475a5c6e7b8f12d8e24ca43a38240a9", + "For every action there is an equal and opposite government program.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2For every action there is an equa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!", + }, + { + "4ff74d9213a8117745f5d37b5353a774ec81c5dfe65c4c8986a56fc01f2c551e", + "His money is twice tainted: 'taint yours and 'taint mine.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2His money is twice tainted: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "b5baf747c307f98849ec881cf0d48605ae4edd386372aea9b26e71db517e650b", + "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2There is no reason for any individual to hav\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,", + }, + { + "7eef0538ebd7ecf18611d23b0e1cd26a74d65b929a2e374197dc66e755ca4944", + "It's a tiny change to the code and not completely disgusting. - Bob Manchek", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2It's a tiny change to the code and no\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%", + }, + { + "d05600964f83f55323104aadab434f32391c029718a7690d08ddb2d7e8708443", + "size: a.out: bad magic", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2size: a.out\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f", + }, + { + "53ed5f9b5c0b674ac0f3425d9f9a5d462655b07cc90f5d0f692eec093884a607", + "The major problem is with sendmail. -Mark Horton", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2The major problem is wit\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18", + }, + { + "5a0147685a44eea2435dbd582724efca7637acd9c428e5e1a05115bc3bc2a0e0", + "Give me a rock, paper and scissors and I will move the world. CCFestoon", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2Give me a rock, paper and scissors a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$", + }, + { + "1152c9b27a99dbf4057d21438f4e63dd0cd0977d5ff12317c64d3b97fcac875a", + "If the enemy is within range, then so are you.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2If the enemy is within \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17", + }, + { + "105e890f5d5cf1748d9a7b4cdaf58b69855779deebc2097747c2210a17b2cb51", + "It's well we cannot hear the screams/That we create in others' dreams.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2It's well we cannot hear the scream\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#", + }, + { + "74644ead770da1434365cd912656fe1aca2056d3039d39f10eb1151bddb32cf3", + "You remind me of a TV show, but that's all right: I watch it anyway.", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2You remind me of a TV show, but th\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"", + }, + { + "50a234625de5587581883dad9ef399460928032a5ea6bd005d7dc7b68d8cc3d6", + "C is as portable as Stonehedge!!", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2C is as portable\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10", + }, + { + "a7a3846005f8a9935a0a2d43e7fd56d95132a9a3609bf3296ef80b8218acffa0", + "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2Even if I could be Shakespeare, I think I sh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,", + }, + { + "688ff03e367680757aa9906cb1e2ad218c51f4526dc0426ea229a5ba9d002c69", + "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2The fugacity of a constituent in a mixture of gases at a given tem\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B", + }, + { + "3fa46d52094b01021cff5af9a438982b887a5793f624c0a6644149b6b7c3f485", + "How can you write a big system without C++? -Paul Glick", + "sha\x06\"1!\x94\xfc+\xf7,\x9fU_\xa3\xc8Ld\xc2#\x93\xb8koS\xb1Q\x968w\x19Y@꽖(>⨎\xff\xe3\xbe^\x1e%S\x869\x92+\x01\x99\xfc,\x85\xb8\xaa\x0e\xb7-܁\xc5,\xa2How can you write a big syst\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, +} + +var golden384 = []sha512Test{ + { + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", + "", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + }, + { + "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31", + "a", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + }, + { + "c7be03ba5bcaa384727076db0018e99248e1a6e8bd1b9ef58a9ec9dd4eeebb3f48b836201221175befa74ddc3d35afdd", + "ab", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + }, + { + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7", + "abc", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + }, + { + "1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b", + "abcd", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", + }, + { + "4c525cbeac729eaf4b4665815bc5db0c84fe6300068a727cf74e2813521565abc0ec57a37ee4d8be89d097c0d2ad52f0", + "abcde", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4ab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", + }, + { + "c6a4c65b227e7387b9c3e839d44869c4cfca3ef583dea64117859b808c1e3d8ae689e1e314eeef52a6ffe22681aa11f5", + "abcdef", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + }, + { + "9f11fc131123f844c1226f429b6a0a6af0525d9f40f056c7fc16cdf1b06bda08e302554417a59fa7dcf6247421959d22", + "abcdefg", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + }, + { + "9000cd7cada59d1d2eb82912f7f24e5e69cc5517f68283b005fa27c285b61e05edf1ad1a8a9bded6fd29eb87d75ad806", + "abcdefgh", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", + }, + { + "ef54915b60cf062b8dd0c29ae3cad69abe6310de63ac081f46ef019c5c90897caefd79b796cfa81139788a260ded52df", + "abcdefghi", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4abcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", + }, + { + "a12070030a02d86b0ddacd0d3a5b598344513d0a051e7355053e556a0055489c1555399b03342845c4adde2dc44ff66c", + "abcdefghij", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4abcde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05", + }, + { + "86f58ec2d74d1b7f8eb0c2ff0967316699639e8d4eb129de54bdf34c96cdbabe200d052149f2dd787f43571ba74670d4", + "Discard medicine more than two years old.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4Discard medicine mor\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14", + }, + { + "ae4a2b639ca9bfa04b1855d5a05fe7f230994f790891c6979103e2605f660c4c1262a48142dcbeb57a1914ba5f7c3fa7", + "He who has a shady past knows that nice guys finish last.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4He who has a shady past know\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "40ae213df6436eca952aa6841886fcdb82908ef1576a99c8f49bb9dd5023169f7c53035abdda0b54c302f4974e2105e7", + "I wouldn't marry him with a ten foot pole.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4I wouldn't marry him \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15", + }, + { + "e7cf8b873c9bc950f06259aa54309f349cefa72c00d597aebf903e6519a50011dfe355afff064a10701c705693848df9", + "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4Free! Free!/A trip/to Mars/f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "c3d4f0f4047181c7d39d34703365f7bf70207183caf2c2f6145f04da895ef69124d9cdeb635da636c3a474e61024e29b", + "The days of the digital watch are numbered. -Tom Stoppard", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4The days of the digital watch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d", + }, + { + "a097aab567e167d5cf93676ed73252a69f9687cb3179bb2d27c9878119e94bf7b7c4b58dc90582edfaf66e11388ed714", + "Nepal premier won't resign.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4Nepal premier\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r", + }, + { + "5026ca45c41fc64712eb65065da92f6467541c78f8966d3fe2c8e3fb769a3ec14215f819654b47bd64f7f0eac17184f3", + "For every action there is an equal and opposite government program.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4For every action there is an equa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!", + }, + { + "ac1cc0f5ac8d5f5514a7b738ac322b7fb52a161b449c3672e9b6a6ad1a5e4b26b001cf3bad24c56598676ca17d4b445a", + "His money is twice tainted: 'taint yours and 'taint mine.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4His money is twice tainted: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "722d10c5de371ec0c8c4b5247ac8a5f1d240d68c73f8da13d8b25f0166d6f309bf9561979a111a0049405771d201941a", + "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4There is no reason for any individual to hav\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,", + }, + { + "dc2d3ea18bfa10549c63bf2b75b39b5167a80c12aff0e05443168ea87ff149fb0eda5e0bd234eb5d48c7d02ffc5807f1", + "It's a tiny change to the code and not completely disgusting. - Bob Manchek", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4It's a tiny change to the code and no\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%", + }, + { + "1d67c969e2a945ae5346d2139760261504d4ba164c522443afe19ef3e29b152a4c52445489cfc9d7215e5a450e8e1e4e", + "size: a.out: bad magic", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4size: a.out\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f", + }, + { + "5ff8e075e465646e7b73ef36d812c6e9f7d60fa6ea0e533e5569b4f73cde53cdd2cc787f33540af57cca3fe467d32fe0", + "The major problem is with sendmail. -Mark Horton", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4The major problem is wit\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18", + }, + { + "5bd0a997a67c9ae1979a894eb0cde403dde003c9b6f2c03cf21925c42ff4e1176e6df1ca005381612ef18457b9b7ec3b", + "Give me a rock, paper and scissors and I will move the world. CCFestoon", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4Give me a rock, paper and scissors a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$", + }, + { + "1eee6da33e7e54fc5be52ae23b94b16ba4d2a947ae4505c6a3edfc7401151ea5205ac01b669b56f27d8ef7f175ed7762", + "If the enemy is within range, then so are you.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4If the enemy is within \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17", + }, + { + "76b06e9dea66bfbb1a96029426dc0dfd7830bd297eb447ff5358d94a87cd00c88b59df2493fef56ecbb5231073892ea9", + "It's well we cannot hear the screams/That we create in others' dreams.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4It's well we cannot hear the scream\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#", + }, + { + "12acaf21452cff586143e3f5db0bfdf7802c057e1adf2a619031c4e1b0ccc4208cf6cef8fe722bbaa2fb46a30d9135d8", + "You remind me of a TV show, but that's all right: I watch it anyway.", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4You remind me of a TV show, but th\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"", + }, + { + "0fc23d7f4183efd186f0bc4fc5db867e026e2146b06cb3d52f4bdbd57d1740122caa853b41868b197b2ac759db39df88", + "C is as portable as Stonehedge!!", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4C is as portable\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10", + }, + { + "bc805578a7f85d34a86a32976e1c34fe65cf815186fbef76f46ef99cda10723f971f3f1464d488243f5e29db7488598d", + "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4Even if I could be Shakespeare, I think I sh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,", + }, + { + "b23918399a12ebf4431559eec3813eaf7412e875fd7464f16d581e473330842d2e96c6be49a7ce3f9bb0b8bc0fcbe0fe", + "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4The fugacity of a constituent in a mixture of gases at a given tem\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B", + }, + { + "1764b700eb1ead52a2fc33cc28975c2180f1b8faa5038d94cffa8d78154aab16e91dd787e7b0303948ebed62561542c8", + "How can you write a big system without C++? -Paul Glick", + "sha\x04˻\x9d]\xc1\x05\x9e\xd8b\x9a)*6|\xd5\a\x91Y\x01Z0p\xdd\x17\x15/\xec\xd8\xf7\x0eY9g3&g\xff\xc0\v1\x8e\xb4J\x87hX\x15\x11\xdb\f.\rd\xf9\x8f\xa7G\xb5H\x1d\xbe\xfaO\xa4How can you write a big syst\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, +} + +var golden512 = []sha512Test{ + { + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + "", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + }, + { + "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", + "a", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + }, + { + "2d408a0717ec188158278a796c689044361dc6fdde28d6f04973b80896e1823975cdbf12eb63f9e0591328ee235d80e9b5bf1aa6a44f4617ff3caf6400eb172d", + "ab", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!ya\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + }, + { + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + "abc", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!ya\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", + }, + { + "d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f", + "abcd", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", + }, + { + "878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665bef2289a5c70b0a1", + "abcde", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", + }, + { + "e32ef19623e8ed9d267f657a81944b3d07adbb768518068e88435745564e8d4150a0a703be2a7d88b61e3d390c2bb97e2d4c311fdc69d6b1267f05f59aa920e7", + "abcdef", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yabc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + }, + { + "d716a4188569b68ab1b6dfac178e570114cdf0ea3a1cc0e31486c3e41241bc6a76424e8c37ab26f096fc85ef9886c8cb634187f4fddff645fb099f1ff54c6b8c", + "abcdefg", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yabc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", + }, + { + "a3a8c81bc97c2560010d7389bc88aac974a104e0e2381220c6e084c4dccd1d2d17d4f86db31c2a851dc80e6681d74733c55dcd03dd96f6062cdda12a291ae6ce", + "abcdefgh", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yabcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", + }, + { + "f22d51d25292ca1d0f68f69aedc7897019308cc9db46efb75a03dd494fc7f126c010e8ade6a00a0c1a5f1b75d81e0ed5a93ce98dc9b833db7839247b1d9c24fe", + "abcdefghi", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yabcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", + }, + { + "ef6b97321f34b1fea2169a7db9e1960b471aa13302a988087357c520be957ca119c3ba68e6b4982c019ec89de3865ccf6a3cda1fe11e59f98d99f1502c8b9745", + "abcdefghij", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yabcde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05", + }, + { + "2210d99af9c8bdecda1b4beff822136753d8342505ddce37f1314e2cdbb488c6016bdaa9bd2ffa513dd5de2e4b50f031393d8ab61f773b0e0130d7381e0f8a1d", + "Discard medicine more than two years old.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yDiscard medicine mor\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14", + }, + { + "a687a8985b4d8d0a24f115fe272255c6afaf3909225838546159c1ed685c211a203796ae8ecc4c81a5b6315919b3a64f10713da07e341fcdbb08541bf03066ce", + "He who has a shady past knows that nice guys finish last.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yHe who has a shady past know\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "8ddb0392e818b7d585ab22769a50df660d9f6d559cca3afc5691b8ca91b8451374e42bcdabd64589ed7c91d85f626596228a5c8572677eb98bc6b624befb7af8", + "I wouldn't marry him with a ten foot pole.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yI wouldn't marry him \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15", + }, + { + "26ed8f6ca7f8d44b6a8a54ae39640fa8ad5c673f70ee9ce074ba4ef0d483eea00bab2f61d8695d6b34df9c6c48ae36246362200ed820448bdc03a720366a87c6", + "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yFree! Free!/A trip/to Mars/f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "e5a14bf044be69615aade89afcf1ab0389d5fc302a884d403579d1386a2400c089b0dbb387ed0f463f9ee342f8244d5a38cfbc0e819da9529fbff78368c9a982", + "The days of the digital watch are numbered. -Tom Stoppard", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yThe days of the digital watch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d", + }, + { + "420a1faa48919e14651bed45725abe0f7a58e0f099424c4e5a49194946e38b46c1f8034b18ef169b2e31050d1648e0b982386595f7df47da4b6fd18e55333015", + "Nepal premier won't resign.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yNepal premier\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r", + }, + { + "d926a863beadb20134db07683535c72007b0e695045876254f341ddcccde132a908c5af57baa6a6a9c63e6649bba0c213dc05fadcf9abccea09f23dcfb637fbe", + "For every action there is an equal and opposite government program.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yFor every action there is an equa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!", + }, + { + "9a98dd9bb67d0da7bf83da5313dff4fd60a4bac0094f1b05633690ffa7f6d61de9a1d4f8617937d560833a9aaa9ccafe3fd24db418d0e728833545cadd3ad92d", + "His money is twice tainted: 'taint yours and 'taint mine.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yHis money is twice tainted: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, + { + "d7fde2d2351efade52f4211d3746a0780a26eec3df9b2ed575368a8a1c09ec452402293a8ea4eceb5a4f60064ea29b13cdd86918cd7a4faf366160b009804107", + "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yThere is no reason for any individual to hav\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,", + }, + { + "b0f35ffa2697359c33a56f5c0cf715c7aeed96da9905ca2698acadb08fbc9e669bf566b6bd5d61a3e86dc22999bcc9f2224e33d1d4f32a228cf9d0349e2db518", + "It's a tiny change to the code and not completely disgusting. - Bob Manchek", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yIt's a tiny change to the code and no\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%", + }, + { + "3d2e5f91778c9e66f7e061293aaa8a8fc742dd3b2e4f483772464b1144189b49273e610e5cccd7a81a19ca1fa70f16b10f1a100a4d8c1372336be8484c64b311", + "size: a.out: bad magic", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!ysize: a.out\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f", + }, + { + "b2f68ff58ac015efb1c94c908b0d8c2bf06f491e4de8e6302c49016f7f8a33eac3e959856c7fddbc464de618701338a4b46f76dbfaf9a1e5262b5f40639771c7", + "The major problem is with sendmail. -Mark Horton", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yThe major problem is wit\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18", + }, + { + "d8c92db5fdf52cf8215e4df3b4909d29203ff4d00e9ad0b64a6a4e04dec5e74f62e7c35c7fb881bd5de95442123df8f57a489b0ae616bd326f84d10021121c57", + "Give me a rock, paper and scissors and I will move the world. CCFestoon", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yGive me a rock, paper and scissors a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$", + }, + { + "19a9f8dc0a233e464e8566ad3ca9b91e459a7b8c4780985b015776e1bf239a19bc233d0556343e2b0a9bc220900b4ebf4f8bdf89ff8efeaf79602d6849e6f72e", + "If the enemy is within range, then so are you.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yIf the enemy is within \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17", + }, + { + "00b4c41f307bde87301cdc5b5ab1ae9a592e8ecbb2021dd7bc4b34e2ace60741cc362560bec566ba35178595a91932b8d5357e2c9cec92d393b0fa7831852476", + "It's well we cannot hear the screams/That we create in others' dreams.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yIt's well we cannot hear the scream\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#", + }, + { + "91eccc3d5375fd026e4d6787874b1dce201cecd8a27dbded5065728cb2d09c58a3d467bb1faf353bf7ba567e005245d5321b55bc344f7c07b91cb6f26c959be7", + "You remind me of a TV show, but that's all right: I watch it anyway.", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yYou remind me of a TV show, but th\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"", + }, + { + "fabbbe22180f1f137cfdc9556d2570e775d1ae02a597ded43a72a40f9b485d500043b7be128fb9fcd982b83159a0d99aa855a9e7cc4240c00dc01a9bdf8218d7", + "C is as portable as Stonehedge!!", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yC is as portable\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10", + }, + { + "2ecdec235c1fa4fc2a154d8fba1dddb8a72a1ad73838b51d792331d143f8b96a9f6fcb0f34d7caa351fe6d88771c4f105040e0392f06e0621689d33b2f3ba92e", + "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yEven if I could be Shakespeare, I think I sh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,", + }, + { + "7ad681f6f96f82f7abfa7ecc0334e8fa16d3dc1cdc45b60b7af43fe4075d2357c0c1d60e98350f1afb1f2fe7a4d7cd2ad55b88e458e06b73c40b437331f5dab4", + "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yThe fugacity of a constituent in a mixture of gases at a given tem\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B", + }, + { + "833f9248ab4a3b9e5131f745fda1ffd2dd435b30e965957e78291c7ab73605fd1912b0794e5c233ab0a12d205a39778d19b83515d6a47003f19cdee51d98c7e0", + "How can you write a big system without C++? -Paul Glick", + "sha\aj\t\xe6g\xf3\xbc\xc9\b\xbbg\xae\x85\x84ʧ;l\x1f\x1f\x83٫\xfbA\xbdk[\xe0\xcd\x19\x13~!yHow can you write a big syst\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c", + }, +} + +func testHash(t *testing.T, name, in, outHex string, oneShotResult []byte, digestFunc hash.Hash) { + if calculated := hex.EncodeToString(oneShotResult); calculated != outHex { + t.Errorf("one-shot result for %s(%q) = %q, but expected %q", name, in, calculated, outHex) + return + } + + for pass := 0; pass < 3; pass++ { + if pass < 2 { + io.WriteString(digestFunc, in) + } else { + io.WriteString(digestFunc, in[:len(in)/2]) + digestFunc.Sum(nil) + io.WriteString(digestFunc, in[len(in)/2:]) + } + + if calculated := hex.EncodeToString(digestFunc.Sum(nil)); calculated != outHex { + t.Errorf("%s(%q) = %q (in pass #%d), but expected %q", name, in, calculated, pass, outHex) + } + digestFunc.Reset() + } +} + +func TestGolden(t *testing.T) { + tests := []struct { + name string + oneShotHash func(in []byte) []byte + digest hash.Hash + golden []sha512Test + }{ + { + "SHA512/224", + func(in []byte) []byte { a := Sum512_224(in); return a[:] }, + New512_224(), + golden224, + }, + { + "SHA512/256", + func(in []byte) []byte { a := Sum512_256(in); return a[:] }, + New512_256(), + golden256, + }, + { + "SHA384", + func(in []byte) []byte { a := Sum384(in); return a[:] }, + New384(), + golden384, + }, + { + "SHA512", + func(in []byte) []byte { a := Sum512(in); return a[:] }, + New(), + golden512, + }, + } + for _, tt := range tests { + for _, test := range tt.golden { + in := []byte(test.in) + testHash(t, tt.name, test.in, test.out, tt.oneShotHash(in), tt.digest) + } + } +} + +func TestGoldenMarshal(t *testing.T) { + tests := []struct { + name string + newHash func() hash.Hash + golden []sha512Test + }{ + {"512/224", New512_224, golden224}, + {"512/256", New512_256, golden256}, + {"384", New384, golden384}, + {"512", New, golden512}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + for _, test := range tt.golden { + h := tt.newHash() + h2 := tt.newHash() + + io.WriteString(h, test.in[:len(test.in)/2]) + + state, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { + t.Errorf("could not marshal: %v", err) + return + } + + if string(state) != test.halfState { + t.Errorf("New%s(%q) state = %q, want %q", tt.name, test.in, state, test.halfState) + continue + } + + if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil { + t.Errorf("could not unmarshal: %v", err) + return + } + + io.WriteString(h, test.in[len(test.in)/2:]) + io.WriteString(h2, test.in[len(test.in)/2:]) + + if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) { + t.Errorf("New%s(%q) = 0x%x != marshaled 0x%x", tt.name, test.in, actual, actual2) + } + } + }) + } +} + +func TestMarshalMismatch(t *testing.T) { + h := []func() hash.Hash{ + New, + New384, + New512_224, + New512_256, + } + + for i, fn1 := range h { + for j, fn2 := range h { + if i == j { + continue + } + + h1 := fn1() + h2 := fn2() + + state, err := h1.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { + t.Errorf("i=%d: could not marshal: %v", i, err) + continue + } + + if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err == nil { + t.Errorf("i=%d, j=%d: got no error, expected one: %v", i, j, err) + } + } + } +} + +func TestSize(t *testing.T) { + c := New() + if got := c.Size(); got != Size { + t.Errorf("Size = %d; want %d", got, Size) + } + c = New384() + if got := c.Size(); got != Size384 { + t.Errorf("New384.Size = %d; want %d", got, Size384) + } + c = New512_224() + if got := c.Size(); got != Size224 { + t.Errorf("New512224.Size = %d; want %d", got, Size224) + } + c = New512_256() + if got := c.Size(); got != Size256 { + t.Errorf("New512256.Size = %d; want %d", got, Size256) + } +} + +func TestBlockSize(t *testing.T) { + c := New() + if got := c.BlockSize(); got != BlockSize { + t.Errorf("BlockSize = %d; want %d", got, BlockSize) + } +} + +// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. +func TestBlockGeneric(t *testing.T) { + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*20) // arbitrary factor + rand.Read(buf) + blockGeneric(gen, buf) + block(asm, buf) + if *gen != *asm { + t.Error("block and blockGeneric resulted in different states") + } +} + +// Tests for unmarshaling hashes that have hashed a large amount of data +// The initial hash generation is omitted from the test, because it takes a long time. +// The test contains some already-generated states, and their expected sums +// Tests a problem that is outlined in GitHub issue #29541 +// The problem is triggered when an amount of data has been hashed for which +// the data length has a 1 in the 32nd bit. When casted to int, this changes +// the sign of the value, and causes the modulus operation to return a +// different result. +type unmarshalTest struct { + state string + sum string +} + +var largeUnmarshalTests = []unmarshalTest{ + // Data length: 6_565_544_823 + { + state: "sha\aηe\x0f\x0f\xe1r]#\aoJ!.{5B\xe4\x140\x91\xdd\x00a\xe1\xb3E&\xb9\xbb\aJ\x9f^\x9f\x03ͺD\x96H\x80\xb0X\x9d\xdeʸ\f\xf7:\xd5\xe6'\xb9\x93f\xddA\xf0~\xe1\x02\x14\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x87VCw", + sum: "12d612357a1dbc74a28883dff79b83e7d2b881ae40d7a67fd7305490bc8a641cd1ce9ece598192080d6e9ac7e75d5988567a58a9812991299eb99a04ecb69523", + }, + { + state: "sha\a2\xd2\xdc\xf5\xd7\xe2\xf9\x97\xaa\xe7}Fϱ\xbc\x8e\xbf\x12h\x83Z\xa1\xc7\xf5p>bfS T\xea\xee\x1e\xa6Z\x9c\xa4ڶ\u0086\bn\xe47\x8fsGs3\xe0\xda\\\x9dqZ\xa5\xf6\xd0kM\xa1\xf2\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xa7VCw", + sum: "94a04b9a901254cd94ca0313557e4be3ab1ca86e920c1f3efdc22d361e9ae12be66bc6d6dc5db79a0a4aa6eca6f293c1e9095bbae127ae405f6c325478343299", + }, +} + +func safeSum(h hash.Hash) (sum []byte, err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("sum panic: %v", r) + } + }() + + return h.Sum(nil), nil +} + +func TestLargeHashes(t *testing.T) { + for i, test := range largeUnmarshalTests { + + h := New() + if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { + t.Errorf("test %d could not unmarshal: %v", i, err) + continue + } + + sum, err := safeSum(h) + if err != nil { + t.Errorf("test %d could not sum: %v", i, err) + continue + } + + if fmt.Sprintf("%x", sum) != test.sum { + t.Errorf("test %d sum mismatch: expect %s got %x", i, test.sum, sum) + } + } +} + +var bench = New() +var buf = make([]byte, 8192) + +func benchmarkSize(b *testing.B, size int) { + b.SetBytes(int64(size)) + sum := make([]byte, bench.Size()) + for i := 0; i < b.N; i++ { + bench.Reset() + bench.Write(buf[:size]) + bench.Sum(sum[:0]) + } +} + +func BenchmarkHash8Bytes(b *testing.B) { + benchmarkSize(b, 8) +} + +func BenchmarkHash1K(b *testing.B) { + benchmarkSize(b, 1024) +} + +func BenchmarkHash8K(b *testing.B) { + benchmarkSize(b, 8192) +} diff --git a/src/crypto/sha512/sha512block.go b/src/crypto/sha512/sha512block.go new file mode 100644 index 0000000..81569c5 --- /dev/null +++ b/src/crypto/sha512/sha512block.go @@ -0,0 +1,144 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// SHA512 block step. +// In its own file so that a faster assembly or C version +// can be substituted easily. + +package sha512 + +import "math/bits" + +var _K = []uint64{ + 0x428a2f98d728ae22, + 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, + 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, + 0x59f111f1b605d019, + 0x923f82a4af194f9b, + 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, + 0x12835b0145706fbe, + 0x243185be4ee4b28c, + 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, + 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, + 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, + 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, + 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, + 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, + 0x76f988da831153b5, + 0x983e5152ee66dfab, + 0xa831c66d2db43210, + 0xb00327c898fb213f, + 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, + 0xd5a79147930aa725, + 0x06ca6351e003826f, + 0x142929670a0e6e70, + 0x27b70a8546d22ffc, + 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, + 0x53380d139d95b3df, + 0x650a73548baf63de, + 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, + 0x92722c851482353b, + 0xa2bfe8a14cf10364, + 0xa81a664bbc423001, + 0xc24b8b70d0f89791, + 0xc76c51a30654be30, + 0xd192e819d6ef5218, + 0xd69906245565a910, + 0xf40e35855771202a, + 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, + 0x1e376c085141ab53, + 0x2748774cdf8eeb99, + 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, + 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, + 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, + 0x78a5636f43172f60, + 0x84c87814a1f0ab72, + 0x8cc702081a6439ec, + 0x90befffa23631e28, + 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, + 0xc67178f2e372532b, + 0xca273eceea26619c, + 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, + 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, + 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, + 0x1b710b35131c471b, + 0x28db77f523047d84, + 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, + 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, + 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, + 0x6c44198c4a475817, +} + +func blockGeneric(dig *digest, p []byte) { + var w [80]uint64 + h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] + for len(p) >= chunk { + for i := 0; i < 16; i++ { + j := i * 8 + w[i] = uint64(p[j])<<56 | uint64(p[j+1])<<48 | uint64(p[j+2])<<40 | uint64(p[j+3])<<32 | + uint64(p[j+4])<<24 | uint64(p[j+5])<<16 | uint64(p[j+6])<<8 | uint64(p[j+7]) + } + for i := 16; i < 80; i++ { + v1 := w[i-2] + t1 := bits.RotateLeft64(v1, -19) ^ bits.RotateLeft64(v1, -61) ^ (v1 >> 6) + v2 := w[i-15] + t2 := bits.RotateLeft64(v2, -1) ^ bits.RotateLeft64(v2, -8) ^ (v2 >> 7) + + w[i] = t1 + w[i-7] + t2 + w[i-16] + } + + a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7 + + for i := 0; i < 80; i++ { + t1 := h + (bits.RotateLeft64(e, -14) ^ bits.RotateLeft64(e, -18) ^ bits.RotateLeft64(e, -41)) + ((e & f) ^ (^e & g)) + _K[i] + w[i] + + t2 := (bits.RotateLeft64(a, -28) ^ bits.RotateLeft64(a, -34) ^ bits.RotateLeft64(a, -39)) + ((a & b) ^ (a & c) ^ (b & c)) + + h = g + g = f + f = e + e = d + t1 + d = c + c = b + b = a + a = t1 + t2 + } + + h0 += a + h1 += b + h2 += c + h3 += d + h4 += e + h5 += f + h6 += g + h7 += h + + p = p[chunk:] + } + + dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7 +} diff --git a/src/crypto/sha512/sha512block_amd64.go b/src/crypto/sha512/sha512block_amd64.go new file mode 100644 index 0000000..e2386f2 --- /dev/null +++ b/src/crypto/sha512/sha512block_amd64.go @@ -0,0 +1,26 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 +// +build amd64 + +package sha512 + +import "internal/cpu" + +//go:noescape +func blockAVX2(dig *digest, p []byte) + +//go:noescape +func blockAMD64(dig *digest, p []byte) + +var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI1 && cpu.X86.HasBMI2 + +func block(dig *digest, p []byte) { + if useAVX2 { + blockAVX2(dig, p) + } else { + blockAMD64(dig, p) + } +} diff --git a/src/crypto/sha512/sha512block_amd64.s b/src/crypto/sha512/sha512block_amd64.s new file mode 100644 index 0000000..0fa0df2 --- /dev/null +++ b/src/crypto/sha512/sha512block_amd64.s @@ -0,0 +1,1468 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// SHA512 block routine. See sha512block.go for Go equivalent. +// +// The algorithm is detailed in FIPS 180-4: +// +// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf +// +// Wt = Mt; for 0 <= t <= 15 +// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 79 +// +// a = H0 +// b = H1 +// c = H2 +// d = H3 +// e = H4 +// f = H5 +// g = H6 +// h = H7 +// +// for t = 0 to 79 { +// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt +// T2 = BIGSIGMA0(a) + Maj(a,b,c) +// h = g +// g = f +// f = e +// e = d + T1 +// d = c +// c = b +// b = a +// a = T1 + T2 +// } +// +// H0 = a + H0 +// H1 = b + H1 +// H2 = c + H2 +// H3 = d + H3 +// H4 = e + H4 +// H5 = f + H5 +// H6 = g + H6 +// H7 = h + H7 + +// Wt = Mt; for 0 <= t <= 15 +#define MSGSCHEDULE0(index) \ + MOVQ (index*8)(SI), AX; \ + BSWAPQ AX; \ + MOVQ AX, (index*8)(BP) + +// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 79 +// SIGMA0(x) = ROTR(1,x) XOR ROTR(8,x) XOR SHR(7,x) +// SIGMA1(x) = ROTR(19,x) XOR ROTR(61,x) XOR SHR(6,x) +#define MSGSCHEDULE1(index) \ + MOVQ ((index-2)*8)(BP), AX; \ + MOVQ AX, CX; \ + RORQ $19, AX; \ + MOVQ CX, DX; \ + RORQ $61, CX; \ + SHRQ $6, DX; \ + MOVQ ((index-15)*8)(BP), BX; \ + XORQ CX, AX; \ + MOVQ BX, CX; \ + XORQ DX, AX; \ + RORQ $1, BX; \ + MOVQ CX, DX; \ + SHRQ $7, DX; \ + RORQ $8, CX; \ + ADDQ ((index-7)*8)(BP), AX; \ + XORQ CX, BX; \ + XORQ DX, BX; \ + ADDQ ((index-16)*8)(BP), BX; \ + ADDQ BX, AX; \ + MOVQ AX, ((index)*8)(BP) + +// Calculate T1 in AX - uses AX, CX and DX registers. +// h is also used as an accumulator. Wt is passed in AX. +// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt +// BIGSIGMA1(x) = ROTR(14,x) XOR ROTR(18,x) XOR ROTR(41,x) +// Ch(x, y, z) = (x AND y) XOR (NOT x AND z) +#define SHA512T1(const, e, f, g, h) \ + MOVQ $const, DX; \ + ADDQ AX, h; \ + MOVQ e, AX; \ + ADDQ DX, h; \ + MOVQ e, CX; \ + RORQ $14, AX; \ + MOVQ e, DX; \ + RORQ $18, CX; \ + XORQ CX, AX; \ + MOVQ e, CX; \ + RORQ $41, DX; \ + ANDQ f, CX; \ + XORQ AX, DX; \ + MOVQ e, AX; \ + NOTQ AX; \ + ADDQ DX, h; \ + ANDQ g, AX; \ + XORQ CX, AX; \ + ADDQ h, AX + +// Calculate T2 in BX - uses BX, CX, DX and DI registers. +// T2 = BIGSIGMA0(a) + Maj(a, b, c) +// BIGSIGMA0(x) = ROTR(28,x) XOR ROTR(34,x) XOR ROTR(39,x) +// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) +#define SHA512T2(a, b, c) \ + MOVQ a, DI; \ + MOVQ c, BX; \ + RORQ $28, DI; \ + MOVQ a, DX; \ + ANDQ b, BX; \ + RORQ $34, DX; \ + MOVQ a, CX; \ + ANDQ c, CX; \ + XORQ DX, DI; \ + XORQ CX, BX; \ + MOVQ a, DX; \ + MOVQ b, CX; \ + RORQ $39, DX; \ + ANDQ a, CX; \ + XORQ CX, BX; \ + XORQ DX, DI; \ + ADDQ DI, BX + +// Calculate T1 and T2, then e = d + T1 and a = T1 + T2. +// The values for e and a are stored in d and h, ready for rotation. +#define SHA512ROUND(index, const, a, b, c, d, e, f, g, h) \ + SHA512T1(const, e, f, g, h); \ + SHA512T2(a, b, c); \ + MOVQ BX, h; \ + ADDQ AX, d; \ + ADDQ AX, h + +#define SHA512ROUND0(index, const, a, b, c, d, e, f, g, h) \ + MSGSCHEDULE0(index); \ + SHA512ROUND(index, const, a, b, c, d, e, f, g, h) + +#define SHA512ROUND1(index, const, a, b, c, d, e, f, g, h) \ + MSGSCHEDULE1(index); \ + SHA512ROUND(index, const, a, b, c, d, e, f, g, h) + +TEXT ·blockAMD64(SB),0,$648-32 + MOVQ p_base+8(FP), SI + MOVQ p_len+16(FP), DX + SHRQ $7, DX + SHLQ $7, DX + + LEAQ (SI)(DX*1), DI + MOVQ DI, 640(SP) + CMPQ SI, DI + JEQ end + + MOVQ dig+0(FP), BP + MOVQ (0*8)(BP), R8 // a = H0 + MOVQ (1*8)(BP), R9 // b = H1 + MOVQ (2*8)(BP), R10 // c = H2 + MOVQ (3*8)(BP), R11 // d = H3 + MOVQ (4*8)(BP), R12 // e = H4 + MOVQ (5*8)(BP), R13 // f = H5 + MOVQ (6*8)(BP), R14 // g = H6 + MOVQ (7*8)(BP), R15 // h = H7 + +loop: + MOVQ SP, BP // message schedule + + SHA512ROUND0(0, 0x428a2f98d728ae22, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND0(1, 0x7137449123ef65cd, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND0(2, 0xb5c0fbcfec4d3b2f, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND0(3, 0xe9b5dba58189dbbc, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND0(4, 0x3956c25bf348b538, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND0(5, 0x59f111f1b605d019, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND0(6, 0x923f82a4af194f9b, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND0(7, 0xab1c5ed5da6d8118, R9, R10, R11, R12, R13, R14, R15, R8) + SHA512ROUND0(8, 0xd807aa98a3030242, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND0(9, 0x12835b0145706fbe, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND0(10, 0x243185be4ee4b28c, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND0(11, 0x550c7dc3d5ffb4e2, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND0(12, 0x72be5d74f27b896f, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND0(13, 0x80deb1fe3b1696b1, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND0(14, 0x9bdc06a725c71235, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND0(15, 0xc19bf174cf692694, R9, R10, R11, R12, R13, R14, R15, R8) + + SHA512ROUND1(16, 0xe49b69c19ef14ad2, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND1(17, 0xefbe4786384f25e3, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND1(18, 0x0fc19dc68b8cd5b5, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND1(19, 0x240ca1cc77ac9c65, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND1(20, 0x2de92c6f592b0275, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND1(21, 0x4a7484aa6ea6e483, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND1(22, 0x5cb0a9dcbd41fbd4, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND1(23, 0x76f988da831153b5, R9, R10, R11, R12, R13, R14, R15, R8) + SHA512ROUND1(24, 0x983e5152ee66dfab, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND1(25, 0xa831c66d2db43210, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND1(26, 0xb00327c898fb213f, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND1(27, 0xbf597fc7beef0ee4, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND1(28, 0xc6e00bf33da88fc2, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND1(29, 0xd5a79147930aa725, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND1(30, 0x06ca6351e003826f, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND1(31, 0x142929670a0e6e70, R9, R10, R11, R12, R13, R14, R15, R8) + SHA512ROUND1(32, 0x27b70a8546d22ffc, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND1(33, 0x2e1b21385c26c926, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND1(34, 0x4d2c6dfc5ac42aed, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND1(35, 0x53380d139d95b3df, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND1(36, 0x650a73548baf63de, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND1(37, 0x766a0abb3c77b2a8, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND1(38, 0x81c2c92e47edaee6, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND1(39, 0x92722c851482353b, R9, R10, R11, R12, R13, R14, R15, R8) + SHA512ROUND1(40, 0xa2bfe8a14cf10364, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND1(41, 0xa81a664bbc423001, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND1(42, 0xc24b8b70d0f89791, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND1(43, 0xc76c51a30654be30, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND1(44, 0xd192e819d6ef5218, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND1(45, 0xd69906245565a910, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND1(46, 0xf40e35855771202a, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND1(47, 0x106aa07032bbd1b8, R9, R10, R11, R12, R13, R14, R15, R8) + SHA512ROUND1(48, 0x19a4c116b8d2d0c8, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND1(49, 0x1e376c085141ab53, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND1(50, 0x2748774cdf8eeb99, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND1(51, 0x34b0bcb5e19b48a8, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND1(52, 0x391c0cb3c5c95a63, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND1(53, 0x4ed8aa4ae3418acb, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND1(54, 0x5b9cca4f7763e373, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND1(55, 0x682e6ff3d6b2b8a3, R9, R10, R11, R12, R13, R14, R15, R8) + SHA512ROUND1(56, 0x748f82ee5defb2fc, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND1(57, 0x78a5636f43172f60, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND1(58, 0x84c87814a1f0ab72, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND1(59, 0x8cc702081a6439ec, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND1(60, 0x90befffa23631e28, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND1(61, 0xa4506cebde82bde9, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND1(62, 0xbef9a3f7b2c67915, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND1(63, 0xc67178f2e372532b, R9, R10, R11, R12, R13, R14, R15, R8) + SHA512ROUND1(64, 0xca273eceea26619c, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND1(65, 0xd186b8c721c0c207, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND1(66, 0xeada7dd6cde0eb1e, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND1(67, 0xf57d4f7fee6ed178, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND1(68, 0x06f067aa72176fba, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND1(69, 0x0a637dc5a2c898a6, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND1(70, 0x113f9804bef90dae, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND1(71, 0x1b710b35131c471b, R9, R10, R11, R12, R13, R14, R15, R8) + SHA512ROUND1(72, 0x28db77f523047d84, R8, R9, R10, R11, R12, R13, R14, R15) + SHA512ROUND1(73, 0x32caab7b40c72493, R15, R8, R9, R10, R11, R12, R13, R14) + SHA512ROUND1(74, 0x3c9ebe0a15c9bebc, R14, R15, R8, R9, R10, R11, R12, R13) + SHA512ROUND1(75, 0x431d67c49c100d4c, R13, R14, R15, R8, R9, R10, R11, R12) + SHA512ROUND1(76, 0x4cc5d4becb3e42b6, R12, R13, R14, R15, R8, R9, R10, R11) + SHA512ROUND1(77, 0x597f299cfc657e2a, R11, R12, R13, R14, R15, R8, R9, R10) + SHA512ROUND1(78, 0x5fcb6fab3ad6faec, R10, R11, R12, R13, R14, R15, R8, R9) + SHA512ROUND1(79, 0x6c44198c4a475817, R9, R10, R11, R12, R13, R14, R15, R8) + + MOVQ dig+0(FP), BP + ADDQ (0*8)(BP), R8 // H0 = a + H0 + MOVQ R8, (0*8)(BP) + ADDQ (1*8)(BP), R9 // H1 = b + H1 + MOVQ R9, (1*8)(BP) + ADDQ (2*8)(BP), R10 // H2 = c + H2 + MOVQ R10, (2*8)(BP) + ADDQ (3*8)(BP), R11 // H3 = d + H3 + MOVQ R11, (3*8)(BP) + ADDQ (4*8)(BP), R12 // H4 = e + H4 + MOVQ R12, (4*8)(BP) + ADDQ (5*8)(BP), R13 // H5 = f + H5 + MOVQ R13, (5*8)(BP) + ADDQ (6*8)(BP), R14 // H6 = g + H6 + MOVQ R14, (6*8)(BP) + ADDQ (7*8)(BP), R15 // H7 = h + H7 + MOVQ R15, (7*8)(BP) + + ADDQ $128, SI + CMPQ SI, 640(SP) + JB loop + +end: + RET + +// Version below is based on "Fast SHA512 Implementations on Intel +// Architecture Processors" White-paper +// https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-sha512-implementations-ia-processors-paper.pdf +// AVX2 version by Intel, same algorithm in Linux kernel: +// https://github.com/torvalds/linux/blob/master/arch/x86/crypto/sha512-avx2-asm.S + +// James Guilford +// Kirk Yap +// Tim Chen +// David Cote +// Aleksey Sidorov + +#define YFER_SIZE (4*8) +#define SRND_SIZE (1*8) +#define INP_SIZE (1*8) + +#define frame_YFER (0) +#define frame_SRND (frame_YFER + YFER_SIZE) +#define frame_INP (frame_SRND + SRND_SIZE) +#define frame_INPEND (frame_INP + INP_SIZE) + +#define addm(p1, p2) \ + ADDQ p1, p2; \ + MOVQ p2, p1 + +#define COPY_YMM_AND_BSWAP(p1, p2, p3) \ + VMOVDQU p2, p1; \ + VPSHUFB p3, p1, p1 + +#define MY_VPALIGNR(YDST, YSRC1, YSRC2, RVAL) \ + VPERM2F128 $0x3, YSRC2, YSRC1, YDST; \ + VPALIGNR $RVAL, YSRC2, YDST, YDST + +DATA PSHUFFLE_BYTE_FLIP_MASK<>+0x00(SB)/8, $0x0001020304050607 +DATA PSHUFFLE_BYTE_FLIP_MASK<>+0x08(SB)/8, $0x08090a0b0c0d0e0f +DATA PSHUFFLE_BYTE_FLIP_MASK<>+0x10(SB)/8, $0x1011121314151617 +DATA PSHUFFLE_BYTE_FLIP_MASK<>+0x18(SB)/8, $0x18191a1b1c1d1e1f + +GLOBL PSHUFFLE_BYTE_FLIP_MASK<>(SB), (NOPTR+RODATA), $32 + +DATA MASK_YMM_LO<>+0x00(SB)/8, $0x0000000000000000 +DATA MASK_YMM_LO<>+0x08(SB)/8, $0x0000000000000000 +DATA MASK_YMM_LO<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF +DATA MASK_YMM_LO<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF + +GLOBL MASK_YMM_LO<>(SB), (NOPTR+RODATA), $32 + +TEXT ·blockAVX2(SB), NOSPLIT, $56-32 + MOVQ dig+0(FP), SI + MOVQ p_base+8(FP), DI + MOVQ p_len+16(FP), DX + + SHRQ $7, DX + SHLQ $7, DX + + JZ done_hash + ADDQ DI, DX + MOVQ DX, frame_INPEND(SP) + + MOVQ (0*8)(SI), AX + MOVQ (1*8)(SI), BX + MOVQ (2*8)(SI), CX + MOVQ (3*8)(SI), R8 + MOVQ (4*8)(SI), DX + MOVQ (5*8)(SI), R9 + MOVQ (6*8)(SI), R10 + MOVQ (7*8)(SI), R11 + + VMOVDQU PSHUFFLE_BYTE_FLIP_MASK<>(SB), Y9 + +loop0: + MOVQ ·_K+0(SB), BP + + // byte swap first 16 dwords + COPY_YMM_AND_BSWAP(Y4, (0*32)(DI), Y9) + COPY_YMM_AND_BSWAP(Y5, (1*32)(DI), Y9) + COPY_YMM_AND_BSWAP(Y6, (2*32)(DI), Y9) + COPY_YMM_AND_BSWAP(Y7, (3*32)(DI), Y9) + + MOVQ DI, frame_INP(SP) + + // schedule 64 input dwords, by doing 12 rounds of 4 each + MOVQ $4, frame_SRND(SP) + +loop1: + VPADDQ (BP), Y4, Y0 + VMOVDQU Y0, frame_YFER(SP) + + MY_VPALIGNR(Y0, Y7, Y6, 8) + + VPADDQ Y4, Y0, Y0 + + MY_VPALIGNR(Y1, Y5, Y4, 8) + + VPSRLQ $1, Y1, Y2 + VPSLLQ $(64-1), Y1, Y3 + VPOR Y2, Y3, Y3 + + VPSRLQ $7, Y1, Y8 + + MOVQ AX, DI + RORXQ $41, DX, R13 + RORXQ $18, DX, R14 + ADDQ frame_YFER(SP), R11 + ORQ CX, DI + MOVQ R9, R15 + RORXQ $34, AX, R12 + + XORQ R14, R13 + XORQ R10, R15 + RORXQ $14, DX, R14 + + ANDQ DX, R15 + XORQ R14, R13 + RORXQ $39, AX, R14 + ADDQ R11, R8 + + ANDQ BX, DI + XORQ R12, R14 + RORXQ $28, AX, R12 + + XORQ R10, R15 + XORQ R12, R14 + MOVQ AX, R12 + ANDQ CX, R12 + + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R11 + + ADDQ R15, R8 + + ADDQ R15, R11 + ADDQ DI, R11 + + VPSRLQ $8, Y1, Y2 + VPSLLQ $(64-8), Y1, Y1 + VPOR Y2, Y1, Y1 + + VPXOR Y8, Y3, Y3 + VPXOR Y1, Y3, Y1 + + VPADDQ Y1, Y0, Y0 + + VPERM2F128 $0x0, Y0, Y0, Y4 + + VPAND MASK_YMM_LO<>(SB), Y0, Y0 + + VPERM2F128 $0x11, Y7, Y7, Y2 + VPSRLQ $6, Y2, Y8 + + MOVQ R11, DI + RORXQ $41, R8, R13 + RORXQ $18, R8, R14 + ADDQ 1*8+frame_YFER(SP), R10 + ORQ BX, DI + + MOVQ DX, R15 + RORXQ $34, R11, R12 + XORQ R14, R13 + XORQ R9, R15 + + RORXQ $14, R8, R14 + XORQ R14, R13 + RORXQ $39, R11, R14 + ANDQ R8, R15 + ADDQ R10, CX + + ANDQ AX, DI + XORQ R12, R14 + + RORXQ $28, R11, R12 + XORQ R9, R15 + + XORQ R12, R14 + MOVQ R11, R12 + ANDQ BX, R12 + ADDQ R13, R15 + + ORQ R12, DI + ADDQ R14, R10 + + ADDQ R15, CX + ADDQ R15, R10 + ADDQ DI, R10 + + VPSRLQ $19, Y2, Y3 + VPSLLQ $(64-19), Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $61, Y2, Y3 + VPSLLQ $(64-61), Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + + VPADDQ Y8, Y4, Y4 + + VPSRLQ $6, Y4, Y8 + + MOVQ R10, DI + RORXQ $41, CX, R13 + ADDQ 2*8+frame_YFER(SP), R9 + + RORXQ $18, CX, R14 + ORQ AX, DI + MOVQ R8, R15 + XORQ DX, R15 + + RORXQ $34, R10, R12 + XORQ R14, R13 + ANDQ CX, R15 + + RORXQ $14, CX, R14 + ADDQ R9, BX + ANDQ R11, DI + + XORQ R14, R13 + RORXQ $39, R10, R14 + XORQ DX, R15 + + XORQ R12, R14 + RORXQ $28, R10, R12 + + XORQ R12, R14 + MOVQ R10, R12 + ANDQ AX, R12 + ADDQ R13, R15 + + ORQ R12, DI + ADDQ R14, R9 + ADDQ R15, BX + ADDQ R15, R9 + + ADDQ DI, R9 + + VPSRLQ $19, Y4, Y3 + VPSLLQ $(64-19), Y4, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $61, Y4, Y3 + VPSLLQ $(64-61), Y4, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + + VPADDQ Y8, Y0, Y2 + + VPBLENDD $0xF0, Y2, Y4, Y4 + + MOVQ R9, DI + RORXQ $41, BX, R13 + RORXQ $18, BX, R14 + ADDQ 3*8+frame_YFER(SP), DX + ORQ R11, DI + + MOVQ CX, R15 + RORXQ $34, R9, R12 + XORQ R14, R13 + XORQ R8, R15 + + RORXQ $14, BX, R14 + ANDQ BX, R15 + ADDQ DX, AX + ANDQ R10, DI + + XORQ R14, R13 + XORQ R8, R15 + + RORXQ $39, R9, R14 + ADDQ R13, R15 + + XORQ R12, R14 + ADDQ R15, AX + + RORXQ $28, R9, R12 + + XORQ R12, R14 + MOVQ R9, R12 + ANDQ R11, R12 + ORQ R12, DI + + ADDQ R14, DX + ADDQ R15, DX + ADDQ DI, DX + + VPADDQ 1*32(BP), Y5, Y0 + VMOVDQU Y0, frame_YFER(SP) + + MY_VPALIGNR(Y0, Y4, Y7, 8) + + VPADDQ Y5, Y0, Y0 + + MY_VPALIGNR(Y1, Y6, Y5, 8) + + VPSRLQ $1, Y1, Y2 + VPSLLQ $(64-1), Y1, Y3 + VPOR Y2, Y3, Y3 + + VPSRLQ $7, Y1, Y8 + + MOVQ DX, DI + RORXQ $41, AX, R13 + RORXQ $18, AX, R14 + ADDQ frame_YFER(SP), R8 + ORQ R10, DI + MOVQ BX, R15 + RORXQ $34, DX, R12 + + XORQ R14, R13 + XORQ CX, R15 + RORXQ $14, AX, R14 + + ANDQ AX, R15 + XORQ R14, R13 + RORXQ $39, DX, R14 + ADDQ R8, R11 + + ANDQ R9, DI + XORQ R12, R14 + RORXQ $28, DX, R12 + + XORQ CX, R15 + XORQ R12, R14 + MOVQ DX, R12 + ANDQ R10, R12 + + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R8 + + ADDQ R15, R11 + + ADDQ R15, R8 + ADDQ DI, R8 + + VPSRLQ $8, Y1, Y2 + VPSLLQ $(64-8), Y1, Y1 + VPOR Y2, Y1, Y1 + + VPXOR Y8, Y3, Y3 + VPXOR Y1, Y3, Y1 + + VPADDQ Y1, Y0, Y0 + + VPERM2F128 $0x0, Y0, Y0, Y5 + + VPAND MASK_YMM_LO<>(SB), Y0, Y0 + + VPERM2F128 $0x11, Y4, Y4, Y2 + VPSRLQ $6, Y2, Y8 + + MOVQ R8, DI + RORXQ $41, R11, R13 + RORXQ $18, R11, R14 + ADDQ 1*8+frame_YFER(SP), CX + ORQ R9, DI + + MOVQ AX, R15 + RORXQ $34, R8, R12 + XORQ R14, R13 + XORQ BX, R15 + + RORXQ $14, R11, R14 + XORQ R14, R13 + RORXQ $39, R8, R14 + ANDQ R11, R15 + ADDQ CX, R10 + + ANDQ DX, DI + XORQ R12, R14 + + RORXQ $28, R8, R12 + XORQ BX, R15 + + XORQ R12, R14 + MOVQ R8, R12 + ANDQ R9, R12 + ADDQ R13, R15 + + ORQ R12, DI + ADDQ R14, CX + + ADDQ R15, R10 + ADDQ R15, CX + ADDQ DI, CX + + VPSRLQ $19, Y2, Y3 + VPSLLQ $(64-19), Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $61, Y2, Y3 + VPSLLQ $(64-61), Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + + VPADDQ Y8, Y5, Y5 + + VPSRLQ $6, Y5, Y8 + + MOVQ CX, DI + RORXQ $41, R10, R13 + ADDQ 2*8+frame_YFER(SP), BX + + RORXQ $18, R10, R14 + ORQ DX, DI + MOVQ R11, R15 + XORQ AX, R15 + + RORXQ $34, CX, R12 + XORQ R14, R13 + ANDQ R10, R15 + + RORXQ $14, R10, R14 + ADDQ BX, R9 + ANDQ R8, DI + + XORQ R14, R13 + RORXQ $39, CX, R14 + XORQ AX, R15 + + XORQ R12, R14 + RORXQ $28, CX, R12 + + XORQ R12, R14 + MOVQ CX, R12 + ANDQ DX, R12 + ADDQ R13, R15 + + ORQ R12, DI + ADDQ R14, BX + ADDQ R15, R9 + ADDQ R15, BX + + ADDQ DI, BX + + VPSRLQ $19, Y5, Y3 + VPSLLQ $(64-19), Y5, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $61, Y5, Y3 + VPSLLQ $(64-61), Y5, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + + VPADDQ Y8, Y0, Y2 + + VPBLENDD $0xF0, Y2, Y5, Y5 + + MOVQ BX, DI + RORXQ $41, R9, R13 + RORXQ $18, R9, R14 + ADDQ 3*8+frame_YFER(SP), AX + ORQ R8, DI + + MOVQ R10, R15 + RORXQ $34, BX, R12 + XORQ R14, R13 + XORQ R11, R15 + + RORXQ $14, R9, R14 + ANDQ R9, R15 + ADDQ AX, DX + ANDQ CX, DI + + XORQ R14, R13 + XORQ R11, R15 + + RORXQ $39, BX, R14 + ADDQ R13, R15 + + XORQ R12, R14 + ADDQ R15, DX + + RORXQ $28, BX, R12 + + XORQ R12, R14 + MOVQ BX, R12 + ANDQ R8, R12 + ORQ R12, DI + + ADDQ R14, AX + ADDQ R15, AX + ADDQ DI, AX + + VPADDQ 2*32(BP), Y6, Y0 + VMOVDQU Y0, frame_YFER(SP) + + MY_VPALIGNR(Y0, Y5, Y4, 8) + + VPADDQ Y6, Y0, Y0 + + MY_VPALIGNR(Y1, Y7, Y6, 8) + + VPSRLQ $1, Y1, Y2 + VPSLLQ $(64-1), Y1, Y3 + VPOR Y2, Y3, Y3 + + VPSRLQ $7, Y1, Y8 + + MOVQ AX, DI + RORXQ $41, DX, R13 + RORXQ $18, DX, R14 + ADDQ frame_YFER(SP), R11 + ORQ CX, DI + MOVQ R9, R15 + RORXQ $34, AX, R12 + + XORQ R14, R13 + XORQ R10, R15 + RORXQ $14, DX, R14 + + ANDQ DX, R15 + XORQ R14, R13 + RORXQ $39, AX, R14 + ADDQ R11, R8 + + ANDQ BX, DI + XORQ R12, R14 + RORXQ $28, AX, R12 + + XORQ R10, R15 + XORQ R12, R14 + MOVQ AX, R12 + ANDQ CX, R12 + + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R11 + + ADDQ R15, R8 + + ADDQ R15, R11 + ADDQ DI, R11 + + VPSRLQ $8, Y1, Y2 + VPSLLQ $(64-8), Y1, Y1 + VPOR Y2, Y1, Y1 + + VPXOR Y8, Y3, Y3 + VPXOR Y1, Y3, Y1 + + VPADDQ Y1, Y0, Y0 + + VPERM2F128 $0x0, Y0, Y0, Y6 + + VPAND MASK_YMM_LO<>(SB), Y0, Y0 + + VPERM2F128 $0x11, Y5, Y5, Y2 + VPSRLQ $6, Y2, Y8 + + MOVQ R11, DI + RORXQ $41, R8, R13 + RORXQ $18, R8, R14 + ADDQ 1*8+frame_YFER(SP), R10 + ORQ BX, DI + + MOVQ DX, R15 + RORXQ $34, R11, R12 + XORQ R14, R13 + XORQ R9, R15 + + RORXQ $14, R8, R14 + XORQ R14, R13 + RORXQ $39, R11, R14 + ANDQ R8, R15 + ADDQ R10, CX + + ANDQ AX, DI + XORQ R12, R14 + + RORXQ $28, R11, R12 + XORQ R9, R15 + + XORQ R12, R14 + MOVQ R11, R12 + ANDQ BX, R12 + ADDQ R13, R15 + + ORQ R12, DI + ADDQ R14, R10 + + ADDQ R15, CX + ADDQ R15, R10 + ADDQ DI, R10 + + VPSRLQ $19, Y2, Y3 + VPSLLQ $(64-19), Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $61, Y2, Y3 + VPSLLQ $(64-61), Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + + VPADDQ Y8, Y6, Y6 + + VPSRLQ $6, Y6, Y8 + + MOVQ R10, DI + RORXQ $41, CX, R13 + ADDQ 2*8+frame_YFER(SP), R9 + + RORXQ $18, CX, R14 + ORQ AX, DI + MOVQ R8, R15 + XORQ DX, R15 + + RORXQ $34, R10, R12 + XORQ R14, R13 + ANDQ CX, R15 + + RORXQ $14, CX, R14 + ADDQ R9, BX + ANDQ R11, DI + + XORQ R14, R13 + RORXQ $39, R10, R14 + XORQ DX, R15 + + XORQ R12, R14 + RORXQ $28, R10, R12 + + XORQ R12, R14 + MOVQ R10, R12 + ANDQ AX, R12 + ADDQ R13, R15 + + ORQ R12, DI + ADDQ R14, R9 + ADDQ R15, BX + ADDQ R15, R9 + + ADDQ DI, R9 + + VPSRLQ $19, Y6, Y3 + VPSLLQ $(64-19), Y6, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $61, Y6, Y3 + VPSLLQ $(64-61), Y6, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + + VPADDQ Y8, Y0, Y2 + + VPBLENDD $0xF0, Y2, Y6, Y6 + + MOVQ R9, DI + RORXQ $41, BX, R13 + RORXQ $18, BX, R14 + ADDQ 3*8+frame_YFER(SP), DX + ORQ R11, DI + + MOVQ CX, R15 + RORXQ $34, R9, R12 + XORQ R14, R13 + XORQ R8, R15 + + RORXQ $14, BX, R14 + ANDQ BX, R15 + ADDQ DX, AX + ANDQ R10, DI + + XORQ R14, R13 + XORQ R8, R15 + + RORXQ $39, R9, R14 + ADDQ R13, R15 + + XORQ R12, R14 + ADDQ R15, AX + + RORXQ $28, R9, R12 + + XORQ R12, R14 + MOVQ R9, R12 + ANDQ R11, R12 + ORQ R12, DI + + ADDQ R14, DX + ADDQ R15, DX + ADDQ DI, DX + + VPADDQ 3*32(BP), Y7, Y0 + VMOVDQU Y0, frame_YFER(SP) + ADDQ $(4*32), BP + + MY_VPALIGNR(Y0, Y6, Y5, 8) + + VPADDQ Y7, Y0, Y0 + + MY_VPALIGNR(Y1, Y4, Y7, 8) + + VPSRLQ $1, Y1, Y2 + VPSLLQ $(64-1), Y1, Y3 + VPOR Y2, Y3, Y3 + + VPSRLQ $7, Y1, Y8 + + MOVQ DX, DI + RORXQ $41, AX, R13 + RORXQ $18, AX, R14 + ADDQ frame_YFER(SP), R8 + ORQ R10, DI + MOVQ BX, R15 + RORXQ $34, DX, R12 + + XORQ R14, R13 + XORQ CX, R15 + RORXQ $14, AX, R14 + + ANDQ AX, R15 + XORQ R14, R13 + RORXQ $39, DX, R14 + ADDQ R8, R11 + + ANDQ R9, DI + XORQ R12, R14 + RORXQ $28, DX, R12 + + XORQ CX, R15 + XORQ R12, R14 + MOVQ DX, R12 + ANDQ R10, R12 + + ADDQ R13, R15 + ORQ R12, DI + ADDQ R14, R8 + + ADDQ R15, R11 + + ADDQ R15, R8 + ADDQ DI, R8 + + VPSRLQ $8, Y1, Y2 + VPSLLQ $(64-8), Y1, Y1 + VPOR Y2, Y1, Y1 + + VPXOR Y8, Y3, Y3 + VPXOR Y1, Y3, Y1 + + VPADDQ Y1, Y0, Y0 + + VPERM2F128 $0x0, Y0, Y0, Y7 + + VPAND MASK_YMM_LO<>(SB), Y0, Y0 + + VPERM2F128 $0x11, Y6, Y6, Y2 + VPSRLQ $6, Y2, Y8 + + MOVQ R8, DI + RORXQ $41, R11, R13 + RORXQ $18, R11, R14 + ADDQ 1*8+frame_YFER(SP), CX + ORQ R9, DI + + MOVQ AX, R15 + RORXQ $34, R8, R12 + XORQ R14, R13 + XORQ BX, R15 + + RORXQ $14, R11, R14 + XORQ R14, R13 + RORXQ $39, R8, R14 + ANDQ R11, R15 + ADDQ CX, R10 + + ANDQ DX, DI + XORQ R12, R14 + + RORXQ $28, R8, R12 + XORQ BX, R15 + + XORQ R12, R14 + MOVQ R8, R12 + ANDQ R9, R12 + ADDQ R13, R15 + + ORQ R12, DI + ADDQ R14, CX + + ADDQ R15, R10 + ADDQ R15, CX + ADDQ DI, CX + + VPSRLQ $19, Y2, Y3 + VPSLLQ $(64-19), Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $61, Y2, Y3 + VPSLLQ $(64-61), Y2, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + + VPADDQ Y8, Y7, Y7 + + VPSRLQ $6, Y7, Y8 + + MOVQ CX, DI + RORXQ $41, R10, R13 + ADDQ 2*8+frame_YFER(SP), BX + + RORXQ $18, R10, R14 + ORQ DX, DI + MOVQ R11, R15 + XORQ AX, R15 + + RORXQ $34, CX, R12 + XORQ R14, R13 + ANDQ R10, R15 + + RORXQ $14, R10, R14 + ADDQ BX, R9 + ANDQ R8, DI + + XORQ R14, R13 + RORXQ $39, CX, R14 + XORQ AX, R15 + + XORQ R12, R14 + RORXQ $28, CX, R12 + + XORQ R12, R14 + MOVQ CX, R12 + ANDQ DX, R12 + ADDQ R13, R15 + + ORQ R12, DI + ADDQ R14, BX + ADDQ R15, R9 + ADDQ R15, BX + + ADDQ DI, BX + + VPSRLQ $19, Y7, Y3 + VPSLLQ $(64-19), Y7, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + VPSRLQ $61, Y7, Y3 + VPSLLQ $(64-61), Y7, Y1 + VPOR Y1, Y3, Y3 + VPXOR Y3, Y8, Y8 + + VPADDQ Y8, Y0, Y2 + + VPBLENDD $0xF0, Y2, Y7, Y7 + + MOVQ BX, DI + RORXQ $41, R9, R13 + RORXQ $18, R9, R14 + ADDQ 3*8+frame_YFER(SP), AX + ORQ R8, DI + + MOVQ R10, R15 + RORXQ $34, BX, R12 + XORQ R14, R13 + XORQ R11, R15 + + RORXQ $14, R9, R14 + ANDQ R9, R15 + ADDQ AX, DX + ANDQ CX, DI + + XORQ R14, R13 + XORQ R11, R15 + + RORXQ $39, BX, R14 + ADDQ R13, R15 + + XORQ R12, R14 + ADDQ R15, DX + + RORXQ $28, BX, R12 + + XORQ R12, R14 + MOVQ BX, R12 + ANDQ R8, R12 + ORQ R12, DI + + ADDQ R14, AX + ADDQ R15, AX + ADDQ DI, AX + + SUBQ $1, frame_SRND(SP) + JNE loop1 + + MOVQ $2, frame_SRND(SP) + +loop2: + VPADDQ (BP), Y4, Y0 + VMOVDQU Y0, frame_YFER(SP) + + MOVQ R9, R15 + RORXQ $41, DX, R13 + RORXQ $18, DX, R14 + XORQ R10, R15 + + XORQ R14, R13 + RORXQ $14, DX, R14 + ANDQ DX, R15 + + XORQ R14, R13 + RORXQ $34, AX, R12 + XORQ R10, R15 + RORXQ $39, AX, R14 + MOVQ AX, DI + + XORQ R12, R14 + RORXQ $28, AX, R12 + ADDQ frame_YFER(SP), R11 + ORQ CX, DI + + XORQ R12, R14 + MOVQ AX, R12 + ANDQ BX, DI + ANDQ CX, R12 + ADDQ R13, R15 + + ADDQ R11, R8 + ORQ R12, DI + ADDQ R14, R11 + + ADDQ R15, R8 + + ADDQ R15, R11 + MOVQ DX, R15 + RORXQ $41, R8, R13 + RORXQ $18, R8, R14 + XORQ R9, R15 + + XORQ R14, R13 + RORXQ $14, R8, R14 + ANDQ R8, R15 + ADDQ DI, R11 + + XORQ R14, R13 + RORXQ $34, R11, R12 + XORQ R9, R15 + RORXQ $39, R11, R14 + MOVQ R11, DI + + XORQ R12, R14 + RORXQ $28, R11, R12 + ADDQ 8*1+frame_YFER(SP), R10 + ORQ BX, DI + + XORQ R12, R14 + MOVQ R11, R12 + ANDQ AX, DI + ANDQ BX, R12 + ADDQ R13, R15 + + ADDQ R10, CX + ORQ R12, DI + ADDQ R14, R10 + + ADDQ R15, CX + + ADDQ R15, R10 + MOVQ R8, R15 + RORXQ $41, CX, R13 + RORXQ $18, CX, R14 + XORQ DX, R15 + + XORQ R14, R13 + RORXQ $14, CX, R14 + ANDQ CX, R15 + ADDQ DI, R10 + + XORQ R14, R13 + RORXQ $34, R10, R12 + XORQ DX, R15 + RORXQ $39, R10, R14 + MOVQ R10, DI + + XORQ R12, R14 + RORXQ $28, R10, R12 + ADDQ 8*2+frame_YFER(SP), R9 + ORQ AX, DI + + XORQ R12, R14 + MOVQ R10, R12 + ANDQ R11, DI + ANDQ AX, R12 + ADDQ R13, R15 + + ADDQ R9, BX + ORQ R12, DI + ADDQ R14, R9 + + ADDQ R15, BX + + ADDQ R15, R9 + MOVQ CX, R15 + RORXQ $41, BX, R13 + RORXQ $18, BX, R14 + XORQ R8, R15 + + XORQ R14, R13 + RORXQ $14, BX, R14 + ANDQ BX, R15 + ADDQ DI, R9 + + XORQ R14, R13 + RORXQ $34, R9, R12 + XORQ R8, R15 + RORXQ $39, R9, R14 + MOVQ R9, DI + + XORQ R12, R14 + RORXQ $28, R9, R12 + ADDQ 8*3+frame_YFER(SP), DX + ORQ R11, DI + + XORQ R12, R14 + MOVQ R9, R12 + ANDQ R10, DI + ANDQ R11, R12 + ADDQ R13, R15 + + ADDQ DX, AX + ORQ R12, DI + ADDQ R14, DX + + ADDQ R15, AX + + ADDQ R15, DX + + ADDQ DI, DX + + VPADDQ 1*32(BP), Y5, Y0 + VMOVDQU Y0, frame_YFER(SP) + ADDQ $(2*32), BP + + MOVQ BX, R15 + RORXQ $41, AX, R13 + RORXQ $18, AX, R14 + XORQ CX, R15 + + XORQ R14, R13 + RORXQ $14, AX, R14 + ANDQ AX, R15 + + XORQ R14, R13 + RORXQ $34, DX, R12 + XORQ CX, R15 + RORXQ $39, DX, R14 + MOVQ DX, DI + + XORQ R12, R14 + RORXQ $28, DX, R12 + ADDQ frame_YFER(SP), R8 + ORQ R10, DI + + XORQ R12, R14 + MOVQ DX, R12 + ANDQ R9, DI + ANDQ R10, R12 + ADDQ R13, R15 + + ADDQ R8, R11 + ORQ R12, DI + ADDQ R14, R8 + + ADDQ R15, R11 + + ADDQ R15, R8 + MOVQ AX, R15 + RORXQ $41, R11, R13 + RORXQ $18, R11, R14 + XORQ BX, R15 + + XORQ R14, R13 + RORXQ $14, R11, R14 + ANDQ R11, R15 + ADDQ DI, R8 + + XORQ R14, R13 + RORXQ $34, R8, R12 + XORQ BX, R15 + RORXQ $39, R8, R14 + MOVQ R8, DI + + XORQ R12, R14 + RORXQ $28, R8, R12 + ADDQ 8*1+frame_YFER(SP), CX + ORQ R9, DI + + XORQ R12, R14 + MOVQ R8, R12 + ANDQ DX, DI + ANDQ R9, R12 + ADDQ R13, R15 + + ADDQ CX, R10 + ORQ R12, DI + ADDQ R14, CX + + ADDQ R15, R10 + + ADDQ R15, CX + MOVQ R11, R15 + RORXQ $41, R10, R13 + RORXQ $18, R10, R14 + XORQ AX, R15 + + XORQ R14, R13 + RORXQ $14, R10, R14 + ANDQ R10, R15 + ADDQ DI, CX + + XORQ R14, R13 + RORXQ $34, CX, R12 + XORQ AX, R15 + RORXQ $39, CX, R14 + MOVQ CX, DI + + XORQ R12, R14 + RORXQ $28, CX, R12 + ADDQ 8*2+frame_YFER(SP), BX + ORQ DX, DI + + XORQ R12, R14 + MOVQ CX, R12 + ANDQ R8, DI + ANDQ DX, R12 + ADDQ R13, R15 + + ADDQ BX, R9 + ORQ R12, DI + ADDQ R14, BX + + ADDQ R15, R9 + + ADDQ R15, BX + MOVQ R10, R15 + RORXQ $41, R9, R13 + RORXQ $18, R9, R14 + XORQ R11, R15 + + XORQ R14, R13 + RORXQ $14, R9, R14 + ANDQ R9, R15 + ADDQ DI, BX + + XORQ R14, R13 + RORXQ $34, BX, R12 + XORQ R11, R15 + RORXQ $39, BX, R14 + MOVQ BX, DI + + XORQ R12, R14 + RORXQ $28, BX, R12 + ADDQ 8*3+frame_YFER(SP), AX + ORQ R8, DI + + XORQ R12, R14 + MOVQ BX, R12 + ANDQ CX, DI + ANDQ R8, R12 + ADDQ R13, R15 + + ADDQ AX, DX + ORQ R12, DI + ADDQ R14, AX + + ADDQ R15, DX + + ADDQ R15, AX + + ADDQ DI, AX + + VMOVDQU Y6, Y4 + VMOVDQU Y7, Y5 + + SUBQ $1, frame_SRND(SP) + JNE loop2 + + addm(8*0(SI),AX) + addm(8*1(SI),BX) + addm(8*2(SI),CX) + addm(8*3(SI),R8) + addm(8*4(SI),DX) + addm(8*5(SI),R9) + addm(8*6(SI),R10) + addm(8*7(SI),R11) + + MOVQ frame_INP(SP), DI + ADDQ $128, DI + CMPQ DI, frame_INPEND(SP) + JNE loop0 + +done_hash: + VZEROUPPER + RET diff --git a/src/crypto/sha512/sha512block_decl.go b/src/crypto/sha512/sha512block_decl.go new file mode 100644 index 0000000..6c22f44 --- /dev/null +++ b/src/crypto/sha512/sha512block_decl.go @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build s390x || ppc64le +// +build s390x ppc64le + +package sha512 + +//go:noescape + +func block(dig *digest, p []byte) diff --git a/src/crypto/sha512/sha512block_generic.go b/src/crypto/sha512/sha512block_generic.go new file mode 100644 index 0000000..865a735 --- /dev/null +++ b/src/crypto/sha512/sha512block_generic.go @@ -0,0 +1,12 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 && !s390x && !ppc64le +// +build !amd64,!s390x,!ppc64le + +package sha512 + +func block(dig *digest, p []byte) { + blockGeneric(dig, p) +} diff --git a/src/crypto/sha512/sha512block_ppc64le.s b/src/crypto/sha512/sha512block_ppc64le.s new file mode 100644 index 0000000..55f0c06 --- /dev/null +++ b/src/crypto/sha512/sha512block_ppc64le.s @@ -0,0 +1,451 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Based on CRYPTOGAMS code with the following comment: +// # ==================================================================== +// # Written by Andy Polyakov for the OpenSSL +// # project. The module is, however, dual licensed under OpenSSL and +// # CRYPTOGAMS licenses depending on where you obtain it. For further +// # details see http://www.openssl.org/~appro/cryptogams/. +// # ==================================================================== + +#include "textflag.h" + +// SHA512 block routine. See sha512block.go for Go equivalent. +// +// The algorithm is detailed in FIPS 180-4: +// +// https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf +// +// Wt = Mt; for 0 <= t <= 15 +// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 79 +// +// a = H0 +// b = H1 +// c = H2 +// d = H3 +// e = H4 +// f = H5 +// g = H6 +// h = H7 +// +// for t = 0 to 79 { +// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt +// T2 = BIGSIGMA0(a) + Maj(a,b,c) +// h = g +// g = f +// f = e +// e = d + T1 +// d = c +// c = b +// b = a +// a = T1 + T2 +// } +// +// H0 = a + H0 +// H1 = b + H1 +// H2 = c + H2 +// H3 = d + H3 +// H4 = e + H4 +// H5 = f + H5 +// H6 = g + H6 +// H7 = h + H7 + +#define CTX R3 +#define INP R4 +#define END R5 +#define TBL R6 +#define IDX R7 +#define CNT R8 +#define LEN R9 +#define OFFLOAD R11 +#define TEMP R12 + +#define HEX00 R0 +#define HEX10 R10 +#define HEX20 R25 +#define HEX30 R26 +#define HEX40 R27 +#define HEX50 R28 +#define HEX60 R29 +#define HEX70 R31 + +// V0-V7 are A-H +// V8-V23 are used for the message schedule +#define KI V24 +#define FUNC V25 +#define S0 V26 +#define S1 V27 +#define s0 V28 +#define s1 V29 +#define LEMASK V31 // Permutation control register for little endian + +// 2 copies of each Kt, to fill both doublewords of a vector register +DATA ·kcon+0x000(SB)/8, $0x428a2f98d728ae22 +DATA ·kcon+0x008(SB)/8, $0x428a2f98d728ae22 +DATA ·kcon+0x010(SB)/8, $0x7137449123ef65cd +DATA ·kcon+0x018(SB)/8, $0x7137449123ef65cd +DATA ·kcon+0x020(SB)/8, $0xb5c0fbcfec4d3b2f +DATA ·kcon+0x028(SB)/8, $0xb5c0fbcfec4d3b2f +DATA ·kcon+0x030(SB)/8, $0xe9b5dba58189dbbc +DATA ·kcon+0x038(SB)/8, $0xe9b5dba58189dbbc +DATA ·kcon+0x040(SB)/8, $0x3956c25bf348b538 +DATA ·kcon+0x048(SB)/8, $0x3956c25bf348b538 +DATA ·kcon+0x050(SB)/8, $0x59f111f1b605d019 +DATA ·kcon+0x058(SB)/8, $0x59f111f1b605d019 +DATA ·kcon+0x060(SB)/8, $0x923f82a4af194f9b +DATA ·kcon+0x068(SB)/8, $0x923f82a4af194f9b +DATA ·kcon+0x070(SB)/8, $0xab1c5ed5da6d8118 +DATA ·kcon+0x078(SB)/8, $0xab1c5ed5da6d8118 +DATA ·kcon+0x080(SB)/8, $0xd807aa98a3030242 +DATA ·kcon+0x088(SB)/8, $0xd807aa98a3030242 +DATA ·kcon+0x090(SB)/8, $0x12835b0145706fbe +DATA ·kcon+0x098(SB)/8, $0x12835b0145706fbe +DATA ·kcon+0x0A0(SB)/8, $0x243185be4ee4b28c +DATA ·kcon+0x0A8(SB)/8, $0x243185be4ee4b28c +DATA ·kcon+0x0B0(SB)/8, $0x550c7dc3d5ffb4e2 +DATA ·kcon+0x0B8(SB)/8, $0x550c7dc3d5ffb4e2 +DATA ·kcon+0x0C0(SB)/8, $0x72be5d74f27b896f +DATA ·kcon+0x0C8(SB)/8, $0x72be5d74f27b896f +DATA ·kcon+0x0D0(SB)/8, $0x80deb1fe3b1696b1 +DATA ·kcon+0x0D8(SB)/8, $0x80deb1fe3b1696b1 +DATA ·kcon+0x0E0(SB)/8, $0x9bdc06a725c71235 +DATA ·kcon+0x0E8(SB)/8, $0x9bdc06a725c71235 +DATA ·kcon+0x0F0(SB)/8, $0xc19bf174cf692694 +DATA ·kcon+0x0F8(SB)/8, $0xc19bf174cf692694 +DATA ·kcon+0x100(SB)/8, $0xe49b69c19ef14ad2 +DATA ·kcon+0x108(SB)/8, $0xe49b69c19ef14ad2 +DATA ·kcon+0x110(SB)/8, $0xefbe4786384f25e3 +DATA ·kcon+0x118(SB)/8, $0xefbe4786384f25e3 +DATA ·kcon+0x120(SB)/8, $0x0fc19dc68b8cd5b5 +DATA ·kcon+0x128(SB)/8, $0x0fc19dc68b8cd5b5 +DATA ·kcon+0x130(SB)/8, $0x240ca1cc77ac9c65 +DATA ·kcon+0x138(SB)/8, $0x240ca1cc77ac9c65 +DATA ·kcon+0x140(SB)/8, $0x2de92c6f592b0275 +DATA ·kcon+0x148(SB)/8, $0x2de92c6f592b0275 +DATA ·kcon+0x150(SB)/8, $0x4a7484aa6ea6e483 +DATA ·kcon+0x158(SB)/8, $0x4a7484aa6ea6e483 +DATA ·kcon+0x160(SB)/8, $0x5cb0a9dcbd41fbd4 +DATA ·kcon+0x168(SB)/8, $0x5cb0a9dcbd41fbd4 +DATA ·kcon+0x170(SB)/8, $0x76f988da831153b5 +DATA ·kcon+0x178(SB)/8, $0x76f988da831153b5 +DATA ·kcon+0x180(SB)/8, $0x983e5152ee66dfab +DATA ·kcon+0x188(SB)/8, $0x983e5152ee66dfab +DATA ·kcon+0x190(SB)/8, $0xa831c66d2db43210 +DATA ·kcon+0x198(SB)/8, $0xa831c66d2db43210 +DATA ·kcon+0x1A0(SB)/8, $0xb00327c898fb213f +DATA ·kcon+0x1A8(SB)/8, $0xb00327c898fb213f +DATA ·kcon+0x1B0(SB)/8, $0xbf597fc7beef0ee4 +DATA ·kcon+0x1B8(SB)/8, $0xbf597fc7beef0ee4 +DATA ·kcon+0x1C0(SB)/8, $0xc6e00bf33da88fc2 +DATA ·kcon+0x1C8(SB)/8, $0xc6e00bf33da88fc2 +DATA ·kcon+0x1D0(SB)/8, $0xd5a79147930aa725 +DATA ·kcon+0x1D8(SB)/8, $0xd5a79147930aa725 +DATA ·kcon+0x1E0(SB)/8, $0x06ca6351e003826f +DATA ·kcon+0x1E8(SB)/8, $0x06ca6351e003826f +DATA ·kcon+0x1F0(SB)/8, $0x142929670a0e6e70 +DATA ·kcon+0x1F8(SB)/8, $0x142929670a0e6e70 +DATA ·kcon+0x200(SB)/8, $0x27b70a8546d22ffc +DATA ·kcon+0x208(SB)/8, $0x27b70a8546d22ffc +DATA ·kcon+0x210(SB)/8, $0x2e1b21385c26c926 +DATA ·kcon+0x218(SB)/8, $0x2e1b21385c26c926 +DATA ·kcon+0x220(SB)/8, $0x4d2c6dfc5ac42aed +DATA ·kcon+0x228(SB)/8, $0x4d2c6dfc5ac42aed +DATA ·kcon+0x230(SB)/8, $0x53380d139d95b3df +DATA ·kcon+0x238(SB)/8, $0x53380d139d95b3df +DATA ·kcon+0x240(SB)/8, $0x650a73548baf63de +DATA ·kcon+0x248(SB)/8, $0x650a73548baf63de +DATA ·kcon+0x250(SB)/8, $0x766a0abb3c77b2a8 +DATA ·kcon+0x258(SB)/8, $0x766a0abb3c77b2a8 +DATA ·kcon+0x260(SB)/8, $0x81c2c92e47edaee6 +DATA ·kcon+0x268(SB)/8, $0x81c2c92e47edaee6 +DATA ·kcon+0x270(SB)/8, $0x92722c851482353b +DATA ·kcon+0x278(SB)/8, $0x92722c851482353b +DATA ·kcon+0x280(SB)/8, $0xa2bfe8a14cf10364 +DATA ·kcon+0x288(SB)/8, $0xa2bfe8a14cf10364 +DATA ·kcon+0x290(SB)/8, $0xa81a664bbc423001 +DATA ·kcon+0x298(SB)/8, $0xa81a664bbc423001 +DATA ·kcon+0x2A0(SB)/8, $0xc24b8b70d0f89791 +DATA ·kcon+0x2A8(SB)/8, $0xc24b8b70d0f89791 +DATA ·kcon+0x2B0(SB)/8, $0xc76c51a30654be30 +DATA ·kcon+0x2B8(SB)/8, $0xc76c51a30654be30 +DATA ·kcon+0x2C0(SB)/8, $0xd192e819d6ef5218 +DATA ·kcon+0x2C8(SB)/8, $0xd192e819d6ef5218 +DATA ·kcon+0x2D0(SB)/8, $0xd69906245565a910 +DATA ·kcon+0x2D8(SB)/8, $0xd69906245565a910 +DATA ·kcon+0x2E0(SB)/8, $0xf40e35855771202a +DATA ·kcon+0x2E8(SB)/8, $0xf40e35855771202a +DATA ·kcon+0x2F0(SB)/8, $0x106aa07032bbd1b8 +DATA ·kcon+0x2F8(SB)/8, $0x106aa07032bbd1b8 +DATA ·kcon+0x300(SB)/8, $0x19a4c116b8d2d0c8 +DATA ·kcon+0x308(SB)/8, $0x19a4c116b8d2d0c8 +DATA ·kcon+0x310(SB)/8, $0x1e376c085141ab53 +DATA ·kcon+0x318(SB)/8, $0x1e376c085141ab53 +DATA ·kcon+0x320(SB)/8, $0x2748774cdf8eeb99 +DATA ·kcon+0x328(SB)/8, $0x2748774cdf8eeb99 +DATA ·kcon+0x330(SB)/8, $0x34b0bcb5e19b48a8 +DATA ·kcon+0x338(SB)/8, $0x34b0bcb5e19b48a8 +DATA ·kcon+0x340(SB)/8, $0x391c0cb3c5c95a63 +DATA ·kcon+0x348(SB)/8, $0x391c0cb3c5c95a63 +DATA ·kcon+0x350(SB)/8, $0x4ed8aa4ae3418acb +DATA ·kcon+0x358(SB)/8, $0x4ed8aa4ae3418acb +DATA ·kcon+0x360(SB)/8, $0x5b9cca4f7763e373 +DATA ·kcon+0x368(SB)/8, $0x5b9cca4f7763e373 +DATA ·kcon+0x370(SB)/8, $0x682e6ff3d6b2b8a3 +DATA ·kcon+0x378(SB)/8, $0x682e6ff3d6b2b8a3 +DATA ·kcon+0x380(SB)/8, $0x748f82ee5defb2fc +DATA ·kcon+0x388(SB)/8, $0x748f82ee5defb2fc +DATA ·kcon+0x390(SB)/8, $0x78a5636f43172f60 +DATA ·kcon+0x398(SB)/8, $0x78a5636f43172f60 +DATA ·kcon+0x3A0(SB)/8, $0x84c87814a1f0ab72 +DATA ·kcon+0x3A8(SB)/8, $0x84c87814a1f0ab72 +DATA ·kcon+0x3B0(SB)/8, $0x8cc702081a6439ec +DATA ·kcon+0x3B8(SB)/8, $0x8cc702081a6439ec +DATA ·kcon+0x3C0(SB)/8, $0x90befffa23631e28 +DATA ·kcon+0x3C8(SB)/8, $0x90befffa23631e28 +DATA ·kcon+0x3D0(SB)/8, $0xa4506cebde82bde9 +DATA ·kcon+0x3D8(SB)/8, $0xa4506cebde82bde9 +DATA ·kcon+0x3E0(SB)/8, $0xbef9a3f7b2c67915 +DATA ·kcon+0x3E8(SB)/8, $0xbef9a3f7b2c67915 +DATA ·kcon+0x3F0(SB)/8, $0xc67178f2e372532b +DATA ·kcon+0x3F8(SB)/8, $0xc67178f2e372532b +DATA ·kcon+0x400(SB)/8, $0xca273eceea26619c +DATA ·kcon+0x408(SB)/8, $0xca273eceea26619c +DATA ·kcon+0x410(SB)/8, $0xd186b8c721c0c207 +DATA ·kcon+0x418(SB)/8, $0xd186b8c721c0c207 +DATA ·kcon+0x420(SB)/8, $0xeada7dd6cde0eb1e +DATA ·kcon+0x428(SB)/8, $0xeada7dd6cde0eb1e +DATA ·kcon+0x430(SB)/8, $0xf57d4f7fee6ed178 +DATA ·kcon+0x438(SB)/8, $0xf57d4f7fee6ed178 +DATA ·kcon+0x440(SB)/8, $0x06f067aa72176fba +DATA ·kcon+0x448(SB)/8, $0x06f067aa72176fba +DATA ·kcon+0x450(SB)/8, $0x0a637dc5a2c898a6 +DATA ·kcon+0x458(SB)/8, $0x0a637dc5a2c898a6 +DATA ·kcon+0x460(SB)/8, $0x113f9804bef90dae +DATA ·kcon+0x468(SB)/8, $0x113f9804bef90dae +DATA ·kcon+0x470(SB)/8, $0x1b710b35131c471b +DATA ·kcon+0x478(SB)/8, $0x1b710b35131c471b +DATA ·kcon+0x480(SB)/8, $0x28db77f523047d84 +DATA ·kcon+0x488(SB)/8, $0x28db77f523047d84 +DATA ·kcon+0x490(SB)/8, $0x32caab7b40c72493 +DATA ·kcon+0x498(SB)/8, $0x32caab7b40c72493 +DATA ·kcon+0x4A0(SB)/8, $0x3c9ebe0a15c9bebc +DATA ·kcon+0x4A8(SB)/8, $0x3c9ebe0a15c9bebc +DATA ·kcon+0x4B0(SB)/8, $0x431d67c49c100d4c +DATA ·kcon+0x4B8(SB)/8, $0x431d67c49c100d4c +DATA ·kcon+0x4C0(SB)/8, $0x4cc5d4becb3e42b6 +DATA ·kcon+0x4C8(SB)/8, $0x4cc5d4becb3e42b6 +DATA ·kcon+0x4D0(SB)/8, $0x597f299cfc657e2a +DATA ·kcon+0x4D8(SB)/8, $0x597f299cfc657e2a +DATA ·kcon+0x4E0(SB)/8, $0x5fcb6fab3ad6faec +DATA ·kcon+0x4E8(SB)/8, $0x5fcb6fab3ad6faec +DATA ·kcon+0x4F0(SB)/8, $0x6c44198c4a475817 +DATA ·kcon+0x4F8(SB)/8, $0x6c44198c4a475817 +DATA ·kcon+0x500(SB)/8, $0x0000000000000000 +DATA ·kcon+0x508(SB)/8, $0x0000000000000000 +DATA ·kcon+0x510(SB)/8, $0x1011121314151617 +DATA ·kcon+0x518(SB)/8, $0x0001020304050607 +GLOBL ·kcon(SB), RODATA, $1312 + +#define SHA512ROUND0(a, b, c, d, e, f, g, h, xi) \ + VSEL g, f, e, FUNC; \ + VSHASIGMAD $15, e, $1, S1; \ + VADDUDM xi, h, h; \ + VSHASIGMAD $0, a, $1, S0; \ + VADDUDM FUNC, h, h; \ + VXOR b, a, FUNC; \ + VADDUDM S1, h, h; \ + VSEL b, c, FUNC, FUNC; \ + VADDUDM KI, g, g; \ + VADDUDM h, d, d; \ + VADDUDM FUNC, S0, S0; \ + LVX (TBL)(IDX), KI; \ + ADD $16, IDX; \ + VADDUDM S0, h, h + +#define SHA512ROUND1(a, b, c, d, e, f, g, h, xi, xj, xj_1, xj_9, xj_14) \ + VSHASIGMAD $0, xj_1, $0, s0; \ + VSEL g, f, e, FUNC; \ + VSHASIGMAD $15, e, $1, S1; \ + VADDUDM xi, h, h; \ + VSHASIGMAD $0, a, $1, S0; \ + VSHASIGMAD $15, xj_14, $0, s1; \ + VADDUDM FUNC, h, h; \ + VXOR b, a, FUNC; \ + VADDUDM xj_9, xj, xj; \ + VADDUDM S1, h, h; \ + VSEL b, c, FUNC, FUNC; \ + VADDUDM KI, g, g; \ + VADDUDM h, d, d; \ + VADDUDM FUNC, S0, S0; \ + VADDUDM s0, xj, xj; \ + LVX (TBL)(IDX), KI; \ + ADD $16, IDX; \ + VADDUDM S0, h, h; \ + VADDUDM s1, xj, xj + +// func block(dig *digest, p []byte) +TEXT ·block(SB),0,$128-32 + MOVD dig+0(FP), CTX + MOVD p_base+8(FP), INP + MOVD p_len+16(FP), LEN + + SRD $6, LEN + SLD $6, LEN + + ADD INP, LEN, END + + CMP INP, END + BEQ end + + MOVD $·kcon(SB), TBL + MOVD R1, OFFLOAD + + MOVD R0, CNT + MOVWZ $0x10, HEX10 + MOVWZ $0x20, HEX20 + MOVWZ $0x30, HEX30 + MOVWZ $0x40, HEX40 + MOVWZ $0x50, HEX50 + MOVWZ $0x60, HEX60 + MOVWZ $0x70, HEX70 + + MOVWZ $8, IDX + LVSL (IDX)(R0), LEMASK + VSPLTISB $0x0F, KI + VXOR KI, LEMASK, LEMASK + + LXVD2X (CTX)(HEX00), VS32 // v0 = vs32 + LXVD2X (CTX)(HEX10), VS34 // v2 = vs34 + LXVD2X (CTX)(HEX20), VS36 // v4 = vs36 + // unpack the input values into vector registers + VSLDOI $8, V0, V0, V1 + LXVD2X (CTX)(HEX30), VS38 // v6 = vs38 + VSLDOI $8, V2, V2, V3 + VSLDOI $8, V4, V4, V5 + VSLDOI $8, V6, V6, V7 + +loop: + LVX (TBL)(HEX00), KI + MOVWZ $16, IDX + + LXVD2X (INP)(R0), VS40 // load v8 (=vs40) in advance + ADD $16, INP + + STVX V0, (OFFLOAD+HEX00) + STVX V1, (OFFLOAD+HEX10) + STVX V2, (OFFLOAD+HEX20) + STVX V3, (OFFLOAD+HEX30) + STVX V4, (OFFLOAD+HEX40) + STVX V5, (OFFLOAD+HEX50) + STVX V6, (OFFLOAD+HEX60) + STVX V7, (OFFLOAD+HEX70) + + VADDUDM KI, V7, V7 // h+K[i] + LVX (TBL)(IDX), KI + ADD $16, IDX + + VPERM V8, V8, LEMASK, V8 + SHA512ROUND0(V0, V1, V2, V3, V4, V5, V6, V7, V8) + LXVD2X (INP)(R0), VS42 // load v10 (=vs42) in advance + ADD $16, INP, INP + VSLDOI $8, V8, V8, V9 + SHA512ROUND0(V7, V0, V1, V2, V3, V4, V5, V6, V9) + VPERM V10, V10, LEMASK, V10 + SHA512ROUND0(V6, V7, V0, V1, V2, V3, V4, V5, V10) + LXVD2X (INP)(R0), VS44 // load v12 (=vs44) in advance + ADD $16, INP, INP + VSLDOI $8, V10, V10, V11 + SHA512ROUND0(V5, V6, V7, V0, V1, V2, V3, V4, V11) + VPERM V12, V12, LEMASK, V12 + SHA512ROUND0(V4, V5, V6, V7, V0, V1, V2, V3, V12) + LXVD2X (INP)(R0), VS46 // load v14 (=vs46) in advance + ADD $16, INP, INP + VSLDOI $8, V12, V12, V13 + SHA512ROUND0(V3, V4, V5, V6, V7, V0, V1, V2, V13) + VPERM V14, V14, LEMASK, V14 + SHA512ROUND0(V2, V3, V4, V5, V6, V7, V0, V1, V14) + LXVD2X (INP)(R0), VS48 // load v16 (=vs48) in advance + ADD $16, INP, INP + VSLDOI $8, V14, V14, V15 + SHA512ROUND0(V1, V2, V3, V4, V5, V6, V7, V0, V15) + VPERM V16, V16, LEMASK, V16 + SHA512ROUND0(V0, V1, V2, V3, V4, V5, V6, V7, V16) + LXVD2X (INP)(R0), VS50 // load v18 (=vs50) in advance + ADD $16, INP, INP + VSLDOI $8, V16, V16, V17 + SHA512ROUND0(V7, V0, V1, V2, V3, V4, V5, V6, V17) + VPERM V18, V18, LEMASK, V18 + SHA512ROUND0(V6, V7, V0, V1, V2, V3, V4, V5, V18) + LXVD2X (INP)(R0), VS52 // load v20 (=vs52) in advance + ADD $16, INP, INP + VSLDOI $8, V18, V18, V19 + SHA512ROUND0(V5, V6, V7, V0, V1, V2, V3, V4, V19) + VPERM V20, V20, LEMASK, V20 + SHA512ROUND0(V4, V5, V6, V7, V0, V1, V2, V3, V20) + LXVD2X (INP)(R0), VS54 // load v22 (=vs54) in advance + ADD $16, INP, INP + VSLDOI $8, V20, V20, V21 + SHA512ROUND0(V3, V4, V5, V6, V7, V0, V1, V2, V21) + VPERM V22, V22, LEMASK, V22 + SHA512ROUND0(V2, V3, V4, V5, V6, V7, V0, V1, V22) + VSLDOI $8, V22, V22, V23 + SHA512ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V23, V8, V9, V17, V22) + + MOVWZ $4, TEMP + MOVWZ TEMP, CTR + +L16_xx: + SHA512ROUND1(V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V18, V23) + SHA512ROUND1(V7, V0, V1, V2, V3, V4, V5, V6, V9, V10, V11, V19, V8) + SHA512ROUND1(V6, V7, V0, V1, V2, V3, V4, V5, V10, V11, V12, V20, V9) + SHA512ROUND1(V5, V6, V7, V0, V1, V2, V3, V4, V11, V12, V13, V21, V10) + SHA512ROUND1(V4, V5, V6, V7, V0, V1, V2, V3, V12, V13, V14, V22, V11) + SHA512ROUND1(V3, V4, V5, V6, V7, V0, V1, V2, V13, V14, V15, V23, V12) + SHA512ROUND1(V2, V3, V4, V5, V6, V7, V0, V1, V14, V15, V16, V8, V13) + SHA512ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V15, V16, V17, V9, V14) + SHA512ROUND1(V0, V1, V2, V3, V4, V5, V6, V7, V16, V17, V18, V10, V15) + SHA512ROUND1(V7, V0, V1, V2, V3, V4, V5, V6, V17, V18, V19, V11, V16) + SHA512ROUND1(V6, V7, V0, V1, V2, V3, V4, V5, V18, V19, V20, V12, V17) + SHA512ROUND1(V5, V6, V7, V0, V1, V2, V3, V4, V19, V20, V21, V13, V18) + SHA512ROUND1(V4, V5, V6, V7, V0, V1, V2, V3, V20, V21, V22, V14, V19) + SHA512ROUND1(V3, V4, V5, V6, V7, V0, V1, V2, V21, V22, V23, V15, V20) + SHA512ROUND1(V2, V3, V4, V5, V6, V7, V0, V1, V22, V23, V8, V16, V21) + SHA512ROUND1(V1, V2, V3, V4, V5, V6, V7, V0, V23, V8, V9, V17, V22) + + BC 0x10, 0, L16_xx // bdnz + + LVX (OFFLOAD)(HEX00), V10 + + LVX (OFFLOAD)(HEX10), V11 + VADDUDM V10, V0, V0 + LVX (OFFLOAD)(HEX20), V12 + VADDUDM V11, V1, V1 + LVX (OFFLOAD)(HEX30), V13 + VADDUDM V12, V2, V2 + LVX (OFFLOAD)(HEX40), V14 + VADDUDM V13, V3, V3 + LVX (OFFLOAD)(HEX50), V15 + VADDUDM V14, V4, V4 + LVX (OFFLOAD)(HEX60), V16 + VADDUDM V15, V5, V5 + LVX (OFFLOAD)(HEX70), V17 + VADDUDM V16, V6, V6 + VADDUDM V17, V7, V7 + + CMPU INP, END + BLT loop + + VPERM V0, V1, KI, V0 + VPERM V2, V3, KI, V2 + VPERM V4, V5, KI, V4 + VPERM V6, V7, KI, V6 + STXVD2X VS32, (CTX+HEX00) // v0 = vs32 + STXVD2X VS34, (CTX+HEX10) // v2 = vs34 + STXVD2X VS36, (CTX+HEX20) // v4 = vs36 + STXVD2X VS38, (CTX+HEX30) // v6 = vs38 + +end: + RET + diff --git a/src/crypto/sha512/sha512block_s390x.go b/src/crypto/sha512/sha512block_s390x.go new file mode 100644 index 0000000..7df29fd --- /dev/null +++ b/src/crypto/sha512/sha512block_s390x.go @@ -0,0 +1,9 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha512 + +import "internal/cpu" + +var useAsm = cpu.S390X.HasSHA512 diff --git a/src/crypto/sha512/sha512block_s390x.s b/src/crypto/sha512/sha512block_s390x.s new file mode 100644 index 0000000..f221bd1 --- /dev/null +++ b/src/crypto/sha512/sha512block_s390x.s @@ -0,0 +1,20 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func block(dig *digest, p []byte) +TEXT ·block(SB), NOSPLIT|NOFRAME, $0-32 + MOVBZ ·useAsm(SB), R4 + LMG dig+0(FP), R1, R3 // R2 = &p[0], R3 = len(p) + MOVBZ $3, R0 // SHA-512 function code + CMPBEQ R4, $0, generic + +loop: + WORD $0xB93E0002 // KIMD R2 + BVS loop // continue if interrupted + RET + +generic: + BR ·blockGeneric(SB) diff --git a/src/crypto/subtle/constant_time.go b/src/crypto/subtle/constant_time.go new file mode 100644 index 0000000..7c3cf05 --- /dev/null +++ b/src/crypto/subtle/constant_time.go @@ -0,0 +1,61 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +package subtle + +// ConstantTimeCompare returns 1 if the two slices, x and y, have equal contents +// and 0 otherwise. The time taken is a function of the length of the slices and +// is independent of the contents. +func ConstantTimeCompare(x, y []byte) int { + if len(x) != len(y) { + return 0 + } + + var v byte + + for i := 0; i < len(x); i++ { + v |= x[i] ^ y[i] + } + + return ConstantTimeByteEq(v, 0) +} + +// ConstantTimeSelect returns x if v == 1 and y if v == 0. +// Its behavior is undefined if v takes any other value. +func ConstantTimeSelect(v, x, y int) int { return ^(v-1)&x | (v-1)&y } + +// ConstantTimeByteEq returns 1 if x == y and 0 otherwise. +func ConstantTimeByteEq(x, y uint8) int { + return int((uint32(x^y) - 1) >> 31) +} + +// ConstantTimeEq returns 1 if x == y and 0 otherwise. +func ConstantTimeEq(x, y int32) int { + return int((uint64(uint32(x^y)) - 1) >> 63) +} + +// ConstantTimeCopy copies the contents of y into x (a slice of equal length) +// if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v +// takes any other value. +func ConstantTimeCopy(v int, x, y []byte) { + if len(x) != len(y) { + panic("subtle: slices have different lengths") + } + + xmask := byte(v - 1) + ymask := byte(^(v - 1)) + for i := 0; i < len(x); i++ { + x[i] = x[i]&xmask | y[i]&ymask + } +} + +// ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise. +// Its behavior is undefined if x or y are negative or > 2**31 - 1. +func ConstantTimeLessOrEq(x, y int) int { + x32 := int32(x) + y32 := int32(y) + return int(((x32 - y32 - 1) >> 31) & 1) +} diff --git a/src/crypto/subtle/constant_time_test.go b/src/crypto/subtle/constant_time_test.go new file mode 100644 index 0000000..033301a --- /dev/null +++ b/src/crypto/subtle/constant_time_test.go @@ -0,0 +1,159 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package subtle + +import ( + "testing" + "testing/quick" +) + +type TestConstantTimeCompareStruct struct { + a, b []byte + out int +} + +var testConstantTimeCompareData = []TestConstantTimeCompareStruct{ + {[]byte{}, []byte{}, 1}, + {[]byte{0x11}, []byte{0x11}, 1}, + {[]byte{0x12}, []byte{0x11}, 0}, + {[]byte{0x11}, []byte{0x11, 0x12}, 0}, + {[]byte{0x11, 0x12}, []byte{0x11}, 0}, +} + +func TestConstantTimeCompare(t *testing.T) { + for i, test := range testConstantTimeCompareData { + if r := ConstantTimeCompare(test.a, test.b); r != test.out { + t.Errorf("#%d bad result (got %x, want %x)", i, r, test.out) + } + } +} + +type TestConstantTimeByteEqStruct struct { + a, b uint8 + out int +} + +var testConstandTimeByteEqData = []TestConstantTimeByteEqStruct{ + {0, 0, 1}, + {0, 1, 0}, + {1, 0, 0}, + {0xff, 0xff, 1}, + {0xff, 0xfe, 0}, +} + +func byteEq(a, b uint8) int { + if a == b { + return 1 + } + return 0 +} + +func TestConstantTimeByteEq(t *testing.T) { + for i, test := range testConstandTimeByteEqData { + if r := ConstantTimeByteEq(test.a, test.b); r != test.out { + t.Errorf("#%d bad result (got %x, want %x)", i, r, test.out) + } + } + err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil) + if err != nil { + t.Error(err) + } +} + +func eq(a, b int32) int { + if a == b { + return 1 + } + return 0 +} + +func TestConstantTimeEq(t *testing.T) { + err := quick.CheckEqual(ConstantTimeEq, eq, nil) + if err != nil { + t.Error(err) + } +} + +func makeCopy(v int, x, y []byte) []byte { + if len(x) > len(y) { + x = x[0:len(y)] + } else { + y = y[0:len(x)] + } + if v == 1 { + copy(x, y) + } + return x +} + +func constantTimeCopyWrapper(v int, x, y []byte) []byte { + if len(x) > len(y) { + x = x[0:len(y)] + } else { + y = y[0:len(x)] + } + v &= 1 + ConstantTimeCopy(v, x, y) + return x +} + +func TestConstantTimeCopy(t *testing.T) { + err := quick.CheckEqual(constantTimeCopyWrapper, makeCopy, nil) + if err != nil { + t.Error(err) + } +} + +var lessOrEqTests = []struct { + x, y, result int +}{ + {0, 0, 1}, + {1, 0, 0}, + {0, 1, 1}, + {10, 20, 1}, + {20, 10, 0}, + {10, 10, 1}, +} + +func TestConstantTimeLessOrEq(t *testing.T) { + for i, test := range lessOrEqTests { + result := ConstantTimeLessOrEq(test.x, test.y) + if result != test.result { + t.Errorf("#%d: %d <= %d gave %d, expected %d", i, test.x, test.y, result, test.result) + } + } +} + +var benchmarkGlobal uint8 + +func BenchmarkConstantTimeByteEq(b *testing.B) { + var x, y uint8 + + for i := 0; i < b.N; i++ { + x, y = uint8(ConstantTimeByteEq(x, y)), x + } + + benchmarkGlobal = x +} + +func BenchmarkConstantTimeEq(b *testing.B) { + var x, y int + + for i := 0; i < b.N; i++ { + x, y = ConstantTimeEq(int32(x), int32(y)), x + } + + benchmarkGlobal = uint8(x) +} + +func BenchmarkConstantTimeLessOrEq(b *testing.B) { + var x, y int + + for i := 0; i < b.N; i++ { + x, y = ConstantTimeLessOrEq(x, y), x + } + + benchmarkGlobal = uint8(x) +} diff --git a/src/crypto/tls/alert.go b/src/crypto/tls/alert.go new file mode 100644 index 0000000..4790b73 --- /dev/null +++ b/src/crypto/tls/alert.go @@ -0,0 +1,99 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import "strconv" + +type alert uint8 + +const ( + // alert level + alertLevelWarning = 1 + alertLevelError = 2 +) + +const ( + alertCloseNotify alert = 0 + alertUnexpectedMessage alert = 10 + alertBadRecordMAC alert = 20 + alertDecryptionFailed alert = 21 + alertRecordOverflow alert = 22 + alertDecompressionFailure alert = 30 + alertHandshakeFailure alert = 40 + alertBadCertificate alert = 42 + alertUnsupportedCertificate alert = 43 + alertCertificateRevoked alert = 44 + alertCertificateExpired alert = 45 + alertCertificateUnknown alert = 46 + alertIllegalParameter alert = 47 + alertUnknownCA alert = 48 + alertAccessDenied alert = 49 + alertDecodeError alert = 50 + alertDecryptError alert = 51 + alertExportRestriction alert = 60 + alertProtocolVersion alert = 70 + alertInsufficientSecurity alert = 71 + alertInternalError alert = 80 + alertInappropriateFallback alert = 86 + alertUserCanceled alert = 90 + alertNoRenegotiation alert = 100 + alertMissingExtension alert = 109 + alertUnsupportedExtension alert = 110 + alertCertificateUnobtainable alert = 111 + alertUnrecognizedName alert = 112 + alertBadCertificateStatusResponse alert = 113 + alertBadCertificateHashValue alert = 114 + alertUnknownPSKIdentity alert = 115 + alertCertificateRequired alert = 116 + alertNoApplicationProtocol alert = 120 +) + +var alertText = map[alert]string{ + alertCloseNotify: "close notify", + alertUnexpectedMessage: "unexpected message", + alertBadRecordMAC: "bad record MAC", + alertDecryptionFailed: "decryption failed", + alertRecordOverflow: "record overflow", + alertDecompressionFailure: "decompression failure", + alertHandshakeFailure: "handshake failure", + alertBadCertificate: "bad certificate", + alertUnsupportedCertificate: "unsupported certificate", + alertCertificateRevoked: "revoked certificate", + alertCertificateExpired: "expired certificate", + alertCertificateUnknown: "unknown certificate", + alertIllegalParameter: "illegal parameter", + alertUnknownCA: "unknown certificate authority", + alertAccessDenied: "access denied", + alertDecodeError: "error decoding message", + alertDecryptError: "error decrypting message", + alertExportRestriction: "export restriction", + alertProtocolVersion: "protocol version not supported", + alertInsufficientSecurity: "insufficient security level", + alertInternalError: "internal error", + alertInappropriateFallback: "inappropriate fallback", + alertUserCanceled: "user canceled", + alertNoRenegotiation: "no renegotiation", + alertMissingExtension: "missing extension", + alertUnsupportedExtension: "unsupported extension", + alertCertificateUnobtainable: "certificate unobtainable", + alertUnrecognizedName: "unrecognized name", + alertBadCertificateStatusResponse: "bad certificate status response", + alertBadCertificateHashValue: "bad certificate hash value", + alertUnknownPSKIdentity: "unknown PSK identity", + alertCertificateRequired: "certificate required", + alertNoApplicationProtocol: "no application protocol", +} + +func (e alert) String() string { + s, ok := alertText[e] + if ok { + return "tls: " + s + } + return "tls: alert(" + strconv.Itoa(int(e)) + ")" +} + +func (e alert) Error() string { + return e.String() +} diff --git a/src/crypto/tls/auth.go b/src/crypto/tls/auth.go new file mode 100644 index 0000000..a9df0da --- /dev/null +++ b/src/crypto/tls/auth.go @@ -0,0 +1,289 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rsa" + "errors" + "fmt" + "hash" + "io" +) + +// verifyHandshakeSignature verifies a signature against pre-hashed +// (if required) handshake contents. +func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, signed, sig []byte) error { + switch sigType { + case signatureECDSA: + pubKey, ok := pubkey.(*ecdsa.PublicKey) + if !ok { + return fmt.Errorf("expected an ECDSA public key, got %T", pubkey) + } + if !ecdsa.VerifyASN1(pubKey, signed, sig) { + return errors.New("ECDSA verification failure") + } + case signatureEd25519: + pubKey, ok := pubkey.(ed25519.PublicKey) + if !ok { + return fmt.Errorf("expected an Ed25519 public key, got %T", pubkey) + } + if !ed25519.Verify(pubKey, signed, sig) { + return errors.New("Ed25519 verification failure") + } + case signaturePKCS1v15: + pubKey, ok := pubkey.(*rsa.PublicKey) + if !ok { + return fmt.Errorf("expected an RSA public key, got %T", pubkey) + } + if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, signed, sig); err != nil { + return err + } + case signatureRSAPSS: + pubKey, ok := pubkey.(*rsa.PublicKey) + if !ok { + return fmt.Errorf("expected an RSA public key, got %T", pubkey) + } + signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash} + if err := rsa.VerifyPSS(pubKey, hashFunc, signed, sig, signOpts); err != nil { + return err + } + default: + return errors.New("internal error: unknown signature type") + } + return nil +} + +const ( + serverSignatureContext = "TLS 1.3, server CertificateVerify\x00" + clientSignatureContext = "TLS 1.3, client CertificateVerify\x00" +) + +var signaturePadding = []byte{ + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +} + +// signedMessage returns the pre-hashed (if necessary) message to be signed by +// certificate keys in TLS 1.3. See RFC 8446, Section 4.4.3. +func signedMessage(sigHash crypto.Hash, context string, transcript hash.Hash) []byte { + if sigHash == directSigning { + b := &bytes.Buffer{} + b.Write(signaturePadding) + io.WriteString(b, context) + b.Write(transcript.Sum(nil)) + return b.Bytes() + } + h := sigHash.New() + h.Write(signaturePadding) + io.WriteString(h, context) + h.Write(transcript.Sum(nil)) + return h.Sum(nil) +} + +// typeAndHashFromSignatureScheme returns the corresponding signature type and +// crypto.Hash for a given TLS SignatureScheme. +func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType uint8, hash crypto.Hash, err error) { + switch signatureAlgorithm { + case PKCS1WithSHA1, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512: + sigType = signaturePKCS1v15 + case PSSWithSHA256, PSSWithSHA384, PSSWithSHA512: + sigType = signatureRSAPSS + case ECDSAWithSHA1, ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512: + sigType = signatureECDSA + case Ed25519: + sigType = signatureEd25519 + default: + return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) + } + switch signatureAlgorithm { + case PKCS1WithSHA1, ECDSAWithSHA1: + hash = crypto.SHA1 + case PKCS1WithSHA256, PSSWithSHA256, ECDSAWithP256AndSHA256: + hash = crypto.SHA256 + case PKCS1WithSHA384, PSSWithSHA384, ECDSAWithP384AndSHA384: + hash = crypto.SHA384 + case PKCS1WithSHA512, PSSWithSHA512, ECDSAWithP521AndSHA512: + hash = crypto.SHA512 + case Ed25519: + hash = directSigning + default: + return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) + } + return sigType, hash, nil +} + +// legacyTypeAndHashFromPublicKey returns the fixed signature type and crypto.Hash for +// a given public key used with TLS 1.0 and 1.1, before the introduction of +// signature algorithm negotiation. +func legacyTypeAndHashFromPublicKey(pub crypto.PublicKey) (sigType uint8, hash crypto.Hash, err error) { + switch pub.(type) { + case *rsa.PublicKey: + return signaturePKCS1v15, crypto.MD5SHA1, nil + case *ecdsa.PublicKey: + return signatureECDSA, crypto.SHA1, nil + case ed25519.PublicKey: + // RFC 8422 specifies support for Ed25519 in TLS 1.0 and 1.1, + // but it requires holding on to a handshake transcript to do a + // full signature, and not even OpenSSL bothers with the + // complexity, so we can't even test it properly. + return 0, 0, fmt.Errorf("tls: Ed25519 public keys are not supported before TLS 1.2") + default: + return 0, 0, fmt.Errorf("tls: unsupported public key: %T", pub) + } +} + +var rsaSignatureSchemes = []struct { + scheme SignatureScheme + minModulusBytes int + maxVersion uint16 +}{ + // RSA-PSS is used with PSSSaltLengthEqualsHash, and requires + // emLen >= hLen + sLen + 2 + {PSSWithSHA256, crypto.SHA256.Size()*2 + 2, VersionTLS13}, + {PSSWithSHA384, crypto.SHA384.Size()*2 + 2, VersionTLS13}, + {PSSWithSHA512, crypto.SHA512.Size()*2 + 2, VersionTLS13}, + // PKCS #1 v1.5 uses prefixes from hashPrefixes in crypto/rsa, and requires + // emLen >= len(prefix) + hLen + 11 + // TLS 1.3 dropped support for PKCS #1 v1.5 in favor of RSA-PSS. + {PKCS1WithSHA256, 19 + crypto.SHA256.Size() + 11, VersionTLS12}, + {PKCS1WithSHA384, 19 + crypto.SHA384.Size() + 11, VersionTLS12}, + {PKCS1WithSHA512, 19 + crypto.SHA512.Size() + 11, VersionTLS12}, + {PKCS1WithSHA1, 15 + crypto.SHA1.Size() + 11, VersionTLS12}, +} + +// signatureSchemesForCertificate returns the list of supported SignatureSchemes +// for a given certificate, based on the public key and the protocol version, +// and optionally filtered by its explicit SupportedSignatureAlgorithms. +// +// This function must be kept in sync with supportedSignatureAlgorithms. +func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme { + priv, ok := cert.PrivateKey.(crypto.Signer) + if !ok { + return nil + } + + var sigAlgs []SignatureScheme + switch pub := priv.Public().(type) { + case *ecdsa.PublicKey: + if version != VersionTLS13 { + // In TLS 1.2 and earlier, ECDSA algorithms are not + // constrained to a single curve. + sigAlgs = []SignatureScheme{ + ECDSAWithP256AndSHA256, + ECDSAWithP384AndSHA384, + ECDSAWithP521AndSHA512, + ECDSAWithSHA1, + } + break + } + switch pub.Curve { + case elliptic.P256(): + sigAlgs = []SignatureScheme{ECDSAWithP256AndSHA256} + case elliptic.P384(): + sigAlgs = []SignatureScheme{ECDSAWithP384AndSHA384} + case elliptic.P521(): + sigAlgs = []SignatureScheme{ECDSAWithP521AndSHA512} + default: + return nil + } + case *rsa.PublicKey: + size := pub.Size() + sigAlgs = make([]SignatureScheme, 0, len(rsaSignatureSchemes)) + for _, candidate := range rsaSignatureSchemes { + if size >= candidate.minModulusBytes && version <= candidate.maxVersion { + sigAlgs = append(sigAlgs, candidate.scheme) + } + } + case ed25519.PublicKey: + sigAlgs = []SignatureScheme{Ed25519} + default: + return nil + } + + if cert.SupportedSignatureAlgorithms != nil { + var filteredSigAlgs []SignatureScheme + for _, sigAlg := range sigAlgs { + if isSupportedSignatureAlgorithm(sigAlg, cert.SupportedSignatureAlgorithms) { + filteredSigAlgs = append(filteredSigAlgs, sigAlg) + } + } + return filteredSigAlgs + } + return sigAlgs +} + +// selectSignatureScheme picks a SignatureScheme from the peer's preference list +// that works with the selected certificate. It's only called for protocol +// versions that support signature algorithms, so TLS 1.2 and 1.3. +func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureScheme) (SignatureScheme, error) { + supportedAlgs := signatureSchemesForCertificate(vers, c) + if len(supportedAlgs) == 0 { + return 0, unsupportedCertificateError(c) + } + if len(peerAlgs) == 0 && vers == VersionTLS12 { + // For TLS 1.2, if the client didn't send signature_algorithms then we + // can assume that it supports SHA1. See RFC 5246, Section 7.4.1.4.1. + peerAlgs = []SignatureScheme{PKCS1WithSHA1, ECDSAWithSHA1} + } + // Pick signature scheme in the peer's preference order, as our + // preference order is not configurable. + for _, preferredAlg := range peerAlgs { + if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) { + return preferredAlg, nil + } + } + return 0, errors.New("tls: peer doesn't support any of the certificate's signature algorithms") +} + +// unsupportedCertificateError returns a helpful error for certificates with +// an unsupported private key. +func unsupportedCertificateError(cert *Certificate) error { + switch cert.PrivateKey.(type) { + case rsa.PrivateKey, ecdsa.PrivateKey: + return fmt.Errorf("tls: unsupported certificate: private key is %T, expected *%T", + cert.PrivateKey, cert.PrivateKey) + case *ed25519.PrivateKey: + return fmt.Errorf("tls: unsupported certificate: private key is *ed25519.PrivateKey, expected ed25519.PrivateKey") + } + + signer, ok := cert.PrivateKey.(crypto.Signer) + if !ok { + return fmt.Errorf("tls: certificate private key (%T) does not implement crypto.Signer", + cert.PrivateKey) + } + + switch pub := signer.Public().(type) { + case *ecdsa.PublicKey: + switch pub.Curve { + case elliptic.P256(): + case elliptic.P384(): + case elliptic.P521(): + default: + return fmt.Errorf("tls: unsupported certificate curve (%s)", pub.Curve.Params().Name) + } + case *rsa.PublicKey: + return fmt.Errorf("tls: certificate RSA key size too small for supported signature algorithms") + case ed25519.PublicKey: + default: + return fmt.Errorf("tls: unsupported certificate key (%T)", pub) + } + + if cert.SupportedSignatureAlgorithms != nil { + return fmt.Errorf("tls: peer doesn't support the certificate custom signature algorithms") + } + + return fmt.Errorf("tls: internal error: unsupported key (%T)", cert.PrivateKey) +} diff --git a/src/crypto/tls/auth_test.go b/src/crypto/tls/auth_test.go new file mode 100644 index 0000000..c42e349 --- /dev/null +++ b/src/crypto/tls/auth_test.go @@ -0,0 +1,168 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "crypto" + "testing" +) + +func TestSignatureSelection(t *testing.T) { + rsaCert := &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + } + pkcs1Cert := &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + SupportedSignatureAlgorithms: []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}, + } + ecdsaCert := &Certificate{ + Certificate: [][]byte{testP256Certificate}, + PrivateKey: testP256PrivateKey, + } + ed25519Cert := &Certificate{ + Certificate: [][]byte{testEd25519Certificate}, + PrivateKey: testEd25519PrivateKey, + } + + tests := []struct { + cert *Certificate + peerSigAlgs []SignatureScheme + tlsVersion uint16 + + expectedSigAlg SignatureScheme + expectedSigType uint8 + expectedHash crypto.Hash + }{ + {rsaCert, []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1}, + {rsaCert, []SignatureScheme{PKCS1WithSHA512, PKCS1WithSHA1}, VersionTLS12, PKCS1WithSHA512, signaturePKCS1v15, crypto.SHA512}, + {rsaCert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS12, PSSWithSHA256, signatureRSAPSS, crypto.SHA256}, + {pkcs1Cert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS12, PKCS1WithSHA256, signaturePKCS1v15, crypto.SHA256}, + {rsaCert, []SignatureScheme{PSSWithSHA384, PKCS1WithSHA1}, VersionTLS13, PSSWithSHA384, signatureRSAPSS, crypto.SHA384}, + {ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1}, + {ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, VersionTLS12, ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256}, + {ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, VersionTLS13, ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256}, + {ed25519Cert, []SignatureScheme{Ed25519}, VersionTLS12, Ed25519, signatureEd25519, directSigning}, + {ed25519Cert, []SignatureScheme{Ed25519}, VersionTLS13, Ed25519, signatureEd25519, directSigning}, + + // TLS 1.2 without signature_algorithms extension + {rsaCert, nil, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1}, + {ecdsaCert, nil, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1}, + + // TLS 1.2 does not restrict the ECDSA curve (our ecdsaCert is P-256) + {ecdsaCert, []SignatureScheme{ECDSAWithP384AndSHA384}, VersionTLS12, ECDSAWithP384AndSHA384, signatureECDSA, crypto.SHA384}, + } + + for testNo, test := range tests { + sigAlg, err := selectSignatureScheme(test.tlsVersion, test.cert, test.peerSigAlgs) + if err != nil { + t.Errorf("test[%d]: unexpected selectSignatureScheme error: %v", testNo, err) + } + if test.expectedSigAlg != sigAlg { + t.Errorf("test[%d]: expected signature scheme %v, got %v", testNo, test.expectedSigAlg, sigAlg) + } + sigType, hashFunc, err := typeAndHashFromSignatureScheme(sigAlg) + if err != nil { + t.Errorf("test[%d]: unexpected typeAndHashFromSignatureScheme error: %v", testNo, err) + } + if test.expectedSigType != sigType { + t.Errorf("test[%d]: expected signature algorithm %#x, got %#x", testNo, test.expectedSigType, sigType) + } + if test.expectedHash != hashFunc { + t.Errorf("test[%d]: expected hash function %#x, got %#x", testNo, test.expectedHash, hashFunc) + } + } + + brokenCert := &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + SupportedSignatureAlgorithms: []SignatureScheme{Ed25519}, + } + + badTests := []struct { + cert *Certificate + peerSigAlgs []SignatureScheme + tlsVersion uint16 + }{ + {rsaCert, []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithSHA1}, VersionTLS12}, + {ecdsaCert, []SignatureScheme{PKCS1WithSHA256, PKCS1WithSHA1}, VersionTLS12}, + {rsaCert, []SignatureScheme{0}, VersionTLS12}, + {ed25519Cert, []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithSHA1}, VersionTLS12}, + {ecdsaCert, []SignatureScheme{Ed25519}, VersionTLS12}, + {brokenCert, []SignatureScheme{Ed25519}, VersionTLS12}, + {brokenCert, []SignatureScheme{PKCS1WithSHA256}, VersionTLS12}, + // RFC 5246, Section 7.4.1.4.1, says to only consider {sha1,ecdsa} as + // default when the extension is missing, and RFC 8422 does not update + // it. Anyway, if a stack supports Ed25519 it better support sigalgs. + {ed25519Cert, nil, VersionTLS12}, + // TLS 1.3 has no default signature_algorithms. + {rsaCert, nil, VersionTLS13}, + {ecdsaCert, nil, VersionTLS13}, + {ed25519Cert, nil, VersionTLS13}, + // Wrong curve, which TLS 1.3 checks + {ecdsaCert, []SignatureScheme{ECDSAWithP384AndSHA384}, VersionTLS13}, + // TLS 1.3 does not support PKCS1v1.5 or SHA-1. + {rsaCert, []SignatureScheme{PKCS1WithSHA256}, VersionTLS13}, + {pkcs1Cert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS13}, + {ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS13}, + // The key can be too small for the hash. + {rsaCert, []SignatureScheme{PSSWithSHA512}, VersionTLS12}, + } + + for testNo, test := range badTests { + sigAlg, err := selectSignatureScheme(test.tlsVersion, test.cert, test.peerSigAlgs) + if err == nil { + t.Errorf("test[%d]: unexpected success, got %v", testNo, sigAlg) + } + } +} + +func TestLegacyTypeAndHash(t *testing.T) { + sigType, hashFunc, err := legacyTypeAndHashFromPublicKey(testRSAPrivateKey.Public()) + if err != nil { + t.Errorf("RSA: unexpected error: %v", err) + } + if expectedSigType := signaturePKCS1v15; expectedSigType != sigType { + t.Errorf("RSA: expected signature type %#x, got %#x", expectedSigType, sigType) + } + if expectedHashFunc := crypto.MD5SHA1; expectedHashFunc != hashFunc { + t.Errorf("RSA: expected hash %#x, got %#x", expectedHashFunc, hashFunc) + } + + sigType, hashFunc, err = legacyTypeAndHashFromPublicKey(testECDSAPrivateKey.Public()) + if err != nil { + t.Errorf("ECDSA: unexpected error: %v", err) + } + if expectedSigType := signatureECDSA; expectedSigType != sigType { + t.Errorf("ECDSA: expected signature type %#x, got %#x", expectedSigType, sigType) + } + if expectedHashFunc := crypto.SHA1; expectedHashFunc != hashFunc { + t.Errorf("ECDSA: expected hash %#x, got %#x", expectedHashFunc, hashFunc) + } + + // Ed25519 is not supported by TLS 1.0 and 1.1. + _, _, err = legacyTypeAndHashFromPublicKey(testEd25519PrivateKey.Public()) + if err == nil { + t.Errorf("Ed25519: unexpected success") + } +} + +// TestSupportedSignatureAlgorithms checks that all supportedSignatureAlgorithms +// have valid type and hash information. +func TestSupportedSignatureAlgorithms(t *testing.T) { + for _, sigAlg := range supportedSignatureAlgorithms { + sigType, hash, err := typeAndHashFromSignatureScheme(sigAlg) + if err != nil { + t.Errorf("%v: unexpected error: %v", sigAlg, err) + } + if sigType == 0 { + t.Errorf("%v: missing signature type", sigAlg) + } + if hash == 0 && sigAlg != Ed25519 { + t.Errorf("%v: missing hash", sigAlg) + } + } +} diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go new file mode 100644 index 0000000..4bf0646 --- /dev/null +++ b/src/crypto/tls/cipher_suites.go @@ -0,0 +1,689 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/des" + "crypto/hmac" + "crypto/rc4" + "crypto/sha1" + "crypto/sha256" + "fmt" + "hash" + "internal/cpu" + "runtime" + + "golang.org/x/crypto/chacha20poly1305" +) + +// CipherSuite is a TLS cipher suite. Note that most functions in this package +// accept and expose cipher suite IDs instead of this type. +type CipherSuite struct { + ID uint16 + Name string + + // Supported versions is the list of TLS protocol versions that can + // negotiate this cipher suite. + SupportedVersions []uint16 + + // Insecure is true if the cipher suite has known security issues + // due to its primitives, design, or implementation. + Insecure bool +} + +var ( + supportedUpToTLS12 = []uint16{VersionTLS10, VersionTLS11, VersionTLS12} + supportedOnlyTLS12 = []uint16{VersionTLS12} + supportedOnlyTLS13 = []uint16{VersionTLS13} +) + +// CipherSuites returns a list of cipher suites currently implemented by this +// package, excluding those with security issues, which are returned by +// InsecureCipherSuites. +// +// The list is sorted by ID. Note that the default cipher suites selected by +// this package might depend on logic that can't be captured by a static list, +// and might not match those returned by this function. +func CipherSuites() []*CipherSuite { + return []*CipherSuite{ + {TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, + {TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, + {TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, + {TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS_RSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false}, + + {TLS_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256", supportedOnlyTLS13, false}, + {TLS_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384", supportedOnlyTLS13, false}, + {TLS_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256", supportedOnlyTLS13, false}, + + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, + {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, + {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, + {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, + {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false}, + {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, + {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false}, + {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false}, + {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false}, + } +} + +// InsecureCipherSuites returns a list of cipher suites currently implemented by +// this package and which have security issues. +// +// Most applications should not use the cipher suites in this list, and should +// only use those returned by CipherSuites. +func InsecureCipherSuites() []*CipherSuite { + // This list includes RC4, CBC_SHA256, and 3DES cipher suites. See + // cipherSuitesPreferenceOrder for details. + return []*CipherSuite{ + {TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, + {TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, + {TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, + {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, + {TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, + {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, + } +} + +// CipherSuiteName returns the standard name for the passed cipher suite ID +// (e.g. "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"), or a fallback representation +// of the ID value if the cipher suite is not implemented by this package. +func CipherSuiteName(id uint16) string { + for _, c := range CipherSuites() { + if c.ID == id { + return c.Name + } + } + for _, c := range InsecureCipherSuites() { + if c.ID == id { + return c.Name + } + } + return fmt.Sprintf("0x%04X", id) +} + +const ( + // suiteECDHE indicates that the cipher suite involves elliptic curve + // Diffie-Hellman. This means that it should only be selected when the + // client indicates that it supports ECC with a curve and point format + // that we're happy with. + suiteECDHE = 1 << iota + // suiteECSign indicates that the cipher suite involves an ECDSA or + // EdDSA signature and therefore may only be selected when the server's + // certificate is ECDSA or EdDSA. If this is not set then the cipher suite + // is RSA based. + suiteECSign + // suiteTLS12 indicates that the cipher suite should only be advertised + // and accepted when using TLS 1.2. + suiteTLS12 + // suiteSHA384 indicates that the cipher suite uses SHA384 as the + // handshake hash. + suiteSHA384 +) + +// A cipherSuite is a TLS 1.0–1.2 cipher suite, and defines the key exchange +// mechanism, as well as the cipher+MAC pair or the AEAD. +type cipherSuite struct { + id uint16 + // the lengths, in bytes, of the key material needed for each component. + keyLen int + macLen int + ivLen int + ka func(version uint16) keyAgreement + // flags is a bitmask of the suite* values, above. + flags int + cipher func(key, iv []byte, isRead bool) interface{} + mac func(key []byte) hash.Hash + aead func(key, fixedNonce []byte) aead +} + +var cipherSuites = []*cipherSuite{ // TODO: replace with a map, since the order doesn't matter. + {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, + {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, + {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM}, + {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadAESGCM}, + {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil}, + {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, + {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil}, + {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, + {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, + {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, + {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, + {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, + {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil}, + {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil}, + {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil}, + {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil}, + {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherRC4, macSHA1, nil}, +} + +// selectCipherSuite returns the first TLS 1.0–1.2 cipher suite from ids which +// is also in supportedIDs and passes the ok filter. +func selectCipherSuite(ids, supportedIDs []uint16, ok func(*cipherSuite) bool) *cipherSuite { + for _, id := range ids { + candidate := cipherSuiteByID(id) + if candidate == nil || !ok(candidate) { + continue + } + + for _, suppID := range supportedIDs { + if id == suppID { + return candidate + } + } + } + return nil +} + +// A cipherSuiteTLS13 defines only the pair of the AEAD algorithm and hash +// algorithm to be used with HKDF. See RFC 8446, Appendix B.4. +type cipherSuiteTLS13 struct { + id uint16 + keyLen int + aead func(key, fixedNonce []byte) aead + hash crypto.Hash +} + +var cipherSuitesTLS13 = []*cipherSuiteTLS13{ // TODO: replace with a map. + {TLS_AES_128_GCM_SHA256, 16, aeadAESGCMTLS13, crypto.SHA256}, + {TLS_CHACHA20_POLY1305_SHA256, 32, aeadChaCha20Poly1305, crypto.SHA256}, + {TLS_AES_256_GCM_SHA384, 32, aeadAESGCMTLS13, crypto.SHA384}, +} + +// cipherSuitesPreferenceOrder is the order in which we'll select (on the +// server) or advertise (on the client) TLS 1.0–1.2 cipher suites. +// +// Cipher suites are filtered but not reordered based on the application and +// peer's preferences, meaning we'll never select a suite lower in this list if +// any higher one is available. This makes it more defensible to keep weaker +// cipher suites enabled, especially on the server side where we get the last +// word, since there are no known downgrade attacks on cipher suites selection. +// +// The list is sorted by applying the following priority rules, stopping at the +// first (most important) applicable one: +// +// - Anything else comes before RC4 +// +// RC4 has practically exploitable biases. See https://www.rc4nomore.com. +// +// - Anything else comes before CBC_SHA256 +// +// SHA-256 variants of the CBC ciphersuites don't implement any Lucky13 +// countermeasures. See http://www.isg.rhul.ac.uk/tls/Lucky13.html and +// https://www.imperialviolet.org/2013/02/04/luckythirteen.html. +// +// - Anything else comes before 3DES +// +// 3DES has 64-bit blocks, which makes it fundamentally susceptible to +// birthday attacks. See https://sweet32.info. +// +// - ECDHE comes before anything else +// +// Once we got the broken stuff out of the way, the most important +// property a cipher suite can have is forward secrecy. We don't +// implement FFDHE, so that means ECDHE. +// +// - AEADs come before CBC ciphers +// +// Even with Lucky13 countermeasures, MAC-then-Encrypt CBC cipher suites +// are fundamentally fragile, and suffered from an endless sequence of +// padding oracle attacks. See https://eprint.iacr.org/2015/1129, +// https://www.imperialviolet.org/2014/12/08/poodleagain.html, and +// https://blog.cloudflare.com/yet-another-padding-oracle-in-openssl-cbc-ciphersuites/. +// +// - AES comes before ChaCha20 +// +// When AES hardware is available, AES-128-GCM and AES-256-GCM are faster +// than ChaCha20Poly1305. +// +// When AES hardware is not available, AES-128-GCM is one or more of: much +// slower, way more complex, and less safe (because not constant time) +// than ChaCha20Poly1305. +// +// We use this list if we think both peers have AES hardware, and +// cipherSuitesPreferenceOrderNoAES otherwise. +// +// - AES-128 comes before AES-256 +// +// The only potential advantages of AES-256 are better multi-target +// margins, and hypothetical post-quantum properties. Neither apply to +// TLS, and AES-256 is slower due to its four extra rounds (which don't +// contribute to the advantages above). +// +// - ECDSA comes before RSA +// +// The relative order of ECDSA and RSA cipher suites doesn't matter, +// as they depend on the certificate. Pick one to get a stable order. +// +var cipherSuitesPreferenceOrder = []uint16{ + // AEADs w/ ECDHE + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + + // CBC w/ ECDHE + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + + // AEADs w/o ECDHE + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, + + // CBC w/o ECDHE + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + + // 3DES + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + + // CBC_SHA256 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + + // RC4 + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_SHA, +} + +var cipherSuitesPreferenceOrderNoAES = []uint16{ + // ChaCha20Poly1305 + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + + // AES-GCM w/ ECDHE + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + + // The rest of cipherSuitesPreferenceOrder. + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_SHA, +} + +// disabledCipherSuites are not used unless explicitly listed in +// Config.CipherSuites. They MUST be at the end of cipherSuitesPreferenceOrder. +var disabledCipherSuites = []uint16{ + // CBC_SHA256 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + + // RC4 + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_SHA, +} + +var ( + defaultCipherSuitesLen = len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites) + defaultCipherSuites = cipherSuitesPreferenceOrder[:defaultCipherSuitesLen] +) + +// defaultCipherSuitesTLS13 is also the preference order, since there are no +// disabled by default TLS 1.3 cipher suites. The same AES vs ChaCha20 logic as +// cipherSuitesPreferenceOrder applies. +var defaultCipherSuitesTLS13 = []uint16{ + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, + TLS_CHACHA20_POLY1305_SHA256, +} + +var defaultCipherSuitesTLS13NoAES = []uint16{ + TLS_CHACHA20_POLY1305_SHA256, + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, +} + +var ( + hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ + hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL + // Keep in sync with crypto/aes/cipher_s390x.go. + hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && + (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) + + hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || + runtime.GOARCH == "arm64" && hasGCMAsmARM64 || + runtime.GOARCH == "s390x" && hasGCMAsmS390X +) + +var aesgcmCiphers = map[uint16]bool{ + // TLS 1.2 + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: true, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: true, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true, + // TLS 1.3 + TLS_AES_128_GCM_SHA256: true, + TLS_AES_256_GCM_SHA384: true, +} + +var nonAESGCMAEADCiphers = map[uint16]bool{ + // TLS 1.2 + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: true, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: true, + // TLS 1.3 + TLS_CHACHA20_POLY1305_SHA256: true, +} + +// aesgcmPreferred returns whether the first known cipher in the preference list +// is an AES-GCM cipher, implying the peer has hardware support for it. +func aesgcmPreferred(ciphers []uint16) bool { + for _, cID := range ciphers { + if c := cipherSuiteByID(cID); c != nil { + return aesgcmCiphers[cID] + } + if c := cipherSuiteTLS13ByID(cID); c != nil { + return aesgcmCiphers[cID] + } + } + return false +} + +func cipherRC4(key, iv []byte, isRead bool) interface{} { + cipher, _ := rc4.NewCipher(key) + return cipher +} + +func cipher3DES(key, iv []byte, isRead bool) interface{} { + block, _ := des.NewTripleDESCipher(key) + if isRead { + return cipher.NewCBCDecrypter(block, iv) + } + return cipher.NewCBCEncrypter(block, iv) +} + +func cipherAES(key, iv []byte, isRead bool) interface{} { + block, _ := aes.NewCipher(key) + if isRead { + return cipher.NewCBCDecrypter(block, iv) + } + return cipher.NewCBCEncrypter(block, iv) +} + +// macSHA1 returns a SHA-1 based constant time MAC. +func macSHA1(key []byte) hash.Hash { + return hmac.New(newConstantTimeHash(sha1.New), key) +} + +// macSHA256 returns a SHA-256 based MAC. This is only supported in TLS 1.2 and +// is currently only used in disabled-by-default cipher suites. +func macSHA256(key []byte) hash.Hash { + return hmac.New(sha256.New, key) +} + +type aead interface { + cipher.AEAD + + // explicitNonceLen returns the number of bytes of explicit nonce + // included in each record. This is eight for older AEADs and + // zero for modern ones. + explicitNonceLen() int +} + +const ( + aeadNonceLength = 12 + noncePrefixLength = 4 +) + +// prefixNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to +// each call. +type prefixNonceAEAD struct { + // nonce contains the fixed part of the nonce in the first four bytes. + nonce [aeadNonceLength]byte + aead cipher.AEAD +} + +func (f *prefixNonceAEAD) NonceSize() int { return aeadNonceLength - noncePrefixLength } +func (f *prefixNonceAEAD) Overhead() int { return f.aead.Overhead() } +func (f *prefixNonceAEAD) explicitNonceLen() int { return f.NonceSize() } + +func (f *prefixNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { + copy(f.nonce[4:], nonce) + return f.aead.Seal(out, f.nonce[:], plaintext, additionalData) +} + +func (f *prefixNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) { + copy(f.nonce[4:], nonce) + return f.aead.Open(out, f.nonce[:], ciphertext, additionalData) +} + +// xoredNonceAEAD wraps an AEAD by XORing in a fixed pattern to the nonce +// before each call. +type xorNonceAEAD struct { + nonceMask [aeadNonceLength]byte + aead cipher.AEAD +} + +func (f *xorNonceAEAD) NonceSize() int { return 8 } // 64-bit sequence number +func (f *xorNonceAEAD) Overhead() int { return f.aead.Overhead() } +func (f *xorNonceAEAD) explicitNonceLen() int { return 0 } + +func (f *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { + for i, b := range nonce { + f.nonceMask[4+i] ^= b + } + result := f.aead.Seal(out, f.nonceMask[:], plaintext, additionalData) + for i, b := range nonce { + f.nonceMask[4+i] ^= b + } + + return result +} + +func (f *xorNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) { + for i, b := range nonce { + f.nonceMask[4+i] ^= b + } + result, err := f.aead.Open(out, f.nonceMask[:], ciphertext, additionalData) + for i, b := range nonce { + f.nonceMask[4+i] ^= b + } + + return result, err +} + +func aeadAESGCM(key, noncePrefix []byte) aead { + if len(noncePrefix) != noncePrefixLength { + panic("tls: internal error: wrong nonce length") + } + aes, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + aead, err := cipher.NewGCM(aes) + if err != nil { + panic(err) + } + + ret := &prefixNonceAEAD{aead: aead} + copy(ret.nonce[:], noncePrefix) + return ret +} + +func aeadAESGCMTLS13(key, nonceMask []byte) aead { + if len(nonceMask) != aeadNonceLength { + panic("tls: internal error: wrong nonce length") + } + aes, err := aes.NewCipher(key) + if err != nil { + panic(err) + } + aead, err := cipher.NewGCM(aes) + if err != nil { + panic(err) + } + + ret := &xorNonceAEAD{aead: aead} + copy(ret.nonceMask[:], nonceMask) + return ret +} + +func aeadChaCha20Poly1305(key, nonceMask []byte) aead { + if len(nonceMask) != aeadNonceLength { + panic("tls: internal error: wrong nonce length") + } + aead, err := chacha20poly1305.New(key) + if err != nil { + panic(err) + } + + ret := &xorNonceAEAD{aead: aead} + copy(ret.nonceMask[:], nonceMask) + return ret +} + +type constantTimeHash interface { + hash.Hash + ConstantTimeSum(b []byte) []byte +} + +// cthWrapper wraps any hash.Hash that implements ConstantTimeSum, and replaces +// with that all calls to Sum. It's used to obtain a ConstantTimeSum-based HMAC. +type cthWrapper struct { + h constantTimeHash +} + +func (c *cthWrapper) Size() int { return c.h.Size() } +func (c *cthWrapper) BlockSize() int { return c.h.BlockSize() } +func (c *cthWrapper) Reset() { c.h.Reset() } +func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) } +func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) } + +func newConstantTimeHash(h func() hash.Hash) func() hash.Hash { + return func() hash.Hash { + return &cthWrapper{h().(constantTimeHash)} + } +} + +// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, Section 6.2.3. +func tls10MAC(h hash.Hash, out, seq, header, data, extra []byte) []byte { + h.Reset() + h.Write(seq) + h.Write(header) + h.Write(data) + res := h.Sum(out) + if extra != nil { + h.Write(extra) + } + return res +} + +func rsaKA(version uint16) keyAgreement { + return rsaKeyAgreement{} +} + +func ecdheECDSAKA(version uint16) keyAgreement { + return &ecdheKeyAgreement{ + isRSA: false, + version: version, + } +} + +func ecdheRSAKA(version uint16) keyAgreement { + return &ecdheKeyAgreement{ + isRSA: true, + version: version, + } +} + +// mutualCipherSuite returns a cipherSuite given a list of supported +// ciphersuites and the id requested by the peer. +func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { + for _, id := range have { + if id == want { + return cipherSuiteByID(id) + } + } + return nil +} + +func cipherSuiteByID(id uint16) *cipherSuite { + for _, cipherSuite := range cipherSuites { + if cipherSuite.id == id { + return cipherSuite + } + } + return nil +} + +func mutualCipherSuiteTLS13(have []uint16, want uint16) *cipherSuiteTLS13 { + for _, id := range have { + if id == want { + return cipherSuiteTLS13ByID(id) + } + } + return nil +} + +func cipherSuiteTLS13ByID(id uint16) *cipherSuiteTLS13 { + for _, cipherSuite := range cipherSuitesTLS13 { + if cipherSuite.id == id { + return cipherSuite + } + } + return nil +} + +// A list of cipher suite IDs that are, or have been, implemented by this +// package. +// +// See https://www.iana.org/assignments/tls-parameters/tls-parameters.xml +const ( + // TLS 1.0 - 1.2 cipher suites. + TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 + TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a + TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f + TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 + TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c + TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c + TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a + TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011 + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027 + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030 + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca8 + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca9 + + // TLS 1.3 cipher suites. + TLS_AES_128_GCM_SHA256 uint16 = 0x1301 + TLS_AES_256_GCM_SHA384 uint16 = 0x1302 + TLS_CHACHA20_POLY1305_SHA256 uint16 = 0x1303 + + // TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator + // that the client is doing version fallback. See RFC 7507. + TLS_FALLBACK_SCSV uint16 = 0x5600 + + // Legacy names for the corresponding cipher suites with the correct _SHA256 + // suffix, retained for backward compatibility. + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 +) diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go new file mode 100644 index 0000000..d561e61 --- /dev/null +++ b/src/crypto/tls/common.go @@ -0,0 +1,1458 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "container/list" + "context" + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/sha512" + "crypto/x509" + "errors" + "fmt" + "io" + "net" + "strings" + "sync" + "time" +) + +const ( + VersionTLS10 = 0x0301 + VersionTLS11 = 0x0302 + VersionTLS12 = 0x0303 + VersionTLS13 = 0x0304 + + // Deprecated: SSLv3 is cryptographically broken, and is no longer + // supported by this package. See golang.org/issue/32716. + VersionSSL30 = 0x0300 +) + +const ( + maxPlaintext = 16384 // maximum plaintext payload length + maxCiphertext = 16384 + 2048 // maximum ciphertext payload length + maxCiphertextTLS13 = 16384 + 256 // maximum ciphertext length in TLS 1.3 + recordHeaderLen = 5 // record header length + maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) + maxUselessRecords = 16 // maximum number of consecutive non-advancing records +) + +// TLS record types. +type recordType uint8 + +const ( + recordTypeChangeCipherSpec recordType = 20 + recordTypeAlert recordType = 21 + recordTypeHandshake recordType = 22 + recordTypeApplicationData recordType = 23 +) + +// TLS handshake message types. +const ( + typeHelloRequest uint8 = 0 + typeClientHello uint8 = 1 + typeServerHello uint8 = 2 + typeNewSessionTicket uint8 = 4 + typeEndOfEarlyData uint8 = 5 + typeEncryptedExtensions uint8 = 8 + typeCertificate uint8 = 11 + typeServerKeyExchange uint8 = 12 + typeCertificateRequest uint8 = 13 + typeServerHelloDone uint8 = 14 + typeCertificateVerify uint8 = 15 + typeClientKeyExchange uint8 = 16 + typeFinished uint8 = 20 + typeCertificateStatus uint8 = 22 + typeKeyUpdate uint8 = 24 + typeNextProtocol uint8 = 67 // Not IANA assigned + typeMessageHash uint8 = 254 // synthetic message +) + +// TLS compression types. +const ( + compressionNone uint8 = 0 +) + +// TLS extension numbers +const ( + extensionServerName uint16 = 0 + extensionStatusRequest uint16 = 5 + extensionSupportedCurves uint16 = 10 // supported_groups in TLS 1.3, see RFC 8446, Section 4.2.7 + extensionSupportedPoints uint16 = 11 + extensionSignatureAlgorithms uint16 = 13 + extensionALPN uint16 = 16 + extensionSCT uint16 = 18 + extensionSessionTicket uint16 = 35 + extensionPreSharedKey uint16 = 41 + extensionEarlyData uint16 = 42 + extensionSupportedVersions uint16 = 43 + extensionCookie uint16 = 44 + extensionPSKModes uint16 = 45 + extensionCertificateAuthorities uint16 = 47 + extensionSignatureAlgorithmsCert uint16 = 50 + extensionKeyShare uint16 = 51 + extensionRenegotiationInfo uint16 = 0xff01 +) + +// TLS signaling cipher suite values +const ( + scsvRenegotiation uint16 = 0x00ff +) + +// CurveID is the type of a TLS identifier for an elliptic curve. See +// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8. +// +// In TLS 1.3, this type is called NamedGroup, but at this time this library +// only supports Elliptic Curve based groups. See RFC 8446, Section 4.2.7. +type CurveID uint16 + +const ( + CurveP256 CurveID = 23 + CurveP384 CurveID = 24 + CurveP521 CurveID = 25 + X25519 CurveID = 29 +) + +// TLS 1.3 Key Share. See RFC 8446, Section 4.2.8. +type keyShare struct { + group CurveID + data []byte +} + +// TLS 1.3 PSK Key Exchange Modes. See RFC 8446, Section 4.2.9. +const ( + pskModePlain uint8 = 0 + pskModeDHE uint8 = 1 +) + +// TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved +// session. See RFC 8446, Section 4.2.11. +type pskIdentity struct { + label []byte + obfuscatedTicketAge uint32 +} + +// TLS Elliptic Curve Point Formats +// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 +const ( + pointFormatUncompressed uint8 = 0 +) + +// TLS CertificateStatusType (RFC 3546) +const ( + statusTypeOCSP uint8 = 1 +) + +// Certificate types (for certificateRequestMsg) +const ( + certTypeRSASign = 1 + certTypeECDSASign = 64 // ECDSA or EdDSA keys, see RFC 8422, Section 3. +) + +// Signature algorithms (for internal signaling use). Starting at 225 to avoid overlap with +// TLS 1.2 codepoints (RFC 5246, Appendix A.4.1), with which these have nothing to do. +const ( + signaturePKCS1v15 uint8 = iota + 225 + signatureRSAPSS + signatureECDSA + signatureEd25519 +) + +// directSigning is a standard Hash value that signals that no pre-hashing +// should be performed, and that the input should be signed directly. It is the +// hash function associated with the Ed25519 signature scheme. +var directSigning crypto.Hash = 0 + +// supportedSignatureAlgorithms contains the signature and hash algorithms that +// the code advertises as supported in a TLS 1.2+ ClientHello and in a TLS 1.2+ +// CertificateRequest. The two fields are merged to match with TLS 1.3. +// Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc. +var supportedSignatureAlgorithms = []SignatureScheme{ + PSSWithSHA256, + ECDSAWithP256AndSHA256, + Ed25519, + PSSWithSHA384, + PSSWithSHA512, + PKCS1WithSHA256, + PKCS1WithSHA384, + PKCS1WithSHA512, + ECDSAWithP384AndSHA384, + ECDSAWithP521AndSHA512, + PKCS1WithSHA1, + ECDSAWithSHA1, +} + +// helloRetryRequestRandom is set as the Random value of a ServerHello +// to signal that the message is actually a HelloRetryRequest. +var helloRetryRequestRandom = []byte{ // See RFC 8446, Section 4.1.3. + 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, + 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C, +} + +const ( + // downgradeCanaryTLS12 or downgradeCanaryTLS11 is embedded in the server + // random as a downgrade protection if the server would be capable of + // negotiating a higher version. See RFC 8446, Section 4.1.3. + downgradeCanaryTLS12 = "DOWNGRD\x01" + downgradeCanaryTLS11 = "DOWNGRD\x00" +) + +// testingOnlyForceDowngradeCanary is set in tests to force the server side to +// include downgrade canaries even if it's using its highers supported version. +var testingOnlyForceDowngradeCanary bool + +// ConnectionState records basic TLS details about the connection. +type ConnectionState struct { + // Version is the TLS version used by the connection (e.g. VersionTLS12). + Version uint16 + + // HandshakeComplete is true if the handshake has concluded. + HandshakeComplete bool + + // DidResume is true if this connection was successfully resumed from a + // previous session with a session ticket or similar mechanism. + DidResume bool + + // CipherSuite is the cipher suite negotiated for the connection (e.g. + // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_AES_128_GCM_SHA256). + CipherSuite uint16 + + // NegotiatedProtocol is the application protocol negotiated with ALPN. + NegotiatedProtocol string + + // NegotiatedProtocolIsMutual used to indicate a mutual NPN negotiation. + // + // Deprecated: this value is always true. + NegotiatedProtocolIsMutual bool + + // ServerName is the value of the Server Name Indication extension sent by + // the client. It's available both on the server and on the client side. + ServerName string + + // PeerCertificates are the parsed certificates sent by the peer, in the + // order in which they were sent. The first element is the leaf certificate + // that the connection is verified against. + // + // On the client side, it can't be empty. On the server side, it can be + // empty if Config.ClientAuth is not RequireAnyClientCert or + // RequireAndVerifyClientCert. + PeerCertificates []*x509.Certificate + + // VerifiedChains is a list of one or more chains where the first element is + // PeerCertificates[0] and the last element is from Config.RootCAs (on the + // client side) or Config.ClientCAs (on the server side). + // + // On the client side, it's set if Config.InsecureSkipVerify is false. On + // the server side, it's set if Config.ClientAuth is VerifyClientCertIfGiven + // (and the peer provided a certificate) or RequireAndVerifyClientCert. + VerifiedChains [][]*x509.Certificate + + // SignedCertificateTimestamps is a list of SCTs provided by the peer + // through the TLS handshake for the leaf certificate, if any. + SignedCertificateTimestamps [][]byte + + // OCSPResponse is a stapled Online Certificate Status Protocol (OCSP) + // response provided by the peer for the leaf certificate, if any. + OCSPResponse []byte + + // TLSUnique contains the "tls-unique" channel binding value (see RFC 5929, + // Section 3). This value will be nil for TLS 1.3 connections and for all + // resumed connections. + // + // Deprecated: there are conditions in which this value might not be unique + // to a connection. See the Security Considerations sections of RFC 5705 and + // RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings. + TLSUnique []byte + + // ekm is a closure exposed via ExportKeyingMaterial. + ekm func(label string, context []byte, length int) ([]byte, error) +} + +// ExportKeyingMaterial returns length bytes of exported key material in a new +// slice as defined in RFC 5705. If context is nil, it is not used as part of +// the seed. If the connection was set to allow renegotiation via +// Config.Renegotiation, this function will return an error. +func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) { + return cs.ekm(label, context, length) +} + +// ClientAuthType declares the policy the server will follow for +// TLS Client Authentication. +type ClientAuthType int + +const ( + // NoClientCert indicates that no client certificate should be requested + // during the handshake, and if any certificates are sent they will not + // be verified. + NoClientCert ClientAuthType = iota + // RequestClientCert indicates that a client certificate should be requested + // during the handshake, but does not require that the client send any + // certificates. + RequestClientCert + // RequireAnyClientCert indicates that a client certificate should be requested + // during the handshake, and that at least one certificate is required to be + // sent by the client, but that certificate is not required to be valid. + RequireAnyClientCert + // VerifyClientCertIfGiven indicates that a client certificate should be requested + // during the handshake, but does not require that the client sends a + // certificate. If the client does send a certificate it is required to be + // valid. + VerifyClientCertIfGiven + // RequireAndVerifyClientCert indicates that a client certificate should be requested + // during the handshake, and that at least one valid certificate is required + // to be sent by the client. + RequireAndVerifyClientCert +) + +// requiresClientCert reports whether the ClientAuthType requires a client +// certificate to be provided. +func requiresClientCert(c ClientAuthType) bool { + switch c { + case RequireAnyClientCert, RequireAndVerifyClientCert: + return true + default: + return false + } +} + +// ClientSessionState contains the state needed by clients to resume TLS +// sessions. +type ClientSessionState struct { + sessionTicket []uint8 // Encrypted ticket used for session resumption with server + vers uint16 // TLS version negotiated for the session + cipherSuite uint16 // Ciphersuite negotiated for the session + masterSecret []byte // Full handshake MasterSecret, or TLS 1.3 resumption_master_secret + serverCertificates []*x509.Certificate // Certificate chain presented by the server + verifiedChains [][]*x509.Certificate // Certificate chains we built for verification + receivedAt time.Time // When the session ticket was received from the server + ocspResponse []byte // Stapled OCSP response presented by the server + scts [][]byte // SCTs presented by the server + + // TLS 1.3 fields. + nonce []byte // Ticket nonce sent by the server, to derive PSK + useBy time.Time // Expiration of the ticket lifetime as set by the server + ageAdd uint32 // Random obfuscation factor for sending the ticket age +} + +// ClientSessionCache is a cache of ClientSessionState objects that can be used +// by a client to resume a TLS session with a given server. ClientSessionCache +// implementations should expect to be called concurrently from different +// goroutines. Up to TLS 1.2, only ticket-based resumption is supported, not +// SessionID-based resumption. In TLS 1.3 they were merged into PSK modes, which +// are supported via this interface. +type ClientSessionCache interface { + // Get searches for a ClientSessionState associated with the given key. + // On return, ok is true if one was found. + Get(sessionKey string) (session *ClientSessionState, ok bool) + + // Put adds the ClientSessionState to the cache with the given key. It might + // get called multiple times in a connection if a TLS 1.3 server provides + // more than one session ticket. If called with a nil *ClientSessionState, + // it should remove the cache entry. + Put(sessionKey string, cs *ClientSessionState) +} + +//go:generate stringer -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go + +// SignatureScheme identifies a signature algorithm supported by TLS. See +// RFC 8446, Section 4.2.3. +type SignatureScheme uint16 + +const ( + // RSASSA-PKCS1-v1_5 algorithms. + PKCS1WithSHA256 SignatureScheme = 0x0401 + PKCS1WithSHA384 SignatureScheme = 0x0501 + PKCS1WithSHA512 SignatureScheme = 0x0601 + + // RSASSA-PSS algorithms with public key OID rsaEncryption. + PSSWithSHA256 SignatureScheme = 0x0804 + PSSWithSHA384 SignatureScheme = 0x0805 + PSSWithSHA512 SignatureScheme = 0x0806 + + // ECDSA algorithms. Only constrained to a specific curve in TLS 1.3. + ECDSAWithP256AndSHA256 SignatureScheme = 0x0403 + ECDSAWithP384AndSHA384 SignatureScheme = 0x0503 + ECDSAWithP521AndSHA512 SignatureScheme = 0x0603 + + // EdDSA algorithms. + Ed25519 SignatureScheme = 0x0807 + + // Legacy signature and hash algorithms for TLS 1.2. + PKCS1WithSHA1 SignatureScheme = 0x0201 + ECDSAWithSHA1 SignatureScheme = 0x0203 +) + +// ClientHelloInfo contains information from a ClientHello message in order to +// guide application logic in the GetCertificate and GetConfigForClient callbacks. +type ClientHelloInfo struct { + // CipherSuites lists the CipherSuites supported by the client (e.g. + // TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256). + CipherSuites []uint16 + + // ServerName indicates the name of the server requested by the client + // in order to support virtual hosting. ServerName is only set if the + // client is using SNI (see RFC 4366, Section 3.1). + ServerName string + + // SupportedCurves lists the elliptic curves supported by the client. + // SupportedCurves is set only if the Supported Elliptic Curves + // Extension is being used (see RFC 4492, Section 5.1.1). + SupportedCurves []CurveID + + // SupportedPoints lists the point formats supported by the client. + // SupportedPoints is set only if the Supported Point Formats Extension + // is being used (see RFC 4492, Section 5.1.2). + SupportedPoints []uint8 + + // SignatureSchemes lists the signature and hash schemes that the client + // is willing to verify. SignatureSchemes is set only if the Signature + // Algorithms Extension is being used (see RFC 5246, Section 7.4.1.4.1). + SignatureSchemes []SignatureScheme + + // SupportedProtos lists the application protocols supported by the client. + // SupportedProtos is set only if the Application-Layer Protocol + // Negotiation Extension is being used (see RFC 7301, Section 3.1). + // + // Servers can select a protocol by setting Config.NextProtos in a + // GetConfigForClient return value. + SupportedProtos []string + + // SupportedVersions lists the TLS versions supported by the client. + // For TLS versions less than 1.3, this is extrapolated from the max + // version advertised by the client, so values other than the greatest + // might be rejected if used. + SupportedVersions []uint16 + + // Conn is the underlying net.Conn for the connection. Do not read + // from, or write to, this connection; that will cause the TLS + // connection to fail. + Conn net.Conn + + // config is embedded by the GetCertificate or GetConfigForClient caller, + // for use with SupportsCertificate. + config *Config + + // ctx is the context of the handshake that is in progress. + ctx context.Context +} + +// Context returns the context of the handshake that is in progress. +// This context is a child of the context passed to HandshakeContext, +// if any, and is canceled when the handshake concludes. +func (c *ClientHelloInfo) Context() context.Context { + return c.ctx +} + +// CertificateRequestInfo contains information from a server's +// CertificateRequest message, which is used to demand a certificate and proof +// of control from a client. +type CertificateRequestInfo struct { + // AcceptableCAs contains zero or more, DER-encoded, X.501 + // Distinguished Names. These are the names of root or intermediate CAs + // that the server wishes the returned certificate to be signed by. An + // empty slice indicates that the server has no preference. + AcceptableCAs [][]byte + + // SignatureSchemes lists the signature schemes that the server is + // willing to verify. + SignatureSchemes []SignatureScheme + + // Version is the TLS version that was negotiated for this connection. + Version uint16 + + // ctx is the context of the handshake that is in progress. + ctx context.Context +} + +// Context returns the context of the handshake that is in progress. +// This context is a child of the context passed to HandshakeContext, +// if any, and is canceled when the handshake concludes. +func (c *CertificateRequestInfo) Context() context.Context { + return c.ctx +} + +// RenegotiationSupport enumerates the different levels of support for TLS +// renegotiation. TLS renegotiation is the act of performing subsequent +// handshakes on a connection after the first. This significantly complicates +// the state machine and has been the source of numerous, subtle security +// issues. Initiating a renegotiation is not supported, but support for +// accepting renegotiation requests may be enabled. +// +// Even when enabled, the server may not change its identity between handshakes +// (i.e. the leaf certificate must be the same). Additionally, concurrent +// handshake and application data flow is not permitted so renegotiation can +// only be used with protocols that synchronise with the renegotiation, such as +// HTTPS. +// +// Renegotiation is not defined in TLS 1.3. +type RenegotiationSupport int + +const ( + // RenegotiateNever disables renegotiation. + RenegotiateNever RenegotiationSupport = iota + + // RenegotiateOnceAsClient allows a remote server to request + // renegotiation once per connection. + RenegotiateOnceAsClient + + // RenegotiateFreelyAsClient allows a remote server to repeatedly + // request renegotiation. + RenegotiateFreelyAsClient +) + +// A Config structure is used to configure a TLS client or server. +// After one has been passed to a TLS function it must not be +// modified. A Config may be reused; the tls package will also not +// modify it. +type Config struct { + // Rand provides the source of entropy for nonces and RSA blinding. + // If Rand is nil, TLS uses the cryptographic random reader in package + // crypto/rand. + // The Reader must be safe for use by multiple goroutines. + Rand io.Reader + + // Time returns the current time as the number of seconds since the epoch. + // If Time is nil, TLS uses time.Now. + Time func() time.Time + + // Certificates contains one or more certificate chains to present to the + // other side of the connection. The first certificate compatible with the + // peer's requirements is selected automatically. + // + // Server configurations must set one of Certificates, GetCertificate or + // GetConfigForClient. Clients doing client-authentication may set either + // Certificates or GetClientCertificate. + // + // Note: if there are multiple Certificates, and they don't have the + // optional field Leaf set, certificate selection will incur a significant + // per-handshake performance cost. + Certificates []Certificate + + // NameToCertificate maps from a certificate name to an element of + // Certificates. Note that a certificate name can be of the form + // '*.example.com' and so doesn't have to be a domain name as such. + // + // Deprecated: NameToCertificate only allows associating a single + // certificate with a given name. Leave this field nil to let the library + // select the first compatible chain from Certificates. + NameToCertificate map[string]*Certificate + + // GetCertificate returns a Certificate based on the given + // ClientHelloInfo. It will only be called if the client supplies SNI + // information or if Certificates is empty. + // + // If GetCertificate is nil or returns nil, then the certificate is + // retrieved from NameToCertificate. If NameToCertificate is nil, the + // best element of Certificates will be used. + GetCertificate func(*ClientHelloInfo) (*Certificate, error) + + // GetClientCertificate, if not nil, is called when a server requests a + // certificate from a client. If set, the contents of Certificates will + // be ignored. + // + // If GetClientCertificate returns an error, the handshake will be + // aborted and that error will be returned. Otherwise + // GetClientCertificate must return a non-nil Certificate. If + // Certificate.Certificate is empty then no certificate will be sent to + // the server. If this is unacceptable to the server then it may abort + // the handshake. + // + // GetClientCertificate may be called multiple times for the same + // connection if renegotiation occurs or if TLS 1.3 is in use. + GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error) + + // GetConfigForClient, if not nil, is called after a ClientHello is + // received from a client. It may return a non-nil Config in order to + // change the Config that will be used to handle this connection. If + // the returned Config is nil, the original Config will be used. The + // Config returned by this callback may not be subsequently modified. + // + // If GetConfigForClient is nil, the Config passed to Server() will be + // used for all connections. + // + // If SessionTicketKey was explicitly set on the returned Config, or if + // SetSessionTicketKeys was called on the returned Config, those keys will + // be used. Otherwise, the original Config keys will be used (and possibly + // rotated if they are automatically managed). + GetConfigForClient func(*ClientHelloInfo) (*Config, error) + + // VerifyPeerCertificate, if not nil, is called after normal + // certificate verification by either a TLS client or server. It + // receives the raw ASN.1 certificates provided by the peer and also + // any verified chains that normal processing found. If it returns a + // non-nil error, the handshake is aborted and that error results. + // + // If normal verification fails then the handshake will abort before + // considering this callback. If normal verification is disabled by + // setting InsecureSkipVerify, or (for a server) when ClientAuth is + // RequestClientCert or RequireAnyClientCert, then this callback will + // be considered but the verifiedChains argument will always be nil. + VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error + + // VerifyConnection, if not nil, is called after normal certificate + // verification and after VerifyPeerCertificate by either a TLS client + // or server. If it returns a non-nil error, the handshake is aborted + // and that error results. + // + // If normal verification fails then the handshake will abort before + // considering this callback. This callback will run for all connections + // regardless of InsecureSkipVerify or ClientAuth settings. + VerifyConnection func(ConnectionState) error + + // RootCAs defines the set of root certificate authorities + // that clients use when verifying server certificates. + // If RootCAs is nil, TLS uses the host's root CA set. + RootCAs *x509.CertPool + + // NextProtos is a list of supported application level protocols, in + // order of preference. If both peers support ALPN, the selected + // protocol will be one from this list, and the connection will fail + // if there is no mutually supported protocol. If NextProtos is empty + // or the peer doesn't support ALPN, the connection will succeed and + // ConnectionState.NegotiatedProtocol will be empty. + NextProtos []string + + // ServerName is used to verify the hostname on the returned + // certificates unless InsecureSkipVerify is given. It is also included + // in the client's handshake to support virtual hosting unless it is + // an IP address. + ServerName string + + // ClientAuth determines the server's policy for + // TLS Client Authentication. The default is NoClientCert. + ClientAuth ClientAuthType + + // ClientCAs defines the set of root certificate authorities + // that servers use if required to verify a client certificate + // by the policy in ClientAuth. + ClientCAs *x509.CertPool + + // InsecureSkipVerify controls whether a client verifies the server's + // certificate chain and host name. If InsecureSkipVerify is true, crypto/tls + // accepts any certificate presented by the server and any host name in that + // certificate. In this mode, TLS is susceptible to machine-in-the-middle + // attacks unless custom verification is used. This should be used only for + // testing or in combination with VerifyConnection or VerifyPeerCertificate. + InsecureSkipVerify bool + + // CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of + // the list is ignored. Note that TLS 1.3 ciphersuites are not configurable. + // + // If CipherSuites is nil, a safe default list is used. The default cipher + // suites might change over time. + CipherSuites []uint16 + + // PreferServerCipherSuites is a legacy field and has no effect. + // + // It used to control whether the server would follow the client's or the + // server's preference. Servers now select the best mutually supported + // cipher suite based on logic that takes into account inferred client + // hardware, server hardware, and security. + // + // Deprected: PreferServerCipherSuites is ignored. + PreferServerCipherSuites bool + + // SessionTicketsDisabled may be set to true to disable session ticket and + // PSK (resumption) support. Note that on clients, session ticket support is + // also disabled if ClientSessionCache is nil. + SessionTicketsDisabled bool + + // SessionTicketKey is used by TLS servers to provide session resumption. + // See RFC 5077 and the PSK mode of RFC 8446. If zero, it will be filled + // with random data before the first server handshake. + // + // Deprecated: if this field is left at zero, session ticket keys will be + // automatically rotated every day and dropped after seven days. For + // customizing the rotation schedule or synchronizing servers that are + // terminating connections for the same host, use SetSessionTicketKeys. + SessionTicketKey [32]byte + + // ClientSessionCache is a cache of ClientSessionState entries for TLS + // session resumption. It is only used by clients. + ClientSessionCache ClientSessionCache + + // MinVersion contains the minimum TLS version that is acceptable. + // If zero, TLS 1.0 is currently taken as the minimum. + MinVersion uint16 + + // MaxVersion contains the maximum TLS version that is acceptable. + // If zero, the maximum version supported by this package is used, + // which is currently TLS 1.3. + MaxVersion uint16 + + // CurvePreferences contains the elliptic curves that will be used in + // an ECDHE handshake, in preference order. If empty, the default will + // be used. The client will use the first preference as the type for + // its key share in TLS 1.3. This may change in the future. + CurvePreferences []CurveID + + // DynamicRecordSizingDisabled disables adaptive sizing of TLS records. + // When true, the largest possible TLS record size is always used. When + // false, the size of TLS records may be adjusted in an attempt to + // improve latency. + DynamicRecordSizingDisabled bool + + // Renegotiation controls what types of renegotiation are supported. + // The default, none, is correct for the vast majority of applications. + Renegotiation RenegotiationSupport + + // KeyLogWriter optionally specifies a destination for TLS master secrets + // in NSS key log format that can be used to allow external programs + // such as Wireshark to decrypt TLS connections. + // See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. + // Use of KeyLogWriter compromises security and should only be + // used for debugging. + KeyLogWriter io.Writer + + // mutex protects sessionTicketKeys and autoSessionTicketKeys. + mutex sync.RWMutex + // sessionTicketKeys contains zero or more ticket keys. If set, it means the + // the keys were set with SessionTicketKey or SetSessionTicketKeys. The + // first key is used for new tickets and any subsequent keys can be used to + // decrypt old tickets. The slice contents are not protected by the mutex + // and are immutable. + sessionTicketKeys []ticketKey + // autoSessionTicketKeys is like sessionTicketKeys but is owned by the + // auto-rotation logic. See Config.ticketKeys. + autoSessionTicketKeys []ticketKey +} + +const ( + // ticketKeyNameLen is the number of bytes of identifier that is prepended to + // an encrypted session ticket in order to identify the key used to encrypt it. + ticketKeyNameLen = 16 + + // ticketKeyLifetime is how long a ticket key remains valid and can be used to + // resume a client connection. + ticketKeyLifetime = 7 * 24 * time.Hour // 7 days + + // ticketKeyRotation is how often the server should rotate the session ticket key + // that is used for new tickets. + ticketKeyRotation = 24 * time.Hour +) + +// ticketKey is the internal representation of a session ticket key. +type ticketKey struct { + // keyName is an opaque byte string that serves to identify the session + // ticket key. It's exposed as plaintext in every session ticket. + keyName [ticketKeyNameLen]byte + aesKey [16]byte + hmacKey [16]byte + // created is the time at which this ticket key was created. See Config.ticketKeys. + created time.Time +} + +// ticketKeyFromBytes converts from the external representation of a session +// ticket key to a ticketKey. Externally, session ticket keys are 32 random +// bytes and this function expands that into sufficient name and key material. +func (c *Config) ticketKeyFromBytes(b [32]byte) (key ticketKey) { + hashed := sha512.Sum512(b[:]) + copy(key.keyName[:], hashed[:ticketKeyNameLen]) + copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16]) + copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32]) + key.created = c.time() + return key +} + +// maxSessionTicketLifetime is the maximum allowed lifetime of a TLS 1.3 session +// ticket, and the lifetime we set for tickets we send. +const maxSessionTicketLifetime = 7 * 24 * time.Hour + +// Clone returns a shallow clone of c or nil if c is nil. It is safe to clone a Config that is +// being used concurrently by a TLS client or server. +func (c *Config) Clone() *Config { + if c == nil { + return nil + } + c.mutex.RLock() + defer c.mutex.RUnlock() + return &Config{ + Rand: c.Rand, + Time: c.Time, + Certificates: c.Certificates, + NameToCertificate: c.NameToCertificate, + GetCertificate: c.GetCertificate, + GetClientCertificate: c.GetClientCertificate, + GetConfigForClient: c.GetConfigForClient, + VerifyPeerCertificate: c.VerifyPeerCertificate, + VerifyConnection: c.VerifyConnection, + RootCAs: c.RootCAs, + NextProtos: c.NextProtos, + ServerName: c.ServerName, + ClientAuth: c.ClientAuth, + ClientCAs: c.ClientCAs, + InsecureSkipVerify: c.InsecureSkipVerify, + CipherSuites: c.CipherSuites, + PreferServerCipherSuites: c.PreferServerCipherSuites, + SessionTicketsDisabled: c.SessionTicketsDisabled, + SessionTicketKey: c.SessionTicketKey, + ClientSessionCache: c.ClientSessionCache, + MinVersion: c.MinVersion, + MaxVersion: c.MaxVersion, + CurvePreferences: c.CurvePreferences, + DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, + Renegotiation: c.Renegotiation, + KeyLogWriter: c.KeyLogWriter, + sessionTicketKeys: c.sessionTicketKeys, + autoSessionTicketKeys: c.autoSessionTicketKeys, + } +} + +// deprecatedSessionTicketKey is set as the prefix of SessionTicketKey if it was +// randomized for backwards compatibility but is not in use. +var deprecatedSessionTicketKey = []byte("DEPRECATED") + +// initLegacySessionTicketKeyRLocked ensures the legacy SessionTicketKey field is +// randomized if empty, and that sessionTicketKeys is populated from it otherwise. +func (c *Config) initLegacySessionTicketKeyRLocked() { + // Don't write if SessionTicketKey is already defined as our deprecated string, + // or if it is defined by the user but sessionTicketKeys is already set. + if c.SessionTicketKey != [32]byte{} && + (bytes.HasPrefix(c.SessionTicketKey[:], deprecatedSessionTicketKey) || len(c.sessionTicketKeys) > 0) { + return + } + + // We need to write some data, so get an exclusive lock and re-check any conditions. + c.mutex.RUnlock() + defer c.mutex.RLock() + c.mutex.Lock() + defer c.mutex.Unlock() + if c.SessionTicketKey == [32]byte{} { + if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil { + panic(fmt.Sprintf("tls: unable to generate random session ticket key: %v", err)) + } + // Write the deprecated prefix at the beginning so we know we created + // it. This key with the DEPRECATED prefix isn't used as an actual + // session ticket key, and is only randomized in case the application + // reuses it for some reason. + copy(c.SessionTicketKey[:], deprecatedSessionTicketKey) + } else if !bytes.HasPrefix(c.SessionTicketKey[:], deprecatedSessionTicketKey) && len(c.sessionTicketKeys) == 0 { + c.sessionTicketKeys = []ticketKey{c.ticketKeyFromBytes(c.SessionTicketKey)} + } + +} + +// ticketKeys returns the ticketKeys for this connection. +// If configForClient has explicitly set keys, those will +// be returned. Otherwise, the keys on c will be used and +// may be rotated if auto-managed. +// During rotation, any expired session ticket keys are deleted from +// c.sessionTicketKeys. If the session ticket key that is currently +// encrypting tickets (ie. the first ticketKey in c.sessionTicketKeys) +// is not fresh, then a new session ticket key will be +// created and prepended to c.sessionTicketKeys. +func (c *Config) ticketKeys(configForClient *Config) []ticketKey { + // If the ConfigForClient callback returned a Config with explicitly set + // keys, use those, otherwise just use the original Config. + if configForClient != nil { + configForClient.mutex.RLock() + if configForClient.SessionTicketsDisabled { + return nil + } + configForClient.initLegacySessionTicketKeyRLocked() + if len(configForClient.sessionTicketKeys) != 0 { + ret := configForClient.sessionTicketKeys + configForClient.mutex.RUnlock() + return ret + } + configForClient.mutex.RUnlock() + } + + c.mutex.RLock() + defer c.mutex.RUnlock() + if c.SessionTicketsDisabled { + return nil + } + c.initLegacySessionTicketKeyRLocked() + if len(c.sessionTicketKeys) != 0 { + return c.sessionTicketKeys + } + // Fast path for the common case where the key is fresh enough. + if len(c.autoSessionTicketKeys) > 0 && c.time().Sub(c.autoSessionTicketKeys[0].created) < ticketKeyRotation { + return c.autoSessionTicketKeys + } + + // autoSessionTicketKeys are managed by auto-rotation. + c.mutex.RUnlock() + defer c.mutex.RLock() + c.mutex.Lock() + defer c.mutex.Unlock() + // Re-check the condition in case it changed since obtaining the new lock. + if len(c.autoSessionTicketKeys) == 0 || c.time().Sub(c.autoSessionTicketKeys[0].created) >= ticketKeyRotation { + var newKey [32]byte + if _, err := io.ReadFull(c.rand(), newKey[:]); err != nil { + panic(fmt.Sprintf("unable to generate random session ticket key: %v", err)) + } + valid := make([]ticketKey, 0, len(c.autoSessionTicketKeys)+1) + valid = append(valid, c.ticketKeyFromBytes(newKey)) + for _, k := range c.autoSessionTicketKeys { + // While rotating the current key, also remove any expired ones. + if c.time().Sub(k.created) < ticketKeyLifetime { + valid = append(valid, k) + } + } + c.autoSessionTicketKeys = valid + } + return c.autoSessionTicketKeys +} + +// SetSessionTicketKeys updates the session ticket keys for a server. +// +// The first key will be used when creating new tickets, while all keys can be +// used for decrypting tickets. It is safe to call this function while the +// server is running in order to rotate the session ticket keys. The function +// will panic if keys is empty. +// +// Calling this function will turn off automatic session ticket key rotation. +// +// If multiple servers are terminating connections for the same host they should +// all have the same session ticket keys. If the session ticket keys leaks, +// previously recorded and future TLS connections using those keys might be +// compromised. +func (c *Config) SetSessionTicketKeys(keys [][32]byte) { + if len(keys) == 0 { + panic("tls: keys must have at least one key") + } + + newKeys := make([]ticketKey, len(keys)) + for i, bytes := range keys { + newKeys[i] = c.ticketKeyFromBytes(bytes) + } + + c.mutex.Lock() + c.sessionTicketKeys = newKeys + c.mutex.Unlock() +} + +func (c *Config) rand() io.Reader { + r := c.Rand + if r == nil { + return rand.Reader + } + return r +} + +func (c *Config) time() time.Time { + t := c.Time + if t == nil { + t = time.Now + } + return t() +} + +func (c *Config) cipherSuites() []uint16 { + if c.CipherSuites != nil { + return c.CipherSuites + } + return defaultCipherSuites +} + +var supportedVersions = []uint16{ + VersionTLS13, + VersionTLS12, + VersionTLS11, + VersionTLS10, +} + +func (c *Config) supportedVersions() []uint16 { + versions := make([]uint16, 0, len(supportedVersions)) + for _, v := range supportedVersions { + if c != nil && c.MinVersion != 0 && v < c.MinVersion { + continue + } + if c != nil && c.MaxVersion != 0 && v > c.MaxVersion { + continue + } + versions = append(versions, v) + } + return versions +} + +func (c *Config) maxSupportedVersion() uint16 { + supportedVersions := c.supportedVersions() + if len(supportedVersions) == 0 { + return 0 + } + return supportedVersions[0] +} + +// supportedVersionsFromMax returns a list of supported versions derived from a +// legacy maximum version value. Note that only versions supported by this +// library are returned. Any newer peer will use supportedVersions anyway. +func supportedVersionsFromMax(maxVersion uint16) []uint16 { + versions := make([]uint16, 0, len(supportedVersions)) + for _, v := range supportedVersions { + if v > maxVersion { + continue + } + versions = append(versions, v) + } + return versions +} + +var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521} + +func (c *Config) curvePreferences() []CurveID { + if c == nil || len(c.CurvePreferences) == 0 { + return defaultCurvePreferences + } + return c.CurvePreferences +} + +func (c *Config) supportsCurve(curve CurveID) bool { + for _, cc := range c.curvePreferences() { + if cc == curve { + return true + } + } + return false +} + +// mutualVersion returns the protocol version to use given the advertised +// versions of the peer. Priority is given to the peer preference order. +func (c *Config) mutualVersion(peerVersions []uint16) (uint16, bool) { + supportedVersions := c.supportedVersions() + for _, peerVersion := range peerVersions { + for _, v := range supportedVersions { + if v == peerVersion { + return v, true + } + } + } + return 0, false +} + +var errNoCertificates = errors.New("tls: no certificates configured") + +// getCertificate returns the best certificate for the given ClientHelloInfo, +// defaulting to the first element of c.Certificates. +func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) { + if c.GetCertificate != nil && + (len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) { + cert, err := c.GetCertificate(clientHello) + if cert != nil || err != nil { + return cert, err + } + } + + if len(c.Certificates) == 0 { + return nil, errNoCertificates + } + + if len(c.Certificates) == 1 { + // There's only one choice, so no point doing any work. + return &c.Certificates[0], nil + } + + if c.NameToCertificate != nil { + name := strings.ToLower(clientHello.ServerName) + if cert, ok := c.NameToCertificate[name]; ok { + return cert, nil + } + if len(name) > 0 { + labels := strings.Split(name, ".") + labels[0] = "*" + wildcardName := strings.Join(labels, ".") + if cert, ok := c.NameToCertificate[wildcardName]; ok { + return cert, nil + } + } + } + + for _, cert := range c.Certificates { + if err := clientHello.SupportsCertificate(&cert); err == nil { + return &cert, nil + } + } + + // If nothing matches, return the first certificate. + return &c.Certificates[0], nil +} + +// SupportsCertificate returns nil if the provided certificate is supported by +// the client that sent the ClientHello. Otherwise, it returns an error +// describing the reason for the incompatibility. +// +// If this ClientHelloInfo was passed to a GetConfigForClient or GetCertificate +// callback, this method will take into account the associated Config. Note that +// if GetConfigForClient returns a different Config, the change can't be +// accounted for by this method. +// +// This function will call x509.ParseCertificate unless c.Leaf is set, which can +// incur a significant performance cost. +func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error { + // Note we don't currently support certificate_authorities nor + // signature_algorithms_cert, and don't check the algorithms of the + // signatures on the chain (which anyway are a SHOULD, see RFC 8446, + // Section 4.4.2.2). + + config := chi.config + if config == nil { + config = &Config{} + } + vers, ok := config.mutualVersion(chi.SupportedVersions) + if !ok { + return errors.New("no mutually supported protocol versions") + } + + // If the client specified the name they are trying to connect to, the + // certificate needs to be valid for it. + if chi.ServerName != "" { + x509Cert, err := c.leaf() + if err != nil { + return fmt.Errorf("failed to parse certificate: %w", err) + } + if err := x509Cert.VerifyHostname(chi.ServerName); err != nil { + return fmt.Errorf("certificate is not valid for requested server name: %w", err) + } + } + + // supportsRSAFallback returns nil if the certificate and connection support + // the static RSA key exchange, and unsupported otherwise. The logic for + // supporting static RSA is completely disjoint from the logic for + // supporting signed key exchanges, so we just check it as a fallback. + supportsRSAFallback := func(unsupported error) error { + // TLS 1.3 dropped support for the static RSA key exchange. + if vers == VersionTLS13 { + return unsupported + } + // The static RSA key exchange works by decrypting a challenge with the + // RSA private key, not by signing, so check the PrivateKey implements + // crypto.Decrypter, like *rsa.PrivateKey does. + if priv, ok := c.PrivateKey.(crypto.Decrypter); ok { + if _, ok := priv.Public().(*rsa.PublicKey); !ok { + return unsupported + } + } else { + return unsupported + } + // Finally, there needs to be a mutual cipher suite that uses the static + // RSA key exchange instead of ECDHE. + rsaCipherSuite := selectCipherSuite(chi.CipherSuites, config.cipherSuites(), func(c *cipherSuite) bool { + if c.flags&suiteECDHE != 0 { + return false + } + if vers < VersionTLS12 && c.flags&suiteTLS12 != 0 { + return false + } + return true + }) + if rsaCipherSuite == nil { + return unsupported + } + return nil + } + + // If the client sent the signature_algorithms extension, ensure it supports + // schemes we can use with this certificate and TLS version. + if len(chi.SignatureSchemes) > 0 { + if _, err := selectSignatureScheme(vers, c, chi.SignatureSchemes); err != nil { + return supportsRSAFallback(err) + } + } + + // In TLS 1.3 we are done because supported_groups is only relevant to the + // ECDHE computation, point format negotiation is removed, cipher suites are + // only relevant to the AEAD choice, and static RSA does not exist. + if vers == VersionTLS13 { + return nil + } + + // The only signed key exchange we support is ECDHE. + if !supportsECDHE(config, chi.SupportedCurves, chi.SupportedPoints) { + return supportsRSAFallback(errors.New("client doesn't support ECDHE, can only use legacy RSA key exchange")) + } + + var ecdsaCipherSuite bool + if priv, ok := c.PrivateKey.(crypto.Signer); ok { + switch pub := priv.Public().(type) { + case *ecdsa.PublicKey: + var curve CurveID + switch pub.Curve { + case elliptic.P256(): + curve = CurveP256 + case elliptic.P384(): + curve = CurveP384 + case elliptic.P521(): + curve = CurveP521 + default: + return supportsRSAFallback(unsupportedCertificateError(c)) + } + var curveOk bool + for _, c := range chi.SupportedCurves { + if c == curve && config.supportsCurve(c) { + curveOk = true + break + } + } + if !curveOk { + return errors.New("client doesn't support certificate curve") + } + ecdsaCipherSuite = true + case ed25519.PublicKey: + if vers < VersionTLS12 || len(chi.SignatureSchemes) == 0 { + return errors.New("connection doesn't support Ed25519") + } + ecdsaCipherSuite = true + case *rsa.PublicKey: + default: + return supportsRSAFallback(unsupportedCertificateError(c)) + } + } else { + return supportsRSAFallback(unsupportedCertificateError(c)) + } + + // Make sure that there is a mutually supported cipher suite that works with + // this certificate. Cipher suite selection will then apply the logic in + // reverse to pick it. See also serverHandshakeState.cipherSuiteOk. + cipherSuite := selectCipherSuite(chi.CipherSuites, config.cipherSuites(), func(c *cipherSuite) bool { + if c.flags&suiteECDHE == 0 { + return false + } + if c.flags&suiteECSign != 0 { + if !ecdsaCipherSuite { + return false + } + } else { + if ecdsaCipherSuite { + return false + } + } + if vers < VersionTLS12 && c.flags&suiteTLS12 != 0 { + return false + } + return true + }) + if cipherSuite == nil { + return supportsRSAFallback(errors.New("client doesn't support any cipher suites compatible with the certificate")) + } + + return nil +} + +// SupportsCertificate returns nil if the provided certificate is supported by +// the server that sent the CertificateRequest. Otherwise, it returns an error +// describing the reason for the incompatibility. +func (cri *CertificateRequestInfo) SupportsCertificate(c *Certificate) error { + if _, err := selectSignatureScheme(cri.Version, c, cri.SignatureSchemes); err != nil { + return err + } + + if len(cri.AcceptableCAs) == 0 { + return nil + } + + for j, cert := range c.Certificate { + x509Cert := c.Leaf + // Parse the certificate if this isn't the leaf node, or if + // chain.Leaf was nil. + if j != 0 || x509Cert == nil { + var err error + if x509Cert, err = x509.ParseCertificate(cert); err != nil { + return fmt.Errorf("failed to parse certificate #%d in the chain: %w", j, err) + } + } + + for _, ca := range cri.AcceptableCAs { + if bytes.Equal(x509Cert.RawIssuer, ca) { + return nil + } + } + } + return errors.New("chain is not signed by an acceptable CA") +} + +// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate +// from the CommonName and SubjectAlternateName fields of each of the leaf +// certificates. +// +// Deprecated: NameToCertificate only allows associating a single certificate +// with a given name. Leave that field nil to let the library select the first +// compatible chain from Certificates. +func (c *Config) BuildNameToCertificate() { + c.NameToCertificate = make(map[string]*Certificate) + for i := range c.Certificates { + cert := &c.Certificates[i] + x509Cert, err := cert.leaf() + if err != nil { + continue + } + // If SANs are *not* present, some clients will consider the certificate + // valid for the name in the Common Name. + if x509Cert.Subject.CommonName != "" && len(x509Cert.DNSNames) == 0 { + c.NameToCertificate[x509Cert.Subject.CommonName] = cert + } + for _, san := range x509Cert.DNSNames { + c.NameToCertificate[san] = cert + } + } +} + +const ( + keyLogLabelTLS12 = "CLIENT_RANDOM" + keyLogLabelClientHandshake = "CLIENT_HANDSHAKE_TRAFFIC_SECRET" + keyLogLabelServerHandshake = "SERVER_HANDSHAKE_TRAFFIC_SECRET" + keyLogLabelClientTraffic = "CLIENT_TRAFFIC_SECRET_0" + keyLogLabelServerTraffic = "SERVER_TRAFFIC_SECRET_0" +) + +func (c *Config) writeKeyLog(label string, clientRandom, secret []byte) error { + if c.KeyLogWriter == nil { + return nil + } + + logLine := []byte(fmt.Sprintf("%s %x %x\n", label, clientRandom, secret)) + + writerMutex.Lock() + _, err := c.KeyLogWriter.Write(logLine) + writerMutex.Unlock() + + return err +} + +// writerMutex protects all KeyLogWriters globally. It is rarely enabled, +// and is only for debugging, so a global mutex saves space. +var writerMutex sync.Mutex + +// A Certificate is a chain of one or more certificates, leaf first. +type Certificate struct { + Certificate [][]byte + // PrivateKey contains the private key corresponding to the public key in + // Leaf. This must implement crypto.Signer with an RSA, ECDSA or Ed25519 PublicKey. + // For a server up to TLS 1.2, it can also implement crypto.Decrypter with + // an RSA PublicKey. + PrivateKey crypto.PrivateKey + // SupportedSignatureAlgorithms is an optional list restricting what + // signature algorithms the PrivateKey can be used for. + SupportedSignatureAlgorithms []SignatureScheme + // OCSPStaple contains an optional OCSP response which will be served + // to clients that request it. + OCSPStaple []byte + // SignedCertificateTimestamps contains an optional list of Signed + // Certificate Timestamps which will be served to clients that request it. + SignedCertificateTimestamps [][]byte + // Leaf is the parsed form of the leaf certificate, which may be initialized + // using x509.ParseCertificate to reduce per-handshake processing. If nil, + // the leaf certificate will be parsed as needed. + Leaf *x509.Certificate +} + +// leaf returns the parsed leaf certificate, either from c.Leaf or by parsing +// the corresponding c.Certificate[0]. +func (c *Certificate) leaf() (*x509.Certificate, error) { + if c.Leaf != nil { + return c.Leaf, nil + } + return x509.ParseCertificate(c.Certificate[0]) +} + +type handshakeMessage interface { + marshal() []byte + unmarshal([]byte) bool +} + +// lruSessionCache is a ClientSessionCache implementation that uses an LRU +// caching strategy. +type lruSessionCache struct { + sync.Mutex + + m map[string]*list.Element + q *list.List + capacity int +} + +type lruSessionCacheEntry struct { + sessionKey string + state *ClientSessionState +} + +// NewLRUClientSessionCache returns a ClientSessionCache with the given +// capacity that uses an LRU strategy. If capacity is < 1, a default capacity +// is used instead. +func NewLRUClientSessionCache(capacity int) ClientSessionCache { + const defaultSessionCacheCapacity = 64 + + if capacity < 1 { + capacity = defaultSessionCacheCapacity + } + return &lruSessionCache{ + m: make(map[string]*list.Element), + q: list.New(), + capacity: capacity, + } +} + +// Put adds the provided (sessionKey, cs) pair to the cache. If cs is nil, the entry +// corresponding to sessionKey is removed from the cache instead. +func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) { + c.Lock() + defer c.Unlock() + + if elem, ok := c.m[sessionKey]; ok { + if cs == nil { + c.q.Remove(elem) + delete(c.m, sessionKey) + } else { + entry := elem.Value.(*lruSessionCacheEntry) + entry.state = cs + c.q.MoveToFront(elem) + } + return + } + + if c.q.Len() < c.capacity { + entry := &lruSessionCacheEntry{sessionKey, cs} + c.m[sessionKey] = c.q.PushFront(entry) + return + } + + elem := c.q.Back() + entry := elem.Value.(*lruSessionCacheEntry) + delete(c.m, entry.sessionKey) + entry.sessionKey = sessionKey + entry.state = cs + c.q.MoveToFront(elem) + c.m[sessionKey] = elem +} + +// Get returns the ClientSessionState value associated with a given key. It +// returns (nil, false) if no value is found. +func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) { + c.Lock() + defer c.Unlock() + + if elem, ok := c.m[sessionKey]; ok { + c.q.MoveToFront(elem) + return elem.Value.(*lruSessionCacheEntry).state, true + } + return nil, false +} + +var emptyConfig Config + +func defaultConfig() *Config { + return &emptyConfig +} + +func unexpectedMessageError(wanted, got interface{}) error { + return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) +} + +func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlgorithms []SignatureScheme) bool { + for _, s := range supportedSignatureAlgorithms { + if s == sigAlg { + return true + } + } + return false +} diff --git a/src/crypto/tls/common_string.go b/src/crypto/tls/common_string.go new file mode 100644 index 0000000..2381088 --- /dev/null +++ b/src/crypto/tls/common_string.go @@ -0,0 +1,116 @@ +// Code generated by "stringer -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go"; DO NOT EDIT. + +package tls + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[PKCS1WithSHA256-1025] + _ = x[PKCS1WithSHA384-1281] + _ = x[PKCS1WithSHA512-1537] + _ = x[PSSWithSHA256-2052] + _ = x[PSSWithSHA384-2053] + _ = x[PSSWithSHA512-2054] + _ = x[ECDSAWithP256AndSHA256-1027] + _ = x[ECDSAWithP384AndSHA384-1283] + _ = x[ECDSAWithP521AndSHA512-1539] + _ = x[Ed25519-2055] + _ = x[PKCS1WithSHA1-513] + _ = x[ECDSAWithSHA1-515] +} + +const ( + _SignatureScheme_name_0 = "PKCS1WithSHA1" + _SignatureScheme_name_1 = "ECDSAWithSHA1" + _SignatureScheme_name_2 = "PKCS1WithSHA256" + _SignatureScheme_name_3 = "ECDSAWithP256AndSHA256" + _SignatureScheme_name_4 = "PKCS1WithSHA384" + _SignatureScheme_name_5 = "ECDSAWithP384AndSHA384" + _SignatureScheme_name_6 = "PKCS1WithSHA512" + _SignatureScheme_name_7 = "ECDSAWithP521AndSHA512" + _SignatureScheme_name_8 = "PSSWithSHA256PSSWithSHA384PSSWithSHA512Ed25519" +) + +var ( + _SignatureScheme_index_8 = [...]uint8{0, 13, 26, 39, 46} +) + +func (i SignatureScheme) String() string { + switch { + case i == 513: + return _SignatureScheme_name_0 + case i == 515: + return _SignatureScheme_name_1 + case i == 1025: + return _SignatureScheme_name_2 + case i == 1027: + return _SignatureScheme_name_3 + case i == 1281: + return _SignatureScheme_name_4 + case i == 1283: + return _SignatureScheme_name_5 + case i == 1537: + return _SignatureScheme_name_6 + case i == 1539: + return _SignatureScheme_name_7 + case 2052 <= i && i <= 2055: + i -= 2052 + return _SignatureScheme_name_8[_SignatureScheme_index_8[i]:_SignatureScheme_index_8[i+1]] + default: + return "SignatureScheme(" + strconv.FormatInt(int64(i), 10) + ")" + } +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[CurveP256-23] + _ = x[CurveP384-24] + _ = x[CurveP521-25] + _ = x[X25519-29] +} + +const ( + _CurveID_name_0 = "CurveP256CurveP384CurveP521" + _CurveID_name_1 = "X25519" +) + +var ( + _CurveID_index_0 = [...]uint8{0, 9, 18, 27} +) + +func (i CurveID) String() string { + switch { + case 23 <= i && i <= 25: + i -= 23 + return _CurveID_name_0[_CurveID_index_0[i]:_CurveID_index_0[i+1]] + case i == 29: + return _CurveID_name_1 + default: + return "CurveID(" + strconv.FormatInt(int64(i), 10) + ")" + } +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NoClientCert-0] + _ = x[RequestClientCert-1] + _ = x[RequireAnyClientCert-2] + _ = x[VerifyClientCertIfGiven-3] + _ = x[RequireAndVerifyClientCert-4] +} + +const _ClientAuthType_name = "NoClientCertRequestClientCertRequireAnyClientCertVerifyClientCertIfGivenRequireAndVerifyClientCert" + +var _ClientAuthType_index = [...]uint8{0, 12, 29, 49, 72, 98} + +func (i ClientAuthType) String() string { + if i < 0 || i >= ClientAuthType(len(_ClientAuthType_index)-1) { + return "ClientAuthType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ClientAuthType_name[_ClientAuthType_index[i]:_ClientAuthType_index[i+1]] +} diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go new file mode 100644 index 0000000..d0a2550 --- /dev/null +++ b/src/crypto/tls/conn.go @@ -0,0 +1,1536 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TLS low level connection and record layer + +package tls + +import ( + "bytes" + "context" + "crypto/cipher" + "crypto/subtle" + "crypto/x509" + "errors" + "fmt" + "hash" + "io" + "net" + "sync" + "sync/atomic" + "time" +) + +// A Conn represents a secured connection. +// It implements the net.Conn interface. +type Conn struct { + // constant + conn net.Conn + isClient bool + handshakeFn func(context.Context) error // (*Conn).clientHandshake or serverHandshake + + // handshakeStatus is 1 if the connection is currently transferring + // application data (i.e. is not currently processing a handshake). + // handshakeStatus == 1 implies handshakeErr == nil. + // This field is only to be accessed with sync/atomic. + handshakeStatus uint32 + // constant after handshake; protected by handshakeMutex + handshakeMutex sync.Mutex + handshakeErr error // error resulting from handshake + vers uint16 // TLS version + haveVers bool // version has been negotiated + config *Config // configuration passed to constructor + // handshakes counts the number of handshakes performed on the + // connection so far. If renegotiation is disabled then this is either + // zero or one. + handshakes int + didResume bool // whether this connection was a session resumption + cipherSuite uint16 + ocspResponse []byte // stapled OCSP response + scts [][]byte // signed certificate timestamps from server + peerCertificates []*x509.Certificate + // verifiedChains contains the certificate chains that we built, as + // opposed to the ones presented by the server. + verifiedChains [][]*x509.Certificate + // serverName contains the server name indicated by the client, if any. + serverName string + // secureRenegotiation is true if the server echoed the secure + // renegotiation extension. (This is meaningless as a server because + // renegotiation is not supported in that case.) + secureRenegotiation bool + // ekm is a closure for exporting keying material. + ekm func(label string, context []byte, length int) ([]byte, error) + // resumptionSecret is the resumption_master_secret for handling + // NewSessionTicket messages. nil if config.SessionTicketsDisabled. + resumptionSecret []byte + + // ticketKeys is the set of active session ticket keys for this + // connection. The first one is used to encrypt new tickets and + // all are tried to decrypt tickets. + ticketKeys []ticketKey + + // clientFinishedIsFirst is true if the client sent the first Finished + // message during the most recent handshake. This is recorded because + // the first transmitted Finished message is the tls-unique + // channel-binding value. + clientFinishedIsFirst bool + + // closeNotifyErr is any error from sending the alertCloseNotify record. + closeNotifyErr error + // closeNotifySent is true if the Conn attempted to send an + // alertCloseNotify record. + closeNotifySent bool + + // clientFinished and serverFinished contain the Finished message sent + // by the client or server in the most recent handshake. This is + // retained to support the renegotiation extension and tls-unique + // channel-binding. + clientFinished [12]byte + serverFinished [12]byte + + // clientProtocol is the negotiated ALPN protocol. + clientProtocol string + + // input/output + in, out halfConn + rawInput bytes.Buffer // raw input, starting with a record header + input bytes.Reader // application data waiting to be read, from rawInput.Next + hand bytes.Buffer // handshake data waiting to be read + buffering bool // whether records are buffered in sendBuf + sendBuf []byte // a buffer of records waiting to be sent + + // bytesSent counts the bytes of application data sent. + // packetsSent counts packets. + bytesSent int64 + packetsSent int64 + + // retryCount counts the number of consecutive non-advancing records + // received by Conn.readRecord. That is, records that neither advance the + // handshake, nor deliver application data. Protected by in.Mutex. + retryCount int + + // activeCall is an atomic int32; the low bit is whether Close has + // been called. the rest of the bits are the number of goroutines + // in Conn.Write. + activeCall int32 + + tmp [16]byte +} + +// Access to net.Conn methods. +// Cannot just embed net.Conn because that would +// export the struct field too. + +// LocalAddr returns the local network address. +func (c *Conn) LocalAddr() net.Addr { + return c.conn.LocalAddr() +} + +// RemoteAddr returns the remote network address. +func (c *Conn) RemoteAddr() net.Addr { + return c.conn.RemoteAddr() +} + +// SetDeadline sets the read and write deadlines associated with the connection. +// A zero value for t means Read and Write will not time out. +// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. +func (c *Conn) SetDeadline(t time.Time) error { + return c.conn.SetDeadline(t) +} + +// SetReadDeadline sets the read deadline on the underlying connection. +// A zero value for t means Read will not time out. +func (c *Conn) SetReadDeadline(t time.Time) error { + return c.conn.SetReadDeadline(t) +} + +// SetWriteDeadline sets the write deadline on the underlying connection. +// A zero value for t means Write will not time out. +// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. +func (c *Conn) SetWriteDeadline(t time.Time) error { + return c.conn.SetWriteDeadline(t) +} + +// A halfConn represents one direction of the record layer +// connection, either sending or receiving. +type halfConn struct { + sync.Mutex + + err error // first permanent error + version uint16 // protocol version + cipher interface{} // cipher algorithm + mac hash.Hash + seq [8]byte // 64-bit sequence number + + scratchBuf [13]byte // to avoid allocs; interface method args escape + + nextCipher interface{} // next encryption state + nextMac hash.Hash // next MAC algorithm + + trafficSecret []byte // current TLS 1.3 traffic secret +} + +type permanentError struct { + err net.Error +} + +func (e *permanentError) Error() string { return e.err.Error() } +func (e *permanentError) Unwrap() error { return e.err } +func (e *permanentError) Timeout() bool { return e.err.Timeout() } +func (e *permanentError) Temporary() bool { return false } + +func (hc *halfConn) setErrorLocked(err error) error { + if e, ok := err.(net.Error); ok { + hc.err = &permanentError{err: e} + } else { + hc.err = err + } + return hc.err +} + +// prepareCipherSpec sets the encryption and MAC states +// that a subsequent changeCipherSpec will use. +func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac hash.Hash) { + hc.version = version + hc.nextCipher = cipher + hc.nextMac = mac +} + +// changeCipherSpec changes the encryption and MAC states +// to the ones previously passed to prepareCipherSpec. +func (hc *halfConn) changeCipherSpec() error { + if hc.nextCipher == nil || hc.version == VersionTLS13 { + return alertInternalError + } + hc.cipher = hc.nextCipher + hc.mac = hc.nextMac + hc.nextCipher = nil + hc.nextMac = nil + for i := range hc.seq { + hc.seq[i] = 0 + } + return nil +} + +func (hc *halfConn) setTrafficSecret(suite *cipherSuiteTLS13, secret []byte) { + hc.trafficSecret = secret + key, iv := suite.trafficKey(secret) + hc.cipher = suite.aead(key, iv) + for i := range hc.seq { + hc.seq[i] = 0 + } +} + +// incSeq increments the sequence number. +func (hc *halfConn) incSeq() { + for i := 7; i >= 0; i-- { + hc.seq[i]++ + if hc.seq[i] != 0 { + return + } + } + + // Not allowed to let sequence number wrap. + // Instead, must renegotiate before it does. + // Not likely enough to bother. + panic("TLS: sequence number wraparound") +} + +// explicitNonceLen returns the number of bytes of explicit nonce or IV included +// in each record. Explicit nonces are present only in CBC modes after TLS 1.0 +// and in certain AEAD modes in TLS 1.2. +func (hc *halfConn) explicitNonceLen() int { + if hc.cipher == nil { + return 0 + } + + switch c := hc.cipher.(type) { + case cipher.Stream: + return 0 + case aead: + return c.explicitNonceLen() + case cbcMode: + // TLS 1.1 introduced a per-record explicit IV to fix the BEAST attack. + if hc.version >= VersionTLS11 { + return c.BlockSize() + } + return 0 + default: + panic("unknown cipher type") + } +} + +// extractPadding returns, in constant time, the length of the padding to remove +// from the end of payload. It also returns a byte which is equal to 255 if the +// padding was valid and 0 otherwise. See RFC 2246, Section 6.2.3.2. +func extractPadding(payload []byte) (toRemove int, good byte) { + if len(payload) < 1 { + return 0, 0 + } + + paddingLen := payload[len(payload)-1] + t := uint(len(payload)-1) - uint(paddingLen) + // if len(payload) >= (paddingLen - 1) then the MSB of t is zero + good = byte(int32(^t) >> 31) + + // The maximum possible padding length plus the actual length field + toCheck := 256 + // The length of the padded data is public, so we can use an if here + if toCheck > len(payload) { + toCheck = len(payload) + } + + for i := 0; i < toCheck; i++ { + t := uint(paddingLen) - uint(i) + // if i <= paddingLen then the MSB of t is zero + mask := byte(int32(^t) >> 31) + b := payload[len(payload)-1-i] + good &^= mask&paddingLen ^ mask&b + } + + // We AND together the bits of good and replicate the result across + // all the bits. + good &= good << 4 + good &= good << 2 + good &= good << 1 + good = uint8(int8(good) >> 7) + + // Zero the padding length on error. This ensures any unchecked bytes + // are included in the MAC. Otherwise, an attacker that could + // distinguish MAC failures from padding failures could mount an attack + // similar to POODLE in SSL 3.0: given a good ciphertext that uses a + // full block's worth of padding, replace the final block with another + // block. If the MAC check passed but the padding check failed, the + // last byte of that block decrypted to the block size. + // + // See also macAndPaddingGood logic below. + paddingLen &= good + + toRemove = int(paddingLen) + 1 + return +} + +func roundUp(a, b int) int { + return a + (b-a%b)%b +} + +// cbcMode is an interface for block ciphers using cipher block chaining. +type cbcMode interface { + cipher.BlockMode + SetIV([]byte) +} + +// decrypt authenticates and decrypts the record if protection is active at +// this stage. The returned plaintext might overlap with the input. +func (hc *halfConn) decrypt(record []byte) ([]byte, recordType, error) { + var plaintext []byte + typ := recordType(record[0]) + payload := record[recordHeaderLen:] + + // In TLS 1.3, change_cipher_spec messages are to be ignored without being + // decrypted. See RFC 8446, Appendix D.4. + if hc.version == VersionTLS13 && typ == recordTypeChangeCipherSpec { + return payload, typ, nil + } + + paddingGood := byte(255) + paddingLen := 0 + + explicitNonceLen := hc.explicitNonceLen() + + if hc.cipher != nil { + switch c := hc.cipher.(type) { + case cipher.Stream: + c.XORKeyStream(payload, payload) + case aead: + if len(payload) < explicitNonceLen { + return nil, 0, alertBadRecordMAC + } + nonce := payload[:explicitNonceLen] + if len(nonce) == 0 { + nonce = hc.seq[:] + } + payload = payload[explicitNonceLen:] + + var additionalData []byte + if hc.version == VersionTLS13 { + additionalData = record[:recordHeaderLen] + } else { + additionalData = append(hc.scratchBuf[:0], hc.seq[:]...) + additionalData = append(additionalData, record[:3]...) + n := len(payload) - c.Overhead() + additionalData = append(additionalData, byte(n>>8), byte(n)) + } + + var err error + plaintext, err = c.Open(payload[:0], nonce, payload, additionalData) + if err != nil { + return nil, 0, alertBadRecordMAC + } + case cbcMode: + blockSize := c.BlockSize() + minPayload := explicitNonceLen + roundUp(hc.mac.Size()+1, blockSize) + if len(payload)%blockSize != 0 || len(payload) < minPayload { + return nil, 0, alertBadRecordMAC + } + + if explicitNonceLen > 0 { + c.SetIV(payload[:explicitNonceLen]) + payload = payload[explicitNonceLen:] + } + c.CryptBlocks(payload, payload) + + // In a limited attempt to protect against CBC padding oracles like + // Lucky13, the data past paddingLen (which is secret) is passed to + // the MAC function as extra data, to be fed into the HMAC after + // computing the digest. This makes the MAC roughly constant time as + // long as the digest computation is constant time and does not + // affect the subsequent write, modulo cache effects. + paddingLen, paddingGood = extractPadding(payload) + default: + panic("unknown cipher type") + } + + if hc.version == VersionTLS13 { + if typ != recordTypeApplicationData { + return nil, 0, alertUnexpectedMessage + } + if len(plaintext) > maxPlaintext+1 { + return nil, 0, alertRecordOverflow + } + // Remove padding and find the ContentType scanning from the end. + for i := len(plaintext) - 1; i >= 0; i-- { + if plaintext[i] != 0 { + typ = recordType(plaintext[i]) + plaintext = plaintext[:i] + break + } + if i == 0 { + return nil, 0, alertUnexpectedMessage + } + } + } + } else { + plaintext = payload + } + + if hc.mac != nil { + macSize := hc.mac.Size() + if len(payload) < macSize { + return nil, 0, alertBadRecordMAC + } + + n := len(payload) - macSize - paddingLen + n = subtle.ConstantTimeSelect(int(uint32(n)>>31), 0, n) // if n < 0 { n = 0 } + record[3] = byte(n >> 8) + record[4] = byte(n) + remoteMAC := payload[n : n+macSize] + localMAC := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload[:n], payload[n+macSize:]) + + // This is equivalent to checking the MACs and paddingGood + // separately, but in constant-time to prevent distinguishing + // padding failures from MAC failures. Depending on what value + // of paddingLen was returned on bad padding, distinguishing + // bad MAC from bad padding can lead to an attack. + // + // See also the logic at the end of extractPadding. + macAndPaddingGood := subtle.ConstantTimeCompare(localMAC, remoteMAC) & int(paddingGood) + if macAndPaddingGood != 1 { + return nil, 0, alertBadRecordMAC + } + + plaintext = payload[:n] + } + + hc.incSeq() + return plaintext, typ, nil +} + +// sliceForAppend extends the input slice by n bytes. head is the full extended +// slice, while tail is the appended part. If the original slice has sufficient +// capacity no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +// encrypt encrypts payload, adding the appropriate nonce and/or MAC, and +// appends it to record, which must already contain the record header. +func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, error) { + if hc.cipher == nil { + return append(record, payload...), nil + } + + var explicitNonce []byte + if explicitNonceLen := hc.explicitNonceLen(); explicitNonceLen > 0 { + record, explicitNonce = sliceForAppend(record, explicitNonceLen) + if _, isCBC := hc.cipher.(cbcMode); !isCBC && explicitNonceLen < 16 { + // The AES-GCM construction in TLS has an explicit nonce so that the + // nonce can be random. However, the nonce is only 8 bytes which is + // too small for a secure, random nonce. Therefore we use the + // sequence number as the nonce. The 3DES-CBC construction also has + // an 8 bytes nonce but its nonces must be unpredictable (see RFC + // 5246, Appendix F.3), forcing us to use randomness. That's not + // 3DES' biggest problem anyway because the birthday bound on block + // collision is reached first due to its similarly small block size + // (see the Sweet32 attack). + copy(explicitNonce, hc.seq[:]) + } else { + if _, err := io.ReadFull(rand, explicitNonce); err != nil { + return nil, err + } + } + } + + var dst []byte + switch c := hc.cipher.(type) { + case cipher.Stream: + mac := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload, nil) + record, dst = sliceForAppend(record, len(payload)+len(mac)) + c.XORKeyStream(dst[:len(payload)], payload) + c.XORKeyStream(dst[len(payload):], mac) + case aead: + nonce := explicitNonce + if len(nonce) == 0 { + nonce = hc.seq[:] + } + + if hc.version == VersionTLS13 { + record = append(record, payload...) + + // Encrypt the actual ContentType and replace the plaintext one. + record = append(record, record[0]) + record[0] = byte(recordTypeApplicationData) + + n := len(payload) + 1 + c.Overhead() + record[3] = byte(n >> 8) + record[4] = byte(n) + + record = c.Seal(record[:recordHeaderLen], + nonce, record[recordHeaderLen:], record[:recordHeaderLen]) + } else { + additionalData := append(hc.scratchBuf[:0], hc.seq[:]...) + additionalData = append(additionalData, record[:recordHeaderLen]...) + record = c.Seal(record, nonce, payload, additionalData) + } + case cbcMode: + mac := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload, nil) + blockSize := c.BlockSize() + plaintextLen := len(payload) + len(mac) + paddingLen := blockSize - plaintextLen%blockSize + record, dst = sliceForAppend(record, plaintextLen+paddingLen) + copy(dst, payload) + copy(dst[len(payload):], mac) + for i := plaintextLen; i < len(dst); i++ { + dst[i] = byte(paddingLen - 1) + } + if len(explicitNonce) > 0 { + c.SetIV(explicitNonce) + } + c.CryptBlocks(dst, dst) + default: + panic("unknown cipher type") + } + + // Update length to include nonce, MAC and any block padding needed. + n := len(record) - recordHeaderLen + record[3] = byte(n >> 8) + record[4] = byte(n) + hc.incSeq() + + return record, nil +} + +// RecordHeaderError is returned when a TLS record header is invalid. +type RecordHeaderError struct { + // Msg contains a human readable string that describes the error. + Msg string + // RecordHeader contains the five bytes of TLS record header that + // triggered the error. + RecordHeader [5]byte + // Conn provides the underlying net.Conn in the case that a client + // sent an initial handshake that didn't look like TLS. + // It is nil if there's already been a handshake or a TLS alert has + // been written to the connection. + Conn net.Conn +} + +func (e RecordHeaderError) Error() string { return "tls: " + e.Msg } + +func (c *Conn) newRecordHeaderError(conn net.Conn, msg string) (err RecordHeaderError) { + err.Msg = msg + err.Conn = conn + copy(err.RecordHeader[:], c.rawInput.Bytes()) + return err +} + +func (c *Conn) readRecord() error { + return c.readRecordOrCCS(false) +} + +func (c *Conn) readChangeCipherSpec() error { + return c.readRecordOrCCS(true) +} + +// readRecordOrCCS reads one or more TLS records from the connection and +// updates the record layer state. Some invariants: +// * c.in must be locked +// * c.input must be empty +// During the handshake one and only one of the following will happen: +// - c.hand grows +// - c.in.changeCipherSpec is called +// - an error is returned +// After the handshake one and only one of the following will happen: +// - c.hand grows +// - c.input is set +// - an error is returned +func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error { + if c.in.err != nil { + return c.in.err + } + handshakeComplete := c.handshakeComplete() + + // This function modifies c.rawInput, which owns the c.input memory. + if c.input.Len() != 0 { + return c.in.setErrorLocked(errors.New("tls: internal error: attempted to read record with pending application data")) + } + c.input.Reset(nil) + + // Read header, payload. + if err := c.readFromUntil(c.conn, recordHeaderLen); err != nil { + // RFC 8446, Section 6.1 suggests that EOF without an alertCloseNotify + // is an error, but popular web sites seem to do this, so we accept it + // if and only if at the record boundary. + if err == io.ErrUnexpectedEOF && c.rawInput.Len() == 0 { + err = io.EOF + } + if e, ok := err.(net.Error); !ok || !e.Temporary() { + c.in.setErrorLocked(err) + } + return err + } + hdr := c.rawInput.Bytes()[:recordHeaderLen] + typ := recordType(hdr[0]) + + // No valid TLS record has a type of 0x80, however SSLv2 handshakes + // start with a uint16 length where the MSB is set and the first record + // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests + // an SSLv2 client. + if !handshakeComplete && typ == 0x80 { + c.sendAlert(alertProtocolVersion) + return c.in.setErrorLocked(c.newRecordHeaderError(nil, "unsupported SSLv2 handshake received")) + } + + vers := uint16(hdr[1])<<8 | uint16(hdr[2]) + n := int(hdr[3])<<8 | int(hdr[4]) + if c.haveVers && c.vers != VersionTLS13 && vers != c.vers { + c.sendAlert(alertProtocolVersion) + msg := fmt.Sprintf("received record with version %x when expecting version %x", vers, c.vers) + return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg)) + } + if !c.haveVers { + // First message, be extra suspicious: this might not be a TLS + // client. Bail out before reading a full 'body', if possible. + // The current max version is 3.3 so if the version is >= 16.0, + // it's probably not real. + if (typ != recordTypeAlert && typ != recordTypeHandshake) || vers >= 0x1000 { + return c.in.setErrorLocked(c.newRecordHeaderError(c.conn, "first record does not look like a TLS handshake")) + } + } + if c.vers == VersionTLS13 && n > maxCiphertextTLS13 || n > maxCiphertext { + c.sendAlert(alertRecordOverflow) + msg := fmt.Sprintf("oversized record received with length %d", n) + return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg)) + } + if err := c.readFromUntil(c.conn, recordHeaderLen+n); err != nil { + if e, ok := err.(net.Error); !ok || !e.Temporary() { + c.in.setErrorLocked(err) + } + return err + } + + // Process message. + record := c.rawInput.Next(recordHeaderLen + n) + data, typ, err := c.in.decrypt(record) + if err != nil { + return c.in.setErrorLocked(c.sendAlert(err.(alert))) + } + if len(data) > maxPlaintext { + return c.in.setErrorLocked(c.sendAlert(alertRecordOverflow)) + } + + // Application Data messages are always protected. + if c.in.cipher == nil && typ == recordTypeApplicationData { + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + + if typ != recordTypeAlert && typ != recordTypeChangeCipherSpec && len(data) > 0 { + // This is a state-advancing message: reset the retry count. + c.retryCount = 0 + } + + // Handshake messages MUST NOT be interleaved with other record types in TLS 1.3. + if c.vers == VersionTLS13 && typ != recordTypeHandshake && c.hand.Len() > 0 { + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + + switch typ { + default: + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + + case recordTypeAlert: + if len(data) != 2 { + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + if alert(data[1]) == alertCloseNotify { + return c.in.setErrorLocked(io.EOF) + } + if c.vers == VersionTLS13 { + return c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])}) + } + switch data[0] { + case alertLevelWarning: + // Drop the record on the floor and retry. + return c.retryReadRecord(expectChangeCipherSpec) + case alertLevelError: + return c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])}) + default: + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + + case recordTypeChangeCipherSpec: + if len(data) != 1 || data[0] != 1 { + return c.in.setErrorLocked(c.sendAlert(alertDecodeError)) + } + // Handshake messages are not allowed to fragment across the CCS. + if c.hand.Len() > 0 { + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + // In TLS 1.3, change_cipher_spec records are ignored until the + // Finished. See RFC 8446, Appendix D.4. Note that according to Section + // 5, a server can send a ChangeCipherSpec before its ServerHello, when + // c.vers is still unset. That's not useful though and suspicious if the + // server then selects a lower protocol version, so don't allow that. + if c.vers == VersionTLS13 { + return c.retryReadRecord(expectChangeCipherSpec) + } + if !expectChangeCipherSpec { + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + if err := c.in.changeCipherSpec(); err != nil { + return c.in.setErrorLocked(c.sendAlert(err.(alert))) + } + + case recordTypeApplicationData: + if !handshakeComplete || expectChangeCipherSpec { + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + // Some OpenSSL servers send empty records in order to randomize the + // CBC IV. Ignore a limited number of empty records. + if len(data) == 0 { + return c.retryReadRecord(expectChangeCipherSpec) + } + // Note that data is owned by c.rawInput, following the Next call above, + // to avoid copying the plaintext. This is safe because c.rawInput is + // not read from or written to until c.input is drained. + c.input.Reset(data) + + case recordTypeHandshake: + if len(data) == 0 || expectChangeCipherSpec { + return c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + c.hand.Write(data) + } + + return nil +} + +// retryReadRecord recurses into readRecordOrCCS to drop a non-advancing record, like +// a warning alert, empty application_data, or a change_cipher_spec in TLS 1.3. +func (c *Conn) retryReadRecord(expectChangeCipherSpec bool) error { + c.retryCount++ + if c.retryCount > maxUselessRecords { + c.sendAlert(alertUnexpectedMessage) + return c.in.setErrorLocked(errors.New("tls: too many ignored records")) + } + return c.readRecordOrCCS(expectChangeCipherSpec) +} + +// atLeastReader reads from R, stopping with EOF once at least N bytes have been +// read. It is different from an io.LimitedReader in that it doesn't cut short +// the last Read call, and in that it considers an early EOF an error. +type atLeastReader struct { + R io.Reader + N int64 +} + +func (r *atLeastReader) Read(p []byte) (int, error) { + if r.N <= 0 { + return 0, io.EOF + } + n, err := r.R.Read(p) + r.N -= int64(n) // won't underflow unless len(p) >= n > 9223372036854775809 + if r.N > 0 && err == io.EOF { + return n, io.ErrUnexpectedEOF + } + if r.N <= 0 && err == nil { + return n, io.EOF + } + return n, err +} + +// readFromUntil reads from r into c.rawInput until c.rawInput contains +// at least n bytes or else returns an error. +func (c *Conn) readFromUntil(r io.Reader, n int) error { + if c.rawInput.Len() >= n { + return nil + } + needs := n - c.rawInput.Len() + // There might be extra input waiting on the wire. Make a best effort + // attempt to fetch it so that it can be used in (*Conn).Read to + // "predict" closeNotify alerts. + c.rawInput.Grow(needs + bytes.MinRead) + _, err := c.rawInput.ReadFrom(&atLeastReader{r, int64(needs)}) + return err +} + +// sendAlert sends a TLS alert message. +func (c *Conn) sendAlertLocked(err alert) error { + switch err { + case alertNoRenegotiation, alertCloseNotify: + c.tmp[0] = alertLevelWarning + default: + c.tmp[0] = alertLevelError + } + c.tmp[1] = byte(err) + + _, writeErr := c.writeRecordLocked(recordTypeAlert, c.tmp[0:2]) + if err == alertCloseNotify { + // closeNotify is a special case in that it isn't an error. + return writeErr + } + + return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) +} + +// sendAlert sends a TLS alert message. +func (c *Conn) sendAlert(err alert) error { + c.out.Lock() + defer c.out.Unlock() + return c.sendAlertLocked(err) +} + +const ( + // tcpMSSEstimate is a conservative estimate of the TCP maximum segment + // size (MSS). A constant is used, rather than querying the kernel for + // the actual MSS, to avoid complexity. The value here is the IPv6 + // minimum MTU (1280 bytes) minus the overhead of an IPv6 header (40 + // bytes) and a TCP header with timestamps (32 bytes). + tcpMSSEstimate = 1208 + + // recordSizeBoostThreshold is the number of bytes of application data + // sent after which the TLS record size will be increased to the + // maximum. + recordSizeBoostThreshold = 128 * 1024 +) + +// maxPayloadSizeForWrite returns the maximum TLS payload size to use for the +// next application data record. There is the following trade-off: +// +// - For latency-sensitive applications, such as web browsing, each TLS +// record should fit in one TCP segment. +// - For throughput-sensitive applications, such as large file transfers, +// larger TLS records better amortize framing and encryption overheads. +// +// A simple heuristic that works well in practice is to use small records for +// the first 1MB of data, then use larger records for subsequent data, and +// reset back to smaller records after the connection becomes idle. See "High +// Performance Web Networking", Chapter 4, or: +// https://www.igvita.com/2013/10/24/optimizing-tls-record-size-and-buffering-latency/ +// +// In the interests of simplicity and determinism, this code does not attempt +// to reset the record size once the connection is idle, however. +func (c *Conn) maxPayloadSizeForWrite(typ recordType) int { + if c.config.DynamicRecordSizingDisabled || typ != recordTypeApplicationData { + return maxPlaintext + } + + if c.bytesSent >= recordSizeBoostThreshold { + return maxPlaintext + } + + // Subtract TLS overheads to get the maximum payload size. + payloadBytes := tcpMSSEstimate - recordHeaderLen - c.out.explicitNonceLen() + if c.out.cipher != nil { + switch ciph := c.out.cipher.(type) { + case cipher.Stream: + payloadBytes -= c.out.mac.Size() + case cipher.AEAD: + payloadBytes -= ciph.Overhead() + case cbcMode: + blockSize := ciph.BlockSize() + // The payload must fit in a multiple of blockSize, with + // room for at least one padding byte. + payloadBytes = (payloadBytes & ^(blockSize - 1)) - 1 + // The MAC is appended before padding so affects the + // payload size directly. + payloadBytes -= c.out.mac.Size() + default: + panic("unknown cipher type") + } + } + if c.vers == VersionTLS13 { + payloadBytes-- // encrypted ContentType + } + + // Allow packet growth in arithmetic progression up to max. + pkt := c.packetsSent + c.packetsSent++ + if pkt > 1000 { + return maxPlaintext // avoid overflow in multiply below + } + + n := payloadBytes * int(pkt+1) + if n > maxPlaintext { + n = maxPlaintext + } + return n +} + +func (c *Conn) write(data []byte) (int, error) { + if c.buffering { + c.sendBuf = append(c.sendBuf, data...) + return len(data), nil + } + + n, err := c.conn.Write(data) + c.bytesSent += int64(n) + return n, err +} + +func (c *Conn) flush() (int, error) { + if len(c.sendBuf) == 0 { + return 0, nil + } + + n, err := c.conn.Write(c.sendBuf) + c.bytesSent += int64(n) + c.sendBuf = nil + c.buffering = false + return n, err +} + +// outBufPool pools the record-sized scratch buffers used by writeRecordLocked. +var outBufPool = sync.Pool{ + New: func() interface{} { + return new([]byte) + }, +} + +// writeRecordLocked writes a TLS record with the given type and payload to the +// connection and updates the record layer state. +func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) { + outBufPtr := outBufPool.Get().(*[]byte) + outBuf := *outBufPtr + defer func() { + // You might be tempted to simplify this by just passing &outBuf to Put, + // but that would make the local copy of the outBuf slice header escape + // to the heap, causing an allocation. Instead, we keep around the + // pointer to the slice header returned by Get, which is already on the + // heap, and overwrite and return that. + *outBufPtr = outBuf + outBufPool.Put(outBufPtr) + }() + + var n int + for len(data) > 0 { + m := len(data) + if maxPayload := c.maxPayloadSizeForWrite(typ); m > maxPayload { + m = maxPayload + } + + _, outBuf = sliceForAppend(outBuf[:0], recordHeaderLen) + outBuf[0] = byte(typ) + vers := c.vers + if vers == 0 { + // Some TLS servers fail if the record version is + // greater than TLS 1.0 for the initial ClientHello. + vers = VersionTLS10 + } else if vers == VersionTLS13 { + // TLS 1.3 froze the record layer version to 1.2. + // See RFC 8446, Section 5.1. + vers = VersionTLS12 + } + outBuf[1] = byte(vers >> 8) + outBuf[2] = byte(vers) + outBuf[3] = byte(m >> 8) + outBuf[4] = byte(m) + + var err error + outBuf, err = c.out.encrypt(outBuf, data[:m], c.config.rand()) + if err != nil { + return n, err + } + if _, err := c.write(outBuf); err != nil { + return n, err + } + n += m + data = data[m:] + } + + if typ == recordTypeChangeCipherSpec && c.vers != VersionTLS13 { + if err := c.out.changeCipherSpec(); err != nil { + return n, c.sendAlertLocked(err.(alert)) + } + } + + return n, nil +} + +// writeRecord writes a TLS record with the given type and payload to the +// connection and updates the record layer state. +func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) { + c.out.Lock() + defer c.out.Unlock() + + return c.writeRecordLocked(typ, data) +} + +// readHandshake reads the next handshake message from +// the record layer. +func (c *Conn) readHandshake() (interface{}, error) { + for c.hand.Len() < 4 { + if err := c.readRecord(); err != nil { + return nil, err + } + } + + data := c.hand.Bytes() + n := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) + if n > maxHandshake { + c.sendAlertLocked(alertInternalError) + return nil, c.in.setErrorLocked(fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake)) + } + for c.hand.Len() < 4+n { + if err := c.readRecord(); err != nil { + return nil, err + } + } + data = c.hand.Next(4 + n) + var m handshakeMessage + switch data[0] { + case typeHelloRequest: + m = new(helloRequestMsg) + case typeClientHello: + m = new(clientHelloMsg) + case typeServerHello: + m = new(serverHelloMsg) + case typeNewSessionTicket: + if c.vers == VersionTLS13 { + m = new(newSessionTicketMsgTLS13) + } else { + m = new(newSessionTicketMsg) + } + case typeCertificate: + if c.vers == VersionTLS13 { + m = new(certificateMsgTLS13) + } else { + m = new(certificateMsg) + } + case typeCertificateRequest: + if c.vers == VersionTLS13 { + m = new(certificateRequestMsgTLS13) + } else { + m = &certificateRequestMsg{ + hasSignatureAlgorithm: c.vers >= VersionTLS12, + } + } + case typeCertificateStatus: + m = new(certificateStatusMsg) + case typeServerKeyExchange: + m = new(serverKeyExchangeMsg) + case typeServerHelloDone: + m = new(serverHelloDoneMsg) + case typeClientKeyExchange: + m = new(clientKeyExchangeMsg) + case typeCertificateVerify: + m = &certificateVerifyMsg{ + hasSignatureAlgorithm: c.vers >= VersionTLS12, + } + case typeFinished: + m = new(finishedMsg) + case typeEncryptedExtensions: + m = new(encryptedExtensionsMsg) + case typeEndOfEarlyData: + m = new(endOfEarlyDataMsg) + case typeKeyUpdate: + m = new(keyUpdateMsg) + default: + return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + + // The handshake message unmarshalers + // expect to be able to keep references to data, + // so pass in a fresh copy that won't be overwritten. + data = append([]byte(nil), data...) + + if !m.unmarshal(data) { + return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + return m, nil +} + +var ( + errShutdown = errors.New("tls: protocol is shutdown") +) + +// Write writes data to the connection. +// +// As Write calls Handshake, in order to prevent indefinite blocking a deadline +// must be set for both Read and Write before Write is called when the handshake +// has not yet completed. See SetDeadline, SetReadDeadline, and +// SetWriteDeadline. +func (c *Conn) Write(b []byte) (int, error) { + // interlock with Close below + for { + x := atomic.LoadInt32(&c.activeCall) + if x&1 != 0 { + return 0, net.ErrClosed + } + if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) { + break + } + } + defer atomic.AddInt32(&c.activeCall, -2) + + if err := c.Handshake(); err != nil { + return 0, err + } + + c.out.Lock() + defer c.out.Unlock() + + if err := c.out.err; err != nil { + return 0, err + } + + if !c.handshakeComplete() { + return 0, alertInternalError + } + + if c.closeNotifySent { + return 0, errShutdown + } + + // TLS 1.0 is susceptible to a chosen-plaintext + // attack when using block mode ciphers due to predictable IVs. + // This can be prevented by splitting each Application Data + // record into two records, effectively randomizing the IV. + // + // https://www.openssl.org/~bodo/tls-cbc.txt + // https://bugzilla.mozilla.org/show_bug.cgi?id=665814 + // https://www.imperialviolet.org/2012/01/15/beastfollowup.html + + var m int + if len(b) > 1 && c.vers == VersionTLS10 { + if _, ok := c.out.cipher.(cipher.BlockMode); ok { + n, err := c.writeRecordLocked(recordTypeApplicationData, b[:1]) + if err != nil { + return n, c.out.setErrorLocked(err) + } + m, b = 1, b[1:] + } + } + + n, err := c.writeRecordLocked(recordTypeApplicationData, b) + return n + m, c.out.setErrorLocked(err) +} + +// handleRenegotiation processes a HelloRequest handshake message. +func (c *Conn) handleRenegotiation() error { + if c.vers == VersionTLS13 { + return errors.New("tls: internal error: unexpected renegotiation") + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + + helloReq, ok := msg.(*helloRequestMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(helloReq, msg) + } + + if !c.isClient { + return c.sendAlert(alertNoRenegotiation) + } + + switch c.config.Renegotiation { + case RenegotiateNever: + return c.sendAlert(alertNoRenegotiation) + case RenegotiateOnceAsClient: + if c.handshakes > 1 { + return c.sendAlert(alertNoRenegotiation) + } + case RenegotiateFreelyAsClient: + // Ok. + default: + c.sendAlert(alertInternalError) + return errors.New("tls: unknown Renegotiation value") + } + + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + + atomic.StoreUint32(&c.handshakeStatus, 0) + if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil { + c.handshakes++ + } + return c.handshakeErr +} + +// handlePostHandshakeMessage processes a handshake message arrived after the +// handshake is complete. Up to TLS 1.2, it indicates the start of a renegotiation. +func (c *Conn) handlePostHandshakeMessage() error { + if c.vers != VersionTLS13 { + return c.handleRenegotiation() + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + + c.retryCount++ + if c.retryCount > maxUselessRecords { + c.sendAlert(alertUnexpectedMessage) + return c.in.setErrorLocked(errors.New("tls: too many non-advancing records")) + } + + switch msg := msg.(type) { + case *newSessionTicketMsgTLS13: + return c.handleNewSessionTicket(msg) + case *keyUpdateMsg: + return c.handleKeyUpdate(msg) + default: + c.sendAlert(alertUnexpectedMessage) + return fmt.Errorf("tls: received unexpected handshake message of type %T", msg) + } +} + +func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error { + cipherSuite := cipherSuiteTLS13ByID(c.cipherSuite) + if cipherSuite == nil { + return c.in.setErrorLocked(c.sendAlert(alertInternalError)) + } + + newSecret := cipherSuite.nextTrafficSecret(c.in.trafficSecret) + c.in.setTrafficSecret(cipherSuite, newSecret) + + if keyUpdate.updateRequested { + c.out.Lock() + defer c.out.Unlock() + + msg := &keyUpdateMsg{} + _, err := c.writeRecordLocked(recordTypeHandshake, msg.marshal()) + if err != nil { + // Surface the error at the next write. + c.out.setErrorLocked(err) + return nil + } + + newSecret := cipherSuite.nextTrafficSecret(c.out.trafficSecret) + c.out.setTrafficSecret(cipherSuite, newSecret) + } + + return nil +} + +// Read reads data from the connection. +// +// As Read calls Handshake, in order to prevent indefinite blocking a deadline +// must be set for both Read and Write before Read is called when the handshake +// has not yet completed. See SetDeadline, SetReadDeadline, and +// SetWriteDeadline. +func (c *Conn) Read(b []byte) (int, error) { + if err := c.Handshake(); err != nil { + return 0, err + } + if len(b) == 0 { + // Put this after Handshake, in case people were calling + // Read(nil) for the side effect of the Handshake. + return 0, nil + } + + c.in.Lock() + defer c.in.Unlock() + + for c.input.Len() == 0 { + if err := c.readRecord(); err != nil { + return 0, err + } + for c.hand.Len() > 0 { + if err := c.handlePostHandshakeMessage(); err != nil { + return 0, err + } + } + } + + n, _ := c.input.Read(b) + + // If a close-notify alert is waiting, read it so that we can return (n, + // EOF) instead of (n, nil), to signal to the HTTP response reading + // goroutine that the connection is now closed. This eliminates a race + // where the HTTP response reading goroutine would otherwise not observe + // the EOF until its next read, by which time a client goroutine might + // have already tried to reuse the HTTP connection for a new request. + // See https://golang.org/cl/76400046 and https://golang.org/issue/3514 + if n != 0 && c.input.Len() == 0 && c.rawInput.Len() > 0 && + recordType(c.rawInput.Bytes()[0]) == recordTypeAlert { + if err := c.readRecord(); err != nil { + return n, err // will be io.EOF on closeNotify + } + } + + return n, nil +} + +// Close closes the connection. +func (c *Conn) Close() error { + // Interlock with Conn.Write above. + var x int32 + for { + x = atomic.LoadInt32(&c.activeCall) + if x&1 != 0 { + return net.ErrClosed + } + if atomic.CompareAndSwapInt32(&c.activeCall, x, x|1) { + break + } + } + if x != 0 { + // io.Writer and io.Closer should not be used concurrently. + // If Close is called while a Write is currently in-flight, + // interpret that as a sign that this Close is really just + // being used to break the Write and/or clean up resources and + // avoid sending the alertCloseNotify, which may block + // waiting on handshakeMutex or the c.out mutex. + return c.conn.Close() + } + + var alertErr error + if c.handshakeComplete() { + if err := c.closeNotify(); err != nil { + alertErr = fmt.Errorf("tls: failed to send closeNotify alert (but connection was closed anyway): %w", err) + } + } + + if err := c.conn.Close(); err != nil { + return err + } + return alertErr +} + +var errEarlyCloseWrite = errors.New("tls: CloseWrite called before handshake complete") + +// CloseWrite shuts down the writing side of the connection. It should only be +// called once the handshake has completed and does not call CloseWrite on the +// underlying connection. Most callers should just use Close. +func (c *Conn) CloseWrite() error { + if !c.handshakeComplete() { + return errEarlyCloseWrite + } + + return c.closeNotify() +} + +func (c *Conn) closeNotify() error { + c.out.Lock() + defer c.out.Unlock() + + if !c.closeNotifySent { + // Set a Write Deadline to prevent possibly blocking forever. + c.SetWriteDeadline(time.Now().Add(time.Second * 5)) + c.closeNotifyErr = c.sendAlertLocked(alertCloseNotify) + c.closeNotifySent = true + // Any subsequent writes will fail. + c.SetWriteDeadline(time.Now()) + } + return c.closeNotifyErr +} + +// Handshake runs the client or server handshake +// protocol if it has not yet been run. +// +// Most uses of this package need not call Handshake explicitly: the +// first Read or Write will call it automatically. +// +// For control over canceling or setting a timeout on a handshake, use +// HandshakeContext or the Dialer's DialContext method instead. +func (c *Conn) Handshake() error { + return c.HandshakeContext(context.Background()) +} + +// HandshakeContext runs the client or server handshake +// protocol if it has not yet been run. +// +// The provided Context must be non-nil. If the context is canceled before +// the handshake is complete, the handshake is interrupted and an error is returned. +// Once the handshake has completed, cancellation of the context will not affect the +// connection. +// +// Most uses of this package need not call HandshakeContext explicitly: the +// first Read or Write will call it automatically. +func (c *Conn) HandshakeContext(ctx context.Context) error { + // Delegate to unexported method for named return + // without confusing documented signature. + return c.handshakeContext(ctx) +} + +func (c *Conn) handshakeContext(ctx context.Context) (ret error) { + // Fast sync/atomic-based exit if there is no handshake in flight and the + // last one succeeded without an error. Avoids the expensive context setup + // and mutex for most Read and Write calls. + if c.handshakeComplete() { + return nil + } + + handshakeCtx, cancel := context.WithCancel(ctx) + // Note: defer this before starting the "interrupter" goroutine + // so that we can tell the difference between the input being canceled and + // this cancellation. In the former case, we need to close the connection. + defer cancel() + + // Start the "interrupter" goroutine, if this context might be canceled. + // (The background context cannot). + // + // The interrupter goroutine waits for the input context to be done and + // closes the connection if this happens before the function returns. + if ctx.Done() != nil { + done := make(chan struct{}) + interruptRes := make(chan error, 1) + defer func() { + close(done) + if ctxErr := <-interruptRes; ctxErr != nil { + // Return context error to user. + ret = ctxErr + } + }() + go func() { + select { + case <-handshakeCtx.Done(): + // Close the connection, discarding the error + _ = c.conn.Close() + interruptRes <- handshakeCtx.Err() + case <-done: + interruptRes <- nil + } + }() + } + + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + + if err := c.handshakeErr; err != nil { + return err + } + if c.handshakeComplete() { + return nil + } + + c.in.Lock() + defer c.in.Unlock() + + c.handshakeErr = c.handshakeFn(handshakeCtx) + if c.handshakeErr == nil { + c.handshakes++ + } else { + // If an error occurred during the handshake try to flush the + // alert that might be left in the buffer. + c.flush() + } + + if c.handshakeErr == nil && !c.handshakeComplete() { + c.handshakeErr = errors.New("tls: internal error: handshake should have had a result") + } + if c.handshakeErr != nil && c.handshakeComplete() { + panic("tls: internal error: handshake returned an error but is marked successful") + } + + return c.handshakeErr +} + +// ConnectionState returns basic TLS details about the connection. +func (c *Conn) ConnectionState() ConnectionState { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + return c.connectionStateLocked() +} + +func (c *Conn) connectionStateLocked() ConnectionState { + var state ConnectionState + state.HandshakeComplete = c.handshakeComplete() + state.Version = c.vers + state.NegotiatedProtocol = c.clientProtocol + state.DidResume = c.didResume + state.NegotiatedProtocolIsMutual = true + state.ServerName = c.serverName + state.CipherSuite = c.cipherSuite + state.PeerCertificates = c.peerCertificates + state.VerifiedChains = c.verifiedChains + state.SignedCertificateTimestamps = c.scts + state.OCSPResponse = c.ocspResponse + if !c.didResume && c.vers != VersionTLS13 { + if c.clientFinishedIsFirst { + state.TLSUnique = c.clientFinished[:] + } else { + state.TLSUnique = c.serverFinished[:] + } + } + if c.config.Renegotiation != RenegotiateNever { + state.ekm = noExportedKeyingMaterial + } else { + state.ekm = c.ekm + } + return state +} + +// OCSPResponse returns the stapled OCSP response from the TLS server, if +// any. (Only valid for client connections.) +func (c *Conn) OCSPResponse() []byte { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + + return c.ocspResponse +} + +// VerifyHostname checks that the peer certificate chain is valid for +// connecting to host. If so, it returns nil; if not, it returns an error +// describing the problem. +func (c *Conn) VerifyHostname(host string) error { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + if !c.isClient { + return errors.New("tls: VerifyHostname called on TLS server connection") + } + if !c.handshakeComplete() { + return errors.New("tls: handshake has not yet been performed") + } + if len(c.verifiedChains) == 0 { + return errors.New("tls: handshake did not verify certificate chain") + } + return c.peerCertificates[0].VerifyHostname(host) +} + +func (c *Conn) handshakeComplete() bool { + return atomic.LoadUint32(&c.handshakeStatus) == 1 +} diff --git a/src/crypto/tls/conn_test.go b/src/crypto/tls/conn_test.go new file mode 100644 index 0000000..78935b1 --- /dev/null +++ b/src/crypto/tls/conn_test.go @@ -0,0 +1,287 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "io" + "net" + "testing" +) + +func TestRoundUp(t *testing.T) { + if roundUp(0, 16) != 0 || + roundUp(1, 16) != 16 || + roundUp(15, 16) != 16 || + roundUp(16, 16) != 16 || + roundUp(17, 16) != 32 { + t.Error("roundUp broken") + } +} + +// will be initialized with {0, 255, 255, ..., 255} +var padding255Bad = [256]byte{} + +// will be initialized with {255, 255, 255, ..., 255} +var padding255Good = [256]byte{255} + +var paddingTests = []struct { + in []byte + good bool + expectedLen int +}{ + {[]byte{1, 2, 3, 4, 0}, true, 4}, + {[]byte{1, 2, 3, 4, 0, 1}, false, 0}, + {[]byte{1, 2, 3, 4, 99, 99}, false, 0}, + {[]byte{1, 2, 3, 4, 1, 1}, true, 4}, + {[]byte{1, 2, 3, 2, 2, 2}, true, 3}, + {[]byte{1, 2, 3, 3, 3, 3}, true, 2}, + {[]byte{1, 2, 3, 4, 3, 3}, false, 0}, + {[]byte{1, 4, 4, 4, 4, 4}, true, 1}, + {[]byte{5, 5, 5, 5, 5, 5}, true, 0}, + {[]byte{6, 6, 6, 6, 6, 6}, false, 0}, + {padding255Bad[:], false, 0}, + {padding255Good[:], true, 0}, +} + +func TestRemovePadding(t *testing.T) { + for i := 1; i < len(padding255Bad); i++ { + padding255Bad[i] = 255 + padding255Good[i] = 255 + } + for i, test := range paddingTests { + paddingLen, good := extractPadding(test.in) + expectedGood := byte(255) + if !test.good { + expectedGood = 0 + } + if good != expectedGood { + t.Errorf("#%d: wrong validity, want:%d got:%d", i, expectedGood, good) + } + if good == 255 && len(test.in)-paddingLen != test.expectedLen { + t.Errorf("#%d: got %d, want %d", i, len(test.in)-paddingLen, test.expectedLen) + } + } +} + +var certExampleCom = `308201713082011ba003020102021005a75ddf21014d5f417083b7a010ba2e300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343135335a170d3137303831373231343135335a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100b37f0fdd67e715bf532046ac34acbd8fdc4dabe2b598588f3f58b1f12e6219a16cbfe54d2b4b665396013589262360b6721efa27d546854f17cc9aeec6751db10203010001a34d304b300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff0402300030160603551d11040f300d820b6578616d706c652e636f6d300d06092a864886f70d01010b050003410059fc487866d3d855503c8e064ca32aac5e9babcece89ec597f8b2b24c17867f4a5d3b4ece06e795bfc5448ccbd2ffca1b3433171ebf3557a4737b020565350a0` + +var certWildcardExampleCom = `308201743082011ea003020102021100a7aa6297c9416a4633af8bec2958c607300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343231395a170d3137303831373231343231395a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100b105afc859a711ee864114e7d2d46c2dcbe392d3506249f6c2285b0eb342cc4bf2d803677c61c0abde443f084745c1a6d62080e5664ef2cc8f50ad8a0ab8870b0203010001a34f304d300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff0402300030180603551d110411300f820d2a2e6578616d706c652e636f6d300d06092a864886f70d01010b0500034100af26088584d266e3f6566360cf862c7fecc441484b098b107439543144a2b93f20781988281e108c6d7656934e56950e1e5f2bcf38796b814ccb729445856c34` + +var certFooExampleCom = `308201753082011fa00302010202101bbdb6070b0aeffc49008cde74deef29300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343234345a170d3137303831373231343234345a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100f00ac69d8ca2829f26216c7b50f1d4bbabad58d447706476cd89a2f3e1859943748aa42c15eedc93ac7c49e40d3b05ed645cb6b81c4efba60d961f44211a54eb0203010001a351304f300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301a0603551d1104133011820f666f6f2e6578616d706c652e636f6d300d06092a864886f70d01010b0500034100a0957fca6d1e0f1ef4b247348c7a8ca092c29c9c0ecc1898ea6b8065d23af6d922a410dd2335a0ea15edd1394cef9f62c9e876a21e35250a0b4fe1ddceba0f36` + +func TestCertificateSelection(t *testing.T) { + config := Config{ + Certificates: []Certificate{ + { + Certificate: [][]byte{fromHex(certExampleCom)}, + }, + { + Certificate: [][]byte{fromHex(certWildcardExampleCom)}, + }, + { + Certificate: [][]byte{fromHex(certFooExampleCom)}, + }, + }, + } + + config.BuildNameToCertificate() + + pointerToIndex := func(c *Certificate) int { + for i := range config.Certificates { + if c == &config.Certificates[i] { + return i + } + } + return -1 + } + + certificateForName := func(name string) *Certificate { + clientHello := &ClientHelloInfo{ + ServerName: name, + } + if cert, err := config.getCertificate(clientHello); err != nil { + t.Errorf("unable to get certificate for name '%s': %s", name, err) + return nil + } else { + return cert + } + } + + if n := pointerToIndex(certificateForName("example.com")); n != 0 { + t.Errorf("example.com returned certificate %d, not 0", n) + } + if n := pointerToIndex(certificateForName("bar.example.com")); n != 1 { + t.Errorf("bar.example.com returned certificate %d, not 1", n) + } + if n := pointerToIndex(certificateForName("foo.example.com")); n != 2 { + t.Errorf("foo.example.com returned certificate %d, not 2", n) + } + if n := pointerToIndex(certificateForName("foo.bar.example.com")); n != 0 { + t.Errorf("foo.bar.example.com returned certificate %d, not 0", n) + } +} + +// Run with multiple crypto configs to test the logic for computing TLS record overheads. +func runDynamicRecordSizingTest(t *testing.T, config *Config) { + clientConn, serverConn := localPipe(t) + + serverConfig := config.Clone() + serverConfig.DynamicRecordSizingDisabled = false + tlsConn := Server(serverConn, serverConfig) + + handshakeDone := make(chan struct{}) + recordSizesChan := make(chan []int, 1) + defer func() { <-recordSizesChan }() // wait for the goroutine to exit + go func() { + // This goroutine performs a TLS handshake over clientConn and + // then reads TLS records until EOF. It writes a slice that + // contains all the record sizes to recordSizesChan. + defer close(recordSizesChan) + defer clientConn.Close() + + tlsConn := Client(clientConn, config) + if err := tlsConn.Handshake(); err != nil { + t.Errorf("Error from client handshake: %v", err) + return + } + close(handshakeDone) + + var recordHeader [recordHeaderLen]byte + var record []byte + var recordSizes []int + + for { + n, err := io.ReadFull(clientConn, recordHeader[:]) + if err == io.EOF { + break + } + if err != nil || n != len(recordHeader) { + t.Errorf("io.ReadFull = %d, %v", n, err) + return + } + + length := int(recordHeader[3])<<8 | int(recordHeader[4]) + if len(record) < length { + record = make([]byte, length) + } + + n, err = io.ReadFull(clientConn, record[:length]) + if err != nil || n != length { + t.Errorf("io.ReadFull = %d, %v", n, err) + return + } + + recordSizes = append(recordSizes, recordHeaderLen+length) + } + + recordSizesChan <- recordSizes + }() + + if err := tlsConn.Handshake(); err != nil { + t.Fatalf("Error from server handshake: %s", err) + } + <-handshakeDone + + // The server writes these plaintexts in order. + plaintext := bytes.Join([][]byte{ + bytes.Repeat([]byte("x"), recordSizeBoostThreshold), + bytes.Repeat([]byte("y"), maxPlaintext*2), + bytes.Repeat([]byte("z"), maxPlaintext), + }, nil) + + if _, err := tlsConn.Write(plaintext); err != nil { + t.Fatalf("Error from server write: %s", err) + } + if err := tlsConn.Close(); err != nil { + t.Fatalf("Error from server close: %s", err) + } + + recordSizes := <-recordSizesChan + if recordSizes == nil { + t.Fatalf("Client encountered an error") + } + + // Drop the size of the second to last record, which is likely to be + // truncated, and the last record, which is a close_notify alert. + recordSizes = recordSizes[:len(recordSizes)-2] + + // recordSizes should contain a series of records smaller than + // tcpMSSEstimate followed by some larger than maxPlaintext. + seenLargeRecord := false + for i, size := range recordSizes { + if !seenLargeRecord { + if size > (i+1)*tcpMSSEstimate { + t.Fatalf("Record #%d has size %d, which is too large too soon", i, size) + } + if size >= maxPlaintext { + seenLargeRecord = true + } + } else if size <= maxPlaintext { + t.Fatalf("Record #%d has size %d but should be full sized", i, size) + } + } + + if !seenLargeRecord { + t.Fatalf("No large records observed") + } +} + +func TestDynamicRecordSizingWithStreamCipher(t *testing.T) { + config := testConfig.Clone() + config.MaxVersion = VersionTLS12 + config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA} + runDynamicRecordSizingTest(t, config) +} + +func TestDynamicRecordSizingWithCBC(t *testing.T) { + config := testConfig.Clone() + config.MaxVersion = VersionTLS12 + config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA} + runDynamicRecordSizingTest(t, config) +} + +func TestDynamicRecordSizingWithAEAD(t *testing.T) { + config := testConfig.Clone() + config.MaxVersion = VersionTLS12 + config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} + runDynamicRecordSizingTest(t, config) +} + +func TestDynamicRecordSizingWithTLSv13(t *testing.T) { + config := testConfig.Clone() + runDynamicRecordSizingTest(t, config) +} + +// hairpinConn is a net.Conn that makes a “hairpin” call when closed, back into +// the tls.Conn which is calling it. +type hairpinConn struct { + net.Conn + tlsConn *Conn +} + +func (conn *hairpinConn) Close() error { + conn.tlsConn.ConnectionState() + return nil +} + +func TestHairpinInClose(t *testing.T) { + // This tests that the underlying net.Conn can call back into the + // tls.Conn when being closed without deadlocking. + client, server := localPipe(t) + defer server.Close() + defer client.Close() + + conn := &hairpinConn{client, nil} + tlsConn := Server(conn, &Config{ + GetCertificate: func(*ClientHelloInfo) (*Certificate, error) { + panic("unreachable") + }, + }) + conn.tlsConn = tlsConn + + // This call should not deadlock. + tlsConn.Close() +} diff --git a/src/crypto/tls/example_test.go b/src/crypto/tls/example_test.go new file mode 100644 index 0000000..6389fd7 --- /dev/null +++ b/src/crypto/tls/example_test.go @@ -0,0 +1,232 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls_test + +import ( + "crypto/tls" + "crypto/x509" + "log" + "net/http" + "net/http/httptest" + "os" + "time" +) + +// zeroSource is an io.Reader that returns an unlimited number of zero bytes. +type zeroSource struct{} + +func (zeroSource) Read(b []byte) (n int, err error) { + for i := range b { + b[i] = 0 + } + + return len(b), nil +} + +func ExampleDial() { + // Connecting with a custom root-certificate set. + + const rootPEM = ` +-- GlobalSign Root R2, valid until Dec 15, 2021 +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE-----` + + // First, create the set of root certificates. For this example we only + // have one. It's also possible to omit this in order to use the + // default root set of the current operating system. + roots := x509.NewCertPool() + ok := roots.AppendCertsFromPEM([]byte(rootPEM)) + if !ok { + panic("failed to parse root certificate") + } + + conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{ + RootCAs: roots, + }) + if err != nil { + panic("failed to connect: " + err.Error()) + } + conn.Close() +} + +func ExampleConfig_keyLogWriter() { + // Debugging TLS applications by decrypting a network traffic capture. + + // WARNING: Use of KeyLogWriter compromises security and should only be + // used for debugging. + + // Dummy test HTTP server for the example with insecure random so output is + // reproducible. + server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + server.TLS = &tls.Config{ + Rand: zeroSource{}, // for example only; don't do this. + } + server.StartTLS() + defer server.Close() + + // Typically the log would go to an open file: + // w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + w := os.Stdout + + client := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + KeyLogWriter: w, + + Rand: zeroSource{}, // for reproducible output; don't do this. + InsecureSkipVerify: true, // test server certificate is not trusted. + }, + }, + } + resp, err := client.Get(server.URL) + if err != nil { + log.Fatalf("Failed to get URL: %v", err) + } + resp.Body.Close() + + // The resulting file can be used with Wireshark to decrypt the TLS + // connection by setting (Pre)-Master-Secret log filename in SSL Protocol + // preferences. +} + +func ExampleLoadX509KeyPair() { + cert, err := tls.LoadX509KeyPair("testdata/example-cert.pem", "testdata/example-key.pem") + if err != nil { + log.Fatal(err) + } + cfg := &tls.Config{Certificates: []tls.Certificate{cert}} + listener, err := tls.Listen("tcp", ":2000", cfg) + if err != nil { + log.Fatal(err) + } + _ = listener +} + +func ExampleX509KeyPair() { + certPem := []byte(`-----BEGIN CERTIFICATE----- +MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d +7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B +5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr +BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 +NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l +Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc +6MF9+Yw1Yy0t +-----END CERTIFICATE-----`) + keyPem := []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 +AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q +EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== +-----END EC PRIVATE KEY-----`) + cert, err := tls.X509KeyPair(certPem, keyPem) + if err != nil { + log.Fatal(err) + } + cfg := &tls.Config{Certificates: []tls.Certificate{cert}} + listener, err := tls.Listen("tcp", ":2000", cfg) + if err != nil { + log.Fatal(err) + } + _ = listener +} + +func ExampleX509KeyPair_httpServer() { + certPem := []byte(`-----BEGIN CERTIFICATE----- +MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d +7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B +5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr +BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 +NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l +Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc +6MF9+Yw1Yy0t +-----END CERTIFICATE-----`) + keyPem := []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 +AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q +EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== +-----END EC PRIVATE KEY-----`) + cert, err := tls.X509KeyPair(certPem, keyPem) + if err != nil { + log.Fatal(err) + } + cfg := &tls.Config{Certificates: []tls.Certificate{cert}} + srv := &http.Server{ + TLSConfig: cfg, + ReadTimeout: time.Minute, + WriteTimeout: time.Minute, + } + log.Fatal(srv.ListenAndServeTLS("", "")) +} + +func ExampleConfig_verifyConnection() { + // VerifyConnection can be used to replace and customize connection + // verification. This example shows a VerifyConnection implementation that + // will be approximately equivalent to what crypto/tls does normally to + // verify the peer's certificate. + + // Client side configuration. + _ = &tls.Config{ + // Set InsecureSkipVerify to skip the default validation we are + // replacing. This will not disable VerifyConnection. + InsecureSkipVerify: true, + VerifyConnection: func(cs tls.ConnectionState) error { + opts := x509.VerifyOptions{ + DNSName: cs.ServerName, + Intermediates: x509.NewCertPool(), + } + for _, cert := range cs.PeerCertificates[1:] { + opts.Intermediates.AddCert(cert) + } + _, err := cs.PeerCertificates[0].Verify(opts) + return err + }, + } + + // Server side configuration. + _ = &tls.Config{ + // Require client certificates (or VerifyConnection will run anyway and + // panic accessing cs.PeerCertificates[0]) but don't verify them with the + // default verifier. This will not disable VerifyConnection. + ClientAuth: tls.RequireAnyClientCert, + VerifyConnection: func(cs tls.ConnectionState) error { + opts := x509.VerifyOptions{ + DNSName: cs.ServerName, + Intermediates: x509.NewCertPool(), + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + } + for _, cert := range cs.PeerCertificates[1:] { + opts.Intermediates.AddCert(cert) + } + _, err := cs.PeerCertificates[0].Verify(opts) + return err + }, + } + + // Note that when certificates are not handled by the default verifier + // ConnectionState.VerifiedChains will be nil. +} diff --git a/src/crypto/tls/generate_cert.go b/src/crypto/tls/generate_cert.go new file mode 100644 index 0000000..7ea90f8 --- /dev/null +++ b/src/crypto/tls/generate_cert.go @@ -0,0 +1,173 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +// Generate a self-signed X.509 certificate for a TLS server. Outputs to +// 'cert.pem' and 'key.pem' and will overwrite existing files. + +package main + +import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "flag" + "log" + "math/big" + "net" + "os" + "strings" + "time" +) + +var ( + host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for") + validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") + validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") + isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") + rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set") + ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521") + ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key") +) + +func publicKey(priv interface{}) interface{} { + switch k := priv.(type) { + case *rsa.PrivateKey: + return &k.PublicKey + case *ecdsa.PrivateKey: + return &k.PublicKey + case ed25519.PrivateKey: + return k.Public().(ed25519.PublicKey) + default: + return nil + } +} + +func main() { + flag.Parse() + + if len(*host) == 0 { + log.Fatalf("Missing required --host parameter") + } + + var priv interface{} + var err error + switch *ecdsaCurve { + case "": + if *ed25519Key { + _, priv, err = ed25519.GenerateKey(rand.Reader) + } else { + priv, err = rsa.GenerateKey(rand.Reader, *rsaBits) + } + case "P224": + priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + case "P256": + priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + case "P384": + priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + case "P521": + priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + default: + log.Fatalf("Unrecognized elliptic curve: %q", *ecdsaCurve) + } + if err != nil { + log.Fatalf("Failed to generate private key: %v", err) + } + + // ECDSA, ED25519 and RSA subject keys should have the DigitalSignature + // KeyUsage bits set in the x509.Certificate template + keyUsage := x509.KeyUsageDigitalSignature + // Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In + // the context of TLS this KeyUsage is particular to RSA key exchange and + // authentication. + if _, isRSA := priv.(*rsa.PrivateKey); isRSA { + keyUsage |= x509.KeyUsageKeyEncipherment + } + + var notBefore time.Time + if len(*validFrom) == 0 { + notBefore = time.Now() + } else { + notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom) + if err != nil { + log.Fatalf("Failed to parse creation date: %v", err) + } + } + + notAfter := notBefore.Add(*validFor) + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + log.Fatalf("Failed to generate serial number: %v", err) + } + + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"Acme Co"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: keyUsage, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + + hosts := strings.Split(*host, ",") + for _, h := range hosts { + if ip := net.ParseIP(h); ip != nil { + template.IPAddresses = append(template.IPAddresses, ip) + } else { + template.DNSNames = append(template.DNSNames, h) + } + } + + if *isCA { + template.IsCA = true + template.KeyUsage |= x509.KeyUsageCertSign + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) + if err != nil { + log.Fatalf("Failed to create certificate: %v", err) + } + + certOut, err := os.Create("cert.pem") + if err != nil { + log.Fatalf("Failed to open cert.pem for writing: %v", err) + } + if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { + log.Fatalf("Failed to write data to cert.pem: %v", err) + } + if err := certOut.Close(); err != nil { + log.Fatalf("Error closing cert.pem: %v", err) + } + log.Print("wrote cert.pem\n") + + keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + log.Fatalf("Failed to open key.pem for writing: %v", err) + return + } + privBytes, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + log.Fatalf("Unable to marshal private key: %v", err) + } + if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil { + log.Fatalf("Failed to write data to key.pem: %v", err) + } + if err := keyOut.Close(); err != nil { + log.Fatalf("Error closing key.pem: %v", err) + } + log.Print("wrote key.pem\n") +} diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go new file mode 100644 index 0000000..4af3d99 --- /dev/null +++ b/src/crypto/tls/handshake_client.go @@ -0,0 +1,1011 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "context" + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rsa" + "crypto/subtle" + "crypto/x509" + "errors" + "fmt" + "hash" + "io" + "net" + "strings" + "sync/atomic" + "time" +) + +type clientHandshakeState struct { + c *Conn + ctx context.Context + serverHello *serverHelloMsg + hello *clientHelloMsg + suite *cipherSuite + finishedHash finishedHash + masterSecret []byte + session *ClientSessionState +} + +func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { + config := c.config + if len(config.ServerName) == 0 && !config.InsecureSkipVerify { + return nil, nil, errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") + } + + nextProtosLength := 0 + for _, proto := range config.NextProtos { + if l := len(proto); l == 0 || l > 255 { + return nil, nil, errors.New("tls: invalid NextProtos value") + } else { + nextProtosLength += 1 + l + } + } + if nextProtosLength > 0xffff { + return nil, nil, errors.New("tls: NextProtos values too large") + } + + supportedVersions := config.supportedVersions() + if len(supportedVersions) == 0 { + return nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion") + } + + clientHelloVersion := config.maxSupportedVersion() + // The version at the beginning of the ClientHello was capped at TLS 1.2 + // for compatibility reasons. The supported_versions extension is used + // to negotiate versions now. See RFC 8446, Section 4.2.1. + if clientHelloVersion > VersionTLS12 { + clientHelloVersion = VersionTLS12 + } + + hello := &clientHelloMsg{ + vers: clientHelloVersion, + compressionMethods: []uint8{compressionNone}, + random: make([]byte, 32), + sessionId: make([]byte, 32), + ocspStapling: true, + scts: true, + serverName: hostnameInSNI(config.ServerName), + supportedCurves: config.curvePreferences(), + supportedPoints: []uint8{pointFormatUncompressed}, + secureRenegotiationSupported: true, + alpnProtocols: config.NextProtos, + supportedVersions: supportedVersions, + } + + if c.handshakes > 0 { + hello.secureRenegotiation = c.clientFinished[:] + } + + preferenceOrder := cipherSuitesPreferenceOrder + if !hasAESGCMHardwareSupport { + preferenceOrder = cipherSuitesPreferenceOrderNoAES + } + configCipherSuites := config.cipherSuites() + hello.cipherSuites = make([]uint16, 0, len(configCipherSuites)) + + for _, suiteId := range preferenceOrder { + suite := mutualCipherSuite(configCipherSuites, suiteId) + if suite == nil { + continue + } + // Don't advertise TLS 1.2-only cipher suites unless + // we're attempting TLS 1.2. + if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { + continue + } + hello.cipherSuites = append(hello.cipherSuites, suiteId) + } + + _, err := io.ReadFull(config.rand(), hello.random) + if err != nil { + return nil, nil, errors.New("tls: short read from Rand: " + err.Error()) + } + + // A random session ID is used to detect when the server accepted a ticket + // and is resuming a session (see RFC 5077). In TLS 1.3, it's always set as + // a compatibility measure (see RFC 8446, Section 4.1.2). + if _, err := io.ReadFull(config.rand(), hello.sessionId); err != nil { + return nil, nil, errors.New("tls: short read from Rand: " + err.Error()) + } + + if hello.vers >= VersionTLS12 { + hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms + } + + var params ecdheParameters + if hello.supportedVersions[0] == VersionTLS13 { + if hasAESGCMHardwareSupport { + hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...) + } else { + hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) + } + + curveID := config.curvePreferences()[0] + if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok { + return nil, nil, errors.New("tls: CurvePreferences includes unsupported curve") + } + params, err = generateECDHEParameters(config.rand(), curveID) + if err != nil { + return nil, nil, err + } + hello.keyShares = []keyShare{{group: curveID, data: params.PublicKey()}} + } + + return hello, params, nil +} + +func (c *Conn) clientHandshake(ctx context.Context) (err error) { + if c.config == nil { + c.config = defaultConfig() + } + + // This may be a renegotiation handshake, in which case some fields + // need to be reset. + c.didResume = false + + hello, ecdheParams, err := c.makeClientHello() + if err != nil { + return err + } + c.serverName = hello.serverName + + cacheKey, session, earlySecret, binderKey := c.loadSession(hello) + if cacheKey != "" && session != nil { + defer func() { + // If we got a handshake failure when resuming a session, throw away + // the session ticket. See RFC 5077, Section 3.2. + // + // RFC 8446 makes no mention of dropping tickets on failure, but it + // does require servers to abort on invalid binders, so we need to + // delete tickets to recover from a corrupted PSK. + if err != nil { + c.config.ClientSessionCache.Put(cacheKey, nil) + } + }() + } + + if _, err := c.writeRecord(recordTypeHandshake, hello.marshal()); err != nil { + return err + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + + serverHello, ok := msg.(*serverHelloMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(serverHello, msg) + } + + if err := c.pickTLSVersion(serverHello); err != nil { + return err + } + + // If we are negotiating a protocol version that's lower than what we + // support, check for the server downgrade canaries. + // See RFC 8446, Section 4.1.3. + maxVers := c.config.maxSupportedVersion() + tls12Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS12 + tls11Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS11 + if maxVers == VersionTLS13 && c.vers <= VersionTLS12 && (tls12Downgrade || tls11Downgrade) || + maxVers == VersionTLS12 && c.vers <= VersionTLS11 && tls11Downgrade { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: downgrade attempt detected, possibly due to a MitM attack or a broken middlebox") + } + + if c.vers == VersionTLS13 { + hs := &clientHandshakeStateTLS13{ + c: c, + ctx: ctx, + serverHello: serverHello, + hello: hello, + ecdheParams: ecdheParams, + session: session, + earlySecret: earlySecret, + binderKey: binderKey, + } + + // In TLS 1.3, session tickets are delivered after the handshake. + return hs.handshake() + } + + hs := &clientHandshakeState{ + c: c, + ctx: ctx, + serverHello: serverHello, + hello: hello, + session: session, + } + + if err := hs.handshake(); err != nil { + return err + } + + // If we had a successful handshake and hs.session is different from + // the one already cached - cache a new one. + if cacheKey != "" && hs.session != nil && session != hs.session { + c.config.ClientSessionCache.Put(cacheKey, hs.session) + } + + return nil +} + +func (c *Conn) loadSession(hello *clientHelloMsg) (cacheKey string, + session *ClientSessionState, earlySecret, binderKey []byte) { + if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { + return "", nil, nil, nil + } + + hello.ticketSupported = true + + if hello.supportedVersions[0] == VersionTLS13 { + // Require DHE on resumption as it guarantees forward secrecy against + // compromise of the session ticket key. See RFC 8446, Section 4.2.9. + hello.pskModes = []uint8{pskModeDHE} + } + + // Session resumption is not allowed if renegotiating because + // renegotiation is primarily used to allow a client to send a client + // certificate, which would be skipped if session resumption occurred. + if c.handshakes != 0 { + return "", nil, nil, nil + } + + // Try to resume a previously negotiated TLS session, if available. + cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) + session, ok := c.config.ClientSessionCache.Get(cacheKey) + if !ok || session == nil { + return cacheKey, nil, nil, nil + } + + // Check that version used for the previous session is still valid. + versOk := false + for _, v := range hello.supportedVersions { + if v == session.vers { + versOk = true + break + } + } + if !versOk { + return cacheKey, nil, nil, nil + } + + // Check that the cached server certificate is not expired, and that it's + // valid for the ServerName. This should be ensured by the cache key, but + // protect the application from a faulty ClientSessionCache implementation. + if !c.config.InsecureSkipVerify { + if len(session.verifiedChains) == 0 { + // The original connection had InsecureSkipVerify, while this doesn't. + return cacheKey, nil, nil, nil + } + serverCert := session.serverCertificates[0] + if c.config.time().After(serverCert.NotAfter) { + // Expired certificate, delete the entry. + c.config.ClientSessionCache.Put(cacheKey, nil) + return cacheKey, nil, nil, nil + } + if err := serverCert.VerifyHostname(c.config.ServerName); err != nil { + return cacheKey, nil, nil, nil + } + } + + if session.vers != VersionTLS13 { + // In TLS 1.2 the cipher suite must match the resumed session. Ensure we + // are still offering it. + if mutualCipherSuite(hello.cipherSuites, session.cipherSuite) == nil { + return cacheKey, nil, nil, nil + } + + hello.sessionTicket = session.sessionTicket + return + } + + // Check that the session ticket is not expired. + if c.config.time().After(session.useBy) { + c.config.ClientSessionCache.Put(cacheKey, nil) + return cacheKey, nil, nil, nil + } + + // In TLS 1.3 the KDF hash must match the resumed session. Ensure we + // offer at least one cipher suite with that hash. + cipherSuite := cipherSuiteTLS13ByID(session.cipherSuite) + if cipherSuite == nil { + return cacheKey, nil, nil, nil + } + cipherSuiteOk := false + for _, offeredID := range hello.cipherSuites { + offeredSuite := cipherSuiteTLS13ByID(offeredID) + if offeredSuite != nil && offeredSuite.hash == cipherSuite.hash { + cipherSuiteOk = true + break + } + } + if !cipherSuiteOk { + return cacheKey, nil, nil, nil + } + + // Set the pre_shared_key extension. See RFC 8446, Section 4.2.11.1. + ticketAge := uint32(c.config.time().Sub(session.receivedAt) / time.Millisecond) + identity := pskIdentity{ + label: session.sessionTicket, + obfuscatedTicketAge: ticketAge + session.ageAdd, + } + hello.pskIdentities = []pskIdentity{identity} + hello.pskBinders = [][]byte{make([]byte, cipherSuite.hash.Size())} + + // Compute the PSK binders. See RFC 8446, Section 4.2.11.2. + psk := cipherSuite.expandLabel(session.masterSecret, "resumption", + session.nonce, cipherSuite.hash.Size()) + earlySecret = cipherSuite.extract(psk, nil) + binderKey = cipherSuite.deriveSecret(earlySecret, resumptionBinderLabel, nil) + transcript := cipherSuite.hash.New() + transcript.Write(hello.marshalWithoutBinders()) + pskBinders := [][]byte{cipherSuite.finishedHash(binderKey, transcript)} + hello.updateBinders(pskBinders) + + return +} + +func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { + peerVersion := serverHello.vers + if serverHello.supportedVersion != 0 { + peerVersion = serverHello.supportedVersion + } + + vers, ok := c.config.mutualVersion([]uint16{peerVersion}) + if !ok { + c.sendAlert(alertProtocolVersion) + return fmt.Errorf("tls: server selected unsupported protocol version %x", peerVersion) + } + + c.vers = vers + c.haveVers = true + c.in.version = vers + c.out.version = vers + + return nil +} + +// Does the handshake, either a full one or resumes old session. Requires hs.c, +// hs.hello, hs.serverHello, and, optionally, hs.session to be set. +func (hs *clientHandshakeState) handshake() error { + c := hs.c + + isResume, err := hs.processServerHello() + if err != nil { + return err + } + + hs.finishedHash = newFinishedHash(c.vers, hs.suite) + + // No signatures of the handshake are needed in a resumption. + // Otherwise, in a full handshake, if we don't have any certificates + // configured then we will never send a CertificateVerify message and + // thus no signatures are needed in that case either. + if isResume || (len(c.config.Certificates) == 0 && c.config.GetClientCertificate == nil) { + hs.finishedHash.discardHandshakeBuffer() + } + + hs.finishedHash.Write(hs.hello.marshal()) + hs.finishedHash.Write(hs.serverHello.marshal()) + + c.buffering = true + c.didResume = isResume + if isResume { + if err := hs.establishKeys(); err != nil { + return err + } + if err := hs.readSessionTicket(); err != nil { + return err + } + if err := hs.readFinished(c.serverFinished[:]); err != nil { + return err + } + c.clientFinishedIsFirst = false + // Make sure the connection is still being verified whether or not this + // is a resumption. Resumptions currently don't reverify certificates so + // they don't call verifyServerCertificate. See Issue 31641. + if c.config.VerifyConnection != nil { + if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + if err := hs.sendFinished(c.clientFinished[:]); err != nil { + return err + } + if _, err := c.flush(); err != nil { + return err + } + } else { + if err := hs.doFullHandshake(); err != nil { + return err + } + if err := hs.establishKeys(); err != nil { + return err + } + if err := hs.sendFinished(c.clientFinished[:]); err != nil { + return err + } + if _, err := c.flush(); err != nil { + return err + } + c.clientFinishedIsFirst = true + if err := hs.readSessionTicket(); err != nil { + return err + } + if err := hs.readFinished(c.serverFinished[:]); err != nil { + return err + } + } + + c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random) + atomic.StoreUint32(&c.handshakeStatus, 1) + + return nil +} + +func (hs *clientHandshakeState) pickCipherSuite() error { + if hs.suite = mutualCipherSuite(hs.hello.cipherSuites, hs.serverHello.cipherSuite); hs.suite == nil { + hs.c.sendAlert(alertHandshakeFailure) + return errors.New("tls: server chose an unconfigured cipher suite") + } + + hs.c.cipherSuite = hs.suite.id + return nil +} + +func (hs *clientHandshakeState) doFullHandshake() error { + c := hs.c + + msg, err := c.readHandshake() + if err != nil { + return err + } + certMsg, ok := msg.(*certificateMsg) + if !ok || len(certMsg.certificates) == 0 { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) + } + hs.finishedHash.Write(certMsg.marshal()) + + msg, err = c.readHandshake() + if err != nil { + return err + } + + cs, ok := msg.(*certificateStatusMsg) + if ok { + // RFC4366 on Certificate Status Request: + // The server MAY return a "certificate_status" message. + + if !hs.serverHello.ocspStapling { + // If a server returns a "CertificateStatus" message, then the + // server MUST have included an extension of type "status_request" + // with empty "extension_data" in the extended server hello. + + c.sendAlert(alertUnexpectedMessage) + return errors.New("tls: received unexpected CertificateStatus message") + } + hs.finishedHash.Write(cs.marshal()) + + c.ocspResponse = cs.response + + msg, err = c.readHandshake() + if err != nil { + return err + } + } + + if c.handshakes == 0 { + // If this is the first handshake on a connection, process and + // (optionally) verify the server's certificates. + if err := c.verifyServerCertificate(certMsg.certificates); err != nil { + return err + } + } else { + // This is a renegotiation handshake. We require that the + // server's identity (i.e. leaf certificate) is unchanged and + // thus any previous trust decision is still valid. + // + // See https://mitls.org/pages/attacks/3SHAKE for the + // motivation behind this requirement. + if !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) { + c.sendAlert(alertBadCertificate) + return errors.New("tls: server's identity changed during renegotiation") + } + } + + keyAgreement := hs.suite.ka(c.vers) + + skx, ok := msg.(*serverKeyExchangeMsg) + if ok { + hs.finishedHash.Write(skx.marshal()) + err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx) + if err != nil { + c.sendAlert(alertUnexpectedMessage) + return err + } + + msg, err = c.readHandshake() + if err != nil { + return err + } + } + + var chainToSend *Certificate + var certRequested bool + certReq, ok := msg.(*certificateRequestMsg) + if ok { + certRequested = true + hs.finishedHash.Write(certReq.marshal()) + + cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq) + if chainToSend, err = c.getClientCertificate(cri); err != nil { + c.sendAlert(alertInternalError) + return err + } + + msg, err = c.readHandshake() + if err != nil { + return err + } + } + + shd, ok := msg.(*serverHelloDoneMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(shd, msg) + } + hs.finishedHash.Write(shd.marshal()) + + // If the server requested a certificate then we have to send a + // Certificate message, even if it's empty because we don't have a + // certificate to send. + if certRequested { + certMsg = new(certificateMsg) + certMsg.certificates = chainToSend.Certificate + hs.finishedHash.Write(certMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { + return err + } + } + + preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[0]) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + if ckx != nil { + hs.finishedHash.Write(ckx.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, ckx.marshal()); err != nil { + return err + } + } + + if chainToSend != nil && len(chainToSend.Certificate) > 0 { + certVerify := &certificateVerifyMsg{} + + key, ok := chainToSend.PrivateKey.(crypto.Signer) + if !ok { + c.sendAlert(alertInternalError) + return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) + } + + var sigType uint8 + var sigHash crypto.Hash + if c.vers >= VersionTLS12 { + signatureAlgorithm, err := selectSignatureScheme(c.vers, chainToSend, certReq.supportedSignatureAlgorithms) + if err != nil { + c.sendAlert(alertIllegalParameter) + return err + } + sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) + if err != nil { + return c.sendAlert(alertInternalError) + } + certVerify.hasSignatureAlgorithm = true + certVerify.signatureAlgorithm = signatureAlgorithm + } else { + sigType, sigHash, err = legacyTypeAndHashFromPublicKey(key.Public()) + if err != nil { + c.sendAlert(alertIllegalParameter) + return err + } + } + + signed := hs.finishedHash.hashForClientCertificate(sigType, sigHash, hs.masterSecret) + signOpts := crypto.SignerOpts(sigHash) + if sigType == signatureRSAPSS { + signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} + } + certVerify.signature, err = key.Sign(c.config.rand(), signed, signOpts) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + + hs.finishedHash.Write(certVerify.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certVerify.marshal()); err != nil { + return err + } + } + + hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) + if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil { + c.sendAlert(alertInternalError) + return errors.New("tls: failed to write to key log: " + err.Error()) + } + + hs.finishedHash.discardHandshakeBuffer() + + return nil +} + +func (hs *clientHandshakeState) establishKeys() error { + c := hs.c + + clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := + keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) + var clientCipher, serverCipher interface{} + var clientHash, serverHash hash.Hash + if hs.suite.cipher != nil { + clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) + clientHash = hs.suite.mac(clientMAC) + serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) + serverHash = hs.suite.mac(serverMAC) + } else { + clientCipher = hs.suite.aead(clientKey, clientIV) + serverCipher = hs.suite.aead(serverKey, serverIV) + } + + c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) + c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) + return nil +} + +func (hs *clientHandshakeState) serverResumedSession() bool { + // If the server responded with the same sessionId then it means the + // sessionTicket is being used to resume a TLS session. + return hs.session != nil && hs.hello.sessionId != nil && + bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) +} + +func (hs *clientHandshakeState) processServerHello() (bool, error) { + c := hs.c + + if err := hs.pickCipherSuite(); err != nil { + return false, err + } + + if hs.serverHello.compressionMethod != compressionNone { + c.sendAlert(alertUnexpectedMessage) + return false, errors.New("tls: server selected unsupported compression format") + } + + if c.handshakes == 0 && hs.serverHello.secureRenegotiationSupported { + c.secureRenegotiation = true + if len(hs.serverHello.secureRenegotiation) != 0 { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: initial handshake had non-empty renegotiation extension") + } + } + + if c.handshakes > 0 && c.secureRenegotiation { + var expectedSecureRenegotiation [24]byte + copy(expectedSecureRenegotiation[:], c.clientFinished[:]) + copy(expectedSecureRenegotiation[12:], c.serverFinished[:]) + if !bytes.Equal(hs.serverHello.secureRenegotiation, expectedSecureRenegotiation[:]) { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: incorrect renegotiation extension contents") + } + } + + if err := checkALPN(hs.hello.alpnProtocols, hs.serverHello.alpnProtocol); err != nil { + c.sendAlert(alertUnsupportedExtension) + return false, err + } + c.clientProtocol = hs.serverHello.alpnProtocol + + c.scts = hs.serverHello.scts + + if !hs.serverResumedSession() { + return false, nil + } + + if hs.session.vers != c.vers { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: server resumed a session with a different version") + } + + if hs.session.cipherSuite != hs.suite.id { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: server resumed a session with a different cipher suite") + } + + // Restore masterSecret, peerCerts, and ocspResponse from previous state + hs.masterSecret = hs.session.masterSecret + c.peerCertificates = hs.session.serverCertificates + c.verifiedChains = hs.session.verifiedChains + c.ocspResponse = hs.session.ocspResponse + // Let the ServerHello SCTs override the session SCTs from the original + // connection, if any are provided + if len(c.scts) == 0 && len(hs.session.scts) != 0 { + c.scts = hs.session.scts + } + + return true, nil +} + +// checkALPN ensure that the server's choice of ALPN protocol is compatible with +// the protocols that we advertised in the Client Hello. +func checkALPN(clientProtos []string, serverProto string) error { + if serverProto == "" { + return nil + } + if len(clientProtos) == 0 { + return errors.New("tls: server advertised unrequested ALPN extension") + } + for _, proto := range clientProtos { + if proto == serverProto { + return nil + } + } + return errors.New("tls: server selected unadvertised ALPN protocol") +} + +func (hs *clientHandshakeState) readFinished(out []byte) error { + c := hs.c + + if err := c.readChangeCipherSpec(); err != nil { + return err + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + serverFinished, ok := msg.(*finishedMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(serverFinished, msg) + } + + verify := hs.finishedHash.serverSum(hs.masterSecret) + if len(verify) != len(serverFinished.verifyData) || + subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: server's Finished message was incorrect") + } + hs.finishedHash.Write(serverFinished.marshal()) + copy(out, verify) + return nil +} + +func (hs *clientHandshakeState) readSessionTicket() error { + if !hs.serverHello.ticketSupported { + return nil + } + + c := hs.c + msg, err := c.readHandshake() + if err != nil { + return err + } + sessionTicketMsg, ok := msg.(*newSessionTicketMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(sessionTicketMsg, msg) + } + hs.finishedHash.Write(sessionTicketMsg.marshal()) + + hs.session = &ClientSessionState{ + sessionTicket: sessionTicketMsg.ticket, + vers: c.vers, + cipherSuite: hs.suite.id, + masterSecret: hs.masterSecret, + serverCertificates: c.peerCertificates, + verifiedChains: c.verifiedChains, + receivedAt: c.config.time(), + ocspResponse: c.ocspResponse, + scts: c.scts, + } + + return nil +} + +func (hs *clientHandshakeState) sendFinished(out []byte) error { + c := hs.c + + if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { + return err + } + + finished := new(finishedMsg) + finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) + hs.finishedHash.Write(finished.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { + return err + } + copy(out, finished.verifyData) + return nil +} + +// verifyServerCertificate parses and verifies the provided chain, setting +// c.verifiedChains and c.peerCertificates or sending the appropriate alert. +func (c *Conn) verifyServerCertificate(certificates [][]byte) error { + certs := make([]*x509.Certificate, len(certificates)) + for i, asn1Data := range certificates { + cert, err := x509.ParseCertificate(asn1Data) + if err != nil { + c.sendAlert(alertBadCertificate) + return errors.New("tls: failed to parse certificate from server: " + err.Error()) + } + certs[i] = cert + } + + if !c.config.InsecureSkipVerify { + opts := x509.VerifyOptions{ + Roots: c.config.RootCAs, + CurrentTime: c.config.time(), + DNSName: c.config.ServerName, + Intermediates: x509.NewCertPool(), + } + for _, cert := range certs[1:] { + opts.Intermediates.AddCert(cert) + } + var err error + c.verifiedChains, err = certs[0].Verify(opts) + if err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + + switch certs[0].PublicKey.(type) { + case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey: + break + default: + c.sendAlert(alertUnsupportedCertificate) + return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) + } + + c.peerCertificates = certs + + if c.config.VerifyPeerCertificate != nil { + if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + + if c.config.VerifyConnection != nil { + if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + + return nil +} + +// certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS +// <= 1.2 CertificateRequest, making an effort to fill in missing information. +func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo { + cri := &CertificateRequestInfo{ + AcceptableCAs: certReq.certificateAuthorities, + Version: vers, + ctx: ctx, + } + + var rsaAvail, ecAvail bool + for _, certType := range certReq.certificateTypes { + switch certType { + case certTypeRSASign: + rsaAvail = true + case certTypeECDSASign: + ecAvail = true + } + } + + if !certReq.hasSignatureAlgorithm { + // Prior to TLS 1.2, signature schemes did not exist. In this case we + // make up a list based on the acceptable certificate types, to help + // GetClientCertificate and SupportsCertificate select the right certificate. + // The hash part of the SignatureScheme is a lie here, because + // TLS 1.0 and 1.1 always use MD5+SHA1 for RSA and SHA1 for ECDSA. + switch { + case rsaAvail && ecAvail: + cri.SignatureSchemes = []SignatureScheme{ + ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, + PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1, + } + case rsaAvail: + cri.SignatureSchemes = []SignatureScheme{ + PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1, + } + case ecAvail: + cri.SignatureSchemes = []SignatureScheme{ + ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, + } + } + return cri + } + + // Filter the signature schemes based on the certificate types. + // See RFC 5246, Section 7.4.4 (where it calls this "somewhat complicated"). + cri.SignatureSchemes = make([]SignatureScheme, 0, len(certReq.supportedSignatureAlgorithms)) + for _, sigScheme := range certReq.supportedSignatureAlgorithms { + sigType, _, err := typeAndHashFromSignatureScheme(sigScheme) + if err != nil { + continue + } + switch sigType { + case signatureECDSA, signatureEd25519: + if ecAvail { + cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme) + } + case signatureRSAPSS, signaturePKCS1v15: + if rsaAvail { + cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme) + } + } + } + + return cri +} + +func (c *Conn) getClientCertificate(cri *CertificateRequestInfo) (*Certificate, error) { + if c.config.GetClientCertificate != nil { + return c.config.GetClientCertificate(cri) + } + + for _, chain := range c.config.Certificates { + if err := cri.SupportsCertificate(&chain); err != nil { + continue + } + return &chain, nil + } + + // No acceptable certificate found. Don't send a certificate. + return new(Certificate), nil +} + +// clientSessionCacheKey returns a key used to cache sessionTickets that could +// be used to resume previously negotiated TLS sessions with a server. +func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { + if len(config.ServerName) > 0 { + return config.ServerName + } + return serverAddr.String() +} + +// hostnameInSNI converts name into an appropriate hostname for SNI. +// Literal IP addresses and absolute FQDNs are not permitted as SNI values. +// See RFC 6066, Section 3. +func hostnameInSNI(name string) string { + host := name + if len(host) > 0 && host[0] == '[' && host[len(host)-1] == ']' { + host = host[1 : len(host)-1] + } + if i := strings.LastIndex(host, "%"); i > 0 { + host = host[:i] + } + if net.ParseIP(host) != nil { + return "" + } + for len(name) > 0 && name[len(name)-1] == '.' { + name = name[:len(name)-1] + } + return name +} diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go new file mode 100644 index 0000000..b6eb488 --- /dev/null +++ b/src/crypto/tls/handshake_client_test.go @@ -0,0 +1,2597 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "context" + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "encoding/binary" + "encoding/pem" + "errors" + "fmt" + "io" + "math/big" + "net" + "os" + "os/exec" + "path/filepath" + "reflect" + "runtime" + "strconv" + "strings" + "testing" + "time" +) + +// Note: see comment in handshake_test.go for details of how the reference +// tests work. + +// opensslInputEvent enumerates possible inputs that can be sent to an `openssl +// s_client` process. +type opensslInputEvent int + +const ( + // opensslRenegotiate causes OpenSSL to request a renegotiation of the + // connection. + opensslRenegotiate opensslInputEvent = iota + + // opensslSendBanner causes OpenSSL to send the contents of + // opensslSentinel on the connection. + opensslSendSentinel + + // opensslKeyUpdate causes OpenSSL to send a key update message to the + // client and request one back. + opensslKeyUpdate +) + +const opensslSentinel = "SENTINEL\n" + +type opensslInput chan opensslInputEvent + +func (i opensslInput) Read(buf []byte) (n int, err error) { + for event := range i { + switch event { + case opensslRenegotiate: + return copy(buf, []byte("R\n")), nil + case opensslKeyUpdate: + return copy(buf, []byte("K\n")), nil + case opensslSendSentinel: + return copy(buf, []byte(opensslSentinel)), nil + default: + panic("unknown event") + } + } + + return 0, io.EOF +} + +// opensslOutputSink is an io.Writer that receives the stdout and stderr from an +// `openssl` process and sends a value to handshakeComplete or readKeyUpdate +// when certain messages are seen. +type opensslOutputSink struct { + handshakeComplete chan struct{} + readKeyUpdate chan struct{} + all []byte + line []byte +} + +func newOpensslOutputSink() *opensslOutputSink { + return &opensslOutputSink{make(chan struct{}), make(chan struct{}), nil, nil} +} + +// opensslEndOfHandshake is a message that the “openssl s_server” tool will +// print when a handshake completes if run with “-state”. +const opensslEndOfHandshake = "SSL_accept:SSLv3/TLS write finished" + +// opensslReadKeyUpdate is a message that the “openssl s_server” tool will +// print when a KeyUpdate message is received if run with “-state”. +const opensslReadKeyUpdate = "SSL_accept:TLSv1.3 read client key update" + +func (o *opensslOutputSink) Write(data []byte) (n int, err error) { + o.line = append(o.line, data...) + o.all = append(o.all, data...) + + for { + i := bytes.IndexByte(o.line, '\n') + if i < 0 { + break + } + + if bytes.Equal([]byte(opensslEndOfHandshake), o.line[:i]) { + o.handshakeComplete <- struct{}{} + } + if bytes.Equal([]byte(opensslReadKeyUpdate), o.line[:i]) { + o.readKeyUpdate <- struct{}{} + } + o.line = o.line[i+1:] + } + + return len(data), nil +} + +func (o *opensslOutputSink) String() string { + return string(o.all) +} + +// clientTest represents a test of the TLS client handshake against a reference +// implementation. +type clientTest struct { + // name is a freeform string identifying the test and the file in which + // the expected results will be stored. + name string + // args, if not empty, contains a series of arguments for the + // command to run for the reference server. + args []string + // config, if not nil, contains a custom Config to use for this test. + config *Config + // cert, if not empty, contains a DER-encoded certificate for the + // reference server. + cert []byte + // key, if not nil, contains either a *rsa.PrivateKey, ed25519.PrivateKey or + // *ecdsa.PrivateKey which is the private key for the reference server. + key interface{} + // extensions, if not nil, contains a list of extension data to be returned + // from the ServerHello. The data should be in standard TLS format with + // a 2-byte uint16 type, 2-byte data length, followed by the extension data. + extensions [][]byte + // validate, if not nil, is a function that will be called with the + // ConnectionState of the resulting connection. It returns a non-nil + // error if the ConnectionState is unacceptable. + validate func(ConnectionState) error + // numRenegotiations is the number of times that the connection will be + // renegotiated. + numRenegotiations int + // renegotiationExpectedToFail, if not zero, is the number of the + // renegotiation attempt that is expected to fail. + renegotiationExpectedToFail int + // checkRenegotiationError, if not nil, is called with any error + // arising from renegotiation. It can map expected errors to nil to + // ignore them. + checkRenegotiationError func(renegotiationNum int, err error) error + // sendKeyUpdate will cause the server to send a KeyUpdate message. + sendKeyUpdate bool +} + +var serverCommand = []string{"openssl", "s_server", "-no_ticket", "-num_tickets", "0"} + +// connFromCommand starts the reference server process, connects to it and +// returns a recordingConn for the connection. The stdin return value is an +// opensslInput for the stdin of the child process. It must be closed before +// Waiting for child. +func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, stdin opensslInput, stdout *opensslOutputSink, err error) { + cert := testRSACertificate + if len(test.cert) > 0 { + cert = test.cert + } + certPath := tempFile(string(cert)) + defer os.Remove(certPath) + + var key interface{} = testRSAPrivateKey + if test.key != nil { + key = test.key + } + derBytes, err := x509.MarshalPKCS8PrivateKey(key) + if err != nil { + panic(err) + } + + var pemOut bytes.Buffer + pem.Encode(&pemOut, &pem.Block{Type: "PRIVATE KEY", Bytes: derBytes}) + + keyPath := tempFile(pemOut.String()) + defer os.Remove(keyPath) + + var command []string + command = append(command, serverCommand...) + command = append(command, test.args...) + command = append(command, "-cert", certPath, "-certform", "DER", "-key", keyPath) + // serverPort contains the port that OpenSSL will listen on. OpenSSL + // can't take "0" as an argument here so we have to pick a number and + // hope that it's not in use on the machine. Since this only occurs + // when -update is given and thus when there's a human watching the + // test, this isn't too bad. + const serverPort = 24323 + command = append(command, "-accept", strconv.Itoa(serverPort)) + + if len(test.extensions) > 0 { + var serverInfo bytes.Buffer + for _, ext := range test.extensions { + pem.Encode(&serverInfo, &pem.Block{ + Type: fmt.Sprintf("SERVERINFO FOR EXTENSION %d", binary.BigEndian.Uint16(ext)), + Bytes: ext, + }) + } + serverInfoPath := tempFile(serverInfo.String()) + defer os.Remove(serverInfoPath) + command = append(command, "-serverinfo", serverInfoPath) + } + + if test.numRenegotiations > 0 || test.sendKeyUpdate { + found := false + for _, flag := range command[1:] { + if flag == "-state" { + found = true + break + } + } + + if !found { + panic("-state flag missing to OpenSSL, you need this if testing renegotiation or KeyUpdate") + } + } + + cmd := exec.Command(command[0], command[1:]...) + stdin = opensslInput(make(chan opensslInputEvent)) + cmd.Stdin = stdin + out := newOpensslOutputSink() + cmd.Stdout = out + cmd.Stderr = out + if err := cmd.Start(); err != nil { + return nil, nil, nil, nil, err + } + + // OpenSSL does print an "ACCEPT" banner, but it does so *before* + // opening the listening socket, so we can't use that to wait until it + // has started listening. Thus we are forced to poll until we get a + // connection. + var tcpConn net.Conn + for i := uint(0); i < 5; i++ { + tcpConn, err = net.DialTCP("tcp", nil, &net.TCPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: serverPort, + }) + if err == nil { + break + } + time.Sleep((1 << i) * 5 * time.Millisecond) + } + if err != nil { + close(stdin) + cmd.Process.Kill() + err = fmt.Errorf("error connecting to the OpenSSL server: %v (%v)\n\n%s", err, cmd.Wait(), out) + return nil, nil, nil, nil, err + } + + record := &recordingConn{ + Conn: tcpConn, + } + + return record, cmd, stdin, out, nil +} + +func (test *clientTest) dataPath() string { + return filepath.Join("testdata", "Client-"+test.name) +} + +func (test *clientTest) loadData() (flows [][]byte, err error) { + in, err := os.Open(test.dataPath()) + if err != nil { + return nil, err + } + defer in.Close() + return parseTestData(in) +} + +func (test *clientTest) run(t *testing.T, write bool) { + var clientConn, serverConn net.Conn + var recordingConn *recordingConn + var childProcess *exec.Cmd + var stdin opensslInput + var stdout *opensslOutputSink + + if write { + var err error + recordingConn, childProcess, stdin, stdout, err = test.connFromCommand() + if err != nil { + t.Fatalf("Failed to start subcommand: %s", err) + } + clientConn = recordingConn + defer func() { + if t.Failed() { + t.Logf("OpenSSL output:\n\n%s", stdout.all) + } + }() + } else { + clientConn, serverConn = localPipe(t) + } + + doneChan := make(chan bool) + defer func() { + clientConn.Close() + <-doneChan + }() + go func() { + defer close(doneChan) + + config := test.config + if config == nil { + config = testConfig + } + client := Client(clientConn, config) + defer client.Close() + + if _, err := client.Write([]byte("hello\n")); err != nil { + t.Errorf("Client.Write failed: %s", err) + return + } + + for i := 1; i <= test.numRenegotiations; i++ { + // The initial handshake will generate a + // handshakeComplete signal which needs to be quashed. + if i == 1 && write { + <-stdout.handshakeComplete + } + + // OpenSSL will try to interleave application data and + // a renegotiation if we send both concurrently. + // Therefore: ask OpensSSL to start a renegotiation, run + // a goroutine to call client.Read and thus process the + // renegotiation request, watch for OpenSSL's stdout to + // indicate that the handshake is complete and, + // finally, have OpenSSL write something to cause + // client.Read to complete. + if write { + stdin <- opensslRenegotiate + } + + signalChan := make(chan struct{}) + + go func() { + defer close(signalChan) + + buf := make([]byte, 256) + n, err := client.Read(buf) + + if test.checkRenegotiationError != nil { + newErr := test.checkRenegotiationError(i, err) + if err != nil && newErr == nil { + return + } + err = newErr + } + + if err != nil { + t.Errorf("Client.Read failed after renegotiation #%d: %s", i, err) + return + } + + buf = buf[:n] + if !bytes.Equal([]byte(opensslSentinel), buf) { + t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) + } + + if expected := i + 1; client.handshakes != expected { + t.Errorf("client should have recorded %d handshakes, but believes that %d have occurred", expected, client.handshakes) + } + }() + + if write && test.renegotiationExpectedToFail != i { + <-stdout.handshakeComplete + stdin <- opensslSendSentinel + } + <-signalChan + } + + if test.sendKeyUpdate { + if write { + <-stdout.handshakeComplete + stdin <- opensslKeyUpdate + } + + doneRead := make(chan struct{}) + + go func() { + defer close(doneRead) + + buf := make([]byte, 256) + n, err := client.Read(buf) + + if err != nil { + t.Errorf("Client.Read failed after KeyUpdate: %s", err) + return + } + + buf = buf[:n] + if !bytes.Equal([]byte(opensslSentinel), buf) { + t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) + } + }() + + if write { + // There's no real reason to wait for the client KeyUpdate to + // send data with the new server keys, except that s_server + // drops writes if they are sent at the wrong time. + <-stdout.readKeyUpdate + stdin <- opensslSendSentinel + } + <-doneRead + + if _, err := client.Write([]byte("hello again\n")); err != nil { + t.Errorf("Client.Write failed: %s", err) + return + } + } + + if test.validate != nil { + if err := test.validate(client.ConnectionState()); err != nil { + t.Errorf("validate callback returned error: %s", err) + } + } + + // If the server sent us an alert after our last flight, give it a + // chance to arrive. + if write && test.renegotiationExpectedToFail == 0 { + if err := peekError(client); err != nil { + t.Errorf("final Read returned an error: %s", err) + } + } + }() + + if !write { + flows, err := test.loadData() + if err != nil { + t.Fatalf("%s: failed to load data from %s: %v", test.name, test.dataPath(), err) + } + for i, b := range flows { + if i%2 == 1 { + if *fast { + serverConn.SetWriteDeadline(time.Now().Add(1 * time.Second)) + } else { + serverConn.SetWriteDeadline(time.Now().Add(1 * time.Minute)) + } + serverConn.Write(b) + continue + } + bb := make([]byte, len(b)) + if *fast { + serverConn.SetReadDeadline(time.Now().Add(1 * time.Second)) + } else { + serverConn.SetReadDeadline(time.Now().Add(1 * time.Minute)) + } + _, err := io.ReadFull(serverConn, bb) + if err != nil { + t.Fatalf("%s, flow %d: %s", test.name, i+1, err) + } + if !bytes.Equal(b, bb) { + t.Fatalf("%s, flow %d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b) + } + } + } + + <-doneChan + if !write { + serverConn.Close() + } + + if write { + path := test.dataPath() + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + t.Fatalf("Failed to create output file: %s", err) + } + defer out.Close() + recordingConn.Close() + close(stdin) + childProcess.Process.Kill() + childProcess.Wait() + if len(recordingConn.flows) < 3 { + t.Fatalf("Client connection didn't work") + } + recordingConn.WriteTo(out) + t.Logf("Wrote %s\n", path) + } +} + +// peekError does a read with a short timeout to check if the next read would +// cause an error, for example if there is an alert waiting on the wire. +func peekError(conn net.Conn) error { + conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) + if n, err := conn.Read(make([]byte, 1)); n != 0 { + return errors.New("unexpectedly read data") + } else if err != nil { + if netErr, ok := err.(net.Error); !ok || !netErr.Timeout() { + return err + } + } + return nil +} + +func runClientTestForVersion(t *testing.T, template *clientTest, version, option string) { + // Make a deep copy of the template before going parallel. + test := *template + if template.config != nil { + test.config = template.config.Clone() + } + test.name = version + "-" + test.name + test.args = append([]string{option}, test.args...) + + runTestAndUpdateIfNeeded(t, version, test.run, false) +} + +func runClientTestTLS10(t *testing.T, template *clientTest) { + runClientTestForVersion(t, template, "TLSv10", "-tls1") +} + +func runClientTestTLS11(t *testing.T, template *clientTest) { + runClientTestForVersion(t, template, "TLSv11", "-tls1_1") +} + +func runClientTestTLS12(t *testing.T, template *clientTest) { + runClientTestForVersion(t, template, "TLSv12", "-tls1_2") +} + +func runClientTestTLS13(t *testing.T, template *clientTest) { + runClientTestForVersion(t, template, "TLSv13", "-tls1_3") +} + +func TestHandshakeClientRSARC4(t *testing.T) { + test := &clientTest{ + name: "RSA-RC4", + args: []string{"-cipher", "RC4-SHA"}, + } + runClientTestTLS10(t, test) + runClientTestTLS11(t, test) + runClientTestTLS12(t, test) +} + +func TestHandshakeClientRSAAES128GCM(t *testing.T) { + test := &clientTest{ + name: "AES128-GCM-SHA256", + args: []string{"-cipher", "AES128-GCM-SHA256"}, + } + runClientTestTLS12(t, test) +} + +func TestHandshakeClientRSAAES256GCM(t *testing.T) { + test := &clientTest{ + name: "AES256-GCM-SHA384", + args: []string{"-cipher", "AES256-GCM-SHA384"}, + } + runClientTestTLS12(t, test) +} + +func TestHandshakeClientECDHERSAAES(t *testing.T) { + test := &clientTest{ + name: "ECDHE-RSA-AES", + args: []string{"-cipher", "ECDHE-RSA-AES128-SHA"}, + } + runClientTestTLS10(t, test) + runClientTestTLS11(t, test) + runClientTestTLS12(t, test) +} + +func TestHandshakeClientECDHEECDSAAES(t *testing.T) { + test := &clientTest{ + name: "ECDHE-ECDSA-AES", + args: []string{"-cipher", "ECDHE-ECDSA-AES128-SHA"}, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + runClientTestTLS10(t, test) + runClientTestTLS11(t, test) + runClientTestTLS12(t, test) +} + +func TestHandshakeClientECDHEECDSAAESGCM(t *testing.T) { + test := &clientTest{ + name: "ECDHE-ECDSA-AES-GCM", + args: []string{"-cipher", "ECDHE-ECDSA-AES128-GCM-SHA256"}, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + runClientTestTLS12(t, test) +} + +func TestHandshakeClientAES256GCMSHA384(t *testing.T) { + test := &clientTest{ + name: "ECDHE-ECDSA-AES256-GCM-SHA384", + args: []string{"-cipher", "ECDHE-ECDSA-AES256-GCM-SHA384"}, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + runClientTestTLS12(t, test) +} + +func TestHandshakeClientAES128CBCSHA256(t *testing.T) { + test := &clientTest{ + name: "AES128-SHA256", + args: []string{"-cipher", "AES128-SHA256"}, + } + runClientTestTLS12(t, test) +} + +func TestHandshakeClientECDHERSAAES128CBCSHA256(t *testing.T) { + test := &clientTest{ + name: "ECDHE-RSA-AES128-SHA256", + args: []string{"-cipher", "ECDHE-RSA-AES128-SHA256"}, + } + runClientTestTLS12(t, test) +} + +func TestHandshakeClientECDHEECDSAAES128CBCSHA256(t *testing.T) { + test := &clientTest{ + name: "ECDHE-ECDSA-AES128-SHA256", + args: []string{"-cipher", "ECDHE-ECDSA-AES128-SHA256"}, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + runClientTestTLS12(t, test) +} + +func TestHandshakeClientX25519(t *testing.T) { + config := testConfig.Clone() + config.CurvePreferences = []CurveID{X25519} + + test := &clientTest{ + name: "X25519-ECDHE", + args: []string{"-cipher", "ECDHE-RSA-AES128-GCM-SHA256", "-curves", "X25519"}, + config: config, + } + + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) +} + +func TestHandshakeClientP256(t *testing.T) { + config := testConfig.Clone() + config.CurvePreferences = []CurveID{CurveP256} + + test := &clientTest{ + name: "P256-ECDHE", + args: []string{"-cipher", "ECDHE-RSA-AES128-GCM-SHA256", "-curves", "P-256"}, + config: config, + } + + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) +} + +func TestHandshakeClientHelloRetryRequest(t *testing.T) { + config := testConfig.Clone() + config.CurvePreferences = []CurveID{X25519, CurveP256} + + test := &clientTest{ + name: "HelloRetryRequest", + args: []string{"-cipher", "ECDHE-RSA-AES128-GCM-SHA256", "-curves", "P-256"}, + config: config, + } + + runClientTestTLS13(t, test) +} + +func TestHandshakeClientECDHERSAChaCha20(t *testing.T) { + config := testConfig.Clone() + config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305} + + test := &clientTest{ + name: "ECDHE-RSA-CHACHA20-POLY1305", + args: []string{"-cipher", "ECDHE-RSA-CHACHA20-POLY1305"}, + config: config, + } + + runClientTestTLS12(t, test) +} + +func TestHandshakeClientECDHEECDSAChaCha20(t *testing.T) { + config := testConfig.Clone() + config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305} + + test := &clientTest{ + name: "ECDHE-ECDSA-CHACHA20-POLY1305", + args: []string{"-cipher", "ECDHE-ECDSA-CHACHA20-POLY1305"}, + config: config, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + + runClientTestTLS12(t, test) +} + +func TestHandshakeClientAES128SHA256(t *testing.T) { + test := &clientTest{ + name: "AES128-SHA256", + args: []string{"-ciphersuites", "TLS_AES_128_GCM_SHA256"}, + } + runClientTestTLS13(t, test) +} +func TestHandshakeClientAES256SHA384(t *testing.T) { + test := &clientTest{ + name: "AES256-SHA384", + args: []string{"-ciphersuites", "TLS_AES_256_GCM_SHA384"}, + } + runClientTestTLS13(t, test) +} +func TestHandshakeClientCHACHA20SHA256(t *testing.T) { + test := &clientTest{ + name: "CHACHA20-SHA256", + args: []string{"-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + } + runClientTestTLS13(t, test) +} + +func TestHandshakeClientECDSATLS13(t *testing.T) { + test := &clientTest{ + name: "ECDSA", + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + runClientTestTLS13(t, test) +} + +func TestHandshakeClientEd25519(t *testing.T) { + test := &clientTest{ + name: "Ed25519", + cert: testEd25519Certificate, + key: testEd25519PrivateKey, + } + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) + + config := testConfig.Clone() + cert, _ := X509KeyPair([]byte(clientEd25519CertificatePEM), []byte(clientEd25519KeyPEM)) + config.Certificates = []Certificate{cert} + + test = &clientTest{ + name: "ClientCert-Ed25519", + args: []string{"-Verify", "1"}, + config: config, + } + + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) +} + +func TestHandshakeClientCertRSA(t *testing.T) { + config := testConfig.Clone() + cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM)) + config.Certificates = []Certificate{cert} + + test := &clientTest{ + name: "ClientCert-RSA-RSA", + args: []string{"-cipher", "AES128", "-Verify", "1"}, + config: config, + } + + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) + + test = &clientTest{ + name: "ClientCert-RSA-ECDSA", + args: []string{"-cipher", "ECDHE-ECDSA-AES128-SHA", "-Verify", "1"}, + config: config, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) + + test = &clientTest{ + name: "ClientCert-RSA-AES256-GCM-SHA384", + args: []string{"-cipher", "ECDHE-RSA-AES256-GCM-SHA384", "-Verify", "1"}, + config: config, + cert: testRSACertificate, + key: testRSAPrivateKey, + } + + runClientTestTLS12(t, test) +} + +func TestHandshakeClientCertECDSA(t *testing.T) { + config := testConfig.Clone() + cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM)) + config.Certificates = []Certificate{cert} + + test := &clientTest{ + name: "ClientCert-ECDSA-RSA", + args: []string{"-cipher", "AES128", "-Verify", "1"}, + config: config, + } + + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) + + test = &clientTest{ + name: "ClientCert-ECDSA-ECDSA", + args: []string{"-cipher", "ECDHE-ECDSA-AES128-SHA", "-Verify", "1"}, + config: config, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) +} + +// TestHandshakeClientCertRSAPSS tests rsa_pss_rsae_sha256 signatures from both +// client and server certificates. It also serves from both sides a certificate +// signed itself with RSA-PSS, mostly to check that crypto/x509 chain validation +// works. +func TestHandshakeClientCertRSAPSS(t *testing.T) { + cert, err := x509.ParseCertificate(testRSAPSSCertificate) + if err != nil { + panic(err) + } + rootCAs := x509.NewCertPool() + rootCAs.AddCert(cert) + + config := testConfig.Clone() + // Use GetClientCertificate to bypass the client certificate selection logic. + config.GetClientCertificate = func(*CertificateRequestInfo) (*Certificate, error) { + return &Certificate{ + Certificate: [][]byte{testRSAPSSCertificate}, + PrivateKey: testRSAPrivateKey, + }, nil + } + config.RootCAs = rootCAs + + test := &clientTest{ + name: "ClientCert-RSA-RSAPSS", + args: []string{"-cipher", "AES128", "-Verify", "1", "-client_sigalgs", + "rsa_pss_rsae_sha256", "-sigalgs", "rsa_pss_rsae_sha256"}, + config: config, + cert: testRSAPSSCertificate, + key: testRSAPrivateKey, + } + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) +} + +func TestHandshakeClientCertRSAPKCS1v15(t *testing.T) { + config := testConfig.Clone() + cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM)) + config.Certificates = []Certificate{cert} + + test := &clientTest{ + name: "ClientCert-RSA-RSAPKCS1v15", + args: []string{"-cipher", "AES128", "-Verify", "1", "-client_sigalgs", + "rsa_pkcs1_sha256", "-sigalgs", "rsa_pkcs1_sha256"}, + config: config, + } + + runClientTestTLS12(t, test) +} + +func TestClientKeyUpdate(t *testing.T) { + test := &clientTest{ + name: "KeyUpdate", + args: []string{"-state"}, + sendKeyUpdate: true, + } + runClientTestTLS13(t, test) +} + +func TestResumption(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testResumption(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testResumption(t, VersionTLS13) }) +} + +func testResumption(t *testing.T, version uint16) { + if testing.Short() { + t.Skip("skipping in -short mode") + } + serverConfig := &Config{ + MaxVersion: version, + CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, + Certificates: testConfig.Certificates, + } + + issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + if err != nil { + panic(err) + } + + rootCAs := x509.NewCertPool() + rootCAs.AddCert(issuer) + + clientConfig := &Config{ + MaxVersion: version, + CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + ClientSessionCache: NewLRUClientSessionCache(32), + RootCAs: rootCAs, + ServerName: "example.golang", + } + + testResumeState := func(test string, didResume bool) { + _, hs, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("%s: handshake failed: %s", test, err) + } + if hs.DidResume != didResume { + t.Fatalf("%s resumed: %v, expected: %v", test, hs.DidResume, didResume) + } + if didResume && (hs.PeerCertificates == nil || hs.VerifiedChains == nil) { + t.Fatalf("expected non-nil certificates after resumption. Got peerCertificates: %#v, verifiedCertificates: %#v", hs.PeerCertificates, hs.VerifiedChains) + } + if got, want := hs.ServerName, clientConfig.ServerName; got != want { + t.Errorf("%s: server name %s, want %s", test, got, want) + } + } + + getTicket := func() []byte { + return clientConfig.ClientSessionCache.(*lruSessionCache).q.Front().Value.(*lruSessionCacheEntry).state.sessionTicket + } + deleteTicket := func() { + ticketKey := clientConfig.ClientSessionCache.(*lruSessionCache).q.Front().Value.(*lruSessionCacheEntry).sessionKey + clientConfig.ClientSessionCache.Put(ticketKey, nil) + } + corruptTicket := func() { + clientConfig.ClientSessionCache.(*lruSessionCache).q.Front().Value.(*lruSessionCacheEntry).state.masterSecret[0] ^= 0xff + } + randomKey := func() [32]byte { + var k [32]byte + if _, err := io.ReadFull(serverConfig.rand(), k[:]); err != nil { + t.Fatalf("Failed to read new SessionTicketKey: %s", err) + } + return k + } + + testResumeState("Handshake", false) + ticket := getTicket() + testResumeState("Resume", true) + if !bytes.Equal(ticket, getTicket()) && version != VersionTLS13 { + t.Fatal("first ticket doesn't match ticket after resumption") + } + if bytes.Equal(ticket, getTicket()) && version == VersionTLS13 { + t.Fatal("ticket didn't change after resumption") + } + + // An old session ticket can resume, but the server will provide a ticket encrypted with a fresh key. + serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } + testResumeState("ResumeWithOldTicket", true) + if bytes.Equal(ticket[:ticketKeyNameLen], getTicket()[:ticketKeyNameLen]) { + t.Fatal("old first ticket matches the fresh one") + } + + // Now the session tickey key is expired, so a full handshake should occur. + serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } + testResumeState("ResumeWithExpiredTicket", false) + if bytes.Equal(ticket, getTicket()) { + t.Fatal("expired first ticket matches the fresh one") + } + + serverConfig.Time = func() time.Time { return time.Now() } // reset the time back + key1 := randomKey() + serverConfig.SetSessionTicketKeys([][32]byte{key1}) + + testResumeState("InvalidSessionTicketKey", false) + testResumeState("ResumeAfterInvalidSessionTicketKey", true) + + key2 := randomKey() + serverConfig.SetSessionTicketKeys([][32]byte{key2, key1}) + ticket = getTicket() + testResumeState("KeyChange", true) + if bytes.Equal(ticket, getTicket()) { + t.Fatal("new ticket wasn't included while resuming") + } + testResumeState("KeyChangeFinish", true) + + // Age the session ticket a bit, but not yet expired. + serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } + testResumeState("OldSessionTicket", true) + ticket = getTicket() + // Expire the session ticket, which would force a full handshake. + serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } + testResumeState("ExpiredSessionTicket", false) + if bytes.Equal(ticket, getTicket()) { + t.Fatal("new ticket wasn't provided after old ticket expired") + } + + // Age the session ticket a bit at a time, but don't expire it. + d := 0 * time.Hour + for i := 0; i < 13; i++ { + d += 12 * time.Hour + serverConfig.Time = func() time.Time { return time.Now().Add(d) } + testResumeState("OldSessionTicket", true) + } + // Expire it (now a little more than 7 days) and make sure a full + // handshake occurs for TLS 1.2. Resumption should still occur for + // TLS 1.3 since the client should be using a fresh ticket sent over + // by the server. + d += 12 * time.Hour + serverConfig.Time = func() time.Time { return time.Now().Add(d) } + if version == VersionTLS13 { + testResumeState("ExpiredSessionTicket", true) + } else { + testResumeState("ExpiredSessionTicket", false) + } + if bytes.Equal(ticket, getTicket()) { + t.Fatal("new ticket wasn't provided after old ticket expired") + } + + // Reset serverConfig to ensure that calling SetSessionTicketKeys + // before the serverConfig is used works. + serverConfig = &Config{ + MaxVersion: version, + CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, + Certificates: testConfig.Certificates, + } + serverConfig.SetSessionTicketKeys([][32]byte{key2}) + + testResumeState("FreshConfig", true) + + // In TLS 1.3, cross-cipher suite resumption is allowed as long as the KDF + // hash matches. Also, Config.CipherSuites does not apply to TLS 1.3. + if version != VersionTLS13 { + clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA} + testResumeState("DifferentCipherSuite", false) + testResumeState("DifferentCipherSuiteRecovers", true) + } + + deleteTicket() + testResumeState("WithoutSessionTicket", false) + + // Session resumption should work when using client certificates + deleteTicket() + serverConfig.ClientCAs = rootCAs + serverConfig.ClientAuth = RequireAndVerifyClientCert + clientConfig.Certificates = serverConfig.Certificates + testResumeState("InitialHandshake", false) + testResumeState("WithClientCertificates", true) + serverConfig.ClientAuth = NoClientCert + + // Tickets should be removed from the session cache on TLS handshake + // failure, and the client should recover from a corrupted PSK + testResumeState("FetchTicketToCorrupt", false) + corruptTicket() + _, _, err = testHandshake(t, clientConfig, serverConfig) + if err == nil { + t.Fatalf("handshake did not fail with a corrupted client secret") + } + testResumeState("AfterHandshakeFailure", false) + + clientConfig.ClientSessionCache = nil + testResumeState("WithoutSessionCache", false) +} + +func TestLRUClientSessionCache(t *testing.T) { + // Initialize cache of capacity 4. + cache := NewLRUClientSessionCache(4) + cs := make([]ClientSessionState, 6) + keys := []string{"0", "1", "2", "3", "4", "5", "6"} + + // Add 4 entries to the cache and look them up. + for i := 0; i < 4; i++ { + cache.Put(keys[i], &cs[i]) + } + for i := 0; i < 4; i++ { + if s, ok := cache.Get(keys[i]); !ok || s != &cs[i] { + t.Fatalf("session cache failed lookup for added key: %s", keys[i]) + } + } + + // Add 2 more entries to the cache. First 2 should be evicted. + for i := 4; i < 6; i++ { + cache.Put(keys[i], &cs[i]) + } + for i := 0; i < 2; i++ { + if s, ok := cache.Get(keys[i]); ok || s != nil { + t.Fatalf("session cache should have evicted key: %s", keys[i]) + } + } + + // Touch entry 2. LRU should evict 3 next. + cache.Get(keys[2]) + cache.Put(keys[0], &cs[0]) + if s, ok := cache.Get(keys[3]); ok || s != nil { + t.Fatalf("session cache should have evicted key 3") + } + + // Update entry 0 in place. + cache.Put(keys[0], &cs[3]) + if s, ok := cache.Get(keys[0]); !ok || s != &cs[3] { + t.Fatalf("session cache failed update for key 0") + } + + // Calling Put with a nil entry deletes the key. + cache.Put(keys[0], nil) + if _, ok := cache.Get(keys[0]); ok { + t.Fatalf("session cache failed to delete key 0") + } + + // Delete entry 2. LRU should keep 4 and 5 + cache.Put(keys[2], nil) + if _, ok := cache.Get(keys[2]); ok { + t.Fatalf("session cache failed to delete key 4") + } + for i := 4; i < 6; i++ { + if s, ok := cache.Get(keys[i]); !ok || s != &cs[i] { + t.Fatalf("session cache should not have deleted key: %s", keys[i]) + } + } +} + +func TestKeyLogTLS12(t *testing.T) { + var serverBuf, clientBuf bytes.Buffer + + clientConfig := testConfig.Clone() + clientConfig.KeyLogWriter = &clientBuf + clientConfig.MaxVersion = VersionTLS12 + + serverConfig := testConfig.Clone() + serverConfig.KeyLogWriter = &serverBuf + serverConfig.MaxVersion = VersionTLS12 + + c, s := localPipe(t) + done := make(chan bool) + + go func() { + defer close(done) + + if err := Server(s, serverConfig).Handshake(); err != nil { + t.Errorf("server: %s", err) + return + } + s.Close() + }() + + if err := Client(c, clientConfig).Handshake(); err != nil { + t.Fatalf("client: %s", err) + } + + c.Close() + <-done + + checkKeylogLine := func(side, loggedLine string) { + if len(loggedLine) == 0 { + t.Fatalf("%s: no keylog line was produced", side) + } + const expectedLen = 13 /* "CLIENT_RANDOM" */ + + 1 /* space */ + + 32*2 /* hex client nonce */ + + 1 /* space */ + + 48*2 /* hex master secret */ + + 1 /* new line */ + if len(loggedLine) != expectedLen { + t.Fatalf("%s: keylog line has incorrect length (want %d, got %d): %q", side, expectedLen, len(loggedLine), loggedLine) + } + if !strings.HasPrefix(loggedLine, "CLIENT_RANDOM "+strings.Repeat("0", 64)+" ") { + t.Fatalf("%s: keylog line has incorrect structure or nonce: %q", side, loggedLine) + } + } + + checkKeylogLine("client", clientBuf.String()) + checkKeylogLine("server", serverBuf.String()) +} + +func TestKeyLogTLS13(t *testing.T) { + var serverBuf, clientBuf bytes.Buffer + + clientConfig := testConfig.Clone() + clientConfig.KeyLogWriter = &clientBuf + + serverConfig := testConfig.Clone() + serverConfig.KeyLogWriter = &serverBuf + + c, s := localPipe(t) + done := make(chan bool) + + go func() { + defer close(done) + + if err := Server(s, serverConfig).Handshake(); err != nil { + t.Errorf("server: %s", err) + return + } + s.Close() + }() + + if err := Client(c, clientConfig).Handshake(); err != nil { + t.Fatalf("client: %s", err) + } + + c.Close() + <-done + + checkKeylogLines := func(side, loggedLines string) { + loggedLines = strings.TrimSpace(loggedLines) + lines := strings.Split(loggedLines, "\n") + if len(lines) != 4 { + t.Errorf("Expected the %s to log 4 lines, got %d", side, len(lines)) + } + } + + checkKeylogLines("client", clientBuf.String()) + checkKeylogLines("server", serverBuf.String()) +} + +func TestHandshakeClientALPNMatch(t *testing.T) { + config := testConfig.Clone() + config.NextProtos = []string{"proto2", "proto1"} + + test := &clientTest{ + name: "ALPN", + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -alpn flag. + args: []string{"-alpn", "proto1,proto2"}, + config: config, + validate: func(state ConnectionState) error { + // The server's preferences should override the client. + if state.NegotiatedProtocol != "proto1" { + return fmt.Errorf("Got protocol %q, wanted proto1", state.NegotiatedProtocol) + } + return nil + }, + } + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) +} + +func TestServerSelectingUnconfiguredApplicationProtocol(t *testing.T) { + // This checks that the server can't select an application protocol that the + // client didn't offer. + + c, s := localPipe(t) + errChan := make(chan error, 1) + + go func() { + client := Client(c, &Config{ + ServerName: "foo", + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + NextProtos: []string{"http", "something-else"}, + }) + errChan <- client.Handshake() + }() + + var header [5]byte + if _, err := io.ReadFull(s, header[:]); err != nil { + t.Fatal(err) + } + recordLen := int(header[3])<<8 | int(header[4]) + + record := make([]byte, recordLen) + if _, err := io.ReadFull(s, record); err != nil { + t.Fatal(err) + } + + serverHello := &serverHelloMsg{ + vers: VersionTLS12, + random: make([]byte, 32), + cipherSuite: TLS_RSA_WITH_AES_128_GCM_SHA256, + alpnProtocol: "how-about-this", + } + serverHelloBytes := serverHello.marshal() + + s.Write([]byte{ + byte(recordTypeHandshake), + byte(VersionTLS12 >> 8), + byte(VersionTLS12 & 0xff), + byte(len(serverHelloBytes) >> 8), + byte(len(serverHelloBytes)), + }) + s.Write(serverHelloBytes) + s.Close() + + if err := <-errChan; !strings.Contains(err.Error(), "server selected unadvertised ALPN protocol") { + t.Fatalf("Expected error about unconfigured cipher suite but got %q", err) + } +} + +// sctsBase64 contains data from `openssl s_client -serverinfo 18 -connect ritter.vg:443` +const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0=" + +func TestHandshakClientSCTs(t *testing.T) { + config := testConfig.Clone() + + scts, err := base64.StdEncoding.DecodeString(sctsBase64) + if err != nil { + t.Fatal(err) + } + + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -serverinfo flag. + test := &clientTest{ + name: "SCT", + config: config, + extensions: [][]byte{scts}, + validate: func(state ConnectionState) error { + expectedSCTs := [][]byte{ + scts[8:125], + scts[127:245], + scts[247:], + } + if n := len(state.SignedCertificateTimestamps); n != len(expectedSCTs) { + return fmt.Errorf("Got %d scts, wanted %d", n, len(expectedSCTs)) + } + for i, expected := range expectedSCTs { + if sct := state.SignedCertificateTimestamps[i]; !bytes.Equal(sct, expected) { + return fmt.Errorf("SCT #%d contained %x, expected %x", i, sct, expected) + } + } + return nil + }, + } + runClientTestTLS12(t, test) + + // TLS 1.3 moved SCTs to the Certificate extensions and -serverinfo only + // supports ServerHello extensions. +} + +func TestRenegotiationRejected(t *testing.T) { + config := testConfig.Clone() + test := &clientTest{ + name: "RenegotiationRejected", + args: []string{"-state"}, + config: config, + numRenegotiations: 1, + renegotiationExpectedToFail: 1, + checkRenegotiationError: func(renegotiationNum int, err error) error { + if err == nil { + return errors.New("expected error from renegotiation but got nil") + } + if !strings.Contains(err.Error(), "no renegotiation") { + return fmt.Errorf("expected renegotiation to be rejected but got %q", err) + } + return nil + }, + } + runClientTestTLS12(t, test) +} + +func TestRenegotiateOnce(t *testing.T) { + config := testConfig.Clone() + config.Renegotiation = RenegotiateOnceAsClient + + test := &clientTest{ + name: "RenegotiateOnce", + args: []string{"-state"}, + config: config, + numRenegotiations: 1, + } + + runClientTestTLS12(t, test) +} + +func TestRenegotiateTwice(t *testing.T) { + config := testConfig.Clone() + config.Renegotiation = RenegotiateFreelyAsClient + + test := &clientTest{ + name: "RenegotiateTwice", + args: []string{"-state"}, + config: config, + numRenegotiations: 2, + } + + runClientTestTLS12(t, test) +} + +func TestRenegotiateTwiceRejected(t *testing.T) { + config := testConfig.Clone() + config.Renegotiation = RenegotiateOnceAsClient + + test := &clientTest{ + name: "RenegotiateTwiceRejected", + args: []string{"-state"}, + config: config, + numRenegotiations: 2, + renegotiationExpectedToFail: 2, + checkRenegotiationError: func(renegotiationNum int, err error) error { + if renegotiationNum == 1 { + return err + } + + if err == nil { + return errors.New("expected error from renegotiation but got nil") + } + if !strings.Contains(err.Error(), "no renegotiation") { + return fmt.Errorf("expected renegotiation to be rejected but got %q", err) + } + return nil + }, + } + + runClientTestTLS12(t, test) +} + +func TestHandshakeClientExportKeyingMaterial(t *testing.T) { + test := &clientTest{ + name: "ExportKeyingMaterial", + config: testConfig.Clone(), + validate: func(state ConnectionState) error { + if km, err := state.ExportKeyingMaterial("test", nil, 42); err != nil { + return fmt.Errorf("ExportKeyingMaterial failed: %v", err) + } else if len(km) != 42 { + return fmt.Errorf("Got %d bytes from ExportKeyingMaterial, wanted %d", len(km), 42) + } + return nil + }, + } + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) + runClientTestTLS13(t, test) +} + +var hostnameInSNITests = []struct { + in, out string +}{ + // Opaque string + {"", ""}, + {"localhost", "localhost"}, + {"foo, bar, baz and qux", "foo, bar, baz and qux"}, + + // DNS hostname + {"golang.org", "golang.org"}, + {"golang.org.", "golang.org"}, + + // Literal IPv4 address + {"1.2.3.4", ""}, + + // Literal IPv6 address + {"::1", ""}, + {"::1%lo0", ""}, // with zone identifier + {"[::1]", ""}, // as per RFC 5952 we allow the [] style as IPv6 literal + {"[::1%lo0]", ""}, +} + +func TestHostnameInSNI(t *testing.T) { + for _, tt := range hostnameInSNITests { + c, s := localPipe(t) + + go func(host string) { + Client(c, &Config{ServerName: host, InsecureSkipVerify: true}).Handshake() + }(tt.in) + + var header [5]byte + if _, err := io.ReadFull(s, header[:]); err != nil { + t.Fatal(err) + } + recordLen := int(header[3])<<8 | int(header[4]) + + record := make([]byte, recordLen) + if _, err := io.ReadFull(s, record[:]); err != nil { + t.Fatal(err) + } + + c.Close() + s.Close() + + var m clientHelloMsg + if !m.unmarshal(record) { + t.Errorf("unmarshaling ClientHello for %q failed", tt.in) + continue + } + if tt.in != tt.out && m.serverName == tt.in { + t.Errorf("prohibited %q found in ClientHello: %x", tt.in, record) + } + if m.serverName != tt.out { + t.Errorf("expected %q not found in ClientHello: %x", tt.out, record) + } + } +} + +func TestServerSelectingUnconfiguredCipherSuite(t *testing.T) { + // This checks that the server can't select a cipher suite that the + // client didn't offer. See #13174. + + c, s := localPipe(t) + errChan := make(chan error, 1) + + go func() { + client := Client(c, &Config{ + ServerName: "foo", + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + }) + errChan <- client.Handshake() + }() + + var header [5]byte + if _, err := io.ReadFull(s, header[:]); err != nil { + t.Fatal(err) + } + recordLen := int(header[3])<<8 | int(header[4]) + + record := make([]byte, recordLen) + if _, err := io.ReadFull(s, record); err != nil { + t.Fatal(err) + } + + // Create a ServerHello that selects a different cipher suite than the + // sole one that the client offered. + serverHello := &serverHelloMsg{ + vers: VersionTLS12, + random: make([]byte, 32), + cipherSuite: TLS_RSA_WITH_AES_256_GCM_SHA384, + } + serverHelloBytes := serverHello.marshal() + + s.Write([]byte{ + byte(recordTypeHandshake), + byte(VersionTLS12 >> 8), + byte(VersionTLS12 & 0xff), + byte(len(serverHelloBytes) >> 8), + byte(len(serverHelloBytes)), + }) + s.Write(serverHelloBytes) + s.Close() + + if err := <-errChan; !strings.Contains(err.Error(), "unconfigured cipher") { + t.Fatalf("Expected error about unconfigured cipher suite but got %q", err) + } +} + +func TestVerifyConnection(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testVerifyConnection(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testVerifyConnection(t, VersionTLS13) }) +} + +func testVerifyConnection(t *testing.T, version uint16) { + checkFields := func(c ConnectionState, called *int, errorType string) error { + if c.Version != version { + return fmt.Errorf("%s: got Version %v, want %v", errorType, c.Version, version) + } + if c.HandshakeComplete { + return fmt.Errorf("%s: got HandshakeComplete, want false", errorType) + } + if c.ServerName != "example.golang" { + return fmt.Errorf("%s: got ServerName %s, want %s", errorType, c.ServerName, "example.golang") + } + if c.NegotiatedProtocol != "protocol1" { + return fmt.Errorf("%s: got NegotiatedProtocol %s, want %s", errorType, c.NegotiatedProtocol, "protocol1") + } + if c.CipherSuite == 0 { + return fmt.Errorf("%s: got CipherSuite 0, want non-zero", errorType) + } + wantDidResume := false + if *called == 2 { // if this is the second time, then it should be a resumption + wantDidResume = true + } + if c.DidResume != wantDidResume { + return fmt.Errorf("%s: got DidResume %t, want %t", errorType, c.DidResume, wantDidResume) + } + return nil + } + + tests := []struct { + name string + configureServer func(*Config, *int) + configureClient func(*Config, *int) + }{ + { + name: "RequireAndVerifyClientCert", + configureServer: func(config *Config, called *int) { + config.ClientAuth = RequireAndVerifyClientCert + config.VerifyConnection = func(c ConnectionState) error { + *called++ + if l := len(c.PeerCertificates); l != 1 { + return fmt.Errorf("server: got len(PeerCertificates) = %d, wanted 1", l) + } + if len(c.VerifiedChains) == 0 { + return fmt.Errorf("server: got len(VerifiedChains) = 0, wanted non-zero") + } + return checkFields(c, called, "server") + } + }, + configureClient: func(config *Config, called *int) { + config.VerifyConnection = func(c ConnectionState) error { + *called++ + if l := len(c.PeerCertificates); l != 1 { + return fmt.Errorf("client: got len(PeerCertificates) = %d, wanted 1", l) + } + if len(c.VerifiedChains) == 0 { + return fmt.Errorf("client: got len(VerifiedChains) = 0, wanted non-zero") + } + if c.DidResume { + return nil + // The SCTs and OCSP Response are dropped on resumption. + // See http://golang.org/issue/39075. + } + if len(c.OCSPResponse) == 0 { + return fmt.Errorf("client: got len(OCSPResponse) = 0, wanted non-zero") + } + if len(c.SignedCertificateTimestamps) == 0 { + return fmt.Errorf("client: got len(SignedCertificateTimestamps) = 0, wanted non-zero") + } + return checkFields(c, called, "client") + } + }, + }, + { + name: "InsecureSkipVerify", + configureServer: func(config *Config, called *int) { + config.ClientAuth = RequireAnyClientCert + config.InsecureSkipVerify = true + config.VerifyConnection = func(c ConnectionState) error { + *called++ + if l := len(c.PeerCertificates); l != 1 { + return fmt.Errorf("server: got len(PeerCertificates) = %d, wanted 1", l) + } + if c.VerifiedChains != nil { + return fmt.Errorf("server: got Verified Chains %v, want nil", c.VerifiedChains) + } + return checkFields(c, called, "server") + } + }, + configureClient: func(config *Config, called *int) { + config.InsecureSkipVerify = true + config.VerifyConnection = func(c ConnectionState) error { + *called++ + if l := len(c.PeerCertificates); l != 1 { + return fmt.Errorf("client: got len(PeerCertificates) = %d, wanted 1", l) + } + if c.VerifiedChains != nil { + return fmt.Errorf("server: got Verified Chains %v, want nil", c.VerifiedChains) + } + if c.DidResume { + return nil + // The SCTs and OCSP Response are dropped on resumption. + // See http://golang.org/issue/39075. + } + if len(c.OCSPResponse) == 0 { + return fmt.Errorf("client: got len(OCSPResponse) = 0, wanted non-zero") + } + if len(c.SignedCertificateTimestamps) == 0 { + return fmt.Errorf("client: got len(SignedCertificateTimestamps) = 0, wanted non-zero") + } + return checkFields(c, called, "client") + } + }, + }, + { + name: "NoClientCert", + configureServer: func(config *Config, called *int) { + config.ClientAuth = NoClientCert + config.VerifyConnection = func(c ConnectionState) error { + *called++ + return checkFields(c, called, "server") + } + }, + configureClient: func(config *Config, called *int) { + config.VerifyConnection = func(c ConnectionState) error { + *called++ + return checkFields(c, called, "client") + } + }, + }, + { + name: "RequestClientCert", + configureServer: func(config *Config, called *int) { + config.ClientAuth = RequestClientCert + config.VerifyConnection = func(c ConnectionState) error { + *called++ + return checkFields(c, called, "server") + } + }, + configureClient: func(config *Config, called *int) { + config.Certificates = nil // clear the client cert + config.VerifyConnection = func(c ConnectionState) error { + *called++ + if l := len(c.PeerCertificates); l != 1 { + return fmt.Errorf("client: got len(PeerCertificates) = %d, wanted 1", l) + } + if len(c.VerifiedChains) == 0 { + return fmt.Errorf("client: got len(VerifiedChains) = 0, wanted non-zero") + } + if c.DidResume { + return nil + // The SCTs and OCSP Response are dropped on resumption. + // See http://golang.org/issue/39075. + } + if len(c.OCSPResponse) == 0 { + return fmt.Errorf("client: got len(OCSPResponse) = 0, wanted non-zero") + } + if len(c.SignedCertificateTimestamps) == 0 { + return fmt.Errorf("client: got len(SignedCertificateTimestamps) = 0, wanted non-zero") + } + return checkFields(c, called, "client") + } + }, + }, + } + for _, test := range tests { + issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + if err != nil { + panic(err) + } + rootCAs := x509.NewCertPool() + rootCAs.AddCert(issuer) + + var serverCalled, clientCalled int + + serverConfig := &Config{ + MaxVersion: version, + Certificates: []Certificate{testConfig.Certificates[0]}, + ClientCAs: rootCAs, + NextProtos: []string{"protocol1"}, + } + serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} + serverConfig.Certificates[0].OCSPStaple = []byte("dummy ocsp") + test.configureServer(serverConfig, &serverCalled) + + clientConfig := &Config{ + MaxVersion: version, + ClientSessionCache: NewLRUClientSessionCache(32), + RootCAs: rootCAs, + ServerName: "example.golang", + Certificates: []Certificate{testConfig.Certificates[0]}, + NextProtos: []string{"protocol1"}, + } + test.configureClient(clientConfig, &clientCalled) + + testHandshakeState := func(name string, didResume bool) { + _, hs, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("%s: handshake failed: %s", name, err) + } + if hs.DidResume != didResume { + t.Errorf("%s: resumed: %v, expected: %v", name, hs.DidResume, didResume) + } + wantCalled := 1 + if didResume { + wantCalled = 2 // resumption would mean this is the second time it was called in this test + } + if clientCalled != wantCalled { + t.Errorf("%s: expected client VerifyConnection called %d times, did %d times", name, wantCalled, clientCalled) + } + if serverCalled != wantCalled { + t.Errorf("%s: expected server VerifyConnection called %d times, did %d times", name, wantCalled, serverCalled) + } + } + testHandshakeState(fmt.Sprintf("%s-FullHandshake", test.name), false) + testHandshakeState(fmt.Sprintf("%s-Resumption", test.name), true) + } +} + +func TestVerifyPeerCertificate(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testVerifyPeerCertificate(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testVerifyPeerCertificate(t, VersionTLS13) }) +} + +func testVerifyPeerCertificate(t *testing.T, version uint16) { + issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + if err != nil { + panic(err) + } + + rootCAs := x509.NewCertPool() + rootCAs.AddCert(issuer) + + now := func() time.Time { return time.Unix(1476984729, 0) } + + sentinelErr := errors.New("TestVerifyPeerCertificate") + + verifyPeerCertificateCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { + if l := len(rawCerts); l != 1 { + return fmt.Errorf("got len(rawCerts) = %d, wanted 1", l) + } + if len(validatedChains) == 0 { + return errors.New("got len(validatedChains) = 0, wanted non-zero") + } + *called = true + return nil + } + verifyConnectionCallback := func(called *bool, isClient bool, c ConnectionState) error { + if l := len(c.PeerCertificates); l != 1 { + return fmt.Errorf("got len(PeerCertificates) = %d, wanted 1", l) + } + if len(c.VerifiedChains) == 0 { + return fmt.Errorf("got len(VerifiedChains) = 0, wanted non-zero") + } + if isClient && len(c.OCSPResponse) == 0 { + return fmt.Errorf("got len(OCSPResponse) = 0, wanted non-zero") + } + *called = true + return nil + } + + tests := []struct { + configureServer func(*Config, *bool) + configureClient func(*Config, *bool) + validate func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) + }{ + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { + return verifyPeerCertificateCallback(called, rawCerts, validatedChains) + } + }, + configureClient: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { + return verifyPeerCertificateCallback(called, rawCerts, validatedChains) + } + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if clientErr != nil { + t.Errorf("test[%d]: client handshake failed: %v", testNo, clientErr) + } + if serverErr != nil { + t.Errorf("test[%d]: server handshake failed: %v", testNo, serverErr) + } + if !clientCalled { + t.Errorf("test[%d]: client did not call callback", testNo) + } + if !serverCalled { + t.Errorf("test[%d]: server did not call callback", testNo) + } + }, + }, + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { + return sentinelErr + } + }, + configureClient: func(config *Config, called *bool) { + config.VerifyPeerCertificate = nil + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if serverErr != sentinelErr { + t.Errorf("#%d: got server error %v, wanted sentinelErr", testNo, serverErr) + } + }, + }, + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + }, + configureClient: func(config *Config, called *bool) { + config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { + return sentinelErr + } + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if clientErr != sentinelErr { + t.Errorf("#%d: got client error %v, wanted sentinelErr", testNo, clientErr) + } + }, + }, + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + }, + configureClient: func(config *Config, called *bool) { + config.InsecureSkipVerify = true + config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { + if l := len(rawCerts); l != 1 { + return fmt.Errorf("got len(rawCerts) = %d, wanted 1", l) + } + // With InsecureSkipVerify set, this + // callback should still be called but + // validatedChains must be empty. + if l := len(validatedChains); l != 0 { + return fmt.Errorf("got len(validatedChains) = %d, wanted zero", l) + } + *called = true + return nil + } + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if clientErr != nil { + t.Errorf("test[%d]: client handshake failed: %v", testNo, clientErr) + } + if serverErr != nil { + t.Errorf("test[%d]: server handshake failed: %v", testNo, serverErr) + } + if !clientCalled { + t.Errorf("test[%d]: client did not call callback", testNo) + } + }, + }, + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyConnection = func(c ConnectionState) error { + return verifyConnectionCallback(called, false, c) + } + }, + configureClient: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyConnection = func(c ConnectionState) error { + return verifyConnectionCallback(called, true, c) + } + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if clientErr != nil { + t.Errorf("test[%d]: client handshake failed: %v", testNo, clientErr) + } + if serverErr != nil { + t.Errorf("test[%d]: server handshake failed: %v", testNo, serverErr) + } + if !clientCalled { + t.Errorf("test[%d]: client did not call callback", testNo) + } + if !serverCalled { + t.Errorf("test[%d]: server did not call callback", testNo) + } + }, + }, + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyConnection = func(c ConnectionState) error { + return sentinelErr + } + }, + configureClient: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyConnection = nil + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if serverErr != sentinelErr { + t.Errorf("#%d: got server error %v, wanted sentinelErr", testNo, serverErr) + } + }, + }, + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyConnection = nil + }, + configureClient: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyConnection = func(c ConnectionState) error { + return sentinelErr + } + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if clientErr != sentinelErr { + t.Errorf("#%d: got client error %v, wanted sentinelErr", testNo, clientErr) + } + }, + }, + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { + return verifyPeerCertificateCallback(called, rawCerts, validatedChains) + } + config.VerifyConnection = func(c ConnectionState) error { + return sentinelErr + } + }, + configureClient: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyPeerCertificate = nil + config.VerifyConnection = nil + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if serverErr != sentinelErr { + t.Errorf("#%d: got server error %v, wanted sentinelErr", testNo, serverErr) + } + if !serverCalled { + t.Errorf("test[%d]: server did not call callback", testNo) + } + }, + }, + { + configureServer: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyPeerCertificate = nil + config.VerifyConnection = nil + }, + configureClient: func(config *Config, called *bool) { + config.InsecureSkipVerify = false + config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { + return verifyPeerCertificateCallback(called, rawCerts, validatedChains) + } + config.VerifyConnection = func(c ConnectionState) error { + return sentinelErr + } + }, + validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) { + if clientErr != sentinelErr { + t.Errorf("#%d: got client error %v, wanted sentinelErr", testNo, clientErr) + } + if !clientCalled { + t.Errorf("test[%d]: client did not call callback", testNo) + } + }, + }, + } + + for i, test := range tests { + c, s := localPipe(t) + done := make(chan error) + + var clientCalled, serverCalled bool + + go func() { + config := testConfig.Clone() + config.ServerName = "example.golang" + config.ClientAuth = RequireAndVerifyClientCert + config.ClientCAs = rootCAs + config.Time = now + config.MaxVersion = version + config.Certificates = make([]Certificate, 1) + config.Certificates[0].Certificate = [][]byte{testRSACertificate} + config.Certificates[0].PrivateKey = testRSAPrivateKey + config.Certificates[0].SignedCertificateTimestamps = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} + config.Certificates[0].OCSPStaple = []byte("dummy ocsp") + test.configureServer(config, &serverCalled) + + err = Server(s, config).Handshake() + s.Close() + done <- err + }() + + config := testConfig.Clone() + config.ServerName = "example.golang" + config.RootCAs = rootCAs + config.Time = now + config.MaxVersion = version + test.configureClient(config, &clientCalled) + clientErr := Client(c, config).Handshake() + c.Close() + serverErr := <-done + + test.validate(t, i, clientCalled, serverCalled, clientErr, serverErr) + } +} + +// brokenConn wraps a net.Conn and causes all Writes after a certain number to +// fail with brokenConnErr. +type brokenConn struct { + net.Conn + + // breakAfter is the number of successful writes that will be allowed + // before all subsequent writes fail. + breakAfter int + + // numWrites is the number of writes that have been done. + numWrites int +} + +// brokenConnErr is the error that brokenConn returns once exhausted. +var brokenConnErr = errors.New("too many writes to brokenConn") + +func (b *brokenConn) Write(data []byte) (int, error) { + if b.numWrites >= b.breakAfter { + return 0, brokenConnErr + } + + b.numWrites++ + return b.Conn.Write(data) +} + +func TestFailedWrite(t *testing.T) { + // Test that a write error during the handshake is returned. + for _, breakAfter := range []int{0, 1} { + c, s := localPipe(t) + done := make(chan bool) + + go func() { + Server(s, testConfig).Handshake() + s.Close() + done <- true + }() + + brokenC := &brokenConn{Conn: c, breakAfter: breakAfter} + err := Client(brokenC, testConfig).Handshake() + if err != brokenConnErr { + t.Errorf("#%d: expected error from brokenConn but got %q", breakAfter, err) + } + brokenC.Close() + + <-done + } +} + +// writeCountingConn wraps a net.Conn and counts the number of Write calls. +type writeCountingConn struct { + net.Conn + + // numWrites is the number of writes that have been done. + numWrites int +} + +func (wcc *writeCountingConn) Write(data []byte) (int, error) { + wcc.numWrites++ + return wcc.Conn.Write(data) +} + +func TestBuffering(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testBuffering(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testBuffering(t, VersionTLS13) }) +} + +func testBuffering(t *testing.T, version uint16) { + c, s := localPipe(t) + done := make(chan bool) + + clientWCC := &writeCountingConn{Conn: c} + serverWCC := &writeCountingConn{Conn: s} + + go func() { + config := testConfig.Clone() + config.MaxVersion = version + Server(serverWCC, config).Handshake() + serverWCC.Close() + done <- true + }() + + err := Client(clientWCC, testConfig).Handshake() + if err != nil { + t.Fatal(err) + } + clientWCC.Close() + <-done + + var expectedClient, expectedServer int + if version == VersionTLS13 { + expectedClient = 2 + expectedServer = 1 + } else { + expectedClient = 2 + expectedServer = 2 + } + + if n := clientWCC.numWrites; n != expectedClient { + t.Errorf("expected client handshake to complete with %d writes, but saw %d", expectedClient, n) + } + + if n := serverWCC.numWrites; n != expectedServer { + t.Errorf("expected server handshake to complete with %d writes, but saw %d", expectedServer, n) + } +} + +func TestAlertFlushing(t *testing.T) { + c, s := localPipe(t) + done := make(chan bool) + + clientWCC := &writeCountingConn{Conn: c} + serverWCC := &writeCountingConn{Conn: s} + + serverConfig := testConfig.Clone() + + // Cause a signature-time error + brokenKey := rsa.PrivateKey{PublicKey: testRSAPrivateKey.PublicKey} + brokenKey.D = big.NewInt(42) + serverConfig.Certificates = []Certificate{{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: &brokenKey, + }} + + go func() { + Server(serverWCC, serverConfig).Handshake() + serverWCC.Close() + done <- true + }() + + err := Client(clientWCC, testConfig).Handshake() + if err == nil { + t.Fatal("client unexpectedly returned no error") + } + + const expectedError = "remote error: tls: internal error" + if e := err.Error(); !strings.Contains(e, expectedError) { + t.Fatalf("expected to find %q in error but error was %q", expectedError, e) + } + clientWCC.Close() + <-done + + if n := serverWCC.numWrites; n != 1 { + t.Errorf("expected server handshake to complete with one write, but saw %d", n) + } +} + +func TestHandshakeRace(t *testing.T) { + if testing.Short() { + t.Skip("skipping in -short mode") + } + t.Parallel() + // This test races a Read and Write to try and complete a handshake in + // order to provide some evidence that there are no races or deadlocks + // in the handshake locking. + for i := 0; i < 32; i++ { + c, s := localPipe(t) + + go func() { + server := Server(s, testConfig) + if err := server.Handshake(); err != nil { + panic(err) + } + + var request [1]byte + if n, err := server.Read(request[:]); err != nil || n != 1 { + panic(err) + } + + server.Write(request[:]) + server.Close() + }() + + startWrite := make(chan struct{}) + startRead := make(chan struct{}) + readDone := make(chan struct{}, 1) + + client := Client(c, testConfig) + go func() { + <-startWrite + var request [1]byte + client.Write(request[:]) + }() + + go func() { + <-startRead + var reply [1]byte + if _, err := io.ReadFull(client, reply[:]); err != nil { + panic(err) + } + c.Close() + readDone <- struct{}{} + }() + + if i&1 == 1 { + startWrite <- struct{}{} + startRead <- struct{}{} + } else { + startRead <- struct{}{} + startWrite <- struct{}{} + } + <-readDone + } +} + +var getClientCertificateTests = []struct { + setup func(*Config, *Config) + expectedClientError string + verify func(*testing.T, int, *ConnectionState) +}{ + { + func(clientConfig, serverConfig *Config) { + // Returning a Certificate with no certificate data + // should result in an empty message being sent to the + // server. + serverConfig.ClientCAs = nil + clientConfig.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) { + if len(cri.SignatureSchemes) == 0 { + panic("empty SignatureSchemes") + } + if len(cri.AcceptableCAs) != 0 { + panic("AcceptableCAs should have been empty") + } + return new(Certificate), nil + } + }, + "", + func(t *testing.T, testNum int, cs *ConnectionState) { + if l := len(cs.PeerCertificates); l != 0 { + t.Errorf("#%d: expected no certificates but got %d", testNum, l) + } + }, + }, + { + func(clientConfig, serverConfig *Config) { + // With TLS 1.1, the SignatureSchemes should be + // synthesised from the supported certificate types. + clientConfig.MaxVersion = VersionTLS11 + clientConfig.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) { + if len(cri.SignatureSchemes) == 0 { + panic("empty SignatureSchemes") + } + return new(Certificate), nil + } + }, + "", + func(t *testing.T, testNum int, cs *ConnectionState) { + if l := len(cs.PeerCertificates); l != 0 { + t.Errorf("#%d: expected no certificates but got %d", testNum, l) + } + }, + }, + { + func(clientConfig, serverConfig *Config) { + // Returning an error should abort the handshake with + // that error. + clientConfig.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) { + return nil, errors.New("GetClientCertificate") + } + }, + "GetClientCertificate", + func(t *testing.T, testNum int, cs *ConnectionState) { + }, + }, + { + func(clientConfig, serverConfig *Config) { + clientConfig.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) { + if len(cri.AcceptableCAs) == 0 { + panic("empty AcceptableCAs") + } + cert := &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + } + return cert, nil + } + }, + "", + func(t *testing.T, testNum int, cs *ConnectionState) { + if len(cs.VerifiedChains) == 0 { + t.Errorf("#%d: expected some verified chains, but found none", testNum) + } + }, + }, +} + +func TestGetClientCertificate(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testGetClientCertificate(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testGetClientCertificate(t, VersionTLS13) }) +} + +func testGetClientCertificate(t *testing.T, version uint16) { + issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + if err != nil { + panic(err) + } + + for i, test := range getClientCertificateTests { + serverConfig := testConfig.Clone() + serverConfig.ClientAuth = VerifyClientCertIfGiven + serverConfig.RootCAs = x509.NewCertPool() + serverConfig.RootCAs.AddCert(issuer) + serverConfig.ClientCAs = serverConfig.RootCAs + serverConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } + serverConfig.MaxVersion = version + + clientConfig := testConfig.Clone() + clientConfig.MaxVersion = version + + test.setup(clientConfig, serverConfig) + + type serverResult struct { + cs ConnectionState + err error + } + + c, s := localPipe(t) + done := make(chan serverResult) + + go func() { + defer s.Close() + server := Server(s, serverConfig) + err := server.Handshake() + + var cs ConnectionState + if err == nil { + cs = server.ConnectionState() + } + done <- serverResult{cs, err} + }() + + clientErr := Client(c, clientConfig).Handshake() + c.Close() + + result := <-done + + if clientErr != nil { + if len(test.expectedClientError) == 0 { + t.Errorf("#%d: client error: %v", i, clientErr) + } else if got := clientErr.Error(); got != test.expectedClientError { + t.Errorf("#%d: expected client error %q, but got %q", i, test.expectedClientError, got) + } else { + test.verify(t, i, &result.cs) + } + } else if len(test.expectedClientError) > 0 { + t.Errorf("#%d: expected client error %q, but got no error", i, test.expectedClientError) + } else if err := result.err; err != nil { + t.Errorf("#%d: server error: %v", i, err) + } else { + test.verify(t, i, &result.cs) + } + } +} + +func TestRSAPSSKeyError(t *testing.T) { + // crypto/tls does not support the rsa_pss_pss_* SignatureSchemes. If support for + // public keys with OID RSASSA-PSS is added to crypto/x509, they will be misused with + // the rsa_pss_rsae_* SignatureSchemes. Assert that RSASSA-PSS certificates don't + // parse, or that they don't carry *rsa.PublicKey keys. + b, _ := pem.Decode([]byte(` +-----BEGIN CERTIFICATE----- +MIIDZTCCAhygAwIBAgIUCF2x0FyTgZG0CC9QTDjGWkB5vgEwPgYJKoZIhvcNAQEK +MDGgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQC +AgDeMBIxEDAOBgNVBAMMB1JTQS1QU1MwHhcNMTgwNjI3MjI0NDM2WhcNMTgwNzI3 +MjI0NDM2WjASMRAwDgYDVQQDDAdSU0EtUFNTMIIBIDALBgkqhkiG9w0BAQoDggEP +ADCCAQoCggEBANxDm0f76JdI06YzsjB3AmmjIYkwUEGxePlafmIASFjDZl/elD0Z +/a7xLX468b0qGxLS5al7XCcEprSdsDR6DF5L520+pCbpfLyPOjuOvGmk9KzVX4x5 +b05YXYuXdsQ0Kjxcx2i3jjCday6scIhMJVgBZxTEyMj1thPQM14SHzKCd/m6HmCL +QmswpH2yMAAcBRWzRpp/vdH5DeOJEB3aelq7094no731mrLUCHRiZ1htq8BDB3ou +czwqgwspbqZ4dnMXl2MvfySQ5wJUxQwILbiuAKO2lVVPUbFXHE9pgtznNoPvKwQT +JNcX8ee8WIZc2SEGzofjk3NpjR+2ADB2u3sCAwEAAaNTMFEwHQYDVR0OBBYEFNEz +AdyJ2f+fU+vSCS6QzohnOnprMB8GA1UdIwQYMBaAFNEzAdyJ2f+fU+vSCS6Qzohn +OnprMA8GA1UdEwEB/wQFMAMBAf8wPgYJKoZIhvcNAQEKMDGgDTALBglghkgBZQME +AgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQCAgDeA4IBAQCjEdrR5aab +sZmCwrMeKidXgfkmWvfuLDE+TCbaqDZp7BMWcMQXT9O0UoUT5kqgKj2ARm2pEW0Z +H3Z1vj3bbds72qcDIJXp+l0fekyLGeCrX/CbgnMZXEP7+/+P416p34ChR1Wz4dU1 +KD3gdsUuTKKeMUog3plxlxQDhRQmiL25ygH1LmjLd6dtIt0GVRGr8lj3euVeprqZ +bZ3Uq5eLfsn8oPgfC57gpO6yiN+UURRTlK3bgYvLh4VWB3XXk9UaQZ7Mq1tpXjoD +HYFybkWzibkZp4WRo+Fa28rirH+/wHt0vfeN7UCceURZEx4JaxIIfe4ku7uDRhJi +RwBA9Xk1KBNF +-----END CERTIFICATE-----`)) + if b == nil { + t.Fatal("Failed to decode certificate") + } + cert, err := x509.ParseCertificate(b.Bytes) + if err != nil { + return + } + if _, ok := cert.PublicKey.(*rsa.PublicKey); ok { + t.Error("A RSASSA-PSS certificate was parsed like a PKCS#1 v1.5 one, and it will be mistakenly used with rsa_pss_rsae_* signature algorithms") + } +} + +func TestCloseClientConnectionOnIdleServer(t *testing.T) { + clientConn, serverConn := localPipe(t) + client := Client(clientConn, testConfig.Clone()) + go func() { + var b [1]byte + serverConn.Read(b[:]) + client.Close() + }() + client.SetWriteDeadline(time.Now().Add(time.Minute)) + err := client.Handshake() + if err != nil { + if err, ok := err.(net.Error); ok && err.Timeout() { + t.Errorf("Expected a closed network connection error but got '%s'", err.Error()) + } + } else { + t.Errorf("Error expected, but no error returned") + } +} + +func testDowngradeCanary(t *testing.T, clientVersion, serverVersion uint16) error { + defer func() { testingOnlyForceDowngradeCanary = false }() + testingOnlyForceDowngradeCanary = true + + clientConfig := testConfig.Clone() + clientConfig.MaxVersion = clientVersion + serverConfig := testConfig.Clone() + serverConfig.MaxVersion = serverVersion + _, _, err := testHandshake(t, clientConfig, serverConfig) + return err +} + +func TestDowngradeCanary(t *testing.T) { + if err := testDowngradeCanary(t, VersionTLS13, VersionTLS12); err == nil { + t.Errorf("downgrade from TLS 1.3 to TLS 1.2 was not detected") + } + if testing.Short() { + t.Skip("skipping the rest of the checks in short mode") + } + if err := testDowngradeCanary(t, VersionTLS13, VersionTLS11); err == nil { + t.Errorf("downgrade from TLS 1.3 to TLS 1.1 was not detected") + } + if err := testDowngradeCanary(t, VersionTLS13, VersionTLS10); err == nil { + t.Errorf("downgrade from TLS 1.3 to TLS 1.0 was not detected") + } + if err := testDowngradeCanary(t, VersionTLS12, VersionTLS11); err == nil { + t.Errorf("downgrade from TLS 1.2 to TLS 1.1 was not detected") + } + if err := testDowngradeCanary(t, VersionTLS12, VersionTLS10); err == nil { + t.Errorf("downgrade from TLS 1.2 to TLS 1.0 was not detected") + } + if err := testDowngradeCanary(t, VersionTLS13, VersionTLS13); err != nil { + t.Errorf("server unexpectedly sent downgrade canary for TLS 1.3") + } + if err := testDowngradeCanary(t, VersionTLS12, VersionTLS12); err != nil { + t.Errorf("client didn't ignore expected TLS 1.2 canary") + } + if err := testDowngradeCanary(t, VersionTLS11, VersionTLS11); err != nil { + t.Errorf("client unexpectedly reacted to a canary in TLS 1.1") + } + if err := testDowngradeCanary(t, VersionTLS10, VersionTLS10); err != nil { + t.Errorf("client unexpectedly reacted to a canary in TLS 1.0") + } +} + +func TestResumptionKeepsOCSPAndSCT(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS13) }) +} + +func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { + issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + if err != nil { + t.Fatalf("failed to parse test issuer") + } + roots := x509.NewCertPool() + roots.AddCert(issuer) + clientConfig := &Config{ + MaxVersion: ver, + ClientSessionCache: NewLRUClientSessionCache(32), + ServerName: "example.golang", + RootCAs: roots, + } + serverConfig := testConfig.Clone() + serverConfig.MaxVersion = ver + serverConfig.Certificates[0].OCSPStaple = []byte{1, 2, 3} + serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{4, 5, 6}} + + _, ccs, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + // after a new session we expect to see OCSPResponse and + // SignedCertificateTimestamps populated as usual + if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) { + t.Errorf("client ConnectionState contained unexpected OCSPResponse: wanted %v, got %v", + serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse) + } + if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) { + t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps: wanted %v, got %v", + serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps) + } + + // if the server doesn't send any SCTs, repopulate the old SCTs + oldSCTs := serverConfig.Certificates[0].SignedCertificateTimestamps + serverConfig.Certificates[0].SignedCertificateTimestamps = nil + _, ccs, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if !ccs.DidResume { + t.Fatalf("expected session to be resumed") + } + // after a resumed session we also expect to see OCSPResponse + // and SignedCertificateTimestamps populated + if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) { + t.Errorf("client ConnectionState contained unexpected OCSPResponse after resumption: wanted %v, got %v", + serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse) + } + if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, oldSCTs) { + t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v", + oldSCTs, ccs.SignedCertificateTimestamps) + } + + // Only test overriding the SCTs for TLS 1.2, since in 1.3 + // the server won't send the message containing them + if ver == VersionTLS13 { + return + } + + // if the server changes the SCTs it sends, they should override the saved SCTs + serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{7, 8, 9}} + _, ccs, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if !ccs.DidResume { + t.Fatalf("expected session to be resumed") + } + if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) { + t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v", + serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps) + } +} + +// TestClientHandshakeContextCancellation tests that cancelling +// the context given to the client side conn.HandshakeContext +// interrupts the in-progress handshake. +func TestClientHandshakeContextCancellation(t *testing.T) { + c, s := localPipe(t) + ctx, cancel := context.WithCancel(context.Background()) + unblockServer := make(chan struct{}) + defer close(unblockServer) + go func() { + cancel() + <-unblockServer + _ = s.Close() + }() + cli := Client(c, testConfig) + // Initiates client side handshake, which will block until the client hello is read + // by the server, unless the cancellation works. + err := cli.HandshakeContext(ctx) + if err == nil { + t.Fatal("Client handshake did not error when the context was canceled") + } + if err != context.Canceled { + t.Errorf("Unexpected client handshake error: %v", err) + } + if runtime.GOARCH == "wasm" { + t.Skip("conn.Close does not error as expected when called multiple times on WASM") + } + err = cli.Close() + if err == nil { + t.Error("Client connection was not closed when the context was canceled") + } +} diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go new file mode 100644 index 0000000..eb59ac9 --- /dev/null +++ b/src/crypto/tls/handshake_client_tls13.go @@ -0,0 +1,682 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "context" + "crypto" + "crypto/hmac" + "crypto/rsa" + "errors" + "hash" + "sync/atomic" + "time" +) + +type clientHandshakeStateTLS13 struct { + c *Conn + ctx context.Context + serverHello *serverHelloMsg + hello *clientHelloMsg + ecdheParams ecdheParameters + + session *ClientSessionState + earlySecret []byte + binderKey []byte + + certReq *certificateRequestMsgTLS13 + usingPSK bool + sentDummyCCS bool + suite *cipherSuiteTLS13 + transcript hash.Hash + masterSecret []byte + trafficSecret []byte // client_application_traffic_secret_0 +} + +// handshake requires hs.c, hs.hello, hs.serverHello, hs.ecdheParams, and, +// optionally, hs.session, hs.earlySecret and hs.binderKey to be set. +func (hs *clientHandshakeStateTLS13) handshake() error { + c := hs.c + + // The server must not select TLS 1.3 in a renegotiation. See RFC 8446, + // sections 4.1.2 and 4.1.3. + if c.handshakes > 0 { + c.sendAlert(alertProtocolVersion) + return errors.New("tls: server selected TLS 1.3 in a renegotiation") + } + + // Consistency check on the presence of a keyShare and its parameters. + if hs.ecdheParams == nil || len(hs.hello.keyShares) != 1 { + return c.sendAlert(alertInternalError) + } + + if err := hs.checkServerHelloOrHRR(); err != nil { + return err + } + + hs.transcript = hs.suite.hash.New() + hs.transcript.Write(hs.hello.marshal()) + + if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) { + if err := hs.sendDummyChangeCipherSpec(); err != nil { + return err + } + if err := hs.processHelloRetryRequest(); err != nil { + return err + } + } + + hs.transcript.Write(hs.serverHello.marshal()) + + c.buffering = true + if err := hs.processServerHello(); err != nil { + return err + } + if err := hs.sendDummyChangeCipherSpec(); err != nil { + return err + } + if err := hs.establishHandshakeKeys(); err != nil { + return err + } + if err := hs.readServerParameters(); err != nil { + return err + } + if err := hs.readServerCertificate(); err != nil { + return err + } + if err := hs.readServerFinished(); err != nil { + return err + } + if err := hs.sendClientCertificate(); err != nil { + return err + } + if err := hs.sendClientFinished(); err != nil { + return err + } + if _, err := c.flush(); err != nil { + return err + } + + atomic.StoreUint32(&c.handshakeStatus, 1) + + return nil +} + +// checkServerHelloOrHRR does validity checks that apply to both ServerHello and +// HelloRetryRequest messages. It sets hs.suite. +func (hs *clientHandshakeStateTLS13) checkServerHelloOrHRR() error { + c := hs.c + + if hs.serverHello.supportedVersion == 0 { + c.sendAlert(alertMissingExtension) + return errors.New("tls: server selected TLS 1.3 using the legacy version field") + } + + if hs.serverHello.supportedVersion != VersionTLS13 { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server selected an invalid version after a HelloRetryRequest") + } + + if hs.serverHello.vers != VersionTLS12 { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server sent an incorrect legacy version") + } + + if hs.serverHello.ocspStapling || + hs.serverHello.ticketSupported || + hs.serverHello.secureRenegotiationSupported || + len(hs.serverHello.secureRenegotiation) != 0 || + len(hs.serverHello.alpnProtocol) != 0 || + len(hs.serverHello.scts) != 0 { + c.sendAlert(alertUnsupportedExtension) + return errors.New("tls: server sent a ServerHello extension forbidden in TLS 1.3") + } + + if !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server did not echo the legacy session ID") + } + + if hs.serverHello.compressionMethod != compressionNone { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server selected unsupported compression format") + } + + selectedSuite := mutualCipherSuiteTLS13(hs.hello.cipherSuites, hs.serverHello.cipherSuite) + if hs.suite != nil && selectedSuite != hs.suite { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server changed cipher suite after a HelloRetryRequest") + } + if selectedSuite == nil { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server chose an unconfigured cipher suite") + } + hs.suite = selectedSuite + c.cipherSuite = hs.suite.id + + return nil +} + +// sendDummyChangeCipherSpec sends a ChangeCipherSpec record for compatibility +// with middleboxes that didn't implement TLS correctly. See RFC 8446, Appendix D.4. +func (hs *clientHandshakeStateTLS13) sendDummyChangeCipherSpec() error { + if hs.sentDummyCCS { + return nil + } + hs.sentDummyCCS = true + + _, err := hs.c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + return err +} + +// processHelloRetryRequest handles the HRR in hs.serverHello, modifies and +// resends hs.hello, and reads the new ServerHello into hs.serverHello. +func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { + c := hs.c + + // The first ClientHello gets double-hashed into the transcript upon a + // HelloRetryRequest. (The idea is that the server might offload transcript + // storage to the client in the cookie.) See RFC 8446, Section 4.4.1. + chHash := hs.transcript.Sum(nil) + hs.transcript.Reset() + hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) + hs.transcript.Write(chHash) + hs.transcript.Write(hs.serverHello.marshal()) + + // The only HelloRetryRequest extensions we support are key_share and + // cookie, and clients must abort the handshake if the HRR would not result + // in any change in the ClientHello. + if hs.serverHello.selectedGroup == 0 && hs.serverHello.cookie == nil { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server sent an unnecessary HelloRetryRequest message") + } + + if hs.serverHello.cookie != nil { + hs.hello.cookie = hs.serverHello.cookie + } + + if hs.serverHello.serverShare.group != 0 { + c.sendAlert(alertDecodeError) + return errors.New("tls: received malformed key_share extension") + } + + // If the server sent a key_share extension selecting a group, ensure it's + // a group we advertised but did not send a key share for, and send a key + // share for it this time. + if curveID := hs.serverHello.selectedGroup; curveID != 0 { + curveOK := false + for _, id := range hs.hello.supportedCurves { + if id == curveID { + curveOK = true + break + } + } + if !curveOK { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server selected unsupported group") + } + if hs.ecdheParams.CurveID() == curveID { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server sent an unnecessary HelloRetryRequest key_share") + } + if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok { + c.sendAlert(alertInternalError) + return errors.New("tls: CurvePreferences includes unsupported curve") + } + params, err := generateECDHEParameters(c.config.rand(), curveID) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + hs.ecdheParams = params + hs.hello.keyShares = []keyShare{{group: curveID, data: params.PublicKey()}} + } + + hs.hello.raw = nil + if len(hs.hello.pskIdentities) > 0 { + pskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite) + if pskSuite == nil { + return c.sendAlert(alertInternalError) + } + if pskSuite.hash == hs.suite.hash { + // Update binders and obfuscated_ticket_age. + ticketAge := uint32(c.config.time().Sub(hs.session.receivedAt) / time.Millisecond) + hs.hello.pskIdentities[0].obfuscatedTicketAge = ticketAge + hs.session.ageAdd + + transcript := hs.suite.hash.New() + transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) + transcript.Write(chHash) + transcript.Write(hs.serverHello.marshal()) + transcript.Write(hs.hello.marshalWithoutBinders()) + pskBinders := [][]byte{hs.suite.finishedHash(hs.binderKey, transcript)} + hs.hello.updateBinders(pskBinders) + } else { + // Server selected a cipher suite incompatible with the PSK. + hs.hello.pskIdentities = nil + hs.hello.pskBinders = nil + } + } + + hs.transcript.Write(hs.hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { + return err + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + + serverHello, ok := msg.(*serverHelloMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(serverHello, msg) + } + hs.serverHello = serverHello + + if err := hs.checkServerHelloOrHRR(); err != nil { + return err + } + + return nil +} + +func (hs *clientHandshakeStateTLS13) processServerHello() error { + c := hs.c + + if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) { + c.sendAlert(alertUnexpectedMessage) + return errors.New("tls: server sent two HelloRetryRequest messages") + } + + if len(hs.serverHello.cookie) != 0 { + c.sendAlert(alertUnsupportedExtension) + return errors.New("tls: server sent a cookie in a normal ServerHello") + } + + if hs.serverHello.selectedGroup != 0 { + c.sendAlert(alertDecodeError) + return errors.New("tls: malformed key_share extension") + } + + if hs.serverHello.serverShare.group == 0 { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server did not send a key share") + } + if hs.serverHello.serverShare.group != hs.ecdheParams.CurveID() { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server selected unsupported group") + } + + if !hs.serverHello.selectedIdentityPresent { + return nil + } + + if int(hs.serverHello.selectedIdentity) >= len(hs.hello.pskIdentities) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server selected an invalid PSK") + } + + if len(hs.hello.pskIdentities) != 1 || hs.session == nil { + return c.sendAlert(alertInternalError) + } + pskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite) + if pskSuite == nil { + return c.sendAlert(alertInternalError) + } + if pskSuite.hash != hs.suite.hash { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: server selected an invalid PSK and cipher suite pair") + } + + hs.usingPSK = true + c.didResume = true + c.peerCertificates = hs.session.serverCertificates + c.verifiedChains = hs.session.verifiedChains + c.ocspResponse = hs.session.ocspResponse + c.scts = hs.session.scts + return nil +} + +func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { + c := hs.c + + sharedKey := hs.ecdheParams.SharedKey(hs.serverHello.serverShare.data) + if sharedKey == nil { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: invalid server key share") + } + + earlySecret := hs.earlySecret + if !hs.usingPSK { + earlySecret = hs.suite.extract(nil, nil) + } + handshakeSecret := hs.suite.extract(sharedKey, + hs.suite.deriveSecret(earlySecret, "derived", nil)) + + clientSecret := hs.suite.deriveSecret(handshakeSecret, + clientHandshakeTrafficLabel, hs.transcript) + c.out.setTrafficSecret(hs.suite, clientSecret) + serverSecret := hs.suite.deriveSecret(handshakeSecret, + serverHandshakeTrafficLabel, hs.transcript) + c.in.setTrafficSecret(hs.suite, serverSecret) + + err := c.config.writeKeyLog(keyLogLabelClientHandshake, hs.hello.random, clientSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + err = c.config.writeKeyLog(keyLogLabelServerHandshake, hs.hello.random, serverSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + + hs.masterSecret = hs.suite.extract(nil, + hs.suite.deriveSecret(handshakeSecret, "derived", nil)) + + return nil +} + +func (hs *clientHandshakeStateTLS13) readServerParameters() error { + c := hs.c + + msg, err := c.readHandshake() + if err != nil { + return err + } + + encryptedExtensions, ok := msg.(*encryptedExtensionsMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(encryptedExtensions, msg) + } + hs.transcript.Write(encryptedExtensions.marshal()) + + if err := checkALPN(hs.hello.alpnProtocols, encryptedExtensions.alpnProtocol); err != nil { + c.sendAlert(alertUnsupportedExtension) + return err + } + c.clientProtocol = encryptedExtensions.alpnProtocol + + return nil +} + +func (hs *clientHandshakeStateTLS13) readServerCertificate() error { + c := hs.c + + // Either a PSK or a certificate is always used, but not both. + // See RFC 8446, Section 4.1.1. + if hs.usingPSK { + // Make sure the connection is still being verified whether or not this + // is a resumption. Resumptions currently don't reverify certificates so + // they don't call verifyServerCertificate. See Issue 31641. + if c.config.VerifyConnection != nil { + if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + return nil + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + + certReq, ok := msg.(*certificateRequestMsgTLS13) + if ok { + hs.transcript.Write(certReq.marshal()) + + hs.certReq = certReq + + msg, err = c.readHandshake() + if err != nil { + return err + } + } + + certMsg, ok := msg.(*certificateMsgTLS13) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) + } + if len(certMsg.certificate.Certificate) == 0 { + c.sendAlert(alertDecodeError) + return errors.New("tls: received empty certificates message") + } + hs.transcript.Write(certMsg.marshal()) + + c.scts = certMsg.certificate.SignedCertificateTimestamps + c.ocspResponse = certMsg.certificate.OCSPStaple + + if err := c.verifyServerCertificate(certMsg.certificate.Certificate); err != nil { + return err + } + + msg, err = c.readHandshake() + if err != nil { + return err + } + + certVerify, ok := msg.(*certificateVerifyMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certVerify, msg) + } + + // See RFC 8446, Section 4.4.3. + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: certificate used with invalid signature algorithm") + } + sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm) + if err != nil { + return c.sendAlert(alertInternalError) + } + if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: certificate used with invalid signature algorithm") + } + signed := signedMessage(sigHash, serverSignatureContext, hs.transcript) + if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, + sigHash, signed, certVerify.signature); err != nil { + c.sendAlert(alertDecryptError) + return errors.New("tls: invalid signature by the server certificate: " + err.Error()) + } + + hs.transcript.Write(certVerify.marshal()) + + return nil +} + +func (hs *clientHandshakeStateTLS13) readServerFinished() error { + c := hs.c + + msg, err := c.readHandshake() + if err != nil { + return err + } + + finished, ok := msg.(*finishedMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(finished, msg) + } + + expectedMAC := hs.suite.finishedHash(c.in.trafficSecret, hs.transcript) + if !hmac.Equal(expectedMAC, finished.verifyData) { + c.sendAlert(alertDecryptError) + return errors.New("tls: invalid server finished hash") + } + + hs.transcript.Write(finished.marshal()) + + // Derive secrets that take context through the server Finished. + + hs.trafficSecret = hs.suite.deriveSecret(hs.masterSecret, + clientApplicationTrafficLabel, hs.transcript) + serverSecret := hs.suite.deriveSecret(hs.masterSecret, + serverApplicationTrafficLabel, hs.transcript) + c.in.setTrafficSecret(hs.suite, serverSecret) + + err = c.config.writeKeyLog(keyLogLabelClientTraffic, hs.hello.random, hs.trafficSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + err = c.config.writeKeyLog(keyLogLabelServerTraffic, hs.hello.random, serverSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + + c.ekm = hs.suite.exportKeyingMaterial(hs.masterSecret, hs.transcript) + + return nil +} + +func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { + c := hs.c + + if hs.certReq == nil { + return nil + } + + cert, err := c.getClientCertificate(&CertificateRequestInfo{ + AcceptableCAs: hs.certReq.certificateAuthorities, + SignatureSchemes: hs.certReq.supportedSignatureAlgorithms, + Version: c.vers, + ctx: hs.ctx, + }) + if err != nil { + return err + } + + certMsg := new(certificateMsgTLS13) + + certMsg.certificate = *cert + certMsg.scts = hs.certReq.scts && len(cert.SignedCertificateTimestamps) > 0 + certMsg.ocspStapling = hs.certReq.ocspStapling && len(cert.OCSPStaple) > 0 + + hs.transcript.Write(certMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { + return err + } + + // If we sent an empty certificate message, skip the CertificateVerify. + if len(cert.Certificate) == 0 { + return nil + } + + certVerifyMsg := new(certificateVerifyMsg) + certVerifyMsg.hasSignatureAlgorithm = true + + certVerifyMsg.signatureAlgorithm, err = selectSignatureScheme(c.vers, cert, hs.certReq.supportedSignatureAlgorithms) + if err != nil { + // getClientCertificate returned a certificate incompatible with the + // CertificateRequestInfo supported signature algorithms. + c.sendAlert(alertHandshakeFailure) + return err + } + + sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerifyMsg.signatureAlgorithm) + if err != nil { + return c.sendAlert(alertInternalError) + } + + signed := signedMessage(sigHash, clientSignatureContext, hs.transcript) + signOpts := crypto.SignerOpts(sigHash) + if sigType == signatureRSAPSS { + signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} + } + sig, err := cert.PrivateKey.(crypto.Signer).Sign(c.config.rand(), signed, signOpts) + if err != nil { + c.sendAlert(alertInternalError) + return errors.New("tls: failed to sign handshake: " + err.Error()) + } + certVerifyMsg.signature = sig + + hs.transcript.Write(certVerifyMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certVerifyMsg.marshal()); err != nil { + return err + } + + return nil +} + +func (hs *clientHandshakeStateTLS13) sendClientFinished() error { + c := hs.c + + finished := &finishedMsg{ + verifyData: hs.suite.finishedHash(c.out.trafficSecret, hs.transcript), + } + + hs.transcript.Write(finished.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { + return err + } + + c.out.setTrafficSecret(hs.suite, hs.trafficSecret) + + if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != nil { + c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret, + resumptionLabel, hs.transcript) + } + + return nil +} + +func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { + if !c.isClient { + c.sendAlert(alertUnexpectedMessage) + return errors.New("tls: received new session ticket from a client") + } + + if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { + return nil + } + + // See RFC 8446, Section 4.6.1. + if msg.lifetime == 0 { + return nil + } + lifetime := time.Duration(msg.lifetime) * time.Second + if lifetime > maxSessionTicketLifetime { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: received a session ticket with invalid lifetime") + } + + cipherSuite := cipherSuiteTLS13ByID(c.cipherSuite) + if cipherSuite == nil || c.resumptionSecret == nil { + return c.sendAlert(alertInternalError) + } + + // Save the resumption_master_secret and nonce instead of deriving the PSK + // to do the least amount of work on NewSessionTicket messages before we + // know if the ticket will be used. Forward secrecy of resumed connections + // is guaranteed by the requirement for pskModeDHE. + session := &ClientSessionState{ + sessionTicket: msg.label, + vers: c.vers, + cipherSuite: c.cipherSuite, + masterSecret: c.resumptionSecret, + serverCertificates: c.peerCertificates, + verifiedChains: c.verifiedChains, + receivedAt: c.config.time(), + nonce: msg.nonce, + useBy: c.config.time().Add(lifetime), + ageAdd: msg.ageAdd, + ocspResponse: c.ocspResponse, + scts: c.scts, + } + + cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config) + c.config.ClientSessionCache.Put(cacheKey, session) + + return nil +} diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go new file mode 100644 index 0000000..b5f81e4 --- /dev/null +++ b/src/crypto/tls/handshake_messages.go @@ -0,0 +1,1809 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "fmt" + "strings" + + "golang.org/x/crypto/cryptobyte" +) + +// The marshalingFunction type is an adapter to allow the use of ordinary +// functions as cryptobyte.MarshalingValue. +type marshalingFunction func(b *cryptobyte.Builder) error + +func (f marshalingFunction) Marshal(b *cryptobyte.Builder) error { + return f(b) +} + +// addBytesWithLength appends a sequence of bytes to the cryptobyte.Builder. If +// the length of the sequence is not the value specified, it produces an error. +func addBytesWithLength(b *cryptobyte.Builder, v []byte, n int) { + b.AddValue(marshalingFunction(func(b *cryptobyte.Builder) error { + if len(v) != n { + return fmt.Errorf("invalid value length: expected %d, got %d", n, len(v)) + } + b.AddBytes(v) + return nil + })) +} + +// addUint64 appends a big-endian, 64-bit value to the cryptobyte.Builder. +func addUint64(b *cryptobyte.Builder, v uint64) { + b.AddUint32(uint32(v >> 32)) + b.AddUint32(uint32(v)) +} + +// readUint64 decodes a big-endian, 64-bit value into out and advances over it. +// It reports whether the read was successful. +func readUint64(s *cryptobyte.String, out *uint64) bool { + var hi, lo uint32 + if !s.ReadUint32(&hi) || !s.ReadUint32(&lo) { + return false + } + *out = uint64(hi)<<32 | uint64(lo) + return true +} + +// readUint8LengthPrefixed acts like s.ReadUint8LengthPrefixed, but targets a +// []byte instead of a cryptobyte.String. +func readUint8LengthPrefixed(s *cryptobyte.String, out *[]byte) bool { + return s.ReadUint8LengthPrefixed((*cryptobyte.String)(out)) +} + +// readUint16LengthPrefixed acts like s.ReadUint16LengthPrefixed, but targets a +// []byte instead of a cryptobyte.String. +func readUint16LengthPrefixed(s *cryptobyte.String, out *[]byte) bool { + return s.ReadUint16LengthPrefixed((*cryptobyte.String)(out)) +} + +// readUint24LengthPrefixed acts like s.ReadUint24LengthPrefixed, but targets a +// []byte instead of a cryptobyte.String. +func readUint24LengthPrefixed(s *cryptobyte.String, out *[]byte) bool { + return s.ReadUint24LengthPrefixed((*cryptobyte.String)(out)) +} + +type clientHelloMsg struct { + raw []byte + vers uint16 + random []byte + sessionId []byte + cipherSuites []uint16 + compressionMethods []uint8 + serverName string + ocspStapling bool + supportedCurves []CurveID + supportedPoints []uint8 + ticketSupported bool + sessionTicket []uint8 + supportedSignatureAlgorithms []SignatureScheme + supportedSignatureAlgorithmsCert []SignatureScheme + secureRenegotiationSupported bool + secureRenegotiation []byte + alpnProtocols []string + scts bool + supportedVersions []uint16 + cookie []byte + keyShares []keyShare + earlyData bool + pskModes []uint8 + pskIdentities []pskIdentity + pskBinders [][]byte +} + +func (m *clientHelloMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeClientHello) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16(m.vers) + addBytesWithLength(b, m.random, 32) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.sessionId) + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, suite := range m.cipherSuites { + b.AddUint16(suite) + } + }) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.compressionMethods) + }) + + // If extensions aren't present, omit them. + var extensionsPresent bool + bWithoutExtensions := *b + + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + if len(m.serverName) > 0 { + // RFC 6066, Section 3 + b.AddUint16(extensionServerName) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8(0) // name_type = host_name + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes([]byte(m.serverName)) + }) + }) + }) + } + if m.ocspStapling { + // RFC 4366, Section 3.6 + b.AddUint16(extensionStatusRequest) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8(1) // status_type = ocsp + b.AddUint16(0) // empty responder_id_list + b.AddUint16(0) // empty request_extensions + }) + } + if len(m.supportedCurves) > 0 { + // RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7 + b.AddUint16(extensionSupportedCurves) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, curve := range m.supportedCurves { + b.AddUint16(uint16(curve)) + } + }) + }) + } + if len(m.supportedPoints) > 0 { + // RFC 4492, Section 5.1.2 + b.AddUint16(extensionSupportedPoints) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.supportedPoints) + }) + }) + } + if m.ticketSupported { + // RFC 5077, Section 3.2 + b.AddUint16(extensionSessionTicket) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.sessionTicket) + }) + } + if len(m.supportedSignatureAlgorithms) > 0 { + // RFC 5246, Section 7.4.1.4.1 + b.AddUint16(extensionSignatureAlgorithms) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, sigAlgo := range m.supportedSignatureAlgorithms { + b.AddUint16(uint16(sigAlgo)) + } + }) + }) + } + if len(m.supportedSignatureAlgorithmsCert) > 0 { + // RFC 8446, Section 4.2.3 + b.AddUint16(extensionSignatureAlgorithmsCert) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, sigAlgo := range m.supportedSignatureAlgorithmsCert { + b.AddUint16(uint16(sigAlgo)) + } + }) + }) + } + if m.secureRenegotiationSupported { + // RFC 5746, Section 3.2 + b.AddUint16(extensionRenegotiationInfo) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.secureRenegotiation) + }) + }) + } + if len(m.alpnProtocols) > 0 { + // RFC 7301, Section 3.1 + b.AddUint16(extensionALPN) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, proto := range m.alpnProtocols { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes([]byte(proto)) + }) + } + }) + }) + } + if m.scts { + // RFC 6962, Section 3.3.1 + b.AddUint16(extensionSCT) + b.AddUint16(0) // empty extension_data + } + if len(m.supportedVersions) > 0 { + // RFC 8446, Section 4.2.1 + b.AddUint16(extensionSupportedVersions) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + for _, vers := range m.supportedVersions { + b.AddUint16(vers) + } + }) + }) + } + if len(m.cookie) > 0 { + // RFC 8446, Section 4.2.2 + b.AddUint16(extensionCookie) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.cookie) + }) + }) + } + if len(m.keyShares) > 0 { + // RFC 8446, Section 4.2.8 + b.AddUint16(extensionKeyShare) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, ks := range m.keyShares { + b.AddUint16(uint16(ks.group)) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(ks.data) + }) + } + }) + }) + } + if m.earlyData { + // RFC 8446, Section 4.2.10 + b.AddUint16(extensionEarlyData) + b.AddUint16(0) // empty extension_data + } + if len(m.pskModes) > 0 { + // RFC 8446, Section 4.2.9 + b.AddUint16(extensionPSKModes) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.pskModes) + }) + }) + } + if len(m.pskIdentities) > 0 { // pre_shared_key must be the last extension + // RFC 8446, Section 4.2.11 + b.AddUint16(extensionPreSharedKey) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, psk := range m.pskIdentities { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(psk.label) + }) + b.AddUint32(psk.obfuscatedTicketAge) + } + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, binder := range m.pskBinders { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(binder) + }) + } + }) + }) + } + + extensionsPresent = len(b.BytesOrPanic()) > 2 + }) + + if !extensionsPresent { + *b = bWithoutExtensions + } + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +// marshalWithoutBinders returns the ClientHello through the +// PreSharedKeyExtension.identities field, according to RFC 8446, Section +// 4.2.11.2. Note that m.pskBinders must be set to slices of the correct length. +func (m *clientHelloMsg) marshalWithoutBinders() []byte { + bindersLen := 2 // uint16 length prefix + for _, binder := range m.pskBinders { + bindersLen += 1 // uint8 length prefix + bindersLen += len(binder) + } + + fullMessage := m.marshal() + return fullMessage[:len(fullMessage)-bindersLen] +} + +// updateBinders updates the m.pskBinders field, if necessary updating the +// cached marshaled representation. The supplied binders must have the same +// length as the current m.pskBinders. +func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) { + if len(pskBinders) != len(m.pskBinders) { + panic("tls: internal error: pskBinders length mismatch") + } + for i := range m.pskBinders { + if len(pskBinders[i]) != len(m.pskBinders[i]) { + panic("tls: internal error: pskBinders length mismatch") + } + } + m.pskBinders = pskBinders + if m.raw != nil { + lenWithoutBinders := len(m.marshalWithoutBinders()) + // TODO(filippo): replace with NewFixedBuilder once CL 148882 is imported. + b := cryptobyte.NewBuilder(m.raw[:lenWithoutBinders]) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, binder := range m.pskBinders { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(binder) + }) + } + }) + if len(b.BytesOrPanic()) != len(m.raw) { + panic("tls: internal error: failed to update binders") + } + } +} + +func (m *clientHelloMsg) unmarshal(data []byte) bool { + *m = clientHelloMsg{raw: data} + s := cryptobyte.String(data) + + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint16(&m.vers) || !s.ReadBytes(&m.random, 32) || + !readUint8LengthPrefixed(&s, &m.sessionId) { + return false + } + + var cipherSuites cryptobyte.String + if !s.ReadUint16LengthPrefixed(&cipherSuites) { + return false + } + m.cipherSuites = []uint16{} + m.secureRenegotiationSupported = false + for !cipherSuites.Empty() { + var suite uint16 + if !cipherSuites.ReadUint16(&suite) { + return false + } + if suite == scsvRenegotiation { + m.secureRenegotiationSupported = true + } + m.cipherSuites = append(m.cipherSuites, suite) + } + + if !readUint8LengthPrefixed(&s, &m.compressionMethods) { + return false + } + + if s.Empty() { + // ClientHello is optionally followed by extension data + return true + } + + var extensions cryptobyte.String + if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { + return false + } + + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + return false + } + + switch extension { + case extensionServerName: + // RFC 6066, Section 3 + var nameList cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&nameList) || nameList.Empty() { + return false + } + for !nameList.Empty() { + var nameType uint8 + var serverName cryptobyte.String + if !nameList.ReadUint8(&nameType) || + !nameList.ReadUint16LengthPrefixed(&serverName) || + serverName.Empty() { + return false + } + if nameType != 0 { + continue + } + if len(m.serverName) != 0 { + // Multiple names of the same name_type are prohibited. + return false + } + m.serverName = string(serverName) + // An SNI value may not include a trailing dot. + if strings.HasSuffix(m.serverName, ".") { + return false + } + } + case extensionStatusRequest: + // RFC 4366, Section 3.6 + var statusType uint8 + var ignored cryptobyte.String + if !extData.ReadUint8(&statusType) || + !extData.ReadUint16LengthPrefixed(&ignored) || + !extData.ReadUint16LengthPrefixed(&ignored) { + return false + } + m.ocspStapling = statusType == statusTypeOCSP + case extensionSupportedCurves: + // RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7 + var curves cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&curves) || curves.Empty() { + return false + } + for !curves.Empty() { + var curve uint16 + if !curves.ReadUint16(&curve) { + return false + } + m.supportedCurves = append(m.supportedCurves, CurveID(curve)) + } + case extensionSupportedPoints: + // RFC 4492, Section 5.1.2 + if !readUint8LengthPrefixed(&extData, &m.supportedPoints) || + len(m.supportedPoints) == 0 { + return false + } + case extensionSessionTicket: + // RFC 5077, Section 3.2 + m.ticketSupported = true + extData.ReadBytes(&m.sessionTicket, len(extData)) + case extensionSignatureAlgorithms: + // RFC 5246, Section 7.4.1.4.1 + var sigAndAlgs cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { + return false + } + for !sigAndAlgs.Empty() { + var sigAndAlg uint16 + if !sigAndAlgs.ReadUint16(&sigAndAlg) { + return false + } + m.supportedSignatureAlgorithms = append( + m.supportedSignatureAlgorithms, SignatureScheme(sigAndAlg)) + } + case extensionSignatureAlgorithmsCert: + // RFC 8446, Section 4.2.3 + var sigAndAlgs cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { + return false + } + for !sigAndAlgs.Empty() { + var sigAndAlg uint16 + if !sigAndAlgs.ReadUint16(&sigAndAlg) { + return false + } + m.supportedSignatureAlgorithmsCert = append( + m.supportedSignatureAlgorithmsCert, SignatureScheme(sigAndAlg)) + } + case extensionRenegotiationInfo: + // RFC 5746, Section 3.2 + if !readUint8LengthPrefixed(&extData, &m.secureRenegotiation) { + return false + } + m.secureRenegotiationSupported = true + case extensionALPN: + // RFC 7301, Section 3.1 + var protoList cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() { + return false + } + for !protoList.Empty() { + var proto cryptobyte.String + if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() { + return false + } + m.alpnProtocols = append(m.alpnProtocols, string(proto)) + } + case extensionSCT: + // RFC 6962, Section 3.3.1 + m.scts = true + case extensionSupportedVersions: + // RFC 8446, Section 4.2.1 + var versList cryptobyte.String + if !extData.ReadUint8LengthPrefixed(&versList) || versList.Empty() { + return false + } + for !versList.Empty() { + var vers uint16 + if !versList.ReadUint16(&vers) { + return false + } + m.supportedVersions = append(m.supportedVersions, vers) + } + case extensionCookie: + // RFC 8446, Section 4.2.2 + if !readUint16LengthPrefixed(&extData, &m.cookie) || + len(m.cookie) == 0 { + return false + } + case extensionKeyShare: + // RFC 8446, Section 4.2.8 + var clientShares cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&clientShares) { + return false + } + for !clientShares.Empty() { + var ks keyShare + if !clientShares.ReadUint16((*uint16)(&ks.group)) || + !readUint16LengthPrefixed(&clientShares, &ks.data) || + len(ks.data) == 0 { + return false + } + m.keyShares = append(m.keyShares, ks) + } + case extensionEarlyData: + // RFC 8446, Section 4.2.10 + m.earlyData = true + case extensionPSKModes: + // RFC 8446, Section 4.2.9 + if !readUint8LengthPrefixed(&extData, &m.pskModes) { + return false + } + case extensionPreSharedKey: + // RFC 8446, Section 4.2.11 + if !extensions.Empty() { + return false // pre_shared_key must be the last extension + } + var identities cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&identities) || identities.Empty() { + return false + } + for !identities.Empty() { + var psk pskIdentity + if !readUint16LengthPrefixed(&identities, &psk.label) || + !identities.ReadUint32(&psk.obfuscatedTicketAge) || + len(psk.label) == 0 { + return false + } + m.pskIdentities = append(m.pskIdentities, psk) + } + var binders cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&binders) || binders.Empty() { + return false + } + for !binders.Empty() { + var binder []byte + if !readUint8LengthPrefixed(&binders, &binder) || + len(binder) == 0 { + return false + } + m.pskBinders = append(m.pskBinders, binder) + } + default: + // Ignore unknown extensions. + continue + } + + if !extData.Empty() { + return false + } + } + + return true +} + +type serverHelloMsg struct { + raw []byte + vers uint16 + random []byte + sessionId []byte + cipherSuite uint16 + compressionMethod uint8 + ocspStapling bool + ticketSupported bool + secureRenegotiationSupported bool + secureRenegotiation []byte + alpnProtocol string + scts [][]byte + supportedVersion uint16 + serverShare keyShare + selectedIdentityPresent bool + selectedIdentity uint16 + supportedPoints []uint8 + + // HelloRetryRequest extensions + cookie []byte + selectedGroup CurveID +} + +func (m *serverHelloMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeServerHello) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16(m.vers) + addBytesWithLength(b, m.random, 32) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.sessionId) + }) + b.AddUint16(m.cipherSuite) + b.AddUint8(m.compressionMethod) + + // If extensions aren't present, omit them. + var extensionsPresent bool + bWithoutExtensions := *b + + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + if m.ocspStapling { + b.AddUint16(extensionStatusRequest) + b.AddUint16(0) // empty extension_data + } + if m.ticketSupported { + b.AddUint16(extensionSessionTicket) + b.AddUint16(0) // empty extension_data + } + if m.secureRenegotiationSupported { + b.AddUint16(extensionRenegotiationInfo) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.secureRenegotiation) + }) + }) + } + if len(m.alpnProtocol) > 0 { + b.AddUint16(extensionALPN) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes([]byte(m.alpnProtocol)) + }) + }) + }) + } + if len(m.scts) > 0 { + b.AddUint16(extensionSCT) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, sct := range m.scts { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(sct) + }) + } + }) + }) + } + if m.supportedVersion != 0 { + b.AddUint16(extensionSupportedVersions) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16(m.supportedVersion) + }) + } + if m.serverShare.group != 0 { + b.AddUint16(extensionKeyShare) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16(uint16(m.serverShare.group)) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.serverShare.data) + }) + }) + } + if m.selectedIdentityPresent { + b.AddUint16(extensionPreSharedKey) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16(m.selectedIdentity) + }) + } + + if len(m.cookie) > 0 { + b.AddUint16(extensionCookie) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.cookie) + }) + }) + } + if m.selectedGroup != 0 { + b.AddUint16(extensionKeyShare) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16(uint16(m.selectedGroup)) + }) + } + if len(m.supportedPoints) > 0 { + b.AddUint16(extensionSupportedPoints) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.supportedPoints) + }) + }) + } + + extensionsPresent = len(b.BytesOrPanic()) > 2 + }) + + if !extensionsPresent { + *b = bWithoutExtensions + } + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func (m *serverHelloMsg) unmarshal(data []byte) bool { + *m = serverHelloMsg{raw: data} + s := cryptobyte.String(data) + + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint16(&m.vers) || !s.ReadBytes(&m.random, 32) || + !readUint8LengthPrefixed(&s, &m.sessionId) || + !s.ReadUint16(&m.cipherSuite) || + !s.ReadUint8(&m.compressionMethod) { + return false + } + + if s.Empty() { + // ServerHello is optionally followed by extension data + return true + } + + var extensions cryptobyte.String + if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { + return false + } + + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + return false + } + + switch extension { + case extensionStatusRequest: + m.ocspStapling = true + case extensionSessionTicket: + m.ticketSupported = true + case extensionRenegotiationInfo: + if !readUint8LengthPrefixed(&extData, &m.secureRenegotiation) { + return false + } + m.secureRenegotiationSupported = true + case extensionALPN: + var protoList cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() { + return false + } + var proto cryptobyte.String + if !protoList.ReadUint8LengthPrefixed(&proto) || + proto.Empty() || !protoList.Empty() { + return false + } + m.alpnProtocol = string(proto) + case extensionSCT: + var sctList cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&sctList) || sctList.Empty() { + return false + } + for !sctList.Empty() { + var sct []byte + if !readUint16LengthPrefixed(&sctList, &sct) || + len(sct) == 0 { + return false + } + m.scts = append(m.scts, sct) + } + case extensionSupportedVersions: + if !extData.ReadUint16(&m.supportedVersion) { + return false + } + case extensionCookie: + if !readUint16LengthPrefixed(&extData, &m.cookie) || + len(m.cookie) == 0 { + return false + } + case extensionKeyShare: + // This extension has different formats in SH and HRR, accept either + // and let the handshake logic decide. See RFC 8446, Section 4.2.8. + if len(extData) == 2 { + if !extData.ReadUint16((*uint16)(&m.selectedGroup)) { + return false + } + } else { + if !extData.ReadUint16((*uint16)(&m.serverShare.group)) || + !readUint16LengthPrefixed(&extData, &m.serverShare.data) { + return false + } + } + case extensionPreSharedKey: + m.selectedIdentityPresent = true + if !extData.ReadUint16(&m.selectedIdentity) { + return false + } + case extensionSupportedPoints: + // RFC 4492, Section 5.1.2 + if !readUint8LengthPrefixed(&extData, &m.supportedPoints) || + len(m.supportedPoints) == 0 { + return false + } + default: + // Ignore unknown extensions. + continue + } + + if !extData.Empty() { + return false + } + } + + return true +} + +type encryptedExtensionsMsg struct { + raw []byte + alpnProtocol string +} + +func (m *encryptedExtensionsMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeEncryptedExtensions) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + if len(m.alpnProtocol) > 0 { + b.AddUint16(extensionALPN) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes([]byte(m.alpnProtocol)) + }) + }) + }) + } + }) + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { + *m = encryptedExtensionsMsg{raw: data} + s := cryptobyte.String(data) + + var extensions cryptobyte.String + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { + return false + } + + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + return false + } + + switch extension { + case extensionALPN: + var protoList cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() { + return false + } + var proto cryptobyte.String + if !protoList.ReadUint8LengthPrefixed(&proto) || + proto.Empty() || !protoList.Empty() { + return false + } + m.alpnProtocol = string(proto) + default: + // Ignore unknown extensions. + continue + } + + if !extData.Empty() { + return false + } + } + + return true +} + +type endOfEarlyDataMsg struct{} + +func (m *endOfEarlyDataMsg) marshal() []byte { + x := make([]byte, 4) + x[0] = typeEndOfEarlyData + return x +} + +func (m *endOfEarlyDataMsg) unmarshal(data []byte) bool { + return len(data) == 4 +} + +type keyUpdateMsg struct { + raw []byte + updateRequested bool +} + +func (m *keyUpdateMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeKeyUpdate) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + if m.updateRequested { + b.AddUint8(1) + } else { + b.AddUint8(0) + } + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func (m *keyUpdateMsg) unmarshal(data []byte) bool { + m.raw = data + s := cryptobyte.String(data) + + var updateRequested uint8 + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint8(&updateRequested) || !s.Empty() { + return false + } + switch updateRequested { + case 0: + m.updateRequested = false + case 1: + m.updateRequested = true + default: + return false + } + return true +} + +type newSessionTicketMsgTLS13 struct { + raw []byte + lifetime uint32 + ageAdd uint32 + nonce []byte + label []byte + maxEarlyData uint32 +} + +func (m *newSessionTicketMsgTLS13) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeNewSessionTicket) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint32(m.lifetime) + b.AddUint32(m.ageAdd) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.nonce) + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.label) + }) + + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + if m.maxEarlyData > 0 { + b.AddUint16(extensionEarlyData) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint32(m.maxEarlyData) + }) + } + }) + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func (m *newSessionTicketMsgTLS13) unmarshal(data []byte) bool { + *m = newSessionTicketMsgTLS13{raw: data} + s := cryptobyte.String(data) + + var extensions cryptobyte.String + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint32(&m.lifetime) || + !s.ReadUint32(&m.ageAdd) || + !readUint8LengthPrefixed(&s, &m.nonce) || + !readUint16LengthPrefixed(&s, &m.label) || + !s.ReadUint16LengthPrefixed(&extensions) || + !s.Empty() { + return false + } + + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + return false + } + + switch extension { + case extensionEarlyData: + if !extData.ReadUint32(&m.maxEarlyData) { + return false + } + default: + // Ignore unknown extensions. + continue + } + + if !extData.Empty() { + return false + } + } + + return true +} + +type certificateRequestMsgTLS13 struct { + raw []byte + ocspStapling bool + scts bool + supportedSignatureAlgorithms []SignatureScheme + supportedSignatureAlgorithmsCert []SignatureScheme + certificateAuthorities [][]byte +} + +func (m *certificateRequestMsgTLS13) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeCertificateRequest) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + // certificate_request_context (SHALL be zero length unless used for + // post-handshake authentication) + b.AddUint8(0) + + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + if m.ocspStapling { + b.AddUint16(extensionStatusRequest) + b.AddUint16(0) // empty extension_data + } + if m.scts { + // RFC 8446, Section 4.4.2.1 makes no mention of + // signed_certificate_timestamp in CertificateRequest, but + // "Extensions in the Certificate message from the client MUST + // correspond to extensions in the CertificateRequest message + // from the server." and it appears in the table in Section 4.2. + b.AddUint16(extensionSCT) + b.AddUint16(0) // empty extension_data + } + if len(m.supportedSignatureAlgorithms) > 0 { + b.AddUint16(extensionSignatureAlgorithms) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, sigAlgo := range m.supportedSignatureAlgorithms { + b.AddUint16(uint16(sigAlgo)) + } + }) + }) + } + if len(m.supportedSignatureAlgorithmsCert) > 0 { + b.AddUint16(extensionSignatureAlgorithmsCert) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, sigAlgo := range m.supportedSignatureAlgorithmsCert { + b.AddUint16(uint16(sigAlgo)) + } + }) + }) + } + if len(m.certificateAuthorities) > 0 { + b.AddUint16(extensionCertificateAuthorities) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, ca := range m.certificateAuthorities { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(ca) + }) + } + }) + }) + } + }) + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func (m *certificateRequestMsgTLS13) unmarshal(data []byte) bool { + *m = certificateRequestMsgTLS13{raw: data} + s := cryptobyte.String(data) + + var context, extensions cryptobyte.String + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint8LengthPrefixed(&context) || !context.Empty() || + !s.ReadUint16LengthPrefixed(&extensions) || + !s.Empty() { + return false + } + + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + return false + } + + switch extension { + case extensionStatusRequest: + m.ocspStapling = true + case extensionSCT: + m.scts = true + case extensionSignatureAlgorithms: + var sigAndAlgs cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { + return false + } + for !sigAndAlgs.Empty() { + var sigAndAlg uint16 + if !sigAndAlgs.ReadUint16(&sigAndAlg) { + return false + } + m.supportedSignatureAlgorithms = append( + m.supportedSignatureAlgorithms, SignatureScheme(sigAndAlg)) + } + case extensionSignatureAlgorithmsCert: + var sigAndAlgs cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { + return false + } + for !sigAndAlgs.Empty() { + var sigAndAlg uint16 + if !sigAndAlgs.ReadUint16(&sigAndAlg) { + return false + } + m.supportedSignatureAlgorithmsCert = append( + m.supportedSignatureAlgorithmsCert, SignatureScheme(sigAndAlg)) + } + case extensionCertificateAuthorities: + var auths cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&auths) || auths.Empty() { + return false + } + for !auths.Empty() { + var ca []byte + if !readUint16LengthPrefixed(&auths, &ca) || len(ca) == 0 { + return false + } + m.certificateAuthorities = append(m.certificateAuthorities, ca) + } + default: + // Ignore unknown extensions. + continue + } + + if !extData.Empty() { + return false + } + } + + return true +} + +type certificateMsg struct { + raw []byte + certificates [][]byte +} + +func (m *certificateMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + var i int + for _, slice := range m.certificates { + i += len(slice) + } + + length := 3 + 3*len(m.certificates) + i + x = make([]byte, 4+length) + x[0] = typeCertificate + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + + certificateOctets := length - 3 + x[4] = uint8(certificateOctets >> 16) + x[5] = uint8(certificateOctets >> 8) + x[6] = uint8(certificateOctets) + + y := x[7:] + for _, slice := range m.certificates { + y[0] = uint8(len(slice) >> 16) + y[1] = uint8(len(slice) >> 8) + y[2] = uint8(len(slice)) + copy(y[3:], slice) + y = y[3+len(slice):] + } + + m.raw = x + return +} + +func (m *certificateMsg) unmarshal(data []byte) bool { + if len(data) < 7 { + return false + } + + m.raw = data + certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6]) + if uint32(len(data)) != certsLen+7 { + return false + } + + numCerts := 0 + d := data[7:] + for certsLen > 0 { + if len(d) < 4 { + return false + } + certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2]) + if uint32(len(d)) < 3+certLen { + return false + } + d = d[3+certLen:] + certsLen -= 3 + certLen + numCerts++ + } + + m.certificates = make([][]byte, numCerts) + d = data[7:] + for i := 0; i < numCerts; i++ { + certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2]) + m.certificates[i] = d[3 : 3+certLen] + d = d[3+certLen:] + } + + return true +} + +type certificateMsgTLS13 struct { + raw []byte + certificate Certificate + ocspStapling bool + scts bool +} + +func (m *certificateMsgTLS13) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeCertificate) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8(0) // certificate_request_context + + certificate := m.certificate + if !m.ocspStapling { + certificate.OCSPStaple = nil + } + if !m.scts { + certificate.SignedCertificateTimestamps = nil + } + marshalCertificate(b, certificate) + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func marshalCertificate(b *cryptobyte.Builder, certificate Certificate) { + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + for i, cert := range certificate.Certificate { + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(cert) + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + if i > 0 { + // This library only supports OCSP and SCT for leaf certificates. + return + } + if certificate.OCSPStaple != nil { + b.AddUint16(extensionStatusRequest) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8(statusTypeOCSP) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(certificate.OCSPStaple) + }) + }) + } + if certificate.SignedCertificateTimestamps != nil { + b.AddUint16(extensionSCT) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, sct := range certificate.SignedCertificateTimestamps { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(sct) + }) + } + }) + }) + } + }) + } + }) +} + +func (m *certificateMsgTLS13) unmarshal(data []byte) bool { + *m = certificateMsgTLS13{raw: data} + s := cryptobyte.String(data) + + var context cryptobyte.String + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint8LengthPrefixed(&context) || !context.Empty() || + !unmarshalCertificate(&s, &m.certificate) || + !s.Empty() { + return false + } + + m.scts = m.certificate.SignedCertificateTimestamps != nil + m.ocspStapling = m.certificate.OCSPStaple != nil + + return true +} + +func unmarshalCertificate(s *cryptobyte.String, certificate *Certificate) bool { + var certList cryptobyte.String + if !s.ReadUint24LengthPrefixed(&certList) { + return false + } + for !certList.Empty() { + var cert []byte + var extensions cryptobyte.String + if !readUint24LengthPrefixed(&certList, &cert) || + !certList.ReadUint16LengthPrefixed(&extensions) { + return false + } + certificate.Certificate = append(certificate.Certificate, cert) + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + return false + } + if len(certificate.Certificate) > 1 { + // This library only supports OCSP and SCT for leaf certificates. + continue + } + + switch extension { + case extensionStatusRequest: + var statusType uint8 + if !extData.ReadUint8(&statusType) || statusType != statusTypeOCSP || + !readUint24LengthPrefixed(&extData, &certificate.OCSPStaple) || + len(certificate.OCSPStaple) == 0 { + return false + } + case extensionSCT: + var sctList cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&sctList) || sctList.Empty() { + return false + } + for !sctList.Empty() { + var sct []byte + if !readUint16LengthPrefixed(&sctList, &sct) || + len(sct) == 0 { + return false + } + certificate.SignedCertificateTimestamps = append( + certificate.SignedCertificateTimestamps, sct) + } + default: + // Ignore unknown extensions. + continue + } + + if !extData.Empty() { + return false + } + } + } + return true +} + +type serverKeyExchangeMsg struct { + raw []byte + key []byte +} + +func (m *serverKeyExchangeMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + length := len(m.key) + x := make([]byte, length+4) + x[0] = typeServerKeyExchange + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + copy(x[4:], m.key) + + m.raw = x + return x +} + +func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool { + m.raw = data + if len(data) < 4 { + return false + } + m.key = data[4:] + return true +} + +type certificateStatusMsg struct { + raw []byte + response []byte +} + +func (m *certificateStatusMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeCertificateStatus) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8(statusTypeOCSP) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.response) + }) + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func (m *certificateStatusMsg) unmarshal(data []byte) bool { + m.raw = data + s := cryptobyte.String(data) + + var statusType uint8 + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint8(&statusType) || statusType != statusTypeOCSP || + !readUint24LengthPrefixed(&s, &m.response) || + len(m.response) == 0 || !s.Empty() { + return false + } + return true +} + +type serverHelloDoneMsg struct{} + +func (m *serverHelloDoneMsg) marshal() []byte { + x := make([]byte, 4) + x[0] = typeServerHelloDone + return x +} + +func (m *serverHelloDoneMsg) unmarshal(data []byte) bool { + return len(data) == 4 +} + +type clientKeyExchangeMsg struct { + raw []byte + ciphertext []byte +} + +func (m *clientKeyExchangeMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + length := len(m.ciphertext) + x := make([]byte, length+4) + x[0] = typeClientKeyExchange + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + copy(x[4:], m.ciphertext) + + m.raw = x + return x +} + +func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool { + m.raw = data + if len(data) < 4 { + return false + } + l := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) + if l != len(data)-4 { + return false + } + m.ciphertext = data[4:] + return true +} + +type finishedMsg struct { + raw []byte + verifyData []byte +} + +func (m *finishedMsg) marshal() []byte { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeFinished) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.verifyData) + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func (m *finishedMsg) unmarshal(data []byte) bool { + m.raw = data + s := cryptobyte.String(data) + return s.Skip(1) && + readUint24LengthPrefixed(&s, &m.verifyData) && + s.Empty() +} + +type certificateRequestMsg struct { + raw []byte + // hasSignatureAlgorithm indicates whether this message includes a list of + // supported signature algorithms. This change was introduced with TLS 1.2. + hasSignatureAlgorithm bool + + certificateTypes []byte + supportedSignatureAlgorithms []SignatureScheme + certificateAuthorities [][]byte +} + +func (m *certificateRequestMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + // See RFC 4346, Section 7.4.4. + length := 1 + len(m.certificateTypes) + 2 + casLength := 0 + for _, ca := range m.certificateAuthorities { + casLength += 2 + len(ca) + } + length += casLength + + if m.hasSignatureAlgorithm { + length += 2 + 2*len(m.supportedSignatureAlgorithms) + } + + x = make([]byte, 4+length) + x[0] = typeCertificateRequest + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + + x[4] = uint8(len(m.certificateTypes)) + + copy(x[5:], m.certificateTypes) + y := x[5+len(m.certificateTypes):] + + if m.hasSignatureAlgorithm { + n := len(m.supportedSignatureAlgorithms) * 2 + y[0] = uint8(n >> 8) + y[1] = uint8(n) + y = y[2:] + for _, sigAlgo := range m.supportedSignatureAlgorithms { + y[0] = uint8(sigAlgo >> 8) + y[1] = uint8(sigAlgo) + y = y[2:] + } + } + + y[0] = uint8(casLength >> 8) + y[1] = uint8(casLength) + y = y[2:] + for _, ca := range m.certificateAuthorities { + y[0] = uint8(len(ca) >> 8) + y[1] = uint8(len(ca)) + y = y[2:] + copy(y, ca) + y = y[len(ca):] + } + + m.raw = x + return +} + +func (m *certificateRequestMsg) unmarshal(data []byte) bool { + m.raw = data + + if len(data) < 5 { + return false + } + + length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) + if uint32(len(data))-4 != length { + return false + } + + numCertTypes := int(data[4]) + data = data[5:] + if numCertTypes == 0 || len(data) <= numCertTypes { + return false + } + + m.certificateTypes = make([]byte, numCertTypes) + if copy(m.certificateTypes, data) != numCertTypes { + return false + } + + data = data[numCertTypes:] + + if m.hasSignatureAlgorithm { + if len(data) < 2 { + return false + } + sigAndHashLen := uint16(data[0])<<8 | uint16(data[1]) + data = data[2:] + if sigAndHashLen&1 != 0 { + return false + } + if len(data) < int(sigAndHashLen) { + return false + } + numSigAlgos := sigAndHashLen / 2 + m.supportedSignatureAlgorithms = make([]SignatureScheme, numSigAlgos) + for i := range m.supportedSignatureAlgorithms { + m.supportedSignatureAlgorithms[i] = SignatureScheme(data[0])<<8 | SignatureScheme(data[1]) + data = data[2:] + } + } + + if len(data) < 2 { + return false + } + casLength := uint16(data[0])<<8 | uint16(data[1]) + data = data[2:] + if len(data) < int(casLength) { + return false + } + cas := make([]byte, casLength) + copy(cas, data) + data = data[casLength:] + + m.certificateAuthorities = nil + for len(cas) > 0 { + if len(cas) < 2 { + return false + } + caLen := uint16(cas[0])<<8 | uint16(cas[1]) + cas = cas[2:] + + if len(cas) < int(caLen) { + return false + } + + m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen]) + cas = cas[caLen:] + } + + return len(data) == 0 +} + +type certificateVerifyMsg struct { + raw []byte + hasSignatureAlgorithm bool // format change introduced in TLS 1.2 + signatureAlgorithm SignatureScheme + signature []byte +} + +func (m *certificateVerifyMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + var b cryptobyte.Builder + b.AddUint8(typeCertificateVerify) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + if m.hasSignatureAlgorithm { + b.AddUint16(uint16(m.signatureAlgorithm)) + } + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.signature) + }) + }) + + m.raw = b.BytesOrPanic() + return m.raw +} + +func (m *certificateVerifyMsg) unmarshal(data []byte) bool { + m.raw = data + s := cryptobyte.String(data) + + if !s.Skip(4) { // message type and uint24 length field + return false + } + if m.hasSignatureAlgorithm { + if !s.ReadUint16((*uint16)(&m.signatureAlgorithm)) { + return false + } + } + return readUint16LengthPrefixed(&s, &m.signature) && s.Empty() +} + +type newSessionTicketMsg struct { + raw []byte + ticket []byte +} + +func (m *newSessionTicketMsg) marshal() (x []byte) { + if m.raw != nil { + return m.raw + } + + // See RFC 5077, Section 3.3. + ticketLen := len(m.ticket) + length := 2 + 4 + ticketLen + x = make([]byte, 4+length) + x[0] = typeNewSessionTicket + x[1] = uint8(length >> 16) + x[2] = uint8(length >> 8) + x[3] = uint8(length) + x[8] = uint8(ticketLen >> 8) + x[9] = uint8(ticketLen) + copy(x[10:], m.ticket) + + m.raw = x + + return +} + +func (m *newSessionTicketMsg) unmarshal(data []byte) bool { + m.raw = data + + if len(data) < 10 { + return false + } + + length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) + if uint32(len(data))-4 != length { + return false + } + + ticketLen := int(data[8])<<8 + int(data[9]) + if len(data)-10 != ticketLen { + return false + } + + m.ticket = data[10:] + + return true +} + +type helloRequestMsg struct { +} + +func (*helloRequestMsg) marshal() []byte { + return []byte{typeHelloRequest, 0, 0, 0} +} + +func (*helloRequestMsg) unmarshal(data []byte) bool { + return len(data) == 4 +} diff --git a/src/crypto/tls/handshake_messages_test.go b/src/crypto/tls/handshake_messages_test.go new file mode 100644 index 0000000..bb8aea8 --- /dev/null +++ b/src/crypto/tls/handshake_messages_test.go @@ -0,0 +1,465 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "math/rand" + "reflect" + "strings" + "testing" + "testing/quick" + "time" +) + +var tests = []interface{}{ + &clientHelloMsg{}, + &serverHelloMsg{}, + &finishedMsg{}, + + &certificateMsg{}, + &certificateRequestMsg{}, + &certificateVerifyMsg{ + hasSignatureAlgorithm: true, + }, + &certificateStatusMsg{}, + &clientKeyExchangeMsg{}, + &newSessionTicketMsg{}, + &sessionState{}, + &sessionStateTLS13{}, + &encryptedExtensionsMsg{}, + &endOfEarlyDataMsg{}, + &keyUpdateMsg{}, + &newSessionTicketMsgTLS13{}, + &certificateRequestMsgTLS13{}, + &certificateMsgTLS13{}, +} + +func TestMarshalUnmarshal(t *testing.T) { + rand := rand.New(rand.NewSource(time.Now().UnixNano())) + + for i, iface := range tests { + ty := reflect.ValueOf(iface).Type() + + n := 100 + if testing.Short() { + n = 5 + } + for j := 0; j < n; j++ { + v, ok := quick.Value(ty, rand) + if !ok { + t.Errorf("#%d: failed to create value", i) + break + } + + m1 := v.Interface().(handshakeMessage) + marshaled := m1.marshal() + m2 := iface.(handshakeMessage) + if !m2.unmarshal(marshaled) { + t.Errorf("#%d failed to unmarshal %#v %x", i, m1, marshaled) + break + } + m2.marshal() // to fill any marshal cache in the message + + if !reflect.DeepEqual(m1, m2) { + t.Errorf("#%d got:%#v want:%#v %x", i, m2, m1, marshaled) + break + } + + if i >= 3 { + // The first three message types (ClientHello, + // ServerHello and Finished) are allowed to + // have parsable prefixes because the extension + // data is optional and the length of the + // Finished varies across versions. + for j := 0; j < len(marshaled); j++ { + if m2.unmarshal(marshaled[0:j]) { + t.Errorf("#%d unmarshaled a prefix of length %d of %#v", i, j, m1) + break + } + } + } + } + } +} + +func TestFuzz(t *testing.T) { + rand := rand.New(rand.NewSource(0)) + for _, iface := range tests { + m := iface.(handshakeMessage) + + for j := 0; j < 1000; j++ { + len := rand.Intn(100) + bytes := randomBytes(len, rand) + // This just looks for crashes due to bounds errors etc. + m.unmarshal(bytes) + } + } +} + +func randomBytes(n int, rand *rand.Rand) []byte { + r := make([]byte, n) + if _, err := rand.Read(r); err != nil { + panic("rand.Read failed: " + err.Error()) + } + return r +} + +func randomString(n int, rand *rand.Rand) string { + b := randomBytes(n, rand) + return string(b) +} + +func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &clientHelloMsg{} + m.vers = uint16(rand.Intn(65536)) + m.random = randomBytes(32, rand) + m.sessionId = randomBytes(rand.Intn(32), rand) + m.cipherSuites = make([]uint16, rand.Intn(63)+1) + for i := 0; i < len(m.cipherSuites); i++ { + cs := uint16(rand.Int31()) + if cs == scsvRenegotiation { + cs += 1 + } + m.cipherSuites[i] = cs + } + m.compressionMethods = randomBytes(rand.Intn(63)+1, rand) + if rand.Intn(10) > 5 { + m.serverName = randomString(rand.Intn(255), rand) + for strings.HasSuffix(m.serverName, ".") { + m.serverName = m.serverName[:len(m.serverName)-1] + } + } + m.ocspStapling = rand.Intn(10) > 5 + m.supportedPoints = randomBytes(rand.Intn(5)+1, rand) + m.supportedCurves = make([]CurveID, rand.Intn(5)+1) + for i := range m.supportedCurves { + m.supportedCurves[i] = CurveID(rand.Intn(30000) + 1) + } + if rand.Intn(10) > 5 { + m.ticketSupported = true + if rand.Intn(10) > 5 { + m.sessionTicket = randomBytes(rand.Intn(300), rand) + } else { + m.sessionTicket = make([]byte, 0) + } + } + if rand.Intn(10) > 5 { + m.supportedSignatureAlgorithms = supportedSignatureAlgorithms + } + if rand.Intn(10) > 5 { + m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms + } + for i := 0; i < rand.Intn(5); i++ { + m.alpnProtocols = append(m.alpnProtocols, randomString(rand.Intn(20)+1, rand)) + } + if rand.Intn(10) > 5 { + m.scts = true + } + if rand.Intn(10) > 5 { + m.secureRenegotiationSupported = true + m.secureRenegotiation = randomBytes(rand.Intn(50)+1, rand) + } + for i := 0; i < rand.Intn(5); i++ { + m.supportedVersions = append(m.supportedVersions, uint16(rand.Intn(0xffff)+1)) + } + if rand.Intn(10) > 5 { + m.cookie = randomBytes(rand.Intn(500)+1, rand) + } + for i := 0; i < rand.Intn(5); i++ { + var ks keyShare + ks.group = CurveID(rand.Intn(30000) + 1) + ks.data = randomBytes(rand.Intn(200)+1, rand) + m.keyShares = append(m.keyShares, ks) + } + switch rand.Intn(3) { + case 1: + m.pskModes = []uint8{pskModeDHE} + case 2: + m.pskModes = []uint8{pskModeDHE, pskModePlain} + } + for i := 0; i < rand.Intn(5); i++ { + var psk pskIdentity + psk.obfuscatedTicketAge = uint32(rand.Intn(500000)) + psk.label = randomBytes(rand.Intn(500)+1, rand) + m.pskIdentities = append(m.pskIdentities, psk) + m.pskBinders = append(m.pskBinders, randomBytes(rand.Intn(50)+32, rand)) + } + if rand.Intn(10) > 5 { + m.earlyData = true + } + + return reflect.ValueOf(m) +} + +func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &serverHelloMsg{} + m.vers = uint16(rand.Intn(65536)) + m.random = randomBytes(32, rand) + m.sessionId = randomBytes(rand.Intn(32), rand) + m.cipherSuite = uint16(rand.Int31()) + m.compressionMethod = uint8(rand.Intn(256)) + m.supportedPoints = randomBytes(rand.Intn(5)+1, rand) + + if rand.Intn(10) > 5 { + m.ocspStapling = true + } + if rand.Intn(10) > 5 { + m.ticketSupported = true + } + if rand.Intn(10) > 5 { + m.alpnProtocol = randomString(rand.Intn(32)+1, rand) + } + + for i := 0; i < rand.Intn(4); i++ { + m.scts = append(m.scts, randomBytes(rand.Intn(500)+1, rand)) + } + + if rand.Intn(10) > 5 { + m.secureRenegotiationSupported = true + m.secureRenegotiation = randomBytes(rand.Intn(50)+1, rand) + } + if rand.Intn(10) > 5 { + m.supportedVersion = uint16(rand.Intn(0xffff) + 1) + } + if rand.Intn(10) > 5 { + m.cookie = randomBytes(rand.Intn(500)+1, rand) + } + if rand.Intn(10) > 5 { + for i := 0; i < rand.Intn(5); i++ { + m.serverShare.group = CurveID(rand.Intn(30000) + 1) + m.serverShare.data = randomBytes(rand.Intn(200)+1, rand) + } + } else if rand.Intn(10) > 5 { + m.selectedGroup = CurveID(rand.Intn(30000) + 1) + } + if rand.Intn(10) > 5 { + m.selectedIdentityPresent = true + m.selectedIdentity = uint16(rand.Intn(0xffff)) + } + + return reflect.ValueOf(m) +} + +func (*encryptedExtensionsMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &encryptedExtensionsMsg{} + + if rand.Intn(10) > 5 { + m.alpnProtocol = randomString(rand.Intn(32)+1, rand) + } + + return reflect.ValueOf(m) +} + +func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &certificateMsg{} + numCerts := rand.Intn(20) + m.certificates = make([][]byte, numCerts) + for i := 0; i < numCerts; i++ { + m.certificates[i] = randomBytes(rand.Intn(10)+1, rand) + } + return reflect.ValueOf(m) +} + +func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &certificateRequestMsg{} + m.certificateTypes = randomBytes(rand.Intn(5)+1, rand) + for i := 0; i < rand.Intn(100); i++ { + m.certificateAuthorities = append(m.certificateAuthorities, randomBytes(rand.Intn(15)+1, rand)) + } + return reflect.ValueOf(m) +} + +func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &certificateVerifyMsg{} + m.hasSignatureAlgorithm = true + m.signatureAlgorithm = SignatureScheme(rand.Intn(30000)) + m.signature = randomBytes(rand.Intn(15)+1, rand) + return reflect.ValueOf(m) +} + +func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &certificateStatusMsg{} + m.response = randomBytes(rand.Intn(10)+1, rand) + return reflect.ValueOf(m) +} + +func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &clientKeyExchangeMsg{} + m.ciphertext = randomBytes(rand.Intn(1000)+1, rand) + return reflect.ValueOf(m) +} + +func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &finishedMsg{} + m.verifyData = randomBytes(12, rand) + return reflect.ValueOf(m) +} + +func (*newSessionTicketMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &newSessionTicketMsg{} + m.ticket = randomBytes(rand.Intn(4), rand) + return reflect.ValueOf(m) +} + +func (*sessionState) Generate(rand *rand.Rand, size int) reflect.Value { + s := &sessionState{} + s.vers = uint16(rand.Intn(10000)) + s.cipherSuite = uint16(rand.Intn(10000)) + s.masterSecret = randomBytes(rand.Intn(100)+1, rand) + s.createdAt = uint64(rand.Int63()) + for i := 0; i < rand.Intn(20); i++ { + s.certificates = append(s.certificates, randomBytes(rand.Intn(500)+1, rand)) + } + return reflect.ValueOf(s) +} + +func (*sessionStateTLS13) Generate(rand *rand.Rand, size int) reflect.Value { + s := &sessionStateTLS13{} + s.cipherSuite = uint16(rand.Intn(10000)) + s.resumptionSecret = randomBytes(rand.Intn(100)+1, rand) + s.createdAt = uint64(rand.Int63()) + for i := 0; i < rand.Intn(2)+1; i++ { + s.certificate.Certificate = append( + s.certificate.Certificate, randomBytes(rand.Intn(500)+1, rand)) + } + if rand.Intn(10) > 5 { + s.certificate.OCSPStaple = randomBytes(rand.Intn(100)+1, rand) + } + if rand.Intn(10) > 5 { + for i := 0; i < rand.Intn(2)+1; i++ { + s.certificate.SignedCertificateTimestamps = append( + s.certificate.SignedCertificateTimestamps, randomBytes(rand.Intn(500)+1, rand)) + } + } + return reflect.ValueOf(s) +} + +func (*endOfEarlyDataMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &endOfEarlyDataMsg{} + return reflect.ValueOf(m) +} + +func (*keyUpdateMsg) Generate(rand *rand.Rand, size int) reflect.Value { + m := &keyUpdateMsg{} + m.updateRequested = rand.Intn(10) > 5 + return reflect.ValueOf(m) +} + +func (*newSessionTicketMsgTLS13) Generate(rand *rand.Rand, size int) reflect.Value { + m := &newSessionTicketMsgTLS13{} + m.lifetime = uint32(rand.Intn(500000)) + m.ageAdd = uint32(rand.Intn(500000)) + m.nonce = randomBytes(rand.Intn(100), rand) + m.label = randomBytes(rand.Intn(1000), rand) + if rand.Intn(10) > 5 { + m.maxEarlyData = uint32(rand.Intn(500000)) + } + return reflect.ValueOf(m) +} + +func (*certificateRequestMsgTLS13) Generate(rand *rand.Rand, size int) reflect.Value { + m := &certificateRequestMsgTLS13{} + if rand.Intn(10) > 5 { + m.ocspStapling = true + } + if rand.Intn(10) > 5 { + m.scts = true + } + if rand.Intn(10) > 5 { + m.supportedSignatureAlgorithms = supportedSignatureAlgorithms + } + if rand.Intn(10) > 5 { + m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms + } + if rand.Intn(10) > 5 { + m.certificateAuthorities = make([][]byte, 3) + for i := 0; i < 3; i++ { + m.certificateAuthorities[i] = randomBytes(rand.Intn(10)+1, rand) + } + } + return reflect.ValueOf(m) +} + +func (*certificateMsgTLS13) Generate(rand *rand.Rand, size int) reflect.Value { + m := &certificateMsgTLS13{} + for i := 0; i < rand.Intn(2)+1; i++ { + m.certificate.Certificate = append( + m.certificate.Certificate, randomBytes(rand.Intn(500)+1, rand)) + } + if rand.Intn(10) > 5 { + m.ocspStapling = true + m.certificate.OCSPStaple = randomBytes(rand.Intn(100)+1, rand) + } + if rand.Intn(10) > 5 { + m.scts = true + for i := 0; i < rand.Intn(2)+1; i++ { + m.certificate.SignedCertificateTimestamps = append( + m.certificate.SignedCertificateTimestamps, randomBytes(rand.Intn(500)+1, rand)) + } + } + return reflect.ValueOf(m) +} + +func TestRejectEmptySCTList(t *testing.T) { + // RFC 6962, Section 3.3.1 specifies that empty SCT lists are invalid. + + var random [32]byte + sct := []byte{0x42, 0x42, 0x42, 0x42} + serverHello := serverHelloMsg{ + vers: VersionTLS12, + random: random[:], + scts: [][]byte{sct}, + } + serverHelloBytes := serverHello.marshal() + + var serverHelloCopy serverHelloMsg + if !serverHelloCopy.unmarshal(serverHelloBytes) { + t.Fatal("Failed to unmarshal initial message") + } + + // Change serverHelloBytes so that the SCT list is empty + i := bytes.Index(serverHelloBytes, sct) + if i < 0 { + t.Fatal("Cannot find SCT in ServerHello") + } + + var serverHelloEmptySCT []byte + serverHelloEmptySCT = append(serverHelloEmptySCT, serverHelloBytes[:i-6]...) + // Append the extension length and SCT list length for an empty list. + serverHelloEmptySCT = append(serverHelloEmptySCT, []byte{0, 2, 0, 0}...) + serverHelloEmptySCT = append(serverHelloEmptySCT, serverHelloBytes[i+4:]...) + + // Update the handshake message length. + serverHelloEmptySCT[1] = byte((len(serverHelloEmptySCT) - 4) >> 16) + serverHelloEmptySCT[2] = byte((len(serverHelloEmptySCT) - 4) >> 8) + serverHelloEmptySCT[3] = byte(len(serverHelloEmptySCT) - 4) + + // Update the extensions length + serverHelloEmptySCT[42] = byte((len(serverHelloEmptySCT) - 44) >> 8) + serverHelloEmptySCT[43] = byte((len(serverHelloEmptySCT) - 44)) + + if serverHelloCopy.unmarshal(serverHelloEmptySCT) { + t.Fatal("Unmarshaled ServerHello with empty SCT list") + } +} + +func TestRejectEmptySCT(t *testing.T) { + // Not only must the SCT list be non-empty, but the SCT elements must + // not be zero length. + + var random [32]byte + serverHello := serverHelloMsg{ + vers: VersionTLS12, + random: random[:], + scts: [][]byte{nil}, + } + serverHelloBytes := serverHello.marshal() + + var serverHelloCopy serverHelloMsg + if serverHelloCopy.unmarshal(serverHelloBytes) { + t.Fatal("Unmarshaled ServerHello with zero-length SCT") + } +} diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go new file mode 100644 index 0000000..43f30e2 --- /dev/null +++ b/src/crypto/tls/handshake_server.go @@ -0,0 +1,875 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "context" + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rsa" + "crypto/subtle" + "crypto/x509" + "errors" + "fmt" + "hash" + "io" + "sync/atomic" + "time" +) + +// serverHandshakeState contains details of a server handshake in progress. +// It's discarded once the handshake has completed. +type serverHandshakeState struct { + c *Conn + ctx context.Context + clientHello *clientHelloMsg + hello *serverHelloMsg + suite *cipherSuite + ecdheOk bool + ecSignOk bool + rsaDecryptOk bool + rsaSignOk bool + sessionState *sessionState + finishedHash finishedHash + masterSecret []byte + cert *Certificate +} + +// serverHandshake performs a TLS handshake as a server. +func (c *Conn) serverHandshake(ctx context.Context) error { + clientHello, err := c.readClientHello(ctx) + if err != nil { + return err + } + + if c.vers == VersionTLS13 { + hs := serverHandshakeStateTLS13{ + c: c, + ctx: ctx, + clientHello: clientHello, + } + return hs.handshake() + } + + hs := serverHandshakeState{ + c: c, + ctx: ctx, + clientHello: clientHello, + } + return hs.handshake() +} + +func (hs *serverHandshakeState) handshake() error { + c := hs.c + + if err := hs.processClientHello(); err != nil { + return err + } + + // For an overview of TLS handshaking, see RFC 5246, Section 7.3. + c.buffering = true + if hs.checkForResumption() { + // The client has included a session ticket and so we do an abbreviated handshake. + c.didResume = true + if err := hs.doResumeHandshake(); err != nil { + return err + } + if err := hs.establishKeys(); err != nil { + return err + } + if err := hs.sendSessionTicket(); err != nil { + return err + } + if err := hs.sendFinished(c.serverFinished[:]); err != nil { + return err + } + if _, err := c.flush(); err != nil { + return err + } + c.clientFinishedIsFirst = false + if err := hs.readFinished(nil); err != nil { + return err + } + } else { + // The client didn't include a session ticket, or it wasn't + // valid so we do a full handshake. + if err := hs.pickCipherSuite(); err != nil { + return err + } + if err := hs.doFullHandshake(); err != nil { + return err + } + if err := hs.establishKeys(); err != nil { + return err + } + if err := hs.readFinished(c.clientFinished[:]); err != nil { + return err + } + c.clientFinishedIsFirst = true + c.buffering = true + if err := hs.sendSessionTicket(); err != nil { + return err + } + if err := hs.sendFinished(nil); err != nil { + return err + } + if _, err := c.flush(); err != nil { + return err + } + } + + c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random) + atomic.StoreUint32(&c.handshakeStatus, 1) + + return nil +} + +// readClientHello reads a ClientHello message and selects the protocol version. +func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { + msg, err := c.readHandshake() + if err != nil { + return nil, err + } + clientHello, ok := msg.(*clientHelloMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return nil, unexpectedMessageError(clientHello, msg) + } + + var configForClient *Config + originalConfig := c.config + if c.config.GetConfigForClient != nil { + chi := clientHelloInfo(ctx, c, clientHello) + if configForClient, err = c.config.GetConfigForClient(chi); err != nil { + c.sendAlert(alertInternalError) + return nil, err + } else if configForClient != nil { + c.config = configForClient + } + } + c.ticketKeys = originalConfig.ticketKeys(configForClient) + + clientVersions := clientHello.supportedVersions + if len(clientHello.supportedVersions) == 0 { + clientVersions = supportedVersionsFromMax(clientHello.vers) + } + c.vers, ok = c.config.mutualVersion(clientVersions) + if !ok { + c.sendAlert(alertProtocolVersion) + return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions) + } + c.haveVers = true + c.in.version = c.vers + c.out.version = c.vers + + return clientHello, nil +} + +func (hs *serverHandshakeState) processClientHello() error { + c := hs.c + + hs.hello = new(serverHelloMsg) + hs.hello.vers = c.vers + + foundCompression := false + // We only support null compression, so check that the client offered it. + for _, compression := range hs.clientHello.compressionMethods { + if compression == compressionNone { + foundCompression = true + break + } + } + + if !foundCompression { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: client does not support uncompressed connections") + } + + hs.hello.random = make([]byte, 32) + serverRandom := hs.hello.random + // Downgrade protection canaries. See RFC 8446, Section 4.1.3. + maxVers := c.config.maxSupportedVersion() + if maxVers >= VersionTLS12 && c.vers < maxVers || testingOnlyForceDowngradeCanary { + if c.vers == VersionTLS12 { + copy(serverRandom[24:], downgradeCanaryTLS12) + } else { + copy(serverRandom[24:], downgradeCanaryTLS11) + } + serverRandom = serverRandom[:24] + } + _, err := io.ReadFull(c.config.rand(), serverRandom) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + + if len(hs.clientHello.secureRenegotiation) != 0 { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: initial handshake had non-empty renegotiation extension") + } + + hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported + hs.hello.compressionMethod = compressionNone + if len(hs.clientHello.serverName) > 0 { + c.serverName = hs.clientHello.serverName + } + + selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols) + if err != nil { + c.sendAlert(alertNoApplicationProtocol) + return err + } + hs.hello.alpnProtocol = selectedProto + c.clientProtocol = selectedProto + + hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello)) + if err != nil { + if err == errNoCertificates { + c.sendAlert(alertUnrecognizedName) + } else { + c.sendAlert(alertInternalError) + } + return err + } + if hs.clientHello.scts { + hs.hello.scts = hs.cert.SignedCertificateTimestamps + } + + hs.ecdheOk = supportsECDHE(c.config, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints) + + if hs.ecdheOk { + // Although omitting the ec_point_formats extension is permitted, some + // old OpenSSL version will refuse to handshake if not present. + // + // Per RFC 4492, section 5.1.2, implementations MUST support the + // uncompressed point format. See golang.org/issue/31943. + hs.hello.supportedPoints = []uint8{pointFormatUncompressed} + } + + if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok { + switch priv.Public().(type) { + case *ecdsa.PublicKey: + hs.ecSignOk = true + case ed25519.PublicKey: + hs.ecSignOk = true + case *rsa.PublicKey: + hs.rsaSignOk = true + default: + c.sendAlert(alertInternalError) + return fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public()) + } + } + if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok { + switch priv.Public().(type) { + case *rsa.PublicKey: + hs.rsaDecryptOk = true + default: + c.sendAlert(alertInternalError) + return fmt.Errorf("tls: unsupported decryption key type (%T)", priv.Public()) + } + } + + return nil +} + +// negotiateALPN picks a shared ALPN protocol that both sides support in server +// preference order. If ALPN is not configured or the peer doesn't support it, +// it returns "" and no error. +func negotiateALPN(serverProtos, clientProtos []string) (string, error) { + if len(serverProtos) == 0 || len(clientProtos) == 0 { + return "", nil + } + var http11fallback bool + for _, s := range serverProtos { + for _, c := range clientProtos { + if s == c { + return s, nil + } + if s == "h2" && c == "http/1.1" { + http11fallback = true + } + } + } + // As a special case, let http/1.1 clients connect to h2 servers as if they + // didn't support ALPN. We used not to enforce protocol overlap, so over + // time a number of HTTP servers were configured with only "h2", but + // expected to accept connections from "http/1.1" clients. See Issue 46310. + if http11fallback { + return "", nil + } + return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", clientProtos) +} + +// supportsECDHE returns whether ECDHE key exchanges can be used with this +// pre-TLS 1.3 client. +func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8) bool { + supportsCurve := false + for _, curve := range supportedCurves { + if c.supportsCurve(curve) { + supportsCurve = true + break + } + } + + supportsPointFormat := false + for _, pointFormat := range supportedPoints { + if pointFormat == pointFormatUncompressed { + supportsPointFormat = true + break + } + } + + return supportsCurve && supportsPointFormat +} + +func (hs *serverHandshakeState) pickCipherSuite() error { + c := hs.c + + preferenceOrder := cipherSuitesPreferenceOrder + if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { + preferenceOrder = cipherSuitesPreferenceOrderNoAES + } + + configCipherSuites := c.config.cipherSuites() + preferenceList := make([]uint16, 0, len(configCipherSuites)) + for _, suiteID := range preferenceOrder { + for _, id := range configCipherSuites { + if id == suiteID { + preferenceList = append(preferenceList, id) + break + } + } + } + + hs.suite = selectCipherSuite(preferenceList, hs.clientHello.cipherSuites, hs.cipherSuiteOk) + if hs.suite == nil { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: no cipher suite supported by both client and server") + } + c.cipherSuite = hs.suite.id + + for _, id := range hs.clientHello.cipherSuites { + if id == TLS_FALLBACK_SCSV { + // The client is doing a fallback connection. See RFC 7507. + if hs.clientHello.vers < c.config.maxSupportedVersion() { + c.sendAlert(alertInappropriateFallback) + return errors.New("tls: client using inappropriate protocol fallback") + } + break + } + } + + return nil +} + +func (hs *serverHandshakeState) cipherSuiteOk(c *cipherSuite) bool { + if c.flags&suiteECDHE != 0 { + if !hs.ecdheOk { + return false + } + if c.flags&suiteECSign != 0 { + if !hs.ecSignOk { + return false + } + } else if !hs.rsaSignOk { + return false + } + } else if !hs.rsaDecryptOk { + return false + } + if hs.c.vers < VersionTLS12 && c.flags&suiteTLS12 != 0 { + return false + } + return true +} + +// checkForResumption reports whether we should perform resumption on this connection. +func (hs *serverHandshakeState) checkForResumption() bool { + c := hs.c + + if c.config.SessionTicketsDisabled { + return false + } + + plaintext, usedOldKey := c.decryptTicket(hs.clientHello.sessionTicket) + if plaintext == nil { + return false + } + hs.sessionState = &sessionState{usedOldKey: usedOldKey} + ok := hs.sessionState.unmarshal(plaintext) + if !ok { + return false + } + + createdAt := time.Unix(int64(hs.sessionState.createdAt), 0) + if c.config.time().Sub(createdAt) > maxSessionTicketLifetime { + return false + } + + // Never resume a session for a different TLS version. + if c.vers != hs.sessionState.vers { + return false + } + + cipherSuiteOk := false + // Check that the client is still offering the ciphersuite in the session. + for _, id := range hs.clientHello.cipherSuites { + if id == hs.sessionState.cipherSuite { + cipherSuiteOk = true + break + } + } + if !cipherSuiteOk { + return false + } + + // Check that we also support the ciphersuite from the session. + hs.suite = selectCipherSuite([]uint16{hs.sessionState.cipherSuite}, + c.config.cipherSuites(), hs.cipherSuiteOk) + if hs.suite == nil { + return false + } + + sessionHasClientCerts := len(hs.sessionState.certificates) != 0 + needClientCerts := requiresClientCert(c.config.ClientAuth) + if needClientCerts && !sessionHasClientCerts { + return false + } + if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { + return false + } + + return true +} + +func (hs *serverHandshakeState) doResumeHandshake() error { + c := hs.c + + hs.hello.cipherSuite = hs.suite.id + c.cipherSuite = hs.suite.id + // We echo the client's session ID in the ServerHello to let it know + // that we're doing a resumption. + hs.hello.sessionId = hs.clientHello.sessionId + hs.hello.ticketSupported = hs.sessionState.usedOldKey + hs.finishedHash = newFinishedHash(c.vers, hs.suite) + hs.finishedHash.discardHandshakeBuffer() + hs.finishedHash.Write(hs.clientHello.marshal()) + hs.finishedHash.Write(hs.hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { + return err + } + + if err := c.processCertsFromClient(Certificate{ + Certificate: hs.sessionState.certificates, + }); err != nil { + return err + } + + if c.config.VerifyConnection != nil { + if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + + hs.masterSecret = hs.sessionState.masterSecret + + return nil +} + +func (hs *serverHandshakeState) doFullHandshake() error { + c := hs.c + + if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 { + hs.hello.ocspStapling = true + } + + hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled + hs.hello.cipherSuite = hs.suite.id + + hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite) + if c.config.ClientAuth == NoClientCert { + // No need to keep a full record of the handshake if client + // certificates won't be used. + hs.finishedHash.discardHandshakeBuffer() + } + hs.finishedHash.Write(hs.clientHello.marshal()) + hs.finishedHash.Write(hs.hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { + return err + } + + certMsg := new(certificateMsg) + certMsg.certificates = hs.cert.Certificate + hs.finishedHash.Write(certMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { + return err + } + + if hs.hello.ocspStapling { + certStatus := new(certificateStatusMsg) + certStatus.response = hs.cert.OCSPStaple + hs.finishedHash.Write(certStatus.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil { + return err + } + } + + keyAgreement := hs.suite.ka(c.vers) + skx, err := keyAgreement.generateServerKeyExchange(c.config, hs.cert, hs.clientHello, hs.hello) + if err != nil { + c.sendAlert(alertHandshakeFailure) + return err + } + if skx != nil { + hs.finishedHash.Write(skx.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, skx.marshal()); err != nil { + return err + } + } + + var certReq *certificateRequestMsg + if c.config.ClientAuth >= RequestClientCert { + // Request a client certificate + certReq = new(certificateRequestMsg) + certReq.certificateTypes = []byte{ + byte(certTypeRSASign), + byte(certTypeECDSASign), + } + if c.vers >= VersionTLS12 { + certReq.hasSignatureAlgorithm = true + certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms + } + + // An empty list of certificateAuthorities signals to + // the client that it may send any certificate in response + // to our request. When we know the CAs we trust, then + // we can send them down, so that the client can choose + // an appropriate certificate to give to us. + if c.config.ClientCAs != nil { + certReq.certificateAuthorities = c.config.ClientCAs.Subjects() + } + hs.finishedHash.Write(certReq.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil { + return err + } + } + + helloDone := new(serverHelloDoneMsg) + hs.finishedHash.Write(helloDone.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, helloDone.marshal()); err != nil { + return err + } + + if _, err := c.flush(); err != nil { + return err + } + + var pub crypto.PublicKey // public key for client auth, if any + + msg, err := c.readHandshake() + if err != nil { + return err + } + + // If we requested a client certificate, then the client must send a + // certificate message, even if it's empty. + if c.config.ClientAuth >= RequestClientCert { + certMsg, ok := msg.(*certificateMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) + } + hs.finishedHash.Write(certMsg.marshal()) + + if err := c.processCertsFromClient(Certificate{ + Certificate: certMsg.certificates, + }); err != nil { + return err + } + if len(certMsg.certificates) != 0 { + pub = c.peerCertificates[0].PublicKey + } + + msg, err = c.readHandshake() + if err != nil { + return err + } + } + if c.config.VerifyConnection != nil { + if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + + // Get client key exchange + ckx, ok := msg.(*clientKeyExchangeMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(ckx, msg) + } + hs.finishedHash.Write(ckx.marshal()) + + preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers) + if err != nil { + c.sendAlert(alertHandshakeFailure) + return err + } + hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random) + if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.clientHello.random, hs.masterSecret); err != nil { + c.sendAlert(alertInternalError) + return err + } + + // If we received a client cert in response to our certificate request message, + // the client will send us a certificateVerifyMsg immediately after the + // clientKeyExchangeMsg. This message is a digest of all preceding + // handshake-layer messages that is signed using the private key corresponding + // to the client's certificate. This allows us to verify that the client is in + // possession of the private key of the certificate. + if len(c.peerCertificates) > 0 { + msg, err = c.readHandshake() + if err != nil { + return err + } + certVerify, ok := msg.(*certificateVerifyMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certVerify, msg) + } + + var sigType uint8 + var sigHash crypto.Hash + if c.vers >= VersionTLS12 { + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, certReq.supportedSignatureAlgorithms) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: client certificate used with invalid signature algorithm") + } + sigType, sigHash, err = typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm) + if err != nil { + return c.sendAlert(alertInternalError) + } + } else { + sigType, sigHash, err = legacyTypeAndHashFromPublicKey(pub) + if err != nil { + c.sendAlert(alertIllegalParameter) + return err + } + } + + signed := hs.finishedHash.hashForClientCertificate(sigType, sigHash, hs.masterSecret) + if err := verifyHandshakeSignature(sigType, pub, sigHash, signed, certVerify.signature); err != nil { + c.sendAlert(alertDecryptError) + return errors.New("tls: invalid signature by the client certificate: " + err.Error()) + } + + hs.finishedHash.Write(certVerify.marshal()) + } + + hs.finishedHash.discardHandshakeBuffer() + + return nil +} + +func (hs *serverHandshakeState) establishKeys() error { + c := hs.c + + clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := + keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) + + var clientCipher, serverCipher interface{} + var clientHash, serverHash hash.Hash + + if hs.suite.aead == nil { + clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */) + clientHash = hs.suite.mac(clientMAC) + serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */) + serverHash = hs.suite.mac(serverMAC) + } else { + clientCipher = hs.suite.aead(clientKey, clientIV) + serverCipher = hs.suite.aead(serverKey, serverIV) + } + + c.in.prepareCipherSpec(c.vers, clientCipher, clientHash) + c.out.prepareCipherSpec(c.vers, serverCipher, serverHash) + + return nil +} + +func (hs *serverHandshakeState) readFinished(out []byte) error { + c := hs.c + + if err := c.readChangeCipherSpec(); err != nil { + return err + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + clientFinished, ok := msg.(*finishedMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(clientFinished, msg) + } + + verify := hs.finishedHash.clientSum(hs.masterSecret) + if len(verify) != len(clientFinished.verifyData) || + subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: client's Finished message is incorrect") + } + + hs.finishedHash.Write(clientFinished.marshal()) + copy(out, verify) + return nil +} + +func (hs *serverHandshakeState) sendSessionTicket() error { + // ticketSupported is set in a resumption handshake if the + // ticket from the client was encrypted with an old session + // ticket key and thus a refreshed ticket should be sent. + if !hs.hello.ticketSupported { + return nil + } + + c := hs.c + m := new(newSessionTicketMsg) + + createdAt := uint64(c.config.time().Unix()) + if hs.sessionState != nil { + // If this is re-wrapping an old key, then keep + // the original time it was created. + createdAt = hs.sessionState.createdAt + } + + var certsFromClient [][]byte + for _, cert := range c.peerCertificates { + certsFromClient = append(certsFromClient, cert.Raw) + } + state := sessionState{ + vers: c.vers, + cipherSuite: hs.suite.id, + createdAt: createdAt, + masterSecret: hs.masterSecret, + certificates: certsFromClient, + } + var err error + m.ticket, err = c.encryptTicket(state.marshal()) + if err != nil { + return err + } + + hs.finishedHash.Write(m.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil { + return err + } + + return nil +} + +func (hs *serverHandshakeState) sendFinished(out []byte) error { + c := hs.c + + if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { + return err + } + + finished := new(finishedMsg) + finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret) + hs.finishedHash.Write(finished.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { + return err + } + + copy(out, finished.verifyData) + + return nil +} + +// processCertsFromClient takes a chain of client certificates either from a +// Certificates message or from a sessionState and verifies them. It returns +// the public key of the leaf certificate. +func (c *Conn) processCertsFromClient(certificate Certificate) error { + certificates := certificate.Certificate + certs := make([]*x509.Certificate, len(certificates)) + var err error + for i, asn1Data := range certificates { + if certs[i], err = x509.ParseCertificate(asn1Data); err != nil { + c.sendAlert(alertBadCertificate) + return errors.New("tls: failed to parse client certificate: " + err.Error()) + } + } + + if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) { + c.sendAlert(alertBadCertificate) + return errors.New("tls: client didn't provide a certificate") + } + + if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 { + opts := x509.VerifyOptions{ + Roots: c.config.ClientCAs, + CurrentTime: c.config.time(), + Intermediates: x509.NewCertPool(), + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + } + + for _, cert := range certs[1:] { + opts.Intermediates.AddCert(cert) + } + + chains, err := certs[0].Verify(opts) + if err != nil { + c.sendAlert(alertBadCertificate) + return errors.New("tls: failed to verify client certificate: " + err.Error()) + } + + c.verifiedChains = chains + } + + c.peerCertificates = certs + c.ocspResponse = certificate.OCSPStaple + c.scts = certificate.SignedCertificateTimestamps + + if len(certs) > 0 { + switch certs[0].PublicKey.(type) { + case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey: + default: + c.sendAlert(alertUnsupportedCertificate) + return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", certs[0].PublicKey) + } + } + + if c.config.VerifyPeerCertificate != nil { + if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + + return nil +} + +func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { + supportedVersions := clientHello.supportedVersions + if len(clientHello.supportedVersions) == 0 { + supportedVersions = supportedVersionsFromMax(clientHello.vers) + } + + return &ClientHelloInfo{ + CipherSuites: clientHello.cipherSuites, + ServerName: clientHello.serverName, + SupportedCurves: clientHello.supportedCurves, + SupportedPoints: clientHello.supportedPoints, + SignatureSchemes: clientHello.supportedSignatureAlgorithms, + SupportedProtos: clientHello.alpnProtocols, + SupportedVersions: supportedVersions, + Conn: c.conn, + config: c.config, + ctx: ctx, + } +} diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go new file mode 100644 index 0000000..f61b4c8 --- /dev/null +++ b/src/crypto/tls/handshake_server_test.go @@ -0,0 +1,2028 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "context" + "crypto" + "crypto/elliptic" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "io" + "net" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + "golang.org/x/crypto/curve25519" +) + +func testClientHello(t *testing.T, serverConfig *Config, m handshakeMessage) { + testClientHelloFailure(t, serverConfig, m, "") +} + +func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessage, expectedSubStr string) { + c, s := localPipe(t) + go func() { + cli := Client(c, testConfig) + if ch, ok := m.(*clientHelloMsg); ok { + cli.vers = ch.vers + } + cli.writeRecord(recordTypeHandshake, m.marshal()) + c.Close() + }() + ctx := context.Background() + conn := Server(s, serverConfig) + ch, err := conn.readClientHello(ctx) + hs := serverHandshakeState{ + c: conn, + ctx: ctx, + clientHello: ch, + } + if err == nil { + err = hs.processClientHello() + } + if err == nil { + err = hs.pickCipherSuite() + } + s.Close() + if len(expectedSubStr) == 0 { + if err != nil && err != io.EOF { + t.Errorf("Got error: %s; expected to succeed", err) + } + } else if err == nil || !strings.Contains(err.Error(), expectedSubStr) { + t.Errorf("Got error: %v; expected to match substring '%s'", err, expectedSubStr) + } +} + +func TestSimpleError(t *testing.T) { + testClientHelloFailure(t, testConfig, &serverHelloDoneMsg{}, "unexpected handshake message") +} + +var badProtocolVersions = []uint16{0x0000, 0x0005, 0x0100, 0x0105, 0x0200, 0x0205, VersionSSL30} + +func TestRejectBadProtocolVersion(t *testing.T) { + config := testConfig.Clone() + config.MinVersion = VersionSSL30 + for _, v := range badProtocolVersions { + testClientHelloFailure(t, config, &clientHelloMsg{ + vers: v, + random: make([]byte, 32), + }, "unsupported versions") + } + testClientHelloFailure(t, config, &clientHelloMsg{ + vers: VersionTLS12, + supportedVersions: badProtocolVersions, + random: make([]byte, 32), + }, "unsupported versions") +} + +func TestNoSuiteOverlap(t *testing.T) { + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{0xff00}, + compressionMethods: []uint8{compressionNone}, + } + testClientHelloFailure(t, testConfig, clientHello, "no cipher suite supported by both client and server") +} + +func TestNoCompressionOverlap(t *testing.T) { + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + compressionMethods: []uint8{0xff}, + } + testClientHelloFailure(t, testConfig, clientHello, "client does not support uncompressed connections") +} + +func TestNoRC4ByDefault(t *testing.T) { + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + compressionMethods: []uint8{compressionNone}, + } + serverConfig := testConfig.Clone() + // Reset the enabled cipher suites to nil in order to test the + // defaults. + serverConfig.CipherSuites = nil + testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server") +} + +func TestRejectSNIWithTrailingDot(t *testing.T) { + testClientHelloFailure(t, testConfig, &clientHelloMsg{ + vers: VersionTLS12, + random: make([]byte, 32), + serverName: "foo.com.", + }, "unexpected message") +} + +func TestDontSelectECDSAWithRSAKey(t *testing.T) { + // Test that, even when both sides support an ECDSA cipher suite, it + // won't be selected if the server's private key doesn't support it. + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, + compressionMethods: []uint8{compressionNone}, + supportedCurves: []CurveID{CurveP256}, + supportedPoints: []uint8{pointFormatUncompressed}, + } + serverConfig := testConfig.Clone() + serverConfig.CipherSuites = clientHello.cipherSuites + serverConfig.Certificates = make([]Certificate, 1) + serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} + serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey + serverConfig.BuildNameToCertificate() + // First test that it *does* work when the server's key is ECDSA. + testClientHello(t, serverConfig, clientHello) + + // Now test that switching to an RSA key causes the expected error (and + // not an internal error about a signing failure). + serverConfig.Certificates = testConfig.Certificates + testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server") +} + +func TestDontSelectRSAWithECDSAKey(t *testing.T) { + // Test that, even when both sides support an RSA cipher suite, it + // won't be selected if the server's private key doesn't support it. + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, + compressionMethods: []uint8{compressionNone}, + supportedCurves: []CurveID{CurveP256}, + supportedPoints: []uint8{pointFormatUncompressed}, + } + serverConfig := testConfig.Clone() + serverConfig.CipherSuites = clientHello.cipherSuites + // First test that it *does* work when the server's key is RSA. + testClientHello(t, serverConfig, clientHello) + + // Now test that switching to an ECDSA key causes the expected error + // (and not an internal error about a signing failure). + serverConfig.Certificates = make([]Certificate, 1) + serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} + serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey + serverConfig.BuildNameToCertificate() + testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server") +} + +func TestRenegotiationExtension(t *testing.T) { + clientHello := &clientHelloMsg{ + vers: VersionTLS12, + compressionMethods: []uint8{compressionNone}, + random: make([]byte, 32), + secureRenegotiationSupported: true, + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + } + + bufChan := make(chan []byte, 1) + c, s := localPipe(t) + + go func() { + cli := Client(c, testConfig) + cli.vers = clientHello.vers + cli.writeRecord(recordTypeHandshake, clientHello.marshal()) + + buf := make([]byte, 1024) + n, err := c.Read(buf) + if err != nil { + t.Errorf("Server read returned error: %s", err) + return + } + c.Close() + bufChan <- buf[:n] + }() + + Server(s, testConfig).Handshake() + buf := <-bufChan + + if len(buf) < 5+4 { + t.Fatalf("Server returned short message of length %d", len(buf)) + } + // buf contains a TLS record, with a 5 byte record header and a 4 byte + // handshake header. The length of the ServerHello is taken from the + // handshake header. + serverHelloLen := int(buf[6])<<16 | int(buf[7])<<8 | int(buf[8]) + + var serverHello serverHelloMsg + // unmarshal expects to be given the handshake header, but + // serverHelloLen doesn't include it. + if !serverHello.unmarshal(buf[5 : 9+serverHelloLen]) { + t.Fatalf("Failed to parse ServerHello") + } + + if !serverHello.secureRenegotiationSupported { + t.Errorf("Secure renegotiation extension was not echoed.") + } +} + +func TestTLS12OnlyCipherSuites(t *testing.T) { + // Test that a Server doesn't select a TLS 1.2-only cipher suite when + // the client negotiates TLS 1.1. + clientHello := &clientHelloMsg{ + vers: VersionTLS11, + random: make([]byte, 32), + cipherSuites: []uint16{ + // The Server, by default, will use the client's + // preference order. So the GCM cipher suite + // will be selected unless it's excluded because + // of the version in this ClientHello. + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_RC4_128_SHA, + }, + compressionMethods: []uint8{compressionNone}, + supportedCurves: []CurveID{CurveP256, CurveP384, CurveP521}, + supportedPoints: []uint8{pointFormatUncompressed}, + } + + c, s := localPipe(t) + replyChan := make(chan interface{}) + go func() { + cli := Client(c, testConfig) + cli.vers = clientHello.vers + cli.writeRecord(recordTypeHandshake, clientHello.marshal()) + reply, err := cli.readHandshake() + c.Close() + if err != nil { + replyChan <- err + } else { + replyChan <- reply + } + }() + config := testConfig.Clone() + config.CipherSuites = clientHello.cipherSuites + Server(s, config).Handshake() + s.Close() + reply := <-replyChan + if err, ok := reply.(error); ok { + t.Fatal(err) + } + serverHello, ok := reply.(*serverHelloMsg) + if !ok { + t.Fatalf("didn't get ServerHello message in reply. Got %v\n", reply) + } + if s := serverHello.cipherSuite; s != TLS_RSA_WITH_RC4_128_SHA { + t.Fatalf("bad cipher suite from server: %x", s) + } +} + +func TestTLSPointFormats(t *testing.T) { + // Test that a Server returns the ec_point_format extension when ECC is + // negotiated, and not returned on RSA handshake. + tests := []struct { + name string + cipherSuites []uint16 + supportedCurves []CurveID + supportedPoints []uint8 + wantSupportedPoints bool + }{ + {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{compressionNone}, true}, + {"RSA", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, nil, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + clientHello := &clientHelloMsg{ + vers: VersionTLS12, + random: make([]byte, 32), + cipherSuites: tt.cipherSuites, + compressionMethods: []uint8{compressionNone}, + supportedCurves: tt.supportedCurves, + supportedPoints: tt.supportedPoints, + } + + c, s := localPipe(t) + replyChan := make(chan interface{}) + go func() { + cli := Client(c, testConfig) + cli.vers = clientHello.vers + cli.writeRecord(recordTypeHandshake, clientHello.marshal()) + reply, err := cli.readHandshake() + c.Close() + if err != nil { + replyChan <- err + } else { + replyChan <- reply + } + }() + config := testConfig.Clone() + config.CipherSuites = clientHello.cipherSuites + Server(s, config).Handshake() + s.Close() + reply := <-replyChan + if err, ok := reply.(error); ok { + t.Fatal(err) + } + serverHello, ok := reply.(*serverHelloMsg) + if !ok { + t.Fatalf("didn't get ServerHello message in reply. Got %v\n", reply) + } + if tt.wantSupportedPoints { + if len(serverHello.supportedPoints) < 1 { + t.Fatal("missing ec_point_format extension from server") + } + found := false + for _, p := range serverHello.supportedPoints { + if p == pointFormatUncompressed { + found = true + break + } + } + if !found { + t.Fatal("missing uncompressed format in ec_point_format extension from server") + } + } else { + if len(serverHello.supportedPoints) != 0 { + t.Fatalf("unexcpected ec_point_format extension from server: %v", serverHello.supportedPoints) + } + } + }) + } +} + +func TestAlertForwarding(t *testing.T) { + c, s := localPipe(t) + go func() { + Client(c, testConfig).sendAlert(alertUnknownCA) + c.Close() + }() + + err := Server(s, testConfig).Handshake() + s.Close() + var opErr *net.OpError + if !errors.As(err, &opErr) || opErr.Err != error(alertUnknownCA) { + t.Errorf("Got error: %s; expected: %s", err, error(alertUnknownCA)) + } +} + +func TestClose(t *testing.T) { + c, s := localPipe(t) + go c.Close() + + err := Server(s, testConfig).Handshake() + s.Close() + if err != io.EOF { + t.Errorf("Got error: %s; expected: %s", err, io.EOF) + } +} + +func TestVersion(t *testing.T) { + serverConfig := &Config{ + Certificates: testConfig.Certificates, + MaxVersion: VersionTLS11, + } + clientConfig := &Config{ + InsecureSkipVerify: true, + } + state, _, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.Version != VersionTLS11 { + t.Fatalf("Incorrect version %x, should be %x", state.Version, VersionTLS11) + } +} + +func TestCipherSuitePreference(t *testing.T) { + serverConfig := &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, + Certificates: testConfig.Certificates, + MaxVersion: VersionTLS12, + GetConfigForClient: func(chi *ClientHelloInfo) (*Config, error) { + if chi.CipherSuites[0] != TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 { + t.Error("the advertised order should not depend on Config.CipherSuites") + } + if len(chi.CipherSuites) != 2+len(defaultCipherSuitesTLS13) { + t.Error("the advertised TLS 1.2 suites should be filtered by Config.CipherSuites") + } + return nil, nil + }, + } + clientConfig := &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, + InsecureSkipVerify: true, + } + state, _, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.CipherSuite != TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 { + t.Error("the preference order should not depend on Config.CipherSuites") + } +} + +func TestSCTHandshake(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testSCTHandshake(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testSCTHandshake(t, VersionTLS13) }) +} + +func testSCTHandshake(t *testing.T, version uint16) { + expected := [][]byte{[]byte("certificate"), []byte("transparency")} + serverConfig := &Config{ + Certificates: []Certificate{{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + SignedCertificateTimestamps: expected, + }}, + MaxVersion: version, + } + clientConfig := &Config{ + InsecureSkipVerify: true, + } + _, state, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + actual := state.SignedCertificateTimestamps + if len(actual) != len(expected) { + t.Fatalf("got %d scts, want %d", len(actual), len(expected)) + } + for i, sct := range expected { + if !bytes.Equal(sct, actual[i]) { + t.Fatalf("SCT #%d was %x, but expected %x", i, actual[i], sct) + } + } +} + +func TestCrossVersionResume(t *testing.T) { + t.Run("TLSv12", func(t *testing.T) { testCrossVersionResume(t, VersionTLS12) }) + t.Run("TLSv13", func(t *testing.T) { testCrossVersionResume(t, VersionTLS13) }) +} + +func testCrossVersionResume(t *testing.T, version uint16) { + serverConfig := &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, + Certificates: testConfig.Certificates, + } + clientConfig := &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, + InsecureSkipVerify: true, + ClientSessionCache: NewLRUClientSessionCache(1), + ServerName: "servername", + } + + // Establish a session at TLS 1.1. + clientConfig.MaxVersion = VersionTLS11 + _, _, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + + // The client session cache now contains a TLS 1.1 session. + state, _, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if !state.DidResume { + t.Fatalf("handshake did not resume at the same version") + } + + // Test that the server will decline to resume at a lower version. + clientConfig.MaxVersion = VersionTLS10 + state, _, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.DidResume { + t.Fatalf("handshake resumed at a lower version") + } + + // The client session cache now contains a TLS 1.0 session. + state, _, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if !state.DidResume { + t.Fatalf("handshake did not resume at the same version") + } + + // Test that the server will decline to resume at a higher version. + clientConfig.MaxVersion = VersionTLS11 + state, _, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.DidResume { + t.Fatalf("handshake resumed at a higher version") + } +} + +// Note: see comment in handshake_test.go for details of how the reference +// tests work. + +// serverTest represents a test of the TLS server handshake against a reference +// implementation. +type serverTest struct { + // name is a freeform string identifying the test and the file in which + // the expected results will be stored. + name string + // command, if not empty, contains a series of arguments for the + // command to run for the reference server. + command []string + // expectedPeerCerts contains a list of PEM blocks of expected + // certificates from the client. + expectedPeerCerts []string + // config, if not nil, contains a custom Config to use for this test. + config *Config + // expectHandshakeErrorIncluding, when not empty, contains a string + // that must be a substring of the error resulting from the handshake. + expectHandshakeErrorIncluding string + // validate, if not nil, is a function that will be called with the + // ConnectionState of the resulting connection. It returns false if the + // ConnectionState is unacceptable. + validate func(ConnectionState) error + // wait, if true, prevents this subtest from calling t.Parallel. + // If false, runServerTest* returns immediately. + wait bool +} + +var defaultClientCommand = []string{"openssl", "s_client", "-no_ticket"} + +// connFromCommand starts opens a listening socket and starts the reference +// client to connect to it. It returns a recordingConn that wraps the resulting +// connection. +func (test *serverTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, err error) { + l, err := net.ListenTCP("tcp", &net.TCPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: 0, + }) + if err != nil { + return nil, nil, err + } + defer l.Close() + + port := l.Addr().(*net.TCPAddr).Port + + var command []string + command = append(command, test.command...) + if len(command) == 0 { + command = defaultClientCommand + } + command = append(command, "-connect") + command = append(command, fmt.Sprintf("127.0.0.1:%d", port)) + cmd := exec.Command(command[0], command[1:]...) + cmd.Stdin = nil + var output bytes.Buffer + cmd.Stdout = &output + cmd.Stderr = &output + if err := cmd.Start(); err != nil { + return nil, nil, err + } + + connChan := make(chan interface{}, 1) + go func() { + tcpConn, err := l.Accept() + if err != nil { + connChan <- err + return + } + connChan <- tcpConn + }() + + var tcpConn net.Conn + select { + case connOrError := <-connChan: + if err, ok := connOrError.(error); ok { + return nil, nil, err + } + tcpConn = connOrError.(net.Conn) + case <-time.After(2 * time.Second): + return nil, nil, errors.New("timed out waiting for connection from child process") + } + + record := &recordingConn{ + Conn: tcpConn, + } + + return record, cmd, nil +} + +func (test *serverTest) dataPath() string { + return filepath.Join("testdata", "Server-"+test.name) +} + +func (test *serverTest) loadData() (flows [][]byte, err error) { + in, err := os.Open(test.dataPath()) + if err != nil { + return nil, err + } + defer in.Close() + return parseTestData(in) +} + +func (test *serverTest) run(t *testing.T, write bool) { + var clientConn, serverConn net.Conn + var recordingConn *recordingConn + var childProcess *exec.Cmd + + if write { + var err error + recordingConn, childProcess, err = test.connFromCommand() + if err != nil { + t.Fatalf("Failed to start subcommand: %s", err) + } + serverConn = recordingConn + defer func() { + if t.Failed() { + t.Logf("OpenSSL output:\n\n%s", childProcess.Stdout) + } + }() + } else { + clientConn, serverConn = localPipe(t) + } + config := test.config + if config == nil { + config = testConfig + } + server := Server(serverConn, config) + connStateChan := make(chan ConnectionState, 1) + go func() { + _, err := server.Write([]byte("hello, world\n")) + if len(test.expectHandshakeErrorIncluding) > 0 { + if err == nil { + t.Errorf("Error expected, but no error returned") + } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) { + t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s) + } + } else { + if err != nil { + t.Logf("Error from Server.Write: '%s'", err) + } + } + server.Close() + serverConn.Close() + connStateChan <- server.ConnectionState() + }() + + if !write { + flows, err := test.loadData() + if err != nil { + t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath()) + } + for i, b := range flows { + if i%2 == 0 { + if *fast { + clientConn.SetWriteDeadline(time.Now().Add(1 * time.Second)) + } else { + clientConn.SetWriteDeadline(time.Now().Add(1 * time.Minute)) + } + clientConn.Write(b) + continue + } + bb := make([]byte, len(b)) + if *fast { + clientConn.SetReadDeadline(time.Now().Add(1 * time.Second)) + } else { + clientConn.SetReadDeadline(time.Now().Add(1 * time.Minute)) + } + n, err := io.ReadFull(clientConn, bb) + if err != nil { + t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", test.name, i+1, err, n, len(bb), bb[:n], b) + } + if !bytes.Equal(b, bb) { + t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b) + } + } + clientConn.Close() + } + + connState := <-connStateChan + peerCerts := connState.PeerCertificates + if len(peerCerts) == len(test.expectedPeerCerts) { + for i, peerCert := range peerCerts { + block, _ := pem.Decode([]byte(test.expectedPeerCerts[i])) + if !bytes.Equal(block.Bytes, peerCert.Raw) { + t.Fatalf("%s: mismatch on peer cert %d", test.name, i+1) + } + } + } else { + t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", test.name, len(test.expectedPeerCerts), len(peerCerts)) + } + + if test.validate != nil { + if err := test.validate(connState); err != nil { + t.Fatalf("validate callback returned error: %s", err) + } + } + + if write { + path := test.dataPath() + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + t.Fatalf("Failed to create output file: %s", err) + } + defer out.Close() + recordingConn.Close() + if len(recordingConn.flows) < 3 { + if len(test.expectHandshakeErrorIncluding) == 0 { + t.Fatalf("Handshake failed") + } + } + recordingConn.WriteTo(out) + t.Logf("Wrote %s\n", path) + childProcess.Wait() + } +} + +func runServerTestForVersion(t *testing.T, template *serverTest, version, option string) { + // Make a deep copy of the template before going parallel. + test := *template + if template.config != nil { + test.config = template.config.Clone() + } + test.name = version + "-" + test.name + if len(test.command) == 0 { + test.command = defaultClientCommand + } + test.command = append([]string(nil), test.command...) + test.command = append(test.command, option) + + runTestAndUpdateIfNeeded(t, version, test.run, test.wait) +} + +func runServerTestTLS10(t *testing.T, template *serverTest) { + runServerTestForVersion(t, template, "TLSv10", "-tls1") +} + +func runServerTestTLS11(t *testing.T, template *serverTest) { + runServerTestForVersion(t, template, "TLSv11", "-tls1_1") +} + +func runServerTestTLS12(t *testing.T, template *serverTest) { + runServerTestForVersion(t, template, "TLSv12", "-tls1_2") +} + +func runServerTestTLS13(t *testing.T, template *serverTest) { + runServerTestForVersion(t, template, "TLSv13", "-tls1_3") +} + +func TestHandshakeServerRSARC4(t *testing.T) { + test := &serverTest{ + name: "RSA-RC4", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"}, + } + runServerTestTLS10(t, test) + runServerTestTLS11(t, test) + runServerTestTLS12(t, test) +} + +func TestHandshakeServerRSA3DES(t *testing.T) { + test := &serverTest{ + name: "RSA-3DES", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "DES-CBC3-SHA"}, + } + runServerTestTLS10(t, test) + runServerTestTLS12(t, test) +} + +func TestHandshakeServerRSAAES(t *testing.T) { + test := &serverTest{ + name: "RSA-AES", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA"}, + } + runServerTestTLS10(t, test) + runServerTestTLS12(t, test) +} + +func TestHandshakeServerAESGCM(t *testing.T) { + test := &serverTest{ + name: "RSA-AES-GCM", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-AES128-GCM-SHA256"}, + } + runServerTestTLS12(t, test) +} + +func TestHandshakeServerAES256GCMSHA384(t *testing.T) { + test := &serverTest{ + name: "RSA-AES256-GCM-SHA384", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-AES256-GCM-SHA384"}, + } + runServerTestTLS12(t, test) +} + +func TestHandshakeServerAES128SHA256(t *testing.T) { + test := &serverTest{ + name: "AES128-SHA256", + command: []string{"openssl", "s_client", "-no_ticket", "-ciphersuites", "TLS_AES_128_GCM_SHA256"}, + } + runServerTestTLS13(t, test) +} +func TestHandshakeServerAES256SHA384(t *testing.T) { + test := &serverTest{ + name: "AES256-SHA384", + command: []string{"openssl", "s_client", "-no_ticket", "-ciphersuites", "TLS_AES_256_GCM_SHA384"}, + } + runServerTestTLS13(t, test) +} +func TestHandshakeServerCHACHA20SHA256(t *testing.T) { + test := &serverTest{ + name: "CHACHA20-SHA256", + command: []string{"openssl", "s_client", "-no_ticket", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + } + runServerTestTLS13(t, test) +} + +func TestHandshakeServerECDHEECDSAAES(t *testing.T) { + config := testConfig.Clone() + config.Certificates = make([]Certificate, 1) + config.Certificates[0].Certificate = [][]byte{testECDSACertificate} + config.Certificates[0].PrivateKey = testECDSAPrivateKey + config.BuildNameToCertificate() + + test := &serverTest{ + name: "ECDHE-ECDSA-AES", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-ECDSA-AES256-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256"}, + config: config, + } + runServerTestTLS10(t, test) + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerX25519(t *testing.T) { + config := testConfig.Clone() + config.CurvePreferences = []CurveID{X25519} + + test := &serverTest{ + name: "X25519", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256", "-curves", "X25519"}, + config: config, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerP256(t *testing.T) { + config := testConfig.Clone() + config.CurvePreferences = []CurveID{CurveP256} + + test := &serverTest{ + name: "P256", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256", "-curves", "P-256"}, + config: config, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerHelloRetryRequest(t *testing.T) { + config := testConfig.Clone() + config.CurvePreferences = []CurveID{CurveP256} + + test := &serverTest{ + name: "HelloRetryRequest", + command: []string{"openssl", "s_client", "-no_ticket", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256", "-curves", "X25519:P-256"}, + config: config, + } + runServerTestTLS13(t, test) +} + +func TestHandshakeServerALPN(t *testing.T) { + config := testConfig.Clone() + config.NextProtos = []string{"proto1", "proto2"} + + test := &serverTest{ + name: "ALPN", + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -alpn flag. + command: []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + config: config, + validate: func(state ConnectionState) error { + // The server's preferences should override the client. + if state.NegotiatedProtocol != "proto1" { + return fmt.Errorf("Got protocol %q, wanted proto1", state.NegotiatedProtocol) + } + return nil + }, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerALPNNoMatch(t *testing.T) { + config := testConfig.Clone() + config.NextProtos = []string{"proto3"} + + test := &serverTest{ + name: "ALPN-NoMatch", + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -alpn flag. + command: []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + config: config, + expectHandshakeErrorIncluding: "client requested unsupported application protocol", + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerALPNNotConfigured(t *testing.T) { + config := testConfig.Clone() + config.NextProtos = nil + + test := &serverTest{ + name: "ALPN-NotConfigured", + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -alpn flag. + command: []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + config: config, + validate: func(state ConnectionState) error { + if state.NegotiatedProtocol != "" { + return fmt.Errorf("Got protocol %q, wanted nothing", state.NegotiatedProtocol) + } + return nil + }, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerALPNFallback(t *testing.T) { + config := testConfig.Clone() + config.NextProtos = []string{"proto1", "h2", "proto2"} + + test := &serverTest{ + name: "ALPN-Fallback", + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -alpn flag. + command: []string{"openssl", "s_client", "-alpn", "proto3,http/1.1,proto4", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + config: config, + validate: func(state ConnectionState) error { + if state.NegotiatedProtocol != "" { + return fmt.Errorf("Got protocol %q, wanted nothing", state.NegotiatedProtocol) + } + return nil + }, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +// TestHandshakeServerSNI involves a client sending an SNI extension of +// "snitest.com", which happens to match the CN of testSNICertificate. The test +// verifies that the server correctly selects that certificate. +func TestHandshakeServerSNI(t *testing.T) { + test := &serverTest{ + name: "SNI", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, + } + runServerTestTLS12(t, test) +} + +// TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but +// tests the dynamic GetCertificate method +func TestHandshakeServerSNIGetCertificate(t *testing.T) { + config := testConfig.Clone() + + // Replace the NameToCertificate map with a GetCertificate function + nameToCert := config.NameToCertificate + config.NameToCertificate = nil + config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + cert := nameToCert[clientHello.ServerName] + return cert, nil + } + test := &serverTest{ + name: "SNI-GetCertificate", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, + config: config, + } + runServerTestTLS12(t, test) +} + +// TestHandshakeServerSNICertForNameNotFound is similar to +// TestHandshakeServerSNICertForName, but tests to make sure that when the +// GetCertificate method doesn't return a cert, we fall back to what's in +// the NameToCertificate map. +func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) { + config := testConfig.Clone() + + config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + return nil, nil + } + test := &serverTest{ + name: "SNI-GetCertificateNotFound", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, + config: config, + } + runServerTestTLS12(t, test) +} + +// TestHandshakeServerSNICertForNameError tests to make sure that errors in +// GetCertificate result in a tls alert. +func TestHandshakeServerSNIGetCertificateError(t *testing.T) { + const errMsg = "TestHandshakeServerSNIGetCertificateError error" + + serverConfig := testConfig.Clone() + serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + return nil, errors.New(errMsg) + } + + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + compressionMethods: []uint8{compressionNone}, + serverName: "test", + } + testClientHelloFailure(t, serverConfig, clientHello, errMsg) +} + +// TestHandshakeServerEmptyCertificates tests that GetCertificates is called in +// the case that Certificates is empty, even without SNI. +func TestHandshakeServerEmptyCertificates(t *testing.T) { + const errMsg = "TestHandshakeServerEmptyCertificates error" + + serverConfig := testConfig.Clone() + serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + return nil, errors.New(errMsg) + } + serverConfig.Certificates = nil + + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + compressionMethods: []uint8{compressionNone}, + } + testClientHelloFailure(t, serverConfig, clientHello, errMsg) + + // With an empty Certificates and a nil GetCertificate, the server + // should always return a “no certificates” error. + serverConfig.GetCertificate = nil + + clientHello = &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + compressionMethods: []uint8{compressionNone}, + } + testClientHelloFailure(t, serverConfig, clientHello, "no certificates") +} + +func TestServerResumption(t *testing.T) { + sessionFilePath := tempFile("") + defer os.Remove(sessionFilePath) + + testIssue := &serverTest{ + name: "IssueTicket", + command: []string{"openssl", "s_client", "-cipher", "AES128-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256", "-sess_out", sessionFilePath}, + wait: true, + } + testResume := &serverTest{ + name: "Resume", + command: []string{"openssl", "s_client", "-cipher", "AES128-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256", "-sess_in", sessionFilePath}, + validate: func(state ConnectionState) error { + if !state.DidResume { + return errors.New("did not resume") + } + return nil + }, + } + + runServerTestTLS12(t, testIssue) + runServerTestTLS12(t, testResume) + + runServerTestTLS13(t, testIssue) + runServerTestTLS13(t, testResume) + + config := testConfig.Clone() + config.CurvePreferences = []CurveID{CurveP256} + + testResumeHRR := &serverTest{ + name: "Resume-HelloRetryRequest", + command: []string{"openssl", "s_client", "-curves", "X25519:P-256", "-cipher", "AES128-SHA", "-ciphersuites", + "TLS_AES_128_GCM_SHA256", "-sess_in", sessionFilePath}, + config: config, + validate: func(state ConnectionState) error { + if !state.DidResume { + return errors.New("did not resume") + } + return nil + }, + } + + runServerTestTLS13(t, testResumeHRR) +} + +func TestServerResumptionDisabled(t *testing.T) { + sessionFilePath := tempFile("") + defer os.Remove(sessionFilePath) + + config := testConfig.Clone() + + testIssue := &serverTest{ + name: "IssueTicketPreDisable", + command: []string{"openssl", "s_client", "-cipher", "AES128-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256", "-sess_out", sessionFilePath}, + config: config, + wait: true, + } + testResume := &serverTest{ + name: "ResumeDisabled", + command: []string{"openssl", "s_client", "-cipher", "AES128-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256", "-sess_in", sessionFilePath}, + config: config, + validate: func(state ConnectionState) error { + if state.DidResume { + return errors.New("resumed with SessionTicketsDisabled") + } + return nil + }, + } + + config.SessionTicketsDisabled = false + runServerTestTLS12(t, testIssue) + config.SessionTicketsDisabled = true + runServerTestTLS12(t, testResume) + + config.SessionTicketsDisabled = false + runServerTestTLS13(t, testIssue) + config.SessionTicketsDisabled = true + runServerTestTLS13(t, testResume) +} + +func TestFallbackSCSV(t *testing.T) { + serverConfig := Config{ + Certificates: testConfig.Certificates, + } + test := &serverTest{ + name: "FallbackSCSV", + config: &serverConfig, + // OpenSSL 1.0.1j is needed for the -fallback_scsv option. + command: []string{"openssl", "s_client", "-fallback_scsv"}, + expectHandshakeErrorIncluding: "inappropriate protocol fallback", + } + runServerTestTLS11(t, test) +} + +func TestHandshakeServerExportKeyingMaterial(t *testing.T) { + test := &serverTest{ + name: "ExportKeyingMaterial", + command: []string{"openssl", "s_client", "-cipher", "ECDHE-RSA-AES256-SHA", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + config: testConfig.Clone(), + validate: func(state ConnectionState) error { + if km, err := state.ExportKeyingMaterial("test", nil, 42); err != nil { + return fmt.Errorf("ExportKeyingMaterial failed: %v", err) + } else if len(km) != 42 { + return fmt.Errorf("Got %d bytes from ExportKeyingMaterial, wanted %d", len(km), 42) + } + return nil + }, + } + runServerTestTLS10(t, test) + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerRSAPKCS1v15(t *testing.T) { + test := &serverTest{ + name: "RSA-RSAPKCS1v15", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-sigalgs", "rsa_pkcs1_sha256"}, + } + runServerTestTLS12(t, test) +} + +func TestHandshakeServerRSAPSS(t *testing.T) { + // We send rsa_pss_rsae_sha512 first, as the test key won't fit, and we + // verify the server implementation will disregard the client preference in + // that case. See Issue 29793. + test := &serverTest{ + name: "RSA-RSAPSS", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256", "-sigalgs", "rsa_pss_rsae_sha512:rsa_pss_rsae_sha256"}, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) + + test = &serverTest{ + name: "RSA-RSAPSS-TooSmall", + command: []string{"openssl", "s_client", "-no_ticket", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256", "-sigalgs", "rsa_pss_rsae_sha512"}, + expectHandshakeErrorIncluding: "peer doesn't support any of the certificate's signature algorithms", + } + runServerTestTLS13(t, test) +} + +func TestHandshakeServerEd25519(t *testing.T) { + config := testConfig.Clone() + config.Certificates = make([]Certificate, 1) + config.Certificates[0].Certificate = [][]byte{testEd25519Certificate} + config.Certificates[0].PrivateKey = testEd25519PrivateKey + config.BuildNameToCertificate() + + test := &serverTest{ + name: "Ed25519", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-ECDSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + config: config, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func benchmarkHandshakeServer(b *testing.B, version uint16, cipherSuite uint16, curve CurveID, cert []byte, key crypto.PrivateKey) { + config := testConfig.Clone() + config.CipherSuites = []uint16{cipherSuite} + config.CurvePreferences = []CurveID{curve} + config.Certificates = make([]Certificate, 1) + config.Certificates[0].Certificate = [][]byte{cert} + config.Certificates[0].PrivateKey = key + config.BuildNameToCertificate() + + clientConn, serverConn := localPipe(b) + serverConn = &recordingConn{Conn: serverConn} + go func() { + config := testConfig.Clone() + config.MaxVersion = version + config.CurvePreferences = []CurveID{curve} + client := Client(clientConn, config) + client.Handshake() + }() + server := Server(serverConn, config) + if err := server.Handshake(); err != nil { + b.Fatalf("handshake failed: %v", err) + } + serverConn.Close() + flows := serverConn.(*recordingConn).flows + + feeder := make(chan struct{}) + clientConn, serverConn = localPipe(b) + + go func() { + for range feeder { + for i, f := range flows { + if i%2 == 0 { + clientConn.Write(f) + continue + } + ff := make([]byte, len(f)) + n, err := io.ReadFull(clientConn, ff) + if err != nil { + b.Errorf("#%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", i+1, err, n, len(ff), ff[:n], f) + } + if !bytes.Equal(f, ff) { + b.Errorf("#%d: mismatch on read: got:%x want:%x", i+1, ff, f) + } + } + } + }() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + feeder <- struct{}{} + server := Server(serverConn, config) + if err := server.Handshake(); err != nil { + b.Fatalf("handshake failed: %v", err) + } + } + close(feeder) +} + +func BenchmarkHandshakeServer(b *testing.B) { + b.Run("RSA", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS12, TLS_RSA_WITH_AES_128_GCM_SHA256, + 0, testRSACertificate, testRSAPrivateKey) + }) + b.Run("ECDHE-P256-RSA", func(b *testing.B) { + b.Run("TLSv13", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS13, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + CurveP256, testRSACertificate, testRSAPrivateKey) + }) + b.Run("TLSv12", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS12, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + CurveP256, testRSACertificate, testRSAPrivateKey) + }) + }) + b.Run("ECDHE-P256-ECDSA-P256", func(b *testing.B) { + b.Run("TLSv13", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS13, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + CurveP256, testP256Certificate, testP256PrivateKey) + }) + b.Run("TLSv12", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS12, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + CurveP256, testP256Certificate, testP256PrivateKey) + }) + }) + b.Run("ECDHE-X25519-ECDSA-P256", func(b *testing.B) { + b.Run("TLSv13", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS13, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + X25519, testP256Certificate, testP256PrivateKey) + }) + b.Run("TLSv12", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS12, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + X25519, testP256Certificate, testP256PrivateKey) + }) + }) + b.Run("ECDHE-P521-ECDSA-P521", func(b *testing.B) { + if testECDSAPrivateKey.PublicKey.Curve != elliptic.P521() { + b.Fatal("test ECDSA key doesn't use curve P-521") + } + b.Run("TLSv13", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS13, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + CurveP521, testECDSACertificate, testECDSAPrivateKey) + }) + b.Run("TLSv12", func(b *testing.B) { + benchmarkHandshakeServer(b, VersionTLS12, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + CurveP521, testECDSACertificate, testECDSAPrivateKey) + }) + }) +} + +func TestClientAuth(t *testing.T) { + var certPath, keyPath, ecdsaCertPath, ecdsaKeyPath, ed25519CertPath, ed25519KeyPath string + + if *update { + certPath = tempFile(clientCertificatePEM) + defer os.Remove(certPath) + keyPath = tempFile(clientKeyPEM) + defer os.Remove(keyPath) + ecdsaCertPath = tempFile(clientECDSACertificatePEM) + defer os.Remove(ecdsaCertPath) + ecdsaKeyPath = tempFile(clientECDSAKeyPEM) + defer os.Remove(ecdsaKeyPath) + ed25519CertPath = tempFile(clientEd25519CertificatePEM) + defer os.Remove(ed25519CertPath) + ed25519KeyPath = tempFile(clientEd25519KeyPEM) + defer os.Remove(ed25519KeyPath) + } else { + t.Parallel() + } + + config := testConfig.Clone() + config.ClientAuth = RequestClientCert + + test := &serverTest{ + name: "ClientAuthRequestedNotGiven", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256"}, + config: config, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) + + test = &serverTest{ + name: "ClientAuthRequestedAndGiven", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256", + "-cert", certPath, "-key", keyPath, "-client_sigalgs", "rsa_pss_rsae_sha256"}, + config: config, + expectedPeerCerts: []string{clientCertificatePEM}, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) + + test = &serverTest{ + name: "ClientAuthRequestedAndECDSAGiven", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256", + "-cert", ecdsaCertPath, "-key", ecdsaKeyPath}, + config: config, + expectedPeerCerts: []string{clientECDSACertificatePEM}, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) + + test = &serverTest{ + name: "ClientAuthRequestedAndEd25519Given", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-ciphersuites", "TLS_AES_128_GCM_SHA256", + "-cert", ed25519CertPath, "-key", ed25519KeyPath}, + config: config, + expectedPeerCerts: []string{clientEd25519CertificatePEM}, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) + + test = &serverTest{ + name: "ClientAuthRequestedAndPKCS1v15Given", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", + "-cert", certPath, "-key", keyPath, "-client_sigalgs", "rsa_pkcs1_sha256"}, + config: config, + expectedPeerCerts: []string{clientCertificatePEM}, + } + runServerTestTLS12(t, test) +} + +func TestSNIGivenOnFailure(t *testing.T) { + const expectedServerName = "test.testing" + + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + compressionMethods: []uint8{compressionNone}, + serverName: expectedServerName, + } + + serverConfig := testConfig.Clone() + // Erase the server's cipher suites to ensure the handshake fails. + serverConfig.CipherSuites = nil + + c, s := localPipe(t) + go func() { + cli := Client(c, testConfig) + cli.vers = clientHello.vers + cli.writeRecord(recordTypeHandshake, clientHello.marshal()) + c.Close() + }() + conn := Server(s, serverConfig) + ctx := context.Background() + ch, err := conn.readClientHello(ctx) + hs := serverHandshakeState{ + c: conn, + ctx: ctx, + clientHello: ch, + } + if err == nil { + err = hs.processClientHello() + } + if err == nil { + err = hs.pickCipherSuite() + } + defer s.Close() + + if err == nil { + t.Error("No error reported from server") + } + + cs := hs.c.ConnectionState() + if cs.HandshakeComplete { + t.Error("Handshake registered as complete") + } + + if cs.ServerName != expectedServerName { + t.Errorf("Expected ServerName of %q, but got %q", expectedServerName, cs.ServerName) + } +} + +var getConfigForClientTests = []struct { + setup func(config *Config) + callback func(clientHello *ClientHelloInfo) (*Config, error) + errorSubstring string + verify func(config *Config) error +}{ + { + nil, + func(clientHello *ClientHelloInfo) (*Config, error) { + return nil, nil + }, + "", + nil, + }, + { + nil, + func(clientHello *ClientHelloInfo) (*Config, error) { + return nil, errors.New("should bubble up") + }, + "should bubble up", + nil, + }, + { + nil, + func(clientHello *ClientHelloInfo) (*Config, error) { + config := testConfig.Clone() + // Setting a maximum version of TLS 1.1 should cause + // the handshake to fail, as the client MinVersion is TLS 1.2. + config.MaxVersion = VersionTLS11 + return config, nil + }, + "client offered only unsupported versions", + nil, + }, + { + func(config *Config) { + for i := range config.SessionTicketKey { + config.SessionTicketKey[i] = byte(i) + } + config.sessionTicketKeys = nil + }, + func(clientHello *ClientHelloInfo) (*Config, error) { + config := testConfig.Clone() + for i := range config.SessionTicketKey { + config.SessionTicketKey[i] = 0 + } + config.sessionTicketKeys = nil + return config, nil + }, + "", + func(config *Config) error { + if config.SessionTicketKey == [32]byte{} { + return fmt.Errorf("expected SessionTicketKey to be set") + } + return nil + }, + }, + { + func(config *Config) { + var dummyKey [32]byte + for i := range dummyKey { + dummyKey[i] = byte(i) + } + + config.SetSessionTicketKeys([][32]byte{dummyKey}) + }, + func(clientHello *ClientHelloInfo) (*Config, error) { + config := testConfig.Clone() + config.sessionTicketKeys = nil + return config, nil + }, + "", + func(config *Config) error { + if config.SessionTicketKey == [32]byte{} { + return fmt.Errorf("expected SessionTicketKey to be set") + } + return nil + }, + }, +} + +func TestGetConfigForClient(t *testing.T) { + serverConfig := testConfig.Clone() + clientConfig := testConfig.Clone() + clientConfig.MinVersion = VersionTLS12 + + for i, test := range getConfigForClientTests { + if test.setup != nil { + test.setup(serverConfig) + } + + var configReturned *Config + serverConfig.GetConfigForClient = func(clientHello *ClientHelloInfo) (*Config, error) { + config, err := test.callback(clientHello) + configReturned = config + return config, err + } + c, s := localPipe(t) + done := make(chan error) + + go func() { + defer s.Close() + done <- Server(s, serverConfig).Handshake() + }() + + clientErr := Client(c, clientConfig).Handshake() + c.Close() + + serverErr := <-done + + if len(test.errorSubstring) == 0 { + if serverErr != nil || clientErr != nil { + t.Errorf("test[%d]: expected no error but got serverErr: %q, clientErr: %q", i, serverErr, clientErr) + } + if test.verify != nil { + if err := test.verify(configReturned); err != nil { + t.Errorf("test[%d]: verify returned error: %v", i, err) + } + } + } else { + if serverErr == nil { + t.Errorf("test[%d]: expected error containing %q but got no error", i, test.errorSubstring) + } else if !strings.Contains(serverErr.Error(), test.errorSubstring) { + t.Errorf("test[%d]: expected error to contain %q but it was %q", i, test.errorSubstring, serverErr) + } + } + } +} + +func TestCloseServerConnectionOnIdleClient(t *testing.T) { + clientConn, serverConn := localPipe(t) + server := Server(serverConn, testConfig.Clone()) + go func() { + clientConn.Write([]byte{'0'}) + server.Close() + }() + server.SetReadDeadline(time.Now().Add(time.Minute)) + err := server.Handshake() + if err != nil { + if err, ok := err.(net.Error); ok && err.Timeout() { + t.Errorf("Expected a closed network connection error but got '%s'", err.Error()) + } + } else { + t.Errorf("Error expected, but no error returned") + } +} + +func TestCloneHash(t *testing.T) { + h1 := crypto.SHA256.New() + h1.Write([]byte("test")) + s1 := h1.Sum(nil) + h2 := cloneHash(h1, crypto.SHA256) + s2 := h2.Sum(nil) + if !bytes.Equal(s1, s2) { + t.Error("cloned hash generated a different sum") + } +} + +func expectError(t *testing.T, err error, sub string) { + if err == nil { + t.Errorf(`expected error %q, got nil`, sub) + } else if !strings.Contains(err.Error(), sub) { + t.Errorf(`expected error %q, got %q`, sub, err) + } +} + +func TestKeyTooSmallForRSAPSS(t *testing.T) { + cert, err := X509KeyPair([]byte(`-----BEGIN CERTIFICATE----- +MIIBcTCCARugAwIBAgIQGjQnkCFlUqaFlt6ixyz/tDANBgkqhkiG9w0BAQsFADAS +MRAwDgYDVQQKEwdBY21lIENvMB4XDTE5MDExODIzMjMyOFoXDTIwMDExODIzMjMy +OFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDd +ez1rFUDwax2HTxbcnFUP9AhcgEGMHVV2nn4VVEWFJB6I8C/Nkx0XyyQlrmFYBzEQ +nIPhKls4T0hFoLvjJnXpAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2CC2V4YW1wbGUu +Y29tMA0GCSqGSIb3DQEBCwUAA0EAxDuUS+BrrS3c+h+k+fQPOmOScy6yTX9mHw0Q +KbucGamXYEy0URIwOdO0tQ3LHPc1YGvYSPwkDjkjqECs2Vm/AA== +-----END CERTIFICATE-----`), []byte(testingKey(`-----BEGIN RSA TESTING KEY----- +MIIBOgIBAAJBAN17PWsVQPBrHYdPFtycVQ/0CFyAQYwdVXaefhVURYUkHojwL82T +HRfLJCWuYVgHMRCcg+EqWzhPSEWgu+MmdekCAwEAAQJBALjQYNTdXF4CFBbXwUz/ +yt9QFDYT9B5WT/12jeGAe653gtYS6OOi/+eAkGmzg1GlRnw6fOfn+HYNFDORST7z +4j0CIQDn2xz9hVWQEu9ee3vecNT3f60huDGTNoRhtqgweQGX0wIhAPSLj1VcRZEz +nKpbtU22+PbIMSJ+e80fmY9LIPx5N4HTAiAthGSimMR9bloz0EY3GyuUEyqoDgMd +hXxjuno2WesoJQIgemilbcALXpxsLmZLgcQ2KSmaVr7jb5ECx9R+hYKTw1sCIG4s +T+E0J8wlH24pgwQHzy7Ko2qLwn1b5PW8ecrlvP1g +-----END RSA TESTING KEY-----`))) + if err != nil { + t.Fatal(err) + } + + clientConn, serverConn := localPipe(t) + client := Client(clientConn, testConfig) + done := make(chan struct{}) + go func() { + config := testConfig.Clone() + config.Certificates = []Certificate{cert} + config.MinVersion = VersionTLS13 + server := Server(serverConn, config) + err := server.Handshake() + expectError(t, err, "key size too small") + close(done) + }() + err = client.Handshake() + expectError(t, err, "handshake failure") + <-done +} + +func TestMultipleCertificates(t *testing.T) { + clientConfig := testConfig.Clone() + clientConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256} + clientConfig.MaxVersion = VersionTLS12 + + serverConfig := testConfig.Clone() + serverConfig.Certificates = []Certificate{{ + Certificate: [][]byte{testECDSACertificate}, + PrivateKey: testECDSAPrivateKey, + }, { + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + }} + + _, clientState, err := testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatal(err) + } + if got := clientState.PeerCertificates[0].PublicKeyAlgorithm; got != x509.RSA { + t.Errorf("expected RSA certificate, got %v", got) + } +} + +func TestAESCipherReordering(t *testing.T) { + currentAESSupport := hasAESGCMHardwareSupport + defer func() { hasAESGCMHardwareSupport = currentAESSupport }() + + tests := []struct { + name string + clientCiphers []uint16 + serverHasAESGCM bool + serverCiphers []uint16 + expectedCipher uint16 + }{ + { + name: "server has hardware AES, client doesn't (pick ChaCha)", + clientCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA, + }, + serverHasAESGCM: true, + expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + { + name: "client prefers AES-GCM, server doesn't have hardware AES (pick ChaCha)", + clientCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS_RSA_WITH_AES_128_CBC_SHA, + }, + serverHasAESGCM: false, + expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + { + name: "client prefers AES-GCM, server has hardware AES (pick AES-GCM)", + clientCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS_RSA_WITH_AES_128_CBC_SHA, + }, + serverHasAESGCM: true, + expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + { + name: "client prefers AES-GCM and sends GREASE, server has hardware AES (pick AES-GCM)", + clientCiphers: []uint16{ + 0x0A0A, // GREASE value + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS_RSA_WITH_AES_128_CBC_SHA, + }, + serverHasAESGCM: true, + expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + { + name: "client prefers AES-GCM and doesn't support ChaCha, server doesn't have hardware AES (pick AES-GCM)", + clientCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA, + }, + serverHasAESGCM: false, + expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + { + name: "client prefers AES-GCM and AES-CBC over ChaCha, server doesn't have hardware AES (pick ChaCha)", + clientCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + serverHasAESGCM: false, + expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + { + name: "client prefers AES-GCM over ChaCha and sends GREASE, server doesn't have hardware AES (pick ChaCha)", + clientCiphers: []uint16{ + 0x0A0A, // GREASE value + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS_RSA_WITH_AES_128_CBC_SHA, + }, + serverHasAESGCM: false, + expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + { + name: "client supports multiple AES-GCM, server doesn't have hardware AES and doesn't support ChaCha (AES-GCM)", + clientCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + serverHasAESGCM: false, + serverCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + { + name: "client prefers AES-GCM, server has hardware but doesn't support AES (pick ChaCha)", + clientCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS_RSA_WITH_AES_128_CBC_SHA, + }, + serverHasAESGCM: true, + serverCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + hasAESGCMHardwareSupport = tc.serverHasAESGCM + hs := &serverHandshakeState{ + c: &Conn{ + config: &Config{ + CipherSuites: tc.serverCiphers, + }, + vers: VersionTLS12, + }, + clientHello: &clientHelloMsg{ + cipherSuites: tc.clientCiphers, + vers: VersionTLS12, + }, + ecdheOk: true, + rsaSignOk: true, + rsaDecryptOk: true, + } + + err := hs.pickCipherSuite() + if err != nil { + t.Errorf("pickCipherSuite failed: %s", err) + } + + if tc.expectedCipher != hs.suite.id { + t.Errorf("unexpected cipher chosen: want %d, got %d", tc.expectedCipher, hs.suite.id) + } + }) + } +} + +func TestAESCipherReorderingTLS13(t *testing.T) { + currentAESSupport := hasAESGCMHardwareSupport + defer func() { hasAESGCMHardwareSupport = currentAESSupport }() + + tests := []struct { + name string + clientCiphers []uint16 + serverHasAESGCM bool + expectedCipher uint16 + }{ + { + name: "server has hardware AES, client doesn't (pick ChaCha)", + clientCiphers: []uint16{ + TLS_CHACHA20_POLY1305_SHA256, + TLS_AES_128_GCM_SHA256, + }, + serverHasAESGCM: true, + expectedCipher: TLS_CHACHA20_POLY1305_SHA256, + }, + { + name: "neither server nor client have hardware AES (pick ChaCha)", + clientCiphers: []uint16{ + TLS_CHACHA20_POLY1305_SHA256, + TLS_AES_128_GCM_SHA256, + }, + serverHasAESGCM: false, + expectedCipher: TLS_CHACHA20_POLY1305_SHA256, + }, + { + name: "client prefers AES, server doesn't have hardware (pick ChaCha)", + clientCiphers: []uint16{ + TLS_AES_128_GCM_SHA256, + TLS_CHACHA20_POLY1305_SHA256, + }, + serverHasAESGCM: false, + expectedCipher: TLS_CHACHA20_POLY1305_SHA256, + }, + { + name: "client prefers AES and sends GREASE, server doesn't have hardware (pick ChaCha)", + clientCiphers: []uint16{ + 0x0A0A, // GREASE value + TLS_AES_128_GCM_SHA256, + TLS_CHACHA20_POLY1305_SHA256, + }, + serverHasAESGCM: false, + expectedCipher: TLS_CHACHA20_POLY1305_SHA256, + }, + { + name: "client prefers AES, server has hardware AES (pick AES)", + clientCiphers: []uint16{ + TLS_AES_128_GCM_SHA256, + TLS_CHACHA20_POLY1305_SHA256, + }, + serverHasAESGCM: true, + expectedCipher: TLS_AES_128_GCM_SHA256, + }, + { + name: "client prefers AES and sends GREASE, server has hardware AES (pick AES)", + clientCiphers: []uint16{ + 0x0A0A, // GREASE value + TLS_AES_128_GCM_SHA256, + TLS_CHACHA20_POLY1305_SHA256, + }, + serverHasAESGCM: true, + expectedCipher: TLS_AES_128_GCM_SHA256, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + hasAESGCMHardwareSupport = tc.serverHasAESGCM + hs := &serverHandshakeStateTLS13{ + c: &Conn{ + config: &Config{}, + vers: VersionTLS13, + }, + clientHello: &clientHelloMsg{ + cipherSuites: tc.clientCiphers, + supportedVersions: []uint16{VersionTLS13}, + compressionMethods: []uint8{compressionNone}, + keyShares: []keyShare{{group: X25519, data: curve25519.Basepoint}}, + }, + } + + err := hs.processClientHello() + if err != nil { + t.Errorf("pickCipherSuite failed: %s", err) + } + + if tc.expectedCipher != hs.suite.id { + t.Errorf("unexpected cipher chosen: want %d, got %d", tc.expectedCipher, hs.suite.id) + } + }) + } +} + +// TestServerHandshakeContextCancellation tests that cancelling +// the context given to the server side conn.HandshakeContext +// interrupts the in-progress handshake. +func TestServerHandshakeContextCancellation(t *testing.T) { + c, s := localPipe(t) + ctx, cancel := context.WithCancel(context.Background()) + unblockClient := make(chan struct{}) + defer close(unblockClient) + go func() { + cancel() + <-unblockClient + _ = c.Close() + }() + conn := Server(s, testConfig) + // Initiates server side handshake, which will block until a client hello is read + // unless the cancellation works. + err := conn.HandshakeContext(ctx) + if err == nil { + t.Fatal("Server handshake did not error when the context was canceled") + } + if err != context.Canceled { + t.Errorf("Unexpected server handshake error: %v", err) + } + if runtime.GOARCH == "wasm" { + t.Skip("conn.Close does not error as expected when called multiple times on WASM") + } + err = conn.Close() + if err == nil { + t.Error("Server connection was not closed when the context was canceled") + } +} + +// TestHandshakeContextHierarchy tests whether the contexts +// available to GetClientCertificate and GetCertificate are +// derived from the context provided to HandshakeContext, and +// that those contexts are canceled after HandshakeContext has +// returned. +func TestHandshakeContextHierarchy(t *testing.T) { + c, s := localPipe(t) + clientErr := make(chan error, 1) + clientConfig := testConfig.Clone() + serverConfig := testConfig.Clone() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + key := struct{}{} + ctx = context.WithValue(ctx, key, true) + go func() { + defer close(clientErr) + defer c.Close() + var innerCtx context.Context + clientConfig.Certificates = nil + clientConfig.GetClientCertificate = func(certificateRequest *CertificateRequestInfo) (*Certificate, error) { + if val, ok := certificateRequest.Context().Value(key).(bool); !ok || !val { + t.Errorf("GetClientCertificate context was not child of HandshakeContext") + } + innerCtx = certificateRequest.Context() + return &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + }, nil + } + cli := Client(c, clientConfig) + err := cli.HandshakeContext(ctx) + if err != nil { + clientErr <- err + return + } + select { + case <-innerCtx.Done(): + default: + t.Errorf("GetClientCertificate context was not canceled after HandshakeContext returned.") + } + }() + var innerCtx context.Context + serverConfig.Certificates = nil + serverConfig.ClientAuth = RequestClientCert + serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + if val, ok := clientHello.Context().Value(key).(bool); !ok || !val { + t.Errorf("GetClientCertificate context was not child of HandshakeContext") + } + innerCtx = clientHello.Context() + return &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + }, nil + } + conn := Server(s, serverConfig) + err := conn.HandshakeContext(ctx) + if err != nil { + t.Errorf("Unexpected server handshake error: %v", err) + } + select { + case <-innerCtx.Done(): + default: + t.Errorf("GetCertificate context was not canceled after HandshakeContext returned.") + } + if err := <-clientErr; err != nil { + t.Errorf("Unexpected client error: %v", err) + } +} diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go new file mode 100644 index 0000000..6aa5269 --- /dev/null +++ b/src/crypto/tls/handshake_server_tls13.go @@ -0,0 +1,872 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "context" + "crypto" + "crypto/hmac" + "crypto/rsa" + "encoding/binary" + "errors" + "hash" + "io" + "sync/atomic" + "time" +) + +// maxClientPSKIdentities is the number of client PSK identities the server will +// attempt to validate. It will ignore the rest not to let cheap ClientHello +// messages cause too much work in session ticket decryption attempts. +const maxClientPSKIdentities = 5 + +type serverHandshakeStateTLS13 struct { + c *Conn + ctx context.Context + clientHello *clientHelloMsg + hello *serverHelloMsg + sentDummyCCS bool + usingPSK bool + suite *cipherSuiteTLS13 + cert *Certificate + sigAlg SignatureScheme + earlySecret []byte + sharedKey []byte + handshakeSecret []byte + masterSecret []byte + trafficSecret []byte // client_application_traffic_secret_0 + transcript hash.Hash + clientFinished []byte +} + +func (hs *serverHandshakeStateTLS13) handshake() error { + c := hs.c + + // For an overview of the TLS 1.3 handshake, see RFC 8446, Section 2. + if err := hs.processClientHello(); err != nil { + return err + } + if err := hs.checkForResumption(); err != nil { + return err + } + if err := hs.pickCertificate(); err != nil { + return err + } + c.buffering = true + if err := hs.sendServerParameters(); err != nil { + return err + } + if err := hs.sendServerCertificate(); err != nil { + return err + } + if err := hs.sendServerFinished(); err != nil { + return err + } + // Note that at this point we could start sending application data without + // waiting for the client's second flight, but the application might not + // expect the lack of replay protection of the ClientHello parameters. + if _, err := c.flush(); err != nil { + return err + } + if err := hs.readClientCertificate(); err != nil { + return err + } + if err := hs.readClientFinished(); err != nil { + return err + } + + atomic.StoreUint32(&c.handshakeStatus, 1) + + return nil +} + +func (hs *serverHandshakeStateTLS13) processClientHello() error { + c := hs.c + + hs.hello = new(serverHelloMsg) + + // TLS 1.3 froze the ServerHello.legacy_version field, and uses + // supported_versions instead. See RFC 8446, sections 4.1.3 and 4.2.1. + hs.hello.vers = VersionTLS12 + hs.hello.supportedVersion = c.vers + + if len(hs.clientHello.supportedVersions) == 0 { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: client used the legacy version field to negotiate TLS 1.3") + } + + // Abort if the client is doing a fallback and landing lower than what we + // support. See RFC 7507, which however does not specify the interaction + // with supported_versions. The only difference is that with + // supported_versions a client has a chance to attempt a [TLS 1.2, TLS 1.4] + // handshake in case TLS 1.3 is broken but 1.2 is not. Alas, in that case, + // it will have to drop the TLS_FALLBACK_SCSV protection if it falls back to + // TLS 1.2, because a TLS 1.3 server would abort here. The situation before + // supported_versions was not better because there was just no way to do a + // TLS 1.4 handshake without risking the server selecting TLS 1.3. + for _, id := range hs.clientHello.cipherSuites { + if id == TLS_FALLBACK_SCSV { + // Use c.vers instead of max(supported_versions) because an attacker + // could defeat this by adding an arbitrary high version otherwise. + if c.vers < c.config.maxSupportedVersion() { + c.sendAlert(alertInappropriateFallback) + return errors.New("tls: client using inappropriate protocol fallback") + } + break + } + } + + if len(hs.clientHello.compressionMethods) != 1 || + hs.clientHello.compressionMethods[0] != compressionNone { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: TLS 1.3 client supports illegal compression methods") + } + + hs.hello.random = make([]byte, 32) + if _, err := io.ReadFull(c.config.rand(), hs.hello.random); err != nil { + c.sendAlert(alertInternalError) + return err + } + + if len(hs.clientHello.secureRenegotiation) != 0 { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: initial handshake had non-empty renegotiation extension") + } + + if hs.clientHello.earlyData { + // See RFC 8446, Section 4.2.10 for the complicated behavior required + // here. The scenario is that a different server at our address offered + // to accept early data in the past, which we can't handle. For now, all + // 0-RTT enabled session tickets need to expire before a Go server can + // replace a server or join a pool. That's the same requirement that + // applies to mixing or replacing with any TLS 1.2 server. + c.sendAlert(alertUnsupportedExtension) + return errors.New("tls: client sent unexpected early data") + } + + hs.hello.sessionId = hs.clientHello.sessionId + hs.hello.compressionMethod = compressionNone + + preferenceList := defaultCipherSuitesTLS13 + if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { + preferenceList = defaultCipherSuitesTLS13NoAES + } + for _, suiteID := range preferenceList { + hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID) + if hs.suite != nil { + break + } + } + if hs.suite == nil { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: no cipher suite supported by both client and server") + } + c.cipherSuite = hs.suite.id + hs.hello.cipherSuite = hs.suite.id + hs.transcript = hs.suite.hash.New() + + // Pick the ECDHE group in server preference order, but give priority to + // groups with a key share, to avoid a HelloRetryRequest round-trip. + var selectedGroup CurveID + var clientKeyShare *keyShare +GroupSelection: + for _, preferredGroup := range c.config.curvePreferences() { + for _, ks := range hs.clientHello.keyShares { + if ks.group == preferredGroup { + selectedGroup = ks.group + clientKeyShare = &ks + break GroupSelection + } + } + if selectedGroup != 0 { + continue + } + for _, group := range hs.clientHello.supportedCurves { + if group == preferredGroup { + selectedGroup = group + break + } + } + } + if selectedGroup == 0 { + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: no ECDHE curve supported by both client and server") + } + if clientKeyShare == nil { + if err := hs.doHelloRetryRequest(selectedGroup); err != nil { + return err + } + clientKeyShare = &hs.clientHello.keyShares[0] + } + + if _, ok := curveForCurveID(selectedGroup); selectedGroup != X25519 && !ok { + c.sendAlert(alertInternalError) + return errors.New("tls: CurvePreferences includes unsupported curve") + } + params, err := generateECDHEParameters(c.config.rand(), selectedGroup) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + hs.hello.serverShare = keyShare{group: selectedGroup, data: params.PublicKey()} + hs.sharedKey = params.SharedKey(clientKeyShare.data) + if hs.sharedKey == nil { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: invalid client key share") + } + + c.serverName = hs.clientHello.serverName + return nil +} + +func (hs *serverHandshakeStateTLS13) checkForResumption() error { + c := hs.c + + if c.config.SessionTicketsDisabled { + return nil + } + + modeOK := false + for _, mode := range hs.clientHello.pskModes { + if mode == pskModeDHE { + modeOK = true + break + } + } + if !modeOK { + return nil + } + + if len(hs.clientHello.pskIdentities) != len(hs.clientHello.pskBinders) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: invalid or missing PSK binders") + } + if len(hs.clientHello.pskIdentities) == 0 { + return nil + } + + for i, identity := range hs.clientHello.pskIdentities { + if i >= maxClientPSKIdentities { + break + } + + plaintext, _ := c.decryptTicket(identity.label) + if plaintext == nil { + continue + } + sessionState := new(sessionStateTLS13) + if ok := sessionState.unmarshal(plaintext); !ok { + continue + } + + createdAt := time.Unix(int64(sessionState.createdAt), 0) + if c.config.time().Sub(createdAt) > maxSessionTicketLifetime { + continue + } + + // We don't check the obfuscated ticket age because it's affected by + // clock skew and it's only a freshness signal useful for shrinking the + // window for replay attacks, which don't affect us as we don't do 0-RTT. + + pskSuite := cipherSuiteTLS13ByID(sessionState.cipherSuite) + if pskSuite == nil || pskSuite.hash != hs.suite.hash { + continue + } + + // PSK connections don't re-establish client certificates, but carry + // them over in the session ticket. Ensure the presence of client certs + // in the ticket is consistent with the configured requirements. + sessionHasClientCerts := len(sessionState.certificate.Certificate) != 0 + needClientCerts := requiresClientCert(c.config.ClientAuth) + if needClientCerts && !sessionHasClientCerts { + continue + } + if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { + continue + } + + psk := hs.suite.expandLabel(sessionState.resumptionSecret, "resumption", + nil, hs.suite.hash.Size()) + hs.earlySecret = hs.suite.extract(psk, nil) + binderKey := hs.suite.deriveSecret(hs.earlySecret, resumptionBinderLabel, nil) + // Clone the transcript in case a HelloRetryRequest was recorded. + transcript := cloneHash(hs.transcript, hs.suite.hash) + if transcript == nil { + c.sendAlert(alertInternalError) + return errors.New("tls: internal error: failed to clone hash") + } + transcript.Write(hs.clientHello.marshalWithoutBinders()) + pskBinder := hs.suite.finishedHash(binderKey, transcript) + if !hmac.Equal(hs.clientHello.pskBinders[i], pskBinder) { + c.sendAlert(alertDecryptError) + return errors.New("tls: invalid PSK binder") + } + + c.didResume = true + if err := c.processCertsFromClient(sessionState.certificate); err != nil { + return err + } + + hs.hello.selectedIdentityPresent = true + hs.hello.selectedIdentity = uint16(i) + hs.usingPSK = true + return nil + } + + return nil +} + +// cloneHash uses the encoding.BinaryMarshaler and encoding.BinaryUnmarshaler +// interfaces implemented by standard library hashes to clone the state of in +// to a new instance of h. It returns nil if the operation fails. +func cloneHash(in hash.Hash, h crypto.Hash) hash.Hash { + // Recreate the interface to avoid importing encoding. + type binaryMarshaler interface { + MarshalBinary() (data []byte, err error) + UnmarshalBinary(data []byte) error + } + marshaler, ok := in.(binaryMarshaler) + if !ok { + return nil + } + state, err := marshaler.MarshalBinary() + if err != nil { + return nil + } + out := h.New() + unmarshaler, ok := out.(binaryMarshaler) + if !ok { + return nil + } + if err := unmarshaler.UnmarshalBinary(state); err != nil { + return nil + } + return out +} + +func (hs *serverHandshakeStateTLS13) pickCertificate() error { + c := hs.c + + // Only one of PSK and certificates are used at a time. + if hs.usingPSK { + return nil + } + + // signature_algorithms is required in TLS 1.3. See RFC 8446, Section 4.2.3. + if len(hs.clientHello.supportedSignatureAlgorithms) == 0 { + return c.sendAlert(alertMissingExtension) + } + + certificate, err := c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello)) + if err != nil { + if err == errNoCertificates { + c.sendAlert(alertUnrecognizedName) + } else { + c.sendAlert(alertInternalError) + } + return err + } + hs.sigAlg, err = selectSignatureScheme(c.vers, certificate, hs.clientHello.supportedSignatureAlgorithms) + if err != nil { + // getCertificate returned a certificate that is unsupported or + // incompatible with the client's signature algorithms. + c.sendAlert(alertHandshakeFailure) + return err + } + hs.cert = certificate + + return nil +} + +// sendDummyChangeCipherSpec sends a ChangeCipherSpec record for compatibility +// with middleboxes that didn't implement TLS correctly. See RFC 8446, Appendix D.4. +func (hs *serverHandshakeStateTLS13) sendDummyChangeCipherSpec() error { + if hs.sentDummyCCS { + return nil + } + hs.sentDummyCCS = true + + _, err := hs.c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + return err +} + +func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) error { + c := hs.c + + // The first ClientHello gets double-hashed into the transcript upon a + // HelloRetryRequest. See RFC 8446, Section 4.4.1. + hs.transcript.Write(hs.clientHello.marshal()) + chHash := hs.transcript.Sum(nil) + hs.transcript.Reset() + hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) + hs.transcript.Write(chHash) + + helloRetryRequest := &serverHelloMsg{ + vers: hs.hello.vers, + random: helloRetryRequestRandom, + sessionId: hs.hello.sessionId, + cipherSuite: hs.hello.cipherSuite, + compressionMethod: hs.hello.compressionMethod, + supportedVersion: hs.hello.supportedVersion, + selectedGroup: selectedGroup, + } + + hs.transcript.Write(helloRetryRequest.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal()); err != nil { + return err + } + + if err := hs.sendDummyChangeCipherSpec(); err != nil { + return err + } + + msg, err := c.readHandshake() + if err != nil { + return err + } + + clientHello, ok := msg.(*clientHelloMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(clientHello, msg) + } + + if len(clientHello.keyShares) != 1 || clientHello.keyShares[0].group != selectedGroup { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: client sent invalid key share in second ClientHello") + } + + if clientHello.earlyData { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: client indicated early data in second ClientHello") + } + + if illegalClientHelloChange(clientHello, hs.clientHello) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: client illegally modified second ClientHello") + } + + hs.clientHello = clientHello + return nil +} + +// illegalClientHelloChange reports whether the two ClientHello messages are +// different, with the exception of the changes allowed before and after a +// HelloRetryRequest. See RFC 8446, Section 4.1.2. +func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool { + if len(ch.supportedVersions) != len(ch1.supportedVersions) || + len(ch.cipherSuites) != len(ch1.cipherSuites) || + len(ch.supportedCurves) != len(ch1.supportedCurves) || + len(ch.supportedSignatureAlgorithms) != len(ch1.supportedSignatureAlgorithms) || + len(ch.supportedSignatureAlgorithmsCert) != len(ch1.supportedSignatureAlgorithmsCert) || + len(ch.alpnProtocols) != len(ch1.alpnProtocols) { + return true + } + for i := range ch.supportedVersions { + if ch.supportedVersions[i] != ch1.supportedVersions[i] { + return true + } + } + for i := range ch.cipherSuites { + if ch.cipherSuites[i] != ch1.cipherSuites[i] { + return true + } + } + for i := range ch.supportedCurves { + if ch.supportedCurves[i] != ch1.supportedCurves[i] { + return true + } + } + for i := range ch.supportedSignatureAlgorithms { + if ch.supportedSignatureAlgorithms[i] != ch1.supportedSignatureAlgorithms[i] { + return true + } + } + for i := range ch.supportedSignatureAlgorithmsCert { + if ch.supportedSignatureAlgorithmsCert[i] != ch1.supportedSignatureAlgorithmsCert[i] { + return true + } + } + for i := range ch.alpnProtocols { + if ch.alpnProtocols[i] != ch1.alpnProtocols[i] { + return true + } + } + return ch.vers != ch1.vers || + !bytes.Equal(ch.random, ch1.random) || + !bytes.Equal(ch.sessionId, ch1.sessionId) || + !bytes.Equal(ch.compressionMethods, ch1.compressionMethods) || + ch.serverName != ch1.serverName || + ch.ocspStapling != ch1.ocspStapling || + !bytes.Equal(ch.supportedPoints, ch1.supportedPoints) || + ch.ticketSupported != ch1.ticketSupported || + !bytes.Equal(ch.sessionTicket, ch1.sessionTicket) || + ch.secureRenegotiationSupported != ch1.secureRenegotiationSupported || + !bytes.Equal(ch.secureRenegotiation, ch1.secureRenegotiation) || + ch.scts != ch1.scts || + !bytes.Equal(ch.cookie, ch1.cookie) || + !bytes.Equal(ch.pskModes, ch1.pskModes) +} + +func (hs *serverHandshakeStateTLS13) sendServerParameters() error { + c := hs.c + + hs.transcript.Write(hs.clientHello.marshal()) + hs.transcript.Write(hs.hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { + return err + } + + if err := hs.sendDummyChangeCipherSpec(); err != nil { + return err + } + + earlySecret := hs.earlySecret + if earlySecret == nil { + earlySecret = hs.suite.extract(nil, nil) + } + hs.handshakeSecret = hs.suite.extract(hs.sharedKey, + hs.suite.deriveSecret(earlySecret, "derived", nil)) + + clientSecret := hs.suite.deriveSecret(hs.handshakeSecret, + clientHandshakeTrafficLabel, hs.transcript) + c.in.setTrafficSecret(hs.suite, clientSecret) + serverSecret := hs.suite.deriveSecret(hs.handshakeSecret, + serverHandshakeTrafficLabel, hs.transcript) + c.out.setTrafficSecret(hs.suite, serverSecret) + + err := c.config.writeKeyLog(keyLogLabelClientHandshake, hs.clientHello.random, clientSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + err = c.config.writeKeyLog(keyLogLabelServerHandshake, hs.clientHello.random, serverSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + + encryptedExtensions := new(encryptedExtensionsMsg) + + selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols) + if err != nil { + c.sendAlert(alertNoApplicationProtocol) + return err + } + encryptedExtensions.alpnProtocol = selectedProto + c.clientProtocol = selectedProto + + hs.transcript.Write(encryptedExtensions.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()); err != nil { + return err + } + + return nil +} + +func (hs *serverHandshakeStateTLS13) requestClientCert() bool { + return hs.c.config.ClientAuth >= RequestClientCert && !hs.usingPSK +} + +func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { + c := hs.c + + // Only one of PSK and certificates are used at a time. + if hs.usingPSK { + return nil + } + + if hs.requestClientCert() { + // Request a client certificate + certReq := new(certificateRequestMsgTLS13) + certReq.ocspStapling = true + certReq.scts = true + certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms + if c.config.ClientCAs != nil { + certReq.certificateAuthorities = c.config.ClientCAs.Subjects() + } + + hs.transcript.Write(certReq.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil { + return err + } + } + + certMsg := new(certificateMsgTLS13) + + certMsg.certificate = *hs.cert + certMsg.scts = hs.clientHello.scts && len(hs.cert.SignedCertificateTimestamps) > 0 + certMsg.ocspStapling = hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 + + hs.transcript.Write(certMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { + return err + } + + certVerifyMsg := new(certificateVerifyMsg) + certVerifyMsg.hasSignatureAlgorithm = true + certVerifyMsg.signatureAlgorithm = hs.sigAlg + + sigType, sigHash, err := typeAndHashFromSignatureScheme(hs.sigAlg) + if err != nil { + return c.sendAlert(alertInternalError) + } + + signed := signedMessage(sigHash, serverSignatureContext, hs.transcript) + signOpts := crypto.SignerOpts(sigHash) + if sigType == signatureRSAPSS { + signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} + } + sig, err := hs.cert.PrivateKey.(crypto.Signer).Sign(c.config.rand(), signed, signOpts) + if err != nil { + public := hs.cert.PrivateKey.(crypto.Signer).Public() + if rsaKey, ok := public.(*rsa.PublicKey); ok && sigType == signatureRSAPSS && + rsaKey.N.BitLen()/8 < sigHash.Size()*2+2 { // key too small for RSA-PSS + c.sendAlert(alertHandshakeFailure) + } else { + c.sendAlert(alertInternalError) + } + return errors.New("tls: failed to sign handshake: " + err.Error()) + } + certVerifyMsg.signature = sig + + hs.transcript.Write(certVerifyMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certVerifyMsg.marshal()); err != nil { + return err + } + + return nil +} + +func (hs *serverHandshakeStateTLS13) sendServerFinished() error { + c := hs.c + + finished := &finishedMsg{ + verifyData: hs.suite.finishedHash(c.out.trafficSecret, hs.transcript), + } + + hs.transcript.Write(finished.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { + return err + } + + // Derive secrets that take context through the server Finished. + + hs.masterSecret = hs.suite.extract(nil, + hs.suite.deriveSecret(hs.handshakeSecret, "derived", nil)) + + hs.trafficSecret = hs.suite.deriveSecret(hs.masterSecret, + clientApplicationTrafficLabel, hs.transcript) + serverSecret := hs.suite.deriveSecret(hs.masterSecret, + serverApplicationTrafficLabel, hs.transcript) + c.out.setTrafficSecret(hs.suite, serverSecret) + + err := c.config.writeKeyLog(keyLogLabelClientTraffic, hs.clientHello.random, hs.trafficSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + err = c.config.writeKeyLog(keyLogLabelServerTraffic, hs.clientHello.random, serverSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + + c.ekm = hs.suite.exportKeyingMaterial(hs.masterSecret, hs.transcript) + + // If we did not request client certificates, at this point we can + // precompute the client finished and roll the transcript forward to send + // session tickets in our first flight. + if !hs.requestClientCert() { + if err := hs.sendSessionTickets(); err != nil { + return err + } + } + + return nil +} + +func (hs *serverHandshakeStateTLS13) shouldSendSessionTickets() bool { + if hs.c.config.SessionTicketsDisabled { + return false + } + + // Don't send tickets the client wouldn't use. See RFC 8446, Section 4.2.9. + for _, pskMode := range hs.clientHello.pskModes { + if pskMode == pskModeDHE { + return true + } + } + return false +} + +func (hs *serverHandshakeStateTLS13) sendSessionTickets() error { + c := hs.c + + hs.clientFinished = hs.suite.finishedHash(c.in.trafficSecret, hs.transcript) + finishedMsg := &finishedMsg{ + verifyData: hs.clientFinished, + } + hs.transcript.Write(finishedMsg.marshal()) + + if !hs.shouldSendSessionTickets() { + return nil + } + + resumptionSecret := hs.suite.deriveSecret(hs.masterSecret, + resumptionLabel, hs.transcript) + + m := new(newSessionTicketMsgTLS13) + + var certsFromClient [][]byte + for _, cert := range c.peerCertificates { + certsFromClient = append(certsFromClient, cert.Raw) + } + state := sessionStateTLS13{ + cipherSuite: hs.suite.id, + createdAt: uint64(c.config.time().Unix()), + resumptionSecret: resumptionSecret, + certificate: Certificate{ + Certificate: certsFromClient, + OCSPStaple: c.ocspResponse, + SignedCertificateTimestamps: c.scts, + }, + } + var err error + m.label, err = c.encryptTicket(state.marshal()) + if err != nil { + return err + } + m.lifetime = uint32(maxSessionTicketLifetime / time.Second) + + // ticket_age_add is a random 32-bit value. See RFC 8446, section 4.6.1 + // The value is not stored anywhere; we never need to check the ticket age + // because 0-RTT is not supported. + ageAdd := make([]byte, 4) + _, err = hs.c.config.rand().Read(ageAdd) + if err != nil { + return err + } + m.ageAdd = binary.LittleEndian.Uint32(ageAdd) + + // ticket_nonce, which must be unique per connection, is always left at + // zero because we only ever send one ticket per connection. + + if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil { + return err + } + + return nil +} + +func (hs *serverHandshakeStateTLS13) readClientCertificate() error { + c := hs.c + + if !hs.requestClientCert() { + // Make sure the connection is still being verified whether or not + // the server requested a client certificate. + if c.config.VerifyConnection != nil { + if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + return nil + } + + // If we requested a client certificate, then the client must send a + // certificate message. If it's empty, no CertificateVerify is sent. + + msg, err := c.readHandshake() + if err != nil { + return err + } + + certMsg, ok := msg.(*certificateMsgTLS13) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) + } + hs.transcript.Write(certMsg.marshal()) + + if err := c.processCertsFromClient(certMsg.certificate); err != nil { + return err + } + + if c.config.VerifyConnection != nil { + if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { + c.sendAlert(alertBadCertificate) + return err + } + } + + if len(certMsg.certificate.Certificate) != 0 { + msg, err = c.readHandshake() + if err != nil { + return err + } + + certVerify, ok := msg.(*certificateVerifyMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certVerify, msg) + } + + // See RFC 8446, Section 4.4.3. + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: client certificate used with invalid signature algorithm") + } + sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm) + if err != nil { + return c.sendAlert(alertInternalError) + } + if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: client certificate used with invalid signature algorithm") + } + signed := signedMessage(sigHash, clientSignatureContext, hs.transcript) + if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, + sigHash, signed, certVerify.signature); err != nil { + c.sendAlert(alertDecryptError) + return errors.New("tls: invalid signature by the client certificate: " + err.Error()) + } + + hs.transcript.Write(certVerify.marshal()) + } + + // If we waited until the client certificates to send session tickets, we + // are ready to do it now. + if err := hs.sendSessionTickets(); err != nil { + return err + } + + return nil +} + +func (hs *serverHandshakeStateTLS13) readClientFinished() error { + c := hs.c + + msg, err := c.readHandshake() + if err != nil { + return err + } + + finished, ok := msg.(*finishedMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(finished, msg) + } + + if !hmac.Equal(hs.clientFinished, finished.verifyData) { + c.sendAlert(alertDecryptError) + return errors.New("tls: invalid client finished hash") + } + + c.in.setTrafficSecret(hs.suite, hs.trafficSecret) + + return nil +} diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go new file mode 100644 index 0000000..9bfb117 --- /dev/null +++ b/src/crypto/tls/handshake_test.go @@ -0,0 +1,529 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bufio" + "crypto/ed25519" + "crypto/x509" + "encoding/hex" + "errors" + "flag" + "fmt" + "io" + "net" + "os" + "os/exec" + "runtime" + "strconv" + "strings" + "sync" + "testing" + "time" +) + +// TLS reference tests run a connection against a reference implementation +// (OpenSSL) of TLS and record the bytes of the resulting connection. The Go +// code, during a test, is configured with deterministic randomness and so the +// reference test can be reproduced exactly in the future. +// +// In order to save everyone who wishes to run the tests from needing the +// reference implementation installed, the reference connections are saved in +// files in the testdata directory. Thus running the tests involves nothing +// external, but creating and updating them requires the reference +// implementation. +// +// Tests can be updated by running them with the -update flag. This will cause +// the test files for failing tests to be regenerated. Since the reference +// implementation will always generate fresh random numbers, large parts of the +// reference connection will always change. + +var ( + update = flag.Bool("update", false, "update golden files on failure") + fast = flag.Bool("fast", false, "impose a quick, possibly flaky timeout on recorded tests") + keyFile = flag.String("keylog", "", "destination file for KeyLogWriter") +) + +func runTestAndUpdateIfNeeded(t *testing.T, name string, run func(t *testing.T, update bool), wait bool) { + success := t.Run(name, func(t *testing.T) { + if !*update && !wait { + t.Parallel() + } + run(t, false) + }) + + if !success && *update { + t.Run(name+"#update", func(t *testing.T) { + run(t, true) + }) + } +} + +// checkOpenSSLVersion ensures that the version of OpenSSL looks reasonable +// before updating the test data. +func checkOpenSSLVersion() error { + if !*update { + return nil + } + + openssl := exec.Command("openssl", "version") + output, err := openssl.CombinedOutput() + if err != nil { + return err + } + + version := string(output) + if strings.HasPrefix(version, "OpenSSL 1.1.1") { + return nil + } + + println("***********************************************") + println("") + println("You need to build OpenSSL 1.1.1 from source in order") + println("to update the test data.") + println("") + println("Configure it with:") + println("./Configure enable-weak-ssl-ciphers no-shared") + println("and then add the apps/ directory at the front of your PATH.") + println("***********************************************") + + return errors.New("version of OpenSSL does not appear to be suitable for updating test data") +} + +// recordingConn is a net.Conn that records the traffic that passes through it. +// WriteTo can be used to produce output that can be later be loaded with +// ParseTestData. +type recordingConn struct { + net.Conn + sync.Mutex + flows [][]byte + reading bool +} + +func (r *recordingConn) Read(b []byte) (n int, err error) { + if n, err = r.Conn.Read(b); n == 0 { + return + } + b = b[:n] + + r.Lock() + defer r.Unlock() + + if l := len(r.flows); l == 0 || !r.reading { + buf := make([]byte, len(b)) + copy(buf, b) + r.flows = append(r.flows, buf) + } else { + r.flows[l-1] = append(r.flows[l-1], b[:n]...) + } + r.reading = true + return +} + +func (r *recordingConn) Write(b []byte) (n int, err error) { + if n, err = r.Conn.Write(b); n == 0 { + return + } + b = b[:n] + + r.Lock() + defer r.Unlock() + + if l := len(r.flows); l == 0 || r.reading { + buf := make([]byte, len(b)) + copy(buf, b) + r.flows = append(r.flows, buf) + } else { + r.flows[l-1] = append(r.flows[l-1], b[:n]...) + } + r.reading = false + return +} + +// WriteTo writes Go source code to w that contains the recorded traffic. +func (r *recordingConn) WriteTo(w io.Writer) (int64, error) { + // TLS always starts with a client to server flow. + clientToServer := true + var written int64 + for i, flow := range r.flows { + source, dest := "client", "server" + if !clientToServer { + source, dest = dest, source + } + n, err := fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, source, dest) + written += int64(n) + if err != nil { + return written, err + } + dumper := hex.Dumper(w) + n, err = dumper.Write(flow) + written += int64(n) + if err != nil { + return written, err + } + err = dumper.Close() + if err != nil { + return written, err + } + clientToServer = !clientToServer + } + return written, nil +} + +func parseTestData(r io.Reader) (flows [][]byte, err error) { + var currentFlow []byte + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + // If the line starts with ">>> " then it marks the beginning + // of a new flow. + if strings.HasPrefix(line, ">>> ") { + if len(currentFlow) > 0 || len(flows) > 0 { + flows = append(flows, currentFlow) + currentFlow = nil + } + continue + } + + // Otherwise the line is a line of hex dump that looks like: + // 00000170 fc f5 06 bf (...) |.....X{&?......!| + // (Some bytes have been omitted from the middle section.) + + if i := strings.IndexByte(line, ' '); i >= 0 { + line = line[i:] + } else { + return nil, errors.New("invalid test data") + } + + if i := strings.IndexByte(line, '|'); i >= 0 { + line = line[:i] + } else { + return nil, errors.New("invalid test data") + } + + hexBytes := strings.Fields(line) + for _, hexByte := range hexBytes { + val, err := strconv.ParseUint(hexByte, 16, 8) + if err != nil { + return nil, errors.New("invalid hex byte in test data: " + err.Error()) + } + currentFlow = append(currentFlow, byte(val)) + } + } + + if len(currentFlow) > 0 { + flows = append(flows, currentFlow) + } + + return flows, nil +} + +// tempFile creates a temp file containing contents and returns its path. +func tempFile(contents string) string { + file, err := os.CreateTemp("", "go-tls-test") + if err != nil { + panic("failed to create temp file: " + err.Error()) + } + path := file.Name() + file.WriteString(contents) + file.Close() + return path +} + +// localListener is set up by TestMain and used by localPipe to create Conn +// pairs like net.Pipe, but connected by an actual buffered TCP connection. +var localListener struct { + mu sync.Mutex + addr net.Addr + ch chan net.Conn +} + +const localFlakes = 0 // change to 1 or 2 to exercise localServer/localPipe handling of mismatches + +func localServer(l net.Listener) { + for n := 0; ; n++ { + c, err := l.Accept() + if err != nil { + return + } + if localFlakes == 1 && n%2 == 0 { + c.Close() + continue + } + localListener.ch <- c + } +} + +var isConnRefused = func(err error) bool { return false } + +func localPipe(t testing.TB) (net.Conn, net.Conn) { + localListener.mu.Lock() + defer localListener.mu.Unlock() + + addr := localListener.addr + + var err error +Dialing: + // We expect a rare mismatch, but probably not 5 in a row. + for i := 0; i < 5; i++ { + tooSlow := time.NewTimer(1 * time.Second) + defer tooSlow.Stop() + var c1 net.Conn + c1, err = net.Dial(addr.Network(), addr.String()) + if err != nil { + if runtime.GOOS == "dragonfly" && (isConnRefused(err) || os.IsTimeout(err)) { + // golang.org/issue/29583: Dragonfly sometimes returns a spurious + // ECONNREFUSED or ETIMEDOUT. + <-tooSlow.C + continue + } + t.Fatalf("localPipe: %v", err) + } + if localFlakes == 2 && i == 0 { + c1.Close() + continue + } + for { + select { + case <-tooSlow.C: + t.Logf("localPipe: timeout waiting for %v", c1.LocalAddr()) + c1.Close() + continue Dialing + + case c2 := <-localListener.ch: + if c2.RemoteAddr().String() == c1.LocalAddr().String() { + return c1, c2 + } + t.Logf("localPipe: unexpected connection: %v != %v", c2.RemoteAddr(), c1.LocalAddr()) + c2.Close() + } + } + } + + t.Fatalf("localPipe: failed to connect: %v", err) + panic("unreachable") +} + +// zeroSource is an io.Reader that returns an unlimited number of zero bytes. +type zeroSource struct{} + +func (zeroSource) Read(b []byte) (n int, err error) { + for i := range b { + b[i] = 0 + } + + return len(b), nil +} + +func allCipherSuites() []uint16 { + ids := make([]uint16, len(cipherSuites)) + for i, suite := range cipherSuites { + ids[i] = suite.id + } + + return ids +} + +var testConfig *Config + +func TestMain(m *testing.M) { + flag.Parse() + os.Exit(runMain(m)) +} + +func runMain(m *testing.M) int { + // Cipher suites preferences change based on the architecture. Force them to + // the version without AES acceleration for test consistency. + hasAESGCMHardwareSupport = false + + // Set up localPipe. + l, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + l, err = net.Listen("tcp6", "[::1]:0") + } + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to open local listener: %v", err) + os.Exit(1) + } + localListener.ch = make(chan net.Conn) + localListener.addr = l.Addr() + defer l.Close() + go localServer(l) + + if err := checkOpenSSLVersion(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v", err) + os.Exit(1) + } + + testConfig = &Config{ + Time: func() time.Time { return time.Unix(0, 0) }, + Rand: zeroSource{}, + Certificates: make([]Certificate, 2), + InsecureSkipVerify: true, + CipherSuites: allCipherSuites(), + } + testConfig.Certificates[0].Certificate = [][]byte{testRSACertificate} + testConfig.Certificates[0].PrivateKey = testRSAPrivateKey + testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate} + testConfig.Certificates[1].PrivateKey = testRSAPrivateKey + testConfig.BuildNameToCertificate() + if *keyFile != "" { + f, err := os.OpenFile(*keyFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + panic("failed to open -keylog file: " + err.Error()) + } + testConfig.KeyLogWriter = f + defer f.Close() + } + + return m.Run() +} + +func testHandshake(t *testing.T, clientConfig, serverConfig *Config) (serverState, clientState ConnectionState, err error) { + const sentinel = "SENTINEL\n" + c, s := localPipe(t) + errChan := make(chan error) + go func() { + cli := Client(c, clientConfig) + err := cli.Handshake() + if err != nil { + errChan <- fmt.Errorf("client: %v", err) + c.Close() + return + } + defer cli.Close() + clientState = cli.ConnectionState() + buf, err := io.ReadAll(cli) + if err != nil { + t.Errorf("failed to call cli.Read: %v", err) + } + if got := string(buf); got != sentinel { + t.Errorf("read %q from TLS connection, but expected %q", got, sentinel) + } + errChan <- nil + }() + server := Server(s, serverConfig) + err = server.Handshake() + if err == nil { + serverState = server.ConnectionState() + if _, err := io.WriteString(server, sentinel); err != nil { + t.Errorf("failed to call server.Write: %v", err) + } + if err := server.Close(); err != nil { + t.Errorf("failed to call server.Close: %v", err) + } + err = <-errChan + } else { + s.Close() + <-errChan + } + return +} + +func fromHex(s string) []byte { + b, _ := hex.DecodeString(s) + return b +} + +var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7") + +var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76") + +// testRSAPSSCertificate has signatureAlgorithm rsassaPss, but subjectPublicKeyInfo +// algorithm rsaEncryption, for use with the rsa_pss_rsae_* SignatureSchemes. +// See also TestRSAPSSKeyError. testRSAPSSCertificate is self-signed. +var testRSAPSSCertificate = fromHex("308202583082018da003020102021100f29926eb87ea8a0db9fcc247347c11b0304106092a864886f70d01010a3034a00f300d06096086480165030402010500a11c301a06092a864886f70d010108300d06096086480165030402010500a20302012030123110300e060355040a130741636d6520436f301e170d3137313132333136313631305a170d3138313132333136313631305a30123110300e060355040a130741636d6520436f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a3463044300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000300f0603551d110408300687047f000001304106092a864886f70d01010a3034a00f300d06096086480165030402010500a11c301a06092a864886f70d010108300d06096086480165030402010500a20302012003818100cdac4ef2ce5f8d79881042707f7cbf1b5a8a00ef19154b40151771006cd41626e5496d56da0c1a139fd84695593cb67f87765e18aa03ea067522dd78d2a589b8c92364e12838ce346c6e067b51f1a7e6f4b37ffab13f1411896679d18e880e0ba09e302ac067efca460288e9538122692297ad8093d4f7dd701424d7700a46a1") + +var testECDSACertificate = fromHex("3082020030820162020900b8bf2d47a0d2ebf4300906072a8648ce3d04013045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3132313132323135303633325a170d3232313132303135303633325a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819b301006072a8648ce3d020106052b81040023038186000400c4a1edbe98f90b4873367ec316561122f23d53c33b4d213dcd6b75e6f6b0dc9adf26c1bcb287f072327cb3642f1c90bcea6823107efee325c0483a69e0286dd33700ef0462dd0da09c706283d881d36431aa9e9731bd96b068c09b23de76643f1a5c7fe9120e5858b65f70dd9bd8ead5d7f5d5ccb9b69f30665b669a20e227e5bffe3b300906072a8648ce3d040103818c0030818802420188a24febe245c5487d1bacf5ed989dae4770c05e1bb62fbdf1b64db76140d311a2ceee0b7e927eff769dc33b7ea53fcefa10e259ec472d7cacda4e970e15a06fd00242014dfcbe67139c2d050ebd3fa38c25c13313830d9406bbd4377af6ec7ac9862eddd711697f857c56defb31782be4c7780daecbbe9e4e3624317b6a0f399512078f2a") + +var testEd25519Certificate = fromHex("3082012e3081e1a00302010202100f431c425793941de987e4f1ad15005d300506032b657030123110300e060355040a130741636d6520436f301e170d3139303531363231333830315a170d3230303531353231333830315a30123110300e060355040a130741636d6520436f302a300506032b65700321003fe2152ee6e3ef3f4e854a7577a3649eede0bf842ccc92268ffa6f3483aaec8fa34d304b300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff0402300030160603551d11040f300d820b6578616d706c652e636f6d300506032b65700341006344ed9cc4be5324539fd2108d9fe82108909539e50dc155ff2c16b71dfcab7d4dd4e09313d0a942e0b66bfe5d6748d79f50bc6ccd4b03837cf20858cdaccf0c") + +var testSNICertificate = fromHex("0441883421114c81480804c430820237308201a0a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a3023310b3009060355040a1302476f311430120603550403130b736e69746573742e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a3773075300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b0500038181007beeecff0230dbb2e7a334af65430b7116e09f327c3bbf918107fc9c66cb497493207ae9b4dbb045cb63d605ec1b5dd485bb69124d68fa298dc776699b47632fd6d73cab57042acb26f083c4087459bc5a3bb3ca4d878d7fe31016b7bc9a627438666566e3389bfaeebe6becc9a0093ceed18d0f9ac79d56f3a73f18188988ed") + +var testP256Certificate = fromHex("308201693082010ea00302010202105012dc24e1124ade4f3e153326ff27bf300a06082a8648ce3d04030230123110300e060355040a130741636d6520436f301e170d3137303533313232343934375a170d3138303533313232343934375a30123110300e060355040a130741636d6520436f3059301306072a8648ce3d020106082a8648ce3d03010703420004c02c61c9b16283bbcc14956d886d79b358aa614596975f78cece787146abf74c2d5dc578c0992b4f3c631373479ebf3892efe53d21c4f4f1cc9a11c3536b7f75a3463044300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000300f0603551d1104083006820474657374300a06082a8648ce3d0403020349003046022100963712d6226c7b2bef41512d47e1434131aaca3ba585d666c924df71ac0448b3022100f4d05c725064741aef125f243cdbccaa2a5d485927831f221c43023bd5ae471a") + +var testRSAPrivateKey, _ = x509.ParsePKCS1PrivateKey(fromHex("3082025b02010002818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d702030100010281800b07fbcf48b50f1388db34b016298b8217f2092a7c9a04f77db6775a3d1279b62ee9951f7e371e9de33f015aea80660760b3951dc589a9f925ed7de13e8f520e1ccbc7498ce78e7fab6d59582c2386cc07ed688212a576ff37833bd5943483b5554d15a0b9b4010ed9bf09f207e7e9805f649240ed6c1256ed75ab7cd56d9671024100fded810da442775f5923debae4ac758390a032a16598d62f059bb2e781a9c2f41bfa015c209f966513fe3bf5a58717cbdb385100de914f88d649b7d15309fa49024100dd10978c623463a1802c52f012cfa72ff5d901f25a2292446552c2568b1840e49a312e127217c2186615aae4fb6602a4f6ebf3f3d160f3b3ad04c592f65ae41f02400c69062ca781841a09de41ed7a6d9f54adc5d693a2c6847949d9e1358555c9ac6a8d9e71653ac77beb2d3abaf7bb1183aa14278956575dbebf525d0482fd72d90240560fe1900ba36dae3022115fd952f2399fb28e2975a1c3e3d0b679660bdcb356cc189d611cfdd6d87cd5aea45aa30a2082e8b51e94c2f3dd5d5c6036a8a615ed0240143993d80ece56f877cb80048335701eb0e608cc0c1ca8c2227b52edf8f1ac99c562f2541b5ce81f0515af1c5b4770dba53383964b4b725ff46fdec3d08907df")) + +var testECDSAPrivateKey, _ = x509.ParseECPrivateKey(fromHex("3081dc0201010442019883e909ad0ac9ea3d33f9eae661f1785206970f8ca9a91672f1eedca7a8ef12bd6561bb246dda5df4b4d5e7e3a92649bc5d83a0bf92972e00e62067d0c7bd99d7a00706052b81040023a18189038186000400c4a1edbe98f90b4873367ec316561122f23d53c33b4d213dcd6b75e6f6b0dc9adf26c1bcb287f072327cb3642f1c90bcea6823107efee325c0483a69e0286dd33700ef0462dd0da09c706283d881d36431aa9e9731bd96b068c09b23de76643f1a5c7fe9120e5858b65f70dd9bd8ead5d7f5d5ccb9b69f30665b669a20e227e5bffe3b")) + +var testP256PrivateKey, _ = x509.ParseECPrivateKey(fromHex("30770201010420012f3b52bc54c36ba3577ad45034e2e8efe1e6999851284cb848725cfe029991a00a06082a8648ce3d030107a14403420004c02c61c9b16283bbcc14956d886d79b358aa614596975f78cece787146abf74c2d5dc578c0992b4f3c631373479ebf3892efe53d21c4f4f1cc9a11c3536b7f75")) + +var testEd25519PrivateKey = ed25519.PrivateKey(fromHex("3a884965e76b3f55e5faf9615458a92354894234de3ec9f684d46d55cebf3dc63fe2152ee6e3ef3f4e854a7577a3649eede0bf842ccc92268ffa6f3483aaec8f")) + +const clientCertificatePEM = ` +-----BEGIN CERTIFICATE----- +MIIB7zCCAVigAwIBAgIQXBnBiWWDVW/cC8m5k5/pvDANBgkqhkiG9w0BAQsFADAS +MRAwDgYDVQQKEwdBY21lIENvMB4XDTE2MDgxNzIxNTIzMVoXDTE3MDgxNzIxNTIz +MVowEjEQMA4GA1UEChMHQWNtZSBDbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC +gYEAum+qhr3Pv5/y71yUYHhv6BPy0ZZvzdkybiI3zkH5yl0prOEn2mGi7oHLEMff +NFiVhuk9GeZcJ3NgyI14AvQdpJgJoxlwaTwlYmYqqyIjxXuFOE8uCXMyp70+m63K +hAfmDzr/d8WdQYUAirab7rCkPy1MTOZCPrtRyN1IVPQMjkcCAwEAAaNGMEQwDgYD +VR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAw +DwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOBgQBGq0Si+yhU+Fpn+GKU +8ZqyGJ7ysd4dfm92lam6512oFmyc9wnTN+RLKzZ8Aa1B0jLYw9KT+RBrjpW5LBeK +o0RIvFkTgxYEiKSBXCUNmAysEbEoVr4dzWFihAm/1oDGRY2CLLTYg5vbySK3KhIR +e/oCO8HJ/+rJnahJ05XX1Q7lNQ== +-----END CERTIFICATE-----` + +var clientKeyPEM = testingKey(` +-----BEGIN RSA TESTING KEY----- +MIICXQIBAAKBgQC6b6qGvc+/n/LvXJRgeG/oE/LRlm/N2TJuIjfOQfnKXSms4Sfa +YaLugcsQx980WJWG6T0Z5lwnc2DIjXgC9B2kmAmjGXBpPCViZiqrIiPFe4U4Ty4J +czKnvT6brcqEB+YPOv93xZ1BhQCKtpvusKQ/LUxM5kI+u1HI3UhU9AyORwIDAQAB +AoGAEJZ03q4uuMb7b26WSQsOMeDsftdatT747LGgs3pNRkMJvTb/O7/qJjxoG+Mc +qeSj0TAZXp+PXXc3ikCECAc+R8rVMfWdmp903XgO/qYtmZGCorxAHEmR80SrfMXv +PJnznLQWc8U9nphQErR+tTESg7xWEzmFcPKwnZd1xg8ERYkCQQDTGtrFczlB2b/Z +9TjNMqUlMnTLIk/a/rPE2fLLmAYhK5sHnJdvDURaH2mF4nso0EGtENnTsh6LATnY +dkrxXGm9AkEA4hXHG2q3MnhgK1Z5hjv+Fnqd+8bcbII9WW4flFs15EKoMgS1w/PJ +zbsySaSy5IVS8XeShmT9+3lrleed4sy+UwJBAJOOAbxhfXP5r4+5R6ql66jES75w +jUCVJzJA5ORJrn8g64u2eGK28z/LFQbv9wXgCwfc72R468BdawFSLa/m2EECQGbZ +rWiFla26IVXV0xcD98VWJsTBZMlgPnSOqoMdM1kSEd4fUmlAYI/dFzV1XYSkOmVr +FhdZnklmpVDeu27P4c0CQQCuCOup0FlJSBpWY1TTfun/KMBkBatMz0VMA3d7FKIU +csPezl677Yjo8u1r/KzeI6zLg87Z8E6r6ZWNc9wBSZK6 +-----END RSA TESTING KEY-----`) + +const clientECDSACertificatePEM = ` +-----BEGIN CERTIFICATE----- +MIIB/DCCAV4CCQCaMIRsJjXZFzAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw +EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0 +eSBMdGQwHhcNMTIxMTE0MTMyNTUzWhcNMjIxMTEyMTMyNTUzWjBBMQswCQYDVQQG +EwJBVTEMMAoGA1UECBMDTlNXMRAwDgYDVQQHEwdQeXJtb250MRIwEAYDVQQDEwlK +b2VsIFNpbmcwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACVjJF1FMBexFe01MNv +ja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd3kfDdq0Z9kUs +jLzYHQFMH3CQRnZIi4+DzEpcj0B22uCJ7B0rxE4wdihBsmKo+1vx+U56jb0JuK7q +ixgnTy5w/hOWusPTQBbNZU6sER7m8TAJBgcqhkjOPQQBA4GMADCBiAJCAOAUxGBg +C3JosDJdYUoCdFzCgbkWqD8pyDbHgf9stlvZcPE4O1BIKJTLCRpS8V3ujfK58PDa +2RU6+b0DeoeiIzXsAkIBo9SKeDUcSpoj0gq+KxAxnZxfvuiRs9oa9V2jI/Umi0Vw +jWVim34BmT0Y9hCaOGGbLlfk+syxis7iI6CH8OFnUes= +-----END CERTIFICATE-----` + +var clientECDSAKeyPEM = testingKey(` +-----BEGIN EC PARAMETERS----- +BgUrgQQAIw== +-----END EC PARAMETERS----- +-----BEGIN EC TESTING KEY----- +MIHcAgEBBEIBkJN9X4IqZIguiEVKMqeBUP5xtRsEv4HJEtOpOGLELwO53SD78Ew8 +k+wLWoqizS3NpQyMtrU8JFdWfj+C57UNkOugBwYFK4EEACOhgYkDgYYABACVjJF1 +FMBexFe01MNvja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd +3kfDdq0Z9kUsjLzYHQFMH3CQRnZIi4+DzEpcj0B22uCJ7B0rxE4wdihBsmKo+1vx ++U56jb0JuK7qixgnTy5w/hOWusPTQBbNZU6sER7m8Q== +-----END EC TESTING KEY-----`) + +const clientEd25519CertificatePEM = ` +-----BEGIN CERTIFICATE----- +MIIBLjCB4aADAgECAhAX0YGTviqMISAQJRXoNCNPMAUGAytlcDASMRAwDgYDVQQK +EwdBY21lIENvMB4XDTE5MDUxNjIxNTQyNloXDTIwMDUxNTIxNTQyNlowEjEQMA4G +A1UEChMHQWNtZSBDbzAqMAUGAytlcAMhAAvgtWC14nkwPb7jHuBQsQTIbcd4bGkv +xRStmmNveRKRo00wSzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH +AwIwDAYDVR0TAQH/BAIwADAWBgNVHREEDzANggtleGFtcGxlLmNvbTAFBgMrZXAD +QQD8GRcqlKUx+inILn9boF2KTjRAOdazENwZ/qAicbP1j6FYDc308YUkv+Y9FN/f +7Q7hF9gRomDQijcjKsJGqjoI +-----END CERTIFICATE-----` + +var clientEd25519KeyPEM = testingKey(` +-----BEGIN TESTING KEY----- +MC4CAQAwBQYDK2VwBCIEINifzf07d9qx3d44e0FSbV4mC/xQxT644RRbpgNpin7I +-----END TESTING KEY-----`) diff --git a/src/crypto/tls/handshake_unix_test.go b/src/crypto/tls/handshake_unix_test.go new file mode 100644 index 0000000..19fc698 --- /dev/null +++ b/src/crypto/tls/handshake_unix_test.go @@ -0,0 +1,19 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package tls + +import ( + "errors" + "syscall" +) + +func init() { + isConnRefused = func(err error) bool { + return errors.Is(err, syscall.ECONNREFUSED) + } +} diff --git a/src/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go new file mode 100644 index 0000000..c28a64f --- /dev/null +++ b/src/crypto/tls/key_agreement.go @@ -0,0 +1,357 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "crypto" + "crypto/md5" + "crypto/rsa" + "crypto/sha1" + "crypto/x509" + "errors" + "fmt" + "io" +) + +// a keyAgreement implements the client and server side of a TLS key agreement +// protocol by generating and processing key exchange messages. +type keyAgreement interface { + // On the server side, the first two methods are called in order. + + // In the case that the key agreement protocol doesn't use a + // ServerKeyExchange message, generateServerKeyExchange can return nil, + // nil. + generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error) + processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error) + + // On the client side, the next two methods are called in order. + + // This method may not be called if the server doesn't send a + // ServerKeyExchange message. + processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error + generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) +} + +var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") +var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") + +// rsaKeyAgreement implements the standard TLS key agreement where the client +// encrypts the pre-master secret to the server's public key. +type rsaKeyAgreement struct{} + +func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { + return nil, nil +} + +func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { + if len(ckx.ciphertext) < 2 { + return nil, errClientKeyExchange + } + ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) + if ciphertextLen != len(ckx.ciphertext)-2 { + return nil, errClientKeyExchange + } + ciphertext := ckx.ciphertext[2:] + + priv, ok := cert.PrivateKey.(crypto.Decrypter) + if !ok { + return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter") + } + // Perform constant time RSA PKCS #1 v1.5 decryption + preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48}) + if err != nil { + return nil, err + } + // We don't check the version number in the premaster secret. For one, + // by checking it, we would leak information about the validity of the + // encrypted pre-master secret. Secondly, it provides only a small + // benefit against a downgrade attack and some implementations send the + // wrong version anyway. See the discussion at the end of section + // 7.4.7.1 of RFC 4346. + return preMasterSecret, nil +} + +func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { + return errors.New("tls: unexpected ServerKeyExchange") +} + +func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { + preMasterSecret := make([]byte, 48) + preMasterSecret[0] = byte(clientHello.vers >> 8) + preMasterSecret[1] = byte(clientHello.vers) + _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) + if err != nil { + return nil, nil, err + } + + rsaKey, ok := cert.PublicKey.(*rsa.PublicKey) + if !ok { + return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite") + } + encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret) + if err != nil { + return nil, nil, err + } + ckx := new(clientKeyExchangeMsg) + ckx.ciphertext = make([]byte, len(encrypted)+2) + ckx.ciphertext[0] = byte(len(encrypted) >> 8) + ckx.ciphertext[1] = byte(len(encrypted)) + copy(ckx.ciphertext[2:], encrypted) + return preMasterSecret, ckx, nil +} + +// sha1Hash calculates a SHA1 hash over the given byte slices. +func sha1Hash(slices [][]byte) []byte { + hsha1 := sha1.New() + for _, slice := range slices { + hsha1.Write(slice) + } + return hsha1.Sum(nil) +} + +// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the +// concatenation of an MD5 and SHA1 hash. +func md5SHA1Hash(slices [][]byte) []byte { + md5sha1 := make([]byte, md5.Size+sha1.Size) + hmd5 := md5.New() + for _, slice := range slices { + hmd5.Write(slice) + } + copy(md5sha1, hmd5.Sum(nil)) + copy(md5sha1[md5.Size:], sha1Hash(slices)) + return md5sha1 +} + +// hashForServerKeyExchange hashes the given slices and returns their digest +// using the given hash function (for >= TLS 1.2) or using a default based on +// the sigType (for earlier TLS versions). For Ed25519 signatures, which don't +// do pre-hashing, it returns the concatenation of the slices. +func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte { + if sigType == signatureEd25519 { + var signed []byte + for _, slice := range slices { + signed = append(signed, slice...) + } + return signed + } + if version >= VersionTLS12 { + h := hashFunc.New() + for _, slice := range slices { + h.Write(slice) + } + digest := h.Sum(nil) + return digest + } + if sigType == signatureECDSA { + return sha1Hash(slices) + } + return md5SHA1Hash(slices) +} + +// ecdheKeyAgreement implements a TLS key agreement where the server +// generates an ephemeral EC public/private key pair and signs it. The +// pre-master secret is then calculated using ECDH. The signature may +// be ECDSA, Ed25519 or RSA. +type ecdheKeyAgreement struct { + version uint16 + isRSA bool + params ecdheParameters + + // ckx and preMasterSecret are generated in processServerKeyExchange + // and returned in generateClientKeyExchange. + ckx *clientKeyExchangeMsg + preMasterSecret []byte +} + +func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { + var curveID CurveID + for _, c := range clientHello.supportedCurves { + if config.supportsCurve(c) { + curveID = c + break + } + } + + if curveID == 0 { + return nil, errors.New("tls: no supported elliptic curves offered") + } + if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok { + return nil, errors.New("tls: CurvePreferences includes unsupported curve") + } + + params, err := generateECDHEParameters(config.rand(), curveID) + if err != nil { + return nil, err + } + ka.params = params + + // See RFC 4492, Section 5.4. + ecdhePublic := params.PublicKey() + serverECDHEParams := make([]byte, 1+2+1+len(ecdhePublic)) + serverECDHEParams[0] = 3 // named curve + serverECDHEParams[1] = byte(curveID >> 8) + serverECDHEParams[2] = byte(curveID) + serverECDHEParams[3] = byte(len(ecdhePublic)) + copy(serverECDHEParams[4:], ecdhePublic) + + priv, ok := cert.PrivateKey.(crypto.Signer) + if !ok { + return nil, fmt.Errorf("tls: certificate private key of type %T does not implement crypto.Signer", cert.PrivateKey) + } + + var signatureAlgorithm SignatureScheme + var sigType uint8 + var sigHash crypto.Hash + if ka.version >= VersionTLS12 { + signatureAlgorithm, err = selectSignatureScheme(ka.version, cert, clientHello.supportedSignatureAlgorithms) + if err != nil { + return nil, err + } + sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) + if err != nil { + return nil, err + } + } else { + sigType, sigHash, err = legacyTypeAndHashFromPublicKey(priv.Public()) + if err != nil { + return nil, err + } + } + if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { + return nil, errors.New("tls: certificate cannot be used with the selected cipher suite") + } + + signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, hello.random, serverECDHEParams) + + signOpts := crypto.SignerOpts(sigHash) + if sigType == signatureRSAPSS { + signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} + } + sig, err := priv.Sign(config.rand(), signed, signOpts) + if err != nil { + return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error()) + } + + skx := new(serverKeyExchangeMsg) + sigAndHashLen := 0 + if ka.version >= VersionTLS12 { + sigAndHashLen = 2 + } + skx.key = make([]byte, len(serverECDHEParams)+sigAndHashLen+2+len(sig)) + copy(skx.key, serverECDHEParams) + k := skx.key[len(serverECDHEParams):] + if ka.version >= VersionTLS12 { + k[0] = byte(signatureAlgorithm >> 8) + k[1] = byte(signatureAlgorithm) + k = k[2:] + } + k[0] = byte(len(sig) >> 8) + k[1] = byte(len(sig)) + copy(k[2:], sig) + + return skx, nil +} + +func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { + if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { + return nil, errClientKeyExchange + } + + preMasterSecret := ka.params.SharedKey(ckx.ciphertext[1:]) + if preMasterSecret == nil { + return nil, errClientKeyExchange + } + + return preMasterSecret, nil +} + +func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { + if len(skx.key) < 4 { + return errServerKeyExchange + } + if skx.key[0] != 3 { // named curve + return errors.New("tls: server selected unsupported curve") + } + curveID := CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) + + publicLen := int(skx.key[3]) + if publicLen+4 > len(skx.key) { + return errServerKeyExchange + } + serverECDHEParams := skx.key[:4+publicLen] + publicKey := serverECDHEParams[4:] + + sig := skx.key[4+publicLen:] + if len(sig) < 2 { + return errServerKeyExchange + } + + if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok { + return errors.New("tls: server selected unsupported curve") + } + + params, err := generateECDHEParameters(config.rand(), curveID) + if err != nil { + return err + } + ka.params = params + + ka.preMasterSecret = params.SharedKey(publicKey) + if ka.preMasterSecret == nil { + return errServerKeyExchange + } + + ourPublicKey := params.PublicKey() + ka.ckx = new(clientKeyExchangeMsg) + ka.ckx.ciphertext = make([]byte, 1+len(ourPublicKey)) + ka.ckx.ciphertext[0] = byte(len(ourPublicKey)) + copy(ka.ckx.ciphertext[1:], ourPublicKey) + + var sigType uint8 + var sigHash crypto.Hash + if ka.version >= VersionTLS12 { + signatureAlgorithm := SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1]) + sig = sig[2:] + if len(sig) < 2 { + return errServerKeyExchange + } + + if !isSupportedSignatureAlgorithm(signatureAlgorithm, clientHello.supportedSignatureAlgorithms) { + return errors.New("tls: certificate used with invalid signature algorithm") + } + sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) + if err != nil { + return err + } + } else { + sigType, sigHash, err = legacyTypeAndHashFromPublicKey(cert.PublicKey) + if err != nil { + return err + } + } + if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { + return errServerKeyExchange + } + + sigLen := int(sig[0])<<8 | int(sig[1]) + if sigLen+2 != len(sig) { + return errServerKeyExchange + } + sig = sig[2:] + + signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, serverHello.random, serverECDHEParams) + if err := verifyHandshakeSignature(sigType, cert.PublicKey, sigHash, signed, sig); err != nil { + return errors.New("tls: invalid signature by the server certificate: " + err.Error()) + } + return nil +} + +func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { + if ka.ckx == nil { + return nil, nil, errors.New("tls: missing ServerKeyExchange message") + } + + return ka.preMasterSecret, ka.ckx, nil +} diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go new file mode 100644 index 0000000..3140169 --- /dev/null +++ b/src/crypto/tls/key_schedule.go @@ -0,0 +1,199 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "crypto/elliptic" + "crypto/hmac" + "errors" + "hash" + "io" + "math/big" + + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/curve25519" + "golang.org/x/crypto/hkdf" +) + +// This file contains the functions necessary to compute the TLS 1.3 key +// schedule. See RFC 8446, Section 7. + +const ( + resumptionBinderLabel = "res binder" + clientHandshakeTrafficLabel = "c hs traffic" + serverHandshakeTrafficLabel = "s hs traffic" + clientApplicationTrafficLabel = "c ap traffic" + serverApplicationTrafficLabel = "s ap traffic" + exporterLabel = "exp master" + resumptionLabel = "res master" + trafficUpdateLabel = "traffic upd" +) + +// expandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. +func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte { + var hkdfLabel cryptobyte.Builder + hkdfLabel.AddUint16(uint16(length)) + hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes([]byte("tls13 ")) + b.AddBytes([]byte(label)) + }) + hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(context) + }) + out := make([]byte, length) + n, err := hkdf.Expand(c.hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out) + if err != nil || n != length { + panic("tls: HKDF-Expand-Label invocation failed unexpectedly") + } + return out +} + +// deriveSecret implements Derive-Secret from RFC 8446, Section 7.1. +func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript hash.Hash) []byte { + if transcript == nil { + transcript = c.hash.New() + } + return c.expandLabel(secret, label, transcript.Sum(nil), c.hash.Size()) +} + +// extract implements HKDF-Extract with the cipher suite hash. +func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte { + if newSecret == nil { + newSecret = make([]byte, c.hash.Size()) + } + return hkdf.Extract(c.hash.New, newSecret, currentSecret) +} + +// nextTrafficSecret generates the next traffic secret, given the current one, +// according to RFC 8446, Section 7.2. +func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte { + return c.expandLabel(trafficSecret, trafficUpdateLabel, nil, c.hash.Size()) +} + +// trafficKey generates traffic keys according to RFC 8446, Section 7.3. +func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) { + key = c.expandLabel(trafficSecret, "key", nil, c.keyLen) + iv = c.expandLabel(trafficSecret, "iv", nil, aeadNonceLength) + return +} + +// finishedHash generates the Finished verify_data or PskBinderEntry according +// to RFC 8446, Section 4.4.4. See sections 4.4 and 4.2.11.2 for the baseKey +// selection. +func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte { + finishedKey := c.expandLabel(baseKey, "finished", nil, c.hash.Size()) + verifyData := hmac.New(c.hash.New, finishedKey) + verifyData.Write(transcript.Sum(nil)) + return verifyData.Sum(nil) +} + +// exportKeyingMaterial implements RFC5705 exporters for TLS 1.3 according to +// RFC 8446, Section 7.5. +func (c *cipherSuiteTLS13) exportKeyingMaterial(masterSecret []byte, transcript hash.Hash) func(string, []byte, int) ([]byte, error) { + expMasterSecret := c.deriveSecret(masterSecret, exporterLabel, transcript) + return func(label string, context []byte, length int) ([]byte, error) { + secret := c.deriveSecret(expMasterSecret, label, nil) + h := c.hash.New() + h.Write(context) + return c.expandLabel(secret, "exporter", h.Sum(nil), length), nil + } +} + +// ecdheParameters implements Diffie-Hellman with either NIST curves or X25519, +// according to RFC 8446, Section 4.2.8.2. +type ecdheParameters interface { + CurveID() CurveID + PublicKey() []byte + SharedKey(peerPublicKey []byte) []byte +} + +func generateECDHEParameters(rand io.Reader, curveID CurveID) (ecdheParameters, error) { + if curveID == X25519 { + privateKey := make([]byte, curve25519.ScalarSize) + if _, err := io.ReadFull(rand, privateKey); err != nil { + return nil, err + } + publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint) + if err != nil { + return nil, err + } + return &x25519Parameters{privateKey: privateKey, publicKey: publicKey}, nil + } + + curve, ok := curveForCurveID(curveID) + if !ok { + return nil, errors.New("tls: internal error: unsupported curve") + } + + p := &nistParameters{curveID: curveID} + var err error + p.privateKey, p.x, p.y, err = elliptic.GenerateKey(curve, rand) + if err != nil { + return nil, err + } + return p, nil +} + +func curveForCurveID(id CurveID) (elliptic.Curve, bool) { + switch id { + case CurveP256: + return elliptic.P256(), true + case CurveP384: + return elliptic.P384(), true + case CurveP521: + return elliptic.P521(), true + default: + return nil, false + } +} + +type nistParameters struct { + privateKey []byte + x, y *big.Int // public key + curveID CurveID +} + +func (p *nistParameters) CurveID() CurveID { + return p.curveID +} + +func (p *nistParameters) PublicKey() []byte { + curve, _ := curveForCurveID(p.curveID) + return elliptic.Marshal(curve, p.x, p.y) +} + +func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte { + curve, _ := curveForCurveID(p.curveID) + // Unmarshal also checks whether the given point is on the curve. + x, y := elliptic.Unmarshal(curve, peerPublicKey) + if x == nil { + return nil + } + + xShared, _ := curve.ScalarMult(x, y, p.privateKey) + sharedKey := make([]byte, (curve.Params().BitSize+7)/8) + return xShared.FillBytes(sharedKey) +} + +type x25519Parameters struct { + privateKey []byte + publicKey []byte +} + +func (p *x25519Parameters) CurveID() CurveID { + return X25519 +} + +func (p *x25519Parameters) PublicKey() []byte { + return p.publicKey[:] +} + +func (p *x25519Parameters) SharedKey(peerPublicKey []byte) []byte { + sharedKey, err := curve25519.X25519(p.privateKey, peerPublicKey) + if err != nil { + return nil + } + return sharedKey +} diff --git a/src/crypto/tls/key_schedule_test.go b/src/crypto/tls/key_schedule_test.go new file mode 100644 index 0000000..79ff6a6 --- /dev/null +++ b/src/crypto/tls/key_schedule_test.go @@ -0,0 +1,175 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "encoding/hex" + "hash" + "strings" + "testing" + "unicode" +) + +// This file contains tests derived from draft-ietf-tls-tls13-vectors-07. + +func parseVector(v string) []byte { + v = strings.Map(func(c rune) rune { + if unicode.IsSpace(c) { + return -1 + } + return c + }, v) + parts := strings.Split(v, ":") + v = parts[len(parts)-1] + res, err := hex.DecodeString(v) + if err != nil { + panic(err) + } + return res +} + +func TestDeriveSecret(t *testing.T) { + chTranscript := cipherSuitesTLS13[0].hash.New() + chTranscript.Write(parseVector(` + payload (512 octets): 01 00 01 fc 03 03 1b c3 ce b6 bb e3 9c ff + 93 83 55 b5 a5 0a db 6d b2 1b 7a 6a f6 49 d7 b4 bc 41 9d 78 76 + 48 7d 95 00 00 06 13 01 13 03 13 02 01 00 01 cd 00 00 00 0b 00 + 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00 12 + 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 33 00 + 26 00 24 00 1d 00 20 e4 ff b6 8a c0 5f 8d 96 c9 9d a2 66 98 34 + 6c 6b e1 64 82 ba dd da fe 05 1a 66 b4 f1 8d 66 8f 0b 00 2a 00 + 00 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03 02 + 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06 02 + 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01 00 15 00 57 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 29 00 dd 00 b8 00 b2 2c 03 5d 82 93 59 ee 5f f7 af 4e c9 00 + 00 00 00 26 2a 64 94 dc 48 6d 2c 8a 34 cb 33 fa 90 bf 1b 00 70 + ad 3c 49 88 83 c9 36 7c 09 a2 be 78 5a bc 55 cd 22 60 97 a3 a9 + 82 11 72 83 f8 2a 03 a1 43 ef d3 ff 5d d3 6d 64 e8 61 be 7f d6 + 1d 28 27 db 27 9c ce 14 50 77 d4 54 a3 66 4d 4e 6d a4 d2 9e e0 + 37 25 a6 a4 da fc d0 fc 67 d2 ae a7 05 29 51 3e 3d a2 67 7f a5 + 90 6c 5b 3f 7d 8f 92 f2 28 bd a4 0d da 72 14 70 f9 fb f2 97 b5 + ae a6 17 64 6f ac 5c 03 27 2e 97 07 27 c6 21 a7 91 41 ef 5f 7d + e6 50 5e 5b fb c3 88 e9 33 43 69 40 93 93 4a e4 d3 57 fa d6 aa + cb 00 21 20 3a dd 4f b2 d8 fd f8 22 a0 ca 3c f7 67 8e f5 e8 8d + ae 99 01 41 c5 92 4d 57 bb 6f a3 1b 9e 5f 9d`)) + + type args struct { + secret []byte + label string + transcript hash.Hash + } + tests := []struct { + name string + args args + want []byte + }{ + { + `derive secret for handshake "tls13 derived"`, + args{ + parseVector(`PRK (32 octets): 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c e2 + 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a`), + "derived", + nil, + }, + parseVector(`expanded (32 octets): 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba + b6 97 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba`), + }, + { + `derive secret "tls13 c e traffic"`, + args{ + parseVector(`PRK (32 octets): 9b 21 88 e9 b2 fc 6d 64 d7 1d c3 29 90 0e 20 bb + 41 91 50 00 f6 78 aa 83 9c bb 79 7c b7 d8 33 2c`), + "c e traffic", + chTranscript, + }, + parseVector(`expanded (32 octets): 3f bb e6 a6 0d eb 66 c3 0a 32 79 5a ba 0e + ff 7e aa 10 10 55 86 e7 be 5c 09 67 8d 63 b6 ca ab 62`), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := cipherSuitesTLS13[0] + if got := c.deriveSecret(tt.args.secret, tt.args.label, tt.args.transcript); !bytes.Equal(got, tt.want) { + t.Errorf("cipherSuiteTLS13.deriveSecret() = % x, want % x", got, tt.want) + } + }) + } +} + +func TestTrafficKey(t *testing.T) { + trafficSecret := parseVector( + `PRK (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4 + e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38`) + wantKey := parseVector( + `key expanded (16 octets): 3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e + e4 03 bc`) + wantIV := parseVector( + `iv expanded (12 octets): 5d 31 3e b2 67 12 76 ee 13 00 0b 30`) + + c := cipherSuitesTLS13[0] + gotKey, gotIV := c.trafficKey(trafficSecret) + if !bytes.Equal(gotKey, wantKey) { + t.Errorf("cipherSuiteTLS13.trafficKey() gotKey = % x, want % x", gotKey, wantKey) + } + if !bytes.Equal(gotIV, wantIV) { + t.Errorf("cipherSuiteTLS13.trafficKey() gotIV = % x, want % x", gotIV, wantIV) + } +} + +func TestExtract(t *testing.T) { + type args struct { + newSecret []byte + currentSecret []byte + } + tests := []struct { + name string + args args + want []byte + }{ + { + `extract secret "early"`, + args{ + nil, + nil, + }, + parseVector(`secret (32 octets): 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c + e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a`), + }, + { + `extract secret "master"`, + args{ + nil, + parseVector(`salt (32 octets): 43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25 90 b5 + 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4`), + }, + parseVector(`secret (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a + 47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19`), + }, + { + `extract secret "handshake"`, + args{ + parseVector(`IKM (32 octets): 8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d + 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d`), + parseVector(`salt (32 octets): 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba b6 97 + 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba`), + }, + parseVector(`secret (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b + 01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac`), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := cipherSuitesTLS13[0] + if got := c.extract(tt.args.newSecret, tt.args.currentSecret); !bytes.Equal(got, tt.want) { + t.Errorf("cipherSuiteTLS13.extract() = % x, want % x", got, tt.want) + } + }) + } +} diff --git a/src/crypto/tls/link_test.go b/src/crypto/tls/link_test.go new file mode 100644 index 0000000..8c392ff --- /dev/null +++ b/src/crypto/tls/link_test.go @@ -0,0 +1,107 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "internal/testenv" + "os" + "os/exec" + "path/filepath" + "testing" +) + +// Tests that the linker is able to remove references to the Client or Server if unused. +func TestLinkerGC(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + t.Parallel() + goBin := testenv.GoToolPath(t) + testenv.MustHaveGoBuild(t) + + tests := []struct { + name string + program string + want []string + bad []string + }{ + { + name: "empty_import", + program: `package main +import _ "crypto/tls" +func main() {} +`, + bad: []string{ + "tls.(*Conn)", + "type.crypto/tls.clientHandshakeState", + "type.crypto/tls.serverHandshakeState", + }, + }, + { + name: "client_and_server", + program: `package main +import "crypto/tls" +func main() { + tls.Dial("", "", nil) + tls.Server(nil, nil) +} +`, + want: []string{ + "crypto/tls.(*Conn).clientHandshake", + "crypto/tls.(*Conn).serverHandshake", + }, + }, + { + name: "only_client", + program: `package main +import "crypto/tls" +func main() { tls.Dial("", "", nil) } +`, + want: []string{ + "crypto/tls.(*Conn).clientHandshake", + }, + bad: []string{ + "crypto/tls.(*Conn).serverHandshake", + }, + }, + // TODO: add only_server like func main() { tls.Server(nil, nil) } + // That currently brings in the client via Conn.handleRenegotiation. + + } + tmpDir := t.TempDir() + goFile := filepath.Join(tmpDir, "x.go") + exeFile := filepath.Join(tmpDir, "x.exe") + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := os.WriteFile(goFile, []byte(tt.program), 0644); err != nil { + t.Fatal(err) + } + os.Remove(exeFile) + cmd := exec.Command(goBin, "build", "-o", "x.exe", "x.go") + cmd.Dir = tmpDir + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("compile: %v, %s", err, out) + } + + cmd = exec.Command(goBin, "tool", "nm", "x.exe") + cmd.Dir = tmpDir + nm, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("nm: %v, %s", err, nm) + } + for _, sym := range tt.want { + if !bytes.Contains(nm, []byte(sym)) { + t.Errorf("expected symbol %q not found", sym) + } + } + for _, sym := range tt.bad { + if bytes.Contains(nm, []byte(sym)) { + t.Errorf("unexpected symbol %q found", sym) + } + } + }) + } +} diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go new file mode 100644 index 0000000..13bfa00 --- /dev/null +++ b/src/crypto/tls/prf.go @@ -0,0 +1,283 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "crypto" + "crypto/hmac" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "errors" + "fmt" + "hash" +) + +// Split a premaster secret in two as specified in RFC 4346, Section 5. +func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { + s1 = secret[0 : (len(secret)+1)/2] + s2 = secret[len(secret)/2:] + return +} + +// pHash implements the P_hash function, as defined in RFC 4346, Section 5. +func pHash(result, secret, seed []byte, hash func() hash.Hash) { + h := hmac.New(hash, secret) + h.Write(seed) + a := h.Sum(nil) + + j := 0 + for j < len(result) { + h.Reset() + h.Write(a) + h.Write(seed) + b := h.Sum(nil) + copy(result[j:], b) + j += len(b) + + h.Reset() + h.Write(a) + a = h.Sum(nil) + } +} + +// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. +func prf10(result, secret, label, seed []byte) { + hashSHA1 := sha1.New + hashMD5 := md5.New + + labelAndSeed := make([]byte, len(label)+len(seed)) + copy(labelAndSeed, label) + copy(labelAndSeed[len(label):], seed) + + s1, s2 := splitPreMasterSecret(secret) + pHash(result, s1, labelAndSeed, hashMD5) + result2 := make([]byte, len(result)) + pHash(result2, s2, labelAndSeed, hashSHA1) + + for i, b := range result2 { + result[i] ^= b + } +} + +// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. +func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { + return func(result, secret, label, seed []byte) { + labelAndSeed := make([]byte, len(label)+len(seed)) + copy(labelAndSeed, label) + copy(labelAndSeed[len(label):], seed) + + pHash(result, secret, labelAndSeed, hashFunc) + } +} + +const ( + masterSecretLength = 48 // Length of a master secret in TLS 1.1. + finishedVerifyLength = 12 // Length of verify_data in a Finished message. +) + +var masterSecretLabel = []byte("master secret") +var keyExpansionLabel = []byte("key expansion") +var clientFinishedLabel = []byte("client finished") +var serverFinishedLabel = []byte("server finished") + +func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { + switch version { + case VersionTLS10, VersionTLS11: + return prf10, crypto.Hash(0) + case VersionTLS12: + if suite.flags&suiteSHA384 != 0 { + return prf12(sha512.New384), crypto.SHA384 + } + return prf12(sha256.New), crypto.SHA256 + default: + panic("unknown version") + } +} + +func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { + prf, _ := prfAndHashForVersion(version, suite) + return prf +} + +// masterFromPreMasterSecret generates the master secret from the pre-master +// secret. See RFC 5246, Section 8.1. +func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { + seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) + seed = append(seed, clientRandom...) + seed = append(seed, serverRandom...) + + masterSecret := make([]byte, masterSecretLength) + prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) + return masterSecret +} + +// keysFromMasterSecret generates the connection keys from the master +// secret, given the lengths of the MAC key, cipher key and IV, as defined in +// RFC 2246, Section 6.3. +func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { + seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) + seed = append(seed, serverRandom...) + seed = append(seed, clientRandom...) + + n := 2*macLen + 2*keyLen + 2*ivLen + keyMaterial := make([]byte, n) + prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) + clientMAC = keyMaterial[:macLen] + keyMaterial = keyMaterial[macLen:] + serverMAC = keyMaterial[:macLen] + keyMaterial = keyMaterial[macLen:] + clientKey = keyMaterial[:keyLen] + keyMaterial = keyMaterial[keyLen:] + serverKey = keyMaterial[:keyLen] + keyMaterial = keyMaterial[keyLen:] + clientIV = keyMaterial[:ivLen] + keyMaterial = keyMaterial[ivLen:] + serverIV = keyMaterial[:ivLen] + return +} + +func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { + var buffer []byte + if version >= VersionTLS12 { + buffer = []byte{} + } + + prf, hash := prfAndHashForVersion(version, cipherSuite) + if hash != 0 { + return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf} + } + + return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} +} + +// A finishedHash calculates the hash of a set of handshake messages suitable +// for including in a Finished message. +type finishedHash struct { + client hash.Hash + server hash.Hash + + // Prior to TLS 1.2, an additional MD5 hash is required. + clientMD5 hash.Hash + serverMD5 hash.Hash + + // In TLS 1.2, a full buffer is sadly required. + buffer []byte + + version uint16 + prf func(result, secret, label, seed []byte) +} + +func (h *finishedHash) Write(msg []byte) (n int, err error) { + h.client.Write(msg) + h.server.Write(msg) + + if h.version < VersionTLS12 { + h.clientMD5.Write(msg) + h.serverMD5.Write(msg) + } + + if h.buffer != nil { + h.buffer = append(h.buffer, msg...) + } + + return len(msg), nil +} + +func (h finishedHash) Sum() []byte { + if h.version >= VersionTLS12 { + return h.client.Sum(nil) + } + + out := make([]byte, 0, md5.Size+sha1.Size) + out = h.clientMD5.Sum(out) + return h.client.Sum(out) +} + +// clientSum returns the contents of the verify_data member of a client's +// Finished message. +func (h finishedHash) clientSum(masterSecret []byte) []byte { + out := make([]byte, finishedVerifyLength) + h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) + return out +} + +// serverSum returns the contents of the verify_data member of a server's +// Finished message. +func (h finishedHash) serverSum(masterSecret []byte) []byte { + out := make([]byte, finishedVerifyLength) + h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) + return out +} + +// hashForClientCertificate returns the handshake messages so far, pre-hashed if +// necessary, suitable for signing by a TLS client certificate. +func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash, masterSecret []byte) []byte { + if (h.version >= VersionTLS12 || sigType == signatureEd25519) && h.buffer == nil { + panic("tls: handshake hash for a client certificate requested after discarding the handshake buffer") + } + + if sigType == signatureEd25519 { + return h.buffer + } + + if h.version >= VersionTLS12 { + hash := hashAlg.New() + hash.Write(h.buffer) + return hash.Sum(nil) + } + + if sigType == signatureECDSA { + return h.server.Sum(nil) + } + + return h.Sum() +} + +// discardHandshakeBuffer is called when there is no more need to +// buffer the entirety of the handshake messages. +func (h *finishedHash) discardHandshakeBuffer() { + h.buffer = nil +} + +// noExportedKeyingMaterial is used as a value of +// ConnectionState.ekm when renegotiation is enabled and thus +// we wish to fail all key-material export requests. +func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) { + return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled") +} + +// ekmFromMasterSecret generates exported keying material as defined in RFC 5705. +func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) { + return func(label string, context []byte, length int) ([]byte, error) { + switch label { + case "client finished", "server finished", "master secret", "key expansion": + // These values are reserved and may not be used. + return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label) + } + + seedLen := len(serverRandom) + len(clientRandom) + if context != nil { + seedLen += 2 + len(context) + } + seed := make([]byte, 0, seedLen) + + seed = append(seed, clientRandom...) + seed = append(seed, serverRandom...) + + if context != nil { + if len(context) >= 1<<16 { + return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long") + } + seed = append(seed, byte(len(context)>>8), byte(len(context))) + seed = append(seed, context...) + } + + keyMaterial := make([]byte, length) + prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed) + return keyMaterial, nil + } +} diff --git a/src/crypto/tls/prf_test.go b/src/crypto/tls/prf_test.go new file mode 100644 index 0000000..8233985 --- /dev/null +++ b/src/crypto/tls/prf_test.go @@ -0,0 +1,140 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "encoding/hex" + "testing" +) + +type testSplitPreMasterSecretTest struct { + in, out1, out2 string +} + +var testSplitPreMasterSecretTests = []testSplitPreMasterSecretTest{ + {"", "", ""}, + {"00", "00", "00"}, + {"0011", "00", "11"}, + {"001122", "0011", "1122"}, + {"00112233", "0011", "2233"}, +} + +func TestSplitPreMasterSecret(t *testing.T) { + for i, test := range testSplitPreMasterSecretTests { + in, _ := hex.DecodeString(test.in) + out1, out2 := splitPreMasterSecret(in) + s1 := hex.EncodeToString(out1) + s2 := hex.EncodeToString(out2) + if s1 != test.out1 || s2 != test.out2 { + t.Errorf("#%d: got: (%s, %s) want: (%s, %s)", i, s1, s2, test.out1, test.out2) + } + } +} + +type testKeysFromTest struct { + version uint16 + suite *cipherSuite + preMasterSecret string + clientRandom, serverRandom string + masterSecret string + clientMAC, serverMAC string + clientKey, serverKey string + macLen, keyLen int + contextKeyingMaterial, noContextKeyingMaterial string +} + +func TestKeysFromPreMasterSecret(t *testing.T) { + for i, test := range testKeysFromTests { + in, _ := hex.DecodeString(test.preMasterSecret) + clientRandom, _ := hex.DecodeString(test.clientRandom) + serverRandom, _ := hex.DecodeString(test.serverRandom) + + masterSecret := masterFromPreMasterSecret(test.version, test.suite, in, clientRandom, serverRandom) + if s := hex.EncodeToString(masterSecret); s != test.masterSecret { + t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret) + continue + } + + clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0) + clientMACString := hex.EncodeToString(clientMAC) + serverMACString := hex.EncodeToString(serverMAC) + clientKeyString := hex.EncodeToString(clientKey) + serverKeyString := hex.EncodeToString(serverKey) + if clientMACString != test.clientMAC || + serverMACString != test.serverMAC || + clientKeyString != test.clientKey || + serverKeyString != test.serverKey { + t.Errorf("#%d: got: (%s, %s, %s, %s) want: (%s, %s, %s, %s)", i, clientMACString, serverMACString, clientKeyString, serverKeyString, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey) + } + + ekm := ekmFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom) + contextKeyingMaterial, err := ekm("label", []byte("context"), 32) + if err != nil { + t.Fatalf("ekmFromMasterSecret failed: %v", err) + } + + noContextKeyingMaterial, err := ekm("label", nil, 32) + if err != nil { + t.Fatalf("ekmFromMasterSecret failed: %v", err) + } + + if hex.EncodeToString(contextKeyingMaterial) != test.contextKeyingMaterial || + hex.EncodeToString(noContextKeyingMaterial) != test.noContextKeyingMaterial { + t.Errorf("#%d: got keying material: (%s, %s) want: (%s, %s)", i, contextKeyingMaterial, noContextKeyingMaterial, test.contextKeyingMaterial, test.noContextKeyingMaterial) + } + } +} + +// These test vectors were generated from GnuTLS using `gnutls-cli --insecure -d 9 ` +var testKeysFromTests = []testKeysFromTest{ + { + VersionTLS10, + cipherSuiteByID(TLS_RSA_WITH_RC4_128_SHA), + "0302cac83ad4b1db3b9ab49ad05957de2a504a634a386fc600889321e1a971f57479466830ac3e6f468e87f5385fa0c5", + "4ae66303755184a3917fcb44880605fcc53baa01912b22ed94473fc69cebd558", + "4ae663020ec16e6bb5130be918cfcafd4d765979a3136a5d50c593446e4e44db", + "3d851bab6e5556e959a16bc36d66cfae32f672bfa9ecdef6096cbb1b23472df1da63dbbd9827606413221d149ed08ceb", + "805aaa19b3d2c0a0759a4b6c9959890e08480119", + "2d22f9fe519c075c16448305ceee209fc24ad109", + "d50b5771244f850cd8117a9ccafe2cf1", + "e076e33206b30507a85c32855acd0919", + 20, + 16, + "4d1bb6fc278c37d27aa6e2a13c2e079095d143272c2aa939da33d88c1c0cec22", + "93fba89599b6321ae538e27c6548ceb8b46821864318f5190d64a375e5d69d41", + }, + { + VersionTLS10, + cipherSuiteByID(TLS_RSA_WITH_RC4_128_SHA), + "03023f7527316bc12cbcd69e4b9e8275d62c028f27e65c745cfcddc7ce01bd3570a111378b63848127f1c36e5f9e4890", + "4ae66364b5ea56b20ce4e25555aed2d7e67f42788dd03f3fee4adae0459ab106", + "4ae66363ab815cbf6a248b87d6b556184e945e9b97fbdf247858b0bdafacfa1c", + "7d64be7c80c59b740200b4b9c26d0baaa1c5ae56705acbcf2307fe62beb4728c19392c83f20483801cce022c77645460", + "97742ed60a0554ca13f04f97ee193177b971e3b0", + "37068751700400e03a8477a5c7eec0813ab9e0dc", + "207cddbc600d2a200abac6502053ee5c", + "df3f94f6e1eacc753b815fe16055cd43", + 20, + 16, + "2c9f8961a72b97cbe76553b5f954caf8294fc6360ef995ac1256fe9516d0ce7f", + "274f19c10291d188857ad8878e2119f5aa437d4da556601cf1337aff23154016", + }, + { + VersionTLS10, + cipherSuiteByID(TLS_RSA_WITH_RC4_128_SHA), + "832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1", + "4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e", + "4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e", + "1aff2e7a2c4279d0126f57a65a77a8d9d0087cf2733366699bec27eb53d5740705a8574bb1acc2abbe90e44f0dd28d6c", + "3c7647c93c1379a31a609542aa44e7f117a70085", + "0d73102994be74a575a3ead8532590ca32a526d4", + "ac7581b0b6c10d85bbd905ffbf36c65e", + "ff07edde49682b45466bd2e39464b306", + 20, + 16, + "678b0d43f607de35241dc7e9d1a7388a52c35033a1a0336d4d740060a6638fe2", + "f3b4ac743f015ef21d79978297a53da3e579ee047133f38c234d829c0f907dab", + }, +} diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA new file mode 100644 index 0000000..c7fa530 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA @@ -0,0 +1,134 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 92 4c b7 e6 07 |....Y...U...L...| +00000010 09 b4 4a 47 6a 29 c7 79 18 0d 43 37 86 26 21 5a |..JGj).y..C7.&!Z| +00000020 25 35 db 5f ae d0 20 0d 85 67 f7 20 75 e5 cb 25 |%5._.. ..g. u..%| +00000030 4b 5d 95 87 78 00 fc 3f 78 26 e8 77 b5 0d d4 0e |K]..x..?x&.w....| +00000040 54 06 66 b4 14 dc 6b db f2 af f3 2a c0 09 00 00 |T.f...k....*....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 d7 b5 |*............ ..| +00000280 51 8e b5 01 4f 02 2f 43 11 2b de 94 7d 82 e6 49 |Q...O./C.+..}..I| +00000290 1b a6 ee a0 7f 12 35 a2 3a 62 46 ce 07 25 00 8b |......5.:bF..%..| +000002a0 30 81 88 02 42 00 83 45 db 03 db b9 74 ce 77 35 |0...B..E....t.w5| +000002b0 1b e5 76 18 dc 3a d3 ee 32 18 f3 16 a6 c3 62 be |..v..:..2.....b.| +000002c0 46 47 40 80 2d a0 08 c5 1e 5a 4a 42 69 8c ee e5 |FG@.-....ZJBi...| +000002d0 70 b5 71 30 2f 54 32 54 5f 5b 26 62 e1 81 52 9e |p.q0/T2T_[&b..R.| +000002e0 49 70 d4 81 e4 76 f1 02 42 01 70 f6 87 84 bb 58 |Ip...v..B.p....X| +000002f0 5d e4 a1 72 87 d5 35 53 99 9c 3f 30 2b 80 7e c9 |]..r..5S..?0+.~.| +00000300 79 eb d8 97 3c 82 ff 37 a5 8d 36 bc 27 c1 51 58 |y...<..7..6.'.QX| +00000310 e6 2a 48 05 bf 9b a4 a5 b1 7f 77 b8 d9 3e 37 c6 |.*H.......w..>7.| +00000320 67 ad ef 8c 72 ea f6 ba bb af 00 16 03 01 00 0a |g...r...........| +00000330 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........| +00000340 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 01 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| +00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 91 0f 00 |...._X.;t.......| +00000240 00 8d 00 8b 30 81 88 02 42 01 f0 c3 b2 6e e2 a3 |....0...B....n..| +00000250 cd 76 02 7a d5 b5 66 fa b6 66 4e 4b a0 17 d6 bd |.v.z..f..fNK....| +00000260 ec f6 8c 1f f9 b4 32 18 a9 ba 66 a8 67 a4 fa c8 |......2...f.g...| +00000270 f7 73 5f 22 fb f2 22 e2 4d a1 f6 30 a2 55 76 51 |.s_"..".M..0.UvQ| +00000280 b7 61 7d 13 68 0a 89 9d 34 31 46 02 42 01 fa 8b |.a}.h...41F.B...| +00000290 61 f6 91 8e 88 ca 84 e6 33 e0 da 92 7e ee 21 1c |a.......3...~.!.| +000002a0 df 47 c2 5d 07 d8 ae 1b 04 58 f9 50 16 13 74 ea |.G.].....X.P..t.| +000002b0 04 cc 18 2d 2b 9a 08 89 24 e8 b8 01 bb c6 84 6c |...-+...$......l| +000002c0 e6 9a c6 8a 44 74 1c 3a 79 0c e9 3c 11 ba 1b 14 |....Dt.:y..<....| +000002d0 03 01 00 01 01 16 03 01 00 30 1d 4b df 00 de 1c |.........0.K....| +000002e0 b5 30 7b ea 64 a0 09 89 8c c5 be fc 9b 07 7e 45 |.0{.d.........~E| +000002f0 27 00 e7 78 da 3e a3 04 97 87 b0 c2 17 32 01 91 |'..x.>.......2..| +00000300 6e 66 7b dd 9e 28 bc cc 66 65 |nf{..(..fe| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 51 68 ca 97 63 |..........0Qh..c| +00000010 c6 c0 24 1c 87 20 70 ac f7 47 16 45 44 17 cc 92 |..$.. p..G.ED...| +00000020 b3 6d 8b fa d1 3c b8 10 d7 da e4 a7 35 3c a2 d0 |.m...<......5<..| +00000030 da 4b 50 e4 89 94 4b bc 20 6b e3 |.KP...K. k.| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 fc fa 90 90 d0 51 0d 35 0f 6a 6d |.... .....Q.5.jm| +00000010 c2 32 ec 92 46 9f d7 e9 66 37 02 2a f6 c6 2e e2 |.2..F...f7.*....| +00000020 13 aa fa fa d3 17 03 01 00 20 45 a9 36 19 7d a8 |......... E.6.}.| +00000030 44 4c 8b aa 4e 47 c8 79 0c 97 a5 20 fa 6f 1f f7 |DL..NG.y... .o..| +00000040 d3 bc d7 6d c2 67 23 c8 d6 05 15 03 01 00 20 f1 |...m.g#....... .| +00000050 f1 ed f9 fc c2 f6 61 c8 42 9d c9 8a b0 d0 de d3 |......a.B.......| +00000060 42 c7 04 64 eb 9e eb 58 3b c3 7d 0d 4d 16 d4 |B..d...X;.}.M..| diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA new file mode 100644 index 0000000..81e5191 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA @@ -0,0 +1,138 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 ca 72 6a a1 69 |....Y...U...rj.i| +00000010 18 a4 f8 76 4a c3 5c e8 d5 c1 fb 06 c6 9a 14 67 |...vJ.\........g| +00000020 ce e4 f6 52 67 ab 64 48 28 5a 63 20 55 ea ff 87 |...Rg.dH(Zc U...| +00000030 5a 78 5c cb 21 af 83 a5 ed 1b d3 2c 39 81 e5 ca |Zx\.!......,9...| +00000040 63 d2 5c 57 27 1d d0 f9 41 40 43 b0 c0 13 00 00 |c.\W'...A@C.....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| +000002c0 aa 0c 00 00 a6 03 00 1d 20 e8 a5 9c e4 73 3d 75 |........ ....s=u| +000002d0 0c 3e f2 de 21 9c 0f 91 b4 fd 94 f0 27 f6 d9 7d |.>..!.......'..}| +000002e0 cd 0c 4c 50 b0 47 db dd 12 00 80 04 c0 be d5 bb |..LP.G..........| +000002f0 e8 e2 a2 2e d9 2e 75 fa b6 07 d0 f7 75 52 fb 2f |......u.....uR./| +00000300 50 cd 43 68 bd 42 11 6d d6 9f a3 d1 00 fd a9 14 |P.Ch.B.m........| +00000310 0c 2a dd 76 ea 73 21 52 00 3a 83 cf d7 07 c7 bd |.*.v.s!R.:......| +00000320 78 21 ce 35 80 b3 06 22 f1 96 a7 20 41 f8 aa 61 |x!.5..."... A..a| +00000330 94 b4 77 d4 d9 92 f2 66 c5 1c d1 82 f3 b9 e2 9d |..w....f........| +00000340 a9 30 1c e2 4e ec 0d 32 3d 0d 61 22 c8 e5 95 9f |.0..N..2=.a"....| +00000350 cf 3e fc a8 c5 c3 f8 45 45 29 ea a7 e7 b7 a6 17 |.>.....EE)......| +00000360 9e 5f 83 d4 b3 f0 da 31 73 94 f2 16 03 01 00 0a |._.....1s.......| +00000370 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........| +00000380 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 01 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| +00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 91 0f 00 |...._X.;t.......| +00000240 00 8d 00 8b 30 81 88 02 42 00 9a b9 f6 98 e3 ed |....0...B.......| +00000250 ed 0d a3 0e 54 51 9f 73 d4 87 40 4e a9 39 4b 2d |....TQ.s..@N.9K-| +00000260 2a b9 4d 8d e3 46 c3 b6 39 f2 ca a9 c9 0f 79 c1 |*.M..F..9.....y.| +00000270 0c 90 6f de 58 97 72 fc a8 c1 4c 12 aa a4 85 57 |..o.X.r...L....W| +00000280 50 7c a0 02 8a 12 c5 80 aa b6 39 02 42 00 9c b7 |P|........9.B...| +00000290 95 b4 04 83 5b 3a e1 ac da 78 86 11 f5 30 75 4a |....[:...x...0uJ| +000002a0 25 67 6c fd ef 5a d8 56 d3 60 93 cf 65 07 2b 1f |%gl..Z.V.`..e.+.| +000002b0 a9 40 a8 ba cd 0e 41 2d 10 43 a4 61 93 b7 0a 11 |.@....A-.C.a....| +000002c0 78 d1 72 2b 20 07 49 5a 76 02 17 57 87 78 c7 14 |x.r+ .IZv..W.x..| +000002d0 03 01 00 01 01 16 03 01 00 30 93 de 1b 64 0e 56 |.........0...d.V| +000002e0 d9 a8 da f7 37 cb ac ac 3e f5 e2 f9 87 19 f2 79 |....7...>......y| +000002f0 24 76 19 a4 a2 41 d6 9e 7d ca aa 3e 1d d7 22 dd |$v...A..}..>..".| +00000300 05 aa dd 74 03 db fd a2 de ee |...t......| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 4d 4f d6 67 05 |..........0MO.g.| +00000010 32 8c 16 cb 19 35 b3 b9 02 d8 5e 24 b6 c8 b7 3a |2....5....^$...:| +00000020 17 34 98 77 e1 73 e0 cd a9 30 a8 15 60 8c f4 9a |.4.w.s...0..`...| +00000030 dc cf 7a fd 86 85 1c 2b 33 21 e8 |..z....+3!.| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 b8 c5 17 b7 92 d8 93 7a b2 fd 4f |.... .......z..O| +00000010 15 d1 db b9 47 54 00 a0 f6 77 92 03 a8 89 e5 ba |....GT...w......| +00000020 cc eb d9 bd 27 17 03 01 00 20 57 d5 9a f6 36 b2 |....'.... W...6.| +00000030 57 ba cd 64 77 36 b9 74 fb bd 95 51 03 61 e8 45 |W..dw6.t...Q.a.E| +00000040 cb b8 35 f0 05 17 b3 08 c6 cb 15 03 01 00 20 28 |..5........... (| +00000050 43 03 ab 3f e2 f5 d0 33 4c 7f 50 a4 ee 7b 46 e6 |C..?...3L.P..{F.| +00000060 12 76 d0 fd c3 99 5c 63 a4 04 ea 4b e3 bd 99 |.v....\c...K...| diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-Ed25519 b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-Ed25519 new file mode 100644 index 0000000..a14cef1 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-Ed25519 @@ -0,0 +1,110 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| +00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| +00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| +00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 08 05 08 06 04 01 04 |................| +000000b0 03 05 01 05 03 06 01 06 03 02 01 02 03 08 07 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 55 df 11 fe c6 |....Y...U..U....| +00000010 aa d4 85 4b 87 c2 35 4c ac a9 c3 15 a3 7f 6d 7e |...K..5L......m~| +00000020 15 d1 47 b2 d2 09 16 4d 08 1b dd 20 49 d9 51 42 |..G....M... I.QB| +00000030 97 cf 36 b3 74 3e 05 0a e5 c9 97 ef 01 9c 24 34 |..6.t>........$4| +00000040 31 17 e1 8a 6a ce 37 60 02 47 46 7f c0 13 00 00 |1...j.7`.GF.....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| +000002c0 aa 0c 00 00 a6 03 00 1d 20 17 27 58 d2 5f 59 a3 |........ .'X._Y.| +000002d0 62 62 d4 97 4a 49 c4 ff ec dc f7 d3 c9 ea f3 00 |bb..JI..........| +000002e0 61 1b d3 73 38 9e af 7d 17 00 80 59 7a 4e 55 97 |a..s8..}...YzNU.| +000002f0 5a 81 0e 2e 85 0b c2 61 f0 79 72 0e d1 d5 3b bf |Z......a.yr...;.| +00000300 6a 77 03 0a 9a 51 42 f5 98 2f 09 d5 7b 17 76 b8 |jw...QB../..{.v.| +00000310 2c a7 95 ee 61 65 d7 37 b3 1b 16 3c 48 7e 9d ed |,...ae.7...>> Flow 3 (client to server) +00000000 16 03 01 01 3c 0b 00 01 38 00 01 35 00 01 32 30 |....<...8..5..20| +00000010 82 01 2e 30 81 e1 a0 03 02 01 02 02 10 17 d1 81 |...0............| +00000020 93 be 2a 8c 21 20 10 25 15 e8 34 23 4f 30 05 06 |..*.! .%..4#O0..| +00000030 03 2b 65 70 30 12 31 10 30 0e 06 03 55 04 0a 13 |.+ep0.1.0...U...| +00000040 07 41 63 6d 65 20 43 6f 30 1e 17 0d 31 39 30 35 |.Acme Co0...1905| +00000050 31 36 32 31 35 34 32 36 5a 17 0d 32 30 30 35 31 |16215426Z..20051| +00000060 35 32 31 35 34 32 36 5a 30 12 31 10 30 0e 06 03 |5215426Z0.1.0...| +00000070 55 04 0a 13 07 41 63 6d 65 20 43 6f 30 2a 30 05 |U....Acme Co0*0.| +00000080 06 03 2b 65 70 03 21 00 0b e0 b5 60 b5 e2 79 30 |..+ep.!....`..y0| +00000090 3d be e3 1e e0 50 b1 04 c8 6d c7 78 6c 69 2f c5 |=....P...m.xli/.| +000000a0 14 ad 9a 63 6f 79 12 91 a3 4d 30 4b 30 0e 06 03 |...coy...M0K0...| +000000b0 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 |U...........0...| +000000c0 55 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 |U.%..0...+......| +000000d0 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 |.0...U.......0.0| +000000e0 16 06 03 55 1d 11 04 0f 30 0d 82 0b 65 78 61 6d |...U....0...exam| +000000f0 70 6c 65 2e 63 6f 6d 30 05 06 03 2b 65 70 03 41 |ple.com0...+ep.A| +00000100 00 fc 19 17 2a 94 a5 31 fa 29 c8 2e 7f 5b a0 5d |....*..1.)...[.]| +00000110 8a 4e 34 40 39 d6 b3 10 dc 19 fe a0 22 71 b3 f5 |.N4@9......."q..| +00000120 8f a1 58 0d cd f4 f1 85 24 bf e6 3d 14 df df ed |..X.....$..=....| +00000130 0e e1 17 d8 11 a2 60 d0 8a 37 23 2a c2 46 aa 3a |......`..7#*.F.:| +00000140 08 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 |.....%...! /.}.G| +00000150 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +00000160 c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 46 |......_X.;t....F| +00000170 0f 00 00 42 00 40 14 6a d7 c1 9c 3d 81 fa e9 da |...B.@.j...=....| +00000180 96 5c 3a 09 e2 fc 36 e2 30 39 e4 6e 0d ac aa 54 |.\:...6.09.n...T| +00000190 24 4d 8c f0 35 14 b0 0b e9 5b 57 52 31 02 9f 6c |$M..5....[WR1..l| +000001a0 6f 6c d7 e9 b5 7f cb 30 fe b9 ba b9 7a 46 67 e3 |ol.....0....zFg.| +000001b0 a7 50 ca ce e4 04 14 03 01 00 01 01 16 03 01 00 |.P..............| +000001c0 30 8d 0a ca d1 5e 2c 7e 92 d0 69 f4 d9 e8 5d 0a |0....^,~..i...].| +000001d0 11 72 67 20 3e 80 64 29 e5 79 f5 33 ad 06 78 07 |.rg >.d).y.3..x.| +000001e0 4c 03 fc 2e 16 35 70 b1 72 e7 35 a9 cc 49 b8 29 |L....5p.r.5..I.)| +000001f0 30 |0| +>>> Flow 4 (server to client) +00000000 15 03 01 00 02 02 50 |......P| diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA new file mode 100644 index 0000000..3ee661e --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA @@ -0,0 +1,133 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 b4 ff c0 49 36 |....Y...U.....I6| +00000010 1d 31 9a a7 f6 33 f5 16 78 d7 10 9e 19 eb 1d 67 |.1...3..x......g| +00000020 20 39 f8 73 7e 27 e2 dc d1 ab 03 20 79 64 67 f7 | 9.s~'..... ydg.| +00000030 8b c8 97 f0 b4 87 0e 2d 4b 22 6c ed 92 48 85 52 |.......-K"l..H.R| +00000040 eb 57 56 a8 cf 19 9f 4d e3 38 5e a0 c0 09 00 00 |.WV....M.8^.....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 01 00 b4 0c 00 00 b0 03 00 1d 20 ec 38 |*............ .8| +00000280 f7 41 d0 f3 f4 6a ca 47 18 74 f1 22 2c 47 ee 39 |.A...j.G.t.",G.9| +00000290 c9 a2 db 64 05 01 ae 5d 08 65 53 7f 24 78 00 8a |...d...].eS.$x..| +000002a0 30 81 87 02 41 64 39 65 56 fa d4 69 e7 c5 a5 32 |0...Ad9eV..i...2| +000002b0 4c 52 55 96 fe 01 cd 41 3c 18 ed df fd 09 c3 89 |LRU....A<.......| +000002c0 80 bd 88 9e d7 a1 85 16 d1 a4 5a f0 9a 76 e9 2f |..........Z..v./| +000002d0 d2 a4 42 a4 89 98 6c 87 64 b1 49 4e 6a 68 d2 43 |..B...l.d.INjh.C| +000002e0 41 a2 c7 a6 2f f7 02 42 01 6c bb 32 c0 47 7e 08 |A.../..B.l.2.G~.| +000002f0 6b 7a 44 18 b7 5d 4c 4d 6d 80 92 bb e5 65 98 1b |kzD..]LMm....e..| +00000300 d7 a6 a3 1b b5 f3 46 1a e7 e0 89 04 40 b0 29 aa |......F.....@.).| +00000310 fe 85 6a 9a 4b 18 75 ab 00 52 71 54 41 8d eb 31 |..j.K.u..RqTA..1| +00000320 47 69 9b 9d dc 3b 1b 3e 76 27 16 03 01 00 0a 0d |Gi...;.>v'......| +00000330 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e 00 |......@.........| +00000340 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 01 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| +00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| +00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.| +00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1| +00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C| +00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523| +00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231| +00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac| +00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.| +00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....| +000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x| +000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.| +000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4| +000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..| +000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#| +000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....| +00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......| +00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..| +00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U| +00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U| +00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.| +00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0| +00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........| +00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..| +00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]| +000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A| +000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...| +000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...| +000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| +000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| +000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| +00000200 e5 35 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| +00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| +00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 |......._X.;t....| +00000230 86 0f 00 00 82 00 80 05 7e 70 eb cb ef e3 d9 6f |........~p.....o| +00000240 59 29 b5 da f2 07 f5 42 62 4e 74 9b cf 00 e1 5c |Y).....BbNt....\| +00000250 69 a5 67 3a b0 b2 ca f2 10 ed 1c b4 81 5d 7d 9e |i.g:.........]}.| +00000260 1a 45 69 42 13 c5 b0 86 dc 3d 60 e5 cf fd ae 0f |.EiB.....=`.....| +00000270 17 bb 4a ed d7 06 eb f1 6d 47 98 b7 e8 87 eb 3c |..J.....mG.....<| +00000280 12 55 2c 06 de 55 48 c7 59 85 cb 62 d6 e7 1d 05 |.U,..UH.Y..b....| +00000290 1e 6d 69 84 cd 16 8e dd ed 5b 5a 2f f2 97 b7 78 |.mi......[Z/...x| +000002a0 93 c1 fb 75 26 c8 b5 58 43 17 c7 52 54 20 4f 7d |...u&..XC..RT O}| +000002b0 7c 46 89 65 fe 51 29 14 03 01 00 01 01 16 03 01 ||F.e.Q).........| +000002c0 00 30 d9 59 e6 7e c0 a6 2a af 36 0c 2e cf 0f 42 |.0.Y.~..*.6....B| +000002d0 54 d4 41 c6 3c f8 84 d9 2a a6 82 94 22 2d ac ae |T.A.<...*..."-..| +000002e0 d9 f7 68 22 f6 f0 2e 56 c1 97 80 73 0d b3 f0 70 |..h"...V...s...p| +000002f0 49 78 |Ix| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 06 19 79 49 41 |..........0..yIA| +00000010 f9 9c 75 84 73 95 96 bd 1e 25 56 a9 49 ed 8e 38 |..u.s....%V.I..8| +00000020 34 40 60 dc f0 2d f3 6c cf 5b 80 84 2b 81 db 5f |4@`..-.l.[..+.._| +00000030 f4 27 03 ad b8 8d 80 0c 99 69 6f |.'.......io| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 20 67 bd ff 84 9b 0e 58 f3 45 1e |.... g.....X.E.| +00000010 7a 25 d5 ae f0 26 4b 42 c7 f3 a5 77 7b 2f 42 21 |z%...&KB...w{/B!| +00000020 2e c6 c9 81 23 17 03 01 00 20 69 1c 2a b9 05 16 |....#.... i.*...| +00000030 8b 71 3a c2 18 76 bd 25 1f de 83 e9 14 e2 a3 5c |.q:..v.%.......\| +00000040 9b 33 ee 14 39 da e2 e7 a3 a7 15 03 01 00 20 e9 |.3..9......... .| +00000050 dc 16 0c 13 56 7a e5 fd ce b9 4f d1 c7 20 3f ca |....Vz....O.. ?.| +00000060 72 20 15 f7 11 81 fe 88 ab 90 4c dc 0b a5 11 |r ........L....| diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA new file mode 100644 index 0000000..980f933 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA @@ -0,0 +1,137 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 4d 6d 71 59 6b |....Y...U..MmqYk| +00000010 cd 8c 6e b0 11 bf 4a 9e 25 90 12 cc ac b4 3f be |..n...J.%.....?.| +00000020 86 1b 13 47 a6 be 3d a0 8f 0b 77 20 6b b5 57 6d |...G..=...w k.Wm| +00000030 39 74 b0 9d b4 ae 2e 72 7e 90 d2 ab ed 32 fa 65 |9t.....r~....2.e| +00000040 ed 85 63 d2 16 ef 47 af a6 37 17 88 c0 13 00 00 |..c...G..7......| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| +000002c0 aa 0c 00 00 a6 03 00 1d 20 96 0b 2f 57 e1 1e 07 |........ ../W...| +000002d0 e0 7f a4 91 67 97 d0 a0 19 d3 9a b2 49 79 f9 5f |....g.......Iy._| +000002e0 7f b5 65 d4 3a 89 92 8f 11 00 80 08 29 72 0b f7 |..e.:.......)r..| +000002f0 7b 68 38 5e 47 15 89 f1 ee be f3 a9 26 a4 9c 6d |{h8^G.......&..m| +00000300 2c 2a ff f0 d6 2d 25 a5 b0 93 66 7d 8c fb fe a5 |,*...-%...f}....| +00000310 3b cc b6 71 f4 1b 55 c4 ef 08 73 b1 49 47 2c e6 |;..q..U...s.IG,.| +00000320 a1 ef 53 ca bb 15 e3 25 ea e7 48 44 18 88 e1 d2 |..S....%..HD....| +00000330 3b e9 f6 92 61 5e 5c 06 44 83 37 6c e6 b6 26 32 |;...a^\.D.7l..&2| +00000340 fd d6 00 fc 87 a2 37 e3 84 d2 ad 2d 99 0d e1 ba |......7....-....| +00000350 bb 2f 3b 0b dd 56 5c c2 14 af 86 58 2c 8b f8 64 |./;..V\....X,..d| +00000360 75 ab d3 35 41 59 fa fe a5 48 26 16 03 01 00 0a |u..5AY...H&.....| +00000370 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........| +00000380 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 01 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| +00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| +00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.| +00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1| +00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C| +00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523| +00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231| +00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac| +00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.| +00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....| +000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x| +000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.| +000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4| +000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..| +000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#| +000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....| +00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......| +00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..| +00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U| +00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U| +00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.| +00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0| +00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........| +00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..| +00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]| +000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A| +000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...| +000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...| +000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| +000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| +000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| +00000200 e5 35 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| +00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| +00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 |......._X.;t....| +00000230 86 0f 00 00 82 00 80 8f 5d a5 27 13 09 5e 49 5f |........].'..^I_| +00000240 ff fd d6 88 75 83 cc 74 f3 e1 af 44 76 6a 35 16 |....u..t...Dvj5.| +00000250 e8 36 5f b7 dc 21 69 77 61 12 c5 69 f7 0d 98 1f |.6_..!iwa..i....| +00000260 d5 15 f1 e8 88 c5 30 e8 b5 c3 2a e5 26 93 cc a4 |......0...*.&...| +00000270 eb 31 c6 d7 f5 f4 7c d5 f7 a2 3f 1f 75 cd b2 b2 |.1....|...?.u...| +00000280 82 3a 03 8c 5e 15 0a d2 98 b8 65 cb 5f d5 db d0 |.:..^.....e._...| +00000290 b6 36 8c 89 7e 48 fa 3a 9f 9a bd c1 48 e7 d6 20 |.6..~H.:....H.. | +000002a0 ef 45 5b 24 32 04 58 82 b3 7b 42 fd fe ba 78 32 |.E[$2.X..{B...x2| +000002b0 2a f5 b7 81 33 da db 14 03 01 00 01 01 16 03 01 |*...3...........| +000002c0 00 30 5f 96 98 94 17 6d ff 84 72 d3 63 fd 14 59 |.0_....m..r.c..Y| +000002d0 eb bf 5f 3e 8f dc f1 c1 dc 77 8a 33 f6 2e a2 4a |.._>.....w.3...J| +000002e0 15 d1 2e a4 ec 0d 3c 0b 18 07 09 6c 0d 09 34 2e |......<....l..4.| +000002f0 a4 6f |.o| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 b7 4a 5c 0c e6 |..........0.J\..| +00000010 7c d9 43 7c e7 b4 2f d7 b5 c6 5e 36 c7 87 dd 82 ||.C|../...^6....| +00000020 da d3 b2 4e 05 ae f5 8c b0 4d db c2 53 62 55 73 |...N.....M..SbUs| +00000030 8c 2a 1b d5 df e4 7c a4 cf db 8b |.*....|....| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 b9 26 60 87 38 9c d9 c4 65 17 8e |.... .&`.8...e..| +00000010 3c 7f 1a b4 23 cd 27 fd 4e 92 ee 0e f2 11 dc e2 |<...#.'.N.......| +00000020 23 e4 26 f3 55 17 03 01 00 20 5e 89 33 21 f0 dc |#.&.U.... ^.3!..| +00000030 e8 4f 33 1c 66 56 99 38 a5 4c 0e 0e 93 41 b7 48 |.O3.fV.8.L...A.H| +00000040 5d ce 49 d0 d2 8a 56 a6 2d 68 15 03 01 00 20 05 |].I...V.-h.... .| +00000050 e0 ed f9 c2 56 ec 64 e5 e7 0b f4 8a e2 41 96 9e |....V.d......A..| +00000060 ed 94 c8 95 69 d7 ce 2d 0e bb 5b 18 5f 30 52 |....i..-..[._0R| diff --git a/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES new file mode 100644 index 0000000..6fc506f --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 a3 4e 79 27 af |....Y...U...Ny'.| +00000010 c8 a3 15 a4 c2 7a 54 58 54 0e 0d 93 c2 ff e1 f9 |.....zTXT.......| +00000020 55 ab 2c ea 32 cf d2 47 2e d7 8e 20 49 08 d1 66 |U.,.2..G... I..f| +00000030 9b 9e aa af c9 90 95 ec cb 64 2e 3d f6 27 d5 f6 |.........d.=.'..| +00000040 23 10 d5 6e 50 5f bc 89 fe c7 d7 de c0 09 00 00 |#..nP_..........| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 4a 7c |*............ J|| +00000280 0a 86 8a 81 f2 60 4a 3c ac d7 7d 3b fc 00 a5 b4 |.....`J<..};....| +00000290 85 45 45 45 fb 09 53 d7 4a cf 24 9d c8 1a 00 8b |.EEE..S.J.$.....| +000002a0 30 81 88 02 42 01 7a c9 c0 76 8c 26 98 63 4e a3 |0...B.z..v.&.cN.| +000002b0 ad 4f 4e a3 d7 c7 d6 4a 69 28 cf d2 7b 0b 36 fb |.ON....Ji(..{.6.| +000002c0 a3 ae 2f e1 83 ea ea 4a b7 2d ef a8 2d 13 96 e4 |../....J.-..-...| +000002d0 73 83 66 70 5e 5c d9 5a d1 1c d1 33 18 0b b3 30 |s.fp^\.Z...3...0| +000002e0 2a 21 d7 78 d8 70 18 02 42 00 c4 ab 80 33 8f f1 |*!.x.p..B....3..| +000002f0 c2 74 1b 58 2f 59 d4 27 a1 19 42 bf 14 ea a8 a2 |.t.X/Y.'..B.....| +00000300 cb bf 96 2d 60 7b 84 40 cc 31 f5 c4 e8 51 87 b8 |...-`{.@.1...Q..| +00000310 7b 47 ec c4 c0 4a 9b 09 59 1e f8 b5 9a e1 45 a4 |{G...J..Y.....E.| +00000320 a1 9b ee 78 55 f8 f5 fa 1a fb c5 16 03 01 00 04 |...xU...........| +00000330 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| +00000030 16 03 01 00 30 b0 5e 4a 8a 07 e3 86 43 05 16 68 |....0.^J....C..h| +00000040 0e d1 58 a6 05 49 e9 a6 42 89 2c 3f 33 68 8b 26 |..X..I..B.,?3h.&| +00000050 23 21 3b 62 ab 7a 21 74 d8 49 15 03 b3 1e c6 53 |#!;b.z!t.I.....S| +00000060 74 1e 1c 4e 0f |t..N.| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 64 4b 3c 1a e3 |..........0dK<..| +00000010 7d bb bb bb 64 d8 51 c3 eb 92 65 65 58 35 dd 7b |}...d.Q...eeX5.{| +00000020 d2 fd f0 0c c1 10 71 a5 a8 f7 14 84 69 b4 81 18 |......q.....i...| +00000030 1e 0d d3 19 b6 23 72 1a a7 43 0e |.....#r..C.| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 c3 e6 70 2c 44 4f 04 0c fb 0b 7f |.... ..p,DO.....| +00000010 1d 2c ef 4d cc c3 21 ba a2 db 74 76 46 ea 00 40 |.,.M..!...tvF..@| +00000020 54 2d 4a fe 59 17 03 01 00 20 0c 6b 39 0d b5 f3 |T-J.Y.... .k9...| +00000030 ed 7e d0 de 01 18 0c 32 4e 59 93 46 d3 c5 4f c0 |.~.....2NY.F..O.| +00000040 f5 fd f1 d2 79 07 7d 07 b0 24 15 03 01 00 20 1d |....y.}..$.... .| +00000050 f7 53 a2 e7 3f 88 87 35 01 6e a5 b1 d6 81 37 5b |.S..?..5.n....7[| +00000060 a7 64 4c 29 f4 71 59 a1 36 c1 1a 24 93 31 7d |.dL).qY.6..$.1}| diff --git a/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES new file mode 100644 index 0000000..24da556 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES @@ -0,0 +1,95 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 63 68 ea 52 0b |....Y...U..ch.R.| +00000010 dc 68 c7 d0 75 3e 7d 6f 0b 8c cb 25 48 b0 bb df |.h..u>}o...%H...| +00000020 7a 56 93 a9 d5 4f 0c 3a e2 37 ab 20 1f 0f a4 d3 |zV...O.:.7. ....| +00000030 b4 f6 66 6f 39 6f 62 fb 6a 1f 41 09 4b 02 5c 15 |..fo9ob.j.A.K.\.| +00000040 a0 ba cb a6 f9 bd 3b ec cb 76 6e ea c0 13 00 00 |......;..vn.....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| +000002c0 aa 0c 00 00 a6 03 00 1d 20 04 9f 8b 4f 13 83 26 |........ ...O..&| +000002d0 a3 cf 08 6e 59 bf b5 49 b8 ff 95 94 21 8d 2a 56 |...nY..I....!.*V| +000002e0 2e 4b be ad ac 89 6e 52 4d 00 80 5f 63 93 43 a2 |.K....nRM.._c.C.| +000002f0 a6 fb 53 b0 ac 93 3f 55 1d c1 0f 71 1e 96 ba 9f |..S...?U...q....| +00000300 86 19 f3 83 7d 90 ce 06 24 9a 60 69 f0 35 24 5d |....}...$.`i.5$]| +00000310 9d ce 49 0d 6f ba 31 59 3c f2 64 27 66 76 0e f1 |..I.o.1Y<.d'fv..| +00000320 33 eb b8 70 61 d3 0c 93 a3 62 c7 5e c2 06 9d 48 |3..pa....b.^...H| +00000330 16 2e a6 62 50 18 f6 c0 79 c2 09 f3 d5 74 bf db |...bP...y....t..| +00000340 b8 d4 25 06 a7 be 4a b0 62 82 86 d0 00 86 5e a2 |..%...J.b.....^.| +00000350 34 49 9b 37 37 9a b6 eb cc b9 8b 17 1f 29 4b a3 |4I.77........)K.| +00000360 51 e3 c3 e8 3e 6e df c4 1d e5 48 16 03 01 00 04 |Q...>n....H.....| +00000370 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| +00000030 16 03 01 00 30 a6 3a 66 02 e6 09 6a dd 68 56 bc |....0.:f...j.hV.| +00000040 aa ec 82 c4 69 9b b9 45 44 ec e2 c2 5b 49 5d 9b |....i..ED...[I].| +00000050 f8 0e 81 1e 23 9e 13 72 d1 d2 0c 24 01 4f 35 aa |....#..r...$.O5.| +00000060 27 fc b3 cc 08 |'....| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 0e 25 d7 a9 c0 |..........0.%...| +00000010 18 3b bf 55 c0 47 3a 95 2d cb 6f c2 2c de e3 94 |.;.U.G:.-.o.,...| +00000020 32 d3 eb e2 b6 6b 5f 42 9c 1e 47 d6 76 0c eb 95 |2....k_B..G.v...| +00000030 fd 2d c3 9a ee ee 83 87 e8 8d 83 |.-.........| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 ba b0 c4 22 ee 52 81 ca 55 97 4d |.... ...".R..U.M| +00000010 39 16 b9 37 bf df 7b d1 ae 4b 47 ac 10 12 a9 77 |9..7..{..KG....w| +00000020 69 50 f3 60 13 17 03 01 00 20 90 d5 17 e4 96 38 |iP.`..... .....8| +00000030 cd f7 30 6e 19 45 4e 32 ad 5f 1b 00 bf 22 9d c2 |..0n.EN2._..."..| +00000040 16 30 fe 92 c7 fc 91 38 29 30 15 03 01 00 20 c0 |.0.....8)0.... .| +00000050 02 ff 81 82 c9 25 c6 b0 06 ee 18 61 19 c8 d2 20 |.....%.....a... | +00000060 d8 4e 7b a4 a5 57 17 64 4d ad 1e 1e 16 1e 52 |.N{..W.dM.....R| diff --git a/src/crypto/tls/testdata/Client-TLSv10-Ed25519 b/src/crypto/tls/testdata/Client-TLSv10-Ed25519 new file mode 100644 index 0000000..e69de29 diff --git a/src/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial b/src/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial new file mode 100644 index 0000000..6a40d83 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial @@ -0,0 +1,95 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 05 31 9d 41 04 |....Y...U...1.A.| +00000010 c0 d4 34 1a fc 0f 63 26 47 d6 13 7f a0 d8 aa bf |..4...c&G.......| +00000020 28 92 04 80 02 75 58 e6 01 e1 30 20 3c fc b0 02 |(....uX...0 <...| +00000030 8b a4 9e 9e b2 5c 17 3c 48 0b 96 6f 15 80 d5 38 |.....\.I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| +000002c0 aa 0c 00 00 a6 03 00 1d 20 a4 50 9a 0d c7 2a 1b |........ .P...*.| +000002d0 f6 d4 78 49 68 ac 5f 8b e7 78 68 05 4b f8 c6 b3 |..xIh._..xh.K...| +000002e0 eb 28 79 96 d5 e6 aa c1 54 00 80 22 66 ec fd 14 |.(y.....T.."f...| +000002f0 83 7b 03 86 14 75 84 a4 a6 d0 ee d3 d0 f7 95 d8 |.{...u..........| +00000300 43 48 a4 eb 83 af 96 ac cf e8 65 20 05 c3 18 9a |CH........e ....| +00000310 54 63 f5 2f b7 17 06 e0 2a b3 65 6a 2f cc cd 93 |Tc./....*.ej/...| +00000320 1e b3 5a 4d 09 da 70 b0 12 46 60 11 e4 9f ee 9f |..ZM..p..F`.....| +00000330 3b 6f ef df bc db 69 22 5e e8 4c 41 d6 b7 7b 06 |;o....i"^.LA..{.| +00000340 b6 99 1c 6d 01 5a 61 7c 4e 3a af 3e 01 7e 46 bd |...m.Za|N:.>.~F.| +00000350 c8 15 28 ba 7f b3 d6 9d 95 74 04 36 6c 38 16 86 |..(......t.6l8..| +00000360 d2 1d 8a 85 d1 21 5c 33 17 50 a1 16 03 01 00 04 |.....!\3.P......| +00000370 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| +00000030 16 03 01 00 30 f0 15 ea 81 0f a6 22 0a cd a5 a1 |....0......"....| +00000040 38 4a da 1b 6c 81 19 d5 35 b7 af e9 ec 16 4d 98 |8J..l...5.....M.| +00000050 21 c2 0e f7 0b fb ff d8 1e 2d 8b 04 56 82 48 c4 |!........-..V.H.| +00000060 e5 f9 38 8c d2 |..8..| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 f0 b5 a3 bb bb |..........0.....| +00000010 9d 85 7d 6f e7 a9 17 31 65 74 82 69 56 a9 33 21 |..}o...1et.iV.3!| +00000020 16 9d 75 3a 28 88 a5 c2 a9 e1 a7 43 6e 03 26 96 |..u:(......Cn.&.| +00000030 37 4b de 63 be 49 cb c8 d4 a2 b6 |7K.c.I.....| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 a9 9c 8f 74 ce f9 77 bc b3 86 2e |.... ...t..w....| +00000010 a5 8e 94 3d 08 a6 96 bf 25 0b 10 c4 66 c2 59 9a |...=....%...f.Y.| +00000020 4a 1a b4 77 12 17 03 01 00 20 03 72 60 38 58 88 |J..w..... .r`8X.| +00000030 86 20 20 3f 18 52 c5 ca 55 3c 04 04 c7 e1 74 6f |. ?.R..U<....to| +00000040 ca 1f cd 27 64 f2 51 12 9c ee 15 03 01 00 20 30 |...'d.Q....... 0| +00000050 71 2a 78 bf 8b d5 11 7c 63 11 c7 25 0e 56 25 ce |q*x....|c..%.V%.| +00000060 24 d5 d7 de a0 ba c7 ba e6 dc db 8e e3 93 a6 |$..............| diff --git a/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 new file mode 100644 index 0000000..dcc18ad --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 01 00 51 02 00 00 4d 03 01 2a 09 26 d2 61 |....Q...M..*.&.a| +00000010 ac 38 91 3d 18 3f f7 a9 3c 34 91 b0 b1 e1 29 68 |.8.=.?..<4....)h| +00000020 dd cb b9 a9 d8 39 0b 64 c6 93 7d 20 ea 51 ff 63 |.....9.d..} .Q.c| +00000030 97 03 b2 6f a3 d6 55 0d 64 65 2a 5d 3a fe e9 3e |...o..U.de*]:..>| +00000040 47 c1 7d c5 d8 03 c6 22 19 2f 6c 5a 00 05 00 00 |G.}...."./lZ....| +00000050 05 ff 01 00 01 00 16 03 01 02 59 0b 00 02 55 00 |..........Y...U.| +00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +000002b0 3b e9 fa e7 16 03 01 00 04 0e 00 00 00 |;............| +>>> Flow 3 (client to server) +00000000 16 03 01 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...| +00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..| +00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.| +00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h| +00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...| +00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........| +00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| +00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| +00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 01 00 01 |.Y(.....ia5.....| +00000090 01 16 03 01 00 24 29 ee 6c 54 d6 21 5e 31 30 9e |.....$).lT.!^10.| +000000a0 fd 02 69 bb 32 c2 9e ad 28 b1 2d 94 49 0a 12 0c |..i.2...(.-.I...| +000000b0 a1 12 b0 98 a6 33 eb 63 2b e4 |.....3.c+.| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 24 32 3e 45 f2 3a |..........$2>E.:| +00000010 01 05 50 db 37 25 f6 b5 67 8e 38 3d f5 ba b7 90 |..P.7%..g.8=....| +00000020 e0 05 a8 cb e0 33 1a 79 ab 44 86 d5 0c fd 86 |.....3.y.D.....| +>>> Flow 5 (client to server) +00000000 17 03 01 00 1a ac 0c 1f 12 4e d4 31 10 dd c1 04 |.........N.1....| +00000010 8b 55 a2 2e a5 f4 e4 80 aa 23 7e bd 79 b0 ee 15 |.U.......#~.y...| +00000020 03 01 00 16 fa d9 ff 50 7d 41 01 2a d2 13 ee 33 |.......P}A.*...3| +00000030 52 ab 20 c5 e7 73 81 5d 81 60 |R. ..s.].`| diff --git a/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES new file mode 100644 index 0000000..92cdc4c --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES @@ -0,0 +1,93 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 02 00 59 02 00 00 55 03 02 bf ac 6b 91 53 |....Y...U....k.S| +00000010 dc 1f d6 ee 0e 71 d6 a4 f5 a2 7c f0 10 69 41 dd |.....q....|..iA.| +00000020 4a b7 30 53 e6 28 07 31 34 8f e5 20 59 d1 bd e1 |J.0S.(.14.. Y...| +00000030 20 44 c4 05 07 e9 07 90 5d de 08 73 72 55 04 a6 | D......]..srU..| +00000040 11 20 bf 32 e0 dd 46 d4 1d ed 45 62 c0 09 00 00 |. .2..F...Eb....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 02 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 02 00 b5 0c 00 00 b1 03 00 1d 20 ab ea |*............ ..| +00000280 ff 17 1e b1 ef f6 22 03 40 8b e1 1a fa ab 01 cf |......".@.......| +00000290 0f f0 b0 6d 43 3c 1f 03 a1 d6 4a 9d 79 43 00 8b |...mC<....J.yC..| +000002a0 30 81 88 02 42 00 a1 b4 50 4b 9b a3 a5 ec ef dc |0...B...PK......| +000002b0 bf c1 a2 65 24 2a 6c aa ab 26 01 ed d1 ad 2e 37 |...e$*l..&.....7| +000002c0 4f f5 8b ff 98 ac ef 15 3e d9 46 07 a3 d2 35 de |O.......>.F...5.| +000002d0 91 bc 3d a0 1f f1 68 55 28 ef 60 ad 13 05 ac 65 |..=...hU(.`....e| +000002e0 e5 67 02 3f 85 8b 1b 02 42 01 26 3f fc 62 e3 93 |.g.?....B.&?.b..| +000002f0 8e fa fb 93 0f 0b ff 68 25 46 ea 71 16 ae 6e d4 |.......h%F.q..n.| +00000300 36 9e 48 2c 77 2b d8 f5 f6 1d 69 68 ed 28 8f e7 |6.H,w+....ih.(..| +00000310 79 7e 78 56 52 ff e8 62 fc e2 bd 2e c7 e8 9f 3f |y~xVR..b.......?| +00000320 93 47 d2 62 6c f6 5c 0e a2 b8 fe 16 03 02 00 04 |.G.bl.\.........| +00000330 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 02 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 02 00 01 01 |....._X.;t......| +00000030 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00000040 00 00 00 00 00 0f 55 37 4b 93 d5 ce b1 1c 6f a3 |......U7K.....o.| +00000050 6d 56 32 f5 de 19 f6 a3 15 b0 6a 90 06 92 60 ca |mV2.......j...`.| +00000060 ec 0e 2b d4 24 16 0a 26 f3 bd 3d ca c5 9f d2 9b |..+.$..&..=.....| +00000070 79 2f af b6 b0 |y/...| +>>> Flow 4 (server to client) +00000000 14 03 02 00 01 01 16 03 02 00 40 4d e3 a9 af 51 |..........@M...Q| +00000010 f5 d1 cd 04 f1 cf c5 48 0f 2e 0b 6e 57 4c 11 28 |.......H...nWL.(| +00000020 dd 89 19 14 98 8e 2e 92 db 3c a4 0f 85 32 90 7e |.........<...2.~| +00000030 49 13 17 a0 85 fa c6 25 79 24 13 90 86 dc ec 45 |I......%y$.....E| +00000040 7c 74 35 92 e4 89 04 c2 51 27 66 ||t5.....Q'f| +>>> Flow 5 (client to server) +00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +00000010 00 00 00 00 00 f9 ac 17 1f 08 b7 80 fb 70 87 e2 |.............p..| +00000020 53 00 27 60 78 6c 80 5b 57 e7 70 72 8a e3 1b 32 |S.'`xl.[W.pr...2| +00000030 8c f0 67 82 82 15 03 02 00 30 00 00 00 00 00 00 |..g......0......| +00000040 00 00 00 00 00 00 00 00 00 00 01 e1 86 47 7f 65 |.............G.e| +00000050 a9 d2 1c 22 7d 99 7c 41 dc 17 f5 16 40 5b b3 7f |..."}.|A....@[..| +00000060 cc 0b 97 41 0c ae 1f 0c 39 e0 |...A....9.| diff --git a/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES new file mode 100644 index 0000000..b2b7ecb --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES @@ -0,0 +1,97 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 02 00 59 02 00 00 55 03 02 95 6e 24 5a ab |....Y...U...n$Z.| +00000010 ae 3c 73 52 9d 31 63 50 cf f9 50 99 3c e4 94 22 |.B.5.h'| +00000040 c4 2b 35 0f f8 1c e3 28 e6 8a 59 dc c0 13 00 00 |.+5....(..Y.....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 02 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 02 00 |.=.`.\!.;.......| +000002c0 aa 0c 00 00 a6 03 00 1d 20 b5 75 ee e5 26 6b c0 |........ .u..&k.| +000002d0 af 34 8a 24 f7 c5 25 58 29 38 4c 08 d3 a2 0c 48 |.4.$..%X)8L....H| +000002e0 18 eb a0 5b e8 64 62 62 78 00 80 d0 1c 9c 11 1a |...[.dbbx.......| +000002f0 58 4c 46 5f 18 03 d7 d7 76 47 d5 56 7a bb bd 95 |XLF_....vG.Vz...| +00000300 16 46 e8 0b 28 6e df 15 65 1a f6 95 fb 4a 6c 42 |.F..(n..e....JlB| +00000310 1b 4c 5c 30 c5 de d0 83 08 d3 2e 4d 59 7e 7b 1b |.L\0.......MY~{.| +00000320 20 9e b5 19 76 fe a3 dd 87 04 f4 9a 3e 3c c0 4a | ...v.......><.J| +00000330 16 7f e3 4e 9a 1f 0a 36 1d f5 09 b4 88 09 b1 1b |...N...6........| +00000340 9b 60 97 dc d7 ea 97 f4 d6 06 16 45 98 ee 5c 39 |.`.........E..\9| +00000350 62 3f 7c 82 7b c3 52 59 01 d4 89 8c a6 e2 d5 eb |b?|.{.RY........| +00000360 e8 30 a6 78 49 1e ec a5 92 ad 24 16 03 02 00 04 |.0.xI.....$.....| +00000370 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 02 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 02 00 01 01 |....._X.;t......| +00000030 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00000040 00 00 00 00 00 28 ab ed 77 d3 56 29 a8 4a 38 c8 |.....(..w.V).J8.| +00000050 64 1c a5 d9 4e f9 6b 0e fa 82 42 ad 0d be 15 69 |d...N.k...B....i| +00000060 9a ff 79 64 db 8f 3e 16 b3 86 93 82 6f 78 c4 2e |..yd..>.....ox..| +00000070 7c 54 6c 4f 90 ||TlO.| +>>> Flow 4 (server to client) +00000000 14 03 02 00 01 01 16 03 02 00 40 15 e9 c5 15 59 |..........@....Y| +00000010 b3 0d 46 22 0c ae a6 41 02 b4 f3 da 11 dc 85 79 |..F"...A.......y| +00000020 bb d9 3f 23 38 51 24 1a 08 b5 a0 63 dc 4b 86 50 |..?#8Q$....c.K.P| +00000030 ef b2 32 07 fd b5 e1 01 06 19 42 ce ba 69 ab 1a |..2.......B..i..| +00000040 c9 bb db 7d d0 9f f9 7c f2 6c 18 |...}...|.l.| +>>> Flow 5 (client to server) +00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +00000010 00 00 00 00 00 67 ef de df a4 91 69 58 b8 3f 06 |.....g.....iX.?.| +00000020 c4 05 4e ad 88 9b c5 12 35 cf 63 39 3a 61 e9 4c |..N.....5.c9:a.L| +00000030 49 22 93 f4 10 15 03 02 00 30 00 00 00 00 00 00 |I".......0......| +00000040 00 00 00 00 00 00 00 00 00 00 00 2a 5a ba 39 7e |...........*Z.9~| +00000050 a8 be 2e 72 f3 ba 7e 0a 32 b5 8c d8 f5 1b 93 6c |...r..~.2......l| +00000060 3e 35 d8 ba cc f3 9f f4 19 74 |>5.......t| diff --git a/src/crypto/tls/testdata/Client-TLSv11-Ed25519 b/src/crypto/tls/testdata/Client-TLSv11-Ed25519 new file mode 100644 index 0000000..e69de29 diff --git a/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 new file mode 100644 index 0000000..aeba311 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 02 00 51 02 00 00 4d 03 02 82 5b 12 ac 33 |....Q...M...[..3| +00000010 08 d4 28 8c 91 6e 52 c4 c6 09 13 24 bf 42 d2 37 |..(..nR....$.B.7| +00000020 6d 78 60 b0 ea bd 9e b3 08 99 43 20 05 5a 93 f9 |mx`.......C .Z..| +00000030 a4 39 43 4f c4 e3 27 20 7d 4c fa 7a 28 c1 c7 33 |.9CO..' }L.z(..3| +00000040 72 fa 14 b8 ba c3 89 b0 a5 54 a3 7c 00 05 00 00 |r........T.|....| +00000050 05 ff 01 00 01 00 16 03 02 02 59 0b 00 02 55 00 |..........Y...U.| +00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +000002b0 3b e9 fa e7 16 03 02 00 04 0e 00 00 00 |;............| +>>> Flow 3 (client to server) +00000000 16 03 02 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...| +00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..| +00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.| +00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h| +00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...| +00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........| +00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| +00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| +00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 02 00 01 |.Y(.....ia5.....| +00000090 01 16 03 02 00 24 e1 1a bf e9 fd 4c fb 56 41 82 |.....$.....L.VA.| +000000a0 c2 48 fc ca d9 d5 ec 2a 0a ee 63 25 e0 5f 53 cf |.H.....*..c%._S.| +000000b0 24 ff fe da 6f f5 8b 61 b7 b9 |$...o..a..| +>>> Flow 4 (server to client) +00000000 14 03 02 00 01 01 16 03 02 00 24 99 2c e7 fa d0 |..........$.,...| +00000010 29 d9 92 07 39 56 b0 0c ad 23 30 c8 d7 0b 38 da |)...9V...#0...8.| +00000020 6f d3 c7 f9 66 d2 ec 8c 52 85 cb db a6 22 50 |o...f...R...."P| +>>> Flow 5 (client to server) +00000000 17 03 02 00 1a 9f 70 c4 77 f3 0a a8 e0 1a 75 87 |......p.w.....u.| +00000010 ab 2a f1 23 52 79 9f 5c 8e af 5d ba 27 45 f9 15 |.*.#Ry.\..].'E..| +00000020 03 02 00 16 f0 28 f3 71 a0 97 6b ba 7e 97 81 85 |.....(.q..k.~...| +00000030 11 59 1b c9 fa a0 48 32 e9 65 |.Y....H2.e| diff --git a/src/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 b/src/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 new file mode 100644 index 0000000..ce92872 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 @@ -0,0 +1,86 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 a4 26 bb e9 70 |....Q...M...&..p| +00000010 57 4e ec f8 ea 23 01 75 c3 f3 a9 d4 d6 e8 71 2b |WN...#.u......q+| +00000020 01 5e c0 73 19 2b b9 d8 8e 3e d1 20 c8 c3 0a 22 |.^.s.+...>. ..."| +00000030 7b ee cd 2e c9 e8 95 db 90 db 70 f5 59 e6 90 65 |{.........p.Y..e| +00000040 35 87 a6 d4 bb dd 85 34 43 e8 66 49 00 9c 00 00 |5......4C.fI....| +00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +000002b0 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...| +00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..| +00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.| +00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h| +00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...| +00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........| +00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| +00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| +00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| +00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 64 6c |.....(........dl| +000000a0 08 78 1d 03 0c ed dd 01 30 d4 fb 7c 3f 24 45 cc |.x......0..|?$E.| +000000b0 f6 b2 e3 42 07 93 8f 34 a8 21 d1 b0 08 e3 |...B...4.!....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 75 9b 91 cd 7d |..........(u...}| +00000010 8d f7 3c a0 d6 5e d4 f2 24 1a 0a f3 04 b1 d9 0b |..<..^..$.......| +00000020 1d 31 ca 1c 8b e7 38 c0 8e 7d 12 19 89 33 28 4d |.1....8..}...3(M| +00000030 83 28 b6 |.(.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 7d fe 53 |.............}.S| +00000010 73 aa ca 3d f3 27 b7 01 56 9e e7 c9 6d 79 2a 97 |s..=.'..V...my*.| +00000020 b2 21 42 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.!B.............| +00000030 de bd 3e 9e 8f c0 98 ec bd b4 9b 89 90 a2 26 a8 |..>...........&.| +00000040 28 97 |(.| diff --git a/src/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 b/src/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 new file mode 100644 index 0000000..15394c7 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 @@ -0,0 +1,95 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 8a a8 2c 00 d8 |....Q...M....,..| +00000010 d8 87 53 14 1e 7b ff ca 19 a2 6d bc 47 6f 73 12 |..S..{....m.Gos.| +00000020 0d 54 6e 33 21 80 01 86 f8 81 9f 20 46 f6 8c e8 |.Tn3!...... F...| +00000030 8b 90 02 b2 da e2 83 3a 2a 0f b3 f7 96 2b f8 96 |.......:*....+..| +00000040 56 77 39 52 9e a1 bd 74 1e 2e b1 b0 00 3c 00 00 |Vw9R...t.....<..| +00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +000002b0 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...| +00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..| +00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.| +00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h| +00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...| +00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........| +00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| +00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| +00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| +00000090 01 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 |.....P..........| +000000a0 00 00 00 00 00 00 8f d8 ac 7f ec 16 9e d8 e9 f2 |................| +000000b0 ce 30 51 dc 87 e0 f9 80 57 66 d9 87 20 77 3a b1 |.0Q.....Wf.. w:.| +000000c0 43 db fc 36 f5 64 6e 96 e9 b8 e2 ab bb 00 48 36 |C..6.dn.......H6| +000000d0 60 9c 5a 7c 38 3f 13 e1 9c ef d9 15 96 91 56 e2 |`.Z|8?........V.| +000000e0 87 2e 23 1a 98 40 |..#..@| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 50 80 01 08 cc d8 |..........P.....| +00000010 08 a8 81 20 b2 bb 5b 50 79 74 4a b5 10 c4 7a 30 |... ..[PytJ...z0| +00000020 6c 46 d6 e5 36 6e 4d cc e5 0c 2c ab 3b de 92 45 |lF..6nM...,.;..E| +00000030 ee 20 58 a9 0f 03 26 3e 6c 05 a7 ef f2 7c a7 9b |. X...&>l....|..| +00000040 57 c0 20 8d d0 69 0e b0 5a cc e6 26 5f e2 c3 24 |W. ..i..Z..&_..$| +00000050 c4 db df 20 03 08 e1 aa 59 2b d2 |... ....Y+.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00000010 00 00 00 00 00 a2 dd a6 ff 57 60 80 dd 97 cf 20 |.........W`.... | +00000020 10 04 60 80 53 17 37 ce ce 39 b6 21 f4 06 61 aa |..`.S.7..9.!..a.| +00000030 49 7b f0 d5 e0 72 4c 6f 38 d2 ab af 1c 94 bd 5b |I{...rLo8......[| +00000040 1b ee 8a 9b e3 15 03 03 00 40 00 00 00 00 00 00 |.........@......| +00000050 00 00 00 00 00 00 00 00 00 00 ba 18 32 e7 6d f5 |............2.m.| +00000060 fa 2e 61 55 cc fe 3c 4d 19 fd 84 6d c4 2a 46 92 |..aU..>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 de 7a 77 5b eb |....Q...M...zw[.| +00000010 fa 84 a0 ac ba 3b ca 25 dc b3 c0 06 44 da 31 5c |.....;.%....D.1\| +00000020 27 e0 4e af be 47 07 5a a5 ab 20 20 72 b2 67 0c |'.N..G.Z.. r.g.| +00000030 7e 71 5d e3 55 89 91 27 7f 65 ac 71 c6 e8 a5 4a |~q].U..'.e.q...J| +00000040 ae e1 a2 0d 3f a6 62 08 17 7e 26 fd 00 9d 00 00 |....?.b..~&.....| +00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +000002b0 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...| +00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..| +00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.| +00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h| +00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...| +00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........| +00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| +00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| +00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| +00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 0b 7d |.....(.........}| +000000a0 83 0f 79 e2 4b ef d3 0e ff 57 d2 55 cd ea e9 be |..y.K....W.U....| +000000b0 8b 38 1e 33 b0 6a eb e3 aa 51 52 82 e6 15 |.8.3.j...QR...| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 1a a3 bb d4 c4 |..........(.....| +00000010 53 c7 5c 09 8c fb e7 51 41 73 d5 76 ef e6 40 9a |S.\....QAs.v..@.| +00000020 06 27 c6 e8 9f 1b 25 f5 d1 7b 39 b7 74 ab e8 83 |.'....%..{9.t...| +00000030 26 f6 40 |&.@| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 1c 0d 06 |................| +00000010 d2 25 8a 06 d9 b4 d6 76 89 1c c6 b7 22 9f 44 63 |.%.....v....".Dc| +00000020 a3 f9 89 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| +00000030 cb 34 e8 4b f7 b1 ab 1a 74 60 2c 2d cf a4 7d 9f |.4.K....t`,-..}.| +00000040 f4 b4 |..| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ALPN b/src/crypto/tls/testdata/Client-TLSv12-ALPN new file mode 100644 index 0000000..8b9a510 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ALPN @@ -0,0 +1,93 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 0e 01 00 01 0a 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 8f 00 05 00 05 01 00 00 00 00 00 0a 00 |................| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 10 00 10 00 0e 06 70 72 6f 74 6f |...........proto| +000000d0 32 06 70 72 6f 74 6f 31 00 12 00 00 00 2b 00 09 |2.proto1.....+..| +000000e0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| +000000f0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| +00000100 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| +00000110 cb 3b 74 |.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 66 02 00 00 62 03 03 2d b3 e1 a8 44 |....f...b..-...D| +00000010 c6 3e 20 b9 50 49 ab b8 48 c3 bf d6 f3 7b 2e 0a |.> .PI..H....{..| +00000020 8c 49 ba e5 8e 54 5e 02 59 01 75 20 f0 a0 60 c2 |.I...T^.Y.u ..`.| +00000030 81 df 62 f9 f8 7d 3c 3c ee 1e 0c 1d c2 11 58 7f |..b..}<<......X.| +00000040 e0 dc b1 6c 17 9e 19 60 ca c2 40 84 cc a8 00 00 |...l...`..@.....| +00000050 1a ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 10 |................| +00000060 00 09 00 07 06 70 72 6f 74 6f 31 16 03 03 02 59 |.....proto1....Y| +00000070 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 |...U..R..O0..K0.| +00000080 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b |.............?.[| +00000090 ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......| +000000a0 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |.0.1.0...U....Go| +000000b0 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f |1.0...U....Go Ro| +000000c0 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 |ot0...1601010000| +000000d0 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 |00Z..25010100000| +000000e0 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 |0Z0.1.0...U....G| +000000f0 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 |o1.0...U....Go0.| +00000100 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 |.0...*.H........| +00000110 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e |....0.......F}..| +00000120 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e |.'.H..(!.~...]..| +00000130 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be |RE.z6G....B[....| +00000140 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 |.y.@.Om..+.....g| +00000150 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 |....."8.J.ts+.4.| +00000160 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 |.....t{.X.la<..A| +00000170 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 |..++$#w[.;.u]. T| +00000180 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 |..c...$....P....| +00000190 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 |C...ub...R......| +000001a0 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff |...0..0...U.....| +000001b0 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 |......0...U.%..0| +000001c0 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 |...+.........+..| +000001d0 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 |.....0...U......| +000001e0 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 |.0.0...U........| +000001f0 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b |..CC>I..m....`0.| +00000200 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 |..U.#..0...H.IM.| +00000210 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 |~.1......n{0...U| +00000220 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e |....0...example.| +00000230 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d |golang0...*.H...| +00000240 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 |..........0.@+[P| +00000250 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 |.a...SX...(.X..8| +00000260 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 |....1Z..f=C.-...| +00000270 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 |... d8.$:....}.@| +00000280 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c | ._...a..v......| +00000290 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c |\.....l..s..Cw..| +000002a0 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 |.....@.a.Lr+...F| +000002b0 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 |..M...>...B...=.| +000002c0 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 |`.\!.;..........| +000002d0 00 a8 03 00 1d 20 7b 47 ec ef 4d 39 ec 65 b9 7c |..... {G..M9.e.|| +000002e0 08 da b5 41 0d 62 0b 52 29 24 25 3d 39 21 ed d3 |...A.b.R)$%=9!..| +000002f0 30 37 0c 15 66 49 08 04 00 80 4b 01 8e 80 78 ed |07..fI....K...x.| +00000300 d1 44 e5 98 a4 43 9a 73 b7 dc 67 72 83 29 f3 e3 |.D...C.s..gr.)..| +00000310 5b 72 ee d6 36 12 db bf ab d6 86 fd a8 54 a5 a0 |[r..6........T..| +00000320 0e 76 ca ea a7 f5 f2 e1 87 94 a7 c5 d8 69 b7 58 |.v...........i.X| +00000330 d2 f0 10 08 8c 08 ac bd aa 60 f5 45 20 15 77 71 |.........`.E .wq| +00000340 5a bb 2a 8b 0a 4b a3 08 71 88 82 01 3c bc 54 ba |Z.*..K..q...<.T.| +00000350 f4 42 7a 08 64 d7 57 5b dc ea 6a 72 e1 7d ca 96 |.Bz.d.W[..jr.}..| +00000360 d9 89 eb 60 9e d2 a4 f5 cb d5 45 d1 4d 09 4e 18 |...`......E.M.N.| +00000370 a2 4f 0f 59 97 a1 5f 7f 65 4f 16 03 03 00 04 0e |.O.Y.._.eO......| +00000380 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 b9 f7 58 6f d3 29 b8 41 35 06 b7 |.... ..Xo.).A5..| +00000040 55 85 c1 f0 63 fe 4f 5f 87 01 cc 67 0b f1 4c b4 |U...c.O_...g..L.| +00000050 ca 92 bd c0 6d |....m| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 68 92 93 84 bd |.......... h....| +00000010 0e de 33 1b db ca 54 b8 a0 2f 53 c5 76 de d2 c5 |..3...T../S.v...| +00000020 7a 54 bb db 0c 08 86 79 d2 6c 58 |zT.....y.lX| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 79 38 07 9b be 83 44 9a 3e 11 1a |.....y8....D.>..| +00000010 99 2f f2 4e 33 84 0b c7 8e ed c3 15 03 03 00 12 |./.N3...........| +00000020 ca bd 7e 59 04 8c e0 52 80 1e 56 1e af c1 5f 61 |..~Y...R..V..._a| +00000030 6c 6a |lj| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch b/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch new file mode 100644 index 0000000..62e7d11 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 9c 01 00 00 98 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 28 c0 2f |.............(./| +00000030 c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 c0 09 c0 14 |.+.0.,.'...#....| +00000040 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 c0 12 00 0a |.......<./.5....| +00000050 00 05 c0 11 c0 07 01 00 00 47 33 74 00 00 00 05 |.........G3t....| +00000060 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 |................| +00000070 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 0c 04 |................| +00000080 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 01 00 |................| +00000090 00 10 00 09 00 07 06 70 72 6f 74 6f 33 00 12 00 |.......proto3...| +000000a0 00 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 36 0e 9f 51 42 |....Y...U..6..QB| +00000010 82 65 fa b5 17 7a 86 d6 40 33 a9 67 d3 3d aa 2f |.e...z..@3.g.=./| +00000020 89 a0 39 82 af 16 30 8e 64 80 d4 20 23 a6 d0 12 |..9...0.d.. #...| +00000030 ff 8c fc b4 b5 47 ec 10 fe ba 73 fb 0f ab e8 1c |.....G....s.....| +00000040 15 c1 fb 11 c1 b2 e1 8a f7 5d 5b ad c0 2f 00 00 |.........][../..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 cd 0c 00 00 c9 03 00 17 41 04 11 b4 a9 10 7e 5c |........A.....~\| +000002d0 41 5e 39 12 15 a3 ed 5b 3e 5d 68 c8 ad 48 39 ef |A^9....[>]h..H9.| +000002e0 09 8b b1 a7 bf db 5f 54 49 cd d5 de 4d b3 47 4c |......_TI...M.GL| +000002f0 18 02 84 7c ec 75 4e d0 3e 8a d1 6c 80 83 98 64 |...|.uN.>..l...d| +00000300 4a 81 bc 8f 84 c7 e5 b4 2d fa 04 01 00 80 72 ee |J.......-.....r.| +00000310 41 38 f2 b8 a1 56 81 d8 04 78 75 05 f4 78 5f f2 |A8...V...xu..x_.| +00000320 2b 5d a2 46 23 9d 48 c8 63 a9 1d de a8 78 6e 99 |+].F#.H.c....xn.| +00000330 cd 59 6b 19 20 f5 b1 11 e1 f8 1c 5b 40 c3 b8 cd |.Yk. ......[@...| +00000340 66 a3 98 37 c5 c2 5c b7 d6 cc 61 b4 5e 97 fa dd |f..7..\...a.^...| +00000350 b7 85 5d b6 34 8c 39 4a 60 5a 03 20 47 7f e3 65 |..].4.9J`Z. G..e| +00000360 01 18 00 2c c3 eb be d4 aa 58 57 a9 5e 69 fb 3c |...,.....XW.^i.<| +00000370 fa c6 28 1a 5c f7 00 d5 21 e5 c1 30 db 84 38 c3 |..(.\...!..0..8.| +00000380 08 aa 08 5f c9 fd a0 b7 8e d0 66 77 bf 13 16 03 |..._......fw....| +00000390 03 00 04 0e 00 00 00 |.......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 4f 7e |.....(........O~| +00000060 9a 3a cc 74 a4 91 77 01 0b 0e 28 0a c5 bd 55 b7 |.:.t..w...(...U.| +00000070 9a 4c 40 4e e9 c9 46 d5 5f c5 e1 77 c3 f2 |.L@N..F._..w..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 62 4b 13 ef 22 |..........(bK.."| +00000010 f9 a8 8d ec 42 3a 36 80 5d a8 5b e9 60 d1 ba 65 |....B:6.].[.`..e| +00000020 2b d8 37 64 e5 12 b2 ef 84 75 87 0c 0f 3d 35 6e |+.7d.....u...=5n| +00000030 59 7c 51 |Y|Q| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 5f cd 4d |............._.M| +00000010 7b a7 c0 f9 6c 1f 80 93 cf 55 3b 12 c7 21 12 86 |{...l....U;..!..| +00000020 f6 b1 52 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..R.............| +00000030 fd 31 a4 4b d1 e9 f0 e0 18 b5 96 28 f7 b4 0c 29 |.1.K.......(...)| +00000040 8c 0c |..| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA new file mode 100644 index 0000000..e1fb8a8 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA @@ -0,0 +1,139 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 36 60 84 12 26 |....Y...U..6`..&| +00000010 51 e4 32 33 26 ef c3 31 bf ea ac 27 0f c3 fb cb |Q.23&..1...'....| +00000020 05 89 af df 56 a9 3f 14 6e 5e 2c 20 ad 6e 60 2d |....V.?.n^, .n`-| +00000030 94 aa e5 73 22 eb 68 92 77 1c 6c cb f4 5a 14 f2 |...s".h.w.l..Z..| +00000040 29 85 88 aa 2e 56 2a ad 80 e1 f0 b1 c0 09 00 00 |)....V*.........| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 87 2c |*............ .,| +00000280 f2 fd 8e b9 3d 5f 1c c8 bb 04 f5 1e 01 a8 ba d8 |....=_..........| +00000290 b6 8e 61 78 15 9e 3b a7 da 96 8e 77 d7 70 04 03 |..ax..;....w.p..| +000002a0 00 8b 30 81 88 02 42 01 dc e2 26 f9 18 39 da 7d |..0...B...&..9.}| +000002b0 bd a1 30 c6 6f dd cd aa a0 4f 71 cf 42 76 61 ba |..0.o....Oq.Bva.| +000002c0 e7 9f 09 b5 05 f2 76 c7 db 2a 93 83 3b 0b 3a cf |......v..*..;.:.| +000002d0 60 96 24 c8 af de 2c db 5a 29 1c 62 67 28 e9 d7 |`.$...,.Z).bg(..| +000002e0 57 5f 54 18 cc bf ee d1 d9 02 42 01 04 cf 67 0b |W_T.......B...g.| +000002f0 62 2c c2 17 a3 f4 f1 32 0f c5 b9 ae 3b 52 36 2b |b,.....2....;R6+| +00000300 f0 c0 60 49 08 e0 bf f5 7c 09 13 e4 b8 ba 08 c7 |..`I....|.......| +00000310 ea 74 a0 f5 88 45 e4 35 f1 c5 4e df fe 45 bc ca |.t...E.5..N..E..| +00000320 9c 5f c8 84 66 13 8f b3 c9 7e b2 ba d6 16 03 03 |._..f....~......| +00000330 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| +00000340 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000350 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| +00000360 03 02 02 02 04 02 05 02 06 02 00 00 16 03 03 00 |................| +00000370 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| +00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 92 0f 00 |...._X.;t.......| +00000240 00 8e 04 03 00 8a 30 81 87 02 42 01 8f ff aa 8c |......0...B.....| +00000250 bd 0c 94 39 34 e5 39 7b d2 12 26 8e 94 4a fd 68 |...94.9{..&..J.h| +00000260 f2 f5 5b 30 69 e1 42 3a 74 cd 9a 37 75 5c d2 a6 |..[0i.B:t..7u\..| +00000270 c9 7b b1 83 c1 d9 c5 55 1a af 3d 19 64 02 43 c0 |.{.....U..=.d.C.| +00000280 0a 1c 0e ff f4 42 85 fb d1 aa a2 52 1a 02 41 2f |.....B.....R..A/| +00000290 c6 23 d7 37 f1 36 75 0c 0f b4 49 14 c4 b4 d9 28 |.#.7.6u...I....(| +000002a0 c1 00 2d e4 d6 93 fd a0 f5 59 4e 45 0c a4 28 d4 |..-......YNE..(.| +000002b0 dc aa 7b 0b 28 29 12 94 f6 db 8c 23 af 81 7e ab |..{.().....#..~.| +000002c0 fd 12 ba 11 27 b2 10 87 89 61 9f 5d 6d 18 79 c5 |....'....a.]m.y.| +000002d0 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +000002e0 00 00 00 00 00 00 00 00 00 00 00 2d 3e 6e 02 fb |...........->n..| +000002f0 50 cc 37 62 77 17 08 ef 71 e6 06 23 82 ba 97 b7 |P.7bw...q..#....| +00000300 0f 38 f9 5e 05 63 4c c9 04 6e bd e4 78 76 32 3b |.8.^.cL..n..xv2;| +00000310 3a a7 9b de 30 ca ed fb 17 dc 40 |:...0.....@| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 19 62 a8 82 26 |..........@.b..&| +00000010 0f 0c 84 b4 31 6a 5d 12 65 dc b9 bc de 5c cb 77 |....1j].e....\.w| +00000020 5d 04 7e a8 10 1a a5 05 e5 ca 04 68 a2 81 ef f5 |].~........h....| +00000030 ae 4e bd f1 f3 ba 3f 6a 81 ae 71 9a 2f 31 e2 79 |.N....?j..q./1.y| +00000040 f1 4d 6c 0e a4 be 4b f7 80 6f 97 |.Ml...K..o.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +00000010 00 00 00 00 00 e9 f4 51 fe c1 02 35 de 6e 72 c3 |.......Q...5.nr.| +00000020 58 f3 01 4a f0 9d f2 34 df fc 0e 93 ef 46 2e 45 |X..J...4.....F.E| +00000030 5e 60 43 52 33 15 03 03 00 30 00 00 00 00 00 00 |^`CR3....0......| +00000040 00 00 00 00 00 00 00 00 00 00 ac 82 d6 47 42 40 |.............GB@| +00000050 d6 6c 6d e3 b6 c6 4a b7 83 ce 6f 3f 33 ad e7 eb |.lm...J...o?3...| +00000060 bf 59 82 50 8a 18 e3 13 46 6c |.Y.P....Fl| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA new file mode 100644 index 0000000..7ae186d --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA @@ -0,0 +1,139 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 2a 52 95 57 8c |....Y...U..*R.W.| +00000010 55 3f d7 82 f0 3f af 57 a1 82 86 00 3a 6b c0 07 |U?...?.W....:k..| +00000020 4d c3 0e 80 cc 37 2d 51 f4 d3 e2 20 4a f6 c9 8a |M....7-Q... J...| +00000030 d2 98 4a ff 22 66 11 da 6f 9a a0 17 b9 96 b0 86 |..J."f..o.......| +00000040 29 e0 39 86 0a 00 42 78 30 60 61 99 c0 2f 00 00 |).9...Bx0`a../..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 fa 3a 8f b7 50 10 38 |........ .:..P.8| +000002d0 04 9d fb c4 e4 76 6d 93 86 b2 8a d7 5b 8f 8d 45 |.....vm.....[..E| +000002e0 41 b7 ba 54 bc cc 7b 07 3c 08 04 00 80 a1 14 65 |A..T..{.<......e| +000002f0 f6 48 29 ba 08 86 52 65 dd 08 ef b8 b8 77 ef fd |.H)...Re.....w..| +00000300 8a ca dc 37 f8 69 fa 04 69 73 84 07 b2 45 f0 a2 |...7.i..is...E..| +00000310 8c 69 f7 7c 4c 5c 95 c5 66 80 ad 93 04 67 4b 3d |.i.|L\..f....gK=| +00000320 f8 53 a9 33 b3 c0 40 17 62 34 f0 f3 1e d2 23 93 |.S.3..@.b4....#.| +00000330 29 52 bc f4 f0 72 58 b9 76 9c 7b 54 b0 d5 d1 ab |)R...rX.v.{T....| +00000340 b3 1b ae f7 f3 46 6a 07 7f f4 91 ee 46 d6 85 43 |.....Fj.....F..C| +00000350 ea c6 f9 f5 47 89 85 39 72 35 af b4 03 e9 a2 ea |....G..9r5......| +00000360 a8 19 09 ea b3 d2 c2 38 59 65 d1 2c 18 16 03 03 |.......8Ye.,....| +00000370 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| +00000380 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000390 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| +000003a0 03 02 02 02 04 02 05 02 06 02 00 00 16 03 03 00 |................| +000003b0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| +00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 91 0f 00 |...._X.;t.......| +00000240 00 8d 04 03 00 89 30 81 86 02 41 63 34 72 b4 70 |......0...Ac4r.p| +00000250 45 46 9c 3c 06 2c f5 ab d4 dd a7 91 69 9c 65 0f |EF.<.,......i.e.| +00000260 4b d9 2d 90 3d d1 f2 4d 2a 6a 43 4f a7 fd b5 22 |K.-.=..M*jCO..."| +00000270 83 61 e2 14 33 8c bc 8a 81 52 a1 f4 69 a7 12 c9 |.a..3....R..i...| +00000280 c3 28 69 85 6d c1 b0 5d d3 5e ac 4e 02 41 35 cd |.(i.m..].^.N.A5.| +00000290 3b c3 f6 ea 9e df 2a a1 ea 80 55 40 d2 13 d3 ff |;.....*...U@....| +000002a0 b2 59 bb a0 c7 10 67 6e 9b dc 6c 3c 97 08 07 e0 |.Y....gn..l<....| +000002b0 db da 79 6b 0e 6c a0 23 13 b1 02 32 ab ee 62 69 |..yk.l.#...2..bi| +000002c0 f9 d5 7f 24 2e 26 94 36 a4 36 53 63 dd 90 20 14 |...$.&.6.6Sc.. .| +000002d0 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 00 |.........(......| +000002e0 00 00 a7 30 0e b0 f7 ba 51 35 c9 4c c2 24 90 5e |...0....Q5.L.$.^| +000002f0 b2 59 57 5d 96 9d ad d1 1e 7d b0 35 09 9c c5 49 |.YW].....}.5...I| +00000300 bd 82 |..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 09 ff 53 e8 0f |..........(..S..| +00000010 ad 86 30 ca 96 54 da 72 45 13 7a cd 51 f6 b3 a5 |..0..T.rE.z.Q...| +00000020 27 4c 7c 26 81 6d 76 6f 19 8e f3 13 77 49 59 73 |'L|&.mvo....wIYs| +00000030 4e 98 3e |N.>| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 99 7b 4c |..............{L| +00000010 1d 0a b1 89 0d ac fa a7 39 eb 9a ff 8f 06 60 d1 |........9.....`.| +00000020 88 e8 ef 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| +00000030 99 42 7f c8 35 79 f3 a0 10 5c 05 25 c1 ac ab aa |.B..5y...\.%....| +00000040 d5 9e |..| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 new file mode 100644 index 0000000..9ecd8e3 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 @@ -0,0 +1,119 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 5c 37 b1 d2 6c |....Y...U..\7..l| +00000010 bc dd 26 8c 4e f7 04 80 09 3c fd 76 23 d4 52 16 |..&.N....<.v#.R.| +00000020 df 0e 79 ab f4 cf 8c f3 61 31 c6 20 7d 7a 1d 8f |..y.....a1. }z..| +00000030 09 3e 2b 25 04 7f 0f 0a a7 0c 03 fd 9c 09 f3 5d |.>+%...........]| +00000040 96 75 f8 da 5b 6b 1b fb ca d7 ec 7a cc a8 00 00 |.u..[k.....z....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 aa c7 43 e7 1e 3b 2b |........ ..C..;+| +000002d0 28 c2 68 aa 83 cc 85 63 68 c4 b8 4d fb 18 fa b9 |(.h....ch..M....| +000002e0 3e 9a f2 7c 04 33 7f 48 6b 08 04 00 80 28 28 c7 |>..|.3.Hk....((.| +000002f0 84 79 65 11 07 43 7a ce f1 d6 cb 0e fe 6a 24 2c |.ye..Cz......j$,| +00000300 f3 f0 e5 9c 80 a6 c7 41 c7 51 f2 84 be 6e 58 df |.......A.Q...nX.| +00000310 f2 d2 d4 d9 62 08 c8 35 75 b9 8e 49 c2 98 b0 9d |....b..5u..I....| +00000320 32 aa db bf 03 c1 61 83 f7 20 d7 ec 07 27 5e 45 |2.....a.. ...'^E| +00000330 dc d6 92 4c a1 4f 4e 7c 53 c5 ca 42 48 40 0f 83 |...L.ON|S..BH@..| +00000340 fc 9d 60 a1 7c 43 d1 f5 f8 3f fe 50 3f d0 03 bc |..`.|C...?.P?...| +00000350 3e 8b ac 69 8f ae b6 9a c8 d4 98 84 30 f1 79 9b |>..i........0.y.| +00000360 af 5d 4e 41 2a 7c 46 22 df 46 42 74 f6 16 03 03 |.]NA*|F".FBt....| +00000370 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| +00000380 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000390 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| +000003a0 03 02 02 02 04 02 05 02 06 02 00 00 16 03 03 00 |................| +000003b0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 01 3c 0b 00 01 38 00 01 35 00 01 32 30 |....<...8..5..20| +00000010 82 01 2e 30 81 e1 a0 03 02 01 02 02 10 17 d1 81 |...0............| +00000020 93 be 2a 8c 21 20 10 25 15 e8 34 23 4f 30 05 06 |..*.! .%..4#O0..| +00000030 03 2b 65 70 30 12 31 10 30 0e 06 03 55 04 0a 13 |.+ep0.1.0...U...| +00000040 07 41 63 6d 65 20 43 6f 30 1e 17 0d 31 39 30 35 |.Acme Co0...1905| +00000050 31 36 32 31 35 34 32 36 5a 17 0d 32 30 30 35 31 |16215426Z..20051| +00000060 35 32 31 35 34 32 36 5a 30 12 31 10 30 0e 06 03 |5215426Z0.1.0...| +00000070 55 04 0a 13 07 41 63 6d 65 20 43 6f 30 2a 30 05 |U....Acme Co0*0.| +00000080 06 03 2b 65 70 03 21 00 0b e0 b5 60 b5 e2 79 30 |..+ep.!....`..y0| +00000090 3d be e3 1e e0 50 b1 04 c8 6d c7 78 6c 69 2f c5 |=....P...m.xli/.| +000000a0 14 ad 9a 63 6f 79 12 91 a3 4d 30 4b 30 0e 06 03 |...coy...M0K0...| +000000b0 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 |U...........0...| +000000c0 55 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 |U.%..0...+......| +000000d0 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 |.0...U.......0.0| +000000e0 16 06 03 55 1d 11 04 0f 30 0d 82 0b 65 78 61 6d |...U....0...exam| +000000f0 70 6c 65 2e 63 6f 6d 30 05 06 03 2b 65 70 03 41 |ple.com0...+ep.A| +00000100 00 fc 19 17 2a 94 a5 31 fa 29 c8 2e 7f 5b a0 5d |....*..1.)...[.]| +00000110 8a 4e 34 40 39 d6 b3 10 dc 19 fe a0 22 71 b3 f5 |.N4@9......."q..| +00000120 8f a1 58 0d cd f4 f1 85 24 bf e6 3d 14 df df ed |..X.....$..=....| +00000130 0e e1 17 d8 11 a2 60 d0 8a 37 23 2a c2 46 aa 3a |......`..7#*.F.:| +00000140 08 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 |.....%...! /.}.G| +00000150 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +00000160 c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 48 |......_X.;t....H| +00000170 0f 00 00 44 08 07 00 40 07 e0 a5 14 ca cf 31 d7 |...D...@......1.| +00000180 99 96 c7 c7 d8 d8 a7 f7 82 e7 c6 c0 12 5d 91 5a |.............].Z| +00000190 bc eb 4a c0 59 c6 5b 7b 03 df 2a ff 48 ca 55 d8 |..J.Y.[{..*.H.U.| +000001a0 3e 10 c1 94 2c 03 b2 e7 16 83 4d e5 5a 3d 8a 48 |>...,.....M.Z=.H| +000001b0 2f e5 c4 59 de 6f 47 05 14 03 03 00 01 01 16 03 |/..Y.oG.........| +000001c0 03 00 20 ae 35 81 df 88 0e a3 2e 67 3f 33 02 3d |.. .5......g?3.=| +000001d0 b8 7e 47 db cb be 05 c7 ba 43 dc 5b 52 3b 4b ca |.~G......C.[R;K.| +000001e0 c0 dc 78 |..x| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 63 23 49 7c 83 |.......... c#I|.| +00000010 1a 8b cd 48 02 e7 86 4d ab 8b 3c 4f 40 27 a6 48 |...H...M..>> Flow 5 (client to server) +00000000 17 03 03 00 16 aa b4 5b 75 04 96 c5 4a e3 2a fb |.......[u...J.*.| +00000010 be 29 32 9e c5 e4 15 bd 38 df 69 15 03 03 00 12 |.)2.....8.i.....| +00000020 50 4d b6 c0 95 e6 5a db f2 b7 ea 02 cb 3e 01 ea |PM....Z......>..| +00000030 35 0d |5.| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 new file mode 100644 index 0000000..35ec347 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 @@ -0,0 +1,137 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 16 f7 21 0a 97 |....Y...U....!..| +00000010 89 11 ec c3 c4 05 41 79 72 60 40 6d ec 78 90 26 |......Ayr`@m.x.&| +00000020 0c a4 f8 5d d5 27 e9 70 bb 40 21 20 b0 bb 98 5d |...].'.p.@! ...]| +00000030 a2 27 08 1e 4a fe f9 e1 cf a5 79 d3 eb c6 40 f7 |.'..J.....y...@.| +00000040 ee 4f 0b fa a1 bb 09 62 07 24 30 b7 c0 30 00 00 |.O.....b.$0..0..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 39 1f 7e 66 c8 20 24 |........ 9.~f. $| +000002d0 cf 8e 51 f6 bf 2a 01 a9 3b 51 19 f1 9d 32 b6 fa |..Q..*..;Q...2..| +000002e0 05 3b 90 c9 a3 8b 49 92 2a 08 04 00 80 da 65 ad |.;....I.*.....e.| +000002f0 fa f9 d5 f6 d7 13 34 d2 ab ac ea 57 37 69 c6 b1 |......4....W7i..| +00000300 91 ee 89 b7 04 6b 17 fb 80 23 df df ef a1 62 9b |.....k...#....b.| +00000310 e4 0a 4e ca b0 35 b2 d3 2a cf 4f c1 e3 d9 37 78 |..N..5..*.O...7x| +00000320 aa c8 59 f8 25 c7 43 51 19 6c c7 50 90 a4 2c 92 |..Y.%.CQ.l.P..,.| +00000330 01 0e 8d ff f0 88 4b af 1d 03 ee 51 8b 18 e4 ee |......K....Q....| +00000340 35 48 16 e7 4c 26 1d d8 af 91 b1 75 38 b5 65 42 |5H..L&.....u8.eB| +00000350 8e 60 c7 f9 25 a7 85 35 72 41 6f f6 c4 61 1d c0 |.`..%..5rAo..a..| +00000360 c8 cf da ae 31 5e 2e d6 9c ca f1 d6 31 16 03 03 |....1^......1...| +00000370 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| +00000380 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000390 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| +000003a0 03 02 02 02 04 02 05 02 06 02 00 00 16 03 03 00 |................| +000003b0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| +00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| +00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.| +00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1| +00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C| +00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523| +00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231| +00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac| +00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.| +00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....| +000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x| +000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.| +000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4| +000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..| +000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#| +000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....| +00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......| +00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..| +00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U| +00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U| +00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.| +00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0| +00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........| +00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..| +00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]| +000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A| +000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...| +000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...| +000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| +000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| +000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| +00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| +00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| +00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| +00000230 88 0f 00 00 84 08 04 00 80 56 1c 58 51 d8 51 bc |.........V.XQ.Q.| +00000240 8e 4b b8 24 64 85 81 d2 26 9b 38 bf 13 19 e7 0a |.K.$d...&.8.....| +00000250 f7 94 e8 b5 94 bf 6f ae f2 07 1a 46 24 38 7b 8b |......o....F$8{.| +00000260 2f a6 da 91 1a 5f 7d 3f cf c4 1b 14 9c 44 8e 6a |/...._}?.....D.j| +00000270 6b c8 c4 60 c6 15 e6 f2 c0 45 e7 46 c4 32 06 b1 |k..`.....E.F.2..| +00000280 46 5e 25 1d ba f7 d8 81 b0 6b 50 40 81 b1 93 89 |F^%......kP@....| +00000290 cb 90 ae 10 b1 db 08 99 e6 0e 8f 17 0f 4d a7 a7 |.............M..| +000002a0 f5 42 8a be ca d6 75 c4 32 44 22 ab df cf 22 f7 |.B....u.2D"...".| +000002b0 58 d9 9f 52 c2 04 c0 81 59 14 03 03 00 01 01 16 |X..R....Y.......| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 eb 5a 97 41 |...(.........Z.A| +000002d0 1d da 2b 81 da 7a b7 9a f8 5e fe 50 75 e5 a4 6a |..+..z...^.Pu..j| +000002e0 21 90 b7 3d 4e bc 44 cf 86 8f cd c3 |!..=N.D.....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 93 a5 d4 a8 16 |..........(.....| +00000010 4e a2 b2 c3 b9 ce dd 0e 57 49 7c eb 92 e4 e7 e3 |N.......WI|.....| +00000020 a8 55 3a 56 54 53 92 b8 ce 15 e3 c3 c2 da 52 01 |.U:VTS........R.| +00000030 6f 35 fd |o5.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 5b 20 4f |.............[ O| +00000010 e9 3f 09 28 6e 88 5d 1d 57 90 2c 35 74 37 d1 df |.?.(n.].W.,5t7..| +00000020 aa 39 9b 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.9..............| +00000030 bb e3 77 62 e5 c9 78 f4 a5 09 93 b0 20 9a 1b a4 |..wb..x..... ...| +00000040 48 44 |HD| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA new file mode 100644 index 0000000..110f689 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA @@ -0,0 +1,138 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 68 dc 2e 5e 8e |....Y...U..h..^.| +00000010 80 38 0e 65 a3 b0 f6 a0 c0 8f 1e 62 ef 1d 5a 54 |.8.e.......b..ZT| +00000020 82 dc 9c 68 77 88 57 dd f3 9d c2 20 4e 56 dd 44 |...hw.W.... NV.D| +00000030 a0 46 67 4c 09 2b d5 e6 fe 15 fb b3 8e 19 ef a3 |.FgL.+..........| +00000040 8e 5c a9 70 00 cf 96 d7 3b 8b c9 64 c0 09 00 00 |.\.p....;..d....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 24 d0 |*............ $.| +00000280 e5 11 4c 95 2c 96 58 62 01 df 20 c8 24 ce 29 a2 |..L.,.Xb.. .$.).| +00000290 1a 3e 97 e2 df 29 49 e6 3a e8 c2 d3 72 49 04 03 |.>...)I.:...rI..| +000002a0 00 8a 30 81 87 02 41 71 15 8d 50 f6 69 40 d7 cd |..0...Aq..P.i@..| +000002b0 da c9 c3 ee 37 c2 5f c3 89 62 23 e0 ef 37 f9 9e |....7._..b#..7..| +000002c0 2a 26 85 10 56 28 08 de 49 3b fa 03 f3 14 4b 3a |*&..V(..I;....K:| +000002d0 b2 3d de 84 d2 08 8d 4e 59 3e 80 8f 6a 44 af 6f |.=.....NY>..jD.o| +000002e0 be ee 08 ae 35 40 42 bc 02 42 00 f3 e9 89 a5 7f |....5@B..B......| +000002f0 9c 50 7c 07 34 e4 cf f0 2b 0f cf f7 68 57 fa fd |.P|.4...+...hW..| +00000300 2f 52 04 f8 90 7b 97 eb c3 e0 cc 68 f7 bf 22 21 |/R...{.....h.."!| +00000310 62 b3 51 c8 a4 30 38 c5 88 46 df 55 21 21 d0 4f |b.Q..08..F.U!!.O| +00000320 6f 95 7b 5f 5a c6 98 dd 2d d1 0a 95 16 03 03 00 |o.{_Z...-.......| +00000330 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 06 |:...6...@.......| +00000340 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 08 |................| +00000350 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 03 |................| +00000360 02 02 02 04 02 05 02 06 02 00 00 16 03 03 00 04 |................| +00000370 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| +00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| +00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.| +00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1| +00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C| +00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523| +00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231| +00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac| +00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.| +00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....| +000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x| +000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.| +000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4| +000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..| +000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#| +000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....| +00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......| +00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..| +00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U| +00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U| +00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.| +00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0| +00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........| +00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..| +00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]| +000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A| +000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...| +000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...| +000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| +000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| +000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| +00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| +00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| +00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| +00000230 88 0f 00 00 84 08 04 00 80 84 38 78 4d dd 9f 84 |..........8xM...| +00000240 ae cb b8 2f e9 f3 76 66 41 56 f6 ed a5 fb 8b f2 |.../..vfAV......| +00000250 43 0f 27 56 9e 7d a8 06 3e 8f ad b0 17 d5 d6 52 |C.'V.}..>......R| +00000260 f4 88 e5 af 55 5b 55 fc 26 c1 a9 d5 a9 34 2b 50 |....U[U.&....4+P| +00000270 96 09 db 59 cc f4 e8 cf 84 6f 9d b1 fd 3b a4 66 |...Y.....o...;.f| +00000280 66 43 74 6d 4f e5 52 2c 22 2d c9 4c 67 3d ff 3d |fCtmO.R,"-.Lg=.=| +00000290 c2 79 b3 b1 85 56 08 cc 02 7c 53 a7 be 39 04 21 |.y...V...|S..9.!| +000002a0 fb db fe ff 1b a6 c7 7a e9 4c 11 c3 34 a6 7c 4f |.......z.L..4.|O| +000002b0 23 61 d9 47 b0 6c ae cb 72 14 03 03 00 01 01 16 |#a.G.l..r.......| +000002c0 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 |...@............| +000002d0 00 00 00 00 d3 95 4a 65 d9 8e 3d 9c 2b 18 67 aa |......Je..=.+.g.| +000002e0 e0 d7 a6 dd fb af 42 06 0d 56 cc 3d 12 3e 7e 95 |......B..V.=.>~.| +000002f0 18 6e 97 d6 cc 84 eb 90 a1 c3 b6 6e 3c 42 d1 2e |.n.........n>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 71 ee 1d 4f 55 |..........@q..OU| +00000010 b4 47 3d 26 52 5a 00 a5 ce 0e 31 6c 2d 09 95 df |.G=&RZ....1l-...| +00000020 fb 74 30 89 32 3d 47 29 58 ee 61 70 74 18 8c 01 |.t0.2=G)X.apt...| +00000030 e3 16 d7 6e 3d a1 30 75 61 b8 99 e4 c5 82 82 d5 |...n=.0ua.......| +00000040 75 f6 e1 b4 f8 97 77 92 00 64 06 |u.....w..d.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +00000010 00 00 00 00 00 e2 68 77 75 6a f8 3c 3d 2c 96 52 |......hwuj.<=,.R| +00000020 2d fc d5 3b d3 17 c0 29 df 99 f1 09 23 13 9f 89 |-..;...)....#...| +00000030 dd 21 15 23 36 15 03 03 00 30 00 00 00 00 00 00 |.!.#6....0......| +00000040 00 00 00 00 00 00 00 00 00 00 37 4e ac 91 80 02 |..........7N....| +00000050 4f 4a 9f b4 3c 0e 24 87 c8 d0 41 24 ce 01 e2 bb |OJ..<.$...A$....| +00000060 18 af bc ce 09 4b 41 f6 db 08 |.....KA...| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA new file mode 100644 index 0000000..cbc4bcc --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA @@ -0,0 +1,137 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 b6 96 f2 bc ed |....Y...U.......| +00000010 1b 14 73 de 12 10 cc e9 4d f2 c7 8b 46 d8 63 55 |..s.....M...F.cU| +00000020 8f 04 33 ec 89 b5 70 93 01 1c f2 20 72 82 e1 16 |..3...p.... r...| +00000030 9c 0e 70 25 84 2c 09 a6 4f 19 c0 ed 44 d6 98 13 |..p%.,..O...D...| +00000040 97 f6 19 08 d4 b6 d3 ad 82 96 ef db c0 2f 00 00 |............./..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 21 1b d1 91 16 9c c1 |........ !......| +000002d0 51 52 39 07 6b 6d ab 07 28 f7 d0 ae 02 13 5e 73 |QR9.km..(.....^s| +000002e0 5b 51 30 96 27 57 56 e5 37 08 04 00 80 6a 13 82 |[Q0.'WV.7....j..| +000002f0 97 81 ea 32 51 cb cb 8e 3b ee e5 dd 4f 80 20 50 |...2Q...;...O. P| +00000300 c9 f0 19 9b d5 1b ae 21 f7 e6 24 4e a3 22 ec b9 |.......!..$N."..| +00000310 25 6e 77 19 12 08 16 8a c7 c1 db 29 e9 be 05 55 |%nw........)...U| +00000320 09 c1 6e 44 c3 d7 bd 18 80 c8 1f 42 53 3b e6 09 |..nD.......BS;..| +00000330 00 29 20 c4 94 04 97 6f f7 e6 f4 3b 66 77 2f e5 |.) ....o...;fw/.| +00000340 de 96 6f c3 67 c5 ce 4b 5e 4b 0e 90 02 fc 32 7f |..o.g..K^K....2.| +00000350 71 f4 63 76 37 57 75 30 fb 1b f5 99 98 5f c3 b1 |q.cv7Wu0....._..| +00000360 fb e3 76 ad 8e 2f 7a 72 86 ed 34 18 98 16 03 03 |..v../zr..4.....| +00000370 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| +00000380 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000390 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| +000003a0 03 02 02 02 04 02 05 02 06 02 00 00 16 03 03 00 |................| +000003b0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| +00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| +00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.| +00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1| +00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C| +00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523| +00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231| +00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac| +00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.| +00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....| +000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x| +000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.| +000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4| +000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..| +000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#| +000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....| +00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......| +00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..| +00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U| +00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U| +00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.| +00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0| +00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........| +00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..| +00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]| +000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A| +000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...| +000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...| +000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| +000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| +000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| +00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| +00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| +00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| +00000230 88 0f 00 00 84 08 04 00 80 90 53 1e fc 7c 63 b0 |..........S..|c.| +00000240 98 c5 19 40 fb 4f cf c3 53 51 81 68 54 c7 49 38 |...@.O..SQ.hT.I8| +00000250 0c 41 f0 12 7d a6 e4 8a 4e 77 97 49 5a 07 7d 30 |.A..}...Nw.IZ.}0| +00000260 fa df 77 2f 51 cf 37 65 07 0b 2c 91 15 43 1d c9 |..w/Q.7e..,..C..| +00000270 69 46 e2 26 66 72 98 ec 62 1a 22 ae e8 3e 3a 28 |iF.&fr..b."..>:(| +00000280 17 83 b9 74 57 59 a2 ec 31 95 17 1f c3 ec 9a 01 |...tWY..1.......| +00000290 f2 d4 07 d5 ee d5 0e f2 f4 75 3b d6 b8 df aa ad |.........u;.....| +000002a0 0b 87 37 30 43 7e c1 b1 e1 0d 7e 90 3d 87 9d 93 |..70C~....~.=...| +000002b0 d7 06 57 18 5c 12 c2 32 0d 14 03 03 00 01 01 16 |..W.\..2........| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 ff 2a ae f8 |...(.........*..| +000002d0 c9 1c bd 3f 62 0e 68 42 e7 96 ec ee c0 fa 71 34 |...?b.hB......q4| +000002e0 f1 e2 67 76 82 cf c3 2a fb b2 5a c1 |..gv...*..Z.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 da 70 e7 aa 1b |..........(.p...| +00000010 6c 66 cb 9b 07 d9 4e 87 6f 87 60 fb 46 f5 e9 33 |lf....N.o.`.F..3| +00000020 48 59 ff 3e b5 bf 0b 0c b2 39 79 64 f6 3c 2e 95 |HY.>.....9yd.<..| +00000030 04 51 87 |.Q.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 21 29 d2 |.............!).| +00000010 27 05 2d b4 a2 bf ea f2 96 8a 61 c9 91 75 9f 0f |'.-.......a..u..| +00000020 50 4a 76 15 03 03 00 1a 00 00 00 00 00 00 00 02 |PJv.............| +00000030 a9 40 eb 86 b2 f0 85 a2 75 bc 4e 09 8c c9 ca 31 |.@......u.N....1| +00000040 e5 49 |.I| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 new file mode 100644 index 0000000..b8ecfff --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 @@ -0,0 +1,134 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 ad e1 a7 5e 0b |....Y...U.....^.| +00000010 b8 bd 9d 05 c2 8e 6c f2 ea 7d a1 c8 32 cc d1 74 |......l..}..2..t| +00000020 ba 86 75 98 33 27 39 c3 0a 6f 49 20 2b 37 9a 0f |..u.3'9..oI +7..| +00000030 9b de 1f 1d 5f 2b 45 29 6c 9b 33 c6 bc c1 15 a4 |...._+E)l.3.....| +00000040 19 9b 70 6c 15 eb 4a 92 92 5f b7 6b c0 2f 00 00 |..pl..J.._.k./..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 ba ad fb 1e 28 95 96 |........ ....(..| +000002d0 f3 62 9d 97 87 0f fd fc a9 91 a2 4b 8d 69 ec 8f |.b.........K.i..| +000002e0 7d 49 08 6e fe 7d b3 5b 03 04 01 00 80 86 57 23 |}I.n.}.[......W#| +000002f0 58 bb 9a 50 d8 bb 99 d9 f5 cc 66 43 38 f0 14 8a |X..P......fC8...| +00000300 cb 6d 8b c0 83 52 f8 53 75 94 07 e3 12 2c 10 bb |.m...R.Su....,..| +00000310 f3 9b 74 84 1f 11 f3 06 c3 f4 df db f0 1e 0a cd |..t.............| +00000320 1b 45 18 44 88 67 79 ca 3e 6e 2b 73 c2 10 84 d8 |.E.D.gy.>n+s....| +00000330 7b c5 2e 81 7d 53 19 46 09 35 35 8b 66 8a a8 cc |{...}S.F.55.f...| +00000340 20 ba 20 15 9f d1 27 9c 6b 3c bb 48 79 4a 7e 11 | . ...'.k<.HyJ~.| +00000350 da e3 26 5b 3a 95 da 4d bd 86 3e 8c 97 55 7c 22 |..&[:..M..>..U|"| +00000360 a1 d3 88 61 ae e1 3b 51 25 c6 01 7e 10 16 03 03 |...a..;Q%..~....| +00000370 00 0c 0d 00 00 08 01 01 00 02 04 01 00 00 16 03 |................| +00000380 03 00 04 0e 00 00 00 |.......| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| +00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| +00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.| +00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1| +00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C| +00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523| +00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231| +00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac| +00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.| +00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....| +000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x| +000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.| +000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4| +000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..| +000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#| +000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....| +00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......| +00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..| +00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U| +00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U| +00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.| +00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0| +00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........| +00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..| +00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]| +000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A| +000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...| +000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...| +000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| +000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| +000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| +00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| +00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| +00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| +00000230 88 0f 00 00 84 04 01 00 80 12 a4 42 13 85 6f 92 |...........B..o.| +00000240 6d 26 5d 05 3c b7 80 ab a9 e0 74 3d 89 67 79 a0 |m&].<.....t=.gy.| +00000250 9f e1 a9 20 d8 82 e2 22 99 38 03 fe 32 d9 1f c7 |... ...".8..2...| +00000260 39 1e 27 31 59 05 eb aa bc 2c 10 eb f0 82 65 65 |9.'1Y....,....ee| +00000270 ce b2 e9 83 67 21 43 03 19 2d 14 9f c3 db bc dc |....g!C..-......| +00000280 59 66 95 d7 4e 09 3c f0 f2 4a 39 f7 db c4 0c 4e |Yf..N.<..J9....N| +00000290 73 e2 d6 59 f1 bc 06 d8 75 df 32 b7 f1 b4 01 98 |s..Y....u.2.....| +000002a0 4f 93 43 a3 a6 09 da cd 1c ee 26 65 ab d1 2a 56 |O.C.......&e..*V| +000002b0 74 32 24 46 27 f3 d9 6a df 14 03 03 00 01 01 16 |t2$F'..j........| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 68 27 5e 44 |...(........h'^D| +000002d0 d7 73 26 f6 51 86 01 f5 f3 5d 61 a0 05 cd c3 00 |.s&.Q....]a.....| +000002e0 85 6f ea 56 85 1e 7a c3 4c d3 6d 64 |.o.V..z.L.md| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 81 f3 33 d8 2a |..........(..3.*| +00000010 57 45 53 2c ee 68 8b 79 ed 07 dc 90 c3 a7 84 38 |WES,.h.y.......8| +00000020 8c 33 03 e9 c6 51 04 b2 73 8a 8b 81 12 eb 6c 5f |.3...Q..s.....l_| +00000030 a3 8f 5e |..^| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 e5 c6 d7 |................| +00000010 4d e0 d1 0c ff a0 66 c4 71 53 af 7e 16 01 3d 2e |M.....f.qS.~..=.| +00000020 6c ab 90 15 03 03 00 1a 00 00 00 00 00 00 00 02 |l...............| +00000030 92 12 87 24 c8 7e 74 23 df f7 23 49 01 9a dd 3b |...$.~t#..#I...;| +00000040 2c 68 |,h| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS new file mode 100644 index 0000000..de05fec --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS @@ -0,0 +1,142 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 61 fe 1e 35 33 |....Y...U..a..53| +00000010 4b b4 dd 9b 0f 55 58 f4 0c c5 b2 73 51 7b 84 e7 |K....UX....sQ{..| +00000020 25 f7 8f 12 5a 12 11 e1 7b e6 52 20 ad 86 a9 f9 |%...Z...{.R ....| +00000030 7f 6a 30 da 79 23 c3 c4 dc 88 f6 19 1d cc 16 8b |.j0.y#..........| +00000040 96 74 84 ce 53 56 65 e2 cb 94 61 0c c0 2f 00 00 |.t..SVe...a../..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 66 0b 00 02 62 00 02 5f 00 02 5c 30 82 02 |..f...b.._..\0..| +00000070 58 30 82 01 8d a0 03 02 01 02 02 11 00 f2 99 26 |X0.............&| +00000080 eb 87 ea 8a 0d b9 fc c2 47 34 7c 11 b0 30 41 06 |........G4|..0A.| +00000090 09 2a 86 48 86 f7 0d 01 01 0a 30 34 a0 0f 30 0d |.*.H......04..0.| +000000a0 06 09 60 86 48 01 65 03 04 02 01 05 00 a1 1c 30 |..`.H.e........0| +000000b0 1a 06 09 2a 86 48 86 f7 0d 01 01 08 30 0d 06 09 |...*.H......0...| +000000c0 60 86 48 01 65 03 04 02 01 05 00 a2 03 02 01 20 |`.H.e.......... | +000000d0 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 6d |0.1.0...U....Acm| +000000e0 65 20 43 6f 30 1e 17 0d 31 37 31 31 32 33 31 36 |e Co0...17112316| +000000f0 31 36 31 30 5a 17 0d 31 38 31 31 32 33 31 36 31 |1610Z..181123161| +00000100 36 31 30 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 |610Z0.1.0...U...| +00000110 07 41 63 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a |.Acme Co0..0...*| +00000120 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 |.H............0.| +00000130 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc 06 |......F}...'.H..| +00000140 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 47 |(!.~...]..RE.z6G| +00000150 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb 4f |....B[.....y.@.O| +00000160 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 22 |m..+.....g....."| +00000170 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 74 |8.J.ts+.4......t| +00000180 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 23 |{.X.la<..A..++$#| +00000190 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d 1e |w[.;.u]. T..c...| +000001a0 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 62 |$....P....C...ub| +000001b0 f4 14 c8 52 d7 02 03 01 00 01 a3 46 30 44 30 0e |...R.......F0D0.| +000001c0 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 |..U...........0.| +000001d0 06 03 55 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 |..U.%..0...+....| +000001e0 07 03 01 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 |...0...U.......0| +000001f0 00 30 0f 06 03 55 1d 11 04 08 30 06 87 04 7f 00 |.0...U....0.....| +00000200 00 01 30 41 06 09 2a 86 48 86 f7 0d 01 01 0a 30 |..0A..*.H......0| +00000210 34 a0 0f 30 0d 06 09 60 86 48 01 65 03 04 02 01 |4..0...`.H.e....| +00000220 05 00 a1 1c 30 1a 06 09 2a 86 48 86 f7 0d 01 01 |....0...*.H.....| +00000230 08 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 |.0...`.H.e......| +00000240 a2 03 02 01 20 03 81 81 00 cd ac 4e f2 ce 5f 8d |.... ......N.._.| +00000250 79 88 10 42 70 7f 7c bf 1b 5a 8a 00 ef 19 15 4b |y..Bp.|..Z.....K| +00000260 40 15 17 71 00 6c d4 16 26 e5 49 6d 56 da 0c 1a |@..q.l..&.ImV...| +00000270 13 9f d8 46 95 59 3c b6 7f 87 76 5e 18 aa 03 ea |...F.Y<...v^....| +00000280 06 75 22 dd 78 d2 a5 89 b8 c9 23 64 e1 28 38 ce |.u".x.....#d.(8.| +00000290 34 6c 6e 06 7b 51 f1 a7 e6 f4 b3 7f fa b1 3f 14 |4ln.{Q........?.| +000002a0 11 89 66 79 d1 8e 88 0e 0b a0 9e 30 2a c0 67 ef |..fy.......0*.g.| +000002b0 ca 46 02 88 e9 53 81 22 69 22 97 ad 80 93 d4 f7 |.F...S."i"......| +000002c0 dd 70 14 24 d7 70 0a 46 a1 16 03 03 00 ac 0c 00 |.p.$.p.F........| +000002d0 00 a8 03 00 1d 20 e0 90 02 58 37 69 79 d6 78 e5 |..... ...X7iy.x.| +000002e0 1d c6 7e a0 c6 38 1b ff 47 72 d6 c2 52 cb 6c 52 |..~..8..Gr..R.lR| +000002f0 36 7e 03 c3 35 1d 08 04 00 80 79 5f 23 fd b1 ee |6~..5.....y_#...| +00000300 ac 62 c8 72 09 52 1f 9a 0f ac 95 3e 4e e4 97 d2 |.b.r.R.....>N...| +00000310 a3 04 ae 19 3f 25 ad 3e b7 78 1f d9 79 5f c8 26 |....?%.>.x..y_.&| +00000320 f0 26 e5 ee 54 46 4a 05 84 15 01 4f 7a 7e 60 bd |.&..TFJ....Oz~`.| +00000330 86 74 78 d7 7c 86 91 2b 4f 76 b6 aa 78 27 c8 21 |.tx.|..+Ov..x'.!| +00000340 7e df 88 2f 26 f0 9d 3c a2 e8 95 f6 9f 5a a4 5e |~../&..<.....Z.^| +00000350 18 dc cd 0d 70 e8 85 b7 e5 57 f6 c2 f4 33 28 1c |....p....W...3(.| +00000360 58 7b 94 b0 9e ee d8 b3 42 b5 f3 63 78 a1 30 f3 |X{......B..cx.0.| +00000370 f7 e4 5e 72 64 6f 80 32 70 4e 16 03 03 00 0c 0d |..^rdo.2pN......| +00000380 00 00 08 01 01 00 02 08 04 00 00 16 03 03 00 04 |................| +00000390 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 02 66 0b 00 02 62 00 02 5f 00 02 5c 30 |....f...b.._..\0| +00000010 82 02 58 30 82 01 8d a0 03 02 01 02 02 11 00 f2 |..X0............| +00000020 99 26 eb 87 ea 8a 0d b9 fc c2 47 34 7c 11 b0 30 |.&........G4|..0| +00000030 41 06 09 2a 86 48 86 f7 0d 01 01 0a 30 34 a0 0f |A..*.H......04..| +00000040 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 a1 |0...`.H.e.......| +00000050 1c 30 1a 06 09 2a 86 48 86 f7 0d 01 01 08 30 0d |.0...*.H......0.| +00000060 06 09 60 86 48 01 65 03 04 02 01 05 00 a2 03 02 |..`.H.e.........| +00000070 01 20 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 |. 0.1.0...U....A| +00000080 63 6d 65 20 43 6f 30 1e 17 0d 31 37 31 31 32 33 |cme Co0...171123| +00000090 31 36 31 36 31 30 5a 17 0d 31 38 31 31 32 33 31 |161610Z..1811231| +000000a0 36 31 36 31 30 5a 30 12 31 10 30 0e 06 03 55 04 |61610Z0.1.0...U.| +000000b0 0a 13 07 41 63 6d 65 20 43 6f 30 81 9f 30 0d 06 |...Acme Co0..0..| +000000c0 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +000000d0 30 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 |0.......F}...'.H| +000000e0 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a |..(!.~...]..RE.z| +000000f0 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 |6G....B[.....y.@| +00000100 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e |.Om..+.....g....| +00000110 d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 |."8.J.ts+.4.....| +00000120 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b |.t{.X.la<..A..++| +00000130 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 |$#w[.;.u]. T..c.| +00000140 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 |..$....P....C...| +00000150 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 46 30 44 |ub...R.......F0D| +00000160 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 |0...U...........| +00000170 30 13 06 03 55 1d 25 04 0c 30 0a 06 08 2b 06 01 |0...U.%..0...+..| +00000180 05 05 07 03 01 30 0c 06 03 55 1d 13 01 01 ff 04 |.....0...U......| +00000190 02 30 00 30 0f 06 03 55 1d 11 04 08 30 06 87 04 |.0.0...U....0...| +000001a0 7f 00 00 01 30 41 06 09 2a 86 48 86 f7 0d 01 01 |....0A..*.H.....| +000001b0 0a 30 34 a0 0f 30 0d 06 09 60 86 48 01 65 03 04 |.04..0...`.H.e..| +000001c0 02 01 05 00 a1 1c 30 1a 06 09 2a 86 48 86 f7 0d |......0...*.H...| +000001d0 01 01 08 30 0d 06 09 60 86 48 01 65 03 04 02 01 |...0...`.H.e....| +000001e0 05 00 a2 03 02 01 20 03 81 81 00 cd ac 4e f2 ce |...... ......N..| +000001f0 5f 8d 79 88 10 42 70 7f 7c bf 1b 5a 8a 00 ef 19 |_.y..Bp.|..Z....| +00000200 15 4b 40 15 17 71 00 6c d4 16 26 e5 49 6d 56 da |.K@..q.l..&.ImV.| +00000210 0c 1a 13 9f d8 46 95 59 3c b6 7f 87 76 5e 18 aa |.....F.Y<...v^..| +00000220 03 ea 06 75 22 dd 78 d2 a5 89 b8 c9 23 64 e1 28 |...u".x.....#d.(| +00000230 38 ce 34 6c 6e 06 7b 51 f1 a7 e6 f4 b3 7f fa b1 |8.4ln.{Q........| +00000240 3f 14 11 89 66 79 d1 8e 88 0e 0b a0 9e 30 2a c0 |?...fy.......0*.| +00000250 67 ef ca 46 02 88 e9 53 81 22 69 22 97 ad 80 93 |g..F...S."i"....| +00000260 d4 f7 dd 70 14 24 d7 70 0a 46 a1 16 03 03 00 25 |...p.$.p.F.....%| +00000270 10 00 00 21 20 2f e5 7d a3 47 cd 62 43 15 28 da |...! /.}.G.bC.(.| +00000280 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| +00000290 5f 58 cb 3b 74 16 03 03 00 88 0f 00 00 84 08 04 |_X.;t...........| +000002a0 00 80 b2 c4 60 82 75 ca be 40 dc 28 ec 6d 14 6f |....`.u..@.(.m.o| +000002b0 6c 88 ca 9a d7 ae ce 94 26 a7 10 ad d8 c3 b9 a6 |l.......&.......| +000002c0 48 4e 01 7d ee 6e f8 e0 15 d9 72 c4 79 8d ac 25 |HN.}.n....r.y..%| +000002d0 37 29 83 fc e6 f1 2e 4f 76 49 6a 36 b9 1e b4 58 |7).....OvIj6...X| +000002e0 a2 3e f7 ff 96 5e d9 17 f2 40 05 1f ec bb 5b f5 |.>...^...@....[.| +000002f0 28 86 d2 fc 0e 7e 70 3a 3d 90 4c 46 a5 3e bc 57 |(....~p:=.LF.>.W| +00000300 24 4c ee 35 23 99 6f 21 12 db ba d8 3a 5f 37 1f |$L.5#.o!....:_7.| +00000310 da 3d c2 c9 bf b6 11 8b b9 b9 43 0b 52 ff 6d 2a |.=........C.R.m*| +00000320 74 a7 14 03 03 00 01 01 16 03 03 00 28 00 00 00 |t...........(...| +00000330 00 00 00 00 00 34 bd 90 a0 3f 1c 0c 11 5c 8a e4 |.....4...?...\..| +00000340 28 82 c4 57 59 73 fd a4 dc a9 91 4b df 2a c6 b5 |(..WYs.....K.*..| +00000350 f0 6e cf 41 70 |.n.Ap| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 e2 44 81 59 e4 |..........(.D.Y.| +00000010 6c cf e2 e7 04 78 61 02 36 29 2c 5c c4 6f 13 0b |l....xa.6),\.o..| +00000020 29 ba 74 b0 13 e8 8f 67 39 b5 ea d1 9d 99 d2 f6 |).t....g9.......| +00000030 f7 32 be |.2.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 5c 7b 38 |.............\{8| +00000010 46 af 57 57 05 5a c5 cb 83 f3 fd 17 d4 c3 2e 93 |F.WW.Z..........| +00000020 d7 70 52 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.pR.............| +00000030 df 2b d8 62 ec 97 c6 ab be d4 7f c9 91 f4 fe 55 |.+.b...........U| +00000040 ac bd |..| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES new file mode 100644 index 0000000..d21e9b3 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES @@ -0,0 +1,93 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 ec 4a 6a f8 c5 |....Y...U...Jj..| +00000010 42 65 f9 d3 4f 65 6f 14 6b bd ae a9 82 5d 06 9b |Be..Oeo.k....]..| +00000020 9d 03 bb 67 eb ba 52 70 74 c3 01 20 f2 ef 69 54 |...g..Rpt.. ..iT| +00000030 1f 4b 79 f7 5b d5 08 b4 18 4c af 8e 55 58 45 22 |.Ky.[....L..UXE"| +00000040 c1 c9 6f cf 36 67 45 20 c7 c5 3a af c0 09 00 00 |..o.6gE ..:.....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 7f e5 |*............ ..| +00000280 3b 03 9e 6a 77 11 1b 0f bc 4a db 44 7c 3b 81 1c |;..jw....J.D|;..| +00000290 03 8b 15 a6 f3 16 a0 58 5b 13 c5 1e d2 2c 04 03 |.......X[....,..| +000002a0 00 8b 30 81 88 02 42 00 cc 7c 76 94 81 89 8f 25 |..0...B..|v....%| +000002b0 16 e2 a0 0d 80 4f 7a 8f 8c 83 23 53 23 45 9c c1 |.....Oz...#S#E..| +000002c0 39 e3 0c c2 1b 4d f3 78 cd ea b9 c8 d4 b6 30 bb |9....M.x......0.| +000002d0 ff d7 ad 6c b2 fd 62 4d 8a 05 19 cf 58 ec 81 17 |...l..bM....X...| +000002e0 21 7c 71 a1 d7 ad 87 11 8d 02 42 01 a2 9e c8 e4 |!|q.......B.....| +000002f0 04 7c 75 22 df 14 97 94 8a 1b a1 34 95 95 dd 4c |.|u".......4...L| +00000300 9f 1a c7 c7 96 db ef 87 82 27 9a 27 3a 3d 75 26 |.........'.':=u&| +00000310 04 47 66 eb 55 60 9f 93 4e b2 09 14 fa 71 5b 3f |.Gf.U`..N....q[?| +00000320 33 37 3f 0c f2 5c 4f 1e cc fa b1 6f 70 16 03 03 |37?..\O....op...| +00000330 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00000040 00 00 00 00 00 d6 67 cb d5 7c 95 9b 16 e2 3b 86 |......g..|....;.| +00000050 22 bd 8c c7 40 36 9b b6 7e 0a 77 78 38 14 37 3c |"...@6..~.wx8.7<| +00000060 48 42 37 a7 07 31 bb 57 c4 e9 f5 e5 a7 58 71 f8 |HB7..1.W.....Xq.| +00000070 82 f7 12 97 72 |....r| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 56 45 5c a3 b3 |..........@VE\..| +00000010 64 43 54 7f b5 90 1a 34 ab 2b 68 25 49 41 bf 78 |dCT....4.+h%IA.x| +00000020 50 b0 66 35 20 76 e1 d0 5c 8a 82 2e 03 83 cf c6 |P.f5 v..\.......| +00000030 b7 48 3d 2c c4 cf f5 31 c1 ab 9a 3b 09 3a 75 e3 |.H=,...1...;.:u.| +00000040 b2 05 fa d9 79 cc 1b 0e 30 44 e1 |....y...0D.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +00000010 00 00 00 00 00 76 5f 1f ec 55 ec f4 87 06 91 b4 |.....v_..U......| +00000020 ba 71 4f 7f 9c ce e1 c7 e6 3d 75 05 fd ba 98 c4 |.qO......=u.....| +00000030 d0 39 24 b8 d4 15 03 03 00 30 00 00 00 00 00 00 |.9$......0......| +00000040 00 00 00 00 00 00 00 00 00 00 e8 4e 09 a1 5f db |...........N.._.| +00000050 91 d5 5b e8 6a 86 7a 6c 7d 4a e1 94 8a 7d 99 52 |..[.j.zl}J...}.R| +00000060 e6 5d d8 35 7c a0 68 8f 09 f9 |.].5|.h...| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM new file mode 100644 index 0000000..02bad39 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM @@ -0,0 +1,88 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 d4 97 12 a8 e7 |....Y...U.......| +00000010 be a9 2d 80 f0 db 01 49 07 04 f4 d1 02 db 3d 4a |..-....I......=J| +00000020 f0 af 31 38 39 d7 4c 1a d3 74 71 20 0f a3 76 14 |..189.L..tq ..v.| +00000030 73 ff 25 1b ef 29 b3 5e 0b 8f fe ee a6 19 d3 31 |s.%..).^.......1| +00000040 5d 2e 71 ab 74 58 e9 d6 c5 9b f4 93 c0 2b 00 00 |].q.tX.......+..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 a8 15 |*............ ..| +00000280 13 40 df f8 dc 39 f0 af 90 53 a8 34 a9 61 68 c8 |.@...9...S.4.ah.| +00000290 ad be 4f 02 0e d2 83 fd 2e 35 bf 8c 8e 13 04 03 |..O......5......| +000002a0 00 8b 30 81 88 02 42 00 bc 69 df 5b ec 9f 17 ff |..0...B..i.[....| +000002b0 e6 e5 24 71 f6 2b a5 88 40 78 12 ef f3 dc 25 a9 |..$q.+..@x....%.| +000002c0 7c 89 24 0d c7 46 b2 db ae 72 b4 2a 87 87 fe 7e ||.$..F...r.*...~| +000002d0 22 8f e6 d4 c4 7b 61 14 c3 04 39 98 87 6f 1f 54 |"....{a...9..o.T| +000002e0 e0 50 16 0b 52 8e d6 1e 0a 02 42 00 b7 40 26 a8 |.P..R.....B..@&.| +000002f0 11 09 77 ec 36 e5 88 26 6d 83 6f e7 c3 b1 98 c3 |..w.6..&m.o.....| +00000300 4b 83 92 48 65 31 87 68 ee 49 25 ec 95 59 82 b5 |K..He1.h.I%..Y..| +00000310 93 92 c8 17 d6 d9 1c 99 60 48 1b 18 50 b4 e7 df |........`H..P...| +00000320 ed 75 1a f2 08 e8 3d 93 99 27 ef 4d e3 16 03 03 |.u....=..'.M....| +00000330 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 30 f1 a9 |....(........0..| +00000040 4a 7e 86 a1 5d b7 db 2f c6 e2 ec 36 41 83 66 75 |J~..]../...6A.fu| +00000050 a3 6c 7d e7 61 36 ac f7 76 f8 8e d8 81 |.l}.a6..v....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 2c 78 86 13 dc |..........(,x...| +00000010 a4 b9 bf ad 50 45 a3 d9 b3 df 33 a2 79 b1 1b 25 |....PE....3.y..%| +00000020 12 94 97 99 07 6b 52 c4 52 64 ab 89 40 8c 93 4a |.....kR.Rd..@..J| +00000030 e3 cc d9 |...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 fa 9e 8b |................| +00000010 92 8c f5 32 e6 d4 11 46 b4 73 62 56 f6 83 15 6f |...2...F.sbV...o| +00000020 ce de 2d 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..-.............| +00000030 93 24 68 83 67 b6 f9 27 b5 26 52 78 5d f3 c9 d2 |.$h.g..'.&Rx]...| +00000040 26 a0 |&.| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 new file mode 100644 index 0000000..4946fe4 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 @@ -0,0 +1,97 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 d1 af 88 61 b7 |....Y...U.....a.| +00000010 b3 01 16 1a 44 26 1c a1 4f 2d 8a f6 9c f2 7e 1a |....D&..O-....~.| +00000020 1f ce cb dd 5b f0 c6 2f 16 5e 4a 20 b3 c7 ae 3f |....[../.^J ...?| +00000030 de d0 d8 9e 48 3e 87 23 f0 9d 43 10 50 3c 66 8b |....H>.#..C.P>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........| +00000040 00 00 00 00 00 85 db ae c1 37 85 25 3d ee 5f f5 |.........7.%=._.| +00000050 12 95 df ee 29 4a f7 3a 80 ca bd c2 b3 d8 f3 8c |....)J.:........| +00000060 56 62 d2 68 13 1d 73 51 09 93 a3 b9 43 4a 2c 0f |Vb.h..sQ....CJ,.| +00000070 bf 3c 96 76 08 a9 17 68 e2 9a 3f 39 e7 04 76 f8 |.<.v...h..?9..v.| +00000080 8f fe e8 f5 ce |.....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 50 fa 85 cc bc dd |..........P.....| +00000010 0e 16 86 b1 5c 51 8a b9 cc 78 cd cd 64 5d 23 ca |....\Q...x..d]#.| +00000020 59 84 b3 42 dd ae a7 98 43 05 21 4f 35 43 75 5c |Y..B....C.!O5Cu\| +00000030 13 c8 e0 b6 66 0f 55 32 69 7a 8b 8f cd c2 37 38 |....f.U2iz....78| +00000040 f6 fa 0b 66 cf 46 91 3e 9f f5 43 44 f5 c7 2b e1 |...f.F.>..CD..+.| +00000050 39 3a f7 3c f2 03 c4 85 dc 58 66 |9:.<.....Xf| +>>> Flow 5 (client to server) +00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00000010 00 00 00 00 00 44 e6 99 40 ae 12 bc d9 92 c5 ae |.....D..@.......| +00000020 fb 4d 5f 64 7a 77 0f 80 8e a4 be d0 ba ba 41 b1 |.M_dzw........A.| +00000030 0d 40 e9 0e 50 32 dc 35 2d 5e 5c 8a ef 20 75 80 |.@..P2.5-^\.. u.| +00000040 a0 e5 9c 61 49 15 03 03 00 40 00 00 00 00 00 00 |...aI....@......| +00000050 00 00 00 00 00 00 00 00 00 00 57 91 40 2a a5 f7 |..........W.@*..| +00000060 9f 29 0f 02 8e 50 ac 4b 2e 55 9a 78 72 f0 d7 c5 |.)...P.K.U.xr...| +00000070 3b f2 cd 28 4d 8b 49 d8 50 a6 22 96 de df 16 d6 |;..(M.I.P.".....| +00000080 61 4b 23 5c 5d de a1 0a 5b 16 |aK#\]...[.| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 new file mode 100644 index 0000000..14af5ae --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 @@ -0,0 +1,88 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 bb 8a 66 ee 44 |....Y...U....f.D| +00000010 42 dc 59 c7 a7 7b a8 57 8e 63 21 f0 4e 31 f4 5c |B.Y..{.W.c!.N1.\| +00000020 1d d3 42 e5 de eb 8c 78 3a 01 01 20 9b 89 05 d6 |..B....x:.. ....| +00000030 d2 07 38 8b 4c 5f 6d 62 9f 43 a0 cd d3 40 0f 77 |..8.L_mb.C...@.w| +00000040 17 ff 43 4a 5c b3 8c 83 b7 4b c7 e7 c0 2c 00 00 |..CJ\....K...,..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| +00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| +00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| +00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| +00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 fd 71 |*............ .q| +00000280 c1 3a 6a a3 69 6a 34 f3 02 c5 1d e5 db 63 f4 eb |.:j.ij4......c..| +00000290 97 4c 70 bc b3 4e 9d 2c 2f b2 b9 9d ac 3f 04 03 |.Lp..N.,/....?..| +000002a0 00 8b 30 81 88 02 42 01 bd 9d ad 24 37 b9 60 55 |..0...B....$7.`U| +000002b0 e4 cc bc 49 c3 88 3b ed ac e4 42 8e fa 81 01 d9 |...I..;...B.....| +000002c0 39 4c f0 1c 7d 39 a2 81 8a e1 17 0e 8d 37 76 96 |9L..}9.......7v.| +000002d0 37 13 3a 1e 2e fd 0d 0a 3c 90 9d 43 3d 06 c0 b1 |7.:.....<..C=...| +000002e0 4e 07 3e c3 9f f2 43 40 0b 02 42 01 d6 d0 20 ad |N.>...C@..B... .| +000002f0 48 09 c0 9b 5d c8 84 46 3b 98 37 9b 5a 91 4a 07 |H...]..F;.7.Z.J.| +00000300 79 68 71 92 76 dc 70 0f 5c 44 7e 81 c3 c6 3f 19 |yhq.v.p.\D~...?.| +00000310 f4 0f 6a 0b aa cc bb 65 e7 34 b5 e9 67 2d 32 98 |..j....e.4..g-2.| +00000320 1c f6 76 4c 96 73 df 21 d6 e1 ea 34 86 16 03 03 |..vL.s.!...4....| +00000330 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 27 fd 98 |....(........'..| +00000040 47 79 56 f9 e8 0e fd 18 c2 8f 2d 32 51 f7 19 b5 |GyV.......-2Q...| +00000050 ab 2f 81 ed b6 cf 6f b5 65 81 81 f1 44 |./....o.e...D| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 a9 b7 63 61 57 |..........(..caW| +00000010 54 57 f0 b2 60 58 e3 dc 6e e1 40 3e 67 b4 99 8f |TW..`X..n.@>g...| +00000020 e9 6b 11 f1 1a 54 bd c1 d3 b9 5b 01 12 27 a4 0b |.k...T....[..'..| +00000030 e9 ec 01 |...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 e0 8a 6e |...............n| +00000010 62 5d e3 db 99 10 d2 53 b6 21 2e 79 31 cf 71 1d |b].....S.!.y1.q.| +00000020 34 71 2a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |4q*.............| +00000030 e7 4a 8d b9 2f 1b b1 70 72 da 7f d8 fa 4f 9f d6 |.J../..pr....O..| +00000040 ca f3 |..| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 new file mode 100644 index 0000000..3113b3c --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 d0 01 00 00 cc 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 08 cc a9 |................| +00000050 13 03 13 01 13 02 01 00 00 7b 00 05 00 05 01 00 |.........{......| +00000060 00 00 00 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 |................| +00000070 19 00 0b 00 02 01 00 00 0d 00 1a 00 18 08 04 04 |................| +00000080 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 06 |................| +00000090 03 02 01 02 03 ff 01 00 01 00 00 12 00 00 00 2b |...............+| +000000a0 00 09 08 03 04 03 03 03 02 03 01 00 33 00 26 00 |............3.&.| +000000b0 24 00 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da |$... /.}.G.bC.(.| +000000c0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| +000000d0 5f 58 cb 3b 74 |_X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 e1 cc 3c 49 04 |....Y...U....>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 7f ab 78 f0 a6 b6 57 bd c3 b9 32 |.... ..x...W...2| +00000040 96 3f 7c 9d a0 4d dc 74 c9 e8 1a 88 c4 b2 10 27 |.?|..M.t.......'| +00000050 e3 9c 1e 9b e1 |.....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 0c b7 0c 47 8e |.......... ...G.| +00000010 40 6b 9f 9c d2 cd 24 25 db 12 e8 0c 50 be f3 98 |@k....$%....P...| +00000020 4a 6f f9 42 58 07 b9 64 d0 00 91 |Jo.BX..d...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 1d 32 1c ef 0b 1f a4 ba 39 a3 63 |......2......9.c| +00000010 04 29 e5 67 1e bb 5a 6e c7 3c c1 15 03 03 00 12 |.).g..Zn.<......| +00000020 0e 0b 0f 49 30 fe d4 c3 35 85 e3 db 6e 65 e3 2d |...I0...5...ne.-| +00000030 d1 1d |..| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES new file mode 100644 index 0000000..ea6c787 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES @@ -0,0 +1,97 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 1e 2f 6f fa 02 |....Y...U.../o..| +00000010 44 3e 0d d0 3e b5 e6 0c a2 d6 aa 04 5b ba 93 39 |D>..>.......[..9| +00000020 29 dd e7 7e b8 11 f9 85 97 a5 e4 20 9c 64 e9 47 |)..~....... .d.G| +00000030 cb 7c 0c 77 9d 83 5a c4 e8 05 62 40 95 8e 8e aa |.|.w..Z...b@....| +00000040 39 bb 24 8f b7 29 75 77 18 66 60 29 c0 13 00 00 |9.$..)uw.f`)....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 92 ed 81 60 d9 51 c2 |........ ...`.Q.| +000002d0 00 3d 99 84 82 c5 83 67 60 b3 11 59 0c c5 5d ff |.=.....g`..Y..].| +000002e0 d6 28 79 68 2d 73 7f 84 40 08 04 00 80 b6 a0 4b |.(yh-s..@......K| +000002f0 3d fb e1 e6 76 cc ae e3 59 d0 1c 50 5c 09 5d 80 |=...v...Y..P\.].| +00000300 c2 58 0d 36 d7 1a 78 e3 c2 66 73 3a 14 06 37 6f |.X.6..x..fs:..7o| +00000310 3a 95 2e 2a eb cc e5 e3 f7 30 eb 0d 33 04 51 6e |:..*.....0..3.Qn| +00000320 06 86 8f 53 6d fd 97 75 b3 13 2e 4e ee 8f 03 68 |...Sm..u...N...h| +00000330 23 32 83 96 af 01 ed b0 21 a7 13 06 47 f4 08 b9 |#2......!...G...| +00000340 8a 47 cc 12 99 20 c6 31 77 28 2c 2e d6 a0 20 8c |.G... .1w(,... .| +00000350 e6 67 c7 70 23 ed 98 9c c9 47 1c e0 37 95 42 aa |.g.p#....G..7.B.| +00000360 c2 19 1b 55 09 5c 58 fb ef 67 a9 b5 65 16 03 03 |...U.\X..g..e...| +00000370 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00000040 00 00 00 00 00 dd 81 23 e0 a3 01 33 bb 87 0d 93 |.......#...3....| +00000050 b2 61 16 01 e3 87 e0 05 cc b0 ec 15 56 df ff 9c |.a..........V...| +00000060 e6 9c 6a 57 79 8a 0b 86 f9 fb 60 3f ca 0d ef f2 |..jWy.....`?....| +00000070 81 c0 5e 22 bf |..^".| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 d4 d3 ba 7f 4c |..........@....L| +00000010 1a ee d9 ca 66 a0 5b d7 08 78 5d 5c fd 17 32 71 |....f.[..x]\..2q| +00000020 7f 8c 2e eb 80 bc 82 0f 0c ed 71 ac 34 59 71 d1 |..........q.4Yq.| +00000030 aa d3 fd 0c 50 7d 4b 1b 01 5d 4c 03 9f 6c 16 8f |....P}K..]L..l..| +00000040 5d f7 8d c0 4b 3f 01 96 23 40 22 |]...K?..#@"| +>>> Flow 5 (client to server) +00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +00000010 00 00 00 00 00 36 49 0e f6 26 13 f7 69 15 54 27 |.....6I..&..i.T'| +00000020 5a e6 f2 fb 7d ad e0 30 d3 cd ed 08 24 74 5f 77 |Z...}..0....$t_w| +00000030 f7 8b 3f bf 94 15 03 03 00 30 00 00 00 00 00 00 |..?......0......| +00000040 00 00 00 00 00 00 00 00 00 00 28 09 ed 2f d8 6f |..........(../.o| +00000050 95 fc db 9e ec d8 81 7e a4 d4 8e c5 ec d3 24 bc |.......~......$.| +00000060 ab 52 e6 01 75 98 b9 e5 9f d9 |.R..u.....| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 new file mode 100644 index 0000000..88d0d01 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 @@ -0,0 +1,101 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 e6 04 5e a9 bb |....Y...U....^..| +00000010 23 56 bd cc e7 72 9f 10 b1 fc 23 48 22 19 cb 27 |#V...r....#H"..'| +00000020 3e c4 22 ec b9 7a 9c 81 60 c5 55 20 b9 7f 8a 0e |>."..z..`.U ....| +00000030 6b d6 cf cb 35 85 52 f3 9f 28 00 87 22 88 6d 7c |k...5.R..(..".m|| +00000040 35 0e f6 af 7c 28 b4 71 cc 46 c1 b5 c0 27 00 00 |5...|(.q.F...'..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 55 af 53 a0 54 77 df |........ U.S.Tw.| +000002d0 ca 8f 49 1a 4d d0 9b 24 a6 a9 2b b2 2a 33 46 b8 |..I.M..$..+.*3F.| +000002e0 01 d6 4e fd fb c1 e4 e6 64 08 04 00 80 5c da 2f |..N.....d....\./| +000002f0 01 2b 10 b9 e9 35 f2 b1 2a 28 4f 78 58 7b 3d 9a |.+...5..*(OxX{=.| +00000300 13 e4 7c 77 41 95 fa 7a 90 1f eb f5 20 55 7c 76 |..|wA..z.... U|v| +00000310 dd c5 66 08 88 eb ba 17 f0 de f3 0c a5 a6 3c 21 |..f...........>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........| +00000040 00 00 00 00 00 91 c1 82 23 f0 03 79 83 38 ef d0 |........#..y.8..| +00000050 73 71 9b 7d 55 5e 53 3b d3 cf 86 48 60 2f 42 97 |sq.}U^S;...H`/B.| +00000060 63 e8 4b 20 4c 92 3e 2f aa b3 32 46 8a 96 69 42 |c.K L.>/..2F..iB| +00000070 96 9a 4b bd 04 f2 3d b6 5f f9 37 4f a4 3d f1 cb |..K...=._.7O.=..| +00000080 d5 57 fc 5e 8e |.W.^.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 50 e1 91 69 dc 7b |..........P..i.{| +00000010 5f a4 c7 7a 8f ba bb 8d 98 c3 0e 3f 10 f1 3e 3f |_..z.......?..>?| +00000020 37 6f 11 81 3f c5 7c 22 6f 22 a3 94 ae 3a 77 17 |7o..?.|"o"...:w.| +00000030 a2 7b cc 8e 5e 6e 9b 4b 98 fd 16 f8 46 9e 78 19 |.{..^n.K....F.x.| +00000040 43 e6 da e3 05 9a 0a 49 b0 09 c7 e5 4b 41 dc b4 |C......I....KA..| +00000050 c0 81 9b 46 7e dd c3 64 2e f8 6e |...F~..d..n| +>>> Flow 5 (client to server) +00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00000010 00 00 00 00 00 65 4c 71 31 d4 47 4d 0b 81 1f 75 |.....eLq1.GM...u| +00000020 b6 71 64 4a e6 a8 80 a1 f1 e2 0a 14 77 af a4 c6 |.qdJ........w...| +00000030 1d 6a 7d 79 6a 15 a1 0e 86 6c 8e e1 32 64 0b 5d |.j}yj....l..2d.]| +00000040 af e0 f5 05 91 15 03 03 00 40 00 00 00 00 00 00 |.........@......| +00000050 00 00 00 00 00 00 00 00 00 00 ca 46 1b 95 2a 41 |...........F..*A| +00000060 ce dc 30 d6 e0 cf 2f 2b 1f 61 81 33 a4 58 e7 af |..0.../+.a.3.X..| +00000070 90 9c 15 42 9b ab 26 64 d1 39 46 45 6b 74 b9 c4 |...B..&d.9FEkt..| +00000080 21 d9 ef 2d 69 51 dc e7 8a 6b |!..-iQ...k| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 new file mode 100644 index 0000000..2c2cb45 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 @@ -0,0 +1,88 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 d0 01 00 00 cc 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 08 cc a8 |................| +00000050 13 03 13 01 13 02 01 00 00 7b 00 05 00 05 01 00 |.........{......| +00000060 00 00 00 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 |................| +00000070 19 00 0b 00 02 01 00 00 0d 00 1a 00 18 08 04 04 |................| +00000080 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 06 |................| +00000090 03 02 01 02 03 ff 01 00 01 00 00 12 00 00 00 2b |...............+| +000000a0 00 09 08 03 04 03 03 03 02 03 01 00 33 00 26 00 |............3.&.| +000000b0 24 00 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da |$... /.}.G.bC.(.| +000000c0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| +000000d0 5f 58 cb 3b 74 |_X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 2a 76 db 4b d5 |....Y...U..*v.K.| +00000010 10 f3 21 f2 4b 29 a2 2e 7a 7d 0b 86 c4 af 60 95 |..!.K)..z}....`.| +00000020 5b 11 84 27 8a 59 7f af a0 27 de 20 02 f7 dc 9b |[..'.Y...'. ....| +00000030 63 8e 2e da 48 b5 73 81 8e 76 13 da dd 2e 17 2b |c...H.s..v.....+| +00000040 ff 18 ad d7 9d f3 44 ed b6 60 0e 42 cc a8 00 00 |......D..`.B....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 0d c3 c2 b5 73 da 39 |........ ....s.9| +000002d0 82 e5 8c 18 0d 8d 16 c2 a5 e7 3e 39 fd 25 00 18 |..........>9.%..| +000002e0 25 16 c0 a7 6e c6 dd bb 01 08 04 00 80 b3 bd 01 |%...n...........| +000002f0 ae dd b1 c8 2a 5d 0e 66 6d 1e b3 92 f4 01 63 59 |....*].fm.....cY| +00000300 0c c1 62 df 75 8f 4f 19 5a cf 2f 63 79 d0 06 31 |..b.u.O.Z./cy..1| +00000310 c0 60 6a 4f db 70 18 bd 80 8b 30 94 40 dd 13 39 |.`jO.p....0.@..9| +00000320 4f db 2b 54 a4 97 f7 ef a5 a3 ff f5 14 3d e2 2d |O.+T.........=.-| +00000330 0c 0e 71 4a bd a8 59 48 ab 06 55 53 45 2a ee 3e |..qJ..YH..USE*.>| +00000340 65 1f 47 ee 8d e3 f6 4e 2e b1 4c d0 af 50 15 02 |e.G....N..L..P..| +00000350 5e 84 fe 76 d5 f3 c5 fb 2a 91 44 f0 92 32 ee ea |^..v....*.D..2..| +00000360 a0 26 77 5c 94 88 24 e3 2f 75 e3 fd b7 16 03 03 |.&w\..$./u......| +00000370 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 0b 58 fe b5 63 ac 28 f8 34 d6 72 |.... .X..c.(.4.r| +00000040 1a a3 ec 26 91 70 07 8d 6a 3a 3b 3a 94 5e a3 fa |...&.p..j:;:.^..| +00000050 6e 92 3a 15 65 |n.:.e| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 01 fa e1 2f 29 |.......... .../)| +00000010 ee f6 d4 e8 22 b6 e0 8f 82 37 81 83 1b 03 4d 5f |...."....7....M_| +00000020 00 80 cb eb 9a 3a 01 c7 aa e9 9a |.....:.....| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 43 6a e8 f2 ca f9 4f 3c 6d ff 5e |.....Cj....O>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 6c 5f 04 9e a6 |....Y...U..l_...| +00000010 c6 41 0c ee a2 2c af 45 f0 bc de 67 2d 20 1c 9c |.A...,.E...g- ..| +00000020 82 33 fd 86 86 b3 50 04 77 ec da 20 f3 09 fb 8c |.3....P.w.. ....| +00000030 79 83 f9 82 58 b9 76 bb d3 58 44 3d 52 0c 37 ae |y...X.v..XD=R.7.| +00000040 18 98 84 9a 56 af 5d 2b 68 68 c7 30 cc a9 00 00 |....V.]+hh.0....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 01 3c 0b 00 01 38 00 01 35 00 01 32 30 82 01 |..<...8..5..20..| +00000070 2e 30 81 e1 a0 03 02 01 02 02 10 0f 43 1c 42 57 |.0..........C.BW| +00000080 93 94 1d e9 87 e4 f1 ad 15 00 5d 30 05 06 03 2b |..........]0...+| +00000090 65 70 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 |ep0.1.0...U....A| +000000a0 63 6d 65 20 43 6f 30 1e 17 0d 31 39 30 35 31 36 |cme Co0...190516| +000000b0 32 31 33 38 30 31 5a 17 0d 32 30 30 35 31 35 32 |213801Z..2005152| +000000c0 31 33 38 30 31 5a 30 12 31 10 30 0e 06 03 55 04 |13801Z0.1.0...U.| +000000d0 0a 13 07 41 63 6d 65 20 43 6f 30 2a 30 05 06 03 |...Acme Co0*0...| +000000e0 2b 65 70 03 21 00 3f e2 15 2e e6 e3 ef 3f 4e 85 |+ep.!.?......?N.| +000000f0 4a 75 77 a3 64 9e ed e0 bf 84 2c cc 92 26 8f fa |Juw.d.....,..&..| +00000100 6f 34 83 aa ec 8f a3 4d 30 4b 30 0e 06 03 55 1d |o4.....M0K0...U.| +00000110 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 1d |..........0...U.| +00000120 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 30 |%..0...+.......0| +00000130 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 16 06 |...U.......0.0..| +00000140 03 55 1d 11 04 0f 30 0d 82 0b 65 78 61 6d 70 6c |.U....0...exampl| +00000150 65 2e 63 6f 6d 30 05 06 03 2b 65 70 03 41 00 63 |e.com0...+ep.A.c| +00000160 44 ed 9c c4 be 53 24 53 9f d2 10 8d 9f e8 21 08 |D....S$S......!.| +00000170 90 95 39 e5 0d c1 55 ff 2c 16 b7 1d fc ab 7d 4d |..9...U.,.....}M| +00000180 d4 e0 93 13 d0 a9 42 e0 b6 6b fe 5d 67 48 d7 9f |......B..k.]gH..| +00000190 50 bc 6c cd 4b 03 83 7c f2 08 58 cd ac cf 0c 16 |P.l.K..|..X.....| +000001a0 03 03 00 6c 0c 00 00 68 03 00 1d 20 a7 28 ef 3e |...l...h... .(.>| +000001b0 1c 65 9f 8e 9a 80 0b 7d ac 9c ce d6 1e 97 54 30 |.e.....}......T0| +000001c0 53 9b e6 0c 61 e0 ea 9c ae 70 f2 78 08 07 00 40 |S...a....p.x...@| +000001d0 0c 49 38 23 a0 75 28 fb ec 71 a4 89 79 45 d1 ca |.I8#.u(..q..yE..| +000001e0 83 6f 5d dd 01 d4 c6 63 53 5d 6e 8f 06 09 80 a1 |.o]....cS]n.....| +000001f0 f7 ef af 2d 29 af aa 10 86 1c 18 19 3f be bb 90 |...-).......?...| +00000200 0e c3 9d 1e 6e 60 49 7f fc c8 42 61 89 c2 e3 04 |....n`I...Ba....| +00000210 16 03 03 00 04 0e 00 00 00 |.........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 b2 7f b6 1b 9c ec bf 2e ae a5 70 |.... ..........p| +00000040 d5 33 9b 63 02 66 77 7d 00 ec 86 e4 bb d4 57 68 |.3.c.fw}......Wh| +00000050 49 2a d3 be e7 |I*...| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 4c 7d ef ed ea |.......... L}...| +00000010 ab 8d 4f 38 46 6e 8f 56 b4 1d f2 1f 2c df 57 c0 |..O8Fn.V....,.W.| +00000020 f9 8a c2 71 f8 6d df b7 c7 1e 23 |...q.m....#| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 26 f1 7c ee c8 3a 61 b0 f7 5a bd |.....&.|..:a..Z.| +00000010 b7 61 61 60 69 db cd ea 10 ee 63 15 03 03 00 12 |.aa`i.....c.....| +00000020 22 c0 65 a4 5d 0e 48 9c 56 f8 54 17 82 5f 29 97 |".e.].H.V.T.._).| +00000030 be 6b |.k| diff --git a/src/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial b/src/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial new file mode 100644 index 0000000..adf1f72 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial @@ -0,0 +1,90 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 79 92 2e 86 bc |....Y...U..y....| +00000010 c0 b7 56 2a 25 58 75 b3 25 ac 58 1d 8d 8e d5 87 |..V*%Xu.%.X.....| +00000020 2d 67 8e 6e d4 d4 b6 67 b1 42 96 20 91 75 0b fa |-g.n...g.B. .u..| +00000030 d0 6f ab 91 4a c3 15 07 1d 6c 8e e5 55 f2 26 aa |.o..J....l..U.&.| +00000040 4d 5c 57 3b 93 a6 fc 46 c9 f6 80 1e cc a8 00 00 |M\W;...F........| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 5f 3c a6 bb 4e 32 85 |........ _<..N2.| +000002d0 69 4b 23 df 18 9c 07 ac 0b a8 dd 9b 59 33 00 02 |iK#.........Y3..| +000002e0 99 de 4e 66 1e 04 3b ce 4b 08 04 00 80 82 41 7c |..Nf..;.K.....A|| +000002f0 7b b8 ee d4 23 08 c3 23 8d b1 ea 27 43 e7 8e f1 |{...#..#...'C...| +00000300 7b 87 b0 88 ab f7 b1 15 2e 45 c5 50 e7 cd 05 31 |{........E.P...1| +00000310 bf 99 30 c8 ff 6a 23 ec 9d e5 c8 09 fa ec 50 a8 |..0..j#.......P.| +00000320 fa b3 54 b7 c5 61 99 f6 94 12 e6 34 4a 59 e3 dd |..T..a.....4JY..| +00000330 e5 7f f4 88 c9 2a 4c 09 65 d9 75 a6 ce 12 96 82 |.....*L.e.u.....| +00000340 a2 36 f2 5e 93 f2 4e 1c 05 91 a7 5a 67 36 e9 3d |.6.^..N....Zg6.=| +00000350 33 cd 6a 77 9c 8d 14 95 80 41 61 bd 80 ed 7b 51 |3.jw.....Aa...{Q| +00000360 cf 76 87 4d ac dc 5f c1 5d 52 a7 f9 51 16 03 03 |.v.M.._.]R..Q...| +00000370 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 bc c3 7c c2 cc a4 4e 8f d0 79 7a |.... ..|...N..yz| +00000040 a4 7d 4c 3d 17 8c 19 93 4f 49 03 50 f6 71 4d 16 |.}L=....OI.P.qM.| +00000050 97 bb 18 88 67 |....g| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 00 c4 8a f9 1e |.......... .....| +00000010 c0 66 ab ef 39 ae 41 7a 05 9c e3 06 e4 4d 00 bb |.f..9.Az.....M..| +00000020 d4 ef 21 71 a3 54 23 fe db 4a 86 |..!q.T#..J.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 0c d3 9a f5 1d f4 5f b2 45 c7 7c |..........._.E.|| +00000010 38 59 6e df 6e 59 d5 94 8b a9 bb 15 03 03 00 12 |8Yn.nY..........| +00000020 9e 74 a5 0e c1 7f 33 52 be 17 f6 f5 4d 9f 3d d1 |.t....3R....M.=.| +00000030 b5 65 |.e| diff --git a/src/crypto/tls/testdata/Client-TLSv12-P256-ECDHE b/src/crypto/tls/testdata/Client-TLSv12-P256-ECDHE new file mode 100644 index 0000000..3331435 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-P256-ECDHE @@ -0,0 +1,98 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 15 01 00 01 11 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 96 00 05 00 05 01 00 00 00 00 00 0a 00 |................| +00000090 04 00 02 00 17 00 0b 00 02 01 00 00 0d 00 1a 00 |................| +000000a0 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 |................| +000000b0 01 05 03 06 03 02 01 02 03 ff 01 00 01 00 00 12 |................| +000000c0 00 00 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 |...+............| +000000d0 33 00 47 00 45 00 17 00 41 04 1e 18 37 ef 0d 19 |3.G.E...A...7...| +000000e0 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..| +000000f0 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..| +00000100 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.| +00000110 b5 68 1a 41 03 56 6b dc 5a 89 |.h.A.Vk.Z.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 0b f0 3e a1 66 |....Y...U....>.f| +00000010 13 35 53 83 59 3c 9e 2a 0f 0b b0 9a 42 de e4 f1 |.5S.Y<.*....B...| +00000020 8a 2d 34 ef 15 fe 28 55 42 d8 bf 20 aa 27 5c 5f |.-4...(UB.. .'\_| +00000030 24 59 17 ef 43 f3 18 f8 40 97 8f 1a 6a f4 e4 4a |$Y..C...@...j..J| +00000040 a3 b7 11 39 01 bd 98 8c 61 08 d9 50 c0 2f 00 00 |...9....a..P./..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 cd 0c 00 00 c9 03 00 17 41 04 79 6a df 70 26 49 |........A.yj.p&I| +000002d0 c0 5a 39 fc 7c 80 d1 2c cd 76 d0 4c 6f a7 7d bc |.Z9.|..,.v.Lo.}.| +000002e0 32 c6 54 c6 76 58 e2 0f 3f 33 ad 92 61 33 11 16 |2.T.vX..?3..a3..| +000002f0 d7 42 a8 ba 2a 8f 22 2a eb 88 3e 74 78 2a 67 de |.B..*."*..>tx*g.| +00000300 39 75 63 2c 1d 2e da 33 77 a5 08 04 00 80 61 f5 |9uc,...3w.....a.| +00000310 ed 56 5b f1 dd 78 a0 c4 8a 9b ac 28 c5 91 0c bd |.V[..x.....(....| +00000320 f1 d5 c1 f6 31 2e 8c c3 d5 84 3a 15 e8 6d f1 bc |....1.....:..m..| +00000330 9e a6 04 fd 95 2f 51 60 2f c6 ff 99 cf 38 24 bf |...../Q`/....8$.| +00000340 a4 32 a2 1f a1 6b bd 27 98 00 14 23 0d 12 66 67 |.2...k.'...#..fg| +00000350 48 33 92 51 e7 e7 3c f5 ef 13 ca 46 3c 39 53 70 |H3.Q..<....F<9Sp| +00000360 41 78 4a 02 70 87 48 ce b0 31 02 33 0b 06 78 b9 |AxJ.p.H..1.3..x.| +00000370 87 0b 07 e0 f7 15 c8 3e 27 a1 a3 20 24 9e 20 93 |.......>'.. $. .| +00000380 7f b5 53 7b 18 88 96 87 2b df 02 ba 0c d8 16 03 |..S{....+.......| +00000390 03 00 04 0e 00 00 00 |.......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 c1 90 |.....(..........| +00000060 a0 8b 53 87 a8 e3 56 4c 5c ad 5f dc 00 af 29 5f |..S...VL\._...)_| +00000070 11 53 7d 49 25 f8 74 16 dc 84 5f 3b c6 24 |.S}I%.t..._;.$| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 00 f9 b2 51 85 |..........(...Q.| +00000010 72 7e ec 79 72 59 90 ae 69 51 79 61 10 3b 4e 4b |r~.yrY..iQya.;NK| +00000020 45 d6 a5 9a c0 1a 69 c9 9f 1c ee cd ad 6a e8 ea |E.....i......j..| +00000030 c4 9e f1 |...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 86 5a 45 |..............ZE| +00000010 24 60 90 dc bc b3 f6 61 6f db 60 02 99 f9 e2 93 |$`.....ao.`.....| +00000020 07 85 0d 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| +00000030 36 86 b0 60 b5 5d dd 28 64 c6 5b c7 ed 01 07 b1 |6..`.].(d.[.....| +00000040 12 39 |.9| diff --git a/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 new file mode 100644 index 0000000..12fb594 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 b0 e7 ee 09 45 |....Q...M......E| +00000010 36 f1 7a 92 be 9e d8 9d ae cd c1 4e b2 12 94 3e |6.z........N...>| +00000020 6c 34 71 ed 5f e0 97 7f 25 e4 dd 20 f4 43 01 03 |l4q._...%.. .C..| +00000030 88 33 26 7f 48 c1 f2 d1 4d d3 f8 1a bd 86 4c 50 |.3&.H...M.....LP| +00000040 18 89 dc 08 99 f1 51 c5 84 be b9 fd 00 05 00 00 |......Q.........| +00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +000002b0 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...| +00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..| +00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.| +00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h| +00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...| +00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........| +00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| +00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| +00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| +00000090 01 16 03 03 00 24 08 65 01 80 0d 59 b8 ac 0f 09 |.....$.e...Y....| +000000a0 bf 61 31 32 e0 74 e9 f4 72 e3 2c 79 11 4d b2 a2 |.a12.t..r.,y.M..| +000000b0 55 65 94 c8 cd 0a 61 99 07 b8 |Ue....a...| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 04 20 46 cd fb |..........$. F..| +00000010 6c 46 9c 47 21 03 fe 9b a4 c6 da 2c 71 2f db 92 |lF.G!......,q/..| +00000020 40 da 7d 46 2e e4 9c 81 86 89 7f 53 46 91 28 |@.}F.......SF.(| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1a 89 2b 2e 49 21 19 b7 d0 df 85 da |......+.I!......| +00000010 b8 a7 f3 73 5f fe 44 e5 0c a1 af 16 74 93 bc 15 |...s_.D.....t...| +00000020 03 03 00 16 5f 9e 64 d0 91 50 34 44 cf f6 1f e0 |...._.d..P4D....| +00000030 e0 13 b9 67 da 5c 99 16 f1 b3 |...g.\....| diff --git a/src/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce b/src/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce new file mode 100644 index 0000000..06752de --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce @@ -0,0 +1,244 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 5b 4b bb c4 39 |....Y...U..[K..9| +00000010 fb 45 5c 54 03 30 0f 71 c3 2e 48 25 33 fd 6d 40 |.E\T.0.q..H%3.m@| +00000020 18 6e 75 43 66 9e 08 fb 6a a1 f8 20 34 3c c4 2a |.nuCf...j.. 4<.*| +00000030 b5 9b 65 b0 cd b9 fc ce cf 51 f8 cc a1 5d 00 ed |..e......Q...]..| +00000040 49 5b 43 9a ff c4 cf 6b d8 2a ea e5 cc a8 00 00 |I[C....k.*......| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 76 c4 f4 ec a2 d6 c1 |........ v......| +000002d0 b1 d8 b0 41 71 8a ee e9 8a 17 06 90 6b 0c 05 66 |...Aq.......k..f| +000002e0 54 d8 a6 ad 50 95 11 f0 03 08 04 00 80 46 0b da |T...P........F..| +000002f0 0b 0c 6c 1a 2e a2 7e 28 40 1b 40 9a b4 5c 36 88 |..l...~(@.@..\6.| +00000300 c1 ad cd 45 be 23 17 a6 98 e5 11 fe a8 78 c6 21 |...E.#.......x.!| +00000310 17 a6 a8 7d ce 28 c4 ef 51 76 f8 b1 b1 75 31 04 |...}.(..Qv...u1.| +00000320 b9 14 bc 3b bf 59 50 b8 e1 ad c6 86 45 3c e1 70 |...;.YP.....E<.p| +00000330 fb cd 69 8c 0a 5f f6 2d bd 10 95 30 ed 4c 9a 47 |..i.._.-...0.L.G| +00000340 73 8b 39 72 00 0a 7e 8f a9 42 27 01 6f 3d 37 f9 |s.9r..~..B'.o=7.| +00000350 7d d4 1b a2 6a 07 37 dc 5e 6c 8b b1 d5 75 3a 9b |}...j.7.^l...u:.| +00000360 d1 45 c5 d8 e0 90 f0 62 3d d5 01 00 9e 16 03 03 |.E.....b=.......| +00000370 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 bb f4 78 64 23 f7 31 50 42 3d 97 |.... ..xd#.1PB=.| +00000040 8f 73 89 b9 90 8f 74 b6 e4 7d 58 27 65 25 59 8a |.s....t..}X'e%Y.| +00000050 5a 8d 8f fa bd |Z....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 0a 43 74 53 47 |.......... .CtSG| +00000010 41 4b 0a f1 f7 75 51 a9 22 c9 e0 5c 53 90 6b d7 |AK...uQ."..\S.k.| +00000020 97 18 c6 ef c3 85 32 f5 7c 26 97 |......2.|&.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 8e 83 1a 32 53 02 1c fa 84 89 4f |........2S.....O| +00000010 25 fb 5f 85 4f bd ee ae 9f 0f ea |%._.O......| +>>> Flow 6 (server to client) +00000000 16 03 03 00 14 96 76 32 c4 6d e6 23 bf 21 a8 09 |......v2.m.#.!..| +00000010 a3 8b 69 98 cd c3 c9 ce 73 |..i.....s| +>>> Flow 7 (client to server) +00000000 16 03 03 01 16 72 5b d9 30 b2 b0 91 e2 3d 2b 12 |.....r[.0....=+.| +00000010 2c c9 43 f1 67 ae 54 ee ce a1 15 12 12 9a 27 46 |,.C.g.T.......'F| +00000020 7e 47 90 d4 f2 7d b9 98 ec f8 61 b8 84 52 9f 21 |~G...}....a..R.!| +00000030 c1 83 6a ce 1a 68 fc 5b 25 42 f3 8f 55 ee 92 45 |..j..h.[%B..U..E| +00000040 af a4 d1 c4 a6 b5 0e 58 3d 70 76 98 ec 47 af 6f |.......X=pv..G.o| +00000050 e3 4f 9f ef 52 a3 aa 33 75 83 f6 57 33 a8 dc f5 |.O..R..3u..W3...| +00000060 36 49 09 1c 72 31 c1 43 52 64 4a b5 ca ce 06 f5 |6I..r1.CRdJ.....| +00000070 91 18 90 85 f0 c9 96 4f bf 4c de 9e 50 a2 1c de |.......O.L..P...| +00000080 86 51 1f 0b 73 e1 df 1d 2d 90 6d 7f a2 f1 28 e8 |.Q..s...-.m...(.| +00000090 5f 2a 78 2d 8e ab f2 05 19 85 4e 92 a8 cf cd 16 |_*x-......N.....| +000000a0 1e df 1d 51 ee 8b ba 72 cd ac d2 01 4b 84 46 62 |...Q...r....K.Fb| +000000b0 1c 28 4d 3f 44 c1 62 12 13 4f f8 73 f4 da c0 98 |.(M?D.b..O.s....| +000000c0 14 da 31 6a 48 0d 1d bb 24 6c ef 0f 98 c0 3c 86 |..1jH...$l....<.| +000000d0 c6 d6 8e ab bd 20 bd 06 e9 ba aa ce 3a 88 25 95 |..... ......:.%.| +000000e0 54 15 fb c6 49 c7 98 ff 27 92 c0 60 6a 3c f8 26 |T...I...'..`j<.&| +000000f0 fd 28 ac c4 8f 5c 4f 15 24 10 45 3c 07 3d 3f 50 |.(...\O.$.E<.=?P| +00000100 e5 db cf 78 bd b0 d2 24 a2 4b 3e a6 9c 2d 3b 0d |...x...$.K>..-;.| +00000110 d8 1b 86 88 dc 0c 3c 9c 16 cf ea |......<....| +>>> Flow 8 (server to client) +00000000 16 03 03 00 81 2e c9 cd ad df 75 cf b6 8d 7f 8c |..........u.....| +00000010 c6 bb 5b e6 2b 40 a0 36 45 13 ae 93 f1 04 bf f3 |..[.+@.6E.......| +00000020 62 bd c8 62 d9 cf 05 a3 4c e9 37 af 35 a6 83 8e |b..b....L.7.5...| +00000030 71 46 b8 2a 5b 02 3b 81 d5 15 b8 17 72 c4 1e 00 |qF.*[.;.....r...| +00000040 78 d9 4a 04 a7 b3 5b 80 bd 1f 88 ba fa 22 b5 0e |x.J...[......"..| +00000050 ca 44 55 27 c0 67 ce 37 4c 9a 9a d7 77 da 58 35 |.DU'.g.7L...w.X5| +00000060 83 b3 39 90 8d e2 7f 08 2e cc 5a 8e 5e a8 c3 bb |..9.......Z.^...| +00000070 db e5 a2 56 56 04 37 13 f3 b1 71 2d ea 0a 56 00 |...VV.7...q-..V.| +00000080 6e 8d 8b 20 79 30 16 03 03 02 69 76 4b a4 c6 5e |n.. y0....ivK..^| +00000090 0a a2 3c 89 24 f6 93 94 25 4e 0b 8a d2 33 2f 03 |..<.$...%N...3/.| +000000a0 ab 20 22 33 ad 84 6d aa 31 6b 5a 10 0e 42 1b dd |. "3..m.1kZ..B..| +000000b0 35 9b a0 dc 31 f8 65 91 c4 14 78 2e 74 2e 1d 46 |5...1.e...x.t..F| +000000c0 3a 66 41 f0 a3 9a 4e ae bc 9b 55 f9 d1 9c c5 6e |:fA...N...U....n| +000000d0 38 24 19 15 fb e6 c3 85 de ef f0 97 a2 a1 db ed |8$..............| +000000e0 b8 d0 05 ae 93 77 d7 45 50 a5 4e 8a 83 84 07 fb |.....w.EP.N.....| +000000f0 3a 80 c6 69 3c 6e b2 e3 e0 97 f7 03 93 76 dd 32 |:..i..ON| +000002d0 73 91 a6 05 2b a7 89 e8 63 28 39 51 53 8d 2c 5e |s...+...c(9QS.,^| +000002e0 c8 64 90 c3 b7 2d ee 00 aa 7f 38 ca 57 ab b8 aa |.d...-....8.W...| +000002f0 93 12 af c5 16 03 03 00 bc 0e 58 31 64 e6 68 e6 |..........X1d.h.| +00000300 10 81 2f 79 e3 49 3a d9 cc 70 09 7e b6 b5 61 c4 |../y.I:..p.~..a.| +00000310 92 16 22 d0 e5 af b8 b8 91 2e 72 7c cf 95 cb ef |..".......r|....| +00000320 14 81 73 33 34 98 65 1b 69 db 2c 9d eb 1c ce be |..s34.e.i.,.....| +00000330 1f ce 48 b4 22 8d f0 6e 48 21 8e aa af 83 43 d2 |..H."..nH!....C.| +00000340 65 54 0f 57 6b ce b1 24 ef 09 bf 7f 23 92 35 07 |eT.Wk..$....#.5.| +00000350 55 2f 2f e7 b7 d7 72 d2 7c 5f 71 d6 20 9a 68 e8 |U//...r.|_q. .h.| +00000360 1b 90 0b 13 f7 37 e2 35 0d fc 04 ea 32 50 2d 04 |.....7.5....2P-.| +00000370 72 1a db d9 71 e1 4e d1 76 7c c3 f5 22 97 92 c5 |r...q.N.v|.."...| +00000380 61 19 e0 40 b1 14 de 37 9d 8e e7 fd fe 2b 28 97 |a..@...7.....+(.| +00000390 91 77 8f a7 d4 b1 db bc a2 78 65 5c a8 8d 41 21 |.w.......xe\..A!| +000003a0 0e 56 6b ac 0b da a9 dd b1 51 84 19 20 ab e5 eb |.Vk......Q.. ...| +000003b0 f2 52 8d 48 a2 16 03 03 00 4a 69 44 32 65 c2 09 |.R.H.....JiD2e..| +000003c0 9c c1 d6 66 06 29 c3 a6 c3 10 2e d9 9e d6 0a d3 |...f.)..........| +000003d0 06 a3 d2 d2 67 52 bd 19 26 a8 ef 08 ed 9f 2b e8 |....gR..&.....+.| +000003e0 96 ea 08 b7 46 a2 36 e3 c1 84 4b c2 a2 b5 34 9c |....F.6...K...4.| +000003f0 83 ea 94 51 e6 ca 9c 0b e1 e3 86 13 b7 1b 1f 4e |...Q...........N| +00000400 ee a1 10 70 16 03 03 00 14 5a 1c c1 14 fd d9 ff |...p.....Z......| +00000410 e3 46 ac 89 3b b3 e1 8e 6b 90 41 44 1f |.F..;...k.AD.| +>>> Flow 9 (client to server) +00000000 16 03 03 02 69 c8 db 54 92 d3 ea 2f 24 47 f9 24 |....i..T.../$G.$| +00000010 53 c1 d4 6a e8 dd 1d 71 d6 fb 2c 7e 3a 41 75 f6 |S..j...q..,~:Au.| +00000020 0c 08 70 b6 f9 0a 12 4b 0d 3d 34 03 a9 36 9e f1 |..p....K.=4..6..| +00000030 c7 93 dc 51 e4 15 3d fd a7 67 28 24 32 fe ff d3 |...Q..=..g($2...| +00000040 cd 69 d6 4a 5d 11 78 3b aa 07 8d 1e c4 97 22 34 |.i.J].x;......"4| +00000050 df 03 f2 37 fd 4f 76 c3 04 a6 a6 0f 35 1c 0f 13 |...7.Ov.....5...| +00000060 7e 0a b9 5e 47 d2 9a 8c d8 a3 f4 7a e4 92 5f 12 |~..^G......z.._.| +00000070 a6 20 fb 51 16 af eb 55 d0 23 4e b5 f9 e8 cc 33 |. .Q...U.#N....3| +00000080 bd d1 52 27 21 96 06 05 67 fa 68 0e ab 2c 84 05 |..R'!...g.h..,..| +00000090 c9 97 6a db 69 57 a8 5c 55 a9 e1 cf 33 01 28 9a |..j.iW.\U...3.(.| +000000a0 76 09 64 a4 a3 31 36 13 72 27 0c 85 e9 59 47 27 |v.d..16.r'...YG'| +000000b0 89 07 ee e2 e0 68 a6 f0 fa d5 c3 8b 2f 75 68 d0 |.....h....../uh.| +000000c0 8e d8 fe ae 1d 0d af 0b 40 3d 9f ec 85 03 24 20 |........@=....$ | +000000d0 c5 11 30 aa 25 ee 2c 86 42 ae 4f 0d 6b 18 70 1d |..0.%.,.B.O.k.p.| +000000e0 5f ae 1e cf 99 a7 0e c8 9b b3 63 58 cd b6 7d be |_.........cX..}.| +000000f0 01 43 96 37 87 45 5f 2f aa 9c 12 48 ef 3b c8 d9 |.C.7.E_/...H.;..| +00000100 60 20 26 69 68 56 48 aa 64 59 9e 41 ed 7e 8d c3 |` &ihVH.dY.A.~..| +00000110 0f cd 0e 19 7a 76 89 95 f8 20 68 cd f9 81 e9 a0 |....zv... h.....| +00000120 21 ff 60 e5 0f 6d dd 73 d2 19 1e 2a 76 f7 9a 46 |!.`..m.s...*v..F| +00000130 5d d5 6b b2 19 28 c2 ac 9c e0 35 c8 d2 2a 53 fa |].k..(....5..*S.| +00000140 3e 58 9e f2 05 7e 6b ce 51 6d 3d 2a ce 2e 9b 59 |>X...~k.Qm=*...Y| +00000150 aa d4 8d cc ad 1f 82 e7 ca 5a ef a6 87 d5 41 0b |.........Z....A.| +00000160 8d 27 6d 09 4d 40 c3 26 a3 a9 91 dd 1b 37 5d ff |.'m.M@.&.....7].| +00000170 8f c3 c7 b1 bf be f5 d1 19 4d 93 86 a7 5f 5e 8f |.........M..._^.| +00000180 14 34 82 50 76 25 42 04 b8 4b d3 da 15 ee 60 d1 |.4.Pv%B..K....`.| +00000190 35 56 4c 63 0d ba 64 13 4f 3d 12 87 84 5a 45 41 |5VLc..d.O=...ZEA| +000001a0 14 b6 6f 91 c4 b9 4f 97 c1 10 d6 3e b3 99 21 18 |..o...O....>..!.| +000001b0 c3 91 82 e4 b6 91 3e bb 01 89 9a f0 60 ac 8e 7d |......>.....`..}| +000001c0 cf c2 f9 b4 4f da 40 e3 5e 83 a1 8f b4 fa 28 aa |....O.@.^.....(.| +000001d0 c9 ae 7b 8f 7d c9 d1 f8 7b b2 b5 3f 0a 9b 00 9e |..{.}...{..?....| +000001e0 1d fa 59 ff 39 b7 85 4d 2a b9 b8 67 03 df a0 f9 |..Y.9..M*..g....| +000001f0 f1 7e 9d 27 1c 55 a9 76 44 9e f1 13 78 7d 34 4d |.~.'.U.vD...x}4M| +00000200 c9 23 07 e6 db 93 d7 70 3c 1b 5d 89 ed 8d 3d 43 |.#.....p<.]...=C| +00000210 2e 89 f6 14 83 ff 87 db 26 a5 9a cd 98 5d 32 24 |........&....]2$| +00000220 70 d2 e0 72 a7 6f a4 b4 2b 37 db 7e 39 4f d7 37 |p..r.o..+7.~9O.7| +00000230 ea 68 b5 98 33 0e 23 21 3f 43 b3 ff 18 8e df 85 |.h..3.#!?C......| +00000240 ba 15 48 3a fe 09 9b b6 27 40 d4 60 a8 3e 55 a3 |..H:....'@.`.>U.| +00000250 75 c9 32 38 b5 21 46 ab 41 99 24 e6 09 3f 64 e6 |u.28.!F.A.$..?d.| +00000260 09 40 cb 93 25 ab 1a 90 c7 d5 a6 40 36 a0 16 03 |.@..%......@6...| +00000270 03 00 35 0f c7 e4 c3 16 c0 4f 7f 25 04 06 63 e7 |..5......O.%..c.| +00000280 79 79 f9 4f c9 66 ca cd ba e3 af 4a 50 a3 3d c3 |yy.O.f.....JP.=.| +00000290 79 0c 71 d9 2f df 93 79 30 8f 6b 0f 54 f9 be 07 |y.q./..y0.k.T...| +000002a0 f3 d6 9b c0 2a 3a 0a a1 16 03 03 00 98 b8 f1 fc |....*:..........| +000002b0 87 62 e9 6b 40 fd 50 ac b7 fa 52 69 51 66 ae 9b |.b.k@.P...RiQf..| +000002c0 05 7e f2 38 73 27 d8 0c 2a 53 37 30 62 76 5d e9 |.~.8s'..*S70bv].| +000002d0 fd 95 c6 14 d2 9d 34 13 e9 4c a5 7c c0 b6 e0 c4 |......4..L.|....| +000002e0 97 ef 01 c0 f9 38 39 ee 17 c0 20 01 76 4f a7 10 |.....89... .vO..| +000002f0 b0 45 9d c7 c3 cd a9 47 14 4a ed 00 1f 06 70 5b |.E.....G.J....p[| +00000300 f5 04 8b 77 ad af 1e 77 7a 9d cc fc a4 1f d2 8d |...w...wz.......| +00000310 8f e3 31 d3 3c de e6 85 f3 3d c0 ae 78 f7 22 c6 |..1.<....=..x.".| +00000320 ec 2e a2 f0 5f ed 95 33 54 8c 89 35 c9 e4 25 4b |...._..3T..5..%K| +00000330 84 5e 31 83 04 d0 f1 67 69 73 8b 7f 24 ae e0 87 |.^1....gis..$...| +00000340 6b f7 ba f0 23 14 03 03 00 11 7a c7 6a 32 2b 9b |k...#.....z.j2+.| +00000350 25 c2 d2 ee 37 b2 8d 7b f2 90 6d 16 03 03 00 20 |%...7..{..m.... | +00000360 c1 1c 9d 18 a9 41 92 fc 05 19 93 7c 7e 2f b2 39 |.....A.....|~/.9| +00000370 8c 76 4b 29 5a 67 cc f5 55 9f c0 e3 8f ad ee 3c |.vK)Zg..U......<| +>>> Flow 10 (server to client) +00000000 14 03 03 00 11 49 66 13 ec 09 83 0d 47 82 45 61 |.....If.....G.Ea| +00000010 06 14 cc f5 da 41 16 03 03 00 20 34 d4 0c bd 86 |.....A.... 4....| +00000020 6d ef a9 b6 97 68 e6 88 84 ed 1c 9d a1 8d 2b c9 |m....h........+.| +00000030 2f 45 75 5b e5 6a 08 72 71 a9 c6 17 03 03 00 19 |/Eu[.j.rq.......| +00000040 e8 83 4c f5 19 ea d1 ef e3 27 25 f9 af d2 f0 a6 |..L......'%.....| +00000050 b3 62 15 66 ec 72 ce 4e e2 |.b.f.r.N.| +>>> Flow 11 (client to server) +00000000 15 03 03 00 12 2e 39 ba ca ad 7c a9 ae 3f 6a 78 |......9...|..?jx| +00000010 b6 31 d2 d0 4e 1f dc |.1..N..| diff --git a/src/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice b/src/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice new file mode 100644 index 0000000..20aa6c9 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice @@ -0,0 +1,343 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 68 39 1d 0e 5a |....Y...U..h9..Z| +00000010 22 ba 13 5f b6 c1 52 5d 13 e5 07 18 aa ec 24 0f |".._..R]......$.| +00000020 c9 56 3a 83 a1 32 a1 7f 02 e8 7b 20 31 e2 f8 c4 |.V:..2....{ 1...| +00000030 5b c2 57 9a 1d a4 6f a7 9c 1c 93 b1 9f 19 c3 cb |[.W...o.........| +00000040 e1 73 87 1b a8 88 d9 4c 67 2f 44 aa cc a8 00 00 |.s.....Lg/D.....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 57 22 18 98 ed 7f 12 |........ W".....| +000002d0 e7 e3 83 6b 42 82 ff 49 54 f8 0b 7d 93 3d 11 42 |...kB..IT..}.=.B| +000002e0 67 cf 89 47 77 31 c5 59 4a 08 04 00 80 69 d4 13 |g..Gw1.YJ....i..| +000002f0 f8 1c 68 9d 40 10 c8 aa e6 44 0e 14 b9 38 6e ca |..h.@....D...8n.| +00000300 a9 50 05 4a ce a0 03 ea 02 92 e4 5a ed 42 6f 70 |.P.J.......Z.Bop| +00000310 e1 c1 99 49 a4 34 20 6b 5e 14 e8 a1 d3 27 ff 0d |...I.4 k^....'..| +00000320 0c d7 47 49 1e 8f 8a 3a 62 1d c9 81 3c 5f a3 16 |..GI...:b...<_..| +00000330 16 34 a0 53 a7 01 1d 09 f7 d9 d4 62 b2 0a 1c 1f |.4.S.......b....| +00000340 b2 e5 24 1b 7e 78 35 43 ed 47 f8 62 53 2d 04 ec |..$.~x5C.G.bS-..| +00000350 81 b5 68 11 3a 2d ee 88 ef 86 eb 71 d0 5e 31 42 |..h.:-.....q.^1B| +00000360 57 6d b6 f2 be 32 4c 38 f8 2a 93 2f db 16 03 03 |Wm...2L8.*./....| +00000370 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 2a 03 0a 58 36 31 ec 26 df e5 7c |.... *..X61.&..|| +00000040 88 b5 d1 f7 6d fc 4b 0a 91 54 4a e7 8c 83 a3 54 |....m.K..TJ....T| +00000050 0a 10 5b ff 69 |..[.i| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 27 b0 69 0c 67 |.......... '.i.g| +00000010 c7 3a ec c1 aa 02 20 cf f9 e8 22 86 3b d3 e1 4f |.:.... ...".;..O| +00000020 bc fd 04 40 19 77 bf bd 38 28 56 |...@.w..8(V| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 8a 2c 24 1b b8 53 01 54 c8 bd f3 |......,$..S.T...| +00000010 e1 ec a9 ab 83 a0 66 a9 29 1c 4e |......f.).N| +>>> Flow 6 (server to client) +00000000 16 03 03 00 14 c5 e3 03 06 89 d8 47 1a 66 18 0e |...........G.f..| +00000010 8d 36 c5 f4 30 80 7e 72 a2 |.6..0.~r.| +>>> Flow 7 (client to server) +00000000 16 03 03 01 16 7e eb a3 b5 ea 58 e3 4a 26 35 7d |.....~....X.J&5}| +00000010 54 15 93 74 e8 e4 63 34 38 d9 e0 02 3d 28 f8 98 |T..t..c48...=(..| +00000020 0f 24 6b ca 08 7f b6 77 68 ec 85 c3 4a 6b 69 c3 |.$k....wh...Jki.| +00000030 8d 8e 1b 8b 41 11 9b 0d d1 c8 99 2b c9 d2 4c f1 |....A......+..L.| +00000040 fd 82 e5 35 ba a3 3b f3 6d 47 82 45 08 e7 02 bb |...5..;.mG.E....| +00000050 10 a6 7b 76 83 78 e0 aa 5a 78 24 59 1c db ae a3 |..{v.x..Zx$Y....| +00000060 37 20 b3 12 98 48 68 d3 b3 72 9f 4f d4 de 50 b4 |7 ...Hh..r.O..P.| +00000070 4a c1 37 93 e0 55 ae e8 37 2a 40 de ac 30 e1 1d |J.7..U..7*@..0..| +00000080 f0 03 19 8c af 77 f5 26 98 af a8 a8 d2 72 6c 68 |.....w.&.....rlh| +00000090 75 00 32 10 e6 3f 91 a8 24 a7 d8 05 23 04 52 23 |u.2..?..$...#.R#| +000000a0 e7 e6 83 ac 37 1b 36 a7 ca d4 7e d5 21 4c ab 38 |....7.6...~.!L.8| +000000b0 23 cb 7c a9 f4 66 26 5e 7f 3e d6 ab 7a ac 34 38 |#.|..f&^.>..z.48| +000000c0 95 16 df e2 e4 cf 3a 62 82 78 cb 71 32 06 6d 07 |......:b.x.q2.m.| +000000d0 84 91 0c e9 d0 63 88 9e d1 b5 f0 fb 43 2b 07 0b |.....c......C+..| +000000e0 32 d7 20 af b8 76 17 da ee cc e6 03 bb 7a 0b f2 |2. ..v.......z..| +000000f0 61 4f db 7f a3 66 b0 05 a8 88 b8 0b b3 6e 9c df |aO...f.......n..| +00000100 48 8b 7e eb 42 cd ea eb 1d bb 63 a0 e4 ee df 21 |H.~.B.....c....!| +00000110 20 67 11 26 dd f1 47 1b 15 2b a0 | g.&..G..+.| +>>> Flow 8 (server to client) +00000000 16 03 03 00 81 60 70 d6 32 5a 0a 8f df ed cd f2 |.....`p.2Z......| +00000010 d7 bf d0 da fd 53 63 65 bf f5 26 83 0c f5 6e e9 |.....Sce..&...n.| +00000020 78 9b 03 7b 17 5f f4 d2 af 2a a3 85 13 92 be 00 |x..{._...*......| +00000030 93 3f b3 f1 cb 04 aa 55 f8 ed c8 e6 9c 32 08 79 |.?.....U.....2.y| +00000040 86 84 ef ac 72 bd 93 07 9c ca d2 e7 74 dd 51 a0 |....r.......t.Q.| +00000050 6d 0e d3 32 3c 33 9d 58 aa 46 a9 ff 22 08 bc 2c |m..2<3.X.F.."..,| +00000060 de 81 aa a8 5a 3c f8 36 93 d3 12 06 79 61 1f 71 |....Z<.6....ya.q| +00000070 5f 45 d7 99 b2 55 10 22 db 56 d9 39 64 57 ad c3 |_E...U.".V.9dW..| +00000080 59 a9 bd cb f2 22 16 03 03 02 69 34 e7 f2 7a bc |Y...."....i4..z.| +00000090 0b 90 72 a3 3b 6b 38 a3 f8 7a 19 39 ff b4 d6 8c |..r.;k8..z.9....| +000000a0 c9 92 4f a3 23 1a f0 89 bb 01 e4 b2 24 f7 db 3d |..O.#.......$..=| +000000b0 f4 4b 02 75 d0 ca 3c ed e8 d9 13 61 c5 61 4e 7c |.K.u..<....a.aN|| +000000c0 fe b9 49 69 63 cc 23 5f 9b 23 85 ec 86 e5 17 28 |..Iic.#_.#.....(| +000000d0 8a 1e 0c 45 e5 4d c2 be 66 92 47 88 28 ec 52 eb |...E.M..f.G.(.R.| +000000e0 72 e5 30 89 58 8d 15 2b 98 eb cd e2 18 7c 53 f2 |r.0.X..+.....|S.| +000000f0 89 ba 71 a5 91 20 64 17 7c 56 f1 01 8a 52 17 66 |..q.. d.|V...R.f| +00000100 ef d7 bc 5b ff 54 53 13 2e 80 53 4c 84 6d a2 20 |...[.TS...SL.m. | +00000110 0f e6 3d 33 90 7a 5b 1a 50 29 ce 1e af 74 a5 b3 |..=3.z[.P)...t..| +00000120 0e 29 c8 e5 c1 50 b6 5d c8 bb e4 b5 f5 6b 04 a8 |.)...P.].....k..| +00000130 24 a6 a8 cc 77 7c 72 d5 b1 f3 6a 1c 2e d7 7e e0 |$...w|r...j...~.| +00000140 4c 46 3f 26 61 2e 54 7d ab d8 d6 ec 1e b0 0d d1 |LF?&a.T}........| +00000150 02 57 00 7f 29 aa d3 1d a4 40 73 d7 21 12 76 58 |.W..)....@s.!.vX| +00000160 7d 79 a5 c1 d2 57 63 48 0e 63 5f 24 49 8a 57 ba |}y...WcH.c_$I.W.| +00000170 26 1c 39 4a f8 b3 89 79 e2 be 4e 8e 37 ae 16 75 |&.9J...y..N.7..u| +00000180 42 5e 2e 9b 14 d5 b3 06 5f b9 c8 f7 16 8f eb 1c |B^......_.......| +00000190 48 0a da 1e b3 4a 78 f7 f8 b4 35 bf 7d 3f c5 8d |H....Jx...5.}?..| +000001a0 fa 7d c0 b7 52 af d3 13 de 96 39 76 fd 49 80 55 |.}..R.....9v.I.U| +000001b0 bb b3 0f 5b 0c 84 4d 8b da 62 8a 20 4b a1 28 28 |...[..M..b. K.((| +000001c0 3d 74 cc 34 9d 95 8e af c0 05 a2 5c 73 9d 73 d8 |=t.4.......\s.s.| +000001d0 6c 4e 77 25 c5 8c 22 07 c6 b9 55 47 0c b2 12 73 |lNw%.."...UG...s| +000001e0 2e f5 95 f7 28 c3 e4 24 2c fd 05 ac e2 3e df 93 |....(..$,....>..| +000001f0 5a 28 66 aa d4 86 8a 48 e2 c8 69 01 18 90 54 10 |Z(f....H..i...T.| +00000200 67 80 a1 be a8 9a 7f f3 17 ee dc 83 06 7a 70 6c |g............zpl| +00000210 59 c2 2d 8f ff 79 a7 e5 e2 f2 f3 f3 5b 44 42 25 |Y.-..y......[DB%| +00000220 a3 8c a0 83 07 5c f6 73 e9 bd f5 6b 86 89 b4 11 |.....\.s...k....| +00000230 7b 9a 28 52 4f 55 70 4a 75 00 73 cc 84 fa 4a ef |{.(ROUpJu.s...J.| +00000240 f8 8a 8d f9 18 e2 bc 13 48 cb 80 4d 6f fc d7 23 |........H..Mo..#| +00000250 3a 9c 6c fd 46 27 94 8a 3d 9d fb 17 f5 06 4d a1 |:.l.F'..=.....M.| +00000260 18 75 a7 9b 08 f8 47 b5 52 b4 19 4b b7 0f a4 e0 |.u....G.R..K....| +00000270 78 f8 8b a4 cc eb d3 85 e1 ad 21 29 0f c7 09 28 |x.........!)...(| +00000280 3f 21 12 6c fd 76 05 13 10 a0 c1 ce ba 7c e8 6f |?!.l.v.......|.o| +00000290 e9 99 67 0a 9d 3a 7f f1 a6 8a 53 56 f1 09 22 21 |..g..:....SV.."!| +000002a0 24 23 6e bc 77 fc 56 3b 31 15 58 1b e9 03 a1 bf |$#n.w.V;1.X.....| +000002b0 0a 06 a0 fb 47 77 b7 ad 01 db ee 6a bc a4 a1 77 |....Gw.....j...w| +000002c0 6f 3e 70 84 4c a6 21 ec ff fa f0 f0 68 ee 7d b1 |o>p.L.!.....h.}.| +000002d0 e6 37 f1 1c aa 43 c7 b9 0e c4 52 7d 54 d8 f7 c5 |.7...C....R}T...| +000002e0 16 21 99 89 cb 02 d0 54 b8 0e 91 2e 58 25 32 6e |.!.....T....X%2n| +000002f0 fa ae 62 c9 16 03 03 00 bc 0c 2f 7e 22 d8 7f 21 |..b......./~"..!| +00000300 0c 1a ec e1 37 72 3f 03 1d cc 73 f9 63 95 cd 47 |....7r?...s.c..G| +00000310 66 17 60 8c da b4 35 a2 44 b1 d8 d1 1c 98 5b 8b |f.`...5.D.....[.| +00000320 c8 9b c8 cb c4 15 0d 8d 08 1e 7c 3a 6b 20 3a f1 |..........|:k :.| +00000330 d1 86 ae 08 bb fd 74 c5 62 9a 50 74 07 96 10 0e |......t.b.Pt....| +00000340 e0 e4 a4 da c4 9d d1 f4 15 97 7d 21 0f 6f cb 39 |..........}!.o.9| +00000350 8e 4e 40 1a 2a 7f 15 88 94 52 bc fd 61 b8 37 d1 |.N@.*....R..a.7.| +00000360 48 62 bc 53 a3 a6 62 ec 0e c3 1f 82 67 19 71 fa |Hb.S..b.....g.q.| +00000370 99 16 c3 cf d6 82 44 36 9e 0b f0 41 12 ca 7b 67 |......D6...A..{g| +00000380 c3 a6 2d f7 13 14 0f d1 16 f9 2a 5a dd 43 45 c6 |..-.......*Z.CE.| +00000390 c0 f4 17 36 64 11 fc ed e6 66 b6 0c e2 3d fb 72 |...6d....f...=.r| +000003a0 93 27 46 20 db 1b 24 f9 69 a0 c7 71 e2 27 6a 93 |.'F ..$.i..q.'j.| +000003b0 36 73 71 10 bd 16 03 03 00 4a cb 15 91 9c 22 96 |6sq......J....".| +000003c0 f0 c8 b9 4d 9a 6c b0 eb 1a c5 d4 06 12 89 44 1b |...M.l........D.| +000003d0 52 cd fb 32 3f 2c 25 f4 d3 88 0f e4 9c 18 91 59 |R..2?,%........Y| +000003e0 42 98 a8 65 35 62 f7 ce fa a3 56 46 c5 b1 da ac |B..e5b....VF....| +000003f0 9e 4e de 8d 14 fc 3c f3 94 74 50 99 1d 65 6b a6 |.N....<..tP..ek.| +00000400 a9 38 93 9f 16 03 03 00 14 d7 5b 68 ca 4c 80 92 |.8........[h.L..| +00000410 f8 13 5d fe 14 22 6f 9a 42 3a 27 de c8 |..].."o.B:'..| +>>> Flow 9 (client to server) +00000000 16 03 03 02 69 aa 39 9e c8 e7 89 97 7f 22 3c 28 |....i.9......"<(| +00000010 76 ac d9 48 51 e0 cd 22 53 a1 6d e7 b4 00 27 7d |v..HQ.."S.m...'}| +00000020 89 4b f0 54 d8 39 d0 a3 fc 35 a6 36 4b 3c eb 3a |.K.T.9...5.6K<.:| +00000030 00 b0 c1 17 9d c8 13 a5 58 ba 16 9e cb 21 50 dd |........X....!P.| +00000040 8a e0 2d 57 dd a6 bf 4d 6e b3 21 3b 46 f4 c3 77 |..-W...Mn.!;F..w| +00000050 a1 86 07 c7 db e9 0a cb 2d 0f ff b5 1b ad 6b c4 |........-.....k.| +00000060 c4 a4 4e 14 cf cb b2 6c 07 65 17 d2 db 30 e9 ec |..N....l.e...0..| +00000070 41 4e 78 26 12 27 08 a6 a7 84 39 c0 4b e7 4b 23 |ANx&.'....9.K.K#| +00000080 2f ca ff 1e 41 9a e8 44 fc 5d a0 34 4e ca a8 6d |/...A..D.].4N..m| +00000090 31 51 57 c9 7e d1 0a 42 22 f2 b4 f9 a7 f9 28 d8 |1QW.~..B".....(.| +000000a0 2a dd 19 0d 90 8b e1 78 b1 1c da 3a bb 5e 05 54 |*......x...:.^.T| +000000b0 0d 0e f8 73 ed 01 e2 e4 d4 c1 f8 fa c3 d6 6f 42 |...s..........oB| +000000c0 cc cb 99 99 97 18 b0 fb ab 51 42 66 45 67 b6 29 |.........QBfEg.)| +000000d0 02 60 ab 74 30 db f6 16 8a 8f 8e 9c cc d5 47 fa |.`.t0.........G.| +000000e0 f5 af 94 4f b1 94 40 57 ab 85 59 e4 3e cc c5 a0 |...O..@W..Y.>...| +000000f0 61 b7 64 f9 dc 96 40 ae fb 4c 57 39 9e 9a 23 8e |a.d...@..LW9..#.| +00000100 c9 36 6c 75 11 c7 6e 54 c3 1c e9 25 6a a0 f8 bb |.6lu..nT...%j...| +00000110 6b 5c ca 5c 06 6c 03 88 01 27 4c 89 02 e6 b6 1a |k\.\.l...'L.....| +00000120 92 99 4d 15 c1 1a aa 58 20 49 d7 4a f9 09 34 1e |..M....X I.J..4.| +00000130 d7 d8 31 79 9f d8 b3 a0 76 ba 96 77 77 77 5b 80 |..1y....v..www[.| +00000140 88 ab a0 90 c7 5f 3d 82 e1 23 29 6e 3a 4d 9b f0 |....._=..#)n:M..| +00000150 7b 6a b1 9d 78 ba 4c 7e 02 1f a0 73 3e 91 cf 75 |{j..x.L~...s>..u| +00000160 c6 52 2d c6 79 be 85 65 0e e4 73 39 fe 53 6d e0 |.R-.y..e..s9.Sm.| +00000170 a3 18 d5 69 80 ca f1 c8 ad f5 f4 fb b5 40 2e f8 |...i.........@..| +00000180 30 82 ca 2c 46 6a ab a6 b2 83 9f a8 95 95 30 e3 |0..,Fj........0.| +00000190 e3 30 6d f5 7c 83 96 af 12 d8 d6 d6 f9 6a ad bd |.0m.|........j..| +000001a0 bb 96 83 99 99 d8 6d 20 0e e1 be da 58 05 44 88 |......m ....X.D.| +000001b0 a6 07 47 84 d4 77 fc 9b fb d7 ac 60 70 0b e7 76 |..G..w.....`p..v| +000001c0 13 c7 38 d9 3d 60 eb a6 9f a5 6d fc 5c d5 f6 2f |..8.=`....m.\../| +000001d0 31 02 38 65 8d be 04 06 84 95 86 b1 84 d9 ce c7 |1.8e............| +000001e0 30 b9 d3 85 9f 1b 12 0f 5c 0e d6 8d e3 a0 15 04 |0.......\.......| +000001f0 03 62 9d 52 7b e7 f4 13 aa 02 64 d9 d4 4b fd 6f |.b.R{.....d..K.o| +00000200 de ea 4a aa 91 60 e7 78 af 84 b5 9d c3 d2 c6 3a |..J..`.x.......:| +00000210 2a 9f 9b c6 8d 9e 5e 2c 90 6c d3 9d c1 be 96 5a |*.....^,.l.....Z| +00000220 60 d8 73 6c 49 50 c8 03 ec 58 73 bc b3 8c 30 c1 |`.slIP...Xs...0.| +00000230 f4 a2 7d 74 3d 8d 7e 64 c1 a7 b6 24 13 06 72 1b |..}t=.~d...$..r.| +00000240 d0 87 22 af df 2a e7 fe 57 fa db e7 00 ba 74 35 |.."..*..W.....t5| +00000250 16 34 20 3f 75 69 35 5f 64 7e 26 56 7c 93 05 4e |.4 ?ui5_d~&V|..N| +00000260 42 65 b8 bf 59 8e 82 13 f1 d0 05 95 c2 3d 16 03 |Be..Y........=..| +00000270 03 00 35 99 1d 52 84 73 d6 e7 90 f6 41 9e 69 07 |..5..R.s....A.i.| +00000280 39 0b bc b6 c7 f4 f2 a0 93 80 b9 c7 bb b4 a6 06 |9...............| +00000290 50 5b 5d 75 97 cf c5 dc 2d 07 3d 8f 9e ae fa bf |P[]u....-.=.....| +000002a0 5b 6b 3e 98 02 fd e4 7d 16 03 03 00 98 80 ac e9 |[k>....}........| +000002b0 4e e0 f8 b5 8c c2 2e 84 ec e0 3b eb b7 a0 14 2d |N.........;....-| +000002c0 ff d2 bf 35 14 20 06 00 2e 48 c7 f8 a3 fd 4f 50 |...5. ...H....OP| +000002d0 4a 04 3e c7 07 50 90 72 29 f0 5c ac e1 fd 9d 3f |J.>..P.r).\....?| +000002e0 42 99 77 32 a9 79 24 7f 9e cc 84 1c d0 db 87 1c |B.w2.y$.........| +000002f0 3c 9a ae e3 45 e5 67 83 5f 75 e9 27 f3 ef 8a 15 |<...E.g._u.'....| +00000300 88 2b 3f cc 6f 6f a4 78 d5 b2 96 3e 72 d4 c8 43 |.+?.oo.x...>r..C| +00000310 98 a7 60 ae 38 8e fe 21 49 5b c2 80 d6 ef 6f 9b |..`.8..!I[....o.| +00000320 08 18 07 c2 64 00 a1 a0 09 8b b4 b7 eb 0c 68 30 |....d.........h0| +00000330 26 87 f9 99 85 63 35 81 5a e4 31 19 9e f8 b8 7b |&....c5.Z.1....{| +00000340 81 aa 24 ff cd 14 03 03 00 11 84 c7 e1 8f 74 66 |..$...........tf| +00000350 e6 bd 14 55 a8 d3 67 30 2d c4 fb 16 03 03 00 20 |...U..g0-...... | +00000360 3a 63 a5 86 f3 78 f1 62 18 77 f7 25 71 52 56 17 |:c...x.b.w.%qRV.| +00000370 d2 a5 e4 fa bc bb 44 07 85 37 cb 36 84 c7 6a 97 |......D..7.6..j.| +>>> Flow 10 (server to client) +00000000 14 03 03 00 11 9e 99 89 2d 10 21 a1 38 04 77 1a |........-.!.8.w.| +00000010 f8 1d b4 01 d1 9f 16 03 03 00 20 2a cb 67 8b 1b |.......... *.g..| +00000020 44 26 41 7b c4 6d a1 f4 cb ee 15 87 01 65 18 5a |D&A{.m.......e.Z| +00000030 c7 2d 10 e4 91 01 cb 22 e8 92 1a 17 03 03 00 19 |.-....."........| +00000040 1a 46 a0 9a c5 1a 27 0c e2 f9 03 55 3a e8 43 a7 |.F....'....U:.C.| +00000050 d7 47 a5 95 6a e7 a1 12 69 16 03 03 00 14 d6 e0 |.G..j...i.......| +00000060 1d 89 e0 c2 9a 52 d5 bc d4 08 3e f6 81 dd 57 a2 |.....R....>...W.| +00000070 25 f6 |%.| +>>> Flow 11 (client to server) +00000000 16 03 03 01 16 27 50 ce c0 8e 5a e2 54 55 cb c0 |.....'P...Z.TU..| +00000010 08 c7 20 87 7e 78 c6 da a6 7a 62 fd 7f f5 87 b3 |.. .~x...zb.....| +00000020 83 a0 c8 70 ab 57 9b ca bf 4c 07 06 f1 89 b9 b6 |...p.W...L......| +00000030 24 f0 ae 72 e1 36 31 9f 74 ed 06 ad 44 3b 51 2c |$..r.61.t...D;Q,| +00000040 ed f0 c2 d8 9b 27 d2 9a ec 44 88 80 7c 5a d0 66 |.....'...D..|Z.f| +00000050 3d 84 e3 7c 24 89 b9 dd 8c eb 86 cd ce 69 0d e3 |=..|$........i..| +00000060 97 ee ad 74 53 7f 9c f0 05 31 43 2a 8c 09 c4 11 |...tS....1C*....| +00000070 46 3e 82 2c 3c 69 91 d1 eb 4b 8a ab a9 cb 24 00 |F>.,>> Flow 12 (server to client) +00000000 16 03 03 00 81 37 3a f4 1b 6a 43 d2 6a 02 02 33 |.....7:..jC.j..3| +00000010 b9 d5 9a 5c d1 3b 52 73 f2 27 a6 c0 f0 9b dd f3 |...\.;Rs.'......| +00000020 d7 cd 89 ec 21 e0 d3 2f 4d 6c b0 cf 50 a7 39 43 |....!../Ml..P.9C| +00000030 c2 56 d2 f8 45 d7 3c a6 b6 b9 06 3f ca a7 f8 37 |.V..E.<....?...7| +00000040 4c 89 01 49 82 5f 27 15 3c bf f0 86 7c 1a 84 03 |L..I._'.<...|...| +00000050 5a 90 77 03 01 fd b8 60 2a be cc 60 c6 54 b5 ec |Z.w....`*..`.T..| +00000060 c1 5d 6b e6 f0 2c 8c e6 7e e3 b6 c3 8b 63 3c 69 |.]k..,..~....c..+L.?...@K..| +000000f0 77 8f 40 1c a2 96 7c d3 ce 34 5e d8 13 5a 82 33 |w.@...|..4^..Z.3| +00000100 41 59 fa d9 81 1c 85 41 9c 61 b9 ca d5 46 e2 77 |AY.....A.a...F.w| +00000110 3d a9 50 4f 11 b1 34 aa ae fd e5 ec fe 12 e6 10 |=.PO..4.........| +00000120 36 84 fb 25 f8 a4 6f 44 e3 ac 89 67 e4 9a 02 c4 |6..%..oD...g....| +00000130 8f a9 4a d0 f4 64 e2 de da 80 02 60 cb a9 2d e0 |..J..d.....`..-.| +00000140 fa d9 b9 ee 43 e1 3e ed 79 79 6b 21 62 3d 6f b0 |....C.>.yyk!b=o.| +00000150 77 53 db 26 60 e1 d6 ff a7 01 2b b7 f0 49 df b8 |wS.&`.....+..I..| +00000160 bc d9 ac 77 80 f8 53 66 16 8d 3a 8d 63 fa 12 e1 |...w..Sf..:.c...| +00000170 ed f7 8b c0 40 46 16 70 e3 db f3 38 87 9f 11 eb |....@F.p...8....| +00000180 0b f5 b3 44 e4 16 e1 ed 85 e6 67 d5 35 60 20 99 |...D......g.5` .| +00000190 7d bd 9f 65 b9 52 68 6c 6b 83 f9 06 e3 a7 3e 0f |}..e.Rhlk.....>.| +000001a0 9e 7c a5 ac 87 7a 45 53 a5 3f 27 5b 99 a9 34 c2 |.|...zES.?'[..4.| +000001b0 5a 44 9a 30 08 30 c6 ff 60 8a a5 72 f7 49 d3 7c |ZD.0.0..`..r.I.|| +000001c0 1f f9 8b 74 a0 b1 c8 65 84 6d 91 86 ab 1e 82 3b |...t...e.m.....;| +000001d0 d5 c4 bb 06 b3 31 61 bb 0e 65 3e 18 4d 0c c1 c1 |.....1a..e>.M...| +000001e0 9d 7f ea ad cf 53 2e 9c 1c 7e aa c8 84 9e 0d ce |.....S...~......| +000001f0 91 53 3c d4 05 7e 57 d1 8b 55 ea e4 6e 57 90 4c |.S<..~W..U..nW.L| +00000200 bb 74 9c 87 1c 6a 89 cf 2c 50 8d 04 04 e6 18 c8 |.t...j..,P......| +00000210 0c 9f 38 84 f4 f4 94 8d 33 2b a1 27 0b 5c 6a 2a |..8.....3+.'.\j*| +00000220 0c 13 b7 07 b7 a0 c9 e5 3c 9d 5a 7e 96 c9 53 fc |........<.Z~..S.| +00000230 ff c4 3a 8f 16 1f 2d 64 50 1d 13 c3 55 fb af d2 |..:...-dP...U...| +00000240 0e f9 e6 18 e3 62 ce 6a 8f 96 ff 00 0e fe 27 53 |.....b.j......'S| +00000250 70 57 53 2d fd f3 02 c7 fe b3 19 49 88 27 7e a2 |pWS-.......I.'~.| +00000260 42 7b 22 d0 77 4e e5 04 aa 0d b6 9d b9 48 97 ab |B{".wN.......H..| +00000270 33 e7 14 97 65 82 f9 2c dc 71 9e 4b eb ed 42 73 |3...e..,.q.K..Bs| +00000280 c6 c8 93 8a 3a 24 bd f9 b4 6a 95 c1 1b 22 1d f5 |....:$...j..."..| +00000290 c8 33 c5 38 1e a7 2e 91 68 35 4c 0a 37 57 ac e2 |.3.8....h5L.7W..| +000002a0 c9 37 9e d9 1c b8 76 73 c2 d2 0c d0 c4 a1 c0 d5 |.7....vs........| +000002b0 72 39 bf 03 f7 8d db e0 8f fe e2 d6 d0 d4 cc bb |r9..............| +000002c0 7d 78 c6 c5 13 a8 4e 45 1e 66 60 77 fe 26 4d 18 |}x....NE.f`w.&M.| +000002d0 90 e8 e1 0c 5b 2b 25 9b ee 6d 76 3f f6 23 a2 26 |....[+%..mv?.#.&| +000002e0 52 8d a9 4e 7f ed 8e e2 6d 7c b4 eb 25 46 54 27 |R..N....m|..%FT'| +000002f0 e2 2d 2c 59 16 03 03 00 bc 6e c1 fb 66 55 ca ea |.-,Y.....n..fU..| +00000300 56 62 78 2f fd c4 ff da 78 dd e7 4d 34 59 a5 8f |Vbx/....x..M4Y..| +00000310 05 ab ac 7f 80 35 f6 de 9d 3f fe 4b d4 79 07 3b |.....5...?.K.y.;| +00000320 c0 8d 02 b8 1a 28 b5 eb 9b 55 6c 26 12 8d 38 01 |.....(...Ul&..8.| +00000330 55 ed 28 68 aa 48 13 61 d3 fe 29 f0 fe 18 4e ae |U.(h.H.a..)...N.| +00000340 6e f9 47 7c 65 91 f9 5e 17 80 68 fd 19 4d ed 17 |n.G|e..^..h..M..| +00000350 7f 11 c4 15 5d 4b fc ea a7 5c df 76 a0 08 2e 15 |....]K...\.v....| +00000360 d1 c6 ae 7b 0d 1f 79 d7 0c 59 6b 53 46 b6 c0 2b |...{..y..YkSF..+| +00000370 ce 09 39 12 7a df f6 7d a2 4b 86 2a df ab b8 7c |..9.z..}.K.*...|| +00000380 07 10 3c 34 cd 15 4c ac 68 a4 28 8a f8 fc 30 a4 |..<4..L.h.(...0.| +00000390 4f 15 77 b4 91 ca 02 ee bb 64 36 90 1b 4b 9d 2b |O.w......d6..K.+| +000003a0 72 e7 dc 10 bd 83 97 18 3c 56 68 58 c9 e3 22 df |r.......>> Flow 13 (client to server) +00000000 16 03 03 00 35 67 14 4b ca 21 7f d2 82 1d 2e b3 |....5g.K.!......| +00000010 1a 82 ae 2d d9 d6 7c 76 94 78 d4 ec 0e 4d fe 5c |...-..|v.x...M.\| +00000020 d5 56 5e 6d 32 f4 a0 64 50 1e f6 e4 32 28 92 80 |.V^m2..dP...2(..| +00000030 d4 15 1c d5 f6 52 fc ca c0 e7 14 03 03 00 11 df |.....R..........| +00000040 9d f3 d1 64 92 92 7e 11 77 64 e5 67 01 33 49 17 |...d..~.wd.g.3I.| +00000050 16 03 03 00 20 c8 0f d9 d2 c8 b7 d6 a5 ac 2c 33 |.... .........,3| +00000060 f8 77 8f b1 df db 16 de 43 6c e6 5a eb a0 6e ff |.w......Cl.Z..n.| +00000070 be 1d 69 ab 30 |..i.0| +>>> Flow 14 (server to client) +00000000 14 03 03 00 11 6e 2c 51 c5 dd fa 70 2a 34 e0 cc |.....n,Q...p*4..| +00000010 3c 9f b8 66 15 e6 16 03 03 00 20 78 02 96 c6 24 |<..f...... x...$| +00000020 57 ca 4a 60 47 68 f6 5a 13 8b 3b ce 90 60 d2 e3 |W.J`Gh.Z..;..`..| +00000030 1b d8 ab 1c df d4 5e c2 8d 5c 5b 17 03 03 00 19 |......^..\[.....| +00000040 b7 15 fb 91 10 48 ae 25 0c cd 4f 06 fa 2a 59 49 |.....H.%..O..*YI| +00000050 2f 18 5e 7e 36 1b 2e cb 3a |/.^~6...:| +>>> Flow 15 (client to server) +00000000 15 03 03 00 12 c3 ff f7 b3 dc d4 b3 f5 d4 7c a3 |..............|.| +00000010 18 db 08 a2 50 ad 75 |....P.u| diff --git a/src/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected b/src/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected new file mode 100644 index 0000000..784bcef --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected @@ -0,0 +1,247 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 96 8a 79 30 8b |....Y...U....y0.| +00000010 13 f5 d3 1c 09 45 76 83 d7 2e e5 ad e3 ee e1 c4 |.....Ev.........| +00000020 d4 b4 4c 37 93 cb 90 e1 9a 5e 52 20 fb 25 91 ea |..L7.....^R .%..| +00000030 1a 96 b6 fb 1f 0c a8 62 06 a0 fe 51 68 c0 fb a5 |.......b...Qh...| +00000040 f1 05 28 02 be dc 87 31 e6 ff 90 1a cc a8 00 00 |..(....1........| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 ad 8e 56 2a c0 d0 7c |........ ..V*..|| +000002d0 e1 cb 6b 20 0b 3e 53 33 28 25 37 42 5b 13 3c d5 |..k .>S3(%7B[.<.| +000002e0 26 98 9e 0f df 45 6d 27 67 08 04 00 80 72 49 21 |&....Em'g....rI!| +000002f0 f0 02 02 a3 7c e1 2a 18 d0 d0 21 8e 50 17 ad 0c |....|.*...!.P...| +00000300 3c a2 6d 65 b5 cb bc 7f 9e 7d 7f e2 36 3d b6 c8 |<.me.....}..6=..| +00000310 df 7e b9 28 ab 01 99 2a 68 a4 be 46 11 94 9f 8c |.~.(...*h..F....| +00000320 67 02 92 1e 3c 51 78 f3 7a 35 ed f4 bb 8b fe b3 |g...>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 b8 c8 5d 3d b8 b8 2b c7 06 94 ec |.... ..]=..+....| +00000040 cc 92 01 22 3d cd 38 d8 aa 9f 1f 18 ef a0 ee 59 |..."=.8........Y| +00000050 c0 3b 04 56 49 |.;.VI| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 be 6c dd f4 ef |.......... .l...| +00000010 71 1d 9c a7 24 ef 74 81 c4 01 1e e0 ef ac 78 90 |q...$.t.......x.| +00000020 4e 51 fd 8a ca 83 e7 57 95 07 fa |NQ.....W...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 35 96 43 38 06 49 b1 3f 01 ae 85 |.....5.C8.I.?...| +00000010 1a ee 4b 2b fe c0 75 76 b6 4a b0 |..K+..uv.J.| +>>> Flow 6 (server to client) +00000000 16 03 03 00 14 df 6c d7 78 02 f5 a7 cb d8 2f fb |......l.x...../.| +00000010 04 dc 30 bc 28 51 f9 ec b8 |..0.(Q...| +>>> Flow 7 (client to server) +00000000 16 03 03 01 16 8c 2a 91 5b 60 aa 44 e7 b7 7e b8 |......*.[`.D..~.| +00000010 ee c2 3e f3 c4 2f 6a 75 8e 25 07 5a 5c 42 81 fd |..>../ju.%.Z\B..| +00000020 65 4c 2a fb a9 80 f0 ba 33 1b 06 a8 79 a8 15 8e |eL*.....3...y...| +00000030 3a c4 08 95 a5 23 f0 ba fb 43 58 26 84 b5 9d 17 |:....#...CX&....| +00000040 03 e5 e7 08 ce 8b 79 9c 5e fb c6 6e a6 b8 12 cf |......y.^..n....| +00000050 b9 6e 4a 2a 90 d0 6b 65 93 bf 41 31 25 7f 3a 7c |.nJ*..ke..A1%.:|| +00000060 75 1f d6 4e 22 d3 90 7b 71 14 57 c6 b6 89 ef 79 |u..N"..{q.W....y| +00000070 74 7e 63 79 b9 63 d6 ef 02 b7 54 4b 53 0e 7f 70 |t~cy.c....TKS..p| +00000080 8a 34 b1 85 98 ae a7 05 b8 41 9d 49 a3 ca eb 7d |.4.......A.I...}| +00000090 8b 64 e7 5d ca 11 71 93 e0 ff 6e 43 37 b4 e9 ec |.d.]..q...nC7...| +000000a0 23 6f d6 c6 bc cb ef a2 0b d0 4b ba 4f 40 b0 4b |#o........K.O@.K| +000000b0 ec 57 cb 8a 10 ae fe cd 14 70 42 a0 b9 1c 81 f6 |.W.......pB.....| +000000c0 d2 79 47 31 4a b8 aa ac 89 98 cf ae 4e 8f 3d 36 |.yG1J.......N.=6| +000000d0 c5 41 0e d8 e6 f3 88 2a 19 e5 e7 71 e2 2f 32 93 |.A.....*...q./2.| +000000e0 ae 05 95 25 8f ec 4e 10 25 7e 53 60 6e c2 f2 72 |...%..N.%~S`n..r| +000000f0 fc 7a 69 c1 93 e9 b8 2e 94 f3 19 31 5b 23 7c fd |.zi........1[#|.| +00000100 04 5d 59 ca 00 cc 37 0b 05 0d 50 10 50 3f b0 86 |.]Y...7...P.P?..| +00000110 84 d4 fc 6a 0a 94 dc ba 88 fe ad |...j.......| +>>> Flow 8 (server to client) +00000000 16 03 03 00 81 41 25 27 5b 76 24 a0 4f f0 bf ca |.....A%'[v$.O...| +00000010 c4 4f f8 7c c6 e8 2a d4 d1 ed f1 b8 34 84 d6 d5 |.O.|..*.....4...| +00000020 93 20 70 7d 8e 75 c5 16 a8 ff 5c e6 de 16 ea 96 |. p}.u....\.....| +00000030 3f 86 3b bd 6d fa 96 3d 27 18 34 b8 18 86 ee 65 |?.;.m..='.4....e| +00000040 7f f2 cc 7a b9 f8 2e 5a 32 f3 16 e2 a2 27 fd 4b |...z...Z2....'.K| +00000050 31 19 e6 81 d9 ef 02 10 ac b6 55 d3 0b e2 b0 09 |1.........U.....| +00000060 56 ea 50 5a 96 b3 ff 07 78 48 df 77 3f 15 c9 ff |V.PZ....xH.w?...| +00000070 a7 24 af 28 ec 99 1a c9 36 09 16 9c 7c 5a c0 85 |.$.(....6...|Z..| +00000080 7c 93 e4 61 2e 5b 16 03 03 02 69 ef 17 31 d5 9c ||..a.[....i..1..| +00000090 bc 09 f9 b7 75 e2 c8 ea 93 6f b7 49 e3 0e af bb |....u....o.I....| +000000a0 84 d6 3b 20 e2 89 13 6f 7a d1 73 a7 cb d5 03 b2 |..; ...oz.s.....| +000000b0 20 40 40 76 d9 5d 3b 23 cb 48 ba 3c 1b e7 5d de | @@v.];#.H.<..].| +000000c0 16 be 82 91 39 d0 b4 83 3e 4c b8 a0 66 56 47 6c |....9...>L..fVGl| +000000d0 08 03 b1 0f be 3f d3 5e 7e b4 40 db db 5b ce 61 |.....?.^~.@..[.a| +000000e0 d9 dc 02 7d ea df ea 43 08 2c b0 1c af 76 8f d3 |...}...C.,...v..| +000000f0 cd af 51 cd 17 df 70 58 90 bd 83 aa 4b e5 fe cd |..Q...pX....K...| +00000100 90 30 e0 b5 d0 95 49 c2 10 06 8c 5a dd a2 37 ad |.0....I....Z..7.| +00000110 d5 d1 0e 73 c7 92 a9 ab 67 51 da 9d a4 62 6d a6 |...s....gQ...bm.| +00000120 d7 89 22 2b 97 59 ad 02 65 e9 1d 48 44 07 c9 c0 |.."+.Y..e..HD...| +00000130 c4 1f 7f da 64 0c 35 19 16 b3 70 41 d8 61 c3 47 |....d.5...pA.a.G| +00000140 59 4d c2 e6 07 86 55 92 b9 98 8e 5c 86 d2 d5 51 |YM....U....\...Q| +00000150 6a 50 19 99 75 0a cf 6e 49 cc 8a 76 b5 2b 20 48 |jP..u..nI..v.+ H| +00000160 2b 11 d4 54 a2 ea 98 ce d8 56 22 c8 f8 eb e5 25 |+..T.....V"....%| +00000170 c8 cf ec 86 95 09 51 7e 18 89 bb 8f d4 66 b8 44 |......Q~.....f.D| +00000180 c2 78 f4 4d ad eb 2d 79 f8 f6 02 4f d2 35 d4 71 |.x.M..-y...O.5.q| +00000190 b3 ae e6 7d f6 45 6c 99 07 57 3c 01 bb c1 fb f1 |...}.El..W<.....| +000001a0 1a ac ba 92 b6 60 52 63 8b 21 eb bf 77 02 c6 29 |.....`Rc.!..w..)| +000001b0 7f 10 f7 11 ac a2 90 a9 8b 47 da c1 2c 41 c9 da |.........G..,A..| +000001c0 3f 18 ab be f0 eb 20 98 80 c6 d2 14 9e 8e d3 41 |?..... ........A| +000001d0 c3 37 ab 12 5b cc d0 25 bd af 16 49 4e 89 a1 92 |.7..[..%...IN...| +000001e0 d1 09 49 59 dc cf f8 6c 73 02 cb 72 6d 28 6e 28 |..IY...ls..rm(n(| +000001f0 c5 a8 84 20 e6 f8 1b ad c1 6c 8f b0 30 b2 49 84 |... .....l..0.I.| +00000200 22 42 7d ec e1 c7 ab 29 de 1c 84 1f cf 59 c6 80 |"B}....).....Y..| +00000210 7e 13 13 d7 c5 e5 f2 e0 3b 9d 81 c9 3f 86 21 27 |~.......;...?.!'| +00000220 d7 c8 45 c1 25 f6 19 8d 0a f6 e9 5a 9b d5 64 a1 |..E.%......Z..d.| +00000230 e4 6d fe 6a cf d1 c3 1b d4 ea d9 1f 6b dc f9 a7 |.m.j........k...| +00000240 e9 d2 6c 31 19 db e1 f4 f8 82 6e 8b da fd b1 fd |..l1......n.....| +00000250 0a 56 84 73 db 25 5f bb 12 61 70 de 67 34 28 1c |.V.s.%_..ap.g4(.| +00000260 c3 e6 eb 81 c8 94 55 ca 52 25 e8 72 bf a1 c5 88 |......U.R%.r....| +00000270 b8 ce 72 8d 64 6c 38 d9 19 07 f3 51 51 91 84 f2 |..r.dl8....QQ...| +00000280 c4 76 7f 8b 57 09 71 94 38 aa f1 64 51 6f 62 50 |.v..W.q.8..dQobP| +00000290 c8 50 68 82 b9 54 b1 28 54 99 21 26 7d 75 c7 c7 |.Ph..T.(T.!&}u..| +000002a0 79 e7 65 93 72 a4 39 2d 4c ec ba b2 4c 92 ae ee |y.e.r.9-L...L...| +000002b0 34 a2 22 2f f9 b9 75 a9 27 77 63 2d ac 27 87 ce |4."/..u.'wc-.'..| +000002c0 ee 37 c0 c7 c1 b6 4c 13 d7 78 97 64 dc af ea 0d |.7....L..x.d....| +000002d0 7c 12 0e 7b 0b 26 77 01 e4 1c 24 e8 9f fc 19 2f ||..{.&w...$..../| +000002e0 46 a2 81 3d 0d c7 16 7e 49 25 b4 c1 0f 0a 71 05 |F..=...~I%....q.| +000002f0 25 eb 53 e4 16 03 03 00 bc 0b 79 2d c6 0a 63 68 |%.S.......y-..ch| +00000300 f0 21 37 d0 42 4a 0f 2f 7d 2f a0 7d 3d c3 94 c4 |.!7.BJ./}/.}=...| +00000310 36 f5 a6 db e1 ad 0f 94 07 67 57 54 d4 57 86 50 |6........gWT.W.P| +00000320 a2 e1 78 09 f2 e3 7b bc 6d 1b c0 fe 16 eb d3 ef |..x...{.m.......| +00000330 fb ec 22 44 ee 2f 78 99 84 e2 c1 4c f7 0d 4f bc |.."D./x....L..O.| +00000340 ca 57 be de 5f 52 08 33 b0 e1 1d 7b 45 9e 5d 17 |.W.._R.3...{E.].| +00000350 41 2c 10 43 44 18 84 38 f3 0b 6a a1 76 bf 75 c9 |A,.CD..8..j.v.u.| +00000360 56 b2 53 4c 98 39 c0 6f 30 13 96 8a 27 59 12 03 |V.SL.9.o0...'Y..| +00000370 60 64 ce 28 54 c0 03 f4 c4 d1 df 94 e3 6e 43 61 |`d.(T........nCa| +00000380 fa 43 40 e5 05 3b 26 dc c4 41 bd 73 c3 9e a0 db |.C@..;&..A.s....| +00000390 fb c9 50 b4 4a d9 2d 71 cf e8 ff 3d 17 9e 29 35 |..P.J.-q...=..)5| +000003a0 61 6c ab 11 ac 21 fa 90 6b 75 1f 0a 9d 30 3f 13 |al...!..ku...0?.| +000003b0 fa c3 97 7a 74 16 03 03 00 4a 3d ca 3b 3d c8 6f |...zt....J=.;=.o| +000003c0 44 4e 53 3d 05 27 97 aa bd 58 33 d6 ad 4a 34 71 |DNS=.'...X3..J4q| +000003d0 22 d9 36 96 17 a5 ba 6b b3 20 2e da 64 65 14 c7 |".6....k. ..de..| +000003e0 6a c7 07 39 55 db bb ad e2 49 84 09 5e 78 88 b5 |j..9U....I..^x..| +000003f0 4b d5 23 fa 17 c5 f2 b8 2a c6 e5 1e 15 47 01 36 |K.#.....*....G.6| +00000400 ef 7f 0a 14 16 03 03 00 14 28 e3 58 7e b9 36 d6 |.........(.X~.6.| +00000410 ef 65 c8 bc fb 10 57 3d 48 70 7f 68 7d |.e....W=Hp.h}| +>>> Flow 9 (client to server) +00000000 16 03 03 02 69 d8 c1 81 7e a9 d7 70 97 62 c7 68 |....i...~..p.b.h| +00000010 df 02 01 9d cc dc 38 d0 d6 bb 48 03 1d 0b be 73 |......8...H....s| +00000020 b3 1a 88 91 a0 1b 55 91 51 a5 d7 54 58 c4 ea 50 |......U.Q..TX..P| +00000030 e5 67 b1 60 78 b6 e2 7f d7 6c b4 76 d7 24 fd af |.g.`x....l.v.$..| +00000040 f6 68 90 8c de 71 cd 15 4f d0 c8 f6 ba 89 ce 05 |.h...q..O.......| +00000050 be 35 e8 9e 7a 8b 8d 0d 23 d4 5a bd 3a 9e d0 bf |.5..z...#.Z.:...| +00000060 80 08 f5 ad 7d 84 f1 8a 16 de 97 6b b2 75 8e 49 |....}......k.u.I| +00000070 0f d7 8b 10 57 f7 21 1f c0 87 de 06 c5 ae ae dd |....W.!.........| +00000080 9c 22 92 a1 6c c7 46 8d e2 be 43 32 9c be 47 6b |."..l.F...C2..Gk| +00000090 4d 2a 60 f0 b6 3a 09 16 d6 16 a1 92 4a 2d 2d 72 |M*`..:......J--r| +000000a0 00 8f 40 7c 3e a9 61 be 35 c8 f8 48 b4 1c 90 61 |..@|>.a.5..H...a| +000000b0 90 c5 aa f8 ae aa d4 8a 15 74 b2 5d aa 24 cf 45 |.........t.].$.E| +000000c0 ef 02 bd 29 b9 50 b4 fe 83 05 fa 4a a5 82 10 28 |...).P.....J...(| +000000d0 b7 ab c3 ca c3 65 bb 51 a4 7c ac 57 03 78 28 e3 |.....e.Q.|.W.x(.| +000000e0 91 9f c1 ce 02 08 70 84 8c 11 1f ae 35 a5 06 12 |......p.....5...| +000000f0 f8 78 5b 38 0a 11 c8 1c 2d 1b 0c 21 66 d9 41 b2 |.x[8....-..!f.A.| +00000100 ed 66 3c 47 f2 dc ab c1 59 7d 65 df bb 80 37 1c |.f.| +00000220 65 99 40 46 73 c8 e1 6e 86 65 92 bf 3d 92 a3 4f |e.@Fs..n.e..=..O| +00000230 37 6d bb 80 33 a5 7d aa d3 a9 37 77 a6 4e 5b d6 |7m..3.}...7w.N[.| +00000240 f3 f9 b2 42 75 18 1f 5a 58 f3 08 35 bc f4 2b 93 |...Bu..ZX..5..+.| +00000250 62 0b 8a 83 f9 44 d0 e1 1a 44 b2 66 45 6f de b3 |b....D...D.fEo..| +00000260 d2 ec 34 ac 15 89 76 b4 da dd 95 ca 44 5b 16 03 |..4...v.....D[..| +00000270 03 00 35 39 e8 06 21 47 85 b5 53 96 03 0b 08 3b |..59..!G..S....;| +00000280 d2 9d 55 1f 23 4f 3a c0 be 4f e0 e0 0a f1 65 6f |..U.#O:..O....eo| +00000290 78 22 c4 10 6b d0 96 dc 04 78 e8 d3 95 f6 9a 78 |x"..k....x.....x| +000002a0 09 f2 42 d3 79 57 99 c4 16 03 03 00 98 37 6b 75 |..B.yW.......7ku| +000002b0 79 17 fa 67 7f 94 2e aa 88 61 91 97 dc 10 1e e6 |y..g.....a......| +000002c0 6d 6d fa d5 64 17 f4 ec ba 01 43 99 88 e2 a7 13 |mm..d.....C.....| +000002d0 e0 9e 6a e9 97 c7 b3 ec b9 c9 72 51 3d 01 eb c0 |..j.......rQ=...| +000002e0 03 0f 08 48 90 27 36 6b bd e7 0d 4e 41 6a ef 11 |...H.'6k...NAj..| +000002f0 42 5b ae d1 16 ec 8f b7 47 a2 f5 b4 6a d4 32 bb |B[......G...j.2.| +00000300 0c cc 4f 2a e0 be 44 47 c8 77 09 f5 78 4b d6 ec |..O*..DG.w..xK..| +00000310 87 95 dc e1 74 75 54 af 45 bb 7a f5 2e f7 ac 3d |....tuT.E.z....=| +00000320 d1 b2 31 5a c0 24 c7 7c 25 36 62 a7 48 73 66 44 |..1Z.$.|%6b.HsfD| +00000330 c1 78 47 f3 48 c5 a0 f7 66 3e 78 27 2c 3c dc 83 |.xG.H...f>x',<..| +00000340 f5 6c e1 09 31 14 03 03 00 11 79 32 99 fd 2d 8d |.l..1.....y2..-.| +00000350 14 33 fd 1b 1b a8 3d 99 4b 0a b7 16 03 03 00 20 |.3....=.K...... | +00000360 76 25 53 83 f2 c5 bf a6 fa 2e d3 5a 62 67 5b 1d |v%S........Zbg[.| +00000370 23 9a 9c b3 16 01 3f 6a e9 4c ea e1 d4 d1 09 42 |#.....?j.L.....B| +>>> Flow 10 (server to client) +00000000 14 03 03 00 11 a7 38 2a 4e 04 a5 b7 df d6 05 bb |......8*N.......| +00000010 b5 93 38 bc 9e 62 16 03 03 00 20 f3 d3 e1 7d 80 |..8..b.... ...}.| +00000020 41 ce 05 99 92 c7 47 fe b5 08 3b 78 9d ae b0 5f |A.....G...;x..._| +00000030 2c ed bd 0b 90 e0 94 9e 0b b0 a5 17 03 03 00 19 |,...............| +00000040 27 f0 6a 55 af 3f c1 82 85 1a 6b 28 e1 cd dc 59 |'.jU.?....k(...Y| +00000050 43 be c7 18 16 30 08 b2 9e 16 03 03 00 14 c1 c5 |C....0..........| +00000060 64 ef 72 4f 6c 96 f1 f6 5b 70 29 e4 59 36 0a cd |d.rOl...[p).Y6..| +00000070 d2 a3 |..| +>>> Flow 11 (client to server) +00000000 15 03 03 00 12 af 73 0e 40 39 dd 1e 04 99 3e 10 |......s.@9....>.| +00000010 c9 62 b3 78 77 9b 56 15 03 03 00 12 25 8b 87 29 |.b.xw.V.....%..)| +00000020 82 d0 9f 5e 9a 27 bd c1 bf b7 a2 f0 92 ac |...^.'........| diff --git a/src/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected b/src/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected new file mode 100644 index 0000000..f7a7668 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected @@ -0,0 +1,95 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 a3 55 d2 e2 bd |....Y...U...U...| +00000010 94 8f 04 51 26 1c a6 61 b1 ed 05 e2 39 44 33 05 |...Q&..a....9D3.| +00000020 79 14 b7 1f 89 1e bb ba 53 0d 12 20 09 29 6d 26 |y.......S.. .)m&| +00000030 04 70 4a 5d 01 90 f2 c6 28 df 11 6a 64 23 ec 9e |.pJ]....(..jd#..| +00000040 9f 2b 15 33 dc 88 26 35 3a b0 86 92 cc a8 00 00 |.+.3..&5:.......| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 43 6b 44 5b 79 c9 38 |........ CkD[y.8| +000002d0 dc e4 ab fa 88 fa e6 06 89 b1 4e ff ab 8d d6 f7 |..........N.....| +000002e0 21 b4 ff 9d a0 c8 54 cc 63 08 04 00 80 cd f4 d6 |!.....T.c.......| +000002f0 c8 ad 03 e7 f0 e8 f4 c9 f0 e6 28 db cd 3b 7c bf |..........(..;|.| +00000300 05 af 3d fe c1 f9 f1 7a ec 41 bf 1f a8 95 6d ee |..=....z.A....m.| +00000310 e6 92 cb c0 ff fd c1 ed 86 b0 59 45 3e 2d 1d 66 |..........YE>-.f| +00000320 56 d1 9f e2 b7 79 ac aa 81 6d b0 42 36 96 80 4d |V....y...m.B6..M| +00000330 ca 36 29 1b 65 03 73 3f 85 ec 59 cb b4 a5 a0 c0 |.6).e.s?..Y.....| +00000340 0c 16 ad e2 6b 35 3c ab 1e da 69 19 7d a2 63 a7 |....k5<...i.}.c.| +00000350 69 2a d2 3f 12 17 bf 4c ed 8a f7 75 fe ce d4 2b |i*.?...L...u...+| +00000360 4d 35 bf 65 d6 9e 01 69 a8 0a 73 26 34 16 03 03 |M5.e...i..s&4...| +00000370 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 b8 d8 22 20 8d 69 23 05 34 eb 69 |.... .." .i#.4.i| +00000040 92 a0 a9 6c cd 94 3b 72 49 91 72 8e 65 79 ca 62 |...l..;rI.r.ey.b| +00000050 14 cf da 2e b6 |.....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 31 25 d4 c7 92 |.......... 1%...| +00000010 16 0b 92 2d a2 20 8b b2 c7 96 a6 b7 b6 b3 82 3a |...-. .........:| +00000020 4d a1 a8 96 29 fb 99 e9 ea 04 6c |M...).....l| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 8b 92 f3 f8 99 bf a3 7c c4 03 d8 |............|...| +00000010 4d e7 1b ad 50 e1 99 17 33 68 e2 |M...P...3h.| +>>> Flow 6 (server to client) +00000000 16 03 03 00 14 91 99 15 68 ae 92 52 bd 13 75 45 |........h..R..uE| +00000010 6d a9 f0 2d ee f5 c3 9b e7 |m..-.....| +>>> Flow 7 (client to server) +00000000 15 03 03 00 12 be 8b 4b a6 a7 7a 62 45 32 ff db |.......K..zbE2..| +00000010 07 ad a0 1b 46 9d c9 15 03 03 00 12 16 da d4 86 |....F...........| +00000020 4f c8 26 5a d0 34 82 fe 47 34 ae 31 db a7 |O.&Z.4..G4.1..| diff --git a/src/crypto/tls/testdata/Client-TLSv12-SCT b/src/crypto/tls/testdata/Client-TLSv12-SCT new file mode 100644 index 0000000..8492ee9 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-SCT @@ -0,0 +1,113 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 01 c6 02 00 01 c2 03 03 b0 59 eb bc ae |............Y...| +00000010 f3 42 03 d1 fe 2c 7d 6f 0e ff e4 0c 9e 13 00 b9 |.B...,}o........| +00000020 46 99 e2 84 49 64 a9 05 05 8a fb 20 16 12 dc b7 |F...Id..... ....| +00000030 e0 09 a2 a6 56 83 43 54 de 40 53 47 43 f0 2f c9 |....V.CT.@SGC./.| +00000040 2d 92 5e a0 9d a3 6a c4 55 17 01 cb cc a8 00 01 |-.^...j.U.......| +00000050 7a 00 12 01 69 01 67 00 75 00 a4 b9 09 90 b4 18 |z...i.g.u.......| +00000060 58 14 87 bb 13 a2 cc 67 70 0a 3c 35 98 04 f9 1b |X......gp.<5....| +00000070 df b8 e3 77 cd 0e c8 0d dc 10 00 00 01 47 97 99 |...w.........G..| +00000080 ee 16 00 00 04 03 00 46 30 44 02 20 1c 4b 82 5d |.......F0D. .K.]| +00000090 95 6e 67 5b db 04 95 4b f6 ce f4 32 3e 86 7a 7a |.ng[...K...2>.zz| +000000a0 32 ab 18 60 74 de 08 da 05 91 4c 2f 02 20 73 54 |2..`t.....L/. sT| +000000b0 1b 6e 7f a1 b0 7d 11 bc e6 f3 85 2f 97 66 1a f7 |.n...}...../.f..| +000000c0 8a e4 10 25 8f 12 f4 6f 39 0f d2 9e 18 f0 00 76 |...%...o9......v| +000000d0 00 68 f6 98 f8 1f 64 82 be 3a 8c ee b9 28 1d 4c |.h....d..:...(.L| +000000e0 fc 71 51 5d 67 93 d4 44 d1 0a 67 ac bb 4f 4f fb |.qQ]g..D..g..OO.| +000000f0 c4 00 00 01 47 97 e1 b5 70 00 00 04 03 00 47 30 |....G...p.....G0| +00000100 45 02 20 32 21 14 38 06 d8 72 2e 00 30 64 1a e2 |E. 2!.8..r..0d..| +00000110 e8 6d 4e 5a e1 d9 42 1e 82 4b 96 25 89 d5 26 13 |.mNZ..B..K.%..&.| +00000120 d3 9c fa 02 21 00 8f 12 28 64 51 4f 44 d5 8c 18 |....!...(dQOD...| +00000130 62 23 b2 43 93 33 05 f3 43 55 a1 d9 ee cd c5 71 |b#.C.3..CU.....q| +00000140 35 91 dd 49 d1 0b 00 76 00 ee 4b bd b7 75 ce 60 |5..I...v..K..u.`| +00000150 ba e1 42 69 1f ab e1 9e 66 a3 0f 7e 5f b0 72 d8 |..Bi....f..~_.r.| +00000160 83 00 c4 7b 89 7a a8 fd cb 00 00 01 48 5c 64 8a |...{.z......H\d.| +00000170 87 00 00 04 03 00 47 30 45 02 20 29 89 d6 b0 53 |......G0E. )...S| +00000180 d3 d2 e9 91 bc f1 b5 40 be 1e 2e e7 5c b4 74 27 |.......@....\.t'| +00000190 ed 8f 9b 02 e9 fa c2 4c ba a2 be 02 21 00 af 43 |.......L....!..C| +000001a0 64 52 71 15 29 58 40 91 c7 08 16 96 03 a8 73 a5 |dRq.)X@.......s.| +000001b0 65 a0 6c b8 48 56 5a b6 29 83 64 6d 2a 9d ff 01 |e.l.HVZ.).dm*...| +000001c0 00 01 00 00 0b 00 04 03 00 01 02 16 03 03 02 59 |...............Y| +000001d0 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 |...U..R..O0..K0.| +000001e0 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b |.............?.[| +000001f0 ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......| +00000200 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |.0.1.0...U....Go| +00000210 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f |1.0...U....Go Ro| +00000220 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 |ot0...1601010000| +00000230 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 |00Z..25010100000| +00000240 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 |0Z0.1.0...U....G| +00000250 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 |o1.0...U....Go0.| +00000260 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 |.0...*.H........| +00000270 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e |....0.......F}..| +00000280 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e |.'.H..(!.~...]..| +00000290 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be |RE.z6G....B[....| +000002a0 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 |.y.@.Om..+.....g| +000002b0 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 |....."8.J.ts+.4.| +000002c0 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 |.....t{.X.la<..A| +000002d0 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 |..++$#w[.;.u]. T| +000002e0 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 |..c...$....P....| +000002f0 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 |C...ub...R......| +00000300 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff |...0..0...U.....| +00000310 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 |......0...U.%..0| +00000320 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 |...+.........+..| +00000330 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 |.....0...U......| +00000340 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 |.0.0...U........| +00000350 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b |..CC>I..m....`0.| +00000360 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 |..U.#..0...H.IM.| +00000370 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 |~.1......n{0...U| +00000380 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e |....0...example.| +00000390 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d |golang0...*.H...| +000003a0 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 |..........0.@+[P| +000003b0 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 |.a...SX...(.X..8| +000003c0 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 |....1Z..f=C.-...| +000003d0 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 |... d8.$:....}.@| +000003e0 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c | ._...a..v......| +000003f0 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c |\.....l..s..Cw..| +00000400 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 |.....@.a.Lr+...F| +00000410 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 |..M...>...B...=.| +00000420 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 |`.\!.;..........| +00000430 00 a8 03 00 1d 20 4c 46 c9 9f ed 2e 81 0f 8c 4b |..... LF.......K| +00000440 bc 05 53 74 c6 c8 76 99 21 94 1b 8f 93 c6 64 ce |..St..v.!.....d.| +00000450 e9 9d 6b 1d 66 51 08 04 00 80 09 9e c2 21 89 93 |..k.fQ.......!..| +00000460 1f c5 2e 2c fa 67 7b 42 23 e1 e0 67 5c 6d e9 1e |...,.g{B#..g\m..| +00000470 e8 a2 ac d7 cf f4 12 98 f6 e6 3d 51 0c 2c 29 ad |..........=Q.,).| +00000480 f8 8e 24 2a a3 99 2e f3 b2 a7 fe a9 6c e9 00 d8 |..$*........l...| +00000490 6a 7f 41 12 84 a0 d6 19 38 b1 5a 13 b6 71 cf bd |j.A.....8.Z..q..| +000004a0 e2 6e 04 01 c8 cd 83 12 71 85 ae bc 94 b1 e4 4d |.n......q......M| +000004b0 a5 5f 9e a5 5d 95 76 fe f5 d6 a9 f0 4c 07 c9 6e |._..].v.....L..n| +000004c0 fc 4a 56 2b 56 4e 9c ec 2c fe bc 9c 9e 57 f3 90 |.JV+VN..,....W..| +000004d0 c6 6e 77 5a cf 8c 1a 15 cd 90 16 03 03 00 04 0e |.nwZ............| +000004e0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 20 19 bf ac 05 d4 bb 8a 6d 11 f4 98 |.... .......m...| +00000040 0d af 78 57 49 74 5c 44 45 9e 2c 92 26 b9 10 b5 |..xWIt\DE.,.&...| +00000050 6d 5f 24 bc a6 |m_$..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 69 3a c4 9c ee |.......... i:...| +00000010 91 6b bc 33 39 82 64 c2 0a f0 a4 dd 85 16 3c ce |.k.39.d.......<.| +00000020 39 c4 98 37 77 47 1e c2 c6 d8 f6 |9..7wG.....| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 92 25 9b 97 11 08 71 63 b2 c1 35 |......%....qc..5| +00000010 14 3b e7 15 f6 05 67 51 46 db ba 15 03 03 00 12 |.;....gQF.......| +00000020 b2 53 a1 ec a8 cf 79 7d f8 86 70 05 e5 81 a1 6c |.S....y}..p....l| +00000030 41 ab |A.| diff --git a/src/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE b/src/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE new file mode 100644 index 0000000..3d3de61 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE @@ -0,0 +1,92 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 f4 01 00 00 f0 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 75 00 05 00 05 01 00 00 00 00 00 0a 00 |...u............| +00000090 04 00 02 00 1d 00 0b 00 02 01 00 00 0d 00 1a 00 |................| +000000a0 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 |................| +000000b0 01 05 03 06 03 02 01 02 03 ff 01 00 01 00 00 12 |................| +000000c0 00 00 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 |...+............| +000000d0 33 00 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 |3.&.$... /.}.G.b| +000000e0 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| +000000f0 c2 ed 90 99 5f 58 cb 3b 74 |...._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 f7 79 97 18 3c |....Y...U...y..<| +00000010 fa 52 c6 d2 6b 1e de a5 60 da d5 e2 0b f6 23 a8 |.R..k...`.....#.| +00000020 48 94 e8 1f fb b9 76 43 94 e8 98 20 31 a5 85 d5 |H.....vC... 1...| +00000030 2f c4 93 b1 ae aa 50 bc 14 9e 57 79 18 85 cd ef |/.....P...Wy....| +00000040 b4 f0 42 c9 6c b1 86 c1 03 27 ca df c0 2f 00 00 |..B.l....'.../..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| +00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| +000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| +000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 90 95 bd 82 cf 8a cc |........ .......| +000002d0 08 b4 09 09 8d 59 2d 03 7a bb 92 4a c4 5c 08 4d |.....Y-.z..J.\.M| +000002e0 42 a3 ba cb 9a 43 ae f0 22 08 04 00 80 a0 97 ac |B....C..".......| +000002f0 01 a5 c8 7b 4c 73 7e 70 7a 9a fc 9d 71 2f fe 67 |...{Ls~pz...q/.g| +00000300 ca dd 6b 43 db 64 0f 64 52 e7 d3 5d 6d b2 7c 50 |..kC.d.dR..]m.|P| +00000310 74 7e 80 d5 22 77 3f fb c2 e8 dc 92 37 4f 1e 1e |t~.."w?.....7O..| +00000320 e7 13 f2 01 33 80 32 66 4f c2 17 8e ec 4f ed 4a |....3.2fO....O.J| +00000330 15 6c e8 86 ec df d5 46 6c a5 43 0d 40 fe a0 c8 |.l.....Fl.C.@...| +00000340 65 b4 76 46 b8 36 2c da 87 7c 60 87 db 39 4c 2e |e.vF.6,..|`..9L.| +00000350 0f e4 72 32 11 26 99 7e c8 7a c0 bc 9c a7 29 57 |..r2.&.~.z....)W| +00000360 9d 27 37 4e ec c5 bb fd a1 3c f3 66 63 16 03 03 |.'7N.....<.fc...| +00000370 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| +00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 81 b1 2c |....(..........,| +00000040 a2 3b 38 34 a6 66 57 02 e3 67 1b ee 73 95 50 de |.;84.fW..g..s.P.| +00000050 dd 5a fd 4e 0d ee b7 a6 46 1a 34 61 73 |.Z.N....F.4as| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 2f a9 80 36 d8 |..........(/..6.| +00000010 d0 74 e4 39 46 04 88 8e 91 ea fd 96 ed 1f 89 9f |.t.9F...........| +00000020 a4 e9 24 0e ca 48 2b 5c 5d f1 cc 57 ce 92 1a ad |..$..H+\]..W....| +00000030 b9 10 11 |...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 da be 68 |...............h| +00000010 97 b4 a4 72 d0 ed 75 66 6a a9 6f 39 8a 08 a9 db |...r..ufj.o9....| +00000020 de 4d e1 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.M..............| +00000030 14 90 0e 1d 26 5c 18 c6 5c 93 66 c4 90 78 a8 91 |....&\..\.f..x..| +00000040 cb fd |..| diff --git a/src/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 b/src/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 new file mode 100644 index 0000000..f8a733e --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 @@ -0,0 +1,90 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 f1 4c f4 16 24 |....z...v...L..$| +00000010 e5 c6 b5 ce 72 08 3b 33 9f 1f 1f 80 2c 10 0b 34 |....r.;3....,..4| +00000020 01 99 85 ba b0 3c 85 50 3d bf 73 20 00 00 00 00 |.....<.P=.s ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 69 |..+.....3.$... i| +00000060 94 3b 83 cd 1f 93 53 53 82 de 14 cb 76 2a 19 62 |.;....SS....v*.b| +00000070 0f f8 9e d1 e3 e0 a9 d5 23 ac 07 64 53 27 4b 14 |........#..dS'K.| +00000080 03 03 00 01 01 17 03 03 00 17 ef 24 2c ea 6f 05 |...........$,.o.| +00000090 c2 07 7a d2 12 30 ce 01 f4 96 b8 dc e6 c2 27 02 |..z..0........'.| +000000a0 bd 17 03 03 02 6d 99 2b cb 79 43 01 66 24 eb f1 |.....m.+.yC.f$..| +000000b0 14 d2 ea 1e 57 67 81 e3 a0 9c 99 1b 1f d5 f0 c7 |....Wg..........| +000000c0 78 48 61 01 42 25 85 0b cd a1 b1 75 3c 50 01 cc |xHa.B%.....u..|.>Q.k| +000001d0 ce f3 51 cf 7e ae 55 40 bb ab 0e 40 6b d9 8a 3b |..Q.~.U@...@k..;| +000001e0 d5 f2 1f 76 6a 05 9b 87 e2 3b db fa cc e8 93 8a |...vj....;......| +000001f0 d9 ba 2b 63 77 77 62 f1 22 ce 11 a9 26 b5 e8 a2 |..+cwwb."...&...| +00000200 ec 3f 98 44 01 27 d7 e1 39 26 33 e3 86 00 60 f7 |.?.D.'..9&3...`.| +00000210 a7 91 07 45 f8 3f 78 dc 88 71 30 26 0c f9 0d 51 |...E.?x..q0&...Q| +00000220 2a c5 ce 33 ac b7 91 a9 74 2e 46 68 80 6e 62 cd |*..3....t.Fh.nb.| +00000230 2d 5e 43 fe bd d1 37 07 71 85 5d c7 38 17 50 3a |-^C...7.q.].8.P:| +00000240 1c 5e 9f cf 1e 3c 96 d0 26 5d 4c 82 78 a8 69 e7 |.^...<..&]L.x.i.| +00000250 d3 9a 81 e5 85 66 c3 d9 74 a1 82 9d fb 24 81 13 |.....f..t....$..| +00000260 0d ce cb 43 61 3c 3a a7 d1 80 7f 1d 41 d8 62 43 |...Ca<:.....A.bC| +00000270 c6 08 5d 91 05 ed 2c 50 04 42 8c db 2a 11 61 96 |..]...,P.B..*.a.| +00000280 9b d2 1d 40 af 83 ed 93 06 ba 65 22 0a a5 e8 a6 |...@......e"....| +00000290 b9 4a 63 6f c0 ac da 72 10 24 c6 ed 08 86 c8 a1 |.Jco...r.$......| +000002a0 92 5e d0 d8 8b 04 b7 43 50 0b 03 41 3f f9 96 16 |.^.....CP..A?...| +000002b0 a3 c8 09 e8 ac 91 b2 45 d5 58 5f 41 05 7c b3 88 |.......E.X_A.|..| +000002c0 7a 59 cd 1a 00 86 29 72 77 a5 19 43 32 79 fc d6 |zY....)rw..C2y..| +000002d0 d7 e9 81 08 e3 d9 d9 56 39 59 7c 1e d3 10 3e a4 |.......V9Y|...>.| +000002e0 c6 80 d3 8b 9b 36 51 c5 d3 14 64 a6 65 e2 1a 26 |.....6Q...d.e..&| +000002f0 c4 a8 31 07 bb 58 8c 9b d8 7d 86 fd 54 6c c9 ae |..1..X...}..Tl..| +00000300 7d 88 4b 13 0f 52 10 41 d6 be 01 32 f2 42 47 0f |}.K..R.A...2.BG.| +00000310 7a 8c 7e 17 03 03 00 99 8b ce c4 db 9c 9c 88 e3 |z.~.............| +00000320 88 58 de 8f 10 e9 fb 4a c7 26 96 60 48 84 2c b1 |.X.....J.&.`H.,.| +00000330 2b 6c 35 70 8a d7 39 91 51 d7 3f db 81 f0 41 07 |+l5p..9.Q.?...A.| +00000340 a2 c9 c1 74 76 62 58 f1 cb e2 50 48 57 bb 6e 3d |...tvbX...PHW.n=| +00000350 ee ee 4a 53 e7 3c 66 aa e3 d9 c1 f1 74 1a 93 b9 |..JS.>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 97 2c 39 3a a5 |..........5.,9:.| +00000010 32 33 e5 74 43 97 98 ef ef 30 de 27 8b f7 b5 ab |23.tC....0.'....| +00000020 dd af 87 7c a5 5e 76 cf 50 2a 03 f8 94 a4 7a df |...|.^v.P*....z.| +00000030 14 0a 2d 39 57 3b 02 97 c5 d7 63 85 21 3f 55 27 |..-9W;....c.!?U'| +00000040 17 03 03 00 17 7c b4 8b 82 f0 0a ec 6f fa 60 ef |.....|......o.`.| +00000050 4c 0a 1c 0b ad 99 c3 89 fb a4 40 2c 17 03 03 00 |L.........@,....| +00000060 13 f2 d5 58 ba 6b ca e8 f4 14 4c 66 23 38 f2 e8 |...X.k....Lf#8..| +00000070 ea a9 ba c1 |....| diff --git a/src/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 b/src/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 new file mode 100644 index 0000000..8ea3ed6 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 @@ -0,0 +1,92 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 71 00 90 30 07 |....z...v..q..0.| +00000010 24 01 ae 33 b2 e8 4f 1f 9a 2c 83 e5 7b 30 1e a2 |$..3..O..,..{0..| +00000020 8e 4a d0 df d1 ec 23 b5 ba aa 75 20 00 00 00 00 |.J....#...u ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 02 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 06 |..+.....3.$... .| +00000060 2a 26 bd 81 c2 90 9b 17 6e d0 b5 ab 72 e6 93 ce |*&......n...r...| +00000070 53 6d 8c 54 b5 a4 50 91 93 32 6e 88 e6 b2 69 14 |Sm.T..P..2n...i.| +00000080 03 03 00 01 01 17 03 03 00 17 7d 11 37 f0 18 b1 |..........}.7...| +00000090 53 55 38 bb 12 7c e8 b3 89 bc 35 fb 2a 36 d1 0f |SU8..|....5.*6..| +000000a0 3a 17 03 03 02 6d a0 fa dc 8e ac a6 90 5a 20 0e |:....m.......Z .| +000000b0 ee 22 89 7b 69 5b c9 1a a1 c6 43 b9 40 f6 85 78 |.".{i[....C.@..x| +000000c0 61 0b 14 c6 e6 3b a9 ac 4c 7a 96 9b 7b 87 d0 ce |a....;..Lz..{...| +000000d0 42 cc 75 9d fc 06 44 3e e8 12 3a 94 b7 de 86 c4 |B.u...D>..:.....| +000000e0 b5 66 e1 f5 48 21 f7 f1 58 7f 23 6c 3f 76 a0 cb |.f..H!..X.#l?v..| +000000f0 a7 f6 72 34 07 fa c1 55 3e 61 cf 72 c4 6c f1 ca |..r4...U>a.r.l..| +00000100 dd dc ec 66 3d 7b f6 cf 53 3b 28 bd 27 1b aa a6 |...f={..S;(.'...| +00000110 28 2a ab fa 48 a5 08 67 b5 49 c7 c7 5d f8 2c ec |(*..H..g.I..].,.| +00000120 83 af 58 33 42 6c c1 4c 94 17 7e 36 1c a9 48 34 |..X3Bl.L..~6..H4| +00000130 5f 26 78 f6 69 88 3a a5 1b d1 76 ad 88 63 25 33 |_&x.i.:...v..c%3| +00000140 0d e3 d0 34 6b 7f fc 96 2b 8d 22 6f 3f 21 8a 14 |...4k...+."o?!..| +00000150 01 e0 5c 54 6c c3 b8 12 f9 17 f5 4c ce e0 bd 10 |..\Tl......L....| +00000160 e7 e1 29 24 73 94 c2 5e b0 ad d3 91 9e 87 ea 23 |..)$s..^.......#| +00000170 4d fd 8f 12 ca 87 ff 2e 93 9f 16 a8 18 e1 66 8f |M.............f.| +00000180 50 76 15 cd 70 5c a2 1d 91 51 e5 54 13 5f 73 d3 |Pv..p\...Q.T._s.| +00000190 b2 6e b1 27 80 0b 3d 64 d5 fa f3 a4 fb 77 33 cb |.n.'..=d.....w3.| +000001a0 ac 93 54 36 2d 71 c3 9e dd 37 02 a9 9d b0 9b ac |..T6-q...7......| +000001b0 f8 c5 dc 43 9b d8 db c7 d0 fb cf 69 fa 62 e4 9d |...C.......i.b..| +000001c0 b7 04 f8 49 d3 a7 8d bd cf 8a e3 4a 62 cb bb 29 |...I.......Jb..)| +000001d0 b5 db 21 80 76 eb 28 67 34 1e 40 0b 83 83 19 10 |..!.v.(g4.@.....| +000001e0 46 8f bd 78 d6 7c 05 c2 19 82 1c e8 7d 84 f2 79 |F..x.|......}..y| +000001f0 c4 a6 e0 f7 7e df 70 7f 42 48 9f e4 99 03 7f 9e |....~.p.BH......| +00000200 e8 fd 75 c3 8a 55 55 8e 08 2e 62 28 a5 16 b7 11 |..u..UU...b(....| +00000210 d8 9a 11 48 46 ad d3 ba 4f 91 c8 fd 72 d9 df 98 |...HF...O...r...| +00000220 1a 59 51 55 af ab 73 b9 f3 bf fe 7d 55 7d 44 54 |.YQU..s....}U}DT| +00000230 cd bb f3 eb 6e ff 5a 09 e9 b9 c1 66 97 8e a5 7c |....n.Z....f...|| +00000240 89 4a 51 1d 8b e4 40 fb 97 ce ef 9d 7c 02 e4 db |.JQ...@.....|...| +00000250 f1 ca 01 d9 05 b4 de 10 23 33 92 ff 26 3b 09 8f |........#3..&;..| +00000260 11 7c 37 ad fb 58 ed 7a 10 08 fd df 98 dd d6 c5 |.|7..X.z........| +00000270 b8 fd 59 37 21 1d 6e 27 8a 56 24 45 e7 64 61 0b |..Y7!.n'.V$E.da.| +00000280 20 2d bc 79 89 fa 6d 7a 06 77 61 0c 60 25 e2 79 | -.y..mz.wa.`%.y| +00000290 6a 54 9e 5b 4b 33 68 17 da 63 ba a7 f9 ad 2c 84 |jT.[K3h..c....,.| +000002a0 52 e9 27 85 71 74 d2 5f c9 f8 8e 67 f7 47 58 f5 |R.'.qt._...g.GX.| +000002b0 e4 72 a7 bd 1c 94 4b 4d 13 5a 62 69 d9 6f 3a 51 |.r....KM.Zbi.o:Q| +000002c0 f0 18 90 e5 b6 21 23 97 70 74 93 ba 9b bc dc e4 |.....!#.pt......| +000002d0 3d 9c 52 3f 93 f0 48 05 e8 50 d0 b4 98 92 7a 18 |=.R?..H..P....z.| +000002e0 3f 39 ba f8 f7 ee 19 b0 ce ac d0 ab 9e 83 ee 0e |?9..............| +000002f0 5d 2a 72 74 a8 8b 4d de 6b a9 91 ad b4 a4 26 99 |]*rt..M.k.....&.| +00000300 4e aa 6d 48 77 83 78 78 be 96 f1 17 d6 96 74 4a |N.mHw.xx......tJ| +00000310 80 d1 5b 17 03 03 00 99 d9 40 96 5c fb 5d 65 69 |..[......@.\.]ei| +00000320 db 54 a8 f6 8c b7 d3 25 8d 2d c5 f1 40 5b f2 26 |.T.....%.-..@[.&| +00000330 f3 86 9e 61 6a a5 b9 66 b1 27 b1 20 6b 2c 64 84 |...aj..f.'. k,d.| +00000340 3f 48 24 5d d9 90 4b d1 ed 1b 0e 05 84 7f ad 0e |?H$]..K.........| +00000350 e6 75 f6 f9 33 90 73 7c 88 10 d7 e9 74 41 4b c3 |.u..3.s|....tAK.| +00000360 19 8e e1 a8 a6 7c 3c 9a bc 69 a7 e7 bb d6 af 98 |.....|<..i......| +00000370 f1 49 53 14 95 80 d6 95 81 5a 5e 88 2c 29 70 df |.IS......Z^.,)p.| +00000380 b2 df fe f3 17 03 e7 de af 12 57 c5 7a ef 70 eb |..........W.z.p.| +00000390 8a c6 c3 05 de 5b 15 af 5f 54 8c 7b 23 b7 e1 f1 |.....[.._T.{#...| +000003a0 30 b1 ed 34 4c 59 f5 68 c2 50 e8 c3 83 78 1d 1f |0..4LY.h.P...x..| +000003b0 eb 17 03 03 00 45 1a d4 61 ba 4a a5 1e 02 80 04 |.....E..a.J.....| +000003c0 2a 19 11 af 8c e9 bd ab 22 6b 75 41 a8 40 de 57 |*......."kuA.@.W| +000003d0 54 8c dc 09 cc 57 76 82 27 5e 59 0c 30 f7 9d c4 |T....Wv.'^Y.0...| +000003e0 fe 1c 09 f2 f4 5f e0 79 ac 02 06 80 f3 60 c4 92 |....._.y.....`..| +000003f0 cd 6a df b6 46 7c de 90 8d bb 94 |.j..F|.....| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 45 8c 37 d5 7e 3e |..........E.7.~>| +00000010 c4 24 64 8b fa fc 8d 03 a7 92 34 35 c3 2c f2 54 |.$d.......45.,.T| +00000020 43 06 5d 8a c9 c0 e8 7d 22 d3 99 58 01 0e 44 aa |C.]....}"..X..D.| +00000030 3c 26 eb 68 45 14 cd bf 6c 61 bb 31 91 9d b4 57 |<&.hE...la.1...W| +00000040 42 79 14 8c 67 c6 65 52 15 07 c8 f3 c3 9f 23 ef |By..g.eR......#.| +00000050 17 03 03 00 17 21 51 dd 67 e4 be f8 7c 7b 84 0d |.....!Q.g...|{..| +00000060 78 3c 7f ac 50 f8 34 7b fb 38 09 d0 17 03 03 00 |x<..P.4{.8......| +00000070 13 35 1a 52 9d de 4a 74 1f 01 70 de 05 c5 c3 b9 |.5.R..Jt..p.....| +00000080 e6 de 9c 0f |....| diff --git a/src/crypto/tls/testdata/Client-TLSv13-ALPN b/src/crypto/tls/testdata/Client-TLSv13-ALPN new file mode 100644 index 0000000..1d8da26 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-ALPN @@ -0,0 +1,93 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 0e 01 00 01 0a 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 8f 00 05 00 05 01 00 00 00 00 00 0a 00 |................| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 10 00 10 00 0e 06 70 72 6f 74 6f |...........proto| +000000d0 32 06 70 72 6f 74 6f 31 00 12 00 00 00 2b 00 09 |2.proto1.....+..| +000000e0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| +000000f0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| +00000100 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| +00000110 cb 3b 74 |.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 c2 91 70 7a 7a |....z...v....pzz| +00000010 d4 c9 46 7a e9 44 d1 c0 92 a6 0a 43 34 08 b2 ce |..Fz.D.....C4...| +00000020 14 99 8f 6c f7 37 fb a1 28 00 ae 20 00 00 00 00 |...l.7..(.. ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 60 |..+.....3.$... `| +00000060 96 62 c2 30 4e ae b6 89 f2 06 e0 4e 8e 32 27 04 |.b.0N......N.2'.| +00000070 b5 74 80 d8 c3 f5 76 7d 0e 0e e1 8d bc 2c 2c 14 |.t....v}.....,,.| +00000080 03 03 00 01 01 17 03 03 00 24 45 c7 50 3e a9 63 |.........$E.P>.c| +00000090 24 0b e9 80 3f 59 bb be 23 8a 5d 46 eb ee 17 9c |$...?Y..#.]F....| +000000a0 70 6f 52 1f 18 f3 9f 72 d6 35 44 55 91 d2 17 03 |poR....r.5DU....| +000000b0 03 02 6d c2 c0 1f 53 2a 0c 3c 7f 08 c3 cb 53 4e |..m...S*.<....SN| +000000c0 b2 f5 b3 2d a5 10 e1 97 00 89 67 db 4e df ad 75 |...-......g.N..u| +000000d0 94 b4 56 c4 8a a3 49 41 43 a1 3f aa 9b 8e e1 8d |..V...IAC.?.....| +000000e0 4c 9c 36 f6 80 da 4e 7f 00 10 c0 81 3e 45 1b a0 |L.6...N.....>E..| +000000f0 b7 7f 2c bd eb 2a 8b c4 e6 fa c8 b3 59 28 f6 b8 |..,..*......Y(..| +00000100 0a 93 cb b3 bf 28 e7 1a ae a0 f5 ff 3a 42 f5 64 |.....(......:B.d| +00000110 92 2c dd c2 24 77 2f a6 7e 23 63 3f 24 16 b3 d5 |.,..$w/.~#c?$...| +00000120 b7 df 3f 30 23 a4 aa c9 14 78 6c f2 82 45 52 df |..?0#....xl..ER.| +00000130 cf a1 1d 35 fd 2a 30 89 14 38 5a 23 b1 63 2c c1 |...5.*0..8Z#.c,.| +00000140 6d 6b 07 d0 41 38 4f 4c 87 d3 bd f1 ec ed 29 52 |mk..A8OL......)R| +00000150 3d c7 74 3d e9 d3 ce 47 1c 24 d5 78 19 c9 5e 01 |=.t=...G.$.x..^.| +00000160 66 a0 f1 8f ea a6 c1 e4 b4 e0 c2 2e d7 d6 64 36 |f.............d6| +00000170 c9 bc d1 27 33 6f 26 a8 c6 aa 0d bc ae f9 2e bc |...'3o&.........| +00000180 f1 a7 82 42 09 83 62 88 c0 9f 20 95 a9 38 50 b4 |...B..b... ..8P.| +00000190 55 d6 e9 f4 c6 a1 e6 67 a9 5f e4 15 97 44 13 ef |U......g._...D..| +000001a0 d3 50 8b 61 38 5e 89 75 b1 cf 6a 6f 0c c5 26 13 |.P.a8^.u..jo..&.| +000001b0 2c 5a 26 c9 81 98 88 cd ec 8c 2c 99 a0 ff 55 8f |,Z&.......,...U.| +000001c0 3f 9b c3 3b 52 d0 a3 3a f9 b8 f0 17 81 53 00 f3 |?..;R..:.....S..| +000001d0 ef 72 b3 4e b9 65 28 8f a2 48 dc dd 6b 16 61 c3 |.r.N.e(..H..k.a.| +000001e0 4e 0e c0 1c ac 8c 40 28 27 63 66 c7 74 40 8d 93 |N.....@('cf.t@..| +000001f0 71 e9 f6 3f d8 8d 5d c6 28 11 4f ac 55 6f 80 1b |q..?..].(.O.Uo..| +00000200 2e 84 05 94 e0 4f e7 63 62 65 c7 52 99 49 2f 5d |.....O.cbe.R.I/]| +00000210 b4 99 d3 c3 fa b9 f5 83 aa 28 2e 9d ce af 72 7f |.........(....r.| +00000220 57 ea 81 f3 bf b5 d7 93 3a 1f a0 83 4d 8a 91 85 |W.......:...M...| +00000230 fe b7 a1 b3 cb 1d b1 85 9b bb 36 1b 12 9f ed 13 |..........6.....| +00000240 09 55 31 bd ee 61 06 57 b4 07 4d c6 1e fa b9 7f |.U1..a.W..M.....| +00000250 c7 b6 60 70 92 b7 9a ff 80 7d da 7f 2a 62 89 be |..`p.....}..*b..| +00000260 79 43 d3 ae 9c f1 00 6d 68 6c a3 f6 48 6e e0 48 |yC.....mhl..Hn.H| +00000270 97 0f 5c 44 43 9f a8 88 27 96 fc 53 a0 e1 f2 7a |..\DC...'..S...z| +00000280 a6 a7 d9 96 2e 3d c4 e0 d9 18 79 ec 83 c2 9b da |.....=....y.....| +00000290 0b d4 8b 87 c5 98 f5 8b e7 e3 d1 bd 2b 2b 42 e2 |............++B.| +000002a0 4b 3e 64 88 4b 72 d0 35 cc c3 e6 68 c6 f6 4f 23 |K>d.Kr.5...h..O#| +000002b0 39 a7 94 8d f3 e6 bd cd d5 e9 8c 53 83 a7 87 09 |9..........S....| +000002c0 15 fe ea eb 2e 56 da 6b d9 5b b7 b1 c5 c4 ba 65 |.....V.k.[.....e| +000002d0 39 89 16 f5 f6 4e e6 3a 63 34 1b 5d f5 fa 6b 8d |9....N.:c4.]..k.| +000002e0 c3 49 07 88 12 ca 18 c5 50 da 74 44 c0 c0 33 bd |.I......P.tD..3.| +000002f0 2e 45 94 af e1 40 90 00 11 2d 08 7b fc e4 3b f0 |.E...@...-.{..;.| +00000300 94 fd 5a 0c 3a f9 76 df 3b 5e a3 0d 0f e7 2d df |..Z.:.v.;^....-.| +00000310 fd e9 ce 45 5a 13 36 a6 18 ae 46 30 00 fc d5 e3 |...EZ.6...F0....| +00000320 17 03 03 00 99 0e 35 b6 91 ad cd a6 62 6e 79 12 |......5.....bny.| +00000330 53 d5 f0 78 72 c5 dd 94 00 e3 75 2c 11 a3 72 f6 |S..xr.....u,..r.| +00000340 b7 b3 5e d9 51 79 d5 a9 1e 21 2f df 0d 53 9a c8 |..^.Qy...!/..S..| +00000350 43 a9 58 e2 a9 3d 9a b4 b4 72 bb 62 65 4b 83 f8 |C.X..=...r.beK..| +00000360 cd 1b 58 e0 69 d9 87 3b 8d 05 42 e1 22 23 e9 5b |..X.i..;..B."#.[| +00000370 3a 5a 38 17 17 fb 3a 56 de fc 56 f8 77 12 31 4a |:Z8...:V..V.w.1J| +00000380 c5 38 ec 69 72 54 e5 63 2a a0 1e b4 7d 86 43 29 |.8.irT.c*...}.C)| +00000390 21 ba 56 c2 d9 1b 9f a4 c1 02 f3 83 c1 9a 56 69 |!.V...........Vi| +000003a0 5c 9e 5f ae 94 9d 6f 03 ec 75 7a 19 98 cd a9 dd |\._...o..uz.....| +000003b0 4a 01 41 72 2e 60 9f ca 4c d2 27 d9 0f 4f 17 03 |J.Ar.`..L.'..O..| +000003c0 03 00 35 5d 61 3c 07 70 2f 35 ba d0 93 44 16 bd |..5]a<.p/5...D..| +000003d0 73 4b a0 fb 05 52 6a cc 5a 2e f2 94 d6 77 98 03 |sK...Rj.Z....w..| +000003e0 c3 2e 8e a9 d1 38 14 d2 cd e6 e3 b6 ad ec d6 a0 |.....8..........| +000003f0 cf b0 58 5f 8f d3 43 4b |..X_..CK| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 3d 0a fd 33 39 |..........5=..39| +00000010 b6 94 43 53 ae ee 3f 4e c6 2d a2 3a f0 ef 94 7d |..CS..?N.-.:...}| +00000020 32 0a b6 90 cd a1 6f 29 88 ff 3c 91 c1 e5 e5 ae |2.....o)..<.....| +00000030 b7 a0 0b b3 c0 e6 37 9d 06 8b d8 ae 06 c0 0e 7b |......7........{| +00000040 17 03 03 00 17 c2 a1 82 db df fa 54 28 79 a0 0c |...........T(y..| +00000050 97 8c 82 ee 22 c9 b9 35 32 7a 21 4b 17 03 03 00 |...."..52z!K....| +00000060 13 87 2b f8 38 81 df fa e5 2e ff e2 d2 51 3e bc |..+.8........Q>.| +00000070 dd d3 e8 62 |...b| diff --git a/src/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256 b/src/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256 new file mode 100644 index 0000000..69749f0 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256 @@ -0,0 +1,90 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 39 b2 74 80 d8 |....z...v..9.t..| +00000010 49 72 79 63 9b 7b da d7 cf b4 29 20 f8 80 ed d9 |Iryc.{....) ....| +00000020 66 09 65 22 b6 27 16 c5 a7 6f 8b 20 00 00 00 00 |f.e".'...o. ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 42 |..+.....3.$... B| +00000060 80 fb 4a d3 49 53 a5 9f f6 da ca 64 f8 5d 2c f5 |..J.IS.....d.],.| +00000070 45 4d f1 a5 ec c3 c6 fc d2 ff 56 b1 63 53 1a 14 |EM........V.cS..| +00000080 03 03 00 01 01 17 03 03 00 17 f8 d8 e1 1a e0 c8 |................| +00000090 75 f9 40 90 da 16 a0 41 4f 8c 23 e7 47 43 89 cf |u.@....AO.#.GC..| +000000a0 d4 17 03 03 02 6d d6 23 1d c6 c0 d4 5e a3 fe 2b |.....m.#....^..+| +000000b0 03 04 6c 88 d1 4a ac 9b dd 90 e5 18 c5 35 9c 4a |..l..J.......5.J| +000000c0 f3 c4 64 e2 c2 40 62 fb 68 b3 22 37 9f f4 eb ae |..d..@b.h."7....| +000000d0 45 d9 a8 be f4 1e 89 16 88 b5 10 e3 5c 2e 42 15 |E...........\.B.| +000000e0 34 24 f3 bd dd 73 6d 6b d1 db 3e 69 b0 0a 54 e6 |4$...smk..>i..T.| +000000f0 b7 2c b7 80 86 93 91 d5 26 02 77 bf 10 38 ee 40 |.,......&.w..8.@| +00000100 22 4d 3f 67 02 6b f8 1c 4a ad 2b c7 f6 19 d4 36 |"M?g.k..J.+....6| +00000110 9b ff c4 08 73 e1 48 0a a6 e8 80 3b 88 8a c2 e8 |....s.H....;....| +00000120 c6 4a ae da a1 4f 3b 9e fb 80 3b 78 ca 80 42 00 |.J...O;...;x..B.| +00000130 a4 5c 9d a0 6c 63 a7 66 e6 26 b7 14 d8 8b ba 1a |.\..lc.f.&......| +00000140 4b 13 81 3c e4 76 4e ac 6c 2f b4 71 e9 dc c4 c8 |K..<.vN.l/.q....| +00000150 ef f0 61 22 f4 6b 83 ae d8 d0 a7 c6 d9 ea 95 85 |..a".k..........| +00000160 77 90 0f 22 a0 50 cb ff 50 a5 98 ee de e4 89 f3 |w..".P..P.......| +00000170 20 f2 63 a2 45 3a 48 33 d5 b9 ff 5e f8 7d c5 2d | .c.E:H3...^.}.-| +00000180 b9 9c b2 65 bf d5 13 36 46 a5 96 9f f4 de 7c 1c |...e...6F.....|.| +00000190 78 3f 1a 0a 62 14 13 8e 55 7e cd 47 87 1b 7e a8 |x?..b...U~.G..~.| +000001a0 7f 03 ec 1c d3 72 eb e5 94 d9 9d 95 d6 f5 ad 2c |.....r.........,| +000001b0 e9 7d 0f 2c ea 7b 1e 8e d7 b4 f1 5d 12 be d7 cf |.}.,.{.....]....| +000001c0 b7 43 89 65 e9 04 0e f8 b4 b4 4d 9c 9c 42 3c 50 |.C.e......M..B/.`| +00000200 1d 41 55 9d c4 88 f3 76 4f 92 b5 03 98 23 6b c4 |.AU....vO....#k.| +00000210 c3 62 bd 12 dd 3a bc 37 d0 18 64 c6 e1 2c cb 62 |.b...:.7..d..,.b| +00000220 f6 d3 24 35 47 e7 cf 15 d3 53 9d ac 3f 97 48 c1 |..$5G....S..?.H.| +00000230 b8 d3 a3 2c 9f cd 2b 72 bc bd a6 8a b1 54 48 7b |...,..+r.....TH{| +00000240 e0 b7 a2 2e 46 04 cc e5 29 1d 73 c7 67 f8 f0 d8 |....F...).s.g...| +00000250 e0 88 f0 7b 11 ff e1 1d 95 6c 85 c4 08 72 3e 94 |...{.....l...r>.| +00000260 92 4b 8a 58 62 04 10 83 7c 5e 65 20 a7 5d 6d 16 |.K.Xb...|^e .]m.| +00000270 30 64 fc aa 7f 8f 06 ed 4e 3c 86 c8 10 92 fb 0d |0d......N<......| +00000280 7b 81 10 07 cf 30 7f 6b 11 63 60 2a 61 92 cb 74 |{....0.k.c`*a..t| +00000290 82 a4 04 cf 23 43 21 55 45 2a 29 93 42 0f 0c f6 |....#C!UE*).B...| +000002a0 9b 14 b5 96 09 25 1b bc b0 7b 72 e2 6f b8 55 74 |.....%...{r.o.Ut| +000002b0 00 bb 1c 7c b1 9b 58 63 97 bb 6d c5 fb a4 da 24 |...|..Xc..m....$| +000002c0 1e b2 97 18 75 ab 8b a2 77 50 38 4d f8 a0 39 58 |....u...wP8M..9X| +000002d0 8c 2d 3e ba 27 03 e9 51 87 0a 95 e0 08 40 5d e6 |.->.'..Q.....@].| +000002e0 6a dd 10 1d 6d 8c 32 88 a8 32 ee dd 44 9c 9b b0 |j...m.2..2..D...| +000002f0 6f f5 4b 08 60 9d 83 1e ab 83 c0 92 10 c7 aa 90 |o.K.`...........| +00000300 d2 b2 61 5e 12 b5 e8 ea a7 68 59 17 a4 f4 15 f7 |..a^.....hY.....| +00000310 dc 10 81 17 03 03 00 99 8a 61 79 8f 33 51 7b a9 |.........ay.3Q{.| +00000320 ce 3f 82 2b bb da 40 2e 73 c8 d9 6e 7d 72 ba 94 |.?.+..@.s..n}r..| +00000330 7d ad fb b7 ba 9c 74 00 0b c9 1d b6 8d 54 b9 48 |}.....t......T.H| +00000340 eb 49 78 c3 1a 75 b8 16 22 5d 50 f5 4a 81 59 d3 |.Ix..u.."]P.J.Y.| +00000350 38 79 38 c1 35 11 55 69 6b d2 86 3c 0f 12 26 57 |8y8.5.Uik..<..&W| +00000360 f5 84 d7 dd 74 61 6f b8 08 66 e9 3c f7 43 29 a5 |....tao..f.<.C).| +00000370 94 9e ab af 68 04 c1 6a ae 9d 12 2d 57 e9 ff 30 |....h..j...-W..0| +00000380 7d 80 35 65 cc df c8 65 0b a1 f9 6d 6b a5 0b df |}.5e...e...mk...| +00000390 0c 1a 04 0a 00 8f ac 2b 29 60 92 4e 91 d3 42 25 |.......+)`.N..B%| +000003a0 b4 a5 0a 1a 5f 83 ec 9a f0 0a 2c 6d 65 00 24 d3 |...._.....,me.$.| +000003b0 e1 17 03 03 00 35 e4 72 aa 9e 6c a8 93 7b e4 49 |.....5.r..l..{.I| +000003c0 1e 23 7c 50 18 59 00 08 3b f1 c1 5f 20 ba 51 56 |.#|P.Y..;.._ .QV| +000003d0 fe bb 93 99 52 e6 5e 6d 26 cc 60 11 c2 a1 c8 18 |....R.^m&.`.....| +000003e0 2e 72 bd ee 36 ca 41 25 73 f2 30 |.r..6.A%s.0| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 b6 c3 b9 b1 52 |..........5....R| +00000010 88 d2 78 2b ec 1c 63 e8 d5 08 0e 4e d6 51 b9 02 |..x+..c....N.Q..| +00000020 ba cc a8 ca b6 da 45 a9 7c 1a 18 39 47 84 db 34 |......E.|..9G..4| +00000030 d6 05 6f e5 16 19 57 6f 65 0b 7a e7 37 b5 d3 28 |..o...Woe.z.7..(| +00000040 17 03 03 00 17 dc b8 e2 1c aa b8 f5 cb b6 fd ba |................| +00000050 29 34 73 bb c6 e0 3a fc 3e fb d3 01 17 03 03 00 |)4s...:.>.......| +00000060 13 eb 66 ab 47 38 1b 01 96 6c 59 46 c2 ad bf 2d |..f.G8...lYF...-| +00000070 36 22 97 19 |6"..| diff --git a/src/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA b/src/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA new file mode 100644 index 0000000..251e339 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA @@ -0,0 +1,139 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 ce 38 98 c9 b7 |....z...v...8...| +00000010 f8 67 af 0d 29 52 88 a4 d0 c2 a8 10 c4 8e 80 26 |.g..)R.........&| +00000020 43 84 0e 60 06 ce f0 b7 b1 cd 29 20 00 00 00 00 |C..`......) ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 aa |..+.....3.$... .| +00000060 00 03 6d 16 04 54 48 55 4d f9 04 e8 29 ca 9c 5d |..m..THUM...)..]| +00000070 14 94 a2 7a 2e 0a 4e 75 12 2d 63 cf 19 81 21 14 |...z..Nu.-c...!.| +00000080 03 03 00 01 01 17 03 03 00 17 7b 90 e1 af 77 ca |..........{...w.| +00000090 a1 3b a6 e0 9f ea 4b f6 3f 45 a0 78 1c fb af 51 |.;....K.?E.x...Q| +000000a0 30 17 03 03 00 42 ff 27 8b 9c fd 65 d7 b1 d4 43 |0....B.'...e...C| +000000b0 eb 8f c3 ca b4 57 be 35 35 75 35 cf 43 73 d6 14 |.....W.55u5.Cs..| +000000c0 7e 2d b4 f8 31 60 1b 35 2a 38 91 32 40 8b f0 ab |~-..1`.5*8.2@...| +000000d0 a8 b0 dc 2b db b9 63 92 28 dc f2 c2 95 d3 4a 63 |...+..c.(.....Jc| +000000e0 69 e7 58 0c e5 9c d5 22 17 03 03 02 6d 7c 70 9b |i.X...."....m|p.| +000000f0 e1 81 3a 0d 6e 7f 5c 30 2e 09 1d 82 ac 48 a6 7e |..:.n.\0.....H.~| +00000100 03 ce d0 ce e2 e8 9e 8b 2b ee af 1a b1 6a 3a 27 |........+....j:'| +00000110 04 53 73 d2 d4 28 68 19 96 3a 3d 89 df 2c e3 2b |.Ss..(h..:=..,.+| +00000120 45 c8 5e 60 42 b0 4d f2 9c 8a 8d 83 f6 97 e0 b0 |E.^`B.M.........| +00000130 02 39 37 46 2b 07 28 8b e8 d8 c2 e3 ba 58 9b dc |.97F+.(......X..| +00000140 62 c4 e6 cb b4 97 f0 67 2b b3 40 4b 64 3e 73 3f |b......g+.@Kd>s?| +00000150 a1 1f 6e fe 7f ba af 7d bd c4 7c 37 60 c0 94 d6 |..n....}..|7`...| +00000160 bc 14 70 a9 95 a6 b7 88 9d 50 cf 9f 36 0c 38 c4 |..p......P..6.8.| +00000170 97 ba ea 43 16 e8 fd 72 22 3c 09 4a 97 1c 97 70 |...C...r"<.J...p| +00000180 88 6d d4 f3 9d b9 5a f3 67 f5 7b da 3e ed 1a 66 |.m....Z.g.{.>..f| +00000190 4c 62 50 ff cd 92 08 d8 5c 2e 11 de ea 44 16 91 |LbP.....\....D..| +000001a0 3e 44 d7 8c dd 2a b4 c7 2b 4d 40 a2 f9 7e 49 a9 |>D...*..+M@..~I.| +000001b0 d8 51 a1 27 b3 34 75 59 04 04 cd 52 d6 37 34 e6 |.Q.'.4uY...R.74.| +000001c0 41 32 36 45 c0 65 fb 5c e2 21 77 7f 35 db 9d 34 |A26E.e.\.!w.5..4| +000001d0 0d 6e 9d a7 9e 00 ec e3 3e 9c 50 50 13 5b ad b9 |.n......>.PP.[..| +000001e0 b3 47 44 f8 9b 12 ab 50 7f a7 df 35 c5 d6 78 3c |.GD....P...5..x<| +000001f0 c1 04 41 db 99 18 cd 8c 05 3f 08 ae 2b 41 c9 46 |..A......?..+A.F| +00000200 16 9a e3 a9 5b d3 9c 00 56 0e e2 d1 da 6d 6b 20 |....[...V....mk | +00000210 65 1b 55 1f 4f b1 eb 94 c6 48 e3 50 d6 14 c5 62 |e.U.O....H.P...b| +00000220 5e fc d2 cf df f4 68 90 c9 bb 80 54 f3 f3 a3 78 |^.....h....T...x| +00000230 af 1f 6f ef e1 d5 64 24 04 e5 d4 59 bc 4d 7b a0 |..o...d$...Y.M{.| +00000240 1a 23 e1 81 b7 c4 bb 52 86 f4 2a 85 d2 d0 7a ed |.#.....R..*...z.| +00000250 c0 5d 27 07 4b df 52 c4 ea c8 c9 9c f0 48 35 71 |.]'.K.R......H5q| +00000260 bd 04 65 65 47 e3 21 88 ff 08 6c 6a f3 6c dd 81 |..eeG.!...lj.l..| +00000270 3f 50 21 66 34 49 07 a0 e0 6d 80 54 77 8b 27 81 |?P!f4I...m.Tw.'.| +00000280 4f b9 59 60 0a b0 c7 00 6a 7b 26 33 f6 5e ad 37 |O.Y`....j{&3.^.7| +00000290 bf ea 87 e4 3c e7 b8 20 b0 89 88 ac 5a a4 af f7 |....<.. ....Z...| +000002a0 23 3c 0a d0 ab 74 fc 49 d2 e5 51 a7 a5 4e 21 5f |#<...t.I..Q..N!_| +000002b0 90 9a 65 36 9f e1 e3 9e 3d 67 d6 93 f1 b8 f0 4b |..e6....=g.....K| +000002c0 c6 d8 ca 50 fb cc 92 ab 47 b5 8c 21 02 4a ee 42 |...P....G..!.J.B| +000002d0 35 a3 52 41 04 94 19 cd 23 c6 33 b0 84 0d 88 97 |5.RA....#.3.....| +000002e0 5a e0 3e 4c 6d 99 ec 6d 11 3f 19 e7 77 60 3b de |Z.>Lm..m.?..w`;.| +000002f0 6d 04 b8 ab bc 83 4f 51 a5 ba 56 56 d6 e3 ff 0e |m.....OQ..VV....| +00000300 d5 4b 75 29 6a f9 4b c6 ef fd 62 25 89 76 f1 fd |.Ku)j.K...b%.v..| +00000310 84 3f e9 93 63 cf eb 47 85 b1 aa a2 4c 94 6b 99 |.?..c..G....L.k.| +00000320 98 6e 1a 19 85 0b 90 d2 9f 0f ec d4 36 1e 22 a0 |.n..........6.".| +00000330 4e 7f a1 ae 90 15 68 8a 48 c5 06 01 aa b9 56 cb |N.....h.H.....V.| +00000340 e0 62 53 d8 96 56 61 1d 81 96 b8 66 ae 94 c8 5f |.bS..Va....f..._| +00000350 86 47 fe ca 27 8d 7f 8e f8 74 17 03 03 00 99 ac |.G..'....t......| +00000360 2b 09 0b 44 a5 33 27 19 86 59 ca 75 5c df 59 fc |+..D.3'..Y.u\.Y.| +00000370 34 57 08 11 4f d8 1a c6 7c 76 d5 0a 36 91 f2 3a |4W..O...|v..6..:| +00000380 d1 96 58 64 29 3a d1 05 e3 cb 6f ea 92 4a f6 3b |..Xd):....o..J.;| +00000390 54 4c 16 41 99 6e 0f e9 c3 9a ac a3 59 ee fa c9 |TL.A.n......Y...| +000003a0 4d 58 ae 23 58 58 b5 b5 d6 6a dd b4 0c 24 bf e1 |MX.#XX...j...$..| +000003b0 d4 16 53 f2 2d e1 78 d0 ea 70 59 ac a3 e4 e4 6f |..S.-.x..pY....o| +000003c0 65 93 28 ad e1 64 83 11 05 42 a3 a0 11 d5 f2 af |e.(..d...B......| +000003d0 7e 03 93 80 82 48 e0 84 2e 1c 50 98 65 22 49 f1 |~....H....P.e"I.| +000003e0 df 41 03 83 b2 5c 1c 56 cb b7 f3 72 04 d6 09 cf |.A...\.V...r....| +000003f0 f9 3a 5d e8 35 80 b6 a2 17 03 03 00 35 b4 b5 c3 |.:].5.......5...| +00000400 43 78 3d e8 eb 66 7d 1c 36 8e a1 9f 26 ab 5a aa |Cx=..f}.6...&.Z.| +00000410 63 b6 2f 7a a5 f6 7d 89 1e 5d c5 a1 bf b4 3b 4a |c./z..}..]....;J| +00000420 89 1f 96 74 e3 c4 d8 72 57 a5 c7 99 a9 f3 77 16 |...t...rW.....w.| +00000430 f3 25 |.%| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 02 1e 2e 1c 18 ac 6e |...............n| +00000010 bd d7 35 f8 21 6f 36 d7 13 94 53 3b 56 5d 03 8e |..5.!o6...S;V]..| +00000020 2d 92 fa cb 17 d3 75 55 13 84 9c aa be f7 34 9e |-.....uU......4.| +00000030 35 67 9b 90 bc 76 5d 65 c0 23 b0 04 d0 ba 15 b5 |5g...v]e.#......| +00000040 30 70 4d 8d d2 38 73 0a 3a 58 c3 bc da a4 f5 ae |0pM..8s.:X......| +00000050 05 ee 0c 06 bd 06 fe ab 1b 31 cf 4d 46 63 cc ee |.........1.MFc..| +00000060 8f 8a 0d e9 32 50 4d a0 f6 f2 ce c5 be 41 c2 16 |....2PM......A..| +00000070 a7 c3 b3 8a 5c 27 4a fd 37 2d 32 d9 76 25 27 12 |....\'J.7-2.v%'.| +00000080 03 b9 e7 ef bc c8 59 e1 16 80 dc b2 16 ae 05 b6 |......Y.........| +00000090 cf 8e 99 0d f8 ed 5a b1 bb c1 05 d5 35 fe fd 2d |......Z.....5..-| +000000a0 97 c6 19 d8 2d 1a a9 30 d1 4a 6d 27 45 93 5f 5d |....-..0.Jm'E._]| +000000b0 45 f4 98 a8 d8 88 27 8f f2 ad 1e 24 6e c8 8f 12 |E.....'....$n...| +000000c0 f7 32 b5 3d 3c e3 e0 32 56 4e 80 a8 5f 27 f0 d0 |.2.=<..2VN.._'..| +000000d0 a1 c2 d0 22 2d 3a 36 0f bd 7b 94 9f ca 8d c1 ea |..."-:6..{......| +000000e0 c6 1f d8 87 4a 75 bd 3e 0f ae 2f e1 78 ae 3f 00 |....Ju.>../.x.?.| +000000f0 f4 3a 82 dd ec 3f 61 43 bf 4b f8 01 a3 32 df 13 |.:...?aC.K...2..| +00000100 61 45 ca bb e0 9a 17 85 45 90 c6 fb 5d 79 1b 58 |aE......E...]y.X| +00000110 54 ca 84 e9 a9 11 c4 74 82 f7 da e4 b3 4f 05 a1 |T......t.....O..| +00000120 23 72 9f 63 b8 4c 55 e6 da 33 b9 1c b0 fe 28 72 |#r.c.LU..3....(r| +00000130 f0 02 b6 ec 70 ae 27 d4 21 51 32 56 32 4e e7 7d |....p.'.!Q2V2N.}| +00000140 b8 0d 75 25 45 5c 68 83 4f e3 3e 8a 87 7c 06 81 |..u%E\h.O.>..|..| +00000150 ac ff 23 44 0e bd e7 0a 76 64 45 c4 04 df 35 db |..#D....vdE...5.| +00000160 ab 8a 38 87 f5 e5 35 75 7a 92 85 3d 14 9e aa 19 |..8...5uz..=....| +00000170 4d 94 25 8f c0 c3 37 ca 63 f3 dd 48 4a 6a 6b f5 |M.%...7.c..HJjk.| +00000180 fa 52 67 30 ab ff 56 9f 58 bd cd 66 d4 83 85 d8 |.Rg0..V.X..f....| +00000190 85 6c 6d 3c 56 e5 17 75 fc dc a7 3d ed 18 a1 3b |.lm.7FQq.m.| +00000290 9f 38 42 95 1a 88 ac 5f 83 a1 8a 59 59 62 cc 4a |.8B...._...YYb.J| +000002a0 57 d2 3e 1e 7e 1d c0 4d 41 23 85 5f 92 f4 63 16 |W.>.~..MA#._..c.| +000002b0 df df 6e 3d d7 c1 e6 21 22 0f e1 13 82 29 a6 e3 |..n=...!"....)..| +000002c0 f8 8c a4 a3 72 1d 61 c1 2a 9d a8 2d 13 8a 4f 87 |....r.a.*..-..O.| +000002d0 91 17 03 03 00 35 9d 35 c8 ac 1e c6 46 8d e1 42 |.....5.5....F..B| +000002e0 68 e5 79 77 64 15 e2 13 c0 70 1a 47 59 d0 1e c3 |h.ywd....p.GY...| +000002f0 68 f7 5a fe 11 a2 3d e4 6e 2c b5 7d ea 98 e7 75 |h.Z...=.n,.}...u| +00000300 7c 54 a4 35 9b 1f c9 ba 72 b1 94 17 03 03 00 17 ||T.5....r.......| +00000310 a3 81 17 ac 97 a9 f0 91 b5 7a 04 38 ff fd 8e d3 |.........z.8....| +00000320 d8 7b c4 40 7e d3 ea 17 03 03 00 13 a8 b1 06 94 |.{.@~...........| +00000330 90 83 62 d5 be a8 23 d5 8b af 77 0d 90 13 98 |..b...#...w....| diff --git a/src/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 b/src/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 new file mode 100644 index 0000000..689c287 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 @@ -0,0 +1,122 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 4e 4c 01 f1 4e |....z...v..NL..N| +00000010 49 97 ec eb df ce 50 4d 1c 9c d0 35 92 10 97 0a |I.....PM...5....| +00000020 dd fb a8 4f 39 c6 14 21 d6 42 ac 20 00 00 00 00 |...O9..!.B. ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 c1 |..+.....3.$... .| +00000060 c2 ca 32 aa 48 d8 52 bc c8 23 6d 98 18 3e 15 b6 |..2.H.R..#m..>..| +00000070 0b 25 db f9 6f a7 e1 75 95 a1 46 d3 47 4a 0e 14 |.%..o..u..F.GJ..| +00000080 03 03 00 01 01 17 03 03 00 17 87 10 92 da b4 9a |................| +00000090 03 a5 0f 73 e6 93 cb 71 1d 58 6e 5d 27 eb ee b6 |...s...q.Xn]'...| +000000a0 c7 17 03 03 00 42 89 8d 57 16 95 5b f0 98 ad c7 |.....B..W..[....| +000000b0 d7 94 ba 4d 7e 88 b9 8d 13 26 a6 6c 81 90 a6 1e |...M~....&.l....| +000000c0 2b 4e 91 70 e2 da 9d a2 0d 6f 9b 5b ee 69 58 a1 |+N.p.....o.[.iX.| +000000d0 4c c3 59 57 28 62 b3 ed 26 15 79 db 01 8c 88 e3 |L.YW(b..&.y.....| +000000e0 63 1f bc b0 01 c9 82 ca 17 03 03 02 6d e5 d6 77 |c...........m..w| +000000f0 4e d3 af c3 5e 01 e9 1b 31 63 a4 84 d3 cc 2d f8 |N...^...1c....-.| +00000100 5d 73 f9 3e 83 03 c5 c5 cd 95 00 7b f2 b5 79 fa |]s.>.......{..y.| +00000110 47 e5 07 89 a9 22 49 7a 7e 7e 6e d2 3b 68 e8 9c |G...."Iz~~n.;h..| +00000120 40 1c 86 2a 48 ee 59 8e 1c 04 8b 91 20 68 65 31 |@..*H.Y..... he1| +00000130 e7 76 dc 6c 5a ce cb 32 d3 e8 71 7f 93 08 b5 01 |.v.lZ..2..q.....| +00000140 84 0a b4 ec 80 68 69 9b b3 4a 4a 4d 56 16 eb 42 |.....hi..JJMV..B| +00000150 29 93 4d b4 76 f6 e0 15 fe 25 b1 cb 5a da 22 4b |).M.v....%..Z."K| +00000160 88 4c ec 66 48 09 e1 d1 0f 3e 3a ad 65 d7 d7 85 |.L.fH....>:.e...| +00000170 1d cb 35 2c 84 60 ec a1 6d f1 60 cf c6 c7 82 1a |..5,.`..m.`.....| +00000180 7c 91 40 2e 3e 88 1f ff 79 2e 6e 97 c5 45 9f e1 ||.@.>...y.n..E..| +00000190 bf 33 ad 65 df f3 ce 1a d7 57 7e db f2 28 79 a9 |.3.e.....W~..(y.| +000001a0 9e 4f 9e 8a ce 02 5a 18 bb f1 ac 72 5b 3f 4c 6b |.O....Z....r[?Lk| +000001b0 97 14 14 f9 82 8a 4f 99 21 98 db af 3e 08 ab 4f |......O.!...>..O| +000001c0 d8 3f f6 cc da 76 77 eb 02 39 0a 00 23 a5 e0 92 |.?...vw..9..#...| +000001d0 01 10 3f 76 ab 1a 38 8e f9 a1 d0 25 c3 9d 50 a4 |..?v..8....%..P.| +000001e0 ef a5 8c f8 5d bc d9 fd dd 25 cd 42 38 52 d1 cd |....]....%.B8R..| +000001f0 d2 1b fc ba 7d 8b bd 82 05 23 c3 9d 02 ff 1b 4e |....}....#.....N| +00000200 08 e1 f3 7c 35 15 0f e8 0e b7 8a e5 4a 2b da 45 |...|5.......J+.E| +00000210 4a 72 9a 32 7e 55 52 65 d2 a8 32 90 53 bf 25 29 |Jr.2~URe..2.S.%)| +00000220 1e 8d d7 a3 22 d6 40 19 95 58 a8 37 af a8 52 e7 |....".@..X.7..R.| +00000230 79 b9 4e 61 d8 f0 7d d2 69 25 99 28 3f 31 f6 b2 |y.Na..}.i%.(?1..| +00000240 44 65 1f 9c 41 08 17 c9 01 5d 20 ea ab fe 06 64 |De..A....] ....d| +00000250 9a f4 d0 24 e0 b5 88 0a 2b 96 e9 71 11 a8 49 b4 |...$....+..q..I.| +00000260 40 62 1b 45 15 47 cb a5 fc 4f 07 58 2b ef d4 5d |@b.E.G...O.X+..]| +00000270 df 40 38 6c 6e ca 63 c5 95 2d 79 26 86 ff 33 02 |.@8ln.c..-y&..3.| +00000280 da 5a 85 0c 8f 7f 58 ba ea 88 cf bc 51 92 12 86 |.Z....X.....Q...| +00000290 f1 c1 f9 0a d0 6e cc b4 2b 16 98 ad f8 11 ad 63 |.....n..+......c| +000002a0 82 d7 4e ea a5 ee 78 a2 9a 35 b6 b3 d9 24 cf 66 |..N...x..5...$.f| +000002b0 03 d2 25 1f 15 37 c7 b5 8e bb 0a 40 0f 28 c2 16 |..%..7.....@.(..| +000002c0 90 a4 61 9e dd fd b5 ad 97 39 0d 66 e7 fa 5b e2 |..a......9.f..[.| +000002d0 c2 ef 44 5d 44 07 d6 c3 ed e2 89 6e 4c ed 79 42 |..D]D......nL.yB| +000002e0 86 3b f4 94 0c 82 5e 52 ce 00 ab 5c 20 b4 18 db |.;....^R...\ ...| +000002f0 c9 fe 8b be 8d da e9 86 13 62 6b 8d 0d 57 c8 fe |.........bk..W..| +00000300 a6 4b 82 52 d5 d8 05 18 2f a0 43 d6 c8 89 fb e7 |.K.R..../.C.....| +00000310 72 17 61 89 36 5b e0 aa 4d 6c 20 ee 68 db 32 e4 |r.a.6[..Ml .h.2.| +00000320 97 9f 18 26 7c 1a cd e8 b9 05 ae fd 86 bf 0e 47 |...&|..........G| +00000330 09 06 bd de 2d b9 50 6a 0c a6 27 04 5e aa e0 ce |....-.Pj..'.^...| +00000340 e7 cf 98 f9 7e 7d b9 4d 77 9a 88 3a d4 41 07 cc |....~}.Mw..:.A..| +00000350 87 b6 41 53 8b 8c 79 8e 07 b9 17 03 03 00 99 0b |..AS..y.........| +00000360 63 4e d8 79 d7 11 f2 46 00 6c 5d d2 9e 49 df 7e |cN.y...F.l]..I.~| +00000370 f2 96 1a 68 9d 6a 05 dc 61 45 47 a4 18 5c 65 04 |...h.j..aEG..\e.| +00000380 00 38 d1 25 0c ff a3 a2 c0 c2 82 7f b1 1b a1 c6 |.8.%............| +00000390 7b ac fb 71 48 b6 e4 e2 7b c4 d0 44 8e 22 d6 91 |{..qH...{..D."..| +000003a0 99 87 a2 88 3d bb b4 80 13 57 2a 6a b0 2d 52 16 |....=....W*j.-R.| +000003b0 d3 f2 e4 cd d0 79 9a 31 ce 68 65 b3 61 67 a0 b9 |.....y.1.he.ag..| +000003c0 1e 6b 9f 73 dc 46 be 5e df d7 c2 30 d5 60 b5 e5 |.k.s.F.^...0.`..| +000003d0 60 cc 10 ae 9a f9 b6 9a fd 14 b9 1e b7 3c 1d 3e |`............<.>| +000003e0 34 a6 49 d2 48 f7 24 56 29 c9 98 f1 33 b1 e5 5e |4.I.H.$V)...3..^| +000003f0 2c 7b bb 5f b6 53 6a c8 17 03 03 00 35 d9 af 32 |,{._.Sj.....5..2| +00000400 1f a5 09 3f 8a 10 df a7 34 9b f8 ec 07 81 80 73 |...?....4......s| +00000410 dc ba 09 fc 40 e4 1e df f6 de 02 54 3c 7d ea 49 |....@......T<}.I| +00000420 91 16 72 70 8e 1a 21 76 c6 00 0e 03 9f 0a 82 fe |..rp..!v........| +00000430 4c 18 |L.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 01 50 1d 6e 16 0d 4e |..........P.n..N| +00000010 c0 a2 41 c3 a2 84 c9 80 c0 f0 ef c0 5d 3a 3b f2 |..A.........]:;.| +00000020 bf 1c 9e 79 d7 d3 94 0b 41 2d bc 50 eb 0f 60 f4 |...y....A-.P..`.| +00000030 bd cd f6 03 22 7b 68 68 44 34 c9 0f 23 ca 76 6f |...."{hhD4..#.vo| +00000040 f2 97 38 07 43 56 7e b7 ce 67 68 67 37 34 d0 f7 |..8.CV~..ghg74..| +00000050 c5 92 fd 65 98 b8 7e 5f 48 a8 a3 aa a8 96 65 b5 |...e..~_H.....e.| +00000060 48 be 91 99 67 0a 37 c7 31 b4 43 ba 26 bb 87 98 |H...g.7.1.C.&...| +00000070 3c 55 e4 63 b0 33 ca ee 0a a5 fe 36 88 ef cf f0 |_C...f..c| +00000130 bd 42 a6 f8 ef 38 42 8a d8 28 dc 55 e5 88 03 76 |.B...8B..(.U...v| +00000140 96 ba 89 35 63 7e 6c da 39 d8 9a 27 04 ab d5 0e |...5c~l.9..'....| +00000150 48 89 cc 81 25 44 61 16 2c b2 69 17 03 03 00 59 |H...%Da.,.i....Y| +00000160 81 8f 94 30 8d fc 47 13 7e 84 06 9b 4a 85 2c bb |...0..G.~...J.,.| +00000170 b3 a0 0d 4f 50 6a cb 0b 9b 40 ef cc 84 70 1f 69 |...OPj...@...p.i| +00000180 b9 3e a6 c4 ba 66 eb a9 6f 78 83 7f d4 1f d8 c4 |.>...f..ox......| +00000190 b0 f6 9b 03 29 7f b1 f8 60 40 0b 28 91 32 2c 03 |....)...`@.(.2,.| +000001a0 aa 9e 7b fb 99 c2 11 51 1f a7 81 69 16 39 f4 52 |..{....Q...i.9.R| +000001b0 ca d8 d0 f3 87 6f 58 ab 9a 17 03 03 00 35 de 03 |.....oX......5..| +000001c0 88 61 50 5c 08 88 77 28 6a 1d 28 44 3d 49 8b 79 |.aP\..w(j.(D=I.y| +000001d0 d1 a2 13 67 95 0f 7c 18 fe e2 e0 07 f1 ce b9 be |...g..|.........| +000001e0 79 aa 40 d6 cf 66 53 ac 15 ae 2a 14 a9 63 98 55 |y.@..fS...*..c.U| +000001f0 96 16 6f 17 03 03 00 17 a8 ac 17 c5 eb d9 8e 77 |..o............w| +00000200 9e 4b e0 20 c6 0c 34 b6 c3 ab c4 b6 8b b2 77 17 |.K. ..4.......w.| +00000210 03 03 00 13 58 d4 7b 8f ca 20 41 e3 3f d1 ae cf |....X.{.. A.?...| +00000220 3d e1 86 91 c0 a1 08 |=......| diff --git a/src/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA new file mode 100644 index 0000000..8e361ea --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA @@ -0,0 +1,134 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 30 0a c5 df b0 |....z...v..0....| +00000010 90 3a 48 4b 20 f1 89 62 be 1f 1b 64 c2 7e 69 25 |.:HK ..b...d.~i%| +00000020 9f b7 f9 2c 86 e7 40 e7 e8 10 fa 20 00 00 00 00 |...,..@.... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 94 |..+.....3.$... .| +00000060 e8 ab 87 65 c8 dd 6f ee b4 d6 0b bb fd 18 9a 2d |...e..o........-| +00000070 e4 bc c6 20 98 09 71 65 7d 54 35 73 22 99 1b 14 |... ..qe}T5s"...| +00000080 03 03 00 01 01 17 03 03 00 17 37 b7 eb eb a2 9f |..........7.....| +00000090 7f 00 8c 9d a9 50 7c 0c 15 31 63 71 45 7a 3d ee |.....P|..1cqEz=.| +000000a0 5e 17 03 03 00 42 9f 23 07 cf d0 bc e8 bb 95 01 |^....B.#........| +000000b0 37 94 18 2e 05 02 8a eb 0a 37 10 79 51 a9 d4 43 |7........7.yQ..C| +000000c0 18 18 e6 00 9d 68 ff 74 f3 9c 19 bf 5e 51 0c 47 |.....h.t....^Q.G| +000000d0 61 35 8c b2 58 5f 32 bc 88 c4 fb 5a 22 61 14 98 |a5..X_2....Z"a..| +000000e0 28 26 8c 75 9d 1d 19 05 17 03 03 02 22 d2 2c 1a |(&.u........".,.| +000000f0 e5 58 0d d7 0b c4 66 b2 06 90 bc 92 0f 05 34 5d |.X....f.......4]| +00000100 2b 20 26 02 cc ac 90 40 a0 f1 5f 0e b9 99 7c 0f |+ &....@.._...|.| +00000110 c9 3e 60 0b 39 ec 6c 94 3a d4 f7 b7 49 5e c7 6e |.>`.9.l.:...I^.n| +00000120 df 3b cc 33 cb 32 41 53 dd 09 8e 91 97 d2 e0 06 |.;.3.2AS........| +00000130 5e 0c 4c 49 46 18 83 fc ac b4 f8 76 2d 18 ee 0b |^.LIF......v-...| +00000140 b6 4a b9 aa eb ee db 7a aa 6d 04 84 ed 8e 15 bc |.J.....z.m......| +00000150 bf 6f a1 29 bc 0b 9f ba 05 a5 42 82 fd 1c 30 c9 |.o.)......B...0.| +00000160 20 df 8e ba 28 ab 0b a2 42 09 5e e8 c1 61 d2 25 | ...(...B.^..a.%| +00000170 fc 05 53 62 91 45 29 54 60 31 b8 4f 01 9c 7b 6a |..Sb.E)T`1.O..{j| +00000180 04 27 df bc e0 a0 3d b3 80 73 22 ca 9b 41 be b6 |.'....=..s"..A..| +00000190 09 22 67 1e 54 52 ce 14 b5 56 7a ca 3f a8 3e 01 |."g.TR...Vz.?.>.| +000001a0 d2 e4 36 18 87 f6 08 19 55 d2 ba 3c a3 c5 11 84 |..6.....U..<....| +000001b0 62 2a 09 c6 67 de cd ab 66 12 dd 0a 23 77 18 b7 |b*..g...f...#w..| +000001c0 73 c1 29 61 52 32 95 eb a0 db 72 ae b7 ff 2a b2 |s.)aR2....r...*.| +000001d0 08 f6 d7 69 32 c2 f8 8b e1 40 a9 d0 fe 11 64 a2 |...i2....@....d.| +000001e0 a2 dd a7 e6 a6 dd 5d 79 49 df bb c0 83 da 56 7a |......]yI.....Vz| +000001f0 a5 22 8e 60 df 89 48 e0 e2 e9 5f d5 fe dd ba 34 |.".`..H..._....4| +00000200 ad 91 52 d8 2f 7e a4 73 50 e8 b7 83 e2 d9 5e 05 |..R./~.sP.....^.| +00000210 96 08 e4 d4 bb 01 39 99 aa 1d fd 74 1b dc ca c2 |......9....t....| +00000220 8f bb b8 bf c4 eb 00 6f cc 70 eb 7c c7 29 e4 64 |.......o.p.|.).d| +00000230 8c 76 a7 b5 79 ea b6 96 fe eb 8f e7 81 9b d1 d0 |.v..y...........| +00000240 41 16 db ef 9e 55 2a 77 6c 34 54 22 48 6a ca 78 |A....U*wl4T"Hj.x| +00000250 31 6e d2 00 7f 54 93 65 ec 28 42 66 7b 74 4d 58 |1n...T.e.(Bf{tMX| +00000260 fe 25 74 bd 9f a4 ff f2 45 06 c6 63 1f 11 68 a4 |.%t.....E..c..h.| +00000270 fb fe 62 2b f8 19 e3 32 2c cc 5d 71 37 21 05 82 |..b+...2,.]q7!..| +00000280 c9 c7 30 c7 74 64 d9 f9 6b c2 ae d8 15 2b 2a 79 |..0.td..k....+*y| +00000290 a0 2d a3 18 1f d7 20 99 96 86 52 32 cf 84 bd 73 |.-.... ...R2...s| +000002a0 63 85 82 a3 64 fb e3 ea 1b 31 f5 df 1c 74 06 48 |c...d....1...t.H| +000002b0 69 8a e3 f0 72 8c 59 8b de 0b 06 02 47 54 4c 2d |i...r.Y.....GTL-| +000002c0 46 ac d4 f5 4d 5c fe 0d bf af d0 37 58 82 3e d2 |F...M\.....7X.>.| +000002d0 4e c1 7e 0f b0 21 f7 8e 2c 88 db 83 43 ed ad 5b |N.~..!..,...C..[| +000002e0 0f a2 ce 47 e4 3f dd 1b 71 fe f0 a7 a1 8d 8c dc |...G.?..q.......| +000002f0 75 e0 7a 89 f7 14 5b 37 9d 35 f6 23 91 a8 d2 1a |u.z...[7.5.#....| +00000300 96 07 1b 5b 9c 35 27 b8 b9 0c 92 1e cf 1b 3c 17 |...[.5'.......<.| +00000310 03 03 00 a4 f0 59 e1 1d 62 39 69 c5 53 ae 66 85 |.....Y..b9i.S.f.| +00000320 df ea 32 73 ca 94 e2 b5 14 d4 30 07 dd fd 2f 9a |..2s......0.../.| +00000330 16 fc e9 71 4a 20 b8 d2 7e 17 26 ff a9 55 56 24 |...qJ ..~.&..UV$| +00000340 31 85 bc ea 19 1c 37 b7 fe 8b 47 5f a3 99 0f 5d |1.....7...G_...]| +00000350 17 92 4b 2a 4c b5 6c db 8f bb 46 ee 89 31 53 79 |..K*L.l...F..1Sy| +00000360 aa 34 9d 9b e8 9b e7 82 55 a3 92 f6 53 53 d3 72 |.4......U...SS.r| +00000370 17 23 33 01 e8 75 7e 8d 63 91 a0 67 8f a5 f0 15 |.#3..u~.c..g....| +00000380 8c f5 81 e2 c4 08 ff 14 1d 96 cf ef 4e 09 18 a1 |............N...| +00000390 2c 38 0a f7 33 f0 1d ef 9d 12 4d 8c 25 f0 80 a2 |,8..3.....M.%...| +000003a0 aa a7 cf e4 7c e6 44 58 6d 30 70 48 55 3b b5 79 |....|.DXm0pHU;.y| +000003b0 55 aa 03 ed 14 ea e5 ee 17 03 03 00 35 72 1a ca |U...........5r..| +000003c0 5c 3d 3b 75 29 cc a9 09 85 67 89 37 18 91 c0 af |\=;u)....g.7....| +000003d0 28 d2 0c c9 8b 05 94 04 3a 68 38 f0 c3 db 95 89 |(.......:h8.....| +000003e0 c8 28 fc 07 4b 49 7d b6 25 36 05 53 96 e0 d9 35 |.(..KI}.%6.S...5| +000003f0 e5 7c |.|| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 02 11 6a 55 c4 ff 7a |...........jU..z| +00000010 5b c4 b7 cb 8d ad ae 53 53 3d 41 3a fc 16 44 fd |[......SS=A:..D.| +00000020 c8 5f 39 c3 5e 6b ee 7d ea 88 9c a9 78 f9 dc 51 |._9.^k.}....x..Q| +00000030 b2 90 68 7d ae 2c b7 90 6e 79 cf f4 97 50 95 87 |..h}.,..ny...P..| +00000040 f1 f6 2c 14 bc 2b a3 68 0d e6 c8 66 2f 3b 89 72 |..,..+.h...f/;.r| +00000050 67 4d d8 e9 8d 6a 89 2a f9 e4 c1 b5 c0 92 16 25 |gM...j.*.......%| +00000060 61 a6 98 ec b6 6b 52 8b a5 80 5a 9e 6d 03 ad 42 |a....kR...Z.m..B| +00000070 a9 46 2f d8 e5 67 c9 8d 89 f7 34 93 82 7c a3 bb |.F/..g....4..|..| +00000080 48 62 06 90 5c 5a aa fd 7c 71 88 24 22 f9 6a 2c |Hb..\Z..|q.$".j,| +00000090 d1 d9 7e 0a 4c 39 11 e8 c0 17 1d 83 64 f2 2b c6 |..~.L9......d.+.| +000000a0 c0 81 8c 6a 39 a9 09 aa 1e 58 eb 30 88 59 4d f2 |...j9....X.0.YM.| +000000b0 d2 64 9f 4c 90 29 c0 66 94 e3 df 12 9c 75 33 24 |.d.L.).f.....u3$| +000000c0 fb 14 bc 70 e1 b5 de 54 28 b0 3f 01 2c 2e 5f 35 |...p...T(.?.,._5| +000000d0 e3 01 59 2a 3f ce ca 11 bb 29 97 03 f6 f4 30 b9 |..Y*?....)....0.| +000000e0 66 db 3c f7 06 41 7b e8 f8 af 3e 03 65 2f 5f 88 |f.<..A{...>.e/_.| +000000f0 fd 30 45 7a c9 b4 9f bf 03 eb c9 dd 06 ac 82 06 |.0Ez............| +00000100 e8 81 8e ea 29 45 78 5c 0f 8e 21 8a fb 0b 95 c1 |....)Ex\..!.....| +00000110 63 e9 18 c1 9a a4 c6 7d 56 4b 9a de 96 dd 37 54 |c......}VK....7T| +00000120 92 ef 71 42 a8 66 e7 df e7 ea ec 4e 3c b3 8e 7d |..qB.f.....N<..}| +00000130 ed 92 da 86 e5 fa 51 f8 e4 b0 09 f3 06 4d 38 f1 |......Q......M8.| +00000140 d5 5f d2 72 1e 5f c3 1e 1d fd 96 70 e7 9c ae ea |._.r._.....p....| +00000150 62 ce e4 a9 31 34 47 bc f0 9f 1c c7 b6 66 f0 70 |b...14G......f.p| +00000160 7a e1 c5 a9 76 64 d4 25 0f 56 cd 36 17 67 bd 4d |z...vd.%.V.6.g.M| +00000170 c7 78 d8 23 46 4b ac 46 34 1a d2 2d c5 e6 67 55 |.x.#FK.F4..-..gU| +00000180 11 ec 8c f0 67 84 bf 89 ce 3c 71 4e 3a ab ff 22 |....g....>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 a9 f1 13 c3 3c |....z...v......<| +00000010 1c dd c9 3a a1 ad 92 92 f1 f4 16 39 be 14 64 9c |...:.......9..d.| +00000020 66 d8 28 cd b7 bb 40 43 ec f4 67 20 00 00 00 00 |f.(...@C..g ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 ff |..+.....3.$... .| +00000060 53 ac b3 b0 48 47 d0 1e b1 70 eb dd 02 e5 e8 07 |S...HG...p......| +00000070 ce c7 e0 af d7 e0 46 c7 ff f5 97 30 e5 80 5b 14 |......F....0..[.| +00000080 03 03 00 01 01 17 03 03 00 17 0b 12 ef 6d ea 5e |.............m.^| +00000090 71 41 83 d6 35 9f 39 2c f0 ab 01 e9 03 54 c6 9e |qA..5.9,.....T..| +000000a0 37 17 03 03 00 20 15 7a 35 f4 a6 6e 65 89 10 ae |7.... .z5..ne...| +000000b0 18 31 c0 0c 15 1c b8 c5 5d f3 54 0c 98 32 a4 5e |.1......].T..2.^| +000000c0 91 f7 03 8a 80 b9 17 03 03 02 7a fa 93 7f c6 d1 |..........z.....| +000000d0 2f 7e 2d d6 1b b7 ff fd 96 6e a1 f7 0e 98 dc 77 |/~-......n.....w| +000000e0 cc 6a 4e 91 3d c1 ad 4b 5c 28 ee ea a7 0a ce 8f |.jN.=..K\(......| +000000f0 51 dd 89 fd 5a 81 6d 21 d6 0d 35 70 84 73 8c fa |Q...Z.m!..5p.s..| +00000100 2e 7a e0 af ab 79 79 aa 67 2b 80 a8 b3 a8 fb 0d |.z...yy.g+......| +00000110 eb 87 66 d5 be 33 0b f0 80 b8 5e 21 84 be 25 fe |..f..3....^!..%.| +00000120 47 98 5a 26 5d c3 96 2e c5 b8 da 9f a6 d4 ca bb |G.Z&]...........| +00000130 de 7f 2c 0a 28 a8 f3 41 bc a2 2e 70 f2 b3 6f a3 |..,.(..A...p..o.| +00000140 10 0e 1f 11 af 11 50 2b 22 84 97 d7 80 f5 62 77 |......P+".....bw| +00000150 a6 94 47 22 ef 24 c6 0e dc 5c f5 40 08 f7 21 78 |..G".$...\.@..!x| +00000160 ae 11 f3 d8 a5 d8 20 ac 90 73 d7 a2 e3 f0 08 57 |...... ..s.....W| +00000170 fc 74 70 66 fd 3d 49 c7 99 37 98 5e b1 1c c4 38 |.tpf.=I..7.^...8| +00000180 64 09 e6 70 b6 8b 00 72 2d 5b b4 70 39 d6 e9 d5 |d..p...r-[.p9...| +00000190 dc cd 8e 01 eb 5f 34 61 d0 97 62 0b 4f 81 ed 30 |....._4a..b.O..0| +000001a0 64 56 f2 6e 31 5e 24 e8 56 2b d6 31 54 c4 48 47 |dV.n1^$.V+.1T.HG| +000001b0 16 00 a7 65 c1 fa ea 12 30 78 41 e7 30 2d 71 cf |...e....0xA.0-q.| +000001c0 b0 e9 be e4 a2 33 38 87 2d 37 14 2d 03 cf ae 87 |.....38.-7.-....| +000001d0 9a 09 f2 ed f3 44 66 c3 8a 56 8e e4 c4 aa e9 f7 |.....Df..V......| +000001e0 cd 75 52 1b d9 ed 66 04 13 dd dd cf 0f 44 cd 18 |.uR...f......D..| +000001f0 68 c5 2c 4c f9 e3 d3 02 12 78 38 5c f6 96 d7 80 |h.,L.....x8\....| +00000200 f0 83 03 fe 7a e0 35 7e a3 ad 99 52 ec fc ee 74 |....z.5~...R...t| +00000210 f5 09 0f ca 69 f0 fb d0 40 90 1b 46 9e 2d 62 c9 |....i...@..F.-b.| +00000220 0f 59 b2 cc a0 4a 9b 84 14 3a 1b 51 fc e7 e8 a1 |.Y...J...:.Q....| +00000230 26 fd 20 8c 88 6f 87 11 ae 97 76 f8 4b cc 67 1a |&. ..o....v.K.g.| +00000240 3e 58 65 77 77 82 06 c0 d4 41 4e 66 d2 5a 83 b1 |>Xeww....ANf.Z..| +00000250 ee 19 5d 7b 99 34 d3 2f 6c bd 30 a3 8c 75 89 ec |..]{.4./l.0..u..| +00000260 cb 90 8b 89 05 b8 e4 6e 3b 60 5d 0e 19 8f d6 c7 |.......n;`].....| +00000270 86 f0 a9 2b c7 12 4a 4c d8 a5 e8 64 49 1d 49 99 |...+..JL...dI.I.| +00000280 a7 80 01 f0 77 57 4a 78 3c ac 38 40 bb d2 10 24 |....wWJx<.8@...$| +00000290 9d e2 29 b2 1e 4b 50 66 64 07 79 80 c7 81 9d e2 |..)..KPfd.y.....| +000002a0 f5 a9 10 9a 8d 3b de 0e 21 85 13 ac 26 30 f9 e4 |.....;..!...&0..| +000002b0 a6 f9 8f e0 3c c1 69 7e 11 4c d1 a8 4e 88 30 fc |....<.i~.L..N.0.| +000002c0 52 6e b0 4f b6 7e 15 9e a5 8a 46 ca 1f ac 8e 2a |Rn.O.~....F....*| +000002d0 07 34 d7 c2 14 c6 c1 ed a1 f9 1e 59 b4 b4 86 3e |.4.........Y...>| +000002e0 d3 d0 78 a6 07 62 d3 88 80 54 a8 2a e9 38 2e 58 |..x..b...T.*.8.X| +000002f0 43 94 cc ed f0 46 f6 cc 4b 7a b8 f5 a2 d6 a8 36 |C....F..Kz.....6| +00000300 e2 8e 11 fb e7 21 19 c5 fa c9 90 98 72 43 88 ac |.....!......rC..| +00000310 c0 56 84 9e cd b7 e5 26 d6 49 19 88 a5 12 ac 49 |.V.....&.I.....I| +00000320 5d 77 37 2a ff 38 5a 7a 5b c8 74 5d 74 fc 22 7f |]w7*.8Zz[.t]t.".| +00000330 46 97 2b 34 32 fb 83 65 75 b6 8b 5c 8a b1 d4 a2 |F.+42..eu..\....| +00000340 14 7f 46 0d 63 17 03 03 00 99 c7 79 bb 4f 88 a0 |..F.c......y.O..| +00000350 78 be 04 ca 39 1f 1f a8 82 59 b5 dd 96 93 0d c4 |x...9....Y......| +00000360 30 f4 22 4c e2 52 51 d4 33 b8 35 7b ed 01 19 25 |0."L.RQ.3.5{...%| +00000370 b5 31 36 25 23 a2 51 d9 7a a9 00 72 05 34 81 62 |.16%#.Q.z..r.4.b| +00000380 d0 df 8b 3a 65 98 4e 87 e2 29 9b 44 77 8c dd c9 |...:e.N..).Dw...| +00000390 4c a5 de 14 97 e0 f1 2c e8 5d 0e 8f d0 fd f6 77 |L......,.].....w| +000003a0 c1 1f ac 79 4d 32 19 09 98 a8 f0 2f 3e d5 7e f7 |...yM2...../>.~.| +000003b0 aa c1 f0 36 b1 8e c7 0b ce 09 00 ac 28 64 c0 33 |...6........(d.3| +000003c0 58 cc 48 3a 15 a4 77 24 50 67 f2 39 53 4d 63 23 |X.H:..w$Pg.9SMc#| +000003d0 48 74 bd 0a c8 02 17 be e4 64 af 6e 02 a9 22 92 |Ht.......d.n..".| +000003e0 65 04 c6 17 03 03 00 35 e0 4e 15 4b 9d 53 57 c6 |e......5.N.K.SW.| +000003f0 97 b4 9d 1a 03 39 26 b9 ca 5b 04 50 af db 52 99 |.....9&..[.P..R.| +00000400 d9 13 40 6a 89 23 99 42 9a 91 1d d1 6c 07 a0 aa |..@j.#.B....l...| +00000410 05 6e 60 0b fd e7 de 32 c3 97 18 0d 9b |.n`....2.....| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 02 7a 94 78 2d 5d 5a |..........z.x-]Z| +00000010 3e 96 7f 19 29 51 99 f3 6e d3 a4 d5 3c 9a 3d d5 |>...)Q..n...<.=.| +00000020 37 bc 3b 71 b3 54 83 d9 5e 9d 64 76 f9 74 7a 24 |7.;q.T..^.dv.tz$| +00000030 e3 cb ea aa 17 f4 44 41 73 71 39 d6 9b d5 a6 a2 |......DAsq9.....| +00000040 6a 1e 1c 02 a1 d5 e3 e8 f5 f7 07 9d 3b ea f8 6d |j...........;..m| +00000050 80 cf 6b 14 71 b8 bd c4 8a 07 49 31 e7 bd d5 91 |..k.q.....I1....| +00000060 ac 80 70 25 5e f4 db 07 ed 36 c2 3a 1d ad 86 6e |..p%^....6.:...n| +00000070 68 1a ca 4f a1 ba c3 2f de 49 01 fa a9 39 a6 51 |h..O.../.I...9.Q| +00000080 3a e6 9f cf 6b 02 4e 1e 70 dd f2 10 c2 62 9b 1f |:...k.N.p....b..| +00000090 83 10 fa 85 52 a8 a7 08 37 9c 92 b0 9c fe 00 78 |....R...7......x| +000000a0 0b a4 7b b5 f9 9f 87 d2 d3 07 72 b2 ab 96 9e 73 |..{.......r....s| +000000b0 55 3c 1e 65 99 89 36 78 7e 42 8f 05 de b6 fb fc |U<.e..6x~B......| +000000c0 1b 34 18 e6 4d 15 6c d1 2f 2c b0 ef 00 e9 07 89 |.4..M.l./,......| +000000d0 ca 91 d9 c1 73 bf 8f a5 a4 7d 7e cc f5 85 fb af |....s....}~.....| +000000e0 57 70 35 63 71 d6 78 57 13 48 27 ba a4 42 22 c2 |Wp5cq.xW.H'..B".| +000000f0 56 f4 ae 38 39 a0 1f 57 44 57 c4 8a 70 90 30 70 |V..89..WDW..p.0p| +00000100 ba 4a 98 29 0f aa e2 33 27 24 ee d9 e9 02 80 68 |.J.)...3'$.....h| +00000110 4c 55 08 fb 3d 25 d6 d4 9d 83 ea 14 99 c2 77 94 |LU..=%........w.| +00000120 f9 70 34 a8 ed 35 e6 4f c2 75 50 63 d5 9d 9a 89 |.p4..5.O.uPc....| +00000130 8f 2e 5b ca 6b b3 ad e7 a2 c6 f7 0c 45 08 b7 f4 |..[.k.......E...| +00000140 58 d3 d5 54 c2 67 f3 76 fb fc 9d fe 42 43 ea 90 |X..T.g.v....BC..| +00000150 2b 29 e7 10 2f d7 9c 04 c4 cc 89 8f a9 36 14 f6 |+)../........6..| +00000160 fc f1 25 6c 90 12 bf c6 cd ad 46 ce 17 3b 26 fb |..%l......F..;&.| +00000170 c6 98 cb 6c f2 2c fd b9 2f 52 3e 56 42 78 0b 92 |...l.,../R>VBx..| +00000180 a5 27 56 18 3d d6 26 3f e4 a1 6f ce c8 f1 f1 7a |.'V.=.&?..o....z| +00000190 1f 84 66 c9 d9 8a 5c 0e 34 80 ba 58 b3 8b 7f f3 |..f...\.4..X....| +000001a0 8a c9 6b c4 99 94 2c b7 e8 e8 9a a5 43 75 f8 e0 |..k...,.....Cu..| +000001b0 29 1f 70 77 c7 4a 9f de ca 92 88 7c 37 12 d9 ef |).pw.J.....|7...| +000001c0 2f 94 de ea d1 d9 69 6a 93 06 36 e0 68 02 53 ae |/.....ij..6.h.S.| +000001d0 0e 00 cd ad d3 10 a7 89 2c 53 a7 03 d9 07 3c e9 |........,S....<.| +000001e0 0b b0 18 2e 03 88 03 5c f4 b2 7e 59 f4 22 8c f7 |.......\..~Y."..| +000001f0 5e d7 c7 ea ac 0f bc f7 3e 3f 75 fd 6d 9c 4c 3c |^.......>?u.m.L<| +00000200 41 8d f5 30 17 20 83 c3 27 83 ce 84 6a e3 75 2b |A..0. ..'...j.u+| +00000210 9d 7d de 2a bf 5a fb e1 2f 80 74 74 f6 09 bc 1f |.}.*.Z../.tt....| +00000220 be f0 59 9e ce a1 62 46 54 a4 9a 25 97 b7 cd 1a |..Y...bFT..%....| +00000230 0a d0 44 f6 ea a4 ed 63 e7 49 9a 4b f4 1a 39 91 |..D....c.I.K..9.| +00000240 e6 34 e1 7b dd e7 53 ab 83 56 57 b2 89 3f 90 1f |.4.{..S..VW..?..| +00000250 98 c4 64 27 b5 f5 f6 57 16 ca d9 0a 33 de 24 c3 |..d'...W....3.$.| +00000260 f3 7c 23 37 94 93 c5 1a 42 da 18 6b 24 dd 37 54 |.|#7....B..k$.7T| +00000270 ae f3 8a 3e 10 42 20 6e 49 23 1a 0f bd 65 7e 45 |...>.B nI#...e~E| +00000280 12 7a 64 9a 30 17 03 03 00 99 af 41 cf 95 21 1f |.zd.0......A..!.| +00000290 34 df 1c c7 a8 b6 ee 31 8d b3 9e 5a 59 8e c4 37 |4......1...ZY..7| +000002a0 79 a4 d8 75 22 da 12 21 e5 de d4 ad 98 17 e2 ae |y..u"..!........| +000002b0 ae 9f f6 e8 29 66 d0 ac b4 08 16 24 40 67 9d d5 |....)f.....$@g..| +000002c0 bf a4 64 91 a1 17 82 c0 e7 77 b6 20 26 4a 70 1d |..d......w. &Jp.| +000002d0 c8 f8 ec 18 b7 c6 3c 81 b9 c6 04 9c 0d 37 a6 39 |......<......7.9| +000002e0 fd 2d 99 d7 ba 41 a4 91 60 f1 1f d2 76 76 aa 47 |.-...A..`...vv.G| +000002f0 89 0a d1 97 0b 91 20 a9 43 c9 ce 2c 84 ba 81 7a |...... .C..,...z| +00000300 39 91 7d 12 75 05 8e 87 b1 3f 80 8d 12 ca 8f 91 |9.}.u....?......| +00000310 23 84 28 11 c3 81 ed 09 05 16 6e 50 57 76 ad 5c |#.(.......nPWv.\| +00000320 c5 92 77 17 03 03 00 35 5a d9 15 29 1f a3 f0 cf |..w....5Z..)....| +00000330 74 c4 1d 0c c3 fa 54 59 1e 54 06 0d 1b ce 07 00 |t.....TY.T......| +00000340 f9 66 3d e1 75 10 cf de cb 7d 0d d6 d1 4d 87 81 |.f=.u....}...M..| +00000350 13 ec 2c 28 13 a5 b3 01 c7 86 3a 84 65 17 03 03 |..,(......:.e...| +00000360 00 17 b4 e4 18 61 62 04 b3 ca 98 36 93 42 a2 be |.....ab....6.B..| +00000370 2c f5 18 11 bd 7d 64 70 bc 17 03 03 00 13 32 65 |,....}dp......2e| +00000380 fa 07 3e 3c ed 9d 85 31 ba 8e 92 ea de 17 59 cd |..><...1......Y.| +00000390 db |.| diff --git a/src/crypto/tls/testdata/Client-TLSv13-ECDSA b/src/crypto/tls/testdata/Client-TLSv13-ECDSA new file mode 100644 index 0000000..dac9ef7 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-ECDSA @@ -0,0 +1,86 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 e3 21 e8 24 fb |....z...v...!.$.| +00000010 e8 fe 46 e2 54 a7 db 98 ae a4 b2 fc f8 17 99 b4 |..F.T...........| +00000020 ed 6a aa 9c f9 ce e2 0f f8 88 05 20 00 00 00 00 |.j......... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 a9 |..+.....3.$... .| +00000060 5a 5c e9 b1 71 e8 a8 64 97 65 02 6b 3d 25 6f 6f |Z\..q..d.e.k=%oo| +00000070 9a 47 cb 4a 81 ac 89 23 22 c1 f4 3d db 77 1e 14 |.G.J...#"..=.w..| +00000080 03 03 00 01 01 17 03 03 00 17 12 15 75 15 9f 10 |............u...| +00000090 90 07 34 9c eb 05 d0 a1 4b 36 5b 4c 7b 26 2a 00 |..4.....K6[L{&*.| +000000a0 29 17 03 03 02 22 85 a0 67 d7 72 57 83 19 79 12 |)...."..g.rW..y.| +000000b0 b7 bd 37 ed ab 49 5d 15 49 2b 4f a1 b2 25 08 22 |..7..I].I+O..%."| +000000c0 88 83 70 07 bc 8f 69 45 1b 21 36 99 f4 99 40 f8 |..p...iE.!6...@.| +000000d0 0d 30 13 87 70 68 f6 9d ce c7 9e 25 2c 1e 7a b5 |.0..ph.....%,.z.| +000000e0 52 ed f8 0f f7 d9 e5 15 fc a3 47 83 0d 18 c4 de |R.........G.....| +000000f0 a1 a6 24 35 aa 56 d1 8b 95 07 5f 0f ba 1f 96 c3 |..$5.V...._.....| +00000100 5b 36 cc d2 15 e6 b4 88 8f e3 7f 79 c2 24 d5 f3 |[6.........y.$..| +00000110 a7 35 69 4e d2 2a f7 5c 08 8a c0 26 dd b9 77 5b |.5iN.*.\...&..w[| +00000120 96 1b 5f 03 89 07 a0 6a b1 14 1d 02 46 08 eb 80 |.._....j....F...| +00000130 d5 4c dc 69 63 8f 14 a1 e5 02 95 05 8a 8b c8 68 |.L.ic..........h| +00000140 c3 d8 75 56 47 94 32 ba 67 71 ed 4b b4 62 ba 6a |..uVG.2.gq.K.b.j| +00000150 31 20 a7 d6 f8 8c a0 e9 e8 d2 1a 6b 85 6b b7 ee |1 .........k.k..| +00000160 78 e1 2e 4c 14 f0 b3 3e b8 dc 7d af f0 9d 29 f3 |x..L...>..}...).| +00000170 54 1d 9d dc 9e a3 9f 29 5b 33 1d f7 00 98 85 bd |T......)[3......| +00000180 42 39 85 75 cf fa dc f3 7e 80 14 4e a5 90 80 b6 |B9.u....~..N....| +00000190 e3 37 d3 27 c6 7b b9 ee 32 61 a5 72 e5 2f a6 ab |.7.'.{..2a.r./..| +000001a0 cb 8e ac 53 4b 86 24 92 4b 77 d6 8d aa b4 37 d5 |...SK.$.Kw....7.| +000001b0 2b b2 2f 07 23 37 4a d9 1f cc 6c 72 c6 21 5b 38 |+./.#7J...lr.![8| +000001c0 a3 33 5c 86 50 69 34 8f 5a b8 cc 5e 82 7d 5b b2 |.3\.Pi4.Z..^.}[.| +000001d0 5b f5 58 7f 2c 61 08 4b 3d 8b 67 09 19 01 d2 4f |[.X.,a.K=.g....O| +000001e0 06 62 17 4e d4 bf 88 89 bb c4 6e 14 2b 3a 50 c9 |.b.N......n.+:P.| +000001f0 56 8a c1 0a 45 e6 67 32 f3 96 37 4b ba c2 2a 2b |V...E.g2..7K..*+| +00000200 84 e1 ff bb e0 ea 68 9b 98 fc 78 26 25 f6 50 25 |......h...x&%.P%| +00000210 52 57 83 94 39 b9 a7 8d 38 43 70 a8 b7 61 a6 cf |RW..9...8Cp..a..| +00000220 09 77 db 3d 64 94 63 73 5b a1 6d f4 06 c1 b3 fb |.w.=d.cs[.m.....| +00000230 c6 9a 0b ea 9f 8e 6d 58 53 0e 13 e0 a6 21 69 7a |......mXS....!iz| +00000240 d3 57 32 d4 c6 32 ef 02 8e 54 1d 72 2d d6 a7 dc |.W2..2...T.r-...| +00000250 59 54 be 69 3f 5c 53 23 a9 f7 3e a9 e6 e7 e0 98 |YT.i?\S#..>.....| +00000260 65 f6 74 f4 49 1c 77 0f 92 34 87 81 29 85 d1 e0 |e.t.I.w..4..)...| +00000270 1e 4d b4 eb c2 44 43 a7 10 51 7c 5e 8e a4 b6 37 |.M...DC..Q|^...7| +00000280 78 e8 35 02 07 3d 60 a5 01 75 01 25 f3 ff 32 ff |x.5..=`..u.%..2.| +00000290 34 ab a4 c3 4c ad 21 b8 91 0a d6 54 4b 7d cf c5 |4...L.!....TK}..| +000002a0 ec 0f e5 4a 4d 75 4c ec fc 37 2b 26 5a 73 93 70 |...JMuL..7+&Zs.p| +000002b0 88 c7 9c cf 32 f9 ee a7 27 6e 1d 9e 36 a2 31 9e |....2...'n..6.1.| +000002c0 cd 0e c2 89 ef 2b 40 1a 17 03 03 00 a4 ad 19 05 |.....+@.........| +000002d0 e6 40 5e b1 ec 69 6b 47 ef 5d d3 ee a6 94 51 85 |.@^..ikG.]....Q.| +000002e0 d8 28 d9 df 8b d0 df 23 7e bd 98 6c 33 26 45 fa |.(.....#~..l3&E.| +000002f0 60 71 8b f5 71 5c 22 4e b3 a7 01 fe 17 39 89 67 |`q..q\"N.....9.g| +00000300 0b 70 ff 52 b9 10 9c e9 02 c0 1c 56 9d c8 45 51 |.p.R.......V..EQ| +00000310 5a dd 86 79 6d a7 7d eb 16 c2 1a 5f 6a 3b 93 42 |Z..ym.}...._j;.B| +00000320 13 f3 3d 8a 39 21 5f a9 7f cf 4b 1e 22 f1 a3 f8 |..=.9!_...K."...| +00000330 5c 35 41 2a e2 91 72 4f 59 61 1c 15 be 27 6a bd |\5A*..rOYa...'j.| +00000340 b7 16 1f 63 97 51 d6 96 dd 81 f9 e7 fd 97 33 6e |...c.Q........3n| +00000350 da 5a 61 77 57 6e 3b 65 24 db b3 3a 18 7b dc f4 |.ZawWn;e$..:.{..| +00000360 7c ff ab 43 7f 1b ae ae b8 73 71 9e be 91 d6 56 ||..C.....sq....V| +00000370 13 17 03 03 00 35 39 61 a3 b7 e5 1d 3d 87 92 84 |.....59a....=...| +00000380 11 39 7d f4 ce 29 b9 4b fd 3c 0c 5a b6 3a fa e2 |.9}..).K.<.Z.:..| +00000390 a8 5b e6 d2 e5 7e e3 a6 33 59 e4 a8 59 95 5d b9 |.[...~..3Y..Y.].| +000003a0 31 6d 51 90 22 be c0 3f 6e 43 f2 |1mQ."..?nC.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 50 4f ce ae a5 |..........5PO...| +00000010 f7 b0 7e 2b 91 86 72 da 90 65 fd 1b a5 46 c6 98 |..~+..r..e...F..| +00000020 47 90 5a f2 b8 5a 1f 18 44 19 bd ca dd 2a 15 e7 |G.Z..Z..D....*..| +00000030 53 f5 17 e8 7d 9b f1 9a 63 ac b0 b0 df c3 0e 4c |S...}...c......L| +00000040 17 03 03 00 17 8b bd fb bc fd f7 af 53 9b 8b 1a |............S...| +00000050 a3 e5 f6 e9 87 bd 4a 8a 1b 0e c9 d9 17 03 03 00 |......J.........| +00000060 13 8e c6 d3 6e 04 8f 3b d4 76 a4 c7 c8 63 a8 a8 |....n..;.v...c..| +00000070 9e ba e7 fd |....| diff --git a/src/crypto/tls/testdata/Client-TLSv13-Ed25519 b/src/crypto/tls/testdata/Client-TLSv13-Ed25519 new file mode 100644 index 0000000..d284740 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-Ed25519 @@ -0,0 +1,68 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 6f b6 d3 79 9b |....z...v..o..y.| +00000010 00 17 a8 46 3f e4 bc fc 08 1e 56 6c d8 63 86 f3 |...F?.....Vl.c..| +00000020 83 1b d8 26 6d 86 d6 4c f3 4f e1 20 00 00 00 00 |...&m..L.O. ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 5b |..+.....3.$... [| +00000060 8f 4f 5a a9 95 6b 04 07 31 d3 ed 91 8b 25 b4 7b |.OZ..k..1....%.{| +00000070 5c a1 0a a6 26 09 92 9b b0 72 26 f9 0d 09 60 14 |\...&....r&...`.| +00000080 03 03 00 01 01 17 03 03 00 17 a8 99 d3 76 1f 12 |.............v..| +00000090 19 18 15 8e 4c 59 43 92 11 4a aa 50 98 7e 4c d9 |....LYC..J.P.~L.| +000000a0 63 17 03 03 01 50 66 f5 d6 ce 35 0f 10 e5 ab 34 |c....Pf...5....4| +000000b0 78 17 c6 b6 60 40 eb 53 34 9f ce 02 c4 36 51 18 |x...`@.S4....6Q.| +000000c0 c2 b3 fb f3 98 92 d0 f2 b7 be 28 f5 c7 2d fa 1f |..........(..-..| +000000d0 9b 8b aa e5 45 54 6b 0e ed 6b 44 cb d4 4d 62 b2 |....ETk..kD..Mb.| +000000e0 30 c9 df ac cf a3 7e 43 58 1e bf 6e 5b 69 4e 48 |0.....~CX..n[iNH| +000000f0 1c 39 49 eb 8a 0c 22 f3 70 4a 80 50 39 d6 68 29 |.9I...".pJ.P9.h)| +00000100 d0 6d 08 20 26 39 6d 37 5a 9f 79 e9 16 e3 7e 94 |.m. &9m7Z.y...~.| +00000110 8f 5f 9b 97 2d e1 b1 48 e4 a3 36 63 40 5a 80 93 |._..-..H..6c@Z..| +00000120 06 27 3b 93 d9 ed 2d b1 3e 74 ed bc 38 a1 cb 17 |.';...-.>t..8...| +00000130 06 4a 9b c1 c1 d7 7a 1c ca ff 4d ee 91 6d d0 3c |.J....z...M..m.<| +00000140 c2 4b cc 33 c6 7c 76 8e db a2 e0 fe 15 e2 ec db |.K.3.|v.........| +00000150 1f 5d 05 c8 5e 0e 7f 2c 7a 95 08 34 68 a2 2c 7c |.]..^..,z..4h.,|| +00000160 04 16 92 7a c8 ec 52 2d 1a c4 7a ea 12 cd 0f b9 |...z..R-..z.....| +00000170 7c 00 51 55 02 5b 02 7d ec 89 af f5 6d 76 89 0e ||.QU.[.}....mv..| +00000180 67 42 f0 e4 67 4d 3f 70 ff 2c 64 81 1c 4a 92 1f |gB..gM?p.,d..J..| +00000190 26 8b a4 4f 15 18 b5 11 4a 61 df 45 53 74 fd 8d |&..O....Ja.ESt..| +000001a0 ff 22 32 91 af c7 7f a4 7b 62 c3 3b 30 51 b6 34 |."2.....{b.;0Q.4| +000001b0 b6 01 21 f9 86 74 be 62 27 1a 41 1f f0 0d 8b 5c |..!..t.b'.A....\| +000001c0 4b 82 ea 76 23 9c 36 af 25 1f f6 2d 5f 9c 28 bd |K..v#.6.%..-_.(.| +000001d0 b6 d5 1e 26 8b c1 dc ac ed 6d 10 ff 13 ed fc 08 |...&.....m......| +000001e0 08 0a 74 1c b1 5b f8 45 e4 83 44 f2 be ce 8d ac |..t..[.E..D.....| +000001f0 ee ae e6 21 da c7 17 03 03 00 59 d9 b3 95 0a f7 |...!......Y.....| +00000200 1a 1a 54 fa ab 09 38 6d 6d 53 0a ef 11 73 bc a2 |..T...8mmS...s..| +00000210 20 03 31 48 e2 0a d1 af 56 6c ca dd 88 ba 72 3a | .1H....Vl....r:| +00000220 c1 e0 c5 60 44 74 d6 c9 18 23 96 2c e7 88 c8 3e |...`Dt...#.,...>| +00000230 02 73 c0 38 d4 bd 85 a4 bb 78 a0 ba d3 fd f1 c4 |.s.8.....x......| +00000240 27 08 05 fb 2c 26 20 b7 1a 41 87 a6 b7 97 19 26 |'...,& ..A.....&| +00000250 50 ed 9a e4 17 03 03 00 35 68 36 c7 78 c3 5e ff |P.......5h6.x.^.| +00000260 b3 92 a7 25 31 2a a2 fa 24 d9 da 69 16 03 8b db |...%1*..$..i....| +00000270 fe b2 3f 63 88 49 f1 14 63 7a 58 a9 6f c5 64 92 |..?c.I..czX.o.d.| +00000280 21 84 82 d8 49 98 fb f3 f1 fd 52 83 32 97 |!...I.....R.2.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 07 7b a2 7a 4f |..........5.{.zO| +00000010 40 e9 a2 94 9f b7 2d 91 87 1e 37 b0 ca b7 ea 91 |@.....-...7.....| +00000020 53 f1 bf 7d 56 6a 0c 6a 9d 07 ac 93 9c db ca ac |S..}Vj.j........| +00000030 43 7b eb 56 9d 6c 79 f2 72 f8 0b 8d 15 08 84 d5 |C{.V.ly.r.......| +00000040 17 03 03 00 17 07 b3 7d a9 56 c4 76 e5 12 97 29 |.......}.V.v...)| +00000050 b7 99 e6 3e 08 79 2d fb 1a 5b eb 7a 17 03 03 00 |...>.y-..[.z....| +00000060 13 66 b7 65 57 0d 54 7b 6a 34 98 a1 4e 29 d5 92 |.f.eW.T{j4..N)..| +00000070 1e b6 52 bc |..R.| diff --git a/src/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial b/src/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial new file mode 100644 index 0000000..a0ede61 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial @@ -0,0 +1,90 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 d6 7f ef 2d f6 |....z...v.....-.| +00000010 82 d9 be 6d 33 80 73 c0 d4 d8 63 e9 95 a6 5b 1f |...m3.s...c...[.| +00000020 ce c0 ec 13 07 f4 68 7d cc 79 18 20 00 00 00 00 |......h}.y. ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 00 |..+.....3.$... .| +00000060 e9 40 7a 65 78 98 47 43 aa e1 63 fd 6b c4 21 1d |.@zex.GC..c.k.!.| +00000070 58 45 5f 64 a0 18 55 a0 c3 14 7d 4e 12 93 7c 14 |XE_d..U...}N..|.| +00000080 03 03 00 01 01 17 03 03 00 17 4c 01 0b f7 e7 1b |..........L.....| +00000090 a9 47 84 10 3b 50 85 6e 3d 8e 52 bc 99 bf d4 35 |.G..;P.n=.R....5| +000000a0 45 17 03 03 02 6d 8c b3 22 04 de 8b 09 e5 e7 9f |E....m..".......| +000000b0 d5 1f fb 8a 57 ad a7 93 4c 5f 29 46 df c3 e5 86 |....W...L_)F....| +000000c0 66 f1 c7 6b 14 79 cf 9d cc e1 f5 3f 31 2c dc ff |f..k.y.....?1,..| +000000d0 77 99 14 9e 56 12 4e a4 cb 56 5c d6 c0 5b 57 dc |w...V.N..V\..[W.| +000000e0 22 72 12 2d d6 a0 8a c7 90 e6 41 66 78 1a d7 a6 |"r.-......Afx...| +000000f0 87 db f1 e3 9b 86 8c cf 94 22 cf 81 99 20 bc 19 |........."... ..| +00000100 50 f9 fe 6c ab ea d4 a2 ee f8 17 1d ae 37 86 2a |P..l.........7.*| +00000110 f9 83 3c 59 d0 aa 63 22 18 d5 12 40 be f7 02 f1 |..z.R| +00000310 3c c9 2f 17 03 03 00 99 07 91 f0 6b e0 bb 6f 0b |<./........k..o.| +00000320 ff 08 69 bc d2 1d f1 40 d2 d7 c7 f6 c2 b3 57 d7 |..i....@......W.| +00000330 90 00 c9 9e ef 40 b6 96 86 0d 27 8b 6f ac 54 2f |.....@....'.o.T/| +00000340 73 b3 b4 82 1b d3 f5 e9 41 a7 fd d5 b1 67 f7 6e |s.......A....g.n| +00000350 2e c1 06 34 ef a3 b9 97 4d a8 64 4f f8 48 24 5c |...4....M.dO.H$\| +00000360 66 f4 d7 d4 e3 ad 45 fb 4a 42 0d 19 bb a1 cc b3 |f.....E.JB......| +00000370 88 d2 2a d7 c3 53 c4 7b 08 a5 68 dc c4 1a f6 f3 |..*..S.{..h.....| +00000380 a1 42 48 1c c9 2b 1f fb 5d fc 49 ed ce 16 14 34 |.BH..+..].I....4| +00000390 34 01 c9 ef e6 29 9c 81 1a 7d 7b bd 95 eb ad 5f |4....)...}{...._| +000003a0 ce 19 30 9c e6 ae 09 15 3c 2b 38 8b e6 97 76 4e |..0.....<+8...vN| +000003b0 dd 17 03 03 00 35 d2 a1 3f 22 e9 2b b6 7a d1 d8 |.....5..?".+.z..| +000003c0 7b 87 bf d1 bf 56 0b 55 52 d0 a9 cf ae 57 6e 6f |{....V.UR....Wno| +000003d0 29 0c c3 f7 f3 d4 bf ff a4 6b 49 1a 57 57 27 89 |)........kI.WW'.| +000003e0 e0 f5 bb d2 16 85 39 40 fd 77 a3 |......9@.w.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 b3 39 ad 6b 24 |..........5.9.k$| +00000010 47 e3 9f 11 f9 7e 9a cf 41 db c8 43 ce 86 ae ce |G....~..A..C....| +00000020 0c af 17 42 d7 24 57 13 e6 ba a7 44 7c 72 38 aa |...B.$W....D|r8.| +00000030 8f fa a2 a2 9f b0 ba 43 47 20 e8 03 3c 00 ee ad |.......CG ..<...| +00000040 17 03 03 00 17 ff 5b 79 f8 c8 0c 7a 52 6d b0 b2 |......[y...zRm..| +00000050 22 17 3b 5d f9 75 23 bb 27 38 35 a6 17 03 03 00 |".;].u#.'85.....| +00000060 13 d3 94 d9 b5 8b fa dc b6 fe 26 ca b0 52 5c ef |..........&..R\.| +00000070 84 e3 3c f9 |..<.| diff --git a/src/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest b/src/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest new file mode 100644 index 0000000..4840339 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest @@ -0,0 +1,119 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 f6 01 00 00 f2 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 77 00 05 00 05 01 00 00 00 00 00 0a 00 |...w............| +00000090 06 00 04 00 1d 00 17 00 0b 00 02 01 00 00 0d 00 |................| +000000a0 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 05 |................| +000000b0 01 06 01 05 03 06 03 02 01 02 03 ff 01 00 01 00 |................| +000000c0 00 12 00 00 00 2b 00 09 08 03 04 03 03 03 02 03 |.....+..........| +000000d0 01 00 33 00 26 00 24 00 1d 00 20 2f e5 7d a3 47 |..3.&.$... /.}.G| +000000e0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +000000f0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 |......_X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 58 02 00 00 54 03 03 cf 21 ad 74 e5 |....X...T...!.t.| +00000010 9a 61 11 be 1d 8c 02 1e 65 b8 91 c2 a2 11 16 7a |.a......e......z| +00000020 bb 8c 5e 07 9e 09 e2 c8 a8 33 9c 20 00 00 00 00 |..^......3. ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 0c 00 2b 00 02 03 04 00 33 00 02 00 17 14 03 03 |..+.....3.......| +00000060 00 01 01 |...| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 16 03 03 01 17 01 00 01 13 03 |................| +00000010 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000030 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000050 00 00 00 32 cc a9 cc a8 c0 2b c0 2f c0 2c c0 30 |...2.....+./.,.0| +00000060 c0 09 c0 13 c0 0a c0 14 00 9c 00 9d 00 2f 00 35 |............./.5| +00000070 c0 12 00 0a c0 23 c0 27 00 3c c0 07 c0 11 00 05 |.....#.'.<......| +00000080 13 03 13 01 13 02 01 00 00 98 00 05 00 05 01 00 |................| +00000090 00 00 00 00 0a 00 06 00 04 00 1d 00 17 00 0b 00 |................| +000000a0 02 01 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 |................| +000000b0 05 08 06 04 01 05 01 06 01 05 03 06 03 02 01 02 |................| +000000c0 03 ff 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 |...........+....| +000000d0 04 03 03 03 02 03 01 00 33 00 47 00 45 00 17 00 |........3.G.E...| +000000e0 41 04 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 |A...7...Q.5uq..T| +000000f0 5b 12 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 |[....g..$ >.V...| +00000100 28 5e f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 |(^.+-O....lK[.V.| +00000110 32 42 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc |2B.X..I..h.A.Vk.| +00000120 5a 89 |Z.| +>>> Flow 4 (server to client) +00000000 16 03 03 00 9b 02 00 00 97 03 03 1d 65 62 8f 58 |............eb.X| +00000010 2b 99 04 1d fd cc e3 0b 46 5c 55 a9 3a 80 76 60 |+.......F\U.:.v`| +00000020 8f 52 09 6e 48 5d 5a e3 92 da a3 20 00 00 00 00 |.R.nH]Z.... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 4f 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |O.+.....3.E...A.| +00000060 1c 01 c6 9e c8 49 43 49 6f 0f 17 f3 ce 87 1a 0f |.....ICIo.......| +00000070 1f 2c 70 18 e4 29 f2 16 a2 e0 02 b7 9d 52 bc b9 |.,p..).......R..| +00000080 d4 b0 1d 19 da 3a 38 f6 93 04 0b ae 5f 60 45 87 |.....:8....._`E.| +00000090 57 80 20 27 c6 9c d4 eb ec c0 85 df f5 aa be de |W. '............| +000000a0 17 03 03 00 17 d4 a9 5f 09 d3 e6 47 ad a7 7b 38 |......._...G..{8| +000000b0 a3 b8 02 37 16 ec 03 56 df d5 8d ec 17 03 03 02 |...7...V........| +000000c0 6d be 1b 2a 60 52 3c 01 2e 6e 7f e3 68 fa de 09 |m..*`R<..n..h...| +000000d0 ed 5e 8f 0f a0 34 d5 0a 8b 2f 30 8f 6c 56 9e fe |.^...4.../0.lV..| +000000e0 e6 9a a9 f1 6e 7c 63 a7 d8 88 e2 95 fa 17 ad 0c |....n|c.........| +000000f0 49 20 93 18 3c ba db fc a1 14 60 2c 77 d4 44 5f |I ..<.....`,w.D_| +00000100 69 9c c7 a3 b9 d0 ee e8 c5 ec 45 d3 79 d0 ee 04 |i.........E.y...| +00000110 fd c3 6d 12 1a f2 6e 62 9f eb ff 32 88 17 4c df |..m...nb...2..L.| +00000120 20 4f cc f9 fd d5 7c 8b 8c c2 da 7d 8a c9 f9 27 | O....|....}...'| +00000130 32 06 75 fe 75 e2 bb bd 6c 31 5d 32 af 36 95 39 |2.u.u...l1]2.6.9| +00000140 92 6c 32 e5 4f b5 f7 07 9f b3 1b b8 10 a8 d9 db |.l2.O...........| +00000150 d3 b0 40 2f 1e e6 54 f5 35 73 7d 22 b3 6b b8 3c |..@/..T.5s}".k.<| +00000160 83 82 8a 75 f4 ec 18 94 57 0c de 98 41 73 61 63 |...u....W...Asac| +00000170 5b 95 3e 4e d4 02 c3 b7 f9 4c 6f 01 c9 52 3c b9 |[.>N.....Lo..R<.| +00000180 ad 61 83 2c 89 6d 63 40 fd d4 67 83 36 8b 9a 1c |.a.,.mc@..g.6...| +00000190 ca 93 16 d8 e3 91 08 d1 3f ba af cb d9 69 09 10 |........?....i..| +000001a0 07 a7 54 9c ee a2 7d 97 ce b6 1f 31 9b 85 b0 82 |..T...}....1....| +000001b0 fc 22 87 70 93 59 9c c9 e3 07 9b d0 c0 a4 1d d4 |.".p.Y..........| +000001c0 2e 36 c0 72 b6 d5 2a f5 b3 fa ab fb 1a 90 05 51 |.6.r..*........Q| +000001d0 b7 19 15 af d9 b2 5f 32 ef e6 5a 2d 4a 2c 7f a9 |......_2..Z-J,..| +000001e0 43 cf b8 ac e4 8a f0 bf 68 90 b9 7c 1c 7e fa f0 |C.......h..|.~..| +000001f0 bc e3 a9 4f a7 2d 3a f3 12 eb b1 93 b4 b9 1b d7 |...O.-:.........| +00000200 81 31 db 58 c4 8e 9f 46 44 39 74 a1 a8 b0 78 0c |.1.X...FD9t...x.| +00000210 b9 23 6d 90 bb a8 b0 7c e2 a3 a3 c4 e6 83 32 5d |.#m....|......2]| +00000220 ea 5a a4 3d 94 ca 51 3c 71 28 cf 43 27 9f 66 9b |.Z.=..Q.[...o| +00000240 8a 11 df 2f be a7 1d 0d 9f a8 04 41 3d 5e 1b f6 |.../.......A=^..| +00000250 b0 10 9b 6a 49 da 6c f9 6c 6e 2e 6c 9b cf f1 fe |...jI.l.ln.l....| +00000260 49 92 2b 16 3f 63 ef 87 71 9c da 0d 49 63 2a 4c |I.+.?c..q...Ic*L| +00000270 b5 82 c8 b0 75 5b 7b 89 39 cd 9a da dc 42 d1 1f |....u[{.9....B..| +00000280 92 61 e1 71 b9 b5 d2 40 3c 7a 4a 8d 91 1f e6 9d |.a.q...@.><.1z..sg.V.8.| +000002d0 bc 39 1f 11 74 ad 69 c6 d2 40 0f 65 d8 ee aa 87 |.9..t.i..@.e....| +000002e0 b3 4c 6c 1a 1d 62 4a 7a d9 15 05 54 0d 8a 22 68 |.Ll..bJz...T.."h| +000002f0 8e 41 22 b0 ee 41 b3 94 5d 1a 62 d8 bb ac f2 87 |.A"..A..].b.....| +00000300 ad 91 19 e7 e1 bc 29 3b 96 8c d1 76 99 e5 82 48 |......);...v...H| +00000310 0b 87 6a 93 3b 2c b7 c1 73 07 53 7c 1f 9f 48 dd |..j.;,..s.S|..H.| +00000320 71 da 55 e1 4a a3 86 d2 ff 23 b2 1d ea b0 17 03 |q.U.J....#......| +00000330 03 00 99 75 af 84 36 54 8e 17 09 c7 2e 72 de 7d |...u..6T.....r.}| +00000340 29 5c 94 a9 e3 d3 d0 9b 3e a0 84 e6 cf b4 48 d8 |)\......>.....H.| +00000350 dd 7c 8a 82 96 15 aa cb 95 38 88 9e 48 c4 bf 75 |.|.......8..H..u| +00000360 9c f4 07 ed 5d 4d 36 8b 58 7f 9c 32 0b f9 d2 44 |....]M6.X..2...D| +00000370 3d d6 ab 3b 3d 38 1f 8d 7e e8 b6 26 57 c9 c6 98 |=..;=8..~..&W...| +00000380 49 4f 1e ad 5d fa 8b ca bc ce 99 f2 d9 5b 14 54 |IO..]........[.T| +00000390 56 0c 59 c8 22 9f 77 f1 db 92 43 c3 dd a5 29 ec |V.Y.".w...C...).| +000003a0 0d 79 0d b3 04 3f 4b 6b d6 a8 da 99 64 94 78 a5 |.y...?Kk....d.x.| +000003b0 e9 cd 7e f8 0c fb 72 d6 03 89 dd 00 13 f3 14 18 |..~...r.........| +000003c0 ba 59 3c 04 7f 6a b5 62 37 56 2e 2d 17 03 03 00 |.Y<..j.b7V.-....| +000003d0 35 af eb 05 4e ec ee 4b d6 6b 03 35 d8 ba a3 cf |5...N..K.k.5....| +000003e0 50 c6 80 07 90 92 1c ed 1f d2 d5 12 e3 7f 74 1a |P.............t.| +000003f0 2c 3b 4b 6c f4 58 af 9a 1a cd 90 f4 d8 78 97 09 |,;Kl.X.......x..| +00000400 2f f6 35 c1 29 b8 |/.5.).| +>>> Flow 5 (client to server) +00000000 17 03 03 00 35 8d 07 5a 33 f5 d1 e7 6d 71 48 45 |....5..Z3...mqHE| +00000010 3e 2a c0 7e 66 03 77 b5 69 b1 e5 13 04 0e 0d ea |>*.~f.w.i.......| +00000020 6f 80 46 a1 9a 54 09 6f a7 be b7 a3 a1 0c d4 ba |o.F..T.o........| +00000030 0e 7d 00 8f 1b 01 0b d4 6b 4c 17 03 03 00 17 b9 |.}......kL......| +00000040 fd 5a 5c a1 c2 33 71 63 99 25 bd 03 a3 24 a7 b6 |.Z\..3qc.%...$..| +00000050 e7 42 04 6a 81 c5 17 03 03 00 13 b6 4a f1 0a 26 |.B.j........J..&| +00000060 95 e8 fb 4b d1 db 24 95 8f 65 1f 3c 5d b9 |...K..$..e.<].| diff --git a/src/crypto/tls/testdata/Client-TLSv13-KeyUpdate b/src/crypto/tls/testdata/Client-TLSv13-KeyUpdate new file mode 100644 index 0000000..ea10f66 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-KeyUpdate @@ -0,0 +1,102 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 fa 01 00 00 f6 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| +00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| +000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| +000000b0 06 04 01 05 01 06 01 05 03 06 03 02 01 02 03 ff |................| +000000c0 01 00 01 00 00 12 00 00 00 2b 00 09 08 03 04 03 |.........+......| +000000d0 03 03 02 03 01 00 33 00 26 00 24 00 1d 00 20 2f |......3.&.$... /| +000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 86 ed 46 3d 38 |....z...v....F=8| +00000010 c5 47 10 b5 4e ac e5 b7 d7 ba cc 23 db f5 0a f4 |.G..N......#....| +00000020 5e d3 62 af 47 8a 23 34 59 5c db 20 00 00 00 00 |^.b.G.#4Y\. ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 e3 |..+.....3.$... .| +00000060 ff 35 33 31 c9 d8 5c 68 2a e5 73 98 4d 11 5b d7 |.531..\h*.s.M.[.| +00000070 06 18 a9 dd 0e 4a 21 92 5b 15 8f bb 91 a9 6c 14 |.....J!.[.....l.| +00000080 03 03 00 01 01 17 03 03 00 17 ea ac f8 a0 41 47 |..............AG| +00000090 af 01 fb 51 2e ec 3b 79 f1 8a 54 2b 93 45 33 c3 |...Q..;y..T+.E3.| +000000a0 79 17 03 03 02 6d 0e c9 a4 55 8e 8c 09 55 cd a6 |y....m...U...U..| +000000b0 d4 dc 1e 5a de ee 56 c8 c2 ac 12 77 77 76 82 fc |...Z..V....wwv..| +000000c0 a6 44 cb c8 c3 16 c4 5e bc 3f f3 3b 6c 33 f3 35 |.D.....^.?.;l3.5| +000000d0 ed bd 8e 37 1a 25 de 7e b3 88 71 ce f9 e5 9b a6 |...7.%.~..q.....| +000000e0 99 11 0f 71 6b 36 11 04 66 a2 5f 74 1c c6 6a 99 |...qk6..f._t..j.| +000000f0 49 84 d1 36 96 df 6d 2c c5 a3 cf 5a c9 37 22 8a |I..6..m,...Z.7".| +00000100 72 e4 d4 25 ed 4a b1 c4 85 5a 9a f7 de 0b dd 41 |r..%.J...Z.....A| +00000110 7d 14 63 35 2e 1c 77 6c 9e 6f 41 d1 cb 29 ca 6d |}.c5..wl.oA..).m| +00000120 88 1c 35 53 1b 14 24 79 84 ec 85 0d de e3 0f 2c |..5S..$y.......,| +00000130 23 ae 41 72 85 fb 43 36 82 ba 8f 78 79 a2 c3 95 |#.Ar..C6...xy...| +00000140 72 19 ea 1d 2f 29 0e d5 11 85 e4 cc 8c a5 f4 8e |r.../)..........| +00000150 39 ba 88 8f e1 5a 54 7c 53 8b a3 1a 44 9c ae 5b |9....ZT|S...D..[| +00000160 1f 0e ea 06 f1 8e 5f 22 d1 ef ee e1 4c b6 1a 26 |......_"....L..&| +00000170 db 53 96 e6 bc 0b 2f ee b7 fa 47 af 1e 9c f6 7b |.S..../...G....{| +00000180 81 97 0f c3 08 9b 2c a3 de bd f7 8a 1e 13 ad de |......,.........| +00000190 a5 fc 5f c7 7a 53 72 e5 17 dc 0a eb 90 91 29 2e |.._.zSr.......).| +000001a0 7a a5 09 fd be 31 ff 81 ec a3 fc 91 41 4f cb c7 |z....1......AO..| +000001b0 27 c3 39 8f cd 77 62 72 9a e9 e9 16 da 90 b6 6b |'.9..wbr.......k| +000001c0 05 70 c8 aa f5 cd 88 13 4d ff a5 a9 0f e7 d2 d3 |.p......M.......| +000001d0 97 2b eb e1 d7 fe 74 da fb 1e af 94 e6 52 18 48 |.+....t......R.H| +000001e0 5b e8 c3 10 9d 76 de 17 86 67 83 4a e9 fa 30 e8 |[....v...g.J..0.| +000001f0 46 95 f5 81 b1 a5 76 38 57 37 3a 8d df ad e7 30 |F.....v8W7:....0| +00000200 41 b2 94 31 da 0d d6 5c df 76 01 cd 4d c2 1b fe |A..1...\.v..M...| +00000210 bc 69 41 ac dd d7 dd 0a 7c 5b 31 5c c8 1e b3 14 |.iA.....|[1\....| +00000220 39 20 51 26 6d e5 55 27 a4 9a bb fc 3d 4b 6a b0 |9 Q&m.U'....=Kj.| +00000230 54 92 ee 33 1b 9b d5 41 fd ef 21 c6 f0 f8 90 a0 |T..3...A..!.....| +00000240 c4 f5 86 d4 d9 c7 89 6f 67 23 37 31 44 2f 8f 55 |.......og#71D/.U| +00000250 0a aa e1 9a ec 32 26 e2 ce 96 90 c6 f5 cc 95 79 |.....2&........y| +00000260 da 0c b4 c1 62 d3 0a 8d 7b 83 33 8e af ff 57 c0 |....b...{.3...W.| +00000270 5b ca 0f b5 64 10 81 43 12 86 67 cf b2 0a 53 f2 |[...d..C..g...S.| +00000280 04 46 4f 99 ee e2 cd ce 3e 82 1f 34 43 26 f9 4c |.FO.....>..4C&.L| +00000290 57 b0 10 c0 37 40 9c 4f fb 14 fa 4e 1e 4b 40 da |W...7@.O...N.K@.| +000002a0 cc c3 d0 d7 ee 63 18 2e 97 06 a6 49 69 07 7a 3e |.....c.....Ii.z>| +000002b0 da 47 68 70 b0 10 bf 8d 18 d2 14 c0 18 18 b2 61 |.Ghp...........a| +000002c0 45 54 e8 20 34 f8 a3 74 5a 8d aa c2 63 af e8 ff |ET. 4..tZ...c...| +000002d0 f9 1b 33 d6 34 c2 f2 c2 3d d8 0e 32 7a 10 cc 21 |..3.4...=..2z..!| +000002e0 02 22 a6 aa 7d 15 c3 7b 3f a2 50 5a 4e 53 ec f5 |."..}..{?.PZNS..| +000002f0 11 dd 48 6e 7e e9 c5 94 2c c4 9a 6e 10 a6 c6 a5 |..Hn~...,..n....| +00000300 9d e1 c5 43 e6 69 a1 91 65 50 eb e6 76 db f0 09 |...C.i..eP..v...| +00000310 14 45 ef 17 03 03 00 99 e4 82 99 6b d8 57 ca 1b |.E.........k.W..| +00000320 78 98 88 ad c7 04 b7 d2 b2 d5 00 3b a9 bf 86 66 |x..........;...f| +00000330 a7 30 72 95 29 2a 27 9f 9a 3d bd 0b e6 a0 04 22 |.0r.)*'..=....."| +00000340 56 3d d8 08 84 a7 e7 c5 67 74 34 7d 57 1f c9 df |V=......gt4}W...| +00000350 71 0c 97 55 5a d9 8d 99 df 49 b5 a9 57 6d b0 c7 |q..UZ....I..Wm..| +00000360 2d 4b 70 9d e7 e3 70 31 f0 2f 32 15 7b 67 b4 4c |-Kp...p1./2.{g.L| +00000370 f0 f0 4a 16 a5 37 b2 ae 9b 2a 72 7c 2e d8 22 a1 |..J..7...*r|..".| +00000380 2b 91 f2 14 fc f9 27 fd ca ad 27 dd 15 11 df b1 |+.....'...'.....| +00000390 cc 4c 3a 45 3f b6 7c 53 c5 d0 82 49 1a f2 28 63 |.L:E?.|S...I..(c| +000003a0 a2 be 6f 2f db d8 d3 76 0a 12 fa 87 14 00 11 e7 |..o/...v........| +000003b0 1f 17 03 03 00 35 0c af 49 a1 ba 14 d4 e5 5c cf |.....5..I.....\.| +000003c0 c8 f7 fb 93 e3 d5 45 ac 59 ed 56 3c 1c e6 53 6a |......E.Y.V<..Sj| +000003d0 77 62 a3 1a 8c 55 14 b0 d8 6f dd 1c fb a4 6f 25 |wb...U...o....o%| +000003e0 18 28 ab 9e a5 ad 6d 97 63 f4 9c |.(....m.c..| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 12 2a a7 31 42 |..........5.*.1B| +00000010 e9 65 d6 88 9c 49 85 53 16 6c 85 bc d1 70 65 3a |.e...I.S.l...pe:| +00000020 aa cd d3 12 ce 69 e3 3a 63 7a 8d ed 54 df 9c 97 |.....i.:cz..T...| +00000030 4e ef 7c 20 ce 41 ac 33 a9 3b fc 5e 35 34 65 00 |N.| .A.3.;.^54e.| +00000040 17 03 03 00 17 11 5f 88 3b 45 0e 4e 8a 26 43 a3 |......_.;E.N.&C.| +00000050 9e 77 10 76 8c e1 ed d3 19 f4 27 5f |.w.v......'_| +>>> Flow 4 (server to client) +00000000 17 03 03 00 16 7d 92 67 60 95 ba fa a0 5f 03 e9 |.....}.g`...._..| +00000010 2b e6 53 ed fb 6b 4f b9 e9 09 10 |+.S..kO....| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 06 17 fb 4b 33 c7 06 d5 a9 40 e8 |........K3....@.| +00000010 c7 09 65 b2 5c 2d 45 2f bf 45 a8 |..e.\-E/.E.| +>>> Flow 6 (server to client) +00000000 17 03 03 00 1a 04 5e c0 bb ad 6c 2f 65 61 5c 39 |......^...l/ea\9| +00000010 a9 e2 c4 9e 0e 4c 68 d2 a9 97 8a bf 95 39 3f |.....Lh......9?| +>>> Flow 7 (client to server) +00000000 17 03 03 00 1d 1f 74 d0 fb ed fa 59 81 21 7e f0 |......t....Y.!~.| +00000010 41 c8 6e 6b 9f b6 1a 86 ad 2e ac 9e 3d 3b 66 c9 |A.nk........=;f.| +00000020 4a 87 17 03 03 00 13 7b 76 c4 85 c1 41 47 6d 35 |J......{v...AGm5| +00000030 98 86 02 d5 3b e4 6b 4c 3e 7a |....;.kL>z| diff --git a/src/crypto/tls/testdata/Client-TLSv13-P256-ECDHE b/src/crypto/tls/testdata/Client-TLSv13-P256-ECDHE new file mode 100644 index 0000000..db87bef --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-P256-ECDHE @@ -0,0 +1,94 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 15 01 00 01 11 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 96 00 05 00 05 01 00 00 00 00 00 0a 00 |................| +00000090 04 00 02 00 17 00 0b 00 02 01 00 00 0d 00 1a 00 |................| +000000a0 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 |................| +000000b0 01 05 03 06 03 02 01 02 03 ff 01 00 01 00 00 12 |................| +000000c0 00 00 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 |...+............| +000000d0 33 00 47 00 45 00 17 00 41 04 1e 18 37 ef 0d 19 |3.G.E...A...7...| +000000e0 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..| +000000f0 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..| +00000100 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.| +00000110 b5 68 1a 41 03 56 6b dc 5a 89 |.h.A.Vk.Z.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 9b 02 00 00 97 03 03 bb 03 f1 4e 88 |..............N.| +00000010 23 9e 85 ee 32 13 db 0d 69 11 48 47 c6 c9 e5 b2 |#...2...i.HG....| +00000020 25 9d 0c 27 87 05 3f 58 42 60 2d 20 00 00 00 00 |%..'..?XB`- ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 4f 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |O.+.....3.E...A.| +00000060 85 3c 83 1b e5 02 e9 0d 89 cc c0 f7 af 1e ba af |.<..............| +00000070 de ad cb 8f 4d 58 04 40 c2 60 e9 41 8b 94 26 76 |....MX.@.`.A..&v| +00000080 73 64 c3 27 e3 51 9d 5f 21 97 59 a3 02 cc 20 61 |sd.'.Q._!.Y... a| +00000090 b7 ef cb bb d9 31 b6 b7 b1 77 ea 8d 69 13 13 48 |.....1...w..i..H| +000000a0 14 03 03 00 01 01 17 03 03 00 17 ab ac 2e 62 de |..............b.| +000000b0 b6 f4 c7 35 cf b4 75 fc a4 a5 2c 40 68 f5 48 80 |...5..u...,@h.H.| +000000c0 d2 8b 17 03 03 02 6d a9 36 b5 10 78 1f af 79 65 |......m.6..x..ye| +000000d0 dd ee 36 08 b9 96 e2 bf 09 53 c7 ee 12 19 1b de |..6......S......| +000000e0 96 25 cb a7 55 71 28 22 16 3f 4b 3e 15 a2 2e 57 |.%..Uq(".?K>...W| +000000f0 99 85 28 b2 01 16 3a 75 ff 5e 21 39 6c be fc bd |..(...:u.^!9l...| +00000100 24 33 ec c7 50 83 49 91 8a ed 43 38 b5 48 cd 92 |$3..P.I...C8.H..| +00000110 dd 9a f1 b7 90 61 3b 8f ff b9 cf 97 3d 8e 23 8e |.....a;.....=.#.| +00000120 d1 78 52 b4 ba a1 75 97 32 52 e3 1f c8 43 ca b7 |.xR...u.2R...C..| +00000130 89 46 e6 30 c2 c5 32 b3 5f a8 ea ea e2 31 d2 41 |.F.0..2._....1.A| +00000140 23 5e 64 a2 b9 23 27 73 b2 df 77 cd 04 8b dd 37 |#^d..#'s..w....7| +00000150 a5 77 df 0e 4f 9d 01 22 7b be 7a 0c 18 5c 8b 62 |.w..O.."{.z..\.b| +00000160 7c 6b 7e a7 54 8c 69 97 50 d7 cf a0 a4 cb 3a 3b ||k~.T.i.P.....:;| +00000170 76 7b 0a de 80 d1 40 c3 05 5e b3 4e 71 cd 03 82 |v{....@..^.Nq...| +00000180 d5 95 d0 38 ab 65 83 24 66 d2 31 2d 9e 58 16 87 |...8.e.$f.1-.X..| +00000190 b8 ab 4c 4e 75 40 7e 3d 33 2f f4 ed 0b a8 11 1c |..LNu@~=3/......| +000001a0 7a a4 b0 e3 6a 73 d0 6e e6 82 39 c1 cf 57 a4 9a |z...js.n..9..W..| +000001b0 8b fc bc 8e e8 6a c3 e1 b0 64 18 55 6d 19 30 25 |.....j...d.Um.0%| +000001c0 34 f8 b1 ef cf 3c 04 08 69 10 ad 08 67 5b 8d 64 |4....<..i...g[.d| +000001d0 eb 83 72 39 2e 56 e4 d2 e9 f2 da 40 3e 85 29 ab |..r9.V.....@>.).| +000001e0 5b 83 e5 b0 d2 9b eb c3 99 6e 2a f3 78 95 d4 7a |[........n*.x..z| +000001f0 7f bf 9c 16 55 77 43 4d 67 f7 4a 6f 40 27 a2 82 |....UwCMg.Jo@'..| +00000200 b9 86 05 5d 90 e2 52 a2 d4 7c 7b 3e da 30 c1 aa |...]..R..|{>.0..| +00000210 30 2e 9a 34 c5 59 dd db e9 25 67 da 22 47 f2 be |0..4.Y...%g."G..| +00000220 cc c8 5a 4e da cf ad 86 8d bd b0 68 26 69 ea 3a |..ZN.......h&i.:| +00000230 1c 1e 29 ae e1 09 63 88 f0 81 31 f9 70 a7 92 27 |..)...c...1.p..'| +00000240 32 9e 3b 6f 09 5e 42 20 53 88 bf 09 8b a8 17 5c |2.;o.^B S......\| +00000250 24 7c 18 1f 9c 99 9b db 6d 11 26 8e 92 2c a1 b4 |$|......m.&..,..| +00000260 5c 9f d9 0a a8 af 25 f7 84 f5 65 d1 b1 6c d8 aa |\.....%...e..l..| +00000270 49 c7 a6 13 47 2e 55 f4 2e de 3d 43 c1 15 8d 60 |I...G.U...=C...`| +00000280 c1 27 59 7e 7b 14 ee 54 09 fc 99 79 c9 bf fb 45 |.'Y~{..T...y...E| +00000290 2d 32 ed 1a 2c 84 bc f4 a2 b5 5f 4e cf 60 29 91 |-2..,....._N.`).| +000002a0 90 b6 ab 06 8f 2d 43 a5 a5 54 0d 67 52 c2 1c fb |.....-C..T.gR...| +000002b0 f3 41 b7 67 b4 50 05 86 19 75 93 8b 6c c3 bf 08 |.A.g.P...u..l...| +000002c0 64 f2 df ff 37 6d 2f 1e 3a 28 f4 ba 27 8d 61 d5 |d...7m/.:(..'.a.| +000002d0 79 70 19 82 99 7a e5 68 f3 c1 23 da 5d e1 98 b2 |yp...z.h..#.]...| +000002e0 69 ca 42 83 61 29 3f d9 20 51 f2 a9 ea 1c 0b 5a |i.B.a)?. Q.....Z| +000002f0 20 b0 af 70 cc c5 ad 72 6b 09 85 56 8a 26 86 cf | ..p...rk..V.&..| +00000300 4e 9a 56 97 5d 63 8d 1d 46 04 48 16 c9 1e 91 47 |N.V.]c..F.H....G| +00000310 74 53 28 51 7e 3c 84 a1 50 d6 f3 ac 31 ce 04 18 |tS(Q~<..P...1...| +00000320 81 38 0d c5 3d f5 d5 04 2f f0 96 9b 73 49 4c d6 |.8..=.../...sIL.| +00000330 89 d9 b9 be 17 03 03 00 99 3a 37 ed 2d 98 80 f9 |.........:7.-...| +00000340 d0 04 14 12 8c 63 45 cc 8d cb 29 5f 0e f0 86 ef |.....cE...)_....| +00000350 8d 6c d6 0f ef 66 99 91 e8 8c d7 7b 21 07 7e 96 |.l...f.....{!.~.| +00000360 84 f8 f9 5b 1b 39 8b 4f 16 ec 5c 69 7b 18 09 5d |...[.9.O..\i{..]| +00000370 95 f1 f3 73 4b 8f 84 66 ee 61 85 dd fe ea 36 df |...sK..f.a....6.| +00000380 e5 2a 71 ec 2d 7e 47 1c b7 79 2d 87 f8 dc 44 27 |.*q.-~G..y-...D'| +00000390 8a f1 13 6e df ca 59 79 9b 18 01 7e 31 bd 44 f7 |...n..Yy...~1.D.| +000003a0 8d ad 1c 97 e7 e1 b9 a6 17 d1 25 d1 b8 0d 04 bb |..........%.....| +000003b0 21 a4 08 db a2 08 87 5c 04 9a 11 fa c6 24 db 20 |!......\.....$. | +000003c0 42 79 9c 97 dd 6c d2 e7 24 b4 79 47 be f3 43 87 |By...l..$.yG..C.| +000003d0 0f 95 17 03 03 00 35 9e 7d 12 0e d6 0a e6 af a3 |......5.}.......| +000003e0 83 dd eb 08 73 2d 43 7e 81 85 51 4c d1 ad d0 77 |....s-C~..QL...w| +000003f0 8d 28 62 44 41 9c b0 e9 93 d7 3d 07 e4 e1 6e 4c |.(bDA.....=...nL| +00000400 a8 5b 4a 3f 58 3f 97 07 73 d7 5a 62 |.[J?X?..s.Zb| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 df 31 1a 84 e2 |..........5.1...| +00000010 93 54 01 f2 d1 e8 32 6c 32 91 e5 64 86 68 ad 5f |.T....2l2..d.h._| +00000020 aa 24 54 86 b2 39 92 24 06 65 5c 06 67 43 7d 09 |.$T..9.$.e\.gC}.| +00000030 79 78 c6 f3 cf 6c a9 ec 38 e3 ec 81 c4 9b c5 33 |yx...l..8......3| +00000040 17 03 03 00 17 25 ed 98 67 8f ad e8 60 ce 5b ad |.....%..g...`.[.| +00000050 ab 3e 67 64 e3 8d bf 98 96 a2 3d 99 17 03 03 00 |.>gd......=.....| +00000060 13 9d 28 f2 24 fe d6 11 b0 64 d6 8a 8d c1 81 e0 |..(.$....d......| +00000070 17 d5 a0 f3 |....| diff --git a/src/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE b/src/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE new file mode 100644 index 0000000..4a43382 --- /dev/null +++ b/src/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE @@ -0,0 +1,90 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 f4 01 00 00 f0 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| +00000080 01 00 00 75 00 05 00 05 01 00 00 00 00 00 0a 00 |...u............| +00000090 04 00 02 00 1d 00 0b 00 02 01 00 00 0d 00 1a 00 |................| +000000a0 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 |................| +000000b0 01 05 03 06 03 02 01 02 03 ff 01 00 01 00 00 12 |................| +000000c0 00 00 00 2b 00 09 08 03 04 03 03 03 02 03 01 00 |...+............| +000000d0 33 00 26 00 24 00 1d 00 20 2f e5 7d a3 47 cd 62 |3.&.$... /.}.G.b| +000000e0 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| +000000f0 c2 ed 90 99 5f 58 cb 3b 74 |...._X.;t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 eb 1b 4e e5 65 |....z...v....N.e| +00000010 54 ab 07 68 1c d9 32 0f 0e c2 ae a3 2a 89 37 50 |T..h..2.....*.7P| +00000020 23 51 61 7d 68 60 34 0d 40 2f b8 20 00 00 00 00 |#Qa}h`4.@/. ....| +00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 17 |..+.....3.$... .| +00000060 7d df 14 8a ad 43 51 c3 c2 08 3a ea f7 e3 96 6a |}....CQ...:....j| +00000070 b7 8b 61 66 d9 82 c5 7b b9 77 bc 62 6a 19 04 14 |..af...{.w.bj...| +00000080 03 03 00 01 01 17 03 03 00 17 4e 7b b6 d1 b1 19 |..........N{....| +00000090 0d 0c d0 d3 5a 66 44 5c 81 49 74 f3 71 3b 97 5e |....ZfD\.It.q;.^| +000000a0 ee 17 03 03 02 6d 00 17 b1 4d b9 f5 fc ea 48 72 |.....m...M....Hr| +000000b0 aa a5 1c 8b fe 97 08 54 ab 2d 0a 0e f7 51 41 bf |.......T.-...QA.| +000000c0 7b 14 ba b7 d9 0a 30 44 db b9 06 e7 6b a9 0a 94 |{.....0D....k...| +000000d0 49 a2 29 50 f2 7f 7e 68 91 41 ad a9 cb ee e2 bd |I.)P..~h.A......| +000000e0 03 fd 95 79 ea c3 77 ee 88 3b 7a 81 15 9f 17 96 |...y..w..;z.....| +000000f0 b2 db b9 f3 26 dd 75 69 ef 12 c0 63 b0 04 63 ae |....&.ui...c..c.| +00000100 aa b3 67 f8 7f a5 17 cf 56 5f ee 34 2d d7 83 23 |..g.....V_.4-..#| +00000110 84 00 4b 94 1a 76 2a 01 ce 49 0a 57 7d c8 65 7a |..K..v*..I.W}.ez| +00000120 d7 16 34 1c a8 37 fd 71 d4 79 08 b1 44 9f 9e a7 |..4..7.q.y..D...| +00000130 78 ab 9d 0d c4 80 0e 81 35 75 23 59 89 1b 2c d3 |x.......5u#Y..,.| +00000140 bc c9 86 b9 7b 22 19 30 dd cc 68 93 ab d2 98 dd |....{".0..h.....| +00000150 c2 9f 20 af c9 1a 87 b3 28 73 84 83 ca 98 1d 60 |.. .....(s.....`| +00000160 df 12 19 70 80 f2 ff 20 64 b5 8c ef e2 e8 6a 5a |...p... d.....jZ| +00000170 df 8e ba 95 d8 2c c4 b6 4f a1 33 8c 8d a3 fc d3 |.....,..O.3.....| +00000180 c4 4b ba b2 6d 3a f7 da 38 23 5f 03 a7 92 13 76 |.K..m:..8#_....v| +00000190 12 73 26 17 30 e0 21 f1 16 8f a1 e5 6d f0 21 a8 |.s&.0.!.....m.!.| +000001a0 c6 25 64 86 95 5e 6f 4d 21 f0 f3 a3 27 23 2b 4b |.%d..^oM!...'#+K| +000001b0 90 03 ba 6c ce 9c 20 ed 69 15 76 cb 39 bc fd 44 |...l.. .i.v.9..D| +000001c0 10 b4 72 d5 44 9d f7 eb a4 b0 d5 07 20 a1 6b 71 |..r.D....... .kq| +000001d0 16 e4 f7 8f a0 d8 fa 86 db e6 ef eb 63 41 a0 17 |............cA..| +000001e0 83 71 0d 1c 4b ec 58 c3 90 9c ea 34 79 a7 91 43 |.q..K.X....4y..C| +000001f0 ad 3d ff 28 c8 b4 3e 7a b6 83 53 f4 99 0b 86 bc |.=.(..>z..S.....| +00000200 f2 cf ae 1d a7 5c 7f 57 d9 85 95 25 33 bb 4d 79 |.....\.W...%3.My| +00000210 25 2e 54 6d 5d 14 32 68 7d 6e 45 bd b1 e1 24 30 |%.Tm].2h}nE...$0| +00000220 c2 1c 45 b9 a2 42 ae b5 c6 6a 56 f9 8a 12 51 f9 |..E..B...jV...Q.| +00000230 61 a2 9d 56 98 09 8d ea 70 17 48 d8 23 48 ca 18 |a..V....p.H.#H..| +00000240 43 1e a2 bc 88 69 3d 45 95 89 cc f0 74 8d 88 36 |C....i=E....t..6| +00000250 5e a8 1b be 88 41 35 8d de a9 20 23 f3 5e ab c9 |^....A5... #.^..| +00000260 61 22 2e 86 54 2f c4 4a 60 04 c2 e3 b8 cf 1a 41 |a"..T/.J`......A| +00000270 a6 31 ab 7a b5 07 dc 54 82 89 b1 1f 9f 62 98 bc |.1.z...T.....b..| +00000280 bd 39 be 23 ed d5 bc 0d 8e a6 69 14 26 39 fe ed |.9.#......i.&9..| +00000290 98 c8 48 36 6c 8e 9f 93 57 7a ba 33 03 35 c6 de |..H6l...Wz.3.5..| +000002a0 55 03 63 e8 a4 53 08 0a b0 a7 3e a3 cb f2 df 3d |U.c..S....>....=| +000002b0 cd 59 df ee f6 45 2d 77 39 32 4a 1f 08 21 e7 db |.Y...E-w92J..!..| +000002c0 52 2a 06 86 e6 00 98 ca 9f a3 ad 0f 7f d3 25 6d |R*............%m| +000002d0 56 58 21 e2 39 59 56 15 74 4d 18 37 f5 40 29 db |VX!.9YV.tM.7.@).| +000002e0 de be 49 77 e0 2c 5c 6b ee b1 bd 4a ea 2a 07 94 |..Iw.,\k...J.*..| +000002f0 0f 21 7c bb 1f bd 3e ad 9e b6 95 7d 16 e8 f0 4e |.!|...>....}...N| +00000300 de e2 ca 9c 34 9f b8 e5 57 d5 b7 b5 8d 60 dd c2 |....4...W....`..| +00000310 ce 47 2c 17 03 03 00 99 37 37 20 49 98 44 f6 b4 |.G,.....77 I.D..| +00000320 58 54 ff 5e b0 05 22 8e c6 68 9a ae 49 51 e9 f1 |XT.^.."..h..IQ..| +00000330 71 75 cf 1a 79 da 33 f1 5f 7e a1 02 81 05 12 8b |qu..y.3._~......| +00000340 a3 a8 ad 87 ee f0 87 da f1 16 80 9d 2e fa 5a 22 |..............Z"| +00000350 a5 f5 b9 14 f5 8f 9b 35 87 ba 1a f7 c4 17 c8 f6 |.......5........| +00000360 a1 1e 28 cd fe 03 90 9f f0 81 d3 80 bb 4c 1a b1 |..(..........L..| +00000370 c6 11 de 19 a1 5a 3c 73 77 f0 70 b8 d1 38 16 f3 |.....Z>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 e5 27 80 72 fd |..........5.'.r.| +00000010 6c 0d b5 a7 14 23 08 0b f5 54 70 8c 29 61 d0 2a |l....#...Tp.)a.*| +00000020 81 2d 05 83 2a 21 1e 16 94 5b 65 0d 6a ca b6 81 |.-..*!...[e.j...| +00000030 d9 9d 3c 5c 9c fe 2b 01 a8 3b 23 fb 9e eb 2c 56 |..<\..+..;#...,V| +00000040 17 03 03 00 17 79 fd 43 29 72 96 e0 ad fd 7e 60 |.....y.C)r....~`| +00000050 94 51 8d 8a 6e 6a 5d 6c f3 0d 4b 74 17 03 03 00 |.Q..nj]l..Kt....| +00000060 13 a4 7c e1 31 71 61 82 e7 7d 28 0f 63 d7 ae 76 |..|.1qa..}(.c..v| +00000070 9c 71 37 cd |.q7.| diff --git a/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES new file mode 100644 index 0000000..1132b39 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES @@ -0,0 +1,80 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 63 01 00 00 5f 03 01 38 de f5 d6 ae |....c..._..8....| +00000010 46 71 e8 02 f2 45 88 b8 64 fb 6e 68 67 d1 7f e8 |Fq...E..d.nhg...| +00000020 49 71 1e a9 ec 8e 54 06 bb 2b 16 00 00 04 c0 0a |Iq....T..+......| +00000030 00 ff 01 00 00 32 00 00 00 0e 00 0c 00 00 09 31 |.....2.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 |........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 37 02 00 00 33 03 01 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 c0 0a 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 01 02 |................| +00000040 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 00 30 |...........0...0| +00000050 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 30 09 |..b.....-G....0.| +00000060 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 09 06 |..*.H.=..0E1.0..| +00000070 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 04 |.U....AU1.0...U.| +00000080 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 |...Some-State1!0| +00000090 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 |...U....Internet| +000000a0 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 | Widgits Pty Ltd| +000000b0 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 33 32 |0...121122150632| +000000c0 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 32 5a |Z..221120150632Z| +000000d0 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 |0E1.0...U....AU1| +000000e0 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 |.0...U....Some-S| +000000f0 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 |tate1!0...U....I| +00000100 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 |nternet Widgits | +00000110 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 2a 86 |Pty Ltd0..0...*.| +00000120 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +00000130 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 16 56 |.........Hs6~..V| +00000140 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 f6 b0 |.".=S.;M!=.ku...| +00000150 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 2f 1c |...&.....r2|.d/.| +00000160 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 e0 28 |...h#.~..%.H:i.(| +00000170 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 d8 81 |m.7...b....pb...| +00000180 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 de 76 |.d1...1...h..#.v| +00000190 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd 9b d8 |d?.\....XX._p...| +000001a0 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a 20 e2 |.........0f[f. .| +000001b0 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d 04 01 |'...;0...*.H.=..| +000001c0 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb e2 45 |....0...B...O..E| +000001d0 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e 1b b6 |.H}.......Gp.^..| +000001e0 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b 7e 92 |/...M.a@......~.| +000001f0 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 ec 47 |~.v..;~.?....Y.G| +00000200 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 4d fc |-|..N....o..B.M.| +00000210 be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 13 83 |.g..-...?..%.3..| +00000220 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd d7 11 |.....7z..z......| +00000230 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d ae cb |i..|V..1x+..x...| +00000240 be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f 2a 16 |..N6$1{j.9....*.| +00000250 03 01 00 b5 0c 00 00 b1 03 00 1d 20 2f e5 7d a3 |........... /.}.| +00000260 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| +00000270 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 00 8b 30 81 |......._X.;t..0.| +00000280 88 02 42 01 ad 26 fd 16 9a 93 5f 87 ce 29 8c d2 |..B..&...._..)..| +00000290 56 a7 d2 59 56 bd d3 1f 90 54 bd af 91 81 25 ff |V..YV....T....%.| +000002a0 66 74 57 16 2f 31 f2 5a 48 97 03 b9 41 4c 8e bb |ftW./1.ZH...AL..| +000002b0 87 31 ed 71 84 37 63 78 9f 0a c7 9d 5e f3 5a 53 |.1.q.7cx....^.ZS| +000002c0 88 89 46 ba a7 02 42 00 92 74 15 1c 0e 1f 2f 95 |..F...B..t..../.| +000002d0 e5 79 d5 e9 90 ce d8 96 0d fd b8 42 55 00 94 08 |.y.........BU...| +000002e0 4e 47 a9 ea bd 67 0b 02 a6 9e 8b d3 09 e5 53 ea |NG...g........S.| +000002f0 03 22 2e 2d 78 2c 69 1d 28 ab 13 3d 0a 46 15 09 |.".-x,i.(..=.F..| +00000300 b6 0b 74 69 2d 5a 96 bf b6 16 03 01 00 04 0e 00 |..ti-Z..........| +00000310 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 01 00 25 10 00 00 21 20 82 c0 dd 83 c2 45 |....%...! .....E| +00000010 a2 bc 3a 2a ec ab 60 8e 02 e0 db 7c 59 83 c1 62 |..:*..`....|Y..b| +00000020 c7 cc 61 1e de dc 40 e4 65 6c 14 03 01 00 01 01 |..a...@.el......| +00000030 16 03 01 00 30 3e 26 56 0b a2 10 47 00 55 27 21 |....0>&V...G.U'!| +00000040 63 33 f2 7d 4b ba 77 5f e7 a7 09 7a 1f 51 85 f2 |c3.}K.w_...z.Q..| +00000050 46 a5 af 80 79 1a c7 72 bb 3d f9 dd 1d 83 05 22 |F...y..r.=....."| +00000060 c9 6c dd 91 d9 |.l...| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 38 fa fd 42 8f |..........08..B.| +00000010 80 5a 7c 33 d4 6c 72 f7 4e 2f 00 ab c2 86 58 9d |.Z|3.lr.N/....X.| +00000020 fc a5 43 fa ea 5b a1 ee a9 df df 9d 90 4c c0 e3 |..C..[.......L..| +00000030 10 09 c4 23 21 f9 e9 69 f5 f8 fa 17 03 01 00 20 |...#!..i....... | +00000040 1e 57 17 e4 96 06 32 d4 00 a3 98 ed bd 1c 61 78 |.W....2.......ax| +00000050 e7 0d 89 ec 84 c3 56 fa 75 73 87 6f 47 35 80 3f |......V.us.oG5.?| +00000060 17 03 01 00 30 4d 51 0a dd 70 6d b0 c2 d1 46 5c |....0MQ..pm...F\| +00000070 b5 03 87 de e6 65 d3 e2 83 e0 33 f8 a2 0a 29 7f |.....e....3...).| +00000080 6c 24 2b 1f 7b 2b 53 19 21 e9 62 6c 31 75 9c be |l$+.{+S.!.bl1u..| +00000090 5b b0 3d 5b 1a 15 03 01 00 20 19 51 64 4b 5a 9b |[.=[..... .QdKZ.| +000000a0 c8 2a 1c e7 9e 29 d9 df ad 1d 08 09 82 a3 b1 1d |.*...)..........| +000000b0 60 99 00 25 30 51 a1 72 b6 27 |`..%0Q.r.'| diff --git a/src/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial b/src/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial new file mode 100644 index 0000000..cb3b8da --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial @@ -0,0 +1,93 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 67 01 00 00 63 03 01 41 69 16 b5 d5 |....g...c..Ai...| +00000010 c2 9d 36 2b 95 8e e5 41 9b 92 82 27 2a cc 4e 6e |..6+...A...'*.Nn| +00000020 5d f1 1b 58 49 3c 95 1d 8b 61 35 00 00 04 c0 14 |]..XI<...a5.....| +00000030 00 ff 01 00 00 36 00 00 00 0e 00 0c 00 00 09 31 |.....6.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 23 00 00 00 16 00 00 00 17 00 00 |.#..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 3b 02 00 00 37 03 01 00 00 00 00 00 |....;...7.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 c0 14 00 00 |...DOWNGRD......| +00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............| +00000040 16 03 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0| +00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............| +00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..| +00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.| +00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....| +00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010| +000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101| +000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U| +000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...| +000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...| +000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......| +000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.| +00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B| +00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[.....y.@.Om..+.| +00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t| +00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l| +00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.| +00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....| +00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.| +00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U| +00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U| +00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.| +000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...| +000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..| +000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...| +000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{| +000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa| +00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*| +00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0| +00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(| +00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C| +00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..| +00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.| +00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.| +00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |.Cw.......@.a.Lr| +00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B| +00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....| +000002a0 01 00 aa 0c 00 00 a6 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G| +000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 00 80 c6 ad e2 |......_X.;t.....| +000002d0 21 0d d7 30 42 da 08 52 d5 46 70 a3 e5 d6 40 ab |!..0B..R.Fp...@.| +000002e0 bf 52 f8 da a5 41 86 1d 48 e6 51 91 52 8d 3c 5d |.R...A..H.Q.R.<]| +000002f0 ca 36 4c 62 d1 6b c8 48 8c 99 50 89 a9 27 4b 21 |.6Lb.k.H..P..'K!| +00000300 c9 9d a6 43 34 d2 47 a7 b3 1a 6d 98 b3 7f 37 94 |...C4.G...m...7.| +00000310 60 ba 88 f1 b7 ed 34 2b 47 f4 80 27 d3 a0 74 6a |`.....4+G..'..tj| +00000320 c6 d6 49 e3 8a e5 5d f1 a7 54 8a b4 84 8d a8 6b |..I...]..T.....k| +00000330 3b 7a 3f eb 81 77 4b bf be 1e ac cd aa f9 4b 79 |;z?..wK.......Ky| +00000340 24 78 6c 67 14 13 ab f8 ad 33 7c 94 38 16 03 01 |$xlg.....3|.8...| +00000350 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 01 00 25 10 00 00 21 20 f5 be 48 cb fb 0d |....%...! ..H...| +00000010 69 27 a8 ab 59 c4 9a ac 92 71 46 d1 17 7e 35 67 |i'..Y....qF..~5g| +00000020 15 b1 ea 9f 53 48 a3 b5 f9 55 14 03 01 00 01 01 |....SH...U......| +00000030 16 03 01 00 30 e1 79 95 7c ab 01 74 35 39 9b ce |....0.y.|..t59..| +00000040 79 5f 15 21 88 fc be fc 46 a9 31 ca 82 07 0c 1f |y_.!....F.1.....| +00000050 d8 2f 93 b5 5d 23 bf f9 10 40 bc b5 22 53 df d6 |./..]#...@.."S..| +00000060 b1 10 b9 16 96 |.....| +>>> Flow 4 (server to client) +00000000 16 03 01 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6d ec a4 83 51 ed 14 ef 68 ca 42 c5 4c d2 34 08 |m...Q...h.B.L.4.| +00000040 0b cc b9 32 8f 21 f7 50 c4 e1 28 9b 7d 5e ed de |...2.!.P..(.}^..| +00000050 0a df 30 0d 16 34 6b 6d 22 3c d3 c8 b2 99 84 8e |..0..4km"<......| +00000060 09 6d 3c 62 d4 0f f6 37 dc 53 ae 72 40 49 38 16 |.m| +00000100 46 a7 41 99 d5 e2 ab 60 b1 eb 8d 68 2f 71 30 70 |F.A....`...h/q0p| +00000110 75 cc b8 50 1a 58 3b 96 d3 5c 99 43 27 4f b1 4a |u..P.X;..\.C'O.J| +00000120 c8 8d 5b ab 49 15 03 01 00 20 34 a6 41 25 fd 23 |..[.I.... 4.A%.#| +00000130 44 6d 60 7f 79 5d 27 23 f7 cb 77 d0 cd 81 c4 67 |Dm`.y]'#..w....g| +00000140 0e 56 92 60 ac a1 32 a5 0d 94 |.V.`..2...| diff --git a/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES b/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES new file mode 100644 index 0000000..502fd28 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES @@ -0,0 +1,76 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 63 01 00 00 5f 03 01 25 03 63 bf 34 |....c..._..%.c.4| +00000010 89 c8 9e f6 e0 46 f8 30 5c e8 62 0a f7 db 68 c9 |.....F.0\.b...h.| +00000020 50 54 0e c2 15 f1 cb 07 66 06 3d 00 00 04 00 0a |PT......f.=.....| +00000030 00 ff 01 00 00 32 00 00 00 0e 00 0c 00 00 09 31 |.....2.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 |........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 37 02 00 00 33 03 01 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 00 0a 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 01 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 01 00 86 10 00 00 82 00 80 0f e9 83 ca 77 |...............w| +00000010 c8 26 16 24 00 b7 09 d2 73 aa c1 d9 77 f3 fc 38 |.&.$....s...w..8| +00000020 1c 2e c0 26 b4 a6 40 e1 1b 93 39 8f a2 1f f2 f9 |...&..@...9.....| +00000030 18 2a 7b 0e cd 9b 9b 9c 49 86 43 3d 48 fd 40 d7 |.*{.....I.C=H.@.| +00000040 af f9 2b 5e c6 cc c6 2d 8d 36 fe b1 75 c1 b5 a0 |..+^...-.6..u...| +00000050 57 97 0f 01 ee b4 6a af 0c fe f0 68 78 04 6a 3e |W.....j....hx.j>| +00000060 83 d0 72 34 80 d8 7d cd 8b 83 06 5b 36 50 10 8e |..r4..}....[6P..| +00000070 b4 27 3d 6a ae b7 7f 8b 2a b1 0b 51 49 05 b5 01 |.'=j....*..QI...| +00000080 3c 27 9a 59 e3 41 18 38 d6 8f 7a 14 03 01 00 01 |<'.Y.A.8..z.....| +00000090 01 16 03 01 00 28 c0 46 65 9f 7f d8 c3 c4 a7 33 |.....(.Fe......3| +000000a0 50 f9 07 41 95 12 a6 f3 ca 53 b9 96 f8 a8 a6 5f |P..A.....S....._| +000000b0 1e c8 20 e5 8b 87 4e 12 73 13 e0 e4 c6 89 |.. ...N.s.....| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 28 e2 47 2b 57 fe |..........(.G+W.| +00000010 74 71 95 6a ee 68 2b f3 48 40 13 52 35 46 58 d4 |tq.j.h+.H@.R5FX.| +00000020 ee aa 4c a8 53 0f 3a 19 ed 18 37 2d e4 b9 1e e6 |..L.S.:...7-....| +00000030 28 42 a1 17 03 01 00 18 d8 7c 20 f2 03 6d a9 ed |(B.......| ..m..| +00000040 c9 73 50 d7 56 4f 0b d8 4b 44 f6 80 e4 c1 a9 f5 |.sP.VO..KD......| +00000050 17 03 01 00 28 f5 b2 11 6b a6 4b 22 30 42 3c cc |....(...k.K"0B<.| +00000060 07 0d ed 10 d0 c7 7b ec b3 60 0b 2b 3c fb ec 3a |......{..`.+<..:| +00000070 c0 be 44 e7 76 b6 9e db 17 36 92 df 88 15 03 01 |..D.v....6......| +00000080 00 18 7a d9 2f 46 2e 0f ec c5 ee 7b ef bd fb e5 |..z./F.....{....| +00000090 26 40 0a a2 4e eb 56 0e ca 03 |&@..N.V...| diff --git a/src/crypto/tls/testdata/Server-TLSv10-RSA-AES b/src/crypto/tls/testdata/Server-TLSv10-RSA-AES new file mode 100644 index 0000000..7425376 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-AES @@ -0,0 +1,79 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 63 01 00 00 5f 03 01 78 91 f6 ad 9e |....c..._..x....| +00000010 79 23 92 10 d9 c5 43 52 8f f6 f4 3f f4 eb ac 6b |y#....CR...?...k| +00000020 f3 ce a9 76 a2 bf c3 5b 9d bc 52 00 00 04 00 2f |...v...[..R..../| +00000030 00 ff 01 00 00 32 00 00 00 0e 00 0c 00 00 09 31 |.....2.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 |........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 37 02 00 00 33 03 01 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 01 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 01 00 86 10 00 00 82 00 80 73 aa be d1 21 |...........s...!| +00000010 67 e9 9c 20 40 cf 0a 47 31 61 e9 2b ba 06 4f aa |g.. @..G1a.+..O.| +00000020 ce 15 6a b7 df 0d 0e b0 fe b5 f2 c0 26 81 39 6e |..j.........&.9n| +00000030 5b 96 3c 2f 42 4f 08 92 48 a3 95 c8 ad 0d 0e 8f |[....2.>....| +00000080 36 99 9f b7 53 ef 34 e8 d6 13 3b 14 03 01 00 01 |6...S.4...;.....| +00000090 01 16 03 01 00 30 c6 d2 a6 85 cf 2a e4 9e 9e e1 |.....0.....*....| +000000a0 d0 82 d0 2a f8 e5 bd f6 9a 67 0b c6 47 07 9c 14 |...*.....g..G...| +000000b0 7e 73 9e 4c 8b d2 55 4f b2 32 9a 16 16 a5 e8 25 |~s.L..UO.2.....%| +000000c0 62 e2 e9 88 b6 44 |b....D| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 21 7a ee 62 6a |..........0!z.bj| +00000010 20 39 2a 39 d1 d3 f7 bd 53 05 4f 1a 36 71 3b b6 | 9*9....S.O.6q;.| +00000020 c5 5a b7 3b c3 0b 3f b9 2f ac 62 1c c2 2f fa 29 |.Z.;..?./.b../.)| +00000030 dd f3 bc ff 35 28 7f 86 b8 0f 33 17 03 01 00 20 |....5(....3.... | +00000040 3a 6c 47 23 37 5a 15 bd 03 c6 64 c5 59 2f 91 e8 |:lG#7Z....d.Y/..| +00000050 a6 1b d5 04 c2 a7 80 0e 94 6c 3c e4 70 2c ea 81 |.........l<.p,..| +00000060 17 03 01 00 30 60 14 bc 6b 84 16 9f 53 b6 ee c9 |....0`..k...S...| +00000070 43 cf f3 46 97 45 e1 2f 86 96 26 cc ef ea 09 72 |C..F.E./..&....r| +00000080 36 92 4e 9e 2a 8e a2 d7 9a cd 5f 38 a8 07 c4 54 |6.N.*....._8...T| +00000090 a1 4d 6e 7a 36 15 03 01 00 20 1e c2 df a3 3e 8e |.Mnz6.... ....>.| +000000a0 15 c4 c0 90 8f 7c 5a e0 68 d7 ea 86 76 8d d1 27 |.....|Z.h...v..'| +000000b0 c1 d9 32 55 f9 ce f5 92 e6 51 |..2U.....Q| diff --git a/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 new file mode 100644 index 0000000..8b1de03 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 @@ -0,0 +1,73 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 63 01 00 00 5f 03 01 55 31 1a ed 02 |....c..._..U1...| +00000010 35 fe 3c ea 62 08 52 96 93 bc 2a 1b 82 fe b9 8f |5.<.b.R...*.....| +00000020 7a 47 0e 6a 9b e8 86 ca 89 a0 e6 00 00 04 00 05 |zG.j............| +00000030 00 ff 01 00 00 32 00 00 00 0e 00 0c 00 00 09 31 |.....2.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 |........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 37 02 00 00 33 03 01 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 00 05 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 01 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 01 00 86 10 00 00 82 00 80 75 7d be e3 5b |...........u}..[| +00000010 66 4b 58 09 f7 86 6a ca 93 8e ba 3c 18 11 47 5e |fKX...j....<..G^| +00000020 7e c2 b1 0c 5e a4 c1 07 ef 25 00 d7 bf c7 b0 03 |~...^....%......| +00000030 0d f6 ff a9 c2 73 a2 c0 dc 8d db f9 5a a9 18 7d |.....s......Z..}| +00000040 1f 8e 0b 9c 24 6c c8 49 99 e1 42 e0 86 d5 e1 e1 |....$l.I..B.....| +00000050 d1 ae fd d2 c4 ef 07 8c 28 95 b7 54 25 57 40 1c |........(..T%W@.| +00000060 c6 af 85 46 a0 31 d4 39 b8 47 43 88 a0 a6 5d d7 |...F.1.9.GC...].| +00000070 95 fb 88 64 ce 36 2b c5 56 85 56 40 f8 d4 d3 90 |...d.6+.V.V@....| +00000080 d1 25 53 06 d8 ab a0 f2 21 8f 88 14 03 01 00 01 |.%S.....!.......| +00000090 01 16 03 01 00 24 26 50 7a 2c ab 3f db 41 06 cf |.....$&Pz,.?.A..| +000000a0 8b 7b f8 46 ad a4 77 b6 06 f0 44 23 04 34 88 9d |.{.F..w...D#.4..| +000000b0 48 d7 5e cc 9e e6 46 a3 04 69 |H.^...F..i| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 24 57 fc eb dd 40 |..........$W...@| +00000010 83 1d 9a 9a 80 a3 62 a0 08 23 c3 97 fd d5 fb d7 |......b..#......| +00000020 98 f8 14 ae 61 c7 21 fb 8a 18 1e c8 15 05 e7 17 |....a.!.........| +00000030 03 01 00 21 7c 2b 2d 72 2f 63 56 3a 09 51 4e ab |...!|+-r/cV:.QN.| +00000040 31 25 c8 7e 34 5b a4 ab 30 87 50 07 ed 32 3f 79 |1%.~4[..0.P..2?y| +00000050 f1 db c0 17 f3 15 03 01 00 16 fc ce c9 0c b6 0c |................| +00000060 c5 2d d9 3f 2a 9e 9a 83 40 e1 a3 b9 5f 89 aa 75 |.-.?*...@..._..u| diff --git a/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV b/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV new file mode 100644 index 0000000..7bd0341 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV @@ -0,0 +1,11 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 77 01 00 00 73 03 02 0a 6b c9 55 9d |....w...s...k.U.| +00000010 bf 4e 61 b2 0a c7 c6 96 9f eb 90 91 87 ca d3 d3 |.Na.............| +00000020 62 dc b6 b4 db ea 41 fe 43 3e a3 00 00 14 c0 0a |b.....A.C>......| +00000030 c0 14 00 39 c0 09 c0 13 00 33 00 35 00 2f 00 ff |...9.....3.5./..| +00000040 56 00 01 00 00 36 00 00 00 0e 00 0c 00 00 09 31 |V....6.........1| +00000050 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000060 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000070 00 23 00 00 00 16 00 00 00 17 00 00 |.#..........| +>>> Flow 2 (server to client) +00000000 15 03 02 00 02 02 56 |......V| diff --git a/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 new file mode 100644 index 0000000..dc70edf --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 @@ -0,0 +1,73 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 63 01 00 00 5f 03 02 2b b6 22 28 e3 |....c..._..+."(.| +00000010 1f 42 f4 2e d0 43 4b 9a ea 2b 36 44 ca 93 6c 71 |.B...CK..+6D..lq| +00000020 b9 4d 52 44 64 57 b2 05 9b 41 da 00 00 04 00 05 |.MRDdW...A......| +00000030 00 ff 01 00 00 32 00 00 00 0e 00 0c 00 00 09 31 |.....2.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 |........| +>>> Flow 2 (server to client) +00000000 16 03 02 00 37 02 00 00 33 03 02 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 00 05 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 02 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 02 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 02 00 86 10 00 00 82 00 80 3d 47 85 0a ef |...........=G...| +00000010 47 7c c5 93 bb 6f 7c 57 dc 2b 3f f4 e7 da 4e fc |G|...o|W.+?...N.| +00000020 04 52 36 71 c5 63 1f 6f e6 43 91 06 bc 5c 14 b0 |.R6q.c.o.C...\..| +00000030 ee 83 ed 3d 7a d2 4e 2c d2 2c bb f0 0c b5 82 d5 |...=z.N,.,......| +00000040 9d c2 5a 03 12 b6 70 20 3c 89 84 af 1b 2c 2f b7 |..Z...p <....,/.| +00000050 9b fe dd 71 06 ac 46 30 a7 b5 9f 0b aa 6e 58 50 |...q..F0.....nXP| +00000060 9d da 6b ba 00 51 e9 2a e9 d2 e9 0f 83 62 73 19 |..k..Q.*.....bs.| +00000070 91 a4 46 bd 53 42 f7 15 ab ab 6b 8f f3 6f d1 07 |..F.SB....k..o..| +00000080 44 41 97 4c 7d 89 4b 33 55 30 30 14 03 02 00 01 |DA.L}.K3U00.....| +00000090 01 16 03 02 00 24 54 fe a0 7c 16 47 de 0b 8f 7d |.....$T..|.G...}| +000000a0 51 68 05 da 1e 6d 96 c9 e1 94 68 fa 79 46 02 db |Qh...m....h.yF..| +000000b0 03 4e 2e 70 9f 7e 14 85 fd 1d |.N.p.~....| +>>> Flow 4 (server to client) +00000000 14 03 02 00 01 01 16 03 02 00 24 4b c5 cf 20 3f |..........$K.. ?| +00000010 0a 13 1f 55 25 26 9b 33 fd 14 61 0f 44 32 26 b3 |...U%&.3..a.D2&.| +00000020 ab 01 ee c2 1f d3 38 08 f0 af 76 6a 0d e1 b7 17 |......8...vj....| +00000030 03 02 00 21 97 16 df 99 06 81 f2 00 d3 fd b4 03 |...!............| +00000040 be 16 b6 aa 74 d4 c7 25 67 94 14 34 25 ec 0d 12 |....t..%g..4%...| +00000050 c7 43 2d a2 1d 15 03 02 00 16 94 58 af 6b 55 5f |.C-........X.kU_| +00000060 25 0c 80 28 99 2d 75 1a ce 24 cd 75 0d 7f b9 71 |%..(.-u..$.u...q| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ALPN b/src/crypto/tls/testdata/Server-TLSv12-ALPN new file mode 100644 index 0000000..d738662 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ALPN @@ -0,0 +1,92 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 9d 01 00 00 99 03 03 53 49 69 68 95 |...........SIih.| +00000010 b9 7b 2a 84 d2 03 93 d4 33 e7 b7 7e bc b5 97 b0 |.{*.....3..~....| +00000020 4f 4f 6c d0 96 43 aa c8 6f da 90 00 00 04 cc a8 |OOl..C..o.......| +00000030 00 ff 01 00 00 6c 00 0b 00 04 03 00 01 02 00 0a |.....l..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000050 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| +00000060 70 72 6f 74 6f 31 00 16 00 00 00 17 00 00 00 0d |proto1..........| +00000070 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| +00000080 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000090 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| +000000a0 06 02 |..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 48 02 00 00 44 03 03 00 00 00 00 00 |....H...D.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| +00000030 1c 00 23 00 00 ff 01 00 01 00 00 10 00 09 00 07 |..#.............| +00000040 06 70 72 6f 74 6f 31 00 0b 00 02 01 00 16 03 03 |.proto1.........| +00000050 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b |.Y...U..R..O0..K| +00000060 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f |0..............?| +00000070 e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |.[..0...*.H.....| +00000080 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 |...0.1.0...U....| +00000090 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 |Go1.0...U....Go | +000000a0 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 |Root0...16010100| +000000b0 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 |0000Z..250101000| +000000c0 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 |000Z0.1.0...U...| +000000d0 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f |.Go1.0...U....Go| +000000e0 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 |0..0...*.H......| +000000f0 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d |......0.......F}| +00000100 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d |...'.H..(!.~...]| +00000110 fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 |..RE.z6G....B[..| +00000120 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 |...y.@.Om..+....| +00000130 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 |.g....."8.J.ts+.| +00000140 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 |4......t{.X.la<.| +00000150 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce |.A..++$#w[.;.u].| +00000160 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa | T..c...$....P..| +00000170 b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 |..C...ub...R....| +00000180 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 |.....0..0...U...| +00000190 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 |........0...U.%.| +000001a0 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b |.0...+.........+| +000001b0 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 |.......0...U....| +000001c0 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 |...0.0...U......| +000001d0 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 |....CC>I..m....`| +000001e0 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 |0...U.#..0...H.I| +000001f0 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 |M.~.1......n{0..| +00000200 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c |.U....0...exampl| +00000210 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 |e.golang0...*.H.| +00000220 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b |............0.@+| +00000230 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a |[P.a...SX...(.X.| +00000240 a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 |.8....1Z..f=C.-.| +00000250 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d |..... d8.$:....}| +00000260 b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc |.@ ._...a..v....| +00000270 e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 |..\.....l..s..Cw| +00000280 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae |.......@.a.Lr+..| +00000290 db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe |.F..M...>...B...| +000002a0 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac |=.`.\!.;........| +000002b0 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 |....... /.}.G.bC| +000002c0 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 |.(.._.).0.......| +000002d0 ed 90 99 5f 58 cb 3b 74 08 04 00 80 3b cd 7a 99 |..._X.;t....;.z.| +000002e0 3f bf 03 5a 26 21 90 db b4 8d 3b 69 14 82 1c ae |?..Z&!....;i....| +000002f0 7d 72 8f 4e eb ff c4 f0 13 fa 6f 69 48 e7 6d 3d |}r.N......oiH.m=| +00000300 fc b3 1c 54 60 54 cf 83 48 1d a3 50 55 28 3f 2c |...T`T..H..PU(?,| +00000310 db d3 dc c7 d9 58 74 de eb 5e 21 26 2f 32 c6 b2 |.....Xt..^!&/2..| +00000320 be 1b 08 fa d6 9f 3b b0 2b e8 c2 36 2f 9d c1 35 |......;.+..6/..5| +00000330 c1 54 4b 37 5f ff 99 4f c1 e4 ad 69 a0 c8 52 d3 |.TK7_..O...i..R.| +00000340 01 23 0d 57 17 08 7c 07 9a 3a 6d c8 87 5d 7e 09 |.#.W..|..:m..]~.| +00000350 7b 03 f9 5e de 83 4d 13 89 08 72 96 16 03 03 00 |{..^..M...r.....| +00000360 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 fb eb 44 09 0e 62 |....%...! ..D..b| +00000010 b0 ce d8 1f c5 f9 46 31 1e 1d e8 fb 02 5f 34 3b |......F1....._4;| +00000020 c1 6f 9a 38 6a 46 d2 cd a0 53 14 03 03 00 01 01 |.o.8jF...S......| +00000030 16 03 03 00 20 88 73 90 39 bc 9b 02 e4 c0 35 f0 |.... .s.9.....5.| +00000040 ef 40 b0 08 ca b9 bd 25 6b cd 03 7d ec 58 73 65 |.@.....%k..}.Xse| +00000050 d5 89 f2 f1 70 |....p| +>>> Flow 4 (server to client) +00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c cd 0b 21 |o...Q...h.B.L..!| +00000040 a5 29 ef 62 07 a5 11 b9 1f 4e 54 c3 66 4c 1e d3 |.).b.....NT.fL..| +00000050 1a 00 52 34 67 2b af 73 02 5f c9 6c 7c 6e ba f2 |..R4g+.s._.l|n..| +00000060 e6 38 bd 23 97 3f 80 6a 3b 8e bb 98 29 49 38 16 |.8.#.?.j;...)I8.| +00000070 77 74 2a a1 c7 36 80 de c9 91 cd b2 7d bc 6c 64 |wt*..6......}.ld| +00000080 6c 06 57 22 d1 f2 51 5f 84 ad 30 85 3a c0 4f e7 |l.W"..Q_..0.:.O.| +00000090 14 03 03 00 01 01 16 03 03 00 20 32 71 5a d3 94 |.......... 2qZ..| +000000a0 d5 17 e4 8c 3a 78 d1 48 4e 1b f5 83 36 f1 5a 38 |....:x.HN...6.Z8| +000000b0 e4 b5 6d ab 46 89 e0 24 74 87 80 17 03 03 00 1d |..m.F..$t.......| +000000c0 69 4c a6 24 67 79 18 59 92 4f 9a d0 2d 1d 57 e0 |iL.$gy.Y.O..-.W.| +000000d0 ec 0c 00 25 6f 2f 3a be 8a aa 80 94 ac 15 03 03 |...%o/:.........| +000000e0 00 12 ef 86 3e 93 42 bb 72 f1 1b 90 df 9a d3 ed |....>.B.r.......| +000000f0 d8 74 35 23 |.t5#| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback b/src/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback new file mode 100644 index 0000000..4fadf39 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 a6 01 00 00 a2 03 03 b5 c9 ab 32 7f |..............2.| +00000010 e1 af 3f f2 ac 2a 11 dd 33 f9 b5 21 88 0d e4 29 |..?..*..3..!...)| +00000020 e2 47 49 dc c7 31 a8 a5 25 81 0c 00 00 04 cc a8 |.GI..1..%.......| +00000030 00 ff 01 00 00 75 00 0b 00 04 03 00 01 02 00 0a |.....u..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000050 00 00 00 10 00 19 00 17 06 70 72 6f 74 6f 33 08 |.........proto3.| +00000060 68 74 74 70 2f 31 2e 31 06 70 72 6f 74 6f 34 00 |http/1.1.proto4.| +00000070 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 05 |..........0.....| +00000080 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 |................| +00000090 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 |................| +000000a0 01 03 02 02 02 04 02 05 02 06 02 |...........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| +00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............| +00000040 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0| +00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............| +00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..| +00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.| +00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....| +00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010| +000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101| +000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U| +000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...| +000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...| +000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......| +000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.| +00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B| +00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[.....y.@.Om..+.| +00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t| +00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l| +00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.| +00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....| +00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.| +00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U| +00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U| +00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.| +000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...| +000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..| +000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...| +000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{| +000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa| +00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*| +00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0| +00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(| +00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C| +00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..| +00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.| +00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.| +00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |.Cw.......@.a.Lr| +00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B| +00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....| +000002a0 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G| +000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 5f |......_X.;t...._| +000002d0 37 27 84 58 1e ea 1e 40 1b de a9 8f 04 d4 94 64 |7'.X...@.......d| +000002e0 4e 27 c7 f1 b3 30 d0 53 f5 3d 57 50 d2 17 97 c8 |N'...0.S.=WP....| +000002f0 3d 61 af a6 21 ab 1c 34 47 70 f8 b1 3b 9c 06 86 |=a..!..4Gp..;...| +00000300 87 00 e2 13 50 83 91 ad bc 84 bd b4 7b f3 4b ed |....P.......{.K.| +00000310 ca 81 0c 94 37 a8 ec 67 ca 9c f3 00 f6 af c2 92 |....7..g........| +00000320 c4 8c 78 07 18 0e 43 24 1b 98 16 50 5c 2b 75 0e |..x...C$...P\+u.| +00000330 40 66 dc 40 cd 10 1a 51 25 f3 96 25 1a 3e 70 af |@f.@...Q%..%.>p.| +00000340 16 24 d0 1c 0e 33 f9 c1 74 cf b7 e2 28 ac 60 16 |.$...3..t...(.`.| +00000350 03 03 00 04 0e 00 00 00 |........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 30 f2 bb f7 a7 ac |....%...! 0.....| +00000010 23 20 22 ee 73 0d 49 9c b3 7b c1 9a db 2c 85 f3 |# ".s.I..{...,..| +00000020 c0 82 31 60 bd 8b 14 4e 73 43 14 03 03 00 01 01 |..1`...NsC......| +00000030 16 03 03 00 20 09 8d c7 86 ee cc f4 c7 36 a3 49 |.... ........6.I| +00000040 d3 f7 a1 4a 68 a2 1e b4 fc cc a2 15 cb 01 92 d8 |...Jh...........| +00000050 72 b0 d1 6f eb |r..o.| +>>> Flow 4 (server to client) +00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c a2 ac 05 |o...Q...h.B.L...| +00000040 9c 69 69 99 08 9f de a4 d4 e7 37 ab 14 38 4c 47 |.ii.......7..8LG| +00000050 70 f0 97 1d db 2d 0a 14 c2 1e f0 16 9f 6d 37 02 |p....-.......m7.| +00000060 4b f1 16 be 98 3f df 74 83 7c 19 85 61 49 38 16 |K....?.t.|..aI8.| +00000070 ee 35 7a e2 3f 74 fe 8d e3 07 93 a1 5e fa f2 02 |.5z.?t......^...| +00000080 e5 c8 60 3f 11 83 8b 0e 32 52 f1 aa 52 b7 0a 89 |..`?....2R..R...| +00000090 14 03 03 00 01 01 16 03 03 00 20 9e 65 15 cf 45 |.......... .e..E| +000000a0 a5 03 69 c9 b1 d8 9e 92 a3 a2 b0 df 2e 62 b1 3a |..i..........b.:| +000000b0 17 78 cd e5 1d f3 51 42 7e 4e 25 17 03 03 00 1d |.x....QB~N%.....| +000000c0 d9 ae d0 fa b7 90 a9 2f 28 8d 1d 6f 54 1f c0 1e |......./(..oT...| +000000d0 4d ae b6 91 f0 e8 84 cf 86 11 22 25 ea 15 03 03 |M........."%....| +000000e0 00 12 0e 71 f2 11 9e 9f 58 ad c0 d8 fc fa 34 bc |...q....X.....4.| +000000f0 02 5a 60 00 |.Z`.| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch b/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch new file mode 100644 index 0000000..2d8a2eb --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch @@ -0,0 +1,14 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 9d 01 00 00 99 03 03 24 15 a8 f2 f5 |...........$....| +00000010 53 02 78 f0 4c f7 82 3c 68 7d a0 b1 9a 0f 29 32 |S.x.L..>> Flow 2 (server to client) +00000000 15 03 03 00 02 02 78 |......x| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured b/src/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured new file mode 100644 index 0000000..e1c991b --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 9d 01 00 00 99 03 03 92 d8 d4 4f 2e |..............O.| +00000010 82 ad e9 4f a2 c3 f7 23 da 2e dc 23 c0 87 fc 33 |...O...#...#...3| +00000020 14 63 f1 da 98 a8 af 70 3a 7e f3 00 00 04 cc a8 |.c.....p:~......| +00000030 00 ff 01 00 00 6c 00 0b 00 04 03 00 01 02 00 0a |.....l..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000050 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| +00000060 70 72 6f 74 6f 31 00 16 00 00 00 17 00 00 00 0d |proto1..........| +00000070 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| +00000080 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000090 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| +000000a0 06 02 |..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| +00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............| +00000040 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0| +00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............| +00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..| +00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.| +00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....| +00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010| +000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101| +000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U| +000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...| +000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...| +000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......| +000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.| +00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B| +00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[.....y.@.Om..+.| +00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t| +00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l| +00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.| +00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....| +00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.| +00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U| +00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U| +00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.| +000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...| +000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..| +000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...| +000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{| +000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa| +00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*| +00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0| +00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(| +00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C| +00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..| +00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.| +00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.| +00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |.Cw.......@.a.Lr| +00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B| +00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....| +000002a0 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G| +000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 8c |......_X.;t.....| +000002d0 cb 8c f6 6c dd 02 5f c9 13 7e c2 26 26 41 7a 1a |...l.._..~.&&Az.| +000002e0 25 c7 3e 22 11 30 32 c0 67 a5 53 32 1e 32 21 cb |%.>".02.g.S2.2!.| +000002f0 ff 0a b7 e1 7a 98 26 e9 bf 05 30 f6 13 38 ee 1d |....z.&...0..8..| +00000300 90 56 a6 0d e0 65 a8 02 0e 08 3e c0 31 ff dd fa |.V...e....>.1...| +00000310 05 3a 22 7c f8 ce 65 43 0c b6 c4 9a e4 ed 22 eb |.:"|..eC......".| +00000320 c4 46 b2 3d 1d 9c c1 e7 d4 6a 79 4f cf 8f 1c 45 |.F.=.....jyO...E| +00000330 52 51 b3 d1 a4 0d 0d df 4e 19 15 e6 af 2e 5a d5 |RQ......N.....Z.| +00000340 8a 2e 3c 48 8a f7 86 e5 53 0e 35 9a 8a c6 dd 16 |..>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 b7 d6 2f 99 8f c7 |....%...! ../...| +00000010 bc 48 b8 4f 01 f8 2c ff 75 e5 fe 10 c6 2d 2d d5 |.H.O..,.u....--.| +00000020 43 2b c3 14 cb d0 b2 7a e9 71 14 03 03 00 01 01 |C+.....z.q......| +00000030 16 03 03 00 20 c9 88 f1 a0 1a 9b 8a 14 00 33 f0 |.... .........3.| +00000040 e8 01 f3 c2 66 06 98 44 4d 35 89 8f 1b 65 d0 cf |....f..DM5...e..| +00000050 eb 7d 9f b1 df |.}...| +>>> Flow 4 (server to client) +00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c 76 fb ec |o...Q...h.B.Lv..| +00000040 0d 89 48 e7 19 98 64 df 59 8f df 50 ce 28 e8 3c |..H...d.Y..P.(.<| +00000050 b6 f8 5a ae bc 6b 2e a2 d6 23 05 f6 7f 36 ea 55 |..Z..k...#...6.U| +00000060 13 54 9e 9c 31 df d0 56 00 1f a7 6a b2 49 38 16 |.T..1..V...j.I8.| +00000070 7f d0 78 12 95 86 11 ca 98 63 07 4a 81 a5 d3 bd |..x......c.J....| +00000080 dc 9e 54 9c 25 f2 55 d5 fd cf 36 94 99 e0 c5 82 |..T.%.U...6.....| +00000090 14 03 03 00 01 01 16 03 03 00 20 e6 d9 c2 bb ca |.......... .....| +000000a0 02 d3 79 a4 fb b0 00 7d e2 47 46 d3 e7 b4 fe be |..y....}.GF.....| +000000b0 b3 8f c4 98 b7 f7 25 bc cc 3f a8 17 03 03 00 1d |......%..?......| +000000c0 ad f3 27 a0 c4 a4 5b 7b 40 11 a4 35 e6 10 03 63 |..'...[{@..5...c| +000000d0 13 d3 1c ce 75 8f 09 8b 85 6c 93 b1 9f 15 03 03 |....u....l......| +000000e0 00 12 79 0c dd 21 72 68 b8 30 45 5d 45 39 a9 c4 |..y..!rh.0E]E9..| +000000f0 a6 d7 12 99 |....| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven new file mode 100644 index 0000000..3d1ceaf --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven @@ -0,0 +1,126 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 6d 01 00 00 69 03 03 b0 00 44 aa 86 |....m...i....D..| +00000010 30 87 8e 3f f1 89 9a 4a f6 4c 3b 11 f3 4f e9 9f |0..?...J.L;..O..| +00000020 00 22 47 82 26 57 c7 d0 f9 59 6f 00 00 04 00 2f |."G.&W...Yo..../| +00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| +00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| +00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000060 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| +00000070 06 02 |..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +00000290 3b e9 fa e7 16 03 03 00 23 0d 00 00 1f 02 01 40 |;.......#......@| +000002a0 00 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 |................| +000002b0 06 01 05 03 06 03 02 01 02 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 03 00 86 10 00 00 82 00 80 10 ab 2f 0f b9 29 |............/..)| +00000220 9f 26 36 09 00 96 9a 3d 2a 01 50 03 f3 d6 ac fc |.&6....=*.P.....| +00000230 40 76 96 d0 e6 a6 67 89 24 b0 56 80 58 5e 6d 03 |@v....g.$.V.X^m.| +00000240 e3 0f dc 61 d1 de 25 95 8a 54 9f 5b 3e f2 31 dd |...a..%..T.[>.1.| +00000250 14 2a e2 de 7b 70 66 b5 ed 95 d9 cc 6f c0 b3 a1 |.*..{pf.....o...| +00000260 bb 41 b2 0f 7d e8 ce b5 11 eb 99 e2 ce c0 33 bc |.A..}.........3.| +00000270 6a 67 10 84 d2 dd ac 15 8f 8e aa 2b 1a 7b ca d3 |jg.........+.{..| +00000280 bb 4b 92 c4 b9 2b 08 c1 0d b2 cf 96 63 64 9d 12 |.K...+......cd..| +00000290 a6 93 cd 21 3b bc 8e 94 72 76 16 03 03 00 93 0f |...!;...rv......| +000002a0 00 00 8f 04 03 00 8b 30 81 88 02 42 00 d5 05 54 |.......0...B...T| +000002b0 b2 68 a5 04 d6 3c 7b 7d c1 be e3 d1 b4 25 42 d6 |.h...<{}.....%B.| +000002c0 2a 3a 2e ea 73 0d 57 ba 0f 96 78 66 c2 c5 d7 57 |*:..s.W...xf...W| +000002d0 79 9c 22 8b 76 e9 45 ff ef 92 e9 43 3e b8 8b b4 |y.".v.E....C>...| +000002e0 cf 3f 67 aa 70 d1 e8 a2 1c a8 3d 24 a2 78 02 42 |.?g.p.....=$.x.B| +000002f0 01 b2 17 64 66 2f 2e 0d 2d b9 1d 67 45 de 48 9e |...df/..-..gE.H.| +00000300 32 f2 1f 79 38 39 b8 bb 8b 7f 82 e9 46 fd 9b 1b |2..y89......F...| +00000310 b3 dd a4 9c 15 b2 a2 88 4c f7 42 a2 62 92 c0 d0 |........L.B.b...| +00000320 a1 78 aa 8b 2d 78 4f 02 5a f7 eb ca c7 34 fc b6 |.x..-xO.Z....4..| +00000330 6c 6e 14 03 03 00 01 01 16 03 03 00 40 bd 47 9b |ln..........@.G.| +00000340 ce 31 2c 09 d3 a8 2c bb 28 0c e8 bd 01 a9 54 34 |.1,...,.(.....T4| +00000350 a5 74 af e0 d2 38 f3 1b fa d0 2b a6 39 24 ae de |.t...8....+.9$..| +00000360 0a cf 4b c0 a2 3b bf 80 23 71 0a 60 ca 94 b7 23 |..K..;..#q.`...#| +00000370 80 e3 89 89 42 74 0b a1 c6 f6 d2 c0 79 |....Bt......y| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 54 52 4a 33 9e |...........TRJ3.| +00000020 bb 59 7e 21 03 a6 23 bd 68 18 43 b5 c5 c5 37 a2 |.Y~!..#.h.C...7.| +00000030 6f ac 8c 78 c5 cf 8f e6 01 df 17 53 45 6f 1a e0 |o..x.......SEo..| +00000040 9c 4a 3d 2c cb 0d 55 7d 32 81 ec 17 03 03 00 40 |.J=,..U}2......@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 ba 75 93 00 86 1c bc 66 9e 27 2f 2b 5a 68 0e 44 |.u.....f.'/+Zh.D| +00000070 81 15 0d 67 e6 ee 7a 43 08 78 93 71 91 00 56 0e |...g..zC.x.q..V.| +00000080 c6 e1 73 4b af 2f e6 e0 92 4d e5 35 ea 53 7c 45 |..sK./...M.5.S|E| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 8d 7e 99 bb 93 bd 5d ba 31 b0 0d |......~....].1..| +000000b0 1f 76 95 50 7c 1e 24 62 9d 05 65 3f ee b7 c2 24 |.v.P|.$b..e?...$| +000000c0 13 60 43 69 3a |.`Ci:| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndEd25519Given b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndEd25519Given new file mode 100644 index 0000000..1c3b08f --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndEd25519Given @@ -0,0 +1,109 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 6d 01 00 00 69 03 03 aa ad c9 dc 56 |....m...i......V| +00000010 79 2e da 42 a6 b2 9e 0a 85 a6 1b e0 5e cd 4e f5 |y..B........^.N.| +00000020 93 93 0c d5 62 a8 53 17 10 f7 e6 00 00 04 00 2f |....b.S......../| +00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| +00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| +00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000060 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| +00000070 06 02 |..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +00000290 3b e9 fa e7 16 03 03 00 23 0d 00 00 1f 02 01 40 |;.......#......@| +000002a0 00 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 |................| +000002b0 06 01 05 03 06 03 02 01 02 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 01 3c 0b 00 01 38 00 01 35 00 01 32 30 |....<...8..5..20| +00000010 82 01 2e 30 81 e1 a0 03 02 01 02 02 10 17 d1 81 |...0............| +00000020 93 be 2a 8c 21 20 10 25 15 e8 34 23 4f 30 05 06 |..*.! .%..4#O0..| +00000030 03 2b 65 70 30 12 31 10 30 0e 06 03 55 04 0a 13 |.+ep0.1.0...U...| +00000040 07 41 63 6d 65 20 43 6f 30 1e 17 0d 31 39 30 35 |.Acme Co0...1905| +00000050 31 36 32 31 35 34 32 36 5a 17 0d 32 30 30 35 31 |16215426Z..20051| +00000060 35 32 31 35 34 32 36 5a 30 12 31 10 30 0e 06 03 |5215426Z0.1.0...| +00000070 55 04 0a 13 07 41 63 6d 65 20 43 6f 30 2a 30 05 |U....Acme Co0*0.| +00000080 06 03 2b 65 70 03 21 00 0b e0 b5 60 b5 e2 79 30 |..+ep.!....`..y0| +00000090 3d be e3 1e e0 50 b1 04 c8 6d c7 78 6c 69 2f c5 |=....P...m.xli/.| +000000a0 14 ad 9a 63 6f 79 12 91 a3 4d 30 4b 30 0e 06 03 |...coy...M0K0...| +000000b0 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 |U...........0...| +000000c0 55 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 |U.%..0...+......| +000000d0 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 |.0...U.......0.0| +000000e0 16 06 03 55 1d 11 04 0f 30 0d 82 0b 65 78 61 6d |...U....0...exam| +000000f0 70 6c 65 2e 63 6f 6d 30 05 06 03 2b 65 70 03 41 |ple.com0...+ep.A| +00000100 00 fc 19 17 2a 94 a5 31 fa 29 c8 2e 7f 5b a0 5d |....*..1.)...[.]| +00000110 8a 4e 34 40 39 d6 b3 10 dc 19 fe a0 22 71 b3 f5 |.N4@9......."q..| +00000120 8f a1 58 0d cd f4 f1 85 24 bf e6 3d 14 df df ed |..X.....$..=....| +00000130 0e e1 17 d8 11 a2 60 d0 8a 37 23 2a c2 46 aa 3a |......`..7#*.F.:| +00000140 08 16 03 03 00 86 10 00 00 82 00 80 14 f2 ac 22 |..............."| +00000150 fb 0b f8 03 a7 cf 23 d5 ea 9f b0 f2 64 ae 41 fe |......#.....d.A.| +00000160 33 f7 54 69 f5 41 b7 c1 91 6d 2b 3e 14 2a f6 c8 |3.Ti.A...m+>.*..| +00000170 96 45 00 28 13 f5 2f de 35 f9 64 89 5c 99 3e 89 |.E.(../.5.d.\.>.| +00000180 06 ff 59 56 69 db 5f 6e 02 84 dd 1c 44 7b 86 e8 |..YVi._n....D{..| +00000190 e3 d9 03 f1 16 9e 06 23 00 43 91 ec a9 dd da a4 |.......#.C......| +000001a0 ac fe 5b f8 62 f9 76 19 38 83 54 b4 8c 0b 02 f0 |..[.b.v.8.T.....| +000001b0 fa 7a 8e 2e da 9d e1 4a c6 51 92 9b f6 4b a1 31 |.z.....J.Q...K.1| +000001c0 c9 64 b2 a6 9a 01 52 86 b3 7a 43 17 16 03 03 00 |.d....R..zC.....| +000001d0 48 0f 00 00 44 08 07 00 40 29 35 71 34 aa b1 f1 |H...D...@)5q4...| +000001e0 64 08 4e 06 43 db 00 f7 f5 98 8e b6 51 d7 c4 b5 |d.N.C.......Q...| +000001f0 2b fa 56 8b bd 7b 18 f2 81 e9 2f 81 82 d8 90 e7 |+.V..{..../.....| +00000200 5b bc 72 7e f7 97 43 df cd 07 bf 7b ae 60 08 8b |[.r~..C....{.`..| +00000210 0a 71 c5 bf f0 7a 3e cc 0b 14 03 03 00 01 01 16 |.q...z>.........| +00000220 03 03 00 40 85 4f e0 c0 f3 3e a4 51 68 d6 ec 1b |...@.O...>.Qh...| +00000230 f1 4b 3e 0e 13 84 87 e3 3c 9a 5f 67 75 3a ad 08 |.K>.....<._gu:..| +00000240 be 29 15 b0 1f 62 27 fd d8 dd 58 b1 65 e7 e2 db |.)...b'...X.e...| +00000250 fe 55 a5 2d 2e 71 59 07 ad 12 12 80 12 bb 26 36 |.U.-.qY.......&6| +00000260 93 fb ea b1 |....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 f4 ed 23 ce da |.............#..| +00000020 73 5f ef 6b a2 82 3d a5 c6 f1 fd 8f a0 47 4e 34 |s_.k..=......GN4| +00000030 f9 7c d0 67 49 00 11 c3 76 83 23 3f 99 41 d5 5c |.|.gI...v.#?.A.\| +00000040 aa 9f 97 66 b7 0a 59 ba f3 40 83 17 03 03 00 40 |...f..Y..@.....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 82 66 85 d7 47 a6 5a 19 4f 89 5c 56 43 cb 6a bd |.f..G.Z.O.\VC.j.| +00000070 1b ae 46 40 7d e8 a9 7b 57 04 91 8b d5 de 24 f1 |..F@}..{W.....$.| +00000080 c0 df 37 45 e9 af d7 c5 1c e7 ee 80 0d 61 2a 7f |..7E.........a*.| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 5a 97 f3 38 e5 3a f1 07 79 b7 eb |.....Z..8.:..y..| +000000b0 ed 85 57 3a 96 16 51 38 85 86 ec 1b 9b 48 82 9c |..W:..Q8.....H..| +000000c0 05 bf 4d e5 fb |..M..| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven new file mode 100644 index 0000000..3dec0de --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven @@ -0,0 +1,125 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 6d 01 00 00 69 03 03 e7 7e 1f 56 df |....m...i...~.V.| +00000010 f1 1b e5 92 47 3b fb 25 a6 57 7d 13 47 08 f0 0f |....G;.%.W}.G...| +00000020 5b 64 64 00 d3 25 33 e5 a5 5b e3 00 00 04 00 2f |[dd..%3..[...../| +00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| +00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| +00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000060 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| +00000070 06 02 |..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +00000290 3b e9 fa e7 16 03 03 00 23 0d 00 00 1f 02 01 40 |;.......#......@| +000002a0 00 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 |................| +000002b0 06 01 05 03 06 03 02 01 02 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| +00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| +00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.| +00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1| +00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C| +00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523| +00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231| +00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac| +00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.| +00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....| +000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x| +000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.| +000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4| +000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..| +000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#| +000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....| +00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......| +00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..| +00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U| +00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U| +00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.| +00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0| +00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........| +00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..| +00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]| +000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A| +000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...| +000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...| +000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| +000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| +000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| +00000200 e5 35 16 03 03 00 86 10 00 00 82 00 80 7f 38 c9 |.5............8.| +00000210 56 ed de 7d a6 2c dc cc 24 61 ea d3 8a fc b8 18 |V..}.,..$a......| +00000220 b8 e5 50 3e c3 d1 ca cf f7 0c d9 9b 22 d8 6d 0f |..P>........".m.| +00000230 71 e7 dd 7c 24 84 c6 f1 6a ac a0 3d ea d7 65 24 |q..|$...j..=..e$| +00000240 d7 3a 17 d5 b7 ec f7 03 bc 58 3a 01 d5 08 27 25 |.:.......X:...'%| +00000250 b9 2f 3b 96 cb d5 7c 12 20 f4 f1 91 58 13 fb 50 |./;...|. ...X..P| +00000260 f8 d5 5c e4 43 85 e8 41 37 3e ff fa a6 64 92 4d |..\.C..A7>...d.M| +00000270 bd d4 96 59 bd 94 f1 95 21 ad 75 1e 0d a2 8d 30 |...Y....!.u....0| +00000280 a3 82 f4 56 0f ba 5d 40 32 7f 0c 5f 5a 16 03 03 |...V..]@2.._Z...| +00000290 00 88 0f 00 00 84 08 04 00 80 39 b4 f4 68 e9 96 |..........9..h..| +000002a0 01 53 95 31 26 fa 3c 70 46 9f ba 62 b4 37 ea a6 |.S.1&..Gy..^p| +000002f0 30 8c 11 3f 27 43 4f 5d 81 89 83 39 9d fe 0c c3 |0..?'CO]...9....| +00000300 af 40 8d 2a 41 bf 57 67 7a df b4 89 29 10 9a 84 |.@.*A.Wgz...)...| +00000310 ff 8c 2f 58 1a 0a b9 62 4e 8e 14 03 03 00 01 01 |../X...bN.......| +00000320 16 03 03 00 40 7c 7a 79 ae 84 60 b8 95 83 30 78 |....@|zy..`...0x| +00000330 e9 6e 02 36 52 85 5a 6a a7 b5 f5 6d 4d a9 09 9d |.n.6R.Zj...mM...| +00000340 43 9d 46 da d0 cf 75 25 49 e1 79 0b 23 2d 85 c2 |C.F...u%I.y.#-..| +00000350 fd 5d 90 08 f5 75 81 ab 01 a0 f4 93 12 87 fb e3 |.]...u..........| +00000360 9b 99 4d fa c5 |..M..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 48 61 67 c0 1e |...........Hag..| +00000020 09 79 82 cc 55 60 fa e5 bd 1a 1d 14 d3 25 e6 4b |.y..U`.......%.K| +00000030 b7 a6 47 64 01 65 12 b3 37 42 1a 13 d9 90 12 7e |..Gd.e..7B.....~| +00000040 ea d8 30 39 e2 25 5e 9a 05 61 11 17 03 03 00 40 |..09.%^..a.....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 cf c5 73 08 e9 15 25 b6 d8 e3 fa 0c a1 25 33 75 |..s...%......%3u| +00000070 8a 2e 66 03 c2 2d 50 c7 e1 10 b4 2a 0c 88 87 90 |..f..-P....*....| +00000080 04 4a 80 26 85 4b fd 9a 4f 0e b1 2c f0 18 57 f5 |.J.&.K..O..,..W.| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 ce e0 a1 71 be 3d 1e b0 bd 06 4c |........q.=....L| +000000b0 1f 5b 10 8d 77 18 e0 c5 81 c9 4e 1b 3b 96 f6 6d |.[..w.....N.;..m| +000000c0 88 03 53 54 30 |..ST0| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given new file mode 100644 index 0000000..8efbc91 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given @@ -0,0 +1,125 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 6d 01 00 00 69 03 03 4c 65 99 ab e0 |....m...i..Le...| +00000010 4b 0a 08 f5 06 20 f9 3d 96 4f 05 e3 58 6f 41 50 |K.... .=.O..XoAP| +00000020 c1 5f e8 a8 0a 5f 8f f2 de 7f 16 00 00 04 00 2f |._..._........./| +00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| +00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| +00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000060 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| +00000070 06 02 |..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +00000290 3b e9 fa e7 16 03 03 00 23 0d 00 00 1f 02 01 40 |;.......#......@| +000002a0 00 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 |................| +000002b0 06 01 05 03 06 03 02 01 02 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| +00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| +00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.| +00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1| +00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C| +00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523| +00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231| +00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac| +00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.| +00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....| +000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x| +000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.| +000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4| +000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..| +000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#| +000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....| +00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......| +00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..| +00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U| +00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U| +00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.| +00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0| +00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........| +00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..| +00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]| +000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A| +000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...| +000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...| +000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......| +000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{| +000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....| +00000200 e5 35 16 03 03 00 86 10 00 00 82 00 80 41 62 b4 |.5...........Ab.| +00000210 fb 81 80 58 e3 0d c7 b2 c0 55 ee 5b 1a ba 2d 8f |...X.....U.[..-.| +00000220 9f 79 24 0a d5 be c7 2b 55 ec 51 6d b9 78 63 85 |.y$....+U.Qm.xc.| +00000230 82 d2 ea 02 0c 06 fe 05 fd ed 08 be 71 99 5f 53 |............q._S| +00000240 94 85 01 ff ba 2a ee 14 cb 99 0a df 1e 67 0d 95 |.....*.......g..| +00000250 63 8d 1f 96 41 75 f9 5d 1a 21 03 6c e3 eb 4f 5e |c...Au.].!.l..O^| +00000260 28 c3 4d bb 6d 29 33 bc 24 75 8c 3b f2 c4 6b f5 |(.M.m)3.$u.;..k.| +00000270 86 db 40 59 34 43 fb a9 1e ea 6f 3f 0e b4 35 39 |..@Y4C....o?..59| +00000280 52 d8 0f 85 ed 3b 52 b6 5b 7f b0 bf c3 16 03 03 |R....;R.[.......| +00000290 00 88 0f 00 00 84 04 01 00 80 52 85 ca 08 7d 07 |..........R...}.| +000002a0 bc d8 0c a4 b8 36 01 c0 b8 8a 18 ba d8 d4 a3 fa |.....6..........| +000002b0 fd 32 e2 00 72 e5 d2 c8 5a 59 6b 5e 6e df 35 da |.2..r...ZYk^n.5.| +000002c0 c7 1e ee af 87 4b d6 30 7e 27 1c 76 70 28 79 ac |.....K.0~'.vp(y.| +000002d0 7f 31 bc 44 55 3c 15 61 d2 0d 24 9c 48 43 9f 12 |.1.DU<.a..$.HC..| +000002e0 a6 74 5c 2f 5b 4e 96 4a 47 b4 6b 7c fa da 37 96 |.t\/[N.JG.k|..7.| +000002f0 ec 46 7d 05 be 24 8f cf 11 31 ab 4c 5b c7 3e 94 |.F}..$...1.L[.>.| +00000300 9a 2a 39 e8 fe aa aa ee e3 00 a3 a8 1e 75 4a 21 |.*9..........uJ!| +00000310 b4 ad 24 8f ee e8 30 85 b1 28 14 03 03 00 01 01 |..$...0..(......| +00000320 16 03 03 00 40 71 47 13 68 49 74 9c 2a 81 35 94 |....@qG.hIt.*.5.| +00000330 52 f6 44 44 67 3b 62 e1 ef 34 18 e7 8a 56 71 88 |R.DDg;b..4...Vq.| +00000340 83 7e 67 28 20 18 b1 c5 8a c8 8b 6a fe ee bf da |.~g( ......j....| +00000350 5f 6e cd fa a8 5c af 5c 3c 83 80 78 f3 fe 1b dc |_n...\.\<..x....| +00000360 95 fe 22 16 82 |.."..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 20 f7 51 8f 23 |........... .Q.#| +00000020 08 8d 67 5d 12 06 b0 48 81 2d 0c ba 88 03 88 31 |..g]...H.-.....1| +00000030 d0 ab 63 0d 9f 28 60 21 0a a3 58 47 c2 04 cc f1 |..c..(`!..XG....| +00000040 50 0d 88 b2 e5 54 50 26 e6 6e ed 17 03 03 00 40 |P....TP&.n.....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 fa 4d e5 00 14 2c 65 82 5d 1b bf 99 6a 54 16 98 |.M...,e.]...jT..| +00000070 ef 55 15 00 f9 c4 3e 61 88 83 63 fd 60 66 f1 87 |.U....>a..c.`f..| +00000080 fa c4 45 ae de b8 0a 36 75 f5 b2 b6 f5 d8 9b df |..E....6u.......| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 54 cc c0 15 e5 6d 62 4d 13 54 e8 |.....T....mbM.T.| +000000b0 fa cf 76 a6 de d6 48 f8 0d ef 30 b7 12 05 cf 75 |..v...H...0....u| +000000c0 8b 00 9e d5 63 |....c| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven new file mode 100644 index 0000000..a81c173 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven @@ -0,0 +1,85 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 6d 01 00 00 69 03 03 be a7 a4 6c f7 |....m...i.....l.| +00000010 f6 b4 f2 64 5d 0e 36 b6 05 f5 f1 c9 fe 3c c2 8e |...d].6......<..| +00000020 c4 b7 18 68 b9 0c 1d 51 50 2f 1e 00 00 04 00 2f |...h...QP/...../| +00000030 00 ff 01 00 00 3c 00 16 00 00 00 17 00 00 00 0d |.....<..........| +00000040 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| +00000050 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000060 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| +00000070 06 02 |..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +00000290 3b e9 fa e7 16 03 03 00 23 0d 00 00 1f 02 01 40 |;.......#......@| +000002a0 00 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 |................| +000002b0 06 01 05 03 06 03 02 01 02 03 00 00 16 03 03 00 |................| +000002c0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 07 0b 00 00 03 00 00 00 16 03 03 00 |................| +00000010 86 10 00 00 82 00 80 a9 b6 12 e2 84 71 62 7a 20 |............qbz | +00000020 63 80 99 c6 ee f7 61 f9 74 d6 0b ab 31 74 69 ca |c.....a.t...1ti.| +00000030 94 20 9e 1b 0e 52 45 c4 f4 b3 cb fb a4 07 61 6f |. ...RE.......ao| +00000040 a1 5a 84 4c 4f f6 4a e4 bc c5 c2 b0 ee 8a 30 5b |.Z.LO.J.......0[| +00000050 10 e0 ed d3 4c b7 32 8c ed 3f 89 a7 a7 95 60 86 |....L.2..?....`.| +00000060 97 1a ae ab 2f 5c e6 6d 1b c3 35 bd f5 c1 f0 1a |..../\.m..5.....| +00000070 d4 70 e5 00 f2 d4 d1 20 6a 82 db e7 52 ca 88 e5 |.p..... j...R...| +00000080 2d cc 79 0c f6 09 84 65 f0 30 41 67 10 0a 48 d1 |-.y....e.0Ag..H.| +00000090 09 3e 56 7a aa 57 bc 14 03 03 00 01 01 16 03 03 |.>Vz.W..........| +000000a0 00 40 e6 0a 91 5f 30 f8 52 75 94 8e ab 82 ec 1d |.@..._0.Ru......| +000000b0 b7 a1 1c 18 1a aa 1c f8 73 93 0e 20 ad 68 a7 65 |........s.. .h.e| +000000c0 86 c9 f5 90 f9 b2 fd d1 32 94 52 6e 82 9b b9 45 |........2.Rn...E| +000000d0 97 52 4b 1e c2 31 a6 2e c8 b3 1a 62 22 83 8f df |.RK..1.....b"...| +000000e0 d7 06 |..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 b0 2c 61 79 87 |............,ay.| +00000020 59 d4 9e 4d e7 56 4a 34 ba 78 d5 06 98 a2 92 35 |Y..M.VJ4.x.....5| +00000030 a1 fc 57 5a 6e d3 0f 44 08 1c a1 7b 3c d3 f1 86 |..WZn..D...{<...| +00000040 a2 04 04 5e 1b 7c 00 4f 51 71 73 17 03 03 00 40 |...^.|.OQqs....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 aa 5c 1a 9a 70 bc b3 fb 70 07 0b 24 cb 95 84 61 |.\..p...p..$...a| +00000070 96 ed d8 97 2f d6 79 51 ed cd 67 44 e5 d4 a3 57 |..../.yQ..gD...W| +00000080 95 f6 c8 31 a8 95 c2 07 a4 ce 1c fc 4a dc 93 d9 |...1........J...| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 ae dd c4 f4 04 d3 b1 1a 8a 56 f7 |..............V.| +000000b0 73 c9 d5 aa 6c 59 d7 66 77 34 64 2d 19 79 13 80 |s...lY.fw4d-.y..| +000000c0 98 60 6d f4 d9 |.`m..| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES new file mode 100644 index 0000000..d7e6188 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES @@ -0,0 +1,85 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 97 01 00 00 93 03 03 86 3b 10 1e 5f |............;.._| +00000010 81 eb 21 bd 77 47 61 e9 3f 82 85 14 91 8c ab 7d |..!.wGa.?......}| +00000020 84 bd b1 f0 06 20 8a 7b 06 d6 78 00 00 04 c0 0a |..... .{..x.....| +00000030 00 ff 01 00 00 66 00 00 00 0e 00 0c 00 00 09 31 |.....f.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 |...........0....| +00000070 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +00000080 08 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 |................| +00000090 02 01 03 02 02 02 04 02 05 02 06 02 |............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 c0 0a 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 00 30 |...........0...0| +00000050 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 30 09 |..b.....-G....0.| +00000060 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 09 06 |..*.H.=..0E1.0..| +00000070 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 04 |.U....AU1.0...U.| +00000080 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 |...Some-State1!0| +00000090 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 |...U....Internet| +000000a0 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 | Widgits Pty Ltd| +000000b0 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 33 32 |0...121122150632| +000000c0 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 32 5a |Z..221120150632Z| +000000d0 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 |0E1.0...U....AU1| +000000e0 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 |.0...U....Some-S| +000000f0 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 |tate1!0...U....I| +00000100 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 |nternet Widgits | +00000110 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 2a 86 |Pty Ltd0..0...*.| +00000120 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +00000130 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 16 56 |.........Hs6~..V| +00000140 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 f6 b0 |.".=S.;M!=.ku...| +00000150 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 2f 1c |...&.....r2|.d/.| +00000160 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 e0 28 |...h#.~..%.H:i.(| +00000170 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 d8 81 |m.7...b....pb...| +00000180 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 de 76 |.d1...1...h..#.v| +00000190 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd 9b d8 |d?.\....XX._p...| +000001a0 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a 20 e2 |.........0f[f. .| +000001b0 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d 04 01 |'...;0...*.H.=..| +000001c0 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb e2 45 |....0...B...O..E| +000001d0 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e 1b b6 |.H}.......Gp.^..| +000001e0 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b 7e 92 |/...M.a@......~.| +000001f0 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 ec 47 |~.v..;~.?....Y.G| +00000200 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 4d fc |-|..N....o..B.M.| +00000210 be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 13 83 |.g..-...?..%.3..| +00000220 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd d7 11 |.....7z..z......| +00000230 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d ae cb |i..|V..1x+..x...| +00000240 be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f 2a 16 |..N6$1{j.9....*.| +00000250 03 03 00 b7 0c 00 00 b3 03 00 1d 20 2f e5 7d a3 |........... /.}.| +00000260 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| +00000270 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 04 03 00 8b |......._X.;t....| +00000280 30 81 88 02 42 01 c5 d1 36 97 5b 0e 5e a6 90 50 |0...B...6.[.^..P| +00000290 a0 2e 80 b5 df d7 5a f6 95 0d a4 c6 f0 da 2e e7 |......Z.........| +000002a0 91 79 9f 85 2e ef ca 66 3c f7 c4 7b bd 61 70 bb |.y.....f<..{.ap.| +000002b0 16 c5 aa 00 35 33 ae 58 00 b3 f1 fe 0f 77 52 23 |....53.X.....wR#| +000002c0 f4 40 ba 4b c7 e5 43 02 42 01 64 af ab 8a 87 38 |.@.K..C.B.d....8| +000002d0 a1 7f b8 ae 84 0e a4 ff ad 16 09 44 0b 65 67 70 |...........D.egp| +000002e0 12 7f 1a 37 9a 1d 5e b7 3b 63 df f9 6b f1 b9 ba |...7..^.;c..k...| +000002f0 6b 35 8f b3 03 da 3d 61 00 3d 4e 75 b4 d0 92 d5 |k5....=a.=Nu....| +00000300 ee 50 9d d7 f9 26 69 e6 ec cf 3b 16 03 03 00 04 |.P...&i...;.....| +00000310 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 54 db 5b a1 4c e0 |....%...! T.[.L.| +00000010 0e 52 a2 45 e3 b4 ac 91 3d e1 de a9 3e eb 80 9e |.R.E....=...>...| +00000020 f5 04 7b fc 82 10 2f d9 d1 41 14 03 03 00 01 01 |..{.../..A......| +00000030 16 03 03 00 40 47 68 cc 5e 68 3f 05 d6 f8 5c 11 |....@Gh.^h?...\.| +00000040 08 a3 91 72 ae 4c 98 67 2f 45 ee 16 6b 8b 2d 28 |...r.L.g/E..k.-(| +00000050 15 34 43 47 f9 46 f2 96 c2 85 d5 cc 03 e0 84 de |.4CG.F..........| +00000060 9c 03 fe bf c9 73 23 15 d0 0f 85 3a 76 db 9f 5d |.....s#....:v..]| +00000070 95 b7 de 9c c2 |.....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 98 34 52 f3 44 |............4R.D| +00000020 18 69 23 61 ef 8f e9 c0 88 9c ad 1f cb e4 8d 55 |.i#a...........U| +00000030 bd bb 77 9c 65 9d 21 f0 54 4c 46 db 4f e6 e8 ab |..w.e.!.TLF.O...| +00000040 6b 1d 60 38 7f e0 2c 38 ef e7 43 17 03 03 00 40 |k.`8..,8..C....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 44 68 90 07 1e 8c 7f db 3e 3f 8c 28 e1 d7 41 38 |Dh......>?.(..A8| +00000070 e2 78 04 e3 42 c2 a9 76 bb 0a ae b9 93 df 81 d7 |.x..B..v........| +00000080 9b 0f 1d 44 19 79 ff 7c 21 8f 75 ca e2 82 cc c4 |...D.y.|!.u.....| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 82 1f e6 2c 3f c7 55 19 01 0b 62 |........,?.U...b| +000000b0 1a 99 fc f8 d3 b0 38 21 41 92 1a d1 e0 43 96 da |......8!A....C..| +000000c0 80 4b 58 91 c8 |.KX..| diff --git a/src/crypto/tls/testdata/Server-TLSv12-Ed25519 b/src/crypto/tls/testdata/Server-TLSv12-Ed25519 new file mode 100644 index 0000000..dd34592 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-Ed25519 @@ -0,0 +1,58 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 85 01 00 00 81 03 03 f0 8d 1b 90 67 |...............g| +00000010 3b 23 46 ac f7 79 f2 f9 e8 90 98 b3 52 b2 55 2a |;#F..y......R.U*| +00000020 fb 0f 1e dd 4f b3 75 4b 9b 88 0e 00 00 04 cc a9 |....O.uK........| +00000030 00 ff 01 00 00 54 00 0b 00 04 03 00 01 02 00 0a |.....T..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000050 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 05 03 |.........0......| +00000060 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000070 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| +00000080 03 02 02 02 04 02 05 02 06 02 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a9 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 01 |................| +00000040 3c 0b 00 01 38 00 01 35 00 01 32 30 82 01 2e 30 |<...8..5..20...0| +00000050 81 e1 a0 03 02 01 02 02 10 0f 43 1c 42 57 93 94 |..........C.BW..| +00000060 1d e9 87 e4 f1 ad 15 00 5d 30 05 06 03 2b 65 70 |........]0...+ep| +00000070 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 6d |0.1.0...U....Acm| +00000080 65 20 43 6f 30 1e 17 0d 31 39 30 35 31 36 32 31 |e Co0...19051621| +00000090 33 38 30 31 5a 17 0d 32 30 30 35 31 35 32 31 33 |3801Z..200515213| +000000a0 38 30 31 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 |801Z0.1.0...U...| +000000b0 07 41 63 6d 65 20 43 6f 30 2a 30 05 06 03 2b 65 |.Acme Co0*0...+e| +000000c0 70 03 21 00 3f e2 15 2e e6 e3 ef 3f 4e 85 4a 75 |p.!.?......?N.Ju| +000000d0 77 a3 64 9e ed e0 bf 84 2c cc 92 26 8f fa 6f 34 |w.d.....,..&..o4| +000000e0 83 aa ec 8f a3 4d 30 4b 30 0e 06 03 55 1d 0f 01 |.....M0K0...U...| +000000f0 01 ff 04 04 03 02 05 a0 30 13 06 03 55 1d 25 04 |........0...U.%.| +00000100 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 30 0c 06 |.0...+.......0..| +00000110 03 55 1d 13 01 01 ff 04 02 30 00 30 16 06 03 55 |.U.......0.0...U| +00000120 1d 11 04 0f 30 0d 82 0b 65 78 61 6d 70 6c 65 2e |....0...example.| +00000130 63 6f 6d 30 05 06 03 2b 65 70 03 41 00 63 44 ed |com0...+ep.A.cD.| +00000140 9c c4 be 53 24 53 9f d2 10 8d 9f e8 21 08 90 95 |...S$S......!...| +00000150 39 e5 0d c1 55 ff 2c 16 b7 1d fc ab 7d 4d d4 e0 |9...U.,.....}M..| +00000160 93 13 d0 a9 42 e0 b6 6b fe 5d 67 48 d7 9f 50 bc |....B..k.]gH..P.| +00000170 6c cd 4b 03 83 7c f2 08 58 cd ac cf 0c 16 03 03 |l.K..|..X.......| +00000180 00 6c 0c 00 00 68 03 00 1d 20 2f e5 7d a3 47 cd |.l...h... /.}.G.| +00000190 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| +000001a0 cf c2 ed 90 99 5f 58 cb 3b 74 08 07 00 40 1f 56 |....._X.;t...@.V| +000001b0 21 8a 44 04 69 65 ee f8 93 52 4c f0 49 42 57 4c |!.D.ie...RL.IBWL| +000001c0 5b f5 1a ef 43 ad 39 93 03 a3 64 84 da e5 82 32 |[...C.9...d....2| +000001d0 fc 77 12 61 f3 f4 2c d8 61 9e 86 01 1f c0 a0 98 |.w.a..,.a.......| +000001e0 94 a3 7f 15 75 c8 e6 2f 20 bd af 7c be 0e 16 03 |....u../ ..|....| +000001f0 03 00 04 0e 00 00 00 |.......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 26 b0 6c 90 e7 71 |....%...! &.l..q| +00000010 23 78 4b a1 a1 32 7c 28 e9 df 7e 98 e9 78 be 8d |#xK..2|(..~..x..| +00000020 0d ec fc 30 82 99 16 f0 9f 20 14 03 03 00 01 01 |...0..... ......| +00000030 16 03 03 00 20 e9 81 b0 ea b3 f3 21 40 9a 3b 3e |.... ......!@.;>| +00000040 71 a7 13 f5 3a 8a cd 86 34 8b 7e 41 b5 2a 1b 03 |q...:...4.~A.*..| +00000050 29 77 b3 b2 da |)w...| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 54 5a ff 09 7d |.......... TZ..}| +00000010 46 04 40 62 c5 63 71 85 c7 b4 6c 09 ee 15 71 6b |F.@b.cq...l...qk| +00000020 60 3b 00 3d 46 47 13 a5 f7 15 16 17 03 03 00 1d |`;.=FG..........| +00000030 13 8d 00 50 58 d0 2a 47 a8 d8 de 87 d4 3e ff ee |...PX.*G.....>..| +00000040 f1 4d 6b 25 94 6f 01 7b 70 ee 53 d9 be 15 03 03 |.Mk%.o.{p.S.....| +00000050 00 12 13 ea 17 69 00 0e 2b ae 21 a9 5e 0a 41 2d |.....i..+.!.^.A-| +00000060 1b 73 f0 2d |.s.-| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial b/src/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial new file mode 100644 index 0000000..e01c32c --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial @@ -0,0 +1,89 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 89 01 00 00 85 03 03 9a d9 fe da 40 |...............@| +00000010 cf 8b ed 11 09 8e 3f 29 4b 0d 46 ff fc f6 56 2c |......?)K.F...V,| +00000020 a8 e7 16 84 8a a4 e9 44 89 97 0b 00 00 04 cc a8 |.......D........| +00000030 00 ff 01 00 00 58 00 0b 00 04 03 00 01 02 00 0a |.....X..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000050 00 00 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e |.............0..| +00000060 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000070 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................| +00000080 03 01 02 01 03 02 02 02 04 02 05 02 06 02 |..............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| +00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............| +00000040 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0| +00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............| +00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..| +00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.| +00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....| +00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010| +000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101| +000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U| +000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...| +000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...| +000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......| +000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.| +00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B| +00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[.....y.@.Om..+.| +00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t| +00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l| +00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.| +00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....| +00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.| +00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U| +00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U| +00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.| +000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...| +000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..| +000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...| +000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{| +000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa| +00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*| +00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0| +00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(| +00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C| +00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..| +00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.| +00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.| +00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |.Cw.......@.a.Lr| +00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B| +00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....| +000002a0 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G| +000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 89 |......_X.;t.....| +000002d0 f8 62 c5 1a ba 78 74 da 6f 96 76 00 0f 6b a9 fb |.b...xt.o.v..k..| +000002e0 83 d4 52 c0 80 0b 81 02 e3 b0 07 c2 9d ff b4 cc |..R.............| +000002f0 ea 2e c7 82 91 35 74 ef 1e 9a ba 78 3e 60 6c 86 |.....5t....x>`l.| +00000300 1d b0 14 52 84 84 70 ce 66 22 31 66 e2 53 04 bd |...R..p.f"1f.S..| +00000310 4d 2b 5e 86 8b 79 dc 17 7a 4f bc 62 5a 21 a1 f6 |M+^..y..zO.bZ!..| +00000320 46 1a 12 aa 7a 98 25 02 97 a8 9c 71 a4 4a 5b 28 |F...z.%....q.J[(| +00000330 c8 11 6a 5f f1 b3 13 a7 f2 26 12 59 02 fa 28 e2 |..j_.....&.Y..(.| +00000340 ba 8c c0 cd 50 c6 60 db 69 9a a1 92 12 26 23 16 |....P.`.i....&#.| +00000350 03 03 00 04 0e 00 00 00 |........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 ba 1b c8 ae 22 78 |....%...! ...."x| +00000010 84 ba d8 1c b3 87 52 f0 bf 13 76 2b a5 47 37 13 |......R...v+.G7.| +00000020 30 89 01 13 1a cb 63 ea b3 37 14 03 03 00 01 01 |0.....c..7......| +00000030 16 03 03 00 20 ac d7 79 45 e6 65 1d 20 1a 95 5e |.... ..yE.e. ..^| +00000040 68 f7 0f ee 8c 3f 3d 0b bc 58 31 aa 46 d7 e3 00 |h....?=..X1.F...| +00000050 7b 10 8c 01 5d |{...]| +>>> Flow 4 (server to client) +00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c f8 79 c6 |o...Q...h.B.L.y.| +00000040 80 85 74 9c 35 6f 4e 9d 60 0b a2 28 b0 45 b6 f6 |..t.5oN.`..(.E..| +00000050 71 a3 f6 a6 95 71 cd 1e 53 e9 58 9f 94 18 ac d6 |q....q..S.X.....| +00000060 6b 03 ba ac b4 4f c2 02 cc 1c 5b 88 84 49 38 16 |k....O....[..I8.| +00000070 d9 5e b8 11 ab c6 f8 a7 9d 5d 58 99 b1 b6 8a be |.^.......]X.....| +00000080 4e 9e 40 3d 00 22 11 25 c7 51 8e cb d2 10 d4 7d |N.@=.".%.Q.....}| +00000090 14 03 03 00 01 01 16 03 03 00 20 ff 4b 1e 87 3e |.......... .K..>| +000000a0 05 5c b4 3e e4 b9 5c 47 f0 a2 0b 67 47 89 c6 48 |.\.>..\G...gG..H| +000000b0 d5 e3 73 d2 00 44 56 e4 8d b6 fb 17 03 03 00 1d |..s..DV.........| +000000c0 58 28 94 02 c2 a9 99 3d b6 0b de 9c fd 52 61 bf |X(.....=.....Ra.| +000000d0 55 c0 12 7f be a8 52 98 d7 99 a5 d0 60 15 03 03 |U.....R.....`...| +000000e0 00 12 26 44 ad f0 a7 56 e5 23 6f 1b 7a 7e f8 e4 |..&D...V.#o.z~..| +000000f0 42 49 5d 1d |BI].| diff --git a/src/crypto/tls/testdata/Server-TLSv12-IssueTicket b/src/crypto/tls/testdata/Server-TLSv12-IssueTicket new file mode 100644 index 0000000..f70c759 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-IssueTicket @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 71 01 00 00 6d 03 03 3d 21 91 3a 4e |....q...m..=!.:N| +00000010 8e cd 65 eb 0f 1c ae 2a 58 40 4c 38 22 c9 46 2c |..e....*X@L8".F,| +00000020 b8 cd dd 38 ad c6 4b a7 60 a9 56 00 00 04 00 2f |...8..K.`.V..../| +00000030 00 ff 01 00 00 40 00 23 00 00 00 16 00 00 00 17 |.....@.#........| +00000040 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 |.....0..........| +00000050 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 |................| +00000060 05 01 06 01 03 03 02 03 03 01 02 01 03 02 02 02 |................| +00000070 04 02 05 02 06 02 |......| +>>> Flow 2 (server to client) +00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 59 0b |..#...........Y.| +00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| +00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| +00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| +00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| +00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| +00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| +000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| +000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| +000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| +000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| +000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| +000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| +00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| +00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| +00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| +00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| +00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| +00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| +00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| +00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| +00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| +00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| +000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| +000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| +000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| +000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| +000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| +000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| +00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| +00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| +00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| +00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| +00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | +00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| +00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| +00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| +00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e 00 00 |.\!.;...........| +000002a0 00 |.| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 1d 1a 1a b8 f4 |................| +00000010 05 77 7a 96 2b 5f 50 7f 1e 69 14 be 40 ad 0c c9 |.wz.+_P..i..@...| +00000020 7e df 2f 1d aa 74 ee b4 a5 05 fa 05 e1 85 a4 87 |~./..t..........| +00000030 59 6a d1 e4 98 ce df e3 a5 82 98 77 c2 c4 fc 2f |Yj.........w.../| +00000040 ec 1d 2e 96 0c 27 12 0d 64 ba 58 90 ff 7d d1 27 |.....'..d.X..}.'| +00000050 9a b9 b5 fb 1d 76 6f 3e af f8 70 a3 cc 53 95 98 |.....vo>..p..S..| +00000060 2c 7e a9 42 25 e5 3a e2 55 3f 19 57 6b 83 43 6a |,~.B%.:.U?.Wk.Cj| +00000070 93 34 2c 6e cb 4e 9d 25 8b 4d 7d d7 cc e1 16 59 |.4,n.N.%.M}....Y| +00000080 2a 95 60 e4 31 0e df 7f cb 9d b7 14 03 03 00 01 |*.`.1...........| +00000090 01 16 03 03 00 40 28 33 df 69 4f 4c 48 b1 fb 8d |.....@(3.iOLH...| +000000a0 3f 3c d2 81 7c 33 cf 21 6a f7 d6 43 82 22 5b de |?<..|3.!j..C."[.| +000000b0 46 7f 7b e2 39 23 bd 39 fa 03 bd 11 9d a8 a2 84 |F.{.9#.9........| +000000c0 4a 90 1a ab e1 b4 23 9f 72 d0 97 9e 05 5c 47 2b |J.....#.r....\G+| +000000d0 7a 53 bb ec a0 07 |zS....| +>>> Flow 4 (server to client) +00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6f 2c 9f 83 51 ed 14 ef 68 ca 42 c5 4c 75 5e a5 |o,..Q...h.B.Lu^.| +00000040 6f d2 49 61 e4 fb 83 46 7c 4c ab f9 c6 d1 3c 9e |o.Ia...F|L....<.| +00000050 5b 8d d8 bc c0 a5 2d 84 db 24 dd a0 16 60 1d 87 |[.....-..$...`..| +00000060 a0 52 88 25 6c c6 8e 5b 71 0f 74 c3 48 49 38 16 |.R.%l..[q.t.HI8.| +00000070 92 8c de 77 bd 8a 2b 45 4d 58 86 40 b1 d6 0f 99 |...w..+EMX.@....| +00000080 de 27 41 b2 41 27 aa fe 26 e9 24 91 2a 00 ff 08 |.'A.A'..&.$.*...| +00000090 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +000000a0 00 00 00 00 00 00 00 00 00 00 00 fc cd 6b 01 90 |.............k..| +000000b0 7b 0c 31 54 a0 3a 8b f7 ba 45 e7 e0 df 9a 59 6d |{.1T.:...E....Ym| +000000c0 83 b6 b2 c8 93 d8 d9 b6 fe 19 56 51 75 a3 ea 0e |..........VQu...| +000000d0 f4 4b 64 27 66 fc 19 7b 7e 13 e7 17 03 03 00 40 |.Kd'f..{~......@| +000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000000f0 c2 1b 6f f1 1e 05 1b 8a 19 16 67 00 0f dc a8 a2 |..o.......g.....| +00000100 00 56 49 0a bb c5 df 7e 96 0c 5c db a0 f4 3e b4 |.VI....~..\...>.| +00000110 30 3e b6 f0 16 dd d4 ed c9 de 64 49 00 9b 51 dc |0>........dI..Q.| +00000120 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +00000130 00 00 00 00 00 e1 9d 08 1a 2e 9a 0f 84 6d 4e e5 |.............mN.| +00000140 2c 50 b9 28 5d 88 ea bb 48 4d af 26 7f 82 0b 56 |,P.(]...HM.&...V| +00000150 c5 87 71 2a e7 |..q*.| diff --git a/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable b/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable new file mode 100644 index 0000000..8cb57f5 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 71 01 00 00 6d 03 03 e1 40 35 c8 5c |....q...m...@5.\| +00000010 71 63 3f 5a 00 42 e6 3e 64 62 b8 c4 e7 e7 ba 98 |qc?Z.B.>db......| +00000020 d8 fa 2c b5 65 f7 50 db 43 d9 70 00 00 04 00 2f |..,.e.P.C.p..../| +00000030 00 ff 01 00 00 40 00 23 00 00 00 16 00 00 00 17 |.....@.#........| +00000040 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 |.....0..........| +00000050 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 |................| +00000060 05 01 06 01 03 03 02 03 03 01 02 01 03 02 02 02 |................| +00000070 04 02 05 02 06 02 |......| +>>> Flow 2 (server to client) +00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 59 0b |..#...........Y.| +00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| +00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| +00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| +00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| +00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| +00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| +000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| +000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| +000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| +000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| +000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| +000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| +00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| +00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| +00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| +00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| +00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| +00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| +00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| +00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| +00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| +00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| +000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| +000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| +000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| +000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| +000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| +000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| +00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| +00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| +00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| +00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| +00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | +00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| +00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| +00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| +00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e 00 00 |.\!.;...........| +000002a0 00 |.| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 4f ce 06 88 66 |...........O...f| +00000010 dd e1 0a 55 ef fb 1b 9e 70 62 8b 3b 0d e4 19 0f |...U....pb.;....| +00000020 4f 16 c9 79 92 9c 4d 16 21 ea 43 d7 58 7f 35 65 |O..y..M.!.C.X.5e| +00000030 a3 15 7a 8d b5 6e 9b f6 73 19 c2 0c 58 be 9d 8a |..z..n..s...X...| +00000040 5a a8 be f3 89 48 64 28 6a 7f be b7 4a 58 93 af |Z....Hd(j...JX..| +00000050 c0 ff 8a ae 01 34 1f cf 7b b0 7a 5e 69 19 43 fa |.....4..{.z^i.C.| +00000060 21 b8 dc ee 0e ab 3b 81 c9 b9 be b9 56 a0 dd 62 |!.....;.....V..b| +00000070 02 45 14 54 4d 05 5a cc 31 68 1f 17 91 a6 0e d7 |.E.TM.Z.1h......| +00000080 5a f3 ae bb 5e 90 1d c3 c9 56 2a 14 03 03 00 01 |Z...^....V*.....| +00000090 01 16 03 03 00 40 a1 34 07 ef 45 42 d2 88 bb 6e |.....@.4..EB...n| +000000a0 7f 3a 2a 39 67 3f 90 76 95 b7 cc 86 b6 1a 6c c6 |.:*9g?.v......l.| +000000b0 da 8f 26 f3 34 6c 1f 6f 05 11 39 40 00 46 00 be |..&.4l.o..9@.F..| +000000c0 8f 3a af 86 d6 6d 5d 00 f3 5d 22 1c 31 2c 24 ee |.:...m]..]".1,$.| +000000d0 e5 11 ba 94 5f b1 |...._.| +>>> Flow 4 (server to client) +00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6f 2c 9f 83 51 ed 14 ef 68 ca 42 c5 4c 20 33 6c |o,..Q...h.B.L 3l| +00000040 01 97 a5 69 44 bf 8f ea db 83 05 fb ef cc 51 1f |...iD.........Q.| +00000050 0b 4d 44 77 89 11 cf c8 38 16 67 ea a2 3e 8b 2a |.MDw....8.g..>.*| +00000060 18 f2 f7 25 ce e0 d8 4c 93 31 b0 59 23 49 38 16 |...%...L.1.Y#I8.| +00000070 3a f9 63 9e 61 21 1b ab 67 09 6a 23 07 8e d0 4a |:.c.a!..g.j#...J| +00000080 19 78 9c 1e 60 40 a7 83 c5 9a 48 41 35 c4 e9 63 |.x..`@....HA5..c| +00000090 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +000000a0 00 00 00 00 00 00 00 00 00 00 00 b8 46 07 9e 14 |............F...| +000000b0 85 ba 6d e0 f1 f5 99 43 80 9a 54 6b 33 1e 4f c1 |..m....C..Tk3.O.| +000000c0 88 b7 3d 60 04 d4 e9 b0 b2 6d c4 1a ca 3b 9f 83 |..=`.....m...;..| +000000d0 28 5f ea b2 54 e4 11 78 69 de 1a 17 03 03 00 40 |(_..T..xi......@| +000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000000f0 55 34 ad ae 9b 37 df cd 88 ae fc 6a ac c5 cf 16 |U4...7.....j....| +00000100 ec f1 bc 22 1e d2 c1 52 5e a2 e7 d2 6e 37 7a 29 |..."...R^...n7z)| +00000110 c8 b9 d4 7d 81 63 1a f0 53 d9 10 fd 4f 3d 1c dd |...}.c..S...O=..| +00000120 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +00000130 00 00 00 00 00 8f f2 11 0d 93 99 83 29 d4 10 a4 |............)...| +00000140 7c bb 26 7b 24 f1 15 3a 9b 81 0e cb 0a 51 4b 39 ||.&{$..:.....QK9| +00000150 69 1d e5 38 5e |i..8^| diff --git a/src/crypto/tls/testdata/Server-TLSv12-P256 b/src/crypto/tls/testdata/Server-TLSv12-P256 new file mode 100644 index 0000000..58b9bed --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-P256 @@ -0,0 +1,86 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 8f 01 00 00 8b 03 03 49 de 51 77 8e |...........I.Qw.| +00000010 58 03 e9 25 0b 9a 88 ef 35 2d 35 a8 30 29 22 61 |X..%....5-5.0)"a| +00000020 ae b4 af 8a a1 2c 45 59 40 5f aa 00 00 04 c0 2f |.....,EY@_...../| +00000030 00 ff 01 00 00 5e 00 00 00 0e 00 0c 00 00 09 31 |.....^.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 04 00 02 00 17 00 16 00 00 00 17 00 00 |................| +00000060 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 |...0............| +00000070 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 |................| +00000080 06 01 03 03 02 03 03 01 02 01 03 02 02 02 04 02 |................| +00000090 05 02 06 02 |....| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 c0 2f 00 00 |...DOWNGRD.../..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 cd 0c |.`.\!.;.........| +000002a0 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 |......A...7...Q.| +000002b0 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 |5uq..T[....g..$ | +000002c0 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f |>.V...(^.+-O....| +000002d0 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 |lK[.V.2B.X..I..h| +000002e0 1a 41 03 56 6b dc 5a 89 08 04 00 80 7b bd 89 a1 |.A.Vk.Z.....{...| +000002f0 d8 9d cf e4 75 ac 15 60 a9 49 0c c7 68 61 4e e4 |....u..`.I..haN.| +00000300 2b 51 37 5a 65 38 a4 52 6a d0 4f 8b 76 93 a4 7c |+Q7Ze8.Rj.O.v..|| +00000310 ac 30 6b 89 f1 c7 88 8f f3 5c c7 e9 d6 7c 33 94 |.0k......\...|3.| +00000320 f7 fc f8 69 35 f3 f7 e0 ea fc 51 5c b2 e2 dc 9e |...i5.....Q\....| +00000330 57 03 af e6 19 0d 0d e4 25 b6 52 19 12 ad 35 fc |W.......%.R...5.| +00000340 7f c3 6a 1f ed 06 82 34 81 13 d7 c1 67 a9 18 88 |..j....4....g...| +00000350 2f bb 00 54 5d d9 01 16 29 dd 03 3c 69 f7 46 52 |/..T]...)..>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 a6 c3 8d d1 32 |....F...BA.....2| +00000010 8e b4 ac 27 75 4a 57 26 7f 6a 52 a7 82 ee c2 b1 |...'uJW&.jR.....| +00000020 a3 68 0a 8d 09 ff 82 61 57 f3 32 5e ec 1a 2f 20 |.h.....aW.2^../ | +00000030 8c c1 d4 cf 27 7b f0 1d f9 5d f6 24 80 6a 45 d2 |....'{...].$.jE.| +00000040 97 cf f1 5d a2 e3 b0 15 7d e6 a4 14 03 03 00 01 |...]....}.......| +00000050 01 16 03 03 00 28 21 36 fe 82 d2 4a b4 da f8 14 |.....(!6...J....| +00000060 d6 d6 8c be 56 1f ca 82 7f 20 bb 01 be fb 2a 0d |....V.... ....*.| +00000070 a8 31 ee 79 f7 8a 8b 4a 1b a7 66 3a 89 67 |.1.y...J..f:.g| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....| +00000010 00 00 00 00 0a 97 89 c3 74 09 63 25 2a fc e1 29 |........t.c%*..)| +00000020 18 b1 bc d6 75 2e 3b 2a fb 90 17 b9 b8 ea e2 c4 |....u.;*........| +00000030 29 94 16 17 03 03 00 25 00 00 00 00 00 00 00 01 |)......%........| +00000040 8c 30 76 b7 fd b1 96 0b 2a 8f f3 e1 b3 38 16 15 |.0v.....*....8..| +00000050 10 3d 32 ee 29 b5 12 cb cb cf 98 a3 c5 15 03 03 |.=2.)...........| +00000060 00 1a 00 00 00 00 00 00 00 02 9e 4a 55 8e 91 ff |...........JU...| +00000070 13 0b 56 be 3c 5d b8 26 42 f1 c8 28 |..V.<].&B..(| diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES b/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES new file mode 100644 index 0000000..17a5ad0 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES @@ -0,0 +1,80 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 97 01 00 00 93 03 03 e2 8f 43 82 4c |.............C.L| +00000010 13 33 88 d2 53 5d b6 02 d2 b6 b2 a1 11 f0 30 14 |.3..S]........0.| +00000020 41 1e 8c 79 85 38 75 cd e8 a6 a7 00 00 04 00 0a |A..y.8u.........| +00000030 00 ff 01 00 00 66 00 00 00 0e 00 0c 00 00 09 31 |.....f.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 |...........0....| +00000070 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +00000080 08 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 |................| +00000090 02 01 03 02 02 02 04 02 05 02 06 02 |............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 0a 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 57 ce 41 c0 4d |...........W.A.M| +00000010 b1 69 27 6e cb 92 a5 71 52 85 e7 a8 69 b0 31 d1 |.i'n...qR...i.1.| +00000020 0a b0 3d a6 9d ab 04 e8 a2 4c d8 67 95 97 da 63 |..=......L.g...c| +00000030 f7 0b 6e 62 29 5b 8b cf 77 f1 80 a5 1f 67 08 71 |..nb)[..w....g.q| +00000040 50 c3 a9 90 ea b8 11 3d 5d c9 f5 1c 37 fa 67 b1 |P......=]...7.g.| +00000050 64 b0 04 3e c1 0d db 77 fe b9 a0 ea f2 0f 1d af |d..>...w........| +00000060 9a 77 b3 96 4f 3f 3c 52 a7 ed c4 3f 48 ef ff f8 |.w..O?>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 30 00 00 00 00 00 |..........0.....| +00000010 00 00 00 0d 0f 3c 6a 28 f0 97 90 1a c3 7e c8 63 |...........su.| +00000070 15 03 03 00 20 00 00 00 00 00 00 00 00 5c 30 63 |.... ........\0c| +00000080 23 55 26 ee 8d 81 9a 2e b4 e7 38 6b 04 e7 42 43 |#U&.......8k..BC| +00000090 50 de 1e 40 2d |P..@-| diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES new file mode 100644 index 0000000..0196e21 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 97 01 00 00 93 03 03 dd 28 eb 68 4a |............(.hJ| +00000010 8a 71 d2 98 d0 2d 21 c7 e9 19 19 de c8 13 0b 67 |.q...-!........g| +00000020 f4 ff 4c d0 37 f5 72 9f 2d fb b3 00 00 04 00 2f |..L.7.r.-....../| +00000030 00 ff 01 00 00 66 00 00 00 0e 00 0c 00 00 09 31 |.....f.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 |...........0....| +00000070 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +00000080 08 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 |................| +00000090 02 01 03 02 02 02 04 02 05 02 06 02 |............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 c0 37 ef f3 d9 |............7...| +00000010 6b 7b 3f c4 9f 46 d2 6b 8f 7f 8d ce 89 cf 8e 2b |k{?..F.k.......+| +00000020 1f 0d 86 f9 90 5a 23 28 6c d3 14 ce 2a 0b f1 0e |.....Z#(l...*...| +00000030 96 1c 11 7d c0 b8 fb 4b 2e cb 07 1c fe b9 e1 62 |...}...K.......b| +00000040 2c 38 1c 46 21 74 23 a9 f2 0b 15 36 ef 88 32 e8 |,8.F!t#....6..2.| +00000050 28 66 8e ab 14 be e9 02 04 9d 92 99 cc 6e 28 d0 |(f...........n(.| +00000060 f9 3d dc 61 7f f7 17 59 ab 1c 86 94 9a 28 7b 46 |.=.a...Y.....({F| +00000070 3c 36 ff d3 26 3c ad 2d 33 ef 99 83 09 a5 a8 2f |<6..&<.-3....../| +00000080 b3 a3 74 7f 49 a3 f1 47 7d 8c 12 14 03 03 00 01 |..t.I..G}.......| +00000090 01 16 03 03 00 40 32 68 cb ea 32 cb f2 7a 0e 4b |.....@2h..2..z.K| +000000a0 63 72 96 93 e8 2d 5b 22 a6 3a 05 9d 60 50 e5 d0 |cr...-[".:..`P..| +000000b0 f3 f8 14 ed 81 fe 17 a0 ee 3f 7b aa ca dc 06 bc |.........?{.....| +000000c0 28 90 73 33 84 0c 92 39 b7 cb da 06 08 05 0b 03 |(.s3...9........| +000000d0 86 be cc 70 0e c2 |...p..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 10 a0 48 48 86 |.............HH.| +00000020 ac 1f f4 05 4d 12 9d 90 54 26 ec c8 1f 6d e7 d5 |....M...T&...m..| +00000030 0c 92 61 88 2f 43 77 75 0c 08 0f 33 ac c3 d3 b0 |..a./Cwu...3....| +00000040 94 68 e3 3f 9f c9 43 a5 8b ee ed 17 03 03 00 40 |.h.?..C........@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 fd 7d d3 d6 3f a5 10 37 a1 93 20 ca c8 8c 9d c3 |.}..?..7.. .....| +00000070 90 df 2f 40 e6 83 af b6 be e4 3d 07 ff 0d 24 97 |../@......=...$.| +00000080 c2 ff af 81 eb b5 91 72 6b 6d 70 8c af 3f 9f 76 |.......rkmp..?.v| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 6b 80 aa 88 45 8c 39 a8 4c ca 33 |.....k...E.9.L.3| +000000b0 f2 33 85 a0 74 6a 64 a3 43 17 4c 5c 9b 50 e5 8d |.3..tjd.C.L\.P..| +000000c0 ff 26 03 e1 07 |.&...| diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM new file mode 100644 index 0000000..fa4b47b --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM @@ -0,0 +1,82 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 97 01 00 00 93 03 03 8a ca f1 8f ad |................| +00000010 fe 0b a3 e1 b8 08 10 1a 40 57 b6 f7 f7 e3 72 c4 |........@W....r.| +00000020 57 4a 71 f8 30 cd 62 62 c7 0f 2d 00 00 04 c0 2f |WJq.0.bb..-..../| +00000030 00 ff 01 00 00 66 00 00 00 0e 00 0c 00 00 09 31 |.....f.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 |...........0....| +00000070 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +00000080 08 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 |................| +00000090 02 01 03 02 02 02 04 02 05 02 06 02 |............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 c0 2f 00 00 |...DOWNGRD.../..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c |.`.\!.;.........| +000002a0 00 00 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 |...... /.}.G.bC.| +000002b0 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| +000002c0 90 99 5f 58 cb 3b 74 08 04 00 80 50 0b d9 1c 03 |.._X.;t....P....| +000002d0 6f 08 05 a6 39 cc 9f 7e 3d f1 fb af 8e 0b 9a ef |o...9..~=.......| +000002e0 39 d3 b6 e3 71 9c 5a 37 a1 86 f2 f0 59 01 fc b2 |9...q.Z7....Y...| +000002f0 51 1c 0e 22 42 24 3e c6 db fb a1 39 9d 75 f4 79 |Q.."B$>....9.u.y| +00000300 55 dd e5 99 0b 22 5b ed c7 19 ac db ed d3 ee 23 |U...."[........#| +00000310 b9 37 2b 51 ea 7f 39 4d 8b 0a bc a2 2e f2 ef 9e |.7+Q..9M........| +00000320 a5 8c 99 77 ff d2 fb 46 e4 10 4e a9 b2 a9 ce b6 |...w...F..N.....| +00000330 50 d4 0a 28 a5 3f 0e 2c 60 cd 0f 07 9c 7e 60 c3 |P..(.?.,`....~`.| +00000340 79 a5 cf f3 cd 77 5a 16 8d fc 14 16 03 03 00 04 |y....wZ.........| +00000350 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 ef 3b b1 d2 a3 f6 |....%...! .;....| +00000010 be f2 fc 2e b5 ed d3 ec 6a fb 2f 0d 5a 04 98 61 |........j./.Z..a| +00000020 92 26 59 ba 17 26 1b 60 27 2b 14 03 03 00 01 01 |.&Y..&.`'+......| +00000030 16 03 03 00 28 e2 94 22 bb 71 70 c8 a6 63 e5 6f |....(..".qp..c.o| +00000040 2e 00 0f b9 bf 6b 54 34 dc ce b0 12 0b 16 e5 ac |.....kT4........| +00000050 8f 6b 1e 96 a1 e3 86 b7 6f 8c 76 09 da |.k......o.v..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....| +00000010 00 00 00 f5 dc 00 28 06 03 50 9b b2 db 4d 89 25 |......(..P...M.%| +00000020 3a 94 04 85 5b 7a 3f 16 fb 55 8f e0 c3 a3 33 21 |:...[z?..U....3!| +00000030 65 84 c5 17 03 03 00 25 00 00 00 00 00 00 00 01 |e......%........| +00000040 a9 35 62 24 4b 63 6e 62 1c 8f 99 e4 e0 3e f0 a2 |.5b$Kcnb.....>..| +00000050 e3 02 34 6f 10 71 9c 6b b3 4a 2d 7f 71 15 03 03 |..4o.q.k.J-.q...| +00000060 00 1a 00 00 00 00 00 00 00 02 91 43 07 98 b1 ba |...........C....| +00000070 06 1b dd 21 46 82 63 67 8b bb 1f b5 |...!F.cg....| diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384 b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384 new file mode 100644 index 0000000..2cc2c28 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384 @@ -0,0 +1,82 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 97 01 00 00 93 03 03 0f 13 d8 49 94 |..............I.| +00000010 b9 cc 41 1d d4 3d bb d2 c9 a3 2c 74 11 ca 01 e8 |..A..=....,t....| +00000020 5b b0 2e 57 60 b5 30 37 2d b9 f0 00 00 04 c0 30 |[..W`.07-......0| +00000030 00 ff 01 00 00 66 00 00 00 0e 00 0c 00 00 09 31 |.....f.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 |...........0....| +00000070 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +00000080 08 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 |................| +00000090 02 01 03 02 02 02 04 02 05 02 06 02 |............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 c0 30 00 00 |...DOWNGRD...0..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c |.`.\!.;.........| +000002a0 00 00 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 |...... /.}.G.bC.| +000002b0 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| +000002c0 90 99 5f 58 cb 3b 74 08 04 00 80 40 f3 67 86 41 |.._X.;t....@.g.A| +000002d0 93 17 f7 db b2 80 ca 73 f9 f8 45 24 cc 46 57 47 |.......s..E$.FWG| +000002e0 28 83 19 df e8 63 e7 19 c4 a2 04 85 25 7d ec 55 |(....c......%}.U| +000002f0 91 d4 df eb 77 53 c2 3b d5 71 1a f7 39 d2 ee b4 |....wS.;.q..9...| +00000300 06 4b e4 07 b7 fa 8a 8e fa 64 22 83 dd 22 8b b8 |.K.......d".."..| +00000310 4d a5 1a f5 e3 81 01 81 6a a1 6e 62 54 3a 3a 09 |M.......j.nbT::.| +00000320 ed 76 f2 5a d3 4e 4b 74 be 46 50 0d 51 77 34 f6 |.v.Z.NKt.FP.Qw4.| +00000330 02 ef 57 39 29 bf d9 64 ad 65 06 ae a6 8d 94 86 |..W9)..d.e......| +00000340 84 76 cf 2c 36 98 04 5b a1 59 6c 16 03 03 00 04 |.v.,6..[.Yl.....| +00000350 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 d5 2b 0e 3c e9 3e |....%...! .+.<.>| +00000010 e9 b0 3d 86 a9 85 b5 68 af cf 27 cf 4b d4 49 2e |..=....h..'.K.I.| +00000020 68 f2 9e 3c 32 7c cb fb dc 57 14 03 03 00 01 01 |h..<2|...W......| +00000030 16 03 03 00 28 5a cc f4 77 38 94 46 7b 39 5d 81 |....(Z..w8.F{9].| +00000040 be 77 a5 4a 76 c9 46 62 17 0b 2b ea 89 c2 29 bd |.w.Jv.Fb..+...).| +00000050 4b b0 dd 51 1e b8 7b a9 55 f5 fb b3 6a |K..Q..{.U...j| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....| +00000010 00 00 00 b9 9b c0 b1 2b 71 af 0b 44 4e 4a cd e8 |.......+q..DNJ..| +00000020 c6 68 b8 2a d9 67 6f 7f 18 12 22 5c 4b 5c ca 43 |.h.*.go..."\K\.C| +00000030 ff c1 9d 17 03 03 00 25 00 00 00 00 00 00 00 01 |.......%........| +00000040 3c ae 33 dd 69 6c 01 a0 d2 a7 91 52 43 f3 78 38 |<.3.il.....RC.x8| +00000050 94 f4 24 0b 3d c9 bb 5f 02 27 89 bb 9b 15 03 03 |..$.=.._.'......| +00000060 00 1a 00 00 00 00 00 00 00 02 68 8d d7 d8 2f 95 |..........h.../.| +00000070 61 09 59 52 0d b8 12 fc 6a 07 28 37 |a.YR....j.(7| diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 new file mode 100644 index 0000000..47a4ef2 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 @@ -0,0 +1,76 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 97 01 00 00 93 03 03 2c 3c 18 04 94 |...........,<...| +00000010 e0 bb 10 99 7c 0c cd 0e e7 72 bc 83 4d f0 cf d7 |....|....r..M...| +00000020 4b 8e 2c 8b 52 bf ed 86 65 d2 a3 00 00 04 00 05 |K.,.R...e.......| +00000030 00 ff 01 00 00 66 00 00 00 0e 00 0c 00 00 09 31 |.....f.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 |...........0....| +00000070 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +00000080 08 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 |................| +00000090 02 01 03 02 02 02 04 02 05 02 06 02 |............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 05 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 a2 43 45 e6 1e |............CE..| +00000010 08 d3 29 62 0b 40 75 98 a3 f6 68 d7 78 31 b0 c9 |..)b.@u...h.x1..| +00000020 f4 f8 a6 98 dc d8 72 c1 2a 68 80 26 54 1c 16 af |......r.*h.&T...| +00000030 9f 67 cf ee 74 de 9e 29 b6 cd 0d eb df aa ea 44 |.g..t..).......D| +00000040 72 c9 aa fc ff c9 2d 9d bf bc f0 9b c1 7b 0d 5c |r.....-......{.\| +00000050 69 0c 75 d8 23 09 29 97 f6 38 9c f9 4f 1b 4a d5 |i.u.#.)..8..O.J.| +00000060 bd 04 d4 15 b3 a6 80 02 a4 11 32 d7 c0 cf 89 1f |..........2.....| +00000070 93 80 2b 48 49 51 44 b7 77 3c bf b1 a6 87 a3 ff |..+HIQD.w<......| +00000080 39 37 4a 42 49 92 93 25 0a 51 9a 14 03 03 00 01 |97JBI..%.Q......| +00000090 01 16 03 03 00 24 b5 c9 d6 9c ec 77 38 d2 30 79 |.....$.....w8.0y| +000000a0 f1 00 77 31 78 9b e6 ab ed 46 7c c6 e5 26 0b 44 |..w1x....F|..&.D| +000000b0 fd 30 b0 fe 0c 84 6f 9a cf 57 |.0....o..W| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 58 cc 9f 3f ac |..........$X..?.| +00000010 2e 20 73 c9 5e 13 d3 12 3a 63 1e a9 ee 13 3d 0d |. s.^...:c....=.| +00000020 51 e9 15 5b 7b 33 92 85 6c fa d6 8a 15 16 dc 17 |Q..[{3..l.......| +00000030 03 03 00 21 bc af 01 72 48 0c 16 c9 7a c0 3c 27 |...!...rH...z.<'| +00000040 63 0a f8 34 e4 54 6a 39 39 61 02 bc c2 a0 07 03 |c..4.Tj99a......| +00000050 fb 2c d0 1b 6a 15 03 03 00 16 98 71 13 a6 5d f5 |.,..j......q..].| +00000060 7d aa 6d 05 2d a2 dc c0 7b 41 88 36 a2 49 a4 8b |}.m.-...{A.6.I..| diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPKCS1v15 b/src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPKCS1v15 new file mode 100644 index 0000000..b193771 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPKCS1v15 @@ -0,0 +1,77 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 59 01 00 00 55 03 03 60 c3 e9 6a 99 |....Y...U..`..j.| +00000010 72 7a 1c b9 1e 10 4b 9a 82 d5 ea b9 b0 6f 1e 05 |rz....K......o..| +00000020 74 a4 35 bb 71 c7 d2 56 87 b8 69 00 00 04 cc a8 |t.5.q..V..i.....| +00000030 00 ff 01 00 00 28 00 0b 00 04 03 00 01 02 00 0a |.....(..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000050 00 00 00 17 00 00 00 0d 00 04 00 02 04 01 |..............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c |.`.\!.;.........| +000002a0 00 00 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 |...... /.}.G.bC.| +000002b0 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| +000002c0 90 99 5f 58 cb 3b 74 04 01 00 80 4e c9 fd 39 89 |.._X.;t....N..9.| +000002d0 52 c1 6b ba 3b c9 02 35 89 e8 e3 f8 41 15 ee 6d |R.k.;..5....A..m| +000002e0 f6 08 6d 1a 47 aa 3b 5c 1d 9b 42 9b 50 85 af 56 |..m.G.;\..B.P..V| +000002f0 a3 99 78 84 7f 06 91 97 e9 33 0d 1d 9b 17 ce 3b |..x......3.....;| +00000300 30 f2 d0 10 1c b6 e2 7d fd b3 e1 bc 14 7a 1a 96 |0......}.....z..| +00000310 be b9 dc 0d 29 33 84 5f d1 77 91 0a a1 f2 2b cc |....)3._.w....+.| +00000320 dc 5e 9b f9 8b e3 34 d2 bd f3 46 b4 0d 97 de 44 |.^....4...F....D| +00000330 aa 83 10 82 bd ca 83 27 d0 40 a7 b1 64 15 dd 84 |.......'.@..d...| +00000340 5f 3c d9 62 42 0d 8f a6 19 0f b1 16 03 03 00 04 |_<.bB...........| +00000350 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 82 3a 50 41 f7 b1 |....%...! .:PA..| +00000010 0f 97 ba 38 04 db f3 a6 ec 8b d1 db 06 c1 84 89 |...8............| +00000020 a0 53 84 92 27 a2 53 e8 5d 21 14 03 03 00 01 01 |.S..'.S.]!......| +00000030 16 03 03 00 20 7d 80 6d 7f a9 28 d6 0d 50 d6 b4 |.... }.m..(..P..| +00000040 24 d3 92 f8 0b 8e 6b d8 7c 64 9e 6c 87 a9 8e 37 |$.....k.|d.l...7| +00000050 9e 1b 0b 2d a5 |...-.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 e4 58 cf fb 81 |.......... .X...| +00000010 be dd 5b 98 97 bd bd 6a f0 76 92 b6 bb 2c 8f a3 |..[....j.v...,..| +00000020 e5 52 5b 1d f4 17 7b 2a a8 40 26 17 03 03 00 1d |.R[...{*.@&.....| +00000030 58 ef 4f 1d 98 0f 3d 59 88 df 6e ac c9 37 43 d5 |X.O...=Y..n..7C.| +00000040 f5 58 b3 7a 62 a3 7d 26 a2 a2 80 23 ef 15 03 03 |.X.zb.}&...#....| +00000050 00 12 05 b8 57 6a 80 71 b6 a4 58 94 15 f4 2f 0c |....Wj.q..X.../.| +00000060 8e 76 b2 aa |.v..| diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPSS b/src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPSS new file mode 100644 index 0000000..af4c069 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-RSAPSS @@ -0,0 +1,77 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 5b 01 00 00 57 03 03 e0 83 fd ef f8 |....[...W.......| +00000010 cb 41 23 14 36 21 07 eb 4e 01 7d 80 63 e4 b9 45 |.A#.6!..N.}.c..E| +00000020 f0 84 72 71 9b ac 60 49 6c 70 74 00 00 04 cc a8 |..rq..`Ilpt.....| +00000030 00 ff 01 00 00 2a 00 0b 00 04 03 00 01 02 00 0a |.....*..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000050 00 00 00 17 00 00 00 0d 00 06 00 04 08 06 08 04 |................| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c |.`.\!.;.........| +000002a0 00 00 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 |...... /.}.G.bC.| +000002b0 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| +000002c0 90 99 5f 58 cb 3b 74 08 04 00 80 58 d3 5f 28 bc |.._X.;t....X._(.| +000002d0 50 79 b9 3d f1 ac a1 af 52 cd d3 fd e7 75 47 c3 |Py.=....R....uG.| +000002e0 65 3a 6f 62 22 c2 b5 cc 2b 22 f3 5d 3f b5 b6 9e |e:ob"...+".]?...| +000002f0 57 bf c7 4e 08 bd fb 5a 17 13 09 1a e9 6c b6 ce |W..N...Z.....l..| +00000300 b2 0e 88 ae ba a3 a0 b5 2c ff 51 b5 87 95 14 09 |........,.Q.....| +00000310 6d 9c 73 3f f0 c7 40 6b 4c ca 40 96 d6 44 96 d0 |m.s?..@kL.@..D..| +00000320 6f b1 a0 1c 4f 66 cc 9b 4f 85 98 3c 03 68 e3 a8 |o...Of..O..<.h..| +00000330 5b 28 04 fb 1e be 9e 2a 66 c1 6e f1 2e a4 20 08 |[(.....*f.n... .| +00000340 7e 11 78 7b fc c4 43 af 2a b4 8b 16 03 03 00 04 |~.x{..C.*.......| +00000350 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 e2 54 7d 82 d2 8d |....%...! .T}...| +00000010 b8 d6 87 17 ec 2a 64 4e 15 6b b0 b3 01 66 b0 7d |.....*dN.k...f.}| +00000020 73 20 9f cb 30 9d 3c 27 ac 13 14 03 03 00 01 01 |s ..0.<'........| +00000030 16 03 03 00 20 fa a0 b7 eb ef 49 97 d5 da f0 9d |.... .....I.....| +00000040 85 a6 e6 67 f3 30 e8 f0 82 3a 7a c4 3f 76 f6 c5 |...g.0...:z.?v..| +00000050 8f d3 a5 65 f3 |...e.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 6b cf 58 e1 52 |.......... k.X.R| +00000010 e3 2c 05 e6 a3 05 c1 36 02 f0 90 63 bb 86 0f 54 |.,.....6...c...T| +00000020 61 d7 1a 31 7d bd 08 00 22 71 09 17 03 03 00 1d |a..1}..."q......| +00000030 4a 8e 05 28 e3 77 31 43 be ac 32 c6 af f2 7b 1c |J..(.w1C..2...{.| +00000040 ab 11 7f 32 5a 6a eb 76 ac c6 eb f1 dc 15 03 03 |...2Zj.v........| +00000050 00 12 3a f1 ee a3 6f bf 9b 9e 5e b8 20 76 84 bc |..:...o...^. v..| +00000060 1e 2e a0 87 |....| diff --git a/src/crypto/tls/testdata/Server-TLSv12-Resume b/src/crypto/tls/testdata/Server-TLSv12-Resume new file mode 100644 index 0000000..456fe2a --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-Resume @@ -0,0 +1,46 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 12 01 00 01 0e 03 03 90 27 78 df 71 |............'x.q| +00000010 d3 0e ce 1d de ec d2 1b 70 e0 89 da 98 a9 45 3e |........p.....E>| +00000020 9c ee 93 90 8f 61 d0 a3 b4 a4 5a 20 9d cd d4 81 |.....a....Z ....| +00000030 e2 c0 59 81 21 bc 9f 2a 84 3e 91 15 3e b9 c0 a1 |..Y.!..*.>..>...| +00000040 e0 6b 73 9c 45 53 03 ad b9 e6 c2 77 00 04 00 2f |.ks.ES.....w.../| +00000050 00 ff 01 00 00 c1 00 23 00 81 50 46 ad c1 db a8 |.......#..PF....| +00000060 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 00 |8.{+....B>......| +00000070 00 00 00 00 00 00 00 00 00 00 94 6f 2c 9f 83 51 |...........o,..Q| +00000080 ed 14 ef 68 ca 42 c5 4c 75 5e a5 6f d2 49 61 e4 |...h.B.Lu^.o.Ia.| +00000090 fb 83 46 7c 4c ab f9 c6 d1 3c 9e 5b 8d d8 bc c0 |..F|L....<.[....| +000000a0 a5 2d 84 db 24 dd a0 16 60 1d 87 a0 52 88 25 6c |.-..$...`...R.%l| +000000b0 c6 8e 5b 71 0f 74 c3 48 49 38 16 92 8c de 77 bd |..[q.t.HI8....w.| +000000c0 8a 2b 45 4d 58 86 40 b1 d6 0f 99 de 27 41 b2 41 |.+EMX.@.....'A.A| +000000d0 27 aa fe 26 e9 24 91 2a 00 ff 08 00 16 00 00 00 |'..&.$.*........| +000000e0 17 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 |......0.........| +000000f0 07 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 04 |................| +00000100 01 05 01 06 01 03 03 02 03 03 01 02 01 03 02 02 |................| +00000110 02 04 02 05 02 06 02 |.......| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 00 00 00 00 00 |....Q...M.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 20 9d cd d4 81 |...DOWNGRD. ....| +00000030 e2 c0 59 81 21 bc 9f 2a 84 3e 91 15 3e b9 c0 a1 |..Y.!..*.>..>...| +00000040 e0 6b 73 9c 45 53 03 ad b9 e6 c2 77 00 2f 00 00 |.ks.ES.....w./..| +00000050 05 ff 01 00 01 00 14 03 03 00 01 01 16 03 03 00 |................| +00000060 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@...............| +00000070 00 57 8e 5f 0a f6 3f 3b 43 f1 33 bc ef 5e c6 8d |.W._..?;C.3..^..| +00000080 86 92 58 58 71 51 e8 54 57 96 5f bd 36 3a 9f d3 |..XXqQ.TW._.6:..| +00000090 e9 27 01 bf fb 6a 05 57 de 2d db b2 79 38 72 95 |.'...j.W.-..y8r.| +000000a0 fd |.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 16 03 03 00 40 6d 3c 76 31 a4 |..........@m.5v...K.| +00000020 01 f8 a8 83 0c eb 58 f7 d6 93 c6 b6 40 0e c8 24 |......X.....@..$| +00000030 46 58 0c 79 4a c6 b4 15 65 1e 9c bd ff 51 4d d0 |FX.yJ...e....QM.| +00000040 44 66 fe c0 98 d5 26 11 98 cf 52 |Df....&...R| +>>> Flow 4 (server to client) +00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| +00000010 00 00 00 00 00 4e 8e bd e5 c8 d4 1a 14 00 f1 ed |.....N..........| +00000020 c4 88 b3 5c 92 b9 ad 8a 68 d4 f3 85 1b 02 25 aa |...\....h.....%.| +00000030 a0 65 49 08 0d 2a b4 0a 64 eb ea ab 06 73 08 ca |.eI..*..d....s..| +00000040 62 c9 56 45 a9 15 03 03 00 30 00 00 00 00 00 00 |b.VE.....0......| +00000050 00 00 00 00 00 00 00 00 00 00 60 51 ae 81 79 6d |..........`Q..ym| +00000060 91 95 02 42 30 3f c4 3c 2b fc 74 47 a7 a9 17 22 |...B0?.<+.tG..."| +00000070 88 26 6d 18 b9 8f ad 43 e3 b0 |.&m....C..| diff --git a/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled b/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled new file mode 100644 index 0000000..339fd9a --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 12 01 00 01 0e 03 03 b8 aa 9b e6 98 |................| +00000010 be 93 d6 03 f2 cd 62 23 76 dd 74 6c 48 ac 9a f6 |......b#v.tlH...| +00000020 f3 27 62 93 6e 99 b2 0d 54 af b7 20 2d 20 97 9a |.'b.n...T.. - ..| +00000030 c8 88 50 65 95 2a 02 8f 7b 47 77 6d 3c 49 ba a9 |..Pe.*..{Gwm......| +00000070 00 00 00 00 00 00 00 00 00 00 94 6f 2c 9f 83 51 |...........o,..Q| +00000080 ed 14 ef 68 ca 42 c5 4c 20 33 6c 01 97 a5 69 44 |...h.B.L 3l...iD| +00000090 bf 8f ea db 83 05 fb ef cc 51 1f 0b 4d 44 77 89 |.........Q..MDw.| +000000a0 11 cf c8 38 16 67 ea a2 3e 8b 2a 18 f2 f7 25 ce |...8.g..>.*...%.| +000000b0 e0 d8 4c 93 31 b0 59 23 49 38 16 3a f9 63 9e 61 |..L.1.Y#I8.:.c.a| +000000c0 21 1b ab 67 09 6a 23 07 8e d0 4a 19 78 9c 1e 60 |!..g.j#...J.x..`| +000000d0 40 a7 83 c5 9a 48 41 35 c4 e9 63 00 16 00 00 00 |@....HA5..c.....| +000000e0 17 00 00 00 0d 00 30 00 2e 04 03 05 03 06 03 08 |......0.........| +000000f0 07 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 04 |................| +00000100 01 05 01 06 01 03 03 02 03 03 01 02 01 03 02 02 |................| +00000110 02 04 02 05 02 06 02 |.......| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| +00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| +00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| +00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.| +00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..| +00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..| +00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..| +000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1| +000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.| +000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...| +000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0| +000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.| +000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6| +00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.| +00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....| +00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......| +00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$| +00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..| +00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u| +00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.| +00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........| +00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.| +00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......| +000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.| +000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>| +000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#| +000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..| +000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0| +000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan| +00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........| +00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...| +00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1| +00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d| +00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..| +00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....| +00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......| +00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..| +00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.| +00000290 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 1f e2 43 ee 88 |.............C..| +00000010 22 0d a0 66 18 ce 8a 04 d1 00 fc 2b 6b 93 d5 b6 |"..f.......+k...| +00000020 fd 13 48 fd ea 19 d8 5d 02 bf 8c d9 fb 64 e8 17 |..H....].....d..| +00000030 a3 49 dc 1d 4d b7 8c eb 7d 8b 1d 13 20 78 4e 02 |.I..M...}... xN.| +00000040 49 7e a5 bd dd 57 ac 45 47 e6 ea 2e 87 6f d2 ca |I~...W.EG....o..| +00000050 e6 ef a4 9e 2d 3a 02 22 2e 67 6f ff 2d 78 6c 7d |....-:.".go.-xl}| +00000060 33 a1 4c 5b ec d5 ae cb 4f db c0 7d 75 01 61 fa |3.L[....O..}u.a.| +00000070 c2 8a dc 75 77 51 60 90 5d 35 45 ca 13 bb 1a c4 |...uwQ`.]5E.....| +00000080 eb f3 74 ef 77 ec 23 ec 98 30 3c 14 03 03 00 01 |..t.w.#..0<.....| +00000090 01 16 03 03 00 40 7a 07 bc 74 d3 6f ef 93 22 69 |.....@z..t.o.."i| +000000a0 a8 05 df df db 5e 58 1e 4b 84 4f 20 7c f5 2c c3 |.....^X.K.O |.,.| +000000b0 0d 51 0a a8 d0 a8 f0 07 02 d5 ca ec f2 4b 3f ef |.Q...........K?.| +000000c0 c9 57 cb 9b 26 2e 62 e7 f2 84 6e ed b9 6e 1d 15 |.W..&.b...n..n..| +000000d0 32 8c d6 b8 0d 8a |2.....| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 67 e1 22 17 24 |...........g.".$| +00000020 95 b4 e5 62 59 15 56 4a af e4 82 76 ad b7 48 81 |...bY.VJ...v..H.| +00000030 cf 55 d1 75 cd 36 86 0d 9d 15 24 4b 84 23 bc 98 |.U.u.6....$K.#..| +00000040 8e c4 62 57 ab 96 0c 27 5d 1c 07 17 03 03 00 40 |..bW...']......@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 c9 b2 0e 04 40 43 26 92 91 45 e3 63 d7 49 09 3e |....@C&..E.c.I.>| +00000070 03 45 e3 d6 af a2 d8 d9 61 36 e5 95 83 75 66 fa |.E......a6...uf.| +00000080 90 c2 80 53 a2 d5 31 aa b1 2a da 45 a9 b3 aa 1f |...S..1..*.E....| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 c4 52 cf b9 f6 0f e2 30 ba 90 18 |......R.....0...| +000000b0 0c 76 c2 ee 4c 78 fb c2 cb 34 7f cb 35 15 5e b0 |.v..Lx...4..5.^.| +000000c0 17 70 cb 76 8a |.p.v.| diff --git a/src/crypto/tls/testdata/Server-TLSv12-SNI b/src/crypto/tls/testdata/Server-TLSv12-SNI new file mode 100644 index 0000000..0ea8375 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-SNI @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 99 01 00 00 95 03 03 fb d6 71 b2 32 |.............q.2| +00000010 74 6c e1 56 19 42 e6 46 a2 0e 37 1f ad 96 4b af |tl.V.B.F..7...K.| +00000020 8b 4c aa 71 2a 53 d8 df 74 7d 39 00 00 04 00 2f |.L.q*S..t}9..../| +00000030 00 ff 01 00 00 68 00 00 00 10 00 0e 00 00 0b 73 |.....h.........s| +00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 0b 00 04 03 00 |nitest.com......| +00000050 01 02 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 |................| +00000060 00 18 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e |.............0..| +00000070 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000080 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................| +00000090 03 01 02 01 03 02 02 02 04 02 05 02 06 02 |..............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 a4 48 88 75 7b |............H.u{| +00000010 a2 04 19 14 69 30 12 d6 14 00 0c 44 e4 68 06 c6 |....i0.....D.h..| +00000020 11 56 53 0c e5 52 fb 84 e2 6e b7 c6 eb 0d 79 25 |.VS..R...n....y%| +00000030 19 f0 bf e4 51 73 85 d5 82 5a 07 53 b2 65 97 6a |....Qs...Z.S.e.j| +00000040 a1 1b 56 bb 23 35 15 83 0f 60 ee de 16 a2 ea 61 |..V.#5...`.....a| +00000050 23 10 e1 5e cf 73 fe 5d 5a 53 16 42 0c 29 a5 ff |#..^.s.]ZS.B.)..| +00000060 06 e5 c4 87 11 d6 24 91 25 e5 58 81 40 80 9e 71 |......$.%.X.@..q| +00000070 49 40 47 50 37 28 7b ed 76 cc 5a fb 04 ba 9c f8 |I@GP7({.v.Z.....| +00000080 be ce 87 07 75 d2 30 88 09 cf bc 14 03 03 00 01 |....u.0.........| +00000090 01 16 03 03 00 40 60 1c 31 95 7d c2 a9 9b 29 c2 |.....@`.1.}...).| +000000a0 ef 59 58 dd fb 26 34 81 60 dc 17 19 c1 23 8d 8f |.YX..&4.`....#..| +000000b0 a8 d2 62 31 96 3d d2 61 b9 c8 7e bf 47 4c 04 fd |..b1.=.a..~.GL..| +000000c0 7c 30 05 37 8e 03 df 13 a1 4d f1 81 05 d7 4c 49 ||0.7.....M....LI| +000000d0 88 d6 c0 21 52 e3 |...!R.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 73 15 54 76 ad |...........s.Tv.| +00000020 c4 38 b0 40 45 32 a8 ca 05 19 bd ce 6e 39 77 6b |.8.@E2......n9wk| +00000030 46 a7 f8 45 a8 cd cd 98 8c aa cf 46 83 f0 20 93 |F..E.......F.. .| +00000040 0d 18 99 d4 2a f9 15 4a 2b f6 bf 17 03 03 00 40 |....*..J+......@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 79 8d 24 ef 72 b3 2c e2 10 a5 6d 3d 61 6c df c1 |y.$.r.,...m=al..| +00000070 26 bf 7e b5 cd b2 8e 87 b9 54 bf ee 35 07 bc 55 |&.~......T..5..U| +00000080 6c cd a2 d3 b4 bb 8c 63 fd ef b1 f0 2f 6d aa d9 |l......c..../m..| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 7b f7 81 e6 5c f2 5c 9d 45 ec 1f |.....{...\.\.E..| +000000b0 7b 0d f8 62 19 d4 83 a8 e5 90 71 03 6e 6a 72 4b |{..b......q.njrK| +000000c0 7e 64 c4 c4 1a |~d...| diff --git a/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate b/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate new file mode 100644 index 0000000..199253f --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 99 01 00 00 95 03 03 cf 09 e7 0d ce |................| +00000010 ce d4 72 66 9d 30 e8 ee 39 b3 95 4c 3b 59 25 66 |..rf.0..9..L;Y%f| +00000020 d2 f5 d3 82 68 7d e7 26 2e 38 97 00 00 04 00 2f |....h}.&.8...../| +00000030 00 ff 01 00 00 68 00 00 00 10 00 0e 00 00 0b 73 |.....h.........s| +00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 0b 00 04 03 00 |nitest.com......| +00000050 01 02 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 |................| +00000060 00 18 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e |.............0..| +00000070 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000080 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................| +00000090 03 01 02 01 03 02 02 02 04 02 05 02 06 02 |..............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 04 57 b2 56 f0 |............W.V.| +00000010 a5 fb c3 4d 4e 7d ba 29 18 04 ea 6e 66 d3 97 68 |...MN}.)...nf..h| +00000020 58 4e c1 47 fe 30 42 4d bf 5b 10 38 6a 01 83 98 |XN.G.0BM.[.8j...| +00000030 2b e3 3a ac c8 67 e5 41 0c 5c 3f 88 d5 15 a2 ab |+.:..g.A.\?.....| +00000040 6a 2b 70 24 d8 40 78 c1 d9 58 78 04 4d 90 03 eb |j+p$.@x..Xx.M...| +00000050 3c b1 61 da 26 62 db b3 41 ab dc 94 22 44 66 b8 |<.a.&b..A..."Df.| +00000060 49 2c fa 59 de c0 69 3c 20 f8 2f a5 e0 47 1d ec |I,.Y..i< ./..G..| +00000070 3c 49 2d 39 f6 41 09 06 79 5f 26 c4 12 3d 9c 8d |>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 5e ea d1 03 d7 |...........^....| +00000020 de 82 9a b4 07 52 46 16 fd 28 86 fe 17 2e 77 52 |.....RF..(....wR| +00000030 67 8f ec 64 93 1e 8e c9 fc fb 69 61 47 78 1a 1b |g..d......iaGx..| +00000040 97 8d fc 56 76 f6 53 8b 62 53 4f 17 03 03 00 40 |...Vv.S.bSO....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 f8 17 e8 ba c4 fb 0b 76 f5 a8 2d 3c 48 44 73 da |.......v..->> Flow 1 (client to server) +00000000 16 03 01 00 99 01 00 00 95 03 03 34 7d 89 eb 2a |...........4}..*| +00000010 19 64 32 17 5d 37 0e dd 51 2c 7e 08 56 47 f3 2c |.d2.]7..Q,~.VG.,| +00000020 ca d0 08 51 86 a6 a3 10 85 5a 41 00 00 04 00 2f |...Q.....ZA..../| +00000030 00 ff 01 00 00 68 00 00 00 10 00 0e 00 00 0b 73 |.....h.........s| +00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 0b 00 04 03 00 |nitest.com......| +00000050 01 02 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 |................| +00000060 00 18 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e |.............0..| +00000070 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000080 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03 |................| +00000090 03 01 02 01 03 02 02 02 04 02 05 02 06 02 |..............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 00 2f 00 00 |...DOWNGRD.../..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e |.`.\!.;.........| +000002a0 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 38 86 92 3e 9a |...........8..>.| +00000010 54 2d 44 46 76 d1 7c 07 04 83 2f 19 6d 89 c6 95 |T-DFv.|.../.m...| +00000020 07 63 17 7d ac e5 f7 95 7f f7 f2 3a f6 eb 38 26 |.c.}.......:..8&| +00000030 e5 c9 32 b1 27 88 46 85 f8 f6 eb 27 a8 9e de 5b |..2.'.F....'...[| +00000040 92 f7 3f 03 be 73 f0 de 2e b4 44 a8 89 4a 5a 6f |..?..s....D..JZo| +00000050 dc e7 16 9c dc f7 9f ca 40 9e 34 4b c2 45 58 7a |........@.4K.EXz| +00000060 6d 5c 4c 58 6a 45 10 21 fb b5 2a 58 17 7d d9 c4 |m\LXjE.!..*X.}..| +00000070 c9 7d d1 3b df 39 1b 59 6a 49 18 e1 fd 02 a2 1d |.}.;.9.YjI......| +00000080 5a 2d 3d c5 ab e7 f6 60 0d aa 38 14 03 03 00 01 |Z-=....`..8.....| +00000090 01 16 03 03 00 40 0e 2a fd e7 cd d0 72 ce 06 5c |.....@.*....r..\| +000000a0 40 c1 81 ef eb 27 e9 77 a8 d4 cc 5c 1e 15 7c 62 |@....'.w...\..|b| +000000b0 87 bd c5 8e b4 e6 6a 3f be 37 9d c0 fe f7 65 8b |......j?.7....e.| +000000c0 b1 3a b8 b4 76 67 ca 58 1c f5 3f f1 10 7c 5b 57 |.:..vg.X..?..|[W| +000000d0 90 e6 43 de d6 25 |..C..%| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +00000010 00 00 00 00 00 00 00 00 00 00 00 8b 11 9a 67 af |..............g.| +00000020 5b 0e c9 01 dc 76 e8 48 2f 40 5c 76 13 ca 28 63 |[....v.H/@\v..(c| +00000030 a9 6d 3c 6b c1 d4 79 4d 39 17 55 a5 b9 0e b6 fd |.m.| +000000c0 b2 ea 47 71 1f |..Gq.| diff --git a/src/crypto/tls/testdata/Server-TLSv12-X25519 b/src/crypto/tls/testdata/Server-TLSv12-X25519 new file mode 100644 index 0000000..c196336 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv12-X25519 @@ -0,0 +1,82 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 8f 01 00 00 8b 03 03 5d ff d6 27 db |...........]..'.| +00000010 3b e5 2b 79 3a a6 cf 75 3d f7 c9 d9 0a d4 8c b2 |;.+y:..u=.......| +00000020 af 3c 29 84 65 a2 d6 98 52 e2 eb 00 00 04 c0 2f |.<).e...R....../| +00000030 00 ff 01 00 00 5e 00 00 00 0e 00 0c 00 00 09 31 |.....^.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 04 00 02 00 1d 00 16 00 00 00 17 00 00 |................| +00000060 00 0d 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 |...0............| +00000070 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 |................| +00000080 06 01 03 03 02 03 03 01 02 01 03 02 02 02 04 02 |................| +00000090 05 02 06 02 |....| +>>> Flow 2 (server to client) +00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 c0 2f 00 00 |...DOWNGRD.../..| +00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| +00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| +00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| +00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| +00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| +00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| +00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| +000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| +000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| +000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| +000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| +000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| +00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| +00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| +00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| +00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| +00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | +00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| +00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| +00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| +00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| +00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| +000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| +000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| +000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| +000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| +000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| +000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| +00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| +00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| +00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| +00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| +00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| +00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| +00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| +00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| +00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| +00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c |.`.\!.;.........| +000002a0 00 00 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 |...... /.}.G.bC.| +000002b0 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| +000002c0 90 99 5f 58 cb 3b 74 08 04 00 80 73 d6 a4 35 5f |.._X.;t....s..5_| +000002d0 3f 46 ad de 81 13 a8 d9 21 17 25 37 61 cb 62 0d |?F......!.%7a.b.| +000002e0 e2 bf 95 51 0e 9e e7 b1 ab bc be f6 ec 80 b1 f4 |...Q............| +000002f0 3e 9c 69 3f c8 1e a4 02 82 fd 57 01 e7 0c 18 be |>.i?......W.....| +00000300 c6 1b 01 68 cb ef dc d8 16 92 fb 1b 07 fd 98 f8 |...h............| +00000310 00 77 a9 8e 71 2a e0 6c 68 d5 83 f9 36 c3 3b 99 |.w..q*.lh...6.;.| +00000320 44 98 a0 96 00 1a 02 95 c5 7c ea ae 51 81 89 94 |D........|..Q...| +00000330 57 b6 37 c5 88 56 9f 49 bf 36 26 48 08 36 a1 69 |W.7..V.I.6&H.6.i| +00000340 48 a2 c4 b2 6f 0f 43 70 91 1e 8a 16 03 03 00 04 |H...o.Cp........| +00000350 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 0a 1b 78 c4 bb eb |....%...! ..x...| +00000010 a4 01 33 3b 69 95 c2 06 5d c9 3e b3 13 51 4b 93 |..3;i...].>..QK.| +00000020 5e 3c 3e a7 42 12 22 e8 7e 49 14 03 03 00 01 01 |^<>.B.".~I......| +00000030 16 03 03 00 28 fc c7 a1 45 50 e0 fe 27 fd ac a4 |....(...EP..'...| +00000040 d8 a2 c6 54 df e1 d3 6f e7 d8 45 a6 57 16 2f 1f |...T...o..E.W./.| +00000050 cf 89 26 c6 0a c3 4f 63 df ac bc c9 79 |..&...Oc....y| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....| +00000010 00 00 00 37 25 28 76 4e 31 dd 5e b0 5b 39 87 fc |...7%(vN1.^.[9..| +00000020 0f 10 3c bc 6d 12 9a dd 59 89 0b 09 bc f2 2c d8 |..<.m...Y.....,.| +00000030 05 a7 77 17 03 03 00 25 00 00 00 00 00 00 00 01 |..w....%........| +00000040 fe 79 9d dd d9 e3 bc 48 47 65 30 64 c7 74 82 0a |.y.....HGe0d.t..| +00000050 9f b7 45 a2 62 40 b5 dd 79 b9 ce 06 83 15 03 03 |..E.b@..y.......| +00000060 00 1a 00 00 00 00 00 00 00 02 58 ed 37 40 33 e4 |..........X.7@3.| +00000070 75 f0 a6 fa 14 f5 6b 93 9e 54 f2 a4 |u.....k..T..| diff --git a/src/crypto/tls/testdata/Server-TLSv13-AES128-SHA256 b/src/crypto/tls/testdata/Server-TLSv13-AES128-SHA256 new file mode 100644 index 0000000..a071f60 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-AES128-SHA256 @@ -0,0 +1,100 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 dc 01 00 00 d8 03 03 5f b5 79 18 5f |..........._.y._| +00000010 d2 f8 b0 fc da 39 90 af e1 ba 04 b5 70 86 c3 6b |.....9......p..k| +00000020 ba b4 87 e3 81 9a 86 02 9b 26 44 20 21 e3 5b 03 |.........&D !.[.| +00000030 0d 0a 6c 1f 71 ea b4 4c 56 aa b6 d1 e8 91 d6 7b |..l.q..LV......{| +00000040 59 12 63 af db d2 69 80 cd 5f 62 22 00 04 13 01 |Y.c...i.._b"....| +00000050 00 ff 01 00 00 8b 00 00 00 0e 00 0c 00 00 09 31 |...............1| +00000060 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000070 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000080 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 |................| +00000090 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +000000a0 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 |...........+....| +000000b0 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 |..-.....3.&.$...| +000000c0 20 57 12 bc 06 e0 46 c7 75 43 b8 af f9 c1 f6 b8 | W....F.uC......| +000000d0 e4 1e 13 6b 02 07 23 d2 e6 89 ec 18 ab c0 9f ae |...k..#.........| +000000e0 69 |i| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 21 e3 5b 03 |........... !.[.| +00000030 0d 0a 6c 1f 71 ea b4 4c 56 aa b6 d1 e8 91 d6 7b |..l.q..LV......{| +00000040 59 12 63 af db d2 69 80 cd 5f 62 22 13 01 00 00 |Y.c...i.._b"....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 be 8f 95 d9 22 d7 |..............".| +00000090 f7 ff 75 78 b6 9c bc 93 23 2f 76 62 c6 cd c6 92 |..ux....#/vb....| +000000a0 fe 17 03 03 02 6d 31 54 c9 32 d0 38 53 8f f0 15 |.....m1T.2.8S...| +000000b0 03 42 16 39 71 61 f9 17 f2 da c5 2e 4c 19 c3 30 |.B.9qa......L..0| +000000c0 d5 c6 b8 ea 5d 3b 47 1b d9 20 31 64 ab 5c f3 00 |....];G.. 1d.\..| +000000d0 43 5b e7 3b 36 69 12 c9 3b 3d e7 4f 91 72 e4 29 |C[.;6i..;=.O.r.)| +000000e0 93 54 65 50 88 07 b9 e2 ed 5e 18 f7 00 0a 49 e5 |.TeP.....^....I.| +000000f0 19 cc d8 e5 b2 c5 f6 bd 34 7a 7f e2 f1 7c 9d a0 |........4z...|..| +00000100 d6 0c 50 4f 80 8a c5 a1 fe b8 2e 54 7c 0c ae 48 |..PO.......T|..H| +00000110 c5 ff 46 d9 45 e6 c0 df 61 74 fc d5 e8 ec e1 84 |..F.E...at......| +00000120 0b c8 df 73 77 e4 9f 13 e5 52 e5 0b d8 9f 65 b7 |...sw....R....e.| +00000130 89 d5 04 74 f8 8d a6 2a c7 a1 76 ff 27 85 6a bb |...t...*..v.'.j.| +00000140 ee 86 c9 38 5a 54 bc ac bc ad 79 85 7c 26 65 c3 |...8ZT....y.|&e.| +00000150 36 97 56 76 d2 4c 55 32 71 82 ec d1 81 22 46 9e |6.Vv.LU2q...."F.| +00000160 75 d8 55 a8 1e 61 10 c8 dc e8 c7 ad fe 96 0e 54 |u.U..a.........T| +00000170 1c 79 0c 41 b9 98 b0 44 f8 45 6e c7 b3 41 68 2d |.y.A...D.En..Ah-| +00000180 ea 73 be 55 99 fe 88 02 e3 5d 0f f3 d1 70 9a 5e |.s.U.....]...p.^| +00000190 be e7 80 96 6c 94 7f 9f ec 1c b6 24 28 ef 90 95 |....l......$(...| +000001a0 d5 5b d4 7b 1b b1 a4 9c 66 09 11 23 ad f5 87 ee |.[.{....f..#....| +000001b0 0b 1f e5 d2 0e 57 16 e9 14 ae 0f 98 9b a1 bc 9e |.....W..........| +000001c0 68 dc d0 fb 76 aa c8 f2 bc e5 d3 ff e2 85 df 01 |h...v...........| +000001d0 2f ad 72 78 85 0f f7 0a 64 a4 cd 61 2a e6 2b a3 |/.rx....d..a*.+.| +000001e0 d5 4a c9 08 00 af 5c 6c 9d 35 e4 1e 7c 32 1a d0 |.J....\l.5..|2..| +000001f0 f3 6d 73 16 9c c8 72 28 4b 67 cf d8 ff 2b 1e 33 |.ms...r(Kg...+.3| +00000200 18 c4 ed c9 31 5d 6a 0f c5 05 bf 08 eb 0b 44 05 |....1]j.......D.| +00000210 83 49 40 d2 1f 7f 5c 08 ef 98 1f 09 f1 09 33 02 |.I@...\.......3.| +00000220 56 04 66 53 69 93 ef 07 0d 8a e7 84 b5 03 b9 78 |V.fSi..........x| +00000230 bb 52 84 3f bb 4e d3 f9 c4 8a 2a d1 59 02 59 36 |.R.?.N....*.Y.Y6| +00000240 88 52 6a 9d 1f 7e c1 5b a6 8a a4 cc 42 f4 44 59 |.Rj..~.[....B.DY| +00000250 ca d2 fa 0e 09 5f 25 e5 cc 27 55 8b 16 b5 f1 62 |....._%..'U....b| +00000260 aa f7 a9 bc 7a 36 fa 16 34 b7 ce 2d b8 bd 67 f0 |....z6..4..-..g.| +00000270 75 15 17 c4 49 81 55 b1 5a e0 d2 b8 45 79 d0 16 |u...I.U.Z...Ey..| +00000280 71 21 01 57 ad 10 48 1f 0d bf 43 da b7 c9 a8 93 |q!.W..H...C.....| +00000290 88 af be 2d 65 a0 81 26 23 de fe e2 a3 9c f6 40 |...-e..&#......@| +000002a0 96 f9 a1 21 0b fe 31 7f 24 ec 75 ae cf b0 8c a7 |...!..1.$.u.....| +000002b0 fe f8 2f ee 60 65 72 5c 86 a6 45 22 11 55 62 29 |../.`er\..E".Ub)| +000002c0 02 8b b5 ff 4b f8 73 71 3d 8c c3 37 68 2d 2c 24 |....K.sq=..7h-,$| +000002d0 b7 dc be 5a 37 d8 25 3b b6 16 e6 2a e9 80 48 0b |...Z7.%;...*..H.| +000002e0 77 be 05 35 b2 86 97 51 49 31 ac de 85 eb a9 a8 |w..5...QI1......| +000002f0 74 1d 00 07 4c 1b 8c a5 ec 1b b5 7a 57 84 da 40 |t...L......zW..@| +00000300 10 6c c9 ed b3 43 06 81 11 e2 84 3c 4c ae 22 6b |.l...C.....Y.3| +00000420 76 f0 23 23 27 94 df 2f 21 6a c0 a9 5a 3d af 41 |v.##'../!j..Z=.A| +00000430 31 4d 9b d5 75 57 f1 a9 c5 57 2a 7a c7 1d b1 a7 |1M..uW...W*z....| +00000440 15 a5 80 ae 63 f8 85 92 46 13 d2 31 26 62 7d 83 |....c...F..1&b}.| +00000450 95 f9 97 9d e8 86 7d 09 f3 cc 30 b1 db 54 2a 8d |......}...0..T*.| +00000460 0f 04 da d9 cf 59 52 2a e3 7d 64 20 f3 26 4a 2e |.....YR*.}d .&J.| +00000470 74 07 c5 2f 98 a2 f7 e1 53 01 e0 c2 3b c7 42 1b |t../....S...;.B.| +00000480 a0 48 12 |.H.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 57 4a c4 5a c1 |..........5WJ.Z.| +00000010 3a b9 ae f0 1d e8 8f 31 38 0e 64 9e 61 13 e6 b2 |:......18.d.a...| +00000020 1b 02 aa b6 46 5a 50 97 07 93 86 13 dc 3d 76 6a |....FZP......=vj| +00000030 67 01 1b 18 9b 7e 21 b2 c1 d4 a5 25 22 4d 14 dc |g....~!....%"M..| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 61 63 5a 22 d2 e6 8e e8 8e 69 7d |.....acZ".....i}| +00000010 24 69 a5 b8 e3 59 98 ac 64 0b 34 6b 16 60 92 db |$i...Y..d.4k.`..| +00000020 6b 62 45 17 03 03 00 13 b7 12 c6 59 fe 23 f4 6c |kbE........Y.#.l| +00000030 a6 d3 8d 59 1b 40 60 72 d6 97 b4 |...Y.@`r...| diff --git a/src/crypto/tls/testdata/Server-TLSv13-AES256-SHA384 b/src/crypto/tls/testdata/Server-TLSv13-AES256-SHA384 new file mode 100644 index 0000000..60aa82d --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-AES256-SHA384 @@ -0,0 +1,103 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 dc 01 00 00 d8 03 03 70 b7 07 12 16 |...........p....| +00000010 50 d7 b9 c9 5f 02 47 2d ff 93 a7 2f e8 51 dc a0 |P..._.G-.../.Q..| +00000020 8f 0d c8 80 38 c7 af 7e da bb ed 20 67 73 58 d7 |....8..~... gsX.| +00000030 11 8b c6 0d 72 86 e0 08 3e 2d d9 b9 16 9f 85 6e |....r...>-.....n| +00000040 3c 87 fd 87 c3 95 f6 4c 76 21 50 af 00 04 13 02 |<......Lv!P.....| +00000050 00 ff 01 00 00 8b 00 00 00 0e 00 0c 00 00 09 31 |...............1| +00000060 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000070 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000080 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 |................| +00000090 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +000000a0 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 |...........+....| +000000b0 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 |..-.....3.&.$...| +000000c0 20 f4 08 51 f6 69 b7 d6 a9 3e 18 a7 ee c0 30 f3 | ..Q.i...>....0.| +000000d0 13 63 52 40 30 7c 79 6c 24 03 c9 89 25 bd a4 5f |.cR@0|yl$...%.._| +000000e0 64 |d| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 67 73 58 d7 |........... gsX.| +00000030 11 8b c6 0d 72 86 e0 08 3e 2d d9 b9 16 9f 85 6e |....r...>-.....n| +00000040 3c 87 fd 87 c3 95 f6 4c 76 21 50 af 13 02 00 00 |<......Lv!P.....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 cc b9 e4 43 5e f6 |.............C^.| +00000090 9a 5a 62 14 02 39 fb 13 76 e8 10 db 26 1c 07 ec |.Zb..9..v...&...| +000000a0 06 17 03 03 02 6d 39 e9 a0 33 ee 39 36 54 62 f1 |.....m9..3.96Tb.| +000000b0 e9 1d 32 45 0f 5a ca 72 f7 7e 43 d8 89 97 00 3d |..2E.Z.r.~C....=| +000000c0 59 70 08 b4 d1 e1 84 24 7a b8 45 3c b8 32 93 b5 |Yp.....$z.E<.2..| +000000d0 51 a5 58 60 3f 60 52 aa c1 ff 85 fb fd 50 87 38 |Q.X`?`R......P.8| +000000e0 47 7a 88 c6 d1 e6 3c b3 16 14 5b cb 23 50 26 7a |Gz....<...[.#P&z| +000000f0 1d 28 d1 d2 29 5d b0 40 97 2f 3b 58 7c 8a 76 1f |.(..)].@./;X|.v.| +00000100 1c c1 d2 2b 63 9d 53 bc fb c2 42 cb 40 0d d0 7c |...+c.S...B.@..|| +00000110 73 6c dc 63 90 89 e3 66 67 2b a2 70 af e0 af fe |sl.c...fg+.p....| +00000120 0c c0 db 41 76 d0 16 37 2a 09 7a 79 31 03 c6 4a |...Av..7*.zy1..J| +00000130 f4 06 22 ac 96 b4 25 1f 54 11 24 c8 67 22 8f 2a |.."...%.T.$.g".*| +00000140 56 0c 24 fa 20 ed a8 37 66 f7 38 44 43 e2 e6 e3 |V.$. ..7f.8DC...| +00000150 96 b5 d5 dd a5 2c 23 e4 57 57 7d 7a 59 e2 4f 66 |.....,#.WW}zY.Of| +00000160 c4 29 d6 d1 32 a3 9c 4c dd 63 b2 a6 dc ff 6f 61 |.)..2..L.c....oa| +00000170 c2 db 88 80 23 c1 27 d4 be dd 4f b4 c9 b8 56 4c |....#.'...O...VL| +00000180 65 b6 f8 32 b2 60 7b af 5f 54 71 61 20 db 25 85 |e..2.`{._Tqa .%.| +00000190 34 b6 58 9b 71 01 dd 53 cd 13 65 2e 23 69 96 0e |4.X.q..S..e.#i..| +000001a0 89 94 75 09 64 60 76 d2 65 85 38 3d f1 0e cb 47 |..u.d`v.e.8=...G| +000001b0 c1 2c 52 f8 ce 7a a6 9f dd 7c 39 7e a7 f9 a6 1b |.,R..z...|9~....| +000001c0 c1 23 81 a6 7a b1 6c d4 3c 1c f3 71 ce 72 24 01 |.#..z.l.<..q.r$.| +000001d0 4a 8d e9 24 47 51 73 67 dc 7a 9f 0b 63 7d 29 e1 |J..$GQsg.z..c}).| +000001e0 3e 5e ac 72 d7 c8 d9 c2 13 de 92 dd 04 cb 09 21 |>^.r...........!| +000001f0 ad 41 69 27 77 48 eb 87 cb 3b 23 ba 06 a3 68 96 |.Ai'wH...;#...h.| +00000200 ad 24 35 f6 a6 03 87 a7 4d 9f d4 bf e5 8b 9f 56 |.$5.....M......V| +00000210 54 dd 0e 08 da 29 ff eb 9b e1 0a a5 25 b1 85 be |T....)......%...| +00000220 f8 ae 63 f4 49 64 cc 0a 41 0e 26 8a 8e bc 6f c9 |..c.Id..A.&...o.| +00000230 f5 41 55 80 0d bd 70 ad 85 b0 d4 8d 33 ac b6 40 |.AU...p.....3..@| +00000240 3e 76 fc fb 8f d2 7d 06 14 d4 45 24 6e 36 46 1c |>v....}...E$n6F.| +00000250 06 d3 f7 f3 4c 3a a5 83 4f 75 72 77 b4 5e 37 49 |....L:..Ourw.^7I| +00000260 41 f1 9f e6 d1 46 87 56 c8 64 28 fd 38 f0 0f 9c |A....F.V.d(.8...| +00000270 d0 39 ff 4b 46 56 73 0d 12 7d bf 63 b4 b8 0d 33 |.9.KFVs..}.c...3| +00000280 6b 4a 2b f8 39 67 f1 ec 2d a6 0b 5c 91 2d d8 3e |kJ+.9g..-..\.-.>| +00000290 91 81 1a 37 29 c7 14 d2 be db 31 61 dc 5d b1 e4 |...7).....1a.]..| +000002a0 64 af 14 9c 93 85 e7 5b 0e 42 63 c7 5e b5 cc 51 |d......[.Bc.^..Q| +000002b0 ca 83 ca fa 52 bd 44 a1 1c 76 20 bc 3d 9f 82 79 |....R.D..v .=..y| +000002c0 20 5c 01 14 e3 07 02 4c f6 87 f7 46 b8 de 47 23 | \.....L...F..G#| +000002d0 5d 5c b3 8f cd 96 49 51 32 3f d2 5d 92 32 19 b5 |]\....IQ2?.].2..| +000002e0 10 33 46 37 f0 b5 82 23 a5 91 1f 60 fb 21 2c 08 |.3F7...#...`.!,.| +000002f0 c3 6e 17 72 0b 5d c9 7b cc 77 97 6f 20 d9 a6 fa |.n.r.].{.w.o ...| +00000300 cc 4a bb c6 3b 0e b1 66 ae 57 f5 1b 16 46 36 b7 |.J..;..f.W...F6.| +00000310 a5 94 ae 17 03 03 00 99 d7 86 a0 5f c0 d2 33 3e |..........._..3>| +00000320 ce ce ea db cb a1 a5 11 b7 cc a1 48 b6 86 f5 11 |...........H....| +00000330 d6 32 8c f9 e8 bb e3 3e ea 6f 1a df 64 cd c8 7d |.2.....>.o..d..}| +00000340 e9 cb e4 19 fe cd 75 74 03 4a fe 91 1d 87 28 65 |......ut.J....(e| +00000350 25 79 3a 19 13 ba 67 16 aa 7e 8e c0 e6 53 4f bb |%y:...g..~...SO.| +00000360 98 ed cc 59 db 5e 73 23 d4 a9 a7 2a 6d 01 73 4a |...Y.^s#...*m.sJ| +00000370 e6 65 2e c0 34 49 c1 d8 70 2e 70 1b 10 97 74 23 |.e..4I..p.p...t#| +00000380 fe 6b 5d cd fa 71 c8 43 c3 5b 42 5c 7b e0 9e 3f |.k]..q.C.[B\{..?| +00000390 a8 3d a9 d1 97 17 87 80 af 7c 5d 8b 70 ba 87 06 |.=.......|].p...| +000003a0 67 dd 29 df f3 ca 9a f4 c8 93 e8 f8 ac c0 df 8e |g.).............| +000003b0 c5 17 03 03 00 45 40 a4 26 66 29 18 b8 d6 a7 87 |.....E@.&f).....| +000003c0 91 5f 6d 79 13 f8 7a 47 cf ac 93 7c 11 cb 4a b2 |._my..zG...|..J.| +000003d0 24 a6 40 fb d4 ed 71 ec 19 53 ba ae e0 bb e6 cf |$.@...q..S......| +000003e0 d6 8a a6 3c 6a 4e a3 6f 6c d7 2d e1 8a a4 6c da |.....q=....| +00000410 dc 2f 4a 62 c2 9f e2 e5 16 51 ff 35 a7 70 df 12 |./Jb.....Q.5.p..| +00000420 23 d6 f7 6c 96 91 7f 0f 6d d4 45 5f c6 8c c5 93 |#..l....m.E_....| +00000430 b1 b7 46 ef f0 f4 a3 68 35 ff 09 38 8d 6d c6 84 |..F....h5..8.m..| +00000440 d3 1c 4d 48 4e fc 4a c0 46 06 b1 a5 1c 74 a0 44 |..MHN.J.F....t.D| +00000450 69 68 20 33 df 70 60 69 57 c7 85 bd 3e ed 55 d0 |ih 3.p`iW...>.U.| +00000460 56 84 8f 19 03 5a 54 9a d5 3e 5d 37 98 40 4c f0 |V....ZT..>]7.@L.| +00000470 5e f1 26 e5 97 01 fc 0f 2a 09 e9 7a 51 69 c0 8e |^.&.....*..zQi..| +00000480 d4 25 80 f4 ca 91 f3 a7 5c 0c 96 ba ec a8 b5 ee |.%......\.......| +00000490 ab ec 05 cb 99 30 78 48 1b 78 bf 3d b9 f4 e8 33 |.....0xH.x.=...3| +000004a0 4d 45 d1 |ME.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 45 54 0e c1 aa 95 |..........ET....| +00000010 fd c5 d2 8b a0 ae 40 a1 9a b8 87 39 17 53 f7 10 |......@....9.S..| +00000020 62 6f 55 18 42 cf 75 cb 05 de 32 28 c4 a0 f1 17 |boU.B.u...2(....| +00000030 f1 55 ae 2c 97 9e dd d2 d0 a7 6b c6 51 51 c6 0c |.U.,......k.QQ..| +00000040 81 3f 04 db 94 e6 68 f0 a1 80 10 39 06 99 25 e2 |.?....h....9..%.| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e e4 4f d5 b0 e7 a0 e2 13 69 75 7c |......O......iu|| +00000010 b1 84 93 be 99 ea 27 20 dd 08 89 6c e2 5a c6 bc |......' ...l.Z..| +00000020 b8 41 3d 17 03 03 00 13 cf 64 ad ad d9 84 87 36 |.A=......d.....6| +00000030 b9 ea b8 76 97 93 c1 03 44 c5 de |...v....D..| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ALPN b/src/crypto/tls/testdata/Server-TLSv13-ALPN new file mode 100644 index 0000000..df8dd45 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ALPN @@ -0,0 +1,100 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 e2 01 00 00 de 03 03 8e d2 a1 8f ea |................| +00000010 e3 7d 5f 7c 70 74 c3 7e 5f 06 bb 21 35 28 38 7a |.}_|pt.~_..!5(8z| +00000020 7f 00 11 86 6e ac 19 38 7f d4 88 20 33 3a b2 14 |....n..8... 3:..| +00000030 c2 4e 6a 39 71 24 81 21 27 21 2d b7 3d bc 5e 97 |.Nj9q$.!'!-.=.^.| +00000040 f8 ed 55 83 be 9a d3 27 b5 e0 0e bd 00 04 13 03 |..U....'........| +00000050 00 ff 01 00 00 91 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| +00000080 70 72 6f 74 6f 31 00 16 00 00 00 17 00 00 00 0d |proto1..........| +00000090 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 |................| +000000a0 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +000000b0 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| +000000c0 26 00 24 00 1d 00 20 89 4d b8 22 62 39 22 e6 5a |&.$... .M."b9".Z| +000000d0 b1 86 ea c9 d9 d1 77 c9 12 c3 62 e1 8e 17 cb ab |......w...b.....| +000000e0 91 83 d8 af 9b be 0a |.......| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 33 3a b2 14 |........... 3:..| +00000030 c2 4e 6a 39 71 24 81 21 27 21 2d b7 3d bc 5e 97 |.Nj9q$.!'!-.=.^.| +00000040 f8 ed 55 83 be 9a d3 27 b5 e0 0e bd 13 03 00 00 |..U....'........| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 24 60 9e a3 43 47 75 |.........$`..CGu| +00000090 d2 38 11 fd 9d da a5 f6 65 de 3c 2a 3d a9 46 7e |.8......e.<*=.F~| +000000a0 50 c8 52 a1 7d e6 95 a7 4b 48 b7 35 e7 a7 17 03 |P.R.}...KH.5....| +000000b0 03 02 6d b8 30 43 88 03 d4 6c cf c6 45 80 b2 6c |..m.0C...l..E..l| +000000c0 52 d7 1e 08 de 0b 6e 7a 27 c8 2c 59 d4 03 41 24 |R.....nz'.,Y..A$| +000000d0 e3 4a e1 d3 85 68 de 23 f6 c4 3a bb 45 ae b1 ac |.J...h.#..:.E...| +000000e0 8b b3 22 7d e7 a6 7c e3 07 68 b1 9c 97 6a d3 e4 |.."}..|..h...j..| +000000f0 5d 0a 73 a3 16 ad e4 7f b9 d7 0a b7 7c 48 bb f2 |].s.........|H..| +00000100 ed 49 61 f7 cb 5e ea d2 d9 a3 73 ea a7 4f a3 10 |.Ia..^....s..O..| +00000110 f7 3e 8f ce b9 56 a0 88 54 52 59 1f f3 55 2b 15 |.>...V..TRY..U+.| +00000120 df fd fa 85 9e 20 ff 72 f3 26 6a 2c 1f 11 a8 3d |..... .r.&j,...=| +00000130 8e 66 75 aa 90 fc 9f 9f a7 67 8f ac 98 54 19 04 |.fu......g...T..| +00000140 c9 1f 48 f7 ed 8f 13 0a f9 6c 9b f8 e9 0a c5 a9 |..H......l......| +00000150 f2 ef 5b 65 a1 ad 40 e4 e7 ff c1 ff e9 d6 ab 5c |..[e..@........\| +00000160 f8 f1 7b 4d 39 33 1d 68 d3 38 20 10 c4 3b 7a 9f |..{M93.h.8 ..;z.| +00000170 fe 55 1d 83 5c 8f 67 d0 bb 5f 32 80 b2 91 38 0a |.U..\.g.._2...8.| +00000180 71 bb b4 3a 10 1c 98 f9 d4 19 7c 7d d5 f7 4b 0a |q..:......|}..K.| +00000190 02 2f bd 0b f9 ff 28 b2 2d ba dd 7f 0d 51 a2 4c |./....(.-....Q.L| +000001a0 51 92 1e e9 47 51 ae 1a d0 66 9c ef 0a 02 dc 69 |Q...GQ...f.....i| +000001b0 95 79 2b b0 8f 7b a2 3d 57 cf 5c 7e b4 0a 91 34 |.y+..{.=W.\~...4| +000001c0 e6 d0 0d 93 1b 6c 61 9e 58 12 47 5f 3a ec 67 19 |.....la.X.G_:.g.| +000001d0 d8 fb 44 43 4d cd 4e ad 1d bc f2 05 66 42 3f 3f |..DCM.N.....fB??| +000001e0 85 5d 93 56 8e ca 62 47 38 ee d2 0e 81 8b 71 7d |.].V..bG8.....q}| +000001f0 d8 cf 6e 4b 61 80 fe 28 34 f4 f1 58 06 36 2a 40 |..nKa..(4..X.6*@| +00000200 93 98 3d d0 9c 69 6f 6a 3a 40 b9 8c 2e 71 5d 52 |..=..ioj:@...q]R| +00000210 66 5d 55 45 e7 38 b7 ce 74 c2 1c ae 2e 4a 03 86 |f]UE.8..t....J..| +00000220 d4 15 c3 40 d9 58 b7 ba ed 84 fd 20 35 a4 1c c6 |...@.X..... 5...| +00000230 8a 50 7a 0c 87 53 d7 2d 4b 5b 7d 23 79 8f 66 f8 |.Pz..S.-K[}#y.f.| +00000240 72 05 72 7b 7d 7a 64 97 8d da c9 dd 23 6a 44 b6 |r.r{}zd.....#jD.| +00000250 e1 99 e4 45 76 a5 53 d8 1b 54 a0 b9 9e ec 0e d3 |...Ev.S..T......| +00000260 91 1b 5e c0 a7 c8 3a 34 22 f9 58 7d da 2b f4 fd |..^...:4".X}.+..| +00000270 2b 9a 9e 26 20 6f d3 9d e9 48 a1 62 70 fe 06 04 |+..& o...H.bp...| +00000280 c2 63 f7 c4 a2 b9 74 28 a8 b3 f9 f0 a1 2a 46 0c |.c....t(.....*F.| +00000290 f5 6b cc 7e b4 c0 47 eb 00 96 6a 3d 32 58 e0 0a |.k.~..G...j=2X..| +000002a0 59 01 3c 42 45 a7 76 6d 78 05 1f 2c db a4 08 5b |Y....c...f/| +00000470 24 2a 06 1b f3 91 a7 7c dd d9 b5 1f b3 9e 7f ce |$*.....|........| +00000480 db 96 cd 2e 36 69 f0 94 0c 5f e8 0b 15 6a 38 40 |....6i..._...j8@| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 32 39 09 c6 64 |..........529..d| +00000010 aa 86 b7 a7 37 6c fa ef 66 01 d4 de e6 35 8d 31 |....7l..f....5.1| +00000020 68 71 f3 27 56 fd 7f 7b cf c8 3c d1 44 ff e0 c7 |hq.'V..{..<.D...| +00000030 78 b7 6c c8 ac 01 0e ee e1 78 b9 dd 1a e1 a9 b6 |x.l......x......| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e da e7 79 04 f5 65 2e f6 c3 c3 b9 |.......y..e.....| +00000010 34 37 14 8f c2 32 cb 81 58 bc cf d0 3b 08 f0 61 |47...2..X...;..a| +00000020 b3 ae b4 17 03 03 00 13 e3 32 09 02 e0 29 5e 4a |.........2...)^J| +00000030 9b 36 a9 b0 65 e9 2c 1d fb ad 50 |.6..e.,...P| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback b/src/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback new file mode 100644 index 0000000..6203e68 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback @@ -0,0 +1,100 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 eb 01 00 00 e7 03 03 1c d3 8e 3b d9 |..............;.| +00000010 fe 7d e7 f9 9f fa c6 51 c3 8c 1b dd dc 87 95 f4 |.}.....Q........| +00000020 39 23 67 e4 d6 bd 94 93 fc 88 4e 20 c3 c0 e2 c1 |9#g.......N ....| +00000030 3d 12 ec 4c 0a 3f 40 51 13 24 61 11 c0 5d 09 f9 |=..L.?@Q.$a..]..| +00000040 08 d6 3e cd e7 b3 51 c3 06 8f b4 42 00 04 13 03 |..>...Q....B....| +00000050 00 ff 01 00 00 9a 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 10 00 19 00 17 06 70 72 6f 74 6f 33 08 |.........proto3.| +00000080 68 74 74 70 2f 31 2e 31 06 70 72 6f 74 6f 34 00 |http/1.1.proto4.| +00000090 16 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 |................| +000000a0 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 |................| +000000b0 05 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 |..........+.....| +000000c0 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 |.-.....3.&.$... | +000000d0 f4 05 eb 4a 7a 73 20 18 74 aa 14 2a 0c 35 63 29 |...Jzs .t..*.5c)| +000000e0 cb f2 ad d1 a2 3d bd 9d 02 b4 62 00 bc eb 10 58 |.....=....b....X| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 c3 c0 e2 c1 |........... ....| +00000030 3d 12 ec 4c 0a 3f 40 51 13 24 61 11 c0 5d 09 f9 |=..L.?@Q.$a..]..| +00000040 08 d6 3e cd e7 b3 51 c3 06 8f b4 42 13 03 00 00 |..>...Q....B....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 fb 75 d8 5c 50 35 |...........u.\P5| +00000090 55 82 ba 65 1e 63 73 b8 c1 e9 d7 f5 28 68 3c c1 |U..e.cs.....(h<.| +000000a0 5d 17 03 03 02 6d 56 c9 a9 09 73 6a bc fd 1a 3c |]....mV...sj...<| +000000b0 6a f8 3e 32 99 83 e8 f6 01 9e 5e 30 e8 53 7f 72 |j.>2......^0.S.r| +000000c0 fd 86 72 a8 9e 47 25 67 c1 f1 9a 03 c0 9d 6f 9d |..r..G%g......o.| +000000d0 bd ed 29 30 8f 3c 01 ce 49 bb 5f dd 58 9a ae 80 |..)0.<..I._.X...| +000000e0 5c 2d 81 fc ea 7b 03 03 3d 5d bb 92 23 73 67 89 |\-...{..=]..#sg.| +000000f0 2e f0 ec 08 20 8a 36 eb 43 a6 a1 68 d0 39 95 37 |.... .6.C..h.9.7| +00000100 6b 15 a9 0e 46 20 92 51 9c 04 bf 3b 07 97 84 cb |k...F .Q...;....| +00000110 1f 30 38 37 2e ff e7 0f f5 14 93 5a 84 f1 f7 10 |.087.......Z....| +00000120 c2 a5 0d bb 97 96 ef 4a e0 13 c0 63 72 2b 60 f3 |.......J...cr+`.| +00000130 59 b5 57 aa 5f d1 da a9 0e dd 9c dd c2 cb 61 fe |Y.W._.........a.| +00000140 e2 69 8e db 5d 70 6c 3a 33 e0 9e db 9a 31 26 6a |.i..]pl:3....1&j| +00000150 2b 9e 19 8e bb 5d 06 48 ea c0 a1 c6 11 24 fb c4 |+....].H.....$..| +00000160 ce ae 48 54 64 81 d1 84 38 a6 e0 7a 7b 74 2b bc |..HTd...8..z{t+.| +00000170 ce 07 8b b6 04 1f 5b 4c 36 29 68 0c 8c c7 32 15 |......[L6)h...2.| +00000180 93 e0 10 52 c2 27 23 96 c5 0c 9c e9 e2 a9 08 7d |...R.'#........}| +00000190 25 68 65 f5 4e 44 eb a9 85 78 13 e1 0d 86 5e dc |%he.ND...x....^.| +000001a0 fd e5 c6 dd 65 46 8e 2f 32 82 83 0b dd 67 f8 42 |....eF./2....g.B| +000001b0 65 87 3b 08 fe b1 f5 12 e9 74 21 04 12 6d 75 35 |e.;......t!..mu5| +000001c0 b2 eb 93 95 72 10 fa 56 96 77 c3 0c 17 8c 9e f6 |....r..V.w......| +000001d0 77 19 28 37 96 3e 73 98 f4 d2 91 4f 40 db 76 56 |w.(7.>s....O@.vV| +000001e0 ce b5 a8 7a b8 86 d0 9a ba b5 8b 40 c2 63 e1 cf |...z.......@.c..| +000001f0 49 29 2c 5d 1a 9b 8b 56 cb 93 ca 2c c0 d0 15 b7 |I),]...V...,....| +00000200 8a f1 6a d5 0a a8 81 57 b1 6e 10 cd a5 ff b1 4d |..j....W.n.....M| +00000210 47 c6 9b 35 f1 5f 83 91 22 f6 88 68 65 b3 b9 c9 |G..5._.."..he...| +00000220 02 dc 4b f7 13 39 06 e6 3a ec 94 ef 51 15 05 72 |..K..9..:...Q..r| +00000230 1d f4 9d 3b da ca 8d 2c 64 be 9b 45 99 2c 63 cc |...;...,d..E.,c.| +00000240 22 b3 8b 93 ad f6 2c f0 d2 d9 11 3f 5b c0 40 fa |".....,....?[.@.| +00000250 90 6e a0 76 b2 43 b9 4c 72 c4 24 28 a2 bf 56 d6 |.n.v.C.Lr.$(..V.| +00000260 d2 a7 2a d1 8c 5e 1d eb f8 be d0 43 da 7a c7 88 |..*..^.....C.z..| +00000270 61 67 a2 69 85 23 43 3e d4 88 f2 33 c3 5b 38 0a |ag.i.#C>...3.[8.| +00000280 1e de 28 3b 3b 19 de 95 2f 84 c0 37 88 80 59 2f |..(;;.../..7..Y/| +00000290 a6 ee 93 1a 69 08 c3 df 7c cf da c3 9b 96 70 d9 |....i...|.....p.| +000002a0 60 c5 e9 0f 42 f6 1a f2 58 5e f2 32 61 6a b2 a3 |`...B...X^.2aj..| +000002b0 1f 97 fa 08 6c 3f 4b 83 1f 04 66 80 8a 26 3a 7f |....l?K...f..&:.| +000002c0 24 30 ec 10 ae 7d 19 ff 39 91 ca 97 4e ed 0a d7 |$0...}..9...N...| +000002d0 64 3b 6b 50 29 33 0d b2 10 bc 83 63 3c fb 9a 82 |d;kP)3.....c<...| +000002e0 3b 7f bc 04 40 f1 33 64 4a 80 cd 01 f9 f4 c6 89 |;...@.3dJ.......| +000002f0 65 27 25 f9 cf 4f 7e c8 6e d9 0e ec 47 4a 51 29 |e'%..O~.n...GJQ)| +00000300 2f be 34 50 bd 9b d2 d8 b7 ea bb 0b a1 e0 20 1b |/.4P.......... .| +00000310 02 9c f2 17 03 03 00 99 61 dc 0b 3a 30 de 39 f6 |........a..:0.9.| +00000320 f3 db f8 6c 3b fa 4e 1e 7e 62 a5 ae 73 ba e1 41 |...l;.N.~b..s..A| +00000330 58 77 2a c1 7a 0c 50 bb 0c 57 b4 c4 25 bf 2f 9f |Xw*.z.P..W..%./.| +00000340 38 91 e2 65 22 9d ca ac 18 58 7e 81 2d fd 74 24 |8..e"....X~.-.t$| +00000350 28 69 76 11 df 9d 23 b8 be ae 8b e0 93 8e 5d df |(iv...#.......].| +00000360 0a 64 d0 b7 02 68 aa 86 01 0d 55 11 3b 76 70 c6 |.d...h....U.;vp.| +00000370 83 0c 5e 0a e3 37 a5 8b ad 25 50 b9 e8 5c 6b 04 |..^..7...%P..\k.| +00000380 b4 51 ec 9c d3 fa c6 b7 9c f0 46 aa 73 da 3c 0d |.Q........F.s.<.| +00000390 d3 bd 32 81 d4 d2 f1 1a b0 92 f3 73 3e 54 2b 05 |..2........s>T+.| +000003a0 92 24 34 75 df d6 18 a0 6a 82 95 4c 9b fc 7e b6 |.$4u....j..L..~.| +000003b0 8e 17 03 03 00 35 8f 34 0e 3b 91 d8 e7 74 24 71 |.....5.4.;...t$q| +000003c0 0e 7b f3 12 bb 76 2f 31 12 17 b8 9e 24 ce f9 2f |.{...v/1....$../| +000003d0 3f 5d f2 13 4b 2e 9b 1e c4 78 03 a6 c8 07 11 a3 |?]..K....x......| +000003e0 98 79 61 6e 4f 44 6e 18 ee c4 9b 17 03 03 00 93 |.yanODn.........| +000003f0 64 dd 52 a9 d9 51 63 6a a0 a3 c2 75 6b 5d 1d 54 |d.R..Qcj...uk].T| +00000400 ce d4 53 7e 14 8e d9 26 93 28 78 65 16 1b 95 77 |..S~...&.(xe...w| +00000410 68 0a 46 f1 82 36 bb 8a fa 0d df 54 8c 3d 83 e0 |h.F..6.....T.=..| +00000420 d7 de 2d 96 e9 c4 d7 22 d3 97 8e ae 90 f8 fc e6 |..-...."........| +00000430 a6 4b 78 98 4c c5 28 87 91 46 fa f4 1c 8d 0e ec |.Kx.L.(..F......| +00000440 0d 71 40 9a 04 49 b4 e8 5b 62 6f cd 16 c1 d5 fb |.q@..I..[bo.....| +00000450 73 2a 96 8f e5 a2 f4 11 1e df 2d 40 45 6b d5 a9 |s*........-@Ek..| +00000460 e4 e3 f7 93 fc fa d7 20 af d5 f7 b4 0e 09 ad d5 |....... ........| +00000470 26 87 b8 6c e2 20 95 fb c0 70 3e 38 be b7 b1 9f |&..l. ...p>8....| +00000480 70 da c1 |p..| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 29 d2 b9 bb 9b |..........5)....| +00000010 de 6c 5d 22 23 c1 fe 99 4c c5 33 bf fd 70 36 6b |.l]"#...L.3..p6k| +00000020 f1 a5 92 e8 bf 7c 3d 6e ef 6a 44 73 bc cb 27 1c |.....|=n.jDs..'.| +00000030 09 5d bf 99 4c 19 24 c3 3b 30 91 b5 e3 b6 63 45 |.]..L.$.;0....cE| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 52 55 85 7c b8 87 dd c7 b2 d9 5b |.....RU.|......[| +00000010 18 1d bb ac bf b6 ab 76 82 be 64 0e b2 7b 2c 0f |.......v..d..{,.| +00000020 aa 17 92 17 03 03 00 13 79 0a 60 b1 46 20 33 74 |........y.`.F 3t| +00000030 ed 12 a0 23 de 68 88 fc 6f dd 8e |...#.h..o..| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch b/src/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch new file mode 100644 index 0000000..b51ff25 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch @@ -0,0 +1,27 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 e2 01 00 00 de 03 03 9f 73 81 5f 56 |............s._V| +00000010 a9 02 5f 8c 33 db dc 2a 92 d0 5e 7c e9 e6 01 d7 |.._.3..*..^|....| +00000020 67 b6 bb 74 da bb d0 c1 11 08 20 20 9f bd d6 f8 |g..t...... ....| +00000030 d7 8c e5 32 15 1d 4a 4c 36 ce 72 90 cb 68 ca dc |...2..JL6.r..h..| +00000040 ea b3 57 93 9a 12 e6 0e 9a bd 91 1a 00 04 13 03 |..W.............| +00000050 00 ff 01 00 00 91 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| +00000080 70 72 6f 74 6f 31 00 16 00 00 00 17 00 00 00 0d |proto1..........| +00000090 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 |................| +000000a0 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +000000b0 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| +000000c0 26 00 24 00 1d 00 20 79 79 04 d3 03 58 93 22 5d |&.$... yy...X."]| +000000d0 06 69 1a 03 11 4e 65 e5 30 85 29 02 22 c8 11 6d |.i...Ne.0.)."..m| +000000e0 21 86 d4 4d 58 93 74 |!..MX.t| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 9f bd d6 f8 |........... ....| +00000030 d7 8c e5 32 15 1d 4a 4c 36 ce 72 90 cb 68 ca dc |...2..JL6.r..h..| +00000040 ea b3 57 93 9a 12 e6 0e 9a bd 91 1a 13 03 00 00 |..W.............| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 13 7c ab 7f dd 94 cf |..........|.....| +00000090 d7 98 34 16 75 02 63 37 fa 4f 19 4e 18 |..4.u.c7.O.N.| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured b/src/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured new file mode 100644 index 0000000..e0830d3 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured @@ -0,0 +1,100 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 e2 01 00 00 de 03 03 9f 49 a7 46 f8 |............I.F.| +00000010 72 04 47 a1 8e 4f 89 c3 cd 89 92 2f 7a 8a 07 37 |r.G..O...../z..7| +00000020 8c 25 10 42 26 07 8b a2 71 3e 92 20 4c 83 1b 70 |.%.B&...q>. L..p| +00000030 45 c3 79 68 c3 83 a7 05 c2 22 06 c6 91 da 8b 96 |E.yh....."......| +00000040 4c 9d 89 c2 ec b8 49 87 17 3f 6c ae 00 04 13 03 |L.....I..?l.....| +00000050 00 ff 01 00 00 91 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| +00000080 70 72 6f 74 6f 31 00 16 00 00 00 17 00 00 00 0d |proto1..........| +00000090 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 |................| +000000a0 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +000000b0 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| +000000c0 26 00 24 00 1d 00 20 f4 91 87 6a ac cd 25 5e f1 |&.$... ...j..%^.| +000000d0 0d 25 fb af a4 d4 fb 16 32 63 af 04 2d 21 d7 2f |.%......2c..-!./| +000000e0 61 f2 c2 d4 c4 6c 2b |a....l+| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 4c 83 1b 70 |........... L..p| +00000030 45 c3 79 68 c3 83 a7 05 c2 22 06 c6 91 da 8b 96 |E.yh....."......| +00000040 4c 9d 89 c2 ec b8 49 87 17 3f 6c ae 13 03 00 00 |L.....I..?l.....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 60 79 16 61 4f 6c |..........`y.aOl| +00000090 9e 2e ce fd cc f5 29 67 38 e7 53 67 92 b1 5f 9d |......)g8.Sg.._.| +000000a0 db 17 03 03 02 6d 54 d9 d6 a1 8e c2 1b 70 3f 3d |.....mT......p?=| +000000b0 a2 2e 0f a5 37 96 e1 68 66 69 cc f8 e9 06 4d bc |....7..hfi....M.| +000000c0 c2 9a 6e 0f ea d4 73 59 6a 59 28 79 7f 44 0c 32 |..n...sYjY(y.D.2| +000000d0 29 22 51 d1 fb 00 c7 33 44 8b 19 71 98 8a 03 44 |)"Q....3D..q...D| +000000e0 e0 95 ad 8f 91 66 e6 15 b8 99 b3 f8 2f 02 e9 a0 |.....f....../...| +000000f0 4a 25 ec 3f 36 56 0c eb 0a a3 e0 d3 79 a1 b3 9e |J%.?6V......y...| +00000100 dc 42 08 76 a4 c3 55 91 06 11 e7 0c 94 dd 71 fc |.B.v..U.......q.| +00000110 bf 8a 87 d2 97 07 a3 b9 36 7e 58 ff ef b3 a3 f4 |........6~X.....| +00000120 6e f1 23 d6 50 e3 23 d3 dc e7 20 ce 9d 84 17 cf |n.#.P.#... .....| +00000130 2d 5f b1 f9 8d 36 41 7d ba 3b 93 63 2f bc be f0 |-_...6A}.;.c/...| +00000140 a1 3a bb 5f b3 99 03 13 fb d2 2c 1a 8c cc 32 02 |.:._......,...2.| +00000150 ef 93 b4 58 a8 f8 b1 42 52 24 c2 73 01 cb 5a fb |...X...BR$.s..Z.| +00000160 9f fc 38 08 d7 f9 0d d7 20 fa dc 8b 1a 8c 73 0f |..8..... .....s.| +00000170 f8 79 b2 84 e1 49 2d 8e 6d 46 16 38 0e 02 2a 2c |.y...I-.mF.8..*,| +00000180 f4 44 89 da f1 7a 01 55 9e 93 a8 d6 d5 f5 72 28 |.D...z.U......r(| +00000190 47 2b 4f 17 7e a5 01 fd ad 85 e0 6d f9 82 e8 cd |G+O.~......m....| +000001a0 09 18 84 8c 9d 4f 4e a1 43 ff d6 3d 55 05 fc 56 |.....ON.C..=U..V| +000001b0 e6 d6 b6 61 4a c7 c7 9c 62 64 26 1d 33 1e 4f d5 |...aJ...bd&.3.O.| +000001c0 5e ee 1f a9 ad 24 e4 7f 05 cc 02 7a f7 e0 c2 ce |^....$.....z....| +000001d0 b8 11 c9 a1 fd c5 d8 0e ef f8 c9 6a 2d 49 30 63 |...........j-I0c| +000001e0 e3 9b 43 bf 87 e1 5f 55 39 fa 80 ec 84 55 59 5d |..C..._U9....UY]| +000001f0 52 76 4c f4 70 eb 43 6a b2 07 d5 29 4c 58 39 04 |RvL.p.Cj...)LX9.| +00000200 46 42 70 8d 28 61 7c d5 7a 3a 2e a0 9f 74 49 2d |FBp.(a|.z:...tI-| +00000210 33 8d 39 18 70 8d 3c 50 4f 62 07 77 2d 15 1f 4b |3.9.p..._.{..<.m$[...| +00000240 1a 40 4e 80 7f 44 12 57 c9 03 57 c6 9b 54 0d 39 |.@N..D.W..W..T.9| +00000250 91 88 72 3e c8 f9 18 eb 34 7c 0a eb 2d c8 56 1c |..r>....4|..-.V.| +00000260 84 8a 62 a2 3a 0a 52 b8 5a b6 5d 54 78 ae 05 b2 |..b.:.R.Z.]Tx...| +00000270 f4 6c 2d 5e 92 94 6b f3 1e 93 13 1a 65 74 60 e3 |.l-^..k.....et`.| +00000280 dd 15 36 62 2b 71 b1 bb 59 19 08 af 8e 9b d0 47 |..6b+q..Y......G| +00000290 05 7b a3 89 ac 68 cf a0 32 ba 4a 2b 9e 5f a5 dc |.{...h..2.J+._..| +000002a0 b3 00 79 a8 1c f6 11 b8 6d 9c 51 b7 f1 f6 b2 13 |..y.....m.Q.....| +000002b0 56 57 4e ac 97 ff 5a b8 52 33 0c c1 3d 52 81 6e |VWN...Z.R3..=R.n| +000002c0 85 ba b2 04 4b eb 41 aa 03 ff ae 63 93 72 3a 5f |....K.A....c.r:_| +000002d0 65 81 f9 6a 2a e4 70 f8 b3 59 31 51 62 ad 25 24 |e..j*.p..Y1Qb.%$| +000002e0 82 0c b5 ad 7c 87 21 97 07 c0 c1 6d f0 22 97 0d |....|.!....m."..| +000002f0 28 cf a7 4d 74 d2 9c ac d7 15 83 26 f7 2f 76 d4 |(..Mt......&./v.| +00000300 ad cf e7 ef 1c f4 3e 1f b4 f4 4f 76 6a 98 15 01 |......>...Ovj...| +00000310 cd 17 8b 17 03 03 00 99 0b 15 9d 16 c6 2a 52 53 |.............*RS| +00000320 33 d7 01 db 8a 49 1d d6 83 b7 28 a4 07 f0 73 5e |3....I....(...s^| +00000330 60 03 2c 6f 3f e0 88 a1 76 22 d6 23 0a df ca 86 |`.,o?...v".#....| +00000340 b0 44 b9 1d 9a d7 53 f2 2b 57 a1 65 01 d4 e7 b4 |.D....S.+W.e....| +00000350 9e 22 00 d2 20 da cd 55 7d 61 86 86 19 81 f9 ed |.".. ..U}a......| +00000360 f8 af c4 69 54 1d 35 0a 6f 9e 69 40 13 08 82 dd |...iT.5.o.i@....| +00000370 59 11 31 f2 81 a7 4b f1 bd d9 f2 5c 29 22 16 49 |Y.1...K....\)".I| +00000380 86 62 8c a8 b8 89 58 96 cc d1 e4 e8 5e ef 6c b7 |.b....X.....^.l.| +00000390 00 71 3d ab 92 b8 78 56 a7 25 5e a0 c4 d8 8c 02 |.q=...xV.%^.....| +000003a0 c4 c8 eb d3 be 68 21 05 5c 5f 9c b0 ec 20 99 ff |.....h!.\_... ..| +000003b0 00 17 03 03 00 35 c9 c1 5e 25 1c b9 64 8e c2 fd |.....5..^%..d...| +000003c0 50 87 48 e6 02 36 75 31 67 f6 82 3c 94 79 7d 0b |P.H..6u1g..<.y}.| +000003d0 cb 83 b1 f4 e1 00 5f a6 b6 2c 2d 63 40 ab 98 f9 |......_..,-c@...| +000003e0 e3 8e 4a 7e d4 77 3d 55 90 10 75 17 03 03 00 93 |..J~.w=U..u.....| +000003f0 47 c4 6e 19 29 c2 5e d5 93 b7 c2 cc 46 a9 49 9d |G.n.).^.....F.I.| +00000400 8a 3b 9a 35 bb 45 22 13 b6 eb c9 ec ba 44 3c 24 |.;.5.E"......D<$| +00000410 f2 ed bd 76 11 cc af 00 b3 89 63 5d 79 32 cc d7 |...v......c]y2..| +00000420 5c 34 f3 5e 64 36 92 5d ac ac 33 74 f4 3d c4 b8 |\4.^d6.]..3t.=..| +00000430 4d ac d0 49 4e 59 1c 16 74 8c 43 94 4b 13 b9 22 |M..INY..t.C.K.."| +00000440 de d7 ee 30 09 63 f3 32 5f a2 9d a1 20 ea ee 91 |...0.c.2_... ...| +00000450 ca d8 01 33 df 43 19 69 63 ee 6a 2c 80 99 ad f0 |...3.C.ic.j,....| +00000460 5e 20 b6 b6 81 28 b6 9d 4a 9a 91 30 30 04 c1 70 |^ ...(..J..00..p| +00000470 68 54 1e e0 72 00 4c fd 23 a8 41 a2 6a ab a3 01 |hT..r.L.#.A.j...| +00000480 7a 40 1a |z@.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 20 1f 0d 20 a8 |..........5 .. .| +00000010 34 c4 dc fa f9 d6 2b fe 01 eb f1 54 f0 14 c2 2d |4.....+....T...-| +00000020 bb 59 db 04 96 f2 18 8b bd 7e b0 38 b7 15 b5 d8 |.Y.......~.8....| +00000030 6b f2 80 25 40 f6 97 67 fb 9e 5a 5c ad 33 c6 5f |k..%@..g..Z\.3._| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 3a 8a fc 60 3a 99 ee b6 01 b7 fe |.....:..`:......| +00000010 54 a9 2d 34 28 ae af 3b 6a bd e0 32 6b df 87 fe |T.-4(..;j..2k...| +00000020 d0 97 8d 17 03 03 00 13 c6 89 d5 ae 4c fa d5 71 |............L..q| +00000030 66 6e 07 b5 9b 00 e8 50 7e b9 5f |fn.....P~._| diff --git a/src/crypto/tls/testdata/Server-TLSv13-CHACHA20-SHA256 b/src/crypto/tls/testdata/Server-TLSv13-CHACHA20-SHA256 new file mode 100644 index 0000000..760c597 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-CHACHA20-SHA256 @@ -0,0 +1,100 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 dc 01 00 00 d8 03 03 7f d6 02 2f 2d |............../-| +00000010 ed b1 3c f2 c2 48 5e d5 f4 57 c9 8c ba 81 36 52 |..<..H^..W....6R| +00000020 85 3e 79 de 79 cc 36 6a f9 88 89 20 db e1 89 a5 |.>y.y.6j... ....| +00000030 26 4c 2a 2d 0f 33 e2 3f 57 05 cc 74 cd 4c 96 be |&L*-.3.?W..t.L..| +00000040 91 94 ef 54 1c 1f 01 ef d4 36 75 2f 00 04 13 03 |...T.....6u/....| +00000050 00 ff 01 00 00 8b 00 00 00 0e 00 0c 00 00 09 31 |...............1| +00000060 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000070 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000080 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 |................| +00000090 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +000000a0 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 |...........+....| +000000b0 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 |..-.....3.&.$...| +000000c0 20 30 20 a8 d0 3d ea df 38 aa 65 6f dd c8 25 13 | 0 ..=..8.eo..%.| +000000d0 03 c4 a2 24 d4 a8 0d 1a a6 65 32 75 83 ef 71 70 |...$.....e2u..qp| +000000e0 30 |0| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 db e1 89 a5 |........... ....| +00000030 26 4c 2a 2d 0f 33 e2 3f 57 05 cc 74 cd 4c 96 be |&L*-.3.?W..t.L..| +00000040 91 94 ef 54 1c 1f 01 ef d4 36 75 2f 13 03 00 00 |...T.....6u/....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 f4 9a 6e ea 99 81 |............n...| +00000090 59 33 26 a6 6a 40 1d a9 59 67 31 35 09 b0 ed 15 |Y3&.j@..Yg15....| +000000a0 83 17 03 03 02 6d 56 59 69 c8 6d 45 c6 2f 58 3d |.....mVYi.mE./X=| +000000b0 db 87 dd 56 0f 2d d9 21 1b 97 94 77 f2 72 28 0d |...V.-.!...w.r(.| +000000c0 48 04 79 83 7e 2e a1 c9 30 56 d7 9c c8 0a 37 65 |H.y.~...0V....7e| +000000d0 b6 6b 31 ae 9a 5f ff 13 15 94 99 7c 92 e1 32 80 |.k1.._.....|..2.| +000000e0 28 3c ab b1 cc fe ba 92 3c 03 bb fd b8 55 f5 f2 |(<......<....U..| +000000f0 ba be 28 90 c5 7e 07 48 d5 45 b6 84 80 02 2d cd |..(..~.H.E....-.| +00000100 14 27 81 b6 4e b4 7f 5f 78 a3 26 c2 0c af 12 d6 |.'..N.._x.&.....| +00000110 e9 14 22 c8 ee 2e 5e fc c3 ca 8f 01 9b 37 6a b0 |.."...^......7j.| +00000120 f8 53 b2 8e 31 d7 1f 34 f6 35 ed 81 e0 f7 6f e1 |.S..1..4.5....o.| +00000130 90 cf 1a 4f 44 50 d5 cd 96 c3 4a 22 7a 54 28 bd |...ODP....J"zT(.| +00000140 88 56 5c 77 67 eb a6 78 5c 8b 82 39 03 13 55 c3 |.V\wg..x\..9..U.| +00000150 20 68 45 26 7a 96 fe 1c f9 33 14 1e 1d 8a 5f 51 | hE&z....3...._Q| +00000160 c3 2f 17 91 ba 37 63 49 e1 65 89 bf e8 a1 27 5f |./...7cI.e....'_| +00000170 fd 59 46 80 f7 9b 45 89 50 ab cd 9b aa b4 45 04 |.YF...E.P.....E.| +00000180 b5 1b 85 88 1c 59 ba b2 d6 50 0b fd 5c d9 59 83 |.....Y...P..\.Y.| +00000190 7a 6c 9b ad 27 33 a0 49 74 eb a6 cd a8 e8 4b d7 |zl..'3.It.....K.| +000001a0 71 ef 63 64 ff 24 a7 09 2e b7 f6 6f 9d 9f 75 84 |q.cd.$.....o..u.| +000001b0 97 0a 76 bf 72 ed ff e8 1a 49 ca 0b 0d f5 2c fb |..v.r....I....,.| +000001c0 69 c2 5c fe db 58 0a a1 9c d4 47 6a 8f a6 bd ec |i.\..X....Gj....| +000001d0 32 fb 40 6a 71 9d 19 37 e6 fd d4 3d fa 5b f3 53 |2.@jq..7...=.[.S| +000001e0 43 df d5 fa 53 29 40 70 77 a6 9e f7 03 7d 08 8b |C...S)@pw....}..| +000001f0 5a 71 73 e5 af 45 58 56 9f 56 ad 73 aa d2 b3 7c |Zqs..EXV.V.s...|| +00000200 92 99 c8 04 16 bf ca f2 81 2e 29 c3 79 21 f1 11 |..........).y!..| +00000210 92 f4 1d 34 24 73 e3 82 28 5a 31 70 45 da 8d 94 |...4$s..(Z1pE...| +00000220 38 75 31 bc f9 e5 2b 11 7e fd bc 19 fe 65 ad 53 |8u1...+.~....e.S| +00000230 e5 e6 17 b8 69 ea 54 fd 92 a9 41 7a 8c 7f da 4f |....i.T...Az...O| +00000240 ba f1 9f a2 e2 5b e7 7a 23 17 9e 29 95 7e 72 79 |.....[.z#..).~ry| +00000250 22 67 c5 68 0a 4d fb e9 64 61 3a 53 18 e7 dd 7d |"g.h.M..da:S...}| +00000260 5b 16 b9 fa 69 95 82 eb ee 1a 30 97 93 97 fc ee |[...i.....0.....| +00000270 9e 2b 22 64 08 7d 25 05 77 5e d7 bd 0e c3 9f a4 |.+"d.}%.w^......| +00000280 f4 bf 77 3d 56 84 c8 a1 10 1c e0 5b da 39 3d 2d |..w=V......[.9=-| +00000290 92 80 9a 07 b2 29 c5 ab e0 e1 1c ad ba 3e fa 4e |.....).......>.N| +000002a0 65 4f 31 63 de 33 6a 5c af e0 88 70 fc 6e 6a a2 |eO1c.3j\...p.nj.| +000002b0 ca da 2f 14 1d 4f 8c 7d 8d da 36 9b ea 7f 7e 79 |../..O.}..6...~y| +000002c0 9c dc 4a 3b 69 d9 50 31 bb f2 f8 8a 7f 6e 73 bc |..J;i.P1.....ns.| +000002d0 41 7c 3a 86 10 91 9b 3a 8e 3e c8 bc 6a c4 4d f2 |A|:....:.>..j.M.| +000002e0 45 87 49 49 d2 2f aa 4d d0 6f e9 1e a4 d6 06 63 |E.II./.M.o.....c| +000002f0 ac 90 ce 9a cb f7 97 55 2b e8 8c 8d 55 f6 32 26 |.......U+...U.2&| +00000300 55 d4 60 0e c0 0b da 0e ac c9 4c c3 95 03 54 d7 |U.`.......L...T.| +00000310 99 ec e1 17 03 03 00 99 c4 65 5e 67 e3 a1 98 d6 |.........e^g....| +00000320 f8 34 15 ed a9 55 80 c7 c0 e7 ca 67 f1 cb 58 e2 |.4...U.....g..X.| +00000330 6e 4d d4 9e 18 c3 37 c2 ff 72 bc cb 8e 6a 97 e2 |nM....7..r...j..| +00000340 b5 83 75 34 2a 75 9f 7f 8e 1e 47 e6 cd 53 85 c5 |..u4*u....G..S..| +00000350 69 b6 c0 46 9f 46 a8 09 6a 21 d5 af 36 d2 d0 ba |i..F.F..j!..6...| +00000360 65 0f da a5 af eb 3a 0c 8b 85 00 2a dd 11 71 28 |e.....:....*..q(| +00000370 5b 71 a9 df 69 20 8a d9 27 1e 4f 02 89 03 6f 27 |[q..i ..'.O...o'| +00000380 20 e1 37 17 69 c2 62 3e 46 39 43 2d 64 43 f3 cc | .7.i.b>F9C-dC..| +00000390 14 5f a0 73 06 bf 42 cb da 79 21 28 b1 a1 c4 de |._.s..B..y!(....| +000003a0 39 98 83 ad 3a d6 05 fd 58 b0 2c 97 bf 48 74 0e |9...:...X.,..Ht.| +000003b0 25 17 03 03 00 35 69 10 76 25 e3 9e 63 10 76 73 |%....5i.v%..c.vs| +000003c0 f5 fc 90 2c 95 e5 dc 29 79 a0 ed 0a 3a 72 58 38 |...,...)y...:rX8| +000003d0 bf b9 17 af 77 9f 05 92 af d4 a7 c7 d6 56 77 01 |....w........Vw.| +000003e0 da 94 31 d2 be be 95 e1 b1 95 75 17 03 03 00 93 |..1.......u.....| +000003f0 f9 fa a9 41 89 d3 e8 3b cb 11 63 76 56 fe 28 86 |...A...;..cvV.(.| +00000400 87 b0 0f d0 4d a8 fb 22 e9 89 f6 40 8a db 51 be |....M.."...@..Q.| +00000410 2c 9f 9c 39 f4 43 bc 1f b0 32 9b 9c 8e a6 6e e1 |,..9.C...2....n.| +00000420 f3 f7 f0 91 ed 56 6f 2d be 37 6b 3b ed f7 5b a6 |.....Vo-.7k;..[.| +00000430 d3 14 0a f9 58 b8 7b 37 fc 15 97 57 79 16 8c 0c |....X.{7...Wy...| +00000440 d2 93 7a 58 b8 48 51 f7 58 82 7d a0 4b e1 41 f6 |..zX.HQ.X.}.K.A.| +00000450 e1 44 12 1e ea 80 f3 b6 d0 72 ec 5c 84 01 6a b3 |.D.......r.\..j.| +00000460 f7 83 b5 47 22 0b e7 03 60 09 a7 23 23 20 5e 6b |...G"...`..## ^k| +00000470 f6 25 34 64 11 ad 46 90 db cb 13 f5 10 0a 75 e8 |.%4d..F.......u.| +00000480 3e c8 03 |>..| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 27 f0 39 68 fc |..........5'.9h.| +00000010 9f 6c a4 fd a7 cf 1f 25 67 54 3c e6 9e 7c 99 5a |.l.....%gT<..|.Z| +00000020 e9 b7 3c 0c f2 dc b6 22 36 0d 43 a3 ee 76 4b a9 |..<...."6.C..vK.| +00000030 6a cb b8 f6 8a c8 58 91 79 19 95 7c 83 a0 87 57 |j.....X.y..|...W| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e d5 8a ef 04 f9 6c 27 62 0a f1 a4 |..........l'b...| +00000010 4b 7f e4 e4 ff 53 f3 61 20 b9 56 96 30 f9 06 c9 |K....S.a .V.0...| +00000020 cc 9c ed 17 03 03 00 13 4a 83 cd 86 98 97 20 45 |........J..... E| +00000030 ab 2f c5 72 15 f6 ed a8 8c 8c 0e |./.r.......| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndECDSAGiven b/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndECDSAGiven new file mode 100644 index 0000000..0b6eaf4 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndECDSAGiven @@ -0,0 +1,179 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ca 01 00 00 c6 03 03 54 78 64 8e b6 |...........Txd..| +00000010 69 c6 1c 8a 69 eb 09 ef 32 59 f9 9f 63 ac 6e 66 |i...i...2Y..c.nf| +00000020 97 b4 bb b7 71 27 60 52 af c4 64 20 26 de 8d 3e |....q'`R..d &..>| +00000030 90 5b c8 96 b5 10 a3 e4 67 f3 39 fb f5 b7 df 50 |.[......g.9....P| +00000040 2b 8f 2d cb a5 c4 0a c9 28 1b c3 21 00 04 13 01 |+.-.....(..!....| +00000050 00 ff 01 00 00 79 00 0b 00 04 03 00 01 02 00 0a |.....y..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| +00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| +000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 65 |-.....3.&.$... e| +000000b0 42 a2 bd 1e e0 0a 52 2d 7a 1e f0 37 86 db 9e c6 |B.....R-z..7....| +000000c0 d6 cd ff 7b 71 f3 4c a3 23 44 2d 94 60 93 0b |...{q.L.#D-.`..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 26 de 8d 3e |........... &..>| +00000030 90 5b c8 96 b5 10 a3 e4 67 f3 39 fb f5 b7 df 50 |.[......g.9....P| +00000040 2b 8f 2d cb a5 c4 0a c9 28 1b c3 21 13 01 00 00 |+.-.....(..!....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 f1 7c 16 5a 86 b4 |...........|.Z..| +00000090 13 82 93 fa ba 07 35 24 03 f5 24 25 cc 2d c8 e5 |......5$..$%.-..| +000000a0 6c 17 03 03 00 3e cb 02 08 06 a3 75 03 c6 5d d9 |l....>.....u..].| +000000b0 9c 66 ad db 29 6d 93 a6 53 c6 38 7f 9c 56 1e b1 |.f..)m..S.8..V..| +000000c0 f5 a8 77 19 43 c3 93 5e 67 dc 80 db 1b c8 30 b2 |..w.C..^g.....0.| +000000d0 04 85 6e 5c 8f 3a 4a f2 d2 aa 17 c7 d3 ea 29 f2 |..n\.:J.......).| +000000e0 09 08 49 90 17 03 03 02 6d dd 26 0f f5 1b 6b 11 |..I.....m.&...k.| +000000f0 1c c7 e9 87 bf de 58 08 e4 bc a6 49 98 fd bf 87 |......X....I....| +00000100 31 35 59 c1 88 5a 8c 0d e7 42 47 b6 cb ec 3c 6f |15Y..Z...BG...| +00000160 16 e6 ff be 29 a3 60 13 f8 8c 82 6c 84 dd c1 c8 |....).`....l....| +00000170 8b a2 bf e5 70 03 c3 a4 92 3d 99 a8 fc 92 15 e4 |....p....=......| +00000180 1d 13 7d b5 1f d3 a6 76 1c 8c 9f 9f e7 87 b4 fb |..}....v........| +00000190 25 b8 cf 83 0a 3b bd c7 e8 30 d4 15 6f ae d5 b9 |%....;...0..o...| +000001a0 da 3b c6 3f 0c 06 7a 78 e6 ac ca 64 cb 34 cc 7b |.;.?..zx...d.4.{| +000001b0 46 78 ec e2 22 9e 31 39 63 a7 7b 1d d6 c2 4b 91 |Fx..".19c.{...K.| +000001c0 45 fa 95 54 ef 9b b3 2e 55 83 77 c8 cf 15 b5 34 |E..T....U.w....4| +000001d0 11 4c 92 36 22 54 3d 2f b0 cb 28 7f 2b 1e b1 3f |.L.6"T=/..(.+..?| +000001e0 38 4a 4a d6 e8 a1 e6 e0 4f 20 ab 04 6f 6b 00 5e |8JJ.....O ..ok.^| +000001f0 d4 16 42 ab a5 04 67 9b 89 45 78 8b ea 0e 7d c8 |..B...g..Ex...}.| +00000200 24 d5 fb 83 c7 13 25 b7 1b 6f 3f 2a 2e cf bb 71 |$.....%..o?*...q| +00000210 11 48 5d e6 98 5e ca dd f7 6d dc 93 b1 51 1e 99 |.H]..^...m...Q..| +00000220 b9 e0 4c 39 c8 82 d8 9f 8d 70 25 78 5b b1 85 1d |..L9.....p%x[...| +00000230 cb 75 31 61 c3 ad d5 c1 d5 1f 26 06 60 5f cd eb |.u1a......&.`_..| +00000240 ee 4c 99 43 02 b9 e5 f5 99 98 94 cf 14 1c ad 54 |.L.C...........T| +00000250 20 a9 d3 73 f2 3f bc a1 25 39 8b ff c4 e0 ee 8b | ..s.?..%9......| +00000260 ba ec fc b0 c2 42 4c 5a 30 9c 26 1b f0 f2 da 94 |.....BLZ0.&.....| +00000270 26 69 55 0e fb 84 a0 58 95 43 08 6c 87 82 93 02 |&iU....X.C.l....| +00000280 cf 27 99 94 a3 ae 9f 08 d0 6e f2 a8 e8 29 fc a8 |.'.......n...)..| +00000290 67 d3 20 37 83 5d 8a 12 0a 57 10 bf 30 5a e1 05 |g. 7.]...W..0Z..| +000002a0 30 e0 b7 7b 47 7e a6 07 cc 9a dd 6d e8 11 89 c7 |0..{G~.....m....| +000002b0 7d 98 c3 6d 83 9f 1b f4 ff ca 31 c8 39 7b c2 fb |}..m......1.9{..| +000002c0 69 dc ee eb ab e2 39 72 35 6b 22 e4 84 2f 1d 58 |i.....9r5k"../.X| +000002d0 07 b0 9e 3e 69 ca ff 17 44 d6 e4 a8 56 6a 24 35 |...>i...D...Vj$5| +000002e0 08 39 42 41 da 76 4b 4f 00 ce 41 58 4e 70 d5 b6 |.9BA.vKO..AXNp..| +000002f0 50 b4 88 91 47 4a 89 04 ef e8 14 2e cf e3 9d 36 |P...GJ.........6| +00000300 c0 b5 2b 8e 42 2f 4b 95 39 55 6f 5a 23 5b 5e 05 |..+.B/K.9UoZ#[^.| +00000310 f0 34 70 c0 f7 92 54 e2 5c 52 20 b0 c1 2a 9a cb |.4p...T.\R ..*..| +00000320 3a 32 0e 93 77 96 f2 6a d8 f7 bc 7c d8 40 4e 5e |:2..w..j...|.@N^| +00000330 37 1c 8b aa 75 89 94 51 da 19 72 80 86 c8 3d bd |7...u..Q..r...=.| +00000340 fd 7d 06 13 bb 54 a1 0b 46 58 07 e5 35 b3 f3 ff |.}...T..FX..5...| +00000350 8a 98 9d e6 e8 05 17 03 03 00 99 5a 63 3c ff cc |...........Zc<..| +00000360 a0 ec 5f 52 4d 28 96 80 22 f7 8c a7 ad b7 1f 4a |.._RM(.."......J| +00000370 8c 46 79 06 31 96 46 f9 f0 57 8c c4 5b f9 71 61 |.Fy.1.F..W..[.qa| +00000380 34 0d 3e 78 67 05 1c 93 a7 a2 cd ea ce e5 a2 6e |4.>xg..........n| +00000390 37 4f 16 a4 e4 4c 60 d5 5a 37 f1 2a bf ce 2f 80 |7O...L`.Z7.*../.| +000003a0 ea 65 e6 25 03 fc 2b 17 3f a4 71 3f 04 46 2b f7 |.e.%..+.?.q?.F+.| +000003b0 12 b0 a6 f3 fc 8d cf 5e 95 85 84 88 e4 db 46 a4 |.......^......F.| +000003c0 f2 3a a5 27 44 3d a2 03 b3 65 af 1f e3 44 aa 02 |.:.'D=...e...D..| +000003d0 0f 39 eb 3d 0e 2a ae 0c 1b ed 84 df 8d e3 a2 1d |.9.=.*..........| +000003e0 6d 55 bf d6 13 f6 00 da 93 a7 fc b1 50 79 2c a9 |mU..........Py,.| +000003f0 93 cb 7d 70 17 03 03 00 35 9e b7 c2 c6 29 a9 43 |..}p....5....).C| +00000400 3f df 06 80 31 ac d9 f7 3b cd 14 16 a0 85 ca e6 |?...1...;.......| +00000410 34 70 e3 fc af 1c 94 9b 87 b3 17 6c a4 83 64 2c |4p.........l..d,| +00000420 6e 26 4c e9 ab 79 a9 c8 1d d4 1c 96 2c f2 |n&L..y......,.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 02 1e 08 6d ee 1c 88 |............m...| +00000010 63 86 93 3e 73 8e 87 6f 51 8b d3 d2 91 c5 cb 55 |c..>s..oQ......U| +00000020 2d 7c 9f 32 d8 0a ab e5 53 95 4b 0c 22 12 23 56 |-|.2....S.K.".#V| +00000030 07 ce 1b e1 46 f7 46 84 cb 47 83 62 4a 16 39 44 |....F.F..G.bJ.9D| +00000040 bf 58 25 6e f1 22 d0 ea 06 d8 da 44 91 bb 27 41 |.X%n.".....D..'A| +00000050 1f 6e 46 89 88 93 a7 0a 60 8f 1a e5 31 19 5c 27 |.nF.....`...1.\'| +00000060 a3 f6 8c 1b ee 5b 2b 21 c4 64 c7 d9 92 7b e9 ca |.....[+!.d...{..| +00000070 e0 16 29 d0 64 32 95 a8 8f a8 24 cc 56 c6 3e 7d |..).d2....$.V.>}| +00000080 1b f6 06 a6 fa d6 dc 79 38 60 4f 6f b7 e1 10 ab |.......y8`Oo....| +00000090 21 14 8e e1 90 95 6d b6 f3 ca 86 1a dd 32 c5 33 |!.....m......2.3| +000000a0 e1 fc 8c da 77 02 54 88 73 f3 72 71 c6 58 ad 1a |....w.T.s.rq.X..| +000000b0 10 b8 15 c3 69 f1 cc 71 b6 ea 7e b7 81 4b de 7b |....i..q..~..K.{| +000000c0 77 87 24 e0 c0 39 5c 5b 17 ad 7c 59 53 43 cf 7e |w.$..9\[..|YSC.~| +000000d0 cb 70 4d 51 f1 7e 8c 2b 19 61 13 75 bf 25 df 80 |.pMQ.~.+.a.u.%..| +000000e0 f2 fa cd 70 8d db eb bc 38 ae 6a 0c ad ef d2 e2 |...p....8.j.....| +000000f0 f0 f1 02 97 ce 37 8b 8f 9e bd 4f 92 40 e7 8f 9f |.....7....O.@...| +00000100 26 b7 cd ef cf 57 28 2f 12 cc 69 e1 be f2 59 c6 |&....W(/..i...Y.| +00000110 be dc 51 9a 67 be 4a f1 97 f9 7a d9 01 05 1f d0 |..Q.g.J...z.....| +00000120 2b 96 5b b5 4d 1d c1 2e 99 7e eb e3 20 92 b0 f8 |+.[.M....~.. ...| +00000130 ac 9f c1 e3 10 cd b1 e9 05 46 15 3c c2 fb ce 27 |.........F.<...'| +00000140 5e f1 47 e7 d8 ca 89 0e 77 37 86 6c c9 d4 e3 ae |^.G.....w7.l....| +00000150 1e 6e 63 4f 5c 2d aa a0 88 7c 35 47 87 e8 40 22 |.ncO\-...|5G..@"| +00000160 f8 45 2f 57 b4 e8 e1 95 45 58 02 53 3c 19 b5 92 |.E/W....EX.S<...| +00000170 73 55 fd 49 31 ec db dc 4c 6f 6f a7 9a 90 89 83 |sU.I1...Loo.....| +00000180 08 97 53 5a c6 6c 23 75 cd 68 37 54 2c 00 d3 56 |..SZ.l#u.h7T,..V| +00000190 5e 24 87 7b 92 a9 61 73 1e 84 31 0e ff d7 f2 fb |^$.{..as..1.....| +000001a0 62 5e f9 27 35 18 bb ca b2 c2 d7 5c bf 7f 6d 36 |b^.'5......\..m6| +000001b0 fa e6 02 4a d0 fa bd b8 c0 d0 2f 0c 27 6b 49 92 |...J....../.'kI.| +000001c0 20 54 01 ea 3c d2 07 f1 2e d6 e3 a3 a3 bd 1d 33 | T..<..........3| +000001d0 90 ee 26 ad a6 5c ee c7 de 4d e8 fc d2 b5 5a b5 |..&..\...M....Z.| +000001e0 7c 6f c5 61 23 11 20 eb 0f 7c b7 0a cc 8c 65 b7 ||o.a#. ..|....e.| +000001f0 e2 87 16 10 b0 fd 40 75 78 d1 3c 70 54 66 b8 cb |......@ux.>> Flow 4 (server to client) +00000000 17 03 03 02 98 07 3b b6 4e c1 7e 84 44 a0 5d 3c |......;.N.~.D.]<| +00000010 b8 45 37 1e bf 0f 43 cf d6 11 c7 0d d9 a4 25 7b |.E7...C.......%{| +00000020 27 fa 6e e1 9c 24 5f e5 f9 12 e8 a1 33 2e cc 24 |'.n..$_.....3..$| +00000030 43 3b ac e3 bd f2 7b 1d 66 70 eb 31 21 7f 3e 5e |C;....{.fp.1!.>^| +00000040 09 7a 29 8f 43 43 cb c4 6d 70 a7 51 1c 0f dc 21 |.z).CC..mp.Q...!| +00000050 e9 4c f5 16 8f 35 e8 5b ae 7f e0 47 e7 d4 53 66 |.L...5.[...G..Sf| +00000060 b2 cc ef 44 b7 3e 34 2b 32 a9 e6 89 b9 c6 f6 56 |...D.>4+2......V| +00000070 97 b3 78 37 3c 89 2f 35 8e a5 c7 ae c4 92 91 69 |..x7<./5.......i| +00000080 50 ae ee c9 7b 7a 3a 10 ce 1c 68 fd 09 57 3d 92 |P...{z:...h..W=.| +00000090 52 42 0e 4e 91 12 b4 fd e4 59 d4 1e 5a c7 25 b3 |RB.N.....Y..Z.%.| +000000a0 dd a1 dd 7d 7d 92 08 52 ec 85 15 c7 b6 60 70 fb |...}}..R.....`p.| +000000b0 76 6b 42 da 84 8e e5 a9 cb a4 b1 76 89 51 93 55 |vkB........v.Q.U| +000000c0 f3 92 aa cc 04 3b 78 97 ed 10 88 d8 77 d1 32 35 |.....;x.....w.25| +000000d0 93 82 a4 1d ca 47 df c8 72 93 10 90 e0 75 2d 3f |.....G..r....u-?| +000000e0 b0 6a 3d 9e b6 20 1d 0a 2a 03 66 be 18 18 d3 25 |.j=.. ..*.f....%| +000000f0 47 a2 ab 67 08 44 24 cb 94 29 8a f7 8b 8e ca a0 |G..g.D$..)......| +00000100 20 71 d0 af 87 5b e1 d9 5d e0 0c 70 13 3d 82 42 | q...[..]..p.=.B| +00000110 b3 b8 fb 5e 1d f1 58 88 ea 11 67 28 49 11 d4 27 |...^..X...g(I..'| +00000120 05 87 e4 b1 21 15 d1 3a 6a df ee 6d 40 7c 3f 8c |....!..:j..m@|?.| +00000130 7e cd 7b 0c 0e ef fd 17 29 29 f8 03 98 8e 76 ac |~.{.....))....v.| +00000140 23 e2 81 30 8b c7 7b 9b 5a 78 f7 6a 53 32 5c bd |#..0..{.Zx.jS2\.| +00000150 d7 42 cb 77 f5 1d ea 03 74 9f ec 1d 1b 68 72 aa |.B.w....t....hr.| +00000160 9f e0 7d 58 2f 26 47 6b 2d e4 1f 78 f4 ab d3 ae |..}X/&Gk-..x....| +00000170 51 6c 2a 35 0a 6f 9a c8 2b 75 ff 69 3e 4b 61 bc |Ql*5.o..+u.i>Ka.| +00000180 03 29 60 04 8b 53 9f ae e4 00 7f 88 7a d4 70 b8 |.)`..S......z.p.| +00000190 65 83 87 96 5d ef f1 b2 e8 7e 0e af 0b 2c 07 dd |e...]....~...,..| +000001a0 a9 0e f8 c3 9b 59 aa cf 74 02 5e 46 8c cb 3d ee |.....Y..t.^F..=.| +000001b0 72 67 7c 46 37 29 78 d8 80 6e 42 16 b7 a8 59 35 |rg|F7)x..nB...Y5| +000001c0 cb 36 ce 73 50 80 d2 35 7a 69 b9 f3 14 73 04 e7 |.6.sP..5zi...s..| +000001d0 ec dd 92 80 b0 f6 b7 51 28 15 56 c4 bb 83 00 86 |.......Q(.V.....| +000001e0 9e 21 e7 bd 91 33 15 d4 aa da 8a 07 eb 2e d9 48 |.!...3.........H| +000001f0 c3 71 1a da be 6f 00 45 bd 08 a3 70 17 d5 c0 1a |.q...o.E...p....| +00000200 74 87 5a 95 60 aa 1d ce 0e e1 46 57 85 8c e0 ae |t.Z.`.....FW....| +00000210 98 1a f9 83 7f ec 04 bd 90 dc 51 4f 7e d2 52 28 |..........QO~.R(| +00000220 ca 33 f6 60 4a 0c e4 7d b3 93 4f 70 7a ce d3 3e |.3.`J..}..Opz..>| +00000230 0a dd 50 b0 17 0a 2e db 2c ad 3d 86 d3 e6 60 07 |..P.....,.=...`.| +00000240 43 61 9c a0 ff 45 37 9a 60 3d c5 f7 4d 27 fc b4 |Ca...E7.`=..M'..| +00000250 9a 05 1c 0a ae 08 9d d9 5c 15 09 c9 8e 24 bb e2 |........\....$..| +00000260 ec a1 a7 27 f0 42 97 a9 af ed 25 fd 5f f1 2a 4d |...'.B....%._.*M| +00000270 ac ab 9c a5 7d 28 6b c8 36 ec 0c 12 5b eb fa 64 |....}(k.6...[..d| +00000280 83 74 13 6e 44 5a 23 38 f0 a6 22 3e f9 88 f1 0d |.t.nDZ#8..">....| +00000290 2a 55 b8 bf aa 87 de a4 7f 8b ba 52 23 17 03 03 |*U.........R#...| +000002a0 00 1e fb 80 15 2b ff db 63 29 a7 77 ef 1e 82 28 |.....+..c).w...(| +000002b0 8d d5 f0 5b 5d 42 8e 34 f9 64 5c 47 eb c3 10 4c |...[]B.4.d\G...L| +000002c0 17 03 03 00 13 a1 8b 9e d8 57 0e 04 96 7c b4 83 |.........W...|..| +000002d0 70 a2 20 03 ee 28 23 c7 |p. ..(#.| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndEd25519Given b/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndEd25519Given new file mode 100644 index 0000000..d80b76f --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndEd25519Given @@ -0,0 +1,149 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ca 01 00 00 c6 03 03 3d 6d 5a b0 92 |...........=mZ..| +00000010 7b 62 6d 14 22 f5 08 70 77 4a 80 fa 69 1a 1c 92 |{bm."..pwJ..i...| +00000020 4c d3 e5 ca 3a d0 ee 33 40 c8 64 20 e5 a7 f1 57 |L...:..3@.d ...W| +00000030 39 32 e3 9f 7c 33 58 16 61 58 29 44 aa e4 50 b1 |92..|3X.aX)D..P.| +00000040 37 c5 59 27 f2 d5 b8 6e 01 24 c2 6b 00 04 13 01 |7.Y'...n.$.k....| +00000050 00 ff 01 00 00 79 00 0b 00 04 03 00 01 02 00 0a |.....y..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| +00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| +000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 cb |-.....3.&.$... .| +000000b0 da f4 03 da e7 6f e5 2b 25 c0 cb cf 52 0a fb af |.....o.+%...R...| +000000c0 8a 87 4c 2b 88 e4 1a b3 a0 34 30 fb 9d 4e 0e |..L+.....40..N.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 e5 a7 f1 57 |........... ...W| +00000030 39 32 e3 9f 7c 33 58 16 61 58 29 44 aa e4 50 b1 |92..|3X.aX)D..P.| +00000040 37 c5 59 27 f2 d5 b8 6e 01 24 c2 6b 13 01 00 00 |7.Y'...n.$.k....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 2d 8b 08 3c eb 5e |..........-..<.^| +00000090 e6 d7 8e 9a 11 d0 e1 a3 3f 88 cc 83 49 e3 af 50 |........?...I..P| +000000a0 66 17 03 03 00 3e 24 ba 0e 2f d7 51 a9 52 5d 51 |f....>$../.Q.R]Q| +000000b0 a4 7d b6 dc 5c 43 2e d8 58 5e 72 f1 86 98 15 b8 |.}..\C..X^r.....| +000000c0 db 0a 48 0a 06 c4 ad 36 41 84 f1 89 36 e9 24 da |..H....6A...6.$.| +000000d0 05 5a dc 82 02 a1 3d 39 ae 4c 7e d9 7b 43 1f 2c |.Z....=9.L~.{C.,| +000000e0 06 71 a0 2f 17 03 03 02 6d 48 44 6b d1 65 fb e1 |.q./....mHDk.e..| +000000f0 fb 96 00 e5 ad c6 60 e2 b5 f6 bf 7c b7 f4 6f 0e |......`....|..o.| +00000100 db a2 4b f7 cd d7 73 29 f8 af 23 5d d4 55 df 37 |..K...s)..#].U.7| +00000110 b7 62 38 d0 95 5c f1 48 32 5f cb fa 67 18 20 7f |.b8..\.H2_..g. .| +00000120 b7 0f ac fc 64 b7 b0 7b 4b 1f 65 1d 2a 94 8d 76 |....d..{K.e.*..v| +00000130 b4 30 3b ee 44 a5 f6 74 5b 7e bd a7 bb b2 d8 d6 |.0;.D..t[~......| +00000140 ac c6 1f b4 88 34 85 7e 89 2c 2e 0d bf 6c 16 0c |.....4.~.,...l..| +00000150 ce 35 57 13 29 55 60 20 86 21 20 c0 46 bc 9e dd |.5W.)U` .! .F...| +00000160 8a a0 41 60 b5 a9 16 cc 66 cb 4a ba 58 e0 70 d1 |..A`....f.J.X.p.| +00000170 a5 b4 eb ac 54 7e 95 11 00 f0 70 63 af 56 57 99 |....T~....pc.VW.| +00000180 68 57 b4 5b aa db f1 08 2e c0 fb df 93 b8 4a f8 |hW.[..........J.| +00000190 2e 04 b3 2c 2b f9 47 09 a1 5f a3 3e 97 eb d4 d5 |...,+.G.._.>....| +000001a0 df ec d1 9e 05 5e 10 b0 2b 7e 0e b4 c8 e1 e3 50 |.....^..+~.....P| +000001b0 29 19 8b 3c f7 d0 95 30 ae 4c e4 60 c8 13 09 15 |)..<...0.L.`....| +000001c0 b7 80 f3 ad a0 06 6b a7 b7 4a c4 6d 65 09 21 d3 |......k..J.me.!.| +000001d0 3b 56 dc ce f5 d3 fa 93 e9 03 8e 0c c9 47 21 89 |;V...........G!.| +000001e0 7f 39 23 f8 aa 68 f6 b4 82 50 1f b8 46 5d 26 dc |.9#..h...P..F]&.| +000001f0 b1 1f e5 e5 6b ad ad 0d d8 55 b7 8b 7a f8 5d fc |....k....U..z.].| +00000200 bd 74 a4 15 72 33 1b a7 3b 8c 09 55 d9 fd 21 bf |.t..r3..;..U..!.| +00000210 cd dd 67 d2 0c d0 bd 9b de 52 e3 5f 4d 54 c0 6c |..g......R._MT.l| +00000220 bd 93 ae 66 55 4b e9 75 6b db cd 6b 80 33 f4 b7 |...fUK.uk..k.3..| +00000230 61 9e e4 5d 75 b5 44 26 79 b5 da bf af 54 8c 40 |a..]u.D&y....T.@| +00000240 23 99 32 60 2a 76 b3 0a 46 37 c9 85 1c fe e9 a1 |#.2`*v..F7......| +00000250 a3 e8 61 67 04 eb 3e e8 2b d3 12 75 87 04 67 40 |..ag..>.+..u..g@| +00000260 19 63 c5 ef 75 d0 39 63 a0 c3 ae 3c b1 88 34 db |.c..u.9c...<..4.| +00000270 c7 29 0c 33 c8 40 c0 b0 e6 76 44 cc 99 4f 2b a6 |.).3.@...vD..O+.| +00000280 b3 e1 28 69 6c 41 74 55 53 a9 87 06 9a cb 14 5d |..(ilAtUS......]| +00000290 ec 74 77 e2 a0 ce 54 02 ba f8 04 2c 84 9a de 2b |.tw...T....,...+| +000002a0 dc 02 32 01 ad 96 5c a0 87 3c 55 dd ee 4d cb fd |..2...\..>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 01 50 d8 03 a6 37 13 |..........P...7.| +00000010 5f fb 65 9f 33 33 79 ae 89 c3 de ea 4b 55 e2 b3 |_.e.33y.....KU..| +00000020 13 07 0d 95 c6 f7 79 74 ad 8a 42 dd 78 55 a5 01 |......yt..B.xU..| +00000030 69 f2 11 cf 72 de 85 04 56 78 9c ba 21 77 b8 76 |i...r...Vx..!w.v| +00000040 e3 58 23 3d 2b 8a ee a4 5c 52 60 4b 50 0d c4 83 |.X#=+...\R`KP...| +00000050 a1 8d 06 82 68 99 34 65 7a 7b 55 8e 46 04 47 55 |....h.4ez{U.F.GU| +00000060 4d 42 02 41 b6 e4 dd a4 33 6a 04 97 e6 4a 80 3a |MB.A....3j...J.:| +00000070 e1 7e 0a a5 4f 0c f9 de 7a 91 96 4f 6a 6a 8a 4b |.~..O...z..Ojj.K| +00000080 fd 24 b9 bf e7 d5 5a 27 17 18 45 77 1d e2 c9 ea |.$....Z'..Ew....| +00000090 23 57 c4 e1 30 9e de d2 bd 0c 28 59 dc a1 12 d9 |#W..0.....(Y....| +000000a0 ee 2e 43 4b 83 fc d7 6c a4 e7 47 c4 14 c1 1f ee |..CK...l..G.....| +000000b0 79 60 26 86 73 5c ec c9 c0 ec f9 c9 38 98 2d ba |y`&.s\......8.-.| +000000c0 10 83 1b fe 8f cf 59 77 f0 60 fe c0 d0 7e 0f 2d |......Yw.`...~.-| +000000d0 69 04 dd 79 49 c5 b1 d9 9b 48 ad de 55 cf d3 47 |i..yI....H..U..G| +000000e0 9b eb 64 ae ed cb b0 48 78 a9 27 24 b8 8d 53 36 |..d....Hx.'$..S6| +000000f0 b7 0f 82 1c ee 11 4b 5a 98 1d 21 73 b4 f4 06 ce |......KZ..!s....| +00000100 50 bc 36 27 e1 87 70 04 68 1b 30 3a 86 68 b3 71 |P.6'..p.h.0:.h.q| +00000110 8c 57 69 60 d6 a8 bd fa 13 46 2b 52 00 dc 45 53 |.Wi`.....F+R..ES| +00000120 06 79 5b 96 78 69 d0 a8 cd 2d 39 8c 11 12 9f 65 |.y[.xi...-9....e| +00000130 72 01 5e b4 c5 df bc 9d a2 7f 00 a7 cc 95 3b 0b |r.^...........;.| +00000140 09 05 19 9f a5 b7 dd 48 3f ab f1 aa 36 da 70 96 |.......H?...6.p.| +00000150 0f f9 f3 bc 80 84 09 a3 76 92 56 17 03 03 00 59 |........v.V....Y| +00000160 4a ba a9 1c c7 f6 ef 77 8e cc 9a 8c 51 9f 43 1e |J......w....Q.C.| +00000170 ec 8f f3 33 93 eb 81 db 06 03 97 fd 3f b2 e0 e5 |...3........?...| +00000180 e7 73 b2 2c 2c f0 c0 a4 51 18 10 79 4e 30 96 3a |.s.,,...Q..yN0.:| +00000190 d8 26 b1 a0 f4 1b e6 12 fe 74 58 68 97 45 1e 85 |.&.......tXh.E..| +000001a0 3a db 04 a6 12 5d ba 19 e4 f6 b1 17 f3 04 75 f2 |:....]........u.| +000001b0 ea 04 db 6c d4 d8 d5 cc fb 17 03 03 00 35 1d c5 |...l.........5..| +000001c0 cd 92 9c 80 3a ec 3c 06 3e 12 ed 7a 82 23 ab 18 |....:.<.>..z.#..| +000001d0 67 4a 92 7d 30 e4 57 7b 25 34 a1 54 46 41 b7 60 |gJ.}0.W{%4.TFA.`| +000001e0 69 cf a2 61 7a 59 6f b3 78 6f 41 0f 7d 9b 4f 00 |i..azYo.xoA.}.O.| +000001f0 91 c7 93 |...| +>>> Flow 4 (server to client) +00000000 17 03 03 01 ca 52 99 bb 74 e8 8e ab 48 c6 03 1d |.....R..t...H...| +00000010 f9 9a a8 be e4 b1 dc b9 8d e5 a8 11 2b d6 54 63 |............+.Tc| +00000020 6f 0d dc 6e d7 55 c8 af 3c 88 c4 3e ab 30 ab b9 |o..n.U..<..>.0..| +00000030 69 94 75 60 0f 75 77 e1 b1 29 09 9f db c1 74 43 |i.u`.uw..)....tC| +00000040 92 2a 55 b9 ae 71 12 79 b9 4d ba 82 84 96 b1 01 |.*U..q.y.M......| +00000050 14 b5 9c 5d 0c fe eb cc a6 44 e5 0b 93 1c 8d 45 |...].....D.....E| +00000060 d8 aa 7c 1b d1 47 5a 36 46 f8 f5 82 c7 fe 2b f3 |..|..GZ6F.....+.| +00000070 46 17 9f 0c 03 df cd dd 0a 38 77 28 45 45 f2 3c |F........8w(EE.<| +00000080 06 1d 88 1b 55 d8 8f 70 9b a8 bb 37 a8 41 81 a6 |....U..p...7.A..| +00000090 a7 f4 28 c1 f1 d2 8b ba 98 0e 35 92 88 ac cb b6 |..(.......5.....| +000000a0 25 dd 5e 62 d5 e7 e9 da 4f 0e 55 b4 36 4d 09 20 |%.^b....O.U.6M. | +000000b0 73 ef b3 6c 4c 6d c6 6a e9 f3 f8 28 74 0d 50 b0 |s..lLm.j...(t.P.| +000000c0 ad 75 f7 c5 fb eb bc 06 6b 07 23 80 70 87 8e a8 |.u......k.#.p...| +000000d0 3e 66 87 07 53 8e 19 bb 3f 94 f1 9e 4b 05 f6 55 |>f..S...?...K..U| +000000e0 34 3b d0 14 36 32 66 6a 62 8a ec 22 a1 82 0a 95 |4;..62fjb.."....| +000000f0 95 b6 85 0c 2c c4 b4 3e 00 59 2a 1e c6 03 4b 2a |....,..>.Y*...K*| +00000100 e4 06 d5 29 e5 a1 e1 57 b0 a1 45 1b b7 0c 12 3f |...)...W..E....?| +00000110 0d 31 1a b2 ef 3d 90 73 3a 39 28 00 8a 0d e0 20 |.1...=.s:9(.... | +00000120 83 a7 32 b8 02 d0 9f 90 f3 b3 ca df 36 ae d4 f8 |..2.........6...| +00000130 c4 4b 82 06 13 04 66 e7 01 63 4e e8 80 b8 52 c0 |.K....f..cN...R.| +00000140 8c a4 5b 3f b9 85 48 ac 01 f0 b6 ee db 73 d0 62 |..[?..H......s.b| +00000150 e2 05 e7 71 7e 87 4b 7b cf d0 a1 77 eb 38 64 85 |...q~.K{...w.8d.| +00000160 5c 3d af fc e3 17 46 e7 c5 71 c9 63 bf 03 ae 35 |\=....F..q.c...5| +00000170 7b 60 61 5d 5a 7b 57 88 79 82 55 68 45 a1 59 bc |{`a]Z{W.y.UhE.Y.| +00000180 e5 3b 5a 31 32 5c 24 13 e3 fc b7 53 41 76 1d 24 |.;Z12\$....SAv.$| +00000190 7f 08 89 c6 f0 b9 57 3a 4d 91 66 66 e4 57 33 51 |......W:M.ff.W3Q| +000001a0 1d b9 1e c5 68 9a 6a 74 1e c3 16 de 15 92 e3 d0 |....h.jt........| +000001b0 0a 64 a4 64 e8 c4 a5 9c 55 30 a9 c3 b0 53 72 54 |.d.d....U0...SrT| +000001c0 75 d7 a0 7a 54 85 6e 9a 4d ff 9f 13 3c b9 42 17 |u..zT.n.M...<.B.| +000001d0 03 03 00 1e 6f 06 3f 1c da f6 55 50 05 de 38 9d |....o.?...UP..8.| +000001e0 07 00 bb 28 32 a5 3f 04 22 4c 6e f2 ea 3a e0 cc |...(2.?."Ln..:..| +000001f0 5d 5b 17 03 03 00 13 3b b8 7c df 14 b4 ba fa 6e |][.....;.|.....n| +00000200 2e 61 d6 6b bf b5 ad c2 35 73 |.a.k....5s| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndGiven b/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndGiven new file mode 100644 index 0000000..800f999 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ClientAuthRequestedAndGiven @@ -0,0 +1,177 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ca 01 00 00 c6 03 03 c8 2f b4 54 5b |............/.T[| +00000010 11 8a 88 a9 a2 9b bf 66 f2 b4 e5 fb 32 af d6 dd |.......f....2...| +00000020 6c 6c 99 4f d6 48 cd eb 63 6e 1d 20 bb 0a 48 2e |ll.O.H..cn. ..H.| +00000030 45 4e 86 2d ae d6 fb 3e 0c 3e 9f a3 17 4a e3 39 |EN.-...>.>...J.9| +00000040 58 a7 92 92 cb 30 03 0d be b5 79 a5 00 04 13 01 |X....0....y.....| +00000050 00 ff 01 00 00 79 00 0b 00 04 03 00 01 02 00 0a |.....y..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| +00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| +000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 f0 |-.....3.&.$... .| +000000b0 8e 19 a6 04 b7 f1 b0 cd a1 28 bb 10 60 30 92 dc |.........(..`0..| +000000c0 bc 7a 1c fc a7 f4 dc 01 2e 88 f3 0e 80 82 71 |.z............q| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 bb 0a 48 2e |........... ..H.| +00000030 45 4e 86 2d ae d6 fb 3e 0c 3e 9f a3 17 4a e3 39 |EN.-...>.>...J.9| +00000040 58 a7 92 92 cb 30 03 0d be b5 79 a5 13 01 00 00 |X....0....y.....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 1a 9d c2 a8 12 c1 |................| +00000090 c3 97 41 bd 1f 6e 48 98 36 4b 13 cd b9 9f 70 34 |..A..nH.6K....p4| +000000a0 60 17 03 03 00 3e f8 19 ab 88 f7 15 07 97 72 ec |`....>........r.| +000000b0 41 6c 0a 64 b3 26 4a 56 21 20 d7 9c a2 84 06 ab |Al.d.&JV! ......| +000000c0 cb e6 99 1b 45 ce ca e7 c6 57 04 c9 3a 76 84 97 |....E....W..:v..| +000000d0 fe a3 be 60 b2 2c 53 31 ab cd 49 d5 fc 59 80 69 |...`.,S1..I..Y.i| +000000e0 38 d3 66 32 17 03 03 02 6d 8f 8b 7a 7d 78 d3 4b |8.f2....m..z}x.K| +000000f0 98 1e 0b 05 38 60 58 d0 0a 7a f8 a7 70 53 67 ce |....8`X..z..pSg.| +00000100 ea ed 86 3e 79 9d 37 66 b2 61 be 34 bf 15 5a d8 |...>y.7f.a.4..Z.| +00000110 4e fb 52 62 8d e2 ae e9 58 b9 bc f9 e9 75 81 16 |N.Rb....X....u..| +00000120 af fa 92 c3 aa ac d2 2c 7b c2 21 2f b0 0d e9 53 |.......,{.!/...S| +00000130 d3 e3 ec d5 e7 95 23 83 d9 b1 ff 25 55 47 6a 1c |......#....%UGj.| +00000140 97 37 84 9a ce 67 15 63 0f ff 24 63 af 43 8a 7d |.7...g.c..$c.C.}| +00000150 46 63 bb 33 67 7a de 86 b4 6a 70 2d 6a 7f 82 c2 |Fc.3gz...jp-j...| +00000160 24 3c e1 0f a9 7f 93 76 d2 c9 e2 56 d3 cb b9 17 |$<.....v...V....| +00000170 97 2f 8a 25 40 dc 35 e4 00 3a 3f 2b 1e 09 1b f2 |./.%@.5..:?+....| +00000180 12 2a 76 c0 2e cd 17 06 32 a9 f8 08 70 3f 06 fa |.*v.....2...p?..| +00000190 c7 1b c4 50 4f b8 1e 0f 6f 6a 3a ba f6 28 1b d0 |...PO...oj:..(..| +000001a0 a7 34 a5 8c 02 fe 35 4f b4 97 45 96 48 bc b9 0d |.4....5O..E.H...| +000001b0 c9 2f df bd c1 8b 19 44 33 12 90 2c d2 99 09 36 |./.....D3..,...6| +000001c0 97 3f 29 56 30 77 15 df 15 c9 b1 26 9c f4 6a 59 |.?)V0w.....&..jY| +000001d0 00 3e d8 28 74 19 6c 38 6c 68 63 16 ab cb f0 3d |.>.(t.l8lhc....=| +000001e0 ce 30 f6 9c 06 00 06 cc 5a 8e 78 73 af 53 a4 e6 |.0......Z.xs.S..| +000001f0 49 10 5b 9d 4d f3 7d 48 f0 5d 87 27 d8 7e 58 a6 |I.[.M.}H.].'.~X.| +00000200 86 51 a0 d6 e8 82 20 6b d3 f9 99 4d 11 b7 49 ad |.Q.... k...M..I.| +00000210 f9 1a 1b f5 cd 81 81 bd 51 76 a4 5a 5f 35 7a 52 |........Qv.Z_5zR| +00000220 12 1b 73 f6 f3 1d cf 93 7a 8e a0 1d 4c f3 b2 f5 |..s.....z...L...| +00000230 16 00 57 21 2f c6 85 af 8c 8b f9 bd 2a f1 ee 15 |..W!/.......*...| +00000240 ec ee 80 b9 8b 0a 50 36 cb 53 fd ca 53 b4 0e 96 |......P6.S..S...| +00000250 7b db e6 93 f7 9e 8d e4 6a d5 ff e3 74 31 76 3a |{.......j...t1v:| +00000260 a8 de ce 06 97 3d 4e 91 c5 cd 85 06 c9 a6 02 91 |.....=N.........| +00000270 f9 36 33 8d 28 23 54 f5 c3 f0 b2 1a a1 6b b7 c6 |.63.(#T......k..| +00000280 d1 c3 31 ad d6 6f 0c 44 e4 34 d8 26 b6 ff 06 6f |..1..o.D.4.&...o| +00000290 f3 56 19 46 8d f3 75 c2 d9 69 4a 5b ff 3a b8 1d |.V.F..u..iJ[.:..| +000002a0 86 a9 6f 45 dc 3a e4 aa 9b 7d 3a 5a 50 ad c6 f6 |..oE.:...}:ZP...| +000002b0 8c e3 0e ca b6 7a 99 e7 4b 58 26 c2 18 95 14 a4 |.....z..KX&.....| +000002c0 f9 ae 79 4f f6 c0 f8 0e d4 52 fb 3c 5d a2 30 9c |..yO.....R.<].0.| +000002d0 ea d9 8d f4 27 4c 6f 7a 02 45 8f ca 8c b1 bc d2 |....'Loz.E......| +000002e0 c5 dc 8b 09 d7 c4 0f ea f6 51 be f7 cd 01 1e 78 |.........Q.....x| +000002f0 a1 37 4a 88 ae 5f c5 79 9c e2 4d c9 74 e7 2e 18 |.7J.._.y..M.t...| +00000300 86 e8 62 3f 6c 39 73 eb c2 e2 54 0c 13 ca f6 57 |..b?l9s...T....W| +00000310 20 92 6a 1d 03 28 d0 53 6f 6e cb 57 da 33 20 1a | .j..(.Son.W.3 .| +00000320 c8 3d 09 73 5f 28 14 6f 4c 16 8c 41 cd 44 ad df |.=.s_(.oL..A.D..| +00000330 77 08 0f f1 3c 4c 2b 37 03 60 9d 07 85 e7 66 f7 |w........55.BL...| +00000400 3e 26 15 0a f1 c3 a6 ab 94 a3 72 bd c7 04 22 bc |>&........r...".| +00000410 67 32 15 16 23 f5 50 97 bc 7f ab f8 ef f0 02 7d |g2..#.P........}| +00000420 2d 76 01 18 72 18 77 c1 f5 9b e9 e9 97 8d |-v..r.w.......| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 02 11 4b 29 10 c9 7b |...........K)..{| +00000010 98 9a fa ce 7a 17 a4 7d 15 5f 97 4f 40 67 37 f0 |....z..}._.O@g7.| +00000020 0b 2d ca 62 77 23 ab 78 d7 9f b6 1d 5c 64 fb 68 |.-.bw#.x....\d.h| +00000030 70 5f 21 df e1 55 3b e3 bb 8e 61 31 11 ba 2b eb |p_!..U;...a1..+.| +00000040 de 78 39 5c 31 62 a3 fb 9a 57 a4 50 34 43 76 55 |.x9\1b...W.P4CvU| +00000050 ae f9 36 b1 35 ee 2b 8d ab c2 70 52 b0 8c d6 1b |..6.5.+...pR....| +00000060 fe 0f fc 5e 79 c3 cf ab d3 9a 81 af 63 2c b3 f7 |...^y.......c,..| +00000070 a6 b7 13 c4 70 22 fa 56 6d 77 cb d1 bf a5 9e c8 |....p".Vmw......| +00000080 74 83 80 f9 9a 19 f3 a3 94 15 72 7c 55 0e 21 47 |t.........r|U.!G| +00000090 2b a2 d3 b8 74 e1 07 37 7f 12 f6 ad ba 71 e5 ca |+...t..7.....q..| +000000a0 17 42 2b 78 9e 90 7d 28 b1 f4 dd 7d b8 69 dd c6 |.B+x..}(...}.i..| +000000b0 eb 3d 93 45 06 ac 5d fe 02 18 b8 f3 8c e4 4e 97 |.=.E..].......N.| +000000c0 05 8b 36 94 cb 0f 66 64 ed a8 50 22 ba c8 a7 23 |..6...fd..P"...#| +000000d0 7d f9 d5 4f d5 27 83 f3 b6 09 3f 4f 69 92 6d be |}..O.'....?Oi.m.| +000000e0 4a 30 02 d2 d5 e6 14 d4 21 e2 c8 5b cb 08 1e 9a |J0......!..[....| +000000f0 28 f7 f4 13 8c 58 9b 69 2c 55 3d 78 f2 ce 93 89 |(....X.i,U=x....| +00000100 2f 62 56 ea a3 21 96 f6 e7 ee a4 3d d8 7d 86 4d |/bV..!.....=.}.M| +00000110 79 c9 3b c8 cf ea a0 6b 5f 29 8c ed c2 d6 73 27 |y.;....k_)....s'| +00000120 a0 35 bb 2b 8b 6c 4e 59 74 e5 84 c4 d2 1a f1 0d |.5.+.lNYt.......| +00000130 5c 36 33 f7 42 d6 08 c3 f8 5b ea 27 a1 cc b9 72 |\63.B....[.'...r| +00000140 d5 b9 4e 17 36 b3 05 29 50 da 52 bc 23 f7 82 82 |..N.6..)P.R.#...| +00000150 c0 67 2b 80 a2 7f e2 ec b9 12 bb dc b6 04 b6 4f |.g+............O| +00000160 87 15 16 13 de c4 1c 04 71 33 ba d7 a7 da f1 f5 |........q3......| +00000170 77 c6 4e 8e b2 65 a1 6c a8 c2 5b a1 f5 da 49 6c |w.N..e.l..[...Il| +00000180 85 ee 21 8d 10 6b 82 bf 0c 0f 7e 33 8b 5e 44 5b |..!..k....~3.^D[| +00000190 70 db bc 76 40 a0 5c 02 f6 8a 9b de aa a4 b2 94 |p..v@.\.........| +000001a0 d0 e0 b7 60 af df ad 3d e3 17 a9 60 e0 d9 a8 3e |...`...=...`...>| +000001b0 c6 06 9b ad 97 0b dc 21 16 9d 42 29 74 a1 f5 03 |.......!..B)t...| +000001c0 d4 15 0d ee fd fa 6b 85 12 2f 8c 26 fd 96 ce 85 |......k../.&....| +000001d0 a5 b7 ba bb ac 8a 6d 54 f5 fd e6 6c 32 24 a9 e7 |......mT...l2$..| +000001e0 1a 11 bf 4d cb f9 18 9a b8 1e a6 e4 1f 61 b1 ce |...M.........a..| +000001f0 1c ca 5d 81 e7 84 e0 a9 4e c7 f9 5d 71 72 76 4b |..].....N..]qrvK| +00000200 65 ca 3a a4 4d d8 ec 82 aa 33 80 bb 15 48 2d 7c |e.:.M....3...H-|| +00000210 4e 5e d2 ec 13 1a e7 03 d5 29 95 80 17 03 03 00 |N^.......)......| +00000220 99 60 a2 43 34 23 c0 a4 4c 0a 18 c5 27 96 2f 7c |.`.C4#..L...'./|| +00000230 af 2b 2c 36 f2 9b cf 93 e7 3e 79 3b 20 d4 3b 60 |.+,6.....>y; .;`| +00000240 a2 ef af 36 d5 45 d4 20 89 be 80 1d 1e ca f7 19 |...6.E. ........| +00000250 35 8f 26 3f be c0 a2 f6 c6 85 a3 88 76 cd 06 f9 |5.&?........v...| +00000260 4f ff 54 79 6c ac 33 71 31 90 70 36 eb 9c c1 b4 |O.Tyl.3q1.p6....| +00000270 4a c8 3a 52 85 2b be 4a 19 8a 24 fd 6f 08 47 19 |J.:R.+.J..$.o.G.| +00000280 84 88 a0 48 f6 17 80 f8 fe 9e 21 68 e1 75 17 14 |...H......!h.u..| +00000290 d4 e2 3a e2 de 9d 19 56 ad cc 33 13 f3 52 b2 1b |..:....V..3..R..| +000002a0 f4 65 04 05 79 9f 3e 14 fb 1f 9c d1 c4 53 c0 93 |.e..y.>......S..| +000002b0 49 ad 3c 2e de c1 b4 fe be b3 17 03 03 00 35 32 |I.<...........52| +000002c0 81 98 1a 6c 38 ca 67 64 c5 30 0b 81 7d fd a1 b9 |...l8.gd.0..}...| +000002d0 2e af 41 1d e9 b7 31 17 d8 08 ce d5 f6 12 4d da |..A...1.......M.| +000002e0 fc db fb e1 fa 5b cd 70 12 e7 bb 26 dd 53 9c 43 |.....[.p...&.S.C| +000002f0 02 06 1f 70 |...p| +>>> Flow 4 (server to client) +00000000 17 03 03 02 8b 8e b1 29 40 b6 53 bc 89 c7 87 69 |.......)@.S....i| +00000010 4c 6d 5b 61 d9 ba 5b 96 22 ac 57 71 58 f8 0e ea |Lm[a..[.".WqX...| +00000020 81 ea bf f9 34 6d a0 ce 1f d2 97 52 62 2b 9e f7 |....4m.....Rb+..| +00000030 03 28 96 56 c0 a1 0e 69 7c 98 13 e5 91 8c 48 5f |.(.V...i|.....H_| +00000040 4e 78 87 14 38 f8 fa 3c 17 97 f9 de 38 3b cf 0f |Nx..8..<....8;..| +00000050 d9 dd 41 0a bb 65 ca a7 0b fd a5 11 c2 c3 6a b8 |..A..e........j.| +00000060 5a e1 68 a1 8d f8 35 9d c6 e1 3e e1 03 a9 06 ee |Z.h...5...>.....| +00000070 1f 92 ca b5 f4 df 3e e5 69 63 9e a2 ea 5e b8 d9 |......>.ic...^..| +00000080 26 31 9e 25 de a8 ea 44 1a c0 86 0b 38 75 04 dc |&1.%...D....8u..| +00000090 2d 37 ad 40 e3 2f d1 b0 9e 9e 64 57 8b 31 20 d6 |-7.@./....dW.1 .| +000000a0 16 64 fd 1b c1 01 58 af 4b 88 49 23 7a f6 a2 15 |.d....X.K.I#z...| +000000b0 ca 02 4b d6 6d 7c f8 7a c9 c0 0d 32 6e 1d 83 ca |..K.m|.z...2n...| +000000c0 47 e5 6f 86 a0 f7 8b 50 1d 91 ec fa 2b 4a 72 f7 |G.o....P....+Jr.| +000000d0 a0 09 f1 65 fb 81 32 d2 a0 be 18 07 9f 5d 89 98 |...e..2......]..| +000000e0 08 09 a6 1d 9a 5a 10 67 81 58 82 00 9d 01 48 a8 |.....Z.g.X....H.| +000000f0 5b df 54 b3 cd 84 87 e0 41 e6 1e 47 46 33 56 0c |[.T.....A..GF3V.| +00000100 67 82 b9 bc 28 68 f3 5b 51 a8 c0 0e 43 14 62 bb |g...(h.[Q...C.b.| +00000110 8a bd 3f 4d d6 33 c4 76 4f c1 06 f8 9b bf 64 41 |..?M.3.vO.....dA| +00000120 6c e5 40 8d 93 4a 6b 6f fe 72 6b db ac 35 b4 fc |l.@..Jko.rk..5..| +00000130 84 13 fa 8a 7d 35 e3 73 12 eb 1a 5f a9 e2 28 53 |....}5.s..._..(S| +00000140 0c 6d 41 ec 4b 76 f5 d9 48 2a c2 85 2a 1f 7d 61 |.mA.Kv..H*..*.}a| +00000150 f6 1f 27 ef 47 c9 c7 b3 19 5c 07 d5 18 ec fd 3e |..'.G....\.....>| +00000160 78 41 cb a4 3a 47 22 cf 7e 7e 17 be 27 c4 90 ce |xA..:G".~~..'...| +00000170 2a cb cd ed 0f a3 bf 1e 4c 62 7a 80 ff 21 38 c5 |*.......Lbz..!8.| +00000180 c2 37 9f 62 4b d8 c0 9e df ae 3c 69 cd 25 f5 65 |.7.bK.....>> Flow 1 (client to server) +00000000 16 03 01 00 ca 01 00 00 c6 03 03 15 b6 db 09 24 |...............$| +00000010 50 ea d6 f7 ae d7 32 2f 72 25 23 db 11 ad 6f c1 |P.....2/r%#...o.| +00000020 5d 62 af e7 93 63 1a 8b f3 82 80 20 5f 15 2e 86 |]b...c..... _...| +00000030 86 2c 2e 2f 82 11 3c d2 9f 00 32 d4 3d 05 04 fa |.,./..<...2.=...| +00000040 36 41 8d dc 30 ce a6 2b 6e d4 3c 9c 00 04 13 01 |6A..0..+n.<.....| +00000050 00 ff 01 00 00 79 00 0b 00 04 03 00 01 02 00 0a |.....y..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| +00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| +000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 98 |-.....3.&.$... .| +000000b0 b7 40 03 d8 a3 4c 9e 16 82 77 16 9b c1 17 3a 2a |.@...L...w....:*| +000000c0 fc 25 73 5d 2d 5c dc 15 78 36 12 7a 28 f2 0e |.%s]-\..x6.z(..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 5f 15 2e 86 |........... _...| +00000030 86 2c 2e 2f 82 11 3c d2 9f 00 32 d4 3d 05 04 fa |.,./..<...2.=...| +00000040 36 41 8d dc 30 ce a6 2b 6e d4 3c 9c 13 01 00 00 |6A..0..+n.<.....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 14 12 e8 30 75 5a |.............0uZ| +00000090 a4 27 7d 83 2e 51 0e 48 14 7b 53 0c 65 24 71 c5 |.'}..Q.H.{S.e$q.| +000000a0 44 17 03 03 00 3e 34 38 ac c0 b5 05 e1 03 e1 a3 |D....>48........| +000000b0 d3 42 ec e3 94 96 e7 a3 05 d8 44 ca 1d 89 b6 6f |.B........D....o| +000000c0 52 ce 3c 7d 61 f1 b4 a2 83 31 ab cf e7 ca 53 57 |R.<}a....1....SW| +000000d0 b8 eb f4 7a 8a 7c ce 31 fe a4 b6 c7 a5 ed f2 2d |...z.|.1.......-| +000000e0 da 36 d6 49 17 03 03 02 6d 2c b4 e1 f3 87 4e c7 |.6.I....m,....N.| +000000f0 ab db ea fa 0d 31 20 f2 1e 63 1d 10 bd 61 98 a2 |.....1 ..c...a..| +00000100 50 8d 12 0d c8 5c f8 e4 97 9c 5f f3 47 f4 60 a5 |P....\...._.G.`.| +00000110 59 16 a2 27 06 94 80 93 af 1e 9d c0 9a 23 20 bf |Y..'.........# .| +00000120 a4 5a 26 2c 37 86 d8 8a b7 e2 bd e2 4f ab 53 65 |.Z&,7.......O.Se| +00000130 bd 34 2c 1a 88 72 bf 8f 20 0c e2 51 0f ea 3f 47 |.4,..r.. ..Q..?G| +00000140 dc 0e cd 21 3c d0 cc 7d 38 b8 b9 1b 20 67 83 a9 |...!<..}8... g..| +00000150 af 4c f7 7b c0 d9 00 5c 66 e3 d7 2e 3b 6a b5 9c |.L.{...\f...;j..| +00000160 6e f6 ed 96 25 3c ce ea db fa 85 ba e2 d8 4c 95 |n...%<........L.| +00000170 92 06 0a 38 19 7f 52 30 2b ef fc 23 c6 b3 e5 d1 |...8..R0+..#....| +00000180 83 2e 56 65 d6 ef 06 3a 71 d6 39 e9 16 62 65 78 |..Ve...:q.9..bex| +00000190 59 c1 9f 7f 99 be c2 b9 0b 56 0a db 26 ec 16 15 |Y........V..&...| +000001a0 be 27 cb bb cf 4a 9c a1 fd 5c 7d 5d c6 df a2 ed |.'...J...\}]....| +000001b0 f1 70 74 03 40 7c 8f af ea 3c 6a c7 c6 30 98 4c |.pt.@|...>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 19 83 88 d2 c3 d4 |................| +00000010 a8 98 6c 8f fa 1b 52 a5 83 58 e3 62 89 3e 22 a3 |..l...R..X.b.>".| +00000020 37 b8 ee 13 17 03 03 00 35 b5 5f aa fd ca 85 74 |7.......5._....t| +00000030 ee c6 06 d9 2e d8 4f 7d 87 a2 b7 20 80 a5 3b 97 |......O}... ..;.| +00000040 41 bc 80 20 af b5 c4 66 26 2e 39 fd 81 e0 1a a0 |A.. ...f&.9.....| +00000050 6f c3 08 d0 23 c2 27 49 91 58 77 15 2d 49 |o...#.'I.Xw.-I| +>>> Flow 4 (server to client) +00000000 17 03 03 00 93 10 f4 e9 f1 51 30 25 9e f0 c4 d2 |.........Q0%....| +00000010 b8 f4 4b ad dd 89 ad ab 1a 39 88 44 98 a2 53 4e |..K......9.D..SN| +00000020 1c e9 bb 4a b7 c1 d8 cc bc 76 e6 a8 e6 41 b9 42 |...J.....v...A.B| +00000030 c8 7a 0a f4 35 73 cc 9f 9d 30 ff 4e e3 44 89 a5 |.z..5s...0.N.D..| +00000040 d0 2b 88 36 0a 87 72 b4 bf 48 6a 4e 2e 03 1a 96 |.+.6..r..HjN....| +00000050 1e 01 07 90 61 b0 f1 c5 58 e0 48 30 db d6 e9 5c |....a...X.H0...\| +00000060 88 05 0d 47 fc d1 33 6e 7e c4 fb 81 e3 80 ce 67 |...G..3n~......g| +00000070 93 59 5e 68 39 6c b2 c3 c3 56 09 61 e5 a1 d6 d9 |.Y^h9l...V.a....| +00000080 95 3a 70 6a 5c 4a 51 24 d9 e7 ed 88 7f 6c 32 0a |.:pj\JQ$.....l2.| +00000090 2d 5d 79 40 75 c9 b9 d4 17 03 03 00 1e 24 cc 07 |-]y@u........$..| +000000a0 53 2b 27 c1 36 47 88 b8 3c 91 9e 8b 13 da 9d 3c |S+'.6G..<......<| +000000b0 f9 65 9d 78 ed 92 36 11 41 fe 42 17 03 03 00 13 |.e.x..6.A.B.....| +000000c0 2b 52 80 d0 d5 39 77 77 38 ad e0 ad 78 f8 0a 59 |+R...9ww8...x..Y| +000000d0 96 18 7e |..~| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES new file mode 100644 index 0000000..d2b0250 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ECDHE-ECDSA-AES @@ -0,0 +1,96 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 dc 01 00 00 d8 03 03 90 bc cf 62 d0 |..............b.| +00000010 bc 89 6b 84 ad 18 87 f5 9c 96 0e 02 3f ae a5 4b |..k.........?..K| +00000020 80 70 f8 54 47 b1 78 03 48 4d 06 20 ae 9e 3c 17 |.p.TG.x.HM. ..<.| +00000030 1a c6 fa 52 84 da ea a9 9c 08 e7 10 65 3a 65 4e |...R........e:eN| +00000040 d1 65 61 40 bf 7c ee db d4 f2 73 ff 00 04 13 01 |.ea@.|....s.....| +00000050 00 ff 01 00 00 8b 00 00 00 0e 00 0c 00 00 09 31 |...............1| +00000060 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000070 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000080 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 |................| +00000090 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 |................| +000000a0 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 |...........+....| +000000b0 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 |..-.....3.&.$...| +000000c0 20 ad 11 a7 07 20 9c cb 33 96 f4 0d 78 a1 89 55 | .... ..3...x..U| +000000d0 6c af 70 f4 ac d6 cb d9 0d 1b 13 fa 50 de 68 17 |l.p.........P.h.| +000000e0 1d |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 ae 9e 3c 17 |........... ..<.| +00000030 1a c6 fa 52 84 da ea a9 9c 08 e7 10 65 3a 65 4e |...R........e:eN| +00000040 d1 65 61 40 bf 7c ee db d4 f2 73 ff 13 01 00 00 |.ea@.|....s.....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 f1 16 14 8f 0a b5 |................| +00000090 92 fa 55 d7 fb 6c 33 04 ae c6 ed 3b 90 27 e9 ae |..U..l3....;.'..| +000000a0 e8 17 03 03 02 22 ca b1 97 19 9d da 2e 1d 12 f4 |....."..........| +000000b0 05 af 35 28 1e 85 9d 28 81 f0 5a 83 46 9c df f7 |..5(...(..Z.F...| +000000c0 58 2e 30 fa b9 07 00 cf fe 69 37 5e f2 75 a0 ef |X.0......i7^.u..| +000000d0 f3 ab 60 0b c5 09 72 bd b4 42 2f 45 24 3e 82 d0 |..`...r..B/E$>..| +000000e0 f1 a1 dd 3a de 6a b9 9d 85 2b 83 75 47 c9 d2 c3 |...:.j...+.uG...| +000000f0 25 91 85 c2 a1 97 6a 62 dd aa 19 11 94 e2 6b f9 |%.....jb......k.| +00000100 7d 5a bc 5e d4 64 bc 74 44 85 d1 7a eb 3a ef d5 |}Z.^.d.tD..z.:..| +00000110 96 f4 22 64 61 2b 79 77 ac 8b 61 69 cc eb ad fd |.."da+yw..ai....| +00000120 38 5e 61 74 d9 4f 70 82 06 3b 3e f8 a8 53 7c e8 |8^at.Op..;>..S|.| +00000130 9d 98 43 a1 af 86 ba d9 64 64 f0 e0 b0 8f 39 6b |..C.....dd....9k| +00000140 16 d6 92 09 8d 5b d0 34 f4 14 60 69 a0 28 73 3a |.....[.4..`i.(s:| +00000150 24 7f 81 4e 8b d1 50 49 1a c0 60 92 fd 02 47 6d |$..N..PI..`...Gm| +00000160 d8 97 62 b2 b4 57 8b d7 d1 b6 bf 19 40 cb 13 09 |..b..W......@...| +00000170 ef d6 55 66 39 88 29 e0 14 2d 06 98 d6 b6 bf a6 |..Uf9.)..-......| +00000180 04 10 47 d5 64 fe 38 69 db 33 a4 fc 12 de 83 5b |..G.d.8i.3.....[| +00000190 c9 8e 76 56 bc f7 dd ac 96 c6 a0 ed e5 43 0b 13 |..vV.........C..| +000001a0 1e 78 94 18 fd 57 50 79 08 91 18 aa 84 63 4e 46 |.x...WPy.....cNF| +000001b0 53 db e0 f3 9a 0b d6 13 20 36 aa 56 dd 7a 62 d9 |S....... 6.V.zb.| +000001c0 3f f6 bd 87 74 3c 86 d1 94 a1 04 79 a8 54 e4 8e |?...t<.....y.T..| +000001d0 11 d6 52 42 5c 4b 77 18 b9 d7 db f7 48 9a 69 e1 |..RB\Kw.....H.i.| +000001e0 2d b9 38 38 e4 e8 94 5e b1 7e 2c 81 96 6a a0 ed |-.88...^.~,..j..| +000001f0 bb 35 6a 8c 93 f2 6d 38 70 df 79 54 d9 45 c8 b8 |.5j...m8p.yT.E..| +00000200 b2 9c 0f 9f 70 34 8f ac b3 08 f5 3e b1 d2 5a d7 |....p4.....>..Z.| +00000210 7b ee f3 dc 9a d1 12 c3 77 24 76 9b bf 09 50 a7 |{.......w$v...P.| +00000220 3c ab 7f 1f 99 b5 02 8c ac 5e 85 cc 53 fd ca e0 |<........^..S...| +00000230 c7 e2 41 08 fd cb b0 79 0c 8b 02 4f 80 92 c2 cd |..A....y...O....| +00000240 6c a1 aa 75 d2 4c d1 25 40 7c 14 41 a7 15 20 a3 |l..u.L.%@|.A.. .| +00000250 a6 81 64 7c c0 c7 2d dd 82 84 ad 2a f4 06 f9 61 |..d|..-....*...a| +00000260 23 1c dd c6 ef 72 da 6b eb be 41 f0 b4 5f 9a 02 |#....r.k..A.._..| +00000270 ee a8 f3 bb 05 48 ec 50 a3 ff f3 94 bb d8 a9 6d |.....H.P.......m| +00000280 92 49 7c bf a1 eb 55 26 08 26 d3 80 d6 cb 05 ea |.I|...U&.&......| +00000290 d1 db bf 97 3d 10 ff 4e f6 05 33 23 68 95 31 42 |....=..N..3#h.1B| +000002a0 5a d5 30 61 79 c4 88 7f e1 be 28 ad 72 bb 78 36 |Z.0ay.....(.r.x6| +000002b0 ba bb 38 75 fb 97 33 b6 28 8c a2 f4 46 fe 37 d8 |..8u..3.(...F.7.| +000002c0 b0 67 63 97 c1 51 0c 61 17 03 03 00 a4 20 15 70 |.gc..Q.a..... .p| +000002d0 7a 69 b1 33 c2 e1 f5 9c 2b b2 06 1e 01 a6 7f 03 |zi.3....+.......| +000002e0 cd 00 13 02 3b 0c 2b 3f 85 d8 ed 6d 81 7e e9 b2 |....;.+?...m.~..| +000002f0 b6 be 7b 77 51 30 dd b5 fc 93 08 91 9e 46 e2 85 |..{wQ0.......F..| +00000300 74 3c 9a 04 26 86 b8 6c 98 99 57 7e 36 54 0d 90 |t<..&..l..W~6T..| +00000310 4c 55 65 77 69 59 b2 e5 5b a3 19 4a b0 72 3d 91 |LUewiY..[..J.r=.| +00000320 2e 5d 9b 8c 52 a1 e6 f5 22 c6 3c 0d 9b d8 9c b9 |.]..R...".<.....| +00000330 cb 90 51 bc 16 69 06 30 22 16 62 08 3b 3f 05 99 |..Q..i.0".b.;?..| +00000340 60 2a cc cf 29 f5 e1 b0 84 81 c8 63 00 d4 d4 13 |`*..)......c....| +00000350 b5 5d 4c 63 8a 60 3e 44 24 03 30 85 91 4c 3d f2 |.]Lc.`>D$.0..L=.| +00000360 2c c2 78 f2 c3 4c bb 90 60 0b 66 18 02 e7 5c 85 |,.x..L..`.f...\.| +00000370 19 17 03 03 00 35 49 76 5f ff 32 3a 09 7a 4b f2 |.....5Iv_.2:.zK.| +00000380 fe f3 38 b6 76 f4 12 f2 aa a3 ed b6 02 ab 0b b9 |..8.v...........| +00000390 3b 9d 00 51 f1 5c 96 23 6b 49 f8 32 9f 74 30 32 |;..Q.\.#kI.2.t02| +000003a0 4d af af ef d5 55 2c ff 2b a0 45 17 03 03 00 93 |M....U,.+.E.....| +000003b0 6e e0 6a f9 44 af c0 af 95 ab 1e ff fd 97 38 f5 |n.j.D.........8.| +000003c0 7b 24 70 da e2 4e 8b dc 9b 49 84 fe 73 0a b0 7e |{$p..N...I..s..~| +000003d0 cf 14 f7 8a 67 e7 74 bd ee 82 93 c6 27 a2 bd 1e |....g.t.....'...| +000003e0 cb 71 06 af 65 dd f0 d9 91 81 b0 f8 21 34 48 d1 |.q..e.......!4H.| +000003f0 c4 e0 e3 19 a8 b4 48 b7 3a be 52 e5 7c a8 a3 c2 |......H.:.R.|...| +00000400 08 6c ac 66 4d 36 cf a1 9d 1f 72 c5 09 20 db 05 |.l.fM6....r.. ..| +00000410 e5 0a 44 af 4a d8 32 38 19 7d 28 e3 05 23 99 66 |..D.J.28.}(..#.f| +00000420 f6 ad 77 02 7e 00 67 c1 71 58 b9 89 3c 93 15 95 |..w.~.g.qX..<...| +00000430 ee 38 e2 ea c0 73 fe da e4 75 6d 38 ca 54 0b bf |.8...s...um8.T..| +00000440 f0 af 86 |...| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 23 02 12 13 f1 |..........5#....| +00000010 db fa 70 c0 92 85 8a d3 fa 80 1b 5c a6 22 ff 20 |..p........\.". | +00000020 5d bf 1d 61 58 34 c0 48 6f e1 26 a6 bf bc 76 c7 |]..aX4.Ho.&...v.| +00000030 8b da ee 54 64 30 c4 5c b1 61 67 82 29 bb 3f 4b |...Td0.\.ag.).?K| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 95 c0 53 e2 37 94 09 83 1e 7e 23 |.......S.7....~#| +00000010 dc 9f 02 5e 91 19 b6 f9 72 0d 38 3f 25 ae b2 5f |...^....r.8?%.._| +00000020 4b f2 78 17 03 03 00 13 d2 ad 73 d6 f3 21 ab 7c |K.x.......s..!.|| +00000030 02 dd 63 ff cf d7 34 ca 71 3d 70 |..c...4.q=p| diff --git a/src/crypto/tls/testdata/Server-TLSv13-Ed25519 b/src/crypto/tls/testdata/Server-TLSv13-Ed25519 new file mode 100644 index 0000000..a94597a --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-Ed25519 @@ -0,0 +1,76 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ca 01 00 00 c6 03 03 a1 5b 14 56 ac |............[.V.| +00000010 3f 2b b0 8e e9 0b ae 7e f7 3b 3b 20 90 b6 e4 06 |?+.....~.;; ....| +00000020 c2 b9 71 88 e4 4c 01 28 41 b3 e8 20 49 01 f7 fc |..q..L.(A.. I...| +00000030 ce 52 3e f4 58 60 56 7d 36 21 ba 23 87 21 f7 36 |.R>.X`V}6!.#.!.6| +00000040 48 88 22 78 26 37 27 a4 fc 7a 8b ea 00 04 13 03 |H."x&7'..z......| +00000050 00 ff 01 00 00 79 00 0b 00 04 03 00 01 02 00 0a |.....y..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| +00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| +000000a0 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 f4 |-.....3.&.$... .| +000000b0 2c db e8 c0 9e 7d 52 f6 fa 33 fe f7 9a 66 ca 5f |,....}R..3...f._| +000000c0 a3 28 e9 80 21 28 b8 ef e9 9f 1e 26 9c cf 0f |.(..!(.....&...| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 49 01 f7 fc |........... I...| +00000030 ce 52 3e f4 58 60 56 7d 36 21 ba 23 87 21 f7 36 |.R>.X`V}6!.#.!.6| +00000040 48 88 22 78 26 37 27 a4 fc 7a 8b ea 13 03 00 00 |H."x&7'..z......| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 f9 df 7b 4f f9 a1 |............{O..| +00000090 f7 78 eb 10 59 5c 4f ed 42 09 08 10 0f c7 a4 81 |.x..Y\O.B.......| +000000a0 8b 17 03 03 01 50 38 d7 96 35 05 7d 3d 3a 60 02 |.....P8..5.}=:`.| +000000b0 bf 93 37 f2 60 3e 64 cb 1a 6f 9c 69 af 06 ca 70 |..7.`>d..o.i...p| +000000c0 94 e2 d1 7f 4a 5d c7 57 0e 11 c7 4e 24 c6 ba 57 |....J].W...N$..W| +000000d0 9f d7 67 3a 0a 8b 93 08 d4 de c5 be 62 79 61 2a |..g:........bya*| +000000e0 3d 4e 57 f9 98 e5 4f 5e 5a 74 52 5b a4 d0 07 ae |=NW...O^ZtR[....| +000000f0 8c 2a cb 50 dd b3 76 ab 3a 61 5b 55 83 8e 37 8d |.*.P..v.:a[U..7.| +00000100 39 e5 4f 58 7e 7a bc 80 26 f6 0f 47 8f 11 55 77 |9.OX~z..&..G..Uw| +00000110 24 b1 a7 06 d8 d2 30 82 0d 99 39 04 5f 97 d8 1d |$.....0...9._...| +00000120 99 67 99 89 f0 ee 4f 18 8b 49 24 d3 6a d0 65 c9 |.g....O..I$.j.e.| +00000130 01 a2 48 54 8b d2 bb 56 d4 0a 73 62 88 fa 70 4e |..HT...V..sb..pN| +00000140 7f dd 59 5b 14 7b 28 02 07 75 01 4d 41 ab 1d 7e |..Y[.{(..u.MA..~| +00000150 ef 24 42 ee 85 7f fa 5f 9e f0 9f f2 7f 92 00 52 |.$B...._.......R| +00000160 ca 73 8a 73 c6 d7 13 f5 9d 31 6f 76 75 db e7 53 |.s.s.....1ovu..S| +00000170 4d 44 40 8f 47 be bd 0e 71 13 d0 f7 f2 72 67 3a |MD@.G...q....rg:| +00000180 de b8 da b0 1d 84 85 d0 c2 c4 8d 16 87 68 c7 98 |.............h..| +00000190 40 0a 92 c8 fb 8a 3a e4 7b 34 43 47 b7 4f 28 8e |@.....:.{4CG.O(.| +000001a0 11 01 98 88 b6 cd ca aa d4 dc 52 5d f9 cf 55 bb |..........R]..U.| +000001b0 f3 13 f2 ce dc 67 74 a7 4d 5e 65 6f 18 cd 82 4e |.....gt.M^eo...N| +000001c0 fc 80 2c 14 17 99 08 6d 59 b3 3f 38 00 52 a2 a3 |..,....mY.?8.R..| +000001d0 c1 98 84 15 91 82 3f e9 47 82 12 a0 94 dc 19 9e |......?.G.......| +000001e0 2e b7 25 79 30 b9 81 d6 9f 33 8e 49 80 7a 4c a2 |..%y0....3.I.zL.| +000001f0 b7 9a e6 17 2c 06 17 03 03 00 59 97 c7 4b ac c3 |....,.....Y..K..| +00000200 ed b3 bd 82 7a c2 45 a0 18 70 7b 88 fe 8b fd 6b |....z.E..p{....k| +00000210 83 f2 dd 77 15 74 9c f0 a6 27 22 bf ee 25 53 07 |...w.t...'"..%S.| +00000220 81 95 3c 91 b3 89 3c ca f9 5b c7 cf bb 32 55 f8 |..<...<..[...2U.| +00000230 3c 76 70 f6 11 ca 5d 92 aa 78 9e 8a 2f ab e0 6f |>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 19 fa 19 c0 ce |..........5.....| +00000010 09 87 c2 06 69 56 2a 0a a7 9c 79 76 03 1b 70 5e |....iV*...yv..p^| +00000020 56 2d d4 a1 09 e3 99 f7 a9 7a e5 ba 3e 17 8b b2 |V-.......z..>...| +00000030 fe da 70 81 d9 30 83 27 b1 da 2e df da 94 75 72 |..p..0.'......ur| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 83 53 ed 09 07 d3 87 ab 37 a2 08 |......S......7..| +00000010 a8 50 66 87 97 54 04 38 4b a6 25 f8 ab 75 ac 39 |.Pf..T.8K.%..u.9| +00000020 52 e2 8d 17 03 03 00 13 86 58 ef 44 c1 59 5e 2e |R........X.D.Y^.| +00000030 e4 2e df 93 6e 52 76 58 c1 9d 2a |....nRvX..*| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ExportKeyingMaterial b/src/crypto/tls/testdata/Server-TLSv13-ExportKeyingMaterial new file mode 100644 index 0000000..8267ca0 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ExportKeyingMaterial @@ -0,0 +1,99 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ce 01 00 00 ca 03 03 26 86 8d 61 97 |...........&..a.| +00000010 6c da 93 d7 43 5c b3 0c 06 5c c2 cb e0 89 46 9f |l...C\...\....F.| +00000020 cc b0 a3 cf 41 3d cf 7a 9e 02 bc 20 a6 33 fe 0b |....A=.z... .3..| +00000030 90 24 8b ed 69 48 86 9b d2 1a 5c 04 66 52 4f 5d |.$..iH....\.fRO]| +00000040 a4 24 6b d2 84 08 c0 48 a9 55 ef 0c 00 04 13 03 |.$k....H.U......| +00000050 00 ff 01 00 00 7d 00 0b 00 04 03 00 01 02 00 0a |.....}..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c |................| +00000080 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000090 08 04 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 |.............+..| +000000a0 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 |....-.....3.&.$.| +000000b0 1d 00 20 b9 ab 39 93 6b 9f aa 46 0a 61 c6 f8 58 |.. ..9.k..F.a..X| +000000c0 45 26 16 6f b6 cb 42 52 e8 24 ab cc a4 2d b6 7a |E&.o..BR.$...-.z| +000000d0 a5 90 67 |..g| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 a6 33 fe 0b |........... .3..| +00000030 90 24 8b ed 69 48 86 9b d2 1a 5c 04 66 52 4f 5d |.$..iH....\.fRO]| +00000040 a4 24 6b d2 84 08 c0 48 a9 55 ef 0c 13 03 00 00 |.$k....H.U......| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 e9 4c 8a ed 0c af |...........L....| +00000090 04 d2 18 14 38 48 c1 71 da 59 db 46 f4 00 0d 19 |....8H.q.Y.F....| +000000a0 1e 17 03 03 02 6d e0 d2 7b bf 0a 51 48 a9 67 46 |.....m..{..QH.gF| +000000b0 25 3b 07 e9 68 da 4d cf 47 31 0f 7d ad 4e 0d 6d |%;..h.M.G1.}.N.m| +000000c0 c3 ad 03 61 4a c0 ae 06 4d b7 84 29 1b 44 49 26 |...aJ...M..).DI&| +000000d0 f4 99 fc 58 1e 5b f0 15 ee be 19 c3 b3 23 20 f0 |...X.[.......# .| +000000e0 7a 10 e4 ab c8 00 f6 e4 93 d6 b3 2a fd 14 10 c9 |z..........*....| +000000f0 72 b2 21 ba 93 50 08 4e d2 1f 3f 64 68 73 3c c7 |r.!..P.N..?dhs<.| +00000100 11 3c f5 84 61 b0 2c 84 42 0c ef a9 03 a2 74 aa |.<..a.,.B.....t.| +00000110 3b 07 e0 d5 f5 c4 d1 a8 8e f5 64 0e 52 41 b1 4d |;.........d.RA.M| +00000120 aa 43 0d f3 6b 0c 19 36 66 fe 4c 73 cd 52 03 2f |.C..k..6f.Ls.R./| +00000130 61 f1 9d 23 12 e2 b9 69 d9 48 92 07 1b 5d 6f 28 |a..#...i.H...]o(| +00000140 e1 96 39 d8 59 19 9d 9c bf 99 3a af 03 68 bd 34 |..9.Y.....:..h.4| +00000150 38 04 9d 8c 9a bf 75 67 74 dd 9c eb 89 13 6d 55 |8.....ugt.....mU| +00000160 b4 c4 17 11 05 54 d7 f9 d7 5a ed ec d5 15 31 5e |.....T...Z....1^| +00000170 2f ed 69 fa 99 23 57 e3 62 98 35 27 17 34 e1 c4 |/.i..#W.b.5'.4..| +00000180 3c 95 3f 69 de 01 aa a9 66 55 4a 40 3a f1 4f 19 |<.?i....fUJ@:.O.| +00000190 02 2f df 51 0c 69 ec 48 7a 60 f7 72 5e f6 f0 4d |./.Q.i.Hz`.r^..M| +000001a0 a1 b2 7a 06 df 69 a1 19 42 29 56 5c 67 99 3d 0e |..z..i..B)V\g.=.| +000001b0 5d da df 7b 93 8e 9a 26 6e 2e 09 c4 30 40 ad a9 |]..{...&n...0@..| +000001c0 ee 4b bd 21 41 b6 cb fc 97 0f fc a2 cf 26 31 d6 |.K.!A........&1.| +000001d0 d6 77 96 4e c6 a2 fd 5a 0e cb d5 31 a6 21 e8 76 |.w.N...Z...1.!.v| +000001e0 a2 48 4d 43 d4 c9 18 b2 21 cc 13 13 84 f2 c2 cf |.HMC....!.......| +000001f0 60 8f 2e 36 39 8a a8 26 03 1d 51 24 b4 08 c5 5d |`..69..&..Q$...]| +00000200 96 b9 4a 46 02 41 1f 59 ea 47 a9 37 bc a0 c4 70 |..JF.A.Y.G.7...p| +00000210 26 d6 8c 11 62 45 1d 92 5d ea 39 cd af af 13 38 |&...bE..].9....8| +00000220 85 ca a8 74 1a 09 07 f2 7c d6 49 0d 2d ad 1c 9f |...t....|.I.-...| +00000230 db 8b 56 91 45 51 32 db ca 9c f4 d2 72 09 8a fe |..V.EQ2.....r...| +00000240 98 9e a8 b5 b2 49 9c 0b e9 3a 42 d0 53 e0 20 6c |.....I...:B.S. l| +00000250 e3 07 36 ef cc 85 56 fd b4 6e ff d2 7c 96 52 27 |..6...V..n..|.R'| +00000260 46 c9 3c b3 bf fb 16 0b 61 54 09 9c ac 3b 18 5f |F.<.....aT...;._| +00000270 5a 01 4b 25 67 22 ef 19 86 a3 3a 80 f0 12 f5 60 |Z.K%g"....:....`| +00000280 4c 77 cf bd a9 e8 a1 19 d4 8c e1 a8 b2 b8 19 b8 |Lw..............| +00000290 98 85 c3 da 1a b8 4d 6e 1f 35 73 28 32 3c a0 44 |......Mn.5s(2<.D| +000002a0 c9 77 46 b8 c6 54 4d 80 67 72 58 c4 e3 0b f3 6c |.wF..TM.grX....l| +000002b0 43 eb e2 89 f1 30 cc 90 b4 e9 b8 ec e2 5f c1 31 |C....0......._.1| +000002c0 a2 de 9d e9 fe 9c fe b0 83 b7 aa e9 2e 62 35 89 |.............b5.| +000002d0 90 0d 36 79 8f 23 bb 7a ae dc db db 1c c3 96 5d |..6y.#.z.......]| +000002e0 7c 06 e9 1c ee 82 58 46 7c 1b 90 9d cf 2d 31 54 ||.....XF|....-1T| +000002f0 96 94 58 dc 95 26 85 c7 f4 c9 9c 2b 8a 2f ae b3 |..X..&.....+./..| +00000300 70 10 bf f1 0e 66 ef f1 1c 66 da 6c 52 d8 6e aa |p....f...f.lR.n.| +00000310 3a 14 d8 17 03 03 00 99 69 45 ee c3 c9 b3 4d 9a |:.......iE....M.| +00000320 01 00 70 27 54 8c 12 bb 74 67 e8 88 07 ac 4e ab |..p'T...tg....N.| +00000330 b1 41 f4 65 ee 3b 06 87 79 5d 9b 1d 70 df 2f f7 |.A.e.;..y]..p./.| +00000340 e0 88 45 2b a1 b9 ca 67 88 65 65 33 51 41 c0 b2 |..E+...g.ee3QA..| +00000350 da 6a 7a 7c bf 42 58 8d ae 7b 24 d0 8a f7 47 c0 |.jz|.BX..{$...G.| +00000360 a9 45 da 24 82 03 a1 65 03 7c 3c 2a bf 48 e2 0d |.E.$...e.|<*.H..| +00000370 fa cc 3f 00 53 63 5d f9 b4 a1 00 d2 a7 3c 81 64 |..?.Sc]......<.d| +00000380 8a d5 90 4f b9 58 2b 1e 1d a7 7e ad 3e 8f d4 4a |...O.X+...~.>..J| +00000390 7b 66 b7 4e 68 04 ac 66 24 6e 76 ed f4 5c aa 52 |{f.Nh..f$nv..\.R| +000003a0 3d f8 f5 ea d0 0a 74 ba 39 da 21 e0 f1 03 80 cd |=.....t.9.!.....| +000003b0 5b 17 03 03 00 35 7b 1f 6e 37 6c 15 5b 1b f7 ea |[....5{.n7l.[...| +000003c0 bf 03 68 5f 15 1f e7 99 a8 64 f1 60 3d e0 b6 5e |..h_.....d.`=..^| +000003d0 c1 60 18 61 e5 ea dc ab b5 d3 5f 10 1b 5c 3a 1b |.`.a......_..\:.| +000003e0 c5 fe a6 d3 fc 45 6b db b1 27 60 17 03 03 00 93 |.....Ek..'`.....| +000003f0 e3 f1 5f f1 18 a6 ab 67 88 e4 5a f9 fd 71 77 4b |.._....g..Z..qwK| +00000400 6c 0d 98 ef 71 72 2a aa d2 0a 2d 72 ac 40 57 2d |l...qr*...-r.@W-| +00000410 73 ad 77 cd 01 19 19 be e7 49 d4 6a aa 97 f9 40 |s.w......I.j...@| +00000420 b1 85 cc bb 5c 57 1a 17 a8 48 65 d3 4d e9 a9 29 |....\W...He.M..)| +00000430 4b 08 6b b3 33 2c 97 d0 89 0a 50 e2 66 06 c6 63 |K.k.3,....P.f..c| +00000440 c3 6f 8d 5e ab a4 af 7a 6a 5e 25 8d 4a 17 ea aa |.o.^...zj^%.J...| +00000450 67 8a ad af c3 1e d6 47 db a5 b5 db 32 1b 83 f8 |g......G....2...| +00000460 2d f9 bc 99 28 07 0d d0 fe 34 bf 52 ae 59 27 40 |-...(....4.R.Y'@| +00000470 cd 0e 4d 4d 12 28 21 01 30 38 b1 c3 df 63 e9 9e |..MM.(!.08...c..| +00000480 34 91 84 |4..| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 1d d8 d0 a8 ec |..........5.....| +00000010 04 45 13 43 a1 72 38 4e 54 85 7a a2 17 dc eb 39 |.E.C.r8NT.z....9| +00000020 36 7d 50 25 5f d3 0d 7f c3 a7 75 93 e9 1e 17 0a |6}P%_.....u.....| +00000030 a3 d7 a8 74 23 98 5e 3a 3a 4c 2c d3 78 b4 04 48 |...t#.^::L,.x..H| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 53 e2 0d f2 62 e8 be 84 e0 33 1a |.....S...b....3.| +00000010 56 bc 45 f9 0b 69 63 72 03 f3 34 c6 72 d8 f9 c4 |V.E..icr..4.r...| +00000020 ba 53 3d 17 03 03 00 13 11 b5 0d 7f d4 e7 51 90 |.S=...........Q.| +00000030 39 be 2b d8 d6 7c e8 12 ea 61 83 |9.+..|...a.| diff --git a/src/crypto/tls/testdata/Server-TLSv13-HelloRetryRequest b/src/crypto/tls/testdata/Server-TLSv13-HelloRetryRequest new file mode 100644 index 0000000..95eefd2 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-HelloRetryRequest @@ -0,0 +1,123 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 c4 01 00 00 c0 03 03 16 5e f5 e2 4e |............^..N| +00000010 27 ce 8e 88 0b e9 13 6d 12 a6 6d 27 c9 ab 95 47 |'......m..m'...G| +00000020 6f 9d 5d a0 92 64 35 c1 b6 70 90 20 ff 47 6f 67 |o.]..d5..p. .Gog| +00000030 69 49 88 2a 84 69 79 48 fe cc 92 db 6e 9e ab 47 |iI.*.iyH....n..G| +00000040 8e 47 10 58 db ad 22 8e da bb 86 e6 00 04 13 03 |.G.X..".........| +00000050 00 ff 01 00 00 73 00 0b 00 04 03 00 01 02 00 0a |.....s..........| +00000060 00 06 00 04 00 1d 00 17 00 16 00 00 00 17 00 00 |................| +00000070 00 0d 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 |................| +00000080 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 |................| +00000090 06 01 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 |...+......-.....| +000000a0 33 00 26 00 24 00 1d 00 20 7e a4 de 34 df 01 99 |3.&.$... ~..4...| +000000b0 37 77 f7 de 6a e2 79 e7 63 eb 86 6c 62 61 fd b0 |7w..j.y.c..lba..| +000000c0 c6 95 04 c8 63 29 cd 32 00 |....c).2.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 58 02 00 00 54 03 03 cf 21 ad 74 e5 |....X...T...!.t.| +00000010 9a 61 11 be 1d 8c 02 1e 65 b8 91 c2 a2 11 16 7a |.a......e......z| +00000020 bb 8c 5e 07 9e 09 e2 c8 a8 33 9c 20 ff 47 6f 67 |..^......3. .Gog| +00000030 69 49 88 2a 84 69 79 48 fe cc 92 db 6e 9e ab 47 |iI.*.iyH....n..G| +00000040 8e 47 10 58 db ad 22 8e da bb 86 e6 13 03 00 00 |.G.X..".........| +00000050 0c 00 2b 00 02 03 04 00 33 00 02 00 17 14 03 03 |..+.....3.......| +00000060 00 01 01 |...| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 16 03 03 00 e5 01 00 00 e1 03 |................| +00000010 03 16 5e f5 e2 4e 27 ce 8e 88 0b e9 13 6d 12 a6 |..^..N'......m..| +00000020 6d 27 c9 ab 95 47 6f 9d 5d a0 92 64 35 c1 b6 70 |m'...Go.]..d5..p| +00000030 90 20 ff 47 6f 67 69 49 88 2a 84 69 79 48 fe cc |. .GogiI.*.iyH..| +00000040 92 db 6e 9e ab 47 8e 47 10 58 db ad 22 8e da bb |..n..G.G.X.."...| +00000050 86 e6 00 04 13 03 00 ff 01 00 00 94 00 0b 00 04 |................| +00000060 03 00 01 02 00 0a 00 06 00 04 00 1d 00 17 00 16 |................| +00000070 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 |................| +00000080 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| +00000090 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 |.........+......| +000000a0 2d 00 02 01 01 00 33 00 47 00 45 00 17 00 41 04 |-.....3.G.E...A.| +000000b0 ca c3 69 88 b3 ed f4 ad 7f 9c 03 6c 7a 44 55 d6 |..i........lzDU.| +000000c0 68 1d a4 27 67 57 d7 27 08 27 e8 b9 c9 32 49 a2 |h..'gW.'.'...2I.| +000000d0 e4 f6 c2 f2 62 bd 74 67 77 f9 26 27 ee d7 a7 f0 |....b.tgw.&'....| +000000e0 9c 9a 41 cd 8b bf 76 25 df ff 5a 9f 4e f5 41 95 |..A...v%..Z.N.A.| +>>> Flow 4 (server to client) +00000000 16 03 03 00 9b 02 00 00 97 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 ff 47 6f 67 |........... .Gog| +00000030 69 49 88 2a 84 69 79 48 fe cc 92 db 6e 9e ab 47 |iI.*.iyH....n..G| +00000040 8e 47 10 58 db ad 22 8e da bb 86 e6 13 03 00 00 |.G.X..".........| +00000050 4f 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |O.+.....3.E...A.| +00000060 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 |..7...Q.5uq..T[.| +00000070 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e |...g..$ >.V...(^| +00000080 f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 |.+-O....lK[.V.2B| +00000090 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |.X..I..h.A.Vk.Z.| +000000a0 17 03 03 00 17 c0 07 64 56 b1 bb f8 bf 36 6b df |.......dV....6k.| +000000b0 e9 ee 72 cc 79 45 f5 8c b8 0c b3 5d 17 03 03 02 |..r.yE.....]....| +000000c0 6d 2e ab b5 84 4f d7 9e 4e 0d 6e a0 42 c1 f0 a6 |m....O..N.n.B...| +000000d0 62 a3 26 eb 9d 9a 42 a5 5d 1f 59 ad 37 a9 8a af |b.&...B.].Y.7...| +000000e0 0d 7b 8f 5a d1 d5 d8 bc 15 5b 0d 0e d2 a9 bb 14 |.{.Z.....[......| +000000f0 56 ed 30 4e 9b aa f9 5a 66 7d 4c 41 8e 6d 58 90 |V.0N...Zf}LA.mX.| +00000100 52 4a f2 78 72 59 34 aa 58 7e 0c 44 1e bc 84 d8 |RJ.xrY4.X~.D....| +00000110 50 17 bd aa 8c 4c d0 c5 e7 69 32 b8 c3 d6 e6 f9 |P....L...i2.....| +00000120 70 93 99 1c 75 1b 13 f2 85 e0 b5 07 1b d8 5a 31 |p...u.........Z1| +00000130 0a 1a 2e 97 86 ff 75 a1 db 45 b2 47 68 ed 88 d9 |......u..E.Gh...| +00000140 fe 31 c9 c0 5e 37 f2 62 37 f7 01 81 11 07 a7 0f |.1..^7.b7.......| +00000150 44 ec 17 3a 4a 38 b3 91 9f 77 6f f9 58 9e 9c 12 |D..:J8...wo.X...| +00000160 6e 54 4c de 43 58 46 a5 f6 c7 58 7e df 33 d7 91 |nTL.CXF...X~.3..| +00000170 e5 cb 9e 28 9d 7f a7 8a bd be 01 48 b7 b1 1e e2 |...(.......H....| +00000180 7a 80 aa f9 cd 3f 62 0d a0 a0 63 0c ca 4b 5f a8 |z....?b...c..K_.| +00000190 a9 5f 42 ac 44 57 67 b2 0f 5a b5 bb 59 a9 56 bd |._B.DWg..Z..Y.V.| +000001a0 28 3c fb 5e 43 33 61 43 7b 60 48 7d 27 67 6a 06 |(<.^C3aC{`H}'gj.| +000001b0 ac 0d db e4 d2 d4 b8 fa fb e8 32 f3 22 83 3a 63 |..........2.".:c| +000001c0 f6 73 02 62 e0 d5 8a d2 61 a5 bf e1 2d 10 59 93 |.s.b....a...-.Y.| +000001d0 55 60 be 32 ce 5c d5 5a f0 54 21 7d 8a 02 23 cf |U`.2.\.Z.T!}..#.| +000001e0 38 2b 2b 67 50 22 72 f7 f7 bf 20 c2 34 df ae 3a |8++gP"r... .4..:| +000001f0 44 b0 a6 2a 51 79 6f b1 7b ff d7 77 45 83 a9 fa |D..*Qyo.{..wE...| +00000200 bf 3c de 34 e8 6a 33 74 6c 24 0b 85 39 ea 7c 13 |.<.4.j3tl$..9.|.| +00000210 43 26 13 1b 61 56 85 0a 08 83 04 45 5f 5a 36 df |C&..aV.....E_Z6.| +00000220 17 c0 59 e9 92 d8 6b 78 66 1f 43 a0 99 f8 4b b1 |..Y...kxf.C...K.| +00000230 f0 8d 25 6f 0f 2e c7 f9 4d bb 79 74 b8 95 e6 b7 |..%o....M.yt....| +00000240 41 0c de 2a d3 7e fc 0f 18 87 2d 21 dd 8d 5f 20 |A..*.~....-!.._ | +00000250 4c 88 cb 63 f4 9c 07 64 14 02 0c 19 46 32 e5 1e |L..c...d....F2..| +00000260 85 84 4a 71 b8 a5 50 92 ca 72 fe f4 9c 69 05 d4 |..Jq..P..r...i..| +00000270 93 22 38 c1 09 e2 da 49 17 e8 e1 b3 f9 42 ee bf |."8....I.....B..| +00000280 ea 40 b2 00 af b9 a8 f9 97 8e ef de 41 de 01 87 |.@..........A...| +00000290 cc 13 23 64 8c a1 10 9a 91 38 9b cb fb 0b 04 66 |..#d.....8.....f| +000002a0 fb 4b e3 77 e7 da 7a 75 5c 66 20 7e dc 22 a9 e6 |.K.w..zu\f ~."..| +000002b0 6a 27 06 ed 3c fc 4c 30 ed f0 31 92 b2 eb a1 f3 |j'..<.L0..1.....| +000002c0 a4 fd 83 20 37 62 71 95 ff 7c 65 e8 88 aa e7 c7 |... 7bq..|e.....| +000002d0 3f 17 9c 94 6f 1a d9 c8 ac 00 8d ec 30 22 98 85 |?...o.......0"..| +000002e0 da cc 69 41 f4 3a 66 1b e6 4c 38 62 8d 37 dc a1 |..iA.:f..L8b.7..| +000002f0 08 cf 88 d4 26 7f 47 33 54 d8 aa d6 c5 02 fc 72 |....&.G3T......r| +00000300 ff 50 19 9f 4a 0e 8b c8 32 6d 8e 15 e4 f1 ed 2e |.P..J...2m......| +00000310 43 cb 9f 8c 7a 0e e1 a2 79 e2 f9 52 12 e4 2f a9 |C...z...y..R../.| +00000320 c1 c5 0b 1f c2 21 c5 2e 21 de 3e 76 29 db 17 03 |.....!..!.>v)...| +00000330 03 00 99 8a ee 54 88 93 d0 4b a0 31 18 ed 83 ff |.....T...K.1....| +00000340 2c 44 78 ab 88 ea 72 d2 2a 27 71 a9 a1 ba 26 a5 |,Dx...r.*'q...&.| +00000350 9a 9b 64 92 e8 c9 f8 02 47 b9 9f 53 95 a8 ad 5b |..d.....G..S...[| +00000360 bd 81 17 87 69 0c 77 c1 0e d7 cb 5b 9f 2d 36 86 |....i.w....[.-6.| +00000370 f5 fc 6d ba d8 f5 63 dd e4 f5 0a 61 8d b2 a9 bb |..m...c....a....| +00000380 a5 a5 d6 41 d4 aa db 46 79 56 02 51 f4 ac d3 57 |...A...FyV.Q...W| +00000390 57 b4 53 71 9f fe ea a6 76 f3 0f ca 39 93 f3 34 |W.Sq....v...9..4| +000003a0 c6 96 96 09 8e 12 04 cc 1e 82 9f 78 6b 1c a2 fc |...........xk...| +000003b0 0c 9d c6 00 3c 33 3a 92 c5 ce 96 15 50 1a 75 6d |....<3:.....P.um| +000003c0 85 ec b6 64 12 2b eb 3a 52 8f 6d 35 17 03 03 00 |...d.+.:R.m5....| +000003d0 35 7f 2b 30 fa e0 92 25 a2 1b 11 f8 cd 04 0d 57 |5.+0...%.......W| +000003e0 01 42 cf e9 0c 92 7f d1 fd fa 26 61 0d 85 d7 d5 |.B........&a....| +000003f0 3c fd cf 73 98 dc 88 a2 76 63 59 82 45 2d e3 bc |<..s....vcY.E-..| +00000400 a2 c0 0b 83 41 75 17 03 03 00 93 f3 17 09 b2 e8 |....Au..........| +00000410 53 11 9b 3e 3a 10 a0 e6 58 04 81 82 cb eb a5 19 |S..>:...X.......| +00000420 0f a3 25 e2 eb ab 7c 07 2b e6 22 19 30 aa fc a6 |..%...|.+.".0...| +00000430 bd c4 7d 69 33 38 2b 58 55 5b a7 27 29 86 af d5 |..}i38+XU[.')...| +00000440 f9 5a b4 85 ad a0 73 ab f7 61 3f 2e 66 53 f5 8f |.Z....s..a?.fS..| +00000450 c7 09 4b 01 99 d0 68 93 32 d1 2e 8f 89 e5 e1 ea |..K...h.2.......| +00000460 ba f2 fb 07 ee 58 7c 28 ff 59 1d d7 f7 b3 e2 56 |.....X|(.Y.....V| +00000470 98 56 cd 9d d1 4f 26 7e 77 0d a0 c1 92 c5 a0 83 |.V...O&~w.......| +00000480 c9 7c d8 7d a8 91 d3 ae 71 41 1d 06 33 68 b8 52 |.|.}....qA..3h.R| +00000490 ad 84 a7 21 80 8f e5 c6 37 11 da 6c 5a 3a |...!....7..lZ:| +>>> Flow 5 (client to server) +00000000 17 03 03 00 35 28 34 b9 16 07 9a c1 82 ad 9f b7 |....5(4.........| +00000010 78 fa 1a d0 1f 57 98 95 37 86 cf 1d 67 19 47 48 |x....W..7...g.GH| +00000020 e9 ab fe 0c ff 26 c6 78 88 1a ad 75 48 63 4b 6e |.....&.x...uHcKn| +00000030 72 4a 44 4f 27 b6 9d 56 b6 43 |rJDO'..V.C| +>>> Flow 6 (server to client) +00000000 17 03 03 00 1e d9 1f 35 86 22 7e 10 f1 8d e5 82 |.......5."~.....| +00000010 f2 f6 88 81 a3 66 da 6a 1e 2f 94 94 16 02 2a 52 |.....f.j./....*R| +00000020 69 8b bb 17 03 03 00 13 3c 87 88 8c c0 78 64 18 |i.......<....xd.| +00000030 9a 9e 07 fd ac d7 2d 5d ab bf a8 |......-]...| diff --git a/src/crypto/tls/testdata/Server-TLSv13-IssueTicket b/src/crypto/tls/testdata/Server-TLSv13-IssueTicket new file mode 100644 index 0000000..fa1f801 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-IssueTicket @@ -0,0 +1,99 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ce 01 00 00 ca 03 03 bb e2 a4 a5 7e |...............~| +00000010 63 65 5c a5 7f 3f 13 a1 9d 5f 53 3c d2 b1 84 bd |ce\..?..._S<....| +00000020 51 0c 9a 14 e8 8a 5a 53 b8 27 88 20 e7 04 4d dc |Q.....ZS.'. ..M.| +00000030 76 f3 7f bd 00 ce 46 d2 a6 58 26 99 02 91 88 bf |v.....F..X&.....| +00000040 b5 6b 56 2b b6 bc 51 b2 e4 cd 82 8d 00 04 13 01 |.kV+..Q.........| +00000050 00 ff 01 00 00 7d 00 0b 00 04 03 00 01 02 00 0a |.....}..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c |................| +00000080 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000090 08 04 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 |.............+..| +000000a0 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 |....-.....3.&.$.| +000000b0 1d 00 20 b2 99 9c bb d1 4c c7 61 5f aa bf 2f 06 |.. .....L.a_../.| +000000c0 a3 50 e7 49 7d 11 ae 68 9b b0 be be 82 6d 27 29 |.P.I}..h.....m')| +000000d0 89 4c 4a |.LJ| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 e7 04 4d dc |........... ..M.| +00000030 76 f3 7f bd 00 ce 46 d2 a6 58 26 99 02 91 88 bf |v.....F..X&.....| +00000040 b5 6b 56 2b b6 bc 51 b2 e4 cd 82 8d 13 01 00 00 |.kV+..Q.........| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 c6 67 93 be 69 04 |...........g..i.| +00000090 58 4f 1d 93 b6 5c 1c 10 8a 91 d0 c0 db 0b d1 0a |XO...\..........| +000000a0 d1 17 03 03 02 6d da d6 28 74 c7 60 d6 02 3e 28 |.....m..(t.`..>(| +000000b0 29 17 50 b9 01 4b 9b 93 07 9d 09 f0 17 05 e0 88 |).P..K..........| +000000c0 53 ec c3 28 f7 a6 4e 9b 80 a3 fd 20 db 97 51 6a |S..(..N.... ..Qj| +000000d0 b1 7a 6d 93 26 61 c8 9c 6d 37 65 94 b4 74 a0 60 |.zm.&a..m7e..t.`| +000000e0 b1 a1 38 4c eb 5e a9 c4 bd d4 29 ee e9 e3 ab 56 |..8L.^....)....V| +000000f0 68 67 57 da b3 3d 85 bd 26 67 e1 52 83 a6 69 14 |hgW..=..&g.R..i.| +00000100 3b 30 31 c7 71 83 fa 62 13 ea a3 a5 de 4b 32 3f |;01.q..b.....K2?| +00000110 c6 48 0b 96 cd 4b da 96 6d e2 31 88 ca 96 5f 63 |.H...K..m.1..._c| +00000120 cb 39 37 d8 fa 8f 1f b9 e2 c5 6b ae 60 05 5b ed |.97.......k.`.[.| +00000130 e0 5d 83 fa 2b 22 f4 e8 33 27 48 e7 c4 3d 54 22 |.]..+"..3'H..=T"| +00000140 5a 60 a9 7a 0d 9b 42 e2 50 28 0e 6c 13 16 a1 51 |Z`.z..B.P(.l...Q| +00000150 60 81 8f 80 e2 1b 53 24 62 78 b7 0a 4a 9b 2f a7 |`.....S$bx..J./.| +00000160 97 b3 ba e5 34 0d 76 a6 0e ea ec 91 f0 9c a9 6d |....4.v........m| +00000170 57 47 ef a3 c4 7a 62 a8 1f c0 1a d7 ea 31 90 20 |WG...zb......1. | +00000180 76 13 ae f1 24 9d 60 9f 30 9f 2b 2a 2f 0a 39 6c |v...$.`.0.+*/.9l| +00000190 7a 47 fe 11 1c 78 42 a1 1c ed c3 cd d2 6a cd 4f |zG...xB......j.O| +000001a0 66 1b 51 d4 43 4e 45 23 15 48 e4 84 3e 89 a3 55 |f.Q.CNE#.H..>..U| +000001b0 7e b0 a6 c2 1c cd eb cf 88 6b e7 d2 07 25 ef 37 |~........k...%.7| +000001c0 e1 8a a5 b9 03 7e 70 73 9c 23 1a 62 07 56 db ed |.....~ps.#.b.V..| +000001d0 93 e3 8a 91 8b 90 74 14 14 cc ff 9e ea e5 45 dd |......t.......E.| +000001e0 a6 2d dc e6 cb 8c 59 33 91 da e6 5c b4 73 4f 36 |.-....Y3...\.sO6| +000001f0 f1 3c d9 6e ba 2c c4 51 de 4f 8a 69 62 c4 db b1 |.<.n.,.Q.O.ib...| +00000200 9e 67 7a 5f 01 7b b7 b2 55 b1 14 c0 46 d1 43 16 |.gz_.{..U...F.C.| +00000210 a0 70 84 7e b8 a3 04 ce e3 e0 0e 5e 5f 3f 95 7a |.p.~.......^_?.z| +00000220 ef 79 8d 50 84 cd 02 f1 e0 e5 f9 26 cf 7a f9 da |.y.P.......&.z..| +00000230 a3 7d 22 31 4d 61 82 f6 ff fd 69 23 07 53 07 df |.}"1Ma....i#.S..| +00000240 5a eb 50 86 28 44 24 06 9b 21 ef ef 78 bc 67 13 |Z.P.(D$..!..x.g.| +00000250 c5 27 d8 18 db c7 fa d5 a6 0c 40 09 e3 e5 17 0c |.'........@.....| +00000260 61 ae bc 48 98 ab 7b 57 82 f7 87 a5 4b 96 25 77 |a..H..{W....K.%w| +00000270 e4 59 53 d1 d3 7b 55 08 e0 1a 5d 9b 0f 2e 6f cd |.YS..{U...]...o.| +00000280 96 9d 19 09 07 84 08 c1 cf bd 99 af 80 52 c0 f7 |.............R..| +00000290 0c 50 85 14 7c fd cb 61 01 05 ee 92 60 bb ac 4c |.P..|..a....`..L| +000002a0 b4 37 48 dc b1 34 9d 26 3a fd dc ae 21 2f d3 51 |.7H..4.&:...!/.Q| +000002b0 84 c3 0e 8f e1 b4 fb 0b 2e 3b 51 a9 e8 c2 d9 d9 |.........;Q.....| +000002c0 6b a5 af 90 30 97 a2 32 9a a3 9d 5d b3 75 c6 48 |k...0..2...].u.H| +000002d0 4b ee a3 23 85 98 a5 b5 00 fd c5 3a 27 65 9e d0 |K..#.......:'e..| +000002e0 19 a8 5a 8c 8b eb 49 c6 58 16 9a 88 67 54 82 a9 |..Z...I.X...gT..| +000002f0 29 0a 98 82 e4 f8 f0 c9 17 a6 81 91 1b c1 2a b7 |).............*.| +00000300 de c3 8b 2d a6 55 1f 61 89 90 84 15 c8 33 6e cb |...-.U.a.....3n.| +00000310 5c f4 e2 17 03 03 00 99 49 e0 38 43 34 61 b9 37 |\.......I.8C4a.7| +00000320 2c 3e d5 c7 8c d7 9b a6 6c 8e ef a6 28 13 3c 79 |,>......l...(..p[Nk..R...h.| +00000340 a0 07 ac c1 17 6e d1 11 76 1d d7 1e e2 26 3e 76 |.....n..v....&>v| +00000350 2b f9 a4 55 67 0b 9c cd db ab 71 1a 84 33 74 eb |+..Ug.....q..3t.| +00000360 b1 4b 26 d8 e8 1c 84 2b 62 c7 70 27 16 fb 16 ae |.K&....+b.p'....| +00000370 9d 72 3a 42 c1 cb cd c8 d0 dd 9c f0 51 2e 33 c1 |.r:B........Q.3.| +00000380 46 35 56 ad 3b ea be 6e 14 4d 05 d1 6d 85 93 86 |F5V.;..n.M..m...| +00000390 cc 6a 1c bf 03 cf 8f 92 c9 18 74 e0 66 0a b6 9a |.j........t.f...| +000003a0 38 ac 1a 73 f4 e0 70 ec 93 61 67 9f b8 12 6f 1f |8..s..p..ag...o.| +000003b0 17 17 03 03 00 35 59 6b 86 a8 cc 89 c6 fa 4f 95 |.....5Yk......O.| +000003c0 25 b6 90 08 ac bf 9f d5 c9 3c 6c e5 cd 0d 14 00 |%........>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 74 1e 4a 56 2c |..........5t.JV,| +00000010 fc 14 0b 66 ab 2f 56 5b fd 33 fe c2 a4 df 0b 62 |...f./V[.3.....b| +00000020 63 11 40 67 d2 11 1b 53 c5 b9 1e 0e 20 83 85 b0 |c.@g...S.... ...| +00000030 3a 81 79 bc a7 9f 49 ab 22 bd 10 8d 3e c9 95 79 |:.y...I."...>..y| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e a4 83 3b 61 a1 00 d5 56 84 4c 83 |.......;a...V.L.| +00000010 0a 8c 86 13 0c e7 95 71 aa 48 e0 d2 5f 11 5f 45 |.......q.H.._._E| +00000020 41 7a 10 17 03 03 00 13 ca 8b f5 38 e5 5f e0 8a |Az.........8._..| +00000030 e3 08 ba 7d 06 f6 b3 b4 6f e9 2b |...}....o.+| diff --git a/src/crypto/tls/testdata/Server-TLSv13-IssueTicketPreDisable b/src/crypto/tls/testdata/Server-TLSv13-IssueTicketPreDisable new file mode 100644 index 0000000..a939822 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-IssueTicketPreDisable @@ -0,0 +1,99 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ce 01 00 00 ca 03 03 cd 51 e4 0b ee |............Q...| +00000010 9c 83 0f a1 bd 1a c8 b4 94 17 5e 17 fb 63 43 31 |..........^..cC1| +00000020 89 86 03 fa 82 d4 bb c5 ba 9d 60 20 a1 0b c7 9c |..........` ....| +00000030 b0 3f d9 7a 52 bd c0 3f cd c5 21 54 40 a5 60 73 |.?.zR..?..!T@.`s| +00000040 fd ff 07 99 75 59 0d f3 bd 57 f6 81 00 04 13 01 |....uY...W......| +00000050 00 ff 01 00 00 7d 00 0b 00 04 03 00 01 02 00 0a |.....}..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c |................| +00000080 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000090 08 04 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 |.............+..| +000000a0 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 |....-.....3.&.$.| +000000b0 1d 00 20 04 16 08 0b 67 76 58 60 4a 32 c2 ea 1b |.. ....gvX`J2...| +000000c0 4a 54 fa 55 9b 39 d8 80 c4 eb 42 cc 1a 84 fe d7 |JT.U.9....B.....| +000000d0 0a 0d 43 |..C| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 a1 0b c7 9c |........... ....| +00000030 b0 3f d9 7a 52 bd c0 3f cd c5 21 54 40 a5 60 73 |.?.zR..?..!T@.`s| +00000040 fd ff 07 99 75 59 0d f3 bd 57 f6 81 13 01 00 00 |....uY...W......| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 ec 4d 41 82 de 4f |...........MA..O| +00000090 c6 cf 1e 56 06 65 0e a4 e7 66 34 1d 89 59 b3 c2 |...V.e...f4..Y..| +000000a0 0a 17 03 03 02 6d 00 e1 17 f1 b3 5e a7 14 b3 f8 |.....m.....^....| +000000b0 3a ab 85 d4 80 75 69 01 6c 91 3f 79 ab 8f 51 e0 |:....ui.l.?y..Q.| +000000c0 f6 a5 65 ab 7e 72 e5 83 99 b2 cb cd f9 5f 27 db |..e.~r......._'.| +000000d0 90 70 9c c1 e5 6d 80 3e 59 7c 4d fa f1 23 8a a7 |.p...m.>Y|M..#..| +000000e0 f4 81 22 32 5b e2 4e d0 eb ab bd 96 05 42 05 5c |.."2[.N......B.\| +000000f0 20 5c 8a 3e ca fd b8 aa dd f2 c4 3e dc 7e a5 ab | \.>.......>.~..| +00000100 95 a4 20 03 0e 41 9b 14 55 91 1b 9c 3b 17 bc 2a |.. ..A..U...;..*| +00000110 60 c0 ee b1 78 e9 37 c4 65 ef 8c 29 ec d9 10 81 |`...x.7.e..)....| +00000120 a0 1d c9 ac cf e5 36 90 88 d3 70 6d 59 66 61 a8 |......6...pmYfa.| +00000130 18 79 ad d8 c7 3e 1f a5 db dc b5 21 83 b0 ae 16 |.y...>.....!....| +00000140 ce 8e 98 d4 8e 28 c1 d3 d2 ef 51 35 45 41 a7 b4 |.....(....Q5EA..| +00000150 e1 15 bb 32 10 aa b1 27 be 53 5e 96 ef 0b bd 2f |...2...'.S^..../| +00000160 81 66 18 f4 8b 9a cc be 67 c1 32 e3 c0 ea e5 c0 |.f......g.2.....| +00000170 76 2c 36 7f 91 11 13 c1 a4 04 7e 8e 7b 60 a5 3d |v,6.......~.{`.=| +00000180 fa 3c d8 68 9a 7e 4b 23 3d 18 1b a3 34 a9 81 a4 |.<.h.~K#=...4...| +00000190 00 09 cd 56 eb f2 29 9f 17 8d 48 4d 21 a2 4e ec |...V..)...HM!.N.| +000001a0 f0 a0 8d b1 ed d6 c7 01 d0 8e 2f 25 65 9f ac eb |........../%e...| +000001b0 44 09 f2 75 db 37 a3 94 cb 70 29 59 37 97 71 63 |D..u.7...p)Y7.qc| +000001c0 9b fa 0f 0f 33 75 0a 60 4f 78 97 9e 6a 2c 4b df |....3u.`Ox..j,K.| +000001d0 54 cc c0 ac 57 4c f3 3a e3 79 01 b9 c3 8c 37 d2 |T...WL.:.y....7.| +000001e0 8f d9 e7 cd 33 5a 0c bb 43 7e 39 5f 63 9f a5 11 |....3Z..C~9_c...| +000001f0 f5 6e e0 95 1f 09 03 56 0f ec b9 7d 08 31 c5 57 |.n.....V...}.1.W| +00000200 fa a6 57 15 6c 6b 91 d4 9f 5d c2 40 8b 3d 3a 57 |..W.lk...].@.=:W| +00000210 c2 64 55 bd 88 bb 5e 24 7f fe 79 0c 88 f3 a7 1c |.dU...^$..y.....| +00000220 f8 20 6f ba d6 ec fc b2 04 2a d7 b7 17 5e 4c 2e |. o......*...^L.| +00000230 24 cd 1b 8a 04 fe 21 e0 5b 90 ec f4 30 df bf fe |$.....!.[...0...| +00000240 a8 f9 2b 40 c1 23 15 f2 44 87 9a aa 30 80 70 27 |..+@.#..D...0.p'| +00000250 80 6f 90 08 b5 47 2e 01 ea 77 3a ba a4 4b 77 8a |.o...G...w:..Kw.| +00000260 12 b4 4e e1 a6 04 8a 01 31 60 27 35 bf 76 de 09 |..N.....1`'5.v..| +00000270 aa 8a c4 c4 21 31 9f eb c2 92 05 be a1 b5 24 eb |....!1........$.| +00000280 71 24 55 f9 aa 5c 62 59 49 bf 42 4c 69 01 4f f7 |q$U..\bYI.BLi.O.| +00000290 b6 27 14 d4 cc 40 80 13 9b 8b 30 55 1f 32 c1 ee |.'...@....0U.2..| +000002a0 51 bd 71 f7 63 3f c2 00 90 60 dc 13 0f 62 c3 06 |Q.q.c?...`...b..| +000002b0 80 f6 4f cc 44 71 d7 5c 2e 18 82 45 ca 80 b7 0e |..O.Dq.\...E....| +000002c0 0c 6f 75 1b 23 cb 86 c1 2d 1e 1b 02 2a 15 fa c7 |.ou.#...-...*...| +000002d0 b2 af 80 5c 48 c2 b7 12 59 a3 e4 3c ed df 26 d0 |...\H...Y..<..&.| +000002e0 85 9b 5a 2d 7b 66 e6 c4 b3 fe cd 4d 72 4d fb da |..Z-{f.....MrM..| +000002f0 1c 0d 5c fb 2f 8a e3 70 98 ee 95 9c 12 1a fa c7 |..\./..p........| +00000300 94 7a 8e ca 4d a4 bb 2f 70 3b 67 95 fb 23 fb 8f |.z..M../p;g..#..| +00000310 8c 77 4c 17 03 03 00 99 8a 72 14 c7 82 18 d7 ed |.wL......r......| +00000320 c7 5d 32 df 44 91 6b 40 3e 0b eb a1 74 da d9 3a |.]2.D.k@>...t..:| +00000330 3c 7a 2e 7a 73 3b 63 72 33 c4 c5 27 29 33 f5 30 |..~b`| +00000480 5d 0a 82 |]..| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 35 fd 9a 7d 02 |..........55..}.| +00000010 fb b2 eb fa 51 27 3e 80 ab 60 f6 a1 54 31 13 2f |....Q'>..`..T1./| +00000020 02 b9 19 ac 68 be 25 69 b3 c4 48 87 42 75 b0 93 |....h.%i..H.Bu..| +00000030 66 3e 2e 0b 79 4f 0b 3a 59 ef 89 83 65 c9 10 9b |f>..yO.:Y...e...| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 58 0f 73 e3 ba ff d3 19 0d 89 c9 |.....X.s........| +00000010 94 8a fb 24 02 58 2a 2c eb 69 29 4e 57 d3 d2 5e |...$.X*,.i)NW..^| +00000020 ba b2 75 17 03 03 00 13 9c 5c 46 44 71 dc 68 b8 |..u......\FDq.h.| +00000030 39 cc e1 fd 2d 2a a1 a9 50 6c af |9...-*..Pl.| diff --git a/src/crypto/tls/testdata/Server-TLSv13-P256 b/src/crypto/tls/testdata/Server-TLSv13-P256 new file mode 100644 index 0000000..dd8e0f4 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-P256 @@ -0,0 +1,102 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 e3 01 00 00 df 03 03 c8 5f 11 a2 29 |............_..)| +00000010 7b c3 b7 72 5e ba e1 c5 83 45 c8 87 e1 51 27 d9 |{..r^....E...Q'.| +00000020 33 0e 68 e0 71 76 9e 8f 4e f4 da 20 da fd c6 1d |3.h.qv..N.. ....| +00000030 46 55 42 89 0a 80 e0 d3 e4 dd db 7d b1 3a 76 a3 |FUB........}.:v.| +00000040 5b d9 2a c7 f1 1a 3b 0b 8c 24 dd 4d 00 04 13 03 |[.*...;..$.M....| +00000050 00 ff 01 00 00 92 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 04 00 02 00 17 00 16 00 00 00 17 00 00 00 0d |................| +00000070 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 |................| +00000080 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000090 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| +000000a0 47 00 45 00 17 00 41 04 04 48 71 9f a6 06 17 16 |G.E...A..Hq.....| +000000b0 04 d2 b4 e7 6b 5c cf d8 9f ca 64 a7 39 9e 1a 22 |....k\....d.9.."| +000000c0 aa fc b5 4c d9 d3 b3 37 e3 d4 e1 3b 5b 00 74 df |...L...7...;[.t.| +000000d0 df e5 29 8f 7c f7 6b 02 f0 e7 fb 9b 43 6a 41 fb |..).|.k.....CjA.| +000000e0 77 5b c2 6e 99 48 69 78 |w[.n.Hix| +>>> Flow 2 (server to client) +00000000 16 03 03 00 9b 02 00 00 97 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 da fd c6 1d |........... ....| +00000030 46 55 42 89 0a 80 e0 d3 e4 dd db 7d b1 3a 76 a3 |FUB........}.:v.| +00000040 5b d9 2a c7 f1 1a 3b 0b 8c 24 dd 4d 13 03 00 00 |[.*...;..$.M....| +00000050 4f 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |O.+.....3.E...A.| +00000060 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 |..7...Q.5uq..T[.| +00000070 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e |...g..$ >.V...(^| +00000080 f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 |.+-O....lK[.V.2B| +00000090 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |.X..I..h.A.Vk.Z.| +000000a0 14 03 03 00 01 01 17 03 03 00 17 81 b8 e3 25 04 |..............%.| +000000b0 6c d8 f6 7c 04 a1 2c 8b 1f 0d cb de 29 1b e1 a3 |l..|..,.....)...| +000000c0 6f 8c 17 03 03 02 6d 81 db bc b4 f8 02 f3 c5 4e |o.....m........N| +000000d0 9e f7 5f 55 54 3e 25 a9 2f 03 06 62 2f 1e 7e d4 |.._UT>%./..b/.~.| +000000e0 19 27 88 1e ac f2 44 87 29 84 08 69 2f 5d a3 ca |.'....D.)..i/]..| +000000f0 de 8f 98 ad 25 6b c5 94 62 34 44 95 bc 17 ed e6 |....%k..b4D.....| +00000100 fe 89 9c ef 46 c9 cb ee 16 d4 42 b6 d3 50 7b 3a |....F.....B..P{:| +00000110 51 d8 20 23 02 3e 69 a8 1a 80 eb bf 7c 82 2b 1f |Q. #.>i.....|.+.| +00000120 10 5a 30 85 dd bc ff 65 4d c6 4f 7b bc 3d 64 e2 |.Z0....eM.O{.=d.| +00000130 93 2a 05 a0 af de b1 41 48 85 db 98 c9 a9 96 5c |.*.....AH......\| +00000140 64 a4 70 2e f9 4e de 38 9f 48 f7 eb 6e 14 42 3f |d.p..N.8.H..n.B?| +00000150 9f 86 0f 2d 70 6a 30 96 1c dd c6 11 28 6f 86 b6 |...-pj0.....(o..| +00000160 da bb 5b 76 c8 56 18 4a 67 bf 59 db 56 46 f0 c7 |..[v.V.Jg.Y.VF..| +00000170 80 2b 0f 0c 8a 02 58 a1 13 aa 2e 5d 61 e2 d5 23 |.+....X....]a..#| +00000180 3c 1c 75 06 e4 e4 e1 39 eb 65 6a ff 38 21 28 c9 |<.u....9.ej.8!(.| +00000190 c5 8b a5 12 21 18 2a 59 e7 4e 66 53 be d3 49 97 |....!.*Y.NfS..I.| +000001a0 f9 b1 7d e2 75 44 37 38 36 35 af 78 27 f4 74 e0 |..}.uD7865.x'.t.| +000001b0 45 ca fd 79 3c 39 65 00 46 58 4b 8b db f9 6e c0 |E..y<9e.FXK...n.| +000001c0 69 ec 1e 25 87 66 e1 b8 d8 cc 16 5b 16 9e 90 2e |i..%.f.....[....| +000001d0 16 0c 8f 25 04 cf 40 c8 50 dd c4 63 19 8f f1 76 |...%..@.P..c...v| +000001e0 5e fa 24 1d 8a d2 c1 d4 98 49 48 f0 e6 fa f3 6e |^.$......IH....n| +000001f0 63 0b a5 7a 2f f2 f0 47 0b c0 89 9f 7b 9f ef 48 |c..z/..G....{..H| +00000200 df fd 38 5d a9 71 ce 0c 3c 6f 88 0b 1b d3 93 8c |..8].q....| +00000250 96 5a 3c 97 8e 7b 47 b8 f0 58 16 12 05 69 69 a1 |.Z<..{G..X...ii.| +00000260 36 7b ff dd 92 60 26 e2 f9 53 4c 3a 25 ac 88 dd |6{...`&..SL:%...| +00000270 9a 81 7c 1f 58 27 33 14 68 44 06 e2 01 14 94 99 |..|.X'3.hD......| +00000280 00 05 8f 64 47 ca 95 fa 92 57 a9 1a 53 d5 47 52 |...dG....W..S.GR| +00000290 e8 c4 aa eb 0a f5 1b a9 09 72 92 37 f5 8d 90 b8 |.........r.7....| +000002a0 4b 08 7f 55 19 2d a7 d8 7b d9 ba 7f 5e 56 bb 80 |K..U.-..{...^V..| +000002b0 c7 d0 49 99 ae ce 2f a4 f0 ab d1 bd ba f3 0f 85 |..I.../.........| +000002c0 f1 68 c1 9d 2a 37 ff de a4 0a 6f 58 27 1d 1d 2b |.h..*7....oX'..+| +000002d0 87 9d 52 d3 70 37 a6 03 cd 77 61 9b 56 64 49 62 |..R.p7...wa.VdIb| +000002e0 ef a1 ed fe 75 1a 61 4a 58 01 d6 80 2f ab ab fc |....u.aJX.../...| +000002f0 b2 49 1f 51 b7 51 29 c1 a1 39 fc f4 0a 9b 0d 76 |.I.Q.Q)..9.....v| +00000300 c6 d0 89 c9 8f 88 e9 ec 13 90 78 4f 0c f5 c9 7e |..........xO...~| +00000310 d5 b3 13 ad 35 6d 53 d0 88 50 e8 47 15 a0 ca fc |....5mS..P.G....| +00000320 5f 6e 98 23 46 6a 69 84 3c a9 3f eb d1 05 f5 97 |_n.#Fji.<.?.....| +00000330 11 39 7f 39 17 03 03 00 99 84 8e 37 a9 57 78 12 |.9.9.......7.Wx.| +00000340 8e 9a e7 8e 45 ee 55 61 66 24 ed 5a 36 19 e3 1c |....E.Uaf$.Z6...| +00000350 22 3b 8b c0 4b c9 cd 2c 4c 17 d2 a9 40 2c 02 40 |";..K..,L...@,.@| +00000360 74 ba 11 de a5 d4 01 11 ae 9d 71 76 4c f0 87 0f |t.........qvL...| +00000370 5e 75 c0 67 c0 33 e7 3e 9b d3 a4 21 e8 40 a6 9f |^u.g.3.>...!.@..| +00000380 d8 24 a7 d7 c1 99 cc 8d 33 10 91 0a 41 a6 05 1c |.$......3...A...| +00000390 85 4c c5 a8 c9 dd 74 d0 5c 67 2e 2a 50 4e 30 c7 |.L....t.\g.*PN0.| +000003a0 bb fa f8 65 ee 48 23 f5 c5 d3 a1 ec 4d 3f ac 4b |...e.H#.....M?.K| +000003b0 ef 1e 8d 84 07 b9 69 2a 34 51 73 ba fb b5 7d 64 |......i*4Qs...}d| +000003c0 1f fc 0e c8 33 d9 77 5e 41 00 65 25 ea 75 75 c9 |....3.w^A.e%.uu.| +000003d0 2b 03 17 03 03 00 35 54 c2 06 55 7c 6f 92 8a d2 |+.....5T..U|o...| +000003e0 d5 35 0c 4b 0d df cb d7 6e 5d 64 e1 2e cf 50 b8 |.5.K....n]d...P.| +000003f0 d8 04 9a f4 ce 69 d3 ac bb 47 cd 57 ac 07 aa 40 |.....i...G.W...@| +00000400 e3 fc 01 bc d6 a1 0e 16 4e 6b 04 cc 17 03 03 00 |........Nk......| +00000410 93 b2 c3 64 29 13 07 75 b4 c4 84 f7 0e 99 d9 9f |...d)..u........| +00000420 8d 5b fd 26 07 42 48 33 3a ab 6f 7d 07 8b f6 8a |.[.&.BH3:.o}....| +00000430 22 a4 ce 64 0f 69 ea 61 95 70 6d d3 f8 5f 8b ad |"..d.i.a.pm.._..| +00000440 02 43 94 41 51 f4 f8 0b 52 fc 58 c1 23 5e 22 a7 |.C.AQ...R.X.#^".| +00000450 74 49 a1 46 e8 29 ab d6 ae 02 a4 7b e4 23 f1 89 |tI.F.).....{.#..| +00000460 1c b1 74 86 92 1b 6a 7c 2f 55 2b 89 f6 01 fc e2 |..t...j|/U+.....| +00000470 d6 15 b9 b1 64 1c 4a af f8 fe 3e e0 76 0f cf 08 |....d.J...>.v...| +00000480 e1 2c db f6 1c 77 6f e4 a4 80 ad 13 74 3d 02 52 |.,...wo.....t=.R| +00000490 a1 ff 3e 85 1d d3 77 bc f2 48 73 1c 45 09 62 34 |..>...w..Hs.E.b4| +000004a0 80 09 21 41 |..!A| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 ab dd 69 66 c8 |..........5..if.| +00000010 f9 eb e6 e6 b0 a9 9b 10 1d fc ad 89 ad 4d f5 2b |.............M.+| +00000020 e4 d7 12 5b 1c 1e 81 12 df 24 ba ea 6b 3e 6f 82 |...[.....$..k>o.| +00000030 dd 2f 38 a1 65 07 55 6a 4f 8e 99 5d 4f 35 b8 5d |./8.e.UjO..]O5.]| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e e5 f4 e6 14 79 8c b9 a9 77 6b c9 |.........y...wk.| +00000010 ff ad 60 f3 03 cf 48 19 19 71 6c 85 da 92 cb 79 |..`...H..ql....y| +00000020 2b 20 41 17 03 03 00 13 69 de ca 08 9c cf 70 37 |+ A.....i.....p7| +00000030 5e fc 32 31 1c 93 d1 e4 01 f3 c6 |^.21.......| diff --git a/src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS b/src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS new file mode 100644 index 0000000..db53ebb --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS @@ -0,0 +1,97 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 b2 01 00 00 ae 03 03 4d a5 7b 2c da |...........M.{,.| +00000010 67 11 9d 4d a0 92 2a 96 6c 85 ef 8c 52 0a 31 cf |g..M..*.l...R.1.| +00000020 43 23 3e 8d 67 63 9b 7e 84 94 17 20 a2 a1 87 c6 |C#>.gc.~... ....| +00000030 5e 64 34 75 da ac ee ba d4 d8 8f 2a a6 55 9f 4f |^d4u.......*.U.O| +00000040 48 38 5a 29 61 a4 ef 7d 1d 74 a7 71 00 04 13 03 |H8Z)a..}.t.q....| +00000050 00 ff 01 00 00 61 00 0b 00 04 03 00 01 02 00 0a |.....a..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000070 00 00 00 17 00 00 00 0d 00 06 00 04 08 06 08 04 |................| +00000080 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| +00000090 26 00 24 00 1d 00 20 16 5e 23 ca e7 24 31 81 c2 |&.$... .^#..$1..| +000000a0 78 21 3a ee 8a f3 61 8a 46 a0 56 ee a9 ed 82 3a |x!:...a.F.V....:| +000000b0 87 b7 4a 0a 03 fe 59 |..J...Y| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 a2 a1 87 c6 |........... ....| +00000030 5e 64 34 75 da ac ee ba d4 d8 8f 2a a6 55 9f 4f |^d4u.......*.U.O| +00000040 48 38 5a 29 61 a4 ef 7d 1d 74 a7 71 13 03 00 00 |H8Z)a..}.t.q....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 f8 7a 9c bc 58 8d |...........z..X.| +00000090 ce cd ff e6 ae 2d c2 e0 40 33 4e c4 ec f5 90 dd |.....-..@3N.....| +000000a0 ba 17 03 03 02 6d f3 65 a1 b4 fe ef 40 37 72 fa |.....m.e....@7r.| +000000b0 a5 b8 10 ad 32 e3 08 e1 ac bb 14 f2 34 bf 25 19 |....2.......4.%.| +000000c0 aa 2d 1a 78 cc 26 2f 5c 0b 7e 13 73 36 85 92 96 |.-.x.&/\.~.s6...| +000000d0 0a 7a 27 f5 35 86 f1 ea 1a 5f 5c 3a 90 28 63 6a |.z'.5...._\:.(cj| +000000e0 b3 7c e0 56 32 10 55 67 59 e0 65 d6 11 ef 7c 50 |.|.V2.UgY.e...|P| +000000f0 0b 9e 88 0a 61 96 93 cf 05 51 47 33 c3 5c e3 82 |....a....QG3.\..| +00000100 01 6d f1 f7 5c dc df b2 61 7c d7 9f de b4 3e c0 |.m..\...a|....>.| +00000110 6d b5 52 39 3b f6 33 c2 03 65 2b 66 39 ed d6 f0 |m.R9;.3..e+f9...| +00000120 83 46 61 db fc 27 a5 8a 68 d6 8a 85 5d 3f b1 46 |.Fa..'..h...]?.F| +00000130 a2 3a 32 37 1f e0 76 a6 79 7f eb b2 81 52 e7 e0 |.:27..v.y....R..| +00000140 4f b2 db 48 7d 20 61 52 d4 22 2a b7 81 2f da 5b |O..H} aR."*../.[| +00000150 f6 e8 0a a6 91 b5 d1 f5 6b 5e 2b ad fd 70 cd a1 |........k^+..p..| +00000160 f8 4d 73 31 3d 2a 49 d3 2e 6b b3 31 95 61 09 08 |.Ms1=*I..k.1.a..| +00000170 c5 f9 eb db 42 b0 e1 5d 47 00 3e 7e 80 31 c6 d2 |....B..]G.>~.1..| +00000180 37 dc 68 d7 36 05 ad 8a a4 05 87 7a 1c 12 f6 ab |7.h.6......z....| +00000190 0e e1 5b 29 b1 1c 16 20 29 75 5a b0 59 24 59 df |..[)... )uZ.Y$Y.| +000001a0 62 fe f2 26 ad ab bf 2b 25 d7 9e db 04 f6 26 96 |b..&...+%.....&.| +000001b0 f7 5f 2c ff 2e 6d 85 c7 58 c8 15 9c d0 7d dd 8e |._,..m..X....}..| +000001c0 1a 39 fc 3d 62 58 47 ce 83 7a ff fc 45 98 02 3d |.9.=bXG..z..E..=| +000001d0 aa 37 b7 5e a7 7b 8e fa f2 05 8b 61 7f 04 08 f5 |.7.^.{.....a....| +000001e0 af 1d 6e 55 18 d2 12 2e bd 8a 80 3d cb e6 0f cd |..nU.......=....| +000001f0 3c d8 a5 38 db ee 07 c6 3b 75 55 c2 ee 2e 6a a3 |<..8....;uU...j.| +00000200 fa 54 ce e3 45 92 c0 b9 8c 10 3d 2f 86 cb a5 c9 |.T..E.....=/....| +00000210 af 37 f7 f6 6c 3e 4b 15 04 bd 46 98 31 5a b9 8c |.7..l>K...F.1Z..| +00000220 ec 67 0d 97 9d 26 56 65 9c a7 74 bb 88 45 dc 4e |.g...&Ve..t..E.N| +00000230 ce 70 a1 fc ce fc a7 d4 e1 7d a7 43 82 a6 e2 30 |.p.......}.C...0| +00000240 e2 94 88 e5 1a 05 c5 28 06 14 7b 29 75 f9 4d 2c |.......(..{)u.M,| +00000250 bb 54 ee f5 17 4e 2a bf 04 e6 38 f2 cf ed ab a2 |.T...N*...8.....| +00000260 ef ae ac 3d 80 5e 03 71 74 70 0c 68 93 ca ea 93 |...=.^.qtp.h....| +00000270 e5 b1 d1 18 80 98 0e c6 e8 f5 65 87 e7 9a 33 1d |..........e...3.| +00000280 e6 3d e2 28 82 19 2a 9d 5f 1a a2 74 fa 27 8b d0 |.=.(..*._..t.'..| +00000290 09 9a ba 1b c5 a6 4c 3b c3 02 12 61 a1 8a 20 d3 |......L;...a.. .| +000002a0 a4 3c 3b aa f2 08 de e0 de 07 9f a0 13 b4 e8 23 |.<;............#| +000002b0 d3 a5 ff 12 74 55 29 3a 57 f5 14 b3 af e6 28 ed |....tU):W.....(.| +000002c0 b1 60 9c 6b 7d 55 a1 58 50 ab 42 71 5d 0e dc 76 |.`.k}U.XP.Bq]..v| +000002d0 87 cd a1 d3 e4 26 25 c4 c1 23 1e 3b 31 13 3d f8 |.....&%..#.;1.=.| +000002e0 b2 1b a8 07 f6 68 83 b4 7e 94 ca 84 95 55 38 d1 |.....h..~....U8.| +000002f0 eb af 19 83 90 4a ab 0a 8d f6 48 9a 25 fa 59 97 |.....J....H.%.Y.| +00000300 3c 5f 6a 2d 68 ec 29 d5 53 b4 9a 97 ea 59 fe 74 |<_j-h.).S....Y.t| +00000310 81 0e b9 17 03 03 00 99 12 25 df 91 85 91 ac c0 |.........%......| +00000320 60 4e 6e ed c4 b2 f0 f3 8b 66 53 75 11 07 29 d6 |`Nn......fSu..).| +00000330 1f 01 81 60 de 5f b7 6b 5e 39 c8 ea f1 f8 2a 94 |...`._.k^9....*.| +00000340 dd b6 c5 a9 31 be 87 a7 aa a9 64 03 16 40 df ef |....1.....d..@..| +00000350 37 ac 66 4c 19 f1 60 d5 b4 88 93 a7 42 ac e3 81 |7.fL..`.....B...| +00000360 c8 88 3f e2 30 a0 ff b7 d5 19 fc f2 72 a7 97 a8 |..?.0.......r...| +00000370 31 ce 20 be 90 bc f5 8a 24 31 b1 c6 2b 2a ad c5 |1. .....$1..+*..| +00000380 7a 34 69 eb a7 86 53 61 a1 88 4f 58 2a 65 a2 18 |z4i...Sa..OX*e..| +00000390 7a 93 81 c6 bd c7 bc 84 5b ff 85 aa ff fc 68 50 |z.......[.....hP| +000003a0 cb 57 37 54 a7 0f 2e 64 82 53 b7 dc ea c2 e3 49 |.W7T...d.S.....I| +000003b0 fd 17 03 03 00 35 da 2a 8c 37 83 a5 a0 d4 06 c4 |.....5.*.7......| +000003c0 ff f3 85 6f e4 11 1f 37 0f 06 35 45 e9 51 43 6f |...o...7..5E.QCo| +000003d0 d2 a4 cb b7 ad f0 66 1c 20 40 c3 14 32 c0 57 71 |......f. @..2.Wq| +000003e0 d3 8c 9c 7f 5b e6 50 a1 c2 e5 62 17 03 03 00 93 |....[.P...b.....| +000003f0 30 b8 ab dc 3b df 60 aa b1 d2 25 5a 60 da b6 c8 |0...;.`...%Z`...| +00000400 22 88 93 79 25 44 56 aa ec 93 e8 01 11 bf 69 ad |"..y%DV.......i.| +00000410 b2 c9 43 67 33 aa 6d ae 73 a3 95 2b f0 86 ed a2 |..Cg3.m.s..+....| +00000420 db df e3 dc 9b 16 1d 8d fc 2f a5 c4 41 d0 86 2f |........./..A../| +00000430 cc a1 a1 ce 9a e5 e6 c8 a2 d1 a8 b2 a4 15 9c 69 |...............i| +00000440 38 5a fa fd de d4 02 95 24 67 1b 61 76 1f c4 65 |8Z......$g.av..e| +00000450 01 fc 36 2d ef 2d 0f 8e f0 5a 6d 04 07 b8 26 18 |..6-.-...Zm...&.| +00000460 90 fc 82 1b 99 68 b0 13 7f 6e a1 9b c4 2a f3 b8 |.....h...n...*..| +00000470 0b 6a 44 cd 04 e8 20 96 6d f5 48 cb 71 8a 04 10 |.jD... .m.H.q...| +00000480 b8 8d 56 |..V| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 54 e5 3f f8 77 |..........5T.?.w| +00000010 59 e3 8b 02 0b 80 8d 59 12 22 23 09 cb d9 93 67 |Y......Y."#....g| +00000020 c7 35 b4 45 a0 54 49 fd 65 b5 ff e6 3e 3c b9 bf |.5.E.TI.e...><..| +00000030 26 ca df 86 db a4 66 b5 3e 1f 36 69 a5 99 2b ed |&.....f.>.6i..+.| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e e3 b4 3e 81 ff 1a 36 f8 11 53 64 |.......>...6..Sd| +00000010 b9 28 4e 68 de ee 9c b6 4d 71 21 fa 85 56 30 ad |.(Nh....Mq!..V0.| +00000020 e9 c2 27 17 03 03 00 13 3d b8 13 b0 5f df 5a 05 |..'.....=..._.Z.| +00000030 85 cf eb 48 86 fb c5 a0 67 f7 ee |...H....g..| diff --git a/src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS-TooSmall b/src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS-TooSmall new file mode 100644 index 0000000..6d27e90 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-RSA-RSAPSS-TooSmall @@ -0,0 +1,15 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 b0 01 00 00 ac 03 03 15 df ef fb ff |................| +00000010 00 89 4d bf 59 d2 30 f1 f3 e7 20 24 c6 06 ba a4 |..M.Y.0... $....| +00000020 28 b4 ba 3d 00 f2 18 9b 98 a3 f2 20 7e d9 d0 58 |(..=....... ~..X| +00000030 50 25 90 2d f0 af 72 66 fb f8 54 33 6e d4 2b f0 |P%.-..rf..T3n.+.| +00000040 0f 1a ea dc 9e 08 34 ed 68 a8 d8 bd 00 04 13 03 |......4.h.......| +00000050 00 ff 01 00 00 5f 00 0b 00 04 03 00 01 02 00 0a |....._..........| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| +00000070 00 00 00 17 00 00 00 0d 00 04 00 02 08 06 00 2b |...............+| +00000080 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 |......-.....3.&.| +00000090 24 00 1d 00 20 6e 42 98 d4 04 32 d1 21 0f 64 c9 |$... nB...2.!.d.| +000000a0 b7 f2 b2 52 6f 2b b7 b1 95 4b 57 85 7b 69 d9 63 |...Ro+...KW.{i.c| +000000b0 19 48 d2 1c 1e |.H...| +>>> Flow 2 (server to client) +00000000 15 03 03 00 02 02 28 |......(| diff --git a/src/crypto/tls/testdata/Server-TLSv13-Resume b/src/crypto/tls/testdata/Server-TLSv13-Resume new file mode 100644 index 0000000..091ffc3 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-Resume @@ -0,0 +1,60 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 6e 01 00 01 6a 03 03 b6 39 89 61 fd |....n...j...9.a.| +00000010 11 84 b3 4b a9 18 23 b2 35 3d 82 85 75 5c e2 f3 |...K..#.5=..u\..| +00000020 c9 f4 b0 2f 05 fb 5a 90 da 73 38 20 7f 06 81 e5 |.../..Z..s8 ....| +00000030 d0 10 08 d1 b0 3c 3c 4b 28 39 34 9a 56 ca 47 4a |.....<.....| +000000f0 00 00 00 00 00 00 00 00 00 00 00 94 68 2c a3 82 |............h,..| +00000100 51 ed 14 ef 68 ca 42 c5 5c ab 26 c2 91 a9 01 83 |Q...h.B.\.&.....| +00000110 13 26 8f 62 7c 89 c0 a2 b5 9b 6d 4f a4 c9 e2 49 |.&.b|.....mO...I| +00000120 34 03 2c b2 7d d9 af eb 1a 99 76 3c a5 ef 70 78 |4.,.}.....v<..px| +00000130 59 58 1c 45 80 c5 f1 b8 91 b2 54 71 3f bf 4f 2a |YX.E......Tq?.O*| +00000140 b2 9d 9d 6f 6f 1c f1 3c 6c e6 a2 73 00 00 00 00 |...oo..>> Flow 2 (server to client) +00000000 16 03 03 00 80 02 00 00 7c 03 03 00 00 00 00 00 |........|.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 7f 06 81 e5 |........... ....| +00000030 d0 10 08 d1 b0 3c 3c 4b 28 39 34 9a 56 ca 47 4a |.....<>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 69 08 b0 a0 71 |..........5i...q| +00000010 1f 95 45 c4 b2 11 43 a9 b5 da ba 11 0a 2b 24 49 |..E...C......+$I| +00000020 ac 3d 8e ec 32 c9 7f 3e cc 1b fc 9a 68 d0 22 cb |.=..2..>....h.".| +00000030 37 0e 8f fe 4f 75 1a 62 44 20 60 c2 64 de 48 6d |7...Ou.bD `.d.Hm| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e d5 71 aa 53 2d 55 b7 76 11 45 b0 |......q.S-U.v.E.| +00000010 f3 de f7 f1 78 0b 10 3f 49 7f ea 83 17 2e b9 50 |....x..?I......P| +00000020 ec d2 0f 17 03 03 00 13 0a 22 58 66 d8 f7 ad fc |........."Xf....| +00000030 9c f2 da d1 ae 02 f8 99 d2 26 63 |.........&c| diff --git a/src/crypto/tls/testdata/Server-TLSv13-Resume-HelloRetryRequest b/src/crypto/tls/testdata/Server-TLSv13-Resume-HelloRetryRequest new file mode 100644 index 0000000..d0aa66a --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-Resume-HelloRetryRequest @@ -0,0 +1,96 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 68 01 00 01 64 03 03 a0 27 b0 af b0 |....h...d...'...| +00000010 15 2c ed 88 b2 e8 c5 67 2e db 0d 29 13 64 bb 58 |.,.....g...).d.X| +00000020 3b 71 67 a9 47 65 8a 3c 09 44 29 20 46 fe 89 4b |;qg.Ge.<.D) F..K| +00000030 f3 1d ed 40 2d 5c 1b 23 26 f5 72 6f d1 b4 77 f5 |...@-\.#&.ro..w.| +00000040 1a 9f d1 98 34 46 fe 89 0b 2d c1 f9 00 04 13 01 |....4F...-......| +00000050 00 ff 01 00 01 17 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 06 00 04 00 1d 00 17 00 23 00 00 00 16 00 00 |.........#......| +00000070 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 03 06 03 |................| +00000080 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 |................| +00000090 04 01 05 01 06 01 00 2b 00 03 02 03 04 00 2d 00 |.......+......-.| +000000a0 02 01 01 00 33 00 26 00 24 00 1d 00 20 8c 7b 61 |....3.&.$... .{a| +000000b0 71 c8 0b 1a 17 14 d9 eb 21 38 e6 2f c0 40 e9 2d |q.......!8./.@.-| +000000c0 3c 91 c5 4e 9d bb dd af 40 bc 91 38 74 00 29 00 |<..N....@..8t.).| +000000d0 9c 00 77 00 71 50 46 ad c1 db a8 38 86 7b 2b bb |..w.qPF....8.{+.| +000000e0 fd d0 c3 42 3e 00 00 00 00 00 00 00 00 00 00 00 |...B>...........| +000000f0 00 00 00 00 00 94 68 2c a3 82 51 ed 14 ef 68 ca |......h,..Q...h.| +00000100 42 c5 5c ab 26 c2 91 a9 01 83 13 26 8f 62 7c 89 |B.\.&......&.b|.| +00000110 c0 a2 b5 9b 6d 4f a4 c9 e2 49 34 03 2c b2 7d d9 |....mO...I4.,.}.| +00000120 af eb 1a 99 76 3c a5 ef 70 78 59 58 1c 45 80 c5 |....v<..pxYX.E..| +00000130 f1 b8 91 b2 54 71 3f bf 4f 2a b2 9d 9d 6f 6f 1c |....Tq?.O*...oo.| +00000140 f1 3c 6c e6 a2 73 00 00 00 00 00 21 20 7b 6e 44 |.>> Flow 2 (server to client) +00000000 16 03 03 00 58 02 00 00 54 03 03 cf 21 ad 74 e5 |....X...T...!.t.| +00000010 9a 61 11 be 1d 8c 02 1e 65 b8 91 c2 a2 11 16 7a |.a......e......z| +00000020 bb 8c 5e 07 9e 09 e2 c8 a8 33 9c 20 46 fe 89 4b |..^......3. F..K| +00000030 f3 1d ed 40 2d 5c 1b 23 26 f5 72 6f d1 b4 77 f5 |...@-\.#&.ro..w.| +00000040 1a 9f d1 98 34 46 fe 89 0b 2d c1 f9 13 01 00 00 |....4F...-......| +00000050 0c 00 2b 00 02 03 04 00 33 00 02 00 17 14 03 03 |..+.....3.......| +00000060 00 01 01 |...| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 16 03 03 01 89 01 00 01 85 03 |................| +00000010 03 a0 27 b0 af b0 15 2c ed 88 b2 e8 c5 67 2e db |..'....,.....g..| +00000020 0d 29 13 64 bb 58 3b 71 67 a9 47 65 8a 3c 09 44 |.).d.X;qg.Ge.<.D| +00000030 29 20 46 fe 89 4b f3 1d ed 40 2d 5c 1b 23 26 f5 |) F..K...@-\.#&.| +00000040 72 6f d1 b4 77 f5 1a 9f d1 98 34 46 fe 89 0b 2d |ro..w.....4F...-| +00000050 c1 f9 00 04 13 01 00 ff 01 00 01 38 00 0b 00 04 |...........8....| +00000060 03 00 01 02 00 0a 00 06 00 04 00 1d 00 17 00 23 |...............#| +00000070 00 00 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c |................| +00000080 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000090 08 04 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 |.............+..| +000000a0 02 03 04 00 2d 00 02 01 01 00 33 00 47 00 45 00 |....-.....3.G.E.| +000000b0 17 00 41 04 6e 14 0d ac 3f 1a 2a 36 54 4f ec 9d |..A.n...?.*6TO..| +000000c0 da 5b 93 12 42 eb 58 11 1b 4c 5c 39 a2 32 b8 5b |.[..B.X..L\9.2.[| +000000d0 41 13 51 05 88 fe 45 d2 01 ef 8d 14 bc 96 de d3 |A.Q...E.........| +000000e0 1c e3 eb 0c a0 a7 a3 7c 1c b1 9e 38 c2 dc f6 35 |.......|...8...5| +000000f0 7b 5b 08 2e 00 29 00 9c 00 77 00 71 50 46 ad c1 |{[...)...w.qPF..| +00000100 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 |..8.{+....B>....| +00000110 00 00 00 00 00 00 00 00 00 00 00 00 94 68 2c a3 |.............h,.| +00000120 82 51 ed 14 ef 68 ca 42 c5 5c ab 26 c2 91 a9 01 |.Q...h.B.\.&....| +00000130 83 13 26 8f 62 7c 89 c0 a2 b5 9b 6d 4f a4 c9 e2 |..&.b|.....mO...| +00000140 49 34 03 2c b2 7d d9 af eb 1a 99 76 3c a5 ef 70 |I4.,.}.....v<..p| +00000150 78 59 58 1c 45 80 c5 f1 b8 91 b2 54 71 3f bf 4f |xYX.E......Tq?.O| +00000160 2a b2 9d 9d 6f 6f 1c f1 3c 6c e6 a2 73 00 00 00 |*...oo..>> Flow 4 (server to client) +00000000 16 03 03 00 a1 02 00 00 9d 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 46 fe 89 4b |........... F..K| +00000030 f3 1d ed 40 2d 5c 1b 23 26 f5 72 6f d1 b4 77 f5 |...@-\.#&.ro..w.| +00000040 1a 9f d1 98 34 46 fe 89 0b 2d c1 f9 13 01 00 00 |....4F...-......| +00000050 55 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |U.+.....3.E...A.| +00000060 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 |..7...Q.5uq..T[.| +00000070 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e |...g..$ >.V...(^| +00000080 f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 |.+-O....lK[.V.2B| +00000090 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |.X..I..h.A.Vk.Z.| +000000a0 00 29 00 02 00 00 17 03 03 00 17 ea 86 30 48 65 |.)...........0He| +000000b0 cf a6 d4 9d af f7 75 d4 d3 dd af 79 ce 3a 42 5b |......u....y.:B[| +000000c0 68 7a 17 03 03 00 35 ef d6 22 53 ec 3c 27 84 c7 |hz....5.."S.<'..| +000000d0 7f b2 81 8e 3e 70 51 25 95 b4 6a 79 01 15 60 c0 |....>pQ%..jy..`.| +000000e0 39 eb 5b 90 7b 50 f5 3b 50 64 d2 b2 d6 c7 72 cf |9.[.{P.;Pd....r.| +000000f0 35 f3 25 1c 86 4b 69 ab 6e 50 86 2e 17 03 03 00 |5.%..Ki.nP......| +00000100 93 66 5a c1 de c6 92 96 95 92 48 90 e7 0f e1 08 |.fZ.......H.....| +00000110 25 b2 72 a5 7f c5 17 6e 70 5d 6e 68 78 32 72 8d |%.r....np]nhx2r.| +00000120 3a fa 7a 66 76 26 10 9e f9 92 ca 3b a7 6c 6c fa |:.zfv&.....;.ll.| +00000130 72 d1 22 f4 b0 b9 2a 90 bd ce 58 e4 ff 1d 88 99 |r."...*...X.....| +00000140 a4 8d f9 10 af c8 35 cd c4 6f 99 cd 9e 6c 95 b1 |......5..o...l..| +00000150 b7 6e a4 48 9e 75 f1 d3 c0 b3 27 f1 61 83 ea 13 |.n.H.u....'.a...| +00000160 06 7f 37 38 f1 31 9e 71 5a 97 15 b5 46 63 44 e8 |..78.1.qZ...FcD.| +00000170 f4 a1 fc 81 5d f4 c7 65 be 76 da 79 bd fb e4 e6 |....]..e.v.y....| +00000180 68 de ce f3 32 6b 0c ee 19 18 75 33 77 f2 34 3d |h...2k....u3w.4=| +00000190 9e c3 da b7 |....| +>>> Flow 5 (client to server) +00000000 17 03 03 00 35 59 51 fe aa 0a 69 ef d5 0e ee e3 |....5YQ...i.....| +00000010 0e 21 f7 e0 80 88 a0 da 23 7a 38 7f 73 e1 da e9 |.!......#z8.s...| +00000020 7c 02 73 5e f2 64 e5 60 0e c6 d5 9e 7a 45 c2 0b ||.s^.d.`....zE..| +00000030 6f 08 46 46 5b f1 5b 67 5d 42 |o.FF[.[g]B| +>>> Flow 6 (server to client) +00000000 17 03 03 00 1e 3c a5 86 73 ea 62 44 ee 3b 45 a2 |.....<..s.bD.;E.| +00000010 2a 57 ed 27 0e 65 40 48 23 10 7f ff 27 e5 4e d1 |*W.'.e@H#...'.N.| +00000020 99 9a e1 17 03 03 00 13 1e 78 1a 08 4b 24 1b fc |.........x..K$..| +00000030 78 e5 ab fd 8f bf 53 26 f9 b7 c0 |x.....S&...| diff --git a/src/crypto/tls/testdata/Server-TLSv13-ResumeDisabled b/src/crypto/tls/testdata/Server-TLSv13-ResumeDisabled new file mode 100644 index 0000000..9f14b60 --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-ResumeDisabled @@ -0,0 +1,99 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 6e 01 00 01 6a 03 03 0f 31 f0 17 d6 |....n...j...1...| +00000010 3e ee f6 b9 14 05 57 cb 41 0b a4 6a 2f 70 9e 69 |>.....W.A..j/p.i| +00000020 09 2a eb ec 9a f4 47 61 09 43 09 20 d2 5d cf 57 |.*....Ga.C. .].W| +00000030 b8 81 3c a5 0a 77 50 0a c3 88 79 7a dc d0 2f 8a |..<..wP...yz../.| +00000040 08 ea 5f 53 54 a6 ff 43 d2 03 55 0e 00 04 13 01 |.._ST..C..U.....| +00000050 00 ff 01 00 01 1d 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c |................| +00000080 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| +00000090 08 04 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 |.............+..| +000000a0 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 |....-.....3.&.$.| +000000b0 1d 00 20 b4 ef 07 d4 1b 0e a1 42 ee f1 f3 84 3e |.. .......B....>| +000000c0 9f fe bb a6 af 59 9d 04 96 03 1b 43 1a b8 f7 7f |.....Y.....C....| +000000d0 44 64 60 00 29 00 9c 00 77 00 71 50 46 ad c1 db |Dd`.)...w.qPF...| +000000e0 a8 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 |.8.{+....B>.....| +000000f0 00 00 00 00 00 00 00 00 00 00 00 94 68 2c a3 82 |............h,..| +00000100 51 ed 14 ef 68 ca 42 c5 5c 90 6b 88 83 a9 b3 63 |Q...h.B.\.k....c| +00000110 7c 1c 04 ce dd be 5a 26 ef 4e 37 52 ea 9a 45 6b ||.....Z&.N7R..Ek| +00000120 ea 89 a5 26 7d c3 ea 67 db 99 76 3c e5 52 89 d0 |...&}..g..v<.R..| +00000130 4b 46 41 2e 62 5c ce a8 2e 9a 67 e9 52 f0 40 d2 |KFA.b\....g.R.@.| +00000140 f1 0e ab 02 0f 54 c8 0b 5e 91 8f 8b 00 00 00 00 |.....T..^.......| +00000150 00 21 20 e0 71 35 06 a0 30 9f bf 5a 6e f3 14 fd |.! .q5..0..Zn...| +00000160 34 0b 6d d5 36 08 82 8f d0 79 cc f3 74 7c a9 a5 |4.m.6....y..t|..| +00000170 c3 81 27 |..'| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 d2 5d cf 57 |........... .].W| +00000030 b8 81 3c a5 0a 77 50 0a c3 88 79 7a dc d0 2f 8a |..<..wP...yz../.| +00000040 08 ea 5f 53 54 a6 ff 43 d2 03 55 0e 13 01 00 00 |.._ST..C..U.....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 df 85 83 6b 9d e0 |.............k..| +00000090 8d b4 da b1 f2 c7 ff c1 13 33 d4 53 b8 92 bf 83 |.........3.S....| +000000a0 6c 17 03 03 02 6d 6b 0f f6 15 41 46 aa 92 06 af |l....mk...AF....| +000000b0 c9 a2 73 c5 31 64 c1 cd 3a e5 e6 9a d9 04 f4 01 |..s.1d..:.......| +000000c0 d5 0e d6 30 e2 7a 6d 0c 23 d5 4b b1 70 58 c8 ca |...0.zm.#.K.pX..| +000000d0 5d 1f c9 7c 76 f8 f9 90 b0 f6 05 f6 85 d2 10 b6 |]..|v...........| +000000e0 bb b1 49 07 8a ba 9b d8 1a f4 48 18 f5 c5 90 f1 |..I.......H.....| +000000f0 a7 24 cd 3b ab 2f 49 28 fa 3c 64 80 50 a6 38 d9 |.$.;./I(..H2..| +00000170 37 13 08 f2 cc cb bb f5 55 d5 7d 97 5e 6a df 11 |7.......U.}.^j..| +00000180 33 fd 34 65 99 c2 40 7b a3 7a 04 92 63 ad 19 9d |3.4e..@{.z..c...| +00000190 02 2a 6f d1 c8 f7 e1 d1 0f a1 c3 5b 81 70 b0 e5 |.*o........[.p..| +000001a0 97 a4 b2 76 c5 9b 55 f5 da 2d 53 d2 49 4b a7 6a |...v..U..-S.IK.j| +000001b0 0f 0f c8 d6 a5 00 83 52 fb 12 c6 6b 98 51 a3 4e |.......R...k.Q.N| +000001c0 86 39 ab 7e 76 1f 31 b5 5e 50 53 1b 21 af 7f a0 |.9.~v.1.^PS.!...| +000001d0 b9 3c cf 59 19 c7 c8 b6 ef d7 4f e5 ea 5e bc 67 |.<.Y......O..^.g| +000001e0 00 47 97 50 85 15 54 19 eb de b8 11 0e 39 9a b0 |.G.P..T......9..| +000001f0 be cd db d9 53 88 9c 78 e8 b9 5e 12 4b 30 63 d5 |....S..x..^.K0c.| +00000200 eb 48 d1 d4 95 94 58 61 9c 53 ad 97 bd 45 3a 09 |.H....Xa.S...E:.| +00000210 d0 83 a7 ba 8c 64 87 42 b7 e1 fa 1b 32 58 8b de |.....d.B....2X..| +00000220 70 34 34 6d fb 0f a0 27 c3 8b 69 61 43 30 24 b2 |p44m...'..iaC0$.| +00000230 32 4b ca 6c 0b ea f7 4b df e5 5f 3d 06 ea 0d 31 |2K.l...K.._=...1| +00000240 4a c6 19 44 61 a1 5b 45 ee 9b ea 69 42 8f 35 86 |J..Da.[E...iB.5.| +00000250 09 c7 83 51 32 e6 7b 45 bb fb 11 1f 4d 3f b8 10 |...Q2.{E....M?..| +00000260 6a 0c 52 4c fd 20 62 0f 75 26 8a 65 67 e9 7e 56 |j.RL. b.u&.eg.~V| +00000270 f4 ed 01 67 9e 27 0d 39 98 b4 97 44 50 f6 26 11 |...g.'.9...DP.&.| +00000280 3c e4 40 17 5c f1 eb 85 1f 13 f9 8d 22 66 2d 2e |<.@.\......."f-.| +00000290 3b f8 eb 08 7d df f6 ba 7b ec 15 34 04 e2 6d aa |;...}...{..4..m.| +000002a0 e2 1c 5a e6 e8 4f 00 0c 07 1b dd 6e 07 03 ed 6d |..Z..O.....n...m| +000002b0 df c0 7d ed 05 84 bb ad 0c 1f df 8b 8d 0a ad 33 |..}............3| +000002c0 90 38 44 db 8a 32 9f 9d b3 ae 2e 92 d6 ab d3 25 |.8D..2.........%| +000002d0 12 32 2d 6e a9 17 0d c9 f9 79 25 17 f0 62 1b 91 |.2-n.....y%..b..| +000002e0 ad d5 2d ec 0d ea cd c4 86 77 04 92 ab a8 8d ea |..-......w......| +000002f0 ce fc 13 7b a0 ca 32 96 50 49 99 dd 25 d7 73 93 |...{..2.PI..%.s.| +00000300 f2 00 72 ca 31 07 fd 7e 12 8a 8b 76 51 4e fe 30 |..r.1..~...vQN.0| +00000310 4d 5c 65 17 03 03 00 99 5b 19 25 c3 5a 4d f0 bd |M\e.....[.%.ZM..| +00000320 71 0e 48 63 61 bb 55 6b d3 26 81 25 cf ea 45 e6 |q.Hca.Uk.&.%..E.| +00000330 52 e4 4e c9 5a a8 c2 e2 72 97 51 8a 38 c6 8d 27 |R.N.Z...r.Q.8..'| +00000340 8d df 09 ce 37 87 a6 41 cb c4 bd 6d 19 ef 56 1a |....7..A...m..V.| +00000350 e8 79 df ad 76 9e a6 92 e3 da b3 a6 0d 9f 6f 6f |.y..v.........oo| +00000360 3f 76 0b 62 b4 cf 2c 5b 24 65 bd c1 90 bb 88 ec |?v.b..,[$e......| +00000370 8b 0c 7d 6b 42 38 26 78 62 5c b0 21 74 95 5f fe |..}kB8&xb\.!t._.| +00000380 68 7d 31 8c 5f f5 dc a4 f0 23 6b 75 be 70 ea b3 |h}1._....#ku.p..| +00000390 19 cc 83 9b 8a f6 cb cc 04 2e 66 b5 77 bb 11 68 |..........f.w..h| +000003a0 56 85 0c b1 b8 b1 4e ed ca bd ea 3c 91 38 8a 63 |V.....N....<.8.c| +000003b0 f3 17 03 03 00 35 06 2f 99 10 0c 41 cf 70 d2 aa |.....5./...A.p..| +000003c0 f9 74 e7 3a cb bb 77 1c e6 5c bf f9 3f 02 df af |.t.:..w..\..?...| +000003d0 ba 08 fa f7 42 60 ad de 65 62 2e 54 5f 35 90 4f |....B`..eb.T_5.O| +000003e0 9c b1 34 3d 5d f5 6e 04 d8 5a 50 |..4=].n..ZP| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 7e dc fc 3f 66 |..........5~..?f| +00000010 cb ed 57 e3 5c 83 19 22 31 18 cb eb d5 b8 d2 3c |..W.\.."1......<| +00000020 6c 10 1f be 5c 04 cf 88 6b ec 04 3d aa 0d 15 68 |l...\...k..=...h| +00000030 e4 42 bb c9 86 12 ef f7 90 c4 f5 41 39 56 62 d0 |.B.........A9Vb.| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e ee b9 1c 7b 56 61 76 91 40 90 11 |........{Vav.@..| +00000010 61 4a 0c 46 60 e2 c1 a7 dd 0c a1 0d da 65 98 3e |aJ.F`........e.>| +00000020 30 62 98 17 03 03 00 13 27 7a 29 e5 53 f1 9b 41 |0b......'z).S..A| +00000030 7a 19 ec cd 29 0e 04 57 90 59 7e |z...)..W.Y~| diff --git a/src/crypto/tls/testdata/Server-TLSv13-X25519 b/src/crypto/tls/testdata/Server-TLSv13-X25519 new file mode 100644 index 0000000..0160c5a --- /dev/null +++ b/src/crypto/tls/testdata/Server-TLSv13-X25519 @@ -0,0 +1,98 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 c2 01 00 00 be 03 03 cb 53 78 a8 58 |............Sx.X| +00000010 de 5b 75 c2 c5 b3 ac fa c3 6e 85 a7 e5 a3 a4 ca |.[u......n......| +00000020 1f 82 95 38 fa 79 4c e2 c8 66 8a 20 be 7a 94 d6 |...8.yL..f. .z..| +00000030 f4 82 e2 2f 3b 2c e4 5f ae c2 8b be d1 2f b6 67 |.../;,._...../.g| +00000040 9e 78 7a 51 86 1f c1 d9 8f 43 2f 78 00 04 13 03 |.xzQ.....C/x....| +00000050 00 ff 01 00 00 71 00 0b 00 04 03 00 01 02 00 0a |.....q..........| +00000060 00 04 00 02 00 1d 00 16 00 00 00 17 00 00 00 0d |................| +00000070 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 |................| +00000080 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000090 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| +000000a0 26 00 24 00 1d 00 20 7f 3e a2 2e 2f 88 8a e1 f3 |&.$... .>../....| +000000b0 6a a4 47 d7 6d b7 3c 02 c4 bb f6 de 41 38 50 74 |j.G.m.<.....A8Pt| +000000c0 29 21 f5 fe 9f 0b 6f |)!....o| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 be 7a 94 d6 |........... .z..| +00000030 f4 82 e2 2f 3b 2c e4 5f ae c2 8b be d1 2f b6 67 |.../;,._...../.g| +00000040 9e 78 7a 51 86 1f c1 d9 8f 43 2f 78 13 03 00 00 |.xzQ.....C/x....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 fb 0e 8b 72 0d 35 |.............r.5| +00000090 97 db e2 2e b8 20 be 96 27 6b cd ab 6b 24 5b c4 |..... ..'k..k$[.| +000000a0 e9 17 03 03 02 6d 3a 21 03 ea 45 e9 4e f1 19 1e |.....m:!..E.N...| +000000b0 33 37 04 5b 3e db 54 f0 27 6f c7 96 78 50 01 46 |37.[>.T.'o..xP.F| +000000c0 d1 8b 8f 79 70 21 9d 62 97 b9 bf 6d 14 e5 82 f4 |...yp!.b...m....| +000000d0 ad 89 90 77 12 1f 61 8e 1d 94 d3 27 0f 0e eb 77 |...w..a....'...w| +000000e0 8d b2 2f fb 58 b4 ee 88 19 91 47 d1 3d 10 9e 4a |../.X.....G.=..J| +000000f0 1e 41 b9 c6 41 8f 59 11 7f e0 ac e7 b9 d5 be 40 |.A..A.Y........@| +00000100 cc aa bc ab 56 5a 2b a9 c9 cf df c0 dc 8f d2 9d |....VZ+.........| +00000110 59 a7 88 36 98 2e 87 c6 1d af 26 a1 e8 08 2d bd |Y..6......&...-.| +00000120 9b 5b 1c 4e 22 d2 a1 7c 4d 0b 0f af da 5d fe f7 |.[.N"..|M....]..| +00000130 83 4d f6 54 c1 fe 03 73 6d c9 17 02 6b 78 09 91 |.M.T...sm...kx..| +00000140 aa 61 9a 93 04 66 fa 6b e8 2e d7 18 d2 4d 6e 25 |.a...f.k.....Mn%| +00000150 c3 01 2f a5 0e 1b da a1 64 67 e5 a5 c0 5b ef ec |../.....dg...[..| +00000160 83 5a d3 0e 44 b7 d5 97 9c c7 c4 94 b4 4b 01 e6 |.Z..D........K..| +00000170 48 28 21 cb 04 10 be b0 3b 53 df 15 47 12 67 ea |H(!.....;S..G.g.| +00000180 24 65 a1 ce 0b af 05 5b c9 95 bf 28 2e 55 3c 21 |$e.....[...(.UT.,..?.......| +000002b0 71 6a d6 0f 53 5e ea 92 53 e3 dd 96 be 38 61 74 |qj..S^..S....8at| +000002c0 5d 74 ac c4 8c 72 c6 82 dc f4 22 fb 5c 64 0f 33 |]t...r....".\d.3| +000002d0 b3 31 a1 a9 e0 6d 96 14 0b e1 00 7d 42 44 45 02 |.1...m.....}BDE.| +000002e0 42 63 a1 15 14 73 b6 e4 18 a7 30 9e e0 df a9 ba |Bc...s....0.....| +000002f0 44 72 64 ea 06 a4 a1 46 58 07 b1 a8 48 dc ea 73 |Drd....FX...H..s| +00000300 35 d8 98 de 6c 13 93 bb 7a 64 fb df bf 93 cb 65 |5...l...zd.....e| +00000310 a4 1a 3a 17 03 03 00 99 41 8d 8b b5 97 ae 6a fb |..:.....A.....j.| +00000320 28 ae 10 17 a7 a7 bd a2 a2 54 61 33 ea 5c 3d 82 |(........Ta3.\=.| +00000330 6c 7d fe 3e 3b 6f 92 6b 6a 0a ee fe 85 90 67 59 |l}.>;o.kj.....gY| +00000340 df d9 fc c0 4a 9a 5b ae 57 29 5d fb ff 74 28 f1 |....J.[.W)]..t(.| +00000350 27 f4 ab ee f9 e8 04 cf 2b 62 4d a8 6a 4f ac 85 |'.......+bM.jO..| +00000360 ec a5 18 d7 88 74 9e 3e ea 79 8e 5d df f8 8a 1c |.....t.>.y.]....| +00000370 10 1b 1d d3 4a cf 2a 56 f2 ca 90 1f 37 2c cc b7 |....J.*V....7,..| +00000380 31 91 fb d7 7f bb 07 e2 ec 84 8a 6f 08 a1 7e 2e |1..........o..~.| +00000390 62 8a 5c b9 76 d3 68 e5 d0 b8 73 92 86 80 e5 af |b.\.v.h...s.....| +000003a0 b4 ef 13 ea 3c 09 2a 3f 7e be 16 72 1c 46 a0 29 |....<.*?~..r.F.)| +000003b0 0a 17 03 03 00 35 a7 10 63 c4 a1 7f 26 17 ba b7 |.....5..c...&...| +000003c0 e3 86 6e 52 36 00 8e 68 84 dc 51 8d a6 0c 21 ba |..nR6..h..Q...!.| +000003d0 c3 d9 84 49 ed 57 78 98 68 be 78 a6 d1 f0 67 ac |...I.Wx.h.x...g.| +000003e0 65 9e d2 d8 f3 b9 58 27 24 57 83 17 03 03 00 93 |e.....X'$W......| +000003f0 00 54 de 7f 11 18 1d 12 83 10 77 b2 e9 fd a7 a4 |.T........w.....| +00000400 46 c4 1c 15 0d 24 e0 94 f8 ff 84 19 45 ad 52 c8 |F....$......E.R.| +00000410 85 0b c5 4a a7 6d a1 b0 12 cb 13 58 f6 44 a3 e2 |...J.m.....X.D..| +00000420 b8 7a b5 8c 8f 8a 47 76 ef cb 2d 7b 6e 75 81 39 |.z....Gv..-{nu.9| +00000430 3e 12 e8 b5 c6 2d cb e0 fd ac af 58 5a 01 70 32 |>....-.....XZ.p2| +00000440 0e 12 32 95 10 70 94 28 ec 9b 50 e5 78 c4 b7 75 |..2..p.(..P.x..u| +00000450 97 4a 54 97 bb 30 e6 19 8a 86 87 d7 50 02 8f a8 |.JT..0......P...| +00000460 1b 97 d6 e7 bf 25 66 9a 5a cd 5c 84 33 42 f1 72 |.....%f.Z.\.3B.r| +00000470 d2 44 f1 64 e1 3d 38 b7 7a 32 e3 e8 9a 49 19 90 |.D.d.=8.z2...I..| +00000480 00 2b f6 |.+.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 9d c7 a1 4d 5f |..........5...M_| +00000010 7f 3a 04 b0 cf de 09 d5 84 c1 8f 9b 85 a6 a0 53 |.:.............S| +00000020 c3 aa 19 5e a0 b2 a2 f1 22 f2 51 e0 25 c5 49 57 |...^....".Q.%.IW| +00000030 52 de ad 75 ec e4 e3 36 84 78 22 c8 6c 80 88 8c |R..u...6.x".l...| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 3f 0d f6 84 47 21 4e 37 7b df eb |.....?...G!N7{..| +00000010 eb 38 af a5 ec b9 b6 20 24 f5 1a 1e 25 77 92 82 |.8..... $...%w..| +00000020 97 88 9f 17 03 03 00 13 e2 80 d8 e1 2a bf d5 e3 |............*...| +00000030 bc b7 82 2f 50 2c e5 b9 4b 8c d6 |.../P,..K..| diff --git a/src/crypto/tls/testdata/example-cert.pem b/src/crypto/tls/testdata/example-cert.pem new file mode 100644 index 0000000..e0bf7db --- /dev/null +++ b/src/crypto/tls/testdata/example-cert.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d +7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B +5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr +BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 +NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l +Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc +6MF9+Yw1Yy0t +-----END CERTIFICATE----- diff --git a/src/crypto/tls/testdata/example-key.pem b/src/crypto/tls/testdata/example-key.pem new file mode 100644 index 0000000..104fb09 --- /dev/null +++ b/src/crypto/tls/testdata/example-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 +AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q +EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== +-----END EC PRIVATE KEY----- diff --git a/src/crypto/tls/ticket.go b/src/crypto/tls/ticket.go new file mode 100644 index 0000000..6c1d20d --- /dev/null +++ b/src/crypto/tls/ticket.go @@ -0,0 +1,185 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/hmac" + "crypto/sha256" + "crypto/subtle" + "errors" + "io" + + "golang.org/x/crypto/cryptobyte" +) + +// sessionState contains the information that is serialized into a session +// ticket in order to later resume a connection. +type sessionState struct { + vers uint16 + cipherSuite uint16 + createdAt uint64 + masterSecret []byte // opaque master_secret<1..2^16-1>; + // struct { opaque certificate<1..2^24-1> } Certificate; + certificates [][]byte // Certificate certificate_list<0..2^24-1>; + + // usedOldKey is true if the ticket from which this session came from + // was encrypted with an older key and thus should be refreshed. + usedOldKey bool +} + +func (m *sessionState) marshal() []byte { + var b cryptobyte.Builder + b.AddUint16(m.vers) + b.AddUint16(m.cipherSuite) + addUint64(&b, m.createdAt) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.masterSecret) + }) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + for _, cert := range m.certificates { + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(cert) + }) + } + }) + return b.BytesOrPanic() +} + +func (m *sessionState) unmarshal(data []byte) bool { + *m = sessionState{usedOldKey: m.usedOldKey} + s := cryptobyte.String(data) + if ok := s.ReadUint16(&m.vers) && + s.ReadUint16(&m.cipherSuite) && + readUint64(&s, &m.createdAt) && + readUint16LengthPrefixed(&s, &m.masterSecret) && + len(m.masterSecret) != 0; !ok { + return false + } + var certList cryptobyte.String + if !s.ReadUint24LengthPrefixed(&certList) { + return false + } + for !certList.Empty() { + var cert []byte + if !readUint24LengthPrefixed(&certList, &cert) { + return false + } + m.certificates = append(m.certificates, cert) + } + return s.Empty() +} + +// sessionStateTLS13 is the content of a TLS 1.3 session ticket. Its first +// version (revision = 0) doesn't carry any of the information needed for 0-RTT +// validation and the nonce is always empty. +type sessionStateTLS13 struct { + // uint8 version = 0x0304; + // uint8 revision = 0; + cipherSuite uint16 + createdAt uint64 + resumptionSecret []byte // opaque resumption_master_secret<1..2^8-1>; + certificate Certificate // CertificateEntry certificate_list<0..2^24-1>; +} + +func (m *sessionStateTLS13) marshal() []byte { + var b cryptobyte.Builder + b.AddUint16(VersionTLS13) + b.AddUint8(0) // revision + b.AddUint16(m.cipherSuite) + addUint64(&b, m.createdAt) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(m.resumptionSecret) + }) + marshalCertificate(&b, m.certificate) + return b.BytesOrPanic() +} + +func (m *sessionStateTLS13) unmarshal(data []byte) bool { + *m = sessionStateTLS13{} + s := cryptobyte.String(data) + var version uint16 + var revision uint8 + return s.ReadUint16(&version) && + version == VersionTLS13 && + s.ReadUint8(&revision) && + revision == 0 && + s.ReadUint16(&m.cipherSuite) && + readUint64(&s, &m.createdAt) && + readUint8LengthPrefixed(&s, &m.resumptionSecret) && + len(m.resumptionSecret) != 0 && + unmarshalCertificate(&s, &m.certificate) && + s.Empty() +} + +func (c *Conn) encryptTicket(state []byte) ([]byte, error) { + if len(c.ticketKeys) == 0 { + return nil, errors.New("tls: internal error: session ticket keys unavailable") + } + + encrypted := make([]byte, ticketKeyNameLen+aes.BlockSize+len(state)+sha256.Size) + keyName := encrypted[:ticketKeyNameLen] + iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] + macBytes := encrypted[len(encrypted)-sha256.Size:] + + if _, err := io.ReadFull(c.config.rand(), iv); err != nil { + return nil, err + } + key := c.ticketKeys[0] + copy(keyName, key.keyName[:]) + block, err := aes.NewCipher(key.aesKey[:]) + if err != nil { + return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error()) + } + cipher.NewCTR(block, iv).XORKeyStream(encrypted[ticketKeyNameLen+aes.BlockSize:], state) + + mac := hmac.New(sha256.New, key.hmacKey[:]) + mac.Write(encrypted[:len(encrypted)-sha256.Size]) + mac.Sum(macBytes[:0]) + + return encrypted, nil +} + +func (c *Conn) decryptTicket(encrypted []byte) (plaintext []byte, usedOldKey bool) { + if len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size { + return nil, false + } + + keyName := encrypted[:ticketKeyNameLen] + iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] + macBytes := encrypted[len(encrypted)-sha256.Size:] + ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size] + + keyIndex := -1 + for i, candidateKey := range c.ticketKeys { + if bytes.Equal(keyName, candidateKey.keyName[:]) { + keyIndex = i + break + } + } + if keyIndex == -1 { + return nil, false + } + key := &c.ticketKeys[keyIndex] + + mac := hmac.New(sha256.New, key.hmacKey[:]) + mac.Write(encrypted[:len(encrypted)-sha256.Size]) + expected := mac.Sum(nil) + + if subtle.ConstantTimeCompare(macBytes, expected) != 1 { + return nil, false + } + + block, err := aes.NewCipher(key.aesKey[:]) + if err != nil { + return nil, false + } + plaintext = make([]byte, len(ciphertext)) + cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) + + return plaintext, keyIndex > 0 +} diff --git a/src/crypto/tls/tls.go b/src/crypto/tls/tls.go new file mode 100644 index 0000000..b529c70 --- /dev/null +++ b/src/crypto/tls/tls.go @@ -0,0 +1,356 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tls partially implements TLS 1.2, as specified in RFC 5246, +// and TLS 1.3, as specified in RFC 8446. +package tls + +// BUG(agl): The crypto/tls package only implements some countermeasures +// against Lucky13 attacks on CBC-mode encryption, and only on SHA1 +// variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and +// https://www.imperialviolet.org/2013/02/04/luckythirteen.html. + +import ( + "bytes" + "context" + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "net" + "os" + "strings" +) + +// Server returns a new TLS server side connection +// using conn as the underlying transport. +// The configuration config must be non-nil and must include +// at least one certificate or else set GetCertificate. +func Server(conn net.Conn, config *Config) *Conn { + c := &Conn{ + conn: conn, + config: config, + } + c.handshakeFn = c.serverHandshake + return c +} + +// Client returns a new TLS client side connection +// using conn as the underlying transport. +// The config cannot be nil: users must set either ServerName or +// InsecureSkipVerify in the config. +func Client(conn net.Conn, config *Config) *Conn { + c := &Conn{ + conn: conn, + config: config, + isClient: true, + } + c.handshakeFn = c.clientHandshake + return c +} + +// A listener implements a network listener (net.Listener) for TLS connections. +type listener struct { + net.Listener + config *Config +} + +// Accept waits for and returns the next incoming TLS connection. +// The returned connection is of type *Conn. +func (l *listener) Accept() (net.Conn, error) { + c, err := l.Listener.Accept() + if err != nil { + return nil, err + } + return Server(c, l.config), nil +} + +// NewListener creates a Listener which accepts connections from an inner +// Listener and wraps each connection with Server. +// The configuration config must be non-nil and must include +// at least one certificate or else set GetCertificate. +func NewListener(inner net.Listener, config *Config) net.Listener { + l := new(listener) + l.Listener = inner + l.config = config + return l +} + +// Listen creates a TLS listener accepting connections on the +// given network address using net.Listen. +// The configuration config must be non-nil and must include +// at least one certificate or else set GetCertificate. +func Listen(network, laddr string, config *Config) (net.Listener, error) { + if config == nil || len(config.Certificates) == 0 && + config.GetCertificate == nil && config.GetConfigForClient == nil { + return nil, errors.New("tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config") + } + l, err := net.Listen(network, laddr) + if err != nil { + return nil, err + } + return NewListener(l, config), nil +} + +type timeoutError struct{} + +func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } +func (timeoutError) Timeout() bool { return true } +func (timeoutError) Temporary() bool { return true } + +// DialWithDialer connects to the given network address using dialer.Dial and +// then initiates a TLS handshake, returning the resulting TLS connection. Any +// timeout or deadline given in the dialer apply to connection and TLS +// handshake as a whole. +// +// DialWithDialer interprets a nil configuration as equivalent to the zero +// configuration; see the documentation of Config for the defaults. +// +// DialWithDialer uses context.Background internally; to specify the context, +// use Dialer.DialContext with NetDialer set to the desired dialer. +func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { + return dial(context.Background(), dialer, network, addr, config) +} + +func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { + if netDialer.Timeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout) + defer cancel() + } + + if !netDialer.Deadline.IsZero() { + var cancel context.CancelFunc + ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline) + defer cancel() + } + + rawConn, err := netDialer.DialContext(ctx, network, addr) + if err != nil { + return nil, err + } + + colonPos := strings.LastIndex(addr, ":") + if colonPos == -1 { + colonPos = len(addr) + } + hostname := addr[:colonPos] + + if config == nil { + config = defaultConfig() + } + // If no ServerName is set, infer the ServerName + // from the hostname we're connecting to. + if config.ServerName == "" { + // Make a copy to avoid polluting argument or default. + c := config.Clone() + c.ServerName = hostname + config = c + } + + conn := Client(rawConn, config) + if err := conn.HandshakeContext(ctx); err != nil { + rawConn.Close() + return nil, err + } + return conn, nil +} + +// Dial connects to the given network address using net.Dial +// and then initiates a TLS handshake, returning the resulting +// TLS connection. +// Dial interprets a nil configuration as equivalent to +// the zero configuration; see the documentation of Config +// for the defaults. +func Dial(network, addr string, config *Config) (*Conn, error) { + return DialWithDialer(new(net.Dialer), network, addr, config) +} + +// Dialer dials TLS connections given a configuration and a Dialer for the +// underlying connection. +type Dialer struct { + // NetDialer is the optional dialer to use for the TLS connections' + // underlying TCP connections. + // A nil NetDialer is equivalent to the net.Dialer zero value. + NetDialer *net.Dialer + + // Config is the TLS configuration to use for new connections. + // A nil configuration is equivalent to the zero + // configuration; see the documentation of Config for the + // defaults. + Config *Config +} + +// Dial connects to the given network address and initiates a TLS +// handshake, returning the resulting TLS connection. +// +// The returned Conn, if any, will always be of type *Conn. +// +// Dial uses context.Background internally; to specify the context, +// use DialContext. +func (d *Dialer) Dial(network, addr string) (net.Conn, error) { + return d.DialContext(context.Background(), network, addr) +} + +func (d *Dialer) netDialer() *net.Dialer { + if d.NetDialer != nil { + return d.NetDialer + } + return new(net.Dialer) +} + +// DialContext connects to the given network address and initiates a TLS +// handshake, returning the resulting TLS connection. +// +// The provided Context must be non-nil. If the context expires before +// the connection is complete, an error is returned. Once successfully +// connected, any expiration of the context will not affect the +// connection. +// +// The returned Conn, if any, will always be of type *Conn. +func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { + c, err := dial(ctx, d.netDialer(), network, addr, d.Config) + if err != nil { + // Don't return c (a typed nil) in an interface. + return nil, err + } + return c, nil +} + +// LoadX509KeyPair reads and parses a public/private key pair from a pair +// of files. The files must contain PEM encoded data. The certificate file +// may contain intermediate certificates following the leaf certificate to +// form a certificate chain. On successful return, Certificate.Leaf will +// be nil because the parsed form of the certificate is not retained. +func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) { + certPEMBlock, err := os.ReadFile(certFile) + if err != nil { + return Certificate{}, err + } + keyPEMBlock, err := os.ReadFile(keyFile) + if err != nil { + return Certificate{}, err + } + return X509KeyPair(certPEMBlock, keyPEMBlock) +} + +// X509KeyPair parses a public/private key pair from a pair of +// PEM encoded data. On successful return, Certificate.Leaf will be nil because +// the parsed form of the certificate is not retained. +func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { + fail := func(err error) (Certificate, error) { return Certificate{}, err } + + var cert Certificate + var skippedBlockTypes []string + for { + var certDERBlock *pem.Block + certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) + if certDERBlock == nil { + break + } + if certDERBlock.Type == "CERTIFICATE" { + cert.Certificate = append(cert.Certificate, certDERBlock.Bytes) + } else { + skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type) + } + } + + if len(cert.Certificate) == 0 { + if len(skippedBlockTypes) == 0 { + return fail(errors.New("tls: failed to find any PEM data in certificate input")) + } + if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") { + return fail(errors.New("tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched")) + } + return fail(fmt.Errorf("tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) + } + + skippedBlockTypes = skippedBlockTypes[:0] + var keyDERBlock *pem.Block + for { + keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) + if keyDERBlock == nil { + if len(skippedBlockTypes) == 0 { + return fail(errors.New("tls: failed to find any PEM data in key input")) + } + if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" { + return fail(errors.New("tls: found a certificate rather than a key in the PEM for the private key")) + } + return fail(fmt.Errorf("tls: failed to find PEM block with type ending in \"PRIVATE KEY\" in key input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) + } + if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { + break + } + skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type) + } + + // We don't need to parse the public key for TLS, but we so do anyway + // to check that it looks sane and matches the private key. + x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + return fail(err) + } + + cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes) + if err != nil { + return fail(err) + } + + switch pub := x509Cert.PublicKey.(type) { + case *rsa.PublicKey: + priv, ok := cert.PrivateKey.(*rsa.PrivateKey) + if !ok { + return fail(errors.New("tls: private key type does not match public key type")) + } + if pub.N.Cmp(priv.N) != 0 { + return fail(errors.New("tls: private key does not match public key")) + } + case *ecdsa.PublicKey: + priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey) + if !ok { + return fail(errors.New("tls: private key type does not match public key type")) + } + if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { + return fail(errors.New("tls: private key does not match public key")) + } + case ed25519.PublicKey: + priv, ok := cert.PrivateKey.(ed25519.PrivateKey) + if !ok { + return fail(errors.New("tls: private key type does not match public key type")) + } + if !bytes.Equal(priv.Public().(ed25519.PublicKey), pub) { + return fail(errors.New("tls: private key does not match public key")) + } + default: + return fail(errors.New("tls: unknown public key algorithm")) + } + + return cert, nil +} + +// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates +// PKCS #1 private keys by default, while OpenSSL 1.0.0 generates PKCS #8 keys. +// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. +func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { + if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { + return key, nil + } + if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { + switch key := key.(type) { + case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey: + return key, nil + default: + return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping") + } + } + if key, err := x509.ParseECPrivateKey(der); err == nil { + return key, nil + } + + return nil, errors.New("tls: failed to parse private key") +} diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go new file mode 100644 index 0000000..d8a43ad --- /dev/null +++ b/src/crypto/tls/tls_test.go @@ -0,0 +1,1611 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "context" + "crypto" + "crypto/x509" + "encoding/json" + "errors" + "fmt" + "internal/testenv" + "io" + "math" + "net" + "os" + "reflect" + "sort" + "strings" + "testing" + "time" +) + +var rsaCertPEM = `-----BEGIN CERTIFICATE----- +MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ +hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa +rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv +zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW +r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V +-----END CERTIFICATE----- +` + +var rsaKeyPEM = testingKey(`-----BEGIN RSA TESTING KEY----- +MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo +k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G +6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N +MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW +SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T +xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi +D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g== +-----END RSA TESTING KEY----- +`) + +// keyPEM is the same as rsaKeyPEM, but declares itself as just +// "PRIVATE KEY", not "RSA PRIVATE KEY". https://golang.org/issue/4477 +var keyPEM = testingKey(`-----BEGIN TESTING KEY----- +MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo +k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G +6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N +MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW +SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T +xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi +D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g== +-----END TESTING KEY----- +`) + +var ecdsaCertPEM = `-----BEGIN CERTIFICATE----- +MIIB/jCCAWICCQDscdUxw16XFDAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw +EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0 +eSBMdGQwHhcNMTIxMTE0MTI0MDQ4WhcNMTUxMTE0MTI0MDQ4WjBFMQswCQYDVQQG +EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk +Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBY9+my9OoeSUR +lDQdV/x8LsOuLilthhiS1Tz4aGDHIPwC1mlvnf7fg5lecYpMCrLLhauAc1UJXcgl +01xoLuzgtAEAgv2P/jgytzRSpUYvgLBt1UA0leLYBy6mQQbrNEuqT3INapKIcUv8 +XxYP0xMEUksLPq6Ca+CRSqTtrd/23uTnapkwCQYHKoZIzj0EAQOBigAwgYYCQXJo +A7Sl2nLVf+4Iu/tAX/IF4MavARKC4PPHK3zfuGfPR3oCCcsAoz3kAzOeijvd0iXb +H5jBImIxPL4WxQNiBTexAkF8D1EtpYuWdlVQ80/h/f4pBcGiXPqX5h2PQSQY7hP1 ++jwM1FGS4fREIOvlBYr/SzzQRtwrvrzGYxDEDbsC0ZGRnA== +-----END CERTIFICATE----- +` + +var ecdsaKeyPEM = testingKey(`-----BEGIN EC PARAMETERS----- +BgUrgQQAIw== +-----END EC PARAMETERS----- +-----BEGIN EC TESTING KEY----- +MIHcAgEBBEIBrsoKp0oqcv6/JovJJDoDVSGWdirrkgCWxrprGlzB9o0X8fV675X0 +NwuBenXFfeZvVcwluO7/Q9wkYoPd/t3jGImgBwYFK4EEACOhgYkDgYYABAFj36bL +06h5JRGUNB1X/Hwuw64uKW2GGJLVPPhoYMcg/ALWaW+d/t+DmV5xikwKssuFq4Bz +VQldyCXTXGgu7OC0AQCC/Y/+ODK3NFKlRi+AsG3VQDSV4tgHLqZBBus0S6pPcg1q +kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ== +-----END EC TESTING KEY----- +`) + +var keyPairTests = []struct { + algo string + cert string + key string +}{ + {"ECDSA", ecdsaCertPEM, ecdsaKeyPEM}, + {"RSA", rsaCertPEM, rsaKeyPEM}, + {"RSA-untyped", rsaCertPEM, keyPEM}, // golang.org/issue/4477 +} + +func TestX509KeyPair(t *testing.T) { + t.Parallel() + var pem []byte + for _, test := range keyPairTests { + pem = []byte(test.cert + test.key) + if _, err := X509KeyPair(pem, pem); err != nil { + t.Errorf("Failed to load %s cert followed by %s key: %s", test.algo, test.algo, err) + } + pem = []byte(test.key + test.cert) + if _, err := X509KeyPair(pem, pem); err != nil { + t.Errorf("Failed to load %s key followed by %s cert: %s", test.algo, test.algo, err) + } + } +} + +func TestX509KeyPairErrors(t *testing.T) { + _, err := X509KeyPair([]byte(rsaKeyPEM), []byte(rsaCertPEM)) + if err == nil { + t.Fatalf("X509KeyPair didn't return an error when arguments were switched") + } + if subStr := "been switched"; !strings.Contains(err.Error(), subStr) { + t.Fatalf("Expected %q in the error when switching arguments to X509KeyPair, but the error was %q", subStr, err) + } + + _, err = X509KeyPair([]byte(rsaCertPEM), []byte(rsaCertPEM)) + if err == nil { + t.Fatalf("X509KeyPair didn't return an error when both arguments were certificates") + } + if subStr := "certificate"; !strings.Contains(err.Error(), subStr) { + t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were certificates, but the error was %q", subStr, err) + } + + const nonsensePEM = ` +-----BEGIN NONSENSE----- +Zm9vZm9vZm9v +-----END NONSENSE----- +` + + _, err = X509KeyPair([]byte(nonsensePEM), []byte(nonsensePEM)) + if err == nil { + t.Fatalf("X509KeyPair didn't return an error when both arguments were nonsense") + } + if subStr := "NONSENSE"; !strings.Contains(err.Error(), subStr) { + t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were nonsense, but the error was %q", subStr, err) + } +} + +func TestX509MixedKeyPair(t *testing.T) { + if _, err := X509KeyPair([]byte(rsaCertPEM), []byte(ecdsaKeyPEM)); err == nil { + t.Error("Load of RSA certificate succeeded with ECDSA private key") + } + if _, err := X509KeyPair([]byte(ecdsaCertPEM), []byte(rsaKeyPEM)); err == nil { + t.Error("Load of ECDSA certificate succeeded with RSA private key") + } +} + +func newLocalListener(t testing.TB) net.Listener { + ln, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + ln, err = net.Listen("tcp6", "[::1]:0") + } + if err != nil { + t.Fatal(err) + } + return ln +} + +func TestDialTimeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + listener := newLocalListener(t) + + addr := listener.Addr().String() + defer listener.Close() + + complete := make(chan bool) + defer close(complete) + + go func() { + conn, err := listener.Accept() + if err != nil { + t.Error(err) + return + } + <-complete + conn.Close() + }() + + dialer := &net.Dialer{ + Timeout: 10 * time.Millisecond, + } + + var err error + if _, err = DialWithDialer(dialer, "tcp", addr, nil); err == nil { + t.Fatal("DialWithTimeout completed successfully") + } + + if !isTimeoutError(err) { + t.Errorf("resulting error not a timeout: %v\nType %T: %#v", err, err, err) + } +} + +func TestDeadlineOnWrite(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + + ln := newLocalListener(t) + defer ln.Close() + + srvCh := make(chan *Conn, 1) + + go func() { + sconn, err := ln.Accept() + if err != nil { + srvCh <- nil + return + } + srv := Server(sconn, testConfig.Clone()) + if err := srv.Handshake(); err != nil { + srvCh <- nil + return + } + srvCh <- srv + }() + + clientConfig := testConfig.Clone() + clientConfig.MaxVersion = VersionTLS12 + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + srv := <-srvCh + if srv == nil { + t.Error(err) + } + + // Make sure the client/server is setup correctly and is able to do a typical Write/Read + buf := make([]byte, 6) + if _, err := srv.Write([]byte("foobar")); err != nil { + t.Errorf("Write err: %v", err) + } + if n, err := conn.Read(buf); n != 6 || err != nil || string(buf) != "foobar" { + t.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf) + } + + // Set a deadline which should cause Write to timeout + if err = srv.SetDeadline(time.Now()); err != nil { + t.Fatalf("SetDeadline(time.Now()) err: %v", err) + } + if _, err = srv.Write([]byte("should fail")); err == nil { + t.Fatal("Write should have timed out") + } + + // Clear deadline and make sure it still times out + if err = srv.SetDeadline(time.Time{}); err != nil { + t.Fatalf("SetDeadline(time.Time{}) err: %v", err) + } + if _, err = srv.Write([]byte("This connection is permanently broken")); err == nil { + t.Fatal("Write which previously failed should still time out") + } + + // Verify the error + if ne := err.(net.Error); ne.Temporary() != false { + t.Error("Write timed out but incorrectly classified the error as Temporary") + } + if !isTimeoutError(err) { + t.Error("Write timed out but did not classify the error as a Timeout") + } +} + +type readerFunc func([]byte) (int, error) + +func (f readerFunc) Read(b []byte) (int, error) { return f(b) } + +// TestDialer tests that tls.Dialer.DialContext can abort in the middle of a handshake. +// (The other cases are all handled by the existing dial tests in this package, which +// all also flow through the same code shared code paths) +func TestDialer(t *testing.T) { + ln := newLocalListener(t) + defer ln.Close() + + unblockServer := make(chan struct{}) // close-only + defer close(unblockServer) + go func() { + conn, err := ln.Accept() + if err != nil { + return + } + defer conn.Close() + <-unblockServer + }() + + ctx, cancel := context.WithCancel(context.Background()) + d := Dialer{Config: &Config{ + Rand: readerFunc(func(b []byte) (n int, err error) { + // By the time crypto/tls wants randomness, that means it has a TCP + // connection, so we're past the Dialer's dial and now blocked + // in a handshake. Cancel our context and see if we get unstuck. + // (Our TCP listener above never reads or writes, so the Handshake + // would otherwise be stuck forever) + cancel() + return len(b), nil + }), + ServerName: "foo", + }} + _, err := d.DialContext(ctx, "tcp", ln.Addr().String()) + if err != context.Canceled { + t.Errorf("err = %v; want context.Canceled", err) + } +} + +func isTimeoutError(err error) bool { + if ne, ok := err.(net.Error); ok { + return ne.Timeout() + } + return false +} + +// tests that Conn.Read returns (non-zero, io.EOF) instead of +// (non-zero, nil) when a Close (alertCloseNotify) is sitting right +// behind the application data in the buffer. +func TestConnReadNonzeroAndEOF(t *testing.T) { + // This test is racy: it assumes that after a write to a + // localhost TCP connection, the peer TCP connection can + // immediately read it. Because it's racy, we skip this test + // in short mode, and then retry it several times with an + // increasing sleep in between our final write (via srv.Close + // below) and the following read. + if testing.Short() { + t.Skip("skipping in short mode") + } + var err error + for delay := time.Millisecond; delay <= 64*time.Millisecond; delay *= 2 { + if err = testConnReadNonzeroAndEOF(t, delay); err == nil { + return + } + } + t.Error(err) +} + +func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error { + ln := newLocalListener(t) + defer ln.Close() + + srvCh := make(chan *Conn, 1) + var serr error + go func() { + sconn, err := ln.Accept() + if err != nil { + serr = err + srvCh <- nil + return + } + serverConfig := testConfig.Clone() + srv := Server(sconn, serverConfig) + if err := srv.Handshake(); err != nil { + serr = fmt.Errorf("handshake: %v", err) + srvCh <- nil + return + } + srvCh <- srv + }() + + clientConfig := testConfig.Clone() + // In TLS 1.3, alerts are encrypted and disguised as application data, so + // the opportunistic peek won't work. + clientConfig.MaxVersion = VersionTLS12 + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + srv := <-srvCh + if srv == nil { + return serr + } + + buf := make([]byte, 6) + + srv.Write([]byte("foobar")) + n, err := conn.Read(buf) + if n != 6 || err != nil || string(buf) != "foobar" { + return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf) + } + + srv.Write([]byte("abcdef")) + srv.Close() + time.Sleep(delay) + n, err = conn.Read(buf) + if n != 6 || string(buf) != "abcdef" { + return fmt.Errorf("Read = %d, buf= %q; want 6, abcdef", n, buf) + } + if err != io.EOF { + return fmt.Errorf("Second Read error = %v; want io.EOF", err) + } + return nil +} + +func TestTLSUniqueMatches(t *testing.T) { + ln := newLocalListener(t) + defer ln.Close() + + serverTLSUniques := make(chan []byte) + parentDone := make(chan struct{}) + childDone := make(chan struct{}) + defer close(parentDone) + go func() { + defer close(childDone) + for i := 0; i < 2; i++ { + sconn, err := ln.Accept() + if err != nil { + t.Error(err) + return + } + serverConfig := testConfig.Clone() + serverConfig.MaxVersion = VersionTLS12 // TLSUnique is not defined in TLS 1.3 + srv := Server(sconn, serverConfig) + if err := srv.Handshake(); err != nil { + t.Error(err) + return + } + select { + case <-parentDone: + return + case serverTLSUniques <- srv.ConnectionState().TLSUnique: + } + } + }() + + clientConfig := testConfig.Clone() + clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + t.Fatal(err) + } + + var serverTLSUniquesValue []byte + select { + case <-childDone: + return + case serverTLSUniquesValue = <-serverTLSUniques: + } + + if !bytes.Equal(conn.ConnectionState().TLSUnique, serverTLSUniquesValue) { + t.Error("client and server channel bindings differ") + } + conn.Close() + + conn, err = Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + if !conn.ConnectionState().DidResume { + t.Error("second session did not use resumption") + } + + select { + case <-childDone: + return + case serverTLSUniquesValue = <-serverTLSUniques: + } + + if !bytes.Equal(conn.ConnectionState().TLSUnique, serverTLSUniquesValue) { + t.Error("client and server channel bindings differ when session resumption is used") + } +} + +func TestVerifyHostname(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + c, err := Dial("tcp", "www.google.com:https", nil) + if err != nil { + t.Fatal(err) + } + if err := c.VerifyHostname("www.google.com"); err != nil { + t.Fatalf("verify www.google.com: %v", err) + } + if err := c.VerifyHostname("www.yahoo.com"); err == nil { + t.Fatalf("verify www.yahoo.com succeeded") + } + + c, err = Dial("tcp", "www.google.com:https", &Config{InsecureSkipVerify: true}) + if err != nil { + t.Fatal(err) + } + if err := c.VerifyHostname("www.google.com"); err == nil { + t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true") + } +} + +func TestConnCloseBreakingWrite(t *testing.T) { + ln := newLocalListener(t) + defer ln.Close() + + srvCh := make(chan *Conn, 1) + var serr error + var sconn net.Conn + go func() { + var err error + sconn, err = ln.Accept() + if err != nil { + serr = err + srvCh <- nil + return + } + serverConfig := testConfig.Clone() + srv := Server(sconn, serverConfig) + if err := srv.Handshake(); err != nil { + serr = fmt.Errorf("handshake: %v", err) + srvCh <- nil + return + } + srvCh <- srv + }() + + cconn, err := net.Dial("tcp", ln.Addr().String()) + if err != nil { + t.Fatal(err) + } + defer cconn.Close() + + conn := &changeImplConn{ + Conn: cconn, + } + + clientConfig := testConfig.Clone() + tconn := Client(conn, clientConfig) + if err := tconn.Handshake(); err != nil { + t.Fatal(err) + } + + srv := <-srvCh + if srv == nil { + t.Fatal(serr) + } + defer sconn.Close() + + connClosed := make(chan struct{}) + conn.closeFunc = func() error { + close(connClosed) + return nil + } + + inWrite := make(chan bool, 1) + var errConnClosed = errors.New("conn closed for test") + conn.writeFunc = func(p []byte) (n int, err error) { + inWrite <- true + <-connClosed + return 0, errConnClosed + } + + closeReturned := make(chan bool, 1) + go func() { + <-inWrite + tconn.Close() // test that this doesn't block forever. + closeReturned <- true + }() + + _, err = tconn.Write([]byte("foo")) + if err != errConnClosed { + t.Errorf("Write error = %v; want errConnClosed", err) + } + + <-closeReturned + if err := tconn.Close(); err != net.ErrClosed { + t.Errorf("Close error = %v; want net.ErrClosed", err) + } +} + +func TestConnCloseWrite(t *testing.T) { + ln := newLocalListener(t) + defer ln.Close() + + clientDoneChan := make(chan struct{}) + + serverCloseWrite := func() error { + sconn, err := ln.Accept() + if err != nil { + return fmt.Errorf("accept: %v", err) + } + defer sconn.Close() + + serverConfig := testConfig.Clone() + srv := Server(sconn, serverConfig) + if err := srv.Handshake(); err != nil { + return fmt.Errorf("handshake: %v", err) + } + defer srv.Close() + + data, err := io.ReadAll(srv) + if err != nil { + return err + } + if len(data) > 0 { + return fmt.Errorf("Read data = %q; want nothing", data) + } + + if err := srv.CloseWrite(); err != nil { + return fmt.Errorf("server CloseWrite: %v", err) + } + + // Wait for clientCloseWrite to finish, so we know we + // tested the CloseWrite before we defer the + // sconn.Close above, which would also cause the + // client to unblock like CloseWrite. + <-clientDoneChan + return nil + } + + clientCloseWrite := func() error { + defer close(clientDoneChan) + + clientConfig := testConfig.Clone() + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + return err + } + if err := conn.Handshake(); err != nil { + return err + } + defer conn.Close() + + if err := conn.CloseWrite(); err != nil { + return fmt.Errorf("client CloseWrite: %v", err) + } + + if _, err := conn.Write([]byte{0}); err != errShutdown { + return fmt.Errorf("CloseWrite error = %v; want errShutdown", err) + } + + data, err := io.ReadAll(conn) + if err != nil { + return err + } + if len(data) > 0 { + return fmt.Errorf("Read data = %q; want nothing", data) + } + return nil + } + + errChan := make(chan error, 2) + + go func() { errChan <- serverCloseWrite() }() + go func() { errChan <- clientCloseWrite() }() + + for i := 0; i < 2; i++ { + select { + case err := <-errChan: + if err != nil { + t.Fatal(err) + } + case <-time.After(10 * time.Second): + t.Fatal("deadlock") + } + } + + // Also test CloseWrite being called before the handshake is + // finished: + { + ln2 := newLocalListener(t) + defer ln2.Close() + + netConn, err := net.Dial("tcp", ln2.Addr().String()) + if err != nil { + t.Fatal(err) + } + defer netConn.Close() + conn := Client(netConn, testConfig.Clone()) + + if err := conn.CloseWrite(); err != errEarlyCloseWrite { + t.Errorf("CloseWrite error = %v; want errEarlyCloseWrite", err) + } + } +} + +func TestWarningAlertFlood(t *testing.T) { + ln := newLocalListener(t) + defer ln.Close() + + server := func() error { + sconn, err := ln.Accept() + if err != nil { + return fmt.Errorf("accept: %v", err) + } + defer sconn.Close() + + serverConfig := testConfig.Clone() + srv := Server(sconn, serverConfig) + if err := srv.Handshake(); err != nil { + return fmt.Errorf("handshake: %v", err) + } + defer srv.Close() + + _, err = io.ReadAll(srv) + if err == nil { + return errors.New("unexpected lack of error from server") + } + const expected = "too many ignored" + if str := err.Error(); !strings.Contains(str, expected) { + return fmt.Errorf("expected error containing %q, but saw: %s", expected, str) + } + + return nil + } + + errChan := make(chan error, 1) + go func() { errChan <- server() }() + + clientConfig := testConfig.Clone() + clientConfig.MaxVersion = VersionTLS12 // there are no warning alerts in TLS 1.3 + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + if err := conn.Handshake(); err != nil { + t.Fatal(err) + } + + for i := 0; i < maxUselessRecords+1; i++ { + conn.sendAlert(alertNoRenegotiation) + } + + if err := <-errChan; err != nil { + t.Fatal(err) + } +} + +func TestCloneFuncFields(t *testing.T) { + const expectedCount = 6 + called := 0 + + c1 := Config{ + Time: func() time.Time { + called |= 1 << 0 + return time.Time{} + }, + GetCertificate: func(*ClientHelloInfo) (*Certificate, error) { + called |= 1 << 1 + return nil, nil + }, + GetClientCertificate: func(*CertificateRequestInfo) (*Certificate, error) { + called |= 1 << 2 + return nil, nil + }, + GetConfigForClient: func(*ClientHelloInfo) (*Config, error) { + called |= 1 << 3 + return nil, nil + }, + VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + called |= 1 << 4 + return nil + }, + VerifyConnection: func(ConnectionState) error { + called |= 1 << 5 + return nil + }, + } + + c2 := c1.Clone() + + c2.Time() + c2.GetCertificate(nil) + c2.GetClientCertificate(nil) + c2.GetConfigForClient(nil) + c2.VerifyPeerCertificate(nil, nil) + c2.VerifyConnection(ConnectionState{}) + + if called != (1< len(p) { + allowed = len(p) + } + if wrote < allowed { + n, err := c.Conn.Write(p[wrote:allowed]) + wrote += n + if err != nil { + return wrote, err + } + } + } + return len(p), nil +} + +func latency(b *testing.B, version uint16, bps int, dynamicRecordSizingDisabled bool) { + ln := newLocalListener(b) + defer ln.Close() + + N := b.N + + go func() { + for i := 0; i < N; i++ { + sconn, err := ln.Accept() + if err != nil { + // panic rather than synchronize to avoid benchmark overhead + // (cannot call b.Fatal in goroutine) + panic(fmt.Errorf("accept: %v", err)) + } + serverConfig := testConfig.Clone() + serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled + srv := Server(&slowConn{sconn, bps}, serverConfig) + if err := srv.Handshake(); err != nil { + panic(fmt.Errorf("handshake: %v", err)) + } + io.Copy(srv, srv) + } + }() + + clientConfig := testConfig.Clone() + clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled + clientConfig.MaxVersion = version + + buf := make([]byte, 16384) + peek := make([]byte, 1) + + for i := 0; i < N; i++ { + conn, err := Dial("tcp", ln.Addr().String(), clientConfig) + if err != nil { + b.Fatal(err) + } + // make sure we're connected and previous connection has stopped + if _, err := conn.Write(buf[:1]); err != nil { + b.Fatal(err) + } + if _, err := io.ReadFull(conn, peek); err != nil { + b.Fatal(err) + } + if _, err := conn.Write(buf); err != nil { + b.Fatal(err) + } + if _, err = io.ReadFull(conn, peek); err != nil { + b.Fatal(err) + } + conn.Close() + } +} + +func BenchmarkLatency(b *testing.B) { + for _, mode := range []string{"Max", "Dynamic"} { + for _, kbps := range []int{200, 500, 1000, 2000, 5000} { + name := fmt.Sprintf("%sPacket/%dkbps", mode, kbps) + b.Run(name, func(b *testing.B) { + b.Run("TLSv12", func(b *testing.B) { + latency(b, VersionTLS12, kbps*1000, mode == "Max") + }) + b.Run("TLSv13", func(b *testing.B) { + latency(b, VersionTLS13, kbps*1000, mode == "Max") + }) + }) + } + } +} + +func TestConnectionStateMarshal(t *testing.T) { + cs := &ConnectionState{} + _, err := json.Marshal(cs) + if err != nil { + t.Errorf("json.Marshal failed on ConnectionState: %v", err) + } +} + +func TestConnectionState(t *testing.T) { + issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + if err != nil { + panic(err) + } + rootCAs := x509.NewCertPool() + rootCAs.AddCert(issuer) + + now := func() time.Time { return time.Unix(1476984729, 0) } + + const alpnProtocol = "golang" + const serverName = "example.golang" + var scts = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} + var ocsp = []byte("dummy ocsp") + + for _, v := range []uint16{VersionTLS12, VersionTLS13} { + var name string + switch v { + case VersionTLS12: + name = "TLSv12" + case VersionTLS13: + name = "TLSv13" + } + t.Run(name, func(t *testing.T) { + config := &Config{ + Time: now, + Rand: zeroSource{}, + Certificates: make([]Certificate, 1), + MaxVersion: v, + RootCAs: rootCAs, + ClientCAs: rootCAs, + ClientAuth: RequireAndVerifyClientCert, + NextProtos: []string{alpnProtocol}, + ServerName: serverName, + } + config.Certificates[0].Certificate = [][]byte{testRSACertificate} + config.Certificates[0].PrivateKey = testRSAPrivateKey + config.Certificates[0].SignedCertificateTimestamps = scts + config.Certificates[0].OCSPStaple = ocsp + + ss, cs, err := testHandshake(t, config, config) + if err != nil { + t.Fatalf("Handshake failed: %v", err) + } + + if ss.Version != v || cs.Version != v { + t.Errorf("Got versions %x (server) and %x (client), expected %x", ss.Version, cs.Version, v) + } + + if !ss.HandshakeComplete || !cs.HandshakeComplete { + t.Errorf("Got HandshakeComplete %v (server) and %v (client), expected true", ss.HandshakeComplete, cs.HandshakeComplete) + } + + if ss.DidResume || cs.DidResume { + t.Errorf("Got DidResume %v (server) and %v (client), expected false", ss.DidResume, cs.DidResume) + } + + if ss.CipherSuite == 0 || cs.CipherSuite == 0 { + t.Errorf("Got invalid cipher suite: %v (server) and %v (client)", ss.CipherSuite, cs.CipherSuite) + } + + if ss.NegotiatedProtocol != alpnProtocol || cs.NegotiatedProtocol != alpnProtocol { + t.Errorf("Got negotiated protocol %q (server) and %q (client), expected %q", ss.NegotiatedProtocol, cs.NegotiatedProtocol, alpnProtocol) + } + + if !cs.NegotiatedProtocolIsMutual { + t.Errorf("Got false NegotiatedProtocolIsMutual on the client side") + } + // NegotiatedProtocolIsMutual on the server side is unspecified. + + if ss.ServerName != serverName { + t.Errorf("Got server name %q, expected %q", ss.ServerName, serverName) + } + if cs.ServerName != serverName { + t.Errorf("Got server name on client connection %q, expected %q", cs.ServerName, serverName) + } + + if len(ss.PeerCertificates) != 1 || len(cs.PeerCertificates) != 1 { + t.Errorf("Got %d (server) and %d (client) peer certificates, expected %d", len(ss.PeerCertificates), len(cs.PeerCertificates), 1) + } + + if len(ss.VerifiedChains) != 1 || len(cs.VerifiedChains) != 1 { + t.Errorf("Got %d (server) and %d (client) verified chains, expected %d", len(ss.VerifiedChains), len(cs.VerifiedChains), 1) + } else if len(ss.VerifiedChains[0]) != 2 || len(cs.VerifiedChains[0]) != 2 { + t.Errorf("Got %d (server) and %d (client) long verified chain, expected %d", len(ss.VerifiedChains[0]), len(cs.VerifiedChains[0]), 2) + } + + if len(cs.SignedCertificateTimestamps) != 2 { + t.Errorf("Got %d SCTs, expected %d", len(cs.SignedCertificateTimestamps), 2) + } + if !bytes.Equal(cs.OCSPResponse, ocsp) { + t.Errorf("Got OCSPs %x, expected %x", cs.OCSPResponse, ocsp) + } + // Only TLS 1.3 supports OCSP and SCTs on client certs. + if v == VersionTLS13 { + if len(ss.SignedCertificateTimestamps) != 2 { + t.Errorf("Got %d client SCTs, expected %d", len(ss.SignedCertificateTimestamps), 2) + } + if !bytes.Equal(ss.OCSPResponse, ocsp) { + t.Errorf("Got client OCSPs %x, expected %x", ss.OCSPResponse, ocsp) + } + } + + if v == VersionTLS13 { + if ss.TLSUnique != nil || cs.TLSUnique != nil { + t.Errorf("Got TLSUnique %x (server) and %x (client), expected nil in TLS 1.3", ss.TLSUnique, cs.TLSUnique) + } + } else { + if ss.TLSUnique == nil || cs.TLSUnique == nil { + t.Errorf("Got TLSUnique %x (server) and %x (client), expected non-nil", ss.TLSUnique, cs.TLSUnique) + } + } + }) + } +} + +// Issue 28744: Ensure that we don't modify memory +// that Config doesn't own such as Certificates. +func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) { + c0 := Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + } + c1 := Certificate{ + Certificate: [][]byte{testSNICertificate}, + PrivateKey: testRSAPrivateKey, + } + config := testConfig.Clone() + config.Certificates = []Certificate{c0, c1} + + config.BuildNameToCertificate() + got := config.Certificates + want := []Certificate{c0, c1} + if !reflect.DeepEqual(got, want) { + t.Fatalf("Certificates were mutated by BuildNameToCertificate\nGot: %#v\nWant: %#v\n", got, want) + } +} + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } + +func TestClientHelloInfo_SupportsCertificate(t *testing.T) { + rsaCert := &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + } + pkcs1Cert := &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + SupportedSignatureAlgorithms: []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}, + } + ecdsaCert := &Certificate{ + // ECDSA P-256 certificate + Certificate: [][]byte{testP256Certificate}, + PrivateKey: testP256PrivateKey, + } + ed25519Cert := &Certificate{ + Certificate: [][]byte{testEd25519Certificate}, + PrivateKey: testEd25519PrivateKey, + } + + tests := []struct { + c *Certificate + chi *ClientHelloInfo + wantErr string + }{ + {rsaCert, &ClientHelloInfo{ + ServerName: "example.golang", + SignatureSchemes: []SignatureScheme{PSSWithSHA256}, + SupportedVersions: []uint16{VersionTLS13}, + }, ""}, + {ecdsaCert, &ClientHelloInfo{ + SignatureSchemes: []SignatureScheme{PSSWithSHA256, ECDSAWithP256AndSHA256}, + SupportedVersions: []uint16{VersionTLS13, VersionTLS12}, + }, ""}, + {rsaCert, &ClientHelloInfo{ + ServerName: "example.com", + SignatureSchemes: []SignatureScheme{PSSWithSHA256}, + SupportedVersions: []uint16{VersionTLS13}, + }, "not valid for requested server name"}, + {ecdsaCert, &ClientHelloInfo{ + SignatureSchemes: []SignatureScheme{ECDSAWithP384AndSHA384}, + SupportedVersions: []uint16{VersionTLS13}, + }, "signature algorithms"}, + {pkcs1Cert, &ClientHelloInfo{ + SignatureSchemes: []SignatureScheme{PSSWithSHA256, ECDSAWithP256AndSHA256}, + SupportedVersions: []uint16{VersionTLS13}, + }, "signature algorithms"}, + + {rsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + SignatureSchemes: []SignatureScheme{PKCS1WithSHA1}, + SupportedVersions: []uint16{VersionTLS13, VersionTLS12}, + }, "signature algorithms"}, + {rsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + SignatureSchemes: []SignatureScheme{PKCS1WithSHA1}, + SupportedVersions: []uint16{VersionTLS13, VersionTLS12}, + config: &Config{ + MaxVersion: VersionTLS12, + }, + }, ""}, // Check that mutual version selection works. + + {ecdsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, + SupportedVersions: []uint16{VersionTLS12}, + }, ""}, + {ecdsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{ECDSAWithP384AndSHA384}, + SupportedVersions: []uint16{VersionTLS12}, + }, ""}, // TLS 1.2 does not restrict curves based on the SignatureScheme. + {ecdsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: nil, + SupportedVersions: []uint16{VersionTLS12}, + }, ""}, // TLS 1.2 comes with default signature schemes. + {ecdsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, + SupportedVersions: []uint16{VersionTLS12}, + }, "cipher suite"}, + {ecdsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, + SupportedVersions: []uint16{VersionTLS12}, + config: &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + }, + }, "cipher suite"}, + {ecdsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP384}, + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, + SupportedVersions: []uint16{VersionTLS12}, + }, "certificate curve"}, + {ecdsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, + SupportedPoints: []uint8{1}, + SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, + SupportedVersions: []uint16{VersionTLS12}, + }, "doesn't support ECDHE"}, + {ecdsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{PSSWithSHA256}, + SupportedVersions: []uint16{VersionTLS12}, + }, "signature algorithms"}, + + {ed25519Cert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{Ed25519}, + SupportedVersions: []uint16{VersionTLS12}, + }, ""}, + {ed25519Cert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{Ed25519}, + SupportedVersions: []uint16{VersionTLS10}, + }, "doesn't support Ed25519"}, + {ed25519Cert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, + SupportedCurves: []CurveID{}, + SupportedPoints: []uint8{pointFormatUncompressed}, + SignatureSchemes: []SignatureScheme{Ed25519}, + SupportedVersions: []uint16{VersionTLS12}, + }, "doesn't support ECDHE"}, + + {rsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, + SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support + SupportedPoints: []uint8{pointFormatUncompressed}, + SupportedVersions: []uint16{VersionTLS10}, + }, ""}, + {rsaCert, &ClientHelloInfo{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + SupportedVersions: []uint16{VersionTLS12}, + }, ""}, // static RSA fallback + } + for i, tt := range tests { + err := tt.chi.SupportsCertificate(tt.c) + switch { + case tt.wantErr == "" && err != nil: + t.Errorf("%d: unexpected error: %v", i, err) + case tt.wantErr != "" && err == nil: + t.Errorf("%d: unexpected success", i) + case tt.wantErr != "" && !strings.Contains(err.Error(), tt.wantErr): + t.Errorf("%d: got error %q, expected %q", i, err, tt.wantErr) + } + } +} + +func TestCipherSuites(t *testing.T) { + var lastID uint16 + for _, c := range CipherSuites() { + if lastID > c.ID { + t.Errorf("CipherSuites are not ordered by ID: got %#04x after %#04x", c.ID, lastID) + } else { + lastID = c.ID + } + + if c.Insecure { + t.Errorf("%#04x: Insecure CipherSuite returned by CipherSuites()", c.ID) + } + } + lastID = 0 + for _, c := range InsecureCipherSuites() { + if lastID > c.ID { + t.Errorf("InsecureCipherSuites are not ordered by ID: got %#04x after %#04x", c.ID, lastID) + } else { + lastID = c.ID + } + + if !c.Insecure { + t.Errorf("%#04x: not Insecure CipherSuite returned by InsecureCipherSuites()", c.ID) + } + } + + CipherSuiteByID := func(id uint16) *CipherSuite { + for _, c := range CipherSuites() { + if c.ID == id { + return c + } + } + for _, c := range InsecureCipherSuites() { + if c.ID == id { + return c + } + } + return nil + } + + for _, c := range cipherSuites { + cc := CipherSuiteByID(c.id) + if cc == nil { + t.Errorf("%#04x: no CipherSuite entry", c.id) + continue + } + + if tls12Only := c.flags&suiteTLS12 != 0; tls12Only && len(cc.SupportedVersions) != 1 { + t.Errorf("%#04x: suite is TLS 1.2 only, but SupportedVersions is %v", c.id, cc.SupportedVersions) + } else if !tls12Only && len(cc.SupportedVersions) != 3 { + t.Errorf("%#04x: suite TLS 1.0-1.2, but SupportedVersions is %v", c.id, cc.SupportedVersions) + } + + if got := CipherSuiteName(c.id); got != cc.Name { + t.Errorf("%#04x: unexpected CipherSuiteName: got %q, expected %q", c.id, got, cc.Name) + } + } + for _, c := range cipherSuitesTLS13 { + cc := CipherSuiteByID(c.id) + if cc == nil { + t.Errorf("%#04x: no CipherSuite entry", c.id) + continue + } + + if cc.Insecure { + t.Errorf("%#04x: Insecure %v, expected false", c.id, cc.Insecure) + } + if len(cc.SupportedVersions) != 1 || cc.SupportedVersions[0] != VersionTLS13 { + t.Errorf("%#04x: suite is TLS 1.3 only, but SupportedVersions is %v", c.id, cc.SupportedVersions) + } + + if got := CipherSuiteName(c.id); got != cc.Name { + t.Errorf("%#04x: unexpected CipherSuiteName: got %q, expected %q", c.id, got, cc.Name) + } + } + + if got := CipherSuiteName(0xabc); got != "0x0ABC" { + t.Errorf("unexpected fallback CipherSuiteName: got %q, expected 0x0ABC", got) + } + + if len(cipherSuitesPreferenceOrder) != len(cipherSuites) { + t.Errorf("cipherSuitesPreferenceOrder is not the same size as cipherSuites") + } + if len(cipherSuitesPreferenceOrderNoAES) != len(cipherSuitesPreferenceOrder) { + t.Errorf("cipherSuitesPreferenceOrderNoAES is not the same size as cipherSuitesPreferenceOrder") + } + + // Check that disabled suites are at the end of the preference lists, and + // that they are marked insecure. + for i, id := range disabledCipherSuites { + offset := len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites) + if cipherSuitesPreferenceOrder[offset+i] != id { + t.Errorf("disabledCipherSuites[%d]: not at the end of cipherSuitesPreferenceOrder", i) + } + if cipherSuitesPreferenceOrderNoAES[offset+i] != id { + t.Errorf("disabledCipherSuites[%d]: not at the end of cipherSuitesPreferenceOrderNoAES", i) + } + c := CipherSuiteByID(id) + if c == nil { + t.Errorf("%#04x: no CipherSuite entry", id) + continue + } + if !c.Insecure { + t.Errorf("%#04x: disabled by default but not marked insecure", id) + } + } + + for i, prefOrder := range [][]uint16{cipherSuitesPreferenceOrder, cipherSuitesPreferenceOrderNoAES} { + // Check that insecure and HTTP/2 bad cipher suites are at the end of + // the preference lists. + var sawInsecure, sawBad bool + for _, id := range prefOrder { + c := CipherSuiteByID(id) + if c == nil { + t.Errorf("%#04x: no CipherSuite entry", id) + continue + } + + if c.Insecure { + sawInsecure = true + } else if sawInsecure { + t.Errorf("%#04x: secure suite after insecure one(s)", id) + } + + if http2isBadCipher(id) { + sawBad = true + } else if sawBad { + t.Errorf("%#04x: non-bad suite after bad HTTP/2 one(s)", id) + } + } + + // Check that the list is sorted according to the documented criteria. + isBetter := func(a, b int) bool { + aSuite, bSuite := cipherSuiteByID(prefOrder[a]), cipherSuiteByID(prefOrder[b]) + aName, bName := CipherSuiteName(prefOrder[a]), CipherSuiteName(prefOrder[b]) + // * < RC4 + if !strings.Contains(aName, "RC4") && strings.Contains(bName, "RC4") { + return true + } else if strings.Contains(aName, "RC4") && !strings.Contains(bName, "RC4") { + return false + } + // * < CBC_SHA256 + if !strings.Contains(aName, "CBC_SHA256") && strings.Contains(bName, "CBC_SHA256") { + return true + } else if strings.Contains(aName, "CBC_SHA256") && !strings.Contains(bName, "CBC_SHA256") { + return false + } + // * < 3DES + if !strings.Contains(aName, "3DES") && strings.Contains(bName, "3DES") { + return true + } else if strings.Contains(aName, "3DES") && !strings.Contains(bName, "3DES") { + return false + } + // ECDHE < * + if aSuite.flags&suiteECDHE != 0 && bSuite.flags&suiteECDHE == 0 { + return true + } else if aSuite.flags&suiteECDHE == 0 && bSuite.flags&suiteECDHE != 0 { + return false + } + // AEAD < CBC + if aSuite.aead != nil && bSuite.aead == nil { + return true + } else if aSuite.aead == nil && bSuite.aead != nil { + return false + } + // AES < ChaCha20 + if strings.Contains(aName, "AES") && strings.Contains(bName, "CHACHA20") { + return i == 0 // true for cipherSuitesPreferenceOrder + } else if strings.Contains(aName, "CHACHA20") && strings.Contains(bName, "AES") { + return i != 0 // true for cipherSuitesPreferenceOrderNoAES + } + // AES-128 < AES-256 + if strings.Contains(aName, "AES_128") && strings.Contains(bName, "AES_256") { + return true + } else if strings.Contains(aName, "AES_256") && strings.Contains(bName, "AES_128") { + return false + } + // ECDSA < RSA + if aSuite.flags&suiteECSign != 0 && bSuite.flags&suiteECSign == 0 { + return true + } else if aSuite.flags&suiteECSign == 0 && bSuite.flags&suiteECSign != 0 { + return false + } + t.Fatalf("two ciphersuites are equal by all criteria: %v and %v", aName, bName) + panic("unreachable") + } + if !sort.SliceIsSorted(prefOrder, isBetter) { + t.Error("preference order is not sorted according to the rules") + } + } +} + +// http2isBadCipher is copied from net/http. +// TODO: if it ends up exposed somewhere, use that instead. +func http2isBadCipher(cipher uint16) bool { + switch cipher { + case TLS_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return true + default: + return false + } +} + +type brokenSigner struct{ crypto.Signer } + +func (s brokenSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) { + // Replace opts with opts.HashFunc(), so rsa.PSSOptions are discarded. + return s.Signer.Sign(rand, digest, opts.HashFunc()) +} + +// TestPKCS1OnlyCert uses a client certificate with a broken crypto.Signer that +// always makes PKCS #1 v1.5 signatures, so can't be used with RSA-PSS. +func TestPKCS1OnlyCert(t *testing.T) { + clientConfig := testConfig.Clone() + clientConfig.Certificates = []Certificate{{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: brokenSigner{testRSAPrivateKey}, + }} + serverConfig := testConfig.Clone() + serverConfig.MaxVersion = VersionTLS12 // TLS 1.3 doesn't support PKCS #1 v1.5 + serverConfig.ClientAuth = RequireAnyClientCert + + // If RSA-PSS is selected, the handshake should fail. + if _, _, err := testHandshake(t, clientConfig, serverConfig); err == nil { + t.Fatal("expected broken certificate to cause connection to fail") + } + + clientConfig.Certificates[0].SupportedSignatureAlgorithms = + []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256} + + // But if the certificate restricts supported algorithms, RSA-PSS should not + // be selected, and the handshake should succeed. + if _, _, err := testHandshake(t, clientConfig, serverConfig); err != nil { + t.Error(err) + } +} diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go new file mode 100644 index 0000000..bcc5db3 --- /dev/null +++ b/src/crypto/x509/cert_pool.go @@ -0,0 +1,248 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "crypto/sha256" + "encoding/pem" + "errors" + "runtime" + "sync" +) + +type sum224 [sha256.Size224]byte + +// CertPool is a set of certificates. +type CertPool struct { + byName map[string][]int // cert.RawSubject => index into lazyCerts + + // lazyCerts contains funcs that return a certificate, + // lazily parsing/decompressing it as needed. + lazyCerts []lazyCert + + // haveSum maps from sum224(cert.Raw) to true. It's used only + // for AddCert duplicate detection, to avoid CertPool.contains + // calls in the AddCert path (because the contains method can + // call getCert and otherwise negate savings from lazy getCert + // funcs). + haveSum map[sum224]bool +} + +// lazyCert is minimal metadata about a Cert and a func to retrieve it +// in its normal expanded *Certificate form. +type lazyCert struct { + // rawSubject is the Certificate.RawSubject value. + // It's the same as the CertPool.byName key, but in []byte + // form to make CertPool.Subjects (as used by crypto/tls) do + // fewer allocations. + rawSubject []byte + + // getCert returns the certificate. + // + // It is not meant to do network operations or anything else + // where a failure is likely; the func is meant to lazily + // parse/decompress data that is already known to be good. The + // error in the signature primarily is meant for use in the + // case where a cert file existed on local disk when the program + // started up is deleted later before it's read. + getCert func() (*Certificate, error) +} + +// NewCertPool returns a new, empty CertPool. +func NewCertPool() *CertPool { + return &CertPool{ + byName: make(map[string][]int), + haveSum: make(map[sum224]bool), + } +} + +// len returns the number of certs in the set. +// A nil set is a valid empty set. +func (s *CertPool) len() int { + if s == nil { + return 0 + } + return len(s.lazyCerts) +} + +// cert returns cert index n in s. +func (s *CertPool) cert(n int) (*Certificate, error) { + return s.lazyCerts[n].getCert() +} + +func (s *CertPool) copy() *CertPool { + p := &CertPool{ + byName: make(map[string][]int, len(s.byName)), + lazyCerts: make([]lazyCert, len(s.lazyCerts)), + haveSum: make(map[sum224]bool, len(s.haveSum)), + } + for k, v := range s.byName { + indexes := make([]int, len(v)) + copy(indexes, v) + p.byName[k] = indexes + } + for k := range s.haveSum { + p.haveSum[k] = true + } + copy(p.lazyCerts, s.lazyCerts) + return p +} + +// SystemCertPool returns a copy of the system cert pool. +// +// On Unix systems other than macOS the environment variables SSL_CERT_FILE and +// SSL_CERT_DIR can be used to override the system default locations for the SSL +// certificate file and SSL certificate files directory, respectively. The +// latter can be a colon-separated list. +// +// Any mutations to the returned pool are not written to disk and do not affect +// any other pool returned by SystemCertPool. +// +// New changes in the system cert pool might not be reflected in subsequent calls. +func SystemCertPool() (*CertPool, error) { + if runtime.GOOS == "windows" { + // Issue 16736, 18609: + return nil, errors.New("crypto/x509: system root pool is not available on Windows") + } + + if sysRoots := systemRootsPool(); sysRoots != nil { + return sysRoots.copy(), nil + } + + return loadSystemRoots() +} + +// findPotentialParents returns the indexes of certificates in s which might +// have signed cert. +func (s *CertPool) findPotentialParents(cert *Certificate) []*Certificate { + if s == nil { + return nil + } + + // consider all candidates where cert.Issuer matches cert.Subject. + // when picking possible candidates the list is built in the order + // of match plausibility as to save cycles in buildChains: + // AKID and SKID match + // AKID present, SKID missing / AKID missing, SKID present + // AKID and SKID don't match + var matchingKeyID, oneKeyID, mismatchKeyID []*Certificate + for _, c := range s.byName[string(cert.RawIssuer)] { + candidate, err := s.cert(c) + if err != nil { + continue + } + kidMatch := bytes.Equal(candidate.SubjectKeyId, cert.AuthorityKeyId) + switch { + case kidMatch: + matchingKeyID = append(matchingKeyID, candidate) + case (len(candidate.SubjectKeyId) == 0 && len(cert.AuthorityKeyId) > 0) || + (len(candidate.SubjectKeyId) > 0 && len(cert.AuthorityKeyId) == 0): + oneKeyID = append(oneKeyID, candidate) + default: + mismatchKeyID = append(mismatchKeyID, candidate) + } + } + + found := len(matchingKeyID) + len(oneKeyID) + len(mismatchKeyID) + if found == 0 { + return nil + } + candidates := make([]*Certificate, 0, found) + candidates = append(candidates, matchingKeyID...) + candidates = append(candidates, oneKeyID...) + candidates = append(candidates, mismatchKeyID...) + return candidates +} + +func (s *CertPool) contains(cert *Certificate) bool { + if s == nil { + return false + } + return s.haveSum[sha256.Sum224(cert.Raw)] +} + +// AddCert adds a certificate to a pool. +func (s *CertPool) AddCert(cert *Certificate) { + if cert == nil { + panic("adding nil Certificate to CertPool") + } + s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) { + return cert, nil + }) +} + +// addCertFunc adds metadata about a certificate to a pool, along with +// a func to fetch that certificate later when needed. +// +// The rawSubject is Certificate.RawSubject and must be non-empty. +// The getCert func may be called 0 or more times. +func (s *CertPool) addCertFunc(rawSum224 sum224, rawSubject string, getCert func() (*Certificate, error)) { + if getCert == nil { + panic("getCert can't be nil") + } + + // Check that the certificate isn't being added twice. + if s.haveSum[rawSum224] { + return + } + + s.haveSum[rawSum224] = true + s.lazyCerts = append(s.lazyCerts, lazyCert{ + rawSubject: []byte(rawSubject), + getCert: getCert, + }) + s.byName[rawSubject] = append(s.byName[rawSubject], len(s.lazyCerts)-1) +} + +// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. +// It appends any certificates found to s and reports whether any certificates +// were successfully parsed. +// +// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set +// of root CAs in a format suitable for this function. +func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { + for len(pemCerts) > 0 { + var block *pem.Block + block, pemCerts = pem.Decode(pemCerts) + if block == nil { + break + } + if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { + continue + } + + certBytes := block.Bytes + cert, err := ParseCertificate(certBytes) + if err != nil { + continue + } + var lazyCert struct { + sync.Once + v *Certificate + } + s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) { + lazyCert.Do(func() { + // This can't fail, as the same bytes already parsed above. + lazyCert.v, _ = ParseCertificate(certBytes) + certBytes = nil + }) + return lazyCert.v, nil + }) + ok = true + } + + return ok +} + +// Subjects returns a list of the DER-encoded subjects of +// all of the certificates in the pool. +func (s *CertPool) Subjects() [][]byte { + res := make([][]byte, s.len()) + for i, lc := range s.lazyCerts { + res[i] = lc.rawSubject + } + return res +} diff --git a/src/crypto/x509/example_test.go b/src/crypto/x509/example_test.go new file mode 100644 index 0000000..19d249a --- /dev/null +++ b/src/crypto/x509/example_test.go @@ -0,0 +1,137 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509_test + +import ( + "crypto/dsa" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" +) + +func ExampleCertificate_Verify() { + // Verifying with a custom list of root certificates. + + const rootPEM = ` +-----BEGIN CERTIFICATE----- +MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG +EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy +bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP +VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv +h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE +ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ +EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC +DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7 +qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD +VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g +K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI +KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n +ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB +BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY +/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/ +zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza +HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto +WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6 +yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx +-----END CERTIFICATE-----` + + const certPEM = ` +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIIE31FZVaPXTUwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE +BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl +cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMTI5MTMyNzQzWhcNMTQwNTI5MDAwMDAw +WjBpMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN +TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEYMBYGA1UEAwwPbWFp +bC5nb29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfRrObuSW5T7q +5CnSEqefEmtH4CCv6+5EckuriNr1CjfVvqzwfAhopXkLrq45EQm8vkmf7W96XJhC +7ZM0dYi1/qOCAU8wggFLMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAa +BgNVHREEEzARgg9tYWlsLmdvb2dsZS5jb20wCwYDVR0PBAQDAgeAMGgGCCsGAQUF +BwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUuY29tL0dJQUcy +LmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2dsZS5jb20vb2Nz +cDAdBgNVHQ4EFgQUiJxtimAuTfwb+aUtBn5UYKreKvMwDAYDVR0TAQH/BAIwADAf +BgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAXBgNVHSAEEDAOMAwGCisG +AQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29nbGUuY29t +L0dJQUcyLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAH6RYHxHdcGpMpFE3oxDoFnP+ +gtuBCHan2yE2GRbJ2Cw8Lw0MmuKqHlf9RSeYfd3BXeKkj1qO6TVKwCh+0HdZk283 +TZZyzmEOyclm3UGFYe82P/iDFt+CeQ3NpmBg+GoaVCuWAARJN/KfglbLyyYygcQq +0SgeDh8dRKUiaW3HQSoYvTvdTuqzwK4CXsr3b5/dAOY8uMuG/IAR3FgwTbZ1dtoW +RvOTa8hYiU6A475WuZKyEHcwnGYe57u2I2KbMgcKjPniocj4QzgYsVAVKW3IwaOh +yE+vPxsiUkvQHdO2fojCkY8jg70jxM+gu59tPDNbw3Uh/2Ij310FgTHsnGQMyA== +-----END CERTIFICATE-----` + + // First, create the set of root certificates. For this example we only + // have one. It's also possible to omit this in order to use the + // default root set of the current operating system. + roots := x509.NewCertPool() + ok := roots.AppendCertsFromPEM([]byte(rootPEM)) + if !ok { + panic("failed to parse root certificate") + } + + block, _ := pem.Decode([]byte(certPEM)) + if block == nil { + panic("failed to parse certificate PEM") + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + panic("failed to parse certificate: " + err.Error()) + } + + opts := x509.VerifyOptions{ + DNSName: "mail.google.com", + Roots: roots, + } + + if _, err := cert.Verify(opts); err != nil { + panic("failed to verify certificate: " + err.Error()) + } +} + +func ExampleParsePKIXPublicKey() { + const pubPEM = ` +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlRuRnThUjU8/prwYxbty +WPT9pURI3lbsKMiB6Fn/VHOKE13p4D8xgOCADpdRagdT6n4etr9atzDKUSvpMtR3 +CP5noNc97WiNCggBjVWhs7szEe8ugyqF23XwpHQ6uV1LKH50m92MbOWfCtjU9p/x +qhNpQQ1AZhqNy5Gevap5k8XzRmjSldNAFZMY7Yv3Gi+nyCwGwpVtBUwhuLzgNFK/ +yDtw2WcWmUU7NuC8Q6MWvPebxVtCfVp/iQU6q60yyt6aGOBkhAX0LpKAEhKidixY +nP9PNVBvxgu3XZ4P36gZV6+ummKdBVnc3NqwBLu5+CcdRdusmHPHd5pHf4/38Z3/ +6qU2a/fPvWzceVTEgZ47QjFMTCTmCwNt29cvi7zZeQzjtwQgn4ipN9NibRH/Ax/q +TbIzHfrJ1xa2RteWSdFjwtxi9C20HUkjXSeI4YlzQMH0fPX6KCE7aVePTOnB69I/ +a9/q96DiXZajwlpq3wFctrs1oXqBp5DVrCIj8hU2wNgB7LtQ1mCtsYz//heai0K9 +PhE4X6hiE0YmeAZjR0uHl8M/5aW9xCoJ72+12kKpWAa0SFRWLy6FejNYCYpkupVJ +yecLk/4L1W0l6jQQZnWErXZYe0PNFcmwGXy1Rep83kfBRNKRy5tvocalLlwXLdUk +AIU+2GKjyT3iMuzZxxFxPFMCAwEAAQ== +-----END PUBLIC KEY-----` + + block, _ := pem.Decode([]byte(pubPEM)) + if block == nil { + panic("failed to parse PEM block containing the public key") + } + + pub, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + panic("failed to parse DER encoded public key: " + err.Error()) + } + + switch pub := pub.(type) { + case *rsa.PublicKey: + fmt.Println("pub is of type RSA:", pub) + case *dsa.PublicKey: + fmt.Println("pub is of type DSA:", pub) + case *ecdsa.PublicKey: + fmt.Println("pub is of type ECDSA:", pub) + case ed25519.PublicKey: + fmt.Println("pub is of type Ed25519:", pub) + default: + panic("unknown type of public key") + } +} diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go new file mode 100644 index 0000000..fcfbc1e --- /dev/null +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -0,0 +1,131 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios +// +build darwin,!ios + +// Package macOS provides cgo-less wrappers for Core Foundation and +// Security.framework, similarly to how package syscall provides access to +// libSystem.dylib. +package macOS + +import ( + "errors" + "internal/abi" + "reflect" + "runtime" + "unsafe" +) + +// Core Foundation linker flags for the external linker. See Issue 42459. +//go:cgo_ldflag "-framework" +//go:cgo_ldflag "CoreFoundation" + +// CFRef is an opaque reference to a Core Foundation object. It is a pointer, +// but to memory not owned by Go, so not an unsafe.Pointer. +type CFRef uintptr + +// CFDataToSlice returns a copy of the contents of data as a bytes slice. +func CFDataToSlice(data CFRef) []byte { + length := CFDataGetLength(data) + ptr := CFDataGetBytePtr(data) + src := (*[1 << 20]byte)(unsafe.Pointer(ptr))[:length:length] + out := make([]byte, length) + copy(out, src) + return out +} + +type CFString CFRef + +const kCFAllocatorDefault = 0 +const kCFStringEncodingUTF8 = 0x08000100 + +//go:cgo_import_dynamic x509_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +// StringToCFString returns a copy of the UTF-8 contents of s as a new CFString. +func StringToCFString(s string) CFString { + p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data) + ret := syscall(abi.FuncPCABI0(x509_CFStringCreateWithBytes_trampoline), kCFAllocatorDefault, uintptr(p), + uintptr(len(s)), uintptr(kCFStringEncodingUTF8), 0 /* isExternalRepresentation */, 0) + runtime.KeepAlive(p) + return CFString(ret) +} +func x509_CFStringCreateWithBytes_trampoline() + +//go:cgo_import_dynamic x509_CFDictionaryGetValueIfPresent CFDictionaryGetValueIfPresent "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) { + ret := syscall(abi.FuncPCABI0(x509_CFDictionaryGetValueIfPresent_trampoline), uintptr(dict), uintptr(key), + uintptr(unsafe.Pointer(&value)), 0, 0, 0) + if ret == 0 { + return 0, false + } + return value, true +} +func x509_CFDictionaryGetValueIfPresent_trampoline() + +const kCFNumberSInt32Type = 3 + +//go:cgo_import_dynamic x509_CFNumberGetValue CFNumberGetValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFNumberGetValue(num CFRef) (int32, error) { + var value int32 + ret := syscall(abi.FuncPCABI0(x509_CFNumberGetValue_trampoline), uintptr(num), uintptr(kCFNumberSInt32Type), + uintptr(unsafe.Pointer(&value)), 0, 0, 0) + if ret == 0 { + return 0, errors.New("CFNumberGetValue call failed") + } + return value, nil +} +func x509_CFNumberGetValue_trampoline() + +//go:cgo_import_dynamic x509_CFDataGetLength CFDataGetLength "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFDataGetLength(data CFRef) int { + ret := syscall(abi.FuncPCABI0(x509_CFDataGetLength_trampoline), uintptr(data), 0, 0, 0, 0, 0) + return int(ret) +} +func x509_CFDataGetLength_trampoline() + +//go:cgo_import_dynamic x509_CFDataGetBytePtr CFDataGetBytePtr "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFDataGetBytePtr(data CFRef) uintptr { + ret := syscall(abi.FuncPCABI0(x509_CFDataGetBytePtr_trampoline), uintptr(data), 0, 0, 0, 0, 0) + return ret +} +func x509_CFDataGetBytePtr_trampoline() + +//go:cgo_import_dynamic x509_CFArrayGetCount CFArrayGetCount "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFArrayGetCount(array CFRef) int { + ret := syscall(abi.FuncPCABI0(x509_CFArrayGetCount_trampoline), uintptr(array), 0, 0, 0, 0, 0) + return int(ret) +} +func x509_CFArrayGetCount_trampoline() + +//go:cgo_import_dynamic x509_CFArrayGetValueAtIndex CFArrayGetValueAtIndex "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFArrayGetValueAtIndex(array CFRef, index int) CFRef { + ret := syscall(abi.FuncPCABI0(x509_CFArrayGetValueAtIndex_trampoline), uintptr(array), uintptr(index), 0, 0, 0, 0) + return CFRef(ret) +} +func x509_CFArrayGetValueAtIndex_trampoline() + +//go:cgo_import_dynamic x509_CFEqual CFEqual "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFEqual(a, b CFRef) bool { + ret := syscall(abi.FuncPCABI0(x509_CFEqual_trampoline), uintptr(a), uintptr(b), 0, 0, 0, 0) + return ret == 1 +} +func x509_CFEqual_trampoline() + +//go:cgo_import_dynamic x509_CFRelease CFRelease "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFRelease(ref CFRef) { + syscall(abi.FuncPCABI0(x509_CFRelease_trampoline), uintptr(ref), 0, 0, 0, 0, 0) +} +func x509_CFRelease_trampoline() + +// syscall is implemented in the runtime package (runtime/sys_darwin.go) +func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr diff --git a/src/crypto/x509/internal/macos/corefoundation.s b/src/crypto/x509/internal/macos/corefoundation.s new file mode 100644 index 0000000..cda2336 --- /dev/null +++ b/src/crypto/x509/internal/macos/corefoundation.s @@ -0,0 +1,30 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios +// +build darwin,!ios + +#include "textflag.h" + +// The trampolines are ABIInternal as they are address-taken in +// Go code. + +TEXT ·x509_CFArrayGetCount_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFArrayGetCount(SB) +TEXT ·x509_CFArrayGetValueAtIndex_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFArrayGetValueAtIndex(SB) +TEXT ·x509_CFDataGetBytePtr_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFDataGetBytePtr(SB) +TEXT ·x509_CFDataGetLength_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFDataGetLength(SB) +TEXT ·x509_CFStringCreateWithBytes_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFStringCreateWithBytes(SB) +TEXT ·x509_CFRelease_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFRelease(SB) +TEXT ·x509_CFDictionaryGetValueIfPresent_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFDictionaryGetValueIfPresent(SB) +TEXT ·x509_CFNumberGetValue_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFNumberGetValue(SB) +TEXT ·x509_CFEqual_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFEqual(SB) diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go new file mode 100644 index 0000000..0f6fa42 --- /dev/null +++ b/src/crypto/x509/internal/macos/security.go @@ -0,0 +1,118 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios +// +build darwin,!ios + +package macOS + +import ( + "errors" + "internal/abi" + "strconv" + "unsafe" +) + +// Security.framework linker flags for the external linker. See Issue 42459. +//go:cgo_ldflag "-framework" +//go:cgo_ldflag "Security" + +// Based on https://opensource.apple.com/source/Security/Security-59306.41.2/base/Security.h + +type SecTrustSettingsResult int32 + +const ( + SecTrustSettingsResultInvalid SecTrustSettingsResult = iota + SecTrustSettingsResultTrustRoot + SecTrustSettingsResultTrustAsRoot + SecTrustSettingsResultDeny + SecTrustSettingsResultUnspecified +) + +type SecTrustSettingsDomain int32 + +const ( + SecTrustSettingsDomainUser SecTrustSettingsDomain = iota + SecTrustSettingsDomainAdmin + SecTrustSettingsDomainSystem +) + +type OSStatus struct { + call string + status int32 +} + +func (s OSStatus) Error() string { + return s.call + " error: " + strconv.Itoa(int(s.status)) +} + +// Dictionary keys are defined as build-time strings with CFSTR, but the Go +// linker's internal linking mode can't handle CFSTR relocations. Create our +// own dynamic strings instead and just never release them. +// +// Note that this might be the only thing that can break over time if +// these values change, as the ABI arguably requires using the strings +// pointed to by the symbols, not values that happen to be equal to them. + +var SecTrustSettingsResultKey = StringToCFString("kSecTrustSettingsResult") +var SecTrustSettingsPolicy = StringToCFString("kSecTrustSettingsPolicy") +var SecTrustSettingsPolicyString = StringToCFString("kSecTrustSettingsPolicyString") +var SecPolicyOid = StringToCFString("SecPolicyOid") +var SecPolicyAppleSSL = StringToCFString("1.2.840.113635.100.1.3") // defined by POLICYMACRO + +var ErrNoTrustSettings = errors.New("no trust settings found") + +const errSecNoTrustSettings = -25263 + +//go:cgo_import_dynamic x509_SecTrustSettingsCopyCertificates SecTrustSettingsCopyCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) { + ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyCertificates_trampoline), uintptr(domain), + uintptr(unsafe.Pointer(&certArray)), 0, 0, 0, 0) + if int32(ret) == errSecNoTrustSettings { + return 0, ErrNoTrustSettings + } else if ret != 0 { + return 0, OSStatus{"SecTrustSettingsCopyCertificates", int32(ret)} + } + return certArray, nil +} +func x509_SecTrustSettingsCopyCertificates_trampoline() + +const kSecFormatX509Cert int32 = 9 + +//go:cgo_import_dynamic x509_SecItemExport SecItemExport "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecItemExport(cert CFRef) (data CFRef, err error) { + ret := syscall(abi.FuncPCABI0(x509_SecItemExport_trampoline), uintptr(cert), uintptr(kSecFormatX509Cert), + 0 /* flags */, 0 /* keyParams */, uintptr(unsafe.Pointer(&data)), 0) + if ret != 0 { + return 0, OSStatus{"SecItemExport", int32(ret)} + } + return data, nil +} +func x509_SecItemExport_trampoline() + +const errSecItemNotFound = -25300 + +//go:cgo_import_dynamic x509_SecTrustSettingsCopyTrustSettings SecTrustSettingsCopyTrustSettings "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) { + ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyTrustSettings_trampoline), uintptr(cert), uintptr(domain), + uintptr(unsafe.Pointer(&trustSettings)), 0, 0, 0) + if int32(ret) == errSecItemNotFound { + return 0, ErrNoTrustSettings + } else if ret != 0 { + return 0, OSStatus{"SecTrustSettingsCopyTrustSettings", int32(ret)} + } + return trustSettings, nil +} +func x509_SecTrustSettingsCopyTrustSettings_trampoline() + +//go:cgo_import_dynamic x509_SecPolicyCopyProperties SecPolicyCopyProperties "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecPolicyCopyProperties(policy CFRef) CFRef { + ret := syscall(abi.FuncPCABI0(x509_SecPolicyCopyProperties_trampoline), uintptr(policy), 0, 0, 0, 0, 0) + return CFRef(ret) +} +func x509_SecPolicyCopyProperties_trampoline() diff --git a/src/crypto/x509/internal/macos/security.s b/src/crypto/x509/internal/macos/security.s new file mode 100644 index 0000000..0038f25 --- /dev/null +++ b/src/crypto/x509/internal/macos/security.s @@ -0,0 +1,20 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios +// +build darwin,!ios + +#include "textflag.h" + +// The trampolines are ABIInternal as they are address-taken in +// Go code. + +TEXT ·x509_SecTrustSettingsCopyCertificates_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustSettingsCopyCertificates(SB) +TEXT ·x509_SecItemExport_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecItemExport(SB) +TEXT ·x509_SecTrustSettingsCopyTrustSettings_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustSettingsCopyTrustSettings(SB) +TEXT ·x509_SecPolicyCopyProperties_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecPolicyCopyProperties(SB) diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go new file mode 100644 index 0000000..c59a7dc --- /dev/null +++ b/src/crypto/x509/name_constraints_test.go @@ -0,0 +1,2160 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509/pkix" + "encoding/asn1" + "encoding/hex" + "encoding/pem" + "fmt" + "math/big" + "net" + "net/url" + "os" + "os/exec" + "strconv" + "strings" + "sync" + "testing" + "time" +) + +const ( + // testNameConstraintsAgainstOpenSSL can be set to true to run tests + // against the system OpenSSL. This is disabled by default because Go + // cannot depend on having OpenSSL installed at testing time. + testNameConstraintsAgainstOpenSSL = false + + // debugOpenSSLFailure can be set to true, when + // testNameConstraintsAgainstOpenSSL is also true, to cause + // intermediate files to be preserved for debugging. + debugOpenSSLFailure = false +) + +type nameConstraintsTest struct { + roots []constraintsSpec + intermediates [][]constraintsSpec + leaf leafSpec + requestedEKUs []ExtKeyUsage + expectedError string + noOpenSSL bool + ignoreCN bool +} + +type constraintsSpec struct { + ok []string + bad []string + ekus []string +} + +type leafSpec struct { + sans []string + ekus []string + cn string +} + +var nameConstraintsTests = []nameConstraintsTest{ + // #0: dummy test for the certificate generation process itself. + { + roots: make([]constraintsSpec, 1), + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #1: dummy test for the certificate generation process itself: single + // level of intermediate. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #2: dummy test for the certificate generation process itself: two + // levels of intermediates. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + {}, + }, + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #3: matching DNS constraint in root + { + roots: []constraintsSpec{ + { + ok: []string{"dns:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #4: matching DNS constraint in intermediate. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ok: []string{"dns:example.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #5: .example.com only matches subdomains. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + expectedError: "\"example.com\" is not permitted", + }, + + // #6: .example.com matches subdomains. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ok: []string{"dns:.example.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.example.com"}, + }, + }, + + // #7: .example.com matches multiple levels of subdomains + { + roots: []constraintsSpec{ + { + ok: []string{"dns:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.bar.example.com"}, + }, + }, + + // #8: specifying a permitted list of names does not exclude other name + // types + { + roots: []constraintsSpec{ + { + ok: []string{"dns:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:10.1.1.1"}, + }, + }, + + // #9: specifying a permitted list of names does not exclude other name + // types + { + roots: []constraintsSpec{ + { + ok: []string{"ip:10.0.0.0/8"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #10: intermediates can try to permit other names, which isn't + // forbidden if the leaf doesn't mention them. I.e. name constraints + // apply to names, not constraints themselves. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + { + ok: []string{"dns:example.com", "dns:foo.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #11: intermediates cannot add permitted names that the root doesn't + // grant them. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + { + ok: []string{"dns:example.com", "dns:foo.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.com"}, + }, + expectedError: "\"foo.com\" is not permitted", + }, + + // #12: intermediates can further limit their scope if they wish. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + { + ok: []string{"dns:.bar.example.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.bar.example.com"}, + }, + }, + + // #13: intermediates can further limit their scope and that limitation + // is effective + { + roots: []constraintsSpec{ + { + ok: []string{"dns:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + { + ok: []string{"dns:.bar.example.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.notbar.example.com"}, + }, + expectedError: "\"foo.notbar.example.com\" is not permitted", + }, + + // #14: roots can exclude subtrees and that doesn't affect other names. + { + roots: []constraintsSpec{ + { + bad: []string{"dns:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.com"}, + }, + }, + + // #15: roots exclusions are effective. + { + roots: []constraintsSpec{ + { + bad: []string{"dns:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.example.com"}, + }, + expectedError: "\"foo.example.com\" is excluded", + }, + + // #16: intermediates can also exclude names and that doesn't affect + // other names. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + bad: []string{"dns:.example.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.com"}, + }, + }, + + // #17: intermediate exclusions are effective. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + bad: []string{"dns:.example.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.example.com"}, + }, + expectedError: "\"foo.example.com\" is excluded", + }, + + // #18: having an exclusion doesn't prohibit other types of names. + { + roots: []constraintsSpec{ + { + bad: []string{"dns:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.com", "ip:10.1.1.1"}, + }, + }, + + // #19: IP-based exclusions are permitted and don't affect unrelated IP + // addresses. + { + roots: []constraintsSpec{ + { + bad: []string{"ip:10.0.0.0/8"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:192.168.1.1"}, + }, + }, + + // #20: IP-based exclusions are effective + { + roots: []constraintsSpec{ + { + bad: []string{"ip:10.0.0.0/8"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:10.0.0.1"}, + }, + expectedError: "\"10.0.0.1\" is excluded", + }, + + // #21: intermediates can further constrain IP ranges. + { + roots: []constraintsSpec{ + { + bad: []string{"ip:0.0.0.0/1"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + { + bad: []string{"ip:11.0.0.0/8"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:11.0.0.1"}, + }, + expectedError: "\"11.0.0.1\" is excluded", + }, + + // #22: when multiple intermediates are present, chain building can + // avoid intermediates with incompatible constraints. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ok: []string{"dns:.foo.com"}, + }, + { + ok: []string{"dns:.example.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.example.com"}, + }, + noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. + }, + + // #23: (same as the previous test, but in the other order in ensure + // that we don't pass it by luck.) + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ok: []string{"dns:.example.com"}, + }, + { + ok: []string{"dns:.foo.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.example.com"}, + }, + noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. + }, + + // #24: when multiple roots are valid, chain building can avoid roots + // with incompatible constraints. + { + roots: []constraintsSpec{ + {}, + { + ok: []string{"dns:foo.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. + }, + + // #25: (same as the previous test, but in the other order in ensure + // that we don't pass it by luck.) + { + roots: []constraintsSpec{ + { + ok: []string{"dns:foo.com"}, + }, + {}, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. + }, + + // #26: chain building can find a valid path even with multiple levels + // of alternative intermediates and alternative roots. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:foo.com"}, + }, + { + ok: []string{"dns:example.com"}, + }, + {}, + }, + intermediates: [][]constraintsSpec{ + { + {}, + { + ok: []string{"dns:foo.com"}, + }, + }, + { + {}, + { + ok: []string{"dns:foo.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:bar.com"}, + }, + noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. + }, + + // #27: chain building doesn't get stuck when there is no valid path. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:foo.com"}, + }, + { + ok: []string{"dns:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + { + ok: []string{"dns:foo.com"}, + }, + }, + { + { + ok: []string{"dns:bar.com"}, + }, + { + ok: []string{"dns:foo.com"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:bar.com"}, + }, + expectedError: "\"bar.com\" is not permitted", + }, + + // #28: unknown name types don't cause a problem without constraints. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"unknown:"}, + }, + }, + + // #29: unknown name types are allowed even in constrained chains. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:foo.com", "dns:.foo.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"unknown:"}, + }, + }, + + // #30: without SANs, a certificate with a CN is still accepted in a + // constrained chain, since we ignore the CN in VerifyHostname. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:foo.com", "dns:.foo.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{}, + cn: "foo.com", + }, + }, + + // #31: IPv6 addresses work in constraints: roots can permit them as + // expected. + { + roots: []constraintsSpec{ + { + ok: []string{"ip:2000:abcd::/32"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:2000:abcd:1234::"}, + }, + }, + + // #32: IPv6 addresses work in constraints: root restrictions are + // effective. + { + roots: []constraintsSpec{ + { + ok: []string{"ip:2000:abcd::/32"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:2000:1234:abcd::"}, + }, + expectedError: "\"2000:1234:abcd::\" is not permitted", + }, + + // #33: An IPv6 permitted subtree doesn't affect DNS names. + { + roots: []constraintsSpec{ + { + ok: []string{"ip:2000:abcd::/32"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:2000:abcd::", "dns:foo.com"}, + }, + }, + + // #34: IPv6 exclusions don't affect unrelated addresses. + { + roots: []constraintsSpec{ + { + bad: []string{"ip:2000:abcd::/32"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:2000:1234::"}, + }, + }, + + // #35: IPv6 exclusions are effective. + { + roots: []constraintsSpec{ + { + bad: []string{"ip:2000:abcd::/32"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:2000:abcd::"}, + }, + expectedError: "\"2000:abcd::\" is excluded", + }, + + // #36: IPv6 constraints do not permit IPv4 addresses. + { + roots: []constraintsSpec{ + { + ok: []string{"ip:2000:abcd::/32"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:10.0.0.1"}, + }, + expectedError: "\"10.0.0.1\" is not permitted", + }, + + // #37: IPv4 constraints do not permit IPv6 addresses. + { + roots: []constraintsSpec{ + { + ok: []string{"ip:10.0.0.0/8"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:2000:abcd::"}, + }, + expectedError: "\"2000:abcd::\" is not permitted", + }, + + // #38: an exclusion of an unknown type doesn't affect other names. + { + roots: []constraintsSpec{ + { + bad: []string{"unknown:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #39: a permitted subtree of an unknown type doesn't affect other + // name types. + { + roots: []constraintsSpec{ + { + ok: []string{"unknown:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #40: exact email constraints work + { + roots: []constraintsSpec{ + { + ok: []string{"email:foo@example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:foo@example.com"}, + }, + }, + + // #41: exact email constraints are effective + { + roots: []constraintsSpec{ + { + ok: []string{"email:foo@example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:bar@example.com"}, + }, + expectedError: "\"bar@example.com\" is not permitted", + }, + + // #42: email canonicalisation works. + { + roots: []constraintsSpec{ + { + ok: []string{"email:foo@example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:\"\\f\\o\\o\"@example.com"}, + }, + noOpenSSL: true, // OpenSSL doesn't canonicalise email addresses before matching + }, + + // #43: limiting email addresses to a host works. + { + roots: []constraintsSpec{ + { + ok: []string{"email:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:foo@example.com"}, + }, + }, + + // #44: a leading dot matches hosts one level deep + { + roots: []constraintsSpec{ + { + ok: []string{"email:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:foo@sub.example.com"}, + }, + }, + + // #45: a leading dot does not match the host itself + { + roots: []constraintsSpec{ + { + ok: []string{"email:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:foo@example.com"}, + }, + expectedError: "\"foo@example.com\" is not permitted", + }, + + // #46: a leading dot also matches two (or more) levels deep. + { + roots: []constraintsSpec{ + { + ok: []string{"email:.example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:foo@sub.sub.example.com"}, + }, + }, + + // #47: the local part of an email is case-sensitive + { + roots: []constraintsSpec{ + { + ok: []string{"email:foo@example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:Foo@example.com"}, + }, + expectedError: "\"Foo@example.com\" is not permitted", + }, + + // #48: the domain part of an email is not case-sensitive + { + roots: []constraintsSpec{ + { + ok: []string{"email:foo@EXAMPLE.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:foo@example.com"}, + }, + }, + + // #49: the domain part of a DNS constraint is also not case-sensitive. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:EXAMPLE.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #50: URI constraints only cover the host part of the URI + { + roots: []constraintsSpec{ + { + ok: []string{"uri:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{ + "uri:http://example.com/bar", + "uri:http://example.com:8080/", + "uri:https://example.com/wibble#bar", + }, + }, + }, + + // #51: URIs with IPs are rejected + { + roots: []constraintsSpec{ + { + ok: []string{"uri:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:http://1.2.3.4/"}, + }, + expectedError: "URI with IP", + }, + + // #52: URIs with IPs and ports are rejected + { + roots: []constraintsSpec{ + { + ok: []string{"uri:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:http://1.2.3.4:43/"}, + }, + expectedError: "URI with IP", + }, + + // #53: URIs with IPv6 addresses are also rejected + { + roots: []constraintsSpec{ + { + ok: []string{"uri:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:http://[2006:abcd::1]/"}, + }, + expectedError: "URI with IP", + }, + + // #54: URIs with IPv6 addresses with ports are also rejected + { + roots: []constraintsSpec{ + { + ok: []string{"uri:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:http://[2006:abcd::1]:16/"}, + }, + expectedError: "URI with IP", + }, + + // #55: URI constraints are effective + { + roots: []constraintsSpec{ + { + ok: []string{"uri:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:http://bar.com/"}, + }, + expectedError: "\"http://bar.com/\" is not permitted", + }, + + // #56: URI constraints are effective + { + roots: []constraintsSpec{ + { + bad: []string{"uri:foo.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:http://foo.com/"}, + }, + expectedError: "\"http://foo.com/\" is excluded", + }, + + // #57: URI constraints can allow subdomains + { + roots: []constraintsSpec{ + { + ok: []string{"uri:.foo.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:http://www.foo.com/"}, + }, + }, + + // #58: excluding an IPv4-mapped-IPv6 address doesn't affect the IPv4 + // version of that address. + { + roots: []constraintsSpec{ + { + bad: []string{"ip:::ffff:1.2.3.4/128"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:1.2.3.4"}, + }, + }, + + // #59: a URI constraint isn't matched by a URN. + { + roots: []constraintsSpec{ + { + ok: []string{"uri:example.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:urn:example"}, + }, + expectedError: "URI with empty host", + }, + + // #60: excluding all IPv6 addresses doesn't exclude all IPv4 addresses + // too, even though IPv4 is mapped into the IPv6 range. + { + roots: []constraintsSpec{ + { + ok: []string{"ip:1.2.3.0/24"}, + bad: []string{"ip:::0/0"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"ip:1.2.3.4"}, + }, + }, + + // #61: omitting extended key usage in a CA certificate implies that + // any usage is ok. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth", "other"}, + }, + }, + + // #62: The “any” EKU also means that any usage is ok. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ekus: []string{"any"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth", "other"}, + }, + }, + + // #63: An intermediate with enumerated EKUs causes a failure if we + // test for an EKU not in that set. (ServerAuth is required by + // default.) + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ekus: []string{"email"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth"}, + }, + expectedError: "incompatible key usage", + }, + + // #64: an unknown EKU in the leaf doesn't break anything, even if it's not + // correctly nested. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ekus: []string{"email"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"other"}, + }, + requestedEKUs: []ExtKeyUsage{ExtKeyUsageAny}, + }, + + // #65: trying to add extra permitted key usages in an intermediate + // (after a limitation in the root) is acceptable so long as the leaf + // certificate doesn't use them. + { + roots: []constraintsSpec{ + { + ekus: []string{"serverAuth"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + { + ekus: []string{"serverAuth", "email"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth"}, + }, + }, + + // #66: EKUs in roots are not ignored. + { + roots: []constraintsSpec{ + { + ekus: []string{"email"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + { + ekus: []string{"serverAuth"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth"}, + }, + expectedError: "incompatible key usage", + }, + + // #67: in order to support COMODO chains, SGC key usages permit + // serverAuth and clientAuth. + { + roots: []constraintsSpec{ + {}, + }, + intermediates: [][]constraintsSpec{ + { + { + ekus: []string{"netscapeSGC"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth", "clientAuth"}, + }, + }, + + // #68: in order to support COMODO chains, SGC key usages permit + // serverAuth and clientAuth. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ekus: []string{"msSGC"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth", "clientAuth"}, + }, + }, + + // #69: an empty DNS constraint should allow anything. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + }, + + // #70: an empty DNS constraint should also reject everything. + { + roots: []constraintsSpec{ + { + bad: []string{"dns:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + }, + expectedError: "\"example.com\" is excluded", + }, + + // #71: an empty email constraint should allow anything + { + roots: []constraintsSpec{ + { + ok: []string{"email:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:foo@example.com"}, + }, + }, + + // #72: an empty email constraint should also reject everything. + { + roots: []constraintsSpec{ + { + bad: []string{"email:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:foo@example.com"}, + }, + expectedError: "\"foo@example.com\" is excluded", + }, + + // #73: an empty URI constraint should allow anything + { + roots: []constraintsSpec{ + { + ok: []string{"uri:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:https://example.com/test"}, + }, + }, + + // #74: an empty URI constraint should also reject everything. + { + roots: []constraintsSpec{ + { + bad: []string{"uri:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"uri:https://example.com/test"}, + }, + expectedError: "\"https://example.com/test\" is excluded", + }, + + // #75: serverAuth in a leaf shouldn't permit clientAuth when requested in + // VerifyOptions. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth"}, + }, + requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}, + expectedError: "incompatible key usage", + }, + + // #76: However, MSSGC in a leaf should match a request for serverAuth. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"msSGC"}, + }, + requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, + }, + + // An invalid DNS SAN should be detected only at validation time so + // that we can process CA certificates in the wild that have invalid SANs. + // See https://github.com/golang/go/issues/23995 + + // #77: an invalid DNS or mail SAN will not be detected if name constraint + // checking is not triggered. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:this is invalid", "email:this @ is invalid"}, + }, + }, + + // #78: an invalid DNS SAN will be detected if any name constraint checking + // is triggered. + { + roots: []constraintsSpec{ + { + bad: []string{"uri:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:this is invalid"}, + }, + expectedError: "cannot parse dnsName", + }, + + // #79: an invalid email SAN will be detected if any name constraint + // checking is triggered. + { + roots: []constraintsSpec{ + { + bad: []string{"uri:"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:this @ is invalid"}, + }, + expectedError: "cannot parse rfc822Name", + }, + + // #80: if several EKUs are requested, satisfying any of them is sufficient. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"email"}, + }, + requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection}, + }, + + // #81: EKUs that are not asserted in VerifyOpts are not required to be + // nested. + { + roots: make([]constraintsSpec, 1), + intermediates: [][]constraintsSpec{ + { + { + ekus: []string{"serverAuth"}, + }, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + // There's no email EKU in the intermediate. This would be rejected if + // full nesting was required. + ekus: []string{"email", "serverAuth"}, + }, + }, + + // #82: a certificate without SANs and CN is accepted in a constrained chain. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:foo.com", "dns:.foo.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{}, + }, + }, + + // #83: a certificate without SANs and with a CN that does not parse as a + // hostname is accepted in a constrained chain. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:foo.com", "dns:.foo.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{}, + cn: "foo,bar", + }, + }, + + // #84: a certificate with SANs and CN is accepted in a constrained chain. + { + roots: []constraintsSpec{ + { + ok: []string{"dns:foo.com", "dns:.foo.com"}, + }, + }, + intermediates: [][]constraintsSpec{ + { + {}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:foo.com"}, + cn: "foo.bar", + }, + }, +} + +func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { + var serialBytes [16]byte + rand.Read(serialBytes[:]) + + template := &Certificate{ + SerialNumber: new(big.Int).SetBytes(serialBytes[:]), + Subject: pkix.Name{ + CommonName: name, + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(2000, 0), + KeyUsage: KeyUsageCertSign, + BasicConstraintsValid: true, + IsCA: true, + } + + if err := addConstraintsToTemplate(constraints, template); err != nil { + return nil, err + } + + if parent == nil { + parent = template + } + derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey) + if err != nil { + return nil, err + } + + caCert, err := ParseCertificate(derBytes) + if err != nil { + return nil, err + } + + return caCert, nil +} + +func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { + var serialBytes [16]byte + rand.Read(serialBytes[:]) + + template := &Certificate{ + SerialNumber: new(big.Int).SetBytes(serialBytes[:]), + Subject: pkix.Name{ + OrganizationalUnit: []string{"Leaf"}, + CommonName: leaf.cn, + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(2000, 0), + KeyUsage: KeyUsageDigitalSignature, + BasicConstraintsValid: true, + IsCA: false, + } + + for _, name := range leaf.sans { + switch { + case strings.HasPrefix(name, "dns:"): + template.DNSNames = append(template.DNSNames, name[4:]) + + case strings.HasPrefix(name, "ip:"): + ip := net.ParseIP(name[3:]) + if ip == nil { + return nil, fmt.Errorf("cannot parse IP %q", name[3:]) + } + template.IPAddresses = append(template.IPAddresses, ip) + + case strings.HasPrefix(name, "invalidip:"): + ipBytes, err := hex.DecodeString(name[10:]) + if err != nil { + return nil, fmt.Errorf("cannot parse invalid IP: %s", err) + } + template.IPAddresses = append(template.IPAddresses, net.IP(ipBytes)) + + case strings.HasPrefix(name, "email:"): + template.EmailAddresses = append(template.EmailAddresses, name[6:]) + + case strings.HasPrefix(name, "uri:"): + uri, err := url.Parse(name[4:]) + if err != nil { + return nil, fmt.Errorf("cannot parse URI %q: %s", name[4:], err) + } + template.URIs = append(template.URIs, uri) + + case strings.HasPrefix(name, "unknown:"): + // This is a special case for testing unknown + // name types. A custom SAN extension is + // injected into the certificate. + if len(leaf.sans) != 1 { + panic("when using unknown name types, it must be the sole name") + } + + template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{ + Id: []int{2, 5, 29, 17}, + Value: []byte{ + 0x30, // SEQUENCE + 3, // three bytes + 9, // undefined GeneralName type 9 + 1, + 1, + }, + }) + + default: + return nil, fmt.Errorf("unknown name type %q", name) + } + } + + var err error + if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(leaf.ekus); err != nil { + return nil, err + } + + if parent == nil { + parent = template + } + + derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey) + if err != nil { + return nil, err + } + + return ParseCertificate(derBytes) +} + +func customConstraintsExtension(typeNum int, constraint []byte, isExcluded bool) pkix.Extension { + appendConstraint := func(contents []byte, tag uint8) []byte { + contents = append(contents, tag|32 /* constructed */ |0x80 /* context-specific */) + contents = append(contents, byte(4+len(constraint)) /* length */) + contents = append(contents, 0x30 /* SEQUENCE */) + contents = append(contents, byte(2+len(constraint)) /* length */) + contents = append(contents, byte(typeNum) /* GeneralName type */) + contents = append(contents, byte(len(constraint))) + return append(contents, constraint...) + } + + var contents []byte + if !isExcluded { + contents = appendConstraint(contents, 0 /* tag 0 for permitted */) + } else { + contents = appendConstraint(contents, 1 /* tag 1 for excluded */) + } + + var value []byte + value = append(value, 0x30 /* SEQUENCE */) + value = append(value, byte(len(contents))) + value = append(value, contents...) + + return pkix.Extension{ + Id: []int{2, 5, 29, 30}, + Value: value, + } +} + +func addConstraintsToTemplate(constraints constraintsSpec, template *Certificate) error { + parse := func(constraints []string) (dnsNames []string, ips []*net.IPNet, emailAddrs []string, uriDomains []string, err error) { + for _, constraint := range constraints { + switch { + case strings.HasPrefix(constraint, "dns:"): + dnsNames = append(dnsNames, constraint[4:]) + + case strings.HasPrefix(constraint, "ip:"): + _, ipNet, err := net.ParseCIDR(constraint[3:]) + if err != nil { + return nil, nil, nil, nil, err + } + ips = append(ips, ipNet) + + case strings.HasPrefix(constraint, "email:"): + emailAddrs = append(emailAddrs, constraint[6:]) + + case strings.HasPrefix(constraint, "uri:"): + uriDomains = append(uriDomains, constraint[4:]) + + default: + return nil, nil, nil, nil, fmt.Errorf("unknown constraint %q", constraint) + } + } + + return dnsNames, ips, emailAddrs, uriDomains, err + } + + handleSpecialConstraint := func(constraint string, isExcluded bool) bool { + switch { + case constraint == "unknown:": + template.ExtraExtensions = append(template.ExtraExtensions, customConstraintsExtension(9 /* undefined GeneralName type */, []byte{1}, isExcluded)) + + default: + return false + } + + return true + } + + if len(constraints.ok) == 1 && len(constraints.bad) == 0 { + if handleSpecialConstraint(constraints.ok[0], false) { + return nil + } + } + + if len(constraints.bad) == 1 && len(constraints.ok) == 0 { + if handleSpecialConstraint(constraints.bad[0], true) { + return nil + } + } + + var err error + template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains, err = parse(constraints.ok) + if err != nil { + return err + } + + template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains, err = parse(constraints.bad) + if err != nil { + return err + } + + if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(constraints.ekus); err != nil { + return err + } + + return nil +} + +func parseEKUs(ekuStrs []string) (ekus []ExtKeyUsage, unknowns []asn1.ObjectIdentifier, err error) { + for _, s := range ekuStrs { + switch s { + case "serverAuth": + ekus = append(ekus, ExtKeyUsageServerAuth) + case "clientAuth": + ekus = append(ekus, ExtKeyUsageClientAuth) + case "email": + ekus = append(ekus, ExtKeyUsageEmailProtection) + case "netscapeSGC": + ekus = append(ekus, ExtKeyUsageNetscapeServerGatedCrypto) + case "msSGC": + ekus = append(ekus, ExtKeyUsageMicrosoftServerGatedCrypto) + case "any": + ekus = append(ekus, ExtKeyUsageAny) + case "other": + unknowns = append(unknowns, asn1.ObjectIdentifier{2, 4, 1, 2, 3}) + default: + return nil, nil, fmt.Errorf("unknown EKU %q", s) + } + } + + return +} + +func TestConstraintCases(t *testing.T) { + privateKeys := sync.Pool{ + New: func() interface{} { + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(err) + } + return priv + }, + } + + for i, test := range nameConstraintsTests { + rootPool := NewCertPool() + rootKey := privateKeys.Get().(*ecdsa.PrivateKey) + rootName := "Root " + strconv.Itoa(i) + + // keys keeps track of all the private keys used in a given + // test and puts them back in the privateKeys pool at the end. + keys := []*ecdsa.PrivateKey{rootKey} + + // At each level (root, intermediate(s), leaf), parent points to + // an example parent certificate and parentKey the key for the + // parent level. Since all certificates at a given level have + // the same name and public key, any parent certificate is + // sufficient to get the correct issuer name and authority + // key ID. + var parent *Certificate + parentKey := rootKey + + for _, root := range test.roots { + rootCert, err := makeConstraintsCACert(root, rootName, rootKey, nil, rootKey) + if err != nil { + t.Fatalf("#%d: failed to create root: %s", i, err) + } + + parent = rootCert + rootPool.AddCert(rootCert) + } + + intermediatePool := NewCertPool() + + for level, intermediates := range test.intermediates { + levelKey := privateKeys.Get().(*ecdsa.PrivateKey) + keys = append(keys, levelKey) + levelName := "Intermediate level " + strconv.Itoa(level) + var last *Certificate + + for _, intermediate := range intermediates { + caCert, err := makeConstraintsCACert(intermediate, levelName, levelKey, parent, parentKey) + if err != nil { + t.Fatalf("#%d: failed to create %q: %s", i, levelName, err) + } + + last = caCert + intermediatePool.AddCert(caCert) + } + + parent = last + parentKey = levelKey + } + + leafKey := privateKeys.Get().(*ecdsa.PrivateKey) + keys = append(keys, leafKey) + + leafCert, err := makeConstraintsLeafCert(test.leaf, leafKey, parent, parentKey) + if err != nil { + t.Fatalf("#%d: cannot create leaf: %s", i, err) + } + + // Skip tests with CommonName set because OpenSSL will try to match it + // against name constraints, while we ignore it when it's not hostname-looking. + if !test.noOpenSSL && testNameConstraintsAgainstOpenSSL && test.leaf.cn == "" { + output, err := testChainAgainstOpenSSL(t, leafCert, intermediatePool, rootPool) + if err == nil && len(test.expectedError) > 0 { + t.Errorf("#%d: unexpectedly succeeded against OpenSSL", i) + if debugOpenSSLFailure { + return + } + } + + if err != nil { + if _, ok := err.(*exec.ExitError); !ok { + t.Errorf("#%d: OpenSSL failed to run: %s", i, err) + } else if len(test.expectedError) == 0 { + t.Errorf("#%d: OpenSSL unexpectedly failed: %v", i, output) + if debugOpenSSLFailure { + return + } + } + } + } + + verifyOpts := VerifyOptions{ + Roots: rootPool, + Intermediates: intermediatePool, + CurrentTime: time.Unix(1500, 0), + KeyUsages: test.requestedEKUs, + } + _, err = leafCert.Verify(verifyOpts) + + logInfo := true + if len(test.expectedError) == 0 { + if err != nil { + t.Errorf("#%d: unexpected failure: %s", i, err) + } else { + logInfo = false + } + } else { + if err == nil { + t.Errorf("#%d: unexpected success", i) + } else if !strings.Contains(err.Error(), test.expectedError) { + t.Errorf("#%d: expected error containing %q, but got: %s", i, test.expectedError, err) + } else { + logInfo = false + } + } + + if logInfo { + certAsPEM := func(cert *Certificate) string { + var buf bytes.Buffer + pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) + return buf.String() + } + t.Errorf("#%d: root:\n%s", i, certAsPEM(rootPool.mustCert(t, 0))) + t.Errorf("#%d: leaf:\n%s", i, certAsPEM(leafCert)) + } + + for _, key := range keys { + privateKeys.Put(key) + } + } +} + +func writePEMsToTempFile(certs []*Certificate) *os.File { + file, err := os.CreateTemp("", "name_constraints_test") + if err != nil { + panic("cannot create tempfile") + } + + pemBlock := &pem.Block{Type: "CERTIFICATE"} + for _, cert := range certs { + pemBlock.Bytes = cert.Raw + pem.Encode(file, pemBlock) + } + + return file +} + +func testChainAgainstOpenSSL(t *testing.T, leaf *Certificate, intermediates, roots *CertPool) (string, error) { + args := []string{"verify", "-no_check_time"} + + rootsFile := writePEMsToTempFile(allCerts(t, roots)) + if debugOpenSSLFailure { + println("roots file:", rootsFile.Name()) + } else { + defer os.Remove(rootsFile.Name()) + } + args = append(args, "-CAfile", rootsFile.Name()) + + if intermediates.len() > 0 { + intermediatesFile := writePEMsToTempFile(allCerts(t, intermediates)) + if debugOpenSSLFailure { + println("intermediates file:", intermediatesFile.Name()) + } else { + defer os.Remove(intermediatesFile.Name()) + } + args = append(args, "-untrusted", intermediatesFile.Name()) + } + + leafFile := writePEMsToTempFile([]*Certificate{leaf}) + if debugOpenSSLFailure { + println("leaf file:", leafFile.Name()) + } else { + defer os.Remove(leafFile.Name()) + } + args = append(args, leafFile.Name()) + + var output bytes.Buffer + cmd := exec.Command("openssl", args...) + cmd.Stdout = &output + cmd.Stderr = &output + + err := cmd.Run() + return output.String(), err +} + +var rfc2821Tests = []struct { + in string + localPart, domain string +}{ + {"foo@example.com", "foo", "example.com"}, + {"@example.com", "", ""}, + {"\"@example.com", "", ""}, + {"\"\"@example.com", "", "example.com"}, + {"\"a\"@example.com", "a", "example.com"}, + {"\"\\a\"@example.com", "a", "example.com"}, + {"a\"@example.com", "", ""}, + {"foo..bar@example.com", "", ""}, + {".foo.bar@example.com", "", ""}, + {"foo.bar.@example.com", "", ""}, + {"|{}?'@example.com", "|{}?'", "example.com"}, + + // Examples from RFC 3696 + {"Abc\\@def@example.com", "Abc@def", "example.com"}, + {"Fred\\ Bloggs@example.com", "Fred Bloggs", "example.com"}, + {"Joe.\\\\Blow@example.com", "Joe.\\Blow", "example.com"}, + {"\"Abc@def\"@example.com", "Abc@def", "example.com"}, + {"\"Fred Bloggs\"@example.com", "Fred Bloggs", "example.com"}, + {"customer/department=shipping@example.com", "customer/department=shipping", "example.com"}, + {"$A12345@example.com", "$A12345", "example.com"}, + {"!def!xyz%abc@example.com", "!def!xyz%abc", "example.com"}, + {"_somename@example.com", "_somename", "example.com"}, +} + +func TestRFC2821Parsing(t *testing.T) { + for i, test := range rfc2821Tests { + mailbox, ok := parseRFC2821Mailbox(test.in) + expectedFailure := len(test.localPart) == 0 && len(test.domain) == 0 + + if ok && expectedFailure { + t.Errorf("#%d: %q unexpectedly parsed as (%q, %q)", i, test.in, mailbox.local, mailbox.domain) + continue + } + + if !ok && !expectedFailure { + t.Errorf("#%d: unexpected failure for %q", i, test.in) + continue + } + + if !ok { + continue + } + + if mailbox.local != test.localPart || mailbox.domain != test.domain { + t.Errorf("#%d: %q parsed as (%q, %q), but wanted (%q, %q)", i, test.in, mailbox.local, mailbox.domain, test.localPart, test.domain) + } + } +} + +func TestBadNamesInConstraints(t *testing.T) { + constraintParseError := func(err error) bool { + str := err.Error() + return strings.Contains(str, "failed to parse ") && strings.Contains(str, "constraint") + } + + encodingError := func(err error) bool { + return strings.Contains(err.Error(), "cannot be encoded as an IA5String") + } + + // Bad names in constraints should not parse. + badNames := []struct { + name string + matcher func(error) bool + }{ + {"dns:foo.com.", constraintParseError}, + {"email:abc@foo.com.", constraintParseError}, + {"email:foo.com.", constraintParseError}, + {"uri:example.com.", constraintParseError}, + {"uri:1.2.3.4", constraintParseError}, + {"uri:ffff::1", constraintParseError}, + {"dns:not–hyphen.com", encodingError}, + {"email:foo@not–hyphen.com", encodingError}, + {"uri:not–hyphen.com", encodingError}, + } + + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(err) + } + + for _, test := range badNames { + _, err := makeConstraintsCACert(constraintsSpec{ + ok: []string{test.name}, + }, "TestAbsoluteNamesInConstraints", priv, nil, priv) + + if err == nil { + t.Errorf("bad name %q unexpectedly accepted in name constraint", test.name) + continue + } else { + if !test.matcher(err) { + t.Errorf("bad name %q triggered unrecognised error: %s", test.name, err) + } + } + } +} + +func TestBadNamesInSANs(t *testing.T) { + // Bad names in URI and IP SANs should not parse. Bad DNS and email SANs + // will parse and are tested in name constraint tests at the top of this + // file. + badNames := []string{ + "uri:https://example.com./dsf", + "invalidip:0102", + "invalidip:0102030405", + } + + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(err) + } + + for _, badName := range badNames { + _, err := makeConstraintsLeafCert(leafSpec{sans: []string{badName}}, priv, nil, priv) + + if err == nil { + t.Errorf("bad name %q unexpectedly accepted in SAN", badName) + continue + } + + if str := err.Error(); !strings.Contains(str, "cannot parse ") { + t.Errorf("bad name %q triggered unrecognised error: %s", badName, str) + } + } +} diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go new file mode 100644 index 0000000..635e74b --- /dev/null +++ b/src/crypto/x509/parser.go @@ -0,0 +1,1013 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package x509 + +import ( + "bytes" + "crypto/dsa" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rsa" + "crypto/x509/pkix" + "encoding/asn1" + "errors" + "fmt" + "math/big" + "net" + "net/url" + "strconv" + "strings" + "time" + "unicode/utf16" + "unicode/utf8" + + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" +) + +// isPrintable reports whether the given b is in the ASN.1 PrintableString set. +// This is a simplified version of encoding/asn1.isPrintable. +func isPrintable(b byte) bool { + return 'a' <= b && b <= 'z' || + 'A' <= b && b <= 'Z' || + '0' <= b && b <= '9' || + '\'' <= b && b <= ')' || + '+' <= b && b <= '/' || + b == ' ' || + b == ':' || + b == '=' || + b == '?' || + // This is technically not allowed in a PrintableString. + // However, x509 certificates with wildcard strings don't + // always use the correct string type so we permit it. + b == '*' || + // This is not technically allowed either. However, not + // only is it relatively common, but there are also a + // handful of CA certificates that contain it. At least + // one of which will not expire until 2027. + b == '&' +} + +// parseASN1String parses the ASN.1 string types T61String, PrintableString, +// UTF8String, BMPString, IA5String, and NumericString. This is mostly copied +// from the respective encoding/asn1.parse... methods, rather than just +// increasing the API surface of that package. +func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) { + switch tag { + case cryptobyte_asn1.T61String: + return string(value), nil + case cryptobyte_asn1.PrintableString: + for _, b := range value { + if !isPrintable(b) { + return "", errors.New("invalid PrintableString") + } + } + return string(value), nil + case cryptobyte_asn1.UTF8String: + if !utf8.Valid(value) { + return "", errors.New("invalid UTF-8 string") + } + return string(value), nil + case cryptobyte_asn1.Tag(asn1.TagBMPString): + if len(value)%2 != 0 { + return "", errors.New("invalid BMPString") + } + + // Strip terminator if present. + if l := len(value); l >= 2 && value[l-1] == 0 && value[l-2] == 0 { + value = value[:l-2] + } + + s := make([]uint16, 0, len(value)/2) + for len(value) > 0 { + s = append(s, uint16(value[0])<<8+uint16(value[1])) + value = value[2:] + } + + return string(utf16.Decode(s)), nil + case cryptobyte_asn1.IA5String: + s := string(value) + if isIA5String(s) != nil { + return "", errors.New("invalid IA5String") + } + return s, nil + case cryptobyte_asn1.Tag(asn1.TagNumericString): + for _, b := range value { + if !('0' <= b && b <= '9' || b == ' ') { + return "", errors.New("invalid NumericString") + } + } + return string(value), nil + } + return "", fmt.Errorf("unsupported string type: %v", tag) +} + +// parseName parses a DER encoded Name as defined in RFC 5280. We may +// want to export this function in the future for use in crypto/tls. +func parseName(raw cryptobyte.String) (*pkix.RDNSequence, error) { + if !raw.ReadASN1(&raw, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid RDNSequence") + } + + var rdnSeq pkix.RDNSequence + for !raw.Empty() { + var rdnSet pkix.RelativeDistinguishedNameSET + var set cryptobyte.String + if !raw.ReadASN1(&set, cryptobyte_asn1.SET) { + return nil, errors.New("x509: invalid RDNSequence") + } + for !set.Empty() { + var atav cryptobyte.String + if !set.ReadASN1(&atav, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid RDNSequence: invalid attribute") + } + var attr pkix.AttributeTypeAndValue + if !atav.ReadASN1ObjectIdentifier(&attr.Type) { + return nil, errors.New("x509: invalid RDNSequence: invalid attribute type") + } + var rawValue cryptobyte.String + var valueTag cryptobyte_asn1.Tag + if !atav.ReadAnyASN1(&rawValue, &valueTag) { + return nil, errors.New("x509: invalid RDNSequence: invalid attribute value") + } + var err error + attr.Value, err = parseASN1String(valueTag, rawValue) + if err != nil { + return nil, fmt.Errorf("x509: invalid RDNSequence: invalid attribute value: %s", err) + } + rdnSet = append(rdnSet, attr) + } + + rdnSeq = append(rdnSeq, rdnSet) + } + + return &rdnSeq, nil +} + +func parseAI(der cryptobyte.String) (pkix.AlgorithmIdentifier, error) { + ai := pkix.AlgorithmIdentifier{} + if !der.ReadASN1ObjectIdentifier(&ai.Algorithm) { + return ai, errors.New("x509: malformed OID") + } + if der.Empty() { + return ai, nil + } + var params cryptobyte.String + var tag cryptobyte_asn1.Tag + if !der.ReadAnyASN1Element(¶ms, &tag) { + return ai, errors.New("x509: malformed parameters") + } + ai.Parameters.Tag = int(tag) + ai.Parameters.FullBytes = params + return ai, nil +} + +func parseValidity(der cryptobyte.String) (time.Time, time.Time, error) { + extract := func() (time.Time, error) { + var t time.Time + switch { + case der.PeekASN1Tag(cryptobyte_asn1.UTCTime): + // TODO(rolandshoemaker): once #45411 is fixed, the following code + // should be replaced with a call to der.ReadASN1UTCTime. + var utc cryptobyte.String + if !der.ReadASN1(&utc, cryptobyte_asn1.UTCTime) { + return t, errors.New("x509: malformed UTCTime") + } + s := string(utc) + + formatStr := "0601021504Z0700" + var err error + t, err = time.Parse(formatStr, s) + if err != nil { + formatStr = "060102150405Z0700" + t, err = time.Parse(formatStr, s) + } + if err != nil { + return t, err + } + + if serialized := t.Format(formatStr); serialized != s { + return t, errors.New("x509: malformed UTCTime") + } + + if t.Year() >= 2050 { + // UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 + t = t.AddDate(-100, 0, 0) + } + case der.PeekASN1Tag(cryptobyte_asn1.GeneralizedTime): + if !der.ReadASN1GeneralizedTime(&t) { + return t, errors.New("x509: malformed GeneralizedTime") + } + default: + return t, errors.New("x509: unsupported time format") + } + return t, nil + } + + notBefore, err := extract() + if err != nil { + return time.Time{}, time.Time{}, err + } + notAfter, err := extract() + if err != nil { + return time.Time{}, time.Time{}, err + } + + return notBefore, notAfter, nil +} + +func parseExtension(der cryptobyte.String) (pkix.Extension, error) { + var ext pkix.Extension + if !der.ReadASN1ObjectIdentifier(&ext.Id) { + return ext, errors.New("x509: malformed extention OID field") + } + if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) { + if !der.ReadASN1Boolean(&ext.Critical) { + return ext, errors.New("x509: malformed extention critical field") + } + } + var val cryptobyte.String + if !der.ReadASN1(&val, cryptobyte_asn1.OCTET_STRING) { + return ext, errors.New("x509: malformed extention value field") + } + ext.Value = val + return ext, nil +} + +func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) { + der := cryptobyte.String(keyData.PublicKey.RightAlign()) + switch algo { + case RSA: + // RSA public keys must have a NULL in the parameters. + // See RFC 3279, Section 2.3.1. + if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1.NullBytes) { + return nil, errors.New("x509: RSA key missing NULL parameters") + } + + p := &pkcs1PublicKey{N: new(big.Int)} + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid RSA public key") + } + if !der.ReadASN1Integer(p.N) { + return nil, errors.New("x509: invalid RSA modulus") + } + if !der.ReadASN1Integer(&p.E) { + return nil, errors.New("x509: invalid RSA public exponent") + } + + if p.N.Sign() <= 0 { + return nil, errors.New("x509: RSA modulus is not a positive number") + } + if p.E <= 0 { + return nil, errors.New("x509: RSA public exponent is not a positive number") + } + + pub := &rsa.PublicKey{ + E: p.E, + N: p.N, + } + return pub, nil + case ECDSA: + paramsDer := cryptobyte.String(keyData.Algorithm.Parameters.FullBytes) + namedCurveOID := new(asn1.ObjectIdentifier) + if !paramsDer.ReadASN1ObjectIdentifier(namedCurveOID) { + return nil, errors.New("x509: invalid ECDSA parameters") + } + namedCurve := namedCurveFromOID(*namedCurveOID) + if namedCurve == nil { + return nil, errors.New("x509: unsupported elliptic curve") + } + x, y := elliptic.Unmarshal(namedCurve, der) + if x == nil { + return nil, errors.New("x509: failed to unmarshal elliptic curve point") + } + pub := &ecdsa.PublicKey{ + Curve: namedCurve, + X: x, + Y: y, + } + return pub, nil + case Ed25519: + // RFC 8410, Section 3 + // > For all of the OIDs, the parameters MUST be absent. + if len(keyData.Algorithm.Parameters.FullBytes) != 0 { + return nil, errors.New("x509: Ed25519 key encoded with illegal parameters") + } + if len(der) != ed25519.PublicKeySize { + return nil, errors.New("x509: wrong Ed25519 public key size") + } + return ed25519.PublicKey(der), nil + case DSA: + y := new(big.Int) + if !der.ReadASN1Integer(y) { + return nil, errors.New("x509: invalid DSA public key") + } + pub := &dsa.PublicKey{ + Y: y, + Parameters: dsa.Parameters{ + P: new(big.Int), + Q: new(big.Int), + G: new(big.Int), + }, + } + paramsDer := cryptobyte.String(keyData.Algorithm.Parameters.FullBytes) + if !paramsDer.ReadASN1(¶msDer, cryptobyte_asn1.SEQUENCE) || + !paramsDer.ReadASN1Integer(pub.Parameters.P) || + !paramsDer.ReadASN1Integer(pub.Parameters.Q) || + !paramsDer.ReadASN1Integer(pub.Parameters.G) { + return nil, errors.New("x509: invalid DSA parameters") + } + if pub.Y.Sign() <= 0 || pub.Parameters.P.Sign() <= 0 || + pub.Parameters.Q.Sign() <= 0 || pub.Parameters.G.Sign() <= 0 { + return nil, errors.New("x509: zero or negative DSA parameter") + } + return pub, nil + default: + return nil, nil + } +} + +func parseKeyUsageExtension(der cryptobyte.String) (KeyUsage, error) { + var usageBits asn1.BitString + if !der.ReadASN1BitString(&usageBits) { + return 0, errors.New("x509: invalid key usage") + } + + var usage int + for i := 0; i < 9; i++ { + if usageBits.At(i) != 0 { + usage |= 1 << uint(i) + } + } + return KeyUsage(usage), nil +} + +func parseBasicConstraintsExtension(der cryptobyte.String) (bool, int, error) { + var isCA bool + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return false, 0, errors.New("x509: invalid basic constraints a") + } + if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) { + if !der.ReadASN1Boolean(&isCA) { + return false, 0, errors.New("x509: invalid basic constraints b") + } + } + maxPathLen := -1 + if !der.Empty() && der.PeekASN1Tag(cryptobyte_asn1.INTEGER) { + if !der.ReadASN1Integer(&maxPathLen) { + return false, 0, errors.New("x509: invalid basic constraints c") + } + } + + // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285) + return isCA, maxPathLen, nil +} + +func forEachSAN(der cryptobyte.String, callback func(tag int, data []byte) error) error { + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid subject alternative names") + } + for !der.Empty() { + var san cryptobyte.String + var tag cryptobyte_asn1.Tag + if !der.ReadAnyASN1(&san, &tag) { + return errors.New("x509: invalid subject alternative name") + } + if err := callback(int(tag^0x80), san); err != nil { + return err + } + } + + return nil +} + +func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL, err error) { + err = forEachSAN(der, func(tag int, data []byte) error { + switch tag { + case nameTypeEmail: + email := string(data) + if err := isIA5String(email); err != nil { + return errors.New("x509: SAN rfc822Name is malformed") + } + emailAddresses = append(emailAddresses, email) + case nameTypeDNS: + name := string(data) + if err := isIA5String(name); err != nil { + return errors.New("x509: SAN dNSName is malformed") + } + dnsNames = append(dnsNames, string(name)) + case nameTypeURI: + uriStr := string(data) + if err := isIA5String(uriStr); err != nil { + return errors.New("x509: SAN uniformResourceIdentifier is malformed") + } + uri, err := url.Parse(uriStr) + if err != nil { + return fmt.Errorf("x509: cannot parse URI %q: %s", uriStr, err) + } + if len(uri.Host) > 0 { + if _, ok := domainToReverseLabels(uri.Host); !ok { + return fmt.Errorf("x509: cannot parse URI %q: invalid domain", uriStr) + } + } + uris = append(uris, uri) + case nameTypeIP: + switch len(data) { + case net.IPv4len, net.IPv6len: + ipAddresses = append(ipAddresses, data) + default: + return errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len(data))) + } + } + + return nil + }) + + return +} + +func parseExtKeyUsageExtension(der cryptobyte.String) ([]ExtKeyUsage, []asn1.ObjectIdentifier, error) { + var extKeyUsages []ExtKeyUsage + var unknownUsages []asn1.ObjectIdentifier + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return nil, nil, errors.New("x509: invalid extended key usages") + } + for !der.Empty() { + var eku asn1.ObjectIdentifier + if !der.ReadASN1ObjectIdentifier(&eku) { + return nil, nil, errors.New("x509: invalid extended key usages") + } + if extKeyUsage, ok := extKeyUsageFromOID(eku); ok { + extKeyUsages = append(extKeyUsages, extKeyUsage) + } else { + unknownUsages = append(unknownUsages, eku) + } + } + return extKeyUsages, unknownUsages, nil +} + +func parseCertificatePoliciesExtension(der cryptobyte.String) ([]asn1.ObjectIdentifier, error) { + var oids []asn1.ObjectIdentifier + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid certificate policies") + } + for !der.Empty() { + var cp cryptobyte.String + if !der.ReadASN1(&cp, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid certificate policies") + } + var oid asn1.ObjectIdentifier + if !cp.ReadASN1ObjectIdentifier(&oid) { + return nil, errors.New("x509: invalid certificate policies") + } + oids = append(oids, oid) + } + + return oids, nil +} + +// isValidIPMask reports whether mask consists of zero or more 1 bits, followed by zero bits. +func isValidIPMask(mask []byte) bool { + seenZero := false + + for _, b := range mask { + if seenZero { + if b != 0 { + return false + } + + continue + } + + switch b { + case 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe: + seenZero = true + case 0xff: + default: + return false + } + } + + return true +} + +func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandled bool, err error) { + // RFC 5280, 4.2.1.10 + + // NameConstraints ::= SEQUENCE { + // permittedSubtrees [0] GeneralSubtrees OPTIONAL, + // excludedSubtrees [1] GeneralSubtrees OPTIONAL } + // + // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree + // + // GeneralSubtree ::= SEQUENCE { + // base GeneralName, + // minimum [0] BaseDistance DEFAULT 0, + // maximum [1] BaseDistance OPTIONAL } + // + // BaseDistance ::= INTEGER (0..MAX) + + outer := cryptobyte.String(e.Value) + var toplevel, permitted, excluded cryptobyte.String + var havePermitted, haveExcluded bool + if !outer.ReadASN1(&toplevel, cryptobyte_asn1.SEQUENCE) || + !outer.Empty() || + !toplevel.ReadOptionalASN1(&permitted, &havePermitted, cryptobyte_asn1.Tag(0).ContextSpecific().Constructed()) || + !toplevel.ReadOptionalASN1(&excluded, &haveExcluded, cryptobyte_asn1.Tag(1).ContextSpecific().Constructed()) || + !toplevel.Empty() { + return false, errors.New("x509: invalid NameConstraints extension") + } + + if !havePermitted && !haveExcluded || len(permitted) == 0 && len(excluded) == 0 { + // From RFC 5280, Section 4.2.1.10: + // “either the permittedSubtrees field + // or the excludedSubtrees MUST be + // present” + return false, errors.New("x509: empty name constraints extension") + } + + getValues := func(subtrees cryptobyte.String) (dnsNames []string, ips []*net.IPNet, emails, uriDomains []string, err error) { + for !subtrees.Empty() { + var seq, value cryptobyte.String + var tag cryptobyte_asn1.Tag + if !subtrees.ReadASN1(&seq, cryptobyte_asn1.SEQUENCE) || + !seq.ReadAnyASN1(&value, &tag) { + return nil, nil, nil, nil, fmt.Errorf("x509: invalid NameConstraints extension") + } + + var ( + dnsTag = cryptobyte_asn1.Tag(2).ContextSpecific() + emailTag = cryptobyte_asn1.Tag(1).ContextSpecific() + ipTag = cryptobyte_asn1.Tag(7).ContextSpecific() + uriTag = cryptobyte_asn1.Tag(6).ContextSpecific() + ) + + switch tag { + case dnsTag: + domain := string(value) + if err := isIA5String(domain); err != nil { + return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) + } + + trimmedDomain := domain + if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' { + // constraints can have a leading + // period to exclude the domain + // itself, but that's not valid in a + // normal domain name. + trimmedDomain = trimmedDomain[1:] + } + if _, ok := domainToReverseLabels(trimmedDomain); !ok { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain) + } + dnsNames = append(dnsNames, domain) + + case ipTag: + l := len(value) + var ip, mask []byte + + switch l { + case 8: + ip = value[:4] + mask = value[4:] + + case 32: + ip = value[:16] + mask = value[16:] + + default: + return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained value of length %d", l) + } + + if !isValidIPMask(mask) { + return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained invalid mask %x", mask) + } + + ips = append(ips, &net.IPNet{IP: net.IP(ip), Mask: net.IPMask(mask)}) + + case emailTag: + constraint := string(value) + if err := isIA5String(constraint); err != nil { + return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) + } + + // If the constraint contains an @ then + // it specifies an exact mailbox name. + if strings.Contains(constraint, "@") { + if _, ok := parseRFC2821Mailbox(constraint); !ok { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) + } + } else { + // Otherwise it's a domain name. + domain := constraint + if len(domain) > 0 && domain[0] == '.' { + domain = domain[1:] + } + if _, ok := domainToReverseLabels(domain); !ok { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) + } + } + emails = append(emails, constraint) + + case uriTag: + domain := string(value) + if err := isIA5String(domain); err != nil { + return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) + } + + if net.ParseIP(domain) != nil { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain) + } + + trimmedDomain := domain + if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' { + // constraints can have a leading + // period to exclude the domain itself, + // but that's not valid in a normal + // domain name. + trimmedDomain = trimmedDomain[1:] + } + if _, ok := domainToReverseLabels(trimmedDomain); !ok { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain) + } + uriDomains = append(uriDomains, domain) + + default: + unhandled = true + } + } + + return dnsNames, ips, emails, uriDomains, nil + } + + if out.PermittedDNSDomains, out.PermittedIPRanges, out.PermittedEmailAddresses, out.PermittedURIDomains, err = getValues(permitted); err != nil { + return false, err + } + if out.ExcludedDNSDomains, out.ExcludedIPRanges, out.ExcludedEmailAddresses, out.ExcludedURIDomains, err = getValues(excluded); err != nil { + return false, err + } + out.PermittedDNSDomainsCritical = e.Critical + + return unhandled, nil +} + +func processExtensions(out *Certificate) error { + var err error + for _, e := range out.Extensions { + unhandled := false + + if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { + switch e.Id[3] { + case 15: + out.KeyUsage, err = parseKeyUsageExtension(e.Value) + if err != nil { + return err + } + case 19: + out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(e.Value) + if err != nil { + return err + } + out.BasicConstraintsValid = true + out.MaxPathLenZero = out.MaxPathLen == 0 + case 17: + out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(e.Value) + if err != nil { + return err + } + + if len(out.DNSNames) == 0 && len(out.EmailAddresses) == 0 && len(out.IPAddresses) == 0 && len(out.URIs) == 0 { + // If we didn't parse anything then we do the critical check, below. + unhandled = true + } + + case 30: + unhandled, err = parseNameConstraintsExtension(out, e) + if err != nil { + return err + } + + case 31: + // RFC 5280, 4.2.1.13 + + // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + // + // DistributionPoint ::= SEQUENCE { + // distributionPoint [0] DistributionPointName OPTIONAL, + // reasons [1] ReasonFlags OPTIONAL, + // cRLIssuer [2] GeneralNames OPTIONAL } + // + // DistributionPointName ::= CHOICE { + // fullName [0] GeneralNames, + // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + val := cryptobyte.String(e.Value) + if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid CRL distribution points") + } + for !val.Empty() { + var dpDER cryptobyte.String + if !val.ReadASN1(&dpDER, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid CRL distribution point") + } + var dpNameDER cryptobyte.String + var dpNamePresent bool + if !dpDER.ReadOptionalASN1(&dpNameDER, &dpNamePresent, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { + return errors.New("x509: invalid CRL distribution point") + } + if !dpNamePresent { + continue + } + if !dpNameDER.ReadASN1(&dpNameDER, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { + return errors.New("x509: invalid CRL distribution point") + } + for !dpNameDER.Empty() { + if !dpNameDER.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) { + break + } + var uri cryptobyte.String + if !dpNameDER.ReadASN1(&uri, cryptobyte_asn1.Tag(6).ContextSpecific()) { + return errors.New("x509: invalid CRL distribution point") + } + out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(uri)) + } + } + + case 35: + // RFC 5280, 4.2.1.1 + val := cryptobyte.String(e.Value) + var akid cryptobyte.String + if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid authority key identifier") + } + if akid.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) { + if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) { + return errors.New("x509: invalid authority key identifier") + } + out.AuthorityKeyId = akid + } + case 37: + out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value) + if err != nil { + return err + } + case 14: + // RFC 5280, 4.2.1.2 + val := cryptobyte.String(e.Value) + var skid cryptobyte.String + if !val.ReadASN1(&skid, cryptobyte_asn1.OCTET_STRING) { + return errors.New("x509: invalid subject key identifier") + } + out.SubjectKeyId = skid + case 32: + out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(e.Value) + if err != nil { + return err + } + default: + // Unknown extensions are recorded if critical. + unhandled = true + } + } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) { + // RFC 5280 4.2.2.1: Authority Information Access + val := cryptobyte.String(e.Value) + if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid authority info access") + } + for !val.Empty() { + var aiaDER cryptobyte.String + if !val.ReadASN1(&aiaDER, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid authority info access") + } + var method asn1.ObjectIdentifier + if !aiaDER.ReadASN1ObjectIdentifier(&method) { + return errors.New("x509: invalid authority info access") + } + if !aiaDER.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) { + continue + } + if !aiaDER.ReadASN1(&aiaDER, cryptobyte_asn1.Tag(6).ContextSpecific()) { + return errors.New("x509: invalid authority info access") + } + switch { + case method.Equal(oidAuthorityInfoAccessOcsp): + out.OCSPServer = append(out.OCSPServer, string(aiaDER)) + case method.Equal(oidAuthorityInfoAccessIssuers): + out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(aiaDER)) + } + } + } else { + // Unknown extensions are recorded if critical. + unhandled = true + } + + if e.Critical && unhandled { + out.UnhandledCriticalExtensions = append(out.UnhandledCriticalExtensions, e.Id) + } + } + + return nil +} + +func parseCertificate(der []byte) (*Certificate, error) { + cert := &Certificate{} + + input := cryptobyte.String(der) + // we read the SEQUENCE including length and tag bytes so that + // we can populate Certificate.Raw, before unwrapping the + // SEQUENCE so it can be operated on + if !input.ReadASN1Element(&input, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed certificate") + } + cert.Raw = input + if !input.ReadASN1(&input, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed certificate") + } + + var tbs cryptobyte.String + // do the same trick again as above to extract the raw + // bytes for Certificate.RawTBSCertificate + if !input.ReadASN1Element(&tbs, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed tbs certificate") + } + cert.RawTBSCertificate = tbs + if !tbs.ReadASN1(&tbs, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed tbs certificate") + } + + if !tbs.ReadOptionalASN1Integer(&cert.Version, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific(), 0) { + return nil, errors.New("x509: malformed version") + } + if cert.Version < 0 { + return nil, errors.New("x509: malformed version") + } + // for backwards compat reasons Version is one-indexed, + // rather than zero-indexed as defined in 5280 + cert.Version++ + if cert.Version > 3 { + return nil, errors.New("x509: invalid version") + } + + serial := new(big.Int) + if !tbs.ReadASN1Integer(serial) { + return nil, errors.New("x509: malformed serial number") + } + // we ignore the presence of negative serial numbers because + // of their prevalence, despite them being invalid + // TODO(rolandshoemaker): revist this decision, there are currently + // only 10 trusted certificates with negative serial numbers + // according to censys.io. + cert.SerialNumber = serial + + var sigAISeq cryptobyte.String + if !tbs.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed signature algorithm identifier") + } + // Before parsing the inner algorithm identifier, extract + // the outer algorithm identifier and make sure that they + // match. + var outerSigAISeq cryptobyte.String + if !input.ReadASN1(&outerSigAISeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed algorithm identifier") + } + if !bytes.Equal(outerSigAISeq, sigAISeq) { + return nil, errors.New("x509: inner and outer signature algorithm identifiers don't match") + } + sigAI, err := parseAI(sigAISeq) + if err != nil { + return nil, err + } + cert.SignatureAlgorithm = getSignatureAlgorithmFromAI(sigAI) + + var issuerSeq cryptobyte.String + if !tbs.ReadASN1Element(&issuerSeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed issuer") + } + cert.RawIssuer = issuerSeq + issuerRDNs, err := parseName(issuerSeq) + if err != nil { + return nil, err + } + cert.Issuer.FillFromRDNSequence(issuerRDNs) + + var validity cryptobyte.String + if !tbs.ReadASN1(&validity, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed validity") + } + cert.NotBefore, cert.NotAfter, err = parseValidity(validity) + if err != nil { + return nil, err + } + + var subjectSeq cryptobyte.String + if !tbs.ReadASN1Element(&subjectSeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed issuer") + } + cert.RawSubject = subjectSeq + subjectRDNs, err := parseName(subjectSeq) + if err != nil { + return nil, err + } + cert.Subject.FillFromRDNSequence(subjectRDNs) + + var spki cryptobyte.String + if !tbs.ReadASN1Element(&spki, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed spki") + } + cert.RawSubjectPublicKeyInfo = spki + if !spki.ReadASN1(&spki, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed spki") + } + var pkAISeq cryptobyte.String + if !spki.ReadASN1(&pkAISeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed public key algorithm identifier") + } + pkAI, err := parseAI(pkAISeq) + if err != nil { + return nil, err + } + cert.PublicKeyAlgorithm = getPublicKeyAlgorithmFromOID(pkAI.Algorithm) + var spk asn1.BitString + if !spki.ReadASN1BitString(&spk) { + return nil, errors.New("x509: malformed subjectPublicKey") + } + cert.PublicKey, err = parsePublicKey(cert.PublicKeyAlgorithm, &publicKeyInfo{ + Algorithm: pkAI, + PublicKey: spk, + }) + if err != nil { + return nil, err + } + + if cert.Version > 1 { + if !tbs.SkipOptionalASN1(cryptobyte_asn1.Tag(1).ContextSpecific()) { + return nil, errors.New("x509: malformed issuerUniqueID") + } + if !tbs.SkipOptionalASN1(cryptobyte_asn1.Tag(2).ContextSpecific()) { + return nil, errors.New("x509: malformed subjectUniqueID") + } + if cert.Version == 3 { + var extensions cryptobyte.String + var present bool + if !tbs.ReadOptionalASN1(&extensions, &present, cryptobyte_asn1.Tag(3).Constructed().ContextSpecific()) { + return nil, errors.New("x509: malformed extensions") + } + if present { + if !extensions.ReadASN1(&extensions, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed extensions") + } + for !extensions.Empty() { + var extension cryptobyte.String + if !extensions.ReadASN1(&extension, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed extension") + } + ext, err := parseExtension(extension) + if err != nil { + return nil, err + } + cert.Extensions = append(cert.Extensions, ext) + } + err = processExtensions(cert) + if err != nil { + return nil, err + } + } + } + } + + var signature asn1.BitString + if !input.ReadASN1BitString(&signature) { + return nil, errors.New("x509: malformed signature") + } + cert.Signature = signature.RightAlign() + + return cert, nil +} + +// ParseCertificate parses a single certificate from the given ASN.1 DER data. +func ParseCertificate(der []byte) (*Certificate, error) { + cert, err := parseCertificate(der) + if err != nil { + return nil, err + } + if len(der) != len(cert.Raw) { + return nil, errors.New("x509: trailing data") + } + return cert, err +} + +// ParseCertificates parses one or more certificates from the given ASN.1 DER +// data. The certificates must be concatenated with no intermediate padding. +func ParseCertificates(der []byte) ([]*Certificate, error) { + var certs []*Certificate + for len(der) > 0 { + cert, err := parseCertificate(der) + if err != nil { + return nil, err + } + certs = append(certs, cert) + der = der[len(cert.Raw):] + } + return certs, nil +} diff --git a/src/crypto/x509/parser_test.go b/src/crypto/x509/parser_test.go new file mode 100644 index 0000000..d7cf7ea --- /dev/null +++ b/src/crypto/x509/parser_test.go @@ -0,0 +1,102 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package x509 + +import ( + "encoding/asn1" + "testing" + + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" +) + +func TestParseASN1String(t *testing.T) { + tests := []struct { + name string + tag cryptobyte_asn1.Tag + value []byte + expected string + expectedErr string + }{ + { + name: "T61String", + tag: cryptobyte_asn1.T61String, + value: []byte{80, 81, 82}, + expected: string("PQR"), + }, + { + name: "PrintableString", + tag: cryptobyte_asn1.PrintableString, + value: []byte{80, 81, 82}, + expected: string("PQR"), + }, + { + name: "PrintableString (invalid)", + tag: cryptobyte_asn1.PrintableString, + value: []byte{1, 2, 3}, + expectedErr: "invalid PrintableString", + }, + { + name: "UTF8String", + tag: cryptobyte_asn1.UTF8String, + value: []byte{80, 81, 82}, + expected: string("PQR"), + }, + { + name: "UTF8String (invalid)", + tag: cryptobyte_asn1.UTF8String, + value: []byte{255}, + expectedErr: "invalid UTF-8 string", + }, + { + name: "BMPString", + tag: cryptobyte_asn1.Tag(asn1.TagBMPString), + value: []byte{80, 81}, + expected: string("偑"), + }, + { + name: "BMPString (invalid length)", + tag: cryptobyte_asn1.Tag(asn1.TagBMPString), + value: []byte{255}, + expectedErr: "invalid BMPString", + }, + { + name: "IA5String", + tag: cryptobyte_asn1.IA5String, + value: []byte{80, 81}, + expected: string("PQ"), + }, + { + name: "IA5String (invalid)", + tag: cryptobyte_asn1.IA5String, + value: []byte{255}, + expectedErr: "invalid IA5String", + }, + { + name: "NumericString", + tag: cryptobyte_asn1.Tag(asn1.TagNumericString), + value: []byte{49, 50}, + expected: string("12"), + }, + { + name: "NumericString (invalid)", + tag: cryptobyte_asn1.Tag(asn1.TagNumericString), + value: []byte{80}, + expectedErr: "invalid NumericString", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + out, err := parseASN1String(tc.tag, tc.value) + if err != nil && err.Error() != tc.expectedErr { + t.Fatalf("parseASN1String returned unexpected error: got %q, want %q", err, tc.expectedErr) + } else if err == nil && tc.expectedErr != "" { + t.Fatalf("parseASN1String didn't fail, expected: %s", tc.expectedErr) + } + if out != tc.expected { + t.Fatalf("parseASN1String returned unexpected value: got %q, want %q", out, tc.expected) + } + }) + } +} diff --git a/src/crypto/x509/pem_decrypt.go b/src/crypto/x509/pem_decrypt.go new file mode 100644 index 0000000..781cb3d --- /dev/null +++ b/src/crypto/x509/pem_decrypt.go @@ -0,0 +1,253 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +// RFC 1423 describes the encryption of PEM blocks. The algorithm used to +// generate a key from the password was derived by looking at the OpenSSL +// implementation. + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/des" + "crypto/md5" + "encoding/hex" + "encoding/pem" + "errors" + "io" + "strings" +) + +type PEMCipher int + +// Possible values for the EncryptPEMBlock encryption algorithm. +const ( + _ PEMCipher = iota + PEMCipherDES + PEMCipher3DES + PEMCipherAES128 + PEMCipherAES192 + PEMCipherAES256 +) + +// rfc1423Algo holds a method for enciphering a PEM block. +type rfc1423Algo struct { + cipher PEMCipher + name string + cipherFunc func(key []byte) (cipher.Block, error) + keySize int + blockSize int +} + +// rfc1423Algos holds a slice of the possible ways to encrypt a PEM +// block. The ivSize numbers were taken from the OpenSSL source. +var rfc1423Algos = []rfc1423Algo{{ + cipher: PEMCipherDES, + name: "DES-CBC", + cipherFunc: des.NewCipher, + keySize: 8, + blockSize: des.BlockSize, +}, { + cipher: PEMCipher3DES, + name: "DES-EDE3-CBC", + cipherFunc: des.NewTripleDESCipher, + keySize: 24, + blockSize: des.BlockSize, +}, { + cipher: PEMCipherAES128, + name: "AES-128-CBC", + cipherFunc: aes.NewCipher, + keySize: 16, + blockSize: aes.BlockSize, +}, { + cipher: PEMCipherAES192, + name: "AES-192-CBC", + cipherFunc: aes.NewCipher, + keySize: 24, + blockSize: aes.BlockSize, +}, { + cipher: PEMCipherAES256, + name: "AES-256-CBC", + cipherFunc: aes.NewCipher, + keySize: 32, + blockSize: aes.BlockSize, +}, +} + +// deriveKey uses a key derivation function to stretch the password into a key +// with the number of bits our cipher requires. This algorithm was derived from +// the OpenSSL source. +func (c rfc1423Algo) deriveKey(password, salt []byte) []byte { + hash := md5.New() + out := make([]byte, c.keySize) + var digest []byte + + for i := 0; i < len(out); i += len(digest) { + hash.Reset() + hash.Write(digest) + hash.Write(password) + hash.Write(salt) + digest = hash.Sum(digest[:0]) + copy(out[i:], digest) + } + return out +} + +// IsEncryptedPEMBlock returns whether the PEM block is password encrypted +// according to RFC 1423. +// +// Deprecated: Legacy PEM encryption as specified in RFC 1423 is insecure by +// design. Since it does not authenticate the ciphertext, it is vulnerable to +// padding oracle attacks that can let an attacker recover the plaintext. +func IsEncryptedPEMBlock(b *pem.Block) bool { + _, ok := b.Headers["DEK-Info"] + return ok +} + +// IncorrectPasswordError is returned when an incorrect password is detected. +var IncorrectPasswordError = errors.New("x509: decryption password incorrect") + +// DecryptPEMBlock takes a PEM block encrypted according to RFC 1423 and the +// password used to encrypt it and returns a slice of decrypted DER encoded +// bytes. It inspects the DEK-Info header to determine the algorithm used for +// decryption. If no DEK-Info header is present, an error is returned. If an +// incorrect password is detected an IncorrectPasswordError is returned. Because +// of deficiencies in the format, it's not always possible to detect an +// incorrect password. In these cases no error will be returned but the +// decrypted DER bytes will be random noise. +// +// Deprecated: Legacy PEM encryption as specified in RFC 1423 is insecure by +// design. Since it does not authenticate the ciphertext, it is vulnerable to +// padding oracle attacks that can let an attacker recover the plaintext. +func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) { + dek, ok := b.Headers["DEK-Info"] + if !ok { + return nil, errors.New("x509: no DEK-Info header in block") + } + + idx := strings.Index(dek, ",") + if idx == -1 { + return nil, errors.New("x509: malformed DEK-Info header") + } + + mode, hexIV := dek[:idx], dek[idx+1:] + ciph := cipherByName(mode) + if ciph == nil { + return nil, errors.New("x509: unknown encryption mode") + } + iv, err := hex.DecodeString(hexIV) + if err != nil { + return nil, err + } + if len(iv) != ciph.blockSize { + return nil, errors.New("x509: incorrect IV size") + } + + // Based on the OpenSSL implementation. The salt is the first 8 bytes + // of the initialization vector. + key := ciph.deriveKey(password, iv[:8]) + block, err := ciph.cipherFunc(key) + if err != nil { + return nil, err + } + + if len(b.Bytes)%block.BlockSize() != 0 { + return nil, errors.New("x509: encrypted PEM data is not a multiple of the block size") + } + + data := make([]byte, len(b.Bytes)) + dec := cipher.NewCBCDecrypter(block, iv) + dec.CryptBlocks(data, b.Bytes) + + // Blocks are padded using a scheme where the last n bytes of padding are all + // equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423. + // For example: + // [x y z 2 2] + // [x y 7 7 7 7 7 7 7] + // If we detect a bad padding, we assume it is an invalid password. + dlen := len(data) + if dlen == 0 || dlen%ciph.blockSize != 0 { + return nil, errors.New("x509: invalid padding") + } + last := int(data[dlen-1]) + if dlen < last { + return nil, IncorrectPasswordError + } + if last == 0 || last > ciph.blockSize { + return nil, IncorrectPasswordError + } + for _, val := range data[dlen-last:] { + if int(val) != last { + return nil, IncorrectPasswordError + } + } + return data[:dlen-last], nil +} + +// EncryptPEMBlock returns a PEM block of the specified type holding the +// given DER encoded data encrypted with the specified algorithm and +// password according to RFC 1423. +// +// Deprecated: Legacy PEM encryption as specified in RFC 1423 is insecure by +// design. Since it does not authenticate the ciphertext, it is vulnerable to +// padding oracle attacks that can let an attacker recover the plaintext. +func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) { + ciph := cipherByKey(alg) + if ciph == nil { + return nil, errors.New("x509: unknown encryption mode") + } + iv := make([]byte, ciph.blockSize) + if _, err := io.ReadFull(rand, iv); err != nil { + return nil, errors.New("x509: cannot generate IV: " + err.Error()) + } + // The salt is the first 8 bytes of the initialization vector, + // matching the key derivation in DecryptPEMBlock. + key := ciph.deriveKey(password, iv[:8]) + block, err := ciph.cipherFunc(key) + if err != nil { + return nil, err + } + enc := cipher.NewCBCEncrypter(block, iv) + pad := ciph.blockSize - len(data)%ciph.blockSize + encrypted := make([]byte, len(data), len(data)+pad) + // We could save this copy by encrypting all the whole blocks in + // the data separately, but it doesn't seem worth the additional + // code. + copy(encrypted, data) + // See RFC 1423, Section 1.1. + for i := 0; i < pad; i++ { + encrypted = append(encrypted, byte(pad)) + } + enc.CryptBlocks(encrypted, encrypted) + + return &pem.Block{ + Type: blockType, + Headers: map[string]string{ + "Proc-Type": "4,ENCRYPTED", + "DEK-Info": ciph.name + "," + hex.EncodeToString(iv), + }, + Bytes: encrypted, + }, nil +} + +func cipherByName(name string) *rfc1423Algo { + for i := range rfc1423Algos { + alg := &rfc1423Algos[i] + if alg.name == name { + return alg + } + } + return nil +} + +func cipherByKey(key PEMCipher) *rfc1423Algo { + for i := range rfc1423Algos { + alg := &rfc1423Algos[i] + if alg.cipher == key { + return alg + } + } + return nil +} diff --git a/src/crypto/x509/pem_decrypt_test.go b/src/crypto/x509/pem_decrypt_test.go new file mode 100644 index 0000000..dacef8b --- /dev/null +++ b/src/crypto/x509/pem_decrypt_test.go @@ -0,0 +1,249 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "crypto/rand" + "encoding/base64" + "encoding/pem" + "strings" + "testing" +) + +func TestDecrypt(t *testing.T) { + for i, data := range testData { + t.Logf("test %v. %v", i, data.kind) + block, rest := pem.Decode(data.pemData) + if len(rest) > 0 { + t.Error("extra data") + } + der, err := DecryptPEMBlock(block, data.password) + if err != nil { + t.Error("decrypt failed: ", err) + continue + } + if _, err := ParsePKCS1PrivateKey(der); err != nil { + t.Error("invalid private key: ", err) + } + plainDER, err := base64.StdEncoding.DecodeString(data.plainDER) + if err != nil { + t.Fatal("cannot decode test DER data: ", err) + } + if !bytes.Equal(der, plainDER) { + t.Error("data mismatch") + } + } +} + +func TestEncrypt(t *testing.T) { + for i, data := range testData { + t.Logf("test %v. %v", i, data.kind) + plainDER, err := base64.StdEncoding.DecodeString(data.plainDER) + if err != nil { + t.Fatal("cannot decode test DER data: ", err) + } + password := []byte("kremvax1") + block, err := EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", plainDER, password, data.kind) + if err != nil { + t.Error("encrypt: ", err) + continue + } + if !IsEncryptedPEMBlock(block) { + t.Error("PEM block does not appear to be encrypted") + } + if block.Type != "RSA PRIVATE KEY" { + t.Errorf("unexpected block type; got %q want %q", block.Type, "RSA PRIVATE KEY") + } + if block.Headers["Proc-Type"] != "4,ENCRYPTED" { + t.Errorf("block does not have correct Proc-Type header") + } + der, err := DecryptPEMBlock(block, password) + if err != nil { + t.Error("decrypt: ", err) + continue + } + if !bytes.Equal(der, plainDER) { + t.Errorf("data mismatch") + } + } +} + +var testData = []struct { + kind PEMCipher + password []byte + pemData []byte + plainDER string +}{ + { + kind: PEMCipherDES, + password: []byte("asdf"), + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,34F09A4FC8DE22B5 + +WXxy8kbZdiZvANtKvhmPBLV7eVFj2A5z6oAxvI9KGyhG0ZK0skfnt00C24vfU7m5 +ICXeoqP67lzJ18xCzQfHjDaBNs53DSDT+Iz4e8QUep1xQ30+8QKX2NA2coee3nwc +6oM1cuvhNUDemBH2i3dKgMVkfaga0zQiiOq6HJyGSncCMSruQ7F9iWEfRbFcxFCx +qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz +XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm +4C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD +r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug== +-----END RSA TESTING KEY-----`)), + plainDER: ` +MIIBPAIBAAJBAPASZe+tCPU6p80AjHhDkVsLYa51D35e/YGa8QcZyooeZM8EHozo +KD0fNiKI+53bHdy07N+81VQ8/ejPcRoXPlsCAwEAAQJBAMTxIuSq27VpR+zZ7WJf +c6fvv1OBvpMZ0/d1pxL/KnOAgq2rD5hDtk9b0LGhTPgQAmrrMTKuSeGoIuYE+gKQ +QvkCIQD+GC1m+/do+QRurr0uo46Kx1LzLeSCrjBk34wiOp2+dwIhAPHfTLRXS2fv +7rljm0bYa4+eDZpz+E8RcXEgzhhvcQQ9AiAI5eHZJGOyml3MXnQjiPi55WcDOw0w +glcRgT6QCEtz2wIhANSyqaFtosIkHKqrDUGfz/bb5tqMYTAnBruVPaf/WEOBAiEA +9xORWeRG1tRpso4+dYy4KdDkuLPIO01KY6neYGm3BCM=`, + }, + { + kind: PEMCipher3DES, + password: []byte("asdf"), + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7 + +0JqVdBEH6iqM7drTkj+e2W/bE3LqakaiWhb9WUVonFkhyu8ca/QzebY3b5gCvAZQ +YwBvDcT/GHospKqPx+cxDHJNsUASDZws6bz8ZXWJGwZGExKzr0+Qx5fgXn44Ms3x +8g1ENFuTXtxo+KoNK0zuAMAqp66Llcds3Fjl4XR18QaD0CrVNAfOdgATWZm5GJxk +Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB +ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w +3z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq +gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk= +-----END RSA TESTING KEY-----`)), + plainDER: ` +MIIBOwIBAAJBANOCXKdoNS/iP/MAbl9cf1/SF3P+Ns7ZeNL27CfmDh0O6Zduaax5 +NBiumd2PmjkaCu7lQ5JOibHfWn+xJsc3kw0CAwEAAQJANX/W8d1Q/sCqzkuAn4xl +B5a7qfJWaLHndu1QRLNTRJPn0Ee7OKJ4H0QKOhQM6vpjRrz+P2u9thn6wUxoPsef +QQIhAP/jCkfejFcy4v15beqKzwz08/tslVjF+Yq41eJGejmxAiEA05pMoqfkyjcx +fyvGhpoOyoCp71vSGUfR2I9CR65oKh0CIC1Msjs66LlfJtQctRq6bCEtFCxEcsP+ +eEjYo/Sk6WphAiEAxpgWPMJeU/shFT28gS+tmhjPZLpEoT1qkVlC14u0b3ECIQDX +tZZZxCtPAm7shftEib0VU77Lk8MsXJcx2C4voRsjEw==`, + }, + { + kind: PEMCipherAES128, + password: []byte("asdf"), + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A + +EyfQSzXSjv6BaNH+NHdXRlkHdimpF9izWlugVJAPApgXrq5YldPe2aGIOFXyJ+QE +ZIG20DYqaPzJRjTEbPNZ6Es0S2JJ5yCpKxwJuDkgJZKtF39Q2i36JeGbSZQIuWJE +GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D +33U43LLb7+9zD4y3Q9OVHqBFGyHcxCY9+9Qh4ZnFp7DTf6RY5TNEvE3s4g6aDpBs +3NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E +080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo +AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0= +-----END RSA TESTING KEY-----`)), + plainDER: ` +MIIBOgIBAAJBAMBlj5FxYtqbcy8wY89d/S7n0+r5MzD9F63BA/Lpl78vQKtdJ5dT +cDGh/rBt1ufRrNp0WihcmZi7Mpl/3jHjiWECAwEAAQJABNOHYnKhtDIqFYj1OAJ3 +k3GlU0OlERmIOoeY/cL2V4lgwllPBEs7r134AY4wMmZSBUj8UR/O4SNO668ElKPE +cQIhAOuqY7/115x5KCdGDMWi+jNaMxIvI4ETGwV40ykGzqlzAiEA0P9oEC3m9tHB +kbpjSTxaNkrXxDgdEOZz8X0uOUUwHNsCIAwzcSCiGLyYJTULUmP1ESERfW1mlV78 +XzzESaJpIM/zAiBQkSTcl9VhcJreQqvjn5BnPZLP4ZHS4gPwJAGdsj5J4QIhAOVR +B3WlRNTXR2WsJ5JdByezg9xzdXzULqmga0OE339a`, + }, + { + kind: PEMCipherAES192, + password: []byte("asdf"), + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369 + +cqVslvHqDDM6qwU6YjezCRifXmKsrgEev7ng6Qs7UmDJOpHDgJQZI9fwMFUhIyn5 +FbCu1SHkLMW52Ld3CuEqMnzWMlhPrW8tFvUOrMWPYSisv7nNq88HobZEJcUNL2MM +Y15XmHW6IJwPqhKyLHpWXyOCVEh4ODND2nV15PCoi18oTa475baxSk7+1qH7GuIs +Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG +ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6 +xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t +Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw= +-----END RSA TESTING KEY-----`)), + plainDER: ` +MIIBOwIBAAJBAMGcRrZiNNmtF20zyS6MQ7pdGx17aFDl+lTl+qnLuJRUCMUG05xs +OmxmL/O1Qlf+bnqR8Bgg65SfKg21SYuLhiMCAwEAAQJBAL94uuHyO4wux2VC+qpj +IzPykjdU7XRcDHbbvksf4xokSeUFjjD3PB0Qa83M94y89ZfdILIqS9x5EgSB4/lX +qNkCIQD6cCIqLfzq/lYbZbQgAAjpBXeQVYsbvVtJrPrXJAlVVQIhAMXpDKMeFPMn +J0g2rbx1gngx0qOa5r5iMU5w/noN4W2XAiBjf+WzCG5yFvazD+dOx3TC0A8+4x3P +uZ3pWbaXf5PNuQIgAcdXarvhelH2w2piY1g3BPeFqhzBSCK/yLGxR82KIh8CIQDD ++qGKsd09NhQ/G27y/DARzOYtml1NvdmCQAgsDIIOLA==`, + }, + { + kind: PEMCipherAES256, + password: []byte("asdf"), + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD + +4Mxr+KIzRVwoOP0wwq6caSkvW0iS+GE2h2Ov/u+n9ZTMwL83PRnmjfjzBgfRZLVf +JFPXxUK26kMNpIdssNnqGOds+DhB+oSrsNKoxgxSl5OBoYv9eJTVYm7qOyAFIsjr +DRKAcjYCmzfesr7PVTowwy0RtHmYwyXMGDlAzzZrEvaiySFFmMyKKvtoavwaFoc7 +Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/ +2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N +sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk +clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0= +-----END RSA TESTING KEY-----`)), + plainDER: ` +MIIBOgIBAAJBAKy3GFkstoCHIEeUU/qO8207m8WSrjksR+p9B4tf1w5k+2O1V/GY +AQ5WFCApItcOkQe/I0yZZJk/PmCqMzSxrc8CAwEAAQJAOCAz0F7AW9oNelVQSP8F +Sfzx7O1yom+qWyAQQJF/gFR11gpf9xpVnnyu1WxIRnDUh1LZwUsjwlDYb7MB74id +oQIhANPcOiLwOPT4sIUpRM5HG6BF1BI7L77VpyGVk8xNP7X/AiEA0LMHZtk4I+lJ +nClgYp4Yh2JZ1Znbu7IoQMCEJCjwKDECIGd8Dzm5tViTkUW6Hs3Tlf73nNs65duF +aRnSglss8I3pAiEAonEnKruawgD8RavDFR+fUgmQiPz4FnGGeVgfwpGG1JECIBYq +PXHYtPqxQIbD2pScR5qum7iGUh11lEUPkmt+2uqS`, + }, + { + // generated with: + // openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128 + kind: PEMCipherAES128, + password: []byte("asdf"), + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7 + +6ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3 +eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD +hTP8O1mS/MHl92NE0nhv0w== +-----END RSA TESTING KEY-----`)), + plainDER: ` +MGMCAQACEQC6ssxmYuauuHGOCDAI54RdAgMBAAECEQCWIn6Yv2O+kBcDF7STctKB +AgkA8SEfu/2i3g0CCQDGNlXbBHX7kQIIK3Ww5o0cYbECCQDCimPb0dYGsQIIeQ7A +jryIst8=`, + }, +} + +var incompleteBlockPEM = testingKey(` +-----BEGIN RSA TESTING KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7 + +6L8yXK2MTQUWBk4ZD6OvCiYp+mXyR1594TQ1K38MxGvDw5pwcDME2Lek8RrR5fd40P2XsL2Z4KKt +ai+OP1BZUetfK6AW4MiqB2FDyIdOAJ8XeWuZy21Wtsh8wPD6yYOFM/w7WZL8weX3Y0TSeG/T +-----END RSA TESTING KEY-----`) + +func TestIncompleteBlock(t *testing.T) { + // incompleteBlockPEM contains ciphertext that is not a multiple of the + // block size. This previously panicked. See #11215. + block, _ := pem.Decode([]byte(incompleteBlockPEM)) + _, err := DecryptPEMBlock(block, []byte("foo")) + if err == nil { + t.Fatal("Bad PEM data decrypted successfully") + } + const expectedSubstr = "block size" + if e := err.Error(); !strings.Contains(e, expectedSubstr) { + t.Fatalf("Expected error containing %q but got: %q", expectedSubstr, e) + } +} + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/src/crypto/x509/pkcs1.go b/src/crypto/x509/pkcs1.go new file mode 100644 index 0000000..f9d3840 --- /dev/null +++ b/src/crypto/x509/pkcs1.go @@ -0,0 +1,173 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "crypto/rsa" + "encoding/asn1" + "errors" + "math/big" +) + +// pkcs1PrivateKey is a structure which mirrors the PKCS #1 ASN.1 for an RSA private key. +type pkcs1PrivateKey struct { + Version int + N *big.Int + E int + D *big.Int + P *big.Int + Q *big.Int + // We ignore these values, if present, because rsa will calculate them. + Dp *big.Int `asn1:"optional"` + Dq *big.Int `asn1:"optional"` + Qinv *big.Int `asn1:"optional"` + + AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"` +} + +type pkcs1AdditionalRSAPrime struct { + Prime *big.Int + + // We ignore these values because rsa will calculate them. + Exp *big.Int + Coeff *big.Int +} + +// pkcs1PublicKey reflects the ASN.1 structure of a PKCS #1 public key. +type pkcs1PublicKey struct { + N *big.Int + E int +} + +// ParsePKCS1PrivateKey parses an RSA private key in PKCS #1, ASN.1 DER form. +// +// This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY". +func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { + var priv pkcs1PrivateKey + rest, err := asn1.Unmarshal(der, &priv) + if len(rest) > 0 { + return nil, asn1.SyntaxError{Msg: "trailing data"} + } + if err != nil { + if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil { + return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)") + } + if _, err := asn1.Unmarshal(der, &pkcs8{}); err == nil { + return nil, errors.New("x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)") + } + return nil, err + } + + if priv.Version > 1 { + return nil, errors.New("x509: unsupported private key version") + } + + if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 { + return nil, errors.New("x509: private key contains zero or negative value") + } + + key := new(rsa.PrivateKey) + key.PublicKey = rsa.PublicKey{ + E: priv.E, + N: priv.N, + } + + key.D = priv.D + key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes)) + key.Primes[0] = priv.P + key.Primes[1] = priv.Q + for i, a := range priv.AdditionalPrimes { + if a.Prime.Sign() <= 0 { + return nil, errors.New("x509: private key contains zero or negative prime") + } + key.Primes[i+2] = a.Prime + // We ignore the other two values because rsa will calculate + // them as needed. + } + + err = key.Validate() + if err != nil { + return nil, err + } + key.Precompute() + + return key, nil +} + +// MarshalPKCS1PrivateKey converts an RSA private key to PKCS #1, ASN.1 DER form. +// +// This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY". +// For a more flexible key format which is not RSA specific, use +// MarshalPKCS8PrivateKey. +func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte { + key.Precompute() + + version := 0 + if len(key.Primes) > 2 { + version = 1 + } + + priv := pkcs1PrivateKey{ + Version: version, + N: key.N, + E: key.PublicKey.E, + D: key.D, + P: key.Primes[0], + Q: key.Primes[1], + Dp: key.Precomputed.Dp, + Dq: key.Precomputed.Dq, + Qinv: key.Precomputed.Qinv, + } + + priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues)) + for i, values := range key.Precomputed.CRTValues { + priv.AdditionalPrimes[i].Prime = key.Primes[2+i] + priv.AdditionalPrimes[i].Exp = values.Exp + priv.AdditionalPrimes[i].Coeff = values.Coeff + } + + b, _ := asn1.Marshal(priv) + return b +} + +// ParsePKCS1PublicKey parses an RSA public key in PKCS #1, ASN.1 DER form. +// +// This kind of key is commonly encoded in PEM blocks of type "RSA PUBLIC KEY". +func ParsePKCS1PublicKey(der []byte) (*rsa.PublicKey, error) { + var pub pkcs1PublicKey + rest, err := asn1.Unmarshal(der, &pub) + if err != nil { + if _, err := asn1.Unmarshal(der, &publicKeyInfo{}); err == nil { + return nil, errors.New("x509: failed to parse public key (use ParsePKIXPublicKey instead for this key format)") + } + return nil, err + } + if len(rest) > 0 { + return nil, asn1.SyntaxError{Msg: "trailing data"} + } + + if pub.N.Sign() <= 0 || pub.E <= 0 { + return nil, errors.New("x509: public key contains zero or negative value") + } + if pub.E > 1<<31-1 { + return nil, errors.New("x509: public key contains large public exponent") + } + + return &rsa.PublicKey{ + E: pub.E, + N: pub.N, + }, nil +} + +// MarshalPKCS1PublicKey converts an RSA public key to PKCS #1, ASN.1 DER form. +// +// This kind of key is commonly encoded in PEM blocks of type "RSA PUBLIC KEY". +func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte { + derBytes, _ := asn1.Marshal(pkcs1PublicKey{ + N: key.N, + E: key.E, + }) + return derBytes +} diff --git a/src/crypto/x509/pkcs8.go b/src/crypto/x509/pkcs8.go new file mode 100644 index 0000000..a5ee4cf --- /dev/null +++ b/src/crypto/x509/pkcs8.go @@ -0,0 +1,136 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rsa" + "crypto/x509/pkix" + "encoding/asn1" + "errors" + "fmt" +) + +// pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See +// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn +// and RFC 5208. +type pkcs8 struct { + Version int + Algo pkix.AlgorithmIdentifier + PrivateKey []byte + // optional attributes omitted. +} + +// ParsePKCS8PrivateKey parses an unencrypted private key in PKCS #8, ASN.1 DER form. +// +// It returns a *rsa.PrivateKey, a *ecdsa.PrivateKey, or a ed25519.PrivateKey. +// More types might be supported in the future. +// +// This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". +func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { + var privKey pkcs8 + if _, err := asn1.Unmarshal(der, &privKey); err != nil { + if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil { + return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)") + } + if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil { + return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)") + } + return nil, err + } + switch { + case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA): + key, err = ParsePKCS1PrivateKey(privKey.PrivateKey) + if err != nil { + return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error()) + } + return key, nil + + case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): + bytes := privKey.Algo.Parameters.FullBytes + namedCurveOID := new(asn1.ObjectIdentifier) + if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { + namedCurveOID = nil + } + key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) + if err != nil { + return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error()) + } + return key, nil + + case privKey.Algo.Algorithm.Equal(oidPublicKeyEd25519): + if l := len(privKey.Algo.Parameters.FullBytes); l != 0 { + return nil, errors.New("x509: invalid Ed25519 private key parameters") + } + var curvePrivateKey []byte + if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil { + return nil, fmt.Errorf("x509: invalid Ed25519 private key: %v", err) + } + if l := len(curvePrivateKey); l != ed25519.SeedSize { + return nil, fmt.Errorf("x509: invalid Ed25519 private key length: %d", l) + } + return ed25519.NewKeyFromSeed(curvePrivateKey), nil + + default: + return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) + } +} + +// MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form. +// +// The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey +// and ed25519.PrivateKey. Unsupported key types result in an error. +// +// This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". +func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) { + var privKey pkcs8 + + switch k := key.(type) { + case *rsa.PrivateKey: + privKey.Algo = pkix.AlgorithmIdentifier{ + Algorithm: oidPublicKeyRSA, + Parameters: asn1.NullRawValue, + } + privKey.PrivateKey = MarshalPKCS1PrivateKey(k) + + case *ecdsa.PrivateKey: + oid, ok := oidFromNamedCurve(k.Curve) + if !ok { + return nil, errors.New("x509: unknown curve while marshaling to PKCS#8") + } + + oidBytes, err := asn1.Marshal(oid) + if err != nil { + return nil, errors.New("x509: failed to marshal curve OID: " + err.Error()) + } + + privKey.Algo = pkix.AlgorithmIdentifier{ + Algorithm: oidPublicKeyECDSA, + Parameters: asn1.RawValue{ + FullBytes: oidBytes, + }, + } + + if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil { + return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error()) + } + + case ed25519.PrivateKey: + privKey.Algo = pkix.AlgorithmIdentifier{ + Algorithm: oidPublicKeyEd25519, + } + curvePrivateKey, err := asn1.Marshal(k.Seed()) + if err != nil { + return nil, fmt.Errorf("x509: failed to marshal private key: %v", err) + } + privKey.PrivateKey = curvePrivateKey + + default: + return nil, fmt.Errorf("x509: unknown key type while marshaling PKCS#8: %T", key) + } + + return asn1.Marshal(privKey) +} diff --git a/src/crypto/x509/pkcs8_test.go b/src/crypto/x509/pkcs8_test.go new file mode 100644 index 0000000..cb7ee4c --- /dev/null +++ b/src/crypto/x509/pkcs8_test.go @@ -0,0 +1,140 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rsa" + "encoding/hex" + "reflect" + "strings" + "testing" +) + +// Generated using: +// openssl genrsa 1024 | openssl pkcs8 -topk8 -nocrypt +var pkcs8RSAPrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031` + +// Generated using: +// openssl ecparam -genkey -name secp224r1 | openssl pkcs8 -topk8 -nocrypt +var pkcs8P224PrivateKeyHex = `3078020100301006072a8648ce3d020106052b810400210461305f020101041cca3d72b3e88fed2684576dad9b80a9180363a5424986900e3abcab3fa13c033a0004f8f2a6372872a4e61263ed893afb919576a4cacfecd6c081a2cbc76873cf4ba8530703c6042b3a00e2205087e87d2435d2e339e25702fae1` + +// Generated using: +// openssl ecparam -genkey -name secp256r1 | openssl pkcs8 -topk8 -nocrypt +var pkcs8P256PrivateKeyHex = `308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420dad6b2f49ca774c36d8ae9517e935226f667c929498f0343d2424d0b9b591b43a14403420004b9c9b90095476afe7b860d8bd43568cab7bcb2eed7b8bf2fa0ce1762dd20b04193f859d2d782b1e4cbfd48492f1f533113a6804903f292258513837f07fda735` + +// Generated using: +// openssl ecparam -genkey -name secp384r1 | openssl pkcs8 -topk8 -nocrypt +var pkcs8P384PrivateKeyHex = `3081b6020100301006072a8648ce3d020106052b8104002204819e30819b02010104309bf832f6aaaeacb78ce47ffb15e6fd0fd48683ae79df6eca39bfb8e33829ac94aa29d08911568684c2264a08a4ceb679a164036200049070ad4ed993c7770d700e9f6dc2baa83f63dd165b5507f98e8ff29b5d2e78ccbe05c8ddc955dbf0f7497e8222cfa49314fe4e269459f8e880147f70d785e530f2939e4bf9f838325bb1a80ad4cf59272ae0e5efe9a9dc33d874492596304bd3` + +// Generated using: +// openssl ecparam -genkey -name secp521r1 | openssl pkcs8 -topk8 -nocrypt +// +// Note that OpenSSL will truncate the private key if it can (i.e. it emits it +// like an integer, even though it's an OCTET STRING field). Thus if you +// regenerate this you may, randomly, find that it's a byte shorter than +// expected and the Go test will fail to recreate it exactly. +var pkcs8P521PrivateKeyHex = `3081ee020100301006072a8648ce3d020106052b810400230481d63081d3020101044200cfe0b87113a205cf291bb9a8cd1a74ac6c7b2ebb8199aaa9a5010d8b8012276fa3c22ac913369fa61beec2a3b8b4516bc049bde4fb3b745ac11b56ab23ac52e361a1818903818600040138f75acdd03fbafa4f047a8e4b272ba9d555c667962b76f6f232911a5786a0964e5edea6bd21a6f8725720958de049c6e3e6661c1c91b227cebee916c0319ed6ca003db0a3206d372229baf9dd25d868bf81140a518114803ce40c1855074d68c4e9dab9e65efba7064c703b400f1767f217dac82715ac1f6d88c74baf47a7971de4ea` + +// From RFC 8410, Section 7. +var pkcs8Ed25519PrivateKeyHex = `302e020100300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842` + +func TestPKCS8(t *testing.T) { + tests := []struct { + name string + keyHex string + keyType reflect.Type + curve elliptic.Curve + }{ + { + name: "RSA private key", + keyHex: pkcs8RSAPrivateKeyHex, + keyType: reflect.TypeOf(&rsa.PrivateKey{}), + }, + { + name: "P-224 private key", + keyHex: pkcs8P224PrivateKeyHex, + keyType: reflect.TypeOf(&ecdsa.PrivateKey{}), + curve: elliptic.P224(), + }, + { + name: "P-256 private key", + keyHex: pkcs8P256PrivateKeyHex, + keyType: reflect.TypeOf(&ecdsa.PrivateKey{}), + curve: elliptic.P256(), + }, + { + name: "P-384 private key", + keyHex: pkcs8P384PrivateKeyHex, + keyType: reflect.TypeOf(&ecdsa.PrivateKey{}), + curve: elliptic.P384(), + }, + { + name: "P-521 private key", + keyHex: pkcs8P521PrivateKeyHex, + keyType: reflect.TypeOf(&ecdsa.PrivateKey{}), + curve: elliptic.P521(), + }, + { + name: "Ed25519 private key", + keyHex: pkcs8Ed25519PrivateKeyHex, + keyType: reflect.TypeOf(ed25519.PrivateKey{}), + }, + } + + for _, test := range tests { + derBytes, err := hex.DecodeString(test.keyHex) + if err != nil { + t.Errorf("%s: failed to decode hex: %s", test.name, err) + continue + } + privKey, err := ParsePKCS8PrivateKey(derBytes) + if err != nil { + t.Errorf("%s: failed to decode PKCS#8: %s", test.name, err) + continue + } + if reflect.TypeOf(privKey) != test.keyType { + t.Errorf("%s: decoded PKCS#8 returned unexpected key type: %T", test.name, privKey) + continue + } + if ecKey, isEC := privKey.(*ecdsa.PrivateKey); isEC && ecKey.Curve != test.curve { + t.Errorf("%s: decoded PKCS#8 returned unexpected curve %#v", test.name, ecKey.Curve) + continue + } + reserialised, err := MarshalPKCS8PrivateKey(privKey) + if err != nil { + t.Errorf("%s: failed to marshal into PKCS#8: %s", test.name, err) + continue + } + if !bytes.Equal(derBytes, reserialised) { + t.Errorf("%s: marshaled PKCS#8 didn't match original: got %x, want %x", test.name, reserialised, derBytes) + continue + } + } +} + +const hexPKCS8TestPKCS1Key = "3082025c02010002818100b1a1e0945b9289c4d3f1329f8a982c4a2dcd59bfd372fb8085a9c517554607ebd2f7990eef216ac9f4605f71a03b04f42a5255b158cf8e0844191f5119348baa44c35056e20609bcf9510f30ead4b481c81d7865fb27b8e0090e112b717f3ee08cdfc4012da1f1f7cf2a1bc34c73a54a12b06372d09714742dd7895eadde4aa5020301000102818062b7fa1db93e993e40237de4d89b7591cc1ea1d04fed4904c643f17ae4334557b4295270d0491c161cb02a9af557978b32b20b59c267a721c4e6c956c2d147046e9ae5f2da36db0106d70021fa9343455f8f973a4b355a26fd19e6b39dee0405ea2b32deddf0f4817759ef705d02b34faab9ca93c6766e9f722290f119f34449024100d9c29a4a013a90e35fd1be14a3f747c589fac613a695282d61812a711906b8a0876c6181f0333ca1066596f57bff47e7cfcabf19c0fc69d9cd76df743038b3cb024100d0d3546fecf879b5551f2bd2c05e6385f2718a08a6face3d2aecc9d7e03645a480a46c81662c12ad6bd6901e3bd4f38029462de7290859567cdf371c79088d4f024100c254150657e460ea58573fcf01a82a4791e3d6223135c8bdfed69afe84fbe7857274f8eb5165180507455f9b4105c6b08b51fe8a481bb986a202245576b713530240045700003b7a867d0041df9547ae2e7f50248febd21c9040b12dae9c2feab0d3d4609668b208e4727a3541557f84d372ac68eaf74ce1018a4c9a0ef92682c8fd02405769731480bb3a4570abf422527c5f34bf732fa6c1e08cc322753c511ce055fac20fc770025663ad3165324314df907f1f1942f0448a7e9cdbf87ecd98b92156" +const hexPKCS8TestECKey = "3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50" + +var pkcs8MismatchKeyTests = []struct { + hexKey string + errorContains string +}{ + {hexKey: hexPKCS8TestECKey, errorContains: "use ParseECPrivateKey instead"}, + {hexKey: hexPKCS8TestPKCS1Key, errorContains: "use ParsePKCS1PrivateKey instead"}, +} + +func TestPKCS8MismatchKeyFormat(t *testing.T) { + for i, test := range pkcs8MismatchKeyTests { + derBytes, _ := hex.DecodeString(test.hexKey) + _, err := ParsePKCS8PrivateKey(derBytes) + if !strings.Contains(err.Error(), test.errorContains) { + t.Errorf("#%d: expected error containing %q, got %s", i, test.errorContains, err) + } + } +} diff --git a/src/crypto/x509/pkix/pkix.go b/src/crypto/x509/pkix/pkix.go new file mode 100644 index 0000000..62ae065 --- /dev/null +++ b/src/crypto/x509/pkix/pkix.go @@ -0,0 +1,316 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package pkix contains shared, low level structures used for ASN.1 parsing +// and serialization of X.509 certificates, CRL and OCSP. +package pkix + +import ( + "encoding/asn1" + "encoding/hex" + "fmt" + "math/big" + "time" +) + +// AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC +// 5280, section 4.1.1.2. +type AlgorithmIdentifier struct { + Algorithm asn1.ObjectIdentifier + Parameters asn1.RawValue `asn1:"optional"` +} + +type RDNSequence []RelativeDistinguishedNameSET + +var attributeTypeNames = map[string]string{ + "2.5.4.6": "C", + "2.5.4.10": "O", + "2.5.4.11": "OU", + "2.5.4.3": "CN", + "2.5.4.5": "SERIALNUMBER", + "2.5.4.7": "L", + "2.5.4.8": "ST", + "2.5.4.9": "STREET", + "2.5.4.17": "POSTALCODE", +} + +// String returns a string representation of the sequence r, +// roughly following the RFC 2253 Distinguished Names syntax. +func (r RDNSequence) String() string { + s := "" + for i := 0; i < len(r); i++ { + rdn := r[len(r)-1-i] + if i > 0 { + s += "," + } + for j, tv := range rdn { + if j > 0 { + s += "+" + } + + oidString := tv.Type.String() + typeName, ok := attributeTypeNames[oidString] + if !ok { + derBytes, err := asn1.Marshal(tv.Value) + if err == nil { + s += oidString + "=#" + hex.EncodeToString(derBytes) + continue // No value escaping necessary. + } + + typeName = oidString + } + + valueString := fmt.Sprint(tv.Value) + escaped := make([]rune, 0, len(valueString)) + + for k, c := range valueString { + escape := false + + switch c { + case ',', '+', '"', '\\', '<', '>', ';': + escape = true + + case ' ': + escape = k == 0 || k == len(valueString)-1 + + case '#': + escape = k == 0 + } + + if escape { + escaped = append(escaped, '\\', c) + } else { + escaped = append(escaped, c) + } + } + + s += typeName + "=" + string(escaped) + } + } + + return s +} + +type RelativeDistinguishedNameSET []AttributeTypeAndValue + +// AttributeTypeAndValue mirrors the ASN.1 structure of the same name in +// RFC 5280, Section 4.1.2.4. +type AttributeTypeAndValue struct { + Type asn1.ObjectIdentifier + Value interface{} +} + +// AttributeTypeAndValueSET represents a set of ASN.1 sequences of +// AttributeTypeAndValue sequences from RFC 2986 (PKCS #10). +type AttributeTypeAndValueSET struct { + Type asn1.ObjectIdentifier + Value [][]AttributeTypeAndValue `asn1:"set"` +} + +// Extension represents the ASN.1 structure of the same name. See RFC +// 5280, section 4.2. +type Extension struct { + Id asn1.ObjectIdentifier + Critical bool `asn1:"optional"` + Value []byte +} + +// Name represents an X.509 distinguished name. This only includes the common +// elements of a DN. Note that Name is only an approximation of the X.509 +// structure. If an accurate representation is needed, asn1.Unmarshal the raw +// subject or issuer as an RDNSequence. +type Name struct { + Country, Organization, OrganizationalUnit []string + Locality, Province []string + StreetAddress, PostalCode []string + SerialNumber, CommonName string + + // Names contains all parsed attributes. When parsing distinguished names, + // this can be used to extract non-standard attributes that are not parsed + // by this package. When marshaling to RDNSequences, the Names field is + // ignored, see ExtraNames. + Names []AttributeTypeAndValue + + // ExtraNames contains attributes to be copied, raw, into any marshaled + // distinguished names. Values override any attributes with the same OID. + // The ExtraNames field is not populated when parsing, see Names. + ExtraNames []AttributeTypeAndValue +} + +// FillFromRDNSequence populates n from the provided RDNSequence. +// Multi-entry RDNs are flattened, all entries are added to the +// relevant n fields, and the grouping is not preserved. +func (n *Name) FillFromRDNSequence(rdns *RDNSequence) { + for _, rdn := range *rdns { + if len(rdn) == 0 { + continue + } + + for _, atv := range rdn { + n.Names = append(n.Names, atv) + value, ok := atv.Value.(string) + if !ok { + continue + } + + t := atv.Type + if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { + switch t[3] { + case 3: + n.CommonName = value + case 5: + n.SerialNumber = value + case 6: + n.Country = append(n.Country, value) + case 7: + n.Locality = append(n.Locality, value) + case 8: + n.Province = append(n.Province, value) + case 9: + n.StreetAddress = append(n.StreetAddress, value) + case 10: + n.Organization = append(n.Organization, value) + case 11: + n.OrganizationalUnit = append(n.OrganizationalUnit, value) + case 17: + n.PostalCode = append(n.PostalCode, value) + } + } + } + } +} + +var ( + oidCountry = []int{2, 5, 4, 6} + oidOrganization = []int{2, 5, 4, 10} + oidOrganizationalUnit = []int{2, 5, 4, 11} + oidCommonName = []int{2, 5, 4, 3} + oidSerialNumber = []int{2, 5, 4, 5} + oidLocality = []int{2, 5, 4, 7} + oidProvince = []int{2, 5, 4, 8} + oidStreetAddress = []int{2, 5, 4, 9} + oidPostalCode = []int{2, 5, 4, 17} +) + +// appendRDNs appends a relativeDistinguishedNameSET to the given RDNSequence +// and returns the new value. The relativeDistinguishedNameSET contains an +// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and +// search for AttributeTypeAndValue. +func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence { + if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) { + return in + } + + s := make([]AttributeTypeAndValue, len(values)) + for i, value := range values { + s[i].Type = oid + s[i].Value = value + } + + return append(in, s) +} + +// ToRDNSequence converts n into a single RDNSequence. The following +// attributes are encoded as multi-value RDNs: +// +// - Country +// - Organization +// - OrganizationalUnit +// - Locality +// - Province +// - StreetAddress +// - PostalCode +// +// Each ExtraNames entry is encoded as an individual RDN. +func (n Name) ToRDNSequence() (ret RDNSequence) { + ret = n.appendRDNs(ret, n.Country, oidCountry) + ret = n.appendRDNs(ret, n.Province, oidProvince) + ret = n.appendRDNs(ret, n.Locality, oidLocality) + ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress) + ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode) + ret = n.appendRDNs(ret, n.Organization, oidOrganization) + ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit) + if len(n.CommonName) > 0 { + ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName) + } + if len(n.SerialNumber) > 0 { + ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber) + } + for _, atv := range n.ExtraNames { + ret = append(ret, []AttributeTypeAndValue{atv}) + } + + return ret +} + +// String returns the string form of n, roughly following +// the RFC 2253 Distinguished Names syntax. +func (n Name) String() string { + var rdns RDNSequence + // If there are no ExtraNames, surface the parsed value (all entries in + // Names) instead. + if n.ExtraNames == nil { + for _, atv := range n.Names { + t := atv.Type + if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { + switch t[3] { + case 3, 5, 6, 7, 8, 9, 10, 11, 17: + // These attributes were already parsed into named fields. + continue + } + } + // Place non-standard parsed values at the beginning of the sequence + // so they will be at the end of the string. See Issue 39924. + rdns = append(rdns, []AttributeTypeAndValue{atv}) + } + } + rdns = append(rdns, n.ToRDNSequence()...) + return rdns.String() +} + +// oidInAttributeTypeAndValue reports whether a type with the given OID exists +// in atv. +func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAndValue) bool { + for _, a := range atv { + if a.Type.Equal(oid) { + return true + } + } + return false +} + +// CertificateList represents the ASN.1 structure of the same name. See RFC +// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the +// signature. +type CertificateList struct { + TBSCertList TBSCertificateList + SignatureAlgorithm AlgorithmIdentifier + SignatureValue asn1.BitString +} + +// HasExpired reports whether certList should have been updated by now. +func (certList *CertificateList) HasExpired(now time.Time) bool { + return !now.Before(certList.TBSCertList.NextUpdate) +} + +// TBSCertificateList represents the ASN.1 structure of the same name. See RFC +// 5280, section 5.1. +type TBSCertificateList struct { + Raw asn1.RawContent + Version int `asn1:"optional,default:0"` + Signature AlgorithmIdentifier + Issuer RDNSequence + ThisUpdate time.Time + NextUpdate time.Time `asn1:"optional"` + RevokedCertificates []RevokedCertificate `asn1:"optional"` + Extensions []Extension `asn1:"tag:0,optional,explicit"` +} + +// RevokedCertificate represents the ASN.1 structure of the same name. See RFC +// 5280, section 5.1. +type RevokedCertificate struct { + SerialNumber *big.Int + RevocationTime time.Time + Extensions []Extension `asn1:"optional"` +} diff --git a/src/crypto/x509/root.go b/src/crypto/x509/root.go new file mode 100644 index 0000000..eef9c04 --- /dev/null +++ b/src/crypto/x509/root.go @@ -0,0 +1,31 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +// To update the embedded iOS root store, update the -version +// argument to the latest security_certificates version from +// https://opensource.apple.com/source/security_certificates/ +// and run "go generate". See https://golang.org/issue/38843. +//go:generate go run root_ios_gen.go -version 55188.120.1.0.1 + +import "sync" + +var ( + once sync.Once + systemRoots *CertPool + systemRootsErr error +) + +func systemRootsPool() *CertPool { + once.Do(initSystemRoots) + return systemRoots +} + +func initSystemRoots() { + systemRoots, systemRootsErr = loadSystemRoots() + if systemRootsErr != nil { + systemRoots = nil + } +} diff --git a/src/crypto/x509/root_aix.go b/src/crypto/x509/root_aix.go new file mode 100644 index 0000000..4d50a13 --- /dev/null +++ b/src/crypto/x509/root_aix.go @@ -0,0 +1,16 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +// Possible certificate files; stop after finding one. +var certFiles = []string{ + "/var/ssl/certs/ca-bundle.crt", +} + +// Possible directories with certificate files; stop after successfully +// reading at least one file from a directory. +var certDirectories = []string{ + "/var/ssl/certs", +} diff --git a/src/crypto/x509/root_bsd.go b/src/crypto/x509/root_bsd.go new file mode 100644 index 0000000..6712ea3 --- /dev/null +++ b/src/crypto/x509/root_bsd.go @@ -0,0 +1,24 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build dragonfly || freebsd || netbsd || openbsd +// +build dragonfly freebsd netbsd openbsd + +package x509 + +// Possible certificate files; stop after finding one. +var certFiles = []string{ + "/usr/local/etc/ssl/cert.pem", // FreeBSD + "/etc/ssl/cert.pem", // OpenBSD + "/usr/local/share/certs/ca-root-nss.crt", // DragonFly + "/etc/openssl/certs/ca-certificates.crt", // NetBSD +} + +// Possible directories with certificate files; stop after successfully +// reading at least one file from a directory. +var certDirectories = []string{ + "/etc/ssl/certs", // FreeBSD 12.2+ + "/usr/local/share/certs", // FreeBSD + "/etc/openssl/certs", // NetBSD +} diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go new file mode 100644 index 0000000..05593bb --- /dev/null +++ b/src/crypto/x509/root_darwin.go @@ -0,0 +1,240 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !ios +// +build !ios + +package x509 + +import ( + "bytes" + macOS "crypto/x509/internal/macos" + "fmt" + "os" + "strings" +) + +var debugDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "x509roots=1") + +func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { + return nil, nil +} + +func loadSystemRoots() (*CertPool, error) { + var trustedRoots []*Certificate + untrustedRoots := make(map[string]bool) + + // macOS has three trust domains: one for CAs added by users to their + // "login" keychain, one for CAs added by Admins to the "System" keychain, + // and one for the CAs that ship with the OS. + for _, domain := range []macOS.SecTrustSettingsDomain{ + macOS.SecTrustSettingsDomainUser, + macOS.SecTrustSettingsDomainAdmin, + macOS.SecTrustSettingsDomainSystem, + } { + certs, err := macOS.SecTrustSettingsCopyCertificates(domain) + if err == macOS.ErrNoTrustSettings { + continue + } else if err != nil { + return nil, err + } + defer macOS.CFRelease(certs) + + for i := 0; i < macOS.CFArrayGetCount(certs); i++ { + c := macOS.CFArrayGetValueAtIndex(certs, i) + cert, err := exportCertificate(c) + if err != nil { + if debugDarwinRoots { + fmt.Fprintf(os.Stderr, "crypto/x509: domain %d, certificate #%d: %v\n", domain, i, err) + } + continue + } + + var result macOS.SecTrustSettingsResult + if domain == macOS.SecTrustSettingsDomainSystem { + // Certs found in the system domain are always trusted. If the user + // configures "Never Trust" on such a cert, it will also be found in the + // admin or user domain, causing it to be added to untrustedRoots. + result = macOS.SecTrustSettingsResultTrustRoot + } else { + result, err = sslTrustSettingsResult(c) + if err != nil { + if debugDarwinRoots { + fmt.Fprintf(os.Stderr, "crypto/x509: trust settings for %v: %v\n", cert.Subject, err) + } + continue + } + if debugDarwinRoots { + fmt.Fprintf(os.Stderr, "crypto/x509: trust settings for %v: %d\n", cert.Subject, result) + } + } + + switch result { + // "Note the distinction between the results kSecTrustSettingsResultTrustRoot + // and kSecTrustSettingsResultTrustAsRoot: The former can only be applied to + // root (self-signed) certificates; the latter can only be applied to + // non-root certificates." + case macOS.SecTrustSettingsResultTrustRoot: + if isRootCertificate(cert) { + trustedRoots = append(trustedRoots, cert) + } + case macOS.SecTrustSettingsResultTrustAsRoot: + if !isRootCertificate(cert) { + trustedRoots = append(trustedRoots, cert) + } + + case macOS.SecTrustSettingsResultDeny: + // Add this certificate to untrustedRoots, which are subtracted + // from trustedRoots, so that we don't have to evaluate policies + // for every root in the system domain, but still apply user and + // admin policies that override system roots. + untrustedRoots[string(cert.Raw)] = true + + case macOS.SecTrustSettingsResultUnspecified: + // Certificates with unspecified trust should be added to a pool + // of intermediates for chain building, but we don't support it + // at the moment. This is Issue 35631. + + default: + if debugDarwinRoots { + fmt.Fprintf(os.Stderr, "crypto/x509: unknown trust setting for %v: %d\n", cert.Subject, result) + } + } + } + } + + pool := NewCertPool() + for _, cert := range trustedRoots { + if !untrustedRoots[string(cert.Raw)] { + pool.AddCert(cert) + } + } + return pool, nil +} + +// exportCertificate returns a *Certificate for a SecCertificateRef. +func exportCertificate(cert macOS.CFRef) (*Certificate, error) { + data, err := macOS.SecItemExport(cert) + if err != nil { + return nil, err + } + defer macOS.CFRelease(data) + der := macOS.CFDataToSlice(data) + + return ParseCertificate(der) +} + +// isRootCertificate reports whether Subject and Issuer match. +func isRootCertificate(cert *Certificate) bool { + return bytes.Equal(cert.RawSubject, cert.RawIssuer) +} + +// sslTrustSettingsResult obtains the final kSecTrustSettingsResult value for a +// certificate in the user or admin domain, combining usage constraints for the +// SSL SecTrustSettingsPolicy, +// +// It ignores SecTrustSettingsKeyUsage and kSecTrustSettingsAllowedError, and +// doesn't support kSecTrustSettingsDefaultRootCertSetting. +// +// https://developer.apple.com/documentation/security/1400261-sectrustsettingscopytrustsetting +func sslTrustSettingsResult(cert macOS.CFRef) (macOS.SecTrustSettingsResult, error) { + // In Apple's implementation user trust settings override admin trust settings + // (which themselves override system trust settings). If SecTrustSettingsCopyTrustSettings + // fails, or returns a NULL trust settings, when looking for the user trust + // settings then fallback to checking the admin trust settings. + // + // See Security-59306.41.2/trust/headers/SecTrustSettings.h for a description of + // the trust settings overrides, and SecLegacyAnchorSourceCopyUsageConstraints in + // Security-59306.41.2/trust/trustd/SecCertificateSource.c for a concrete example + // of how Apple applies the override in the case of NULL trust settings, or non + // success errors. + trustSettings, err := macOS.SecTrustSettingsCopyTrustSettings(cert, macOS.SecTrustSettingsDomainUser) + if err != nil || trustSettings == 0 { + if debugDarwinRoots && err != macOS.ErrNoTrustSettings { + fmt.Fprintf(os.Stderr, "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainUser failed: %s\n", err) + } + trustSettings, err = macOS.SecTrustSettingsCopyTrustSettings(cert, macOS.SecTrustSettingsDomainAdmin) + } + if err != nil || trustSettings == 0 { + // If there are neither user nor admin trust settings for a certificate returned + // from SecTrustSettingsCopyCertificates Apple returns kSecTrustSettingsResultInvalid, + // as this method is intended to return certificates _which have trust settings_. + // The most likely case for this being triggered is that the existing trust settings + // are invalid and cannot be properly parsed. In this case SecTrustSettingsCopyTrustSettings + // returns errSecInvalidTrustSettings. The existing cgo implementation returns + // kSecTrustSettingsResultUnspecified in this case, which mostly matches the Apple + // implementation because we don't do anything with certificates marked with this + // result. + // + // See SecPVCGetTrustSettingsResult in Security-59306.41.2/trust/trustd/SecPolicyServer.c + if debugDarwinRoots && err != macOS.ErrNoTrustSettings { + fmt.Fprintf(os.Stderr, "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainAdmin failed: %s\n", err) + } + return macOS.SecTrustSettingsResultUnspecified, nil + } + defer macOS.CFRelease(trustSettings) + + // "An empty trust settings array means 'always trust this certificate' with an + // overall trust setting for the certificate of kSecTrustSettingsResultTrustRoot." + if macOS.CFArrayGetCount(trustSettings) == 0 { + return macOS.SecTrustSettingsResultTrustRoot, nil + } + + isSSLPolicy := func(policyRef macOS.CFRef) bool { + properties := macOS.SecPolicyCopyProperties(policyRef) + defer macOS.CFRelease(properties) + if v, ok := macOS.CFDictionaryGetValueIfPresent(properties, macOS.SecPolicyOid); ok { + return macOS.CFEqual(v, macOS.CFRef(macOS.SecPolicyAppleSSL)) + } + return false + } + + for i := 0; i < macOS.CFArrayGetCount(trustSettings); i++ { + tSetting := macOS.CFArrayGetValueAtIndex(trustSettings, i) + + // First, check if this trust setting is constrained to a non-SSL policy. + if policyRef, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsPolicy); ok { + if !isSSLPolicy(policyRef) { + continue + } + } + + // Then check if it is restricted to a hostname, so not a root. + if _, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsPolicyString); ok { + continue + } + + cfNum, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsResultKey) + // "If this key is not present, a default value of kSecTrustSettingsResultTrustRoot is assumed." + if !ok { + return macOS.SecTrustSettingsResultTrustRoot, nil + } + result, err := macOS.CFNumberGetValue(cfNum) + if err != nil { + return 0, err + } + + // If multiple dictionaries match, we are supposed to "OR" them, + // the semantics of which are not clear. Since TrustRoot and TrustAsRoot + // are mutually exclusive, Deny should probably override, and Invalid and + // Unspecified be overridden, approximate this by stopping at the first + // TrustRoot, TrustAsRoot or Deny. + switch r := macOS.SecTrustSettingsResult(result); r { + case macOS.SecTrustSettingsResultTrustRoot, + macOS.SecTrustSettingsResultTrustAsRoot, + macOS.SecTrustSettingsResultDeny: + return r, nil + } + } + + // If trust settings are present, but none of them match the policy... + // the docs don't tell us what to do. + // + // "Trust settings for a given use apply if any of the dictionaries in the + // certificate’s trust settings array satisfies the specified use." suggests + // that it's as if there were no trust settings at all, so we should maybe + // fallback to the admin trust settings? TODO(golang.org/issue/38888). + + return macOS.SecTrustSettingsResultUnspecified, nil +} diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go new file mode 100644 index 0000000..ae2bd02 --- /dev/null +++ b/src/crypto/x509/root_darwin_test.go @@ -0,0 +1,39 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "os" + "os/exec" + "testing" + "time" +) + +func TestSystemRoots(t *testing.T) { + t0 := time.Now() + sysRoots, err := loadSystemRoots() // actual system roots + sysRootsDuration := time.Since(t0) + + if err != nil { + t.Fatalf("failed to read system roots: %v", err) + } + + t.Logf("loadSystemRoots: %v", sysRootsDuration) + + // There are 174 system roots on Catalina, and 163 on iOS right now, require + // at least 100 to make sure this is not completely broken. + if want, have := 100, sysRoots.len(); have < want { + t.Errorf("want at least %d system roots, have %d", want, have) + } + + if t.Failed() { + cmd := exec.Command("security", "dump-trust-settings") + cmd.Stdout, cmd.Stderr = os.Stderr, os.Stderr + cmd.Run() + cmd = exec.Command("security", "dump-trust-settings", "-d") + cmd.Stdout, cmd.Stderr = os.Stderr, os.Stderr + cmd.Run() + } +} diff --git a/src/crypto/x509/root_ios.go b/src/crypto/x509/root_ios.go new file mode 100644 index 0000000..9bc62f8 --- /dev/null +++ b/src/crypto/x509/root_ios.go @@ -0,0 +1,4873 @@ +// Code generated by root_ios_gen.go -version 55188.120.1.0.1; DO NOT EDIT. +// Update the version in root.go and regenerate with "go generate". + +//go:build ios && !x509omitbundledroots +// +build ios,!x509omitbundledroots + +package x509 + +func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { + return nil, nil +} + +func loadSystemRoots() (*CertPool, error) { + p := NewCertPool() + p.AppendCertsFromPEM([]byte(systemRootsPEM)) + return p, nil +} + +const systemRootsPEM = ` +# "AAA Certificate Services" +# D7 A7 A0 FB 5D 7E 27 31 D7 71 E9 48 4E BC DE F7 +# 1D 5F 0C 3E 0A 29 48 78 2B C8 3E E0 EA 69 9E F4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- +# "AC RAIZ FNMT-RCM" +# EB C5 57 0C 29 01 8C 4D 67 B1 AA 12 7B AF 12 F7 +# 03 B4 61 1E BC 17 B7 DA B5 57 38 94 17 9B 93 FA +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ +WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ +BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG +Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ +yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf +BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz +WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF +tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z +374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC +IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL +mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 +wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS +MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 +ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet +UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H +YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 +LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 +RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM +LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf +77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N +JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm +fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp +6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp +1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B +9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok +RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv +uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- +# "Actalis Authentication Root CA" +# 55 92 60 84 EC 96 3A 64 B9 6E 2A BE 01 CE 0B A8 +# 6A 64 FB FE BC C7 AA B5 AF C1 55 B3 7F D7 60 66 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- +# "Admin-Root-CA" +# A3 1F 09 30 53 BD 12 C1 F5 C3 C6 EF D4 98 02 3F +# D2 91 4D 77 58 D0 5D 69 8C E0 84 B5 06 26 E0 E5 +-----BEGIN CERTIFICATE----- +MIIFVTCCBD2gAwIBAgIEO/OB0DANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJj +aDEOMAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZpY2VzMSIwIAYDVQQLExlD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMRYwFAYDVQQDEw1BZG1pbi1Sb290LUNB +MB4XDTAxMTExNTA4NTEwN1oXDTIxMTExMDA3NTEwN1owbDELMAkGA1UEBhMCY2gx +DjAMBgNVBAoTBWFkbWluMREwDwYDVQQLEwhTZXJ2aWNlczEiMCAGA1UECxMZQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdGllczEWMBQGA1UEAxMNQWRtaW4tUm9vdC1DQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMvgr0QUIv5qF0nyXZ3PXAJi +C4C5Wr+oVTN7oxIkXkxvO0GJToM9n7OVJjSmzBL0zJ2HXj0MDRcvhSY+KiZZc6Go +vDvr5Ua481l7ILFeQAFtumeza+vvxeL5Nd0Maga2miiacLNAKXbAcUYRa0Ov5VZB +++YcOYNNt/aisWbJqA2y8He+NsEgJzK5zNdayvYXQTZN+7tVgWOck16Da3+4FXdy +fH1NCWtZlebtMKtERtkVAaVbiWW24CjZKAiVfggjsiLo3yVMPGj3budLx5D9hEEm +vlyDOtcjebca+AcZglppWMX/iHIrx7740y0zd6cWEqiLIcZCrnpkr/KzwO135GkC +AwEAAaOCAf0wggH5MA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIASBkTCBjjCBiwYI +YIV0AREDAQAwfzArBggrBgEFBQcCAjAfGh1UaGlzIGlzIHRoZSBBZG1pbi1Sb290 +LUNBIENQUzBQBggrBgEFBQcCARZEaHR0cDovL3d3dy5pbmZvcm1hdGlrLmFkbWlu +LmNoL1BLSS9saW5rcy9DUFNfMl8xNl83NTZfMV8xN18zXzFfMC5wZGYwfwYDVR0f +BHgwdjB0oHKgcKRuMGwxFjAUBgNVBAMTDUFkbWluLVJvb3QtQ0ExIjAgBgNVBAsT +GUNlcnRpZmljYXRpb24gQXV0aG9yaXRpZXMxETAPBgNVBAsTCFNlcnZpY2VzMQ4w +DAYDVQQKEwVhZG1pbjELMAkGA1UEBhMCY2gwHQYDVR0OBBYEFIKf+iNzIPGXi7JM +Tb5CxX9mzWToMIGZBgNVHSMEgZEwgY6AFIKf+iNzIPGXi7JMTb5CxX9mzWTooXCk +bjBsMQswCQYDVQQGEwJjaDEOMAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZp +Y2VzMSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMRYwFAYDVQQD +Ew1BZG1pbi1Sb290LUNBggQ784HQMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0B +AQUFAAOCAQEAeE96XCYRpy6umkPKXDWCRn7INo96ZrWpMggcDORuofHIwdTkgOeM +vWOxDN/yuT7CC3FAaUajbPRbDw0hRMcqKz0aC8CgwcyIyhw/rFK29mfNTG3EviP9 +QSsEbnelFnjpm1wjz4EaBiFjatwpUbI6+Zv3XbEt9QQXBn+c6DeFLe4xvC4B+MTr +a440xTk59pSYux8OHhEvqIwHCkiijGqZhTS3KmGFeBopaR+dJVBRBMoXwzk4B3Hn +0Zib1dEYFZa84vPJZyvxCbLOnPRDJgH6V2uQqbG+6DXVaf/wORVOvF/wzzv0viM/ +RWbEtJZdvo8N3sdtCULzifnxP/V0T9+4ZQ== +-----END CERTIFICATE----- +# "AffirmTrust Commercial" +# 03 76 AB 1D 54 C5 F9 80 3C E4 B2 E2 01 A0 EE 7E +# EF 7B 57 B6 36 E8 A9 3C 9B 8D 48 60 C9 6F 5F A7 +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- +# "AffirmTrust Networking" +# 0A 81 EC 5A 92 97 77 F1 45 90 4A F3 8D 5D 50 9F +# 66 B5 E2 C5 8F CD B5 31 05 8B 0E 17 F3 F0 B4 1B +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- +# "AffirmTrust Premium" +# 70 A7 3F 7F 37 6B 60 07 42 48 90 45 34 B1 14 82 +# D5 BF 0E 69 8E CC 49 8D F5 25 77 EB F2 E9 3B 9A +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- +# "AffirmTrust Premium ECC" +# BD 71 FD F6 DA 97 E4 CF 62 D1 64 7A DD 25 81 B0 +# 7D 79 AD F8 39 7E B4 EC BA 9C 5E 84 88 82 14 23 +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- +# "Amazon Root CA 1" +# 8E CD E6 88 4F 3D 87 B1 12 5B A3 1A C3 FC B1 3D +# 70 16 DE 7F 57 CC 90 4F E1 CB 97 C6 AE 98 19 6E +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- +# "Amazon Root CA 2" +# 1B A5 B2 AA 8C 65 40 1A 82 96 01 18 F8 0B EC 4F +# 62 30 4D 83 CE C4 71 3A 19 C3 9C 01 1E A4 6D B4 +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- +# "Amazon Root CA 3" +# 18 CE 6C FE 7B F1 4E 60 B2 E3 47 B8 DF E8 68 CB +# 31 D0 2E BB 3A DA 27 15 69 F5 03 43 B4 6D B3 A4 +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- +# "Amazon Root CA 4" +# E3 5D 28 41 9E D0 20 25 CF A6 90 38 CD 62 39 62 +# 45 8D A5 C6 95 FB DE A3 C2 2B 0B FB 25 89 70 92 +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- +# "ANF Global Root CA" +# E3 26 8F 61 06 BA 8B 66 5A 1A 96 2D DE A1 45 9D +# 2A 46 97 2F 1F 24 40 32 9B 39 0B 89 57 49 AD 45 +-----BEGIN CERTIFICATE----- +MIIIGDCCBgCgAwIBAgIGAT8vMXfmMA0GCSqGSIb3DQEBCwUAMIIBCjELMAkGA1UE +BhMCRVMxEjAQBgNVBAgMCUJhcmNlbG9uYTFYMFYGA1UEBwxPQmFyY2Vsb25hIChz +ZWUgY3VycmVudCBhZGRyZXNzIGF0IGh0dHA6Ly93d3cuYW5mLmVzL2VzL2FkZHJl +c3MtZGlyZWNjaW9uLmh0bWwgKTEnMCUGA1UECgweQU5GIEF1dG9yaWRhZCBkZSBD +ZXJ0aWZpY2FjaW9uMRcwFQYDVQQLDA5BTkYgQ2xhc2UgMSBDQTEaMBgGCSqGSIb3 +DQEJARYLaW5mb0BhbmYuZXMxEjAQBgNVBAUTCUc2MzI4NzUxMDEbMBkGA1UEAwwS +QU5GIEdsb2JhbCBSb290IENBMB4XDTEzMDYxMDE3NDUzOFoXDTMzMDYwNTE3NDUz +OFowggEKMQswCQYDVQQGEwJFUzESMBAGA1UECAwJQmFyY2Vsb25hMVgwVgYDVQQH +DE9CYXJjZWxvbmEgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgaHR0cDovL3d3dy5h +bmYuZXMvZXMvYWRkcmVzcy1kaXJlY2Npb24uaHRtbCApMScwJQYDVQQKDB5BTkYg +QXV0b3JpZGFkIGRlIENlcnRpZmljYWNpb24xFzAVBgNVBAsMDkFORiBDbGFzZSAx +IENBMRowGAYJKoZIhvcNAQkBFgtpbmZvQGFuZi5lczESMBAGA1UEBRMJRzYzMjg3 +NTEwMRswGQYDVQQDDBJBTkYgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDHPi9xy4wynbcUbWjorVUgQKeUAVh937J7P37XmsfH +ZLOBZKIIlhhCtRwnDlg7x+BUvtJOTkIbEGMujDygUQ2s3HDYr5I41hTyM2Pl0cq2 +EuSGEbPIHb3dEX8NAguFexM0jqNjrreN3hM2/+TOkAxSdDJP2aMurlySC5zwl47K +ZLHtcVrkZnkDa0o5iN24hJT4vBDT4t2q9khQ+qb1D8KgCOb02r1PxWXu3vfd6Ha2 +mkdB97iGuEh5gO2n4yOmFS5goFlVA2UdPbbhJsb8oKVKDd+YdCKGQDCkQyG4AjmC +YiNm3UPG/qtftTH5cWri67DlLtm6fyUFOMmO6NSh0RtR745pL8GyWJUanyq/Q4bF +HQB21E+WtTsCaqjGaoFcrBunMypmCd+jUZXl27TYENRFbrwNdAh7m2UztcIyb+Sg +VJFyfvVsBQNvnp7GPimVxXZNc4VpxEXObRuPWQN1oZN/90PcZVqTia/SHzEyTryL +ckhiLG3jZiaFZ7pTZ5I9wti9Pn+4kOHvE3Y/4nEnUo4mTxPX9pOlinF+VCiybtV2 +u1KSlc+YaIM7VmuyndDZCJRXm3v0/qTE7t5A5fArZl9lvibigMbWB8fpD+c1GpGH +Eo8NRY0lkaM+DkIqQoaziIsz3IKJrfdKaq9bQMSlIfameKBZ8fNYTBZrH9KZAIhz +YwIDAQABo4IBfjCCAXowHQYDVR0OBBYEFIf6nt9SdnXsSUogb1twlo+d77sXMB8G +A1UdIwQYMBaAFIf6nt9SdnXsSUogb1twlo+d77sXMA8GA1UdEwEB/wQFMAMBAf8w +DgYDVR0PAQH/BAQDAgEGMIIBFQYDVR0RBIIBDDCCAQiCEWh0dHA6Ly93d3cuYW5m +LmVzgQtpbmZvQGFuZi5lc6SB5TCB4jE0MDIGA1UECQwrR3JhbiBWaWEgZGUgbGVz +IENvcnRzIENhdGFsYW5lcy4gOTk2LiAwODAxODESMBAGA1UEBwwJQmFyY2Vsb25h +MScwJQYDVQQKDB5BTkYgQXV0b3JpZGFkIGRlIENlcnRpZmljYWNpb24xEjAQBgNV +BAUTCUc2MzI4NzUxMDFZMFcGA1UECwxQSW5zY3JpdGEgZW4gZWwgTWluaXN0ZXJp +byBkZWwgSW50ZXJpb3IgZGUgRXNwYcOxYSBjb24gZWwgbnVtZXJvIG5hY2lvbmFs +IDE3MS40NDMwDQYJKoZIhvcNAQELBQADggIBAIgR9tFTZ9BCYg+HViMxOfF0MHN2 +Pe/eC128ARdS+GH8A4thtbqiH/SOYbWofO/0zssHhNKa5iQEj45lCAb8BANpWJMD +nWkPr6jq2+50a6d0MMgSS2l1rvjSF+3nIrEuicshHXSTi3q/vBLKr7uGKMVFaM68 +XAropIwk6ndlA0JseARSPsbetv7ALESMIZAxlHV1TcctYHd0bB3c/Jz+PLszJQqs +Cg/kBPo2D111OXZkIY8W/fJuG9veR783khAK2gUnC0zLLCNsYzEbdGt8zUmBsAsM +cGxqGm6B6vDXd65OxWqw13xdq/24+5R8Ng1PF9tvfjZkUFBF30CxjWur7P90WiKI +G7IGfr6BE1NgXlhEQQu4F+HizB1ypEPzGWltecXQ4yOzO+H0WfFTjLTYX6VSveyW +DQV18ixF8M4tHP/SwNE+yyv2b2JJ3/3RpxjtFlLk+opJ574x0gD/dMJuWTH0JqVY +3PbRfE1jIxFpk164Qz/Xp7H7w7f6xh+tQCkBs3PUYmnGIZcPwq44Q6JHlCNsKx4K +hxfggTvRCk4w79cUID45c2qDsRCqTPoOo/cbOpcfVhbH9LdMORpmuLwNogRZEUSE +fWpqR9q+0kcQf4zGSWIURIyDrogdpDgoHDxktqgMgc+qA4ZE2WQl1D8hmev53A46 +lUSrWUiWfDXtK3ux +-----END CERTIFICATE----- +# "Apple Root CA" +# B0 B1 73 0E CB C7 FF 45 05 14 2C 49 F1 29 5E 6E +# DA 6B CA ED 7E 2C 68 C5 BE 91 B5 A1 10 01 F0 24 +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET +MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDYwNDI1MjE0 +MDM2WhcNMzUwMjA5MjE0MDM2WjBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw +bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +FjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDkkakJH5HbHkdQ6wXtXnmELes2oldMVeyLGYne+Uts9QerIjAC6Bg+ ++FAJ039BqJj50cpmnCRrEdCju+QbKsMflZ56DKRHi1vUFjczy8QPTc4UadHJGXL1 +XQ7Vf1+b8iUDulWPTV0N8WQ1IxVLFVkds5T39pyez1C6wVhQZ48ItCD3y6wsIG9w +tj8BMIy3Q88PnT3zK0koGsj+zrW5DtleHNbLPbU6rfQPDgCSC7EhFi501TwN22IW +q6NxkkdTVcGvL0Gz+PvjcM3mo0xFfh9Ma1CWQYnEdGILEINBhzOKgbEwWOxaBDKM +aLOPHd5lc/9nXmW8Sdh2nzMUZaF3lMktAgMBAAGjggF6MIIBdjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUK9BpR5R2Cf70a40uQKb3 +R01/CF4wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wggERBgNVHSAE +ggEIMIIBBDCCAQAGCSqGSIb3Y2QFATCB8jAqBggrBgEFBQcCARYeaHR0cHM6Ly93 +d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEFBQcCAjCBthqBs1JlbGlhbmNl +IG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0 +YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBj +b25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZp +Y2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMA0GCSqGSIb3DQEBBQUAA4IBAQBc +NplMLXi37Yyb3PN3m/J20ncwT8EfhYOFG5k9RzfyqZtAjizUsZAS2L70c5vu0mQP +y3lPNNiiPvl4/2vIB+x9OYOLUyDTOMSxv5pPCmv/K/xZpwUJfBdAVhEedNO3iyM7 +R6PVbyTi69G3cN8PReEnyvFteO3ntRcXqNx+IjXKJdXZD9Zr1KIkIxH3oayPc4Fg +xhtbCS+SsvhESPBgOJ4V9T0mZyCKM2r3DYLP3uujL/lTaltkwGMzd/c6ByxW69oP +IQ7aunMZT7XZNn/Bh1XZp5m5MkL72NVxnn6hUrcbvZNCJBIqxw8dtk2cXmPIS4AX +UKqK1drk/NAJBzewdXUh +-----END CERTIFICATE----- +# "Apple Root CA - G2" +# C2 B9 B0 42 DD 57 83 0E 7D 11 7D AC 55 AC 8A E1 +# 94 07 D3 8E 41 D8 8F 32 15 BC 3A 89 04 44 A0 50 +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIIAeDltYNno+AwDQYJKoZIhvcNAQEMBQAwZzEbMBkGA1UE +AwwSQXBwbGUgUm9vdCBDQSAtIEcyMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMw +HhcNMTQwNDMwMTgxMDA5WhcNMzkwNDMwMTgxMDA5WjBnMRswGQYDVQQDDBJBcHBs +ZSBSb290IENBIC0gRzIxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBANgREkhI2imKScUcx+xuM23+TfvgHN6s +XuI2pyT5f1BrTM65MFQn5bPW7SXmMLYFN14UIhHF6Kob0vuy0gmVOKTvKkmMXT5x +ZgM4+xb1hYjkWpIMBDLyyED7Ul+f9sDx47pFoFDVEovy3d6RhiPw9bZyLgHaC/Yu +OQhfGaFjQQscp5TBhsRTL3b2CtcM0YM/GlMZ81fVJ3/8E7j4ko380yhDPLVoACVd +J2LT3VXdRCCQgzWTxb+4Gftr49wIQuavbfqeQMpOhYV4SbHXw8EwOTKrfl+q04tv +ny0aIWhwZ7Oj8ZhBbZF8+NfbqOdfIRqMM78xdLe40fTgIvS/cjTf94FNcX1RoeKz +8NMoFnNvzcytN31O661A4T+B/fc9Cj6i8b0xlilZ3MIZgIxbdMYs0xBTJh0UT8TU +gWY8h2czJxQI6bR3hDRSj4n4aJgXv8O7qhOTH11UL6jHfPsNFL4VPSQ08prcdUFm +IrQB1guvkJ4M6mL4m1k8COKWNORj3rw31OsMiANDC1CvoDTdUE0V+1ok2Az6DGOe +HwOx4e7hqkP0ZmUoNwIx7wHHHtHMn23KVDpA287PT0aLSmWaasZobNfMmRtHsHLD +d4/E92GcdB/O/WuhwpyUgquUoue9G7q5cDmVF8Up8zlYNPXEpMZ7YLlmQ1A/bmH8 +DvmGqmAMQ0uVAgMBAAGjQjBAMB0GA1UdDgQWBBTEmRNsGAPCe8CjoA1/coB6HHcm +jTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwF +AAOCAgEAUabz4vS4PZO/Lc4Pu1vhVRROTtHlznldgX/+tvCHM/jvlOV+3Gp5pxy+ +8JS3ptEwnMgNCnWefZKVfhidfsJxaXwU6s+DDuQUQp50DhDNqxq6EWGBeNjxtUVA +eKuowM77fWM3aPbn+6/Gw0vsHzYmE1SGlHKy6gLti23kDKaQwFd1z4xCfVzmMX3z +ybKSaUYOiPjjLUKyOKimGY3xn83uamW8GrAlvacp/fQ+onVJv57byfenHmOZ4VxG +/5IFjPoeIPmGlFYl5bRXOJ3riGQUIUkhOb9iZqmxospvPyFgxYnURTbImHy99v6Z +SYA7LNKmp4gDBDEZt7Y6YUX6yfIjyGNzv1aJMbDZfGKnexWoiIqrOEDCzBL/FePw +N983csvMmOa/orz6JopxVtfnJBtIRD6e/J/JzBrsQzwBvDR4yGn1xuZW7AYJNpDr +FEobXsmII9oDMJELuDY++ee1KG++P+w8j2Ud5cAeh6Squpj9kuNsJnfdBrRkBof0 +Tta6SqoWqPQFZ2aWuuJVecMsXUmPgEkrihLHdoBR37q9ZV0+N0djMenl9MU/S60E +inpxLK8JQzcPqOMyT/RFtm2XNuyE9QoB6he7hY1Ck3DDUOUUi78/w0EP3SIEIwiK +um1xRKtzCTrJ+VKACd+66eYWyi4uTLLT3OUEVLLUNIAytbwPF+E= +-----END CERTIFICATE----- +# "Apple Root CA - G3" +# 63 34 3A BF B8 9A 6A 03 EB B5 7E 9B 3F 5F A7 BE +# 7C 4F 5C 75 6F 30 17 B3 A8 C4 88 C3 65 3E 91 79 +-----BEGIN CERTIFICATE----- +MIICQzCCAcmgAwIBAgIILcX8iNLFS5UwCgYIKoZIzj0EAwMwZzEbMBkGA1UEAwwS +QXBwbGUgUm9vdCBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwHhcN +MTQwNDMwMTgxOTA2WhcNMzkwNDMwMTgxOTA2WjBnMRswGQYDVQQDDBJBcHBsZSBS +b290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABJjpLz1AcqTtkyJygRMc3RCV8cWjTnHcFBbZDuWmBSp3ZHtf +TjjTuxxEtX/1H7YyYl3J6YRbTzBPEVoA/VhYDKX1DyxNB0cTddqXl5dvMVztK517 +IDvYuVTZXpmkOlEKMaNCMEAwHQYDVR0OBBYEFLuw3qFYM4iapIqZ3r6966/ayySr +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gA +MGUCMQCD6cHEFl4aXTQY2e3v9GwOAEZLuN+yRhHFD/3meoyhpmvOwgPUnPWTxnS4 +at+qIxUCMG1mihDK1A3UT82NQz60imOlM27jbdoXt2QfyFMm+YhidDkLF1vLUagM +6BgD56KyKA== +-----END CERTIFICATE----- +# "Apple Root Certificate Authority" +# 0D 83 B6 11 B6 48 A1 A7 5E B8 55 84 00 79 53 75 +# CA D9 2E 26 4E D8 E9 D7 A7 57 C1 F5 EE 2B B2 2D +-----BEGIN CERTIFICATE----- +MIIFujCCBKKgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhjELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD +b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIEFwcGxlIFJv +b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA1MDIxMDAwMTgxNFoXDTI1MDIx +MDAwMTgxNFowgYYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBcHBsZSBDb21wdXRl +ciwgSW5jLjEtMCsGA1UECxMkQXBwbGUgQ29tcHV0ZXIgQ2VydGlmaWNhdGUgQXV0 +aG9yaXR5MSkwJwYDVQQDEyBBcHBsZSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOSRqQkfkdseR1DrBe1e +eYQt6zaiV0xV7IsZid75S2z1B6siMALoGD74UAnTf0GomPnRymacJGsR0KO75Bsq +wx+VnnoMpEeLW9QWNzPLxA9NzhRp0ckZcvVdDtV/X5vyJQO6VY9NXQ3xZDUjFUsV +WR2zlPf2nJ7PULrBWFBnjwi0IPfLrCwgb3C2PwEwjLdDzw+dPfMrSSgayP7OtbkO +2V4c1ss9tTqt9A8OAJILsSEWLnTVPA3bYharo3GSR1NVwa8vQbP4++NwzeajTEV+ +H0xrUJZBicR0YgsQg0GHM4qBsTBY7FoEMoxos48d3mVz/2deZbxJ2HafMxRloXeU +yS0CAwEAAaOCAi8wggIrMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBQr0GlHlHYJ/vRrjS5ApvdHTX8IXjAfBgNVHSMEGDAWgBQr0GlH +lHYJ/vRrjS5ApvdHTX8IXjCCASkGA1UdIASCASAwggEcMIIBGAYJKoZIhvdjZAUB +MIIBCTBBBggrBgEFBQcCARY1aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmlj +YXRlYXV0aG9yaXR5L3Rlcm1zLmh0bWwwgcMGCCsGAQUFBwICMIG2GoGzUmVsaWFu +Y2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2Nl +cHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5k +IGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRp +ZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wRAYDVR0fBD0wOzA5oDegNYYz +aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L3Jvb3Qu +Y3JsMFUGCCsGAQUFBwEBBEkwRzBFBggrBgEFBQcwAoY5aHR0cHM6Ly93d3cuYXBw +bGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L2Nhc2lnbmVycy5odG1sMA0GCSqG +SIb3DQEBBQUAA4IBAQCd2i0oWC99dgS5BNM+zrdmY06PL9T+S61yvaM5xlJNBZhS +9YlRASR5vhoy9+VEi0tEBzmC1lrKtCBe2a4VXR2MHTK/ODFiSF3H4ZCx+CRA+F9Y +m1FdV53B5f88zHIhbsTp6aF31ywXJsM/65roCwO66bNKcuszCVut5mIxauivL9Wv +Hld2j383LS4CXN1jyfJxuCZA3xWNdUQ/eb3mHZnhQyw+rW++uaT+DjUZUWOxw961 +kj5ReAFziqQjyqSI8R5cH0EWLX6VCqrpiUGYGxrdyyC/R14MJsVVNU3GMIuZZxTH +CR+6R8faAQmHJEKVvRNgGQrv6n8Obs3BREM6StXj +-----END CERTIFICATE----- +# "Atos TrustedRoot 2011" +# F3 56 BE A2 44 B7 A9 1E B3 5D 53 CA 9A D7 86 4A +# CE 01 8E 2D 35 D5 F8 F9 6D DF 68 A6 F4 1A A4 74 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- +# "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# 04 04 80 28 BF 1F 28 64 D4 8F 9A D4 D8 32 94 36 +# 6A 82 88 56 55 3F 3B 14 30 3F 90 14 7F 5D 40 EF +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy +MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD +VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv +ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl +AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF +661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 +am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 +ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 +PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS +3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k +SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF +3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM +ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g +StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz +Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB +jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- +# "Autoridad de Certificacion Raiz del Estado Venezolano" +# 0E D3 FF AB 6C 14 9C 8B 4E 71 05 8E 86 68 D4 29 +# AB FD A6 81 C2 FF F5 08 20 76 41 F0 D7 51 A3 E5 +-----BEGIN CERTIFICATE----- +MIIJmzCCB4OgAwIBAgIBATANBgkqhkiG9w0BAQwFADCCAR4xPjA8BgNVBAMTNUF1 +dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9s +YW5vMQswCQYDVQQGEwJWRTEQMA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlz +dHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0 +aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBlcmludGVuZGVuY2lh +IGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUwIwYJ +KoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyMjE4MDgy +MVoXDTMwMTIxNzIzNTk1OVowggEeMT4wPAYDVQQDEzVBdXRvcmlkYWQgZGUgQ2Vy +dGlmaWNhY2lvbiBSYWl6IGRlbCBFc3RhZG8gVmVuZXpvbGFubzELMAkGA1UEBhMC +VkUxEDAOBgNVBAcTB0NhcmFjYXMxGTAXBgNVBAgTEERpc3RyaXRvIENhcGl0YWwx +NjA0BgNVBAoTLVNpc3RlbWEgTmFjaW9uYWwgZGUgQ2VydGlmaWNhY2lvbiBFbGVj +dHJvbmljYTFDMEEGA1UECxM6U3VwZXJpbnRlbmRlbmNpYSBkZSBTZXJ2aWNpb3Mg +ZGUgQ2VydGlmaWNhY2lvbiBFbGVjdHJvbmljYTElMCMGCSqGSIb3DQEJARYWYWNy +YWl6QHN1c2NlcnRlLmdvYi52ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAME77xNS8ZlW47RsBeEaaRZhJoZ4rw785UAFCuPZOAVMqNS1wMYqzy95q6Gk +UO81ER/ugiQX/KMcq/4HBn83fwdYWxPZfwBfK7BP2p/JsFgzYeFP0BXOLmvoJIzl +Jb6FW+1MPwGBjuaZGFImWZsSmGUclb51mRYMZETh9/J5CLThR1exStxHQptwSzra +zNFpkQY/zmj7+YZNA9yDoroVFv6sybYOZ7OxNDo7zkSLo45I7gMwtxqWZ8VkJZkC +8+p0dX6mkhUT0QAV64Zc9HsZiH/oLhEkXjhrgZ28cF73MXIqLx1fyM4kPH1yOJi/ +R72nMwL7D+Sd6mZgI035TxuHXc2/uOwXfKrrTjaJDz8Jp6DdessOkxIgkKXRjP+F +K3ze3n4NUIRGhGRtyvEjK95/2g02t6PeYiYVGur6ruS49n0RAaSS0/LJb6XzaAAe +0mmO2evnEqxIKwy2mZRNPfAVW1l3wCnWiUwryBU6OsbFcFFrQm+00wOicXvOTHBM +aiCVAVZTb9RSLyi+LJ1llzJZO3pq3IRiiBj38Nooo+2ZNbMEciSgmig7YXaUcmud +SVQvLSL+Yw+SqawyezwZuASbp7d/0rutQ59d81zlbMt3J7yB567rT2IqIydQ8qBW +k+fmXzghX+/FidYsh/aK+zZ7Wy68kKHuzEw1Vqkat5DGs+VzAgMBAAGjggLeMIIC +2jASBgNVHRMBAf8ECDAGAQH/AgECMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52 +ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0wMB0GA1UdDgQWBBStuyIdxuDS +Aaj9dlBSk+2YwU2u0zCCAVAGA1UdIwSCAUcwggFDgBStuyIdxuDSAaj9dlBSk+2Y +wU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRpZmlj +YWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAw +DgYDVQQHEwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYD +VQQKEy1TaXN0ZW1hIE5hY2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25p +Y2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5kZW5jaWEgZGUgU2VydmljaW9zIGRlIENl +cnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG9w0BCQEWFmFjcmFpekBz +dXNjZXJ0ZS5nb2IudmWCAQEwDgYDVR0PAQH/BAQDAgEGMDcGA1UdEQQwMC6CD3N1 +c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0wMFQGA1Ud +HwRNMEswJKAioCCGHmhodHA6Ly93d3cuc3VzY2VydGUuZ29iLnZlL2xjcjAjoCGg +H4YdbGRhcDovL2FjcmFpei5zdXNjZXJ0ZS5nb2IudmUwNwYIKwYBBQUHAQEEKzAp +MCcGCCsGAQUFBzABhhtoaHRwOi8vb2NzcC5zdXNjZXJ0ZS5nb2IudmUwQAYDVR0g +BDkwNzA1BgVghl4BAjAsMCoGCCsGAQUFBwIBFh5odHRwOi8vd3d3LnN1c2NlcnRl +LmdvYi52ZS9kcGMwDQYJKoZIhvcNAQEMBQADggIBAK4qy/zmZ9zBwfW3yOYtLcBT +Oy4szJyPz7/RhNH3bPVH7HbDTGpi6JZ4YXdXMBeJE5qBF4a590Kgj8Rlnltt+Rbo +OFQOU1UDqKuTdBsA//Zry5899fmn8jBUkg4nh09jhHHbLlaUScdz704Zz2+UVg7i +s/r3Legxap60KzmdrmTAE9VKte1TQRgavQwVX5/2mO/J+SCas//UngI+h8SyOucq +mjudYEgBrZaodUsagUfn/+AzFNrGLy+al+5nZeHb8JnCfLHWS0M9ZyhgoeO/czyn +99+5G93VWNv4zfc4KiavHZKrkn8F9pg0ycIZh+OwPT/RE2zq4gTazBMlP3ACIe/p +olkNaOEa8KvgzW96sjBZpMW49zFmyINYkcj+uaNCJrVGsXgdBmkuRGJNWFZ9r0cG +woIaxViFBypsz045r1ESfYPlfDOavBhZ/giR/Xocm9CHkPRY2BApMMR0DUCyGETg +Ql+L3kfdTKzuDjUp2DM9FqysQmaM81YDZufWkMhlZPfHwC7KbNougoLroa5Umeos +bqAXWmk46SwIdWRPLLqbUpDTKooynZKpSYIkkotdgJoVZUUCY+RCO8jsVPEU6ece +SxztNUm5UOta1OJPMwSAKRHOo3ilVb9c6lAixDdvV8MeNbqe6asM1mpCHWbJ/0rg +5Ls9Cxx8hracyp0ev7b0 +-----END CERTIFICATE----- +# "Baltimore CyberTrust Root" +# 16 AF 57 A9 F6 76 B0 AB 12 60 95 AA 5E BA DE F2 +# 2A B3 11 19 D6 44 AC 95 CD 4B 93 DB F3 F2 6A EB +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- +# "Belgium Root CA2" +# 9F 97 44 46 3B E1 37 14 75 4E 1A 3B EC F9 8C 08 +# CC 20 5E 4A B3 20 28 F4 E2 83 0C 4A 1B 27 75 B8 +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIIKv++n6Lw6YcwDQYJKoZIhvcNAQEFBQAwKDELMAkGA1UE +BhMCQkUxGTAXBgNVBAMTEEJlbGdpdW0gUm9vdCBDQTIwHhcNMDcxMDA0MTAwMDAw +WhcNMjExMjE1MDgwMDAwWjAoMQswCQYDVQQGEwJCRTEZMBcGA1UEAxMQQmVsZ2l1 +bSBSb290IENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMZzQh6S +/3UPi790hqc/7bIYLS2X+an7mEoj39WN4IzGMhwWLQdC1i22bi+n9fzGhYJdld61 +IgDMqFNAn68KNaJ6x+HK92AQZw6nUHMXU5WfIp8MXW+2QbyM69odRr2nlL/zGsvU ++40OHjPIltfsjFPekx40HopQcSZYtF3CiInaYNKJIT/e1wEYNm7hLHADBGXvmAYr +XR5i3FVr/mZkIV/4L+HXmymvb82fqgxG0YjFnaKVn6w/Fa7yYd/vw2uaItgscf1Y +HewApDgglVrH1Tdjuk+bqv5WRi5j2Qsj1Yr6tSPwiRuhFA0m2kHwOI8w7QUmecFL +TqG4flVSOmlGhHUCAwEAAaOBuzCBuDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zBCBgNVHSAEOzA5MDcGBWA4CQEBMC4wLAYIKwYBBQUHAgEWIGh0dHA6 +Ly9yZXBvc2l0b3J5LmVpZC5iZWxnaXVtLmJlMB0GA1UdDgQWBBSFiuv0xbu+DlkD +lN7WgAEV4xCcOTARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUhYrr9MW7 +vg5ZA5Te1oABFeMQnDkwDQYJKoZIhvcNAQEFBQADggEBAFHYhd27V2/MoGy1oyCc +UwnzSgEMdL8rs5qauhjyC4isHLMzr87lEwEnkoRYmhC598wUkmt0FoqW6FHvv/pK +JaeJtmMrXZRY0c8RcrYeuTlBFk0pvDVTC9rejg7NqZV3JcqUWumyaa7YwBO+mPyW +nIR/VRPmPIfjvCCkpDZoa01gZhz5v6yAlGYuuUGK02XThIAC71AdXkbc98m6tTR8 +KvPG2F9fVJ3bTc0R5/0UAoNmXsimABKgX77OFP67H6dh96tK8QYUn8pJQsKpvO2F +sauBQeYNxUJpU4c5nUwfAA4+Bw11V0SoU7Q2dmSZ3G7rPUZuFF1eR1ONeE3gJ7uO +hXY= +-----END CERTIFICATE----- +# "Buypass Class 2 Root CA" +# 9A 11 40 25 19 7C 5B B9 5D 94 E6 3D 55 CD 43 79 +# 08 47 B6 46 B2 3C DF 11 AD A4 A0 0E FF 15 FB 48 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- +# "Buypass Class 3 Root CA" +# ED F7 EB BC A2 7A 2A 38 4D 38 7B 7D 40 10 C6 66 +# E2 ED B4 84 3E 4C 29 B4 AE 1D 5B 93 32 E6 B2 4D +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- +# "CA Disig Root R1" +# F9 6F 23 F4 C3 E7 9C 07 7A 46 98 8D 5A F5 90 06 +# 76 A0 F0 39 CB 64 5D D1 75 49 B2 16 C8 24 40 CE +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy +MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk +D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o +OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A +fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe +IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n +oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK +/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj +rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD +3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE +7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC +yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd +qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI +hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR +xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA +SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo +HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB +emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC +AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb +7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x +DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk +F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF +a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT +Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL +-----END CERTIFICATE----- +# "CA Disig Root R2" +# E2 3D 4A 03 6D 7B 70 E9 F5 95 B1 42 20 79 D2 B9 +# 1E DF BB 1F B6 51 A0 63 3E AA 8A 9D C5 F8 07 03 +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- +# "Certigna" +# E3 B6 A2 DB 2E D7 CE 48 84 2F 7A C5 32 41 C7 B7 +# 1D 54 14 4B FB 40 C1 1F 3F 1D 0B 42 F5 EE A1 2D +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- +# "Certinomis - Autorité Racine" +# FC BF E2 88 62 06 F7 2B 27 59 3C 8B 07 02 97 E1 +# 2D 76 9E D1 0E D7 93 07 05 A8 09 8E FF C1 4D 17 +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjET +MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAk +BgNVBAMMHUNlcnRpbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4 +Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNl +cnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0 +aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jY +F1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N +8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe +rP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K +/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu +7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC +28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6 +lSTClrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1E +nn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB +0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql09 +5gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29YnfAgMBAAGj +WzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN +jLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ +KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9s +ov3/4gbIOZ/xWqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZM +OH8oMDX/nyNTt7buFHAAQCvaR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q +619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40nJ+U8/aGH88bc62UeYdocMMzpXDn +2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1BCxMjidPJC+iKunqj +o3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjvJL1v +nxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG +5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq +pdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZb +dsLLO7XSAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0 +BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5 +-----END CERTIFICATE----- +# "Certinomis - Root CA" +# 2A 99 F5 BC 11 74 B7 3C BB 1D 62 08 84 E0 1C 34 +# E5 1C CB 39 78 DA 12 5F 0E 33 26 88 83 BF 41 58 +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET +MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb +BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz +MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx +FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g +Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 +fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl +LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV +WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF +TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb +5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc +CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri +wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ +wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG +m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 +F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng +WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 +2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF +AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ +0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw +F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS +g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj +qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN +h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ +ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V +btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj +Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ +8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW +gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= +-----END CERTIFICATE----- +# "Certplus Root CA G1" +# 15 2A 40 2B FC DF 2C D5 48 05 4D 22 75 B3 9C 7F +# CA 3E C0 97 80 78 B0 F0 EA 76 E5 61 A6 C7 43 3E +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA +MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy +dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa +MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy +dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a +iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt +6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP +0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f +6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE +EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN +1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc +h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT +mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV +4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO +WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud +DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd +Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq +hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh +66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 +/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS +S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j +2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R +Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr +RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy +6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV +V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 +g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl +++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= +-----END CERTIFICATE----- +# "Certplus Root CA G2" +# 6C C0 50 41 E6 44 5E 74 69 6C 4C FB C9 F8 0F 54 +# 3B 7E AB BB 44 B4 CE 6F 78 7C 6A 99 71 C4 2F 17 +-----BEGIN CERTIFICATE----- +MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x +CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs +dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x +CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs +dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat +93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x +Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P +AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj +FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG +SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch +p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal +U5ORGpOucGpnutee5WEaXw== +-----END CERTIFICATE----- +# "certSIGN ROOT CA" +# EA A9 62 C4 FA 4A 6B AF EB E4 15 19 6D 35 1C CD +# 88 8D 4F 53 F3 FA 8A E6 D7 C4 66 A9 4E 60 42 BB +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- +# "Certum CA" +# D8 E0 FE BC 1D B2 E3 8D 00 94 0F 37 D2 7D 41 34 +# 4D 99 3E 73 4B 99 D5 65 6D 97 78 D4 D8 14 36 24 +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E +jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo +ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI +ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu +Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg +AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 +HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA +uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa +TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg +xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q +CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x +O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs +6GAqm4VKQPNriiTsBhYscw== +-----END CERTIFICATE----- +# "Certum Trusted Network CA" +# 5C 58 46 8D 55 F5 8E 49 7E 74 39 82 D2 B5 00 10 +# B6 D1 65 37 4A CF 83 A7 D4 A3 2D B7 68 C4 40 8E +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- +# "Certum Trusted Network CA 2" +# B6 76 F2 ED DA E8 77 5C D3 6C B0 F6 3C D1 D4 60 +# 39 61 F4 9E 62 65 BA 01 3A 2F 03 07 B6 D0 B8 04 +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB +gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu +QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG +A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz +OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ +VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 +b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA +DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn +0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB +OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE +fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E +Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m +o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i +sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW +OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez +Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS +adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n +3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ +F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf +CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 +XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm +djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ +WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb +AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq +P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko +b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj +XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P +5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi +DrW5viSP +-----END CERTIFICATE----- +# "CFCA EV ROOT" +# 5C C3 D7 8E 4E 1D 5E 45 54 7A 04 E6 87 3E 64 F9 +# 0C F9 53 6D 1C CC 2E F8 00 F3 55 C4 C5 FD 70 FD +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx +MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP +T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 +sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL +TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 +/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp +7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz +EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt +hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP +a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot +aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg +TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV +PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv +cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL +tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT +ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL +jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS +ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy +P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 +xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d +Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN +5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe +/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z +AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ +5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- +# "Chambers of Commerce Root" +# 0C 25 8A 12 A5 67 4A EF 25 F2 8B A7 DC FA EC EE +# A3 48 E5 41 E6 F5 CC 4E E6 3B 71 B3 61 60 6A C3 +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg +b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa +MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB +ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw +IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B +AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb +unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d +BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq +7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 +0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX +roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG +A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j +aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p +26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA +BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud +EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN +BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB +AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd +p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi +1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc +XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 +eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu +tGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- +# "Chambers of Commerce Root - 2008" +# 06 3E 4A FA C4 91 DF D3 32 F3 08 9B 85 42 E9 46 +# 17 D8 93 D7 FE 94 4E 10 A7 93 7E E2 9D 96 93 C0 +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz +IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz +MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj +dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw +EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp +MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 +28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq +VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q +DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR +5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL +ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a +Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl +UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s ++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 +Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx +hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV +HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 ++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN +YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t +L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy +ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt +IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV +HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w +DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW +PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF +5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 +glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH +FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 +pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD +xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG +tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq +jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De +fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ +d0jQ +-----END CERTIFICATE----- +# "Cisco Root CA 2048" +# 83 27 BC 8C 9D 69 94 7B 3D E3 C2 75 11 53 72 67 +# F5 9C 21 B9 FA 7B 61 3F AF BC CD 53 B7 02 40 00 +-----BEGIN CERTIFICATE----- +MIIDQzCCAiugAwIBAgIQX/h7KCtU3I1CoxW1aMmt/zANBgkqhkiG9w0BAQUFADA1 +MRYwFAYDVQQKEw1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENB +IDIwNDgwHhcNMDQwNTE0MjAxNzEyWhcNMjkwNTE0MjAyNTQyWjA1MRYwFAYDVQQK +Ew1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENBIDIwNDgwggEg +MA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQCwmrmrp68Kd6ficba0ZmKUeIhH +xmJVhEAyv8CrLqUccda8bnuoqrpu0hWISEWdovyD0My5jOAmaHBKeN8hF570YQXJ +FcjPFto1YYmUQ6iEqDGYeJu5Tm8sUxJszR2tKyS7McQr/4NEb7Y9JHcJ6r8qqB9q +VvYgDxFUl4F1pyXOWWqCZe+36ufijXWLbvLdT6ZeYpzPEApk0E5tzivMW/VgpSdH +jWn0f84bcN5wGyDWbs2mAag8EtKpP6BrXruOIIt6keO1aO6g58QBdKhTCytKmg9l +Eg6CTY5j/e/rmxrbU6YTYK/CfdfHbBcl1HP7R2RQgYCUTOG/rksc35LtLgXfAgED +o1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUJ/PI +FR5umgIJFq0roIlgX9p7L6owEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEF +BQADggEBAJ2dhISjQal8dwy3U8pORFBi71R803UXHOjgxkhLtv5MOhmBVrBW7hmW +Yqpao2TB9k5UM8Z3/sUcuuVdJcr18JOagxEu5sv4dEX+5wW4q+ffy0vhN4TauYuX +cB7w4ovXsNgOnbFp1iqRe6lJT37mjpXYgyc81WhJDtSd9i7rp77rMKSsH0T8lasz +Bvt9YAretIpjsJyp8qS5UwGH0GikJ3+r/+n6yUA4iGe0OcaEb1fJU9u6ju7AQ7L4 +CYNu/2bPPu8Xs1gYJQk0XuPL1hS27PKSb3TkL4Eq1ZKR4OCXPDJoBYVL0fdX4lId +kxpUnwVwwEpxYB5DC2Ae/qPOgRnhCzU= +-----END CERTIFICATE----- +# "COMODO Certification Authority" +# 0C 2C D6 3D F7 80 6F A3 99 ED E8 09 11 6B 57 5B +# F8 79 89 F0 65 18 F9 80 8C 86 05 03 17 8B AF 66 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- +# "COMODO ECC Certification Authority" +# 17 93 92 7A 06 14 54 97 89 AD CE 2F 8F 34 F7 F0 +# B6 6D 0F 3A E3 A3 B8 4D 21 EC 15 DB BA 4F AD C7 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- +# "COMODO RSA Certification Authority" +# 52 F0 E1 C4 E5 8E C6 29 29 1B 60 31 7F 07 46 71 +# B8 5D 7E A8 0D 5B 07 27 34 63 53 4B 32 B4 02 34 +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- +# "ComSign CA" +# AE 44 57 B4 0D 9E DA 96 67 7B 0D 3C 92 D5 7B 51 +# 77 AB D7 AC 10 37 95 83 56 D1 E0 94 51 8B E5 F2 +-----BEGIN CERTIFICATE----- +MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0 +MRMwEQYDVQQDEwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQG +EwJJTDAeFw0wNDAzMjQxMTMyMThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMT +CkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNpZ24xCzAJBgNVBAYTAklMMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49qROR+WCf4C9DklBKK +8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTyP2Q2 +98CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb +2CEJKHxNGGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxC +ejVb7Us6eva1jsz/D3zkYDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7Kpi +Xd3DTKaCQeQzC6zJMw9kglcq/QytNuEMrkvF7zuZ2SOzW120V+x0cAwqTwIDAQAB +o4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Zl +ZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0PAQH/BAQD +AgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRL +AZs+VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWd +foPPbrxHbvUanlR2QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0M +cXS6hMTXcpuEfDhOZAYnKuGntewImbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq +8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb/627HOkthIDYIb6FUtnUdLlp +hbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VGzT2ouvDzuFYk +Res3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U +AGegcQCCSA== +-----END CERTIFICATE----- +# "ComSign Global Root CA" +# 26 05 87 5A FC C1 76 B2 D6 6D D6 6A 99 5D 7F 8D +# 5E BB 86 CE 12 0D 0E 7E 9E 7C 6E F2 94 A2 7D 4C +-----BEGIN CERTIFICATE----- +MIIGATCCA+mgAwIBAgIRAI9hcRW6eVgXjH0ROqzW264wDQYJKoZIhvcNAQELBQAw +RTEfMB0GA1UEAxMWQ29tU2lnbiBHbG9iYWwgUm9vdCBDQTEVMBMGA1UEChMMQ29t +U2lnbiBMdGQuMQswCQYDVQQGEwJJTDAeFw0xMTA3MTgxMDI0NTRaFw0zNjA3MTYx +MDI0NTVaMEUxHzAdBgNVBAMTFkNvbVNpZ24gR2xvYmFsIFJvb3QgQ0ExFTATBgNV +BAoTDENvbVNpZ24gTHRkLjELMAkGA1UEBhMCSUwwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCyKClzKh3rm6n1nvigmV/VU1D4hSwYW2ro3VqpzpPo0Ph3 +3LguqjXd5juDwN4mpxTpD99d7Xu5X6KGTlMVtfN+bTbA4t3x7DU0Zqn0BE5XuOgs +3GLH41Vmr5wox1bShVpM+IsjcN4E/hMnDtt/Bkb5s33xCG+ohz5dlq0gA9qfr/g4 +O9lkHZXTCeYrmVzd/il4x79CqNvGkdL3um+OKYl8rg1dPtD8UsytMaDgBAopKR+W +igc16QJzCbvcinlETlrzP/Ny76BWPnAQgaYBULax/Q5thVU+N3sEOKp6uviTdD+X +O6i96gARU4H0xxPFI75PK/YdHrHjfjQevXl4J37FJfPMSHAbgPBhHC+qn/014DOx +46fEGXcdw2BFeIIIwbj2GH70VyJWmuk/xLMCHHpJ/nIF8w25BQtkPpkwESL6esaU +b1CyB4Vgjyf16/0nRiCAKAyC/DY/Yh+rDWtXK8c6QkXD2XamrVJo43DVNFqGZzbf +5bsUXqiVDOz71AxqqK+p4ek9374xPNMJ2rB5MLPAPycwI0bUuLHhLy6nAIFHLhut +TNI+6Y/soYpi5JSaEjcY7pxI8WIkUAzr2r+6UoT0vAdyOt7nt1y8844a7szo/aKf +woziHl2O1w6ZXUC30K+ptXVaOiW79pBDcbLZ9ZdbONhS7Ea3iH4HJNwktrBJLQID +AQABo4HrMIHoMA8GA1UdEwEB/wQFMAMBAf8wgYQGA1UdHwR9MHswPKA6oDiGNmh0 +dHA6Ly9mZWRpci5jb21zaWduLmNvLmlsL2NybC9jb21zaWduZ2xvYmFscm9vdGNh +LmNybDA7oDmgN4Y1aHR0cDovL2NybDEuY29tc2lnbi5jby5pbC9jcmwvY29tc2ln +bmdsb2JhbHJvb3RjYS5jcmwwDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBQCRZPY +DUhirGm6rgZbPvuqJpFQsTAfBgNVHSMEGDAWgBQCRZPYDUhirGm6rgZbPvuqJpFQ +sTANBgkqhkiG9w0BAQsFAAOCAgEAk1V5V9701xsfy4mfX+tP9Ln5e9h3N+QMwUfj +kr+k3e8iXOqADjTpUHeBkEee5tJq09ZLp/43F5tZ2eHdYq2ZEX7iWHCnOQet6Yw9 +SU1TahsrGDA6JJD9sdPFnNZooGsU1520e0zNB0dNWwxrWAmu4RsBxvEpWCJbvzQL +dOfyX85RWwli81OiVMBc5XvJ1mxsIIqli45oRynKtsWP7E+b0ISJ1n+XFLdQo/Nm +WA/5sDfT0F5YPzWdZymudMbXitimxC+n4oQE4mbQ4Zm718Iwg3pP9gMMcSc7Qc1J +kJHPH9O7gVubkKHuSYj9T3Ym6c6egL1pb4pz/uT7cT26Fiopc/jdqbe2EAfoJZkv +hlp/zdzOoXTWjiKNA5zmgWnZn943FuE9KMRyKtyi/ezJXCh8ypnqLIKxeFfZl69C +BwJsPXUTuqj8Fic0s3aZmmr7C4jXycP+Q8V+akMEIoHAxcd960b4wVWKqOcI/kZS +Q0cYqWOY1LNjznRt9lweWEfwDBL3FhrHOmD4++1N3FkkM4W+Q1b2WOL24clDMj+i +2n9Iw0lc1llHMSMvA5D0vpsXZpOgcCVahfXczQKi9wQ3oZyonJeWx4/rXdMtagAB +VBYGFuMEUEQtybI+eIbnp5peO2WAAblQI4eTy/jMVowe5tfMEXovV3sz9ULgmGb3 +DscLP1I= +-----END CERTIFICATE----- +# "ComSign Secured CA" +# 50 79 41 C7 44 60 A0 B4 70 86 22 0D 4E 99 32 57 +# 2A B5 D1 B5 BB CB 89 80 AB 1C B1 76 51 A8 44 D2 +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAw +PDEbMBkGA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWdu +MQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwx +GzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjEL +MAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGtWhf +HZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs49oh +gHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sW +v+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ue +Mv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr +9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt +6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7 +MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNl +Y3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58 +ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkq +hkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7p +iL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtC +dsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAmlaxMDPWL +kz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL +hfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz +OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== +-----END CERTIFICATE----- +# "D-TRUST Root CA 3 2013" +# A1 A8 6D 04 12 1E B8 7F 02 7C 66 F5 33 03 C2 8E +# 57 39 F9 43 FC 84 B3 8A D6 AF 00 90 35 DD 94 57 +-----BEGIN CERTIFICATE----- +MIIEDjCCAvagAwIBAgIDD92sMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxHzAdBgNVBAMMFkQtVFJVU1QgUm9vdCBD +QSAzIDIwMTMwHhcNMTMwOTIwMDgyNTUxWhcNMjgwOTIwMDgyNTUxWjBFMQswCQYD +VQQGEwJERTEVMBMGA1UECgwMRC1UcnVzdCBHbWJIMR8wHQYDVQQDDBZELVRSVVNU +IFJvb3QgQ0EgMyAyMDEzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +xHtCkoIf7O1UmI4SwMoJ35NuOpNcG+QQd55OaYhs9uFp8vabomGxvQcgdJhl8Ywm +CM2oNcqANtFjbehEeoLDbF7eu+g20sRoNoyfMr2EIuDcwu4QRjltr5M5rofmw7wJ +ySxrZ1vZm3Z1TAvgu8XXvD558l++0ZBX+a72Zl8xv9Ntj6e6SvMjZbu376Ml1wrq +WLbviPr6ebJSWNXwrIyhUXQplapRO5AyA58ccnSQ3j3tYdLl4/1kR+W5t0qp9x+u +loYErC/jpIF3t1oW/9gPP/a3eMykr/pbPBJbqFKJcu+I89VEgYaVI5973bzZNO98 +lDyqwEHC451QGsDkGSL8swIDAQABo4IBBTCCAQEwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUP5DIfccVb/Mkj6nDL0uiDyGyL+cwDgYDVR0PAQH/BAQDAgEGMIG+ +BgNVHR8EgbYwgbMwdKByoHCGbmxkYXA6Ly9kaXJlY3RvcnkuZC10cnVzdC5uZXQv +Q049RC1UUlVTVCUyMFJvb3QlMjBDQSUyMDMlMjAyMDEzLE89RC1UcnVzdCUyMEdt +YkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MDugOaA3hjVodHRwOi8v +Y3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2FfM18yMDEzLmNybDAN +BgkqhkiG9w0BAQsFAAOCAQEADlkOWOR0SCNEzzQhtZwUGq2aS7eziG1cqRdw8Cqf +jXv5e4X6xznoEAiwNStfzwLS05zICx7uBVSuN5MECX1sj8J0vPgclL4xAUAt8yQg +t4RVLFzI9XRKEBmLo8ftNdYJSNMOwLo5qLBGArDbxohZwr78e7Erz35ih1WWzAFv +m2chlTWL+BD8cRu3SzdppjvW7IvuwbDzJcmPkn2h6sPKRL8mpXSSnON065102ctN +h9j8tGlsi6BDB2B4l+nZk3zCRrybN1Kj7Yo8E6l7U0tJmhEFLAtuVqwfLoJs4Gln +tQ5tLdnkwBXxP/oYcuEVbSdbLTAoK59ImmQrme/ydUlfXA== +-----END CERTIFICATE----- +# "D-TRUST Root Class 3 CA 2 2009" +# 49 E7 A4 42 AC F0 EA 62 87 05 00 54 B5 25 64 B6 +# 50 E4 F4 9E 42 E3 48 D6 AA 38 E0 39 E9 57 B1 C1 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- +# "D-TRUST Root Class 3 CA 2 EV 2009" +# EE C5 49 6B 98 8C E9 86 25 B9 34 09 2E EC 29 08 +# BE D0 B0 F3 16 C2 D4 73 0C 84 EA F1 F3 D3 48 81 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- +# "Developer ID Certification Authority" +# 7A FC 9D 01 A6 2F 03 A2 DE 96 37 93 6D 4A FE 68 +# 09 0D 2D E1 8D 03 F2 9C 88 CF B0 B1 BA 63 58 7F +-----BEGIN CERTIFICATE----- +MIIEBDCCAuygAwIBAgIIGHqpqMKWIQwwDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1BcHBsZSBSb290IENBMB4XDTEy +MDIwMTIyMTIxNVoXDTI3MDIwMTIyMTIxNVoweTEtMCsGA1UEAwwkRGV2ZWxvcGVy +IElEIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSYwJAYDVQQLDB1BcHBsZSBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UE +BhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCJdk8GW5pB7qUj +KwKjX9dzP8A1sIuECj8GJH+nlT/rTw6Tr7QO0Mg+5W0Ysx/oiUe/1wkI5P9WmCkV +55SduTWjCs20wOHiYPTK7Cl4RWlpYGtfipL8niPmOsIiszFPHLrytjRZQu6wqQID +GJEEtrN4LjMfgEUNRW+7Dlpbfzrn2AjXCw4ybfuGNuRsq8QRinCEJqqfRNHxuMZ7 +lBebSPcLWBa6I8WfFTl+yl3DMl8P4FJ/QOq+rAhklVvJGpzlgMofakQcbD7EsCYf +Hex7r16gaj1HqVgSMT8gdihtHRywwk4RaSaLy9bQEYLJTg/xVnTQ2QhLZniiq6yn +4tJMh1nJAgMBAAGjgaYwgaMwHQYDVR0OBBYEFFcX7aLP3HyYoRDg/L6HLSzy4xdU +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/ +CF4wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDovL2NybC5hcHBsZS5jb20vcm9vdC5j +cmwwDgYDVR0PAQH/BAQDAgGGMBAGCiqGSIb3Y2QGAgYEAgUAMA0GCSqGSIb3DQEB +CwUAA4IBAQBCOXRrodzGpI83KoyzHQpEvJUsf7xZuKxh+weQkjK51L87wVA5akR0 +ouxbH3Dlqt1LbBwjcS1f0cWTvu6binBlgp0W4xoQF4ktqM39DHhYSQwofzPuAHob +tHastrW7T9+oG53IGZdKC1ZnL8I+trPEgzrwd210xC4jUe6apQNvYPSlSKcGwrta +4h8fRkV+5Jf1JxC3ICJyb3LaxlB1xT0lj12jAOmfNoxIOY+zO+qQgC6VmmD0eM70 +DgpTPqL6T9geroSVjTK8Vk2J6XgY4KyaQrp6RhuEoonOFOiI0ViL9q5WxCwFKkWv +C9lLqQIPNKyIx2FViUTJJ3MH7oLlTvVw +-----END CERTIFICATE----- +# "DigiCert Assured ID Root CA" +# 3E 90 99 B5 01 5E 8F 48 6C 00 BC EA 9D 11 1E E7 +# 21 FA BA 35 5A 89 BC F1 DF 69 56 1E 3D C6 32 5C +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- +# "DigiCert Assured ID Root G2" +# 7D 05 EB B6 82 33 9F 8C 94 51 EE 09 4E EB FE FA +# 79 53 A1 14 ED B2 F4 49 49 45 2F AB 7D 2F C1 85 +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA +n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc +biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp +EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA +bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu +YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI +QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I +0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni +lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 +B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv +ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- +# "DigiCert Assured ID Root G3" +# 7E 37 CB 8B 4C 47 09 0C AB 36 55 1B A6 F4 5D B8 +# 40 68 0F BA 16 6A 95 2D B1 00 71 7F 43 05 3F C2 +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg +RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf +Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q +RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD +AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY +JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv +6pZjamVFkpUBtA== +-----END CERTIFICATE----- +# "DigiCert Global Root CA" +# 43 48 A0 E9 44 4C 78 CB 26 5E 05 8D 5E 89 44 B4 +# D8 4F 96 62 BD 26 DB 25 7F 89 34 A4 43 C7 01 61 +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- +# "DigiCert Global Root G2" +# CB 3C CB B7 60 31 E5 E0 13 8F 8D D3 9A 23 F9 DE +# 47 FF C3 5E 43 C1 14 4C EA 27 D4 6A 5A B1 CB 5F +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- +# "DigiCert Global Root G3" +# 31 AD 66 48 F8 10 41 38 C7 38 F3 9E A4 32 01 33 +# 39 3E 3A 18 CC 02 29 6E F9 7C 2A C9 EF 67 31 D0 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE----- +# "DigiCert High Assurance EV Root CA" +# 74 31 E5 F4 C3 C1 CE 46 90 77 4F 0B 61 E0 54 40 +# 88 3B A9 A0 1E D0 0B A6 AB D7 80 6E D3 B1 18 CF +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- +# "DigiCert Trusted Root G4" +# 55 2F 7B DC F1 A7 AF 9E 6C E6 72 01 7F 4F 12 AB +# F7 72 40 C7 8E 76 1A C2 03 D1 D9 D2 0A C8 99 88 +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE----- +# "DST Root CA X3" +# 06 87 26 03 31 A7 24 03 D9 09 F1 05 E6 9B CF 0D +# 32 E1 BD 24 93 FF C6 D9 20 6D 11 BC D6 77 07 39 +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- +# "E-Tugra Certification Authority" +# B0 BF D5 2B B0 D7 D9 BD 92 BF 5D 4D C1 3D A2 55 +# C0 2C 54 2F 37 83 65 EA 89 39 11 F5 5E 55 F2 3C +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC +aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV +BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 +Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz +MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ +BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp +em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY +B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH +D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF +Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo +q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D +k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH +fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut +dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM +ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 +zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX +U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 +Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 +XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF +Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR +HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY +GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c +77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 ++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK +vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 +FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl +yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P +AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD +y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d +NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- +# "Echoworx Root CA2" +# 66 39 D1 3C AB 85 DF 1A D9 A2 3C 44 3B 3A 60 90 +# 1E 2B 13 8D 45 6F A7 11 83 57 81 08 88 4E C6 BF +-----BEGIN CERTIFICATE----- +MIIE5zCCA8+gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCQ0Ex +EDAOBgNVBAgTB09udGFyaW8xEDAOBgNVBAcTB1Rvcm9udG8xHTAbBgNVBAoTFEVj +aG93b3J4IENvcnBvcmF0aW9uMR8wHQYDVQQLExZDZXJ0aWZpY2F0aW9uIFNlcnZp +Y2VzMRowGAYDVQQDExFFY2hvd29yeCBSb290IENBMjAeFw0wNTEwMDYxMDQ5MTNa +Fw0zMDEwMDcxMDQ5MTNaMIGNMQswCQYDVQQGEwJDQTEQMA4GA1UECBMHT250YXJp +bzEQMA4GA1UEBxMHVG9yb250bzEdMBsGA1UEChMURWNob3dvcnggQ29ycG9yYXRp +b24xHzAdBgNVBAsTFkNlcnRpZmljYXRpb24gU2VydmljZXMxGjAYBgNVBAMTEUVj +aG93b3J4IFJvb3QgQ0EyMIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA +utU/5BkV15UBf+s+JQruKQxr77s3rjp/RpOtmhHILIiO5gsEWP8MMrfrVEiidjI6 +Qh6ans0KAWc2Dw0/j4qKAQzOSyAZgjcdypNTBZ7muv212DA2Pu41rXqwMrlBrVi/ +KTghfdLlNRu6JrC5y8HarrnRFSKF1Thbzz921kLDRoCi+FVs5eVuK5LvIfkhNAqA +byrTgO3T9zfZgk8upmEkANPDL1+8y7dGPB/d6lk0I5mv8PESKX02TlvwgRSIiTHR +k8++iOPLBWlGp7ZfqTEXkPUZhgrQQvxcrwCUo6mk8TqgxCDP5FgPoHFiPLef5szP +ZLBJDWp7GLyE1PmkQI6WiwIBA6OCAVAwggFMMA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBQ74YEboKs/OyGC1eISrq5QqxSlEzCBugYDVR0j +BIGyMIGvgBQ74YEboKs/OyGC1eISrq5QqxSlE6GBk6SBkDCBjTELMAkGA1UEBhMC +Q0ExEDAOBgNVBAgTB09udGFyaW8xEDAOBgNVBAcTB1Rvcm9udG8xHTAbBgNVBAoT +FEVjaG93b3J4IENvcnBvcmF0aW9uMR8wHQYDVQQLExZDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzMRowGAYDVQQDExFFY2hvd29yeCBSb290IENBMoIBADBQBgNVHSAESTBH +MEUGCysGAQQB+REKAQMBMDYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuZWNob3dv +cnguY29tL2NhL3Jvb3QyL2Nwcy5wZGYwDQYJKoZIhvcNAQEFBQADggEBAG+nrPi/ +0RpfEzrj02C6JGPUar4nbjIhcY6N7DWNeqBoUulBSIH/PYGNHYx7/lnJefiixPGE +7TQ5xPgElxb9bK8zoAApO7U33OubqZ7M7DlHnFeCoOoIAZnG1kuwKwD5CXKB2a74 +HzcqNnFW0IsBFCYqrVh/rQgJOzDA8POGbH0DeD0xjwBBooAolkKT+7ZItJF1Pb56 +QpDL9G+16F7GkmnKlAIYT3QTS3yFGYChnJcd+6txUPhKi9sSOOmAIaKHnkH9Scz+ +A2cSi4A3wUYXVatuVNHpRb2lygfH3SuCX9MU8Ure3zBlSU1LALtMqI4JmcQmQpIq +zIzvO2jHyu9PQqo= +-----END CERTIFICATE----- +# "EE Certification Centre Root CA" +# 3E 84 BA 43 42 90 85 16 E7 75 73 C0 99 2F 09 79 +# CA 08 4E 46 85 68 1F F1 95 CC BA 8A 22 9B 8A 76 +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 +MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 +czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG +CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy +MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl +ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS +b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy +euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO +bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw +WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d +MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE +1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ +zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF +BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV +v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG +E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW +iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v +GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= +-----END CERTIFICATE----- +# "Entrust Root Certification Authority" +# 73 C1 76 43 4F 1B C6 D5 AD F4 5B 0E 76 E7 27 28 +# 7C 8D E5 76 16 C1 E6 E6 14 1A 2B 2C BC 7D 8E 4C +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- +# "Entrust Root Certification Authority - EC1" +# 02 ED 0E B2 8C 14 DA 45 16 5C 56 67 91 70 0D 64 +# 51 D7 FB 56 F0 B2 AB 1D 3B 8E B0 70 E5 6E DF F5 +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG +A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 +d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu +dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq +RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy +MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g +Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt +ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH +Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC +R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX +hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- +# "Entrust Root Certification Authority - G2" +# 43 DF 57 74 B0 3E 7F EF 5F E4 0D 93 1A 7B ED F1 +# BB 2E 6B 42 73 8C 4E 6D 38 41 10 3D 3A A7 F3 39 +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 +cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs +IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz +dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy +NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu +dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt +dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 +aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T +RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN +cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW +wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 +U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 +jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN +BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ +jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v +1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R +nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH +VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== +-----END CERTIFICATE----- +# "Entrust.net Certification Authority (2048)" +# 6D C4 71 72 E0 1C BC B0 BF 62 58 0D 89 5F E2 B8 +# AC 9A D4 F8 73 80 1E 0C 10 B9 C8 37 D2 1E B1 77 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- +# "ePKI Root Certification Authority" +# C0 A6 F4 DC 63 A2 4B FD CF 54 EF 2A 6A 08 2A 0A +# 72 DE 35 80 3E 2F F5 FF 52 7A E5 D8 72 06 DF D5 +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- +# "GDCA TrustAUTH R5 ROOT" +# BF FF 8F D0 44 33 48 7D 6A 8A A6 0C 1A 29 76 7A +# 9F C2 BB B0 5E 42 0F 71 3A 13 B9 92 89 1D 38 93 +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 +MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w +HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj +Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj +TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u +KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj +qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm +MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 +ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP +zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk +L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC +jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA +HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC +AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm +DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 +COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry +L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf +JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg +IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io +2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV +09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ +XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq +T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe +MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- +# "GeoTrust Global CA" +# FF 85 6A 2D 25 1D CD 88 D3 66 56 F4 50 12 67 98 +# CF AB AA DE 40 79 9C 72 2D E4 D2 B5 DB 36 A7 3A +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- +# "GeoTrust Primary Certification Authority" +# 37 D5 10 06 C5 12 EA AB 62 64 21 F1 EC 8C 92 01 +# 3F C5 F8 2A E9 8E E5 33 EB 46 19 B8 DE B4 D0 6C +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- +# "GeoTrust Primary Certification Authority - G2" +# 5E DB 7A C4 3B 82 A0 6A 87 61 E8 D7 BE 49 79 EB +# F2 61 1F 7D D7 9B F9 1C 1C 6B 56 6A 21 9E D7 66 +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj +KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 +MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw +NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV +BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL +So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal +tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG +CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT +qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz +rD6ogRLQy7rQkgu2npaqBA+K +-----END CERTIFICATE----- +# "GeoTrust Primary Certification Authority - G3" +# B4 78 B8 12 25 0D F8 78 63 5C 2A A7 EC 7D 15 5E +# AA 62 5E E8 29 16 E2 CD 29 43 61 88 6C D1 FB D4 +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB +mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT +MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 +BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz ++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm +hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn +5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W +JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL +DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC +huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB +AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB +zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN +kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH +SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G +spki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- +# "Global Chambersign Root" +# EF 3C B4 17 FC 8E BF 6F 97 87 6C 9E 4E CE 39 DE +# 1E A5 FE 64 91 41 D1 02 8B 7D 11 C0 B2 29 8C ED +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo +YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 +MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy +NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G +A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA +A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 +Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s +QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV +eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 +B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh +z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T +AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i +ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w +TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH +MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD +VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE +VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B +AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM +bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi +ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG +VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c +ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ +AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- +# "Global Chambersign Root - 2008" +# 13 63 35 43 93 34 A7 69 80 16 A0 D3 24 DE 72 28 +# 4E 07 9D 7B 52 20 BB 8F BD 74 78 16 EE BE BA CA +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx +MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy +cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG +A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl +BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed +KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 +G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 +zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 +ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG +HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 +Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V +yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e +beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r +6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog +zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW +BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr +ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp +ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk +cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt +YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC +CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow +KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI +hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ +UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz +X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x +fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz +a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd +Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd +SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O +AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso +M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge +v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- +# "GlobalSign" +# CA 42 DD 41 74 5F D0 B8 1E B9 02 36 2C F9 D8 BF +# 71 9D A1 BD 1B 1E FC 94 6F 5B 4C 99 F4 2C 1B 9E +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- +# "GlobalSign" +# CB B5 22 D7 B7 F1 27 AD 6A 01 13 86 5B DF 1C D4 +# 10 2E 7D 07 59 AF 63 5A 7C F4 72 0D C9 63 C5 3B +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- +# "GlobalSign" +# 17 9F BC 14 8A 3D D0 0F D2 4E A1 34 58 CC 43 BF +# A7 F5 9C 81 82 D7 83 A5 13 F6 EB EC 10 0C 89 24 +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc +8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke +hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI +KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg +515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO +xwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- +# "GlobalSign" +# BE C9 49 11 C2 95 56 76 DB 6C 0A 55 09 86 D7 6E +# 3B A0 05 66 7C 44 2C 97 62 B4 FB B7 73 DE 22 8C +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ +FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F +uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX +kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs +ewv4n4Q= +-----END CERTIFICATE----- +# "GlobalSign" +# 2C AB EA FE 37 D0 6C A2 2A BA 73 91 C0 03 3D 25 +# 98 29 52 C4 53 64 73 49 76 3A 3A B5 AD 6C CF 69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- +# "GlobalSign Root CA" +# EB D4 10 40 E4 BB 3E C7 42 C9 E3 81 D3 1E F2 A4 +# 1A 48 B6 68 5C 96 E7 CE F3 C1 DF 6C D4 33 1C 99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- +# "Go Daddy Class 2 Certification Authority" +# C3 84 6B F2 4B 9E 93 CA 64 27 4C 0E C6 7C 1E CC +# 5E 02 4F FC AC D2 D7 40 19 35 0E 81 FE 54 6A E4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- +# "Go Daddy Root Certificate Authority - G2" +# 45 14 0B 32 47 EB 9C C8 C5 B4 F0 D7 B5 30 91 F7 +# 32 92 08 9E 6E 5A 63 E2 74 9D D3 AC A9 19 8E DA +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- +# "Government Root Certification Authority" +# 70 B9 22 BF DA 0E 3F 4A 34 2E 4E E2 2D 57 9A E5 +# 98 D0 71 CC 5E C9 C3 0F 12 36 80 34 03 88 AE A5 +-----BEGIN CERTIFICATE----- +MIIFSzCCAzOgAwIBAgIRALZLiAfiI+7IXBKtpg4GofIwDQYJKoZIhvcNAQELBQAw +PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xMjA5MjgwODU4NTFaFw0zNzEyMzExNTU5NTla +MD8xCzAJBgNVBAYTAlRXMTAwLgYDVQQKDCdHb3Zlcm5tZW50IFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQC2/5c8gb4BWCQnr44BK9ZykjAyG1+bfNTUf+ihYHMwVxAA+lCWJP5Q5ow6ldFX +eYTVZ1MMKoI+GFy4MCYa1l7GLbIEUQ7v3wxjR+vEEghRK5lxXtVpe+FdyXcdIOxW +juVhYC386RyA3/pqg7sFtR4jEpyCygrzFB0g5AaPQySZn7YKk1pzGxY5vgW28Yyl +ZJKPBeRcdvc5w88tvQ7Yy6gOMZvJRg9nU0MEj8iyyIOAX7ryD6uBNaIgIZfOD4k0 +eA/PH07p+4woPN405+2f0mb1xcoxeNLOUNFggmOd4Ez3B66DNJ1JSUPUfr0t4urH +cWWACOQ2nnlwCjyHKenkkpTqBpIpJ3jmrdc96QoLXvTg1oadLXLLi2RW5vSueKWg +OTNYPNyoj420ai39iHPplVBzBN8RiD5C1gJ0+yzEb7xs1uCAb9GGpTJXA9ZN9E4K +mSJ2fkpAgvjJ5E7LUy3Hsbbi08J1J265DnGyNPy/HE7CPfg26QrMWJqhGIZO4uGq +s3NZbl6dtMIIr69c/aQCb/+4DbvVq9dunxpPkUDwH0ZVbaCSw4nNt7H/HLPLo5wK +4/7NqrwB7N1UypHdTxOHpPaY7/1J1lcqPKZc9mA3v9g+fk5oKiMyOr5u5CI9ByTP +isubXVGzMNJxbc5Gim18SjNE2hIvNkvy6fFRCW3bapcOFwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBTVZx3gnHosnMvFmOcdByYqhux0zTAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAJA75cJTQijq9TFOjj2Rnk0J +89ixUuZPrAwxIbvx6pnMg/y2KOTshAcOD06Xu29oRo8OURWV+Do7H1+CDgxxDryR +T64zLiNB9CZrTxOH+nj2LsIPkQWXqmrBap+8hJ4IKifd2ocXhuGzyl3tOKkpboTe +Rmv8JxlQpRJ6jH1i/NrnzLyfSa8GuCcn8on3Fj0Y5r3e9YwSkZ/jBI3+BxQaWqw5 +ghvxOBnhY+OvbLamURfr+kvriyL2l/4QOl+UoEtTcT9a4RD4co+WgN2NApgAYT2N +vC2xR8zaXeEgp4wxXPHj2rkKhkfIoT0Hozymc26Uke1uJDr5yTDRB6iBfSZ9fYTf +hsmL5a4NHr6JSFEVg5iWL0rrczTXdM3Jb9DCuiv2mv6Z3WAUjhv5nDk8f0OJU+jl +wqu+Iq0nOJt3KLejY2OngeepaUXrjnhWzAWEx/uttjB8YwWfLYwkf0uLkvw4Hp+g +pVezbp3YZLhwmmBScMip0P/GnO0QYV7Ngw5u6E0CQUridgR51lQ/ipgyFKDdLZzn +uoJxo4ZVKZnSKdt1OvfbQ/+2W/u3fjWAjg1srnm3Ni2XUqGwB5wH5Ss2zQOXlL0t +DjQG/MAWifw3VOTWzz0TBPKR2ck2Lj7FWtClTILD/y58Jnb38/1FoqVuVa4uzM8s +iTTa9g3nkagQ6hed8vbs +-----END CERTIFICATE----- +# "GTS Root R1" +# 2A 57 54 71 E3 13 40 BC 21 58 1C BD 2C F1 3E 15 +# 84 63 20 3E CE 94 BC F9 D3 CC 19 6B F0 9A 54 72 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX +mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7 +zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P +fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc +vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4 +Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp +zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO +Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW +k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+ +DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF +lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW +Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z +XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR +gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3 +d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv +J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg +DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM ++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy +F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9 +SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws +E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl +-----END CERTIFICATE----- +# "GTS Root R2" +# C4 5D 7B B0 8E 6D 67 E6 2E 42 35 11 0B 56 4E 5F +# 78 FD 92 EF 05 8C 84 0A EA 4E 64 55 D7 58 5C 60 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg +GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu +XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd +re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu +PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1 +mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K +8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj +x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR +nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0 +kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok +twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp +8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT +z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA +pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb +pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB +R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R +RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk +0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC +5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF +izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn +yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC +-----END CERTIFICATE----- +# "GTS Root R3" +# 15 D5 B8 77 46 19 EA 7D 54 CE 1C A6 D0 B0 C4 03 +# E0 37 A9 17 F1 31 E8 A0 4E 1E 6B 7A 71 BA BC E5 +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A +DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk +fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA +njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE----- +# "GTS Root R4" +# 71 CC A5 39 1F 9E 79 4B 04 80 25 30 B3 63 E1 21 +# DA 8A 30 43 BB 26 66 2F EA 4D CA 7F C9 51 A4 BD +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l +xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0 +CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx +sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w== +-----END CERTIFICATE----- +# "Hellenic Academic and Research Institutions ECC RootCA 2015" +# 44 B5 45 AA 8A 25 E6 5A 73 CA 15 DC 27 FC 36 D2 +# 4C 1C B9 95 3A 06 65 39 B1 15 82 DC 48 7B 48 33 +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN +BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl +bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv +b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ +BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj +YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 +MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 +dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg +QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa +jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi +C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep +lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof +TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- +# "Hellenic Academic and Research Institutions RootCA 2011" +# BC 10 4F 15 A4 8B E7 09 DC A5 42 A7 E1 D4 B9 DF +# 6F 05 45 27 E8 02 EA A9 2D 59 54 44 25 8A FE 71 +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix +RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p +YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw +NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK +EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl +cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz +dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ +fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns +bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD +75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP +FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV +HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp +5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu +b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA +A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p +6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 +dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys +Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI +l7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- +# "Hellenic Academic and Research Institutions RootCA 2015" +# A0 40 92 9A 02 CE 53 B4 AC F4 F2 FF C6 98 1C E4 +# 49 6F 75 5E 6D 45 FE 0B 2A 69 2B CD 52 52 3F 36 +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix +DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k +IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT +N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v +dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG +A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh +ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx +QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA +4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 +AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 +4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C +ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV +9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD +gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 +Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq +NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko +LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd +ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I +XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI +M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot +9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V +Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea +j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh +X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ +l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf +bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 +pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK +e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 +vm9qp/UsQu0yrbYhnr68 +-----END CERTIFICATE----- +# "Hongkong Post Root CA 1" +# F9 E6 7D 33 6C 51 00 2A C0 54 C6 32 02 2D 66 DD +# A2 E7 E3 FF F1 0A D0 61 ED 31 D8 BB B4 10 CF B2 +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- +# "IdenTrust Commercial Root CA 1" +# 5D 56 49 9B E4 D2 E0 8B CF CA D0 8A 3E 38 72 3D +# 50 50 3B DE 70 69 48 E4 2F 55 60 30 19 E5 28 AE +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- +# "IdenTrust Public Sector Root CA 1" +# 30 D0 89 5A 9A 44 8A 26 20 91 63 55 22 D1 F5 20 +# 10 B5 86 7A CA E1 2C 78 EF 95 8F D4 F4 38 9F 2F +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu +VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN +MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 +MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 +ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy +RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS +bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF +/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R +3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw +EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy +9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V +GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ +2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV +WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD +W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN +AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV +DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 +TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G +lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW +mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df +WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 ++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ +tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA +GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv +8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- +# "ISRG Root X1" +# 96 BC EC 06 26 49 76 F3 74 60 77 9A CF 28 C5 A7 +# CF E8 A3 C0 AA E1 1A 8F FC EE 05 C0 BD DF 08 C6 +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- +# "Izenpe.com" +# 23 80 42 03 CA 45 D8 CD E7 16 B8 C1 3B F3 B4 48 +# 45 7F A0 6C C1 02 50 99 7F A0 14 58 31 7C 41 E5 +-----BEGIN CERTIFICATE----- +MIIF8DCCA9igAwIBAgIPBuhGJy8fCo/RhFzjafbVMA0GCSqGSIb3DQEBBQUAMDgx +CzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXpl +bnBlLmNvbTAeFw0wNzEyMTMxMzA4MjdaFw0zNzEyMTMwODI3MjVaMDgxCzAJBgNV +BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNv +bTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMnTesoPHqynhugWZWqx +whtFMnGV2f4QW8yv56V5AY+Jw8ryVXH3d753lPNypCxE2J6SmxQ6oeckkAoKVo7F +2CaU4dlI4S0+2gpy3aOZFdqBoof0e24md4lYrdbrDLJBenNubdt6eEHpCIgSfocu +ZhFjbFT7PJ1ywLwu/8K33Q124zrX97RovqL144FuwUZvXY3gTcZUVYkaMzEKsVe5 +o4qYw+w7NMWVQWl+dcI8IMVhulFHoCCQk6GQS/NOfIVFVJrRBSZBsLVNHTO+xAPI +JXzBcNs79AktVCdIrC/hxKw+yMuSTFM5NyPs0wH54AlETU1kwOENWocivK0bo/4m +tRXzp/yEGensoYi0RGmEg/OJ0XQGqcwL1sLeJ4VQJsoXuMl6h1YsGgEebL4TrRCs +tST1OJGh1kva8bvS3ke18byB9llrzxlT6Y0Vy0rLqW9E5RtBz+GGp8rQap+8TI0G +M1qiheWQNaBiXBZO8OOi+gMatCxxs1gs3nsL2xoP694hHwZ3BgOwye+Z/MC5TwuG +KP7Suerj2qXDR2kS4Nvw9hmL7Xtw1wLW7YcYKCwEJEx35EiKGsY7mtQPyvp10gFA +Wo15v4vPS8+qFsGV5K1Mij4XkdSxYuWC5YAEpAN+jb/af6IPl08M0w3719Hlcn4c +yHf/W5oPt64FRuXxqBbsR6QXAgMBAAGjgfYwgfMwgbAGA1UdEQSBqDCBpYEPaW5m +b0BpemVucGUuY29tpIGRMIGOMUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBB +MDEzMzcyNjAtUk1lcmMuVml0b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEG +A1UECQw6QXZkYSBkZWwgTWVkaXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEw +IFZpdG9yaWEtR2FzdGVpejAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUHRxlDqjyJXu0kc/ksbHmvVV0bAUwDQYJKoZIhvcNAQEFBQAD +ggIBAMeBRm8hGE+gBe/n1bqXUKJg7aWSFBpSm/nxiEqg3Hh10dUflU7F57dp5iL0 ++CmoKom+z892j+Mxc50m0xwbRxYpB2iEitL7sRskPtKYGCwkjq/2e+pEFhsqxPqg +l+nqbFik73WrAGLRne0TNtsiC7bw0fRue0aHwp28vb5CO7dz0JoqPLRbEhYArxk5 +ja2DUBzIgU+9Ag89njWW7u/kwgN8KRwCfr00J16vU9adF79XbOnQgxCvv11N75B7 +XSus7Op9ACYXzAJcY9cZGKfsK8eKPlgOiofmg59OsjQerFQJTx0CCzl+gQgVuaBp +E8gyK+OtbBPWg50jLbJtooiGfqgNASYJQNntKE6MkyQP2/EeTXp6WuKlWPHcj1+Z +ggwuz7LdmMySlD/5CbOlliVbN/UShUHiGUzGigjB3Bh6Dx4/glmimj4/+eAJn/3B +kUtdyXvWton83x18hqrNA/ILUpLxYm9/h+qrdslsUMIZgq+qHfUgKGgu1fxkN0/P +pUTEvnK0jHS0bKf68r10OEMr3q/53NjgnZ/cPcqlY0S/kqJPTIAcuxrDmkoEVU3K +7iYLHL8CxWTTnn7S05EcS6L1HOUXHA0MUqORH5zwIe0ClG+poEnK6EOMxPQ02nwi +o8ZmPrgbBYhdurz3vOXcFD2nhqi2WVIhA16L4wTtSyoeo09Q +-----END CERTIFICATE----- +# "Izenpe.com" +# 25 30 CC 8E 98 32 15 02 BA D9 6F 9B 1F BA 1B 09 +# 9E 2D 29 9E 0F 45 48 BB 91 4F 36 3B C0 D4 53 1F +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD +VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j +b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq +scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO +xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H +LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX +uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD +yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ +JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q +rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN +BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L +hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB +QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ +HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu +Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg +QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB +BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA +A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb +laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 +awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo +JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw +LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT +VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk +LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb +UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ +QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ +naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls +QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- +# "KISA RootCA 1" +# 6F DB 3F 76 C8 B8 01 A7 53 38 D8 A5 0A 7C 02 87 +# 9F 61 98 B5 7E 59 4D 31 8D 38 32 90 0F ED CD 79 +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgIBBDANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJLUjEN +MAsGA1UECgwES0lTQTEuMCwGA1UECwwlS29yZWEgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkgQ2VudHJhbDEWMBQGA1UEAwwNS0lTQSBSb290Q0EgMTAeFw0wNTA4MjQw +ODA1NDZaFw0yNTA4MjQwODA1NDZaMGQxCzAJBgNVBAYTAktSMQ0wCwYDVQQKDARL +SVNBMS4wLAYDVQQLDCVLb3JlYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDZW50 +cmFsMRYwFAYDVQQDDA1LSVNBIFJvb3RDQSAxMIIBIDANBgkqhkiG9w0BAQEFAAOC +AQ0AMIIBCAKCAQEAvATk+hM58DSWIGtsaLv623f/J/es7C/n/fB/bW+MKs0lCVsk +9KFo/CjsySXirO3eyDOE9bClCTqnsUdIxcxPjHmc+QZXfd3uOPbPFLKc6tPAXXdi +8EcNuRpAU1xkcK8IWsD3z3X5bI1kKB4g/rcbGdNaZoNy4rCbvdMlFQ0yb2Q3lIVG +yHK+d9VuHygvx2nt54OJM1jT3qC/QOhDUO7cTWu8peqmyGGO9cNkrwYV3CmLP3WM +vHFE2/yttRcdbYmDz8Yzvb9Fov4Kn6MRXw+5H5wawkbMnChmn3AmPC7fqoD+jMUE +CSVPzZNHPDfqAmeS/vwiJFys0izgXAEzisEZ2wIBA6MyMDAwHQYDVR0OBBYEFL+2 +J9gDWnZlTGEBQVYx5Yt7OtnMMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF +BQADggEBABOvUQveimpb5poKyLGQSk6hAp3MiNKrZr097LuxQpVqslxa/6FjZJap +aBV/JV6K+KRzwYCKhQoOUugy50X4TmWAkZl0Q+VFnUkq8JSV3enhMNITbslOsXfl +BM+tWh6UCVrXPAgcrnrpFDLBRa3SJkhyrKhB2vAhhzle3/xk/2F0KpzZm4tfwjeT +2KM3LzuTa7IbB6d/CVDv0zq+IWuKkDsnSlFOa56ch534eJAx7REnxqhZvvwYC/uO +fi5C4e3nCSG9uRPFVmf0JqZCQ5BEVLRxm3bkGhKsGigA35vB1fjbXKP4krG9tNT5 +UNkAAk/bg9ART6RCVmE6fhMy04Qfybo= +-----END CERTIFICATE----- +# "Microsec e-Szigno Root CA 2009" +# 3C 5F 81 FE A5 FA B8 2C 64 BF A2 EA EC AF CD E8 +# E0 77 FC 86 20 A7 CA E5 37 16 3D F3 6E DB F3 78 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- +# "NetLock Arany (Class Gold) Főtanúsítvány" +# 6C 61 DA C3 A2 DE F0 31 50 6B E0 36 D2 A6 FE 40 +# 19 94 FB D1 3D F9 C8 D4 66 59 92 74 C4 46 EC 98 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- +# "Network Solutions Certificate Authority" +# 15 F0 BA 00 A3 AC 7A F3 AC 88 4C 07 2B 10 11 A0 +# 77 BD 77 C0 97 F4 01 64 B2 F8 59 8A BD 83 86 0C +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- +# "OISTE WISeKey Global Root GA CA" +# 41 C9 23 86 6A B4 CA D6 B7 AD 57 80 81 58 2E 02 +# 07 97 A6 CB DF 4F FF 78 CE 83 96 B3 89 37 D7 F5 +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +/L7fCg0= +-----END CERTIFICATE----- +# "OISTE WISeKey Global Root GB CA" +# 6B 9C 08 E8 6E B0 F7 67 CF AD 65 CD 98 B6 21 49 +# E5 49 4A 67 F5 84 5E 7B D1 ED 01 9F 27 B8 6B D6 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg +Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i +YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x +CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG +b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 +HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx +WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX +1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk +u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P +99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r +M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB +BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh +cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 +gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO +ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf +aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- +# "OISTE WISeKey Global Root GC CA" +# 85 60 F9 1C 36 24 DA BA 95 70 B5 FE A0 DB E3 6F +# F1 1A 83 23 BE 94 86 85 4F B3 F3 4A 55 71 19 8D +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- +# "OpenTrust Root CA G1" +# 56 C7 71 28 D9 8C 18 D9 1B 4C FD FF BC 25 EE 91 +# 03 D4 75 8E A2 AB AD 82 6A 90 F3 45 7D 46 0E B4 +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA +MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w +ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw +MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU +T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b +wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX +/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 +77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP +uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx +p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx +Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 +TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W +G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw +vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY +EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 +2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw +DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E +PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf +gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS +FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 +V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P +XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I +i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t +TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 +09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky +Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ +AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj +1oxx +-----END CERTIFICATE----- +# "OpenTrust Root CA G2" +# 27 99 58 29 FE 6A 75 15 C1 BF E8 48 F9 C4 76 1D +# B1 6C 22 59 29 25 7B F4 0D 08 94 F2 9E A8 BA F2 +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA +MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w +ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw +MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU +T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh +/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e +CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 +1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE +FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS +gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X +G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy +YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH +vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 +t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ +gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 +5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w +DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz +Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 +nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT +RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT +wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 +t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa +TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 +o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU +3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA +iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f +WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM +S1IK +-----END CERTIFICATE----- +# "OpenTrust Root CA G3" +# B7 C3 62 31 70 6E 81 07 8C 36 7C B8 96 19 8F 1E +# 32 08 DD 92 69 49 DD 8F 57 09 A4 10 F7 5B 62 92 +-----BEGIN CERTIFICATE----- +MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx +CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U +cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow +QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl +blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm +3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d +oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 +DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK +BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q +j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx +4nxp5V2a+EEfOzmTk51V6s2N8fvB +-----END CERTIFICATE----- +# "QuoVadis Root CA 1 G3" +# 8A 86 6F D1 B2 76 B5 7E 57 8E 92 1C 65 82 8A 2B +# ED 58 E9 F2 F2 88 05 41 34 B7 F1 F4 BF C9 CC 74 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 +MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV +wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe +rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 +68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh +4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp +UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o +abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc +3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G +KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt +hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO +Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt +zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD +ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 +cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN +qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 +YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv +b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 +8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k +NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj +ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp +q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt +nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD +-----END CERTIFICATE----- +# "QuoVadis Root CA 2" +# 85 A0 DD 7D D7 20 AD B7 FF 05 F8 3D 54 2B 20 9D +# C7 FF 45 28 F7 D6 77 B1 83 89 FE A5 E5 C4 9E 86 +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- +# "QuoVadis Root CA 2 G3" +# 8F E4 FB 0A F9 3A 4D 0D 67 DB 0B EB B2 3E 37 C7 +# 1B F3 25 DC BC DD 24 0E A0 4D AF 58 B4 7E 18 40 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- +# "QuoVadis Root CA 3" +# 18 F1 FC 7F 20 5D F8 AD DD EB 7F E0 07 DD 57 E3 +# AF 37 5A 9C 4D 8D 73 54 6B F4 F1 FE D1 E1 8D 35 +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- +# "QuoVadis Root CA 3 G3" +# 88 EF 81 DE 20 2E B0 18 45 2E 43 F8 64 72 5C EA +# 5F BD 1F C2 D9 D2 05 73 07 09 C5 D8 B8 69 0F 46 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 +MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR +/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu +FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR +U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c +ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR +FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k +A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw +eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl +sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp +VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q +A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ +ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD +ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI +FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv +oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg +u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP +0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf +3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl +8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ +DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN +PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ +ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- +# "QuoVadis Root Certification Authority" +# A4 5E DE 3B BB F0 9C 8A E1 5C 72 EF C0 72 68 D6 +# 93 A2 1C 99 6F D5 1E 67 CA 07 94 60 FD 6D 88 73 +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----END CERTIFICATE----- +# "Secure Global CA" +# 42 00 F5 04 3A C8 59 0E BB 52 7D 20 9E D1 50 30 +# 29 FB CB D4 1C A1 B5 06 EC 27 F1 5A DE 7D AC 69 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- +# "SecureTrust CA" +# F1 C1 B5 0A E5 A2 0D D8 03 0E C9 F6 BC 24 82 3D +# D3 67 B5 25 57 59 B4 E7 1B 61 FC E9 F7 37 5D 73 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- +# "Security Communication EV RootCA1" +# A2 2D BA 68 1E 97 37 6E 2D 39 7D 72 8A AE 3A 9B +# 62 96 B9 FD BA 60 BC 2E 11 F6 47 F2 C6 75 FB 37 +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz +MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N +IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 +bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE +RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO +zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 +bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF +MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 +VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC +OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW +tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ +q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb +EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ +Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O +VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 +-----END CERTIFICATE----- +# "Security Communication RootCA1" +# E7 5E 72 ED 9F 56 0E EC 6E B4 80 00 73 A4 3F C3 +# AD 19 19 5A 39 22 82 01 78 95 97 4A 99 02 6B 6C +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- +# "Security Communication RootCA2" +# 51 3B 2C EC B8 10 D4 CD E5 DD 85 39 1A DF C6 C2 +# DD 60 D8 7B B7 36 D2 B5 21 48 4A A4 7A 0E BE F6 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- +# "Sonera Class2 CA" +# 79 08 B4 03 14 C1 38 10 0B 51 8D 07 35 80 7F FB +# FC F8 51 8A 00 95 33 71 05 BA 38 6B 15 3D D9 27 +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----END CERTIFICATE----- +# "SSL.com EV Root Certification Authority ECC" +# 22 A2 C1 F7 BD ED 70 4C C1 E7 01 B5 F4 08 C3 10 +# 88 0F E9 56 B5 DE 2A 4A 44 F9 9C 87 3A 25 A7 C8 +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx +NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv +bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA +VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku +WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX +5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ +ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg +h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- +# "SSL.com EV Root Certification Authority RSA R2" +# 2E 7B F1 6C C2 24 85 A7 BB E2 AA 86 96 75 07 61 +# B0 AE 39 BE 3B 2F E9 D0 CC 6D 4E F7 34 91 42 5C +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE +CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy +MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G +A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD +DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq +M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf +OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa +4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 +HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR +aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA +b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ +Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV +PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO +pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu +UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY +MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 +9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW +s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 +Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg +cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM +79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz +/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt +ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm +Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK +QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ +w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi +S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 +mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- +# "SSL.com Root Certification Authority ECC" +# 34 17 BB 06 CC 60 07 DA 1B 96 1C 92 0B 8A B4 CE +# 3F AD 82 0E 4A A3 0B 9A CB C4 A7 4E BD CE BC 65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- +# "SSL.com Root Certification Authority RSA" +# 85 66 6A 56 2E E0 BE 5C E9 25 C1 D8 89 0A 6F 76 +# A8 7E C1 6D 4D 7D 5F 29 EA 74 19 CF 20 12 3B 69 +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK +DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz +OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R +xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX +qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC +C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 +6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh +/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF +YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E +JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc +US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 +ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm ++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi +M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV +cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc +Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs +PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ +q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 +cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr +a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I +H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y +K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu +nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf +oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY +Ic2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- +# "Staat der Nederlanden EV Root CA" +# 4D 24 91 41 4C FE 95 67 46 EC 4C EF A6 CF 6F 72 +# E2 8A 13 29 43 2F 9D 8A 90 7A C4 CB 5D AD C1 5A +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y +MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg +TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS +b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS +M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC +UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d +Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p +rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l +pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb +j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC +KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS +/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X +cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH +1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP +px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 +MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u +2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS +v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC +wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy +CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e +vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 +Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa +Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL +eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 +FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc +7uzXLg== +-----END CERTIFICATE----- +# "Staat der Nederlanden Root CA - G2" +# 66 8C 83 94 7D A6 3B 72 4B EC E1 74 3C 31 A0 E6 +# AE D0 DB 8E C5 B3 1B E3 77 BB 78 4F 91 B6 71 6F +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX +DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 +qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp +uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU +Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE +pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp +5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M +UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN +GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy +5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv +6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK +eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 +B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ +BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov +L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG +SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS +CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen +5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 +IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK +gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL ++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL +vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm +bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk +N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC +Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z +ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== +-----END CERTIFICATE----- +# "Staat der Nederlanden Root CA - G3" +# 3C 4F B0 B9 5A B8 B3 00 32 F4 32 B8 6F 53 5F E1 +# 72 C1 85 D0 FD 39 86 58 37 CF 36 18 7F A6 F4 28 +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX +DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP +cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW +IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX +xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy +KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR +9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az +5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 +6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 +Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP +bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt +BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt +XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd +INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp +LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 +Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp +gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh +/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw +0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A +fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq +4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR +1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ +QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM +94B7IWcnMFk= +-----END CERTIFICATE----- +# "Starfield Class 2 Certification Authority" +# 14 65 FA 20 53 97 B8 76 FA A6 F0 A9 95 8E 55 90 +# E4 0F CC 7F AA 4F B7 C2 C8 67 75 21 FB 5F B6 58 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- +# "Starfield Root Certificate Authority - G2" +# 2C E1 CB 0B F9 D2 F9 E1 02 99 3F BE 21 51 52 C3 +# B2 DD 0C AB DE 1C 68 E5 31 9B 83 91 54 DB B7 F5 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- +# "Starfield Services Root Certificate Authority - G2" +# 56 8D 69 05 A2 C8 87 08 A4 B3 02 51 90 ED CF ED +# B1 97 4A 60 6A 13 C6 E5 29 0F CB 2A E6 3E DA B5 +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- +# "StartCom Certification Authority" +# C7 66 A9 BE F2 D4 07 1C 86 3A 31 AA 49 20 E8 13 +# B2 D1 98 60 8C B7 B7 CF E2 11 43 B8 36 DF 09 EA +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j +ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js +LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM +BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy +dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh +cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh +YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg +dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp +bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ +YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT +TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ +9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 +jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW +FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz +ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 +ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L +EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu +L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC +O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V +um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh +NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= +-----END CERTIFICATE----- +# "StartCom Certification Authority" +# E1 78 90 EE 09 A3 FB F4 F4 8B 9C 41 4A 17 D6 37 +# B7 A5 06 47 E9 BC 75 23 22 72 7F CC 17 42 A9 11 +-----BEGIN CERTIFICATE----- +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul +F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC +ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w +ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk +aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 +YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg +c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 +d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG +CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF +wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS +Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst +0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc +pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl +CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF +P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK +1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm +KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ +8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm +fyWl8kgAwKQB2j8= +-----END CERTIFICATE----- +# "StartCom Certification Authority G2" +# C7 BA 65 67 DE 93 A7 98 AE 1F AA 79 1E 71 2D 37 +# 8F AE 1F 93 C4 39 7F EA 44 1B B7 CB E6 FD 59 95 +-----BEGIN CERTIFICATE----- +MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 +OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG +A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ +JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD +vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo +D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ +Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW +RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK +HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN +nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM +0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i +UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 +Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg +TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL +BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K +2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX +UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl +6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK +9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ +HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI +wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY +XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l +IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo +hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr +so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI +-----END CERTIFICATE----- +# "Swisscom Root CA 1" +# 21 DB 20 12 36 60 BB 2E D4 18 20 5D A1 1E E7 A8 +# 5A 65 E2 BC 6E 55 B5 AF 7E 78 99 C8 A2 66 D9 2E +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk +MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg +Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT +AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp +Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 +m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih +FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ +TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F +EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco +kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu +HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF +vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo +19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC +L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW +bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX +JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw +FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j +BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc +K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf +ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik +Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB +sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e +3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR +ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip +mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH +b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf +rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms +hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y +zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 +MBr1mmz0DlP5OlvRHA== +-----END CERTIFICATE----- +# "Swisscom Root CA 2" +# F0 9B 12 2C 71 14 F4 A0 9B D4 EA 4F 4A 99 D5 58 +# B4 6E 4C 25 CD 81 14 0D 29 C0 56 13 91 4C 38 41 +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBk +MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg +Q0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2MjUwNzM4MTRaMGQxCzAJBgNVBAYT +AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp +Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvEr +jw0DzpPMLgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r +0rk0X2s682Q2zsKwzxNoysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f +2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJwDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVP +ACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpHWrumnf2U5NGKpV+GY3aF +y6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1aSgJA/MTA +tukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL +6yxSNLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0 +uPoTXGiTOmekl9AbmbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrAL +acywlKinh/LTSlDcX3KwFnUey7QYYpqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velh +k6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3qPyZ7iVNTA6z00yPhOgpD/0Q +VAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw +FDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O +BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqh +b97iEoHF8TwuMA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4R +fbgZPnm3qKhyN2abGu2sEzsOv2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv +/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ82YqZh6NM4OKb3xuqFp1mrjX2lhI +REeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLzo9v/tdhZsnPdTSpx +srpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcsa0vv +aGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciAT +woCqISxxOQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99n +Bjx8Oto0QuFmtEYE3saWmA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5W +t6NlUe07qxS/TFED6F+KBZvuim6c779o+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N +8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TCrvJcwhbtkj6EPnNgiLx2 +9CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX5OfNeOI5 +wSsSnqaeG8XmDtkx2Q== +-----END CERTIFICATE----- +# "Swisscom Root EV CA 2" +# D9 5F EA 3C A4 EE DC E7 4C D7 6E 75 FC 6D 1F F6 +# 2C 44 1F 0F A8 BC 77 F0 34 B1 9E 5D B2 58 01 5D +-----BEGIN CERTIFICATE----- +MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAw +ZzELMAkGA1UEBhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdp +dGFsIENlcnRpZmljYXRlIFNlcnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290 +IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcNMzEwNjI1MDg0NTA4WjBnMQswCQYD +VQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2Vy +dGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYgQ0Eg +MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7Bx +UglgRCgzo3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD +1ycfMQ4jFrclyxy0uYAyXhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPH +oCE2G3pXKSinLr9xJZDzRINpUKTk4RtiGZQJo/PDvO/0vezbE53PnUgJUmfANykR +HvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8LiqG12W0OfvrSdsyaGOx9/ +5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaHZa0zKcQv +idm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHL +OdAGalNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaC +NYGu+HuB5ur+rPQam3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f +46Fq9mDU5zXNysRojddxyNMkM3OxbPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCB +UWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDixzgHcgplwLa7JSnaFp6LNYth +7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgGGMB0G +A1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED +MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWB +bj2ITY1x0kbBbkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6x +XCX5145v9Ydkn+0UjrgEjihLj6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98T +PLr+flaYC/NUn81ETm484T4VvwYmneTwkLbUwp4wLh/vx3rEUMfqe9pQy3omywC0 +Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7XwgiG/W9mR4U9s70 +WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH59yL +Gn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm +7JFe3VE/23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4S +nr8PyQUQ3nqjsTzyP6WqJ3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VN +vBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyAHmBR3NdUIR7KYndP+tiPsys6DXhyyWhB +WkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/giuMod89a2GQ+fYWVq6nTI +fI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuWl8PVP3wb +I+2ksx0WckNLIOFZfsLorSa/ovc= +-----END CERTIFICATE----- +# "SwissSign Gold CA - G2" +# 62 DD 0B E9 B9 F5 0A 16 3E A0 F8 E7 5C 05 3B 1E +# CA 57 EA 55 C8 68 8F 64 7C 68 81 F2 C8 35 7B 95 +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln +biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF +MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT +d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 +76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ +bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c +6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE +emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd +MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt +MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y +MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y +FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi +aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM +gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB +qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 +lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn +8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 +45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO +UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 +O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC +bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv +GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a +77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC +hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 +92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp +Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w +ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt +Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- +# "SwissSign Platinum CA - G2" +# 3B 22 2E 56 67 11 E9 92 30 0D C0 B1 5A B9 47 3D +# AF DE F8 C8 4D 0C EF 7D 33 17 B4 C1 82 1D 14 36 +-----BEGIN CERTIFICATE----- +MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu +IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw +WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD +ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y +IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn +IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ +6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob +jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw +izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl ++zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY +zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP +pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF +KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW +ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB +AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 +ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW +IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA +A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 +uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ +FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 +jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ +u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D +YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 +puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa +icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG +DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x +kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z +Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== +-----END CERTIFICATE----- +# "SwissSign Silver CA - G2" +# BE 6C 4D A2 BB B9 BA 59 B6 F3 93 97 68 37 42 46 +# C3 C0 05 99 3F A9 8F 02 0D 1D ED BE D4 8A 81 D5 +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu +IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow +RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY +U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv +Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br +YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF +nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH +6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt +eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ +c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ +MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH +HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf +jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 +5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB +rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c +wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB +AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp +WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 +xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ +2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ +IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 +aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X +em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR +dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ +OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ +hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy +tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- +# "Symantec Class 1 Public Primary Certification Authority - G6" +# 9D 19 0B 2E 31 45 66 68 5B E8 A8 89 E2 7A A8 C7 +# D7 AE 1D 8A AD DB A3 C1 EC F9 D2 48 63 CD 34 B9 +-----BEGIN CERTIFICATE----- +MIID9jCCAt6gAwIBAgIQJDJ18h0v0gkz97RqytDzmDANBgkqhkiG9w0BAQsFADCB +lDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8w +HQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMUUwQwYDVQQDEzxTeW1hbnRl +YyBDbGFzcyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzYwHhcNMTExMDE4MDAwMDAwWhcNMzcxMjAxMjM1OTU5WjCBlDELMAkGA1UE +BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZT +eW1hbnRlYyBUcnVzdCBOZXR3b3JrMUUwQwYDVQQDEzxTeW1hbnRlYyBDbGFzcyAx +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzYwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHOddJZKmZgiJM6kXZBxbje/SD +6Jlz+muxNuCad6BAwoGNAcfMjL2Pffd543pMA03Z+/2HOCgs3ZqLVAjbZ/sbjP4o +ki++t7JIp4Gh2F6Iw8w5QEFa0dzl2hCfL9oBTf0uRnz5LicKaTfukaMbasxEvxvH +w9QRslBglwm9LiL1QYRmn81ApqkAgMEflZKf3vNI79sdd2H8f9/ulqRy0LY+/3gn +r8uSFWkI22MQ4uaXrG7crPaizh5HmbmJtxLmodTNWRFnw2+F2EJOKL5ZVVkElauP +N4C/DfD8HzpkMViBeNfiNfYgPym4jxZuPkjctUwH4fIa6n4KedaovetdhitNAgMB +AAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBQzQejIORIVk0jyljIuWvXalF9TYDANBgkqhkiG9w0BAQsFAAOCAQEAFeNzV7EX +tl9JaUSm9l56Z6zS3nVJq/4lVcc6yUQVEG6/MWvL2QeTfxyFYwDjMhLgzMv7OWyP +4lPiPEAz2aSMR+atWPuJr+PehilWNCxFuBL6RIluLRQlKCQBZdbqUqwFblYSCT3Q +dPTXvQbKqDqNVkL6jXI+dPEDct+HG14OelWWLDi3mIXNTTNEyZSPWjEwN0ujOhKz +5zbRIWhLLTjmU64cJVYIVgNnhJ3Gw84kYsdMNs+wBkS39V8C3dlU6S+QTnrIToNA +DJqXPDe/v+z28LSFdyjBC8hnghAXOKK3Buqbvzr46SMHv3TgmDgVVXjucgBcGaP0 +0jPg/73RVDkpDw== +-----END CERTIFICATE----- +# "Symantec Class 2 Public Primary Certification Authority - G6" +# CB 62 7D 18 B5 8A D5 6D DE 33 1A 30 45 6B C6 5C +# 60 1A 4E 9B 18 DE DC EA 08 E7 DA AA 07 81 5F F0 +-----BEGIN CERTIFICATE----- +MIID9jCCAt6gAwIBAgIQZIKe/DcedF38l/+XyLH/QTANBgkqhkiG9w0BAQsFADCB +lDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8w +HQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMUUwQwYDVQQDEzxTeW1hbnRl +YyBDbGFzcyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzYwHhcNMTExMDE4MDAwMDAwWhcNMzcxMjAxMjM1OTU5WjCBlDELMAkGA1UE +BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZT +eW1hbnRlYyBUcnVzdCBOZXR3b3JrMUUwQwYDVQQDEzxTeW1hbnRlYyBDbGFzcyAy +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzYwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNzOkFyGOFyz9AYxe9GPo15gRn +V2WYKaRPyVyPDzTS+NqoE2KquB5QZ3iwFkygOakVeq7t0qLA8JA3KRgmXOgNPLZs +ST/B4NzZS7YUGQum05bh1gnjGSYc+R9lS/kaQxwAg9bQqkmi1NvmYji6UBRDbfkx ++FYW2TgCkc/rbN27OU6Z4TBnRfHU8I3D3/7yOAchfQBeVkSz5GC9kSucq1sEcg+y +KNlyqwUgQiWpWwNqIBDMMfAr2jUs0Pual07wgksr2F82owstr2MNHSV/oW5cYqGN +KD6h/Bwg+AEvulWaEbAZ0shQeWsOagXXqgQ2sqPy4V93p3ec5R7c6d9qwWVdAgMB +AAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBSHjCCVyJhK0daABkqQNETfHE2/sDANBgkqhkiG9w0BAQsFAAOCAQEAgY6ypWaW +tyGltu9vI1pf24HFQqV4wWn99DzX+VxrcHIa/FqXTQCAiIiCisNxDY7FiZss7Y0L +0nJU9X3UXENX6fOupQIR9nYrgVfdfdp0MP1UR/bgFm6mtApI5ud1Bw8pGTnOefS2 +bMVfmdUfS/rfbSw8DVSAcPCIC4DPxmiiuB1w2XaM/O6lyc+tHc+ZJVdaYkXLFmu9 +Sc2lo4xpeSWuuExsi0BmSxY/zwIa3eFsawdhanYVKZl/G92IgMG/tY9zxaaWI4Sm +KIYkM2oBLldzJbZev4/mHWGoQClnHYebHX+bn5nNMdZUvmK7OaxoEkiRIKXLsd3+ +b/xa5IJVWa8xqQ== +-----END CERTIFICATE----- +# "SZAFIR ROOT CA" +# FA BC F5 19 7C DD 7F 45 8A C3 38 32 D3 28 40 21 +# DB 24 25 FD 6B EA 7A 2E 69 B7 48 6E 8F 51 F9 CC +-----BEGIN CERTIFICATE----- +MIIDcTCCAlmgAwIBAgIVAOYJ/nrqAGiM4CS07SAbH+9StETRMA0GCSqGSIb3DQEB +BQUAMFAxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGlj +emVuaW93YSBTLkEuMRcwFQYDVQQDDA5TWkFGSVIgUk9PVCBDQTAeFw0xMTEyMDYx +MTEwNTdaFw0zMTEyMDYxMTEwNTdaMFAxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L +cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRcwFQYDVQQDDA5TWkFGSVIg +Uk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKxHL49ZMTml +6g3wpYwrvQKkvc0Kc6oJ5sxfgmp1qZfluwbv88BdocHSiXlY8NzrVYzuWBp7J/9K +ULMAoWoTIzOQ6C9TNm4YbA9A1jdX1wYNL5Akylf8W5L/I4BXhT9KnlI6x+a7BVAm +nr/Ttl+utT/Asms2fRfEsF2vZPMxH4UFqOAhFjxTkmJWf2Cu4nvRQJHcttB+cEAo +ag/hERt/+tzo4URz6x6r19toYmxx4FjjBkUhWQw1X21re//Hof2+0YgiwYT84zLb +eqDqCOMOXxvH480yGDkh/QoazWX3U75HQExT/iJlwnu7I1V6HXztKIwCBjsxffbH +3jOshCJtywcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFFOSo33/gnbwM9TrkmdHYTMbaDsqMA0GCSqGSIb3DQEBBQUA +A4IBAQA5UFWd5EL/pBviIMm1zD2JLUCpp0mJG7JkwznIOzawhGmFFaxGoxAhQBEg +haP+E0KR66oAwVC6xe32QUVSHfWqWndzbODzLB8yj7WAR0cDM45ZngSBPBuFE3Wu +GLJX9g100ETfIX+4YBR/4NR/uvTnpnd9ete7Whl0ZfY94yuu4xQqB5QFv+P7IXXV +lTOjkjuGXEcyQAjQzbFaT9vIABSbeCXWBbjvOXukJy6WgAiclzGNSYprre8Ryydd +fmjW9HIGwsIO03EldivvqEYL1Hv1w/Pur+6FUEOaL68PEIUovfgwIB2BAw+vZDuw +cH0mX548PojGyg434cDjkSXa3mHF +-----END CERTIFICATE----- +# "T-TeleSec GlobalRoot Class 2" +# 91 E2 F5 78 8D 58 10 EB A7 BA 58 73 7D E1 54 8A +# 8E CA CD 01 45 98 BC 0B 14 3E 04 1B 17 05 25 52 +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd +AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC +FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi +1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq +jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ +wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ +WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy +NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC +uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw +IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 +g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP +BSeOE6Fuwg== +-----END CERTIFICATE----- +# "T-TeleSec GlobalRoot Class 3" +# FD 73 DA D3 1C 64 4F F1 B4 3B EF 0C CD DA 96 71 +# 0B 9C D9 87 5E CA 7E 31 70 7A F3 E9 6D 52 2B BD +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- +# "TeliaSonera Root CA v1" +# DD 69 36 FE 21 F8 F0 77 C1 23 A1 A5 21 C1 22 24 +# F7 22 55 B7 3E 03 A7 26 06 93 E8 A2 4B 0F A3 89 +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw +NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv +b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD +VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F +VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 +7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X +Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ +/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs +81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm +dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe +Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu +sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 +pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs +slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ +arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG +9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl +dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj +TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed +Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 +Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI +OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 +vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW +t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn +HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx +SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- +# "thawte Primary Root CA" +# 8D 72 2F 81 A9 C1 13 C0 79 1D F1 36 A2 96 6D B2 +# 6C 95 0A 97 1D B4 6B 41 99 F4 EA 54 B7 8B FB 9F +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB +qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV +BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw +NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j +LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG +A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs +W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta +3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk +6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 +Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J +NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP +r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU +DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz +YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 +/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ +LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 +jVaMaA== +-----END CERTIFICATE----- +# "thawte Primary Root CA - G3" +# 4B 03 F4 58 07 AD 70 F2 1B FC 2C AE 71 C9 FD E4 +# 60 4C 06 4C F5 FF B6 86 BA E5 DB AA D7 FD D3 4C +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB +rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV +BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa +Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl +LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u +MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm +gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 +YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf +b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 +9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S +zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk +OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA +2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW +oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c +KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM +m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu +MdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- +# "TRUST2408 OCES Primary CA" +# 92 D8 09 2E E7 7B C9 20 8F 08 97 DC 05 27 18 94 +# E6 3E F2 79 33 AE 53 7F B9 83 EE F0 EA E3 EE C8 +-----BEGIN CERTIFICATE----- +MIIGHDCCBASgAwIBAgIES45gAzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJE +SzESMBAGA1UEChMJVFJVU1QyNDA4MSIwIAYDVQQDExlUUlVTVDI0MDggT0NFUyBQ +cmltYXJ5IENBMB4XDTEwMDMwMzEyNDEzNFoXDTM3MTIwMzEzMTEzNFowRTELMAkG +A1UEBhMCREsxEjAQBgNVBAoTCVRSVVNUMjQwODEiMCAGA1UEAxMZVFJVU1QyNDA4 +IE9DRVMgUHJpbWFyeSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJlJodr3U1Fa+v8HnyACHV81/wLevLS0KUk58VIABl6Wfs3LLNoj5soVAZv4LBi5 +gs7E8CZ9w0F2CopW8vzM8i5HLKE4eedPdnaFqHiBZ0q5aaaQArW+qKJx1rT/AaXt +alMB63/yvJcYlXS2lpexk5H/zDBUXeEQyvfmK+slAySWT6wKxIPDwVapauFY9QaG ++VBhCa5jBstWS7A5gQfEvYqn6csZ3jW472kW6OFNz6ftBcTwufomGJBMkonf4ZLr +6t0AdRi9jflBPz3MNNRGxyjIuAmFqGocYFA/OODBRjvSHB2DygqQ8k+9tlpvzMRr +kU7jq3RKL+83G1dJ3/LTjCLz4ryEMIC/OJ/gNZfE0qXddpPtzflIPtUFVffXdbFV +1t6XZFhJ+wBHQCpJobq/BjqLWUA86upsDbfwnePtmIPRCemeXkY0qabC+2Qmd2Fe +xyZphwTyMnbqy6FG1tB65dYf3mOqStmLa3RcHn9+2dwNfUkh0tjO2FXD7drWcU0O +I9DW8oAypiPhm/QCjMU6j6t+0pzqJ/S0tdAo+BeiXK5hwk6aR+sRb608QfBbRAs3 +U/q8jSPByenggac2BtTN6cl+AA1Mfcgl8iXWNFVGegzd/VS9vINClJCe3FNVoUnR +YCKkj+x0fqxvBLopOkJkmuZw/yhgMxljUi2qYYGn90OzAgMBAAGjggESMIIBDjAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjARBgNVHSAECjAIMAYGBFUd +IAAwgZcGA1UdHwSBjzCBjDAsoCqgKIYmaHR0cDovL2NybC5vY2VzLnRydXN0MjQw +OC5jb20vb2Nlcy5jcmwwXKBaoFikVjBUMQswCQYDVQQGEwJESzESMBAGA1UEChMJ +VFJVU1QyNDA4MSIwIAYDVQQDExlUUlVTVDI0MDggT0NFUyBQcmltYXJ5IENBMQ0w +CwYDVQQDEwRDUkwxMB8GA1UdIwQYMBaAFPZt+LFIs0FDAduGROUYBbdezAY3MB0G +A1UdDgQWBBT2bfixSLNBQwHbhkTlGAW3XswGNzANBgkqhkiG9w0BAQsFAAOCAgEA +VPAQGrT7dIjD3/sIbQW86f9CBPu0c7JKN6oUoRUtKqgJ2KCdcB5ANhCoyznHpu3m +/dUfVUI5hc31CaPgZyY37hch1q4/c9INcELGZVE/FWfehkH+acpdNr7j8UoRZlkN +15b/0UUBfGeiiJG/ugo4llfoPrp8bUmXEGggK3wyqIPcJatPtHwlb6ympfC2b/Ld +v/0IdIOzIOm+A89Q0utx+1cOBq72OHy8gpGb6MfncVFMoL2fjP652Ypgtr8qN9Ka +/XOazktiIf+2Pzp7hLi92hRc9QMYexrV/nnFSQoWdU8TqULFUoZ3zTEC3F/g2yj+ +FhbrgXHGo5/A4O74X+lpbY2XV47aSuw+DzcPt/EhMj2of7SA55WSgbjPMbmNX0rb +oenSIte2HRFW5Tr2W+qqkc/StixgkKdyzGLoFx/xeTWdJkZKwyjqge2wJqws2upY +EiThhC497+/mTiSuXd69eVUwKyqYp9SD2rTtNmF6TCghRM/dNsJOl+osxDVGcwvt +WIVFF/Onlu5fu1NHXdqNEfzldKDUvCfii3L2iATTZyHwU9CALE+2eIA+PIaLgnM1 +1oCfUnYBkQurTrihvzz9PryCVkLxiqRmBVvUz+D4N5G/wvvKDS6t6cPCS+hqM482 +cbBsn0R9fFLO4El62S9eH1tqOzO20OAOK65yJIsOpSE= +-----END CERTIFICATE----- +# "TrustCor ECA-1" +# 5A 88 5D B1 9C 01 D9 12 C5 75 93 88 93 8C AF BB +# DF 03 1A B2 D4 8E 91 EE 15 58 9B 42 97 1D 03 9C +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y +IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig +RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb +3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA +BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 +3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou +owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ +wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF +ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf +BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv +civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 +AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 +soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI +WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi +tJ/X5g== +-----END CERTIFICATE----- +# "TrustCor RootCert CA-1" +# D4 0E 9C 86 CD 8F E4 68 C1 77 69 59 F4 9E A7 74 +# FA 54 86 84 B6 C4 06 F3 90 92 61 F4 DC E2 57 5C +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y +IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB +pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h +IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG +A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU +cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid +RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V +seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme +9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV +EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW +hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ +DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I +/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ +yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts +L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN +zl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- +# "TrustCor RootCert CA-2" +# 07 53 E9 40 37 8C 1B D5 E3 83 6E 39 5D AE A5 CB +# 83 9E 50 46 F1 BD 0E AE 19 51 CF 10 FE C7 C9 65 +-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig +Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk +MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg +Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD +VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy +dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ +QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq +1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp +2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK +DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape +az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF +3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 +oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM +g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 +mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd +BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U +nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw +DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX +dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ +MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL +/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX +CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa +ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW +2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 +N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 +Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB +As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp +5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu +1uwJ +-----END CERTIFICATE----- +# "Trustis FPS Root CA" +# C1 B4 82 99 AB A5 20 8F E9 63 0A CE 55 CA 68 A0 +# 3E DA 5A 51 9C 88 02 A0 D3 A6 73 BE 8F 8E 55 7D +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL +ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx +MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc +MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ +AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH +iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj +vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA +0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB +OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ +BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E +FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 +GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW +zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 +1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE +f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F +jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN +ZetX2fNXlrtIzYE= +-----END CERTIFICATE----- +# "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" +# 46 ED C3 68 90 46 D5 3A 45 3F B3 10 4A B8 0D CA +# EC 65 8B 26 60 EA 16 29 DD 7E 86 79 90 64 87 16 +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx +GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp +bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w +KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 +BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy +dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG +EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll +IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU +QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT +TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg +LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 +a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr +LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr +N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X +YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ +iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f +AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH +V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf +IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 +lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c +8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf +lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- +# "TWCA Global Root CA" +# 59 76 90 07 F7 68 5D 0F CD 50 87 2F 9F 95 D5 75 +# 5A 5B 2B 45 7D 81 F3 69 2B 61 0A 98 67 2F 0E 1B +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- +# "TWCA Root Certification Authority" +# BF D8 8F E1 10 1C 41 AE 3E 80 1B F8 BE 56 35 0E +# E9 BA D1 A6 B9 BD 51 5E DC 5C 6D 5B 87 11 AC 44 +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- +# "UCA Global Root" +# A1 F0 5C CB 80 C2 D7 10 EC 7D 47 9A BD CB B8 79 +# E5 8D 7E DB 71 49 FE 78 A8 78 84 E3 D0 BA D0 F9 +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBCDANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJDTjER +MA8GA1UEChMIVW5pVHJ1c3QxGDAWBgNVBAMTD1VDQSBHbG9iYWwgUm9vdDAeFw0w +ODAxMDEwMDAwMDBaFw0zNzEyMzEwMDAwMDBaMDoxCzAJBgNVBAYTAkNOMREwDwYD +VQQKEwhVbmlUcnVzdDEYMBYGA1UEAxMPVUNBIEdsb2JhbCBSb290MIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2rPlBlA/9nP3xDK/RqUlYjOHsGj+p9+I +A2N9Apb964fJ7uIIu527u+RBj8cwiQ9tJMAEbBSUgU2gDXRm8/CFr/hkGd656YGT +0CiFmUdCSiw8OCdKzP/5bBnXtfPvm65bNAbXj6ITBpyKhELVs6OQaG2BkO5NhOxM +cE4t3iQ5zhkAQ5N4+QiGHUPR9HK8BcBn+sBR0smFBySuOR56zUHSNqth6iur8CBV +mTxtLRwuLnWW2HKX4AzKaXPudSsVCeCObbvaE/9GqOgADKwHLx25urnRoPeZnnRc +GQVmMc8+KlL+b5/zub35wYH1N9ouTIElXfbZlJrTNYsgKDdfUet9Ysepk9H50DTL +qScmLCiQkjtVY7cXDlRzq6987DqrcDOsIfsiJrOGrCOp139tywgg8q9A9f9ER3Hd +J90TKKHqdjn5EKCgTUCkJ7JZFStsLSS3JGN490MYeg9NEePorIdCjedYcaSrbqLA +l3y74xNLytu7awj5abQEctXDRrl36v+6++nwOgw19o8PrgaEFt2UVdTvyie3AzzF +HCYq9TyopZWbhvGKiWf4xwxmse1Bv4KmAGg6IjTuHuvlb4l0T2qqaqhXZ1LUIGHB +zlPL/SR/XybfoQhplqCe/klD4tPq2sTxiDEhbhzhzfN1DiBEFsx9c3Q1RSw7gdQg +7LYJjD5IskkCAwEAAaOBojCBnzALBgNVHQ8EBAMCAQYwDAYDVR0TBAUwAwEB/zBj +BgNVHSUEXDBaBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcD +BAYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUHAwgGCCsGAQUF +BwMJMB0GA1UdDgQWBBTZw9P4gJJnzF3SOqLXcaK0xDiALTANBgkqhkiG9w0BAQUF +AAOCAgEA0Ih5ygiq9ws0oE4Jwul+NUiJcIQjL1HDKy9e21NrW3UIKlS6Mg7VxnGF +sZdJgPaE0PC6t3GUyHlrpsVE6EKirSUtVy/m1jEp+hmJVCl+t35HNmktbjK81HXa +QnO4TuWDQHOyXd/URHOmYgvbqm4FjMh/Rk85hZCdvBtUKayl1/7lWFZXbSyZoUkh +1WHGjGHhdSTBAd0tGzbDLxLMC9Z4i3WA6UG5iLHKPKkWxk4V43I29tSgQYWvimVw +TbVEEFDs7d9t5tnGwBLxSzovc+k8qe4bqi81pZufTcU0hF8mFGmzI7GJchT46U1R +IgP/SobEHOh7eQrbRyWBfvw0hKxZuFhD5D1DCVR0wtD92e9uWfdyYJl2b/Unp7uD +pEqB7CmB9HdL4UISVdSGKhK28FWbAS7d9qjjGcPORy/AeGEYWsdl/J1GW1fcfA67 +loMQfFUYCQSu0feLKj6g5lDWMDbX54s4U+xJRODPpN/xU3uLWrb2EZBL1nXz/gLz +Ka/wI3J9FO2pXd96gZ6bkiL8HvgBRUGXx2sBYb4zaPKgZYRmvOAqpGjTcezHCN6j +w8k2SjTxF+KAryAhk5Qe5hXTVGLxtTgv48y5ZwSpuuXu+RBuyy5+E6+SFP7zJ3N7 +OPxzbbm5iPZujAv1/P8JDrMtXnt145Ik4ubhWD5LKAN1axibRww= +-----END CERTIFICATE----- +# "UCA Root" +# 93 E6 5E C7 62 F0 55 DC 71 8A 33 25 82 C4 1A 04 +# 43 0D 72 E3 CB 87 E8 B8 97 B6 75 16 F0 D1 AA 39 +-----BEGIN CERTIFICATE----- +MIIDhDCCAmygAwIBAgIBCTANBgkqhkiG9w0BAQUFADAzMQswCQYDVQQGEwJDTjER +MA8GA1UEChMIVW5pVHJ1c3QxETAPBgNVBAMTCFVDQSBSb290MB4XDTA0MDEwMTAw +MDAwMFoXDTI5MTIzMTAwMDAwMFowMzELMAkGA1UEBhMCQ04xETAPBgNVBAoTCFVu +aVRydXN0MREwDwYDVQQDEwhVQ0EgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBALNdB8qGJn1r4vs4CQ7MgsJqGgCiFV/W6dQBt1YDAVmP9ThpJHbC +XivF9iu/r/tB/Q9a/KvXg3BNMJjRnrJ2u5LWu+kQKGkoNkTo8SzXWHwk1n8COvCB +a2FgP/Qz3m3l6ihST/ypHWN8C7rqrsRoRuTej8GnsrZYWm0dLNmMOreIy4XU9+gD +Xv2yTVDo1h//rgI/i0+WITyb1yXJHT/7mLFZ5PCpO6+zzYUs4mBGzG+OoOvwNMXx +QhhgrhLtRnUc5dipllq+3lrWeGeWW5N3UPJuG96WUUqm1ktDdSFmjXfsAoR2XEQQ +th1hbOSjIH23jboPkXXHjd+8AmCoKai9PUMCAwEAAaOBojCBnzALBgNVHQ8EBAMC +AQYwDAYDVR0TBAUwAwEB/zBjBgNVHSUEXDBaBggrBgEFBQcDAQYIKwYBBQUHAwIG +CCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcD +BwYIKwYBBQUHAwgGCCsGAQUFBwMJMB0GA1UdDgQWBBTbHzXza0z/QjFkm827Wh4d +SBC37jANBgkqhkiG9w0BAQUFAAOCAQEAOGy3iPGt+lg3dNHocN6cJ1nL5BXXoMNg +14iABMUwTD3UGusGXllH5rxmy+AI/Og17GJ9ysDawXiv5UZv+4mCI4/211NmVaDe +JRI7cTYWVRJ2+z34VFsxugAG+H1V5ad2g6pcSpemKijfvcZsCyOVjjN/Hl5AHxNU +LJzltQ7dFyiuawHTUin1Ih+QOfTcYmjwPIZH7LgFRbu3DJaUxmfLI3HQjnQi1kHr +A6i26r7EARK1s11AdgYg1GS4KUYGis4fk5oQ7vuqWrTcL9Ury/bXBYSYBZELhPc9 ++tb5evosFeo2gkO3t7jj83EB7UNDogVFwygFBzXjAaU4HoDU18PZ3g== +-----END CERTIFICATE----- +# "USERTrust ECC Certification Authority" +# 4F F4 60 D5 4B 9C 86 DA BF BC FC 57 12 E0 40 0D +# 2B ED 3F BC 4D 4F BD AA 86 E0 6A DC D2 A9 AD 7A +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl +eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT +JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg +VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo +I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng +o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G +A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB +zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW +RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- +# "USERTrust RSA Certification Authority" +# E7 93 C9 B0 2F D8 AA 13 E2 1C 31 22 8A CC B0 81 +# 19 64 3B 74 9C 89 89 64 B1 74 6D 46 C3 D4 CB D2 +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw +MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV +BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B +3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY +tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ +Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 +VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT +79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 +c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT +Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l +c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee +UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE +Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF +Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO +VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 +ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs +8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR +iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze +Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ +XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ +qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB +VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB +L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG +jjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- +# "VeriSign Class 1 Public Primary Certification Authority - G3" +# CB B5 AF 18 5E 94 2A 24 02 F9 EA CB C0 ED 5B B8 +# 76 EE A3 C1 22 36 23 D0 04 47 E4 F3 BA 55 4B 65 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 +nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO +8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV +ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb +PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 +6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr +n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a +qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 +wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 +ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs +pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 +E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== +-----END CERTIFICATE----- +# "VeriSign Class 2 Public Primary Certification Authority - G3" +# 92 A9 D9 83 3F E1 94 4D B3 66 E8 BF AE 7A 95 B6 +# 48 0C 2D 6C 6C 2A 1B E6 5D 42 36 B6 08 FC A1 BB +-----BEGIN CERTIFICATE----- +MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy +aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp +Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV +BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp +Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g +Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU +J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO +JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY +wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o +koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN +qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E +Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe +xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u +7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU +sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI +sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP +cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q +-----END CERTIFICATE----- +# "VeriSign Class 3 Public Primary Certification Authority - G3" +# EB 04 CF 5E B1 F3 9A FA 76 2F 2B B1 20 F2 96 CB +# A5 20 C1 B9 7D B1 58 95 65 B8 1C B9 A1 7B 72 44 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- +# "VeriSign Class 3 Public Primary Certification Authority - G4" +# 69 DD D7 EA 90 BB 57 C9 3E 13 5D C8 5E A6 FC D5 +# 48 0B 60 32 39 BD C4 54 FC 75 8B 2A 26 CF 7F 79 +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp +U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg +SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln +biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm +GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve +fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ +aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj +aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW +kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC +4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga +FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- +# "VeriSign Class 3 Public Primary Certification Authority - G5" +# 9A CF AB 7E 43 C8 D8 80 D0 6B 26 2A 94 DE EE E4 +# B4 65 99 89 C3 D0 CA F1 9B AF 64 05 E4 1A B7 DF +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- +# "VeriSign Universal Root Certification Authority" +# 23 99 56 11 27 A5 71 25 DE 8C EF EA 61 0D DF 2F +# A0 78 B5 C8 06 7F 4E 82 82 90 BF B8 60 E8 4B 3C +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB +vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W +ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 +IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y +IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh +bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF +9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH +H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H +LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN +/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT +rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw +WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs +exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 +sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ +seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz +4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ +BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR +lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 +7M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- +# "Visa eCommerce Root" +# 69 FA C9 BD 55 FB 0A C7 8D 53 BB EE 5C F1 D5 97 +# 98 9F D0 AA AB 20 A2 51 51 BD F1 73 3E E7 D1 22 +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw +CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h +dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l +cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h +2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E +lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV +ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq +299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t +vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL +dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF +AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR +zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 +LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd +7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw +++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- +# "Visa Information Delivery Root CA" +# C5 7A 3A CB E8 C0 6B A1 98 8A 83 48 5B F3 26 F2 +# 44 87 75 37 98 49 DE 01 CA 43 57 1A F3 57 E7 4B +-----BEGIN CERTIFICATE----- +MIID+TCCAuGgAwIBAgIQW1fXqEywr9nTb0ugMbTW4jANBgkqhkiG9w0BAQUFADB5 +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xKjAoBgNVBAMTIVZpc2EgSW5m +b3JtYXRpb24gRGVsaXZlcnkgUm9vdCBDQTAeFw0wNTA2MjcxNzQyNDJaFw0yNTA2 +MjkxNzQyNDJaMHkxCzAJBgNVBAYTAlVTMQ0wCwYDVQQKEwRWSVNBMS8wLQYDVQQL +EyZWaXNhIEludGVybmF0aW9uYWwgU2VydmljZSBBc3NvY2lhdGlvbjEqMCgGA1UE +AxMhVmlzYSBJbmZvcm1hdGlvbiBEZWxpdmVyeSBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyREA4R/QkkfpLx0cYjga/EhIPZpchH0MZsRZ +FfP6C2ITtf/Wc+MtgD4yTK0yoiXvni3d+aCtEgK3GDvkdgYrgF76ROJFZwUQjQ9l +x42gRT05DbXvWFoy7dTglCZ9z/Tt2Cnktv9oxKgmkeHY/CyfpCBg1S8xth2JlGMR +0ug/GMO5zANuegZOv438p5Lt5So+du2Gl+RMFQqEPwqN5uJSqAe0VtmB4gWdQ8on +Bj2ZAM2R73QW7UW0Igt2vA4JaSiNtaAG/Y/58VXWHGgbq7rDtNK1R30X0kJV0rGA +ib3RSwB3LpG7bOjbIucV5mQgJoVjoA1e05w6g1x/KmNTmOGRVwIDAQABo30wezAP +BgNVHRMBAf8EBTADAQH/MDkGA1UdIAQyMDAwLgYFZ4EDAgEwJTAVBggrBgEFBQcC +ARYJMS4yLjMuNC41MAwGCCsGAQUFBwICMAAwDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBRPitp2/2d3I5qmgH1924h1hfeBejANBgkqhkiG9w0BAQUFAAOCAQEACUW1 +QdUHdDJydgDPmYt+telnG/Su+DPaf1cregzlN43bJaJosMP7NwjoJY/H2He4XLWb +5rXEkl+xH1UyUwF7mtaUoxbGxEvt8hPZSTB4da2mzXgwKvXuHyzF5Qjy1hOB0/pS +WaF9ARpVKJJ7TOJQdGKBsF2Ty4fSCLqZLgfxbqwMsd9sysXI3rDXjIhekqvbgeLz +PqZr+pfgFhwCCLSMQWl5Ll3u7Qk9wR094DZ6jj6+JCVCRUS3HyabH4OlM0Vc2K+j +INsF/64Or7GNtRf9HYEJvrPxHINxl3JVwhYj4ASeaO4KwhVbwtw94Tc/XrGcexDo +c5lC3rAi4/UZqweYCw== +-----END CERTIFICATE----- +# "VRK Gov. Root CA" +# F0 08 73 3E C5 00 DC 49 87 63 CC 92 64 C6 FC EA +# 40 EC 22 00 0E 92 7D 05 3C E9 C9 0B FA 04 6C B2 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwKgAwIBAgIDAYagMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYDVQQGEwJG +STEQMA4GA1UECBMHRmlubGFuZDEhMB8GA1UEChMYVmFlc3RvcmVraXN0ZXJpa2Vz +a3VzIENBMSkwJwYDVQQLEyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBTZXJ2aWNl +czEZMBcGA1UECxMQVmFybWVubmVwYWx2ZWx1dDEZMBcGA1UEAxMQVlJLIEdvdi4g +Um9vdCBDQTAeFw0wMjEyMTgxMzUzMDBaFw0yMzEyMTgxMzUxMDhaMIGjMQswCQYD +VQQGEwJGSTEQMA4GA1UECBMHRmlubGFuZDEhMB8GA1UEChMYVmFlc3RvcmVraXN0 +ZXJpa2Vza3VzIENBMSkwJwYDVQQLEyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBT +ZXJ2aWNlczEZMBcGA1UECxMQVmFybWVubmVwYWx2ZWx1dDEZMBcGA1UEAxMQVlJL +IEdvdi4gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALCF +FdrIAzfQo0Y3bBseljDCWoUSZyPyu5/nioFgJ/gTqTy894aqqvTzJSm0/nWuHoGG +igWyHWWyOOi0zCia+xc28ZPVec7Bg4shT8MNrUHfeJ1I4x9CRPw8bSEga60ihCRC +jxdNwlAfZM0tOSJWiP2yY51U2kJpwMhP1xjiPshphJQ9LIDGfM6911Mf64i5psu7 +hVfvV3ZdDIvTXhJBnyHAOfQmbQj6OLOhd7HuFtjQaNq0mKWgZUZKa41+qk1guPjI +DfxxPu45h4G02fhukO4/DmHXHSto5i7hQkQmeCxY8n0Wf2HASSQqiYe2XS8pGfim +545SnkFLWg6quMJmQlMCAwEAAaNVMFMwDwYDVR0TAQH/BAUwAwEB/zARBglghkgB +hvhCAQEEBAMCAAcwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBTb6eGb0tEkC/yr +46Bn6q6cS3f0sDANBgkqhkiG9w0BAQUFAAOCAQEArX1ID1QRnljurw2bEi8hpM2b +uoRH5sklVSPj3xhYKizbXvfNVPVRJHtiZ+GxH0mvNNDrsczZog1Sf0JLiGCXzyVy +t08pLWKfT6HAVVdWDsRol5EfnGTCKTIB6dTI2riBmCguGMcs/OubUpbf9MiQGS0j +8/G7cdqehSO9Gu8u5Hp5t8OdhkktY7ktdM9lDzJmid87Ie4pbzlj2RXBbvbfgD5Q +eBmK3QOjFKU3p7UsfLYRh+cF8ry23tT/l4EohP7+bEaFEEGfTXWMB9SZZ291im/k +UJL2mdUQuMSpe/cXjUu/15WfCdxEDx4yw8DP03kN5Mc7h/CQNIghYkmSBAQfvA== +-----END CERTIFICATE----- +# "XRamp Global Certification Authority" +# CE CD DC 90 50 99 D8 DA DF C5 B1 D2 09 B7 37 CB +# E2 C1 8C FB 2C 10 C0 FF 0B CF 0D 32 86 FC 1A A2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- +` diff --git a/src/crypto/x509/root_ios_gen.go b/src/crypto/x509/root_ios_gen.go new file mode 100644 index 0000000..05bd672 --- /dev/null +++ b/src/crypto/x509/root_ios_gen.go @@ -0,0 +1,181 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +// Generates root_ios.go. +// +// As of iOS 13, there is no API for querying the system trusted X.509 root +// certificates. +// +// Apple publishes the trusted root certificates for iOS and macOS on +// opensource.apple.com so we embed them into the x509 package. +// +// Note that this ignores distrusted and revoked certificates. +package main + +import ( + "archive/tar" + "bytes" + "compress/gzip" + "crypto/sha256" + "crypto/tls" + "crypto/x509" + "encoding/pem" + "flag" + "fmt" + "go/format" + "io" + "log" + "net/http" + "os" + "path" + "sort" + "strings" + "time" +) + +func main() { + var output = flag.String("output", "root_ios.go", "file name to write") + var version = flag.String("version", "", "security_certificates version") + flag.Parse() + if *version == "" { + log.Fatal("Select the latest security_certificates version from " + + "https://opensource.apple.com/source/security_certificates/") + } + + url := "https://opensource.apple.com/tarballs/security_certificates/security_certificates-%s.tar.gz" + hc := &http.Client{Timeout: 1 * time.Minute} + resp, err := hc.Get(fmt.Sprintf(url, *version)) + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + log.Fatalf("HTTP status not OK: %s", resp.Status) + } + + zr, err := gzip.NewReader(resp.Body) + if err != nil { + log.Fatal(err) + } + defer zr.Close() + + var certs []*x509.Certificate + pool := x509.NewCertPool() + + tr := tar.NewReader(zr) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + log.Fatal(err) + } + + rootsDirectory := fmt.Sprintf("security_certificates-%s/certificates/roots/", *version) + if dir, file := path.Split(hdr.Name); hdr.Typeflag != tar.TypeReg || + dir != rootsDirectory || strings.HasPrefix(file, ".") { + continue + } + + der, err := io.ReadAll(tr) + if err != nil { + log.Fatal(err) + } + + c, err := x509.ParseCertificate(der) + if err != nil { + log.Printf("Failed to parse certificate %q: %v", hdr.Name, err) + continue + } + + certs = append(certs, c) + pool.AddCert(c) + } + + // Quick smoke test to check the pool is well formed, and that we didn't end + // up trusting roots in the removed folder. + for _, c := range certs { + if c.Subject.CommonName == "Symantec Class 2 Public Primary Certification Authority - G4" { + log.Fatal("The pool includes a removed root!") + } + } + conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{ + RootCAs: pool, + }) + if err != nil { + log.Fatal(err) + } + conn.Close() + + certName := func(c *x509.Certificate) string { + if c.Subject.CommonName != "" { + return c.Subject.CommonName + } + if len(c.Subject.OrganizationalUnit) > 0 { + return c.Subject.OrganizationalUnit[0] + } + return c.Subject.Organization[0] + } + sort.Slice(certs, func(i, j int) bool { + if strings.ToLower(certName(certs[i])) != strings.ToLower(certName(certs[j])) { + return strings.ToLower(certName(certs[i])) < strings.ToLower(certName(certs[j])) + } + if !certs[i].NotBefore.Equal(certs[j].NotBefore) { + return certs[i].NotBefore.Before(certs[j].NotBefore) + } + fi, fj := sha256.Sum256(certs[i].Raw), sha256.Sum256(certs[j].Raw) + return bytes.Compare(fi[:], fj[:]) < 0 + }) + + out := new(bytes.Buffer) + fmt.Fprintf(out, header, *version) + fmt.Fprintf(out, "const systemRootsPEM = `\n") + + for _, c := range certs { + fmt.Fprintf(out, "# %q\n", certName(c)) + h := sha256.Sum256(c.Raw) + fmt.Fprintf(out, "# % X\n", h[:len(h)/2]) + fmt.Fprintf(out, "# % X\n", h[len(h)/2:]) + b := &pem.Block{ + Type: "CERTIFICATE", + Bytes: c.Raw, + } + if err := pem.Encode(out, b); err != nil { + log.Fatal(err) + } + } + + fmt.Fprintf(out, "`") + + source, err := format.Source(out.Bytes()) + if err != nil { + log.Fatal(err) + } + if err := os.WriteFile(*output, source, 0644); err != nil { + log.Fatal(err) + } +} + +const header = `// Code generated by root_ios_gen.go -version %s; DO NOT EDIT. +// Update the version in root.go and regenerate with "go generate". + +// +build ios +// +build !x509omitbundledroots + +package x509 + +func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { + return nil, nil +} + +func loadSystemRoots() (*CertPool, error) { + p := NewCertPool() + p.AppendCertsFromPEM([]byte(systemRootsPEM)) + return p, nil +} +` diff --git a/src/crypto/x509/root_js.go b/src/crypto/x509/root_js.go new file mode 100644 index 0000000..f2c2c0a --- /dev/null +++ b/src/crypto/x509/root_js.go @@ -0,0 +1,15 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build js && wasm +// +build js,wasm + +package x509 + +// Possible certificate files; stop after finding one. +var certFiles = []string{} + +// Possible directories with certificate files; stop after successfully +// reading at least one file from a directory. +var certDirectories = []string{} diff --git a/src/crypto/x509/root_linux.go b/src/crypto/x509/root_linux.go new file mode 100644 index 0000000..ad6ce5c --- /dev/null +++ b/src/crypto/x509/root_linux.go @@ -0,0 +1,23 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +// Possible certificate files; stop after finding one. +var certFiles = []string{ + "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6 + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7 + "/etc/ssl/cert.pem", // Alpine Linux +} + +// Possible directories with certificate files; stop after successfully +// reading at least one file from a directory. +var certDirectories = []string{ + "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 + "/etc/pki/tls/certs", // Fedora/RHEL + "/system/etc/security/cacerts", // Android +} diff --git a/src/crypto/x509/root_omit.go b/src/crypto/x509/root_omit.go new file mode 100644 index 0000000..81f2f11 --- /dev/null +++ b/src/crypto/x509/root_omit.go @@ -0,0 +1,27 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots +// +build darwin,arm64 darwin,amd64,ios +// +build x509omitbundledroots + +// This file provides the loadSystemRoots func when the +// "x509omitbundledroots" build tag has disabled bundling a copy, +// which currently on happens on darwin/arm64 (root_darwin_arm64.go). +// This then saves 256 KiB of binary size and another 560 KiB of +// runtime memory size retaining the parsed roots forever. Constrained +// environments can construct minimal x509 root CertPools on the fly +// in the crypto/tls.Config.VerifyPeerCertificate hook. + +package x509 + +import "errors" + +func loadSystemRoots() (*CertPool, error) { + return nil, errors.New("x509: system root bundling disabled") +} + +func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { + return nil, nil +} diff --git a/src/crypto/x509/root_omit_test.go b/src/crypto/x509/root_omit_test.go new file mode 100644 index 0000000..158bd7f --- /dev/null +++ b/src/crypto/x509/root_omit_test.go @@ -0,0 +1,24 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots +// +build darwin,arm64 darwin,amd64,ios +// +build x509omitbundledroots + +package x509 + +import ( + "strings" + "testing" +) + +func TestOmitBundledRoots(t *testing.T) { + cp, err := loadSystemRoots() + if err == nil { + t.Fatalf("loadSystemRoots = (pool %p, error %v); want non-nil error", cp, err) + } + if !strings.Contains(err.Error(), "root bundling disabled") { + t.Errorf("unexpected error doesn't mention bundling: %v", err) + } +} diff --git a/src/crypto/x509/root_plan9.go b/src/crypto/x509/root_plan9.go new file mode 100644 index 0000000..2bdb2fe --- /dev/null +++ b/src/crypto/x509/root_plan9.go @@ -0,0 +1,40 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build plan9 +// +build plan9 + +package x509 + +import ( + "os" +) + +// Possible certificate files; stop after finding one. +var certFiles = []string{ + "/sys/lib/tls/ca.pem", +} + +func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { + return nil, nil +} + +func loadSystemRoots() (*CertPool, error) { + roots := NewCertPool() + var bestErr error + for _, file := range certFiles { + data, err := os.ReadFile(file) + if err == nil { + roots.AppendCertsFromPEM(data) + return roots, nil + } + if bestErr == nil || (os.IsNotExist(bestErr) && !os.IsNotExist(err)) { + bestErr = err + } + } + if bestErr == nil { + return roots, nil + } + return nil, bestErr +} diff --git a/src/crypto/x509/root_solaris.go b/src/crypto/x509/root_solaris.go new file mode 100644 index 0000000..97c1913 --- /dev/null +++ b/src/crypto/x509/root_solaris.go @@ -0,0 +1,18 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +// Possible certificate files; stop after finding one. +var certFiles = []string{ + "/etc/certs/ca-certificates.crt", // Solaris 11.2+ + "/etc/ssl/certs/ca-certificates.crt", // Joyent SmartOS + "/etc/ssl/cacert.pem", // OmniOS +} + +// Possible directories with certificate files; stop after successfully +// reading at least one file from a directory. +var certDirectories = []string{ + "/etc/certs/CA", +} diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go new file mode 100644 index 0000000..dede825 --- /dev/null +++ b/src/crypto/x509/root_unix.go @@ -0,0 +1,109 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris +// +build aix dragonfly freebsd js,wasm linux netbsd openbsd solaris + +package x509 + +import ( + "io/fs" + "os" + "path/filepath" + "strings" +) + +const ( + // certFileEnv is the environment variable which identifies where to locate + // the SSL certificate file. If set this overrides the system default. + certFileEnv = "SSL_CERT_FILE" + + // certDirEnv is the environment variable which identifies which directory + // to check for SSL certificate files. If set this overrides the system default. + // It is a colon separated list of directories. + // See https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html. + certDirEnv = "SSL_CERT_DIR" +) + +func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { + return nil, nil +} + +func loadSystemRoots() (*CertPool, error) { + roots := NewCertPool() + + files := certFiles + if f := os.Getenv(certFileEnv); f != "" { + files = []string{f} + } + + var firstErr error + for _, file := range files { + data, err := os.ReadFile(file) + if err == nil { + roots.AppendCertsFromPEM(data) + break + } + if firstErr == nil && !os.IsNotExist(err) { + firstErr = err + } + } + + dirs := certDirectories + if d := os.Getenv(certDirEnv); d != "" { + // OpenSSL and BoringSSL both use ":" as the SSL_CERT_DIR separator. + // See: + // * https://golang.org/issue/35325 + // * https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html + dirs = strings.Split(d, ":") + } + + for _, directory := range dirs { + fis, err := readUniqueDirectoryEntries(directory) + if err != nil { + if firstErr == nil && !os.IsNotExist(err) { + firstErr = err + } + continue + } + for _, fi := range fis { + data, err := os.ReadFile(directory + "/" + fi.Name()) + if err == nil { + roots.AppendCertsFromPEM(data) + } + } + } + + if roots.len() > 0 || firstErr == nil { + return roots, nil + } + + return nil, firstErr +} + +// readUniqueDirectoryEntries is like os.ReadDir but omits +// symlinks that point within the directory. +func readUniqueDirectoryEntries(dir string) ([]fs.DirEntry, error) { + files, err := os.ReadDir(dir) + if err != nil { + return nil, err + } + uniq := files[:0] + for _, f := range files { + if !isSameDirSymlink(f, dir) { + uniq = append(uniq, f) + } + } + return uniq, nil +} + +// isSameDirSymlink reports whether fi in dir is a symlink with a +// target not containing a slash. +func isSameDirSymlink(f fs.DirEntry, dir string) bool { + if f.Type()&fs.ModeSymlink == 0 { + return false + } + target, err := os.Readlink(filepath.Join(dir, f.Name())) + return err == nil && !strings.Contains(target, "/") +} diff --git a/src/crypto/x509/root_unix_test.go b/src/crypto/x509/root_unix_test.go new file mode 100644 index 0000000..7118f12 --- /dev/null +++ b/src/crypto/x509/root_unix_test.go @@ -0,0 +1,229 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris +// +build dragonfly freebsd linux netbsd openbsd solaris + +package x509 + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "reflect" + "strings" + "testing" +) + +const ( + testDir = "testdata" + testDirCN = "test-dir" + testFile = "test-file.crt" + testFileCN = "test-file" + testMissing = "missing" +) + +func TestEnvVars(t *testing.T) { + testCases := []struct { + name string + fileEnv string + dirEnv string + files []string + dirs []string + cns []string + }{ + { + // Environment variables override the default locations preventing fall through. + name: "override-defaults", + fileEnv: testMissing, + dirEnv: testMissing, + files: []string{testFile}, + dirs: []string{testDir}, + cns: nil, + }, + { + // File environment overrides default file locations. + name: "file", + fileEnv: testFile, + dirEnv: "", + files: nil, + dirs: nil, + cns: []string{testFileCN}, + }, + { + // Directory environment overrides default directory locations. + name: "dir", + fileEnv: "", + dirEnv: testDir, + files: nil, + dirs: nil, + cns: []string{testDirCN}, + }, + { + // File & directory environment overrides both default locations. + name: "file+dir", + fileEnv: testFile, + dirEnv: testDir, + files: nil, + dirs: nil, + cns: []string{testFileCN, testDirCN}, + }, + { + // Environment variable empty / unset uses default locations. + name: "empty-fall-through", + fileEnv: "", + dirEnv: "", + files: []string{testFile}, + dirs: []string{testDir}, + cns: []string{testFileCN, testDirCN}, + }, + } + + // Save old settings so we can restore before the test ends. + origCertFiles, origCertDirectories := certFiles, certDirectories + origFile, origDir := os.Getenv(certFileEnv), os.Getenv(certDirEnv) + defer func() { + certFiles = origCertFiles + certDirectories = origCertDirectories + os.Setenv(certFileEnv, origFile) + os.Setenv(certDirEnv, origDir) + }() + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if err := os.Setenv(certFileEnv, tc.fileEnv); err != nil { + t.Fatalf("setenv %q failed: %v", certFileEnv, err) + } + if err := os.Setenv(certDirEnv, tc.dirEnv); err != nil { + t.Fatalf("setenv %q failed: %v", certDirEnv, err) + } + + certFiles, certDirectories = tc.files, tc.dirs + + r, err := loadSystemRoots() + if err != nil { + t.Fatal("unexpected failure:", err) + } + + if r == nil { + t.Fatal("nil roots") + } + + // Verify that the returned certs match, otherwise report where the mismatch is. + for i, cn := range tc.cns { + if i >= r.len() { + t.Errorf("missing cert %v @ %v", cn, i) + } else if r.mustCert(t, i).Subject.CommonName != cn { + fmt.Printf("%#v\n", r.mustCert(t, 0).Subject) + t.Errorf("unexpected cert common name %q, want %q", r.mustCert(t, i).Subject.CommonName, cn) + } + } + if r.len() > len(tc.cns) { + t.Errorf("got %v certs, which is more than %v wanted", r.len(), len(tc.cns)) + } + }) + } +} + +// Ensure that "SSL_CERT_DIR" when used as the environment +// variable delimited by colons, allows loadSystemRoots to +// load all the roots from the respective directories. +// See https://golang.org/issue/35325. +func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) { + origFile, origDir := os.Getenv(certFileEnv), os.Getenv(certDirEnv) + origCertFiles := certFiles[:] + + // To prevent any other certs from being loaded in + // through "SSL_CERT_FILE" or from known "certFiles", + // clear them all, and they'll be reverting on defer. + certFiles = certFiles[:0] + os.Setenv(certFileEnv, "") + + defer func() { + certFiles = origCertFiles[:] + os.Setenv(certDirEnv, origDir) + os.Setenv(certFileEnv, origFile) + }() + + tmpDir := t.TempDir() + + rootPEMs := []string{ + geoTrustRoot, + googleLeaf, + startComRoot, + } + + var certDirs []string + for i, certPEM := range rootPEMs { + certDir := filepath.Join(tmpDir, fmt.Sprintf("cert-%d", i)) + if err := os.MkdirAll(certDir, 0755); err != nil { + t.Fatalf("Failed to create certificate dir: %v", err) + } + certOutFile := filepath.Join(certDir, "cert.crt") + if err := os.WriteFile(certOutFile, []byte(certPEM), 0655); err != nil { + t.Fatalf("Failed to write certificate to file: %v", err) + } + certDirs = append(certDirs, certDir) + } + + // Sanity check: the number of certDirs should be equal to the number of roots. + if g, w := len(certDirs), len(rootPEMs); g != w { + t.Fatalf("Failed sanity check: len(certsDir)=%d is not equal to len(rootsPEMS)=%d", g, w) + } + + // Now finally concatenate them with a colon. + colonConcatCertDirs := strings.Join(certDirs, ":") + os.Setenv(certDirEnv, colonConcatCertDirs) + gotPool, err := loadSystemRoots() + if err != nil { + t.Fatalf("Failed to load system roots: %v", err) + } + subjects := gotPool.Subjects() + // We expect exactly len(rootPEMs) subjects back. + if g, w := len(subjects), len(rootPEMs); g != w { + t.Fatalf("Invalid number of subjects: got %d want %d", g, w) + } + + wantPool := NewCertPool() + for _, certPEM := range rootPEMs { + wantPool.AppendCertsFromPEM([]byte(certPEM)) + } + strCertPool := func(p *CertPool) string { + return string(bytes.Join(p.Subjects(), []byte("\n"))) + } + + if !certPoolEqual(gotPool, wantPool) { + g, w := strCertPool(gotPool), strCertPool(wantPool) + t.Fatalf("Mismatched certPools\nGot:\n%s\n\nWant:\n%s", g, w) + } +} + +func TestReadUniqueDirectoryEntries(t *testing.T) { + tmp := t.TempDir() + temp := func(base string) string { return filepath.Join(tmp, base) } + if f, err := os.Create(temp("file")); err != nil { + t.Fatal(err) + } else { + f.Close() + } + if err := os.Symlink("target-in", temp("link-in")); err != nil { + t.Fatal(err) + } + if err := os.Symlink("../target-out", temp("link-out")); err != nil { + t.Fatal(err) + } + got, err := readUniqueDirectoryEntries(tmp) + if err != nil { + t.Fatal(err) + } + gotNames := []string{} + for _, fi := range got { + gotNames = append(gotNames, fi.Name()) + } + wantNames := []string{"file", "link-out"} + if !reflect.DeepEqual(gotNames, wantNames) { + t.Errorf("got %q; want %q", gotNames, wantNames) + } +} diff --git a/src/crypto/x509/root_windows.go b/src/crypto/x509/root_windows.go new file mode 100644 index 0000000..1e9be80 --- /dev/null +++ b/src/crypto/x509/root_windows.go @@ -0,0 +1,322 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "errors" + "syscall" + "unsafe" +) + +// Creates a new *syscall.CertContext representing the leaf certificate in an in-memory +// certificate store containing itself and all of the intermediate certificates specified +// in the opts.Intermediates CertPool. +// +// A pointer to the in-memory store is available in the returned CertContext's Store field. +// The store is automatically freed when the CertContext is freed using +// syscall.CertFreeCertificateContext. +func createStoreContext(leaf *Certificate, opts *VerifyOptions) (*syscall.CertContext, error) { + var storeCtx *syscall.CertContext + + leafCtx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &leaf.Raw[0], uint32(len(leaf.Raw))) + if err != nil { + return nil, err + } + defer syscall.CertFreeCertificateContext(leafCtx) + + handle, err := syscall.CertOpenStore(syscall.CERT_STORE_PROV_MEMORY, 0, 0, syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, 0) + if err != nil { + return nil, err + } + defer syscall.CertCloseStore(handle, 0) + + err = syscall.CertAddCertificateContextToStore(handle, leafCtx, syscall.CERT_STORE_ADD_ALWAYS, &storeCtx) + if err != nil { + return nil, err + } + + if opts.Intermediates != nil { + for i := 0; i < opts.Intermediates.len(); i++ { + intermediate, err := opts.Intermediates.cert(i) + if err != nil { + return nil, err + } + ctx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &intermediate.Raw[0], uint32(len(intermediate.Raw))) + if err != nil { + return nil, err + } + + err = syscall.CertAddCertificateContextToStore(handle, ctx, syscall.CERT_STORE_ADD_ALWAYS, nil) + syscall.CertFreeCertificateContext(ctx) + if err != nil { + return nil, err + } + } + } + + return storeCtx, nil +} + +// extractSimpleChain extracts the final certificate chain from a CertSimpleChain. +func extractSimpleChain(simpleChain **syscall.CertSimpleChain, count int) (chain []*Certificate, err error) { + if simpleChain == nil || count == 0 { + return nil, errors.New("x509: invalid simple chain") + } + + simpleChains := (*[1 << 20]*syscall.CertSimpleChain)(unsafe.Pointer(simpleChain))[:count:count] + lastChain := simpleChains[count-1] + elements := (*[1 << 20]*syscall.CertChainElement)(unsafe.Pointer(lastChain.Elements))[:lastChain.NumElements:lastChain.NumElements] + for i := 0; i < int(lastChain.NumElements); i++ { + // Copy the buf, since ParseCertificate does not create its own copy. + cert := elements[i].CertContext + encodedCert := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:cert.Length:cert.Length] + buf := make([]byte, cert.Length) + copy(buf, encodedCert) + parsedCert, err := ParseCertificate(buf) + if err != nil { + return nil, err + } + chain = append(chain, parsedCert) + } + + return chain, nil +} + +// checkChainTrustStatus checks the trust status of the certificate chain, translating +// any errors it finds into Go errors in the process. +func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) error { + if chainCtx.TrustStatus.ErrorStatus != syscall.CERT_TRUST_NO_ERROR { + status := chainCtx.TrustStatus.ErrorStatus + switch status { + case syscall.CERT_TRUST_IS_NOT_TIME_VALID: + return CertificateInvalidError{c, Expired, ""} + case syscall.CERT_TRUST_IS_NOT_VALID_FOR_USAGE: + return CertificateInvalidError{c, IncompatibleUsage, ""} + // TODO(filippo): surface more error statuses. + default: + return UnknownAuthorityError{c, nil, nil} + } + } + return nil +} + +// checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for +// use as a certificate chain for a SSL/TLS server. +func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error { + servernamep, err := syscall.UTF16PtrFromString(opts.DNSName) + if err != nil { + return err + } + sslPara := &syscall.SSLExtraCertChainPolicyPara{ + AuthType: syscall.AUTHTYPE_SERVER, + ServerName: servernamep, + } + sslPara.Size = uint32(unsafe.Sizeof(*sslPara)) + + para := &syscall.CertChainPolicyPara{ + ExtraPolicyPara: (syscall.Pointer)(unsafe.Pointer(sslPara)), + } + para.Size = uint32(unsafe.Sizeof(*para)) + + status := syscall.CertChainPolicyStatus{} + err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status) + if err != nil { + return err + } + + // TODO(mkrautz): use the lChainIndex and lElementIndex fields + // of the CertChainPolicyStatus to provide proper context, instead + // using c. + if status.Error != 0 { + switch status.Error { + case syscall.CERT_E_EXPIRED: + return CertificateInvalidError{c, Expired, ""} + case syscall.CERT_E_CN_NO_MATCH: + return HostnameError{c, opts.DNSName} + case syscall.CERT_E_UNTRUSTEDROOT: + return UnknownAuthorityError{c, nil, nil} + default: + return UnknownAuthorityError{c, nil, nil} + } + } + + return nil +} + +// windowsExtKeyUsageOIDs are the C NUL-terminated string representations of the +// OIDs for use with the Windows API. +var windowsExtKeyUsageOIDs = make(map[ExtKeyUsage][]byte, len(extKeyUsageOIDs)) + +func init() { + for _, eku := range extKeyUsageOIDs { + windowsExtKeyUsageOIDs[eku.extKeyUsage] = []byte(eku.oid.String() + "\x00") + } +} + +func verifyChain(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) (chain []*Certificate, err error) { + err = checkChainTrustStatus(c, chainCtx) + if err != nil { + return nil, err + } + + if opts != nil && len(opts.DNSName) > 0 { + err = checkChainSSLServerPolicy(c, chainCtx, opts) + if err != nil { + return nil, err + } + } + + chain, err = extractSimpleChain(chainCtx.Chains, int(chainCtx.ChainCount)) + if err != nil { + return nil, err + } + if len(chain) == 0 { + return nil, errors.New("x509: internal error: system verifier returned an empty chain") + } + + // Mitigate CVE-2020-0601, where the Windows system verifier might be + // tricked into using custom curve parameters for a trusted root, by + // double-checking all ECDSA signatures. If the system was tricked into + // using spoofed parameters, the signature will be invalid for the correct + // ones we parsed. (We don't support custom curves ourselves.) + for i, parent := range chain[1:] { + if parent.PublicKeyAlgorithm != ECDSA { + continue + } + if err := parent.CheckSignature(chain[i].SignatureAlgorithm, + chain[i].RawTBSCertificate, chain[i].Signature); err != nil { + return nil, err + } + } + return chain, nil +} + +// systemVerify is like Verify, except that it uses CryptoAPI calls +// to build certificate chains and verify them. +func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { + storeCtx, err := createStoreContext(c, opts) + if err != nil { + return nil, err + } + defer syscall.CertFreeCertificateContext(storeCtx) + + para := new(syscall.CertChainPara) + para.Size = uint32(unsafe.Sizeof(*para)) + + keyUsages := opts.KeyUsages + if len(keyUsages) == 0 { + keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} + } + oids := make([]*byte, 0, len(keyUsages)) + for _, eku := range keyUsages { + if eku == ExtKeyUsageAny { + oids = nil + break + } + if oid, ok := windowsExtKeyUsageOIDs[eku]; ok { + oids = append(oids, &oid[0]) + } + // Like the standard verifier, accept SGC EKUs as equivalent to ServerAuth. + if eku == ExtKeyUsageServerAuth { + oids = append(oids, &syscall.OID_SERVER_GATED_CRYPTO[0]) + oids = append(oids, &syscall.OID_SGC_NETSCAPE[0]) + } + } + if oids != nil { + para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_OR + para.RequestedUsage.Usage.Length = uint32(len(oids)) + para.RequestedUsage.Usage.UsageIdentifiers = &oids[0] + } else { + para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_AND + para.RequestedUsage.Usage.Length = 0 + para.RequestedUsage.Usage.UsageIdentifiers = nil + } + + var verifyTime *syscall.Filetime + if opts != nil && !opts.CurrentTime.IsZero() { + ft := syscall.NsecToFiletime(opts.CurrentTime.UnixNano()) + verifyTime = &ft + } + + // The default is to return only the highest quality chain, + // setting this flag will add additional lower quality contexts. + // These are returned in the LowerQualityChains field. + const CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS = 0x00000080 + + // CertGetCertificateChain will traverse Windows's root stores in an attempt to build a verified certificate chain + var topCtx *syscall.CertChainContext + err = syscall.CertGetCertificateChain(syscall.Handle(0), storeCtx, verifyTime, storeCtx.Store, para, CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS, 0, &topCtx) + if err != nil { + return nil, err + } + defer syscall.CertFreeCertificateChain(topCtx) + + chain, topErr := verifyChain(c, topCtx, opts) + if topErr == nil { + chains = append(chains, chain) + } + + if lqCtxCount := topCtx.LowerQualityChainCount; lqCtxCount > 0 { + lqCtxs := (*[1 << 20]*syscall.CertChainContext)(unsafe.Pointer(topCtx.LowerQualityChains))[:lqCtxCount:lqCtxCount] + + for _, ctx := range lqCtxs { + chain, err := verifyChain(c, ctx, opts) + if err == nil { + chains = append(chains, chain) + } + } + } + + if len(chains) == 0 { + // Return the error from the highest quality context. + return nil, topErr + } + + return chains, nil +} + +func loadSystemRoots() (*CertPool, error) { + // TODO: restore this functionality on Windows. We tried to do + // it in Go 1.8 but had to revert it. See Issue 18609. + // Returning (nil, nil) was the old behavior, prior to CL 30578. + // The if statement here avoids vet complaining about + // unreachable code below. + if true { + return nil, nil + } + + const CRYPT_E_NOT_FOUND = 0x80092004 + + store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT")) + if err != nil { + return nil, err + } + defer syscall.CertCloseStore(store, 0) + + roots := NewCertPool() + var cert *syscall.CertContext + for { + cert, err = syscall.CertEnumCertificatesInStore(store, cert) + if err != nil { + if errno, ok := err.(syscall.Errno); ok { + if errno == CRYPT_E_NOT_FOUND { + break + } + } + return nil, err + } + if cert == nil { + break + } + // Copy the buf, since ParseCertificate does not create its own copy. + buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:cert.Length:cert.Length] + buf2 := make([]byte, cert.Length) + copy(buf2, buf) + if c, err := ParseCertificate(buf2); err == nil { + roots.AddCert(c) + } + } + return roots, nil +} diff --git a/src/crypto/x509/sec1.go b/src/crypto/x509/sec1.go new file mode 100644 index 0000000..52c108f --- /dev/null +++ b/src/crypto/x509/sec1.go @@ -0,0 +1,120 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "encoding/asn1" + "errors" + "fmt" + "math/big" +) + +const ecPrivKeyVersion = 1 + +// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure. +// References: +// RFC 5915 +// SEC1 - http://www.secg.org/sec1-v2.pdf +// Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in +// most cases it is not. +type ecPrivateKey struct { + Version int + PrivateKey []byte + NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` + PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` +} + +// ParseECPrivateKey parses an EC private key in SEC 1, ASN.1 DER form. +// +// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY". +func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error) { + return parseECPrivateKey(nil, der) +} + +// MarshalECPrivateKey converts an EC private key to SEC 1, ASN.1 DER form. +// +// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY". +// For a more flexible key format which is not EC specific, use +// MarshalPKCS8PrivateKey. +func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) { + oid, ok := oidFromNamedCurve(key.Curve) + if !ok { + return nil, errors.New("x509: unknown elliptic curve") + } + + return marshalECPrivateKeyWithOID(key, oid) +} + +// marshalECPrivateKey marshals an EC private key into ASN.1, DER format and +// sets the curve ID to the given OID, or omits it if OID is nil. +func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) { + privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8) + return asn1.Marshal(ecPrivateKey{ + Version: 1, + PrivateKey: key.D.FillBytes(privateKey), + NamedCurveOID: oid, + PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}, + }) +} + +// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure. +// The OID for the named curve may be provided from another source (such as +// the PKCS8 container) - if it is provided then use this instead of the OID +// that may exist in the EC private key structure. +func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) { + var privKey ecPrivateKey + if _, err := asn1.Unmarshal(der, &privKey); err != nil { + if _, err := asn1.Unmarshal(der, &pkcs8{}); err == nil { + return nil, errors.New("x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)") + } + if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil { + return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)") + } + return nil, errors.New("x509: failed to parse EC private key: " + err.Error()) + } + if privKey.Version != ecPrivKeyVersion { + return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version) + } + + var curve elliptic.Curve + if namedCurveOID != nil { + curve = namedCurveFromOID(*namedCurveOID) + } else { + curve = namedCurveFromOID(privKey.NamedCurveOID) + } + if curve == nil { + return nil, errors.New("x509: unknown elliptic curve") + } + + k := new(big.Int).SetBytes(privKey.PrivateKey) + curveOrder := curve.Params().N + if k.Cmp(curveOrder) >= 0 { + return nil, errors.New("x509: invalid elliptic curve private key value") + } + priv := new(ecdsa.PrivateKey) + priv.Curve = curve + priv.D = k + + privateKey := make([]byte, (curveOrder.BitLen()+7)/8) + + // Some private keys have leading zero padding. This is invalid + // according to [SEC1], but this code will ignore it. + for len(privKey.PrivateKey) > len(privateKey) { + if privKey.PrivateKey[0] != 0 { + return nil, errors.New("x509: invalid private key length") + } + privKey.PrivateKey = privKey.PrivateKey[1:] + } + + // Some private keys remove all leading zeros, this is also invalid + // according to [SEC1] but since OpenSSL used to do this, we ignore + // this too. + copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey) + priv.X, priv.Y = curve.ScalarBaseMult(privateKey) + + return priv, nil +} diff --git a/src/crypto/x509/sec1_test.go b/src/crypto/x509/sec1_test.go new file mode 100644 index 0000000..9ac2518 --- /dev/null +++ b/src/crypto/x509/sec1_test.go @@ -0,0 +1,66 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "encoding/hex" + "strings" + "testing" +) + +var ecKeyTests = []struct { + derHex string + shouldReserialize bool +}{ + // Generated using: + // openssl ecparam -genkey -name secp384r1 -outform PEM + {"3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50", true}, + // This key was generated by GnuTLS and has illegal zero-padding of the + // private key. See https://golang.org/issues/13699. + {"3078020101042100f9f43a04b9bdc3ab01f53be6df80e7a7bc3eaf7b87fc24e630a4a0aa97633645a00a06082a8648ce3d030107a1440342000441a51bc318461b4c39a45048a16d4fc2a935b1ea7fe86e8c1fa219d6f2438f7c7fd62957d3442efb94b6a23eb0ea66dda663dc42f379cda6630b21b7888a5d3d", false}, + // This was generated using an old version of OpenSSL and is missing a + // leading zero byte in the private key that should be present. + {"3081db0201010441607b4f985774ac21e633999794542e09312073480baa69550914d6d43d8414441e61b36650567901da714f94dffb3ce0e2575c31928a0997d51df5c440e983ca17a00706052b81040023a181890381860004001661557afedd7ac8d6b70e038e576558c626eb62edda36d29c3a1310277c11f67a8c6f949e5430a37dcfb95d902c1b5b5379c389873b9dd17be3bdb088a4774a7401072f830fb9a08d93bfa50a03dd3292ea07928724ddb915d831917a338f6b0aecfbc3cf5352c4a1295d356890c41c34116d29eeb93779aab9d9d78e2613437740f6", false}, +} + +func TestParseECPrivateKey(t *testing.T) { + for i, test := range ecKeyTests { + derBytes, _ := hex.DecodeString(test.derHex) + key, err := ParseECPrivateKey(derBytes) + if err != nil { + t.Fatalf("#%d: failed to decode EC private key: %s", i, err) + } + serialized, err := MarshalECPrivateKey(key) + if err != nil { + t.Fatalf("#%d: failed to encode EC private key: %s", i, err) + } + matches := bytes.Equal(serialized, derBytes) + if matches != test.shouldReserialize { + t.Fatalf("#%d: when serializing key: matches=%t, should match=%t: original %x, reserialized %x", i, matches, test.shouldReserialize, serialized, derBytes) + } + } +} + +const hexECTestPKCS1Key = "3082025c02010002818100b1a1e0945b9289c4d3f1329f8a982c4a2dcd59bfd372fb8085a9c517554607ebd2f7990eef216ac9f4605f71a03b04f42a5255b158cf8e0844191f5119348baa44c35056e20609bcf9510f30ead4b481c81d7865fb27b8e0090e112b717f3ee08cdfc4012da1f1f7cf2a1bc34c73a54a12b06372d09714742dd7895eadde4aa5020301000102818062b7fa1db93e993e40237de4d89b7591cc1ea1d04fed4904c643f17ae4334557b4295270d0491c161cb02a9af557978b32b20b59c267a721c4e6c956c2d147046e9ae5f2da36db0106d70021fa9343455f8f973a4b355a26fd19e6b39dee0405ea2b32deddf0f4817759ef705d02b34faab9ca93c6766e9f722290f119f34449024100d9c29a4a013a90e35fd1be14a3f747c589fac613a695282d61812a711906b8a0876c6181f0333ca1066596f57bff47e7cfcabf19c0fc69d9cd76df743038b3cb024100d0d3546fecf879b5551f2bd2c05e6385f2718a08a6face3d2aecc9d7e03645a480a46c81662c12ad6bd6901e3bd4f38029462de7290859567cdf371c79088d4f024100c254150657e460ea58573fcf01a82a4791e3d6223135c8bdfed69afe84fbe7857274f8eb5165180507455f9b4105c6b08b51fe8a481bb986a202245576b713530240045700003b7a867d0041df9547ae2e7f50248febd21c9040b12dae9c2feab0d3d4609668b208e4727a3541557f84d372ac68eaf74ce1018a4c9a0ef92682c8fd02405769731480bb3a4570abf422527c5f34bf732fa6c1e08cc322753c511ce055fac20fc770025663ad3165324314df907f1f1942f0448a7e9cdbf87ecd98b92156" +const hexECTestPKCS8Key = "30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031" + +var ecMismatchKeyTests = []struct { + hexKey string + errorContains string +}{ + {hexKey: hexECTestPKCS8Key, errorContains: "use ParsePKCS8PrivateKey instead"}, + {hexKey: hexECTestPKCS1Key, errorContains: "use ParsePKCS1PrivateKey instead"}, +} + +func TestECMismatchKeyFormat(t *testing.T) { + for i, test := range ecMismatchKeyTests { + derBytes, _ := hex.DecodeString(test.hexKey) + _, err := ParseECPrivateKey(derBytes) + if !strings.Contains(err.Error(), test.errorContains) { + t.Errorf("#%d: expected error containing %q, got %s", i, test.errorContains, err) + } + } +} diff --git a/src/crypto/x509/test-file.crt b/src/crypto/x509/test-file.crt new file mode 100644 index 0000000..caa83b9 --- /dev/null +++ b/src/crypto/x509/test-file.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFbTCCA1WgAwIBAgIJAN338vEmMtLsMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNV +BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz +dHMxEjAQBgNVBAMMCXRlc3QtZmlsZTAeFw0xNzAyMDEyMzUyMDhaFw0yNzAxMzAy +MzUyMDhaME0xCzAJBgNVBAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYD +VQQKDAxHb2xhbmcgVGVzdHMxEjAQBgNVBAMMCXRlc3QtZmlsZTCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBAPMGiLjdiffQo3Xc8oUe7wsDhSaAJFOhO6Qs +i0xYrYl7jmCuz9rGD2fdgk5cLqGazKuQ6fIFzHXFU2BKs4CWXt9KO0KFEhfvZeuW +jG5d7C1ZUiuKOrPqjKVu8SZtFPc7y7Ke7msXzY+Z2LLyiJJ93LCMq4+cTSGNXVlI +KqUxhxeoD5/QkUPyQy/ilu3GMYfx/YORhDP6Edcuskfj8wRh1UxBejP8YPMvI6St +cE2GkxoEGqDWnQ/61F18te6WI3MD29tnKXOkXVhnSC+yvRLljotW2/tAhHKBG4tj +iQWT5Ri4Wrw2tXxPKRLsVWc7e1/hdxhnuvYpXkWNhKsm002jzkFXlzfEwPd8nZdw +5aT6gPUBN2AAzdoqZI7E200i0orEF7WaSoMfjU1tbHvExp3vyAPOfJ5PS2MQ6W03 +Zsy5dTVH+OBH++rkRzQCFcnIv/OIhya5XZ9KX9nFPgBEP7Xq2A+IjH7B6VN/S/bv +8lhp2V+SQvlew9GttKC4hKuPsl5o7+CMbcqcNUdxm9gGkN8epGEKCuix97bpNlxN +fHZxHE5+8GMzPXMkCD56y5TNKR6ut7JGHMPtGl5lPCLqzG/HzYyFgxsDfDUu2B0A +GKj0lGpnLfGqwhs2/s3jpY7+pcvVQxEpvVTId5byDxu1ujP4HjO/VTQ2P72rE8Ft +C6J2Av0tAgMBAAGjUDBOMB0GA1UdDgQWBBTLT/RbyfBB/Pa07oBnaM+QSJPO9TAf +BgNVHSMEGDAWgBTLT/RbyfBB/Pa07oBnaM+QSJPO9TAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQB3sCntCcQwhMgRPPyvOCMyTcQ/Iv+cpfxz2Ck14nlx +AkEAH2CH0ov5GWTt07/ur3aa5x+SAKi0J3wTD1cdiw4U/6Uin6jWGKKxvoo4IaeK +SbM8w/6eKx6UbmHx7PA/eRABY9tTlpdPCVgw7/o3WDr03QM+IAtatzvaCPPczake +pbdLwmBZB/v8V+6jUajy6jOgdSH0PyffGnt7MWgDETmNC6p/Xigp5eh+C8Fb4NGT +xgHES5PBC+sruWp4u22bJGDKTvYNdZHsnw/CaKQWNsQqwisxa3/8N5v+PCff/pxl +r05pE3PdHn9JrCl4iWdVlgtiI9BoPtQyDfa/OEFaScE8KYR8LxaAgdgp3zYncWls +BpwQ6Y/A2wIkhlD9eEp5Ib2hz7isXOs9UwjdriKqrBXqcIAE5M+YIk3+KAQKxAtd +4YsK3CSJ010uphr12YKqlScj4vuKFjuOtd5RyyMIxUG3lrrhAu2AzCeKCLdVgA8+ +75FrYMApUdvcjp4uzbBoED4XRQlx9kdFHVbYgmE/+yddBYJM8u4YlgAL0hW2/D8p +z9JWIfxVmjJnBnXaKGBuiUyZ864A3PJndP6EMMo7TzS2CDnfCYuJjvI0KvDjFNmc +rQA04+qfMSEz3nmKhbbZu4eYLzlADhfH8tT4GMtXf71WLA5AUHGf2Y4+HIHTsmHG +vQ== +-----END CERTIFICATE----- diff --git a/src/crypto/x509/testdata/test-dir.crt b/src/crypto/x509/testdata/test-dir.crt new file mode 100644 index 0000000..b7fc9c5 --- /dev/null +++ b/src/crypto/x509/testdata/test-dir.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIJAL8a/lsnspOqMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV +BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz +dHMxETAPBgNVBAMMCHRlc3QtZGlyMB4XDTE3MDIwMTIzNTAyN1oXDTI3MDEzMDIz +NTAyN1owTDELMAkGA1UEBhMCVUsxEzARBgNVBAgMClRlc3QtU3RhdGUxFTATBgNV +BAoMDEdvbGFuZyBUZXN0czERMA8GA1UEAwwIdGVzdC1kaXIwggIiMA0GCSqGSIb3 +DQEBAQUAA4ICDwAwggIKAoICAQDzBoi43Yn30KN13PKFHu8LA4UmgCRToTukLItM +WK2Je45grs/axg9n3YJOXC6hmsyrkOnyBcx1xVNgSrOAll7fSjtChRIX72Xrloxu +XewtWVIrijqz6oylbvEmbRT3O8uynu5rF82Pmdiy8oiSfdywjKuPnE0hjV1ZSCql +MYcXqA+f0JFD8kMv4pbtxjGH8f2DkYQz+hHXLrJH4/MEYdVMQXoz/GDzLyOkrXBN +hpMaBBqg1p0P+tRdfLXuliNzA9vbZylzpF1YZ0gvsr0S5Y6LVtv7QIRygRuLY4kF +k+UYuFq8NrV8TykS7FVnO3tf4XcYZ7r2KV5FjYSrJtNNo85BV5c3xMD3fJ2XcOWk ++oD1ATdgAM3aKmSOxNtNItKKxBe1mkqDH41NbWx7xMad78gDznyeT0tjEOltN2bM +uXU1R/jgR/vq5Ec0AhXJyL/ziIcmuV2fSl/ZxT4ARD+16tgPiIx+welTf0v27/JY +adlfkkL5XsPRrbSguISrj7JeaO/gjG3KnDVHcZvYBpDfHqRhCgrosfe26TZcTXx2 +cRxOfvBjMz1zJAg+esuUzSkerreyRhzD7RpeZTwi6sxvx82MhYMbA3w1LtgdABio +9JRqZy3xqsIbNv7N46WO/qXL1UMRKb1UyHeW8g8btboz+B4zv1U0Nj+9qxPBbQui +dgL9LQIDAQABo1AwTjAdBgNVHQ4EFgQUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwHwYD +VR0jBBgwFoAUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwDAYDVR0TBAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAgEAvEVnUYsIOt87rggmLPqEueynkuQ+562M8EDHSQl82zbe +xDCxeg3DvPgKb+RvaUdt1362z/szK10SoeMgx6+EQLoV9LiVqXwNqeYfixrhrdw3 +ppAhYYhymdkbUQCEMHypmXP1vPhAz4o8Bs+eES1M+zO6ErBiD7SqkmBElT+GixJC +6epC9ZQFs+dw3lPlbiZSsGE85sqc3VAs0/JgpL/pb1/Eg4s0FUhZD2C2uWdSyZGc +g0/v3aXJCp4j/9VoNhI1WXz3M45nysZIL5OQgXymLqJElQa1pZ3Wa4i/nidvT4AT +Xlxc/qijM8set/nOqp7hVd5J0uG6qdwLRILUddZ6OpXd7ZNi1EXg+Bpc7ehzGsDt +3UFGzYXDjxYnK2frQfjLS8stOQIqSrGthW6x0fdkVx0y8BByvd5J6+JmZl4UZfzA +m99VxXSt4B9x6BvnY7ktzcFDOjtuLc4B/7yg9fv1eQuStA4cHGGAttsCg1X/Kx8W +PvkkeH0UWDZ9vhH9K36703z89da6MWF+bz92B0+4HoOmlVaXRkvblsNaynJnL0LC +Ayry7QBxuh5cMnDdRwJB3AVJIiJ1GVpb7aGvBOnx+s2lwRv9HWtghb+cbwwktx1M +JHyBf3GZNSWTpKY7cD8V+NnBv3UuioOVVo+XAU4LF/bYUjdRpxWADJizNtZrtFo= +-----END CERTIFICATE----- diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go new file mode 100644 index 0000000..9ef1146 --- /dev/null +++ b/src/crypto/x509/verify.go @@ -0,0 +1,1108 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/url" + "reflect" + "runtime" + "strings" + "time" + "unicode/utf8" +) + +type InvalidReason int + +const ( + // NotAuthorizedToSign results when a certificate is signed by another + // which isn't marked as a CA certificate. + NotAuthorizedToSign InvalidReason = iota + // Expired results when a certificate has expired, based on the time + // given in the VerifyOptions. + Expired + // CANotAuthorizedForThisName results when an intermediate or root + // certificate has a name constraint which doesn't permit a DNS or + // other name (including IP address) in the leaf certificate. + CANotAuthorizedForThisName + // TooManyIntermediates results when a path length constraint is + // violated. + TooManyIntermediates + // IncompatibleUsage results when the certificate's key usage indicates + // that it may only be used for a different purpose. + IncompatibleUsage + // NameMismatch results when the subject name of a parent certificate + // does not match the issuer name in the child. + NameMismatch + // NameConstraintsWithoutSANs is a legacy error and is no longer returned. + NameConstraintsWithoutSANs + // UnconstrainedName results when a CA certificate contains permitted + // name constraints, but leaf certificate contains a name of an + // unsupported or unconstrained type. + UnconstrainedName + // TooManyConstraints results when the number of comparison operations + // needed to check a certificate exceeds the limit set by + // VerifyOptions.MaxConstraintComparisions. This limit exists to + // prevent pathological certificates can consuming excessive amounts of + // CPU time to verify. + TooManyConstraints + // CANotAuthorizedForExtKeyUsage results when an intermediate or root + // certificate does not permit a requested extended key usage. + CANotAuthorizedForExtKeyUsage +) + +// CertificateInvalidError results when an odd error occurs. Users of this +// library probably want to handle all these errors uniformly. +type CertificateInvalidError struct { + Cert *Certificate + Reason InvalidReason + Detail string +} + +func (e CertificateInvalidError) Error() string { + switch e.Reason { + case NotAuthorizedToSign: + return "x509: certificate is not authorized to sign other certificates" + case Expired: + return "x509: certificate has expired or is not yet valid: " + e.Detail + case CANotAuthorizedForThisName: + return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e.Detail + case CANotAuthorizedForExtKeyUsage: + return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e.Detail + case TooManyIntermediates: + return "x509: too many intermediates for path length constraint" + case IncompatibleUsage: + return "x509: certificate specifies an incompatible key usage" + case NameMismatch: + return "x509: issuer name does not match subject from issuing certificate" + case NameConstraintsWithoutSANs: + return "x509: issuer has name constraints but leaf doesn't have a SAN extension" + case UnconstrainedName: + return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e.Detail + } + return "x509: unknown error" +} + +// HostnameError results when the set of authorized names doesn't match the +// requested name. +type HostnameError struct { + Certificate *Certificate + Host string +} + +func (h HostnameError) Error() string { + c := h.Certificate + + if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) { + return "x509: certificate relies on legacy Common Name field, use SANs instead" + } + + var valid string + if ip := net.ParseIP(h.Host); ip != nil { + // Trying to validate an IP + if len(c.IPAddresses) == 0 { + return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs" + } + for _, san := range c.IPAddresses { + if len(valid) > 0 { + valid += ", " + } + valid += san.String() + } + } else { + valid = strings.Join(c.DNSNames, ", ") + } + + if len(valid) == 0 { + return "x509: certificate is not valid for any names, but wanted to match " + h.Host + } + return "x509: certificate is valid for " + valid + ", not " + h.Host +} + +// UnknownAuthorityError results when the certificate issuer is unknown +type UnknownAuthorityError struct { + Cert *Certificate + // hintErr contains an error that may be helpful in determining why an + // authority wasn't found. + hintErr error + // hintCert contains a possible authority certificate that was rejected + // because of the error in hintErr. + hintCert *Certificate +} + +func (e UnknownAuthorityError) Error() string { + s := "x509: certificate signed by unknown authority" + if e.hintErr != nil { + certName := e.hintCert.Subject.CommonName + if len(certName) == 0 { + if len(e.hintCert.Subject.Organization) > 0 { + certName = e.hintCert.Subject.Organization[0] + } else { + certName = "serial:" + e.hintCert.SerialNumber.String() + } + } + s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName) + } + return s +} + +// SystemRootsError results when we fail to load the system root certificates. +type SystemRootsError struct { + Err error +} + +func (se SystemRootsError) Error() string { + msg := "x509: failed to load system roots and no roots provided" + if se.Err != nil { + return msg + "; " + se.Err.Error() + } + return msg +} + +func (se SystemRootsError) Unwrap() error { return se.Err } + +// errNotParsed is returned when a certificate without ASN.1 contents is +// verified. Platform-specific verification needs the ASN.1 contents. +var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate") + +// VerifyOptions contains parameters for Certificate.Verify. +type VerifyOptions struct { + // DNSName, if set, is checked against the leaf certificate with + // Certificate.VerifyHostname or the platform verifier. + DNSName string + + // Intermediates is an optional pool of certificates that are not trust + // anchors, but can be used to form a chain from the leaf certificate to a + // root certificate. + Intermediates *CertPool + // Roots is the set of trusted root certificates the leaf certificate needs + // to chain up to. If nil, the system roots or the platform verifier are used. + Roots *CertPool + + // CurrentTime is used to check the validity of all certificates in the + // chain. If zero, the current time is used. + CurrentTime time.Time + + // KeyUsages specifies which Extended Key Usage values are acceptable. A + // chain is accepted if it allows any of the listed values. An empty list + // means ExtKeyUsageServerAuth. To accept any key usage, include ExtKeyUsageAny. + KeyUsages []ExtKeyUsage + + // MaxConstraintComparisions is the maximum number of comparisons to + // perform when checking a given certificate's name constraints. If + // zero, a sensible default is used. This limit prevents pathological + // certificates from consuming excessive amounts of CPU time when + // validating. It does not apply to the platform verifier. + MaxConstraintComparisions int +} + +const ( + leafCertificate = iota + intermediateCertificate + rootCertificate +) + +// rfc2821Mailbox represents a “mailbox” (which is an email address to most +// people) by breaking it into the “local” (i.e. before the '@') and “domain” +// parts. +type rfc2821Mailbox struct { + local, domain string +} + +// parseRFC2821Mailbox parses an email address into local and domain parts, +// based on the ABNF for a “Mailbox” from RFC 2821. According to RFC 5280, +// Section 4.2.1.6 that's correct for an rfc822Name from a certificate: “The +// format of an rfc822Name is a "Mailbox" as defined in RFC 2821, Section 4.1.2”. +func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) { + if len(in) == 0 { + return mailbox, false + } + + localPartBytes := make([]byte, 0, len(in)/2) + + if in[0] == '"' { + // Quoted-string = DQUOTE *qcontent DQUOTE + // non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127 + // qcontent = qtext / quoted-pair + // qtext = non-whitespace-control / + // %d33 / %d35-91 / %d93-126 + // quoted-pair = ("\" text) / obs-qp + // text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text + // + // (Names beginning with “obs-” are the obsolete syntax from RFC 2822, + // Section 4. Since it has been 16 years, we no longer accept that.) + in = in[1:] + QuotedString: + for { + if len(in) == 0 { + return mailbox, false + } + c := in[0] + in = in[1:] + + switch { + case c == '"': + break QuotedString + + case c == '\\': + // quoted-pair + if len(in) == 0 { + return mailbox, false + } + if in[0] == 11 || + in[0] == 12 || + (1 <= in[0] && in[0] <= 9) || + (14 <= in[0] && in[0] <= 127) { + localPartBytes = append(localPartBytes, in[0]) + in = in[1:] + } else { + return mailbox, false + } + + case c == 11 || + c == 12 || + // Space (char 32) is not allowed based on the + // BNF, but RFC 3696 gives an example that + // assumes that it is. Several “verified” + // errata continue to argue about this point. + // We choose to accept it. + c == 32 || + c == 33 || + c == 127 || + (1 <= c && c <= 8) || + (14 <= c && c <= 31) || + (35 <= c && c <= 91) || + (93 <= c && c <= 126): + // qtext + localPartBytes = append(localPartBytes, c) + + default: + return mailbox, false + } + } + } else { + // Atom ("." Atom)* + NextChar: + for len(in) > 0 { + // atext from RFC 2822, Section 3.2.4 + c := in[0] + + switch { + case c == '\\': + // Examples given in RFC 3696 suggest that + // escaped characters can appear outside of a + // quoted string. Several “verified” errata + // continue to argue the point. We choose to + // accept it. + in = in[1:] + if len(in) == 0 { + return mailbox, false + } + fallthrough + + case ('0' <= c && c <= '9') || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + c == '!' || c == '#' || c == '$' || c == '%' || + c == '&' || c == '\'' || c == '*' || c == '+' || + c == '-' || c == '/' || c == '=' || c == '?' || + c == '^' || c == '_' || c == '`' || c == '{' || + c == '|' || c == '}' || c == '~' || c == '.': + localPartBytes = append(localPartBytes, in[0]) + in = in[1:] + + default: + break NextChar + } + } + + if len(localPartBytes) == 0 { + return mailbox, false + } + + // From RFC 3696, Section 3: + // “period (".") may also appear, but may not be used to start + // or end the local part, nor may two or more consecutive + // periods appear.” + twoDots := []byte{'.', '.'} + if localPartBytes[0] == '.' || + localPartBytes[len(localPartBytes)-1] == '.' || + bytes.Contains(localPartBytes, twoDots) { + return mailbox, false + } + } + + if len(in) == 0 || in[0] != '@' { + return mailbox, false + } + in = in[1:] + + // The RFC species a format for domains, but that's known to be + // violated in practice so we accept that anything after an '@' is the + // domain part. + if _, ok := domainToReverseLabels(in); !ok { + return mailbox, false + } + + mailbox.local = string(localPartBytes) + mailbox.domain = in + return mailbox, true +} + +// domainToReverseLabels converts a textual domain name like foo.example.com to +// the list of labels in reverse order, e.g. ["com", "example", "foo"]. +func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) { + for len(domain) > 0 { + if i := strings.LastIndexByte(domain, '.'); i == -1 { + reverseLabels = append(reverseLabels, domain) + domain = "" + } else { + reverseLabels = append(reverseLabels, domain[i+1:]) + domain = domain[:i] + } + } + + if len(reverseLabels) > 0 && len(reverseLabels[0]) == 0 { + // An empty label at the end indicates an absolute value. + return nil, false + } + + for _, label := range reverseLabels { + if len(label) == 0 { + // Empty labels are otherwise invalid. + return nil, false + } + + for _, c := range label { + if c < 33 || c > 126 { + // Invalid character. + return nil, false + } + } + } + + return reverseLabels, true +} + +func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) { + // If the constraint contains an @, then it specifies an exact mailbox + // name. + if strings.Contains(constraint, "@") { + constraintMailbox, ok := parseRFC2821Mailbox(constraint) + if !ok { + return false, fmt.Errorf("x509: internal error: cannot parse constraint %q", constraint) + } + return mailbox.local == constraintMailbox.local && strings.EqualFold(mailbox.domain, constraintMailbox.domain), nil + } + + // Otherwise the constraint is like a DNS constraint of the domain part + // of the mailbox. + return matchDomainConstraint(mailbox.domain, constraint) +} + +func matchURIConstraint(uri *url.URL, constraint string) (bool, error) { + // From RFC 5280, Section 4.2.1.10: + // “a uniformResourceIdentifier that does not include an authority + // component with a host name specified as a fully qualified domain + // name (e.g., if the URI either does not include an authority + // component or includes an authority component in which the host name + // is specified as an IP address), then the application MUST reject the + // certificate.” + + host := uri.Host + if len(host) == 0 { + return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", uri.String()) + } + + if strings.Contains(host, ":") && !strings.HasSuffix(host, "]") { + var err error + host, _, err = net.SplitHostPort(uri.Host) + if err != nil { + return false, err + } + } + + if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") || + net.ParseIP(host) != nil { + return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String()) + } + + return matchDomainConstraint(host, constraint) +} + +func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) { + if len(ip) != len(constraint.IP) { + return false, nil + } + + for i := range ip { + if mask := constraint.Mask[i]; ip[i]&mask != constraint.IP[i]&mask { + return false, nil + } + } + + return true, nil +} + +func matchDomainConstraint(domain, constraint string) (bool, error) { + // The meaning of zero length constraints is not specified, but this + // code follows NSS and accepts them as matching everything. + if len(constraint) == 0 { + return true, nil + } + + domainLabels, ok := domainToReverseLabels(domain) + if !ok { + return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain) + } + + // RFC 5280 says that a leading period in a domain name means that at + // least one label must be prepended, but only for URI and email + // constraints, not DNS constraints. The code also supports that + // behaviour for DNS constraints. + + mustHaveSubdomains := false + if constraint[0] == '.' { + mustHaveSubdomains = true + constraint = constraint[1:] + } + + constraintLabels, ok := domainToReverseLabels(constraint) + if !ok { + return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint) + } + + if len(domainLabels) < len(constraintLabels) || + (mustHaveSubdomains && len(domainLabels) == len(constraintLabels)) { + return false, nil + } + + for i, constraintLabel := range constraintLabels { + if !strings.EqualFold(constraintLabel, domainLabels[i]) { + return false, nil + } + } + + return true, nil +} + +// checkNameConstraints checks that c permits a child certificate to claim the +// given name, of type nameType. The argument parsedName contains the parsed +// form of name, suitable for passing to the match function. The total number +// of comparisons is tracked in the given count and should not exceed the given +// limit. +func (c *Certificate) checkNameConstraints(count *int, + maxConstraintComparisons int, + nameType string, + name string, + parsedName interface{}, + match func(parsedName, constraint interface{}) (match bool, err error), + permitted, excluded interface{}) error { + + excludedValue := reflect.ValueOf(excluded) + + *count += excludedValue.Len() + if *count > maxConstraintComparisons { + return CertificateInvalidError{c, TooManyConstraints, ""} + } + + for i := 0; i < excludedValue.Len(); i++ { + constraint := excludedValue.Index(i).Interface() + match, err := match(parsedName, constraint) + if err != nil { + return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()} + } + + if match { + return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", nameType, name, constraint)} + } + } + + permittedValue := reflect.ValueOf(permitted) + + *count += permittedValue.Len() + if *count > maxConstraintComparisons { + return CertificateInvalidError{c, TooManyConstraints, ""} + } + + ok := true + for i := 0; i < permittedValue.Len(); i++ { + constraint := permittedValue.Index(i).Interface() + + var err error + if ok, err = match(parsedName, constraint); err != nil { + return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()} + } + + if ok { + break + } + } + + if !ok { + return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", nameType, name)} + } + + return nil +} + +// isValid performs validity checks on c given that it is a candidate to append +// to the chain in currentChain. +func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error { + if len(c.UnhandledCriticalExtensions) > 0 { + return UnhandledCriticalExtension{} + } + + if len(currentChain) > 0 { + child := currentChain[len(currentChain)-1] + if !bytes.Equal(child.RawIssuer, c.RawSubject) { + return CertificateInvalidError{c, NameMismatch, ""} + } + } + + now := opts.CurrentTime + if now.IsZero() { + now = time.Now() + } + if now.Before(c.NotBefore) { + return CertificateInvalidError{ + Cert: c, + Reason: Expired, + Detail: fmt.Sprintf("current time %s is before %s", now.Format(time.RFC3339), c.NotBefore.Format(time.RFC3339)), + } + } else if now.After(c.NotAfter) { + return CertificateInvalidError{ + Cert: c, + Reason: Expired, + Detail: fmt.Sprintf("current time %s is after %s", now.Format(time.RFC3339), c.NotAfter.Format(time.RFC3339)), + } + } + + maxConstraintComparisons := opts.MaxConstraintComparisions + if maxConstraintComparisons == 0 { + maxConstraintComparisons = 250000 + } + comparisonCount := 0 + + var leaf *Certificate + if certType == intermediateCertificate || certType == rootCertificate { + if len(currentChain) == 0 { + return errors.New("x509: internal error: empty chain when appending CA cert") + } + leaf = currentChain[0] + } + + if (certType == intermediateCertificate || certType == rootCertificate) && + c.hasNameConstraints() && leaf.hasSANExtension() { + err := forEachSAN(leaf.getSANExtension(), func(tag int, data []byte) error { + switch tag { + case nameTypeEmail: + name := string(data) + mailbox, ok := parseRFC2821Mailbox(name) + if !ok { + return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox) + } + + if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox, + func(parsedName, constraint interface{}) (bool, error) { + return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string)) + }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil { + return err + } + + case nameTypeDNS: + name := string(data) + if _, ok := domainToReverseLabels(name); !ok { + return fmt.Errorf("x509: cannot parse dnsName %q", name) + } + + if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name, + func(parsedName, constraint interface{}) (bool, error) { + return matchDomainConstraint(parsedName.(string), constraint.(string)) + }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil { + return err + } + + case nameTypeURI: + name := string(data) + uri, err := url.Parse(name) + if err != nil { + return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name) + } + + if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri, + func(parsedName, constraint interface{}) (bool, error) { + return matchURIConstraint(parsedName.(*url.URL), constraint.(string)) + }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil { + return err + } + + case nameTypeIP: + ip := net.IP(data) + if l := len(ip); l != net.IPv4len && l != net.IPv6len { + return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data) + } + + if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip, + func(parsedName, constraint interface{}) (bool, error) { + return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet)) + }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil { + return err + } + + default: + // Unknown SAN types are ignored. + } + + return nil + }) + + if err != nil { + return err + } + } + + // KeyUsage status flags are ignored. From Engineering Security, Peter + // Gutmann: A European government CA marked its signing certificates as + // being valid for encryption only, but no-one noticed. Another + // European CA marked its signature keys as not being valid for + // signatures. A different CA marked its own trusted root certificate + // as being invalid for certificate signing. Another national CA + // distributed a certificate to be used to encrypt data for the + // country’s tax authority that was marked as only being usable for + // digital signatures but not for encryption. Yet another CA reversed + // the order of the bit flags in the keyUsage due to confusion over + // encoding endianness, essentially setting a random keyUsage in + // certificates that it issued. Another CA created a self-invalidating + // certificate by adding a certificate policy statement stipulating + // that the certificate had to be used strictly as specified in the + // keyUsage, and a keyUsage containing a flag indicating that the RSA + // encryption key could only be used for Diffie-Hellman key agreement. + + if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) { + return CertificateInvalidError{c, NotAuthorizedToSign, ""} + } + + if c.BasicConstraintsValid && c.MaxPathLen >= 0 { + numIntermediates := len(currentChain) - 1 + if numIntermediates > c.MaxPathLen { + return CertificateInvalidError{c, TooManyIntermediates, ""} + } + } + + return nil +} + +// Verify attempts to verify c by building one or more chains from c to a +// certificate in opts.Roots, using certificates in opts.Intermediates if +// needed. If successful, it returns one or more chains where the first +// element of the chain is c and the last element is from opts.Roots. +// +// If opts.Roots is nil, the platform verifier might be used, and +// verification details might differ from what is described below. If system +// roots are unavailable the returned error will be of type SystemRootsError. +// +// Name constraints in the intermediates will be applied to all names claimed +// in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim +// example.com if an intermediate doesn't permit it, even if example.com is not +// the name being validated. Note that DirectoryName constraints are not +// supported. +// +// Name constraint validation follows the rules from RFC 5280, with the +// addition that DNS name constraints may use the leading period format +// defined for emails and URIs. When a constraint has a leading period +// it indicates that at least one additional label must be prepended to +// the constrained name to be considered valid. +// +// Extended Key Usage values are enforced nested down a chain, so an intermediate +// or root that enumerates EKUs prevents a leaf from asserting an EKU not in that +// list. (While this is not specified, it is common practice in order to limit +// the types of certificates a CA can issue.) +// +// WARNING: this function doesn't do any revocation checking. +func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { + // Platform-specific verification needs the ASN.1 contents so + // this makes the behavior consistent across platforms. + if len(c.Raw) == 0 { + return nil, errNotParsed + } + for i := 0; i < opts.Intermediates.len(); i++ { + c, err := opts.Intermediates.cert(i) + if err != nil { + return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", err) + } + if len(c.Raw) == 0 { + return nil, errNotParsed + } + } + + // Use Windows's own verification and chain building. + if opts.Roots == nil && runtime.GOOS == "windows" { + return c.systemVerify(&opts) + } + + if opts.Roots == nil { + opts.Roots = systemRootsPool() + if opts.Roots == nil { + return nil, SystemRootsError{systemRootsErr} + } + } + + err = c.isValid(leafCertificate, nil, &opts) + if err != nil { + return + } + + if len(opts.DNSName) > 0 { + err = c.VerifyHostname(opts.DNSName) + if err != nil { + return + } + } + + var candidateChains [][]*Certificate + if opts.Roots.contains(c) { + candidateChains = append(candidateChains, []*Certificate{c}) + } else { + if candidateChains, err = c.buildChains(nil, []*Certificate{c}, nil, &opts); err != nil { + return nil, err + } + } + + keyUsages := opts.KeyUsages + if len(keyUsages) == 0 { + keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} + } + + // If any key usage is acceptable then we're done. + for _, usage := range keyUsages { + if usage == ExtKeyUsageAny { + return candidateChains, nil + } + } + + for _, candidate := range candidateChains { + if checkChainForKeyUsage(candidate, keyUsages) { + chains = append(chains, candidate) + } + } + + if len(chains) == 0 { + return nil, CertificateInvalidError{c, IncompatibleUsage, ""} + } + + return chains, nil +} + +func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { + n := make([]*Certificate, len(chain)+1) + copy(n, chain) + n[len(chain)] = cert + return n +} + +// maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls +// that an invocation of buildChains will (transitively) make. Most chains are +// less than 15 certificates long, so this leaves space for multiple chains and +// for failed checks due to different intermediates having the same Subject. +const maxChainSignatureChecks = 100 + +func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) { + var ( + hintErr error + hintCert *Certificate + ) + + considerCandidate := func(certType int, candidate *Certificate) { + for _, cert := range currentChain { + if cert.Equal(candidate) { + return + } + } + + if sigChecks == nil { + sigChecks = new(int) + } + *sigChecks++ + if *sigChecks > maxChainSignatureChecks { + err = errors.New("x509: signature check attempts limit reached while verifying certificate chain") + return + } + + if err := c.CheckSignatureFrom(candidate); err != nil { + if hintErr == nil { + hintErr = err + hintCert = candidate + } + return + } + + err = candidate.isValid(certType, currentChain, opts) + if err != nil { + return + } + + switch certType { + case rootCertificate: + chains = append(chains, appendToFreshChain(currentChain, candidate)) + case intermediateCertificate: + if cache == nil { + cache = make(map[*Certificate][][]*Certificate) + } + childChains, ok := cache[candidate] + if !ok { + childChains, err = candidate.buildChains(cache, appendToFreshChain(currentChain, candidate), sigChecks, opts) + cache[candidate] = childChains + } + chains = append(chains, childChains...) + } + } + + for _, root := range opts.Roots.findPotentialParents(c) { + considerCandidate(rootCertificate, root) + } + for _, intermediate := range opts.Intermediates.findPotentialParents(c) { + considerCandidate(intermediateCertificate, intermediate) + } + + if len(chains) > 0 { + err = nil + } + if len(chains) == 0 && err == nil { + err = UnknownAuthorityError{c, hintErr, hintCert} + } + + return +} + +func validHostnamePattern(host string) bool { return validHostname(host, true) } +func validHostnameInput(host string) bool { return validHostname(host, false) } + +// validHostname reports whether host is a valid hostname that can be matched or +// matched against according to RFC 6125 2.2, with some leniency to accommodate +// legacy values. +func validHostname(host string, isPattern bool) bool { + if !isPattern { + host = strings.TrimSuffix(host, ".") + } + if len(host) == 0 { + return false + } + + for i, part := range strings.Split(host, ".") { + if part == "" { + // Empty label. + return false + } + if isPattern && i == 0 && part == "*" { + // Only allow full left-most wildcards, as those are the only ones + // we match, and matching literal '*' characters is probably never + // the expected behavior. + continue + } + for j, c := range part { + if 'a' <= c && c <= 'z' { + continue + } + if '0' <= c && c <= '9' { + continue + } + if 'A' <= c && c <= 'Z' { + continue + } + if c == '-' && j != 0 { + continue + } + if c == '_' { + // Not a valid character in hostnames, but commonly + // found in deployments outside the WebPKI. + continue + } + return false + } + } + + return true +} + +func matchExactly(hostA, hostB string) bool { + if hostA == "" || hostA == "." || hostB == "" || hostB == "." { + return false + } + return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB) +} + +func matchHostnames(pattern, host string) bool { + pattern = toLowerCaseASCII(pattern) + host = toLowerCaseASCII(strings.TrimSuffix(host, ".")) + + if len(pattern) == 0 || len(host) == 0 { + return false + } + + patternParts := strings.Split(pattern, ".") + hostParts := strings.Split(host, ".") + + if len(patternParts) != len(hostParts) { + return false + } + + for i, patternPart := range patternParts { + if i == 0 && patternPart == "*" { + continue + } + if patternPart != hostParts[i] { + return false + } + } + + return true +} + +// toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use +// an explicitly ASCII function to avoid any sharp corners resulting from +// performing Unicode operations on DNS labels. +func toLowerCaseASCII(in string) string { + // If the string is already lower-case then there's nothing to do. + isAlreadyLowerCase := true + for _, c := range in { + if c == utf8.RuneError { + // If we get a UTF-8 error then there might be + // upper-case ASCII bytes in the invalid sequence. + isAlreadyLowerCase = false + break + } + if 'A' <= c && c <= 'Z' { + isAlreadyLowerCase = false + break + } + } + + if isAlreadyLowerCase { + return in + } + + out := []byte(in) + for i, c := range out { + if 'A' <= c && c <= 'Z' { + out[i] += 'a' - 'A' + } + } + return string(out) +} + +// VerifyHostname returns nil if c is a valid certificate for the named host. +// Otherwise it returns an error describing the mismatch. +// +// IP addresses can be optionally enclosed in square brackets and are checked +// against the IPAddresses field. Other names are checked case insensitively +// against the DNSNames field. If the names are valid hostnames, the certificate +// fields can have a wildcard as the left-most label. +// +// Note that the legacy Common Name field is ignored. +func (c *Certificate) VerifyHostname(h string) error { + // IP addresses may be written in [ ]. + candidateIP := h + if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' { + candidateIP = h[1 : len(h)-1] + } + if ip := net.ParseIP(candidateIP); ip != nil { + // We only match IP addresses against IP SANs. + // See RFC 6125, Appendix B.2. + for _, candidate := range c.IPAddresses { + if ip.Equal(candidate) { + return nil + } + } + return HostnameError{c, candidateIP} + } + + candidateName := toLowerCaseASCII(h) // Save allocations inside the loop. + validCandidateName := validHostnameInput(candidateName) + + for _, match := range c.DNSNames { + // Ideally, we'd only match valid hostnames according to RFC 6125 like + // browsers (more or less) do, but in practice Go is used in a wider + // array of contexts and can't even assume DNS resolution. Instead, + // always allow perfect matches, and only apply wildcard and trailing + // dot processing to valid hostnames. + if validCandidateName && validHostnamePattern(match) { + if matchHostnames(match, candidateName) { + return nil + } + } else { + if matchExactly(match, candidateName) { + return nil + } + } + } + + return HostnameError{c, h} +} + +func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { + usages := make([]ExtKeyUsage, len(keyUsages)) + copy(usages, keyUsages) + + if len(chain) == 0 { + return false + } + + usagesRemaining := len(usages) + + // We walk down the list and cross out any usages that aren't supported + // by each certificate. If we cross out all the usages, then the chain + // is unacceptable. + +NextCert: + for i := len(chain) - 1; i >= 0; i-- { + cert := chain[i] + if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 { + // The certificate doesn't have any extended key usage specified. + continue + } + + for _, usage := range cert.ExtKeyUsage { + if usage == ExtKeyUsageAny { + // The certificate is explicitly good for any usage. + continue NextCert + } + } + + const invalidUsage ExtKeyUsage = -1 + + NextRequestedUsage: + for i, requestedUsage := range usages { + if requestedUsage == invalidUsage { + continue + } + + for _, usage := range cert.ExtKeyUsage { + if requestedUsage == usage { + continue NextRequestedUsage + } else if requestedUsage == ExtKeyUsageServerAuth && + (usage == ExtKeyUsageNetscapeServerGatedCrypto || + usage == ExtKeyUsageMicrosoftServerGatedCrypto) { + // In order to support COMODO + // certificate chains, we have to + // accept Netscape or Microsoft SGC + // usages as equal to ServerAuth. + continue NextRequestedUsage + } + } + + usages[i] = invalidUsage + usagesRemaining-- + if usagesRemaining == 0 { + return false + } + } + } + + return true +} diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go new file mode 100644 index 0000000..9954a67 --- /dev/null +++ b/src/crypto/x509/verify_test.go @@ -0,0 +1,1970 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509/pkix" + "encoding/pem" + "errors" + "fmt" + "math/big" + "runtime" + "strings" + "testing" + "time" +) + +type verifyTest struct { + name string + leaf string + intermediates []string + roots []string + currentTime int64 + dnsName string + systemSkip bool + systemLax bool + keyUsages []ExtKeyUsage + + errorCallback func(*testing.T, error) + expectedChains [][]string +} + +var verifyTests = []verifyTest{ + { + name: "Valid", + leaf: googleLeaf, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, + dnsName: "www.google.com", + + expectedChains: [][]string{ + {"Google", "Google Internet Authority", "GeoTrust"}, + }, + }, + { + name: "MixedCase", + leaf: googleLeaf, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, + dnsName: "WwW.GooGLE.coM", + + expectedChains: [][]string{ + {"Google", "Google Internet Authority", "GeoTrust"}, + }, + }, + { + name: "HostnameMismatch", + leaf: googleLeaf, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, + dnsName: "www.example.com", + + errorCallback: expectHostnameError("certificate is valid for"), + }, + { + name: "IPMissing", + leaf: googleLeaf, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, + dnsName: "1.2.3.4", + + errorCallback: expectHostnameError("doesn't contain any IP SANs"), + }, + { + name: "Expired", + leaf: googleLeaf, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1, + dnsName: "www.example.com", + + errorCallback: expectExpired, + }, + { + name: "MissingIntermediate", + leaf: googleLeaf, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, + dnsName: "www.google.com", + + // Skip when using systemVerify, since Windows + // *will* find the missing intermediate cert. + systemSkip: true, + errorCallback: expectAuthorityUnknown, + }, + { + name: "RootInIntermediates", + leaf: googleLeaf, + intermediates: []string{geoTrustRoot, giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, + dnsName: "www.google.com", + + expectedChains: [][]string{ + {"Google", "Google Internet Authority", "GeoTrust"}, + }, + // CAPI doesn't build the chain with the duplicated GeoTrust + // entry so the results don't match. + systemLax: true, + }, + { + name: "dnssec-exp", + leaf: dnssecExpLeaf, + intermediates: []string{startComIntermediate}, + roots: []string{startComRoot}, + currentTime: 1302726541, + + // The StartCom root is not trusted by Windows when the default + // ServerAuth EKU is requested. + systemSkip: true, + + expectedChains: [][]string{ + {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, + }, + }, + { + name: "dnssec-exp/AnyEKU", + leaf: dnssecExpLeaf, + intermediates: []string{startComIntermediate}, + roots: []string{startComRoot}, + currentTime: 1302726541, + keyUsages: []ExtKeyUsage{ExtKeyUsageAny}, + + expectedChains: [][]string{ + {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, + }, + }, + { + name: "dnssec-exp/RootInIntermediates", + leaf: dnssecExpLeaf, + intermediates: []string{startComIntermediate, startComRoot}, + roots: []string{startComRoot}, + currentTime: 1302726541, + systemSkip: true, // see dnssec-exp test + + expectedChains: [][]string{ + {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, + }, + }, + { + name: "InvalidHash", + leaf: googleLeafWithInvalidHash, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, + dnsName: "www.google.com", + + // The specific error message may not occur when using system + // verification. + systemLax: true, + errorCallback: expectHashError, + }, + // EKULeaf tests use an unconstrained chain leading to a leaf certificate + // with an E-mail Protection EKU but not a Server Auth one, checking that + // the EKUs on the leaf are enforced. + { + name: "EKULeaf", + leaf: smimeLeaf, + intermediates: []string{smimeIntermediate}, + roots: []string{smimeRoot}, + currentTime: 1594673418, + + errorCallback: expectUsageError, + }, + { + name: "EKULeafExplicit", + leaf: smimeLeaf, + intermediates: []string{smimeIntermediate}, + roots: []string{smimeRoot}, + currentTime: 1594673418, + keyUsages: []ExtKeyUsage{ExtKeyUsageServerAuth}, + + errorCallback: expectUsageError, + }, + { + name: "EKULeafValid", + leaf: smimeLeaf, + intermediates: []string{smimeIntermediate}, + roots: []string{smimeRoot}, + currentTime: 1594673418, + keyUsages: []ExtKeyUsage{ExtKeyUsageEmailProtection}, + + expectedChains: [][]string{ + {"CORPORATIVO FICTICIO ACTIVO", "EAEko Herri Administrazioen CA - CA AAPP Vascas (2)", "IZENPE S.A."}, + }, + }, + { + name: "SGCIntermediate", + leaf: megaLeaf, + intermediates: []string{comodoIntermediate1}, + roots: []string{comodoRoot}, + currentTime: 1360431182, + + // CryptoAPI can find alternative validation paths. + systemLax: true, + expectedChains: [][]string{ + {"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"}, + }, + }, + { + // Check that a name constrained intermediate works even when + // it lists multiple constraints. + name: "MultipleConstraints", + leaf: nameConstraintsLeaf, + intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2}, + roots: []string{globalSignRoot}, + currentTime: 1382387896, + dnsName: "secure.iddl.vt.edu", + + expectedChains: [][]string{ + { + "Technology-enhanced Learning and Online Strategies", + "Virginia Tech Global Qualified Server CA", + "Trusted Root CA G2", + "GlobalSign Root CA", + }, + }, + }, + { + // Check that SHA-384 intermediates (which are popping up) + // work. + name: "SHA-384", + leaf: moipLeafCert, + intermediates: []string{comodoIntermediateSHA384, comodoRSAAuthority}, + roots: []string{addTrustRoot}, + currentTime: 1397502195, + dnsName: "api.moip.com.br", + + // CryptoAPI can find alternative validation paths. + systemLax: true, + + expectedChains: [][]string{ + { + "api.moip.com.br", + "COMODO RSA Extended Validation Secure Server CA", + "COMODO RSA Certification Authority", + "AddTrust External CA Root", + }, + }, + }, + { + // Putting a certificate as a root directly should work as a + // way of saying “exactly this”. + name: "LeafInRoots", + leaf: selfSigned, + roots: []string{selfSigned}, + currentTime: 1471624472, + dnsName: "foo.example", + systemSkip: true, // does not chain to a system root + + expectedChains: [][]string{ + {"Acme Co"}, + }, + }, + { + // Putting a certificate as a root directly should not skip + // other checks however. + name: "LeafInRootsInvalid", + leaf: selfSigned, + roots: []string{selfSigned}, + currentTime: 1471624472, + dnsName: "notfoo.example", + systemSkip: true, // does not chain to a system root + + errorCallback: expectHostnameError("certificate is valid for"), + }, + { + // An X.509 v1 certificate should not be accepted as an + // intermediate. + name: "X509v1Intermediate", + leaf: x509v1TestLeaf, + intermediates: []string{x509v1TestIntermediate}, + roots: []string{x509v1TestRoot}, + currentTime: 1481753183, + systemSkip: true, // does not chain to a system root + + errorCallback: expectNotAuthorizedError, + }, + { + name: "IgnoreCNWithSANs", + leaf: ignoreCNWithSANLeaf, + dnsName: "foo.example.com", + roots: []string{ignoreCNWithSANRoot}, + currentTime: 1486684488, + systemSkip: true, // does not chain to a system root + + errorCallback: expectHostnameError("certificate is not valid for any names"), + }, + { + // Test that excluded names are respected. + name: "ExcludedNames", + leaf: excludedNamesLeaf, + dnsName: "bender.local", + intermediates: []string{excludedNamesIntermediate}, + roots: []string{excludedNamesRoot}, + currentTime: 1486684488, + systemSkip: true, // does not chain to a system root + + errorCallback: expectNameConstraintsError, + }, + { + // Test that unknown critical extensions in a leaf cause a + // verify error. + name: "CriticalExtLeaf", + leaf: criticalExtLeafWithExt, + intermediates: []string{criticalExtIntermediate}, + roots: []string{criticalExtRoot}, + currentTime: 1486684488, + systemSkip: true, // does not chain to a system root + + errorCallback: expectUnhandledCriticalExtension, + }, + { + // Test that unknown critical extensions in an intermediate + // cause a verify error. + name: "CriticalExtIntermediate", + leaf: criticalExtLeaf, + intermediates: []string{criticalExtIntermediateWithExt}, + roots: []string{criticalExtRoot}, + currentTime: 1486684488, + systemSkip: true, // does not chain to a system root + + errorCallback: expectUnhandledCriticalExtension, + }, + { + name: "ValidCN", + leaf: validCNWithoutSAN, + dnsName: "foo.example.com", + roots: []string{invalidCNRoot}, + currentTime: 1540000000, + systemSkip: true, // does not chain to a system root + + errorCallback: expectHostnameError("certificate relies on legacy Common Name field"), + }, + { + // A certificate with an AKID should still chain to a parent without SKID. + // See Issue 30079. + name: "AKIDNoSKID", + leaf: leafWithAKID, + roots: []string{rootWithoutSKID}, + currentTime: 1550000000, + dnsName: "example", + systemSkip: true, // does not chain to a system root + + expectedChains: [][]string{ + {"Acme LLC", "Acme Co"}, + }, + }, + { + // When there are two parents, one with a incorrect subject but matching SKID + // and one with a correct subject but missing SKID, the latter should be + // considered as a possible parent. + leaf: leafMatchingAKIDMatchingIssuer, + roots: []string{rootMatchingSKIDMismatchingSubject, rootMismatchingSKIDMatchingSubject}, + currentTime: 1550000000, + dnsName: "example", + systemSkip: true, + + expectedChains: [][]string{ + {"Leaf", "Root B"}, + }, + }, +} + +func expectHostnameError(msg string) func(*testing.T, error) { + return func(t *testing.T, err error) { + if _, ok := err.(HostnameError); !ok { + t.Fatalf("error was not a HostnameError: %v", err) + } + if !strings.Contains(err.Error(), msg) { + t.Fatalf("HostnameError did not contain %q: %v", msg, err) + } + } +} + +func expectExpired(t *testing.T, err error) { + if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired { + t.Fatalf("error was not Expired: %v", err) + } +} + +func expectUsageError(t *testing.T, err error) { + if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage { + t.Fatalf("error was not IncompatibleUsage: %v", err) + } +} + +func expectAuthorityUnknown(t *testing.T, err error) { + e, ok := err.(UnknownAuthorityError) + if !ok { + t.Fatalf("error was not UnknownAuthorityError: %v", err) + } + if e.Cert == nil { + t.Fatalf("error was UnknownAuthorityError, but missing Cert: %v", err) + } +} + +func expectHashError(t *testing.T, err error) { + if err == nil { + t.Fatalf("no error resulted from invalid hash") + } + if expected := "algorithm unimplemented"; !strings.Contains(err.Error(), expected) { + t.Fatalf("error resulting from invalid hash didn't contain '%s', rather it was: %v", expected, err) + } +} + +func expectNameConstraintsError(t *testing.T, err error) { + if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != CANotAuthorizedForThisName { + t.Fatalf("error was not a CANotAuthorizedForThisName: %v", err) + } +} + +func expectNotAuthorizedError(t *testing.T, err error) { + if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NotAuthorizedToSign { + t.Fatalf("error was not a NotAuthorizedToSign: %v", err) + } +} + +func expectUnhandledCriticalExtension(t *testing.T, err error) { + if _, ok := err.(UnhandledCriticalExtension); !ok { + t.Fatalf("error was not an UnhandledCriticalExtension: %v", err) + } +} + +func certificateFromPEM(pemBytes string) (*Certificate, error) { + block, _ := pem.Decode([]byte(pemBytes)) + if block == nil { + return nil, errors.New("failed to decode PEM") + } + return ParseCertificate(block.Bytes) +} + +func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { + opts := VerifyOptions{ + Intermediates: NewCertPool(), + DNSName: test.dnsName, + CurrentTime: time.Unix(test.currentTime, 0), + KeyUsages: test.keyUsages, + } + + if !useSystemRoots { + opts.Roots = NewCertPool() + for j, root := range test.roots { + ok := opts.Roots.AppendCertsFromPEM([]byte(root)) + if !ok { + t.Fatalf("failed to parse root #%d", j) + } + } + } + + for j, intermediate := range test.intermediates { + ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate)) + if !ok { + t.Fatalf("failed to parse intermediate #%d", j) + } + } + + leaf, err := certificateFromPEM(test.leaf) + if err != nil { + t.Fatalf("failed to parse leaf: %v", err) + } + + chains, err := leaf.Verify(opts) + + if test.errorCallback == nil && err != nil { + t.Fatalf("unexpected error: %v", err) + } + if test.errorCallback != nil { + if useSystemRoots && test.systemLax { + if err == nil { + t.Fatalf("expected error") + } + } else { + test.errorCallback(t, err) + } + } + + doesMatch := func(expectedChain []string, chain []*Certificate) bool { + if len(chain) != len(expectedChain) { + return false + } + + for k, cert := range chain { + if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) { + return false + } + } + return true + } + + // Every expected chain should match 1 returned chain + for _, expectedChain := range test.expectedChains { + nChainMatched := 0 + for _, chain := range chains { + if doesMatch(expectedChain, chain) { + nChainMatched++ + } + } + + if nChainMatched != 1 { + t.Errorf("Got %v matches instead of %v for expected chain %v", nChainMatched, 1, expectedChain) + for _, chain := range chains { + if doesMatch(expectedChain, chain) { + t.Errorf("\t matched %v", chainToDebugString(chain)) + } + } + } + } + + // Every returned chain should match 1 expected chain (or <2 if testing against the system) + for _, chain := range chains { + nMatched := 0 + for _, expectedChain := range test.expectedChains { + if doesMatch(expectedChain, chain) { + nMatched++ + } + } + // Allow additional unknown chains if systemLax is set + if nMatched == 0 && test.systemLax == false || nMatched > 1 { + t.Errorf("Got %v matches for chain %v", nMatched, chainToDebugString(chain)) + for _, expectedChain := range test.expectedChains { + if doesMatch(expectedChain, chain) { + t.Errorf("\t matched %v", expectedChain) + } + } + } + } +} + +func TestGoVerify(t *testing.T) { + for _, test := range verifyTests { + t.Run(test.name, func(t *testing.T) { + testVerify(t, test, false) + }) + } +} + +func TestSystemVerify(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS) + } + + for _, test := range verifyTests { + t.Run(test.name, func(t *testing.T) { + if test.systemSkip { + t.SkipNow() + } + testVerify(t, test, true) + }) + } +} + +func chainToDebugString(chain []*Certificate) string { + var chainStr string + for _, cert := range chain { + if len(chainStr) > 0 { + chainStr += " -> " + } + chainStr += nameToKey(&cert.Subject) + } + return chainStr +} + +func nameToKey(name *pkix.Name) string { + return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName +} + +const geoTrustRoot = `-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE-----` + +const giag2Intermediate = `-----BEGIN CERTIFICATE----- +MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG +EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy +bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP +VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv +h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE +ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ +EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC +DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7 +qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD +VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g +K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI +KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n +ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB +BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY +/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/ +zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza +HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto +WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6 +yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx +-----END CERTIFICATE-----` + +const googleLeaf = `-----BEGIN CERTIFICATE----- +MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE +BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl +cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMzEyMDkzODMwWhcNMTQwNjEwMDAwMDAw +WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN +TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3 +Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4zYCe +m0oUBhwE0EwBr65eBOcgcQO2PaSIAB2dEP/c1EMX2tOy0ov8rk83ePhJ+MWdT1z6 +jge9X4zQQI8ZyA9qIiwrKBZOi8DNUvrqNZC7fJAVRrb9aX/99uYOJCypIbpmWG1q +fhbHjJewhwf8xYPj71eU4rLG80a+DapWmphtfq3h52lDQIBzLVf1yYbyrTaELaz4 +NXF7HXb5YkId/gxIsSzM0aFUVu2o8sJcLYAsJqwfFKBKOMxUcn545nlspf0mTcWZ +0APlbwsKznNs4/xCDwIxxWjjqgHrYAFl6y07i1gzbAOqdNEyR24p+3JWI8WZBlBI +dk2KGj0W1fIfsvyxAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE +XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0 +MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G +A1UdDgQWBBTXD5Bx6iqT+dmEhbFL4OUoHyZn8zAMBgNVHRMBAf8EAjAAMB8GA1Ud +IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW +eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB +RzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCR3RJtHzgDh33b/MI1ugiki+nl8Ikj +5larbJRE/rcA5oite+QJyAr6SU1gJJ/rRrK3ItVEHr9L621BCM7GSdoNMjB9MMcf +tJAW0kYGJ+wqKm53wG/JaOADTnnq2Mt/j6F2uvjgN/ouns1nRHufIvd370N0LeH+ +orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi +8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA +Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX +-----END CERTIFICATE-----` + +// googleLeafWithInvalidHash is the same as googleLeaf, but the signature +// algorithm in the certificate contains a nonsense OID. +const googleLeafWithInvalidHash = `-----BEGIN CERTIFICATE----- +MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAWAFBQAwSTELMAkGA1UE +BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl +cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMzEyMDkzODMwWhcNMTQwNjEwMDAwMDAw +WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN +TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3 +Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4zYCe +m0oUBhwE0EwBr65eBOcgcQO2PaSIAB2dEP/c1EMX2tOy0ov8rk83ePhJ+MWdT1z6 +jge9X4zQQI8ZyA9qIiwrKBZOi8DNUvrqNZC7fJAVRrb9aX/99uYOJCypIbpmWG1q +fhbHjJewhwf8xYPj71eU4rLG80a+DapWmphtfq3h52lDQIBzLVf1yYbyrTaELaz4 +NXF7HXb5YkId/gxIsSzM0aFUVu2o8sJcLYAsJqwfFKBKOMxUcn545nlspf0mTcWZ +0APlbwsKznNs4/xCDwIxxWjjqgHrYAFl6y07i1gzbAOqdNEyR24p+3JWI8WZBlBI +dk2KGj0W1fIfsvyxAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE +XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0 +MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G +A1UdDgQWBBTXD5Bx6iqT+dmEhbFL4OUoHyZn8zAMBgNVHRMBAf8EAjAAMB8GA1Ud +IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW +eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB +RzIuY3JsMA0GCSqGSIb3DQFgBQUAA4IBAQCR3RJtHzgDh33b/MI1ugiki+nl8Ikj +5larbJRE/rcA5oite+QJyAr6SU1gJJ/rRrK3ItVEHr9L621BCM7GSdoNMjB9MMcf +tJAW0kYGJ+wqKm53wG/JaOADTnnq2Mt/j6F2uvjgN/ouns1nRHufIvd370N0LeH+ +orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi +8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA +Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX +-----END CERTIFICATE-----` + +const dnssecExpLeaf = `-----BEGIN CERTIFICATE----- +MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ +TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg +MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTAwNzA0MTQ1MjQ1 +WhcNMTEwNzA1MTA1NzA0WjCBwTEgMB4GA1UEDRMXMjIxMTM3LWxpOWE5dHhJRzZM +NnNyVFMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVQZXJzb25hIE5vdCBWYWxpZGF0 +ZWQxKTAnBgNVBAsTIFN0YXJ0Q29tIEZyZWUgQ2VydGlmaWNhdGUgTWVtYmVyMRsw +GQYDVQQDExJ3d3cuZG5zc2VjLWV4cC5vcmcxKDAmBgkqhkiG9w0BCQEWGWhvc3Rt +YXN0ZXJAZG5zc2VjLWV4cC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDEdF/22vaxrPbqpgVYMWi+alfpzBctpbfLBdPGuqOazJdCT0NbWcK8/+B4 +X6OlSOURNIlwLzhkmwVsWdVv6dVSaN7d4yI/fJkvgfDB9+au+iBJb6Pcz8ULBfe6 +D8HVvqKdORp6INzHz71z0sghxrQ0EAEkoWAZLh+kcn2ZHdcmZaBNUfjmGbyU6PRt +RjdqoP+owIaC1aktBN7zl4uO7cRjlYFdusINrh2kPP02KAx2W84xjxX1uyj6oS6e +7eBfvcwe8czW/N1rbE0CoR7h9+HnIrjnVG9RhBiZEiw3mUmF++Up26+4KTdRKbu3 ++BL4yMpfd66z0+zzqu+HkvyLpFn5AgMBAAGjggL/MIIC+zAJBgNVHRMEAjAAMAsG +A1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUy04I5guM +drzfh2JQaXhgV86+4jUwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUw +LQYDVR0RBCYwJIISd3d3LmRuc3NlYy1leHAub3Jngg5kbnNzZWMtZXhwLm9yZzCC +AUIGA1UdIASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgIwggEgMC4GCCsGAQUFBwIB +FiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIB +FihodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3Bggr +BgEFBQcCAjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJp +bGl0eSwgc2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBh +dCBodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGEGA1UdHwRaMFgw +KqAooCaGJGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDAqoCig +JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF +BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v +c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuc3Rh +cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE +HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB +ACXj6SB59KRJPenn6gUdGEqcta97U769SATyiQ87i9er64qLwvIGLMa3o2Rcgl2Y +kghUeyLdN/EXyFBYA8L8uvZREPoc7EZukpT/ZDLXy9i2S0jkOxvF2fD/XLbcjGjM +iEYG1/6ASw0ri9C0k4oDDoJLCoeH9++yqF7SFCCMcDkJqiAGXNb4euDpa8vCCtEQ +CSS+ObZbfkreRt3cNCf5LfCXe9OsTnCfc8Cuq81c0oLaG+SmaLUQNBuToq8e9/Zm ++b+/a3RVjxmkV5OCcGVBxsXNDn54Q6wsdw0TBMcjwoEndzpLS7yWgFbbkq5ZiGpw +Qibb2+CfKuQ+WFV1GkVQmVA= +-----END CERTIFICATE-----` + +const startComIntermediate = `-----BEGIN CERTIFICATE----- +MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB +jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT +IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0 +YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE +gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA +pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv +kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/ +ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5 +xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID +AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul +F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov +L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0 +YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3 +dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0 +c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu +BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0 +BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl +LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp +tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen +xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw +xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X +t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI +RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi +YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L +WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN +SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD +wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L +p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un +0q6Dp6jOW6c= +-----END CERTIFICATE-----` + +const startComRoot = `-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW +MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg +Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 +MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi +U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh +cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk +pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf +OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C +Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT +Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi +HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM +Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w ++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ +Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 +Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B +26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID +AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j +ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js +LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM +BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy +dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh +cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh +YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg +dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp +bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ +YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT +TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ +9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 +jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW +FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz +ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 +ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L +EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu +L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC +O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V +um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh +NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= +-----END CERTIFICATE-----` + +const smimeLeaf = `-----BEGIN CERTIFICATE----- +MIIIPDCCBiSgAwIBAgIQaMDxFS0pOMxZZeOBxoTJtjANBgkqhkiG9w0BAQsFADCB +nTELMAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMTowOAYDVQQLDDFB +WlogWml1cnRhZ2lyaSBwdWJsaWtvYSAtIENlcnRpZmljYWRvIHB1YmxpY28gU0NB +MTwwOgYDVQQDDDNFQUVrbyBIZXJyaSBBZG1pbmlzdHJhemlvZW4gQ0EgLSBDQSBB +QVBQIFZhc2NhcyAoMikwHhcNMTcwNzEyMDg1MzIxWhcNMjEwNzEyMDg1MzIxWjCC +AQwxDzANBgNVBAoMBklaRU5QRTE4MDYGA1UECwwvWml1cnRhZ2lyaSBrb3Jwb3Jh +dGlib2EtQ2VydGlmaWNhZG8gY29ycG9yYXRpdm8xQzBBBgNVBAsMOkNvbmRpY2lv +bmVzIGRlIHVzbyBlbiB3d3cuaXplbnBlLmNvbSBub2xhIGVyYWJpbGkgamFraXRl +a28xFzAVBgNVBC4TDi1kbmkgOTk5OTk5ODlaMSQwIgYDVQQDDBtDT1JQT1JBVElW +TyBGSUNUSUNJTyBBQ1RJVk8xFDASBgNVBCoMC0NPUlBPUkFUSVZPMREwDwYDVQQE +DAhGSUNUSUNJTzESMBAGA1UEBRMJOTk5OTk5ODlaMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAwVOMwUDfBtsH0XuxYnb+v/L774jMH8valX7RPH8cl2Lb +SiqSo0RchW2RGA2d1yuYHlpChC9jGmt0X/g66/E/+q2hUJlfJtqVDJFwtFYV4u2S +yzA3J36V4PRkPQrKxAsbzZriFXAF10XgiHQz9aVeMMJ9GBhmh9+DK8Tm4cMF6i8l ++AuC35KdngPF1x0ealTYrYZplpEJFO7CiW42aLi6vQkDR2R7nmZA4AT69teqBWsK +0DZ93/f0G/3+vnWwNTBF0lB6dIXoaz8OMSyHLqGnmmAtMrzbjAr/O/WWgbB/BqhR +qjJQ7Ui16cuDldXaWQ/rkMzsxmsAox0UF+zdQNvXUQIDAQABo4IDBDCCAwAwgccG +A1UdEgSBvzCBvIYVaHR0cDovL3d3dy5pemVucGUuY29tgQ9pbmZvQGl6ZW5wZS5j +b22kgZEwgY4xRzBFBgNVBAoMPklaRU5QRSBTLkEuIC0gQ0lGIEEwMTMzNzI2MC1S +TWVyYy5WaXRvcmlhLUdhc3RlaXogVDEwNTUgRjYyIFM4MUMwQQYDVQQJDDpBdmRh +IGRlbCBNZWRpdGVycmFuZW8gRXRvcmJpZGVhIDE0IC0gMDEwMTAgVml0b3JpYS1H +YXN0ZWl6MB4GA1UdEQQXMBWBE2ZpY3RpY2lvQGl6ZW5wZS5ldXMwDgYDVR0PAQH/ +BAQDAgXgMCkGA1UdJQQiMCAGCCsGAQUFBwMCBggrBgEFBQcDBAYKKwYBBAGCNxQC +AjAdBgNVHQ4EFgQUyeoOD4cgcljKY0JvrNuX2waFQLAwHwYDVR0jBBgwFoAUwKlK +90clh/+8taaJzoLSRqiJ66MwggEnBgNVHSAEggEeMIIBGjCCARYGCisGAQQB8zkB +AQEwggEGMDMGCCsGAQUFBwIBFidodHRwOi8vd3d3Lml6ZW5wZS5jb20vcnBhc2Nh +Y29ycG9yYXRpdm8wgc4GCCsGAQUFBwICMIHBGoG+Wml1cnRhZ2lyaWEgRXVza2Fs +IEF1dG9ub21pYSBFcmtpZGVnb2tvIHNla3RvcmUgcHVibGlrb2tvIGVyYWt1bmRl +ZW4gYmFybmUtc2FyZWV0YW4gYmFrYXJyaWsgZXJhYmlsIGRhaXRla2UuIFVzbyBy +ZXN0cmluZ2lkbyBhbCBhbWJpdG8gZGUgcmVkZXMgaW50ZXJuYXMgZGUgRW50aWRh +ZGVzIGRlbCBTZWN0b3IgUHVibGljbyBWYXNjbzAyBggrBgEFBQcBAQQmMCQwIgYI +KwYBBQUHMAGGFmh0dHA6Ly9vY3NwLml6ZW5wZS5jb20wOgYDVR0fBDMwMTAvoC2g +K4YpaHR0cDovL2NybC5pemVucGUuY29tL2NnaS1iaW4vY3JsaW50ZXJuYTIwDQYJ +KoZIhvcNAQELBQADggIBAIy5PQ+UZlCRq6ig43vpHwlwuD9daAYeejV0Q+ZbgWAE +GtO0kT/ytw95ZEJMNiMw3fYfPRlh27ThqiT0VDXZJDlzmn7JZd6QFcdXkCsiuv4+ +ZoXAg/QwnA3SGUUO9aVaXyuOIIuvOfb9MzoGp9xk23SMV3eiLAaLMLqwB5DTfBdt +BGI7L1MnGJBv8RfP/TL67aJ5bgq2ri4S8vGHtXSjcZ0+rCEOLJtmDNMnTZxancg3 +/H5edeNd+n6Z48LO+JHRxQufbC4mVNxVLMIP9EkGUejlq4E4w6zb5NwCQczJbSWL +i31rk2orsNsDlyaLGsWZp3JSNX6RmodU4KAUPor4jUJuUhrrm3Spb73gKlV/gcIw +bCE7mML1Kss3x1ySaXsis6SZtLpGWKkW2iguPWPs0ydV6RPhmsCxieMwPPIJ87vS +5IejfgyBae7RSuAIHyNFy4uI5xwvwUFf6OZ7az8qtW7ImFOgng3Ds+W9k1S2CNTx +d0cnKTfA6IpjGo8EeHcxnIXT8NPImWaRj0qqonvYady7ci6U4m3lkNSdXNn1afgw +mYust+gxVtOZs1gk2MUCgJ1V1X+g7r/Cg7viIn6TLkLrpS1kS1hvMqkl9M+7XqPo +Qd95nJKOkusQpy99X4dF/lfbYAQnnjnqh3DLD2gvYObXFaAYFaiBKTiMTV2X72F+ +-----END CERTIFICATE-----` + +const smimeIntermediate = `-----BEGIN CERTIFICATE----- +MIIHNzCCBSGgAwIBAgIQJMXIqlZvjuhMvqcFXOFkpDALBgkqhkiG9w0BAQswODEL +MAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMRMwEQYDVQQDDApJemVu +cGUuY29tMB4XDTEwMTAyMDA4MjMzM1oXDTM3MTIxMjIzMDAwMFowgZ0xCzAJBgNV +BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjE6MDgGA1UECwwxQVpaIFppdXJ0 +YWdpcmkgcHVibGlrb2EgLSBDZXJ0aWZpY2FkbyBwdWJsaWNvIFNDQTE8MDoGA1UE +AwwzRUFFa28gSGVycmkgQWRtaW5pc3RyYXppb2VuIENBIC0gQ0EgQUFQUCBWYXNj +YXMgKDIpMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoIM7nEdI0N1h +rR5T4xuV/usKDoMIasaiKvfLhbwxaNtTt+a7W/6wV5bv3svQFIy3sUXjjdzV1nG2 +To2wo/YSPQiOt8exWvOapvL21ogiof+kelWnXFjWaKJI/vThHYLgIYEMj/y4HdtU +ojI646rZwqsb4YGAopwgmkDfUh5jOhV2IcYE3TgJAYWVkj6jku9PLaIsHiarAHjD +PY8dig8a4SRv0gm5Yk7FXLmW1d14oxQBDeHZ7zOEXfpafxdEDO2SNaRJjpkh8XRr +PGqkg2y1Q3gT6b4537jz+StyDIJ3omylmlJsGCwqT7p8mEqjGJ5kC5I2VnjXKuNn +soShc72khWZVUJiJo5SGuAkNE2ZXqltBVm5Jv6QweQKsX6bkcMc4IZok4a+hx8FM +8IBpGf/I94pU6HzGXqCyc1d46drJgDY9mXa+6YDAJFl3xeXOOW2iGCfwXqhiCrKL +MYvyMZzqF3QH5q4nb3ZnehYvraeMFXJXDn+Utqp8vd2r7ShfQJz01KtM4hgKdgSg +jtW+shkVVN5ng/fPN85ovfAH2BHXFfHmQn4zKsYnLitpwYM/7S1HxlT61cdQ7Nnk +3LZTYEgAoOmEmdheklT40WAYakksXGM5VrzG7x9S7s1Tm+Vb5LSThdHC8bxxwyTb +KsDRDNJ84N9fPDO6qHnzaL2upQ43PycCAwEAAaOCAdkwggHVMIHHBgNVHREEgb8w +gbyGFWh0dHA6Ly93d3cuaXplbnBlLmNvbYEPaW5mb0BpemVucGUuY29tpIGRMIGO +MUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBBMDEzMzcyNjAtUk1lcmMuVml0 +b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEGA1UECQw6QXZkYSBkZWwgTWVk +aXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEwIFZpdG9yaWEtR2FzdGVpejAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUwKlK90cl +h/+8taaJzoLSRqiJ66MwHwYDVR0jBBgwFoAUHRxlDqjyJXu0kc/ksbHmvVV0bAUw +OgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly93d3cuaXpl +bnBlLmNvbS9jcHMwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8v +b2NzcC5pemVucGUuY29tOjgwOTQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny +bC5pemVucGUuY29tL2NnaS1iaW4vYXJsMjALBgkqhkiG9w0BAQsDggIBAMbjc3HM +3DG9ubWPkzsF0QsktukpujbTTcGk4h20G7SPRy1DiiTxrRzdAMWGjZioOP3/fKCS +M539qH0M+gsySNie+iKlbSZJUyE635T1tKw+G7bDUapjlH1xyv55NC5I6wCXGC6E +3TEP5B/E7dZD0s9E4lS511ubVZivFgOzMYo1DO96diny/N/V1enaTCpRl1qH1OyL +xUYTijV4ph2gL6exwuG7pxfRcVNHYlrRaXWfTz3F6NBKyULxrI3P/y6JAtN1GqT4 +VF/+vMygx22n0DufGepBwTQz6/rr1ulSZ+eMnuJiTXgh/BzQnkUsXTb8mHII25iR +0oYF2qAsk6ecWbLiDpkHKIDHmML21MZE13MS8NSvTHoqJO4LyAmDe6SaeNHtrPlK +b6mzE1BN2ug+ZaX8wLA5IMPFaf0jKhb/Cxu8INsxjt00brsErCc9ip1VNaH0M4bi +1tGxfiew2436FaeyUxW7Pl6G5GgkNbuUc7QIoRy06DdU/U38BxW3uyJMY60zwHvS +FlKAn0OvYp4niKhAJwaBVN3kowmJuOU5Rid+TUnfyxbJ9cttSgzaF3hP/N4zgMEM +5tikXUskeckt8LUK96EH0QyssavAMECUEb/xrupyRdYWwjQGvNLq6T5+fViDGyOw +k+lzD44wofy8paAy9uC9Owae0zMEzhcsyRm7 +-----END CERTIFICATE-----` + +const smimeRoot = `-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD +VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j +b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq +scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO +xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H +LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX +uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD +yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ +JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q +rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN +BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L +hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB +QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ +HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu +Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg +QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB +BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA +A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb +laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 +awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo +JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw +LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT +VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk +LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb +UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ +QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ +naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls +QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE-----` + +var megaLeaf = `-----BEGIN CERTIFICATE----- +MIIFOjCCBCKgAwIBAgIQWYE8Dup170kZ+k11Lg51OjANBgkqhkiG9w0BAQUFADBy +MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD +VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE +AxMPRXNzZW50aWFsU1NMIENBMB4XDTEyMTIxNDAwMDAwMFoXDTE0MTIxNDIzNTk1 +OVowfzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMS4wLAYDVQQL +EyVIb3N0ZWQgYnkgSW5zdHJhIENvcnBvcmF0aW9uIFB0eS4gTFREMRUwEwYDVQQL +EwxFc3NlbnRpYWxTU0wxEzARBgNVBAMTCm1lZ2EuY28ubnowggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDcxMCClae8BQIaJHBUIVttlLvhbK4XhXPk3RQ3 +G5XA6tLZMBQ33l3F9knYJ0YErXtr8IdfYoulRQFmKFMJl9GtWyg4cGQi2Rcr5VN5 +S5dA1vu4oyJBxE9fPELcK6Yz1vqaf+n6za+mYTiQYKggVdS8/s8hmNuXP9Zk1pIn ++q0pGsf8NAcSHMJgLqPQrTDw+zae4V03DvcYfNKjuno88d2226ld7MAmQZ7uRNsI +/CnkdelVs+akZsXf0szefSqMJlf08SY32t2jj4Ra7RApVYxOftD9nij/aLfuqOU6 +ow6IgIcIG2ZvXLZwK87c5fxL7UAsTTV+M1sVv8jA33V2oKLhAgMBAAGjggG9MIIB +uTAfBgNVHSMEGDAWgBTay+qtWwhdzP/8JlTOSeVVxjj0+DAdBgNVHQ4EFgQUmP9l +6zhyrZ06Qj4zogt+6LKFk4AwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAw +NAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBgorBgEEAYI3CgMDBglghkgB +hvhCBAEwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQICBzArMCkGCCsGAQUFBwIBFh1o +dHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAIBgZngQwBAgEwOwYDVR0fBDQw +MjAwoC6gLIYqaHR0cDovL2NybC5jb21vZG9jYS5jb20vRXNzZW50aWFsU1NMQ0Eu +Y3JsMG4GCCsGAQUFBwEBBGIwYDA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21v +ZG9jYS5jb20vRXNzZW50aWFsU1NMQ0FfMi5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6 +Ly9vY3NwLmNvbW9kb2NhLmNvbTAlBgNVHREEHjAcggptZWdhLmNvLm56gg53d3cu +bWVnYS5jby5uejANBgkqhkiG9w0BAQUFAAOCAQEAcYhrsPSvDuwihMOh0ZmRpbOE +Gw6LqKgLNTmaYUPQhzi2cyIjhUhNvugXQQlP5f0lp5j8cixmArafg1dTn4kQGgD3 +ivtuhBTgKO1VYB/VRoAt6Lmswg3YqyiS7JiLDZxjoV7KoS5xdiaINfHDUaBBY4ZH +j2BUlPniNBjCqXe/HndUTVUewlxbVps9FyCmH+C4o9DWzdGBzDpCkcmo5nM+cp7q +ZhTIFTvZfo3zGuBoyu8BzuopCJcFRm3cRiXkpI7iOMUIixO1szkJS6WpL1sKdT73 +UXp08U0LBqoqG130FbzEJBBV3ixbvY6BWMHoCWuaoF12KJnC5kHt2RoWAAgMXA== +-----END CERTIFICATE-----` + +var comodoIntermediate1 = `-----BEGIN CERTIFICATE----- +MIIFAzCCA+ugAwIBAgIQGLLLuqME8aAPwfLzJkYqSjANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0xOTEyMzEyMzU5NTlaMHIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVh +dGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9E +TyBDQSBMaW1pdGVkMRgwFgYDVQQDEw9Fc3NlbnRpYWxTU0wgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt8AiwcsargxIxF3CJhakgEtSYau2A1NHf +5I5ZLdOWIY120j8YC0YZYwvHIPPlC92AGvFaoL0dds23Izp0XmEbdaqb1IX04XiR +0y3hr/yYLgbSeT1awB8hLRyuIVPGOqchfr7tZ291HRqfalsGs2rjsQuqag7nbWzD +ypWMN84hHzWQfdvaGlyoiBSyD8gSIF/F03/o4Tjg27z5H6Gq1huQByH6RSRQXScq +oChBRVt9vKCiL6qbfltTxfEFFld+Edc7tNkBdtzffRDPUanlOPJ7FAB1WfnwWdsX +Pvev5gItpHnBXaIcw5rIp6gLSApqLn8tl2X2xQScRMiZln5+pN0vAgMBAAGjggGD +MIIBfzAfBgNVHSMEGDAWgBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAdBgNVHQ4EFgQU +2svqrVsIXcz//CZUzknlVcY49PgwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI +MAYBAf8CAQAwIAYDVR0lBBkwFwYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMD4GA1Ud +IAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21v +ZG8uY29tL0NQUzBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9kb2Nh +LmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBsBggrBgEFBQcB +AQRgMF4wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NvbW9k +b1VUTlNHQ0NBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2Eu +Y29tMA0GCSqGSIb3DQEBBQUAA4IBAQAtlzR6QDLqcJcvgTtLeRJ3rvuq1xqo2l/z +odueTZbLN3qo6u6bldudu+Ennv1F7Q5Slqz0J790qpL0pcRDAB8OtXj5isWMcL2a +ejGjKdBZa0wztSz4iw+SY1dWrCRnilsvKcKxudokxeRiDn55w/65g+onO7wdQ7Vu +F6r7yJiIatnyfKH2cboZT7g440LX8NqxwCPf3dfxp+0Jj1agq8MLy6SSgIGSH6lv ++Wwz3D5XxqfyH8wqfOQsTEZf6/Nh9yvENZ+NWPU6g0QO2JOsTGvMd/QDzczc4BxL +XSXaPV7Od4rhPsbXlM1wSTz/Dr0ISKvlUhQVnQ6cGodWaK2cCQBk +-----END CERTIFICATE-----` + +var comodoRoot = `-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE-----` + +var nameConstraintsLeaf = `-----BEGIN CERTIFICATE----- +MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV +BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj +MCEGA1UECxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zp +cmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0 +eTExMC8GA1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZl +ciBDQTAeFw0xMzA5MTkxNDM2NTVaFw0xNTA5MTkxNDM2NTVaMIHNMQswCQYDVQQG +EwJVUzERMA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkJsYWNrc2J1cmcxPDA6 +BgNVBAoMM1ZpcmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUg +VW5pdmVyc2l0eTE7MDkGA1UECwwyVGVjaG5vbG9neS1lbmhhbmNlZCBMZWFybmlu +ZyBhbmQgT25saW5lIFN0cmF0ZWdpZXMxGzAZBgNVBAMMEnNlY3VyZS5pZGRsLnZ0 +LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkOyPpsOK/6IuPG +WnIBlVwlHzeYf+cUlggqkLq0b0+vZbiTXgio9/VCuNQ8opSoss7J7o3ygV9to+9Y +YwJKVC5WDT/y5JWpQey0CWILymViJnpNSwnxBc8A+Q8w5NUGDd/UhtPx/U8/hqbd +WPDYj2hbOqyq8UlRhfS5pwtnv6BbCTaY11I6FhCLK7zttISyTuWCf9p9o/ggiipP +ii/5oh4dkl+r5SfuSp5GPNHlYO8lWqys5NAPoDD4fc/kuflcK7Exx7XJ+Oqu0W0/ +psjEY/tES1ZgDWU/ParcxxFpFmKHbD5DXsfPOObzkVWXIY6tGMutSlE1Froy/Nn0 +OZsAOrcCAwEAAaOCAhMwggIPMIG4BggrBgEFBQcBAQSBqzCBqDBYBggrBgEFBQcw +AoZMaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbHF1YWxpZmllZHNlcnZlci9j +YWNlcnQvZ2xvYmFscXVhbGlmaWVkc2VydmVyLmNydDBMBggrBgEFBQcwAYZAaHR0 +cDovL3Z0Y2EtcC5lcHJvdi5zZXRpLnZ0LmVkdTo4MDgwL2VqYmNhL3B1YmxpY3dl +Yi9zdGF0dXMvb2NzcDAdBgNVHQ4EFgQUp7xbO6iHkvtZbPE4jmndmnAbSEcwDAYD +VR0TAQH/BAIwADAfBgNVHSMEGDAWgBS8YmAn1eM1SBfpS6tFatDIqHdxjDBqBgNV +HSAEYzBhMA4GDCsGAQQBtGgFAgICATAOBgwrBgEEAbRoBQICAQEwPwYMKwYBBAG0 +aAUCAgMBMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9i +YWwvY3BzLzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vd3d3LnBraS52dC5lZHUv +Z2xvYmFscXVhbGlmaWVkc2VydmVyL2NybC9jYWNybC5jcmwwDgYDVR0PAQH/BAQD +AgTwMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHREEFjAUghJz +ZWN1cmUuaWRkbC52dC5lZHUwDQYJKoZIhvcNAQEFBQADggIBAEgoYo4aUtatY3gI +OyyKp7QlIOaLbTJZywESHqy+L5EGDdJW2DJV+mcE0LDGvqa2/1Lo+AR1ntsZwfOi +Y718JwgVVaX/RCd5+QKP25c5/x72xI8hb/L1bgS0ED9b0YAhd7Qm1K1ot82+6mqX +DW6WiGeDr8Z07MQ3143qQe2rBlq+QI69DYzm2GOqAIAnUIWv7tCyLUm31b4DwmrJ +TeudVreTKUbBNB1TWRFHEPkWhjjXKZnNGRO11wHXcyBu6YekIvVZ+vmx8ePee4jJ +3GFOi7lMuWOeq57jTVL7KOKaKLVXBb6gqo5aq+Wwt8RUD5MakrCAEeQZj7DKaFmZ +oQCO0Pxrsl3InCGvxnGzT+bFVO9nJ/BAMj7hknFdm9Jr6Bg5q33Z+gnf909AD9QF +ESqUSykaHu2LVdJx2MaCH1CyKnRgMw5tEwE15EXpUjCm24m8FMOYC+rNtf18pgrz +5D8Jhh+oxK9PjcBYqXNtnioIxiMCYcV0q5d4w4BYFEh71tk7/bYB0R55CsBUVPmp +timWNOdRd57Tfpk3USaVsumWZAf9MP3wPiC7gb4d5tYEEAG5BuDT8ruFw838wU8G +1VvAVutSiYBg7k3NYO7AUqZ+Ax4klQX3aM9lgonmJ78Qt94UPtbptrfZ4/lSqEf8 +GBUwDrQNTb+gsXsDkjd5lcYxNx6l +-----END CERTIFICATE-----` + +var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE----- +MIINLjCCDBagAwIBAgIRIqpyf/YoGgvHc8HiDAxAI8owDQYJKoZIhvcNAQEFBQAw +XDELMAkGA1UEBhMCQkUxFTATBgNVBAsTDFRydXN0ZWQgUm9vdDEZMBcGA1UEChMQ +R2xvYmFsU2lnbiBudi1zYTEbMBkGA1UEAxMSVHJ1c3RlZCBSb290IENBIEcyMB4X +DTEyMTIxMzAwMDAwMFoXDTE3MTIxMzAwMDAwMFowgcsxCzAJBgNVBAYTAlVTMREw +DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UECxMa +R2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1ZpcmdpbmlhIFBv +bHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8GA1UE +AxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFGzMXa +GHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3RhgV+r +ihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmjv7fm +5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t4lA9 +pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP0YmM +R3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnbELhz +qyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyqG66W +ZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYrheq+ +9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3JWqnV +HNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wUin3y +cnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX0071s3 +Z2a2fio5c8m3JkdrAgMBAAGjggh5MIIIdTAOBgNVHQ8BAf8EBAMCAQYwTAYDVR0g +BEUwQzBBBgkrBgEEAaAyATwwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv +YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wEgYDVR0TAQH/BAgwBgEB/wIBADCCBtAG +A1UdHgSCBscwggbDoIIGvzASghAzZGJsYWNrc2J1cmcub3JnMBiCFmFjY2VsZXJh +dGV2aXJnaW5pYS5jb20wGIIWYWNjZWxlcmF0ZXZpcmdpbmlhLm9yZzALgglhY3Zj +cC5vcmcwCYIHYmV2Lm5ldDAJggdiZXYub3JnMAuCCWNsaWdzLm9yZzAMggpjbWl3 +ZWIub3JnMBeCFWVhc3Rlcm5icm9va3Ryb3V0Lm5ldDAXghVlYXN0ZXJuYnJvb2t0 +cm91dC5vcmcwEYIPZWNvcnJpZG9ycy5pbmZvMBOCEWVkZ2FycmVzZWFyY2gub3Jn +MBKCEGdldC1lZHVjYXRlZC5jb20wE4IRZ2V0LWVkdWNhdGVkLmluZm8wEYIPZ2V0 +ZWR1Y2F0ZWQubmV0MBKCEGdldC1lZHVjYXRlZC5uZXQwEYIPZ2V0ZWR1Y2F0ZWQu +b3JnMBKCEGdldC1lZHVjYXRlZC5vcmcwD4INaG9raWVjbHViLmNvbTAQgg5ob2tp +ZXBob3RvLmNvbTAPgg1ob2tpZXNob3AuY29tMBGCD2hva2llc3BvcnRzLmNvbTAS +ghBob2tpZXRpY2tldHMuY29tMBKCEGhvdGVscm9hbm9rZS5jb20wE4IRaHVtYW53 +aWxkbGlmZS5vcmcwF4IVaW5uYXR2aXJnaW5pYXRlY2guY29tMA+CDWlzY2hwMjAx +MS5vcmcwD4INbGFuZHJlaGFiLm9yZzAggh5uYXRpb25hbHRpcmVyZXNlYXJjaGNl +bnRlci5jb20wFYITbmV0d29ya3ZpcmdpbmlhLm5ldDAMggpwZHJjdnQuY29tMBiC +FnBldGVkeWVyaXZlcmNvdXJzZS5jb20wDYILcmFkaW9pcS5vcmcwFYITcml2ZXJj +b3Vyc2Vnb2xmLmNvbTALgglzZGltaS5vcmcwEIIOc292YW1vdGlvbi5jb20wHoIc +c3VzdGFpbmFibGUtYmlvbWF0ZXJpYWxzLmNvbTAeghxzdXN0YWluYWJsZS1iaW9t +YXRlcmlhbHMub3JnMBWCE3RoaXNpc3RoZWZ1dHVyZS5jb20wGIIWdGhpcy1pcy10 +aGUtZnV0dXJlLmNvbTAVghN0aGlzaXN0aGVmdXR1cmUubmV0MBiCFnRoaXMtaXMt +dGhlLWZ1dHVyZS5uZXQwCoIIdmFkcy5vcmcwDIIKdmFsZWFmLm9yZzANggt2YXRl +Y2guaW5mbzANggt2YXRlY2gubW9iaTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5n +LmNvbTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5nLm5ldDAcghp2YXRlY2hsaWZl +bG9uZ2xlYXJuaW5nLm9yZzAKggh2Y29tLmVkdTASghB2aXJnaW5pYXZpZXcubmV0 +MDSCMnZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVuaXZlcnNp +dHkuY29tMDWCM3ZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVu +aXZlcnNpdHkuaW5mbzA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0dXRlYW5k +c3RhdGV1bml2ZXJzaXR5Lm5ldDA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0 +dXRlYW5kc3RhdGV1bml2ZXJzaXR5Lm9yZzAZghd2aXJnaW5pYXB1YmxpY3JhZGlv +Lm9yZzASghB2aXJnaW5pYXRlY2guZWR1MBOCEXZpcmdpbmlhdGVjaC5tb2JpMByC +GnZpcmdpbmlhdGVjaGZvdW5kYXRpb24ub3JnMAiCBnZ0LmVkdTALggl2dGFyYy5v +cmcwDIIKdnQtYXJjLm9yZzALggl2dGNyYy5jb20wCoIIdnRpcC5vcmcwDIIKdnRs +ZWFuLm9yZzAWghR2dGtub3dsZWRnZXdvcmtzLmNvbTAYghZ2dGxpZmVsb25nbGVh +cm5pbmcuY29tMBiCFnZ0bGlmZWxvbmdsZWFybmluZy5uZXQwGIIWdnRsaWZlbG9u +Z2xlYXJuaW5nLm9yZzATghF2dHNwb3J0c21lZGlhLmNvbTALggl2dHdlaS5jb20w +D4INd2l3YXR3ZXJjLmNvbTAKggh3dnRmLm9yZzAIgQZ2dC5lZHUwd6R1MHMxCzAJ +BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVy +ZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBT +dGF0ZSBVbml2ZXJzaXR5MCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAQYI +KwYBBQUHAwkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5nbG9iYWxzaWdu +LmNvbS9ncy90cnVzdHJvb3RnMi5jcmwwgYQGCCsGAQUFBwEBBHgwdjAzBggrBgEF +BQcwAYYnaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3RydXN0cm9vdGcyMD8G +CCsGAQUFBzAChjNodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90 +cnVzdHJvb3RnMi5jcnQwHQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8G +A1UdIwQYMBaAFBT25YsxtkWASkxt/MKHico2w5BiMA0GCSqGSIb3DQEBBQUAA4IB +AQAyJm/lOB2Er4tHXhc/+fSufSzgjohJgYfMkvG4LknkvnZ1BjliefR8tTXX49d2 +SCDFWfGjqyJZwavavkl/4p3oXPG/nAMDMvxh4YAT+CfEK9HH+6ICV087kD4BLegi ++aFJMj8MMdReWCzn5sLnSR1rdse2mo2arX3Uod14SW+PGrbUmTuWNyvRbz3fVmxp +UdbGmj3laknO9YPsBGgHfv73pVVsTJkW4ZfY/7KdD/yaVv6ophpOB3coXfjl2+kd +Z4ypn2zK+cx9IL/LSewqd/7W9cD55PCUy4X9OTbEmAccwiz3LB66mQoUGfdHdkoB +jUY+v9vLQXmaVwI0AYL7g9LN +-----END CERTIFICATE-----` + +var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE----- +MIIEXTCCA0WgAwIBAgILBAAAAAABNuk6OrMwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMjA0MjUxMTAw +MDBaFw0yNzA0MjUxMTAwMDBaMFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVz +dGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRy +dXN0ZWQgUm9vdCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKyuvqrtcMr7g7EuNbu4sKwxM127UsCmx1RxbxxgcArGS7rjiefpBH/w4LYrymjf +vcw1ueyMNoqLo9nJMz/ORXupb35NNfE667prQYHa+tTjl1IiKpB7QUwt3wXPuTMF +Ja1tXtjKzkqJyuJlNuPKT76HcjgNqgV1s9qG44MD5I2JvI12du8zI1bgdQ+l/KsX +kTfbGjUvhOLOlVNWVQDpL+YMIrGqgBYxy5TUNgrAcRtwpNdS2KkF5otSmMweVb5k +hoUVv3u8UxQH/WWbNhHq1RrIlg/0rBUfi/ziShYFSB7U+aLx5DxPphTFBiDquQGp +tB+FC4JvnukDStFihZCZ1R8CAwEAAaOCASMwggEfMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIB +FiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAdBgNVHQ4E +FgQUFPblizG2RYBKTG38woeJyjbDkGIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov +L2NybC5nbG9iYWxzaWduLm5ldC9yb290LmNybDA+BggrBgEFBQcBAQQyMDAwLgYI +KwYBBQUHMAGGImh0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjEwHwYD +VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQADggEB +AL7IG0l+k4LkcpI+a/kvZsSRwSM4uA6zGX34e78A2oytr8RG8bJwVb8+AHMUD+Xe +2kYdh/Uj/waQXfqR0OgxQXL9Ct4ZM+JlR1avsNKXWL5AwYXAXCOB3J5PW2XOck7H +Zw0vRbGQhjWjQx+B4KOUFg1b3ov/z6Xkr3yaCfRQhXh7KC0Bc0RXPPG5Nv5lCW+z +tbbg0zMm3kyfQITRusMSg6IBsDJqOnjaiaKQRcXiD0Sk43ZXb2bUKMxC7+Td3QL4 +RyHcWJbQ7YylLTS/x+jxWIcOQ0oO5/54t5PTQ14neYhOz9x4gUk2AYAW6d1vePwb +hcC8roQwkHT7HvfYBoc74FM= +-----END CERTIFICATE-----` + +var globalSignRoot = `-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE-----` + +var moipLeafCert = `-----BEGIN CERTIFICATE----- +MIIGQDCCBSigAwIBAgIRAPe/cwh7CUWizo8mYSDavLIwDQYJKoZIhvcNAQELBQAw +gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD +VQQDEy9DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl +ciBDQTAeFw0xMzA4MTUwMDAwMDBaFw0xNDA4MTUyMzU5NTlaMIIBQjEXMBUGA1UE +BRMOMDg3MTg0MzEwMDAxMDgxEzARBgsrBgEEAYI3PAIBAxMCQlIxGjAYBgsrBgEE +AYI3PAIBAhMJU2FvIFBhdWxvMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlv +bjELMAkGA1UEBhMCQlIxETAPBgNVBBETCDAxNDUyMDAwMRIwEAYDVQQIEwlTYW8g +UGF1bG8xEjAQBgNVBAcTCVNhbyBQYXVsbzEtMCsGA1UECRMkQXZlbmlkYSBCcmln +YWRlaXJvIEZhcmlhIExpbWEgLCAyOTI3MR0wGwYDVQQKExRNb2lwIFBhZ2FtZW50 +b3MgUy5BLjENMAsGA1UECxMETU9JUDEYMBYGA1UECxMPU1NMIEJsaW5kYWRvIEVW +MRgwFgYDVQQDEw9hcGkubW9pcC5jb20uYnIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDN0b9x6TrXXA9hPCF8/NjqGJ++2D4LO4ZiMFTjs0VwpXy2Y1Oe +s74/HuiLGnAHxTmAtV7IpZMibiOcTxcnDYp9oEWkf+gR+hZvwFZwyOBC7wyb3SR3 +UvV0N1ZbEVRYpN9kuX/3vjDghjDmzzBwu8a/T+y5JTym5uiJlngVAWyh/RjtIvYi ++NVkQMbyVlPGkoCe6c30pH8DKYuUCZU6DHjUsPTX3jAskqbhDSAnclX9iX0p2bmw +KVBc+5Vh/2geyzDuquF0w+mNIYdU5h7uXvlmJnf3d2Cext5dxdL8/jezD3U0dAqI +pYSKERbyxSkJWxdvRlhdpM9YXMJcpc88xNp1AgMBAAGjggHcMIIB2DAfBgNVHSME +GDAWgBQ52v/KKBSKqHQTCLnkDqnS+n6daTAdBgNVHQ4EFgQU/lXuOa7DMExzZjRj +LQWcMWGZY7swDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw +FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQUB +MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMFYG +A1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JT +QUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBhwYIKwYBBQUH +AQEEezB5MFEGCCsGAQUFBzAChkVodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01P +RE9SU0FFeHRlbmRlZFZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwJAYIKwYB +BQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAvBgNVHREEKDAmgg9hcGku +bW9pcC5jb20uYnKCE3d3dy5hcGkubW9pcC5jb20uYnIwDQYJKoZIhvcNAQELBQAD +ggEBAFoTmPlaDcf+nudhjXHwud8g7/LRyA8ucb+3/vfmgbn7FUc1eprF5sJS1mA+ +pbiTyXw4IxcJq2KUj0Nw3IPOe9k84mzh+XMmdCKH+QK3NWkE9Udz+VpBOBc0dlqC +1RH5umStYDmuZg/8/r652eeQ5kUDcJyADfpKWBgDPYaGtwzKVT4h3Aok9SLXRHx6 +z/gOaMjEDMarMCMw4VUIG1pvNraZrG5oTaALPaIXXpd8VqbQYPudYJ6fR5eY3FeW +H/ofbYFdRcuD26MfBFWE9VGGral9Fgo8sEHffho+UWhgApuQV4/l5fMzxB5YBXyQ +jhuy8PqqZS9OuLilTeLu4a8z2JI= +-----END CERTIFICATE-----` + +var comodoIntermediateSHA384 = `-----BEGIN CERTIFICATE----- +MIIGDjCCA/agAwIBAgIQBqdDgNTr/tQ1taP34Wq92DANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTIwMjEy +MDAwMDAwWhcNMjcwMjExMjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQg +VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAlVbeVLTf1QJJe9FbXKKyHo+cK2JMK40SKPMalaPGEP0p3uGf +CzhAk9HvbpUQ/OGQF3cs7nU+e2PsYZJuTzurgElr3wDqAwB/L3XVKC/sVmePgIOj +vdwDmZOLlJFWW6G4ajo/Br0OksxgnP214J9mMF/b5pTwlWqvyIqvgNnmiDkBfBzA +xSr3e5Wg8narbZtyOTDr0VdVAZ1YEZ18bYSPSeidCfw8/QpKdhQhXBZzQCMZdMO6 +WAqmli7eNuWf0MLw4eDBYuPCGEUZUaoXHugjddTI0JYT/8ck0YwLJ66eetw6YWNg +iJctXQUL5Tvrrs46R3N2qPos3cCHF+msMJn4HwIDAQABo4IBaTCCAWUwHwYDVR0j +BBgwFoAUu69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFDna/8ooFIqodBMI +ueQOqdL6fp1pMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMD4G +A1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5j +b21vZG8uY29tL0NQUzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggr +BgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29t +L0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz +cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAERCnUFRK0iIXZebeV4R +AUpSGXtBLMeJPNBy3IX6WK/VJeQT+FhlZ58N/1eLqYVeyqZLsKeyLeCMIs37/3mk +jCuN/gI9JN6pXV/kD0fQ22YlPodHDK4ixVAihNftSlka9pOlk7DgG4HyVsTIEFPk +1Hax0VtpS3ey4E/EhOfUoFDuPPpE/NBXueEoU/1Tzdy5H3pAvTA/2GzS8+cHnx8i +teoiccsq8FZ8/qyo0QYPFBRSTP5kKwxpKrgNUG4+BAe/eiCL+O5lCeHHSQgyPQ0o +fkkdt0rvAucNgBfIXOBhYsvss2B5JdoaZXOcOBCgJjqwyBZ9kzEi7nQLiMBciUEA +KKlHMd99SUWa9eanRRrSjhMQ34Ovmw2tfn6dNVA0BM7pINae253UqNpktNEvWS5e +ojZh1CSggjMziqHRbO9haKPl0latxf1eYusVqHQSTC8xjOnB3xBLAer2VBvNfzu9 +XJ/B288ByvK6YBIhMe2pZLiySVgXbVrXzYxtvp5/4gJYp9vDLVj2dAZqmvZh+fYA +tmnYOosxWd2R5nwnI4fdAw+PKowegwFOAWEMUnNt/AiiuSpm5HZNMaBWm9lTjaK2 +jwLI5jqmBNFI+8NKAnb9L9K8E7bobTQk+p0pisehKxTxlgBzuRPpwLk6R1YCcYAn +pLwltum95OmYdBbxN4SBB7SC +-----END CERTIFICATE-----` + +const comodoRSAAuthority = `-----BEGIN CERTIFICATE----- +MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow +gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD +VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw +AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6 +2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr +ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt +4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq +m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/ +vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT +8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE +IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO +KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO +GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/ +s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g +JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD +AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9 +MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy +bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6 +Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ +zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj +Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY +Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5 +B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx +PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR +pu/xO28QOG8= +-----END CERTIFICATE-----` + +const addTrustRoot = `-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE-----` + +const selfSigned = `-----BEGIN CERTIFICATE----- +MIIC/DCCAeSgAwIBAgIRAK0SWRVmi67xU3z0gkgY+PkwDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTkxNjMzNDdaFw0xNzA4MTkxNjMz +NDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDWkm1kdCwxyKEt6OTmZitkmLGH8cQu9z7rUdrhW8lWNm4kh2SuaUWP +pscBjda5iqg51aoKuWJR2rw6ElDne+X5eit2FT8zJgAU8v39lMFjbaVZfS9TFOYF +w0Tk0Luo/PyKJpZnwhsP++iiGQiteJbndy8aLKmJ2MpLfpDGIgxEIyNb5dgoDi0D +WReDCpE6K9WDYqvKVGnQ2Jvqqra6Gfx0tFkuqJxQuqA8aUOlPHcCH4KBZdNEoXdY +YL3E4dCAh0YiDs80wNZx4cHqEM3L8gTEFqW2Tn1TSuPZO6gjJ9QPsuUZVjaMZuuO +NVxqLGujZkDzARhC3fBpptMuaAfi20+BAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2C +C2Zvby5leGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQBPvvfnDhsHWt+/cfwdAVim +4EDn+hYOMkTQwU0pouYIvY8QXYkZ8MBxpBtBMK4JhFU+ewSWoBAEH2dCCvx/BDxN +UGTSJHMbsvJHcFvdmsvvRxOqQ/cJz7behx0cfoeHMwcs0/vWv8ms5wHesb5Ek7L0 +pl01FCBGTcncVqr6RK1r4fTpeCCfRIERD+YRJz8TtPH6ydesfLL8jIV40H8NiDfG +vRAvOtNiKtPzFeQVdbRPOskC4rcHyPeiDAMAMixeLi63+CFty4da3r5lRezeedCE +cw3ESZzThBwWqvPOtJdpXdm+r57pDW8qD+/0lY8wfImMNkQAyCUCLg/1Lxt/hrBj +-----END CERTIFICATE-----` + +const issuerSubjectMatchRoot = `-----BEGIN CERTIFICATE----- +MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE +ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNhMB4XDTE1MDEwMTAwMDAwMFoXDTI1 +MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNh +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1 +siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw ++QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD +JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw +FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE +EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAb4TfSeCZ1HFmHTKG +VsvqWmsOAGrRWm4fBiMH/8vRGnTkJEMLqiqgc3Ulgry/P6n4SIis7TqUOw3TiMhn +RGEz33Fsxa/tFoy/gvlJu+MqB1M2NyV33pGkdwl/b7KRWMQFieqO+uE7Ge/49pS3 +eyfm5ITdK/WT9TzYhsU4AVZcn20= +-----END CERTIFICATE-----` + +const issuerSubjectMatchLeaf = `-----BEGIN CERTIFICATE----- +MIICODCCAaGgAwIBAgIJAOjwnT/iW+qmMA0GCSqGSIb3DQEBCwUAMCMxDzANBgNV +BAoTBkdvbGFuZzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xNTAxMDEwMDAwMDBaFw0y +NTAxMDEwMDAwMDBaMCAxDzANBgNVBAoTBkdvbGFuZzENMAsGA1UEAxMETGVhZjCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA20Z9ky4SJwZIvAYoIat+xLaiXf4e +UkWIejZHpQgNkkJbwoHAvpd5mED7T20U/SsTi8KlLmfY1Ame1iI4t0oLdHMrwjTx +0ZPlltl0e/NYn2xhPMCwQdTZKyskI3dbHDu9dV3OIFTPoWOHHR4kxPMdGlCLqrYU +Q+2Xp3Vi9BTIUtcCAwEAAaN3MHUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBCfkRYf +Q0M+SabebbaA159gMBsGA1UdIwQUMBKAEEA31wH7QC+4HH5UBCeMWQEwDQYJKoZI +hvcNAQELBQADgYEAjYYF2on1HcUWFEG5NIcrXDiZ49laW3pb3gtcCEUJbxydMV8I +ynqjmdqDCyK+TwI1kU5dXDe/iSJYfTB20i/QoO53nnfA1hnr7KBjNWqAm4AagN5k +vEA4PCJprUYmoj3q9MKSSRYDlq5kIbl87mSRR4GqtAwJKxIasvOvULOxziQ= +-----END CERTIFICATE-----` + +const x509v1TestRoot = `-----BEGIN CERTIFICATE----- +MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE +ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENBMB4XDTE1MDEwMTAwMDAwMFoXDTI1 +MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENB +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1 +siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw ++QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD +JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw +FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE +EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAcIwqeNUpQr9cOcYm +YjpGpYkQ6b248xijCK7zI+lOeWN89zfSXn1AvfsC9pSdTMeDklWktbF/Ad0IN8Md +h2NtN34ard0hEfHc8qW8mkXdsysVmq6cPvFYaHz+dBtkHuHDoy8YQnC0zdN/WyYB +/1JmacUUofl+HusHuLkDxmadogI= +-----END CERTIFICATE-----` + +const x509v1TestIntermediate = `-----BEGIN CERTIFICATE----- +MIIByjCCATMCCQCCdEMsT8ykqTANBgkqhkiG9w0BAQsFADAjMQ8wDQYDVQQKEwZH +b2xhbmcxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTUwMTAxMDAwMDAwWhcNMjUwMTAx +MDAwMDAwWjAwMQ8wDQYDVQQKEwZHb2xhbmcxHTAbBgNVBAMTFFguNTA5djEgaW50 +ZXJtZWRpYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ2QyniAOT+5YL +jeinEBJr3NsC/Q2QJ/VKmgvp+xRxuKTHJiVmxVijmp0vWg8AWfkmuE4p3hXQbbqM +k5yxrk1n60ONhim2L4VXriEvCE7X2OXhTmBls5Ufr7aqIgPMikwjScCXwz8E8qI8 +UxyAhnjeJwMYBU8TuwBImSd4LBHoQQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAIab +DRG6FbF9kL9jb/TDHkbVBk+sl/Pxi4/XjuFyIALlARgAkeZcPmL5tNW1ImHkwsHR +zWE77kJDibzd141u21ZbLsKvEdUJXjla43bdyMmEqf5VGpC3D4sFt3QVH7lGeRur +x5Wlq1u3YDL/j6s1nU2dQ3ySB/oP7J+vQ9V4QeM+ +-----END CERTIFICATE-----` + +const x509v1TestLeaf = `-----BEGIN CERTIFICATE----- +MIICMzCCAZygAwIBAgIJAPo99mqJJrpJMA0GCSqGSIb3DQEBCwUAMDAxDzANBgNV +BAoTBkdvbGFuZzEdMBsGA1UEAxMUWC41MDl2MSBpbnRlcm1lZGlhdGUwHhcNMTUw +MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjArMQ8wDQYDVQQKEwZHb2xhbmcxGDAW +BgNVBAMTD2Zvby5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC +gYEApUh60Z+a5/oKJxG//Dn8CihSo2CJHNIIO3zEJZ1EeNSMZCynaIR6D3IPZEIR ++RG2oGt+f5EEukAPYxwasp6VeZEezoQWJ+97nPCT6DpwLlWp3i2MF8piK2R9vxkG +Z5n0+HzYk1VM8epIrZFUXSMGTX8w1y041PX/yYLxbdEifdcCAwEAAaNaMFgwDgYD +VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNV +HRMBAf8EAjAAMBkGA1UdDgQSBBBFozXe0SnzAmjy+1U6M/cvMA0GCSqGSIb3DQEB +CwUAA4GBADYzYUvaToO/ucBskPdqXV16AaakIhhSENswYVSl97/sODaxsjishKq9 +5R7siu+JnIFotA7IbBe633p75xEnLN88X626N/XRFG9iScLzpj0o0PWXBUiB+fxL +/jt8qszOXCv2vYdUTPNuPqufXLWMoirpuXrr1liJDmedCcAHepY/ +-----END CERTIFICATE-----` + +const ignoreCNWithSANRoot = `-----BEGIN CERTIFICATE----- +MIIDPzCCAiegAwIBAgIIJkzCwkNrPHMwDQYJKoZIhvcNAQELBQAwMDEQMA4GA1UE +ChMHVEVTVElORzEcMBoGA1UEAxMTKipUZXN0aW5nKiogUm9vdCBDQTAeFw0xNTAx +MDEwMDAwMDBaFw0yNTAxMDEwMDAwMDBaMDAxEDAOBgNVBAoTB1RFU1RJTkcxHDAa +BgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQC4YAf5YqlXGcikvbMWtVrNICt+V/NNWljwfvSKdg4Inm7k6BwW +P6y4Y+n4qSYIWNU4iRkdpajufzctxQCO6ty13iw3qVktzcC5XBIiS6ymiRhhDgnY +VQqyakVGw9MxrPwdRZVlssUv3Hmy6tU+v5Ok31SLY5z3wKgYWvSyYs0b8bKNU8kf +2FmSHnBN16lxGdjhe3ji58F/zFMr0ds+HakrLIvVdFcQFAnQopM8FTHpoWNNzGU3 +KaiO0jBbMFkd6uVjVnuRJ+xjuiqi/NWwiwQA+CEr9HKzGkxOF8nAsHamdmO1wW+w +OsCrC0qWQ/f5NTOVATTJe0vj88OMTvo3071VAgMBAAGjXTBbMA4GA1UdDwEB/wQE +AwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUw +AwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOC +AQEAGOn3XjxHyHbXLKrRmpwV447B7iNBXR5VlhwOgt1kWaHDL2+8f/9/h0HMkB6j +fC+/yyuYVqYuOeavqMGVrh33D2ODuTQcFlOx5lXukP46j3j+Lm0jjZ1qNX7vlP8I +VlUXERhbelkw8O4oikakwIY9GE8syuSgYf+VeBW/lvuAZQrdnPfabxe05Tre6RXy +nJHMB1q07YHpbwIkcV/lfCE9pig2nPXTLwYZz9cl46Ul5RCpPUi+IKURo3x8y0FU +aSLjI/Ya0zwUARMmyZ3RRGCyhIarPb20mKSaMf1/Nb23pS3k1QgmZhk5pAnXYsWu +BJ6bvwEAasFiLGP6Zbdmxb2hIA== +-----END CERTIFICATE-----` + +const ignoreCNWithSANLeaf = `-----BEGIN CERTIFICATE----- +MIIDaTCCAlGgAwIBAgIJAONakvRTxgJhMA0GCSqGSIb3DQEBCwUAMDAxEDAOBgNV +BAoTB1RFU1RJTkcxHDAaBgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwHhcNMTUw +MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjAsMRAwDgYDVQQKEwdURVNUSU5HMRgw +FgYDVQQDEw9mb28uZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDBqskp89V/JMIBBqcauKSOVLcMyIE/t0jgSWVrsI4sksBTabLsfMdS +ui2n+dHQ1dRBuw3o4g4fPrWwS3nMnV3pZUHEn2TPi5N1xkjTaxObXgKIY2GKmFP3 +rJ9vYqHT6mT4K93kCHoRcmJWWySc7S3JAOhTcdB4G+tIdQJN63E+XRYQQfNrn5HZ +hxQoOzaguHFx+ZGSD4Ntk6BSZz5NfjqCYqYxe+iCpTpEEYhIpi8joSPSmkTMTxBW +S1W2gXbYNQ9KjNkGM6FnQsUJrSPMrWs4v3UB/U88N5LkZeF41SqD9ySFGwbGajFV +nyzj12+4K4D8BLhlOc0Eo/F/8GwOwvmxAgMBAAGjgYkwgYYwDgYDVR0PAQH/BAQD +AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAA +MBkGA1UdDgQSBBCjeab27q+5pV43jBGANOJ1MBsGA1UdIwQUMBKAEEA31wH7QC+4 +HH5UBCeMWQEwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAGZfZ +ErTVxxpIg64s22mQpXSk/72THVQsfsKHzlXmztM0CJzH8ccoN67ZqKxJCfdiE/FI +Emb6BVV4cGPeIKpcxaM2dwX/Y+Y0JaxpQJvqLxs+EByRL0gPP3shgg86WWCjYLxv +AgOn862d/JXGDrC9vIlQ/DDQcyL5g0JV5UjG2G9TUigbnrXxBw7BoWK6wmoSaHnR +sZKEHSs3RUJvm7qqpA9Yfzm9jg+i9j32zh1xFacghAOmFRFXa9eCVeigZ/KK2mEY +j2kBQyvnyKsXHLAKUoUOpd6t/1PHrfXnGj+HmzZNloJ/BZ1kiWb4eLvMljoLGkZn +xZbqP3Krgjj4XNaXjg== +-----END CERTIFICATE-----` + +const excludedNamesLeaf = `-----BEGIN CERTIFICATE----- +MIID4DCCAsigAwIBAgIHDUSFtJknhzANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU +MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 +ICgzNzM0NTE1NTYyODA2Mzk3KTEhMB8GA1UEAwwYSW50ZXJtZWRpYXRlIENBIGZv +ciAzMzkyMB4XDTE3MDIwODIxMTUwNFoXDTE4MDIwODIwMjQ1OFowgZAxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlMb3MgR2F0b3Mx +FDASBgNVBAoMC05ldGZsaXggSW5jMS0wKwYDVQQLDCRQbGF0Zm9ybSBTZWN1cml0 +eSAoMzczNDUxNTc0ODUwMjY5NikxEzARBgNVBAMMCjE3Mi4xNi4wLjEwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ0oP1bMv6bOeqcKbzinnGpNOpenhA +zdFFsgea62znWsH3Wg4+1Md8uPCqlaQIsaJQKZHc50eKD3bg0Io7c6kxHkBQr1b8 +Q7cGeK3CjdqG3NwS/aizzrLKOwL693hFwwy7JY7GGCvogbhyQRKn6iV0U9zMm7bu +/9pQVV/wx8u01u2uAlLttjyQ5LJkxo5t8cATFVqxdN5J9eY//VSDiTwXnlpQITBP +/Ow+zYuZ3kFlzH3CtCOhOEvNG3Ar1NvP3Icq35PlHV+Eki4otnKfixwByoiGpqCB +UEIY04VrZJjwBxk08y/3jY2B3VLYGgi+rryyCxIqkB7UpSNPMMWSG4UpAgMBAAGj +LzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0RBBYwFIIMYmVuZGVyLmxvY2FshwSsEAAB +MA0GCSqGSIb3DQEBCwUAA4IBAQCLW3JO8L7LKByjzj2RciPjCGH5XF87Wd20gYLq +sNKcFwCIeyZhnQy5aZ164a5G9AIk2HLvH6HevBFPhA9Ivmyv/wYEfnPd1VcFkpgP +hDt8MCFJ8eSjCyKdtZh1MPMLrLVymmJV+Rc9JUUYM9TIeERkpl0rskcO1YGewkYt +qKlWE+0S16+pzsWvKn831uylqwIb8ANBPsCX4aM4muFBHavSWAHgRO+P+yXVw8Q+ +VQDnMHUe5PbZd1/+1KKVs1K/CkBCtoHNHp1d/JT+2zUQJphwja9CcgfFdVhSnHL4 +oEEOFtqVMIuQfR2isi08qW/JGOHc4sFoLYB8hvdaxKWSE19A +-----END CERTIFICATE-----` + +const excludedNamesIntermediate = `-----BEGIN CERTIFICATE----- +MIIDzTCCArWgAwIBAgIHDUSFqYeczDANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU +MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 +ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBmb3IgMzM5 +MjAeFw0xNzAyMDgyMTE1MDRaFw0xODAyMDgyMDI0NThaMIGeMQswCQYDVQQGEwJV +UzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJTG9zIEdhdG9zMRQwEgYD +VQQKDAtOZXRmbGl4IEluYzEtMCsGA1UECwwkUGxhdGZvcm0gU2VjdXJpdHkgKDM3 +MzQ1MTU1NjI4MDYzOTcpMSEwHwYDVQQDDBhJbnRlcm1lZGlhdGUgQ0EgZm9yIDMz +OTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCOyEs6tJ/t9emQTvlx +3FS7uJSou5rKkuqVxZdIuYQ+B2ZviBYUnMRT9bXDB0nsVdKZdp0hdchdiwNXDG/I +CiWu48jkcv/BdynVyayOT+0pOJSYLaPYpzBx1Pb9M5651ct9GSbj6Tz0ChVonoIE +1AIZ0kkebucZRRFHd0xbAKVRKyUzPN6HJ7WfgyauUp7RmlC35wTmrmARrFohQLlL +7oICy+hIQePMy9x1LSFTbPxZ5AUUXVC3eUACU3vLClF/Xs8XGHebZpUXCdMQjOGS +nq1eFguFHR1poSB8uSmmLqm4vqUH9CDhEgiBAC8yekJ8//kZQ7lUEqZj3YxVbk+Y +E4H5AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB +ADxrnmNX5gWChgX9K5fYwhFDj5ofxZXAKVQk+WjmkwMcmCx3dtWSm++Wdksj/ZlA +V1cLW3ohWv1/OAZuOlw7sLf98aJpX+UUmIYYQxDubq+4/q7VA7HzEf2k/i/oN1NI +JgtrhpPcZ/LMO6k7DYx0qlfYq8pTSfd6MI4LnWKgLc+JSPJJjmvspgio2ZFcnYr7 +A264BwLo6v1Mos1o1JUvFFcp4GANlw0XFiWh7JXYRl8WmS5DoouUC+aNJ3lmyF6z +LbIjZCSfgZnk/LK1KU1j91FI2bc2ULYZvAC1PAg8/zvIgxn6YM2Q7ZsdEgWw0FpS +zMBX1/lk4wkFckeUIlkD55Y= +-----END CERTIFICATE-----` + +const excludedNamesRoot = `-----BEGIN CERTIFICATE----- +MIIEGTCCAwGgAwIBAgIHDUSFpInn/zANBgkqhkiG9w0BAQsFADCBozELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU +MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 +ICgzNzMxNTA5NDM3NDYyNDg1KTEmMCQGA1UEAwwdTmFtZSBDb25zdHJhaW50cyBU +ZXN0IFJvb3QgQ0EwHhcNMTcwMjA4MjExNTA0WhcNMTgwMjA4MjAyNDU4WjCBmTEL +MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBH +YXRvczEUMBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNl +Y3VyaXR5ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBm +b3IgMzM5MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJymcnX29ekc +7+MLyr8QuAzoHWznmGdDd2sITwWRjM89/21cdlHCGKSpULUNdFp9HDLWvYECtxt+ +8TuzKiQz7qAerzGUT1zI5McIjHy0e/i4xIkfiBiNeTCuB/N9QRbZlcfM80ErkaA4 +gCAFK8qZAcWkHIl6e+KaQFMPLKk9kckgAnVDHEJe8oLNCogCJ15558b65g05p9eb +5Lg+E98hoPRTQaDwlz3CZPfTTA2EiEZInSi8qzodFCbTpJUVTbiVUH/JtVjlibbb +smdcx5PORK+8ZJkhLEh54AjaWOX4tB/7Tkk8stg2VBmrIARt/j4UVj7cTrIWU3bV +m8TwHJG+YgsCAwEAAaNaMFgwDwYDVR0TAQH/BAUwAwEB/zBFBgNVHR4EPjA8oBww +CocICgEAAP//AAAwDoIMYmVuZGVyLmxvY2FsoRwwCocICgEAAP//AAAwDoIMYmVu +ZGVyLmxvY2FsMA0GCSqGSIb3DQEBCwUAA4IBAQAMjbheffPxtSKSv9NySW+8qmHs +n7Mb5GGyCFu+cMZSoSaabstbml+zHEFJvWz6/1E95K4F8jKhAcu/CwDf4IZrSD2+ +Hee0DolVSQhZpnHgPyj7ZATz48e3aJaQPUlhCEOh0wwF4Y0N4FV0t7R6woLylYRZ +yU1yRHUqUYpN0DWFpsPbBqgM6uUAVO2ayBFhPgWUaqkmSbZ/Nq7isGvknaTmcIwT +6mOAFN0qFb4RGzfGJW7x6z7KCULS7qVDp6fU3tRoScHFEgRubks6jzQ1W5ooSm4o ++NQCZDd5eFeU8PpNX7rgaYE4GPq+EEmLVCBYmdctr8QVdqJ//8Xu3+1phjDy +-----END CERTIFICATE-----` + +const invalidCNRoot = `-----BEGIN CERTIFICATE----- +MIIBFjCBvgIJAIsu4r+jb70UMAoGCCqGSM49BAMCMBQxEjAQBgNVBAsMCVRlc3Qg +cm9vdDAeFw0xODA3MTExODMyMzVaFw0yODA3MDgxODMyMzVaMBQxEjAQBgNVBAsM +CVRlc3Qgcm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF6oDgMg0LV6YhPj +QXaPXYCc2cIyCdqp0ROUksRz0pOLTc5iY2nraUheRUD1vRRneq7GeXOVNn7uXONg +oCGMjNwwCgYIKoZIzj0EAwIDRwAwRAIgDSiwgIn8g1lpruYH0QD1GYeoWVunfmrI +XzZZl0eW/ugCICgOfXeZ2GGy3wIC0352BaC3a8r5AAb2XSGNe+e9wNN6 +-----END CERTIFICATE-----` + +const validCNWithoutSAN = `-----BEGIN CERTIFICATE----- +MIIBJzCBzwIUB7q8t9mrDAL+UB1OFaMN5BEWFKQwCgYIKoZIzj0EAwIwFDESMBAG +A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4NDcyNFoXDTI4MDcwODE4NDcyNFow +GjEYMBYGA1UEAwwPZm9vLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D +AQcDQgAEp6Z8IjOnR38Iky1fYTUu2kVndvKXcxiwARJKGtW3b0E8uwVp9AZd/+sr +p4ULTPdFToFAeqnGHbu62bkms8pQkDAKBggqhkjOPQQDAgNHADBEAiBTbNe3WWFR +cqUYo0sNUuoV+tCTMDJUS+0PWIW4qBqCOwIgFHdLDn5PCk9kJpfc0O2qZx03hdq0 +h7olHCpY9yMRiz0= +-----END CERTIFICATE-----` + +const rootWithoutSKID = `-----BEGIN CERTIFICATE----- +MIIBbzCCARSgAwIBAgIQeCkq3C8SOX/JM5PqYTl9cDAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTE5MDIwNDIyNTYzNFoXDTI5MDIwMTIyNTYzNFow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABISm +jGlTr4dLOWT+BCTm2PzWRjk1DpLcSAh+Al8eB1Nc2eBWxYIH9qPirfatvqBOA4c5 +ZwycRpFoaw6O+EmXnVujTDBKMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr +BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBIGA1UdEQQLMAmCB2V4YW1wbGUwCgYI +KoZIzj0EAwIDSQAwRgIhAMaBYWFCjTfn0MNyQ0QXvYT/iIFompkIqzw6wB7qjLrA +AiEA3sn65V7G4tsjZEOpN0Jykn9uiTjqniqn/S/qmv8gIec= +-----END CERTIFICATE-----` + +const leafWithAKID = `-----BEGIN CERTIFICATE----- +MIIBjTCCATSgAwIBAgIRAPCKYvADhKLPaWOtcTu2XYwwCgYIKoZIzj0EAwIwEjEQ +MA4GA1UEChMHQWNtZSBDbzAeFw0xOTAyMDQyMzA2NTJaFw0yOTAyMDEyMzA2NTJa +MBMxETAPBgNVBAoTCEFjbWUgTExDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +Wk5N+/8X97YT6ClFNIE5/4yc2YwKn921l0wrIJEcT2u+Uydm7EqtCJNtZjYMAnBd +Acp/wynpTwC6tBTsxcM0s6NqMGgwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoG +CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUwitfkXg0JglCjW9R +ssWvTAveakIwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNHADBEAiBk +4LpWiWPOIl5PIhX9PDVkmjpre5oyoH/3aYwG8ABYuAIgCeSfbYueOOG2AdXuMqSU +ZZMqeJS7JldLx91sPUArY5A= +-----END CERTIFICATE-----` + +const rootMatchingSKIDMismatchingSubject = `-----BEGIN CERTIFICATE----- +MIIBQjCB6aADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQTAe +Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMBExDzANBgNVBAMTBlJvb3Qg +QTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPK4p1uXq2aAeDtKDHIokg2rTcPM +2gq3N9Y96wiW6/7puBK1+INEW//cO9x6FpzkcsHw/TriAqy4sck/iDAvf9WjMjAw +MA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHQ4EBQQDAQID +MAoGCCqGSM49BAMCA0gAMEUCIQDgtAp7iVHxMnKxZPaLQPC+Tv2r7+DJc88k2SKH +MPs/wQIgFjjNvBoQEl7vSHTcRGCCcFMdlN4l0Dqc9YwGa9fyrQs= +-----END CERTIFICATE-----` + +const rootMismatchingSKIDMatchingSubject = `-----BEGIN CERTIFICATE----- +MIIBNDCB26ADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQjAe +Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMBExDzANBgNVBAMTBlJvb3Qg +QjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI1YRFcIlkWzm9BdEVrIsEQJ2dT6 +qiW8/WV9GoIhmDtX9SEDHospc0Cgm+TeD2QYW2iMrS5mvNe4GSw0Jezg/bOjJDAi +MA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNI +ADBFAiEAukWOiuellx8bugRiwCS5XQ6IOJ1SZcjuZxj76WojwxkCIHqa71qNw8FM +DtA5yoL9M2pDFF6ovFWnaCe+KlzSwAW/ +-----END CERTIFICATE-----` + +const leafMatchingAKIDMatchingIssuer = `-----BEGIN CERTIFICATE----- +MIIBNTCB26ADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQjAe +Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMA8xDTALBgNVBAMTBExlYWYw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASNWERXCJZFs5vQXRFayLBECdnU+qol +vP1lfRqCIZg7V/UhAx6LKXNAoJvk3g9kGFtojK0uZrzXuBksNCXs4P2zoyYwJDAO +BgNVHSMEBzAFgAMBAgMwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNJ +ADBGAiEAnV9XV7a4h0nfJB8pWv+pBUXRlRFA2uZz3mXEpee8NYACIQCWa+wL70GL +ePBQCV1F9sE2q4ZrnsT9TZoNrSe/bMDjzA== +-----END CERTIFICATE-----` + +var unknownAuthorityErrorTests = []struct { + cert string + expected string +}{ + {selfSignedWithCommonName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"test\")"}, + {selfSignedNoCommonNameWithOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"ca\")"}, + {selfSignedNoCommonNameNoOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"serial:0\")"}, +} + +func TestUnknownAuthorityError(t *testing.T) { + for i, tt := range unknownAuthorityErrorTests { + der, _ := pem.Decode([]byte(tt.cert)) + if der == nil { + t.Errorf("#%d: Unable to decode PEM block", i) + } + c, err := ParseCertificate(der.Bytes) + if err != nil { + t.Errorf("#%d: Unable to parse certificate -> %v", i, err) + } + uae := &UnknownAuthorityError{ + Cert: c, + hintErr: fmt.Errorf("empty"), + hintCert: c, + } + actual := uae.Error() + if actual != tt.expected { + t.Errorf("#%d: UnknownAuthorityError.Error() response invalid actual: %s expected: %s", i, actual, tt.expected) + } + } +} + +var nameConstraintTests = []struct { + constraint, domain string + expectError bool + shouldMatch bool +}{ + {"", "anything.com", false, true}, + {"example.com", "example.com", false, true}, + {"example.com.", "example.com", true, false}, + {"example.com", "example.com.", true, false}, + {"example.com", "ExAmPle.coM", false, true}, + {"example.com", "exampl1.com", false, false}, + {"example.com", "www.ExAmPle.coM", false, true}, + {"example.com", "sub.www.ExAmPle.coM", false, true}, + {"example.com", "notexample.com", false, false}, + {".example.com", "example.com", false, false}, + {".example.com", "www.example.com", false, true}, + {".example.com", "www..example.com", true, false}, +} + +func TestNameConstraints(t *testing.T) { + for i, test := range nameConstraintTests { + result, err := matchDomainConstraint(test.domain, test.constraint) + + if err != nil && !test.expectError { + t.Errorf("unexpected error for test #%d: domain=%s, constraint=%s, err=%s", i, test.domain, test.constraint, err) + continue + } + + if err == nil && test.expectError { + t.Errorf("unexpected success for test #%d: domain=%s, constraint=%s", i, test.domain, test.constraint) + continue + } + + if result != test.shouldMatch { + t.Errorf("unexpected result for test #%d: domain=%s, constraint=%s, result=%t", i, test.domain, test.constraint, result) + } + } +} + +const selfSignedWithCommonName = `-----BEGIN CERTIFICATE----- +MIIDCjCCAfKgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL +MAkGA1UEAxMCY2EwHhcNMTYwODI4MTcwOTE4WhcNMjEwODI3MTcwOTE4WjAcMQsw +CQYDVQQKEwJjYTENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAOH55PfRsbvmcabfLLko1w/yuapY/hk13Cgmc3WE/Z1ZStxGiVxY +gQVH9n4W/TbUsrep/TmcC4MV7xEm5252ArcgaH6BeQ4QOTFj/6Jx0RT7U/ix+79x +8RRysf7OlzNpGIctwZEM7i/G+0ZfqX9ULxL/EW9tppSxMX1jlXZQarnU7BERL5cH ++G2jcbU9H28FXYishqpVYE9L7xrXMm61BAwvGKB0jcVW6JdhoAOSfQbbgp7JjIlq +czXqUsv1UdORO/horIoJptynTvuARjZzyWatya6as7wyOgEBllE6BjPK9zpn+lp3 +tQ8dwKVqm/qBPhIrVqYG/Ec7pIv8mJfYabMCAwEAAaNZMFcwDgYDVR0PAQH/BAQD +AgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA +MAoGA1UdDgQDBAEAMAwGA1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAAAM +XMFphzq4S5FBcRdB2fRrmcoz+jEROBWvIH/1QUJeBEBz3ZqBaJYfBtQTvqCA5Rjw +dxyIwVd1W3q3aSulM0tO62UCU6L6YeeY/eq8FmpD7nMJo7kCrXUUAMjxbYvS3zkT +v/NErK6SgWnkQiPJBZNX1Q9+aSbLT/sbaCTdbWqcGNRuLGJkmqfIyoxRt0Hhpqsx +jP5cBaVl50t4qoCuVIE9cOucnxYXnI7X5HpXWvu8Pfxo4SwVjb1az8Fk5s8ZnxGe +fPB6Q3L/pKBe0SEe5GywpwtokPLB3lAygcuHbxp/1FlQ1NQZqq+vgXRIla26bNJf +IuYkJwt6w+LH/9HZgf8= +-----END CERTIFICATE-----` +const selfSignedNoCommonNameWithOrgName = `-----BEGIN CERTIFICATE----- +MIIC+zCCAeOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL +MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxMzQ4WhcNMjEwODI3MTgxMzQ4WjANMQsw +CQYDVQQKEwJjYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL5EjrUa +7EtOMxWiIgTzp2FlQvncPsG329O3l3uNGnbigb8TmNMw2M8UhoDjd84pnU5RAfqd +8t5TJyw/ybnIKBN131Q2xX+gPQ0dFyMvcO+i1CUgCxmYZomKVA2MXO1RD1hLTYGS +gOVjc3no3MBwd8uVQp0NStqJ1QvLtNG4Uy+B28qe+ZFGGbjGqx8/CU4A8Szlpf7/ +xAZR8w5qFUUlpA2LQYeHHJ5fQVXw7kyL1diNrKNi0G3qcY0IrBh++hT+hnEEXyXu +g8a0Ux18hoE8D6rAr34rCZl6AWfqW5wjwm+N5Ns2ugr9U4N8uCKJYMPHb2CtdubU +46IzVucpTfGLdaMCAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgOoMB0GA1UdJQQWMBQG +CCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMAoGA1UdDgQDBAEAMAwG +A1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAEn5SgVpJ3zjsdzPqK7Qd/sB +bYd1qtPHlrszjhbHBg35C6mDgKhcv4o6N+fuC+FojZb8lIxWzJtvT9pQbfy/V6u3 +wOb816Hm71uiP89sioIOKCvSAstj/p9doKDOUaKOcZBTw0PS2m9eja8bnleZzBvK +rD8cNkHf74v98KvBhcwBlDifVzmkWzMG6TL1EkRXUyLKiWgoTUFSkCDV927oXXMR +DKnszq+AVw+K8hbeV2A7GqT7YfeqOAvSbatTDnDtKOPmlCnQui8A149VgZzXv7eU +29ssJSqjUPyp58dlV6ZuynxPho1QVZUOQgnJToXIQ3/5vIvJRXy52GJCs4/Gh/w= +-----END CERTIFICATE-----` +const selfSignedNoCommonNameNoOrgName = `-----BEGIN CERTIFICATE----- +MIIC7jCCAdagAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL +MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxOTQ1WhcNMjEwODI3MTgxOTQ1WjAAMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp3E+Jl6DpgzogHUW/i/AAcCM +fnNJLOamNVKFGmmxhb4XTHxRaWoTzrlsyzIMS0WzivvJeZVe6mWbvuP2kZanKgIz +35YXRTR9HbqkNTMuvnpUESzWxbGWE2jmt2+a/Jnz89FS4WIYRhF7nI2z8PvZOfrI +2gETTT2tEpoF2S4soaYfm0DBeT8K0/rogAaf+oeUS6V+v3miRcAooJgpNJGu9kqm +S0xKPn1RCFVjpiRd6YNS0xZirjYQIBMFBvoSoHjaOdgJptNRBprYPOxVJ/ItzGf0 +kPmzPFCx2tKfxV9HLYBPgxi+fP3IIx8aIYuJn8yReWtYEMYU11hDPeAFN5Gm+wID +AQABo1kwVzAOBgNVHQ8BAf8EBAMCA6gwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG +AQUFBwMBMAwGA1UdEwEB/wQCMAAwCgYDVR0OBAMEAQAwDAYDVR0jBAUwA4ABADAN +BgkqhkiG9w0BAQsFAAOCAQEATZVOFeiCpPM5QysToLv+8k7Rjoqt6L5IxMUJGEpq +4ENmldmwkhEKr9VnYEJY3njydnnTm97d9vOfnLj9nA9wMBODeOO3KL2uJR2oDnmM +9z1NSe2aQKnyBb++DM3ZdikpHn/xEpGV19pYKFQVn35x3lpPh2XijqRDO/erKemb +w67CoNRb81dy+4Q1lGpA8ORoLWh5fIq2t2eNGc4qB8vlTIKiESzAwu7u3sRfuWQi +4R+gnfLd37FWflMHwztFbVTuNtPOljCX0LN7KcuoXYlr05RhQrmoN7fQHsrZMNLs +8FVjHdKKu+uPstwd04Uy4BR/H2y1yerN9j/L6ZkMl98iiA== +-----END CERTIFICATE-----` + +const criticalExtRoot = `-----BEGIN CERTIFICATE----- +MIIBqzCCAVGgAwIBAgIJAJ+mI/85cXApMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT +A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw +MDBaMB0xDDAKBgNVBAoTA09yZzENMAsGA1UEAxMEUm9vdDBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABJGp9joiG2QSQA+1FczEDAsWo84rFiP3GTL+n+ugcS6TyNib +gzMsdbJgVi+a33y0SzLZxB+YvU3/4KTk8yKLC+2jejB4MA4GA1UdDwEB/wQEAwIC +BDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB +/zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATAbBgNVHSMEFDASgBBAN9cB+0Av +uBx+VAQnjFkBMAoGCCqGSM49BAMCA0gAMEUCIFeSV00fABFceWR52K+CfIgOHotY +FizzGiLB47hGwjMuAiEA8e0um2Kr8FPQ4wmFKaTRKHMaZizCGl3m+RG5QsE1KWo= +-----END CERTIFICATE-----` + +const criticalExtIntermediate = `-----BEGIN CERTIFICATE----- +MIIBszCCAVmgAwIBAgIJAL2kcGZKpzVqMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT +A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw +MDBaMCUxDDAKBgNVBAoTA09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMFkwEwYH +KoZIzj0CAQYIKoZIzj0DAQcDQgAESqVq92iPEq01cL4o99WiXDc5GZjpjNlzMS1n +rk8oHcVDp4tQRRQG3F4A6dF1rn/L923ha3b0fhDLlAvXZB+7EKN6MHgwDgYDVR0P +AQH/BAQDAgIEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMB +Af8EBTADAQH/MBkGA1UdDgQSBBCMGmiotXbbXVd7H40UsgajMBsGA1UdIwQUMBKA +EEA31wH7QC+4HH5UBCeMWQEwCgYIKoZIzj0EAwIDSAAwRQIhAOhhNRb6KV7h3wbE +cdap8bojzvUcPD78fbsQPCNw1jPxAiBOeAJhlTwpKn9KHpeJphYSzydj9NqcS26Y +xXbdbm27KQ== +-----END CERTIFICATE-----` + +const criticalExtLeafWithExt = `-----BEGIN CERTIFICATE----- +MIIBxTCCAWugAwIBAgIJAJZAUtw5ccb1MAoGCCqGSM49BAMCMCUxDDAKBgNVBAoT +A09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMB4XDTE1MDEwMTAwMDAwMFoXDTI1 +MDEwMTAwMDAwMFowJDEMMAoGA1UEChMDT3JnMRQwEgYDVQQDEwtleGFtcGxlLmNv +bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF3ABa2+B6gUyg6ayCaRQWYY/+No +6PceLqEavZNUeVNuz7bS74Toy8I7R3bGMkMgbKpLSPlPTroAATvebTXoBaijgYQw +gYEwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD +AjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBRNtBL2vq8nCV3qVp7ycxMMBsGA1Ud +IwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwCgYDUQMEAQH/BAAwCgYIKoZIzj0EAwID +SAAwRQIgVjy8GBgZFiagexEuDLqtGjIRJQtBcf7lYgf6XFPH1h4CIQCT6nHhGo6E +I+crEm4P5q72AnA/Iy0m24l7OvLuXObAmg== +-----END CERTIFICATE-----` + +const criticalExtIntermediateWithExt = `-----BEGIN CERTIFICATE----- +MIIB2TCCAX6gAwIBAgIIQD3NrSZtcUUwCgYIKoZIzj0EAwIwHTEMMAoGA1UEChMD +T3JnMQ0wCwYDVQQDEwRSb290MB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAw +MFowPTEMMAoGA1UEChMDT3JnMS0wKwYDVQQDEyRJbnRlcm1lZGlhdGUgd2l0aCBD +cml0aWNhbCBFeHRlbnNpb24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtnmzH +mcRm10bdDBnJE7xQEJ25cLCL5okuEphRR0Zneo6+nQZikoh+UBbtt5GV3Dms7LeP +oF5HOplYDCd8wi/wo4GHMIGEMA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggr +BgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQKxdv +UuQZ6sO3XvBsxgNZ3zAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQnjFkBMAoGA1ED +BAEB/wQAMAoGCCqGSM49BAMCA0kAMEYCIQCQzTPd6XKex+OAPsKT/1DsoMsg8vcG +c2qZ4Q0apT/kvgIhAKu2TnNQMIUdcO0BYQIl+Uhxc78dc9h4lO+YJB47pHGx +-----END CERTIFICATE-----` + +const criticalExtLeaf = `-----BEGIN CERTIFICATE----- +MIIBzzCCAXWgAwIBAgIJANoWFIlhCI9MMAoGCCqGSM49BAMCMD0xDDAKBgNVBAoT +A09yZzEtMCsGA1UEAxMkSW50ZXJtZWRpYXRlIHdpdGggQ3JpdGljYWwgRXh0ZW5z +aW9uMB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAwMFowJDEMMAoGA1UEChMD +T3JnMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH +A0IABG1Lfh8A0Ho2UvZN5H0+ONil9c8jwtC0y0xIZftyQE+Fwr9XwqG3rV2g4M1h +GnJa9lV9MPHg8+b85Hixm0ZSw7SjdzB1MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE +FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAZBgNVHQ4EEgQQ +UNhY4JhezH9gQYqvDMWrWDAbBgNVHSMEFDASgBArF29S5Bnqw7de8GzGA1nfMAoG +CCqGSM49BAMCA0gAMEUCIQClA3d4tdrDu9Eb5ZBpgyC+fU1xTZB0dKQHz6M5fPZA +2AIgN96lM+CPGicwhN24uQI6flOsO3H0TJ5lNzBYLtnQtlc= +-----END CERTIFICATE-----` + +func TestValidHostname(t *testing.T) { + tests := []struct { + host string + validInput, validPattern bool + }{ + {host: "example.com", validInput: true, validPattern: true}, + {host: "eXample123-.com", validInput: true, validPattern: true}, + {host: "-eXample123-.com"}, + {host: ""}, + {host: "."}, + {host: "example..com"}, + {host: ".example.com"}, + {host: "example.com.", validInput: true}, + {host: "*.example.com."}, + {host: "*.example.com", validPattern: true}, + {host: "*foo.example.com"}, + {host: "foo.*.example.com"}, + {host: "exa_mple.com", validInput: true, validPattern: true}, + {host: "foo,bar"}, + {host: "project-dev:us-central1:main"}, + } + for _, tt := range tests { + if got := validHostnamePattern(tt.host); got != tt.validPattern { + t.Errorf("validHostnamePattern(%q) = %v, want %v", tt.host, got, tt.validPattern) + } + if got := validHostnameInput(tt.host); got != tt.validInput { + t.Errorf("validHostnameInput(%q) = %v, want %v", tt.host, got, tt.validInput) + } + } +} + +func generateCert(cn string, isCA bool, issuer *Certificate, issuerKey crypto.PrivateKey) (*Certificate, crypto.PrivateKey, error) { + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, nil, err + } + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit) + + template := &Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{CommonName: cn}, + NotBefore: time.Now().Add(-1 * time.Hour), + NotAfter: time.Now().Add(24 * time.Hour), + + KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature | KeyUsageCertSign, + ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + IsCA: isCA, + } + if issuer == nil { + issuer = template + issuerKey = priv + } + + derBytes, err := CreateCertificate(rand.Reader, template, issuer, priv.Public(), issuerKey) + if err != nil { + return nil, nil, err + } + cert, err := ParseCertificate(derBytes) + if err != nil { + return nil, nil, err + } + + return cert, priv, nil +} + +func TestPathologicalChain(t *testing.T) { + if testing.Short() { + t.Skip("skipping generation of a long chain of certificates in short mode") + } + + // Build a chain where all intermediates share the same subject, to hit the + // path building worst behavior. + roots, intermediates := NewCertPool(), NewCertPool() + + parent, parentKey, err := generateCert("Root CA", true, nil, nil) + if err != nil { + t.Fatal(err) + } + roots.AddCert(parent) + + for i := 1; i < 100; i++ { + parent, parentKey, err = generateCert("Intermediate CA", true, parent, parentKey) + if err != nil { + t.Fatal(err) + } + intermediates.AddCert(parent) + } + + leaf, _, err := generateCert("Leaf", false, parent, parentKey) + if err != nil { + t.Fatal(err) + } + + start := time.Now() + _, err = leaf.Verify(VerifyOptions{ + Roots: roots, + Intermediates: intermediates, + }) + t.Logf("verification took %v", time.Since(start)) + + if err == nil || !strings.Contains(err.Error(), "signature check attempts limit") { + t.Errorf("expected verification to fail with a signature checks limit error; got %v", err) + } +} + +func TestLongChain(t *testing.T) { + if testing.Short() { + t.Skip("skipping generation of a long chain of certificates in short mode") + } + + roots, intermediates := NewCertPool(), NewCertPool() + + parent, parentKey, err := generateCert("Root CA", true, nil, nil) + if err != nil { + t.Fatal(err) + } + roots.AddCert(parent) + + for i := 1; i < 15; i++ { + name := fmt.Sprintf("Intermediate CA #%d", i) + parent, parentKey, err = generateCert(name, true, parent, parentKey) + if err != nil { + t.Fatal(err) + } + intermediates.AddCert(parent) + } + + leaf, _, err := generateCert("Leaf", false, parent, parentKey) + if err != nil { + t.Fatal(err) + } + + start := time.Now() + if _, err := leaf.Verify(VerifyOptions{ + Roots: roots, + Intermediates: intermediates, + }); err != nil { + t.Error(err) + } + t.Logf("verification took %v", time.Since(start)) +} + +func TestSystemRootsError(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Windows does not use (or support) systemRoots") + } + + defer func(oldSystemRoots *CertPool) { systemRoots = oldSystemRoots }(systemRootsPool()) + + opts := VerifyOptions{ + Intermediates: NewCertPool(), + DNSName: "www.google.com", + CurrentTime: time.Unix(1395785200, 0), + } + + if ok := opts.Intermediates.AppendCertsFromPEM([]byte(giag2Intermediate)); !ok { + t.Fatalf("failed to parse intermediate") + } + + leaf, err := certificateFromPEM(googleLeaf) + if err != nil { + t.Fatalf("failed to parse leaf: %v", err) + } + + systemRoots = nil + + _, err = leaf.Verify(opts) + if _, ok := err.(SystemRootsError); !ok { + t.Errorf("error was not SystemRootsError: %v", err) + } +} + +func TestSystemRootsErrorUnwrap(t *testing.T) { + var err1 = errors.New("err1") + err := SystemRootsError{Err: err1} + if !errors.Is(err, err1) { + t.Error("errors.Is failed, wanted success") + } +} diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go new file mode 100644 index 0000000..4304ab5 --- /dev/null +++ b/src/crypto/x509/x509.go @@ -0,0 +1,2203 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package x509 parses X.509-encoded keys and certificates. +package x509 + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rsa" + "crypto/sha1" + "crypto/x509/pkix" + "encoding/asn1" + "encoding/pem" + "errors" + "fmt" + "io" + "math/big" + "net" + "net/url" + "strconv" + "time" + "unicode" + + // Explicitly import these for their crypto.RegisterHash init side-effects. + // Keep these as blank imports, even if they're imported above. + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" +) + +// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo +// in RFC 3280. +type pkixPublicKey struct { + Algo pkix.AlgorithmIdentifier + BitString asn1.BitString +} + +// ParsePKIXPublicKey parses a public key in PKIX, ASN.1 DER form. +// The encoded public key is a SubjectPublicKeyInfo structure +// (see RFC 5280, Section 4.1). +// +// It returns a *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, or +// ed25519.PublicKey. More types might be supported in the future. +// +// This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY". +func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) { + var pki publicKeyInfo + if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil { + if _, err := asn1.Unmarshal(derBytes, &pkcs1PublicKey{}); err == nil { + return nil, errors.New("x509: failed to parse public key (use ParsePKCS1PublicKey instead for this key format)") + } + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("x509: trailing data after ASN.1 of public-key") + } + algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm) + if algo == UnknownPublicKeyAlgorithm { + return nil, errors.New("x509: unknown public key algorithm") + } + return parsePublicKey(algo, &pki) +} + +func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) { + switch pub := pub.(type) { + case *rsa.PublicKey: + publicKeyBytes, err = asn1.Marshal(pkcs1PublicKey{ + N: pub.N, + E: pub.E, + }) + if err != nil { + return nil, pkix.AlgorithmIdentifier{}, err + } + publicKeyAlgorithm.Algorithm = oidPublicKeyRSA + // This is a NULL parameters value which is required by + // RFC 3279, Section 2.3.1. + publicKeyAlgorithm.Parameters = asn1.NullRawValue + case *ecdsa.PublicKey: + publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) + oid, ok := oidFromNamedCurve(pub.Curve) + if !ok { + return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve") + } + publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA + var paramBytes []byte + paramBytes, err = asn1.Marshal(oid) + if err != nil { + return + } + publicKeyAlgorithm.Parameters.FullBytes = paramBytes + case ed25519.PublicKey: + publicKeyBytes = pub + publicKeyAlgorithm.Algorithm = oidPublicKeyEd25519 + default: + return nil, pkix.AlgorithmIdentifier{}, fmt.Errorf("x509: unsupported public key type: %T", pub) + } + + return publicKeyBytes, publicKeyAlgorithm, nil +} + +// MarshalPKIXPublicKey converts a public key to PKIX, ASN.1 DER form. +// The encoded public key is a SubjectPublicKeyInfo structure +// (see RFC 5280, Section 4.1). +// +// The following key types are currently supported: *rsa.PublicKey, *ecdsa.PublicKey +// and ed25519.PublicKey. Unsupported key types result in an error. +// +// This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY". +func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) { + var publicKeyBytes []byte + var publicKeyAlgorithm pkix.AlgorithmIdentifier + var err error + + if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil { + return nil, err + } + + pkix := pkixPublicKey{ + Algo: publicKeyAlgorithm, + BitString: asn1.BitString{ + Bytes: publicKeyBytes, + BitLength: 8 * len(publicKeyBytes), + }, + } + + ret, _ := asn1.Marshal(pkix) + return ret, nil +} + +// These structures reflect the ASN.1 structure of X.509 certificates.: + +type certificate struct { + Raw asn1.RawContent + TBSCertificate tbsCertificate + SignatureAlgorithm pkix.AlgorithmIdentifier + SignatureValue asn1.BitString +} + +type tbsCertificate struct { + Raw asn1.RawContent + Version int `asn1:"optional,explicit,default:0,tag:0"` + SerialNumber *big.Int + SignatureAlgorithm pkix.AlgorithmIdentifier + Issuer asn1.RawValue + Validity validity + Subject asn1.RawValue + PublicKey publicKeyInfo + UniqueId asn1.BitString `asn1:"optional,tag:1"` + SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"` + Extensions []pkix.Extension `asn1:"optional,explicit,tag:3"` +} + +type dsaAlgorithmParameters struct { + P, Q, G *big.Int +} + +type validity struct { + NotBefore, NotAfter time.Time +} + +type publicKeyInfo struct { + Raw asn1.RawContent + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString +} + +// RFC 5280, 4.2.1.1 +type authKeyId struct { + Id []byte `asn1:"optional,tag:0"` +} + +type SignatureAlgorithm int + +const ( + UnknownSignatureAlgorithm SignatureAlgorithm = iota + + MD2WithRSA // Unsupported. + MD5WithRSA // Only supported for signing, not verification. + SHA1WithRSA + SHA256WithRSA + SHA384WithRSA + SHA512WithRSA + DSAWithSHA1 // Unsupported. + DSAWithSHA256 // Unsupported. + ECDSAWithSHA1 + ECDSAWithSHA256 + ECDSAWithSHA384 + ECDSAWithSHA512 + SHA256WithRSAPSS + SHA384WithRSAPSS + SHA512WithRSAPSS + PureEd25519 +) + +func (algo SignatureAlgorithm) isRSAPSS() bool { + switch algo { + case SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS: + return true + default: + return false + } +} + +func (algo SignatureAlgorithm) String() string { + for _, details := range signatureAlgorithmDetails { + if details.algo == algo { + return details.name + } + } + return strconv.Itoa(int(algo)) +} + +type PublicKeyAlgorithm int + +const ( + UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota + RSA + DSA // Unsupported. + ECDSA + Ed25519 +) + +var publicKeyAlgoName = [...]string{ + RSA: "RSA", + DSA: "DSA", + ECDSA: "ECDSA", + Ed25519: "Ed25519", +} + +func (algo PublicKeyAlgorithm) String() string { + if 0 < algo && int(algo) < len(publicKeyAlgoName) { + return publicKeyAlgoName[algo] + } + return strconv.Itoa(int(algo)) +} + +// OIDs for signature algorithms +// +// pkcs-1 OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } +// +// +// RFC 3279 2.2.1 RSA Signature Algorithms +// +// md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } +// +// md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } +// +// sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } +// +// dsaWithSha1 OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 } +// +// RFC 3279 2.2.3 ECDSA Signature Algorithm +// +// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) ansi-x962(10045) +// signatures(4) ecdsa-with-SHA1(1)} +// +// +// RFC 4055 5 PKCS #1 Version 1.5 +// +// sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } +// +// sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } +// +// sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } +// +// +// RFC 5758 3.1 DSA Signature Algorithms +// +// dsaWithSha256 OBJECT IDENTIFIER ::= { +// joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101) +// csor(3) algorithms(4) id-dsa-with-sha2(3) 2} +// +// RFC 5758 3.2 ECDSA Signature Algorithm +// +// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } +// +// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 } +// +// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 } +// +// +// RFC 8410 3 Curve25519 and Curve448 Algorithm Identifiers +// +// id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } + +var ( + oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} + oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} + oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} + oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} + oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} + oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} + oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10} + oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} + oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} + oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} + oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} + oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} + oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} + oidSignatureEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} + + oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1} + oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2} + oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3} + + oidMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8} + + // oidISOSignatureSHA1WithRSA means the same as oidSignatureSHA1WithRSA + // but it's specified by ISO. Microsoft's makecert.exe has been known + // to produce certificates with this OID. + oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29} +) + +var signatureAlgorithmDetails = []struct { + algo SignatureAlgorithm + name string + oid asn1.ObjectIdentifier + pubKeyAlgo PublicKeyAlgorithm + hash crypto.Hash +}{ + {MD2WithRSA, "MD2-RSA", oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */}, + {MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, RSA, crypto.MD5}, + {SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, RSA, crypto.SHA1}, + {SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, RSA, crypto.SHA1}, + {SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, RSA, crypto.SHA256}, + {SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, RSA, crypto.SHA384}, + {SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, RSA, crypto.SHA512}, + {SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA256}, + {SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA384}, + {SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA512}, + {DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, DSA, crypto.SHA1}, + {DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, DSA, crypto.SHA256}, + {ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1}, + {ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, ECDSA, crypto.SHA256}, + {ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, ECDSA, crypto.SHA384}, + {ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512}, + {PureEd25519, "Ed25519", oidSignatureEd25519, Ed25519, crypto.Hash(0) /* no pre-hashing */}, +} + +// hashToPSSParameters contains the DER encoded RSA PSS parameters for the +// SHA256, SHA384, and SHA512 hashes as defined in RFC 3447, Appendix A.2.3. +// The parameters contain the following values: +// * hashAlgorithm contains the associated hash identifier with NULL parameters +// * maskGenAlgorithm always contains the default mgf1SHA1 identifier +// * saltLength contains the length of the associated hash +// * trailerField always contains the default trailerFieldBC value +var hashToPSSParameters = map[crypto.Hash]asn1.RawValue{ + crypto.SHA256: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 162, 3, 2, 1, 32}}, + crypto.SHA384: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 162, 3, 2, 1, 48}}, + crypto.SHA512: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 162, 3, 2, 1, 64}}, +} + +// pssParameters reflects the parameters in an AlgorithmIdentifier that +// specifies RSA PSS. See RFC 3447, Appendix A.2.3. +type pssParameters struct { + // The following three fields are not marked as + // optional because the default values specify SHA-1, + // which is no longer suitable for use in signatures. + Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"` + MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"` + SaltLength int `asn1:"explicit,tag:2"` + TrailerField int `asn1:"optional,explicit,tag:3,default:1"` +} + +func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm { + if ai.Algorithm.Equal(oidSignatureEd25519) { + // RFC 8410, Section 3 + // > For all of the OIDs, the parameters MUST be absent. + if len(ai.Parameters.FullBytes) != 0 { + return UnknownSignatureAlgorithm + } + } + + if !ai.Algorithm.Equal(oidSignatureRSAPSS) { + for _, details := range signatureAlgorithmDetails { + if ai.Algorithm.Equal(details.oid) { + return details.algo + } + } + return UnknownSignatureAlgorithm + } + + // RSA PSS is special because it encodes important parameters + // in the Parameters. + + var params pssParameters + if _, err := asn1.Unmarshal(ai.Parameters.FullBytes, ¶ms); err != nil { + return UnknownSignatureAlgorithm + } + + var mgf1HashFunc pkix.AlgorithmIdentifier + if _, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgf1HashFunc); err != nil { + return UnknownSignatureAlgorithm + } + + // PSS is greatly overburdened with options. This code forces them into + // three buckets by requiring that the MGF1 hash function always match the + // message hash function (as recommended in RFC 3447, Section 8.1), that the + // salt length matches the hash length, and that the trailer field has the + // default value. + if (len(params.Hash.Parameters.FullBytes) != 0 && !bytes.Equal(params.Hash.Parameters.FullBytes, asn1.NullBytes)) || + !params.MGF.Algorithm.Equal(oidMGF1) || + !mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) || + (len(mgf1HashFunc.Parameters.FullBytes) != 0 && !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1.NullBytes)) || + params.TrailerField != 1 { + return UnknownSignatureAlgorithm + } + + switch { + case params.Hash.Algorithm.Equal(oidSHA256) && params.SaltLength == 32: + return SHA256WithRSAPSS + case params.Hash.Algorithm.Equal(oidSHA384) && params.SaltLength == 48: + return SHA384WithRSAPSS + case params.Hash.Algorithm.Equal(oidSHA512) && params.SaltLength == 64: + return SHA512WithRSAPSS + } + + return UnknownSignatureAlgorithm +} + +// RFC 3279, 2.3 Public Key Algorithms +// +// pkcs-1 OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840) +// rsadsi(113549) pkcs(1) 1 } +// +// rsaEncryption OBJECT IDENTIFIER ::== { pkcs1-1 1 } +// +// id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840) +// x9-57(10040) x9cm(4) 1 } +// +// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters +// +// id-ecPublicKey OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } +var ( + oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} + oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1} + oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} + oidPublicKeyEd25519 = oidSignatureEd25519 +) + +func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm { + switch { + case oid.Equal(oidPublicKeyRSA): + return RSA + case oid.Equal(oidPublicKeyDSA): + return DSA + case oid.Equal(oidPublicKeyECDSA): + return ECDSA + case oid.Equal(oidPublicKeyEd25519): + return Ed25519 + } + return UnknownPublicKeyAlgorithm +} + +// RFC 5480, 2.1.1.1. Named Curve +// +// secp224r1 OBJECT IDENTIFIER ::= { +// iso(1) identified-organization(3) certicom(132) curve(0) 33 } +// +// secp256r1 OBJECT IDENTIFIER ::= { +// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) +// prime(1) 7 } +// +// secp384r1 OBJECT IDENTIFIER ::= { +// iso(1) identified-organization(3) certicom(132) curve(0) 34 } +// +// secp521r1 OBJECT IDENTIFIER ::= { +// iso(1) identified-organization(3) certicom(132) curve(0) 35 } +// +// NB: secp256r1 is equivalent to prime256v1 +var ( + oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} + oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} + oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} + oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} +) + +func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { + switch { + case oid.Equal(oidNamedCurveP224): + return elliptic.P224() + case oid.Equal(oidNamedCurveP256): + return elliptic.P256() + case oid.Equal(oidNamedCurveP384): + return elliptic.P384() + case oid.Equal(oidNamedCurveP521): + return elliptic.P521() + } + return nil +} + +func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { + switch curve { + case elliptic.P224(): + return oidNamedCurveP224, true + case elliptic.P256(): + return oidNamedCurveP256, true + case elliptic.P384(): + return oidNamedCurveP384, true + case elliptic.P521(): + return oidNamedCurveP521, true + } + + return nil, false +} + +// KeyUsage represents the set of actions that are valid for a given key. It's +// a bitmap of the KeyUsage* constants. +type KeyUsage int + +const ( + KeyUsageDigitalSignature KeyUsage = 1 << iota + KeyUsageContentCommitment + KeyUsageKeyEncipherment + KeyUsageDataEncipherment + KeyUsageKeyAgreement + KeyUsageCertSign + KeyUsageCRLSign + KeyUsageEncipherOnly + KeyUsageDecipherOnly +) + +// RFC 5280, 4.2.1.12 Extended Key Usage +// +// anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } +// +// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } +// +// id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } +// id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } +// id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } +// id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } +// id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } +// id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } +var ( + oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0} + oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1} + oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2} + oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3} + oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4} + oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5} + oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6} + oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7} + oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} + oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9} + oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3} + oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1} + oidExtKeyUsageMicrosoftCommercialCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 2, 1, 22} + oidExtKeyUsageMicrosoftKernelCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 61, 1, 1} +) + +// ExtKeyUsage represents an extended set of actions that are valid for a given key. +// Each of the ExtKeyUsage* constants define a unique action. +type ExtKeyUsage int + +const ( + ExtKeyUsageAny ExtKeyUsage = iota + ExtKeyUsageServerAuth + ExtKeyUsageClientAuth + ExtKeyUsageCodeSigning + ExtKeyUsageEmailProtection + ExtKeyUsageIPSECEndSystem + ExtKeyUsageIPSECTunnel + ExtKeyUsageIPSECUser + ExtKeyUsageTimeStamping + ExtKeyUsageOCSPSigning + ExtKeyUsageMicrosoftServerGatedCrypto + ExtKeyUsageNetscapeServerGatedCrypto + ExtKeyUsageMicrosoftCommercialCodeSigning + ExtKeyUsageMicrosoftKernelCodeSigning +) + +// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID. +var extKeyUsageOIDs = []struct { + extKeyUsage ExtKeyUsage + oid asn1.ObjectIdentifier +}{ + {ExtKeyUsageAny, oidExtKeyUsageAny}, + {ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth}, + {ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth}, + {ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning}, + {ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection}, + {ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem}, + {ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel}, + {ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser}, + {ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping}, + {ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning}, + {ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto}, + {ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto}, + {ExtKeyUsageMicrosoftCommercialCodeSigning, oidExtKeyUsageMicrosoftCommercialCodeSigning}, + {ExtKeyUsageMicrosoftKernelCodeSigning, oidExtKeyUsageMicrosoftKernelCodeSigning}, +} + +func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) { + for _, pair := range extKeyUsageOIDs { + if oid.Equal(pair.oid) { + return pair.extKeyUsage, true + } + } + return +} + +func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) { + for _, pair := range extKeyUsageOIDs { + if eku == pair.extKeyUsage { + return pair.oid, true + } + } + return +} + +// A Certificate represents an X.509 certificate. +type Certificate struct { + Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature). + RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content. + RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo. + RawSubject []byte // DER encoded Subject + RawIssuer []byte // DER encoded Issuer + + Signature []byte + SignatureAlgorithm SignatureAlgorithm + + PublicKeyAlgorithm PublicKeyAlgorithm + PublicKey interface{} + + Version int + SerialNumber *big.Int + Issuer pkix.Name + Subject pkix.Name + NotBefore, NotAfter time.Time // Validity bounds. + KeyUsage KeyUsage + + // Extensions contains raw X.509 extensions. When parsing certificates, + // this can be used to extract non-critical extensions that are not + // parsed by this package. When marshaling certificates, the Extensions + // field is ignored, see ExtraExtensions. + Extensions []pkix.Extension + + // ExtraExtensions contains extensions to be copied, raw, into any + // marshaled certificates. Values override any extensions that would + // otherwise be produced based on the other fields. The ExtraExtensions + // field is not populated when parsing certificates, see Extensions. + ExtraExtensions []pkix.Extension + + // UnhandledCriticalExtensions contains a list of extension IDs that + // were not (fully) processed when parsing. Verify will fail if this + // slice is non-empty, unless verification is delegated to an OS + // library which understands all the critical extensions. + // + // Users can access these extensions using Extensions and can remove + // elements from this slice if they believe that they have been + // handled. + UnhandledCriticalExtensions []asn1.ObjectIdentifier + + ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages. + UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package. + + // BasicConstraintsValid indicates whether IsCA, MaxPathLen, + // and MaxPathLenZero are valid. + BasicConstraintsValid bool + IsCA bool + + // MaxPathLen and MaxPathLenZero indicate the presence and + // value of the BasicConstraints' "pathLenConstraint". + // + // When parsing a certificate, a positive non-zero MaxPathLen + // means that the field was specified, -1 means it was unset, + // and MaxPathLenZero being true mean that the field was + // explicitly set to zero. The case of MaxPathLen==0 with MaxPathLenZero==false + // should be treated equivalent to -1 (unset). + // + // When generating a certificate, an unset pathLenConstraint + // can be requested with either MaxPathLen == -1 or using the + // zero value for both MaxPathLen and MaxPathLenZero. + MaxPathLen int + // MaxPathLenZero indicates that BasicConstraintsValid==true + // and MaxPathLen==0 should be interpreted as an actual + // maximum path length of zero. Otherwise, that combination is + // interpreted as MaxPathLen not being set. + MaxPathLenZero bool + + SubjectKeyId []byte + AuthorityKeyId []byte + + // RFC 5280, 4.2.2.1 (Authority Information Access) + OCSPServer []string + IssuingCertificateURL []string + + // Subject Alternate Name values. (Note that these values may not be valid + // if invalid values were contained within a parsed certificate. For + // example, an element of DNSNames may not be a valid DNS domain name.) + DNSNames []string + EmailAddresses []string + IPAddresses []net.IP + URIs []*url.URL + + // Name constraints + PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical. + PermittedDNSDomains []string + ExcludedDNSDomains []string + PermittedIPRanges []*net.IPNet + ExcludedIPRanges []*net.IPNet + PermittedEmailAddresses []string + ExcludedEmailAddresses []string + PermittedURIDomains []string + ExcludedURIDomains []string + + // CRL Distribution Points + CRLDistributionPoints []string + + PolicyIdentifiers []asn1.ObjectIdentifier +} + +// ErrUnsupportedAlgorithm results from attempting to perform an operation that +// involves algorithms that are not currently implemented. +var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented") + +// An InsecureAlgorithmError +type InsecureAlgorithmError SignatureAlgorithm + +func (e InsecureAlgorithmError) Error() string { + return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) +} + +// ConstraintViolationError results when a requested usage is not permitted by +// a certificate. For example: checking a signature when the public key isn't a +// certificate signing key. +type ConstraintViolationError struct{} + +func (ConstraintViolationError) Error() string { + return "x509: invalid signature: parent certificate cannot sign this kind of certificate" +} + +func (c *Certificate) Equal(other *Certificate) bool { + if c == nil || other == nil { + return c == other + } + return bytes.Equal(c.Raw, other.Raw) +} + +func (c *Certificate) hasSANExtension() bool { + return oidInExtensions(oidExtensionSubjectAltName, c.Extensions) +} + +// CheckSignatureFrom verifies that the signature on c is a valid signature +// from parent. +func (c *Certificate) CheckSignatureFrom(parent *Certificate) error { + // RFC 5280, 4.2.1.9: + // "If the basic constraints extension is not present in a version 3 + // certificate, or the extension is present but the cA boolean is not + // asserted, then the certified public key MUST NOT be used to verify + // certificate signatures." + if parent.Version == 3 && !parent.BasicConstraintsValid || + parent.BasicConstraintsValid && !parent.IsCA { + return ConstraintViolationError{} + } + + if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCertSign == 0 { + return ConstraintViolationError{} + } + + if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm { + return ErrUnsupportedAlgorithm + } + + // TODO(agl): don't ignore the path length constraint. + + return parent.CheckSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature) +} + +// CheckSignature verifies that signature is a valid signature over signed from +// c's public key. +func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) error { + return checkSignature(algo, signed, signature, c.PublicKey) +} + +func (c *Certificate) hasNameConstraints() bool { + return oidInExtensions(oidExtensionNameConstraints, c.Extensions) +} + +func (c *Certificate) getSANExtension() []byte { + for _, e := range c.Extensions { + if e.Id.Equal(oidExtensionSubjectAltName) { + return e.Value + } + } + return nil +} + +func signaturePublicKeyAlgoMismatchError(expectedPubKeyAlgo PublicKeyAlgorithm, pubKey interface{}) error { + return fmt.Errorf("x509: signature algorithm specifies an %s public key, but have public key of type %T", expectedPubKeyAlgo.String(), pubKey) +} + +// CheckSignature verifies that signature is a valid signature over signed from +// a crypto.PublicKey. +func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey crypto.PublicKey) (err error) { + var hashType crypto.Hash + var pubKeyAlgo PublicKeyAlgorithm + + for _, details := range signatureAlgorithmDetails { + if details.algo == algo { + hashType = details.hash + pubKeyAlgo = details.pubKeyAlgo + } + } + + switch hashType { + case crypto.Hash(0): + if pubKeyAlgo != Ed25519 { + return ErrUnsupportedAlgorithm + } + case crypto.MD5: + return InsecureAlgorithmError(algo) + default: + if !hashType.Available() { + return ErrUnsupportedAlgorithm + } + h := hashType.New() + h.Write(signed) + signed = h.Sum(nil) + } + + switch pub := publicKey.(type) { + case *rsa.PublicKey: + if pubKeyAlgo != RSA { + return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub) + } + if algo.isRSAPSS() { + return rsa.VerifyPSS(pub, hashType, signed, signature, &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}) + } else { + return rsa.VerifyPKCS1v15(pub, hashType, signed, signature) + } + case *ecdsa.PublicKey: + if pubKeyAlgo != ECDSA { + return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub) + } + if !ecdsa.VerifyASN1(pub, signed, signature) { + return errors.New("x509: ECDSA verification failure") + } + return + case ed25519.PublicKey: + if pubKeyAlgo != Ed25519 { + return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub) + } + if !ed25519.Verify(pub, signed, signature) { + return errors.New("x509: Ed25519 verification failure") + } + return + } + return ErrUnsupportedAlgorithm +} + +// CheckCRLSignature checks that the signature in crl is from c. +func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) error { + algo := getSignatureAlgorithmFromAI(crl.SignatureAlgorithm) + return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign()) +} + +type UnhandledCriticalExtension struct{} + +func (h UnhandledCriticalExtension) Error() string { + return "x509: unhandled critical extension" +} + +type basicConstraints struct { + IsCA bool `asn1:"optional"` + MaxPathLen int `asn1:"optional,default:-1"` +} + +// RFC 5280 4.2.1.4 +type policyInformation struct { + Policy asn1.ObjectIdentifier + // policyQualifiers omitted +} + +const ( + nameTypeEmail = 1 + nameTypeDNS = 2 + nameTypeURI = 6 + nameTypeIP = 7 +) + +// RFC 5280, 4.2.2.1 +type authorityInfoAccess struct { + Method asn1.ObjectIdentifier + Location asn1.RawValue +} + +// RFC 5280, 4.2.1.14 +type distributionPoint struct { + DistributionPoint distributionPointName `asn1:"optional,tag:0"` + Reason asn1.BitString `asn1:"optional,tag:1"` + CRLIssuer asn1.RawValue `asn1:"optional,tag:2"` +} + +type distributionPointName struct { + FullName []asn1.RawValue `asn1:"optional,tag:0"` + RelativeName pkix.RDNSequence `asn1:"optional,tag:1"` +} + +func reverseBitsInAByte(in byte) byte { + b1 := in>>4 | in<<4 + b2 := b1>>2&0x33 | b1<<2&0xcc + b3 := b2>>1&0x55 | b2<<1&0xaa + return b3 +} + +// asn1BitLength returns the bit-length of bitString by considering the +// most-significant bit in a byte to be the "first" bit. This convention +// matches ASN.1, but differs from almost everything else. +func asn1BitLength(bitString []byte) int { + bitLen := len(bitString) * 8 + + for i := range bitString { + b := bitString[len(bitString)-i-1] + + for bit := uint(0); bit < 8; bit++ { + if (b>>bit)&1 == 1 { + return bitLen + } + bitLen-- + } + } + + return 0 +} + +var ( + oidExtensionSubjectKeyId = []int{2, 5, 29, 14} + oidExtensionKeyUsage = []int{2, 5, 29, 15} + oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37} + oidExtensionAuthorityKeyId = []int{2, 5, 29, 35} + oidExtensionBasicConstraints = []int{2, 5, 29, 19} + oidExtensionSubjectAltName = []int{2, 5, 29, 17} + oidExtensionCertificatePolicies = []int{2, 5, 29, 32} + oidExtensionNameConstraints = []int{2, 5, 29, 30} + oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31} + oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1} + oidExtensionCRLNumber = []int{2, 5, 29, 20} +) + +var ( + oidAuthorityInfoAccessOcsp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1} + oidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2} +) + +// oidNotInExtensions reports whether an extension with the given oid exists in +// extensions. +func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool { + for _, e := range extensions { + if e.Id.Equal(oid) { + return true + } + } + return false +} + +// marshalSANs marshals a list of addresses into a the contents of an X.509 +// SubjectAlternativeName extension. +func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL) (derBytes []byte, err error) { + var rawValues []asn1.RawValue + for _, name := range dnsNames { + if err := isIA5String(name); err != nil { + return nil, err + } + rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeDNS, Class: 2, Bytes: []byte(name)}) + } + for _, email := range emailAddresses { + if err := isIA5String(email); err != nil { + return nil, err + } + rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeEmail, Class: 2, Bytes: []byte(email)}) + } + for _, rawIP := range ipAddresses { + // If possible, we always want to encode IPv4 addresses in 4 bytes. + ip := rawIP.To4() + if ip == nil { + ip = rawIP + } + rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeIP, Class: 2, Bytes: ip}) + } + for _, uri := range uris { + uriStr := uri.String() + if err := isIA5String(uriStr); err != nil { + return nil, err + } + rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeURI, Class: 2, Bytes: []byte(uriStr)}) + } + return asn1.Marshal(rawValues) +} + +func isIA5String(s string) error { + for _, r := range s { + // Per RFC5280 "IA5String is limited to the set of ASCII characters" + if r > unicode.MaxASCII { + return fmt.Errorf("x509: %q cannot be encoded as an IA5String", s) + } + } + + return nil +} + +func buildCertExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId []byte, subjectKeyId []byte) (ret []pkix.Extension, err error) { + ret = make([]pkix.Extension, 10 /* maximum number of elements. */) + n := 0 + + if template.KeyUsage != 0 && + !oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) { + ret[n], err = marshalKeyUsage(template.KeyUsage) + if err != nil { + return nil, err + } + n++ + } + + if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) && + !oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) { + ret[n], err = marshalExtKeyUsage(template.ExtKeyUsage, template.UnknownExtKeyUsage) + if err != nil { + return nil, err + } + n++ + } + + if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) { + ret[n], err = marshalBasicConstraints(template.IsCA, template.MaxPathLen, template.MaxPathLenZero) + if err != nil { + return nil, err + } + n++ + } + + if len(subjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) { + ret[n].Id = oidExtensionSubjectKeyId + ret[n].Value, err = asn1.Marshal(subjectKeyId) + if err != nil { + return + } + n++ + } + + if len(authorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) { + ret[n].Id = oidExtensionAuthorityKeyId + ret[n].Value, err = asn1.Marshal(authKeyId{authorityKeyId}) + if err != nil { + return + } + n++ + } + + if (len(template.OCSPServer) > 0 || len(template.IssuingCertificateURL) > 0) && + !oidInExtensions(oidExtensionAuthorityInfoAccess, template.ExtraExtensions) { + ret[n].Id = oidExtensionAuthorityInfoAccess + var aiaValues []authorityInfoAccess + for _, name := range template.OCSPServer { + aiaValues = append(aiaValues, authorityInfoAccess{ + Method: oidAuthorityInfoAccessOcsp, + Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}, + }) + } + for _, name := range template.IssuingCertificateURL { + aiaValues = append(aiaValues, authorityInfoAccess{ + Method: oidAuthorityInfoAccessIssuers, + Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}, + }) + } + ret[n].Value, err = asn1.Marshal(aiaValues) + if err != nil { + return + } + n++ + } + + if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) && + !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { + ret[n].Id = oidExtensionSubjectAltName + // From RFC 5280, Section 4.2.1.6: + // “If the subject field contains an empty sequence ... then + // subjectAltName extension ... is marked as critical” + ret[n].Critical = subjectIsEmpty + ret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs) + if err != nil { + return + } + n++ + } + + if len(template.PolicyIdentifiers) > 0 && + !oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) { + ret[n], err = marshalCertificatePolicies(template.PolicyIdentifiers) + if err != nil { + return nil, err + } + n++ + } + + if (len(template.PermittedDNSDomains) > 0 || len(template.ExcludedDNSDomains) > 0 || + len(template.PermittedIPRanges) > 0 || len(template.ExcludedIPRanges) > 0 || + len(template.PermittedEmailAddresses) > 0 || len(template.ExcludedEmailAddresses) > 0 || + len(template.PermittedURIDomains) > 0 || len(template.ExcludedURIDomains) > 0) && + !oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) { + ret[n].Id = oidExtensionNameConstraints + ret[n].Critical = template.PermittedDNSDomainsCritical + + ipAndMask := func(ipNet *net.IPNet) []byte { + maskedIP := ipNet.IP.Mask(ipNet.Mask) + ipAndMask := make([]byte, 0, len(maskedIP)+len(ipNet.Mask)) + ipAndMask = append(ipAndMask, maskedIP...) + ipAndMask = append(ipAndMask, ipNet.Mask...) + return ipAndMask + } + + serialiseConstraints := func(dns []string, ips []*net.IPNet, emails []string, uriDomains []string) (der []byte, err error) { + var b cryptobyte.Builder + + for _, name := range dns { + if err = isIA5String(name); err != nil { + return nil, err + } + + b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1(cryptobyte_asn1.Tag(2).ContextSpecific(), func(b *cryptobyte.Builder) { + b.AddBytes([]byte(name)) + }) + }) + } + + for _, ipNet := range ips { + b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1(cryptobyte_asn1.Tag(7).ContextSpecific(), func(b *cryptobyte.Builder) { + b.AddBytes(ipAndMask(ipNet)) + }) + }) + } + + for _, email := range emails { + if err = isIA5String(email); err != nil { + return nil, err + } + + b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1(cryptobyte_asn1.Tag(1).ContextSpecific(), func(b *cryptobyte.Builder) { + b.AddBytes([]byte(email)) + }) + }) + } + + for _, uriDomain := range uriDomains { + if err = isIA5String(uriDomain); err != nil { + return nil, err + } + + b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1(cryptobyte_asn1.Tag(6).ContextSpecific(), func(b *cryptobyte.Builder) { + b.AddBytes([]byte(uriDomain)) + }) + }) + } + + return b.Bytes() + } + + permitted, err := serialiseConstraints(template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains) + if err != nil { + return nil, err + } + + excluded, err := serialiseConstraints(template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains) + if err != nil { + return nil, err + } + + var b cryptobyte.Builder + b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + if len(permitted) > 0 { + b.AddASN1(cryptobyte_asn1.Tag(0).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) { + b.AddBytes(permitted) + }) + } + + if len(excluded) > 0 { + b.AddASN1(cryptobyte_asn1.Tag(1).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) { + b.AddBytes(excluded) + }) + } + }) + + ret[n].Value, err = b.Bytes() + if err != nil { + return nil, err + } + n++ + } + + if len(template.CRLDistributionPoints) > 0 && + !oidInExtensions(oidExtensionCRLDistributionPoints, template.ExtraExtensions) { + ret[n].Id = oidExtensionCRLDistributionPoints + + var crlDp []distributionPoint + for _, name := range template.CRLDistributionPoints { + dp := distributionPoint{ + DistributionPoint: distributionPointName{ + FullName: []asn1.RawValue{ + {Tag: 6, Class: 2, Bytes: []byte(name)}, + }, + }, + } + crlDp = append(crlDp, dp) + } + + ret[n].Value, err = asn1.Marshal(crlDp) + if err != nil { + return + } + n++ + } + + // Adding another extension here? Remember to update the maximum number + // of elements in the make() at the top of the function and the list of + // template fields used in CreateCertificate documentation. + + return append(ret[:n], template.ExtraExtensions...), nil +} + +func marshalKeyUsage(ku KeyUsage) (pkix.Extension, error) { + ext := pkix.Extension{Id: oidExtensionKeyUsage, Critical: true} + + var a [2]byte + a[0] = reverseBitsInAByte(byte(ku)) + a[1] = reverseBitsInAByte(byte(ku >> 8)) + + l := 1 + if a[1] != 0 { + l = 2 + } + + bitString := a[:l] + var err error + ext.Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)}) + if err != nil { + return ext, err + } + return ext, nil +} + +func marshalExtKeyUsage(extUsages []ExtKeyUsage, unknownUsages []asn1.ObjectIdentifier) (pkix.Extension, error) { + ext := pkix.Extension{Id: oidExtensionExtendedKeyUsage} + + oids := make([]asn1.ObjectIdentifier, len(extUsages)+len(unknownUsages)) + for i, u := range extUsages { + if oid, ok := oidFromExtKeyUsage(u); ok { + oids[i] = oid + } else { + return ext, errors.New("x509: unknown extended key usage") + } + } + + copy(oids[len(extUsages):], unknownUsages) + + var err error + ext.Value, err = asn1.Marshal(oids) + if err != nil { + return ext, err + } + return ext, nil +} + +func marshalBasicConstraints(isCA bool, maxPathLen int, maxPathLenZero bool) (pkix.Extension, error) { + ext := pkix.Extension{Id: oidExtensionBasicConstraints, Critical: true} + // Leaving MaxPathLen as zero indicates that no maximum path + // length is desired, unless MaxPathLenZero is set. A value of + // -1 causes encoding/asn1 to omit the value as desired. + if maxPathLen == 0 && !maxPathLenZero { + maxPathLen = -1 + } + var err error + ext.Value, err = asn1.Marshal(basicConstraints{isCA, maxPathLen}) + if err != nil { + return ext, nil + } + return ext, nil +} + +func marshalCertificatePolicies(policyIdentifiers []asn1.ObjectIdentifier) (pkix.Extension, error) { + ext := pkix.Extension{Id: oidExtensionCertificatePolicies} + policies := make([]policyInformation, len(policyIdentifiers)) + for i, policy := range policyIdentifiers { + policies[i].Policy = policy + } + var err error + ext.Value, err = asn1.Marshal(policies) + if err != nil { + return ext, err + } + return ext, nil +} + +func buildCSRExtensions(template *CertificateRequest) ([]pkix.Extension, error) { + var ret []pkix.Extension + + if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) && + !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { + sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs) + if err != nil { + return nil, err + } + + ret = append(ret, pkix.Extension{ + Id: oidExtensionSubjectAltName, + Value: sanBytes, + }) + } + + return append(ret, template.ExtraExtensions...), nil +} + +func subjectBytes(cert *Certificate) ([]byte, error) { + if len(cert.RawSubject) > 0 { + return cert.RawSubject, nil + } + + return asn1.Marshal(cert.Subject.ToRDNSequence()) +} + +// signingParamsForPublicKey returns the parameters to use for signing with +// priv. If requestedSigAlgo is not zero then it overrides the default +// signature algorithm. +func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { + var pubType PublicKeyAlgorithm + + switch pub := pub.(type) { + case *rsa.PublicKey: + pubType = RSA + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureSHA256WithRSA + sigAlgo.Parameters = asn1.NullRawValue + + case *ecdsa.PublicKey: + pubType = ECDSA + + switch pub.Curve { + case elliptic.P224(), elliptic.P256(): + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 + case elliptic.P384(): + hashFunc = crypto.SHA384 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 + case elliptic.P521(): + hashFunc = crypto.SHA512 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 + default: + err = errors.New("x509: unknown elliptic curve") + } + + case ed25519.PublicKey: + pubType = Ed25519 + sigAlgo.Algorithm = oidSignatureEd25519 + + default: + err = errors.New("x509: only RSA, ECDSA and Ed25519 keys supported") + } + + if err != nil { + return + } + + if requestedSigAlgo == 0 { + return + } + + found := false + for _, details := range signatureAlgorithmDetails { + if details.algo == requestedSigAlgo { + if details.pubKeyAlgo != pubType { + err = errors.New("x509: requested SignatureAlgorithm does not match private key type") + return + } + sigAlgo.Algorithm, hashFunc = details.oid, details.hash + if hashFunc == 0 && pubType != Ed25519 { + err = errors.New("x509: cannot sign with hash function requested") + return + } + if requestedSigAlgo.isRSAPSS() { + sigAlgo.Parameters = hashToPSSParameters[hashFunc] + } + found = true + break + } + } + + if !found { + err = errors.New("x509: unknown SignatureAlgorithm") + } + + return +} + +// emptyASN1Subject is the ASN.1 DER encoding of an empty Subject, which is +// just an empty SEQUENCE. +var emptyASN1Subject = []byte{0x30, 0} + +// CreateCertificate creates a new X.509 v3 certificate based on a template. +// The following members of template are currently used: +// +// - AuthorityKeyId +// - BasicConstraintsValid +// - CRLDistributionPoints +// - DNSNames +// - EmailAddresses +// - ExcludedDNSDomains +// - ExcludedEmailAddresses +// - ExcludedIPRanges +// - ExcludedURIDomains +// - ExtKeyUsage +// - ExtraExtensions +// - IPAddresses +// - IsCA +// - IssuingCertificateURL +// - KeyUsage +// - MaxPathLen +// - MaxPathLenZero +// - NotAfter +// - NotBefore +// - OCSPServer +// - PermittedDNSDomains +// - PermittedDNSDomainsCritical +// - PermittedEmailAddresses +// - PermittedIPRanges +// - PermittedURIDomains +// - PolicyIdentifiers +// - SerialNumber +// - SignatureAlgorithm +// - Subject +// - SubjectKeyId +// - URIs +// - UnknownExtKeyUsage +// +// The certificate is signed by parent. If parent is equal to template then the +// certificate is self-signed. The parameter pub is the public key of the +// certificate to be generated and priv is the private key of the signer. +// +// The returned slice is the certificate in DER encoding. +// +// The currently supported key types are *rsa.PublicKey, *ecdsa.PublicKey and +// ed25519.PublicKey. pub must be a supported key type, and priv must be a +// crypto.Signer with a supported public key. +// +// The AuthorityKeyId will be taken from the SubjectKeyId of parent, if any, +// unless the resulting certificate is self-signed. Otherwise the value from +// template will be used. +// +// If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId +// will be generated from the hash of the public key. +func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) ([]byte, error) { + key, ok := priv.(crypto.Signer) + if !ok { + return nil, errors.New("x509: certificate private key does not implement crypto.Signer") + } + + if template.SerialNumber == nil { + return nil, errors.New("x509: no SerialNumber given") + } + + if template.BasicConstraintsValid && !template.IsCA && template.MaxPathLen != -1 && (template.MaxPathLen != 0 || template.MaxPathLenZero) { + return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen") + } + + hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm) + if err != nil { + return nil, err + } + + publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub) + if err != nil { + return nil, err + } + + asn1Issuer, err := subjectBytes(parent) + if err != nil { + return nil, err + } + + asn1Subject, err := subjectBytes(template) + if err != nil { + return nil, err + } + + authorityKeyId := template.AuthorityKeyId + if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 { + authorityKeyId = parent.SubjectKeyId + } + + subjectKeyId := template.SubjectKeyId + if len(subjectKeyId) == 0 && template.IsCA { + // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2: + // (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the + // value of the BIT STRING subjectPublicKey (excluding the tag, + // length, and number of unused bits). + h := sha1.Sum(publicKeyBytes) + subjectKeyId = h[:] + } + + // Check that the signer's public key matches the private key, if available. + type privateKey interface { + Equal(crypto.PublicKey) bool + } + if privPub, ok := key.Public().(privateKey); !ok { + return nil, errors.New("x509: internal error: supported public key does not implement Equal") + } else if parent.PublicKey != nil && !privPub.Equal(parent.PublicKey) { + return nil, errors.New("x509: provided PrivateKey doesn't match parent's PublicKey") + } + + extensions, err := buildCertExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId, subjectKeyId) + if err != nil { + return nil, err + } + + encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes} + c := tbsCertificate{ + Version: 2, + SerialNumber: template.SerialNumber, + SignatureAlgorithm: signatureAlgorithm, + Issuer: asn1.RawValue{FullBytes: asn1Issuer}, + Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()}, + Subject: asn1.RawValue{FullBytes: asn1Subject}, + PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey}, + Extensions: extensions, + } + + tbsCertContents, err := asn1.Marshal(c) + if err != nil { + return nil, err + } + c.Raw = tbsCertContents + + signed := tbsCertContents + if hashFunc != 0 { + h := hashFunc.New() + h.Write(signed) + signed = h.Sum(nil) + } + + var signerOpts crypto.SignerOpts = hashFunc + if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() { + signerOpts = &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: hashFunc, + } + } + + var signature []byte + signature, err = key.Sign(rand, signed, signerOpts) + if err != nil { + return nil, err + } + + signedCert, err := asn1.Marshal(certificate{ + nil, + c, + signatureAlgorithm, + asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, + }) + if err != nil { + return nil, err + } + + // Check the signature to ensure the crypto.Signer behaved correctly. + // We skip this check if the signature algorithm is MD5WithRSA as we + // only support this algorithm for signing, and not verification. + if sigAlg := getSignatureAlgorithmFromAI(signatureAlgorithm); sigAlg != MD5WithRSA { + if err := checkSignature(sigAlg, c.Raw, signature, key.Public()); err != nil { + return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err) + } + } + + return signedCert, nil +} + +// pemCRLPrefix is the magic string that indicates that we have a PEM encoded +// CRL. +var pemCRLPrefix = []byte("-----BEGIN X509 CRL") + +// pemType is the type of a PEM encoded CRL. +var pemType = "X509 CRL" + +// ParseCRL parses a CRL from the given bytes. It's often the case that PEM +// encoded CRLs will appear where they should be DER encoded, so this function +// will transparently handle PEM encoding as long as there isn't any leading +// garbage. +func ParseCRL(crlBytes []byte) (*pkix.CertificateList, error) { + if bytes.HasPrefix(crlBytes, pemCRLPrefix) { + block, _ := pem.Decode(crlBytes) + if block != nil && block.Type == pemType { + crlBytes = block.Bytes + } + } + return ParseDERCRL(crlBytes) +} + +// ParseDERCRL parses a DER encoded CRL from the given bytes. +func ParseDERCRL(derBytes []byte) (*pkix.CertificateList, error) { + certList := new(pkix.CertificateList) + if rest, err := asn1.Unmarshal(derBytes, certList); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("x509: trailing data after CRL") + } + return certList, nil +} + +// CreateCRL returns a DER encoded CRL, signed by this Certificate, that +// contains the given list of revoked certificates. +// +// Note: this method does not generate an RFC 5280 conformant X.509 v2 CRL. +// To generate a standards compliant CRL, use CreateRevocationList instead. +func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) { + key, ok := priv.(crypto.Signer) + if !ok { + return nil, errors.New("x509: certificate private key does not implement crypto.Signer") + } + + hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0) + if err != nil { + return nil, err + } + + // Force revocation times to UTC per RFC 5280. + revokedCertsUTC := make([]pkix.RevokedCertificate, len(revokedCerts)) + for i, rc := range revokedCerts { + rc.RevocationTime = rc.RevocationTime.UTC() + revokedCertsUTC[i] = rc + } + + tbsCertList := pkix.TBSCertificateList{ + Version: 1, + Signature: signatureAlgorithm, + Issuer: c.Subject.ToRDNSequence(), + ThisUpdate: now.UTC(), + NextUpdate: expiry.UTC(), + RevokedCertificates: revokedCertsUTC, + } + + // Authority Key Id + if len(c.SubjectKeyId) > 0 { + var aki pkix.Extension + aki.Id = oidExtensionAuthorityKeyId + aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId}) + if err != nil { + return + } + tbsCertList.Extensions = append(tbsCertList.Extensions, aki) + } + + tbsCertListContents, err := asn1.Marshal(tbsCertList) + if err != nil { + return + } + + signed := tbsCertListContents + if hashFunc != 0 { + h := hashFunc.New() + h.Write(signed) + signed = h.Sum(nil) + } + + var signature []byte + signature, err = key.Sign(rand, signed, hashFunc) + if err != nil { + return + } + + return asn1.Marshal(pkix.CertificateList{ + TBSCertList: tbsCertList, + SignatureAlgorithm: signatureAlgorithm, + SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, + }) +} + +// CertificateRequest represents a PKCS #10, certificate signature request. +type CertificateRequest struct { + Raw []byte // Complete ASN.1 DER content (CSR, signature algorithm and signature). + RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content. + RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo. + RawSubject []byte // DER encoded Subject. + + Version int + Signature []byte + SignatureAlgorithm SignatureAlgorithm + + PublicKeyAlgorithm PublicKeyAlgorithm + PublicKey interface{} + + Subject pkix.Name + + // Attributes contains the CSR attributes that can parse as + // pkix.AttributeTypeAndValueSET. + // + // Deprecated: Use Extensions and ExtraExtensions instead for parsing and + // generating the requestedExtensions attribute. + Attributes []pkix.AttributeTypeAndValueSET + + // Extensions contains all requested extensions, in raw form. When parsing + // CSRs, this can be used to extract extensions that are not parsed by this + // package. + Extensions []pkix.Extension + + // ExtraExtensions contains extensions to be copied, raw, into any CSR + // marshaled by CreateCertificateRequest. Values override any extensions + // that would otherwise be produced based on the other fields but are + // overridden by any extensions specified in Attributes. + // + // The ExtraExtensions field is not populated by ParseCertificateRequest, + // see Extensions instead. + ExtraExtensions []pkix.Extension + + // Subject Alternate Name values. + DNSNames []string + EmailAddresses []string + IPAddresses []net.IP + URIs []*url.URL +} + +// These structures reflect the ASN.1 structure of X.509 certificate +// signature requests (see RFC 2986): + +type tbsCertificateRequest struct { + Raw asn1.RawContent + Version int + Subject asn1.RawValue + PublicKey publicKeyInfo + RawAttributes []asn1.RawValue `asn1:"tag:0"` +} + +type certificateRequest struct { + Raw asn1.RawContent + TBSCSR tbsCertificateRequest + SignatureAlgorithm pkix.AlgorithmIdentifier + SignatureValue asn1.BitString +} + +// oidExtensionRequest is a PKCS #9 OBJECT IDENTIFIER that indicates requested +// extensions in a CSR. +var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14} + +// newRawAttributes converts AttributeTypeAndValueSETs from a template +// CertificateRequest's Attributes into tbsCertificateRequest RawAttributes. +func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawValue, error) { + var rawAttributes []asn1.RawValue + b, err := asn1.Marshal(attributes) + if err != nil { + return nil, err + } + rest, err := asn1.Unmarshal(b, &rawAttributes) + if err != nil { + return nil, err + } + if len(rest) != 0 { + return nil, errors.New("x509: failed to unmarshal raw CSR Attributes") + } + return rawAttributes, nil +} + +// parseRawAttributes Unmarshals RawAttributes into AttributeTypeAndValueSETs. +func parseRawAttributes(rawAttributes []asn1.RawValue) []pkix.AttributeTypeAndValueSET { + var attributes []pkix.AttributeTypeAndValueSET + for _, rawAttr := range rawAttributes { + var attr pkix.AttributeTypeAndValueSET + rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr) + // Ignore attributes that don't parse into pkix.AttributeTypeAndValueSET + // (i.e.: challengePassword or unstructuredName). + if err == nil && len(rest) == 0 { + attributes = append(attributes, attr) + } + } + return attributes +} + +// parseCSRExtensions parses the attributes from a CSR and extracts any +// requested extensions. +func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) { + // pkcs10Attribute reflects the Attribute structure from RFC 2986, Section 4.1. + type pkcs10Attribute struct { + Id asn1.ObjectIdentifier + Values []asn1.RawValue `asn1:"set"` + } + + var ret []pkix.Extension + for _, rawAttr := range rawAttributes { + var attr pkcs10Attribute + if rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr); err != nil || len(rest) != 0 || len(attr.Values) == 0 { + // Ignore attributes that don't parse. + continue + } + + if !attr.Id.Equal(oidExtensionRequest) { + continue + } + + var extensions []pkix.Extension + if _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil { + return nil, err + } + ret = append(ret, extensions...) + } + + return ret, nil +} + +// CreateCertificateRequest creates a new certificate request based on a +// template. The following members of template are used: +// +// - SignatureAlgorithm +// - Subject +// - DNSNames +// - EmailAddresses +// - IPAddresses +// - URIs +// - ExtraExtensions +// - Attributes (deprecated) +// +// priv is the private key to sign the CSR with, and the corresponding public +// key will be included in the CSR. It must implement crypto.Signer and its +// Public() method must return a *rsa.PublicKey or a *ecdsa.PublicKey or a +// ed25519.PublicKey. (A *rsa.PrivateKey, *ecdsa.PrivateKey or +// ed25519.PrivateKey satisfies this.) +// +// The returned slice is the certificate request in DER encoding. +func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv interface{}) (csr []byte, err error) { + key, ok := priv.(crypto.Signer) + if !ok { + return nil, errors.New("x509: certificate private key does not implement crypto.Signer") + } + + var hashFunc crypto.Hash + var sigAlgo pkix.AlgorithmIdentifier + hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm) + if err != nil { + return nil, err + } + + var publicKeyBytes []byte + var publicKeyAlgorithm pkix.AlgorithmIdentifier + publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(key.Public()) + if err != nil { + return nil, err + } + + extensions, err := buildCSRExtensions(template) + if err != nil { + return nil, err + } + + // Make a copy of template.Attributes because we may alter it below. + attributes := make([]pkix.AttributeTypeAndValueSET, 0, len(template.Attributes)) + for _, attr := range template.Attributes { + values := make([][]pkix.AttributeTypeAndValue, len(attr.Value)) + copy(values, attr.Value) + attributes = append(attributes, pkix.AttributeTypeAndValueSET{ + Type: attr.Type, + Value: values, + }) + } + + extensionsAppended := false + if len(extensions) > 0 { + // Append the extensions to an existing attribute if possible. + for _, atvSet := range attributes { + if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 { + continue + } + + // specifiedExtensions contains all the extensions that we + // found specified via template.Attributes. + specifiedExtensions := make(map[string]bool) + + for _, atvs := range atvSet.Value { + for _, atv := range atvs { + specifiedExtensions[atv.Type.String()] = true + } + } + + newValue := make([]pkix.AttributeTypeAndValue, 0, len(atvSet.Value[0])+len(extensions)) + newValue = append(newValue, atvSet.Value[0]...) + + for _, e := range extensions { + if specifiedExtensions[e.Id.String()] { + // Attributes already contained a value for + // this extension and it takes priority. + continue + } + + newValue = append(newValue, pkix.AttributeTypeAndValue{ + // There is no place for the critical + // flag in an AttributeTypeAndValue. + Type: e.Id, + Value: e.Value, + }) + } + + atvSet.Value[0] = newValue + extensionsAppended = true + break + } + } + + rawAttributes, err := newRawAttributes(attributes) + if err != nil { + return + } + + // If not included in attributes, add a new attribute for the + // extensions. + if len(extensions) > 0 && !extensionsAppended { + attr := struct { + Type asn1.ObjectIdentifier + Value [][]pkix.Extension `asn1:"set"` + }{ + Type: oidExtensionRequest, + Value: [][]pkix.Extension{extensions}, + } + + b, err := asn1.Marshal(attr) + if err != nil { + return nil, errors.New("x509: failed to serialise extensions attribute: " + err.Error()) + } + + var rawValue asn1.RawValue + if _, err := asn1.Unmarshal(b, &rawValue); err != nil { + return nil, err + } + + rawAttributes = append(rawAttributes, rawValue) + } + + asn1Subject := template.RawSubject + if len(asn1Subject) == 0 { + asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence()) + if err != nil { + return nil, err + } + } + + tbsCSR := tbsCertificateRequest{ + Version: 0, // PKCS #10, RFC 2986 + Subject: asn1.RawValue{FullBytes: asn1Subject}, + PublicKey: publicKeyInfo{ + Algorithm: publicKeyAlgorithm, + PublicKey: asn1.BitString{ + Bytes: publicKeyBytes, + BitLength: len(publicKeyBytes) * 8, + }, + }, + RawAttributes: rawAttributes, + } + + tbsCSRContents, err := asn1.Marshal(tbsCSR) + if err != nil { + return + } + tbsCSR.Raw = tbsCSRContents + + signed := tbsCSRContents + if hashFunc != 0 { + h := hashFunc.New() + h.Write(signed) + signed = h.Sum(nil) + } + + var signature []byte + signature, err = key.Sign(rand, signed, hashFunc) + if err != nil { + return + } + + return asn1.Marshal(certificateRequest{ + TBSCSR: tbsCSR, + SignatureAlgorithm: sigAlgo, + SignatureValue: asn1.BitString{ + Bytes: signature, + BitLength: len(signature) * 8, + }, + }) +} + +// ParseCertificateRequest parses a single certificate request from the +// given ASN.1 DER data. +func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error) { + var csr certificateRequest + + rest, err := asn1.Unmarshal(asn1Data, &csr) + if err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, asn1.SyntaxError{Msg: "trailing data"} + } + + return parseCertificateRequest(&csr) +} + +func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error) { + out := &CertificateRequest{ + Raw: in.Raw, + RawTBSCertificateRequest: in.TBSCSR.Raw, + RawSubjectPublicKeyInfo: in.TBSCSR.PublicKey.Raw, + RawSubject: in.TBSCSR.Subject.FullBytes, + + Signature: in.SignatureValue.RightAlign(), + SignatureAlgorithm: getSignatureAlgorithmFromAI(in.SignatureAlgorithm), + + PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm), + + Version: in.TBSCSR.Version, + Attributes: parseRawAttributes(in.TBSCSR.RawAttributes), + } + + var err error + out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCSR.PublicKey) + if err != nil { + return nil, err + } + + var subject pkix.RDNSequence + if rest, err := asn1.Unmarshal(in.TBSCSR.Subject.FullBytes, &subject); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("x509: trailing data after X.509 Subject") + } + + out.Subject.FillFromRDNSequence(&subject) + + if out.Extensions, err = parseCSRExtensions(in.TBSCSR.RawAttributes); err != nil { + return nil, err + } + + for _, extension := range out.Extensions { + switch { + case extension.Id.Equal(oidExtensionSubjectAltName): + out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(extension.Value) + if err != nil { + return nil, err + } + } + } + + return out, nil +} + +// CheckSignature reports whether the signature on c is valid. +func (c *CertificateRequest) CheckSignature() error { + return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificateRequest, c.Signature, c.PublicKey) +} + +// RevocationList contains the fields used to create an X.509 v2 Certificate +// Revocation list with CreateRevocationList. +type RevocationList struct { + // SignatureAlgorithm is used to determine the signature algorithm to be + // used when signing the CRL. If 0 the default algorithm for the signing + // key will be used. + SignatureAlgorithm SignatureAlgorithm + + // RevokedCertificates is used to populate the revokedCertificates + // sequence in the CRL, it may be empty. RevokedCertificates may be nil, + // in which case an empty CRL will be created. + RevokedCertificates []pkix.RevokedCertificate + + // Number is used to populate the X.509 v2 cRLNumber extension in the CRL, + // which should be a monotonically increasing sequence number for a given + // CRL scope and CRL issuer. + Number *big.Int + // ThisUpdate is used to populate the thisUpdate field in the CRL, which + // indicates the issuance date of the CRL. + ThisUpdate time.Time + // NextUpdate is used to populate the nextUpdate field in the CRL, which + // indicates the date by which the next CRL will be issued. NextUpdate + // must be greater than ThisUpdate. + NextUpdate time.Time + // ExtraExtensions contains any additional extensions to add directly to + // the CRL. + ExtraExtensions []pkix.Extension +} + +// CreateRevocationList creates a new X.509 v2 Certificate Revocation List, +// according to RFC 5280, based on template. +// +// The CRL is signed by priv which should be the private key associated with +// the public key in the issuer certificate. +// +// The issuer may not be nil, and the crlSign bit must be set in KeyUsage in +// order to use it as a CRL issuer. +// +// The issuer distinguished name CRL field and authority key identifier +// extension are populated using the issuer certificate. issuer must have +// SubjectKeyId set. +func CreateRevocationList(rand io.Reader, template *RevocationList, issuer *Certificate, priv crypto.Signer) ([]byte, error) { + if template == nil { + return nil, errors.New("x509: template can not be nil") + } + if issuer == nil { + return nil, errors.New("x509: issuer can not be nil") + } + if (issuer.KeyUsage & KeyUsageCRLSign) == 0 { + return nil, errors.New("x509: issuer must have the crlSign key usage bit set") + } + if len(issuer.SubjectKeyId) == 0 { + return nil, errors.New("x509: issuer certificate doesn't contain a subject key identifier") + } + if template.NextUpdate.Before(template.ThisUpdate) { + return nil, errors.New("x509: template.ThisUpdate is after template.NextUpdate") + } + if template.Number == nil { + return nil, errors.New("x509: template contains nil Number field") + } + + hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) + if err != nil { + return nil, err + } + + // Force revocation times to UTC per RFC 5280. + revokedCertsUTC := make([]pkix.RevokedCertificate, len(template.RevokedCertificates)) + for i, rc := range template.RevokedCertificates { + rc.RevocationTime = rc.RevocationTime.UTC() + revokedCertsUTC[i] = rc + } + + aki, err := asn1.Marshal(authKeyId{Id: issuer.SubjectKeyId}) + if err != nil { + return nil, err + } + crlNum, err := asn1.Marshal(template.Number) + if err != nil { + return nil, err + } + + tbsCertList := pkix.TBSCertificateList{ + Version: 1, // v2 + Signature: signatureAlgorithm, + Issuer: issuer.Subject.ToRDNSequence(), + ThisUpdate: template.ThisUpdate.UTC(), + NextUpdate: template.NextUpdate.UTC(), + Extensions: []pkix.Extension{ + { + Id: oidExtensionAuthorityKeyId, + Value: aki, + }, + { + Id: oidExtensionCRLNumber, + Value: crlNum, + }, + }, + } + if len(revokedCertsUTC) > 0 { + tbsCertList.RevokedCertificates = revokedCertsUTC + } + + if len(template.ExtraExtensions) > 0 { + tbsCertList.Extensions = append(tbsCertList.Extensions, template.ExtraExtensions...) + } + + tbsCertListContents, err := asn1.Marshal(tbsCertList) + if err != nil { + return nil, err + } + + input := tbsCertListContents + if hashFunc != 0 { + h := hashFunc.New() + h.Write(tbsCertListContents) + input = h.Sum(nil) + } + var signerOpts crypto.SignerOpts = hashFunc + if template.SignatureAlgorithm.isRSAPSS() { + signerOpts = &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: hashFunc, + } + } + + signature, err := priv.Sign(rand, input, signerOpts) + if err != nil { + return nil, err + } + + return asn1.Marshal(pkix.CertificateList{ + TBSCertList: tbsCertList, + SignatureAlgorithm: signatureAlgorithm, + SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, + }) +} diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go new file mode 100644 index 0000000..f32dc7d --- /dev/null +++ b/src/crypto/x509/x509_test.go @@ -0,0 +1,3361 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509 + +import ( + "bytes" + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + _ "crypto/sha256" + _ "crypto/sha512" + "crypto/x509/pkix" + "encoding/asn1" + "encoding/base64" + "encoding/hex" + "encoding/pem" + "fmt" + "internal/testenv" + "io" + "math/big" + "net" + "net/url" + "os/exec" + "reflect" + "runtime" + "strings" + "testing" + "time" +) + +func TestParsePKCS1PrivateKey(t *testing.T) { + block, _ := pem.Decode([]byte(pemPrivateKey)) + priv, err := ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + t.Errorf("Failed to parse private key: %s", err) + return + } + if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 || + priv.PublicKey.E != rsaPrivateKey.PublicKey.E || + priv.D.Cmp(rsaPrivateKey.D) != 0 || + priv.Primes[0].Cmp(rsaPrivateKey.Primes[0]) != 0 || + priv.Primes[1].Cmp(rsaPrivateKey.Primes[1]) != 0 { + t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey) + } + + // This private key includes an invalid prime that + // rsa.PrivateKey.Validate should reject. + data := []byte("0\x16\x02\x00\x02\x02\u007f\x00\x02\x0200\x02\x0200\x02\x02\x00\x01\x02\x02\u007f\x00") + if _, err := ParsePKCS1PrivateKey(data); err == nil { + t.Errorf("parsing invalid private key did not result in an error") + } +} + +func TestPKCS1MismatchPublicKeyFormat(t *testing.T) { + + const pkixPublicKey = "30820122300d06092a864886f70d01010105000382010f003082010a0282010100dd5a0f37d3ca5232852ccc0e81eebec270e2f2c6c44c6231d852971a0aad00aa7399e9b9de444611083c59ea919a9d76c20a7be131a99045ec19a7bb452d647a72429e66b87e28be9e8187ed1d2a2a01ef3eb2360706bd873b07f2d1f1a72337aab5ec94e983e39107f52c480d404915e84d75a3db2cfd601726a128cb1d7f11492d4bdb53272e652276667220795c709b8a9b4af6489cbf48bb8173b8fb607c834a71b6e8bf2d6aab82af3c8ad7ce16d8dcf58373a6edc427f7484d09744d4c08f4e19ed07adbf6cb31243bc5d0d1145e77a08a6fc5efd208eca67d6abf2d6f38f58b6fdd7c28774fb0cc03fc4935c6e074842d2e1479d3d8787249258719f90203010001" + const errorContains = "use ParsePKIXPublicKey instead" + derBytes, _ := hex.DecodeString(pkixPublicKey) + _, err := ParsePKCS1PublicKey(derBytes) + if !strings.Contains(err.Error(), errorContains) { + t.Errorf("expected error containing %q, got %s", errorContains, err) + } +} + +func testParsePKIXPublicKey(t *testing.T, pemBytes string) (pub interface{}) { + block, _ := pem.Decode([]byte(pemBytes)) + pub, err := ParsePKIXPublicKey(block.Bytes) + if err != nil { + t.Fatalf("Failed to parse public key: %s", err) + } + + pubBytes2, err := MarshalPKIXPublicKey(pub) + if err != nil { + t.Errorf("Failed to marshal public key for the second time: %s", err) + return + } + if !bytes.Equal(pubBytes2, block.Bytes) { + t.Errorf("Reserialization of public key didn't match. got %x, want %x", pubBytes2, block.Bytes) + } + return +} + +func TestParsePKIXPublicKey(t *testing.T) { + t.Run("RSA", func(t *testing.T) { + pub := testParsePKIXPublicKey(t, pemPublicKey) + _, ok := pub.(*rsa.PublicKey) + if !ok { + t.Errorf("Value returned from ParsePKIXPublicKey was not an RSA public key") + } + }) + t.Run("Ed25519", func(t *testing.T) { + pub := testParsePKIXPublicKey(t, pemEd25519Key) + _, ok := pub.(ed25519.PublicKey) + if !ok { + t.Errorf("Value returned from ParsePKIXPublicKey was not an Ed25519 public key") + } + }) +} + +var pemPublicKey = `-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3VoPN9PKUjKFLMwOge6+ +wnDi8sbETGIx2FKXGgqtAKpzmem53kRGEQg8WeqRmp12wgp74TGpkEXsGae7RS1k +enJCnma4fii+noGH7R0qKgHvPrI2Bwa9hzsH8tHxpyM3qrXslOmD45EH9SxIDUBJ +FehNdaPbLP1gFyahKMsdfxFJLUvbUycuZSJ2ZnIgeVxwm4qbSvZInL9Iu4FzuPtg +fINKcbbovy1qq4KvPIrXzhbY3PWDc6btxCf3SE0JdE1MCPThntB62/bLMSQ7xdDR +FF53oIpvxe/SCOymfWq/LW849Ytv3Xwod0+wzAP8STXG4HSELS4UedPYeHJJJYcZ ++QIDAQAB +-----END PUBLIC KEY----- +` + +var pemPrivateKey = testingKey(` +-----BEGIN RSA TESTING KEY----- +MIICXAIBAAKBgQCxoeCUW5KJxNPxMp+KmCxKLc1Zv9Ny+4CFqcUXVUYH69L3mQ7v +IWrJ9GBfcaA7BPQqUlWxWM+OCEQZH1EZNIuqRMNQVuIGCbz5UQ8w6tS0gcgdeGX7 +J7jgCQ4RK3F/PuCM38QBLaHx988qG8NMc6VKErBjctCXFHQt14lerd5KpQIDAQAB +AoGAYrf6Hbk+mT5AI33k2Jt1kcweodBP7UkExkPxeuQzRVe0KVJw0EkcFhywKpr1 +V5eLMrILWcJnpyHE5slWwtFHBG6a5fLaNtsBBtcAIfqTQ0Vfj5c6SzVaJv0Z5rOd +7gQF6isy3t3w9IF3We9wXQKzT6q5ypPGdm6fciKQ8RnzREkCQQDZwppKATqQ41/R +vhSj90fFifrGE6aVKC1hgSpxGQa4oIdsYYHwMzyhBmWW9Xv/R+fPyr8ZwPxp2c12 +33QwOLPLAkEA0NNUb+z4ebVVHyvSwF5jhfJxigim+s49KuzJ1+A2RaSApGyBZiwS +rWvWkB471POAKUYt5ykIWVZ83zcceQiNTwJBAMJUFQZX5GDqWFc/zwGoKkeR49Yi +MTXIvf7Wmv6E++eFcnT461FlGAUHRV+bQQXGsItR/opIG7mGogIkVXa3E1MCQARX +AAA7eoZ9AEHflUeuLn9QJI/r0hyQQLEtrpwv6rDT1GCWaLII5HJ6NUFVf4TTcqxo +6vdM4QGKTJoO+SaCyP0CQFdpcxSAuzpFcKv0IlJ8XzS/cy+mweCMwyJ1PFEc4FX6 +wg/HcAJWY60xZTJDFN+Qfx8ZQvBEin6c2/h+zZi5IVY= +-----END RSA TESTING KEY----- +`) + +// pemEd25519Key is the example from RFC 8410, Secrion 4. +var pemEd25519Key = ` +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE= +-----END PUBLIC KEY----- +` + +func TestPKIXMismatchPublicKeyFormat(t *testing.T) { + + const pkcs1PublicKey = "308201080282010100817cfed98bcaa2e2a57087451c7674e0c675686dc33ff1268b0c2a6ee0202dec710858ee1c31bdf5e7783582e8ca800be45f3275c6576adc35d98e26e95bb88ca5beb186f853b8745d88bc9102c5f38753bcda519fb05948d5c77ac429255ff8aaf27d9f45d1586e95e2e9ba8a7cb771b8a09dd8c8fed3f933fd9b439bc9f30c475953418ef25f71a2b6496f53d94d39ce850aa0cc75d445b5f5b4f4ee4db78ab197a9a8d8a852f44529a007ac0ac23d895928d60ba538b16b0b087a7f903ed29770e215019b77eaecc360f35f7ab11b6d735978795b2c4a74e5bdea4dc6594cd67ed752a108e666729a753ab36d6c4f606f8760f507e1765be8cd744007e629020103" + const errorContains = "use ParsePKCS1PublicKey instead" + derBytes, _ := hex.DecodeString(pkcs1PublicKey) + _, err := ParsePKIXPublicKey(derBytes) + if !strings.Contains(err.Error(), errorContains) { + t.Errorf("expected error containing %q, got %s", errorContains, err) + } +} + +var testPrivateKey *rsa.PrivateKey + +func init() { + block, _ := pem.Decode([]byte(pemPrivateKey)) + + var err error + if testPrivateKey, err = ParsePKCS1PrivateKey(block.Bytes); err != nil { + panic("Failed to parse private key: " + err.Error()) + } +} + +func bigFromString(s string) *big.Int { + ret := new(big.Int) + ret.SetString(s, 10) + return ret +} + +func fromBase10(base10 string) *big.Int { + i := new(big.Int) + i.SetString(base10, 10) + return i +} + +func bigFromHexString(s string) *big.Int { + ret := new(big.Int) + ret.SetString(s, 16) + return ret +} + +var rsaPrivateKey = &rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + N: bigFromString("124737666279038955318614287965056875799409043964547386061640914307192830334599556034328900586693254156136128122194531292927142396093148164407300419162827624945636708870992355233833321488652786796134504707628792159725681555822420087112284637501705261187690946267527866880072856272532711620639179596808018872997"), + E: 65537, + }, + D: bigFromString("69322600686866301945688231018559005300304807960033948687567105312977055197015197977971637657636780793670599180105424702854759606794705928621125408040473426339714144598640466128488132656829419518221592374964225347786430566310906679585739468938549035854760501049443920822523780156843263434219450229353270690889"), + Primes: []*big.Int{ + bigFromString("11405025354575369741595561190164746858706645478381139288033759331174478411254205003127028642766986913445391069745480057674348716675323735886284176682955723"), + bigFromString("10937079261204603443118731009201819560867324167189758120988909645641782263430128449826989846631183550578761324239709121189827307416350485191350050332642639"), + }, +} + +func TestMarshalRSAPrivateKey(t *testing.T) { + priv := &rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"), + E: 3, + }, + D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"), + Primes: []*big.Int{ + fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"), + fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"), + fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"), + }, + } + + derBytes := MarshalPKCS1PrivateKey(priv) + + priv2, err := ParsePKCS1PrivateKey(derBytes) + if err != nil { + t.Errorf("error parsing serialized key: %s", err) + return + } + if priv.PublicKey.N.Cmp(priv2.PublicKey.N) != 0 || + priv.PublicKey.E != priv2.PublicKey.E || + priv.D.Cmp(priv2.D) != 0 || + len(priv2.Primes) != 3 || + priv.Primes[0].Cmp(priv2.Primes[0]) != 0 || + priv.Primes[1].Cmp(priv2.Primes[1]) != 0 || + priv.Primes[2].Cmp(priv2.Primes[2]) != 0 { + t.Errorf("got:%+v want:%+v", priv, priv2) + } +} + +func TestMarshalRSAPublicKey(t *testing.T) { + pub := &rsa.PublicKey{ + N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"), + E: 3, + } + derBytes := MarshalPKCS1PublicKey(pub) + pub2, err := ParsePKCS1PublicKey(derBytes) + if err != nil { + t.Errorf("ParsePKCS1PublicKey: %s", err) + } + if pub.N.Cmp(pub2.N) != 0 || pub.E != pub2.E { + t.Errorf("ParsePKCS1PublicKey = %+v, want %+v", pub, pub2) + } + + // It's never been documented that asn1.Marshal/Unmarshal on rsa.PublicKey works, + // but it does, and we know of code that depends on it. + // Lock that in, even though we'd prefer that people use MarshalPKCS1PublicKey and ParsePKCS1PublicKey. + derBytes2, err := asn1.Marshal(*pub) + if err != nil { + t.Errorf("Marshal(rsa.PublicKey): %v", err) + } else if !bytes.Equal(derBytes, derBytes2) { + t.Errorf("Marshal(rsa.PublicKey) = %x, want %x", derBytes2, derBytes) + } + pub3 := new(rsa.PublicKey) + rest, err := asn1.Unmarshal(derBytes, pub3) + if err != nil { + t.Errorf("Unmarshal(rsa.PublicKey): %v", err) + } + if len(rest) != 0 || pub.N.Cmp(pub3.N) != 0 || pub.E != pub3.E { + t.Errorf("Unmarshal(rsa.PublicKey) = %+v, %q want %+v, %q", pub, rest, pub2, []byte(nil)) + } + + publicKeys := []struct { + derBytes []byte + expectedErrSubstr string + }{ + { + derBytes: []byte{ + 0x30, 6, // SEQUENCE, 6 bytes + 0x02, 1, // INTEGER, 1 byte + 17, + 0x02, 1, // INTEGER, 1 byte + 3, // 3 + }, + }, { + derBytes: []byte{ + 0x30, 6, // SEQUENCE + 0x02, 1, // INTEGER, 1 byte + 0xff, // -1 + 0x02, 1, // INTEGER, 1 byte + 3, + }, + expectedErrSubstr: "zero or negative", + }, { + derBytes: []byte{ + 0x30, 6, // SEQUENCE + 0x02, 1, // INTEGER, 1 byte + 17, + 0x02, 1, // INTEGER, 1 byte + 0xff, // -1 + }, + expectedErrSubstr: "zero or negative", + }, { + derBytes: []byte{ + 0x30, 6, // SEQUENCE + 0x02, 1, // INTEGER, 1 byte + 17, + 0x02, 1, // INTEGER, 1 byte + 3, + 1, + }, + expectedErrSubstr: "trailing data", + }, { + derBytes: []byte{ + 0x30, 9, // SEQUENCE + 0x02, 1, // INTEGER, 1 byte + 17, + 0x02, 4, // INTEGER, 4 bytes + 0x7f, 0xff, 0xff, 0xff, + }, + }, { + derBytes: []byte{ + 0x30, 10, // SEQUENCE + 0x02, 1, // INTEGER, 1 byte + 17, + 0x02, 5, // INTEGER, 5 bytes + 0x00, 0x80, 0x00, 0x00, 0x00, + }, + // On 64-bit systems, encoding/asn1 will accept the + // public exponent, but ParsePKCS1PublicKey will return + // an error. On 32-bit systems, encoding/asn1 will + // return the error. The common substring of both error + // is the word “large”. + expectedErrSubstr: "large", + }, + } + + for i, test := range publicKeys { + shouldFail := len(test.expectedErrSubstr) > 0 + pub, err := ParsePKCS1PublicKey(test.derBytes) + if shouldFail { + if err == nil { + t.Errorf("#%d: unexpected success, got %#v", i, pub) + } else if !strings.Contains(err.Error(), test.expectedErrSubstr) { + t.Errorf("#%d: expected error containing %q, got %s", i, test.expectedErrSubstr, err) + } + } else { + if err != nil { + t.Errorf("#%d: unexpected failure: %s", i, err) + continue + } + reserialized := MarshalPKCS1PublicKey(pub) + if !bytes.Equal(reserialized, test.derBytes) { + t.Errorf("#%d: failed to reserialize: got %x, expected %x", i, reserialized, test.derBytes) + } + } + } +} + +type matchHostnamesTest struct { + pattern, host string + ok bool +} + +var matchHostnamesTests = []matchHostnamesTest{ + {"a.b.c", "a.b.c", true}, + {"a.b.c", "b.b.c", false}, + {"", "b.b.c", false}, + {"a.b.c", "", false}, + {"example.com", "example.com", true}, + {"example.com", "www.example.com", false}, + {"*.example.com", "example.com", false}, + {"*.example.com", "www.example.com", true}, + {"*.example.com", "www.example.com.", true}, + {"*.example.com", "xyz.www.example.com", false}, + {"*.example.com", "https://www.example.com", false}, // Issue 27591 + {"*.example..com", "www.example..com", false}, + {"www.example..com", "www.example..com", true}, + {"*.*.example.com", "xyz.www.example.com", false}, + {"*.www.*.com", "xyz.www.example.com", false}, + {"*bar.example.com", "foobar.example.com", false}, + {"f*.example.com", "foobar.example.com", false}, + {"www.example.com", "*.example.com", false}, + {"", ".", false}, + {".", "", false}, + {".", ".", false}, + {"example.com", "example.com.", true}, + {"example.com.", "example.com", false}, + {"example.com.", "example.com.", true}, // perfect matches allow trailing dots in patterns + {"*.com.", "example.com.", false}, + {"*.com.", "example.com", false}, + {"*.com", "example.com", true}, + {"*.com", "example.com.", true}, + {"foo:bar", "foo:bar", true}, + {"*.foo:bar", "xxx.foo:bar", false}, + {"*.2.3.4", "1.2.3.4", false}, + {"*.2.3.4", "[1.2.3.4]", false}, + {"*:4860:4860::8888", "2001:4860:4860::8888", false}, + {"*:4860:4860::8888", "[2001:4860:4860::8888]", false}, + {"2001:4860:4860::8888", "2001:4860:4860::8888", false}, + {"2001:4860:4860::8888", "[2001:4860:4860::8888]", false}, + {"[2001:4860:4860::8888]", "2001:4860:4860::8888", false}, + {"[2001:4860:4860::8888]", "[2001:4860:4860::8888]", false}, +} + +func TestMatchHostnames(t *testing.T) { + for i, test := range matchHostnamesTests { + c := &Certificate{DNSNames: []string{test.pattern}} + r := c.VerifyHostname(test.host) == nil + if r != test.ok { + t.Errorf("#%d mismatch got: %t want: %t when matching '%s' against '%s'", i, r, test.ok, test.host, test.pattern) + } + } +} + +func TestMatchIP(t *testing.T) { + // Check that pattern matching is working. + c := &Certificate{ + DNSNames: []string{"*.foo.bar.baz"}, + Subject: pkix.Name{ + CommonName: "*.foo.bar.baz", + }, + } + err := c.VerifyHostname("quux.foo.bar.baz") + if err != nil { + t.Fatalf("VerifyHostname(quux.foo.bar.baz): %v", err) + } + + // But check that if we change it to be matching against an IP address, + // it is rejected. + c = &Certificate{ + DNSNames: []string{"*.2.3.4"}, + Subject: pkix.Name{ + CommonName: "*.2.3.4", + }, + } + err = c.VerifyHostname("1.2.3.4") + if err == nil { + t.Fatalf("VerifyHostname(1.2.3.4) should have failed, did not") + } + + c = &Certificate{ + IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}, + } + err = c.VerifyHostname("127.0.0.1") + if err != nil { + t.Fatalf("VerifyHostname(127.0.0.1): %v", err) + } + err = c.VerifyHostname("::1") + if err != nil { + t.Fatalf("VerifyHostname(::1): %v", err) + } + err = c.VerifyHostname("[::1]") + if err != nil { + t.Fatalf("VerifyHostname([::1]): %v", err) + } +} + +func TestCertificateParse(t *testing.T) { + s, _ := base64.StdEncoding.DecodeString(certBytes) + certs, err := ParseCertificates(s) + if err != nil { + t.Error(err) + } + if len(certs) != 2 { + t.Errorf("Wrong number of certs: got %d want 2", len(certs)) + return + } + + err = certs[0].CheckSignatureFrom(certs[1]) + if err != nil { + t.Error(err) + } + + if err := certs[0].VerifyHostname("mail.google.com"); err != nil { + t.Error(err) + } + + const expectedExtensions = 10 + if n := len(certs[0].Extensions); n != expectedExtensions { + t.Errorf("want %d extensions, got %d", expectedExtensions, n) + } +} + +func TestCertificateEqualOnNil(t *testing.T) { + cNonNil := new(Certificate) + var cNil1, cNil2 *Certificate + if !cNil1.Equal(cNil2) { + t.Error("Nil certificates: cNil1 is not equal to cNil2") + } + if !cNil2.Equal(cNil1) { + t.Error("Nil certificates: cNil2 is not equal to cNil1") + } + if cNil1.Equal(cNonNil) { + t.Error("Unexpectedly cNil1 is equal to cNonNil") + } + if cNonNil.Equal(cNil1) { + t.Error("Unexpectedly cNonNil is equal to cNil1") + } +} + +func TestMismatchedSignatureAlgorithm(t *testing.T) { + der, _ := pem.Decode([]byte(rsaPSSSelfSignedPEM)) + if der == nil { + t.Fatal("Failed to find PEM block") + } + + cert, err := ParseCertificate(der.Bytes) + if err != nil { + t.Fatal(err) + } + + if err = cert.CheckSignature(ECDSAWithSHA256, nil, nil); err == nil { + t.Fatal("CheckSignature unexpectedly return no error") + } + + const expectedSubstring = " but have public key of type " + if !strings.Contains(err.Error(), expectedSubstring) { + t.Errorf("Expected error containing %q, but got %q", expectedSubstring, err) + } +} + +var certBytes = "MIIE0jCCA7qgAwIBAgIQWcvS+TTB3GwCAAAAAGEAWzANBgkqhkiG9w0BAQsFADBCMQswCQYD" + + "VQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMRMwEQYDVQQDEwpHVFMg" + + "Q0EgMU8xMB4XDTIwMDQwMTEyNTg1NloXDTIwMDYyNDEyNTg1NlowaTELMAkGA1UEBhMCVVMx" + + "EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEzARBgNVBAoT" + + "Ckdvb2dsZSBMTEMxGDAWBgNVBAMTD21haWwuZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqG" + + "SM49AwEHA0IABO+dYiPnkFl+cZVf6mrWeNp0RhQcJSBGH+sEJxjvc+cYlW3QJCnm57qlpFdd" + + "pz3MPyVejvXQdM6iI1mEWP4C2OujggJmMIICYjAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAww" + + "CgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUI6pZhnQ/lQgmPDwSKR2A54G7" + + "AS4wHwYDVR0jBBgwFoAUmNH4bhDrz5vsYJ8YkBug630J/SswZAYIKwYBBQUHAQEEWDBWMCcG" + + "CCsGAQUFBzABhhtodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHMxbzEwKwYIKwYBBQUHMAKGH2h0" + + "dHA6Ly9wa2kuZ29vZy9nc3IyL0dUUzFPMS5jcnQwLAYDVR0RBCUwI4IPbWFpbC5nb29nbGUu" + + "Y29tghBpbmJveC5nb29nbGUuY29tMCEGA1UdIAQaMBgwCAYGZ4EMAQICMAwGCisGAQQB1nkC" + + "BQMwLwYDVR0fBCgwJjAkoCKgIIYeaHR0cDovL2NybC5wa2kuZ29vZy9HVFMxTzEuY3JsMIIB" + + "AwYKKwYBBAHWeQIEAgSB9ASB8QDvAHYAsh4FzIuizYogTodm+Su5iiUgZ2va+nDnsklTLe+L" + + "kF4AAAFxNgmxKgAABAMARzBFAiEA12/OHdTGXQ3qHHC3NvYCyB8aEz/+ZFOLCAI7lhqj28sC" + + "IG2/7Yz2zK6S6ai+dH7cTMZmoFGo39gtaTqtZAqEQX7nAHUAXqdz+d9WwOe1Nkh90EngMnqR" + + "mgyEoRIShBh1loFxRVgAAAFxNgmxTAAABAMARjBEAiA7PNq+MFfv6O9mBkxFViS2TfU66yRB" + + "/njcebWglLQjZQIgOyRKhxlEizncFRml7yn4Bg48ktXKGjo+uiw6zXEINb0wDQYJKoZIhvcN" + + "AQELBQADggEBADM2Rh306Q10PScsolYMxH1B/K4Nb2WICvpY0yDPJFdnGjqCYym196TjiEvs" + + "R6etfeHdyzlZj6nh82B4TVyHjiWM02dQgPalOuWQcuSy0OvLh7F1E7CeHzKlczdFPBTOTdM1" + + "RDTxlvw1bAqc0zueM8QIAyEy3opd7FxAcGQd5WRIJhzLBL+dbbMOW/LTeW7cm/Xzq8cgCybN" + + "BSZAvhjseJ1L29OlCTZL97IfnX0IlFQzWuvvHy7V2B0E3DHlzM0kjwkkCKDUUp/wajv2NZKC" + + "TkhEyERacZRKc9U0ADxwsAzHrdz5+5zfD2usEV/MQ5V6d8swLXs+ko0X6swrd4YCiB8wggRK" + + "MIIDMqADAgECAg0B47SaoY2KqYElaVC4MA0GCSqGSIb3DQEBCwUAMEwxIDAeBgNVBAsTF0ds" + + "b2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpH" + + "bG9iYWxTaWduMB4XDTE3MDYxNTAwMDA0MloXDTIxMTIxNTAwMDA0MlowQjELMAkGA1UEBhMC" + + "VVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczETMBEGA1UEAxMKR1RTIENBIDFP" + + "MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAYz0XUi83TnORA73603WkhG8nP" + + "PI5MdbkPMRmEPZ48Ke9QDRCTbwWAgJ8qoL0SSwLhPZ9YFiT+MJ8LdHdVkx1L903hkoIQ9lGs" + + "DMOyIpQPNGuYEEnnC52DOd0gxhwt79EYYWXnI4MgqCMS/9Ikf9Qv50RqW03XUGawr55CYwX7" + + "4BzEY2Gvn2oz/2KXvUjZ03wUZ9x13C5p6PhteGnQtxAFuPExwjsk/RozdPgj4OxrGYoWxuPN" + + "pM0L27OkWWA4iDutHbnGjKdTG/y82aSrvN08YdeTFZjugb2P4mRHIEAGTtesl+i5wFkSoUkl" + + "I+TtcDQspbRjfPmjPYPRzW0krAcCAwEAAaOCATMwggEvMA4GA1UdDwEB/wQEAwIBhjAdBgNV" + + "HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E" + + "FgQUmNH4bhDrz5vsYJ8YkBug630J/SswHwYDVR0jBBgwFoAUm+IHV2ccHsBqBt5ZtJot39wZ" + + "hi4wNQYIKwYBBQUHAQEEKTAnMCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5wa2kuZ29vZy9n" + + "c3IyMDIGA1UdHwQrMCkwJ6AloCOGIWh0dHA6Ly9jcmwucGtpLmdvb2cvZ3NyMi9nc3IyLmNy" + + "bDA/BgNVHSAEODA2MDQGBmeBDAECAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3BraS5nb29n" + + "L3JlcG9zaXRvcnkvMA0GCSqGSIb3DQEBCwUAA4IBAQAagD42efvzLqlGN31eVBY1rsdOCJn+" + + "vdE0aSZSZgc9CrpJy2L08RqO/BFPaJZMdCvTZ96yo6oFjYRNTCBlD6WW2g0W+Gw7228EI4hr" + + "OmzBYL1on3GO7i1YNAfw1VTphln9e14NIZT1jMmo+NjyrcwPGvOap6kEJ/mjybD/AnhrYbrH" + + "NSvoVvpPwxwM7bY8tEvq7czhPOzcDYzWPpvKQliLzBYhF0C8otZm79rEFVvNiaqbCSbnMtIN" + + "bmcgAlsQsJAJnAwfnq3YO+qh/GzoEFwIUhlRKnG7rHq13RXtK8kIKiyKtKYhq2P/11JJUNCJ" + + "t63yr/tQri/hlQ3zRq2dnPXK" + +func parseCIDR(s string) *net.IPNet { + _, net, err := net.ParseCIDR(s) + if err != nil { + panic(err) + } + return net +} + +func parseURI(s string) *url.URL { + uri, err := url.Parse(s) + if err != nil { + panic(err) + } + return uri +} + +func TestCreateSelfSignedCertificate(t *testing.T) { + random := rand.Reader + + ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("Failed to generate ECDSA key: %s", err) + } + + ed25519Pub, ed25519Priv, err := ed25519.GenerateKey(random) + if err != nil { + t.Fatalf("Failed to generate Ed25519 key: %s", err) + } + + tests := []struct { + name string + pub, priv interface{} + checkSig bool + sigAlgo SignatureAlgorithm + }{ + {"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA1WithRSA}, + {"RSA/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, + {"ECDSA/RSA", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSA}, + {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA1}, + {"RSAPSS/RSAPSS", &testPrivateKey.PublicKey, testPrivateKey, true, SHA256WithRSAPSS}, + {"ECDSA/RSAPSS", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSAPSS}, + {"RSAPSS/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, + {"Ed25519", ed25519Pub, ed25519Priv, true, PureEd25519}, + } + + testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth} + testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}} + extraExtensionData := []byte("extra extension") + + for _, test := range tests { + commonName := "test.example.com" + template := Certificate{ + // SerialNumber is negative to ensure that negative + // values are parsed. This is due to the prevalence of + // buggy code that produces certificates with negative + // serial numbers. + SerialNumber: big.NewInt(-1), + Subject: pkix.Name{ + CommonName: commonName, + Organization: []string{"Σ Acme Co"}, + Country: []string{"US"}, + ExtraNames: []pkix.AttributeTypeAndValue{ + { + Type: []int{2, 5, 4, 42}, + Value: "Gopher", + }, + // This should override the Country, above. + { + Type: []int{2, 5, 4, 6}, + Value: "NL", + }, + }, + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + + SignatureAlgorithm: test.sigAlgo, + + SubjectKeyId: []byte{1, 2, 3, 4}, + KeyUsage: KeyUsageCertSign, + + ExtKeyUsage: testExtKeyUsage, + UnknownExtKeyUsage: testUnknownExtKeyUsage, + + BasicConstraintsValid: true, + IsCA: true, + + OCSPServer: []string{"http://ocsp.example.com"}, + IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"}, + + DNSNames: []string{"test.example.com"}, + EmailAddresses: []string{"gopher@golang.org"}, + IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, + URIs: []*url.URL{parseURI("https://foo.com/wibble#foo")}, + + PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}}, + PermittedDNSDomains: []string{".example.com", "example.com"}, + ExcludedDNSDomains: []string{"bar.example.com"}, + PermittedIPRanges: []*net.IPNet{parseCIDR("192.168.1.1/16"), parseCIDR("1.2.3.4/8")}, + ExcludedIPRanges: []*net.IPNet{parseCIDR("2001:db8::/48")}, + PermittedEmailAddresses: []string{"foo@example.com"}, + ExcludedEmailAddresses: []string{".example.com", "example.com"}, + PermittedURIDomains: []string{".bar.com", "bar.com"}, + ExcludedURIDomains: []string{".bar2.com", "bar2.com"}, + + CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"}, + + ExtraExtensions: []pkix.Extension{ + { + Id: []int{1, 2, 3, 4}, + Value: extraExtensionData, + }, + // This extension should override the SubjectKeyId, above. + { + Id: oidExtensionSubjectKeyId, + Critical: false, + Value: []byte{0x04, 0x04, 4, 3, 2, 1}, + }, + }, + } + + derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv) + if err != nil { + t.Errorf("%s: failed to create certificate: %s", test.name, err) + continue + } + + cert, err := ParseCertificate(derBytes) + if err != nil { + t.Errorf("%s: failed to parse certificate: %s", test.name, err) + continue + } + + if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) { + t.Errorf("%s: failed to parse policy identifiers: got:%#v want:%#v", test.name, cert.PolicyIdentifiers, template.PolicyIdentifiers) + } + + if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" { + t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains) + } + + if len(cert.ExcludedDNSDomains) != 1 || cert.ExcludedDNSDomains[0] != "bar.example.com" { + t.Errorf("%s: failed to parse name constraint exclusions: %#v", test.name, cert.ExcludedDNSDomains) + } + + if len(cert.PermittedIPRanges) != 2 || cert.PermittedIPRanges[0].String() != "192.168.0.0/16" || cert.PermittedIPRanges[1].String() != "1.0.0.0/8" { + t.Errorf("%s: failed to parse IP constraints: %#v", test.name, cert.PermittedIPRanges) + } + + if len(cert.ExcludedIPRanges) != 1 || cert.ExcludedIPRanges[0].String() != "2001:db8::/48" { + t.Errorf("%s: failed to parse IP constraint exclusions: %#v", test.name, cert.ExcludedIPRanges) + } + + if len(cert.PermittedEmailAddresses) != 1 || cert.PermittedEmailAddresses[0] != "foo@example.com" { + t.Errorf("%s: failed to parse permitted email addreses: %#v", test.name, cert.PermittedEmailAddresses) + } + + if len(cert.ExcludedEmailAddresses) != 2 || cert.ExcludedEmailAddresses[0] != ".example.com" || cert.ExcludedEmailAddresses[1] != "example.com" { + t.Errorf("%s: failed to parse excluded email addreses: %#v", test.name, cert.ExcludedEmailAddresses) + } + + if len(cert.PermittedURIDomains) != 2 || cert.PermittedURIDomains[0] != ".bar.com" || cert.PermittedURIDomains[1] != "bar.com" { + t.Errorf("%s: failed to parse permitted URIs: %#v", test.name, cert.PermittedURIDomains) + } + + if len(cert.ExcludedURIDomains) != 2 || cert.ExcludedURIDomains[0] != ".bar2.com" || cert.ExcludedURIDomains[1] != "bar2.com" { + t.Errorf("%s: failed to parse excluded URIs: %#v", test.name, cert.ExcludedURIDomains) + } + + if cert.Subject.CommonName != commonName { + t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName) + } + + if len(cert.Subject.Country) != 1 || cert.Subject.Country[0] != "NL" { + t.Errorf("%s: ExtraNames didn't override Country", test.name) + } + + for _, ext := range cert.Extensions { + if ext.Id.Equal(oidExtensionSubjectAltName) { + if ext.Critical { + t.Fatal("SAN extension is marked critical") + } + } + } + + found := false + for _, atv := range cert.Subject.Names { + if atv.Type.Equal([]int{2, 5, 4, 42}) { + found = true + break + } + } + if !found { + t.Errorf("%s: Names didn't contain oid 2.5.4.42 from ExtraNames", test.name) + } + + if cert.Issuer.CommonName != commonName { + t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName) + } + + if cert.SignatureAlgorithm != test.sigAlgo { + t.Errorf("%s: SignatureAlgorithm wasn't copied from template. Got %v, want %v", test.name, cert.SignatureAlgorithm, test.sigAlgo) + } + + if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) { + t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage) + } + + if !reflect.DeepEqual(cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) { + t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) + } + + if !reflect.DeepEqual(cert.OCSPServer, template.OCSPServer) { + t.Errorf("%s: OCSP servers differ from template. Got %v, want %v", test.name, cert.OCSPServer, template.OCSPServer) + } + + if !reflect.DeepEqual(cert.IssuingCertificateURL, template.IssuingCertificateURL) { + t.Errorf("%s: Issuing certificate URLs differ from template. Got %v, want %v", test.name, cert.IssuingCertificateURL, template.IssuingCertificateURL) + } + + if !reflect.DeepEqual(cert.DNSNames, template.DNSNames) { + t.Errorf("%s: SAN DNS names differ from template. Got %v, want %v", test.name, cert.DNSNames, template.DNSNames) + } + + if !reflect.DeepEqual(cert.EmailAddresses, template.EmailAddresses) { + t.Errorf("%s: SAN emails differ from template. Got %v, want %v", test.name, cert.EmailAddresses, template.EmailAddresses) + } + + if len(cert.URIs) != 1 || cert.URIs[0].String() != "https://foo.com/wibble#foo" { + t.Errorf("%s: URIs differ from template. Got %v, want %v", test.name, cert.URIs, template.URIs) + } + + if !reflect.DeepEqual(cert.IPAddresses, template.IPAddresses) { + t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses) + } + + if !reflect.DeepEqual(cert.CRLDistributionPoints, template.CRLDistributionPoints) { + t.Errorf("%s: CRL distribution points differ from template. Got %v, want %v", test.name, cert.CRLDistributionPoints, template.CRLDistributionPoints) + } + + if !bytes.Equal(cert.SubjectKeyId, []byte{4, 3, 2, 1}) { + t.Errorf("%s: ExtraExtensions didn't override SubjectKeyId", test.name) + } + + if !bytes.Contains(derBytes, extraExtensionData) { + t.Errorf("%s: didn't find extra extension in DER output", test.name) + } + + if test.checkSig { + err = cert.CheckSignatureFrom(cert) + if err != nil { + t.Errorf("%s: signature verification failed: %s", test.name, err) + } + } + } +} + +// Self-signed certificate using ECDSA with SHA1 & secp256r1 +var ecdsaSHA1CertPem = ` +-----BEGIN CERTIFICATE----- +MIICDjCCAbUCCQDF6SfN0nsnrjAJBgcqhkjOPQQBMIGPMQswCQYDVQQGEwJVUzET +MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMG +A1UECgwMR29vZ2xlLCBJbmMuMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG +CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIwMjAyMDUw +WhcNMjIwNTE4MjAyMDUwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm +b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTATBgNVBAoMDEdvb2dsZSwg +SW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGdv +bGFuZy1kZXZAZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Wgn +WQDo5+bz71T0327ERgd5SDDXFbXLpzIZDXTkjpe8QTEbsF+ezsQfrekrpDPC4Cd3 +P9LY0tG+aI8IyVKdUjAJBgcqhkjOPQQBA0gAMEUCIGlsqMcRqWVIWTD6wXwe6Jk2 +DKxL46r/FLgJYnzBEH99AiEA3fBouObsvV1R3oVkb4BQYnD4/4LeId6lAT43YvyV +a/A= +-----END CERTIFICATE----- +` + +// Self-signed certificate using ECDSA with SHA256 & secp256r1 +var ecdsaSHA256p256CertPem = ` +-----BEGIN CERTIFICATE----- +MIICDzCCAbYCCQDlsuMWvgQzhTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT +BgNVBAoMDEdvb2dsZSwgSW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAh +BgkqhkiG9w0BCQEWFGdvbGFuZy1kZXZAZ21haWwuY29tMB4XDTEyMDUyMTAwMTkx +NloXDTIyMDUxOTAwMTkxNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp +Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYDVQQKDAxHb29nbGUs +IEluYy4xFzAVBgNVBAMMDnd3dy5nb29nbGUuY29tMSMwIQYJKoZIhvcNAQkBFhRn +b2xhbmctZGV2QGdtYWlsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMt +2ErhxAty5EJRu9yM+MTy+hUXm3pdW1ensAv382KoGExSXAFWP7pjJnNtHO+XSwVm +YNtqjcAGFKpweoN//kQwCgYIKoZIzj0EAwIDRwAwRAIgIYSaUA/IB81gjbIw/hUV +70twxJr5EcgOo0hLp3Jm+EYCIFDO3NNcgmURbJ1kfoS3N/0O+irUtoPw38YoNkqJ +h5wi +-----END CERTIFICATE----- +` + +// Self-signed certificate using ECDSA with SHA256 & secp384r1 +var ecdsaSHA256p384CertPem = ` +-----BEGIN CERTIFICATE----- +MIICSjCCAdECCQDje/no7mXkVzAKBggqhkjOPQQDAjCBjjELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS +BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG +CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMDYxMDM0 +WhcNMjIwNTE5MDYxMDM0WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm +b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg +SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s +YW5nLWRldkBnbWFpbC5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARRuzRNIKRK +jIktEmXanNmrTR/q/FaHXLhWRZ6nHWe26Fw7Rsrbk+VjGy4vfWtNn7xSFKrOu5ze +qxKnmE0h5E480MNgrUiRkaGO2GMJJVmxx20aqkXOk59U8yGA4CghE6MwCgYIKoZI +zj0EAwIDZwAwZAIwBZEN8gvmRmfeP/9C1PRLzODIY4JqWub2PLRT4mv9GU+yw3Gr +PU9A3CHMdEcdw/MEAjBBO1lId8KOCh9UZunsSMfqXiVurpzmhWd6VYZ/32G+M+Mh +3yILeYQzllt/g0rKVRk= +-----END CERTIFICATE----- +` + +// Self-signed certificate using ECDSA with SHA384 & secp521r1 +var ecdsaSHA384p521CertPem = ` +-----BEGIN CERTIFICATE----- +MIICljCCAfcCCQDhp1AFD/ahKjAKBggqhkjOPQQDAzCBjjELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS +BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG +CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMTUwNDI5 +WhcNMjIwNTE5MTUwNDI5WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm +b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg +SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s +YW5nLWRldkBnbWFpbC5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACqx9Rv +IssRs1LWYcNN+WffwlHw4Tv3y8/LIAA9MF1ZScIonU9nRMxt4a2uGJVCPDw6JHpz +PaYc0E9puLoE9AfKpwFr59Jkot7dBg55SKPEFkddoip/rvmN7NPAWjMBirOwjOkm +8FPthvPhGPqsu9AvgVuHu3PosWiHGNrhh379pva8MzAKBggqhkjOPQQDAwOBjAAw +gYgCQgEHNmswkUdPpHqrVxp9PvLVl+xxPuHBkT+75z9JizyxtqykHQo9Uh6SWCYH +BF9KLolo01wMt8DjoYP5Fb3j5MH7xwJCAbWZzTOp4l4DPkIvAh4LeC4VWbwPPyqh +kBg71w/iEcSY3wUKgHGcJJrObZw7wys91I5kENljqw/Samdr3ka+jBJa +-----END CERTIFICATE----- +` + +var ecdsaTests = []struct { + sigAlgo SignatureAlgorithm + pemCert string +}{ + {ECDSAWithSHA1, ecdsaSHA1CertPem}, + {ECDSAWithSHA256, ecdsaSHA256p256CertPem}, + {ECDSAWithSHA256, ecdsaSHA256p384CertPem}, + {ECDSAWithSHA384, ecdsaSHA384p521CertPem}, +} + +func TestECDSA(t *testing.T) { + for i, test := range ecdsaTests { + pemBlock, _ := pem.Decode([]byte(test.pemCert)) + cert, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + t.Errorf("%d: failed to parse certificate: %s", i, err) + continue + } + if sa := cert.SignatureAlgorithm; sa != test.sigAlgo { + t.Errorf("%d: signature algorithm is %v, want %v", i, sa, test.sigAlgo) + } + if parsedKey, ok := cert.PublicKey.(*ecdsa.PublicKey); !ok { + t.Errorf("%d: wanted an ECDSA public key but found: %#v", i, parsedKey) + } + if pka := cert.PublicKeyAlgorithm; pka != ECDSA { + t.Errorf("%d: public key algorithm is %v, want ECDSA", i, pka) + } + if err = cert.CheckSignatureFrom(cert); err != nil { + t.Errorf("%d: certificate verification failed: %s", i, err) + } + } +} + +// Self-signed certificate using DSA with SHA1 +var dsaCertPem = `-----BEGIN CERTIFICATE----- +MIIEDTCCA82gAwIBAgIJALHPghaoxeDhMAkGByqGSM44BAMweTELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAk5DMQ8wDQYDVQQHEwZOZXd0b24xFDASBgNVBAoTC0dvb2ds +ZSwgSW5jMRIwEAYDVQQDEwlKb24gQWxsaWUxIjAgBgkqhkiG9w0BCQEWE2pvbmFs +bGllQGdvb2dsZS5jb20wHhcNMTEwNTE0MDMwMTQ1WhcNMTEwNjEzMDMwMTQ1WjB5 +MQswCQYDVQQGEwJVUzELMAkGA1UECBMCTkMxDzANBgNVBAcTBk5ld3RvbjEUMBIG +A1UEChMLR29vZ2xlLCBJbmMxEjAQBgNVBAMTCUpvbiBBbGxpZTEiMCAGCSqGSIb3 +DQEJARYTam9uYWxsaWVAZ29vZ2xlLmNvbTCCAbcwggEsBgcqhkjOOAQBMIIBHwKB +gQC8hLUnQ7FpFYu4WXTj6DKvXvz8QrJkNJCVMTpKAT7uBpobk32S5RrPKXocd4gN +8lyGB9ggS03EVlEwXvSmO0DH2MQtke2jl9j1HLydClMf4sbx5V6TV9IFw505U1iW +jL7awRMgxge+FsudtJK254FjMFo03ZnOQ8ZJJ9E6AEDrlwIVAJpnBn9moyP11Ox5 +Asc/5dnjb6dPAoGBAJFHd4KVv1iTVCvEG6gGiYop5DJh28hUQcN9kul+2A0yPUSC +X93oN00P8Vh3eYgSaCWZsha7zDG53MrVJ0Zf6v/X/CoZNhLldeNOepivTRAzn+Rz +kKUYy5l1sxYLHQKF0UGNCXfFKZT0PCmgU+PWhYNBBMn6/cIh44vp85ideo5CA4GE +AAKBgFmifCafzeRaohYKXJgMGSEaggCVCRq5xdyDCat+wbOkjC4mfG01/um3G8u5 +LxasjlWRKTR/tcAL7t0QuokVyQaYdVypZXNaMtx1db7YBuHjj3aP+8JOQRI9xz8c +bp5NDJ5pISiFOv4p3GZfqZPcqckDt78AtkQrmnal2txhhjF6o4HeMIHbMB0GA1Ud +DgQWBBQVyyr7hO11ZFFpWX50298Sa3V+rzCBqwYDVR0jBIGjMIGggBQVyyr7hO11 +ZFFpWX50298Sa3V+r6F9pHsweTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk5DMQ8w +DQYDVQQHEwZOZXd0b24xFDASBgNVBAoTC0dvb2dsZSwgSW5jMRIwEAYDVQQDEwlK +b24gQWxsaWUxIjAgBgkqhkiG9w0BCQEWE2pvbmFsbGllQGdvb2dsZS5jb22CCQCx +z4IWqMXg4TAMBgNVHRMEBTADAQH/MAkGByqGSM44BAMDLwAwLAIUPtn/5j8Q1jJI +7ggOIsgrhgUdjGQCFCsmDq1H11q9+9Wp9IMeGrTSKHIM +-----END CERTIFICATE----- +` + +func TestParseCertificateWithDsaPublicKey(t *testing.T) { + expectedKey := &dsa.PublicKey{ + Parameters: dsa.Parameters{ + P: bigFromHexString("00BC84B52743B169158BB85974E3E832AF5EFCFC42B264349095313A4A013EEE069A1B937D92E51ACF297A1C77880DF25C8607D8204B4DC45651305EF4A63B40C7D8C42D91EDA397D8F51CBC9D0A531FE2C6F1E55E9357D205C39D395358968CBEDAC11320C607BE16CB9DB492B6E78163305A34DD99CE43C64927D13A0040EB97"), + Q: bigFromHexString("009A67067F66A323F5D4EC7902C73FE5D9E36FA74F"), + G: bigFromHexString("009147778295BF5893542BC41BA806898A29E43261DBC85441C37D92E97ED80D323D44825FDDE8374D0FF15877798812682599B216BBCC31B9DCCAD527465FEAFFD7FC2A193612E575E34E7A98AF4D10339FE47390A518CB9975B3160B1D0285D1418D0977C52994F43C29A053E3D685834104C9FAFDC221E38BE9F3989D7A8E42"), + }, + Y: bigFromHexString("59A27C269FCDE45AA2160A5C980C19211A820095091AB9C5DC8309AB7EC1B3A48C2E267C6D35FEE9B71BCBB92F16AC8E559129347FB5C00BEEDD10BA8915C90698755CA965735A32DC7575BED806E1E38F768FFBC24E41123DC73F1C6E9E4D0C9E692128853AFE29DC665FA993DCA9C903B7BF00B6442B9A76A5DADC6186317A"), + } + pemBlock, _ := pem.Decode([]byte(dsaCertPem)) + cert, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + t.Fatalf("Failed to parse certificate: %s", err) + } + if cert.PublicKeyAlgorithm != DSA { + t.Errorf("Parsed key algorithm was not DSA") + } + parsedKey, ok := cert.PublicKey.(*dsa.PublicKey) + if !ok { + t.Fatalf("Parsed key was not a DSA key: %s", err) + } + if expectedKey.Y.Cmp(parsedKey.Y) != 0 || + expectedKey.P.Cmp(parsedKey.P) != 0 || + expectedKey.Q.Cmp(parsedKey.Q) != 0 || + expectedKey.G.Cmp(parsedKey.G) != 0 { + t.Fatal("Parsed key differs from expected key") + } +} + +func TestParseCertificateWithDSASignatureAlgorithm(t *testing.T) { + pemBlock, _ := pem.Decode([]byte(dsaCertPem)) + cert, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + t.Fatalf("Failed to parse certificate: %s", err) + } + if cert.SignatureAlgorithm != DSAWithSHA1 { + t.Errorf("Parsed signature algorithm was not DSAWithSHA1") + } +} + +func TestVerifyCertificateWithDSASignature(t *testing.T) { + pemBlock, _ := pem.Decode([]byte(dsaCertPem)) + cert, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + t.Fatalf("Failed to parse certificate: %s", err) + } + // test cert is self-signed + if err = cert.CheckSignatureFrom(cert); err == nil { + t.Fatalf("Expected error verifying DSA certificate") + } +} + +var rsaPSSSelfSignedPEM = `-----BEGIN CERTIFICATE----- +MIIGHjCCA9KgAwIBAgIBdjBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQCAQUA +oRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogMCASAwbjELMAkGA1UEBhMC +SlAxHDAaBgNVBAoME0phcGFuZXNlIEdvdmVybm1lbnQxKDAmBgNVBAsMH1RoZSBN +aW5pc3RyeSBvZiBGb3JlaWduIEFmZmFpcnMxFzAVBgNVBAMMDmUtcGFzc3BvcnRD +U0NBMB4XDTEzMDUxNDA1MDczMFoXDTI5MDUxNDA1MDczMFowbjELMAkGA1UEBhMC +SlAxHDAaBgNVBAoME0phcGFuZXNlIEdvdmVybm1lbnQxKDAmBgNVBAsMH1RoZSBN +aW5pc3RyeSBvZiBGb3JlaWduIEFmZmFpcnMxFzAVBgNVBAMMDmUtcGFzc3BvcnRD +U0NBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAx/E3WRVxcCDXhoST +8nVSLjW6hwM4Ni99AegWzcGtfGFo0zjFA1Cl5URqxauvYu3gQgQHBGA1CovWeGrl +yVSRzOL1imcYsSgLOcnhVYB3Xcrof4ebv9+W+TwNdc9YzAwcj8rNd5nP6PKXIQ+W +PCkEOXdyb80YEnxuT+NPjkVfFSPBS7QYZpvT2fwy4fZ0eh48253+7VleSmTO0mqj +7TlzaG56q150SLZbhpOd8jD8bM/wACnLCPR88wj4hCcDLEwoLyY85HJCTIQQMnoT +UpqyzEeupPREIm6yi4d8C9YqIWFn2YTnRcWcmMaJLzq+kYwKoudfnoC6RW2vzZXn +defQs68IZuK+uALu9G3JWGPgu0CQGj0JNDT8zkiDV++4eNrZczWKjr1YnAL+VbLK +bApwL2u19l2WDpfUklimhWfraqHNIUKU6CjZOG31RzXcplIj0mtqs0E1r7r357Es +yFoB28iNo4cz1lCulh0E4WJzWzLZcT4ZspHHRCFyvYnXoibXEV1nULq8ByKKG0FS +7nn4SseoV+8PvjHLPhmHGMvi4mxkbcXdV3wthHT1/HXdqY84A4xHWt1+sB/TpTek +tDhFlEfcUygvTu58UtOnysomOVVeERmi7WSujfzKsGJAJYeetiA5R+zX7BxeyFVE +qW0zh1Tkwh0S8LRe5diJh4+6FG0CAwEAAaNfMF0wHQYDVR0OBBYEFD+oahaikBTV +Urk81Uz7kRS2sx0aMA4GA1UdDwEB/wQEAwIBBjAYBgNVHSAEETAPMA0GCyqDCIaP +fgYFAQEBMBIGA1UdEwEB/wQIMAYBAf8CAQAwQQYJKoZIhvcNAQEKMDSgDzANBglg +hkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAKIDAgEgA4IC +AQAaxWBQn5CZuNBfyzL57mn31ukHUFd61OMROSX3PT7oCv1Dy+C2AdRlxOcbN3/n +li0yfXUUqiY3COlLAHKRlkr97mLtxEFoJ0R8nVN2IQdChNQM/XSCzSGyY8NVa1OR +TTpEWLnexJ9kvIdbFXwUqdTnAkOI0m7Rg8j+E+lRRHg1xDAA1qKttrtUj3HRQWf3 +kNTu628SiMvap6aIdncburaK56MP7gkR1Wr/ichOfjIA3Jgw2PapI31i0GqeMd66 +U1+lC9FeyMAJpuSVp/SoiYzYo+79SFcVoM2yw3yAnIKg7q9GLYYqzncdykT6C06c +15gWFI6igmReAsD9ITSvYh0jLrLHfEYcPTOD3ZXJ4EwwHtWSoO3gq1EAtOYKu/Lv +C8zfBsZcFdsHvsSiYeBU8Oioe42mguky3Ax9O7D805Ek6R68ra07MW/G4YxvV7IN +2BfSaYy8MX9IG0ZMIOcoc0FeF5xkFmJ7kdrlTaJzC0IE9PNxNaH5QnOAFB8vxHcO +FioUxb6UKdHcPLR1VZtAdTdTMjSJxUqD/35Cdfqs7oDJXz8f6TXO2Tdy6G++YUs9 +qsGZWxzFvvkXUkQSl0dQQ5jO/FtUJcAVXVVp20LxPemfatAHpW31WdJYeWSQWky2 ++f9b5TXKXVyjlUL7uHxowWrT2AtTchDH22wTEtqLEF9Z3Q== +-----END CERTIFICATE-----` + +// openssl req -newkey rsa:2048 -keyout test.key -sha256 -sigopt \ +// rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 \ +// -x509 -days 3650 -nodes -subj '/C=US/ST=CA/L=SF/O=Test/CN=Test' -out \ +// test.pem +var rsaPSSSelfSignedOpenSSL110PEM = `-----BEGIN CERTIFICATE----- +MIIDwDCCAnigAwIBAgIJAM9LAMHTE5xpMD0GCSqGSIb3DQEBCjAwoA0wCwYJYIZI +AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIDAgEgMEUxCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDTALBgNVBAoMBFRlc3Qx +DTALBgNVBAMMBFRlc3QwHhcNMTgwMjIyMjIxMzE4WhcNMjgwMjIwMjIxMzE4WjBF +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ0wCwYDVQQK +DARUZXN0MQ0wCwYDVQQDDARUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA4Zrsydod+GoTAJLLutWNF87qhhVPBsK1zB1Gj+NAAe4+VbrZ1E41H1wp +qITx7DA8DRtJEf+NqrTAnAdZWBG/tAOA5LfXVax0ZSQtLnYLSeylLoMtDyY3eFAj +TmuTOoyVy6raktowCnHCh01NsstqqTfrx6SbmzOmDmKTkq/I+7K0MCVsn41xRDVM ++ShD0WGFGioEGoiWnFSWupxJDA3Q6jIDEygVwNKHwnhv/2NgG2kqZzrZSQA67en0 +iKAXtoDNPpmyD5oS9YbEJ+2Nbm7oLeON30i6kZvXKIzJXx+UWViazHZqnsi5rQ8G +RHF+iVFXsqd0MzDKmkKOT5FDhrsbKQIDAQABo1MwUTAdBgNVHQ4EFgQU9uFY/nlg +gLH00NBnr/o7QvpN9ugwHwYDVR0jBBgwFoAU9uFY/nlggLH00NBnr/o7QvpN9ugw +DwYDVR0TAQH/BAUwAwEB/zA9BgkqhkiG9w0BAQowMKANMAsGCWCGSAFlAwQCAaEa +MBgGCSqGSIb3DQEBCDALBglghkgBZQMEAgGiAwIBIAOCAQEAhJzpwxBNGKvzKWDe +WLqv6RMrl/q4GcH3b7M9wjxe0yOm4F+Tb2zJ7re4h+D39YkJf8cX1NV9UQVu6z4s +Fvo2kmlR0qZOXAg5augmCQ1xS0WHFoF6B52anNzHkZQbAIYJ3kGoFsUHzs7Sz7F/ +656FsRpHA9UzJQ3avPPMrA4Y4aoJ7ANJ6XIwTrdWrhULOVuvYRLCl4CdTVztVFX6 +wxX8nS1ISYd8jXPUMgsBKVbWufvLoIymMJW8CZbpprVZel5zFn0bmPrON8IHS30w +Gs+ITJjKEnZgXmAQ25SLKVzkZkBcGANs2GsdHNJ370Puisy0FIPD2NXR5uASAf7J ++w9fjQ== +-----END CERTIFICATE-----` + +func TestRSAPSSSelfSigned(t *testing.T) { + for i, pemBlock := range []string{rsaPSSSelfSignedPEM, rsaPSSSelfSignedOpenSSL110PEM} { + der, _ := pem.Decode([]byte(pemBlock)) + if der == nil { + t.Errorf("#%d: failed to find PEM block", i) + continue + } + + cert, err := ParseCertificate(der.Bytes) + if err != nil { + t.Errorf("#%d: failed to parse: %s", i, err) + continue + } + + if err = cert.CheckSignatureFrom(cert); err != nil { + t.Errorf("#%d: signature check failed: %s", i, err) + continue + } + } +} + +const ed25519Certificate = ` +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0c:83:d8:21:2b:82:cb:23:98:23:63:e2:f7:97:8a:43:5b:f3:bd:92 + Signature Algorithm: ED25519 + Issuer: CN = Ed25519 test certificate + Validity + Not Before: May 6 17:27:16 2019 GMT + Not After : Jun 5 17:27:16 2019 GMT + Subject: CN = Ed25519 test certificate + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + 36:29:c5:6c:0d:4f:14:6c:81:d0:ff:75:d3:6a:70: + 5f:69:cd:0f:4d:66:d5:da:98:7e:82:49:89:a3:8a: + 3c:fa + X509v3 extensions: + X509v3 Subject Key Identifier: + 09:3B:3A:9D:4A:29:D8:95:FF:68:BE:7B:43:54:72:E0:AD:A2:E3:AE + X509v3 Authority Key Identifier: + keyid:09:3B:3A:9D:4A:29:D8:95:FF:68:BE:7B:43:54:72:E0:AD:A2:E3:AE + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: ED25519 + 53:a5:58:1c:2c:3b:2a:9e:ac:9d:4e:a5:1d:5f:5d:6d:a6:b5: + 08:de:12:82:f3:97:20:ae:fa:d8:98:f4:1a:83:32:6b:91:f5: + 24:1d:c4:20:7f:2c:e2:4d:da:13:3b:6d:54:1a:d2:a8:28:dc: + 60:b9:d4:f4:78:4b:3c:1c:91:00 +-----BEGIN CERTIFICATE----- +MIIBWzCCAQ2gAwIBAgIUDIPYISuCyyOYI2Pi95eKQ1vzvZIwBQYDK2VwMCMxITAf +BgNVBAMMGEVkMjU1MTkgdGVzdCBjZXJ0aWZpY2F0ZTAeFw0xOTA1MDYxNzI3MTZa +Fw0xOTA2MDUxNzI3MTZaMCMxITAfBgNVBAMMGEVkMjU1MTkgdGVzdCBjZXJ0aWZp +Y2F0ZTAqMAUGAytlcAMhADYpxWwNTxRsgdD/ddNqcF9pzQ9NZtXamH6CSYmjijz6 +o1MwUTAdBgNVHQ4EFgQUCTs6nUop2JX/aL57Q1Ry4K2i464wHwYDVR0jBBgwFoAU +CTs6nUop2JX/aL57Q1Ry4K2i464wDwYDVR0TAQH/BAUwAwEB/zAFBgMrZXADQQBT +pVgcLDsqnqydTqUdX11tprUI3hKC85cgrvrYmPQagzJrkfUkHcQgfyziTdoTO21U +GtKoKNxgudT0eEs8HJEA +-----END CERTIFICATE-----` + +func TestEd25519SelfSigned(t *testing.T) { + der, _ := pem.Decode([]byte(ed25519Certificate)) + if der == nil { + t.Fatalf("Failed to find PEM block") + } + + cert, err := ParseCertificate(der.Bytes) + if err != nil { + t.Fatalf("Failed to parse: %s", err) + } + + if cert.PublicKeyAlgorithm != Ed25519 { + t.Fatalf("Parsed key algorithm was not Ed25519") + } + parsedKey, ok := cert.PublicKey.(ed25519.PublicKey) + if !ok { + t.Fatalf("Parsed key was not an Ed25519 key: %s", err) + } + if len(parsedKey) != ed25519.PublicKeySize { + t.Fatalf("Invalid Ed25519 key") + } + + if err = cert.CheckSignatureFrom(cert); err != nil { + t.Fatalf("Signature check failed: %s", err) + } +} + +const pemCertificate = `-----BEGIN CERTIFICATE----- +MIIDATCCAemgAwIBAgIRAKQkkrFx1T/dgB/Go/xBM5swDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTcyMDM2MDdaFw0xNzA4MTcyMDM2 +MDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDAoJtjG7M6InsWwIo+l3qq9u+g2rKFXNu9/mZ24XQ8XhV6PUR+5HQ4 +jUFWC58ExYhottqK5zQtKGkw5NuhjowFUgWB/VlNGAUBHtJcWR/062wYrHBYRxJH +qVXOpYKbIWwFKoXu3hcpg/CkdOlDWGKoZKBCwQwUBhWE7MDhpVdQ+ZljUJWL+FlK +yQK5iRsJd5TGJ6VUzLzdT4fmN2DzeK6GLeyMpVpU3sWV90JJbxWQ4YrzkKzYhMmB +EcpXTG2wm+ujiHU/k2p8zlf8Sm7VBM/scmnMFt0ynNXop4FWvJzEm1G0xD2t+e2I +5Utr04dOZPCgkm++QJgYhtZvgW7ZZiGTAgMBAAGjUjBQMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBsGA1UdEQQUMBKC +EHRlc3QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBADpqKQxrthH5InC7 +X96UP0OJCu/lLEMkrjoEWYIQaFl7uLPxKH5AmQPH4lYwF7u7gksR7owVG9QU9fs6 +1fK7II9CVgCd/4tZ0zm98FmU4D0lHGtPARrrzoZaqVZcAvRnFTlPX5pFkPhVjjai +/mkxX9LpD8oK1445DFHxK5UjLMmPIIWd8EOi+v5a+hgGwnJpoW7hntSl8kHMtTmy +fnnktsblSUV4lRCit0ymC7Ojhe+gzCCwkgs5kDzVVag+tnl/0e2DloIjASwOhpbH +KVcg7fBd484ht/sS+l0dsB4KDOSpd8JzVDMF8OZqlaydizoJO0yWr9GbCN1+OKq5 +EhLrEqU= +-----END CERTIFICATE-----` + +const ed25519CRLCertificate = ` +Certificate: +Data: + Version: 3 (0x2) + Serial Number: + 7a:07:a0:9d:14:04:16:fc:1f:d8:e5:fe:d1:1d:1f:8d + Signature Algorithm: ED25519 + Issuer: CN = Ed25519 CRL Test CA + Validity + Not Before: Oct 30 01:20:20 2019 GMT + Not After : Dec 31 23:59:59 9999 GMT + Subject: CN = Ed25519 CRL Test CA + Subject Public Key Info: + Public Key Algorithm: ED25519 + ED25519 Public-Key: + pub: + 95:73:3b:b0:06:2a:31:5a:b6:a7:a6:6e:ef:71:df: + ac:6f:6b:39:03:85:5e:63:4b:f8:a6:0f:68:c6:6f: + 75:21 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Client Authentication, TLS Web Server Authentication, OCSP Signing + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + B7:17:DA:16:EA:C5:ED:1F:18:49:44:D3:D2:E3:A0:35:0A:81:93:60 + X509v3 Authority Key Identifier: + keyid:B7:17:DA:16:EA:C5:ED:1F:18:49:44:D3:D2:E3:A0:35:0A:81:93:60 + +Signature Algorithm: ED25519 + fc:3e:14:ea:bb:70:c2:6f:38:34:70:bc:c8:a7:f4:7c:0d:1e: + 28:d7:2a:9f:22:8a:45:e8:02:76:84:1e:2d:64:2d:1e:09:b5: + 29:71:1f:95:8a:4e:79:87:51:60:9a:e7:86:40:f6:60:c7:d1: + ee:68:76:17:1d:90:cc:92:93:07 +-----BEGIN CERTIFICATE----- +MIIBijCCATygAwIBAgIQegegnRQEFvwf2OX+0R0fjTAFBgMrZXAwHjEcMBoGA1UE +AxMTRWQyNTUxOSBDUkwgVGVzdCBDQTAgFw0xOTEwMzAwMTIwMjBaGA85OTk5MTIz +MTIzNTk1OVowHjEcMBoGA1UEAxMTRWQyNTUxOSBDUkwgVGVzdCBDQTAqMAUGAytl +cAMhAJVzO7AGKjFatqembu9x36xvazkDhV5jS/imD2jGb3Uho4GNMIGKMA4GA1Ud +DwEB/wQEAwIBhjAnBgNVHSUEIDAeBggrBgEFBQcDAgYIKwYBBQUHAwEGCCsGAQUF +BwMJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLcX2hbqxe0fGElE09LjoDUK +gZNgMB8GA1UdIwQYMBaAFLcX2hbqxe0fGElE09LjoDUKgZNgMAUGAytlcANBAPw+ +FOq7cMJvODRwvMin9HwNHijXKp8iikXoAnaEHi1kLR4JtSlxH5WKTnmHUWCa54ZA +9mDH0e5odhcdkMySkwc= +-----END CERTIFICATE-----` + +var ed25519CRLKey = testingKey(`-----BEGIN TEST KEY----- +MC4CAQAwBQYDK2VwBCIEINdKh2096vUBYu4EIFpjShsUSh3vimKya1sQ1YTT4RZG +-----END TEST KEY-----`) + +func TestCRLCreation(t *testing.T) { + block, _ := pem.Decode([]byte(pemPrivateKey)) + privRSA, _ := ParsePKCS1PrivateKey(block.Bytes) + block, _ = pem.Decode([]byte(pemCertificate)) + certRSA, _ := ParseCertificate(block.Bytes) + + block, _ = pem.Decode([]byte(ed25519CRLKey)) + privEd25519, _ := ParsePKCS8PrivateKey(block.Bytes) + block, _ = pem.Decode([]byte(ed25519CRLCertificate)) + certEd25519, _ := ParseCertificate(block.Bytes) + + tests := []struct { + name string + priv interface{} + cert *Certificate + }{ + {"RSA CA", privRSA, certRSA}, + {"Ed25519 CA", privEd25519, certEd25519}, + } + + loc := time.FixedZone("Oz/Atlantis", int((2 * time.Hour).Seconds())) + + now := time.Unix(1000, 0).In(loc) + nowUTC := now.UTC() + expiry := time.Unix(10000, 0) + + revokedCerts := []pkix.RevokedCertificate{ + { + SerialNumber: big.NewInt(1), + RevocationTime: nowUTC, + }, + { + SerialNumber: big.NewInt(42), + // RevocationTime should be converted to UTC before marshaling. + RevocationTime: now, + }, + } + expectedCerts := []pkix.RevokedCertificate{ + { + SerialNumber: big.NewInt(1), + RevocationTime: nowUTC, + }, + { + SerialNumber: big.NewInt(42), + RevocationTime: nowUTC, + }, + } + + for _, test := range tests { + crlBytes, err := test.cert.CreateCRL(rand.Reader, test.priv, revokedCerts, now, expiry) + if err != nil { + t.Errorf("%s: error creating CRL: %s", test.name, err) + } + + parsedCRL, err := ParseDERCRL(crlBytes) + if err != nil { + t.Errorf("%s: error reparsing CRL: %s", test.name, err) + } + if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) { + t.Errorf("%s: RevokedCertificates mismatch: got %v; want %v.", test.name, + parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) + } + } +} + +func fromBase64(in string) []byte { + out := make([]byte, base64.StdEncoding.DecodedLen(len(in))) + n, err := base64.StdEncoding.Decode(out, []byte(in)) + if err != nil { + panic("failed to base64 decode") + } + return out[:n] +} + +func TestParseDERCRL(t *testing.T) { + derBytes := fromBase64(derCRLBase64) + certList, err := ParseDERCRL(derBytes) + if err != nil { + t.Errorf("error parsing: %s", err) + return + } + numCerts := len(certList.TBSCertList.RevokedCertificates) + expected := 88 + if numCerts != expected { + t.Errorf("bad number of revoked certificates. got: %d want: %d", numCerts, expected) + } + + if certList.HasExpired(time.Unix(1302517272, 0)) { + t.Errorf("CRL has expired (but shouldn't have)") + } + + // Can't check the signature here without a package cycle. +} + +func TestCRLWithoutExpiry(t *testing.T) { + derBytes := fromBase64("MIHYMIGZMAkGByqGSM44BAMwEjEQMA4GA1UEAxMHQ2FybERTUxcNOTkwODI3MDcwMDAwWjBpMBMCAgDIFw05OTA4MjIwNzAwMDBaMBMCAgDJFw05OTA4MjIwNzAwMDBaMBMCAgDTFw05OTA4MjIwNzAwMDBaMBMCAgDSFw05OTA4MjIwNzAwMDBaMBMCAgDUFw05OTA4MjQwNzAwMDBaMAkGByqGSM44BAMDLwAwLAIUfmVSdjP+NHMX0feW+aDU2G1cfT0CFAJ6W7fVWxjBz4fvftok8yqDnDWh") + certList, err := ParseDERCRL(derBytes) + if err != nil { + t.Fatal(err) + } + if !certList.TBSCertList.NextUpdate.IsZero() { + t.Errorf("NextUpdate is not the zero value") + } +} + +func TestParsePEMCRL(t *testing.T) { + pemBytes := fromBase64(pemCRLBase64) + certList, err := ParseCRL(pemBytes) + if err != nil { + t.Errorf("error parsing: %s", err) + return + } + numCerts := len(certList.TBSCertList.RevokedCertificates) + expected := 2 + if numCerts != expected { + t.Errorf("bad number of revoked certificates. got: %d want: %d", numCerts, expected) + } + + if certList.HasExpired(time.Unix(1302517272, 0)) { + t.Errorf("CRL has expired (but shouldn't have)") + } + + // Can't check the signature here without a package cycle. +} + +func TestImports(t *testing.T) { + if testing.Short() { + t.Skip("skipping in -short mode") + } + testenv.MustHaveGoRun(t) + + if out, err := exec.Command(testenv.GoToolPath(t), "run", "x509_test_import.go").CombinedOutput(); err != nil { + t.Errorf("failed to run x509_test_import.go: %s\n%s", err, out) + } +} + +const derCRLBase64 = "MIINqzCCDJMCAQEwDQYJKoZIhvcNAQEFBQAwVjEZMBcGA1UEAxMQUEtJIEZJTk1FQ0NBTklDQTEVMBMGA1UEChMMRklOTUVDQ0FOSUNBMRUwEwYDVQQLEwxGSU5NRUNDQU5JQ0ExCzAJBgNVBAYTAklUFw0xMTA1MDQxNjU3NDJaFw0xMTA1MDQyMDU3NDJaMIIMBzAhAg4Ze1od49Lt1qIXBydAzhcNMDkwNzE2MDg0MzIyWjAAMCECDl0HSL9bcZ1Ci/UHJ0DPFw0wOTA3MTYwODQzMTNaMAAwIQIOESB9tVAmX3cY7QcnQNAXDTA5MDcxNjA4NDUyMlowADAhAg4S1tGAQ3mHt8uVBydA1RcNMDkwODA0MTUyNTIyWjAAMCECDlQ249Y7vtC25ScHJ0DWFw0wOTA4MDQxNTI1MzdaMAAwIQIOISMop3NkA4PfYwcnQNkXDTA5MDgwNDExMDAzNFowADAhAg56/BMoS29KEShTBydA2hcNMDkwODA0MTEwMTAzWjAAMCECDnBp/22HPH5CSWoHJ0DbFw0wOTA4MDQxMDU0NDlaMAAwIQIOV9IP+8CD8bK+XAcnQNwXDTA5MDgwNDEwNTcxN1owADAhAg4v5aRz0IxWqYiXBydA3RcNMDkwODA0MTA1NzQ1WjAAMCECDlOU34VzvZAybQwHJ0DeFw0wOTA4MDQxMDU4MjFaMAAwIAINO4CD9lluIxcwBydBAxcNMDkwNzIyMTUzMTU5WjAAMCECDgOllfO8Y1QA7/wHJ0ExFw0wOTA3MjQxMTQxNDNaMAAwIQIOJBX7jbiCdRdyjgcnQUQXDTA5MDkxNjA5MzAwOFowADAhAg5iYSAgmDrlH/RZBydBRRcNMDkwOTE2MDkzMDE3WjAAMCECDmu6k6srP3jcMaQHJ0FRFw0wOTA4MDQxMDU2NDBaMAAwIQIOX8aHlO0V+WVH4QcnQVMXDTA5MDgwNDEwNTcyOVowADAhAg5flK2rg3NnsRgDBydBzhcNMTEwMjAxMTUzMzQ2WjAAMCECDg35yJDL1jOPTgoHJ0HPFw0xMTAyMDExNTM0MjZaMAAwIQIOMyFJ6+e9iiGVBQcnQdAXDTA5MDkxODEzMjAwNVowADAhAg5Emb/Oykucmn8fBydB1xcNMDkwOTIxMTAxMDQ3WjAAMCECDjQKCncV+MnUavMHJ0HaFw0wOTA5MjIwODE1MjZaMAAwIQIOaxiFUt3dpd+tPwcnQfQXDTEwMDYxODA4NDI1MVowADAhAg5G7P8nO0tkrMt7BydB9RcNMTAwNjE4MDg0MjMwWjAAMCECDmTCC3SXhmDRst4HJ0H2Fw0wOTA5MjgxMjA3MjBaMAAwIQIOHoGhUr/pRwzTKgcnQfcXDTA5MDkyODEyMDcyNFowADAhAg50wrcrCiw8mQmPBydCBBcNMTAwMjE2MTMwMTA2WjAAMCECDifWmkvwyhEqwEcHJ0IFFw0xMDAyMTYxMzAxMjBaMAAwIQIOfgPmlW9fg+osNgcnQhwXDTEwMDQxMzA5NTIwMFowADAhAg4YHAGuA6LgCk7tBydCHRcNMTAwNDEzMDk1MTM4WjAAMCECDi1zH1bxkNJhokAHJ0IsFw0xMDA0MTMwOTU5MzBaMAAwIQIOMipNccsb/wo2fwcnQi0XDTEwMDQxMzA5NTkwMFowADAhAg46lCmvPl4GpP6ABydCShcNMTAwMTE5MDk1MjE3WjAAMCECDjaTcaj+wBpcGAsHJ0JLFw0xMDAxMTkwOTUyMzRaMAAwIQIOOMC13EOrBuxIOQcnQloXDTEwMDIwMTA5NDcwNVowADAhAg5KmZl+krz4RsmrBydCWxcNMTAwMjAxMDk0NjQwWjAAMCECDmLG3zQJ/fzdSsUHJ0JiFw0xMDAzMDEwOTUxNDBaMAAwIQIOP39ksgHdojf4owcnQmMXDTEwMDMwMTA5NTExN1owADAhAg4LDQzvWNRlD6v9BydCZBcNMTAwMzAxMDk0NjIyWjAAMCECDkmNfeclaFhIaaUHJ0JlFw0xMDAzMDEwOTQ2MDVaMAAwIQIOT/qWWfpH/m8NTwcnQpQXDTEwMDUxMTA5MTgyMVowADAhAg5m/ksYxvCEgJSvBydClRcNMTAwNTExMDkxODAxWjAAMCECDgvf3Ohq6JOPU9AHJ0KWFw0xMDA1MTEwOTIxMjNaMAAwIQIOKSPas10z4jNVIQcnQpcXDTEwMDUxMTA5MjEwMlowADAhAg4mCWmhoZ3lyKCDBydCohcNMTEwNDI4MTEwMjI1WjAAMCECDkeiyRsBMK0Gvr4HJ0KjFw0xMTA0MjgxMTAyMDdaMAAwIQIOa09b/nH2+55SSwcnQq4XDTExMDQwMTA4Mjk0NlowADAhAg5O7M7iq7gGplr1BydCrxcNMTEwNDAxMDgzMDE3WjAAMCECDjlT6mJxUjTvyogHJ0K1Fw0xMTAxMjcxNTQ4NTJaMAAwIQIODS/l4UUFLe21NAcnQrYXDTExMDEyNzE1NDgyOFowADAhAg5lPRA0XdOUF6lSBydDHhcNMTEwMTI4MTQzNTA1WjAAMCECDixKX4fFGGpENwgHJ0MfFw0xMTAxMjgxNDM1MzBaMAAwIQIORNBkqsPnpKTtbAcnQ08XDTEwMDkwOTA4NDg0MlowADAhAg5QL+EMM3lohedEBydDUBcNMTAwOTA5MDg0ODE5WjAAMCECDlhDnHK+HiTRAXcHJ0NUFw0xMDEwMTkxNjIxNDBaMAAwIQIOdBFqAzq/INz53gcnQ1UXDTEwMTAxOTE2MjA0NFowADAhAg4OjR7s8MgKles1BydDWhcNMTEwMTI3MTY1MzM2WjAAMCECDmfR/elHee+d0SoHJ0NbFw0xMTAxMjcxNjUzNTZaMAAwIQIOBTKv2ui+KFMI+wcnQ5YXDTEwMDkxNTEwMjE1N1owADAhAg49F3c/GSah+oRUBydDmxcNMTEwMTI3MTczMjMzWjAAMCECDggv4I61WwpKFMMHJ0OcFw0xMTAxMjcxNzMyNTVaMAAwIQIOXx/Y8sEvwS10LAcnQ6UXDTExMDEyODExMjkzN1owADAhAg5LSLbnVrSKaw/9BydDphcNMTEwMTI4MTEyOTIwWjAAMCECDmFFoCuhKUeACQQHJ0PfFw0xMTAxMTExMDE3MzdaMAAwIQIOQTDdFh2fSPF6AAcnQ+AXDTExMDExMTEwMTcxMFowADAhAg5B8AOXX61FpvbbBydD5RcNMTAxMDA2MTAxNDM2WjAAMCECDh41P2Gmi7PkwI4HJ0PmFw0xMDEwMDYxMDE2MjVaMAAwIQIOWUHGLQCd+Ale9gcnQ/0XDTExMDUwMjA3NTYxMFowADAhAg5Z2c9AYkikmgWOBydD/hcNMTEwNTAyMDc1NjM0WjAAMCECDmf/UD+/h8nf+74HJ0QVFw0xMTA0MTUwNzI4MzNaMAAwIQIOICvj4epy3MrqfwcnRBYXDTExMDQxNTA3Mjg1NlowADAhAg4bouRMfOYqgv4xBydEHxcNMTEwMzA4MTYyNDI1WjAAMCECDhebWHGoKiTp7pEHJ0QgFw0xMTAzMDgxNjI0NDhaMAAwIQIOX+qnxxAqJ8LtawcnRDcXDTExMDEzMTE1MTIyOFowADAhAg4j0fICqZ+wkOdqBydEOBcNMTEwMTMxMTUxMTQxWjAAMCECDhmXjsV4SUpWtAMHJ0RLFw0xMTAxMjgxMTI0MTJaMAAwIQIODno/w+zG43kkTwcnREwXDTExMDEyODExMjM1MlowADAhAg4b1gc88767Fr+LBydETxcNMTEwMTI4MTEwMjA4WjAAMCECDn+M3Pa1w2nyFeUHJ0RQFw0xMTAxMjgxMDU4NDVaMAAwIQIOaduoyIH61tqybAcnRJUXDTEwMTIxNTA5NDMyMlowADAhAg4nLqQPkyi3ESAKBydElhcNMTAxMjE1MDk0MzM2WjAAMCECDi504NIMH8578gQHJ0SbFw0xMTAyMTQxNDA1NDFaMAAwIQIOGuaM8PDaC5u1egcnRJwXDTExMDIxNDE0MDYwNFowADAhAg4ehYq/BXGnB5PWBydEnxcNMTEwMjA0MDgwOTUxWjAAMCECDkSD4eS4FxW5H20HJ0SgFw0xMTAyMDQwODA5MjVaMAAwIQIOOCcb6ilYObt1egcnRKEXDTExMDEyNjEwNDEyOVowADAhAg58tISWCCwFnKGnBydEohcNMTEwMjA0MDgxMzQyWjAAMCECDn5rjtabY/L/WL0HJ0TJFw0xMTAyMDQxMTAzNDFaMAAwDQYJKoZIhvcNAQEFBQADggEBAGnF2Gs0+LNiYCW1Ipm83OXQYP/bd5tFFRzyz3iepFqNfYs4D68/QihjFoRHQoXEB0OEe1tvaVnnPGnEOpi6krwekquMxo4H88B5SlyiFIqemCOIss0SxlCFs69LmfRYvPPvPEhoXtQ3ZThe0UvKG83GOklhvGl6OaiRf4Mt+m8zOT4Wox/j6aOBK6cw6qKCdmD+Yj1rrNqFGg1CnSWMoD6S6mwNgkzwdBUJZ22BwrzAAo4RHa2Uy3ef1FjwD0XtU5N3uDSxGGBEDvOe5z82rps3E22FpAA8eYl8kaXtmWqyvYU0epp4brGuTxCuBMCAsxt/OjIjeNNQbBGkwxgfYA0=" + +const pemCRLBase64 = "LS0tLS1CRUdJTiBYNTA5IENSTC0tLS0tDQpNSUlCOWpDQ0FWOENBUUV3RFFZSktvWklodmNOQVFFRkJRQXdiREVhTUJnR0ExVUVDaE1SVWxOQklGTmxZM1Z5DQphWFI1SUVsdVl5NHhIakFjQmdOVkJBTVRGVkpUUVNCUWRXSnNhV01nVW05dmRDQkRRU0IyTVRFdU1Dd0dDU3FHDQpTSWIzRFFFSkFSWWZjbk5oYTJWdmJuSnZiM1J6YVdkdVFISnpZWE5sWTNWeWFYUjVMbU52YlJjTk1URXdNakl6DQpNVGt5T0RNd1doY05NVEV3T0RJeU1Ua3lPRE13V2pDQmpEQktBaEVBckRxb2g5RkhKSFhUN09QZ3V1bjQrQmNODQpNRGt4TVRBeU1UUXlOekE1V2pBbU1Bb0dBMVVkRlFRRENnRUpNQmdHQTFVZEdBUVJHQTh5TURBNU1URXdNakUwDQpNalExTlZvd1BnSVJBTEd6blowOTVQQjVhQU9MUGc1N2ZNTVhEVEF5TVRBeU16RTBOVEF4TkZvd0dqQVlCZ05WDQpIUmdFRVJnUE1qQXdNakV3TWpNeE5EVXdNVFJhb0RBd0xqQWZCZ05WSFNNRUdEQVdnQlQxVERGNlVRTS9MTmVMDQpsNWx2cUhHUXEzZzltekFMQmdOVkhSUUVCQUlDQUlRd0RRWUpLb1pJaHZjTkFRRUZCUUFEZ1lFQUZVNUFzNk16DQpxNVBSc2lmYW9iUVBHaDFhSkx5QytNczVBZ2MwYld5QTNHQWR4dXI1U3BQWmVSV0NCamlQL01FSEJXSkNsQkhQDQpHUmNxNXlJZDNFakRrYUV5eFJhK2k2N0x6dmhJNmMyOUVlNks5cFNZd2ppLzdSVWhtbW5Qclh0VHhsTDBsckxyDQptUVFKNnhoRFJhNUczUUE0Q21VZHNITnZicnpnbUNZcHZWRT0NCi0tLS0tRU5EIFg1MDkgQ1JMLS0tLS0NCg0K" + +func TestCreateCertificateRequest(t *testing.T) { + random := rand.Reader + + ecdsa256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("Failed to generate ECDSA key: %s", err) + } + + ecdsa384Priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatalf("Failed to generate ECDSA key: %s", err) + } + + ecdsa521Priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + if err != nil { + t.Fatalf("Failed to generate ECDSA key: %s", err) + } + + _, ed25519Priv, err := ed25519.GenerateKey(random) + if err != nil { + t.Fatalf("Failed to generate Ed25519 key: %s", err) + } + + tests := []struct { + name string + priv interface{} + sigAlgo SignatureAlgorithm + }{ + {"RSA", testPrivateKey, SHA1WithRSA}, + {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA1}, + {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA1}, + {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA1}, + {"Ed25519", ed25519Priv, PureEd25519}, + } + + for _, test := range tests { + template := CertificateRequest{ + Subject: pkix.Name{ + CommonName: "test.example.com", + Organization: []string{"Σ Acme Co"}, + }, + SignatureAlgorithm: test.sigAlgo, + DNSNames: []string{"test.example.com"}, + EmailAddresses: []string{"gopher@golang.org"}, + IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, + } + + derBytes, err := CreateCertificateRequest(random, &template, test.priv) + if err != nil { + t.Errorf("%s: failed to create certificate request: %s", test.name, err) + continue + } + + out, err := ParseCertificateRequest(derBytes) + if err != nil { + t.Errorf("%s: failed to create certificate request: %s", test.name, err) + continue + } + + err = out.CheckSignature() + if err != nil { + t.Errorf("%s: failed to check certificate request signature: %s", test.name, err) + continue + } + + if out.Subject.CommonName != template.Subject.CommonName { + t.Errorf("%s: output subject common name and template subject common name don't match", test.name) + } else if len(out.Subject.Organization) != len(template.Subject.Organization) { + t.Errorf("%s: output subject organisation and template subject organisation don't match", test.name) + } else if len(out.DNSNames) != len(template.DNSNames) { + t.Errorf("%s: output DNS names and template DNS names don't match", test.name) + } else if len(out.EmailAddresses) != len(template.EmailAddresses) { + t.Errorf("%s: output email addresses and template email addresses don't match", test.name) + } else if len(out.IPAddresses) != len(template.IPAddresses) { + t.Errorf("%s: output IP addresses and template IP addresses names don't match", test.name) + } + } +} + +func marshalAndParseCSR(t *testing.T, template *CertificateRequest) *CertificateRequest { + derBytes, err := CreateCertificateRequest(rand.Reader, template, testPrivateKey) + if err != nil { + t.Fatal(err) + } + + csr, err := ParseCertificateRequest(derBytes) + if err != nil { + t.Fatal(err) + } + + return csr +} + +func TestCertificateRequestOverrides(t *testing.T) { + sanContents, err := marshalSANs([]string{"foo.example.com"}, nil, nil, nil) + if err != nil { + t.Fatal(err) + } + + template := CertificateRequest{ + Subject: pkix.Name{ + CommonName: "test.example.com", + Organization: []string{"Σ Acme Co"}, + }, + DNSNames: []string{"test.example.com"}, + + // An explicit extension should override the DNSNames from the + // template. + ExtraExtensions: []pkix.Extension{ + { + Id: oidExtensionSubjectAltName, + Value: sanContents, + Critical: true, + }, + }, + } + + csr := marshalAndParseCSR(t, &template) + + if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "foo.example.com" { + t.Errorf("Extension did not override template. Got %v\n", csr.DNSNames) + } + + if len(csr.Extensions) != 1 || !csr.Extensions[0].Id.Equal(oidExtensionSubjectAltName) || !csr.Extensions[0].Critical { + t.Errorf("SAN extension was not faithfully copied, got %#v", csr.Extensions) + } + + // If there is already an attribute with X.509 extensions then the + // extra extensions should be added to it rather than creating a CSR + // with two extension attributes. + + template.Attributes = []pkix.AttributeTypeAndValueSET{ + { + Type: oidExtensionRequest, + Value: [][]pkix.AttributeTypeAndValue{ + { + { + Type: oidExtensionAuthorityInfoAccess, + Value: []byte("foo"), + }, + }, + }, + }, + } + + csr = marshalAndParseCSR(t, &template) + if l := len(csr.Attributes); l != 1 { + t.Errorf("incorrect number of attributes: %d\n", l) + } + + if !csr.Attributes[0].Type.Equal(oidExtensionRequest) || + len(csr.Attributes[0].Value) != 1 || + len(csr.Attributes[0].Value[0]) != 2 { + t.Errorf("bad attributes: %#v\n", csr.Attributes) + } + + sanContents2, err := marshalSANs([]string{"foo2.example.com"}, nil, nil, nil) + if err != nil { + t.Fatal(err) + } + + // Extensions in Attributes should override those in ExtraExtensions. + template.Attributes[0].Value[0] = append(template.Attributes[0].Value[0], pkix.AttributeTypeAndValue{ + Type: oidExtensionSubjectAltName, + Value: sanContents2, + }) + + csr = marshalAndParseCSR(t, &template) + + if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "foo2.example.com" { + t.Errorf("Attributes did not override ExtraExtensions. Got %v\n", csr.DNSNames) + } +} + +func TestParseCertificateRequest(t *testing.T) { + for _, csrBase64 := range csrBase64Array { + csrBytes := fromBase64(csrBase64) + csr, err := ParseCertificateRequest(csrBytes) + if err != nil { + t.Fatalf("failed to parse CSR: %s", err) + } + + if len(csr.EmailAddresses) != 1 || csr.EmailAddresses[0] != "gopher@golang.org" { + t.Errorf("incorrect email addresses found: %v", csr.EmailAddresses) + } + + if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "test.example.com" { + t.Errorf("incorrect DNS names found: %v", csr.DNSNames) + } + + if len(csr.Subject.Country) != 1 || csr.Subject.Country[0] != "AU" { + t.Errorf("incorrect Subject name: %v", csr.Subject) + } + + found := false + for _, e := range csr.Extensions { + if e.Id.Equal(oidExtensionBasicConstraints) { + found = true + break + } + } + if !found { + t.Errorf("basic constraints extension not found in CSR") + } + } +} + +func TestCriticalFlagInCSRRequestedExtensions(t *testing.T) { + // This CSR contains an extension request where the extensions have a + // critical flag in them. In the past we failed to handle this. + const csrBase64 = "MIICrTCCAZUCAQIwMzEgMB4GA1UEAwwXU0NFUCBDQSBmb3IgRGV2ZWxlciBTcmwxDzANBgNVBAsMBjQzNTk3MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALFMAJ7Zy9YyfgbNlbUWAW0LalNRMPs7aXmLANsCpjhnw3lLlfDPaLeWyKh1nK5I5ojaJOW6KIOSAcJkDUe3rrE0wR0RVt3UxArqs0R/ND3u5Q+bDQY2X1HAFUHzUzcdm5JRAIA355v90teMckaWAIlkRQjDE22Lzc6NAl64KOd1rqOUNj8+PfX6fSo20jm94Pp1+a6mfk3G/RUWVuSm7owO5DZI/Fsi2ijdmb4NUar6K/bDKYTrDFkzcqAyMfP3TitUtBp19Mp3B1yAlHjlbp/r5fSSXfOGHZdgIvp0WkLuK2u5eQrX5l7HMB/5epgUs3HQxKY6ljhh5wAjDwz//LsCAwEAAaA1MDMGCSqGSIb3DQEJDjEmMCQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQEFBQADggEBAAMq3bxJSPQEgzLYR/yaVvgjCDrc3zUbIwdOis6Go06Q4RnjH5yRaSZAqZQTDsPurQcnz2I39VMGEiSkFJFavf4QHIZ7QFLkyXadMtALc87tm17Ej719SbHcBSSZayR9VYJUNXRLayI6HvyUrmqcMKh+iX3WY3ICr59/wlM0tYa8DYN4yzmOa2Onb29gy3YlaF5A2AKAMmk003cRT9gY26mjpv7d21czOSSeNyVIoZ04IR9ee71vWTMdv0hu/af5kSjQ+ZG5/Qgc0+mnECLz/1gtxt1srLYbtYQ/qAY8oX1DCSGFS61tN/vl+4cxGMD/VGcGzADRLRHSlVqy2Qgss6Q=" + + csrBytes := fromBase64(csrBase64) + csr, err := ParseCertificateRequest(csrBytes) + if err != nil { + t.Fatalf("failed to parse CSR: %s", err) + } + + expected := []struct { + Id asn1.ObjectIdentifier + Value []byte + }{ + {oidExtensionBasicConstraints, fromBase64("MAYBAf8CAQA=")}, + {oidExtensionKeyUsage, fromBase64("AwIChA==")}, + } + + if n := len(csr.Extensions); n != len(expected) { + t.Fatalf("expected to find %d extensions but found %d", len(expected), n) + } + + for i, extension := range csr.Extensions { + if !extension.Id.Equal(expected[i].Id) { + t.Fatalf("extension #%d has unexpected type %v (expected %v)", i, extension.Id, expected[i].Id) + } + + if !bytes.Equal(extension.Value, expected[i].Value) { + t.Fatalf("extension #%d has unexpected contents %x (expected %x)", i, extension.Value, expected[i].Value) + } + } +} + +// serialiseAndParse generates a self-signed certificate from template and +// returns a parsed version of it. +func serialiseAndParse(t *testing.T, template *Certificate) *Certificate { + derBytes, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey) + if err != nil { + t.Fatalf("failed to create certificate: %s", err) + return nil + } + + cert, err := ParseCertificate(derBytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + return nil + } + + return cert +} + +func TestMaxPathLenNotCA(t *testing.T) { + template := &Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "Σ Acme Co", + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + + BasicConstraintsValid: true, + IsCA: false, + } + if m := serialiseAndParse(t, template).MaxPathLen; m != -1 { + t.Errorf("MaxPathLen should be -1 when IsCa is false, got %d", m) + } + + template.MaxPathLen = -1 + if m := serialiseAndParse(t, template).MaxPathLen; m != -1 { + t.Errorf("MaxPathLen should be -1 when IsCa is false and MaxPathLen set to -1, got %d", m) + } + + template.MaxPathLen = 5 + if _, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey); err == nil { + t.Error("specifying a MaxPathLen when IsCA is false should fail") + } + + template.MaxPathLen = 0 + template.MaxPathLenZero = true + if _, err := CreateCertificate(rand.Reader, template, template, &testPrivateKey.PublicKey, testPrivateKey); err == nil { + t.Error("setting MaxPathLenZero when IsCA is false should fail") + } + + template.BasicConstraintsValid = false + if m := serialiseAndParse(t, template).MaxPathLen; m != 0 { + t.Errorf("Bad MaxPathLen should be ignored if BasicConstraintsValid is false, got %d", m) + } +} + +func TestMaxPathLen(t *testing.T) { + template := &Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "Σ Acme Co", + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + + BasicConstraintsValid: true, + IsCA: true, + } + + cert1 := serialiseAndParse(t, template) + if m := cert1.MaxPathLen; m != -1 { + t.Errorf("Omitting MaxPathLen didn't turn into -1, got %d", m) + } + if cert1.MaxPathLenZero { + t.Errorf("Omitting MaxPathLen resulted in MaxPathLenZero") + } + + template.MaxPathLen = 1 + cert2 := serialiseAndParse(t, template) + if m := cert2.MaxPathLen; m != 1 { + t.Errorf("Setting MaxPathLen didn't work. Got %d but set 1", m) + } + if cert2.MaxPathLenZero { + t.Errorf("Setting MaxPathLen resulted in MaxPathLenZero") + } + + template.MaxPathLen = 0 + template.MaxPathLenZero = true + cert3 := serialiseAndParse(t, template) + if m := cert3.MaxPathLen; m != 0 { + t.Errorf("Setting MaxPathLenZero didn't work, got %d", m) + } + if !cert3.MaxPathLenZero { + t.Errorf("Setting MaxPathLen to zero didn't result in MaxPathLenZero") + } +} + +func TestNoAuthorityKeyIdInSelfSignedCert(t *testing.T) { + template := &Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "Σ Acme Co", + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + + BasicConstraintsValid: true, + IsCA: true, + SubjectKeyId: []byte{1, 2, 3, 4}, + } + + if cert := serialiseAndParse(t, template); len(cert.AuthorityKeyId) != 0 { + t.Fatalf("self-signed certificate contained default authority key id") + } + + template.AuthorityKeyId = []byte{1, 2, 3, 4} + if cert := serialiseAndParse(t, template); len(cert.AuthorityKeyId) == 0 { + t.Fatalf("self-signed certificate erased explicit authority key id") + } +} + +func TestNoSubjectKeyIdInCert(t *testing.T) { + template := &Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "Σ Acme Co", + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + + BasicConstraintsValid: true, + IsCA: true, + } + if cert := serialiseAndParse(t, template); len(cert.SubjectKeyId) == 0 { + t.Fatalf("self-signed certificate did not generate subject key id using the public key") + } + + template.IsCA = false + if cert := serialiseAndParse(t, template); len(cert.SubjectKeyId) != 0 { + t.Fatalf("self-signed certificate generated subject key id when it isn't a CA") + } + + template.SubjectKeyId = []byte{1, 2, 3, 4} + if cert := serialiseAndParse(t, template); len(cert.SubjectKeyId) == 0 { + t.Fatalf("self-signed certificate erased explicit subject key id") + } +} + +func TestASN1BitLength(t *testing.T) { + tests := []struct { + bytes []byte + bitLen int + }{ + {nil, 0}, + {[]byte{0x00}, 0}, + {[]byte{0x00, 0x00}, 0}, + {[]byte{0xf0}, 4}, + {[]byte{0x88}, 5}, + {[]byte{0xff}, 8}, + {[]byte{0xff, 0x80}, 9}, + {[]byte{0xff, 0x81}, 16}, + } + + for i, test := range tests { + if got := asn1BitLength(test.bytes); got != test.bitLen { + t.Errorf("#%d: calculated bit-length of %d for %x, wanted %d", i, got, test.bytes, test.bitLen) + } + } +} + +func TestVerifyEmptyCertificate(t *testing.T) { + if _, err := new(Certificate).Verify(VerifyOptions{}); err != errNotParsed { + t.Errorf("Verifying empty certificate resulted in unexpected error: %q (wanted %q)", err, errNotParsed) + } +} + +func TestInsecureAlgorithmErrorString(t *testing.T) { + tests := []struct { + sa SignatureAlgorithm + want string + }{ + {MD2WithRSA, "x509: cannot verify signature: insecure algorithm MD2-RSA"}, + {-1, "x509: cannot verify signature: insecure algorithm -1"}, + {0, "x509: cannot verify signature: insecure algorithm 0"}, + {9999, "x509: cannot verify signature: insecure algorithm 9999"}, + } + for i, tt := range tests { + if got := fmt.Sprint(InsecureAlgorithmError(tt.sa)); got != tt.want { + t.Errorf("%d. mismatch.\n got: %s\nwant: %s\n", i, got, tt.want) + } + } +} + +// These CSR was generated with OpenSSL: +// openssl req -out CSR.csr -new -sha256 -nodes -keyout privateKey.key -config openssl.cnf +// +// With openssl.cnf containing the following sections: +// [ v3_req ] +// basicConstraints = CA:FALSE +// keyUsage = nonRepudiation, digitalSignature, keyEncipherment +// subjectAltName = email:gopher@golang.org,DNS:test.example.com +// [ req_attributes ] +// challengePassword = ignored challenge +// unstructuredName = ignored unstructured name +var csrBase64Array = [...]string{ + // Just [ v3_req ] + "MIIDHDCCAgQCAQAwfjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLQ29tbW9uIE5hbWUxITAfBgkqhkiG9w0BCQEWEnRlc3RAZW1haWwuYWRkcmVzczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK1GY4YFx2ujlZEOJxQVYmsjUnLsd5nFVnNpLE4cV+77sgv9NPNlB8uhn3MXt5leD34rm/2BisCHOifPucYlSrszo2beuKhvwn4+2FxDmWtBEMu/QA16L5IvoOfYZm/gJTsPwKDqvaR0tTU67a9OtxwNTBMI56YKtmwd/o8d3hYv9cg+9ZGAZ/gKONcg/OWYx/XRh6bd0g8DMbCikpWgXKDsvvK1Nk+VtkDO1JxuBaj4Lz/p/MifTfnHoqHxWOWl4EaTs4Ychxsv34/rSj1KD1tJqorIv5Xv2aqv4sjxfbrYzX4kvS5SC1goIovLnhj5UjmQ3Qy8u65eow/LLWw+YFcCAwEAAaBZMFcGCSqGSIb3DQEJDjFKMEgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwLgYDVR0RBCcwJYERZ29waGVyQGdvbGFuZy5vcmeCEHRlc3QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBAB6VPMRrchvNW61Tokyq3ZvO6/NoGIbuwUn54q6l5VZW0Ep5Nq8juhegSSnaJ0jrovmUgKDN9vEo2KxuAtwG6udS6Ami3zP+hRd4k9Q8djJPb78nrjzWiindLK5Fps9U5mMoi1ER8ViveyAOTfnZt/jsKUaRsscY2FzE9t9/o5moE6LTcHUS4Ap1eheR+J72WOnQYn3cifYaemsA9MJuLko+kQ6xseqttbh9zjqd9fiCSh/LNkzos9c+mg2yMADitaZinAh+HZi50ooEbjaT3erNq9O6RqwJlgD00g6MQdoz9bTAryCUhCQfkIaepmQ7BxS0pqWNW3MMwfDwx/Snz6g=", + // Both [ v3_req ] and [ req_attributes ] + "MIIDaTCCAlECAQAwfjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLQ29tbW9uIE5hbWUxITAfBgkqhkiG9w0BCQEWEnRlc3RAZW1haWwuYWRkcmVzczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK1GY4YFx2ujlZEOJxQVYmsjUnLsd5nFVnNpLE4cV+77sgv9NPNlB8uhn3MXt5leD34rm/2BisCHOifPucYlSrszo2beuKhvwn4+2FxDmWtBEMu/QA16L5IvoOfYZm/gJTsPwKDqvaR0tTU67a9OtxwNTBMI56YKtmwd/o8d3hYv9cg+9ZGAZ/gKONcg/OWYx/XRh6bd0g8DMbCikpWgXKDsvvK1Nk+VtkDO1JxuBaj4Lz/p/MifTfnHoqHxWOWl4EaTs4Ychxsv34/rSj1KD1tJqorIv5Xv2aqv4sjxfbrYzX4kvS5SC1goIovLnhj5UjmQ3Qy8u65eow/LLWw+YFcCAwEAAaCBpTAgBgkqhkiG9w0BCQcxEwwRaWdub3JlZCBjaGFsbGVuZ2UwKAYJKoZIhvcNAQkCMRsMGWlnbm9yZWQgdW5zdHJ1Y3R1cmVkIG5hbWUwVwYJKoZIhvcNAQkOMUowSDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAuBgNVHREEJzAlgRFnb3BoZXJAZ29sYW5nLm9yZ4IQdGVzdC5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAgxe2N5O48EMsYE7o0rZBB0wi3Ov5/yYfnmmVI22Y3sP6VXbLDW0+UWIeSccOhzUCcZ/G4qcrfhhx6gTZTeA01nP7TdTJURvWAH5iFqj9sQ0qnLq6nEcVHij3sG6M5+BxAIVClQBk6lTCzgphc835Fjj6qSLuJ20XHdL5UfUbiJxx299CHgyBRL+hBUIPfz8p+ZgamyAuDLfnj54zzcRVyLlrmMLNPZNll1Q70RxoU6uWvLH8wB8vQe3Q/guSGubLyLRTUQVPh+dw1L4t8MKFWfX/48jwRM4gIRHFHPeAAE9D9YAoqdIvj/iFm/eQ++7DP8MDwOZWsXeB6jjwHuLmkQ==", +} + +var md5cert = ` +-----BEGIN CERTIFICATE----- +MIIB4TCCAUoCCQCfmw3vMgPS5TANBgkqhkiG9w0BAQQFADA1MQswCQYDVQQGEwJB +VTETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMITUQ1IEluYy4wHhcNMTUx +MjAzMTkyOTMyWhcNMjkwODEyMTkyOTMyWjA1MQswCQYDVQQGEwJBVTETMBEGA1UE +CBMKU29tZS1TdGF0ZTERMA8GA1UEChMITUQ1IEluYy4wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBANrq2nhLQj5mlXbpVX3QUPhfEm/vdEqPkoWtR/jRZIWm4WGf +Wpq/LKHJx2Pqwn+t117syN8l4U5unyAi1BJSXjBwPZNd7dXjcuJ+bRLV7FZ/iuvs +cfYyQQFTxan4TaJMd0x1HoNDbNbjHa02IyjjYE/r3mb/PIg+J2t5AZEh80lPAgMB +AAEwDQYJKoZIhvcNAQEEBQADgYEAjGzp3K3ey/YfKHohf33yHHWd695HQxDAP+wY +cs9/TAyLR+gJzJP7d18EcDDLJWVi7bhfa4EAD86di05azOh9kWSn4b3o9QYRGCSw +GNnI3Zk0cwNKA49hZntKKiy22DhRk7JAHF01d6Bu3KkHkmENrtJ+zj/+159WAnUa +qViorq4= +-----END CERTIFICATE----- +` + +func TestMD5(t *testing.T) { + pemBlock, _ := pem.Decode([]byte(md5cert)) + cert, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + if sa := cert.SignatureAlgorithm; sa != MD5WithRSA { + t.Errorf("signature algorithm is %v, want %v", sa, MD5WithRSA) + } + if err = cert.CheckSignatureFrom(cert); err == nil { + t.Fatalf("certificate verification succeeded incorrectly") + } + if _, ok := err.(InsecureAlgorithmError); !ok { + t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err) + } +} + +// certMissingRSANULL contains an RSA public key where the AlgorithmIdentifier +// parameters are omitted rather than being an ASN.1 NULL. +const certMissingRSANULL = ` +-----BEGIN CERTIFICATE----- +MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD +bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4 +MDAxMlowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGc +MAsGCSqGSIb3DQEBAQOBjAAwgYgCgYBO0Hsx44Jk2VnAwoekXh6LczPHY1PfZpIG +hPZk1Y/kNqcdK+izIDZFI7Xjla7t4PUgnI2V339aEu+H5Fto5OkOdOwEin/ekyfE +ARl6vfLcPRSr0FTKIQzQTW6HLlzF0rtNS0/Otiz3fojsfNcCkXSmHgwa2uNKWi7e +E5xMQIhZkwIDAQABozIwMDAOBgNVHQ8BAf8EBAMCAKAwDQYDVR0OBAYEBAECAwQw +DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A +p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4 +hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE +GFGNEH5PlGffo05wc46QkYU= +-----END CERTIFICATE-----` + +func TestRSAMissingNULLParameters(t *testing.T) { + block, _ := pem.Decode([]byte(certMissingRSANULL)) + if _, err := ParseCertificate(block.Bytes); err == nil { + t.Error("unexpected success when parsing certificate with missing RSA NULL parameter") + } else if !strings.Contains(err.Error(), "missing NULL") { + t.Errorf("unrecognised error when parsing certificate with missing RSA NULL parameter: %s", err) + } +} + +const certISOOID = ` +-----BEGIN CERTIFICATE----- +MIIB5TCCAVKgAwIBAgIQtwyL3RPWV7dJQp34HwZG9DAJBgUrDgMCHQUAMBExDzAN +BgNVBAMTBm15dGVzdDAeFw0xNjA4MDkyMjExMDVaFw0zOTEyMzEyMzU5NTlaMBEx +DzANBgNVBAMTBm15dGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArzIH +GsyDB3ohIGkkvijF2PTRUX1bvOtY1eUUpjwHyu0twpAKSuaQv2Ha+/63+aHe8O86 +BT+98wjXFX6RFSagtAujo80rIF2dSm33BGt18pDN8v6zp93dnAm0jRaSQrHJ75xw +5O+S1oEYR1LtUoFJy6qB104j6aINBAgOiLIKiMkCAwEAAaNGMEQwQgYDVR0BBDsw +OYAQVuYVQ/WDjdGSkZRlTtJDNKETMBExDzANBgNVBAMTBm15dGVzdIIQtwyL3RPW +V7dJQp34HwZG9DAJBgUrDgMCHQUAA4GBABngrSkH7vG5lY4sa4AZF59lAAXqBVJE +J4TBiKC62hCdZv18rBleP6ETfhbPg7pTs8p4ebQbpmtNxRS9Lw3MzQ8Ya5Ybwzj2 +NwBSyCtCQl7mrEg4nJqJl4A2EUhnET/oVxU0oTV/SZ3ziGXcY1oG1s6vidV7TZTu +MCRtdSdaM7g3 +-----END CERTIFICATE-----` + +func TestISOOIDInCertificate(t *testing.T) { + block, _ := pem.Decode([]byte(certISOOID)) + if cert, err := ParseCertificate(block.Bytes); err != nil { + t.Errorf("certificate with ISO OID failed to parse: %s", err) + } else if cert.SignatureAlgorithm == UnknownSignatureAlgorithm { + t.Errorf("ISO OID not recognised in certificate") + } +} + +// certMultipleRDN contains a RelativeDistinguishedName with two elements (the +// common name and serial number). This particular certificate was the first +// such certificate in the “Pilot” Certificate Transparency log. +const certMultipleRDN = ` +-----BEGIN CERTIFICATE----- +MIIFRzCCBC+gAwIBAgIEOl59NTANBgkqhkiG9w0BAQUFADA9MQswCQYDVQQGEwJz +aTEbMBkGA1UEChMSc3RhdGUtaW5zdGl0dXRpb25zMREwDwYDVQQLEwhzaWdvdi1j +YTAeFw0xMjExMTYxMDUyNTdaFw0xNzExMTYxMjQ5MDVaMIGLMQswCQYDVQQGEwJz +aTEbMBkGA1UEChMSc3RhdGUtaW5zdGl0dXRpb25zMRkwFwYDVQQLExB3ZWItY2Vy +dGlmaWNhdGVzMRAwDgYDVQQLEwdTZXJ2ZXJzMTIwFAYDVQQFEw0xMjM2NDg0MDEw +MDEwMBoGA1UEAxMTZXBvcnRhbC5tc3MuZWR1cy5zaTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMrNkZH9MPuBTjMGNk3sJX8V+CkFx/4ru7RTlLS6dlYM +098dtSfJ3s2w0p/1NB9UmR8j0yS0Kg6yoZ3ShsSO4DWBtcQD8820a6BYwqxxQTNf +HSRZOc+N/4TQrvmK6t4k9Aw+YEYTMrWOU4UTeyhDeCcUsBdh7HjfWsVaqNky+2sv +oic3zP5gF+2QfPkvOoHT3FLR8olNhViIE6Kk3eFIEs4dkq/ZzlYdLb8pHQoj/sGI +zFmA5AFvm1HURqOmJriFjBwaCtn8AVEYOtQrnUCzJYu1ex8azyS2ZgYMX0u8A5Z/ +y2aMS/B2W+H79WcgLpK28vPwe7vam0oFrVytAd+u65ECAwEAAaOCAf4wggH6MA4G +A1UdDwEB/wQEAwIFoDBABgNVHSAEOTA3MDUGCisGAQQBr1kBAwMwJzAlBggrBgEF +BQcCARYZaHR0cDovL3d3dy5jYS5nb3Yuc2kvY3BzLzAfBgNVHREEGDAWgRRwb2Rw +b3JhLm1pemtzQGdvdi5zaTCB8QYDVR0fBIHpMIHmMFWgU6BRpE8wTTELMAkGA1UE +BhMCc2kxGzAZBgNVBAoTEnN0YXRlLWluc3RpdHV0aW9uczERMA8GA1UECxMIc2ln +b3YtY2ExDjAMBgNVBAMTBUNSTDM5MIGMoIGJoIGGhldsZGFwOi8veDUwMC5nb3Yu +c2kvb3U9c2lnb3YtY2Esbz1zdGF0ZS1pbnN0aXR1dGlvbnMsYz1zaT9jZXJ0aWZp +Y2F0ZVJldm9jYXRpb25MaXN0P2Jhc2WGK2h0dHA6Ly93d3cuc2lnb3YtY2EuZ292 +LnNpL2NybC9zaWdvdi1jYS5jcmwwKwYDVR0QBCQwIoAPMjAxMjExMTYxMDUyNTda +gQ8yMDE3MTExNjEyNDkwNVowHwYDVR0jBBgwFoAUHvjUU2uzgwbpBAZXAvmlv8ZY +PHIwHQYDVR0OBBYEFGI1Duuu+wTGDZka/xHNbwcbM69ZMAkGA1UdEwQCMAAwGQYJ +KoZIhvZ9B0EABAwwChsEVjcuMQMCA6gwDQYJKoZIhvcNAQEFBQADggEBAHny0K1y +BQznrzDu3DDpBcGYguKU0dvU9rqsV1ua4nxkriSMWjgsX6XJFDdDW60I3P4VWab5 +ag5fZzbGqi8kva/CzGgZh+CES0aWCPy+4Gb8lwOTt+854/laaJvd6kgKTER7z7U9 +9C86Ch2y4sXNwwwPJ1A9dmrZJZOcJjS/WYZgwaafY2Hdxub5jqPE5nehwYUPVu9R +uH6/skk4OEKcfOtN0hCnISOVuKYyS4ANARWRG5VGHIH06z3lGUVARFRJ61gtAprd +La+fgSS+LVZ+kU2TkeoWAKvGq8MAgDq4D4Xqwekg7WKFeuyusi/NI5rm40XgjBMF +DF72IUofoVt7wo0= +-----END CERTIFICATE-----` + +func TestMultipleRDN(t *testing.T) { + block, _ := pem.Decode([]byte(certMultipleRDN)) + cert, err := ParseCertificate(block.Bytes) + if err != nil { + t.Fatalf("certificate with two elements in an RDN failed to parse: %v", err) + } + + if want := "eportal.mss.edus.si"; cert.Subject.CommonName != want { + t.Errorf("got common name of %q, but want %q", cert.Subject.CommonName, want) + } + + if want := "1236484010010"; cert.Subject.SerialNumber != want { + t.Errorf("got serial number of %q, but want %q", cert.Subject.SerialNumber, want) + } +} + +func TestSystemCertPool(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("not implemented on Windows; Issue 16736, 18609") + } + a, err := SystemCertPool() + if err != nil { + t.Fatal(err) + } + b, err := SystemCertPool() + if err != nil { + t.Fatal(err) + } + if !certPoolEqual(a, b) { + t.Fatal("two calls to SystemCertPool had different results") + } + if ok := b.AppendCertsFromPEM([]byte(` +-----BEGIN CERTIFICATE----- +MIIDBjCCAe6gAwIBAgIRANXM5I3gjuqDfTp/PYrs+u8wDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xODAzMjcxOTU2MjFaFw0xOTAzMjcxOTU2 +MjFaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDK+9m3rjsO2Djes6bIYQZ3eV29JF09ZrjOrEHLtaKrD6/acsoSoTsf +cQr+rzzztdB5ijWXCS64zo/0OiqBeZUNZ67jVdToa9qW5UYe2H0Y+ZNdfA5GYMFD +yk/l3/uBu3suTZPfXiW2TjEi27Q8ruNUIZ54DpTcs6y2rBRFzadPWwn/VQMlvRXM +jrzl8Y08dgnYmaAHprxVzwMXcQ/Brol+v9GvjaH1DooHqkn8O178wsPQNhdtvN01 +IXL46cYdcUwWrE/GX5u+9DaSi+0KWxAPQ+NVD5qUI0CKl4714yGGh7feXMjJdHgl +VG4QJZlJvC4FsURgCHJT6uHGIelnSwhbAgMBAAGjVzBVMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMCAGA1UdEQQZMBeC +FVRlc3RTeXN0ZW1DZXJ0UG9vbC5nbzANBgkqhkiG9w0BAQsFAAOCAQEAwuSRx/VR +BKh2ICxZjL6jBwk/7UlU1XKbhQD96RqkidDNGEc6eLZ90Z5XXTurEsXqdm5jQYPs +1cdcSW+fOSMl7MfW9e5tM66FaIPZl9rKZ1r7GkOfgn93xdLAWe8XHd19xRfDreub +YC8DVqgLASOEYFupVSl76ktPfxkU5KCvmUf3P2PrRybk1qLGFytGxfyice2gHSNI +gify3K/+H/7wCkyFW4xYvzl7WW4mXxoqPRPjQt1J423DhnnQ4G1P8V/vhUpXNXOq +N9IEPnWuihC09cyx/WMQIUlWnaQLHdfpPS04Iez3yy2PdfXJzwfPrja7rNE+skK6 +pa/O1nF0AfWOpw== +-----END CERTIFICATE----- + `)); !ok { + t.Fatal("AppendCertsFromPEM failed") + } + if reflect.DeepEqual(a, b) { + t.Fatal("changing one pool modified the other") + } +} + +const emptyNameConstraintsPEM = ` +-----BEGIN CERTIFICATE----- +MIIC1jCCAb6gAwIBAgICEjQwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAxMdRW1w +dHkgbmFtZSBjb25zdHJhaW50cyBpc3N1ZXIwHhcNMTMwMjAxMDAwMDAwWhcNMjAw +NTMwMTA0ODM4WjAhMR8wHQYDVQQDExZFbXB0eSBuYW1lIGNvbnN0cmFpbnRzMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwriElUIt3LCqmJObs+yDoWPD +F5IqgWk6moIobYjPfextZiYU6I3EfvAwoNxPDkN2WowcocUZMJbEeEq5ebBksFnx +f12gBxlIViIYwZAzu7aFvhDMyPKQI3C8CG0ZSC9ABZ1E3umdA3CEueNOmP/TChNq +Cl23+BG1Qb/PJkpAO+GfpWSVhTcV53Mf/cKvFHcjGNrxzdSoq9fyW7a6gfcGEQY0 +LVkmwFWUfJ0wT8kaeLr0E0tozkIfo01KNWNzv6NcYP80QOBRDlApWu9ODmEVJHPD +blx4jzTQ3JLa+4DvBNOjVUOp+mgRmjiW0rLdrxwOxIqIOwNjweMCp/hgxX/hTQID +AQABoxEwDzANBgNVHR4EBjAEoAChADANBgkqhkiG9w0BAQsFAAOCAQEAWG+/zUMH +QhP8uNCtgSHyim/vh7wminwAvWgMKxlkLBFns6nZeQqsOV1lABY7U0Zuoqa1Z5nb +6L+iJa4ElREJOi/erLc9uLwBdDCAR0hUTKD7a6i4ooS39DTle87cUnj0MW1CUa6H +v5SsvpYW+1XleYJk/axQOOTcy4Es53dvnZsjXH0EA/QHnn7UV+JmlE3rtVxcYp6M +LYPmRhTioROA/drghicRkiu9hxdPyxkYS16M5g3Zj30jdm+k/6C6PeNtN9YmOOga +nCOSyFYfGhqOANYzpmuV+oIedAsPpIbfIzN8njYUs1zio+1IoI4o8ddM9sCbtPU8 +o+WoY6IsCKXV/g== +-----END CERTIFICATE-----` + +func TestEmptyNameConstraints(t *testing.T) { + block, _ := pem.Decode([]byte(emptyNameConstraintsPEM)) + _, err := ParseCertificate(block.Bytes) + if err == nil { + t.Fatal("unexpected success") + } + + const expected = "empty name constraints" + if str := err.Error(); !strings.Contains(str, expected) { + t.Errorf("expected %q in error but got %q", expected, str) + } +} + +func TestPKIXNameString(t *testing.T) { + der, err := base64.StdEncoding.DecodeString(certBytes) + if err != nil { + t.Fatal(err) + } + certs, err := ParseCertificates(der) + if err != nil { + t.Fatal(err) + } + + // Check that parsed non-standard attributes are printed. + rdns := pkix.Name{ + Locality: []string{"Gophertown"}, + ExtraNames: []pkix.AttributeTypeAndValue{ + {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}}, + }.ToRDNSequence() + nn := pkix.Name{} + nn.FillFromRDNSequence(&rdns) + + // Check that zero-length non-nil ExtraNames hide Names. + extra := []pkix.AttributeTypeAndValue{ + {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "backing array"}} + extraNotNil := pkix.Name{ + Locality: []string{"Gophertown"}, + ExtraNames: extra[:0], + Names: []pkix.AttributeTypeAndValue{ + {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}}, + } + + tests := []struct { + dn pkix.Name + want string + }{ + {nn, "L=Gophertown,1.2.3.4.5=#130a676f6c616e672e6f7267"}, + {extraNotNil, "L=Gophertown"}, + {pkix.Name{ + CommonName: "Steve Kille", + Organization: []string{"Isode Limited"}, + OrganizationalUnit: []string{"RFCs"}, + Locality: []string{"Richmond"}, + Province: []string{"Surrey"}, + StreetAddress: []string{"The Square"}, + PostalCode: []string{"TW9 1DT"}, + SerialNumber: "RFC 2253", + Country: []string{"GB"}, + }, "SERIALNUMBER=RFC 2253,CN=Steve Kille,OU=RFCs,O=Isode Limited,POSTALCODE=TW9 1DT,STREET=The Square,L=Richmond,ST=Surrey,C=GB"}, + {certs[0].Subject, + "CN=mail.google.com,O=Google LLC,L=Mountain View,ST=California,C=US"}, + {pkix.Name{ + Organization: []string{"#Google, Inc. \n-> 'Alphabet\" "}, + Country: []string{"US"}, + }, "O=\\#Google\\, Inc. \n-\\> 'Alphabet\\\"\\ ,C=US"}, + {pkix.Name{ + CommonName: "foo.com", + Organization: []string{"Gopher Industries"}, + ExtraNames: []pkix.AttributeTypeAndValue{ + {Type: asn1.ObjectIdentifier([]int{2, 5, 4, 3}), Value: "bar.com"}}, + }, "CN=bar.com,O=Gopher Industries"}, + {pkix.Name{ + Locality: []string{"Gophertown"}, + ExtraNames: []pkix.AttributeTypeAndValue{ + {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}}, + }, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown"}, + // If there are no ExtraNames, the Names are printed instead. + {pkix.Name{ + Locality: []string{"Gophertown"}, + Names: []pkix.AttributeTypeAndValue{ + {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}}, + }, "L=Gophertown,1.2.3.4.5=#130a676f6c616e672e6f7267"}, + // If there are both, print only the ExtraNames. + {pkix.Name{ + Locality: []string{"Gophertown"}, + ExtraNames: []pkix.AttributeTypeAndValue{ + {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}}, + Names: []pkix.AttributeTypeAndValue{ + {Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 6}), Value: "example.com"}}, + }, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown"}, + } + + for i, test := range tests { + if got := test.dn.String(); got != test.want { + t.Errorf("#%d: String() = \n%s\n, want \n%s", i, got, test.want) + } + } + + if extra[0].Value != "backing array" { + t.Errorf("the backing array of an empty ExtraNames got modified by String") + } +} + +func TestRDNSequenceString(t *testing.T) { + // Test some extra cases that get lost in pkix.Name conversions such as + // multi-valued attributes. + + var ( + oidCountry = []int{2, 5, 4, 6} + oidOrganization = []int{2, 5, 4, 10} + oidOrganizationalUnit = []int{2, 5, 4, 11} + oidCommonName = []int{2, 5, 4, 3} + ) + + tests := []struct { + seq pkix.RDNSequence + want string + }{ + { + seq: pkix.RDNSequence{ + pkix.RelativeDistinguishedNameSET{ + pkix.AttributeTypeAndValue{Type: oidCountry, Value: "US"}, + }, + pkix.RelativeDistinguishedNameSET{ + pkix.AttributeTypeAndValue{Type: oidOrganization, Value: "Widget Inc."}, + }, + pkix.RelativeDistinguishedNameSET{ + pkix.AttributeTypeAndValue{Type: oidOrganizationalUnit, Value: "Sales"}, + pkix.AttributeTypeAndValue{Type: oidCommonName, Value: "J. Smith"}, + }, + }, + want: "OU=Sales+CN=J. Smith,O=Widget Inc.,C=US", + }, + } + + for i, test := range tests { + if got := test.seq.String(); got != test.want { + t.Errorf("#%d: String() = \n%s\n, want \n%s", i, got, test.want) + } + } +} + +const criticalNameConstraintWithUnknownTypePEM = ` +-----BEGIN CERTIFICATE----- +MIIC/TCCAeWgAwIBAgICEjQwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAxMdRW1w +dHkgbmFtZSBjb25zdHJhaW50cyBpc3N1ZXIwHhcNMTMwMjAxMDAwMDAwWhcNMjAw +NTMwMTA0ODM4WjAhMR8wHQYDVQQDExZFbXB0eSBuYW1lIGNvbnN0cmFpbnRzMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwriElUIt3LCqmJObs+yDoWPD +F5IqgWk6moIobYjPfextZiYU6I3EfvAwoNxPDkN2WowcocUZMJbEeEq5ebBksFnx +f12gBxlIViIYwZAzu7aFvhDMyPKQI3C8CG0ZSC9ABZ1E3umdA3CEueNOmP/TChNq +Cl23+BG1Qb/PJkpAO+GfpWSVhTcV53Mf/cKvFHcjGNrxzdSoq9fyW7a6gfcGEQY0 +LVkmwFWUfJ0wT8kaeLr0E0tozkIfo01KNWNzv6NcYP80QOBRDlApWu9ODmEVJHPD +blx4jzTQ3JLa+4DvBNOjVUOp+mgRmjiW0rLdrxwOxIqIOwNjweMCp/hgxX/hTQID +AQABozgwNjA0BgNVHR4BAf8EKjAooCQwIokgIACrzQAAAAAAAAAAAAAAAP////8A +AAAAAAAAAAAAAAChADANBgkqhkiG9w0BAQsFAAOCAQEAWG+/zUMHQhP8uNCtgSHy +im/vh7wminwAvWgMKxlkLBFns6nZeQqsOV1lABY7U0Zuoqa1Z5nb6L+iJa4ElREJ +Oi/erLc9uLwBdDCAR0hUTKD7a6i4ooS39DTle87cUnj0MW1CUa6Hv5SsvpYW+1Xl +eYJk/axQOOTcy4Es53dvnZsjXH0EA/QHnn7UV+JmlE3rtVxcYp6MLYPmRhTioROA +/drghicRkiu9hxdPyxkYS16M5g3Zj30jdm+k/6C6PeNtN9YmOOganCOSyFYfGhqO +ANYzpmuV+oIedAsPpIbfIzN8njYUs1zio+1IoI4o8ddM9sCbtPU8o+WoY6IsCKXV +/g== +-----END CERTIFICATE-----` + +func TestCriticalNameConstraintWithUnknownType(t *testing.T) { + block, _ := pem.Decode([]byte(criticalNameConstraintWithUnknownTypePEM)) + cert, err := ParseCertificate(block.Bytes) + if err != nil { + t.Fatalf("unexpected parsing failure: %s", err) + } + + if l := len(cert.UnhandledCriticalExtensions); l != 1 { + t.Fatalf("expected one unhandled critical extension, but found %d", l) + } +} + +const badIPMaskPEM = ` +-----BEGIN CERTIFICATE----- +MIICzzCCAbegAwIBAgICEjQwDQYJKoZIhvcNAQELBQAwHTEbMBkGA1UEAxMSQmFk +IElQIG1hc2sgaXNzdWVyMB4XDTEzMDIwMTAwMDAwMFoXDTIwMDUzMDEwNDgzOFow +FjEUMBIGA1UEAxMLQmFkIElQIG1hc2swggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDCuISVQi3csKqYk5uz7IOhY8MXkiqBaTqagihtiM997G1mJhTojcR+ +8DCg3E8OQ3ZajByhxRkwlsR4Srl5sGSwWfF/XaAHGUhWIhjBkDO7toW+EMzI8pAj +cLwIbRlIL0AFnUTe6Z0DcIS5406Y/9MKE2oKXbf4EbVBv88mSkA74Z+lZJWFNxXn +cx/9wq8UdyMY2vHN1Kir1/JbtrqB9wYRBjQtWSbAVZR8nTBPyRp4uvQTS2jOQh+j +TUo1Y3O/o1xg/zRA4FEOUCla704OYRUkc8NuXHiPNNDcktr7gO8E06NVQ6n6aBGa +OJbSst2vHA7Eiog7A2PB4wKn+GDFf+FNAgMBAAGjIDAeMBwGA1UdHgEB/wQSMBCg +DDAKhwgBAgME//8BAKEAMA0GCSqGSIb3DQEBCwUAA4IBAQBYb7/NQwdCE/y40K2B +IfKKb++HvCaKfAC9aAwrGWQsEWezqdl5Cqw5XWUAFjtTRm6iprVnmdvov6IlrgSV +EQk6L96stz24vAF0MIBHSFRMoPtrqLiihLf0NOV7ztxSePQxbUJRroe/lKy+lhb7 +VeV5gmT9rFA45NzLgSznd2+dmyNcfQQD9AeeftRX4maUTeu1XFxinowtg+ZGFOKh +E4D92uCGJxGSK72HF0/LGRhLXozmDdmPfSN2b6T/oLo942031iY46BqcI5LIVh8a +Go4A1jOma5X6gh50Cw+kht8jM3yeNhSzXOKj7Uigjijx10z2wJu09Tyj5ahjoiwI +pdX+ +-----END CERTIFICATE-----` + +func TestBadIPMask(t *testing.T) { + block, _ := pem.Decode([]byte(badIPMaskPEM)) + _, err := ParseCertificate(block.Bytes) + if err == nil { + t.Fatalf("unexpected success") + } + + const expected = "contained invalid mask" + if !strings.Contains(err.Error(), expected) { + t.Fatalf("expected %q in error but got: %s", expected, err) + } +} + +const additionalGeneralSubtreePEM = ` +-----BEGIN CERTIFICATE----- +MIIG4TCCBMmgAwIBAgIRALss+4rLw2Ia7tFFhxE8g5cwDQYJKoZIhvcNAQELBQAw +bjELMAkGA1UEBhMCTkwxIDAeBgNVBAoMF01pbmlzdGVyaWUgdmFuIERlZmVuc2ll +MT0wOwYDVQQDDDRNaW5pc3RlcmllIHZhbiBEZWZlbnNpZSBDZXJ0aWZpY2F0aWUg +QXV0b3JpdGVpdCAtIEcyMB4XDTEzMDMwNjEyMDM0OVoXDTEzMTEzMDEyMDM1MFow +bDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUNlcnRpUGF0aCBMTEMxIjAgBgNVBAsT +GUNlcnRpZmljYXRpb24gQXV0aG9yaXRpZXMxITAfBgNVBAMTGENlcnRpUGF0aCBC +cmlkZ2UgQ0EgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANLW +4kXiRqvwBhJfN9uz12FA+P2D34MPxOt7TGXljm2plJ2CLzvaH8/ymsMdSWdJBS1M +8FmwvNL1w3A6ZuzksJjPikAu8kY3dcp3mrkk9eCPORDAwGtfsXwZysLiuEaDWpbD +dHOaHnI6qWU0N6OI+hNX58EjDpIGC1WQdho1tHOTPc5Hf5/hOpM/29v/wr7kySjs +Z+7nsvkm5rNhuJNzPsLsgzVaJ5/BVyOplZy24FKM8Y43MjR4osZm+a2e0zniqw6/ +rvcjcGYabYaznZfQG1GXoyf2Vea+CCgpgUhlVafgkwEs8izl8rIpvBzXiFAgFQuG +Ituoy92PJbDs430fA/cCAwEAAaOCAnowggJ2MEUGCCsGAQUFBwEBBDkwNzA1Bggr +BgEFBQcwAoYpaHR0cDovL2NlcnRzLmNhLm1pbmRlZi5ubC9taW5kZWYtY2EtMi5w +N2MwHwYDVR0jBBgwFoAUzln9WSPz2M64Rl2HYf2/KD8StmQwDwYDVR0TAQH/BAUw +AwEB/zCB6QYDVR0gBIHhMIHeMEgGCmCEEAGHawECBQEwOjA4BggrBgEFBQcCARYs +aHR0cDovL2Nwcy5kcC5jYS5taW5kZWYubmwvbWluZGVmLWNhLWRwLWNwcy8wSAYK +YIQQAYdrAQIFAjA6MDgGCCsGAQUFBwIBFixodHRwOi8vY3BzLmRwLmNhLm1pbmRl +Zi5ubC9taW5kZWYtY2EtZHAtY3BzLzBIBgpghBABh2sBAgUDMDowOAYIKwYBBQUH +AgEWLGh0dHA6Ly9jcHMuZHAuY2EubWluZGVmLm5sL21pbmRlZi1jYS1kcC1jcHMv +MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmxzLmNhLm1pbmRlZi5ubC9taW5k +ZWYtY2EtMi5jcmwwDgYDVR0PAQH/BAQDAgEGMEYGA1UdHgEB/wQ8MDqhODA2pDEw +LzELMAkGA1UEBhMCTkwxIDAeBgNVBAoTF01pbmlzdGVyaWUgdmFuIERlZmVuc2ll +gQFjMF0GA1UdIQRWMFQwGgYKYIQQAYdrAQIFAQYMKwYBBAGBu1MBAQECMBoGCmCE +EAGHawECBQIGDCsGAQQBgbtTAQEBAjAaBgpghBABh2sBAgUDBgwrBgEEAYG7UwEB +AQIwHQYDVR0OBBYEFNDCjBM3M3ZKkag84ei3/aKc0d0UMA0GCSqGSIb3DQEBCwUA +A4ICAQAQXFn9jF90/DNFf15JhoGtta/0dNInb14PMu3PAjcdrXYCDPpQZOArTUng +5YT1WuzfmjnXiTsziT3my0r9Mxvz/btKK/lnVOMW4c2q/8sIsIPnnW5ZaRGrsANB +dNDZkzMYmeG2Pfgvd0AQSOrpE/TVgWfu/+MMRWwX9y6VbooBR7BLv7zMuVH0WqLn +6OMFth7fqsThlfMSzkE/RDSaU6n3wXAWT1SIqBITtccRjSUQUFm/q3xrb2cwcZA6 +8vdS4hzNd+ttS905ay31Ks4/1Wrm1bH5RhEfRSH0VSXnc0b+z+RyBbmiwtVZqzxE +u3UQg/rAmtLDclLFEzjp8YDTIRYSLwstDbEXO/0ArdGrQm79HQ8i/3ZbP2357myW +i15qd6gMJIgGHS4b8Hc7R1K8LQ9Gm1aLKBEWVNGZlPK/cpXThpVmoEyslN2DHCrc +fbMbjNZpXlTMa+/b9z7Fa4X8dY8u/ELzZuJXJv5Rmqtg29eopFFYDCl0Nkh1XAjo +QejEoHHUvYV8TThHZr6Z6Ib8CECgTehU4QvepkgDXNoNrKRZBG0JhLjkwxh2whZq +nvWBfALC2VuNOM6C0rDY+HmhMlVt0XeqnybD9MuQALMit7Z00Cw2CIjNsBI9xBqD +xKK9CjUb7gzRUWSpB9jGHsvpEMHOzIFhufvH2Bz1XJw+Cl7khw== +-----END CERTIFICATE-----` + +func TestAdditionFieldsInGeneralSubtree(t *testing.T) { + // Very rarely, certificates can include additional fields in the + // GeneralSubtree structure. This tests that such certificates can be + // parsed. + block, _ := pem.Decode([]byte(additionalGeneralSubtreePEM)) + if _, err := ParseCertificate(block.Bytes); err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } +} + +func TestEmptySubject(t *testing.T) { + template := Certificate{ + SerialNumber: big.NewInt(1), + DNSNames: []string{"example.com"}, + } + + derBytes, err := CreateCertificate(rand.Reader, &template, &template, &testPrivateKey.PublicKey, testPrivateKey) + if err != nil { + t.Fatalf("failed to create certificate: %s", err) + } + + cert, err := ParseCertificate(derBytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + + for _, ext := range cert.Extensions { + if ext.Id.Equal(oidExtensionSubjectAltName) { + if !ext.Critical { + t.Fatal("SAN extension is not critical") + } + return + } + } + + t.Fatal("SAN extension is missing") +} + +// multipleURLsInCRLDPPEM contains two URLs in a single CRL DistributionPoint +// structure. It is taken from https://crt.sh/?id=12721534. +const multipleURLsInCRLDPPEM = ` +-----BEGIN CERTIFICATE----- +MIIF4TCCBMmgAwIBAgIQc+6uFePfrahUGpXs8lhiTzANBgkqhkiG9w0BAQsFADCB +8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy +dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1 +YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3 +dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh +IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD +LUFDQzAeFw0xNDA5MTgwODIxMDBaFw0zMDA5MTgwODIxMDBaMIGGMQswCQYDVQQG +EwJFUzEzMDEGA1UECgwqQ09OU09SQ0kgQURNSU5JU1RSQUNJTyBPQkVSVEEgREUg +Q0FUQUxVTllBMSowKAYDVQQLDCFTZXJ2ZWlzIFDDumJsaWNzIGRlIENlcnRpZmlj +YWNpw7MxFjAUBgNVBAMMDUVDLUNpdXRhZGFuaWEwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDFkHPRZPZlXTWZ5psJhbS/Gx+bxcTpGrlVQHHtIkgGz77y +TA7UZUFb2EQMncfbOhR0OkvQQn1aMvhObFJSR6nI+caf2D+h/m/InMl1MyH3S0Ak +YGZZsthnyC6KxqK2A/NApncrOreh70ULkQs45aOKsi1kR1W0zE+iFN+/P19P7AkL +Rl3bXBCVd8w+DLhcwRrkf1FCDw6cEqaFm3cGgf5cbBDMaVYAweWTxwBZAq2RbQAW +jE7mledcYghcZa4U6bUmCBPuLOnO8KMFAvH+aRzaf3ws5/ZoOVmryyLLJVZ54peZ +OwnP9EL4OuWzmXCjBifXR2IAblxs5JYj57tls45nAgMBAAGjggHaMIIB1jASBgNV +HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUC2hZPofI +oxUa4ECCIl+fHbLFNxUwHwYDVR0jBBgwFoAUoMOLRKo3pUW/l4Ba0fF4opvpXY0w +gdYGA1UdIASBzjCByzCByAYEVR0gADCBvzAxBggrBgEFBQcCARYlaHR0cHM6Ly93 +d3cuYW9jLmNhdC9DQVRDZXJ0L1JlZ3VsYWNpbzCBiQYIKwYBBQUHAgIwfQx7QXF1 +ZXN0IGNlcnRpZmljYXQgw6lzIGVtw6hzIMO6bmljYSBpIGV4Y2x1c2l2YW1lbnQg +YSBFbnRpdGF0cyBkZSBDZXJ0aWZpY2FjacOzLiBWZWdldSBodHRwczovL3d3dy5h +b2MuY2F0L0NBVENlcnQvUmVndWxhY2lvMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEF +BQcwAYYXaHR0cDovL29jc3AuY2F0Y2VydC5jYXQwYgYDVR0fBFswWTBXoFWgU4Yn +aHR0cDovL2Vwc2NkLmNhdGNlcnQubmV0L2NybC9lYy1hY2MuY3JshihodHRwOi8v +ZXBzY2QyLmNhdGNlcnQubmV0L2NybC9lYy1hY2MuY3JsMA0GCSqGSIb3DQEBCwUA +A4IBAQChqFTjlAH5PyIhLjLgEs68CyNNC1+vDuZXRhy22TI83JcvGmQrZosPvVIL +PsUXx+C06Pfqmh48Q9S89X9K8w1SdJxP/rZeGEoRiKpwvQzM4ArD9QxyC8jirxex +3Umg9Ai/sXQ+1lBf6xw4HfUUr1WIp7pNHj0ZWLo106urqktcdeAFWme+/klis5fu +labCSVPuT/QpwakPrtqOhRms8vgpKiXa/eLtL9ZiA28X/Mker0zlAeTA7Z7uAnp6 +oPJTlZu1Gg1ZDJueTWWsLlO+P+Wzm3MRRIbcgdRzm4mdO7ubu26SzX/aQXDhuih+ +eVxXDTCfs7GUlxnjOp5j559X/N0A +-----END CERTIFICATE----- +` + +func TestMultipleURLsInCRLDP(t *testing.T) { + block, _ := pem.Decode([]byte(multipleURLsInCRLDPPEM)) + cert, err := ParseCertificate(block.Bytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + + want := []string{ + "http://epscd.catcert.net/crl/ec-acc.crl", + "http://epscd2.catcert.net/crl/ec-acc.crl", + } + if got := cert.CRLDistributionPoints; !reflect.DeepEqual(got, want) { + t.Errorf("CRL distribution points = %#v, want #%v", got, want) + } +} + +const hexPKCS1TestPKCS8Key = "30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031" +const hexPKCS1TestECKey = "3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50" + +var pkcs1MismatchKeyTests = []struct { + hexKey string + errorContains string +}{ + {hexKey: hexPKCS1TestPKCS8Key, errorContains: "use ParsePKCS8PrivateKey instead"}, + {hexKey: hexPKCS1TestECKey, errorContains: "use ParseECPrivateKey instead"}, +} + +func TestPKCS1MismatchKeyFormat(t *testing.T) { + for i, test := range pkcs1MismatchKeyTests { + derBytes, _ := hex.DecodeString(test.hexKey) + _, err := ParsePKCS1PrivateKey(derBytes) + if !strings.Contains(err.Error(), test.errorContains) { + t.Errorf("#%d: expected error containing %q, got %s", i, test.errorContains, err) + } + } +} + +func TestCreateRevocationList(t *testing.T) { + ec256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("Failed to generate ECDSA P256 key: %s", err) + } + _, ed25519Priv, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + t.Fatalf("Failed to generate Ed25519 key: %s", err) + } + tests := []struct { + name string + key crypto.Signer + issuer *Certificate + template *RevocationList + expectedError string + }{ + { + name: "nil template", + key: ec256Priv, + issuer: nil, + template: nil, + expectedError: "x509: template can not be nil", + }, + { + name: "nil issuer", + key: ec256Priv, + issuer: nil, + template: &RevocationList{}, + expectedError: "x509: issuer can not be nil", + }, + { + name: "issuer doesn't have crlSign key usage bit set", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCertSign, + }, + template: &RevocationList{}, + expectedError: "x509: issuer must have the crlSign key usage bit set", + }, + { + name: "issuer missing SubjectKeyId", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + }, + template: &RevocationList{}, + expectedError: "x509: issuer certificate doesn't contain a subject key identifier", + }, + { + name: "nextUpdate before thisUpdate", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + Subject: pkix.Name{ + CommonName: "testing", + }, + SubjectKeyId: []byte{1, 2, 3}, + }, + template: &RevocationList{ + ThisUpdate: time.Time{}.Add(time.Hour), + NextUpdate: time.Time{}, + }, + expectedError: "x509: template.ThisUpdate is after template.NextUpdate", + }, + { + name: "nil Number", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + Subject: pkix.Name{ + CommonName: "testing", + }, + SubjectKeyId: []byte{1, 2, 3}, + }, + template: &RevocationList{ + ThisUpdate: time.Time{}.Add(time.Hour * 24), + NextUpdate: time.Time{}.Add(time.Hour * 48), + }, + expectedError: "x509: template contains nil Number field", + }, + { + name: "invalid signature algorithm", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + Subject: pkix.Name{ + CommonName: "testing", + }, + SubjectKeyId: []byte{1, 2, 3}, + }, + template: &RevocationList{ + SignatureAlgorithm: SHA256WithRSA, + RevokedCertificates: []pkix.RevokedCertificate{ + { + SerialNumber: big.NewInt(2), + RevocationTime: time.Time{}.Add(time.Hour), + }, + }, + Number: big.NewInt(5), + ThisUpdate: time.Time{}.Add(time.Hour * 24), + NextUpdate: time.Time{}.Add(time.Hour * 48), + }, + expectedError: "x509: requested SignatureAlgorithm does not match private key type", + }, + { + name: "valid", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + Subject: pkix.Name{ + CommonName: "testing", + }, + SubjectKeyId: []byte{1, 2, 3}, + }, + template: &RevocationList{ + RevokedCertificates: []pkix.RevokedCertificate{ + { + SerialNumber: big.NewInt(2), + RevocationTime: time.Time{}.Add(time.Hour), + }, + }, + Number: big.NewInt(5), + ThisUpdate: time.Time{}.Add(time.Hour * 24), + NextUpdate: time.Time{}.Add(time.Hour * 48), + }, + }, + { + name: "valid, Ed25519 key", + key: ed25519Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + Subject: pkix.Name{ + CommonName: "testing", + }, + SubjectKeyId: []byte{1, 2, 3}, + }, + template: &RevocationList{ + RevokedCertificates: []pkix.RevokedCertificate{ + { + SerialNumber: big.NewInt(2), + RevocationTime: time.Time{}.Add(time.Hour), + }, + }, + Number: big.NewInt(5), + ThisUpdate: time.Time{}.Add(time.Hour * 24), + NextUpdate: time.Time{}.Add(time.Hour * 48), + }, + }, + { + name: "valid, non-default signature algorithm", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + Subject: pkix.Name{ + CommonName: "testing", + }, + SubjectKeyId: []byte{1, 2, 3}, + }, + template: &RevocationList{ + SignatureAlgorithm: ECDSAWithSHA512, + RevokedCertificates: []pkix.RevokedCertificate{ + { + SerialNumber: big.NewInt(2), + RevocationTime: time.Time{}.Add(time.Hour), + }, + }, + Number: big.NewInt(5), + ThisUpdate: time.Time{}.Add(time.Hour * 24), + NextUpdate: time.Time{}.Add(time.Hour * 48), + }, + }, + { + name: "valid, extra extension", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + Subject: pkix.Name{ + CommonName: "testing", + }, + SubjectKeyId: []byte{1, 2, 3}, + }, + template: &RevocationList{ + RevokedCertificates: []pkix.RevokedCertificate{ + { + SerialNumber: big.NewInt(2), + RevocationTime: time.Time{}.Add(time.Hour), + }, + }, + Number: big.NewInt(5), + ThisUpdate: time.Time{}.Add(time.Hour * 24), + NextUpdate: time.Time{}.Add(time.Hour * 48), + ExtraExtensions: []pkix.Extension{ + { + Id: []int{2, 5, 29, 99}, + Value: []byte{5, 0}, + }, + }, + }, + }, + { + name: "valid, empty list", + key: ec256Priv, + issuer: &Certificate{ + KeyUsage: KeyUsageCRLSign, + Subject: pkix.Name{ + CommonName: "testing", + }, + SubjectKeyId: []byte{1, 2, 3}, + }, + template: &RevocationList{ + Number: big.NewInt(5), + ThisUpdate: time.Time{}.Add(time.Hour * 24), + NextUpdate: time.Time{}.Add(time.Hour * 48), + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + crl, err := CreateRevocationList(rand.Reader, tc.template, tc.issuer, tc.key) + if err != nil && tc.expectedError == "" { + t.Fatalf("CreateRevocationList failed unexpectedly: %s", err) + } else if err != nil && tc.expectedError != err.Error() { + t.Fatalf("CreateRevocationList failed unexpectedly, wanted: %s, got: %s", tc.expectedError, err) + } else if err == nil && tc.expectedError != "" { + t.Fatalf("CreateRevocationList didn't fail, expected: %s", tc.expectedError) + } + if tc.expectedError != "" { + return + } + + parsedCRL, err := ParseDERCRL(crl) + if err != nil { + t.Fatalf("Failed to parse generated CRL: %s", err) + } + + if tc.template.SignatureAlgorithm != UnknownSignatureAlgorithm && + parsedCRL.SignatureAlgorithm.Algorithm.Equal(signatureAlgorithmDetails[tc.template.SignatureAlgorithm].oid) { + t.Fatalf("SignatureAlgorithm mismatch: got %v; want %v.", parsedCRL.SignatureAlgorithm, + tc.template.SignatureAlgorithm) + } + + if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, tc.template.RevokedCertificates) { + t.Fatalf("RevokedCertificates mismatch: got %v; want %v.", + parsedCRL.TBSCertList.RevokedCertificates, tc.template.RevokedCertificates) + } + + if len(parsedCRL.TBSCertList.Extensions) != 2+len(tc.template.ExtraExtensions) { + t.Fatalf("Generated CRL has wrong number of extensions, wanted: %d, got: %d", 2+len(tc.template.ExtraExtensions), len(parsedCRL.TBSCertList.Extensions)) + } + expectedAKI, err := asn1.Marshal(authKeyId{Id: tc.issuer.SubjectKeyId}) + if err != nil { + t.Fatalf("asn1.Marshal failed: %s", err) + } + akiExt := pkix.Extension{ + Id: oidExtensionAuthorityKeyId, + Value: expectedAKI, + } + if !reflect.DeepEqual(parsedCRL.TBSCertList.Extensions[0], akiExt) { + t.Fatalf("Unexpected first extension: got %v, want %v", + parsedCRL.TBSCertList.Extensions[0], akiExt) + } + expectedNum, err := asn1.Marshal(tc.template.Number) + if err != nil { + t.Fatalf("asn1.Marshal failed: %s", err) + } + crlExt := pkix.Extension{ + Id: oidExtensionCRLNumber, + Value: expectedNum, + } + if !reflect.DeepEqual(parsedCRL.TBSCertList.Extensions[1], crlExt) { + t.Fatalf("Unexpected second extension: got %v, want %v", + parsedCRL.TBSCertList.Extensions[1], crlExt) + } + if len(parsedCRL.TBSCertList.Extensions[2:]) == 0 && len(tc.template.ExtraExtensions) == 0 { + // If we don't have anything to check return early so we don't + // hit a [] != nil false positive below. + return + } + if !reflect.DeepEqual(parsedCRL.TBSCertList.Extensions[2:], tc.template.ExtraExtensions) { + t.Fatalf("Extensions mismatch: got %v; want %v.", + parsedCRL.TBSCertList.Extensions[2:], tc.template.ExtraExtensions) + } + }) + } +} + +func TestRSAPSAParameters(t *testing.T) { + generateParams := func(hashFunc crypto.Hash) []byte { + var hashOID asn1.ObjectIdentifier + + switch hashFunc { + case crypto.SHA256: + hashOID = oidSHA256 + case crypto.SHA384: + hashOID = oidSHA384 + case crypto.SHA512: + hashOID = oidSHA512 + } + + params := pssParameters{ + Hash: pkix.AlgorithmIdentifier{ + Algorithm: hashOID, + Parameters: asn1.NullRawValue, + }, + MGF: pkix.AlgorithmIdentifier{ + Algorithm: oidMGF1, + }, + SaltLength: hashFunc.Size(), + TrailerField: 1, + } + + mgf1Params := pkix.AlgorithmIdentifier{ + Algorithm: hashOID, + Parameters: asn1.NullRawValue, + } + + var err error + params.MGF.Parameters.FullBytes, err = asn1.Marshal(mgf1Params) + if err != nil { + t.Fatalf("failed to marshal MGF parameters: %s", err) + } + + serialized, err := asn1.Marshal(params) + if err != nil { + t.Fatalf("failed to marshal parameters: %s", err) + } + + return serialized + } + + for h, params := range hashToPSSParameters { + generated := generateParams(h) + if !bytes.Equal(params.FullBytes, generated) { + t.Errorf("hardcoded parameters for %s didn't match generated parameters: got (generated) %x, wanted (hardcoded) %x", h, generated, params.FullBytes) + } + } +} + +func TestUnknownExtKey(t *testing.T) { + const errorContains = "unknown extended key usage" + + template := &Certificate{ + SerialNumber: big.NewInt(10), + DNSNames: []string{"foo"}, + ExtKeyUsage: []ExtKeyUsage{ExtKeyUsage(-1)}, + } + signer, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + t.Errorf("failed to generate key for TestUnknownExtKey") + } + + _, err = CreateCertificate(rand.Reader, template, template, signer.Public(), signer) + if !strings.Contains(err.Error(), errorContains) { + t.Errorf("expected error containing %q, got %s", errorContains, err) + } +} + +func TestIA5SANEnforcement(t *testing.T) { + k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("ecdsa.GenerateKey failed: %s", err) + } + + testURL, err := url.Parse("https://example.com/") + if err != nil { + t.Fatalf("url.Parse failed: %s", err) + } + testURL.RawQuery = "∞" + + marshalTests := []struct { + name string + template *Certificate + expectedError string + }{ + { + name: "marshal: unicode dNSName", + template: &Certificate{ + SerialNumber: big.NewInt(0), + DNSNames: []string{"∞"}, + }, + expectedError: "x509: \"∞\" cannot be encoded as an IA5String", + }, + { + name: "marshal: unicode rfc822Name", + template: &Certificate{ + SerialNumber: big.NewInt(0), + EmailAddresses: []string{"∞"}, + }, + expectedError: "x509: \"∞\" cannot be encoded as an IA5String", + }, + { + name: "marshal: unicode uniformResourceIdentifier", + template: &Certificate{ + SerialNumber: big.NewInt(0), + URIs: []*url.URL{testURL}, + }, + expectedError: "x509: \"https://example.com/?∞\" cannot be encoded as an IA5String", + }, + } + + for _, tc := range marshalTests { + t.Run(tc.name, func(t *testing.T) { + _, err := CreateCertificate(rand.Reader, tc.template, tc.template, k.Public(), k) + if err == nil { + t.Errorf("expected CreateCertificate to fail with template: %v", tc.template) + } else if err.Error() != tc.expectedError { + t.Errorf("unexpected error: got %q, want %q", err.Error(), tc.expectedError) + } + }) + } + + unmarshalTests := []struct { + name string + cert string + expectedError string + }{ + { + name: "unmarshal: unicode dNSName", + cert: "308201083081aea003020102020100300a06082a8648ce3d04030230003022180f30303031303130313030303030305a180f30303031303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d0301070342000424bcc48180d8d9db794028f2575ebe3cac79f04d7b0d0151c5292e588aac3668c495f108c626168462e0668c9705e08a211dd103a659d2684e0adf8c2bfd47baa315301330110603551d110101ff040730058203e2889e300a06082a8648ce3d04030203490030460221008ac7827ac326a6ee0fa70b2afe99af575ec60b975f820f3c25f60fff43fbccd0022100bffeed93556722d43d13e461d5b3e33efc61f6349300327d3a0196cb6da501c2", + expectedError: "x509: SAN dNSName is malformed", + }, + { + name: "unmarshal: unicode rfc822Name", + cert: "308201083081aea003020102020100300a06082a8648ce3d04030230003022180f30303031303130313030303030305a180f30303031303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d0301070342000405cb4c4ba72aac980f7b11b0285191425e29e196ce7c5df1c83f56886566e517f196657cc1b73de89ab84ce503fd634e2f2af88fde24c63ca536dc3a5eed2665a315301330110603551d110101ff040730058103e2889e300a06082a8648ce3d0403020349003046022100ed1431cd4b9bb03d88d1511a0ec128a51204375764c716280dc36e2a60142c8902210088c96d25cfaf97eea851ff17d87bb6fe619d6546656e1739f35c3566051c3d0f", + expectedError: "x509: SAN rfc822Name is malformed", + }, + { + name: "unmarshal: unicode uniformResourceIdentifier", + cert: "3082011b3081c3a003020102020100300a06082a8648ce3d04030230003022180f30303031303130313030303030305a180f30303031303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d03010703420004ce0a79b511701d9188e1ea76bcc5907f1db51de6cc1a037b803f256e8588145ca409d120288bfeb4e38f3088104674d374b35bb91fc80d768d1d519dbe2b0b5aa32a302830260603551d110101ff041c301a861868747470733a2f2f6578616d706c652e636f6d2f3fe2889e300a06082a8648ce3d0403020347003044022044f4697779fd1dae1e382d2452413c5c5ca67851e267d6bc64a8d164977c172c0220505015e657637aa1945d46e7650b6f59b968fc1508ca8b152c99f782446dfc81", + expectedError: "x509: SAN uniformResourceIdentifier is malformed", + }, + } + + for _, tc := range unmarshalTests { + der, err := hex.DecodeString(tc.cert) + if err != nil { + t.Fatalf("failed to decode test cert: %s", err) + } + _, err = ParseCertificate(der) + if err == nil { + t.Error("expected CreateCertificate to fail") + } else if err.Error() != tc.expectedError { + t.Errorf("unexpected error: got %q, want %q", err.Error(), tc.expectedError) + } + } +} + +func BenchmarkCreateCertificate(b *testing.B) { + template := &Certificate{ + SerialNumber: big.NewInt(10), + DNSNames: []string{"example.com"}, + } + tests := []struct { + name string + gen func() crypto.Signer + }{ + { + name: "RSA 2048", + gen: func() crypto.Signer { + k, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + b.Fatalf("failed to generate test key: %s", err) + } + return k + }, + }, + { + name: "ECDSA P256", + gen: func() crypto.Signer { + k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + b.Fatalf("failed to generate test key: %s", err) + } + return k + }, + }, + } + + for _, tc := range tests { + k := tc.gen() + b.ResetTimer() + b.Run(tc.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, err := CreateCertificate(rand.Reader, template, template, k.Public(), k) + if err != nil { + b.Fatalf("failed to create certificate: %s", err) + } + } + }) + } +} + +type brokenSigner struct { + pub crypto.PublicKey +} + +func (bs *brokenSigner) Public() crypto.PublicKey { + return bs.pub +} + +func (bs *brokenSigner) Sign(_ io.Reader, _ []byte, _ crypto.SignerOpts) ([]byte, error) { + return []byte{1, 2, 3}, nil +} + +func TestCreateCertificateBrokenSigner(t *testing.T) { + template := &Certificate{ + SerialNumber: big.NewInt(10), + DNSNames: []string{"example.com"}, + } + k, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + t.Fatalf("failed to generate test key: %s", err) + } + expectedErr := "x509: signature over certificate returned by signer is invalid: crypto/rsa: verification error" + _, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()}) + if err == nil { + t.Fatal("expected CreateCertificate to fail with a broken signer") + } else if err.Error() != expectedErr { + t.Fatalf("CreateCertificate returned an unexpected error: got %q, want %q", err, expectedErr) + } +} + +func TestCreateCertificateMD5(t *testing.T) { + template := &Certificate{ + SerialNumber: big.NewInt(10), + DNSNames: []string{"example.com"}, + SignatureAlgorithm: MD5WithRSA, + } + k, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + t.Fatalf("failed to generate test key: %s", err) + } + _, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()}) + if err != nil { + t.Fatalf("CreateCertificate failed when SignatureAlgorithm = MD5WithRSA: %s", err) + } +} + +func (s *CertPool) mustCert(t *testing.T, n int) *Certificate { + c, err := s.lazyCerts[n].getCert() + if err != nil { + t.Fatalf("failed to load cert %d: %v", n, err) + } + return c +} + +func allCerts(t *testing.T, p *CertPool) []*Certificate { + all := make([]*Certificate, p.len()) + for i := range all { + all[i] = p.mustCert(t, i) + } + return all +} + +// certPoolEqual reports whether a and b are equal, except for the +// function pointers. +func certPoolEqual(a, b *CertPool) bool { + if (a != nil) != (b != nil) { + return false + } + if a == nil { + return true + } + if !reflect.DeepEqual(a.byName, b.byName) || + len(a.lazyCerts) != len(b.lazyCerts) { + return false + } + for i := range a.lazyCerts { + la, lb := a.lazyCerts[i], b.lazyCerts[i] + if !bytes.Equal(la.rawSubject, lb.rawSubject) { + return false + } + ca, err := la.getCert() + if err != nil { + panic(err) + } + cb, err := la.getCert() + if err != nil { + panic(err) + } + if !ca.Equal(cb) { + return false + } + } + + return true +} + +func TestCertificateRequestRoundtripFields(t *testing.T) { + urlA, err := url.Parse("https://example.com/_") + if err != nil { + t.Fatal(err) + } + urlB, err := url.Parse("https://example.org/_") + if err != nil { + t.Fatal(err) + } + in := &CertificateRequest{ + DNSNames: []string{"example.com", "example.org"}, + EmailAddresses: []string{"a@example.com", "b@example.com"}, + IPAddresses: []net.IP{net.IPv4(192, 0, 2, 0), net.IPv6loopback}, + URIs: []*url.URL{urlA, urlB}, + } + out := marshalAndParseCSR(t, in) + + if !reflect.DeepEqual(in.DNSNames, out.DNSNames) { + t.Fatalf("Unexpected DNSNames: got %v, want %v", out.DNSNames, in.DNSNames) + } + if !reflect.DeepEqual(in.EmailAddresses, out.EmailAddresses) { + t.Fatalf("Unexpected EmailAddresses: got %v, want %v", out.EmailAddresses, in.EmailAddresses) + } + if len(in.IPAddresses) != len(out.IPAddresses) || + !in.IPAddresses[0].Equal(out.IPAddresses[0]) || + !in.IPAddresses[1].Equal(out.IPAddresses[1]) { + t.Fatalf("Unexpected IPAddresses: got %v, want %v", out.IPAddresses, in.IPAddresses) + } + if !reflect.DeepEqual(in.URIs, out.URIs) { + t.Fatalf("Unexpected URIs: got %v, want %v", out.URIs, in.URIs) + } +} + +func BenchmarkParseCertificate(b *testing.B) { + cases := []struct { + name string + pem string + }{ + { + name: "ecdsa leaf", + pem: `-----BEGIN CERTIFICATE----- +MIIINjCCBx6gAwIBAgIQHdQ6oBMoe/MJAAAAAEHzmTANBgkqhkiG9w0BAQsFADBG +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMDEyMDgwOTExMzZaFw0yMTAzMDIw +OTExMzVaMBcxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABEFYegyHh1AHRS1nar5+zYJgMACcsIQMtg0YMyK/59ml8ERIt/JF +kXM3XIvQuCJhghUawZrrAcAs8djZF1U9M4mjggYYMIIGFDAOBgNVHQ8BAf8EBAMC +B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU +6SWWF36XBsmXJ6iV0EHPXUFoMbwwHwYDVR0jBBgwFoAUinR/r4XN7pXNPZzQ4kYU +83E1HScwagYIKwYBBQUHAQEEXjBcMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5w +a2kuZ29vZy9ndHMxYzMwMQYIKwYBBQUHMAKGJWh0dHA6Ly9wa2kuZ29vZy9yZXBv +L2NlcnRzL2d0czFjMy5kZXIwggTCBgNVHREEggS5MIIEtYIMKi5nb29nbGUuY29t +gg0qLmFuZHJvaWQuY29tghYqLmFwcGVuZ2luZS5nb29nbGUuY29tggkqLmJkbi5k +ZXaCEiouY2xvdWQuZ29vZ2xlLmNvbYIYKi5jcm93ZHNvdXJjZS5nb29nbGUuY29t +ghgqLmRhdGFjb21wdXRlLmdvb2dsZS5jb22CBiouZy5jb4IOKi5nY3AuZ3Z0Mi5j +b22CESouZ2NwY2RuLmd2dDEuY29tggoqLmdncGh0LmNugg4qLmdrZWNuYXBwcy5j +boIWKi5nb29nbGUtYW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xl +LmNsgg4qLmdvb2dsZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNv +LnVrgg8qLmdvb2dsZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUu +Y29tLmJygg8qLmdvb2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29n +bGUuY29tLnRygg8qLmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2ds +ZS5lc4ILKi5nb29nbGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5n +b29nbGUubmyCCyouZ29vZ2xlLnBsggsqLmdvb2dsZS5wdIISKi5nb29nbGVhZGFw +aXMuY29tgg8qLmdvb2dsZWFwaXMuY26CESouZ29vZ2xlY25hcHBzLmNughQqLmdv +b2dsZWNvbW1lcmNlLmNvbYIRKi5nb29nbGV2aWRlby5jb22CDCouZ3N0YXRpYy5j +boINKi5nc3RhdGljLmNvbYISKi5nc3RhdGljY25hcHBzLmNuggoqLmd2dDEuY29t +ggoqLmd2dDIuY29tghQqLm1ldHJpYy5nc3RhdGljLmNvbYIMKi51cmNoaW4uY29t +ghAqLnVybC5nb29nbGUuY29tghMqLndlYXIuZ2tlY25hcHBzLmNughYqLnlvdXR1 +YmUtbm9jb29raWUuY29tgg0qLnlvdXR1YmUuY29tghYqLnlvdXR1YmVlZHVjYXRp +b24uY29tghEqLnlvdXR1YmVraWRzLmNvbYIHKi55dC5iZYILKi55dGltZy5jb22C +GmFuZHJvaWQuY2xpZW50cy5nb29nbGUuY29tggthbmRyb2lkLmNvbYIbZGV2ZWxv +cGVyLmFuZHJvaWQuZ29vZ2xlLmNughxkZXZlbG9wZXJzLmFuZHJvaWQuZ29vZ2xl +LmNuggRnLmNvgghnZ3BodC5jboIMZ2tlY25hcHBzLmNuggZnb28uZ2yCFGdvb2ds +ZS1hbmFseXRpY3MuY29tggpnb29nbGUuY29tgg9nb29nbGVjbmFwcHMuY26CEmdv +b2dsZWNvbW1lcmNlLmNvbYIYc291cmNlLmFuZHJvaWQuZ29vZ2xlLmNuggp1cmNo +aW4uY29tggp3d3cuZ29vLmdsggh5b3V0dS5iZYILeW91dHViZS5jb22CFHlvdXR1 +YmVlZHVjYXRpb24uY29tgg95b3V0dWJla2lkcy5jb22CBXl0LmJlMCEGA1UdIAQa +MBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwNQYDVR0fBC4wLDAqoCigJoYkaHR0 +cDovL2NybC5wa2kuZ29vZy9ndHNyMS9ndHMxYzMuY3JsMBMGCisGAQQB1nkCBAMB +Af8EAgUAMA0GCSqGSIb3DQEBCwUAA4IBAQAlDQm5zY7JcPxcJ9ulfTGsWV/m6Pro +gLYmAlBUPGKy313aetT4Zjz44ZseVtUOKsXVHh4avPA9O+ta1FgkASlbkgJ05ivb +j/+MMqkrLemdMv9Svvx3CNaAq2jJ2E+8GdrA1RzMkiNthJCiRafaPnXnN6hOHGNr +GtqYfMHsvrRHW8J2IPHW0/MUHmJ/NDu/vNchxke2OEfCPLtseo3hJt8l8HbH+yE8 +DFrt8YVRi1CLomEyuPJDF4og3O3ZsoXuxcPd9UPxULOCxycdolRw8Iv/Xgr082j3 +svXC3HUd3apM2Yy3xJAlk/mUkzVXfdJZ+Zy1huNsUoJ+gM8rmpyGhYyx +-----END CERTIFICATE-----`, + }, + { + name: "rsa leaf", + pem: `-----BEGIN CERTIFICATE----- +MIIJXjCCCEagAwIBAgIRAPYaTUsjP4iRBQAAAACHSSgwDQYJKoZIhvcNAQELBQAw +QjELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczET +MBEGA1UEAxMKR1RTIENBIDFPMTAeFw0yMTAxMjYwODQ2MzRaFw0yMTA0MjAwODQ2 +MzNaMGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH +Ew1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgTExDMRUwEwYDVQQDDAwq +Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC76xx0 +UdZ36/41rZNPfQ/yQ05vsBLUO0d+3uMOhvDlpst+XvIsG6L+vLDgf3RiQRFlei0h +KqqLOtWLDc/y0+OmaaC+8ft1zljBYdvQlAYoZrT79Cc5pAIDq7G1OZ7cC4ahDno/ +n46FHjT/UTUAMYa8cKWBaMPneMIsKvn8nMdZzHkfO2nUd6OEecn90XweMvNmx8De +6h5AlIgG3m66hkD/UCSdxn7yJHBQVdHgkfTqzv3sz2YyBQGNi288F1bn541f6khE +fYti1MvXRtkky7yLCQNUG6PtvuSU4cKaNvRklHigf5i1nVdGEuH61gAElZIklSia +OVK46UyU4DGtbdWNAgMBAAGjggYpMIIGJTAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU8zCvllLd3jhB +k//+Wdjo40Q+T3gwHwYDVR0jBBgwFoAUmNH4bhDrz5vsYJ8YkBug630J/SswaAYI +KwYBBQUHAQEEXDBaMCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC5wa2kuZ29vZy9n +dHMxbzFjb3JlMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2cvZ3NyMi9HVFMx +TzEuY3J0MIIE1wYDVR0RBIIEzjCCBMqCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk +LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYIJKi5iZG4uZGV2ghIqLmNsb3Vk +Lmdvb2dsZS5jb22CGCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIYKi5kYXRhY29t +cHV0ZS5nb29nbGUuY29tghMqLmZsYXNoLmFuZHJvaWQuY29tggYqLmcuY2+CDiou +Z2NwLmd2dDIuY29tghEqLmdjcGNkbi5ndnQxLmNvbYIKKi5nZ3BodC5jboIOKi5n +a2VjbmFwcHMuY26CFiouZ29vZ2xlLWFuYWx5dGljcy5jb22CCyouZ29vZ2xlLmNh +ggsqLmdvb2dsZS5jbIIOKi5nb29nbGUuY28uaW6CDiouZ29vZ2xlLmNvLmpwgg4q +Lmdvb2dsZS5jby51a4IPKi5nb29nbGUuY29tLmFygg8qLmdvb2dsZS5jb20uYXWC +DyouZ29vZ2xlLmNvbS5icoIPKi5nb29nbGUuY29tLmNvgg8qLmdvb2dsZS5jb20u +bXiCDyouZ29vZ2xlLmNvbS50coIPKi5nb29nbGUuY29tLnZuggsqLmdvb2dsZS5k +ZYILKi5nb29nbGUuZXOCCyouZ29vZ2xlLmZyggsqLmdvb2dsZS5odYILKi5nb29n +bGUuaXSCCyouZ29vZ2xlLm5sggsqLmdvb2dsZS5wbIILKi5nb29nbGUucHSCEiou +Z29vZ2xlYWRhcGlzLmNvbYIPKi5nb29nbGVhcGlzLmNughEqLmdvb2dsZWNuYXBw +cy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESouZ29vZ2xldmlkZW8uY29tggwq +LmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CEiouZ3N0YXRpY2NuYXBwcy5jboIK +Ki5ndnQxLmNvbYIKKi5ndnQyLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22CDCou +dXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYITKi53ZWFyLmdrZWNuYXBwcy5j +boIWKi55b3V0dWJlLW5vY29va2llLmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0 +dWJlZWR1Y2F0aW9uLmNvbYIRKi55b3V0dWJla2lkcy5jb22CByoueXQuYmWCCyou +eXRpbWcuY29tghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYILYW5kcm9pZC5j +b22CG2RldmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRy +b2lkLmdvb2dsZS5jboIEZy5jb4IIZ2dwaHQuY26CDGdrZWNuYXBwcy5jboIGZ29v +LmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIKZ29vZ2xlLmNvbYIPZ29vZ2xlY25h +cHBzLmNughJnb29nbGVjb21tZXJjZS5jb22CGHNvdXJjZS5hbmRyb2lkLmdvb2ds +ZS5jboIKdXJjaGluLmNvbYIKd3d3Lmdvby5nbIIIeW91dHUuYmWCC3lvdXR1YmUu +Y29tghR5b3V0dWJlZWR1Y2F0aW9uLmNvbYIPeW91dHViZWtpZHMuY29tggV5dC5i +ZTAhBgNVHSAEGjAYMAgGBmeBDAECAjAMBgorBgEEAdZ5AgUDMDMGA1UdHwQsMCow +KKAmoCSGImh0dHA6Ly9jcmwucGtpLmdvb2cvR1RTMU8xY29yZS5jcmwwEwYKKwYB +BAHWeQIEAwEB/wQCBQAwDQYJKoZIhvcNAQELBQADggEBAHh9/ozYUGRd+W5akWlM +4WvX808TK2oUISnagbxCCFZ2trpg2oi03CJf4o4o3Je5Qzzz10s22oQY6gPHAR0B +QHzrpqAveQw9D5vd8xjgtQ/SAujPzPKNQee5511rS7/EKW9I83ccd5XhhoEyx8A1 +/65RTS+2hKpJKTMkr0yHBPJV7kUW+n/KIef5YaSOA9VYK7hyH0niDpvm9EmoqvWS +U5xAFAe/Xrrq3sxTuDJPQA8alk6h/ql5Klkw6dL53csiPka/MevDqdifWkzuT/6n +YK/ePeJzPD17FA9V+N1rcuF3Wk29AZvCOSasdIkIuE82vGr3dfNrsrn9E9lWIbCr +Qc4= +-----END CERTIFICATE-----`, + }, + } + for _, c := range cases { + b.Run(c.name, func(b *testing.B) { + pemBlock, _ := pem.Decode([]byte(c.pem)) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + b.Fatal(err) + } + } + }) + } +} + +func TestParseCertificateRawEquals(t *testing.T) { + p, _ := pem.Decode([]byte(pemCertificate)) + cert, err := ParseCertificate(p.Bytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + if !bytes.Equal(p.Bytes, cert.Raw) { + t.Fatalf("unexpected Certificate.Raw\ngot: %x\nwant: %x\n", cert.Raw, p.Bytes) + } + fmt.Printf("in: %x\nout: %x\n", p.Bytes, cert.Raw) +} + +// mismatchingSigAlgIDPEM contains a certificate where the Certificate +// signatureAlgorithm and the TBSCertificate signature contain +// mismatching OIDs +const mismatchingSigAlgIDPEM = `-----BEGIN CERTIFICATE----- +MIIBBzCBrqADAgECAgEAMAoGCCqGSM49BAMCMAAwIhgPMDAwMTAxMDEwMDAwMDBa +GA8wMDAxMDEwMTAwMDAwMFowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOqV +EDuVXxwZgIU3+dOwv1SsMu0xuV48hf7xmK8n7sAMYgllB+96DnPqBeboJj4snYnx +0AcE0PDVQ1l4Z3YXsQWjFTATMBEGA1UdEQEB/wQHMAWCA2FzZDAKBggqhkjOPQQD +AwNIADBFAiBi1jz/T2HT5nAfrD7zsgR+68qh7Erc6Q4qlxYBOgKG4QIhAOtjIn+Q +tA+bq+55P3ntxTOVRq0nv1mwnkjwt9cQR9Fn +-----END CERTIFICATE-----` + +// mismatchingSigAlgParamPEM contains a certificate where the Certificate +// signatureAlgorithm and the TBSCertificate signature contain +// mismatching parameters +const mismatchingSigAlgParamPEM = `-----BEGIN CERTIFICATE----- +MIIBCTCBrqADAgECAgEAMAoGCCqGSM49BAMCMAAwIhgPMDAwMTAxMDEwMDAwMDBa +GA8wMDAxMDEwMTAwMDAwMFowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOqV +EDuVXxwZgIU3+dOwv1SsMu0xuV48hf7xmK8n7sAMYgllB+96DnPqBeboJj4snYnx +0AcE0PDVQ1l4Z3YXsQWjFTATMBEGA1UdEQEB/wQHMAWCA2FzZDAMBggqhkjOPQQD +AgUAA0gAMEUCIGLWPP9PYdPmcB+sPvOyBH7ryqHsStzpDiqXFgE6AobhAiEA62Mi +f5C0D5ur7nk/ee3FM5VGrSe/WbCeSPC31xBH0Wc= +-----END CERTIFICATE-----` + +func TestSigAlgMismatch(t *testing.T) { + for _, certPEM := range []string{mismatchingSigAlgIDPEM, mismatchingSigAlgParamPEM} { + b, _ := pem.Decode([]byte(certPEM)) + if b == nil { + t.Fatalf("couldn't decode test certificate") + } + _, err := ParseCertificate(b.Bytes) + if err == nil { + t.Fatalf("expected ParseCertificate to fail") + } + expected := "x509: inner and outer signature algorithm identifiers don't match" + if err.Error() != expected { + t.Errorf("unexpected error from ParseCertificate: got %q, want %q", err.Error(), expected) + } + } +} + +const optionalAuthKeyIDPEM = `-----BEGIN CERTIFICATE----- +MIIFEjCCBHugAwIBAgICAQwwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh +bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu +Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g +QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe +BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MzkxNloX +DTI0MDYyOTE3MzkxNlowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVs +ZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAy +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A +MIIBCAKCAQEAtzLI/ulxpgSFrQwRZN/OTe/IAxiHP6Gr+zymn/DDodrU2G4rU5D7 +JKQ+hPCe6F/s5SdE9SimP3ve4CrwyK9TL57KBQGTHo9mHDmnTfpatnMEJWbrd3/n +WcZKmSUUVOsmx/N/GdUwcI+vsEYq/63rKe3Xn6oEh6PU+YmlNF/bQ5GCNtlmPLG4 +uYL9nDo+EMg77wZlZnqbGRg9/3FRPDAuX749d3OyXQZswyNWmiuFJpIcpwKz5D8N +rwh5grg2Peqc0zWzvGnK9cyd6P1kjReAM25eSl2ZyR6HtJ0awNVuEzUjXt+bXz3v +1vd2wuo+u3gNHEJnawTY+Nbab4vyRKABqwIBA6OCAfMwggHvMB0GA1UdDgQWBBS/ +X7fRzt0fhvRbVazc1xDCDqmI5zCB0gYDVR0jBIHKMIHHoYHBpIG+MIG7MSQwIgYD +VQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNVBAoTDlZhbGlD +ZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBvbGljeSBWYWxp +ZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52YWxpY2VydC5j +b20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbYIBATAPBgNVHRMB +Af8EBTADAQH/MDkGCCsGAQUFBwEBBC0wKzApBggrBgEFBQcwAYYdaHR0cDovL29j +c3Auc3RhcmZpZWxkdGVjaC5jb20wSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2Nl +cnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3Jvb3QuY3Js +MFEGA1UdIARKMEgwRgYEVR0gADA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY2VydGlm +aWNhdGVzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkwDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKVi8afCXSWlcD284ipxs33kDTcdVWptobCr +mADkhWBKIMuh8D1195TaQ39oXCUIuNJ9MxB73HZn8bjhU3zhxoNbKXuNSm8uf0So +GkVrMgfHeMpkksK0hAzc3S1fTbvdiuo43NlmouxBulVtWmQ9twPMHOKRUJ7jCUSV +FxdzPcwl +-----END CERTIFICATE-----` + +func TestAuthKeyIdOptional(t *testing.T) { + b, _ := pem.Decode([]byte(optionalAuthKeyIDPEM)) + if b == nil { + t.Fatalf("couldn't decode test certificate") + } + _, err := ParseCertificate(b.Bytes) + if err != nil { + t.Fatalf("ParseCertificate to failed to parse certificate with optional authority key identifier fields: %s", err) + } +} + +const largeOIDPEM = ` +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + da:ba:53:19:1b:09:4b:82:b2:89:26:7d:c7:6f:a0:02 + Signature Algorithm: sha256WithRSAEncryption + Issuer: O = Acme Co + Validity + Not Before: Dec 21 16:59:27 2021 GMT + Not After : Dec 21 16:59:27 2022 GMT + Subject: O = Acme Co + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bf:17:16:d8:bc:29:9c:16:e5:76:b4:93:15:78: + ad:6e:45:c5:4a:63:46:a1:b2:76:71:65:51:9c:14: + c4:ea:74:13:e4:34:df:2f:2c:65:11:e8:56:52:69: + 11:f9:0e:fc:77:bb:63:a8:7c:1a:c6:a1:7b:6e:6c: + e7:18:25:25:c9:e8:fb:06:7f:a2:a9:98:fe:2a:bc: + 8a:b3:75:b6:b8:7d:b6:c9:6b:29:08:32:22:10:cb: + 8d:d6:60:c8:83:ad:f5:58:91:d6:11:e8:55:56:fb: + 8f:a3:a2:9f:48:cb:79:e4:65:4a:8c:a6:52:64:9f: + 99:38:35:d4:d5:ac:6f:cf:a0:cb:42:8c:07:eb:21: + 17:31:3a:eb:91:7b:62:43:a4:75:5f:ef:a7:2f:94: + f8:69:0b:d4:ec:09:e6:00:c0:8c:dd:07:63:0b:e4: + 77:aa:60:18:3c:a0:e0:ae:0a:ea:0e:52:3b:b4:fa: + 6a:30:1b:50:62:21:73:53:33:01:60:a1:6b:99:58: + 00:f3:77:c6:0f:46:19:ca:c2:5d:cd:f5:e2:52:4d: + 84:94:23:d3:32:2f:ae:5f:da:43:a1:19:95:d2:17: + dd:49:14:b4:d9:48:1c:08:13:93:8e:d5:09:43:21: + b6:ce:52:e8:87:bb:d2:60:0d:c6:4e:bf:c5:93:6a: + c6:bf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Alternative Name: + DNS:longOID.example + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.311.21.8.1492336001 + + Signature Algorithm: sha256WithRSAEncryption + 72:77:8b:de:48:fb:6d:9a:94:b1:be:d4:90:7d:4c:e6:d3:79: + fa:fb:fc:3e:d5:3d:e9:a0:ce:28:2b:2f:94:77:3f:87:f8:9c: + 9f:91:1c:f3:f6:58:91:15:6b:24:b9:ca:ae:9f:ee:ca:c8:31: + db:1a:3d:bb:6b:83:6d:bc:81:8b:a1:79:d5:3e:bb:dd:93:fe: + 35:3e:b7:99:e0:d6:eb:58:0c:fd:42:73:dc:49:da:e2:b7:ae: + 15:ee:e6:cc:aa:ef:91:41:9a:18:46:8d:4a:39:65:a2:85:3c: + 7f:0c:41:f8:0b:9c:e8:1f:35:36:60:8d:8c:e0:8e:18:b1:06: + 57:d0:4e:c4:c3:cd:8f:6f:e7:76:02:52:da:03:43:61:2b:b3: + bf:19:fd:73:0d:6a:0b:b4:b6:cb:a9:6f:70:4e:53:2a:54:07: + b3:74:fd:85:49:57:5b:23:8d:8c:6b:53:2b:09:e8:41:a5:80: + 3f:69:1b:11:d1:6b:13:35:2e:f9:d6:50:15:d9:91:38:42:43: + e9:17:af:67:d9:96:a4:d1:6a:4f:cc:b4:a7:8e:48:1f:00:72: + 69:de:4d:f1:73:a4:47:12:67:e9:f9:07:3e:79:75:90:42:b8: + d4:b5:fd:d1:7e:35:04:f7:00:04:cf:f1:36:be:0f:27:81:1f: + a6:ba:88:6c +-----BEGIN CERTIFICATE----- +MIIDHTCCAgWgAwIBAgIRANq6UxkbCUuCsokmfcdvoAIwDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0yMTEyMjExNjU5MjdaFw0yMjEyMjExNjU5 +MjdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQC/FxbYvCmcFuV2tJMVeK1uRcVKY0ahsnZxZVGcFMTqdBPkNN8vLGUR +6FZSaRH5Dvx3u2OofBrGoXtubOcYJSXJ6PsGf6KpmP4qvIqzdba4fbbJaykIMiIQ +y43WYMiDrfVYkdYR6FVW+4+jop9Iy3nkZUqMplJkn5k4NdTVrG/PoMtCjAfrIRcx +OuuRe2JDpHVf76cvlPhpC9TsCeYAwIzdB2ML5HeqYBg8oOCuCuoOUju0+mowG1Bi +IXNTMwFgoWuZWADzd8YPRhnKwl3N9eJSTYSUI9MyL65f2kOhGZXSF91JFLTZSBwI +E5OO1QlDIbbOUuiHu9JgDcZOv8WTasa/AgMBAAGjbjBsMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGC +D2xvbmdPSUQuZXhhbXBsZTAbBgNVHSAEFDASMBAGDisGAQQBgjcVCIXHzPsBMA0G +CSqGSIb3DQEBCwUAA4IBAQByd4veSPttmpSxvtSQfUzm03n6+/w+1T3poM4oKy+U +dz+H+JyfkRzz9liRFWskucqun+7KyDHbGj27a4NtvIGLoXnVPrvdk/41PreZ4Nbr +WAz9QnPcSdrit64V7ubMqu+RQZoYRo1KOWWihTx/DEH4C5zoHzU2YI2M4I4YsQZX +0E7Ew82Pb+d2AlLaA0NhK7O/Gf1zDWoLtLbLqW9wTlMqVAezdP2FSVdbI42Ma1Mr +CehBpYA/aRsR0WsTNS751lAV2ZE4QkPpF69n2Zak0WpPzLSnjkgfAHJp3k3xc6RH +Emfp+Qc+eXWQQrjUtf3RfjUE9wAEz/E2vg8ngR+muohs +-----END CERTIFICATE-----` + +func TestLargeOID(t *testing.T) { + // See Issue 49678. + b, _ := pem.Decode([]byte(largeOIDPEM)) + if b == nil { + t.Fatalf("couldn't decode test certificate") + } + _, err := ParseCertificate(b.Bytes) + if err != nil { + t.Fatalf("ParseCertificate to failed to parse certificate with large OID: %s", err) + } +} + +const uniqueIDPEM = `-----BEGIN CERTIFICATE----- +MIIFsDCCBJigAwIBAgIIrOyC1ydafZMwDQYJKoZIhvcNAQEFBQAwgY4xgYswgYgG +A1UEAx6BgABNAGkAYwByAG8AcwBvAGYAdAAgAEYAbwByAGUAZgByAG8AbgB0ACAA +VABNAEcAIABIAFQAVABQAFMAIABJAG4AcwBwAGUAYwB0AGkAbwBuACAAQwBlAHIA +dABpAGYAaQBjAGEAdABpAG8AbgAgAEEAdQB0AGgAbwByAGkAdAB5MB4XDTE0MDEx +ODAwNDEwMFoXDTE1MTExNTA5Mzc1NlowgZYxCzAJBgNVBAYTAklEMRAwDgYDVQQI +EwdqYWthcnRhMRIwEAYDVQQHEwlJbmRvbmVzaWExHDAaBgNVBAoTE3N0aG9ub3Jl +aG90ZWxyZXNvcnQxHDAaBgNVBAsTE3N0aG9ub3JlaG90ZWxyZXNvcnQxJTAjBgNV +BAMTHG1haWwuc3Rob25vcmVob3RlbHJlc29ydC5jb20wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCvuu0qpI+Ko2X84Twkf84cRD/rgp6vpgc5Ebejx/D4 +PEVON5edZkazrMGocK/oQqIlRxx/lefponN/chlGcllcVVPWTuFjs8k+Aat6T1qp +4iXxZekAqX+U4XZMIGJD3PckPL6G2RQSlF7/LhGCsRNRdKpMWSTbou2Ma39g52Kf +gsl3SK/GwLiWpxpcSkNQD1hugguEIsQYLxbeNwpcheXZtxbBGguPzQ7rH8c5vuKU +BkMOzaiNKLzHbBdFSrua8KWwCJg76Vdq/q36O9GlW6YgG3i+A4pCJjXWerI1lWwX +Ktk5V+SvUHGey1bkDuZKJ6myMk2pGrrPWCT7jP7WskChAgMBAAGBCQBCr1dgEleo +cKOCAfswggH3MIHDBgNVHREEgbswgbiCHG1haWwuc3Rob25vcmVob3RlbHJlc29y +dC5jb22CIGFzaGNoc3ZyLnN0aG9ub3JlaG90ZWxyZXNvcnQuY29tgiRBdXRvRGlz +Y292ZXIuc3Rob25vcmVob3RlbHJlc29ydC5jb22CHEF1dG9EaXNjb3Zlci5ob3Rl +bHJlc29ydC5jb22CCEFTSENIU1ZSghdzdGhvbm9yZWhvdGVscmVzb3J0LmNvbYIP +aG90ZWxyZXNvcnQuY29tMCEGCSsGAQQBgjcUAgQUHhIAVwBlAGIAUwBlAHIAdgBl +AHIwHQYDVR0OBBYEFMAC3UR4FwAdGekbhMgnd6lMejtbMAsGA1UdDwQEAwIFoDAT +BgNVHSUEDDAKBggrBgEFBQcDATAJBgNVHRMEAjAAMIG/BgNVHQEEgbcwgbSAFGfF +6xihk+gJJ5TfwvtWe1UFnHLQoYGRMIGOMYGLMIGIBgNVBAMegYAATQBpAGMAcgBv +AHMAbwBmAHQAIABGAG8AcgBlAGYAcgBvAG4AdAAgAFQATQBHACAASABUAFQAUABT +ACAASQBuAHMAcABlAGMAdABpAG8AbgAgAEMAZQByAHQAaQBmAGkAYwBhAHQAaQBv +AG4AIABBAHUAdABoAG8AcgBpAHQAeYIIcKhXEmBXr0IwDQYJKoZIhvcNAQEFBQAD +ggEBABlSxyCMr3+ANr+WmPSjyN5YCJBgnS0IFCwJAzIYP87bcTye/U8eQ2+E6PqG +Q7Huj7nfHEw9qnGo+HNyPp1ad3KORzXDb54c6xEoi+DeuPzYHPbn4c3hlH49I0aQ +eWW2w4RslSWpLvO6Y7Lboyz2/Thk/s2kd4RHxkkWpH2ltPqJuYYg3X6oM5+gIFHJ +WGnh+ojZ5clKvS5yXh3Wkj78M6sb32KfcBk0Hx6NkCYPt60ODYmWtvqwtw6r73u5 +TnTYWRNvo2svX69TriL+CkHY9O1Hkwf2It5zHl3gNiKTJVaak8AuEz/CKWZneovt +yYLwhUhg3PX5Co1VKYE+9TxloiE= +-----END CERTIFICATE-----` + +func TestParseUniqueID(t *testing.T) { + b, _ := pem.Decode([]byte(uniqueIDPEM)) + if b == nil { + t.Fatalf("couldn't decode test certificate") + } + cert, err := ParseCertificate(b.Bytes) + if err != nil { + t.Fatalf("ParseCertificate to failed to parse certificate with unique identifier id: %s", err) + } + if len(cert.Extensions) != 7 { + t.Fatalf("unexpected number of extensions (probably because the extension section was not parsed): got %d, want 7", len(cert.Extensions)) + } +} diff --git a/src/crypto/x509/x509_test_import.go b/src/crypto/x509/x509_test_import.go new file mode 100644 index 0000000..ef3ee80 --- /dev/null +++ b/src/crypto/x509/x509_test_import.go @@ -0,0 +1,57 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +// This file is run by the x509 tests to ensure that a program with minimal +// imports can sign certificates without errors resulting from missing hash +// functions. +package main + +import ( + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "strings" + "time" +) + +func main() { + block, _ := pem.Decode([]byte(pemPrivateKey)) + rsaPriv, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + panic("Failed to parse private key: " + err.Error()) + } + + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "test", + Organization: []string{"Σ Acme Co"}, + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + KeyUsage: x509.KeyUsageCertSign, + } + + if _, err = x509.CreateCertificate(rand.Reader, &template, &template, &rsaPriv.PublicKey, rsaPriv); err != nil { + panic("failed to create certificate with basic imports: " + err.Error()) + } +} + +var pemPrivateKey = testingKey(`-----BEGIN RSA TESTING KEY----- +MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 +fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu +/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu +RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ +EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A +IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS +tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V +-----END RSA TESTING KEY----- +`) + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } -- cgit v1.2.3