Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be873e9f48 | |||
| b8684f0276 |
+1
-1
@@ -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
@@ -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
@@ -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
|
||||
```
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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"); }
|
||||
|
||||
+135
-1151
File diff suppressed because it is too large
Load Diff
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
___
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
|
||||
+10
-17
@@ -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;
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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(<mp, 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, <mp, 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);
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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");
|
||||
¬ ("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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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)) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
@@ -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:
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
+89
-1069
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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, ¶m, CBS_ASN1_NULL) ||
|
||||
CBS_len(¶m) != 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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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> ¶ms) {
|
||||
// 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
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
DIGEST,101,DECODE_ERROR
|
||||
DIGEST,100,INPUT_NOT_INITIALIZED
|
||||
DIGEST,102,UNKNOWN_HASH
|
||||
|
||||
+76
-35
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+4
-958
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user