diff options
author | Robert Sloan <varomodt@google.com> | 2018-02-06 09:26:18 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-02-06 09:26:18 +0000 |
commit | 1ec9ae796d7306c71bc324e6680b510d9aca9d73 (patch) | |
tree | 65345a0acda3104c65b39662f207fbc9239e9ad5 | |
parent | e682e96f615e52dbd22430cf5c0b684bea524db5 (diff) | |
parent | edfa0167be4229a1a4f9d5f5348b7834f682a6c4 (diff) | |
download | boringssl-1ec9ae796d7306c71bc324e6680b510d9aca9d73.tar.gz |
external/boringssl: Sync to 45210dd4e21ace9d28cb76b3f83303fcdd2efcce. am: 8542c08a00
am: edfa0167be
Change-Id: I99b8ef205e13497b5817587aca86f446d4665b47
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 @@ -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" @@ -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\ @@ -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", @@ -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 |