summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Sloan <varomodt@google.com>2018-02-06 09:26:18 +0000
committerandroid-build-merger <android-build-merger@google.com>2018-02-06 09:26:18 +0000
commit1ec9ae796d7306c71bc324e6680b510d9aca9d73 (patch)
tree65345a0acda3104c65b39662f207fbc9239e9ad5
parente682e96f615e52dbd22430cf5c0b684bea524db5 (diff)
parentedfa0167be4229a1a4f9d5f5348b7834f682a6c4 (diff)
downloadboringssl-1ec9ae796d7306c71bc324e6680b510d9aca9d73.tar.gz
external/boringssl: Sync to 45210dd4e21ace9d28cb76b3f83303fcdd2efcce. am: 8542c08a00
am: edfa0167be Change-Id: I99b8ef205e13497b5817587aca86f446d4665b47
-rw-r--r--BORINGSSL_REVISION2
-rw-r--r--err_data.c374
-rw-r--r--eureka.mk3
-rw-r--r--sources.bp3
-rw-r--r--sources.mk2
-rw-r--r--src/crypto/curve25519/CMakeLists.txt9
-rw-r--r--src/crypto/curve25519/asm/x25519-asm-x86_64.S1894
-rw-r--r--src/crypto/curve25519/ed25519_test.cc22
-rw-r--r--src/crypto/curve25519/x25519-x86_64.c247
-rw-r--r--src/crypto/dsa/dsa.c10
-rw-r--r--src/crypto/err/ssl.errordata1
-rw-r--r--src/crypto/fipsmodule/bn/add.c8
-rw-r--r--src/crypto/fipsmodule/bn/bn.c72
-rw-r--r--src/crypto/fipsmodule/bn/bn_test.cc248
-rw-r--r--src/crypto/fipsmodule/bn/bytes.c72
-rw-r--r--src/crypto/fipsmodule/bn/cmp.c102
-rw-r--r--src/crypto/fipsmodule/bn/exponentiation.c52
-rw-r--r--src/crypto/fipsmodule/bn/internal.h40
-rw-r--r--src/crypto/fipsmodule/bn/montgomery.c163
-rw-r--r--src/crypto/fipsmodule/bn/prime.c5
-rw-r--r--src/crypto/fipsmodule/ec/ec.c17
-rw-r--r--src/crypto/fipsmodule/ec/ec_montgomery.c12
-rw-r--r--src/crypto/fipsmodule/ec/ec_test.cc64
-rw-r--r--src/crypto/fipsmodule/ec/oct.c70
-rw-r--r--src/crypto/fipsmodule/ec/p256-x86_64.c8
-rw-r--r--src/crypto/fipsmodule/ec/p256-x86_64_test.cc14
-rw-r--r--src/crypto/fipsmodule/rsa/rsa_impl.c69
-rw-r--r--src/fipstools/cavp_tlskdf_test.cc2
-rw-r--r--src/fipstools/run_cavp.go66
-rw-r--r--src/include/openssl/bn.h33
-rw-r--r--src/include/openssl/ssl.h87
-rw-r--r--src/include/openssl/tls1.h7
-rw-r--r--src/ssl/CMakeLists.txt1
-rw-r--r--src/ssl/handoff.cc285
-rw-r--r--src/ssl/handshake.cc5
-rw-r--r--src/ssl/handshake_client.cc3
-rw-r--r--src/ssl/handshake_server.cc4
-rw-r--r--src/ssl/internal.h47
-rw-r--r--src/ssl/s3_pkt.cc18
-rw-r--r--src/ssl/ssl_lib.cc26
-rw-r--r--src/ssl/ssl_privkey.cc6
-rw-r--r--src/ssl/ssl_test.cc140
-rw-r--r--src/ssl/ssl_versions.cc34
-rw-r--r--src/ssl/t1_enc.cc8
-rw-r--r--src/ssl/t1_lib.cc103
-rw-r--r--src/ssl/test/bssl_shim.cc147
-rw-r--r--src/ssl/test/runner/common.go33
-rw-r--r--src/ssl/test/runner/conn.go36
-rw-r--r--src/ssl/test/runner/fuzzer_mode.json6
-rw-r--r--src/ssl/test/runner/handshake_client.go105
-rw-r--r--src/ssl/test/runner/handshake_messages.go165
-rw-r--r--src/ssl/test/runner/handshake_server.go112
-rw-r--r--src/ssl/test/runner/prf.go67
-rw-r--r--src/ssl/test/runner/runner.go498
-rw-r--r--src/ssl/test/test_config.cc4
-rw-r--r--src/ssl/test/test_config.h3
-rw-r--r--src/ssl/tls13_client.cc258
-rw-r--r--src/ssl/tls13_enc.cc195
-rw-r--r--src/ssl/tls13_server.cc191
-rw-r--r--src/ssl/tls_record.cc9
-rw-r--r--src/third_party/fiat/curve25519.c65
-rw-r--r--src/third_party/fiat/internal.h9
-rw-r--r--src/tool/client.cc8
-rw-r--r--src/tool/server.cc2
-rw-r--r--src/util/fipstools/delocate.go2
-rw-r--r--src/util/fipstools/delocate.peg2
-rw-r--r--src/util/fipstools/delocate.peg.go2733
-rw-r--r--src/util/fipstools/testdata/x86_64-Basic/in.s1
-rw-r--r--src/util/fipstools/testdata/x86_64-Basic/out.s1
-rw-r--r--src/util/generate_build_files.py6
70 files changed, 3886 insertions, 5230 deletions
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index c9520175..f3ee8ac3 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-a62dbf88d8a3c04446db833a1eb80a620cb1514d
+45210dd4e21ace9d28cb76b3f83303fcdd2efcce
diff --git a/err_data.c b/err_data.c
index dbb34a3a..4dda17bd 100644
--- a/err_data.c
+++ b/err_data.c
@@ -185,43 +185,43 @@ const uint32_t kOpenSSLReasonValues[] = {
0x28340c5e,
0x283480ac,
0x283500ea,
- 0x2c322cda,
+ 0x2c322cf7,
0x2c3292a5,
- 0x2c332ce8,
- 0x2c33acfa,
- 0x2c342d0e,
- 0x2c34ad20,
- 0x2c352d3b,
- 0x2c35ad4d,
- 0x2c362d60,
+ 0x2c332d05,
+ 0x2c33ad17,
+ 0x2c342d2b,
+ 0x2c34ad3d,
+ 0x2c352d58,
+ 0x2c35ad6a,
+ 0x2c362d7d,
0x2c36832d,
- 0x2c372d6d,
- 0x2c37ad7f,
- 0x2c382da4,
- 0x2c38adbb,
- 0x2c392dc9,
- 0x2c39add9,
- 0x2c3a2deb,
- 0x2c3aadff,
- 0x2c3b2e10,
- 0x2c3bae2f,
+ 0x2c372d8a,
+ 0x2c37ad9c,
+ 0x2c382dc1,
+ 0x2c38add8,
+ 0x2c392de6,
+ 0x2c39adf6,
+ 0x2c3a2e08,
+ 0x2c3aae1c,
+ 0x2c3b2e2d,
+ 0x2c3bae4c,
0x2c3c12b7,
0x2c3c92cd,
- 0x2c3d2e43,
+ 0x2c3d2e60,
0x2c3d92e6,
- 0x2c3e2e60,
- 0x2c3eae6e,
- 0x2c3f2e86,
- 0x2c3fae9e,
- 0x2c402eab,
+ 0x2c3e2e7d,
+ 0x2c3eae8b,
+ 0x2c3f2ea3,
+ 0x2c3faebb,
+ 0x2c402ec8,
0x2c4091b8,
- 0x2c412ebc,
- 0x2c41aecf,
+ 0x2c412ed9,
+ 0x2c41aeec,
0x2c42117e,
- 0x2c42aee0,
+ 0x2c42aefd,
0x2c430720,
- 0x2c43ae21,
- 0x2c442d92,
+ 0x2c43ae3e,
+ 0x2c442daf,
0x30320000,
0x30328015,
0x3033001f,
@@ -448,65 +448,65 @@ const uint32_t kOpenSSLReasonValues[] = {
0x405fa21e,
0x4060222c,
0x4060a24e,
- 0x40612292,
- 0x4061a2ca,
- 0x406222e1,
- 0x4062a2f2,
- 0x40632303,
- 0x4063a318,
- 0x4064232f,
- 0x4064a35b,
- 0x40652376,
- 0x4065a38d,
- 0x406623a5,
- 0x4066a3cf,
- 0x406723fa,
- 0x4067a41b,
- 0x40682463,
- 0x4068a484,
- 0x406924b6,
- 0x4069a4e4,
- 0x406a2505,
- 0x406aa525,
- 0x406b26ad,
- 0x406ba6d0,
- 0x406c26e6,
- 0x406ca961,
- 0x406d2990,
- 0x406da9b8,
- 0x406e29e6,
- 0x406eaa33,
- 0x406f2a52,
- 0x406faa8a,
- 0x40702a9d,
- 0x4070aaba,
+ 0x406122af,
+ 0x4061a2e7,
+ 0x406222fe,
+ 0x4062a30f,
+ 0x40632320,
+ 0x4063a335,
+ 0x4064234c,
+ 0x4064a378,
+ 0x40652393,
+ 0x4065a3aa,
+ 0x406623c2,
+ 0x4066a3ec,
+ 0x40672417,
+ 0x4067a438,
+ 0x40682480,
+ 0x4068a4a1,
+ 0x406924d3,
+ 0x4069a501,
+ 0x406a2522,
+ 0x406aa542,
+ 0x406b26ca,
+ 0x406ba6ed,
+ 0x406c2703,
+ 0x406ca97e,
+ 0x406d29ad,
+ 0x406da9d5,
+ 0x406e2a03,
+ 0x406eaa50,
+ 0x406f2a6f,
+ 0x406faaa7,
+ 0x40702aba,
+ 0x4070aad7,
0x40710800,
- 0x4071aacc,
- 0x40722adf,
- 0x4072aaf8,
- 0x40732b10,
+ 0x4071aae9,
+ 0x40722afc,
+ 0x4072ab15,
+ 0x40732b2d,
0x407394a4,
- 0x40742b24,
- 0x4074ab3e,
- 0x40752b4f,
- 0x4075ab63,
- 0x40762b71,
+ 0x40742b41,
+ 0x4074ab5b,
+ 0x40752b6c,
+ 0x4075ab80,
+ 0x40762b8e,
0x4076927b,
- 0x40772b96,
- 0x4077abb8,
- 0x40782bd3,
- 0x4078ac0c,
- 0x40792c23,
- 0x4079ac39,
- 0x407a2c45,
- 0x407aac58,
- 0x407b2c6d,
- 0x407bac7f,
- 0x407c2cb0,
- 0x407cacb9,
- 0x407d249f,
+ 0x40772bb3,
+ 0x4077abd5,
+ 0x40782bf0,
+ 0x4078ac29,
+ 0x40792c40,
+ 0x4079ac56,
+ 0x407a2c62,
+ 0x407aac75,
+ 0x407b2c8a,
+ 0x407bac9c,
+ 0x407c2ccd,
+ 0x407cacd6,
+ 0x407d24bc,
0x407d9eca,
- 0x407e2be8,
+ 0x407e2c05,
0x407ea0a3,
0x407f1c93,
0x407f9a53,
@@ -514,66 +514,67 @@ const uint32_t kOpenSSLReasonValues[] = {
0x40809cbb,
0x40811f46,
0x40819e7b,
- 0x408229d1,
+ 0x408229ee,
0x40829a39,
0x4083207e,
- 0x4083a340,
+ 0x4083a35d,
0x40841ccf,
0x4084a0db,
0x40852160,
0x4085a276,
0x408621d2,
0x40869ee4,
- 0x40872a17,
- 0x4087a2a7,
+ 0x40872a34,
+ 0x4087a2c4,
0x40881a9a,
- 0x4088a42e,
+ 0x4088a44b,
0x40891ae9,
0x40899a76,
- 0x408a2706,
+ 0x408a2723,
0x408a9884,
- 0x408b2c94,
- 0x408baa67,
+ 0x408b2cb1,
+ 0x408baa84,
0x408c2170,
0x408c98a0,
0x408d1d12,
0x408d9ce3,
0x408e1e2c,
0x408e9fe6,
- 0x408f2442,
- 0x41f425d8,
- 0x41f9266a,
- 0x41fe255d,
- 0x41fea752,
- 0x41ff2843,
- 0x420325f1,
- 0x42082613,
- 0x4208a64f,
- 0x42092541,
- 0x4209a689,
- 0x420a2598,
- 0x420aa578,
- 0x420b25b8,
- 0x420ba631,
- 0x420c285f,
- 0x420ca71f,
- 0x420d2739,
- 0x420da770,
- 0x4212278a,
- 0x42172826,
- 0x4217a7cc,
- 0x421c27ee,
- 0x421f27a9,
- 0x42212876,
- 0x42262809,
- 0x422b2945,
- 0x422ba8f3,
- 0x422c292d,
- 0x422ca8b2,
- 0x422d2891,
- 0x422da912,
- 0x422e28d8,
- 0x422ea9fe,
+ 0x408f245f,
+ 0x408fa292,
+ 0x41f425f5,
+ 0x41f92687,
+ 0x41fe257a,
+ 0x41fea76f,
+ 0x41ff2860,
+ 0x4203260e,
+ 0x42082630,
+ 0x4208a66c,
+ 0x4209255e,
+ 0x4209a6a6,
+ 0x420a25b5,
+ 0x420aa595,
+ 0x420b25d5,
+ 0x420ba64e,
+ 0x420c287c,
+ 0x420ca73c,
+ 0x420d2756,
+ 0x420da78d,
+ 0x421227a7,
+ 0x42172843,
+ 0x4217a7e9,
+ 0x421c280b,
+ 0x421f27c6,
+ 0x42212893,
+ 0x42262826,
+ 0x422b2962,
+ 0x422ba910,
+ 0x422c294a,
+ 0x422ca8cf,
+ 0x422d28ae,
+ 0x422da92f,
+ 0x422e28f5,
+ 0x422eaa1b,
0x4432072b,
0x4432873a,
0x44330746,
@@ -626,69 +627,69 @@ const uint32_t kOpenSSLReasonValues[] = {
0x4c4014c9,
0x4c4092f7,
0x4c4114ed,
- 0x50322ef2,
- 0x5032af01,
- 0x50332f0c,
- 0x5033af1c,
- 0x50342f35,
- 0x5034af4f,
- 0x50352f5d,
- 0x5035af73,
- 0x50362f85,
- 0x5036af9b,
- 0x50372fb4,
- 0x5037afc7,
- 0x50382fdf,
- 0x5038aff0,
- 0x50393005,
- 0x5039b019,
- 0x503a3039,
- 0x503ab04f,
- 0x503b3067,
- 0x503bb079,
- 0x503c3095,
- 0x503cb0ac,
- 0x503d30c5,
- 0x503db0db,
- 0x503e30e8,
- 0x503eb0fe,
- 0x503f3110,
+ 0x50322f0f,
+ 0x5032af1e,
+ 0x50332f29,
+ 0x5033af39,
+ 0x50342f52,
+ 0x5034af6c,
+ 0x50352f7a,
+ 0x5035af90,
+ 0x50362fa2,
+ 0x5036afb8,
+ 0x50372fd1,
+ 0x5037afe4,
+ 0x50382ffc,
+ 0x5038b00d,
+ 0x50393022,
+ 0x5039b036,
+ 0x503a3056,
+ 0x503ab06c,
+ 0x503b3084,
+ 0x503bb096,
+ 0x503c30b2,
+ 0x503cb0c9,
+ 0x503d30e2,
+ 0x503db0f8,
+ 0x503e3105,
+ 0x503eb11b,
+ 0x503f312d,
0x503f8382,
- 0x50403123,
- 0x5040b133,
- 0x5041314d,
- 0x5041b15c,
- 0x50423176,
- 0x5042b193,
- 0x504331a3,
- 0x5043b1b3,
- 0x504431c2,
+ 0x50403140,
+ 0x5040b150,
+ 0x5041316a,
+ 0x5041b179,
+ 0x50423193,
+ 0x5042b1b0,
+ 0x504331c0,
+ 0x5043b1d0,
+ 0x504431df,
0x5044843f,
- 0x504531d6,
- 0x5045b1f4,
- 0x50463207,
- 0x5046b21d,
- 0x5047322f,
- 0x5047b244,
- 0x5048326a,
- 0x5048b278,
- 0x5049328b,
- 0x5049b2a0,
- 0x504a32b6,
- 0x504ab2c6,
- 0x504b32e6,
- 0x504bb2f9,
- 0x504c331c,
- 0x504cb34a,
- 0x504d335c,
- 0x504db379,
- 0x504e3394,
- 0x504eb3b0,
- 0x504f33c2,
- 0x504fb3d9,
- 0x505033e8,
+ 0x504531f3,
+ 0x5045b211,
+ 0x50463224,
+ 0x5046b23a,
+ 0x5047324c,
+ 0x5047b261,
+ 0x50483287,
+ 0x5048b295,
+ 0x504932a8,
+ 0x5049b2bd,
+ 0x504a32d3,
+ 0x504ab2e3,
+ 0x504b3303,
+ 0x504bb316,
+ 0x504c3339,
+ 0x504cb367,
+ 0x504d3379,
+ 0x504db396,
+ 0x504e33b1,
+ 0x504eb3cd,
+ 0x504f33df,
+ 0x504fb3f6,
+ 0x50503405,
0x505086ef,
- 0x505133fb,
+ 0x50513418,
0x58320f3a,
0x68320efc,
0x68328c6a,
@@ -1166,6 +1167,7 @@ const char kOpenSSLReasonStringData[] =
"PEER_DID_NOT_RETURN_A_CERTIFICATE\0"
"PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0"
"PRE_SHARED_KEY_MUST_BE_LAST\0"
+ "PRIVATE_KEY_OPERATION_FAILED\0"
"PROTOCOL_IS_SHUTDOWN\0"
"PSK_IDENTITY_BINDER_COUNT_MISMATCH\0"
"PSK_IDENTITY_NOT_FOUND\0"
diff --git a/eureka.mk b/eureka.mk
index c2c8289e..6d0558e6 100644
--- a/eureka.mk
+++ b/eureka.mk
@@ -85,7 +85,6 @@ crypto_sources := \
src/crypto/cpu-ppc64le.c\
src/crypto/crypto.c\
src/crypto/curve25519/spake25519.c\
- src/crypto/curve25519/x25519-x86_64.c\
src/crypto/dh/check.c\
src/crypto/dh/dh.c\
src/crypto/dh/dh_asn1.c\
@@ -244,6 +243,7 @@ ssl_sources := \
src/ssl/d1_srtp.cc\
src/ssl/dtls_method.cc\
src/ssl/dtls_record.cc\
+ src/ssl/handoff.cc\
src/ssl/handshake.cc\
src/ssl/handshake_client.cc\
src/ssl/handshake_server.cc\
@@ -350,5 +350,4 @@ linux_x86_64_sources := \
linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S\
linux-x86_64/crypto/fipsmodule/x86_64-mont.S\
linux-x86_64/crypto/fipsmodule/x86_64-mont5.S\
- src/crypto/curve25519/asm/x25519-asm-x86_64.S\
diff --git a/sources.bp b/sources.bp
index 8cf85c05..377c715a 100644
--- a/sources.bp
+++ b/sources.bp
@@ -87,7 +87,6 @@ cc_defaults {
"src/crypto/cpu-ppc64le.c",
"src/crypto/crypto.c",
"src/crypto/curve25519/spake25519.c",
- "src/crypto/curve25519/x25519-x86_64.c",
"src/crypto/dh/check.c",
"src/crypto/dh/dh.c",
"src/crypto/dh/dh_asn1.c",
@@ -301,7 +300,6 @@ cc_defaults {
"linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S",
"linux-x86_64/crypto/fipsmodule/x86_64-mont.S",
"linux-x86_64/crypto/fipsmodule/x86_64-mont5.S",
- "src/crypto/curve25519/asm/x25519-asm-x86_64.S",
],
},
},
@@ -318,6 +316,7 @@ cc_defaults {
"src/ssl/d1_srtp.cc",
"src/ssl/dtls_method.cc",
"src/ssl/dtls_record.cc",
+ "src/ssl/handoff.cc",
"src/ssl/handshake.cc",
"src/ssl/handshake_client.cc",
"src/ssl/handshake_server.cc",
diff --git a/sources.mk b/sources.mk
index f4c6fbc2..dd17d8bb 100644
--- a/sources.mk
+++ b/sources.mk
@@ -85,7 +85,6 @@ crypto_sources := \
src/crypto/cpu-ppc64le.c\
src/crypto/crypto.c\
src/crypto/curve25519/spake25519.c\
- src/crypto/curve25519/x25519-x86_64.c\
src/crypto/dh/check.c\
src/crypto/dh/dh.c\
src/crypto/dh/dh_asn1.c\
@@ -295,5 +294,4 @@ linux_x86_64_sources := \
linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S\
linux-x86_64/crypto/fipsmodule/x86_64-mont.S\
linux-x86_64/crypto/fipsmodule/x86_64-mont5.S\
- src/crypto/curve25519/asm/x25519-asm-x86_64.S\
diff --git a/src/crypto/curve25519/CMakeLists.txt b/src/crypto/curve25519/CMakeLists.txt
index 6f51d54f..4894fa8e 100644
--- a/src/crypto/curve25519/CMakeLists.txt
+++ b/src/crypto/curve25519/CMakeLists.txt
@@ -8,21 +8,12 @@ if (${ARCH} STREQUAL "arm")
)
endif()
-if (${ARCH} STREQUAL "x86_64")
- set(
- CURVE25519_ARCH_SOURCES
-
- asm/x25519-asm-x86_64.S
- )
-endif()
-
add_library(
curve25519
OBJECT
spake25519.c
- x25519-x86_64.c
${CURVE25519_ARCH_SOURCES}
)
diff --git a/src/crypto/curve25519/asm/x25519-asm-x86_64.S b/src/crypto/curve25519/asm/x25519-asm-x86_64.S
deleted file mode 100644
index 6cff53ee..00000000
--- a/src/crypto/curve25519/asm/x25519-asm-x86_64.S
+++ /dev/null
@@ -1,1894 +0,0 @@
-/* Copyright (c) 2015, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-/* This file is adapted from crypto_scalarmult/curve25519/amd64-51/ in
- * SUPERCOP 20141124 (http://bench.cr.yp.to/supercop.html). That code is public
- * domain licensed but the standard ISC license is included above to keep
- * licensing simple. */
-
-#if !defined(OPENSSL_NO_ASM)
-#if defined(__x86_64__)
-
-.data
-.p2align 4
-
-#if defined(__APPLE__)
-/* OS X's C ABI prefixes functions with underscore. */
-#define C_ABI(x) _ ## x
-#define HIDDEN .private_extern
-#else
-#define C_ABI(x) x
-#define HIDDEN .hidden
-#endif
-
-x25519_x86_64_REDMASK51: .quad 0x0007FFFFFFFFFFFF
-x25519_x86_64_121666_213: .quad 996687872
-x25519_x86_64_2P0: .quad 0xFFFFFFFFFFFDA
-x25519_x86_64_2P1234: .quad 0xFFFFFFFFFFFFE
-x25519_x86_64_4P0: .quad 0x1FFFFFFFFFFFB4
-x25519_x86_64_4P1234: .quad 0x1FFFFFFFFFFFFC
-x25519_x86_64_MU0: .quad 0xED9CE5A30A2C131B
-x25519_x86_64_MU1: .quad 0x2106215D086329A7
-x25519_x86_64_MU2: .quad 0xFFFFFFFFFFFFFFEB
-x25519_x86_64_MU3: .quad 0xFFFFFFFFFFFFFFFF
-x25519_x86_64_MU4: .quad 0x000000000000000F
-x25519_x86_64_ORDER0: .quad 0x5812631A5CF5D3ED
-x25519_x86_64_ORDER1: .quad 0x14DEF9DEA2F79CD6
-x25519_x86_64_ORDER2: .quad 0x0000000000000000
-x25519_x86_64_ORDER3: .quad 0x1000000000000000
-x25519_x86_64_EC2D0: .quad 1859910466990425
-x25519_x86_64_EC2D1: .quad 932731440258426
-x25519_x86_64_EC2D2: .quad 1072319116312658
-x25519_x86_64_EC2D3: .quad 1815898335770999
-x25519_x86_64_EC2D4: .quad 633789495995903
-x25519_x86_64__38: .quad 38
-
-.text
-.p2align 5
-
-.globl C_ABI(x25519_x86_64_freeze)
-HIDDEN C_ABI(x25519_x86_64_freeze)
-C_ABI(x25519_x86_64_freeze):
-.cfi_startproc
-/* This is a leaf function and uses the redzone for saving registers. */
-movq %r12,-8(%rsp)
-.cfi_rel_offset r12, -8
-movq 0(%rdi),%rsi
-movq 8(%rdi),%rdx
-movq 16(%rdi),%rcx
-movq 24(%rdi),%r8
-movq 32(%rdi),%r9
-movq x25519_x86_64_REDMASK51(%rip),%rax
-mov %rax,%r10
-sub $18,%r10
-mov $3,%r11
-._reduceloop:
-mov %rsi,%r12
-shr $51,%r12
-and %rax,%rsi
-add %r12,%rdx
-mov %rdx,%r12
-shr $51,%r12
-and %rax,%rdx
-add %r12,%rcx
-mov %rcx,%r12
-shr $51,%r12
-and %rax,%rcx
-add %r12,%r8
-mov %r8,%r12
-shr $51,%r12
-and %rax,%r8
-add %r12,%r9
-mov %r9,%r12
-shr $51,%r12
-and %rax,%r9
-imulq $19,%r12,%r12
-add %r12,%rsi
-sub $1,%r11
-ja ._reduceloop
-mov $1,%r12
-cmp %r10,%rsi
-cmovl %r11,%r12
-cmp %rax,%rdx
-cmovne %r11,%r12
-cmp %rax,%rcx
-cmovne %r11,%r12
-cmp %rax,%r8
-cmovne %r11,%r12
-cmp %rax,%r9
-cmovne %r11,%r12
-neg %r12
-and %r12,%rax
-and %r12,%r10
-sub %r10,%rsi
-sub %rax,%rdx
-sub %rax,%rcx
-sub %rax,%r8
-sub %rax,%r9
-movq %rsi,0(%rdi)
-movq %rdx,8(%rdi)
-movq %rcx,16(%rdi)
-movq %r8,24(%rdi)
-movq %r9,32(%rdi)
-movq -8(%rsp),%r12
-ret
-.cfi_endproc
-
-.p2align 5
-.globl C_ABI(x25519_x86_64_mul)
-HIDDEN C_ABI(x25519_x86_64_mul)
-C_ABI(x25519_x86_64_mul):
-.cfi_startproc
-/* This is a leaf function and uses the redzone for saving registers. */
-movq %r12,-8(%rsp)
-.cfi_rel_offset r12, -8
-movq %r13,-16(%rsp)
-.cfi_rel_offset r13, -16
-movq %r14,-24(%rsp)
-.cfi_rel_offset r14, -24
-movq %r15,-32(%rsp)
-.cfi_rel_offset r15, -32
-movq %rbx,-40(%rsp)
-.cfi_rel_offset rbx, -40
-movq %rbp,-48(%rsp)
-.cfi_rel_offset rbp, -48
-mov %rdx,%rcx
-movq 24(%rsi),%rdx
-imulq $19,%rdx,%rax
-movq %rax,-64(%rsp)
-mulq 16(%rcx)
-mov %rax,%r8
-mov %rdx,%r9
-movq 32(%rsi),%rdx
-imulq $19,%rdx,%rax
-movq %rax,-72(%rsp)
-mulq 8(%rcx)
-add %rax,%r8
-adc %rdx,%r9
-movq 0(%rsi),%rax
-mulq 0(%rcx)
-add %rax,%r8
-adc %rdx,%r9
-movq 0(%rsi),%rax
-mulq 8(%rcx)
-mov %rax,%r10
-mov %rdx,%r11
-movq 0(%rsi),%rax
-mulq 16(%rcx)
-mov %rax,%r12
-mov %rdx,%r13
-movq 0(%rsi),%rax
-mulq 24(%rcx)
-mov %rax,%r14
-mov %rdx,%r15
-movq 0(%rsi),%rax
-mulq 32(%rcx)
-mov %rax,%rbx
-mov %rdx,%rbp
-movq 8(%rsi),%rax
-mulq 0(%rcx)
-add %rax,%r10
-adc %rdx,%r11
-movq 8(%rsi),%rax
-mulq 8(%rcx)
-add %rax,%r12
-adc %rdx,%r13
-movq 8(%rsi),%rax
-mulq 16(%rcx)
-add %rax,%r14
-adc %rdx,%r15
-movq 8(%rsi),%rax
-mulq 24(%rcx)
-add %rax,%rbx
-adc %rdx,%rbp
-movq 8(%rsi),%rdx
-imulq $19,%rdx,%rax
-mulq 32(%rcx)
-add %rax,%r8
-adc %rdx,%r9
-movq 16(%rsi),%rax
-mulq 0(%rcx)
-add %rax,%r12
-adc %rdx,%r13
-movq 16(%rsi),%rax
-mulq 8(%rcx)
-add %rax,%r14
-adc %rdx,%r15
-movq 16(%rsi),%rax
-mulq 16(%rcx)
-add %rax,%rbx
-adc %rdx,%rbp
-movq 16(%rsi),%rdx
-imulq $19,%rdx,%rax
-mulq 24(%rcx)
-add %rax,%r8
-adc %rdx,%r9
-movq 16(%rsi),%rdx
-imulq $19,%rdx,%rax
-mulq 32(%rcx)
-add %rax,%r10
-adc %rdx,%r11
-movq 24(%rsi),%rax
-mulq 0(%rcx)
-add %rax,%r14
-adc %rdx,%r15
-movq 24(%rsi),%rax
-mulq 8(%rcx)
-add %rax,%rbx
-adc %rdx,%rbp
-movq -64(%rsp),%rax
-mulq 24(%rcx)
-add %rax,%r10
-adc %rdx,%r11
-movq -64(%rsp),%rax
-mulq 32(%rcx)
-add %rax,%r12
-adc %rdx,%r13
-movq 32(%rsi),%rax
-mulq 0(%rcx)
-add %rax,%rbx
-adc %rdx,%rbp
-movq -72(%rsp),%rax
-mulq 16(%rcx)
-add %rax,%r10
-adc %rdx,%r11
-movq -72(%rsp),%rax
-mulq 24(%rcx)
-add %rax,%r12
-adc %rdx,%r13
-movq -72(%rsp),%rax
-mulq 32(%rcx)
-add %rax,%r14
-adc %rdx,%r15
-movq x25519_x86_64_REDMASK51(%rip),%rsi
-shld $13,%r8,%r9
-and %rsi,%r8
-shld $13,%r10,%r11
-and %rsi,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rsi,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rsi,%r14
-add %r13,%r14
-shld $13,%rbx,%rbp
-and %rsi,%rbx
-add %r15,%rbx
-imulq $19,%rbp,%rdx
-add %rdx,%r8
-mov %r8,%rdx
-shr $51,%rdx
-add %r10,%rdx
-mov %rdx,%rcx
-shr $51,%rdx
-and %rsi,%r8
-add %r12,%rdx
-mov %rdx,%r9
-shr $51,%rdx
-and %rsi,%rcx
-add %r14,%rdx
-mov %rdx,%rax
-shr $51,%rdx
-and %rsi,%r9
-add %rbx,%rdx
-mov %rdx,%r10
-shr $51,%rdx
-and %rsi,%rax
-imulq $19,%rdx,%rdx
-add %rdx,%r8
-and %rsi,%r10
-movq %r8,0(%rdi)
-movq %rcx,8(%rdi)
-movq %r9,16(%rdi)
-movq %rax,24(%rdi)
-movq %r10,32(%rdi)
-movq -8(%rsp),%r12
-movq -16(%rsp),%r13
-movq -24(%rsp),%r14
-movq -32(%rsp),%r15
-movq -40(%rsp),%rbx
-movq -48(%rsp),%rbp
-ret
-.cfi_endproc
-
-.p2align 5
-.globl C_ABI(x25519_x86_64_square)
-HIDDEN C_ABI(x25519_x86_64_square)
-C_ABI(x25519_x86_64_square):
-.cfi_startproc
-/* This is a leaf function and uses the redzone for saving registers. */
-movq %r12,-8(%rsp)
-.cfi_rel_offset r12, -8
-movq %r13,-16(%rsp)
-.cfi_rel_offset r13, -16
-movq %r14,-24(%rsp)
-.cfi_rel_offset r14, -24
-movq %r15,-32(%rsp)
-.cfi_rel_offset r15, -32
-movq %rbx,-40(%rsp)
-.cfi_rel_offset rbx, -40
-movq 0(%rsi),%rax
-mulq 0(%rsi)
-mov %rax,%rcx
-mov %rdx,%r8
-movq 0(%rsi),%rax
-shl $1,%rax
-mulq 8(%rsi)
-mov %rax,%r9
-mov %rdx,%r10
-movq 0(%rsi),%rax
-shl $1,%rax
-mulq 16(%rsi)
-mov %rax,%r11
-mov %rdx,%r12
-movq 0(%rsi),%rax
-shl $1,%rax
-mulq 24(%rsi)
-mov %rax,%r13
-mov %rdx,%r14
-movq 0(%rsi),%rax
-shl $1,%rax
-mulq 32(%rsi)
-mov %rax,%r15
-mov %rdx,%rbx
-movq 8(%rsi),%rax
-mulq 8(%rsi)
-add %rax,%r11
-adc %rdx,%r12
-movq 8(%rsi),%rax
-shl $1,%rax
-mulq 16(%rsi)
-add %rax,%r13
-adc %rdx,%r14
-movq 8(%rsi),%rax
-shl $1,%rax
-mulq 24(%rsi)
-add %rax,%r15
-adc %rdx,%rbx
-movq 8(%rsi),%rdx
-imulq $38,%rdx,%rax
-mulq 32(%rsi)
-add %rax,%rcx
-adc %rdx,%r8
-movq 16(%rsi),%rax
-mulq 16(%rsi)
-add %rax,%r15
-adc %rdx,%rbx
-movq 16(%rsi),%rdx
-imulq $38,%rdx,%rax
-mulq 24(%rsi)
-add %rax,%rcx
-adc %rdx,%r8
-movq 16(%rsi),%rdx
-imulq $38,%rdx,%rax
-mulq 32(%rsi)
-add %rax,%r9
-adc %rdx,%r10
-movq 24(%rsi),%rdx
-imulq $19,%rdx,%rax
-mulq 24(%rsi)
-add %rax,%r9
-adc %rdx,%r10
-movq 24(%rsi),%rdx
-imulq $38,%rdx,%rax
-mulq 32(%rsi)
-add %rax,%r11
-adc %rdx,%r12
-movq 32(%rsi),%rdx
-imulq $19,%rdx,%rax
-mulq 32(%rsi)
-add %rax,%r13
-adc %rdx,%r14
-movq x25519_x86_64_REDMASK51(%rip),%rsi
-shld $13,%rcx,%r8
-and %rsi,%rcx
-shld $13,%r9,%r10
-and %rsi,%r9
-add %r8,%r9
-shld $13,%r11,%r12
-and %rsi,%r11
-add %r10,%r11
-shld $13,%r13,%r14
-and %rsi,%r13
-add %r12,%r13
-shld $13,%r15,%rbx
-and %rsi,%r15
-add %r14,%r15
-imulq $19,%rbx,%rdx
-add %rdx,%rcx
-mov %rcx,%rdx
-shr $51,%rdx
-add %r9,%rdx
-and %rsi,%rcx
-mov %rdx,%r8
-shr $51,%rdx
-add %r11,%rdx
-and %rsi,%r8
-mov %rdx,%r9
-shr $51,%rdx
-add %r13,%rdx
-and %rsi,%r9
-mov %rdx,%rax
-shr $51,%rdx
-add %r15,%rdx
-and %rsi,%rax
-mov %rdx,%r10
-shr $51,%rdx
-imulq $19,%rdx,%rdx
-add %rdx,%rcx
-and %rsi,%r10
-movq %rcx,0(%rdi)
-movq %r8,8(%rdi)
-movq %r9,16(%rdi)
-movq %rax,24(%rdi)
-movq %r10,32(%rdi)
-movq -8(%rsp),%r12
-movq -16(%rsp),%r13
-movq -24(%rsp),%r14
-movq -32(%rsp),%r15
-movq -40(%rsp),%rbx
-ret
-.cfi_endproc
-
-.p2align 5
-.globl C_ABI(x25519_x86_64_ladderstep)
-HIDDEN C_ABI(x25519_x86_64_ladderstep)
-C_ABI(x25519_x86_64_ladderstep):
-.cfi_startproc
-sub $344,%rsp
-.cfi_adjust_cfa_offset 344
-movq %r12,296(%rsp)
-.cfi_rel_offset r12, 296
-movq %r13,304(%rsp)
-.cfi_rel_offset r13, 304
-movq %r14,312(%rsp)
-.cfi_rel_offset r14, 312
-movq %r15,320(%rsp)
-.cfi_rel_offset r15, 320
-movq %rbx,328(%rsp)
-.cfi_rel_offset rbx, 328
-movq %rbp,336(%rsp)
-.cfi_rel_offset rbp, 336
-movq 40(%rdi),%rsi
-movq 48(%rdi),%rdx
-movq 56(%rdi),%rcx
-movq 64(%rdi),%r8
-movq 72(%rdi),%r9
-mov %rsi,%rax
-mov %rdx,%r10
-mov %rcx,%r11
-mov %r8,%r12
-mov %r9,%r13
-add x25519_x86_64_2P0(%rip),%rax
-add x25519_x86_64_2P1234(%rip),%r10
-add x25519_x86_64_2P1234(%rip),%r11
-add x25519_x86_64_2P1234(%rip),%r12
-add x25519_x86_64_2P1234(%rip),%r13
-addq 80(%rdi),%rsi
-addq 88(%rdi),%rdx
-addq 96(%rdi),%rcx
-addq 104(%rdi),%r8
-addq 112(%rdi),%r9
-subq 80(%rdi),%rax
-subq 88(%rdi),%r10
-subq 96(%rdi),%r11
-subq 104(%rdi),%r12
-subq 112(%rdi),%r13
-movq %rsi,0(%rsp)
-movq %rdx,8(%rsp)
-movq %rcx,16(%rsp)
-movq %r8,24(%rsp)
-movq %r9,32(%rsp)
-movq %rax,40(%rsp)
-movq %r10,48(%rsp)
-movq %r11,56(%rsp)
-movq %r12,64(%rsp)
-movq %r13,72(%rsp)
-movq 40(%rsp),%rax
-mulq 40(%rsp)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 40(%rsp),%rax
-shl $1,%rax
-mulq 48(%rsp)
-mov %rax,%r8
-mov %rdx,%r9
-movq 40(%rsp),%rax
-shl $1,%rax
-mulq 56(%rsp)
-mov %rax,%r10
-mov %rdx,%r11
-movq 40(%rsp),%rax
-shl $1,%rax
-mulq 64(%rsp)
-mov %rax,%r12
-mov %rdx,%r13
-movq 40(%rsp),%rax
-shl $1,%rax
-mulq 72(%rsp)
-mov %rax,%r14
-mov %rdx,%r15
-movq 48(%rsp),%rax
-mulq 48(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 48(%rsp),%rax
-shl $1,%rax
-mulq 56(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 48(%rsp),%rax
-shl $1,%rax
-mulq 64(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 48(%rsp),%rdx
-imulq $38,%rdx,%rax
-mulq 72(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 56(%rsp),%rax
-mulq 56(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 56(%rsp),%rdx
-imulq $38,%rdx,%rax
-mulq 64(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 56(%rsp),%rdx
-imulq $38,%rdx,%rax
-mulq 72(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 64(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 64(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 64(%rsp),%rdx
-imulq $38,%rdx,%rax
-mulq 72(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 72(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 72(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-and %rdx,%rsi
-mov %rcx,%r8
-shr $51,%rcx
-add %r10,%rcx
-and %rdx,%r8
-mov %rcx,%r9
-shr $51,%rcx
-add %r12,%rcx
-and %rdx,%r9
-mov %rcx,%rax
-shr $51,%rcx
-add %r14,%rcx
-and %rdx,%rax
-mov %rcx,%r10
-shr $51,%rcx
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-movq %rsi,80(%rsp)
-movq %r8,88(%rsp)
-movq %r9,96(%rsp)
-movq %rax,104(%rsp)
-movq %r10,112(%rsp)
-movq 0(%rsp),%rax
-mulq 0(%rsp)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 0(%rsp),%rax
-shl $1,%rax
-mulq 8(%rsp)
-mov %rax,%r8
-mov %rdx,%r9
-movq 0(%rsp),%rax
-shl $1,%rax
-mulq 16(%rsp)
-mov %rax,%r10
-mov %rdx,%r11
-movq 0(%rsp),%rax
-shl $1,%rax
-mulq 24(%rsp)
-mov %rax,%r12
-mov %rdx,%r13
-movq 0(%rsp),%rax
-shl $1,%rax
-mulq 32(%rsp)
-mov %rax,%r14
-mov %rdx,%r15
-movq 8(%rsp),%rax
-mulq 8(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 8(%rsp),%rax
-shl $1,%rax
-mulq 16(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 8(%rsp),%rax
-shl $1,%rax
-mulq 24(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 8(%rsp),%rdx
-imulq $38,%rdx,%rax
-mulq 32(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 16(%rsp),%rax
-mulq 16(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 16(%rsp),%rdx
-imulq $38,%rdx,%rax
-mulq 24(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 16(%rsp),%rdx
-imulq $38,%rdx,%rax
-mulq 32(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 24(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 24(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 24(%rsp),%rdx
-imulq $38,%rdx,%rax
-mulq 32(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 32(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 32(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-and %rdx,%rsi
-mov %rcx,%r8
-shr $51,%rcx
-add %r10,%rcx
-and %rdx,%r8
-mov %rcx,%r9
-shr $51,%rcx
-add %r12,%rcx
-and %rdx,%r9
-mov %rcx,%rax
-shr $51,%rcx
-add %r14,%rcx
-and %rdx,%rax
-mov %rcx,%r10
-shr $51,%rcx
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-movq %rsi,120(%rsp)
-movq %r8,128(%rsp)
-movq %r9,136(%rsp)
-movq %rax,144(%rsp)
-movq %r10,152(%rsp)
-mov %rsi,%rsi
-mov %r8,%rdx
-mov %r9,%rcx
-mov %rax,%r8
-mov %r10,%r9
-add x25519_x86_64_2P0(%rip),%rsi
-add x25519_x86_64_2P1234(%rip),%rdx
-add x25519_x86_64_2P1234(%rip),%rcx
-add x25519_x86_64_2P1234(%rip),%r8
-add x25519_x86_64_2P1234(%rip),%r9
-subq 80(%rsp),%rsi
-subq 88(%rsp),%rdx
-subq 96(%rsp),%rcx
-subq 104(%rsp),%r8
-subq 112(%rsp),%r9
-movq %rsi,160(%rsp)
-movq %rdx,168(%rsp)
-movq %rcx,176(%rsp)
-movq %r8,184(%rsp)
-movq %r9,192(%rsp)
-movq 120(%rdi),%rsi
-movq 128(%rdi),%rdx
-movq 136(%rdi),%rcx
-movq 144(%rdi),%r8
-movq 152(%rdi),%r9
-mov %rsi,%rax
-mov %rdx,%r10
-mov %rcx,%r11
-mov %r8,%r12
-mov %r9,%r13
-add x25519_x86_64_2P0(%rip),%rax
-add x25519_x86_64_2P1234(%rip),%r10
-add x25519_x86_64_2P1234(%rip),%r11
-add x25519_x86_64_2P1234(%rip),%r12
-add x25519_x86_64_2P1234(%rip),%r13
-addq 160(%rdi),%rsi
-addq 168(%rdi),%rdx
-addq 176(%rdi),%rcx
-addq 184(%rdi),%r8
-addq 192(%rdi),%r9
-subq 160(%rdi),%rax
-subq 168(%rdi),%r10
-subq 176(%rdi),%r11
-subq 184(%rdi),%r12
-subq 192(%rdi),%r13
-movq %rsi,200(%rsp)
-movq %rdx,208(%rsp)
-movq %rcx,216(%rsp)
-movq %r8,224(%rsp)
-movq %r9,232(%rsp)
-movq %rax,240(%rsp)
-movq %r10,248(%rsp)
-movq %r11,256(%rsp)
-movq %r12,264(%rsp)
-movq %r13,272(%rsp)
-movq 224(%rsp),%rsi
-imulq $19,%rsi,%rax
-movq %rax,280(%rsp)
-mulq 56(%rsp)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 232(%rsp),%rdx
-imulq $19,%rdx,%rax
-movq %rax,288(%rsp)
-mulq 48(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 200(%rsp),%rax
-mulq 40(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 200(%rsp),%rax
-mulq 48(%rsp)
-mov %rax,%r8
-mov %rdx,%r9
-movq 200(%rsp),%rax
-mulq 56(%rsp)
-mov %rax,%r10
-mov %rdx,%r11
-movq 200(%rsp),%rax
-mulq 64(%rsp)
-mov %rax,%r12
-mov %rdx,%r13
-movq 200(%rsp),%rax
-mulq 72(%rsp)
-mov %rax,%r14
-mov %rdx,%r15
-movq 208(%rsp),%rax
-mulq 40(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 208(%rsp),%rax
-mulq 48(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 208(%rsp),%rax
-mulq 56(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 208(%rsp),%rax
-mulq 64(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 208(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 72(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 216(%rsp),%rax
-mulq 40(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 216(%rsp),%rax
-mulq 48(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 216(%rsp),%rax
-mulq 56(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 216(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 64(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 216(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 72(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 224(%rsp),%rax
-mulq 40(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 224(%rsp),%rax
-mulq 48(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 280(%rsp),%rax
-mulq 64(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 280(%rsp),%rax
-mulq 72(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 232(%rsp),%rax
-mulq 40(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 288(%rsp),%rax
-mulq 56(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 288(%rsp),%rax
-mulq 64(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 288(%rsp),%rax
-mulq 72(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-mov %rcx,%r8
-shr $51,%rcx
-and %rdx,%rsi
-add %r10,%rcx
-mov %rcx,%r9
-shr $51,%rcx
-and %rdx,%r8
-add %r12,%rcx
-mov %rcx,%rax
-shr $51,%rcx
-and %rdx,%r9
-add %r14,%rcx
-mov %rcx,%r10
-shr $51,%rcx
-and %rdx,%rax
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-movq %rsi,40(%rsp)
-movq %r8,48(%rsp)
-movq %r9,56(%rsp)
-movq %rax,64(%rsp)
-movq %r10,72(%rsp)
-movq 264(%rsp),%rsi
-imulq $19,%rsi,%rax
-movq %rax,200(%rsp)
-mulq 16(%rsp)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 272(%rsp),%rdx
-imulq $19,%rdx,%rax
-movq %rax,208(%rsp)
-mulq 8(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 240(%rsp),%rax
-mulq 0(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 240(%rsp),%rax
-mulq 8(%rsp)
-mov %rax,%r8
-mov %rdx,%r9
-movq 240(%rsp),%rax
-mulq 16(%rsp)
-mov %rax,%r10
-mov %rdx,%r11
-movq 240(%rsp),%rax
-mulq 24(%rsp)
-mov %rax,%r12
-mov %rdx,%r13
-movq 240(%rsp),%rax
-mulq 32(%rsp)
-mov %rax,%r14
-mov %rdx,%r15
-movq 248(%rsp),%rax
-mulq 0(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 248(%rsp),%rax
-mulq 8(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 248(%rsp),%rax
-mulq 16(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 248(%rsp),%rax
-mulq 24(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 248(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 32(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 256(%rsp),%rax
-mulq 0(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 256(%rsp),%rax
-mulq 8(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 256(%rsp),%rax
-mulq 16(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 256(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 24(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 256(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 32(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 264(%rsp),%rax
-mulq 0(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 264(%rsp),%rax
-mulq 8(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 200(%rsp),%rax
-mulq 24(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 200(%rsp),%rax
-mulq 32(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 272(%rsp),%rax
-mulq 0(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 208(%rsp),%rax
-mulq 16(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 208(%rsp),%rax
-mulq 24(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 208(%rsp),%rax
-mulq 32(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-mov %rcx,%r8
-shr $51,%rcx
-and %rdx,%rsi
-add %r10,%rcx
-mov %rcx,%r9
-shr $51,%rcx
-and %rdx,%r8
-add %r12,%rcx
-mov %rcx,%rax
-shr $51,%rcx
-and %rdx,%r9
-add %r14,%rcx
-mov %rcx,%r10
-shr $51,%rcx
-and %rdx,%rax
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-mov %rsi,%rdx
-mov %r8,%rcx
-mov %r9,%r11
-mov %rax,%r12
-mov %r10,%r13
-add x25519_x86_64_2P0(%rip),%rdx
-add x25519_x86_64_2P1234(%rip),%rcx
-add x25519_x86_64_2P1234(%rip),%r11
-add x25519_x86_64_2P1234(%rip),%r12
-add x25519_x86_64_2P1234(%rip),%r13
-addq 40(%rsp),%rsi
-addq 48(%rsp),%r8
-addq 56(%rsp),%r9
-addq 64(%rsp),%rax
-addq 72(%rsp),%r10
-subq 40(%rsp),%rdx
-subq 48(%rsp),%rcx
-subq 56(%rsp),%r11
-subq 64(%rsp),%r12
-subq 72(%rsp),%r13
-movq %rsi,120(%rdi)
-movq %r8,128(%rdi)
-movq %r9,136(%rdi)
-movq %rax,144(%rdi)
-movq %r10,152(%rdi)
-movq %rdx,160(%rdi)
-movq %rcx,168(%rdi)
-movq %r11,176(%rdi)
-movq %r12,184(%rdi)
-movq %r13,192(%rdi)
-movq 120(%rdi),%rax
-mulq 120(%rdi)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 120(%rdi),%rax
-shl $1,%rax
-mulq 128(%rdi)
-mov %rax,%r8
-mov %rdx,%r9
-movq 120(%rdi),%rax
-shl $1,%rax
-mulq 136(%rdi)
-mov %rax,%r10
-mov %rdx,%r11
-movq 120(%rdi),%rax
-shl $1,%rax
-mulq 144(%rdi)
-mov %rax,%r12
-mov %rdx,%r13
-movq 120(%rdi),%rax
-shl $1,%rax
-mulq 152(%rdi)
-mov %rax,%r14
-mov %rdx,%r15
-movq 128(%rdi),%rax
-mulq 128(%rdi)
-add %rax,%r10
-adc %rdx,%r11
-movq 128(%rdi),%rax
-shl $1,%rax
-mulq 136(%rdi)
-add %rax,%r12
-adc %rdx,%r13
-movq 128(%rdi),%rax
-shl $1,%rax
-mulq 144(%rdi)
-add %rax,%r14
-adc %rdx,%r15
-movq 128(%rdi),%rdx
-imulq $38,%rdx,%rax
-mulq 152(%rdi)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 136(%rdi),%rax
-mulq 136(%rdi)
-add %rax,%r14
-adc %rdx,%r15
-movq 136(%rdi),%rdx
-imulq $38,%rdx,%rax
-mulq 144(%rdi)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 136(%rdi),%rdx
-imulq $38,%rdx,%rax
-mulq 152(%rdi)
-add %rax,%r8
-adc %rdx,%r9
-movq 144(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 144(%rdi)
-add %rax,%r8
-adc %rdx,%r9
-movq 144(%rdi),%rdx
-imulq $38,%rdx,%rax
-mulq 152(%rdi)
-add %rax,%r10
-adc %rdx,%r11
-movq 152(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 152(%rdi)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-and %rdx,%rsi
-mov %rcx,%r8
-shr $51,%rcx
-add %r10,%rcx
-and %rdx,%r8
-mov %rcx,%r9
-shr $51,%rcx
-add %r12,%rcx
-and %rdx,%r9
-mov %rcx,%rax
-shr $51,%rcx
-add %r14,%rcx
-and %rdx,%rax
-mov %rcx,%r10
-shr $51,%rcx
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-movq %rsi,120(%rdi)
-movq %r8,128(%rdi)
-movq %r9,136(%rdi)
-movq %rax,144(%rdi)
-movq %r10,152(%rdi)
-movq 160(%rdi),%rax
-mulq 160(%rdi)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 160(%rdi),%rax
-shl $1,%rax
-mulq 168(%rdi)
-mov %rax,%r8
-mov %rdx,%r9
-movq 160(%rdi),%rax
-shl $1,%rax
-mulq 176(%rdi)
-mov %rax,%r10
-mov %rdx,%r11
-movq 160(%rdi),%rax
-shl $1,%rax
-mulq 184(%rdi)
-mov %rax,%r12
-mov %rdx,%r13
-movq 160(%rdi),%rax
-shl $1,%rax
-mulq 192(%rdi)
-mov %rax,%r14
-mov %rdx,%r15
-movq 168(%rdi),%rax
-mulq 168(%rdi)
-add %rax,%r10
-adc %rdx,%r11
-movq 168(%rdi),%rax
-shl $1,%rax
-mulq 176(%rdi)
-add %rax,%r12
-adc %rdx,%r13
-movq 168(%rdi),%rax
-shl $1,%rax
-mulq 184(%rdi)
-add %rax,%r14
-adc %rdx,%r15
-movq 168(%rdi),%rdx
-imulq $38,%rdx,%rax
-mulq 192(%rdi)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 176(%rdi),%rax
-mulq 176(%rdi)
-add %rax,%r14
-adc %rdx,%r15
-movq 176(%rdi),%rdx
-imulq $38,%rdx,%rax
-mulq 184(%rdi)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 176(%rdi),%rdx
-imulq $38,%rdx,%rax
-mulq 192(%rdi)
-add %rax,%r8
-adc %rdx,%r9
-movq 184(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 184(%rdi)
-add %rax,%r8
-adc %rdx,%r9
-movq 184(%rdi),%rdx
-imulq $38,%rdx,%rax
-mulq 192(%rdi)
-add %rax,%r10
-adc %rdx,%r11
-movq 192(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 192(%rdi)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-and %rdx,%rsi
-mov %rcx,%r8
-shr $51,%rcx
-add %r10,%rcx
-and %rdx,%r8
-mov %rcx,%r9
-shr $51,%rcx
-add %r12,%rcx
-and %rdx,%r9
-mov %rcx,%rax
-shr $51,%rcx
-add %r14,%rcx
-and %rdx,%rax
-mov %rcx,%r10
-shr $51,%rcx
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-movq %rsi,160(%rdi)
-movq %r8,168(%rdi)
-movq %r9,176(%rdi)
-movq %rax,184(%rdi)
-movq %r10,192(%rdi)
-movq 184(%rdi),%rsi
-imulq $19,%rsi,%rax
-movq %rax,0(%rsp)
-mulq 16(%rdi)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 192(%rdi),%rdx
-imulq $19,%rdx,%rax
-movq %rax,8(%rsp)
-mulq 8(%rdi)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 160(%rdi),%rax
-mulq 0(%rdi)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 160(%rdi),%rax
-mulq 8(%rdi)
-mov %rax,%r8
-mov %rdx,%r9
-movq 160(%rdi),%rax
-mulq 16(%rdi)
-mov %rax,%r10
-mov %rdx,%r11
-movq 160(%rdi),%rax
-mulq 24(%rdi)
-mov %rax,%r12
-mov %rdx,%r13
-movq 160(%rdi),%rax
-mulq 32(%rdi)
-mov %rax,%r14
-mov %rdx,%r15
-movq 168(%rdi),%rax
-mulq 0(%rdi)
-add %rax,%r8
-adc %rdx,%r9
-movq 168(%rdi),%rax
-mulq 8(%rdi)
-add %rax,%r10
-adc %rdx,%r11
-movq 168(%rdi),%rax
-mulq 16(%rdi)
-add %rax,%r12
-adc %rdx,%r13
-movq 168(%rdi),%rax
-mulq 24(%rdi)
-add %rax,%r14
-adc %rdx,%r15
-movq 168(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 32(%rdi)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 176(%rdi),%rax
-mulq 0(%rdi)
-add %rax,%r10
-adc %rdx,%r11
-movq 176(%rdi),%rax
-mulq 8(%rdi)
-add %rax,%r12
-adc %rdx,%r13
-movq 176(%rdi),%rax
-mulq 16(%rdi)
-add %rax,%r14
-adc %rdx,%r15
-movq 176(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 24(%rdi)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 176(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 32(%rdi)
-add %rax,%r8
-adc %rdx,%r9
-movq 184(%rdi),%rax
-mulq 0(%rdi)
-add %rax,%r12
-adc %rdx,%r13
-movq 184(%rdi),%rax
-mulq 8(%rdi)
-add %rax,%r14
-adc %rdx,%r15
-movq 0(%rsp),%rax
-mulq 24(%rdi)
-add %rax,%r8
-adc %rdx,%r9
-movq 0(%rsp),%rax
-mulq 32(%rdi)
-add %rax,%r10
-adc %rdx,%r11
-movq 192(%rdi),%rax
-mulq 0(%rdi)
-add %rax,%r14
-adc %rdx,%r15
-movq 8(%rsp),%rax
-mulq 16(%rdi)
-add %rax,%r8
-adc %rdx,%r9
-movq 8(%rsp),%rax
-mulq 24(%rdi)
-add %rax,%r10
-adc %rdx,%r11
-movq 8(%rsp),%rax
-mulq 32(%rdi)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-mov %rcx,%r8
-shr $51,%rcx
-and %rdx,%rsi
-add %r10,%rcx
-mov %rcx,%r9
-shr $51,%rcx
-and %rdx,%r8
-add %r12,%rcx
-mov %rcx,%rax
-shr $51,%rcx
-and %rdx,%r9
-add %r14,%rcx
-mov %rcx,%r10
-shr $51,%rcx
-and %rdx,%rax
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-movq %rsi,160(%rdi)
-movq %r8,168(%rdi)
-movq %r9,176(%rdi)
-movq %rax,184(%rdi)
-movq %r10,192(%rdi)
-movq 144(%rsp),%rsi
-imulq $19,%rsi,%rax
-movq %rax,0(%rsp)
-mulq 96(%rsp)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 152(%rsp),%rdx
-imulq $19,%rdx,%rax
-movq %rax,8(%rsp)
-mulq 88(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 120(%rsp),%rax
-mulq 80(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 120(%rsp),%rax
-mulq 88(%rsp)
-mov %rax,%r8
-mov %rdx,%r9
-movq 120(%rsp),%rax
-mulq 96(%rsp)
-mov %rax,%r10
-mov %rdx,%r11
-movq 120(%rsp),%rax
-mulq 104(%rsp)
-mov %rax,%r12
-mov %rdx,%r13
-movq 120(%rsp),%rax
-mulq 112(%rsp)
-mov %rax,%r14
-mov %rdx,%r15
-movq 128(%rsp),%rax
-mulq 80(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 128(%rsp),%rax
-mulq 88(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 128(%rsp),%rax
-mulq 96(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 128(%rsp),%rax
-mulq 104(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 128(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 112(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 136(%rsp),%rax
-mulq 80(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 136(%rsp),%rax
-mulq 88(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 136(%rsp),%rax
-mulq 96(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 136(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 104(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 136(%rsp),%rdx
-imulq $19,%rdx,%rax
-mulq 112(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 144(%rsp),%rax
-mulq 80(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 144(%rsp),%rax
-mulq 88(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 0(%rsp),%rax
-mulq 104(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 0(%rsp),%rax
-mulq 112(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 152(%rsp),%rax
-mulq 80(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 8(%rsp),%rax
-mulq 96(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 8(%rsp),%rax
-mulq 104(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 8(%rsp),%rax
-mulq 112(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-mov %rcx,%r8
-shr $51,%rcx
-and %rdx,%rsi
-add %r10,%rcx
-mov %rcx,%r9
-shr $51,%rcx
-and %rdx,%r8
-add %r12,%rcx
-mov %rcx,%rax
-shr $51,%rcx
-and %rdx,%r9
-add %r14,%rcx
-mov %rcx,%r10
-shr $51,%rcx
-and %rdx,%rax
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-movq %rsi,40(%rdi)
-movq %r8,48(%rdi)
-movq %r9,56(%rdi)
-movq %rax,64(%rdi)
-movq %r10,72(%rdi)
-movq 160(%rsp),%rax
-mulq x25519_x86_64_121666_213(%rip)
-shr $13,%rax
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 168(%rsp),%rax
-mulq x25519_x86_64_121666_213(%rip)
-shr $13,%rax
-add %rax,%rcx
-mov %rdx,%r8
-movq 176(%rsp),%rax
-mulq x25519_x86_64_121666_213(%rip)
-shr $13,%rax
-add %rax,%r8
-mov %rdx,%r9
-movq 184(%rsp),%rax
-mulq x25519_x86_64_121666_213(%rip)
-shr $13,%rax
-add %rax,%r9
-mov %rdx,%r10
-movq 192(%rsp),%rax
-mulq x25519_x86_64_121666_213(%rip)
-shr $13,%rax
-add %rax,%r10
-imulq $19,%rdx,%rdx
-add %rdx,%rsi
-addq 80(%rsp),%rsi
-addq 88(%rsp),%rcx
-addq 96(%rsp),%r8
-addq 104(%rsp),%r9
-addq 112(%rsp),%r10
-movq %rsi,80(%rdi)
-movq %rcx,88(%rdi)
-movq %r8,96(%rdi)
-movq %r9,104(%rdi)
-movq %r10,112(%rdi)
-movq 104(%rdi),%rsi
-imulq $19,%rsi,%rax
-movq %rax,0(%rsp)
-mulq 176(%rsp)
-mov %rax,%rsi
-mov %rdx,%rcx
-movq 112(%rdi),%rdx
-imulq $19,%rdx,%rax
-movq %rax,8(%rsp)
-mulq 168(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 80(%rdi),%rax
-mulq 160(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 80(%rdi),%rax
-mulq 168(%rsp)
-mov %rax,%r8
-mov %rdx,%r9
-movq 80(%rdi),%rax
-mulq 176(%rsp)
-mov %rax,%r10
-mov %rdx,%r11
-movq 80(%rdi),%rax
-mulq 184(%rsp)
-mov %rax,%r12
-mov %rdx,%r13
-movq 80(%rdi),%rax
-mulq 192(%rsp)
-mov %rax,%r14
-mov %rdx,%r15
-movq 88(%rdi),%rax
-mulq 160(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 88(%rdi),%rax
-mulq 168(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 88(%rdi),%rax
-mulq 176(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 88(%rdi),%rax
-mulq 184(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 88(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 192(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 96(%rdi),%rax
-mulq 160(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 96(%rdi),%rax
-mulq 168(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 96(%rdi),%rax
-mulq 176(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 96(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 184(%rsp)
-add %rax,%rsi
-adc %rdx,%rcx
-movq 96(%rdi),%rdx
-imulq $19,%rdx,%rax
-mulq 192(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 104(%rdi),%rax
-mulq 160(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq 104(%rdi),%rax
-mulq 168(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 0(%rsp),%rax
-mulq 184(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 0(%rsp),%rax
-mulq 192(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 112(%rdi),%rax
-mulq 160(%rsp)
-add %rax,%r14
-adc %rdx,%r15
-movq 8(%rsp),%rax
-mulq 176(%rsp)
-add %rax,%r8
-adc %rdx,%r9
-movq 8(%rsp),%rax
-mulq 184(%rsp)
-add %rax,%r10
-adc %rdx,%r11
-movq 8(%rsp),%rax
-mulq 192(%rsp)
-add %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and %rdx,%rsi
-shld $13,%r8,%r9
-and %rdx,%r8
-add %rcx,%r8
-shld $13,%r10,%r11
-and %rdx,%r10
-add %r9,%r10
-shld $13,%r12,%r13
-and %rdx,%r12
-add %r11,%r12
-shld $13,%r14,%r15
-and %rdx,%r14
-add %r13,%r14
-imulq $19,%r15,%rcx
-add %rcx,%rsi
-mov %rsi,%rcx
-shr $51,%rcx
-add %r8,%rcx
-mov %rcx,%r8
-shr $51,%rcx
-and %rdx,%rsi
-add %r10,%rcx
-mov %rcx,%r9
-shr $51,%rcx
-and %rdx,%r8
-add %r12,%rcx
-mov %rcx,%rax
-shr $51,%rcx
-and %rdx,%r9
-add %r14,%rcx
-mov %rcx,%r10
-shr $51,%rcx
-and %rdx,%rax
-imulq $19,%rcx,%rcx
-add %rcx,%rsi
-and %rdx,%r10
-movq %rsi,80(%rdi)
-movq %r8,88(%rdi)
-movq %r9,96(%rdi)
-movq %rax,104(%rdi)
-movq %r10,112(%rdi)
-movq 296(%rsp),%r12
-movq 304(%rsp),%r13
-movq 312(%rsp),%r14
-movq 320(%rsp),%r15
-movq 328(%rsp),%rbx
-movq 336(%rsp),%rbp
-add $344,%rsp
-.cfi_adjust_cfa_offset -344
-ret
-.cfi_endproc
-
-.p2align 5
-.globl C_ABI(x25519_x86_64_work_cswap)
-HIDDEN C_ABI(x25519_x86_64_work_cswap)
-C_ABI(x25519_x86_64_work_cswap):
-.cfi_startproc
-subq $1,%rsi
-notq %rsi
-movq %rsi,%xmm15
-pshufd $0x44,%xmm15,%xmm15
-movdqu 0(%rdi),%xmm0
-movdqu 16(%rdi),%xmm2
-movdqu 32(%rdi),%xmm4
-movdqu 48(%rdi),%xmm6
-movdqu 64(%rdi),%xmm8
-movdqu 80(%rdi),%xmm1
-movdqu 96(%rdi),%xmm3
-movdqu 112(%rdi),%xmm5
-movdqu 128(%rdi),%xmm7
-movdqu 144(%rdi),%xmm9
-movdqa %xmm1,%xmm10
-movdqa %xmm3,%xmm11
-movdqa %xmm5,%xmm12
-movdqa %xmm7,%xmm13
-movdqa %xmm9,%xmm14
-pxor %xmm0,%xmm10
-pxor %xmm2,%xmm11
-pxor %xmm4,%xmm12
-pxor %xmm6,%xmm13
-pxor %xmm8,%xmm14
-pand %xmm15,%xmm10
-pand %xmm15,%xmm11
-pand %xmm15,%xmm12
-pand %xmm15,%xmm13
-pand %xmm15,%xmm14
-pxor %xmm10,%xmm0
-pxor %xmm10,%xmm1
-pxor %xmm11,%xmm2
-pxor %xmm11,%xmm3
-pxor %xmm12,%xmm4
-pxor %xmm12,%xmm5
-pxor %xmm13,%xmm6
-pxor %xmm13,%xmm7
-pxor %xmm14,%xmm8
-pxor %xmm14,%xmm9
-movdqu %xmm0,0(%rdi)
-movdqu %xmm2,16(%rdi)
-movdqu %xmm4,32(%rdi)
-movdqu %xmm6,48(%rdi)
-movdqu %xmm8,64(%rdi)
-movdqu %xmm1,80(%rdi)
-movdqu %xmm3,96(%rdi)
-movdqu %xmm5,112(%rdi)
-movdqu %xmm7,128(%rdi)
-movdqu %xmm9,144(%rdi)
-ret
-.cfi_endproc
-
-#endif /* __x86_64__ */
-#endif /* !OPENSSL_NO_ASM */
diff --git a/src/crypto/curve25519/ed25519_test.cc b/src/crypto/curve25519/ed25519_test.cc
index 31216f1b..4f34675b 100644
--- a/src/crypto/curve25519/ed25519_test.cc
+++ b/src/crypto/curve25519/ed25519_test.cc
@@ -44,6 +44,28 @@ TEST(Ed25519Test, TestVectors) {
});
}
+TEST(Ed25519Test, Malleability) {
+ // 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.
+ static const uint8_t kMsg[] = {0x54, 0x65, 0x73, 0x74};
+ static const uint8_t kSig[] = {
+ 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,
+ };
+ static const uint8_t kPub[] = {
+ 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,
+ };
+
+ EXPECT_FALSE(ED25519_verify(kMsg, sizeof(kMsg), kSig, kPub));
+}
+
TEST(Ed25519Test, KeypairFromSeed) {
uint8_t public_key1[32], private_key1[64];
ED25519_keypair(public_key1, private_key1);
diff --git a/src/crypto/curve25519/x25519-x86_64.c b/src/crypto/curve25519/x25519-x86_64.c
deleted file mode 100644
index 41db0bdd..00000000
--- a/src/crypto/curve25519/x25519-x86_64.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/* Copyright (c) 2015, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-// This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
-// 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
-// public domain but this file has the ISC license just to keep licencing
-// simple.
-//
-// The field functions are shared by Ed25519 and X25519 where possible.
-
-#include <openssl/curve25519.h>
-
-#include <string.h>
-
-#include "../internal.h"
-#include "../../third_party/fiat/internal.h"
-
-
-#if defined(BORINGSSL_X25519_X86_64)
-
-typedef struct { uint64_t v[5]; } fe25519;
-
-// These functions are defined in asm/x25519-x86_64.S
-void x25519_x86_64_work_cswap(fe25519 *, uint64_t);
-void x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b);
-void x25519_x86_64_square(fe25519 *out, const fe25519 *a);
-void x25519_x86_64_freeze(fe25519 *);
-void x25519_x86_64_ladderstep(fe25519 *work);
-
-static void fe25519_setint(fe25519 *r, unsigned v) {
- r->v[0] = v;
- r->v[1] = 0;
- r->v[2] = 0;
- r->v[3] = 0;
- r->v[4] = 0;
-}
-
-// Assumes input x being reduced below 2^255
-static void fe25519_pack(unsigned char r[32], const fe25519 *x) {
- fe25519 t;
- t = *x;
- x25519_x86_64_freeze(&t);
-
- r[0] = (uint8_t)(t.v[0] & 0xff);
- r[1] = (uint8_t)((t.v[0] >> 8) & 0xff);
- r[2] = (uint8_t)((t.v[0] >> 16) & 0xff);
- r[3] = (uint8_t)((t.v[0] >> 24) & 0xff);
- r[4] = (uint8_t)((t.v[0] >> 32) & 0xff);
- r[5] = (uint8_t)((t.v[0] >> 40) & 0xff);
- r[6] = (uint8_t)((t.v[0] >> 48));
-
- r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8);
- r[7] = (uint8_t)((t.v[1] >> 5) & 0xff);
- r[8] = (uint8_t)((t.v[1] >> 13) & 0xff);
- r[9] = (uint8_t)((t.v[1] >> 21) & 0xff);
- r[10] = (uint8_t)((t.v[1] >> 29) & 0xff);
- r[11] = (uint8_t)((t.v[1] >> 37) & 0xff);
- r[12] = (uint8_t)((t.v[1] >> 45));
-
- r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0);
- r[13] = (uint8_t)((t.v[2] >> 2) & 0xff);
- r[14] = (uint8_t)((t.v[2] >> 10) & 0xff);
- r[15] = (uint8_t)((t.v[2] >> 18) & 0xff);
- r[16] = (uint8_t)((t.v[2] >> 26) & 0xff);
- r[17] = (uint8_t)((t.v[2] >> 34) & 0xff);
- r[18] = (uint8_t)((t.v[2] >> 42) & 0xff);
- r[19] = (uint8_t)((t.v[2] >> 50));
-
- r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe);
- r[20] = (uint8_t)((t.v[3] >> 7) & 0xff);
- r[21] = (uint8_t)((t.v[3] >> 15) & 0xff);
- r[22] = (uint8_t)((t.v[3] >> 23) & 0xff);
- r[23] = (uint8_t)((t.v[3] >> 31) & 0xff);
- r[24] = (uint8_t)((t.v[3] >> 39) & 0xff);
- r[25] = (uint8_t)((t.v[3] >> 47));
-
- r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0);
- r[26] = (uint8_t)((t.v[4] >> 4) & 0xff);
- r[27] = (uint8_t)((t.v[4] >> 12) & 0xff);
- r[28] = (uint8_t)((t.v[4] >> 20) & 0xff);
- r[29] = (uint8_t)((t.v[4] >> 28) & 0xff);
- r[30] = (uint8_t)((t.v[4] >> 36) & 0xff);
- r[31] = (uint8_t)((t.v[4] >> 44));
-}
-
-static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) {
- r->v[0] = x[0];
- r->v[0] += (uint64_t)x[1] << 8;
- r->v[0] += (uint64_t)x[2] << 16;
- r->v[0] += (uint64_t)x[3] << 24;
- r->v[0] += (uint64_t)x[4] << 32;
- r->v[0] += (uint64_t)x[5] << 40;
- r->v[0] += ((uint64_t)x[6] & 7) << 48;
-
- r->v[1] = x[6] >> 3;
- r->v[1] += (uint64_t)x[7] << 5;
- r->v[1] += (uint64_t)x[8] << 13;
- r->v[1] += (uint64_t)x[9] << 21;
- r->v[1] += (uint64_t)x[10] << 29;
- r->v[1] += (uint64_t)x[11] << 37;
- r->v[1] += ((uint64_t)x[12] & 63) << 45;
-
- r->v[2] = x[12] >> 6;
- r->v[2] += (uint64_t)x[13] << 2;
- r->v[2] += (uint64_t)x[14] << 10;
- r->v[2] += (uint64_t)x[15] << 18;
- r->v[2] += (uint64_t)x[16] << 26;
- r->v[2] += (uint64_t)x[17] << 34;
- r->v[2] += (uint64_t)x[18] << 42;
- r->v[2] += ((uint64_t)x[19] & 1) << 50;
-
- r->v[3] = x[19] >> 1;
- r->v[3] += (uint64_t)x[20] << 7;
- r->v[3] += (uint64_t)x[21] << 15;
- r->v[3] += (uint64_t)x[22] << 23;
- r->v[3] += (uint64_t)x[23] << 31;
- r->v[3] += (uint64_t)x[24] << 39;
- r->v[3] += ((uint64_t)x[25] & 15) << 47;
-
- r->v[4] = x[25] >> 4;
- r->v[4] += (uint64_t)x[26] << 4;
- r->v[4] += (uint64_t)x[27] << 12;
- r->v[4] += (uint64_t)x[28] << 20;
- r->v[4] += (uint64_t)x[29] << 28;
- r->v[4] += (uint64_t)x[30] << 36;
- r->v[4] += ((uint64_t)x[31] & 127) << 44;
-}
-
-static void fe25519_invert(fe25519 *r, const fe25519 *x) {
- fe25519 z2;
- fe25519 z9;
- fe25519 z11;
- fe25519 z2_5_0;
- fe25519 z2_10_0;
- fe25519 z2_20_0;
- fe25519 z2_50_0;
- fe25519 z2_100_0;
- fe25519 t;
- int i;
-
- /* 2 */ x25519_x86_64_square(&z2, x);
- /* 4 */ x25519_x86_64_square(&t, &z2);
- /* 8 */ x25519_x86_64_square(&t, &t);
- /* 9 */ x25519_x86_64_mul(&z9, &t, x);
- /* 11 */ x25519_x86_64_mul(&z11, &z9, &z2);
- /* 22 */ x25519_x86_64_square(&t, &z11);
- /* 2^5 - 2^0 = 31 */ x25519_x86_64_mul(&z2_5_0, &t, &z9);
-
- /* 2^6 - 2^1 */ x25519_x86_64_square(&t, &z2_5_0);
- /* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { x25519_x86_64_square(&t, &t); }
- /* 2^10 - 2^0 */ x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0);
-
- /* 2^11 - 2^1 */ x25519_x86_64_square(&t, &z2_10_0);
- /* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
- /* 2^20 - 2^0 */ x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0);
-
- /* 2^21 - 2^1 */ x25519_x86_64_square(&t, &z2_20_0);
- /* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { x25519_x86_64_square(&t, &t); }
- /* 2^40 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_20_0);
-
- /* 2^41 - 2^1 */ x25519_x86_64_square(&t, &t);
- /* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
- /* 2^50 - 2^0 */ x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0);
-
- /* 2^51 - 2^1 */ x25519_x86_64_square(&t, &z2_50_0);
- /* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
- /* 2^100 - 2^0 */ x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0);
-
- /* 2^101 - 2^1 */ x25519_x86_64_square(&t, &z2_100_0);
- /* 2^200 - 2^100 */ for (i = 1; i < 100; i++) {
- x25519_x86_64_square(&t, &t);
- }
- /* 2^200 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_100_0);
-
- /* 2^201 - 2^1 */ x25519_x86_64_square(&t, &t);
- /* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
- /* 2^250 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_50_0);
-
- /* 2^251 - 2^1 */ x25519_x86_64_square(&t, &t);
- /* 2^252 - 2^2 */ x25519_x86_64_square(&t, &t);
- /* 2^253 - 2^3 */ x25519_x86_64_square(&t, &t);
-
- /* 2^254 - 2^4 */ x25519_x86_64_square(&t, &t);
-
- /* 2^255 - 2^5 */ x25519_x86_64_square(&t, &t);
- /* 2^255 - 21 */ x25519_x86_64_mul(r, &t, &z11);
-}
-
-static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) {
- fe25519 work[5];
-
- work[0] = *xr;
- fe25519_setint(work + 1, 1);
- fe25519_setint(work + 2, 0);
- work[3] = *xr;
- fe25519_setint(work + 4, 1);
-
- int i, j;
- uint8_t prevbit = 0;
-
- j = 6;
- for (i = 31; i >= 0; i--) {
- while (j >= 0) {
- const uint8_t bit = 1 & (s[i] >> j);
- const uint64_t swap = bit ^ prevbit;
- prevbit = bit;
- x25519_x86_64_work_cswap(work + 1, swap);
- x25519_x86_64_ladderstep(work);
- j -= 1;
- }
- j = 7;
- }
-
- *xr = work[1];
- *zr = work[2];
-}
-
-void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
- const uint8_t point[32]) {
- uint8_t e[32];
- OPENSSL_memcpy(e, scalar, sizeof(e));
-
- e[0] &= 248;
- e[31] &= 127;
- e[31] |= 64;
-
- fe25519 t;
- fe25519 z;
- fe25519_unpack(&t, point);
- mladder(&t, &z, e);
- fe25519_invert(&z, &z);
- x25519_x86_64_mul(&t, &t, &z);
- fe25519_pack(out, &t);
-}
-
-#endif // BORINGSSL_X25519_X86_64
diff --git a/src/crypto/dsa/dsa.c b/src/crypto/dsa/dsa.c
index f3d4f859..532ffec9 100644
--- a/src/crypto/dsa/dsa.c
+++ b/src/crypto/dsa/dsa.c
@@ -239,11 +239,6 @@ int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
}
BN_CTX_start(ctx);
- mont = BN_MONT_CTX_new();
- if (mont == NULL) {
- goto err;
- }
-
r0 = BN_CTX_get(ctx);
g = BN_CTX_get(ctx);
W = BN_CTX_get(ctx);
@@ -401,8 +396,9 @@ end:
goto err;
}
- if (!BN_set_word(test, h) ||
- !BN_MONT_CTX_set(mont, p, ctx)) {
+ mont = BN_MONT_CTX_new_for_modulus(p, ctx);
+ if (mont == NULL ||
+ !BN_set_word(test, h)) {
goto err;
}
diff --git a/src/crypto/err/ssl.errordata b/src/crypto/err/ssl.errordata
index 44509584..7b63bc8e 100644
--- a/src/crypto/err/ssl.errordata
+++ b/src/crypto/err/ssl.errordata
@@ -117,6 +117,7 @@ SSL,191,PATH_TOO_LONG
SSL,192,PEER_DID_NOT_RETURN_A_CERTIFICATE
SSL,193,PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE
SSL,267,PRE_SHARED_KEY_MUST_BE_LAST
+SSL,287,PRIVATE_KEY_OPERATION_FAILED
SSL,194,PROTOCOL_IS_SHUTDOWN
SSL,271,PSK_IDENTITY_BINDER_COUNT_MISMATCH
SSL,195,PSK_IDENTITY_NOT_FOUND
diff --git a/src/crypto/fipsmodule/bn/add.c b/src/crypto/fipsmodule/bn/add.c
index 201c526d..645e647d 100644
--- a/src/crypto/fipsmodule/bn/add.c
+++ b/src/crypto/fipsmodule/bn/add.c
@@ -199,7 +199,6 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) {
}
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
- int max;
int add = 0, neg = 0;
const BIGNUM *tmp;
@@ -232,13 +231,6 @@ int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
return 1;
}
- // We are actually doing a - b :-)
-
- max = (a->top > b->top) ? a->top : b->top;
- if (!bn_wexpand(r, max)) {
- return 0;
- }
-
if (BN_ucmp(a, b) < 0) {
if (!BN_usub(r, b, a)) {
return 0;
diff --git a/src/crypto/fipsmodule/bn/bn.c b/src/crypto/fipsmodule/bn/bn.c
index 4be4f21c..520ca27d 100644
--- a/src/crypto/fipsmodule/bn/bn.c
+++ b/src/crypto/fipsmodule/bn/bn.c
@@ -227,13 +227,12 @@ unsigned BN_num_bits_word(BN_ULONG l) {
}
unsigned BN_num_bits(const BIGNUM *bn) {
- const int max = bn->top - 1;
-
- if (BN_is_zero(bn)) {
+ const int width = bn_minimal_width(bn);
+ if (width == 0) {
return 0;
}
- return max*BN_BITS2 + BN_num_bits_word(bn->d[max]);
+ return (width - 1) * BN_BITS2 + BN_num_bits_word(bn->d[width - 1]);
}
unsigned BN_num_bytes(const BIGNUM *bn) {
@@ -298,6 +297,35 @@ int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
return 1;
}
+int bn_fits_in_words(const BIGNUM *bn, size_t num) {
+ // All words beyond |num| must be zero.
+ BN_ULONG mask = 0;
+ for (size_t i = num; i < (size_t)bn->top; i++) {
+ mask |= bn->d[i];
+ }
+ return mask == 0;
+}
+
+int bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn) {
+ if (bn->neg) {
+ OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
+ return 0;
+ }
+
+ size_t width = (size_t)bn->top;
+ if (width > num) {
+ if (!bn_fits_in_words(bn, num)) {
+ OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
+ return 0;
+ }
+ width = num;
+ }
+
+ OPENSSL_memset(out, 0, sizeof(BN_ULONG) * num);
+ OPENSSL_memcpy(out, bn->d, sizeof(BN_ULONG) * width);
+ return 1;
+}
+
int BN_is_negative(const BIGNUM *bn) {
return bn->neg != 0;
}
@@ -350,19 +378,35 @@ int bn_expand(BIGNUM *bn, size_t bits) {
return bn_wexpand(bn, (bits+BN_BITS2-1)/BN_BITS2);
}
-void bn_correct_top(BIGNUM *bn) {
- BN_ULONG *ftl;
- int tmp_top = bn->top;
-
- if (tmp_top > 0) {
- for (ftl = &(bn->d[tmp_top - 1]); tmp_top > 0; tmp_top--) {
- if (*(ftl--)) {
- break;
- }
+int bn_resize_words(BIGNUM *bn, size_t words) {
+ if ((size_t)bn->top <= words) {
+ if (!bn_wexpand(bn, words)) {
+ return 0;
}
- bn->top = tmp_top;
+ OPENSSL_memset(bn->d + bn->top, 0, (words - bn->top) * sizeof(BN_ULONG));
+ bn->top = words;
+ return 1;
+ }
+
+ // All words beyond the new width must be zero.
+ if (!bn_fits_in_words(bn, words)) {
+ OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
+ return 0;
}
+ bn->top = words;
+ return 1;
+}
+
+int bn_minimal_width(const BIGNUM *bn) {
+ int ret = bn->top;
+ while (ret > 0 && bn->d[ret - 1] == 0) {
+ ret--;
+ }
+ return ret;
+}
+void bn_correct_top(BIGNUM *bn) {
+ bn->top = bn_minimal_width(bn);
if (bn->top == 0) {
bn->neg = 0;
}
diff --git a/src/crypto/fipsmodule/bn/bn_test.cc b/src/crypto/fipsmodule/bn/bn_test.cc
index ca5f978d..f36656f6 100644
--- a/src/crypto/fipsmodule/bn/bn_test.cc
+++ b/src/crypto/fipsmodule/bn/bn_test.cc
@@ -387,15 +387,15 @@ static void TestSquare(FileTest *t, BN_CTX *ctx) {
}
#if !defined(BORINGSSL_SHARED_LIBRARY)
- if (static_cast<size_t>(a->top) <= BN_SMALL_MAX_WORDS) {
- for (size_t num_a = a->top; num_a <= BN_SMALL_MAX_WORDS; num_a++) {
+ int a_width = bn_minimal_width(a.get());
+ if (a_width <= BN_SMALL_MAX_WORDS) {
+ for (size_t num_a = a_width; num_a <= BN_SMALL_MAX_WORDS; num_a++) {
SCOPED_TRACE(num_a);
size_t num_r = 2 * num_a;
// Use newly-allocated buffers so ASan will catch out-of-bounds writes.
std::unique_ptr<BN_ULONG[]> a_words(new BN_ULONG[num_a]),
r_words(new BN_ULONG[num_r]);
- OPENSSL_memset(a_words.get(), 0, num_a * sizeof(BN_ULONG));
- OPENSSL_memcpy(a_words.get(), a->d, a->top * sizeof(BN_ULONG));
+ ASSERT_TRUE(bn_copy_words(a_words.get(), num_a, a.get()));
ASSERT_TRUE(bn_mul_small(r_words.get(), num_r, a_words.get(), num_a,
a_words.get(), num_a));
@@ -445,22 +445,25 @@ static void TestProduct(FileTest *t, BN_CTX *ctx) {
}
#if !defined(BORINGSSL_SHARED_LIBRARY)
- if (!BN_is_negative(product.get()) &&
- static_cast<size_t>(a->top) <= BN_SMALL_MAX_WORDS &&
- static_cast<size_t>(b->top) <= BN_SMALL_MAX_WORDS) {
- for (size_t num_a = a->top; num_a <= BN_SMALL_MAX_WORDS; num_a++) {
+ BN_set_negative(a.get(), 0);
+ BN_set_negative(b.get(), 0);
+ BN_set_negative(product.get(), 0);
+
+ int a_width = bn_minimal_width(a.get());
+ int b_width = bn_minimal_width(b.get());
+ if (a_width <= BN_SMALL_MAX_WORDS && b_width <= BN_SMALL_MAX_WORDS) {
+ for (size_t num_a = static_cast<size_t>(a_width);
+ num_a <= BN_SMALL_MAX_WORDS; num_a++) {
SCOPED_TRACE(num_a);
- for (size_t num_b = b->top; num_b <= BN_SMALL_MAX_WORDS; num_b++) {
+ for (size_t num_b = static_cast<size_t>(b_width);
+ num_b <= BN_SMALL_MAX_WORDS; num_b++) {
SCOPED_TRACE(num_b);
size_t num_r = num_a + num_b;
// Use newly-allocated buffers so ASan will catch out-of-bounds writes.
std::unique_ptr<BN_ULONG[]> a_words(new BN_ULONG[num_a]),
b_words(new BN_ULONG[num_b]), r_words(new BN_ULONG[num_r]);
- OPENSSL_memset(a_words.get(), 0, num_a * sizeof(BN_ULONG));
- OPENSSL_memcpy(a_words.get(), a->d, a->top * sizeof(BN_ULONG));
-
- OPENSSL_memset(b_words.get(), 0, num_b * sizeof(BN_ULONG));
- OPENSSL_memcpy(b_words.get(), b->d, b->top * sizeof(BN_ULONG));
+ ASSERT_TRUE(bn_copy_words(a_words.get(), num_a, a.get()));
+ ASSERT_TRUE(bn_copy_words(b_words.get(), num_b, b.get()));
ASSERT_TRUE(bn_mul_small(r_words.get(), num_r, a_words.get(), num_a,
b_words.get(), num_b));
@@ -537,12 +540,12 @@ static void TestModMul(FileTest *t, BN_CTX *ctx) {
if (BN_is_odd(m.get())) {
// Reduce |a| and |b| and test the Montgomery version.
- bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
+ bssl::UniquePtr<BN_MONT_CTX> mont(
+ BN_MONT_CTX_new_for_modulus(m.get(), ctx));
bssl::UniquePtr<BIGNUM> a_tmp(BN_new()), b_tmp(BN_new());
ASSERT_TRUE(mont);
ASSERT_TRUE(a_tmp);
ASSERT_TRUE(b_tmp);
- ASSERT_TRUE(BN_MONT_CTX_set(mont.get(), m.get(), ctx));
ASSERT_TRUE(BN_nnmod(a.get(), a.get(), m.get(), ctx));
ASSERT_TRUE(BN_nnmod(b.get(), b.get(), m.get(), ctx));
ASSERT_TRUE(BN_to_montgomery(a_tmp.get(), a.get(), mont.get(), ctx));
@@ -554,24 +557,23 @@ static void TestModMul(FileTest *t, BN_CTX *ctx) {
ret.get());
#if !defined(BORINGSSL_SHARED_LIBRARY)
- if (m->top <= BN_SMALL_MAX_WORDS) {
- std::unique_ptr<BN_ULONG[]> a_words(new BN_ULONG[m->top]),
- b_words(new BN_ULONG[m->top]), r_words(new BN_ULONG[m->top]);
- OPENSSL_memset(a_words.get(), 0, m->top * sizeof(BN_ULONG));
- OPENSSL_memcpy(a_words.get(), a->d, a->top * sizeof(BN_ULONG));
- OPENSSL_memset(b_words.get(), 0, m->top * sizeof(BN_ULONG));
- OPENSSL_memcpy(b_words.get(), b->d, b->top * sizeof(BN_ULONG));
- ASSERT_TRUE(bn_to_montgomery_small(a_words.get(), m->top, a_words.get(),
- m->top, mont.get()));
- ASSERT_TRUE(bn_to_montgomery_small(b_words.get(), m->top, b_words.get(),
- m->top, mont.get()));
+ size_t m_width = static_cast<size_t>(bn_minimal_width(m.get()));
+ if (m_width <= BN_SMALL_MAX_WORDS) {
+ std::unique_ptr<BN_ULONG[]> a_words(new BN_ULONG[m_width]),
+ b_words(new BN_ULONG[m_width]), r_words(new BN_ULONG[m_width]);
+ ASSERT_TRUE(bn_copy_words(a_words.get(), m_width, a.get()));
+ ASSERT_TRUE(bn_copy_words(b_words.get(), m_width, b.get()));
+ ASSERT_TRUE(bn_to_montgomery_small(a_words.get(), m_width, a_words.get(),
+ m_width, mont.get()));
+ ASSERT_TRUE(bn_to_montgomery_small(b_words.get(), m_width, b_words.get(),
+ m_width, mont.get()));
ASSERT_TRUE(bn_mod_mul_montgomery_small(
- r_words.get(), m->top, a_words.get(), m->top, b_words.get(), m->top,
+ r_words.get(), m_width, a_words.get(), m_width, b_words.get(), m_width,
mont.get()));
// Use the second half of |tmp| so ASan will catch out-of-bounds writes.
- ASSERT_TRUE(bn_from_montgomery_small(r_words.get(), m->top, r_words.get(),
- m->top, mont.get()));
- ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m->top));
+ ASSERT_TRUE(bn_from_montgomery_small(r_words.get(), m_width, r_words.get(),
+ m_width, mont.get()));
+ ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A * B (mod M) (Montgomery, words)", mod_mul.get(),
ret.get());
}
@@ -601,11 +603,11 @@ static void TestModSquare(FileTest *t, BN_CTX *ctx) {
if (BN_is_odd(m.get())) {
// Reduce |a| and test the Montgomery version.
- bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
+ bssl::UniquePtr<BN_MONT_CTX> mont(
+ BN_MONT_CTX_new_for_modulus(m.get(), ctx));
bssl::UniquePtr<BIGNUM> a_tmp(BN_new());
ASSERT_TRUE(mont);
ASSERT_TRUE(a_tmp);
- ASSERT_TRUE(BN_MONT_CTX_set(mont.get(), m.get(), ctx));
ASSERT_TRUE(BN_nnmod(a.get(), a.get(), m.get(), ctx));
ASSERT_TRUE(BN_to_montgomery(a_tmp.get(), a.get(), mont.get(), ctx));
ASSERT_TRUE(BN_mod_mul_montgomery(ret.get(), a_tmp.get(), a_tmp.get(),
@@ -623,32 +625,32 @@ static void TestModSquare(FileTest *t, BN_CTX *ctx) {
ret.get());
#if !defined(BORINGSSL_SHARED_LIBRARY)
- if (m->top <= BN_SMALL_MAX_WORDS) {
- std::unique_ptr<BN_ULONG[]> a_words(new BN_ULONG[m->top]),
- a_copy_words(new BN_ULONG[m->top]), r_words(new BN_ULONG[m->top]);
- OPENSSL_memset(a_words.get(), 0, m->top * sizeof(BN_ULONG));
- OPENSSL_memcpy(a_words.get(), a->d, a->top * sizeof(BN_ULONG));
- ASSERT_TRUE(bn_to_montgomery_small(a_words.get(), m->top, a_words.get(),
- m->top, mont.get()));
+ size_t m_width = static_cast<size_t>(bn_minimal_width(m.get()));
+ if (m_width <= BN_SMALL_MAX_WORDS) {
+ std::unique_ptr<BN_ULONG[]> a_words(new BN_ULONG[m_width]),
+ a_copy_words(new BN_ULONG[m_width]), r_words(new BN_ULONG[m_width]);
+ ASSERT_TRUE(bn_copy_words(a_words.get(), m_width, a.get()));
+ ASSERT_TRUE(bn_to_montgomery_small(a_words.get(), m_width, a_words.get(),
+ m_width, mont.get()));
ASSERT_TRUE(bn_mod_mul_montgomery_small(
- r_words.get(), m->top, a_words.get(), m->top, a_words.get(), m->top,
- mont.get()));
- ASSERT_TRUE(bn_from_montgomery_small(r_words.get(), m->top, r_words.get(),
- m->top, mont.get()));
- ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m->top));
+ r_words.get(), m_width, a_words.get(), m_width, a_words.get(),
+ m_width, mont.get()));
+ ASSERT_TRUE(bn_from_montgomery_small(r_words.get(), m_width,
+ r_words.get(), m_width, mont.get()));
+ ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A * A (mod M) (Montgomery, words)",
mod_square.get(), ret.get());
// Repeat the operation with |a_copy_words|.
OPENSSL_memcpy(a_copy_words.get(), a_words.get(),
- m->top * sizeof(BN_ULONG));
+ m_width * sizeof(BN_ULONG));
ASSERT_TRUE(bn_mod_mul_montgomery_small(
- r_words.get(), m->top, a_words.get(), m->top, a_copy_words.get(),
- m->top, mont.get()));
+ r_words.get(), m_width, a_words.get(), m_width, a_copy_words.get(),
+ m_width, mont.get()));
// Use the second half of |tmp| so ASan will catch out-of-bounds writes.
- ASSERT_TRUE(bn_from_montgomery_small(r_words.get(), m->top, r_words.get(),
- m->top, mont.get()));
- ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m->top));
+ ASSERT_TRUE(bn_from_montgomery_small(r_words.get(), m_width,
+ r_words.get(), m_width, mont.get()));
+ ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A * A_copy (mod M) (Montgomery, words)",
mod_square.get(), ret.get());
}
@@ -683,22 +685,22 @@ static void TestModExp(FileTest *t, BN_CTX *ctx) {
ret.get());
#if !defined(BORINGSSL_SHARED_LIBRARY)
- if (m->top <= BN_SMALL_MAX_WORDS) {
- bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
+ size_t m_width = static_cast<size_t>(bn_minimal_width(m.get()));
+ if (m_width <= BN_SMALL_MAX_WORDS) {
+ bssl::UniquePtr<BN_MONT_CTX> mont(
+ BN_MONT_CTX_new_for_modulus(m.get(), ctx));
ASSERT_TRUE(mont.get());
- ASSERT_TRUE(BN_MONT_CTX_set(mont.get(), m.get(), ctx));
ASSERT_TRUE(BN_nnmod(a.get(), a.get(), m.get(), ctx));
- std::unique_ptr<BN_ULONG[]> r_words(new BN_ULONG[m->top]),
- a_words(new BN_ULONG[m->top]);
- OPENSSL_memset(a_words.get(), 0, m->top * sizeof(BN_ULONG));
- OPENSSL_memcpy(a_words.get(), a->d, a->top * sizeof(BN_ULONG));
- ASSERT_TRUE(bn_to_montgomery_small(a_words.get(), m->top, a_words.get(),
- m->top, mont.get()));
- ASSERT_TRUE(bn_mod_exp_mont_small(r_words.get(), m->top, a_words.get(),
- m->top, e->d, e->top, mont.get()));
- ASSERT_TRUE(bn_from_montgomery_small(r_words.get(), m->top, r_words.get(),
- m->top, mont.get()));
- ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m->top));
+ std::unique_ptr<BN_ULONG[]> r_words(new BN_ULONG[m_width]),
+ a_words(new BN_ULONG[m_width]);
+ ASSERT_TRUE(bn_copy_words(a_words.get(), m_width, a.get()));
+ ASSERT_TRUE(bn_to_montgomery_small(a_words.get(), m_width, a_words.get(),
+ m_width, mont.get()));
+ ASSERT_TRUE(bn_mod_exp_mont_small(r_words.get(), m_width, a_words.get(),
+ m_width, e->d, e->top, mont.get()));
+ ASSERT_TRUE(bn_from_montgomery_small(r_words.get(), m_width,
+ r_words.get(), m_width, mont.get()));
+ ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
EXPECT_BIGNUMS_EQUAL("A ^ E (mod M) (Montgomery, words)", mod_exp.get(),
ret.get());
}
@@ -862,6 +864,17 @@ TEST_F(BNTest, BN2BinPadded) {
EXPECT_EQ(Bytes(zeros, sizeof(out) - bytes),
Bytes(out, sizeof(out) - bytes));
EXPECT_EQ(Bytes(reference, bytes), Bytes(out + sizeof(out) - bytes, bytes));
+
+#if !defined(BORINGSSL_SHARED_LIBRARY)
+ // Repeat some tests with a non-minimal |BIGNUM|.
+ EXPECT_TRUE(bn_resize_words(n.get(), 32));
+
+ EXPECT_FALSE(BN_bn2bin_padded(out, bytes - 1, n.get()));
+
+ ASSERT_TRUE(BN_bn2bin_padded(out, bytes + 1, n.get()));
+ EXPECT_EQ(0u, out[0]);
+ EXPECT_EQ(Bytes(reference, bytes), Bytes(out + 1, bytes));
+#endif
}
}
@@ -1267,11 +1280,9 @@ TEST_F(BNTest, BadModulus) {
bssl::UniquePtr<BIGNUM> a(BN_new());
bssl::UniquePtr<BIGNUM> b(BN_new());
bssl::UniquePtr<BIGNUM> zero(BN_new());
- bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
ASSERT_TRUE(a);
ASSERT_TRUE(b);
ASSERT_TRUE(zero);
- ASSERT_TRUE(mont);
BN_zero(zero.get());
@@ -1294,13 +1305,16 @@ TEST_F(BNTest, BadModulus) {
a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx(), nullptr));
ERR_clear_error();
- EXPECT_FALSE(BN_MONT_CTX_set(mont.get(), zero.get(), ctx()));
+ bssl::UniquePtr<BN_MONT_CTX> mont(
+ BN_MONT_CTX_new_for_modulus(zero.get(), ctx()));
+ EXPECT_FALSE(mont);
ERR_clear_error();
// Some operations also may not be used with an even modulus.
ASSERT_TRUE(BN_set_word(b.get(), 16));
- EXPECT_FALSE(BN_MONT_CTX_set(mont.get(), b.get(), ctx()));
+ mont.reset(BN_MONT_CTX_new_for_modulus(b.get(), ctx()));
+ EXPECT_FALSE(mont);
ERR_clear_error();
EXPECT_FALSE(BN_mod_exp_mont(a.get(), BN_value_one(), BN_value_one(), b.get(),
@@ -1883,4 +1897,100 @@ TEST_F(BNTest, LessThanWords) {
EXPECT_EQ(0, bn_less_than_words(NULL, NULL, 0));
EXPECT_EQ(0, bn_in_range_words(NULL, 0, NULL, 0));
}
+
+TEST_F(BNTest, NonMinimal) {
+ bssl::UniquePtr<BIGNUM> ten(BN_new());
+ ASSERT_TRUE(ten);
+ ASSERT_TRUE(BN_set_word(ten.get(), 10));
+
+ bssl::UniquePtr<BIGNUM> ten_copy(BN_dup(ten.get()));
+ ASSERT_TRUE(ten_copy);
+
+ bssl::UniquePtr<BIGNUM> eight(BN_new());
+ ASSERT_TRUE(eight);
+ ASSERT_TRUE(BN_set_word(eight.get(), 8));
+
+ bssl::UniquePtr<BIGNUM> forty_two(BN_new());
+ ASSERT_TRUE(forty_two);
+ ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
+
+ bssl::UniquePtr<BIGNUM> two_exp_256(BN_new());
+ ASSERT_TRUE(two_exp_256);
+ ASSERT_TRUE(BN_lshift(two_exp_256.get(), BN_value_one(), 256));
+
+ // Check some comparison functions on |ten| before and after expanding.
+ for (size_t width = 1; width < 10; width++) {
+ SCOPED_TRACE(width);
+ // Make a wider version of |ten|.
+ EXPECT_TRUE(bn_resize_words(ten.get(), width));
+ EXPECT_EQ(static_cast<int>(width), ten->top);
+
+ EXPECT_TRUE(BN_abs_is_word(ten.get(), 10));
+ EXPECT_TRUE(BN_is_word(ten.get(), 10));
+ EXPECT_EQ(10u, BN_get_word(ten.get()));
+ uint64_t v;
+ ASSERT_TRUE(BN_get_u64(ten.get(), &v));
+ EXPECT_EQ(10u, v);
+
+ EXPECT_TRUE(BN_equal_consttime(ten.get(), ten_copy.get()));
+ EXPECT_TRUE(BN_equal_consttime(ten_copy.get(), ten.get()));
+ EXPECT_FALSE(BN_less_than_consttime(ten.get(), ten_copy.get()));
+ EXPECT_FALSE(BN_less_than_consttime(ten_copy.get(), ten.get()));
+ EXPECT_EQ(BN_cmp(ten.get(), ten_copy.get()), 0);
+
+ EXPECT_FALSE(BN_equal_consttime(ten.get(), eight.get()));
+ EXPECT_FALSE(BN_less_than_consttime(ten.get(), eight.get()));
+ EXPECT_TRUE(BN_less_than_consttime(eight.get(), ten.get()));
+ EXPECT_LT(BN_cmp(eight.get(), ten.get()), 0);
+
+ EXPECT_FALSE(BN_equal_consttime(ten.get(), forty_two.get()));
+ EXPECT_TRUE(BN_less_than_consttime(ten.get(), forty_two.get()));
+ EXPECT_FALSE(BN_less_than_consttime(forty_two.get(), ten.get()));
+ EXPECT_GT(BN_cmp(forty_two.get(), ten.get()), 0);
+
+ EXPECT_FALSE(BN_equal_consttime(ten.get(), two_exp_256.get()));
+ EXPECT_TRUE(BN_less_than_consttime(ten.get(), two_exp_256.get()));
+ EXPECT_FALSE(BN_less_than_consttime(two_exp_256.get(), ten.get()));
+ EXPECT_GT(BN_cmp(two_exp_256.get(), ten.get()), 0);
+
+ EXPECT_EQ(4u, BN_num_bits(ten.get()));
+ EXPECT_EQ(1u, BN_num_bytes(ten.get()));
+ EXPECT_FALSE(BN_is_pow2(ten.get()));
+ }
+
+ // |ten| may be resized back down to one word.
+ EXPECT_TRUE(bn_resize_words(ten.get(), 1));
+ EXPECT_EQ(1, ten->top);
+
+ // But not to zero words, which it does not fit.
+ EXPECT_FALSE(bn_resize_words(ten.get(), 0));
+
+ EXPECT_TRUE(BN_is_pow2(eight.get()));
+ EXPECT_TRUE(bn_resize_words(eight.get(), 4));
+ EXPECT_EQ(4, eight->top);
+ EXPECT_TRUE(BN_is_pow2(eight.get()));
+
+ // |BN_MONT_CTX| is always stored minimally and uses the same R independent of
+ // input width.
+ static const uint8_t kP[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
+ ASSERT_TRUE(p);
+
+ bssl::UniquePtr<BN_MONT_CTX> mont(
+ BN_MONT_CTX_new_for_modulus(p.get(), ctx()));
+ ASSERT_TRUE(mont);
+
+ ASSERT_TRUE(bn_resize_words(p.get(), 32));
+ bssl::UniquePtr<BN_MONT_CTX> mont2(
+ BN_MONT_CTX_new_for_modulus(p.get(), ctx()));
+ ASSERT_TRUE(mont2);
+
+ EXPECT_EQ(mont->N.top, mont2->N.top);
+ EXPECT_EQ(0, BN_cmp(&mont->RR, &mont2->RR));
+}
+
#endif // !BORINGSSL_SHARED_LIBRARY
diff --git a/src/crypto/fipsmodule/bn/bytes.c b/src/crypto/fipsmodule/bn/bytes.c
index 328d56e7..aa654835 100644
--- a/src/crypto/fipsmodule/bn/bytes.c
+++ b/src/crypto/fipsmodule/bn/bytes.c
@@ -159,22 +159,9 @@ size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
return n;
}
-int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
- // If we don't have enough space, fail out.
- size_t num_bytes = BN_num_bytes(in);
- if (len < num_bytes) {
- return 0;
- }
-
- // We only support little-endian platforms, so we can simply memcpy into the
- // internal representation.
- OPENSSL_memcpy(out, in->d, num_bytes);
-
- // Pad out the rest of the buffer with zeroes.
- OPENSSL_memset(out + num_bytes, 0, len - num_bytes);
-
- return 1;
-}
+// TODO(davidben): This does not need to be quite so complex once the |BIGNUM|s
+// we care about are fixed-width. |read_word_padded| is a hack to paper over
+// parts of the |bn_correct_top| leak. Fix that, and this can be simpler.
// constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
// behavior is undefined if |v| takes any other value.
@@ -197,6 +184,10 @@ static int constant_time_le_size_t(size_t x, size_t y) {
// the access would be out of bounds, it reads the last word of |in|. |in| must
// not be zero.
static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
+ if (in->dmax == 0) {
+ return 0;
+ }
+
// Read |in->d[i]| if valid. Otherwise, read the last word.
BN_ULONG l = in->d[constant_time_select_ulong(
constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
@@ -205,24 +196,45 @@ static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l);
}
-int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
- // Special case for |in| = 0. Just branch as the probability is negligible.
- if (BN_is_zero(in)) {
- OPENSSL_memset(out, 0, len);
- return 1;
+static int fits_in_bytes(const BIGNUM *in, size_t len) {
+ BN_ULONG mask = 0;
+ for (size_t i = (len + (BN_BYTES - 1)) / BN_BYTES; i < (size_t)in->top; i++) {
+ mask |= in->d[i];
}
+ if ((len % BN_BYTES) != 0) {
+ BN_ULONG l = read_word_padded(in, len / BN_BYTES);
+ mask |= l >> (8 * (len % BN_BYTES));
+ }
+ return mask == 0;
+}
+int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
+ // If we don't have enough space, fail out.
+ if (!fits_in_bytes(in, len)) {
+ return 0;
+ }
+
+ size_t todo = in->top * BN_BYTES;
+ if (todo > len) {
+ todo = len;
+ }
+
+ // We only support little-endian platforms, so we can simply memcpy into the
+ // internal representation.
+ OPENSSL_memcpy(out, in->d, todo);
+
+ // Pad out the rest of the buffer with zeroes.
+ OPENSSL_memset(out + todo, 0, len - todo);
+
+ return 1;
+}
+
+int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
// Check if the integer is too big. This case can exit early in non-constant
// time.
- if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) {
+ if (!fits_in_bytes(in, len)) {
return 0;
}
- if ((len % BN_BYTES) != 0) {
- BN_ULONG l = read_word_padded(in, len / BN_BYTES);
- if (l >> (8 * (len % BN_BYTES)) != 0) {
- return 0;
- }
- }
// Write the bytes out one by one. Serialization is done without branching on
// the bits of |in| or on |in->top|, but if the routine would otherwise read
@@ -240,7 +252,7 @@ int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
}
BN_ULONG BN_get_word(const BIGNUM *bn) {
- switch (bn->top) {
+ switch (bn_minimal_width(bn)) {
case 0:
return 0;
case 1:
@@ -251,7 +263,7 @@ BN_ULONG BN_get_word(const BIGNUM *bn) {
}
int BN_get_u64(const BIGNUM *bn, uint64_t *out) {
- switch (bn->top) {
+ switch (bn_minimal_width(bn)) {
case 0:
*out = 0;
return 1;
diff --git a/src/crypto/fipsmodule/bn/cmp.c b/src/crypto/fipsmodule/bn/cmp.c
index acc017ff..265c8526 100644
--- a/src/crypto/fipsmodule/bn/cmp.c
+++ b/src/crypto/fipsmodule/bn/cmp.c
@@ -64,19 +64,18 @@
int BN_ucmp(const BIGNUM *a, const BIGNUM *b) {
- int i;
- BN_ULONG t1, t2, *ap, *bp;
-
- i = a->top - b->top;
+ int a_width = bn_minimal_width(a);
+ int b_width = bn_minimal_width(b);
+ int i = a_width - b_width;
if (i != 0) {
return i;
}
- ap = a->d;
- bp = b->d;
- for (i = a->top - 1; i >= 0; i--) {
- t1 = ap[i];
- t2 = bp[i];
+ const BN_ULONG *ap = a->d;
+ const BN_ULONG *bp = b->d;
+ for (i = a_width - 1; i >= 0; i--) {
+ BN_ULONG t1 = ap[i];
+ BN_ULONG t2 = bp[i];
if (t1 != t2) {
return (t1 > t2) ? 1 : -1;
}
@@ -114,14 +113,16 @@ int BN_cmp(const BIGNUM *a, const BIGNUM *b) {
lt = 1;
}
- if (a->top > b->top) {
+ int a_width = bn_minimal_width(a);
+ int b_width = bn_minimal_width(b);
+ if (a_width > b_width) {
return gt;
}
- if (a->top < b->top) {
+ if (a_width < b_width) {
return lt;
}
- for (i = a->top - 1; i >= 0; i--) {
+ for (i = a_width - 1; i >= 0; i--) {
t1 = a->d[i];
t2 = b->d[i];
if (t1 > t2) {
@@ -176,21 +177,43 @@ int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl) {
return bn_cmp_words(a, b, cl);
}
-int bn_less_than_words(const BN_ULONG *a, const BN_ULONG *b, size_t len) {
+static int bn_less_than_words_impl(const BN_ULONG *a, size_t a_len,
+ const BN_ULONG *b, size_t b_len) {
OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t),
crypto_word_t_too_small);
int ret = 0;
- // Process the words in little-endian order.
- for (size_t i = 0; i < len; i++) {
+ // Process the common words in little-endian order.
+ size_t min = a_len < b_len ? a_len : b_len;
+ for (size_t i = 0; i < min; i++) {
crypto_word_t eq = constant_time_eq_w(a[i], b[i]);
crypto_word_t lt = constant_time_lt_w(a[i], b[i]);
ret = constant_time_select_int(eq, ret, constant_time_select_int(lt, 1, 0));
}
+
+ // If |a| or |b| has non-zero words beyond |min|, they take precedence.
+ if (a_len < b_len) {
+ crypto_word_t mask = 0;
+ for (size_t i = a_len; i < b_len; i++) {
+ mask |= b[i];
+ }
+ ret = constant_time_select_int(constant_time_is_zero_w(mask), ret, 1);
+ } else if (b_len < a_len) {
+ crypto_word_t mask = 0;
+ for (size_t i = b_len; i < a_len; i++) {
+ mask |= a[i];
+ }
+ ret = constant_time_select_int(constant_time_is_zero_w(mask), ret, 0);
+ }
+
return ret;
}
+int bn_less_than_words(const BN_ULONG *a, const BN_ULONG *b, size_t len) {
+ return bn_less_than_words_impl(a, len, b, len);
+}
+
int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w) {
- switch (bn->top) {
+ switch (bn_minimal_width(bn)) {
case 1:
return bn->d[0] == w;
case 0:
@@ -212,7 +235,7 @@ int BN_cmp_word(const BIGNUM *a, BN_ULONG b) {
}
int BN_is_zero(const BIGNUM *bn) {
- return bn->top == 0;
+ return bn_minimal_width(bn) == 0;
}
int BN_is_one(const BIGNUM *bn) {
@@ -228,27 +251,52 @@ int BN_is_odd(const BIGNUM *bn) {
}
int BN_is_pow2(const BIGNUM *bn) {
- if (bn->top == 0 || bn->neg) {
+ int width = bn_minimal_width(bn);
+ if (width == 0 || bn->neg) {
return 0;
}
- for (int i = 0; i < bn->top - 1; i++) {
+ for (int i = 0; i < width - 1; i++) {
if (bn->d[i] != 0) {
return 0;
}
}
- return 0 == (bn->d[bn->top-1] & (bn->d[bn->top-1] - 1));
+ return 0 == (bn->d[width-1] & (bn->d[width-1] - 1));
}
int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) {
- if (a->top != b->top) {
- return 0;
+ BN_ULONG mask = 0;
+ // If |a| or |b| has more words than the other, all those words must be zero.
+ for (int i = a->top; i < b->top; i++) {
+ mask |= b->d[i];
}
+ for (int i = b->top; i < a->top; i++) {
+ mask |= a->d[i];
+ }
+ // Common words must match.
+ int min = a->top < b->top ? a->top : b->top;
+ for (int i = 0; i < min; i++) {
+ mask |= (a->d[i] ^ b->d[i]);
+ }
+ // The sign bit must match.
+ mask |= (a->neg ^ b->neg);
+ return mask == 0;
+}
- int limbs_are_equal =
- CRYPTO_memcmp(a->d, b->d, (size_t)a->top * sizeof(a->d[0])) == 0;
-
- return constant_time_select_int(constant_time_eq_int(a->neg, b->neg),
- limbs_are_equal, 0);
+int BN_less_than_consttime(const BIGNUM *a, const BIGNUM *b) {
+ // We do not attempt to process the sign bit in constant time. Negative
+ // |BIGNUM|s should never occur in crypto, only calculators.
+ if (a->neg && !b->neg) {
+ return 1;
+ }
+ if (b->neg && !a->neg) {
+ return 0;
+ }
+ if (a->neg && b->neg) {
+ const BIGNUM *tmp = a;
+ a = b;
+ b = tmp;
+ }
+ return bn_less_than_words_impl(a->d, a->top, b->d, b->top);
}
diff --git a/src/crypto/fipsmodule/bn/exponentiation.c b/src/crypto/fipsmodule/bn/exponentiation.c
index 63c1c050..9e0ddfbb 100644
--- a/src/crypto/fipsmodule/bn/exponentiation.c
+++ b/src/crypto/fipsmodule/bn/exponentiation.c
@@ -622,8 +622,8 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
// Allocate a montgomery context if it was not supplied by the caller.
if (mont == NULL) {
- new_mont = BN_MONT_CTX_new();
- if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
+ new_mont = BN_MONT_CTX_new_for_modulus(m, ctx);
+ if (new_mont == NULL) {
goto err;
}
mont = new_mont;
@@ -666,22 +666,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
}
- // Set |r| to one in Montgomery form. If the high bit of |m| is set, |m| is
- // close to R and we subtract rather than perform Montgomery reduction.
- if (m->d[m->top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
- if (!bn_wexpand(r, m->top)) {
- goto err;
- }
- // r = 2^(top*BN_BITS2) - m
- r->d[0] = 0 - m->d[0];
- for (int i = 1; i < m->top; i++) {
- r->d[i] = ~m->d[i];
- }
- r->top = m->top;
- // The upper words will be zero if the corresponding words of |m| were
- // 0xfff[...], so call |bn_correct_top|.
- bn_correct_top(r);
- } else if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) {
+ if (!bn_one_to_montgomery(r, mont, ctx)) {
goto err;
}
@@ -746,7 +731,6 @@ err:
int bn_mod_exp_mont_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_ULONG *p, size_t num_p,
const BN_MONT_CTX *mont) {
- const BN_ULONG *n = mont->N.d;
size_t num_n = mont->N.top;
if (num_n != num_a || num_n != num_r || num_n > BN_SMALL_MAX_WORDS) {
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
@@ -793,16 +777,7 @@ int bn_mod_exp_mont_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
}
}
- // Set |r| to one in Montgomery form. If the high bit of |m| is set, |m| is
- // close to R and we subtract rather than perform Montgomery reduction.
- if (n[num_n - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
- // r = 2^(top*BN_BITS2) - m
- r[0] = 0 - n[0];
- for (size_t i = 1; i < num_n; i++) {
- r[i] = ~n[i];
- }
- } else if (!bn_from_montgomery_small(r, num_r, mont->RR.d, mont->RR.top,
- mont)) {
+ if (!bn_one_to_montgomery_small(r, num_r, mont)) {
goto err;
}
@@ -1039,8 +1014,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
// Allocate a montgomery context if it was not supplied by the caller.
if (mont == NULL) {
- new_mont = BN_MONT_CTX_new();
- if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
+ new_mont = BN_MONT_CTX_new_for_modulus(m, ctx);
+ if (new_mont == NULL) {
goto err;
}
mont = new_mont;
@@ -1118,16 +1093,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
tmp.neg = am.neg = 0;
tmp.flags = am.flags = BN_FLG_STATIC_DATA;
-// prepare a^0 in Montgomery domain
-// by Shay Gueron's suggestion
- if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
- // 2^(top*BN_BITS2) - m
- tmp.d[0] = 0 - m->d[0];
- for (i = 1; i < top; i++) {
- tmp.d[i] = ~m->d[i];
- }
- tmp.top = top;
- } else if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx)) {
+ if (!bn_one_to_montgomery(&tmp, mont, ctx)) {
goto err;
}
@@ -1365,8 +1331,8 @@ int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
// Allocate a montgomery context if it was not supplied by the caller.
if (mont == NULL) {
- new_mont = BN_MONT_CTX_new();
- if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
+ new_mont = BN_MONT_CTX_new_for_modulus(m, ctx);
+ if (new_mont == NULL) {
goto err;
}
mont = new_mont;
diff --git a/src/crypto/fipsmodule/bn/internal.h b/src/crypto/fipsmodule/bn/internal.h
index 706e544d..f3b8d8ad 100644
--- a/src/crypto/fipsmodule/bn/internal.h
+++ b/src/crypto/fipsmodule/bn/internal.h
@@ -197,8 +197,12 @@ extern "C" {
#define Hw(t) ((BN_ULONG)((t) >> BN_BITS2))
#endif
-// bn_correct_top decrements |bn->top| until |bn->d[top-1]| is non-zero or
-// until |top| is zero. If |bn| is zero, |bn->neg| is set to zero.
+// bn_minimal_width returns the minimal value of |bn->top| which fits the
+// value of |bn|.
+int bn_minimal_width(const BIGNUM *bn);
+
+// bn_correct_top decrements |bn->top| to |bn_minimal_width|. If |bn| is zero,
+// |bn->neg| is set to zero.
void bn_correct_top(BIGNUM *bn);
// bn_wexpand ensures that |bn| has at least |words| works of space without
@@ -210,10 +214,26 @@ int bn_wexpand(BIGNUM *bn, size_t words);
// than a number of words.
int bn_expand(BIGNUM *bn, size_t bits);
+// bn_resize_words adjusts |bn->top| to be |words|. It returns one on success
+// and zero on allocation error or if |bn|'s value is too large.
+//
+// Do not call this function outside of unit tests. Most functions currently
+// require |BIGNUM|s be minimal. This function breaks that invariant. It is
+// introduced early so the invariant may be relaxed incrementally.
+int bn_resize_words(BIGNUM *bn, size_t words);
+
// bn_set_words sets |bn| to the value encoded in the |num| words in |words|,
// least significant word first.
int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num);
+// bn_fits_in_words returns one if |bn| may be represented in |num| words, plus
+// a sign bit, and zero otherwise.
+int bn_fits_in_words(const BIGNUM *bn, size_t num);
+
+// bn_copy_words copies the value of |bn| to |out| and returns one if the value
+// is representable in |num| words. Otherwise, it returns zero.
+int bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn);
+
// bn_mul_add_words multiples |ap| by |w|, adds the result to |rp|, and places
// the result in |rp|. |ap| and |rp| must both be |num| words long. It returns
// the carry word of the operation. |ap| and |rp| may be equal but otherwise may
@@ -326,6 +346,15 @@ int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
// otherwise.
int bn_is_bit_set_words(const BN_ULONG *a, size_t num, unsigned bit);
+// bn_one_to_montgomery sets |r| to one in Montgomery form. It returns one on
+// success and zero on error. This function treats the bit width of the modulus
+// as public.
+int bn_one_to_montgomery(BIGNUM *r, const BN_MONT_CTX *mont, BN_CTX *ctx);
+
+// bn_less_than_montgomery_R returns one if |bn| is less than the Montgomery R
+// value for |mont| and zero otherwise.
+int bn_less_than_montgomery_R(const BIGNUM *bn, const BN_MONT_CTX *mont);
+
// Low-level operations for small numbers.
//
@@ -372,6 +401,13 @@ int bn_to_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
int bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont);
+// bn_one_to_montgomery_small sets |r| to one in Montgomery form. It returns one
+// on success and zero on error. |num_r| must be the length of the modulus,
+// which is |mont->N.top|. This function treats the bit width of the modulus as
+// public.
+int bn_one_to_montgomery_small(BN_ULONG *r, size_t num_r,
+ const BN_MONT_CTX *mont);
+
// bn_mod_mul_montgomery_small sets |r| to |a| * |b| mod |mont->N|. Both inputs
// and outputs are in the Montgomery domain. |num_r| must be the length of the
// modulus, which is |mont->N.top|. This function returns one on success and
diff --git a/src/crypto/fipsmodule/bn/montgomery.c b/src/crypto/fipsmodule/bn/montgomery.c
index e8505dae..a51725c7 100644
--- a/src/crypto/fipsmodule/bn/montgomery.c
+++ b/src/crypto/fipsmodule/bn/montgomery.c
@@ -126,10 +126,6 @@
#define OPENSSL_BN_ASM_MONT
#endif
-static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
- const BIGNUM *b,
- const BN_MONT_CTX *mont, BN_CTX *ctx);
-
BN_MONT_CTX *BN_MONT_CTX_new(void) {
BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
@@ -193,6 +189,10 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
return 0;
}
+ // |mont->N| is always stored minimally. Computing RR efficiently leaks the
+ // size of the modulus. While the modulus may be private in RSA (one of the
+ // primes), their sizes are public, so this is fine.
+ bn_correct_top(&mont->N);
// Find n0 such that n0 * N == -1 (mod r).
//
@@ -200,7 +200,7 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
// others, we could use a shorter R value and use faster |BN_ULONG|-based
// math instead of |uint64_t|-based math, which would be double-precision.
// However, currently only the assembler files know which is which.
- uint64_t n0 = bn_mont_n0(mod);
+ uint64_t n0 = bn_mont_n0(&mont->N);
mont->n0[0] = (BN_ULONG)n0;
#if BN_MONT_CTX_N0_LIMBS == 2
mont->n0[1] = (BN_ULONG)(n0 >> BN_BITS2);
@@ -215,7 +215,7 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
// as |BN_MONT_CTX_N0_LIMBS| is either one or two.
//
// XXX: This is not constant time with respect to |mont->N|, but it should be.
- unsigned lgBigR = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
+ unsigned lgBigR = mont->N.top * BN_BITS2;
if (!bn_mod_exp_base_2_vartime(&mont->RR, lgBigR * 2, &mont->N)) {
return 0;
}
@@ -223,6 +223,16 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
return 1;
}
+BN_MONT_CTX *BN_MONT_CTX_new_for_modulus(const BIGNUM *mod, BN_CTX *ctx) {
+ BN_MONT_CTX *mont = BN_MONT_CTX_new();
+ if (mont == NULL ||
+ !BN_MONT_CTX_set(mont, mod, ctx)) {
+ BN_MONT_CTX_free(mont);
+ return NULL;
+ }
+ return mont;
+}
+
int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
const BIGNUM *mod, BN_CTX *bn_ctx) {
CRYPTO_MUTEX_lock_read(lock);
@@ -234,25 +244,12 @@ int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
}
CRYPTO_MUTEX_lock_write(lock);
- ctx = *pmont;
- if (ctx) {
- goto out;
- }
-
- ctx = BN_MONT_CTX_new();
- if (ctx == NULL) {
- goto out;
+ if (*pmont == NULL) {
+ *pmont = BN_MONT_CTX_new_for_modulus(mod, bn_ctx);
}
- if (!BN_MONT_CTX_set(ctx, mod, bn_ctx)) {
- BN_MONT_CTX_free(ctx);
- ctx = NULL;
- goto out;
- }
- *pmont = ctx;
-
-out:
+ const int ok = *pmont != NULL;
CRYPTO_MUTEX_unlock_write(lock);
- return ctx != NULL;
+ return ok;
}
int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
@@ -304,6 +301,11 @@ static int bn_from_montgomery_in_place(BN_ULONG *r, size_t num_r, BN_ULONG *a,
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
const BN_MONT_CTX *mont) {
+ if (r->neg) {
+ OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
+ return 0;
+ }
+
const BIGNUM *n = &mont->N;
if (n->top == 0) {
ret->top = 0;
@@ -311,21 +313,16 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
}
int max = (2 * n->top); // carry is stored separately
- if (!bn_wexpand(r, max) ||
+ if (!bn_resize_words(r, max) ||
!bn_wexpand(ret, n->top)) {
return 0;
}
- // Clear the top words of |r|.
- if (max > r->top) {
- OPENSSL_memset(r->d + r->top, 0, (max - r->top) * sizeof(BN_ULONG));
- }
- r->top = max;
ret->top = n->top;
if (!bn_from_montgomery_in_place(ret->d, ret->top, r->d, r->top, mont)) {
return 0;
}
- ret->neg = r->neg;
+ ret->neg = 0;
bn_correct_top(r);
bn_correct_top(ret);
@@ -352,35 +349,27 @@ err:
return ret;
}
-int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
- const BN_MONT_CTX *mont, BN_CTX *ctx) {
-#if !defined(OPENSSL_BN_ASM_MONT)
- return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
-#else
- int num = mont->N.top;
-
- // |bn_mul_mont| requires at least 128 bits of limbs, at least for x86.
- if (num < (128 / BN_BITS2) ||
- a->top != num ||
- b->top != num) {
- return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
- }
-
- if (!bn_wexpand(r, num)) {
- return 0;
- }
- if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
- // The check above ensures this won't happen.
- assert(0);
- OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
- return 0;
+int bn_one_to_montgomery(BIGNUM *r, const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ // If the high bit of |n| is set, R = 2^(top*BN_BITS2) < 2 * |n|, so we
+ // compute R - |n| rather than perform Montgomery reduction.
+ const BIGNUM *n = &mont->N;
+ if (n->top > 0 && (n->d[n->top - 1] >> (BN_BITS2 - 1)) != 0) {
+ if (!bn_wexpand(r, n->top)) {
+ return 0;
+ }
+ r->d[0] = 0 - n->d[0];
+ for (int i = 1; i < n->top; i++) {
+ r->d[i] = ~n->d[i];
+ }
+ r->top = n->top;
+ r->neg = 0;
+ // The upper words will be zero if the corresponding words of |n| were
+ // 0xfff[...], so call |bn_correct_top|.
+ bn_correct_top(r);
+ return 1;
}
- r->neg = a->neg ^ b->neg;
- r->top = num;
- bn_correct_top(r);
- return 1;
-#endif
+ return BN_from_montgomery(r, &mont->RR, mont, ctx);
}
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
@@ -417,6 +406,44 @@ err:
return ret;
}
+int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ if (a->neg || b->neg) {
+ OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
+ return 0;
+ }
+
+#if defined(OPENSSL_BN_ASM_MONT)
+ // |bn_mul_mont| requires at least 128 bits of limbs, at least for x86.
+ int num = mont->N.top;
+ if (num >= (128 / BN_BITS2) &&
+ a->top == num &&
+ b->top == num) {
+ if (!bn_wexpand(r, num)) {
+ return 0;
+ }
+ if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
+ // The check above ensures this won't happen.
+ assert(0);
+ OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ r->neg = 0;
+ r->top = num;
+ bn_correct_top(r);
+
+ return 1;
+ }
+#endif
+
+ return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
+}
+
+int bn_less_than_montgomery_R(const BIGNUM *bn, const BN_MONT_CTX *mont) {
+ return !BN_is_negative(bn) &&
+ bn_fits_in_words(bn, mont->N.top);
+}
+
int bn_to_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont) {
return bn_mod_mul_montgomery_small(r, num_r, a, num_a, mont->RR.d,
@@ -439,6 +466,28 @@ int bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
return ret;
}
+int bn_one_to_montgomery_small(BN_ULONG *r, size_t num_r,
+ const BN_MONT_CTX *mont) {
+ const BN_ULONG *n = mont->N.d;
+ size_t num_n = mont->N.top;
+ if (num_n == 0 || num_r != num_n) {
+ OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ // If the high bit of |n| is set, R = 2^(num_n*BN_BITS2) < 2 * |n|, so we
+ // compute R - |n| rather than perform Montgomery reduction.
+ if (num_n > 0 && (n[num_n - 1] >> (BN_BITS2 - 1)) != 0) {
+ r[0] = 0 - n[0];
+ for (size_t i = 1; i < num_n; i++) {
+ r[i] = ~n[i];
+ }
+ return 1;
+ }
+
+ return bn_from_montgomery_small(r, num_r, mont->RR.d, mont->RR.top, mont);
+}
+
int bn_mod_mul_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_ULONG *b, size_t num_b,
const BN_MONT_CTX *mont) {
diff --git a/src/crypto/fipsmodule/bn/prime.c b/src/crypto/fipsmodule/bn/prime.c
index 691d0cba..a291f7a0 100644
--- a/src/crypto/fipsmodule/bn/prime.c
+++ b/src/crypto/fipsmodule/bn/prime.c
@@ -586,9 +586,8 @@ int BN_enhanced_miller_rabin_primality_test(
}
// Montgomery setup for computations mod A
- mont = BN_MONT_CTX_new();
- if (mont == NULL ||
- !BN_MONT_CTX_set(mont, w, ctx)) {
+ mont = BN_MONT_CTX_new_for_modulus(w, ctx);
+ if (mont == NULL) {
goto err;
}
diff --git a/src/crypto/fipsmodule/ec/ec.c b/src/crypto/fipsmodule/ec/ec.c
index c9687a61..616df162 100644
--- a/src/crypto/fipsmodule/ec/ec.c
+++ b/src/crypto/fipsmodule/ec/ec.c
@@ -389,9 +389,8 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
}
BN_MONT_CTX_free(group->order_mont);
- group->order_mont = BN_MONT_CTX_new();
- if (group->order_mont == NULL ||
- !BN_MONT_CTX_set(group->order_mont, &group->order, NULL)) {
+ group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
+ if (group->order_mont == NULL) {
return 0;
}
@@ -448,9 +447,8 @@ static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
goto err;
}
- group->order_mont = BN_MONT_CTX_new();
- if (group->order_mont == NULL ||
- !BN_MONT_CTX_set(group->order_mont, &group->order, ctx)) {
+ group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx);
+ if (group->order_mont == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
goto err;
}
@@ -768,6 +766,9 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
}
if (!EC_POINT_is_on_curve(group, point, ctx)) {
+ // In the event of an error, defend against the caller not checking the
+ // return value by setting a known safe value: the base point.
+ EC_POINT_copy(point, EC_GROUP_get0_generator(group));
OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
return 0;
}
@@ -952,12 +953,10 @@ int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
int ec_bignum_to_scalar_unchecked(const EC_GROUP *group, EC_SCALAR *out,
const BIGNUM *in) {
- if (BN_is_negative(in) || in->top > group->order.top) {
+ if (!bn_copy_words(out->words, group->order.top, in)) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR);
return 0;
}
- OPENSSL_memset(out->words, 0, group->order.top * sizeof(BN_ULONG));
- OPENSSL_memcpy(out->words, in->d, in->top * sizeof(BN_ULONG));
return 1;
}
diff --git a/src/crypto/fipsmodule/ec/ec_montgomery.c b/src/crypto/fipsmodule/ec/ec_montgomery.c
index 898cf07a..165c06f1 100644
--- a/src/crypto/fipsmodule/ec/ec_montgomery.c
+++ b/src/crypto/fipsmodule/ec/ec_montgomery.c
@@ -93,7 +93,6 @@ void ec_GFp_mont_group_finish(EC_GROUP *group) {
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
BN_CTX *new_ctx = NULL;
- BN_MONT_CTX *mont = NULL;
int ret = 0;
BN_MONT_CTX_free(group->mont);
@@ -106,18 +105,12 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
}
}
- mont = BN_MONT_CTX_new();
- if (mont == NULL) {
- goto err;
- }
- if (!BN_MONT_CTX_set(mont, p, ctx)) {
+ group->mont = BN_MONT_CTX_new_for_modulus(p, ctx);
+ if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
goto err;
}
- group->mont = mont;
- mont = NULL;
-
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
if (!ret) {
@@ -127,7 +120,6 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
err:
BN_CTX_free(new_ctx);
- BN_MONT_CTX_free(mont);
return ret;
}
diff --git a/src/crypto/fipsmodule/ec/ec_test.cc b/src/crypto/fipsmodule/ec/ec_test.cc
index e69f8d72..8a215e91 100644
--- a/src/crypto/fipsmodule/ec/ec_test.cc
+++ b/src/crypto/fipsmodule/ec/ec_test.cc
@@ -28,6 +28,7 @@
#include <openssl/nid.h>
#include <openssl/obj.h>
+#include "../bn/internal.h"
#include "../../test/test_util.h"
@@ -553,6 +554,32 @@ TEST_P(ECCurveTest, Mul) {
EXPECT_EQ(0, EC_POINT_cmp(group.get(), result.get(), generator, nullptr));
}
+#if !defined(BORINGSSL_SHARED_LIBRARY)
+TEST_P(ECCurveTest, MulNonMinimal) {
+ bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
+ ASSERT_TRUE(group);
+
+ bssl::UniquePtr<BIGNUM> forty_two(BN_new());
+ ASSERT_TRUE(forty_two);
+ ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
+
+ // Compute g × 42.
+ bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
+ ASSERT_TRUE(point);
+ ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr,
+ nullptr, nullptr));
+
+ // Compute it again with a non-minimal 42, much larger than the scalar.
+ ASSERT_TRUE(bn_resize_words(forty_two.get(), 64));
+
+ bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group.get()));
+ ASSERT_TRUE(point2);
+ ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), forty_two.get(), nullptr,
+ nullptr, nullptr));
+ EXPECT_EQ(0, EC_POINT_cmp(group.get(), point.get(), point2.get(), nullptr));
+}
+#endif // BORINGSSL_SHARED_LIBRARY
+
// Test that EC_KEY_set_private_key rejects invalid values.
TEST_P(ECCurveTest, SetInvalidPrivateKey) {
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
@@ -572,6 +599,43 @@ TEST_P(ECCurveTest, SetInvalidPrivateKey) {
ERR_clear_error();
}
+TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
+ bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
+ ASSERT_TRUE(group);
+
+ bssl::UniquePtr<BIGNUM> forty_two(BN_new());
+ ASSERT_TRUE(forty_two);
+ ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
+
+ // Compute g × 42.
+ bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
+ ASSERT_TRUE(point);
+ ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr,
+ nullptr, nullptr));
+
+ // Serialize the point.
+ size_t serialized_len =
+ EC_POINT_point2oct(group.get(), point.get(),
+ POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
+ ASSERT_NE(0u, serialized_len);
+
+ std::vector<uint8_t> serialized(serialized_len);
+ ASSERT_EQ(serialized_len,
+ EC_POINT_point2oct(group.get(), point.get(),
+ POINT_CONVERSION_UNCOMPRESSED, serialized.data(),
+ serialized_len, nullptr));
+
+ // Create a serialized point that is not on the curve.
+ serialized[serialized_len - 1]++;
+
+ ASSERT_FALSE(EC_POINT_oct2point(group.get(), point.get(), serialized.data(),
+ serialized.size(), nullptr));
+ // After a failure, |point| should have been set to the generator to defend
+ // against code that doesn't check the return value.
+ ASSERT_EQ(0, EC_POINT_cmp(group.get(), point.get(),
+ EC_GROUP_get0_generator(group.get()), nullptr));
+}
+
static std::vector<EC_builtin_curve> AllCurves() {
const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
std::vector<EC_builtin_curve> curves(num_curves);
diff --git a/src/crypto/fipsmodule/ec/oct.c b/src/crypto/fipsmodule/ec/oct.c
index 96c138a1..3a6b4dd3 100644
--- a/src/crypto/fipsmodule/ec/oct.c
+++ b/src/crypto/fipsmodule/ec/oct.c
@@ -77,11 +77,9 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
const EC_POINT *point,
point_conversion_form_t form,
uint8_t *buf, size_t len, BN_CTX *ctx) {
- size_t ret;
+ size_t ret = 0;
BN_CTX *new_ctx = NULL;
int used_ctx = 0;
- BIGNUM *x, *y;
- size_t field_len, i;
if ((form != POINT_CONVERSION_COMPRESSED) &&
(form != POINT_CONVERSION_UNCOMPRESSED)) {
@@ -94,14 +92,16 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
goto err;
}
- // ret := required output buffer length
- field_len = BN_num_bytes(&group->field);
- ret =
- (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
+ const size_t field_len = BN_num_bytes(&group->field);
+ size_t output_len = 1 /* type byte */ + field_len;
+ if (form == POINT_CONVERSION_UNCOMPRESSED) {
+ // Uncompressed points have a second coordinate.
+ output_len += field_len;
+ }
// if 'buf' is NULL, just return required length
if (buf != NULL) {
- if (len < ret) {
+ if (len < output_len) {
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
goto err;
}
@@ -115,8 +115,8 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
BN_CTX_start(ctx);
used_ctx = 1;
- x = BN_CTX_get(ctx);
- y = BN_CTX_get(ctx);
+ BIGNUM *x = BN_CTX_get(ctx);
+ BIGNUM *y = BN_CTX_get(ctx);
if (y == NULL) {
goto err;
}
@@ -131,7 +131,7 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
} else {
buf[0] = form;
}
- i = 1;
+ size_t i = 1;
if (!BN_bn2bin_padded(buf + i, field_len, x)) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
@@ -147,70 +147,66 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
i += field_len;
}
- if (i != ret) {
+ if (i != output_len) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
goto err;
}
}
- if (used_ctx) {
- BN_CTX_end(ctx);
- }
- BN_CTX_free(new_ctx);
- return ret;
+ ret = output_len;
err:
if (used_ctx) {
BN_CTX_end(ctx);
}
BN_CTX_free(new_ctx);
- return 0;
+ return ret;
}
-
static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
const uint8_t *buf, size_t len,
BN_CTX *ctx) {
- point_conversion_form_t form;
- int y_bit;
BN_CTX *new_ctx = NULL;
- BIGNUM *x, *y;
- size_t field_len, enc_len;
- int ret = 0;
+ int ret = 0, used_ctx = 0;
if (len == 0) {
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
- return 0;
+ goto err;
}
- form = buf[0];
- y_bit = form & 1;
+
+ point_conversion_form_t form = buf[0];
+ const int y_bit = form & 1;
form = form & ~1U;
if ((form != POINT_CONVERSION_COMPRESSED &&
form != POINT_CONVERSION_UNCOMPRESSED) ||
(form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
- return 0;
+ goto err;
}
- field_len = BN_num_bytes(&group->field);
- enc_len =
- (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
+ const size_t field_len = BN_num_bytes(&group->field);
+ size_t enc_len = 1 /* type byte */ + field_len;
+ if (form == POINT_CONVERSION_UNCOMPRESSED) {
+ // Uncompressed points have a second coordinate.
+ enc_len += field_len;
+ }
if (len != enc_len) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
- return 0;
+ goto err;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
- return 0;
+ goto err;
}
}
BN_CTX_start(ctx);
- x = BN_CTX_get(ctx);
- y = BN_CTX_get(ctx);
+ used_ctx = 1;
+ BIGNUM *x = BN_CTX_get(ctx);
+ BIGNUM *y = BN_CTX_get(ctx);
if (x == NULL || y == NULL) {
goto err;
}
@@ -244,7 +240,9 @@ static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
ret = 1;
err:
- BN_CTX_end(ctx);
+ if (used_ctx) {
+ BN_CTX_end(ctx);
+ }
BN_CTX_free(new_ctx);
return ret;
}
diff --git a/src/crypto/fipsmodule/ec/p256-x86_64.c b/src/crypto/fipsmodule/ec/p256-x86_64.c
index 0e79b6dc..ec371bf0 100644
--- a/src/crypto/fipsmodule/ec/p256-x86_64.c
+++ b/src/crypto/fipsmodule/ec/p256-x86_64.c
@@ -205,13 +205,7 @@ static void ecp_nistz256_mod_inverse_mont(BN_ULONG r[P256_LIMBS],
// returns one if it fits. Otherwise it returns zero.
static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS],
const BIGNUM *in) {
- if (in->top > P256_LIMBS) {
- return 0;
- }
-
- OPENSSL_memset(out, 0, sizeof(BN_ULONG) * P256_LIMBS);
- OPENSSL_memcpy(out, in->d, sizeof(BN_ULONG) * in->top);
- return 1;
+ return bn_copy_words(out, P256_LIMBS, in);
}
// r = p * p_scalar
diff --git a/src/crypto/fipsmodule/ec/p256-x86_64_test.cc b/src/crypto/fipsmodule/ec/p256-x86_64_test.cc
index a802bfb5..5cd701ba 100644
--- a/src/crypto/fipsmodule/ec/p256-x86_64_test.cc
+++ b/src/crypto/fipsmodule/ec/p256-x86_64_test.cc
@@ -160,17 +160,16 @@ static bool PointToAffine(P256_POINT_AFFINE *out, const P256_POINT *in) {
return false;
}
- OPENSSL_memset(out, 0, sizeof(P256_POINT_AFFINE));
-
if (BN_is_zero(z.get())) {
// The point at infinity is represented as (0, 0).
+ OPENSSL_memset(out, 0, sizeof(P256_POINT_AFFINE));
return true;
}
bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
- bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
+ bssl::UniquePtr<BN_MONT_CTX> mont(
+ BN_MONT_CTX_new_for_modulus(p.get(), ctx.get()));
if (!ctx || !mont ||
- !BN_MONT_CTX_set(mont.get(), p.get(), ctx.get()) ||
// Invert Z.
!BN_from_montgomery(z.get(), z.get(), mont.get(), ctx.get()) ||
!BN_mod_inverse(z.get(), z.get(), p.get(), ctx.get()) ||
@@ -185,12 +184,11 @@ static bool PointToAffine(P256_POINT_AFFINE *out, const P256_POINT *in) {
!BN_mod_mul_montgomery(y.get(), y.get(), z.get(), mont.get(),
ctx.get()) ||
!BN_mod_mul_montgomery(y.get(), y.get(), z.get(), mont.get(),
- ctx.get())) {
+ ctx.get()) ||
+ !bn_copy_words(out->X, P256_LIMBS, x.get()) ||
+ !bn_copy_words(out->Y, P256_LIMBS, y.get())) {
return false;
}
-
- OPENSSL_memcpy(out->X, x->d, sizeof(BN_ULONG) * x->top);
- OPENSSL_memcpy(out->Y, y->d, sizeof(BN_ULONG) * y->top);
return true;
}
diff --git a/src/crypto/fipsmodule/rsa/rsa_impl.c b/src/crypto/fipsmodule/rsa/rsa_impl.c
index b5a4e515..626bbe85 100644
--- a/src/crypto/fipsmodule/rsa/rsa_impl.c
+++ b/src/crypto/fipsmodule/rsa/rsa_impl.c
@@ -646,12 +646,11 @@ err:
static int mod_montgomery(BIGNUM *r, const BIGNUM *I, const BIGNUM *p,
const BN_MONT_CTX *mont_p, const BIGNUM *q,
BN_CTX *ctx) {
- // Reduce in constant time with Montgomery reduction, which requires I <= p *
- // R. If p and q are the same size, which is true for any RSA keys we or
- // anyone sane generates, we have q < R and I < p * q, so this holds.
- //
- // If q is too big, fall back to |BN_mod|.
- if (q->top > p->top) {
+ // Reducing in constant-time with Montgomery reduction requires I <= p * R. We
+ // have I < p * q, so this follows if q < R. In particular, this always holds
+ // if p and q are the same size, which is true for any RSA keys we or anyone
+ // sane generates. For other keys, we fall back to |BN_mod|.
+ if (!bn_less_than_montgomery_R(q, mont_p)) {
return BN_mod(r, I, p, ctx);
}
@@ -838,7 +837,8 @@ int rsa_greater_than_pow2(const BIGNUM *b, int n) {
// relatively prime to |e|. If |p| is non-NULL, |out| will also not be close to
// |p|.
static int generate_prime(BIGNUM *out, int bits, const BIGNUM *e,
- const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb) {
+ const BIGNUM *p, const BIGNUM *sqrt2, BN_CTX *ctx,
+ BN_GENCB *cb) {
if (bits < 128 || (bits % BN_BITS2) != 0) {
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
return 0;
@@ -882,30 +882,14 @@ static int generate_prime(BIGNUM *out, int bits, const BIGNUM *e,
}
}
- // If out < 2^(bits-1)×√2, try again (steps 4.4 and 5.5).
- //
- // We check the most significant words, so we retry if ⌊out/2^k⌋ <= ⌊b/2^k⌋,
- // where b = 2^(bits-1)×√2 and k = max(0, bits - 1536). For key sizes up to
- // 3072 (bits = 1536), k = 0, so we are testing that ⌊out⌋ <= ⌊b⌋. out is an
- // integer and b is not, so this is equivalent to out < b. That is, the
- // comparison is exact for FIPS key sizes.
+ // If out < 2^(bits-1)×√2, try again (steps 4.4 and 5.5). This is equivalent
+ // to out <= ⌊2^(bits-1)×√2⌋, or out <= sqrt2 for FIPS key sizes.
//
// For larger keys, the comparison is approximate, leaning towards
// retrying. That is, we reject a negligible fraction of primes that are
// within the FIPS bound, but we will never accept a prime outside the
- // bound, ensuring the resulting RSA key is the right size. Specifically, if
- // the FIPS bound holds, we have ⌊out/2^k⌋ < out/2^k < b/2^k. This implies
- // ⌊out/2^k⌋ <= ⌊b/2^k⌋. That is, the FIPS bound implies our bound and so we
- // are slightly tighter.
- size_t out_len = (size_t)out->top;
- assert(out_len == (size_t)bits / BN_BITS2);
- size_t to_check = kBoringSSLRSASqrtTwoLen;
- if (to_check > out_len) {
- to_check = out_len;
- }
- if (!bn_less_than_words(
- kBoringSSLRSASqrtTwo + kBoringSSLRSASqrtTwoLen - to_check,
- out->d + out_len - to_check, to_check)) {
+ // bound, ensuring the resulting RSA key is the right size.
+ if (!BN_less_than_consttime(sqrt2, out)) {
continue;
}
@@ -969,7 +953,9 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
BIGNUM *pm1 = BN_CTX_get(ctx);
BIGNUM *qm1 = BN_CTX_get(ctx);
BIGNUM *gcd = BN_CTX_get(ctx);
- if (totient == NULL || pm1 == NULL || qm1 == NULL || gcd == NULL) {
+ BIGNUM *sqrt2 = BN_CTX_get(ctx);
+ if (totient == NULL || pm1 == NULL || qm1 == NULL || gcd == NULL ||
+ sqrt2 == NULL) {
goto bn_err;
}
@@ -990,12 +976,35 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
}
int prime_bits = bits / 2;
+
+ // Compute sqrt2 >= ⌊2^(prime_bits-1)×√2⌋.
+ if (!bn_set_words(sqrt2, kBoringSSLRSASqrtTwo, kBoringSSLRSASqrtTwoLen)) {
+ goto bn_err;
+ }
+ int sqrt2_bits = kBoringSSLRSASqrtTwoLen * BN_BITS2;
+ assert(sqrt2_bits == (int)BN_num_bits(sqrt2));
+ if (sqrt2_bits > prime_bits) {
+ // For key sizes up to 3072 (prime_bits = 1536), this is exactly
+ // ⌊2^(prime_bits-1)×√2⌋.
+ if (!BN_rshift(sqrt2, sqrt2, sqrt2_bits - prime_bits)) {
+ goto bn_err;
+ }
+ } else if (prime_bits > sqrt2_bits) {
+ // For key sizes beyond 3072, this is approximate. We err towards retrying
+ // to ensure our key is the right size and round up.
+ if (!BN_add_word(sqrt2, 1) ||
+ !BN_lshift(sqrt2, sqrt2, prime_bits - sqrt2_bits)) {
+ goto bn_err;
+ }
+ }
+ assert(prime_bits == (int)BN_num_bits(sqrt2));
+
do {
// Generate p and q, each of size |prime_bits|, using the steps outlined in
// appendix FIPS 186-4 appendix B.3.3.
- if (!generate_prime(rsa->p, prime_bits, rsa->e, NULL, ctx, cb) ||
+ if (!generate_prime(rsa->p, prime_bits, rsa->e, NULL, sqrt2, ctx, cb) ||
!BN_GENCB_call(cb, 3, 0) ||
- !generate_prime(rsa->q, prime_bits, rsa->e, rsa->p, ctx, cb) ||
+ !generate_prime(rsa->q, prime_bits, rsa->e, rsa->p, sqrt2, ctx, cb) ||
!BN_GENCB_call(cb, 3, 1)) {
goto bn_err;
}
diff --git a/src/fipstools/cavp_tlskdf_test.cc b/src/fipstools/cavp_tlskdf_test.cc
index ac0f83f7..0af2d47c 100644
--- a/src/fipstools/cavp_tlskdf_test.cc
+++ b/src/fipstools/cavp_tlskdf_test.cc
@@ -18,6 +18,8 @@
#include <vector>
+#include <errno.h>
+
#include <openssl/digest.h>
#include "cavp_test_util.h"
diff --git a/src/fipstools/run_cavp.go b/src/fipstools/run_cavp.go
index 2b1bf6d4..587ba070 100644
--- a/src/fipstools/run_cavp.go
+++ b/src/fipstools/run_cavp.go
@@ -4,10 +4,12 @@ package main
import (
"bufio"
+ "errors"
"flag"
"fmt"
"os"
"os/exec"
+ "path"
"path/filepath"
"runtime"
"strings"
@@ -20,6 +22,13 @@ var (
suiteDir = flag.String("suite-dir", "", "Base directory containing the CAVP test suite")
noFAX = flag.Bool("no-fax", false, "Skip comparing against FAX files")
niap = flag.Bool("niap", false, "Perform NIAP tests rather than FIPS tests")
+ android = flag.Bool("android", false, "Run tests via ADB")
+)
+
+const (
+ androidTmpPath = "/data/local/tmp/"
+ androidCAVPPath = androidTmpPath + "cavp"
+ androidLibCryptoPath = androidTmpPath + "libcrypto.so"
)
// test describes a single request file.
@@ -374,10 +383,27 @@ func worker(wg *sync.WaitGroup, work <-chan testInstance) {
}
}
+func checkAndroidPrereqs() error {
+ // The cavp binary, and a matching libcrypto.so, are required to be placed
+ // in /data/local/tmp before running this script.
+ if err := exec.Command("adb", "shell", "ls", androidCAVPPath).Run(); err != nil {
+ return errors.New("failed to list cavp binary; ensure that adb works and cavp binary is in place: " + err.Error())
+ }
+ if err := exec.Command("adb", "shell", "ls", androidLibCryptoPath).Run(); err != nil {
+ return errors.New("failed to list libcrypto.so; ensure that library is in place: " + err.Error())
+ }
+ return nil
+}
+
func main() {
flag.Parse()
- if len(*oraclePath) == 0 {
+ if *android {
+ if err := checkAndroidPrereqs(); err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+ } else if len(*oraclePath) == 0 {
fmt.Fprintf(os.Stderr, "Must give -oracle-bin\n")
os.Exit(1)
}
@@ -385,7 +411,12 @@ func main() {
work := make(chan testInstance)
var wg sync.WaitGroup
- for i := 0; i < runtime.NumCPU(); i++ {
+ numWorkers := runtime.NumCPU()
+ if *android {
+ numWorkers = 1
+ }
+
+ for i := 0; i < numWorkers; i++ {
wg.Add(1)
go worker(&wg, work)
}
@@ -406,9 +437,28 @@ func main() {
}
func doTest(suite *testSuite, test test) error {
- args := []string{suite.suite}
+ bin := *oraclePath
+ var args []string
+
+ if *android {
+ bin = "adb"
+ args = []string{"shell", "LD_LIBRARY_PATH=" + androidTmpPath, androidCAVPPath}
+ }
+
+ args = append(args, suite.suite)
args = append(args, test.args...)
- args = append(args, filepath.Join(suite.getDirectory(), "req", test.inFile+".req"))
+ reqPath := filepath.Join(suite.getDirectory(), "req", test.inFile+".req")
+ var reqPathOnDevice string
+
+ if *android {
+ reqPathOnDevice = path.Join(androidTmpPath, test.inFile+".req")
+ if err := exec.Command("adb", "push", reqPath, reqPathOnDevice).Run(); err != nil {
+ return errors.New("failed to push request file: " + err.Error())
+ }
+ args = append(args, reqPathOnDevice)
+ } else {
+ args = append(args, reqPath)
+ }
respDir := filepath.Join(suite.getDirectory(), "resp")
if err := os.Mkdir(respDir, 0755); err != nil && !os.IsExist(err) {
@@ -421,11 +471,11 @@ func doTest(suite *testSuite, test test) error {
}
defer outFile.Close()
- cmd := exec.Command(*oraclePath, args...)
+ cmd := exec.Command(bin, args...)
cmd.Stdout = outFile
cmd.Stderr = os.Stderr
- cmdLine := strings.Join(append([]string{*oraclePath}, args...), " ")
+ cmdLine := strings.Join(append([]string{bin}, args...), " ")
startTime := time.Now()
if err := cmd.Run(); err != nil {
return fmt.Errorf("cannot run command for %q %q (%s): %s", suite.getDirectory(), test.inFile, cmdLine, err)
@@ -433,6 +483,10 @@ func doTest(suite *testSuite, test test) error {
fmt.Printf("%s (%ds)\n", cmdLine, int(time.Since(startTime).Seconds()))
+ if *android {
+ exec.Command("adb", "shell", "rm", reqPathOnDevice).Run()
+ }
+
return nil
}
diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h
index bb32c2f5..7f7d4795 100644
--- a/src/include/openssl/bn.h
+++ b/src/include/openssl/bn.h
@@ -440,6 +440,11 @@ OPENSSL_EXPORT int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
// independent of the contents (including the signs) of |a| and |b|.
OPENSSL_EXPORT int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b);
+// BN_less_than_consttime returns one if |a| is less than |b|, and zero
+// otherwise. It takes an amount of time dependent on the sizes and signs of |a|
+// and |b|, but independent of the contents of |a| and |b|.
+OPENSSL_EXPORT int BN_less_than_consttime(const BIGNUM *a, const BIGNUM *b);
+
// BN_abs_is_word returns one if the absolute value of |bn| equals |w| and zero
// otherwise.
OPENSSL_EXPORT int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w);
@@ -788,8 +793,10 @@ int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
// BN_MONT_CTX contains the precomputed values needed to work in a specific
// Montgomery domain.
-// BN_MONT_CTX_new returns a fresh BN_MONT_CTX or NULL on allocation failure.
-OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new(void);
+// BN_MONT_CTX_new_for_modulus returns a fresh |BN_MONT_CTX| given the modulus,
+// |mod| or NULL on error.
+OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new_for_modulus(const BIGNUM *mod,
+ BN_CTX *ctx);
// BN_MONT_CTX_free frees memory associated with |mont|.
OPENSSL_EXPORT void BN_MONT_CTX_free(BN_MONT_CTX *mont);
@@ -799,11 +806,6 @@ OPENSSL_EXPORT void BN_MONT_CTX_free(BN_MONT_CTX *mont);
OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,
const BN_MONT_CTX *from);
-// BN_MONT_CTX_set sets up a Montgomery context given the modulus, |mod|. It
-// returns one on success and zero on error.
-OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod,
- BN_CTX *ctx);
-
// BN_MONT_CTX_set_locked takes |lock| and checks whether |*pmont| is NULL. If
// so, it creates a new |BN_MONT_CTX| and sets the modulus for it to |mod|. It
// then stores it as |*pmont|. It returns one on success and zero on error.
@@ -891,6 +893,16 @@ OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1,
const BIGNUM *p2, const BIGNUM *m,
BN_CTX *ctx, const BN_MONT_CTX *mont);
+// BN_MONT_CTX_new returns a fresh |BN_MONT_CTX| or NULL on allocation failure.
+// Use |BN_MONT_CTX_new_for_modulus| instead.
+OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new(void);
+
+// BN_MONT_CTX_set sets up a Montgomery context given the modulus, |mod|. It
+// returns one on success and zero on error. Use |BN_MONT_CTX_new_for_modulus|
+// instead.
+OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod,
+ BN_CTX *ctx);
+
// Private functions
@@ -904,8 +916,11 @@ struct bignum_st {
};
struct bn_mont_ctx_st {
- BIGNUM RR; // used to convert to montgomery form
- BIGNUM N; // The modulus
+ // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form.
+ BIGNUM RR;
+ // N is the modulus. It is always stored in minimal form, so |N.top|
+ // determines R.
+ BIGNUM N;
BN_ULONG n0[2]; // least significant words of (R*Ri-1)/N
};
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index a44241aa..249fce13 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -534,6 +534,8 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code);
// See also |SSL_CTX_set_custom_verify|.
#define SSL_ERROR_WANT_CERTIFICATE_VERIFY 16
+#define SSL_ERROR_HANDOFF 17
+
// SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success
// and zero on failure.
OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu);
@@ -593,9 +595,7 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl);
#define DTLS1_VERSION 0xfeff
#define DTLS1_2_VERSION 0xfefd
-#define TLS1_3_DRAFT22_VERSION 0x7f16
#define TLS1_3_DRAFT23_VERSION 0x7f17
-#define TLS1_3_EXPERIMENT2_VERSION 0x7e02
// SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to
// |version|. If |version| is zero, the default minimum version is used. It
@@ -2953,6 +2953,38 @@ OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *ssl);
OPENSSL_EXPORT int SSL_set_dummy_pq_padding_size(SSL *ssl, size_t num_bytes);
+// QUIC Transport Parameters.
+//
+// draft-ietf-quic-tls defines a new TLS extension quic_transport_parameters
+// used by QUIC for each endpoint to unilaterally declare its supported
+// transport parameters. draft-ietf-quic-transport (section 7.4) defines the
+// contents of that extension (a TransportParameters struct) and describes how
+// to handle it and its semantic meaning.
+//
+// BoringSSL handles this extension as an opaque byte string. The caller is
+// responsible for serializing and parsing it.
+
+// SSL_set_quic_transport_params configures |ssl| to send |params| (of length
+// |params_len|) in the quic_transport_parameters extension in either the
+// ClientHello or EncryptedExtensions handshake message. This extension will
+// only be sent if the TLS version is at least 1.3, and for a server, only if
+// the client sent the extension. The buffer pointed to by |params| only need be
+// valid for the duration of the call to this function. This function returns 1
+// on success and 0 on failure.
+OPENSSL_EXPORT int SSL_set_quic_transport_params(SSL *ssl,
+ const uint8_t *params,
+ size_t params_len);
+
+// SSL_get_peer_quic_transport_params provides the caller with the value of the
+// quic_transport_parameters extension sent by the peer. A pointer to the buffer
+// containing the TransportParameters will be put in |*out_params|, and its
+// length in |*params_len|. This buffer will be valid for the lifetime of the
+// |SSL|. If no params were received from the peer, |*out_params_len| will be 0.
+OPENSSL_EXPORT void SSL_get_peer_quic_transport_params(const SSL *ssl,
+ const uint8_t **out_params,
+ size_t *out_params_len);
+
+
// Early data.
//
// WARNING: 0-RTT support in BoringSSL is currently experimental and not fully
@@ -3272,8 +3304,6 @@ OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl);
enum tls13_variant_t {
tls13_default = 0,
- tls13_experiment2 = 1,
- tls13_draft22 = 2,
};
// SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the
@@ -3890,6 +3920,7 @@ OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb(
#define SSL_PENDING_TICKET 10
#define SSL_EARLY_DATA_REJECTED 11
#define SSL_CERTIFICATE_VERIFY 12
+#define SSL_HANDOFF 13
// SSL_want returns one of the above values to determine what the most recent
// operation on |ssl| was blocked on. Use |SSL_get_error| instead.
@@ -4425,6 +4456,53 @@ OPENSSL_EXPORT bool SealRecord(SSL *ssl, Span<uint8_t> out_prefix,
Span<uint8_t> out, Span<uint8_t> out_suffix,
Span<const uint8_t> in);
+
+// *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING ***
+//
+// Split handshakes.
+//
+// Split handshakes allows the handshake part of a TLS connection to be
+// performed in a different process (or on a different machine) than the data
+// exchange. This only applies to servers.
+//
+// In the first part of a split handshake, an |SSL| (where the |SSL_CTX| has
+// been configured with |SSL_CTX_set_handoff_mode|) is used normally. Once the
+// ClientHello message has been received, the handshake will stop and
+// |SSL_get_error| will indicate |SSL_ERROR_HANDOFF|. At this point (and only
+// at this point), |SSL_serialize_handoff| can be called to write the “handoff”
+// state of the connection.
+//
+// Elsewhere, a fresh |SSL| can be used with |SSL_apply_handoff| to continue
+// the connection. The connection from the client is fed into this |SSL| until
+// the handshake completes normally. At this point (and only at this point),
+// |SSL_serialize_handback| can be called to serialize the result of the
+// handshake.
+//
+// Back at the first location, a fresh |SSL| can be used with
+// |SSL_apply_handback|. Then the client's connection can be processed mostly
+// as normal.
+//
+// Lastly, when a connection is in the handoff state, whether or not
+// |SSL_serialize_handoff| is called, |SSL_decline_handoff| will move it back
+// into a normal state where the connection can procede without impact.
+//
+// WARNING: Currently only works with TLS 1.0–1.2.
+// WARNING: The serialisation formats are not yet stable: version skew may be
+// fatal.
+// WARNING: The handback data contains sensitive key material and must be
+// protected.
+// WARNING: Some calls on the final |SSL| will not work. Just as an example,
+// calls like |SSL_get0_session_id_context| and |SSL_get_privatekey| won't
+// work because the certificate used for handshaking isn't available.
+// WARNING: |SSL_apply_handoff| may trigger “msg” callback calls.
+
+OPENSSL_EXPORT void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on);
+OPENSSL_EXPORT bool SSL_serialize_handoff(const SSL *ssl, CBB *out);
+OPENSSL_EXPORT bool SSL_decline_handoff(SSL *ssl);
+OPENSSL_EXPORT bool SSL_apply_handoff(SSL *ssl, Span<const uint8_t> handoff);
+OPENSSL_EXPORT bool SSL_serialize_handback(const SSL *ssl, CBB *out);
+OPENSSL_EXPORT bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback);
+
} // namespace bssl
} // extern C++
@@ -4619,6 +4697,7 @@ OPENSSL_EXPORT bool SealRecord(SSL *ssl, Span<uint8_t> out_prefix,
#define SSL_R_HANDSHAKE_NOT_COMPLETE 284
#define SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI 285
#define SSL_R_SERVER_ECHOED_INVALID_SESSION_ID 286
+#define SSL_R_PRIVATE_KEY_OPERATION_FAILED 287
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/src/include/openssl/tls1.h b/src/include/openssl/tls1.h
index 682bb9ba..3424f3dc 100644
--- a/src/include/openssl/tls1.h
+++ b/src/include/openssl/tls1.h
@@ -205,20 +205,21 @@ extern "C" {
// ExtensionType value from draft-ietf-tokbind-negotiation-10
#define TLSEXT_TYPE_token_binding 24
+// ExtensionType value from draft-ietf-quic-tls
+#define TLSEXT_TYPE_quic_transport_parameters 26
+
// ExtensionType value from RFC4507
#define TLSEXT_TYPE_session_ticket 35
// ExtensionType values from draft-ietf-tls-tls13-18
#define TLSEXT_TYPE_supported_groups 10
-#define TLSEXT_TYPE_old_key_share 40
#define TLSEXT_TYPE_pre_shared_key 41
#define TLSEXT_TYPE_early_data 42
#define TLSEXT_TYPE_supported_versions 43
#define TLSEXT_TYPE_cookie 44
#define TLSEXT_TYPE_psk_key_exchange_modes 45
-#define TLSEXT_TYPE_ticket_early_data_info 46
#define TLSEXT_TYPE_certificate_authorities 47
-#define TLSEXT_TYPE_new_key_share 51
+#define TLSEXT_TYPE_key_share 51
// ExtensionType value from RFC5746
#define TLSEXT_TYPE_renegotiate 0xff01
diff --git a/src/ssl/CMakeLists.txt b/src/ssl/CMakeLists.txt
index 35288e19..3eab0b52 100644
--- a/src/ssl/CMakeLists.txt
+++ b/src/ssl/CMakeLists.txt
@@ -11,6 +11,7 @@ add_library(
d1_srtp.cc
dtls_method.cc
dtls_record.cc
+ handoff.cc
handshake.cc
handshake_client.cc
handshake_server.cc
diff --git a/src/ssl/handoff.cc b/src/ssl/handoff.cc
new file mode 100644
index 00000000..b19d4432
--- /dev/null
+++ b/src/ssl/handoff.cc
@@ -0,0 +1,285 @@
+/* Copyright (c) 2018, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/ssl.h>
+
+#include <openssl/bytestring.h>
+
+#include "internal.h"
+
+
+namespace bssl {
+
+constexpr int kHandoffVersion = 0;
+constexpr int kHandbackVersion = 0;
+
+bool SSL_serialize_handoff(const SSL *ssl, CBB *out) {
+ const SSL3_STATE *const s3 = ssl->s3;
+ if (!ssl->server ||
+ s3->hs == nullptr ||
+ s3->rwstate != SSL_HANDOFF) {
+ return false;
+ }
+
+ CBB seq;
+ Span<const uint8_t> transcript = s3->hs->transcript.buffer();
+ if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&seq, kHandoffVersion) ||
+ !CBB_add_asn1_octet_string(&seq, transcript.data(), transcript.size()) ||
+ !CBB_add_asn1_octet_string(&seq,
+ reinterpret_cast<uint8_t *>(s3->hs_buf->data),
+ s3->hs_buf->length) ||
+ !CBB_flush(out)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool SSL_decline_handoff(SSL *ssl) {
+ const SSL3_STATE *const s3 = ssl->s3;
+ if (!ssl->server ||
+ s3->hs == nullptr ||
+ s3->rwstate != SSL_HANDOFF) {
+ return false;
+ }
+
+ ssl->handoff = false;
+ return true;
+}
+
+bool SSL_apply_handoff(SSL *ssl, Span<const uint8_t> handoff) {
+ if (ssl->method->is_dtls) {
+ return false;
+ }
+
+ CBS seq, handoff_cbs(handoff);
+ uint64_t handoff_version;
+ if (!CBS_get_asn1(&handoff_cbs, &seq, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&seq, &handoff_version) ||
+ handoff_version != kHandoffVersion) {
+ return false;
+ }
+
+ CBS transcript, hs_buf;
+ if (!CBS_get_asn1(&seq, &transcript, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&seq, &hs_buf, CBS_ASN1_OCTETSTRING)) {
+ return false;
+ }
+
+ SSL_set_accept_state(ssl);
+
+ SSL3_STATE *const s3 = ssl->s3;
+ s3->v2_hello_done = true;
+ s3->has_message = true;
+
+ s3->hs_buf.reset(BUF_MEM_new());
+ if (!s3->hs_buf ||
+ !BUF_MEM_append(s3->hs_buf.get(), CBS_data(&hs_buf), CBS_len(&hs_buf))) {
+ return false;
+ }
+
+ if (CBS_len(&transcript) != 0) {
+ s3->hs->transcript.Update(transcript);
+ s3->is_v2_hello = true;
+ ssl_do_msg_callback(ssl, 0 /* read */, 0 /* V2ClientHello */, transcript);
+ }
+
+ return true;
+}
+
+bool SSL_serialize_handback(const SSL *ssl, CBB *out) {
+ if (!ssl->server ||
+ !ssl->s3->initial_handshake_complete ||
+ ssl->method->is_dtls ||
+ ssl->version < TLS1_VERSION) {
+ return false;
+ }
+
+ const SSL3_STATE *const s3 = ssl->s3;
+ size_t hostname_len = 0;
+ if (s3->hostname) {
+ hostname_len = strlen(s3->hostname.get());
+ }
+
+ size_t iv_len = 0;
+ const uint8_t *read_iv = nullptr, *write_iv = nullptr;
+ if (ssl->version == TLS1_VERSION &&
+ SSL_CIPHER_is_block_cipher(s3->aead_read_ctx->cipher()) &&
+ (!s3->aead_read_ctx->GetIV(&read_iv, &iv_len) ||
+ !s3->aead_write_ctx->GetIV(&write_iv, &iv_len))) {
+ return false;
+ }
+
+ CBB seq;
+ if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&seq, kHandbackVersion) ||
+ !CBB_add_asn1_uint64(&seq, ssl->version) ||
+ !CBB_add_asn1_uint64(&seq, ssl->conf_max_version) ||
+ !CBB_add_asn1_uint64(&seq, ssl->conf_min_version) ||
+ !CBB_add_asn1_uint64(&seq, ssl->max_send_fragment) ||
+ !CBB_add_asn1_octet_string(&seq, s3->read_sequence,
+ sizeof(s3->read_sequence)) ||
+ !CBB_add_asn1_octet_string(&seq, s3->write_sequence,
+ sizeof(s3->write_sequence)) ||
+ !CBB_add_asn1_octet_string(&seq, s3->server_random,
+ sizeof(s3->server_random)) ||
+ !CBB_add_asn1_octet_string(&seq, s3->client_random,
+ sizeof(s3->client_random)) ||
+ !CBB_add_asn1_octet_string(&seq, read_iv, iv_len) ||
+ !CBB_add_asn1_octet_string(&seq, write_iv, iv_len) ||
+ !CBB_add_asn1_bool(&seq, s3->session_reused) ||
+ !CBB_add_asn1_bool(&seq, s3->send_connection_binding) ||
+ !CBB_add_asn1_bool(&seq, s3->tlsext_channel_id_valid) ||
+ !ssl_session_serialize(s3->established_session.get(), &seq) ||
+ !CBB_add_asn1_octet_string(&seq, s3->next_proto_negotiated.data(),
+ s3->next_proto_negotiated.size()) ||
+ !CBB_add_asn1_octet_string(&seq, s3->alpn_selected.data(),
+ s3->alpn_selected.size()) ||
+ !CBB_add_asn1_octet_string(
+ &seq, reinterpret_cast<uint8_t *>(s3->hostname.get()),
+ hostname_len) ||
+ !CBB_add_asn1_octet_string(&seq, s3->tlsext_channel_id,
+ sizeof(s3->tlsext_channel_id)) ||
+ !CBB_add_asn1_uint64(&seq, ssl->options) ||
+ !CBB_add_asn1_uint64(&seq, ssl->mode) ||
+ !CBB_add_asn1_uint64(&seq, ssl->max_cert_list) ||
+ !CBB_add_asn1_bool(&seq, ssl->quiet_shutdown) ||
+ !CBB_add_asn1_bool(&seq, ssl->tlsext_channel_id_enabled) ||
+ !CBB_add_asn1_bool(&seq, ssl->retain_only_sha256_of_client_certs) ||
+ !CBB_flush(out)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) {
+ if (ssl->do_handshake != nullptr ||
+ ssl->method->is_dtls) {
+ return false;
+ }
+
+ SSL3_STATE *const s3 = ssl->s3;
+ uint64_t handback_version, version, conf_max_version, conf_min_version,
+ max_send_fragment, options, mode, max_cert_list;
+ CBS seq, read_seq, write_seq, server_rand, client_rand, read_iv, write_iv,
+ next_proto, alpn, hostname, channel_id;
+ int session_reused, send_connection_binding, channel_id_valid,
+ quiet_shutdown, channel_id_enabled, retain_only_sha256;
+
+ CBS handback_cbs(handback);
+ if (!CBS_get_asn1(&handback_cbs, &seq, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&seq, &handback_version) ||
+ handback_version != kHandbackVersion) {
+ return false;
+ }
+
+ if (!CBS_get_asn1_uint64(&seq, &version) ||
+ !CBS_get_asn1_uint64(&seq, &conf_max_version) ||
+ !CBS_get_asn1_uint64(&seq, &conf_min_version) ||
+ !CBS_get_asn1_uint64(&seq, &max_send_fragment) ||
+ !CBS_get_asn1(&seq, &read_seq, CBS_ASN1_OCTETSTRING) ||
+ CBS_len(&read_seq) != sizeof(s3->read_sequence) ||
+ !CBS_get_asn1(&seq, &write_seq, CBS_ASN1_OCTETSTRING) ||
+ CBS_len(&write_seq) != sizeof(s3->write_sequence) ||
+ !CBS_get_asn1(&seq, &server_rand, CBS_ASN1_OCTETSTRING) ||
+ CBS_len(&server_rand) != sizeof(s3->server_random) ||
+ !CBS_copy_bytes(&server_rand, s3->server_random,
+ sizeof(s3->server_random)) ||
+ !CBS_get_asn1(&seq, &client_rand, CBS_ASN1_OCTETSTRING) ||
+ CBS_len(&client_rand) != sizeof(s3->client_random) ||
+ !CBS_copy_bytes(&client_rand, s3->client_random,
+ sizeof(s3->client_random)) ||
+ !CBS_get_asn1(&seq, &read_iv, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&seq, &write_iv, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1_bool(&seq, &session_reused) ||
+ !CBS_get_asn1_bool(&seq, &send_connection_binding) ||
+ !CBS_get_asn1_bool(&seq, &channel_id_valid)) {
+ return false;
+ }
+
+ s3->established_session =
+ SSL_SESSION_parse(&seq, ssl->ctx->x509_method, ssl->ctx->pool);
+
+ if (!s3->established_session ||
+ !CBS_get_asn1(&seq, &next_proto, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&seq, &alpn, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&seq, &hostname, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&seq, &channel_id, CBS_ASN1_OCTETSTRING) ||
+ CBS_len(&channel_id) != sizeof(s3->tlsext_channel_id) ||
+ !CBS_copy_bytes(&channel_id, s3->tlsext_channel_id,
+ sizeof(s3->tlsext_channel_id)) ||
+ !CBS_get_asn1_uint64(&seq, &options) ||
+ !CBS_get_asn1_uint64(&seq, &mode) ||
+ !CBS_get_asn1_uint64(&seq, &max_cert_list) ||
+ !CBS_get_asn1_bool(&seq, &quiet_shutdown) ||
+ !CBS_get_asn1_bool(&seq, &channel_id_enabled) ||
+ !CBS_get_asn1_bool(&seq, &retain_only_sha256)) {
+ return false;
+ }
+
+ ssl->version = version;
+ ssl->conf_max_version = conf_max_version;
+ ssl->conf_min_version = conf_min_version;
+ ssl->max_send_fragment = max_send_fragment;
+ ssl->do_handshake = ssl_server_handshake;
+ ssl->server = true;
+ ssl->options = options;
+ ssl->mode = mode;
+ ssl->max_cert_list = max_cert_list;
+
+ s3->hs.reset();
+ s3->have_version = true;
+ s3->initial_handshake_complete = true;
+ s3->session_reused = session_reused;
+ s3->send_connection_binding = send_connection_binding;
+ s3->tlsext_channel_id_valid = channel_id_valid;
+ s3->next_proto_negotiated.CopyFrom(next_proto);
+ s3->alpn_selected.CopyFrom(alpn);
+
+ const size_t hostname_len = CBS_len(&hostname);
+ if (hostname_len == 0) {
+ s3->hostname.reset();
+ } else {
+ char *hostname_str = nullptr;
+ if (!CBS_strdup(&hostname, &hostname_str)) {
+ return false;
+ }
+ s3->hostname.reset(hostname_str);
+ }
+
+ ssl->quiet_shutdown = quiet_shutdown;
+ ssl->tlsext_channel_id_enabled = channel_id_enabled;
+ ssl->retain_only_sha256_of_client_certs = retain_only_sha256;
+
+ Array<uint8_t> key_block;
+ if (!tls1_configure_aead(ssl, evp_aead_open, &key_block,
+ s3->established_session->cipher, read_iv) ||
+ !tls1_configure_aead(ssl, evp_aead_seal, &key_block,
+ s3->established_session->cipher, write_iv)) {
+ return false;
+ }
+
+ if (!CBS_copy_bytes(&read_seq, s3->read_sequence,
+ sizeof(s3->read_sequence)) ||
+ !CBS_copy_bytes(&write_seq, s3->write_sequence,
+ sizeof(s3->write_sequence))) {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace bssl
diff --git a/src/ssl/handshake.cc b/src/ssl/handshake.cc
index 43afc6c4..64324245 100644
--- a/src/ssl/handshake.cc
+++ b/src/ssl/handshake.cc
@@ -560,6 +560,11 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) {
hs->wait = ssl_hs_ok;
return -1;
+ case ssl_hs_handoff:
+ ssl->s3->rwstate = SSL_HANDOFF;
+ hs->wait = ssl_hs_ok;
+ return -1;
+
case ssl_hs_x509_lookup:
ssl->s3->rwstate = SSL_X509_LOOKUP;
hs->wait = ssl_hs_ok;
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 1f91adbf..e8dd0d37 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -493,8 +493,7 @@ static enum ssl_hs_wait_t do_enter_early_data(SSL_HANDSHAKE *hs) {
}
ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->session->ssl_version);
- if (ssl_is_draft22(ssl->session->ssl_version) &&
- !ssl->method->add_change_cipher_spec(ssl)) {
+ if (!ssl->method->add_change_cipher_spec(ssl)) {
return ssl_hs_error;
}
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index bcbd7e2e..fa8a2410 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -441,6 +441,10 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
+ if (ssl->handoff) {
+ return ssl_hs_handoff;
+ }
+
SSL_CLIENT_HELLO client_hello;
if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 04d534a8..b67637dd 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -342,7 +342,7 @@ class Array {
};
// CBBFinishArray behaves like |CBB_finish| but stores the result in an Array.
-bool CBBFinishArray(CBB *cbb, Array<uint8_t> *out);
+OPENSSL_EXPORT bool CBBFinishArray(CBB *cbb, Array<uint8_t> *out);
// Protocol versions.
@@ -392,18 +392,6 @@ bool ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
// call this function before the version is determined.
uint16_t ssl_protocol_version(const SSL *ssl);
-// ssl_is_draft22 returns whether the version corresponds to a draft22 TLS 1.3
-// variant.
-bool ssl_is_draft22(uint16_t version);
-
-// ssl_is_draft23 returns whether the version corresponds to a draft23 TLS 1.3
-// variant.
-bool ssl_is_draft23(uint16_t version);
-
-// ssl_is_draft23_variant returns whether the variant corresponds to a
-// draft23 TLS 1.3 variant.
- bool ssl_is_draft23_variant(enum tls13_variant_t variant);
-
// Cipher suites.
} // namespace bssl
@@ -1269,6 +1257,7 @@ enum ssl_hs_wait_t {
ssl_hs_read_message,
ssl_hs_flush,
ssl_hs_certificate_selection_pending,
+ ssl_hs_handoff,
ssl_hs_x509_lookup,
ssl_hs_channel_id_lookup,
ssl_hs_private_key_operation,
@@ -2185,6 +2174,11 @@ struct SSLContext {
// false_start_allowed_without_alpn is whether False Start (if
// |SSL_MODE_ENABLE_FALSE_START| is enabled) is allowed without ALPN.
bool false_start_allowed_without_alpn:1;
+
+ // handoff indicates that a server should stop after receiving the
+ // ClientHello and pause the handshake in such a way that |SSL_get_error|
+ // returns |SSL_HANDOFF|.
+ bool handoff:1;
};
// An ssl_shutdown_t describes the shutdown state of one end of the connection,
@@ -2378,6 +2372,9 @@ struct SSL3_STATE {
// verified Channel ID from the client: a P256 point, (x,y), where
// each are big-endian values.
uint8_t tlsext_channel_id[64] = {0};
+
+ // Contains the QUIC transport params received by the peer.
+ Array<uint8_t> peer_quic_transport_params;
};
// lengths of messages
@@ -2546,8 +2543,8 @@ struct SSLConnection {
// session info
- // client cert?
- // This is used to hold the server certificate used
+ // This is used to hold the local certificate used (i.e. the server
+ // certificate for a server or the client certificate for a client).
CERT *cert;
// initial_timeout_duration_ms is the default DTLS timeout duration in
@@ -2629,6 +2626,10 @@ struct SSLConnection {
// |token_binding_negotiated| is set.
uint8_t negotiated_token_binding_param;
+ // Contains the QUIC transport params that this endpoint will send.
+ uint8_t *quic_transport_params;
+ size_t quic_transport_params_len;
+
// renegotiate_mode controls how peer renegotiation attempts are handled.
enum ssl_renegotiate_mode_t renegotiate_mode;
@@ -2663,6 +2664,12 @@ struct SSLConnection {
// hash of the peer's certificate and then discard it to save memory and
// session space. Only effective on the server side.
bool retain_only_sha256_of_client_certs:1;
+
+ // handoff indicates that a server should stop after receiving the
+ // ClientHello and pause the handshake in such a way that |SSL_get_error|
+ // returns |SSL_HANDOFF|. This is copied in |SSL_new| from the |SSL_CTX|
+ // element of the same name and may be cleared if the handoff is declined.
+ bool handoff:1;
};
// From draft-ietf-tls-tls13-18, used in determining PSK modes.
@@ -2852,6 +2859,16 @@ ssl_open_record_t dtls1_open_handshake(SSL *ssl, size_t *out_consumed,
void dtls1_next_message(SSL *ssl);
int dtls1_dispatch_alert(SSL *ssl);
+// tls1_configure_aead configures either the read or write direction AEAD (as
+// determined by |direction|) using the keys generated by the TLS KDF. The
+// |key_block_cache| argument is used to store the generated key block, if
+// empty. Otherwise it's assumed that the key block is already contained within
+// it. Returns one on success or zero on error.
+int tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction,
+ Array<uint8_t> *key_block_cache,
+ const SSL_CIPHER *cipher,
+ Span<const uint8_t> iv_override);
+
int tls1_change_cipher_state(SSL_HANDSHAKE *hs, evp_aead_direction_t direction);
int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
Span<const uint8_t> premaster);
diff --git a/src/ssl/s3_pkt.cc b/src/ssl/s3_pkt.cc
index e14d551a..5eb68f6b 100644
--- a/src/ssl/s3_pkt.cc
+++ b/src/ssl/s3_pkt.cc
@@ -304,14 +304,6 @@ ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span<uint8_t> *out,
const bool is_early_data_read = ssl->server && SSL_in_early_data(ssl);
if (type == SSL3_RT_HANDSHAKE) {
- // If reading 0-RTT data, reject handshake data. 0-RTT data is terminated
- // by an alert.
- if (!ssl_is_draft22(ssl->version) && is_early_data_read) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
- *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
- return ssl_open_record_error;
- }
-
// Post-handshake data prior to TLS 1.3 is always renegotiation, which we
// never accept as a server. Otherwise |ssl3_get_message| will send
// |SSL_R_EXCESSIVE_MESSAGE_SIZE|.
@@ -332,16 +324,6 @@ ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span<uint8_t> *out,
return ssl_open_record_discard;
}
- // Handle the end_of_early_data alert.
- static const uint8_t kEndOfEarlyData[2] = {SSL3_AL_WARNING,
- TLS1_AD_END_OF_EARLY_DATA};
- if (!ssl_is_draft22(ssl->version) && is_early_data_read &&
- type == SSL3_RT_ALERT && body == kEndOfEarlyData) {
- // Stop accepting early data.
- ssl->s3->hs->can_early_read = false;
- return ssl_open_record_discard;
- }
-
if (type != SSL3_RT_APPLICATION_DATA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
*out_alert = SSL_AD_UNEXPECTED_MESSAGE;
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 75e438d4..2fd3beb2 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -465,6 +465,10 @@ void ssl_ctx_get_current_time(const SSL_CTX *ctx,
#endif
}
+void SSL_CTX_set_handoff_mode(SSL_CTX *ctx, bool on) {
+ ctx->handoff = on;
+}
+
} // namespace bssl
using namespace bssl;
@@ -736,6 +740,7 @@ SSL *SSL_new(SSL_CTX *ctx) {
ssl->signed_cert_timestamps_enabled = ctx->signed_cert_timestamps_enabled;
ssl->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled;
+ ssl->handoff = ctx->handoff;
return ssl;
@@ -772,6 +777,7 @@ void SSL_free(SSL *ssl) {
OPENSSL_free(ssl->supported_group_list);
OPENSSL_free(ssl->alpn_client_proto_list);
OPENSSL_free(ssl->token_binding_params);
+ OPENSSL_free(ssl->quic_transport_params);
EVP_PKEY_free(ssl->tlsext_channel_id_private);
OPENSSL_free(ssl->psk_identity_hint);
sk_CRYPTO_BUFFER_pop_free(ssl->client_CA, CRYPTO_BUFFER_free);
@@ -1164,6 +1170,23 @@ int SSL_send_fatal_alert(SSL *ssl, uint8_t alert) {
return ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
}
+int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params,
+ size_t params_len) {
+ ssl->quic_transport_params = (uint8_t *)BUF_memdup(params, params_len);
+ if (!ssl->quic_transport_params) {
+ return 0;
+ }
+ ssl->quic_transport_params_len = params_len;
+ return 1;
+}
+
+void SSL_get_peer_quic_transport_params(const SSL *ssl,
+ const uint8_t **out_params,
+ size_t *out_params_len) {
+ *out_params = ssl->s3->peer_quic_transport_params.data();
+ *out_params_len = ssl->s3->peer_quic_transport_params.size();
+}
+
void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) {
ctx->cert->enable_early_data = !!enabled;
}
@@ -1251,6 +1274,9 @@ int SSL_get_error(const SSL *ssl, int ret_code) {
case SSL_CERTIFICATE_SELECTION_PENDING:
return SSL_ERROR_PENDING_CERTIFICATE;
+ case SSL_HANDOFF:
+ return SSL_ERROR_HANDOFF;
+
case SSL_READING: {
BIO *bio = SSL_get_rbio(ssl);
if (BIO_should_read(bio)) {
diff --git a/src/ssl/ssl_privkey.cc b/src/ssl/ssl_privkey.cc
index 134ad561..33cc720a 100644
--- a/src/ssl/ssl_privkey.cc
+++ b/src/ssl/ssl_privkey.cc
@@ -205,6 +205,9 @@ enum ssl_private_key_result_t ssl_private_key_sign(
ret = ssl->cert->key_method->sign(ssl, out, out_len, max_out, sigalg,
in.data(), in.size());
}
+ if (ret == ssl_private_key_failure) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED);
+ }
hs->pending_private_key_op = ret == ssl_private_key_retry;
return ret;
}
@@ -241,6 +244,9 @@ enum ssl_private_key_result_t ssl_private_key_decrypt(SSL_HANDSHAKE *hs,
ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out,
in.data(), in.size());
}
+ if (ret == ssl_private_key_failure) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED);
+ }
hs->pending_private_key_op = ret == ssl_private_key_retry;
return ret;
}
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 6c4282e4..0f2a33cf 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -1537,7 +1537,8 @@ struct ClientConfig {
static bool ConnectClientAndServer(bssl::UniquePtr<SSL> *out_client,
bssl::UniquePtr<SSL> *out_server,
SSL_CTX *client_ctx, SSL_CTX *server_ctx,
- const ClientConfig &config = ClientConfig()) {
+ const ClientConfig &config = ClientConfig(),
+ bool do_handshake = true) {
bssl::UniquePtr<SSL> client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
if (!client || !server) {
return false;
@@ -1561,7 +1562,7 @@ static bool ConnectClientAndServer(bssl::UniquePtr<SSL> *out_client,
SSL_set_bio(client.get(), bio1, bio1);
SSL_set_bio(server.get(), bio2, bio2);
- if (!CompleteHandshakes(client.get(), server.get())) {
+ if (do_handshake && !CompleteHandshakes(client.get(), server.get())) {
return false;
}
@@ -2618,7 +2619,7 @@ TEST(SSLTest, SetVersion) {
// TLS1_3_DRAFT_VERSION is not an API-level version.
EXPECT_FALSE(
- SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_DRAFT22_VERSION));
+ SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_DRAFT23_VERSION));
ERR_clear_error();
ctx.reset(SSL_CTX_new(DTLS_method()));
@@ -3923,6 +3924,139 @@ TEST(SSLTest, SignatureAlgorithmProperties) {
EXPECT_TRUE(SSL_is_signature_algorithm_rsa_pss(SSL_SIGN_RSA_PSS_SHA384));
}
+void MoveBIOs(SSL *dest, SSL *src) {
+ BIO *rbio = SSL_get_rbio(src);
+ BIO_up_ref(rbio);
+ SSL_set0_rbio(dest, rbio);
+
+ BIO *wbio = SSL_get_wbio(src);
+ BIO_up_ref(wbio);
+ SSL_set0_wbio(dest, wbio);
+
+ SSL_set0_rbio(src, nullptr);
+ SSL_set0_wbio(src, nullptr);
+}
+
+TEST(SSLTest, Handoff) {
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+ bssl::UniquePtr<SSL_CTX> handshaker_ctx(SSL_CTX_new(TLS_method()));
+ ASSERT_TRUE(client_ctx);
+ ASSERT_TRUE(server_ctx);
+ ASSERT_TRUE(handshaker_ctx);
+
+ SSL_CTX_set_handoff_mode(server_ctx.get(), 1);
+ ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_2_VERSION));
+ ASSERT_TRUE(
+ SSL_CTX_set_max_proto_version(handshaker_ctx.get(), TLS1_2_VERSION));
+
+ bssl::UniquePtr<X509> cert = GetTestCertificate();
+ bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+ ASSERT_TRUE(cert);
+ ASSERT_TRUE(key);
+ ASSERT_TRUE(SSL_CTX_use_certificate(handshaker_ctx.get(), cert.get()));
+ ASSERT_TRUE(SSL_CTX_use_PrivateKey(handshaker_ctx.get(), key.get()));
+
+ bssl::UniquePtr<SSL> client, server;
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get(), ClientConfig(),
+ false /* don't handshake */));
+
+ int client_ret = SSL_do_handshake(client.get());
+ int client_err = SSL_get_error(client.get(), client_ret);
+ ASSERT_EQ(client_err, SSL_ERROR_WANT_READ);
+
+ int server_ret = SSL_do_handshake(server.get());
+ int server_err = SSL_get_error(server.get(), server_ret);
+ ASSERT_EQ(server_err, SSL_ERROR_HANDOFF);
+
+ ScopedCBB cbb;
+ Array<uint8_t> handoff;
+ ASSERT_TRUE(CBB_init(cbb.get(), 256));
+ ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get()));
+ ASSERT_TRUE(CBBFinishArray(cbb.get(), &handoff));
+
+ bssl::UniquePtr<SSL> handshaker(SSL_new(handshaker_ctx.get()));
+ ASSERT_TRUE(SSL_apply_handoff(handshaker.get(), handoff));
+
+ MoveBIOs(handshaker.get(), server.get());
+
+ int handshake_ret = SSL_do_handshake(handshaker.get());
+ int handshake_err = SSL_get_error(handshaker.get(), handshake_ret);
+ ASSERT_EQ(handshake_err, SSL_ERROR_WANT_READ);
+
+ ASSERT_TRUE(CompleteHandshakes(client.get(), handshaker.get()));
+
+ ScopedCBB cbb_handback;
+ Array<uint8_t> handback;
+ ASSERT_TRUE(CBB_init(cbb_handback.get(), 1024));
+ ASSERT_TRUE(SSL_serialize_handback(handshaker.get(), cbb_handback.get()));
+ ASSERT_TRUE(CBBFinishArray(cbb_handback.get(), &handback));
+
+ bssl::UniquePtr<SSL> server2(SSL_new(server_ctx.get()));
+ ASSERT_TRUE(SSL_apply_handback(server2.get(), handback));
+
+ MoveBIOs(server2.get(), handshaker.get());
+
+ uint8_t byte = 42;
+ EXPECT_EQ(SSL_write(client.get(), &byte, 1), 1);
+ EXPECT_EQ(SSL_read(server2.get(), &byte, 1), 1);
+ EXPECT_EQ(42, byte);
+
+ byte = 43;
+ EXPECT_EQ(SSL_write(server2.get(), &byte, 1), 1);
+ EXPECT_EQ(SSL_read(client.get(), &byte, 1), 1);
+ EXPECT_EQ(43, byte);
+}
+
+TEST(SSLTest, HandoffDeclined) {
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+ ASSERT_TRUE(client_ctx);
+ ASSERT_TRUE(server_ctx);
+
+ SSL_CTX_set_handoff_mode(server_ctx.get(), 1);
+ ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_2_VERSION));
+
+ bssl::UniquePtr<X509> cert = GetTestCertificate();
+ bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+ ASSERT_TRUE(cert);
+ ASSERT_TRUE(key);
+ ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+ ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
+
+ bssl::UniquePtr<SSL> client, server;
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get(), ClientConfig(),
+ false /* don't handshake */));
+
+ int client_ret = SSL_do_handshake(client.get());
+ int client_err = SSL_get_error(client.get(), client_ret);
+ ASSERT_EQ(client_err, SSL_ERROR_WANT_READ);
+
+ int server_ret = SSL_do_handshake(server.get());
+ int server_err = SSL_get_error(server.get(), server_ret);
+ ASSERT_EQ(server_err, SSL_ERROR_HANDOFF);
+
+ ScopedCBB cbb;
+ ASSERT_TRUE(CBB_init(cbb.get(), 256));
+ ASSERT_TRUE(SSL_serialize_handoff(server.get(), cbb.get()));
+
+ ASSERT_TRUE(SSL_decline_handoff(server.get()));
+
+ ASSERT_TRUE(CompleteHandshakes(client.get(), server.get()));
+
+ uint8_t byte = 42;
+ EXPECT_EQ(SSL_write(client.get(), &byte, 1), 1);
+ EXPECT_EQ(SSL_read(server.get(), &byte, 1), 1);
+ EXPECT_EQ(42, byte);
+
+ byte = 43;
+ EXPECT_EQ(SSL_write(server.get(), &byte, 1), 1);
+ EXPECT_EQ(SSL_read(client.get(), &byte, 1), 1);
+ EXPECT_EQ(43, byte);
+}
+
// TODO(davidben): Convert this file to GTest properly.
TEST(SSLTest, AllTests) {
if (!TestSSL_SESSIONEncoding(kOpenSSLSession) ||
diff --git a/src/ssl/ssl_versions.cc b/src/ssl/ssl_versions.cc
index 15012dc8..aeb41d3d 100644
--- a/src/ssl/ssl_versions.cc
+++ b/src/ssl/ssl_versions.cc
@@ -34,9 +34,7 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
*out = version;
return true;
- case TLS1_3_DRAFT22_VERSION:
case TLS1_3_DRAFT23_VERSION:
- case TLS1_3_EXPERIMENT2_VERSION:
*out = TLS1_3_VERSION;
return true;
@@ -59,8 +57,6 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
static const uint16_t kTLSVersions[] = {
TLS1_3_DRAFT23_VERSION,
- TLS1_3_DRAFT22_VERSION,
- TLS1_3_EXPERIMENT2_VERSION,
TLS1_2_VERSION,
TLS1_1_VERSION,
TLS1_VERSION,
@@ -103,9 +99,7 @@ static bool method_supports_version(const SSL_PROTOCOL_METHOD *method,
static const char *ssl_version_to_string(uint16_t version) {
switch (version) {
- case TLS1_3_DRAFT22_VERSION:
case TLS1_3_DRAFT23_VERSION:
- case TLS1_3_EXPERIMENT2_VERSION:
return "TLSv1.3";
case TLS1_2_VERSION:
@@ -134,9 +128,7 @@ static const char *ssl_version_to_string(uint16_t version) {
static uint16_t wire_version_to_api(uint16_t version) {
switch (version) {
// Report TLS 1.3 draft versions as TLS 1.3 in the public API.
- case TLS1_3_DRAFT22_VERSION:
case TLS1_3_DRAFT23_VERSION:
- case TLS1_3_EXPERIMENT2_VERSION:
return TLS1_3_VERSION;
default:
return version;
@@ -147,13 +139,11 @@ static uint16_t wire_version_to_api(uint16_t version) {
// particular, it picks an arbitrary TLS 1.3 representative. This should only be
// used in context where that does not matter.
static bool api_version_to_wire(uint16_t *out, uint16_t version) {
- if (version == TLS1_3_DRAFT22_VERSION ||
- version == TLS1_3_DRAFT23_VERSION ||
- version == TLS1_3_EXPERIMENT2_VERSION) {
+ if (version == TLS1_3_DRAFT23_VERSION) {
return false;
}
if (version == TLS1_3_VERSION) {
- version = TLS1_3_DRAFT22_VERSION;
+ version = TLS1_3_DRAFT23_VERSION;
}
// Check it is a real protocol version.
@@ -304,12 +294,10 @@ bool ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) {
return false;
}
- // TLS 1.3 variants must additionally match |tls13_variant|.
+ // This logic is part of the TLS 1.3 variants mechanism used in TLS 1.3
+ // experimentation. Although we currently only have one variant, TLS 1.3 does
+ // not a final stable deployment yet, so leave the logic in place for now.
if (protocol_version != TLS1_3_VERSION ||
- (ssl->tls13_variant == tls13_experiment2 &&
- version == TLS1_3_EXPERIMENT2_VERSION) ||
- (ssl->tls13_variant == tls13_draft22 &&
- version == TLS1_3_DRAFT22_VERSION) ||
(ssl->tls13_variant == tls13_default &&
version == TLS1_3_DRAFT23_VERSION)) {
return true;
@@ -368,18 +356,6 @@ bool ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
return false;
}
-bool ssl_is_draft22(uint16_t version) {
- return version == TLS1_3_DRAFT22_VERSION || version == TLS1_3_DRAFT23_VERSION;
-}
-
-bool ssl_is_draft23(uint16_t version) {
- return version == TLS1_3_DRAFT23_VERSION;
-}
-
-bool ssl_is_draft23_variant(tls13_variant_t variant) {
- return variant == tls13_default;
-}
-
} // namespace bssl
using namespace bssl;
diff --git a/src/ssl/t1_enc.cc b/src/ssl/t1_enc.cc
index d1fb7109..5947627e 100644
--- a/src/ssl/t1_enc.cc
+++ b/src/ssl/t1_enc.cc
@@ -239,10 +239,10 @@ static bool get_key_block_lengths(const SSL *ssl, size_t *out_mac_secret_len,
return true;
}
-static int tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction,
- Array<uint8_t> *key_block_cache,
- const SSL_CIPHER *cipher,
- Span<const uint8_t> iv_override) {
+int tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction,
+ Array<uint8_t> *key_block_cache,
+ const SSL_CIPHER *cipher,
+ Span<const uint8_t> iv_override) {
size_t mac_secret_len, key_len, iv_len;
if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &iv_len, cipher)) {
return 0;
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 4303d4e0..02ed22be 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -551,10 +551,6 @@ static bool forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
return true;
}
-static bool dont_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
- return true;
-}
-
static bool ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
// This extension from the client is handled elsewhere.
@@ -1821,7 +1817,6 @@ static bool ext_pre_shared_key_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
// selected cipher in HelloRetryRequest does not match. This avoids performing
// the transcript hash transformation for multiple hashes.
if (hs->received_hello_retry_request &&
- ssl_is_draft22(ssl->version) &&
ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) {
return true;
}
@@ -2091,9 +2086,7 @@ static bool ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
}
CBB contents, kse_bytes;
- if (!CBB_add_u16(out, ssl_is_draft23_variant(ssl->tls13_variant)
- ? TLSEXT_TYPE_new_key_share
- : TLSEXT_TYPE_old_key_share) ||
+ if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &kse_bytes)) {
return false;
@@ -2250,9 +2243,7 @@ bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
uint16_t group_id;
CBB kse_bytes, public_key;
if (!tls1_get_shared_group(hs, &group_id) ||
- !CBB_add_u16(out, ssl_is_draft23(hs->ssl->version)
- ? TLSEXT_TYPE_new_key_share
- : TLSEXT_TYPE_old_key_share) ||
+ !CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
!CBB_add_u16_length_prefixed(out, &kse_bytes) ||
!CBB_add_u16(&kse_bytes, group_id) ||
!CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
@@ -2588,6 +2579,77 @@ static bool ext_token_binding_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
return true;
}
+// QUIC Transport Parameters
+
+static bool ext_quic_transport_params_add_clienthello(SSL_HANDSHAKE *hs,
+ CBB *out) {
+ SSL *const ssl = hs->ssl;
+ if (!ssl->quic_transport_params || hs->max_version <= TLS1_2_VERSION) {
+ return true;
+ }
+
+ CBB contents;
+ if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
+ !CBB_add_u16_length_prefixed(out, &contents) ||
+ !CBB_add_bytes(&contents, ssl->quic_transport_params,
+ ssl->quic_transport_params_len) ||
+ !CBB_flush(out)) {
+ return false;
+ }
+ return true;
+}
+
+static bool ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
+ CBS *contents) {
+ SSL *const ssl = hs->ssl;
+ if (contents == nullptr) {
+ return true;
+ }
+ // QUIC requires TLS 1.3.
+ if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
+ *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+ return false;
+ }
+
+ return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
+}
+
+static bool ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
+ CBS *contents) {
+ SSL *const ssl = hs->ssl;
+ if (!contents || !ssl->quic_transport_params) {
+ return true;
+ }
+ // Ignore the extension before TLS 1.3.
+ if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
+ return true;
+ }
+
+ return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
+}
+
+static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
+ CBB *out) {
+ SSL *const ssl = hs->ssl;
+ if (!ssl->quic_transport_params) {
+ return true;
+ }
+
+ CBB contents;
+ if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
+ !CBB_add_u16_length_prefixed(out, &contents) ||
+ !CBB_add_bytes(&contents, ssl->quic_transport_params,
+ ssl->quic_transport_params_len) ||
+ !CBB_flush(out)) {
+ return false;
+ }
+
+ return true;
+}
+
+
// kExtensions contains all the supported extensions.
static const struct tls_extension kExtensions[] = {
{
@@ -2689,16 +2751,7 @@ static const struct tls_extension kExtensions[] = {
ext_ec_point_add_serverhello,
},
{
- TLSEXT_TYPE_old_key_share,
- // This is added by TLSEXT_TYPE_new_key_share's callback.
- NULL,
- dont_add_clienthello,
- forbid_parse_serverhello,
- ignore_parse_clienthello,
- dont_add_serverhello,
- },
- {
- TLSEXT_TYPE_new_key_share,
+ TLSEXT_TYPE_key_share,
NULL,
ext_key_share_add_clienthello,
forbid_parse_serverhello,
@@ -2745,6 +2798,14 @@ static const struct tls_extension kExtensions[] = {
ignore_parse_clienthello,
dont_add_serverhello,
},
+ {
+ TLSEXT_TYPE_quic_transport_parameters,
+ NULL,
+ ext_quic_transport_params_add_clienthello,
+ ext_quic_transport_params_parse_serverhello,
+ ext_quic_transport_params_parse_clienthello,
+ ext_quic_transport_params_add_serverhello,
+ },
// The final extension must be non-empty. WebSphere Application Server 7.0 is
// intolerant to the last extension being zero-length. See
// https://crbug.com/363583.
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 50182b1b..5790dc3f 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -150,6 +150,32 @@ static TestState *GetTestState(const SSL *ssl) {
return (TestState *)SSL_get_ex_data(ssl, g_state_index);
}
+static bool MoveExData(SSL *dest, SSL *src) {
+ TestState *state = GetTestState(src);
+ const TestConfig *config = GetTestConfig(src);
+ if (!SSL_set_ex_data(src, g_state_index, nullptr) ||
+ !SSL_set_ex_data(dest, g_state_index, state) ||
+ !SSL_set_ex_data(src, g_config_index, nullptr) ||
+ !SSL_set_ex_data(dest, g_config_index, (void *) config)) {
+ return false;
+ }
+
+ return true;
+}
+
+static void MoveBIOs(SSL *dest, SSL *src) {
+ BIO *rbio = SSL_get_rbio(src);
+ BIO_up_ref(rbio);
+ SSL_set0_rbio(dest, rbio);
+
+ BIO *wbio = SSL_get_wbio(src);
+ BIO_up_ref(wbio);
+ SSL_set0_wbio(dest, wbio);
+
+ SSL_set0_rbio(src, nullptr);
+ SSL_set0_wbio(src, nullptr);
+}
+
static bool LoadCertificate(bssl::UniquePtr<X509> *out_x509,
bssl::UniquePtr<STACK_OF(X509)> *out_chain,
const std::string &file) {
@@ -1711,6 +1737,19 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
}
}
+ if (!config->expected_quic_transport_params.empty()) {
+ const uint8_t *peer_params;
+ size_t peer_params_len;
+ SSL_get_peer_quic_transport_params(ssl, &peer_params, &peer_params_len);
+ if (peer_params_len != config->expected_quic_transport_params.size() ||
+ OPENSSL_memcmp(peer_params,
+ config->expected_quic_transport_params.data(),
+ peer_params_len) != 0) {
+ fprintf(stderr, "QUIC transport params mismatch\n");
+ return false;
+ }
+ }
+
if (!config->expected_channel_id.empty()) {
uint8_t channel_id[64];
if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
@@ -1889,7 +1928,8 @@ static bool WriteSettings(int i, const TestConfig *config,
return fwrite(settings, settings_len, 1, file.get()) == 1;
}
-static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session, SSL *ssl,
+static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
+ bssl::UniquePtr<SSL> *ssl_uniqueptr,
const TestConfig *config, bool is_resume, bool is_retry);
// DoConnection tests an SSL connection against the peer. On success, it returns
@@ -2076,6 +2116,15 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
!SSL_set_dummy_pq_padding_size(ssl.get(), config->dummy_pq_padding_len)) {
return false;
}
+ if (!config->quic_transport_params.empty()) {
+ if (!SSL_set_quic_transport_params(
+ ssl.get(),
+ reinterpret_cast<const uint8_t *>(
+ config->quic_transport_params.data()),
+ config->quic_transport_params.size())) {
+ return false;
+ }
+ }
int sock = Connect(config->port);
if (sock == -1) {
@@ -2133,7 +2182,7 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
SSL_set_connect_state(ssl.get());
}
- bool ret = DoExchange(out_session, ssl.get(), config, is_resume, false);
+ bool ret = DoExchange(out_session, &ssl, config, is_resume, false);
if (!config->is_server && is_resume && config->expect_reject_early_data) {
// We must have failed due to an early data rejection.
if (ret) {
@@ -2167,7 +2216,8 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
return false;
}
- ret = DoExchange(out_session, ssl.get(), retry_config, is_resume, true);
+ assert(!config->handoff);
+ ret = DoExchange(out_session, &ssl, retry_config, is_resume, true);
}
if (!ret) {
@@ -2190,21 +2240,110 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
return true;
}
-static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session, SSL *ssl,
+static bool HandoffReady(SSL *ssl, int ret) {
+ return ret < 0 && SSL_get_error(ssl, ret) == SSL_ERROR_HANDOFF;
+}
+
+static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
+ bssl::UniquePtr<SSL> *ssl_uniqueptr,
const TestConfig *config, bool is_resume,
bool is_retry) {
int ret;
+ SSL *ssl = ssl_uniqueptr->get();
+
if (!config->implicit_handshake) {
+ if (config->handoff) {
+ bssl::UniquePtr<SSL_CTX> ctx_handoff(SSL_CTX_new(TLSv1_method()));
+ if (!ctx_handoff) {
+ return false;
+ }
+ SSL_CTX_set_handoff_mode(ctx_handoff.get(), 1);
+
+ bssl::UniquePtr<SSL> ssl_handoff(SSL_new(ctx_handoff.get()));
+ if (!ssl_handoff) {
+ return false;
+ }
+ SSL_set_accept_state(ssl_handoff.get());
+ if (!MoveExData(ssl_handoff.get(), ssl)) {
+ return false;
+ }
+ MoveBIOs(ssl_handoff.get(), ssl);
+
+ do {
+ ret = CheckIdempotentError("SSL_do_handshake", ssl_handoff.get(),
+ [&]() -> int {
+ return SSL_do_handshake(ssl_handoff.get());
+ });
+ } while (!HandoffReady(ssl_handoff.get(), ret) &&
+ config->async &&
+ RetryAsync(ssl_handoff.get(), ret));
+
+ if (!HandoffReady(ssl_handoff.get(), ret)) {
+ fprintf(stderr, "Handshake failed while waiting for handoff.\n");
+ return false;
+ }
+
+ bssl::ScopedCBB cbb;
+ bssl::Array<uint8_t> handoff;
+ if (!CBB_init(cbb.get(), 512) ||
+ !SSL_serialize_handoff(ssl_handoff.get(), cbb.get()) ||
+ !CBBFinishArray(cbb.get(), &handoff)) {
+ fprintf(stderr, "Handoff serialisation failed.\n");
+ return false;
+ }
+
+ MoveBIOs(ssl, ssl_handoff.get());
+ if (!MoveExData(ssl, ssl_handoff.get())) {
+ return false;
+ }
+
+ if (!SSL_apply_handoff(ssl, handoff)) {
+ fprintf(stderr, "Handoff application failed.\n");
+ return false;
+ }
+ }
+
do {
ret = CheckIdempotentError("SSL_do_handshake", ssl, [&]() -> int {
return SSL_do_handshake(ssl);
});
} while (config->async && RetryAsync(ssl, ret));
+
if (ret != 1 ||
!CheckHandshakeProperties(ssl, is_resume, config)) {
return false;
}
+ if (config->handoff) {
+ bssl::ScopedCBB cbb;
+ bssl::Array<uint8_t> handback;
+ if (!CBB_init(cbb.get(), 512) ||
+ !SSL_serialize_handback(ssl, cbb.get()) ||
+ !CBBFinishArray(cbb.get(), &handback)) {
+ fprintf(stderr, "Handback serialisation failed.\n");
+ return false;
+ }
+
+ bssl::UniquePtr<SSL_CTX> ctx_handback(SSL_CTX_new(TLSv1_method()));
+ SSL_CTX_set_msg_callback(ctx_handback.get(), MessageCallback);
+ bssl::UniquePtr<SSL> ssl_handback(SSL_new(ctx_handback.get()));
+ if (!ssl_handback) {
+ return false;
+ }
+ if (!SSL_apply_handback(ssl_handback.get(), handback)) {
+ fprintf(stderr, "Applying handback failed.\n");
+ return false;
+ }
+
+ MoveBIOs(ssl_handback.get(), ssl);
+ if (!MoveExData(ssl_handback.get(), ssl)) {
+ return false;
+ }
+
+ *ssl_uniqueptr = std::move(ssl_handback);
+ ssl = ssl_uniqueptr->get();
+ }
+
if (is_resume && !is_retry && !config->is_server &&
config->expect_no_offer_early_data && SSL_in_early_data(ssl)) {
fprintf(stderr, "Client unexpectedly offered early data.\n");
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index d89f7fb1..fef51291 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -33,21 +33,15 @@ const (
// A draft version of TLS 1.3 that is sent over the wire for the current draft.
const (
- tls13Experiment2Version = 0x7e02
- tls13Draft22Version = 0x7f16
- tls13Draft23Version = 0x7f17
+ tls13Draft23Version = 0x7f17
)
const (
- TLS13Draft23 = 0
- TLS13Experiment2 = 1
- TLS13Draft22 = 2
+ TLS13Draft23 = 0
)
var allTLSWireVersions = []uint16{
tls13Draft23Version,
- tls13Draft22Version,
- tls13Experiment2Version,
VersionTLS12,
VersionTLS11,
VersionTLS10,
@@ -123,8 +117,8 @@ const (
extensionPadding uint16 = 21
extensionExtendedMasterSecret uint16 = 23
extensionTokenBinding uint16 = 24
+ extensionQUICTransportParams uint16 = 26
extensionSessionTicket uint16 = 35
- extensionOldKeyShare uint16 = 40 // draft-ietf-tls-tls13-16
extensionPreSharedKey uint16 = 41 // draft-ietf-tls-tls13-16
extensionEarlyData uint16 = 42 // draft-ietf-tls-tls13-16
extensionSupportedVersions uint16 = 43 // draft-ietf-tls-tls13-16
@@ -132,7 +126,7 @@ const (
extensionPSKKeyExchangeModes uint16 = 45 // draft-ietf-tls-tls13-18
extensionTicketEarlyDataInfo uint16 = 46 // draft-ietf-tls-tls13-18
extensionCertificateAuthorities uint16 = 47 // draft-ietf-tls-tls13-21
- extensionNewKeyShare uint16 = 51 // draft-ietf-tls-tls13-23
+ extensionKeyShare uint16 = 51 // draft-ietf-tls-tls13-23
extensionCustom uint16 = 1234 // not IANA assigned
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
@@ -269,6 +263,7 @@ type ConnectionState struct {
SCTList []byte // signed certificate timestamp list
PeerSignatureAlgorithm signatureAlgorithm // algorithm used by the peer in the handshake
CurveID CurveID // the curve used in ECDHE
+ QUICTransportParams []byte // the QUIC transport params received from the peer
}
// ClientAuthType declares the policy the server will follow for
@@ -496,6 +491,10 @@ type Config struct {
// supported signature algorithms that are accepted.
VerifySignatureAlgorithms []signatureAlgorithm
+ // QUICTransportParams, if not empty, will be sent in the QUIC
+ // transport parameters extension.
+ QUICTransportParams []byte
+
// Bugs specifies optional misbehaviour to be used for testing other
// implementations.
Bugs ProtocolBugs
@@ -1664,7 +1663,7 @@ func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
switch vers {
case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
return vers, true
- case tls13Draft23Version, tls13Draft22Version, tls13Experiment2Version:
+ case tls13Draft23Version:
return VersionTLS13, true
}
}
@@ -1672,21 +1671,11 @@ func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
return 0, false
}
-func isDraft22(vers uint16) bool {
- return vers == tls13Draft22Version || vers == tls13Draft23Version
-}
-
-func isDraft23(vers uint16) bool {
- return vers == tls13Draft23Version
-}
-
// isSupportedVersion checks if the specified wire version is acceptable. If so,
// it returns true and the corresponding protocol version. Otherwise, it returns
// false.
func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) {
- if (c.TLS13Variant != TLS13Experiment2 && wireVers == tls13Experiment2Version) ||
- (c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version) ||
- (c.TLS13Variant != TLS13Draft22 && wireVers == tls13Draft22Version) {
+ if c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version {
return 0, false
}
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index c38fba9a..79cd06a7 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -62,6 +62,9 @@ type Conn struct {
// curveID contains the curve that was used in the handshake, or zero if
// not applicable.
curveID CurveID
+ // quicTransportParams contains the QUIC transport params received
+ // by the peer.
+ quicTransportParams []byte
clientRandom, serverRandom [32]byte
earlyExporterSecret []byte
@@ -1563,9 +1566,7 @@ func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMs
earlyALPN: c.clientProtocol,
}
- if isDraft22(c.wireVersion) {
- session.masterSecret = deriveSessionPSK(cipherSuite, c.wireVersion, c.resumptionSecret, newSessionTicket.ticketNonce)
- }
+ session.masterSecret = deriveSessionPSK(cipherSuite, c.wireVersion, c.resumptionSecret, newSessionTicket.ticketNonce)
cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
_, ok := c.config.ClientSessionCache.Get(cacheKey)
@@ -1822,6 +1823,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.SCTList = c.sctList
state.PeerSignatureAlgorithm = c.peerSignatureAlgorithm
state.CurveID = c.curveID
+ state.QUICTransportParams = c.quicTransportParams
}
return state
@@ -1856,16 +1858,13 @@ func (c *Conn) exportKeyingMaterialTLS13(length int, secret, label, context []by
if cipherSuite == nil {
cipherSuite = c.earlyCipherSuite
}
- if isDraft22(c.wireVersion) {
- hash := cipherSuite.hash()
- exporterKeyingLabel := []byte("exporter")
- contextHash := hash.New()
- contextHash.Write(context)
- exporterContext := hash.New().Sum(nil)
- derivedSecret := hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, secret, label, exporterContext, hash.Size())
- return hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length)
- }
- return hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, secret, label, context, length)
+ hash := cipherSuite.hash()
+ exporterKeyingLabel := []byte("exporter")
+ contextHash := hash.New()
+ contextHash.Write(context)
+ exporterContext := hash.New().Sum(nil)
+ derivedSecret := hkdfExpandLabel(cipherSuite.hash(), secret, label, exporterContext, hash.Size())
+ return hkdfExpandLabel(cipherSuite.hash(), derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length)
}
// ExportKeyingMaterial exports keying material from the current connection
@@ -1950,13 +1949,10 @@ func (c *Conn) SendNewSessionTicket(nonce []byte) error {
duplicateEarlyDataExtension: c.config.Bugs.DuplicateTicketEarlyData,
customExtension: c.config.Bugs.CustomTicketExtension,
ticketAgeAdd: ticketAgeAdd,
+ ticketNonce: nonce,
maxEarlyDataSize: c.config.MaxEarlyDataSize,
}
- if isDraft22(c.wireVersion) {
- m.ticketNonce = nonce
- }
-
if c.config.Bugs.SendTicketLifetime != 0 {
m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second)
}
@@ -1964,7 +1960,7 @@ func (c *Conn) SendNewSessionTicket(nonce []byte) error {
state := sessionState{
vers: c.vers,
cipherSuite: c.cipherSuite.id,
- masterSecret: c.resumptionSecret,
+ masterSecret: deriveSessionPSK(c.cipherSuite, c.wireVersion, c.resumptionSecret, nonce),
certificates: peerCertificatesRaw,
ticketCreationTime: c.config.time(),
ticketExpiration: c.config.time().Add(time.Duration(m.ticketLifetime) * time.Second),
@@ -1972,10 +1968,6 @@ func (c *Conn) SendNewSessionTicket(nonce []byte) error {
earlyALPN: []byte(c.clientProtocol),
}
- if isDraft22(c.wireVersion) {
- state.masterSecret = deriveSessionPSK(c.cipherSuite, c.wireVersion, c.resumptionSecret, nonce)
- }
-
if !c.config.Bugs.SendEmptySessionTicket {
var err error
m.ticket, err = c.encryptTicket(&state)
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index 89ba707e..a840f37f 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -7,7 +7,7 @@
"DTLSIgnoreBadPackets*": "Fuzzer mode has no bad packets.",
"TLSFatalBadPackets": "Fuzzer mode has no bad packets.",
- "*-BadRecord": "Fuzzer mode has no bad packets.",
+ "*-BadRecord*": "Fuzzer mode has no bad packets.",
"BadRSAClientKeyExchange*": "Fuzzer mode does not notice a bad premaster secret.",
@@ -22,7 +22,7 @@
"*Auth-Verify-ECDSA-SHA1-TLS13*": "Fuzzer mode always accepts a signature.",
"*Auth-Verify-ECDSA-P224-*-TLS13*": "Fuzzer mode always accepts a signature.",
"Verify-*Auth-SignatureType*": "Fuzzer mode always accepts a signature.",
- "ECDSACurveMismatch-Verify-TLS13": "Fuzzer mode always accepts a signature.",
+ "ECDSACurveMismatch-Verify-TLS13*": "Fuzzer mode always accepts a signature.",
"InvalidChannelIDSignature-*": "Fuzzer mode always accepts a signature.",
"Resume-Server-CipherNotPreferred*": "Fuzzer mode does not encrypt tickets.",
@@ -30,7 +30,7 @@
"Resume-Server-DeclineCrossVersion*": "Fuzzer mode does not encrypt tickets.",
"TicketCallback-SingleCall-*": "Fuzzer mode does not encrypt tickets.",
"CorruptTicket-*": "Fuzzer mode does not encrypt tickets.",
- "ShimTicketRewritable": "Fuzzer mode does not encrypt tickets.",
+ "ShimTicketRewritable*": "Fuzzer mode does not encrypt tickets.",
"Resume-Server-*Binder*": "Fuzzer mode does not check binders.",
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index ab41e120..11402698 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -87,6 +87,7 @@ func (c *Conn) clientHandshake() error {
nextProtoNeg: len(c.config.NextProtos) > 0,
secureRenegotiation: []byte{},
alpnProtocols: c.config.NextProtos,
+ quicTransportParams: c.config.QUICTransportParams,
duplicateExtension: c.config.Bugs.DuplicateExtension,
channelIDSupported: c.config.ChannelID != nil,
tokenBindingParams: c.config.TokenBindingParams,
@@ -161,11 +162,6 @@ func (c *Conn) clientHandshake() error {
if maxVersion >= VersionTLS13 {
keyShares = make(map[CurveID]ecdhCurve)
hello.hasKeyShares = true
- if c.config.TLS13Variant == TLS13Draft23 {
- hello.keyShareExtension = extensionNewKeyShare
- } else {
- hello.keyShareExtension = extensionOldKeyShare
- }
hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
curvesToSend := c.config.defaultCurves()
for _, curveID := range hello.supportedCurves {
@@ -384,7 +380,7 @@ NextCipherSuite:
// set. Fill in an arbitrary TLS 1.3 version to compute
// the binder.
if session.vers < VersionTLS13 {
- version = tls13Draft22Version
+ version = tls13Draft23Version
}
generatePSKBinders(version, hello, pskCipherSuite, session.masterSecret, []byte{}, []byte{}, c.config)
}
@@ -421,7 +417,7 @@ NextCipherSuite:
finishedHash.addEntropy(session.masterSecret)
finishedHash.Write(helloBytes)
- if !c.config.Bugs.SkipChangeCipherSpec && isDraft22(session.wireVersion) {
+ if !c.config.Bugs.SkipChangeCipherSpec {
c.wireVersion = session.wireVersion
c.vers = VersionTLS13
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
@@ -429,14 +425,8 @@ NextCipherSuite:
c.vers = 0
}
- var earlyTrafficSecret []byte
- if isDraft22(session.wireVersion) {
- earlyTrafficSecret = finishedHash.deriveSecret(earlyTrafficLabelDraft22)
- c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabelDraft22)
- } else {
- earlyTrafficSecret = finishedHash.deriveSecret(earlyTrafficLabel)
- c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel)
- }
+ earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
+ c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel)
c.useOutTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret)
for _, earlyData := range c.config.Bugs.SendEarlyData {
@@ -497,7 +487,7 @@ NextCipherSuite:
c.vers = serverVersion
c.haveVers = true
- if isDraft22(c.wireVersion) {
+ if c.vers >= VersionTLS13 {
// The first server message must be followed by a ChangeCipherSpec.
c.expectTLS13ChangeCipherSpec = true
}
@@ -505,12 +495,10 @@ NextCipherSuite:
helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
var secondHelloBytes []byte
if haveHelloRetryRequest {
- if isDraft22(c.wireVersion) {
- // Explicitly read the ChangeCipherSpec now; it should
- // be attached to the first flight, not the second flight.
- if err := c.readTLS13ChangeCipherSpec(); err != nil {
- return err
- }
+ // Explicitly read the ChangeCipherSpec now; it should
+ // be attached to the first flight, not the second flight.
+ if err := c.readTLS13ChangeCipherSpec(); err != nil {
+ return err
}
c.out.resetCipher()
@@ -638,11 +626,9 @@ NextCipherSuite:
hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
if haveHelloRetryRequest {
- if isDraft22(c.wireVersion) {
- err = hs.finishedHash.UpdateForHelloRetryRequest()
- if err != nil {
- return err
- }
+ err = hs.finishedHash.UpdateForHelloRetryRequest()
+ if err != nil {
+ return err
}
hs.writeServerHash(helloRetryRequest.marshal())
hs.writeClientHash(secondHelloBytes)
@@ -739,12 +725,6 @@ NextCipherSuite:
func (hs *clientHandshakeState) doTLS13Handshake() error {
c := hs.c
- if !isDraft22(c.wireVersion) {
- // Early versions of the middlebox hacks inserted
- // ChangeCipherSpec differently on 0-RTT and 2-RTT handshakes.
- c.expectTLS13ChangeCipherSpec = true
- }
-
if !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
return errors.New("tls: session IDs did not match.")
}
@@ -801,17 +781,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
hs.finishedHash.addEntropy(zeroSecret)
}
- clientLabel := clientHandshakeTrafficLabel
- serverLabel := serverHandshakeTrafficLabel
- if isDraft22(c.wireVersion) {
- clientLabel = clientHandshakeTrafficLabelDraft22
- serverLabel = serverHandshakeTrafficLabelDraft22
- }
-
// Derive handshake traffic keys and switch read key to handshake
// traffic key.
- clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientLabel)
- serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel)
+ clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
+ serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret); err != nil {
return err
}
@@ -948,18 +921,9 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
hs.finishedHash.nextSecret()
hs.finishedHash.addEntropy(zeroSecret)
- clientLabel = clientApplicationTrafficLabel
- serverLabel = serverApplicationTrafficLabel
- exportLabel := exporterLabel
- if isDraft22(c.wireVersion) {
- clientLabel = clientApplicationTrafficLabelDraft22
- serverLabel = serverApplicationTrafficLabelDraft22
- exportLabel = exporterLabelDraft22
- }
-
- clientTrafficSecret := hs.finishedHash.deriveSecret(clientLabel)
- serverTrafficSecret := hs.finishedHash.deriveSecret(serverLabel)
- c.exporterSecret = hs.finishedHash.deriveSecret(exportLabel)
+ clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
+ serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
+ c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
// Switch to application data keys on read. In particular, any alerts
// from the client certificate are read over these keys.
@@ -1003,14 +967,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
helloRequest := new(helloRequestMsg)
c.writeRecord(recordTypeHandshake, helloRequest.marshal())
}
- if isDraft22(c.wireVersion) {
- endOfEarlyData := new(endOfEarlyDataMsg)
- endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData
- c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal())
- hs.writeClientHash(endOfEarlyData.marshal())
- } else {
- c.sendAlert(alertEndOfEarlyData)
- }
+ endOfEarlyData := new(endOfEarlyDataMsg)
+ endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData
+ c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal())
+ hs.writeClientHash(endOfEarlyData.marshal())
}
if !c.config.Bugs.SkipChangeCipherSpec && !hs.hello.hasEarlyData {
@@ -1108,13 +1068,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
// Switch to application data keys.
c.useOutTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret)
-
- resumeLabel := resumptionLabel
- if isDraft22(c.wireVersion) {
- resumeLabel = resumptionLabelDraft22
- }
-
- c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel)
+ c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
for _, ticket := range deferredTickets {
if err := c.processTLS13NewSessionTicket(ticket, hs.suite); err != nil {
return err
@@ -1531,6 +1485,13 @@ func (hs *clientHandshakeState) processServerExtensions(serverExtensions *server
}
}
+ if len(serverExtensions.quicTransportParams) > 0 {
+ if c.vers < VersionTLS13 {
+ c.sendAlert(alertHandshakeFailure)
+ return errors.New("tls: server sent QUIC transport params for TLS version less than 1.3")
+ }
+ c.quicTransportParams = serverExtensions.quicTransportParams
+ }
return nil
}
@@ -1879,11 +1840,7 @@ func generatePSKBinders(version uint16, hello *clientHelloMsg, pskCipherSuite *c
helloBytes := hello.marshal()
binderSize := len(hello.pskBinders)*(binderLen+1) + 2
truncatedHello := helloBytes[:len(helloBytes)-binderSize]
- binderLabel := resumptionPSKBinderLabel
- if isDraft22(version) {
- binderLabel = resumptionPSKBinderLabelDraft22
- }
- binder := computePSKBinder(psk, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
+ binder := computePSKBinder(psk, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
if config.Bugs.SendShortPSKBinder {
binder = binder[:binderLen]
}
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index c80b1cfc..b19506d3 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -265,7 +265,6 @@ type clientHelloMsg struct {
supportedCurves []CurveID
supportedPoints []uint8
hasKeyShares bool
- keyShareExtension uint16
keyShares []keyShareEntry
trailingKeyShareData bool
pskIdentities []pskIdentity
@@ -279,6 +278,7 @@ type clientHelloMsg struct {
supportedVersions []uint16
secureRenegotiation []byte
alpnProtocols []string
+ quicTransportParams []byte
duplicateExtension bool
channelIDSupported bool
tokenBindingParams []byte
@@ -331,6 +331,7 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
(m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
+ bytes.Equal(m.quicTransportParams, m1.quicTransportParams) &&
m.duplicateExtension == m1.duplicateExtension &&
m.channelIDSupported == m1.channelIDSupported &&
bytes.Equal(m.tokenBindingParams, m1.tokenBindingParams) &&
@@ -451,7 +452,7 @@ func (m *clientHelloMsg) marshal() []byte {
supportedPoints.addBytes(m.supportedPoints)
}
if m.hasKeyShares {
- extensions.addU16(m.keyShareExtension)
+ extensions.addU16(extensionKeyShare)
keyShareList := extensions.addU16LengthPrefixed()
keyShares := keyShareList.addU16LengthPrefixed()
@@ -519,6 +520,11 @@ func (m *clientHelloMsg) marshal() []byte {
protocolName.addBytes([]byte(s))
}
}
+ if len(m.quicTransportParams) > 0 {
+ extensions.addU16(extensionQUICTransportParams)
+ params := extensions.addU16LengthPrefixed()
+ params.addBytes(m.quicTransportParams)
+ }
if m.channelIDSupported {
extensions.addU16(extensionChannelID)
extensions.addU16(0) // Length is always 0
@@ -733,12 +739,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
// http://tools.ietf.org/html/rfc5077#section-3.2
m.ticketSupported = true
m.sessionTicket = []byte(body)
- case extensionOldKeyShare, extensionNewKeyShare:
- // We assume the client only supports one of draft-22 or draft-23.
- if m.keyShareExtension != 0 {
- return false
- }
- m.keyShareExtension = extension
+ case extensionKeyShare:
// draft-ietf-tls-tls13 section 6.3.2.3
var keyShares byteReader
if !body.readU16LengthPrefixed(&keyShares) || len(body) != 0 {
@@ -832,6 +833,8 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
}
m.alpnProtocols = append(m.alpnProtocols, string(protocol))
}
+ case extensionQUICTransportParams:
+ m.quicTransportParams = body
case extensionChannelID:
if len(body) != 0 {
return false
@@ -942,11 +945,7 @@ func (m *serverHelloMsg) marshal() []byte {
if vers >= VersionTLS13 {
if m.hasKeyShare {
- if isDraft23(m.vers) {
- extensions.addU16(extensionNewKeyShare)
- } else {
- extensions.addU16(extensionOldKeyShare)
- }
+ extensions.addU16(extensionKeyShare)
keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed()
@@ -1049,10 +1048,6 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
if vers >= VersionTLS13 {
- extensionKeyShare := extensionOldKeyShare
- if isDraft23(m.vers) {
- extensionKeyShare = extensionNewKeyShare
- }
for len(extensions) > 0 {
var extension uint16
var body byteReader
@@ -1147,6 +1142,7 @@ type serverExtensions struct {
supportedVersion uint16
supportedPoints []uint8
supportedCurves []CurveID
+ quicTransportParams []byte
serverNameAck bool
}
@@ -1242,7 +1238,7 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) {
}
}
if m.hasKeyShare {
- extensions.addU16(extensionOldKeyShare)
+ extensions.addU16(extensionKeyShare)
keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed()
@@ -1269,6 +1265,11 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) {
supportedCurves.addU16(uint16(curve))
}
}
+ if len(m.quicTransportParams) > 0 {
+ extensions.addU16(extensionQUICTransportParams)
+ params := extensions.addU16LengthPrefixed()
+ params.addBytes(m.quicTransportParams)
+ }
if m.hasEarlyData {
extensions.addU16(extensionEarlyData)
extensions.addBytes([]byte{0, 0})
@@ -1374,6 +1375,8 @@ func (m *serverExtensions) unmarshal(data byteReader, version uint16) bool {
if version < VersionTLS13 {
return false
}
+ case extensionQUICTransportParams:
+ m.quicTransportParams = body
case extensionEarlyData:
if version < VersionTLS13 || len(body) != 0 {
return false
@@ -1408,26 +1411,15 @@ func (m *helloRetryRequestMsg) marshal() []byte {
}
retryRequestMsg := newByteBuilder()
- if isDraft22(m.vers) {
- retryRequestMsg.addU8(typeServerHello)
- } else {
- retryRequestMsg.addU8(typeHelloRetryRequest)
- }
+ retryRequestMsg.addU8(typeServerHello)
retryRequest := retryRequestMsg.addU24LengthPrefixed()
+ retryRequest.addU16(VersionTLS12)
+ retryRequest.addBytes(tls13HelloRetryRequest)
+ sessionId := retryRequest.addU8LengthPrefixed()
+ sessionId.addBytes(m.sessionId)
+ retryRequest.addU16(m.cipherSuite)
+ retryRequest.addU8(m.compressionMethod)
- if isDraft22(m.vers) {
- retryRequest.addU16(VersionTLS12)
- retryRequest.addBytes(tls13HelloRetryRequest)
- sessionId := retryRequest.addU8LengthPrefixed()
- sessionId.addBytes(m.sessionId)
- retryRequest.addU16(m.cipherSuite)
- retryRequest.addU8(m.compressionMethod)
- } else {
- retryRequest.addU16(m.vers)
- if isDraft22(m.vers) {
- retryRequest.addU16(m.cipherSuite)
- }
- }
extensions := retryRequest.addU16LengthPrefixed()
count := 1
@@ -1436,17 +1428,11 @@ func (m *helloRetryRequestMsg) marshal() []byte {
}
for i := 0; i < count; i++ {
- if isDraft22(m.vers) {
- extensions.addU16(extensionSupportedVersions)
- extensions.addU16(2) // Length
- extensions.addU16(m.vers)
- }
+ extensions.addU16(extensionSupportedVersions)
+ extensions.addU16(2) // Length
+ extensions.addU16(m.vers)
if m.hasSelectedGroup {
- if isDraft23(m.vers) {
- extensions.addU16(extensionNewKeyShare)
- } else {
- extensions.addU16(extensionOldKeyShare)
- }
+ extensions.addU16(extensionKeyShare)
extensions.addU16(2) // length
extensions.addU16(uint16(m.selectedGroup))
}
@@ -1482,7 +1468,7 @@ func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
compressionMethod != 0 {
return false
}
- } else if isDraft22(m.vers) && !reader.readU16(&m.cipherSuite) {
+ } else if !reader.readU16(&m.cipherSuite) {
return false
}
var extensions byteReader
@@ -1507,10 +1493,6 @@ func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
default:
}
}
- extensionKeyShare := extensionOldKeyShare
- if isDraft23(m.vers) {
- extensionKeyShare = extensionNewKeyShare
- }
for len(extensions) > 0 {
var extension uint16
var body byteReader
@@ -1866,37 +1848,21 @@ func (m *certificateRequestMsg) marshal() []byte {
requestContext := body.addU8LengthPrefixed()
requestContext.addBytes(m.requestContext)
extensions := newByteBuilder()
- if isDraft22(m.vers) {
- extensions = body.addU16LengthPrefixed()
- if m.hasSignatureAlgorithm {
- extensions.addU16(extensionSignatureAlgorithms)
- signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
- for _, sigAlg := range m.signatureAlgorithms {
- signatureAlgorithms.addU16(uint16(sigAlg))
- }
- }
- if len(m.certificateAuthorities) > 0 {
- extensions.addU16(extensionCertificateAuthorities)
- certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
- for _, ca := range m.certificateAuthorities {
- caEntry := certificateAuthorities.addU16LengthPrefixed()
- caEntry.addBytes(ca)
- }
- }
- } else {
- if m.hasSignatureAlgorithm {
- signatureAlgorithms := body.addU16LengthPrefixed()
- for _, sigAlg := range m.signatureAlgorithms {
- signatureAlgorithms.addU16(uint16(sigAlg))
- }
+ extensions = body.addU16LengthPrefixed()
+ if m.hasSignatureAlgorithm {
+ extensions.addU16(extensionSignatureAlgorithms)
+ signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
+ for _, sigAlg := range m.signatureAlgorithms {
+ signatureAlgorithms.addU16(uint16(sigAlg))
}
-
- certificateAuthorities := body.addU16LengthPrefixed()
+ }
+ if len(m.certificateAuthorities) > 0 {
+ extensions.addU16(extensionCertificateAuthorities)
+ certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
for _, ca := range m.certificateAuthorities {
caEntry := certificateAuthorities.addU16LengthPrefixed()
caEntry.addBytes(ca)
}
- extensions = body.addU16LengthPrefixed()
}
if m.customExtension > 0 {
@@ -1944,7 +1910,7 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
- if isDraft22(m.vers) {
+ if m.hasRequestContext {
var extensions byteReader
if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
!reader.readU16LengthPrefixed(&extensions) ||
@@ -1970,16 +1936,6 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
m.hasCAExtension = true
}
}
- } else if m.hasRequestContext {
- var extensions byteReader
- if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
- !parseSignatureAlgorithms(&reader, &m.signatureAlgorithms) ||
- !parseCAs(&reader, &m.certificateAuthorities) ||
- !reader.readU16LengthPrefixed(&extensions) ||
- len(reader) != 0 {
- return false
- }
- // Ignore certificate extensions.
} else {
if !reader.readU8LengthPrefixedBytes(&m.certificateTypes) {
return false
@@ -2097,9 +2053,7 @@ func (m *newSessionTicketMsg) marshal() []byte {
body.addU32(m.ticketLifetime)
if version >= VersionTLS13 {
body.addU32(m.ticketAgeAdd)
- if isDraft22(m.vers) {
- body.addU8LengthPrefixed().addBytes(m.ticketNonce)
- }
+ body.addU8LengthPrefixed().addBytes(m.ticketNonce)
}
ticket := body.addU16LengthPrefixed()
@@ -2108,14 +2062,10 @@ func (m *newSessionTicketMsg) marshal() []byte {
if version >= VersionTLS13 {
extensions := body.addU16LengthPrefixed()
if m.maxEarlyDataSize > 0 {
- extID := extensionTicketEarlyDataInfo
- if isDraft22(m.vers) {
- extID = extensionEarlyData
- }
- extensions.addU16(extID)
+ extensions.addU16(extensionEarlyData)
extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
if m.duplicateEarlyDataExtension {
- extensions.addU16(extID)
+ extensions.addU16(extensionEarlyData)
extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
}
}
@@ -2149,15 +2099,13 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
}
m.ticketAgeAdd = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
data = data[4:]
- if isDraft22(m.vers) {
- nonceLen := int(data[0])
- data = data[1:]
- if len(data) < nonceLen {
- return false
- }
- m.ticketNonce = data[:nonceLen]
- data = data[nonceLen:]
+ nonceLen := int(data[0])
+ data = data[1:]
+ if len(data) < nonceLen {
+ return false
}
+ m.ticketNonce = data[:nonceLen]
+ data = data[nonceLen:]
}
if len(data) < 2 {
@@ -2187,11 +2135,6 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
return false
}
- extID := extensionTicketEarlyDataInfo
- if isDraft22(m.vers) {
- extID = extensionEarlyData
- }
-
for len(data) != 0 {
if len(data) < 4 {
return false
@@ -2204,7 +2147,7 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
}
switch extension {
- case extID:
+ case extensionEarlyData:
if length != 4 {
return false
}
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 123ab163..caa66eda 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -280,14 +280,6 @@ func (hs *serverHandshakeState) readClientHello() error {
}
}
- // Check that we received the expected version of the key_share extension.
- if c.vers >= VersionTLS13 {
- if (isDraft23(c.wireVersion) && hs.clientHello.keyShareExtension != extensionNewKeyShare) ||
- (!isDraft23(c.wireVersion) && hs.clientHello.keyShareExtension != extensionOldKeyShare) {
- return fmt.Errorf("tls: client offered wrong key_share extension")
- }
- }
-
if config.Bugs.ExpectNoTLS12Session {
if len(hs.clientHello.sessionId) > 0 && c.vers >= VersionTLS13 {
return fmt.Errorf("tls: client offered an unexpected session ID")
@@ -370,11 +362,8 @@ func (hs *serverHandshakeState) doTLS13Handshake() error {
c := hs.c
config := c.config
- // We've read the ClientHello, so the next record in draft 22 must be
- // preceded with ChangeCipherSpec.
- if isDraft22(c.wireVersion) {
- c.expectTLS13ChangeCipherSpec = true
- }
+ // We've read the ClientHello, so the next record must be preceded with ChangeCipherSpec.
+ c.expectTLS13ChangeCipherSpec = true
hs.hello = &serverHelloMsg{
isDTLS: c.isDTLS,
@@ -597,10 +586,8 @@ ResendHelloRetryRequest:
}
if sendHelloRetryRequest {
- if isDraft22(c.wireVersion) {
- if err := hs.finishedHash.UpdateForHelloRetryRequest(); err != nil {
- return err
- }
+ if err := hs.finishedHash.UpdateForHelloRetryRequest(); err != nil {
+ return err
}
oldClientHelloBytes := hs.clientHello.marshal()
@@ -608,7 +595,7 @@ ResendHelloRetryRequest:
c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
c.flushHandshake()
- if !c.config.Bugs.SkipChangeCipherSpec && isDraft22(c.wireVersion) {
+ if !c.config.Bugs.SkipChangeCipherSpec {
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
}
@@ -666,7 +653,7 @@ ResendHelloRetryRequest:
// PSK binders and obfuscated ticket age are both updated in the
// second ClientHello.
- if isDraft22(c.wireVersion) && len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
+ if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
newClientHelloCopy.pskIdentities = oldClientHelloCopy.pskIdentities
} else {
if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
@@ -706,14 +693,8 @@ ResendHelloRetryRequest:
}
}
if encryptedExtensions.extensions.hasEarlyData {
- var earlyTrafficSecret []byte
- if isDraft22(c.wireVersion) {
- earlyTrafficSecret = hs.finishedHash.deriveSecret(earlyTrafficLabelDraft22)
- c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabelDraft22)
- } else {
- earlyTrafficSecret = hs.finishedHash.deriveSecret(earlyTrafficLabel)
- c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel)
- }
+ earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel)
+ c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel)
if err := c.useInTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret); err != nil {
return err
@@ -829,18 +810,11 @@ ResendHelloRetryRequest:
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
}
- clientLabel := clientHandshakeTrafficLabel
- serverLabel := serverHandshakeTrafficLabel
- if isDraft22(c.wireVersion) {
- clientLabel = clientHandshakeTrafficLabelDraft22
- serverLabel = serverHandshakeTrafficLabelDraft22
- }
-
// Switch to handshake traffic keys.
- serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel)
+ serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
c.useOutTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret)
// Derive handshake traffic read key, but don't switch yet.
- clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientLabel)
+ clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
// Send EncryptedExtensions.
hs.writeServerHash(encryptedExtensions.marshal())
@@ -977,18 +951,9 @@ ResendHelloRetryRequest:
hs.finishedHash.nextSecret()
hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
- clientLabel = clientApplicationTrafficLabel
- serverLabel = serverApplicationTrafficLabel
- exportLabel := exporterLabel
- if isDraft22(c.wireVersion) {
- clientLabel = clientApplicationTrafficLabelDraft22
- serverLabel = serverApplicationTrafficLabelDraft22
- exportLabel = exporterLabelDraft22
- }
-
- clientTrafficSecret := hs.finishedHash.deriveSecret(clientLabel)
- serverTrafficSecret := hs.finishedHash.deriveSecret(serverLabel)
- c.exporterSecret = hs.finishedHash.deriveSecret(exportLabel)
+ clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
+ serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
+ c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
// Switch to application data keys on write. In particular, any alerts
// from the client certificate are sent over these keys.
@@ -1003,31 +968,17 @@ ResendHelloRetryRequest:
// Read end_of_early_data.
if encryptedExtensions.extensions.hasEarlyData {
- if isDraft22(c.wireVersion) {
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
- endOfEarlyData, ok := msg.(*endOfEarlyDataMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(endOfEarlyData, msg)
- }
- hs.writeClientHash(endOfEarlyData.marshal())
- } else {
- if err := c.readRecord(recordTypeAlert); err != errEndOfEarlyDataAlert {
- if err == nil {
- panic("readRecord(recordTypeAlert) returned nil")
- }
- return err
- }
+ endOfEarlyData, ok := msg.(*endOfEarlyDataMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(endOfEarlyData, msg)
}
- }
- if !isDraft22(c.wireVersion) && !hs.clientHello.hasEarlyData {
- // Early versions of the middlebox hacks inserted
- // ChangeCipherSpec differently on 0-RTT and 2-RTT handshakes.
- c.expectTLS13ChangeCipherSpec = true
+ hs.writeClientHash(endOfEarlyData.marshal())
}
// Switch input stream to handshake traffic keys.
@@ -1142,13 +1093,7 @@ ResendHelloRetryRequest:
}
c.cipherSuite = hs.suite
-
- resumeLabel := resumptionLabel
- if isDraft22(c.wireVersion) {
- resumeLabel = resumptionLabelDraft22
- }
-
- c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel)
+ c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
// TODO(davidben): Allow configuring the number of tickets sent for
// testing.
@@ -1369,6 +1314,11 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
}
}
+ if len(hs.clientHello.quicTransportParams) > 0 {
+ c.quicTransportParams = hs.clientHello.quicTransportParams
+ serverExtensions.quicTransportParams = c.config.QUICTransportParams
+ }
+
if c.vers < VersionTLS13 || config.Bugs.NegotiateEMSAtAllVersions {
disableEMS := config.Bugs.NoExtendedMasterSecret
if c.cipherSuite != nil {
@@ -2167,11 +2117,7 @@ func verifyPSKBinder(version uint16, clientHello *clientHelloMsg, sessionState *
return errors.New("tls: Unknown cipher suite for PSK in session")
}
- binderLabel := resumptionPSKBinderLabel
- if isDraft22(version) {
- binderLabel = resumptionPSKBinderLabelDraft22
- }
- binder := computePSKBinder(sessionState.masterSecret, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
+ binder := computePSKBinder(sessionState.masterSecret, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
if !bytes.Equal(binder, binderToVerify) {
return errors.New("tls: PSK binder does not verify")
}
diff --git a/src/ssl/test/runner/prf.go b/src/ssl/test/runner/prf.go
index 62c98b73..8c2da0dd 100644
--- a/src/ssl/test/runner/prf.go
+++ b/src/ssl/test/runner/prf.go
@@ -328,7 +328,7 @@ func (h finishedHash) clientSum(baseKey []byte) []byte {
return out
}
- clientFinishedKey := hkdfExpandLabel(h.hash, h.wireVersion, baseKey, finishedLabel, nil, h.hash.Size())
+ clientFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
finishedHMAC := hmac.New(h.hash.New, clientFinishedKey)
finishedHMAC.Write(h.appendContextHashes(nil))
return finishedHMAC.Sum(nil)
@@ -347,7 +347,7 @@ func (h finishedHash) serverSum(baseKey []byte) []byte {
return out
}
- serverFinishedKey := hkdfExpandLabel(h.hash, h.wireVersion, baseKey, finishedLabel, nil, h.hash.Size())
+ serverFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
finishedHMAC := hmac.New(h.hash.New, serverFinishedKey)
finishedHMAC.Write(h.appendContextHashes(nil))
return finishedHMAC.Sum(nil)
@@ -396,24 +396,17 @@ func (h *finishedHash) addEntropy(ikm []byte) {
}
func (h *finishedHash) nextSecret() {
- if isDraft22(h.wireVersion) {
- derivedLabel := []byte("derived")
- h.secret = hkdfExpandLabel(h.hash, h.wireVersion, h.secret, derivedLabel, h.hash.New().Sum(nil), h.hash.Size())
- }
+ h.secret = hkdfExpandLabel(h.hash, h.secret, []byte("derived"), h.hash.New().Sum(nil), h.hash.Size())
}
// hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined
// in section 7.1 of draft-ietf-tls-tls13-16.
-func hkdfExpandLabel(hash crypto.Hash, version uint16, secret, label, hashValue []byte, length int) []byte {
+func hkdfExpandLabel(hash crypto.Hash, secret, label, hashValue []byte, length int) []byte {
if len(label) > 255 || len(hashValue) > 255 {
panic("hkdfExpandLabel: label or hashValue too long")
}
- versionLabel := []byte("TLS 1.3, ")
- if isDraft22(version) {
- versionLabel = []byte("tls13 ")
- }
-
+ versionLabel := []byte("tls13 ")
hkdfLabel := make([]byte, 3+len(versionLabel)+len(label)+1+len(hashValue))
x := hkdfLabel
x[0] = byte(length >> 8)
@@ -438,29 +431,17 @@ func (h *finishedHash) appendContextHashes(b []byte) []byte {
// The following are labels for traffic secret derivation in TLS 1.3.
var (
- externalPSKBinderLabel = []byte("external psk binder key")
- resumptionPSKBinderLabel = []byte("resumption psk binder key")
- earlyTrafficLabel = []byte("client early traffic secret")
- clientHandshakeTrafficLabel = []byte("client handshake traffic secret")
- serverHandshakeTrafficLabel = []byte("server handshake traffic secret")
- clientApplicationTrafficLabel = []byte("client application traffic secret")
- serverApplicationTrafficLabel = []byte("server application traffic secret")
- applicationTrafficLabel = []byte("application traffic secret")
- earlyExporterLabel = []byte("early exporter master secret")
- exporterLabel = []byte("exporter master secret")
- resumptionLabel = []byte("resumption master secret")
-
- externalPSKBinderLabelDraft22 = []byte("ext binder")
- resumptionPSKBinderLabelDraft22 = []byte("res binder")
- earlyTrafficLabelDraft22 = []byte("c e traffic")
- clientHandshakeTrafficLabelDraft22 = []byte("c hs traffic")
- serverHandshakeTrafficLabelDraft22 = []byte("s hs traffic")
- clientApplicationTrafficLabelDraft22 = []byte("c ap traffic")
- serverApplicationTrafficLabelDraft22 = []byte("s ap traffic")
- applicationTrafficLabelDraft22 = []byte("traffic upd")
- earlyExporterLabelDraft22 = []byte("e exp master")
- exporterLabelDraft22 = []byte("exp master")
- resumptionLabelDraft22 = []byte("res master")
+ externalPSKBinderLabel = []byte("ext binder")
+ resumptionPSKBinderLabel = []byte("res binder")
+ earlyTrafficLabel = []byte("c e traffic")
+ clientHandshakeTrafficLabel = []byte("c hs traffic")
+ serverHandshakeTrafficLabel = []byte("s hs traffic")
+ clientApplicationTrafficLabel = []byte("c ap traffic")
+ serverApplicationTrafficLabel = []byte("s ap traffic")
+ applicationTrafficLabel = []byte("traffic upd")
+ earlyExporterLabel = []byte("e exp master")
+ exporterLabel = []byte("exp master")
+ resumptionLabel = []byte("res master")
resumptionPSKLabel = []byte("resumption")
)
@@ -468,7 +449,7 @@ var (
// deriveSecret implements TLS 1.3's Derive-Secret function, as defined in
// section 7.1 of draft ietf-tls-tls13-16.
func (h *finishedHash) deriveSecret(label []byte) []byte {
- return hkdfExpandLabel(h.hash, h.wireVersion, h.secret, label, h.appendContextHashes(nil), h.hash.Size())
+ return hkdfExpandLabel(h.hash, h.secret, label, h.appendContextHashes(nil), h.hash.Size())
}
// The following are context strings for CertificateVerify in TLS 1.3.
@@ -507,18 +488,14 @@ var (
// deriveTrafficAEAD derives traffic keys and constructs an AEAD given a traffic
// secret.
func deriveTrafficAEAD(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) interface{} {
- key := hkdfExpandLabel(suite.hash(), version, secret, keyTLS13, nil, suite.keyLen)
- iv := hkdfExpandLabel(suite.hash(), version, secret, ivTLS13, nil, suite.ivLen(version))
+ key := hkdfExpandLabel(suite.hash(), secret, keyTLS13, nil, suite.keyLen)
+ iv := hkdfExpandLabel(suite.hash(), secret, ivTLS13, nil, suite.ivLen(version))
return suite.aead(version, key, iv)
}
func updateTrafficSecret(hash crypto.Hash, version uint16, secret []byte) []byte {
- trafficLabel := applicationTrafficLabel
- if isDraft22(version) {
- trafficLabel = applicationTrafficLabelDraft22
- }
- return hkdfExpandLabel(hash, version, secret, trafficLabel, nil, hash.Size())
+ return hkdfExpandLabel(hash, secret, applicationTrafficLabel, nil, hash.Size())
}
func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cipherSuite, clientHello, helloRetryRequest, truncatedHello []byte) []byte {
@@ -526,7 +503,7 @@ func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cip
finishedHash.addEntropy(psk)
binderKey := finishedHash.deriveSecret(label)
finishedHash.Write(clientHello)
- if isDraft22(version) && len(helloRetryRequest) != 0 {
+ if len(helloRetryRequest) != 0 {
finishedHash.UpdateForHelloRetryRequest()
}
finishedHash.Write(helloRetryRequest)
@@ -536,5 +513,5 @@ func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cip
func deriveSessionPSK(suite *cipherSuite, version uint16, masterSecret []byte, nonce []byte) []byte {
hash := suite.hash()
- return hkdfExpandLabel(hash, version, masterSecret, resumptionPSKLabel, nonce, hash.Size())
+ return hkdfExpandLabel(hash, masterSecret, resumptionPSKLabel, nonce, hash.Size())
}
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 02ea5398..430e3d92 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -475,6 +475,9 @@ type testCase struct {
// configured with the specified TLS 1.3 variant. This is a convenience
// option for configuring both concurrently.
tls13Variant int
+ // expectedQUICTransportParams contains the QUIC transport
+ // parameters that are expected to be sent by the peer.
+ expectedQUICTransportParams []byte
}
var testCases []testCase
@@ -714,6 +717,12 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, tr
}
}
+ if len(test.expectedQUICTransportParams) > 0 {
+ if !bytes.Equal(test.expectedQUICTransportParams, connState.QUICTransportParams) {
+ return errors.New("Peer did not send expected QUIC transport params")
+ }
+ }
+
if isResume && test.exportEarlyKeyingMaterial > 0 {
actual := make([]byte, test.exportEarlyKeyingMaterial)
if _, err := io.ReadFull(tlsConn, actual); err != nil {
@@ -1363,26 +1372,12 @@ var tlsVersions = []tlsVersion{
versionDTLS: VersionDTLS12,
},
{
- name: "TLS13Draft22",
- version: VersionTLS13,
- excludeFlag: "-no-tls13",
- versionWire: tls13Draft22Version,
- tls13Variant: TLS13Draft22,
- },
- {
name: "TLS13Draft23",
version: VersionTLS13,
excludeFlag: "-no-tls13",
versionWire: tls13Draft23Version,
tls13Variant: TLS13Draft23,
},
- {
- name: "TLS13Experiment2",
- version: VersionTLS13,
- excludeFlag: "-no-tls13",
- versionWire: tls13Experiment2Version,
- tls13Variant: TLS13Experiment2,
- },
}
func allVersions(protocol protocol) []tlsVersion {
@@ -1460,6 +1455,36 @@ func bigFromHex(hex string) *big.Int {
return ret
}
+func convertToSplitHandshakeTests(tests []testCase) (splitHandshakeTests []testCase) {
+NextTest:
+ for _, test := range tests {
+ if test.protocol != tls ||
+ test.testType != serverTest ||
+ test.config.MaxVersion >= VersionTLS13 ||
+ test.config.MaxVersion < VersionTLS10 ||
+ (test.resumeConfig != nil && (test.resumeConfig.MaxVersion < VersionTLS10 || test.resumeConfig.MaxVersion >= VersionTLS13)) ||
+ strings.HasPrefix(test.name, "VersionNegotiation-") {
+ continue
+ }
+
+ for _, flag := range test.flags {
+ if flag == "-implicit-handshake" {
+ continue NextTest
+ }
+ }
+
+ shTest := test
+ shTest.name += "-Split"
+ shTest.flags = make([]string, len(test.flags), len(test.flags)+1)
+ copy(shTest.flags, test.flags)
+ shTest.flags = append(shTest.flags, "-handoff")
+
+ splitHandshakeTests = append(splitHandshakeTests, shTest)
+ }
+
+ return splitHandshakeTests
+}
+
func addBasicTests() {
basicTests := []testCase{
{
@@ -2845,20 +2870,20 @@ read alert 1 0
},
{
testType: clientTest,
- name: "TLS13Draft22-InvalidCompressionMethod",
+ name: "TLS13Draft23-InvalidCompressionMethod",
config: Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendCompressionMethod: 1,
},
},
- tls13Variant: TLS13Draft22,
+ tls13Variant: TLS13Draft23,
shouldFail: true,
expectedError: ":DECODE_ERROR:",
},
{
testType: clientTest,
- name: "TLS13Draft22-HRR-InvalidCompressionMethod",
+ name: "TLS13Draft23-HRR-InvalidCompressionMethod",
config: Config{
MaxVersion: VersionTLS13,
CurvePreferences: []CurveID{CurveP384},
@@ -2866,7 +2891,7 @@ read alert 1 0
SendCompressionMethod: 1,
},
},
- tls13Variant: TLS13Draft22,
+ tls13Variant: TLS13Draft23,
shouldFail: true,
expectedError: ":DECODE_ERROR:",
expectedLocalError: "remote error: error decoding message",
@@ -3959,7 +3984,7 @@ func addClientAuthTests() {
// Test that an empty client CA list doesn't send a CA extension.
testCases = append(testCases, testCase{
testType: serverTest,
- name: "TLS13Draft22-Empty-Client-CA-List",
+ name: "TLS13Draft23-Empty-Client-CA-List",
config: Config{
MaxVersion: VersionTLS13,
Certificates: []Certificate{rsaCertificate},
@@ -3967,7 +3992,7 @@ func addClientAuthTests() {
ExpectNoCertificateAuthoritiesExtension: true,
},
},
- tls13Variant: TLS13Draft22,
+ tls13Variant: TLS13Draft23,
flags: []string{
"-require-any-client-certificate",
"-use-client-ca-list", "<EMPTY>",
@@ -4325,7 +4350,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
})
tests = append(tests, testCase{
- name: "TLS13Draft22-HelloRetryRequest-Client",
+ name: "TLS13Draft23-HelloRetryRequest-Client",
config: Config{
MaxVersion: VersionTLS13,
MinVersion: VersionTLS13,
@@ -4336,21 +4361,21 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
ExpectMissingKeyShare: true,
},
},
- tls13Variant: TLS13Draft22,
+ tls13Variant: TLS13Draft23,
// Cover HelloRetryRequest during an ECDHE-PSK resumption.
resumeSession: true,
})
tests = append(tests, testCase{
testType: serverTest,
- name: "TLS13Draft22-HelloRetryRequest-Server",
+ name: "TLS13Draft23-HelloRetryRequest-Server",
config: Config{
MaxVersion: VersionTLS13,
MinVersion: VersionTLS13,
// Require a HelloRetryRequest for every curve.
DefaultCurves: []CurveID{},
},
- tls13Variant: TLS13Draft22,
+ tls13Variant: TLS13Draft23,
// Cover HelloRetryRequest during an ECDHE-PSK resumption.
resumeSession: true,
})
@@ -6588,6 +6613,106 @@ func addExtensionTests() {
})
}
+ // Test QUIC transport params
+ if ver.version >= VersionTLS13 {
+ // Client sends params
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "QUICTransportParams-Client-" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ QUICTransportParams: []byte{1, 2},
+ },
+ tls13Variant: ver.tls13Variant,
+ flags: []string{
+ "-quic-transport-params",
+ base64.StdEncoding.EncodeToString([]byte{3, 4}),
+ "-expected-quic-transport-params",
+ base64.StdEncoding.EncodeToString([]byte{1, 2}),
+ },
+ expectedQUICTransportParams: []byte{3, 4},
+ })
+ // Server sends params
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "QUICTransportParams-Server-" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ QUICTransportParams: []byte{1, 2},
+ },
+ tls13Variant: ver.tls13Variant,
+ flags: []string{
+ "-quic-transport-params",
+ base64.StdEncoding.EncodeToString([]byte{3, 4}),
+ "-expected-quic-transport-params",
+ base64.StdEncoding.EncodeToString([]byte{1, 2}),
+ },
+ expectedQUICTransportParams: []byte{3, 4},
+ })
+ } else {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "QUICTransportParams-Client-NotSent-" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ },
+ tls13Variant: ver.tls13Variant,
+ flags: []string{
+ "-max-version",
+ strconv.Itoa(int(ver.version)),
+ "-quic-transport-params",
+ base64.StdEncoding.EncodeToString([]byte{3, 4}),
+ },
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "QUICTransportParams-Client-Rejected-" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ QUICTransportParams: []byte{1, 2},
+ },
+ tls13Variant: ver.tls13Variant,
+ flags: []string{
+ "-quic-transport-params",
+ base64.StdEncoding.EncodeToString([]byte{3, 4}),
+ },
+ shouldFail: true,
+ expectedError: ":ERROR_PARSING_EXTENSION:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "QUICTransportParams-Server-Rejected-" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ QUICTransportParams: []byte{1, 2},
+ },
+ tls13Variant: ver.tls13Variant,
+ flags: []string{
+ "-expected-quic-transport-params",
+ base64.StdEncoding.EncodeToString([]byte{1, 2}),
+ },
+ shouldFail: true,
+ expectedError: "QUIC transport params mismatch",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "QUICTransportParams-OldServerIgnores-" + ver.name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ QUICTransportParams: []byte{1, 2},
+ },
+ flags: []string{
+ "-min-version", ver.shimFlag(tls),
+ "-max-version", ver.shimFlag(tls),
+ },
+ })
+ }
+
// Test ticket behavior.
// Resume with a corrupt ticket.
@@ -7794,14 +7919,14 @@ func addRenegotiationTests() {
},
})
testCases = append(testCases, testCase{
- name: "Renegotiate-Client-TLS13Draft22",
+ name: "Renegotiate-Client-TLS13Draft23",
config: Config{
MaxVersion: VersionTLS12,
Bugs: ProtocolBugs{
FailIfResumeOnRenego: true,
},
},
- tls13Variant: TLS13Draft22,
+ tls13Variant: TLS13Draft23,
renegotiate: 1,
// Test renegotiation after both an initial and resumption
// handshake.
@@ -11608,7 +11733,7 @@ func makePerMessageTests() []perMessageTest {
messageType: typeEndOfEarlyData,
test: testCase{
testType: serverTest,
- name: "TLS13Draft22-EndOfEarlyData",
+ name: "TLS13Draft23-EndOfEarlyData",
config: Config{
MaxVersion: VersionTLS13,
},
@@ -11619,7 +11744,7 @@ func makePerMessageTests() []perMessageTest {
ExpectEarlyDataAccepted: true,
},
},
- tls13Variant: TLS13Draft22,
+ tls13Variant: TLS13Draft23,
resumeSession: true,
flags: []string{"-enable-early-data"},
},
@@ -12166,50 +12291,48 @@ func addTLS13HandshakeTests() {
expectedError: ":WRONG_CURVE:",
})
- if isDraft22(version.versionWire) {
- testCases = append(testCases, testCase{
- name: "HelloRetryRequest-CipherChange-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- SendCipherSuite: TLS_AES_128_GCM_SHA256,
- SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-CipherChange-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ SendCipherSuite: TLS_AES_128_GCM_SHA256,
+ SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":WRONG_CIPHER_RETURNED:",
- })
+ },
+ tls13Variant: variant,
+ shouldFail: true,
+ expectedError: ":WRONG_CIPHER_RETURNED:",
+ })
- // Test that the client does not offer a PSK in the second ClientHello if the
- // HelloRetryRequest is incompatible with it.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "HelloRetryRequest-NonResumableCipher-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- CipherSuites: []uint16{
- TLS_AES_128_GCM_SHA256,
- },
+ // Test that the client does not offer a PSK in the second ClientHello if the
+ // HelloRetryRequest is incompatible with it.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "HelloRetryRequest-NonResumableCipher-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- ExpectNoTLS13PSKAfterHRR: true,
- },
- CipherSuites: []uint16{
- TLS_AES_256_GCM_SHA384,
- },
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ ExpectNoTLS13PSKAfterHRR: true,
},
- tls13Variant: variant,
- resumeSession: true,
- expectResumeRejected: true,
- })
- }
+ CipherSuites: []uint16{
+ TLS_AES_256_GCM_SHA384,
+ },
+ },
+ tls13Variant: variant,
+ resumeSession: true,
+ expectResumeRejected: true,
+ })
testCases = append(testCases, testCase{
name: "DisabledCurve-HelloRetryRequest-" + name,
@@ -12453,43 +12576,41 @@ func addTLS13HandshakeTests() {
expectedError: ":DECODE_ERROR:",
})
- if isDraft22(version.versionWire) {
- testCases = append(testCases, testCase{
- name: "UnknownExtensionInCertificateRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- ClientAuth: RequireAnyClientCert,
- Bugs: ProtocolBugs{
- SendCustomCertificateRequest: 0x1212,
- },
- },
- tls13Variant: variant,
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ testCases = append(testCases, testCase{
+ name: "UnknownExtensionInCertificateRequest-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ ClientAuth: RequireAnyClientCert,
+ Bugs: ProtocolBugs{
+ SendCustomCertificateRequest: 0x1212,
},
- })
+ },
+ tls13Variant: variant,
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ },
+ })
- testCases = append(testCases, testCase{
- name: "MissingSignatureAlgorithmsInCertificateRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- ClientAuth: RequireAnyClientCert,
- Bugs: ProtocolBugs{
- OmitCertificateRequestAlgorithms: true,
- },
- },
- tls13Variant: variant,
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ testCases = append(testCases, testCase{
+ name: "MissingSignatureAlgorithmsInCertificateRequest-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ ClientAuth: RequireAnyClientCert,
+ Bugs: ProtocolBugs{
+ OmitCertificateRequestAlgorithms: true,
},
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- })
- }
+ },
+ tls13Variant: variant,
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ },
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ })
testCases = append(testCases, testCase{
testType: serverTest,
@@ -12686,73 +12807,71 @@ func addTLS13HandshakeTests() {
expectedError: ":UNEXPECTED_EXTENSION:",
})
- if isDraft22(version.versionWire) {
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "SkipChangeCipherSpec-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SkipChangeCipherSpec: true,
- },
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "SkipChangeCipherSpec-Client-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
},
- tls13Variant: variant,
- })
+ },
+ tls13Variant: variant,
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipChangeCipherSpec-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SkipChangeCipherSpec: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipChangeCipherSpec-Server-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
},
- tls13Variant: variant,
- })
+ },
+ tls13Variant: variant,
+ })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TooManyChangeCipherSpec-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendExtraChangeCipherSpec: 33,
- },
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TooManyChangeCipherSpec-Client-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendExtraChangeCipherSpec: 33,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
- })
+ },
+ tls13Variant: variant,
+ shouldFail: true,
+ expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TooManyChangeCipherSpec-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendExtraChangeCipherSpec: 33,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TooManyChangeCipherSpec-Server-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendExtraChangeCipherSpec: 33,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
- })
+ },
+ tls13Variant: variant,
+ shouldFail: true,
+ expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
+ })
- testCases = append(testCases, testCase{
- name: "SendPostHandshakeChangeCipherSpec-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendPostHandshakeChangeCipherSpec: true,
- },
+ testCases = append(testCases, testCase{
+ name: "SendPostHandshakeChangeCipherSpec-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendPostHandshakeChangeCipherSpec: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- expectedLocalError: "remote error: unexpected message",
- })
- }
+ },
+ tls13Variant: variant,
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ expectedLocalError: "remote error: unexpected message",
+ })
fooString := "foo"
barString := "bar"
@@ -13134,13 +13253,6 @@ func addTLS13HandshakeTests() {
expectedError: ":BAD_DECRYPT:",
})
- expectedError := ":UNEXPECTED_RECORD:"
- if isDraft22(version.versionWire) {
- // In draft-21 and up, early data is expected to be
- // terminated by a handshake message, though we test
- // with the wrong one.
- expectedError = ":UNEXPECTED_MESSAGE:"
- }
testCases = append(testCases, testCase{
testType: serverTest,
name: "EarlyData-UnexpectedHandshake-Server-" + name,
@@ -13158,7 +13270,7 @@ func addTLS13HandshakeTests() {
tls13Variant: variant,
resumeSession: true,
shouldFail: true,
- expectedError: expectedError,
+ expectedError: ":UNEXPECTED_MESSAGE:",
expectedLocalError: "remote error: unexpected message",
flags: []string{
"-enable-early-data",
@@ -13237,32 +13349,30 @@ func addTLS13HandshakeTests() {
expectedLocalError: "remote error: error decrypting message",
})
- if isDraft22(version.versionWire) {
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Server-NonEmptyEndOfEarlyData-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- NonEmptyEndOfEarlyData: true,
- },
- },
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-accept-early-data",
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Server-NonEmptyEndOfEarlyData-" + name,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ NonEmptyEndOfEarlyData: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- })
- }
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-accept-early-data",
+ },
+ tls13Variant: variant,
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ })
testCases = append(testCases, testCase{
testType: serverTest,
@@ -14020,6 +14130,8 @@ func main() {
addExtraHandshakeTests()
addOmitExtensionsTests()
+ testCases = append(testCases, convertToSplitHandshakeTests(testCases)...)
+
var wg sync.WaitGroup
statusChan := make(chan statusMsg, *numWorkers)
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 7c660c8a..1125aefd 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -131,6 +131,7 @@ const Flag<bool> kBoolFlags[] = {
{ "-allow-false-start-without-alpn",
&TestConfig::allow_false_start_without_alpn },
{ "-expect-draft-downgrade", &TestConfig::expect_draft_downgrade },
+ { "-handoff", &TestConfig::handoff },
};
const Flag<std::string> kStringFlags[] = {
@@ -170,6 +171,9 @@ const Flag<std::string> kBase64Flags[] = {
{ "-ocsp-response", &TestConfig::ocsp_response },
{ "-signed-cert-timestamps", &TestConfig::signed_cert_timestamps },
{ "-ticket-key", &TestConfig::ticket_key },
+ { "-quic-transport-params", &TestConfig::quic_transport_params },
+ { "-expected-quic-transport-params",
+ &TestConfig::expected_quic_transport_params },
};
const Flag<int> kIntFlags[] = {
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 75743378..8768654d 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -59,6 +59,8 @@ struct TestConfig {
std::string expected_advertised_alpn;
std::string select_alpn;
bool decline_alpn = false;
+ std::string quic_transport_params;
+ std::string expected_quic_transport_params;
bool expect_session_miss = false;
bool expect_extended_master_secret = false;
std::string psk;
@@ -150,6 +152,7 @@ struct TestConfig {
bool allow_false_start_without_alpn = false;
bool expect_draft_downgrade = false;
int dummy_pq_padding_len = 0;
+ bool handoff = false;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_initial,
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index f013afda..aa054563 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -58,88 +58,63 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
return ssl_hs_read_message;
}
- CBS extensions;
- uint16_t cipher_suite = 0;
- if (ssl_is_draft22(ssl->version)) {
- // Queue up a ChangeCipherSpec for whenever we next send something. This
- // will be before the second ClientHello. If we offered early data, this was
- // already done.
- if (!hs->early_data_offered &&
- !ssl->method->add_change_cipher_spec(ssl)) {
- return ssl_hs_error;
- }
-
- if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
- return ssl_hs_error;
- }
+ // Queue up a ChangeCipherSpec for whenever we next send something. This
+ // will be before the second ClientHello. If we offered early data, this was
+ // already done.
+ if (!hs->early_data_offered &&
+ !ssl->method->add_change_cipher_spec(ssl)) {
+ return ssl_hs_error;
+ }
- CBS body = msg.body, server_random, session_id;
- uint16_t server_version;
- uint8_t compression_method;
- if (!CBS_get_u16(&body, &server_version) ||
- !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) ||
- !CBS_get_u8_length_prefixed(&body, &session_id) ||
- !CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len) ||
- !CBS_get_u16(&body, &cipher_suite) ||
- !CBS_get_u8(&body, &compression_method) ||
- compression_method != 0 ||
- !CBS_get_u16_length_prefixed(&body, &extensions) ||
- CBS_len(&extensions) == 0 ||
- CBS_len(&body) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- return ssl_hs_error;
- }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
+ return ssl_hs_error;
+ }
- if (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
- hs->tls13_state = state_read_server_hello;
- return ssl_hs_ok;
- }
- } else {
- if (msg.type != SSL3_MT_HELLO_RETRY_REQUEST) {
- hs->tls13_state = state_read_server_hello;
- return ssl_hs_ok;
- }
+ CBS body = msg.body, extensions, server_random, session_id;
+ uint16_t server_version, cipher_suite;
+ uint8_t compression_method;
+ if (!CBS_get_u16(&body, &server_version) ||
+ !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) ||
+ !CBS_get_u8_length_prefixed(&body, &session_id) ||
+ !CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len) ||
+ !CBS_get_u16(&body, &cipher_suite) ||
+ !CBS_get_u8(&body, &compression_method) ||
+ compression_method != 0 ||
+ !CBS_get_u16_length_prefixed(&body, &extensions) ||
+ CBS_len(&extensions) == 0 ||
+ CBS_len(&body) != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ return ssl_hs_error;
+ }
- CBS body = msg.body;
- uint16_t server_version;
- if (!CBS_get_u16(&body, &server_version) ||
- (ssl_is_draft22(ssl->version) &&
- !CBS_get_u16(&body, &cipher_suite)) ||
- !CBS_get_u16_length_prefixed(&body, &extensions) ||
- CBS_len(&body) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- return ssl_hs_error;
- }
+ if (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
+ hs->tls13_state = state_read_server_hello;
+ return ssl_hs_ok;
}
- if (ssl_is_draft22(ssl->version)) {
- const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
- // Check if the cipher is a TLS 1.3 cipher.
- if (cipher == NULL ||
- SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) ||
- SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- return ssl_hs_error;
- }
+ const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
+ // Check if the cipher is a TLS 1.3 cipher.
+ if (cipher == NULL ||
+ SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) ||
+ SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ return ssl_hs_error;
+ }
- hs->new_cipher = cipher;
+ hs->new_cipher = cipher;
- if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher) ||
- !hs->transcript.UpdateForHelloRetryRequest()) {
- return ssl_hs_error;
- }
+ if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher) ||
+ !hs->transcript.UpdateForHelloRetryRequest()) {
+ return ssl_hs_error;
}
bool have_cookie, have_key_share, have_supported_versions;
CBS cookie, key_share, supported_versions;
SSL_EXTENSION_TYPE ext_types[] = {
- {ssl_is_draft23(ssl->version) ? (uint16_t)TLSEXT_TYPE_new_key_share
- : (uint16_t)TLSEXT_TYPE_old_key_share,
- &have_key_share, &key_share},
+ {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
{TLSEXT_TYPE_cookie, &have_cookie, &cookie},
{TLSEXT_TYPE_supported_versions, &have_supported_versions,
&supported_versions},
@@ -153,11 +128,6 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
- if (!ssl_is_draft22(ssl->version) && have_supported_versions) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
- return ssl_hs_error;
- }
if (!have_cookie && !have_key_share) {
OPENSSL_PUT_ERROR(SSL, SSL_R_EMPTY_HELLO_RETRY_REQUEST);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@@ -274,8 +244,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
}
// Forbid a second HelloRetryRequest.
- if (ssl_is_draft22(ssl->version) &&
- CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
+ if (CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
return ssl_hs_error;
@@ -295,8 +264,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
}
// Check that the cipher matches the one in the HelloRetryRequest.
- if (ssl_is_draft22(ssl->version) &&
- hs->received_hello_retry_request &&
+ if (hs->received_hello_retry_request &&
hs->new_cipher != cipher) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@@ -308,9 +276,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
have_supported_versions = false;
CBS key_share, pre_shared_key, supported_versions;
SSL_EXTENSION_TYPE ext_types[] = {
- {ssl_is_draft23(ssl->version) ? (uint16_t)TLSEXT_TYPE_new_key_share
- : (uint16_t)TLSEXT_TYPE_old_key_share,
- &have_key_share, &key_share},
+ {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
{TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key},
{TLSEXT_TYPE_supported_versions, &have_supported_versions,
&supported_versions},
@@ -416,13 +382,6 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
}
if (!hs->early_data_offered) {
- // Earlier versions of the resumption experiment added ChangeCipherSpec just
- // before the Finished flight.
- if (!ssl_is_draft22(ssl->version) &&
- !ssl->method->add_change_cipher_spec(ssl)) {
- return ssl_hs_error;
- }
-
// If not sending early data, set client traffic keys now so that alerts are
// encrypted.
if (!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
@@ -515,75 +474,45 @@ static enum ssl_hs_wait_t do_read_certificate_request(SSL_HANDSHAKE *hs) {
}
- if (ssl_is_draft22(ssl->version)) {
- bool have_sigalgs = false, have_ca = false;
- CBS sigalgs, ca;
- const SSL_EXTENSION_TYPE ext_types[] = {
- {TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs},
- {TLSEXT_TYPE_certificate_authorities, &have_ca, &ca},
- };
-
- CBS body = msg.body, context, extensions, supported_signature_algorithms;
- uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!CBS_get_u8_length_prefixed(&body, &context) ||
- // The request context is always empty during the handshake.
- CBS_len(&context) != 0 ||
- !CBS_get_u16_length_prefixed(&body, &extensions) ||
- CBS_len(&body) != 0 ||
- !ssl_parse_extensions(&extensions, &alert, ext_types,
- OPENSSL_ARRAY_SIZE(ext_types),
- 1 /* accept unknown */) ||
- (have_ca && CBS_len(&ca) == 0) ||
- !have_sigalgs ||
- !CBS_get_u16_length_prefixed(&sigalgs,
- &supported_signature_algorithms) ||
- CBS_len(&supported_signature_algorithms) == 0 ||
- !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
- ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- return ssl_hs_error;
- }
+ bool have_sigalgs = false, have_ca = false;
+ CBS sigalgs, ca;
+ const SSL_EXTENSION_TYPE ext_types[] = {
+ {TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs},
+ {TLSEXT_TYPE_certificate_authorities, &have_ca, &ca},
+ };
- if (have_ca) {
- hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca);
- if (!hs->ca_names) {
- ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
- return ssl_hs_error;
- }
- } else {
- hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null());
- if (!hs->ca_names) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- return ssl_hs_error;
- }
- }
- } else {
- CBS body = msg.body, context, supported_signature_algorithms;
- if (!CBS_get_u8_length_prefixed(&body, &context) ||
- // The request context is always empty during the handshake.
- CBS_len(&context) != 0 ||
- !CBS_get_u16_length_prefixed(&body, &supported_signature_algorithms) ||
- CBS_len(&supported_signature_algorithms) == 0 ||
- !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- return ssl_hs_error;
- }
+ CBS body = msg.body, context, extensions, supported_signature_algorithms;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
+ if (!CBS_get_u8_length_prefixed(&body, &context) ||
+ // The request context is always empty during the handshake.
+ CBS_len(&context) != 0 ||
+ !CBS_get_u16_length_prefixed(&body, &extensions) ||
+ CBS_len(&body) != 0 ||
+ !ssl_parse_extensions(&extensions, &alert, ext_types,
+ OPENSSL_ARRAY_SIZE(ext_types),
+ 1 /* accept unknown */) ||
+ (have_ca && CBS_len(&ca) == 0) ||
+ !have_sigalgs ||
+ !CBS_get_u16_length_prefixed(&sigalgs,
+ &supported_signature_algorithms) ||
+ CBS_len(&supported_signature_algorithms) == 0 ||
+ !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
+ ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ return ssl_hs_error;
+ }
- uint8_t alert = SSL_AD_DECODE_ERROR;
- hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &body);
+ if (have_ca) {
+ hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca);
if (!hs->ca_names) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
-
- // Ignore extensions.
- CBS extensions;
- if (!CBS_get_u16_length_prefixed(&body, &extensions) ||
- CBS_len(&body) != 0) {
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ } else {
+ hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null());
+ if (!hs->ca_names) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
}
@@ -670,19 +599,12 @@ static enum ssl_hs_wait_t do_send_end_of_early_data(SSL_HANDSHAKE *hs) {
if (ssl->s3->early_data_accepted) {
hs->can_early_write = false;
- if (ssl_is_draft22(ssl->version)) {
- ScopedCBB cbb;
- CBB body;
- if (!ssl->method->init_message(ssl, cbb.get(), &body,
- SSL3_MT_END_OF_EARLY_DATA) ||
- !ssl_add_message_cbb(ssl, cbb.get())) {
- return ssl_hs_error;
- }
- } else {
- if (!ssl->method->add_alert(ssl, SSL3_AL_WARNING,
- TLS1_AD_END_OF_EARLY_DATA)) {
- return ssl_hs_error;
- }
+ ScopedCBB cbb;
+ CBB body;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
+ SSL3_MT_END_OF_EARLY_DATA) ||
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ return ssl_hs_error;
}
}
@@ -909,8 +831,7 @@ int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg) {
CBS body = msg.body, ticket_nonce, ticket, extensions;
if (!CBS_get_u32(&body, &server_timeout) ||
!CBS_get_u32(&body, &session->ticket_age_add) ||
- (ssl_is_draft22(ssl->version) &&
- !CBS_get_u8_length_prefixed(&body, &ticket_nonce)) ||
+ !CBS_get_u8_length_prefixed(&body, &ticket_nonce) ||
!CBS_get_u16_length_prefixed(&body, &ticket) ||
!CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen) ||
!CBS_get_u16_length_prefixed(&body, &extensions) ||
@@ -933,11 +854,8 @@ int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg) {
// Parse out the extensions.
bool have_early_data_info = false;
CBS early_data_info;
- uint16_t ext_id = ssl_is_draft22(ssl->version)
- ? TLSEXT_TYPE_early_data
- : TLSEXT_TYPE_ticket_early_data_info;
const SSL_EXTENSION_TYPE ext_types[] = {
- {ext_id, &have_early_data_info, &early_data_info},
+ {TLSEXT_TYPE_early_data, &have_early_data_info, &early_data_info},
};
uint8_t alert = SSL_AD_DECODE_ERROR;
diff --git a/src/ssl/tls13_enc.cc b/src/ssl/tls13_enc.cc
index 1bf820ea..cc7afb8d 100644
--- a/src/ssl/tls13_enc.cc
+++ b/src/ssl/tls13_enc.cc
@@ -66,13 +66,11 @@ int tls13_init_early_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *psk,
psk_len, hs->secret, hs->hash_len);
}
-static int hkdf_expand_label(uint8_t *out, uint16_t version,
- const EVP_MD *digest, const uint8_t *secret,
- size_t secret_len, const char *label,
- size_t label_len, const uint8_t *hash,
- size_t hash_len, size_t len) {
- const char *kTLS13LabelVersion =
- ssl_is_draft22(version) ? "tls13 " : "TLS 1.3, ";
+static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
+ const uint8_t *secret, size_t secret_len,
+ const char *label, size_t label_len,
+ const uint8_t *hash, size_t hash_len, size_t len) {
+ static const char kTLS13LabelVersion[] = "tls13 ";
ScopedCBB cbb;
CBB child;
@@ -101,23 +99,18 @@ static const char kTLS13LabelDerived[] = "derived";
int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
size_t len) {
- SSL *const ssl = hs->ssl;
-
- // Draft 18 does not include the extra Derive-Secret step.
- if (ssl_is_draft22(ssl->version)) {
- uint8_t derive_context[EVP_MAX_MD_SIZE];
- unsigned derive_context_len;
- if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len,
- hs->transcript.Digest(), nullptr)) {
- return 0;
- }
+ uint8_t derive_context[EVP_MAX_MD_SIZE];
+ unsigned derive_context_len;
+ if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len,
+ hs->transcript.Digest(), nullptr)) {
+ return 0;
+ }
- if (!hkdf_expand_label(hs->secret, ssl->version, hs->transcript.Digest(),
- hs->secret, hs->hash_len, kTLS13LabelDerived,
- strlen(kTLS13LabelDerived), derive_context,
- derive_context_len, hs->hash_len)) {
- return 0;
- }
+ if (!hkdf_expand_label(hs->secret, hs->transcript.Digest(), hs->secret,
+ hs->hash_len, kTLS13LabelDerived,
+ strlen(kTLS13LabelDerived), derive_context,
+ derive_context_len, hs->hash_len)) {
+ return 0;
}
return HKDF_extract(hs->secret, &hs->hash_len, hs->transcript.Digest(), in,
@@ -135,10 +128,9 @@ static int derive_secret(SSL_HANDSHAKE *hs, uint8_t *out, size_t len,
return 0;
}
- return hkdf_expand_label(out, SSL_get_session(hs->ssl)->ssl_version,
- hs->transcript.Digest(), hs->secret, hs->hash_len,
- label, label_len, context_hash, context_hash_len,
- len);
+ return hkdf_expand_label(out, hs->transcript.Digest(), hs->secret,
+ hs->hash_len, label, label_len, context_hash,
+ context_hash_len, len);
}
int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
@@ -165,16 +157,16 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
// Derive the key.
size_t key_len = EVP_AEAD_key_length(aead);
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
- if (!hkdf_expand_label(key, session->ssl_version, digest, traffic_secret,
- traffic_secret_len, "key", 3, NULL, 0, key_len)) {
+ if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, "key",
+ 3, NULL, 0, key_len)) {
return 0;
}
// Derive the IV.
size_t iv_len = EVP_AEAD_nonce_length(aead);
uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
- if (!hkdf_expand_label(iv, session->ssl_version, digest, traffic_secret,
- traffic_secret_len, "iv", 2, NULL, 0, iv_len)) {
+ if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, "iv",
+ 2, NULL, 0, iv_len)) {
return 0;
}
@@ -210,45 +202,26 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
return 1;
}
-static const char kTLS13LabelExporter[] = "exporter master secret";
-static const char kTLS13LabelEarlyExporter[] = "early exporter master secret";
-
-static const char kTLS13LabelClientEarlyTraffic[] =
- "client early traffic secret";
-static const char kTLS13LabelClientHandshakeTraffic[] =
- "client handshake traffic secret";
-static const char kTLS13LabelServerHandshakeTraffic[] =
- "server handshake traffic secret";
-static const char kTLS13LabelClientApplicationTraffic[] =
- "client application traffic secret";
-static const char kTLS13LabelServerApplicationTraffic[] =
- "server application traffic secret";
-
-static const char kTLS13Draft22LabelExporter[] = "exp master";
-static const char kTLS13Draft22LabelEarlyExporter[] = "e exp master";
-
-static const char kTLS13Draft22LabelClientEarlyTraffic[] = "c e traffic";
-static const char kTLS13Draft22LabelClientHandshakeTraffic[] = "c hs traffic";
-static const char kTLS13Draft22LabelServerHandshakeTraffic[] = "s hs traffic";
-static const char kTLS13Draft22LabelClientApplicationTraffic[] = "c ap traffic";
-static const char kTLS13Draft22LabelServerApplicationTraffic[] = "s ap traffic";
+
+static const char kTLS13LabelExporter[] = "exp master";
+static const char kTLS13LabelEarlyExporter[] = "e exp master";
+
+static const char kTLS13LabelClientEarlyTraffic[] = "c e traffic";
+static const char kTLS13LabelClientHandshakeTraffic[] = "c hs traffic";
+static const char kTLS13LabelServerHandshakeTraffic[] = "s hs traffic";
+static const char kTLS13LabelClientApplicationTraffic[] = "c ap traffic";
+static const char kTLS13LabelServerApplicationTraffic[] = "s ap traffic";
int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- uint16_t version = SSL_get_session(ssl)->ssl_version;
-
- const char *early_traffic_label = ssl_is_draft22(version)
- ? kTLS13Draft22LabelClientEarlyTraffic
- : kTLS13LabelClientEarlyTraffic;
- const char *early_exporter_label = ssl_is_draft22(version)
- ? kTLS13Draft22LabelEarlyExporter
- : kTLS13LabelEarlyExporter;
if (!derive_secret(hs, hs->early_traffic_secret, hs->hash_len,
- early_traffic_label, strlen(early_traffic_label)) ||
+ kTLS13LabelClientEarlyTraffic,
+ strlen(kTLS13LabelClientEarlyTraffic)) ||
!ssl_log_secret(ssl, "CLIENT_EARLY_TRAFFIC_SECRET",
hs->early_traffic_secret, hs->hash_len) ||
!derive_secret(hs, ssl->s3->early_exporter_secret, hs->hash_len,
- early_exporter_label, strlen(early_exporter_label))) {
+ kTLS13LabelEarlyExporter,
+ strlen(kTLS13LabelEarlyExporter))) {
return 0;
}
ssl->s3->early_exporter_secret_len = hs->hash_len;
@@ -257,18 +230,14 @@ int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) {
int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- const char *client_label = ssl_is_draft22(ssl->version)
- ? kTLS13Draft22LabelClientHandshakeTraffic
- : kTLS13LabelClientHandshakeTraffic;
- const char *server_label = ssl_is_draft22(ssl->version)
- ? kTLS13Draft22LabelServerHandshakeTraffic
- : kTLS13LabelServerHandshakeTraffic;
return derive_secret(hs, hs->client_handshake_secret, hs->hash_len,
- client_label, strlen(client_label)) &&
+ kTLS13LabelClientHandshakeTraffic,
+ strlen(kTLS13LabelClientHandshakeTraffic)) &&
ssl_log_secret(ssl, "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
hs->client_handshake_secret, hs->hash_len) &&
derive_secret(hs, hs->server_handshake_secret, hs->hash_len,
- server_label, strlen(server_label)) &&
+ kTLS13LabelServerHandshakeTraffic,
+ strlen(kTLS13LabelServerHandshakeTraffic)) &&
ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
hs->server_handshake_secret, hs->hash_len);
}
@@ -276,32 +245,23 @@ int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) {
int tls13_derive_application_secrets(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
ssl->s3->exporter_secret_len = hs->hash_len;
- const char *client_label = ssl_is_draft22(ssl->version)
- ? kTLS13Draft22LabelClientApplicationTraffic
- : kTLS13LabelClientApplicationTraffic;
- const char *server_label = ssl_is_draft22(ssl->version)
- ? kTLS13Draft22LabelServerApplicationTraffic
- : kTLS13LabelServerApplicationTraffic;
- const char *exporter_label = ssl_is_draft22(ssl->version)
- ? kTLS13Draft22LabelExporter
- : kTLS13LabelExporter;
return derive_secret(hs, hs->client_traffic_secret_0, hs->hash_len,
- client_label, strlen(client_label)) &&
+ kTLS13LabelClientApplicationTraffic,
+ strlen(kTLS13LabelClientApplicationTraffic)) &&
ssl_log_secret(ssl, "CLIENT_TRAFFIC_SECRET_0",
hs->client_traffic_secret_0, hs->hash_len) &&
derive_secret(hs, hs->server_traffic_secret_0, hs->hash_len,
- server_label, strlen(server_label)) &&
+ kTLS13LabelServerApplicationTraffic,
+ strlen(kTLS13LabelServerApplicationTraffic)) &&
ssl_log_secret(ssl, "SERVER_TRAFFIC_SECRET_0",
hs->server_traffic_secret_0, hs->hash_len) &&
derive_secret(hs, ssl->s3->exporter_secret, hs->hash_len,
- exporter_label, strlen(exporter_label)) &&
+ kTLS13LabelExporter, strlen(kTLS13LabelExporter)) &&
ssl_log_secret(ssl, "EXPORTER_SECRET", ssl->s3->exporter_secret,
hs->hash_len);
}
-static const char kTLS13LabelApplicationTraffic[] =
- "application traffic secret";
-static const char kTLS13Draft22LabelApplicationTraffic[] = "traffic upd";
+static const char kTLS13LabelApplicationTraffic[] = "traffic upd";
int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
uint8_t *secret;
@@ -314,35 +274,27 @@ int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
secret_len = ssl->s3->write_traffic_secret_len;
}
- const char *traffic_label = ssl_is_draft22(ssl->version)
- ? kTLS13Draft22LabelApplicationTraffic
- : kTLS13LabelApplicationTraffic;
-
const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl));
- if (!hkdf_expand_label(secret, ssl->version, digest, secret, secret_len,
- traffic_label, strlen(traffic_label), NULL, 0,
- secret_len)) {
+ if (!hkdf_expand_label(
+ secret, digest, secret, secret_len, kTLS13LabelApplicationTraffic,
+ strlen(kTLS13LabelApplicationTraffic), NULL, 0, secret_len)) {
return 0;
}
return tls13_set_traffic_key(ssl, direction, secret, secret_len);
}
-static const char kTLS13LabelResumption[] = "resumption master secret";
-static const char kTLS13Draft22LabelResumption[] = "res master";
+static const char kTLS13LabelResumption[] = "res master";
int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs) {
if (hs->hash_len > SSL_MAX_MASTER_KEY_LENGTH) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- const char *resumption_label = ssl_is_draft22(hs->ssl->version)
- ? kTLS13Draft22LabelResumption
- : kTLS13LabelResumption;
hs->new_session->master_key_length = hs->hash_len;
return derive_secret(hs, hs->new_session->master_key,
- hs->new_session->master_key_length, resumption_label,
- strlen(resumption_label));
+ hs->new_session->master_key_length,
+ kTLS13LabelResumption, strlen(kTLS13LabelResumption));
}
static const char kTLS13LabelFinished[] = "finished";
@@ -355,9 +307,8 @@ static int tls13_verify_data(const EVP_MD *digest, uint16_t version,
uint8_t *context, size_t context_len) {
uint8_t key[EVP_MAX_MD_SIZE];
unsigned len;
- if (!hkdf_expand_label(key, version, digest, secret, hash_len,
- kTLS13LabelFinished, strlen(kTLS13LabelFinished), NULL,
- 0, hash_len) ||
+ if (!hkdf_expand_label(key, digest, secret, hash_len, kTLS13LabelFinished,
+ strlen(kTLS13LabelFinished), NULL, 0, hash_len) ||
HMAC(digest, key, hash_len, context, context_len, out, &len) == NULL) {
return 0;
}
@@ -388,14 +339,9 @@ int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len,
static const char kTLS13LabelResumptionPSK[] = "resumption";
bool tls13_derive_session_psk(SSL_SESSION *session, Span<const uint8_t> nonce) {
- if (!ssl_is_draft22(session->ssl_version)) {
- return true;
- }
-
const EVP_MD *digest = ssl_session_get_digest(session);
- return hkdf_expand_label(session->master_key, session->ssl_version, digest,
- session->master_key, session->master_key_length,
- kTLS13LabelResumptionPSK,
+ return hkdf_expand_label(session->master_key, digest, session->master_key,
+ session->master_key_length, kTLS13LabelResumptionPSK,
strlen(kTLS13LabelResumptionPSK), nonce.data(),
nonce.size(), session->master_key_length);
}
@@ -412,14 +358,6 @@ int tls13_export_keying_material(SSL *ssl, Span<uint8_t> out,
return 0;
}
- uint16_t version = SSL_get_session(ssl)->ssl_version;
- if (!ssl_is_draft22(version)) {
- const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl));
- return hkdf_expand_label(out.data(), version, digest, secret.data(),
- secret.size(), label.data(), label.size(),
- context.data(), context.size(), out.size());
- }
-
const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl));
uint8_t hash[EVP_MAX_MD_SIZE];
@@ -432,18 +370,16 @@ int tls13_export_keying_material(SSL *ssl, Span<uint8_t> out,
nullptr) &&
EVP_Digest(nullptr, 0, export_context, &export_context_len, digest,
nullptr) &&
- hkdf_expand_label(derived_secret, version, digest, secret.data(),
- secret.size(), label.data(), label.size(),
- export_context, export_context_len,
- derived_secret_len) &&
- hkdf_expand_label(out.data(), version, digest, derived_secret,
+ hkdf_expand_label(derived_secret, digest, secret.data(), secret.size(),
+ label.data(), label.size(), export_context,
+ export_context_len, derived_secret_len) &&
+ hkdf_expand_label(out.data(), digest, derived_secret,
derived_secret_len, kTLS13LabelExportKeying,
strlen(kTLS13LabelExportKeying), hash, hash_len,
out.size());
}
-static const char kTLS13LabelPSKBinder[] = "resumption psk binder key";
-static const char kTLS13Draft22LabelPSKBinder[] = "res binder";
+static const char kTLS13LabelPSKBinder[] = "res binder";
static int tls13_psk_binder(uint8_t *out, uint16_t version,
const EVP_MD *digest, uint8_t *psk, size_t psk_len,
@@ -461,15 +397,12 @@ static int tls13_psk_binder(uint8_t *out, uint16_t version,
NULL, 0)) {
return 0;
}
- const char *binder_label = ssl_is_draft22(version)
- ? kTLS13Draft22LabelPSKBinder
- : kTLS13LabelPSKBinder;
uint8_t binder_key[EVP_MAX_MD_SIZE] = {0};
size_t len;
- if (!hkdf_expand_label(binder_key, version, digest, early_secret, hash_len,
- binder_label, strlen(binder_label), binder_context,
- binder_context_len, hash_len) ||
+ if (!hkdf_expand_label(binder_key, digest, early_secret, hash_len,
+ kTLS13LabelPSKBinder, strlen(kTLS13LabelPSKBinder),
+ binder_context, binder_context_len, hash_len) ||
!tls13_verify_data(digest, version, out, &len, binder_key, hash_len,
context, context_len)) {
return 0;
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index a6a3a0a5..3bd67866 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -63,15 +63,10 @@ static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, bool *out_need_retry,
SSL *const ssl = hs->ssl;
*out_need_retry = false;
- uint16_t key_share_ext = TLSEXT_TYPE_old_key_share;
- if (ssl_is_draft23(ssl->version)) {
- key_share_ext = TLSEXT_TYPE_new_key_share;
- }
-
// We only support connections that include an ECDHE key exchange.
CBS key_share;
if (!ssl_client_hello_get_extension(client_hello, &key_share,
- key_share_ext)) {
+ TLSEXT_TYPE_key_share)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
return 0;
@@ -187,9 +182,8 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) {
SSL3_MT_NEW_SESSION_TICKET) ||
!CBB_add_u32(&body, session->timeout) ||
!CBB_add_u32(&body, session->ticket_age_add) ||
- (ssl_is_draft22(ssl->version) &&
- (!CBB_add_u8_length_prefixed(&body, &nonce_cbb) ||
- !CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)))) ||
+ !CBB_add_u8_length_prefixed(&body, &nonce_cbb) ||
+ !CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)) ||
!CBB_add_u16_length_prefixed(&body, &ticket) ||
!tls13_derive_session_psk(session.get(), nonce) ||
!ssl_encrypt_ticket(ssl, &ticket, session.get()) ||
@@ -199,9 +193,7 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) {
if (ssl->cert->enable_early_data) {
CBB early_data_info;
- if (!CBB_add_u16(&extensions, ssl_is_draft22(ssl->version)
- ? TLSEXT_TYPE_early_data
- : TLSEXT_TYPE_ticket_early_data_info) ||
+ if (!CBB_add_u16(&extensions, TLSEXT_TYPE_early_data) ||
!CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
!CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
!CBB_flush(&extensions)) {
@@ -479,8 +471,7 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
ssl->s3->early_data_accepted = false;
ssl->s3->skip_early_data = true;
ssl->method->next_message(ssl);
- if (ssl_is_draft22(ssl->version) &&
- !hs->transcript.UpdateForHelloRetryRequest()) {
+ if (!hs->transcript.UpdateForHelloRetryRequest()) {
return ssl_hs_error;
}
hs->tls13_state = state_send_hello_retry_request;
@@ -498,52 +489,30 @@ static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (ssl_is_draft22(ssl->version)) {
- ScopedCBB cbb;
- CBB body, session_id, extensions;
- uint16_t group_id;
- if (!ssl->method->init_message(ssl, cbb.get(), &body,
- SSL3_MT_SERVER_HELLO) ||
- !CBB_add_u16(&body, TLS1_2_VERSION) ||
- !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) ||
- !CBB_add_u8_length_prefixed(&body, &session_id) ||
- !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
- !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
- !CBB_add_u8(&body, 0 /* no compression */) ||
- !tls1_get_shared_group(hs, &group_id) ||
- !CBB_add_u16_length_prefixed(&body, &extensions) ||
- !CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) ||
- !CBB_add_u16(&extensions, 2 /* length */) ||
- !CBB_add_u16(&extensions, ssl->version) ||
- !CBB_add_u16(&extensions, ssl_is_draft23(ssl->version)
- ? TLSEXT_TYPE_new_key_share
- : TLSEXT_TYPE_old_key_share) ||
- !CBB_add_u16(&extensions, 2 /* length */) ||
- !CBB_add_u16(&extensions, group_id) ||
- !ssl_add_message_cbb(ssl, cbb.get())) {
- return ssl_hs_error;
- }
+ ScopedCBB cbb;
+ CBB body, session_id, extensions;
+ uint16_t group_id;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
+ !CBB_add_u16(&body, TLS1_2_VERSION) ||
+ !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) ||
+ !CBB_add_u8_length_prefixed(&body, &session_id) ||
+ !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
+ !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
+ !CBB_add_u8(&body, 0 /* no compression */) ||
+ !tls1_get_shared_group(hs, &group_id) ||
+ !CBB_add_u16_length_prefixed(&body, &extensions) ||
+ !CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) ||
+ !CBB_add_u16(&extensions, 2 /* length */) ||
+ !CBB_add_u16(&extensions, ssl->version) ||
+ !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
+ !CBB_add_u16(&extensions, 2 /* length */) ||
+ !CBB_add_u16(&extensions, group_id) ||
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ return ssl_hs_error;
+ }
- if (!ssl->method->add_change_cipher_spec(ssl)) {
- return ssl_hs_error;
- }
- } else {
- ScopedCBB cbb;
- CBB body, extensions;
- uint16_t group_id;
- if (!ssl->method->init_message(ssl, cbb.get(), &body,
- SSL3_MT_HELLO_RETRY_REQUEST) ||
- !CBB_add_u16(&body, ssl->version) ||
- (ssl_is_draft22(ssl->version) &&
- !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher))) ||
- !tls1_get_shared_group(hs, &group_id) ||
- !CBB_add_u16_length_prefixed(&body, &extensions) ||
- !CBB_add_u16(&extensions, TLSEXT_TYPE_old_key_share) ||
- !CBB_add_u16(&extensions, 2 /* length */) ||
- !CBB_add_u16(&extensions, group_id) ||
- !ssl_add_message_cbb(ssl, cbb.get())) {
- return ssl_hs_error;
- }
+ if (!ssl->method->add_change_cipher_spec(ssl)) {
+ return ssl_hs_error;
}
hs->sent_hello_retry_request = true;
@@ -608,7 +577,7 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
- if ((!ssl_is_draft22(ssl->version) || !hs->sent_hello_retry_request) &&
+ if (!hs->sent_hello_retry_request &&
!ssl->method->add_change_cipher_spec(ssl)) {
return ssl_hs_error;
}
@@ -640,48 +609,34 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
// Send a CertificateRequest, if necessary.
if (hs->cert_request) {
- if (ssl_is_draft22(ssl->version)) {
- CBB cert_request_extensions, sigalg_contents, sigalgs_cbb;
- if (!ssl->method->init_message(ssl, cbb.get(), &body,
- SSL3_MT_CERTIFICATE_REQUEST) ||
- !CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
- !CBB_add_u16_length_prefixed(&body, &cert_request_extensions) ||
- !CBB_add_u16(&cert_request_extensions,
- TLSEXT_TYPE_signature_algorithms) ||
+ CBB cert_request_extensions, sigalg_contents, sigalgs_cbb;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
+ SSL3_MT_CERTIFICATE_REQUEST) ||
+ !CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
+ !CBB_add_u16_length_prefixed(&body, &cert_request_extensions) ||
+ !CBB_add_u16(&cert_request_extensions,
+ TLSEXT_TYPE_signature_algorithms) ||
+ !CBB_add_u16_length_prefixed(&cert_request_extensions,
+ &sigalg_contents) ||
+ !CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) ||
+ !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) {
+ return ssl_hs_error;
+ }
+
+ if (ssl_has_client_CAs(ssl)) {
+ CBB ca_contents;
+ if (!CBB_add_u16(&cert_request_extensions,
+ TLSEXT_TYPE_certificate_authorities) ||
!CBB_add_u16_length_prefixed(&cert_request_extensions,
- &sigalg_contents) ||
- !CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) ||
- !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) {
+ &ca_contents) ||
+ !ssl_add_client_CA_list(ssl, &ca_contents) ||
+ !CBB_flush(&cert_request_extensions)) {
return ssl_hs_error;
}
+ }
- if (ssl_has_client_CAs(ssl)) {
- CBB ca_contents;
- if (!CBB_add_u16(&cert_request_extensions,
- TLSEXT_TYPE_certificate_authorities) ||
- !CBB_add_u16_length_prefixed(&cert_request_extensions,
- &ca_contents) ||
- !ssl_add_client_CA_list(ssl, &ca_contents) ||
- !CBB_flush(&cert_request_extensions)) {
- return ssl_hs_error;
- }
- }
-
- if (!ssl_add_message_cbb(ssl, cbb.get())) {
- return ssl_hs_error;
- }
- } else {
- CBB sigalgs_cbb;
- if (!ssl->method->init_message(ssl, cbb.get(), &body,
- SSL3_MT_CERTIFICATE_REQUEST) ||
- !CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
- !CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
- !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb) ||
- !ssl_add_client_CA_list(ssl, &body) ||
- !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
- !ssl_add_message_cbb(ssl, cbb.get())) {
- return ssl_hs_error;
- }
+ if (!ssl_add_message_cbb(ssl, cbb.get())) {
+ return ssl_hs_error;
}
}
@@ -738,13 +693,11 @@ static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
// the wire sooner and also avoids triggering a write on |SSL_read| when
// processing the client Finished. This requires computing the client
// Finished early. See draft-ietf-tls-tls13-18, section 4.5.1.
- if (ssl_is_draft22(ssl->version)) {
- static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0,
- 0, 0};
- if (!hs->transcript.Update(kEndOfEarlyData)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return ssl_hs_error;
- }
+ static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0,
+ 0, 0};
+ if (!hs->transcript.Update(kEndOfEarlyData)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return ssl_hs_error;
}
size_t finished_len;
@@ -801,22 +754,20 @@ static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) {
// If early data was not accepted, the EndOfEarlyData and ChangeCipherSpec
// message will be in the discarded early data.
if (hs->ssl->s3->early_data_accepted) {
- if (ssl_is_draft22(ssl->version)) {
- SSLMessage msg;
- if (!ssl->method->get_message(ssl, &msg)) {
- return ssl_hs_read_message;
- }
-
- if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) {
- return ssl_hs_error;
- }
- if (CBS_len(&msg.body) != 0) {
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- return ssl_hs_error;
- }
- ssl->method->next_message(ssl);
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
}
+
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) {
+ return ssl_hs_error;
+ }
+ if (CBS_len(&msg.body) != 0) {
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ return ssl_hs_error;
+ }
+ ssl->method->next_message(ssl);
}
}
if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
diff --git a/src/ssl/tls_record.cc b/src/ssl/tls_record.cc
index 3d34951d..05a3d569 100644
--- a/src/ssl/tls_record.cc
+++ b/src/ssl/tls_record.cc
@@ -356,15 +356,6 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type,
}
if (type == SSL3_RT_ALERT) {
- // Return end_of_early_data alerts as-is for the caller to process.
- if (!ssl_is_draft22(ssl->version) &&
- out->size() == 2 &&
- (*out)[0] == SSL3_AL_WARNING &&
- (*out)[1] == TLS1_AD_END_OF_EARLY_DATA) {
- *out_type = type;
- return ssl_open_record_success;
- }
-
return ssl_process_alert(ssl, out_alert, *out);
}
diff --git a/src/third_party/fiat/curve25519.c b/src/third_party/fiat/curve25519.c
index dfa4a392..ecf00e53 100644
--- a/src/third_party/fiat/curve25519.c
+++ b/src/third_party/fiat/curve25519.c
@@ -512,8 +512,6 @@ static void fe_sq_tt(fe *h, const fe *f) {
fe_sqr_impl(h->v, f->v);
}
-#if !defined(BORINGSSL_X25519_X86_64)
-
// Replace (f,g) with (g,f) if b == 1;
// replace (f,g) with (f,g) if b == 0.
//
@@ -589,8 +587,6 @@ static void fe_mul121666(fe *h, const fe_loose *f) {
assert_fe(h->v);
}
-#endif // !BORINGSSL_X25519_X86_64
-
// Adapted from Fiat-synthesized |fe_sub_impl| with |out| = 0.
static void fe_neg_impl(uint64_t out[5], const uint64_t in2[5]) {
{ const uint64_t x10 = 0;
@@ -1201,8 +1197,6 @@ static void fe_sq_tt(fe *h, const fe *f) {
fe_sqr_impl(h->v, f->v);
}
-#if !defined(BORINGSSL_X25519_X86_64)
-
// Replace (f,g) with (g,f) if b == 1;
// replace (f,g) with (f,g) if b == 0.
//
@@ -1342,8 +1336,6 @@ static void fe_mul121666(fe *h, const fe_loose *f) {
assert_fe(h->v);
}
-#endif // !BORINGSSL_X25519_X86_64
-
// Adapted from Fiat-synthesized |fe_sub_impl| with |out| = 0.
static void fe_neg_impl(uint32_t out[10], const uint32_t in2[10]) {
{ const uint32_t x20 = 0;
@@ -3022,8 +3014,31 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
OPENSSL_memcpy(pkcopy, public_key, 32);
uint8_t rcopy[32];
OPENSSL_memcpy(rcopy, signature, 32);
- uint8_t scopy[32];
- OPENSSL_memcpy(scopy, signature + 32, 32);
+ union {
+ uint64_t u64[4];
+ uint8_t u8[32];
+ } scopy;
+ OPENSSL_memcpy(&scopy.u8[0], signature + 32, 32);
+
+ // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
+ // the range [0, order) in order to prevent signature malleability.
+
+ // kOrder is the order of Curve25519 in little-endian form.
+ static const uint64_t kOrder[4] = {
+ UINT64_C(0x5812631a5cf5d3ed),
+ UINT64_C(0x14def9dea2f79cd6),
+ 0,
+ UINT64_C(0x1000000000000000),
+ };
+ for (size_t i = 3;; i--) {
+ if (scopy.u64[i] > kOrder[i]) {
+ return 0;
+ } else if (scopy.u64[i] < kOrder[i]) {
+ break;
+ } else if (i == 0) {
+ return 0;
+ }
+ }
SHA512_CTX hash_ctx;
SHA512_Init(&hash_ctx);
@@ -3036,7 +3051,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
x25519_sc_reduce(h);
ge_p2 R;
- ge_double_scalarmult_vartime(&R, h, &A, scopy);
+ ge_double_scalarmult_vartime(&R, h, &A, scopy.u8);
uint8_t rcheck[32];
x25519_ge_tobytes(rcheck, &R);
@@ -3063,15 +3078,6 @@ void ED25519_keypair_from_seed(uint8_t out_public_key[32],
}
-#if defined(BORINGSSL_X25519_X86_64)
-
-static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
- const uint8_t point[32]) {
- x25519_x86_64(out, scalar, point);
-}
-
-#else
-
static void x25519_scalar_mult_generic(uint8_t out[32],
const uint8_t scalar[32],
const uint8_t point[32]) {
@@ -3166,9 +3172,6 @@ static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
x25519_scalar_mult_generic(out, scalar, point);
}
-#endif // BORINGSSL_X25519_X86_64
-
-
void X25519_keypair(uint8_t out_public_value[32], uint8_t out_private_key[32]) {
RAND_bytes(out_private_key, 32);
@@ -3200,20 +3203,6 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0;
}
-#if defined(BORINGSSL_X25519_X86_64)
-
-// When |BORINGSSL_X25519_X86_64| is set, base point multiplication is done with
-// the Montgomery ladder because it's faster. Otherwise it's done using the
-// Ed25519 tables.
-
-void X25519_public_from_private(uint8_t out_public_value[32],
- const uint8_t private_key[32]) {
- static const uint8_t kMongomeryBasePoint[32] = {9};
- x25519_scalar_mult(out_public_value, private_key, kMongomeryBasePoint);
-}
-
-#else
-
void X25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32]) {
#if defined(BORINGSSL_X25519_NEON)
@@ -3243,5 +3232,3 @@ void X25519_public_from_private(uint8_t out_public_value[32],
fe_mul_tlt(&zminusy_inv, &zplusy, &zminusy_inv);
fe_tobytes(out_public_value, &zminusy_inv);
}
-
-#endif // BORINGSSL_X25519_X86_64
diff --git a/src/third_party/fiat/internal.h b/src/third_party/fiat/internal.h
index c5dcc047..be3e265a 100644
--- a/src/third_party/fiat/internal.h
+++ b/src/third_party/fiat/internal.h
@@ -32,15 +32,6 @@ extern "C" {
#include "../../crypto/internal.h"
-#if defined(OPENSSL_X86_64) && !defined(OPENSSL_SMALL) && \
- !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_ASM)
-#define BORINGSSL_X25519_X86_64
-
-void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
- const uint8_t point[32]);
-#endif
-
-
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_APPLE)
#define BORINGSSL_X25519_NEON
diff --git a/src/tool/client.cc b/src/tool/client.cc
index de1a8ca3..41626982 100644
--- a/src/tool/client.cc
+++ b/src/tool/client.cc
@@ -332,12 +332,8 @@ static bool DoConnection(SSL_CTX *ctx,
}
static bool GetTLS13Variant(tls13_variant_t *out, const std::string &in) {
- if (in == "draft22") {
- *out = tls13_draft22;
- return true;
- }
- if (in == "experiment2") {
- *out = tls13_experiment2;
+ if (in == "draft23") {
+ *out = tls13_default;
return true;
}
return false;
diff --git a/src/tool/server.cc b/src/tool/server.cc
index 37235a78..896aa867 100644
--- a/src/tool/server.cc
+++ b/src/tool/server.cc
@@ -308,7 +308,7 @@ bool Server(const std::vector<std::string> &args) {
}
if (args_map.count("-tls13-variant") != 0) {
- SSL_CTX_set_tls13_variant(ctx.get(), tls13_experiment2);
+ SSL_CTX_set_tls13_variant(ctx.get(), tls13_default);
}
if (args_map.count("-debug") != 0) {
diff --git a/src/util/fipstools/delocate.go b/src/util/fipstools/delocate.go
index b4371fc6..7f45b87b 100644
--- a/src/util/fipstools/delocate.go
+++ b/src/util/fipstools/delocate.go
@@ -12,8 +12,6 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-//go:generate peg delocate.peg
-
// delocate performs several transformations of textual assembly code. See
// crypto/fipsmodule/FIPS.md for an overview.
package main
diff --git a/src/util/fipstools/delocate.peg b/src/util/fipstools/delocate.peg
index abcd9534..3dcead2d 100644
--- a/src/util/fipstools/delocate.peg
+++ b/src/util/fipstools/delocate.peg
@@ -32,7 +32,7 @@ Directive <- '.' DirectiveName (WS Args)?
DirectiveName <- [[A-Z0-9_]]+
LocationDirective <- (".file" / ".loc") WS [^#\n]+
Args <- Arg ((WS? ',' WS?) Arg)*
-Arg <- QuotedArg / [[0-9a-z%+\-_@.]]*
+Arg <- QuotedArg / [[0-9a-z%+\-*_@.]]*
QuotedArg <- '"' QuotedText '"'
QuotedText <- (EscapedChar / [^"])*
LabelContainingDirective <- LabelContainingDirectiveName WS SymbolArgs
diff --git a/src/util/fipstools/delocate.peg.go b/src/util/fipstools/delocate.peg.go
index 4cbdcada..f0ad78f6 100644
--- a/src/util/fipstools/delocate.peg.go
+++ b/src/util/fipstools/delocate.peg.go
@@ -1,5 +1,7 @@
package main
+//go:generate peg delocate.peg
+
import (
"fmt"
"math"
@@ -1067,7 +1069,7 @@ func (p *Asm) Init() {
position, tokenIndex = position96, tokenIndex96
return false
},
- /* 7 Arg <- <(QuotedArg / ([0-9] / [0-9] / ([a-z] / [A-Z]) / '%' / '+' / '-' / '_' / '@' / '.')*)> */
+ /* 7 Arg <- <(QuotedArg / ([0-9] / [0-9] / ([a-z] / [A-Z]) / '%' / '+' / '-' / '*' / '_' / '@' / '.')*)> */
func() bool {
{
position105 := position
@@ -1137,20 +1139,27 @@ func (p *Asm) Init() {
goto l110
l118:
position, tokenIndex = position110, tokenIndex110
- if buffer[position] != rune('_') {
+ if buffer[position] != rune('*') {
goto l119
}
position++
goto l110
l119:
position, tokenIndex = position110, tokenIndex110
- if buffer[position] != rune('@') {
+ if buffer[position] != rune('_') {
goto l120
}
position++
goto l110
l120:
position, tokenIndex = position110, tokenIndex110
+ if buffer[position] != rune('@') {
+ goto l121
+ }
+ position++
+ goto l110
+ l121:
+ position, tokenIndex = position110, tokenIndex110
if buffer[position] != rune('.') {
goto l109
}
@@ -1169,2838 +1178,2838 @@ func (p *Asm) Init() {
},
/* 8 QuotedArg <- <('"' QuotedText '"')> */
func() bool {
- position121, tokenIndex121 := position, tokenIndex
+ position122, tokenIndex122 := position, tokenIndex
{
- position122 := position
+ position123 := position
if buffer[position] != rune('"') {
- goto l121
+ goto l122
}
position++
if !_rules[ruleQuotedText]() {
- goto l121
+ goto l122
}
if buffer[position] != rune('"') {
- goto l121
+ goto l122
}
position++
- add(ruleQuotedArg, position122)
+ add(ruleQuotedArg, position123)
}
return true
- l121:
- position, tokenIndex = position121, tokenIndex121
+ l122:
+ position, tokenIndex = position122, tokenIndex122
return false
},
/* 9 QuotedText <- <(EscapedChar / (!'"' .))*> */
func() bool {
{
- position124 := position
- l125:
+ position125 := position
+ l126:
{
- position126, tokenIndex126 := position, tokenIndex
+ position127, tokenIndex127 := position, tokenIndex
{
- position127, tokenIndex127 := position, tokenIndex
+ position128, tokenIndex128 := position, tokenIndex
if !_rules[ruleEscapedChar]() {
- goto l128
+ goto l129
}
- goto l127
- l128:
- position, tokenIndex = position127, tokenIndex127
+ goto l128
+ l129:
+ position, tokenIndex = position128, tokenIndex128
{
- position129, tokenIndex129 := position, tokenIndex
+ position130, tokenIndex130 := position, tokenIndex
if buffer[position] != rune('"') {
- goto l129
+ goto l130
}
position++
- goto l126
- l129:
- position, tokenIndex = position129, tokenIndex129
+ goto l127
+ l130:
+ position, tokenIndex = position130, tokenIndex130
}
if !matchDot() {
- goto l126
+ goto l127
}
}
+ l128:
+ goto l126
l127:
- goto l125
- l126:
- position, tokenIndex = position126, tokenIndex126
+ position, tokenIndex = position127, tokenIndex127
}
- add(ruleQuotedText, position124)
+ add(ruleQuotedText, position125)
}
return true
},
/* 10 LabelContainingDirective <- <(LabelContainingDirectiveName WS SymbolArgs)> */
func() bool {
- position130, tokenIndex130 := position, tokenIndex
+ position131, tokenIndex131 := position, tokenIndex
{
- position131 := position
+ position132 := position
if !_rules[ruleLabelContainingDirectiveName]() {
- goto l130
+ goto l131
}
if !_rules[ruleWS]() {
- goto l130
+ goto l131
}
if !_rules[ruleSymbolArgs]() {
- goto l130
+ goto l131
}
- add(ruleLabelContainingDirective, position131)
+ add(ruleLabelContainingDirective, position132)
}
return true
- l130:
- position, tokenIndex = position130, tokenIndex130
+ l131:
+ position, tokenIndex = position131, tokenIndex131
return false
},
/* 11 LabelContainingDirectiveName <- <(('.' ('l' / 'L') ('o' / 'O') ('n' / 'N') ('g' / 'G')) / ('.' ('s' / 'S') ('e' / 'E') ('t' / 'T')) / ('.' '8' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' '4' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' ('q' / 'Q') ('u' / 'U') ('a' / 'A') ('d' / 'D')) / ('.' ('t' / 'T') ('c' / 'C')) / ('.' ('l' / 'L') ('o' / 'O') ('c' / 'C') ('a' / 'A') ('l' / 'L') ('e' / 'E') ('n' / 'N') ('t' / 'T') ('r' / 'R') ('y' / 'Y')) / ('.' ('s' / 'S') ('i' / 'I') ('z' / 'Z') ('e' / 'E')) / ('.' ('t' / 'T') ('y' / 'Y') ('p' / 'P') ('e' / 'E')))> */
func() bool {
- position132, tokenIndex132 := position, tokenIndex
+ position133, tokenIndex133 := position, tokenIndex
{
- position133 := position
+ position134 := position
{
- position134, tokenIndex134 := position, tokenIndex
+ position135, tokenIndex135 := position, tokenIndex
if buffer[position] != rune('.') {
- goto l135
+ goto l136
}
position++
{
- position136, tokenIndex136 := position, tokenIndex
+ position137, tokenIndex137 := position, tokenIndex
if buffer[position] != rune('l') {
- goto l137
+ goto l138
}
position++
- goto l136
- l137:
- position, tokenIndex = position136, tokenIndex136
+ goto l137
+ l138:
+ position, tokenIndex = position137, tokenIndex137
if buffer[position] != rune('L') {
- goto l135
+ goto l136
}
position++
}
- l136:
+ l137:
{
- position138, tokenIndex138 := position, tokenIndex
+ position139, tokenIndex139 := position, tokenIndex
if buffer[position] != rune('o') {
- goto l139
+ goto l140
}
position++
- goto l138
- l139:
- position, tokenIndex = position138, tokenIndex138
+ goto l139
+ l140:
+ position, tokenIndex = position139, tokenIndex139
if buffer[position] != rune('O') {
- goto l135
+ goto l136
}
position++
}
- l138:
+ l139:
{
- position140, tokenIndex140 := position, tokenIndex
+ position141, tokenIndex141 := position, tokenIndex
if buffer[position] != rune('n') {
- goto l141
+ goto l142
}
position++
- goto l140
- l141:
- position, tokenIndex = position140, tokenIndex140
+ goto l141
+ l142:
+ position, tokenIndex = position141, tokenIndex141
if buffer[position] != rune('N') {
- goto l135
+ goto l136
}
position++
}
- l140:
+ l141:
{
- position142, tokenIndex142 := position, tokenIndex
+ position143, tokenIndex143 := position, tokenIndex
if buffer[position] != rune('g') {
- goto l143
+ goto l144
}
position++
- goto l142
- l143:
- position, tokenIndex = position142, tokenIndex142
+ goto l143
+ l144:
+ position, tokenIndex = position143, tokenIndex143
if buffer[position] != rune('G') {
- goto l135
+ goto l136
}
position++
}
- l142:
- goto l134
- l135:
- position, tokenIndex = position134, tokenIndex134
+ l143:
+ goto l135
+ l136:
+ position, tokenIndex = position135, tokenIndex135
if buffer[position] != rune('.') {
- goto l144
+ goto l145
}
position++
{
- position145, tokenIndex145 := position, tokenIndex
+ position146, tokenIndex146 := position, tokenIndex
if buffer[position] != rune('s') {
- goto l146
+ goto l147
}
position++
- goto l145
- l146:
- position, tokenIndex = position145, tokenIndex145
+ goto l146
+ l147:
+ position, tokenIndex = position146, tokenIndex146
if buffer[position] != rune('S') {
- goto l144
+ goto l145
}
position++
}
- l145:
+ l146:
{
- position147, tokenIndex147 := position, tokenIndex
+ position148, tokenIndex148 := position, tokenIndex
if buffer[position] != rune('e') {
- goto l148
+ goto l149
}
position++
- goto l147
- l148:
- position, tokenIndex = position147, tokenIndex147
+ goto l148
+ l149:
+ position, tokenIndex = position148, tokenIndex148
if buffer[position] != rune('E') {
- goto l144
+ goto l145
}
position++
}
- l147:
+ l148:
{
- position149, tokenIndex149 := position, tokenIndex
+ position150, tokenIndex150 := position, tokenIndex
if buffer[position] != rune('t') {
- goto l150
+ goto l151
}
position++
- goto l149
- l150:
- position, tokenIndex = position149, tokenIndex149
+ goto l150
+ l151:
+ position, tokenIndex = position150, tokenIndex150
if buffer[position] != rune('T') {
- goto l144
+ goto l145
}
position++
}
- l149:
- goto l134
- l144:
- position, tokenIndex = position134, tokenIndex134
+ l150:
+ goto l135
+ l145:
+ position, tokenIndex = position135, tokenIndex135
if buffer[position] != rune('.') {
- goto l151
+ goto l152
}
position++
if buffer[position] != rune('8') {
- goto l151
+ goto l152
}
position++
{
- position152, tokenIndex152 := position, tokenIndex
+ position153, tokenIndex153 := position, tokenIndex
if buffer[position] != rune('b') {
- goto l153
+ goto l154
}
position++
- goto l152
- l153:
- position, tokenIndex = position152, tokenIndex152
+ goto l153
+ l154:
+ position, tokenIndex = position153, tokenIndex153
if buffer[position] != rune('B') {
- goto l151
+ goto l152
}
position++
}
- l152:
+ l153:
{
- position154, tokenIndex154 := position, tokenIndex
+ position155, tokenIndex155 := position, tokenIndex
if buffer[position] != rune('y') {
- goto l155
+ goto l156
}
position++
- goto l154
- l155:
- position, tokenIndex = position154, tokenIndex154
+ goto l155
+ l156:
+ position, tokenIndex = position155, tokenIndex155
if buffer[position] != rune('Y') {
- goto l151
+ goto l152
}
position++
}
- l154:
+ l155:
{
- position156, tokenIndex156 := position, tokenIndex
+ position157, tokenIndex157 := position, tokenIndex
if buffer[position] != rune('t') {
- goto l157
+ goto l158
}
position++
- goto l156
- l157:
- position, tokenIndex = position156, tokenIndex156
+ goto l157
+ l158:
+ position, tokenIndex = position157, tokenIndex157
if buffer[position] != rune('T') {
- goto l151
+ goto l152
}
position++
}
- l156:
+ l157:
{
- position158, tokenIndex158 := position, tokenIndex
+ position159, tokenIndex159 := position, tokenIndex
if buffer[position] != rune('e') {
- goto l159
+ goto l160
}
position++
- goto l158
- l159:
- position, tokenIndex = position158, tokenIndex158
+ goto l159
+ l160:
+ position, tokenIndex = position159, tokenIndex159
if buffer[position] != rune('E') {
- goto l151
+ goto l152
}
position++
}
- l158:
- goto l134
- l151:
- position, tokenIndex = position134, tokenIndex134
+ l159:
+ goto l135
+ l152:
+ position, tokenIndex = position135, tokenIndex135
if buffer[position] != rune('.') {
- goto l160
+ goto l161
}
position++
if buffer[position] != rune('4') {
- goto l160
+ goto l161
}
position++
{
- position161, tokenIndex161 := position, tokenIndex
+ position162, tokenIndex162 := position, tokenIndex
if buffer[position] != rune('b') {
- goto l162
+ goto l163
}
position++
- goto l161
- l162:
- position, tokenIndex = position161, tokenIndex161
+ goto l162
+ l163:
+ position, tokenIndex = position162, tokenIndex162
if buffer[position] != rune('B') {
- goto l160
+ goto l161
}
position++
}
- l161:
+ l162:
{
- position163, tokenIndex163 := position, tokenIndex
+ position164, tokenIndex164 := position, tokenIndex
if buffer[position] != rune('y') {
- goto l164
+ goto l165
}
position++
- goto l163
- l164:
- position, tokenIndex = position163, tokenIndex163
+ goto l164
+ l165:
+ position, tokenIndex = position164, tokenIndex164
if buffer[position] != rune('Y') {
- goto l160
+ goto l161
}
position++
}
- l163:
+ l164:
{
- position165, tokenIndex165 := position, tokenIndex
+ position166, tokenIndex166 := position, tokenIndex
if buffer[position] != rune('t') {
- goto l166
+ goto l167
}
position++
- goto l165
- l166:
- position, tokenIndex = position165, tokenIndex165
+ goto l166
+ l167:
+ position, tokenIndex = position166, tokenIndex166
if buffer[position] != rune('T') {
- goto l160
+ goto l161
}
position++
}
- l165:
+ l166:
{
- position167, tokenIndex167 := position, tokenIndex
+ position168, tokenIndex168 := position, tokenIndex
if buffer[position] != rune('e') {
- goto l168
+ goto l169
}
position++
- goto l167
- l168:
- position, tokenIndex = position167, tokenIndex167
+ goto l168
+ l169:
+ position, tokenIndex = position168, tokenIndex168
if buffer[position] != rune('E') {
- goto l160
+ goto l161
}
position++
}
- l167:
- goto l134
- l160:
- position, tokenIndex = position134, tokenIndex134
+ l168:
+ goto l135
+ l161:
+ position, tokenIndex = position135, tokenIndex135
if buffer[position] != rune('.') {
- goto l169
+ goto l170
}
position++
{
- position170, tokenIndex170 := position, tokenIndex
+ position171, tokenIndex171 := position, tokenIndex
if buffer[position] != rune('q') {
- goto l171
+ goto l172
}
position++
- goto l170
- l171:
- position, tokenIndex = position170, tokenIndex170
+ goto l171
+ l172:
+ position, tokenIndex = position171, tokenIndex171
if buffer[position] != rune('Q') {
- goto l169
+ goto l170
}
position++
}
- l170:
+ l171:
{
- position172, tokenIndex172 := position, tokenIndex
+ position173, tokenIndex173 := position, tokenIndex
if buffer[position] != rune('u') {
- goto l173
+ goto l174
}
position++
- goto l172
- l173:
- position, tokenIndex = position172, tokenIndex172
+ goto l173
+ l174:
+ position, tokenIndex = position173, tokenIndex173
if buffer[position] != rune('U') {
- goto l169
+ goto l170
}
position++
}
- l172:
+ l173:
{
- position174, tokenIndex174 := position, tokenIndex
+ position175, tokenIndex175 := position, tokenIndex
if buffer[position] != rune('a') {
- goto l175
+ goto l176
}
position++
- goto l174
- l175:
- position, tokenIndex = position174, tokenIndex174
+ goto l175
+ l176:
+ position, tokenIndex = position175, tokenIndex175
if buffer[position] != rune('A') {
- goto l169
+ goto l170
}
position++
}
- l174:
+ l175:
{
- position176, tokenIndex176 := position, tokenIndex
+ position177, tokenIndex177 := position, tokenIndex
if buffer[position] != rune('d') {
- goto l177
+ goto l178
}
position++
- goto l176
- l177:
- position, tokenIndex = position176, tokenIndex176
+ goto l177
+ l178:
+ position, tokenIndex = position177, tokenIndex177
if buffer[position] != rune('D') {
- goto l169
+ goto l170
}
position++
}
- l176:
- goto l134
- l169:
- position, tokenIndex = position134, tokenIndex134
+ l177:
+ goto l135
+ l170:
+ position, tokenIndex = position135, tokenIndex135
if buffer[position] != rune('.') {
- goto l178
+ goto l179
}
position++
{
- position179, tokenIndex179 := position, tokenIndex
+ position180, tokenIndex180 := position, tokenIndex
if buffer[position] != rune('t') {
- goto l180
+ goto l181
}
position++
- goto l179
- l180:
- position, tokenIndex = position179, tokenIndex179
+ goto l180
+ l181:
+ position, tokenIndex = position180, tokenIndex180
if buffer[position] != rune('T') {
- goto l178
+ goto l179
}
position++
}
- l179:
+ l180:
{
- position181, tokenIndex181 := position, tokenIndex
+ position182, tokenIndex182 := position, tokenIndex
if buffer[position] != rune('c') {
- goto l182
+ goto l183
}
position++
- goto l181
- l182:
- position, tokenIndex = position181, tokenIndex181
+ goto l182
+ l183:
+ position, tokenIndex = position182, tokenIndex182
if buffer[position] != rune('C') {
- goto l178
+ goto l179
}
position++
}
- l181:
- goto l134
- l178:
- position, tokenIndex = position134, tokenIndex134
+ l182:
+ goto l135
+ l179:
+ position, tokenIndex = position135, tokenIndex135
if buffer[position] != rune('.') {
- goto l183
+ goto l184
}
position++
{
- position184, tokenIndex184 := position, tokenIndex
+ position185, tokenIndex185 := position, tokenIndex
if buffer[position] != rune('l') {
- goto l185
+ goto l186
}
position++
- goto l184
- l185:
- position, tokenIndex = position184, tokenIndex184
+ goto l185
+ l186:
+ position, tokenIndex = position185, tokenIndex185
if buffer[position] != rune('L') {
- goto l183
+ goto l184
}
position++
}
- l184:
+ l185:
{
- position186, tokenIndex186 := position, tokenIndex
+ position187, tokenIndex187 := position, tokenIndex
if buffer[position] != rune('o') {
- goto l187
+ goto l188
}
position++
- goto l186
- l187:
- position, tokenIndex = position186, tokenIndex186
+ goto l187
+ l188:
+ position, tokenIndex = position187, tokenIndex187
if buffer[position] != rune('O') {
- goto l183
+ goto l184
}
position++
}
- l186:
+ l187:
{
- position188, tokenIndex188 := position, tokenIndex
+ position189, tokenIndex189 := position, tokenIndex
if buffer[position] != rune('c') {
- goto l189
+ goto l190
}
position++
- goto l188
- l189:
- position, tokenIndex = position188, tokenIndex188
+ goto l189
+ l190:
+ position, tokenIndex = position189, tokenIndex189
if buffer[position] != rune('C') {
- goto l183
+ goto l184
}
position++
}
- l188:
+ l189:
{
- position190, tokenIndex190 := position, tokenIndex
+ position191, tokenIndex191 := position, tokenIndex
if buffer[position] != rune('a') {
- goto l191
+ goto l192
}
position++
- goto l190
- l191:
- position, tokenIndex = position190, tokenIndex190
+ goto l191
+ l192:
+ position, tokenIndex = position191, tokenIndex191
if buffer[position] != rune('A') {
- goto l183
+ goto l184
}
position++
}
- l190:
+ l191:
{
- position192, tokenIndex192 := position, tokenIndex
+ position193, tokenIndex193 := position, tokenIndex
if buffer[position] != rune('l') {
- goto l193
+ goto l194
}
position++
- goto l192
- l193:
- position, tokenIndex = position192, tokenIndex192
+ goto l193
+ l194:
+ position, tokenIndex = position193, tokenIndex193
if buffer[position] != rune('L') {
- goto l183
+ goto l184
}
position++
}
- l192:
+ l193:
{
- position194, tokenIndex194 := position, tokenIndex
+ position195, tokenIndex195 := position, tokenIndex
if buffer[position] != rune('e') {
- goto l195
+ goto l196
}
position++
- goto l194
- l195:
- position, tokenIndex = position194, tokenIndex194
+ goto l195
+ l196:
+ position, tokenIndex = position195, tokenIndex195
if buffer[position] != rune('E') {
- goto l183
+ goto l184
}
position++
}
- l194:
+ l195:
{
- position196, tokenIndex196 := position, tokenIndex
+ position197, tokenIndex197 := position, tokenIndex
if buffer[position] != rune('n') {
- goto l197
+ goto l198
}
position++
- goto l196
- l197:
- position, tokenIndex = position196, tokenIndex196
+ goto l197
+ l198:
+ position, tokenIndex = position197, tokenIndex197
if buffer[position] != rune('N') {
- goto l183
+ goto l184
}
position++
}
- l196:
+ l197:
{
- position198, tokenIndex198 := position, tokenIndex
+ position199, tokenIndex199 := position, tokenIndex
if buffer[position] != rune('t') {
- goto l199
+ goto l200
}
position++
- goto l198
- l199:
- position, tokenIndex = position198, tokenIndex198
+ goto l199
+ l200:
+ position, tokenIndex = position199, tokenIndex199
if buffer[position] != rune('T') {
- goto l183
+ goto l184
}
position++
}
- l198:
+ l199:
{
- position200, tokenIndex200 := position, tokenIndex
+ position201, tokenIndex201 := position, tokenIndex
if buffer[position] != rune('r') {
- goto l201
+ goto l202
}
position++
- goto l200
- l201:
- position, tokenIndex = position200, tokenIndex200
+ goto l201
+ l202:
+ position, tokenIndex = position201, tokenIndex201
if buffer[position] != rune('R') {
- goto l183
+ goto l184
}
position++
}
- l200:
+ l201:
{
- position202, tokenIndex202 := position, tokenIndex
+ position203, tokenIndex203 := position, tokenIndex
if buffer[position] != rune('y') {
- goto l203
+ goto l204
}
position++
- goto l202
- l203:
- position, tokenIndex = position202, tokenIndex202
+ goto l203
+ l204:
+ position, tokenIndex = position203, tokenIndex203
if buffer[position] != rune('Y') {
- goto l183
+ goto l184
}
position++
}
- l202:
- goto l134
- l183:
- position, tokenIndex = position134, tokenIndex134
+ l203:
+ goto l135
+ l184:
+ position, tokenIndex = position135, tokenIndex135
if buffer[position] != rune('.') {
- goto l204
+ goto l205
}
position++
{
- position205, tokenIndex205 := position, tokenIndex
+ position206, tokenIndex206 := position, tokenIndex
if buffer[position] != rune('s') {
- goto l206
+ goto l207
}
position++
- goto l205
- l206:
- position, tokenIndex = position205, tokenIndex205
+ goto l206
+ l207:
+ position, tokenIndex = position206, tokenIndex206
if buffer[position] != rune('S') {
- goto l204
+ goto l205
}
position++
}
- l205:
+ l206:
{
- position207, tokenIndex207 := position, tokenIndex
+ position208, tokenIndex208 := position, tokenIndex
if buffer[position] != rune('i') {
- goto l208
+ goto l209
}
position++
- goto l207
- l208:
- position, tokenIndex = position207, tokenIndex207
+ goto l208
+ l209:
+ position, tokenIndex = position208, tokenIndex208
if buffer[position] != rune('I') {
- goto l204
+ goto l205
}
position++
}
- l207:
+ l208:
{
- position209, tokenIndex209 := position, tokenIndex
+ position210, tokenIndex210 := position, tokenIndex
if buffer[position] != rune('z') {
- goto l210
+ goto l211
}
position++
- goto l209
- l210:
- position, tokenIndex = position209, tokenIndex209
+ goto l210
+ l211:
+ position, tokenIndex = position210, tokenIndex210
if buffer[position] != rune('Z') {
- goto l204
+ goto l205
}
position++
}
- l209:
+ l210:
{
- position211, tokenIndex211 := position, tokenIndex
+ position212, tokenIndex212 := position, tokenIndex
if buffer[position] != rune('e') {
- goto l212
+ goto l213
}
position++
- goto l211
- l212:
- position, tokenIndex = position211, tokenIndex211
+ goto l212
+ l213:
+ position, tokenIndex = position212, tokenIndex212
if buffer[position] != rune('E') {
- goto l204
+ goto l205
}
position++
}
- l211:
- goto l134
- l204:
- position, tokenIndex = position134, tokenIndex134
+ l212:
+ goto l135
+ l205:
+ position, tokenIndex = position135, tokenIndex135
if buffer[position] != rune('.') {
- goto l132
+ goto l133
}
position++
{
- position213, tokenIndex213 := position, tokenIndex
+ position214, tokenIndex214 := position, tokenIndex
if buffer[position] != rune('t') {
- goto l214
+ goto l215
}
position++
- goto l213
- l214:
- position, tokenIndex = position213, tokenIndex213
+ goto l214
+ l215:
+ position, tokenIndex = position214, tokenIndex214
if buffer[position] != rune('T') {
- goto l132
+ goto l133
}
position++
}
- l213:
+ l214:
{
- position215, tokenIndex215 := position, tokenIndex
+ position216, tokenIndex216 := position, tokenIndex
if buffer[position] != rune('y') {
- goto l216
+ goto l217
}
position++
- goto l215
- l216:
- position, tokenIndex = position215, tokenIndex215
+ goto l216
+ l217:
+ position, tokenIndex = position216, tokenIndex216
if buffer[position] != rune('Y') {
- goto l132
+ goto l133
}
position++
}
- l215:
+ l216:
{
- position217, tokenIndex217 := position, tokenIndex
+ position218, tokenIndex218 := position, tokenIndex
if buffer[position] != rune('p') {
- goto l218
+ goto l219
}
position++
- goto l217
- l218:
- position, tokenIndex = position217, tokenIndex217
+ goto l218
+ l219:
+ position, tokenIndex = position218, tokenIndex218
if buffer[position] != rune('P') {
- goto l132
+ goto l133
}
position++
}
- l217:
+ l218:
{
- position219, tokenIndex219 := position, tokenIndex
+ position220, tokenIndex220 := position, tokenIndex
if buffer[position] != rune('e') {
- goto l220
+ goto l221
}
position++
- goto l219
- l220:
- position, tokenIndex = position219, tokenIndex219
+ goto l220
+ l221:
+ position, tokenIndex = position220, tokenIndex220
if buffer[position] != rune('E') {
- goto l132
+ goto l133
}
position++
}
- l219:
+ l220:
}
- l134:
- add(ruleLabelContainingDirectiveName, position133)
+ l135:
+ add(ruleLabelContainingDirectiveName, position134)
}
return true
- l132:
- position, tokenIndex = position132, tokenIndex132
+ l133:
+ position, tokenIndex = position133, tokenIndex133
return false
},
/* 12 SymbolArgs <- <(SymbolArg (WS? ',' WS? SymbolArg)*)> */
func() bool {
- position221, tokenIndex221 := position, tokenIndex
+ position222, tokenIndex222 := position, tokenIndex
{
- position222 := position
+ position223 := position
if !_rules[ruleSymbolArg]() {
- goto l221
+ goto l222
}
- l223:
+ l224:
{
- position224, tokenIndex224 := position, tokenIndex
+ position225, tokenIndex225 := position, tokenIndex
{
- position225, tokenIndex225 := position, tokenIndex
+ position226, tokenIndex226 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l225
+ goto l226
}
- goto l226
- l225:
- position, tokenIndex = position225, tokenIndex225
+ goto l227
+ l226:
+ position, tokenIndex = position226, tokenIndex226
}
- l226:
+ l227:
if buffer[position] != rune(',') {
- goto l224
+ goto l225
}
position++
{
- position227, tokenIndex227 := position, tokenIndex
+ position228, tokenIndex228 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l227
+ goto l228
}
- goto l228
- l227:
- position, tokenIndex = position227, tokenIndex227
+ goto l229
+ l228:
+ position, tokenIndex = position228, tokenIndex228
}
- l228:
+ l229:
if !_rules[ruleSymbolArg]() {
- goto l224
+ goto l225
}
- goto l223
- l224:
- position, tokenIndex = position224, tokenIndex224
+ goto l224
+ l225:
+ position, tokenIndex = position225, tokenIndex225
}
- add(ruleSymbolArgs, position222)
+ add(ruleSymbolArgs, position223)
}
return true
- l221:
- position, tokenIndex = position221, tokenIndex221
+ l222:
+ position, tokenIndex = position222, tokenIndex222
return false
},
/* 13 SymbolArg <- <(Offset / SymbolType / ((Offset / LocalSymbol / SymbolName / Dot) WS? Operator WS? (Offset / LocalSymbol / SymbolName)) / (LocalSymbol TCMarker?) / (SymbolName Offset) / (SymbolName TCMarker?))> */
func() bool {
- position229, tokenIndex229 := position, tokenIndex
+ position230, tokenIndex230 := position, tokenIndex
{
- position230 := position
+ position231 := position
{
- position231, tokenIndex231 := position, tokenIndex
+ position232, tokenIndex232 := position, tokenIndex
if !_rules[ruleOffset]() {
- goto l232
- }
- goto l231
- l232:
- position, tokenIndex = position231, tokenIndex231
- if !_rules[ruleSymbolType]() {
goto l233
}
- goto l231
+ goto l232
l233:
- position, tokenIndex = position231, tokenIndex231
+ position, tokenIndex = position232, tokenIndex232
+ if !_rules[ruleSymbolType]() {
+ goto l234
+ }
+ goto l232
+ l234:
+ position, tokenIndex = position232, tokenIndex232
{
- position235, tokenIndex235 := position, tokenIndex
+ position236, tokenIndex236 := position, tokenIndex
if !_rules[ruleOffset]() {
- goto l236
- }
- goto l235
- l236:
- position, tokenIndex = position235, tokenIndex235
- if !_rules[ruleLocalSymbol]() {
goto l237
}
- goto l235
+ goto l236
l237:
- position, tokenIndex = position235, tokenIndex235
- if !_rules[ruleSymbolName]() {
+ position, tokenIndex = position236, tokenIndex236
+ if !_rules[ruleLocalSymbol]() {
goto l238
}
- goto l235
+ goto l236
l238:
- position, tokenIndex = position235, tokenIndex235
+ position, tokenIndex = position236, tokenIndex236
+ if !_rules[ruleSymbolName]() {
+ goto l239
+ }
+ goto l236
+ l239:
+ position, tokenIndex = position236, tokenIndex236
if !_rules[ruleDot]() {
- goto l234
+ goto l235
}
}
- l235:
+ l236:
{
- position239, tokenIndex239 := position, tokenIndex
+ position240, tokenIndex240 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l239
+ goto l240
}
- goto l240
- l239:
- position, tokenIndex = position239, tokenIndex239
+ goto l241
+ l240:
+ position, tokenIndex = position240, tokenIndex240
}
- l240:
+ l241:
if !_rules[ruleOperator]() {
- goto l234
+ goto l235
}
{
- position241, tokenIndex241 := position, tokenIndex
+ position242, tokenIndex242 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l241
+ goto l242
}
- goto l242
- l241:
- position, tokenIndex = position241, tokenIndex241
+ goto l243
+ l242:
+ position, tokenIndex = position242, tokenIndex242
}
- l242:
+ l243:
{
- position243, tokenIndex243 := position, tokenIndex
+ position244, tokenIndex244 := position, tokenIndex
if !_rules[ruleOffset]() {
- goto l244
- }
- goto l243
- l244:
- position, tokenIndex = position243, tokenIndex243
- if !_rules[ruleLocalSymbol]() {
goto l245
}
- goto l243
+ goto l244
l245:
- position, tokenIndex = position243, tokenIndex243
+ position, tokenIndex = position244, tokenIndex244
+ if !_rules[ruleLocalSymbol]() {
+ goto l246
+ }
+ goto l244
+ l246:
+ position, tokenIndex = position244, tokenIndex244
if !_rules[ruleSymbolName]() {
- goto l234
+ goto l235
}
}
- l243:
- goto l231
- l234:
- position, tokenIndex = position231, tokenIndex231
+ l244:
+ goto l232
+ l235:
+ position, tokenIndex = position232, tokenIndex232
if !_rules[ruleLocalSymbol]() {
- goto l246
+ goto l247
}
{
- position247, tokenIndex247 := position, tokenIndex
+ position248, tokenIndex248 := position, tokenIndex
if !_rules[ruleTCMarker]() {
- goto l247
+ goto l248
}
- goto l248
- l247:
- position, tokenIndex = position247, tokenIndex247
+ goto l249
+ l248:
+ position, tokenIndex = position248, tokenIndex248
}
- l248:
- goto l231
- l246:
- position, tokenIndex = position231, tokenIndex231
+ l249:
+ goto l232
+ l247:
+ position, tokenIndex = position232, tokenIndex232
if !_rules[ruleSymbolName]() {
- goto l249
+ goto l250
}
if !_rules[ruleOffset]() {
- goto l249
+ goto l250
}
- goto l231
- l249:
- position, tokenIndex = position231, tokenIndex231
+ goto l232
+ l250:
+ position, tokenIndex = position232, tokenIndex232
if !_rules[ruleSymbolName]() {
- goto l229
+ goto l230
}
{
- position250, tokenIndex250 := position, tokenIndex
+ position251, tokenIndex251 := position, tokenIndex
if !_rules[ruleTCMarker]() {
- goto l250
+ goto l251
}
- goto l251
- l250:
- position, tokenIndex = position250, tokenIndex250
+ goto l252
+ l251:
+ position, tokenIndex = position251, tokenIndex251
}
- l251:
+ l252:
}
- l231:
- add(ruleSymbolArg, position230)
+ l232:
+ add(ruleSymbolArg, position231)
}
return true
- l229:
- position, tokenIndex = position229, tokenIndex229
+ l230:
+ position, tokenIndex = position230, tokenIndex230
return false
},
/* 14 SymbolType <- <(('@' 'f' 'u' 'n' 'c' 't' 'i' 'o' 'n') / ('@' 'o' 'b' 'j' 'e' 'c' 't'))> */
func() bool {
- position252, tokenIndex252 := position, tokenIndex
+ position253, tokenIndex253 := position, tokenIndex
{
- position253 := position
+ position254 := position
{
- position254, tokenIndex254 := position, tokenIndex
+ position255, tokenIndex255 := position, tokenIndex
if buffer[position] != rune('@') {
- goto l255
+ goto l256
}
position++
if buffer[position] != rune('f') {
- goto l255
+ goto l256
}
position++
if buffer[position] != rune('u') {
- goto l255
+ goto l256
}
position++
if buffer[position] != rune('n') {
- goto l255
+ goto l256
}
position++
if buffer[position] != rune('c') {
- goto l255
+ goto l256
}
position++
if buffer[position] != rune('t') {
- goto l255
+ goto l256
}
position++
if buffer[position] != rune('i') {
- goto l255
+ goto l256
}
position++
if buffer[position] != rune('o') {
- goto l255
+ goto l256
}
position++
if buffer[position] != rune('n') {
- goto l255
+ goto l256
}
position++
- goto l254
- l255:
- position, tokenIndex = position254, tokenIndex254
+ goto l255
+ l256:
+ position, tokenIndex = position255, tokenIndex255
if buffer[position] != rune('@') {
- goto l252
+ goto l253
}
position++
if buffer[position] != rune('o') {
- goto l252
+ goto l253
}
position++
if buffer[position] != rune('b') {
- goto l252
+ goto l253
}
position++
if buffer[position] != rune('j') {
- goto l252
+ goto l253
}
position++
if buffer[position] != rune('e') {
- goto l252
+ goto l253
}
position++
if buffer[position] != rune('c') {
- goto l252
+ goto l253
}
position++
if buffer[position] != rune('t') {
- goto l252
+ goto l253
}
position++
}
- l254:
- add(ruleSymbolType, position253)
+ l255:
+ add(ruleSymbolType, position254)
}
return true
- l252:
- position, tokenIndex = position252, tokenIndex252
+ l253:
+ position, tokenIndex = position253, tokenIndex253
return false
},
/* 15 Dot <- <'.'> */
func() bool {
- position256, tokenIndex256 := position, tokenIndex
+ position257, tokenIndex257 := position, tokenIndex
{
- position257 := position
+ position258 := position
if buffer[position] != rune('.') {
- goto l256
+ goto l257
}
position++
- add(ruleDot, position257)
+ add(ruleDot, position258)
}
return true
- l256:
- position, tokenIndex = position256, tokenIndex256
+ l257:
+ position, tokenIndex = position257, tokenIndex257
return false
},
/* 16 TCMarker <- <('[' 'T' 'C' ']')> */
func() bool {
- position258, tokenIndex258 := position, tokenIndex
+ position259, tokenIndex259 := position, tokenIndex
{
- position259 := position
+ position260 := position
if buffer[position] != rune('[') {
- goto l258
+ goto l259
}
position++
if buffer[position] != rune('T') {
- goto l258
+ goto l259
}
position++
if buffer[position] != rune('C') {
- goto l258
+ goto l259
}
position++
if buffer[position] != rune(']') {
- goto l258
+ goto l259
}
position++
- add(ruleTCMarker, position259)
+ add(ruleTCMarker, position260)
}
return true
- l258:
- position, tokenIndex = position258, tokenIndex258
+ l259:
+ position, tokenIndex = position259, tokenIndex259
return false
},
/* 17 EscapedChar <- <('\\' .)> */
func() bool {
- position260, tokenIndex260 := position, tokenIndex
+ position261, tokenIndex261 := position, tokenIndex
{
- position261 := position
+ position262 := position
if buffer[position] != rune('\\') {
- goto l260
+ goto l261
}
position++
if !matchDot() {
- goto l260
+ goto l261
}
- add(ruleEscapedChar, position261)
+ add(ruleEscapedChar, position262)
}
return true
- l260:
- position, tokenIndex = position260, tokenIndex260
+ l261:
+ position, tokenIndex = position261, tokenIndex261
return false
},
/* 18 WS <- <(' ' / '\t')+> */
func() bool {
- position262, tokenIndex262 := position, tokenIndex
+ position263, tokenIndex263 := position, tokenIndex
{
- position263 := position
+ position264 := position
{
- position266, tokenIndex266 := position, tokenIndex
+ position267, tokenIndex267 := position, tokenIndex
if buffer[position] != rune(' ') {
- goto l267
+ goto l268
}
position++
- goto l266
- l267:
- position, tokenIndex = position266, tokenIndex266
+ goto l267
+ l268:
+ position, tokenIndex = position267, tokenIndex267
if buffer[position] != rune('\t') {
- goto l262
+ goto l263
}
position++
}
- l266:
- l264:
+ l267:
+ l265:
{
- position265, tokenIndex265 := position, tokenIndex
+ position266, tokenIndex266 := position, tokenIndex
{
- position268, tokenIndex268 := position, tokenIndex
+ position269, tokenIndex269 := position, tokenIndex
if buffer[position] != rune(' ') {
- goto l269
+ goto l270
}
position++
- goto l268
- l269:
- position, tokenIndex = position268, tokenIndex268
+ goto l269
+ l270:
+ position, tokenIndex = position269, tokenIndex269
if buffer[position] != rune('\t') {
- goto l265
+ goto l266
}
position++
}
- l268:
- goto l264
- l265:
- position, tokenIndex = position265, tokenIndex265
+ l269:
+ goto l265
+ l266:
+ position, tokenIndex = position266, tokenIndex266
}
- add(ruleWS, position263)
+ add(ruleWS, position264)
}
return true
- l262:
- position, tokenIndex = position262, tokenIndex262
+ l263:
+ position, tokenIndex = position263, tokenIndex263
return false
},
/* 19 Comment <- <('#' (!'\n' .)*)> */
func() bool {
- position270, tokenIndex270 := position, tokenIndex
+ position271, tokenIndex271 := position, tokenIndex
{
- position271 := position
+ position272 := position
if buffer[position] != rune('#') {
- goto l270
+ goto l271
}
position++
- l272:
+ l273:
{
- position273, tokenIndex273 := position, tokenIndex
+ position274, tokenIndex274 := position, tokenIndex
{
- position274, tokenIndex274 := position, tokenIndex
+ position275, tokenIndex275 := position, tokenIndex
if buffer[position] != rune('\n') {
- goto l274
+ goto l275
}
position++
- goto l273
- l274:
- position, tokenIndex = position274, tokenIndex274
+ goto l274
+ l275:
+ position, tokenIndex = position275, tokenIndex275
}
if !matchDot() {
- goto l273
+ goto l274
}
- goto l272
- l273:
- position, tokenIndex = position273, tokenIndex273
+ goto l273
+ l274:
+ position, tokenIndex = position274, tokenIndex274
}
- add(ruleComment, position271)
+ add(ruleComment, position272)
}
return true
- l270:
- position, tokenIndex = position270, tokenIndex270
+ l271:
+ position, tokenIndex = position271, tokenIndex271
return false
},
/* 20 Label <- <((LocalSymbol / LocalLabel / SymbolName) ':')> */
func() bool {
- position275, tokenIndex275 := position, tokenIndex
+ position276, tokenIndex276 := position, tokenIndex
{
- position276 := position
+ position277 := position
{
- position277, tokenIndex277 := position, tokenIndex
+ position278, tokenIndex278 := position, tokenIndex
if !_rules[ruleLocalSymbol]() {
- goto l278
- }
- goto l277
- l278:
- position, tokenIndex = position277, tokenIndex277
- if !_rules[ruleLocalLabel]() {
goto l279
}
- goto l277
+ goto l278
l279:
- position, tokenIndex = position277, tokenIndex277
+ position, tokenIndex = position278, tokenIndex278
+ if !_rules[ruleLocalLabel]() {
+ goto l280
+ }
+ goto l278
+ l280:
+ position, tokenIndex = position278, tokenIndex278
if !_rules[ruleSymbolName]() {
- goto l275
+ goto l276
}
}
- l277:
+ l278:
if buffer[position] != rune(':') {
- goto l275
+ goto l276
}
position++
- add(ruleLabel, position276)
+ add(ruleLabel, position277)
}
return true
- l275:
- position, tokenIndex = position275, tokenIndex275
+ l276:
+ position, tokenIndex = position276, tokenIndex276
return false
},
/* 21 SymbolName <- <(([a-z] / [A-Z] / '.' / '_') ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')*)> */
func() bool {
- position280, tokenIndex280 := position, tokenIndex
+ position281, tokenIndex281 := position, tokenIndex
{
- position281 := position
+ position282 := position
{
- position282, tokenIndex282 := position, tokenIndex
+ position283, tokenIndex283 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l283
- }
- position++
- goto l282
- l283:
- position, tokenIndex = position282, tokenIndex282
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l284
}
position++
- goto l282
+ goto l283
l284:
- position, tokenIndex = position282, tokenIndex282
- if buffer[position] != rune('.') {
+ position, tokenIndex = position283, tokenIndex283
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l285
}
position++
- goto l282
+ goto l283
l285:
- position, tokenIndex = position282, tokenIndex282
+ position, tokenIndex = position283, tokenIndex283
+ if buffer[position] != rune('.') {
+ goto l286
+ }
+ position++
+ goto l283
+ l286:
+ position, tokenIndex = position283, tokenIndex283
if buffer[position] != rune('_') {
- goto l280
+ goto l281
}
position++
}
- l282:
- l286:
+ l283:
+ l287:
{
- position287, tokenIndex287 := position, tokenIndex
+ position288, tokenIndex288 := position, tokenIndex
{
- position288, tokenIndex288 := position, tokenIndex
+ position289, tokenIndex289 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l289
- }
- position++
- goto l288
- l289:
- position, tokenIndex = position288, tokenIndex288
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l290
}
position++
- goto l288
+ goto l289
l290:
- position, tokenIndex = position288, tokenIndex288
- if buffer[position] != rune('.') {
+ position, tokenIndex = position289, tokenIndex289
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l291
}
position++
- goto l288
+ goto l289
l291:
- position, tokenIndex = position288, tokenIndex288
+ position, tokenIndex = position289, tokenIndex289
+ if buffer[position] != rune('.') {
+ goto l292
+ }
+ position++
+ goto l289
+ l292:
+ position, tokenIndex = position289, tokenIndex289
{
- position293, tokenIndex293 := position, tokenIndex
+ position294, tokenIndex294 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l294
+ goto l295
}
position++
- goto l293
- l294:
- position, tokenIndex = position293, tokenIndex293
+ goto l294
+ l295:
+ position, tokenIndex = position294, tokenIndex294
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l292
+ goto l293
}
position++
}
+ l294:
+ goto l289
l293:
- goto l288
- l292:
- position, tokenIndex = position288, tokenIndex288
+ position, tokenIndex = position289, tokenIndex289
if buffer[position] != rune('$') {
- goto l295
+ goto l296
}
position++
- goto l288
- l295:
- position, tokenIndex = position288, tokenIndex288
+ goto l289
+ l296:
+ position, tokenIndex = position289, tokenIndex289
if buffer[position] != rune('_') {
- goto l287
+ goto l288
}
position++
}
+ l289:
+ goto l287
l288:
- goto l286
- l287:
- position, tokenIndex = position287, tokenIndex287
+ position, tokenIndex = position288, tokenIndex288
}
- add(ruleSymbolName, position281)
+ add(ruleSymbolName, position282)
}
return true
- l280:
- position, tokenIndex = position280, tokenIndex280
+ l281:
+ position, tokenIndex = position281, tokenIndex281
return false
},
/* 22 LocalSymbol <- <('.' 'L' ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')+)> */
func() bool {
- position296, tokenIndex296 := position, tokenIndex
+ position297, tokenIndex297 := position, tokenIndex
{
- position297 := position
+ position298 := position
if buffer[position] != rune('.') {
- goto l296
+ goto l297
}
position++
if buffer[position] != rune('L') {
- goto l296
+ goto l297
}
position++
{
- position300, tokenIndex300 := position, tokenIndex
+ position301, tokenIndex301 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l301
- }
- position++
- goto l300
- l301:
- position, tokenIndex = position300, tokenIndex300
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l302
}
position++
- goto l300
+ goto l301
l302:
- position, tokenIndex = position300, tokenIndex300
- if buffer[position] != rune('.') {
+ position, tokenIndex = position301, tokenIndex301
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l303
}
position++
- goto l300
+ goto l301
l303:
- position, tokenIndex = position300, tokenIndex300
+ position, tokenIndex = position301, tokenIndex301
+ if buffer[position] != rune('.') {
+ goto l304
+ }
+ position++
+ goto l301
+ l304:
+ position, tokenIndex = position301, tokenIndex301
{
- position305, tokenIndex305 := position, tokenIndex
+ position306, tokenIndex306 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l306
+ goto l307
}
position++
- goto l305
- l306:
- position, tokenIndex = position305, tokenIndex305
+ goto l306
+ l307:
+ position, tokenIndex = position306, tokenIndex306
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l304
+ goto l305
}
position++
}
+ l306:
+ goto l301
l305:
- goto l300
- l304:
- position, tokenIndex = position300, tokenIndex300
+ position, tokenIndex = position301, tokenIndex301
if buffer[position] != rune('$') {
- goto l307
+ goto l308
}
position++
- goto l300
- l307:
- position, tokenIndex = position300, tokenIndex300
+ goto l301
+ l308:
+ position, tokenIndex = position301, tokenIndex301
if buffer[position] != rune('_') {
- goto l296
+ goto l297
}
position++
}
- l300:
- l298:
+ l301:
+ l299:
{
- position299, tokenIndex299 := position, tokenIndex
+ position300, tokenIndex300 := position, tokenIndex
{
- position308, tokenIndex308 := position, tokenIndex
+ position309, tokenIndex309 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l309
- }
- position++
- goto l308
- l309:
- position, tokenIndex = position308, tokenIndex308
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l310
}
position++
- goto l308
+ goto l309
l310:
- position, tokenIndex = position308, tokenIndex308
- if buffer[position] != rune('.') {
+ position, tokenIndex = position309, tokenIndex309
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l311
}
position++
- goto l308
+ goto l309
l311:
- position, tokenIndex = position308, tokenIndex308
+ position, tokenIndex = position309, tokenIndex309
+ if buffer[position] != rune('.') {
+ goto l312
+ }
+ position++
+ goto l309
+ l312:
+ position, tokenIndex = position309, tokenIndex309
{
- position313, tokenIndex313 := position, tokenIndex
+ position314, tokenIndex314 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l314
+ goto l315
}
position++
- goto l313
- l314:
- position, tokenIndex = position313, tokenIndex313
+ goto l314
+ l315:
+ position, tokenIndex = position314, tokenIndex314
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l312
+ goto l313
}
position++
}
+ l314:
+ goto l309
l313:
- goto l308
- l312:
- position, tokenIndex = position308, tokenIndex308
+ position, tokenIndex = position309, tokenIndex309
if buffer[position] != rune('$') {
- goto l315
+ goto l316
}
position++
- goto l308
- l315:
- position, tokenIndex = position308, tokenIndex308
+ goto l309
+ l316:
+ position, tokenIndex = position309, tokenIndex309
if buffer[position] != rune('_') {
- goto l299
+ goto l300
}
position++
}
- l308:
- goto l298
- l299:
- position, tokenIndex = position299, tokenIndex299
+ l309:
+ goto l299
+ l300:
+ position, tokenIndex = position300, tokenIndex300
}
- add(ruleLocalSymbol, position297)
+ add(ruleLocalSymbol, position298)
}
return true
- l296:
- position, tokenIndex = position296, tokenIndex296
+ l297:
+ position, tokenIndex = position297, tokenIndex297
return false
},
/* 23 LocalLabel <- <([0-9] ([0-9] / '$')*)> */
func() bool {
- position316, tokenIndex316 := position, tokenIndex
+ position317, tokenIndex317 := position, tokenIndex
{
- position317 := position
+ position318 := position
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l316
+ goto l317
}
position++
- l318:
+ l319:
{
- position319, tokenIndex319 := position, tokenIndex
+ position320, tokenIndex320 := position, tokenIndex
{
- position320, tokenIndex320 := position, tokenIndex
+ position321, tokenIndex321 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l321
+ goto l322
}
position++
- goto l320
- l321:
- position, tokenIndex = position320, tokenIndex320
+ goto l321
+ l322:
+ position, tokenIndex = position321, tokenIndex321
if buffer[position] != rune('$') {
- goto l319
+ goto l320
}
position++
}
+ l321:
+ goto l319
l320:
- goto l318
- l319:
- position, tokenIndex = position319, tokenIndex319
+ position, tokenIndex = position320, tokenIndex320
}
- add(ruleLocalLabel, position317)
+ add(ruleLocalLabel, position318)
}
return true
- l316:
- position, tokenIndex = position316, tokenIndex316
+ l317:
+ position, tokenIndex = position317, tokenIndex317
return false
},
/* 24 LocalLabelRef <- <([0-9] ([0-9] / '$')* ('b' / 'f'))> */
func() bool {
- position322, tokenIndex322 := position, tokenIndex
+ position323, tokenIndex323 := position, tokenIndex
{
- position323 := position
+ position324 := position
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l322
+ goto l323
}
position++
- l324:
+ l325:
{
- position325, tokenIndex325 := position, tokenIndex
+ position326, tokenIndex326 := position, tokenIndex
{
- position326, tokenIndex326 := position, tokenIndex
+ position327, tokenIndex327 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l327
+ goto l328
}
position++
- goto l326
- l327:
- position, tokenIndex = position326, tokenIndex326
+ goto l327
+ l328:
+ position, tokenIndex = position327, tokenIndex327
if buffer[position] != rune('$') {
- goto l325
+ goto l326
}
position++
}
+ l327:
+ goto l325
l326:
- goto l324
- l325:
- position, tokenIndex = position325, tokenIndex325
+ position, tokenIndex = position326, tokenIndex326
}
{
- position328, tokenIndex328 := position, tokenIndex
+ position329, tokenIndex329 := position, tokenIndex
if buffer[position] != rune('b') {
- goto l329
+ goto l330
}
position++
- goto l328
- l329:
- position, tokenIndex = position328, tokenIndex328
+ goto l329
+ l330:
+ position, tokenIndex = position329, tokenIndex329
if buffer[position] != rune('f') {
- goto l322
+ goto l323
}
position++
}
- l328:
- add(ruleLocalLabelRef, position323)
+ l329:
+ add(ruleLocalLabelRef, position324)
}
return true
- l322:
- position, tokenIndex = position322, tokenIndex322
+ l323:
+ position, tokenIndex = position323, tokenIndex323
return false
},
/* 25 Instruction <- <(InstructionName (WS InstructionArg (WS? ',' WS? InstructionArg)*)? (WS? '{' InstructionArg '}')*)> */
func() bool {
- position330, tokenIndex330 := position, tokenIndex
+ position331, tokenIndex331 := position, tokenIndex
{
- position331 := position
+ position332 := position
if !_rules[ruleInstructionName]() {
- goto l330
+ goto l331
}
{
- position332, tokenIndex332 := position, tokenIndex
+ position333, tokenIndex333 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l332
+ goto l333
}
if !_rules[ruleInstructionArg]() {
- goto l332
+ goto l333
}
- l334:
+ l335:
{
- position335, tokenIndex335 := position, tokenIndex
+ position336, tokenIndex336 := position, tokenIndex
{
- position336, tokenIndex336 := position, tokenIndex
+ position337, tokenIndex337 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l336
+ goto l337
}
- goto l337
- l336:
- position, tokenIndex = position336, tokenIndex336
+ goto l338
+ l337:
+ position, tokenIndex = position337, tokenIndex337
}
- l337:
+ l338:
if buffer[position] != rune(',') {
- goto l335
+ goto l336
}
position++
{
- position338, tokenIndex338 := position, tokenIndex
+ position339, tokenIndex339 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l338
+ goto l339
}
- goto l339
- l338:
- position, tokenIndex = position338, tokenIndex338
+ goto l340
+ l339:
+ position, tokenIndex = position339, tokenIndex339
}
- l339:
+ l340:
if !_rules[ruleInstructionArg]() {
- goto l335
+ goto l336
}
- goto l334
- l335:
- position, tokenIndex = position335, tokenIndex335
+ goto l335
+ l336:
+ position, tokenIndex = position336, tokenIndex336
}
- goto l333
- l332:
- position, tokenIndex = position332, tokenIndex332
+ goto l334
+ l333:
+ position, tokenIndex = position333, tokenIndex333
}
- l333:
- l340:
+ l334:
+ l341:
{
- position341, tokenIndex341 := position, tokenIndex
+ position342, tokenIndex342 := position, tokenIndex
{
- position342, tokenIndex342 := position, tokenIndex
+ position343, tokenIndex343 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l342
+ goto l343
}
- goto l343
- l342:
- position, tokenIndex = position342, tokenIndex342
+ goto l344
+ l343:
+ position, tokenIndex = position343, tokenIndex343
}
- l343:
+ l344:
if buffer[position] != rune('{') {
- goto l341
+ goto l342
}
position++
if !_rules[ruleInstructionArg]() {
- goto l341
+ goto l342
}
if buffer[position] != rune('}') {
- goto l341
+ goto l342
}
position++
- goto l340
- l341:
- position, tokenIndex = position341, tokenIndex341
+ goto l341
+ l342:
+ position, tokenIndex = position342, tokenIndex342
}
- add(ruleInstruction, position331)
+ add(ruleInstruction, position332)
}
return true
- l330:
- position, tokenIndex = position330, tokenIndex330
+ l331:
+ position, tokenIndex = position331, tokenIndex331
return false
},
/* 26 InstructionName <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))* ('.' / '+' / '-')?)> */
func() bool {
- position344, tokenIndex344 := position, tokenIndex
+ position345, tokenIndex345 := position, tokenIndex
{
- position345 := position
+ position346 := position
{
- position346, tokenIndex346 := position, tokenIndex
+ position347, tokenIndex347 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l347
+ goto l348
}
position++
- goto l346
- l347:
- position, tokenIndex = position346, tokenIndex346
+ goto l347
+ l348:
+ position, tokenIndex = position347, tokenIndex347
if c := buffer[position]; c < rune('A') || c > rune('Z') {
- goto l344
+ goto l345
}
position++
}
- l346:
- l348:
+ l347:
+ l349:
{
- position349, tokenIndex349 := position, tokenIndex
+ position350, tokenIndex350 := position, tokenIndex
{
- position350, tokenIndex350 := position, tokenIndex
+ position351, tokenIndex351 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l351
+ goto l352
}
position++
- goto l350
- l351:
- position, tokenIndex = position350, tokenIndex350
+ goto l351
+ l352:
+ position, tokenIndex = position351, tokenIndex351
if c := buffer[position]; c < rune('A') || c > rune('Z') {
- goto l352
+ goto l353
}
position++
- goto l350
- l352:
- position, tokenIndex = position350, tokenIndex350
+ goto l351
+ l353:
+ position, tokenIndex = position351, tokenIndex351
{
- position353, tokenIndex353 := position, tokenIndex
+ position354, tokenIndex354 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l354
+ goto l355
}
position++
- goto l353
- l354:
- position, tokenIndex = position353, tokenIndex353
+ goto l354
+ l355:
+ position, tokenIndex = position354, tokenIndex354
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l349
+ goto l350
}
position++
}
- l353:
+ l354:
}
+ l351:
+ goto l349
l350:
- goto l348
- l349:
- position, tokenIndex = position349, tokenIndex349
+ position, tokenIndex = position350, tokenIndex350
}
{
- position355, tokenIndex355 := position, tokenIndex
+ position356, tokenIndex356 := position, tokenIndex
{
- position357, tokenIndex357 := position, tokenIndex
+ position358, tokenIndex358 := position, tokenIndex
if buffer[position] != rune('.') {
- goto l358
+ goto l359
}
position++
- goto l357
- l358:
- position, tokenIndex = position357, tokenIndex357
+ goto l358
+ l359:
+ position, tokenIndex = position358, tokenIndex358
if buffer[position] != rune('+') {
- goto l359
+ goto l360
}
position++
- goto l357
- l359:
- position, tokenIndex = position357, tokenIndex357
+ goto l358
+ l360:
+ position, tokenIndex = position358, tokenIndex358
if buffer[position] != rune('-') {
- goto l355
+ goto l356
}
position++
}
- l357:
- goto l356
- l355:
- position, tokenIndex = position355, tokenIndex355
+ l358:
+ goto l357
+ l356:
+ position, tokenIndex = position356, tokenIndex356
}
- l356:
- add(ruleInstructionName, position345)
+ l357:
+ add(ruleInstructionName, position346)
}
return true
- l344:
- position, tokenIndex = position344, tokenIndex344
+ l345:
+ position, tokenIndex = position345, tokenIndex345
return false
},
/* 27 InstructionArg <- <(IndirectionIndicator? (RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / MemoryRef))> */
func() bool {
- position360, tokenIndex360 := position, tokenIndex
+ position361, tokenIndex361 := position, tokenIndex
{
- position361 := position
+ position362 := position
{
- position362, tokenIndex362 := position, tokenIndex
+ position363, tokenIndex363 := position, tokenIndex
if !_rules[ruleIndirectionIndicator]() {
- goto l362
+ goto l363
}
- goto l363
- l362:
- position, tokenIndex = position362, tokenIndex362
+ goto l364
+ l363:
+ position, tokenIndex = position363, tokenIndex363
}
- l363:
+ l364:
{
- position364, tokenIndex364 := position, tokenIndex
+ position365, tokenIndex365 := position, tokenIndex
if !_rules[ruleRegisterOrConstant]() {
- goto l365
- }
- goto l364
- l365:
- position, tokenIndex = position364, tokenIndex364
- if !_rules[ruleLocalLabelRef]() {
goto l366
}
- goto l364
+ goto l365
l366:
- position, tokenIndex = position364, tokenIndex364
- if !_rules[ruleTOCRefHigh]() {
+ position, tokenIndex = position365, tokenIndex365
+ if !_rules[ruleLocalLabelRef]() {
goto l367
}
- goto l364
+ goto l365
l367:
- position, tokenIndex = position364, tokenIndex364
- if !_rules[ruleTOCRefLow]() {
+ position, tokenIndex = position365, tokenIndex365
+ if !_rules[ruleTOCRefHigh]() {
goto l368
}
- goto l364
+ goto l365
l368:
- position, tokenIndex = position364, tokenIndex364
+ position, tokenIndex = position365, tokenIndex365
+ if !_rules[ruleTOCRefLow]() {
+ goto l369
+ }
+ goto l365
+ l369:
+ position, tokenIndex = position365, tokenIndex365
if !_rules[ruleMemoryRef]() {
- goto l360
+ goto l361
}
}
- l364:
- add(ruleInstructionArg, position361)
+ l365:
+ add(ruleInstructionArg, position362)
}
return true
- l360:
- position, tokenIndex = position360, tokenIndex360
+ l361:
+ position, tokenIndex = position361, tokenIndex361
return false
},
/* 28 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */
func() bool {
- position369, tokenIndex369 := position, tokenIndex
+ position370, tokenIndex370 := position, tokenIndex
{
- position370 := position
+ position371 := position
if buffer[position] != rune('.') {
- goto l369
+ goto l370
}
position++
if buffer[position] != rune('T') {
- goto l369
+ goto l370
}
position++
if buffer[position] != rune('O') {
- goto l369
+ goto l370
}
position++
if buffer[position] != rune('C') {
- goto l369
+ goto l370
}
position++
if buffer[position] != rune('.') {
- goto l369
+ goto l370
}
position++
if buffer[position] != rune('-') {
- goto l369
+ goto l370
}
position++
{
- position371, tokenIndex371 := position, tokenIndex
+ position372, tokenIndex372 := position, tokenIndex
if buffer[position] != rune('0') {
- goto l372
+ goto l373
}
position++
if buffer[position] != rune('b') {
- goto l372
+ goto l373
}
position++
- goto l371
- l372:
- position, tokenIndex = position371, tokenIndex371
+ goto l372
+ l373:
+ position, tokenIndex = position372, tokenIndex372
if buffer[position] != rune('.') {
- goto l369
+ goto l370
}
position++
if buffer[position] != rune('L') {
- goto l369
+ goto l370
}
position++
{
- position375, tokenIndex375 := position, tokenIndex
+ position376, tokenIndex376 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l376
- }
- position++
- goto l375
- l376:
- position, tokenIndex = position375, tokenIndex375
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l377
}
position++
- goto l375
+ goto l376
l377:
- position, tokenIndex = position375, tokenIndex375
- if buffer[position] != rune('_') {
+ position, tokenIndex = position376, tokenIndex376
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l378
}
position++
- goto l375
+ goto l376
l378:
- position, tokenIndex = position375, tokenIndex375
+ position, tokenIndex = position376, tokenIndex376
+ if buffer[position] != rune('_') {
+ goto l379
+ }
+ position++
+ goto l376
+ l379:
+ position, tokenIndex = position376, tokenIndex376
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l369
+ goto l370
}
position++
}
- l375:
- l373:
+ l376:
+ l374:
{
- position374, tokenIndex374 := position, tokenIndex
+ position375, tokenIndex375 := position, tokenIndex
{
- position379, tokenIndex379 := position, tokenIndex
+ position380, tokenIndex380 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l380
- }
- position++
- goto l379
- l380:
- position, tokenIndex = position379, tokenIndex379
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l381
}
position++
- goto l379
+ goto l380
l381:
- position, tokenIndex = position379, tokenIndex379
- if buffer[position] != rune('_') {
+ position, tokenIndex = position380, tokenIndex380
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l382
}
position++
- goto l379
+ goto l380
l382:
- position, tokenIndex = position379, tokenIndex379
+ position, tokenIndex = position380, tokenIndex380
+ if buffer[position] != rune('_') {
+ goto l383
+ }
+ position++
+ goto l380
+ l383:
+ position, tokenIndex = position380, tokenIndex380
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l374
+ goto l375
}
position++
}
- l379:
- goto l373
- l374:
- position, tokenIndex = position374, tokenIndex374
+ l380:
+ goto l374
+ l375:
+ position, tokenIndex = position375, tokenIndex375
}
}
- l371:
+ l372:
if buffer[position] != rune('@') {
- goto l369
+ goto l370
}
position++
{
- position383, tokenIndex383 := position, tokenIndex
+ position384, tokenIndex384 := position, tokenIndex
if buffer[position] != rune('h') {
- goto l384
+ goto l385
}
position++
- goto l383
- l384:
- position, tokenIndex = position383, tokenIndex383
+ goto l384
+ l385:
+ position, tokenIndex = position384, tokenIndex384
if buffer[position] != rune('H') {
- goto l369
+ goto l370
}
position++
}
- l383:
+ l384:
{
- position385, tokenIndex385 := position, tokenIndex
+ position386, tokenIndex386 := position, tokenIndex
if buffer[position] != rune('a') {
- goto l386
+ goto l387
}
position++
- goto l385
- l386:
- position, tokenIndex = position385, tokenIndex385
+ goto l386
+ l387:
+ position, tokenIndex = position386, tokenIndex386
if buffer[position] != rune('A') {
- goto l369
+ goto l370
}
position++
}
- l385:
- add(ruleTOCRefHigh, position370)
+ l386:
+ add(ruleTOCRefHigh, position371)
}
return true
- l369:
- position, tokenIndex = position369, tokenIndex369
+ l370:
+ position, tokenIndex = position370, tokenIndex370
return false
},
/* 29 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */
func() bool {
- position387, tokenIndex387 := position, tokenIndex
+ position388, tokenIndex388 := position, tokenIndex
{
- position388 := position
+ position389 := position
if buffer[position] != rune('.') {
- goto l387
+ goto l388
}
position++
if buffer[position] != rune('T') {
- goto l387
+ goto l388
}
position++
if buffer[position] != rune('O') {
- goto l387
+ goto l388
}
position++
if buffer[position] != rune('C') {
- goto l387
+ goto l388
}
position++
if buffer[position] != rune('.') {
- goto l387
+ goto l388
}
position++
if buffer[position] != rune('-') {
- goto l387
+ goto l388
}
position++
{
- position389, tokenIndex389 := position, tokenIndex
+ position390, tokenIndex390 := position, tokenIndex
if buffer[position] != rune('0') {
- goto l390
+ goto l391
}
position++
if buffer[position] != rune('b') {
- goto l390
+ goto l391
}
position++
- goto l389
- l390:
- position, tokenIndex = position389, tokenIndex389
+ goto l390
+ l391:
+ position, tokenIndex = position390, tokenIndex390
if buffer[position] != rune('.') {
- goto l387
+ goto l388
}
position++
if buffer[position] != rune('L') {
- goto l387
+ goto l388
}
position++
{
- position393, tokenIndex393 := position, tokenIndex
+ position394, tokenIndex394 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l394
- }
- position++
- goto l393
- l394:
- position, tokenIndex = position393, tokenIndex393
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l395
}
position++
- goto l393
+ goto l394
l395:
- position, tokenIndex = position393, tokenIndex393
- if buffer[position] != rune('_') {
+ position, tokenIndex = position394, tokenIndex394
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l396
}
position++
- goto l393
+ goto l394
l396:
- position, tokenIndex = position393, tokenIndex393
+ position, tokenIndex = position394, tokenIndex394
+ if buffer[position] != rune('_') {
+ goto l397
+ }
+ position++
+ goto l394
+ l397:
+ position, tokenIndex = position394, tokenIndex394
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l387
+ goto l388
}
position++
}
- l393:
- l391:
+ l394:
+ l392:
{
- position392, tokenIndex392 := position, tokenIndex
+ position393, tokenIndex393 := position, tokenIndex
{
- position397, tokenIndex397 := position, tokenIndex
+ position398, tokenIndex398 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l398
- }
- position++
- goto l397
- l398:
- position, tokenIndex = position397, tokenIndex397
- if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l399
}
position++
- goto l397
+ goto l398
l399:
- position, tokenIndex = position397, tokenIndex397
- if buffer[position] != rune('_') {
+ position, tokenIndex = position398, tokenIndex398
+ if c := buffer[position]; c < rune('A') || c > rune('Z') {
goto l400
}
position++
- goto l397
+ goto l398
l400:
- position, tokenIndex = position397, tokenIndex397
+ position, tokenIndex = position398, tokenIndex398
+ if buffer[position] != rune('_') {
+ goto l401
+ }
+ position++
+ goto l398
+ l401:
+ position, tokenIndex = position398, tokenIndex398
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l392
+ goto l393
}
position++
}
- l397:
- goto l391
- l392:
- position, tokenIndex = position392, tokenIndex392
+ l398:
+ goto l392
+ l393:
+ position, tokenIndex = position393, tokenIndex393
}
}
- l389:
+ l390:
if buffer[position] != rune('@') {
- goto l387
+ goto l388
}
position++
{
- position401, tokenIndex401 := position, tokenIndex
+ position402, tokenIndex402 := position, tokenIndex
if buffer[position] != rune('l') {
- goto l402
+ goto l403
}
position++
- goto l401
- l402:
- position, tokenIndex = position401, tokenIndex401
+ goto l402
+ l403:
+ position, tokenIndex = position402, tokenIndex402
if buffer[position] != rune('L') {
- goto l387
+ goto l388
}
position++
}
- l401:
- add(ruleTOCRefLow, position388)
+ l402:
+ add(ruleTOCRefLow, position389)
}
return true
- l387:
- position, tokenIndex = position387, tokenIndex387
+ l388:
+ position, tokenIndex = position388, tokenIndex388
return false
},
/* 30 IndirectionIndicator <- <'*'> */
func() bool {
- position403, tokenIndex403 := position, tokenIndex
+ position404, tokenIndex404 := position, tokenIndex
{
- position404 := position
+ position405 := position
if buffer[position] != rune('*') {
- goto l403
+ goto l404
}
position++
- add(ruleIndirectionIndicator, position404)
+ add(ruleIndirectionIndicator, position405)
}
return true
- l403:
- position, tokenIndex = position403, tokenIndex403
+ l404:
+ position, tokenIndex = position404, tokenIndex404
return false
},
/* 31 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset))) !('f' / 'b' / ':' / '(' / '+' / '-'))> */
func() bool {
- position405, tokenIndex405 := position, tokenIndex
+ position406, tokenIndex406 := position, tokenIndex
{
- position406 := position
+ position407 := position
{
- position407, tokenIndex407 := position, tokenIndex
+ position408, tokenIndex408 := position, tokenIndex
if buffer[position] != rune('%') {
- goto l408
+ goto l409
}
position++
{
- position409, tokenIndex409 := position, tokenIndex
+ position410, tokenIndex410 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l410
+ goto l411
}
position++
- goto l409
- l410:
- position, tokenIndex = position409, tokenIndex409
+ goto l410
+ l411:
+ position, tokenIndex = position410, tokenIndex410
if c := buffer[position]; c < rune('A') || c > rune('Z') {
- goto l408
+ goto l409
}
position++
}
- l409:
- l411:
+ l410:
+ l412:
{
- position412, tokenIndex412 := position, tokenIndex
+ position413, tokenIndex413 := position, tokenIndex
{
- position413, tokenIndex413 := position, tokenIndex
+ position414, tokenIndex414 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l414
+ goto l415
}
position++
- goto l413
- l414:
- position, tokenIndex = position413, tokenIndex413
+ goto l414
+ l415:
+ position, tokenIndex = position414, tokenIndex414
if c := buffer[position]; c < rune('A') || c > rune('Z') {
- goto l415
+ goto l416
}
position++
- goto l413
- l415:
- position, tokenIndex = position413, tokenIndex413
+ goto l414
+ l416:
+ position, tokenIndex = position414, tokenIndex414
{
- position416, tokenIndex416 := position, tokenIndex
+ position417, tokenIndex417 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l417
+ goto l418
}
position++
- goto l416
- l417:
- position, tokenIndex = position416, tokenIndex416
+ goto l417
+ l418:
+ position, tokenIndex = position417, tokenIndex417
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l412
+ goto l413
}
position++
}
- l416:
+ l417:
}
+ l414:
+ goto l412
l413:
- goto l411
- l412:
- position, tokenIndex = position412, tokenIndex412
+ position, tokenIndex = position413, tokenIndex413
}
- goto l407
- l408:
- position, tokenIndex = position407, tokenIndex407
+ goto l408
+ l409:
+ position, tokenIndex = position408, tokenIndex408
{
- position418, tokenIndex418 := position, tokenIndex
+ position419, tokenIndex419 := position, tokenIndex
if buffer[position] != rune('$') {
- goto l418
+ goto l419
}
position++
- goto l419
- l418:
- position, tokenIndex = position418, tokenIndex418
+ goto l420
+ l419:
+ position, tokenIndex = position419, tokenIndex419
}
- l419:
+ l420:
{
- position420, tokenIndex420 := position, tokenIndex
+ position421, tokenIndex421 := position, tokenIndex
if !_rules[ruleOffset]() {
- goto l421
+ goto l422
}
if !_rules[ruleOffset]() {
- goto l421
+ goto l422
}
- goto l420
- l421:
- position, tokenIndex = position420, tokenIndex420
+ goto l421
+ l422:
+ position, tokenIndex = position421, tokenIndex421
if !_rules[ruleOffset]() {
- goto l405
+ goto l406
}
}
- l420:
+ l421:
}
- l407:
+ l408:
{
- position422, tokenIndex422 := position, tokenIndex
+ position423, tokenIndex423 := position, tokenIndex
{
- position423, tokenIndex423 := position, tokenIndex
+ position424, tokenIndex424 := position, tokenIndex
if buffer[position] != rune('f') {
- goto l424
- }
- position++
- goto l423
- l424:
- position, tokenIndex = position423, tokenIndex423
- if buffer[position] != rune('b') {
goto l425
}
position++
- goto l423
+ goto l424
l425:
- position, tokenIndex = position423, tokenIndex423
- if buffer[position] != rune(':') {
+ position, tokenIndex = position424, tokenIndex424
+ if buffer[position] != rune('b') {
goto l426
}
position++
- goto l423
+ goto l424
l426:
- position, tokenIndex = position423, tokenIndex423
- if buffer[position] != rune('(') {
+ position, tokenIndex = position424, tokenIndex424
+ if buffer[position] != rune(':') {
goto l427
}
position++
- goto l423
+ goto l424
l427:
- position, tokenIndex = position423, tokenIndex423
- if buffer[position] != rune('+') {
+ position, tokenIndex = position424, tokenIndex424
+ if buffer[position] != rune('(') {
goto l428
}
position++
- goto l423
+ goto l424
l428:
- position, tokenIndex = position423, tokenIndex423
+ position, tokenIndex = position424, tokenIndex424
+ if buffer[position] != rune('+') {
+ goto l429
+ }
+ position++
+ goto l424
+ l429:
+ position, tokenIndex = position424, tokenIndex424
if buffer[position] != rune('-') {
- goto l422
+ goto l423
}
position++
}
+ l424:
+ goto l406
l423:
- goto l405
- l422:
- position, tokenIndex = position422, tokenIndex422
+ position, tokenIndex = position423, tokenIndex423
}
- add(ruleRegisterOrConstant, position406)
+ add(ruleRegisterOrConstant, position407)
}
return true
- l405:
- position, tokenIndex = position405, tokenIndex405
+ l406:
+ position, tokenIndex = position406, tokenIndex406
return false
},
/* 32 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / BaseIndexScale)> */
func() bool {
- position429, tokenIndex429 := position, tokenIndex
+ position430, tokenIndex430 := position, tokenIndex
{
- position430 := position
+ position431 := position
{
- position431, tokenIndex431 := position, tokenIndex
+ position432, tokenIndex432 := position, tokenIndex
if !_rules[ruleSymbolRef]() {
- goto l432
+ goto l433
}
if !_rules[ruleBaseIndexScale]() {
- goto l432
- }
- goto l431
- l432:
- position, tokenIndex = position431, tokenIndex431
- if !_rules[ruleSymbolRef]() {
goto l433
}
- goto l431
+ goto l432
l433:
- position, tokenIndex = position431, tokenIndex431
- l435:
+ position, tokenIndex = position432, tokenIndex432
+ if !_rules[ruleSymbolRef]() {
+ goto l434
+ }
+ goto l432
+ l434:
+ position, tokenIndex = position432, tokenIndex432
+ l436:
{
- position436, tokenIndex436 := position, tokenIndex
+ position437, tokenIndex437 := position, tokenIndex
if !_rules[ruleOffset]() {
- goto l436
+ goto l437
}
- goto l435
- l436:
- position, tokenIndex = position436, tokenIndex436
+ goto l436
+ l437:
+ position, tokenIndex = position437, tokenIndex437
}
if !_rules[ruleBaseIndexScale]() {
- goto l434
+ goto l435
}
- goto l431
- l434:
- position, tokenIndex = position431, tokenIndex431
+ goto l432
+ l435:
+ position, tokenIndex = position432, tokenIndex432
if !_rules[ruleSegmentRegister]() {
- goto l437
+ goto l438
}
if !_rules[ruleOffset]() {
- goto l437
- }
- if !_rules[ruleBaseIndexScale]() {
- goto l437
- }
- goto l431
- l437:
- position, tokenIndex = position431, tokenIndex431
- if !_rules[ruleSegmentRegister]() {
goto l438
}
if !_rules[ruleBaseIndexScale]() {
goto l438
}
- goto l431
+ goto l432
l438:
- position, tokenIndex = position431, tokenIndex431
+ position, tokenIndex = position432, tokenIndex432
if !_rules[ruleSegmentRegister]() {
goto l439
}
- if !_rules[ruleOffset]() {
+ if !_rules[ruleBaseIndexScale]() {
goto l439
}
- goto l431
+ goto l432
l439:
- position, tokenIndex = position431, tokenIndex431
+ position, tokenIndex = position432, tokenIndex432
+ if !_rules[ruleSegmentRegister]() {
+ goto l440
+ }
+ if !_rules[ruleOffset]() {
+ goto l440
+ }
+ goto l432
+ l440:
+ position, tokenIndex = position432, tokenIndex432
if !_rules[ruleBaseIndexScale]() {
- goto l429
+ goto l430
}
}
- l431:
- add(ruleMemoryRef, position430)
+ l432:
+ add(ruleMemoryRef, position431)
}
return true
- l429:
- position, tokenIndex = position429, tokenIndex429
+ l430:
+ position, tokenIndex = position430, tokenIndex430
return false
},
/* 33 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */
func() bool {
- position440, tokenIndex440 := position, tokenIndex
+ position441, tokenIndex441 := position, tokenIndex
{
- position441 := position
+ position442 := position
{
- position442, tokenIndex442 := position, tokenIndex
- l444:
+ position443, tokenIndex443 := position, tokenIndex
+ l445:
{
- position445, tokenIndex445 := position, tokenIndex
+ position446, tokenIndex446 := position, tokenIndex
if !_rules[ruleOffset]() {
- goto l445
+ goto l446
}
- goto l444
- l445:
- position, tokenIndex = position445, tokenIndex445
+ goto l445
+ l446:
+ position, tokenIndex = position446, tokenIndex446
}
if buffer[position] != rune('+') {
- goto l442
+ goto l443
}
position++
- goto l443
- l442:
- position, tokenIndex = position442, tokenIndex442
+ goto l444
+ l443:
+ position, tokenIndex = position443, tokenIndex443
}
- l443:
+ l444:
{
- position446, tokenIndex446 := position, tokenIndex
+ position447, tokenIndex447 := position, tokenIndex
if !_rules[ruleLocalSymbol]() {
- goto l447
+ goto l448
}
- goto l446
- l447:
- position, tokenIndex = position446, tokenIndex446
+ goto l447
+ l448:
+ position, tokenIndex = position447, tokenIndex447
if !_rules[ruleSymbolName]() {
- goto l440
+ goto l441
}
}
- l446:
- l448:
+ l447:
+ l449:
{
- position449, tokenIndex449 := position, tokenIndex
+ position450, tokenIndex450 := position, tokenIndex
if !_rules[ruleOffset]() {
- goto l449
+ goto l450
}
- goto l448
- l449:
- position, tokenIndex = position449, tokenIndex449
+ goto l449
+ l450:
+ position, tokenIndex = position450, tokenIndex450
}
{
- position450, tokenIndex450 := position, tokenIndex
+ position451, tokenIndex451 := position, tokenIndex
if buffer[position] != rune('@') {
- goto l450
+ goto l451
}
position++
if !_rules[ruleSection]() {
- goto l450
+ goto l451
}
- l452:
+ l453:
{
- position453, tokenIndex453 := position, tokenIndex
+ position454, tokenIndex454 := position, tokenIndex
if !_rules[ruleOffset]() {
- goto l453
+ goto l454
}
- goto l452
- l453:
- position, tokenIndex = position453, tokenIndex453
+ goto l453
+ l454:
+ position, tokenIndex = position454, tokenIndex454
}
- goto l451
- l450:
- position, tokenIndex = position450, tokenIndex450
+ goto l452
+ l451:
+ position, tokenIndex = position451, tokenIndex451
}
- l451:
- add(ruleSymbolRef, position441)
+ l452:
+ add(ruleSymbolRef, position442)
}
return true
- l440:
- position, tokenIndex = position440, tokenIndex440
+ l441:
+ position, tokenIndex = position441, tokenIndex441
return false
},
/* 34 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */
func() bool {
- position454, tokenIndex454 := position, tokenIndex
+ position455, tokenIndex455 := position, tokenIndex
{
- position455 := position
+ position456 := position
if buffer[position] != rune('(') {
- goto l454
+ goto l455
}
position++
{
- position456, tokenIndex456 := position, tokenIndex
+ position457, tokenIndex457 := position, tokenIndex
if !_rules[ruleRegisterOrConstant]() {
- goto l456
+ goto l457
}
- goto l457
- l456:
- position, tokenIndex = position456, tokenIndex456
+ goto l458
+ l457:
+ position, tokenIndex = position457, tokenIndex457
}
- l457:
+ l458:
{
- position458, tokenIndex458 := position, tokenIndex
+ position459, tokenIndex459 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l458
+ goto l459
}
- goto l459
- l458:
- position, tokenIndex = position458, tokenIndex458
+ goto l460
+ l459:
+ position, tokenIndex = position459, tokenIndex459
}
- l459:
+ l460:
{
- position460, tokenIndex460 := position, tokenIndex
+ position461, tokenIndex461 := position, tokenIndex
if buffer[position] != rune(',') {
- goto l460
+ goto l461
}
position++
{
- position462, tokenIndex462 := position, tokenIndex
+ position463, tokenIndex463 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l462
+ goto l463
}
- goto l463
- l462:
- position, tokenIndex = position462, tokenIndex462
+ goto l464
+ l463:
+ position, tokenIndex = position463, tokenIndex463
}
- l463:
+ l464:
if !_rules[ruleRegisterOrConstant]() {
- goto l460
+ goto l461
}
{
- position464, tokenIndex464 := position, tokenIndex
+ position465, tokenIndex465 := position, tokenIndex
if !_rules[ruleWS]() {
- goto l464
+ goto l465
}
- goto l465
- l464:
- position, tokenIndex = position464, tokenIndex464
+ goto l466
+ l465:
+ position, tokenIndex = position465, tokenIndex465
}
- l465:
+ l466:
{
- position466, tokenIndex466 := position, tokenIndex
+ position467, tokenIndex467 := position, tokenIndex
if buffer[position] != rune(',') {
- goto l466
+ goto l467
}
position++
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l466
+ goto l467
}
position++
- l468:
+ l469:
{
- position469, tokenIndex469 := position, tokenIndex
+ position470, tokenIndex470 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l469
+ goto l470
}
position++
- goto l468
- l469:
- position, tokenIndex = position469, tokenIndex469
+ goto l469
+ l470:
+ position, tokenIndex = position470, tokenIndex470
}
- goto l467
- l466:
- position, tokenIndex = position466, tokenIndex466
+ goto l468
+ l467:
+ position, tokenIndex = position467, tokenIndex467
}
- l467:
- goto l461
- l460:
- position, tokenIndex = position460, tokenIndex460
+ l468:
+ goto l462
+ l461:
+ position, tokenIndex = position461, tokenIndex461
}
- l461:
+ l462:
if buffer[position] != rune(')') {
- goto l454
+ goto l455
}
position++
- add(ruleBaseIndexScale, position455)
+ add(ruleBaseIndexScale, position456)
}
return true
- l454:
- position, tokenIndex = position454, tokenIndex454
+ l455:
+ position, tokenIndex = position455, tokenIndex455
return false
},
/* 35 Operator <- <('+' / '-')> */
func() bool {
- position470, tokenIndex470 := position, tokenIndex
+ position471, tokenIndex471 := position, tokenIndex
{
- position471 := position
+ position472 := position
{
- position472, tokenIndex472 := position, tokenIndex
+ position473, tokenIndex473 := position, tokenIndex
if buffer[position] != rune('+') {
- goto l473
+ goto l474
}
position++
- goto l472
- l473:
- position, tokenIndex = position472, tokenIndex472
+ goto l473
+ l474:
+ position, tokenIndex = position473, tokenIndex473
if buffer[position] != rune('-') {
- goto l470
+ goto l471
}
position++
}
- l472:
- add(ruleOperator, position471)
+ l473:
+ add(ruleOperator, position472)
}
return true
- l470:
- position, tokenIndex = position470, tokenIndex470
+ l471:
+ position, tokenIndex = position471, tokenIndex471
return false
},
/* 36 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */
func() bool {
- position474, tokenIndex474 := position, tokenIndex
+ position475, tokenIndex475 := position, tokenIndex
{
- position475 := position
+ position476 := position
{
- position476, tokenIndex476 := position, tokenIndex
+ position477, tokenIndex477 := position, tokenIndex
if buffer[position] != rune('+') {
- goto l476
+ goto l477
}
position++
- goto l477
- l476:
- position, tokenIndex = position476, tokenIndex476
+ goto l478
+ l477:
+ position, tokenIndex = position477, tokenIndex477
}
- l477:
+ l478:
{
- position478, tokenIndex478 := position, tokenIndex
+ position479, tokenIndex479 := position, tokenIndex
if buffer[position] != rune('-') {
- goto l478
+ goto l479
}
position++
- goto l479
- l478:
- position, tokenIndex = position478, tokenIndex478
+ goto l480
+ l479:
+ position, tokenIndex = position479, tokenIndex479
}
- l479:
+ l480:
{
- position480, tokenIndex480 := position, tokenIndex
+ position481, tokenIndex481 := position, tokenIndex
if buffer[position] != rune('0') {
- goto l481
+ goto l482
}
position++
{
- position482, tokenIndex482 := position, tokenIndex
+ position483, tokenIndex483 := position, tokenIndex
if buffer[position] != rune('b') {
- goto l483
+ goto l484
}
position++
- goto l482
- l483:
- position, tokenIndex = position482, tokenIndex482
+ goto l483
+ l484:
+ position, tokenIndex = position483, tokenIndex483
if buffer[position] != rune('B') {
- goto l481
+ goto l482
}
position++
}
- l482:
+ l483:
{
- position486, tokenIndex486 := position, tokenIndex
+ position487, tokenIndex487 := position, tokenIndex
if buffer[position] != rune('0') {
- goto l487
+ goto l488
}
position++
- goto l486
- l487:
- position, tokenIndex = position486, tokenIndex486
+ goto l487
+ l488:
+ position, tokenIndex = position487, tokenIndex487
if buffer[position] != rune('1') {
- goto l481
+ goto l482
}
position++
}
- l486:
- l484:
+ l487:
+ l485:
{
- position485, tokenIndex485 := position, tokenIndex
+ position486, tokenIndex486 := position, tokenIndex
{
- position488, tokenIndex488 := position, tokenIndex
+ position489, tokenIndex489 := position, tokenIndex
if buffer[position] != rune('0') {
- goto l489
+ goto l490
}
position++
- goto l488
- l489:
- position, tokenIndex = position488, tokenIndex488
+ goto l489
+ l490:
+ position, tokenIndex = position489, tokenIndex489
if buffer[position] != rune('1') {
- goto l485
+ goto l486
}
position++
}
- l488:
- goto l484
- l485:
- position, tokenIndex = position485, tokenIndex485
+ l489:
+ goto l485
+ l486:
+ position, tokenIndex = position486, tokenIndex486
}
- goto l480
- l481:
- position, tokenIndex = position480, tokenIndex480
+ goto l481
+ l482:
+ position, tokenIndex = position481, tokenIndex481
if buffer[position] != rune('0') {
- goto l490
+ goto l491
}
position++
{
- position491, tokenIndex491 := position, tokenIndex
+ position492, tokenIndex492 := position, tokenIndex
if buffer[position] != rune('x') {
- goto l492
+ goto l493
}
position++
- goto l491
- l492:
- position, tokenIndex = position491, tokenIndex491
+ goto l492
+ l493:
+ position, tokenIndex = position492, tokenIndex492
if buffer[position] != rune('X') {
- goto l490
+ goto l491
}
position++
}
- l491:
+ l492:
{
- position495, tokenIndex495 := position, tokenIndex
+ position496, tokenIndex496 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l496
+ goto l497
}
position++
- goto l495
- l496:
- position, tokenIndex = position495, tokenIndex495
+ goto l496
+ l497:
+ position, tokenIndex = position496, tokenIndex496
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l497
+ goto l498
}
position++
- goto l495
- l497:
- position, tokenIndex = position495, tokenIndex495
+ goto l496
+ l498:
+ position, tokenIndex = position496, tokenIndex496
{
- position498, tokenIndex498 := position, tokenIndex
+ position499, tokenIndex499 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('f') {
- goto l499
+ goto l500
}
position++
- goto l498
- l499:
- position, tokenIndex = position498, tokenIndex498
+ goto l499
+ l500:
+ position, tokenIndex = position499, tokenIndex499
if c := buffer[position]; c < rune('A') || c > rune('F') {
- goto l490
+ goto l491
}
position++
}
- l498:
+ l499:
}
- l495:
- l493:
+ l496:
+ l494:
{
- position494, tokenIndex494 := position, tokenIndex
+ position495, tokenIndex495 := position, tokenIndex
{
- position500, tokenIndex500 := position, tokenIndex
+ position501, tokenIndex501 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l501
+ goto l502
}
position++
- goto l500
- l501:
- position, tokenIndex = position500, tokenIndex500
+ goto l501
+ l502:
+ position, tokenIndex = position501, tokenIndex501
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l502
+ goto l503
}
position++
- goto l500
- l502:
- position, tokenIndex = position500, tokenIndex500
+ goto l501
+ l503:
+ position, tokenIndex = position501, tokenIndex501
{
- position503, tokenIndex503 := position, tokenIndex
+ position504, tokenIndex504 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('f') {
- goto l504
+ goto l505
}
position++
- goto l503
- l504:
- position, tokenIndex = position503, tokenIndex503
+ goto l504
+ l505:
+ position, tokenIndex = position504, tokenIndex504
if c := buffer[position]; c < rune('A') || c > rune('F') {
- goto l494
+ goto l495
}
position++
}
- l503:
+ l504:
}
- l500:
- goto l493
- l494:
- position, tokenIndex = position494, tokenIndex494
+ l501:
+ goto l494
+ l495:
+ position, tokenIndex = position495, tokenIndex495
}
- goto l480
- l490:
- position, tokenIndex = position480, tokenIndex480
+ goto l481
+ l491:
+ position, tokenIndex = position481, tokenIndex481
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l474
+ goto l475
}
position++
- l505:
+ l506:
{
- position506, tokenIndex506 := position, tokenIndex
+ position507, tokenIndex507 := position, tokenIndex
if c := buffer[position]; c < rune('0') || c > rune('9') {
- goto l506
+ goto l507
}
position++
- goto l505
- l506:
- position, tokenIndex = position506, tokenIndex506
+ goto l506
+ l507:
+ position, tokenIndex = position507, tokenIndex507
}
}
- l480:
- add(ruleOffset, position475)
+ l481:
+ add(ruleOffset, position476)
}
return true
- l474:
- position, tokenIndex = position474, tokenIndex474
+ l475:
+ position, tokenIndex = position475, tokenIndex475
return false
},
/* 37 Section <- <([a-z] / [A-Z] / '@')+> */
func() bool {
- position507, tokenIndex507 := position, tokenIndex
+ position508, tokenIndex508 := position, tokenIndex
{
- position508 := position
+ position509 := position
{
- position511, tokenIndex511 := position, tokenIndex
+ position512, tokenIndex512 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l512
+ goto l513
}
position++
- goto l511
- l512:
- position, tokenIndex = position511, tokenIndex511
+ goto l512
+ l513:
+ position, tokenIndex = position512, tokenIndex512
if c := buffer[position]; c < rune('A') || c > rune('Z') {
- goto l513
+ goto l514
}
position++
- goto l511
- l513:
- position, tokenIndex = position511, tokenIndex511
+ goto l512
+ l514:
+ position, tokenIndex = position512, tokenIndex512
if buffer[position] != rune('@') {
- goto l507
+ goto l508
}
position++
}
- l511:
- l509:
+ l512:
+ l510:
{
- position510, tokenIndex510 := position, tokenIndex
+ position511, tokenIndex511 := position, tokenIndex
{
- position514, tokenIndex514 := position, tokenIndex
+ position515, tokenIndex515 := position, tokenIndex
if c := buffer[position]; c < rune('a') || c > rune('z') {
- goto l515
+ goto l516
}
position++
- goto l514
- l515:
- position, tokenIndex = position514, tokenIndex514
+ goto l515
+ l516:
+ position, tokenIndex = position515, tokenIndex515
if c := buffer[position]; c < rune('A') || c > rune('Z') {
- goto l516
+ goto l517
}
position++
- goto l514
- l516:
- position, tokenIndex = position514, tokenIndex514
+ goto l515
+ l517:
+ position, tokenIndex = position515, tokenIndex515
if buffer[position] != rune('@') {
- goto l510
+ goto l511
}
position++
}
- l514:
- goto l509
- l510:
- position, tokenIndex = position510, tokenIndex510
+ l515:
+ goto l510
+ l511:
+ position, tokenIndex = position511, tokenIndex511
}
- add(ruleSection, position508)
+ add(ruleSection, position509)
}
return true
- l507:
- position, tokenIndex = position507, tokenIndex507
+ l508:
+ position, tokenIndex = position508, tokenIndex508
return false
},
/* 38 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */
func() bool {
- position517, tokenIndex517 := position, tokenIndex
+ position518, tokenIndex518 := position, tokenIndex
{
- position518 := position
+ position519 := position
if buffer[position] != rune('%') {
- goto l517
+ goto l518
}
position++
{
- position519, tokenIndex519 := position, tokenIndex
+ position520, tokenIndex520 := position, tokenIndex
if c := buffer[position]; c < rune('c') || c > rune('g') {
- goto l520
+ goto l521
}
position++
- goto l519
- l520:
- position, tokenIndex = position519, tokenIndex519
+ goto l520
+ l521:
+ position, tokenIndex = position520, tokenIndex520
if buffer[position] != rune('s') {
- goto l517
+ goto l518
}
position++
}
- l519:
+ l520:
if buffer[position] != rune('s') {
- goto l517
+ goto l518
}
position++
if buffer[position] != rune(':') {
- goto l517
+ goto l518
}
position++
- add(ruleSegmentRegister, position518)
+ add(ruleSegmentRegister, position519)
}
return true
- l517:
- position, tokenIndex = position517, tokenIndex517
+ l518:
+ position, tokenIndex = position518, tokenIndex518
return false
},
}
diff --git a/src/util/fipstools/testdata/x86_64-Basic/in.s b/src/util/fipstools/testdata/x86_64-Basic/in.s
index 3b535ed7..89e8aafa 100644
--- a/src/util/fipstools/testdata/x86_64-Basic/in.s
+++ b/src/util/fipstools/testdata/x86_64-Basic/in.s
@@ -13,6 +13,7 @@ foo:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
+ .cfi_adjust_cfa_offset 32*5+8
movq %rsp, %rbp
movq %rdi, -24(%rbp)
movq -24(%rbp), %rax
diff --git a/src/util/fipstools/testdata/x86_64-Basic/out.s b/src/util/fipstools/testdata/x86_64-Basic/out.s
index 211b7ea1..a03b5d7a 100644
--- a/src/util/fipstools/testdata/x86_64-Basic/out.s
+++ b/src/util/fipstools/testdata/x86_64-Basic/out.s
@@ -16,6 +16,7 @@ foo:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
+ .cfi_adjust_cfa_offset 32*5+8
movq %rsp, %rbp
movq %rdi, -24(%rbp)
movq -24(%rbp), %rax
diff --git a/src/util/generate_build_files.py b/src/util/generate_build_files.py
index a4af6667..f2b10dec 100644
--- a/src/util/generate_build_files.py
+++ b/src/util/generate_build_files.py
@@ -44,12 +44,6 @@ NON_PERL_FILES = {
'src/crypto/curve25519/asm/x25519-asm-arm.S',
'src/crypto/poly1305/poly1305_arm_asm.S',
],
- ('linux', 'x86_64'): [
- 'src/crypto/curve25519/asm/x25519-asm-x86_64.S',
- ],
- ('mac', 'x86_64'): [
- 'src/crypto/curve25519/asm/x25519-asm-x86_64.S',
- ],
}
PREFIX = None