Compare commits

..

2 Commits

Author SHA1 Message Date
Adam Langley be873e9f48 Set output alert when failing to parse public key.
Previously, the alert was uninitialised.

(Thanks to Robert Swiecki and honggfuzz.)

Change-Id: I2d4eb96b0126f3eb502672b2600ad43ae140acec
Reviewed-on: https://boringssl-review.googlesource.com/13700
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
(cherry picked from commit 7dccc71e08)
2017-02-14 14:49:06 -05:00
David Benjamin b8684f0276 Revert changes to use getrandom for M57.
This reverts commit 2d58482004 and
39ae144759.

BUG=chromium:673183

Change-Id: I19abdb11fc3872d2499072de8269d0744ae2f90a
Reviewed-on: https://boringssl-review.googlesource.com/13235
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2017-01-23 21:02:55 +00:00
723 changed files with 21597 additions and 109214 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
## Build Prerequisites
* [CMake](https://cmake.org/download/) 2.8.11 or later is required.
* [CMake](https://cmake.org/download/) 2.8.10 or later is required.
* Perl 5.6.1 or later is required. On Windows,
[Active State Perl](http://www.activestate.com/activeperl/) has been
+3 -18
View File
@@ -1,4 +1,4 @@
cmake_minimum_required (VERSION 2.8.11)
cmake_minimum_required (VERSION 2.8.10)
# Defer enabling C and CXX languages.
project (BoringSSL NONE)
@@ -43,9 +43,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
endif()
elseif(MSVC)
set(MSVC_DISABLED_WARNINGS_LIST
"C4061" # enumerator 'identifier' in switch of enum 'enumeration' is not
# explicitly handled by a case label
# Disable this because it flags even when there is a default.
"C4100" # 'exarg' : unreferenced formal parameter
"C4127" # conditional expression is constant
"C4200" # nonstandard extension used : zero-sized array in
@@ -81,16 +78,12 @@ elseif(MSVC)
# copy constructor is inaccessible or deleted
"C4626" # assignment operator could not be generated because a base class
# assignment operator is inaccessible or deleted
"C4668" # 'symbol' is not defined as a preprocessor macro, replacing with
# '0' for 'directives'
# Disable this because GTest uses it everywhere.
"C4706" # assignment within conditional expression
"C4710" # 'function': function not inlined
"C4711" # function 'function' selected for inline expansion
"C4800" # 'int' : forcing value to bool 'true' or 'false'
# (performance warning)
"C4820" # 'bytes' bytes padding added after construct 'member_name'
"C5026" # move constructor was implicitly defined as deleted
"C5027" # move assignment operator was implicitly defined as deleted
)
set(MSVC_LEVEL4_WARNINGS_LIST
@@ -181,7 +174,6 @@ elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
set(ARCH "aarch64")
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "mips")
# Just to avoid the “unknown processor” error.
set(ARCH "generic")
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64le")
set(ARCH "ppc64le")
else()
@@ -221,8 +213,8 @@ if (ASAN)
message(FATAL_ERROR "Cannot enable ASAN unless using Clang")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(OPENSSL_NO_ASM "1")
endif()
@@ -236,13 +228,6 @@ if (OPENSSL_NO_ASM)
set(ARCH "generic")
endif()
# Add minimal googletest targets. The provided one has many side-effects, and
# googletest has a very straightforward build.
add_library(gtest third_party/googletest/src/gtest-all.cc)
target_include_directories(gtest PRIVATE third_party/googletest)
include_directories(third_party/googletest/include)
# Declare a dummy target to build all unit tests. Test targets should inject
# themselves as dependencies next to the target definition.
add_custom_target(all_tests)
+1 -1
View File
@@ -80,5 +80,5 @@ If both sets of tests pass, refresh the fuzzer corpora with `refresh_ssl_corpora
```
cd fuzz
./refresh_ssl_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
./refresh_fuzzer_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
```
-1
View File
@@ -227,7 +227,6 @@ parameter.
`SSL_CTRL_OPTIONS` | `SSL_CTX_get_options` or `SSL_CTX_set_options`
`SSL_CTRL_SESS_NUMBER` | `SSL_CTX_sess_number`
`SSL_CTRL_SET_CURVES` | `SSL_CTX_set1_curves`
`SSL_CTRL_SET_ECDH_AUTO` | `SSL_CTX_set_ecdh_auto`
`SSL_CTRL_SET_MAX_CERT_LIST` | `SSL_CTX_set_max_cert_list`
`SSL_CTRL_SET_MAX_SEND_FRAGMENT` | `SSL_CTX_set_max_send_fragment`
`SSL_CTRL_SET_MSG_CALLBACK` | `SSL_set_msg_callback`
+12 -26
View File
@@ -129,6 +129,7 @@ add_library(
thread_none.c
thread_pthread.c
thread_win.c
time_support.c
$<TARGET_OBJECTS:stack>
$<TARGET_OBJECTS:lhash>
@@ -176,6 +177,17 @@ if(NOT MSVC AND NOT ANDROID)
target_link_libraries(crypto pthread)
endif()
add_executable(
constant_time_test
constant_time_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(constant_time_test crypto)
add_dependencies(all_tests constant_time_test)
add_executable(
thread_test
@@ -195,29 +207,3 @@ add_executable(
target_link_libraries(refcount_test crypto)
add_dependencies(all_tests refcount_test)
# TODO(davidben): Convert the remaining tests to GTest.
add_executable(
crypto_test
asn1/asn1_test.cc
bio/bio_test.cc
chacha/chacha_test.cc
constant_time_test.cc
curve25519/x25519_test.cc
dh/dh_test.cc
dsa/dsa_test.cc
ec/ec_test.cc
err/err_test.cc
evp/evp_extra_test.cc
rsa/rsa_test.cc
$<TARGET_OBJECTS:gtest_main>
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(crypto_test crypto gtest)
if (WIN32)
target_link_libraries(crypto_test ws2_32)
endif()
add_dependencies(all_tests crypto_test)
+6 -6
View File
@@ -116,7 +116,7 @@
# words every cache-line is *guaranteed* to be accessed within ~50
# cycles window. Why just SSE? Because it's needed on hyper-threading
# CPU! Which is also why it's prefetched with 64 byte stride. Best
# part is that it has no negative effect on performance:-)
# part is that it has no negative effect on performance:-)
#
# Version 4.3 implements switch between compact and non-compact block
# functions in AES_cbc_encrypt depending on how much data was asked
@@ -578,7 +578,7 @@ sub enctransform()
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | mm4 | mm0 |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# | s3 | s2 | s1 | s0 |
# | s3 | s2 | s1 | s0 |
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
# |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
@@ -798,7 +798,7 @@ sub encstep()
if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx
elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2]
else { &mov ($tmp,$s[3]);
else { &mov ($tmp,$s[3]);
&shr ($tmp,24) }
&xor ($out,&DWP(1,$te,$tmp,8));
if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
@@ -1551,7 +1551,7 @@ sub sse_deccompact()
&pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp4
&pshufw ("mm3","mm1",0xb1); &pshufw ("mm7","mm5",0xb1);
&pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp4
&pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= ROTATE(tp4,16)
&pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= ROTATE(tp4,16)
&pxor ("mm3","mm3"); &pxor ("mm7","mm7");
&pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5");
@@ -2021,7 +2021,7 @@ sub declast()
{
# stack frame layout
# -4(%esp) # return address 0(%esp)
# 0(%esp) # s0 backing store 4(%esp)
# 0(%esp) # s0 backing store 4(%esp)
# 4(%esp) # s1 backing store 8(%esp)
# 8(%esp) # s2 backing store 12(%esp)
# 12(%esp) # s3 backing store 16(%esp)
@@ -2731,7 +2731,7 @@ sub enckey()
&mov (&DWP(80,"edi"),10); # setup number of rounds
&xor ("eax","eax");
&jmp (&label("exit"));
&set_label("12rounds");
&mov ("eax",&DWP(0,"esi")); # copy first 6 dwords
&mov ("ebx",&DWP(4,"esi"));
Executable → Regular
+24 -22
View File
@@ -590,7 +590,6 @@ $code.=<<___;
.type asm_AES_encrypt,\@function,3
.hidden asm_AES_encrypt
asm_AES_encrypt:
mov %rsp,%rax
push %rbx
push %rbp
push %r12
@@ -599,6 +598,7 @@ asm_AES_encrypt:
push %r15
# allocate frame "above" key schedule
mov %rsp,%r10
lea -63(%rdx),%rcx # %rdx is key argument
and \$-64,%rsp
sub %rsp,%rcx
@@ -608,7 +608,7 @@ asm_AES_encrypt:
sub \$32,%rsp
mov %rsi,16(%rsp) # save out
mov %rax,24(%rsp) # save original stack pointer
mov %r10,24(%rsp) # save real stack pointer
.Lenc_prologue:
mov %rdx,$key
@@ -640,13 +640,13 @@ asm_AES_encrypt:
mov $s2,8($out)
mov $s3,12($out)
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
mov -24(%rsi),%r12
mov -16(%rsi),%rbp
mov -8(%rsi),%rbx
lea (%rsi),%rsp
mov (%rsi),%r15
mov 8(%rsi),%r14
mov 16(%rsi),%r13
mov 24(%rsi),%r12
mov 32(%rsi),%rbp
mov 40(%rsi),%rbx
lea 48(%rsi),%rsp
.Lenc_epilogue:
ret
.size asm_AES_encrypt,.-asm_AES_encrypt
@@ -1186,7 +1186,6 @@ $code.=<<___;
.type asm_AES_decrypt,\@function,3
.hidden asm_AES_decrypt
asm_AES_decrypt:
mov %rsp,%rax
push %rbx
push %rbp
push %r12
@@ -1195,6 +1194,7 @@ asm_AES_decrypt:
push %r15
# allocate frame "above" key schedule
mov %rsp,%r10
lea -63(%rdx),%rcx # %rdx is key argument
and \$-64,%rsp
sub %rsp,%rcx
@@ -1204,7 +1204,7 @@ asm_AES_decrypt:
sub \$32,%rsp
mov %rsi,16(%rsp) # save out
mov %rax,24(%rsp) # save original stack pointer
mov %r10,24(%rsp) # save real stack pointer
.Ldec_prologue:
mov %rdx,$key
@@ -1238,13 +1238,13 @@ asm_AES_decrypt:
mov $s2,8($out)
mov $s3,12($out)
mov -48(%rsi),%r15
mov -40(%rsi),%r14
mov -32(%rsi),%r13
mov -24(%rsi),%r12
mov -16(%rsi),%rbp
mov -8(%rsi),%rbx
lea (%rsi),%rsp
mov (%rsi),%r15
mov 8(%rsi),%r14
mov 16(%rsi),%r13
mov 24(%rsi),%r12
mov 32(%rsi),%rbp
mov 40(%rsi),%rbx
lea 48(%rsi),%rsp
.Ldec_epilogue:
ret
.size asm_AES_decrypt,.-asm_AES_decrypt
@@ -1286,7 +1286,7 @@ $code.=<<___;
asm_AES_set_encrypt_key:
push %rbx
push %rbp
push %r12 # redundant, but allows to share
push %r12 # redundant, but allows to share
push %r13 # exception handler...
push %r14
push %r15
@@ -1412,7 +1412,7 @@ $code.=<<___;
xor %rax,%rax
jmp .Lexit
.L14rounds:
.L14rounds:
mov 0(%rsi),%rax # copy first 8 dwords
mov 8(%rsi),%rbx
mov 16(%rsi),%rcx
@@ -1660,9 +1660,10 @@ asm_AES_cbc_encrypt:
mov %r9d,%r9d # clear upper half of enc
lea .LAES_Te(%rip),$sbox
lea .LAES_Td(%rip),%r10
cmp \$0,%r9
cmoveq %r10,$sbox
jne .Lcbc_picked_te
lea .LAES_Td(%rip),$sbox
.Lcbc_picked_te:
mov OPENSSL_ia32cap_P(%rip),%r10d
cmp \$$speed_limit,%rdx
@@ -2564,6 +2565,7 @@ block_se_handler:
jae .Lin_block_prologue
mov 24(%rax),%rax # pull saved real stack pointer
lea 48(%rax),%rax # adjust...
mov -8(%rax),%rbx
mov -16(%rax),%rbp
+1 -3
View File
@@ -51,9 +51,7 @@
# Westmere 3.77/1.37 1.37 1.52 1.27
# * Bridge 5.07/0.98 0.99 1.09 0.91
# Haswell 4.44/0.80 0.97 1.03 0.72
# Skylake 2.68/0.65 0.65 0.66 0.64
# Silvermont 5.77/3.56 3.67 4.03 3.46
# Goldmont 3.84/1.39 1.39 1.63 1.31
# Bulldozer 5.80/0.98 1.05 1.24 0.93
$PREFIX="aesni"; # if $PREFIX is set to "AES", the script
@@ -1042,7 +1040,7 @@ if ($PREFIX eq "aesni") {
&set_label("ctr32_one_shortcut",16);
&movups ($inout0,&QWP(0,$rounds_)); # load ivec
&mov ($rounds,&DWP(240,$key));
&set_label("ctr32_one");
if ($inline)
{ &aesni_inline_generate1("enc"); }
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -957,21 +957,21 @@ if ($flavour =~ /64/) { ######## 64-bit code
$arg =~ m/q([0-9]+),\s*\{q([0-9]+)\},\s*q([0-9]+)/o &&
sprintf "vtbl.8 d%d,{q%d},d%d\n\t".
"vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1;
"vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1;
}
sub unvdup32 {
my $arg=shift;
$arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o &&
sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
}
sub unvmov32 {
my $arg=shift;
$arg =~ m/q([0-9]+)\[([0-3])\],(.*)/o &&
sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3;
sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3;
}
foreach(split("\n",$code)) {
+3 -11
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -91,7 +84,7 @@ my @s=@_[12..15];
sub InBasisChange {
# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
my @b=@_[0..7];
$code.=<<___;
veor @b[2], @b[2], @b[1]
@@ -738,7 +731,6 @@ $code.=<<___;
.thumb
#else
.code 32
# undef __thumb2__
#endif
.type _bsaes_decrypt8,%function
@@ -1365,7 +1357,7 @@ bsaes_cbc_encrypt:
vmov @XMM[4],@XMM[15] @ just in case ensure that IV
vmov @XMM[5],@XMM[0] @ and input are preserved
bl AES_decrypt
vld1.8 {@XMM[0]}, [$fp] @ load result
vld1.8 {@XMM[0]}, [$fp,:64] @ load result
veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV
vmov @XMM[15], @XMM[5] @ @XMM[5] holds input
vst1.8 {@XMM[0]}, [$rounds] @ write output
+74 -91
View File
@@ -41,7 +41,6 @@
# Nehalem(**) 7.63 6.88 +11%
# Atom 17.1 16.4 +4%
# Silvermont - 12.9
# Goldmont - 8.85
#
# (*) Comparison is not completely fair, because "this" is ECB,
# i.e. no extra processing such as counter values calculation
@@ -81,7 +80,6 @@
# Nehalem 7.80
# Atom 17.9
# Silvermont 14.0
# Goldmont 10.2
#
# November 2011.
#
@@ -124,7 +122,7 @@ my @s=@_[12..15];
sub InBasisChange {
# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
my @b=@_[0..7];
$code.=<<___;
pxor @b[6], @b[5]
@@ -374,7 +372,7 @@ $code.=<<___;
pxor @s[0], @t[3]
pxor @s[1], @t[2]
pxor @s[2], @t[1]
pxor @s[3], @t[0]
pxor @s[3], @t[0]
#Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
@@ -1327,7 +1325,7 @@ $code.=<<___;
cmp %rax, %rbp
jb .Lecb_enc_bzero
lea 0x78(%rbp),%rax
lea (%rbp),%rsp # restore %rsp
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -1340,17 +1338,17 @@ $code.=<<___ if ($win64);
movaps 0xb0(%rbp), %xmm13
movaps 0xc0(%rbp), %xmm14
movaps 0xd0(%rbp), %xmm15
lea 0xa0(%rax), %rax
.Lecb_enc_tail:
lea 0xa0(%rbp), %rsp
___
$code.=<<___;
mov -48(%rax), %r15
mov -40(%rax), %r14
mov -32(%rax), %r13
mov -24(%rax), %r12
mov -16(%rax), %rbx
mov -8(%rax), %rbp
lea (%rax), %rsp # restore %rsp
mov 0x48(%rsp), %r15
mov 0x50(%rsp), %r14
mov 0x58(%rsp), %r13
mov 0x60(%rsp), %r12
mov 0x68(%rsp), %rbx
mov 0x70(%rsp), %rax
lea 0x78(%rsp), %rsp
mov %rax, %rbp
.Lecb_enc_epilogue:
ret
.size bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
@@ -1529,7 +1527,7 @@ $code.=<<___;
cmp %rax, %rbp
jb .Lecb_dec_bzero
lea 0x78(%rbp),%rax
lea (%rbp),%rsp # restore %rsp
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -1542,17 +1540,17 @@ $code.=<<___ if ($win64);
movaps 0xb0(%rbp), %xmm13
movaps 0xc0(%rbp), %xmm14
movaps 0xd0(%rbp), %xmm15
lea 0xa0(%rax), %rax
.Lecb_dec_tail:
lea 0xa0(%rbp), %rsp
___
$code.=<<___;
mov -48(%rax), %r15
mov -40(%rax), %r14
mov -32(%rax), %r13
mov -24(%rax), %r12
mov -16(%rax), %rbx
mov -8(%rax), %rbp
lea (%rax), %rsp # restore %rsp
mov 0x48(%rsp), %r15
mov 0x50(%rsp), %r14
mov 0x58(%rsp), %r13
mov 0x60(%rsp), %r12
mov 0x68(%rsp), %rbx
mov 0x70(%rsp), %rax
lea 0x78(%rsp), %rsp
mov %rax, %rbp
.Lecb_dec_epilogue:
ret
.size bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks
@@ -1819,7 +1817,7 @@ $code.=<<___;
cmp %rax, %rbp
ja .Lcbc_dec_bzero
lea 0x78(%rbp),%rax
lea (%rbp),%rsp # restore %rsp
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -1832,17 +1830,17 @@ $code.=<<___ if ($win64);
movaps 0xb0(%rbp), %xmm13
movaps 0xc0(%rbp), %xmm14
movaps 0xd0(%rbp), %xmm15
lea 0xa0(%rax), %rax
.Lcbc_dec_tail:
lea 0xa0(%rbp), %rsp
___
$code.=<<___;
mov -48(%rax), %r15
mov -40(%rax), %r14
mov -32(%rax), %r13
mov -24(%rax), %r12
mov -16(%rax), %rbx
mov -8(%rax), %rbp
lea (%rax), %rsp # restore %rsp
mov 0x48(%rsp), %r15
mov 0x50(%rsp), %r14
mov 0x58(%rsp), %r13
mov 0x60(%rsp), %r12
mov 0x68(%rsp), %rbx
mov 0x70(%rsp), %rax
lea 0x78(%rsp), %rsp
mov %rax, %rbp
.Lcbc_dec_epilogue:
ret
.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
@@ -2051,7 +2049,7 @@ $code.=<<___;
cmp %rax, %rbp
ja .Lctr_enc_bzero
lea 0x78(%rbp),%rax
lea (%rbp),%rsp # restore %rsp
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -2064,17 +2062,17 @@ $code.=<<___ if ($win64);
movaps 0xb0(%rbp), %xmm13
movaps 0xc0(%rbp), %xmm14
movaps 0xd0(%rbp), %xmm15
lea 0xa0(%rax), %rax
.Lctr_enc_tail:
lea 0xa0(%rbp), %rsp
___
$code.=<<___;
mov -48(%rax), %r15
mov -40(%rax), %r14
mov -32(%rax), %r13
mov -24(%rax), %r12
mov -16(%rax), %rbx
mov -8(%rax), %rbp
lea (%rax), %rsp # restore %rsp
mov 0x48(%rsp), %r15
mov 0x50(%rsp), %r14
mov 0x58(%rsp), %r13
mov 0x60(%rsp), %r12
mov 0x68(%rsp), %rbx
mov 0x70(%rsp), %rax
lea 0x78(%rsp), %rsp
mov %rax, %rbp
.Lctr_enc_epilogue:
ret
.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
@@ -2441,7 +2439,7 @@ $code.=<<___;
cmp %rax, %rbp
ja .Lxts_enc_bzero
lea 0x78(%rbp),%rax
lea (%rbp),%rsp # restore %rsp
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -2454,17 +2452,17 @@ $code.=<<___ if ($win64);
movaps 0xb0(%rbp), %xmm13
movaps 0xc0(%rbp), %xmm14
movaps 0xd0(%rbp), %xmm15
lea 0xa0(%rax), %rax
.Lxts_enc_tail:
lea 0xa0(%rbp), %rsp
___
$code.=<<___;
mov -48(%rax), %r15
mov -40(%rax), %r14
mov -32(%rax), %r13
mov -24(%rax), %r12
mov -16(%rax), %rbx
mov -8(%rax), %rbp
lea (%rax), %rsp # restore %rsp
mov 0x48(%rsp), %r15
mov 0x50(%rsp), %r14
mov 0x58(%rsp), %r13
mov 0x60(%rsp), %r12
mov 0x68(%rsp), %rbx
mov 0x70(%rsp), %rax
lea 0x78(%rsp), %rsp
mov %rax, %rbp
.Lxts_enc_epilogue:
ret
.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
@@ -2848,7 +2846,7 @@ $code.=<<___;
cmp %rax, %rbp
ja .Lxts_dec_bzero
lea 0x78(%rbp),%rax
lea (%rbp),%rsp # restore %rsp
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -2861,17 +2859,17 @@ $code.=<<___ if ($win64);
movaps 0xb0(%rbp), %xmm13
movaps 0xc0(%rbp), %xmm14
movaps 0xd0(%rbp), %xmm15
lea 0xa0(%rax), %rax
.Lxts_dec_tail:
lea 0xa0(%rbp), %rsp
___
$code.=<<___;
mov -48(%rax), %r15
mov -40(%rax), %r14
mov -32(%rax), %r13
mov -24(%rax), %r12
mov -16(%rax), %rbx
mov -8(%rax), %rbp
lea (%rax), %rsp # restore %rsp
mov 0x48(%rsp), %r15
mov 0x50(%rsp), %r14
mov 0x58(%rsp), %r13
mov 0x60(%rsp), %r12
mov 0x68(%rsp), %rbx
mov 0x70(%rsp), %rax
lea 0x78(%rsp), %rsp
mov %rax, %rbp
.Lxts_dec_epilogue:
ret
.size bsaes_xts_decrypt,.-bsaes_xts_decrypt
@@ -2967,34 +2965,31 @@ se_handler:
mov 0(%r11),%r10d # HandlerData[0]
lea (%rsi,%r10),%r10 # prologue label
cmp %r10,%rbx # context->Rip<=prologue label
jbe .Lin_prologue
cmp %r10,%rbx # context->Rip<prologue label
jb .Lin_prologue
mov 152($context),%rax # pull context->Rsp
mov 4(%r11),%r10d # HandlerData[1]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=epilogue label
jae .Lin_prologue
mov 8(%r11),%r10d # HandlerData[2]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=tail label
jae .Lin_tail
mov 160($context),%rax # pull context->Rbp
lea 0x40(%rax),%rsi # %xmm save area
lea 512($context),%rdi # &context.Xmm6
mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
.long 0xa548f3fc # cld; rep movsq
lea 0xa0+0x78(%rax),%rax # adjust stack pointer
lea 0xa0(%rax),%rax # adjust stack pointer
.Lin_tail:
mov -48(%rax),%rbp
mov -40(%rax),%rbx
mov -32(%rax),%r12
mov -24(%rax),%r13
mov -16(%rax),%r14
mov -8(%rax),%r15
mov 0x70(%rax),%rbp
mov 0x68(%rax),%rbx
mov 0x60(%rax),%r12
mov 0x58(%rax),%r13
mov 0x50(%rax),%r14
mov 0x48(%rax),%r15
lea 0x78(%rax),%rax # adjust stack pointer
mov %rbx,144($context) # restore context->Rbx
mov %rbp,160($context) # restore context->Rbp
mov %r12,216($context) # restore context->R12
@@ -3075,40 +3070,28 @@ $code.=<<___ if ($ecb);
.byte 9,0,0,0
.rva se_handler
.rva .Lecb_enc_body,.Lecb_enc_epilogue # HandlerData[]
.rva .Lecb_enc_tail
.long 0
.Lecb_dec_info:
.byte 9,0,0,0
.rva se_handler
.rva .Lecb_dec_body,.Lecb_dec_epilogue # HandlerData[]
.rva .Lecb_dec_tail
.long 0
___
$code.=<<___;
.Lcbc_dec_info:
.byte 9,0,0,0
.rva se_handler
.rva .Lcbc_dec_body,.Lcbc_dec_epilogue # HandlerData[]
.rva .Lcbc_dec_tail
.long 0
.Lctr_enc_info:
.byte 9,0,0,0
.rva se_handler
.rva .Lctr_enc_body,.Lctr_enc_epilogue # HandlerData[]
.rva .Lctr_enc_tail
.long 0
.Lxts_enc_info:
.byte 9,0,0,0
.rva se_handler
.rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[]
.rva .Lxts_enc_tail
.long 0
.Lxts_dec_info:
.byte 9,0,0,0
.rva se_handler
.rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[]
.rva .Lxts_dec_tail
.long 0
___
}
+4 -4
View File
@@ -438,7 +438,7 @@ $k_dsbo=0x2c0; # decryption sbox final output
##
&set_label("schedule_192",16);
&movdqu ("xmm0",&QWP(8,$inp)); # load key part 2 (very unaligned)
&call ("_vpaes_schedule_transform"); # input transform
&call ("_vpaes_schedule_transform"); # input transform
&movdqa ("xmm6","xmm0"); # save short part
&pxor ("xmm4","xmm4"); # clear 4
&movhlps("xmm6","xmm4"); # clobber low side with zeros
@@ -469,7 +469,7 @@ $k_dsbo=0x2c0; # decryption sbox final output
##
&set_label("schedule_256",16);
&movdqu ("xmm0",&QWP(16,$inp)); # load key part 2 (unaligned)
&call ("_vpaes_schedule_transform"); # input transform
&call ("_vpaes_schedule_transform"); # input transform
&mov ($round,7);
&set_label("loop_schedule_256");
@@ -480,7 +480,7 @@ $k_dsbo=0x2c0; # decryption sbox final output
&call ("_vpaes_schedule_round");
&dec ($round);
&jz (&label("schedule_mangle_last"));
&call ("_vpaes_schedule_mangle");
&call ("_vpaes_schedule_mangle");
# low round. swap xmm7 and xmm6
&pshufd ("xmm0","xmm0",0xFF);
@@ -603,7 +603,7 @@ $k_dsbo=0x2c0; # decryption sbox final output
# subbyte
&movdqa ("xmm4",&QWP($k_s0F,$const));
&movdqa ("xmm5",&QWP($k_inv,$const)); # 4 : 1/j
&movdqa ("xmm1","xmm4");
&movdqa ("xmm1","xmm4");
&pandn ("xmm1","xmm0");
&psrld ("xmm1",4); # 1 = i
&pand ("xmm0","xmm4"); # 0 = k
+10 -11
View File
@@ -31,7 +31,6 @@
# Nehalem 29.6/40.3/14.6 10.0/11.8
# Atom 57.3/74.2/32.1 60.9/77.2(***)
# Silvermont 52.7/64.0/19.5 48.8/60.8(***)
# Goldmont 38.9/49.0/17.8 10.6/12.6
#
# (*) "Hyper-threading" in the context refers rather to cache shared
# among multiple cores, than to specifically Intel HTT. As vast
@@ -165,7 +164,7 @@ _vpaes_encrypt_core:
pshufb %xmm1, %xmm0
ret
.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
##
## Decryption core
##
@@ -326,7 +325,7 @@ _vpaes_schedule_core:
##
.Lschedule_128:
mov \$10, %esi
.Loop_schedule_128:
call _vpaes_schedule_round
dec %rsi
@@ -360,7 +359,7 @@ _vpaes_schedule_core:
.Loop_schedule_192:
call _vpaes_schedule_round
palignr \$8,%xmm6,%xmm0
palignr \$8,%xmm6,%xmm0
call _vpaes_schedule_mangle # save key n
call _vpaes_schedule_192_smear
call _vpaes_schedule_mangle # save key n+1
@@ -386,7 +385,7 @@ _vpaes_schedule_core:
movdqu 16(%rdi),%xmm0 # load key part 2 (unaligned)
call _vpaes_schedule_transform # input transform
mov \$7, %esi
.Loop_schedule_256:
call _vpaes_schedule_mangle # output low result
movdqa %xmm0, %xmm6 # save cur_lo in xmm6
@@ -395,7 +394,7 @@ _vpaes_schedule_core:
call _vpaes_schedule_round
dec %rsi
jz .Lschedule_mangle_last
call _vpaes_schedule_mangle
call _vpaes_schedule_mangle
# low round. swap xmm7 and xmm6
pshufd \$0xFF, %xmm0, %xmm0
@@ -403,10 +402,10 @@ _vpaes_schedule_core:
movdqa %xmm6, %xmm7
call _vpaes_schedule_low_round
movdqa %xmm5, %xmm7
jmp .Loop_schedule_256
##
## .aes_schedule_mangle_last
##
@@ -505,9 +504,9 @@ _vpaes_schedule_round:
# rotate
pshufd \$0xFF, %xmm0, %xmm0
palignr \$1, %xmm0, %xmm0
# fall through...
# low round: same as high round, but no rotation and no rcon.
_vpaes_schedule_low_round:
# smear xmm7
@@ -546,7 +545,7 @@ _vpaes_schedule_low_round:
pxor %xmm4, %xmm0 # 0 = sbox output
# add in smeared stuff
pxor %xmm7, %xmm0
pxor %xmm7, %xmm0
movdqa %xmm0, %xmm7
ret
.size _vpaes_schedule_round,.-_vpaes_schedule_round
+13 -1
View File
@@ -35,5 +35,17 @@ add_library(
tasn_new.c
tasn_typ.c
tasn_utl.c
time_support.c
x_bignum.c
x_long.c
)
add_executable(
asn1_test
asn1_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(asn1_test crypto)
add_dependencies(all_tests asn1_test)
+1
View File
@@ -61,6 +61,7 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/time_support.h>
#include "asn1_locl.h"
+10 -17
View File
@@ -63,6 +63,7 @@
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/time_support.h>
#include "asn1_locl.h"
@@ -114,7 +115,7 @@ int ASN1_TIME_check(ASN1_TIME *t)
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *ret = NULL;
ASN1_GENERALIZEDTIME *ret;
char *str;
int newlen;
@@ -123,21 +124,22 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
if (!out || !*out) {
if (!(ret = ASN1_GENERALIZEDTIME_new()))
goto err;
} else {
return NULL;
if (out)
*out = ret;
} else
ret = *out;
}
/* If already GeneralizedTime just copy across */
if (t->type == V_ASN1_GENERALIZEDTIME) {
if (!ASN1_STRING_set(ret, t->data, t->length))
goto err;
goto done;
return NULL;
return ret;
}
/* grow the string */
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
goto err;
return NULL;
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
newlen = t->length + 2 + 1;
str = (char *)ret->data;
@@ -149,18 +151,9 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
BUF_strlcat(str, (char *)t->data, newlen);
done:
if (out != NULL && *out == NULL)
*out = ret;
return ret;
err:
if (out == NULL || *out != ret)
ASN1_GENERALIZEDTIME_free(ret);
return NULL;
return ret;
}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
ASN1_TIME t;
+1
View File
@@ -61,6 +61,7 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/time_support.h>
#include "asn1_locl.h"
-35
View File
@@ -57,42 +57,7 @@
*
*/
#ifndef OPENSSL_HEADER_ASN1_ASN1_LOCL_H
#define OPENSSL_HEADER_ASN1_ASN1_LOCL_H
#include <time.h>
#include <openssl/asn1.h>
#if defined(__cplusplus)
extern "C" {
#endif
/* Wrapper functions for time functions. */
/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
* seconds. */
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
* outputs the difference as a number of days and seconds in |*out_days| and
* |*out_secs|. */
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
const struct tm *to);
/* Internal ASN1 structures and functions: not for application use */
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
#if defined(__cplusplus)
} /* extern C */
#endif
#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */
+29 -12
View File
@@ -14,13 +14,10 @@
#include <stdio.h>
#include <gtest/gtest.h>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "../test/test_util.h"
// kTag128 is an ASN.1 structure with a universal tag with number 128.
static const uint8_t kTag128[] = {
@@ -41,22 +38,42 @@ static const uint8_t kTagOverflow[] = {
0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
};
TEST(ASN1Test, LargeTags) {
static bool TestLargeTags() {
const uint8_t *p = kTag258;
bssl::UniquePtr<ASN1_TYPE> obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258)));
EXPECT_FALSE(obj) << "Parsed value with illegal tag" << obj->type;
if (obj) {
fprintf(stderr, "Parsed value with illegal tag (type = %d).\n", obj->type);
return false;
}
ERR_clear_error();
p = kTagOverflow;
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow)));
EXPECT_FALSE(obj) << "Parsed value with tag overflow" << obj->type;
if (obj) {
fprintf(stderr, "Parsed value with tag overflow (type = %d).\n", obj->type);
return false;
}
ERR_clear_error();
p = kTag128;
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128)));
ASSERT_TRUE(obj);
EXPECT_EQ(128, obj->type);
const uint8_t kZero = 0;
EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data,
obj->value.asn1_string->length));
if (!obj || obj->type != 128 || obj->value.asn1_string->length != 1 ||
obj->value.asn1_string->data[0] != 0) {
fprintf(stderr, "Failed to parse value with tag 128.\n");
ERR_print_errors_fp(stderr);
return false;
}
return true;
}
int main() {
CRYPTO_library_init();
if (!TestLargeTags()) {
return 1;
}
printf("PASS\n");
return 0;
}
-2
View File
@@ -180,7 +180,6 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
int ret = 0;
ASN1_VALUE **pchptr, *ptmpval;
int combine = aclass & ASN1_TFLG_COMBINE;
aclass &= ~ASN1_TFLG_COMBINE;
if (!pval)
return 0;
if (aux && aux->asn1_cb)
@@ -668,7 +667,6 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
}
len -= p - q;
if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) {
ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item));
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
+5 -7
View File
@@ -160,7 +160,7 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
}
asn1_set_choice_selector(pval, -1, it);
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr2;
goto auxerr;
break;
case ASN1_ITYPE_NDEF_SEQUENCE:
@@ -188,10 +188,10 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
pseqval = asn1_get_field_ptr(pval, tt);
if (!ASN1_template_new(pseqval, tt))
goto memerr2;
goto memerr;
}
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr2;
goto auxerr;
break;
}
#ifdef CRYPTO_MDEBUG
@@ -200,20 +200,18 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
#endif
return 1;
memerr2:
ASN1_item_ex_free(pval, it);
memerr:
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 0;
auxerr2:
ASN1_item_ex_free(pval, it);
auxerr:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
+153
View File
@@ -0,0 +1,153 @@
/* 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/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
/*
* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
* as a BIGNUM directly. Currently it ignores the sign which isn't a problem
* since all BIGNUMs used are non negative and anything that looks negative
* is normally due to an encoding error.
*/
#define BN_SENSITIVE 1
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it);
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
NULL, 0,
bn_new,
bn_free,
0,
bn_c2i,
bn_i2c,
NULL /* prim_print */ ,
};
ASN1_ITEM_start(BIGNUM)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
ASN1_ITEM_end(BIGNUM)
ASN1_ITEM_start(CBIGNUM)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
ASN1_ITEM_end(CBIGNUM)
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*pval = (ASN1_VALUE *)BN_new();
if (*pval)
return 1;
else
return 0;
}
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if (!*pval)
return;
if (it->size & BN_SENSITIVE)
BN_clear_free((BIGNUM *)*pval);
else
BN_free((BIGNUM *)*pval);
*pval = NULL;
}
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it)
{
BIGNUM *bn;
int pad;
if (!*pval)
return -1;
bn = (BIGNUM *)*pval;
/* If MSB set in an octet we need a padding byte */
if (BN_num_bits(bn) & 0x7)
pad = 0;
else
pad = 1;
if (cont) {
if (pad)
*cont++ = 0;
BN_bn2bin(bn, cont);
}
return pad + BN_num_bytes(bn);
}
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it)
{
BIGNUM *bn;
if (!*pval) {
if (!bn_new(pval, it)) {
return 0;
}
}
bn = (BIGNUM *)*pval;
if (!BN_bin2bn(cont, len, bn)) {
bn_free(pval, it);
return 0;
}
return 1;
}
+200
View File
@@ -0,0 +1,200 @@
/* 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/asn1.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
/*
* Custom primitive type for long handling. This converts between an
* ASN1_INTEGER and a long directly.
*/
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it);
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx);
static const ASN1_PRIMITIVE_FUNCS long_pf = {
NULL, 0,
long_new,
long_free,
long_free, /* Clear should set to initial value */
long_c2i,
long_i2c,
long_print
};
ASN1_ITEM_start(LONG)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
ASN1_ITEM_end(LONG)
ASN1_ITEM_start(ZLONG)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
ASN1_ITEM_end(ZLONG)
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*(long *)pval = it->size;
return 1;
}
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*(long *)pval = it->size;
}
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it)
{
long ltmp;
unsigned long utmp;
int clen, pad, i;
/* this exists to bypass broken gcc optimization */
char *cp = (char *)pval;
/* use memcpy, because we may not be long aligned */
OPENSSL_memcpy(&ltmp, cp, sizeof(long));
if (ltmp == it->size)
return -1;
/*
* Convert the long to positive: we subtract one if negative so we can
* cleanly handle the padding if only the MSB of the leading octet is
* set.
*/
if (ltmp < 0)
utmp = -ltmp - 1;
else
utmp = ltmp;
clen = BN_num_bits_word(utmp);
/* If MSB of leading octet set we need to pad */
if (!(clen & 0x7))
pad = 1;
else
pad = 0;
/* Convert number of bits to number of octets */
clen = (clen + 7) >> 3;
if (cont) {
if (pad)
*cont++ = (ltmp < 0) ? 0xff : 0;
for (i = clen - 1; i >= 0; i--) {
cont[i] = (unsigned char)(utmp & 0xff);
if (ltmp < 0)
cont[i] ^= 0xff;
utmp >>= 8;
}
}
return clen + pad;
}
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it)
{
int neg, i;
long ltmp;
unsigned long utmp = 0;
char *cp = (char *)pval;
if (len > (int)sizeof(long)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
/* Is it negative? */
if (len && (cont[0] & 0x80))
neg = 1;
else
neg = 0;
utmp = 0;
for (i = 0; i < len; i++) {
utmp <<= 8;
if (neg)
utmp |= cont[i] ^ 0xff;
else
utmp |= cont[i];
}
ltmp = (long)utmp;
if (neg) {
ltmp++;
ltmp = -ltmp;
}
if (ltmp == it->size) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
OPENSSL_memcpy(cp, &ltmp, sizeof(long));
return 1;
}
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
return BIO_printf(out, "%ld\n", *(long *)pval);
}
+15
View File
@@ -7,6 +7,7 @@ add_library(
bio.c
bio_mem.c
buffer.c
connect.c
fd.c
file.c
@@ -16,3 +17,17 @@ add_library(
socket.c
socket_helper.c
)
add_executable(
bio_test
bio_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(bio_test crypto)
if (WIN32)
target_link_libraries(bio_test ws2_32)
endif()
add_dependencies(all_tests bio_test)
-2
View File
@@ -608,5 +608,3 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
void BIO_set_retry_special(BIO *bio) {
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL;
}
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { return 0; }
+6 -6
View File
@@ -189,6 +189,10 @@ err:
return ret;
}
static int mem_puts(BIO *bp, const char *str) {
return mem_write(bp, str, strlen(str));
}
static int mem_gets(BIO *bio, char *buf, int size) {
int i, j;
char *p;
@@ -291,12 +295,8 @@ static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
}
static const BIO_METHOD mem_method = {
BIO_TYPE_MEM, "memory buffer",
mem_write, mem_read,
NULL /* puts */, mem_gets,
mem_ctrl, mem_new,
mem_free, NULL /* callback_ctrl */,
};
BIO_TYPE_MEM, "memory buffer", mem_write, mem_read, mem_puts,
mem_gets, mem_ctrl, mem_new, mem_free, NULL, };
const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
+326 -215
View File
@@ -16,18 +16,7 @@
#define _POSIX_C_SOURCE 201410L
#endif
#include <algorithm>
#include <string>
#include <gtest/gtest.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
#include "../test/test_util.h"
#include <openssl/base.h>
#if !defined(OPENSSL_WINDOWS)
#include <arpa/inet.h>
@@ -44,15 +33,27 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <algorithm>
#include "../internal.h"
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) { return close(sock); }
static std::string LastSocketError() { return strerror(errno); }
static int closesocket(int sock) {
return close(sock);
}
static void PrintSocketError(const char *func) {
perror(func);
}
#else
static std::string LastSocketError() {
char buf[DECIMAL_SIZE(int) + 1];
BIO_snprintf(buf, sizeof(buf), "%d", WSAGetLastError());
return buf;
static void PrintSocketError(const char *func) {
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
}
#endif
@@ -67,246 +68,356 @@ class ScopedSocket {
const int sock_;
};
TEST(BIOTest, SocketConnect) {
static bool TestSocketConnect() {
static const char kTestMessage[] = "test";
// Set up a listening socket on localhost.
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
ASSERT_NE(-1, listening_sock) << LastSocketError();
if (listening_sock == -1) {
PrintSocketError("socket");
return false;
}
ScopedSocket listening_sock_closer(listening_sock);
struct sockaddr_in sin;
OPENSSL_memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr))
<< LastSocketError();
ASSERT_EQ(0, bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)))
<< LastSocketError();
ASSERT_EQ(0, listen(listening_sock, 1)) << LastSocketError();
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
PrintSocketError("inet_pton");
return false;
}
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
PrintSocketError("bind");
return false;
}
if (listen(listening_sock, 1)) {
PrintSocketError("listen");
return false;
}
socklen_t sockaddr_len = sizeof(sin);
ASSERT_EQ(0,
getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len))
<< LastSocketError();
// The Android NDK, contrary to POSIX, makes |socklen_t| signed.
ASSERT_EQ(sizeof(sin), static_cast<size_t>(sockaddr_len));
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
sockaddr_len != sizeof(sin)) {
PrintSocketError("getsockname");
return false;
}
// Connect to it with a connect BIO.
char hostname[80];
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
ntohs(sin.sin_port));
bssl::UniquePtr<BIO> bio(BIO_new_connect(hostname));
ASSERT_TRUE(bio);
if (!bio) {
fprintf(stderr, "BIO_new_connect failed.\n");
return false;
}
// Write a test message to the BIO.
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)));
if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) !=
sizeof(kTestMessage)) {
fprintf(stderr, "BIO_write failed.\n");
ERR_print_errors_fp(stderr);
return false;
}
// Accept the socket.
int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
ASSERT_NE(-1, sock) << LastSocketError();
if (sock == -1) {
PrintSocketError("accept");
return false;
}
ScopedSocket sock_closer(sock);
// Check the same message is read back out.
char buf[sizeof(kTestMessage)];
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
recv(sock, buf, sizeof(buf), 0))
<< LastSocketError();
EXPECT_EQ(Bytes(kTestMessage, sizeof(kTestMessage)), Bytes(buf, sizeof(buf)));
char buf[5];
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
PrintSocketError("read");
return false;
}
if (OPENSSL_memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
return false;
}
return true;
}
TEST(BIOTest, Printf) {
static bool TestPrintf() {
// Test a short output, a very long one, and various sizes around
// 256 (the size of the buffer) to ensure edge cases are correct.
static const size_t kLengths[] = {5, 250, 251, 252, 253, 254, 1023};
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
ASSERT_TRUE(bio);
if (!bio) {
fprintf(stderr, "BIO_new failed\n");
return false;
}
for (size_t length : kLengths) {
SCOPED_TRACE(length);
std::string in(length, 'a');
int ret = BIO_printf(bio.get(), "test %s", in.c_str());
ASSERT_GE(ret, 0);
EXPECT_EQ(5 + length, static_cast<size_t>(ret));
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kLengths); i++) {
char string[1024];
if (kLengths[i] >= sizeof(string)) {
fprintf(stderr, "Bad test string length\n");
return false;
}
OPENSSL_memset(string, 'a', sizeof(string));
string[kLengths[i]] = '\0';
int ret = BIO_printf(bio.get(), "test %s", string);
if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) {
fprintf(stderr, "BIO_printf failed: %d\n", ret);
return false;
}
const uint8_t *contents;
size_t len;
ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
EXPECT_EQ("test " + in,
std::string(reinterpret_cast<const char *>(contents), len));
if (!BIO_mem_contents(bio.get(), &contents, &len)) {
fprintf(stderr, "BIO_mem_contents failed\n");
return false;
}
if (len != 5 + kLengths[i] ||
strncmp((const char *)contents, "test ", 5) != 0 ||
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
return false;
}
ASSERT_TRUE(BIO_reset(bio.get()));
if (!BIO_reset(bio.get())) {
fprintf(stderr, "BIO_reset failed\n");
return false;
}
}
return true;
}
static const size_t kLargeASN1PayloadLen = 8000;
struct ASN1TestParam {
bool should_succeed;
std::vector<uint8_t> input;
// suffix_len is the number of zeros to append to |input|.
size_t suffix_len;
// expected_len, if |should_succeed| is true, is the expected length of the
// ASN.1 element.
size_t expected_len;
size_t max_len;
} kASN1TestParams[] = {
{true, {0x30, 2, 1, 2, 0, 0}, 0, 4, 100},
{false /* truncated */, {0x30, 3, 1, 2}, 0, 0, 100},
{false /* should be short len */, {0x30, 0x81, 1, 1}, 0, 0, 100},
{false /* zero padded */, {0x30, 0x82, 0, 1, 1}, 0, 0, 100},
// Test a large payload.
{true,
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
kLargeASN1PayloadLen,
4 + kLargeASN1PayloadLen,
kLargeASN1PayloadLen * 2},
{false /* max_len too short */,
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
kLargeASN1PayloadLen,
4 + kLargeASN1PayloadLen,
3 + kLargeASN1PayloadLen},
// Test an indefinite-length input.
{true,
{0x30, 0x80},
kLargeASN1PayloadLen + 2,
2 + kLargeASN1PayloadLen + 2,
kLargeASN1PayloadLen * 2},
{false /* max_len too short */,
{0x30, 0x80},
kLargeASN1PayloadLen + 2,
2 + kLargeASN1PayloadLen + 2,
2 + kLargeASN1PayloadLen + 1},
};
class BIOASN1Test : public testing::TestWithParam<ASN1TestParam> {};
TEST_P(BIOASN1Test, ReadASN1) {
const ASN1TestParam& param = GetParam();
std::vector<uint8_t> input = param.input;
input.resize(input.size() + param.suffix_len, 0);
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(input.data(), input.size()));
ASSERT_TRUE(bio);
static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
size_t expected_len, size_t max_len) {
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(data, data_len));
uint8_t *out;
size_t out_len;
int ok = BIO_read_asn1(bio.get(), &out, &out_len, param.max_len);
int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len);
if (!ok) {
out = nullptr;
}
bssl::UniquePtr<uint8_t> out_storage(out);
ASSERT_EQ(param.should_succeed, (ok == 1));
if (param.should_succeed) {
EXPECT_EQ(Bytes(input.data(), param.expected_len), Bytes(out, out_len));
}
}
INSTANTIATE_TEST_CASE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams));
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
class BIOPairTest : public testing::TestWithParam<bool> {};
TEST_P(BIOPairTest, TestPair) {
BIO *bio1, *bio2;
ASSERT_TRUE(BIO_new_bio_pair(&bio1, 10, &bio2, 10));
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
if (GetParam()) {
std::swap(bio1, bio2);
if (should_succeed != (ok == 1)) {
return false;
}
// Check initial states.
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
if (should_succeed && (out_len != expected_len ||
OPENSSL_memcmp(data, out, expected_len) != 0)) {
return false;
}
// Data written in one end may be read out the other.
uint8_t buf[20];
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
// Attempting to write more than 10 bytes will write partially.
EXPECT_EQ(10, BIO_write(bio1, "1234567890___", 13));
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(-1, BIO_write(bio1, "z", 1));
EXPECT_TRUE(BIO_should_write(bio1));
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("1234567890"), Bytes(buf, 10));
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
// Unsuccessful reads update the read request.
EXPECT_EQ(-1, BIO_read(bio2, buf, 5));
EXPECT_TRUE(BIO_should_read(bio2));
EXPECT_EQ(5u, BIO_ctrl_get_read_request(bio1));
// The read request is clamped to the size of the buffer.
EXPECT_EQ(-1, BIO_read(bio2, buf, 20));
EXPECT_TRUE(BIO_should_read(bio2));
EXPECT_EQ(10u, BIO_ctrl_get_read_request(bio1));
// Data may be written and read in chunks.
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(5, BIO_write(bio1, "67890___", 8));
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
EXPECT_EQ(Bytes("123"), Bytes(buf, 3));
EXPECT_EQ(3u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(7, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("4567890"), Bytes(buf, 7));
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
// Successful reads reset the read request.
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
// Test writes and reads starting in the middle of the ring buffer and
// wrapping to front.
EXPECT_EQ(8, BIO_write(bio1, "abcdefgh", 8));
EXPECT_EQ(2u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
EXPECT_EQ(Bytes("abc"), Bytes(buf, 3));
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(5, BIO_write(bio1, "ijklm___", 8));
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("defghijklm"), Bytes(buf, 10));
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
// Data may flow from both ends in parallel.
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
EXPECT_EQ(5, BIO_write(bio2, "67890", 5));
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
EXPECT_EQ(Bytes("67890"), Bytes(buf, 5));
// Closing the write end causes an EOF on the read half, after draining.
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
EXPECT_TRUE(BIO_shutdown_wr(bio1));
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
EXPECT_EQ(0, BIO_read(bio2, buf, sizeof(buf)));
// A closed write end may not be written to.
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
EXPECT_EQ(-1, BIO_write(bio1, "_____", 5));
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_LIB_BIO, ERR_GET_LIB(err));
EXPECT_EQ(BIO_R_BROKEN_PIPE, ERR_GET_REASON(err));
// The other end is still functional.
EXPECT_EQ(5, BIO_write(bio2, "12345", 5));
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
return true;
}
INSTANTIATE_TEST_CASE_P(, BIOPairTest, testing::Values(false, true));
static bool TestASN1() {
static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0};
static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */
static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */
static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */
if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) ||
!ReadASN1(false, kData2, sizeof(kData2), 0, 100) ||
!ReadASN1(false, kData3, sizeof(kData3), 0, 100) ||
!ReadASN1(false, kData4, sizeof(kData4), 0, 100)) {
return false;
}
static const size_t kLargePayloadLen = 8000;
static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
kLargePayloadLen & 0xff};
bssl::UniquePtr<uint8_t> large(reinterpret_cast<uint8_t *>(
OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
if (!large) {
return false;
}
OPENSSL_memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen);
OPENSSL_memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix));
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
sizeof(kLargePrefix) + kLargePayloadLen,
kLargePayloadLen * 2)) {
fprintf(stderr, "Large payload test failed.\n");
return false;
}
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
sizeof(kLargePrefix) + kLargePayloadLen,
kLargePayloadLen - 1)) {
fprintf(stderr, "max_len test failed.\n");
return false;
}
static const uint8_t kIndefPrefix[] = {0x30, 0x80};
OPENSSL_memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix));
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
sizeof(kLargePrefix) + kLargePayloadLen,
kLargePayloadLen*2)) {
fprintf(stderr, "indefinite length test failed.\n");
return false;
}
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
sizeof(kLargePrefix) + kLargePayloadLen,
kLargePayloadLen-1)) {
fprintf(stderr, "indefinite length, max_len test failed.\n");
return false;
}
return true;
}
static bool TestPair() {
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
for (int i = 0; i < 2; i++) {
BIO *bio1, *bio2;
if (!BIO_new_bio_pair(&bio1, 10, &bio2, 10)) {
return false;
}
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
if (i == 1) {
std::swap(bio1, bio2);
}
// Check initial states.
if (BIO_ctrl_get_write_guarantee(bio1) != 10 ||
BIO_ctrl_get_read_request(bio1) != 0) {
return false;
}
// Data written in one end may be read out the other.
char buf[20];
if (BIO_write(bio1, "12345", 5) != 5 ||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
return false;
}
// Attempting to write more than 10 bytes will write partially.
if (BIO_write(bio1, "1234567890___", 13) != 10 ||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
BIO_write(bio1, "z", 1) != -1 ||
!BIO_should_write(bio1) ||
BIO_read(bio2, buf, sizeof(buf)) != 10 ||
OPENSSL_memcmp(buf, "1234567890", 10) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
return false;
}
// Unsuccessful reads update the read request.
if (BIO_read(bio2, buf, 5) != -1 ||
!BIO_should_read(bio2) ||
BIO_ctrl_get_read_request(bio1) != 5) {
return false;
}
// The read request is clamped to the size of the buffer.
if (BIO_read(bio2, buf, 20) != -1 ||
!BIO_should_read(bio2) ||
BIO_ctrl_get_read_request(bio1) != 10) {
return false;
}
// Data may be written and read in chunks.
if (BIO_write(bio1, "12345", 5) != 5 ||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
BIO_write(bio1, "67890___", 8) != 5 ||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
BIO_read(bio2, buf, 3) != 3 ||
OPENSSL_memcmp(buf, "123", 3) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 3 ||
BIO_read(bio2, buf, sizeof(buf)) != 7 ||
OPENSSL_memcmp(buf, "4567890", 7) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
return false;
}
// Successful reads reset the read request.
if (BIO_ctrl_get_read_request(bio1) != 0) {
return false;
}
// Test writes and reads starting in the middle of the ring buffer and
// wrapping to front.
if (BIO_write(bio1, "abcdefgh", 8) != 8 ||
BIO_ctrl_get_write_guarantee(bio1) != 2 ||
BIO_read(bio2, buf, 3) != 3 ||
OPENSSL_memcmp(buf, "abc", 3) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
BIO_write(bio1, "ijklm___", 8) != 5 ||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
BIO_read(bio2, buf, sizeof(buf)) != 10 ||
OPENSSL_memcmp(buf, "defghijklm", 10) != 0 ||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
return false;
}
// Data may flow from both ends in parallel.
if (BIO_write(bio1, "12345", 5) != 5 ||
BIO_write(bio2, "67890", 5) != 5 ||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
BIO_read(bio1, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "67890", 5) != 0) {
return false;
}
// Closing the write end causes an EOF on the read half, after draining.
if (BIO_write(bio1, "12345", 5) != 5 ||
!BIO_shutdown_wr(bio1) ||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
BIO_read(bio2, buf, sizeof(buf)) != 0) {
return false;
}
// A closed write end may not be written to.
if (BIO_ctrl_get_write_guarantee(bio1) != 0 ||
BIO_write(bio1, "_____", 5) != -1) {
return false;
}
uint32_t err = ERR_get_error();
if (ERR_GET_LIB(err) != ERR_LIB_BIO ||
ERR_GET_REASON(err) != BIO_R_BROKEN_PIPE) {
return false;
}
// The other end is still functional.
if (BIO_write(bio2, "12345", 5) != 5 ||
BIO_read(bio1, buf, sizeof(buf)) != 5 ||
OPENSSL_memcmp(buf, "12345", 5) != 0) {
return false;
}
}
return true;
}
int main() {
CRYPTO_library_init();
#if defined(OPENSSL_WINDOWS)
// Initialize Winsock.
WORD wsa_version = MAKEWORD(2, 2);
WSADATA wsa_data;
int wsa_err = WSAStartup(wsa_version, &wsa_data);
if (wsa_err != 0) {
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
return 1;
}
if (wsa_data.wVersion != wsa_version) {
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
return 1;
}
#endif
if (!TestSocketConnect() ||
!TestPrintf() ||
!TestASN1() ||
!TestPair()) {
return 1;
}
printf("PASS\n");
return 0;
}
+486
View File
@@ -0,0 +1,486 @@
/* 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/bio.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
#define DEFAULT_BUFFER_SIZE 4096
typedef struct bio_f_buffer_ctx_struct {
/* Buffers are setup like this:
*
* <---------------------- size ----------------------->
* +---------------------------------------------------+
* | consumed | remaining | free space |
* +---------------------------------------------------+
* <-- off --><------- len ------->
*/
int ibuf_size; /* how big is the input buffer */
int obuf_size; /* how big is the output buffer */
char *ibuf; /* the char array */
int ibuf_len; /* how many bytes are in it */
int ibuf_off; /* write/read offset */
char *obuf; /* the char array */
int obuf_len; /* how many bytes are in it */
int obuf_off; /* write/read offset */
} BIO_F_BUFFER_CTX;
static int buffer_new(BIO *bio) {
BIO_F_BUFFER_CTX *ctx;
ctx = OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX));
if (ctx == NULL) {
return 0;
}
OPENSSL_memset(ctx, 0, sizeof(BIO_F_BUFFER_CTX));
ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
if (ctx->ibuf == NULL) {
goto err1;
}
ctx->obuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
if (ctx->obuf == NULL) {
goto err2;
}
ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
ctx->obuf_size = DEFAULT_BUFFER_SIZE;
bio->init = 1;
bio->ptr = (char *)ctx;
return 1;
err2:
OPENSSL_free(ctx->ibuf);
err1:
OPENSSL_free(ctx);
return 0;
}
static int buffer_free(BIO *bio) {
BIO_F_BUFFER_CTX *ctx;
if (bio == NULL || bio->ptr == NULL) {
return 0;
}
ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
OPENSSL_free(ctx->ibuf);
OPENSSL_free(ctx->obuf);
OPENSSL_free(bio->ptr);
bio->ptr = NULL;
bio->init = 0;
bio->flags = 0;
return 1;
}
static int buffer_read(BIO *bio, char *out, int outl) {
int i, num = 0;
BIO_F_BUFFER_CTX *ctx;
ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
if (ctx == NULL || bio->next_bio == NULL) {
return 0;
}
num = 0;
BIO_clear_retry_flags(bio);
for (;;) {
i = ctx->ibuf_len;
/* If there is stuff left over, grab it */
if (i != 0) {
if (i > outl) {
i = outl;
}
OPENSSL_memcpy(out, &ctx->ibuf[ctx->ibuf_off], i);
ctx->ibuf_off += i;
ctx->ibuf_len -= i;
num += i;
if (outl == i) {
return num;
}
outl -= i;
out += i;
}
/* We may have done a partial read. Try to do more. We have nothing in the
* buffer. If we get an error and have read some data, just return it and
* let them retry to get the error again. Copy direct to parent address
* space */
if (outl > ctx->ibuf_size) {
for (;;) {
i = BIO_read(bio->next_bio, out, outl);
if (i <= 0) {
BIO_copy_next_retry(bio);
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
num += i;
if (outl == i) {
return num;
}
out += i;
outl -= i;
}
}
/* else */
/* we are going to be doing some buffering */
i = BIO_read(bio->next_bio, ctx->ibuf, ctx->ibuf_size);
if (i <= 0) {
BIO_copy_next_retry(bio);
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
ctx->ibuf_off = 0;
ctx->ibuf_len = i;
}
}
static int buffer_write(BIO *b, const char *in, int inl) {
int i, num = 0;
BIO_F_BUFFER_CTX *ctx;
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
if (ctx == NULL || b->next_bio == NULL) {
return 0;
}
BIO_clear_retry_flags(b);
for (;;) {
i = ctx->obuf_size - (ctx->obuf_off + ctx->obuf_len);
/* add to buffer and return */
if (i >= inl) {
OPENSSL_memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, inl);
ctx->obuf_len += inl;
return num + inl;
}
/* else */
/* stuff already in buffer, so add to it first, then flush */
if (ctx->obuf_len != 0) {
if (i > 0) {
OPENSSL_memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, i);
in += i;
inl -= i;
num += i;
ctx->obuf_len += i;
}
/* we now have a full buffer needing flushing */
for (;;) {
i = BIO_write(b->next_bio, &ctx->obuf[ctx->obuf_off], ctx->obuf_len);
if (i <= 0) {
BIO_copy_next_retry(b);
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
ctx->obuf_off += i;
ctx->obuf_len -= i;
if (ctx->obuf_len == 0) {
break;
}
}
}
/* we only get here if the buffer has been flushed and we
* still have stuff to write */
ctx->obuf_off = 0;
/* we now have inl bytes to write */
while (inl >= ctx->obuf_size) {
i = BIO_write(b->next_bio, in, inl);
if (i <= 0) {
BIO_copy_next_retry(b);
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
num += i;
in += i;
inl -= i;
if (inl == 0) {
return num;
}
}
/* copy the rest into the buffer since we have only a small
* amount left */
}
}
static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
BIO_F_BUFFER_CTX *ctx;
long ret = 1;
char *p1, *p2;
int r, *ip;
int ibs, obs;
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ctx->ibuf_off = 0;
ctx->ibuf_len = 0;
ctx->obuf_off = 0;
ctx->obuf_len = 0;
if (b->next_bio == NULL) {
return 0;
}
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_INFO:
ret = ctx->obuf_len;
break;
case BIO_CTRL_WPENDING:
ret = (long)ctx->obuf_len;
break;
case BIO_CTRL_PENDING:
ret = (long)ctx->ibuf_len;
break;
case BIO_C_SET_BUFF_SIZE:
ip = (int *)ptr;
if (*ip == 0) {
ibs = (int)num;
obs = ctx->obuf_size;
} else /* if (*ip == 1) */ {
ibs = ctx->ibuf_size;
obs = (int)num;
}
p1 = ctx->ibuf;
p2 = ctx->obuf;
if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
p1 = OPENSSL_malloc(ibs);
if (p1 == NULL) {
goto malloc_error;
}
}
if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
p2 = OPENSSL_malloc(obs);
if (p2 == NULL) {
if (p1 != ctx->ibuf) {
OPENSSL_free(p1);
}
goto malloc_error;
}
}
if (ctx->ibuf != p1) {
OPENSSL_free(ctx->ibuf);
ctx->ibuf = p1;
ctx->ibuf_size = ibs;
}
ctx->ibuf_off = 0;
ctx->ibuf_len = 0;
if (ctx->obuf != p2) {
OPENSSL_free(ctx->obuf);
ctx->obuf = p2;
ctx->obuf_size = obs;
}
ctx->obuf_off = 0;
ctx->obuf_len = 0;
break;
case BIO_CTRL_FLUSH:
if (b->next_bio == NULL) {
return 0;
}
while (ctx->obuf_len > 0) {
BIO_clear_retry_flags(b);
r = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
ctx->obuf_len);
BIO_copy_next_retry(b);
if (r <= 0) {
return r;
}
ctx->obuf_off += r;
ctx->obuf_len -= r;
}
ctx->obuf_len = 0;
ctx->obuf_off = 0;
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
break;
default:
if (b->next_bio == NULL) {
return 0;
}
BIO_clear_retry_flags(b);
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
BIO_copy_next_retry(b);
break;
}
return ret;
malloc_error:
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
static long buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) {
long ret = 1;
if (b->next_bio == NULL) {
return 0;
}
switch (cmd) {
default:
ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
break;
}
return ret;
}
static int buffer_gets(BIO *b, char *buf, int size) {
BIO_F_BUFFER_CTX *ctx;
int num = 0, i, flag;
char *p;
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
if (buf == NULL || size <= 0) {
return 0;
}
size--; /* reserve space for a '\0' */
BIO_clear_retry_flags(b);
for (;;) {
if (ctx->ibuf_len > 0) {
p = &ctx->ibuf[ctx->ibuf_off];
flag = 0;
for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) {
*(buf++) = p[i];
if (p[i] == '\n') {
flag = 1;
i++;
break;
}
}
num += i;
size -= i;
ctx->ibuf_len -= i;
ctx->ibuf_off += i;
if (flag || size == 0) {
*buf = '\0';
return num;
}
} else /* read another chunk */
{
i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
if (i <= 0) {
BIO_copy_next_retry(b);
*buf = '\0';
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
ctx->ibuf_len = i;
ctx->ibuf_off = 0;
}
}
}
static int buffer_puts(BIO *b, const char *str) {
return buffer_write(b, str, strlen(str));
}
static const BIO_METHOD methods_buffer = {
BIO_TYPE_BUFFER, "buffer", buffer_write, buffer_read,
buffer_puts, buffer_gets, buffer_ctrl, buffer_new,
buffer_free, buffer_callback_ctrl,
};
const BIO_METHOD *BIO_f_buffer(void) { return &methods_buffer; }
int BIO_set_read_buffer_size(BIO *bio, int buffer_size) {
return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 0);
}
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) {
return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 1);
}
+17 -5
View File
@@ -468,6 +468,14 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
break;
case BIO_CTRL_FLUSH:
break;
case BIO_CTRL_SET_CALLBACK: {
#if 0 /* FIXME: Should this be used? -- Richard Levitte */
OPENSSL_PUT_ERROR(BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
ret = -1;
#else
ret = 0;
#endif
} break;
case BIO_CTRL_GET_CALLBACK: {
int (**fptr)(const BIO *bio, int state, int xret);
fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
@@ -477,7 +485,7 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
ret = 0;
break;
}
return ret;
return (ret);
}
static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
@@ -487,9 +495,9 @@ static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
data = (BIO_CONNECT *)bio->ptr;
switch (cmd) {
case BIO_CTRL_SET_CALLBACK:
case BIO_CTRL_SET_CALLBACK: {
data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
break;
} break;
default:
ret = 0;
break;
@@ -497,6 +505,10 @@ static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
return ret;
}
static int conn_puts(BIO *bp, const char *str) {
return conn_write(bp, str, strlen(str));
}
BIO *BIO_new_connect(const char *hostname) {
BIO *ret;
@@ -512,8 +524,8 @@ BIO *BIO_new_connect(const char *hostname) {
}
static const BIO_METHOD methods_connectp = {
BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
NULL /* puts */, NULL /* gets */, conn_ctrl, conn_new,
BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
conn_puts, NULL /* connect_gets, */, conn_ctrl, conn_new,
conn_free, conn_callback_ctrl,
};
+6 -3
View File
@@ -241,6 +241,10 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
return ret;
}
static int fd_puts(BIO *bp, const char *str) {
return fd_write(bp, str, strlen(str));
}
static int fd_gets(BIO *bp, char *buf, int size) {
char *ptr = buf;
char *end = buf + size - 1;
@@ -259,9 +263,8 @@ static int fd_gets(BIO *bp, char *buf, int size) {
}
static const BIO_METHOD methods_fdp = {
BIO_TYPE_FD, "file descriptor", fd_write, fd_read, NULL /* puts */,
fd_gets, fd_ctrl, fd_new, fd_free, NULL /* callback_ctrl */,
};
BIO_TYPE_FD, "file descriptor", fd_write, fd_read, fd_puts,
fd_gets, fd_ctrl, fd_new, fd_free, NULL, };
const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; }
+6 -6
View File
@@ -273,13 +273,13 @@ err:
return ret;
}
static int file_puts(BIO *bp, const char *str) {
return file_write(bp, str, strlen(str));
}
static const BIO_METHOD methods_filep = {
BIO_TYPE_FILE, "FILE pointer",
file_write, file_read,
NULL /* puts */, file_gets,
file_ctrl, file_new,
file_free, NULL /* callback_ctrl */,
};
BIO_TYPE_FILE, "FILE pointer", file_write, file_read, file_puts,
file_gets, file_ctrl, file_new, file_free, NULL, };
const BIO_METHOD *BIO_s_file(void) { return &methods_filep; }
+6 -2
View File
@@ -450,10 +450,14 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
return ret;
}
static int bio_puts(BIO *bio, const char *str) {
return bio_write(bio, str, strlen(str));
}
static const BIO_METHOD methods_biop = {
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, NULL /* puts */,
NULL /* gets */, bio_ctrl, bio_new, bio_free, NULL /* callback_ctrl */
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read,
bio_puts, NULL /* no bio_gets */, bio_ctrl, bio_new,
bio_free, NULL /* no bio_callback_ctrl */
};
static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
+6 -5
View File
@@ -142,6 +142,10 @@ static int sock_write(BIO *b, const char *in, int inl) {
return ret;
}
static int sock_puts(BIO *bp, const char *str) {
return sock_write(bp, str, strlen(str));
}
static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
long ret = 1;
int *ip;
@@ -181,11 +185,8 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
}
static const BIO_METHOD methods_sockp = {
BIO_TYPE_SOCKET, "socket",
sock_write, sock_read,
NULL /* puts */, NULL /* gets, */,
sock_ctrl, sock_new,
sock_free, NULL /* callback_ctrl */,
BIO_TYPE_SOCKET, "socket", sock_write, sock_read, sock_puts,
NULL /* gets, */, sock_ctrl, sock_new, sock_free, NULL,
};
const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
+1 -1
View File
@@ -16,7 +16,7 @@
# [depending on key length, less for longer keys] on ARM920T, and
# +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code
# base and compiler generated code with in-lined umull and even umlal
# instructions. The latter means that this code didn't really have an
# instructions. The latter means that this code didn't really have an
# "advantage" of utilizing some "secret" instruction.
#
# The code is interoperable with Thumb ISA and is rather compact, less
+12 -12
View File
@@ -47,7 +47,7 @@ sub bn_mul_add_words
&movd("mm0",&wparam(3)); # mm0 = w
&pxor("mm1","mm1"); # mm1 = carry_in
&jmp(&label("maw_sse2_entry"));
&set_label("maw_sse2_unrolled",16);
&movd("mm3",&DWP(0,$r,"",0)); # mm3 = r[0]
&paddq("mm1","mm3"); # mm1 = carry_in + r[0]
@@ -668,20 +668,20 @@ sub bn_sub_part_words
&adc($c,0);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
}
&comment("");
&add($b,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_neg_loop"));
&set_label("pw_neg_finish",0);
&mov($tmp2,&wparam(4)); # get dl
&mov($num,0);
&sub($num,$tmp2);
&and($num,7);
&jz(&label("pw_end"));
for ($i=0; $i<7; $i++)
{
&comment("dl<0 Tail Round $i");
@@ -698,9 +698,9 @@ sub bn_sub_part_words
}
&jmp(&label("pw_end"));
&set_label("pw_pos",0);
&and($num,0xfffffff8); # num / 8
&jz(&label("pw_pos_finish"));
@@ -715,18 +715,18 @@ sub bn_sub_part_words
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jnc(&label("pw_nc".$i));
}
&comment("");
&add($a,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_pos_loop"));
&set_label("pw_pos_finish",0);
&mov($num,&wparam(4)); # get dl
&and($num,7);
&jz(&label("pw_end"));
for ($i=0; $i<7; $i++)
{
&comment("dl>0 Tail Round $i");
@@ -747,17 +747,17 @@ sub bn_sub_part_words
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&set_label("pw_nc".$i,0);
}
&comment("");
&add($a,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_nc_loop"));
&mov($num,&wparam(4)); # get dl
&and($num,7);
&jz(&label("pw_nc_end"));
for ($i=0; $i<7; $i++)
{
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+6 -6
View File
@@ -41,7 +41,7 @@ sub mul_add_c
&mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1; # laod next b
###
&adc($c2,0);
# is pos > 1, it means it is the last loop
# is pos > 1, it means it is the last loop
&mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0; # save r[];
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # laod next a
}
@@ -70,7 +70,7 @@ sub sqr_add_c
&mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb);
###
&adc($c2,0);
# is pos > 1, it means it is the last loop
# is pos > 1, it means it is the last loop
&mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[];
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b
}
@@ -121,7 +121,7 @@ sub bn_mul_comba
$c2="ebp";
$a="esi";
$b="edi";
$as=0;
$ae=0;
$bs=0;
@@ -136,9 +136,9 @@ sub bn_mul_comba
&push("ebx");
&xor($c0,$c0);
&mov("eax",&DWP(0,$a,"",0)); # load the first word
&mov("eax",&DWP(0,$a,"",0)); # load the first word
&xor($c1,$c1);
&mov("edx",&DWP(0,$b,"",0)); # load the first second
&mov("edx",&DWP(0,$b,"",0)); # load the first second
for ($i=0; $i<$tot; $i++)
{
@@ -146,7 +146,7 @@ sub bn_mul_comba
$bi=$bs;
$end=$be+1;
&comment("################## Calculate word $i");
&comment("################## Calculate word $i");
for ($j=$bs; $j<$end; $j++)
{
+12 -59
View File
@@ -84,8 +84,8 @@ die "can't locate x86_64-xlate.pl";
# output, so this isn't useful anyway.
#
# TODO(davidben): Enable these after testing. $avx goes up to 2 and $addx to 1.
$avx = 2;
$addx = 1;
$avx = 0;
$addx = 0;
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
*STDOUT = *OUT;
@@ -145,21 +145,13 @@ $code.=<<___;
.type rsaz_1024_sqr_avx2,\@function,5
.align 64
rsaz_1024_sqr_avx2: # 702 cycles, 14% faster than rsaz_1024_mul_avx2
.cfi_startproc
lea (%rsp), %rax
.cfi_def_cfa_register %rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
vzeroupper
___
$code.=<<___ if ($win64);
@@ -178,7 +170,6 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov %rax,%rbp
.cfi_def_cfa_register %rbp
mov %rdx, $np # reassigned argument
sub \$$FrameSize, %rsp
mov $np, $tmp
@@ -368,7 +359,7 @@ $code.=<<___;
vpaddq $TEMP1, $ACC1, $ACC1
vpmuludq 32*7-128($aap), $B2, $ACC2
vpbroadcastq 32*5-128($tpa), $B2
vpaddq 32*11-448($tp1), $ACC2, $ACC2
vpaddq 32*11-448($tp1), $ACC2, $ACC2
vmovdqu $ACC6, 32*6-192($tp0)
vmovdqu $ACC7, 32*7-192($tp0)
@@ -427,7 +418,7 @@ $code.=<<___;
vmovdqu $ACC7, 32*16-448($tp1)
lea 8($tp1), $tp1
dec $i
dec $i
jnz .LOOP_SQR_1024
___
$ZERO = $ACC9;
@@ -772,7 +763,7 @@ $code.=<<___;
vpblendd \$3, $TEMP4, $TEMP5, $TEMP4
vpaddq $TEMP3, $ACC7, $ACC7
vpaddq $TEMP4, $ACC8, $ACC8
vpsrlq \$29, $ACC4, $TEMP1
vpand $AND_MASK, $ACC4, $ACC4
vpsrlq \$29, $ACC5, $TEMP2
@@ -811,10 +802,8 @@ $code.=<<___;
vzeroall
mov %rbp, %rax
.cfi_def_cfa_register %rax
___
$code.=<<___ if ($win64);
.Lsqr_1024_in_tail:
movaps -0xd8(%rax),%xmm6
movaps -0xc8(%rax),%xmm7
movaps -0xb8(%rax),%xmm8
@@ -828,22 +817,14 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -48(%rax),%r15
.cfi_restore %r15
mov -40(%rax),%r14
.cfi_restore %r14
mov -32(%rax),%r13
.cfi_restore %r13
mov -24(%rax),%r12
.cfi_restore %r12
mov -16(%rax),%rbp
.cfi_restore %rbp
mov -8(%rax),%rbx
.cfi_restore %rbx
lea (%rax),%rsp # restore %rsp
.cfi_def_cfa_register %rsp
.Lsqr_1024_epilogue:
ret
.cfi_endproc
.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2
___
}
@@ -896,21 +877,13 @@ $code.=<<___;
.type rsaz_1024_mul_avx2,\@function,5
.align 64
rsaz_1024_mul_avx2:
.cfi_startproc
lea (%rsp), %rax
.cfi_def_cfa_register %rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
___
$code.=<<___ if ($win64);
vzeroupper
@@ -929,7 +902,6 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov %rax,%rbp
.cfi_def_cfa_register %rbp
vzeroall
mov %rdx, $bp # reassigned argument
sub \$64,%rsp
@@ -1456,17 +1428,15 @@ $code.=<<___;
vpaddq $TEMP4, $ACC8, $ACC8
vmovdqu $ACC4, 128-128($rp)
vmovdqu $ACC5, 160-128($rp)
vmovdqu $ACC5, 160-128($rp)
vmovdqu $ACC6, 192-128($rp)
vmovdqu $ACC7, 224-128($rp)
vmovdqu $ACC8, 256-128($rp)
vzeroupper
mov %rbp, %rax
.cfi_def_cfa_register %rax
___
$code.=<<___ if ($win64);
.Lmul_1024_in_tail:
movaps -0xd8(%rax),%xmm6
movaps -0xc8(%rax),%xmm7
movaps -0xb8(%rax),%xmm8
@@ -1480,22 +1450,14 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -48(%rax),%r15
.cfi_restore %r15
mov -40(%rax),%r14
.cfi_restore %r14
mov -32(%rax),%r13
.cfi_restore %r13
mov -24(%rax),%r12
.cfi_restore %r12
mov -16(%rax),%rbp
.cfi_restore %rbp
mov -8(%rax),%rbx
.cfi_restore %rbx
lea (%rax),%rsp # restore %rsp
.cfi_def_cfa_register %rsp
.Lmul_1024_epilogue:
ret
.cfi_endproc
.size rsaz_1024_mul_avx2,.-rsaz_1024_mul_avx2
___
}
@@ -1614,10 +1576,8 @@ rsaz_1024_scatter5_avx2:
.type rsaz_1024_gather5_avx2,\@abi-omnipotent
.align 32
rsaz_1024_gather5_avx2:
.cfi_startproc
vzeroupper
mov %rsp,%r11
.cfi_def_cfa_register %r11
___
$code.=<<___ if ($win64);
lea -0x88(%rsp),%rax
@@ -1755,13 +1715,11 @@ $code.=<<___ if ($win64);
movaps -0x38(%r11),%xmm13
movaps -0x28(%r11),%xmm14
movaps -0x18(%r11),%xmm15
.LSEH_end_rsaz_1024_gather5:
___
$code.=<<___;
lea (%r11),%rsp
.cfi_def_cfa_register %rsp
ret
.cfi_endproc
.LSEH_end_rsaz_1024_gather5:
.size rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2
___
}
@@ -1834,17 +1792,14 @@ rsaz_se_handler:
cmp %r10,%rbx # context->Rip<prologue label
jb .Lcommon_seh_tail
mov 152($context),%rax # pull context->Rsp
mov 4(%r11),%r10d # HandlerData[1]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=epilogue label
jae .Lcommon_seh_tail
mov 160($context),%rbp # pull context->Rbp
mov 8(%r11),%r10d # HandlerData[2]
lea (%rsi,%r10),%r10 # "in tail" label
cmp %r10,%rbx # context->Rip>="in tail" label
cmovc %rbp,%rax
mov 160($context),%rax # pull context->Rbp
mov -48(%rax),%r15
mov -40(%rax),%r14
@@ -1922,13 +1877,11 @@ rsaz_se_handler:
.LSEH_info_rsaz_1024_sqr_avx2:
.byte 9,0,0,0
.rva rsaz_se_handler
.rva .Lsqr_1024_body,.Lsqr_1024_epilogue,.Lsqr_1024_in_tail
.long 0
.rva .Lsqr_1024_body,.Lsqr_1024_epilogue
.LSEH_info_rsaz_1024_mul_avx2:
.byte 9,0,0,0
.rva rsaz_se_handler
.rva .Lmul_1024_body,.Lmul_1024_epilogue,.Lmul_1024_in_tail
.long 0
.rva .Lmul_1024_body,.Lmul_1024_epilogue
.LSEH_info_rsaz_1024_gather5:
.byte 0x01,0x36,0x17,0x0b
.byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
Executable → Regular
+19 -44
View File
@@ -32,7 +32,7 @@ require "x86asm.pl";
$output = pop;
open STDOUT,">$output";
&asm_init($ARGV[0],$0);
$sse2=0;
@@ -66,57 +66,33 @@ $frame=32; # size of above frame rounded up to 16n
&lea ("esi",&wparam(0)); # put aside pointer to argument block
&lea ("edx",&wparam(1)); # load ap
&mov ("ebp","esp"); # saved stack pointer!
&add ("edi",2); # extra two words on top of tp
&neg ("edi");
&lea ("ebp",&DWP(-$frame,"esp","edi",4)); # future alloca($frame+4*(num+2))
&lea ("esp",&DWP(-$frame,"esp","edi",4)); # alloca($frame+4*(num+2))
&neg ("edi");
# minimize cache contention by arraning 2K window between stack
# pointer and ap argument [np is also position sensitive vector,
# but it's assumed to be near ap, as it's allocated at ~same
# time].
&mov ("eax","ebp");
&mov ("eax","esp");
&sub ("eax","edx");
&and ("eax",2047);
&sub ("ebp","eax"); # this aligns sp and ap modulo 2048
&sub ("esp","eax"); # this aligns sp and ap modulo 2048
&xor ("edx","ebp");
&xor ("edx","esp");
&and ("edx",2048);
&xor ("edx",2048);
&sub ("ebp","edx"); # this splits them apart modulo 4096
&sub ("esp","edx"); # this splits them apart modulo 4096
&and ("ebp",-64); # align to cache line
# An OS-agnostic version of __chkstk.
#
# Some OSes (Windows) insist on stack being "wired" to
# physical memory in strictly sequential manner, i.e. if stack
# allocation spans two pages, then reference to farmost one can
# be punishable by SEGV. But page walking can do good even on
# other OSes, because it guarantees that villain thread hits
# the guard page before it can make damage to innocent one...
&mov ("eax","esp");
&sub ("eax","ebp");
&and ("eax",-4096);
&mov ("edx","esp"); # saved stack pointer!
&lea ("esp",&DWP(0,"ebp","eax"));
&mov ("eax",&DWP(0,"esp"));
&cmp ("esp","ebp");
&ja (&label("page_walk"));
&jmp (&label("page_walk_done"));
&set_label("page_walk",16);
&lea ("esp",&DWP(-4096,"esp"));
&mov ("eax",&DWP(0,"esp"));
&cmp ("esp","ebp");
&ja (&label("page_walk"));
&set_label("page_walk_done");
&and ("esp",-64); # align to cache line
################################# load argument block...
&mov ("eax",&DWP(0*4,"esi"));# BN_ULONG *rp
&mov ("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap
&mov ("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp
&mov ("ebp",&DWP(3*4,"esi"));# const BN_ULONG *np
&mov ("edx",&DWP(3*4,"esi"));# const BN_ULONG *np
&mov ("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0
#&mov ("edi",&DWP(5*4,"esi"));# int num
@@ -124,11 +100,11 @@ $frame=32; # size of above frame rounded up to 16n
&mov ($_rp,"eax"); # ... save a copy of argument block
&mov ($_ap,"ebx");
&mov ($_bp,"ecx");
&mov ($_np,"ebp");
&mov ($_np,"edx");
&mov ($_n0,"esi");
&lea ($num,&DWP(-3,"edi")); # num=num-1 to assist modulo-scheduling
#&mov ($_num,$num); # redundant as $num is not reused
&mov ($_sp,"edx"); # saved stack pointer!
&mov ($_sp,"ebp"); # saved stack pointer!
if($sse2) {
$acc0="mm0"; # mmx register bank layout
@@ -294,7 +270,7 @@ if (0) {
&xor ("eax","eax"); # signal "not fast enough [yet]"
&jmp (&label("just_leave"));
# While the below code provides competitive performance for
# all key lengths on modern Intel cores, it's still more
# all key lengthes on modern Intel cores, it's still more
# than 10% slower for 4096-bit key elsewhere:-( "Competitive"
# means compared to the original integer-only assembler.
# 512-bit RSA sign is better by ~40%, but that's about all
@@ -597,16 +573,15 @@ $sbit=$num;
&jge (&label("sub"));
&sbb ("eax",0); # handle upmost overflow bit
&and ($tp,"eax");
&not ("eax");
&mov ($np,$rp);
&and ($np,"eax");
&or ($tp,$np); # tp=carry?tp:rp
&set_label("copy",16); # copy or in-place refresh
&mov ("eax",&DWP(0,$tp,$num,4));
&mov (&DWP(0,$rp,$num,4),"eax"); # rp[i]=tp[i]
&mov (&DWP($frame,"esp",$num,4),$j); # zap temporary vector
&mov ("edx",&DWP(0,$tp,$num,4));
&mov ($np,&DWP(0,$rp,$num,4));
&xor ("edx",$np); # conditional select
&and ("edx","eax");
&xor ("edx",$np);
&mov (&DWP(0,$tp,$num,4),$j) # zap temporary vector
&mov (&DWP(0,$rp,$num,4),"edx"); # rp[i]=tp[i]
&dec ($num);
&jge (&label("copy"));
+85 -229
View File
@@ -84,10 +84,6 @@ $code=<<___;
.type bn_mul_mont,\@function,6
.align 16
bn_mul_mont:
.cfi_startproc
mov ${num}d,${num}d
mov %rsp,%rax
.cfi_def_cfa_register %rax
test \$3,${num}d
jnz .Lmul_enter
cmp \$8,${num}d
@@ -106,50 +102,20 @@ $code.=<<___;
.align 16
.Lmul_enter:
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
neg $num
mov ${num}d,${num}d
lea 2($num),%r10
mov %rsp,%r11
lea -16(%rsp,$num,8),%r10 # future alloca(8*(num+2))
neg $num # restore $num
and \$-1024,%r10 # minimize TLB usage
neg %r10
lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+2))
and \$-1024,%rsp # minimize TLB usage
# An OS-agnostic version of __chkstk.
#
# Some OSes (Windows) insist on stack being "wired" to
# physical memory in strictly sequential manner, i.e. if stack
# allocation spans two pages, then reference to farmost one can
# be punishable by SEGV. But page walking can do good even on
# other OSes, because it guarantees that villain thread hits
# the guard page before it can make damage to innocent one...
sub %r10,%r11
and \$-4096,%r11
lea (%r10,%r11),%rsp
mov (%rsp),%r11
cmp %r10,%rsp
ja .Lmul_page_walk
jmp .Lmul_page_walk_done
.align 16
.Lmul_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r11
cmp %r10,%rsp
ja .Lmul_page_walk
.Lmul_page_walk_done:
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8
mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp
.Lmul_body:
mov $bp,%r12 # reassign $bp
___
@@ -299,46 +265,36 @@ $code.=<<___;
mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i]
mov 8($ap,$i,8),%rax # tp[i+1]
lea 1($i),$i # i++
dec $j # doesnn't affect CF!
dec $j # doesn't affect CF!
jnz .Lsub
sbb \$0,%rax # handle upmost overflow bit
xor $i,$i
and %rax,$ap
not %rax
mov $rp,$np
and %rax,$np
mov $num,$j # j=num
or $np,$ap # ap=borrow?tp:rp
.align 16
.Lcopy: # copy or in-place refresh
mov ($ap,$i,8),%rax
mov (%rsp,$i,8),$ap
mov ($rp,$i,8),$np
xor $np,$ap # conditional select:
and %rax,$ap # ((ap ^ np) & %rax) ^ np
xor $np,$ap # ap = borrow?tp:rp
mov $i,(%rsp,$i,8) # zap temporary vector
mov %rax,($rp,$i,8) # rp[i]=tp[i]
mov $ap,($rp,$i,8) # rp[i]=tp[i]
lea 1($i),$i
sub \$1,$j
jnz .Lcopy
mov 8(%rsp,$num,8),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
mov (%rsi),%r15
mov 8(%rsi),%r14
mov 16(%rsi),%r13
mov 24(%rsi),%r12
mov 32(%rsi),%rbp
mov 40(%rsi),%rbx
lea 48(%rsi),%rsp
.Lmul_epilogue:
ret
.cfi_endproc
.size bn_mul_mont,.-bn_mul_mont
___
{{{
@@ -348,10 +304,6 @@ $code.=<<___;
.type bn_mul4x_mont,\@function,6
.align 16
bn_mul4x_mont:
.cfi_startproc
mov ${num}d,${num}d
mov %rsp,%rax
.cfi_def_cfa_register %rax
.Lmul4x_enter:
___
$code.=<<___ if ($addx);
@@ -361,41 +313,20 @@ $code.=<<___ if ($addx);
___
$code.=<<___;
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
neg $num
mov ${num}d,${num}d
lea 4($num),%r10
mov %rsp,%r11
lea -32(%rsp,$num,8),%r10 # future alloca(8*(num+4))
neg $num # restore
and \$-1024,%r10 # minimize TLB usage
neg %r10
lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+4))
and \$-1024,%rsp # minimize TLB usage
sub %r10,%r11
and \$-4096,%r11
lea (%r10,%r11),%rsp
mov (%rsp),%r11
cmp %r10,%rsp
ja .Lmul4x_page_walk
jmp .Lmul4x_page_walk_done
.Lmul4x_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r11
cmp %r10,%rsp
ja .Lmul4x_page_walk
.Lmul4x_page_walk_done:
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8
mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp
.Lmul4x_body:
mov $rp,16(%rsp,$num,8) # tp[num+2]=$rp
mov %rdx,%r12 # reassign $bp
@@ -702,11 +633,9 @@ ___
my @ri=("%rax","%rdx",$m0,$m1);
$code.=<<___;
mov 16(%rsp,$num,8),$rp # restore $rp
lea -4($num),$j
mov 0(%rsp),@ri[0] # tp[0]
pxor %xmm0,%xmm0
mov 8(%rsp),@ri[1] # tp[1]
shr \$2,$j # j=num/4-1
shr \$2,$num # num/=4
lea (%rsp),$ap # borrow ap for tp
xor $i,$i # i=0 and clear CF!
@@ -714,6 +643,7 @@ $code.=<<___;
mov 16($ap),@ri[2] # tp[2]
mov 24($ap),@ri[3] # tp[3]
sbb 8($np),@ri[1]
lea -1($num),$j # j=num/4-1
jmp .Lsub4x
.align 16
.Lsub4x:
@@ -741,58 +671,50 @@ $code.=<<___;
mov @ri[2],16($rp,$i,8) # rp[i]=tp[i]-np[i]
sbb \$0,@ri[0] # handle upmost overflow bit
mov @ri[0],%xmm0
punpcklqdq %xmm0,%xmm0 # extend mask to 128 bits
mov @ri[3],24($rp,$i,8) # rp[i]=tp[i]-np[i]
xor $i,$i # i=0
and @ri[0],$ap
not @ri[0]
mov $rp,$np
and @ri[0],$np
lea -4($num),$j
or $np,$ap # ap=borrow?tp:rp
shr \$2,$j # j=num/4-1
movdqu ($ap),%xmm1
movdqa %xmm0,(%rsp)
movdqu %xmm1,($rp)
mov $num,$j
pxor %xmm5,%xmm5
jmp .Lcopy4x
.align 16
.Lcopy4x: # copy or in-place refresh
movdqu 16($ap,$i),%xmm2
movdqu 32($ap,$i),%xmm1
movdqa %xmm0,16(%rsp,$i)
movdqu %xmm2,16($rp,$i)
movdqa %xmm0,32(%rsp,$i)
movdqu %xmm1,32($rp,$i)
.Lcopy4x: # copy or in-place refresh
movdqu (%rsp,$i),%xmm2
movdqu 16(%rsp,$i),%xmm4
movdqu ($rp,$i),%xmm1
movdqu 16($rp,$i),%xmm3
pxor %xmm1,%xmm2 # conditional select
pxor %xmm3,%xmm4
pand %xmm0,%xmm2
pand %xmm0,%xmm4
pxor %xmm1,%xmm2
pxor %xmm3,%xmm4
movdqu %xmm2,($rp,$i)
movdqu %xmm4,16($rp,$i)
movdqa %xmm5,(%rsp,$i) # zap temporary vectors
movdqa %xmm5,16(%rsp,$i)
lea 32($i),$i
dec $j
jnz .Lcopy4x
movdqu 16($ap,$i),%xmm2
movdqa %xmm0,16(%rsp,$i)
movdqu %xmm2,16($rp,$i)
shl \$2,$num
___
}
$code.=<<___;
mov 8(%rsp,$num,8),%rsi # restore %rsp
.cfi_def_cfa %rsi, 8
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
mov (%rsi),%r15
mov 8(%rsi),%r14
mov 16(%rsi),%r13
mov 24(%rsi),%r12
mov 32(%rsi),%rbp
mov 40(%rsi),%rbx
lea 48(%rsi),%rsp
.Lmul4x_epilogue:
ret
.cfi_endproc
.size bn_mul4x_mont,.-bn_mul4x_mont
___
}}}
@@ -820,23 +742,14 @@ $code.=<<___;
.type bn_sqr8x_mont,\@function,6
.align 32
bn_sqr8x_mont:
.cfi_startproc
mov %rsp,%rax
.cfi_def_cfa_register %rax
.Lsqr8x_enter:
mov %rsp,%rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
.Lsqr8x_prologue:
mov ${num}d,%r10d
shl \$3,${num}d # convert $num to bytes
@@ -849,49 +762,30 @@ bn_sqr8x_mont:
# do its job.
#
lea -64(%rsp,$num,2),%r11
mov %rsp,%rbp
mov ($n0),$n0 # *n0
sub $aptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lsqr8x_sp_alt
sub %r11,%rbp # align with $aptr
lea -64(%rbp,$num,2),%rbp # future alloca(frame+2*$num)
sub %r11,%rsp # align with $aptr
lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
jmp .Lsqr8x_sp_done
.align 32
.Lsqr8x_sp_alt:
lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
lea -64(%rbp,$num,2),%rbp # future alloca(frame+2*$num)
lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
sub %r11,%rbp
sub %r11,%rsp
.Lsqr8x_sp_done:
and \$-64,%rbp
mov %rsp,%r11
sub %rbp,%r11
and \$-4096,%r11
lea (%rbp,%r11),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lsqr8x_page_walk
jmp .Lsqr8x_page_walk_done
.align 16
.Lsqr8x_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lsqr8x_page_walk
.Lsqr8x_page_walk_done:
and \$-64,%rsp
mov $num,%r10
neg $num
mov $n0, 32(%rsp)
mov %rax, 40(%rsp) # save original %rsp
.cfi_cfa_expression %rsp+40,deref,+8
.Lsqr8x_body:
movq $nptr, %xmm2 # save pointer to modulus
@@ -961,7 +855,6 @@ $code.=<<___;
pxor %xmm0,%xmm0
pshufd \$0,%xmm1,%xmm1
mov 40(%rsp),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
jmp .Lsqr8x_cond_copy
.align 32
@@ -991,22 +884,14 @@ $code.=<<___;
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lsqr8x_epilogue:
ret
.cfi_endproc
.size bn_sqr8x_mont,.-bn_sqr8x_mont
___
}}}
@@ -1018,48 +903,23 @@ $code.=<<___;
.type bn_mulx4x_mont,\@function,6
.align 32
bn_mulx4x_mont:
.cfi_startproc
mov %rsp,%rax
.cfi_def_cfa_register %rax
.Lmulx4x_enter:
mov %rsp,%rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
.Lmulx4x_prologue:
shl \$3,${num}d # convert $num to bytes
.byte 0x67
xor %r10,%r10
sub $num,%r10 # -$num
mov ($n0),$n0 # *n0
lea -72(%rsp,%r10),%rbp # future alloca(frame+$num+8)
and \$-128,%rbp
mov %rsp,%r11
sub %rbp,%r11
and \$-4096,%r11
lea (%rbp,%r11),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lmulx4x_page_walk
jmp .Lmulx4x_page_walk_done
.align 16
.Lmulx4x_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lmulx4x_page_walk
.Lmulx4x_page_walk_done:
lea -72(%rsp,%r10),%rsp # alloca(frame+$num+8)
lea ($bp,$num),%r10
and \$-128,%rsp
##############################################################
# Stack layout
# +0 num
@@ -1079,7 +939,6 @@ bn_mulx4x_mont:
mov $n0, 24(%rsp) # save *n0
mov $rp, 32(%rsp) # save $rp
mov %rax,40(%rsp) # save original %rsp
.cfi_cfa_expression %rsp+40,deref,+8
mov $num,48(%rsp) # inner counter
jmp .Lmulx4x_body
@@ -1329,7 +1188,6 @@ $code.=<<___;
pxor %xmm0,%xmm0
pshufd \$0,%xmm1,%xmm1
mov 40(%rsp),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
jmp .Lmulx4x_cond_copy
.align 32
@@ -1359,22 +1217,14 @@ $code.=<<___;
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lmulx4x_epilogue:
ret
.cfi_endproc
.size bn_mulx4x_mont,.-bn_mulx4x_mont
___
}}}
@@ -1427,8 +1277,22 @@ mul_handler:
mov 192($context),%r10 # pull $num
mov 8(%rax,%r10,8),%rax # pull saved stack pointer
lea 48(%rax),%rax
jmp .Lcommon_pop_regs
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
mov -32(%rax),%r13
mov -40(%rax),%r14
mov -48(%rax),%r15
mov %rbx,144($context) # restore context->Rbx
mov %rbp,160($context) # restore context->Rbp
mov %r12,216($context) # restore context->R12
mov %r13,224($context) # restore context->R13
mov %r14,232($context) # restore context->R14
mov %r15,240($context) # restore context->R15
jmp .Lcommon_seh_tail
.size mul_handler,.-mul_handler
.type sqr_handler,\@abi-omnipotent
@@ -1453,24 +1317,18 @@ sqr_handler:
mov 0(%r11),%r10d # HandlerData[0]
lea (%rsi,%r10),%r10 # end of prologue label
cmp %r10,%rbx # context->Rip<.Lsqr_prologue
jb .Lcommon_seh_tail
mov 4(%r11),%r10d # HandlerData[1]
lea (%rsi,%r10),%r10 # body label
cmp %r10,%rbx # context->Rip<.Lsqr_body
jb .Lcommon_pop_regs
jb .Lcommon_seh_tail
mov 152($context),%rax # pull context->Rsp
mov 8(%r11),%r10d # HandlerData[2]
mov 4(%r11),%r10d # HandlerData[1]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=.Lsqr_epilogue
jae .Lcommon_seh_tail
mov 40(%rax),%rax # pull saved stack pointer
.Lcommon_pop_regs:
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
@@ -1557,15 +1415,13 @@ $code.=<<___;
.LSEH_info_bn_sqr8x_mont:
.byte 9,0,0,0
.rva sqr_handler
.rva .Lsqr8x_prologue,.Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[]
.align 8
.rva .Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[]
___
$code.=<<___ if ($addx);
.LSEH_info_bn_mulx4x_mont:
.byte 9,0,0,0
.rva sqr_handler
.rva .Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
.align 8
.rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
___
}
+77 -303
View File
@@ -73,10 +73,6 @@ $code=<<___;
.type bn_mul_mont_gather5,\@function,6
.align 64
bn_mul_mont_gather5:
.cfi_startproc
mov ${num}d,${num}d
mov %rsp,%rax
.cfi_def_cfa_register %rax
test \$7,${num}d
jnz .Lmul_enter
___
@@ -88,54 +84,24 @@ $code.=<<___;
.align 16
.Lmul_enter:
mov ${num}d,${num}d
mov %rsp,%rax
movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
neg $num
mov %rsp,%r11
lea -280(%rsp,$num,8),%r10 # future alloca(8*(num+2)+256+8)
neg $num # restore $num
and \$-1024,%r10 # minimize TLB usage
# An OS-agnostic version of __chkstk.
#
# Some OSes (Windows) insist on stack being "wired" to
# physical memory in strictly sequential manner, i.e. if stack
# allocation spans two pages, then reference to farmost one can
# be punishable by SEGV. But page walking can do good even on
# other OSes, because it guarantees that villain thread hits
# the guard page before it can make damage to innocent one...
sub %r10,%r11
and \$-4096,%r11
lea (%r10,%r11),%rsp
mov (%rsp),%r11
cmp %r10,%rsp
ja .Lmul_page_walk
jmp .Lmul_page_walk_done
.Lmul_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r11
cmp %r10,%rsp
ja .Lmul_page_walk
.Lmul_page_walk_done:
lea .Linc(%rip),%r10
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8
.Lmul_body:
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
lea 2($num),%r11
neg %r11
lea -264(%rsp,%r11,8),%rsp # tp=alloca(8*(num+2)+256+8)
and \$-1024,%rsp # minimize TLB usage
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
.Lmul_body:
lea 128($bp),%r12 # reassign $bp (+size optimization)
___
$bp="%r12";
@@ -404,42 +370,32 @@ $code.=<<___;
sbb \$0,%rax # handle upmost overflow bit
xor $i,$i
and %rax,$ap
not %rax
mov $rp,$np
and %rax,$np
mov $num,$j # j=num
or $np,$ap # ap=borrow?tp:rp
.align 16
.Lcopy: # copy or in-place refresh
mov ($ap,$i,8),%rax
mov (%rsp,$i,8),$ap
mov ($rp,$i,8),$np
xor $np,$ap # conditional select:
and %rax,$ap # ((ap ^ np) & %rax) ^ np
xor $np,$ap # ap = borrow?tp:rp
mov $i,(%rsp,$i,8) # zap temporary vector
mov %rax,($rp,$i,8) # rp[i]=tp[i]
mov $ap,($rp,$i,8) # rp[i]=tp[i]
lea 1($i),$i
sub \$1,$j
jnz .Lcopy
mov 8(%rsp,$num,8),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lmul_epilogue:
ret
.cfi_endproc
.size bn_mul_mont_gather5,.-bn_mul_mont_gather5
___
{{{
@@ -449,10 +405,6 @@ $code.=<<___;
.type bn_mul4x_mont_gather5,\@function,6
.align 32
bn_mul4x_mont_gather5:
.cfi_startproc
.byte 0x67
mov %rsp,%rax
.cfi_def_cfa_register %rax
.Lmul4x_enter:
___
$code.=<<___ if ($addx);
@@ -461,19 +413,14 @@ $code.=<<___ if ($addx);
je .Lmulx4x_enter
___
$code.=<<___;
.byte 0x67
mov %rsp,%rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
.Lmul4x_prologue:
.byte 0x67
shl \$3,${num}d # convert $num to bytes
@@ -490,70 +437,43 @@ $code.=<<___;
# calculated from 7th argument, the index.]
#
lea -320(%rsp,$num,2),%r11
mov %rsp,%rbp
sub $rp,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lmul4xsp_alt
sub %r11,%rbp # align with $rp
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
sub %r11,%rsp # align with $rp
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
jmp .Lmul4xsp_done
.align 32
.Lmul4xsp_alt:
lea 4096-320(,$num,2),%r10
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
sub %r11,%rbp
sub %r11,%rsp
.Lmul4xsp_done:
and \$-64,%rbp
mov %rsp,%r11
sub %rbp,%r11
and \$-4096,%r11
lea (%rbp,%r11),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lmul4x_page_walk
jmp .Lmul4x_page_walk_done
.Lmul4x_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lmul4x_page_walk
.Lmul4x_page_walk_done:
and \$-64,%rsp
neg $num
mov %rax,40(%rsp)
.cfi_cfa_expression %rsp+40,deref,+8
.Lmul4x_body:
call mul4x_internal
mov 40(%rsp),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lmul4x_epilogue:
ret
.cfi_endproc
.size bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5
.type mul4x_internal,\@abi-omnipotent
@@ -1065,7 +985,7 @@ my $bptr="%rdx"; # const void *table,
my $nptr="%rcx"; # const BN_ULONG *nptr,
my $n0 ="%r8"; # const BN_ULONG *n0);
my $num ="%r9"; # int num, has to be divisible by 8
# int pwr
# int pwr
my ($i,$j,$tptr)=("%rbp","%rcx",$rptr);
my @A0=("%r10","%r11");
@@ -1077,9 +997,6 @@ $code.=<<___;
.type bn_power5,\@function,6
.align 32
bn_power5:
.cfi_startproc
mov %rsp,%rax
.cfi_def_cfa_register %rax
___
$code.=<<___ if ($addx);
mov OPENSSL_ia32cap_P+8(%rip),%r11d
@@ -1088,19 +1005,13 @@ $code.=<<___ if ($addx);
je .Lpowerx5_enter
___
$code.=<<___;
mov %rsp,%rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
.Lpower5_prologue:
shl \$3,${num}d # convert $num to bytes
lea ($num,$num,2),%r10d # 3*$num
@@ -1115,42 +1026,25 @@ $code.=<<___;
# calculated from 7th argument, the index.]
#
lea -320(%rsp,$num,2),%r11
mov %rsp,%rbp
sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lpwr_sp_alt
sub %r11,%rbp # align with $aptr
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
sub %r11,%rsp # align with $aptr
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
jmp .Lpwr_sp_done
.align 32
.Lpwr_sp_alt:
lea 4096-320(,$num,2),%r10
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
sub %r11,%rbp
sub %r11,%rsp
.Lpwr_sp_done:
and \$-64,%rbp
mov %rsp,%r11
sub %rbp,%r11
and \$-4096,%r11
lea (%rbp,%r11),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lpwr_page_walk
jmp .Lpwr_page_walk_done
.Lpwr_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lpwr_page_walk
.Lpwr_page_walk_done:
mov $num,%r10
and \$-64,%rsp
mov $num,%r10
neg $num
##############################################################
@@ -1164,7 +1058,6 @@ $code.=<<___;
#
mov $n0, 32(%rsp)
mov %rax, 40(%rsp) # save original %rsp
.cfi_cfa_expression %rsp+40,deref,+8
.Lpower5_body:
movq $rptr,%xmm1 # save $rptr, used in sqr8x
movq $nptr,%xmm2 # save $nptr
@@ -1191,25 +1084,16 @@ $code.=<<___;
call mul4x_internal
mov 40(%rsp),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lpower5_epilogue:
ret
.cfi_endproc
.size bn_power5,.-bn_power5
.globl bn_sqr8x_internal
@@ -1968,7 +1852,6 @@ __bn_sqr8x_reduction:
.align 32
.L8x_tail_done:
xor %rax,%rax
add (%rdx),%r8 # can this overflow?
adc \$0,%r9
adc \$0,%r10
@@ -1976,8 +1859,10 @@ __bn_sqr8x_reduction:
adc \$0,%r12
adc \$0,%r13
adc \$0,%r14
adc \$0,%r15
adc \$0,%rax
adc \$0,%r15 # can't overflow, because we
# started with "overhung" part
# of multiplication
xor %rax,%rax
neg $carry
.L8x_no_tail:
@@ -2069,7 +1954,7 @@ __bn_post4x_internal:
jnz .Lsqr4x_sub
mov $num,%r10 # prepare for back-to-back call
neg $num # restore $num
neg $num # restore $num
ret
.size __bn_post4x_internal,.-__bn_post4x_internal
___
@@ -2089,23 +1974,14 @@ bn_from_montgomery:
.type bn_from_mont8x,\@function,6
.align 32
bn_from_mont8x:
.cfi_startproc
.byte 0x67
mov %rsp,%rax
.cfi_def_cfa_register %rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
.Lfrom_prologue:
shl \$3,${num}d # convert $num to bytes
lea ($num,$num,2),%r10 # 3*$num in bytes
@@ -2120,42 +1996,25 @@ bn_from_mont8x:
# last operation, we use the opportunity to cleanse it.
#
lea -320(%rsp,$num,2),%r11
mov %rsp,%rbp
sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lfrom_sp_alt
sub %r11,%rbp # align with $aptr
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
sub %r11,%rsp # align with $aptr
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lfrom_sp_done
.align 32
.Lfrom_sp_alt:
lea 4096-320(,$num,2),%r10
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
sub %r11,%rbp
sub %r11,%rsp
.Lfrom_sp_done:
and \$-64,%rbp
mov %rsp,%r11
sub %rbp,%r11
and \$-4096,%r11
lea (%rbp,%r11),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lfrom_page_walk
jmp .Lfrom_page_walk_done
.Lfrom_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lfrom_page_walk
.Lfrom_page_walk_done:
mov $num,%r10
and \$-64,%rsp
mov $num,%r10
neg $num
##############################################################
@@ -2169,7 +2028,6 @@ bn_from_mont8x:
#
mov $n0, 32(%rsp)
mov %rax, 40(%rsp) # save original %rsp
.cfi_cfa_expression %rsp+40,deref,+8
.Lfrom_body:
mov $num,%r11
lea 48(%rsp),%rax
@@ -2213,6 +2071,7 @@ $code.=<<___ if ($addx);
pxor %xmm0,%xmm0
lea 48(%rsp),%rax
mov 40(%rsp),%rsi # restore %rsp
jmp .Lfrom_mont_zero
.align 32
@@ -2224,12 +2083,11 @@ $code.=<<___;
pxor %xmm0,%xmm0
lea 48(%rsp),%rax
mov 40(%rsp),%rsi # restore %rsp
jmp .Lfrom_mont_zero
.align 32
.Lfrom_mont_zero:
mov 40(%rsp),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
movdqa %xmm0,16*0(%rax)
movdqa %xmm0,16*1(%rax)
movdqa %xmm0,16*2(%rax)
@@ -2240,22 +2098,14 @@ $code.=<<___;
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lfrom_epilogue:
ret
.cfi_endproc
.size bn_from_mont8x,.-bn_from_mont8x
___
}
@@ -2268,23 +2118,14 @@ $code.=<<___;
.type bn_mulx4x_mont_gather5,\@function,6
.align 32
bn_mulx4x_mont_gather5:
.cfi_startproc
mov %rsp,%rax
.cfi_def_cfa_register %rax
.Lmulx4x_enter:
mov %rsp,%rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
.Lmulx4x_prologue:
shl \$3,${num}d # convert $num to bytes
lea ($num,$num,2),%r10 # 3*$num in bytes
@@ -2301,40 +2142,23 @@ bn_mulx4x_mont_gather5:
# calculated from 7th argument, the index.]
#
lea -320(%rsp,$num,2),%r11
mov %rsp,%rbp
sub $rp,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lmulx4xsp_alt
sub %r11,%rbp # align with $aptr
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
sub %r11,%rsp # align with $aptr
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lmulx4xsp_done
.Lmulx4xsp_alt:
lea 4096-320(,$num,2),%r10
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
sub %r11,%rbp
.Lmulx4xsp_done:
and \$-64,%rbp # ensure alignment
mov %rsp,%r11
sub %rbp,%r11
and \$-4096,%r11
lea (%rbp,%r11),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lmulx4x_page_walk
jmp .Lmulx4x_page_walk_done
.Lmulx4x_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lmulx4x_page_walk
.Lmulx4x_page_walk_done:
sub %r11,%rsp
.Lmulx4xsp_done:
and \$-64,%rsp # ensure alignment
##############################################################
# Stack layout
# +0 -num
@@ -2349,31 +2173,21 @@ bn_mulx4x_mont_gather5:
#
mov $n0, 32(%rsp) # save *n0
mov %rax,40(%rsp) # save original %rsp
.cfi_cfa_expression %rsp+40,deref,+8
.Lmulx4x_body:
call mulx4x_internal
mov 40(%rsp),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lmulx4x_epilogue:
ret
.cfi_endproc
.size bn_mulx4x_mont_gather5,.-bn_mulx4x_mont_gather5
.type mulx4x_internal,\@abi-omnipotent
@@ -2751,23 +2565,14 @@ $code.=<<___;
.type bn_powerx5,\@function,6
.align 32
bn_powerx5:
.cfi_startproc
mov %rsp,%rax
.cfi_def_cfa_register %rax
.Lpowerx5_enter:
mov %rsp,%rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
.Lpowerx5_prologue:
shl \$3,${num}d # convert $num to bytes
lea ($num,$num,2),%r10 # 3*$num in bytes
@@ -2782,42 +2587,25 @@ bn_powerx5:
# calculated from 7th argument, the index.]
#
lea -320(%rsp,$num,2),%r11
mov %rsp,%rbp
sub $rptr,%r11
and \$4095,%r11
cmp %r11,%r10
jb .Lpwrx_sp_alt
sub %r11,%rbp # align with $aptr
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
sub %r11,%rsp # align with $aptr
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
jmp .Lpwrx_sp_done
.align 32
.Lpwrx_sp_alt:
lea 4096-320(,$num,2),%r10
lea -320(%rbp,$num,2),%rbp # alloca(frame+2*$num*8+256)
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
sub %r10,%r11
mov \$0,%r10
cmovc %r10,%r11
sub %r11,%rbp
sub %r11,%rsp
.Lpwrx_sp_done:
and \$-64,%rbp
mov %rsp,%r11
sub %rbp,%r11
and \$-4096,%r11
lea (%rbp,%r11),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lpwrx_page_walk
jmp .Lpwrx_page_walk_done
.Lpwrx_page_walk:
lea -4096(%rsp),%rsp
mov (%rsp),%r10
cmp %rbp,%rsp
ja .Lpwrx_page_walk
.Lpwrx_page_walk_done:
mov $num,%r10
and \$-64,%rsp
mov $num,%r10
neg $num
##############################################################
@@ -2838,7 +2626,6 @@ bn_powerx5:
movq $bptr,%xmm4
mov $n0, 32(%rsp)
mov %rax, 40(%rsp) # save original %rsp
.cfi_cfa_expression %rsp+40,deref,+8
.Lpowerx5_body:
call __bn_sqrx8x_internal
@@ -2861,26 +2648,17 @@ bn_powerx5:
call mulx4x_internal
mov 40(%rsp),%rsi # restore %rsp
.cfi_def_cfa %rsi,8
mov \$1,%rax
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lpowerx5_epilogue:
ret
.cfi_endproc
.size bn_powerx5,.-bn_powerx5
.globl bn_sqrx8x_internal
@@ -3470,7 +3248,6 @@ __bn_sqrx8x_reduction:
.align 32
.Lsqrx8x_tail_done:
xor %rax,%rax
add 24+8(%rsp),%r8 # can this overflow?
adc \$0,%r9
adc \$0,%r10
@@ -3478,8 +3255,10 @@ __bn_sqrx8x_reduction:
adc \$0,%r12
adc \$0,%r13
adc \$0,%r14
adc \$0,%r15
adc \$0,%rax
adc \$0,%r15 # can't overflow, because we
# started with "overhung" part
# of multiplication
mov $carry,%rax # xor %rax,%rax
sub 16+8(%rsp),$carry # mov 16(%rsp),%cf
.Lsqrx8x_no_tail: # %cf is 0 if jumped here
@@ -3494,7 +3273,7 @@ __bn_sqrx8x_reduction:
adc 8*5($tptr),%r13
adc 8*6($tptr),%r14
adc 8*7($tptr),%r15
adc \$0,%rax # top-most carry
adc %rax,%rax # top-most carry
mov 32+8(%rsp),%rbx # n0
mov 8*8($tptr,%rcx),%rdx # modulo-scheduled "%r8"
@@ -3736,14 +3515,9 @@ mul_handler:
cmp %r10,%rbx # context->Rip<end of prologue label
jb .Lcommon_seh_tail
mov 4(%r11),%r10d # HandlerData[1]
lea (%rsi,%r10),%r10 # beginning of body label
cmp %r10,%rbx # context->Rip<body label
jb .Lcommon_pop_regs
mov 152($context),%rax # pull context->Rsp
mov 8(%r11),%r10d # HandlerData[2]
mov 4(%r11),%r10d # HandlerData[1]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=epilogue label
jae .Lcommon_seh_tail
@@ -3755,11 +3529,11 @@ mul_handler:
mov 192($context),%r10 # pull $num
mov 8(%rax,%r10,8),%rax # pull saved stack pointer
jmp .Lcommon_pop_regs
jmp .Lbody_proceed
.Lbody_40:
mov 40(%rax),%rax # pull saved stack pointer
.Lcommon_pop_regs:
.Lbody_proceed:
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
@@ -3850,34 +3624,34 @@ $code.=<<___;
.LSEH_info_bn_mul_mont_gather5:
.byte 9,0,0,0
.rva mul_handler
.rva .Lmul_body,.Lmul_body,.Lmul_epilogue # HandlerData[]
.rva .Lmul_body,.Lmul_epilogue # HandlerData[]
.align 8
.LSEH_info_bn_mul4x_mont_gather5:
.byte 9,0,0,0
.rva mul_handler
.rva .Lmul4x_prologue,.Lmul4x_body,.Lmul4x_epilogue # HandlerData[]
.rva .Lmul4x_body,.Lmul4x_epilogue # HandlerData[]
.align 8
.LSEH_info_bn_power5:
.byte 9,0,0,0
.rva mul_handler
.rva .Lpower5_prologue,.Lpower5_body,.Lpower5_epilogue # HandlerData[]
.rva .Lpower5_body,.Lpower5_epilogue # HandlerData[]
.align 8
.LSEH_info_bn_from_mont8x:
.byte 9,0,0,0
.rva mul_handler
.rva .Lfrom_prologue,.Lfrom_body,.Lfrom_epilogue # HandlerData[]
.rva .Lfrom_body,.Lfrom_epilogue # HandlerData[]
___
$code.=<<___ if ($addx);
.align 8
.LSEH_info_bn_mulx4x_mont_gather5:
.byte 9,0,0,0
.rva mul_handler
.rva .Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
.rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
.align 8
.LSEH_info_bn_powerx5:
.byte 9,0,0,0
.rva mul_handler
.rva .Lpowerx5_prologue,.Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[]
.rva .Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[]
___
$code.=<<___;
.align 8
+1 -138
View File
@@ -515,54 +515,6 @@ static bool TestModMul(FileTest *t, BN_CTX *ctx) {
return true;
}
static bool TestModSquare(FileTest *t, BN_CTX *ctx) {
bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
bssl::UniquePtr<BIGNUM> m = GetBIGNUM(t, "M");
bssl::UniquePtr<BIGNUM> mod_square = GetBIGNUM(t, "ModSquare");
if (!a || !m || !mod_square) {
return false;
}
bssl::UniquePtr<BIGNUM> a_copy(BN_new());
bssl::UniquePtr<BIGNUM> ret(BN_new());
if (!ret || !a_copy ||
!BN_mod_mul(ret.get(), a.get(), a.get(), m.get(), ctx) ||
!ExpectBIGNUMsEqual(t, "A * A (mod M)", mod_square.get(), ret.get()) ||
// Repeat the operation with |a_copy|.
!BN_copy(a_copy.get(), a.get()) ||
!BN_mod_mul(ret.get(), a.get(), a_copy.get(), m.get(), ctx) ||
!ExpectBIGNUMsEqual(t, "A * A_copy (mod M)", mod_square.get(),
ret.get())) {
return false;
}
if (BN_is_odd(m.get())) {
// Reduce |a| and test the Montgomery version.
bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
bssl::UniquePtr<BIGNUM> a_tmp(BN_new());
if (!mont || !a_tmp ||
!BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
!BN_nnmod(a_tmp.get(), a.get(), m.get(), ctx) ||
!BN_to_montgomery(a_tmp.get(), a_tmp.get(), mont.get(), ctx) ||
!BN_mod_mul_montgomery(ret.get(), a_tmp.get(), a_tmp.get(), mont.get(),
ctx) ||
!BN_from_montgomery(ret.get(), ret.get(), mont.get(), ctx) ||
!ExpectBIGNUMsEqual(t, "A * A (mod M) (Montgomery)",
mod_square.get(), ret.get()) ||
// Repeat the operation with |a_copy|.
!BN_copy(a_copy.get(), a_tmp.get()) ||
!BN_mod_mul_montgomery(ret.get(), a_tmp.get(), a_copy.get(), mont.get(),
ctx) ||
!BN_from_montgomery(ret.get(), ret.get(), mont.get(), ctx) ||
!ExpectBIGNUMsEqual(t, "A * A_copy (mod M) (Montgomery)",
mod_square.get(), ret.get())) {
return false;
}
}
return true;
}
static bool TestModExp(FileTest *t, BN_CTX *ctx) {
bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
bssl::UniquePtr<BIGNUM> e = GetBIGNUM(t, "E");
@@ -697,7 +649,6 @@ static const Test kTests[] = {
{"Product", TestProduct},
{"Quotient", TestQuotient},
{"ModMul", TestModMul},
{"ModSquare", TestModSquare},
{"ModExp", TestModExp},
{"Exp", TestExp},
{"ModSqrt", TestModSqrt},
@@ -1668,93 +1619,6 @@ static bool TestBNSetGetU64() {
return true;
}
static bool TestBNPow2(BN_CTX *ctx) {
bssl::UniquePtr<BIGNUM>
power_of_two(BN_new()),
random(BN_new()),
expected(BN_new()),
actual(BN_new());
if (!power_of_two.get() ||
!random.get() ||
!expected.get() ||
!actual.get()) {
return false;
}
// Choose an exponent.
for (size_t e = 3; e < 512; e += 11) {
// Choose a bit length for our randoms.
for (int len = 3; len < 512; len += 23) {
// Set power_of_two = 2^e.
if (!BN_lshift(power_of_two.get(), BN_value_one(), (int) e)) {
fprintf(stderr, "Failed to shiftl.\n");
return false;
}
// Test BN_is_pow2 on power_of_two.
if (!BN_is_pow2(power_of_two.get())) {
fprintf(stderr, "BN_is_pow2 returned false for a power of two.\n");
hexdump(stderr, "Arg: ", power_of_two->d,
power_of_two->top * sizeof(BN_ULONG));
return false;
}
// Pick a large random value, ensuring it isn't a power of two.
if (!BN_rand(random.get(), len, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY)) {
fprintf(stderr, "Failed to generate random in TestBNPow2.\n");
return false;
}
// Test BN_is_pow2 on |r|.
if (BN_is_pow2(random.get())) {
fprintf(stderr, "BN_is_pow2 returned true for a non-power of two.\n");
hexdump(stderr, "Arg: ", random->d, random->top * sizeof(BN_ULONG));
return false;
}
// Test BN_mod_pow2 on |r|.
if (!BN_mod(expected.get(), random.get(), power_of_two.get(), ctx) ||
!BN_mod_pow2(actual.get(), random.get(), e) ||
BN_cmp(actual.get(), expected.get())) {
fprintf(stderr, "BN_mod_pow2 returned the wrong value:\n");
hexdump(stderr, "Expected: ", expected->d,
expected->top * sizeof(BN_ULONG));
hexdump(stderr, "Got: ", actual->d,
actual->top * sizeof(BN_ULONG));
return false;
}
// Test BN_nnmod_pow2 on |r|.
if (!BN_nnmod(expected.get(), random.get(), power_of_two.get(), ctx) ||
!BN_nnmod_pow2(actual.get(), random.get(), e) ||
BN_cmp(actual.get(), expected.get())) {
fprintf(stderr, "BN_nnmod_pow2 failed on positive input:\n");
hexdump(stderr, "Expected: ", expected->d,
expected->top * sizeof(BN_ULONG));
hexdump(stderr, "Got: ", actual->d,
actual->top * sizeof(BN_ULONG));
return false;
}
// Test BN_nnmod_pow2 on -|r|.
BN_set_negative(random.get(), 1);
if (!BN_nnmod(expected.get(), random.get(), power_of_two.get(), ctx) ||
!BN_nnmod_pow2(actual.get(), random.get(), e) ||
BN_cmp(actual.get(), expected.get())) {
fprintf(stderr, "BN_nnmod_pow2 failed on negative input:\n");
hexdump(stderr, "Expected: ", expected->d,
expected->top * sizeof(BN_ULONG));
hexdump(stderr, "Got: ", actual->d,
actual->top * sizeof(BN_ULONG));
return false;
}
}
}
return true;
}
int main(int argc, char *argv[]) {
CRYPTO_library_init();
@@ -1782,8 +1646,7 @@ int main(int argc, char *argv[]) {
!TestSmallPrime(ctx.get()) ||
!TestCmpWord() ||
!TestBN2Dec() ||
!TestBNSetGetU64() ||
!TestBNPow2(ctx.get())) {
!TestBNSetGetU64()) {
return 1;
}
-10
View File
@@ -9888,16 +9888,6 @@ B = 7878787878787878787878787878787878787878787878787878787878787878787878787878
M = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf
# ModSquare tests.
#
# These test vectors satisfy A * A = ModSquare (mod M) and 0 <= ModSquare < M.
# Regression test for CVE-2017-3732.
ModSquare = fffffffdfffffd01000009000002f6fffdf403000312000402f3fff5f602fe080a0005fdfafffa00010001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000002000002fefffff7fffffd07000109fdfffef3fffdfd06000405ff00fdfbfffe00010001
A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff00000000
M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff
# ModExp tests.
#
# These test vectors satisfy A ^ E = ModExp (mod M) and 0 <= ModExp < M.
-14
View File
@@ -212,20 +212,6 @@ int BN_is_odd(const BIGNUM *bn) {
return bn->top > 0 && (bn->d[0] & 1) == 1;
}
int BN_is_pow2(const BIGNUM *bn) {
if (bn->top == 0 || bn->neg) {
return 0;
}
for (int i = 0; i < bn->top - 1; i++) {
if (bn->d[i] != 0) {
return 0;
}
}
return 0 == (bn->d[bn->top-1] & (bn->d[bn->top-1] - 1));
}
int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) {
if (a->top != b->top) {
return 0;
-80
View File
@@ -58,7 +58,6 @@
#include <assert.h>
#include <limits.h>
#include <openssl/err.h>
#include "internal.h"
@@ -647,82 +646,3 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
}
return (BN_ULONG)ret;
}
int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
if (e == 0 || a->top == 0) {
BN_zero(r);
return 1;
}
size_t num_words = 1 + ((e - 1) / BN_BITS2);
/* If |a| definitely has less than |e| bits, just BN_copy. */
if ((size_t) a->top < num_words) {
return BN_copy(r, a) != NULL;
}
/* Otherwise, first make sure we have enough space in |r|.
* Note that this will fail if num_words > INT_MAX. */
if (bn_wexpand(r, num_words) == NULL) {
return 0;
}
/* Copy the content of |a| into |r|. */
OPENSSL_memcpy(r->d, a->d, num_words * sizeof(BN_ULONG));
/* If |e| isn't word-aligned, we have to mask off some of our bits. */
size_t top_word_exponent = e % (sizeof(BN_ULONG) * 8);
if (top_word_exponent != 0) {
r->d[num_words - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
}
/* Fill in the remaining fields of |r|. */
r->neg = a->neg;
r->top = (int) num_words;
bn_correct_top(r);
return 1;
}
int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
if (!BN_mod_pow2(r, a, e)) {
return 0;
}
/* If the returned value was non-negative, we're done. */
if (BN_is_zero(r) || !r->neg) {
return 1;
}
size_t num_words = 1 + (e - 1) / BN_BITS2;
/* Expand |r| to the size of our modulus. */
if (bn_wexpand(r, num_words) == NULL) {
return 0;
}
/* Clear the upper words of |r|. */
OPENSSL_memset(&r->d[r->top], 0, (num_words - r->top) * BN_BYTES);
/* Set parameters of |r|. */
r->neg = 0;
r->top = (int) num_words;
/* Now, invert every word. The idea here is that we want to compute 2^e-|x|,
* which is actually equivalent to the twos-complement representation of |x|
* in |e| bits, which is -x = ~x + 1. */
for (int i = 0; i < r->top; i++) {
r->d[i] = ~r->d[i];
}
/* If our exponent doesn't span the top word, we have to mask the rest. */
size_t top_word_exponent = e % BN_BITS2;
if (top_word_exponent != 0) {
r->d[r->top - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
}
/* Keep the correct_top invariant for BN_add. */
bn_correct_top(r);
/* Finally, add one, for the reason described above. */
return BN_add(r, r, BN_value_one());
}
+18 -39
View File
@@ -125,11 +125,6 @@
#define OPENSSL_BN_ASM_MONT
#endif
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
const BIGNUM *b,
const BN_MONT_CTX *mont, BN_CTX *ctx);
BN_MONT_CTX *BN_MONT_CTX_new(void) {
BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
@@ -366,43 +361,27 @@ err:
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BN_MONT_CTX *mont, BN_CTX *ctx) {
#if !defined(OPENSSL_BN_ASM_MONT)
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
#else
int num = mont->N.top;
/* |bn_mul_mont| requires at least 128 bits of limbs, at least for x86. */
if (num < (128 / BN_BITS2) ||
a->top != num ||
b->top != num) {
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
}
if (bn_wexpand(r, num) == NULL) {
return 0;
}
if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
/* The check above ensures this won't happen. */
assert(0);
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
return 0;
}
r->neg = a->neg ^ b->neg;
r->top = num;
bn_correct_top(r);
return 1;
#endif
}
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
const BIGNUM *b,
const BN_MONT_CTX *mont,
BN_CTX *ctx) {
BIGNUM *tmp;
int ret = 0;
#if defined(OPENSSL_BN_ASM_MONT)
int num = mont->N.top;
if (num > 1 && a->top == num && b->top == num) {
if (bn_wexpand(r, num) == NULL) {
return 0;
}
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
r->neg = a->neg ^ b->neg;
r->top = num;
bn_correct_top(r);
return 1;
}
}
#endif
BN_CTX_start(ctx);
BIGNUM *tmp = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL) {
goto err;
}
+4 -4
View File
@@ -148,7 +148,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
}
q->neg = 0;
if (!BN_add_word(q, 1) ||
!BN_mod_exp_mont(ret, A, q, p, ctx, NULL)) {
!BN_mod_exp(ret, A, q, p, ctx)) {
goto end;
}
err = 0;
@@ -193,7 +193,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
goto end;
}
q->neg = 0;
if (!BN_mod_exp_mont(b, t, q, p, ctx, NULL)) {
if (!BN_mod_exp(b, t, q, p, ctx)) {
goto end;
}
@@ -281,7 +281,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
/* Now that we have some non-square, we can find an element
* of order 2^e by computing its q'th power. */
if (!BN_mod_exp_mont(y, y, q, p, ctx, NULL)) {
if (!BN_mod_exp(y, y, q, p, ctx)) {
goto end;
}
if (BN_is_one(y)) {
@@ -327,7 +327,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
goto end;
}
} else {
if (!BN_mod_exp_mont(x, A, t, p, ctx, NULL)) {
if (!BN_mod_exp(x, A, t, p, ctx)) {
goto end;
}
if (BN_is_zero(x)) {
+1 -1
View File
@@ -38,7 +38,7 @@ static int is_string_type(unsigned tag) {
case CBS_ASN1_UTF8STRING:
case CBS_ASN1_NUMERICSTRING:
case CBS_ASN1_PRINTABLESTRING:
case CBS_ASN1_T61STRING:
case CBS_ASN1_T16STRING:
case CBS_ASN1_VIDEOTEXSTRING:
case CBS_ASN1_IA5STRING:
case CBS_ASN1_GRAPHICSTRING:
+11 -1
View File
@@ -42,7 +42,17 @@ add_library(
${CHACHA_ARCH_SOURCES}
)
add_executable(
chacha_test
chacha_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(chacha_test crypto)
add_dependencies(all_tests chacha_test)
perlasm(chacha-armv4.${ASM_EXT} asm/chacha-armv4.pl)
perlasm(chacha-armv8.${ASM_EXT} asm/chacha-armv8.pl)
perlasm(chacha-x86.${ASM_EXT} asm/chacha-x86.pl)
perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl)
perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl)
+3 -3
View File
@@ -8,7 +8,7 @@
# ====================================================================
#
# December 2014
#
#
# ChaCha20 for ARMv4.
#
# Performance in cycles per byte out of large buffer.
@@ -713,7 +713,7 @@ ChaCha20_neon:
vadd.i32 $d2,$d1,$t0 @ counter+2
str @t[3], [sp,#4*(16+15)]
mov @t[3],#10
add @x[12],@x[12],#3 @ counter+3
add @x[12],@x[12],#3 @ counter+3
b .Loop_neon
.align 4
@@ -1127,7 +1127,7 @@ $code.=<<___;
ldrb @t[1],[r12],#1 @ read input
subs @t[3],@t[3],#1
eor @t[0],@t[0],@t[1]
strb @t[0],[r14],#1 @ store output
strb @t[0],[r14],#1 @ store ouput
bne .Loop_tail_neon
.Ldone_neon:
+2 -2
View File
@@ -8,7 +8,7 @@
# ====================================================================
#
# June 2015
#
#
# ChaCha20 for ARMv8.
#
# Performance in cycles per byte out of large buffer.
@@ -193,7 +193,7 @@ ChaCha20_ctr32:
mov $ctr,#10
subs $len,$len,#64
.Loop:
sub $ctr,$ctr,#1
sub $ctr,$ctr,#1
___
foreach (&ROUND(0, 4, 8,12)) { eval; }
foreach (&ROUND(0, 5,10,15)) { eval; }
+4 -11
View File
@@ -21,9 +21,7 @@
# Westmere 9.50/+45% 3.35
# Sandy Bridge 10.5/+47% 3.20
# Haswell 8.15/+50% 2.83
# Skylake 7.53/+22% 2.75
# Silvermont 17.4/+36% 8.35
# Goldmont 13.4/+40% 4.36
# Sledgehammer 10.2/+54%
# Bulldozer 13.4/+50% 4.38(*)
#
@@ -40,8 +38,10 @@ open STDOUT,">$output";
&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386");
$xmm=$ymm=1;
$gasver=999; # enable everything
$xmm=$ymm=0;
for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); }
$ymm=$xmm;
$a="eax";
($b,$b_)=("ebx","ebp");
@@ -438,12 +438,6 @@ my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous
&label("pic_point"),"eax"));
&movdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce
if (defined($gasver) && $gasver>=2.17) { # even though we encode
# pshufb manually, we
# handle only register
# operands, while this
# segment uses memory
# operand...
&cmp ($len,64*4);
&jb (&label("1x"));
@@ -625,7 +619,6 @@ if (defined($gasver) && $gasver>=2.17) { # even though we encode
&paddd ("xmm2",&QWP(16*6,"eax")); # +four
&pand ("xmm3",&QWP(16*7,"eax"));
&por ("xmm3","xmm2"); # counter value
}
{
my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7));
File diff suppressed because it is too large Load Diff
+28 -14
View File
@@ -18,13 +18,10 @@
#include <memory>
#include <gtest/gtest.h>
#include <openssl/crypto.h>
#include <openssl/chacha.h>
#include "../internal.h"
#include "../test/test_util.h"
static const uint8_t kKey[32] = {
@@ -219,18 +216,35 @@ static const uint8_t kOutput[] = {
static_assert(sizeof(kInput) == sizeof(kOutput),
"Input and output lengths don't match.");
TEST(ChaChaTest, TestVector) {
static bool TestChaCha20(size_t len) {
std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter);
if (OPENSSL_memcmp(buf.get(), kOutput, len) != 0) {
fprintf(stderr, "Mismatch at length %zu.\n", len);
return false;
}
// Test in-place.
OPENSSL_memcpy(buf.get(), kInput, len);
CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kCounter);
if (OPENSSL_memcmp(buf.get(), kOutput, len) != 0) {
fprintf(stderr, "Mismatch at length %zu, in-place.\n", len);
return false;
}
return true;
}
int main(int argc, char **argv) {
CRYPTO_library_init();
// Run the test with the test vector at all lengths.
for (size_t len = 0; len <= sizeof(kInput); len++) {
SCOPED_TRACE(len);
std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter);
EXPECT_EQ(Bytes(kOutput, len), Bytes(buf.get(), len));
// Test the in-place version.
OPENSSL_memcpy(buf.get(), kInput, len);
CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kCounter);
EXPECT_EQ(Bytes(kOutput, len), Bytes(buf.get(), len));
if (!TestChaCha20(len)) {
return 1;
}
}
printf("PASS\n");
return 0;
}
-12
View File
@@ -1,13 +1,5 @@
include_directories(../../include)
if (${ARCH} STREQUAL "x86_64")
set(
CIPHER_ARCH_SOURCES
chacha20_poly1305_x86_64.${ASM_EXT}
)
endif()
add_library(
cipher
@@ -27,8 +19,6 @@ add_library(
tls_cbc.c
e_tls.c
e_ssl3.c
${CIPHER_ARCH_SOURCES}
)
add_executable(
@@ -45,8 +35,6 @@ add_executable(
$<TARGET_OBJECTS:test_support>
)
perlasm(chacha20_poly1305_x86_64.${ASM_EXT} asm/chacha20_poly1305_x86_64.pl)
target_link_libraries(cipher_test crypto)
target_link_libraries(aead_test crypto)
add_dependencies(all_tests cipher_test aead_test)
+28 -106
View File
@@ -12,7 +12,6 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <assert.h>
#include <stdint.h>
#include <string.h>
@@ -169,12 +168,16 @@ static bool TestAEAD(FileTest *t, void *arg) {
}
static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
EVP_AEAD_CTX ctx;
uint8_t key[128];
OPENSSL_memset(key, 0, sizeof(key));
const size_t key_len = EVP_AEAD_key_length(aead);
assert(sizeof(key) >= key_len);
if (key_len > sizeof(key)) {
fprintf(stderr, "Key length of AEAD too long.\n");
return 0;
}
EVP_AEAD_CTX ctx;
if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
9999 /* a silly tag length to trigger an error */,
NULL /* ENGINE */) != 0) {
@@ -198,80 +201,6 @@ static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
return 1;
}
static int TestTruncatedTags(const EVP_AEAD *aead) {
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
OPENSSL_memset(key, 0, sizeof(key));
const size_t key_len = EVP_AEAD_key_length(aead);
assert(sizeof(key) >= key_len);
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
OPENSSL_memset(nonce, 0, sizeof(nonce));
const size_t nonce_len = EVP_AEAD_nonce_length(aead);
assert(sizeof(nonce) >= nonce_len);
bssl::ScopedEVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key, key_len, 1 /* one byte tag */,
NULL /* ENGINE */)) {
fprintf(stderr, "Couldn't initialise AEAD with truncated tag.\n");
return 1;
}
const uint8_t plaintext[1] = {'A'};
uint8_t ciphertext[128];
size_t ciphertext_len;
constexpr uint8_t kSentinel = 42;
OPENSSL_memset(ciphertext, kSentinel, sizeof(ciphertext));
if (!EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
sizeof(ciphertext), nonce, nonce_len, plaintext,
sizeof(plaintext), nullptr /* ad */, 0)) {
fprintf(stderr, "Sealing with truncated tag didn't work.\n");
return 0;
}
for (size_t i = ciphertext_len; i < sizeof(ciphertext); i++) {
// Sealing must not write past where it said it did.
if (ciphertext[i] != kSentinel) {
fprintf(stderr, "Sealing wrote off the end of the buffer.\n");
return 0;
}
}
const size_t overhead_used = ciphertext_len - sizeof(plaintext);
if (overhead_used != 1) {
fprintf(stderr, "AEAD is probably ignoring request to truncate tags.\n");
return 0;
}
uint8_t plaintext2[sizeof(plaintext) + 16];
OPENSSL_memset(plaintext2, kSentinel, sizeof(plaintext2));
size_t plaintext2_len;
if (!EVP_AEAD_CTX_open(ctx.get(), plaintext2, &plaintext2_len,
sizeof(plaintext2), nonce, nonce_len, ciphertext,
ciphertext_len, nullptr /* ad */, 0)) {
fprintf(stderr, "Opening with truncated tag didn't work.\n");
return 0;
}
for (size_t i = plaintext2_len; i < sizeof(plaintext2); i++) {
// Likewise, opening should also stay within bounds.
if (plaintext2[i] != kSentinel) {
fprintf(stderr, "Opening wrote off the end of the buffer.\n");
return 0;
}
}
if (plaintext2_len != sizeof(plaintext) ||
OPENSSL_memcmp(plaintext2, plaintext, sizeof(plaintext)) != 0) {
fprintf(stderr, "Opening with truncated tag gave wrong result.\n");
return 0;
}
return 1;
}
static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
const size_t key_len = EVP_AEAD_key_length(aead);
const size_t nonce_len = EVP_AEAD_nonce_length(aead);
@@ -377,32 +306,30 @@ struct KnownAEAD {
// handle inputs that are a multiple of eight bytes in length and the
// SSLv3/TLS AEADs have the concept of “direction”.
bool limited_implementation;
// truncated_tags is true if the AEAD supports truncating tags to arbitrary
// lengths.
bool truncated_tags;
};
static const struct KnownAEAD kAEADs[] = {
{ "aes-128-gcm", EVP_aead_aes_128_gcm, false, true },
{ "aes-256-gcm", EVP_aead_aes_256_gcm, false, true },
{ "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false, false },
{ "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false, false },
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false, true },
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true, false },
{ "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true, false },
{ "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true, false },
{ "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true, false },
{ "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true, false },
{ "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true, false },
{ "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true, false },
{ "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true, false },
{ "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true, false },
{ "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true, false },
{ "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true, false },
{ "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true, false },
{ "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false, true },
{ "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false, true },
{ "", NULL, false, false },
{ "aes-128-gcm", EVP_aead_aes_128_gcm, false },
{ "aes-256-gcm", EVP_aead_aes_256_gcm, false },
{ "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false },
{ "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false },
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false },
{ "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false },
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true },
{ "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true },
{ "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true },
{ "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true },
{ "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true },
{ "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true },
{ "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true },
{ "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true },
{ "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true },
{ "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true },
{ "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true },
{ "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true },
{ "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false },
{ "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false },
{ "", NULL, false },
};
int main(int argc, char **argv) {
@@ -436,11 +363,6 @@ int main(int argc, char **argv) {
return 1;
}
if (known_aead->truncated_tags && !TestTruncatedTags(aead)) {
fprintf(stderr, "Truncated tags test failed for %s.\n", known_aead->name);
return 1;
}
if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
return 1;
File diff suppressed because it is too large Load Diff
+1 -5
View File
@@ -132,7 +132,6 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) {
if (in->cipher_data && in->cipher->ctx_size) {
out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
if (!out->cipher_data) {
out->cipher = NULL;
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -140,10 +139,7 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) {
}
if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) {
if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out)) {
out->cipher = NULL;
return 0;
}
return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
}
return 1;
+27 -42
View File
@@ -1448,7 +1448,6 @@ const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void) {
#if !defined(OPENSSL_SMALL)
#define EVP_AEAD_AES_GCM_SIV_NONCE_LEN 12
#define EVP_AEAD_AES_GCM_SIV_TAG_LEN 16
struct aead_aes_gcm_siv_ctx {
@@ -1549,10 +1548,9 @@ static void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
/* gcm_siv_polyval evaluates POLYVAL at |auth_key| on the given plaintext and
* AD. The result is written to |out_tag|. */
static void gcm_siv_polyval(
uint8_t out_tag[16], const uint8_t *in, size_t in_len, const uint8_t *ad,
size_t ad_len, const uint8_t auth_key[16],
const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
static void gcm_siv_polyval(uint8_t out_tag[16], const uint8_t *in,
size_t in_len, const uint8_t *ad, size_t ad_len,
const uint8_t auth_key[16]) {
struct polyval_ctx polyval_ctx;
CRYPTO_POLYVAL_init(&polyval_ctx, auth_key);
@@ -1586,9 +1584,6 @@ static void gcm_siv_polyval(
sizeof(length_block));
CRYPTO_POLYVAL_finish(&polyval_ctx, out_tag);
for (size_t i = 0; i < EVP_AEAD_AES_GCM_SIV_NONCE_LEN; i++) {
out_tag[i] ^= nonce[i];
}
out_tag[15] &= 0x7f;
}
@@ -1607,26 +1602,22 @@ struct gcm_siv_record_keys {
static void gcm_siv_keys(
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
struct gcm_siv_record_keys *out_keys,
const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_TAG_LEN]) {
const AES_KEY *const key = &gcm_siv_ctx->ks.ks;
uint8_t key_material[(128 /* POLYVAL key */ + 256 /* max AES key */) / 8];
const size_t blocks_needed = gcm_siv_ctx->is_256 ? 6 : 4;
gcm_siv_ctx->kgk_block(nonce, out_keys->auth_key, key);
uint8_t counter[AES_BLOCK_SIZE];
OPENSSL_memset(counter, 0, AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
OPENSSL_memcpy(counter + AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN,
nonce, EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
for (size_t i = 0; i < blocks_needed; i++) {
counter[0] = i;
uint8_t ciphertext[AES_BLOCK_SIZE];
gcm_siv_ctx->kgk_block(counter, ciphertext, key);
OPENSSL_memcpy(&key_material[i * 8], ciphertext, 8);
if (gcm_siv_ctx->is_256) {
uint8_t record_enc_key[32];
gcm_siv_ctx->kgk_block(out_keys->auth_key, record_enc_key + 16, key);
gcm_siv_ctx->kgk_block(record_enc_key + 16, record_enc_key, key);
aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
record_enc_key, sizeof(record_enc_key));
} else {
uint8_t record_enc_key[16];
gcm_siv_ctx->kgk_block(out_keys->auth_key, record_enc_key, key);
aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
record_enc_key, sizeof(record_enc_key));
}
OPENSSL_memcpy(out_keys->auth_key, key_material, 16);
aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
}
static int aead_aes_gcm_siv_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
@@ -1650,7 +1641,7 @@ static int aead_aes_gcm_siv_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
if (nonce_len != AES_BLOCK_SIZE) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
@@ -1659,7 +1650,7 @@ static int aead_aes_gcm_siv_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
uint8_t tag[16];
gcm_siv_polyval(tag, in, in_len, ad, ad_len, keys.auth_key, nonce);
gcm_siv_polyval(tag, in, in_len, ad, ad_len, keys.auth_key);
keys.enc_block(tag, tag, &keys.enc_key.ks);
gcm_siv_crypt(out, in, in_len, tag, keys.enc_block, &keys.enc_key.ks);
@@ -1688,11 +1679,6 @@ static int aead_aes_gcm_siv_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
@@ -1708,8 +1694,7 @@ static int aead_aes_gcm_siv_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
&keys.enc_key.ks);
uint8_t expected_tag[EVP_AEAD_AES_GCM_SIV_TAG_LEN];
gcm_siv_polyval(expected_tag, out, plaintext_len, ad, ad_len, keys.auth_key,
nonce);
gcm_siv_polyval(expected_tag, out, plaintext_len, ad, ad_len, keys.auth_key);
keys.enc_block(expected_tag, expected_tag, &keys.enc_key.ks);
if (CRYPTO_memcmp(expected_tag, &in[plaintext_len], sizeof(expected_tag)) !=
@@ -1723,10 +1708,10 @@ static int aead_aes_gcm_siv_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
}
static const EVP_AEAD aead_aes_128_gcm_siv = {
16, /* key length */
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
16, /* key length */
AES_BLOCK_SIZE, /* nonce length */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
aead_aes_gcm_siv_init,
NULL /* init_with_direction */,
@@ -1737,10 +1722,10 @@ static const EVP_AEAD aead_aes_128_gcm_siv = {
};
static const EVP_AEAD aead_aes_256_gcm_siv = {
32, /* key length */
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
32, /* key length */
AES_BLOCK_SIZE, /* nonce length */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
aead_aes_gcm_siv_init,
NULL /* init_with_direction */,
+133 -109
View File
@@ -18,7 +18,6 @@
#include <openssl/chacha.h>
#include <openssl/cipher.h>
#include <openssl/cpu.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/poly1305.h>
@@ -34,51 +33,6 @@ struct aead_chacha20_poly1305_ctx {
unsigned char tag_len;
};
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
!defined(OPENSSL_WINDOWS)
static int asm_capable(void) {
const int sse41_capable = (OPENSSL_ia32cap_P[1] & (1 << 19)) != 0;
return sse41_capable;
}
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It
// decrypts |plaintext_len| bytes from |ciphertext| and writes them to
// |out_plaintext|. On entry, |aead_data| must contain the final 48 bytes of
// the initial ChaCha20 block, i.e. the key, followed by four zeros, followed
// by the nonce. On exit, it will contain the calculated tag value, which the
// caller must check.
extern void chacha20_poly1305_open(uint8_t *out_plaintext,
const uint8_t *ciphertext,
size_t plaintext_len, const uint8_t *ad,
size_t ad_len, uint8_t *aead_data);
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It
// encrypts |plaintext_len| bytes from |plaintext| and writes them to
// |out_ciphertext|. On entry, |aead_data| must contain the final 48 bytes of
// the initial ChaCha20 block, i.e. the key, followed by four zeros, followed
// by the nonce. On exit, it will contain the calculated tag value, which the
// caller must append to the ciphertext.
extern void chacha20_poly1305_seal(uint8_t *out_ciphertext,
const uint8_t *plaintext,
size_t plaintext_len, const uint8_t *ad,
size_t ad_len, uint8_t *aead_data);
#else
static int asm_capable(void) {
return 0;
}
static void chacha20_poly1305_open(uint8_t *out_plaintext,
const uint8_t *ciphertext,
size_t plaintext_len, const uint8_t *ad,
size_t ad_len, uint8_t *aead_data) {}
static void chacha20_poly1305_seal(uint8_t *out_ciphertext,
const uint8_t *plaintext,
size_t plaintext_len, const uint8_t *ad,
size_t ad_len, uint8_t *aead_data) {}
#endif
static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
struct aead_chacha20_poly1305_ctx *c20_ctx;
@@ -116,8 +70,9 @@ static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) {
static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
uint8_t length_bytes[8];
unsigned i;
for (unsigned i = 0; i < sizeof(length_bytes); i++) {
for (i = 0; i < sizeof(length_bytes); i++) {
length_bytes[i] = data_len;
data_len >>= 8;
}
@@ -125,49 +80,37 @@ 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. */
typedef void (*aead_poly1305_update)(poly1305_state *ctx, const uint8_t *ad,
size_t ad_len, const uint8_t *ciphertext,
size_t ciphertext_len);
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) {
/* aead_poly1305 fills |tag| with the authentication tag for the given
* inputs, using |update| to control the order and format that the inputs are
* signed/authenticated. */
static void aead_poly1305(aead_poly1305_update update,
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) {
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);
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);
poly1305_update_length(&ctx, ad_len);
poly1305_update_length(&ctx, ciphertext_len);
update(&ctx, ad, ad_len, ciphertext, ciphertext_len);
CRYPTO_poly1305_finish(&ctx, tag);
}
static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
static int seal_impl(aead_poly1305_update poly1305_update,
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t nonce[12],
const uint8_t *in, size_t in_len, const uint8_t *ad,
size_t ad_len) {
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
const uint64_t in_len_64 = in_len;
if (nonce_len != 12) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
/* |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
* individual operations that work on more than 256GB at a time.
* |in_len_64| is needed because, on 32-bit platforms, size_t is only
@@ -189,37 +132,25 @@ static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}
alignas(16) uint8_t tag[48];
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
if (asm_capable()) {
OPENSSL_memcpy(tag, c20_ctx->key, 32);
OPENSSL_memset(tag + 32, 0, 4);
OPENSSL_memcpy(tag + 32 + 4, nonce, 12);
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);
}
alignas(16) uint8_t tag[POLY1305_TAG_LEN];
aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, out, in_len);
OPENSSL_memcpy(out + in_len, tag, c20_ctx->tag_len);
*out_len = in_len + c20_ctx->tag_len;
return 1;
}
static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
static int open_impl(aead_poly1305_update poly1305_update,
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t nonce[12],
const uint8_t *in, size_t in_len, const uint8_t *ad,
size_t ad_len) {
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
size_t plaintext_len;
const uint64_t in_len_64 = in_len;
if (nonce_len != 12) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
if (in_len < c20_ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
@@ -237,27 +168,64 @@ static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
}
plaintext_len = in_len - c20_ctx->tag_len;
alignas(16) uint8_t tag[48];
if (asm_capable()) {
OPENSSL_memcpy(tag, c20_ctx->key, 32);
OPENSSL_memset(tag + 32, 0, 4);
OPENSSL_memcpy(tag + 32 + 4, nonce, 12);
chacha20_poly1305_open(out, in, plaintext_len, ad, ad_len, tag);
} else {
calc_tag(tag, c20_ctx, nonce, ad, ad_len, in, plaintext_len);
CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
}
alignas(16) uint8_t tag[POLY1305_TAG_LEN];
aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, in,
plaintext_len);
if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
*out_len = plaintext_len;
return 1;
}
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));
}
}
static void poly1305_update(poly1305_state *ctx, const uint8_t *ad,
size_t ad_len, const uint8_t *ciphertext,
size_t ciphertext_len) {
poly1305_update_padded_16(ctx, ad, ad_len);
poly1305_update_padded_16(ctx, ciphertext, ciphertext_len);
poly1305_update_length(ctx, ad_len);
poly1305_update_length(ctx, ciphertext_len);
}
static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
if (nonce_len != 12) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
return seal_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
in_len, ad, ad_len);
}
static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
if (nonce_len != 12) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
return open_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
in_len, ad, ad_len);
}
static const EVP_AEAD aead_chacha20_poly1305 = {
32, /* key len */
12, /* nonce len */
@@ -274,3 +242,59 @@ static const EVP_AEAD aead_chacha20_poly1305 = {
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
return &aead_chacha20_poly1305;
}
static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad,
size_t ad_len, const uint8_t *ciphertext,
size_t ciphertext_len) {
CRYPTO_poly1305_update(ctx, ad, ad_len);
poly1305_update_length(ctx, ad_len);
CRYPTO_poly1305_update(ctx, ciphertext, ciphertext_len);
poly1305_update_length(ctx, ciphertext_len);
}
static int aead_chacha20_poly1305_old_seal(
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
if (nonce_len != 8) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
uint8_t nonce_96[12];
OPENSSL_memset(nonce_96, 0, 4);
OPENSSL_memcpy(nonce_96 + 4, nonce, 8);
return seal_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
nonce_96, in, in_len, ad, ad_len);
}
static int aead_chacha20_poly1305_old_open(
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
if (nonce_len != 8) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
uint8_t nonce_96[12];
OPENSSL_memset(nonce_96, 0, 4);
OPENSSL_memcpy(nonce_96 + 4, nonce, 8);
return open_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
nonce_96, in, in_len, ad, ad_len);
}
static const EVP_AEAD aead_chacha20_poly1305_old = {
32, /* key len */
8, /* nonce len */
POLY1305_TAG_LEN, /* overhead */
POLY1305_TAG_LEN, /* max tag length */
aead_chacha20_poly1305_init,
NULL, /* init_with_direction */
aead_chacha20_poly1305_cleanup,
aead_chacha20_poly1305_old_seal,
aead_chacha20_poly1305_old_open,
NULL, /* get_iv */
};
const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void) {
return &aead_chacha20_poly1305_old;
}
+6 -6
View File
@@ -262,24 +262,24 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
/* Remove CBC padding. Code from here on is timing-sensitive with respect to
* |padding_ok| and |data_plus_mac_len| for CBC ciphers. */
size_t padding_ok, data_plus_mac_len;
unsigned padding_ok, data_plus_mac_len;
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
if (!EVP_tls_cbc_remove_padding(
&padding_ok, &data_plus_mac_len, out, total,
EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
HMAC_size(&tls_ctx->hmac_ctx))) {
(unsigned)HMAC_size(&tls_ctx->hmac_ctx))) {
/* Publicly invalid. This can be rejected in non-constant time. */
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
} else {
padding_ok = CONSTTIME_TRUE_S;
padding_ok = ~0u;
data_plus_mac_len = total;
/* |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has
* already been checked against the MAC size at the top of the function. */
assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx));
}
size_t data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
unsigned data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
/* At this point, if the padding is valid, the first |data_plus_mac_len| bytes
* after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is
@@ -332,8 +332,8 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
* safe to simply perform the padding check first, but it would not be under a
* different choice of MAC location on padding failure. See
* EVP_tls_cbc_remove_padding. */
size_t good =
constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len), 0);
unsigned good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len),
0);
good &= padding_ok;
if (!good) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+6 -5
View File
@@ -110,9 +110,9 @@ struct evp_aead_st {
* If the function returns one, it runs in time independent of the contents of
* |in|. It is also guaranteed that |*out_len| >= |mac_size|, satisfying
* |EVP_tls_cbc_copy_mac|'s precondition. */
int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
const uint8_t *in, size_t in_len,
size_t block_size, size_t mac_size);
int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
const uint8_t *in, unsigned in_len,
unsigned block_size, unsigned mac_size);
/* EVP_tls_cbc_copy_mac copies |md_size| bytes from the end of the first
* |in_len| bytes of |in| to |out| in constant time (independent of the concrete
@@ -122,8 +122,9 @@ int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
* On entry:
* orig_len >= in_len >= md_size
* md_size <= EVP_MAX_MD_SIZE */
void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
size_t in_len, size_t orig_len);
void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
const uint8_t *in, unsigned in_len,
unsigned orig_len);
/* EVP_tls_cbc_record_digest_supported returns 1 iff |md| is a hash function
* which EVP_tls_cbc_digest_record supports. */
+170 -58
View File
@@ -1,133 +1,245 @@
# This is the example from
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#section-8
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#section-8
KEY: ee8e1ed9ff2540ae8f2ba9f50bc2f27c
NONCE: 752abad3e0afb5f434dc4310
NONCE: 752abad3e0afb5f434dc4310f71f3d21
IN: "Hello world"
AD: "example"
CT: 5d349ead175ef6b1def6fd
TAG: 4fbcdeb7e4793f4a1d7e4faa70100af1
CT: 810649724764545b3625ff
TAG: 010a10f4942710781d2948ac0192572f
# Test vectors from
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#appendix-C
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-B
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN:
AD:
CT:
TAG: dc20e2d83f25705bb49e439eca56de25
TAG: cb52de357fad226ae428d0ed5a575496
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0100000000000000
AD:
CT: b5d839330ac7b786
TAG: 578782fff6013b815b287c22493a364c
CT: 7e139f58002d68ee
TAG: 715835541f2136f03b6dc80ae0a8ac46
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 010000000000000000000000
AD:
CT: 7323ea61d05932260047d942
TAG: a4978db357391a0bc4fdec8b0d106639
CT: 4a87f0cd26e5d5086e90da02
TAG: 4dff905e48d512e9c34ae8f3be66ec43
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 01000000000000000000000000000000
AD:
CT: 743f7c8077ab25f8624e2e948579cf77
TAG: 303aaf90f6fe21199c6068577437a0c4
CT: 048ca58c46d2368ce00132389f40b511
TAG: 971da9aa385283522c4f67a9aedb37e5
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0100000000000000000000000000000002000000000000000000000000000000
AD:
CT: 84e07e62ba83a6585417245d7ec413a9fe427d6315c09b57ce45f2e3936a9445
TAG: 1a8e45dcd4578c667cd86847bf6155ff
CT: e1cf1cf545d2743ec005b26bd2c836ac1a4233d646c195ffa401f28063127baa
TAG: 1071338b8c2930d3ec4c17cecbefa4b4
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
AD:
CT: 3fd24ce1f5a67b75bf2351f181a475c7b800a5b4d3dcf70106b1eea82fa1d64df42bf7226122fa92e17a40eeaac1201b
TAG: 5e6e311dbf395d35b0fe39c2714388f8
CT: 2e7e6881a02d57b877794b2fbfbfef5484f1cf74f4ad53a751b2582c0e698466bd9a49dcab53806d8e31d864c4632d00
TAG: 04b1b8a9c1630ff028b14d2e57bca429
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
AD:
CT: 2433668f1058190f6d43e360f4f35cd8e475127cfca7028ea8ab5c20f7ab2af02516a2bdcbc08d521be37ff28c152bba36697f25b4cd169c6590d1dd39566d3f
TAG: 8a263dd317aa88d56bdf3936dba75bb8
CT: 0ac5be860726209d9218de3e9d533743e1efe1595bc58f93f00e9bb9a7558dc1e1b14a9c0d49eb5064c7efa79842f9c7cfdd77614709f0b545d3227498e774d5
TAG: 860b73a1ed8a5b9acd925c3f3f49c5c5
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0200000000000000
AD: 01
CT: 1e6daba35669f427
TAG: 3b0a1a2560969cdf790d99759abd1508
CT: 4919e29e9890e452
TAG: 1433a5c0284c911163888dbd128e6874
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 020000000000000000000000
AD: 01
CT: 296c7889fd99f41917f44620
TAG: 08299c5102745aaa3a0c469fad9e075a
CT: db55d6da719fe0473538294e
TAG: 5a8ab948ccd205a70c78e8fdf954693b
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000000000000000000000000000
AD: 01
CT: e2b0c5da79a901c1745f700525cb335b
TAG: 8f8936ec039e4e4bb97ebd8c4457441f
CT: aea3c54272abc1b58ed34a536743f4da
TAG: da10d98bfe23784cfdfd0af97b6d5b78
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0200000000000000000000000000000003000000000000000000000000000000
AD: 01
CT: 620048ef3c1e73e57e02bb8562c416a319e73e4caac8e96a1ecb2933145a1d71
TAG: e6af6a7f87287da059a71684ed3498e1
CT: aa694c0cfe148100cb5c6e27a77a7ff7b4233d6af251d9faa3d84f7c0d1113f1
TAG: 778c5b68356a1a6a6f3c14a8f96c35ca
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
AD: 01
CT: 50c8303ea93925d64090d07bd109dfd9515a5a33431019c17d93465999a8b0053201d723120a8562b838cdff25bf9d1e
TAG: 6a8cc3865f76897c2e4b245cf31c51f2
CT: 9ac909928bcde79c2afa885df9c035c85a9eab136f6f6ea11034456bd306ea3c5dd542f706fffe538b5f139fa9dc622e
TAG: 26c0c0d146d38787ca0fcbc3f911577a
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
AD: 01
CT: 2f5c64059db55ee0fb847ed513003746aca4e61c711b5de2e7a77ffd02da42feec601910d3467bb8b36ebbaebce5fba30d36c95f48a3e7980f0e7ac299332a80
TAG: cdc46ae475563de037001ef84ae21744
CT: c56be9d61ecf6a31a6289cddc9b91aaf84cdb53a3913b825d6eb5e157906dfb0a308c6b0b095d6fd1a5b761ca7fa0e39ca92f38ae206eec844c0c4ab0c1c165e
TAG: a60986309b99431a35dd8c5ebeef8375
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000
AD: 010000000000000000000000
CT: a8fe3e87
TAG: 07eb1f84fb28f8cb73de8e99e2f48a14
CT: 47995b96
TAG: 16b668094202cadde992e0c16205793c
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0300000000000000000000000000000004000000
AD: 010000000000000000000000000000000200
CT: 6bb0fecf5ded9b77f902c7d5da236a4391dd0297
TAG: 24afc9805e976f451e6d87f6fe106514
CT: 8fe25de75089e9f849150e57ab7f7810981cd319
TAG: 89ca91ebc560709432fe9496746404cc
KEY: 01000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 030000000000000000000000000000000400
AD: 0100000000000000000000000000000002000000
CT: 44d0aaf6fb2f1f34add5e8064e83e12a2ada
TAG: bff9b2ef00fb47920cc72a0c0f13b9fd
CT: b26d43ae158316ac37f41579ccf1d461274e
TAG: 13b7c01d08dd6969d51d1bf0fbbdc4d2
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN:
AD:
CT:
TAG: cb52de357fad226ae428d0ed5a575496
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0100000000000000
AD:
CT: 7e139f58002d68ee
TAG: 715835541f2136f03b6dc80ae0a8ac46
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 010000000000000000000000
AD:
CT: 4a87f0cd26e5d5086e90da02
TAG: 4dff905e48d512e9c34ae8f3be66ec43
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 01000000000000000000000000000000
AD:
CT: 048ca58c46d2368ce00132389f40b511
TAG: 971da9aa385283522c4f67a9aedb37e5
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0100000000000000000000000000000002000000000000000000000000000000
AD:
CT: e1cf1cf545d2743ec005b26bd2c836ac1a4233d646c195ffa401f28063127baa
TAG: 1071338b8c2930d3ec4c17cecbefa4b4
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
AD:
CT: 2e7e6881a02d57b877794b2fbfbfef5484f1cf74f4ad53a751b2582c0e698466bd9a49dcab53806d8e31d864c4632d00
TAG: 04b1b8a9c1630ff028b14d2e57bca429
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
AD:
CT: 0ac5be860726209d9218de3e9d533743e1efe1595bc58f93f00e9bb9a7558dc1e1b14a9c0d49eb5064c7efa79842f9c7cfdd77614709f0b545d3227498e774d5
TAG: 860b73a1ed8a5b9acd925c3f3f49c5c5
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0200000000000000
AD: 01
CT: 4919e29e9890e452
TAG: 1433a5c0284c911163888dbd128e6874
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 020000000000000000000000
AD: 01
CT: db55d6da719fe0473538294e
TAG: 5a8ab948ccd205a70c78e8fdf954693b
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000000000000000000000000000
AD: 01
CT: aea3c54272abc1b58ed34a536743f4da
TAG: da10d98bfe23784cfdfd0af97b6d5b78
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0200000000000000000000000000000003000000000000000000000000000000
AD: 01
CT: aa694c0cfe148100cb5c6e27a77a7ff7b4233d6af251d9faa3d84f7c0d1113f1
TAG: 778c5b68356a1a6a6f3c14a8f96c35ca
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
AD: 01
CT: 9ac909928bcde79c2afa885df9c035c85a9eab136f6f6ea11034456bd306ea3c5dd542f706fffe538b5f139fa9dc622e
TAG: 26c0c0d146d38787ca0fcbc3f911577a
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
AD: 01
CT: c56be9d61ecf6a31a6289cddc9b91aaf84cdb53a3913b825d6eb5e157906dfb0a308c6b0b095d6fd1a5b761ca7fa0e39ca92f38ae206eec844c0c4ab0c1c165e
TAG: a60986309b99431a35dd8c5ebeef8375
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000
AD: 010000000000000000000000
CT: 47995b96
TAG: 16b668094202cadde992e0c16205793c
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0300000000000000000000000000000004000000
AD: 010000000000000000000000000000000200
CT: 8fe25de75089e9f849150e57ab7f7810981cd319
TAG: 89ca91ebc560709432fe9496746404cc
KEY: 01000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 030000000000000000000000000000000400
AD: 0100000000000000000000000000000002000000
CT: b26d43ae158316ac37f41579ccf1d461274e
TAG: 13b7c01d08dd6969d51d1bf0fbbdc4d2
# Sample large random test vector.
KEY: d301238025c7ef4fe32fd20cc3ddb1dc
NONCE: cab44881cefbcae419a122d6
IN: 71356c78191cf4181cee0532d45d2d4fbbf62b9adf86b0643dd3735191283b1f9fd6a890029a4640294d0ffa9e18bf9da18cea164f87a01a376ec43163c5a612b125ca261e1eaedc03e3105b59e11bbbb8cc6c8247b3e5a0e55ad690c2a77b9f30e3b5202a187a6027097efa66ab0ba824dfc167ae51a581ca5e6c78d10a2e485c61404f0cf4bbb535e0b781ec1cf558e385d3f2d31334852015c402f77e7a4f69e45c88ca3b2950a0232971d80aec4b47c22d70ec2dfd058d5dad5ec4843df0173094053ccf265de85465d32dd36309798d88f7552e2b8a962d42e3744544e753516647fd0686860cdfa52c9a674a461df0a772f05cd814dcd80e8ebc871fa6994e045112178f98dea9f1fbcc3931bd5c3a6ba834ed083bdaad943e896c86c710ce59d49b36b882a24236e792e91351fc2b7a4385ed8d304b0c89e4785660822daecdf938fa237a97a95dec37d89cfc44c5964e31f4a257f996b628e8b0fded09d06e73b864200c7a8973dcc0e84f172940fa443c05dbe3a18e49b05c362adb57c7dcad2c31d3b2588e5931922c02f0eac0c3c7780213a978cd5a0ebcbaa4bdfb6873812e61c36b93d8f5d3b81db3f97f5a5207f274e4b1174f919defc2c63fe5cee5e9e2f3d91d7e726dfadb35bbb28ef01a625a97b502fe8a5ee56a5140668ca3429395440dc75dfb8212827ef9e5b7562f3f57dbf1a9d0e0fcbb2ceaddcbeea4cb2a8ef419cc12b767ed56712d19e431da3c6e48a21c3a5dba1b83f60e7a546000543946b24a8670684283736c230253873c39ed8d884967c2dacb365e55dc40c7f77787c1f050f16376c8220611ecec2887382b8fefa4b8627b0640038732f7ef0aad2877376b5256dd6f770a426749dd2f22f69684340e32548972be0feaab5dbbb0ae0b41460f6b483086b2d3d108e7f80a7cfa559dea483ea3c567cea8b16bb2f3eb29e9917be929e32571c7253b07d967a2c05d7f5b05c56f0dda6936a4d7d7b2e0ab877c99a9fedec49bc5058ffbaea034f7a5d493bf99cf3dea26d39076246e2a0f10d62b29799c04759b534a03b82e6cfff39872b07997a8de7d71ed87f0518581d15d34ccdbf66e6bbace42c56d7e4a7ef5e7e1462bd102fe104488bb4555676f04b4974ec436e6b05f7ea043641934bf02117079eb0323e213217662331d5dd310550a5db9a3a198770238e74da7d6667959956d736cd607c6c5c05eb279f077858101767a613024dfd31f50081ec482a2532276b2ccb272c1a5f00fc041dea0220ce8d51e5c73a7be649dfbaf1c4e75ab2e30cbfc61f3a83d866cc7e9318a4eca8ab9da2f4aea2c8a7e8b2f867adb134c3433f72edf471388fcd804ba316af409474197ade5a1f39d58a7378cd8bfca5a81588f43a05c09e4249a242cfb54a1c5ec70972dfabcbdccc61f305835dfa92a37d59148ad0b74d7
AD: d1bbfb956faacbfd116bc473b3e0ae09feb224ec760f65b941d99a09eef82dcdd4f8111cfecf1ad4f02e0bdc3a137b9095f922dc3a80d98282827066c201779af4f4267364dcb3eee26a8c9e885b835e7836666dedce8dc912aa328c56bafa3f5746a5c7304cb6805e895885dc520edcea76739db2b426e93ef404b406ede2d57f0131ad6cb1049b18e0bff1bea181b57a3b942b55348a7d2afb056e90f421f5e281c9c3ada60c5891a2e518981704d92c5712991b31a620a3d53811b971469d4fa86e32de261a4679671cfd983c56fe037e9232f06a53aa1eeb2f61caa4f8c1079679ee9fa581ee5eb49842290152655c15bad483b96340a5f1fd67368fda29
CT: 8dd19cbf232354e78032baaafd52903569381a29110fe1a6bdeeb539149d69e35f1d8efa09c029c21514ce1a040371714b317921228d8718bb979378cfbb53e60b16ba6ffbdedfa0283d9c48fdef183aa6000d05aa1bcf76f478a6de9356726f1645a681ec9cd84716403e354f38b5364f5ca290291c965b82fe4c0d3085d853ccb0588e4c815214e895b46fc2758747559920e0d137d105419e2856d0e0e5bcbb6f7d3d6055bbbcdd29c7a70fc80a00392bd27174c0bc806adfae08e32b308ce8128e4bbae574e96daea0d3676c7ee259bf2a1ee0af0f474401795794cb51d508db5ee02d346a5019a5dcda7532317a41a7147af946d56cb1dcbd53e28feadbd9af9cd3eb96c7bff0611c2f387d95f8caf8b3ca59d02020340630406e597d665b2d2193635f157c51f1b19a1cf4349d1ef227f62812d6cdb0c7dae87647f1ac28c79d643ac0d06781ccc24d626c44e0a3b7a55e3a81f30118703d489b93dd01f94ecae0ac42e1eb7e937f67a38dafe9ec0c5d2bf846acd1536011c02a63153c9e4c0bd4e467e5671e52507a34e3a8dc6de18eb967a54cf63bc049e0c7fe89988c394959ef80f8c23bd93aef9a150ae33a245fe8b6db955193632118e1adfea566620b6dd8ac46a16f86651a8d34719128a07c63123eda805602ce923eb0b945886bd73adfe08beb77b50cbc6fb023f41355d5f1e16f289b9ad86ae89e35c978dfe8b8356f80bb809fe9274553dc094e96d865ee1cad1de31e4c838e5b5564b581369e8ff719e1dd84c3465bff3981bbafc874bb206b5e9f58d175c292613ac4005bdfafd411acda8c94d64b58462d2612b2877c9284b1a88fd55631abe6fa17a7fecf3635256c3e09fe3b7aaf032a411e8b9645def45219de48d58aeec6e239ee211de18051a2a5175a265ce1bab462c7a35c46590f6e1fa543f0ffd3777c564dba9a1bd1124b96fc2d1e7e81e51ecc83f7c6f2ee02b09962bd5f2744e54d58592336515f39a4ccccbfaa8d829259abd0030da76648dab078574638c730bd9c32f8179592029faa9f19adde63fd7e2d671d1c22cbadd8d28d4dbe8d098fa5fbb593884830fe6bb4afd89bd1143f77d194938c71f01fa3323cc23f18bdd486bc7a468bfa6fc0e9bd198ac4fb572f1d94fc3ff7e4860621929d39967e1baf493132188d6978bba043b2264ded093709a224af7358d5aae09667a1b6533e714fd9ab5157e201d7d14e7f559c1e0709faadad5c18ec7144faea92b134f9ac48a97a13d98e4fe0b4c4a66daa0b6adb23d2d17be82da4f590caf6034b2f0c3a846a2740339ec24223e1c024a3955f54b87358b62247afeca011d4830b0e23174965aac60b7f5517f11b23dadc06e4e72e4d89d0f5764e804e840a495d8352dc0bf22ff454a118db981224b73632eeebe5496a2c5a43cf69af0a79e84e1d12398c8024
TAG: ae3f5d2b7ff538343964febbcd9e919b
KEY: ee0f62a965fa640d1c95d79b215dca71
NONCE: 7df5a22c91e6b6f37594dfef54847bd9
IN: 5d90037e677666fbc0215305096301d852609e1380992d8c2e3594344a7f9a0521fdeda53de07d3184d590667fc7151a93ba097f20c67da0b1da8c23bd05887a4b66ab50333874819035eafd775fcfa86b380968f15d8cd46483d418b2c074f0dc18407108f63abe89c5448e83d064b6544a275dd75a21dd0241dafa086beb8446f398f6c1b2b117ad6f2cdb04031640852b5e15560d39b8d9088824f728ae66b2214e4cd70f60174313a5f0286741caeb4b66d0513b63c4a1325306f79f1f79bb28ccf6448fa3160876eefd85ca03c196a3e5568b0f3c818e7cf9d661423ed6a50a6911d52217a1b81e94ba040f336e74ac71b33964c3a7d960a32c255e22fcb7dcc41b9b136815b784ce4015b61b55e305e2ab1f96d17b561eb0281476cbaec54e942a186fbf3df92358960182c3c034066364e80fa492b36d36ee68f2738220f249a69f24405fe9995dab0b0b338ee68d85f0e59870903ca9d02f32ee6a24efc85434610586470b938daa9d14206c360339f7ec50857f4e5075a29bb51720d9a6f399f7b8bd45b402b0eed8f6e427d5dd358a0c3f10a58582be8934ebd7903497cc6622a977d6045f97a58f5ed7a3470583ebf88f71150499047e4b624f8018cffaca0d5a9db7f73da2db6770c98cd628d2d6682a4c41d584f37ea0ff7e8763616a548027e29cb3ec3e02a82eab205f7af46b6c9b02a15de54fc301a9845d50396cf3826b23296c360fafbaf65e5f48c4998085d7dac07736b106a8bb1e8e69dca15464d1bf156a5f84b62170f680826dcca7bf1c126cdb70dc872a005806d423cee46ab0d84d2d8d490c8eaec8b17b12913d4856c59f5348c6956c96a32595eef8c89ee5ae99706c92e748714dae4ae45685710261cd66d3ef93ed01bb862bfeb3b4fb5074ffec5517c8845173fde2774cd3b5a25cc1dc11d833c29614b7272bf213aeb19f83603aee97a9bc43e8b88c8789c520f634028cce2b0be343e74c8c341a153a36f797f38a4ebb53589e45f1e64299fedd2e9bbdeb9ad9ab4e2eccb4bd2b57000a5d7b064e6b6fb5cb9c743d6afe697bac549ade238c7a3a094e799e9c7e6cef6e6d4b8c8f1d862bc8ab9b96238c7d5393b2f684c5b4826df6c5f48cadb43fd6d6cb189ca56125bfee9dd44d22a2e28d7a9e63565321c9ecad96b3ae7376c984c44cab978002ff78d947230fe15918b3a73232ff5c05586c4b0e2e0d737be6abef80414b008ad2deea1944a4248f02063500a9276217ceabeca39ec4d6af647395a9c91401dcbe8f9645ef97eca5624029f942cc9979fd31636d65ed181a65763c5c16e65f8673a3cc6143ede8144d894559dedfac3000e8d86590b0ced25dd8666d71f237fd3511d7f8a20dbb4e95e3aca9807a2351bf705a7eec5a80f2b390ef9df496c5cd7ca9f5d8846df291025beb9781c793613efe7798
AD: 4b7531e0a946b20c80f70dea4d437833f3dd26ae6f6dc37b7b99e82122acf2b7975f6d8efcb7ec4c6ff3c0ce4a5864adba0e658aeb8d9b839f3509f033827bc69a1ab080a0a1cc63559b00a3a259c53c145b0282f5e56930fc35b11c83b6564f2e80f186c2ef2e8886641fe6c4966dc9f86c567e73902d1a8fc33be1551e8359aa585bd2b8da83c0cd78a086cdebf8904d1b66a2fee176fa19714f062b752653d75a0e441ff7fba0c5a0cb6ded48f68b38af82faa985f9d97ba3c0978e1d23d8eb8899072fbec9379ca5f2b91293cb57eac81a6d711f9cccb36ff16b0de86d27d62e136ddbc1a2be38d5a1284e4620f4f9ab1f16729630e16dd2901f24f5ad6e
CT: 1b5a273ee4e1f87516bb711bd97c559fd5139286d90d3f64813f88c697ff448c7ce57ff3a2b70479c0f904f0c6de92234ef72b4ad62038a32108804042e07ad94e49a327bd28f1c49786c2b1537392c582031f52e3bd27336dab9d237ce47ffd0c8002b60b1055226cf28c6d99be0e4f75afb72c6953ffa0b033f74304efe19601d34dfda29874efdc9ebfa74c9d55c7273561c46b7cd4d631ab05ca7172111c13f0703ff9cec063988b7bf1bd9557b8d8a914162d2f31113f1682e951acaba4a314aabf901bdc5117184109fca1cecfe552f2e7d003eab51ceb992c2bb11245e1cd7e230398a3d18bab59c9acf033bde779166bfd3f98792902f84e4ef32cf5f410af2cec9cbe67ebb28f3fceb497abf4b1c240cab4852d840de9dec20f0e21853be6227784beee276ea3a4c6092654f7d62af614e5ea976791195415befa1f4a9d77c35a84b0d54b5eb1e00f55bbafac209468532b18d020e16798256aab9ea3989d876822cc68135ee103169962965a9383b2cff70213f9c52bcf2441e7b8ec07bee0c225be5353bcfe6d9ff546d30889813a13e1e966028dd80ec096202a26e478278af8b15bcf29137d536658d51293c6cfecde110e5b17ec39ce5317db5a03a1919f52f89ceeec0b5f48875e9692501b34303110e52ef4ea96d98cc28ab6e9ca24a8bb124629ac480b06fa8321b5712f2ae22e750848404ac20232716e195b343adebb52234cbc002c602574a7fbad638c1a7201eb38d4404b3d672119617e1190402b57568ee1e776ba18087164ddfbbf77f26ae5ee229ef101f10306f6449920b08d4e46bb2039d4777319547d7b4ef32e61c3cc897bc36cc2d5983c63e38814276a28125468112b646b877bbe2d206e578a8fd402be6d963b1d79c8b14dbca801bb92d7217cb7375d5e126702270158c89db653f1ee34e1c1ca066fe854532a36b74d36d9bc077506349a4cb8143dca1be3241f64cdc410c4d362982500aeea2a12172ccac996a333a2bff5393e0be9bcb93ca0fd62a22f0f72618325e233b42214ce8683c57dcf3113edbc5102e84b265aa031e26ec5fa18b1a7fa72358072d47b85e045cd52541e49b94d74fb21bb19725675c0d014ca8f8219c26cb8158f5d84b2cafb0474b2b39cb7f21c3320b5cbd57cff7133243a462e492de6340ee7d60ef888d639ca50380529f09b9eb279c49ad04662b7ec4f579fcec011790f18b2c0ad081eaf2be13d6f6a5969db46d56df9daea2cb332e719135109fd1d7caa84af315c0054f37177312c01a9f3f05a6e9bca719f906d1e8af7fdc24a3677c922f435e6e4c069073ea779c2b74c98f9374f5a38961a4354e74803f0f4042b91fb82a0c593c13f9ff720a70136d0b108acdb762a08f98a222f48c2858c0cc9a27edc9e79fe0f71ebe2940c60a279476975926eab478685ebf8a74705
TAG: 6f5223329c07cbf6b038d307cbb8a719
+166 -54
View File
@@ -1,123 +1,235 @@
# Test vectors from
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#appendix-C
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-B
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN:
AD:
CT:
TAG: 07f5f4169bbf55a8400cd47ea6fd400f
TAG: eb7ccf36eeff369241379c87cc08e4f0
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0100000000000000
AD:
CT: c2ef328e5c71c83b
TAG: 843122130f7364b761e0b97427e3df28
CT: ab3f382a6f0fb4c3
TAG: a0a69e07b73281f5cdfd034f646cfa08
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 010000000000000000000000
AD:
CT: 9aab2aeb3faa0a34aea8e2b1
TAG: 8ca50da9ae6559e48fd10f6e5c9ca17e
CT: be8d81f033ca23b953da2197
TAG: cdf3ba70da9c7cbd45f5140ba0cca9f1
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 01000000000000000000000000000000
AD:
CT: 85a01b63025ba19b7fd3ddfc033b3e76
TAG: c9eac6fa700942702e90862383c6c366
CT: 46e05b7116dbe27aaeffe99892194072
TAG: be19d78991c62130cf97f628c37c3eaa
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0100000000000000000000000000000002000000000000000000000000000000
AD:
CT: 4a6a9db4c8c6549201b9edb53006cba821ec9cf850948a7c86c68ac7539d027f
TAG: e819e63abcd020b006a976397632eb5d
CT: 23ddbe9ef342b03003f56d6b4a2e8aff035c7d7cfd705e1ab4502904254bb67a
TAG: 16c5944034050657af7c0fec7efbc40f
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
AD:
CT: c00d121893a9fa603f48ccc1ca3c57ce7499245ea0046db16c53c7c66fe717e39cf6c748837b61f6ee3adcee17534ed5
TAG: 790bc96880a99ba804bd12c0e6a22cc4
CT: b104c8945f280e75b52c05c45a63d1872c7f0552b1501968d9913d71207d0433f978f1a3eecdf782016b77e8c9d3ff53
TAG: abedb4841c20f3b05e61e0fd1fcaf3d0
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
AD:
CT: c2d5160a1f8683834910acdafc41fbb1632d4a353e8b905ec9a5499ac34f96c7e1049eb080883891a4db8caaa1f99dd004d80487540735234e3744512c6f90ce
TAG: 112864c269fc0d9d88c61fa47e39aa08
CT: e3f2bd14f4c80c9cea4c90c81f0e4d7eedb87eb19a7c0cf5a5a95cd3e441a71083b1191d115e9a9ff008b93feeb5a86d012a3e0adb89de2d1e3225479022292f
TAG: 3ced67f5e03bb476a738c1343926dc19
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0200000000000000
AD: 01
CT: 1de22967237a8132
TAG: 91213f267e3b452f02d01ae33e4ec854
CT: 4dca2c16c3b0413c
TAG: ac9b952c76a6f8b5df315f88126daa1c
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 020000000000000000000000
AD: 01
CT: 163d6f9cc1b346cd453a2e4c
TAG: c1a4a19ae800941ccdc57cc8413c277f
CT: ee0ca9068b5b85dfe115a660
TAG: 756d6155927271077d790a05390ecb71
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000000000000000000000000000
AD: 01
CT: c91545823cc24f17dbb0e9e807d5ec17
TAG: b292d28ff61189e8e49f3875ef91aff7
CT: 590edb785c0cb89d19f031fa7e7d4f91
TAG: ac2c8f711c86dbecc8c7b663c5fbc1ea
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0200000000000000000000000000000003000000000000000000000000000000
AD: 01
CT: 07dad364bfc2b9da89116d7bef6daaaf6f255510aa654f920ac81b94e8bad365
TAG: aea1bad12702e1965604374aab96dbbc
CT: dcf2024f5f98d463b82a8673c47dd82159748cac8bcc7c76b8cfa26029cb333c
TAG: a9b406643e190e602fb104fbb842a1ac
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
AD: 01
CT: c67a1f0f567a5198aa1fcc8e3f21314336f7f51ca8b1af61feac35a86416fa47fbca3b5f749cdf564527f2314f42fe25
TAG: 03332742b228c647173616cfd44c54eb
CT: 79216506b1ddadfe16366e4ec886d10dc9400b995259f74c0091f9b5a6add5680a612130f6c31ab833aa76d9b2be86de
TAG: 3ddfe9ad2c350980942638d3f954ac6d
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
AD: 01
CT: 67fd45e126bfb9a79930c43aad2d36967d3f0e4d217c1e551f59727870beefc98cb933a8fce9de887b1e40799988db1fc3f91880ed405b2dd298318858467c89
TAG: 5bde0285037c5de81e5b570a049b62a0
CT: 9535eb67240c49f30a0de5a90670813fa615e71fcb4c522ca79d9a33459a22f8c6a56d650bf0b15eecdd706e7689cf6510a281724613fea76b5366b40574b1b9
TAG: abcb59ee31d25ee8889b70d7c36f9a41
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000
AD: 010000000000000000000000
CT: 22b3f4cd
TAG: 1835e517741dfddccfa07fa4661b74cf
CT: 9611baa0
TAG: 53daf2bc5916f7a6750f2432068dabee
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0300000000000000000000000000000004000000
AD: 010000000000000000000000000000000200
CT: 43dd0163cdb48f9fe3212bf61b201976067f342b
TAG: b879ad976d8242acc188ab59cabfe307
CT: 78e3a1b54daa6547f775f30c38a45e887aea5c87
TAG: f65187d8c28adba364d659b627b16431
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 030000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 030000000000000000000000000000000400
AD: 0100000000000000000000000000000002000000
CT: 462401724b5ce6588d5a54aae5375513a075
TAG: cfcdf5042112aa29685c912fc2056543
CT: c6d3d28704bf20067d62e1a3872d40dda44b
TAG: 6ac0135a4379dbc67967ff55fd4d1f2f
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN:
AD:
CT:
TAG: eb7ccf36eeff369241379c87cc08e4f0
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0100000000000000
AD:
CT: ab3f382a6f0fb4c3
TAG: a0a69e07b73281f5cdfd034f646cfa08
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 010000000000000000000000
AD:
CT: be8d81f033ca23b953da2197
TAG: cdf3ba70da9c7cbd45f5140ba0cca9f1
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 01000000000000000000000000000000
AD:
CT: 46e05b7116dbe27aaeffe99892194072
TAG: be19d78991c62130cf97f628c37c3eaa
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0100000000000000000000000000000002000000000000000000000000000000
AD:
CT: 23ddbe9ef342b03003f56d6b4a2e8aff035c7d7cfd705e1ab4502904254bb67a
TAG: 16c5944034050657af7c0fec7efbc40f
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
AD:
CT: b104c8945f280e75b52c05c45a63d1872c7f0552b1501968d9913d71207d0433f978f1a3eecdf782016b77e8c9d3ff53
TAG: abedb4841c20f3b05e61e0fd1fcaf3d0
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
AD:
CT: e3f2bd14f4c80c9cea4c90c81f0e4d7eedb87eb19a7c0cf5a5a95cd3e441a71083b1191d115e9a9ff008b93feeb5a86d012a3e0adb89de2d1e3225479022292f
TAG: 3ced67f5e03bb476a738c1343926dc19
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0200000000000000
AD: 01
CT: 4dca2c16c3b0413c
TAG: ac9b952c76a6f8b5df315f88126daa1c
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 020000000000000000000000
AD: 01
CT: ee0ca9068b5b85dfe115a660
TAG: 756d6155927271077d790a05390ecb71
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000000000000000000000000000
AD: 01
CT: 590edb785c0cb89d19f031fa7e7d4f91
TAG: ac2c8f711c86dbecc8c7b663c5fbc1ea
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0200000000000000000000000000000003000000000000000000000000000000
AD: 01
CT: dcf2024f5f98d463b82a8673c47dd82159748cac8bcc7c76b8cfa26029cb333c
TAG: a9b406643e190e602fb104fbb842a1ac
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
AD: 01
CT: 79216506b1ddadfe16366e4ec886d10dc9400b995259f74c0091f9b5a6add5680a612130f6c31ab833aa76d9b2be86de
TAG: 3ddfe9ad2c350980942638d3f954ac6d
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
AD: 01
CT: 9535eb67240c49f30a0de5a90670813fa615e71fcb4c522ca79d9a33459a22f8c6a56d650bf0b15eecdd706e7689cf6510a281724613fea76b5366b40574b1b9
TAG: abcb59ee31d25ee8889b70d7c36f9a41
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 02000000
AD: 010000000000000000000000
CT: 9611baa0
TAG: 53daf2bc5916f7a6750f2432068dabee
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 0300000000000000000000000000000004000000
AD: 010000000000000000000000000000000200
CT: 78e3a1b54daa6547f775f30c38a45e887aea5c87
TAG: f65187d8c28adba364d659b627b16431
KEY: 0100000000000000000000000000000000000000000000000000000000000000
NONCE: 03000000000000000000000000000000
IN: 030000000000000000000000000000000400
AD: 0100000000000000000000000000000002000000
CT: c6d3d28704bf20067d62e1a3872d40dda44b
TAG: 6ac0135a4379dbc67967ff55fd4d1f2f
# Sample large random test vector.
KEY: 9f646d6337565c689c9ec7627ad95c26a2df7d3a36fba9f1265c607458bbb1b6
NONCE: 336bb4bb0c03e8c87efe3b5b
IN: ec257ff779f7cb246a38462562e508b14adbd3ff33041b94aab6f10a3e8b7fe16738f12afa470c9100924b211a728f90ba6d2260b4d451d3f4701d72b8a8cd53921f65e8aa7b6bd3995fef3cf6db60d1e2927c9012ea2a62af3a50fdada2262f8f02d9651d542e3856210af36def3c6d1b712de4dd34c63a09a6d2928019c62a7253cb47a9ed056d7435d723809768192c7df2768aa4b9ab247e1a522fa58532c7d785d2236f92fc1f4ab621023f5e5af084fe41584d136cec5ce33472f85c4dc045e70bbd5b6781c394b4b2872b3734879de37454a5351d272a84301ef5df121c0ac70de6f375b7bb185730baaa7f9b4ab093d66e34e799e3abd94d03b6c344a82968a07ed8b6fea37e5c2275b8ad40faa040558ea8636af91f42be30af2c61c34c50459e04ed93998da10c2d7cb75f4b18fa027fbd7d5f0e0b830784fc530b0df84b253690649dba92671373e43773a324b81624298a5006c9083adf09ff35ab7b098b67e40c65888f6027eb741637afc646b6769c70b594c771fb94049d4f4e74e0c9967689716d8d37405687a7dea0527500df90dee256e496f251892023dc729d42cbfb4f2514cdc177cb427d6d46493770f91744b9c173ddae6b6baf7e2e95dc6dd268e2b89510deeb2fa5aaa108cf4b7da8a2af7a6cb18c32ceec6be8d2ec734bfeffe25464aa0cbcaaea9508c92ffbb1973d7cdc6118845df7d9386da2fac4e36bddb37d01bbd47d0bcb793850865a4ee08836a72281ff1bda146017145962bbbdd486e6e3a457d3f3c0e05a7cd3514e4aaec85730a39fc8ffe8904e1009d565d919b64e388988db05f90599649699a33f7620df75be25c0c45e1f3829ca38df1343f93dd1fe5b8f05584828f9bcc61c474737ddef2ad0b0436cf303ad2f404785a6db7314e9af2e0eaa68fffcd9dac3a905709d31a259c1e5b808c2fe036ffacb4ce0ca072835815e9f232e29c193e8519d0cb4cf4e8b1f9145c13211232d082229bd80efadd0e215e30873233f60a45441295396c03916d2c44cdc30e8c3650b4045b656d530372414723d1739fe353f4124b80d78d0a170925044b225139e75b4a774262656c72ad4cce99725d505871e3c7e01fb45e5f9f36b68f6ed7974f698967fbabe57b3143ed43d7e6c9cf253b16e8758267598f687e69c217194c5ea1bbbae73757d28d109582129dfc4777a27fafb3a8c3f64c5db209e4ce06099dd0ef3ab5c123a6435d2b0603b102e9b88398413373c53d2252620b8bd7293abe35e46be0b2f828ecfe573312dd85444d32fd5d18a39295865d367aec0d51193cfe8284670f3f1febdf64e34bb6f3ecb2efd0c43f66234ff01dee3465d2fb1d9ce87f3ef7f8f57674fb269bbe8f3e2001ef6b610eed4a2d0d2e2c1b696e4e32084fe4c340612aa13636e223dd758cd765e7864b96ba787d16432bd3c
AD: 3d186bc3d38b19b41e8c039f5417be09358ad8743cb26b6fefe19a9752901a9bc18a6ed325ec307861bd0fa333a9b0d156dbf30a84f11b72d9b74000d1690f317c04598b1930ef6df873fd9c098abdb7e92eb82d9e5675518365af68a990477f2b70fa5514ec5f5010b5ac0d00fa6d848c40c49aed54b526cd8586bb783bcac299b8c0e96853c242d7c34479bca18aff6d55fbef52c735c41a363d68452304125bea529d235e09cc861198bd292ee63ea1387f859eda363f664c3952aa4fae135cbc0d37ae89f2f34cf1a5b6a685ebbfbac18209e0ea38aadd71a6c16163b5676e84b4bc539c4b1079553a6765726cc8064489c8cbfd3c0999021d70b4c0aea0
CT: 17bb864ba0458a63fa51ec47259f0e22a9aa387bff7774f3badc55e13748c96f4d0463d73a29d70140f384aba50f9efcd5d0fcbfd1b0b4b16226993aa00260fc1f0a0a28b4a9a19acd9d966920a56a95cacee547a0b3b1d6a752e575a10101d3ba91d59a10ac9eac7367caa1e3a5ad7173d149bd69f97ee1e6782e05f14d9434716bd103ca2e48337bb1cc68d54f31d75244a53cf1d2e47f55da7fc2b80b8eea4110c1887b157530cafa2519bef54f7f4641a8bb5bf2a7f3ea50be71aa8def7d6244c49d2d11de0e08058d08e8619aa3cedcfed1850651585e38489b9b1c7a8aad5ccb3fd380ca2745c5b8b530e6c6ce4fdb7acc8de1543d0364a96d6dac08ffe4474a4f34a96a47c4a7d5db27997963546350e28150e34f81dc6d1d354e867d5e3850f285da5890906f76471f8133da4899ee9b6774da38860e7d8de09edb782eefbbcbebfc2b61aaaae92e0f576a789b8ae4c40359e2dc69e352dc1631a7b791b41788b13b228585301e035c134f3e3a51a7622aead20191445437a9283cd03c6fd9cf128006f96eaaebfa4d71476efafef719189aefdee20d14fb5fb2d0a783ec9894edf3e937b405b7eec3c51649bba3c73a2d94e1b3cb059b6d587d9ee2714c813345f5b29852bec2422490edaf8a7423f2481c8c65497db9711143cff07c0a9889b786ac3e4def8065c8417fd56a91b20a27fb6e5bf8a188039fd51ccfb8be365b1a9f4abbf05135c66928a449aeb6110a70894edbe7e00c2111ff7bf718781965f6e49b758397036b9df6ef77f5aa005d98ff9d61612dc70fe0794e6aa9d3e78a86a3d42f5048a0f6ece5d1264eeb88c94ae529c53933b977dceb41da1b0299fd89ef4b94f66cafb67d0165a9e4210b6958f1ee66d30f7be6643970ccd9df3b11ed29580c5352cbfa3bc8cdd11454282de0b43ad748366948871d4862167fa42d6ed8de023009c9944149227f88e135c53bd50f6ea0727e7cf30ec5bf68ec951d5713fa79175e6aa5ccfe634594497e82b57f7efac8e7293d40ca2af0b63be2aa09d8b97edb7002152220ff96c620f2ab9463f1a1f0517a5df03a47842480f06835377506dd50595946a1bbccb0ef299335fe8b442aca0f900f7068d3f4c06b1c7da8c59c22ab6d1489b474c3e346f67d4a4f0b895b6c45a432bca80f95d34fb2c12dd60c4fe0cc1ac1f4e826f353ddc1ec9072554ac2259c572072d309135d3fbf879288c4cebe756663ebab72fe2078c661f3feb5ed7ef398c2f9d69dd289a835e5251d916e733b3f981714dc3e28ef8fc17b230f7aaa8ed11a99d81a7238f9041704c66b1ae02ef7d4a14bf94b5713e6a5f16718e2b2152e4e8a5f9d673dbfb14ce0b032aa7fc9e264f9002a7f955f7644cf16deede930ec209171472f2cdbabc65632220928a64eb29bfaf411b63b58a30a98b1a47a54c007bbd6
TAG: f2d188b9ec069b81793a841cfdcd1f88
KEY: 83475d5042f8baedf4ca779088abfab17d35416a767d8c42c2a650cc597e5004
NONCE: 7df5a22c91e6b6f37594dfef54847bd9
IN: 5d90037e677666fbc0215305096301d852609e1380992d8c2e3594344a7f9a0521fdeda53de07d3184d590667fc7151a93ba097f20c67da0b1da8c23bd05887a4b66ab50333874819035eafd775fcfa86b380968f15d8cd46483d418b2c074f0dc18407108f63abe89c5448e83d064b6544a275dd75a21dd0241dafa086beb8446f398f6c1b2b117ad6f2cdb04031640852b5e15560d39b8d9088824f728ae66b2214e4cd70f60174313a5f0286741caeb4b66d0513b63c4a1325306f79f1f79bb28ccf6448fa3160876eefd85ca03c196a3e5568b0f3c818e7cf9d661423ed6a50a6911d52217a1b81e94ba040f336e74ac71b33964c3a7d960a32c255e22fcb7dcc41b9b136815b784ce4015b61b55e305e2ab1f96d17b561eb0281476cbaec54e942a186fbf3df92358960182c3c034066364e80fa492b36d36ee68f2738220f249a69f24405fe9995dab0b0b338ee68d85f0e59870903ca9d02f32ee6a24efc85434610586470b938daa9d14206c360339f7ec50857f4e5075a29bb51720d9a6f399f7b8bd45b402b0eed8f6e427d5dd358a0c3f10a58582be8934ebd7903497cc6622a977d6045f97a58f5ed7a3470583ebf88f71150499047e4b624f8018cffaca0d5a9db7f73da2db6770c98cd628d2d6682a4c41d584f37ea0ff7e8763616a548027e29cb3ec3e02a82eab205f7af46b6c9b02a15de54fc301a9845d50396cf3826b23296c360fafbaf65e5f48c4998085d7dac07736b106a8bb1e8e69dca15464d1bf156a5f84b62170f680826dcca7bf1c126cdb70dc872a005806d423cee46ab0d84d2d8d490c8eaec8b17b12913d4856c59f5348c6956c96a32595eef8c89ee5ae99706c92e748714dae4ae45685710261cd66d3ef93ed01bb862bfeb3b4fb5074ffec5517c8845173fde2774cd3b5a25cc1dc11d833c29614b7272bf213aeb19f83603aee97a9bc43e8b88c8789c520f634028cce2b0be343e74c8c341a153a36f797f38a4ebb53589e45f1e64299fedd2e9bbdeb9ad9ab4e2eccb4bd2b57000a5d7b064e6b6fb5cb9c743d6afe697bac549ade238c7a3a094e799e9c7e6cef6e6d4b8c8f1d862bc8ab9b96238c7d5393b2f684c5b4826df6c5f48cadb43fd6d6cb189ca56125bfee9dd44d22a2e28d7a9e63565321c9ecad96b3ae7376c984c44cab978002ff78d947230fe15918b3a73232ff5c05586c4b0e2e0d737be6abef80414b008ad2deea1944a4248f02063500a9276217ceabeca39ec4d6af647395a9c91401dcbe8f9645ef97eca5624029f942cc9979fd31636d65ed181a65763c5c16e65f8673a3cc6143ede8144d894559dedfac3000e8d86590b0ced25dd8666d71f237fd3511d7f8a20dbb4e95e3aca9807a2351bf705a7eec5a80f2b390ef9df496c5cd7ca9f5d8846df291025beb9781c793613efe7798
AD: 4b7531e0a946b20c80f70dea4d437833f3dd26ae6f6dc37b7b99e82122acf2b7975f6d8efcb7ec4c6ff3c0ce4a5864adba0e658aeb8d9b839f3509f033827bc69a1ab080a0a1cc63559b00a3a259c53c145b0282f5e56930fc35b11c83b6564f2e80f186c2ef2e8886641fe6c4966dc9f86c567e73902d1a8fc33be1551e8359aa585bd2b8da83c0cd78a086cdebf8904d1b66a2fee176fa19714f062b752653d75a0e441ff7fba0c5a0cb6ded48f68b38af82faa985f9d97ba3c0978e1d23d8eb8899072fbec9379ca5f2b91293cb57eac81a6d711f9cccb36ff16b0de86d27d62e136ddbc1a2be38d5a1284e4620f4f9ab1f16729630e16dd2901f24f5ad6e
CT: 30b73374cc093ffaad4be2088142b08ed1b0d2914f96d90e0279aeb3a6547807b9b3bbfe2cd880e8f3a9f3b6e42da1ef53d78a6c63da686498b61523ac4c82caa01d31afe1ec00e80349df969684b060299aa86e4b7a38c643987889eab5a0a0996d18b2350439c7162d566dbb0d55f0f50a81d982df5e2047a23800a418b5adf42d8ff26cfd961527347439e76fbb2c2da08c1dd1a5fddf149d47eaf571498e23c3104c6b2dffb8e5d5e5f90e50eae9146f48b19a6e2d49cd170654a0041096f4f57aff5054dbf784e7748b3ddfdb9c447ed86681bcfb8055407fcec320990609089c3b51845f8e9bcb21382421a2f8634e1ad8739795202ade68aa47ab10026031cb3bfd94adc70702c31760753af4a2bb852581519e91cce5b1e0e49d028a1a03b915917d1011a4a7c04b46e1d8434663aa9473d1ad135966ab18145caf825f4a04d47b953989e188d21ec9f3858623fe16c413d2caa73761ec9dab8bf4e6dcdb997a503168487b67d1b3a9768a1887c292b9f39d40a404b8ffd011150490ed2e751ccbe4f7661785d8c5b778a21aa7e6efc132afe81765cc4ef32b5959e19ca97a4c37601257b8484fab234760242db6fd140ed1cfaff1d11cfad836171b42a164671c178164bbdb14815376f4eed1fbbb95f8e4614ff23de5cc9a0642a228d6bce19fbeea0e661b14696c6eb4aca97ac2cbe838578e7033703e2b551f7ef5dae4a68cdc58daac41eddc07b38ea7c4de1262ce04fb16f75870bbf41c95acbce6eb86dc3452a0d177aef3bc1e39878788d4a2680feb5d888debe62ec64fd72290c0cf8b9105c365c7305d994b28a2b32b88fdd11c3879dc1e005d6a2aa99daa926b18338f0980cdf0d8275e190bb9b8da9a63ff332bb5f5b654414a110b9d6128d0984d015c2a0a100985733fd400be0829f57e72655bfcd10c20341cd24cad0705647363ec0a3d678f30f7a1e85bc1a2dd133fcef5f25852eb6d81d7b4b531aff4e655285375f1b1ceee0d58a63f85f21f6525e3ad43f76a8fef16c785047778e1eccfe8e3c7cb34f2e037a61e3f01af88874b30911df60664e5ca65d6836166ff796e6b710af474add57957c2139b24257bcee287090f1ca1f91c95cc2c9348689aa7b95dfcedb02e68e38c1cd75ef966f0d33c4e09c40e2e58d30f6d0771d11debf01e57f342f3fffa34a1ed2bf10035c1607f3fd79423c0164dd6c171d8046edaed9b7b2a75bc11e1e8417c4550795aab6f106a95b5dda022e512269e8b2937b1d5601cfec1dba8b763707b97bc786ac94e38cd368cadeb1b48a3e068b614fc7b06430db80d46889027ca3d228d87c6eb00531e8d913734e3af987b104d052bbd63564184cd9dc803e6948d70575c9606a704245ef6136f707ddba8a00f288199867774c6e7487311c29aada3f607fc904f88be90cae49789a5163a4c
TAG: 37db916a9c13afd36e39ce5d01665067
@@ -47,6 +47,9 @@ AD: "123456789abcdef0"
CT: e275aeb341e1fc9a70c4fd4496fc7cdb
TAG: 41acd0560ea6843d3e5d4e5babf6e946
# Test vectors from chacha20_poly1305_old_tests.txt, modified for the RFC 7539
# AEAD construction.
KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6
NONCE: 000000003de9c0da2bd7f91e
IN: ""
+102 -104
View File
@@ -73,19 +73,20 @@
* supported by TLS.) */
#define MAX_HASH_BLOCK_SIZE 128
int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
const uint8_t *in, size_t in_len,
size_t block_size, size_t mac_size) {
const size_t overhead = 1 /* padding length byte */ + mac_size;
int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
const uint8_t *in, unsigned in_len,
unsigned block_size, unsigned mac_size) {
unsigned padding_length, good, to_check, i;
const unsigned overhead = 1 /* padding length byte */ + mac_size;
/* These lengths are all public so we can test them in non-constant time. */
if (overhead > in_len) {
return 0;
}
size_t padding_length = in[in_len - 1];
padding_length = in[in_len - 1];
size_t good = constant_time_ge_s(in_len, overhead + padding_length);
good = constant_time_ge(in_len, overhead + padding_length);
/* The padding consists of a length byte at the end of the record and
* then that many bytes of padding, all with the same value as the
* length byte. Thus, with the length byte included, there are i+1
@@ -95,12 +96,12 @@ int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
* decrypted information. Therefore we always have to check the maximum
* amount of padding possible. (Again, the length of the record is
* public information so we can use it.) */
size_t to_check = 256; /* maximum amount of padding, inc length byte. */
to_check = 256; /* maximum amount of padding, inc length byte. */
if (to_check > in_len) {
to_check = in_len;
}
for (size_t i = 0; i < to_check; i++) {
for (i = 0; i < to_check; i++) {
uint8_t mask = constant_time_ge_8(padding_length, i);
uint8_t b = in[in_len - 1 - i];
/* The final |padding_length+1| bytes should all have the value
@@ -110,7 +111,7 @@ int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
/* If any of the final |padding_length+1| bytes had the wrong value,
* one or more of the lower eight bits of |good| will be cleared. */
good = constant_time_eq_s(0xff, good & 0xff);
good = constant_time_eq(0xff, good & 0xff);
/* Always treat |padding_length| as zero on error. If, assuming block size of
* 16, a padding of [<15 arbitrary bytes> 15] treated |padding_length| as 16
@@ -122,15 +123,16 @@ int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
return 1;
}
void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
size_t in_len, size_t orig_len) {
void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
const uint8_t *in, unsigned in_len,
unsigned orig_len) {
uint8_t rotated_mac1[EVP_MAX_MD_SIZE], rotated_mac2[EVP_MAX_MD_SIZE];
uint8_t *rotated_mac = rotated_mac1;
uint8_t *rotated_mac_tmp = rotated_mac2;
/* mac_end is the index of |in| just after the end of the MAC. */
size_t mac_end = in_len;
size_t mac_start = mac_end - md_size;
unsigned mac_end = in_len;
unsigned mac_start = mac_end - md_size;
assert(orig_len >= in_len);
assert(in_len >= md_size);
@@ -138,20 +140,20 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
/* scan_start contains the number of bytes that we can ignore because
* the MAC's position can only vary by 255 bytes. */
size_t scan_start = 0;
unsigned scan_start = 0;
/* This information is public so it's safe to branch based on it. */
if (orig_len > md_size + 255 + 1) {
scan_start = orig_len - (md_size + 255 + 1);
}
size_t rotate_offset = 0;
unsigned rotate_offset = 0;
uint8_t mac_started = 0;
OPENSSL_memset(rotated_mac, 0, md_size);
for (size_t i = scan_start, j = 0; i < orig_len; i++, j++) {
for (unsigned i = scan_start, j = 0; i < orig_len; i++, j++) {
if (j >= md_size) {
j -= md_size;
}
size_t is_mac_start = constant_time_eq_s(i, mac_start);
unsigned is_mac_start = constant_time_eq(i, mac_start);
mac_started |= is_mac_start;
uint8_t mac_ended = constant_time_ge_8(i, mac_end);
rotated_mac[j] |= in[i] & mac_started & ~mac_ended;
@@ -161,11 +163,12 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
/* Now rotate the MAC. We rotate in log(md_size) steps, one for each bit
* position. */
for (size_t offset = 1; offset < md_size; offset <<= 1, rotate_offset >>= 1) {
for (unsigned offset = 1; offset < md_size;
offset <<= 1, rotate_offset >>= 1) {
/* Rotate by |offset| iff the corresponding bit is set in
* |rotate_offset|, placing the result in |rotated_mac_tmp|. */
const uint8_t skip_rotate = (rotate_offset & 1) - 1;
for (size_t i = 0, j = offset; i < md_size; i++, j++) {
for (unsigned i = 0, j = offset; i < md_size; i++, j++) {
if (j >= md_size) {
j -= md_size;
}
@@ -208,49 +211,40 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
*((p)++) = (uint8_t)((n)); \
} while (0)
typedef union {
SHA_CTX sha1;
SHA256_CTX sha256;
SHA512_CTX sha512;
} HASH_CTX;
static void tls1_sha1_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA1_Transform(&ctx->sha1, block);
}
static void tls1_sha256_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA256_Transform(&ctx->sha256, block);
}
static void tls1_sha512_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA512_Transform(&ctx->sha512, block);
}
/* These functions serialize the state of a hash and thus perform the standard
* "final" operation without adding the padding and length that such a function
* typically does. */
static void tls1_sha1_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA_CTX *sha1 = &ctx->sha1;
static void tls1_sha1_final_raw(void *ctx, uint8_t *md_out) {
SHA_CTX *sha1 = ctx;
u32toBE(sha1->h[0], md_out);
u32toBE(sha1->h[1], md_out);
u32toBE(sha1->h[2], md_out);
u32toBE(sha1->h[3], md_out);
u32toBE(sha1->h[4], md_out);
}
#define LARGEST_DIGEST_CTX SHA_CTX
static void tls1_sha256_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA256_CTX *sha256 = &ctx->sha256;
for (unsigned i = 0; i < 8; i++) {
static void tls1_sha256_final_raw(void *ctx, uint8_t *md_out) {
SHA256_CTX *sha256 = ctx;
unsigned i;
for (i = 0; i < 8; i++) {
u32toBE(sha256->h[i], md_out);
}
}
#undef LARGEST_DIGEST_CTX
#define LARGEST_DIGEST_CTX SHA256_CTX
static void tls1_sha512_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA512_CTX *sha512 = &ctx->sha512;
for (unsigned i = 0; i < 8; i++) {
static void tls1_sha512_final_raw(void *ctx, uint8_t *md_out) {
SHA512_CTX *sha512 = ctx;
unsigned i;
for (i = 0; i < 8; i++) {
u64toBE(sha512->h[i], md_out);
}
}
#undef LARGEST_DIGEST_CTX
#define LARGEST_DIGEST_CTX SHA512_CTX
int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) {
switch (EVP_MD_type(md)) {
@@ -270,42 +264,54 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
size_t data_plus_mac_plus_padding_size,
const uint8_t *mac_secret,
unsigned mac_secret_length) {
HASH_CTX md_state;
void (*md_final_raw)(HASH_CTX *ctx, uint8_t *md_out);
void (*md_transform)(HASH_CTX *ctx, const uint8_t *block);
union {
double align;
uint8_t c[sizeof(LARGEST_DIGEST_CTX)];
} md_state;
void (*md_final_raw)(void *ctx, uint8_t *md_out);
void (*md_transform)(void *ctx, const uint8_t *block);
unsigned md_size, md_block_size = 64;
/* md_length_size is the number of bytes in the length field that terminates
* the hash. */
unsigned len, max_mac_bytes, num_blocks, num_starting_blocks, k,
mac_end_offset, c, index_a, index_b;
unsigned int bits; /* at most 18 bits */
uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
/* hmac_pad is the masked HMAC key. */
uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
uint8_t first_block[MAX_HASH_BLOCK_SIZE];
uint8_t mac_out[EVP_MAX_MD_SIZE];
unsigned i, j, md_out_size_u;
EVP_MD_CTX md_ctx;
/* mdLengthSize is the number of bytes in the length field that terminates
* the hash. */
unsigned md_length_size = 8;
/* Bound the acceptable input so we can forget about many possible overflows
* later in this function. This is redundant with the record size limits in
* TLS. */
if (data_plus_mac_plus_padding_size >= 1024 * 1024) {
assert(0);
return 0;
}
/* This is a, hopefully redundant, check that allows us to forget about
* many possible overflows later in this function. */
assert(data_plus_mac_plus_padding_size < 1024 * 1024);
switch (EVP_MD_type(md)) {
case NID_sha1:
SHA1_Init(&md_state.sha1);
SHA1_Init((SHA_CTX *)md_state.c);
md_final_raw = tls1_sha1_final_raw;
md_transform = tls1_sha1_transform;
md_size = SHA_DIGEST_LENGTH;
md_transform =
(void (*)(void *ctx, const uint8_t *block))SHA1_Transform;
md_size = 20;
break;
case NID_sha256:
SHA256_Init(&md_state.sha256);
SHA256_Init((SHA256_CTX *)md_state.c);
md_final_raw = tls1_sha256_final_raw;
md_transform = tls1_sha256_transform;
md_size = SHA256_DIGEST_LENGTH;
md_transform =
(void (*)(void *ctx, const uint8_t *block))SHA256_Transform;
md_size = 32;
break;
case NID_sha384:
SHA384_Init(&md_state.sha512);
SHA384_Init((SHA512_CTX *)md_state.c);
md_final_raw = tls1_sha512_final_raw;
md_transform = tls1_sha512_transform;
md_size = SHA384_DIGEST_LENGTH;
md_transform =
(void (*)(void *ctx, const uint8_t *block))SHA512_Transform;
md_size = 384 / 8;
md_block_size = 128;
md_length_size = 16;
break;
@@ -322,7 +328,7 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
assert(md_size <= EVP_MAX_MD_SIZE);
static const size_t kHeaderLength = 13;
static const unsigned kHeaderLength = 13;
/* kVarianceBlocks is the number of blocks of the hash that we have to
* calculate in constant time because they could be altered by the
@@ -331,16 +337,16 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
* TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
* required to be minimal. Therefore we say that the final six blocks
* can vary based on the padding. */
static const size_t kVarianceBlocks = 6;
static const unsigned kVarianceBlocks = 6;
/* From now on we're dealing with the MAC, which conceptually has 13
* bytes of `header' before the start of the data. */
size_t len = data_plus_mac_plus_padding_size + kHeaderLength;
len = data_plus_mac_plus_padding_size + kHeaderLength;
/* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
* |header|, assuming that there's no padding. */
size_t max_mac_bytes = len - md_size - 1;
* |header|, assuming that there's no padding. */
max_mac_bytes = len - md_size - 1;
/* num_blocks is the maximum number of hash blocks. */
size_t num_blocks =
num_blocks =
(max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
/* In order to calculate the MAC in constant time we have to handle
* the final blocks specially because the padding value could cause the
@@ -348,47 +354,43 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
* can't leak where. However, |num_starting_blocks| worth of data can
* be hashed right away because no padding value can affect whether
* they are plaintext. */
size_t num_starting_blocks = 0;
num_starting_blocks = 0;
/* k is the starting byte offset into the conceptual header||data where
* we start processing. */
size_t k = 0;
k = 0;
/* mac_end_offset is the index just past the end of the data to be
* MACed. */
size_t mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
/* c is the index of the 0x80 byte in the final hash block that
* contains application data. */
size_t c = mac_end_offset % md_block_size;
c = mac_end_offset % md_block_size;
/* index_a is the hash block number that contains the 0x80 terminating
* value. */
size_t index_a = mac_end_offset / md_block_size;
index_a = mac_end_offset / md_block_size;
/* index_b is the hash block number that contains the 64-bit hash
* length, in bits. */
size_t index_b = (mac_end_offset + md_length_size) / md_block_size;
index_b = (mac_end_offset + md_length_size) / md_block_size;
/* bits is the hash-length in bits. It includes the additional hash
* block for the masked HMAC key. */
if (num_blocks > kVarianceBlocks) {
num_starting_blocks = num_blocks - kVarianceBlocks;
k = md_block_size * num_starting_blocks;
}
/* bits is the hash-length in bits. It includes the additional hash
* block for the masked HMAC key. */
size_t bits = 8 * mac_end_offset; /* at most 18 bits to represent */
bits = 8 * mac_end_offset;
/* Compute the initial HMAC block. */
bits += 8 * md_block_size;
/* hmac_pad is the masked HMAC key. */
uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
OPENSSL_memset(hmac_pad, 0, md_block_size);
assert(mac_secret_length <= sizeof(hmac_pad));
OPENSSL_memcpy(hmac_pad, mac_secret, mac_secret_length);
for (size_t i = 0; i < md_block_size; i++) {
for (i = 0; i < md_block_size; i++) {
hmac_pad[i] ^= 0x36;
}
md_transform(&md_state, hmac_pad);
md_transform(md_state.c, hmac_pad);
/* The length check means |bits| fits in four bytes. */
uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
OPENSSL_memset(length_bytes, 0, md_length_size - 4);
length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24);
length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16);
@@ -397,29 +399,27 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
if (k > 0) {
/* k is a multiple of md_block_size. */
uint8_t first_block[MAX_HASH_BLOCK_SIZE];
OPENSSL_memcpy(first_block, header, 13);
OPENSSL_memcpy(first_block + 13, data, md_block_size - 13);
md_transform(&md_state, first_block);
for (size_t i = 1; i < k / md_block_size; i++) {
md_transform(&md_state, data + md_block_size * i - 13);
md_transform(md_state.c, first_block);
for (i = 1; i < k / md_block_size; i++) {
md_transform(md_state.c, data + md_block_size * i - 13);
}
}
uint8_t mac_out[EVP_MAX_MD_SIZE];
OPENSSL_memset(mac_out, 0, sizeof(mac_out));
/* We now process the final hash blocks. For each block, we construct
* it in constant time. If the |i==index_a| then we'll include the 0x80
* bytes and zero pad etc. For each block we selectively copy it, in
* constant time, to |mac_out|. */
for (size_t i = num_starting_blocks;
i <= num_starting_blocks + kVarianceBlocks; i++) {
for (i = num_starting_blocks; i <= num_starting_blocks + kVarianceBlocks;
i++) {
uint8_t block[MAX_HASH_BLOCK_SIZE];
uint8_t is_block_a = constant_time_eq_8(i, index_a);
uint8_t is_block_b = constant_time_eq_8(i, index_b);
for (size_t j = 0; j < md_block_size; j++) {
uint8_t b = 0;
for (j = 0; j < md_block_size; j++) {
uint8_t b = 0, is_past_c, is_past_cp1;
if (k < kHeaderLength) {
b = header[k];
} else if (k < data_plus_mac_plus_padding_size + kHeaderLength) {
@@ -427,8 +427,8 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
}
k++;
uint8_t is_past_c = is_block_a & constant_time_ge_8(j, c);
uint8_t is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
is_past_c = is_block_a & constant_time_ge_8(j, c);
is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
/* If this is the block containing the end of the
* application data, and we are at the offset for the
* 0x80 value, then overwrite b with 0x80. */
@@ -453,15 +453,14 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
block[j] = b;
}
md_transform(&md_state, block);
md_final_raw(&md_state, block);
md_transform(md_state.c, block);
md_final_raw(md_state.c, block);
/* If this is index_b, copy the hash value to |mac_out|. */
for (size_t j = 0; j < md_size; j++) {
for (j = 0; j < md_size; j++) {
mac_out[j] |= block[j] & is_block_b;
}
}
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) {
EVP_MD_CTX_cleanup(&md_ctx);
@@ -469,13 +468,12 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
}
/* Complete the HMAC in the standard manner. */
for (size_t i = 0; i < md_block_size; i++) {
for (i = 0; i < md_block_size; i++) {
hmac_pad[i] ^= 0x6a;
}
EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
EVP_DigestUpdate(&md_ctx, mac_out, md_size);
unsigned md_out_size_u;
EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
*md_out_size = md_out_size_u;
EVP_MD_CTX_cleanup(&md_ctx);
+1 -13
View File
@@ -69,10 +69,6 @@
#include "../internal.h"
/* The maximum length we can grow a value to after variable expansion. 64k
* should be more than enough for all reasonable uses. */
#define MAX_CONF_VALUE_LENGTH 65536
static uint32_t conf_value_hash(const CONF_VALUE *v) {
return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name);
}
@@ -320,15 +316,7 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from) {
OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_HAS_NO_VALUE);
goto err;
}
size_t newsize = strlen(p) + buf->length - (e - from);
if (newsize > MAX_CONF_VALUE_LENGTH) {
OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
goto err;
}
if (!BUF_MEM_grow_clean(buf, newsize)) {
OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
BUF_MEM_grow_clean(buf, (strlen(p) + buf->length - (e - from)));
while (*p) {
buf->data[to++] = *(p++);
}
+234 -63
View File
@@ -49,88 +49,259 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits>
#include <gtest/gtest.h>
static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
static const unsigned int CONSTTIME_FALSE = 0;
static const uint8_t CONSTTIME_TRUE_8 = 0xff;
static const uint8_t CONSTTIME_FALSE_8 = 0;
static uint8_t FromBool8(bool b) {
return b ? CONSTTIME_TRUE_8 : CONSTTIME_FALSE_8;
static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
const char* op_name, unsigned int a, unsigned int b,
int is_true) {
unsigned c = op(a, b);
if (is_true && c != CONSTTIME_TRUE) {
fprintf(stderr,
"Test failed for %s(%du, %du): expected %du (TRUE), got %du\n",
op_name, a, b, CONSTTIME_TRUE, c);
return 1;
} else if (!is_true && c != CONSTTIME_FALSE) {
fprintf(stderr,
"Test failed for %s(%du, %du): expected %du (FALSE), got %du\n",
op_name, a, b, CONSTTIME_FALSE, c);
return 1;
}
return 0;
}
static size_t FromBoolS(bool b) {
return b ? CONSTTIME_TRUE_S : CONSTTIME_FALSE_S;
static int test_binary_op_8(uint8_t (*op)(unsigned int a, unsigned int b),
const char* op_name, unsigned int a, unsigned int b,
int is_true) {
uint8_t c = op(a, b);
if (is_true && c != CONSTTIME_TRUE_8) {
fprintf(stderr,
"Test failed for %s(%du, %du): expected %u (TRUE), got %u\n",
op_name, a, b, CONSTTIME_TRUE_8, c);
return 1;
} else if (!is_true && c != CONSTTIME_FALSE_8) {
fprintf(stderr,
"Test failed for %s(%du, %du): expected %u (FALSE), got %u\n",
op_name, a, b, CONSTTIME_FALSE_8, c);
return 1;
}
return 0;
}
static const uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
static int test_is_zero(unsigned int a) {
unsigned int c = constant_time_is_zero(a);
if (a == 0 && c != CONSTTIME_TRUE) {
fprintf(stderr,
"Test failed for constant_time_is_zero(%du): expected %du (TRUE), "
"got %du\n",
a, CONSTTIME_TRUE, c);
return 1;
} else if (a != 0 && c != CONSTTIME_FALSE) {
fprintf(stderr,
"Test failed for constant_time_is_zero(%du): expected %du (FALSE), "
"got %du\n",
a, CONSTTIME_FALSE, c);
return 1;
}
return 0;
}
static size_t test_values_s[] = {
0,
1,
1024,
12345,
32000,
#if defined(OPENSSL_64_BIT)
0xffffffff / 2 - 1,
0xffffffff / 2,
0xffffffff / 2 + 1,
0xffffffff - 1,
0xffffffff,
#endif
std::numeric_limits<size_t>::max() / 2 - 1,
std::numeric_limits<size_t>::max() / 2,
std::numeric_limits<size_t>::max() / 2 + 1,
std::numeric_limits<size_t>::max() - 1,
std::numeric_limits<size_t>::max(),
};
static int test_is_zero_8(unsigned int a) {
uint8_t c = constant_time_is_zero_8(a);
if (a == 0 && c != CONSTTIME_TRUE_8) {
fprintf(stderr,
"Test failed for constant_time_is_zero(%du): expected %u (TRUE), "
"got %u\n",
a, CONSTTIME_TRUE_8, c);
return 1;
} else if (a != 0 && c != CONSTTIME_FALSE) {
fprintf(stderr,
"Test failed for constant_time_is_zero(%du): expected %u (FALSE), "
"got %u\n",
a, CONSTTIME_FALSE_8, c);
return 1;
}
return 0;
}
static int test_select(unsigned int a, unsigned int b) {
unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
if (selected != a) {
fprintf(stderr,
"Test failed for constant_time_select(%du, %du,"
"%du): expected %du(first value), got %du\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select(CONSTTIME_FALSE, a, b);
if (selected != b) {
fprintf(stderr,
"Test failed for constant_time_select(%du, %du,"
"%du): expected %du(second value), got %du\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}
static int test_select_8(uint8_t a, uint8_t b) {
uint8_t selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
if (selected != a) {
fprintf(stderr,
"Test failed for constant_time_select(%u, %u,"
"%u): expected %u(first value), got %u\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
if (selected != b) {
fprintf(stderr,
"Test failed for constant_time_select(%u, %u,"
"%u): expected %u(second value), got %u\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}
static int test_select_int(int a, int b) {
int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
if (selected != a) {
fprintf(stderr,
"Test failed for constant_time_select(%du, %d,"
"%d): expected %d(first value), got %d\n",
CONSTTIME_TRUE, a, b, a, selected);
return 1;
}
selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
if (selected != b) {
fprintf(stderr,
"Test failed for constant_time_select(%du, %d,"
"%d): expected %d(second value), got %d\n",
CONSTTIME_FALSE, a, b, b, selected);
return 1;
}
return 0;
}
static int test_eq_int(int a, int b) {
unsigned int equal = constant_time_eq_int(a, b);
if (a == b && equal != CONSTTIME_TRUE) {
fprintf(stderr,
"Test failed for constant_time_eq_int(%d, %d): expected %du(TRUE), "
"got %du\n",
a, b, CONSTTIME_TRUE, equal);
return 1;
} else if (a != b && equal != CONSTTIME_FALSE) {
fprintf(stderr,
"Test failed for constant_time_eq_int(%d, %d): expected "
"%du(FALSE), got %du\n",
a, b, CONSTTIME_FALSE, equal);
return 1;
}
return 0;
}
static int test_eq_int_8(int a, int b) {
uint8_t equal = constant_time_eq_int_8(a, b);
if (a == b && equal != CONSTTIME_TRUE_8) {
fprintf(stderr,
"Test failed for constant_time_eq_int_8(%d, %d): expected "
"%u(TRUE), got %u\n",
a, b, CONSTTIME_TRUE_8, equal);
return 1;
} else if (a != b && equal != CONSTTIME_FALSE_8) {
fprintf(stderr,
"Test failed for constant_time_eq_int_8(%d, %d): expected "
"%u(FALSE), got %u\n",
a, b, CONSTTIME_FALSE_8, equal);
return 1;
}
return 0;
}
static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1,
UINT_MAX / 2, UINT_MAX / 2 + 1,
UINT_MAX - 1, UINT_MAX};
static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
static int signed_test_values[] = {
0, 1, -1, 1024, -1024, 12345, -12345,
32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
TEST(ConstantTimeTest, Test) {
for (size_t a : test_values_s) {
SCOPED_TRACE(a);
int main(int argc, char* argv[]) {
unsigned int a, b, i, j;
int c, d;
uint8_t e, f;
int num_failed = 0, num_all = 0;
fprintf(stdout, "Testing constant time operations...\n");
EXPECT_EQ(FromBoolS(a == 0), constant_time_is_zero_s(a));
EXPECT_EQ(FromBool8(a == 0), constant_time_is_zero_8(a));
for (size_t b : test_values_s) {
SCOPED_TRACE(b);
EXPECT_EQ(FromBoolS(a < b), constant_time_lt_s(a, b));
EXPECT_EQ(FromBool8(a < b), constant_time_lt_8(a, b));
EXPECT_EQ(FromBoolS(a >= b), constant_time_ge_s(a, b));
EXPECT_EQ(FromBool8(a >= b), constant_time_ge_8(a, b));
EXPECT_EQ(FromBoolS(a == b), constant_time_eq_s(a, b));
EXPECT_EQ(FromBool8(a == b), constant_time_eq_8(a, b));
EXPECT_EQ(a, constant_time_select_s(CONSTTIME_TRUE_S, a, b));
EXPECT_EQ(b, constant_time_select_s(CONSTTIME_FALSE_S, a, b));
for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) {
a = test_values[i];
num_failed += test_is_zero(a);
num_failed += test_is_zero_8(a);
num_all += 2;
for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) {
b = test_values[j];
num_failed +=
test_binary_op(&constant_time_lt, "constant_time_lt", a, b, a < b);
num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
a, b, a < b);
num_failed +=
test_binary_op(&constant_time_lt, "constant_time_lt_8", b, a, b < a);
num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
b, a, b < a);
num_failed +=
test_binary_op(&constant_time_ge, "constant_time_ge", a, b, a >= b);
num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
a, b, a >= b);
num_failed +=
test_binary_op(&constant_time_ge, "constant_time_ge", b, a, b >= a);
num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
b, a, b >= a);
num_failed +=
test_binary_op(&constant_time_eq, "constant_time_eq", a, b, a == b);
num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
a, b, a == b);
num_failed +=
test_binary_op(&constant_time_eq, "constant_time_eq", b, a, b == a);
num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
b, a, b == a);
num_failed += test_select(a, b);
num_all += 13;
}
}
for (int a : signed_test_values) {
SCOPED_TRACE(a);
for (int b : signed_test_values) {
SCOPED_TRACE(b);
EXPECT_EQ(a, constant_time_select_int(CONSTTIME_TRUE_S, a, b));
EXPECT_EQ(b, constant_time_select_int(CONSTTIME_FALSE_S, a, b));
EXPECT_EQ(FromBoolS(a == b), constant_time_eq_int(a, b));
EXPECT_EQ(FromBool8(a == b), constant_time_eq_int_8(a, b));
for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) {
c = signed_test_values[i];
for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) {
d = signed_test_values[j];
num_failed += test_select_int(c, d);
num_failed += test_eq_int(c, d);
num_failed += test_eq_int_8(c, d);
num_all += 3;
}
}
for (uint8_t a : test_values_8) {
SCOPED_TRACE(static_cast<int>(a));
for (uint8_t b : test_values_8) {
SCOPED_TRACE(static_cast<int>(b));
EXPECT_EQ(a, constant_time_select_8(CONSTTIME_TRUE_8, a, b));
EXPECT_EQ(b, constant_time_select_8(CONSTTIME_FALSE_8, a, b));
for (i = 0; i < sizeof(test_values_8); ++i) {
e = test_values_8[i];
for (j = 0; j < sizeof(test_values_8); ++j) {
f = test_values_8[j];
num_failed += test_select_8(e, f);
num_all += 1;
}
}
if (!num_failed) {
fprintf(stdout, "ok (ran %d tests)\n", num_all);
fprintf(stdout, "PASS\n");
return EXIT_SUCCESS;
} else {
fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
return EXIT_FAILURE;
}
}
+4 -2
View File
@@ -27,12 +27,14 @@
#define PPC_FEATURE2_HAS_VCRYPTO 0x02000000
#endif
static unsigned long g_ppc64le_hwcap2 = 0;
void OPENSSL_cpuid_setup(void) {
OPENSSL_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
g_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
}
int CRYPTO_is_PPC64LE_vcrypto_capable(void) {
return (OPENSSL_ppc64le_hwcap2 & PPC_FEATURE2_HAS_VCRYPTO) != 0;
return (g_ppc64le_hwcap2 & PPC_FEATURE2_HAS_VCRYPTO) != 0;
}
#endif /* OPENSSL_PPC64LE */
-6
View File
@@ -49,7 +49,6 @@
* far, the init constructor function only sets the capability variables. */
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
/* This value must be explicitly initialised to zero in order to work around a
* bug in libtool or the linker on OS X.
*
@@ -58,11 +57,6 @@
* initialising it to zero, it becomes a "data symbol", which isn't so
* affected. */
uint32_t OPENSSL_ia32cap_P[4] = {0};
#elif defined(OPENSSL_PPC64LE)
unsigned long OPENSSL_ppc64le_hwcap2 = 0;
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
#include <openssl/arm_arch.h>
+9
View File
@@ -38,6 +38,15 @@ add_executable(
target_link_libraries(ed25519_test crypto)
add_dependencies(all_tests ed25519_test)
add_executable(
x25519_test
x25519_test.cc
)
target_link_libraries(x25519_test crypto)
add_dependencies(all_tests x25519_test)
add_executable(
spake25519_test
File diff suppressed because it is too large Load Diff
-13
View File
@@ -2575,16 +2575,3 @@ PRIV: 4f4b20d899366f2f23ee628f229b236cf80f43ba183177c97ee34829546f1742c94576641f
PUB: c94576641f4a893cdfcee7b39fc21929b86b349976d7b0a46d39a588bcfe4357
MESSAGE: db8ef02e3033e6b96a56cab05082fb4695f4a1c916250dd75173f430a10c9468817709d37623346ae8245b42bda0da6b60462ccfdfc75a9ab994e66c9ab9fecdd8599610910affe4f10215cb280bf8f9f2700a444796dae93e06c6bea7d8b4fe1301baa79ccec769368feb2442c7de84f095e6b3bff63d388cbafb2b9809dc38e9b12ebd039c0a57f4d522e91ec8d1f2b8d23a4a0ae059af85393bb0a15f749110f6774a1fd731a6ec213e4ff435daab546d31ed9ec3b6d8cc2edacebf4facc5566556eea92e5b3f2542239b25e28012dd4ef40072eebf83ed2a255181f3a442189d68c6c609f4dfdf3db7d67d087a2fcd6d2dc50bbfed8bfbbfcb74d3c41f02a87865b13b8efcf5c3581257be0aa913f60c370527bde11a475c136a17c5eefeb03f5bff28693ed841e8ed1f7c29102f5599dd444009bcea6a92d5574152458e0caf8a36aa72b5dc4908a6461c9b741453005c8fbcc68113ae184208ee14b835480c6efafed18a76000b38e5858290f4d51f52f096cbe490e1eb5cacb226ec495a55a7fa457843d57fab67f8be7e209334785bdd665d7b63e4daf57b6e78928b603c8c0f9bc85464733b61273ef9e2b8a0cd7c3bf8ee0a6872e34d5a27a625e35eaf7ff5440b8b141af704df70c9c18623bd11209513192505105cd7bcfa5f0d919da706948fbe1f761f315846aa3b4813dd9ba3d81b9204e5409c0382b6eb
SIG: 0f80ff5d17488fe26f93c543b04ed959b5f0643fc61c7f2c3bc60132ba9c6210c8b250ea5e84d07b01de68bc174414eeeb31fdc2ba6823e231e312a91ededd02
# Additional test vectors from RFC 8032
PRIV: f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
PUB: 278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
MESSAGE: 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0
SIG: 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03
PRIV: 833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
PUB: ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
MESSAGE: ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
SIG: dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704
+42 -21
View File
@@ -16,16 +16,13 @@
#include <stdio.h>
#include <string.h>
#include <gtest/gtest.h>
#include <openssl/curve25519.h>
#include "../internal.h"
#include "../test/test_util.h"
TEST(X25519Test, TestVector) {
// Taken from https://tools.ietf.org/html/rfc7748#section-5.2
static bool TestX25519() {
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
static const uint8_t kScalar1[32] = {
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
@@ -38,14 +35,17 @@ TEST(X25519Test, TestVector) {
};
uint8_t out[32];
EXPECT_TRUE(X25519(out, kScalar1, kPoint1));
X25519(out, kScalar1, kPoint1);
static const uint8_t kExpected1[32] = {
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52,
};
EXPECT_EQ(Bytes(kExpected1), Bytes(out));
if (OPENSSL_memcmp(kExpected1, out, sizeof(out)) != 0) {
fprintf(stderr, "X25519 test one failed.\n");
return false;
}
static const uint8_t kScalar2[32] = {
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26,
@@ -58,17 +58,22 @@ TEST(X25519Test, TestVector) {
0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
};
EXPECT_TRUE(X25519(out, kScalar2, kPoint2));
X25519(out, kScalar2, kPoint2);
static const uint8_t kExpected2[32] = {
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4,
0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f,
0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
};
EXPECT_EQ(Bytes(kExpected2), Bytes(out));
if (OPENSSL_memcmp(kExpected2, out, sizeof(out)) != 0) {
fprintf(stderr, "X25519 test two failed.\n");
return false;
}
return true;
}
TEST(X25519Test, SmallOrder) {
static bool TestX25519SmallOrder() {
static const uint8_t kSmallOrderPoint[32] = {
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
@@ -78,21 +83,21 @@ TEST(X25519Test, SmallOrder) {
uint8_t out[32], private_key[32];
OPENSSL_memset(private_key, 0x11, sizeof(private_key));
OPENSSL_memset(out, 0xff, sizeof(out));
EXPECT_FALSE(X25519(out, private_key, kSmallOrderPoint))
<< "X25519 returned success with a small-order input.";
if (X25519(out, private_key, kSmallOrderPoint)) {
fprintf(stderr, "X25519 returned success with a small-order input.\n");
return false;
}
// For callers which don't check, |out| should still be filled with zeros.
static const uint8_t kZeros[32] = {0};
EXPECT_EQ(Bytes(kZeros), Bytes(out));
return true;
}
TEST(X25519Test, Iterated) {
// Taken from https://tools.ietf.org/html/rfc7748#section-5.2.
static bool TestX25519Iterated() {
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
for (unsigned i = 0; i < 1000; i++) {
EXPECT_TRUE(X25519(out, scalar, point));
unsigned i;
for (i = 0; i < 1000; i++) {
X25519(out, scalar, point);
OPENSSL_memcpy(point, scalar, sizeof(point));
OPENSSL_memcpy(scalar, out, sizeof(scalar));
}
@@ -103,5 +108,21 @@ TEST(X25519Test, Iterated) {
0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51,
};
EXPECT_EQ(Bytes(kExpected), Bytes(scalar));
if (OPENSSL_memcmp(kExpected, scalar, sizeof(kExpected)) != 0) {
fprintf(stderr, "Iterated X25519 test failed\n");
return false;
}
return true;
}
int main(int argc, char **argv) {
if (!TestX25519() ||
!TestX25519Iterated() ||
!TestX25519SmallOrder()) {
return 1;
}
printf("PASS\n");
return 0;
}
+11
View File
@@ -10,3 +10,14 @@ add_library(
check.c
dh_asn1.c
)
add_executable(
dh_test
dh_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(dh_test crypto)
add_dependencies(all_tests dh_test)
+2 -2
View File
@@ -93,7 +93,7 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) {
/* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114
* groups which are not safe primes but pick a generator on a prime-order
* subgroup of size |dh->q|. */
if (!BN_mod_exp_mont(tmp, pub_key, dh->q, dh->p, ctx, NULL)) {
if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) {
goto err;
}
if (!BN_is_one(tmp)) {
@@ -145,7 +145,7 @@ int DH_check(const DH *dh, int *ret) {
*ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
} else {
/* Check g^q == 1 mod p */
if (!BN_mod_exp_mont(t1, dh->g, dh->q, dh->p, ctx, NULL)) {
if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) {
goto err;
}
if (!BN_is_one(t1)) {
+8 -5
View File
@@ -61,8 +61,6 @@
#include <vector>
#include <gtest/gtest.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
@@ -79,15 +77,20 @@ static bool TestBadY();
static bool TestASN1();
static bool TestRFC3526();
// TODO(davidben): Convert this file to GTest properly.
TEST(DHTest, AllTests) {
int main() {
CRYPTO_library_init();
if (!RunBasicTests() ||
!RunRFC5114Tests() ||
!TestBadY() ||
!TestASN1() ||
!TestRFC3526()) {
ADD_FAILURE() << "Tests failed.";
ERR_print_errors_fp(stderr);
return 1;
}
printf("PASS\n");
return 0;
}
static int GenerateCallback(int p, int n, BN_GENCB *arg) {
+7 -10
View File
@@ -18,14 +18,12 @@
#include <memory>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/nid.h>
#include <openssl/obj.h>
#include <openssl/sha.h>
#include "../internal.h"
@@ -225,6 +223,13 @@ static int TestDigest(const TestVector *test) {
if (!CompareDigest(test, digest.get(), EVP_MD_size(test->md.func()))) {
return false;
}
// Test the deprecated static buffer variant, until it's removed.
out = test->md.one_shot_func((const uint8_t *)test->input,
strlen(test->input), NULL);
if (!CompareDigest(test, out, EVP_MD_size(test->md.func()))) {
return false;
}
}
return true;
@@ -245,14 +250,6 @@ static int TestGetters() {
return false;
}
bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj("1.3.14.3.2.26", 0));
if (!obj ||
EVP_get_digestbyobj(obj.get()) != EVP_sha1() ||
EVP_get_digestbyobj(OBJ_nid2obj(NID_md5_sha1)) != EVP_md5_sha1() ||
EVP_get_digestbyobj(OBJ_nid2obj(NID_sha1)) != EVP_sha1()) {
return false;
}
return true;
}
+3 -47
View File
@@ -60,7 +60,6 @@
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/bytestring.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/nid.h>
@@ -329,11 +328,10 @@ static const struct {
{ {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, EVP_sha224 },
};
static const EVP_MD *cbs_to_md(const CBS *cbs) {
const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj) {
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
if (CBS_len(cbs) == kMDOIDs[i].oid_len &&
OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) ==
0) {
if (obj->length == kMDOIDs[i].oid_len &&
memcmp(obj->data, kMDOIDs[i].oid, obj->length) == 0) {
return kMDOIDs[i].md_func();
}
}
@@ -341,48 +339,6 @@ static const EVP_MD *cbs_to_md(const CBS *cbs) {
return NULL;
}
const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj) {
/* Handle objects with no corresponding OID. */
if (obj->nid != NID_undef) {
return EVP_get_digestbynid(obj->nid);
}
CBS cbs;
CBS_init(&cbs, obj->data, obj->length);
return cbs_to_md(&cbs);
}
const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs) {
CBS algorithm, oid;
if (!CBS_get_asn1(cbs, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) {
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR);
return NULL;
}
const EVP_MD *ret = cbs_to_md(&oid);
if (ret == NULL) {
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_UNKNOWN_HASH);
return NULL;
}
/* The parameters, if present, must be NULL. Historically, whether the NULL
* was included or omitted was not well-specified. When parsing an
* AlgorithmIdentifier, we allow both. (Note this code is not used when
* verifying RSASSA-PKCS1-v1_5 signatures.) */
if (CBS_len(&algorithm) > 0) {
CBS param;
if (!CBS_get_asn1(&algorithm, &param, CBS_ASN1_NULL) ||
CBS_len(&param) != 0 ||
CBS_len(&algorithm) != 0) {
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR);
return NULL;
}
}
return ret;
}
const EVP_MD *EVP_get_digestbyname(const char *name) {
for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) {
const char *short_name = nid_to_digest_mapping[i].short_name;
-2
View File
@@ -104,8 +104,6 @@ struct evp_md_pctx_ops {
EVP_PKEY_CTX* (*dup) (EVP_PKEY_CTX *pctx);
};
const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs);
#if defined(__cplusplus)
} /* extern C */
+11
View File
@@ -8,3 +8,14 @@ add_library(
dsa.c
dsa_asn1.c
)
add_executable(
dsa_test
dsa_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(dsa_test crypto)
add_dependencies(all_tests dsa_test)
+8 -5
View File
@@ -62,8 +62,6 @@
#include <stdio.h>
#include <string.h>
#include <gtest/gtest.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
@@ -304,14 +302,19 @@ static bool TestVerify(const uint8_t *sig, size_t sig_len, int expect) {
return true;
}
// TODO(davidben): Convert this file to GTest properly.
TEST(DSATest, AllTests) {
int main(int argc, char **argv) {
CRYPTO_library_init();
if (!TestGenerate(stdout) ||
!TestVerify(fips_sig, sizeof(fips_sig), 1) ||
!TestVerify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
!TestVerify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
!TestVerify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
!TestVerify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
ADD_FAILURE() << "Tests failed";
ERR_print_errors_fp(stderr);
return 1;
}
printf("PASS\n");
return 0;
}
+10 -1
View File
@@ -38,6 +38,14 @@ add_executable(
$<TARGET_OBJECTS:test_support>
)
add_executable(
ec_test
ec_test.cc
$<TARGET_OBJECTS:test_support>
)
add_executable(
p256-x86_64_test
@@ -47,5 +55,6 @@ add_executable(
)
target_link_libraries(example_mul crypto)
target_link_libraries(ec_test crypto)
target_link_libraries(p256-x86_64_test crypto)
add_dependencies(all_tests example_mul p256-x86_64_test)
add_dependencies(all_tests example_mul ec_test p256-x86_64_test)
+6 -6
View File
@@ -289,7 +289,7 @@ __ecp_nistz256_mul_montq:
adc \$0, $acc0
########################################################################
# Second reduction step
# Second reduction step
mov $acc1, $t1
shl \$32, $acc1
mulq $poly3
@@ -336,7 +336,7 @@ __ecp_nistz256_mul_montq:
adc \$0, $acc1
########################################################################
# Third reduction step
# Third reduction step
mov $acc2, $t1
shl \$32, $acc2
mulq $poly3
@@ -383,7 +383,7 @@ __ecp_nistz256_mul_montq:
adc \$0, $acc2
########################################################################
# Final reduction step
# Final reduction step
mov $acc3, $t1
shl \$32, $acc3
mulq $poly3
@@ -396,7 +396,7 @@ __ecp_nistz256_mul_montq:
mov $acc5, $t1
adc \$0, $acc2
########################################################################
########################################################################
# Branch-less conditional subtraction of P
sub \$-1, $acc4 # .Lpoly[0]
mov $acc0, $t2
@@ -1649,7 +1649,7 @@ $code.=<<___;
movq %xmm1, $r_ptr
call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(res_y, S);
___
{
{
######## ecp_nistz256_div_by_2(res_y, res_y); ##########################
# operate in 4-5-6-7 "name space" that matches squaring output
#
@@ -1738,7 +1738,7 @@ $code.=<<___;
lea $M(%rsp), $b_ptr
mov $acc4, $acc6 # harmonize sub output and mul input
xor %ecx, %ecx
mov $acc4, $S+8*0(%rsp) # have to save:-(
mov $acc4, $S+8*0(%rsp) # have to save:-(
mov $acc5, $acc2
mov $acc5, $S+8*1(%rsp)
cmovz $acc0, $acc3
+298 -152
View File
@@ -17,8 +17,6 @@
#include <vector>
#include <gtest/gtest.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
@@ -26,9 +24,6 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/nid.h>
#include <openssl/obj.h>
#include "../test/test_util.h"
// kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
@@ -128,75 +123,201 @@ static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
return true;
}
TEST(ECTest, Encoding) {
bssl::UniquePtr<EC_KEY> key =
DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
ASSERT_TRUE(key);
static bool Testd2i_ECPrivateKey() {
bssl::UniquePtr<EC_KEY> key = DecodeECPrivateKey(kECKeyWithoutPublic,
sizeof(kECKeyWithoutPublic));
if (!key) {
fprintf(stderr, "Failed to parse private key.\n");
ERR_print_errors_fp(stderr);
return false;
}
// Test that the encoding round-trips.
std::vector<uint8_t> out;
ASSERT_TRUE(EncodeECPrivateKey(&out, key.get()));
EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
if (!EncodeECPrivateKey(&out, key.get())) {
fprintf(stderr, "Failed to serialize private key.\n");
ERR_print_errors_fp(stderr);
return false;
}
if (std::vector<uint8_t>(kECKeyWithoutPublic,
kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) !=
out) {
fprintf(stderr, "Serialisation of key doesn't match original.\n");
return false;
}
const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
ASSERT_TRUE(pub_key) << "Public key missing";
if (pub_key == NULL) {
fprintf(stderr, "Public key missing.\n");
return false;
}
bssl::UniquePtr<BIGNUM> x(BN_new());
bssl::UniquePtr<BIGNUM> y(BN_new());
ASSERT_TRUE(x);
ASSERT_TRUE(y);
ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL));
if (!x || !y) {
return false;
}
if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
pub_key, x.get(), y.get(), NULL)) {
fprintf(stderr, "Failed to get public key in affine coordinates.\n");
return false;
}
bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
ASSERT_TRUE(x_hex);
ASSERT_TRUE(y_hex);
if (!x_hex || !y_hex) {
return false;
}
if (0 != strcmp(
x_hex.get(),
"c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681") ||
0 != strcmp(
y_hex.get(),
"e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88")) {
fprintf(stderr, "Incorrect public key: %s %s\n", x_hex.get(), y_hex.get());
return false;
}
EXPECT_STREQ(
"c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681",
x_hex.get());
EXPECT_STREQ(
"e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88",
y_hex.get());
return true;
}
TEST(ECTest, ZeroPadding) {
static bool TestZeroPadding() {
// Check that the correct encoding round-trips.
bssl::UniquePtr<EC_KEY> key =
DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros));
ASSERT_TRUE(key);
bssl::UniquePtr<EC_KEY> key = DecodeECPrivateKey(kECKeyWithZeros,
sizeof(kECKeyWithZeros));
std::vector<uint8_t> out;
EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
if (!key || !EncodeECPrivateKey(&out, key.get())) {
ERR_print_errors_fp(stderr);
return false;
}
if (std::vector<uint8_t>(kECKeyWithZeros,
kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) {
fprintf(stderr, "Serialisation of key was incorrect.\n");
return false;
}
// Keys without leading zeros also parse, but they encode correctly.
key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
ASSERT_TRUE(key);
EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
if (!key || !EncodeECPrivateKey(&out, key.get())) {
ERR_print_errors_fp(stderr);
return false;
}
if (std::vector<uint8_t>(kECKeyWithZeros,
kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) {
fprintf(stderr, "Serialisation of key was incorrect.\n");
return false;
}
return true;
}
TEST(ECTest, SpecifiedCurve) {
static bool TestSpecifiedCurve() {
// Test keys with specified curves may be decoded.
bssl::UniquePtr<EC_KEY> key =
DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
ASSERT_TRUE(key);
if (!key) {
ERR_print_errors_fp(stderr);
return false;
}
// The group should have been interpreted as P-256.
EXPECT_EQ(NID_X9_62_prime256v1,
EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())));
if (EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())) !=
NID_X9_62_prime256v1) {
fprintf(stderr, "Curve name incorrect.\n");
return false;
}
// Encoding the key should still use named form.
std::vector<uint8_t> out;
EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
if (!EncodeECPrivateKey(&out, key.get())) {
ERR_print_errors_fp(stderr);
return false;
}
if (std::vector<uint8_t>(kECKeyWithoutPublic,
kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) !=
out) {
fprintf(stderr, "Serialisation of key was incorrect.\n");
return false;
}
return true;
}
TEST(ECTest, ArbitraryCurve) {
static bool TestSetAffine(const int nid) {
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
if (!key) {
return false;
}
const EC_GROUP *const group = EC_KEY_get0_group(key.get());
if (!EC_KEY_generate_key(key.get())) {
fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid);
ERR_print_errors_fp(stderr);
return false;
}
if (!EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()),
nullptr)) {
fprintf(stderr, "generated point is not on curve with nid %d", nid);
ERR_print_errors_fp(stderr);
return false;
}
bssl::UniquePtr<BIGNUM> x(BN_new());
bssl::UniquePtr<BIGNUM> y(BN_new());
if (!EC_POINT_get_affine_coordinates_GFp(group,
EC_KEY_get0_public_key(key.get()),
x.get(), y.get(), nullptr)) {
fprintf(stderr, "EC_POINT_get_affine_coordinates_GFp failed with nid %d\n",
nid);
ERR_print_errors_fp(stderr);
return false;
}
auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group));
if (!point) {
return false;
}
if (!EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(), y.get(),
nullptr)) {
fprintf(stderr, "EC_POINT_set_affine_coordinates_GFp failed with nid %d\n",
nid);
ERR_print_errors_fp(stderr);
return false;
}
// Subtract one from |y| to make the point no longer on the curve.
if (!BN_sub(y.get(), y.get(), BN_value_one())) {
return false;
}
bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group));
if (!invalid_point) {
return false;
}
if (EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(), x.get(),
y.get(), nullptr)) {
fprintf(stderr,
"EC_POINT_set_affine_coordinates_GFp succeeded with invalid "
"coordinates with nid %d\n",
nid);
ERR_print_errors_fp(stderr);
return false;
}
return true;
}
static bool TestArbitraryCurve() {
// Make a P-256 key and extract the affine coordinates.
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
ASSERT_TRUE(key);
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
if (!key || !EC_KEY_generate_key(key.get())) {
return false;
}
// Make an arbitrary curve which is identical to P-256.
static const uint8_t kP[] = {
@@ -230,161 +351,186 @@ TEST(ECTest, ArbitraryCurve) {
0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
};
bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
ASSERT_TRUE(ctx);
bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
ASSERT_TRUE(p);
bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
ASSERT_TRUE(a);
bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
ASSERT_TRUE(b);
bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr));
ASSERT_TRUE(gx);
bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr));
ASSERT_TRUE(gy);
bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
ASSERT_TRUE(order);
bssl::UniquePtr<BIGNUM> cofactor(BN_new());
if (!ctx || !p || !a || !b || !gx || !gy || !order || !cofactor ||
!BN_set_word(cofactor.get(), 1)) {
return false;
}
bssl::UniquePtr<EC_GROUP> group(
EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
ASSERT_TRUE(group);
if (!group) {
return false;
}
bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
ASSERT_TRUE(generator);
ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
group.get(), generator.get(), gx.get(), gy.get(), ctx.get()));
ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
BN_value_one()));
if (!generator ||
!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(),
gx.get(), gy.get(), ctx.get()) ||
!EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
cofactor.get())) {
return false;
}
// |group| should not have a curve name.
EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get()));
if (EC_GROUP_get_curve_name(group.get()) != NID_undef) {
return false;
}
// Copy |key| to |key2| using |group|.
bssl::UniquePtr<EC_KEY> key2(EC_KEY_new());
ASSERT_TRUE(key2);
bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
ASSERT_TRUE(point);
bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
ASSERT_TRUE(x);
ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get()));
ASSERT_TRUE(
EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())));
ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(),
y.get(), nullptr));
ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(),
x.get(), y.get(), nullptr));
ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get()));
if (!key2 || !point || !x || !y ||
!EC_KEY_set_group(key2.get(), group.get()) ||
!EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())) ||
!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
EC_KEY_get0_public_key(key.get()),
x.get(), y.get(), nullptr) ||
!EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), x.get(),
y.get(), nullptr) ||
!EC_KEY_set_public_key(key2.get(), point.get())) {
fprintf(stderr, "Could not copy key.\n");
return false;
}
// The key must be valid according to the new group too.
EXPECT_TRUE(EC_KEY_check_key(key2.get()));
if (!EC_KEY_check_key(key2.get())) {
fprintf(stderr, "Copied key is not valid.\n");
return false;
}
return true;
}
class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {};
TEST_P(ECCurveTest, SetAffine) {
// Generate an EC_KEY.
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
ASSERT_TRUE(key);
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
static bool TestAddingEqualPoints(int nid) {
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
if (!key) {
return false;
}
const EC_GROUP *const group = EC_KEY_get0_group(key.get());
EXPECT_TRUE(
EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()), nullptr));
// Get the public key's coordinates.
bssl::UniquePtr<BIGNUM> x(BN_new());
ASSERT_TRUE(x);
bssl::UniquePtr<BIGNUM> y(BN_new());
ASSERT_TRUE(y);
EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
group, EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
// Points on the curve should be accepted.
auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group));
ASSERT_TRUE(point);
EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(),
y.get(), nullptr));
// Subtract one from |y| to make the point no longer on the curve.
EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
// Points not on the curve should be rejected.
bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group));
ASSERT_TRUE(invalid_point);
EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(),
x.get(), y.get(), nullptr));
}
TEST_P(ECCurveTest, AddingEqualPoints) {
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
ASSERT_TRUE(key);
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
const EC_GROUP *const group = EC_KEY_get0_group(key.get());
if (!EC_KEY_generate_key(key.get())) {
fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid);
ERR_print_errors_fp(stderr);
return false;
}
bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group));
ASSERT_TRUE(p1);
ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group));
ASSERT_TRUE(p2);
ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group));
ASSERT_TRUE(double_p1);
bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
ASSERT_TRUE(ctx);
ASSERT_TRUE(EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()));
bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group));
ASSERT_TRUE(p1_plus_p2);
ASSERT_TRUE(
EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
if (!p1 || !p2 || !double_p1 || !p1_plus_p2) {
return false;
}
EXPECT_EQ(0,
EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()))
<< "A+A != 2A";
if (!EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())) ||
!EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))) {
fprintf(stderr, "EC_POINT_COPY failed with nid %d\n", nid);
ERR_print_errors_fp(stderr);
return false;
}
bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
if (!ctx) {
return false;
}
if (!EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()) ||
!EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get())) {
fprintf(stderr, "Point operation failed with nid %d\n", nid);
ERR_print_errors_fp(stderr);
return false;
}
if (EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()) != 0) {
fprintf(stderr, "A+A != 2A for nid %d", nid);
return false;
}
return true;
}
TEST_P(ECCurveTest, MulZero) {
bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
ASSERT_TRUE(group);
static bool TestMulZero(int nid) {
bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(nid));
if (!group) {
return false;
}
bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
ASSERT_TRUE(point);
bssl::UniquePtr<BIGNUM> zero(BN_new());
ASSERT_TRUE(zero);
BN_zero(zero.get());
ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr,
nullptr, nullptr));
if (!point || !zero) {
return false;
}
EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
<< "g * 0 did not return point at infinity.";
BN_zero(zero.get());
if (!EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr, nullptr,
nullptr)) {
return false;
}
if (!EC_POINT_is_at_infinity(group.get(), point.get())) {
fprintf(stderr, "g * 0 did not return point at infinity.\n");
return false;
}
// Test that zero times an arbitrary point is also infinity. The generator is
// used as the arbitrary point.
bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
ASSERT_TRUE(generator);
ASSERT_TRUE(EC_POINT_mul(group.get(), generator.get(), BN_value_one(),
nullptr, nullptr, nullptr));
ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, generator.get(),
zero.get(), nullptr));
bssl::UniquePtr<BIGNUM> one(BN_new());
if (!generator ||
!one ||
!BN_one(one.get()) ||
!EC_POINT_mul(group.get(), generator.get(), one.get(), nullptr, nullptr,
nullptr) ||
!EC_POINT_mul(group.get(), point.get(), nullptr, generator.get(),
zero.get(), nullptr)) {
return false;
}
EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
<< "p * 0 did not return point at infinity.";
if (!EC_POINT_is_at_infinity(group.get(), point.get())) {
fprintf(stderr, "p * 0 did not return point at infinity.\n");
return false;
}
return true;
}
static std::vector<EC_builtin_curve> AllCurves() {
static bool ForEachCurve(bool (*test_func)(int nid)) {
const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
std::vector<EC_builtin_curve> curves(num_curves);
EC_get_builtin_curves(curves.data(), num_curves);
return curves;
for (const auto& curve : curves) {
if (!test_func(curve.nid)) {
fprintf(stderr, "Test failed for %s\n", curve.comment);
return false;
}
}
return true;
}
static std::string CurveToString(
const testing::TestParamInfo<EC_builtin_curve> &params) {
// The comment field contains characters GTest rejects, so use the OBJ name.
return OBJ_nid2sn(params.param.nid);
}
int main() {
CRYPTO_library_init();
INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
CurveToString);
if (!Testd2i_ECPrivateKey() ||
!TestZeroPadding() ||
!TestSpecifiedCurve() ||
!ForEachCurve(TestSetAffine) ||
!ForEachCurve(TestAddingEqualPoints) ||
!ForEachCurve(TestMulZero) ||
!TestArbitraryCurve()) {
fprintf(stderr, "failed\n");
return 1;
}
printf("PASS\n");
return 0;
}
+9 -11
View File
@@ -66,10 +66,9 @@
int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig,
unsigned int *sig_len, const EC_KEY *eckey) {
unsigned int *sig_len, EC_KEY *eckey) {
if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len,
(EC_KEY*) eckey /* cast away const */);
return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len, eckey);
}
return ECDSA_sign_ex(type, digest, digest_len, sig, sig_len, NULL, NULL,
@@ -77,7 +76,7 @@ int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig,
}
int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
const uint8_t *sig, size_t sig_len, const EC_KEY *eckey) {
const uint8_t *sig, size_t sig_len, EC_KEY *eckey) {
ECDSA_SIG *s;
int ret = 0;
uint8_t *der = NULL;
@@ -134,12 +133,12 @@ static int digest_to_bn(BIGNUM *out, const uint8_t *digest, size_t digest_len,
}
ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
const EC_KEY *key) {
EC_KEY *key) {
return ECDSA_do_sign_ex(digest, digest_len, NULL, NULL, key);
}
int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
const ECDSA_SIG *sig, const EC_KEY *eckey) {
const ECDSA_SIG *sig, EC_KEY *eckey) {
int ret = 0;
BN_CTX *ctx;
BIGNUM *u1, *u2, *m, *X;
@@ -225,7 +224,7 @@ err:
return ret;
}
static int ecdsa_sign_setup(const EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp, const uint8_t *digest,
size_t digest_len) {
BN_CTX *ctx = NULL;
@@ -339,14 +338,13 @@ err:
return ret;
}
int ECDSA_sign_setup(const EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
BIGNUM **rp) {
int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp) {
return ecdsa_sign_setup(eckey, ctx, kinv, rp, NULL, 0);
}
ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len,
const BIGNUM *in_kinv, const BIGNUM *in_r,
const EC_KEY *eckey) {
EC_KEY *eckey) {
int ok = 0;
BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL;
const BIGNUM *ckinv;
@@ -443,7 +441,7 @@ err:
int ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len,
uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv,
const BIGNUM *r, const EC_KEY *eckey) {
const BIGNUM *r, EC_KEY *eckey) {
int ret = 0;
ECDSA_SIG *s = NULL;
+11
View File
@@ -37,3 +37,14 @@ add_library(
err.c
err_data.c
)
add_executable(
err_test
err_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(err_test crypto)
add_dependencies(all_tests err_test)
-1
View File
@@ -3,5 +3,4 @@ CONF,101,MISSING_CLOSE_SQUARE_BRACKET
CONF,102,MISSING_EQUAL_SIGN
CONF,103,NO_CLOSE_BRACE
CONF,104,UNABLE_TO_CREATE_NEW_SECTION
CONF,106,VARIABLE_EXPANSION_TOO_LONG
CONF,105,VARIABLE_HAS_NO_VALUE
-2
View File
@@ -1,3 +1 @@
DIGEST,101,DECODE_ERROR
DIGEST,100,INPUT_NOT_INITIALIZED
DIGEST,102,UNKNOWN_HASH
+76 -35
View File
@@ -15,34 +15,40 @@
#include <stdio.h>
#include <string.h>
#include <gtest/gtest.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
TEST(ErrTest, Overflow) {
static bool TestOverflow() {
for (unsigned i = 0; i < ERR_NUM_ERRORS*2; i++) {
ERR_put_error(1, 0 /* unused */, i+1, "test", 1);
}
for (unsigned i = 0; i < ERR_NUM_ERRORS - 1; i++) {
SCOPED_TRACE(i);
uint32_t err = ERR_get_error();
/* Errors are returned in order they were pushed, with the least recent ones
* removed, up to |ERR_NUM_ERRORS - 1| errors. So the errors returned are
* |ERR_NUM_ERRORS + 2| through |ERR_NUM_ERRORS * 2|, inclusive. */
EXPECT_NE(0u, err);
EXPECT_EQ(static_cast<int>(i + ERR_NUM_ERRORS + 2), ERR_GET_REASON(err));
if (err == 0 || ((unsigned)ERR_GET_REASON(err)) != i + ERR_NUM_ERRORS + 2) {
fprintf(stderr, "ERR_get_error failed at %u\n", i);
return false;
}
}
EXPECT_EQ(0u, ERR_get_error());
if (ERR_get_error() != 0) {
fprintf(stderr, "ERR_get_error more than the expected number of values.\n");
return false;
}
return true;
}
TEST(ErrTest, PutError) {
ASSERT_EQ(0u, ERR_get_error())
<< "ERR_get_error returned value before an error was added.";
static bool TestPutError() {
if (ERR_get_error() != 0) {
fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
return false;
}
ERR_put_error(1, 0 /* unused */, 2, "test", 4);
ERR_add_error_data(1, "testing");
@@ -54,31 +60,45 @@ TEST(ErrTest, PutError) {
&peeked_flags);
uint32_t packed_error = ERR_get_error_line_data(&file, &line, &data, &flags);
EXPECT_EQ(peeked_packed_error, packed_error);
EXPECT_EQ(peeked_file, file);
EXPECT_EQ(peeked_data, data);
EXPECT_EQ(peeked_flags, flags);
if (peeked_packed_error != packed_error ||
peeked_file != file ||
peeked_data != data ||
peeked_flags != flags) {
fprintf(stderr, "Bad peeked error data returned.\n");
return false;
}
EXPECT_STREQ("test", file);
EXPECT_EQ(4, line);
EXPECT_TRUE(flags & ERR_FLAG_STRING);
EXPECT_EQ(1, ERR_GET_LIB(packed_error));
EXPECT_EQ(2, ERR_GET_REASON(packed_error));
EXPECT_STREQ("testing", data);
if (strcmp(file, "test") != 0 ||
line != 4 ||
(flags & ERR_FLAG_STRING) == 0 ||
ERR_GET_LIB(packed_error) != 1 ||
ERR_GET_REASON(packed_error) != 2 ||
strcmp(data, "testing") != 0) {
fprintf(stderr, "Bad error data returned.\n");
return false;
}
return true;
}
TEST(ErrTest, ClearError) {
ASSERT_EQ(0u, ERR_get_error())
<< "ERR_get_error returned value before an error was added.";
static bool TestClearError() {
if (ERR_get_error() != 0) {
fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
return false;
}
ERR_put_error(1, 0 /* unused */, 2, "test", 4);
ERR_clear_error();
// The error queue should be cleared.
EXPECT_EQ(0u, ERR_get_error());
if (ERR_get_error() != 0) {
fprintf(stderr, "Error remained after clearing.\n");
return false;
}
return true;
}
TEST(ErrTest, Print) {
static bool TestPrint() {
ERR_put_error(1, 0 /* unused */, 2, "test", 4);
ERR_add_error_data(1, "testing");
uint32_t packed_error = ERR_get_error();
@@ -87,14 +107,14 @@ TEST(ErrTest, Print) {
for (size_t i = 0; i <= sizeof(buf); i++) {
ERR_error_string_n(packed_error, buf, i);
}
return true;
}
TEST(ErrTest, Release) {
static bool TestRelease() {
ERR_put_error(1, 0 /* unused */, 2, "test", 4);
ERR_remove_thread_state(NULL);
// The error queue should be cleared.
EXPECT_EQ(0u, ERR_get_error());
return true;
}
static bool HasSuffix(const char *str, const char *suffix) {
@@ -106,7 +126,7 @@ static bool HasSuffix(const char *str, const char *suffix) {
return strcmp(str + str_len - suffix_len, suffix) == 0;
}
TEST(ErrTest, PutMacro) {
static bool TestPutMacro() {
int expected_line = __LINE__ + 1;
OPENSSL_PUT_ERROR(USER, ERR_R_INTERNAL_ERROR);
@@ -114,8 +134,29 @@ TEST(ErrTest, PutMacro) {
const char *file;
uint32_t error = ERR_get_error_line(&file, &line);
EXPECT_PRED2(HasSuffix, file, "err_test.cc");
EXPECT_EQ(expected_line, line);
EXPECT_EQ(ERR_LIB_USER, ERR_GET_LIB(error));
EXPECT_EQ(ERR_R_INTERNAL_ERROR, ERR_GET_REASON(error));
if (!HasSuffix(file, "err_test.cc") ||
line != expected_line ||
ERR_GET_LIB(error) != ERR_LIB_USER ||
ERR_GET_REASON(error) != ERR_R_INTERNAL_ERROR) {
fprintf(stderr, "Bad error data returned.\n");
return false;
}
return true;
}
int main() {
CRYPTO_library_init();
if (!TestOverflow() ||
!TestPutError() ||
!TestClearError() ||
!TestPrint() ||
!TestRelease() ||
!TestPutMacro()) {
return 1;
}
printf("PASS\n");
return 0;
}
-6
View File
@@ -1,4 +1,3 @@
PKCS8,129,BAD_ITERATION_COUNT
PKCS8,100,BAD_PKCS12_DATA
PKCS8,101,BAD_PKCS12_VERSION
PKCS8,102,CIPHER_HAS_NO_OBJECT_IDENTIFIER
@@ -23,9 +22,4 @@ PKCS8,120,UNKNOWN_CIPHER
PKCS8,121,UNKNOWN_CIPHER_ALGORITHM
PKCS8,122,UNKNOWN_DIGEST
PKCS8,123,UNKNOWN_HASH
PKCS8,127,UNSUPPORTED_CIPHER
PKCS8,125,UNSUPPORTED_KEYLENGTH
PKCS8,128,UNSUPPORTED_KEY_DERIVATION_FUNCTION
PKCS8,130,UNSUPPORTED_PRF
PKCS8,124,UNSUPPORTED_PRIVATE_KEY_ALGORITHM
PKCS8,126,UNSUPPORTED_SALT_TYPE
+1 -7
View File
@@ -1,4 +1,3 @@
SSL,277,ALPN_MISMATCH_ON_EARLY_DATA
SSL,100,APP_DATA_IN_HANDSHAKE
SSL,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT
SSL,102,BAD_ALERT
@@ -23,17 +22,14 @@ SSL,261,BLOCK_CIPHER_PAD_IS_WRONG
SSL,120,BN_LIB
SSL,255,BUFFERED_MESSAGES_ON_CIPHER_CHANGE
SSL,121,BUFFER_TOO_SMALL
SSL,275,CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD
SSL,272,CANNOT_PARSE_LEAF_CERT
SSL,122,CA_DN_LENGTH_MISMATCH
SSL,123,CA_DN_TOO_LONG
SSL,124,CCS_RECEIVED_EARLY
SSL,274,CERTIFICATE_AND_PRIVATE_KEY_MISMATCH
SSL,125,CERTIFICATE_VERIFY_FAILED
SSL,126,CERT_CB_ERROR
SSL,127,CERT_LENGTH_MISMATCH
SSL,128,CHANNEL_ID_NOT_P256
SSL,279,CHANNEL_ID_ON_EARLY_DATA
SSL,129,CHANNEL_ID_SIGNATURE_INVALID
SSL,130,CIPHER_OR_HASH_UNAVAILABLE
SSL,131,CLIENTHELLO_PARSE_FAILED
@@ -75,6 +71,7 @@ SSL,269,INVALID_SCT_LIST
SSL,160,INVALID_SSL_SESSION
SSL,161,INVALID_TICKET_KEYS_LENGTH
SSL,162,LENGTH_MISMATCH
SSL,163,LIBRARY_HAS_NO_CIPHERS
SSL,164,MISSING_EXTENSION
SSL,258,MISSING_KEY_SHARE
SSL,165,MISSING_RSA_CERTIFICATE
@@ -128,7 +125,6 @@ SSL,204,RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION
SSL,205,RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION
SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING
SSL,207,SERVERHELLO_TLSEXT
SSL,273,SERVER_CERT_CHANGED
SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED
SSL,209,SESSION_MAY_NOT_BE_CREATED
SSL,250,SHUTDOWN_WHILE_IN_INIT
@@ -151,7 +147,6 @@ SSL,1043,SSLV3_ALERT_UNSUPPORTED_CERTIFICATE
SSL,214,SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION
SSL,215,SSL_HANDSHAKE_FAILURE
SSL,216,SSL_SESSION_ID_CONTEXT_TOO_LONG
SSL,276,TICKET_ENCRYPTION_FAILED
SSL,1049,TLSV1_ALERT_ACCESS_DENIED
SSL,1050,TLSV1_ALERT_DECODE_ERROR
SSL,1021,TLSV1_ALERT_DECRYPTION_FAILED
@@ -206,6 +201,5 @@ SSL,244,WRONG_MESSAGE_TYPE
SSL,245,WRONG_SIGNATURE_TYPE
SSL,246,WRONG_SSL_VERSION
SSL,247,WRONG_VERSION_NUMBER
SSL,278,WRONG_VERSION_ON_EARLY_DATA
SSL,248,X509_LIB
SSL,249,X509_VERIFICATION_SETUP_PROBLEMS
+10 -1
View File
@@ -20,6 +20,14 @@ add_library(
)
add_executable(
evp_extra_test
evp_extra_test.cc
$<TARGET_OBJECTS:test_support>
)
add_executable(
evp_test
@@ -36,6 +44,7 @@ add_executable(
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(evp_extra_test crypto)
target_link_libraries(evp_test crypto)
target_link_libraries(pbkdf_test crypto)
add_dependencies(all_tests evp_test pbkdf_test)
add_dependencies(all_tests evp_extra_test evp_test pbkdf_test)
+7
View File
@@ -120,6 +120,13 @@ int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
return 0;
}
int EVP_PKEY_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
if (pkey->ameth && pkey->ameth->pkey_supports_digest) {
return pkey->ameth->pkey_supports_digest(pkey, md);
}
return 1;
}
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
if (a->type != b->type) {
return -1;
+28 -21
View File
@@ -148,40 +148,48 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) {
OPENSSL_free(ctx);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx) {
if (!ctx->pmeth || !ctx->pmeth->copy) {
EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) {
EVP_PKEY_CTX *rctx;
if (!pctx->pmeth || !pctx->pmeth->copy) {
return NULL;
}
EVP_PKEY_CTX *ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
if (!ret) {
rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
if (!rctx) {
return NULL;
}
OPENSSL_memset(ret, 0, sizeof(EVP_PKEY_CTX));
OPENSSL_memset(rctx, 0, sizeof(EVP_PKEY_CTX));
ret->pmeth = ctx->pmeth;
ret->engine = ctx->engine;
ret->operation = ctx->operation;
rctx->pmeth = pctx->pmeth;
rctx->engine = pctx->engine;
rctx->operation = pctx->operation;
if (ctx->pkey != NULL) {
EVP_PKEY_up_ref(ctx->pkey);
ret->pkey = ctx->pkey;
if (pctx->pkey) {
EVP_PKEY_up_ref(pctx->pkey);
rctx->pkey = pctx->pkey;
if (rctx->pkey == NULL) {
goto err;
}
}
if (ctx->peerkey != NULL) {
EVP_PKEY_up_ref(ctx->peerkey);
ret->peerkey = ctx->peerkey;
if (pctx->peerkey) {
EVP_PKEY_up_ref(pctx->peerkey);
rctx->peerkey = pctx->peerkey;
if (rctx->peerkey == NULL) {
goto err;
}
}
if (ctx->pmeth->copy(ret, ctx) <= 0) {
ret->pmeth = NULL;
EVP_PKEY_CTX_free(ret);
OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
return NULL;
if (pctx->pmeth->copy(rctx, pctx) > 0) {
return rctx;
}
return ret;
err:
EVP_PKEY_CTX_free(rctx);
OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
return NULL;
}
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; }
@@ -193,7 +201,6 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd,
return 0;
}
if (keytype != -1 && ctx->pmeth->pkey_id != keytype) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
+288 -109
View File
@@ -20,8 +20,6 @@
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
@@ -30,7 +28,6 @@
#include <openssl/rsa.h>
#include "../internal.h"
#include "../test/test_util.h"
// kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
@@ -373,170 +370,352 @@ static bssl::UniquePtr<EVP_PKEY> LoadExampleRSAKey() {
return pkey;
}
TEST(EVPExtraTest, DigestSignInit) {
static bool TestEVP_DigestSignInit(void) {
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
ASSERT_TRUE(pkey);
bssl::ScopedEVP_MD_CTX md_ctx;
ASSERT_TRUE(
EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
if (!pkey ||
!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
!EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg))) {
return false;
}
// Determine the size of the signature.
size_t sig_len = 0;
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len));
if (!EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len)) {
return false;
}
// Sanity check for testing.
EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(pkey.get())), sig_len);
if (sig_len != (size_t)EVP_PKEY_size(pkey.get())) {
fprintf(stderr, "sig_len mismatch\n");
return false;
}
std::vector<uint8_t> sig;
sig.resize(sig_len);
ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len));
if (!EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len)) {
return false;
}
sig.resize(sig_len);
// Ensure that the signature round-trips.
md_ctx.Reset();
ASSERT_TRUE(
EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len));
if (!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
pkey.get()) ||
!EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
!EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len)) {
return false;
}
return true;
}
TEST(EVPExtraTest, DigestVerifyInit) {
static bool TestEVP_DigestVerifyInit(void) {
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
bssl::ScopedEVP_MD_CTX md_ctx;
ASSERT_TRUE(pkey);
ASSERT_TRUE(
EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
ASSERT_TRUE(
EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature)));
if (!pkey ||
!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
pkey.get()) ||
!EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
!EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature))) {
return false;
}
return true;
}
TEST(EVPExtraTest, VerifyRecover) {
static bool TestVerifyRecover() {
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
ASSERT_TRUE(pkey);
if (!pkey) {
return false;
}
bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey.get()));
ASSERT_TRUE(rsa);
if (!rsa) {
return false;
}
const uint8_t kDummyHash[32] = {0};
uint8_t sig[2048/8];
unsigned sig_len = sizeof(sig);
ASSERT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig,
&sig_len, rsa.get()));
if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig, &sig_len,
rsa.get())) {
fprintf(stderr, "RSA_sign failed.\n");
ERR_print_errors_fp(stderr);
return false;
}
size_t out_len;
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
ASSERT_TRUE(EVP_PKEY_verify_recover_init(ctx.get()));
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING));
ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()));
ASSERT_TRUE(
EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len));
if (!EVP_PKEY_verify_recover_init(ctx.get()) ||
!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) ||
!EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()) ||
!EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len)) {
fprintf(stderr, "verify_recover failed will nullptr buffer.\n");
ERR_print_errors_fp(stderr);
return false;
}
std::vector<uint8_t> recovered;
recovered.resize(out_len);
ASSERT_TRUE(EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len,
sig, sig_len));
EXPECT_EQ(Bytes(kDummyHash), Bytes(recovered.data(), out_len));
if (!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig,
sig_len)) {
fprintf(stderr, "verify_recover failed.\n");
ERR_print_errors_fp(stderr);
return false;
}
if (out_len != sizeof(kDummyHash)) {
fprintf(stderr, "verify_recover length is %u, expected %u.\n",
static_cast<unsigned>(out_len),
static_cast<unsigned>(sizeof(kDummyHash)));
return false;
}
if (OPENSSL_memcmp(recovered.data(), kDummyHash, sizeof(kDummyHash)) != 0) {
fprintf(stderr, "verify_recover got wrong value.\n");
ERR_print_errors_fp(stderr);
return false;
}
out_len = recovered.size();
ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr));
ASSERT_TRUE(EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len,
sig, sig_len));
if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr) ||
!EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len, sig,
sig_len)) {
fprintf(stderr, "verify_recover failed with NULL MD.\n");
ERR_print_errors_fp(stderr);
return false;
}
// The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51
// bytes.
EXPECT_EQ(51u, out_len);
/* The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51
* bytes. */
static const size_t kExpectedASN1Size = 51;
if (out_len != kExpectedASN1Size) {
fprintf(stderr, "verify_recover length without MD is %u, expected %u.\n",
static_cast<unsigned>(out_len),
static_cast<unsigned>(kExpectedASN1Size));
return false;
}
return true;
}
static void TestValidPrivateKey(const uint8_t *input, size_t input_len,
static bool TestValidPrivateKey(const uint8_t *input, size_t input_len,
int expected_id) {
const uint8_t *p = input;
bssl::UniquePtr<EVP_PKEY> pkey(d2i_AutoPrivateKey(NULL, &p, input_len));
ASSERT_TRUE(pkey);
EXPECT_EQ(input + input_len, p);
EXPECT_EQ(expected_id, EVP_PKEY_id(pkey.get()));
if (!pkey || p != input + input_len) {
fprintf(stderr, "d2i_AutoPrivateKey failed\n");
return false;
}
if (EVP_PKEY_id(pkey.get()) != expected_id) {
fprintf(stderr, "Did not decode expected type\n");
return false;
}
return true;
}
TEST(EVPExtraTest, d2i_AutoPrivateKey) {
TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
EVP_PKEY_RSA);
TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
EVP_PKEY_RSA);
TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER), EVP_PKEY_EC);
TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8),
EVP_PKEY_EC);
TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8,
sizeof(kExampleECKeySpecifiedCurvePKCS8), EVP_PKEY_EC);
TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
EVP_PKEY_DSA);
static bool Testd2i_AutoPrivateKey() {
if (!TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
EVP_PKEY_RSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
EVP_PKEY_RSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER),
EVP_PKEY_EC)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8),
EVP_PKEY_EC)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyPKCS8) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8,
sizeof(kExampleECKeySpecifiedCurvePKCS8),
EVP_PKEY_EC)) {
fprintf(stderr,
"d2i_AutoPrivateKey(kExampleECKeySpecifiedCurvePKCS8) failed\n");
return false;
}
if (!TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
EVP_PKEY_DSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleDSAKeyDER) failed\n");
return false;
}
const uint8_t *p = kInvalidPrivateKey;
bssl::UniquePtr<EVP_PKEY> pkey(
d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey)));
EXPECT_FALSE(pkey) << "Parsed invalid private key";
bssl::UniquePtr<EVP_PKEY> pkey(d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey)));
if (pkey) {
fprintf(stderr, "Parsed invalid private key\n");
return false;
}
ERR_clear_error();
return true;
}
// Tests loading a bad key in PKCS8 format.
TEST(EVPExtraTest, BadECKey) {
// TestEVP_PKCS82PKEY tests loading a bad key in PKCS8 format.
static bool TestEVP_PKCS82PKEY(void) {
const uint8_t *derp = kExampleBadECKeyDER;
bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> p8inf(
d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER)));
ASSERT_TRUE(p8inf);
EXPECT_EQ(kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER), derp);
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKCS82PKEY(p8inf.get()));
ASSERT_FALSE(pkey) << "Imported invalid EC key";
ERR_clear_error();
}
// Tests |EVP_marshal_public_key| on an empty key.
TEST(EVPExtraTest, MarshalEmptyPublicKey) {
bssl::UniquePtr<EVP_PKEY> empty(EVP_PKEY_new());
ASSERT_TRUE(empty);
bssl::ScopedCBB cbb;
EXPECT_FALSE(EVP_marshal_public_key(cbb.get(), empty.get()))
<< "Marshalled empty public key.";
EXPECT_EQ(EVP_R_UNSUPPORTED_ALGORITHM, ERR_GET_REASON(ERR_peek_last_error()));
}
static bssl::UniquePtr<EVP_PKEY> ParsePrivateKey(int type, const uint8_t *in,
size_t len) {
const uint8_t *ptr = in;
bssl::UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(type, nullptr, &ptr, len));
if (!pkey) {
return nullptr;
if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) {
fprintf(stderr, "Failed to parse key\n");
return false;
}
EXPECT_EQ(in + len, ptr);
return pkey;
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKCS82PKEY(p8inf.get()));
if (pkey) {
fprintf(stderr, "Imported invalid EC key\n");
return false;
}
ERR_clear_error();
return true;
}
TEST(EVPExtraTest, d2i_PrivateKey) {
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_RSA, kExampleRSAKeyDER,
sizeof(kExampleRSAKeyDER)));
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_DSA, kExampleDSAKeyDER,
sizeof(kExampleDSAKeyDER)));
EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_RSA, kExampleRSAKeyPKCS8,
sizeof(kExampleRSAKeyPKCS8)));
EXPECT_TRUE(
ParsePrivateKey(EVP_PKEY_EC, kExampleECKeyDER, sizeof(kExampleECKeyDER)));
// TestEVPMarshalEmptyPublicKey tests |EVP_marshal_public_key| on an empty key.
static bool TestEVPMarshalEmptyPublicKey(void) {
bssl::UniquePtr<EVP_PKEY> empty(EVP_PKEY_new());
if (!empty) {
return false;
}
bssl::ScopedCBB cbb;
if (EVP_marshal_public_key(cbb.get(), empty.get())) {
fprintf(stderr, "Marshalled empty public key.\n");
return false;
}
if (ERR_GET_REASON(ERR_peek_last_error()) != EVP_R_UNSUPPORTED_ALGORITHM) {
fprintf(stderr, "Marshalling an empty public key gave wrong error.\n");
return false;
}
ERR_clear_error();
return true;
}
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, kExampleBadECKeyDER,
sizeof(kExampleBadECKeyDER)));
// Testd2i_PrivateKey tests |d2i_PrivateKey|.
static bool Testd2i_PrivateKey(void) {
const uint8_t *derp = kExampleRSAKeyDER;
bssl::UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp,
sizeof(kExampleRSAKeyDER)));
if (!pkey || derp != kExampleRSAKeyDER + sizeof(kExampleRSAKeyDER)) {
fprintf(stderr, "Failed to import raw RSA key.\n");
return false;
}
derp = kExampleDSAKeyDER;
pkey.reset(d2i_PrivateKey(EVP_PKEY_DSA, nullptr, &derp,
sizeof(kExampleDSAKeyDER)));
if (!pkey || derp != kExampleDSAKeyDER + sizeof(kExampleDSAKeyDER)) {
fprintf(stderr, "Failed to import raw DSA key.\n");
return false;
}
derp = kExampleRSAKeyPKCS8;
pkey.reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp,
sizeof(kExampleRSAKeyPKCS8)));
if (!pkey || derp != kExampleRSAKeyPKCS8 + sizeof(kExampleRSAKeyPKCS8)) {
fprintf(stderr, "Failed to import PKCS#8 RSA key.\n");
return false;
}
derp = kExampleECKeyDER;
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
sizeof(kExampleECKeyDER)));
if (!pkey || derp != kExampleECKeyDER + sizeof(kExampleECKeyDER)) {
fprintf(stderr, "Failed to import raw EC key.\n");
return false;
}
derp = kExampleBadECKeyDER;
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
sizeof(kExampleBadECKeyDER)));
if (pkey) {
fprintf(stderr, "Imported invalid EC key.\n");
return false;
}
ERR_clear_error();
// Copy the input into a |malloc|'d vector to flag memory errors.
std::vector<uint8_t> copy(
kExampleBadECKeyDER2,
kExampleBadECKeyDER2 + sizeof(kExampleBadECKeyDER2));
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, copy.data(), copy.size()));
std::vector<uint8_t> copy(kExampleBadECKeyDER2, kExampleBadECKeyDER2 +
sizeof(kExampleBadECKeyDER2));
derp = copy.data();
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, copy.size()));
if (pkey) {
fprintf(stderr, "Imported invalid EC key #2.\n");
return false;
}
ERR_clear_error();
// Test that an RSA key may not be imported as an EC key.
EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, kExampleRSAKeyPKCS8,
sizeof(kExampleRSAKeyPKCS8)));
derp = kExampleRSAKeyPKCS8;
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
sizeof(kExampleRSAKeyPKCS8)));
if (pkey) {
fprintf(stderr, "Imported RSA key as EC key.\n");
return false;
}
ERR_clear_error();
return true;
}
int main() {
CRYPTO_library_init();
if (!TestEVP_DigestSignInit()) {
fprintf(stderr, "EVP_DigestSignInit failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!TestEVP_DigestVerifyInit()) {
fprintf(stderr, "EVP_DigestVerifyInit failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!TestVerifyRecover()) {
fprintf(stderr, "EVP_PKEY_verify_recover failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!Testd2i_AutoPrivateKey()) {
fprintf(stderr, "Testd2i_AutoPrivateKey failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!TestEVP_PKCS82PKEY()) {
fprintf(stderr, "TestEVP_PKCS82PKEY failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!TestEVPMarshalEmptyPublicKey()) {
fprintf(stderr, "TestEVPMarshalEmptyPublicKey failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
if (!Testd2i_PrivateKey()) {
fprintf(stderr, "Testd2i_PrivateKey failed\n");
ERR_print_errors_fp(stderr);
return 1;
}
printf("PASS\n");
return 0;
}
+6 -8
View File
@@ -224,8 +224,9 @@ static bool TestEVP(FileTest *t, void *arg) {
}
EVP_PKEY *key = (*key_map)[key_name].get();
std::vector<uint8_t> input;
if (!t->GetBytes(&input, "Input")) {
std::vector<uint8_t> input, output;
if (!t->GetBytes(&input, "Input") ||
!t->GetBytes(&output, "Output")) {
return false;
}
@@ -262,9 +263,7 @@ static bool TestEVP(FileTest *t, void *arg) {
}
if (t->GetType() == "Verify") {
std::vector<uint8_t> output;
if (!t->GetBytes(&output, "Output") ||
!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
if (!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
input.size())) {
// ECDSA sometimes doesn't push an error code. Push one on the error queue
// so it's distinguishable from other errors.
@@ -275,7 +274,7 @@ static bool TestEVP(FileTest *t, void *arg) {
}
size_t len;
std::vector<uint8_t> actual, output;
std::vector<uint8_t> actual;
if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) {
return false;
}
@@ -284,8 +283,7 @@ static bool TestEVP(FileTest *t, void *arg) {
return false;
}
actual.resize(len);
if (!t->GetBytes(&output, "Output") ||
!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
if (!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
return false;
}
return true;
File diff suppressed because it is too large Load Diff
+6
View File
@@ -100,6 +100,12 @@ struct evp_pkey_asn1_method_st {
* custom implementations which do not expose key material and parameters.*/
int (*pkey_opaque)(const EVP_PKEY *pk);
/* pkey_supports_digest returns one if |pkey| supports digests of
* type |md|. This is intended for use with EVP_PKEYs backing custom
* implementations which can't sign all digests. If null, it is
* assumed that all digests are supported. */
int (*pkey_supports_digest)(const EVP_PKEY *pkey, const EVP_MD *md);
int (*pkey_size)(const EVP_PKEY *pk);
int (*pkey_bits)(const EVP_PKEY *pk);
+2 -2
View File
@@ -151,8 +151,7 @@ static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* Calculate the public key. */
ctx = BN_CTX_new();
if (ctx == NULL ||
!BN_mod_exp_mont(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx,
NULL)) {
!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
goto err;
}
@@ -256,6 +255,7 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
dsa_priv_encode,
NULL /* pkey_opaque */,
NULL /* pkey_supports_digest */,
int_dsa_size,
dsa_bits,

Some files were not shown because too many files have changed in this diff Show More