Compare commits
182 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f41eb86149 | |||
| 10bec39d0e | |||
| 84edfee6a7 | |||
| ca9a538aa0 | |||
| 44e2709cd6 | |||
| a83cc803b1 | |||
| 7cc3f992ae | |||
| aac2f6a6a0 | |||
| 0ed0cf6f38 | |||
| 46a7ca0fa3 | |||
| 780d6dd0fe | |||
| 2be62c304c | |||
| 4dd053e059 | |||
| 517073cd4b | |||
| b9e0ccc650 | |||
| a7f6d3c1dc | |||
| 93efb7228b | |||
| d3bcf13165 | |||
| fcf25833bc | |||
| 4685e87746 | |||
| be2900a6a3 | |||
| cf70188d53 | |||
| 1bea173fd4 | |||
| 6e73d62dcc | |||
| f49196052c | |||
| a6d81018f8 | |||
| 263eac02f5 | |||
| 9cf708807c | |||
| 2481975857 | |||
| 4841ce49a0 | |||
| ef5885e410 | |||
| e4824e8af0 | |||
| 44f2d1a9bf | |||
| bf42f82ad9 | |||
| 07046a0946 | |||
| 16d031a493 | |||
| 71d8a085d0 | |||
| 139ed19580 | |||
| 87909c0445 | |||
| 82c9e90a58 | |||
| 4b755cb0da | |||
| 63c55a8e35 | |||
| 1f48fba861 | |||
| accb454e44 | |||
| 1eb367c03e | |||
| 9ec6bcaebe | |||
| e99e912bea | |||
| ceb6f2880f | |||
| 69b9e597ae | |||
| 7e23746dd4 | |||
| 138c2ac627 | |||
| 28014cb4f2 | |||
| 338fcafe76 | |||
| f080ecd86d | |||
| 226a872d2f | |||
| d14c6ee234 | |||
| b8a824d70d | |||
| e3594df7f1 | |||
| 1e29a6b7c5 | |||
| af7e74ba9f | |||
| 3547688ee0 | |||
| 306e520cda | |||
| 8c37cb60d4 | |||
| 0ac86b0220 | |||
| 129992360a | |||
| 8278184631 | |||
| 83abdd6e58 | |||
| e518f65d2c | |||
| 41aa325c6a | |||
| 74c68e5e37 | |||
| a6689b0488 | |||
| 687759db79 | |||
| 7baab87798 | |||
| f1eba30292 | |||
| 61f1085ee9 | |||
| d8a3e78223 | |||
| 90eeb11652 | |||
| edb03cf31f | |||
| 00505ec2e1 | |||
| af9d9419a6 | |||
| 0105ece171 | |||
| 94d701b7e8 | |||
| d0f257dc2c | |||
| 128dbc30f6 | |||
| beb47022b0 | |||
| 8c6fe45c2f | |||
| cde8abae14 | |||
| f34a009834 | |||
| 63246e8a99 | |||
| e319a2f73a | |||
| 533ef7304d | |||
| 8c88153465 | |||
| ff42cc1eac | |||
| e58a71b9b3 | |||
| 0b145c29a3 | |||
| 8c6a295c39 | |||
| 9cbd4a809e | |||
| 502a909bd6 | |||
| 95eeb191c0 | |||
| c44b1df459 | |||
| 81ea0bf538 | |||
| 8b8c006564 | |||
| 65ea8ff84c | |||
| 95f9cfcde0 | |||
| bafc58dfa4 | |||
| 0f1e64bf7f | |||
| 61f95277d4 | |||
| bb15e3ddb5 | |||
| 52d699f668 | |||
| 192f34b175 | |||
| 4e0a7e5a1d | |||
| d1681e614f | |||
| fe8eb9a603 | |||
| ae3e487d51 | |||
| 69a01608f3 | |||
| deb5284138 | |||
| 000800a306 | |||
| ec2f27dee1 | |||
| 033e5f47d1 | |||
| f31e681acf | |||
| 81257cb2e0 | |||
| 6a8d70c528 | |||
| 253b3e76dc | |||
| 1ad868176d | |||
| b398d16c1d | |||
| 675227e0d2 | |||
| 248f350ed8 | |||
| c20febe177 | |||
| ca6c82643a | |||
| ce5be4bd5c | |||
| 5e4f6e9247 | |||
| 3087f6e594 | |||
| 4cd8c43e73 | |||
| bdf5e72f50 | |||
| 2f3ba910a2 | |||
| e18d821dfc | |||
| d0297db108 | |||
| ca6554b133 | |||
| 9114fae39e | |||
| 688d8dfe48 | |||
| e1b20a0136 | |||
| 5e961c1ff1 | |||
| 0d82482e47 | |||
| f2f3cfedb7 | |||
| b145c8140b | |||
| 1f10d9c8e1 | |||
| 1df112448b | |||
| 525a0fe315 | |||
| b4188f0c9d | |||
| 6867f4854e | |||
| d8138e91d0 | |||
| 60e7992764 | |||
| b044020f84 | |||
| 9ed9dae18e | |||
| a0b74eb241 | |||
| af6e45bde5 | |||
| a952d96656 | |||
| 7530e3031d | |||
| fba236fa88 | |||
| 920e69658e | |||
| 0e7f89f96c | |||
| 08d6fe2fdb | |||
| e1cf3f1579 | |||
| 3dfbcc1f25 | |||
| b15d8132c7 | |||
| 655038e7db | |||
| 9398f168f9 | |||
| 9f5a314d35 | |||
| 1a8b549098 | |||
| 9da9035b50 | |||
| 23586e1e0e | |||
| a85093f5bb | |||
| ab2815eaff | |||
| 4aa86f1cdf | |||
| e2793a7189 | |||
| 9ecafa5c78 | |||
| f2b32a2de2 | |||
| 626fb8b75c | |||
| 74072ac84c | |||
| 3f383908e2 | |||
| 25cb99c149 | |||
| 404e6e64d0 |
+9
-2
@@ -3,8 +3,8 @@ cmake_minimum_required (VERSION 2.8.8)
|
||||
project (BoringSSL)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -ggdb -std=c89")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -ggdb -std=c++0x")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wshadow -Werror -ggdb -std=c89")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wshadow -Werror -ggdb -std=c++0x")
|
||||
elseif(MSVC)
|
||||
# Disable warnings for implicit integer narrowing.
|
||||
set(CMAKE_C_FLAGS "/wd4267")
|
||||
@@ -36,6 +36,13 @@ else()
|
||||
message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86" AND APPLE)
|
||||
# With CMake 2.8.x, ${CMAKE_SYSTEM_PROCESSOR} evalutes to i386 on OS X,
|
||||
# but clang defaults to 64-bit builds on OS X unless otherwise told.
|
||||
# Set ARCH to x86_64 so clang and CMake agree. This is fixed in CMake 3.
|
||||
set(ARCH "x86_64")
|
||||
endif()
|
||||
|
||||
add_subdirectory(crypto)
|
||||
add_subdirectory(ssl)
|
||||
add_subdirectory(ssl/test)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# This file is used by gcl to get repository specific information.
|
||||
GERRIT_HOST: True
|
||||
GERRIT_PORT: True
|
||||
CODE_REVIEW_SERVER: https://boringssl-review.googlesource.com
|
||||
@@ -105,6 +105,7 @@ add_subdirectory(hmac)
|
||||
|
||||
# Level 3
|
||||
add_subdirectory(evp)
|
||||
add_subdirectory(hkdf)
|
||||
add_subdirectory(pem)
|
||||
add_subdirectory(x509)
|
||||
add_subdirectory(x509v3)
|
||||
@@ -160,11 +161,20 @@ add_library(
|
||||
$<TARGET_OBJECTS:ecdsa>
|
||||
$<TARGET_OBJECTS:hmac>
|
||||
$<TARGET_OBJECTS:evp>
|
||||
$<TARGET_OBJECTS:hkdf>
|
||||
$<TARGET_OBJECTS:pem>
|
||||
$<TARGET_OBJECTS:x509>
|
||||
$<TARGET_OBJECTS:x509v3>
|
||||
$<TARGET_OBJECTS:pkcs8>
|
||||
)
|
||||
|
||||
add_executable(
|
||||
constant_time_test
|
||||
|
||||
constant_time_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(constant_time_test crypto)
|
||||
|
||||
perlasm(cpu-x86_64-asm.${ASM_EXT} cpu-x86_64-asm.pl)
|
||||
perlasm(cpu-x86-asm.${ASM_EXT} cpu-x86-asm.pl)
|
||||
|
||||
@@ -584,6 +584,16 @@ $code.=<<___;
|
||||
.type aesni_ecb_encrypt,\@function,5
|
||||
.align 16
|
||||
aesni_ecb_encrypt:
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
lea -0x58(%rsp),%rsp
|
||||
movaps %xmm6,(%rsp)
|
||||
movaps %xmm7,0x10(%rsp)
|
||||
movaps %xmm8,0x20(%rsp)
|
||||
movaps %xmm9,0x30(%rsp)
|
||||
.Lecb_enc_body:
|
||||
___
|
||||
$code.=<<___;
|
||||
and \$-16,$len
|
||||
jz .Lecb_ret
|
||||
|
||||
@@ -862,6 +872,16 @@ $code.=<<___;
|
||||
movups $inout5,0x50($out)
|
||||
|
||||
.Lecb_ret:
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps (%rsp),%xmm6
|
||||
movaps 0x10(%rsp),%xmm7
|
||||
movaps 0x20(%rsp),%xmm8
|
||||
movaps 0x30(%rsp),%xmm9
|
||||
lea 0x58(%rsp),%rsp
|
||||
.Lecb_enc_ret:
|
||||
___
|
||||
$code.=<<___;
|
||||
ret
|
||||
.size aesni_ecb_encrypt,.-aesni_ecb_encrypt
|
||||
___
|
||||
@@ -3225,28 +3245,9 @@ $code.=<<___;
|
||||
.extern __imp_RtlVirtualUnwind
|
||||
___
|
||||
$code.=<<___ if ($PREFIX eq "aesni");
|
||||
.type ecb_se_handler,\@abi-omnipotent
|
||||
.type ecb_ccm64_se_handler,\@abi-omnipotent
|
||||
.align 16
|
||||
ecb_se_handler:
|
||||
push %rsi
|
||||
push %rdi
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
pushfq
|
||||
sub \$64,%rsp
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
|
||||
jmp .Lcommon_seh_tail
|
||||
.size ecb_se_handler,.-ecb_se_handler
|
||||
|
||||
.type ccm64_se_handler,\@abi-omnipotent
|
||||
.align 16
|
||||
ccm64_se_handler:
|
||||
ecb_ccm64_se_handler:
|
||||
push %rsi
|
||||
push %rdi
|
||||
push %rbx
|
||||
@@ -3283,7 +3284,7 @@ ccm64_se_handler:
|
||||
lea 0x58(%rax),%rax # adjust stack pointer
|
||||
|
||||
jmp .Lcommon_seh_tail
|
||||
.size ccm64_se_handler,.-ccm64_se_handler
|
||||
.size ecb_ccm64_se_handler,.-ecb_ccm64_se_handler
|
||||
|
||||
.type ctr_xts_se_handler,\@abi-omnipotent
|
||||
.align 16
|
||||
@@ -3457,14 +3458,15 @@ ___
|
||||
$code.=<<___ if ($PREFIX eq "aesni");
|
||||
.LSEH_info_ecb:
|
||||
.byte 9,0,0,0
|
||||
.rva ecb_se_handler
|
||||
.rva ecb_ccm64_se_handler
|
||||
.rva .Lecb_enc_body,.Lecb_enc_ret # HandlerData[]
|
||||
.LSEH_info_ccm64_enc:
|
||||
.byte 9,0,0,0
|
||||
.rva ccm64_se_handler
|
||||
.rva ecb_ccm64_se_handler
|
||||
.rva .Lccm64_enc_body,.Lccm64_enc_ret # HandlerData[]
|
||||
.LSEH_info_ccm64_dec:
|
||||
.byte 9,0,0,0
|
||||
.rva ccm64_se_handler
|
||||
.rva ecb_ccm64_se_handler
|
||||
.rva .Lccm64_dec_body,.Lccm64_dec_ret # HandlerData[]
|
||||
.LSEH_info_ctr32:
|
||||
.byte 9,0,0,0
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
# Core 2 9.30 8.69 +7%
|
||||
# Nehalem(**) 7.63 6.88 +11%
|
||||
# Atom 17.1 16.4 +4%
|
||||
# Silvermont - 12.9
|
||||
#
|
||||
# (*) Comparison is not completely fair, because "this" is ECB,
|
||||
# i.e. no extra processing such as counter values calculation
|
||||
@@ -78,6 +79,7 @@
|
||||
# Core 2 9.98
|
||||
# Nehalem 7.80
|
||||
# Atom 17.9
|
||||
# Silvermont 14.0
|
||||
#
|
||||
# November 2011.
|
||||
#
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
# Core 2(**) 28.1/41.4/18.3 21.9/25.2(***)
|
||||
# Nehalem 27.9/40.4/18.1 10.2/11.9
|
||||
# Atom 70.7/92.1/60.1 61.1/75.4(***)
|
||||
# Silvermont 45.4/62.9/24.1 49.2/61.1(***)
|
||||
#
|
||||
# (*) "Hyper-threading" in the context refers rather to cache shared
|
||||
# among multiple cores, than to specifically Intel HTT. As vast
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
# Core 2(**) 29.6/41.1/14.3 21.9/25.2(***)
|
||||
# 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(***)
|
||||
#
|
||||
# (*) "Hyper-threading" in the context refers rather to cache shared
|
||||
# among multiple cores, than to specifically Intel HTT. As vast
|
||||
|
||||
@@ -111,7 +111,7 @@ int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
|
||||
}
|
||||
|
||||
/* Returns 0 if they are equal, != 0 otherwise. */
|
||||
int ASN1_TYPE_cmp(ASN1_TYPE *a, ASN1_TYPE *b)
|
||||
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
|
||||
@@ -159,7 +159,6 @@ int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
|
||||
if (sp == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
|
||||
if (s != NULL) OPENSSL_free(s);
|
||||
goto err;
|
||||
}
|
||||
s=sp;
|
||||
@@ -200,6 +199,8 @@ err:
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_ENUMERATED, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -163,7 +163,6 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
|
||||
if (sp == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
|
||||
if (s != NULL) OPENSSL_free(s);
|
||||
goto err;
|
||||
}
|
||||
s=sp;
|
||||
@@ -204,6 +203,8 @@ err:
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_INTEGER, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,6 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
|
||||
if (sp == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_STRING, ERR_R_MALLOC_FAILURE);
|
||||
if (s != NULL) OPENSSL_free(s);
|
||||
goto err;
|
||||
}
|
||||
s=sp;
|
||||
@@ -198,6 +197,8 @@ err:
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_STRING, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -599,14 +599,13 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
|
||||
{
|
||||
int flags, aclass;
|
||||
int ret;
|
||||
const unsigned char *p, *q;
|
||||
const unsigned char *p;
|
||||
if (!val)
|
||||
return 0;
|
||||
flags = tt->flags;
|
||||
aclass = flags & ASN1_TFLG_TAG_CLASS;
|
||||
|
||||
p = *in;
|
||||
q = p;
|
||||
|
||||
if (flags & ASN1_TFLG_SK_MASK)
|
||||
{
|
||||
@@ -663,7 +662,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
|
||||
while(len > 0)
|
||||
{
|
||||
ASN1_VALUE *skfield;
|
||||
q = p;
|
||||
const unsigned char *q = p;
|
||||
/* See if EOC found */
|
||||
if (asn1_check_eoc(&p, len))
|
||||
{
|
||||
|
||||
@@ -126,7 +126,13 @@ 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) bn_new(pval, it);
|
||||
if(!*pval)
|
||||
{
|
||||
if (!bn_new(pval, it))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bn = (BIGNUM *)*pval;
|
||||
if(!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
|
||||
@@ -22,6 +22,10 @@ const ERR_STRING_DATA BIO_error_string_data[] = {
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new, 0), "BIO_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new_file, 0), "BIO_new_file"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new_mem_buf, 0), "BIO_new_mem_buf"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_zero_copy_get_read_buf, 0), "BIO_zero_copy_get_read_buf"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_zero_copy_get_read_buf_done, 0), "BIO_zero_copy_get_read_buf_done"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_zero_copy_get_write_buf, 0), "BIO_zero_copy_get_write_buf"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_zero_copy_get_write_buf_done, 0), "BIO_zero_copy_get_write_buf_done"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_bio_ctrl, 0), "bio_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_bio_io, 0), "bio_io"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_bio_ip_and_port_to_socket_and_addr, 0), "bio_ip_and_port_to_socket_and_addr"},
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#define MIN(a, b) ((a < b) ? a : b)
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
@@ -119,6 +120,155 @@ static int test_socket_connect(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* bio_read_zero_copy_wrapper is a wrapper around the zero-copy APIs to make
|
||||
* testing easier. */
|
||||
static size_t bio_read_zero_copy_wrapper(BIO *bio, uint8_t *data, size_t len) {
|
||||
uint8_t *read_buf;
|
||||
size_t read_buf_offset;
|
||||
size_t available_bytes;
|
||||
size_t len_read = 0;
|
||||
|
||||
do {
|
||||
if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset,
|
||||
&available_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
available_bytes = MIN(available_bytes, len - len_read);
|
||||
memmove(data + len_read, read_buf + read_buf_offset, available_bytes);
|
||||
|
||||
BIO_zero_copy_get_read_buf_done(bio, available_bytes);
|
||||
|
||||
len_read += available_bytes;
|
||||
} while (len - len_read > 0 && available_bytes > 0);
|
||||
|
||||
return len_read;
|
||||
}
|
||||
|
||||
/* bio_write_zero_copy_wrapper is a wrapper around the zero-copy APIs to make
|
||||
* testing easier. */
|
||||
static size_t bio_write_zero_copy_wrapper(BIO *bio, const uint8_t *data,
|
||||
size_t len) {
|
||||
uint8_t *write_buf;
|
||||
size_t write_buf_offset;
|
||||
size_t available_bytes;
|
||||
size_t len_written = 0;
|
||||
|
||||
do {
|
||||
if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset,
|
||||
&available_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
available_bytes = MIN(available_bytes, len - len_written);
|
||||
memmove(write_buf + write_buf_offset, data + len_written, available_bytes);
|
||||
|
||||
BIO_zero_copy_get_write_buf_done(bio, available_bytes);
|
||||
|
||||
len_written += available_bytes;
|
||||
} while (len - len_written > 0 && available_bytes > 0);
|
||||
|
||||
return len_written;
|
||||
}
|
||||
|
||||
static int test_zero_copy_bio_pairs(void) {
|
||||
/* Test read and write, especially triggering the ring buffer wrap-around.*/
|
||||
BIO* bio1;
|
||||
BIO* bio2;
|
||||
size_t i, j;
|
||||
uint8_t bio1_application_send_buffer[1024];
|
||||
uint8_t bio2_application_recv_buffer[1024];
|
||||
size_t total_read = 0;
|
||||
size_t total_write = 0;
|
||||
uint8_t* write_buf;
|
||||
size_t write_buf_offset;
|
||||
size_t available_bytes;
|
||||
size_t bytes_left;
|
||||
|
||||
const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513};
|
||||
|
||||
/* These trigger ring buffer wrap around. */
|
||||
const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512};
|
||||
|
||||
static const size_t kBufferSize = 512;
|
||||
|
||||
srand(1);
|
||||
for (i = 0; i < sizeof(bio1_application_send_buffer); i++) {
|
||||
bio1_application_send_buffer[i] = rand() & 255;
|
||||
}
|
||||
|
||||
/* Transfer bytes from bio1_application_send_buffer to
|
||||
* bio2_application_recv_buffer in various ways. */
|
||||
for (i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
|
||||
for (j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]); j++) {
|
||||
total_write = 0;
|
||||
total_read = 0;
|
||||
|
||||
BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize);
|
||||
|
||||
total_write += bio_write_zero_copy_wrapper(
|
||||
bio1, bio1_application_send_buffer, kLengths[i]);
|
||||
|
||||
/* This tests interleaved read/write calls. Do a read between zero copy
|
||||
* write calls. */
|
||||
if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset,
|
||||
&available_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free kPartialLengths[j] bytes in the beginning of bio1 write buffer.
|
||||
* This enables ring buffer wrap around for the next write. */
|
||||
total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read,
|
||||
kPartialLengths[j]);
|
||||
|
||||
size_t interleaved_write_len = MIN(kPartialLengths[j], available_bytes);
|
||||
|
||||
/* Write the data for the interleaved write call. If the buffer becomes
|
||||
* empty after a read, the write offset is normally set to 0. Check that
|
||||
* this does not happen for interleaved read/write and that
|
||||
* |write_buf_offset| is still valid. */
|
||||
memcpy(write_buf + write_buf_offset,
|
||||
bio1_application_send_buffer + total_write, interleaved_write_len);
|
||||
if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) {
|
||||
total_write += interleaved_write_len;
|
||||
}
|
||||
|
||||
/* Do another write in case |write_buf_offset| was wrapped */
|
||||
total_write += bio_write_zero_copy_wrapper(
|
||||
bio1, bio1_application_send_buffer + total_write,
|
||||
kPartialLengths[j] - interleaved_write_len);
|
||||
|
||||
/* Drain the rest. */
|
||||
bytes_left = BIO_pending(bio2);
|
||||
total_read += bio_read_zero_copy_wrapper(
|
||||
bio2, bio2_application_recv_buffer + total_read, bytes_left);
|
||||
|
||||
BIO_free(bio1);
|
||||
BIO_free(bio2);
|
||||
|
||||
if (total_read != total_write) {
|
||||
fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return 0;
|
||||
}
|
||||
if (total_read > kLengths[i] + kPartialLengths[j]) {
|
||||
fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer,
|
||||
total_read) != 0) {
|
||||
fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_printf(void) {
|
||||
/* Test a short output, a very long one, and various sizes around
|
||||
* 256 (the size of the buffer) to ensure edge cases are correct. */
|
||||
@@ -201,6 +351,10 @@ int main(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!test_zero_copy_bio_pairs()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -81,9 +81,10 @@ static char to_char(uint8_t b) {
|
||||
return b;
|
||||
}
|
||||
|
||||
/* hexdump adds |len| bytes of |data| to the current hex dump described by
|
||||
/* hexdump_write adds |len| bytes of |data| to the current hex dump described by
|
||||
* |ctx|. */
|
||||
static int hexdump(struct hexdump_ctx *ctx, const uint8_t *data, size_t len) {
|
||||
static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
|
||||
size_t len) {
|
||||
size_t i;
|
||||
char buf[10];
|
||||
unsigned l;
|
||||
@@ -182,7 +183,7 @@ int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
|
||||
ctx.bio = bio;
|
||||
ctx.indent = indent;
|
||||
|
||||
if (!hexdump(&ctx, data, len) || !finish(&ctx)) {
|
||||
if (!hexdump_write(&ctx, data, len) || !finish(&ctx)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+343
-72
@@ -70,7 +70,13 @@ struct bio_bio_st {
|
||||
size_t len; /* valid iff buf != NULL; 0 if peer == NULL */
|
||||
size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
|
||||
size_t size;
|
||||
char *buf; /* "size" elements (if != NULL) */
|
||||
uint8_t *buf; /* "size" elements (if != NULL) */
|
||||
char buf_externally_allocated; /* true iff buf was externally allocated. */
|
||||
|
||||
char zero_copy_read_lock; /* true iff a zero copy read operation
|
||||
* is in progress. */
|
||||
char zero_copy_write_lock; /* true iff a zero copy write operation
|
||||
* is in progress. */
|
||||
|
||||
size_t request; /* valid iff peer != NULL; 0 if len != 0,
|
||||
* otherwise set by peer to number of bytes
|
||||
@@ -85,11 +91,9 @@ static int bio_new(BIO *bio) {
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memset(b, 0, sizeof(struct bio_bio_st));
|
||||
|
||||
b->peer = NULL;
|
||||
b->size = 17 * 1024; /* enough for one TLS record (just a default) */
|
||||
b->buf = NULL;
|
||||
|
||||
bio->ptr = b;
|
||||
return 1;
|
||||
}
|
||||
@@ -140,7 +144,7 @@ static int bio_free(BIO *bio) {
|
||||
bio_destroy_pair(bio);
|
||||
}
|
||||
|
||||
if (b->buf != NULL) {
|
||||
if (b->buf != NULL && !b->buf_externally_allocated) {
|
||||
OPENSSL_free(b->buf);
|
||||
}
|
||||
|
||||
@@ -149,6 +153,268 @@ static int bio_free(BIO *bio) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
|
||||
uint8_t** out_read_buf,
|
||||
size_t* out_buf_offset) {
|
||||
size_t max_available;
|
||||
if (peer_b->len > peer_b->size - peer_b->offset) {
|
||||
/* Only the first half of the ring buffer can be read. */
|
||||
max_available = peer_b->size - peer_b->offset;
|
||||
} else {
|
||||
max_available = peer_b->len;
|
||||
}
|
||||
|
||||
*out_read_buf = peer_b->buf;
|
||||
*out_buf_offset = peer_b->offset;
|
||||
return max_available;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
|
||||
size_t* out_buf_offset,
|
||||
size_t* out_available_bytes) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
*out_available_bytes = 0;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf,
|
||||
BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf,
|
||||
BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (peer_b->zero_copy_read_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b->request = 0; /* Is not used by zero-copy API. */
|
||||
|
||||
max_available =
|
||||
bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
|
||||
|
||||
assert(peer_b->buf != NULL);
|
||||
if (max_available > 0) {
|
||||
peer_b->zero_copy_read_lock = 1;
|
||||
}
|
||||
|
||||
*out_available_bytes = max_available;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
size_t dummy_read_offset;
|
||||
uint8_t* dummy_read_buf;
|
||||
|
||||
assert(BIO_get_retry_flags(bio) == 0);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
|
||||
BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
|
||||
BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
|
||||
BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!peer_b->zero_copy_read_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
|
||||
BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_available =
|
||||
bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
|
||||
if (bytes_read > max_available) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
|
||||
BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b->len -= bytes_read;
|
||||
assert(peer_b->len >= 0);
|
||||
assert(peer_b->offset + bytes_read <= peer_b->size);
|
||||
|
||||
/* Move read offset. If zero_copy_write_lock == 1 we must advance the
|
||||
* offset even if buffer becomes empty, to make sure
|
||||
* write_offset = (offset + len) mod size does not change. */
|
||||
if (peer_b->offset + bytes_read == peer_b->size ||
|
||||
(!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
|
||||
peer_b->offset = 0;
|
||||
} else {
|
||||
peer_b->offset += bytes_read;
|
||||
}
|
||||
|
||||
bio->num_read += bytes_read;
|
||||
peer_b->zero_copy_read_lock = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
|
||||
uint8_t** out_write_buf,
|
||||
size_t* out_buf_offset) {
|
||||
size_t write_offset;
|
||||
size_t max_available;
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
write_offset = b->offset + b->len;
|
||||
|
||||
if (write_offset >= b->size) {
|
||||
/* Only the first half of the ring buffer can be written to. */
|
||||
write_offset -= b->size;
|
||||
/* write up to the start of the ring buffer. */
|
||||
max_available = b->offset - write_offset;
|
||||
} else {
|
||||
/* write up to the end the buffer. */
|
||||
max_available = b->size - write_offset;
|
||||
}
|
||||
|
||||
*out_write_buf = b->buf;
|
||||
*out_buf_offset = write_offset;
|
||||
return max_available;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
|
||||
size_t* out_buf_offset,
|
||||
size_t* out_available_bytes) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
|
||||
*out_available_bytes = 0;
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->buf || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf,
|
||||
BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf,
|
||||
BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(b->buf != NULL);
|
||||
|
||||
if (b->zero_copy_write_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* Bio is already closed. */
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_BROKEN_PIPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
|
||||
|
||||
if (max_available > 0) {
|
||||
b->zero_copy_write_lock = 1;
|
||||
}
|
||||
|
||||
*out_available_bytes = max_available;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
|
||||
size_t rest;
|
||||
size_t dummy_write_offset;
|
||||
uint8_t* dummy_write_buf;
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
|
||||
BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->buf || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
|
||||
BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
|
||||
BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* BIO is already closed. */
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done, BIO_R_BROKEN_PIPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!b->zero_copy_write_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
|
||||
BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
|
||||
|
||||
if (bytes_written > rest) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
|
||||
BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bio->num_write += bytes_written;
|
||||
/* Move write offset. */
|
||||
b->len += bytes_written;
|
||||
b->zero_copy_write_lock = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
size_t size = size_;
|
||||
size_t rest;
|
||||
@@ -169,7 +435,7 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
|
||||
peer_b->request = 0; /* will be set in "retry_read" situation */
|
||||
|
||||
if (buf == NULL || size == 0) {
|
||||
if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -214,7 +480,10 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
memcpy(buf, peer_b->buf + peer_b->offset, chunk);
|
||||
|
||||
peer_b->len -= chunk;
|
||||
if (peer_b->len) {
|
||||
/* If zero_copy_write_lock == 1 we must advance the offset even if buffer
|
||||
* becomes empty, to make sure write_offset = (offset + len) % size
|
||||
* does not change. */
|
||||
if (peer_b->len || peer_b->zero_copy_write_lock) {
|
||||
peer_b->offset += chunk;
|
||||
assert(peer_b->offset <= peer_b->size);
|
||||
if (peer_b->offset == peer_b->size) {
|
||||
@@ -248,6 +517,10 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
assert(b->peer != NULL);
|
||||
assert(b->buf != NULL);
|
||||
|
||||
if (b->zero_copy_write_lock) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* we already closed */
|
||||
@@ -304,7 +577,9 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
return num;
|
||||
}
|
||||
|
||||
static int bio_make_pair(BIO *bio1, BIO *bio2) {
|
||||
static int bio_make_pair(BIO* bio1, BIO* bio2,
|
||||
size_t writebuf1_len, uint8_t* ext_writebuf1,
|
||||
size_t writebuf2_len, uint8_t* ext_writebuf2) {
|
||||
struct bio_bio_st *b1, *b2;
|
||||
|
||||
assert(bio1 != NULL);
|
||||
@@ -318,21 +593,42 @@ static int bio_make_pair(BIO *bio1, BIO *bio2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(b1->buf_externally_allocated == 0);
|
||||
assert(b2->buf_externally_allocated == 0);
|
||||
|
||||
if (b1->buf == NULL) {
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
if (writebuf1_len) {
|
||||
b1->size = writebuf1_len;
|
||||
}
|
||||
if (!ext_writebuf1) {
|
||||
b1->buf_externally_allocated = 0;
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
b1->buf = ext_writebuf1;
|
||||
b1->buf_externally_allocated = 1;
|
||||
}
|
||||
b1->len = 0;
|
||||
b1->offset = 0;
|
||||
}
|
||||
|
||||
if (b2->buf == NULL) {
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
if (writebuf2_len) {
|
||||
b2->size = writebuf2_len;
|
||||
}
|
||||
if (!ext_writebuf2) {
|
||||
b2->buf_externally_allocated = 0;
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
b2->buf = ext_writebuf2;
|
||||
b2->buf_externally_allocated = 1;
|
||||
}
|
||||
b2->len = 0;
|
||||
b2->offset = 0;
|
||||
@@ -341,9 +637,13 @@ static int bio_make_pair(BIO *bio1, BIO *bio2) {
|
||||
b1->peer = bio2;
|
||||
b1->closed = 0;
|
||||
b1->request = 0;
|
||||
b1->zero_copy_read_lock = 0;
|
||||
b1->zero_copy_write_lock = 0;
|
||||
b2->peer = bio1;
|
||||
b2->closed = 0;
|
||||
b2->request = 0;
|
||||
b2->zero_copy_read_lock = 0;
|
||||
b2->zero_copy_write_lock = 0;
|
||||
|
||||
bio1->init = 1;
|
||||
bio2->init = 1;
|
||||
@@ -360,27 +660,6 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
switch (cmd) {
|
||||
/* specific CTRL codes */
|
||||
|
||||
case BIO_C_SET_BUFF_SIZE:
|
||||
if (b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_ctrl, BIO_R_IN_USE);
|
||||
ret = 0;
|
||||
} else if (num == 0) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_ctrl, BIO_R_INVALID_ARGUMENT);
|
||||
ret = 0;
|
||||
} else {
|
||||
size_t new_size = num;
|
||||
|
||||
if (b->size != new_size) {
|
||||
if (b->buf) {
|
||||
OPENSSL_free(b->buf);
|
||||
b->buf = NULL;
|
||||
}
|
||||
b->size = new_size;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_GET_WRITE_BUF_SIZE:
|
||||
ret = (long)b->size;
|
||||
break;
|
||||
@@ -419,14 +698,6 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
|
||||
/* standard CTRL codes follow */
|
||||
|
||||
case BIO_CTRL_RESET:
|
||||
if (b->buf != NULL) {
|
||||
b->len = 0;
|
||||
b->offset = 0;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = bio->shutdown;
|
||||
break;
|
||||
@@ -478,35 +749,43 @@ static int bio_puts(BIO *bio, const char *str) {
|
||||
return bio_write(bio, str, strlen(str));
|
||||
}
|
||||
|
||||
int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, BIO **bio2_p,
|
||||
size_t writebuf2) {
|
||||
static const BIO_METHOD methods_biop = {
|
||||
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 */
|
||||
};
|
||||
|
||||
const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
|
||||
|
||||
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
|
||||
BIO** bio2_p, size_t writebuf2) {
|
||||
return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
|
||||
writebuf2, NULL);
|
||||
}
|
||||
|
||||
int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
|
||||
uint8_t* ext_writebuf1,
|
||||
BIO** bio2_p, size_t writebuf2_len,
|
||||
uint8_t* ext_writebuf2) {
|
||||
BIO *bio1 = NULL, *bio2 = NULL;
|
||||
long r;
|
||||
int ret = 0;
|
||||
|
||||
bio1 = BIO_new(BIO_s_bio());
|
||||
/* External buffers must have sizes greater than 0. */
|
||||
if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bio1 = BIO_new(bio_s_bio());
|
||||
if (bio1 == NULL) {
|
||||
goto err;
|
||||
}
|
||||
bio2 = BIO_new(BIO_s_bio());
|
||||
bio2 = BIO_new(bio_s_bio());
|
||||
if (bio2 == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (writebuf1) {
|
||||
r = BIO_set_write_buffer_size(bio1, writebuf1);
|
||||
if (!r) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (writebuf2) {
|
||||
r = BIO_set_write_buffer_size(bio2, writebuf2);
|
||||
if (!r) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bio_make_pair(bio1, bio2)) {
|
||||
if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
|
||||
ext_writebuf2)) {
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
@@ -528,14 +807,6 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_biop = {
|
||||
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 */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_bio(void) { return &methods_biop; }
|
||||
|
||||
size_t BIO_ctrl_get_read_request(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ if (!$avx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-
|
||||
$addx = ($ver>=3.03);
|
||||
}
|
||||
|
||||
open OUT,"| $^X $xlate $flavour $output";
|
||||
open OUT,"| \"$^X\" $xlate $flavour $output";
|
||||
*STDOUT = *OUT;
|
||||
|
||||
if ($avx>1) {{{
|
||||
|
||||
@@ -95,7 +95,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
|
||||
die "can't locate x86_64-xlate.pl";
|
||||
|
||||
open OUT,"| $^X $xlate $flavour $output";
|
||||
open OUT,"| \"$^X\" $xlate $flavour $output";
|
||||
*STDOUT=*OUT;
|
||||
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
|
||||
+27
-65
@@ -292,80 +292,45 @@ BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
|
||||
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0)
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/* original macros are kept for reference purposes */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
{ \
|
||||
BN_ULONG ta = (a), tb = (b); \
|
||||
t1 = ta * tb; \
|
||||
t2 = BN_UMULT_HIGH(ta, tb); \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
{ \
|
||||
BN_ULONG ta = (a), tb = (b), t0; \
|
||||
t1 = BN_UMULT_HIGH(ta, tb); \
|
||||
t0 = ta * tb; \
|
||||
t2 = t1 + t1; \
|
||||
c2 += (t2 < t1) ? 1 : 0; \
|
||||
t1 = t0 + t0; \
|
||||
t2 += (t1 < t0) ? 1 : 0; \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
#else
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
/* Keep in mind that carrying into high part of multiplication result can not
|
||||
* overflow, because it cannot be all-ones. */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0), "+d"(t2) \
|
||||
: "a"(t1), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1), "+r"(c2) \
|
||||
: "d"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0), "+d"(t2) \
|
||||
: "a"(t1), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1), "+r"(c2) \
|
||||
: "d"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
|
||||
asm("addq %0,%0; adcq %2,%1" : "+d"(t2), "+r"(c2) : "g"(0) : "cc"); \
|
||||
asm("addq %0,%0; adcq %2,%1" : "+a"(t1), "+d"(t2) : "g"(0) : "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0), "+d"(t2) \
|
||||
: "a"(t1), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1), "+r"(c2) \
|
||||
: "d"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -468,7 +433,6 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -507,7 +471,6 @@ void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
}
|
||||
|
||||
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -582,7 +545,6 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
|
||||
}
|
||||
|
||||
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
|
||||
+79
-21
@@ -653,40 +653,98 @@ int test_mul(BIO *bp) {
|
||||
}
|
||||
|
||||
int test_sqr(BIO *bp, BN_CTX *ctx) {
|
||||
BIGNUM a, c, d, e;
|
||||
int i;
|
||||
BIGNUM *a, *c, *d, *e;
|
||||
int i, ret = 0;
|
||||
|
||||
BN_init(&a);
|
||||
BN_init(&c);
|
||||
BN_init(&d);
|
||||
BN_init(&e);
|
||||
a = BN_new();
|
||||
c = BN_new();
|
||||
d = BN_new();
|
||||
e = BN_new();
|
||||
if (a == NULL || c == NULL || d == NULL || e == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < num0; i++) {
|
||||
BN_rand(&a, 40 + i * 10, 0, 0);
|
||||
a.neg = rand_neg();
|
||||
BN_sqr(&c, &a, ctx);
|
||||
BN_rand(a, 40 + i * 10, 0, 0);
|
||||
a->neg = rand_neg();
|
||||
BN_sqr(c, a, ctx);
|
||||
if (bp != NULL) {
|
||||
if (!results) {
|
||||
BN_print(bp, &a);
|
||||
BN_print(bp, a);
|
||||
BIO_puts(bp, " * ");
|
||||
BN_print(bp, &a);
|
||||
BN_print(bp, a);
|
||||
BIO_puts(bp, " - ");
|
||||
}
|
||||
BN_print(bp, &c);
|
||||
BN_print(bp, c);
|
||||
BIO_puts(bp, "\n");
|
||||
}
|
||||
BN_div(&d, &e, &c, &a, ctx);
|
||||
BN_sub(&d, &d, &a);
|
||||
if (!BN_is_zero(&d) || !BN_is_zero(&e)) {
|
||||
BN_div(d, e, c, a, ctx);
|
||||
BN_sub(d, d, a);
|
||||
if (!BN_is_zero(d) || !BN_is_zero(e)) {
|
||||
fprintf(stderr, "Square test failed!\n");
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
BN_free(&a);
|
||||
BN_free(&c);
|
||||
BN_free(&d);
|
||||
BN_free(&e);
|
||||
return (1);
|
||||
|
||||
/* Regression test for a BN_sqr overflow bug. */
|
||||
BN_hex2bn(&a,
|
||||
"80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000");
|
||||
BN_sqr(c, a, ctx);
|
||||
if (bp != NULL) {
|
||||
if (!results) {
|
||||
BN_print(bp, a);
|
||||
BIO_puts(bp, " * ");
|
||||
BN_print(bp, a);
|
||||
BIO_puts(bp, " - ");
|
||||
}
|
||||
BN_print(bp, c);
|
||||
BIO_puts(bp, "\n");
|
||||
}
|
||||
BN_mul(d, a, a, ctx);
|
||||
if (BN_cmp(c, d)) {
|
||||
fprintf(stderr,
|
||||
"Square test failed: BN_sqr and BN_mul produce "
|
||||
"different results!\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Regression test for a BN_sqr overflow bug. */
|
||||
BN_hex2bn(&a,
|
||||
"80000000000000000000000080000001FFFFFFFE000000000000000000000000");
|
||||
BN_sqr(c, a, ctx);
|
||||
if (bp != NULL) {
|
||||
if (!results) {
|
||||
BN_print(bp, a);
|
||||
BIO_puts(bp, " * ");
|
||||
BN_print(bp, a);
|
||||
BIO_puts(bp, " - ");
|
||||
}
|
||||
BN_print(bp, c);
|
||||
BIO_puts(bp, "\n");
|
||||
}
|
||||
BN_mul(d, a, a, ctx);
|
||||
if (BN_cmp(c, d)) {
|
||||
fprintf(stderr,
|
||||
"Square test failed: BN_sqr and BN_mul produce "
|
||||
"different results!\n");
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (a != NULL) {
|
||||
BN_free(a);
|
||||
}
|
||||
if (c != NULL) {
|
||||
BN_free(c);
|
||||
}
|
||||
if (d != NULL) {
|
||||
BN_free(d);
|
||||
}
|
||||
if (e != NULL) {
|
||||
BN_free(e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -416,7 +416,7 @@ err:
|
||||
|
||||
static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx) {
|
||||
int i, j, bits, ret = 0, wstart, wend, window, wvalue;
|
||||
int i, j, bits, ret = 0, wstart, window;
|
||||
int start = 1;
|
||||
BIGNUM *aa;
|
||||
/* Table of variables obtained from 'ctx' */
|
||||
@@ -485,15 +485,16 @@ static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
start = 1; /* This is used to avoid multiplication etc
|
||||
* when there is only the value '1' in the
|
||||
* buffer. */
|
||||
wvalue = 0; /* The 'value' of the window */
|
||||
wstart = bits - 1; /* The top bit of the window */
|
||||
wend = 0; /* The bottom bit of the window */
|
||||
|
||||
if (!BN_one(r)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int wvalue; /* The 'value' of the window */
|
||||
int wend; /* The bottom bit of the window */
|
||||
|
||||
if (BN_is_bit_set(p, wstart) == 0) {
|
||||
if (!start) {
|
||||
if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) {
|
||||
@@ -542,7 +543,6 @@ static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
|
||||
/* move the 'window' down further */
|
||||
wstart -= wend + 1;
|
||||
wvalue = 0;
|
||||
start = 0;
|
||||
if (wstart < 0) {
|
||||
break;
|
||||
@@ -601,7 +601,7 @@ int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
|
||||
|
||||
int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) {
|
||||
int i, j, bits, ret = 0, wstart, wend, window, wvalue;
|
||||
int i, j, bits, ret = 0, wstart, window;
|
||||
int start = 1;
|
||||
BIGNUM *d, *r;
|
||||
const BIGNUM *aa;
|
||||
@@ -680,9 +680,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
start = 1; /* This is used to avoid multiplication etc
|
||||
* when there is only the value '1' in the
|
||||
* buffer. */
|
||||
wvalue = 0; /* The 'value' of the window */
|
||||
wstart = bits - 1; /* The top bit of the window */
|
||||
wend = 0; /* The bottom bit of the window */
|
||||
|
||||
j = m->top; /* borrow j */
|
||||
if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
|
||||
@@ -701,6 +699,9 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int wvalue; /* The 'value' of the window */
|
||||
int wend; /* The bottom bit of the window */
|
||||
|
||||
if (BN_is_bit_set(p, wstart) == 0) {
|
||||
if (!start) {
|
||||
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
|
||||
@@ -716,7 +717,6 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
/* We now have wstart on a 'set' bit, we now need to work out how bit a
|
||||
* window to do. To do this we need to scan forward until the last set bit
|
||||
* before the end of the window */
|
||||
j = wstart;
|
||||
wvalue = 1;
|
||||
wend = 0;
|
||||
for (i = 1; i < window; i++) {
|
||||
@@ -748,7 +748,6 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
|
||||
/* move the 'window' down further */
|
||||
wstart -= wend + 1;
|
||||
wvalue = 0;
|
||||
start = 0;
|
||||
if (wstart < 0) {
|
||||
break;
|
||||
|
||||
+155
-154
@@ -659,175 +659,194 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */
|
||||
|
||||
#ifdef BN_LLONG
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
t = (BN_ULLONG)a * b; \
|
||||
t1 = (BN_ULONG)Lw(t); \
|
||||
t2 = (BN_ULONG)Hw(t); \
|
||||
c0 = (c0 + t1) & BN_MASK2; \
|
||||
if ((c0) < t1) \
|
||||
t2++; \
|
||||
c1 = (c1 + t2) & BN_MASK2; \
|
||||
if ((c1) < t2) \
|
||||
c2++;
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
t = (BN_ULLONG)a * b; \
|
||||
tt = (t + t) & BN_MASK; \
|
||||
if (tt < t) \
|
||||
c2++; \
|
||||
t1 = (BN_ULONG)Lw(tt); \
|
||||
t2 = (BN_ULONG)Hw(tt); \
|
||||
c0 = (c0 + t1) & BN_MASK2; \
|
||||
if ((c0 < t1) && (((++t2) & BN_MASK2) == 0)) \
|
||||
c2++; \
|
||||
c1 = (c1 + t2) & BN_MASK2; \
|
||||
if ((c1) < t2) \
|
||||
c2++;
|
||||
/* Keep in mind that additions to multiplication result can not overflow,
|
||||
* because its high half cannot be all-ones. */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG hi; \
|
||||
BN_ULLONG t = (BN_ULLONG)(a) * (b); \
|
||||
t += c0; /* no carry */ \
|
||||
c0 = (BN_ULONG)Lw(t); \
|
||||
hi = (BN_ULONG)Hw(t); \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
t = (BN_ULLONG)a[i] * a[i]; \
|
||||
t1 = (BN_ULONG)Lw(t); \
|
||||
t2 = (BN_ULONG)Hw(t); \
|
||||
c0 = (c0 + t1) & BN_MASK2; \
|
||||
if ((c0) < t1) \
|
||||
t2++; \
|
||||
c1 = (c1 + t2) & BN_MASK2; \
|
||||
if ((c1) < t2) \
|
||||
c2++;
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG hi; \
|
||||
BN_ULLONG t = (BN_ULLONG)(a) * (b); \
|
||||
BN_ULLONG tt = t + c0; /* no carry */ \
|
||||
c0 = (BN_ULONG)Lw(tt); \
|
||||
hi = (BN_ULONG)Hw(tt); \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
t += c0; /* no carry */ \
|
||||
c0 = (BN_ULONG)Lw(t); \
|
||||
hi = (BN_ULONG)Hw(t); \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG hi; \
|
||||
BN_ULLONG t = (BN_ULLONG)a[i] * a[i]; \
|
||||
t += c0; /* no carry */ \
|
||||
c0 = (BN_ULONG)Lw(t); \
|
||||
hi = (BN_ULONG)Hw(t); \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
#elif defined(BN_UMULT_LOHI)
|
||||
|
||||
/* Keep in mind that additions to hi can not overflow, because the high word of
|
||||
* a multiplication result cannot be all-ones. */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
{ \
|
||||
do { \
|
||||
BN_ULONG ta = (a), tb = (b); \
|
||||
BN_UMULT_LOHI(t1, t2, ta, tb); \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
BN_ULONG lo, hi; \
|
||||
BN_UMULT_LOHI(lo, hi, ta, tb); \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
{ \
|
||||
BN_ULONG ta = (a), tb = (b), t0; \
|
||||
BN_UMULT_LOHI(t0, t1, ta, tb); \
|
||||
t2 = t1 + t1; \
|
||||
c2 += (t2 < t1) ? 1 : 0; \
|
||||
t1 = t0 + t0; \
|
||||
t2 += (t1 < t0) ? 1 : 0; \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
do { \
|
||||
BN_ULONG ta = (a), tb = (b); \
|
||||
BN_ULONG lo, hi, tt; \
|
||||
BN_UMULT_LOHI(lo, hi, ta, tb); \
|
||||
c0 += lo; \
|
||||
tt = hi + ((c0 < lo) ? 1 : 0); \
|
||||
c1 += tt; \
|
||||
c2 += (c1 < tt) ? 1 : 0; \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
{ \
|
||||
do { \
|
||||
BN_ULONG ta = (a)[i]; \
|
||||
BN_UMULT_LOHI(t1, t2, ta, ta); \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
BN_ULONG lo, hi; \
|
||||
BN_UMULT_LOHI(lo, hi, ta, ta); \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
#elif defined(BN_UMULT_HIGH)
|
||||
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
{ \
|
||||
BN_ULONG ta = (a), tb = (b); \
|
||||
t1 = ta * tb; \
|
||||
t2 = BN_UMULT_HIGH(ta, tb); \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
/* Keep in mind that additions to hi can not overflow, because
|
||||
* the high word of a multiplication result cannot be all-ones. */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG ta = (a), tb = (b); \
|
||||
BN_ULONG lo = ta * tb; \
|
||||
BN_ULONG hi = BN_UMULT_HIGH(ta, tb); \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
{ \
|
||||
BN_ULONG ta = (a), tb = (b), t0; \
|
||||
t1 = BN_UMULT_HIGH(ta, tb); \
|
||||
t0 = ta * tb; \
|
||||
t2 = t1 + t1; \
|
||||
c2 += (t2 < t1) ? 1 : 0; \
|
||||
t1 = t0 + t0; \
|
||||
t2 += (t1 < t0) ? 1 : 0; \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG ta = (a), tb = (b), tt; \
|
||||
BN_ULONG lo = ta * tb; \
|
||||
BN_ULONG hi = BN_UMULT_HIGH(ta, tb); \
|
||||
c0 += lo; \
|
||||
tt = hi + ((c0 < lo) ? 1 : 0); \
|
||||
c1 += tt; \
|
||||
c2 += (c1 < tt) ? 1 : 0; \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
{ \
|
||||
BN_ULONG ta = (a)[i]; \
|
||||
t1 = ta * ta; \
|
||||
t2 = BN_UMULT_HIGH(ta, ta); \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG ta = (a)[i]; \
|
||||
BN_ULONG lo = ta * ta; \
|
||||
BN_ULONG hi = BN_UMULT_HIGH(ta, ta); \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
#else /* !BN_LLONG */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
t1 = LBITS(a); \
|
||||
t2 = HBITS(a); \
|
||||
bl = LBITS(b); \
|
||||
bh = HBITS(b); \
|
||||
mul64(t1, t2, bl, bh); \
|
||||
c0 = (c0 + t1) & BN_MASK2; \
|
||||
if ((c0) < t1) \
|
||||
t2++; \
|
||||
c1 = (c1 + t2) & BN_MASK2; \
|
||||
if ((c1) < t2) \
|
||||
c2++;
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
t1 = LBITS(a); \
|
||||
t2 = HBITS(a); \
|
||||
bl = LBITS(b); \
|
||||
bh = HBITS(b); \
|
||||
mul64(t1, t2, bl, bh); \
|
||||
if (t2 & BN_TBIT) \
|
||||
c2++; \
|
||||
t2 = (t2 + t2) & BN_MASK2; \
|
||||
if (t1 & BN_TBIT) \
|
||||
t2++; \
|
||||
t1 = (t1 + t1) & BN_MASK2; \
|
||||
c0 = (c0 + t1) & BN_MASK2; \
|
||||
if ((c0 < t1) && (((++t2) & BN_MASK2) == 0)) \
|
||||
c2++; \
|
||||
c1 = (c1 + t2) & BN_MASK2; \
|
||||
if ((c1) < t2) \
|
||||
c2++;
|
||||
/* Keep in mind that additions to hi can not overflow, because
|
||||
* the high word of a multiplication result cannot be all-ones. */
|
||||
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
|
||||
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
|
||||
mul64(lo, hi, bl, bh); \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG tt; \
|
||||
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
|
||||
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
|
||||
mul64(lo, hi, bl, bh); \
|
||||
tt = hi; \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
tt++; \
|
||||
c1 = (c1 + tt) & BN_MASK2; \
|
||||
if (c1 < tt) \
|
||||
c2++; \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
sqr64(t1, t2, (a)[i]); \
|
||||
c0 = (c0 + t1) & BN_MASK2; \
|
||||
if ((c0) < t1) \
|
||||
t2++; \
|
||||
c1 = (c1 + t2) & BN_MASK2; \
|
||||
if ((c1) < t2) \
|
||||
c2++;
|
||||
do { \
|
||||
BN_ULONG lo, hi; \
|
||||
sqr64(lo, hi, (a)[i]); \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
#endif /* !BN_LLONG */
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
#if defined(BN_LLONG)
|
||||
BN_ULLONG t;
|
||||
#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
|
||||
BN_ULONG bl, bh;
|
||||
#endif
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -930,12 +949,6 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
#if defined(BN_LLONG)
|
||||
BN_ULLONG t;
|
||||
#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
|
||||
BN_ULONG bl, bh;
|
||||
#endif
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -974,12 +987,6 @@ void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
}
|
||||
|
||||
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
|
||||
#if defined(BN_LLONG)
|
||||
BN_ULLONG t, tt;
|
||||
#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
|
||||
BN_ULONG bl, bh;
|
||||
#endif
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -1054,12 +1061,6 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
|
||||
}
|
||||
|
||||
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
|
||||
#if defined(BN_LLONG)
|
||||
BN_ULLONG t, tt;
|
||||
#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
|
||||
BN_ULONG bl, bh;
|
||||
#endif
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
|
||||
@@ -127,6 +127,11 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(__umulh, _umul128)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -239,7 +244,7 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
|
||||
# if defined(__GNUC__) && __GNUC__>=2
|
||||
# if defined(__GNUC__) && __GNUC__ >= 2
|
||||
# define BN_UMULT_HIGH(a,b) ({ \
|
||||
register BN_ULONG ret,discard; \
|
||||
__asm__ ("mulq %3" \
|
||||
@@ -252,14 +257,9 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
: "=a"(low),"=d"(high) \
|
||||
: "a"(a),"g"(b) \
|
||||
: "cc");
|
||||
# endif
|
||||
# if defined(_MSC_VER) && _MSC_VER>=1400
|
||||
unsigned __int64 __umulh (unsigned __int64 a,unsigned __int64 b);
|
||||
unsigned __int64 _umul128 (unsigned __int64 a,unsigned __int64 b,
|
||||
unsigned __int64 *h);
|
||||
# pragma intrinsic(__umulh,_umul128)
|
||||
# define BN_UMULT_HIGH(a,b) __umulh((a),(b))
|
||||
# define BN_UMULT_LOHI(low,high,a,b) ((low)=_umul128((a),(b),&(high)))
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
# define BN_UMULT_HIGH(a, b) __umulh((a), (b))
|
||||
# define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
|
||||
# endif
|
||||
#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64)
|
||||
# if defined(__GNUC__) && __GNUC__>=2
|
||||
|
||||
+4
-3
@@ -136,9 +136,10 @@ int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* make a random number and set the top and bottom bits */
|
||||
if (RAND_pseudo_bytes(buf, bytes) <= 0)
|
||||
/* Make a random number and set the top and bottom bits. */
|
||||
if (!RAND_bytes(buf, bytes)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (top != -1) {
|
||||
if (top) {
|
||||
@@ -286,7 +287,7 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
|
||||
|
||||
for (attempt = 0;; attempt++) {
|
||||
for (done = 0; done < num_k_bytes;) {
|
||||
if (RAND_pseudo_bytes(random_bytes, sizeof(random_bytes)) != 1) {
|
||||
if (!RAND_bytes(random_bytes, sizeof(random_bytes))) {
|
||||
goto err;
|
||||
}
|
||||
SHA512_Init(&sha);
|
||||
|
||||
@@ -122,15 +122,17 @@ static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
|
||||
* implicit and the tags within are fragments of a primitive type that
|
||||
* need to be concatenated. */
|
||||
if (context_specific && (tag & CBS_ASN1_CONSTRUCTED)) {
|
||||
CBS in_copy, contents;
|
||||
unsigned tag;
|
||||
size_t header_len;
|
||||
CBS in_copy, inner_contents;
|
||||
unsigned inner_tag;
|
||||
size_t inner_header_len;
|
||||
|
||||
CBS_init(&in_copy, CBS_data(in), CBS_len(in));
|
||||
if (!CBS_get_any_asn1_element(&in_copy, &contents, &tag, &header_len)) {
|
||||
if (!CBS_get_any_asn1_element(&in_copy, &inner_contents, &inner_tag,
|
||||
&inner_header_len)) {
|
||||
return 0;
|
||||
}
|
||||
if (CBS_len(&contents) > header_len && is_primitive_type(tag)) {
|
||||
if (CBS_len(&inner_contents) > inner_header_len &&
|
||||
is_primitive_type(inner_tag)) {
|
||||
squash_child_headers = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,8 +448,7 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) {
|
||||
if (arg) {
|
||||
memcpy(gctx->iv, ptr, arg);
|
||||
}
|
||||
if (c->encrypt &&
|
||||
RAND_pseudo_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) {
|
||||
if (c->encrypt && !RAND_bytes(gctx->iv + arg, gctx->ivlen - arg)) {
|
||||
return 0;
|
||||
}
|
||||
gctx->iv_gen = 1;
|
||||
@@ -1103,7 +1102,7 @@ static int aead_aes_key_wrap_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
/* The code below only handles a 32-bit |t| thus 6*|n| must be less than
|
||||
* 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we
|
||||
* conservatively cap it to 2^32-16 to stop 32-bit platforms complaining that
|
||||
* a comparision is always true. */
|
||||
* a comparison is always true. */
|
||||
if (in_len > 0xfffffff0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
@@ -1198,7 +1197,7 @@ static int aead_aes_key_wrap_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
/* The code below only handles a 32-bit |t| thus 6*|n| must be less than
|
||||
* 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we
|
||||
* conservatively cap it to 2^32-8 to stop 32-bit platforms complaining that
|
||||
* a comparision is always true. */
|
||||
* a comparison is always true. */
|
||||
if (in_len > 0xfffffff8) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
|
||||
@@ -279,7 +279,6 @@ static void RC2_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
l2c(xor0, iv);
|
||||
l2c(xor1, iv);
|
||||
}
|
||||
tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
|
||||
tin[0] = tin[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/cpu.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/mem.h>
|
||||
@@ -176,7 +177,6 @@ static int aead_rc4_md5_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
MD5_CTX md;
|
||||
#if defined(STITCHED_CALL)
|
||||
size_t rc4_off, md5_off, blocks;
|
||||
extern unsigned int OPENSSL_ia32cap_P[];
|
||||
#else
|
||||
const size_t rc4_off = 0;
|
||||
const size_t md5_off = 0;
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Utilities for constant-time cryptography.
|
||||
*
|
||||
* Author: Emilia Kasper (emilia@openssl.org)
|
||||
* Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
|
||||
* (Google).
|
||||
* ====================================================================
|
||||
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the 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 "internal.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.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 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 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 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 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};
|
||||
|
||||
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");
|
||||
|
||||
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 (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 (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;
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,11 @@ add_library(
|
||||
digests.c
|
||||
digest_error.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
digest_test
|
||||
|
||||
digest_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(digest_test crypto)
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md4.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* md_func is the digest to test. */
|
||||
const EVP_MD *(*md_func)(void);
|
||||
/* one_shot_func is the convenience one-shot version of the
|
||||
* digest. */
|
||||
uint8_t *(*one_shot_func)(const uint8_t *, size_t, uint8_t *);
|
||||
/* input is a NUL-terminated string to hash. */
|
||||
const char *input;
|
||||
/* repeat is the number of times to repeat input. */
|
||||
size_t repeat;
|
||||
/* expected_hex is the expected digest in hexadecimal. */
|
||||
const char *expected_hex;
|
||||
} TEST_VECTOR;
|
||||
|
||||
static const TEST_VECTOR kTestVectors[] = {
|
||||
/* MD4 tests, from RFC 1320. (crypto/md4 does not provide a
|
||||
* one-shot MD4 function.) */
|
||||
{ &EVP_md4, NULL, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0" },
|
||||
{ &EVP_md4, NULL, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24" },
|
||||
{ &EVP_md4, NULL, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d" },
|
||||
{ &EVP_md4, NULL, "message digest", 1,
|
||||
"d9130a8164549fe818874806e1c7014b" },
|
||||
{ &EVP_md4, NULL, "abcdefghijklmnopqrstuvwxyz", 1,
|
||||
"d79e1c308aa5bbcdeea8ed63df412da9" },
|
||||
{ &EVP_md4, NULL,
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
|
||||
"043f8582f241db351ce627e153e7f0e4" },
|
||||
{ &EVP_md4, NULL, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536" },
|
||||
|
||||
/* MD5 tests, from RFC 1321. */
|
||||
{ &EVP_md5, &MD5, "", 1, "d41d8cd98f00b204e9800998ecf8427e" },
|
||||
{ &EVP_md5, &MD5, "a", 1, "0cc175b9c0f1b6a831c399e269772661" },
|
||||
{ &EVP_md5, &MD5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72" },
|
||||
{ &EVP_md5, &MD5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0" },
|
||||
{ &EVP_md5, &MD5, "abcdefghijklmnopqrstuvwxyz", 1,
|
||||
"c3fcd3d76192e4007dfb496cca67e13b" },
|
||||
{ &EVP_md5, &MD5,
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
|
||||
"d174ab98d277d9f5a5611c2c9f419d9f" },
|
||||
{ &EVP_md5, &MD5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" },
|
||||
|
||||
/* SHA-1 tests, from RFC 3174. */
|
||||
{ &EVP_sha1, &SHA1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" },
|
||||
{ &EVP_sha1, &SHA1,
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"84983e441c3bd26ebaae4aa1f95129e5e54670f1" },
|
||||
{ &EVP_sha1, &SHA1, "a", 1000000,
|
||||
"34aa973cd4c4daa4f61eeb2bdbad27316534016f" },
|
||||
{ &EVP_sha1, &SHA1,
|
||||
"0123456701234567012345670123456701234567012345670123456701234567", 10,
|
||||
"dea356a2cddd90c7a7ecedc5ebb563934f460452" },
|
||||
|
||||
/* SHA-224 tests, from RFC 3874. */
|
||||
{ &EVP_sha224, &SHA224, "abc", 1,
|
||||
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" },
|
||||
{ &EVP_sha224, &SHA224,
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" },
|
||||
{ &EVP_sha224, &SHA224,
|
||||
"a", 1000000,
|
||||
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" },
|
||||
|
||||
/* SHA-256 tests, from NIST. */
|
||||
{ &EVP_sha256, &SHA256, "abc", 1,
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" },
|
||||
{ &EVP_sha256, &SHA256,
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" },
|
||||
|
||||
/* SHA-384 tests, from NIST. */
|
||||
{ &EVP_sha384, &SHA384, "abc", 1,
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
|
||||
"8086072ba1e7cc2358baeca134c825a7" },
|
||||
{ &EVP_sha384, &SHA384,
|
||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
|
||||
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
|
||||
"fcc7c71a557e2db966c3e9fa91746039" },
|
||||
|
||||
/* SHA-512 tests, from NIST. */
|
||||
{ &EVP_sha512, &SHA512, "abc", 1,
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
|
||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" },
|
||||
{ &EVP_sha512, &SHA512,
|
||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
|
||||
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
|
||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
|
||||
|
||||
/* MD5-SHA1 tests. */
|
||||
{ &EVP_md5_sha1, NULL, "abc", 1,
|
||||
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
|
||||
};
|
||||
|
||||
static int compare_digest(const TEST_VECTOR *test,
|
||||
const uint8_t *digest,
|
||||
size_t digest_len) {
|
||||
static const char kHexTable[] = "0123456789abcdef";
|
||||
size_t i;
|
||||
char digest_hex[2*EVP_MAX_MD_SIZE + 1];
|
||||
|
||||
for (i = 0; i < digest_len; i++) {
|
||||
digest_hex[2*i] = kHexTable[digest[i] >> 4];
|
||||
digest_hex[2*i + 1] = kHexTable[digest[i] & 0xf];
|
||||
}
|
||||
digest_hex[2*digest_len] = '\0';
|
||||
|
||||
if (strcmp(digest_hex, test->expected_hex) != 0) {
|
||||
fprintf(stderr, "%s(\"%s\" * %d) = %s; want %s\n",
|
||||
EVP_MD_name(test->md_func()), test->input, (int)test->repeat,
|
||||
digest_hex, test->expected_hex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_digest(const TEST_VECTOR *test) {
|
||||
int ret = 0;
|
||||
EVP_MD_CTX ctx;
|
||||
size_t i;
|
||||
uint8_t digest[EVP_MAX_MD_SIZE];
|
||||
unsigned digest_len;
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
|
||||
/* Test the input provided. */
|
||||
if (!EVP_DigestInit_ex(&ctx, test->md_func(), NULL)) {
|
||||
fprintf(stderr, "EVP_DigestInit_ex failed\n");
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; i < test->repeat; i++) {
|
||||
if (!EVP_DigestUpdate(&ctx, test->input, strlen(test->input))) {
|
||||
fprintf(stderr, "EVP_DigestUpdate failed\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) {
|
||||
fprintf(stderr, "EVP_DigestFinal_ex failed\n");
|
||||
goto done;
|
||||
}
|
||||
if (!compare_digest(test, digest, digest_len)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Test the input one character at a time. */
|
||||
if (!EVP_DigestInit_ex(&ctx, test->md_func(), NULL)) {
|
||||
fprintf(stderr, "EVP_DigestInit_ex failed\n");
|
||||
goto done;
|
||||
}
|
||||
if (!EVP_DigestUpdate(&ctx, NULL, 0)) {
|
||||
fprintf(stderr, "EVP_DigestUpdate failed\n");
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; i < test->repeat; i++) {
|
||||
const char *p;
|
||||
for (p = test->input; *p; p++) {
|
||||
if (!EVP_DigestUpdate(&ctx, p, 1)) {
|
||||
fprintf(stderr, "EVP_DigestUpdate failed\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) {
|
||||
fprintf(stderr, "EVP_DigestFinal_ex failed\n");
|
||||
goto done;
|
||||
}
|
||||
if (digest_len != EVP_MD_size(test->md_func())) {
|
||||
fprintf(stderr, "EVP_MD_size output incorrect\n");
|
||||
goto done;
|
||||
}
|
||||
if (!compare_digest(test, digest, digest_len)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Test the one-shot function. */
|
||||
if (test->one_shot_func && test->repeat == 1) {
|
||||
uint8_t *out = test->one_shot_func((const uint8_t *)test->input,
|
||||
strlen(test->input), digest);
|
||||
if (out != digest) {
|
||||
fprintf(stderr, "one_shot_func gave incorrect return\n");
|
||||
goto done;
|
||||
}
|
||||
if (!compare_digest(test, digest, EVP_MD_size(test->md_func()))) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Test the deprecated static buffer variant, until it's removed. */
|
||||
out = test->one_shot_func((const uint8_t *)test->input, strlen(test->input),
|
||||
NULL);
|
||||
if (!compare_digest(test, out, EVP_MD_size(test->md_func()))) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
done:
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
size_t i;
|
||||
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
for (i = 0; i < sizeof(kTestVectors) / sizeof(kTestVectors[0]); i++) {
|
||||
if (!test_digest(&kTestVectors[i])) {
|
||||
fprintf(stderr, "Test %d failed\n", (int)i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
+41
-1
@@ -193,9 +193,48 @@ static const EVP_MD sha512_md = {
|
||||
|
||||
const EVP_MD *EVP_sha512(void) { return &sha512_md; }
|
||||
|
||||
|
||||
typedef struct {
|
||||
MD5_CTX md5;
|
||||
SHA_CTX sha1;
|
||||
} MD5_SHA1_CTX;
|
||||
|
||||
static int md5_sha1_init(EVP_MD_CTX *md_ctx) {
|
||||
MD5_SHA1_CTX *ctx = md_ctx->md_data;
|
||||
return MD5_Init(&ctx->md5) && SHA1_Init(&ctx->sha1);
|
||||
}
|
||||
|
||||
static int md5_sha1_update(EVP_MD_CTX *md_ctx, const void *data, size_t count) {
|
||||
MD5_SHA1_CTX *ctx = md_ctx->md_data;
|
||||
return MD5_Update(&ctx->md5, data, count) && SHA1_Update(&ctx->sha1, data, count);
|
||||
}
|
||||
|
||||
static int md5_sha1_final(EVP_MD_CTX *md_ctx, unsigned char *out) {
|
||||
MD5_SHA1_CTX *ctx = md_ctx->md_data;
|
||||
if (!MD5_Final(out, &ctx->md5) ||
|
||||
!SHA1_Final(out + MD5_DIGEST_LENGTH, &ctx->sha1)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_MD md5_sha1_md = {
|
||||
NID_md5_sha1,
|
||||
MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
|
||||
0 /* flags */,
|
||||
md5_sha1_init,
|
||||
md5_sha1_update,
|
||||
md5_sha1_final,
|
||||
64 /* block size */,
|
||||
sizeof(MD5_SHA1_CTX),
|
||||
};
|
||||
|
||||
const EVP_MD *EVP_md5_sha1(void) { return &md5_sha1_md; }
|
||||
|
||||
|
||||
struct nid_to_digest {
|
||||
int nid;
|
||||
const EVP_MD *(*md_func)();
|
||||
const EVP_MD* (*md_func)(void);
|
||||
};
|
||||
|
||||
static const struct nid_to_digest nid_to_digest_mapping[] = {
|
||||
@@ -205,6 +244,7 @@ static const struct nid_to_digest nid_to_digest_mapping[] = {
|
||||
{ NID_sha256, EVP_sha256 },
|
||||
{ NID_sha384, EVP_sha384 },
|
||||
{ NID_sha512, EVP_sha512 },
|
||||
{ NID_md5_sha1, EVP_md5_sha1 },
|
||||
{ NID_dsaWithSHA, EVP_sha1 },
|
||||
{ NID_dsaWithSHA1, EVP_sha1 },
|
||||
{ NID_ecdsa_with_SHA1, EVP_sha1 },
|
||||
|
||||
+12
-1
@@ -243,13 +243,21 @@ int DSA_verify(int type, const uint8_t *digest, size_t digest_len,
|
||||
const uint8_t *sig, size_t sig_len, const DSA *dsa) {
|
||||
DSA_SIG *s = NULL;
|
||||
int ret = -1, valid;
|
||||
uint8_t *der = NULL;
|
||||
|
||||
s = DSA_SIG_new();
|
||||
if (s == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (d2i_DSA_SIG(&s, &sig, sig_len) == NULL) {
|
||||
const uint8_t *sigp = sig;
|
||||
if (d2i_DSA_SIG(&s, &sigp, sig_len) == NULL || sigp != sig + sig_len) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Ensure that the signature uses DER and doesn't have trailing garbage. */
|
||||
int der_len = i2d_DSA_SIG(s, &der);
|
||||
if (der_len < 0 || (size_t)der_len != sig_len || memcmp(sig, der, sig_len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -260,6 +268,9 @@ int DSA_verify(int type, const uint8_t *digest, size_t digest_len,
|
||||
ret = valid;
|
||||
|
||||
err:
|
||||
if (der != NULL) {
|
||||
OPENSSL_free(der);
|
||||
}
|
||||
if (s) {
|
||||
DSA_SIG_free(s);
|
||||
}
|
||||
|
||||
+91
-65
@@ -482,30 +482,35 @@ static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in,
|
||||
qsize = qbits / 8;
|
||||
|
||||
if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
|
||||
qsize != SHA256_DIGEST_LENGTH)
|
||||
qsize != SHA256_DIGEST_LENGTH) {
|
||||
/* invalid q size */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bits < 512)
|
||||
if (bits < 512) {
|
||||
bits = 512;
|
||||
}
|
||||
|
||||
bits = (bits + 63) / 64 * 64;
|
||||
|
||||
/* NB: seed_len == 0 is special case: copy generated seed to
|
||||
* seed_in if it is not NULL. */
|
||||
if (seed_len && (seed_len < (size_t)qsize))
|
||||
if (seed_len && (seed_len < (size_t)qsize)) {
|
||||
seed_in = NULL; /* seed buffer too small -- ignore */
|
||||
if (seed_len > (size_t)qsize)
|
||||
}
|
||||
if (seed_len > (size_t)qsize) {
|
||||
seed_len = qsize; /* App. 2.2 of FIPS PUB 186 allows larger SEED,
|
||||
* but our internal buffers are restricted to 160 bits*/
|
||||
if (seed_in != NULL)
|
||||
}
|
||||
if (seed_in != NULL) {
|
||||
memcpy(seed, seed_in, seed_len);
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if ((mont = BN_MONT_CTX_new()) == NULL)
|
||||
ctx = BN_CTX_new();
|
||||
mont = BN_MONT_CTX_new();
|
||||
if (ctx == NULL || mont == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
r0 = BN_CTX_get(ctx);
|
||||
@@ -517,20 +522,24 @@ static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in,
|
||||
p = BN_CTX_get(ctx);
|
||||
test = BN_CTX_get(ctx);
|
||||
|
||||
if (!BN_lshift(test, BN_value_one(), bits - 1))
|
||||
if (!BN_lshift(test, BN_value_one(), bits - 1)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (;;) /* find q */
|
||||
{
|
||||
/* Find q. */
|
||||
for (;;) {
|
||||
int seed_is_random;
|
||||
|
||||
/* step 1 */
|
||||
if (!BN_GENCB_call(cb, 0, m++))
|
||||
if (!BN_GENCB_call(cb, 0, m++)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!seed_len) {
|
||||
RAND_pseudo_bytes(seed, qsize);
|
||||
if (!RAND_bytes(seed, qsize)) {
|
||||
goto err;
|
||||
}
|
||||
seed_is_random = 1;
|
||||
} else {
|
||||
seed_is_random = 0;
|
||||
@@ -541,39 +550,43 @@ static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in,
|
||||
/* precompute "SEED + 1" for step 7: */
|
||||
for (i = qsize - 1; i < qsize; i--) {
|
||||
buf[i]++;
|
||||
if (buf[i] != 0)
|
||||
if (buf[i] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* step 2 */
|
||||
if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL))
|
||||
if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) ||
|
||||
!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL)) {
|
||||
goto err;
|
||||
if (!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL))
|
||||
goto err;
|
||||
for (i = 0; i < qsize; i++)
|
||||
}
|
||||
for (i = 0; i < qsize; i++) {
|
||||
md[i] ^= buf2[i];
|
||||
}
|
||||
|
||||
/* step 3 */
|
||||
md[0] |= 0x80;
|
||||
md[qsize - 1] |= 0x01;
|
||||
if (!BN_bin2bn(md, qsize, q))
|
||||
if (!BN_bin2bn(md, qsize, q)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 4 */
|
||||
r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, seed_is_random, cb);
|
||||
if (r > 0)
|
||||
if (r > 0) {
|
||||
break;
|
||||
if (r != 0)
|
||||
}
|
||||
if (r != 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* do a callback call */
|
||||
/* step 5 */
|
||||
}
|
||||
|
||||
if (!BN_GENCB_call(cb, 2, 0))
|
||||
goto err;
|
||||
if (!BN_GENCB_call(cb, 3, 0))
|
||||
if (!BN_GENCB_call(cb, 2, 0) || !BN_GENCB_call(cb, 3, 0)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 6 */
|
||||
counter = 0;
|
||||
@@ -582,8 +595,9 @@ static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in,
|
||||
n = (bits - 1) / 160;
|
||||
|
||||
for (;;) {
|
||||
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
|
||||
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 7 */
|
||||
BN_zero(W);
|
||||
@@ -592,48 +606,48 @@ static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in,
|
||||
/* obtain "SEED + offset + k" by incrementing: */
|
||||
for (i = qsize - 1; i < qsize; i--) {
|
||||
buf[i]++;
|
||||
if (buf[i] != 0)
|
||||
if (buf[i] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL))
|
||||
if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 8 */
|
||||
if (!BN_bin2bn(md, qsize, r0))
|
||||
goto err;
|
||||
if (!BN_lshift(r0, r0, (qsize << 3) * k))
|
||||
goto err;
|
||||
if (!BN_add(W, W, r0))
|
||||
if (!BN_bin2bn(md, qsize, r0) ||
|
||||
!BN_lshift(r0, r0, (qsize << 3) * k) ||
|
||||
!BN_add(W, W, r0)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* more of step 8 */
|
||||
if (!BN_mask_bits(W, bits - 1))
|
||||
goto err;
|
||||
if (!BN_copy(X, W))
|
||||
goto err;
|
||||
if (!BN_add(X, X, test))
|
||||
if (!BN_mask_bits(W, bits - 1) ||
|
||||
!BN_copy(X, W) ||
|
||||
!BN_add(X, X, test)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 9 */
|
||||
if (!BN_lshift1(r0, q))
|
||||
goto err;
|
||||
if (!BN_mod(c, X, r0, ctx))
|
||||
goto err;
|
||||
if (!BN_sub(r0, c, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_sub(p, X, r0))
|
||||
if (!BN_lshift1(r0, q) ||
|
||||
!BN_mod(c, X, r0, ctx) ||
|
||||
!BN_sub(r0, c, BN_value_one()) ||
|
||||
!BN_sub(p, X, r0)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 10 */
|
||||
if (BN_cmp(p, test) >= 0) {
|
||||
/* step 11 */
|
||||
r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
|
||||
if (r > 0)
|
||||
if (r > 0) {
|
||||
goto end; /* found it */
|
||||
if (r != 0)
|
||||
}
|
||||
if (r != 0) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* step 13 */
|
||||
@@ -641,50 +655,59 @@ static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in,
|
||||
/* "offset = offset + n + 1" */
|
||||
|
||||
/* step 14 */
|
||||
if (counter >= 4096)
|
||||
if (counter >= 4096) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
if (!BN_GENCB_call(cb, 2, 1))
|
||||
if (!BN_GENCB_call(cb, 2, 1)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We now need to generate g */
|
||||
/* Set r0=(p-1)/q */
|
||||
if (!BN_sub(test, p, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_div(r0, NULL, test, q, ctx))
|
||||
if (!BN_sub(test, p, BN_value_one()) ||
|
||||
!BN_div(r0, NULL, test, q, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_set_word(test, h))
|
||||
goto err;
|
||||
if (!BN_MONT_CTX_set(mont, p, ctx))
|
||||
if (!BN_set_word(test, h) ||
|
||||
!BN_MONT_CTX_set(mont, p, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* g=test^r0%p */
|
||||
if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
|
||||
if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) {
|
||||
goto err;
|
||||
if (!BN_is_one(g))
|
||||
}
|
||||
if (!BN_is_one(g)) {
|
||||
break;
|
||||
if (!BN_add(test, test, BN_value_one()))
|
||||
}
|
||||
if (!BN_add(test, test, BN_value_one())) {
|
||||
goto err;
|
||||
}
|
||||
h++;
|
||||
}
|
||||
|
||||
if (!BN_GENCB_call(cb, 3, 1))
|
||||
if (!BN_GENCB_call(cb, 3, 1)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
if (ok) {
|
||||
if (ret->p)
|
||||
if (ret->p) {
|
||||
BN_free(ret->p);
|
||||
if (ret->q)
|
||||
}
|
||||
if (ret->q) {
|
||||
BN_free(ret->q);
|
||||
if (ret->g)
|
||||
}
|
||||
if (ret->g) {
|
||||
BN_free(ret->g);
|
||||
}
|
||||
ret->p = BN_dup(p);
|
||||
ret->q = BN_dup(q);
|
||||
ret->g = BN_dup(g);
|
||||
@@ -692,10 +715,12 @@ err:
|
||||
ok = 0;
|
||||
goto err;
|
||||
}
|
||||
if (counter_ret != NULL)
|
||||
if (counter_ret != NULL) {
|
||||
*counter_ret = counter;
|
||||
if (h_ret != NULL)
|
||||
}
|
||||
if (h_ret != NULL) {
|
||||
*h_ret = h;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx) {
|
||||
@@ -703,8 +728,9 @@ err:
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
|
||||
if (mont != NULL)
|
||||
if (mont != NULL) {
|
||||
BN_MONT_CTX_free(mont);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -21,4 +21,11 @@ add_executable(
|
||||
example_mul.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
ec_test
|
||||
|
||||
ec_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(example_mul crypto)
|
||||
target_link_libraries(ec_test crypto)
|
||||
|
||||
@@ -247,7 +247,6 @@ EC_GROUP *ec_group_new(const EC_METHOD *meth) {
|
||||
ret->meth = meth;
|
||||
BN_init(&ret->order);
|
||||
BN_init(&ret->cofactor);
|
||||
ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
|
||||
|
||||
if (!meth->group_init(ret)) {
|
||||
OPENSSL_free(ret);
|
||||
@@ -457,7 +456,6 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) {
|
||||
}
|
||||
|
||||
dest->curve_name = src->curve_name;
|
||||
dest->asn1_form = src->asn1_form;
|
||||
|
||||
return dest->meth->group_copy(dest, src);
|
||||
}
|
||||
@@ -540,11 +538,6 @@ int EC_GROUP_get_degree(const EC_GROUP *group) {
|
||||
return group->meth->group_get_degree(group);
|
||||
}
|
||||
|
||||
void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
|
||||
point_conversion_form_t form) {
|
||||
group->asn1_form = form;
|
||||
}
|
||||
|
||||
int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
|
||||
if (group->meth->mul == 0) {
|
||||
/* use default */
|
||||
|
||||
+27
-11
@@ -341,28 +341,41 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **in, long len) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* TODO(fork): loading the public key is silly. Why not calculate it? */
|
||||
if (ret->pub_key) {
|
||||
EC_POINT_free(ret->pub_key);
|
||||
}
|
||||
ret->pub_key = EC_POINT_new(ret->group);
|
||||
if (ret->pub_key == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (priv_key->publicKey) {
|
||||
const uint8_t *pub_oct;
|
||||
size_t pub_oct_len;
|
||||
int pub_oct_len;
|
||||
|
||||
if (ret->pub_key) {
|
||||
EC_POINT_free(ret->pub_key);
|
||||
}
|
||||
ret->pub_key = EC_POINT_new(ret->group);
|
||||
if (ret->pub_key == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
|
||||
pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
|
||||
/* save the point conversion form */
|
||||
/* The first byte (the point conversion form) must be present. */
|
||||
if (pub_oct_len <= 0) {
|
||||
OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, EC_R_BUFFER_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
/* Save the point conversion form. */
|
||||
ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
|
||||
if (!EC_POINT_oct2point(ret->group, ret->pub_key, pub_oct, pub_oct_len,
|
||||
NULL)) {
|
||||
OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key, NULL, NULL,
|
||||
NULL)) {
|
||||
OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
/* Remember the original private-key-only encoding. */
|
||||
ret->enc_flag |= EC_PKEY_NO_PUBKEY;
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
@@ -373,6 +386,9 @@ err:
|
||||
EC_KEY_free(ret);
|
||||
}
|
||||
ret = NULL;
|
||||
if (a) {
|
||||
*a = ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv_key) {
|
||||
|
||||
@@ -295,9 +295,6 @@ point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) {
|
||||
|
||||
void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) {
|
||||
key->conv_form = cform;
|
||||
if (key->group != NULL) {
|
||||
EC_GROUP_set_point_conversion_form(key->group, cform);
|
||||
}
|
||||
}
|
||||
|
||||
int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) {
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ec_key.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static const uint8_t kECKeyWithoutPublic[] = {
|
||||
0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
|
||||
0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
|
||||
0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
|
||||
0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
|
||||
};
|
||||
|
||||
int test_d2i_ECPrivateKey(void) {
|
||||
int len, ret = 0;
|
||||
uint8_t *out = NULL, *outp;
|
||||
const uint8_t *inp;
|
||||
EC_KEY *key = NULL;
|
||||
BIGNUM *x = NULL, *y = NULL;
|
||||
const EC_POINT *public;
|
||||
char *x_hex = NULL, *y_hex = NULL;
|
||||
|
||||
inp = kECKeyWithoutPublic;
|
||||
key = d2i_ECPrivateKey(NULL, &inp, sizeof(kECKeyWithoutPublic));
|
||||
|
||||
if (key == NULL || inp != kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) {
|
||||
fprintf(stderr, "Failed to parse private key.\n");
|
||||
BIO_print_errors_fp(stderr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = i2d_ECPrivateKey(key, NULL);
|
||||
out = malloc(len);
|
||||
outp = out;
|
||||
if (len != i2d_ECPrivateKey(key, &outp)) {
|
||||
fprintf(stderr, "Failed to serialize private key.\n");
|
||||
BIO_print_errors_fp(stderr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (0 != memcmp(out, kECKeyWithoutPublic, len)) {
|
||||
fprintf(stderr, "Serialisation of key doesn't match original.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
public = EC_KEY_get0_public_key(key);
|
||||
if (public == NULL) {
|
||||
fprintf(stderr, "Public key missing.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
x = BN_new();
|
||||
y = BN_new();
|
||||
if (x == NULL || y == NULL) {
|
||||
goto out;
|
||||
}
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key), public, x, y,
|
||||
NULL)) {
|
||||
fprintf(stderr, "Failed to get public key in affine coordinates.\n");
|
||||
goto out;
|
||||
}
|
||||
x_hex = BN_bn2hex(x);
|
||||
y_hex = BN_bn2hex(y);
|
||||
if (0 != strcmp(x_hex, "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681") ||
|
||||
0 != strcmp(y_hex, "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88")) {
|
||||
fprintf(stderr, "Incorrect public key: %s %s\n", x_hex, y_hex);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
if (key != NULL) {
|
||||
EC_KEY_free(key);
|
||||
}
|
||||
if (out != NULL) {
|
||||
free(out);
|
||||
}
|
||||
if (x != NULL) {
|
||||
BN_free(x);
|
||||
}
|
||||
if (y != NULL) {
|
||||
BN_free(y);
|
||||
}
|
||||
if (x_hex != NULL) {
|
||||
OPENSSL_free(x_hex);
|
||||
}
|
||||
if (y_hex != NULL) {
|
||||
OPENSSL_free(y_hex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
if (!test_d2i_ECPrivateKey()) {
|
||||
fprintf(stderr, "failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -199,7 +199,6 @@ struct ec_group_st {
|
||||
BIGNUM order, cofactor;
|
||||
|
||||
int curve_name; /* optional NID for named curve */
|
||||
point_conversion_form_t asn1_form;
|
||||
|
||||
struct ec_pre_comp_st *pre_comp;
|
||||
|
||||
|
||||
+26
-45
@@ -81,11 +81,10 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int used_ctx = 0;
|
||||
BIGNUM *x, *y;
|
||||
size_t field_len, i, skip;
|
||||
size_t field_len, i;
|
||||
|
||||
if ((form != POINT_CONVERSION_COMPRESSED) &&
|
||||
(form != POINT_CONVERSION_UNCOMPRESSED) &&
|
||||
(form != POINT_CONVERSION_HYBRID)) {
|
||||
(form != POINT_CONVERSION_UNCOMPRESSED)) {
|
||||
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, EC_R_INVALID_FORM);
|
||||
goto err;
|
||||
}
|
||||
@@ -117,58 +116,43 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
if (ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
used_ctx = 1;
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
if (y == NULL)
|
||||
if (y == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((form == POINT_CONVERSION_COMPRESSED ||
|
||||
form == POINT_CONVERSION_HYBRID) &&
|
||||
BN_is_odd(y))
|
||||
if ((form == POINT_CONVERSION_COMPRESSED) &&
|
||||
BN_is_odd(y)) {
|
||||
buf[0] = form + 1;
|
||||
else
|
||||
} else {
|
||||
buf[0] = form;
|
||||
|
||||
}
|
||||
i = 1;
|
||||
|
||||
skip = field_len - BN_num_bytes(x);
|
||||
if (skip > field_len) {
|
||||
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
while (skip > 0) {
|
||||
buf[i++] = 0;
|
||||
skip--;
|
||||
}
|
||||
skip = BN_bn2bin(x, buf + i);
|
||||
i += skip;
|
||||
if (i != 1 + field_len) {
|
||||
if (!BN_bn2bin_padded(buf + i, field_len, x)) {
|
||||
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
i += field_len;
|
||||
|
||||
if (form == POINT_CONVERSION_UNCOMPRESSED ||
|
||||
form == POINT_CONVERSION_HYBRID) {
|
||||
skip = field_len - BN_num_bytes(y);
|
||||
if (skip > field_len) {
|
||||
if (form == POINT_CONVERSION_UNCOMPRESSED) {
|
||||
if (!BN_bn2bin_padded(buf + i, field_len, y)) {
|
||||
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
while (skip > 0) {
|
||||
buf[i++] = 0;
|
||||
skip--;
|
||||
}
|
||||
skip = BN_bn2bin(y, buf + i);
|
||||
i += skip;
|
||||
i += field_len;
|
||||
}
|
||||
|
||||
if (i != ret) {
|
||||
@@ -177,17 +161,21 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
|
||||
}
|
||||
}
|
||||
|
||||
if (used_ctx)
|
||||
if (used_ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
}
|
||||
if (new_ctx != NULL) {
|
||||
BN_CTX_free(new_ctx);
|
||||
}
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (used_ctx)
|
||||
if (used_ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
}
|
||||
if (new_ctx != NULL) {
|
||||
BN_CTX_free(new_ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -210,8 +198,7 @@ static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
|
||||
y_bit = form & 1;
|
||||
form = form & ~1U;
|
||||
if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) &&
|
||||
(form != POINT_CONVERSION_UNCOMPRESSED) &&
|
||||
(form != POINT_CONVERSION_HYBRID)) {
|
||||
(form != POINT_CONVERSION_UNCOMPRESSED)) {
|
||||
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
@@ -267,12 +254,6 @@ static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
|
||||
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
if (form == POINT_CONVERSION_HYBRID) {
|
||||
if (y_bit != BN_is_odd(y)) {
|
||||
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
|
||||
goto err;
|
||||
|
||||
+3
-2
@@ -1338,9 +1338,10 @@ err:
|
||||
}
|
||||
if (prod_Z != NULL) {
|
||||
for (i = 0; i < num; i++) {
|
||||
if (prod_Z[i] != NULL) {
|
||||
BN_clear_free(prod_Z[i]);
|
||||
if (prod_Z[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
BN_clear_free(prod_Z[i]);
|
||||
}
|
||||
OPENSSL_free(prod_Z);
|
||||
}
|
||||
|
||||
+7
-4
@@ -389,13 +389,16 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
sizeof wNAF[0]); /* includes space for pivot */
|
||||
val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
|
||||
|
||||
/* Ensure wNAF is initialised in case we end up going to err. */
|
||||
if (wNAF) {
|
||||
wNAF[0] = NULL; /* preliminary pivot */
|
||||
}
|
||||
|
||||
if (!wsize || !wNAF_len || !wNAF || !val_sub) {
|
||||
OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
wNAF[0] = NULL; /* preliminary pivot */
|
||||
|
||||
/* num_val will be the total number of temporarily precomputed points */
|
||||
num_val = 0;
|
||||
|
||||
@@ -443,8 +446,8 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
* as the wNAF belonging to the generator,
|
||||
* so wNAF splitting will not buy us anything. */
|
||||
|
||||
numblocks = 1;
|
||||
totalnum = num + 1; /* don't use wNAF splitting */
|
||||
numblocks = 1; /* don't use wNAF splitting */
|
||||
totalnum = num + numblocks;
|
||||
wNAF[num] = tmp_wNAF;
|
||||
wNAF[num + 1] = NULL;
|
||||
wNAF_len[num] = tmp_len;
|
||||
|
||||
+3
-9
@@ -81,7 +81,7 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
|
||||
const BIGNUM *priv;
|
||||
const EC_GROUP *group;
|
||||
int ret = -1;
|
||||
size_t buflen, len;
|
||||
size_t buflen;
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL) {
|
||||
@@ -116,20 +116,14 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
|
||||
}
|
||||
|
||||
buflen = (EC_GROUP_get_degree(group) + 7) / 8;
|
||||
len = BN_num_bytes(x);
|
||||
if (len > buflen) {
|
||||
OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
buf = OPENSSL_malloc(buflen);
|
||||
if (buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(buf, 0, buflen - len);
|
||||
if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) {
|
||||
OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ERR_R_BN_LIB);
|
||||
if (!BN_bn2bin_padded(buf, buflen, x)) {
|
||||
OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
+14
-1
@@ -74,18 +74,31 @@ int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
|
||||
const uint8_t *sig, size_t sig_len, EC_KEY *eckey) {
|
||||
ECDSA_SIG *s;
|
||||
int ret = 0;
|
||||
uint8_t *der = NULL;
|
||||
|
||||
if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
|
||||
return eckey->ecdsa_meth->verify(digest, digest_len, sig, sig_len, eckey);
|
||||
}
|
||||
|
||||
s = ECDSA_SIG_new();
|
||||
if (s == NULL || d2i_ECDSA_SIG(&s, &sig, sig_len) == NULL) {
|
||||
const uint8_t *sigp = sig;
|
||||
if (s == NULL || d2i_ECDSA_SIG(&s, &sigp, sig_len) == NULL ||
|
||||
sigp != sig + sig_len) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Ensure that the signature uses DER and doesn't have trailing garbage. */
|
||||
const int der_len = i2d_ECDSA_SIG(s, &der);
|
||||
if (der_len < 0 || (size_t) der_len != sig_len || memcmp(sig, der, sig_len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ECDSA_do_verify(digest, digest_len, s, eckey);
|
||||
|
||||
err:
|
||||
if (der != NULL) {
|
||||
OPENSSL_free(der);
|
||||
}
|
||||
if (s != NULL) {
|
||||
ECDSA_SIG_free(s);
|
||||
}
|
||||
|
||||
+31
-14
@@ -66,21 +66,27 @@ int test_builtin(BIO *out) {
|
||||
size_t n = 0;
|
||||
EC_KEY *eckey = NULL, *wrong_eckey = NULL;
|
||||
EC_GROUP *group;
|
||||
BIGNUM *order = NULL;
|
||||
ECDSA_SIG *ecdsa_sig = NULL;
|
||||
unsigned char digest[20], wrong_digest[20];
|
||||
unsigned char *signature = NULL;
|
||||
const unsigned char *sig_ptr;
|
||||
unsigned char *sig_ptr2;
|
||||
unsigned char *raw_buf = NULL;
|
||||
unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len;
|
||||
unsigned int sig_len, r_len, s_len, bn_len, buf_len;
|
||||
int nid, ret = 0;
|
||||
|
||||
/* fill digest values with some random data */
|
||||
if (!RAND_pseudo_bytes(digest, 20) || !RAND_pseudo_bytes(wrong_digest, 20)) {
|
||||
if (!RAND_bytes(digest, 20) || !RAND_bytes(wrong_digest, 20)) {
|
||||
BIO_printf(out, "ERROR: unable to get random data\n");
|
||||
goto builtin_err;
|
||||
}
|
||||
|
||||
order = BN_new();
|
||||
if (order == NULL) {
|
||||
goto builtin_err;
|
||||
}
|
||||
|
||||
/* create and verify a ecdsa signature with every availble curve
|
||||
* (with ) */
|
||||
BIO_printf(out,
|
||||
@@ -108,8 +114,10 @@ int test_builtin(BIO *out) {
|
||||
goto builtin_err;
|
||||
}
|
||||
EC_GROUP_free(group);
|
||||
degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey));
|
||||
if (degree < 160) {
|
||||
if (!EC_GROUP_get_order(EC_KEY_get0_group(eckey), order, NULL)) {
|
||||
goto builtin_err;
|
||||
}
|
||||
if (BN_num_bits(order) < 160) {
|
||||
/* Too small to test. */
|
||||
EC_KEY_free(eckey);
|
||||
eckey = NULL;
|
||||
@@ -203,20 +211,21 @@ int test_builtin(BIO *out) {
|
||||
/* Store the two BIGNUMs in raw_buf. */
|
||||
r_len = BN_num_bytes(ecdsa_sig->r);
|
||||
s_len = BN_num_bytes(ecdsa_sig->s);
|
||||
bn_len = (degree + 7) / 8;
|
||||
bn_len = BN_num_bytes(order);
|
||||
if (r_len > bn_len || s_len > bn_len) {
|
||||
BIO_printf(out, " failed\n");
|
||||
goto builtin_err;
|
||||
}
|
||||
buf_len = 2 * bn_len;
|
||||
raw_buf = OPENSSL_malloc(buf_len);
|
||||
raw_buf = OPENSSL_malloc(2 * bn_len);
|
||||
if (raw_buf == NULL) {
|
||||
goto builtin_err;
|
||||
}
|
||||
/* Pad the bignums with leading zeroes. */
|
||||
memset(raw_buf, 0, buf_len);
|
||||
BN_bn2bin(ecdsa_sig->r, raw_buf + bn_len - r_len);
|
||||
BN_bn2bin(ecdsa_sig->s, raw_buf + buf_len - s_len);
|
||||
if (!BN_bn2bin_padded(raw_buf, bn_len, ecdsa_sig->r) ||
|
||||
!BN_bn2bin_padded(raw_buf + bn_len, bn_len, ecdsa_sig->s)) {
|
||||
goto builtin_err;
|
||||
}
|
||||
|
||||
/* Modify a single byte in the buffer. */
|
||||
offset = raw_buf[10] % buf_len;
|
||||
@@ -268,16 +277,24 @@ int test_builtin(BIO *out) {
|
||||
|
||||
ret = 1;
|
||||
builtin_err:
|
||||
if (eckey)
|
||||
if (eckey) {
|
||||
EC_KEY_free(eckey);
|
||||
if (wrong_eckey)
|
||||
}
|
||||
if (order) {
|
||||
BN_free(order);
|
||||
}
|
||||
if (wrong_eckey) {
|
||||
EC_KEY_free(wrong_eckey);
|
||||
if (ecdsa_sig)
|
||||
}
|
||||
if (ecdsa_sig) {
|
||||
ECDSA_SIG_free(ecdsa_sig);
|
||||
if (signature)
|
||||
}
|
||||
if (signature) {
|
||||
OPENSSL_free(signature);
|
||||
if (raw_buf)
|
||||
}
|
||||
if (raw_buf) {
|
||||
OPENSSL_free(raw_buf);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+35
-10
@@ -175,12 +175,12 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line,
|
||||
uint32_t ret;
|
||||
|
||||
state = err_get_state();
|
||||
|
||||
if (state->bottom == state->top) {
|
||||
if (state == NULL || state->bottom == state->top) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (top) {
|
||||
assert(!inc);
|
||||
/* last error */
|
||||
i = state->top;
|
||||
} else {
|
||||
@@ -211,14 +211,21 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line,
|
||||
if (flags != NULL) {
|
||||
*flags = error->flags & ERR_FLAG_PUBLIC_MASK;
|
||||
}
|
||||
if (error->flags & ERR_FLAG_MALLOCED) {
|
||||
if (state->to_free) {
|
||||
OPENSSL_free(state->to_free);
|
||||
/* If this error is being removed, take ownership of data from
|
||||
* the error. The semantics are such that the caller doesn't
|
||||
* take ownership either. Instead the error system takes
|
||||
* ownership and retains it until the next call that affects the
|
||||
* error queue. */
|
||||
if (inc) {
|
||||
if (error->flags & ERR_FLAG_MALLOCED) {
|
||||
if (state->to_free) {
|
||||
OPENSSL_free(state->to_free);
|
||||
}
|
||||
state->to_free = error->data;
|
||||
}
|
||||
state->to_free = error->data;
|
||||
error->data = NULL;
|
||||
error->flags = 0;
|
||||
}
|
||||
error->data = NULL;
|
||||
error->flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,6 +281,10 @@ void ERR_clear_error(void) {
|
||||
ERR_STATE *const state = err_get_state();
|
||||
unsigned i;
|
||||
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ERR_NUM_ERRORS; i++) {
|
||||
err_clear(&state->errors[i]);
|
||||
}
|
||||
@@ -473,7 +484,10 @@ static void err_set_error_data(char *data, int flags) {
|
||||
ERR_STATE *const state = err_get_state();
|
||||
struct err_error_st *error;
|
||||
|
||||
if (state->top == state->bottom) {
|
||||
if (state == NULL || state->top == state->bottom) {
|
||||
if (flags & ERR_FLAG_MALLOCED) {
|
||||
OPENSSL_free(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -489,6 +503,10 @@ void ERR_put_error(int library, int func, int reason, const char *file,
|
||||
ERR_STATE *const state = err_get_state();
|
||||
struct err_error_st *error;
|
||||
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (library == ERR_LIB_SYS && reason == 0) {
|
||||
#if defined(WIN32)
|
||||
reason = GetLastError();
|
||||
@@ -589,7 +607,7 @@ void ERR_add_error_dataf(const char *format, ...) {
|
||||
int ERR_set_mark(void) {
|
||||
ERR_STATE *const state = err_get_state();
|
||||
|
||||
if (state->bottom == state->top) {
|
||||
if (state == NULL || state->bottom == state->top) {
|
||||
return 0;
|
||||
}
|
||||
state->errors[state->top].flags |= ERR_FLAG_MARK;
|
||||
@@ -600,6 +618,10 @@ int ERR_pop_to_mark(void) {
|
||||
ERR_STATE *const state = err_get_state();
|
||||
struct err_error_st *error;
|
||||
|
||||
if (state == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (state->bottom != state->top) {
|
||||
error = &state->errors[state->top];
|
||||
|
||||
@@ -656,6 +678,7 @@ static const char *const kLibraryNames[ERR_NUM_LIBS] = {
|
||||
"Digest functions", /* ERR_LIB_DIGEST */
|
||||
"Cipher functions", /* ERR_LIB_CIPHER */
|
||||
"User defined functions", /* ERR_LIB_USER */
|
||||
"HKDF functions", /* ERR_LIB_HKDF */
|
||||
};
|
||||
|
||||
#define NUM_SYS_ERRNOS 127
|
||||
@@ -700,6 +723,7 @@ extern const ERR_STRING_DATA ECDSA_error_string_data[];
|
||||
extern const ERR_STRING_DATA EC_error_string_data[];
|
||||
extern const ERR_STRING_DATA ENGINE_error_string_data[];
|
||||
extern const ERR_STRING_DATA EVP_error_string_data[];
|
||||
extern const ERR_STRING_DATA HKDF_error_string_data[];
|
||||
extern const ERR_STRING_DATA OBJ_error_string_data[];
|
||||
extern const ERR_STRING_DATA PEM_error_string_data[];
|
||||
extern const ERR_STRING_DATA PKCS8_error_string_data[];
|
||||
@@ -754,6 +778,7 @@ static void err_load_strings(void) {
|
||||
ERR_load_strings(EC_error_string_data);
|
||||
ERR_load_strings(ENGINE_error_string_data);
|
||||
ERR_load_strings(EVP_error_string_data);
|
||||
ERR_load_strings(HKDF_error_string_data);
|
||||
ERR_load_strings(OBJ_error_string_data);
|
||||
ERR_load_strings(PEM_error_string_data);
|
||||
ERR_load_strings(PKCS8_error_string_data);
|
||||
|
||||
@@ -231,6 +231,11 @@ static ERR_STATE *err_get_state(void) {
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_ERR);
|
||||
}
|
||||
|
||||
if (state_hash == NULL) {
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = lh_ERR_STATE_retrieve(state_hash, &pattern);
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
|
||||
if (state != NULL) {
|
||||
|
||||
+20
-5
@@ -23,11 +23,15 @@ static int test_overflow(void) {
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ERR_NUM_ERRORS*2; i++) {
|
||||
ERR_put_error(1, 2, 3, "test", 1);
|
||||
ERR_put_error(1, 2, i+1, "test", 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < ERR_NUM_ERRORS - 1; i++) {
|
||||
if (ERR_get_error() == 0) {
|
||||
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. */
|
||||
if (err == 0 || ERR_GET_REASON(err) != i + ERR_NUM_ERRORS + 2) {
|
||||
fprintf(stderr, "ERR_get_error failed at %u\n", i);
|
||||
return 0;
|
||||
}
|
||||
@@ -42,9 +46,9 @@ static int test_overflow(void) {
|
||||
}
|
||||
|
||||
static int test_put_error(void) {
|
||||
uint32_t packed_error;
|
||||
int line, flags;
|
||||
const char *file, *data;
|
||||
uint32_t peeked_packed_error, packed_error;
|
||||
int peeked_line, line, peeked_flags, flags;
|
||||
const char *peeked_file, *file, *peeked_data, *data;
|
||||
|
||||
if (ERR_get_error() != 0) {
|
||||
fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
|
||||
@@ -54,7 +58,18 @@ static int test_put_error(void) {
|
||||
ERR_put_error(1, 2, 3, "test", 4);
|
||||
ERR_add_error_data(1, "testing");
|
||||
|
||||
peeked_packed_error = ERR_peek_error_line_data(&peeked_file, &peeked_line,
|
||||
&peeked_data, &peeked_flags);
|
||||
packed_error = ERR_get_error_line_data(&file, &line, &data, &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 0;
|
||||
}
|
||||
|
||||
if (strcmp(file, "test") != 0 ||
|
||||
line != 4 ||
|
||||
(flags & ERR_FLAG_STRING) == 0 ||
|
||||
|
||||
@@ -124,6 +124,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;
|
||||
|
||||
+16
-1
@@ -124,7 +124,10 @@ static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) {
|
||||
|
||||
if (pmeth->init) {
|
||||
if (pmeth->init(ret) <= 0) {
|
||||
EVP_PKEY_CTX_free(ret);
|
||||
if (pkey) {
|
||||
EVP_PKEY_free(ret->pkey);
|
||||
}
|
||||
OPENSSL_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -176,17 +179,25 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) {
|
||||
|
||||
if (pctx->pkey) {
|
||||
rctx->pkey = EVP_PKEY_dup(pctx->pkey);
|
||||
if (rctx->pkey == NULL) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (pctx->peerkey) {
|
||||
rctx->peerkey = EVP_PKEY_dup(pctx->peerkey);
|
||||
if (rctx->peerkey == NULL) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (pctx->pmeth->copy(rctx, pctx) > 0) {
|
||||
return rctx;
|
||||
}
|
||||
|
||||
err:
|
||||
EVP_PKEY_CTX_free(rctx);
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_dup, ERR_LIB_EVP);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -485,6 +496,10 @@ int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) {
|
||||
|
||||
if (!*ppkey) {
|
||||
*ppkey = EVP_PKEY_new();
|
||||
if (!*ppkey) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_PKEY_keygen, ERR_LIB_EVP);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctx->pmeth->keygen(ctx, *ppkey)) {
|
||||
|
||||
@@ -20,6 +20,7 @@ const ERR_STRING_DATA EVP_error_string_data[] = {
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestSignAlgorithm, 0), "EVP_DigestSignAlgorithm"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestVerifyInitFromAlgorithm, 0), "EVP_DigestVerifyInitFromAlgorithm"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_ctrl, 0), "EVP_PKEY_CTX_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_dup, 0), "EVP_PKEY_CTX_dup"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_copy_parameters, 0), "EVP_PKEY_copy_parameters"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt, 0), "EVP_PKEY_decrypt"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt_init, 0), "EVP_PKEY_decrypt_init"},
|
||||
|
||||
@@ -229,6 +229,20 @@ static const uint8_t kExampleECKeyDER[] = {
|
||||
0xc1,
|
||||
};
|
||||
|
||||
/* kExampleBadECKeyDER is a sample EC private key encoded as an ECPrivateKey
|
||||
* structure. The private key is equal to the order and will fail to import */
|
||||
static const uint8_t kExampleBadECKeyDER[] = {
|
||||
0x30, 0x66, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48,
|
||||
0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03,
|
||||
0x01, 0x07, 0x04, 0x4C, 0x30, 0x4A, 0x02, 0x01, 0x01, 0x04, 0x20, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3,
|
||||
0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0xA1, 0x23, 0x03, 0x21, 0x00,
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
|
||||
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
|
||||
};
|
||||
|
||||
static EVP_PKEY *load_example_rsa_key(void) {
|
||||
EVP_PKEY *ret = NULL;
|
||||
const uint8_t *derp = kExampleRSAKeyDER;
|
||||
@@ -539,6 +553,40 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Tests loading a bad key in PKCS8 format */
|
||||
static int test_EVP_PKCS82PKEY(void) {
|
||||
int ret = 0;
|
||||
const uint8_t *derp = kExampleBadECKeyDER;
|
||||
PKCS8_PRIV_KEY_INFO *p8inf = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
||||
p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER));
|
||||
|
||||
if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) {
|
||||
fprintf(stderr, "Failed to parse key\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
pkey = EVP_PKCS82PKEY(p8inf);
|
||||
if (pkey) {
|
||||
fprintf(stderr, "Imported invalid EC key\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
done:
|
||||
if (p8inf != NULL) {
|
||||
PKCS8_PRIV_KEY_INFO_free(p8inf);
|
||||
}
|
||||
|
||||
if (pkey != NULL) {
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
@@ -581,6 +629,11 @@ int main(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!test_EVP_PKCS82PKEY()) {
|
||||
fprintf(stderr, "test_EVP_PKCS82PKEY failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,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);
|
||||
|
||||
@@ -121,7 +127,6 @@ struct evp_pkey_asn1_method_st {
|
||||
|
||||
|
||||
void (*pkey_free)(EVP_PKEY *pkey);
|
||||
int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
|
||||
|
||||
/* Legacy functions for old PEM */
|
||||
|
||||
|
||||
+1
-12
@@ -538,17 +538,6 @@ static int old_ec_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
|
||||
return i2d_ECPrivateKey(pkey->pkey.ec, pder);
|
||||
}
|
||||
|
||||
static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) {
|
||||
switch (op) {
|
||||
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
||||
*(int *)arg2 = NID_sha1;
|
||||
return 2;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
|
||||
EVP_PKEY_EC,
|
||||
EVP_PKEY_EC,
|
||||
@@ -566,6 +555,7 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
|
||||
eckey_priv_print,
|
||||
|
||||
eckey_opaque,
|
||||
0 /* pkey_supports_digest */,
|
||||
|
||||
int_ec_size,
|
||||
ec_bits,
|
||||
@@ -579,7 +569,6 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
|
||||
0,
|
||||
|
||||
int_ec_free,
|
||||
ec_pkey_ctrl,
|
||||
old_ec_priv_decode,
|
||||
old_ec_priv_encode
|
||||
};
|
||||
|
||||
@@ -109,6 +109,10 @@ static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
|
||||
static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx) {
|
||||
HMAC_PKEY_CTX *hctx = ctx->data;
|
||||
|
||||
if (hctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
HMAC_CTX_cleanup(&hctx->ctx);
|
||||
if (hctx->ktmp.data) {
|
||||
if (hctx->ktmp.length) {
|
||||
|
||||
@@ -75,26 +75,15 @@ static void hmac_key_free(EVP_PKEY *pkey) {
|
||||
}
|
||||
}
|
||||
|
||||
static int hmac_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) {
|
||||
switch (op) {
|
||||
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
||||
*(int *)arg2 = NID_sha1;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = {
|
||||
EVP_PKEY_HMAC, EVP_PKEY_HMAC, 0 /* flags */,
|
||||
"HMAC", "OpenSSL HMAC method", 0 /* pub_decode */,
|
||||
0 /* pub_encode */, 0 /* pub_cmp */, 0 /* pub_print */,
|
||||
0 /*priv_decode */, 0 /* priv_encode */, 0 /* priv_print */,
|
||||
0 /* pkey_opaque */,
|
||||
0 /* pkey_opaque */, 0 /* pkey_supports_digest */,
|
||||
hmac_size, 0 /* pkey_bits */, 0 /* param_decode */,
|
||||
0 /* param_encode*/, 0 /* param_missing*/, 0 /* param_copy*/,
|
||||
0 /* param_cmp*/, 0 /* param_print*/, 0 /* sig_print*/,
|
||||
hmac_key_free, hmac_pkey_ctrl, 0 /* old_priv_decode */,
|
||||
hmac_key_free, 0 /* old_priv_decode */,
|
||||
0 /* old_priv_encode */
|
||||
};
|
||||
|
||||
+5
-19
@@ -153,6 +153,10 @@ static int rsa_opaque(const EVP_PKEY *pkey) {
|
||||
return RSA_is_opaque(pkey->pkey.rsa);
|
||||
}
|
||||
|
||||
static int rsa_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
|
||||
return RSA_supports_digest(pkey->pkey.rsa, md);
|
||||
}
|
||||
|
||||
static int int_rsa_size(const EVP_PKEY *pkey) {
|
||||
return RSA_size(pkey->pkey.rsa);
|
||||
}
|
||||
@@ -409,24 +413,6 @@ static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) {
|
||||
X509_ALGOR *alg = NULL;
|
||||
switch (op) {
|
||||
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
||||
*(int *)arg2 = NID_sha1;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (alg) {
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int old_rsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder,
|
||||
int derlen) {
|
||||
RSA *rsa = d2i_RSAPrivateKey(NULL, pder, derlen);
|
||||
@@ -701,6 +687,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
|
||||
rsa_priv_print,
|
||||
|
||||
rsa_opaque,
|
||||
rsa_supports_digest,
|
||||
|
||||
int_rsa_size,
|
||||
rsa_bits,
|
||||
@@ -709,7 +696,6 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
|
||||
|
||||
rsa_sig_print,
|
||||
int_rsa_free,
|
||||
rsa_pkey_ctrl,
|
||||
|
||||
old_rsa_priv_decode,
|
||||
old_rsa_priv_encode,
|
||||
|
||||
@@ -151,7 +151,7 @@ static uint32_t class_hash(const EX_CLASS_ITEM *a) {
|
||||
return a->class_value;
|
||||
}
|
||||
|
||||
/* class_cmp is a comparision function for an LHASH of |EX_CLASS_ITEM|
|
||||
/* class_cmp is a comparison function for an LHASH of |EX_CLASS_ITEM|
|
||||
* structures. */
|
||||
static int class_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b) {
|
||||
return a->class_value - b->class_value;
|
||||
@@ -193,8 +193,10 @@ static LHASH_OF(EX_CLASS_ITEM) *get_classes(void) {
|
||||
static void cleanup(void) {
|
||||
LHASH_OF(EX_CLASS_ITEM) *classes = get_classes();
|
||||
|
||||
lh_EX_CLASS_ITEM_doall(classes, class_free);
|
||||
lh_EX_CLASS_ITEM_free(classes);
|
||||
if (classes != NULL) {
|
||||
lh_EX_CLASS_ITEM_doall(classes, class_free);
|
||||
lh_EX_CLASS_ITEM_free(classes);
|
||||
}
|
||||
|
||||
global_classes = NULL;
|
||||
}
|
||||
@@ -204,6 +206,10 @@ static EX_CLASS_ITEM *get_class(int class_value) {
|
||||
EX_CLASS_ITEM template, *class_item;
|
||||
int ok = 0;
|
||||
|
||||
if (classes == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
|
||||
template.class_value = class_value;
|
||||
class_item = lh_EX_CLASS_ITEM_retrieve(classes, &template);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
include_directories(. .. ../../include)
|
||||
|
||||
add_library(
|
||||
hkdf
|
||||
|
||||
OBJECT
|
||||
|
||||
hkdf.c
|
||||
hkdf_error.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
hkdf_test
|
||||
|
||||
hkdf_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(hkdf_test crypto)
|
||||
@@ -0,0 +1,88 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/hkdf.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
|
||||
int HKDF(uint8_t *out_key, size_t out_len,
|
||||
const EVP_MD *digest,
|
||||
const uint8_t *secret, size_t secret_len,
|
||||
const uint8_t *salt, size_t salt_len,
|
||||
const uint8_t *info, size_t info_len) {
|
||||
/* https://tools.ietf.org/html/rfc5869#section-2.2 */
|
||||
const size_t digest_len = EVP_MD_size(digest);
|
||||
uint8_t prk[EVP_MAX_MD_SIZE], previous[EVP_MAX_MD_SIZE];
|
||||
size_t n, done = 0;
|
||||
unsigned i, prk_len;
|
||||
int ret = 0;
|
||||
HMAC_CTX hmac;
|
||||
|
||||
/* If salt is not given, HashLength zeros are used. However, HMAC does that
|
||||
* internally already so we can ignore it.*/
|
||||
|
||||
/* Expand key material to desired length. */
|
||||
n = (out_len + digest_len - 1) / digest_len;
|
||||
if (out_len + digest_len < out_len || n > 255) {
|
||||
OPENSSL_PUT_ERROR(HKDF, HKDF, HKDF_R_OUTPUT_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HMAC_CTX_init(&hmac);
|
||||
|
||||
/* Extract input keying material into pseudorandom key |prk|. */
|
||||
if (HMAC(digest, salt, salt_len, secret, secret_len, prk, &prk_len) == NULL) {
|
||||
goto out;
|
||||
}
|
||||
assert(prk_len == digest_len);
|
||||
|
||||
if (!HMAC_Init_ex(&hmac, prk, prk_len, digest, NULL)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
uint8_t ctr = i + 1;
|
||||
size_t todo;
|
||||
|
||||
if (i != 0 && (!HMAC_Init_ex(&hmac, NULL, 0, NULL, NULL) ||
|
||||
!HMAC_Update(&hmac, previous, digest_len))) {
|
||||
goto out;
|
||||
}
|
||||
if (!HMAC_Update(&hmac, info, info_len) ||
|
||||
!HMAC_Update(&hmac, &ctr, 1) ||
|
||||
!HMAC_Final(&hmac, previous, NULL)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
todo = digest_len;
|
||||
if (done + todo > out_len) {
|
||||
todo = out_len - done;
|
||||
}
|
||||
memcpy(out_key + done, previous, todo);
|
||||
done += todo;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
HMAC_CTX_cleanup(&hmac);
|
||||
if (ret != 1) {
|
||||
OPENSSL_PUT_ERROR(HKDF, HKDF, ERR_R_HMAC_LIB);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <openssl/hkdf.h>
|
||||
|
||||
const ERR_STRING_DATA HKDF_error_string_data[] = {
|
||||
{ERR_PACK(ERR_LIB_HKDF, HKDF_F_HKDF, 0), "HKDF"},
|
||||
{ERR_PACK(ERR_LIB_HKDF, 0, HKDF_R_OUTPUT_TOO_LARGE), "OUTPUT_TOO_LARGE"},
|
||||
{0, NULL},
|
||||
};
|
||||
@@ -0,0 +1,239 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hkdf.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
const EVP_MD *(*md_func)(void);
|
||||
const uint8_t ikm[80];
|
||||
const size_t ikm_len;
|
||||
const uint8_t salt[80];
|
||||
const size_t salt_len;
|
||||
const uint8_t info[80];
|
||||
const size_t info_len;
|
||||
const size_t out_len;
|
||||
const uint8_t out[82];
|
||||
} hkdf_test_vector_t;
|
||||
|
||||
/* These test vectors are from RFC 5869. */
|
||||
static const hkdf_test_vector_t kTests[] = {
|
||||
{
|
||||
EVP_sha256,
|
||||
{
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
}, 22,
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
||||
0x0c,
|
||||
}, 13,
|
||||
{
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
|
||||
}, 10,
|
||||
42, {
|
||||
0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64,
|
||||
0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
|
||||
0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08,
|
||||
0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65
|
||||
}
|
||||
},
|
||||
{
|
||||
EVP_sha256,
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
||||
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
||||
0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
|
||||
}, 80,
|
||||
{
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
|
||||
0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
|
||||
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
|
||||
0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf
|
||||
}, 80,
|
||||
{
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb,
|
||||
0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3,
|
||||
0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
|
||||
0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
}, 80,
|
||||
82, {
|
||||
0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c,
|
||||
0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
|
||||
0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99,
|
||||
0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
|
||||
0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9,
|
||||
0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
|
||||
0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87
|
||||
}
|
||||
},
|
||||
{
|
||||
EVP_sha256,
|
||||
{
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
}, 22,
|
||||
{
|
||||
0,
|
||||
}, 0,
|
||||
{
|
||||
0,
|
||||
}, 0,
|
||||
42, {
|
||||
0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a,
|
||||
0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
|
||||
0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95,
|
||||
0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8
|
||||
}
|
||||
},
|
||||
{
|
||||
EVP_sha1,
|
||||
{
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
}, 11,
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
||||
0x0c,
|
||||
}, 13,
|
||||
{
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
|
||||
}, 10,
|
||||
42, {
|
||||
0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56,
|
||||
0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
|
||||
0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24,
|
||||
0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96
|
||||
}
|
||||
},
|
||||
{
|
||||
EVP_sha1,
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
||||
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
||||
0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
|
||||
}, 80,
|
||||
{
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
|
||||
0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
|
||||
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
|
||||
0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf
|
||||
}, 80,
|
||||
{
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb,
|
||||
0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3,
|
||||
0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
|
||||
0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
}, 80,
|
||||
82, {
|
||||
0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5,
|
||||
0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
|
||||
0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4,
|
||||
0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
|
||||
0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d,
|
||||
0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
|
||||
0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4
|
||||
}
|
||||
},
|
||||
{
|
||||
EVP_sha1,
|
||||
{
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
}, 22,
|
||||
{
|
||||
0,
|
||||
}, 0,
|
||||
{
|
||||
0,
|
||||
}, 0,
|
||||
42, {
|
||||
0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98,
|
||||
0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
|
||||
0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d,
|
||||
0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18
|
||||
}
|
||||
},
|
||||
{
|
||||
EVP_sha1,
|
||||
{
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
}, 22,
|
||||
{
|
||||
0,
|
||||
}, 0,
|
||||
{
|
||||
0,
|
||||
}, 0,
|
||||
42, {
|
||||
0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a,
|
||||
0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
|
||||
0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, 0x67, 0x3a, 0x08, 0x1d,
|
||||
0x70, 0xcc, 0xe7, 0xac, 0xfc, 0x48
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
uint8_t buf[82];
|
||||
size_t i;
|
||||
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
for (i = 0; i < sizeof(kTests) / sizeof(kTests[0]); i++) {
|
||||
const hkdf_test_vector_t *test = &kTests[i];
|
||||
if (!HKDF(buf, test->out_len, test->md_func(), test->ikm, test->ikm_len,
|
||||
test->salt, test->salt_len, test->info, test->info_len)) {
|
||||
fprintf(stderr, "Call to HKDF failed\n");
|
||||
BIO_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
if (memcmp(buf, test->out, test->out_len) != 0) {
|
||||
fprintf(stderr, "%u: Resulting key material does not match test vector\n",
|
||||
(unsigned)i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
ERR_free_strings();
|
||||
return 0;
|
||||
}
|
||||
@@ -74,6 +74,13 @@ uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len,
|
||||
out = static_out_buffer;
|
||||
}
|
||||
|
||||
/* If key_len is 0, the value of key doesn't matter. However, if we pass
|
||||
* key == NULL into HMAC_Init, it interprets it to mean "use the previous
|
||||
* value" instead of using a key of length 0. */
|
||||
if (key == NULL && key_len == 0) {
|
||||
key = static_out_buffer;
|
||||
}
|
||||
|
||||
HMAC_CTX_init(&ctx);
|
||||
if (!HMAC_Init(&ctx, key, key_len, evp_md) ||
|
||||
!HMAC_Update(&ctx, data, data_len) ||
|
||||
|
||||
@@ -145,6 +145,20 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Test that HMAC() functions corretly when called with key=NULL */
|
||||
const struct test_st *test = &kTests[0];
|
||||
if (NULL == HMAC(EVP_md5(), NULL, test->key_len, test->data,
|
||||
test->data_len, out, &out_len)) {
|
||||
printf("HMAC failed.\n");
|
||||
err++;
|
||||
}
|
||||
|
||||
p = to_hex(out, out_len);
|
||||
if (strcmp(p, test->hex_digest) != 0) {
|
||||
printf("got %s instead of %s\n", p, test->hex_digest);
|
||||
err++;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+147
-2
@@ -132,7 +132,7 @@ struct st_CRYPTO_EX_DATA_IMPL {
|
||||
};
|
||||
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
#if defined(_MSC_VER)
|
||||
#define OPENSSL_U64(x) x##UI64
|
||||
#else
|
||||
|
||||
@@ -142,13 +142,158 @@ struct st_CRYPTO_EX_DATA_IMPL {
|
||||
#define OPENSSL_U64(x) x##ULL
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_WINDOWS */
|
||||
#endif /* defined(_MSC_VER) */
|
||||
|
||||
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
|
||||
/* OPENSSL_cpuid_setup initializes OPENSSL_ia32cap_P. */
|
||||
void OPENSSL_cpuid_setup(void);
|
||||
#endif
|
||||
|
||||
#if !defined(inline)
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
|
||||
/* Constant-time utility functions.
|
||||
*
|
||||
* The following methods return a bitmask of all ones (0xff...f) for true and 0
|
||||
* for false. This is useful for choosing a value based on the result of a
|
||||
* conditional in constant time. For example,
|
||||
*
|
||||
* if (a < b) {
|
||||
* c = a;
|
||||
* } else {
|
||||
* c = b;
|
||||
* }
|
||||
*
|
||||
* can be written as
|
||||
*
|
||||
* unsigned int lt = constant_time_lt(a, b);
|
||||
* c = constant_time_select(lt, a, b); */
|
||||
|
||||
/* constant_time_msb returns the given value with the MSB copied to all the
|
||||
* other bits. */
|
||||
static inline unsigned int constant_time_msb(unsigned int a) {
|
||||
return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
|
||||
}
|
||||
|
||||
/* constant_time_lt returns 0xff..f if a < b and 0 otherwise. */
|
||||
static inline unsigned int constant_time_lt(unsigned int a, unsigned int b) {
|
||||
/* Consider the two cases of the problem:
|
||||
* msb(a) == msb(b): a < b iff the MSB of a - b is set.
|
||||
* msb(a) != msb(b): a < b iff the MSB of b is set.
|
||||
*
|
||||
* If msb(a) == msb(b) then the following evaluates as:
|
||||
* msb(a^((a^b)|((a-b)^a))) ==
|
||||
* msb(a^((a-b) ^ a)) == (because msb(a^b) == 0)
|
||||
* msb(a^a^(a-b)) == (rearranging)
|
||||
* msb(a-b) (because ∀x. x^x == 0)
|
||||
*
|
||||
* Else, if msb(a) != msb(b) then the following evaluates as:
|
||||
* msb(a^((a^b)|((a-b)^a))) ==
|
||||
* msb(a^(𝟙 | ((a-b)^a))) == (because msb(a^b) == 1 and 𝟙
|
||||
* represents a value s.t. msb(𝟙) = 1)
|
||||
* msb(a^𝟙) == (because ORing with 1 results in 1)
|
||||
* msb(b)
|
||||
*
|
||||
*
|
||||
* Here is an SMT-LIB verification of this formula:
|
||||
*
|
||||
* (define-fun lt ((a (_ BitVec 32)) (b (_ BitVec 32))) (_ BitVec 32)
|
||||
* (bvxor a (bvor (bvxor a b) (bvxor (bvsub a b) a)))
|
||||
* )
|
||||
*
|
||||
* (declare-fun a () (_ BitVec 32))
|
||||
* (declare-fun b () (_ BitVec 32))
|
||||
*
|
||||
* (assert (not (= (= #x00000001 (bvlshr (lt a b) #x0000001f)) (bvult a b))))
|
||||
* (check-sat)
|
||||
* (get-model)
|
||||
*/
|
||||
return constant_time_msb(a^((a^b)|((a-b)^a)));
|
||||
}
|
||||
|
||||
/* constant_time_lt_8 acts like |constant_time_lt| but returns an 8-bit mask. */
|
||||
static inline uint8_t constant_time_lt_8(unsigned int a, unsigned int b) {
|
||||
return (uint8_t)(constant_time_lt(a, b));
|
||||
}
|
||||
|
||||
/* constant_time_gt returns 0xff..f if a >= b and 0 otherwise. */
|
||||
static inline unsigned int constant_time_ge(unsigned int a, unsigned int b) {
|
||||
return ~constant_time_lt(a, b);
|
||||
}
|
||||
|
||||
/* constant_time_ge_8 acts like |constant_time_ge| but returns an 8-bit mask. */
|
||||
static inline uint8_t constant_time_ge_8(unsigned int a, unsigned int b) {
|
||||
return (uint8_t)(constant_time_ge(a, b));
|
||||
}
|
||||
|
||||
/* constant_time_is_zero returns 0xff..f if a == 0 and 0 otherwise. */
|
||||
static inline unsigned int constant_time_is_zero(unsigned int a) {
|
||||
/* Here is an SMT-LIB verification of this formula:
|
||||
*
|
||||
* (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32)
|
||||
* (bvand (bvnot a) (bvsub a #x00000001))
|
||||
* )
|
||||
*
|
||||
* (declare-fun a () (_ BitVec 32))
|
||||
*
|
||||
* (assert (not (= (= #x00000001 (bvlshr (is_zero a) #x0000001f)) (= a #x00000000))))
|
||||
* (check-sat)
|
||||
* (get-model)
|
||||
*/
|
||||
return constant_time_msb(~a & (a - 1));
|
||||
}
|
||||
|
||||
/* constant_time_is_zero_8 acts like constant_time_is_zero but returns an 8-bit
|
||||
* mask. */
|
||||
static inline uint8_t constant_time_is_zero_8(unsigned int a) {
|
||||
return (uint8_t)(constant_time_is_zero(a));
|
||||
}
|
||||
|
||||
/* constant_time_eq returns 0xff..f if a == b and 0 otherwise. */
|
||||
static inline unsigned int constant_time_eq(unsigned int a, unsigned int b) {
|
||||
return constant_time_is_zero(a ^ b);
|
||||
}
|
||||
|
||||
/* constant_time_eq_8 acts like |constant_time_eq| but returns an 8-bit mask. */
|
||||
static inline uint8_t constant_time_eq_8(unsigned int a, unsigned int b) {
|
||||
return (uint8_t)(constant_time_eq(a, b));
|
||||
}
|
||||
|
||||
/* constant_time_eq_int acts like |constant_time_eq| but works on int values. */
|
||||
static inline unsigned int constant_time_eq_int(int a, int b) {
|
||||
return constant_time_eq((unsigned)(a), (unsigned)(b));
|
||||
}
|
||||
|
||||
/* constant_time_eq_int_8 acts like |constant_time_eq_int| but returns an 8-bit
|
||||
* mask. */
|
||||
static inline uint8_t constant_time_eq_int_8(int a, int b) {
|
||||
return constant_time_eq_8((unsigned)(a), (unsigned)(b));
|
||||
}
|
||||
|
||||
/* constant_time_select returns (mask & a) | (~mask & b). When |mask| is all 1s
|
||||
* or all 0s (as returned by the methods above), the select methods return
|
||||
* either |a| (if |mask| is nonzero) or |b| (if |mask| is zero). */
|
||||
static inline unsigned int constant_time_select(unsigned int mask,
|
||||
unsigned int a, unsigned int b) {
|
||||
return (mask & a) | (~mask & b);
|
||||
}
|
||||
|
||||
/* constant_time_select_8 acts like |constant_time_select| but operates on
|
||||
* 8-bit values. */
|
||||
static inline uint8_t constant_time_select_8(uint8_t mask, uint8_t a,
|
||||
uint8_t b) {
|
||||
return (uint8_t)(constant_time_select(mask, a, b));
|
||||
}
|
||||
|
||||
/* constant_time_select_int acts like |constant_time_select| but operates on
|
||||
* ints. */
|
||||
static inline int constant_time_select_int(unsigned int mask, int a, int b) {
|
||||
return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
|
||||
}
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
@@ -28,11 +28,3 @@ add_library(
|
||||
|
||||
perlasm(md5-x86_64.${ASM_EXT} asm/md5-x86_64.pl)
|
||||
perlasm(md5-586.${ASM_EXT} asm/md5-586.pl)
|
||||
|
||||
add_executable(
|
||||
md5_test
|
||||
|
||||
md5_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(md5_test crypto)
|
||||
|
||||
@@ -108,6 +108,7 @@ sub round4_step
|
||||
EOF
|
||||
}
|
||||
|
||||
no warnings qw(uninitialized);
|
||||
my $flavour = shift;
|
||||
my $output = shift || "";
|
||||
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
|
||||
@@ -119,7 +120,6 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate;
|
||||
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
|
||||
die "can't locate x86_64-xlate.pl";
|
||||
|
||||
no warnings qw(uninitialized);
|
||||
open OUT,"| \"$^X\" $xlate $flavour $output";
|
||||
*STDOUT=*OUT;
|
||||
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
|
||||
static const char *const test[] = {
|
||||
"", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz",
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"12345678901234567890123456789012345678901234567890123456789012345678901234"
|
||||
"567890",
|
||||
NULL, };
|
||||
|
||||
static const char *const expected[] = {
|
||||
"d41d8cd98f00b204e9800998ecf8427e", "0cc175b9c0f1b6a831c399e269772661",
|
||||
"900150983cd24fb0d6963f7d28e17f72", "f96b697d7cb7938d525a2f31aaf161d0",
|
||||
"c3fcd3d76192e4007dfb496cca67e13b", "d174ab98d277d9f5a5611c2c9f419d9f",
|
||||
"57edf4a22be3c955ac49da2e2107b67a", };
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
size_t i, j;
|
||||
uint8_t md[MD5_DIGEST_LENGTH];
|
||||
char md_hex[sizeof(md) * 2 + 1];
|
||||
int ok = 1;
|
||||
|
||||
CRYPTO_library_init();
|
||||
|
||||
for (i = 0; test[i] != NULL; i++) {
|
||||
EVP_Digest(test[i], strlen(test[i]), md, NULL, EVP_md5(), NULL);
|
||||
for (j = 0; j < sizeof(md); j++) {
|
||||
sprintf(&md_hex[j * 2], "%02x", md[j]);
|
||||
}
|
||||
md_hex[MD5_DIGEST_LENGTH * 2] = 0;
|
||||
|
||||
if (strcmp(md_hex, expected[i]) != 0) {
|
||||
fprintf(stderr, "#%u: got %s, wanted %s\n", (unsigned)i, md_hex,
|
||||
expected[i]);
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
printf("PASS\n");
|
||||
}
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
@@ -64,6 +64,7 @@
|
||||
# Ivy Bridge 1.80(+7%)
|
||||
# Haswell 0.55(+93%) (if system doesn't support AVX)
|
||||
# Bulldozer 1.49(+27%)
|
||||
# Silvermont 2.88(+13%)
|
||||
|
||||
# March 2013
|
||||
#
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
OID information is generated via a series of perl scripts. In order, the full
|
||||
list of commands to run are:
|
||||
|
||||
perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h
|
||||
perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h
|
||||
perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h
|
||||
|
||||
objects.txt contains the list of all built-in OIDs. It is processed by
|
||||
objects.pl to output obj_mac.num and obj_mac.h. obj_mac.num is the list of NID
|
||||
values for each OID. This is an input/output parameter so NID values are stable
|
||||
across regenerations. obj_mac.h is the header which defines macros for all the
|
||||
built-in OIDs in C.
|
||||
|
||||
obj_mac.h is read by obj_dat.pl to generate obj_dat.h. obj_dat.h contains the
|
||||
ASN1_OBJECTs corresponding to built-in OIDs themselves along with lookup tables
|
||||
for search by short name, OID, etc.
|
||||
|
||||
obj_mac.num and obj_xref.txt are read by obj_xref.pl to generate
|
||||
obj_xref.h. obj_xref.txt links signature OIDs to corresponding public key
|
||||
algorithms and digests. obj_xref.h contains lookup tables for querying this
|
||||
information in both directions.
|
||||
|
||||
Dependency graph:
|
||||
|
||||
objects.txt
|
||||
|
|
||||
V
|
||||
[objects.pl] <--+
|
||||
/ \ |
|
||||
V V |
|
||||
obj_mac.h obj_mac.num obj_xref.txt
|
||||
| \ /
|
||||
V V V
|
||||
[obj_dat.pl] [obj_xref.pl]
|
||||
| |
|
||||
V V
|
||||
obj_dat.h obj_xref.h
|
||||
+36
-39
@@ -1,6 +1,6 @@
|
||||
/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
|
||||
* following command:
|
||||
* perl obj_dat.pl obj_mac.h obj_dat.h */
|
||||
* perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */
|
||||
|
||||
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
@@ -58,7 +58,7 @@
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#define NUM_NID 951
|
||||
#define NUM_NID 948
|
||||
#define NUM_SN 941
|
||||
#define NUM_LN 941
|
||||
#define NUM_OBJ 883
|
||||
@@ -2451,9 +2451,6 @@ static const ASN1_OBJECT kObjects[NUM_NID]={
|
||||
{"brainpoolP512t1","brainpoolP512t1",NID_brainpoolP512t1,9,
|
||||
&(lvalues[6097]),0},
|
||||
{"PSPECIFIED","pSpecified",NID_pSpecified,9,&(lvalues[6106]),0},
|
||||
{NULL,NULL,NID_undef,0,NULL,0},
|
||||
{NULL,NULL,NID_undef,0,NULL,0},
|
||||
{NULL,NULL,NID_undef,0,NULL,0},
|
||||
{"dhSinglePass-stdDH-sha1kdf-scheme",
|
||||
"dhSinglePass-stdDH-sha1kdf-scheme",
|
||||
NID_dhSinglePass_stdDH_sha1kdf_scheme,9,&(lvalues[6115]),0},
|
||||
@@ -2769,19 +2766,19 @@ static const unsigned int kNIDsInShortNameOrder[NUM_SN]={
|
||||
891, /* "deltaRevocationList" */
|
||||
107, /* "description" */
|
||||
871, /* "destinationIndicator" */
|
||||
950, /* "dh-cofactor-kdf" */
|
||||
949, /* "dh-std-kdf" */
|
||||
947, /* "dh-cofactor-kdf" */
|
||||
946, /* "dh-std-kdf" */
|
||||
28, /* "dhKeyAgreement" */
|
||||
944, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
|
||||
945, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
|
||||
946, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
|
||||
947, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
|
||||
948, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
|
||||
939, /* "dhSinglePass-stdDH-sha1kdf-scheme" */
|
||||
940, /* "dhSinglePass-stdDH-sha224kdf-scheme" */
|
||||
941, /* "dhSinglePass-stdDH-sha256kdf-scheme" */
|
||||
942, /* "dhSinglePass-stdDH-sha384kdf-scheme" */
|
||||
943, /* "dhSinglePass-stdDH-sha512kdf-scheme" */
|
||||
941, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
|
||||
942, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
|
||||
943, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
|
||||
944, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
|
||||
945, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
|
||||
936, /* "dhSinglePass-stdDH-sha1kdf-scheme" */
|
||||
937, /* "dhSinglePass-stdDH-sha224kdf-scheme" */
|
||||
938, /* "dhSinglePass-stdDH-sha256kdf-scheme" */
|
||||
939, /* "dhSinglePass-stdDH-sha384kdf-scheme" */
|
||||
940, /* "dhSinglePass-stdDH-sha512kdf-scheme" */
|
||||
920, /* "dhpublicnumber" */
|
||||
382, /* "directory" */
|
||||
887, /* "distinguishedName" */
|
||||
@@ -3723,19 +3720,19 @@ static const unsigned int kNIDsInLongNameOrder[NUM_LN]={
|
||||
107, /* "description" */
|
||||
871, /* "destinationIndicator" */
|
||||
80, /* "desx-cbc" */
|
||||
950, /* "dh-cofactor-kdf" */
|
||||
949, /* "dh-std-kdf" */
|
||||
947, /* "dh-cofactor-kdf" */
|
||||
946, /* "dh-std-kdf" */
|
||||
28, /* "dhKeyAgreement" */
|
||||
944, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
|
||||
945, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
|
||||
946, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
|
||||
947, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
|
||||
948, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
|
||||
939, /* "dhSinglePass-stdDH-sha1kdf-scheme" */
|
||||
940, /* "dhSinglePass-stdDH-sha224kdf-scheme" */
|
||||
941, /* "dhSinglePass-stdDH-sha256kdf-scheme" */
|
||||
942, /* "dhSinglePass-stdDH-sha384kdf-scheme" */
|
||||
943, /* "dhSinglePass-stdDH-sha512kdf-scheme" */
|
||||
941, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
|
||||
942, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
|
||||
943, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
|
||||
944, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
|
||||
945, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
|
||||
936, /* "dhSinglePass-stdDH-sha1kdf-scheme" */
|
||||
937, /* "dhSinglePass-stdDH-sha224kdf-scheme" */
|
||||
938, /* "dhSinglePass-stdDH-sha256kdf-scheme" */
|
||||
939, /* "dhSinglePass-stdDH-sha384kdf-scheme" */
|
||||
940, /* "dhSinglePass-stdDH-sha512kdf-scheme" */
|
||||
11, /* "directory services (X.500)" */
|
||||
378, /* "directory services - algorithms" */
|
||||
887, /* "distinguishedName" */
|
||||
@@ -4703,14 +4700,14 @@ static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={
|
||||
505, /* OBJ_mime_mhs_headings 1 3 6 1 7 1 1 */
|
||||
506, /* OBJ_mime_mhs_bodies 1 3 6 1 7 1 2 */
|
||||
119, /* OBJ_ripemd160WithRSA 1 3 36 3 3 1 2 */
|
||||
940, /* OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1 3 132 1 11 0 */
|
||||
941, /* OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1 3 132 1 11 1 */
|
||||
942, /* OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1 3 132 1 11 2 */
|
||||
943, /* OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1 3 132 1 11 3 */
|
||||
945, /* OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1 3 132 1 14 0 */
|
||||
946, /* OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1 3 132 1 14 1 */
|
||||
947, /* OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1 3 132 1 14 2 */
|
||||
948, /* OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme 1 3 132 1 14 3 */
|
||||
937, /* OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1 3 132 1 11 0 */
|
||||
938, /* OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1 3 132 1 11 1 */
|
||||
939, /* OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1 3 132 1 11 2 */
|
||||
940, /* OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1 3 132 1 11 3 */
|
||||
942, /* OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1 3 132 1 14 0 */
|
||||
943, /* OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1 3 132 1 14 1 */
|
||||
944, /* OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1 3 132 1 14 2 */
|
||||
945, /* OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme 1 3 132 1 14 3 */
|
||||
631, /* OBJ_setAttr_GenCryptgrm 2 23 42 3 3 3 1 */
|
||||
632, /* OBJ_setAttr_T2Enc 2 23 42 3 3 4 1 */
|
||||
633, /* OBJ_setAttr_T2cleartxt 2 23 42 3 3 4 2 */
|
||||
@@ -5053,8 +5050,8 @@ static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={
|
||||
932, /* OBJ_brainpoolP384t1 1 3 36 3 3 2 8 1 1 12 */
|
||||
933, /* OBJ_brainpoolP512r1 1 3 36 3 3 2 8 1 1 13 */
|
||||
934, /* OBJ_brainpoolP512t1 1 3 36 3 3 2 8 1 1 14 */
|
||||
939, /* OBJ_dhSinglePass_stdDH_sha1kdf_scheme 1 3 133 16 840 63 0 2 */
|
||||
944, /* OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme 1 3 133 16 840 63 0 3 */
|
||||
936, /* OBJ_dhSinglePass_stdDH_sha1kdf_scheme 1 3 133 16 840 63 0 2 */
|
||||
941, /* OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme 1 3 133 16 840 63 0 3 */
|
||||
418, /* OBJ_aes_128_ecb 2 16 840 1 101 3 4 1 1 */
|
||||
419, /* OBJ_aes_128_cbc 2 16 840 1 101 3 4 1 2 */
|
||||
420, /* OBJ_aes_128_ofb128 2 16 840 1 101 3 4 1 3 */
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
#!/usr/local/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# fixes bug in floating point emulation on sparc64 when
|
||||
# this script produces off-by-one output on sparc64
|
||||
use integer;
|
||||
|
||||
if (scalar @ARGV != 2)
|
||||
{
|
||||
print "Usage: perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub obj_cmp
|
||||
{
|
||||
local(@a,@b,$_,$r);
|
||||
@@ -170,7 +176,7 @@ foreach (sort obj_cmp @a)
|
||||
print OUT <<'EOF';
|
||||
/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
|
||||
* following command:
|
||||
* perl obj_dat.pl obj_mac.h obj_dat.h */
|
||||
* perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */
|
||||
|
||||
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
|
||||
+947
-938
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,6 @@
|
||||
/* AUTOGENERATED BY objxref.pl, DO NOT EDIT */
|
||||
/* THIS FILE IS GENERATED FROM obj_xref.txt by obj_xref.pl via the
|
||||
* following command:
|
||||
* perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -53,9 +55,6 @@ static const nid_triple sigoid_srt[] =
|
||||
|
||||
static const nid_triple * const sigoid_srt_xref[] =
|
||||
{
|
||||
&sigoid_srt[29],
|
||||
&sigoid_srt[17],
|
||||
&sigoid_srt[18],
|
||||
&sigoid_srt[0],
|
||||
&sigoid_srt[1],
|
||||
&sigoid_srt[7],
|
||||
|
||||
+14
-3
@@ -1,7 +1,13 @@
|
||||
#!/usr/local/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
if (scalar @ARGV != 2)
|
||||
{
|
||||
print "Usage: perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my %xref_tbl;
|
||||
my %oid_tbl;
|
||||
|
||||
@@ -60,7 +66,9 @@ my $pname = $0;
|
||||
$pname =~ s|^.[^/]/||;
|
||||
|
||||
print <<EOF;
|
||||
/* AUTOGENERATED BY $pname, DO NOT EDIT */
|
||||
/* THIS FILE IS GENERATED FROM obj_xref.txt by obj_xref.pl via the
|
||||
* following command:
|
||||
* perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -90,7 +98,10 @@ EOF
|
||||
|
||||
foreach (@srt2)
|
||||
{
|
||||
my $x = $xref_tbl{$_}[2];
|
||||
my ($p1, $p2, $x) = @{$xref_tbl{$_}};
|
||||
# If digest or signature algorithm is "undef" then the algorithm
|
||||
# needs special handling and is excluded from the cross reference table.
|
||||
next if $p1 eq "undef" || $p2 eq "undef";
|
||||
print "\t\&sigoid_srt\[$x\],\n";
|
||||
}
|
||||
|
||||
|
||||
+16
-9
@@ -1,4 +1,10 @@
|
||||
#!/usr/local/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
if (scalar @ARGV != 3)
|
||||
{
|
||||
print "Usage: perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
open (NUMIN,"$ARGV[1]") || die "Can't open number file $ARGV[1]";
|
||||
$max_nid=0;
|
||||
@@ -121,7 +127,7 @@ open (OUT,">$ARGV[2]") || die "Can't open output file $ARGV[2]";
|
||||
print OUT <<'EOF';
|
||||
/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
|
||||
* following command:
|
||||
* perl objects.pl objects.txt obj_mac.num obj_mac.h */
|
||||
* perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h */
|
||||
|
||||
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
@@ -129,21 +135,21 @@ print OUT <<'EOF';
|
||||
* 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:
|
||||
@@ -158,10 +164,10 @@ print OUT <<'EOF';
|
||||
* 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
|
||||
* 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
|
||||
@@ -173,11 +179,12 @@ print OUT <<'EOF';
|
||||
* 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.] */
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#define SN_undef "UNDEF"
|
||||
#define LN_undef "undefined"
|
||||
|
||||
@@ -340,7 +340,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
|
||||
kstr=(unsigned char *)buf;
|
||||
}
|
||||
assert(iv_len <= (int)sizeof(iv));
|
||||
if (RAND_pseudo_bytes(iv,iv_len) < 0) /* Generate a salt */
|
||||
if (!RAND_bytes(iv, iv_len)) /* Generate a salt */
|
||||
goto err;
|
||||
/* The 'iv' is used as the iv and as a salt. It is
|
||||
* NOT taken from the BytesToKey function */
|
||||
@@ -390,7 +390,7 @@ err:
|
||||
int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
|
||||
pem_password_cb *callback,void *u)
|
||||
{
|
||||
int i,j,o,klen;
|
||||
int i=0,j,o,klen;
|
||||
long len;
|
||||
EVP_CIPHER_CTX ctx;
|
||||
unsigned char key[EVP_MAX_KEY_LENGTH];
|
||||
|
||||
@@ -121,7 +121,7 @@ my %globals;
|
||||
$self->{sz} = "";
|
||||
} elsif ($self->{op} =~ /^v/) { # VEX
|
||||
$self->{sz} = "";
|
||||
} elsif ($self->{op} =~ /movq/ && $line =~ /%xmm/) {
|
||||
} elsif ($self->{op} =~ /mov[dq]/ && $line =~ /%xmm/) {
|
||||
$self->{sz} = "";
|
||||
} elsif ($self->{op} =~ /([a-z]{3,})([qlwb])$/) {
|
||||
$self->{op} = $1;
|
||||
|
||||
@@ -104,7 +104,7 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
|
||||
sstr = ASN1_STRING_data(pbe->salt);
|
||||
if (salt)
|
||||
memcpy(sstr, salt, saltlen);
|
||||
else if (RAND_pseudo_bytes(sstr, saltlen) < 0)
|
||||
else if (!RAND_bytes(sstr, saltlen))
|
||||
goto err;
|
||||
|
||||
if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str))
|
||||
|
||||
@@ -141,7 +141,7 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
|
||||
{
|
||||
if (aiv)
|
||||
memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
|
||||
else if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0)
|
||||
else if (!RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)))
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
|
||||
|
||||
if (salt)
|
||||
memcpy (osalt->data, salt, saltlen);
|
||||
else if (RAND_pseudo_bytes (osalt->data, saltlen) < 0)
|
||||
else if (!RAND_bytes(osalt->data, saltlen))
|
||||
goto merr;
|
||||
|
||||
if(iter <= 0)
|
||||
|
||||
@@ -263,8 +263,8 @@ typedef int (*keygen_func)(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw,
|
||||
|
||||
struct pbe_suite {
|
||||
int pbe_nid;
|
||||
const EVP_CIPHER* (*cipher_func)();
|
||||
const EVP_MD* (*md_func)();
|
||||
const EVP_CIPHER* (*cipher_func)(void);
|
||||
const EVP_MD* (*md_func)(void);
|
||||
keygen_func keygen;
|
||||
};
|
||||
|
||||
|
||||
@@ -181,13 +181,13 @@ int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned tlen,
|
||||
/* pad out with non-zero random data */
|
||||
j = tlen - 3 - flen;
|
||||
|
||||
if (RAND_pseudo_bytes(p, j) <= 0) {
|
||||
if (!RAND_bytes(p, j)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < j; i++) {
|
||||
while (*p == 0) {
|
||||
if (RAND_pseudo_bytes(p, 1) <= 0) {
|
||||
if (!RAND_bytes(p, 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -411,7 +411,7 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
|
||||
memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
|
||||
db[emlen - flen - mdlen - 1] = 0x01;
|
||||
memcpy(db + emlen - flen - mdlen, from, flen);
|
||||
if (RAND_pseudo_bytes(seed, mdlen) <= 0) {
|
||||
if (!RAND_bytes(seed, mdlen)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -718,7 +718,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (RAND_pseudo_bytes(salt, sLen) <= 0) {
|
||||
if (!RAND_bytes(salt, sLen)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +260,13 @@ int RSA_is_opaque(const RSA *rsa) {
|
||||
return rsa->meth && (rsa->meth->flags & RSA_FLAG_OPAQUE);
|
||||
}
|
||||
|
||||
int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) {
|
||||
if (rsa->meth && rsa->meth->supports_digest) {
|
||||
return rsa->meth->supports_digest(rsa, md);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
|
||||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
|
||||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp, new_func,
|
||||
|
||||
@@ -51,11 +51,3 @@ perlasm(sha512-586.${ASM_EXT} asm/sha512-586.pl)
|
||||
perlasm(sha1-armv4-large.${ASM_EXT} asm/sha1-armv4-large.pl)
|
||||
perlasm(sha256-armv4.${ASM_EXT} asm/sha256-armv4.pl)
|
||||
perlasm(sha512-armv4.${ASM_EXT} asm/sha512-armv4.pl)
|
||||
|
||||
add_executable(
|
||||
sha1_test
|
||||
|
||||
sha1_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(sha1_test crypto)
|
||||
|
||||
@@ -93,16 +93,19 @@
|
||||
# P4 10.6 -
|
||||
# AMD K8 7.1 -
|
||||
# Core2 7.3 6.0/+22% -
|
||||
# Atom 12.5 9.3(*)/+35% -
|
||||
# Westmere 7.3 5.5/+33% -
|
||||
# Sandy Bridge 8.8 6.2/+40% 5.1(**)/+73%
|
||||
# Ivy Bridge 7.2 4.8/+51% 4.7(**)/+53%
|
||||
# Haswell 6.5 4.3/+51% 4.1(**)/+58%
|
||||
# Bulldozer 11.6 6.0/+92%
|
||||
# VIA Nano 10.6 7.5/+41%
|
||||
# Atom 12.5 9.3(*)/+35%
|
||||
# Silvermont 14.5 9.9(*)/+46%
|
||||
#
|
||||
# (*) Loop is 1056 instructions long and expected result is ~8.25.
|
||||
# It remains mystery [to me] why ILP is limited to 1.7.
|
||||
# The discrepancy is because of front-end limitations, so
|
||||
# called MS-ROM penalties, and on Silvermont even rotate's
|
||||
# limited parallelism.
|
||||
#
|
||||
# (**) As per above comment, the result is for AVX *plus* sh[rl]d.
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
# Bulldozer 36 - 27/22 17.0 13.6
|
||||
# VIA Nano 36 - 25/22 16.8 16.5
|
||||
# Atom 50 - 30/25 21.9 18.9
|
||||
# Silvermont 40 - 34/31 22.9 20.6
|
||||
#
|
||||
# (*) numbers after slash are for unrolled loop, where applicable;
|
||||
# (**) x86_64 assembly performance is presented for reference
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
# Bulldozer 121 - 50 14.0 13.5
|
||||
# VIA Nano 91 - 52 33 14.7
|
||||
# Atom 126 - 68 48(***) 14.7
|
||||
# Silvermont 97 - 58 42(***) 17.5
|
||||
#
|
||||
# (*) whichever best applicable.
|
||||
# (**) x86_64 assembler performance is presented for reference
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
# Bulldozer 21.1 13.6(+54%) 13.6(+54%(***)) 13.5 8.58(+57%)
|
||||
# VIA Nano 23.0 16.5(+39%) - 14.7 -
|
||||
# Atom 23.0 18.9(+22%) - 14.7 -
|
||||
# Silvermont 27.4 20.6(+33%) - 17.5 -
|
||||
#
|
||||
# (*) whichever best applicable;
|
||||
# (**) switch from ror to shrd stands for fair share of improvement;
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
|
||||
static const char *const test[] = {
|
||||
"abc", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", NULL, };
|
||||
|
||||
static const char *const expected[] = {
|
||||
"a9993e364706816aba3e25717850c26c9cd0d89d",
|
||||
"84983e441c3bd26ebaae4aa1f95129e5e54670f1", };
|
||||
|
||||
static int test_incremental(void) {
|
||||
EVP_MD_CTX ctx;
|
||||
char buf[1000];
|
||||
uint8_t md[SHA_DIGEST_LENGTH];
|
||||
char md_hex[sizeof(md) * 2 + 1];
|
||||
size_t i;
|
||||
static const char expected[] = "34aa973cd4c4daa4f61eeb2bdbad27316534016f";
|
||||
|
||||
memset(buf, 'a', sizeof(buf));
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
|
||||
for (i = 0; i < 1000; i++) {
|
||||
EVP_DigestUpdate(&ctx, buf, sizeof(buf));
|
||||
}
|
||||
EVP_DigestFinal_ex(&ctx, md, NULL);
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
|
||||
for (i = 0; i < sizeof(md); i++) {
|
||||
sprintf(&md_hex[i * 2], "%02x", md[i]);
|
||||
}
|
||||
|
||||
if (strcmp(md_hex, expected) != 0) {
|
||||
fprintf(stderr, "test_incremental: got %s, wanted %s\n", md_hex, expected);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
size_t i, j;
|
||||
uint8_t md[SHA_DIGEST_LENGTH];
|
||||
char md_hex[sizeof(md) * 2 + 1];
|
||||
int ok = 1;
|
||||
|
||||
CRYPTO_library_init();
|
||||
|
||||
for (i = 0; test[i] != NULL; i++) {
|
||||
EVP_Digest(test[i], strlen(test[i]), md, NULL, EVP_sha1(), NULL);
|
||||
for (j = 0; j < sizeof(md); j++) {
|
||||
sprintf(&md_hex[j * 2], "%02x", md[j]);
|
||||
}
|
||||
|
||||
if (strcmp(md_hex, expected[i]) != 0) {
|
||||
fprintf(stderr, "#%u: got %s, wanted %s\n", (unsigned)i, md_hex,
|
||||
expected[i]);
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ok &= test_incremental();
|
||||
|
||||
if (ok) {
|
||||
printf("PASS\n");
|
||||
}
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
@@ -554,6 +554,7 @@ int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
|
||||
mbflag |= MBSTRING_FLAG;
|
||||
stmp.data = NULL;
|
||||
stmp.length = 0;
|
||||
stmp.flags = 0;
|
||||
ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING);
|
||||
if(ret < 0) return ret;
|
||||
*out = stmp.data;
|
||||
|
||||
@@ -84,6 +84,12 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(X509, ASN1_item_verify, X509_R_INVALID_BIT_STRING_BITS_LEFT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
|
||||
if (!EVP_DigestVerifyInitFromAlgorithm(&ctx, a, pkey))
|
||||
|
||||
@@ -91,7 +91,6 @@ int X509_CRL_print(BIO *out, X509_CRL *x)
|
||||
BIO_printf(out, "Certificate Revocation List (CRL):\n");
|
||||
l = X509_CRL_get_version(x);
|
||||
BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l+1, l);
|
||||
i = OBJ_obj2nid(x->sig_alg->algorithm);
|
||||
X509_signature_print(out, x->sig_alg, NULL);
|
||||
p=X509_NAME_oneline(X509_CRL_get_issuer(x),NULL,0);
|
||||
BIO_printf(out,"%8sIssuer: %s\n","",p);
|
||||
|
||||
@@ -94,6 +94,7 @@ const ERR_STRING_DATA X509_error_string_data[] = {
|
||||
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE), "CRL_VERIFY_FAILURE"},
|
||||
{ERR_PACK(ERR_LIB_X509, 0, X509_R_ERR_ASN1_LIB), "ERR_ASN1_LIB"},
|
||||
{ERR_PACK(ERR_LIB_X509, 0, X509_R_IDP_MISMATCH), "IDP_MISMATCH"},
|
||||
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_BIT_STRING_BITS_LEFT), "INVALID_BIT_STRING_BITS_LEFT"},
|
||||
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DIRECTORY), "INVALID_DIRECTORY"},
|
||||
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_FIELD_NAME), "INVALID_FIELD_NAME"},
|
||||
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_TRUST), "INVALID_TRUST"},
|
||||
|
||||
@@ -64,6 +64,12 @@
|
||||
int X509_set_version(X509 *x, long version)
|
||||
{
|
||||
if (x == NULL) return(0);
|
||||
if (version == 0)
|
||||
{
|
||||
M_ASN1_INTEGER_free(x->cert_info->version);
|
||||
x->cert_info->version = NULL;
|
||||
return(1);
|
||||
}
|
||||
if (x->cert_info->version == NULL)
|
||||
{
|
||||
if ((x->cert_info->version=M_ASN1_INTEGER_new()) == NULL)
|
||||
|
||||
+13
-4
@@ -168,6 +168,8 @@ int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
|
||||
{
|
||||
int idx;
|
||||
X509_TRUST *trtmp;
|
||||
char *name_dup;
|
||||
|
||||
/* This is set according to what we change: application can't set it */
|
||||
flags &= ~X509_TRUST_DYNAMIC;
|
||||
/* This will always be set for application modified trust entries */
|
||||
@@ -183,13 +185,18 @@ int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
|
||||
trtmp->flags = X509_TRUST_DYNAMIC;
|
||||
} else trtmp = X509_TRUST_get0(idx);
|
||||
|
||||
/* OPENSSL_free existing name if dynamic */
|
||||
if(trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name);
|
||||
/* dup supplied name */
|
||||
if(!(trtmp->name = BUF_strdup(name))) {
|
||||
/* Duplicate the supplied name. */
|
||||
name_dup = BUF_strdup(name);
|
||||
if (name_dup == NULL) {
|
||||
OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
|
||||
if (idx == -1)
|
||||
OPENSSL_free(trtmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OPENSSL_free existing name if dynamic */
|
||||
if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name);
|
||||
trtmp->name = name_dup;
|
||||
/* Keep the dynamic flag of existing entry */
|
||||
trtmp->flags &= X509_TRUST_DYNAMIC;
|
||||
/* Set all other flags */
|
||||
@@ -204,10 +211,12 @@ int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
|
||||
if(idx == -1) {
|
||||
if(!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
|
||||
OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
|
||||
trtable_free(trtmp);
|
||||
return 0;
|
||||
}
|
||||
if (!sk_X509_TRUST_push(trtable, trtmp)) {
|
||||
OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
|
||||
trtable_free(trtmp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+28
-42
@@ -484,7 +484,6 @@ static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
|
||||
ctx->current_cert = x;
|
||||
ctx->current_issuer = issuer;
|
||||
return ctx->verify_cb(0, ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Alternative lookup method: look from a STACK stored in other_ctx */
|
||||
@@ -1901,7 +1900,7 @@ ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
|
||||
ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
|
||||
int offset_day, long offset_sec, time_t *in_tm)
|
||||
{
|
||||
time_t t;
|
||||
time_t t = 0;
|
||||
|
||||
if (in_tm) t = *in_tm;
|
||||
else time(&t);
|
||||
@@ -2248,38 +2247,26 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
STACK_OF(X509) *chain)
|
||||
{
|
||||
int ret = 1;
|
||||
int ex_data_allocated = 0;
|
||||
|
||||
memset(ctx, 0, sizeof(X509_STORE_CTX));
|
||||
ctx->ctx=store;
|
||||
ctx->current_method=0;
|
||||
ctx->cert=x509;
|
||||
ctx->untrusted=chain;
|
||||
ctx->crls = NULL;
|
||||
ctx->last_untrusted=0;
|
||||
ctx->other_ctx=NULL;
|
||||
ctx->valid=0;
|
||||
ctx->chain=NULL;
|
||||
ctx->error=0;
|
||||
ctx->explicit_policy=0;
|
||||
ctx->error_depth=0;
|
||||
ctx->current_cert=NULL;
|
||||
ctx->current_issuer=NULL;
|
||||
ctx->current_crl=NULL;
|
||||
ctx->current_crl_score=0;
|
||||
ctx->current_reasons=0;
|
||||
ctx->tree = NULL;
|
||||
ctx->parent = NULL;
|
||||
|
||||
if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
|
||||
&ctx->ex_data))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
ex_data_allocated = 1;
|
||||
|
||||
ctx->param = X509_VERIFY_PARAM_new();
|
||||
|
||||
if (!ctx->param)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
goto err;
|
||||
|
||||
/* Inherit callbacks and flags from X509_STORE if not set
|
||||
* use defaults.
|
||||
*/
|
||||
|
||||
* use defaults. */
|
||||
|
||||
if (store)
|
||||
ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
|
||||
@@ -2299,10 +2286,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
X509_VERIFY_PARAM_lookup("default"));
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
goto err;
|
||||
|
||||
if (store && store->check_issued)
|
||||
ctx->check_issued = store->check_issued;
|
||||
@@ -2356,19 +2340,21 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
|
||||
ctx->check_policy = check_policy;
|
||||
|
||||
|
||||
/* This memset() can't make any sense anyway, so it's removed. As
|
||||
* X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
|
||||
* corresponding "new" here and remove this bogus initialisation. */
|
||||
/* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
|
||||
if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
|
||||
&(ctx->ex_data)))
|
||||
{
|
||||
OPENSSL_free(ctx);
|
||||
OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
err:
|
||||
if (ex_data_allocated)
|
||||
{
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &ctx->ex_data);
|
||||
}
|
||||
if (ctx->param != NULL)
|
||||
{
|
||||
X509_VERIFY_PARAM_free(ctx->param);
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(X509_STORE_CTX));
|
||||
OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set alternative lookup method: just a STACK of trusted certificates.
|
||||
|
||||
@@ -140,3 +140,15 @@ void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
|
||||
|
||||
}
|
||||
|
||||
/* X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise. */
|
||||
int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
|
||||
{
|
||||
int rv;
|
||||
rv = OBJ_cmp(a->algorithm, b->algorithm);
|
||||
if (rv)
|
||||
return rv;
|
||||
if (!a->parameter && !b->parameter)
|
||||
return 0;
|
||||
return ASN1_TYPE_cmp(a->parameter, b->parameter);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ extern const ASN1_ITEM RSAPublicKey_it;
|
||||
|
||||
int X509_verify(X509 *a, EVP_PKEY *r)
|
||||
{
|
||||
if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
|
||||
return 0;
|
||||
return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF),a->sig_alg,
|
||||
a->signature,a->cert_info,r));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user