diff options
author | Robert Sloan <varomodt@google.com> | 2017-07-19 09:53:00 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-07-19 09:53:00 +0000 |
commit | 28270ee35f9b52c3d312152ef1a86fed0fd90fbf (patch) | |
tree | a64a9a882f0a6e436241f60f86369d1e753d9523 | |
parent | 51e6800ac65b501b4d928ac7c13a543d33d95889 (diff) | |
parent | c8d1fc550cb021c2acad2c044b5df9ddbd9ee593 (diff) | |
download | boringssl-28270ee35f9b52c3d312152ef1a86fed0fd90fbf.tar.gz |
Merge "external/boringssl: Sync to 14308731e5446a73ac2258688a9688b524483cb6." am: 033ec98c50 am: 629cf99720
am: c8d1fc550c
Change-Id: I275c697de66cc5f9b392123af4874b125525f2cd
-rw-r--r-- | BORINGSSL_REVISION | 2 | ||||
-rw-r--r-- | linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S | 198 | ||||
-rw-r--r-- | mac-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S | 198 | ||||
-rw-r--r-- | sources.bp | 81 | ||||
-rw-r--r-- | src/CMakeLists.txt | 12 | ||||
-rw-r--r-- | src/crypto/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/crypto/cipher_extra/aead_test.cc | 1 | ||||
-rw-r--r-- | src/crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl | 122 | ||||
-rw-r--r-- | src/crypto/cipher_extra/e_aesgcmsiv.c | 8 | ||||
-rw-r--r-- | src/crypto/cipher_extra/e_chacha20poly1305.c | 74 | ||||
-rw-r--r-- | src/crypto/fipsmodule/CMakeLists.txt | 11 | ||||
-rw-r--r-- | src/crypto/fipsmodule/bn/exponentiation.c | 9 | ||||
-rw-r--r-- | src/crypto/fipsmodule/ec/ec_test.cc | 25 | ||||
-rw-r--r-- | src/crypto/fipsmodule/ec/example_mul.c | 133 | ||||
-rw-r--r-- | src/crypto/fipsmodule/ec/p224-64.c | 14 | ||||
-rw-r--r-- | src/crypto/fipsmodule/ec/p256-64.c | 26 | ||||
-rw-r--r-- | src/crypto/x509v3/CMakeLists.txt | 22 | ||||
-rw-r--r-- | src/crypto/x509v3/ext_dat.h | 8 | ||||
-rw-r--r-- | src/crypto/x509v3/tab_test.cc (renamed from src/crypto/x509v3/tab_test.c) | 56 | ||||
-rw-r--r-- | src/crypto/x509v3/v3name_test.cc (renamed from src/crypto/x509v3/v3name_test.c) | 30 | ||||
-rw-r--r-- | src/include/openssl/bn.h | 14 | ||||
-rw-r--r-- | src/include/openssl/pem.h | 4 | ||||
-rw-r--r-- | src/include/openssl/ssl.h | 36 | ||||
-rw-r--r-- | src/include/openssl/ssl3.h | 1 | ||||
-rw-r--r-- | src/ssl/CMakeLists.txt | 71 | ||||
-rw-r--r-- | src/ssl/bio_ssl.cc (renamed from src/ssl/bio_ssl.c) | 14 | ||||
-rw-r--r-- | src/ssl/custom_extensions.cc (renamed from src/ssl/custom_extensions.c) | 3 | ||||
-rw-r--r-- | src/ssl/d1_both.cc (renamed from src/ssl/d1_both.c) | 16 | ||||
-rw-r--r-- | src/ssl/d1_lib.cc (renamed from src/ssl/d1_lib.c) | 4 | ||||
-rw-r--r-- | src/ssl/d1_pkt.cc (renamed from src/ssl/d1_pkt.c) | 3 | ||||
-rw-r--r-- | src/ssl/d1_srtp.cc (renamed from src/ssl/d1_srtp.c) | 0 | ||||
-rw-r--r-- | src/ssl/dtls_method.cc (renamed from src/ssl/dtls_method.c) | 0 | ||||
-rw-r--r-- | src/ssl/dtls_record.cc (renamed from src/ssl/dtls_record.c) | 0 | ||||
-rw-r--r-- | src/ssl/handshake_client.cc (renamed from src/ssl/handshake_client.c) | 206 | ||||
-rw-r--r-- | src/ssl/handshake_server.cc (renamed from src/ssl/handshake_server.c) | 102 | ||||
-rw-r--r-- | src/ssl/internal.h | 80 | ||||
-rw-r--r-- | src/ssl/s3_both.cc (renamed from src/ssl/s3_both.c) | 12 | ||||
-rw-r--r-- | src/ssl/s3_lib.cc (renamed from src/ssl/s3_lib.c) | 4 | ||||
-rw-r--r-- | src/ssl/s3_pkt.cc (renamed from src/ssl/s3_pkt.c) | 11 | ||||
-rw-r--r-- | src/ssl/ssl_aead_ctx.cc (renamed from src/ssl/ssl_aead_ctx.c) | 91 | ||||
-rw-r--r-- | src/ssl/ssl_asn1.cc (renamed from src/ssl/ssl_asn1.c) | 9 | ||||
-rw-r--r-- | src/ssl/ssl_buffer.cc (renamed from src/ssl/ssl_buffer.c) | 32 | ||||
-rw-r--r-- | src/ssl/ssl_cert.cc (renamed from src/ssl/ssl_cert.c) | 18 | ||||
-rw-r--r-- | src/ssl/ssl_cipher.cc (renamed from src/ssl/ssl_cipher.c) | 21 | ||||
-rw-r--r-- | src/ssl/ssl_ecdh.cc (renamed from src/ssl/ssl_ecdh.c) | 123 | ||||
-rw-r--r-- | src/ssl/ssl_file.cc (renamed from src/ssl/ssl_file.c) | 0 | ||||
-rw-r--r-- | src/ssl/ssl_lib.cc (renamed from src/ssl/ssl_lib.c) | 55 | ||||
-rw-r--r-- | src/ssl/ssl_privkey.cc (renamed from src/ssl/ssl_privkey.c) | 20 | ||||
-rw-r--r-- | src/ssl/ssl_privkey_cc.cc | 76 | ||||
-rw-r--r-- | src/ssl/ssl_session.cc (renamed from src/ssl/ssl_session.c) | 72 | ||||
-rw-r--r-- | src/ssl/ssl_stat.cc (renamed from src/ssl/ssl_stat.c) | 0 | ||||
-rw-r--r-- | src/ssl/ssl_transcript.cc (renamed from src/ssl/ssl_transcript.c) | 0 | ||||
-rw-r--r-- | src/ssl/ssl_versions.cc (renamed from src/ssl/ssl_versions.c) | 36 | ||||
-rw-r--r-- | src/ssl/ssl_x509.cc (renamed from src/ssl/ssl_x509.c) | 22 | ||||
-rw-r--r-- | src/ssl/t1_enc.cc (renamed from src/ssl/t1_enc.c) | 4 | ||||
-rw-r--r-- | src/ssl/t1_lib.cc (renamed from src/ssl/t1_lib.c) | 206 | ||||
-rw-r--r-- | src/ssl/test/bssl_shim.cc | 18 | ||||
-rw-r--r-- | src/ssl/test/fuzzer.h | 18 | ||||
-rw-r--r-- | src/ssl/test/runner/common.go | 44 | ||||
-rw-r--r-- | src/ssl/test/runner/conn.go | 22 | ||||
-rw-r--r-- | src/ssl/test/runner/dtls.go | 9 | ||||
-rw-r--r-- | src/ssl/test/runner/fuzzer_mode.json | 28 | ||||
-rw-r--r-- | src/ssl/test/runner/handshake_client.go | 15 | ||||
-rw-r--r-- | src/ssl/test/runner/handshake_messages.go | 125 | ||||
-rw-r--r-- | src/ssl/test/runner/handshake_server.go | 41 | ||||
-rw-r--r-- | src/ssl/test/runner/runner.go | 696 | ||||
-rw-r--r-- | src/ssl/test/test_config.cc | 1 | ||||
-rw-r--r-- | src/ssl/test/test_config.h | 1 | ||||
-rw-r--r-- | src/ssl/tls13_both.cc (renamed from src/ssl/tls13_both.c) | 99 | ||||
-rw-r--r-- | src/ssl/tls13_client.cc (renamed from src/ssl/tls13_client.c) | 107 | ||||
-rw-r--r-- | src/ssl/tls13_enc.cc (renamed from src/ssl/tls13_enc.c) | 0 | ||||
-rw-r--r-- | src/ssl/tls13_server.cc (renamed from src/ssl/tls13_server.c) | 73 | ||||
-rw-r--r-- | src/ssl/tls_method.cc (renamed from src/ssl/tls_method.c) | 0 | ||||
-rw-r--r-- | src/ssl/tls_record.cc (renamed from src/ssl/tls_record.c) | 175 | ||||
-rw-r--r-- | src/tool/client.cc | 10 | ||||
-rw-r--r-- | src/tool/server.cc | 8 | ||||
-rw-r--r-- | src/util/all_tests.json | 3 | ||||
-rw-r--r-- | src/util/generate_build_files.py | 167 |
78 files changed, 2620 insertions, 1438 deletions
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION index 959b0f0c..5388f09f 100644 --- a/BORINGSSL_REVISION +++ b/BORINGSSL_REVISION @@ -1 +1 @@ -ee7aa02744a78bf4630913b1c83d0fe36aa45efc +14308731e5446a73ac2258688a9688b524483cb6 diff --git a/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S b/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S index d149d0f7..a6f5e07d 100644 --- a/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S +++ b/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S @@ -41,6 +41,7 @@ chacha20_poly1305_constants: .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00 .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00 .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 +.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff .type poly_hash_ad_internal,@function .align 64 @@ -2124,7 +2125,9 @@ chacha20_poly1305_seal: .cfi_offset r15, -56 leaq 32(%rsp),%rbp andq $-32,%rbp - movq %rdx,8+32(%rbp) + movq 56(%r9),%rbx + addq %rdx,%rbx + movq %rbx,8+32(%rbp) movq %r8,0+32(%rbp) movq %rdx,%rbx @@ -3587,11 +3590,9 @@ seal_sse_128_seal: seal_sse_tail_16: testq %rbx,%rbx - jz seal_sse_finalize + jz process_blocks_of_extra_in movq %rbx,%r8 - shlq $4,%r8 - leaq .and_masks(%rip),%r13 movq %rbx,%rcx leaq -1(%rsi,%rbx), %rsi pxor %xmm15,%xmm15 @@ -3615,7 +3616,72 @@ seal_sse_tail_16: subq $1,%rcx jnz 2b - pand -16(%r13,%r8), %xmm15 + + + + + + + + movq 288+32(%rsp),%r9 + movq 56(%r9),%r14 + movq 48(%r9),%r13 + testq %r14,%r14 + jz process_partial_block + + movq $16,%r15 + subq %rbx,%r15 + cmpq %r15,%r14 + + jge load_extra_in + movq %r14,%r15 + +load_extra_in: + + + leaq -1(%r13,%r15), %rsi + + + addq %r15,%r13 + subq %r15,%r14 + movq %r13,48(%r9) + movq %r14,56(%r9) + + + + addq %r15,%r8 + + + pxor %xmm11,%xmm11 +3: + pslldq $1,%xmm11 + pinsrb $0,(%rsi),%xmm11 + leaq -1(%rsi),%rsi + subq $1,%r15 + jnz 3b + + + + + movq %rbx,%r15 + +4: + pslldq $1,%xmm11 + subq $1,%r15 + jnz 4b + + + + + leaq .and_masks(%rip),%r15 + shlq $4,%rbx + pand -16(%r15,%rbx), %xmm15 + + + por %xmm11,%xmm15 + + + .byte 102,77,15,126,253 pextrq $1,%xmm15,%r14 addq %r13,%r10 @@ -3660,7 +3726,127 @@ seal_sse_tail_16: adcq %r9,%r11 adcq $0,%r12 -seal_sse_finalize: + +process_blocks_of_extra_in: + + movq 288+32(%rsp),%r9 + movq 48(%r9),%rsi + movq 56(%r9),%r8 + movq %r8,%rcx + shrq $4,%r8 + +5: + jz process_extra_in_trailer + addq 0(%rsi),%r10 + adcq 8+0(%rsi),%r11 + adcq $1,%r12 + movq 0+0(%rbp),%rax + movq %rax,%r15 + mulq %r10 + movq %rax,%r13 + movq %rdx,%r14 + movq 0+0(%rbp),%rax + mulq %r11 + imulq %r12,%r15 + addq %rax,%r14 + adcq %rdx,%r15 + movq 8+0(%rbp),%rax + movq %rax,%r9 + mulq %r10 + addq %rax,%r14 + adcq $0,%rdx + movq %rdx,%r10 + movq 8+0(%rbp),%rax + mulq %r11 + addq %rax,%r15 + adcq $0,%rdx + imulq %r12,%r9 + addq %r10,%r15 + adcq %rdx,%r9 + movq %r13,%r10 + movq %r14,%r11 + movq %r15,%r12 + andq $3,%r12 + movq %r15,%r13 + andq $-4,%r13 + movq %r9,%r14 + shrdq $2,%r9,%r15 + shrq $2,%r9 + addq %r13,%r10 + adcq %r14,%r11 + adcq $0,%r12 + addq %r15,%r10 + adcq %r9,%r11 + adcq $0,%r12 + + leaq 16(%rsi),%rsi + subq $1,%r8 + jmp 5b + +process_extra_in_trailer: + andq $15,%rcx + movq %rcx,%rbx + jz do_length_block + leaq -1(%rsi,%rcx), %rsi + +6: + pslldq $1,%xmm15 + pinsrb $0,(%rsi),%xmm15 + leaq -1(%rsi),%rsi + subq $1,%rcx + jnz 6b + +process_partial_block: + + leaq .and_masks(%rip),%r15 + shlq $4,%rbx + pand -16(%r15,%rbx), %xmm15 +.byte 102,77,15,126,253 + pextrq $1,%xmm15,%r14 + addq %r13,%r10 + adcq %r14,%r11 + adcq $1,%r12 + movq 0+0(%rbp),%rax + movq %rax,%r15 + mulq %r10 + movq %rax,%r13 + movq %rdx,%r14 + movq 0+0(%rbp),%rax + mulq %r11 + imulq %r12,%r15 + addq %rax,%r14 + adcq %rdx,%r15 + movq 8+0(%rbp),%rax + movq %rax,%r9 + mulq %r10 + addq %rax,%r14 + adcq $0,%rdx + movq %rdx,%r10 + movq 8+0(%rbp),%rax + mulq %r11 + addq %rax,%r15 + adcq $0,%rdx + imulq %r12,%r9 + addq %r10,%r15 + adcq %rdx,%r9 + movq %r13,%r10 + movq %r14,%r11 + movq %r15,%r12 + andq $3,%r12 + movq %r15,%r13 + andq $-4,%r13 + movq %r9,%r14 + shrdq $2,%r9,%r15 + shrq $2,%r9 + addq %r13,%r10 + adcq %r14,%r11 + adcq $0,%r12 + addq %r15,%r10 + adcq %r9,%r11 + adcq $0,%r12 + + +do_length_block: addq 32(%rbp),%r10 adcq 8+32(%rbp),%r11 adcq $1,%r12 diff --git a/mac-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S b/mac-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S index 9db2a586..c90447ac 100644 --- a/mac-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S +++ b/mac-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S @@ -40,6 +40,7 @@ chacha20_poly1305_constants: .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00 .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00 .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 +.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff .p2align 6 @@ -2123,7 +2124,9 @@ _chacha20_poly1305_seal: leaq 32(%rsp),%rbp andq $-32,%rbp - movq %rdx,8+32(%rbp) + movq 56(%r9),%rbx + addq %rdx,%rbx + movq %rbx,8+32(%rbp) movq %r8,0+32(%rbp) movq %rdx,%rbx @@ -3586,11 +3589,9 @@ seal_sse_128_seal: seal_sse_tail_16: testq %rbx,%rbx - jz seal_sse_finalize + jz process_blocks_of_extra_in movq %rbx,%r8 - shlq $4,%r8 - leaq .and_masks(%rip),%r13 movq %rbx,%rcx leaq -1(%rsi,%rbx), %rsi pxor %xmm15,%xmm15 @@ -3614,7 +3615,72 @@ seal_sse_tail_16: subq $1,%rcx jnz 2b - pand -16(%r13,%r8), %xmm15 + + + + + + + + movq 288+32(%rsp),%r9 + movq 56(%r9),%r14 + movq 48(%r9),%r13 + testq %r14,%r14 + jz process_partial_block + + movq $16,%r15 + subq %rbx,%r15 + cmpq %r15,%r14 + + jge load_extra_in + movq %r14,%r15 + +load_extra_in: + + + leaq -1(%r13,%r15), %rsi + + + addq %r15,%r13 + subq %r15,%r14 + movq %r13,48(%r9) + movq %r14,56(%r9) + + + + addq %r15,%r8 + + + pxor %xmm11,%xmm11 +3: + pslldq $1,%xmm11 + pinsrb $0,(%rsi),%xmm11 + leaq -1(%rsi),%rsi + subq $1,%r15 + jnz 3b + + + + + movq %rbx,%r15 + +4: + pslldq $1,%xmm11 + subq $1,%r15 + jnz 4b + + + + + leaq .and_masks(%rip),%r15 + shlq $4,%rbx + pand -16(%r15,%rbx), %xmm15 + + + por %xmm11,%xmm15 + + + .byte 102,77,15,126,253 pextrq $1,%xmm15,%r14 addq %r13,%r10 @@ -3659,7 +3725,127 @@ seal_sse_tail_16: adcq %r9,%r11 adcq $0,%r12 -seal_sse_finalize: + +process_blocks_of_extra_in: + + movq 288+32(%rsp),%r9 + movq 48(%r9),%rsi + movq 56(%r9),%r8 + movq %r8,%rcx + shrq $4,%r8 + +5: + jz process_extra_in_trailer + addq 0(%rsi),%r10 + adcq 8+0(%rsi),%r11 + adcq $1,%r12 + movq 0+0(%rbp),%rax + movq %rax,%r15 + mulq %r10 + movq %rax,%r13 + movq %rdx,%r14 + movq 0+0(%rbp),%rax + mulq %r11 + imulq %r12,%r15 + addq %rax,%r14 + adcq %rdx,%r15 + movq 8+0(%rbp),%rax + movq %rax,%r9 + mulq %r10 + addq %rax,%r14 + adcq $0,%rdx + movq %rdx,%r10 + movq 8+0(%rbp),%rax + mulq %r11 + addq %rax,%r15 + adcq $0,%rdx + imulq %r12,%r9 + addq %r10,%r15 + adcq %rdx,%r9 + movq %r13,%r10 + movq %r14,%r11 + movq %r15,%r12 + andq $3,%r12 + movq %r15,%r13 + andq $-4,%r13 + movq %r9,%r14 + shrdq $2,%r9,%r15 + shrq $2,%r9 + addq %r13,%r10 + adcq %r14,%r11 + adcq $0,%r12 + addq %r15,%r10 + adcq %r9,%r11 + adcq $0,%r12 + + leaq 16(%rsi),%rsi + subq $1,%r8 + jmp 5b + +process_extra_in_trailer: + andq $15,%rcx + movq %rcx,%rbx + jz do_length_block + leaq -1(%rsi,%rcx), %rsi + +6: + pslldq $1,%xmm15 + pinsrb $0,(%rsi),%xmm15 + leaq -1(%rsi),%rsi + subq $1,%rcx + jnz 6b + +process_partial_block: + + leaq .and_masks(%rip),%r15 + shlq $4,%rbx + pand -16(%r15,%rbx), %xmm15 +.byte 102,77,15,126,253 + pextrq $1,%xmm15,%r14 + addq %r13,%r10 + adcq %r14,%r11 + adcq $1,%r12 + movq 0+0(%rbp),%rax + movq %rax,%r15 + mulq %r10 + movq %rax,%r13 + movq %rdx,%r14 + movq 0+0(%rbp),%rax + mulq %r11 + imulq %r12,%r15 + addq %rax,%r14 + adcq %rdx,%r15 + movq 8+0(%rbp),%rax + movq %rax,%r9 + mulq %r10 + addq %rax,%r14 + adcq $0,%rdx + movq %rdx,%r10 + movq 8+0(%rbp),%rax + mulq %r11 + addq %rax,%r15 + adcq $0,%rdx + imulq %r12,%r9 + addq %r10,%r15 + adcq %rdx,%r9 + movq %r13,%r10 + movq %r14,%r11 + movq %r15,%r12 + andq $3,%r12 + movq %r15,%r13 + andq $-4,%r13 + movq %r9,%r14 + shrdq $2,%r9,%r15 + shrq $2,%r9 + addq %r13,%r10 + adcq %r14,%r11 + adcq $0,%r12 + addq %r15,%r10 + adcq %r9,%r11 + adcq $0,%r12 + + +do_length_block: addq 32(%rbp),%r10 adcq 8+32(%rbp),%r11 adcq $1,%r12 @@ -349,42 +349,41 @@ cc_defaults { cc_defaults { name: "libssl_sources", srcs: [ - "src/ssl/bio_ssl.c", - "src/ssl/custom_extensions.c", - "src/ssl/d1_both.c", - "src/ssl/d1_lib.c", - "src/ssl/d1_pkt.c", - "src/ssl/d1_srtp.c", - "src/ssl/dtls_method.c", - "src/ssl/dtls_record.c", - "src/ssl/handshake_client.c", - "src/ssl/handshake_server.c", - "src/ssl/s3_both.c", - "src/ssl/s3_lib.c", - "src/ssl/s3_pkt.c", - "src/ssl/ssl_aead_ctx.c", - "src/ssl/ssl_asn1.c", - "src/ssl/ssl_buffer.c", - "src/ssl/ssl_cert.c", - "src/ssl/ssl_cipher.c", - "src/ssl/ssl_ecdh.c", - "src/ssl/ssl_file.c", - "src/ssl/ssl_lib.c", - "src/ssl/ssl_privkey.c", - "src/ssl/ssl_privkey_cc.cc", - "src/ssl/ssl_session.c", - "src/ssl/ssl_stat.c", - "src/ssl/ssl_transcript.c", - "src/ssl/ssl_versions.c", - "src/ssl/ssl_x509.c", - "src/ssl/t1_enc.c", - "src/ssl/t1_lib.c", - "src/ssl/tls13_both.c", - "src/ssl/tls13_client.c", - "src/ssl/tls13_enc.c", - "src/ssl/tls13_server.c", - "src/ssl/tls_method.c", - "src/ssl/tls_record.c", + "src/ssl/bio_ssl.cc", + "src/ssl/custom_extensions.cc", + "src/ssl/d1_both.cc", + "src/ssl/d1_lib.cc", + "src/ssl/d1_pkt.cc", + "src/ssl/d1_srtp.cc", + "src/ssl/dtls_method.cc", + "src/ssl/dtls_record.cc", + "src/ssl/handshake_client.cc", + "src/ssl/handshake_server.cc", + "src/ssl/s3_both.cc", + "src/ssl/s3_lib.cc", + "src/ssl/s3_pkt.cc", + "src/ssl/ssl_aead_ctx.cc", + "src/ssl/ssl_asn1.cc", + "src/ssl/ssl_buffer.cc", + "src/ssl/ssl_cert.cc", + "src/ssl/ssl_cipher.cc", + "src/ssl/ssl_ecdh.cc", + "src/ssl/ssl_file.cc", + "src/ssl/ssl_lib.cc", + "src/ssl/ssl_privkey.cc", + "src/ssl/ssl_session.cc", + "src/ssl/ssl_stat.cc", + "src/ssl/ssl_transcript.cc", + "src/ssl/ssl_versions.cc", + "src/ssl/ssl_x509.cc", + "src/ssl/t1_enc.cc", + "src/ssl/t1_lib.cc", + "src/ssl/tls13_both.cc", + "src/ssl/tls13_client.cc", + "src/ssl/tls13_enc.cc", + "src/ssl/tls13_server.cc", + "src/ssl/tls_method.cc", + "src/ssl/tls_record.cc", ], } @@ -466,6 +465,8 @@ cc_defaults { "src/crypto/test/gtest_main.cc", "src/crypto/thread_test.cc", "src/crypto/x509/x509_test.cc", + "src/crypto/x509v3/tab_test.cc", + "src/crypto/x509v3/v3name_test.cc", ], } @@ -477,11 +478,3 @@ cc_defaults { ], } -cc_defaults { - name: "boringssl_tests_sources", - srcs: [ - "src/crypto/fipsmodule/ec/example_mul.c", - "src/crypto/x509v3/tab_test.c", - "src/crypto/x509v3/v3name_test.c", - ], -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index deab75ba..7b7f9343 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,6 +43,16 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS} -Wmissing-declarations") + # In GCC, -Wmissing-declarations is the C++ spelling of -Wmissing-prototypes + # and using the wrong one is an error. In Clang, -Wmissing-prototypes is the + # spelling for both and -Wmissing-declarations is some other warning. + # + # https://gcc.gnu.org/onlinedocs/gcc-7.1.0/gcc/Warning-Options.html#Warning-Options + # https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-prototypes + # https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-declarations + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-prototypes") + endif() elseif(MSVC) set(MSVC_DISABLED_WARNINGS_LIST "C4061" # enumerator 'identifier' in switch of enum 'enumeration' is not @@ -299,7 +309,7 @@ if(FUZZ) add_library(Fuzzer STATIC ${LIBFUZZER_SOURCES}) # libFuzzer does not pass our aggressive warnings. It also must be built # without -fsanitize-coverage options or clang crashes. - set_target_properties(Fuzzer PROPERTIES COMPILE_FLAGS "-Wno-shadow -Wno-format-nonliteral -fsanitize-coverage=0") + set_target_properties(Fuzzer PROPERTIES COMPILE_FLAGS "-Wno-shadow -Wno-format-nonliteral -Wno-missing-prototypes -fsanitize-coverage=0") endif() add_subdirectory(fuzz) diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index b941f67d..651793fd 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -260,6 +260,8 @@ add_executable( test/file_test_gtest.cc thread_test.cc x509/x509_test.cc + x509v3/tab_test.cc + x509v3/v3name_test.cc $<TARGET_OBJECTS:crypto_test_data> $<TARGET_OBJECTS:gtest_main> diff --git a/src/crypto/cipher_extra/aead_test.cc b/src/crypto/cipher_extra/aead_test.cc index 949c8002..a699890a 100644 --- a/src/crypto/cipher_extra/aead_test.cc +++ b/src/crypto/cipher_extra/aead_test.cc @@ -240,6 +240,7 @@ TEST_P(PerAEADTest, TestExtraInput) { for (size_t extra_in_size = 0; extra_in_size < in.size(); extra_in_size++) { size_t tag_bytes_written; + SCOPED_TRACE(extra_in_size); ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter( ctx.get(), out.data(), out_tag.data(), &tag_bytes_written, out_tag.size(), nonce.data(), nonce.size(), in.data(), diff --git a/src/crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl b/src/crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl index 857f1d5d..0e322798 100644 --- a/src/crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl +++ b/src/crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl @@ -78,6 +78,7 @@ chacha20_poly1305_constants: .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00 .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00 .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 +.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff ___ my ($oup,$inp,$inl,$adp,$keyp,$itr1,$itr2)=("%rdi","%rsi","%rbx","%rcx","%r9","%rcx","%r8"); @@ -856,7 +857,9 @@ chacha20_poly1305_seal: .cfi_offset r15, -56 lea 32(%rsp), %rbp and \$-32, %rbp - mov %rdx, 8+$len_store + mov 56($keyp), $inl # extra_in_len + addq %rdx, $inl + mov $inl, 8+$len_store mov %r8, 0+$len_store mov %rdx, $inl\n"; $code.=" mov OPENSSL_ia32cap_P+8(%rip), %eax @@ -1093,11 +1096,9 @@ seal_sse_128_seal: seal_sse_tail_16: test $inl, $inl - jz seal_sse_finalize + jz process_blocks_of_extra_in # We can only load the PT one byte at a time to avoid buffer overread mov $inl, $itr2 - shl \$4, $itr2 - lea .and_masks(%rip), $t0 mov $inl, $itr1 lea -1($inp, $inl), $inp pxor $T3, $T3 @@ -1106,7 +1107,7 @@ seal_sse_tail_16: pinsrb \$0, ($inp), $T3 lea -1($inp), $inp dec $itr1 - jne 1b + jne 1b # XOR the keystream with the plaintext. pxor $A0, $T3 @@ -1121,14 +1122,121 @@ seal_sse_tail_16: sub \$1, $itr1 jnz 2b - pand -16($t0, $itr2), $T3 + # $T3 contains the final (partial, non-empty) block of ciphertext which + # needs to be fed into the Poly1305 state. The right-most $inl bytes of it + # are valid. We need to fill it with extra_in bytes until full, or until we + # run out of bytes. + # + # $keyp points to the tag output, which is actually a struct with the + # extra_in pointer and length at offset 48. + movq 288+32(%rsp), $keyp + movq 56($keyp), $t1 # extra_in_len + movq 48($keyp), $t0 # extra_in + test $t1, $t1 + jz process_partial_block # Common case: no bytes of extra_in + + movq \$16, $t2 + subq $inl, $t2 # 16-$inl is the number of bytes that fit into $T3. + cmpq $t2, $t1 # if extra_in_len < 16-$inl, only copy extra_in_len + # (note that AT&T syntax reverses the arguments) + jge load_extra_in + movq $t1, $t2 + +load_extra_in: + # $t2 contains the number of bytes of extra_in (pointed to by $t0) to load + # into $T3. They are loaded in reverse order. + leaq -1($t0, $t2), $inp + # Update extra_in and extra_in_len to reflect the bytes that are about to + # be read. + addq $t2, $t0 + subq $t2, $t1 + movq $t0, 48($keyp) + movq $t1, 56($keyp) + + # Update $itr2, which is used to select the mask later on, to reflect the + # extra bytes about to be added. + addq $t2, $itr2 + + # Load $t2 bytes of extra_in into $T2. + pxor $T2, $T2 +3: + pslldq \$1, $T2 + pinsrb \$0, ($inp), $T2 + lea -1($inp), $inp + sub \$1, $t2 + jnz 3b + + # Shift $T2 up the length of the remainder from the main encryption. Sadly, + # the shift for an XMM register has to be a constant, thus we loop to do + # this. + movq $inl, $t2 + +4: + pslldq \$1, $T2 + sub \$1, $t2 + jnz 4b + + # Mask $T3 (the remainder from the main encryption) so that superfluous + # bytes are zero. This means that the non-zero bytes in $T2 and $T3 are + # disjoint and so we can merge them with an OR. + lea .and_masks(%rip), $t2 + shl \$4, $inl + pand -16($t2, $inl), $T3 + + # Merge $T2 into $T3, forming the remainder block. + por $T2, $T3 + + # The block of ciphertext + extra_in is ready to be included in the + # Poly1305 state. + movq $T3, $t0 + pextrq \$1, $T3, $t1 + add $t0, $acc0 + adc $t1, $acc1 + adc \$1, $acc2\n"; + &poly_mul(); $code.=" + +process_blocks_of_extra_in: + # There may be additional bytes of extra_in to process. + movq 288+32(%rsp), $keyp + movq 48($keyp), $inp # extra_in + movq 56($keyp), $itr2 # extra_in_len + movq $itr2, $itr1 + shr \$4, $itr2 # number of blocks + +5: + jz process_extra_in_trailer\n"; + &poly_add("0($inp)"); + &poly_mul(); $code.=" + leaq 16($inp), $inp + subq \$1, $itr2 + jmp 5b + +process_extra_in_trailer: + andq \$15, $itr1 # remaining num bytes (<16) of extra_in + movq $itr1, $inl + jz do_length_block + leaq -1($inp, $itr1), $inp + +6: + pslldq \$1, $T3 + pinsrb \$0, ($inp), $T3 + lea -1($inp), $inp + sub \$1, $itr1 + jnz 6b + +process_partial_block: + # $T3 contains $inl bytes of data to be fed into Poly1305. $inl != 0 + lea .and_masks(%rip), $t2 + shl \$4, $inl + pand -16($t2, $inl), $T3 movq $T3, $t0 pextrq \$1, $T3, $t1 add $t0, $acc0 adc $t1, $acc1 adc \$1, $acc2\n"; &poly_mul(); $code.=" -seal_sse_finalize:\n"; + +do_length_block:\n"; &poly_add($len_store); &poly_mul(); $code.=" # Final reduce diff --git a/src/crypto/cipher_extra/e_aesgcmsiv.c b/src/crypto/cipher_extra/e_aesgcmsiv.c index 190a1b96..2dd12670 100644 --- a/src/crypto/cipher_extra/e_aesgcmsiv.c +++ b/src/crypto/cipher_extra/e_aesgcmsiv.c @@ -13,6 +13,9 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <openssl/aead.h> + +#include <assert.h> + #include <openssl/cipher.h> #include <openssl/cpu.h> #include <openssl/crypto.h> @@ -29,7 +32,7 @@ /* Optimised AES-GCM-SIV */ struct aead_aes_gcm_siv_asm_ctx { - alignas(64) uint8_t key[16*15]; + alignas(16) uint8_t key[16*15]; int is_128_bit; }; @@ -67,6 +70,9 @@ static int aead_aes_gcm_siv_asm_init(EVP_AEAD_CTX *ctx, const uint8_t *key, return 0; } + /* malloc should return a 16-byte-aligned address. */ + assert((((uintptr_t)gcm_siv_ctx) & 15) == 0); + if (key_bits == 128) { aes128gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]); gcm_siv_ctx->is_128_bit = 1; diff --git a/src/crypto/cipher_extra/e_chacha20poly1305.c b/src/crypto/cipher_extra/e_chacha20poly1305.c index 6cfc856c..515b60f2 100644 --- a/src/crypto/cipher_extra/e_chacha20poly1305.c +++ b/src/crypto/cipher_extra/e_chacha20poly1305.c @@ -124,33 +124,34 @@ static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) { CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes)); } -static void poly1305_update_padded_16(poly1305_state *poly1305, - const uint8_t *data, size_t data_len) { - static const uint8_t padding[16] = { 0 }; /* Padding is all zeros. */ - - CRYPTO_poly1305_update(poly1305, data, data_len); - if (data_len % 16 != 0) { - CRYPTO_poly1305_update(poly1305, padding, - sizeof(padding) - (data_len % 16)); - } -} - /* calc_tag fills |tag| with the authentication tag for the given inputs. */ static void calc_tag(uint8_t tag[POLY1305_TAG_LEN], const struct aead_chacha20_poly1305_ctx *c20_ctx, const uint8_t nonce[12], const uint8_t *ad, size_t ad_len, - const uint8_t *ciphertext, size_t ciphertext_len) { + const uint8_t *ciphertext, size_t ciphertext_len, + const uint8_t *ciphertext_extra, + size_t ciphertext_extra_len) { alignas(16) uint8_t poly1305_key[32]; OPENSSL_memset(poly1305_key, 0, sizeof(poly1305_key)); CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), c20_ctx->key, nonce, 0); + static const uint8_t padding[16] = { 0 }; /* Padding is all zeros. */ poly1305_state ctx; CRYPTO_poly1305_init(&ctx, poly1305_key); - poly1305_update_padded_16(&ctx, ad, ad_len); - poly1305_update_padded_16(&ctx, ciphertext, ciphertext_len); + CRYPTO_poly1305_update(&ctx, ad, ad_len); + if (ad_len % 16 != 0) { + CRYPTO_poly1305_update(&ctx, padding, sizeof(padding) - (ad_len % 16)); + } + CRYPTO_poly1305_update(&ctx, ciphertext, ciphertext_len); + CRYPTO_poly1305_update(&ctx, ciphertext_extra, ciphertext_extra_len); + const size_t ciphertext_total = ciphertext_len + ciphertext_extra_len; + if (ciphertext_total % 16 != 0) { + CRYPTO_poly1305_update(&ctx, padding, + sizeof(padding) - (ciphertext_total % 16)); + } poly1305_update_length(&ctx, ad_len); - poly1305_update_length(&ctx, ciphertext_len); + poly1305_update_length(&ctx, ciphertext_total); CRYPTO_poly1305_finish(&ctx, tag); } @@ -161,6 +162,14 @@ static int aead_chacha20_poly1305_seal_scatter( size_t extra_in_len, const uint8_t *ad, size_t ad_len) { const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; + if (extra_in_len + ctx->tag_len < ctx->tag_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); + return 0; + } + if (max_out_tag_len < ctx->tag_len + extra_in_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } if (nonce_len != 12) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE); return 0; @@ -183,20 +192,43 @@ static int aead_chacha20_poly1305_seal_scatter( return 0; } - alignas(16) uint8_t tag[48]; + /* The the extra input is given, it is expected to be very short and so is + * encrypted byte-by-byte first. */ + if (extra_in_len) { + static const size_t kChaChaBlockSize = 64; + uint32_t block_counter = 1 + (in_len / kChaChaBlockSize); + size_t offset = in_len % kChaChaBlockSize; + uint8_t block[64 /* kChaChaBlockSize */]; + + for (size_t done = 0; done < extra_in_len; block_counter++) { + memset(block, 0, sizeof(block)); + CRYPTO_chacha_20(block, block, sizeof(block), c20_ctx->key, nonce, + block_counter); + for (size_t i = offset; i < sizeof(block) && done < extra_in_len; + i++, done++) { + out_tag[done] = extra_in[done] ^ block[i]; + } + offset = 0; + } + } + + alignas(16) uint8_t tag[48 + 8 + 8]; if (asm_capable()) { OPENSSL_memcpy(tag, c20_ctx->key, 32); OPENSSL_memset(tag + 32, 0, 4); OPENSSL_memcpy(tag + 32 + 4, nonce, 12); + OPENSSL_memcpy(tag + 48, &out_tag, sizeof(out_tag)); + OPENSSL_memcpy(tag + 56, &extra_in_len, sizeof(extra_in_len)); chacha20_poly1305_seal(out, in, in_len, ad, ad_len, tag); } else { CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1); - calc_tag(tag, c20_ctx, nonce, ad, ad_len, out, in_len); + calc_tag(tag, c20_ctx, nonce, ad, ad_len, out, in_len, + out_tag, extra_in_len); } - OPENSSL_memcpy(out_tag, tag, ctx->tag_len); - *out_tag_len = ctx->tag_len; + OPENSSL_memcpy(out_tag + extra_in_len, tag, ctx->tag_len); + *out_tag_len = extra_in_len + ctx->tag_len; return 1; } @@ -236,7 +268,7 @@ static int aead_chacha20_poly1305_open_gather( OPENSSL_memcpy(tag + 32 + 4, nonce, 12); chacha20_poly1305_open(out, in, in_len, ad, ad_len, tag); } else { - calc_tag(tag, c20_ctx, nonce, ad, ad_len, in, in_len); + calc_tag(tag, c20_ctx, nonce, ad, ad_len, in, in_len, NULL, 0); CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1); } @@ -253,7 +285,7 @@ static const EVP_AEAD aead_chacha20_poly1305 = { 12, /* nonce len */ POLY1305_TAG_LEN, /* overhead */ POLY1305_TAG_LEN, /* max tag length */ - 0, /* seal_scatter_supports_extra_in */ + 1, /* seal_scatter_supports_extra_in */ aead_chacha20_poly1305_init, NULL, /* init_with_direction */ diff --git a/src/crypto/fipsmodule/CMakeLists.txt b/src/crypto/fipsmodule/CMakeLists.txt index a1bc6dc9..e83c4835 100644 --- a/src/crypto/fipsmodule/CMakeLists.txt +++ b/src/crypto/fipsmodule/CMakeLists.txt @@ -193,14 +193,3 @@ else() ${BCM_ASM_SOURCES} ) endif() - -add_executable( - example_mul - - ec/example_mul.c - - $<TARGET_OBJECTS:test_support> -) - -target_link_libraries(example_mul crypto) -add_dependencies(all_tests example_mul) diff --git a/src/crypto/fipsmodule/bn/exponentiation.c b/src/crypto/fipsmodule/bn/exponentiation.c index e5521d68..187b845c 100644 --- a/src/crypto/fipsmodule/bn/exponentiation.c +++ b/src/crypto/fipsmodule/bn/exponentiation.c @@ -1085,11 +1085,12 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, while (bits >= 0) { /* Read five bits from |bits-4| through |bits|, inclusive. */ int first_bit = bits - 4; - wvalue = *(const uint16_t *) (p_bytes + (first_bit >> 3)); - wvalue >>= first_bit & 7; - wvalue &= 0x1f; + uint16_t val; + OPENSSL_memcpy(&val, p_bytes + (first_bit >> 3), sizeof(val)); + val >>= first_bit & 7; + val &= 0x1f; bits -= 5; - bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue); + bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, val); } } diff --git a/src/crypto/fipsmodule/ec/ec_test.cc b/src/crypto/fipsmodule/ec/ec_test.cc index 71f9fd80..48b60ee9 100644 --- a/src/crypto/fipsmodule/ec/ec_test.cc +++ b/src/crypto/fipsmodule/ec/ec_test.cc @@ -380,6 +380,31 @@ TEST_P(ECCurveTest, MulZero) { << "p * 0 did not return point at infinity."; } +// Test that 10×∞ + G = G. +TEST_P(ECCurveTest, Mul) { + bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); + ASSERT_TRUE(group); + bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get())); + ASSERT_TRUE(p); + bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get())); + ASSERT_TRUE(result); + bssl::UniquePtr<BIGNUM> n(BN_new()); + ASSERT_TRUE(n); + ASSERT_TRUE(EC_POINT_set_to_infinity(group.get(), p.get())); + ASSERT_TRUE(BN_set_word(n.get(), 10)); + + // First check that 10×∞ = ∞. + ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), nullptr, p.get(), n.get(), + nullptr)); + EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), result.get())); + + // Now check that 10×∞ + G = G. + const EC_POINT *generator = EC_GROUP_get0_generator(group.get()); + ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), BN_value_one(), p.get(), + n.get(), nullptr)); + EXPECT_EQ(0, EC_POINT_cmp(group.get(), result.get(), generator, 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/example_mul.c b/src/crypto/fipsmodule/ec/example_mul.c deleted file mode 100644 index a2bdd527..00000000 --- a/src/crypto/fipsmodule/ec/example_mul.c +++ /dev/null @@ -1,133 +0,0 @@ -/* Originally written by Bodo Moeller for the OpenSSL project. - * ==================================================================== - * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * - * Portions of the attached software ("Contribution") are developed by - * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. - * - * The Contribution is licensed pursuant to the OpenSSL open source - * license provided above. - * - * The elliptic curve binary polynomial software is originally written by - * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems - * Laboratories. */ - -#include <stdio.h> - -#include <openssl/bn.h> -#include <openssl/crypto.h> -#include <openssl/ec.h> -#include <openssl/nid.h> - - -static int example_EC_POINT_mul(void) { - /* This example ensures that 10×∞ + G = G, in P-256. */ - EC_GROUP *group = NULL; - EC_POINT *p = NULL, *result = NULL; - BIGNUM *n = NULL; - int ret = 0; - const EC_POINT *generator; - - group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); - p = EC_POINT_new(group); - result = EC_POINT_new(group); - n = BN_new(); - - if (p == NULL || - result == NULL || - group == NULL || - n == NULL || - !EC_POINT_set_to_infinity(group, p) || - !BN_set_word(n, 10)) { - goto err; - } - - /* First check that 10×∞ = ∞. */ - if (!EC_POINT_mul(group, result, NULL, p, n, NULL) || - !EC_POINT_is_at_infinity(group, result)) { - goto err; - } - - generator = EC_GROUP_get0_generator(group); - - /* Now check that 10×∞ + G = G. */ - if (!EC_POINT_mul(group, result, BN_value_one(), p, n, NULL) || - EC_POINT_cmp(group, result, generator, NULL) != 0) { - goto err; - } - - ret = 1; - -err: - BN_free(n); - EC_POINT_free(result); - EC_POINT_free(p); - EC_GROUP_free(group); - - return ret; -} - -int main(void) { - CRYPTO_library_init(); - - if (!example_EC_POINT_mul()) { - fprintf(stderr, "failed\n"); - return 1; - } - - printf("PASS\n"); - return 0; -} diff --git a/src/crypto/fipsmodule/ec/p224-64.c b/src/crypto/fipsmodule/ec/p224-64.c index 31097d43..67dfcc85 100644 --- a/src/crypto/fipsmodule/ec/p224-64.c +++ b/src/crypto/fipsmodule/ec/p224-64.c @@ -181,12 +181,18 @@ static const p224_felem g_p224_pre_comp[2][16][3] = { {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e}, {1, 0, 0, 0}}}}; +static uint64_t p224_load_u64(const uint8_t in[8]) { + uint64_t ret; + OPENSSL_memcpy(&ret, in, sizeof(ret)); + return ret; +} + /* Helper functions to convert field elements to/from internal representation */ static void p224_bin28_to_felem(p224_felem out, const uint8_t in[28]) { - out[0] = *((const uint64_t *)(in)) & 0x00ffffffffffffff; - out[1] = (*((const uint64_t *)(in + 7))) & 0x00ffffffffffffff; - out[2] = (*((const uint64_t *)(in + 14))) & 0x00ffffffffffffff; - out[3] = (*((const uint64_t *)(in + 20))) >> 8; + out[0] = p224_load_u64(in) & 0x00ffffffffffffff; + out[1] = p224_load_u64(in + 7) & 0x00ffffffffffffff; + out[2] = p224_load_u64(in + 14) & 0x00ffffffffffffff; + out[3] = p224_load_u64(in + 20) >> 8; } static void p224_felem_to_bin28(uint8_t out[28], const p224_felem in) { diff --git a/src/crypto/fipsmodule/ec/p256-64.c b/src/crypto/fipsmodule/ec/p256-64.c index de1edc2b..8952aa2e 100644 --- a/src/crypto/fipsmodule/ec/p256-64.c +++ b/src/crypto/fipsmodule/ec/p256-64.c @@ -71,22 +71,32 @@ static const uint64_t kPrime[4] = {0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul}; static const uint64_t bottom63bits = 0x7ffffffffffffffful; +static uint64_t load_u64(const uint8_t in[8]) { + uint64_t ret; + OPENSSL_memcpy(&ret, in, sizeof(ret)); + return ret; +} + +static void store_u64(uint8_t out[8], uint64_t in) { + OPENSSL_memcpy(out, &in, sizeof(in)); +} + /* bin32_to_felem takes a little-endian byte array and converts it into felem * form. This assumes that the CPU is little-endian. */ static void bin32_to_felem(felem out, const uint8_t in[32]) { - out[0] = *((const uint64_t *)&in[0]); - out[1] = *((const uint64_t *)&in[8]); - out[2] = *((const uint64_t *)&in[16]); - out[3] = *((const uint64_t *)&in[24]); + out[0] = load_u64(&in[0]); + out[1] = load_u64(&in[8]); + out[2] = load_u64(&in[16]); + out[3] = load_u64(&in[24]); } /* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian, * 32 byte array. This assumes that the CPU is little-endian. */ static void smallfelem_to_bin32(uint8_t out[32], const smallfelem in) { - *((uint64_t *)&out[0]) = in[0]; - *((uint64_t *)&out[8]) = in[1]; - *((uint64_t *)&out[16]) = in[2]; - *((uint64_t *)&out[24]) = in[3]; + store_u64(&out[0], in[0]); + store_u64(&out[8], in[1]); + store_u64(&out[16], in[2]); + store_u64(&out[24], in[3]); } /* To preserve endianness when using BN_bn2bin and BN_bin2bn. */ diff --git a/src/crypto/x509v3/CMakeLists.txt b/src/crypto/x509v3/CMakeLists.txt index cf2474a4..b2eb6189 100644 --- a/src/crypto/x509v3/CMakeLists.txt +++ b/src/crypto/x509v3/CMakeLists.txt @@ -42,25 +42,3 @@ add_library( v3_sxnet.c v3_utl.c ) - -add_executable( - v3name_test - - v3name_test.c - - $<TARGET_OBJECTS:test_support> -) - -target_link_libraries(v3name_test crypto) -add_dependencies(all_tests v3name_test) - -add_executable( - tab_test - - tab_test.c - - $<TARGET_OBJECTS:test_support> -) - -target_link_libraries(tab_test crypto) -add_dependencies(all_tests tab_test) diff --git a/src/crypto/x509v3/ext_dat.h b/src/crypto/x509v3/ext_dat.h index 9ece19c5..78fa7936 100644 --- a/src/crypto/x509v3/ext_dat.h +++ b/src/crypto/x509v3/ext_dat.h @@ -56,6 +56,10 @@ /* This file contains a table of "standard" extensions */ +#if defined(__cplusplus) +extern "C" { +#endif + extern const X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, v3_sinfo; @@ -133,3 +137,7 @@ static const X509V3_EXT_METHOD *const standard_exts[] = { /* Number of standard extensions */ #define STANDARD_EXTENSION_COUNT (sizeof(standard_exts)/sizeof(X509V3_EXT_METHOD *)) + +#if defined(__cplusplus) +} /* extern C */ +#endif diff --git a/src/crypto/x509v3/tab_test.c b/src/crypto/x509v3/tab_test.cc index 19005474..bf91a265 100644 --- a/src/crypto/x509v3/tab_test.c +++ b/src/crypto/x509v3/tab_test.cc @@ -57,52 +57,22 @@ * */ -/* - * Simple program to check the ext_dat.h is correct and print out problems if - * it is not. - */ +#if !defined(BORINGSSL_SHARED_LIBRARY) -#include <stdio.h> +#include <gtest/gtest.h> -#include <openssl/base.h> -#include <openssl/crypto.h> -#include <openssl/obj.h> #include <openssl/x509v3.h> -#if !defined(BORINGSSL_SHARED_LIBRARY) -# include "ext_dat.h" -#endif +#include "../internal.h" +#include "ext_dat.h" -int main(void) -{ -#if !defined(BORINGSSL_SHARED_LIBRARY) - unsigned i; - int prev = -1, bad = 0; - const X509V3_EXT_METHOD *const *tmp; - CRYPTO_library_init(); - i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *); - if (i != STANDARD_EXTENSION_COUNT) - fprintf(stderr, "Extension number invalid expecting %d\n", i); - tmp = standard_exts; - for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) { - if ((*tmp)->ext_nid < prev) - bad = 1; - prev = (*tmp)->ext_nid; - - } - if (bad) { - tmp = standard_exts; - fprintf(stderr, "Extensions out of order!\n"); - for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) - printf("%d : %s\n", (*tmp)->ext_nid, OBJ_nid2sn((*tmp)->ext_nid)); - return 1; - } else { - printf("PASS\n"); - return 0; - } -#else - /* TODO(davidben): Fix this test in the shared library build. */ - printf("PASS\n"); - return 0; -#endif +// Check ext_data.h is correct. +TEST(X509V3Test, TabTest) { + EXPECT_EQ(OPENSSL_ARRAY_SIZE(standard_exts), STANDARD_EXTENSION_COUNT); + for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(standard_exts); i++) { + SCOPED_TRACE(i); + EXPECT_LT(standard_exts[i-1]->ext_nid, standard_exts[i]->ext_nid); + } } + +#endif // !BORINGSSL_SHARED_LIBRARY diff --git a/src/crypto/x509v3/v3name_test.c b/src/crypto/x509v3/v3name_test.cc index 959b924d..0736120f 100644 --- a/src/crypto/x509v3/v3name_test.c +++ b/src/crypto/x509v3/v3name_test.cc @@ -57,6 +57,8 @@ #include <stdarg.h> #include <string.h> +#include <gtest/gtest.h> + #include <openssl/crypto.h> #include <openssl/mem.h> #include <openssl/x509.h> @@ -335,7 +337,7 @@ static void run_cert(X509 *crt, const char *nameincert, while (*pname) { int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0; size_t namelen = strlen(*pname); - char *name = malloc(namelen); + char *name = (char *)malloc(namelen); int match, ret; OPENSSL_memcpy(name, *pname, namelen); @@ -383,31 +385,19 @@ static void run_cert(X509 *crt, const char *nameincert, } } -int main(void) -{ - CRYPTO_library_init(); - +// TOOD(davidben): Convert this test to GTest more thoroughly. +TEST(X509V3Test, NameTest) { const struct set_name_fn *pfn = name_fns; while (pfn->name) { const char *const *pname = names; while (*pname) { - X509 *crt = make_cert(); - if (crt == NULL) { - fprintf(stderr, "make_cert failed\n"); - return 1; - } - if (!pfn->fn(crt, *pname)) { - fprintf(stderr, "X509 name setting failed\n"); - return 1; - } - run_cert(crt, *pname, pfn); - X509_free(crt); + bssl::UniquePtr<X509> crt(make_cert()); + ASSERT_TRUE(crt); + ASSERT_TRUE(pfn->fn(crt.get(), *pname)); + run_cert(crt.get(), *pname, pfn); ++pname; } ++pfn; } - if (errors == 0) { - printf("PASS\n"); - } - return errors > 0 ? 1 : 0; + EXPECT_EQ(0, errors); } diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h index 5ebdade3..0d2068fa 100644 --- a/src/include/openssl/bn.h +++ b/src/include/openssl/bn.h @@ -938,6 +938,7 @@ OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l); #if defined(__cplusplus) } /* extern C */ +#if !defined(OPENSSL_NO_CXX) extern "C++" { namespace bssl { @@ -946,9 +947,22 @@ BORINGSSL_MAKE_DELETER(BIGNUM, BN_free) BORINGSSL_MAKE_DELETER(BN_CTX, BN_CTX_free) BORINGSSL_MAKE_DELETER(BN_MONT_CTX, BN_MONT_CTX_free) +class BN_CTXScope { + public: + BN_CTXScope(BN_CTX *ctx) : ctx_(ctx) { BN_CTX_start(ctx_); } + ~BN_CTXScope() { BN_CTX_end(ctx_); } + + private: + BN_CTX *ctx_; + + BN_CTXScope(BN_CTXScope &) = delete; + BN_CTXScope &operator=(BN_CTXScope &) = delete; +}; + } // namespace bssl } /* extern C++ */ +#endif #endif diff --git a/src/include/openssl/pem.h b/src/include/openssl/pem.h index ae6c23c0..4868e12f 100644 --- a/src/include/openssl/pem.h +++ b/src/include/openssl/pem.h @@ -125,7 +125,7 @@ extern "C" { #define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\ { \ -return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \ +return (type *)PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \ } #define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ @@ -161,7 +161,7 @@ OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ #define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ OPENSSL_EXPORT type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\ { \ -return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \ +return (type *)PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \ } #define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h index 59fbeb87..16aeaff0 100644 --- a/src/include/openssl/ssl.h +++ b/src/include/openssl/ssl.h @@ -492,8 +492,7 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code); /* SSL_ERROR_PENDING_CERTIFICATE indicates the operation failed because the * early callback indicated certificate lookup was incomplete. The caller may - * retry the operation when lookup has completed. Note: when the operation is - * retried, the early callback will not be called a second time. + * retry the operation when lookup has completed. * * See also |SSL_CTX_set_select_certificate_cb|. */ #define SSL_ERROR_PENDING_CERTIFICATE 12 @@ -578,6 +577,8 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl); #define DTLS1_2_VERSION 0xfefd #define TLS1_3_DRAFT_VERSION 0x7f12 +#define TLS1_3_EXPERIMENT_VERSION 0x7e01 +#define TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION 0x7a12 /* 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 @@ -1874,12 +1875,17 @@ OPENSSL_EXPORT void SSL_CTX_flush_sessions(SSL_CTX *ctx, uint64_t time); * unset), the callback is not called. * * The callback is passed a reference to |session|. It returns one if it takes - * ownership and zero otherwise. + * ownership (and then calls |SSL_SESSION_free| when done) and zero otherwise. A + * consumer which places |session| into an in-memory cache will likely return + * one, with the cache calling |SSL_SESSION_free|. A consumer which serializes + * |session| with |SSL_SESSION_to_bytes| may not need to retain |session| and + * will likely return zero. Returning one is equivalent to calling + * |SSL_SESSION_up_ref| and then returning zero. * * Note: For a client, the callback may be called on abbreviated handshakes if a * ticket is renewed. Further, it may not be called until some time after * |SSL_do_handshake| or |SSL_connect| completes if False Start is enabled. Thus - * it's recommended to use this callback over checking |SSL_session_reused| on + * it's recommended to use this callback over calling |SSL_get_session| on * handshake completion. */ OPENSSL_EXPORT void SSL_CTX_sess_set_new_cb( SSL_CTX *ctx, int (*new_session_cb)(SSL *ssl, SSL_SESSION *session)); @@ -3131,6 +3137,24 @@ OPENSSL_EXPORT int SSL_renegotiate_pending(SSL *ssl); * performed by |ssl|. This includes the pending renegotiation, if any. */ OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl); +enum tls13_variant_t { + tls13_default = 0, + tls13_experiment = 1, + tls13_record_type_experiment = 2, +}; + +/* SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the + * server, if |variant| is not |tls13_default|, all variants are enabled. On the + * client, only the configured variant is enabled. */ +OPENSSL_EXPORT void SSL_CTX_set_tls13_variant(SSL_CTX *ctx, + enum tls13_variant_t variant); + +/* SSL_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the + * server, if |variant| is not |tls13_default|, all variants are enabled. On the + * client, only the configured variant is enabled. */ +OPENSSL_EXPORT void SSL_set_tls13_variant(SSL *ssl, + enum tls13_variant_t variant); + /* SSL_MAX_CERT_LIST_DEFAULT is the default maximum length, in bytes, of a peer * certificate chain. */ #define SSL_MAX_CERT_LIST_DEFAULT (1024 * 100) @@ -4119,6 +4143,10 @@ struct ssl_ctx_st { * and is further constrainted by |SSL_OP_NO_*|. */ uint16_t conf_min_version; + /* tls13_variant is the variant of TLS 1.3 we are using for this + * configuration. */ + enum tls13_variant_t tls13_variant; + struct ssl_cipher_preference_list_st *cipher_list; X509_STORE *cert_store; diff --git a/src/include/openssl/ssl3.h b/src/include/openssl/ssl3.h index 98648c4c..2b241ba8 100644 --- a/src/include/openssl/ssl3.h +++ b/src/include/openssl/ssl3.h @@ -272,6 +272,7 @@ OPENSSL_COMPILE_ASSERT( #define SSL3_RT_ALERT 21 #define SSL3_RT_HANDSHAKE 22 #define SSL3_RT_APPLICATION_DATA 23 +#define SSL3_RT_PLAINTEXT_HANDSHAKE 24 /* Pseudo content type for SSL/TLS header info */ #define SSL3_RT_HEADER 0x100 diff --git a/src/ssl/CMakeLists.txt b/src/ssl/CMakeLists.txt index 0c09443d..b6f4451c 100644 --- a/src/ssl/CMakeLists.txt +++ b/src/ssl/CMakeLists.txt @@ -3,42 +3,41 @@ include_directories(../include) add_library( ssl - bio_ssl.c - custom_extensions.c - d1_both.c - d1_lib.c - d1_pkt.c - d1_srtp.c - dtls_method.c - dtls_record.c - handshake_client.c - handshake_server.c - s3_both.c - s3_lib.c - s3_pkt.c - ssl_aead_ctx.c - ssl_asn1.c - ssl_buffer.c - ssl_cert.c - ssl_cipher.c - ssl_ecdh.c - ssl_file.c - ssl_lib.c - ssl_privkey.c - ssl_privkey_cc.cc - ssl_session.c - ssl_stat.c - ssl_transcript.c - ssl_versions.c - ssl_x509.c - t1_enc.c - t1_lib.c - tls_method.c - tls_record.c - tls13_both.c - tls13_client.c - tls13_enc.c - tls13_server.c + bio_ssl.cc + custom_extensions.cc + d1_both.cc + d1_lib.cc + d1_pkt.cc + d1_srtp.cc + dtls_method.cc + dtls_record.cc + handshake_client.cc + handshake_server.cc + s3_both.cc + s3_lib.cc + s3_pkt.cc + ssl_aead_ctx.cc + ssl_asn1.cc + ssl_buffer.cc + ssl_cert.cc + ssl_cipher.cc + ssl_ecdh.cc + ssl_file.cc + ssl_lib.cc + ssl_privkey.cc + ssl_session.cc + ssl_stat.cc + ssl_transcript.cc + ssl_versions.cc + ssl_x509.cc + t1_enc.cc + t1_lib.cc + tls_method.cc + tls_record.cc + tls13_both.cc + tls13_client.cc + tls13_enc.cc + tls13_server.cc ) target_link_libraries(ssl crypto) diff --git a/src/ssl/bio_ssl.c b/src/ssl/bio_ssl.cc index ad8f5d8f..61afee56 100644 --- a/src/ssl/bio_ssl.c +++ b/src/ssl/bio_ssl.cc @@ -12,8 +12,12 @@ #include <openssl/bio.h> +static SSL *get_ssl(BIO *bio) { + return reinterpret_cast<SSL *>(bio->ptr); +} + static int ssl_read(BIO *bio, char *out, int outl) { - SSL *ssl = bio->ptr; + SSL *ssl = get_ssl(bio); if (ssl == NULL) { return 0; } @@ -53,7 +57,7 @@ static int ssl_read(BIO *bio, char *out, int outl) { } static int ssl_write(BIO *bio, const char *out, int outl) { - SSL *ssl = bio->ptr; + SSL *ssl = get_ssl(bio); if (ssl == NULL) { return 0; } @@ -87,7 +91,7 @@ static int ssl_write(BIO *bio, const char *out, int outl) { } static long ssl_ctrl(BIO *bio, int cmd, long num, void *ptr) { - SSL *ssl = bio->ptr; + SSL *ssl = get_ssl(bio); if (ssl == NULL && cmd != BIO_C_SET_SSL) { return 0; } @@ -134,7 +138,7 @@ static int ssl_new(BIO *bio) { } static int ssl_free(BIO *bio) { - SSL *ssl = bio->ptr; + SSL *ssl = get_ssl(bio); if (ssl == NULL) { return 1; @@ -149,7 +153,7 @@ static int ssl_free(BIO *bio) { } static long ssl_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) { - SSL *ssl = bio->ptr; + SSL *ssl = get_ssl(bio); if (ssl == NULL) { return 0; } diff --git a/src/ssl/custom_extensions.c b/src/ssl/custom_extensions.cc index ac185178..f438f739 100644 --- a/src/ssl/custom_extensions.c +++ b/src/ssl/custom_extensions.cc @@ -214,7 +214,8 @@ static int custom_ext_append(STACK_OF(SSL_CUSTOM_EXTENSION) **stack, return 0; } - SSL_CUSTOM_EXTENSION *ext = OPENSSL_malloc(sizeof(SSL_CUSTOM_EXTENSION)); + SSL_CUSTOM_EXTENSION *ext = + (SSL_CUSTOM_EXTENSION *)OPENSSL_malloc(sizeof(SSL_CUSTOM_EXTENSION)); if (ext == NULL) { return 0; } diff --git a/src/ssl/d1_both.c b/src/ssl/d1_both.cc index 44e3f2ef..ee0ec4fd 100644 --- a/src/ssl/d1_both.c +++ b/src/ssl/d1_both.cc @@ -122,7 +122,6 @@ #include <openssl/evp.h> #include <openssl/mem.h> #include <openssl/rand.h> -#include <openssl/type_check.h> #include "../crypto/internal.h" #include "internal.h" @@ -153,7 +152,7 @@ static void dtls1_hm_fragment_free(hm_fragment *frag) { } static hm_fragment *dtls1_hm_fragment_new(const struct hm_header_st *msg_hdr) { - hm_fragment *frag = OPENSSL_malloc(sizeof(hm_fragment)); + hm_fragment *frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment)); if (frag == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; @@ -164,7 +163,8 @@ static hm_fragment *dtls1_hm_fragment_new(const struct hm_header_st *msg_hdr) { frag->msg_len = msg_hdr->msg_len; /* Allocate space for the reassembled message and fill in the header. */ - frag->data = OPENSSL_malloc(DTLS1_HM_HEADER_LENGTH + msg_hdr->msg_len); + frag->data = + (uint8_t *)OPENSSL_malloc(DTLS1_HM_HEADER_LENGTH + msg_hdr->msg_len); if (frag->data == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -191,7 +191,7 @@ static hm_fragment *dtls1_hm_fragment_new(const struct hm_header_st *msg_hdr) { goto err; } size_t bitmask_len = (msg_hdr->msg_len + 7) / 8; - frag->reassembly = OPENSSL_malloc(bitmask_len); + frag->reassembly = (uint8_t *)OPENSSL_malloc(bitmask_len); if (frag->reassembly == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -537,9 +537,9 @@ int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg, * it takes ownership of |data| and releases it with |OPENSSL_free| when * done. */ static int add_outgoing(SSL *ssl, int is_ccs, uint8_t *data, size_t len) { - OPENSSL_COMPILE_ASSERT(SSL_MAX_HANDSHAKE_FLIGHT < - (1 << 8 * sizeof(ssl->d1->outgoing_messages_len)), - outgoing_messages_len_is_too_small); + static_assert(SSL_MAX_HANDSHAKE_FLIGHT < + (1 << 8 * sizeof(ssl->d1->outgoing_messages_len)), + "outgoing_messages_len is too small"); if (ssl->d1->outgoing_messages_len >= SSL_MAX_HANDSHAKE_FLIGHT) { assert(0); OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); @@ -760,7 +760,7 @@ int dtls1_flush_flight(SSL *ssl) { dtls1_update_mtu(ssl); int ret = -1; - uint8_t *packet = OPENSSL_malloc(ssl->d1->mtu); + uint8_t *packet = (uint8_t *)OPENSSL_malloc(ssl->d1->mtu); if (packet == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; diff --git a/src/ssl/d1_lib.c b/src/ssl/d1_lib.cc index ef15252f..0074855b 100644 --- a/src/ssl/d1_lib.c +++ b/src/ssl/d1_lib.cc @@ -78,12 +78,10 @@ #define DTLS1_MAX_TIMEOUTS 12 int dtls1_new(SSL *ssl) { - DTLS1_STATE *d1; - if (!ssl3_new(ssl)) { return 0; } - d1 = OPENSSL_malloc(sizeof *d1); + DTLS1_STATE *d1 = (DTLS1_STATE *)OPENSSL_malloc(sizeof *d1); if (d1 == NULL) { ssl3_free(ssl); return 0; diff --git a/src/ssl/d1_pkt.c b/src/ssl/d1_pkt.cc index e2c7315d..1ae55ebb 100644 --- a/src/ssl/d1_pkt.c +++ b/src/ssl/d1_pkt.cc @@ -171,7 +171,7 @@ again: /* Impossible in DTLS. */ break; - case ssl_open_record_success: + case ssl_open_record_success: { if (CBS_len(&body) > 0xffff) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return -1; @@ -182,6 +182,7 @@ again: rr->length = (uint16_t)CBS_len(&body); rr->data = (uint8_t *)CBS_data(&body); return 1; + } case ssl_open_record_discard: goto again; diff --git a/src/ssl/d1_srtp.c b/src/ssl/d1_srtp.cc index 10853777..10853777 100644 --- a/src/ssl/d1_srtp.c +++ b/src/ssl/d1_srtp.cc diff --git a/src/ssl/dtls_method.c b/src/ssl/dtls_method.cc index dd8d7865..dd8d7865 100644 --- a/src/ssl/dtls_method.c +++ b/src/ssl/dtls_method.cc diff --git a/src/ssl/dtls_record.c b/src/ssl/dtls_record.cc index 879706df..879706df 100644 --- a/src/ssl/dtls_record.c +++ b/src/ssl/dtls_record.cc diff --git a/src/ssl/handshake_client.c b/src/ssl/handshake_client.cc index c772f771..9efbf0ad 100644 --- a/src/ssl/handshake_client.c +++ b/src/ssl/handshake_client.cc @@ -647,29 +647,43 @@ static int ssl_write_client_cipher_list(SSL_HANDSHAKE *hs, CBB *out) { int ssl_write_client_hello(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - CBB cbb, body; - if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CLIENT_HELLO)) { - goto err; + bssl::ScopedCBB cbb; + CBB body; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO)) { + return 0; } /* Renegotiations do not participate in session resumption. */ - int has_session = ssl->session != NULL && - !ssl->s3->initial_handshake_complete; + int has_session_id = ssl->session != NULL && + !ssl->s3->initial_handshake_complete && + ssl->session->session_id_length > 0; CBB child; if (!CBB_add_u16(&body, hs->client_version) || !CBB_add_bytes(&body, ssl->s3->client_random, SSL3_RANDOM_SIZE) || - !CBB_add_u8_length_prefixed(&body, &child) || - (has_session && - !CBB_add_bytes(&child, ssl->session->session_id, - ssl->session->session_id_length))) { - goto err; + !CBB_add_u8_length_prefixed(&body, &child)) { + return 0; + } + + if (has_session_id) { + if (!CBB_add_bytes(&child, ssl->session->session_id, + ssl->session->session_id_length)) { + return 0; + } + } else { + /* In TLS 1.3 experimental encodings, send a fake placeholder session ID + * when we do not otherwise have one to send. */ + if (hs->max_version >= TLS1_3_VERSION && + ssl->tls13_variant == tls13_experiment && + !CBB_add_bytes(&child, hs->session_id, hs->session_id_len)) { + return 0; + } } if (SSL_is_dtls(ssl)) { if (!CBB_add_u8_length_prefixed(&body, &child) || !CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) { - goto err; + return 0; } } @@ -679,13 +693,13 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { !CBB_add_u8(&body, 1 /* one compression method */) || !CBB_add_u8(&body, 0 /* null compression */) || !ssl_add_clienthello_tlsext(hs, &body, header_len + CBB_len(&body))) { - goto err; + return 0; } uint8_t *msg = NULL; size_t len; - if (!ssl->method->finish_message(ssl, &cbb, &msg, &len)) { - goto err; + if (!ssl->method->finish_message(ssl, cbb.get(), &msg, &len)) { + return 0; } /* Now that the length prefixes have been computed, fill in the placeholder @@ -693,14 +707,10 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { if (hs->needs_psk_binder && !tls13_write_psk_binder(hs, msg, len)) { OPENSSL_free(msg); - goto err; + return 0; } return ssl->method->add_message(ssl, msg, len); - - err: - CBB_cleanup(&cbb); - return 0; } static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) { @@ -748,6 +758,14 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) { return -1; } + /* Initialize a random session ID for the experimental TLS 1.3 variant. */ + if (ssl->tls13_variant == tls13_experiment) { + hs->session_id_len = sizeof(hs->session_id); + if (!RAND_bytes(hs->session_id, hs->session_id_len)) { + return -1; + } + } + if (!ssl_write_client_hello(hs)) { return -1; } @@ -788,12 +806,80 @@ static int dtls1_get_hello_verify_request(SSL_HANDSHAKE *hs) { return 1; } -static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { +static int parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out) { SSL *const ssl = hs->ssl; - CBS server_hello, server_random, session_id; - uint16_t server_version, cipher_suite; - uint8_t compression_method; + if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO && + ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + return 0; + } + + CBS server_hello; + CBS_init(&server_hello, ssl->init_msg, ssl->init_num); + if (!CBS_get_u16(&server_hello, out)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return 0; + } + + /* The server version may also be in the supported_versions extension if + * applicable. */ + if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO || + *out != TLS1_2_VERSION) { + return 1; + } + + uint8_t sid_length; + if (!CBS_skip(&server_hello, SSL3_RANDOM_SIZE) || + !CBS_get_u8(&server_hello, &sid_length) || + !CBS_skip(&server_hello, sid_length + 2 /* cipher_suite */ + + 1 /* compression_method */)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return 0; + } + /* The extensions block may not be present. */ + if (CBS_len(&server_hello) == 0) { + return 1; + } + + CBS extensions; + if (!CBS_get_u16_length_prefixed(&server_hello, &extensions) || + CBS_len(&server_hello) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return 0; + } + + int have_supported_versions; + CBS supported_versions; + const SSL_EXTENSION_TYPE ext_types[] = { + {TLSEXT_TYPE_supported_versions, &have_supported_versions, + &supported_versions}, + }; + + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!ssl_parse_extensions(&extensions, &alert, ext_types, + OPENSSL_ARRAY_SIZE(ext_types), + 1 /* ignore unknown */)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); + return 0; + } + + if (have_supported_versions && + (!CBS_get_u16(&supported_versions, out) || + CBS_len(&supported_versions) != 0)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return 0; + } + + return 1; +} + +static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { + SSL *const ssl = hs->ssl; int ret = ssl->method->ssl_get_message(ssl); if (ret <= 0) { uint32_t err = ERR_peek_error(); @@ -810,18 +896,8 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { return ret; } - if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO && - ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) { - ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); - return -1; - } - - CBS_init(&server_hello, ssl->init_msg, ssl->init_num); - - if (!CBS_get_u16(&server_hello, &server_version)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + uint16_t server_version; + if (!parse_server_version(hs, &server_version)) { return -1; } @@ -861,7 +937,12 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { return -1; } - if (!CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) || + CBS server_hello, server_random, session_id; + uint16_t cipher_suite; + uint8_t compression_method; + CBS_init(&server_hello, ssl->init_msg, ssl->init_num); + if (!CBS_skip(&server_hello, 2 /* version */) || + !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) || !CBS_get_u8_length_prefixed(&server_hello, &session_id) || CBS_len(&session_id) > SSL3_SESSION_ID_SIZE || !CBS_get_u16(&server_hello, &cipher_suite) || @@ -1431,19 +1512,20 @@ static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs) { return 1; } -OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned), - SIZE_T_IS_SMALLER_THAN_UNSIGNED); +static_assert(sizeof(size_t) >= sizeof(unsigned), + "size_t is smaller than unsigned"); static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - uint8_t *pms = NULL; - size_t pms_len = 0; - CBB cbb, body; - if (!ssl->method->init_message(ssl, &cbb, &body, + bssl::ScopedCBB cbb; + CBB body; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_KEY_EXCHANGE)) { - goto err; + return -1; } + uint8_t *pms = NULL; + size_t pms_len = 0; uint32_t alg_k = hs->new_cipher->algorithm_mkey; uint32_t alg_a = hs->new_cipher->algorithm_auth; @@ -1488,7 +1570,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { /* Depending on the key exchange method, compute |pms| and |pms_len|. */ if (alg_k & SSL_kRSA) { pms_len = SSL_MAX_MASTER_KEY_LENGTH; - pms = OPENSSL_malloc(pms_len); + pms = (uint8_t *)OPENSSL_malloc(pms_len); if (pms == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1551,7 +1633,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { /* For plain PSK, other_secret is a block of 0s with the same length as * the pre-shared key. */ pms_len = psk_len; - pms = OPENSSL_malloc(pms_len); + pms = (uint8_t *)OPENSSL_malloc(pms_len); if (pms == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1589,7 +1671,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { /* The message must be added to the finished hash before calculating the * master secret. */ - if (!ssl_add_message_cbb(ssl, &cbb)) { + if (!ssl_add_message_cbb(ssl, cbb.get())) { goto err; } @@ -1605,7 +1687,6 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { return 1; err: - CBB_cleanup(&cbb); if (pms != NULL) { OPENSSL_cleanse(pms, pms_len); OPENSSL_free(pms); @@ -1617,21 +1698,22 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; assert(ssl_has_private_key(ssl)); - CBB cbb, body, child; - if (!ssl->method->init_message(ssl, &cbb, &body, + bssl::ScopedCBB cbb; + CBB body, child; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE_VERIFY)) { - goto err; + return -1; } uint16_t signature_algorithm; if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) { - goto err; + return -1; } if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { /* Write out the digest type in TLS 1.2. */ if (!CBB_add_u16(&body, signature_algorithm)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return -1; } } @@ -1640,7 +1722,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { uint8_t *ptr; if (!CBB_add_u16_length_prefixed(&body, &child) || !CBB_reserve(&child, &ptr, max_sig_len)) { - goto err; + return -1; } size_t sig_len = max_sig_len; @@ -1649,7 +1731,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { if (ssl3_protocol_version(ssl) == SSL3_VERSION) { if (ssl->cert->key_method != NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY); - goto err; + return -1; } uint8_t digest[EVP_MAX_MD_SIZE]; @@ -1657,7 +1739,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest, &digest_len, hs->new_session, signature_algorithm)) { - goto err; + return -1; } EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL); @@ -1666,7 +1748,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len); EVP_PKEY_CTX_free(pctx); if (!ok) { - goto err; + return -1; } } else { switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len, @@ -1676,25 +1758,21 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { case ssl_private_key_success: break; case ssl_private_key_failure: - goto err; + return -1; case ssl_private_key_retry: ssl->rwstate = SSL_PRIVATE_KEY_OPERATION; - goto err; + return -1; } } if (!CBB_did_write(&child, sig_len) || - !ssl_add_message_cbb(ssl, &cbb)) { - goto err; + !ssl_add_message_cbb(ssl, cbb.get())) { + return -1; } /* The handshake buffer is no longer necessary. */ SSL_TRANSCRIPT_free_buffer(&hs->transcript); return 1; - -err: - CBB_cleanup(&cbb); - return -1; } static int ssl3_send_next_proto(SSL_HANDSHAKE *hs) { diff --git a/src/ssl/handshake_server.c b/src/ssl/handshake_server.cc index 64abd5d2..ee5358c4 100644 --- a/src/ssl/handshake_server.c +++ b/src/ssl/handshake_server.cc @@ -800,9 +800,6 @@ static int ssl3_select_certificate(SSL_HANDSHAKE *hs) { static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - int ret = -1; - SSL_SESSION *session = NULL; - SSL_CLIENT_HELLO client_hello; if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg, ssl->init_num)) { @@ -811,49 +808,52 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { /* Determine whether we are doing session resumption. */ int tickets_supported = 0, renew_ticket = 0; - switch (ssl_get_prev_session(ssl, &session, &tickets_supported, &renew_ticket, - &client_hello)) { + /* TODO(davidben): Switch |ssl_get_prev_session| to take a |bssl::UniquePtr| + * output and simplify this. */ + SSL_SESSION *session_raw = nullptr; + auto session_ret = ssl_get_prev_session(ssl, &session_raw, &tickets_supported, + &renew_ticket, &client_hello); + bssl::UniquePtr<SSL_SESSION> session(session_raw); + switch (session_ret) { case ssl_session_success: break; case ssl_session_error: - goto err; + return -1; case ssl_session_retry: ssl->rwstate = SSL_PENDING_SESSION; - goto err; + return -1; case ssl_session_ticket_retry: ssl->rwstate = SSL_PENDING_TICKET; - goto err; + return -1; } - if (session != NULL) { + if (session) { if (session->extended_master_secret && !hs->extended_master_secret) { /* A ClientHello without EMS that attempts to resume a session with EMS * is fatal to the connection. */ OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - goto err; + return -1; } - if (!ssl_session_is_resumable(hs, session) || + if (!ssl_session_is_resumable(hs, session.get()) || /* If the client offers the EMS extension, but the previous session * didn't use it, then negotiate a new session. */ hs->extended_master_secret != session->extended_master_secret) { - SSL_SESSION_free(session); - session = NULL; + session.reset(); } } - if (session != NULL) { + if (session) { /* Use the old session. */ hs->ticket_expected = renew_ticket; - ssl->session = session; - session = NULL; + ssl->session = session.release(); ssl->s3->session_reused = 1; } else { hs->ticket_expected = tickets_supported; ssl_set_session(ssl, NULL); if (!ssl_get_new_session(hs, 1 /* server */)) { - goto err; + return -1; } /* Clear the session ID if we want the session to be single-use. */ @@ -867,7 +867,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { /* Connection rejected for DOS reasons. */ OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return -1; } if (ssl->session == NULL) { @@ -879,7 +879,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname); if (hs->new_session->tlsext_hostname == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return -1; } } @@ -907,7 +907,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { uint8_t alert = SSL_AD_DECODE_ERROR; if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); - goto err; + return -1; } /* Now that all parameters are known, initialize the handshake hash and hash @@ -916,7 +916,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { hs->new_cipher->algorithm_prf) || !ssl_hash_current_message(hs)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return -1; } /* Release the handshake buffer if client authentication isn't required. */ @@ -924,11 +924,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { SSL_TRANSCRIPT_free_buffer(&hs->transcript); } - ret = 1; - -err: - SSL_SESSION_free(session); - return ret; + return 1; } static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) { @@ -988,32 +984,30 @@ static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) { static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - int ret = -1; - CBB cbb; - CBB_zero(&cbb); + bssl::ScopedCBB cbb; if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) { if (!ssl_has_certificate(ssl)) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET); - goto err; + return -1; } if (!ssl3_output_cert_chain(ssl)) { - goto err; + return -1; } if (hs->certificate_status_expected) { CBB body, ocsp_response; - if (!ssl->method->init_message(ssl, &cbb, &body, + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE_STATUS) || !CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) || !CBB_add_u24_length_prefixed(&body, &ocsp_response) || !CBB_add_bytes(&ocsp_response, CRYPTO_BUFFER_data(ssl->cert->ocsp_response), CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) || - !ssl_add_message_cbb(ssl, &cbb)) { + !ssl_add_message_cbb(ssl, cbb.get())) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return -1; } } } @@ -1027,20 +1021,20 @@ static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) { /* Pre-allocate enough room to comfortably fit an ECDHE public key. Prepend * the client and server randoms for the signing transcript. */ CBB child; - if (!CBB_init(&cbb, SSL3_RANDOM_SIZE * 2 + 128) || - !CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) || - !CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE)) { - goto err; + if (!CBB_init(cbb.get(), SSL3_RANDOM_SIZE * 2 + 128) || + !CBB_add_bytes(cbb.get(), ssl->s3->client_random, SSL3_RANDOM_SIZE) || + !CBB_add_bytes(cbb.get(), ssl->s3->server_random, SSL3_RANDOM_SIZE)) { + return -1; } /* PSK ciphers begin with an identity hint. */ if (alg_a & SSL_aPSK) { size_t len = (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint); - if (!CBB_add_u16_length_prefixed(&cbb, &child) || + if (!CBB_add_u16_length_prefixed(cbb.get(), &child) || !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint, len)) { - goto err; + return -1; } } @@ -1050,32 +1044,28 @@ static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) { if (!tls1_get_shared_group(hs, &group_id)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - goto err; - } + return -1; + } hs->new_session->group_id = group_id; /* Set up ECDH, generate a key, and emit the public half. */ if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) || - !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) || - !CBB_add_u16(&cbb, group_id) || - !CBB_add_u8_length_prefixed(&cbb, &child) || + !CBB_add_u8(cbb.get(), NAMED_CURVE_TYPE) || + !CBB_add_u16(cbb.get(), group_id) || + !CBB_add_u8_length_prefixed(cbb.get(), &child) || !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) { - goto err; + return -1; } } else { assert(alg_k & SSL_kPSK); } - if (!CBB_finish(&cbb, &hs->server_params, &hs->server_params_len)) { - goto err; + if (!CBB_finish(cbb.get(), &hs->server_params, &hs->server_params_len)) { + return -1; } } - ret = 1; - -err: - CBB_cleanup(&cbb); - return ret; + return 1; } static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) { @@ -1348,7 +1338,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { /* Allocate a buffer large enough for an RSA decryption. */ const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey); - decrypt_buf = OPENSSL_malloc(rsa_size); + decrypt_buf = (uint8_t *)OPENSSL_malloc(rsa_size); if (decrypt_buf == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1379,7 +1369,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { /* Prepare a random premaster, to be used on invalid padding. See RFC 5246, * section 7.4.7.1. */ premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH; - premaster_secret = OPENSSL_malloc(premaster_secret_len); + premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len); if (premaster_secret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1476,7 +1466,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { /* In plain PSK, other_secret is a block of 0s with the same length as the * pre-shared key. */ premaster_secret_len = psk_len; - premaster_secret = OPENSSL_malloc(premaster_secret_len); + premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len); if (premaster_secret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; diff --git a/src/ssl/internal.h b/src/ssl/internal.h index f6cea7ab..6b880701 100644 --- a/src/ssl/internal.h +++ b/src/ssl/internal.h @@ -217,38 +217,38 @@ uint16_t ssl3_protocol_version(const SSL *ssl); /* Cipher suites. */ /* Bits for |algorithm_mkey| (key exchange algorithm). */ -#define SSL_kRSA 0x00000001L -#define SSL_kECDHE 0x00000002L +#define SSL_kRSA 0x00000001u +#define SSL_kECDHE 0x00000002u /* SSL_kPSK is only set for plain PSK, not ECDHE_PSK. */ -#define SSL_kPSK 0x00000004L -#define SSL_kGENERIC 0x00000008L +#define SSL_kPSK 0x00000004u +#define SSL_kGENERIC 0x00000008u /* Bits for |algorithm_auth| (server authentication). */ -#define SSL_aRSA 0x00000001L -#define SSL_aECDSA 0x00000002L +#define SSL_aRSA 0x00000001u +#define SSL_aECDSA 0x00000002u /* SSL_aPSK is set for both PSK and ECDHE_PSK. */ -#define SSL_aPSK 0x00000004L -#define SSL_aGENERIC 0x00000008L +#define SSL_aPSK 0x00000004u +#define SSL_aGENERIC 0x00000008u #define SSL_aCERT (SSL_aRSA | SSL_aECDSA) /* Bits for |algorithm_enc| (symmetric encryption). */ -#define SSL_3DES 0x00000001L -#define SSL_AES128 0x00000002L -#define SSL_AES256 0x00000004L -#define SSL_AES128GCM 0x00000008L -#define SSL_AES256GCM 0x00000010L -#define SSL_eNULL 0x00000020L -#define SSL_CHACHA20POLY1305 0x00000040L +#define SSL_3DES 0x00000001u +#define SSL_AES128 0x00000002u +#define SSL_AES256 0x00000004u +#define SSL_AES128GCM 0x00000008u +#define SSL_AES256GCM 0x00000010u +#define SSL_eNULL 0x00000020u +#define SSL_CHACHA20POLY1305 0x00000040u #define SSL_AES (SSL_AES128 | SSL_AES256 | SSL_AES128GCM | SSL_AES256GCM) /* Bits for |algorithm_mac| (symmetric authentication). */ -#define SSL_SHA1 0x00000001L -#define SSL_SHA256 0x00000002L -#define SSL_SHA384 0x00000004L +#define SSL_SHA1 0x00000001u +#define SSL_SHA256 0x00000002u +#define SSL_SHA384 0x00000004u /* SSL_AEAD is set for all AEADs. */ -#define SSL_AEAD 0x00000008L +#define SSL_AEAD 0x00000008u /* Bits for |algorithm_prf| (handshake digest). */ #define SSL_HANDSHAKE_MAC_DEFAULT 0x1 @@ -447,6 +447,13 @@ size_t SSL_AEAD_CTX_explicit_nonce_len(const SSL_AEAD_CTX *ctx); * |SSL_AEAD_CTX_seal|. |ctx| may be NULL to denote the null cipher. */ size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *ctx); +/* SSL_AEAD_CTX_max_suffix_len returns the maximum suffix length written by + * |SSL_AEAD_CTX_seal_scatter|. |ctx| may be NULL to denote the null cipher. + * |extra_in_len| should equal the argument of the same name passed to + * |SSL_AEAD_CTX_seal_scatter|. */ +size_t SSL_AEAD_CTX_max_suffix_len(const SSL_AEAD_CTX *ctx, + size_t extra_in_len); + /* SSL_AEAD_CTX_open authenticates and decrypts |in_len| bytes from |in| * in-place. On success, it sets |*out| to the plaintext in |in| and returns * one. Otherwise, it returns zero. |ctx| may be NULL to denote the null cipher. @@ -465,6 +472,31 @@ int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, const uint8_t seqnum[8], const uint8_t *in, size_t in_len); +/* SSL_AEAD_CTX_seal_scatter encrypts and authenticates |in_len| bytes from |in| + * and splits the result between |out_prefix|, |out| and |out_suffix|. It + * returns one on success and zero on error. |ctx| may be NULL to denote the + * null cipher. + * + * On successful return, exactly |SSL_AEAD_CTX_explicit_nonce_len| bytes are + * written to |out_prefix|, |in_len| bytes to |out|, and up to + * |SSL_AEAD_CTX_max_suffix_len| bytes to |out_suffix|. |*out_suffix_len| is set + * to the actual number of bytes written to |out_suffix|. + * + * |extra_in| may point to an additional plaintext buffer. If present, + * |extra_in_len| additional bytes are encrypted and authenticated, and the + * ciphertext is written to the beginning of |out_suffix|. + * |SSL_AEAD_CTX_max_suffix_len| may be used to size |out_suffix| accordingly. + * + * If |in| and |out| alias then |out| must be == |in|. Other arguments may not + * alias anything. */ +int SSL_AEAD_CTX_seal_scatter(SSL_AEAD_CTX *aead, uint8_t *out_prefix, + uint8_t *out, uint8_t *out_suffix, + size_t *out_suffix_len, size_t max_out_suffix_len, + uint8_t type, uint16_t wire_version, + const uint8_t seqnum[8], const uint8_t *in, + size_t in_len, const uint8_t *extra_in, + size_t extra_in_len); + /* DTLS replay bitmap. */ @@ -974,6 +1006,7 @@ enum ssl_hs_wait_t { ssl_hs_pending_ticket, ssl_hs_early_data_rejected, ssl_hs_read_end_of_early_data, + ssl_hs_read_change_cipher_spec, }; struct ssl_handshake_st { @@ -1007,6 +1040,11 @@ struct ssl_handshake_st { * |SSL_OP_NO_*| and |SSL_CTX_set_max_proto_version| APIs. */ uint16_t max_version; + /* session_id is the session ID in the ClientHello, used for the experimental + * TLS 1.3 variant. */ + uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + uint8_t session_id_len; + size_t hash_len; uint8_t secret[EVP_MAX_MD_SIZE]; uint8_t early_traffic_secret[EVP_MAX_MD_SIZE]; @@ -1896,6 +1934,10 @@ struct ssl_st { * further constrainted by |SSL_OP_NO_*|. */ uint16_t conf_min_version; + /* tls13_variant is the variant of TLS 1.3 we are using for this + * configuration. */ + enum tls13_variant_t tls13_variant; + uint16_t max_send_fragment; /* There are 2 BIO's even though they are normally both the same. This is so diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.cc index 65d438a1..79f71faf 100644 --- a/src/ssl/s3_both.c +++ b/src/ssl/s3_both.cc @@ -131,7 +131,7 @@ SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) { - SSL_HANDSHAKE *hs = OPENSSL_malloc(sizeof(SSL_HANDSHAKE)); + SSL_HANDSHAKE *hs = (SSL_HANDSHAKE *)OPENSSL_malloc(sizeof(SSL_HANDSHAKE)); if (hs == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; @@ -266,7 +266,15 @@ int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) { todo = ssl->max_send_fragment; } - if (!add_record_to_flight(ssl, SSL3_RT_HANDSHAKE, msg + added, todo)) { + uint8_t type = SSL3_RT_HANDSHAKE; + if (ssl->server && + ssl->s3->have_version && + ssl->version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION && + ssl->s3->aead_write_ctx == NULL) { + type = SSL3_RT_PLAINTEXT_HANDSHAKE; + } + + if (!add_record_to_flight(ssl, type, msg + added, todo)) { goto err; } added += todo; diff --git a/src/ssl/s3_lib.c b/src/ssl/s3_lib.cc index ac8bb678..9548bbd4 100644 --- a/src/ssl/s3_lib.c +++ b/src/ssl/s3_lib.cc @@ -163,9 +163,7 @@ int ssl3_new(SSL *ssl) { - SSL3_STATE *s3; - - s3 = OPENSSL_malloc(sizeof *s3); + SSL3_STATE *s3 = (SSL3_STATE *)OPENSSL_malloc(sizeof *s3); if (s3 == NULL) { return 0; } diff --git a/src/ssl/s3_pkt.c b/src/ssl/s3_pkt.cc index 445f8826..4ae2e34c 100644 --- a/src/ssl/s3_pkt.c +++ b/src/ssl/s3_pkt.cc @@ -157,7 +157,7 @@ again: goto again; } - case ssl_open_record_success: + case ssl_open_record_success: { if (CBS_len(&body) > 0xffff) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return -1; @@ -168,6 +168,7 @@ again: rr->length = (uint16_t)CBS_len(&body); rr->data = (uint8_t *)CBS_data(&body); return 1; + } case ssl_open_record_discard: goto again; @@ -522,7 +523,13 @@ int ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len) { return -1; } - if (rr->type != SSL3_RT_HANDSHAKE) { + /* Accept server_plaintext_handshake records when the content type TLS 1.3 + * variant is enabled. */ + if (rr->type != SSL3_RT_HANDSHAKE && + !(!ssl->server && + ssl->tls13_variant == tls13_record_type_experiment && + ssl->s3->aead_read_ctx == NULL && + rr->type == SSL3_RT_PLAINTEXT_HANDSHAKE)) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); return -1; diff --git a/src/ssl/ssl_aead_ctx.c b/src/ssl/ssl_aead_ctx.cc index 1b9dcd2c..5264a653 100644 --- a/src/ssl/ssl_aead_ctx.c +++ b/src/ssl/ssl_aead_ctx.cc @@ -20,7 +20,6 @@ #include <openssl/aead.h> #include <openssl/err.h> #include <openssl/rand.h> -#include <openssl/type_check.h> #include "../crypto/internal.h" #include "internal.h" @@ -61,7 +60,7 @@ SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction, enc_key_len += fixed_iv_len; } - SSL_AEAD_CTX *aead_ctx = OPENSSL_malloc(sizeof(SSL_AEAD_CTX)); + SSL_AEAD_CTX *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX)); if (aead_ctx == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; @@ -78,8 +77,8 @@ SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction, } assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH); - OPENSSL_COMPILE_ASSERT(EVP_AEAD_MAX_NONCE_LENGTH < 256, - variable_nonce_len_doesnt_fit_in_uint8_t); + static_assert(EVP_AEAD_MAX_NONCE_LENGTH < 256, + "variable_nonce_len doesn't fit in uint8_t"); aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead); if (mac_key_len == 0) { assert(fixed_iv_len <= sizeof(aead_ctx->fixed_nonce)); @@ -140,16 +139,19 @@ size_t SSL_AEAD_CTX_explicit_nonce_len(const SSL_AEAD_CTX *aead) { return 0; } -size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *aead) { +size_t SSL_AEAD_CTX_max_suffix_len(const SSL_AEAD_CTX *aead, + size_t extra_in_len) { #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) aead = NULL; #endif - if (aead == NULL) { - return 0; - } - return EVP_AEAD_max_overhead(aead->ctx.aead) + - SSL_AEAD_CTX_explicit_nonce_len(aead); + return extra_in_len + + (aead == NULL ? 0 : EVP_AEAD_max_overhead(aead->ctx.aead)); +} + +size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *aead) { + return SSL_AEAD_CTX_explicit_nonce_len(aead) + + SSL_AEAD_CTX_max_suffix_len(aead, 0); } /* ssl_aead_ctx_get_ad writes the additional data for |aead| into |out| and @@ -252,22 +254,32 @@ int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, CBS *out, uint8_t type, return 1; } -int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len, - size_t max_out, uint8_t type, uint16_t wire_version, - const uint8_t seqnum[8], const uint8_t *in, - size_t in_len) { +int SSL_AEAD_CTX_seal_scatter(SSL_AEAD_CTX *aead, uint8_t *out_prefix, + uint8_t *out, uint8_t *out_suffix, + size_t *out_suffix_len, size_t max_out_suffix_len, + uint8_t type, uint16_t wire_version, + const uint8_t seqnum[8], const uint8_t *in, + size_t in_len, const uint8_t *extra_in, + size_t extra_in_len) { #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) aead = NULL; #endif + if ((in != out && buffers_alias(in, in_len, out, in_len)) || + buffers_alias(in, in_len, out_suffix, max_out_suffix_len)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); + return 0; + } + if (extra_in_len > max_out_suffix_len) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + if (aead == NULL) { /* Handle the initial NULL cipher. */ - if (in_len > max_out) { - OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); - return 0; - } OPENSSL_memmove(out, in, in_len); - *out_len = in_len; + OPENSSL_memmove(out_suffix, extra_in, extra_in_len); + *out_suffix_len = extra_in_len; return 1; } @@ -303,22 +315,14 @@ int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len, nonce_len += aead->variable_nonce_len; /* Emit the variable nonce if included in the record. */ - size_t extra_len = 0; if (aead->variable_nonce_included_in_record) { assert(!aead->xor_fixed_nonce); - if (max_out < aead->variable_nonce_len) { - OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); - return 0; - } - if (out < in + in_len && in < out + aead->variable_nonce_len) { + if (buffers_alias(in, in_len, out_prefix, aead->variable_nonce_len)) { OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); return 0; } - OPENSSL_memcpy(out, nonce + aead->fixed_nonce_len, + OPENSSL_memcpy(out_prefix, nonce + aead->fixed_nonce_len, aead->variable_nonce_len); - extra_len = aead->variable_nonce_len; - out += aead->variable_nonce_len; - max_out -= aead->variable_nonce_len; } /* XOR the fixed nonce, if necessary. */ @@ -329,10 +333,33 @@ int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len, } } - if (!EVP_AEAD_CTX_seal(&aead->ctx, out, out_len, max_out, nonce, nonce_len, - in, in_len, ad, ad_len)) { + return EVP_AEAD_CTX_seal_scatter(&aead->ctx, out, out_suffix, out_suffix_len, + max_out_suffix_len, nonce, nonce_len, in, + in_len, extra_in, extra_in_len, ad, ad_len); +} + +int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len, + size_t max_out_len, uint8_t type, uint16_t wire_version, + const uint8_t seqnum[8], const uint8_t *in, + size_t in_len) { + size_t prefix_len = SSL_AEAD_CTX_explicit_nonce_len(aead); + if (in_len + prefix_len < in_len) { + OPENSSL_PUT_ERROR(CIPHER, SSL_R_RECORD_TOO_LARGE); + return 0; + } + if (in_len + prefix_len > max_out_len) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + + size_t suffix_len; + if (!SSL_AEAD_CTX_seal_scatter(aead, out, out + prefix_len, + out + prefix_len + in_len, &suffix_len, + max_out_len - prefix_len - in_len, type, + wire_version, seqnum, in, in_len, 0, 0)) { return 0; } - *out_len += extra_len; + assert(suffix_len <= SSL_AEAD_CTX_max_suffix_len(aead, 0)); + *out_len = prefix_len + in_len + suffix_len; return 1; } diff --git a/src/ssl/ssl_asn1.c b/src/ssl/ssl_asn1.cc index cc6a5596..1d6140e9 100644 --- a/src/ssl/ssl_asn1.c +++ b/src/ssl/ssl_asn1.cc @@ -80,6 +80,13 @@ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR * OTHERWISE. */ +/* Per C99, various stdint.h macros are unavailable in C++ unless some macros + * are defined. C++11 overruled this decision, but older Android NDKs still + * require it. */ +#if !defined(__STDC_LIMIT_MACROS) +#define __STDC_LIMIT_MACROS +#endif + #include <openssl/ssl.h> #include <limits.h> @@ -425,7 +432,7 @@ int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data, static const char kNotResumableSession[] = "NOT RESUMABLE"; *out_len = strlen(kNotResumableSession); - *out_data = BUF_memdup(kNotResumableSession, *out_len); + *out_data = (uint8_t *)BUF_memdup(kNotResumableSession, *out_len); if (*out_data == NULL) { return 0; } diff --git a/src/ssl/ssl_buffer.c b/src/ssl/ssl_buffer.cc index 9ea5c68c..579899b2 100644 --- a/src/ssl/ssl_buffer.c +++ b/src/ssl/ssl_buffer.cc @@ -22,16 +22,17 @@ #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/mem.h> -#include <openssl/type_check.h> #include "../crypto/internal.h" #include "internal.h" -OPENSSL_COMPILE_ASSERT(0xffff <= INT_MAX, uint16_fits_in_int); +/* BIO uses int instead of size_t. No lengths will exceed uint16_t, so this will + * not overflow. */ +static_assert(0xffff <= INT_MAX, "uint16_t does not fit in int"); -OPENSSL_COMPILE_ASSERT((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0, - align_to_a_power_of_two); +static_assert((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0, + "SSL3_ALIGN_PAYLOAD must be a power of 2"); /* ensure_buffer ensures |buf| has capacity at least |cap|, aligned such that * data written after |header_len| is aligned to a |SSL3_ALIGN_PAYLOAD|-byte @@ -47,7 +48,7 @@ static int ensure_buffer(SSL3_BUFFER *buf, size_t header_len, size_t cap) { } /* Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment. */ - uint8_t *new_buf = OPENSSL_malloc(cap + SSL3_ALIGN_PAYLOAD - 1); + uint8_t *new_buf = (uint8_t *)OPENSSL_malloc(cap + SSL3_ALIGN_PAYLOAD - 1); if (new_buf == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; @@ -142,9 +143,9 @@ int ssl_read_buffer_extend_to(SSL *ssl, size_t len) { ssl_read_buffer_discard(ssl); if (SSL_is_dtls(ssl)) { - OPENSSL_COMPILE_ASSERT( + static_assert( DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <= 0xffff, - dtls_read_buffer_too_large); + "DTLS read buffer is too large"); /* The |len| parameter is ignored in DTLS. */ len = DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; @@ -203,15 +204,16 @@ int ssl_write_buffer_is_pending(const SSL *ssl) { return ssl->s3->write_buffer.len > 0; } -OPENSSL_COMPILE_ASSERT(SSL3_RT_HEADER_LENGTH * 2 + - SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 + - SSL3_RT_MAX_PLAIN_LENGTH <= 0xffff, - maximum_tls_write_buffer_too_large); +static_assert(SSL3_RT_HEADER_LENGTH * 2 + + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 + + SSL3_RT_MAX_PLAIN_LENGTH <= + 0xffff, + "maximum TLS write buffer is too large"); -OPENSSL_COMPILE_ASSERT(DTLS1_RT_HEADER_LENGTH + - SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + - SSL3_RT_MAX_PLAIN_LENGTH <= 0xffff, - maximum_dtls_write_buffer_too_large); +static_assert(DTLS1_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + + SSL3_RT_MAX_PLAIN_LENGTH <= + 0xffff, + "maximum DTLS write buffer is too large"); int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len) { SSL3_BUFFER *buf = &ssl->s3->write_buffer; diff --git a/src/ssl/ssl_cert.c b/src/ssl/ssl_cert.cc index 674db101..df4b9c8c 100644 --- a/src/ssl/ssl_cert.c +++ b/src/ssl/ssl_cert.cc @@ -132,7 +132,7 @@ CERT *ssl_cert_new(const SSL_X509_METHOD *x509_method) { - CERT *ret = OPENSSL_malloc(sizeof(CERT)); + CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); if (ret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; @@ -149,7 +149,7 @@ static CRYPTO_BUFFER *buffer_up_ref(CRYPTO_BUFFER *buffer) { } CERT *ssl_cert_dup(CERT *cert) { - CERT *ret = OPENSSL_malloc(sizeof(CERT)); + CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); if (ret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; @@ -168,8 +168,8 @@ CERT *ssl_cert_dup(CERT *cert) { ret->x509_method = cert->x509_method; if (cert->sigalgs != NULL) { - ret->sigalgs = - BUF_memdup(cert->sigalgs, cert->num_sigalgs * sizeof(cert->sigalgs[0])); + ret->sigalgs = (uint16_t *)BUF_memdup( + cert->sigalgs, cert->num_sigalgs * sizeof(cert->sigalgs[0])); if (ret->sigalgs == NULL) { goto err; } @@ -496,7 +496,8 @@ int ssl_add_cert_chain(SSL *ssl, CBB *cbb) { CBB certs; if (!CBB_add_u24_length_prefixed(cbb, &certs)) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } STACK_OF(CRYPTO_BUFFER) *chain = ssl->cert->chain; @@ -507,15 +508,12 @@ int ssl_add_cert_chain(SSL *ssl, CBB *cbb) { !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer)) || !CBB_flush(&certs)) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } } return CBB_flush(cbb); - -err: - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return 0; } /* ssl_cert_skip_to_spki parses a DER-encoded, X.509 certificate from |in| and diff --git a/src/ssl/ssl_cipher.c b/src/ssl/ssl_cipher.cc index 5d888783..c0f4122a 100644 --- a/src/ssl/ssl_cipher.c +++ b/src/ssl/ssl_cipher.cc @@ -631,8 +631,8 @@ static const CIPHER_ALIAS kCipherAliases[] = { static const size_t kCipherAliasesLen = OPENSSL_ARRAY_SIZE(kCipherAliases); static int ssl_cipher_id_cmp(const void *in_a, const void *in_b) { - const SSL_CIPHER *a = in_a; - const SSL_CIPHER *b = in_b; + const SSL_CIPHER *a = reinterpret_cast<const SSL_CIPHER *>(in_a); + const SSL_CIPHER *b = reinterpret_cast<const SSL_CIPHER *>(in_b); if (a->id > b->id) { return 1; @@ -647,8 +647,8 @@ const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) { SSL_CIPHER c; c.id = 0x03000000L | value; - return bsearch(&c, kCiphers, kCiphersLen, sizeof(SSL_CIPHER), - ssl_cipher_id_cmp); + return reinterpret_cast<const SSL_CIPHER *>(bsearch( + &c, kCiphers, kCiphersLen, sizeof(SSL_CIPHER), ssl_cipher_id_cmp)); } int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead, @@ -1001,7 +1001,7 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p, curr = curr->next; } - number_uses = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int)); + number_uses = (int *)OPENSSL_malloc((max_strength_bits + 1) * sizeof(int)); if (!number_uses) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; @@ -1227,7 +1227,7 @@ int ssl_create_cipher_list( /* Now we have to collect the available ciphers from the compiled in ciphers. * We cannot get more than the number compiled in, so it is used for * allocation. */ - co_list = OPENSSL_malloc(sizeof(CIPHER_ORDER) * kCiphersLen); + co_list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * kCiphersLen); if (co_list == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; @@ -1314,7 +1314,7 @@ int ssl_create_cipher_list( goto err; } - in_group_flags = OPENSSL_malloc(kCiphersLen); + in_group_flags = (uint8_t *)OPENSSL_malloc(kCiphersLen); if (!in_group_flags) { goto err; } @@ -1332,12 +1332,13 @@ int ssl_create_cipher_list( OPENSSL_free(co_list); /* Not needed any longer */ co_list = NULL; - pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); + pref_list = (ssl_cipher_preference_list_st *)OPENSSL_malloc( + sizeof(struct ssl_cipher_preference_list_st)); if (!pref_list) { goto err; } pref_list->ciphers = cipherstack; - pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags); + pref_list->in_group_flags = (uint8_t *)OPENSSL_malloc(num_in_group_flags); if (!pref_list->in_group_flags) { goto err; } @@ -1672,7 +1673,7 @@ const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, if (buf == NULL) { len = 128; - buf = OPENSSL_malloc(len); + buf = (char *)OPENSSL_malloc(len); if (buf == NULL) { return NULL; } diff --git a/src/ssl/ssl_ecdh.c b/src/ssl/ssl_ecdh.cc index 49652f2e..fa1cbe97 100644 --- a/src/ssl/ssl_ecdh.c +++ b/src/ssl/ssl_ecdh.cc @@ -37,49 +37,35 @@ static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) { } static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) { - assert(ctx->data == NULL); - BIGNUM *private_key = BN_new(); - if (private_key == NULL) { - return 0; - } - ctx->data = private_key; - /* Set up a shared |BN_CTX| for all operations. */ - BN_CTX *bn_ctx = BN_CTX_new(); - if (bn_ctx == NULL) { + bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new()); + if (!bn_ctx) { return 0; } - BN_CTX_start(bn_ctx); - - int ret = 0; - EC_POINT *public_key = NULL; - EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid); - if (group == NULL) { - goto err; - } + bssl::BN_CTXScope scope(bn_ctx.get()); /* Generate a private key. */ - if (!BN_rand_range_ex(private_key, 1, EC_GROUP_get0_order(group))) { - goto err; + bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid)); + bssl::UniquePtr<BIGNUM> private_key(BN_new()); + if (!group || !private_key || + !BN_rand_range_ex(private_key.get(), 1, + EC_GROUP_get0_order(group.get()))) { + return 0; } /* Compute the corresponding public key and serialize it. */ - public_key = EC_POINT_new(group); - if (public_key == NULL || - !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx) || - !EC_POINT_point2cbb(out, group, public_key, POINT_CONVERSION_UNCOMPRESSED, - bn_ctx)) { - goto err; + bssl::UniquePtr<EC_POINT> public_key(EC_POINT_new(group.get())); + if (!public_key || + !EC_POINT_mul(group.get(), public_key.get(), private_key.get(), NULL, + NULL, bn_ctx.get()) || + !EC_POINT_point2cbb(out, group.get(), public_key.get(), + POINT_CONVERSION_UNCOMPRESSED, bn_ctx.get())) { + return 0; } - ret = 1; - -err: - EC_GROUP_free(group); - EC_POINT_free(public_key); - BN_CTX_end(bn_ctx); - BN_CTX_free(bn_ctx); - return ret; + assert(ctx->data == NULL); + ctx->data = private_key.release(); + return 1; } static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, @@ -90,59 +76,48 @@ static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, *out_alert = SSL_AD_INTERNAL_ERROR; /* Set up a shared |BN_CTX| for all operations. */ - BN_CTX *bn_ctx = BN_CTX_new(); - if (bn_ctx == NULL) { + bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new()); + if (!bn_ctx) { return 0; } - BN_CTX_start(bn_ctx); - - int ret = 0; - EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid); - EC_POINT *peer_point = NULL, *result = NULL; - uint8_t *secret = NULL; - if (group == NULL) { - goto err; - } + bssl::BN_CTXScope scope(bn_ctx.get()); - /* Compute the x-coordinate of |peer_key| * |private_key|. */ - peer_point = EC_POINT_new(group); - result = EC_POINT_new(group); - if (peer_point == NULL || result == NULL) { - goto err; + bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid)); + if (!group) { + return 0; } - BIGNUM *x = BN_CTX_get(bn_ctx); - if (x == NULL) { - goto err; + + bssl::UniquePtr<EC_POINT> peer_point(EC_POINT_new(group.get())); + bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get())); + BIGNUM *x = BN_CTX_get(bn_ctx.get()); + if (!peer_point || !result || !x) { + return 0; } - if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) { + + if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key, peer_key_len, + bn_ctx.get())) { *out_alert = SSL_AD_DECODE_ERROR; - goto err; + return 0; } - if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) || - !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) { - goto err; + + /* Compute the x-coordinate of |peer_key| * |private_key|. */ + if (!EC_POINT_mul(group.get(), result.get(), NULL, peer_point.get(), + private_key, bn_ctx.get()) || + !EC_POINT_get_affine_coordinates_GFp(group.get(), result.get(), x, NULL, + bn_ctx.get())) { + return 0; } /* Encode the x-coordinate left-padded with zeros. */ - size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8; - secret = OPENSSL_malloc(secret_len); - if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) { - goto err; + size_t secret_len = (EC_GROUP_get_degree(group.get()) + 7) / 8; + bssl::UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len)); + if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) { + return 0; } - *out_secret = secret; + *out_secret = secret.release(); *out_secret_len = secret_len; - secret = NULL; - ret = 1; - -err: - EC_GROUP_free(group); - EC_POINT_free(peer_point); - EC_POINT_free(result); - BN_CTX_end(bn_ctx); - BN_CTX_free(bn_ctx); - OPENSSL_free(secret); - return ret; + return 1; } static int ssl_ec_point_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key, @@ -187,7 +162,7 @@ static int ssl_x25519_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, assert(ctx->data != NULL); *out_alert = SSL_AD_INTERNAL_ERROR; - uint8_t *secret = OPENSSL_malloc(32); + uint8_t *secret = (uint8_t *)OPENSSL_malloc(32); if (secret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; diff --git a/src/ssl/ssl_file.c b/src/ssl/ssl_file.cc index 59351a32..59351a32 100644 --- a/src/ssl/ssl_file.c +++ b/src/ssl/ssl_file.cc diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.cc index 109dfd07..74419252 100644 --- a/src/ssl/ssl_lib.c +++ b/src/ssl/ssl_lib.cc @@ -173,9 +173,9 @@ OPENSSL_DECLARE_ERROR_REASON(SSL, NO_CIPHERS_SPECIFIED) /* Some error codes are special. Ensure the make_errors.go script never * regresses this. */ -OPENSSL_COMPILE_ASSERT(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION == - SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET, - ssl_alert_reason_code_mismatch); +static_assert(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION == + SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET, + "alert reason code mismatch"); /* kMaxHandshakeSize is the maximum size, in bytes, of a handshake message. */ static const size_t kMaxHandshakeSize = (1u << 24) - 1; @@ -234,7 +234,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) { return NULL; } - ret = OPENSSL_malloc(sizeof(SSL_CTX)); + ret = (SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX)); if (ret == NULL) { goto err; } @@ -365,7 +365,7 @@ SSL *SSL_new(SSL_CTX *ctx) { return NULL; } - SSL *ssl = OPENSSL_malloc(sizeof(SSL)); + SSL *ssl = (SSL *)OPENSSL_malloc(sizeof(SSL)); if (ssl == NULL) { goto err; } @@ -373,6 +373,7 @@ SSL *SSL_new(SSL_CTX *ctx) { ssl->conf_min_version = ctx->conf_min_version; ssl->conf_max_version = ctx->conf_max_version; + ssl->tls13_variant = ctx->tls13_variant; /* RFC 6347 states that implementations SHOULD use an initial timer value of * 1 second. */ @@ -407,8 +408,8 @@ SSL *SSL_new(SSL_CTX *ctx) { } if (ctx->supported_group_list) { - ssl->supported_group_list = BUF_memdup(ctx->supported_group_list, - ctx->supported_group_list_len * 2); + ssl->supported_group_list = (uint16_t *)BUF_memdup( + ctx->supported_group_list, ctx->supported_group_list_len * 2); if (!ssl->supported_group_list) { goto err; } @@ -416,8 +417,8 @@ SSL *SSL_new(SSL_CTX *ctx) { } if (ctx->alpn_client_proto_list) { - ssl->alpn_client_proto_list = BUF_memdup(ctx->alpn_client_proto_list, - ctx->alpn_client_proto_list_len); + ssl->alpn_client_proto_list = (uint8_t *)BUF_memdup( + ctx->alpn_client_proto_list, ctx->alpn_client_proto_list_len); if (ssl->alpn_client_proto_list == NULL) { goto err; } @@ -719,7 +720,8 @@ static int ssl_read_impl(SSL *ssl, void *buf, int num, int peek) { } int got_handshake; - int ret = ssl->method->read_app_data(ssl, &got_handshake, buf, num, peek); + int ret = ssl->method->read_app_data(ssl, &got_handshake, (uint8_t *)buf, + num, peek); if (ret > 0 || !got_handshake) { ssl->s3->key_update_count = 0; return ret; @@ -774,7 +776,8 @@ int SSL_write(SSL *ssl, const void *buf, int num) { } } - ret = ssl->method->write_app_data(ssl, &needs_handshake, buf, num); + ret = ssl->method->write_app_data(ssl, &needs_handshake, + (const uint8_t *)buf, num); } while (needs_handshake); return ret; } @@ -845,6 +848,14 @@ void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) { ctx->cert->enable_early_data = !!enabled; } +void SSL_CTX_set_tls13_variant(SSL_CTX *ctx, enum tls13_variant_t variant) { + ctx->tls13_variant = variant; +} + +void SSL_set_tls13_variant(SSL *ssl, enum tls13_variant_t variant) { + ssl->tls13_variant = variant; +} + void SSL_set_early_data_enabled(SSL *ssl, int enabled) { ssl->cert->enable_early_data = !!enabled; } @@ -1032,11 +1043,14 @@ void SSL_CTX_set0_buffer_pool(SSL_CTX *ctx, CRYPTO_BUFFER_POOL *pool) { int SSL_get_tls_unique(const SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { + *out_len = 0; + OPENSSL_memset(out, 0, max_out); + /* tls-unique is not defined for SSL 3.0 or TLS 1.3. */ if (!ssl->s3->initial_handshake_complete || ssl3_protocol_version(ssl) < TLS1_VERSION || ssl3_protocol_version(ssl) >= TLS1_3_VERSION) { - goto err; + return 0; } /* The tls-unique value is the first Finished message in the handshake, which @@ -1047,7 +1061,7 @@ int SSL_get_tls_unique(const SSL *ssl, uint8_t *out, size_t *out_len, if (ssl->session != NULL) { /* tls-unique is broken for resumed sessions unless EMS is used. */ if (!ssl->session->extended_master_secret) { - goto err; + return 0; } finished = ssl->s3->previous_server_finished; finished_len = ssl->s3->previous_server_finished_len; @@ -1060,11 +1074,6 @@ int SSL_get_tls_unique(const SSL *ssl, uint8_t *out, size_t *out_len, OPENSSL_memcpy(out, finished, *out_len); return 1; - -err: - *out_len = 0; - OPENSSL_memset(out, 0, max_out); - return 0; } static int set_session_id_context(CERT *cert, const uint8_t *sid_ctx, @@ -1074,7 +1083,7 @@ static int set_session_id_context(CERT *cert, const uint8_t *sid_ctx, return 0; } - OPENSSL_COMPILE_ASSERT(sizeof(cert->sid_ctx) < 256, sid_ctx_too_large); + static_assert(sizeof(cert->sid_ctx) < 256, "sid_ctx too large"); cert->sid_ctx_length = (uint8_t)sid_ctx_len; OPENSSL_memcpy(cert->sid_ctx, sid_ctx, sid_ctx_len); return 1; @@ -1383,7 +1392,7 @@ int SSL_CTX_get_tlsext_ticket_keys(SSL_CTX *ctx, void *out, size_t len) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH); return 0; } - uint8_t *out_bytes = out; + uint8_t *out_bytes = reinterpret_cast<uint8_t *>(out); OPENSSL_memcpy(out_bytes, ctx->tlsext_tick_key_name, 16); OPENSSL_memcpy(out_bytes + 16, ctx->tlsext_tick_hmac_key, 16); OPENSSL_memcpy(out_bytes + 32, ctx->tlsext_tick_aes_key, 16); @@ -1398,7 +1407,7 @@ int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in, size_t len) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH); return 0; } - const uint8_t *in_bytes = in; + const uint8_t *in_bytes = reinterpret_cast<const uint8_t *>(in); OPENSSL_memcpy(ctx->tlsext_tick_key_name, in_bytes, 16); OPENSSL_memcpy(ctx->tlsext_tick_hmac_key, in_bytes + 16, 16); OPENSSL_memcpy(ctx->tlsext_tick_aes_key, in_bytes + 32, 16); @@ -1682,7 +1691,7 @@ void SSL_CTX_set_next_proto_select_cb( int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, unsigned protos_len) { OPENSSL_free(ctx->alpn_client_proto_list); - ctx->alpn_client_proto_list = BUF_memdup(protos, protos_len); + ctx->alpn_client_proto_list = (uint8_t *)BUF_memdup(protos, protos_len); if (!ctx->alpn_client_proto_list) { return 1; } @@ -1693,7 +1702,7 @@ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, unsigned protos_len) { OPENSSL_free(ssl->alpn_client_proto_list); - ssl->alpn_client_proto_list = BUF_memdup(protos, protos_len); + ssl->alpn_client_proto_list = (uint8_t *)BUF_memdup(protos, protos_len); if (!ssl->alpn_client_proto_list) { return 1; } diff --git a/src/ssl/ssl_privkey.c b/src/ssl/ssl_privkey.cc index 257d03e4..5b620f88 100644 --- a/src/ssl/ssl_privkey.c +++ b/src/ssl/ssl_privkey.cc @@ -64,7 +64,6 @@ #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/mem.h> -#include <openssl/type_check.h> #include "internal.h" #include "../crypto/internal.h" @@ -119,6 +118,16 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) { return ret; } +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) { + bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len)); + if (!rsa) { + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); + return 0; + } + + return SSL_use_RSAPrivateKey(ssl, rsa.get()); +} + int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) { if (pkey == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); @@ -228,7 +237,7 @@ static int set_algorithm_prefs(uint16_t **out_prefs, size_t *out_num_prefs, OPENSSL_free(*out_prefs); *out_num_prefs = 0; - *out_prefs = BUF_memdup(prefs, num_prefs * sizeof(prefs[0])); + *out_prefs = (uint16_t *)BUF_memdup(prefs, num_prefs * sizeof(prefs[0])); if (*out_prefs == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; @@ -261,11 +270,12 @@ int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids, size_t num_digests) { OPENSSL_free(ssl->cert->sigalgs); - OPENSSL_COMPILE_ASSERT(sizeof(int) >= 2 * sizeof(uint16_t), - digest_list_conversion_cannot_overflow); + static_assert(sizeof(int) >= 2 * sizeof(uint16_t), + "sigalgs allocation may overflow"); ssl->cert->num_sigalgs = 0; - ssl->cert->sigalgs = OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests); + ssl->cert->sigalgs = + (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests); if (ssl->cert->sigalgs == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; diff --git a/src/ssl/ssl_privkey_cc.cc b/src/ssl/ssl_privkey_cc.cc deleted file mode 100644 index 653308c1..00000000 --- a/src/ssl/ssl_privkey_cc.cc +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] */ - -#include <openssl/ssl.h> - -#include <openssl/err.h> -#include <openssl/rsa.h> - - -/* This function has been converted to C++ to check if all of libssl's - * consumers' toolchains are capable of handling C++11. Once all problems in - * consumer toolchains are found and fixed, we will convert the rest of - * libssl. */ - -int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) { - bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len)); - if (!rsa) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); - return 0; - } - - return SSL_use_RSAPrivateKey(ssl, rsa.get()); -} diff --git a/src/ssl/ssl_session.c b/src/ssl/ssl_session.cc index 3e2c9f49..9cb78cc2 100644 --- a/src/ssl/ssl_session.c +++ b/src/ssl/ssl_session.cc @@ -161,7 +161,7 @@ static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session); static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock); SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method) { - SSL_SESSION *session = OPENSSL_malloc(sizeof(SSL_SESSION)); + SSL_SESSION *session = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); if (session == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; @@ -228,8 +228,8 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) { new_session->ocsp_response_length = session->ocsp_response_length; if (session->ocsp_response != NULL) { - new_session->ocsp_response = BUF_memdup(session->ocsp_response, - session->ocsp_response_length); + new_session->ocsp_response = (uint8_t *)BUF_memdup( + session->ocsp_response, session->ocsp_response_length); if (new_session->ocsp_response == NULL) { goto err; } @@ -238,9 +238,9 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) { new_session->tlsext_signed_cert_timestamp_list_length = session->tlsext_signed_cert_timestamp_list_length; if (session->tlsext_signed_cert_timestamp_list != NULL) { - new_session->tlsext_signed_cert_timestamp_list = - BUF_memdup(session->tlsext_signed_cert_timestamp_list, - session->tlsext_signed_cert_timestamp_list_length); + new_session->tlsext_signed_cert_timestamp_list = (uint8_t *)BUF_memdup( + session->tlsext_signed_cert_timestamp_list, + session->tlsext_signed_cert_timestamp_list_length); if (new_session->tlsext_signed_cert_timestamp_list == NULL) { goto err; } @@ -283,7 +283,7 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) { if (session->early_alpn != NULL) { new_session->early_alpn = - BUF_memdup(session->early_alpn, session->early_alpn_len); + (uint8_t *)BUF_memdup(session->early_alpn, session->early_alpn_len); if (new_session->early_alpn == NULL) { goto err; } @@ -295,7 +295,7 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) { if (dup_flags & SSL_SESSION_INCLUDE_TICKET) { if (session->tlsext_tick != NULL) { new_session->tlsext_tick = - BUF_memdup(session->tlsext_tick, session->tlsext_ticklen); + (uint8_t *)BUF_memdup(session->tlsext_tick, session->tlsext_ticklen); if (new_session->tlsext_tick == NULL) { goto err; } @@ -595,12 +595,8 @@ err: static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out, const uint8_t *session_buf, size_t session_len) { - int ret = 0; - - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&ctx); - HMAC_CTX hctx; - HMAC_CTX_init(&hctx); + bssl::ScopedEVP_CIPHER_CTX ctx; + bssl::ScopedHMAC_CTX hctx; /* If the session is too long, emit a dummy value rather than abort the * connection. */ @@ -608,11 +604,8 @@ static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out, 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE; if (session_len > 0xffff - kMaxTicketOverhead) { static const char kTicketPlaceholder[] = "TICKET TOO LARGE"; - if (CBB_add_bytes(out, (const uint8_t *)kTicketPlaceholder, - strlen(kTicketPlaceholder))) { - ret = 1; - } - goto err; + return CBB_add_bytes(out, (const uint8_t *)kTicketPlaceholder, + strlen(kTicketPlaceholder)); } /* Initialize HMAC and cipher contexts. If callback present it does all the @@ -621,26 +614,26 @@ static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out, uint8_t iv[EVP_MAX_IV_LENGTH]; uint8_t key_name[16]; if (tctx->tlsext_ticket_key_cb != NULL) { - if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, &ctx, &hctx, + if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, ctx.get(), hctx.get(), 1 /* encrypt */) < 0) { - goto err; + return 0; } } else { if (!RAND_bytes(iv, 16) || - !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + !EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, iv) || - !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), - NULL)) { - goto err; + !HMAC_Init_ex(hctx.get(), tctx->tlsext_tick_hmac_key, 16, + tlsext_tick_md(), NULL)) { + return 0; } OPENSSL_memcpy(key_name, tctx->tlsext_tick_key_name, 16); } uint8_t *ptr; if (!CBB_add_bytes(out, key_name, 16) || - !CBB_add_bytes(out, iv, EVP_CIPHER_CTX_iv_length(&ctx)) || + !CBB_add_bytes(out, iv, EVP_CIPHER_CTX_iv_length(ctx.get())) || !CBB_reserve(out, &ptr, session_len + EVP_MAX_BLOCK_LENGTH)) { - goto err; + return 0; } size_t total = 0; @@ -649,33 +642,28 @@ static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out, total = session_len; #else int len; - if (!EVP_EncryptUpdate(&ctx, ptr + total, &len, session_buf, session_len)) { - goto err; + if (!EVP_EncryptUpdate(ctx.get(), ptr + total, &len, session_buf, session_len)) { + return 0; } total += len; - if (!EVP_EncryptFinal_ex(&ctx, ptr + total, &len)) { - goto err; + if (!EVP_EncryptFinal_ex(ctx.get(), ptr + total, &len)) { + return 0; } total += len; #endif if (!CBB_did_write(out, total)) { - goto err; + return 0; } unsigned hlen; - if (!HMAC_Update(&hctx, CBB_data(out), CBB_len(out)) || + if (!HMAC_Update(hctx.get(), CBB_data(out), CBB_len(out)) || !CBB_reserve(out, &ptr, EVP_MAX_MD_SIZE) || - !HMAC_Final(&hctx, ptr, &hlen) || + !HMAC_Final(hctx.get(), ptr, &hlen) || !CBB_did_write(out, hlen)) { - goto err; + return 0; } - ret = 1; - -err: - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); - return ret; + return 1; } static int ssl_encrypt_ticket_with_method(SSL *ssl, CBB *out, @@ -1027,7 +1015,7 @@ typedef struct timeout_param_st { } TIMEOUT_PARAM; static void timeout_doall_arg(SSL_SESSION *session, void *void_param) { - TIMEOUT_PARAM *param = void_param; + TIMEOUT_PARAM *param = reinterpret_cast<TIMEOUT_PARAM *>(void_param); if (param->time == 0 || session->time + session->timeout < session->time || diff --git a/src/ssl/ssl_stat.c b/src/ssl/ssl_stat.cc index 22149e25..22149e25 100644 --- a/src/ssl/ssl_stat.c +++ b/src/ssl/ssl_stat.cc diff --git a/src/ssl/ssl_transcript.c b/src/ssl/ssl_transcript.cc index 9cc37778..9cc37778 100644 --- a/src/ssl/ssl_transcript.c +++ b/src/ssl/ssl_transcript.cc diff --git a/src/ssl/ssl_versions.c b/src/ssl/ssl_versions.cc index 5d927718..8b54bd2f 100644 --- a/src/ssl/ssl_versions.c +++ b/src/ssl/ssl_versions.cc @@ -33,6 +33,8 @@ int ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) { return 1; case TLS1_3_DRAFT_VERSION: + case TLS1_3_EXPERIMENT_VERSION: + case TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION: *out = TLS1_3_VERSION; return 1; @@ -54,6 +56,8 @@ int ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) { * decreasing preference. */ static const uint16_t kTLSVersions[] = { + TLS1_3_EXPERIMENT_VERSION, + TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION, TLS1_3_DRAFT_VERSION, TLS1_2_VERSION, TLS1_1_VERSION, @@ -95,7 +99,9 @@ static int set_version_bound(const SSL_PROTOCOL_METHOD *method, uint16_t *out, /* The public API uses wire versions, except we use |TLS1_3_VERSION| * everywhere to refer to any draft TLS 1.3 versions. In this direction, we * map it to some representative TLS 1.3 draft version. */ - if (version == TLS1_3_DRAFT_VERSION) { + if (version == TLS1_3_DRAFT_VERSION || + version == TLS1_3_EXPERIMENT_VERSION || + version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_SSL_VERSION); return 0; } @@ -235,7 +241,8 @@ static uint16_t ssl_version(const SSL *ssl) { int SSL_version(const SSL *ssl) { uint16_t ret = ssl_version(ssl); /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */ - if (ret == TLS1_3_DRAFT_VERSION) { + if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION || + ret == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) { return TLS1_3_VERSION; } return ret; @@ -245,6 +252,8 @@ static const char *ssl_get_version(int version) { switch (version) { /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */ case TLS1_3_DRAFT_VERSION: + case TLS1_3_EXPERIMENT_VERSION: + case TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION: return "TLSv1.3"; case TLS1_2_VERSION: @@ -291,8 +300,29 @@ uint16_t ssl3_protocol_version(const SSL *ssl) { } int ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) { + SSL *const ssl = hs->ssl; + /* As a client, only allow the configured TLS 1.3 variant. As a server, + * support all TLS 1.3 variants as long as tls13_variant is set to a + * non-default value. */ + if (ssl->server) { + if (ssl->tls13_variant == tls13_default && + (version == TLS1_3_EXPERIMENT_VERSION || + version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION)) { + return 0; + } + } else { + if ((ssl->tls13_variant != tls13_experiment && + version == TLS1_3_EXPERIMENT_VERSION) || + (ssl->tls13_variant != tls13_record_type_experiment && + version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) || + (ssl->tls13_variant != tls13_default && + version == TLS1_3_DRAFT_VERSION)) { + return 0; + } + } + uint16_t protocol_version; - return method_supports_version(hs->ssl->method, version) && + return method_supports_version(ssl->method, version) && ssl_protocol_version_from_wire(&protocol_version, version) && hs->min_version <= protocol_version && protocol_version <= hs->max_version; diff --git a/src/ssl/ssl_x509.c b/src/ssl/ssl_x509.cc index 65405aaf..77fc0e2a 100644 --- a/src/ssl/ssl_x509.c +++ b/src/ssl/ssl_x509.cc @@ -494,14 +494,13 @@ static void ssl_crypto_x509_cert_dup(CERT *new_cert, const CERT *cert) { } static int ssl_crypto_x509_session_cache_objects(SSL_SESSION *sess) { - STACK_OF(X509) *chain = NULL; + bssl::UniquePtr<STACK_OF(X509)> chain; const size_t num_certs = sk_CRYPTO_BUFFER_num(sess->certs); - if (num_certs > 0) { - chain = sk_X509_new_null(); - if (chain == NULL) { + chain.reset(sk_X509_new_null()); + if (!chain) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); - goto err; + return 0; } } @@ -510,12 +509,12 @@ static int ssl_crypto_x509_session_cache_objects(SSL_SESSION *sess) { X509 *x509 = X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(sess->certs, i)); if (x509 == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - goto err; + return 0; } - if (!sk_X509_push(chain, x509)) { + if (!sk_X509_push(chain.get(), x509)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); X509_free(x509); - goto err; + return 0; } if (i == 0) { leaf = x509; @@ -523,7 +522,7 @@ static int ssl_crypto_x509_session_cache_objects(SSL_SESSION *sess) { } sk_X509_pop_free(sess->x509_chain, X509_free); - sess->x509_chain = chain; + sess->x509_chain = chain.release(); sk_X509_pop_free(sess->x509_chain_without_leaf, X509_free); sess->x509_chain_without_leaf = NULL; @@ -532,12 +531,7 @@ static int ssl_crypto_x509_session_cache_objects(SSL_SESSION *sess) { X509_up_ref(leaf); } sess->x509_peer = leaf; - return 1; - -err: - sk_X509_pop_free(chain, X509_free); - return 0; } static int ssl_crypto_x509_session_dup(SSL_SESSION *new_session, diff --git a/src/ssl/t1_enc.c b/src/ssl/t1_enc.cc index 6aa5e0c1..c2242405 100644 --- a/src/ssl/t1_enc.c +++ b/src/ssl/t1_enc.cc @@ -365,7 +365,7 @@ static int tls1_setup_key_block(SSL_HANDSHAKE *hs) { size_t key_block_len = SSL_get_key_block_len(ssl); - uint8_t *keyblock = OPENSSL_malloc(key_block_len); + uint8_t *keyblock = (uint8_t *)OPENSSL_malloc(key_block_len); if (keyblock == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; @@ -533,7 +533,7 @@ int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, } seed_len += 2 + context_len; } - uint8_t *seed = OPENSSL_malloc(seed_len); + uint8_t *seed = (uint8_t *)OPENSSL_malloc(seed_len); if (seed == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.cc index 8e858c42..76469ebb 100644 --- a/src/ssl/t1_lib.c +++ b/src/ssl/t1_lib.cc @@ -121,7 +121,6 @@ #include <openssl/mem.h> #include <openssl/nid.h> #include <openssl/rand.h> -#include <openssl/type_check.h> #include "internal.h" #include "../crypto/internal.h" @@ -168,7 +167,8 @@ static int tls1_check_duplicate_extensions(const CBS *cbs) { return 1; } - extension_types = OPENSSL_malloc(sizeof(uint16_t) * num_extensions); + extension_types = + (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * num_extensions); if (extension_types == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto done; @@ -362,9 +362,7 @@ int tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) { int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len, const int *curves, size_t ncurves) { - uint16_t *group_ids; - - group_ids = OPENSSL_malloc(ncurves * sizeof(uint16_t)); + uint16_t *group_ids = (uint16_t *)OPENSSL_malloc(ncurves * sizeof(uint16_t)); if (group_ids == NULL) { return 0; } @@ -400,8 +398,8 @@ int tls1_set_curves_list(uint16_t **out_group_ids, size_t *out_group_ids_len, goto err; } - uint16_t *new_group_ids = OPENSSL_realloc(group_ids, - (ncurves + 1) * sizeof(uint16_t)); + uint16_t *new_group_ids = (uint16_t *)OPENSSL_realloc( + group_ids, (ncurves + 1) * sizeof(uint16_t)); if (new_group_ids == NULL) { goto err; } @@ -1233,7 +1231,8 @@ static int ext_npn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, } OPENSSL_free(ssl->s3->next_proto_negotiated); - ssl->s3->next_proto_negotiated = BUF_memdup(selected, selected_len); + ssl->s3->next_proto_negotiated = + (uint8_t *)BUF_memdup(selected, selected_len); if (ssl->s3->next_proto_negotiated == NULL) { *out_alert = SSL_AD_INTERNAL_ERROR; return 0; @@ -1522,7 +1521,7 @@ int ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS_len(&protocol_name_list), ssl->ctx->alpn_select_cb_arg) == SSL_TLSEXT_ERR_OK) { OPENSSL_free(ssl->s3->alpn_selected); - ssl->s3->alpn_selected = BUF_memdup(selected, selected_len); + ssl->s3->alpn_selected = (uint8_t *)BUF_memdup(selected, selected_len); if (ssl->s3->alpn_selected == NULL) { *out_alert = SSL_AD_INTERNAL_ERROR; return 0; @@ -2197,7 +2196,8 @@ static int ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { /* Save the contents of the extension to repeat it in the second * ClientHello. */ hs->key_share_bytes_len = CBB_len(&kse_bytes); - hs->key_share_bytes = BUF_memdup(CBB_data(&kse_bytes), CBB_len(&kse_bytes)); + hs->key_share_bytes = + (uint8_t *)BUF_memdup(CBB_data(&kse_bytes), CBB_len(&kse_bytes)); if (hs->key_share_bytes == NULL) { return 0; } @@ -2451,7 +2451,7 @@ static int ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs, } hs->peer_supported_group_list = - OPENSSL_malloc(CBS_len(&supported_group_list)); + (uint16_t *)OPENSSL_malloc(CBS_len(&supported_group_list)); if (hs->peer_supported_group_list == NULL) { *out_alert = SSL_AD_INTERNAL_ERROR; return 0; @@ -2638,12 +2638,12 @@ static const struct tls_extension kExtensions[] = { #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension)) -OPENSSL_COMPILE_ASSERT(kNumExtensions <= - sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8, - too_many_extensions_for_sent_bitset); -OPENSSL_COMPILE_ASSERT( - kNumExtensions <= sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8, - too_many_extensions_for_received_bitset); +static_assert(kNumExtensions <= + sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8, + "too many extensions for sent bitset"); +static_assert(kNumExtensions <= + sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8, + "too many extensions for received bitset"); static const struct tls_extension *tls_extension_find(uint32_t *out_index, uint16_t value) { @@ -2674,7 +2674,8 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { CBB extensions; if (!CBB_add_u16_length_prefixed(out, &extensions)) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } hs->extensions.sent = 0; @@ -2692,7 +2693,8 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { grease_ext1 = ssl_get_grease_value(ssl, ssl_grease_extension1); if (!CBB_add_u16(&extensions, grease_ext1) || !CBB_add_u16(&extensions, 0 /* zero length */)) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } } @@ -2701,7 +2703,7 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { if (!kExtensions[i].add_clienthello(hs, &extensions)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION); ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value); - goto err; + return 0; } if (CBB_len(&extensions) != len_before) { @@ -2710,7 +2712,8 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { } if (!custom_ext_add_clienthello(hs, &extensions)) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } if (ssl->ctx->grease_enabled) { @@ -2727,7 +2730,8 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { if (!CBB_add_u16(&extensions, grease_ext2) || !CBB_add_u16(&extensions, 1 /* one byte length */) || !CBB_add_u8(&extensions, 0 /* single zero byte as contents */)) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } } @@ -2754,7 +2758,8 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { if (!CBB_add_u16(&extensions, TLSEXT_TYPE_padding) || !CBB_add_u16(&extensions, padding_len) || !CBB_add_space(&extensions, &padding_bytes, padding_len)) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } OPENSSL_memset(padding_bytes, 0, padding_len); @@ -2763,7 +2768,8 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { /* The PSK extension must be last, including after the padding. */ if (!ext_pre_shared_key_add_clienthello(hs, &extensions)) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } /* Discard empty extensions blocks. */ @@ -2772,10 +2778,6 @@ int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { } return CBB_flush(out); - -err: - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return 0; } int ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out) { @@ -2957,8 +2959,8 @@ static int ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs, continue; } - OPENSSL_COMPILE_ASSERT(kNumExtensions <= sizeof(hs->extensions.sent) * 8, - too_many_bits); + static_assert(kNumExtensions <= sizeof(hs->extensions.sent) * 8, + "too many bits"); if (!(hs->extensions.sent & (1u << ext_index)) && type != TLSEXT_TYPE_renegotiate) { @@ -3040,33 +3042,28 @@ static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_cipher_ctx(SSL *ssl, uint8_t **out, size_t *out_len, int *out_renew_ticket, const uint8_t *ticket, size_t ticket_len) { - enum ssl_ticket_aead_result_t ret = ssl_ticket_aead_ignore_ticket; const SSL_CTX *const ssl_ctx = ssl->session_ctx; - uint8_t *plaintext = NULL; - HMAC_CTX hmac_ctx; - HMAC_CTX_init(&hmac_ctx); - EVP_CIPHER_CTX cipher_ctx; - EVP_CIPHER_CTX_init(&cipher_ctx); + bssl::ScopedHMAC_CTX hmac_ctx; + bssl::ScopedEVP_CIPHER_CTX cipher_ctx; /* Ensure there is room for the key name and the largest IV * |tlsext_ticket_key_cb| may try to consume. The real limit may be lower, but * the maximum IV length should be well under the minimum size for the * session material and HMAC. */ if (ticket_len < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) { - goto out; + return ssl_ticket_aead_ignore_ticket; } const uint8_t *iv = ticket + SSL_TICKET_KEY_NAME_LEN; if (ssl_ctx->tlsext_ticket_key_cb != NULL) { int cb_ret = ssl_ctx->tlsext_ticket_key_cb( - ssl, (uint8_t *)ticket /* name */, (uint8_t *)iv, &cipher_ctx, - &hmac_ctx, 0 /* decrypt */); + ssl, (uint8_t *)ticket /* name */, (uint8_t *)iv, cipher_ctx.get(), + hmac_ctx.get(), 0 /* decrypt */); if (cb_ret < 0) { - ret = ssl_ticket_aead_error; - goto out; + return ssl_ticket_aead_error; } else if (cb_ret == 0) { - goto out; + return ssl_ticket_aead_ignore_ticket; } else if (cb_ret == 2) { *out_renew_ticket = 1; } @@ -3074,80 +3071,71 @@ ssl_decrypt_ticket_with_cipher_ctx(SSL *ssl, uint8_t **out, size_t *out_len, /* Check the key name matches. */ if (OPENSSL_memcmp(ticket, ssl_ctx->tlsext_tick_key_name, SSL_TICKET_KEY_NAME_LEN) != 0) { - goto out; + return ssl_ticket_aead_ignore_ticket; } - if (!HMAC_Init_ex(&hmac_ctx, ssl_ctx->tlsext_tick_hmac_key, + if (!HMAC_Init_ex(hmac_ctx.get(), ssl_ctx->tlsext_tick_hmac_key, sizeof(ssl_ctx->tlsext_tick_hmac_key), tlsext_tick_md(), NULL) || - !EVP_DecryptInit_ex(&cipher_ctx, EVP_aes_128_cbc(), NULL, + !EVP_DecryptInit_ex(cipher_ctx.get(), EVP_aes_128_cbc(), NULL, ssl_ctx->tlsext_tick_aes_key, iv)) { - ret = ssl_ticket_aead_error; - goto out; + return ssl_ticket_aead_error; } } - size_t iv_len = EVP_CIPHER_CTX_iv_length(&cipher_ctx); + size_t iv_len = EVP_CIPHER_CTX_iv_length(cipher_ctx.get()); /* Check the MAC at the end of the ticket. */ uint8_t mac[EVP_MAX_MD_SIZE]; - size_t mac_len = HMAC_size(&hmac_ctx); + size_t mac_len = HMAC_size(hmac_ctx.get()); if (ticket_len < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) { /* The ticket must be large enough for key name, IV, data, and MAC. */ - goto out; + return ssl_ticket_aead_ignore_ticket; } - HMAC_Update(&hmac_ctx, ticket, ticket_len - mac_len); - HMAC_Final(&hmac_ctx, mac, NULL); + HMAC_Update(hmac_ctx.get(), ticket, ticket_len - mac_len); + HMAC_Final(hmac_ctx.get(), mac, NULL); int mac_ok = CRYPTO_memcmp(mac, ticket + (ticket_len - mac_len), mac_len) == 0; #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) mac_ok = 1; #endif if (!mac_ok) { - goto out; + return ssl_ticket_aead_ignore_ticket; } /* Decrypt the session data. */ const uint8_t *ciphertext = ticket + SSL_TICKET_KEY_NAME_LEN + iv_len; size_t ciphertext_len = ticket_len - SSL_TICKET_KEY_NAME_LEN - iv_len - mac_len; - plaintext = OPENSSL_malloc(ciphertext_len); - if (plaintext == NULL) { - ret = ssl_ticket_aead_error; - goto out; + bssl::UniquePtr<uint8_t> plaintext((uint8_t *)OPENSSL_malloc(ciphertext_len)); + if (!plaintext) { + return ssl_ticket_aead_error; } size_t plaintext_len; #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) - OPENSSL_memcpy(plaintext, ciphertext, ciphertext_len); + OPENSSL_memcpy(plaintext.get(), ciphertext, ciphertext_len); plaintext_len = ciphertext_len; #else if (ciphertext_len >= INT_MAX) { - goto out; + return ssl_ticket_aead_ignore_ticket; } int len1, len2; - if (!EVP_DecryptUpdate(&cipher_ctx, plaintext, &len1, ciphertext, + if (!EVP_DecryptUpdate(cipher_ctx.get(), plaintext.get(), &len1, ciphertext, (int)ciphertext_len) || - !EVP_DecryptFinal_ex(&cipher_ctx, plaintext + len1, &len2)) { + !EVP_DecryptFinal_ex(cipher_ctx.get(), plaintext.get() + len1, &len2)) { ERR_clear_error(); - goto out; + return ssl_ticket_aead_ignore_ticket; } plaintext_len = (size_t)(len1) + len2; #endif - *out = plaintext; - plaintext = NULL; + *out = plaintext.release(); *out_len = plaintext_len; - ret = ssl_ticket_aead_success; - -out: - OPENSSL_free(plaintext); - HMAC_CTX_cleanup(&hmac_ctx); - EVP_CIPHER_CTX_cleanup(&cipher_ctx); - return ret; + return ssl_ticket_aead_success; } static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method( SSL *ssl, uint8_t **out, size_t *out_len, int *out_renew_ticket, const uint8_t *ticket, size_t ticket_len) { - uint8_t *plaintext = OPENSSL_malloc(ticket_len); + uint8_t *plaintext = (uint8_t *)OPENSSL_malloc(ticket_len); if (plaintext == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return ssl_ticket_aead_error; @@ -3238,7 +3226,7 @@ int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) { /* This multiplication doesn't overflow because sizeof(uint16_t) is two * and we just divided |num_sigalgs| by two. */ - hs->peer_sigalgs = OPENSSL_malloc(num_sigalgs * sizeof(uint16_t)); + hs->peer_sigalgs = (uint16_t *)OPENSSL_malloc(num_sigalgs * sizeof(uint16_t)); if (hs->peer_sigalgs == NULL) { return 0; } @@ -3324,7 +3312,6 @@ int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) { int tls1_verify_channel_id(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - int ret = 0; uint16_t extension_type; CBS extension, channel_id; @@ -3341,52 +3328,44 @@ int tls1_verify_channel_id(SSL_HANDSHAKE *hs) { return 0; } - EC_GROUP *p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + bssl::UniquePtr<EC_GROUP> p256( + EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); if (!p256) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT); return 0; } - EC_KEY *key = NULL; - EC_POINT *point = NULL; - BIGNUM x, y; - ECDSA_SIG sig; - BN_init(&x); - BN_init(&y); - sig.r = BN_new(); - sig.s = BN_new(); - if (sig.r == NULL || sig.s == NULL) { - goto err; + bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new()); + bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new()); + if (!sig || !x || !y) { + return 0; } const uint8_t *p = CBS_data(&extension); - if (BN_bin2bn(p + 0, 32, &x) == NULL || - BN_bin2bn(p + 32, 32, &y) == NULL || - BN_bin2bn(p + 64, 32, sig.r) == NULL || - BN_bin2bn(p + 96, 32, sig.s) == NULL) { - goto err; - } - - point = EC_POINT_new(p256); - if (point == NULL || - !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) { - goto err; + if (BN_bin2bn(p + 0, 32, x.get()) == NULL || + BN_bin2bn(p + 32, 32, y.get()) == NULL || + BN_bin2bn(p + 64, 32, sig->r) == NULL || + BN_bin2bn(p + 96, 32, sig->s) == NULL) { + return 0; } - key = EC_KEY_new(); - if (key == NULL || - !EC_KEY_set_group(key, p256) || - !EC_KEY_set_public_key(key, point)) { - goto err; + bssl::UniquePtr<EC_KEY> key(EC_KEY_new()); + bssl::UniquePtr<EC_POINT> point(EC_POINT_new(p256.get())); + if (!key || !point || + !EC_POINT_set_affine_coordinates_GFp(p256.get(), point.get(), x.get(), + y.get(), nullptr) || + !EC_KEY_set_group(key.get(), p256.get()) || + !EC_KEY_set_public_key(key.get(), point.get())) { + return 0; } uint8_t digest[EVP_MAX_MD_SIZE]; size_t digest_len; if (!tls1_channel_id_hash(hs, digest, &digest_len)) { - goto err; + return 0; } - int sig_ok = ECDSA_do_verify(digest, digest_len, &sig, key); + int sig_ok = ECDSA_do_verify(digest, digest_len, sig.get(), key.get()); #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) sig_ok = 1; #endif @@ -3394,21 +3373,11 @@ int tls1_verify_channel_id(SSL_HANDSHAKE *hs) { OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR); ssl->s3->tlsext_channel_id_valid = 0; - goto err; + return 0; } OPENSSL_memcpy(ssl->s3->tlsext_channel_id, p, 64); - ret = 1; - -err: - BN_free(&x); - BN_free(&y); - BN_free(sig.r); - BN_free(sig.s); - EC_KEY_free(key); - EC_POINT_free(point); - EC_GROUP_free(p256); - return ret; + return 1; } int tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) { @@ -3516,9 +3485,9 @@ int tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) { return -1; } - OPENSSL_COMPILE_ASSERT( + static_assert( sizeof(hs->new_session->original_handshake_hash) == EVP_MAX_MD_SIZE, - original_handshake_hash_is_too_small); + "original_handshake_hash is too small"); size_t digest_len; if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, @@ -3527,7 +3496,8 @@ int tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) { return -1; } - OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE <= 0xff, max_md_size_is_too_large); + static_assert(EVP_MAX_MD_SIZE <= 0xff, + "EVP_MAX_MD_SIZE does not fit in uint8_t"); hs->new_session->original_handshake_hash_len = (uint8_t)digest_len; return 1; diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc index 6d3e6d1c..cd846be4 100644 --- a/src/ssl/test/bssl_shim.cc +++ b/src/ssl/test/bssl_shim.cc @@ -39,6 +39,7 @@ OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib")) #include <assert.h> #include <inttypes.h> #include <string.h> +#include <time.h> #include <openssl/aead.h> #include <openssl/bio.h> @@ -969,6 +970,7 @@ static int ServerNameCallback(SSL *ssl, int *out_alert, void *arg) { // Connect returns a new socket connected to localhost on |port| or -1 on // error. static int Connect(uint16_t port) { + time_t start_time = time(nullptr); for (int af : { AF_INET6, AF_INET }) { int sock = socket(af, SOCK_STREAM, 0); if (sock == -1) { @@ -1013,6 +1015,13 @@ static int Connect(uint16_t port) { } closesocket(sock); } + + PrintSocketError("connect"); + // TODO(davidben): Remove this logging when https://crbug.com/boringssl/199 is + // resolved. + fprintf(stderr, "start_time = %lld, end_time = %lld\n", + static_cast<long long>(start_time), + static_cast<long long>(time(nullptr))); return -1; } @@ -1171,6 +1180,9 @@ static bssl::UniquePtr<SSL_CTX> SetupCtx(SSL_CTX *old_ctx, SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1); } + SSL_CTX_set_tls13_variant( + ssl_ctx.get(), static_cast<enum tls13_variant_t>(config->tls13_variant)); + if (config->allow_unknown_alpn_protos) { SSL_CTX_set_allow_unknown_alpn_protos(ssl_ctx.get(), 1); } @@ -1691,6 +1703,12 @@ static bool WriteSettings(int i, const TestConfig *config, return false; } + if (config->tls13_variant != 0 && + (!CBB_add_u16(cbb.get(), kTLS13Variant) || + !CBB_add_u8(cbb.get(), static_cast<uint8_t>(config->tls13_variant)))) { + return false; + } + uint8_t *settings; size_t settings_len; if (!CBB_add_u16(cbb.get(), kDataTag) || diff --git a/src/ssl/test/fuzzer.h b/src/ssl/test/fuzzer.h index 2f816534..e52f55e1 100644 --- a/src/ssl/test/fuzzer.h +++ b/src/ssl/test/fuzzer.h @@ -40,12 +40,16 @@ static const uint16_t kSessionTag = 1; // certificates. static const uint16_t kRequestClientCert = 2; +// kTLS13Variant is followed by a u8 denoting the TLS 1.3 variant to configure. +static const uint16_t kTLS13Variant = 3; + // SetupTest parses parameters from |cbs| and returns a newly-configured |SSL| // object or nullptr on error. On success, the caller should feed the remaining // input in |cbs| to the SSL stack. static inline bssl::UniquePtr<SSL> SetupTest(CBS *cbs, SSL_CTX *ctx, bool is_server) { - // Clear any sessions saved in |ctx| from the previous run. + // |ctx| is shared between runs, so we must clear any modifications to it made + // later on in this function. SSL_CTX_flush_sessions(ctx, 0); bssl::UniquePtr<SSL> ssl(SSL_new(ctx)); @@ -89,6 +93,18 @@ static inline bssl::UniquePtr<SSL> SetupTest(CBS *cbs, SSL_CTX *ctx, } SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, nullptr); break; + + case kTLS13Variant: { + uint8_t variant; + if (!CBS_get_u8(cbs, &variant)) { + return nullptr; + } + SSL_set_tls13_variant(ssl.get(), static_cast<tls13_variant_t>(variant)); + break; + } + + default: + return nullptr; } } } diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go index 9e7b2044..fd9fb3d5 100644 --- a/src/ssl/test/runner/common.go +++ b/src/ssl/test/runner/common.go @@ -32,10 +32,22 @@ const ( ) // A draft version of TLS 1.3 that is sent over the wire for the current draft. -const tls13DraftVersion = 0x7f12 +const ( + tls13DraftVersion = 0x7f12 + tls13ExperimentVersion = 0x7e01 + tls13RecordTypeExperimentVersion = 0x7a12 +) + +const ( + TLS13Default = 0 + TLS13Experiment = 1 + TLS13RecordTypeExperiment = 2 +) var allTLSWireVersions = []uint16{ tls13DraftVersion, + tls13ExperimentVersion, + tls13RecordTypeExperimentVersion, VersionTLS12, VersionTLS11, VersionTLS10, @@ -62,10 +74,11 @@ const ( type recordType uint8 const ( - recordTypeChangeCipherSpec recordType = 20 - recordTypeAlert recordType = 21 - recordTypeHandshake recordType = 22 - recordTypeApplicationData recordType = 23 + recordTypeChangeCipherSpec recordType = 20 + recordTypeAlert recordType = 21 + recordTypeHandshake recordType = 22 + recordTypeApplicationData recordType = 23 + recordTypePlaintextHandshake recordType = 24 ) // TLS handshake message types. @@ -404,6 +417,9 @@ type Config struct { // which is currently TLS 1.2. MaxVersion uint16 + // TLS13Variant is the variant of TLS 1.3 to use. + TLS13Variant int + // CurvePreferences contains the elliptic curves that will be used in // an ECDHE handshake, in preference order. If empty, the default will // be used. @@ -1250,6 +1266,10 @@ type ProtocolBugs struct { // specified value in ServerHello version field. SendServerHelloVersion uint16 + // SendServerSupportedExtensionVersion, if non-zero, causes the server to send + // the specified value in supported_versions extension in the ServerHello. + SendServerSupportedExtensionVersion uint16 + // SkipHelloRetryRequest, if true, causes the TLS 1.3 server to not send // HelloRetryRequest. SkipHelloRetryRequest bool @@ -1364,6 +1384,14 @@ type ProtocolBugs struct { // RejectUnsolicitedKeyUpdate, if true, causes all unsolicited // KeyUpdates from the peer to be rejected. RejectUnsolicitedKeyUpdate bool + + // OmitExtensions, if true, causes the extensions field in ClientHello + // and ServerHello messages to be omitted. + OmitExtensions bool + + // EmptyExtensions, if true, causese the extensions field in ClientHello + // and ServerHello messages to be present, but empty. + EmptyExtensions bool } func (c *Config) serverInit() { @@ -1468,6 +1496,12 @@ func (c *Config) defaultCurves() map[CurveID]bool { // 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 != TLS13Experiment && wireVers == tls13ExperimentVersion) || + (c.TLS13Variant != TLS13RecordTypeExperiment && wireVers == tls13RecordTypeExperimentVersion) || + (c.TLS13Variant != TLS13Default && wireVers == tls13DraftVersion) { + return 0, false + } + vers, ok := wireToVersion(wireVers, isDTLS) if !ok || c.minVersion(isDTLS) > vers || vers > c.maxVersion(isDTLS) { return 0, false diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go index 61fc9d31..c974bd43 100644 --- a/src/ssl/test/runner/conn.go +++ b/src/ssl/test/runner/conn.go @@ -762,6 +762,11 @@ RestartReadRecord: return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received")) } + // Accept server_plaintext_handshake records when the content type TLS 1.3 variant is enabled. + if c.isClient && c.in.cipher == nil && c.config.TLS13Variant == TLS13RecordTypeExperiment && want == recordTypeHandshake && typ == recordTypePlaintextHandshake { + typ = recordTypeHandshake + } + vers := uint16(b.data[1])<<8 | uint16(b.data[2]) n := int(b.data[3])<<8 | int(b.data[4]) @@ -916,9 +921,11 @@ Again: c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) break } - err := c.in.changeCipherSpec(c.config) - if err != nil { - c.in.setErrorLocked(c.sendAlert(err.(alert))) + if c.wireVersion != tls13ExperimentVersion { + err := c.in.changeCipherSpec(c.config) + if err != nil { + c.in.setErrorLocked(c.sendAlert(err.(alert))) + } } case recordTypeApplicationData: @@ -1138,15 +1145,10 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) { } c.out.freeBlock(b) - if typ == recordTypeChangeCipherSpec { + if typ == recordTypeChangeCipherSpec && c.wireVersion != tls13ExperimentVersion { err = c.out.changeCipherSpec(c.config) if err != nil { - // Cannot call sendAlert directly, - // because we already hold c.out.Mutex. - c.tmp[0] = alertLevelError - c.tmp[1] = byte(err.(alert)) - c.writeRecord(recordTypeAlert, c.tmp[0:2]) - return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) + return n, c.sendAlertLocked(alertLevelError, err.(alert)) } } return diff --git a/src/ssl/test/runner/dtls.go b/src/ssl/test/runner/dtls.go index d46b247a..72369d60 100644 --- a/src/ssl/test/runner/dtls.go +++ b/src/ssl/test/runner/dtls.go @@ -35,7 +35,7 @@ func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) { switch vers { case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12: return vers, true - case tls13DraftVersion: + case tls13DraftVersion, tls13ExperimentVersion, tls13RecordTypeExperimentVersion: return VersionTLS13, true } } @@ -159,12 +159,7 @@ func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) { if typ == recordTypeChangeCipherSpec { err = c.out.changeCipherSpec(c.config) if err != nil { - // Cannot call sendAlert directly, - // because we already hold c.out.Mutex. - c.tmp[0] = alertLevelError - c.tmp[1] = byte(err.(alert)) - c.writeRecord(recordTypeAlert, c.tmp[0:2]) - return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) + return n, c.sendAlertLocked(alertLevelError, err.(alert)) } } return diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json index d2f64efc..3957bea1 100644 --- a/src/ssl/test/runner/fuzzer_mode.json +++ b/src/ssl/test/runner/fuzzer_mode.json @@ -19,9 +19,9 @@ "BadECDSA-*": "Fuzzer mode always accepts a signature.", "*-InvalidSignature-*": "Fuzzer mode always accepts a signature.", - "*Auth-Verify-RSA-PKCS1-*-TLS13": "Fuzzer mode always accepts a signature.", - "*Auth-Verify-ECDSA-SHA1-TLS13": "Fuzzer mode always accepts a signature.", - "*Auth-Verify-ECDSA-P224-*-TLS13": "Fuzzer mode always accepts a signature.", + "*Auth-Verify-RSA-PKCS1-*-TLS13*": "Fuzzer mode always accepts a signature.", + "*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.", "InvalidChannelIDSignature-*": "Fuzzer mode always accepts a signature.", @@ -36,17 +36,17 @@ "Resume-Server-*Binder*": "Fuzzer mode does not check binders.", "SkipEarlyData*": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyDataChannelID-OfferBoth-Server": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-NonZeroRTTSession-Server": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-SkipEndOfEarlyData": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-ALPNMismatch-Server": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-ALPNOmitted1-Client": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-ALPNOmitted2-Client": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-ALPNOmitted1-Server": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-ALPNOmitted2-Server": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-RejectUnfinishedWrite-Client-*": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-Reject-Client": "Trial decryption does not work with the NULL cipher.", - "TLS13-EarlyData-RejectTicket-Client": "Trial decryption does not work with the NULL cipher.", + "*-EarlyDataChannelID-OfferBoth-Server": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-NonZeroRTTSession-Server": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-SkipEndOfEarlyData": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-ALPNMismatch-Server": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-ALPNOmitted1-Client": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-ALPNOmitted2-Client": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-ALPNOmitted1-Server": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-ALPNOmitted2-Server": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-RejectUnfinishedWrite-Client-*": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-Reject-Client": "Trial decryption does not work with the NULL cipher.", + "*-EarlyData-RejectTicket-Client": "Trial decryption does not work with the NULL cipher.", "Renegotiate-Client-BadExt*": "Fuzzer mode does not check renegotiation_info." } diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go index f0bfca48..05e7311c 100644 --- a/src/ssl/test/runner/handshake_client.go +++ b/src/ssl/test/runner/handshake_client.go @@ -84,7 +84,6 @@ func (c *Conn) clientHandshake() error { sctListSupported: !c.config.Bugs.NoSignedCertificateTimestamps, serverName: c.config.ServerName, supportedCurves: c.config.curvePreferences(), - pskKEModes: []byte{pskDHEKEMode}, supportedPoints: []uint8{pointFormatUncompressed}, nextProtoNeg: len(c.config.NextProtos) > 0, secureRenegotiation: []byte{}, @@ -97,6 +96,8 @@ func (c *Conn) clientHandshake() error { srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer, customExtension: c.config.Bugs.CustomExtension, pskBinderFirst: c.config.Bugs.PSKBinderFirst, + omitExtensions: c.config.Bugs.OmitExtensions, + emptyExtensions: c.config.Bugs.EmptyExtensions, } if maxVersion >= VersionTLS13 { @@ -104,6 +105,7 @@ func (c *Conn) clientHandshake() error { if !c.config.Bugs.OmitSupportedVersions { hello.supportedVersions = c.config.supportedVersions(c.isDTLS) } + hello.pskKEModes = []byte{pskDHEKEMode} } else { hello.vers = mapClientHelloVersion(maxVersion, c.isDTLS) } @@ -732,6 +734,12 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { hs.finishedHash.addEntropy(zeroSecret) } + if c.wireVersion == tls13ExperimentVersion { + if err := c.readRecord(recordTypeChangeCipherSpec); err != nil { + return err + } + } + // Derive handshake traffic keys and switch read key to handshake // traffic key. clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel) @@ -911,6 +919,11 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { } c.sendAlert(alertEndOfEarlyData) } + + if c.wireVersion == tls13ExperimentVersion { + c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + } + c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite) if certReq != nil && !c.config.Bugs.SkipClientCertificate { diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go index 86e2821d..4be873d8 100644 --- a/src/ssl/test/runner/handshake_messages.go +++ b/src/ssl/test/runner/handshake_messages.go @@ -7,6 +7,7 @@ package runner import ( "bytes" "encoding/binary" + "fmt" ) func writeLen(buf []byte, v, size int) { @@ -35,6 +36,11 @@ func (bb *byteBuilder) len() int { return len(*bb.buf) - bb.start - bb.prefixLen } +func (bb *byteBuilder) data() []byte { + bb.flush() + return (*bb.buf)[bb.start+bb.prefixLen:] +} + func (bb *byteBuilder) flush() { if bb.child == nil { return @@ -112,11 +118,11 @@ func (bb *byteBuilder) createChild(lengthPrefixSize int) *byteBuilder { } func (bb *byteBuilder) discardChild() { - if bb.child != nil { + if bb.child == nil { return } + *bb.buf = (*bb.buf)[:bb.child.start] bb.child = nil - *bb.buf = (*bb.buf)[:bb.start] } type keyShareEntry struct { @@ -167,6 +173,8 @@ type clientHelloMsg struct { customExtension string hasGREASEExtension bool pskBinderFirst bool + omitExtensions bool + emptyExtensions bool } func (m *clientHelloMsg) equal(i interface{}) bool { @@ -212,7 +220,9 @@ func (m *clientHelloMsg) equal(i interface{}) bool { m.sctListSupported == m1.sctListSupported && m.customExtension == m1.customExtension && m.hasGREASEExtension == m1.hasGREASEExtension && - m.pskBinderFirst == m1.pskBinderFirst + m.pskBinderFirst == m1.pskBinderFirst && + m.omitExtensions == m1.omitExtensions && + m.emptyExtensions == m1.emptyExtensions } func (m *clientHelloMsg) marshal() []byte { @@ -444,8 +454,12 @@ func (m *clientHelloMsg) marshal() []byte { } } - if extensions.len() == 0 { + if m.omitExtensions || m.emptyExtensions { + // Silently erase any extensions which were sent. hello.discardChild() + if m.emptyExtensions { + hello.addU16(0) + } } m.raw = handshakeMsg.finish() @@ -813,21 +827,24 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { } type serverHelloMsg struct { - raw []byte - isDTLS bool - vers uint16 - versOverride uint16 - random []byte - sessionId []byte - cipherSuite uint16 - hasKeyShare bool - keyShare keyShareEntry - hasPSKIdentity bool - pskIdentity uint16 - compressionMethod uint8 - customExtension string - unencryptedALPN string - extensions serverExtensions + raw []byte + isDTLS bool + vers uint16 + versOverride uint16 + supportedVersOverride uint16 + random []byte + sessionId []byte + cipherSuite uint16 + hasKeyShare bool + keyShare keyShareEntry + hasPSKIdentity bool + pskIdentity uint16 + compressionMethod uint8 + customExtension string + unencryptedALPN string + omitExtensions bool + emptyExtensions bool + extensions serverExtensions } func (m *serverHelloMsg) marshal() []byte { @@ -848,17 +865,19 @@ func (m *serverHelloMsg) marshal() []byte { } if m.versOverride != 0 { hello.addU16(m.versOverride) + } else if m.vers == tls13ExperimentVersion { + hello.addU16(VersionTLS12) } else { hello.addU16(m.vers) } hello.addBytes(m.random) - if vers < VersionTLS13 { + if vers < VersionTLS13 || m.vers == tls13ExperimentVersion { sessionId := hello.addU8LengthPrefixed() sessionId.addBytes(m.sessionId) } hello.addU16(m.cipherSuite) - if vers < VersionTLS13 { + if vers < VersionTLS13 || m.vers == tls13ExperimentVersion { hello.addU8(m.compressionMethod) } @@ -877,6 +896,15 @@ func (m *serverHelloMsg) marshal() []byte { extensions.addU16(2) // Length extensions.addU16(m.pskIdentity) } + if m.vers == tls13ExperimentVersion || m.supportedVersOverride != 0 { + extensions.addU16(extensionSupportedVersions) + extensions.addU16(2) // Length + if m.supportedVersOverride != 0 { + extensions.addU16(m.supportedVersOverride) + } else { + extensions.addU16(m.vers) + } + } if len(m.customExtension) > 0 { extensions.addU16(extensionCustom) customExt := extensions.addU16LengthPrefixed() @@ -892,8 +920,17 @@ func (m *serverHelloMsg) marshal() []byte { } } else { m.extensions.marshal(extensions) - if extensions.len() == 0 { + if m.omitExtensions || m.emptyExtensions { + // Silently erasing server extensions will break the handshake. Instead, + // assert that tests which use this field also disable all features which + // would write an extension. + if extensions.len() != 0 { + panic(fmt.Sprintf("ServerHello unexpectedly contained extensions: %x, %+v", extensions.data(), m)) + } hello.discardChild() + if m.emptyExtensions { + hello.addU16(0) + } } } @@ -913,7 +950,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { } m.random = data[6:38] data = data[38:] - if vers < VersionTLS13 { + if vers < VersionTLS13 || m.vers == tls13ExperimentVersion { sessionIdLen := int(data[0]) if sessionIdLen > 32 || len(data) < 1+sessionIdLen { return false @@ -926,7 +963,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { } m.cipherSuite = uint16(data[0])<<8 | uint16(data[1]) data = data[2:] - if vers < VersionTLS13 { + if vers < VersionTLS13 || m.vers == tls13ExperimentVersion { if len(data) < 1 { return false } @@ -949,6 +986,36 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { return false } + // Parse out the version from supported_versions if available. + if m.vers == VersionTLS12 { + vdata := data + for len(vdata) != 0 { + if len(vdata) < 4 { + return false + } + extension := uint16(vdata[0])<<8 | uint16(vdata[1]) + length := int(vdata[2])<<8 | int(vdata[3]) + vdata = vdata[4:] + + if len(vdata) < length { + return false + } + d := vdata[:length] + vdata = vdata[length:] + + if extension == extensionSupportedVersions { + if len(d) < 2 { + return false + } + m.vers = uint16(d[0])<<8 | uint16(d[1]) + vers, ok = wireToVersion(m.vers, m.isDTLS) + if !ok { + return false + } + } + } + } + if vers >= VersionTLS13 { for len(data) != 0 { if len(data) < 4 { @@ -983,6 +1050,10 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { } m.pskIdentity = uint16(d[0])<<8 | uint16(d[1]) m.hasPSKIdentity = true + case extensionSupportedVersions: + if m.vers != tls13ExperimentVersion { + return false + } default: // Only allow the 3 extensions that are sent in // the clear in TLS 1.3. @@ -1059,6 +1130,7 @@ type serverExtensions struct { hasKeyShare bool hasEarlyData bool keyShare keyShareEntry + supportedVersion uint16 supportedPoints []uint8 serverNameAck bool } @@ -1155,6 +1227,11 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) { keyExchange := keyShare.addU16LengthPrefixed() keyExchange.addBytes(m.keyShare.keyExchange) } + if m.supportedVersion != 0 { + extensions.addU16(extensionSupportedVersions) + extensions.addU16(2) // Length + extensions.addU16(m.supportedVersion) + } if len(m.supportedPoints) > 0 { // http://tools.ietf.org/html/rfc4492#section-5.1.2 extensions.addU16(extensionSupportedPoints) diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go index f70f4697..b31a562e 100644 --- a/src/ssl/test/runner/handshake_server.go +++ b/src/ssl/test/runner/handshake_server.go @@ -281,7 +281,7 @@ func (hs *serverHandshakeState) readClientHello() error { } if config.Bugs.ExpectNoTLS12Session { - if len(hs.clientHello.sessionId) > 0 { + if len(hs.clientHello.sessionId) > 0 && c.wireVersion != tls13ExperimentVersion { return fmt.Errorf("tls: client offered an unexpected session ID") } if len(hs.clientHello.sessionTicket) > 0 { @@ -359,11 +359,13 @@ func (hs *serverHandshakeState) doTLS13Handshake() error { config := c.config hs.hello = &serverHelloMsg{ - isDTLS: c.isDTLS, - vers: c.wireVersion, - versOverride: config.Bugs.SendServerHelloVersion, - customExtension: config.Bugs.CustomUnencryptedExtension, - unencryptedALPN: config.Bugs.SendUnencryptedALPN, + isDTLS: c.isDTLS, + vers: c.wireVersion, + sessionId: hs.clientHello.sessionId, + versOverride: config.Bugs.SendServerHelloVersion, + supportedVersOverride: config.Bugs.SendServerSupportedExtensionVersion, + customExtension: config.Bugs.CustomUnencryptedExtension, + unencryptedALPN: config.Bugs.SendUnencryptedALPN, } hs.hello.random = make([]byte, 32) @@ -571,7 +573,11 @@ ResendHelloRetryRequest: if sendHelloRetryRequest { oldClientHelloBytes := hs.clientHello.marshal() hs.writeServerHash(helloRetryRequest.marshal()) - c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal()) + if c.vers == tls13RecordTypeExperimentVersion { + c.writeRecord(recordTypePlaintextHandshake, helloRetryRequest.marshal()) + } else { + c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal()) + } c.flushHandshake() if hs.clientHello.hasEarlyData { @@ -749,10 +755,18 @@ ResendHelloRetryRequest: toWrite = append(toWrite, typeEncryptedExtensions) c.writeRecord(recordTypeHandshake, toWrite) } else { - c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + if c.vers == tls13RecordTypeExperimentVersion { + c.writeRecord(recordTypePlaintextHandshake, hs.hello.marshal()) + } else { + c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + } } c.flushHandshake() + if c.wireVersion == tls13ExperimentVersion { + c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + } + // Switch to handshake traffic keys. serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel) c.out.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite) @@ -913,6 +927,12 @@ ResendHelloRetryRequest: } } + if c.wireVersion == tls13ExperimentVersion && !c.skipEarlyData { + if err := c.readRecord(recordTypeChangeCipherSpec); err != nil { + return err + } + } + // Switch input stream to handshake traffic keys. c.in.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite) @@ -1045,6 +1065,11 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) vers: c.wireVersion, versOverride: config.Bugs.SendServerHelloVersion, compressionMethod: config.Bugs.SendCompressionMethod, + extensions: serverExtensions{ + supportedVersion: config.Bugs.SendServerSupportedExtensionVersion, + }, + omitExtensions: config.Bugs.OmitExtensions, + emptyExtensions: config.Bugs.EmptyExtensions, } hs.hello.random = make([]byte, 32) diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go index 03ba7555..29747db6 100644 --- a/src/ssl/test/runner/runner.go +++ b/src/ssl/test/runner/runner.go @@ -263,12 +263,9 @@ func getShimKey(t testCert) string { panic("Unknown test certificate") } -// configVersionToWire maps a protocol version to the default wire version to -// test at that protocol. -// -// TODO(davidben): Rather than mapping these, make tlsVersions contains a list -// of wire versions and test all of them. -func configVersionToWire(vers uint16, protocol protocol) uint16 { +// recordVersionToWire maps a record-layer protocol version to its wire +// representation. +func recordVersionToWire(vers uint16, protocol protocol) uint16 { if protocol == dtls { switch vers { case VersionTLS12: @@ -280,8 +277,6 @@ func configVersionToWire(vers uint16, protocol protocol) uint16 { switch vers { case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12: return vers - case VersionTLS13: - return tls13DraftVersion } } @@ -461,6 +456,10 @@ type testCase struct { // resumeShimPrefix is the prefix that the shim will send to the server on a // resumption. resumeShimPrefix string + // tls13Variant, if non-zero, causes both runner and shim to be + // configured with the specified TLS 1.3 variant. This is a convenience + // option for configuring both concurrently. + tls13Variant int } var testCases []testCase @@ -882,18 +881,26 @@ var ( // exit first. func acceptOrWait(listener *net.TCPListener, waitChan chan error) (net.Conn, error) { type connOrError struct { - conn net.Conn - err error + conn net.Conn + err error + startTime, endTime time.Time } connChan := make(chan connOrError, 1) go func() { + startTime := time.Now() listener.SetDeadline(time.Now().Add(*idleTimeout)) conn, err := listener.Accept() - connChan <- connOrError{conn, err} + endTime := time.Now() + connChan <- connOrError{conn, err, startTime, endTime} close(connChan) }() select { case result := <-connChan: + if result.err != nil { + // TODO(davidben): Remove this logging when + // https://crbug.com/boringssl/199 is resolved. + fmt.Fprintf(os.Stderr, "acceptOrWait failed, startTime=%v, endTime=%v\n", result.startTime, result.endTime) + } return result.conn, result.err case childErr := <-waitChan: waitChan <- childErr @@ -935,11 +942,23 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error { continue } - if test.config.MaxVersion != 0 || test.config.MinVersion != 0 || test.expectedVersion != 0 { - continue + if test.config.MaxVersion == 0 && test.config.MinVersion == 0 && test.expectedVersion == 0 { + panic(fmt.Sprintf("The name of test %q suggests that it's version specific, but min/max version in the Config is %x/%x. One of them should probably be %x", test.name, test.config.MinVersion, test.config.MaxVersion, ver.version)) + } + + if ver.tls13Variant != 0 { + var foundFlag bool + for _, flag := range test.flags { + if flag == "-tls13-variant" { + foundFlag = true + break + } + } + if !foundFlag && test.config.TLS13Variant != ver.tls13Variant && test.tls13Variant != ver.tls13Variant { + panic(fmt.Sprintf("The name of test %q suggests that uses an experimental TLS 1.3 variant, but neither the shim nor the runner configures it", test.name)) + } } - panic(fmt.Sprintf("The name of test %q suggests that it's version specific, but min/max version in the Config is %x/%x. One of them should probably be %x", test.name, test.config.MinVersion, test.config.MaxVersion, ver.version)) } listener, err := net.ListenTCP("tcp", &net.TCPAddr{IP: net.IPv6loopback}) @@ -1018,6 +1037,11 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error { flags = append(flags, "-tls-unique") } + if test.tls13Variant != 0 { + test.config.TLS13Variant = test.tls13Variant + flags = append(flags, "-tls13-variant", strconv.Itoa(test.tls13Variant)) + } + var transcriptPrefix string if len(*transcriptDir) != 0 { protocol := "tls" @@ -1191,29 +1215,100 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error { } type tlsVersion struct { - name string + name string + // version is the protocol version. version uint16 // excludeFlag is the legacy shim flag to disable the version. excludeFlag string hasDTLS bool - // shimTLS and shimDTLS are values the shim uses to refer to these - // versions in TLS and DTLS, respectively. - shimTLS, shimDTLS int + // versionDTLS, if non-zero, is the DTLS-specific representation of the version. + versionDTLS uint16 + // versionWire, if non-zero, is the wire representation of the + // version. Otherwise the wire version is the protocol version or + // versionDTLS. + versionWire uint16 + tls13Variant int } func (vers tlsVersion) shimFlag(protocol protocol) string { - if protocol == dtls { - return strconv.Itoa(vers.shimDTLS) + // The shim uses the protocol version in its public API, but uses the + // DTLS-specific version if it exists. + if protocol == dtls && vers.versionDTLS != 0 { + return strconv.Itoa(int(vers.versionDTLS)) } - return strconv.Itoa(vers.shimTLS) + return strconv.Itoa(int(vers.version)) +} + +func (vers tlsVersion) wire(protocol protocol) uint16 { + if protocol == dtls && vers.versionDTLS != 0 { + return vers.versionDTLS + } + if vers.versionWire != 0 { + return vers.versionWire + } + return vers.version } var tlsVersions = []tlsVersion{ - {"SSL3", VersionSSL30, "-no-ssl3", false, VersionSSL30, 0}, - {"TLS1", VersionTLS10, "-no-tls1", true, VersionTLS10, VersionDTLS10}, - {"TLS11", VersionTLS11, "-no-tls11", false, VersionTLS11, 0}, - {"TLS12", VersionTLS12, "-no-tls12", true, VersionTLS12, VersionDTLS12}, - {"TLS13", VersionTLS13, "-no-tls13", false, VersionTLS13, 0}, + { + name: "SSL3", + version: VersionSSL30, + excludeFlag: "-no-ssl3", + }, + { + name: "TLS1", + version: VersionTLS10, + excludeFlag: "-no-tls1", + hasDTLS: true, + versionDTLS: VersionDTLS10, + }, + { + name: "TLS11", + version: VersionTLS11, + excludeFlag: "-no-tls11", + }, + { + name: "TLS12", + version: VersionTLS12, + excludeFlag: "-no-tls12", + hasDTLS: true, + versionDTLS: VersionDTLS12, + }, + { + name: "TLS13", + version: VersionTLS13, + excludeFlag: "-no-tls13", + versionWire: tls13DraftVersion, + tls13Variant: TLS13Default, + }, + { + name: "TLS13Experiment", + version: VersionTLS13, + excludeFlag: "-no-tls13", + versionWire: tls13ExperimentVersion, + tls13Variant: TLS13Experiment, + }, + { + name: "TLS13RecordTypeExperiment", + version: VersionTLS13, + excludeFlag: "-no-tls13", + versionWire: tls13RecordTypeExperimentVersion, + tls13Variant: TLS13RecordTypeExperiment, + }, +} + +func allVersions(protocol protocol) []tlsVersion { + if protocol == tls { + return tlsVersions + } + + var ret []tlsVersion + for _, vers := range tlsVersions { + if vers.hasDTLS { + ret = append(ret, vers) + } + } + return ret } type testCipherSuite struct { @@ -2735,6 +2830,7 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto AdvertiseAllConfiguredCiphers: true, }, }, + tls13Variant: ver.tls13Variant, certFile: certFile, keyFile: keyFile, flags: flags, @@ -2760,6 +2856,7 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto SendCipherSuite: sendCipherSuite, }, }, + tls13Variant: ver.tls13Variant, flags: flags, resumeSession: true, shouldFail: shouldClientFail, @@ -2783,8 +2880,9 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto PreSharedKey: []byte(psk), PreSharedKeyIdentity: pskIdentity, }, - flags: flags, - messageLen: maxPlaintext, + tls13Variant: ver.tls13Variant, + flags: flags, + messageLen: maxPlaintext, }) // Test bad records for all ciphers. Bad records are fatal in TLS @@ -2807,6 +2905,7 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto PreSharedKey: []byte(psk), PreSharedKeyIdentity: pskIdentity, }, + tls13Variant: ver.tls13Variant, flags: flags, damageFirstWrite: true, messageLen: maxPlaintext, @@ -3274,6 +3373,7 @@ func addClientAuthTests() { ClientAuth: RequireAnyClientCert, ClientCAs: certPool, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-cert-file", path.Join(*resourceDir, rsaCertificateFile), "-key-file", path.Join(*resourceDir, rsaKeyFile), @@ -3287,7 +3387,8 @@ func addClientAuthTests() { MaxVersion: ver.version, Certificates: []Certificate{rsaCertificate}, }, - flags: []string{"-require-any-client-certificate"}, + tls13Variant: ver.tls13Variant, + flags: []string{"-require-any-client-certificate"}, }) if ver.version != VersionSSL30 { testCases = append(testCases, testCase{ @@ -3298,7 +3399,8 @@ func addClientAuthTests() { MaxVersion: ver.version, Certificates: []Certificate{ecdsaP256Certificate}, }, - flags: []string{"-require-any-client-certificate"}, + tls13Variant: ver.tls13Variant, + flags: []string{"-require-any-client-certificate"}, }) testCases = append(testCases, testCase{ testType: clientTest, @@ -3309,6 +3411,7 @@ func addClientAuthTests() { ClientAuth: RequireAnyClientCert, ClientCAs: certPool, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile), "-key-file", path.Join(*resourceDir, ecdsaP256KeyFile), @@ -3323,6 +3426,7 @@ func addClientAuthTests() { MaxVersion: ver.version, ClientAuth: RequireAnyClientCert, }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedLocalError: "client didn't provide a certificate", }) @@ -3336,6 +3440,7 @@ func addClientAuthTests() { MinVersion: ver.version, MaxVersion: ver.version, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-expect-verify-result", }, @@ -3351,6 +3456,7 @@ func addClientAuthTests() { MinVersion: ver.version, MaxVersion: ver.version, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-expect-verify-result", "-verify-peer", @@ -3372,6 +3478,7 @@ func addClientAuthTests() { MaxVersion: ver.version, }, flags: []string{"-require-any-client-certificate"}, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:", expectedLocalError: certificateRequired, @@ -3390,6 +3497,7 @@ func addClientAuthTests() { }, // Setting SSL_VERIFY_PEER allows anonymous clients. flags: []string{"-verify-peer"}, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":UNEXPECTED_MESSAGE:", }) @@ -3405,6 +3513,7 @@ func addClientAuthTests() { "-enable-channel-id", "-verify-peer-if-no-obc", }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:", expectedLocalError: certificateRequired, @@ -3419,6 +3528,7 @@ func addClientAuthTests() { ChannelID: channelIDKey, }, expectChannelID: true, + tls13Variant: ver.tls13Variant, flags: []string{ "-enable-channel-id", "-verify-peer-if-no-obc", @@ -3437,6 +3547,7 @@ func addClientAuthTests() { ExpectCertificateReqNames: caNames, }, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-require-any-client-certificate", "-use-client-ca-list", encodeDERValues(caNames), @@ -3453,6 +3564,7 @@ func addClientAuthTests() { ClientAuth: RequireAnyClientCert, ClientCAs: certPool, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-cert-file", path.Join(*resourceDir, rsaCertificateFile), "-key-file", path.Join(*resourceDir, rsaKeyFile), @@ -3552,8 +3664,9 @@ func addExtendedMasterSecretTests() { RequireExtendedMasterSecret: with, }, }, - flags: flags, - shouldFail: ver.version == VersionSSL30 && with, + tls13Variant: ver.tls13Variant, + flags: flags, + shouldFail: ver.version == VersionSSL30 && with, } if test.shouldFail { test.expectedLocalError = "extended master secret required but not supported by peer" @@ -3892,6 +4005,62 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { tests = append(tests, testCase{ testType: clientTest, + name: "TLS13Experiment-EarlyData-Client", + config: Config{ + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + TLS13Variant: TLS13Experiment, + MaxEarlyDataSize: 16384, + }, + resumeConfig: &Config{ + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + TLS13Variant: TLS13Experiment, + MaxEarlyDataSize: 16384, + Bugs: ProtocolBugs{ + ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}}, + }, + }, + resumeSession: true, + flags: []string{ + "-enable-early-data", + "-expect-early-data-info", + "-expect-accept-early-data", + "-on-resume-shim-writes-first", + "-tls13-variant", "1", + }, + }) + + tests = append(tests, testCase{ + testType: clientTest, + name: "TLS13RecordTypeExperiment-EarlyData-Client", + config: Config{ + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + TLS13Variant: TLS13RecordTypeExperiment, + MaxEarlyDataSize: 16384, + }, + resumeConfig: &Config{ + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + TLS13Variant: TLS13RecordTypeExperiment, + MaxEarlyDataSize: 16384, + Bugs: ProtocolBugs{ + ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}}, + }, + }, + resumeSession: true, + flags: []string{ + "-enable-early-data", + "-expect-early-data-info", + "-expect-accept-early-data", + "-on-resume-shim-writes-first", + "-tls13-variant", "2", + }, + }) + + tests = append(tests, testCase{ + testType: clientTest, name: "TLS13-EarlyData-TooMuchData-Client", config: Config{ MaxVersion: VersionTLS13, @@ -3998,6 +4167,50 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { tests = append(tests, testCase{ testType: serverTest, + name: "TLS13Experiment-EarlyData-Server", + config: Config{ + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + TLS13Variant: TLS13Experiment, + Bugs: ProtocolBugs{ + SendEarlyData: [][]byte{{1, 2, 3, 4}}, + ExpectEarlyDataAccepted: true, + ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}}, + }, + }, + messageCount: 2, + resumeSession: true, + flags: []string{ + "-enable-early-data", + "-expect-accept-early-data", + "-tls13-variant", "1", + }, + }) + + tests = append(tests, testCase{ + testType: serverTest, + name: "TLS13RecordTypeExperiment-EarlyData-Server", + config: Config{ + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + TLS13Variant: TLS13RecordTypeExperiment, + Bugs: ProtocolBugs{ + SendEarlyData: [][]byte{{1, 2, 3, 4}}, + ExpectEarlyDataAccepted: true, + ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}}, + }, + }, + messageCount: 2, + resumeSession: true, + flags: []string{ + "-enable-early-data", + "-expect-accept-early-data", + "-tls13-variant", "2", + }, + }) + + tests = append(tests, testCase{ + testType: serverTest, name: "TLS13-MaxEarlyData-Server", config: Config{ MaxVersion: VersionTLS13, @@ -4353,6 +4566,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { MaxVersion: vers.version, Certificates: []Certificate{rsaCertificate}, }, + tls13Variant: vers.tls13Variant, flags: []string{ flag, "-expect-verify-result", @@ -4366,6 +4580,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { MaxVersion: vers.version, Certificates: []Certificate{rsaCertificate}, }, + tls13Variant: vers.tls13Variant, flags: []string{ flag, "-verify-fail", @@ -4384,6 +4599,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { MaxVersion: vers.version, Certificates: []Certificate{rsaCertificate}, }, + tls13Variant: vers.tls13Variant, flags: []string{ "-verify-fail", "-expect-verify-result", @@ -4543,6 +4759,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { MaxVersion: ver.version, RequestChannelID: true, }, + tls13Variant: ver.tls13Variant, flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)}, resumeSession: true, expectChannelID: true, @@ -4556,6 +4773,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { MaxVersion: ver.version, ChannelID: channelIDKey, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-expect-channel-id", base64.StdEncoding.EncodeToString(channelIDBytes), @@ -4574,6 +4792,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { InvalidChannelIDSignature: true, }, }, + tls13Variant: ver.tls13Variant, flags: []string{"-enable-channel-id"}, shouldFail: true, expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:", @@ -4782,24 +5001,42 @@ func addDDoSCallbackTests() { } func addVersionNegotiationTests() { - for i, shimVers := range tlsVersions { - // Assemble flags to disable all newer versions on the shim. - var flags []string - for _, vers := range tlsVersions[i+1:] { - flags = append(flags, vers.excludeFlag) - } + for _, protocol := range []protocol{tls, dtls} { + for _, shimVers := range allVersions(protocol) { + // Assemble flags to disable all newer versions on the shim. + var flags []string + for _, vers := range allVersions(protocol) { + if vers.version > shimVers.version { + flags = append(flags, vers.excludeFlag) + } + } - // Test configuring the runner's maximum version. - for _, runnerVers := range tlsVersions { - protocols := []protocol{tls} - if runnerVers.hasDTLS && shimVers.hasDTLS { - protocols = append(protocols, dtls) + flags2 := []string{"-max-version", shimVers.shimFlag(protocol)} + + if shimVers.tls13Variant != 0 { + flags = append(flags, "-tls13-variant", strconv.Itoa(shimVers.tls13Variant)) + flags2 = append(flags2, "-tls13-variant", strconv.Itoa(shimVers.tls13Variant)) } - for _, protocol := range protocols { + + // Test configuring the runner's maximum version. + for _, runnerVers := range allVersions(protocol) { expectedVersion := shimVers.version if runnerVers.version < shimVers.version { expectedVersion = runnerVers.version } + // When running and shim have different TLS 1.3 variants enabled, + // shim clients are expected to fall back to TLS 1.2, while shim + // servers support both variants when enabled when the experiment is + // enabled. + expectedServerVersion := expectedVersion + expectedClientVersion := expectedVersion + if expectedVersion == VersionTLS13 && runnerVers.tls13Variant != shimVers.tls13Variant { + expectedClientVersion = VersionTLS12 + expectedServerVersion = VersionTLS12 + if shimVers.tls13Variant != TLS13Default { + expectedServerVersion = VersionTLS13 + } + } suffix := shimVers.name + "-" + runnerVers.name if protocol == dtls { @@ -4811,38 +5048,40 @@ func addVersionNegotiationTests() { if clientVers > VersionTLS10 { clientVers = VersionTLS10 } - clientVers = configVersionToWire(clientVers, protocol) - serverVers := expectedVersion - if expectedVersion >= VersionTLS13 { + clientVers = recordVersionToWire(clientVers, protocol) + serverVers := expectedServerVersion + if expectedServerVersion >= VersionTLS13 { serverVers = VersionTLS10 } - serverVers = configVersionToWire(serverVers, protocol) + serverVers = recordVersionToWire(serverVers, protocol) testCases = append(testCases, testCase{ protocol: protocol, testType: clientTest, name: "VersionNegotiation-Client-" + suffix, config: Config{ - MaxVersion: runnerVers.version, + MaxVersion: runnerVers.version, + TLS13Variant: runnerVers.tls13Variant, Bugs: ProtocolBugs{ ExpectInitialRecordVersion: clientVers, }, }, flags: flags, - expectedVersion: expectedVersion, + expectedVersion: expectedClientVersion, }) testCases = append(testCases, testCase{ protocol: protocol, testType: clientTest, name: "VersionNegotiation-Client2-" + suffix, config: Config{ - MaxVersion: runnerVers.version, + MaxVersion: runnerVers.version, + TLS13Variant: runnerVers.tls13Variant, Bugs: ProtocolBugs{ ExpectInitialRecordVersion: clientVers, }, }, - flags: []string{"-max-version", shimVers.shimFlag(protocol)}, - expectedVersion: expectedVersion, + flags: flags2, + expectedVersion: expectedClientVersion, }) testCases = append(testCases, testCase{ @@ -4850,26 +5089,28 @@ func addVersionNegotiationTests() { testType: serverTest, name: "VersionNegotiation-Server-" + suffix, config: Config{ - MaxVersion: runnerVers.version, + MaxVersion: runnerVers.version, + TLS13Variant: runnerVers.tls13Variant, Bugs: ProtocolBugs{ ExpectInitialRecordVersion: serverVers, }, }, flags: flags, - expectedVersion: expectedVersion, + expectedVersion: expectedServerVersion, }) testCases = append(testCases, testCase{ protocol: protocol, testType: serverTest, name: "VersionNegotiation-Server2-" + suffix, config: Config{ - MaxVersion: runnerVers.version, + MaxVersion: runnerVers.version, + TLS13Variant: runnerVers.tls13Variant, Bugs: ProtocolBugs{ ExpectInitialRecordVersion: serverVers, }, }, - flags: []string{"-max-version", shimVers.shimFlag(protocol)}, - expectedVersion: expectedVersion, + flags: flags2, + expectedVersion: expectedServerVersion, }) } } @@ -4887,20 +5128,20 @@ func addVersionNegotiationTests() { suffix += "-DTLS" } - wireVersion := configVersionToWire(vers.version, protocol) testCases = append(testCases, testCase{ protocol: protocol, testType: serverTest, name: "VersionNegotiationExtension-" + suffix, config: Config{ + TLS13Variant: vers.tls13Variant, Bugs: ProtocolBugs{ - SendSupportedVersions: []uint16{0x1111, wireVersion, 0x2222}, + SendSupportedVersions: []uint16{0x1111, vers.wire(protocol), 0x2222}, }, }, expectedVersion: vers.version, + flags: []string{"-tls13-variant", strconv.Itoa(vers.tls13Variant)}, }) } - } // If all versions are unknown, negotiation fails. @@ -4980,6 +5221,36 @@ func addVersionNegotiationTests() { expectedVersion: VersionTLS12, }) + // Test that TLS 1.2 isn't negotiated by the supported_versions extension in + // the ServerHello. + testCases = append(testCases, testCase{ + testType: clientTest, + name: "SupportedVersionSelection-TLS12", + config: Config{ + MaxVersion: VersionTLS12, + Bugs: ProtocolBugs{ + SendServerSupportedExtensionVersion: VersionTLS12, + }, + }, + shouldFail: true, + expectedError: ":UNEXPECTED_EXTENSION:", + }) + + // Test that the non-experimental TLS 1.3 isn't negotiated by the + // supported_versions extension in the ServerHello. + testCases = append(testCases, testCase{ + testType: clientTest, + name: "SupportedVersionSelection-TLS13", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendServerSupportedExtensionVersion: tls13DraftVersion, + }, + }, + shouldFail: true, + expectedError: ":UNEXPECTED_EXTENSION:", + }) + // Test that the maximum version is selected regardless of the // client-sent order. testCases = append(testCases, testCase{ @@ -5121,19 +5392,34 @@ func addVersionNegotiationTests() { } func addMinimumVersionTests() { - for i, shimVers := range tlsVersions { - // Assemble flags to disable all older versions on the shim. - var flags []string - for _, vers := range tlsVersions[:i] { - flags = append(flags, vers.excludeFlag) - } + for _, protocol := range []protocol{tls, dtls} { + for _, shimVers := range allVersions(protocol) { + // Assemble flags to disable all older versions on the shim. + var flags []string + for _, vers := range allVersions(protocol) { + if vers.version < shimVers.version { + flags = append(flags, vers.excludeFlag) + } + } - for _, runnerVers := range tlsVersions { - protocols := []protocol{tls} - if runnerVers.hasDTLS && shimVers.hasDTLS { - protocols = append(protocols, dtls) + flags2 := []string{"-min-version", shimVers.shimFlag(protocol)} + + if shimVers.tls13Variant != 0 { + flags = append(flags, "-tls13-variant", strconv.Itoa(shimVers.tls13Variant)) + flags2 = append(flags2, "-tls13-variant", strconv.Itoa(shimVers.tls13Variant)) } - for _, protocol := range protocols { + + for _, runnerVers := range allVersions(protocol) { + // Different TLS 1.3 variants are incompatible with each other and don't + // produce consistent minimum versions. + // + // TODO(davidben): Fold these tests (the main value is in the + // NegotiateVersion bug) into addVersionNegotiationTests and test based + // on intended shim behavior, not the shim + runner combination. + if shimVers.tls13Variant != runnerVers.tls13Variant { + continue + } + suffix := shimVers.name + "-" + runnerVers.name if protocol == dtls { suffix += "-DTLS" @@ -5155,12 +5441,13 @@ func addMinimumVersionTests() { testType: clientTest, name: "MinimumVersion-Client-" + suffix, config: Config{ - MaxVersion: runnerVers.version, + MaxVersion: runnerVers.version, + TLS13Variant: runnerVers.tls13Variant, Bugs: ProtocolBugs{ // Ensure the server does not decline to // select a version (versions extension) or // cipher (some ciphers depend on versions). - NegotiateVersion: configVersionToWire(runnerVers.version, protocol), + NegotiateVersion: runnerVers.wire(protocol), IgnorePeerCipherPreferences: shouldFail, }, }, @@ -5175,16 +5462,17 @@ func addMinimumVersionTests() { testType: clientTest, name: "MinimumVersion-Client2-" + suffix, config: Config{ - MaxVersion: runnerVers.version, + MaxVersion: runnerVers.version, + TLS13Variant: runnerVers.tls13Variant, Bugs: ProtocolBugs{ // Ensure the server does not decline to // select a version (versions extension) or // cipher (some ciphers depend on versions). - NegotiateVersion: configVersionToWire(runnerVers.version, protocol), + NegotiateVersion: runnerVers.wire(protocol), IgnorePeerCipherPreferences: shouldFail, }, }, - flags: []string{"-min-version", shimVers.shimFlag(protocol)}, + flags: flags2, expectedVersion: expectedVersion, shouldFail: shouldFail, expectedError: expectedError, @@ -5196,7 +5484,8 @@ func addMinimumVersionTests() { testType: serverTest, name: "MinimumVersion-Server-" + suffix, config: Config{ - MaxVersion: runnerVers.version, + MaxVersion: runnerVers.version, + TLS13Variant: runnerVers.tls13Variant, }, flags: flags, expectedVersion: expectedVersion, @@ -5209,9 +5498,10 @@ func addMinimumVersionTests() { testType: serverTest, name: "MinimumVersion-Server2-" + suffix, config: Config{ - MaxVersion: runnerVers.version, + MaxVersion: runnerVers.version, + TLS13Variant: runnerVers.tls13Variant, }, - flags: []string{"-min-version", shimVers.shimFlag(protocol)}, + flags: flags2, expectedVersion: expectedVersion, shouldFail: shouldFail, expectedError: expectedError, @@ -5243,6 +5533,7 @@ func addExtensionTests() { DuplicateExtension: true, }, }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedLocalError: "remote error: error decoding message", }) @@ -5255,6 +5546,7 @@ func addExtensionTests() { DuplicateExtension: true, }, }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedLocalError: "remote error: error decoding message", }) @@ -5269,7 +5561,8 @@ func addExtensionTests() { ExpectServerName: "example.com", }, }, - flags: []string{"-host-name", "example.com"}, + tls13Variant: ver.tls13Variant, + flags: []string{"-host-name", "example.com"}, }) testCases = append(testCases, testCase{ testType: clientTest, @@ -5281,6 +5574,7 @@ func addExtensionTests() { }, }, flags: []string{"-host-name", "example.com"}, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedLocalError: "tls: unexpected server name", }) @@ -5293,6 +5587,7 @@ func addExtensionTests() { ExpectServerName: "missing.com", }, }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedLocalError: "tls: unexpected server name", }) @@ -5305,6 +5600,7 @@ func addExtensionTests() { SendServerNameAck: true, }, }, + tls13Variant: ver.tls13Variant, flags: []string{"-host-name", "example.com"}, resumeSession: true, }) @@ -5317,6 +5613,7 @@ func addExtensionTests() { SendServerNameAck: true, }, }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":UNEXPECTED_EXTENSION:", expectedLocalError: "remote error: unsupported extension", @@ -5328,6 +5625,7 @@ func addExtensionTests() { MaxVersion: ver.version, ServerName: "example.com", }, + tls13Variant: ver.tls13Variant, flags: []string{"-expect-server-name", "example.com"}, resumeSession: true, }) @@ -5344,6 +5642,7 @@ func addExtensionTests() { "-advertise-alpn", "\x03foo\x03bar\x03baz", "-expect-alpn", "foo", }, + tls13Variant: ver.tls13Variant, expectedNextProto: "foo", expectedNextProtoType: alpn, resumeSession: true, @@ -5360,6 +5659,7 @@ func addExtensionTests() { flags: []string{ "-advertise-alpn", "\x03foo\x03bar", }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":INVALID_ALPN_PROTOCOL:", expectedLocalError: "remote error: illegal parameter", @@ -5378,6 +5678,7 @@ func addExtensionTests() { "-allow-unknown-alpn-protos", "-expect-alpn", "baz", }, + tls13Variant: ver.tls13Variant, }) testCases = append(testCases, testCase{ testType: serverTest, @@ -5390,6 +5691,7 @@ func addExtensionTests() { "-expect-advertised-alpn", "\x03foo\x03bar\x03baz", "-select-alpn", "foo", }, + tls13Variant: ver.tls13Variant, expectedNextProto: "foo", expectedNextProtoType: alpn, resumeSession: true, @@ -5402,6 +5704,7 @@ func addExtensionTests() { NextProtos: []string{"foo", "bar", "baz"}, }, flags: []string{"-decline-alpn"}, + tls13Variant: ver.tls13Variant, expectNoNextProto: true, resumeSession: true, }) @@ -5422,6 +5725,7 @@ func addExtensionTests() { "-select-alpn", "foo", "-async", }, + tls13Variant: ver.tls13Variant, expectedNextProto: "foo", expectedNextProtoType: alpn, resumeSession: true, @@ -5443,6 +5747,7 @@ func addExtensionTests() { flags: []string{ "-advertise-alpn", "\x03foo", }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":PARSE_TLSEXT:", }) @@ -5458,6 +5763,7 @@ func addExtensionTests() { flags: []string{ "-select-alpn", "foo", }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":PARSE_TLSEXT:", }) @@ -5477,6 +5783,7 @@ func addExtensionTests() { "-select-alpn", "foo", "-advertise-npn", "\x03foo\x03bar\x03baz", }, + tls13Variant: ver.tls13Variant, expectedNextProto: "foo", expectedNextProtoType: alpn, resumeSession: true, @@ -5496,6 +5803,7 @@ func addExtensionTests() { "-select-alpn", "foo", "-advertise-npn", "\x03foo\x03bar\x03baz", }, + tls13Variant: ver.tls13Variant, expectedNextProto: "foo", expectedNextProtoType: alpn, resumeSession: true, @@ -5515,6 +5823,7 @@ func addExtensionTests() { "-advertise-alpn", "\x03foo", "-select-next-proto", "foo", }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:", }) @@ -5532,6 +5841,7 @@ func addExtensionTests() { "-advertise-alpn", "\x03foo", "-select-next-proto", "foo", }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:", }) @@ -5552,6 +5862,7 @@ func addExtensionTests() { }, }, }, + tls13Variant: ver.tls13Variant, resumeSession: true, expectResumeRejected: true, }) @@ -5562,6 +5873,7 @@ func addExtensionTests() { config: Config{ MaxVersion: ver.version, }, + tls13Variant: ver.tls13Variant, resumeSession: true, flags: []string{"-use-ticket-callback"}, }) @@ -5574,6 +5886,7 @@ func addExtensionTests() { ExpectNewTicket: true, }, }, + tls13Variant: ver.tls13Variant, flags: []string{"-use-ticket-callback", "-renew-ticket"}, resumeSession: true, }) @@ -5593,6 +5906,7 @@ func addExtensionTests() { }, }, }, + tls13Variant: ver.tls13Variant, resumeSession: true, expectResumeRejected: true, flags: []string{ @@ -5748,6 +6062,7 @@ func addExtensionTests() { "-expect-signed-cert-timestamps", base64.StdEncoding.EncodeToString(testSCTList), }, + tls13Variant: ver.tls13Variant, resumeSession: true, }) @@ -5770,6 +6085,7 @@ func addExtensionTests() { "-expect-signed-cert-timestamps", base64.StdEncoding.EncodeToString(testSCTList), }, + tls13Variant: ver.tls13Variant, resumeSession: true, }) @@ -5783,6 +6099,7 @@ func addExtensionTests() { "-signed-cert-timestamps", base64.StdEncoding.EncodeToString(testSCTList), }, + tls13Variant: ver.tls13Variant, expectedSCTList: testSCTList, resumeSession: true, }) @@ -5801,6 +6118,7 @@ func addExtensionTests() { flags: []string{ "-enable-signed-cert-timestamps", }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":ERROR_PARSING_EXTENSION:", }) @@ -5819,6 +6137,7 @@ func addExtensionTests() { flags: []string{ "-enable-signed-cert-timestamps", }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":ERROR_PARSING_EXTENSION:", }) @@ -5834,6 +6153,7 @@ func addExtensionTests() { NoSignedCertificateTimestamps: true, }, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-ocsp-response", base64.StdEncoding.EncodeToString(testOCSPResponse), @@ -6178,13 +6498,20 @@ func addResumptionVersionTests() { suffix += "-DTLS" } + // We can't resume across TLS 1.3 variants and error out earlier in the + // session resumption. + if sessionVers.tls13Variant != resumeVers.tls13Variant { + continue + } + if sessionVers.version == resumeVers.version { testCases = append(testCases, testCase{ protocol: protocol, name: "Resume-Client" + suffix, resumeSession: true, config: Config{ - MaxVersion: sessionVers.version, + MaxVersion: sessionVers.version, + TLS13Variant: sessionVers.tls13Variant, Bugs: ProtocolBugs{ ExpectNoTLS12Session: sessionVers.version >= VersionTLS13, ExpectNoTLS13PSK: sessionVers.version < VersionTLS13, @@ -6192,6 +6519,9 @@ func addResumptionVersionTests() { }, expectedVersion: sessionVers.version, expectedResumeVersion: resumeVers.version, + flags: []string{ + "-tls13-variant", strconv.Itoa(sessionVers.tls13Variant), + }, }) } else { error := ":OLD_SESSION_VERSION_NOT_RETURNED:" @@ -6209,11 +6539,13 @@ func addResumptionVersionTests() { name: "Resume-Client-Mismatch" + suffix, resumeSession: true, config: Config{ - MaxVersion: sessionVers.version, + MaxVersion: sessionVers.version, + TLS13Variant: sessionVers.tls13Variant, }, expectedVersion: sessionVers.version, resumeConfig: &Config{ - MaxVersion: resumeVers.version, + MaxVersion: resumeVers.version, + TLS13Variant: resumeVers.tls13Variant, Bugs: ProtocolBugs{ AcceptAnySession: true, }, @@ -6221,6 +6553,10 @@ func addResumptionVersionTests() { expectedResumeVersion: resumeVers.version, shouldFail: true, expectedError: error, + flags: []string{ + "-on-initial-tls13-variant", strconv.Itoa(sessionVers.tls13Variant), + "-on-resume-tls13-variant", strconv.Itoa(resumeVers.tls13Variant), + }, }) } @@ -6229,15 +6565,21 @@ func addResumptionVersionTests() { name: "Resume-Client-NoResume" + suffix, resumeSession: true, config: Config{ - MaxVersion: sessionVers.version, + MaxVersion: sessionVers.version, + TLS13Variant: sessionVers.tls13Variant, }, expectedVersion: sessionVers.version, resumeConfig: &Config{ - MaxVersion: resumeVers.version, + MaxVersion: resumeVers.version, + TLS13Variant: resumeVers.tls13Variant, }, newSessionsOnResume: true, expectResumeRejected: true, expectedResumeVersion: resumeVers.version, + flags: []string{ + "-on-initial-tls13-variant", strconv.Itoa(sessionVers.tls13Variant), + "-on-resume-tls13-variant", strconv.Itoa(resumeVers.tls13Variant), + }, }) testCases = append(testCases, testCase{ @@ -6246,17 +6588,23 @@ func addResumptionVersionTests() { name: "Resume-Server" + suffix, resumeSession: true, config: Config{ - MaxVersion: sessionVers.version, + MaxVersion: sessionVers.version, + TLS13Variant: sessionVers.tls13Variant, }, expectedVersion: sessionVers.version, - expectResumeRejected: sessionVers.version != resumeVers.version, + expectResumeRejected: sessionVers != resumeVers, resumeConfig: &Config{ - MaxVersion: resumeVers.version, + MaxVersion: resumeVers.version, + TLS13Variant: resumeVers.tls13Variant, Bugs: ProtocolBugs{ SendBothTickets: true, }, }, expectedResumeVersion: resumeVers.version, + flags: []string{ + "-on-initial-tls13-variant", strconv.Itoa(sessionVers.tls13Variant), + "-on-resume-tls13-variant", strconv.Itoa(resumeVers.tls13Variant), + }, }) } } @@ -7252,6 +7600,7 @@ func addSignatureAlgorithmTests() { "-enable-all-curves", "-enable-ed25519", }, + tls13Variant: ver.tls13Variant, shouldFail: shouldSignFail, expectedError: signError, expectedPeerSignatureAlgorithm: alg.id, @@ -7273,6 +7622,7 @@ func addSignatureAlgorithmTests() { IgnorePeerSignatureAlgorithmPreferences: shouldVerifyFail, }, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-require-any-client-certificate", "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)), @@ -7300,6 +7650,7 @@ func addSignatureAlgorithmTests() { fakeSigAlg2, }, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)), "-key-file", path.Join(*resourceDir, getShimKey(alg.cert)), @@ -7328,6 +7679,7 @@ func addSignatureAlgorithmTests() { IgnorePeerSignatureAlgorithmPreferences: shouldVerifyFail, }, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)), "-enable-all-curves", @@ -7354,6 +7706,7 @@ func addSignatureAlgorithmTests() { InvalidSignature: true, }, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-require-any-client-certificate", "-enable-all-curves", @@ -7376,6 +7729,7 @@ func addSignatureAlgorithmTests() { InvalidSignature: true, }, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-enable-all-curves", "-enable-ed25519", @@ -7393,6 +7747,7 @@ func addSignatureAlgorithmTests() { ClientAuth: RequireAnyClientCert, VerifySignatureAlgorithms: allAlgorithms, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)), "-key-file", path.Join(*resourceDir, getShimKey(alg.cert)), @@ -7411,6 +7766,7 @@ func addSignatureAlgorithmTests() { CipherSuites: signingCiphers, VerifySignatureAlgorithms: allAlgorithms, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)), "-key-file", path.Join(*resourceDir, getShimKey(alg.cert)), @@ -8341,6 +8697,7 @@ func addExportKeyingMaterialTests() { config: Config{ MaxVersion: vers.version, }, + tls13Variant: vers.tls13Variant, exportKeyingMaterial: 1024, exportLabel: "label", exportContext: "context", @@ -8351,6 +8708,7 @@ func addExportKeyingMaterialTests() { config: Config{ MaxVersion: vers.version, }, + tls13Variant: vers.tls13Variant, exportKeyingMaterial: 1024, }) testCases = append(testCases, testCase{ @@ -8358,6 +8716,7 @@ func addExportKeyingMaterialTests() { config: Config{ MaxVersion: vers.version, }, + tls13Variant: vers.tls13Variant, exportKeyingMaterial: 1024, useExportContext: true, }) @@ -8366,6 +8725,7 @@ func addExportKeyingMaterialTests() { config: Config{ MaxVersion: vers.version, }, + tls13Variant: vers.tls13Variant, exportKeyingMaterial: 1, exportLabel: "label", exportContext: "context", @@ -10169,6 +10529,32 @@ func addTLS13HandshakeTests() { testCases = append(testCases, testCase{ testType: serverTest, + name: "SkipEarlyData-TLS13Experiment", + config: Config{ + MaxVersion: VersionTLS13, + TLS13Variant: TLS13Experiment, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 4, + }, + }, + flags: []string{"-tls13-variant", "1"}, + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-TLS13RecordTypeExperiment", + config: Config{ + MaxVersion: VersionTLS13, + TLS13Variant: TLS13RecordTypeExperiment, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 4, + }, + }, + flags: []string{"-tls13-variant", "2"}, + }) + + testCases = append(testCases, testCase{ + testType: serverTest, name: "SkipEarlyData-OmitEarlyDataExtension", config: Config{ MaxVersion: VersionTLS13, @@ -10669,6 +11055,58 @@ func addTLS13HandshakeTests() { testCases = append(testCases, testCase{ testType: clientTest, + name: "TLS13Experiment-EarlyData-Reject-Client", + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + TLS13Variant: TLS13Experiment, + }, + resumeConfig: &Config{ + MaxVersion: VersionTLS13, + TLS13Variant: TLS13Experiment, + MaxEarlyDataSize: 16384, + Bugs: ProtocolBugs{ + AlwaysRejectEarlyData: true, + }, + }, + resumeSession: true, + flags: []string{ + "-enable-early-data", + "-expect-early-data-info", + "-expect-reject-early-data", + "-on-resume-shim-writes-first", + "-tls13-variant", "1", + }, + }) + + testCases = append(testCases, testCase{ + testType: clientTest, + name: "TLS13RecordTypeExperiment-EarlyData-Reject-Client", + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + TLS13Variant: TLS13RecordTypeExperiment, + }, + resumeConfig: &Config{ + MaxVersion: VersionTLS13, + TLS13Variant: TLS13RecordTypeExperiment, + MaxEarlyDataSize: 16384, + Bugs: ProtocolBugs{ + AlwaysRejectEarlyData: true, + }, + }, + resumeSession: true, + flags: []string{ + "-enable-early-data", + "-expect-early-data-info", + "-expect-reject-early-data", + "-on-resume-shim-writes-first", + "-tls13-variant", "2", + }, + }) + + testCases = append(testCases, testCase{ + testType: clientTest, name: "TLS13-EarlyData-RejectTicket-Client", config: Config{ MaxVersion: VersionTLS13, @@ -11309,6 +11747,7 @@ func addRecordVersionTests() { SendRecordVersion: 0x03ff, }, }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":WRONG_VERSION_NUMBER:", }) @@ -11325,6 +11764,7 @@ func addRecordVersionTests() { SendInitialRecordVersion: 0x03ff, }, }, + tls13Variant: ver.tls13Variant, }) // Test that garbage ClientHello record versions are rejected. @@ -11338,6 +11778,7 @@ func addRecordVersionTests() { SendInitialRecordVersion: 0xffff, }, }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":WRONG_VERSION_NUMBER:", }) @@ -11357,6 +11798,7 @@ func addCertificateTests() { Certificates: []Certificate{rsaChainCertificate}, ClientAuth: RequireAnyClientCert, }, + tls13Variant: ver.tls13Variant, expectPeerCertificate: &rsaChainCertificate, flags: []string{ "-cert-file", path.Join(*resourceDir, rsaChainCertificateFile), @@ -11373,6 +11815,7 @@ func addCertificateTests() { MaxVersion: ver.version, Certificates: []Certificate{rsaChainCertificate}, }, + tls13Variant: ver.tls13Variant, expectPeerCertificate: &rsaChainCertificate, flags: []string{ "-cert-file", path.Join(*resourceDir, rsaChainCertificateFile), @@ -11396,6 +11839,7 @@ func addRetainOnlySHA256ClientCertTests() { MinVersion: ver.version, MaxVersion: ver.version, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-retain-only-sha256-client-cert-initial", "-retain-only-sha256-client-cert-resume", @@ -11413,6 +11857,7 @@ func addRetainOnlySHA256ClientCertTests() { MaxVersion: ver.version, Certificates: []Certificate{rsaCertificate}, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-verify-peer", "-retain-only-sha256-client-cert-initial", @@ -11434,6 +11879,7 @@ func addRetainOnlySHA256ClientCertTests() { MaxVersion: ver.version, Certificates: []Certificate{rsaCertificate}, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-verify-peer", "-retain-only-sha256-client-cert-initial", @@ -11454,6 +11900,7 @@ func addRetainOnlySHA256ClientCertTests() { MaxVersion: ver.version, Certificates: []Certificate{rsaCertificate}, }, + tls13Variant: ver.tls13Variant, flags: []string{ "-verify-peer", "-retain-only-sha256-client-cert-resume", @@ -11516,6 +11963,7 @@ func addECDSAKeyUsageTests() { MaxVersion: ver.version, Certificates: []Certificate{cert}, }, + tls13Variant: ver.tls13Variant, shouldFail: true, expectedError: ":ECC_CERT_NOT_FOR_SIGNING:", }) @@ -11626,6 +12074,75 @@ func addExtraHandshakeTests() { }) } +// Test that omitted and empty extensions blocks are tolerated. +func addOmitExtensionsTests() { + for _, ver := range tlsVersions { + if ver.version > VersionTLS12 { + continue + } + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "OmitExtensions-ClientHello-" + ver.name, + config: Config{ + MinVersion: ver.version, + MaxVersion: ver.version, + SessionTicketsDisabled: true, + Bugs: ProtocolBugs{ + OmitExtensions: true, + }, + }, + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "EmptyExtensions-ClientHello-" + ver.name, + config: Config{ + MinVersion: ver.version, + MaxVersion: ver.version, + SessionTicketsDisabled: true, + Bugs: ProtocolBugs{ + EmptyExtensions: true, + }, + }, + }) + + testCases = append(testCases, testCase{ + testType: clientTest, + name: "OmitExtensions-ServerHello-" + ver.name, + config: Config{ + MinVersion: ver.version, + MaxVersion: ver.version, + SessionTicketsDisabled: true, + Bugs: ProtocolBugs{ + OmitExtensions: true, + // Disable all ServerHello extensions so + // OmitExtensions works. + NoExtendedMasterSecret: true, + NoRenegotiationInfo: true, + }, + }, + }) + + testCases = append(testCases, testCase{ + testType: clientTest, + name: "EmptyExtensions-ServerHello-" + ver.name, + config: Config{ + MinVersion: ver.version, + MaxVersion: ver.version, + SessionTicketsDisabled: true, + Bugs: ProtocolBugs{ + EmptyExtensions: true, + // Disable all ServerHello extensions so + // EmptyExtensions works. + NoExtendedMasterSecret: true, + NoRenegotiationInfo: true, + }, + }, + }) + } +} + func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) { defer wg.Done() @@ -11753,6 +12270,7 @@ func main() { addRetainOnlySHA256ClientCertTests() addECDSAKeyUsageTests() addExtraHandshakeTests() + addOmitExtensionsTests() var wg sync.WaitGroup diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc index 195371fb..f925504d 100644 --- a/src/ssl/test/test_config.cc +++ b/src/ssl/test/test_config.cc @@ -189,6 +189,7 @@ const Flag<int> kIntFlags[] = { { "-max-send-fragment", &TestConfig::max_send_fragment }, { "-read-size", &TestConfig::read_size }, { "-expect-ticket-age-skew", &TestConfig::expect_ticket_age_skew }, + { "-tls13-variant", &TestConfig::tls13_variant }, }; const Flag<std::vector<int>> kIntVectorFlags[] = { diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h index 7b4b3427..e157936d 100644 --- a/src/ssl/test/test_config.h +++ b/src/ssl/test/test_config.h @@ -93,6 +93,7 @@ struct TestConfig { bool use_ticket_callback = false; bool renew_ticket = false; bool enable_early_data = false; + int tls13_variant = 0; bool enable_client_custom_extension = false; bool enable_server_custom_extension = false; bool custom_extension_skip = false; diff --git a/src/ssl/tls13_both.c b/src/ssl/tls13_both.cc index 6fdfb269..763dc0e5 100644 --- a/src/ssl/tls13_both.c +++ b/src/ssl/tls13_both.cc @@ -64,6 +64,14 @@ int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return) { break; } + case ssl_hs_read_change_cipher_spec: { + int ret = ssl->method->read_change_cipher_spec(ssl); + if (ret <= 0) { + return ret; + } + break; + } + case ssl_hs_read_end_of_early_data: { if (ssl->s3->hs->can_early_read) { /* While we are processing early data, the handshake returns early. */ @@ -365,12 +373,9 @@ err: int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - int ret = 0; - uint8_t *msg = NULL; - size_t msg_len; - if (hs->peer_pubkey == NULL) { - goto err; + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return 0; } CBS cbs, signature; @@ -381,22 +386,25 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) { CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - goto err; + return 0; } uint8_t alert = SSL_AD_DECODE_ERROR; if (!tls12_check_peer_sigalg(ssl, &alert, signature_algorithm)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); - goto err; + return 0; } hs->new_session->peer_signature_algorithm = signature_algorithm; + uint8_t *msg = NULL; + size_t msg_len; if (!tls13_get_cert_verify_signature_input( hs, &msg, &msg_len, ssl->server ? ssl_cert_verify_client : ssl_cert_verify_server)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return 0; } + bssl::UniquePtr<uint8_t> free_msg(msg); int sig_ok = ssl_public_key_verify(ssl, CBS_data(&signature), CBS_len(&signature), @@ -408,14 +416,10 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) { if (!sig_ok) { OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR); - goto err; + return 0; } - ret = 1; - -err: - OPENSSL_free(msg); - return ret; + return 1; } int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value) { @@ -452,21 +456,18 @@ int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value) { int tls13_add_certificate(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - CBB cbb, body, certificate_list; - if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) || + bssl::ScopedCBB cbb; + CBB body, certificate_list; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE) || /* The request context is always empty in the handshake. */ !CBB_add_u8(&body, 0) || !CBB_add_u24_length_prefixed(&body, &certificate_list)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } if (!ssl_has_certificate(ssl)) { - if (!ssl_add_message_cbb(ssl, &cbb)) { - goto err; - } - - return 1; + return ssl_add_message_cbb(ssl, cbb.get()); } CERT *cert = ssl->cert; @@ -477,7 +478,7 @@ int tls13_add_certificate(SSL_HANDSHAKE *hs) { CRYPTO_BUFFER_len(leaf_buf)) || !CBB_add_u16_length_prefixed(&certificate_list, &extensions)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } if (hs->scts_requested && ssl->cert->signed_cert_timestamp_list != NULL) { @@ -490,7 +491,7 @@ int tls13_add_certificate(SSL_HANDSHAKE *hs) { CRYPTO_BUFFER_len(ssl->cert->signed_cert_timestamp_list)) || !CBB_flush(&extensions)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } } @@ -506,7 +507,7 @@ int tls13_add_certificate(SSL_HANDSHAKE *hs) { CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) || !CBB_flush(&extensions)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } } @@ -518,38 +519,27 @@ int tls13_add_certificate(SSL_HANDSHAKE *hs) { CRYPTO_BUFFER_len(cert_buf)) || !CBB_add_u16(&certificate_list, 0 /* no extensions */)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } } - if (!ssl_add_message_cbb(ssl, &cbb)) { - goto err; - } - - return 1; - -err: - CBB_cleanup(&cbb); - return 0; + return ssl_add_message_cbb(ssl, cbb.get()); } enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - enum ssl_private_key_result_t ret = ssl_private_key_failure; - uint8_t *msg = NULL; - size_t msg_len; - CBB cbb, body; - CBB_zero(&cbb); - uint16_t signature_algorithm; if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) { - goto err; + return ssl_private_key_failure; } - if (!ssl->method->init_message(ssl, &cbb, &body, + + bssl::ScopedCBB cbb; + CBB body; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE_VERIFY) || !CBB_add_u16(&body, signature_algorithm)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return ssl_private_key_failure; } /* Sign the digest. */ @@ -560,34 +550,31 @@ enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) { if (!CBB_add_u16_length_prefixed(&body, &child) || !CBB_reserve(&child, &sig, max_sig_len)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return ssl_private_key_failure; } + uint8_t *msg = NULL; + size_t msg_len; if (!tls13_get_cert_verify_signature_input( hs, &msg, &msg_len, ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return ssl_private_key_failure; } + bssl::UniquePtr<uint8_t> free_msg(msg); enum ssl_private_key_result_t sign_result = ssl_private_key_sign( hs, sig, &sig_len, max_sig_len, signature_algorithm, msg, msg_len); if (sign_result != ssl_private_key_success) { - ret = sign_result; - goto err; + return sign_result; } if (!CBB_did_write(&child, sig_len) || - !ssl_add_message_cbb(ssl, &cbb)) { - goto err; + !ssl_add_message_cbb(ssl, cbb.get())) { + return ssl_private_key_failure; } - ret = ssl_private_key_success; - -err: - CBB_cleanup(&cbb); - OPENSSL_free(msg); - return ret; + return ssl_private_key_success; } int tls13_add_finished(SSL_HANDSHAKE *hs) { diff --git a/src/ssl/tls13_client.c b/src/ssl/tls13_client.cc index 92ea4f87..7f961bff 100644 --- a/src/ssl/tls13_client.c +++ b/src/ssl/tls13_client.cc @@ -32,6 +32,7 @@ enum client_hs_state_t { state_process_hello_retry_request = 0, state_send_second_client_hello, state_process_server_hello, + state_process_change_cipher_spec, state_process_encrypted_extensions, state_continue_second_server_flight, state_process_certificate_request, @@ -55,9 +56,9 @@ static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) { } CBS cbs, extensions; - uint16_t server_wire_version; + uint16_t server_version; CBS_init(&cbs, ssl->init_msg, ssl->init_num); - if (!CBS_get_u16(&cbs, &server_wire_version) || + if (!CBS_get_u16(&cbs, &server_version) || !CBS_get_u16_length_prefixed(&cbs, &extensions) || /* HelloRetryRequest may not be empty. */ CBS_len(&extensions) == 0 || @@ -165,13 +166,18 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - CBS cbs, server_random, extensions; - uint16_t server_wire_version; + CBS cbs, server_random, session_id, extensions; + uint16_t server_version; uint16_t cipher_suite; + uint8_t compression_method; CBS_init(&cbs, ssl->init_msg, ssl->init_num); - if (!CBS_get_u16(&cbs, &server_wire_version) || + if (!CBS_get_u16(&cbs, &server_version) || !CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) || + (ssl->version == TLS1_3_EXPERIMENT_VERSION && + !CBS_get_u8_length_prefixed(&cbs, &session_id)) || !CBS_get_u16(&cbs, &cipher_suite) || + (ssl->version == TLS1_3_EXPERIMENT_VERSION && + (!CBS_get_u8(&cbs, &compression_method) || compression_method != 0)) || !CBS_get_u16_length_prefixed(&cbs, &extensions) || CBS_len(&cbs) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); @@ -179,7 +185,9 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - if (server_wire_version != ssl->version) { + uint16_t expected_version = + ssl->version == TLS1_3_EXPERIMENT_VERSION ? TLS1_2_VERSION : ssl->version; + if (server_version != expected_version) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); return ssl_hs_error; @@ -205,11 +213,13 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { } /* Parse out the extensions. */ - int have_key_share = 0, have_pre_shared_key = 0; - CBS key_share, pre_shared_key; + int have_key_share = 0, have_pre_shared_key = 0, have_supported_versions = 0; + CBS key_share, pre_shared_key, supported_versions; const SSL_EXTENSION_TYPE ext_types[] = { {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}, }; uint8_t alert = SSL_AD_DECODE_ERROR; @@ -220,6 +230,14 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } + /* supported_versions is parsed in handshake_client to select the experimental + * TLS 1.3 version. */ + if (have_supported_versions && ssl->version != TLS1_3_EXPERIMENT_VERSION) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); + return ssl_hs_error; + } + alert = SSL_AD_DECODE_ERROR; if (have_pre_shared_key) { if (ssl->session == NULL) { @@ -313,20 +331,33 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { OPENSSL_free(dhe_secret); if (!ssl_hash_current_message(hs) || - !tls13_derive_handshake_secrets(hs) || - !tls13_set_traffic_key(ssl, evp_aead_open, hs->server_handshake_secret, - hs->hash_len)) { + !tls13_derive_handshake_secrets(hs)) { return ssl_hs_error; } + hs->tls13_state = state_process_change_cipher_spec; + return ssl->version == TLS1_3_EXPERIMENT_VERSION + ? ssl_hs_read_change_cipher_spec + : ssl_hs_ok; +} - /* If not sending early data, set client traffic keys now so that alerts are - * encrypted. */ - if (!hs->early_data_offered && - !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret, +static enum ssl_hs_wait_t do_process_change_cipher_spec(SSL_HANDSHAKE *hs) { + SSL *const ssl = hs->ssl; + if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->server_handshake_secret, hs->hash_len)) { return ssl_hs_error; } + if (!hs->early_data_offered) { + /* If not sending early data, set client traffic keys now so that alerts are + * encrypted. */ + if ((ssl->version == TLS1_3_EXPERIMENT_VERSION && + !ssl3_add_change_cipher_spec(ssl)) || + !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret, + hs->hash_len)) { + return ssl_hs_error; + } + } + hs->tls13_state = state_process_encrypted_extensions; return ssl_hs_read_message; } @@ -351,8 +382,8 @@ static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) { /* Store the negotiated ALPN in the session. */ if (ssl->s3->alpn_selected != NULL) { - hs->new_session->early_alpn = - BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len); + hs->new_session->early_alpn = (uint8_t *)BUF_memdup( + ssl->s3->alpn_selected, ssl->s3->alpn_selected_len); if (hs->new_session->early_alpn == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; @@ -500,10 +531,13 @@ static enum ssl_hs_wait_t do_send_end_of_early_data(SSL_HANDSHAKE *hs) { } } - if (hs->early_data_offered && - !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret, - hs->hash_len)) { - return ssl_hs_error; + if (hs->early_data_offered) { + if ((ssl->version == TLS1_3_EXPERIMENT_VERSION && + !ssl3_add_change_cipher_spec(ssl)) || + !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret, + hs->hash_len)) { + return ssl_hs_error; + } } hs->tls13_state = state_send_client_certificate; @@ -611,7 +645,8 @@ static enum ssl_hs_wait_t do_complete_second_flight(SSL_HANDSHAKE *hs) { enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) { while (hs->tls13_state != state_done) { enum ssl_hs_wait_t ret = ssl_hs_error; - enum client_hs_state_t state = hs->tls13_state; + enum client_hs_state_t state = + static_cast<enum client_hs_state_t>(hs->tls13_state); switch (state) { case state_process_hello_retry_request: ret = do_process_hello_retry_request(hs); @@ -622,6 +657,9 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) { case state_process_server_hello: ret = do_process_server_hello(hs); break; + case state_process_change_cipher_spec: + ret = do_process_change_cipher_spec(hs); + break; case state_process_encrypted_extensions: ret = do_process_encrypted_extensions(hs); break; @@ -666,14 +704,13 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) { } int tls13_process_new_session_ticket(SSL *ssl) { - int ret = 0; - SSL_SESSION *session = SSL_SESSION_dup(ssl->s3->established_session, - SSL_SESSION_INCLUDE_NONAUTH); - if (session == NULL) { + bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_dup( + ssl->s3->established_session, SSL_SESSION_INCLUDE_NONAUTH)); + if (!session) { return 0; } - ssl_session_rebase_time(ssl, session); + ssl_session_rebase_time(ssl, session.get()); uint32_t server_timeout; CBS cbs, ticket, extensions; @@ -686,7 +723,7 @@ int tls13_process_new_session_ticket(SSL *ssl) { CBS_len(&cbs) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - goto err; + return 0; } /* Cap the renewable lifetime by the server advertised value. This avoids @@ -708,7 +745,7 @@ int tls13_process_new_session_ticket(SSL *ssl) { OPENSSL_ARRAY_SIZE(ext_types), 1 /* ignore unknown */)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); - goto err; + return 0; } if (have_early_data_info && ssl->cert->enable_early_data) { @@ -716,7 +753,7 @@ int tls13_process_new_session_ticket(SSL *ssl) { CBS_len(&early_data_info) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - goto err; + return 0; } } @@ -724,16 +761,12 @@ int tls13_process_new_session_ticket(SSL *ssl) { session->not_resumable = 0; if (ssl->ctx->new_session_cb != NULL && - ssl->ctx->new_session_cb(ssl, session)) { + ssl->ctx->new_session_cb(ssl, session.get())) { /* |new_session_cb|'s return value signals that it took ownership. */ - session = NULL; + session.release(); } - ret = 1; - -err: - SSL_SESSION_free(session); - return ret; + return 1; } void ssl_clear_tls13_state(SSL_HANDSHAKE *hs) { diff --git a/src/ssl/tls13_enc.c b/src/ssl/tls13_enc.cc index 97f0ed93..97f0ed93 100644 --- a/src/ssl/tls13_enc.c +++ b/src/ssl/tls13_enc.cc diff --git a/src/ssl/tls13_server.c b/src/ssl/tls13_server.cc index fe2463bc..4e66016f 100644 --- a/src/ssl/tls13_server.c +++ b/src/ssl/tls13_server.cc @@ -12,6 +12,13 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* Per C99, various stdint.h macros are unavailable in C++ unless some macros + * are defined. C++11 overruled this decision, but older Android NDKs still + * require it. */ +#if !defined(__STDC_LIMIT_MACROS) +#define __STDC_LIMIT_MACROS +#endif + #include <openssl/ssl.h> #include <assert.h> @@ -38,6 +45,7 @@ enum server_hs_state_t { state_send_server_certificate_verify, state_send_server_finished, state_read_second_client_flight, + state_process_change_cipher_spec, state_process_end_of_early_data, state_process_client_certificate, state_process_client_certificate_verify, @@ -84,6 +92,19 @@ static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, int *out_need_retry, return ok; } +static int ssl_ext_supported_versions_add_serverhello(SSL_HANDSHAKE *hs, + CBB *out) { + CBB contents; + if (!CBB_add_u16(out, TLSEXT_TYPE_supported_versions) || + !CBB_add_u16_length_prefixed(out, &contents) || + !CBB_add_u16(&contents, hs->ssl->version) || + !CBB_flush(out)) { + return 0; + } + + return 1; +} + static const SSL_CIPHER *choose_tls13_cipher( const SSL *ssl, const SSL_CLIENT_HELLO *client_hello) { if (client_hello->cipher_suites_len % 2 != 0) { @@ -199,12 +220,17 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) { SSL_CLIENT_HELLO client_hello; if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg, - ssl->init_num)) { + ssl->init_num) || + client_hello.session_id_len > sizeof(hs->session_id)) { OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } + OPENSSL_memcpy(hs->session_id, client_hello.session_id, + client_hello.session_id_len); + hs->session_id_len = client_hello.session_id_len; + /* Negotiate the cipher suite. */ hs->new_cipher = choose_tls13_cipher(ssl, &client_hello); if (hs->new_cipher == NULL) { @@ -398,8 +424,8 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { /* Store the initial negotiated ALPN in the session. */ if (ssl->s3->alpn_selected != NULL) { - hs->new_session->early_alpn = - BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len); + hs->new_session->early_alpn = (uint8_t *)BUF_memdup( + ssl->s3->alpn_selected, ssl->s3->alpn_selected_len); if (hs->new_session->early_alpn == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; @@ -508,20 +534,36 @@ static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) { static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; + uint16_t version = ssl->version; + if (ssl->version == TLS1_3_EXPERIMENT_VERSION) { + version = TLS1_2_VERSION; + } + /* Send a ServerHello. */ - CBB cbb, body, extensions; + CBB cbb, body, extensions, session_id; if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) || - !CBB_add_u16(&body, ssl->version) || + !CBB_add_u16(&body, version) || !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) || !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) || + (ssl->version == TLS1_3_EXPERIMENT_VERSION && + (!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)) || + (ssl->version == TLS1_3_EXPERIMENT_VERSION && !CBB_add_u8(&body, 0)) || !CBB_add_u16_length_prefixed(&body, &extensions) || !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) || !ssl_ext_key_share_add_serverhello(hs, &extensions) || + (ssl->version == TLS1_3_EXPERIMENT_VERSION && + !ssl_ext_supported_versions_add_serverhello(hs, &extensions)) || !ssl_add_message_cbb(ssl, &cbb)) { goto err; } + if (ssl->version == TLS1_3_EXPERIMENT_VERSION && + !ssl3_add_change_cipher_spec(ssl)) { + goto err; + } + /* Derive and enable the handshake traffic secrets. */ if (!tls13_derive_handshake_secrets(hs) || !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret, @@ -635,7 +677,8 @@ static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) { * * TODO(davidben): This will need to be updated for DTLS 1.3. */ assert(!SSL_is_dtls(hs->ssl)); - uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0, hs->hash_len}; + assert(hs->hash_len <= 0xff); + uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0, static_cast<uint8_t>(hs->hash_len)}; if (!SSL_TRANSCRIPT_update(&hs->transcript, header, sizeof(header)) || !SSL_TRANSCRIPT_update(&hs->transcript, hs->expected_client_finished, hs->hash_len) || @@ -667,6 +710,18 @@ static enum ssl_hs_wait_t do_read_second_client_flight(SSL_HANDSHAKE *hs) { } static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) { + hs->tls13_state = state_process_change_cipher_spec; + /* If early data was accepted, the ChangeCipherSpec message will be in the + * discarded early data. */ + if (hs->early_data_offered && !hs->ssl->early_data_accepted) { + return ssl_hs_ok; + } + return hs->ssl->version == TLS1_3_EXPERIMENT_VERSION + ? ssl_hs_read_change_cipher_spec + : ssl_hs_ok; +} + +static enum ssl_hs_wait_t do_process_change_cipher_spec(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret, hs->hash_len)) { @@ -785,7 +840,8 @@ static enum ssl_hs_wait_t do_send_new_session_ticket(SSL_HANDSHAKE *hs) { enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) { while (hs->tls13_state != state_done) { enum ssl_hs_wait_t ret = ssl_hs_error; - enum server_hs_state_t state = hs->tls13_state; + enum server_hs_state_t state = + static_cast<enum server_hs_state_t>(hs->tls13_state); switch (state) { case state_select_parameters: ret = do_select_parameters(hs); @@ -814,6 +870,9 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) { case state_process_end_of_early_data: ret = do_process_end_of_early_data(hs); break; + case state_process_change_cipher_spec: + ret = do_process_change_cipher_spec(hs); + break; case state_process_client_certificate: ret = do_process_client_certificate(hs); break; diff --git a/src/ssl/tls_method.c b/src/ssl/tls_method.cc index d039b7db..d039b7db 100644 --- a/src/ssl/tls_method.c +++ b/src/ssl/tls_method.cc diff --git a/src/ssl/tls_record.c b/src/ssl/tls_record.cc index 3bc0b297..47082960 100644 --- a/src/ssl/tls_record.c +++ b/src/ssl/tls_record.cc @@ -139,10 +139,14 @@ static const uint8_t kMaxWarningAlerts = 4; /* ssl_needs_record_splitting returns one if |ssl|'s current outgoing cipher * state needs record-splitting and zero otherwise. */ static int ssl_needs_record_splitting(const SSL *ssl) { +#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE) return ssl->s3->aead_write_ctx != NULL && ssl->s3->aead_write_ctx->version < TLS1_1_VERSION && (ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0 && SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher); +#else + return 0; +#endif } int ssl_record_sequence_update(uint8_t *seq, size_t seq_len) { @@ -358,30 +362,24 @@ skipped_data: return ssl_open_record_discard; } -static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, - size_t max_out, uint8_t type, const uint8_t *in, - size_t in_len) { - assert(!buffers_alias(in, in_len, out, max_out)); +static int do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out, + uint8_t *out_suffix, size_t *out_suffix_len, + const size_t max_out_suffix_len, uint8_t type, + const uint8_t *in, const size_t in_len) { + assert(in == out || !buffers_alias(in, in_len, out, in_len)); + assert(!buffers_alias(in, in_len, out_prefix, ssl_record_prefix_len(ssl))); + assert(!buffers_alias(in, in_len, out_suffix, max_out_suffix_len)); /* TLS 1.3 hides the actual record type inside the encrypted data. */ + uint8_t *extra_in = NULL; + size_t extra_in_len = 0; if (ssl->s3->aead_write_ctx != NULL && ssl->s3->aead_write_ctx->version >= TLS1_3_VERSION) { - if (in_len > in_len + SSL3_RT_HEADER_LENGTH + 1 || - max_out < in_len + SSL3_RT_HEADER_LENGTH + 1) { - OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); - return 0; - } - - OPENSSL_memcpy(out + SSL3_RT_HEADER_LENGTH, in, in_len); - out[SSL3_RT_HEADER_LENGTH + in_len] = type; - in = out + SSL3_RT_HEADER_LENGTH; - type = SSL3_RT_APPLICATION_DATA; - in_len++; - } - - if (max_out < SSL3_RT_HEADER_LENGTH) { - OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); - return 0; + extra_in = &type; + extra_in_len = 1; + out_prefix[0] = SSL3_RT_APPLICATION_DATA; + } else { + out_prefix[0] = type; } /* The TLS record-layer version number is meaningless and, starting in @@ -395,65 +393,142 @@ static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, if (ssl->s3->have_version && ssl3_protocol_version(ssl) < TLS1_3_VERSION) { wire_version = ssl->version; } - - /* Write the non-length portions of the header. */ - out[0] = type; - out[1] = wire_version >> 8; - out[2] = wire_version & 0xff; + out_prefix[1] = wire_version >> 8; + out_prefix[2] = wire_version & 0xff; /* Write the ciphertext, leaving two bytes for the length. */ - size_t ciphertext_len; - if (!SSL_AEAD_CTX_seal(ssl->s3->aead_write_ctx, out + SSL3_RT_HEADER_LENGTH, - &ciphertext_len, max_out - SSL3_RT_HEADER_LENGTH, type, - wire_version, ssl->s3->write_sequence, in, in_len) || + if (!SSL_AEAD_CTX_seal_scatter( + ssl->s3->aead_write_ctx, out_prefix + SSL3_RT_HEADER_LENGTH, out, + out_suffix, out_suffix_len, max_out_suffix_len, type, wire_version, + ssl->s3->write_sequence, in, in_len, extra_in, extra_in_len) || !ssl_record_sequence_update(ssl->s3->write_sequence, 8)) { return 0; } /* Fill in the length. */ + const size_t ciphertext_len = + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx) + in_len + + *out_suffix_len; if (ciphertext_len >= 1 << 15) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return 0; } - out[3] = ciphertext_len >> 8; - out[4] = ciphertext_len & 0xff; + out_prefix[3] = ciphertext_len >> 8; + out_prefix[4] = ciphertext_len & 0xff; - *out_len = SSL3_RT_HEADER_LENGTH + ciphertext_len; - - ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, out, + ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, out_prefix, SSL3_RT_HEADER_LENGTH); return 1; } -int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, - uint8_t type, const uint8_t *in, size_t in_len) { - if (buffers_alias(in, in_len, out, max_out)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); - return 0; +static size_t tls_seal_scatter_prefix_len(const SSL *ssl, uint8_t type, + size_t in_len) { + size_t ret = SSL3_RT_HEADER_LENGTH; + if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 && + ssl_needs_record_splitting(ssl)) { + /* In the case of record splitting, the 1-byte record (of the 1/n-1 split) + * will be placed in the prefix, as will four of the five bytes of the + * record header for the main record. The final byte will replace the first + * byte of the plaintext that was used in the small record. */ + ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher); + ret += SSL3_RT_HEADER_LENGTH - 1; + } else { + ret += SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx); } + return ret; +} - size_t frag_len = 0; +/* tls_seal_scatter_record seals a new record of type |type| and body |in| and + * splits it between |out_prefix|, |out|, and |out_suffix|. Exactly + * |tls_seal_scatter_prefix_len| bytes are written to |out_prefix|, |in_len| + * bytes to |out|, and up to 1 + |SSL_AEAD_CTX_max_overhead| bytes to + * |out_suffix|. |*out_suffix_len| is set to the actual number of bytes written + * to |out_suffix|. It returns one on success and zero on error. If enabled, + * |tls_seal_scatter_record| implements TLS 1.0 CBC 1/n-1 record splitting and + * may write two records concatenated. */ +static int tls_seal_scatter_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out, + uint8_t *out_suffix, size_t *out_suffix_len, + size_t max_out_suffix_len, uint8_t type, + const uint8_t *in, size_t in_len) { if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 && ssl_needs_record_splitting(ssl)) { - if (!do_seal_record(ssl, out, &frag_len, max_out, type, in, 1)) { + assert(SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx) == 0); + const size_t prefix_len = SSL3_RT_HEADER_LENGTH; + + /* Write the 1-byte fragment into |out_prefix|. */ + uint8_t *split_body = out_prefix + prefix_len; + uint8_t *split_suffix = split_body + 1; + + /* TODO(martinkr): Make AEAD code not complain if max_suffix_len is lower + * than |EVP_AEAD_max_overhead| but still sufficiently large. */ + size_t split_max_suffix_len = + SSL_AEAD_CTX_max_suffix_len(ssl->s3->aead_write_ctx, 0); + size_t split_suffix_len = 0; + if (!do_seal_record(ssl, out_prefix, split_body, split_suffix, + &split_suffix_len, split_max_suffix_len, type, in, 1)) { return 0; } - in++; - in_len--; - out += frag_len; - max_out -= frag_len; -#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE) + size_t split_record_len = prefix_len + 1 + split_suffix_len; + assert(SSL3_RT_HEADER_LENGTH + ssl_cipher_get_record_split_len( ssl->s3->aead_write_ctx->cipher) == - frag_len); -#endif + split_record_len); + + /* Write the n-1-byte fragment. The header gets split between |out_prefix| + * (header[:-1]) and |out| (header[-1:]). */ + uint8_t tmp_prefix[SSL3_RT_HEADER_LENGTH]; + if (!do_seal_record(ssl, tmp_prefix, out + 1, out_suffix, out_suffix_len, + max_out_suffix_len, type, in + 1, in_len - 1)) { + return 0; + } + assert(tls_seal_scatter_prefix_len(ssl, type, in_len) == + split_record_len + SSL3_RT_HEADER_LENGTH - 1); + OPENSSL_memcpy(out_prefix + split_record_len, tmp_prefix, + SSL3_RT_HEADER_LENGTH - 1); + OPENSSL_memcpy(out, tmp_prefix + SSL3_RT_HEADER_LENGTH - 1, 1); + return 1; + } + + return do_seal_record(ssl, out_prefix, out, out_suffix, out_suffix_len, + max_out_suffix_len, type, in, in_len); +} + +int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out_len, + uint8_t type, const uint8_t *in, size_t in_len) { + if (buffers_alias(in, in_len, out, max_out_len)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); + return 0; } - if (!do_seal_record(ssl, out, out_len, max_out, type, in, in_len)) { + const size_t prefix_len = tls_seal_scatter_prefix_len(ssl, type, in_len); + + if (in_len + prefix_len < in_len) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); + return 0; + } + if (max_out_len < in_len + prefix_len) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); + return 0; + } + + uint8_t *prefix = out; + uint8_t *body = out + prefix_len; + uint8_t *suffix = body + in_len; + size_t max_suffix_len = max_out_len - prefix_len - in_len; + size_t suffix_len = 0; + + if (!tls_seal_scatter_record(ssl, prefix, body, suffix, &suffix_len, + max_suffix_len, type, in, in_len)) { + return 0; + } + + if (prefix_len + in_len + suffix_len < prefix_len + in_len) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); return 0; } - *out_len += frag_len; + + *out_len = prefix_len + in_len + suffix_len; return 1; } diff --git a/src/tool/client.cc b/src/tool/client.cc index 74a7124c..f7a82598 100644 --- a/src/tool/client.cc +++ b/src/tool/client.cc @@ -124,6 +124,10 @@ static const struct argument kArguments[] = { "-early-data", kOptionalArgument, "Allow early data", }, { + "-tls13-variant", kOptionalArgument, + "Enable the specified experimental TLS 1.3 variant", + }, + { "-ed25519", kBooleanArgument, "Advertise Ed25519 support", }, { @@ -459,6 +463,12 @@ bool Client(const std::vector<std::string> &args) { SSL_CTX_set_early_data_enabled(ctx.get(), 1); } + if (args_map.count("-tls13-variant") != 0) { + SSL_CTX_set_tls13_variant(ctx.get(), + static_cast<enum tls13_variant_t>( + atoi(args_map["-tls13-variant"].c_str()))); + } + if (args_map.count("-ed25519") != 0) { SSL_CTX_set_ed25519_enabled(ctx.get(), 1); } diff --git a/src/tool/server.cc b/src/tool/server.cc index 1d6d27c7..3b125ad1 100644 --- a/src/tool/server.cc +++ b/src/tool/server.cc @@ -68,6 +68,9 @@ static const struct argument kArguments[] = { "-early-data", kBooleanArgument, "Allow early data", }, { + "-tls13-variant", kBooleanArgument, "Enable TLS 1.3 variants", + }, + { "", kOptionalArgument, "", }, }; @@ -233,6 +236,11 @@ bool Server(const std::vector<std::string> &args) { SSL_CTX_set_early_data_enabled(ctx.get(), 1); } + // Enabling any TLS 1.3 variant on the server enables all of them. + if (args_map.count("-tls13-variant") != 0) { + SSL_CTX_set_tls13_variant(ctx.get(), tls13_experiment); + } + Listener listener; if (!listener.Init(args_map["-accept"])) { return false; diff --git a/src/util/all_tests.json b/src/util/all_tests.json index b92a057c..01d6fd06 100644 --- a/src/util/all_tests.json +++ b/src/util/all_tests.json @@ -1,8 +1,5 @@ [ ["crypto/crypto_test"], - ["crypto/fipsmodule/example_mul"], - ["crypto/x509v3/tab_test"], - ["crypto/x509v3/v3name_test"], ["decrepit/decrepit_test"], ["ssl/ssl_test"] ] diff --git a/src/util/generate_build_files.py b/src/util/generate_build_files.py index 38d757be..ef340e64 100644 --- a/src/util/generate_build_files.py +++ b/src/util/generate_build_files.py @@ -164,14 +164,6 @@ class Android(object): blueprint.write(' ],\n') blueprint.write('}\n\n') - blueprint.write('cc_defaults {\n') - blueprint.write(' name: "boringssl_tests_sources",\n') - blueprint.write(' srcs: [\n') - for f in sorted(files['test']): - blueprint.write(' "%s",\n' % f) - blueprint.write(' ],\n') - blueprint.write('}\n') - # Legacy Android.mk format, only used by Trusty in new branches with open('sources.mk', 'w+') as makefile: makefile.write(self.header) @@ -214,8 +206,6 @@ class Bazel(object): self.PrintVariableSection( out, 'ssl_internal_headers', files['ssl_internal_headers']) self.PrintVariableSection(out, 'ssl_sources', files['ssl']) - self.PrintVariableSection(out, 'ssl_c_sources', files['ssl_c']) - self.PrintVariableSection(out, 'ssl_cc_sources', files['ssl_cc']) self.PrintVariableSection(out, 'crypto_headers', files['crypto_headers']) self.PrintVariableSection( out, 'crypto_internal_headers', files['crypto_internal_headers']) @@ -245,79 +235,6 @@ class Bazel(object): files['crypto_test']) self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test']) - out.write('def create_tests(copts, crypto, ssl):\n') - name_counts = {} - for test in files['tests']: - name = os.path.basename(test[0]) - name_counts[name] = name_counts.get(name, 0) + 1 - - first = True - test_names = set() - for test in files['tests']: - name = os.path.basename(test[0]) - if name_counts[name] > 1: - if '/' in test[-1]: - arg = test[-1].replace('crypto/cipher/test/','') # boooring - arg = arg.replace('/', '_') - arg = os.path.splitext(arg)[0] # remove .txt - arg = arg.replace('_tests', '') - name += '_' + arg - else: - name += '_' + test[-1].replace('-', '_') - - if name in test_names: - raise ValueError("test name %s is not unique" % name) - test_names.add(name) - - if not first: - out.write('\n') - first = False - - for src in files['test']: - # For example, basename(src/crypto/fipsmodule/aes/aes_test.cc) - # startswith basename(crypto/fipsmodule/aes_test). - if os.path.basename(src).startswith(os.path.basename(test[0]) + '.'): - src = src - break - else: - raise ValueError("Can't find source for %s" % test[0]) - - out.write(' native.cc_test(\n') - out.write(' name = "%s",\n' % name) - out.write(' size = "small",\n') - out.write(' srcs = ["%s"] + test_support_sources,\n' % - PathOf(src)) - - data_files = [] - if len(test) > 1: - - out.write(' args = [\n') - for arg in test[1:]: - if '/' in arg: - out.write(' "$(location %s)",\n' % - PathOf(os.path.join('src', arg))) - data_files.append('src/%s' % arg) - else: - out.write(' "%s",\n' % arg) - out.write(' ],\n') - - out.write(' copts = copts,\n') - - if len(data_files) > 0: - out.write(' data = [\n') - for filename in data_files: - out.write(' "%s",\n' % PathOf(filename)) - out.write(' ],\n') - - if 'ssl/' in test[0]: - out.write(' deps = [\n') - out.write(' crypto,\n') - out.write(' ssl,\n') - out.write(' ],\n') - else: - out.write(' deps = [crypto],\n') - out.write(' )\n') - class GN(object): @@ -371,36 +288,6 @@ class GN(object): self.PrintVariableSection(out, 'crypto_test_sources', files['crypto_test']) self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test']) - out.write('\n') - - out.write('template("create_tests") {\n') - - all_tests = [] - for test in sorted(files['test']): - test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0] - all_tests.append(test_name) - - out.write(' executable("%s") {\n' % test_name) - out.write(' sources = [\n') - out.write(' "%s",\n' % test) - out.write(' ]\n') - out.write(' sources += test_support_sources\n') - out.write(' if (defined(invoker.configs_exclude)) {\n') - out.write(' configs -= invoker.configs_exclude\n') - out.write(' }\n') - out.write(' configs += invoker.configs\n') - out.write(' deps = invoker.deps + ') - out.write('[ "//build/config:exe_and_shlib_deps" ]\n') - out.write(' }\n') - out.write('\n') - - out.write(' group(target_name) {\n') - out.write(' deps = [\n') - for test_name in sorted(all_tests): - out.write(' ":%s",\n' % test_name) - out.write(' ]\n') - out.write(' }\n') - out.write('}\n') class GYP(object): @@ -464,7 +351,7 @@ def NoTests(path, dent, is_dir): sources.""" if is_dir: return dent != 'test' - return 'test.' not in dent and not dent.startswith('example_') + return 'test.' not in dent def OnlyTests(path, dent, is_dir): @@ -472,7 +359,7 @@ def OnlyTests(path, dent, is_dir): non-test sources.""" if is_dir: return dent != 'test' - return '_test.' in dent or dent.startswith('example_') + return '_test.' in dent def AllFiles(path, dent, is_dir): @@ -662,11 +549,6 @@ def ExtractVariablesFromCMakeFile(cmakefile): return variables -def IsGTest(path): - with open(path) as f: - return "#include <gtest/gtest.h>" in f.read() - - def main(platforms): cmake = ExtractVariablesFromCMakeFile(os.path.join('src', 'sources.cmake')) crypto_c_files = FindCFiles(os.path.join('src', 'crypto'), NoTestsNorFIPSFragments) @@ -695,18 +577,12 @@ def main(platforms): cwd='src', stdout=out) - test_c_files = [] - crypto_test_files = [ + crypto_test_files = FindCFiles(os.path.join('src', 'crypto'), OnlyTests) + crypto_test_files += [ 'crypto_test_data.cc', 'src/crypto/test/file_test_gtest.cc', 'src/crypto/test/gtest_main.cc', ] - # TODO(davidben): Remove this loop once all tests are converted. - for path in FindCFiles(os.path.join('src', 'crypto'), OnlyTests): - if IsGTest(path): - crypto_test_files.append(path) - else: - test_c_files.append(path) ssl_test_files = FindCFiles(os.path.join('src', 'ssl'), OnlyTests) ssl_test_files.append('src/crypto/test/gtest_main.cc') @@ -729,37 +605,6 @@ def main(platforms): crypto_internal_h_files = FindHeaderFiles( os.path.join('src', 'crypto'), NoTests) - with open('src/util/all_tests.json', 'r') as f: - tests = json.load(f) - # For now, GTest-based tests are specified manually. - tests = [test for test in tests if test[0] not in ['crypto/crypto_test', - 'decrepit/decrepit_test', - 'ssl/ssl_test']] - # The same test name can appear multiple times with different arguments. So, - # make a set to get a list of unique test binaries. - test_names = set([test[0] for test in tests]) - test_binaries = set(map(os.path.basename, test_names)) - # Make sure the test basenames are unique. - if len(test_binaries) != len(set(test_names)): - raise ValueError('non-unique test basename') - # Ensure a 1:1 correspondence between test sources and tests. This - # guarantees that the Bazel output includes everything in the JSON. - # Sometimes, a test's source isn't in the same directory as the test, - # which we handle by considering only the basename. - test_sources = set(map(os.path.basename, [ - test.replace('.cc', '').replace('.c', '').replace( - 'src/', - '') - for test in test_c_files])) - if test_binaries != test_sources: - print 'Test sources and configured tests do not match' - a = test_binaries.difference(test_sources) - if len(a) > 0: - print 'These tests are configured without sources: ' + str(a) - b = test_sources.difference(test_binaries) - if len(b) > 0: - print 'These test sources are not configured: ' + str(b) - files = { 'crypto': crypto_c_files, 'crypto_headers': crypto_h_files, @@ -768,17 +613,13 @@ def main(platforms): 'fips_fragments': fips_fragments, 'fuzz': fuzz_c_files, 'ssl': ssl_source_files, - 'ssl_c': [s for s in ssl_source_files if s.endswith('.c')], - 'ssl_cc': [s for s in ssl_source_files if s.endswith('.cc')], 'ssl_headers': ssl_h_files, 'ssl_internal_headers': ssl_internal_h_files, 'ssl_test': sorted(ssl_test_files), 'tool': tool_c_files, 'tool_headers': tool_h_files, - 'test': test_c_files, 'test_support': test_support_c_files, 'test_support_headers': test_support_h_files, - 'tests': tests, } asm_outputs = sorted(WriteAsmFiles(ReadPerlAsmOperations()).iteritems()) |