summaryrefslogtreecommitdiffstats
path: root/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/CMakeLists.txt33
-rw-r--r--src/crypto/aes/aes.c24
-rw-r--r--src/crypto/aes/asm/aes-armv4.pl43
-rw-r--r--src/crypto/aes/asm/aesni-x86.pl319
-rw-r--r--src/crypto/aes/asm/aesni-x86_64.pl945
-rw-r--r--src/crypto/aes/asm/aesv8-armx.pl228
-rw-r--r--src/crypto/aes/asm/bsaes-armv7.pl54
-rw-r--r--src/crypto/asn1/CMakeLists.txt1
-rw-r--r--src/crypto/asn1/a_d2i_fp.c2
-rw-r--r--src/crypto/asn1/a_gentm.c1
-rw-r--r--src/crypto/asn1/a_time.c1
-rw-r--r--src/crypto/asn1/a_type.c3
-rw-r--r--src/crypto/asn1/a_utctm.c3
-rw-r--r--src/crypto/asn1/asn1_error.c203
-rw-r--r--src/crypto/asn1/asn1_lib.c47
-rw-r--r--src/crypto/asn1/asn1_par.c40
-rw-r--r--src/crypto/asn1/bio_ndef.c6
-rw-r--r--src/crypto/asn1/tasn_dec.c33
-rw-r--r--src/crypto/asn1/tasn_new.c10
-rw-r--r--src/crypto/asn1/tasn_prn.c3
-rw-r--r--src/crypto/asn1/tasn_typ.c67
-rw-r--r--src/crypto/asn1/tasn_utl.c1
-rw-r--r--src/crypto/base64/CMakeLists.txt2
-rw-r--r--src/crypto/base64/base64.c4
-rw-r--r--src/crypto/base64/base64_test.cc (renamed from src/crypto/base64/base64_test.c)71
-rw-r--r--src/crypto/bio/CMakeLists.txt3
-rw-r--r--src/crypto/bio/bio.c28
-rw-r--r--src/crypto/bio/bio_error.c59
-rw-r--r--src/crypto/bio/bio_test.cc (renamed from src/crypto/bio/bio_test.c)261
-rw-r--r--src/crypto/bio/buffer.c13
-rw-r--r--src/crypto/bio/connect.c31
-rw-r--r--src/crypto/bio/pair.c14
-rw-r--r--src/crypto/bio/socket.c8
-rw-r--r--src/crypto/bn/CMakeLists.txt3
-rw-r--r--src/crypto/bn/asm/armv4-mont.pl42
-rw-r--r--src/crypto/bn/asm/x86_64-gcc.c74
-rw-r--r--src/crypto/bn/bn.c12
-rw-r--r--src/crypto/bn/bn_error.c63
-rw-r--r--src/crypto/bn/bn_test.c1471
-rw-r--r--src/crypto/bn/bn_test.cc1619
-rw-r--r--src/crypto/bn/convert.c10
-rw-r--r--src/crypto/bn/ctx.c12
-rw-r--r--src/crypto/bn/div.c23
-rw-r--r--src/crypto/bn/exponentiation.c163
-rw-r--r--src/crypto/bn/gcd.c15
-rw-r--r--src/crypto/bn/generic.c33
-rw-r--r--src/crypto/bn/internal.h10
-rw-r--r--src/crypto/bn/montgomery.c62
-rw-r--r--src/crypto/bn/mul.c6
-rw-r--r--src/crypto/bn/prime.c14
-rw-r--r--src/crypto/bn/random.c4
-rw-r--r--src/crypto/bn/sqrt.c2
-rw-r--r--src/crypto/buf/CMakeLists.txt1
-rw-r--r--src/crypto/buf/buf_error.c25
-rw-r--r--src/crypto/bytestring/CMakeLists.txt2
-rw-r--r--src/crypto/bytestring/bytestring_test.cc (renamed from src/crypto/bytestring/bytestring_test.c)421
-rw-r--r--src/crypto/bytestring/cbb.c15
-rw-r--r--src/crypto/bytestring/cbs.c16
-rw-r--r--src/crypto/chacha/chacha_vec.c23
-rw-r--r--src/crypto/chacha/chacha_vec_arm.S728
-rw-r--r--src/crypto/chacha/chacha_vec_arm_generate.go148
-rw-r--r--src/crypto/cipher/CMakeLists.txt4
-rw-r--r--src/crypto/cipher/aead.c42
-rw-r--r--src/crypto/cipher/aead_test.c387
-rw-r--r--src/crypto/cipher/aead_test.cc276
-rw-r--r--src/crypto/cipher/cipher.c10
-rw-r--r--src/crypto/cipher/cipher_error.c78
-rw-r--r--src/crypto/cipher/cipher_test.c64
-rw-r--r--src/crypto/cipher/e_aes.c444
-rw-r--r--src/crypto/cipher/e_chacha20poly1305.c8
-rw-r--r--src/crypto/cipher/e_des.c30
-rw-r--r--src/crypto/cipher/e_rc4.c19
-rw-r--r--src/crypto/cipher/e_ssl3.c125
-rw-r--r--src/crypto/cipher/e_tls.c180
-rw-r--r--src/crypto/cipher/internal.h10
-rw-r--r--src/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt336
-rw-r--r--src/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt336
-rw-r--r--src/crypto/cipher/test/cipher_test.txt37
-rw-r--r--src/crypto/cmac/CMakeLists.txt17
-rw-r--r--src/crypto/cmac/cmac.c239
-rw-r--r--src/crypto/cmac/cmac_test.cc154
-rw-r--r--src/crypto/conf/CMakeLists.txt1
-rw-r--r--src/crypto/conf/conf.c76
-rw-r--r--src/crypto/conf/conf_error.c31
-rw-r--r--src/crypto/cpu-arm-asm.S32
-rw-r--r--src/crypto/cpu-arm.c87
-rw-r--r--src/crypto/cpu-intel.c1
-rw-r--r--src/crypto/cpu-x86-asm.pl4
-rw-r--r--src/crypto/cpu-x86_64-asm.pl4
-rw-r--r--src/crypto/crypto_error.c25
-rw-r--r--src/crypto/crypto_error.h18
-rw-r--r--src/crypto/des/des.c54
-rw-r--r--src/crypto/dh/CMakeLists.txt3
-rw-r--r--src/crypto/dh/dh.c33
-rw-r--r--src/crypto/dh/dh_error.c29
-rw-r--r--src/crypto/dh/dh_impl.c14
-rw-r--r--src/crypto/dh/dh_test.cc (renamed from src/crypto/dh/dh_test.c)390
-rw-r--r--src/crypto/digest/CMakeLists.txt3
-rw-r--r--src/crypto/digest/digest.c2
-rw-r--r--src/crypto/digest/digest_error.c24
-rw-r--r--src/crypto/digest/digest_test.cc (renamed from src/crypto/digest/digest_test.c)225
-rw-r--r--src/crypto/digest/md32_common.h18
-rw-r--r--src/crypto/directory_posix.c1
-rw-r--r--src/crypto/directory_win.c3
-rw-r--r--src/crypto/dsa/CMakeLists.txt1
-rw-r--r--src/crypto/dsa/dsa.c64
-rw-r--r--src/crypto/dsa/dsa_error.c30
-rw-r--r--src/crypto/dsa/dsa_impl.c68
-rw-r--r--src/crypto/dsa/dsa_test.c57
-rw-r--r--src/crypto/ec/CMakeLists.txt11
-rw-r--r--src/crypto/ec/ec.c53
-rw-r--r--src/crypto/ec/ec_asn1.c61
-rw-r--r--src/crypto/ec/ec_error.c107
-rw-r--r--src/crypto/ec/ec_key.c95
-rw-r--r--src/crypto/ec/ec_montgomery.c129
-rw-r--r--src/crypto/ec/ec_test.c124
-rw-r--r--src/crypto/ec/ec_test.cc185
-rw-r--r--src/crypto/ec/internal.h47
-rw-r--r--src/crypto/ec/oct.c39
-rw-r--r--src/crypto/ec/p256-64.c1936
-rw-r--r--src/crypto/ec/simple.c611
-rw-r--r--src/crypto/ec/util-64.c183
-rw-r--r--src/crypto/ec/wnaf.c180
-rw-r--r--src/crypto/ecdh/CMakeLists.txt1
-rw-r--r--src/crypto/ecdh/ecdh.c12
-rw-r--r--src/crypto/ecdh/ecdh_error.c25
-rw-r--r--src/crypto/ecdsa/CMakeLists.txt3
-rw-r--r--src/crypto/ecdsa/ecdsa.c56
-rw-r--r--src/crypto/ecdsa/ecdsa_asn1.c27
-rw-r--r--src/crypto/ecdsa/ecdsa_error.c32
-rw-r--r--src/crypto/ecdsa/ecdsa_test.c328
-rw-r--r--src/crypto/ecdsa/ecdsa_test.cc340
-rw-r--r--src/crypto/engine/CMakeLists.txt1
-rw-r--r--src/crypto/engine/engine.c42
-rw-r--r--src/crypto/engine/engine_error.c22
-rw-r--r--src/crypto/err/CMakeLists.txt35
-rw-r--r--src/crypto/err/asn1.errordata152
-rw-r--r--src/crypto/err/bio.errordata35
-rw-r--r--src/crypto/err/bn.errordata42
-rw-r--r--src/crypto/err/buf.errordata4
-rw-r--r--src/crypto/err/cipher.errordata60
-rw-r--r--src/crypto/err/conf.errordata10
-rw-r--r--src/crypto/err/crypto.errordata4
-rw-r--r--src/crypto/err/dh.errordata8
-rw-r--r--src/crypto/err/digest.errordata3
-rw-r--r--src/crypto/err/dsa.errordata9
-rw-r--r--src/crypto/err/ec.errordata93
-rw-r--r--src/crypto/err/ecdh.errordata4
-rw-r--r--src/crypto/err/ecdsa.errordata10
-rw-r--r--src/crypto/err/engine.errordata1
-rw-r--r--src/crypto/err/err.c456
-rw-r--r--src/crypto/err/err_data_generate.go287
-rw-r--r--src/crypto/err/err_impl.c323
-rw-r--r--src/crypto/err/err_test.cc (renamed from src/crypto/err/err_test.c)74
-rw-r--r--src/crypto/err/evp.errordata114
-rw-r--r--src/crypto/err/hkdf.errordata2
-rw-r--r--src/crypto/err/obj.errordata5
-rw-r--r--src/crypto/err/pem.errordata39
-rw-r--r--src/crypto/err/pkcs8.errordata43
-rw-r--r--src/crypto/err/rsa.errordata69
-rw-r--r--src/crypto/err/ssl.errordata376
-rw-r--r--src/crypto/err/x509.errordata96
-rw-r--r--src/crypto/err/x509v3.errordata120
-rw-r--r--src/crypto/evp/CMakeLists.txt14
-rw-r--r--src/crypto/evp/asn1.c2
-rw-r--r--src/crypto/evp/digestsign.c35
-rw-r--r--src/crypto/evp/evp.c42
-rw-r--r--src/crypto/evp/evp_ctx.c41
-rw-r--r--src/crypto/evp/evp_error.c131
-rw-r--r--src/crypto/evp/evp_extra_test.cc (renamed from src/crypto/evp/evp_test.c)524
-rw-r--r--src/crypto/evp/evp_test.cc262
-rw-r--r--src/crypto/evp/evp_tests.txt174
-rw-r--r--src/crypto/evp/internal.h43
-rw-r--r--src/crypto/evp/p_dsa_asn1.c569
-rw-r--r--src/crypto/evp/p_ec.c10
-rw-r--r--src/crypto/evp/p_ec_asn1.c65
-rw-r--r--src/crypto/evp/p_hmac.c3
-rw-r--r--src/crypto/evp/p_rsa.c65
-rw-r--r--src/crypto/evp/p_rsa_asn1.c42
-rw-r--r--src/crypto/evp/pbkdf_test.cc179
-rw-r--r--src/crypto/evp/sign.c10
-rw-r--r--src/crypto/ex_data.c196
-rw-r--r--src/crypto/ex_data_impl.c401
-rw-r--r--src/crypto/hkdf/CMakeLists.txt1
-rw-r--r--src/crypto/hkdf/hkdf_error.c23
-rw-r--r--src/crypto/hkdf/hkdf_test.c3
-rw-r--r--src/crypto/hmac/CMakeLists.txt3
-rw-r--r--src/crypto/hmac/hmac.c72
-rw-r--r--src/crypto/hmac/hmac_test.c223
-rw-r--r--src/crypto/hmac/hmac_test.cc171
-rw-r--r--src/crypto/hmac/hmac_tests.txt102
-rw-r--r--src/crypto/internal.h241
-rw-r--r--src/crypto/lhash/make_macros.sh11
-rw-r--r--src/crypto/md4/md4.c1
-rw-r--r--src/crypto/modes/asm/ghash-armv4.pl49
-rw-r--r--src/crypto/modes/asm/ghash-x86.pl4
-rw-r--r--src/crypto/modes/asm/ghashv8-armx.pl291
-rw-r--r--src/crypto/modes/cbc.c6
-rw-r--r--src/crypto/modes/ctr.c12
-rw-r--r--src/crypto/modes/gcm.c21
-rw-r--r--src/crypto/modes/gcm_test.c32
-rw-r--r--src/crypto/modes/internal.h3
-rw-r--r--src/crypto/obj/CMakeLists.txt1
-rw-r--r--src/crypto/obj/obj.c69
-rw-r--r--src/crypto/obj/obj_error.c26
-rw-r--r--src/crypto/pem/CMakeLists.txt1
-rw-r--r--src/crypto/pem/pem_error.c73
-rw-r--r--src/crypto/pem/pem_lib.c3
-rw-r--r--src/crypto/pem/pem_pk8.c1
-rwxr-xr-xsrc/crypto/perlasm/arm-xlate.pl165
-rwxr-xr-xsrc/crypto/perlasm/ppc-xlate.pl167
-rw-r--r--src/crypto/perlasm/sparcv9_modes.pl1680
-rw-r--r--src/crypto/perlasm/x86masm.pl15
-rw-r--r--src/crypto/pkcs8/CMakeLists.txt3
-rw-r--r--src/crypto/pkcs8/pkcs12_test.cc (renamed from src/crypto/pkcs8/pkcs12_test.c)88
-rw-r--r--src/crypto/pkcs8/pkcs8.c98
-rw-r--r--src/crypto/pkcs8/pkcs8_error.c68
-rw-r--r--src/crypto/poly1305/poly1305.c24
-rw-r--r--src/crypto/poly1305/poly1305_arm.c33
-rw-r--r--src/crypto/poly1305/poly1305_vec.c15
-rw-r--r--src/crypto/rand/CMakeLists.txt13
-rw-r--r--src/crypto/rand/asm/rdrand-x86_64.pl25
-rw-r--r--src/crypto/rand/hwrand.c56
-rw-r--r--src/crypto/rand/internal.h40
-rw-r--r--src/crypto/rand/rand.c128
-rw-r--r--src/crypto/rand/urandom.c58
-rw-r--r--src/crypto/rand/windows.c8
-rw-r--r--src/crypto/rc4/asm/rc4-x86_64.pl26
-rw-r--r--src/crypto/rc4/rc4.c67
-rw-r--r--src/crypto/rsa/CMakeLists.txt1
-rw-r--r--src/crypto/rsa/blinding.c36
-rw-r--r--src/crypto/rsa/internal.h3
-rw-r--r--src/crypto/rsa/padding.c19
-rw-r--r--src/crypto/rsa/rsa.c123
-rw-r--r--src/crypto/rsa/rsa_error.c95
-rw-r--r--src/crypto/rsa/rsa_impl.c184
-rw-r--r--src/crypto/rsa/rsa_test.c37
-rw-r--r--src/crypto/sha/asm/sha1-586.pl2
-rw-r--r--src/crypto/sha/asm/sha1-armv4-large.pl23
-rw-r--r--src/crypto/sha/asm/sha1-armv8.pl17
-rw-r--r--src/crypto/sha/asm/sha256-armv4.pl101
-rw-r--r--src/crypto/sha/asm/sha512-armv4.pl100
-rw-r--r--src/crypto/sha/asm/sha512-armv8.pl35
-rw-r--r--src/crypto/sha/sha1.c3
-rw-r--r--src/crypto/sha/sha512.c24
-rw-r--r--src/crypto/stack/make_macros.sh3
-rw-r--r--src/crypto/stack/stack.c38
-rw-r--r--src/crypto/test/CMakeLists.txt7
-rw-r--r--src/crypto/test/file_test.cc326
-rw-r--r--src/crypto/test/file_test.h166
-rw-r--r--src/crypto/test/scoped_types.h120
-rw-r--r--src/crypto/test/stl_compat.h144
-rw-r--r--src/crypto/thread.c74
-rw-r--r--src/crypto/thread_none.c55
-rw-r--r--src/crypto/thread_pthread.c162
-rw-r--r--src/crypto/thread_test.c202
-rw-r--r--src/crypto/thread_win.c282
-rw-r--r--src/crypto/time_support.c12
-rw-r--r--src/crypto/x509/CMakeLists.txt1
-rw-r--r--src/crypto/x509/asn1_gen.c73
-rw-r--r--src/crypto/x509/by_dir.c7
-rw-r--r--src/crypto/x509/by_file.c5
-rw-r--r--src/crypto/x509/i2d_pr.c7
-rw-r--r--src/crypto/x509/pkcs7.c1
-rw-r--r--src/crypto/x509/pkcs7_test.c1
-rw-r--r--src/crypto/x509/vpm_int.h6
-rw-r--r--src/crypto/x509/x509_att.c2
-rw-r--r--src/crypto/x509/x509_error.c128
-rw-r--r--src/crypto/x509/x509_lu.c5
-rw-r--r--src/crypto/x509/x509_req.c2
-rw-r--r--src/crypto/x509/x509_v3.c2
-rw-r--r--src/crypto/x509/x509_vfy.c95
-rw-r--r--src/crypto/x509/x509_vpm.c126
-rw-r--r--src/crypto/x509/x_crl.c1
-rw-r--r--src/crypto/x509/x_info.c1
-rw-r--r--src/crypto/x509/x_name.c29
-rw-r--r--src/crypto/x509/x_pkey.c3
-rw-r--r--src/crypto/x509/x_pubkey.c5
-rw-r--r--src/crypto/x509/x_x509.c29
-rw-r--r--src/crypto/x509v3/CMakeLists.txt4
-rw-r--r--src/crypto/x509v3/tabtest.c9
-rw-r--r--src/crypto/x509v3/v3_alt.c2
-rw-r--r--src/crypto/x509v3/v3_conf.c76
-rw-r--r--src/crypto/x509v3/v3_cpols.c14
-rw-r--r--src/crypto/x509v3/v3_purp.c3
-rw-r--r--src/crypto/x509v3/v3_utl.c88
-rw-r--r--src/crypto/x509v3/v3nametest.c11
-rw-r--r--src/crypto/x509v3/x509v3_error.c147
288 files changed, 17713 insertions, 11388 deletions
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index cb8f63a..6433dc6 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -2,7 +2,7 @@ include_directories(. ../include)
if(APPLE)
if (${ARCH} STREQUAL "x86")
- set(PERLASM_FLAGS "-fPIC")
+ set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
endif()
set(PERLASM_STYLE macosx)
set(ASM_EXT S)
@@ -12,8 +12,10 @@ elseif(UNIX)
# The "armx" Perl scripts look for "64" in the style argument
# in order to decide whether to generate 32- or 64-bit asm.
set(PERLASM_STYLE linux64)
+ elseif (${ARCH} STREQUAL "arm")
+ set(PERLASM_STYLE linux32)
elseif (${ARCH} STREQUAL "x86")
- set(PERLASM_FLAGS "-fPIC")
+ set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
set(PERLASM_STYLE elf)
else()
set(PERLASM_STYLE elf)
@@ -27,6 +29,7 @@ else()
else()
message("Using win32n")
set(PERLASM_STYLE win32n)
+ set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2")
endif()
# On Windows, we use the NASM output, specifically built with Yasm.
@@ -37,9 +40,10 @@ endif()
function(perlasm dest src)
add_custom_command(
OUTPUT ${dest}
- COMMAND perl ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest}
+ COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest}
DEPENDS
${src}
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/arm-xlate.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl
@@ -72,6 +76,7 @@ if (${ARCH} STREQUAL "arm")
CRYPTO_ARCH_SOURCES
cpu-arm.c
+ cpu-arm-asm.S
)
endif()
@@ -123,6 +128,7 @@ add_subdirectory(ecdsa)
add_subdirectory(hmac)
# Level 3
+add_subdirectory(cmac)
add_subdirectory(evp)
add_subdirectory(hkdf)
add_subdirectory(pem)
@@ -132,15 +138,19 @@ add_subdirectory(x509v3)
# Level 4
add_subdirectory(pkcs8)
+# Test support code
+add_subdirectory(test)
+
add_library(
crypto
crypto.c
- crypto_error.c
mem.c
thread.c
+ thread_none.c
+ thread_pthread.c
+ thread_win.c
ex_data.c
- ex_data_impl.c
time_support.c
directory_posix.c
directory_win.c
@@ -178,6 +188,7 @@ add_library(
$<TARGET_OBJECTS:ecdh>
$<TARGET_OBJECTS:ecdsa>
$<TARGET_OBJECTS:hmac>
+ $<TARGET_OBJECTS:cmac>
$<TARGET_OBJECTS:evp>
$<TARGET_OBJECTS:hkdf>
$<TARGET_OBJECTS:pem>
@@ -186,6 +197,10 @@ add_library(
$<TARGET_OBJECTS:pkcs8>
)
+if(NOT MSVC AND NOT ANDROID)
+ target_link_libraries(crypto pthread)
+endif()
+
add_executable(
constant_time_test
@@ -194,5 +209,13 @@ add_executable(
target_link_libraries(constant_time_test crypto)
+add_executable(
+ thread_test
+
+ thread_test.c
+)
+
+target_link_libraries(thread_test crypto)
+
perlasm(cpu-x86_64-asm.${ASM_EXT} cpu-x86_64-asm.pl)
perlasm(cpu-x86-asm.${ASM_EXT} cpu-x86-asm.pl)
diff --git a/src/crypto/aes/aes.c b/src/crypto/aes/aes.c
index 97b4fbd..933aa07 100644
--- a/src/crypto/aes/aes.c
+++ b/src/crypto/aes/aes.c
@@ -1033,17 +1033,25 @@ void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
#endif /* ?FULL_UNROLL */
/* apply last round and
* map cipher state to byte array block: */
- s0 = (Td4[(t0 >> 24)] << 24) ^ (Td4[(t3 >> 16) & 0xff] << 16) ^
- (Td4[(t2 >> 8) & 0xff] << 8) ^ (Td4[(t1) & 0xff]) ^ rk[0];
+ s0 = ((uint32_t)Td4[(t0 >> 24)] << 24) ^
+ ((uint32_t)Td4[(t3 >> 16) & 0xff] << 16) ^
+ ((uint32_t)Td4[(t2 >> 8) & 0xff] << 8) ^
+ ((uint32_t)Td4[(t1) & 0xff]) ^ rk[0];
PUTU32(out, s0);
- s1 = (Td4[(t1 >> 24)] << 24) ^ (Td4[(t0 >> 16) & 0xff] << 16) ^
- (Td4[(t3 >> 8) & 0xff] << 8) ^ (Td4[(t2) & 0xff]) ^ rk[1];
+ s1 = ((uint32_t)Td4[(t1 >> 24)] << 24) ^
+ ((uint32_t)Td4[(t0 >> 16) & 0xff] << 16) ^
+ ((uint32_t)Td4[(t3 >> 8) & 0xff] << 8) ^
+ ((uint32_t)Td4[(t2) & 0xff]) ^ rk[1];
PUTU32(out + 4, s1);
- s2 = (Td4[(t2 >> 24)] << 24) ^ (Td4[(t1 >> 16) & 0xff] << 16) ^
- (Td4[(t0 >> 8) & 0xff] << 8) ^ (Td4[(t3) & 0xff]) ^ rk[2];
+ s2 = ((uint32_t)Td4[(t2 >> 24)] << 24) ^
+ ((uint32_t)Td4[(t1 >> 16) & 0xff] << 16) ^
+ ((uint32_t)Td4[(t0 >> 8) & 0xff] << 8) ^
+ ((uint32_t)Td4[(t3) & 0xff]) ^ rk[2];
PUTU32(out + 8, s2);
- s3 = (Td4[(t3 >> 24)] << 24) ^ (Td4[(t2 >> 16) & 0xff] << 16) ^
- (Td4[(t1 >> 8) & 0xff] << 8) ^ (Td4[(t0) & 0xff]) ^ rk[3];
+ s3 = ((uint32_t)Td4[(t3 >> 24)] << 24) ^
+ ((uint32_t)Td4[(t2 >> 16) & 0xff] << 16) ^
+ ((uint32_t)Td4[(t1 >> 8) & 0xff] << 8) ^
+ ((uint32_t)Td4[(t0) & 0xff]) ^ rk[3];
PUTU32(out + 12, s3);
}
diff --git a/src/crypto/aes/asm/aes-armv4.pl b/src/crypto/aes/asm/aes-armv4.pl
index 3bd9a6d..36cd3b6 100644
--- a/src/crypto/aes/asm/aes-armv4.pl
+++ b/src/crypto/aes/asm/aes-armv4.pl
@@ -32,8 +32,20 @@
# Profiler-assisted and platform-specific optimization resulted in 16%
# improvement on Cortex A8 core and ~21.5 cycles per byte.
-while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
$s0="r0";
$s1="r1";
@@ -63,7 +75,7 @@ $code=<<___;
.code 32
#else
.syntax unified
-# ifdef __thumb2__
+# if defined(__thumb2__) && !defined(__APPLE__)
.thumb
# else
.code 32
@@ -189,9 +201,13 @@ asm_AES_encrypt:
adr r3,asm_AES_encrypt
#endif
stmdb sp!,{r1,r4-r12,lr}
+#ifdef __APPLE__
+ adr $tbl,AES_Te
+#else
+ sub $tbl,r3,#asm_AES_encrypt-AES_Te @ Te
+#endif
mov $rounds,r0 @ inp
mov $key,r2
- sub $tbl,r3,#asm_AES_encrypt-AES_Te @ Te
#if __ARM_ARCH__<7
ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
ldrb $t1,[$rounds,#2] @ manner...
@@ -460,12 +476,16 @@ _armv4_AES_set_encrypt_key:
bne .Labrt
.Lok: stmdb sp!,{r4-r12,lr}
- sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4
-
mov $rounds,r0 @ inp
mov lr,r1 @ bits
mov $key,r2 @ key
+#ifdef __APPLE__
+ adr $tbl,AES_Te+1024 @ Te4
+#else
+ sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4
+#endif
+
#if __ARM_ARCH__<7
ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
ldrb $t1,[$rounds,#2] @ manner...
@@ -718,8 +738,8 @@ _armv4_AES_set_encrypt_key:
.Ldone: mov r0,#0
ldmia sp!,{r4-r12,lr}
.Labrt:
-#if defined(__thumb2__) && __ARM_ARCH__>=7
- .short 0x4770 @ bx lr in Thumb2 encoding
+#if __ARM_ARCH__>=5
+ ret @ bx lr
#else
tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
@@ -961,9 +981,13 @@ asm_AES_decrypt:
adr r3,asm_AES_decrypt
#endif
stmdb sp!,{r1,r4-r12,lr}
+#ifdef __APPLE__
+ adr $tbl,AES_Td
+#else
+ sub $tbl,r3,#asm_AES_decrypt-AES_Td @ Td
+#endif
mov $rounds,r0 @ inp
mov $key,r2
- sub $tbl,r3,#asm_AES_decrypt-AES_Td @ Td
#if __ARM_ARCH__<7
ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
ldrb $t1,[$rounds,#2] @ manner...
@@ -1211,6 +1235,7 @@ _armv4_AES_decrypt:
___
$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
+$code =~ s/\bret\b/bx\tlr/gm;
open SELF,$0;
while(<SELF>) {
diff --git a/src/crypto/aes/asm/aesni-x86.pl b/src/crypto/aes/asm/aesni-x86.pl
index 3deb86a..f67df8c 100644
--- a/src/crypto/aes/asm/aesni-x86.pl
+++ b/src/crypto/aes/asm/aesni-x86.pl
@@ -51,7 +51,7 @@
# Westmere 3.77/1.37 1.37 1.52 1.27
# * Bridge 5.07/0.98 0.99 1.09 0.91
# Haswell 4.44/0.80 0.97 1.03 0.72
-# Atom 5.77/3.56 3.67 4.03 3.46
+# Silvermont 5.77/3.56 3.67 4.03 3.46
# Bulldozer 5.80/0.98 1.05 1.24 0.93
$PREFIX="aesni"; # if $PREFIX is set to "AES", the script
@@ -65,6 +65,9 @@ require "x86asm.pl";
&asm_init($ARGV[0],$0);
+&external_label("OPENSSL_ia32cap_P");
+&static_label("key_const");
+
if ($PREFIX eq "aesni") { $movekey=\&movups; }
else { $movekey=\&movups; }
@@ -181,7 +184,10 @@ sub aesni_generate1 # fully unrolled loop
{ &aesni_inline_generate1("enc"); }
else
{ &call ("_aesni_encrypt1"); }
+ &pxor ($rndkey0,$rndkey0); # clear register bank
+ &pxor ($rndkey1,$rndkey1);
&movups (&QWP(0,"eax"),$inout0);
+ &pxor ($inout0,$inout0);
&ret ();
&function_end_B("${PREFIX}_encrypt");
@@ -197,7 +203,10 @@ sub aesni_generate1 # fully unrolled loop
{ &aesni_inline_generate1("dec"); }
else
{ &call ("_aesni_decrypt1"); }
+ &pxor ($rndkey0,$rndkey0); # clear register bank
+ &pxor ($rndkey1,$rndkey1);
&movups (&QWP(0,"eax"),$inout0);
+ &pxor ($inout0,$inout0);
&ret ();
&function_end_B("${PREFIX}_decrypt");
@@ -349,17 +358,15 @@ sub aesni_generate6
&neg ($rounds);
eval"&aes${p} ($inout2,$rndkey1)";
&pxor ($inout5,$rndkey0);
+ &$movekey ($rndkey0,&QWP(0,$key,$rounds));
&add ($rounds,16);
- eval"&aes${p} ($inout3,$rndkey1)";
- eval"&aes${p} ($inout4,$rndkey1)";
- eval"&aes${p} ($inout5,$rndkey1)";
- &$movekey ($rndkey0,&QWP(-16,$key,$rounds));
- &jmp (&label("_aesni_${p}rypt6_enter"));
+ &jmp (&label("_aesni_${p}rypt6_inner"));
&set_label("${p}6_loop",16);
eval"&aes${p} ($inout0,$rndkey1)";
eval"&aes${p} ($inout1,$rndkey1)";
eval"&aes${p} ($inout2,$rndkey1)";
+ &set_label("_aesni_${p}rypt6_inner");
eval"&aes${p} ($inout3,$rndkey1)";
eval"&aes${p} ($inout4,$rndkey1)";
eval"&aes${p} ($inout5,$rndkey1)";
@@ -615,6 +622,14 @@ if ($PREFIX eq "aesni") {
&movups (&QWP(0x30,$out),$inout3);
&set_label("ecb_ret");
+ &pxor ("xmm0","xmm0"); # clear register bank
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &pxor ("xmm3","xmm3");
+ &pxor ("xmm4","xmm4");
+ &pxor ("xmm5","xmm5");
+ &pxor ("xmm6","xmm6");
+ &pxor ("xmm7","xmm7");
&function_end("aesni_ecb_encrypt");
######################################################################
@@ -704,6 +719,15 @@ if ($PREFIX eq "aesni") {
&mov ("esp",&DWP(48,"esp"));
&mov ($out,&wparam(5));
&movups (&QWP(0,$out),$cmac);
+
+ &pxor ("xmm0","xmm0"); # clear register bank
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &pxor ("xmm3","xmm3");
+ &pxor ("xmm4","xmm4");
+ &pxor ("xmm5","xmm5");
+ &pxor ("xmm6","xmm6");
+ &pxor ("xmm7","xmm7");
&function_end("aesni_ccm64_encrypt_blocks");
&function_begin("aesni_ccm64_decrypt_blocks");
@@ -804,6 +828,15 @@ if ($PREFIX eq "aesni") {
&mov ("esp",&DWP(48,"esp"));
&mov ($out,&wparam(5));
&movups (&QWP(0,$out),$cmac);
+
+ &pxor ("xmm0","xmm0"); # clear register bank
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &pxor ("xmm3","xmm3");
+ &pxor ("xmm4","xmm4");
+ &pxor ("xmm5","xmm5");
+ &pxor ("xmm6","xmm6");
+ &pxor ("xmm7","xmm7");
&function_end("aesni_ccm64_decrypt_blocks");
}
@@ -1053,6 +1086,17 @@ if ($PREFIX eq "aesni") {
&movups (&QWP(0x30,$out),$inout3);
&set_label("ctr32_ret");
+ &pxor ("xmm0","xmm0"); # clear register bank
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &pxor ("xmm3","xmm3");
+ &pxor ("xmm4","xmm4");
+ &movdqa (&QWP(32,"esp"),"xmm0"); # clear stack
+ &pxor ("xmm5","xmm5");
+ &movdqa (&QWP(48,"esp"),"xmm0");
+ &pxor ("xmm6","xmm6");
+ &movdqa (&QWP(64,"esp"),"xmm0");
+ &pxor ("xmm7","xmm7");
&mov ("esp",&DWP(80,"esp"));
&function_end("aesni_ctr32_encrypt_blocks");
@@ -1394,6 +1438,20 @@ if ($PREFIX eq "aesni") {
&movups (&QWP(-16,$out),$inout0); # write output
&set_label("xts_enc_ret");
+ &pxor ("xmm0","xmm0"); # clear register bank
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack
+ &pxor ("xmm3","xmm3");
+ &movdqa (&QWP(16*1,"esp"),"xmm0");
+ &pxor ("xmm4","xmm4");
+ &movdqa (&QWP(16*2,"esp"),"xmm0");
+ &pxor ("xmm5","xmm5");
+ &movdqa (&QWP(16*3,"esp"),"xmm0");
+ &pxor ("xmm6","xmm6");
+ &movdqa (&QWP(16*4,"esp"),"xmm0");
+ &pxor ("xmm7","xmm7");
+ &movdqa (&QWP(16*5,"esp"),"xmm0");
&mov ("esp",&DWP(16*7+4,"esp")); # restore %esp
&function_end("aesni_xts_encrypt");
@@ -1756,6 +1814,20 @@ if ($PREFIX eq "aesni") {
&movups (&QWP(0,$out),$inout0); # write output
&set_label("xts_dec_ret");
+ &pxor ("xmm0","xmm0"); # clear register bank
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack
+ &pxor ("xmm3","xmm3");
+ &movdqa (&QWP(16*1,"esp"),"xmm0");
+ &pxor ("xmm4","xmm4");
+ &movdqa (&QWP(16*2,"esp"),"xmm0");
+ &pxor ("xmm5","xmm5");
+ &movdqa (&QWP(16*3,"esp"),"xmm0");
+ &pxor ("xmm6","xmm6");
+ &movdqa (&QWP(16*4,"esp"),"xmm0");
+ &pxor ("xmm7","xmm7");
+ &movdqa (&QWP(16*5,"esp"),"xmm0");
&mov ("esp",&DWP(16*7+4,"esp")); # restore %esp
&function_end("aesni_xts_decrypt");
}
@@ -1808,6 +1880,7 @@ if ($PREFIX eq "aesni") {
&add ($len,16);
&jnz (&label("cbc_enc_tail"));
&movaps ($ivec,$inout0);
+ &pxor ($inout0,$inout0);
&jmp (&label("cbc_ret"));
&set_label("cbc_enc_tail");
@@ -1871,7 +1944,7 @@ if ($PREFIX eq "aesni") {
&movaps ($inout0,$inout5);
&movaps ($ivec,$rndkey0);
&add ($len,0x50);
- &jle (&label("cbc_dec_tail_collected"));
+ &jle (&label("cbc_dec_clear_tail_collected"));
&movups (&QWP(0,$out),$inout0);
&lea ($out,&DWP(0x10,$out));
&set_label("cbc_dec_tail");
@@ -1910,10 +1983,14 @@ if ($PREFIX eq "aesni") {
&xorps ($inout4,$rndkey0);
&movups (&QWP(0,$out),$inout0);
&movups (&QWP(0x10,$out),$inout1);
+ &pxor ($inout1,$inout1);
&movups (&QWP(0x20,$out),$inout2);
+ &pxor ($inout2,$inout2);
&movups (&QWP(0x30,$out),$inout3);
+ &pxor ($inout3,$inout3);
&lea ($out,&DWP(0x40,$out));
&movaps ($inout0,$inout4);
+ &pxor ($inout4,$inout4);
&sub ($len,0x50);
&jmp (&label("cbc_dec_tail_collected"));
@@ -1933,6 +2010,7 @@ if ($PREFIX eq "aesni") {
&xorps ($inout1,$in0);
&movups (&QWP(0,$out),$inout0);
&movaps ($inout0,$inout1);
+ &pxor ($inout1,$inout1);
&lea ($out,&DWP(0x10,$out));
&movaps ($ivec,$in1);
&sub ($len,0x20);
@@ -1945,7 +2023,9 @@ if ($PREFIX eq "aesni") {
&xorps ($inout2,$in1);
&movups (&QWP(0,$out),$inout0);
&movaps ($inout0,$inout2);
+ &pxor ($inout2,$inout2);
&movups (&QWP(0x10,$out),$inout1);
+ &pxor ($inout1,$inout1);
&lea ($out,&DWP(0x20,$out));
&movups ($ivec,&QWP(0x20,$inp));
&sub ($len,0x30);
@@ -1961,29 +2041,44 @@ if ($PREFIX eq "aesni") {
&movups (&QWP(0,$out),$inout0);
&xorps ($inout2,$rndkey1);
&movups (&QWP(0x10,$out),$inout1);
+ &pxor ($inout1,$inout1);
&xorps ($inout3,$rndkey0);
&movups (&QWP(0x20,$out),$inout2);
+ &pxor ($inout2,$inout2);
&lea ($out,&DWP(0x30,$out));
&movaps ($inout0,$inout3);
+ &pxor ($inout3,$inout3);
&sub ($len,0x40);
+ &jmp (&label("cbc_dec_tail_collected"));
+&set_label("cbc_dec_clear_tail_collected",16);
+ &pxor ($inout1,$inout1);
+ &pxor ($inout2,$inout2);
+ &pxor ($inout3,$inout3);
+ &pxor ($inout4,$inout4);
&set_label("cbc_dec_tail_collected");
&and ($len,15);
&jnz (&label("cbc_dec_tail_partial"));
&movups (&QWP(0,$out),$inout0);
+ &pxor ($rndkey0,$rndkey0);
&jmp (&label("cbc_ret"));
&set_label("cbc_dec_tail_partial",16);
&movaps (&QWP(0,"esp"),$inout0);
+ &pxor ($rndkey0,$rndkey0);
&mov ("ecx",16);
&mov ($inp,"esp");
&sub ("ecx",$len);
&data_word(0xA4F3F689); # rep movsb
+ &movdqa (&QWP(0,"esp"),$inout0);
&set_label("cbc_ret");
&mov ("esp",&DWP(16,"esp")); # pull original %esp
&mov ($key_,&wparam(4));
+ &pxor ($inout0,$inout0);
+ &pxor ($rndkey1,$rndkey1);
&movups (&QWP(0,$key_),$ivec); # output IV
+ &pxor ($ivec,$ivec);
&set_label("cbc_abort");
&function_end("${PREFIX}_cbc_encrypt");
@@ -2000,14 +2095,24 @@ if ($PREFIX eq "aesni") {
# $round rounds
&function_begin_B("_aesni_set_encrypt_key");
+ &push ("ebp");
+ &push ("ebx");
&test ("eax","eax");
&jz (&label("bad_pointer"));
&test ($key,$key);
&jz (&label("bad_pointer"));
+ &call (&label("pic"));
+&set_label("pic");
+ &blindpop("ebx");
+ &lea ("ebx",&DWP(&label("key_const")."-".&label("pic"),"ebx"));
+
+ &picmeup("ebp","OPENSSL_ia32cap_P","ebx",&label("key_const"));
&movups ("xmm0",&QWP(0,"eax")); # pull first 128 bits of *userKey
&xorps ("xmm4","xmm4"); # low dword of xmm4 is assumed 0
+ &mov ("ebp",&DWP(4,"ebp"));
&lea ($key,&DWP(16,$key));
+ &and ("ebp",1<<28|1<<11); # AVX and XOP bits
&cmp ($rounds,256);
&je (&label("14rounds"));
&cmp ($rounds,192);
@@ -2016,6 +2121,9 @@ if ($PREFIX eq "aesni") {
&jne (&label("bad_keybits"));
&set_label("10rounds",16);
+ &cmp ("ebp",1<<28);
+ &je (&label("10rounds_alt"));
+
&mov ($rounds,9);
&$movekey (&QWP(-16,$key),"xmm0"); # round 0
&aeskeygenassist("xmm1","xmm0",0x01); # round 1
@@ -2040,8 +2148,8 @@ if ($PREFIX eq "aesni") {
&call (&label("key_128"));
&$movekey (&QWP(0,$key),"xmm0");
&mov (&DWP(80,$key),$rounds);
- &xor ("eax","eax");
- &ret();
+
+ &jmp (&label("good_key"));
&set_label("key_128",16);
&$movekey (&QWP(0,$key),"xmm0");
@@ -2055,8 +2163,76 @@ if ($PREFIX eq "aesni") {
&xorps ("xmm0","xmm1");
&ret();
+&set_label("10rounds_alt",16);
+ &movdqa ("xmm5",&QWP(0x00,"ebx"));
+ &mov ($rounds,8);
+ &movdqa ("xmm4",&QWP(0x20,"ebx"));
+ &movdqa ("xmm2","xmm0");
+ &movdqu (&QWP(-16,$key),"xmm0");
+
+&set_label("loop_key128");
+ &pshufb ("xmm0","xmm5");
+ &aesenclast ("xmm0","xmm4");
+ &pslld ("xmm4",1);
+ &lea ($key,&DWP(16,$key));
+
+ &movdqa ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm2","xmm3");
+
+ &pxor ("xmm0","xmm2");
+ &movdqu (&QWP(-16,$key),"xmm0");
+ &movdqa ("xmm2","xmm0");
+
+ &dec ($rounds);
+ &jnz (&label("loop_key128"));
+
+ &movdqa ("xmm4",&QWP(0x30,"ebx"));
+
+ &pshufb ("xmm0","xmm5");
+ &aesenclast ("xmm0","xmm4");
+ &pslld ("xmm4",1);
+
+ &movdqa ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm2","xmm3");
+
+ &pxor ("xmm0","xmm2");
+ &movdqu (&QWP(0,$key),"xmm0");
+
+ &movdqa ("xmm2","xmm0");
+ &pshufb ("xmm0","xmm5");
+ &aesenclast ("xmm0","xmm4");
+
+ &movdqa ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm3","xmm2");
+ &pslldq ("xmm2",4);
+ &pxor ("xmm2","xmm3");
+
+ &pxor ("xmm0","xmm2");
+ &movdqu (&QWP(16,$key),"xmm0");
+
+ &mov ($rounds,9);
+ &mov (&DWP(96,$key),$rounds);
+
+ &jmp (&label("good_key"));
+
&set_label("12rounds",16);
&movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey
+ &cmp ("ebp",1<<28);
+ &je (&label("12rounds_alt"));
+
&mov ($rounds,11);
&$movekey (&QWP(-16,$key),"xmm0"); # round 0
&aeskeygenassist("xmm1","xmm2",0x01); # round 1,2
@@ -2077,8 +2253,8 @@ if ($PREFIX eq "aesni") {
&call (&label("key_192b"));
&$movekey (&QWP(0,$key),"xmm0");
&mov (&DWP(48,$key),$rounds);
- &xor ("eax","eax");
- &ret();
+
+ &jmp (&label("good_key"));
&set_label("key_192a",16);
&$movekey (&QWP(0,$key),"xmm0");
@@ -2108,10 +2284,52 @@ if ($PREFIX eq "aesni") {
&lea ($key,&DWP(32,$key));
&jmp (&label("key_192b_warm"));
+&set_label("12rounds_alt",16);
+ &movdqa ("xmm5",&QWP(0x10,"ebx"));
+ &movdqa ("xmm4",&QWP(0x20,"ebx"));
+ &mov ($rounds,8);
+ &movdqu (&QWP(-16,$key),"xmm0");
+
+&set_label("loop_key192");
+ &movq (&QWP(0,$key),"xmm2");
+ &movdqa ("xmm1","xmm2");
+ &pshufb ("xmm2","xmm5");
+ &aesenclast ("xmm2","xmm4");
+ &pslld ("xmm4",1);
+ &lea ($key,&DWP(24,$key));
+
+ &movdqa ("xmm3","xmm0");
+ &pslldq ("xmm0",4);
+ &pxor ("xmm3","xmm0");
+ &pslldq ("xmm0",4);
+ &pxor ("xmm3","xmm0");
+ &pslldq ("xmm0",4);
+ &pxor ("xmm0","xmm3");
+
+ &pshufd ("xmm3","xmm0",0xff);
+ &pxor ("xmm3","xmm1");
+ &pslldq ("xmm1",4);
+ &pxor ("xmm3","xmm1");
+
+ &pxor ("xmm0","xmm2");
+ &pxor ("xmm2","xmm3");
+ &movdqu (&QWP(-16,$key),"xmm0");
+
+ &dec ($rounds);
+ &jnz (&label("loop_key192"));
+
+ &mov ($rounds,11);
+ &mov (&DWP(32,$key),$rounds);
+
+ &jmp (&label("good_key"));
+
&set_label("14rounds",16);
&movups ("xmm2",&QWP(16,"eax")); # remaining half of *userKey
- &mov ($rounds,13);
&lea ($key,&DWP(16,$key));
+ &cmp ("ebp",1<<28);
+ &je (&label("14rounds_alt"));
+
+ &mov ($rounds,13);
&$movekey (&QWP(-32,$key),"xmm0"); # round 0
&$movekey (&QWP(-16,$key),"xmm2"); # round 1
&aeskeygenassist("xmm1","xmm2",0x01); # round 2
@@ -2143,7 +2361,8 @@ if ($PREFIX eq "aesni") {
&$movekey (&QWP(0,$key),"xmm0");
&mov (&DWP(16,$key),$rounds);
&xor ("eax","eax");
- &ret();
+
+ &jmp (&label("good_key"));
&set_label("key_256a",16);
&$movekey (&QWP(0,$key),"xmm2");
@@ -2169,11 +2388,77 @@ if ($PREFIX eq "aesni") {
&xorps ("xmm2","xmm1");
&ret();
+&set_label("14rounds_alt",16);
+ &movdqa ("xmm5",&QWP(0x00,"ebx"));
+ &movdqa ("xmm4",&QWP(0x20,"ebx"));
+ &mov ($rounds,7);
+ &movdqu (&QWP(-32,$key),"xmm0");
+ &movdqa ("xmm1","xmm2");
+ &movdqu (&QWP(-16,$key),"xmm2");
+
+&set_label("loop_key256");
+ &pshufb ("xmm2","xmm5");
+ &aesenclast ("xmm2","xmm4");
+
+ &movdqa ("xmm3","xmm0");
+ &pslldq ("xmm0",4);
+ &pxor ("xmm3","xmm0");
+ &pslldq ("xmm0",4);
+ &pxor ("xmm3","xmm0");
+ &pslldq ("xmm0",4);
+ &pxor ("xmm0","xmm3");
+ &pslld ("xmm4",1);
+
+ &pxor ("xmm0","xmm2");
+ &movdqu (&QWP(0,$key),"xmm0");
+
+ &dec ($rounds);
+ &jz (&label("done_key256"));
+
+ &pshufd ("xmm2","xmm0",0xff);
+ &pxor ("xmm3","xmm3");
+ &aesenclast ("xmm2","xmm3");
+
+ &movdqa ("xmm3","xmm1")
+ &pslldq ("xmm1",4);
+ &pxor ("xmm3","xmm1");
+ &pslldq ("xmm1",4);
+ &pxor ("xmm3","xmm1");
+ &pslldq ("xmm1",4);
+ &pxor ("xmm1","xmm3");
+
+ &pxor ("xmm2","xmm1");
+ &movdqu (&QWP(16,$key),"xmm2");
+ &lea ($key,&DWP(32,$key));
+ &movdqa ("xmm1","xmm2");
+ &jmp (&label("loop_key256"));
+
+&set_label("done_key256");
+ &mov ($rounds,13);
+ &mov (&DWP(16,$key),$rounds);
+
+&set_label("good_key");
+ &pxor ("xmm0","xmm0");
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &pxor ("xmm3","xmm3");
+ &pxor ("xmm4","xmm4");
+ &pxor ("xmm5","xmm5");
+ &xor ("eax","eax");
+ &pop ("ebx");
+ &pop ("ebp");
+ &ret ();
+
&set_label("bad_pointer",4);
&mov ("eax",-1);
+ &pop ("ebx");
+ &pop ("ebp");
&ret ();
&set_label("bad_keybits",4);
+ &pxor ("xmm0","xmm0");
&mov ("eax",-2);
+ &pop ("ebx");
+ &pop ("ebp");
&ret ();
&function_end_B("_aesni_set_encrypt_key");
@@ -2223,10 +2508,18 @@ if ($PREFIX eq "aesni") {
&aesimc ("xmm0","xmm0");
&$movekey (&QWP(0,$key),"xmm0");
+ &pxor ("xmm0","xmm0");
+ &pxor ("xmm1","xmm1");
&xor ("eax","eax"); # return success
&set_label("dec_key_ret");
&ret ();
&function_end_B("${PREFIX}_set_decrypt_key");
+
+&set_label("key_const",64);
+&data_word(0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d);
+&data_word(0x04070605,0x04070605,0x04070605,0x04070605);
+&data_word(1,1,1,1);
+&data_word(0x1b,0x1b,0x1b,0x1b);
&asciz("AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>");
&asm_finish();
diff --git a/src/crypto/aes/asm/aesni-x86_64.pl b/src/crypto/aes/asm/aesni-x86_64.pl
index 5f61746..25ca574 100644
--- a/src/crypto/aes/asm/aesni-x86_64.pl
+++ b/src/crypto/aes/asm/aesni-x86_64.pl
@@ -165,11 +165,11 @@
# Westmere 3.77/1.25 1.25 1.25 1.26
# * Bridge 5.07/0.74 0.75 0.90 0.85
# Haswell 4.44/0.63 0.63 0.73 0.63
-# Atom 5.75/3.54 3.56 4.12 3.87(*)
+# Silvermont 5.75/3.54 3.56 4.12 3.87(*)
# Bulldozer 5.77/0.70 0.72 0.90 0.70
#
-# (*) Atom ECB result is suboptimal because of penalties incurred
-# by operations on %xmm8-15. As ECB is not considered
+# (*) Atom Silvermont ECB result is suboptimal because of penalties
+# incurred by operations on %xmm8-15. As ECB is not considered
# critical, nothing was done to mitigate the problem.
$PREFIX="aesni"; # if $PREFIX is set to "AES", the script
@@ -263,7 +263,10 @@ ${PREFIX}_encrypt:
___
&aesni_generate1("enc",$key,$rounds);
$code.=<<___;
+ pxor $rndkey0,$rndkey0 # clear register bank
+ pxor $rndkey1,$rndkey1
movups $inout0,($out) # output
+ pxor $inout0,$inout0
ret
.size ${PREFIX}_encrypt,.-${PREFIX}_encrypt
@@ -276,7 +279,10 @@ ${PREFIX}_decrypt:
___
&aesni_generate1("dec",$key,$rounds);
$code.=<<___;
+ pxor $rndkey0,$rndkey0 # clear register bank
+ pxor $rndkey1,$rndkey1
movups $inout0,($out) # output
+ pxor $inout0,$inout0
ret
.size ${PREFIX}_decrypt, .-${PREFIX}_decrypt
___
@@ -445,21 +451,18 @@ _aesni_${dir}rypt6:
pxor $rndkey0,$inout4
aes${dir} $rndkey1,$inout2
pxor $rndkey0,$inout5
+ $movkey ($key,%rax),$rndkey0
add \$16,%rax
- aes${dir} $rndkey1,$inout3
- aes${dir} $rndkey1,$inout4
- aes${dir} $rndkey1,$inout5
- $movkey -16($key,%rax),$rndkey0
jmp .L${dir}_loop6_enter
.align 16
.L${dir}_loop6:
aes${dir} $rndkey1,$inout0
aes${dir} $rndkey1,$inout1
aes${dir} $rndkey1,$inout2
+.L${dir}_loop6_enter:
aes${dir} $rndkey1,$inout3
aes${dir} $rndkey1,$inout4
aes${dir} $rndkey1,$inout5
-.L${dir}_loop6_enter:
$movkey ($key,%rax),$rndkey1
add \$32,%rax
aes${dir} $rndkey0,$inout0
@@ -506,23 +509,18 @@ _aesni_${dir}rypt8:
lea 32($key,$rounds),$key
neg %rax # $rounds
aes${dir} $rndkey1,$inout0
- add \$16,%rax
pxor $rndkey0,$inout5
- aes${dir} $rndkey1,$inout1
pxor $rndkey0,$inout6
+ aes${dir} $rndkey1,$inout1
pxor $rndkey0,$inout7
- aes${dir} $rndkey1,$inout2
- aes${dir} $rndkey1,$inout3
- aes${dir} $rndkey1,$inout4
- aes${dir} $rndkey1,$inout5
- aes${dir} $rndkey1,$inout6
- aes${dir} $rndkey1,$inout7
- $movkey -16($key,%rax),$rndkey0
- jmp .L${dir}_loop8_enter
+ $movkey ($key,%rax),$rndkey0
+ add \$16,%rax
+ jmp .L${dir}_loop8_inner
.align 16
.L${dir}_loop8:
aes${dir} $rndkey1,$inout0
aes${dir} $rndkey1,$inout1
+.L${dir}_loop8_inner:
aes${dir} $rndkey1,$inout2
aes${dir} $rndkey1,$inout3
aes${dir} $rndkey1,$inout4
@@ -587,15 +585,15 @@ aesni_ecb_encrypt:
___
$code.=<<___ if ($win64);
lea -0x58(%rsp),%rsp
- movaps %xmm6,(%rsp)
+ movaps %xmm6,(%rsp) # offload $inout4..7
movaps %xmm7,0x10(%rsp)
movaps %xmm8,0x20(%rsp)
movaps %xmm9,0x30(%rsp)
.Lecb_enc_body:
___
$code.=<<___;
- and \$-16,$len
- jz .Lecb_ret
+ and \$-16,$len # if ($len<16)
+ jz .Lecb_ret # return
mov 240($key),$rounds # key->rounds
$movkey ($key),$rndkey0
@@ -604,10 +602,10 @@ $code.=<<___;
test %r8d,%r8d # 5th argument
jz .Lecb_decrypt
#--------------------------- ECB ENCRYPT ------------------------------#
- cmp \$0x80,$len
- jb .Lecb_enc_tail
+ cmp \$0x80,$len # if ($len<8*16)
+ jb .Lecb_enc_tail # short input
- movdqu ($inp),$inout0
+ movdqu ($inp),$inout0 # load 8 input blocks
movdqu 0x10($inp),$inout1
movdqu 0x20($inp),$inout2
movdqu 0x30($inp),$inout3
@@ -615,14 +613,14 @@ $code.=<<___;
movdqu 0x50($inp),$inout5
movdqu 0x60($inp),$inout6
movdqu 0x70($inp),$inout7
- lea 0x80($inp),$inp
- sub \$0x80,$len
+ lea 0x80($inp),$inp # $inp+=8*16
+ sub \$0x80,$len # $len-=8*16 (can be zero)
jmp .Lecb_enc_loop8_enter
.align 16
.Lecb_enc_loop8:
- movups $inout0,($out)
+ movups $inout0,($out) # store 8 output blocks
mov $key_,$key # restore $key
- movdqu ($inp),$inout0
+ movdqu ($inp),$inout0 # load 8 input blocks
mov $rnds_,$rounds # restore $rounds
movups $inout1,0x10($out)
movdqu 0x10($inp),$inout1
@@ -637,17 +635,17 @@ $code.=<<___;
movups $inout6,0x60($out)
movdqu 0x60($inp),$inout6
movups $inout7,0x70($out)
- lea 0x80($out),$out
+ lea 0x80($out),$out # $out+=8*16
movdqu 0x70($inp),$inout7
- lea 0x80($inp),$inp
+ lea 0x80($inp),$inp # $inp+=8*16
.Lecb_enc_loop8_enter:
call _aesni_encrypt8
sub \$0x80,$len
- jnc .Lecb_enc_loop8
+ jnc .Lecb_enc_loop8 # loop if $len-=8*16 didn't borrow
- movups $inout0,($out)
+ movups $inout0,($out) # store 8 output blocks
mov $key_,$key # restore $key
movups $inout1,0x10($out)
mov $rnds_,$rounds # restore $rounds
@@ -657,11 +655,11 @@ $code.=<<___;
movups $inout5,0x50($out)
movups $inout6,0x60($out)
movups $inout7,0x70($out)
- lea 0x80($out),$out
- add \$0x80,$len
- jz .Lecb_ret
+ lea 0x80($out),$out # $out+=8*16
+ add \$0x80,$len # restore real remaining $len
+ jz .Lecb_ret # done if ($len==0)
-.Lecb_enc_tail:
+.Lecb_enc_tail: # $len is less than 8*16
movups ($inp),$inout0
cmp \$0x20,$len
jb .Lecb_enc_one
@@ -678,8 +676,9 @@ $code.=<<___;
movups 0x50($inp),$inout5
je .Lecb_enc_six
movdqu 0x60($inp),$inout6
+ xorps $inout7,$inout7
call _aesni_encrypt8
- movups $inout0,($out)
+ movups $inout0,($out) # store 7 output blocks
movups $inout1,0x10($out)
movups $inout2,0x20($out)
movups $inout3,0x30($out)
@@ -692,25 +691,25 @@ $code.=<<___;
___
&aesni_generate1("enc",$key,$rounds);
$code.=<<___;
- movups $inout0,($out)
+ movups $inout0,($out) # store one output block
jmp .Lecb_ret
.align 16
.Lecb_enc_two:
call _aesni_encrypt2
- movups $inout0,($out)
+ movups $inout0,($out) # store 2 output blocks
movups $inout1,0x10($out)
jmp .Lecb_ret
.align 16
.Lecb_enc_three:
call _aesni_encrypt3
- movups $inout0,($out)
+ movups $inout0,($out) # store 3 output blocks
movups $inout1,0x10($out)
movups $inout2,0x20($out)
jmp .Lecb_ret
.align 16
.Lecb_enc_four:
call _aesni_encrypt4
- movups $inout0,($out)
+ movups $inout0,($out) # store 4 output blocks
movups $inout1,0x10($out)
movups $inout2,0x20($out)
movups $inout3,0x30($out)
@@ -719,7 +718,7 @@ $code.=<<___;
.Lecb_enc_five:
xorps $inout5,$inout5
call _aesni_encrypt6
- movups $inout0,($out)
+ movups $inout0,($out) # store 5 output blocks
movups $inout1,0x10($out)
movups $inout2,0x20($out)
movups $inout3,0x30($out)
@@ -728,7 +727,7 @@ $code.=<<___;
.align 16
.Lecb_enc_six:
call _aesni_encrypt6
- movups $inout0,($out)
+ movups $inout0,($out) # store 6 output blocks
movups $inout1,0x10($out)
movups $inout2,0x20($out)
movups $inout3,0x30($out)
@@ -738,10 +737,10 @@ $code.=<<___;
#--------------------------- ECB DECRYPT ------------------------------#
.align 16
.Lecb_decrypt:
- cmp \$0x80,$len
- jb .Lecb_dec_tail
+ cmp \$0x80,$len # if ($len<8*16)
+ jb .Lecb_dec_tail # short input
- movdqu ($inp),$inout0
+ movdqu ($inp),$inout0 # load 8 input blocks
movdqu 0x10($inp),$inout1
movdqu 0x20($inp),$inout2
movdqu 0x30($inp),$inout3
@@ -749,14 +748,14 @@ $code.=<<___;
movdqu 0x50($inp),$inout5
movdqu 0x60($inp),$inout6
movdqu 0x70($inp),$inout7
- lea 0x80($inp),$inp
- sub \$0x80,$len
+ lea 0x80($inp),$inp # $inp+=8*16
+ sub \$0x80,$len # $len-=8*16 (can be zero)
jmp .Lecb_dec_loop8_enter
.align 16
.Lecb_dec_loop8:
- movups $inout0,($out)
+ movups $inout0,($out) # store 8 output blocks
mov $key_,$key # restore $key
- movdqu ($inp),$inout0
+ movdqu ($inp),$inout0 # load 8 input blocks
mov $rnds_,$rounds # restore $rounds
movups $inout1,0x10($out)
movdqu 0x10($inp),$inout1
@@ -771,30 +770,38 @@ $code.=<<___;
movups $inout6,0x60($out)
movdqu 0x60($inp),$inout6
movups $inout7,0x70($out)
- lea 0x80($out),$out
+ lea 0x80($out),$out # $out+=8*16
movdqu 0x70($inp),$inout7
- lea 0x80($inp),$inp
+ lea 0x80($inp),$inp # $inp+=8*16
.Lecb_dec_loop8_enter:
call _aesni_decrypt8
$movkey ($key_),$rndkey0
sub \$0x80,$len
- jnc .Lecb_dec_loop8
+ jnc .Lecb_dec_loop8 # loop if $len-=8*16 didn't borrow
- movups $inout0,($out)
+ movups $inout0,($out) # store 8 output blocks
+ pxor $inout0,$inout0 # clear register bank
mov $key_,$key # restore $key
movups $inout1,0x10($out)
+ pxor $inout1,$inout1
mov $rnds_,$rounds # restore $rounds
movups $inout2,0x20($out)
+ pxor $inout2,$inout2
movups $inout3,0x30($out)
+ pxor $inout3,$inout3
movups $inout4,0x40($out)
+ pxor $inout4,$inout4
movups $inout5,0x50($out)
+ pxor $inout5,$inout5
movups $inout6,0x60($out)
+ pxor $inout6,$inout6
movups $inout7,0x70($out)
- lea 0x80($out),$out
- add \$0x80,$len
- jz .Lecb_ret
+ pxor $inout7,$inout7
+ lea 0x80($out),$out # $out+=8*16
+ add \$0x80,$len # restore real remaining $len
+ jz .Lecb_ret # done if ($len==0)
.Lecb_dec_tail:
movups ($inp),$inout0
@@ -814,70 +821,107 @@ $code.=<<___;
je .Lecb_dec_six
movups 0x60($inp),$inout6
$movkey ($key),$rndkey0
+ xorps $inout7,$inout7
call _aesni_decrypt8
- movups $inout0,($out)
+ movups $inout0,($out) # store 7 output blocks
+ pxor $inout0,$inout0 # clear register bank
movups $inout1,0x10($out)
+ pxor $inout1,$inout1
movups $inout2,0x20($out)
+ pxor $inout2,$inout2
movups $inout3,0x30($out)
+ pxor $inout3,$inout3
movups $inout4,0x40($out)
+ pxor $inout4,$inout4
movups $inout5,0x50($out)
+ pxor $inout5,$inout5
movups $inout6,0x60($out)
+ pxor $inout6,$inout6
+ pxor $inout7,$inout7
jmp .Lecb_ret
.align 16
.Lecb_dec_one:
___
&aesni_generate1("dec",$key,$rounds);
$code.=<<___;
- movups $inout0,($out)
+ movups $inout0,($out) # store one output block
+ pxor $inout0,$inout0 # clear register bank
jmp .Lecb_ret
.align 16
.Lecb_dec_two:
call _aesni_decrypt2
- movups $inout0,($out)
+ movups $inout0,($out) # store 2 output blocks
+ pxor $inout0,$inout0 # clear register bank
movups $inout1,0x10($out)
+ pxor $inout1,$inout1
jmp .Lecb_ret
.align 16
.Lecb_dec_three:
call _aesni_decrypt3
- movups $inout0,($out)
+ movups $inout0,($out) # store 3 output blocks
+ pxor $inout0,$inout0 # clear register bank
movups $inout1,0x10($out)
+ pxor $inout1,$inout1
movups $inout2,0x20($out)
+ pxor $inout2,$inout2
jmp .Lecb_ret
.align 16
.Lecb_dec_four:
call _aesni_decrypt4
- movups $inout0,($out)
+ movups $inout0,($out) # store 4 output blocks
+ pxor $inout0,$inout0 # clear register bank
movups $inout1,0x10($out)
+ pxor $inout1,$inout1
movups $inout2,0x20($out)
+ pxor $inout2,$inout2
movups $inout3,0x30($out)
+ pxor $inout3,$inout3
jmp .Lecb_ret
.align 16
.Lecb_dec_five:
xorps $inout5,$inout5
call _aesni_decrypt6
- movups $inout0,($out)
+ movups $inout0,($out) # store 5 output blocks
+ pxor $inout0,$inout0 # clear register bank
movups $inout1,0x10($out)
+ pxor $inout1,$inout1
movups $inout2,0x20($out)
+ pxor $inout2,$inout2
movups $inout3,0x30($out)
+ pxor $inout3,$inout3
movups $inout4,0x40($out)
+ pxor $inout4,$inout4
+ pxor $inout5,$inout5
jmp .Lecb_ret
.align 16
.Lecb_dec_six:
call _aesni_decrypt6
- movups $inout0,($out)
+ movups $inout0,($out) # store 6 output blocks
+ pxor $inout0,$inout0 # clear register bank
movups $inout1,0x10($out)
+ pxor $inout1,$inout1
movups $inout2,0x20($out)
+ pxor $inout2,$inout2
movups $inout3,0x30($out)
+ pxor $inout3,$inout3
movups $inout4,0x40($out)
+ pxor $inout4,$inout4
movups $inout5,0x50($out)
+ pxor $inout5,$inout5
.Lecb_ret:
+ xorps $rndkey0,$rndkey0 # %xmm0
+ pxor $rndkey1,$rndkey1
___
$code.=<<___ if ($win64);
movaps (%rsp),%xmm6
+ movaps %xmm0,(%rsp) # clear stack
movaps 0x10(%rsp),%xmm7
+ movaps %xmm0,0x10(%rsp)
movaps 0x20(%rsp),%xmm8
+ movaps %xmm0,0x20(%rsp)
movaps 0x30(%rsp),%xmm9
+ movaps %xmm0,0x30(%rsp)
lea 0x58(%rsp),%rsp
.Lecb_enc_ret:
___
@@ -911,10 +955,10 @@ aesni_ccm64_encrypt_blocks:
___
$code.=<<___ if ($win64);
lea -0x58(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
- movaps %xmm8,0x20(%rsp)
- movaps %xmm9,0x30(%rsp)
+ movaps %xmm6,(%rsp) # $iv
+ movaps %xmm7,0x10(%rsp) # $bswap_mask
+ movaps %xmm8,0x20(%rsp) # $in0
+ movaps %xmm9,0x30(%rsp) # $increment
.Lccm64_enc_body:
___
$code.=<<___;
@@ -956,7 +1000,7 @@ $code.=<<___;
aesenc $rndkey1,$inout0
aesenc $rndkey1,$inout1
paddq $increment,$iv
- dec $len
+ dec $len # $len-- ($len is in blocks)
aesenclast $rndkey0,$inout0
aesenclast $rndkey0,$inout1
@@ -965,16 +1009,26 @@ $code.=<<___;
movdqa $iv,$inout0
movups $in0,($out) # save output
pshufb $bswap_mask,$inout0
- lea 16($out),$out
- jnz .Lccm64_enc_outer
+ lea 16($out),$out # $out+=16
+ jnz .Lccm64_enc_outer # loop if ($len!=0)
- movups $inout1,($cmac)
+ pxor $rndkey0,$rndkey0 # clear register bank
+ pxor $rndkey1,$rndkey1
+ pxor $inout0,$inout0
+ movups $inout1,($cmac) # store resulting mac
+ pxor $inout1,$inout1
+ pxor $in0,$in0
+ pxor $iv,$iv
___
$code.=<<___ if ($win64);
movaps (%rsp),%xmm6
+ movaps %xmm0,(%rsp) # clear stack
movaps 0x10(%rsp),%xmm7
+ movaps %xmm0,0x10(%rsp)
movaps 0x20(%rsp),%xmm8
+ movaps %xmm0,0x20(%rsp)
movaps 0x30(%rsp),%xmm9
+ movaps %xmm0,0x30(%rsp)
lea 0x58(%rsp),%rsp
.Lccm64_enc_ret:
___
@@ -991,10 +1045,10 @@ aesni_ccm64_decrypt_blocks:
___
$code.=<<___ if ($win64);
lea -0x58(%rsp),%rsp
- movaps %xmm6,(%rsp)
- movaps %xmm7,0x10(%rsp)
- movaps %xmm8,0x20(%rsp)
- movaps %xmm9,0x30(%rsp)
+ movaps %xmm6,(%rsp) # $iv
+ movaps %xmm7,0x10(%rsp) # $bswap_mask
+ movaps %xmm8,0x20(%rsp) # $in8
+ movaps %xmm9,0x30(%rsp) # $increment
.Lccm64_dec_body:
___
$code.=<<___;
@@ -1015,7 +1069,7 @@ $code.=<<___;
mov \$16,$rounds
movups ($inp),$in0 # load inp
paddq $increment,$iv
- lea 16($inp),$inp
+ lea 16($inp),$inp # $inp+=16
sub %r10,%rax # twisted $rounds
lea 32($key_,$rnds_),$key # end of key schedule
mov %rax,%r10
@@ -1025,11 +1079,11 @@ $code.=<<___;
xorps $inout0,$in0 # inp ^= E(iv)
movdqa $iv,$inout0
movups $in0,($out) # save output
- lea 16($out),$out
+ lea 16($out),$out # $out+=16
pshufb $bswap_mask,$inout0
- sub \$1,$len
- jz .Lccm64_dec_break
+ sub \$1,$len # $len-- ($len is in blocks)
+ jz .Lccm64_dec_break # if ($len==0) break
$movkey ($key_),$rndkey0
mov %r10,%rax
@@ -1049,13 +1103,13 @@ $code.=<<___;
aesenc $rndkey0,$inout1
$movkey -16($key,%rax),$rndkey0
jnz .Lccm64_dec2_loop
- movups ($inp),$in0 # load inp
+ movups ($inp),$in0 # load input
paddq $increment,$iv
aesenc $rndkey1,$inout0
aesenc $rndkey1,$inout1
aesenclast $rndkey0,$inout0
aesenclast $rndkey0,$inout1
- lea 16($inp),$inp
+ lea 16($inp),$inp # $inp+=16
jmp .Lccm64_dec_outer
.align 16
@@ -1065,13 +1119,23 @@ $code.=<<___;
___
&aesni_generate1("enc",$key_,$rounds,$inout1,$in0);
$code.=<<___;
- movups $inout1,($cmac)
+ pxor $rndkey0,$rndkey0 # clear register bank
+ pxor $rndkey1,$rndkey1
+ pxor $inout0,$inout0
+ movups $inout1,($cmac) # store resulting mac
+ pxor $inout1,$inout1
+ pxor $in0,$in0
+ pxor $iv,$iv
___
$code.=<<___ if ($win64);
movaps (%rsp),%xmm6
+ movaps %xmm0,(%rsp) # clear stack
movaps 0x10(%rsp),%xmm7
+ movaps %xmm0,0x10(%rsp)
movaps 0x20(%rsp),%xmm8
+ movaps %xmm0,0x20(%rsp)
movaps 0x30(%rsp),%xmm9
+ movaps %xmm0,0x30(%rsp)
lea 0x58(%rsp),%rsp
.Lccm64_dec_ret:
___
@@ -1102,13 +1166,34 @@ $code.=<<___;
.type aesni_ctr32_encrypt_blocks,\@function,5
.align 16
aesni_ctr32_encrypt_blocks:
+ cmp \$1,$len
+ jne .Lctr32_bulk
+
+ # handle single block without allocating stack frame,
+ # useful when handling edges
+ movups ($ivp),$inout0
+ movups ($inp),$inout1
+ mov 240($key),%edx # key->rounds
+___
+ &aesni_generate1("enc",$key,"%edx");
+$code.=<<___;
+ pxor $rndkey0,$rndkey0 # clear register bank
+ pxor $rndkey1,$rndkey1
+ xorps $inout1,$inout0
+ pxor $inout1,$inout1
+ movups $inout0,($out)
+ xorps $inout0,$inout0
+ jmp .Lctr32_epilogue
+
+.align 16
+.Lctr32_bulk:
lea (%rsp),%rax
push %rbp
sub \$$frame_size,%rsp
and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
___
$code.=<<___ if ($win64);
- movaps %xmm6,-0xa8(%rax)
+ movaps %xmm6,-0xa8(%rax) # offload everything
movaps %xmm7,-0x98(%rax)
movaps %xmm8,-0x88(%rax)
movaps %xmm9,-0x78(%rax)
@@ -1123,8 +1208,8 @@ ___
$code.=<<___;
lea -8(%rax),%rbp
- cmp \$1,$len
- je .Lctr32_one_shortcut
+ # 8 16-byte words on top of stack are counter values
+ # xor-ed with zero-round key
movdqu ($ivp),$inout0
movdqu ($key),$rndkey0
@@ -1139,7 +1224,7 @@ $code.=<<___;
movdqa $inout0,0x40(%rsp)
movdqa $inout0,0x50(%rsp)
movdqa $inout0,0x60(%rsp)
- mov %rdx,%r10 # borrow %rdx
+ mov %rdx,%r10 # about to borrow %rdx
movdqa $inout0,0x70(%rsp)
lea 1($ctr),%rax
@@ -1183,15 +1268,15 @@ $code.=<<___;
movdqa 0x40(%rsp),$inout4
movdqa 0x50(%rsp),$inout5
- cmp \$8,$len
- jb .Lctr32_tail
+ cmp \$8,$len # $len is in blocks
+ jb .Lctr32_tail # short input if ($len<8)
- sub \$6,$len
+ sub \$6,$len # $len is biased by -6
cmp \$`1<<22`,%r10d # check for MOVBE without XSAVE
- je .Lctr32_6x
+ je .Lctr32_6x # [which denotes Atom Silvermont]
lea 0x80($key),$key # size optimization
- sub \$2,$len
+ sub \$2,$len # $len is biased by -8
jmp .Lctr32_loop8
.align 16
@@ -1205,13 +1290,13 @@ $code.=<<___;
.align 16
.Lctr32_loop6:
- add \$6,$ctr
+ add \$6,$ctr # next counter value
$movkey -48($key,$rnds_),$rndkey0
aesenc $rndkey1,$inout0
mov $ctr,%eax
xor $key0,%eax
aesenc $rndkey1,$inout1
- movbe %eax,`0x00+12`(%rsp)
+ movbe %eax,`0x00+12`(%rsp) # store next counter value
lea 1($ctr),%eax
aesenc $rndkey1,$inout2
xor $key0,%eax
@@ -1244,16 +1329,16 @@ $code.=<<___;
call .Lenc_loop6
- movdqu ($inp),$inout6
+ movdqu ($inp),$inout6 # load 6 input blocks
movdqu 0x10($inp),$inout7
movdqu 0x20($inp),$in0
movdqu 0x30($inp),$in1
movdqu 0x40($inp),$in2
movdqu 0x50($inp),$in3
- lea 0x60($inp),$inp
+ lea 0x60($inp),$inp # $inp+=6*16
$movkey -64($key,$rnds_),$rndkey1
- pxor $inout0,$inout6
- movaps 0x00(%rsp),$inout0
+ pxor $inout0,$inout6 # inp^=E(ctr)
+ movaps 0x00(%rsp),$inout0 # load next counter [xor-ed with 0 round]
pxor $inout1,$inout7
movaps 0x10(%rsp),$inout1
pxor $inout2,$in0
@@ -1264,19 +1349,19 @@ $code.=<<___;
movaps 0x40(%rsp),$inout4
pxor $inout5,$in3
movaps 0x50(%rsp),$inout5
- movdqu $inout6,($out)
+ movdqu $inout6,($out) # store 6 output blocks
movdqu $inout7,0x10($out)
movdqu $in0,0x20($out)
movdqu $in1,0x30($out)
movdqu $in2,0x40($out)
movdqu $in3,0x50($out)
- lea 0x60($out),$out
-
+ lea 0x60($out),$out # $out+=6*16
+
sub \$6,$len
- jnc .Lctr32_loop6
+ jnc .Lctr32_loop6 # loop if $len-=6 didn't borrow
- add \$6,$len
- jz .Lctr32_done
+ add \$6,$len # restore real remaining $len
+ jz .Lctr32_done # done if ($len==0)
lea -48($rnds_),$rounds
lea -80($key,$rnds_),$key # restore $key
@@ -1286,7 +1371,7 @@ $code.=<<___;
.align 32
.Lctr32_loop8:
- add \$8,$ctr
+ add \$8,$ctr # next counter value
movdqa 0x60(%rsp),$inout6
aesenc $rndkey1,$inout0
mov $ctr,%r9d
@@ -1298,7 +1383,7 @@ $code.=<<___;
xor $key0,%r9d
nop
aesenc $rndkey1,$inout3
- mov %r9d,0x00+12(%rsp)
+ mov %r9d,0x00+12(%rsp) # store next counter value
lea 1($ctr),%r9
aesenc $rndkey1,$inout4
aesenc $rndkey1,$inout5
@@ -1331,7 +1416,7 @@ $code.=<<___;
aesenc $rndkey0,$inout1
aesenc $rndkey0,$inout2
xor $key0,%r9d
- movdqu 0x00($inp),$in0
+ movdqu 0x00($inp),$in0 # start loading input
aesenc $rndkey0,$inout3
mov %r9d,0x70+12(%rsp)
cmp \$11,$rounds
@@ -1388,7 +1473,7 @@ $code.=<<___;
.align 16
.Lctr32_enc_done:
movdqu 0x10($inp),$in1
- pxor $rndkey0,$in0
+ pxor $rndkey0,$in0 # input^=round[last]
movdqu 0x20($inp),$in2
pxor $rndkey0,$in1
movdqu 0x30($inp),$in3
@@ -1406,11 +1491,11 @@ $code.=<<___;
aesenc $rndkey1,$inout5
aesenc $rndkey1,$inout6
aesenc $rndkey1,$inout7
- movdqu 0x60($inp),$rndkey1
- lea 0x80($inp),$inp
+ movdqu 0x60($inp),$rndkey1 # borrow $rndkey1 for inp[6]
+ lea 0x80($inp),$inp # $inp+=8*16
- aesenclast $in0,$inout0
- pxor $rndkey0,$rndkey1
+ aesenclast $in0,$inout0 # $inN is inp[N]^round[last]
+ pxor $rndkey0,$rndkey1 # borrowed $rndkey
movdqu 0x70-0x80($inp),$in0
aesenclast $in1,$inout1
pxor $rndkey0,$in0
@@ -1425,10 +1510,10 @@ $code.=<<___;
movdqa 0x40(%rsp),$in5
aesenclast $rndkey1,$inout6
movdqa 0x50(%rsp),$rndkey0
- $movkey 0x10-0x80($key),$rndkey1
+ $movkey 0x10-0x80($key),$rndkey1#real 1st-round key
aesenclast $in0,$inout7
- movups $inout0,($out) # store output
+ movups $inout0,($out) # store 8 output blocks
movdqa $in1,$inout0
movups $inout1,0x10($out)
movdqa $in2,$inout1
@@ -1442,21 +1527,24 @@ $code.=<<___;
movdqa $rndkey0,$inout5
movups $inout6,0x60($out)
movups $inout7,0x70($out)
- lea 0x80($out),$out
-
+ lea 0x80($out),$out # $out+=8*16
+
sub \$8,$len
- jnc .Lctr32_loop8
+ jnc .Lctr32_loop8 # loop if $len-=8 didn't borrow
- add \$8,$len
- jz .Lctr32_done
+ add \$8,$len # restore real remainig $len
+ jz .Lctr32_done # done if ($len==0)
lea -0x80($key),$key
.Lctr32_tail:
+ # note that at this point $inout0..5 are populated with
+ # counter values xor-ed with 0-round key
lea 16($key),$key
cmp \$4,$len
jb .Lctr32_loop3
je .Lctr32_loop4
+ # if ($len>4) compute 7 E(counter)
shl \$4,$rounds
movdqa 0x60(%rsp),$inout6
pxor $inout7,$inout7
@@ -1464,14 +1552,14 @@ $code.=<<___;
$movkey 16($key),$rndkey0
aesenc $rndkey1,$inout0
aesenc $rndkey1,$inout1
- lea 32-16($key,$rounds),$key
+ lea 32-16($key,$rounds),$key# prepare for .Lenc_loop8_enter
neg %rax
aesenc $rndkey1,$inout2
- add \$16,%rax
+ add \$16,%rax # prepare for .Lenc_loop8_enter
movups ($inp),$in0
aesenc $rndkey1,$inout3
aesenc $rndkey1,$inout4
- movups 0x10($inp),$in1
+ movups 0x10($inp),$in1 # pre-load input
movups 0x20($inp),$in2
aesenc $rndkey1,$inout5
aesenc $rndkey1,$inout6
@@ -1482,7 +1570,7 @@ $code.=<<___;
pxor $in0,$inout0
movdqu 0x40($inp),$in0
pxor $in1,$inout1
- movdqu $inout0,($out)
+ movdqu $inout0,($out) # store output
pxor $in2,$inout2
movdqu $inout1,0x10($out)
pxor $in3,$inout3
@@ -1491,17 +1579,17 @@ $code.=<<___;
movdqu $inout3,0x30($out)
movdqu $inout4,0x40($out)
cmp \$6,$len
- jb .Lctr32_done
+ jb .Lctr32_done # $len was 5, stop store
movups 0x50($inp),$in1
xorps $in1,$inout5
movups $inout5,0x50($out)
- je .Lctr32_done
+ je .Lctr32_done # $len was 6, stop store
movups 0x60($inp),$in2
xorps $in2,$inout6
movups $inout6,0x60($out)
- jmp .Lctr32_done
+ jmp .Lctr32_done # $len was 7, stop store
.align 32
.Lctr32_loop4:
@@ -1515,7 +1603,7 @@ $code.=<<___;
jnz .Lctr32_loop4
aesenclast $rndkey1,$inout0
aesenclast $rndkey1,$inout1
- movups ($inp),$in0
+ movups ($inp),$in0 # load input
movups 0x10($inp),$in1
aesenclast $rndkey1,$inout2
aesenclast $rndkey1,$inout3
@@ -1523,14 +1611,14 @@ $code.=<<___;
movups 0x30($inp),$in3
xorps $in0,$inout0
- movups $inout0,($out)
+ movups $inout0,($out) # store output
xorps $in1,$inout1
movups $inout1,0x10($out)
pxor $in2,$inout2
movdqu $inout2,0x20($out)
pxor $in3,$inout3
movdqu $inout3,0x30($out)
- jmp .Lctr32_done
+ jmp .Lctr32_done # $len was 4, stop store
.align 32
.Lctr32_loop3:
@@ -1545,48 +1633,79 @@ $code.=<<___;
aesenclast $rndkey1,$inout1
aesenclast $rndkey1,$inout2
- movups ($inp),$in0
+ movups ($inp),$in0 # load input
xorps $in0,$inout0
- movups $inout0,($out)
+ movups $inout0,($out) # store output
cmp \$2,$len
- jb .Lctr32_done
+ jb .Lctr32_done # $len was 1, stop store
movups 0x10($inp),$in1
xorps $in1,$inout1
movups $inout1,0x10($out)
- je .Lctr32_done
+ je .Lctr32_done # $len was 2, stop store
movups 0x20($inp),$in2
xorps $in2,$inout2
- movups $inout2,0x20($out)
- jmp .Lctr32_done
-
-.align 16
-.Lctr32_one_shortcut:
- movups ($ivp),$inout0
- movups ($inp),$in0
- mov 240($key),$rounds # key->rounds
-___
- &aesni_generate1("enc",$key,$rounds);
-$code.=<<___;
- xorps $in0,$inout0
- movups $inout0,($out)
- jmp .Lctr32_done
+ movups $inout2,0x20($out) # $len was 3, stop store
-.align 16
.Lctr32_done:
+ xorps %xmm0,%xmm0 # clear regiser bank
+ xor $key0,$key0
+ pxor %xmm1,%xmm1
+ pxor %xmm2,%xmm2
+ pxor %xmm3,%xmm3
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+$code.=<<___ if (!$win64);
+ pxor %xmm6,%xmm6
+ pxor %xmm7,%xmm7
+ movaps %xmm0,0x00(%rsp) # clear stack
+ pxor %xmm8,%xmm8
+ movaps %xmm0,0x10(%rsp)
+ pxor %xmm9,%xmm9
+ movaps %xmm0,0x20(%rsp)
+ pxor %xmm10,%xmm10
+ movaps %xmm0,0x30(%rsp)
+ pxor %xmm11,%xmm11
+ movaps %xmm0,0x40(%rsp)
+ pxor %xmm12,%xmm12
+ movaps %xmm0,0x50(%rsp)
+ pxor %xmm13,%xmm13
+ movaps %xmm0,0x60(%rsp)
+ pxor %xmm14,%xmm14
+ movaps %xmm0,0x70(%rsp)
+ pxor %xmm15,%xmm15
___
$code.=<<___ if ($win64);
movaps -0xa0(%rbp),%xmm6
+ movaps %xmm0,-0xa0(%rbp) # clear stack
movaps -0x90(%rbp),%xmm7
+ movaps %xmm0,-0x90(%rbp)
movaps -0x80(%rbp),%xmm8
+ movaps %xmm0,-0x80(%rbp)
movaps -0x70(%rbp),%xmm9
+ movaps %xmm0,-0x70(%rbp)
movaps -0x60(%rbp),%xmm10
+ movaps %xmm0,-0x60(%rbp)
movaps -0x50(%rbp),%xmm11
+ movaps %xmm0,-0x50(%rbp)
movaps -0x40(%rbp),%xmm12
+ movaps %xmm0,-0x40(%rbp)
movaps -0x30(%rbp),%xmm13
+ movaps %xmm0,-0x30(%rbp)
movaps -0x20(%rbp),%xmm14
+ movaps %xmm0,-0x20(%rbp)
movaps -0x10(%rbp),%xmm15
+ movaps %xmm0,-0x10(%rbp)
+ movaps %xmm0,0x00(%rsp)
+ movaps %xmm0,0x10(%rsp)
+ movaps %xmm0,0x20(%rsp)
+ movaps %xmm0,0x30(%rsp)
+ movaps %xmm0,0x40(%rsp)
+ movaps %xmm0,0x50(%rsp)
+ movaps %xmm0,0x60(%rsp)
+ movaps %xmm0,0x70(%rsp)
___
$code.=<<___;
lea (%rbp),%rsp
@@ -1619,7 +1738,7 @@ aesni_xts_encrypt:
and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
___
$code.=<<___ if ($win64);
- movaps %xmm6,-0xa8(%rax)
+ movaps %xmm6,-0xa8(%rax) # offload everything
movaps %xmm7,-0x98(%rax)
movaps %xmm8,-0x88(%rax)
movaps %xmm9,-0x78(%rax)
@@ -1679,7 +1798,7 @@ $code.=<<___;
movaps $rndkey1,0x60(%rsp) # save round[0]^round[last]
sub \$16*6,$len
- jc .Lxts_enc_short
+ jc .Lxts_enc_short # if $len-=6*16 borrowed
mov \$16+96,$rounds
lea 32($key_,$rnds_),$key # end of key schedule
@@ -1694,7 +1813,7 @@ $code.=<<___;
movdqu `16*0`($inp),$inout0 # load input
movdqa $rndkey0,$twmask
movdqu `16*1`($inp),$inout1
- pxor @tweak[0],$inout0
+ pxor @tweak[0],$inout0 # input^=tweak^round[0]
movdqu `16*2`($inp),$inout2
pxor @tweak[1],$inout1
aesenc $rndkey1,$inout0
@@ -1713,10 +1832,10 @@ $code.=<<___;
lea `16*6`($inp),$inp
pxor $twmask,$inout5
- pxor $twres,@tweak[0]
+ pxor $twres,@tweak[0] # calclulate tweaks^round[last]
aesenc $rndkey1,$inout4
pxor $twres,@tweak[1]
- movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^last round key
+ movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^round[last]
aesenc $rndkey1,$inout5
$movkey 48($key_),$rndkey1
pxor $twres,@tweak[2]
@@ -1757,7 +1876,7 @@ $code.=<<___;
$movkey -80($key,%rax),$rndkey0
jnz .Lxts_enc_loop6
- movdqa (%r8),$twmask
+ movdqa (%r8),$twmask # start calculating next tweak
movdqa $twres,$twtmp
paddd $twres,$twres
aesenc $rndkey1,$inout0
@@ -1851,15 +1970,15 @@ $code.=<<___;
aesenclast `16*5`(%rsp),$inout5
pxor $twres,@tweak[5]
- lea `16*6`($out),$out
- movups $inout0,`-16*6`($out) # write output
+ lea `16*6`($out),$out # $out+=6*16
+ movups $inout0,`-16*6`($out) # store 6 output blocks
movups $inout1,`-16*5`($out)
movups $inout2,`-16*4`($out)
movups $inout3,`-16*3`($out)
movups $inout4,`-16*2`($out)
movups $inout5,`-16*1`($out)
sub \$16*6,$len
- jnc .Lxts_enc_grandloop
+ jnc .Lxts_enc_grandloop # loop if $len-=6*16 didn't borrow
mov \$16+96,$rounds
sub $rnds_,$rounds
@@ -1867,34 +1986,36 @@ $code.=<<___;
shr \$4,$rounds # restore original value
.Lxts_enc_short:
+ # at the point @tweak[0..5] are populated with tweak values
mov $rounds,$rnds_ # backup $rounds
pxor $rndkey0,@tweak[0]
- add \$16*6,$len
- jz .Lxts_enc_done
+ add \$16*6,$len # restore real remaining $len
+ jz .Lxts_enc_done # done if ($len==0)
pxor $rndkey0,@tweak[1]
cmp \$0x20,$len
- jb .Lxts_enc_one
+ jb .Lxts_enc_one # $len is 1*16
pxor $rndkey0,@tweak[2]
- je .Lxts_enc_two
+ je .Lxts_enc_two # $len is 2*16
pxor $rndkey0,@tweak[3]
cmp \$0x40,$len
- jb .Lxts_enc_three
+ jb .Lxts_enc_three # $len is 3*16
pxor $rndkey0,@tweak[4]
- je .Lxts_enc_four
+ je .Lxts_enc_four # $len is 4*16
- movdqu ($inp),$inout0
+ movdqu ($inp),$inout0 # $len is 5*16
movdqu 16*1($inp),$inout1
movdqu 16*2($inp),$inout2
pxor @tweak[0],$inout0
movdqu 16*3($inp),$inout3
pxor @tweak[1],$inout1
movdqu 16*4($inp),$inout4
- lea 16*5($inp),$inp
+ lea 16*5($inp),$inp # $inp+=5*16
pxor @tweak[2],$inout2
pxor @tweak[3],$inout3
pxor @tweak[4],$inout4
+ pxor $inout5,$inout5
call _aesni_encrypt6
@@ -1902,35 +2023,35 @@ $code.=<<___;
movdqa @tweak[5],@tweak[0]
xorps @tweak[1],$inout1
xorps @tweak[2],$inout2
- movdqu $inout0,($out)
+ movdqu $inout0,($out) # store 5 output blocks
xorps @tweak[3],$inout3
movdqu $inout1,16*1($out)
xorps @tweak[4],$inout4
movdqu $inout2,16*2($out)
movdqu $inout3,16*3($out)
movdqu $inout4,16*4($out)
- lea 16*5($out),$out
+ lea 16*5($out),$out # $out+=5*16
jmp .Lxts_enc_done
.align 16
.Lxts_enc_one:
movups ($inp),$inout0
- lea 16*1($inp),$inp
+ lea 16*1($inp),$inp # inp+=1*16
xorps @tweak[0],$inout0
___
&aesni_generate1("enc",$key,$rounds);
$code.=<<___;
xorps @tweak[0],$inout0
movdqa @tweak[1],@tweak[0]
- movups $inout0,($out)
- lea 16*1($out),$out
+ movups $inout0,($out) # store one output block
+ lea 16*1($out),$out # $out+=1*16
jmp .Lxts_enc_done
.align 16
.Lxts_enc_two:
movups ($inp),$inout0
movups 16($inp),$inout1
- lea 32($inp),$inp
+ lea 32($inp),$inp # $inp+=2*16
xorps @tweak[0],$inout0
xorps @tweak[1],$inout1
@@ -1939,9 +2060,9 @@ $code.=<<___;
xorps @tweak[0],$inout0
movdqa @tweak[2],@tweak[0]
xorps @tweak[1],$inout1
- movups $inout0,($out)
+ movups $inout0,($out) # store 2 output blocks
movups $inout1,16*1($out)
- lea 16*2($out),$out
+ lea 16*2($out),$out # $out+=2*16
jmp .Lxts_enc_done
.align 16
@@ -1949,7 +2070,7 @@ $code.=<<___;
movups ($inp),$inout0
movups 16*1($inp),$inout1
movups 16*2($inp),$inout2
- lea 16*3($inp),$inp
+ lea 16*3($inp),$inp # $inp+=3*16
xorps @tweak[0],$inout0
xorps @tweak[1],$inout1
xorps @tweak[2],$inout2
@@ -1960,10 +2081,10 @@ $code.=<<___;
movdqa @tweak[3],@tweak[0]
xorps @tweak[1],$inout1
xorps @tweak[2],$inout2
- movups $inout0,($out)
+ movups $inout0,($out) # store 3 output blocks
movups $inout1,16*1($out)
movups $inout2,16*2($out)
- lea 16*3($out),$out
+ lea 16*3($out),$out # $out+=3*16
jmp .Lxts_enc_done
.align 16
@@ -1973,7 +2094,7 @@ $code.=<<___;
movups 16*2($inp),$inout2
xorps @tweak[0],$inout0
movups 16*3($inp),$inout3
- lea 16*4($inp),$inp
+ lea 16*4($inp),$inp # $inp+=4*16
xorps @tweak[1],$inout1
xorps @tweak[2],$inout2
xorps @tweak[3],$inout3
@@ -1984,17 +2105,17 @@ $code.=<<___;
movdqa @tweak[4],@tweak[0]
pxor @tweak[1],$inout1
pxor @tweak[2],$inout2
- movdqu $inout0,($out)
+ movdqu $inout0,($out) # store 4 output blocks
pxor @tweak[3],$inout3
movdqu $inout1,16*1($out)
movdqu $inout2,16*2($out)
movdqu $inout3,16*3($out)
- lea 16*4($out),$out
+ lea 16*4($out),$out # $out+=4*16
jmp .Lxts_enc_done
.align 16
.Lxts_enc_done:
- and \$15,$len_
+ and \$15,$len_ # see if $len%16 is 0
jz .Lxts_enc_ret
mov $len_,$len
@@ -2021,18 +2142,60 @@ $code.=<<___;
movups $inout0,-16($out)
.Lxts_enc_ret:
+ xorps %xmm0,%xmm0 # clear register bank
+ pxor %xmm1,%xmm1
+ pxor %xmm2,%xmm2
+ pxor %xmm3,%xmm3
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+$code.=<<___ if (!$win64);
+ pxor %xmm6,%xmm6
+ pxor %xmm7,%xmm7
+ movaps %xmm0,0x00(%rsp) # clear stack
+ pxor %xmm8,%xmm8
+ movaps %xmm0,0x10(%rsp)
+ pxor %xmm9,%xmm9
+ movaps %xmm0,0x20(%rsp)
+ pxor %xmm10,%xmm10
+ movaps %xmm0,0x30(%rsp)
+ pxor %xmm11,%xmm11
+ movaps %xmm0,0x40(%rsp)
+ pxor %xmm12,%xmm12
+ movaps %xmm0,0x50(%rsp)
+ pxor %xmm13,%xmm13
+ movaps %xmm0,0x60(%rsp)
+ pxor %xmm14,%xmm14
+ pxor %xmm15,%xmm15
___
$code.=<<___ if ($win64);
movaps -0xa0(%rbp),%xmm6
+ movaps %xmm0,-0xa0(%rbp) # clear stack
movaps -0x90(%rbp),%xmm7
+ movaps %xmm0,-0x90(%rbp)
movaps -0x80(%rbp),%xmm8
+ movaps %xmm0,-0x80(%rbp)
movaps -0x70(%rbp),%xmm9
+ movaps %xmm0,-0x70(%rbp)
movaps -0x60(%rbp),%xmm10
+ movaps %xmm0,-0x60(%rbp)
movaps -0x50(%rbp),%xmm11
+ movaps %xmm0,-0x50(%rbp)
movaps -0x40(%rbp),%xmm12
+ movaps %xmm0,-0x40(%rbp)
movaps -0x30(%rbp),%xmm13
+ movaps %xmm0,-0x30(%rbp)
movaps -0x20(%rbp),%xmm14
+ movaps %xmm0,-0x20(%rbp)
movaps -0x10(%rbp),%xmm15
+ movaps %xmm0,-0x10(%rbp)
+ movaps %xmm0,0x00(%rsp)
+ movaps %xmm0,0x10(%rsp)
+ movaps %xmm0,0x20(%rsp)
+ movaps %xmm0,0x30(%rsp)
+ movaps %xmm0,0x40(%rsp)
+ movaps %xmm0,0x50(%rsp)
+ movaps %xmm0,0x60(%rsp)
___
$code.=<<___;
lea (%rbp),%rsp
@@ -2053,7 +2216,7 @@ aesni_xts_decrypt:
and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
___
$code.=<<___ if ($win64);
- movaps %xmm6,-0xa8(%rax)
+ movaps %xmm6,-0xa8(%rax) # offload everything
movaps %xmm7,-0x98(%rax)
movaps %xmm8,-0x88(%rax)
movaps %xmm9,-0x78(%rax)
@@ -2116,7 +2279,7 @@ $code.=<<___;
movaps $rndkey1,0x60(%rsp) # save round[0]^round[last]
sub \$16*6,$len
- jc .Lxts_dec_short
+ jc .Lxts_dec_short # if $len-=6*16 borrowed
mov \$16+96,$rounds
lea 32($key_,$rnds_),$key # end of key schedule
@@ -2131,7 +2294,7 @@ $code.=<<___;
movdqu `16*0`($inp),$inout0 # load input
movdqa $rndkey0,$twmask
movdqu `16*1`($inp),$inout1
- pxor @tweak[0],$inout0
+ pxor @tweak[0],$inout0 # intput^=tweak^round[0]
movdqu `16*2`($inp),$inout2
pxor @tweak[1],$inout1
aesdec $rndkey1,$inout0
@@ -2150,7 +2313,7 @@ $code.=<<___;
lea `16*6`($inp),$inp
pxor $twmask,$inout5
- pxor $twres,@tweak[0]
+ pxor $twres,@tweak[0] # calclulate tweaks^round[last]
aesdec $rndkey1,$inout4
pxor $twres,@tweak[1]
movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^last round key
@@ -2194,7 +2357,7 @@ $code.=<<___;
$movkey -80($key,%rax),$rndkey0
jnz .Lxts_dec_loop6
- movdqa (%r8),$twmask
+ movdqa (%r8),$twmask # start calculating next tweak
movdqa $twres,$twtmp
paddd $twres,$twres
aesdec $rndkey1,$inout0
@@ -2288,15 +2451,15 @@ $code.=<<___;
aesdeclast `16*5`(%rsp),$inout5
pxor $twres,@tweak[5]
- lea `16*6`($out),$out
- movups $inout0,`-16*6`($out) # write output
+ lea `16*6`($out),$out # $out+=6*16
+ movups $inout0,`-16*6`($out) # store 6 output blocks
movups $inout1,`-16*5`($out)
movups $inout2,`-16*4`($out)
movups $inout3,`-16*3`($out)
movups $inout4,`-16*2`($out)
movups $inout5,`-16*1`($out)
sub \$16*6,$len
- jnc .Lxts_dec_grandloop
+ jnc .Lxts_dec_grandloop # loop if $len-=6*16 didn't borrow
mov \$16+96,$rounds
sub $rnds_,$rounds
@@ -2304,31 +2467,32 @@ $code.=<<___;
shr \$4,$rounds # restore original value
.Lxts_dec_short:
+ # at the point @tweak[0..5] are populated with tweak values
mov $rounds,$rnds_ # backup $rounds
pxor $rndkey0,@tweak[0]
pxor $rndkey0,@tweak[1]
- add \$16*6,$len
- jz .Lxts_dec_done
+ add \$16*6,$len # restore real remaining $len
+ jz .Lxts_dec_done # done if ($len==0)
pxor $rndkey0,@tweak[2]
cmp \$0x20,$len
- jb .Lxts_dec_one
+ jb .Lxts_dec_one # $len is 1*16
pxor $rndkey0,@tweak[3]
- je .Lxts_dec_two
+ je .Lxts_dec_two # $len is 2*16
pxor $rndkey0,@tweak[4]
cmp \$0x40,$len
- jb .Lxts_dec_three
- je .Lxts_dec_four
+ jb .Lxts_dec_three # $len is 3*16
+ je .Lxts_dec_four # $len is 4*16
- movdqu ($inp),$inout0
+ movdqu ($inp),$inout0 # $len is 5*16
movdqu 16*1($inp),$inout1
movdqu 16*2($inp),$inout2
pxor @tweak[0],$inout0
movdqu 16*3($inp),$inout3
pxor @tweak[1],$inout1
movdqu 16*4($inp),$inout4
- lea 16*5($inp),$inp
+ lea 16*5($inp),$inp # $inp+=5*16
pxor @tweak[2],$inout2
pxor @tweak[3],$inout3
pxor @tweak[4],$inout4
@@ -2338,7 +2502,7 @@ $code.=<<___;
xorps @tweak[0],$inout0
xorps @tweak[1],$inout1
xorps @tweak[2],$inout2
- movdqu $inout0,($out)
+ movdqu $inout0,($out) # store 5 output blocks
xorps @tweak[3],$inout3
movdqu $inout1,16*1($out)
xorps @tweak[4],$inout4
@@ -2347,7 +2511,7 @@ $code.=<<___;
movdqu $inout3,16*3($out)
pcmpgtd @tweak[5],$twtmp
movdqu $inout4,16*4($out)
- lea 16*5($out),$out
+ lea 16*5($out),$out # $out+=5*16
pshufd \$0x13,$twtmp,@tweak[1] # $twres
and \$15,$len_
jz .Lxts_dec_ret
@@ -2361,23 +2525,23 @@ $code.=<<___;
.align 16
.Lxts_dec_one:
movups ($inp),$inout0
- lea 16*1($inp),$inp
+ lea 16*1($inp),$inp # $inp+=1*16
xorps @tweak[0],$inout0
___
&aesni_generate1("dec",$key,$rounds);
$code.=<<___;
xorps @tweak[0],$inout0
movdqa @tweak[1],@tweak[0]
- movups $inout0,($out)
+ movups $inout0,($out) # store one output block
movdqa @tweak[2],@tweak[1]
- lea 16*1($out),$out
+ lea 16*1($out),$out # $out+=1*16
jmp .Lxts_dec_done
.align 16
.Lxts_dec_two:
movups ($inp),$inout0
movups 16($inp),$inout1
- lea 32($inp),$inp
+ lea 32($inp),$inp # $inp+=2*16
xorps @tweak[0],$inout0
xorps @tweak[1],$inout1
@@ -2387,9 +2551,9 @@ $code.=<<___;
movdqa @tweak[2],@tweak[0]
xorps @tweak[1],$inout1
movdqa @tweak[3],@tweak[1]
- movups $inout0,($out)
+ movups $inout0,($out) # store 2 output blocks
movups $inout1,16*1($out)
- lea 16*2($out),$out
+ lea 16*2($out),$out # $out+=2*16
jmp .Lxts_dec_done
.align 16
@@ -2397,7 +2561,7 @@ $code.=<<___;
movups ($inp),$inout0
movups 16*1($inp),$inout1
movups 16*2($inp),$inout2
- lea 16*3($inp),$inp
+ lea 16*3($inp),$inp # $inp+=3*16
xorps @tweak[0],$inout0
xorps @tweak[1],$inout1
xorps @tweak[2],$inout2
@@ -2409,10 +2573,10 @@ $code.=<<___;
xorps @tweak[1],$inout1
movdqa @tweak[4],@tweak[1]
xorps @tweak[2],$inout2
- movups $inout0,($out)
+ movups $inout0,($out) # store 3 output blocks
movups $inout1,16*1($out)
movups $inout2,16*2($out)
- lea 16*3($out),$out
+ lea 16*3($out),$out # $out+=3*16
jmp .Lxts_dec_done
.align 16
@@ -2422,7 +2586,7 @@ $code.=<<___;
movups 16*2($inp),$inout2
xorps @tweak[0],$inout0
movups 16*3($inp),$inout3
- lea 16*4($inp),$inp
+ lea 16*4($inp),$inp # $inp+=4*16
xorps @tweak[1],$inout1
xorps @tweak[2],$inout2
xorps @tweak[3],$inout3
@@ -2434,17 +2598,17 @@ $code.=<<___;
pxor @tweak[1],$inout1
movdqa @tweak[5],@tweak[1]
pxor @tweak[2],$inout2
- movdqu $inout0,($out)
+ movdqu $inout0,($out) # store 4 output blocks
pxor @tweak[3],$inout3
movdqu $inout1,16*1($out)
movdqu $inout2,16*2($out)
movdqu $inout3,16*3($out)
- lea 16*4($out),$out
+ lea 16*4($out),$out # $out+=4*16
jmp .Lxts_dec_done
.align 16
.Lxts_dec_done:
- and \$15,$len_
+ and \$15,$len_ # see if $len%16 is 0
jz .Lxts_dec_ret
.Lxts_dec_done2:
mov $len_,$len
@@ -2482,18 +2646,60 @@ $code.=<<___;
movups $inout0,($out)
.Lxts_dec_ret:
+ xorps %xmm0,%xmm0 # clear register bank
+ pxor %xmm1,%xmm1
+ pxor %xmm2,%xmm2
+ pxor %xmm3,%xmm3
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+___
+$code.=<<___ if (!$win64);
+ pxor %xmm6,%xmm6
+ pxor %xmm7,%xmm7
+ movaps %xmm0,0x00(%rsp) # clear stack
+ pxor %xmm8,%xmm8
+ movaps %xmm0,0x10(%rsp)
+ pxor %xmm9,%xmm9
+ movaps %xmm0,0x20(%rsp)
+ pxor %xmm10,%xmm10
+ movaps %xmm0,0x30(%rsp)
+ pxor %xmm11,%xmm11
+ movaps %xmm0,0x40(%rsp)
+ pxor %xmm12,%xmm12
+ movaps %xmm0,0x50(%rsp)
+ pxor %xmm13,%xmm13
+ movaps %xmm0,0x60(%rsp)
+ pxor %xmm14,%xmm14
+ pxor %xmm15,%xmm15
___
$code.=<<___ if ($win64);
movaps -0xa0(%rbp),%xmm6
+ movaps %xmm0,-0xa0(%rbp) # clear stack
movaps -0x90(%rbp),%xmm7
+ movaps %xmm0,-0x90(%rbp)
movaps -0x80(%rbp),%xmm8
+ movaps %xmm0,-0x80(%rbp)
movaps -0x70(%rbp),%xmm9
+ movaps %xmm0,-0x70(%rbp)
movaps -0x60(%rbp),%xmm10
+ movaps %xmm0,-0x60(%rbp)
movaps -0x50(%rbp),%xmm11
+ movaps %xmm0,-0x50(%rbp)
movaps -0x40(%rbp),%xmm12
+ movaps %xmm0,-0x40(%rbp)
movaps -0x30(%rbp),%xmm13
+ movaps %xmm0,-0x30(%rbp)
movaps -0x20(%rbp),%xmm14
+ movaps %xmm0,-0x20(%rbp)
movaps -0x10(%rbp),%xmm15
+ movaps %xmm0,-0x10(%rbp)
+ movaps %xmm0,0x00(%rsp)
+ movaps %xmm0,0x10(%rsp)
+ movaps %xmm0,0x20(%rsp)
+ movaps %xmm0,0x30(%rsp)
+ movaps %xmm0,0x40(%rsp)
+ movaps %xmm0,0x50(%rsp)
+ movaps %xmm0,0x60(%rsp)
___
$code.=<<___;
lea (%rbp),%rsp
@@ -2548,7 +2754,11 @@ $code.=<<___;
jnc .Lcbc_enc_loop
add \$16,$len
jnz .Lcbc_enc_tail
+ pxor $rndkey0,$rndkey0 # clear register bank
+ pxor $rndkey1,$rndkey1
movups $inout0,($ivp)
+ pxor $inout0,$inout0
+ pxor $inout1,$inout1
jmp .Lcbc_ret
.Lcbc_enc_tail:
@@ -2568,6 +2778,27 @@ $code.=<<___;
#--------------------------- CBC DECRYPT ------------------------------#
.align 16
.Lcbc_decrypt:
+ cmp \$16,$len
+ jne .Lcbc_decrypt_bulk
+
+ # handle single block without allocating stack frame,
+ # useful in ciphertext stealing mode
+ movdqu ($inp),$inout0 # load input
+ movdqu ($ivp),$inout1 # load iv
+ movdqa $inout0,$inout2 # future iv
+___
+ &aesni_generate1("dec",$key,$rnds_);
+$code.=<<___;
+ pxor $rndkey0,$rndkey0 # clear register bank
+ pxor $rndkey1,$rndkey1
+ movdqu $inout2,($ivp) # store iv
+ xorps $inout1,$inout0 # ^=iv
+ pxor $inout1,$inout1
+ movups $inout0,($out) # store output
+ pxor $inout0,$inout0
+ jmp .Lcbc_ret
+.align 16
+.Lcbc_decrypt_bulk:
lea (%rsp),%rax
push %rbp
sub \$$frame_size,%rsp
@@ -2609,11 +2840,11 @@ $code.=<<___;
cmp \$0x70,$len
jbe .Lcbc_dec_six_or_seven
- and \$`1<<26|1<<22`,%r9d # isolate XSAVE+MOVBE
- sub \$0x50,$len
+ and \$`1<<26|1<<22`,%r9d # isolate XSAVE+MOVBE
+ sub \$0x50,$len # $len is biased by -5*16
cmp \$`1<<22`,%r9d # check for MOVBE without XSAVE
- je .Lcbc_dec_loop6_enter
- sub \$0x20,$len
+ je .Lcbc_dec_loop6_enter # [which denotes Atom Silvermont]
+ sub \$0x20,$len # $len is biased by -7*16
lea 0x70($key),$key # size optimization
jmp .Lcbc_dec_loop8_enter
.align 16
@@ -2740,7 +2971,7 @@ $code.=<<___;
movaps $inout7,$inout0
lea -0x70($key),$key
add \$0x70,$len
- jle .Lcbc_dec_tail_collected
+ jle .Lcbc_dec_clear_tail_collected
movups $inout7,($out)
lea 0x10($out),$out
cmp \$0x50,$len
@@ -2759,14 +2990,19 @@ $code.=<<___;
movdqu $inout0,($out)
pxor $in1,$inout2
movdqu $inout1,0x10($out)
+ pxor $inout1,$inout1 # clear register bank
pxor $in2,$inout3
movdqu $inout2,0x20($out)
+ pxor $inout2,$inout2
pxor $in3,$inout4
movdqu $inout3,0x30($out)
+ pxor $inout3,$inout3
pxor $in4,$inout5
movdqu $inout4,0x40($out)
+ pxor $inout4,$inout4
lea 0x50($out),$out
movdqa $inout5,$inout0
+ pxor $inout5,$inout5
jmp .Lcbc_dec_tail_collected
.align 16
@@ -2781,16 +3017,23 @@ $code.=<<___;
movdqu $inout0,($out)
pxor $in1,$inout2
movdqu $inout1,0x10($out)
+ pxor $inout1,$inout1 # clear register bank
pxor $in2,$inout3
movdqu $inout2,0x20($out)
+ pxor $inout2,$inout2
pxor $in3,$inout4
movdqu $inout3,0x30($out)
+ pxor $inout3,$inout3
pxor $in4,$inout5
movdqu $inout4,0x40($out)
+ pxor $inout4,$inout4
pxor $inout7,$inout6
movdqu $inout5,0x50($out)
+ pxor $inout5,$inout5
lea 0x60($out),$out
movdqa $inout6,$inout0
+ pxor $inout6,$inout6
+ pxor $inout7,$inout7
jmp .Lcbc_dec_tail_collected
.align 16
@@ -2834,31 +3077,31 @@ $code.=<<___;
movdqa $inout5,$inout0
add \$0x50,$len
- jle .Lcbc_dec_tail_collected
+ jle .Lcbc_dec_clear_tail_collected
movups $inout5,($out)
lea 0x10($out),$out
.Lcbc_dec_tail:
movups ($inp),$inout0
sub \$0x10,$len
- jbe .Lcbc_dec_one
+ jbe .Lcbc_dec_one # $len is 1*16 or less
movups 0x10($inp),$inout1
movaps $inout0,$in0
sub \$0x10,$len
- jbe .Lcbc_dec_two
+ jbe .Lcbc_dec_two # $len is 2*16 or less
movups 0x20($inp),$inout2
movaps $inout1,$in1
sub \$0x10,$len
- jbe .Lcbc_dec_three
+ jbe .Lcbc_dec_three # $len is 3*16 or less
movups 0x30($inp),$inout3
movaps $inout2,$in2
sub \$0x10,$len
- jbe .Lcbc_dec_four
+ jbe .Lcbc_dec_four # $len is 4*16 or less
- movups 0x40($inp),$inout4
+ movups 0x40($inp),$inout4 # $len is 5*16 or less
movaps $inout3,$in3
movaps $inout4,$in4
xorps $inout5,$inout5
@@ -2869,12 +3112,17 @@ $code.=<<___;
movdqu $inout0,($out)
pxor $in1,$inout2
movdqu $inout1,0x10($out)
+ pxor $inout1,$inout1 # clear register bank
pxor $in2,$inout3
movdqu $inout2,0x20($out)
+ pxor $inout2,$inout2
pxor $in3,$inout4
movdqu $inout3,0x30($out)
+ pxor $inout3,$inout3
lea 0x40($out),$out
movdqa $inout4,$inout0
+ pxor $inout4,$inout4
+ pxor $inout5,$inout5
sub \$0x10,$len
jmp .Lcbc_dec_tail_collected
@@ -2896,6 +3144,7 @@ $code.=<<___;
pxor $in0,$inout1
movdqu $inout0,($out)
movdqa $inout1,$inout0
+ pxor $inout1,$inout1 # clear register bank
lea 0x10($out),$out
jmp .Lcbc_dec_tail_collected
.align 16
@@ -2908,7 +3157,9 @@ $code.=<<___;
movdqu $inout0,($out)
pxor $in1,$inout2
movdqu $inout1,0x10($out)
+ pxor $inout1,$inout1 # clear register bank
movdqa $inout2,$inout0
+ pxor $inout2,$inout2
lea 0x20($out),$out
jmp .Lcbc_dec_tail_collected
.align 16
@@ -2921,41 +3172,71 @@ $code.=<<___;
movdqu $inout0,($out)
pxor $in1,$inout2
movdqu $inout1,0x10($out)
+ pxor $inout1,$inout1 # clear register bank
pxor $in2,$inout3
movdqu $inout2,0x20($out)
+ pxor $inout2,$inout2
movdqa $inout3,$inout0
+ pxor $inout3,$inout3
lea 0x30($out),$out
jmp .Lcbc_dec_tail_collected
.align 16
+.Lcbc_dec_clear_tail_collected:
+ pxor $inout1,$inout1 # clear register bank
+ pxor $inout2,$inout2
+ pxor $inout3,$inout3
+___
+$code.=<<___ if (!$win64);
+ pxor $inout4,$inout4 # %xmm6..9
+ pxor $inout5,$inout5
+ pxor $inout6,$inout6
+ pxor $inout7,$inout7
+___
+$code.=<<___;
.Lcbc_dec_tail_collected:
movups $iv,($ivp)
and \$15,$len
jnz .Lcbc_dec_tail_partial
movups $inout0,($out)
+ pxor $inout0,$inout0
jmp .Lcbc_dec_ret
.align 16
.Lcbc_dec_tail_partial:
movaps $inout0,(%rsp)
+ pxor $inout0,$inout0
mov \$16,%rcx
mov $out,%rdi
sub $len,%rcx
lea (%rsp),%rsi
- .long 0x9066A4F3 # rep movsb
+ .long 0x9066A4F3 # rep movsb
+ movdqa $inout0,(%rsp)
.Lcbc_dec_ret:
+ xorps $rndkey0,$rndkey0 # %xmm0
+ pxor $rndkey1,$rndkey1
___
$code.=<<___ if ($win64);
movaps 0x10(%rsp),%xmm6
+ movaps %xmm0,0x10(%rsp) # clear stack
movaps 0x20(%rsp),%xmm7
+ movaps %xmm0,0x20(%rsp)
movaps 0x30(%rsp),%xmm8
+ movaps %xmm0,0x30(%rsp)
movaps 0x40(%rsp),%xmm9
+ movaps %xmm0,0x40(%rsp)
movaps 0x50(%rsp),%xmm10
+ movaps %xmm0,0x50(%rsp)
movaps 0x60(%rsp),%xmm11
+ movaps %xmm0,0x60(%rsp)
movaps 0x70(%rsp),%xmm12
+ movaps %xmm0,0x70(%rsp)
movaps 0x80(%rsp),%xmm13
+ movaps %xmm0,0x80(%rsp)
movaps 0x90(%rsp),%xmm14
+ movaps %xmm0,0x90(%rsp)
movaps 0xa0(%rsp),%xmm15
+ movaps %xmm0,0xa0(%rsp)
___
$code.=<<___;
lea (%rbp),%rsp
@@ -2965,8 +3246,15 @@ $code.=<<___;
.size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
___
}
-# int $PREFIX_set_[en|de]crypt_key (const unsigned char *userKey,
+# int ${PREFIX}_set_decrypt_key(const unsigned char *inp,
# int bits, AES_KEY *key)
+#
+# input: $inp user-supplied key
+# $bits $inp length in bits
+# $key pointer to key schedule
+# output: %eax 0 denoting success, -1 or -2 - failure (see C)
+# *$key key schedule
+#
{ my ($inp,$bits,$key) = @_4args;
$bits =~ s/%r/%e/;
@@ -3003,7 +3291,9 @@ ${PREFIX}_set_decrypt_key:
$movkey ($key),%xmm0 # inverse middle
aesimc %xmm0,%xmm0
+ pxor %xmm1,%xmm1
$movkey %xmm0,($inp)
+ pxor %xmm0,%xmm0
.Ldec_key_ret:
add \$8,%rsp
ret
@@ -3020,6 +3310,22 @@ ___
# Agressively optimized in respect to aeskeygenassist's critical path
# and is contained in %xmm0-5 to meet Win64 ABI requirement.
#
+# int ${PREFIX}_set_encrypt_key(const unsigned char *inp,
+# int bits, AES_KEY * const key);
+#
+# input: $inp user-supplied key
+# $bits $inp length in bits
+# $key pointer to key schedule
+# output: %eax 0 denoting success, -1 or -2 - failure (see C)
+# $bits rounds-1 (used in aesni_set_decrypt_key)
+# *$key key schedule
+# $key pointer to key schedule (used in
+# aesni_set_decrypt_key)
+#
+# Subroutine is frame-less, which means that only volatile registers
+# are used. Note that it's declared "abi-omnipotent", which means that
+# amount of volatile registers is smaller on Windows.
+#
$code.=<<___;
.globl ${PREFIX}_set_encrypt_key
.type ${PREFIX}_set_encrypt_key,\@abi-omnipotent
@@ -3033,9 +3339,11 @@ __aesni_set_encrypt_key:
test $key,$key
jz .Lenc_key_ret
+ mov \$`1<<28|1<<11`,%r10d # AVX and XOP bits
movups ($inp),%xmm0 # pull first 128 bits of *userKey
xorps %xmm4,%xmm4 # low dword of xmm4 is assumed 0
- lea 16($key),%rax
+ and OPENSSL_ia32cap_P+4(%rip),%r10d
+ lea 16($key),%rax # %rax is used as modifiable copy of $key
cmp \$256,$bits
je .L14rounds
cmp \$192,$bits
@@ -3045,6 +3353,9 @@ __aesni_set_encrypt_key:
.L10rounds:
mov \$9,$bits # 10 rounds for 128-bit key
+ cmp \$`1<<28`,%r10d # AVX, bit no XOP
+ je .L10rounds_alt
+
$movkey %xmm0,($key) # round 0
aeskeygenassist \$0x1,%xmm0,%xmm1 # round 1
call .Lkey_expansion_128_cold
@@ -3072,9 +3383,79 @@ __aesni_set_encrypt_key:
jmp .Lenc_key_ret
.align 16
+.L10rounds_alt:
+ movdqa .Lkey_rotate(%rip),%xmm5
+ mov \$8,%r10d
+ movdqa .Lkey_rcon1(%rip),%xmm4
+ movdqa %xmm0,%xmm2
+ movdqu %xmm0,($key)
+ jmp .Loop_key128
+
+.align 16
+.Loop_key128:
+ pshufb %xmm5,%xmm0
+ aesenclast %xmm4,%xmm0
+ pslld \$1,%xmm4
+ lea 16(%rax),%rax
+
+ movdqa %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm3,%xmm2
+
+ pxor %xmm2,%xmm0
+ movdqu %xmm0,-16(%rax)
+ movdqa %xmm0,%xmm2
+
+ dec %r10d
+ jnz .Loop_key128
+
+ movdqa .Lkey_rcon1b(%rip),%xmm4
+
+ pshufb %xmm5,%xmm0
+ aesenclast %xmm4,%xmm0
+ pslld \$1,%xmm4
+
+ movdqa %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm3,%xmm2
+
+ pxor %xmm2,%xmm0
+ movdqu %xmm0,(%rax)
+
+ movdqa %xmm0,%xmm2
+ pshufb %xmm5,%xmm0
+ aesenclast %xmm4,%xmm0
+
+ movdqa %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm2,%xmm3
+ pslldq \$4,%xmm2
+ pxor %xmm3,%xmm2
+
+ pxor %xmm2,%xmm0
+ movdqu %xmm0,16(%rax)
+
+ mov $bits,96(%rax) # 240($key)
+ xor %eax,%eax
+ jmp .Lenc_key_ret
+
+.align 16
.L12rounds:
movq 16($inp),%xmm2 # remaining 1/3 of *userKey
mov \$11,$bits # 12 rounds for 192
+ cmp \$`1<<28`,%r10d # AVX, but no XOP
+ je .L12rounds_alt
+
$movkey %xmm0,($key) # round 0
aeskeygenassist \$0x1,%xmm2,%xmm1 # round 1,2
call .Lkey_expansion_192a_cold
@@ -3098,10 +3479,54 @@ __aesni_set_encrypt_key:
jmp .Lenc_key_ret
.align 16
+.L12rounds_alt:
+ movdqa .Lkey_rotate192(%rip),%xmm5
+ movdqa .Lkey_rcon1(%rip),%xmm4
+ mov \$8,%r10d
+ movdqu %xmm0,($key)
+ jmp .Loop_key192
+
+.align 16
+.Loop_key192:
+ movq %xmm2,0(%rax)
+ movdqa %xmm2,%xmm1
+ pshufb %xmm5,%xmm2
+ aesenclast %xmm4,%xmm2
+ pslld \$1, %xmm4
+ lea 24(%rax),%rax
+
+ movdqa %xmm0,%xmm3
+ pslldq \$4,%xmm0
+ pxor %xmm0,%xmm3
+ pslldq \$4,%xmm0
+ pxor %xmm0,%xmm3
+ pslldq \$4,%xmm0
+ pxor %xmm3,%xmm0
+
+ pshufd \$0xff,%xmm0,%xmm3
+ pxor %xmm1,%xmm3
+ pslldq \$4,%xmm1
+ pxor %xmm1,%xmm3
+
+ pxor %xmm2,%xmm0
+ pxor %xmm3,%xmm2
+ movdqu %xmm0,-16(%rax)
+
+ dec %r10d
+ jnz .Loop_key192
+
+ mov $bits,32(%rax) # 240($key)
+ xor %eax,%eax
+ jmp .Lenc_key_ret
+
+.align 16
.L14rounds:
movups 16($inp),%xmm2 # remaning half of *userKey
mov \$13,$bits # 14 rounds for 256
lea 16(%rax),%rax
+ cmp \$`1<<28`,%r10d # AVX, but no XOP
+ je .L14rounds_alt
+
$movkey %xmm0,($key) # round 0
$movkey %xmm2,16($key) # round 1
aeskeygenassist \$0x1,%xmm2,%xmm1 # round 2
@@ -3136,9 +3561,69 @@ __aesni_set_encrypt_key:
jmp .Lenc_key_ret
.align 16
+.L14rounds_alt:
+ movdqa .Lkey_rotate(%rip),%xmm5
+ movdqa .Lkey_rcon1(%rip),%xmm4
+ mov \$7,%r10d
+ movdqu %xmm0,0($key)
+ movdqa %xmm2,%xmm1
+ movdqu %xmm2,16($key)
+ jmp .Loop_key256
+
+.align 16
+.Loop_key256:
+ pshufb %xmm5,%xmm2
+ aesenclast %xmm4,%xmm2
+
+ movdqa %xmm0,%xmm3
+ pslldq \$4,%xmm0
+ pxor %xmm0,%xmm3
+ pslldq \$4,%xmm0
+ pxor %xmm0,%xmm3
+ pslldq \$4,%xmm0
+ pxor %xmm3,%xmm0
+ pslld \$1,%xmm4
+
+ pxor %xmm2,%xmm0
+ movdqu %xmm0,(%rax)
+
+ dec %r10d
+ jz .Ldone_key256
+
+ pshufd \$0xff,%xmm0,%xmm2
+ pxor %xmm3,%xmm3
+ aesenclast %xmm3,%xmm2
+
+ movdqa %xmm1,%xmm3
+ pslldq \$4,%xmm1
+ pxor %xmm1,%xmm3
+ pslldq \$4,%xmm1
+ pxor %xmm1,%xmm3
+ pslldq \$4,%xmm1
+ pxor %xmm3,%xmm1
+
+ pxor %xmm1,%xmm2
+ movdqu %xmm2,16(%rax)
+ lea 32(%rax),%rax
+ movdqa %xmm2,%xmm1
+
+ jmp .Loop_key256
+
+.Ldone_key256:
+ mov $bits,16(%rax) # 240($key)
+ xor %eax,%eax
+ jmp .Lenc_key_ret
+
+.align 16
.Lbad_keybits:
mov \$-2,%rax
.Lenc_key_ret:
+ pxor %xmm0,%xmm0
+ pxor %xmm1,%xmm1
+ pxor %xmm2,%xmm2
+ pxor %xmm3,%xmm3
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
add \$8,%rsp
ret
.LSEH_end_set_encrypt_key:
@@ -3228,6 +3713,14 @@ $code.=<<___;
.long 0x87,0,1,0
.Lincrement1:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+.Lkey_rotate:
+ .long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d
+.Lkey_rotate192:
+ .long 0x04070605,0x04070605,0x04070605,0x04070605
+.Lkey_rcon1:
+ .long 1,1,1,1
+.Lkey_rcon1b:
+ .long 0x1b,0x1b,0x1b,0x1b
.asciz "AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>"
.align 64
@@ -3345,7 +3838,7 @@ cbc_se_handler:
mov 152($context),%rax # pull context->Rsp
mov 248($context),%rbx # pull context->Rip
- lea .Lcbc_decrypt(%rip),%r10
+ lea .Lcbc_decrypt_bulk(%rip),%r10
cmp %r10,%rbx # context->Rip<"prologue" label
jb .Lcommon_seh_tail
diff --git a/src/crypto/aes/asm/aesv8-armx.pl b/src/crypto/aes/asm/aesv8-armx.pl
index 703da04..b0916f6 100644
--- a/src/crypto/aes/asm/aesv8-armx.pl
+++ b/src/crypto/aes/asm/aesv8-armx.pl
@@ -24,11 +24,23 @@
#
# CBC enc CBC dec CTR
# Apple A7 2.39 1.20 1.20
-# Cortex-A53 2.45 1.87 1.94
-# Cortex-A57 3.64 1.34 1.32
+# Cortex-A53 1.32 1.29 1.46
+# Cortex-A57(*) 1.95 0.85 0.93
+# Denver 1.96 0.86 0.80
+#
+# (*) original 3.64/1.34/1.32 results were for r0p0 revision
+# and are still same even for updated module;
$flavour = shift;
-open STDOUT,">".shift;
+$output = shift;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
$prefix="aes_v8";
@@ -38,10 +50,9 @@ $code=<<___;
#if __ARM_MAX_ARCH__>=7
.text
___
-
-$code.=<<___ if ($flavour =~ /64/);
+$code.=<<___ if ($flavour =~ /64/);
#if !defined(__clang__)
-.arch armv8-a+crypto
+.arch armv8-a+crypto
#endif
___
$code.=".arch armv7-a\n.fpu neon\n.code 32\n" if ($flavour !~ /64/);
@@ -61,7 +72,7 @@ my ($zero,$rcon,$mask,$in0,$in1,$tmp,$key)=
$code.=<<___;
.align 5
-rcon:
+.Lrcon:
.long 0x01,0x01,0x01,0x01
.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat
.long 0x1b,0x1b,0x1b,0x1b
@@ -90,7 +101,7 @@ $code.=<<___;
tst $bits,#0x3f
b.ne .Lenc_key_abort
- adr $ptr,rcon
+ adr $ptr,.Lrcon
cmp $bits,#192
veor $zero,$zero,$zero
@@ -313,17 +324,17 @@ ${prefix}_${dir}crypt:
.Loop_${dir}c:
aes$e $inout,$rndkey0
- vld1.32 {$rndkey0},[$key],#16
aes$mc $inout,$inout
+ vld1.32 {$rndkey0},[$key],#16
subs $rounds,$rounds,#2
aes$e $inout,$rndkey1
- vld1.32 {$rndkey1},[$key],#16
aes$mc $inout,$inout
+ vld1.32 {$rndkey1},[$key],#16
b.gt .Loop_${dir}c
aes$e $inout,$rndkey0
- vld1.32 {$rndkey0},[$key]
aes$mc $inout,$inout
+ vld1.32 {$rndkey0},[$key]
aes$e $inout,$rndkey1
veor $inout,$inout,$rndkey0
@@ -341,6 +352,7 @@ my ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12");
my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7));
my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
+my ($key4,$key5,$key6,$key7)=("x6","x12","x14",$key);
### q8-q15 preloaded key schedule
@@ -390,25 +402,50 @@ $code.=<<___;
veor $rndzero_n_last,q8,$rndlast
b.eq .Lcbc_enc128
+ vld1.32 {$in0-$in1},[$key_]
+ add $key_,$key,#16
+ add $key4,$key,#16*4
+ add $key5,$key,#16*5
+ aese $dat,q8
+ aesmc $dat,$dat
+ add $key6,$key,#16*6
+ add $key7,$key,#16*7
+ b .Lenter_cbc_enc
+
+.align 4
.Loop_cbc_enc:
aese $dat,q8
- vld1.32 {q8},[$key_],#16
aesmc $dat,$dat
- subs $cnt,$cnt,#2
+ vst1.8 {$ivec},[$out],#16
+.Lenter_cbc_enc:
aese $dat,q9
- vld1.32 {q9},[$key_],#16
aesmc $dat,$dat
- b.gt .Loop_cbc_enc
+ aese $dat,$in0
+ aesmc $dat,$dat
+ vld1.32 {q8},[$key4]
+ cmp $rounds,#4
+ aese $dat,$in1
+ aesmc $dat,$dat
+ vld1.32 {q9},[$key5]
+ b.eq .Lcbc_enc192
aese $dat,q8
aesmc $dat,$dat
+ vld1.32 {q8},[$key6]
+ aese $dat,q9
+ aesmc $dat,$dat
+ vld1.32 {q9},[$key7]
+ nop
+
+.Lcbc_enc192:
+ aese $dat,q8
+ aesmc $dat,$dat
subs $len,$len,#16
aese $dat,q9
aesmc $dat,$dat
cclr $step,eq
aese $dat,q10
aesmc $dat,$dat
- add $key_,$key,#16
aese $dat,q11
aesmc $dat,$dat
vld1.8 {q8},[$inp],$step
@@ -417,16 +454,14 @@ $code.=<<___;
veor q8,q8,$rndzero_n_last
aese $dat,q13
aesmc $dat,$dat
- vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vld1.32 {q9},[$key_] // re-pre-load rndkey[1]
aese $dat,q14
aesmc $dat,$dat
aese $dat,q15
-
- mov $cnt,$rounds
veor $ivec,$dat,$rndlast
- vst1.8 {$ivec},[$out],#16
b.hs .Loop_cbc_enc
+ vst1.8 {$ivec},[$out],#16
b .Lcbc_done
.align 5
@@ -488,79 +523,78 @@ $code.=<<___;
.Loop3x_cbc_dec:
aesd $dat0,q8
- aesd $dat1,q8
- aesd $dat2,q8
- vld1.32 {q8},[$key_],#16
aesimc $dat0,$dat0
+ aesd $dat1,q8
aesimc $dat1,$dat1
+ aesd $dat2,q8
aesimc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aesd $dat0,q9
- aesd $dat1,q9
- aesd $dat2,q9
- vld1.32 {q9},[$key_],#16
aesimc $dat0,$dat0
+ aesd $dat1,q9
aesimc $dat1,$dat1
+ aesd $dat2,q9
aesimc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
b.gt .Loop3x_cbc_dec
aesd $dat0,q8
- aesd $dat1,q8
- aesd $dat2,q8
- veor $tmp0,$ivec,$rndlast
aesimc $dat0,$dat0
+ aesd $dat1,q8
aesimc $dat1,$dat1
+ aesd $dat2,q8
aesimc $dat2,$dat2
+ veor $tmp0,$ivec,$rndlast
+ subs $len,$len,#0x30
veor $tmp1,$in0,$rndlast
+ mov.lo x6,$len // x6, $cnt, is zero at this point
aesd $dat0,q9
- aesd $dat1,q9
- aesd $dat2,q9
- veor $tmp2,$in1,$rndlast
- subs $len,$len,#0x30
aesimc $dat0,$dat0
+ aesd $dat1,q9
aesimc $dat1,$dat1
+ aesd $dat2,q9
aesimc $dat2,$dat2
- vorr $ivec,$in2,$in2
- mov.lo x6,$len // x6, $cnt, is zero at this point
- aesd $dat0,q12
- aesd $dat1,q12
- aesd $dat2,q12
+ veor $tmp2,$in1,$rndlast
add $inp,$inp,x6 // $inp is adjusted in such way that
// at exit from the loop $dat1-$dat2
// are loaded with last "words"
+ vorr $ivec,$in2,$in2
+ mov $key_,$key
+ aesd $dat0,q12
aesimc $dat0,$dat0
+ aesd $dat1,q12
aesimc $dat1,$dat1
+ aesd $dat2,q12
aesimc $dat2,$dat2
- mov $key_,$key
- aesd $dat0,q13
- aesd $dat1,q13
- aesd $dat2,q13
vld1.8 {$in0},[$inp],#16
+ aesd $dat0,q13
aesimc $dat0,$dat0
+ aesd $dat1,q13
aesimc $dat1,$dat1
+ aesd $dat2,q13
aesimc $dat2,$dat2
vld1.8 {$in1},[$inp],#16
aesd $dat0,q14
- aesd $dat1,q14
- aesd $dat2,q14
- vld1.8 {$in2},[$inp],#16
aesimc $dat0,$dat0
+ aesd $dat1,q14
aesimc $dat1,$dat1
+ aesd $dat2,q14
aesimc $dat2,$dat2
- vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ vld1.8 {$in2},[$inp],#16
aesd $dat0,q15
aesd $dat1,q15
aesd $dat2,q15
-
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
add $cnt,$rounds,#2
veor $tmp0,$tmp0,$dat0
veor $tmp1,$tmp1,$dat1
veor $dat2,$dat2,$tmp2
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
- vorr $dat0,$in0,$in0
vst1.8 {$tmp0},[$out],#16
- vorr $dat1,$in1,$in1
+ vorr $dat0,$in0,$in0
vst1.8 {$tmp1},[$out],#16
+ vorr $dat1,$in1,$in1
vst1.8 {$dat2},[$out],#16
vorr $dat2,$in2,$in2
b.hs .Loop3x_cbc_dec
@@ -571,39 +605,39 @@ $code.=<<___;
.Lcbc_dec_tail:
aesd $dat1,q8
- aesd $dat2,q8
- vld1.32 {q8},[$key_],#16
aesimc $dat1,$dat1
+ aesd $dat2,q8
aesimc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aesd $dat1,q9
- aesd $dat2,q9
- vld1.32 {q9},[$key_],#16
aesimc $dat1,$dat1
+ aesd $dat2,q9
aesimc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
b.gt .Lcbc_dec_tail
aesd $dat1,q8
- aesd $dat2,q8
aesimc $dat1,$dat1
+ aesd $dat2,q8
aesimc $dat2,$dat2
aesd $dat1,q9
- aesd $dat2,q9
aesimc $dat1,$dat1
+ aesd $dat2,q9
aesimc $dat2,$dat2
aesd $dat1,q12
- aesd $dat2,q12
aesimc $dat1,$dat1
+ aesd $dat2,q12
aesimc $dat2,$dat2
cmn $len,#0x20
aesd $dat1,q13
- aesd $dat2,q13
aesimc $dat1,$dat1
+ aesd $dat2,q13
aesimc $dat2,$dat2
veor $tmp1,$ivec,$rndlast
aesd $dat1,q14
- aesd $dat2,q14
aesimc $dat1,$dat1
+ aesd $dat2,q14
aesimc $dat2,$dat2
veor $tmp2,$in1,$rndlast
aesd $dat1,q15
@@ -704,70 +738,69 @@ $code.=<<___;
.align 4
.Loop3x_ctr32:
aese $dat0,q8
- aese $dat1,q8
- aese $dat2,q8
- vld1.32 {q8},[$key_],#16
aesmc $dat0,$dat0
+ aese $dat1,q8
aesmc $dat1,$dat1
+ aese $dat2,q8
aesmc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aese $dat0,q9
- aese $dat1,q9
- aese $dat2,q9
- vld1.32 {q9},[$key_],#16
aesmc $dat0,$dat0
+ aese $dat1,q9
aesmc $dat1,$dat1
+ aese $dat2,q9
aesmc $dat2,$dat2
+ vld1.32 {q9},[$key_],#16
b.gt .Loop3x_ctr32
aese $dat0,q8
- aese $dat1,q8
- aese $dat2,q8
- mov $key_,$key
aesmc $tmp0,$dat0
- vld1.8 {$in0},[$inp],#16
+ aese $dat1,q8
aesmc $tmp1,$dat1
- aesmc $dat2,$dat2
+ vld1.8 {$in0},[$inp],#16
vorr $dat0,$ivec,$ivec
- aese $tmp0,q9
+ aese $dat2,q8
+ aesmc $dat2,$dat2
vld1.8 {$in1},[$inp],#16
- aese $tmp1,q9
- aese $dat2,q9
vorr $dat1,$ivec,$ivec
+ aese $tmp0,q9
aesmc $tmp0,$tmp0
- vld1.8 {$in2},[$inp],#16
+ aese $tmp1,q9
aesmc $tmp1,$tmp1
+ vld1.8 {$in2},[$inp],#16
+ mov $key_,$key
+ aese $dat2,q9
aesmc $tmp2,$dat2
vorr $dat2,$ivec,$ivec
add $tctr0,$ctr,#1
aese $tmp0,q12
+ aesmc $tmp0,$tmp0
aese $tmp1,q12
- aese $tmp2,q12
+ aesmc $tmp1,$tmp1
veor $in0,$in0,$rndlast
add $tctr1,$ctr,#2
- aesmc $tmp0,$tmp0
- aesmc $tmp1,$tmp1
+ aese $tmp2,q12
aesmc $tmp2,$tmp2
veor $in1,$in1,$rndlast
add $ctr,$ctr,#3
aese $tmp0,q13
+ aesmc $tmp0,$tmp0
aese $tmp1,q13
- aese $tmp2,q13
+ aesmc $tmp1,$tmp1
veor $in2,$in2,$rndlast
rev $tctr0,$tctr0
- aesmc $tmp0,$tmp0
- vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
- aesmc $tmp1,$tmp1
+ aese $tmp2,q13
aesmc $tmp2,$tmp2
vmov.32 ${dat0}[3], $tctr0
rev $tctr1,$tctr1
aese $tmp0,q14
+ aesmc $tmp0,$tmp0
aese $tmp1,q14
- aese $tmp2,q14
+ aesmc $tmp1,$tmp1
vmov.32 ${dat1}[3], $tctr1
rev $tctr2,$ctr
- aesmc $tmp0,$tmp0
- aesmc $tmp1,$tmp1
+ aese $tmp2,q14
aesmc $tmp2,$tmp2
vmov.32 ${dat2}[3], $tctr2
subs $len,$len,#3
@@ -775,13 +808,14 @@ $code.=<<___;
aese $tmp1,q15
aese $tmp2,q15
- mov $cnt,$rounds
veor $in0,$in0,$tmp0
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ vst1.8 {$in0},[$out],#16
veor $in1,$in1,$tmp1
+ mov $cnt,$rounds
+ vst1.8 {$in1},[$out],#16
veor $in2,$in2,$tmp2
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
- vst1.8 {$in0},[$out],#16
- vst1.8 {$in1},[$out],#16
vst1.8 {$in2},[$out],#16
b.hs .Loop3x_ctr32
@@ -793,40 +827,40 @@ $code.=<<___;
.Lctr32_tail:
aese $dat0,q8
- aese $dat1,q8
- vld1.32 {q8},[$key_],#16
aesmc $dat0,$dat0
+ aese $dat1,q8
aesmc $dat1,$dat1
+ vld1.32 {q8},[$key_],#16
subs $cnt,$cnt,#2
aese $dat0,q9
- aese $dat1,q9
- vld1.32 {q9},[$key_],#16
aesmc $dat0,$dat0
+ aese $dat1,q9
aesmc $dat1,$dat1
+ vld1.32 {q9},[$key_],#16
b.gt .Lctr32_tail
aese $dat0,q8
- aese $dat1,q8
aesmc $dat0,$dat0
+ aese $dat1,q8
aesmc $dat1,$dat1
aese $dat0,q9
- aese $dat1,q9
aesmc $dat0,$dat0
+ aese $dat1,q9
aesmc $dat1,$dat1
vld1.8 {$in0},[$inp],$step
aese $dat0,q12
- aese $dat1,q12
- vld1.8 {$in1},[$inp]
aesmc $dat0,$dat0
+ aese $dat1,q12
aesmc $dat1,$dat1
+ vld1.8 {$in1},[$inp]
aese $dat0,q13
- aese $dat1,q13
aesmc $dat0,$dat0
+ aese $dat1,q13
aesmc $dat1,$dat1
- aese $dat0,q14
- aese $dat1,q14
veor $in0,$in0,$rndlast
+ aese $dat0,q14
aesmc $dat0,$dat0
+ aese $dat1,q14
aesmc $dat1,$dat1
veor $in1,$in1,$rndlast
aese $dat0,q15
diff --git a/src/crypto/aes/asm/bsaes-armv7.pl b/src/crypto/aes/asm/bsaes-armv7.pl
index d70f3ea..a5e4a98 100644
--- a/src/crypto/aes/asm/bsaes-armv7.pl
+++ b/src/crypto/aes/asm/bsaes-armv7.pl
@@ -47,8 +47,20 @@
#
# <ard.biesheuvel@linaro.org>
-while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
my @XMM=map("q$_",(0..15));
@@ -703,29 +715,35 @@ $code.=<<___;
# define BSAES_ASM_EXTENDED_KEY
# define XTS_CHAIN_TWEAK
# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
#endif
#ifdef __thumb__
# define adrl adr
#endif
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
+.fpu neon
+
.text
.syntax unified @ ARMv7-capable assembler is expected to handle this
-#ifdef __thumb2__
+#if defined(__thumb2__) && !defined(__APPLE__)
.thumb
#else
.code 32
#endif
-.fpu neon
-
.type _bsaes_decrypt8,%function
.align 4
_bsaes_decrypt8:
adr $const,_bsaes_decrypt8
vldmia $key!, {@XMM[9]} @ round 0 key
+#ifdef __APPLE__
+ adr $const,.LM0ISR
+#else
add $const,$const,#.LM0ISR-_bsaes_decrypt8
+#endif
vldmia $const!, {@XMM[8]} @ .LM0ISR
veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key
@@ -820,7 +838,11 @@ _bsaes_const:
_bsaes_encrypt8:
adr $const,_bsaes_encrypt8
vldmia $key!, {@XMM[9]} @ round 0 key
+#ifdef __APPLE__
+ adr $const,.LM0SR
+#else
sub $const,$const,#_bsaes_encrypt8-.LM0SR
+#endif
vldmia $const!, {@XMM[8]} @ .LM0SR
_bsaes_encrypt8_alt:
@@ -924,7 +946,11 @@ $code.=<<___;
_bsaes_key_convert:
adr $const,_bsaes_key_convert
vld1.8 {@XMM[7]}, [$inp]! @ load round 0 key
+#ifdef __APPLE__
+ adr $const,.LM0
+#else
sub $const,$const,#_bsaes_key_convert-.LM0
+#endif
vld1.8 {@XMM[15]}, [$inp]! @ load round 1 key
vmov.i8 @XMM[8], #0x01 @ bit masks
@@ -1397,7 +1423,12 @@ bsaes_ctr32_encrypt_blocks:
vstmia r12, {@XMM[7]} @ save last round key
vld1.8 {@XMM[0]}, [$ctr] @ load counter
+#ifdef __APPLE__
+ mov $ctr, #.LREVM0SR-.LM0
+ add $ctr, $const, $ctr
+#else
add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr
+#endif
vldmia $keysched, {@XMM[4]} @ load round0 key
#else
ldr r12, [$key, #244]
@@ -1454,7 +1485,12 @@ bsaes_ctr32_encrypt_blocks:
vldmia $ctr, {@XMM[8]} @ .LREVM0SR
mov r5, $rounds @ pass rounds
vstmia $fp, {@XMM[10]} @ save next counter
+#ifdef __APPLE__
+ mov $const, #.LREVM0SR-.LSR
+ sub $const, $ctr, $const
+#else
sub $const, $ctr, #.LREVM0SR-.LSR @ pass constants
+#endif
bl _bsaes_encrypt8_alt
@@ -1555,7 +1591,7 @@ bsaes_ctr32_encrypt_blocks:
rev r8, r8
#endif
sub sp, sp, #0x10
- vst1.8 {@XMM[1]}, [sp,:64] @ copy counter value
+ vst1.8 {@XMM[1]}, [sp] @ copy counter value
sub sp, sp, #0x10
.Lctr_enc_short_loop:
@@ -1566,7 +1602,7 @@ bsaes_ctr32_encrypt_blocks:
bl AES_encrypt
vld1.8 {@XMM[0]}, [r4]! @ load input
- vld1.8 {@XMM[1]}, [sp,:64] @ load encrypted counter
+ vld1.8 {@XMM[1]}, [sp] @ load encrypted counter
add r8, r8, #1
#ifdef __ARMEL__
rev r0, r8
@@ -2085,9 +2121,11 @@ bsaes_xts_decrypt:
vld1.8 {@XMM[8]}, [r0] @ initial tweak
adr $magic, .Lxts_magic
+#ifndef XTS_CHAIN_TWEAK
tst $len, #0xf @ if not multiple of 16
it ne @ Thumb2 thing, sanity check in ARM
subne $len, #0x10 @ subtract another 16 bytes
+#endif
subs $len, #0x80
blo .Lxts_dec_short
diff --git a/src/crypto/asn1/CMakeLists.txt b/src/crypto/asn1/CMakeLists.txt
index 35e1bec..283636e 100644
--- a/src/crypto/asn1/CMakeLists.txt
+++ b/src/crypto/asn1/CMakeLists.txt
@@ -23,7 +23,6 @@ add_library(
a_type.c
a_utctm.c
a_utf8.c
- asn1_error.c
asn1_lib.c
asn1_par.c
asn_pack.c
diff --git a/src/crypto/asn1/a_d2i_fp.c b/src/crypto/asn1/a_d2i_fp.c
index c28532b..6022c74 100644
--- a/src/crypto/asn1/a_d2i_fp.c
+++ b/src/crypto/asn1/a_d2i_fp.c
@@ -194,7 +194,7 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
len-off);
if (c.inf & 0x80)
{
- unsigned long e;
+ uint32_t e;
e=ERR_GET_REASON(ERR_peek_error());
if (e != ASN1_R_TOO_LONG)
diff --git a/src/crypto/asn1/a_gentm.c b/src/crypto/asn1/a_gentm.c
index 355feff..be093a4 100644
--- a/src/crypto/asn1/a_gentm.c
+++ b/src/crypto/asn1/a_gentm.c
@@ -57,6 +57,7 @@
#include <openssl/asn1.h>
#include <string.h>
+#include <time.h>
#include <openssl/err.h>
#include <openssl/mem.h>
diff --git a/src/crypto/asn1/a_time.c b/src/crypto/asn1/a_time.c
index f0badcc..e02e858 100644
--- a/src/crypto/asn1/a_time.c
+++ b/src/crypto/asn1/a_time.c
@@ -57,6 +57,7 @@
#include <openssl/asn1.h>
#include <string.h>
+#include <time.h>
#include <openssl/asn1t.h>
#include <openssl/buf.h>
diff --git a/src/crypto/asn1/a_type.c b/src/crypto/asn1/a_type.c
index 75a17d5..fd3d5b1 100644
--- a/src/crypto/asn1/a_type.c
+++ b/src/crypto/asn1/a_type.c
@@ -125,6 +125,9 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
case V_ASN1_NULL:
result = 0; /* They do not have content. */
break;
+ case V_ASN1_BOOLEAN:
+ result = a->value.boolean - b->value.boolean;
+ break;
case V_ASN1_INTEGER:
case V_ASN1_NEG_INTEGER:
case V_ASN1_ENUMERATED:
diff --git a/src/crypto/asn1/a_utctm.c b/src/crypto/asn1/a_utctm.c
index 7a3f5f6..52b010f 100644
--- a/src/crypto/asn1/a_utctm.c
+++ b/src/crypto/asn1/a_utctm.c
@@ -57,6 +57,7 @@
#include <openssl/asn1.h>
#include <string.h>
+#include <time.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -287,7 +288,7 @@ int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
if (!OPENSSL_gmtime(&t, &ttm))
return -2;
- if (!OPENSSL_gmtime_diff(&day, &sec, &stm, &ttm))
+ if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2;
if (day > 0)
diff --git a/src/crypto/asn1/asn1_error.c b/src/crypto/asn1/asn1_error.c
deleted file mode 100644
index 5e9fcaa..0000000
--- a/src/crypto/asn1/asn1_error.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* 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/asn1.h>
-
-const ERR_STRING_DATA ASN1_error_string_data[] = {
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_set_bit, 0), "ASN1_BIT_STRING_set_bit"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENUMERATED_set, 0), "ASN1_ENUMERATED_set"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENUMERATED_to_BN, 0), "ASN1_ENUMERATED_to_BN"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_adj, 0), "ASN1_GENERALIZEDTIME_adj"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_INTEGER_set, 0), "ASN1_INTEGER_set"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_INTEGER_to_BN, 0), "ASN1_INTEGER_to_BN"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_new, 0), "ASN1_OBJECT_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_new, 0), "ASN1_PCTX_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_add, 0), "ASN1_STRING_TABLE_add"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_set, 0), "ASN1_STRING_set"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_type_new, 0), "ASN1_STRING_type_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_adj, 0), "ASN1_TIME_adj"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_adj, 0), "ASN1_UTCTIME_adj"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_d2i_fp, 0), "ASN1_d2i_fp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_dup, 0), "ASN1_dup"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_get_object, 0), "ASN1_get_object"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_i2d_bio, 0), "ASN1_i2d_bio"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_i2d_fp, 0), "ASN1_i2d_fp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_d2i_fp, 0), "ASN1_item_d2i_fp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_dup, 0), "ASN1_item_dup"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_ex_d2i, 0), "ASN1_item_ex_d2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_i2d_bio, 0), "ASN1_item_i2d_bio"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_i2d_fp, 0), "ASN1_item_i2d_fp"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_pack, 0), "ASN1_item_pack"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_unpack, 0), "ASN1_item_unpack"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_mbstring_ncopy, 0), "ASN1_mbstring_ncopy"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_pack_string, 0), "ASN1_pack_string"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_seq_pack, 0), "ASN1_seq_pack"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_seq_unpack, 0), "ASN1_seq_unpack"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_template_new, 0), "ASN1_template_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_unpack_string, 0), "ASN1_unpack_string"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_new_NDEF, 0), "BIO_new_NDEF"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_to_ASN1_ENUMERATED, 0), "BN_to_ASN1_ENUMERATED"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_to_ASN1_INTEGER, 0), "BN_to_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2d_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_ENUMERATED, 0), "a2i_ASN1_ENUMERATED"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_STRING, 0), "a2i_ASN1_STRING"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_check_tlen, 0), "asn1_check_tlen"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_collate_primitive, 0), "asn1_collate_primitive"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_collect, 0), "asn1_collect"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_d2i_ex_primitive, 0), "asn1_d2i_ex_primitive"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_d2i_read_bio, 0), "asn1_d2i_read_bio"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_do_adb, 0), "asn1_do_adb"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_ex_c2i, 0), "asn1_ex_c2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_find_end, 0), "asn1_find_end"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_item_ex_combine_new, 0), "asn1_item_ex_combine_new"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_template_ex_d2i, 0), "asn1_template_ex_d2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_template_noexp_d2i, 0), "asn1_template_noexp_d2i"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_BIT_STRING, 0), "c2i_ASN1_BIT_STRING"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_collect_data, 0), "collect_data"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_BOOLEAN, 0), "d2i_ASN1_BOOLEAN"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_UTCTIME, 0), "d2i_ASN1_UTCTIME"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_bytes, 0), "d2i_ASN1_bytes"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_type_bytes, 0), "d2i_ASN1_type_bytes"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_i2d_ASN1_TIME, 0), "i2d_ASN1_TIME"},
- {ERR_PACK(ERR_LIB_ASN1, ASN1_F_long_c2i, 0), "long_c2i"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "ADDING_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_LENGTH_MISMATCH), "ASN1_LENGTH_MISMATCH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "ASN1_PARSE_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_SIG_PARSE_ERROR), "ASN1_SIG_PARSE_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_AUX_ERROR), "AUX_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_CLASS), "BAD_CLASS"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_GET_ASN1_OBJECT_CALL), "BAD_GET_ASN1_OBJECT_CALL"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_OBJECT_HEADER), "BAD_OBJECT_HEADER"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_PASSWORD_READ), "BAD_PASSWORD_READ"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_TAG), "BAD_TAG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BMPSTRING_IS_WRONG_LENGTH), "BMPSTRING_IS_WRONG_LENGTH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BN_LIB), "BN_LIB"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BOOLEAN_IS_WRONG_LENGTH), "BOOLEAN_IS_WRONG_LENGTH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "CIPHER_HAS_NO_OBJECT_IDENTIFIER"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DATA_IS_WRONG), "DATA_IS_WRONG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODE_ERROR), "DECODE_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODING_ERROR), "DECODING_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DEPTH_EXCEEDED), "DEPTH_EXCEEDED"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ENCODE_ERROR), "ENCODE_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_GETTING_TIME), "ERROR_GETTING_TIME"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_LOADING_SECTION), "ERROR_LOADING_SECTION"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_PARSING_SET_ELEMENT), "ERROR_PARSING_SET_ELEMENT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_SETTING_CIPHER_PARAMS), "ERROR_SETTING_CIPHER_PARAMS"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_ASN1_SEQUENCE), "EXPECTING_AN_ASN1_SEQUENCE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_INTEGER), "EXPECTING_AN_INTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_OBJECT), "EXPECTING_AN_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_A_BOOLEAN), "EXPECTING_A_BOOLEAN"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_A_TIME), "EXPECTING_A_TIME"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_LENGTH_MISMATCH), "EXPLICIT_LENGTH_MISMATCH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED), "EXPLICIT_TAG_NOT_CONSTRUCTED"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIELD_MISSING), "FIELD_MISSING"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIRST_NUM_TOO_LARGE), "FIRST_NUM_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_HEADER_TOO_LONG), "HEADER_TOO_LONG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BITSTRING_FORMAT), "ILLEGAL_BITSTRING_FORMAT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BOOLEAN), "ILLEGAL_BOOLEAN"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_CHARACTERS), "ILLEGAL_CHARACTERS"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_FORMAT), "ILLEGAL_FORMAT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_HEX), "ILLEGAL_HEX"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_IMPLICIT_TAG), "ILLEGAL_IMPLICIT_TAG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_INTEGER), "ILLEGAL_INTEGER"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NESTED_TAGGING), "ILLEGAL_NESTED_TAGGING"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL), "ILLEGAL_NULL"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL_VALUE), "ILLEGAL_NULL_VALUE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OBJECT), "ILLEGAL_OBJECT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONAL_ANY), "ILLEGAL_OPTIONAL_ANY"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE), "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TAGGED_ANY), "ILLEGAL_TAGGED_ANY"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TIME_VALUE), "ILLEGAL_TIME_VALUE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_NOT_ASCII_FORMAT), "INTEGER_NOT_ASCII_FORMAT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG), "INTEGER_TOO_LARGE_FOR_LONG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BIT_STRING_BITS_LEFT), "INVALID_BIT_STRING_BITS_LEFT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BMPSTRING_LENGTH), "INVALID_BMPSTRING_LENGTH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_DIGIT), "INVALID_DIGIT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MIME_TYPE), "INVALID_MIME_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MODIFIER), "INVALID_MODIFIER"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_NUMBER), "INVALID_NUMBER"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_OBJECT_ENCODING), "INVALID_OBJECT_ENCODING"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SEPARATOR), "INVALID_SEPARATOR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_TIME_FORMAT), "INVALID_TIME_FORMAT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH), "INVALID_UNIVERSALSTRING_LENGTH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING), "INVALID_UTF8STRING"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_IV_TOO_LARGE), "IV_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LENGTH_ERROR), "LENGTH_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "LIST_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MALLOC_FAILURE), "MALLOC_FAILURE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE), "MIME_NO_CONTENT_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_PARSE_ERROR), "MIME_PARSE_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_SIG_PARSE_ERROR), "MIME_SIG_PARSE_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_ASN1_EOS), "MISSING_ASN1_EOS"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_EOC), "MISSING_EOC"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_SECOND_NUMBER), "MISSING_SECOND_NUMBER"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_VALUE), "MISSING_VALUE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_NOT_UNIVERSAL), "MSTRING_NOT_UNIVERSAL"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_WRONG_TAG), "MSTRING_WRONG_TAG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_ERROR), "NESTED_ASN1_ERROR"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_STRING), "NESTED_ASN1_STRING"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NON_HEX_CHARACTERS), "NON_HEX_CHARACTERS"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ASCII_FORMAT), "NOT_ASCII_FORMAT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ENOUGH_DATA), "NOT_ENOUGH_DATA"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_CONTENT_TYPE), "NO_CONTENT_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_DEFAULT_DIGEST), "NO_DEFAULT_DIGEST"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MATCHING_CHOICE_TYPE), "NO_MATCHING_CHOICE_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BODY_FAILURE), "NO_MULTIPART_BODY_FAILURE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BOUNDARY), "NO_MULTIPART_BOUNDARY"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_SIG_CONTENT_TYPE), "NO_SIG_CONTENT_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NULL_IS_WRONG_LENGTH), "NULL_IS_WRONG_LENGTH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_OBJECT_NOT_ASCII_FORMAT), "OBJECT_NOT_ASCII_FORMAT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ODD_NUMBER_OF_CHARS), "ODD_NUMBER_OF_CHARS"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_PRIVATE_KEY_HEADER_MISSING), "PRIVATE_KEY_HEADER_MISSING"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SECOND_NUMBER_TOO_LARGE), "SECOND_NUMBER_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_LENGTH_MISMATCH), "SEQUENCE_LENGTH_MISMATCH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_NOT_CONSTRUCTED), "SEQUENCE_NOT_CONSTRUCTED"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG), "SEQUENCE_OR_SET_NEEDS_CONFIG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SHORT_LINE), "SHORT_LINE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SIG_INVALID_MIME_TYPE), "SIG_INVALID_MIME_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STREAMING_NOT_SUPPORTED), "STREAMING_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_LONG), "STRING_TOO_LONG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_SHORT), "STRING_TOO_SHORT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TAG_VALUE_TOO_HIGH), "TAG_VALUE_TOO_HIGH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TIME_NOT_ASCII_FORMAT), "TIME_NOT_ASCII_FORMAT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LONG), "TOO_LONG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_CONSTRUCTED), "TYPE_NOT_CONSTRUCTED"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_PRIMITIVE), "TYPE_NOT_PRIMITIVE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNABLE_TO_DECODE_RSA_KEY), "UNABLE_TO_DECODE_RSA_KEY"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY), "UNABLE_TO_DECODE_RSA_PRIVATE_KEY"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "UNEXPECTED_EOC"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH), "UNIVERSALSTRING_IS_WRONG_LENGTH"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "UNKNOWN_FORMAT"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_OBJECT_TYPE), "UNKNOWN_OBJECT_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), "UNKNOWN_PUBLIC_KEY_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_TAG), "UNKNOWN_TAG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE), "UNSUPPORTED_ANY_DEFINED_BY_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_CIPHER), "UNSUPPORTED_CIPHER"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM), "UNSUPPORTED_ENCRYPTION_ALGORITHM"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "UNSUPPORTED_PUBLIC_KEY_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_TYPE), "UNSUPPORTED_TYPE"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TAG), "WRONG_TAG"},
- {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TYPE), "WRONG_TYPE"},
- {0, NULL},
-};
diff --git a/src/crypto/asn1/asn1_lib.c b/src/crypto/asn1/asn1_lib.c
index 1fc2c06..9aa2678 100644
--- a/src/crypto/asn1/asn1_lib.c
+++ b/src/crypto/asn1/asn1_lib.c
@@ -63,8 +63,46 @@
#include <openssl/err.h>
#include <openssl/mem.h>
+
+/* Used in asn1_mac.h.
+ * TODO(davidben): Remove this once asn1_mac.h is gone or trimmed. */
OPENSSL_DECLARE_ERROR_REASON(ASN1, MALLOC_FAILURE);
+/* Cross-module errors from crypto/x509/i2d_pr.c */
+OPENSSL_DECLARE_ERROR_FUNCTION(ASN1, i2d_PrivateKey);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
+
+/* Cross-module errors from crypto/x509/asn1_gen.c.
+ * TODO(davidben): Remove these once asn1_gen.c is gone. */
+OPENSSL_DECLARE_ERROR_FUNCTION(ASN1, ASN1_generate_v3);
+OPENSSL_DECLARE_ERROR_FUNCTION(ASN1, asn1_cb);
+OPENSSL_DECLARE_ERROR_FUNCTION(ASN1, parse_tagging);
+OPENSSL_DECLARE_ERROR_FUNCTION(ASN1, append_exp);
+OPENSSL_DECLARE_ERROR_FUNCTION(ASN1, asn1_str2type);
+OPENSSL_DECLARE_ERROR_FUNCTION(ASN1, bitstr_cb);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG);
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE);
static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
static void asn1_put_length(unsigned char **pp, int length);
@@ -466,15 +504,6 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
return(i);
}
-void asn1_add_error(const unsigned char *address, int offset)
- {
- char buf1[DECIMAL_SIZE(address)+1],buf2[DECIMAL_SIZE(offset)+1];
-
- BIO_snprintf(buf1,sizeof buf1,"%lu",(unsigned long)address);
- BIO_snprintf(buf2,sizeof buf2,"%d",offset);
- ERR_add_error_data(4,"address=",buf1," offset=",buf2);
- }
-
int ASN1_STRING_length(const ASN1_STRING *x)
{ return M_ASN1_STRING_length(x); }
diff --git a/src/crypto/asn1/asn1_par.c b/src/crypto/asn1/asn1_par.c
index 53b11fe..aff3e2b 100644
--- a/src/crypto/asn1/asn1_par.c
+++ b/src/crypto/asn1/asn1_par.c
@@ -137,7 +137,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
#endif
if (j & 0x80)
{
- if (BIO_write(bp,"Error in encoding\n",18) <= 0)
+ if (BIO_puts(bp, "Error in encoding\n") <= 0)
goto end;
ret=0;
goto end;
@@ -165,7 +165,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
if (j & V_ASN1_CONSTRUCTED)
{
ep=p+len;
- if (BIO_write(bp,"\n",1) <= 0) goto end;
+ if (BIO_puts(bp, "\n") <= 0) goto end;
if (len > length)
{
BIO_printf(bp,
@@ -196,7 +196,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
else if (xclass != 0)
{
p+=len;
- if (BIO_write(bp,"\n",1) <= 0) goto end;
+ if (BIO_puts(bp, "\n") <= 0) goto end;
}
else
{
@@ -210,7 +210,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
(tag == V_ASN1_UTCTIME) ||
(tag == V_ASN1_GENERALIZEDTIME))
{
- if (BIO_write(bp,":",1) <= 0) goto end;
+ if (BIO_puts(bp, ":") <= 0) goto end;
if ((len > 0) &&
BIO_write(bp,(const char *)p,(int)len)
!= (int)len)
@@ -221,12 +221,12 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
opp=op;
if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL)
{
- if (BIO_write(bp,":",1) <= 0) goto end;
+ if (BIO_puts(bp, ":") <= 0) goto end;
i2a_ASN1_OBJECT(bp,o);
}
else
{
- if (BIO_write(bp,":BAD OBJECT",11) <= 0)
+ if (BIO_puts(bp, ":BAD OBJECT") <= 0)
goto end;
}
}
@@ -238,7 +238,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl);
if (ii < 0)
{
- if (BIO_write(bp,"Bad boolean\n",12) <= 0)
+ if (BIO_puts(bp, "Bad boolean\n") <= 0)
goto end;
}
BIO_printf(bp,":%d",ii);
@@ -273,7 +273,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
if (printable)
/* printable string */
{
- if (BIO_write(bp,":",1) <= 0)
+ if (BIO_puts(bp, ":") <= 0)
goto end;
if (BIO_write(bp,(const char *)opp,
os->length) <= 0)
@@ -283,7 +283,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
/* not printable => print octet string
* as hex dump */
{
- if (BIO_write(bp,"[HEX DUMP]:",11) <= 0)
+ if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
goto end;
for (i=0; i<os->length; i++)
{
@@ -297,7 +297,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
{
if (!nl)
{
- if (BIO_write(bp,"\n",1) <= 0)
+ if (BIO_puts(bp, "\n") <= 0)
goto end;
}
if (!BIO_hexdump(bp, opp,
@@ -323,9 +323,9 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl);
if (bs != NULL)
{
- if (BIO_write(bp,":",1) <= 0) goto end;
+ if (BIO_puts(bp, ":") <= 0) goto end;
if (bs->type == V_ASN1_NEG_INTEGER)
- if (BIO_write(bp,"-",1) <= 0)
+ if (BIO_puts(bp, "-") <= 0)
goto end;
for (i=0; i<bs->length; i++)
{
@@ -335,13 +335,13 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
}
if (bs->length == 0)
{
- if (BIO_write(bp,"00",2) <= 0)
+ if (BIO_puts(bp, "00") <= 0)
goto end;
}
}
else
{
- if (BIO_write(bp,"BAD INTEGER",11) <= 0)
+ if (BIO_puts(bp, "BAD INTEGER") <= 0)
goto end;
}
M_ASN1_INTEGER_free(bs);
@@ -355,9 +355,9 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl);
if (bs != NULL)
{
- if (BIO_write(bp,":",1) <= 0) goto end;
+ if (BIO_puts(bp, ":") <= 0) goto end;
if (bs->type == V_ASN1_NEG_ENUMERATED)
- if (BIO_write(bp,"-",1) <= 0)
+ if (BIO_puts(bp, "-") <= 0)
goto end;
for (i=0; i<bs->length; i++)
{
@@ -367,13 +367,13 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
}
if (bs->length == 0)
{
- if (BIO_write(bp,"00",2) <= 0)
+ if (BIO_puts(bp, "00") <= 0)
goto end;
}
}
else
{
- if (BIO_write(bp,"BAD ENUMERATED",11) <= 0)
+ if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
goto end;
}
M_ASN1_ENUMERATED_free(bs);
@@ -382,7 +382,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
{
if (!nl)
{
- if (BIO_write(bp,"\n",1) <= 0)
+ if (BIO_puts(bp, "\n") <= 0)
goto end;
}
if (!BIO_hexdump(bp,p,
@@ -394,7 +394,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offse
if (!nl)
{
- if (BIO_write(bp,"\n",1) <= 0) goto end;
+ if (BIO_puts(bp, "\n") <= 0) goto end;
}
p+=len;
if ((tag == V_ASN1_EOC) && (xclass == 0))
diff --git a/src/crypto/asn1/bio_ndef.c b/src/crypto/asn1/bio_ndef.c
index c814814..2f7105d 100644
--- a/src/crypto/asn1/bio_ndef.c
+++ b/src/crypto/asn1/bio_ndef.c
@@ -170,6 +170,9 @@ static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
p = OPENSSL_malloc(derlen);
+ if (p == NULL)
+ return 0;
+
ndef_aux->derbuf = p;
*pbuf = p;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
@@ -235,6 +238,9 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
p = OPENSSL_malloc(derlen);
+ if (p == NULL)
+ return 0;
+
ndef_aux->derbuf = p;
*pbuf = p;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
diff --git a/src/crypto/asn1/tasn_dec.c b/src/crypto/asn1/tasn_dec.c
index 4cece89..73d3bb3 100644
--- a/src/crypto/asn1/tasn_dec.c
+++ b/src/crypto/asn1/tasn_dec.c
@@ -63,6 +63,8 @@
#include <openssl/err.h>
#include <openssl/mem.h>
+#include "../internal.h"
+
static int asn1_check_eoc(const unsigned char **in, long len);
static int asn1_find_end(const unsigned char **in, long len, char inf);
@@ -304,8 +306,19 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
goto auxerr;
- /* Allocate structure */
- if (!*pval && !ASN1_item_ex_new(pval, it))
+ if (*pval)
+ {
+ /* Free up and zero CHOICE value if initialised */
+ i = asn1_get_choice_selector(pval, it);
+ if ((i >= 0) && (i < it->tcount))
+ {
+ tt = it->templates + i;
+ pchptr = asn1_get_field_ptr(pval, tt);
+ ASN1_template_free(pchptr, tt);
+ asn1_set_choice_selector(pval, -1, it);
+ }
+ }
+ else if (!ASN1_item_ex_new(pval, it))
{
OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
goto err;
@@ -394,6 +407,19 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
goto auxerr;
+ /* Free up and zero any ADB found */
+ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
+ {
+ if (tt->flags & ASN1_TFLG_ADB_MASK)
+ {
+ const ASN1_TEMPLATE *seqtt;
+ ASN1_VALUE **pseqval;
+ seqtt = asn1_do_adb(pval, tt, 1);
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ ASN1_template_free(pseqval, seqtt);
+ }
+ }
+
/* Get each field entry */
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
{
@@ -738,6 +764,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
const unsigned char **in, long inlen,
const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx)
+ OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
{
int ret = 0, utype;
long plen;
@@ -1193,7 +1220,7 @@ static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
len = buf->length;
if (!BUF_MEM_grow_clean(buf, len + plen))
{
- OPENSSL_PUT_ERROR(ASN1, asn1_collect, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(ASN1, collect_data, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(buf->data + len, *p, plen);
diff --git a/src/crypto/asn1/tasn_new.c b/src/crypto/asn1/tasn_new.c
index b68eed7..918aba7 100644
--- a/src/crypto/asn1/tasn_new.c
+++ b/src/crypto/asn1/tasn_new.c
@@ -100,8 +100,6 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
else
asn1_cb = 0;
- if (!combine) *pval = NULL;
-
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_push_info(it->sname);
@@ -212,6 +210,7 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
memerr:
OPENSSL_PUT_ERROR(ASN1, asn1_item_ex_combine_new, ERR_R_MALLOC_FAILURE);
+ ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
if (it->sname) CRYPTO_pop_info();
#endif
@@ -328,14 +327,17 @@ int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
ASN1_STRING *str;
int utype;
- if (it && it->funcs)
+ if (!it)
+ return 0;
+
+ if (it->funcs)
{
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_new)
return pf->prim_new(pval, it);
}
- if (!it || (it->itype == ASN1_ITYPE_MSTRING))
+ if (it->itype == ASN1_ITYPE_MSTRING)
utype = -1;
else
utype = it->utype;
diff --git a/src/crypto/asn1/tasn_prn.c b/src/crypto/asn1/tasn_prn.c
index 4eb522d..df19ff0 100644
--- a/src/crypto/asn1/tasn_prn.c
+++ b/src/crypto/asn1/tasn_prn.c
@@ -229,6 +229,7 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
if (!asn1_template_print_ctx(out, fld, indent,
it->templates, pctx))
return 0;
+ break;
}
/* fall thru */
case ASN1_ITYPE_MSTRING:
@@ -309,6 +310,8 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
{
const ASN1_TEMPLATE *seqtt;
seqtt = asn1_do_adb(fld, tt, 1);
+ if (!seqtt)
+ return 0;
tmpfld = asn1_get_field_ptr(fld, seqtt);
if (!asn1_template_print_ctx(out, tmpfld,
indent + 2, seqtt, pctx))
diff --git a/src/crypto/asn1/tasn_typ.c b/src/crypto/asn1/tasn_typ.c
index f2bbbc8..f004b0d 100644
--- a/src/crypto/asn1/tasn_typ.c
+++ b/src/crypto/asn1/tasn_typ.c
@@ -61,53 +61,38 @@
/* Declarations for string types */
-IMPLEMENT_ASN1_TYPE(ASN1_INTEGER);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_INTEGER);
-
-IMPLEMENT_ASN1_TYPE(ASN1_ENUMERATED);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_ENUMERATED);
-
-IMPLEMENT_ASN1_TYPE(ASN1_BIT_STRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_BIT_STRING);
-
-IMPLEMENT_ASN1_TYPE(ASN1_OCTET_STRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_OCTET_STRING);
+#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
+ IMPLEMENT_ASN1_TYPE(sname) \
+ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
+ sname *sname##_new(void) \
+ { \
+ return ASN1_STRING_type_new(V_##sname); \
+ } \
+ void sname##_free(sname *x) \
+ { \
+ ASN1_STRING_free(x); \
+ }
+
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING)
+IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING)
IMPLEMENT_ASN1_TYPE(ASN1_NULL);
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL);
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT);
-IMPLEMENT_ASN1_TYPE(ASN1_UTF8STRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTF8STRING);
-
-IMPLEMENT_ASN1_TYPE(ASN1_PRINTABLESTRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING);
-
-IMPLEMENT_ASN1_TYPE(ASN1_T61STRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_T61STRING);
-
-IMPLEMENT_ASN1_TYPE(ASN1_IA5STRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_IA5STRING);
-
-IMPLEMENT_ASN1_TYPE(ASN1_GENERALSTRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALSTRING);
-
-IMPLEMENT_ASN1_TYPE(ASN1_UTCTIME);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTCTIME);
-
-IMPLEMENT_ASN1_TYPE(ASN1_GENERALIZEDTIME);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME);
-
-IMPLEMENT_ASN1_TYPE(ASN1_VISIBLESTRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_VISIBLESTRING);
-
-IMPLEMENT_ASN1_TYPE(ASN1_UNIVERSALSTRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING);
-
-IMPLEMENT_ASN1_TYPE(ASN1_BMPSTRING);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_BMPSTRING);
-
IMPLEMENT_ASN1_TYPE(ASN1_ANY);
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */;
diff --git a/src/crypto/asn1/tasn_utl.c b/src/crypto/asn1/tasn_utl.c
index f6045e4..1b9de94 100644
--- a/src/crypto/asn1/tasn_utl.c
+++ b/src/crypto/asn1/tasn_utl.c
@@ -62,6 +62,7 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/err.h>
+#include <openssl/thread.h>
/* Utility functions for manipulating fields and offsets */
diff --git a/src/crypto/base64/CMakeLists.txt b/src/crypto/base64/CMakeLists.txt
index 2b4f081..8bc531a 100644
--- a/src/crypto/base64/CMakeLists.txt
+++ b/src/crypto/base64/CMakeLists.txt
@@ -11,7 +11,7 @@ add_library(
add_executable(
base64_test
- base64_test.c
+ base64_test.cc
)
target_link_libraries(base64_test crypto)
diff --git a/src/crypto/base64/base64.c b/src/crypto/base64/base64.c
index 12a52cf..4822fb8 100644
--- a/src/crypto/base64/base64.c
+++ b/src/crypto/base64/base64.c
@@ -373,6 +373,10 @@ int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
rv = 0;
goto end;
}
+ if (eof > v) {
+ rv = -1;
+ goto end;
+ }
ret += (v - eof);
} else {
eof = 1;
diff --git a/src/crypto/base64/base64_test.c b/src/crypto/base64/base64_test.cc
index 411323f..fde0b46 100644
--- a/src/crypto/base64/base64_test.c
+++ b/src/crypto/base64/base64_test.cc
@@ -20,13 +20,13 @@
#include <openssl/err.h>
-typedef struct {
+struct TestVector {
const char *decoded;
const char *encoded;
-} TEST_VECTOR;
+};
-/* Test vectors from RFC 4648. */
-static const TEST_VECTOR test_vectors[] = {
+// Test vectors from RFC 4648.
+static const TestVector kTestVectors[] = {
{ "", "" },
{ "f" , "Zg==" },
{ "fo", "Zm8=" },
@@ -36,95 +36,90 @@ static const TEST_VECTOR test_vectors[] = {
{ "foobar", "Zm9vYmFy" },
};
-static const size_t kNumTests = sizeof(test_vectors) / sizeof(test_vectors[0]);
-
-static int test_encode(void) {
- uint8_t out[9];
- size_t i, len;
+static const size_t kNumTests = sizeof(kTestVectors) / sizeof(kTestVectors[0]);
- for (i = 0; i < kNumTests; i++) {
- const TEST_VECTOR *t = &test_vectors[i];
- len = EVP_EncodeBlock(out, (const uint8_t*)t->decoded, strlen(t->decoded));
+static bool TestEncode() {
+ for (size_t i = 0; i < kNumTests; i++) {
+ const TestVector *t = &kTestVectors[i];
+ uint8_t out[9];
+ size_t len = EVP_EncodeBlock(out, (const uint8_t*)t->decoded,
+ strlen(t->decoded));
if (len != strlen(t->encoded) ||
memcmp(out, t->encoded, len) != 0) {
fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
t->decoded, (int)len, (const char*)out, t->encoded);
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
-static int test_decode(void) {
+static bool TestDecode() {
uint8_t out[6];
- size_t i, len;
- int ret;
+ size_t len;
- for (i = 0; i < kNumTests; i++) {
- /* Test the normal API. */
- const TEST_VECTOR *t = &test_vectors[i];
+ for (size_t i = 0; i < kNumTests; i++) {
+ // Test the normal API.
+ const TestVector *t = &kTestVectors[i];
size_t expected_len = strlen(t->decoded);
if (!EVP_DecodeBase64(out, &len, sizeof(out),
(const uint8_t*)t->encoded, strlen(t->encoded))) {
fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
- return 0;
+ return false;
}
if (len != strlen(t->decoded) ||
memcmp(out, t->decoded, len) != 0) {
fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
t->encoded, (int)len, (const char*)out, t->decoded);
- return 0;
+ return false;
}
- /* Test that the padding behavior of the deprecated API is
- * preserved. */
- ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded, strlen(t->encoded));
+ // Test that the padding behavior of the deprecated API is preserved.
+ int ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded,
+ strlen(t->encoded));
if (ret < 0) {
fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
- return 0;
+ return false;
}
if (ret % 3 != 0) {
fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
- return 0;
+ return false;
}
if (expected_len % 3 != 0) {
ret -= 3 - (expected_len % 3);
}
- if (ret != strlen(t->decoded) ||
+ if (static_cast<size_t>(ret) != strlen(t->decoded) ||
memcmp(out, t->decoded, ret) != 0) {
fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
t->encoded, ret, (const char*)out, t->decoded);
- return 0;
+ return false;
}
}
if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a!bc", 4)) {
fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
- return 0;
+ return false;
}
if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a=bc", 4)) {
fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
- return 0;
+ return false;
}
if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"abc", 4)) {
fprintf(stderr, "Failed to reject invalid input length.\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
int main(void) {
CRYPTO_library_init();
ERR_load_crypto_strings();
- if (!test_encode()) {
- return 1;
- }
-
- if (!test_decode()) {
+ if (!TestEncode() ||
+ !TestDecode()) {
return 1;
}
diff --git a/src/crypto/bio/CMakeLists.txt b/src/crypto/bio/CMakeLists.txt
index 6211e85..f4122c4 100644
--- a/src/crypto/bio/CMakeLists.txt
+++ b/src/crypto/bio/CMakeLists.txt
@@ -6,7 +6,6 @@ add_library(
OBJECT
bio.c
- bio_error.c
bio_mem.c
buffer.c
connect.c
@@ -22,7 +21,7 @@ add_library(
add_executable(
bio_test
- bio_test.c
+ bio_test.cc
)
target_link_libraries(bio_test crypto)
diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c
index 4d947a6..48c1466 100644
--- a/src/crypto/bio/bio.c
+++ b/src/crypto/bio/bio.c
@@ -58,7 +58,6 @@
#include <errno.h>
#include <limits.h>
-#include <stddef.h>
#include <string.h>
#include <openssl/err.h>
@@ -78,17 +77,10 @@ static int bio_set(BIO *bio, const BIO_METHOD *method) {
bio->shutdown = 1;
bio->references = 1;
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data)) {
+ if (method->create != NULL && !method->create(bio)) {
return 0;
}
- if (method->create != NULL) {
- if (!method->create(bio)) {
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
- return 0;
- }
- }
-
return 1;
}
@@ -125,8 +117,6 @@ int BIO_free(BIO *bio) {
next_bio = BIO_pop(bio);
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
-
if (bio->method != NULL && bio->method->destroy != NULL) {
bio->method->destroy(bio);
}
@@ -136,6 +126,11 @@ int BIO_free(BIO *bio) {
return 1;
}
+BIO *BIO_up_ref(BIO *bio) {
+ CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO);
+ return bio;
+}
+
void BIO_vfree(BIO *bio) {
BIO_free(bio);
}
@@ -397,10 +392,6 @@ BIO *BIO_push(BIO *bio, BIO *appended_bio) {
}
last_bio->next_bio = appended_bio;
- /* TODO(fork): this seems very suspect. If we got rid of BIO SSL, we could
- * get rid of this. */
- BIO_ctrl(bio, BIO_CTRL_PUSH, 0, bio);
-
return bio;
}
@@ -411,7 +402,6 @@ BIO *BIO_pop(BIO *bio) {
return NULL;
}
ret = bio->next_bio;
- BIO_ctrl(bio, BIO_CTRL_POP, 0, bio);
bio->next_bio = NULL;
return ret;
}
@@ -462,12 +452,6 @@ int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) {
return 1;
}
-void BIO_print_errors_fp(FILE *out) {
- BIO *bio = BIO_new_fp(out, BIO_NOCLOSE);
- BIO_print_errors(bio);
- BIO_free(bio);
-}
-
static int print_bio(const char *str, size_t len, void *bio) {
return BIO_write((BIO *)bio, str, len);
}
diff --git a/src/crypto/bio/bio_error.c b/src/crypto/bio/bio_error.c
deleted file mode 100644
index 09585e4..0000000
--- a/src/crypto/bio/bio_error.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* 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/bio.h>
-
-const ERR_STRING_DATA BIO_error_string_data[] = {
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_callback_ctrl, 0), "BIO_callback_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ctrl, 0), "BIO_ctrl"},
- {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"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_bio_make_pair, 0), "bio_make_pair"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_bio_write, 0), "bio_write"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_buffer_ctrl, 0), "buffer_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_conn_ctrl, 0), "conn_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_conn_state, 0), "conn_state"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_file_ctrl, 0), "file_ctrl"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_file_read, 0), "file_read"},
- {ERR_PACK(ERR_LIB_BIO, BIO_F_mem_write, 0), "mem_write"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ASN1_OBJECT_TOO_LONG), "ASN1_OBJECT_TOO_LONG"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BAD_FOPEN_MODE), "BAD_FOPEN_MODE"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BROKEN_PIPE), "BROKEN_PIPE"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_ERROR), "CONNECT_ERROR"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ERROR_SETTING_NBIO), "ERROR_SETTING_NBIO"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_INVALID_ARGUMENT), "INVALID_ARGUMENT"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_IN_USE), "IN_USE"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_KEEPALIVE), "KEEPALIVE"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NBIO_CONNECT_ERROR), "NBIO_CONNECT_ERROR"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_HOSTNAME_SPECIFIED), "NO_HOSTNAME_SPECIFIED"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_SPECIFIED), "NO_PORT_SPECIFIED"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "NO_SUCH_FILE"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NULL_PARAMETER), "NULL_PARAMETER"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_SYS_LIB), "SYS_LIB"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_CREATE_SOCKET), "UNABLE_TO_CREATE_SOCKET"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNINITIALIZED), "UNINITIALIZED"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_METHOD), "UNSUPPORTED_METHOD"},
- {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WRITE_TO_READ_ONLY_BIO), "WRITE_TO_READ_ONLY_BIO"},
- {0, NULL},
-};
diff --git a/src/crypto/bio/bio_test.c b/src/crypto/bio/bio_test.cc
index ee11acc..4c88df5 100644
--- a/src/crypto/bio/bio_test.c
+++ b/src/crypto/bio/bio_test.cc
@@ -36,96 +36,109 @@
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include <algorithm>
+
+#include "../test/scoped_types.h"
-#define MIN(a, b) ((a < b) ? a : b)
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) {
return close(sock);
}
-static void print_socket_error(const char *func) {
+static void PrintSocketError(const char *func) {
perror(func);
}
#else
-static void print_socket_error(const char *func) {
+static void PrintSocketError(const char *func) {
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
}
#endif
-static int test_socket_connect(void) {
- int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
- int sock;
- struct sockaddr_in sin;
- socklen_t sockaddr_len = sizeof(sin);
+class ScopedSocket {
+ public:
+ ScopedSocket(int sock) : sock_(sock) {}
+ ~ScopedSocket() {
+ closesocket(sock_);
+ }
+
+ private:
+ const int sock_;
+};
+
+static bool TestSocketConnect() {
static const char kTestMessage[] = "test";
- char hostname[80], buf[5];
- BIO *bio;
+ int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (listening_sock == -1) {
+ PrintSocketError("socket");
+ return false;
+ }
+ ScopedSocket listening_sock_closer(listening_sock);
+
+ struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
- print_socket_error("inet_pton");
- return 0;
+ PrintSocketError("inet_pton");
+ return false;
}
-
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
- print_socket_error("bind");
- return 0;
+ PrintSocketError("bind");
+ return false;
}
-
if (listen(listening_sock, 1)) {
- print_socket_error("listen");
- return 0;
+ PrintSocketError("listen");
+ return false;
}
-
+ socklen_t sockaddr_len = sizeof(sin);
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
sockaddr_len != sizeof(sin)) {
- print_socket_error("getsockname");
- return 0;
+ PrintSocketError("getsockname");
+ return false;
}
+ char hostname[80];
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
ntohs(sin.sin_port));
- bio = BIO_new_connect(hostname);
+ ScopedBIO bio(BIO_new_connect(hostname));
if (!bio) {
fprintf(stderr, "BIO_new_connect failed.\n");
- return 0;
+ return false;
}
- if (BIO_write(bio, kTestMessage, sizeof(kTestMessage)) !=
+ if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) !=
sizeof(kTestMessage)) {
fprintf(stderr, "BIO_write failed.\n");
- BIO_print_errors_fp(stderr);
- return 0;
+ ERR_print_errors_fp(stderr);
+ return false;
}
- sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
- if (sock < 0) {
- print_socket_error("accept");
- return 0;
+ int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
+ if (sock == -1) {
+ PrintSocketError("accept");
+ return false;
}
+ ScopedSocket sock_closer(sock);
+ char buf[5];
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
- print_socket_error("read");
- return 0;
+ PrintSocketError("read");
+ return false;
}
-
if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
- return 0;
+ return false;
}
- closesocket(sock);
- closesocket(listening_sock);
- BIO_free(bio);
-
- return 1;
+ return true;
}
-/* 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) {
+// BioReadZeroCopyWrapper is a wrapper around the zero-copy APIs to make
+// testing easier.
+static size_t BioReadZeroCopyWrapper(BIO *bio, uint8_t *data, size_t len) {
uint8_t *read_buf;
size_t read_buf_offset;
size_t available_bytes;
@@ -137,7 +150,7 @@ static size_t bio_read_zero_copy_wrapper(BIO *bio, uint8_t *data, size_t len) {
return 0;
}
- available_bytes = MIN(available_bytes, len - len_read);
+ available_bytes = std::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);
@@ -148,10 +161,10 @@ static size_t bio_read_zero_copy_wrapper(BIO *bio, uint8_t *data, size_t len) {
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) {
+// BioWriteZeroCopyWrapper is a wrapper around the zero-copy APIs to make
+// testing easier.
+static size_t BioWriteZeroCopyWrapper(BIO *bio, const uint8_t *data,
+ size_t len) {
uint8_t *write_buf;
size_t write_buf_offset;
size_t available_bytes;
@@ -163,7 +176,7 @@ static size_t bio_write_zero_copy_wrapper(BIO *bio, const uint8_t *data,
return 0;
}
- available_bytes = MIN(available_bytes, len - len_written);
+ available_bytes = std::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);
@@ -174,167 +187,157 @@ static size_t bio_write_zero_copy_wrapper(BIO *bio, const uint8_t *data,
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;
+static bool TestZeroCopyBioPairs() {
+ // Test read and write, especially triggering the ring buffer wrap-around.
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. */
+ // 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++) {
+ for (size_t 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);
+ // Transfer bytes from bio1_application_send_buffer to
+ // bio2_application_recv_buffer in various ways.
+ for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
+ for (size_t j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]);
+ j++) {
+ size_t total_write = 0;
+ size_t total_read = 0;
+
+ BIO *bio1, *bio2;
+ if (!BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize)) {
+ return false;
+ }
+ ScopedBIO bio1_scoper(bio1);
+ ScopedBIO bio2_scoper(bio2);
- total_write += bio_write_zero_copy_wrapper(
+ total_write += BioWriteZeroCopyWrapper(
bio1, bio1_application_send_buffer, kLengths[i]);
- /* This tests interleaved read/write calls. Do a read between zero copy
- * write calls. */
+ // This tests interleaved read/write calls. Do a read between zero copy
+ // write calls.
+ uint8_t *write_buf;
+ size_t write_buf_offset;
+ size_t available_bytes;
if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset,
&available_bytes)) {
- return 0;
+ return false;
}
- /* Free kPartialLengths[j] bytes in the beginning of bio1 write buffer.
- * This enables ring buffer wrap around for the next write. */
+ // 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);
+ size_t interleaved_write_len = std::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. */
+ // 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(
+ // Do another write in case |write_buf_offset| was wrapped.
+ total_write += BioWriteZeroCopyWrapper(
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(
+ // Drain the rest.
+ size_t bytes_left = BIO_pending(bio2);
+ total_read += BioReadZeroCopyWrapper(
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;
+ return false;
}
if (total_read > kLengths[i] + kPartialLengths[j]) {
fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i,
(unsigned)j);
- return 0;
+ return false;
}
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 false;
}
}
}
- return 1;
+ return true;
}
-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. */
+static bool TestPrintf() {
+ // Test a short output, a very long one, and various sizes around
+ // 256 (the size of the buffer) to ensure edge cases are correct.
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
- BIO *bio;
- char string[1024];
- int ret;
- const uint8_t *contents;
- size_t i, len;
- bio = BIO_new(BIO_s_mem());
+ ScopedBIO bio(BIO_new(BIO_s_mem()));
if (!bio) {
fprintf(stderr, "BIO_new failed\n");
- return 0;
+ return false;
}
- for (i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
+ for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
+ char string[1024];
if (kLengths[i] >= sizeof(string)) {
fprintf(stderr, "Bad test string length\n");
- return 0;
+ return false;
}
memset(string, 'a', sizeof(string));
string[kLengths[i]] = '\0';
- ret = BIO_printf(bio, "test %s", string);
- if (ret != 5 + kLengths[i]) {
+ int ret = BIO_printf(bio.get(), "test %s", string);
+ if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) {
fprintf(stderr, "BIO_printf failed: %d\n", ret);
- return 0;
+ return false;
}
- if (!BIO_mem_contents(bio, &contents, &len)) {
+ const uint8_t *contents;
+ size_t len;
+ if (!BIO_mem_contents(bio.get(), &contents, &len)) {
fprintf(stderr, "BIO_mem_contents failed\n");
- return 0;
+ return false;
}
if (len != 5 + kLengths[i] ||
strncmp((const char *)contents, "test ", 5) != 0 ||
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
- return 0;
+ return false;
}
- if (!BIO_reset(bio)) {
+ if (!BIO_reset(bio.get())) {
fprintf(stderr, "BIO_reset failed\n");
- return 0;
+ return false;
}
}
- BIO_free(bio);
- return 1;
+ return true;
}
int main(void) {
-#if defined(OPENSSL_WINDOWS)
- WSADATA wsa_data;
- WORD wsa_version;
- int wsa_err;
-#endif
-
CRYPTO_library_init();
ERR_load_crypto_strings();
#if defined(OPENSSL_WINDOWS)
- /* Initialize Winsock. */
- wsa_version = MAKEWORD(2, 2);
- wsa_err = WSAStartup(wsa_version, &wsa_data);
+ // Initialize Winsock.
+ WORD wsa_version = MAKEWORD(2, 2);
+ WSADATA wsa_data;
+ int wsa_err = WSAStartup(wsa_version, &wsa_data);
if (wsa_err != 0) {
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
return 1;
@@ -345,15 +348,9 @@ int main(void) {
}
#endif
- if (!test_socket_connect()) {
- return 1;
- }
-
- if (!test_printf()) {
- return 1;
- }
-
- if (!test_zero_copy_bio_pairs()) {
+ if (!TestSocketConnect() ||
+ !TestPrintf() ||
+ !TestZeroCopyBioPairs()) {
return 1;
}
diff --git a/src/crypto/bio/buffer.c b/src/crypto/bio/buffer.c
index 5e423a1..3fc0685 100644
--- a/src/crypto/bio/buffer.c
+++ b/src/crypto/bio/buffer.c
@@ -122,17 +122,13 @@ err1:
static int buffer_free(BIO *bio) {
BIO_F_BUFFER_CTX *ctx;
- if (bio == NULL) {
+ if (bio == NULL || bio->ptr == NULL) {
return 0;
}
ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
- if (ctx->ibuf != NULL) {
- OPENSSL_free(ctx->ibuf);
- }
- if (ctx->obuf != NULL) {
- OPENSSL_free(ctx->obuf);
- }
+ OPENSSL_free(ctx->ibuf);
+ OPENSSL_free(ctx->obuf);
OPENSSL_free(bio->ptr);
bio->ptr = NULL;
@@ -315,8 +311,9 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
case BIO_CTRL_WPENDING:
ret = (long)ctx->obuf_len;
if (ret == 0) {
- if (b->next_bio == NULL)
+ if (b->next_bio == NULL) {
return 0;
+ }
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
}
break;
diff --git a/src/crypto/bio/connect.c b/src/crypto/bio/connect.c
index cbb1bb6..32361bf 100644
--- a/src/crypto/bio/connect.c
+++ b/src/crypto/bio/connect.c
@@ -161,9 +161,7 @@ static int conn_state(BIO *bio, BIO_CONNECT *c) {
break;
}
}
- if (c->param_port != NULL) {
- OPENSSL_free(c->param_port);
- }
+ OPENSSL_free(c->param_port);
c->param_port = BUF_strdup(p);
}
}
@@ -286,12 +284,8 @@ static void BIO_CONNECT_free(BIO_CONNECT *c) {
return;
}
- if (c->param_hostname != NULL) {
- OPENSSL_free(c->param_hostname);
- }
- if (c->param_port != NULL) {
- OPENSSL_free(c->param_port);
- }
+ OPENSSL_free(c->param_hostname);
+ OPENSSL_free(c->param_port);
OPENSSL_free(c);
}
@@ -397,10 +391,11 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
break;
case BIO_C_DO_STATE_MACHINE:
/* use this one to start the connection */
- if (data->state != BIO_CONN_S_OK)
+ if (data->state != BIO_CONN_S_OK) {
ret = (long)conn_state(bio, data);
- else
+ } else {
ret = 1;
+ }
break;
case BIO_C_GET_CONNECT:
/* TODO(fork): can this be removed? (Or maybe this whole file). */
@@ -425,15 +420,17 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
if (ptr != NULL) {
bio->init = 1;
if (num == 0) {
- if (data->param_hostname != NULL) {
- OPENSSL_free(data->param_hostname);
- }
+ OPENSSL_free(data->param_hostname);
data->param_hostname = BUF_strdup(ptr);
- } else if (num == 1) {
- if (data->param_port != NULL) {
- OPENSSL_free(data->param_port);
+ if (data->param_hostname == NULL) {
+ ret = 0;
}
+ } else if (num == 1) {
+ OPENSSL_free(data->param_port);
data->param_port = BUF_strdup(ptr);
+ if (data->param_port == NULL) {
+ ret = 0;
+ }
} else {
ret = 0;
}
diff --git a/src/crypto/bio/pair.c b/src/crypto/bio/pair.c
index de2b4cb..cc55950 100644
--- a/src/crypto/bio/pair.c
+++ b/src/crypto/bio/pair.c
@@ -145,7 +145,7 @@ static int bio_free(BIO *bio) {
bio_destroy_pair(bio);
}
- if (b->buf != NULL && !b->buf_externally_allocated) {
+ if (!b->buf_externally_allocated) {
OPENSSL_free(b->buf);
}
@@ -793,14 +793,10 @@ int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
err:
if (ret == 0) {
- if (bio1) {
- BIO_free(bio1);
- bio1 = NULL;
- }
- if (bio2) {
- BIO_free(bio2);
- bio2 = NULL;
- }
+ BIO_free(bio1);
+ bio1 = NULL;
+ BIO_free(bio2);
+ bio2 = NULL;
}
*bio1_p = bio1;
diff --git a/src/crypto/bio/socket.c b/src/crypto/bio/socket.c
index e86befe..98f32a6 100644
--- a/src/crypto/bio/socket.c
+++ b/src/crypto/bio/socket.c
@@ -66,6 +66,8 @@
#pragma warning(push, 3)
#include <winsock2.h>
#pragma warning(pop)
+
+#pragma comment(lib, "Ws2_32.lib")
#endif
#include "internal.h"
@@ -150,11 +152,13 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
case BIO_C_GET_FD:
if (b->init) {
ip = (int *)ptr;
- if (ip != NULL)
+ if (ip != NULL) {
*ip = b->num;
+ }
ret = b->num;
- } else
+ } else {
ret = -1;
+ }
break;
case BIO_CTRL_GET_CLOSE:
ret = b->shutdown;
diff --git a/src/crypto/bn/CMakeLists.txt b/src/crypto/bn/CMakeLists.txt
index 600be4d..25663af 100644
--- a/src/crypto/bn/CMakeLists.txt
+++ b/src/crypto/bn/CMakeLists.txt
@@ -37,7 +37,6 @@ add_library(
OBJECT
- bn_error.c
add.c
bn.c
cmp.c
@@ -70,7 +69,7 @@ perlasm(armv4-mont.${ASM_EXT} asm/armv4-mont.pl)
add_executable(
bn_test
- bn_test.c
+ bn_test.cc
)
target_link_libraries(bn_test crypto)
diff --git a/src/crypto/bn/asm/armv4-mont.pl b/src/crypto/bn/asm/armv4-mont.pl
index 5cc1328..0f1b6a9 100644
--- a/src/crypto/bn/asm/armv4-mont.pl
+++ b/src/crypto/bn/asm/armv4-mont.pl
@@ -38,8 +38,20 @@
# for execution on all NEON-capable processors, because gain on
# others outweighs the marginal loss on Cortex-A9.
-while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
$num="r0"; # starts as num argument, but holds &tp[num-1]
$ap="r1";
@@ -72,10 +84,10 @@ $code=<<___;
.text
.code 32
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
.align 5
.LOPENSSL_armcap:
-.word OPENSSL_armcap_P-bn_mul_mont
+.word OPENSSL_armcap_P-.Lbn_mul_mont
#endif
.global bn_mul_mont
@@ -84,14 +96,18 @@ $code=<<___;
.align 5
bn_mul_mont:
+.Lbn_mul_mont:
ldr ip,[sp,#4] @ load num
stmdb sp!,{r0,r2} @ sp points at argument block
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
tst ip,#7
bne .Lialu
adr r0,bn_mul_mont
ldr r2,.LOPENSSL_armcap
ldr r0,[r0,r2]
+#ifdef __APPLE__
+ ldr r0,[r0]
+#endif
tst r0,#1 @ NEON available?
ldmia sp, {r0,r2}
beq .Lialu
@@ -231,9 +247,14 @@ bn_mul_mont:
ldmia sp!,{r4-r12,lr} @ restore registers
add sp,sp,#2*4 @ skip over {r0,r2}
mov r0,#1
-.Labrt: tst lr,#1
+.Labrt:
+#if __ARM_ARCH__>=5
+ ret @ bx lr
+#else
+ tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
+#endif
.size bn_mul_mont,.-bn_mul_mont
___
{
@@ -252,7 +273,8 @@ my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("r$_",(0..5));
my ($tinptr,$toutptr,$inner,$outer)=map("r$_",(6..9));
$code.=<<___;
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
.fpu neon
.type bn_mul8x_mont_neon,%function
@@ -651,7 +673,7 @@ bn_mul8x_mont_neon:
sub sp,ip,#96
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r11}
- bx lr
+ ret @ bx lr
.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
#endif
___
@@ -659,12 +681,14 @@ ___
$code.=<<___;
.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
.comm OPENSSL_armcap_P,4,4
+.hidden OPENSSL_armcap_P
#endif
___
$code =~ s/\`([^\`]*)\`/eval $1/gem;
$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
+$code =~ s/\bret\b/bx lr/gm;
print $code;
close STDOUT;
diff --git a/src/crypto/bn/asm/x86_64-gcc.c b/src/crypto/bn/asm/x86_64-gcc.c
index c05e433..ac63934 100644
--- a/src/crypto/bn/asm/x86_64-gcc.c
+++ b/src/crypto/bn/asm/x86_64-gcc.c
@@ -1,6 +1,6 @@
#include <openssl/bn.h>
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS)
+#if defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS)
#include "../internal.h"
@@ -100,8 +100,9 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w) {
BN_ULONG c1 = 0;
- if (num <= 0)
+ if (num <= 0) {
return (c1);
+ }
while (num & ~3) {
mul_add(rp[0], ap[0], w, c1);
@@ -114,23 +115,26 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
}
if (num) {
mul_add(rp[0], ap[0], w, c1);
- if (--num == 0)
+ if (--num == 0) {
return c1;
+ }
mul_add(rp[1], ap[1], w, c1);
- if (--num == 0)
+ if (--num == 0) {
return c1;
+ }
mul_add(rp[2], ap[2], w, c1);
return c1;
}
- return (c1);
+ return c1;
}
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
BN_ULONG c1 = 0;
- if (num <= 0)
- return (c1);
+ if (num <= 0) {
+ return c1;
+ }
while (num & ~3) {
mul(rp[0], ap[0], w, c1);
@@ -143,19 +147,22 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
}
if (num) {
mul(rp[0], ap[0], w, c1);
- if (--num == 0)
+ if (--num == 0) {
return c1;
+ }
mul(rp[1], ap[1], w, c1);
- if (--num == 0)
+ if (--num == 0) {
return c1;
+ }
mul(rp[2], ap[2], w, c1);
}
- return (c1);
+ return c1;
}
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
- if (n <= 0)
+ if (n <= 0) {
return;
+ }
while (n & ~3) {
sqr(r[0], r[1], a[0]);
@@ -168,11 +175,13 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
}
if (n) {
sqr(r[0], r[1], a[0]);
- if (--n == 0)
+ if (--n == 0) {
return;
+ }
sqr(r[2], r[3], a[1]);
- if (--n == 0)
+ if (--n == 0) {
return;
+ }
sqr(r[4], r[5], a[2]);
}
}
@@ -190,8 +199,9 @@ BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
BN_ULONG ret;
size_t i = 0;
- if (n <= 0)
+ if (n <= 0) {
return 0;
+ }
asm volatile (
" subq %0,%0 \n" /* clear carry */
@@ -216,8 +226,9 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
BN_ULONG ret;
size_t i = 0;
- if (n <= 0)
+ if (n <= 0) {
return 0;
+ }
asm volatile (
" subq %0,%0 \n" /* clear borrow */
@@ -242,47 +253,56 @@ BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
BN_ULONG t1, t2;
int c = 0;
- if (n <= 0)
- return ((BN_ULONG)0);
+ if (n <= 0) {
+ return (BN_ULONG)0;
+ }
for (;;) {
t1 = a[0];
t2 = b[0];
r[0] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
- if (--n <= 0)
+ }
+ if (--n <= 0) {
break;
+ }
t1 = a[1];
t2 = b[1];
r[1] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
- if (--n <= 0)
+ }
+ if (--n <= 0) {
break;
+ }
t1 = a[2];
t2 = b[2];
r[2] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
- if (--n <= 0)
+ }
+ if (--n <= 0) {
break;
+ }
t1 = a[3];
t2 = b[3];
r[3] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
- if (--n <= 0)
+ }
+ if (--n <= 0) {
break;
+ }
a += 4;
b += 4;
r += 4;
}
- return (c);
+ return c;
}
#endif
@@ -576,4 +596,4 @@ void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
r[7] = c2;
}
-#endif /* !NO_ASM && X86_64 && !WINDOWS */
+#endif /* defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS) */
diff --git a/src/crypto/bn/bn.c b/src/crypto/bn/bn.c
index 368c4f1..f32d6b0 100644
--- a/src/crypto/bn/bn.c
+++ b/src/crypto/bn/bn.c
@@ -88,7 +88,7 @@ void BN_free(BIGNUM *bn) {
return;
}
- if (bn->d != NULL && (bn->flags & BN_FLG_STATIC_DATA) == 0) {
+ if ((bn->flags & BN_FLG_STATIC_DATA) == 0) {
OPENSSL_free(bn->d);
}
@@ -200,13 +200,15 @@ unsigned BN_num_bits_word(BN_ULONG l) {
if (l & 0xffff000000000000L) {
if (l & 0xff00000000000000L) {
return (bits[(int)(l >> 56)] + 56);
- } else
+ } else {
return (bits[(int)(l >> 48)] + 48);
+ }
} else {
if (l & 0x0000ff0000000000L) {
return (bits[(int)(l >> 40)] + 40);
- } else
+ } else {
return (bits[(int)(l >> 32)] + 32);
+ }
}
} else
#endif
@@ -302,9 +304,7 @@ BIGNUM *bn_wexpand(BIGNUM *bn, unsigned words) {
memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top);
- if (bn->d) {
- OPENSSL_free(bn->d);
- }
+ OPENSSL_free(bn->d);
bn->d = a;
bn->dmax = words;
diff --git a/src/crypto/bn/bn_error.c b/src/crypto/bn/bn_error.c
deleted file mode 100644
index b522c2a..0000000
--- a/src/crypto/bn/bn_error.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* 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/bn.h>
-
-const ERR_STRING_DATA BN_error_string_data[] = {
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_get, 0), "BN_CTX_get"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_new, 0), "BN_CTX_new"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_start, 0), "BN_CTX_start"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_bn2dec, 0), "BN_bn2dec"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_bn2hex, 0), "BN_bn2hex"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_div, 0), "BN_div"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_div_recp, 0), "BN_div_recp"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_exp, 0), "BN_exp"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_generate_dsa_nonce, 0), "BN_generate_dsa_nonce"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_generate_prime_ex, 0), "BN_generate_prime_ex"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp2_mont, 0), "BN_mod_exp2_mont"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont, 0), "BN_mod_exp_mont"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont_consttime, 0), "BN_mod_exp_mont_consttime"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont_word, 0), "BN_mod_exp_mont_word"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_inverse, 0), "BN_mod_inverse"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_inverse_no_branch, 0), "BN_mod_inverse_no_branch"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_lshift_quick, 0), "BN_mod_lshift_quick"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_sqrt, 0), "BN_mod_sqrt"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_new, 0), "BN_new"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_rand, 0), "BN_rand"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_rand_range, 0), "BN_rand_range"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_sqrt, 0), "BN_sqrt"},
- {ERR_PACK(ERR_LIB_BN, BN_F_BN_usub, 0), "BN_usub"},
- {ERR_PACK(ERR_LIB_BN, BN_F_bn_wexpand, 0), "bn_wexpand"},
- {ERR_PACK(ERR_LIB_BN, BN_F_mod_exp_recp, 0), "mod_exp_recp"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_ARG2_LT_ARG3), "ARG2_LT_ARG3"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_BAD_RECIPROCAL), "BAD_RECIPROCAL"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_BIGNUM_TOO_LONG), "BIGNUM_TOO_LONG"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_BITS_TOO_SMALL), "BITS_TOO_SMALL"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_CALLED_WITH_EVEN_MODULUS), "CALLED_WITH_EVEN_MODULUS"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_DIV_BY_ZERO), "DIV_BY_ZERO"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA), "EXPAND_ON_STATIC_BIGNUM_DATA"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_INPUT_NOT_REDUCED), "INPUT_NOT_REDUCED"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_INVALID_RANGE), "INVALID_RANGE"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_NEGATIVE_NUMBER), "NEGATIVE_NUMBER"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_A_SQUARE), "NOT_A_SQUARE"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_INITIALIZED), "NOT_INITIALIZED"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_INVERSE), "NO_INVERSE"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_PRIVATE_KEY_TOO_LARGE), "PRIVATE_KEY_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_P_IS_NOT_PRIME), "P_IS_NOT_PRIME"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_ITERATIONS), "TOO_MANY_ITERATIONS"},
- {ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_TEMPORARY_VARIABLES), "TOO_MANY_TEMPORARY_VARIABLES"},
- {0, NULL},
-};
diff --git a/src/crypto/bn/bn_test.c b/src/crypto/bn/bn_test.c
deleted file mode 100644
index e342ed8..0000000
--- a/src/crypto/bn/bn_test.c
+++ /dev/null
@@ -1,1471 +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.]
- */
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the Eric Young open source
- * license provided above.
- *
- * The binary polynomial arithmetic software is originally written by
- * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
- * Laboratories. */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/crypto.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-#include "internal.h"
-
-
-static const int num0 = 100; /* number of tests */
-static const int num1 = 50; /* additional tests for some functions */
-static const int num2 = 5; /* number of tests for slow functions */
-
-int test_add(BIO *bp);
-int test_sub(BIO *bp);
-int test_lshift1(BIO *bp);
-int test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_);
-int test_rshift1(BIO *bp);
-int test_rshift(BIO *bp, BN_CTX *ctx);
-int test_sqr(BIO *bp, BN_CTX *ctx);
-int test_mul(BIO *bp);
-int test_div(BIO *bp, BN_CTX *ctx);
-int rand_neg(void);
-
-int test_div_word(BIO *bp);
-int test_mont(BIO *bp, BN_CTX *ctx);
-int test_mod(BIO *bp, BN_CTX *ctx);
-int test_mod_mul(BIO *bp, BN_CTX *ctx);
-int test_mod_exp(BIO *bp, BN_CTX *ctx);
-int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx);
-int test_exp(BIO *bp, BN_CTX *ctx);
-int test_mod_sqrt(BIO *bp, BN_CTX *ctx);
-static int test_exp_mod_zero(void);
-int test_small_prime(BIO *bp,BN_CTX *ctx);
-int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx);
-int test_sqrt(BIO *bp, BN_CTX *ctx);
-int test_bn2bin_padded(BIO *bp, BN_CTX *ctx);
-#if 0
-int test_gf2m_add(BIO *bp);
-int test_gf2m_mod(BIO *bp);
-int test_gf2m_mod_mul(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_sqr(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_inv(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_div(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_exp(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_sqrt(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_solve_quad(BIO *bp, BN_CTX *ctx);
-#endif
-static int results = 0;
-
-static unsigned char lst[] =
- "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
- "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
-
-static void ERR_print_errors_fp(FILE *out) {
-}
-
-static void message(BIO *out, char *m) {
- BIO_puts(out, "print \"test ");
- BIO_puts(out, m);
- BIO_puts(out, "\\n\"\n");
-}
-
-int main(int argc, char *argv[]) {
- BN_CTX *ctx;
- BIO *out = NULL;
- char *outfile = NULL;
-
- CRYPTO_library_init();
-
- results = 0;
-
- argc--;
- argv++;
- while (argc >= 1) {
- if (strcmp(*argv, "-results") == 0)
- results = 1;
- else if (strcmp(*argv, "-out") == 0) {
- if (--argc < 1)
- break;
- outfile = *(++argv);
- }
- argc--;
- argv++;
- }
-
-
- ctx = BN_CTX_new();
- if (ctx == NULL)
- return 1;
-
- out = BIO_new(BIO_s_file());
- if (out == NULL) {
- return 1;
- }
-
- if (outfile == NULL) {
- BIO_set_fp(out, stdout, BIO_NOCLOSE);
- } else {
- if (!BIO_write_filename(out, outfile)) {
- perror(outfile);
- return 1;
- }
- }
-
- if (!results)
- BIO_puts(out, "obase=16\nibase=16\n");
-
- message(out, "BN_add");
- if (!test_add(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_sub");
- if (!test_sub(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_lshift1");
- if (!test_lshift1(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_lshift (fixed)");
- if (!test_lshift(out, ctx, BN_bin2bn(lst, sizeof(lst) - 1, NULL)))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_lshift");
- if (!test_lshift(out, ctx, NULL))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_rshift1");
- if (!test_rshift1(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_rshift");
- if (!test_rshift(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_sqr");
- if (!test_sqr(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mul");
- if (!test_mul(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_div");
- if (!test_div(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_div_word");
- if (!test_div_word(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod");
- if (!test_mod(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod_mul");
- if (!test_mod_mul(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mont");
- if (!test_mont(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod_exp");
- if (!test_mod_exp(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod_exp_mont_consttime");
- if (!test_mod_exp_mont_consttime(out, ctx) ||
- !test_mod_exp_mont5(out, ctx)) {
- goto err;
- }
- (void)BIO_flush(out);
-
- message(out, "BN_exp");
- if (!test_exp(out, ctx) ||
- !test_exp_mod_zero()) {
- goto err;
- }
- (void)BIO_flush(out);
-
- message(out, "BN_mod_sqrt");
- if (!test_mod_sqrt(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "Small prime generation");
- if (!test_small_prime(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_sqrt");
- if (!test_sqrt(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_bn2bin_padded");
- if (!test_bn2bin_padded(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- BN_CTX_free(ctx);
- BIO_free(out);
-
- printf("PASS\n");
- return 0;
-
-err:
- BIO_puts(out, "1\n"); /* make sure the Perl script fed by bc notices
- * the failure, see test_bn in test/Makefile.ssl*/
- (void)BIO_flush(out);
-
- return 1;
-}
-
-int test_add(BIO *bp) {
- BIGNUM a, b, c;
- int i;
-
- BN_init(&a);
- BN_init(&b);
- BN_init(&c);
-
- BN_rand(&a, 512, 0, 0);
- for (i = 0; i < num0; i++) {
- BN_rand(&b, 450 + i, 0, 0);
- a.neg = rand_neg();
- b.neg = rand_neg();
- BN_add(&c, &a, &b);
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, &a);
- BIO_puts(bp, " + ");
- BN_print(bp, &b);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, &c);
- BIO_puts(bp, "\n");
- }
- a.neg = !a.neg;
- b.neg = !b.neg;
- BN_add(&c, &c, &b);
- BN_add(&c, &c, &a);
- if (!BN_is_zero(&c)) {
- fprintf(stderr, "Add test failed!\n");
- return 0;
- }
- }
- BN_free(&a);
- BN_free(&b);
- BN_free(&c);
- return (1);
-}
-
-int test_sub(BIO *bp) {
- BIGNUM a, b, c;
- int i;
-
- BN_init(&a);
- BN_init(&b);
- BN_init(&c);
-
- for (i = 0; i < num0 + num1; i++) {
- if (i < num1) {
- BN_rand(&a, 512, 0, 0);
- BN_copy(&b, &a);
- if (BN_set_bit(&a, i) == 0)
- return (0);
- BN_add_word(&b, i);
- } else {
- BN_rand(&b, 400 + i - num1, 0, 0);
- a.neg = rand_neg();
- b.neg = rand_neg();
- }
- BN_sub(&c, &a, &b);
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, &a);
- BIO_puts(bp, " - ");
- BN_print(bp, &b);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, &c);
- BIO_puts(bp, "\n");
- }
- BN_add(&c, &c, &b);
- BN_sub(&c, &c, &a);
- if (!BN_is_zero(&c)) {
- fprintf(stderr, "Subtract test failed!\n");
- return 0;
- }
- }
- BN_free(&a);
- BN_free(&b);
- BN_free(&c);
- return (1);
-}
-
-int test_div(BIO *bp, BN_CTX *ctx) {
- BIGNUM a, b, c, d, e;
- int i;
-
- BN_init(&a);
- BN_init(&b);
- BN_init(&c);
- BN_init(&d);
- BN_init(&e);
-
- for (i = 0; i < num0 + num1; i++) {
- if (i < num1) {
- BN_rand(&a, 400, 0, 0);
- BN_copy(&b, &a);
- BN_lshift(&a, &a, i);
- BN_add_word(&a, i);
- } else
- BN_rand(&b, 50 + 3 * (i - num1), 0, 0);
- a.neg = rand_neg();
- b.neg = rand_neg();
- BN_div(&d, &c, &a, &b, ctx);
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, &a);
- BIO_puts(bp, " / ");
- BN_print(bp, &b);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, &d);
- BIO_puts(bp, "\n");
-
- if (!results) {
- BN_print(bp, &a);
- BIO_puts(bp, " % ");
- BN_print(bp, &b);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, &c);
- BIO_puts(bp, "\n");
- }
- BN_mul(&e, &d, &b, ctx);
- BN_add(&d, &e, &c);
- BN_sub(&d, &d, &a);
- if (!BN_is_zero(&d)) {
- fprintf(stderr, "Division test failed!\n");
- return 0;
- }
- }
- BN_free(&a);
- BN_free(&b);
- BN_free(&c);
- BN_free(&d);
- BN_free(&e);
- return (1);
-}
-
-int test_lshift1(BIO *bp) {
- BIGNUM *a, *b, *c;
- int i;
-
- a = BN_new();
- b = BN_new();
- c = BN_new();
-
- BN_rand(a, 200, 0, 0); /**/
- a->neg = rand_neg();
- for (i = 0; i < num0; i++) {
- BN_lshift1(b, a);
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " * 2");
- BIO_puts(bp, " - ");
- }
- BN_print(bp, b);
- BIO_puts(bp, "\n");
- }
- BN_add(c, a, a);
- BN_sub(a, b, c);
- if (!BN_is_zero(a)) {
- fprintf(stderr, "Left shift one test failed!\n");
- return 0;
- }
-
- BN_copy(a, b);
- }
- BN_free(a);
- BN_free(b);
- BN_free(c);
- return (1);
-}
-
-int test_rshift(BIO *bp, BN_CTX *ctx) {
- BIGNUM *a, *b, *c, *d, *e;
- int i;
-
- a = BN_new();
- b = BN_new();
- c = BN_new();
- d = BN_new();
- e = BN_new();
- BN_one(c);
-
- BN_rand(a, 200, 0, 0); /**/
- a->neg = rand_neg();
- for (i = 0; i < num0; i++) {
- BN_rshift(b, a, i + 1);
- BN_add(c, c, c);
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " / ");
- BN_print(bp, c);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, b);
- BIO_puts(bp, "\n");
- }
- BN_div(d, e, a, c, ctx);
- BN_sub(d, d, b);
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Right shift test failed!\n");
- return 0;
- }
- }
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (1);
-}
-
-int test_rshift1(BIO *bp) {
- BIGNUM *a, *b, *c;
- int i;
-
- a = BN_new();
- b = BN_new();
- c = BN_new();
-
- BN_rand(a, 200, 0, 0); /**/
- a->neg = rand_neg();
- for (i = 0; i < num0; i++) {
- BN_rshift1(b, a);
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " / 2");
- BIO_puts(bp, " - ");
- }
- BN_print(bp, b);
- BIO_puts(bp, "\n");
- }
- BN_sub(c, a, b);
- BN_sub(c, c, b);
- if (!BN_is_zero(c) && !BN_abs_is_word(c, 1)) {
- fprintf(stderr, "Right shift one test failed!\n");
- return 0;
- }
- BN_copy(a, b);
- }
- BN_free(a);
- BN_free(b);
- BN_free(c);
- return (1);
-}
-
-int test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_) {
- BIGNUM *a, *b, *c, *d;
- int i;
-
- b = BN_new();
- c = BN_new();
- d = BN_new();
- BN_one(c);
-
- if (a_)
- a = a_;
- else {
- a = BN_new();
- BN_rand(a, 200, 0, 0); /**/
- a->neg = rand_neg();
- }
- for (i = 0; i < num0; i++) {
- BN_lshift(b, a, i + 1);
- BN_add(c, c, c);
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " * ");
- BN_print(bp, c);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, b);
- BIO_puts(bp, "\n");
- }
- BN_mul(d, a, c, ctx);
- BN_sub(d, d, b);
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Left shift test failed!\n");
- fprintf(stderr, "a=");
- BN_print_fp(stderr, a);
- fprintf(stderr, "\nb=");
- BN_print_fp(stderr, b);
- fprintf(stderr, "\nc=");
- BN_print_fp(stderr, c);
- fprintf(stderr, "\nd=");
- BN_print_fp(stderr, d);
- fprintf(stderr, "\n");
- return 0;
- }
- }
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- return (1);
-}
-
-int test_mul(BIO *bp) {
- BIGNUM a, b, c, d, e;
- int i;
- BN_CTX *ctx;
-
- ctx = BN_CTX_new();
- if (ctx == NULL)
- abort();
-
- BN_init(&a);
- BN_init(&b);
- BN_init(&c);
- BN_init(&d);
- BN_init(&e);
-
- for (i = 0; i < num0 + num1; i++) {
- if (i <= num1) {
- BN_rand(&a, 100, 0, 0);
- BN_rand(&b, 100, 0, 0);
- } else
- BN_rand(&b, i - num1, 0, 0);
- a.neg = rand_neg();
- b.neg = rand_neg();
- BN_mul(&c, &a, &b, ctx);
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, &a);
- BIO_puts(bp, " * ");
- BN_print(bp, &b);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, &c);
- BIO_puts(bp, "\n");
- }
- BN_div(&d, &e, &c, &a, ctx);
- BN_sub(&d, &d, &b);
- if (!BN_is_zero(&d) || !BN_is_zero(&e)) {
- fprintf(stderr, "Multiplication test failed!\n");
- return 0;
- }
- }
- BN_free(&a);
- BN_free(&b);
- BN_free(&c);
- BN_free(&d);
- BN_free(&e);
- BN_CTX_free(ctx);
- return (1);
-}
-
-int test_sqr(BIO *bp, BN_CTX *ctx) {
- BIGNUM *a, *c, *d, *e;
- int i, ret = 0;
-
- 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);
- 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_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");
- goto err;
- }
- }
-
- /* 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;
-}
-
-
-int rand_neg(void) {
- static unsigned int neg = 0;
- static int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1};
-
- return (sign[(neg++) % 8]);
-}
-
-static void print_word(BIO *bp, BN_ULONG w) {
- BIO_printf(bp, BN_HEX_FMT1, w);
-}
-
-int test_div_word(BIO *bp) {
- BIGNUM a, b;
- BN_ULONG r, s;
- int i;
-
- BN_init(&a);
- BN_init(&b);
-
- for (i = 0; i < num0; i++) {
- do {
- BN_rand(&a, 512, -1, 0);
- BN_rand(&b, BN_BITS2, -1, 0);
- s = b.d[0];
- } while (!s);
-
- BN_copy(&b, &a);
- r = BN_div_word(&b, s);
-
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, &a);
- BIO_puts(bp, " / ");
- print_word(bp, s);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, &b);
- BIO_puts(bp, "\n");
-
- if (!results) {
- BN_print(bp, &a);
- BIO_puts(bp, " % ");
- print_word(bp, s);
- BIO_puts(bp, " - ");
- }
- print_word(bp, r);
- BIO_puts(bp, "\n");
- }
- BN_mul_word(&b, s);
- BN_add_word(&b, r);
- BN_sub(&b, &a, &b);
- if (!BN_is_zero(&b)) {
- fprintf(stderr, "Division (word) test failed!\n");
- return 0;
- }
- }
- BN_free(&a);
- BN_free(&b);
- return (1);
-}
-
-int test_mont(BIO *bp, BN_CTX *ctx) {
- BIGNUM a, b, c, d, A, B;
- BIGNUM n;
- int i;
- BN_MONT_CTX *mont;
-
- BN_init(&a);
- BN_init(&b);
- BN_init(&c);
- BN_init(&d);
- BN_init(&A);
- BN_init(&B);
- BN_init(&n);
-
- mont = BN_MONT_CTX_new();
- if (mont == NULL)
- return 0;
-
- BN_rand(&a, 100, 0, 0); /**/
- BN_rand(&b, 100, 0, 0); /**/
- for (i = 0; i < num2; i++) {
- int bits = (200 * (i + 1)) / num2;
-
- if (bits == 0)
- continue;
- BN_rand(&n, bits, 0, 1);
- BN_MONT_CTX_set(mont, &n, ctx);
-
- BN_nnmod(&a, &a, &n, ctx);
- BN_nnmod(&b, &b, &n, ctx);
-
- BN_to_montgomery(&A, &a, mont, ctx);
- BN_to_montgomery(&B, &b, mont, ctx);
-
- BN_mod_mul_montgomery(&c, &A, &B, mont, ctx); /**/
- BN_from_montgomery(&A, &c, mont, ctx); /**/
- if (bp != NULL) {
- if (!results) {
-#ifdef undef
- fprintf(stderr, "%d * %d %% %d\n", BN_num_bits(&a), BN_num_bits(&b),
- BN_num_bits(mont->N));
-#endif
- BN_print(bp, &a);
- BIO_puts(bp, " * ");
- BN_print(bp, &b);
- BIO_puts(bp, " % ");
- BN_print(bp, &(mont->N));
- BIO_puts(bp, " - ");
- }
- BN_print(bp, &A);
- BIO_puts(bp, "\n");
- }
- BN_mod_mul(&d, &a, &b, &n, ctx);
- BN_sub(&d, &d, &A);
- if (!BN_is_zero(&d)) {
- fprintf(stderr, "Montgomery multiplication test failed!\n");
- return 0;
- }
- }
- BN_MONT_CTX_free(mont);
- BN_free(&a);
- BN_free(&b);
- BN_free(&c);
- BN_free(&d);
- BN_free(&A);
- BN_free(&B);
- BN_free(&n);
- return (1);
-}
-
-int test_mod(BIO *bp, BN_CTX *ctx) {
- BIGNUM *a, *b, *c, *d, *e;
- int i;
-
- a = BN_new();
- b = BN_new();
- c = BN_new();
- d = BN_new();
- e = BN_new();
-
- BN_rand(a, 1024, 0, 0); /**/
- for (i = 0; i < num0; i++) {
- BN_rand(b, 450 + i * 10, 0, 0); /**/
- a->neg = rand_neg();
- b->neg = rand_neg();
- BN_mod(c, a, b, ctx); /**/
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " % ");
- BN_print(bp, b);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, c);
- BIO_puts(bp, "\n");
- }
- BN_div(d, e, a, b, ctx);
- BN_sub(e, e, c);
- if (!BN_is_zero(e)) {
- fprintf(stderr, "Modulo test failed!\n");
- return 0;
- }
- }
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (1);
-}
-
-int test_mod_mul(BIO *bp, BN_CTX *ctx) {
- BIGNUM *a, *b, *c, *d, *e;
- int i, j;
-
- a = BN_new();
- b = BN_new();
- c = BN_new();
- d = BN_new();
- e = BN_new();
-
- for (j = 0; j < 3; j++) {
- BN_rand(c, 1024, 0, 0); /**/
- for (i = 0; i < num0; i++) {
- BN_rand(a, 475 + i * 10, 0, 0); /**/
- BN_rand(b, 425 + i * 11, 0, 0); /**/
- a->neg = rand_neg();
- b->neg = rand_neg();
- if (!BN_mod_mul(e, a, b, c, ctx)) {
- unsigned long l;
-
- while ((l = ERR_get_error()))
- fprintf(stderr, "ERROR:%s\n", ERR_error_string(l, NULL));
- abort();
- }
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " * ");
- BN_print(bp, b);
- BIO_puts(bp, " % ");
- BN_print(bp, c);
- if ((a->neg ^ b->neg) && !BN_is_zero(e)) {
- /* If (a*b) % c is negative, c must be added
- * in order to obtain the normalized remainder
- * (new with OpenSSL 0.9.7, previous versions of
- * BN_mod_mul could generate negative results)
- */
- BIO_puts(bp, " + ");
- BN_print(bp, c);
- }
- BIO_puts(bp, " - ");
- }
- BN_print(bp, e);
- BIO_puts(bp, "\n");
- }
- BN_mul(d, a, b, ctx);
- BN_sub(d, d, e);
- BN_div(a, b, d, c, ctx);
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Modulo multiply test failed!\n");
- ERR_print_errors_fp(stderr);
- return 0;
- }
- }
- }
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (1);
-}
-
-int test_mod_exp(BIO *bp, BN_CTX *ctx) {
- BIGNUM *a, *b, *c, *d, *e;
- int i;
-
- a = BN_new();
- b = BN_new();
- c = BN_new();
- d = BN_new();
- e = BN_new();
-
- BN_rand(c, 30, 0, 1); /* must be odd for montgomery */
- for (i = 0; i < num2; i++) {
- BN_rand(a, 20 + i * 5, 0, 0); /**/
- BN_rand(b, 2 + i, 0, 0); /**/
-
- if (!BN_mod_exp(d, a, b, c, ctx))
- return (0);
-
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " ^ ");
- BN_print(bp, b);
- BIO_puts(bp, " % ");
- BN_print(bp, c);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, d);
- BIO_puts(bp, "\n");
- }
- BN_exp(e, a, b, ctx);
- BN_sub(e, e, d);
- BN_div(a, b, e, c, ctx);
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Modulo exponentiation test failed!\n");
- return 0;
- }
- }
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (1);
-}
-
-int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx) {
- BIGNUM *a, *b, *c, *d, *e;
- int i;
-
- a = BN_new();
- b = BN_new();
- c = BN_new();
- d = BN_new();
- e = BN_new();
-
- BN_rand(c, 30, 0, 1); /* must be odd for montgomery */
- for (i = 0; i < num2; i++) {
- BN_rand(a, 20 + i * 5, 0, 0); /**/
- BN_rand(b, 2 + i, 0, 0); /**/
-
- if (!BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL))
- return (00);
-
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " ^ ");
- BN_print(bp, b);
- BIO_puts(bp, " % ");
- BN_print(bp, c);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, d);
- BIO_puts(bp, "\n");
- }
- BN_exp(e, a, b, ctx);
- BN_sub(e, e, d);
- BN_div(a, b, e, c, ctx);
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Modulo exponentiation test failed!\n");
- return 0;
- }
- }
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (1);
-}
-
-/* Test constant-time modular exponentiation with 1024-bit inputs,
- * which on x86_64 cause a different code branch to be taken. */
-int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx) {
- BIGNUM *a, *p, *m, *d, *e;
-
- BN_MONT_CTX *mont;
-
- a = BN_new();
- p = BN_new();
- m = BN_new();
- d = BN_new();
- e = BN_new();
-
- mont = BN_MONT_CTX_new();
-
- BN_rand(m, 1024, 0, 1); /* must be odd for montgomery */
- /* Zero exponent */
- BN_rand(a, 1024, 0, 0);
- BN_zero(p);
- if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
- return 0;
- if (!BN_is_one(d)) {
- fprintf(stderr, "Modular exponentiation test failed!\n");
- return 0;
- }
- /* Zero input */
- BN_rand(p, 1024, 0, 0);
- BN_zero(a);
- if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
- return 0;
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Modular exponentiation test failed!\n");
- return 0;
- }
- /* Craft an input whose Montgomery representation is 1,
- * i.e., shorter than the modulus m, in order to test
- * the const time precomputation scattering/gathering.
- */
- BN_one(a);
- BN_MONT_CTX_set(mont, m, ctx);
- if (!BN_from_montgomery(e, a, mont, ctx) ||
- !BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL) ||
- !BN_mod_exp(a, e, p, m, ctx)) {
- return 0;
- }
- if (BN_cmp(a, d) != 0) {
- fprintf(stderr, "Modular exponentiation test failed!\n");
- return 0;
- }
- /* Finally, some regular test vectors. */
- BN_rand(e, 1024, 0, 0);
- if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))
- return 0;
- if (!BN_mod_exp(a, e, p, m, ctx))
- return 0;
- if (BN_cmp(a, d) != 0) {
- fprintf(stderr, "Modular exponentiation test failed!\n");
- return 0;
- }
-
- BN_MONT_CTX_free(mont);
- BN_free(a);
- BN_free(p);
- BN_free(m);
- BN_free(d);
- BN_free(e);
- return (1);
-}
-
-int test_exp(BIO *bp, BN_CTX *ctx) {
- BIGNUM *a, *b, *d, *e, *one;
- int i;
-
- a = BN_new();
- b = BN_new();
- d = BN_new();
- e = BN_new();
- one = BN_new();
- BN_one(one);
-
- for (i = 0; i < num2; i++) {
- BN_rand(a, 20 + i * 5, 0, 0); /**/
- BN_rand(b, 2 + i, 0, 0); /**/
-
- if (BN_exp(d, a, b, ctx) <= 0)
- return (0);
-
- if (bp != NULL) {
- if (!results) {
- BN_print(bp, a);
- BIO_puts(bp, " ^ ");
- BN_print(bp, b);
- BIO_puts(bp, " - ");
- }
- BN_print(bp, d);
- BIO_puts(bp, "\n");
- }
- BN_one(e);
- for (; !BN_is_zero(b); BN_sub(b, b, one))
- BN_mul(e, e, a, ctx);
- BN_sub(e, e, d);
- if (!BN_is_zero(e)) {
- fprintf(stderr, "Exponentiation test failed!\n");
- return 0;
- }
- }
- BN_free(a);
- BN_free(b);
- BN_free(d);
- BN_free(e);
- BN_free(one);
- return (1);
-}
-
-/* test_exp_mod_zero tests that x**0 mod 1 == 0. */
-static int test_exp_mod_zero(void) {
- BIGNUM a, p, m;
- BIGNUM r;
- BN_CTX *ctx = BN_CTX_new();
- int ret = 0;
-
- BN_init(&m);
- BN_one(&m);
-
- BN_init(&a);
- BN_one(&a);
-
- BN_init(&p);
- BN_zero(&p);
-
- BN_init(&r);
- BN_mod_exp(&r, &a, &p, &m, ctx);
- BN_CTX_free(ctx);
-
- if (BN_is_zero(&r)) {
- ret = 1;
- } else {
- printf("1**0 mod 1 = ");
- BN_print_fp(stdout, &r);
- printf(", should be 0\n");
- }
-
- BN_free(&r);
- BN_free(&a);
- BN_free(&p);
- BN_free(&m);
-
- return ret;
-}
-
-static int genprime_cb(int p, int n, BN_GENCB *arg) {
- char c = '*';
-
- if (p == 0)
- c = '.';
- if (p == 1)
- c = '+';
- if (p == 2)
- c = '*';
- if (p == 3)
- c = '\n';
- putc(c, stdout);
- fflush(stdout);
- return 1;
-}
-
-int test_mod_sqrt(BIO *bp, BN_CTX *ctx) {
- BN_GENCB cb;
- BIGNUM *a, *p, *r;
- int i, j;
- int ret = 0;
-
- a = BN_new();
- p = BN_new();
- r = BN_new();
- if (a == NULL || p == NULL || r == NULL)
- goto err;
-
- BN_GENCB_set(&cb, genprime_cb, NULL);
-
- for (i = 0; i < 16; i++) {
- if (i < 8) {
- unsigned primes[8] = {2, 3, 5, 7, 11, 13, 17, 19};
-
- if (!BN_set_word(p, primes[i]))
- goto err;
- } else {
- if (!BN_set_word(a, 32))
- goto err;
- if (!BN_set_word(r, 2 * i + 1))
- goto err;
-
- if (!BN_generate_prime_ex(p, 256, 0, a, r, &cb))
- goto err;
- putc('\n', stdout);
- }
- p->neg = rand_neg();
-
- for (j = 0; j < num2; j++) {
- /* construct 'a' such that it is a square modulo p,
- * but in general not a proper square and not reduced modulo p */
- if (!BN_rand(r, 256, 0, 3))
- goto err;
- if (!BN_nnmod(r, r, p, ctx))
- goto err;
- if (!BN_mod_sqr(r, r, p, ctx))
- goto err;
- if (!BN_rand(a, 256, 0, 3))
- goto err;
- if (!BN_nnmod(a, a, p, ctx))
- goto err;
- if (!BN_mod_sqr(a, a, p, ctx))
- goto err;
- if (!BN_mul(a, a, r, ctx))
- goto err;
- if (rand_neg())
- if (!BN_sub(a, a, p))
- goto err;
-
- if (!BN_mod_sqrt(r, a, p, ctx))
- goto err;
- if (!BN_mod_sqr(r, r, p, ctx))
- goto err;
-
- if (!BN_nnmod(a, a, p, ctx))
- goto err;
-
- if (BN_cmp(a, r) != 0) {
- fprintf(stderr, "BN_mod_sqrt failed: a = ");
- BN_print_fp(stderr, a);
- fprintf(stderr, ", r = ");
- BN_print_fp(stderr, r);
- fprintf(stderr, ", p = ");
- BN_print_fp(stderr, p);
- fprintf(stderr, "\n");
- goto err;
- }
-
- putc('.', stdout);
- fflush(stdout);
- }
-
- putc('\n', stdout);
- fflush(stderr);
- }
- ret = 1;
-err:
- if (a != NULL)
- BN_free(a);
- if (p != NULL)
- BN_free(p);
- if (r != NULL)
- BN_free(r);
- return ret;
-}
-
-int test_small_prime(BIO *bp, BN_CTX *ctx) {
- static const int bits = 10;
- int ret = 0;
- BIGNUM r;
-
- BN_init(&r);
- if (!BN_generate_prime_ex(&r, bits, 0, NULL, NULL, NULL)) {
- goto err;
- }
- if (BN_num_bits(&r) != bits) {
- BIO_printf(bp, "Expected %d bit prime, got %d bit number\n", bits,
- BN_num_bits(&r));
- goto err;
- }
-
- ret = 1;
-
-err:
- BN_free(&r);
- return ret;
-}
-
-int test_sqrt(BIO *bp, BN_CTX *ctx) {
- BIGNUM *n = BN_new(), *nn = BN_new(), *sqrt = BN_new();
- unsigned i;
-
- /* Test some random squares. */
- for (i = 0; i < 100; i++) {
- if (!BN_rand(n, 1024 /* bit length */, -1 /* no modification of top bits */,
- 0 /* don't modify bottom bit */) ||
- !BN_mul(nn, n, n, ctx) ||
- !BN_sqrt(sqrt, nn, ctx)) {
- BIO_print_errors_fp(stderr);
- return 0;
- }
- if (BN_cmp(n, sqrt) != 0) {
- fprintf(stderr, "Bad result from BN_sqrt.\n");
- return 0;
- }
- }
-
- /* Test some non-squares */
- for (i = 0; i < 100; i++) {
- if (!BN_rand(n, 1024 /* bit length */, -1 /* no modification of top bits */,
- 0 /* don't modify bottom bit */) ||
- !BN_mul(nn, n, n, ctx) ||
- !BN_add(nn, nn, BN_value_one())) {
- BIO_print_errors_fp(stderr);
- return 0;
- }
-
- if (BN_sqrt(sqrt, nn, ctx)) {
- char *nn_str = BN_bn2dec(nn);
- fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str);
- OPENSSL_free(nn_str);
- }
- }
-
- BN_free(n);
- BN_free(sqrt);
- BN_free(nn);
-
- return 1;
-}
-
-int test_bn2bin_padded(BIO *bp, BN_CTX *ctx) {
- BIGNUM *n = BN_new();
- uint8_t zeros[256], out[256], reference[128];
- size_t bytes;
-
- memset(zeros, 0, sizeof(zeros));
-
- /* Test edge case at 0. */
- if (!BN_bn2bin_padded(NULL, 0, n)) {
- fprintf(stderr,
- "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n");
- return 0;
- }
- memset(out, -1, sizeof(out));
- if (!BN_bn2bin_padded(out, sizeof(out), n)) {
- fprintf(stderr,
- "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n");
- return 0;
- }
- if (memcmp(zeros, out, sizeof(out))) {
- fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n");
- return 0;
- }
-
- /* Test a random numbers at various byte lengths. */
- for (bytes = 128 - 7; bytes <= 128; bytes++) {
- if (!BN_rand(n, bytes * 8, 0 /* make sure top bit is 1 */,
- 0 /* don't modify bottom bit */)) {
- BIO_print_errors_fp(stderr);
- return 0;
- }
- if (BN_num_bytes(n) != bytes || BN_bn2bin(n, reference) != bytes) {
- fprintf(stderr, "Bad result from BN_rand; bytes.\n");
- return 0;
- }
- /* Empty buffer should fail. */
- if (BN_bn2bin_padded(NULL, 0, n)) {
- fprintf(stderr,
- "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n");
- return 0;
- }
- /* One byte short should fail. */
- if (BN_bn2bin_padded(out, bytes - 1, n)) {
- fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n");
- return 0;
- }
- /* Exactly right size should encode. */
- if (!BN_bn2bin_padded(out, bytes, n) ||
- memcmp(out, reference, bytes) != 0) {
- fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
- return 0;
- }
- /* Pad up one byte extra. */
- if (!BN_bn2bin_padded(out, bytes + 1, n) ||
- memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) {
- fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
- return 0;
- }
- /* Pad up to 256. */
- if (!BN_bn2bin_padded(out, sizeof(out), n) ||
- memcmp(out + sizeof(out) - bytes, reference, bytes) ||
- memcmp(out, zeros, sizeof(out) - bytes)) {
- fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
- return 0;
- }
- }
-
- BN_free(n);
-
- return 1;
-}
diff --git a/src/crypto/bn/bn_test.cc b/src/crypto/bn/bn_test.cc
new file mode 100644
index 0000000..9aa2bf5
--- /dev/null
+++ b/src/crypto/bn/bn_test.cc
@@ -0,0 +1,1619 @@
+/* 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.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the Eric Young open source
+ * license provided above.
+ *
+ * The binary polynomial arithmetic software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
+ * Laboratories. */
+
+/* For BIGNUM format macros. */
+#if !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "../crypto/test/scoped_types.h"
+
+
+static const int num0 = 100; // number of tests
+static const int num1 = 50; // additional tests for some functions
+static const int num2 = 5; // number of tests for slow functions
+
+static bool test_add(FILE *fp);
+static bool test_sub(FILE *fp);
+static bool test_lshift1(FILE *fp);
+static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a);
+static bool test_rshift1(FILE *fp);
+static bool test_rshift(FILE *fp, BN_CTX *ctx);
+static bool test_sqr(FILE *fp, BN_CTX *ctx);
+static bool test_mul(FILE *fp);
+static bool test_div(FILE *fp, BN_CTX *ctx);
+static int rand_neg();
+
+static bool test_div_word(FILE *fp);
+static bool test_mont(FILE *fp, BN_CTX *ctx);
+static bool test_mod(FILE *fp, BN_CTX *ctx);
+static bool test_mod_mul(FILE *fp, BN_CTX *ctx);
+static bool test_mod_exp(FILE *fp, BN_CTX *ctx);
+static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx);
+static bool test_exp(FILE *fp, BN_CTX *ctx);
+static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx);
+static bool test_exp_mod_zero(void);
+static bool test_small_prime(FILE *fp, BN_CTX *ctx);
+static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx);
+static bool test_sqrt(FILE *fp, BN_CTX *ctx);
+static bool test_bn2bin_padded(FILE *fp, BN_CTX *ctx);
+static bool test_dec2bn(FILE *fp, BN_CTX *ctx);
+static bool test_hex2bn(FILE *fp, BN_CTX *ctx);
+static bool test_asc2bn(FILE *fp, BN_CTX *ctx);
+
+// g_results can be set to true to cause the result of each computation to be
+// printed.
+static bool g_results = false;
+
+static const uint8_t kSample[] =
+ "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
+ "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
+
+// A wrapper around puts that takes its arguments in the same order as our *_fp
+// functions.
+static void puts_fp(FILE *out, const char *m) {
+ fputs(m, out);
+}
+
+static void message(FILE *out, const char *m) {
+ puts_fp(out, "print \"test ");
+ puts_fp(out, m);
+ puts_fp(out, "\\n\"\n");
+}
+
+int main(int argc, char *argv[]) {
+ CRYPTO_library_init();
+
+ argc--;
+ argv++;
+ while (argc >= 1) {
+ if (strcmp(*argv, "-results") == 0) {
+ g_results = true;
+ }
+ argc--;
+ argv++;
+ }
+
+
+ ScopedBN_CTX ctx(BN_CTX_new());
+ if (!ctx) {
+ return 1;
+ }
+
+ if (!g_results) {
+ puts_fp(stdout, "obase=16\nibase=16\n");
+ }
+
+ message(stdout, "BN_add");
+ if (!test_add(stdout)) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_sub");
+ if (!test_sub(stdout)) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_lshift1");
+ if (!test_lshift1(stdout)) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_lshift (fixed)");
+ ScopedBIGNUM sample(BN_bin2bn(kSample, sizeof(kSample) - 1, NULL));
+ if (!sample) {
+ return 1;
+ }
+ if (!test_lshift(stdout, ctx.get(), bssl::move(sample))) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_lshift");
+ if (!test_lshift(stdout, ctx.get(), nullptr)) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_rshift1");
+ if (!test_rshift1(stdout)) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_rshift");
+ if (!test_rshift(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_sqr");
+ if (!test_sqr(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_mul");
+ if (!test_mul(stdout)) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_div");
+ if (!test_div(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_div_word");
+ if (!test_div_word(stdout)) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_mod");
+ if (!test_mod(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_mod_mul");
+ if (!test_mod_mul(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_mont");
+ if (!test_mont(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_mod_exp");
+ if (!test_mod_exp(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_mod_exp_mont_consttime");
+ if (!test_mod_exp_mont_consttime(stdout, ctx.get()) ||
+ !test_mod_exp_mont5(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_exp");
+ if (!test_exp(stdout, ctx.get()) ||
+ !test_exp_mod_zero()) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_mod_sqrt");
+ if (!test_mod_sqrt(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "Small prime generation");
+ if (!test_small_prime(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_sqrt");
+ if (!test_sqrt(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_bn2bin_padded");
+ if (!test_bn2bin_padded(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_dec2bn");
+ if (!test_dec2bn(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_hex2bn");
+ if (!test_hex2bn(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ message(stdout, "BN_asc2bn");
+ if (!test_asc2bn(stdout, ctx.get())) {
+ return 1;
+ }
+ fflush(stdout);
+
+ printf("PASS\n");
+ return 0;
+}
+
+static bool test_add(FILE *fp) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ if (!a || !b || !c || !BN_rand(a.get(), 512, 0, 0)) {
+ return false;
+ }
+
+ for (int i = 0; i < num0; i++) {
+ if (!BN_rand(b.get(), 450 + i, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ b->neg = rand_neg();
+ if (!BN_add(c.get(), a.get(), b.get())) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " + ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, "\n");
+ }
+ a->neg = !a->neg;
+ b->neg = !b->neg;
+ if (!BN_add(c.get(), c.get(), b.get()) ||
+ !BN_add(c.get(), c.get(), a.get())) {
+ return false;
+ }
+ if (!BN_is_zero(c.get())) {
+ fprintf(stderr, "Add test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_sub(FILE *fp) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ if (!a || !b || !c) {
+ return false;
+ }
+
+ for (int i = 0; i < num0 + num1; i++) {
+ if (i < num1) {
+ if (!BN_rand(a.get(), 512, 0, 0) ||
+ !BN_copy(b.get(), a.get()) ||
+ !BN_set_bit(a.get(), i) ||
+ !BN_add_word(b.get(), i)) {
+ return false;
+ }
+ } else {
+ if (!BN_rand(b.get(), 400 + i - num1, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ b->neg = rand_neg();
+ }
+ if (!BN_sub(c.get(), a.get(), b.get())) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " - ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_add(c.get(), c.get(), b.get()) ||
+ !BN_sub(c.get(), c.get(), a.get())) {
+ return false;
+ }
+ if (!BN_is_zero(c.get())) {
+ fprintf(stderr, "Subtract test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_div(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !b || !c || !d || !e) {
+ return false;
+ }
+
+ for (int i = 0; i < num0 + num1; i++) {
+ if (i < num1) {
+ if (!BN_rand(a.get(), 400, 0, 0) ||
+ !BN_copy(b.get(), a.get()) ||
+ !BN_lshift(a.get(), a.get(), i) ||
+ !BN_add_word(a.get(), i)) {
+ return false;
+ }
+ } else if (!BN_rand(b.get(), 50 + 3 * (i - num1), 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ b->neg = rand_neg();
+ if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " / ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, d.get());
+ puts_fp(fp, "\n");
+
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " % ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_mul(e.get(), d.get(), b.get(), ctx) ||
+ !BN_add(d.get(), e.get(), c.get()) ||
+ !BN_sub(d.get(), d.get(), a.get())) {
+ return false;
+ }
+ if (!BN_is_zero(d.get())) {
+ fprintf(stderr, "Division test failed!\n");
+ return false;
+ }
+ }
+
+ // Test that BN_div never gives negative zero in the quotient.
+ if (!BN_set_word(a.get(), 1) ||
+ !BN_set_word(b.get(), 2)) {
+ return false;
+ }
+ BN_set_negative(a.get(), 1);
+ if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
+ return false;
+ }
+ if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) {
+ fprintf(stderr, "Division test failed!\n");
+ return false;
+ }
+
+ // Test that BN_div never gives negative zero in the remainder.
+ if (!BN_set_word(b.get(), 1)) {
+ return false;
+ }
+ if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
+ return false;
+ }
+ if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
+ fprintf(stderr, "Division test failed!\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_lshift1(FILE *fp) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ for (int i = 0; i < num0; i++) {
+ if (!BN_lshift1(b.get(), a.get())) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " * 2");
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_add(c.get(), a.get(), a.get()) ||
+ !BN_sub(a.get(), b.get(), c.get())) {
+ return false;
+ }
+ if (!BN_is_zero(a.get())) {
+ fprintf(stderr, "Left shift one test failed!\n");
+ return false;
+ }
+
+ if (!BN_copy(a.get(), b.get())) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_rshift(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !b || !c || !d || !e || !BN_one(c.get()) ||
+ !BN_rand(a.get(), 200, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ for (int i = 0; i < num0; i++) {
+ if (!BN_rshift(b.get(), a.get(), i + 1) ||
+ !BN_add(c.get(), c.get(), c.get())) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " / ");
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_div(d.get(), e.get(), a.get(), c.get(), ctx) ||
+ !BN_sub(d.get(), d.get(), b.get())) {
+ return false;
+ }
+ if (!BN_is_zero(d.get())) {
+ fprintf(stderr, "Right shift test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_rshift1(FILE *fp) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+
+ for (int i = 0; i < num0; i++) {
+ if (!BN_rshift1(b.get(), a.get())) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " / 2");
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_sub(c.get(), a.get(), b.get()) ||
+ !BN_sub(c.get(), c.get(), b.get())) {
+ return false;
+ }
+ if (!BN_is_zero(c.get()) && !BN_abs_is_word(c.get(), 1)) {
+ fprintf(stderr, "Right shift one test failed!\n");
+ return false;
+ }
+ if (!BN_copy(a.get(), b.get())) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a) {
+ if (!a) {
+ a.reset(BN_new());
+ if (!a || !BN_rand(a.get(), 200, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ }
+
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ if (!b || !c || !d || !BN_one(c.get())) {
+ return false;
+ }
+
+ for (int i = 0; i < num0; i++) {
+ if (!BN_lshift(b.get(), a.get(), i + 1) ||
+ !BN_add(c.get(), c.get(), c.get())) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " * ");
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_mul(d.get(), a.get(), c.get(), ctx) ||
+ !BN_sub(d.get(), d.get(), b.get())) {
+ return false;
+ }
+ if (!BN_is_zero(d.get())) {
+ fprintf(stderr, "Left shift test failed!\n");
+ fprintf(stderr, "a=");
+ BN_print_fp(stderr, a.get());
+ fprintf(stderr, "\nb=");
+ BN_print_fp(stderr, b.get());
+ fprintf(stderr, "\nc=");
+ BN_print_fp(stderr, c.get());
+ fprintf(stderr, "\nd=");
+ BN_print_fp(stderr, d.get());
+ fprintf(stderr, "\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_mul(FILE *fp) {
+ ScopedBN_CTX ctx(BN_CTX_new());
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!ctx || !a || !b || !c || !d || !e) {
+ return false;
+ }
+
+ for (int i = 0; i < num0 + num1; i++) {
+ if (i <= num1) {
+ if (!BN_rand(a.get(), 100, 0, 0) ||
+ !BN_rand(b.get(), 100, 0, 0)) {
+ return false;
+ }
+ } else if (!BN_rand(b.get(), i - num1, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ b->neg = rand_neg();
+ if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " * ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx.get()) ||
+ !BN_sub(d.get(), d.get(), b.get())) {
+ return false;
+ }
+ if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
+ fprintf(stderr, "Multiplication test failed!\n");
+ return false;
+ }
+ }
+
+ // Test that BN_mul never gives negative zero.
+ if (!BN_set_word(a.get(), 1)) {
+ return false;
+ }
+ BN_set_negative(a.get(), 1);
+ BN_zero(b.get());
+ if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
+ return false;
+ }
+ if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
+ fprintf(stderr, "Multiplication test failed!\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_sqr(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !c || !d || !e) {
+ return false;
+ }
+
+ for (int i = 0; i < num0; i++) {
+ if (!BN_rand(a.get(), 40 + i * 10, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ if (!BN_sqr(c.get(), a.get(), ctx)) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " * ");
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx) ||
+ !BN_sub(d.get(), d.get(), a.get())) {
+ return false;
+ }
+ if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
+ fprintf(stderr, "Square test failed!\n");
+ return false;
+ }
+ }
+
+ // Regression test for a BN_sqr overflow bug.
+ BIGNUM *a_raw = a.get();
+ if (!BN_hex2bn(
+ &a_raw,
+ "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000") ||
+ !BN_sqr(c.get(), a.get(), ctx)) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " * ");
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
+ return false;
+ }
+ if (BN_cmp(c.get(), d.get())) {
+ fprintf(stderr,
+ "Square test failed: BN_sqr and BN_mul produce "
+ "different results!\n");
+ return false;
+ }
+
+ // Regression test for a BN_sqr overflow bug.
+ a_raw = a.get();
+ if (!BN_hex2bn(
+ &a_raw,
+ "80000000000000000000000080000001FFFFFFFE000000000000000000000000") ||
+ !BN_sqr(c.get(), a.get(), ctx)) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " * ");
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
+ return false;
+ }
+ if (BN_cmp(c.get(), d.get())) {
+ fprintf(stderr,
+ "Square test failed: BN_sqr and BN_mul produce "
+ "different results!\n");
+ return false;
+ }
+
+ return true;
+}
+
+
+static int rand_neg() {
+ static unsigned int neg = 0;
+ static const int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1};
+
+ return sign[(neg++) % 8];
+}
+
+static void print_word(FILE *fp, BN_ULONG w) {
+ fprintf(fp, BN_HEX_FMT1, w);
+}
+
+static bool test_div_word(FILE *fp) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ if (!a || !b) {
+ return false;
+ }
+
+ for (int i = 0; i < num0; i++) {
+ BN_ULONG s;
+ do {
+ if (!BN_rand(a.get(), 512, -1, 0) ||
+ !BN_rand(b.get(), BN_BITS2, -1, 0)) {
+ return false;
+ }
+ s = b->d[0];
+ } while (!s);
+
+ if (!BN_copy(b.get(), a.get())) {
+ return false;
+ }
+ BN_ULONG r = BN_div_word(b.get(), s);
+ if (r == (BN_ULONG)-1) {
+ return false;
+ }
+
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " / ");
+ print_word(fp, s);
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, "\n");
+
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " % ");
+ print_word(fp, s);
+ puts_fp(fp, " - ");
+ }
+ print_word(fp, r);
+ puts_fp(fp, "\n");
+ }
+ if (!BN_mul_word(b.get(), s) ||
+ !BN_add_word(b.get(), r) ||
+ !BN_sub(b.get(), a.get(), b.get())) {
+ return false;
+ }
+ if (!BN_is_zero(b.get())) {
+ fprintf(stderr, "Division (word) test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_mont(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM A(BN_new());
+ ScopedBIGNUM B(BN_new());
+ ScopedBIGNUM n(BN_new());
+ ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
+ if (!a || !b || !c || !d || !A || !B || !n || !mont ||
+ !BN_rand(a.get(), 100, 0, 0) ||
+ !BN_rand(b.get(), 100, 0, 0)) {
+ return false;
+ }
+
+ for (int i = 0; i < num2; i++) {
+ int bits = (200 * (i + 1)) / num2;
+
+ if (bits == 0) {
+ continue;
+ }
+ if (!BN_rand(n.get(), bits, 0, 1) ||
+ !BN_MONT_CTX_set(mont.get(), n.get(), ctx) ||
+ !BN_nnmod(a.get(), a.get(), n.get(), ctx) ||
+ !BN_nnmod(b.get(), b.get(), n.get(), ctx) ||
+ !BN_to_montgomery(A.get(), a.get(), mont.get(), ctx) ||
+ !BN_to_montgomery(B.get(), b.get(), mont.get(), ctx) ||
+ !BN_mod_mul_montgomery(c.get(), A.get(), B.get(), mont.get(), ctx) ||
+ !BN_from_montgomery(A.get(), c.get(), mont.get(), ctx)) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " * ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " % ");
+ BN_print_fp(fp, &mont->N);
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, A.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_mod_mul(d.get(), a.get(), b.get(), n.get(), ctx) ||
+ !BN_sub(d.get(), d.get(), A.get())) {
+ return false;
+ }
+ if (!BN_is_zero(d.get())) {
+ fprintf(stderr, "Montgomery multiplication test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_mod(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !b || !c || !d || !e ||
+ !BN_rand(a.get(), 1024, 0, 0)) {
+ return false;
+ }
+
+ for (int i = 0; i < num0; i++) {
+ if (!BN_rand(b.get(), 450 + i * 10, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ b->neg = rand_neg();
+ if (!BN_mod(c.get(), a.get(), b.get(), ctx)) {
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " % ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_div(d.get(), e.get(), a.get(), b.get(), ctx) ||
+ !BN_sub(e.get(), e.get(), c.get())) {
+ return false;
+ }
+ if (!BN_is_zero(e.get())) {
+ fprintf(stderr, "Modulo test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_mod_mul(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !b || !c || !d || !e) {
+ return false;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ if (!BN_rand(c.get(), 1024, 0, 0)) {
+ return false;
+ }
+ for (int i = 0; i < num0; i++) {
+ if (!BN_rand(a.get(), 475 + i * 10, 0, 0) ||
+ !BN_rand(b.get(), 425 + i * 11, 0, 0)) {
+ return false;
+ }
+ a->neg = rand_neg();
+ b->neg = rand_neg();
+ if (!BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) {
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " * ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " % ");
+ BN_print_fp(fp, c.get());
+ if (a->neg != b->neg && !BN_is_zero(e.get())) {
+ // If (a*b) % c is negative, c must be added
+ // in order to obtain the normalized remainder
+ // (new with OpenSSL 0.9.7, previous versions of
+ // BN_mod_mul could generate negative results)
+ puts_fp(fp, " + ");
+ BN_print_fp(fp, c.get());
+ }
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, e.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_mul(d.get(), a.get(), b.get(), ctx) ||
+ !BN_sub(d.get(), d.get(), e.get()) ||
+ !BN_div(a.get(), b.get(), d.get(), c.get(), ctx)) {
+ return false;
+ }
+ if (!BN_is_zero(b.get())) {
+ fprintf(stderr, "Modulo multiply test failed!\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+static bool test_mod_exp(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !b || !c || !d || !e ||
+ !BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery
+ return false;
+ }
+ for (int i = 0; i < num2; i++) {
+ if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
+ !BN_rand(b.get(), 2 + i, 0, 0) ||
+ !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) {
+ return false;
+ }
+
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " ^ ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " % ");
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, d.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
+ !BN_sub(e.get(), e.get(), d.get()) ||
+ !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
+ return false;
+ }
+ if (!BN_is_zero(b.get())) {
+ fprintf(stderr, "Modulo exponentiation test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM c(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !b || !c || !d || !e ||
+ !BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery
+ return false;
+ }
+ for (int i = 0; i < num2; i++) {
+ if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
+ !BN_rand(b.get(), 2 + i, 0, 0) ||
+ !BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
+ NULL)) {
+ return false;
+ }
+
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " ^ ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " % ");
+ BN_print_fp(fp, c.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, d.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
+ !BN_sub(e.get(), e.get(), d.get()) ||
+ !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
+ return false;
+ }
+ if (!BN_is_zero(b.get())) {
+ fprintf(stderr, "Modulo exponentiation test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+// Test constant-time modular exponentiation with 1024-bit inputs,
+// which on x86_64 cause a different code branch to be taken.
+static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM p(BN_new());
+ ScopedBIGNUM m(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !p || !m || !d || !e ||
+ !BN_rand(m.get(), 1024, 0, 1) || // must be odd for montgomery
+ !BN_rand(a.get(), 1024, 0, 0)) {
+ return false;
+ }
+ // Zero exponent.
+ BN_zero(p.get());
+ if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
+ NULL)) {
+ return false;
+ }
+ if (!BN_is_one(d.get())) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ return false;
+ }
+ if (!BN_rand(p.get(), 1024, 0, 0)) {
+ return false;
+ }
+ // Zero input.
+ BN_zero(a.get());
+ if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
+ NULL)) {
+ return false;
+ }
+ if (!BN_is_zero(d.get())) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ return false;
+ }
+ // Craft an input whose Montgomery representation is 1, i.e., shorter than the
+ // modulus m, in order to test the const time precomputation
+ // scattering/gathering.
+ ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
+ if (!mont || !BN_one(a.get()) ||
+ !BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
+ !BN_from_montgomery(e.get(), a.get(), mont.get(), ctx) ||
+ !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
+ NULL) ||
+ !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
+ return false;
+ }
+ if (BN_cmp(a.get(), d.get()) != 0) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ return false;
+ }
+ // Finally, some regular test vectors.
+ if (!BN_rand(e.get(), 1024, 0, 0) ||
+ !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
+ NULL) ||
+ !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
+ return false;
+ }
+ if (BN_cmp(a.get(), d.get()) != 0) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_exp(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM b(BN_new());
+ ScopedBIGNUM d(BN_new());
+ ScopedBIGNUM e(BN_new());
+ if (!a || !b || !d || !e) {
+ return false;
+ }
+
+ for (int i = 0; i < num2; i++) {
+ if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
+ !BN_rand(b.get(), 2 + i, 0, 0) ||
+ !BN_exp(d.get(), a.get(), b.get(), ctx)) {
+ return false;
+ }
+
+ if (fp != NULL) {
+ if (!g_results) {
+ BN_print_fp(fp, a.get());
+ puts_fp(fp, " ^ ");
+ BN_print_fp(fp, b.get());
+ puts_fp(fp, " - ");
+ }
+ BN_print_fp(fp, d.get());
+ puts_fp(fp, "\n");
+ }
+ if (!BN_one(e.get())) {
+ return false;
+ }
+ for (; !BN_is_zero(b.get()); BN_sub(b.get(), b.get(), BN_value_one())) {
+ if (!BN_mul(e.get(), e.get(), a.get(), ctx)) {
+ return false;
+ }
+ }
+ if (!BN_sub(e.get(), e.get(), d.get())) {
+ return false;
+ }
+ if (!BN_is_zero(e.get())) {
+ fprintf(stderr, "Exponentiation test failed!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+// test_exp_mod_zero tests that 1**0 mod 1 == 0.
+static bool test_exp_mod_zero(void) {
+ ScopedBIGNUM zero(BN_new());
+ if (!zero) {
+ return false;
+ }
+ BN_zero(zero.get());
+
+ ScopedBN_CTX ctx(BN_CTX_new());
+ ScopedBIGNUM r(BN_new());
+ if (!ctx || !r ||
+ !BN_mod_exp(r.get(), BN_value_one(), zero.get(), BN_value_one(), ctx.get())) {
+ return false;
+ }
+
+ if (!BN_is_zero(r.get())) {
+ printf("1**0 mod 1 = ");
+ BN_print_fp(stdout, r.get());
+ printf(", should be 0\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int genprime_cb(int p, int n, BN_GENCB *arg) {
+ char c = '*';
+
+ if (p == 0) {
+ c = '.';
+ } else if (p == 1) {
+ c = '+';
+ } else if (p == 2) {
+ c = '*';
+ } else if (p == 3) {
+ c = '\n';
+ }
+ putc(c, stdout);
+ fflush(stdout);
+ return 1;
+}
+
+static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM a(BN_new());
+ ScopedBIGNUM p(BN_new());
+ ScopedBIGNUM r(BN_new());
+ if (!a || !p || !r) {
+ return false;
+ }
+
+ BN_GENCB cb;
+ BN_GENCB_set(&cb, genprime_cb, NULL);
+
+ for (int i = 0; i < 16; i++) {
+ if (i < 8) {
+ const unsigned kPrimes[8] = {2, 3, 5, 7, 11, 13, 17, 19};
+ if (!BN_set_word(p.get(), kPrimes[i])) {
+ return false;
+ }
+ } else {
+ if (!BN_set_word(a.get(), 32) ||
+ !BN_set_word(r.get(), 2 * i + 1) ||
+ !BN_generate_prime_ex(p.get(), 256, 0, a.get(), r.get(), &cb)) {
+ return false;
+ }
+ putc('\n', stdout);
+ }
+ p->neg = rand_neg();
+
+ for (int j = 0; j < num2; j++) {
+ // construct 'a' such that it is a square modulo p, but in general not a
+ // proper square and not reduced modulo p
+ if (!BN_rand(r.get(), 256, 0, 3) ||
+ !BN_nnmod(r.get(), r.get(), p.get(), ctx) ||
+ !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
+ !BN_rand(a.get(), 256, 0, 3) ||
+ !BN_nnmod(a.get(), a.get(), p.get(), ctx) ||
+ !BN_mod_sqr(a.get(), a.get(), p.get(), ctx) ||
+ !BN_mul(a.get(), a.get(), r.get(), ctx)) {
+ return false;
+ }
+ if (rand_neg() && !BN_sub(a.get(), a.get(), p.get())) {
+ return false;
+ }
+
+ if (!BN_mod_sqrt(r.get(), a.get(), p.get(), ctx) ||
+ !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
+ !BN_nnmod(a.get(), a.get(), p.get(), ctx)) {
+ return false;
+ }
+
+ if (BN_cmp(a.get(), r.get()) != 0) {
+ fprintf(stderr, "BN_mod_sqrt failed: a = ");
+ BN_print_fp(stderr, a.get());
+ fprintf(stderr, ", r = ");
+ BN_print_fp(stderr, r.get());
+ fprintf(stderr, ", p = ");
+ BN_print_fp(stderr, p.get());
+ fprintf(stderr, "\n");
+ return false;
+ }
+
+ putc('.', stdout);
+ fflush(stdout);
+ }
+
+ putc('\n', stdout);
+ fflush(stderr);
+ }
+ return true;
+}
+
+static bool test_small_prime(FILE *fp, BN_CTX *ctx) {
+ static const int kBits = 10;
+
+ ScopedBIGNUM r(BN_new());
+ if (!r || !BN_generate_prime_ex(r.get(), kBits, 0, NULL, NULL, NULL)) {
+ return false;
+ }
+ if (BN_num_bits(r.get()) != kBits) {
+ fprintf(fp, "Expected %d bit prime, got %d bit number\n", kBits,
+ BN_num_bits(r.get()));
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_sqrt(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM n(BN_new());
+ ScopedBIGNUM nn(BN_new());
+ ScopedBIGNUM sqrt(BN_new());
+ if (!n || !nn || !sqrt) {
+ return false;
+ }
+
+ // Test some random squares.
+ for (int i = 0; i < 100; i++) {
+ if (!BN_rand(n.get(), 1024 /* bit length */,
+ -1 /* no modification of top bits */,
+ 0 /* don't modify bottom bit */) ||
+ !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
+ !BN_sqrt(sqrt.get(), nn.get(), ctx)) {
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+ if (BN_cmp(n.get(), sqrt.get()) != 0) {
+ fprintf(stderr, "Bad result from BN_sqrt.\n");
+ return false;
+ }
+ }
+
+ // Test some non-squares.
+ for (int i = 0; i < 100; i++) {
+ if (!BN_rand(n.get(), 1024 /* bit length */,
+ -1 /* no modification of top bits */,
+ 0 /* don't modify bottom bit */) ||
+ !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
+ !BN_add(nn.get(), nn.get(), BN_value_one())) {
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (BN_sqrt(sqrt.get(), nn.get(), ctx)) {
+ char *nn_str = BN_bn2dec(nn.get());
+ fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str);
+ OPENSSL_free(nn_str);
+ }
+ }
+
+ return true;
+}
+
+static bool test_bn2bin_padded(FILE *fp, BN_CTX *ctx) {
+ uint8_t zeros[256], out[256], reference[128];
+
+ memset(zeros, 0, sizeof(zeros));
+
+ // Test edge case at 0.
+ ScopedBIGNUM n(BN_new());
+ if (!n || !BN_bn2bin_padded(NULL, 0, n.get())) {
+ fprintf(stderr,
+ "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n");
+ return false;
+ }
+ memset(out, -1, sizeof(out));
+ if (!BN_bn2bin_padded(out, sizeof(out), n.get())) {
+ fprintf(stderr,
+ "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n");
+ return false;
+ }
+ if (memcmp(zeros, out, sizeof(out))) {
+ fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n");
+ return false;
+ }
+
+ // Test a random numbers at various byte lengths.
+ for (size_t bytes = 128 - 7; bytes <= 128; bytes++) {
+ if (!BN_rand(n.get(), bytes * 8, 0 /* make sure top bit is 1 */,
+ 0 /* don't modify bottom bit */)) {
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+ if (BN_num_bytes(n.get()) != bytes ||
+ BN_bn2bin(n.get(), reference) != bytes) {
+ fprintf(stderr, "Bad result from BN_rand; bytes.\n");
+ return false;
+ }
+ // Empty buffer should fail.
+ if (BN_bn2bin_padded(NULL, 0, n.get())) {
+ fprintf(stderr,
+ "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n");
+ return false;
+ }
+ // One byte short should fail.
+ if (BN_bn2bin_padded(out, bytes - 1, n.get())) {
+ fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n");
+ return false;
+ }
+ // Exactly right size should encode.
+ if (!BN_bn2bin_padded(out, bytes, n.get()) ||
+ memcmp(out, reference, bytes) != 0) {
+ fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
+ return false;
+ }
+ // Pad up one byte extra.
+ if (!BN_bn2bin_padded(out, bytes + 1, n.get()) ||
+ memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) {
+ fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
+ return false;
+ }
+ // Pad up to 256.
+ if (!BN_bn2bin_padded(out, sizeof(out), n.get()) ||
+ memcmp(out + sizeof(out) - bytes, reference, bytes) ||
+ memcmp(out, zeros, sizeof(out) - bytes)) {
+ fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int DecimalToBIGNUM(ScopedBIGNUM *out, const char *in) {
+ BIGNUM *raw = NULL;
+ int ret = BN_dec2bn(&raw, in);
+ out->reset(raw);
+ return ret;
+}
+
+static bool test_dec2bn(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM bn;
+ int ret = DecimalToBIGNUM(&bn, "0");
+ if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_dec2bn gave a bad result.\n");
+ return false;
+ }
+
+ ret = DecimalToBIGNUM(&bn, "256");
+ if (ret != 3 || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_dec2bn gave a bad result.\n");
+ return false;
+ }
+
+ ret = DecimalToBIGNUM(&bn, "-42");
+ if (ret != 3 || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_dec2bn gave a bad result.\n");
+ return false;
+ }
+
+ ret = DecimalToBIGNUM(&bn, "-0");
+ if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_dec2bn gave a bad result.\n");
+ return false;
+ }
+
+ ret = DecimalToBIGNUM(&bn, "42trailing garbage is ignored");
+ if (ret != 2 || !BN_abs_is_word(bn.get(), 42) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_dec2bn gave a bad result.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
+ BIGNUM *raw = NULL;
+ int ret = BN_hex2bn(&raw, in);
+ out->reset(raw);
+ return ret;
+}
+
+static bool test_hex2bn(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM bn;
+ int ret = HexToBIGNUM(&bn, "0");
+ if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_hex2bn gave a bad result.\n");
+ return false;
+ }
+
+ ret = HexToBIGNUM(&bn, "256");
+ if (ret != 3 || !BN_is_word(bn.get(), 0x256) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_hex2bn gave a bad result.\n");
+ return false;
+ }
+
+ ret = HexToBIGNUM(&bn, "-42");
+ if (ret != 3 || !BN_abs_is_word(bn.get(), 0x42) || !BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_hex2bn gave a bad result.\n");
+ return false;
+ }
+
+ ret = HexToBIGNUM(&bn, "-0");
+ if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_hex2bn gave a bad result.\n");
+ return false;
+ }
+
+ ret = HexToBIGNUM(&bn, "abctrailing garbage is ignored");
+ if (ret != 3 || !BN_is_word(bn.get(), 0xabc) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_hex2bn gave a bad result.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static ScopedBIGNUM ASCIIToBIGNUM(const char *in) {
+ BIGNUM *raw = NULL;
+ if (!BN_asc2bn(&raw, in)) {
+ return nullptr;
+ }
+ return ScopedBIGNUM(raw);
+}
+
+static bool test_asc2bn(FILE *fp, BN_CTX *ctx) {
+ ScopedBIGNUM bn = ASCIIToBIGNUM("0");
+ if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_asc2bn gave a bad result.\n");
+ return false;
+ }
+
+ bn = ASCIIToBIGNUM("256");
+ if (!bn || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_asc2bn gave a bad result.\n");
+ return false;
+ }
+
+ bn = ASCIIToBIGNUM("-42");
+ if (!bn || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_asc2bn gave a bad result.\n");
+ return false;
+ }
+
+ bn = ASCIIToBIGNUM("0x1234");
+ if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_asc2bn gave a bad result.\n");
+ return false;
+ }
+
+ bn = ASCIIToBIGNUM("0X1234");
+ if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_asc2bn gave a bad result.\n");
+ return false;
+ }
+
+ bn = ASCIIToBIGNUM("-0xabcd");
+ if (!bn || !BN_abs_is_word(bn.get(), 0xabcd) || !BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_asc2bn gave a bad result.\n");
+ return false;
+ }
+
+ bn = ASCIIToBIGNUM("-0");
+ if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_asc2bn gave a bad result.\n");
+ return false;
+ }
+
+ bn = ASCIIToBIGNUM("123trailing garbage is ignored");
+ if (!bn || !BN_is_word(bn.get(), 123) || BN_is_negative(bn.get())) {
+ fprintf(stderr, "BN_asc2bn gave a bad result.\n");
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/crypto/bn/convert.c b/src/crypto/bn/convert.c
index 9c7b9be..531b661 100644
--- a/src/crypto/bn/convert.c
+++ b/src/crypto/bn/convert.c
@@ -407,13 +407,9 @@ char *BN_bn2dec(const BIGNUM *a) {
ok = 1;
err:
- if (bn_data != NULL) {
- OPENSSL_free(bn_data);
- }
- if (t != NULL) {
- BN_free(t);
- }
- if (!ok && buf) {
+ OPENSSL_free(bn_data);
+ BN_free(t);
+ if (!ok) {
OPENSSL_free(buf);
buf = NULL;
}
diff --git a/src/crypto/bn/ctx.c b/src/crypto/bn/ctx.c
index e54007b..0578376 100644
--- a/src/crypto/bn/ctx.c
+++ b/src/crypto/bn/ctx.c
@@ -205,14 +205,12 @@ static void BN_STACK_init(BN_STACK *st) {
}
static void BN_STACK_finish(BN_STACK *st) {
- if (st->size)
- OPENSSL_free(st->indexes);
+ OPENSSL_free(st->indexes);
}
static int BN_STACK_push(BN_STACK *st, unsigned int idx) {
- if (st->depth == st->size)
- /* Need to expand */
- {
+ if (st->depth == st->size) {
+ /* Need to expand */
unsigned int newsize =
(st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES);
unsigned int *newitems = OPENSSL_malloc(newsize * sizeof(unsigned int));
@@ -222,9 +220,7 @@ static int BN_STACK_push(BN_STACK *st, unsigned int idx) {
if (st->depth) {
memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
}
- if (st->size) {
- OPENSSL_free(st->indexes);
- }
+ OPENSSL_free(st->indexes);
st->indexes = newitems;
st->size = newsize;
}
diff --git a/src/crypto/bn/div.c b/src/crypto/bn/div.c
index d65957a..3588ea1 100644
--- a/src/crypto/bn/div.c
+++ b/src/crypto/bn/div.c
@@ -278,12 +278,14 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
t2 = (BN_ULLONG)d1 * q;
for (;;) {
- if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2]))
+ if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) {
break;
+ }
q--;
rem += d0;
- if (rem < d0)
+ if (rem < d0) {
break; /* don't let rem overflow */
+ }
t2 -= d1;
}
#else /* !BN_LLONG */
@@ -316,14 +318,17 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
#endif
for (;;) {
- if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2])))
+ if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) {
break;
+ }
q--;
rem += d0;
- if (rem < d0)
+ if (rem < d0) {
break; /* don't let rem overflow */
- if (t2l < d1)
+ }
+ if (t2l < d1) {
t2h--;
+ }
t2l -= d1;
}
#endif /* !BN_LLONG */
@@ -357,7 +362,9 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
* BN_rshift() will overwrite it.
*/
int neg = num->neg;
- BN_rshift(rm, snum, norm_shift);
+ if (!BN_rshift(rm, snum, norm_shift)) {
+ goto err;
+ }
if (!BN_is_zero(rm)) {
rm->neg = neg;
}
@@ -485,9 +492,7 @@ int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m));
- if (abs_m) {
- BN_free(abs_m);
- }
+ BN_free(abs_m);
return ret;
}
diff --git a/src/crypto/bn/exponentiation.c b/src/crypto/bn/exponentiation.c
index 53f3e9c..d3063c9 100644
--- a/src/crypto/bn/exponentiation.c
+++ b/src/crypto/bn/exponentiation.c
@@ -172,12 +172,13 @@ int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
}
}
}
- ret = 1;
-err:
if (r != rr) {
BN_copy(r, rr);
}
+ ret = 1;
+
+err:
BN_CTX_end(ctx);
return ret;
}
@@ -685,12 +686,14 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
j = m->top; /* borrow j */
if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
- if (bn_wexpand(r, j) == NULL)
+ if (bn_wexpand(r, j) == NULL) {
goto err;
+ }
/* 2^(top*BN_BITS2) - m */
r->d[0] = (0 - m->d[0]) & BN_MASK2;
- for (i = 1; i < j; i++)
+ for (i = 1; i < j; i++) {
r->d[i] = (~m->d[i]) & BN_MASK2;
+ }
r->top = j;
/* Upper words will be zero if the corresponding words of 'm'
* were 0xfff[...], so decrement r->top accordingly. */
@@ -704,9 +707,8 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
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))
- goto err;
+ if (!start && !BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
+ goto err;
}
if (wstart == 0) {
break;
@@ -761,7 +763,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
ret = 1;
err:
- if (in_mont == NULL && mont != NULL) {
+ if (in_mont == NULL) {
BN_MONT_CTX_free(mont);
}
BN_CTX_end(ctx);
@@ -876,15 +878,14 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
BN_CTX_start(ctx);
/* Allocate a montgomery context if it was not supplied by the caller.
- * If this is not done, things will break in the montgomery part.
- */
- if (in_mont != NULL)
+ * If this is not done, things will break in the montgomery part. */
+ if (in_mont != NULL) {
mont = in_mont;
- else {
- if ((mont = BN_MONT_CTX_new()) == NULL)
- goto err;
- if (!BN_MONT_CTX_set(mont, m, ctx))
+ } else {
+ mont = BN_MONT_CTX_new();
+ if (mont == NULL || !BN_MONT_CTX_set(mont, m, ctx)) {
goto err;
+ }
}
#ifdef RSAZ_ENABLED
@@ -893,8 +894,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
* crypto/bn/rsaz_exp.c and accompanying assembly modules. */
if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) &&
rsaz_avx2_eligible()) {
- if (NULL == bn_wexpand(rr, 16))
+ if (NULL == bn_wexpand(rr, 16)) {
goto err;
+ }
RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, mont->n0[0]);
rr->top = 16;
rr->neg = 0;
@@ -902,8 +904,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
ret = 1;
goto err;
} else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) {
- if (NULL == bn_wexpand(rr, 8))
+ if (NULL == bn_wexpand(rr, 8)) {
goto err;
+ }
RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d);
rr->top = 8;
rr->neg = 0;
@@ -918,8 +921,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
#if defined(OPENSSL_BN_ASM_MONT5)
if (window >= 5) {
window = 5; /* ~5% improvement for RSA2048 sign, and even for RSA4096 */
- if ((top & 7) == 0)
+ if ((top & 7) == 0) {
powerbufLen += 2 * top * sizeof(m->d[0]);
+ }
}
#endif
(void)0;
@@ -932,20 +936,24 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
sizeof(m->d[0]) *
(top * numPowers + ((2 * top) > numPowers ? (2 * top) : numPowers));
#ifdef alloca
- if (powerbufLen < 3072)
+ if (powerbufLen < 3072) {
powerbufFree = alloca(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH);
- else
+ } else
#endif
- if ((powerbufFree = (unsigned char *)OPENSSL_malloc(
- powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL)
- goto err;
+ {
+ if ((powerbufFree = (unsigned char *)OPENSSL_malloc(
+ powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) {
+ goto err;
+ }
+ }
powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
memset(powerbuf, 0, powerbufLen);
#ifdef alloca
- if (powerbufLen < 3072)
+ if (powerbufLen < 3072) {
powerbufFree = NULL;
+ }
#endif
/* lay down tmp and am right after powers table */
@@ -961,20 +969,23 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
/* 2^(top*BN_BITS2) - m */
tmp.d[0] = (0 - m->d[0]) & BN_MASK2;
- for (i = 1; i < top; i++)
+ for (i = 1; i < top; i++) {
tmp.d[i] = (~m->d[i]) & BN_MASK2;
+ }
tmp.top = top;
- } else if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx))
+ } else if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx)) {
goto err;
+ }
/* prepare a^1 in Montgomery domain */
if (a->neg || BN_ucmp(a, m) >= 0) {
- if (!BN_mod(&am, a, m, ctx))
- goto err;
- if (!BN_to_montgomery(&am, &am, mont, ctx))
+ if (!BN_mod(&am, a, m, ctx) ||
+ !BN_to_montgomery(&am, &am, mont, ctx)) {
goto err;
- } else if (!BN_to_montgomery(&am, a, mont, ctx))
+ }
+ } else if (!BN_to_montgomery(&am, a, mont, ctx)) {
goto err;
+ }
#if defined(OPENSSL_BN_ASM_MONT5)
/* This optimization uses ideas from http://eprint.iacr.org/2011/239,
@@ -1001,16 +1012,20 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/* BN_to_montgomery can contaminate words above .top
* [in BN_DEBUG[_DEBUG] build]... */
- for (i = am.top; i < top; i++)
+ for (i = am.top; i < top; i++) {
am.d[i] = 0;
- for (i = tmp.top; i < top; i++)
+ }
+ for (i = tmp.top; i < top; i++) {
tmp.d[i] = 0;
+ }
- if (top & 7)
+ if (top & 7) {
np2 = np;
- else
- for (np2 = am.d + top, i = 0; i < top; i++)
+ } else {
+ for (np2 = am.d + top, i = 0; i < top; i++) {
np2[2 * i] = np[i];
+ }
+ }
bn_scatter5(tmp.d, top, powerbuf, 0);
bn_scatter5(am.d, am.top, powerbuf, 1);
@@ -1043,8 +1058,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
bits--;
- for (wvalue = 0, i = bits % 5; i >= 0; i--, bits--)
+ for (wvalue = 0, i = bits % 5; i >= 0; i--, bits--) {
wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
+ }
bn_gather5(tmp.d, top, powerbuf, wvalue);
/* At this point |bits| is 4 mod 5 and at least -1. (|bits| is the first bit
@@ -1056,8 +1072,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
*/
if (top & 7) {
while (bits >= 0) {
- for (wvalue = 0, i = 0; i < 5; i++, bits--)
+ for (wvalue = 0, i = 0; i < 5; i++, bits--) {
wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
+ }
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
@@ -1101,17 +1118,18 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
tmp.top = top;
bn_correct_top(&tmp);
if (ret) {
- if (!BN_copy(rr, &tmp))
+ if (!BN_copy(rr, &tmp)) {
ret = 0;
+ }
goto err; /* non-zero ret means it's not error */
}
} else
#endif
{
- if (!copy_to_prebuf(&tmp, top, powerbuf, 0, numPowers))
- goto err;
- if (!copy_to_prebuf(&am, top, powerbuf, 1, numPowers))
+ if (!copy_to_prebuf(&tmp, top, powerbuf, 0, numPowers) ||
+ !copy_to_prebuf(&am, top, powerbuf, 1, numPowers)) {
goto err;
+ }
/* If the window size is greater than 1, then calculate
* val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1)
@@ -1119,24 +1137,26 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
* to use the slight performance advantage of sqr over mul).
*/
if (window > 1) {
- if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx))
- goto err;
- if (!copy_to_prebuf(&tmp, top, powerbuf, 2, numPowers))
+ if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx) ||
+ !copy_to_prebuf(&tmp, top, powerbuf, 2, numPowers)) {
goto err;
+ }
for (i = 3; i < numPowers; i++) {
/* Calculate a^i = a^(i-1) * a */
- if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx))
- goto err;
- if (!copy_to_prebuf(&tmp, top, powerbuf, i, numPowers))
+ if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx) ||
+ !copy_to_prebuf(&tmp, top, powerbuf, i, numPowers)) {
goto err;
+ }
}
}
bits--;
- for (wvalue = 0, i = bits % window; i >= 0; i--, bits--)
+ for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) {
wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
- if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, numPowers))
+ }
+ if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, numPowers)) {
goto err;
+ }
/* Scan the exponent one window at a time starting from the most
* significant bits.
@@ -1146,32 +1166,36 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/* Scan the window, squaring the result as we go */
for (i = 0; i < window; i++, bits--) {
- if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx))
+ if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx)) {
goto err;
+ }
wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
}
/* Fetch the appropriate pre-computed value from the pre-buf */
- if (!copy_from_prebuf(&am, top, powerbuf, wvalue, numPowers))
+ if (!copy_from_prebuf(&am, top, powerbuf, wvalue, numPowers)) {
goto err;
+ }
/* Multiply the result into the intermediate result */
- if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx))
+ if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx)) {
goto err;
+ }
}
}
/* Convert the final result from montgomery to standard format */
- if (!BN_from_montgomery(rr, &tmp, mont, ctx))
+ if (!BN_from_montgomery(rr, &tmp, mont, ctx)) {
goto err;
+ }
ret = 1;
err:
- if ((in_mont == NULL) && (mont != NULL))
+ if (in_mont == NULL) {
BN_MONT_CTX_free(mont);
+ }
if (powerbuf != NULL) {
OPENSSL_cleanse(powerbuf, powerbufLen);
- if (powerbufFree)
- OPENSSL_free(powerbufFree);
+ OPENSSL_free(powerbufFree);
}
BN_CTX_end(ctx);
return (ret);
@@ -1238,13 +1262,11 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
goto err;
}
- if (in_mont != NULL)
+ if (in_mont != NULL) {
mont = in_mont;
- else {
- if ((mont = BN_MONT_CTX_new()) == NULL) {
- goto err;
- }
- if (!BN_MONT_CTX_set(mont, m, ctx)) {
+ } else {
+ mont = BN_MONT_CTX_new();
+ if (mont == NULL || !BN_MONT_CTX_set(mont, m, ctx)) {
goto err;
}
}
@@ -1328,7 +1350,7 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
ret = 1;
err:
- if (in_mont == NULL && mont != NULL) {
+ if (in_mont == NULL) {
BN_MONT_CTX_free(mont);
}
BN_CTX_end(ctx);
@@ -1477,28 +1499,33 @@ int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
if (!wvalue1 && BN_is_bit_set(p1, b)) {
/* consider bits b-window1+1 .. b for this window */
i = b - window1 + 1;
- while (!BN_is_bit_set(p1, i)) /* works for i<0 */
+ /* works for i<0 */
+ while (!BN_is_bit_set(p1, i)) {
i++;
+ }
wpos1 = i;
wvalue1 = 1;
for (i = b - 1; i >= wpos1; i--) {
wvalue1 <<= 1;
- if (BN_is_bit_set(p1, i))
+ if (BN_is_bit_set(p1, i)) {
wvalue1++;
+ }
}
}
if (!wvalue2 && BN_is_bit_set(p2, b)) {
/* consider bits b-window2+1 .. b for this window */
i = b - window2 + 1;
- while (!BN_is_bit_set(p2, i))
+ while (!BN_is_bit_set(p2, i)) {
i++;
+ }
wpos2 = i;
wvalue2 = 1;
for (i = b - 1; i >= wpos2; i--) {
wvalue2 <<= 1;
- if (BN_is_bit_set(p2, i))
+ if (BN_is_bit_set(p2, i)) {
wvalue2++;
+ }
}
}
@@ -1527,7 +1554,7 @@ int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
ret = 1;
err:
- if (in_mont == NULL && mont != NULL) {
+ if (in_mont == NULL) {
BN_MONT_CTX_free(mont);
}
BN_CTX_end(ctx);
diff --git a/src/crypto/bn/gcd.c b/src/crypto/bn/gcd.c
index 2dce296..3132c29 100644
--- a/src/crypto/bn/gcd.c
+++ b/src/crypto/bn/gcd.c
@@ -258,12 +258,8 @@ BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
goto err;
}
- BN_one(X);
BN_zero(Y);
- if (BN_copy(B, a) == NULL) {
- goto err;
- }
- if (BN_copy(A, n) == NULL) {
+ if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) {
goto err;
}
A->neg = 0;
@@ -570,12 +566,8 @@ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, const BIGNUM *a,
goto err;
}
- BN_one(X);
BN_zero(Y);
- if (BN_copy(B, a) == NULL) {
- goto err;
- }
- if (BN_copy(A, n) == NULL) {
+ if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) {
goto err;
}
A->neg = 0;
@@ -586,8 +578,9 @@ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, const BIGNUM *a,
*/
pB = &local_B;
BN_with_flags(pB, B, BN_FLG_CONSTTIME);
- if (!BN_nnmod(B, pB, A, ctx))
+ if (!BN_nnmod(B, pB, A, ctx)) {
goto err;
+ }
}
sign = -1;
/* From B = a mod |n|, A = |n| it follows that
diff --git a/src/crypto/bn/generic.c b/src/crypto/bn/generic.c
index 224a47c..0e7d867 100644
--- a/src/crypto/bn/generic.c
+++ b/src/crypto/bn/generic.c
@@ -585,23 +585,27 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
t1 = a[0];
t2 = b[0];
r[0] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
+ }
t1 = a[1];
t2 = b[1];
r[1] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
+ }
t1 = a[2];
t2 = b[2];
r[2] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
+ }
t1 = a[3];
t2 = b[3];
r[3] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
+ }
a += 4;
b += 4;
r += 4;
@@ -611,8 +615,9 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
t1 = a[0];
t2 = b[0];
r[0] = (t1 - t2 - c) & BN_MASK2;
- if (t1 != t2)
+ if (t1 != t2) {
c = (t1 < t2);
+ }
a++;
b++;
r++;
@@ -1050,11 +1055,13 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
#ifdef mul64
mh = HBITS(ml);
ml = LBITS(ml);
- for (j = 0; j < num; ++j)
+ for (j = 0; j < num; ++j) {
mul(tp[j], ap[j], ml, mh, c0);
+ }
#else
- for (j = 0; j < num; ++j)
+ for (j = 0; j < num; ++j) {
mul(tp[j], ap[j], ml, c0);
+ }
#endif
tp[num] = c0;
@@ -1067,11 +1074,13 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
#ifdef mul64
mh = HBITS(ml);
ml = LBITS(ml);
- for (j = 0; j < num; ++j)
+ for (j = 0; j < num; ++j) {
mul_add(tp[j], ap[j], ml, mh, c0);
+ }
#else
- for (j = 0; j < num; ++j)
+ for (j = 0; j < num; ++j) {
mul_add(tp[j], ap[j], ml, c0);
+ }
#endif
c1 = (tp[num] + c0) & BN_MASK2;
tp[num] = c1;
@@ -1104,13 +1113,15 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {
c0 = bn_sub_words(rp, tp, np, num);
if (tp[num] != 0 || c0 == 0) {
- for (i = 0; i < num + 2; i++)
+ for (i = 0; i < num + 2; i++) {
vp[i] = 0;
+ }
return 1;
}
}
- for (i = 0; i < num; i++)
+ for (i = 0; i < num; i++) {
rp[i] = tp[i], vp[i] = 0;
+ }
vp[num] = 0;
vp[num + 1] = 0;
return 1;
diff --git a/src/crypto/bn/internal.h b/src/crypto/bn/internal.h
index d421cf3..2674b3c 100644
--- a/src/crypto/bn/internal.h
+++ b/src/crypto/bn/internal.h
@@ -125,10 +125,10 @@
#include <openssl/base.h>
-#include <inttypes.h>
-
#if defined(OPENSSL_X86_64) && defined(_MSC_VER) && _MSC_VER >= 1400
+#pragma warning(push, 3)
#include <intrin.h>
+#pragma warning(pop)
#pragma intrinsic(__umulh, _umul128)
#endif
@@ -159,10 +159,7 @@ BIGNUM *bn_expand(BIGNUM *bn, unsigned bits);
#define BN_MASK2h1 (0xffffffff80000000L)
#define BN_TBIT (0x8000000000000000L)
#define BN_DEC_CONV (10000000000000000000UL)
-#define BN_DEC_FMT1 "%" PRIu64
-#define BN_DEC_FMT2 "%019" PRIu64
#define BN_DEC_NUM 19
-#define BN_HEX_FMT1 "%" PRIx64
#elif defined(OPENSSL_32_BIT)
@@ -179,10 +176,7 @@ BIGNUM *bn_expand(BIGNUM *bn, unsigned bits);
#define BN_MASK2h (0xffff0000L)
#define BN_TBIT (0x80000000L)
#define BN_DEC_CONV (1000000000L)
-#define BN_DEC_FMT1 "%" PRIu32
-#define BN_DEC_FMT2 "%09" PRIu32
#define BN_DEC_NUM 9
-#define BN_HEX_FMT1 "%" PRIx32
#else
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
diff --git a/src/crypto/bn/montgomery.c b/src/crypto/bn/montgomery.c
index 65e177c..152cf2d 100644
--- a/src/crypto/bn/montgomery.c
+++ b/src/crypto/bn/montgomery.c
@@ -114,6 +114,7 @@
#include <openssl/thread.h>
#include "internal.h"
+#include "../internal.h"
#if !defined(OPENSSL_NO_ASM) && \
@@ -292,44 +293,36 @@ err:
return ret;
}
-BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
- const BIGNUM *mod, BN_CTX *ctx) {
- BN_MONT_CTX *ret;
-
- CRYPTO_r_lock(lock);
- ret = *pmont;
- CRYPTO_r_unlock(lock);
- if (ret) {
- return ret;
- }
-
- /* We don't want to serialise globally while doing our lazy-init math in
- * BN_MONT_CTX_set. That punishes threads that are doing independent
- * things. Instead, punish the case where more than one thread tries to
- * lazy-init the same 'pmont', by having each do the lazy-init math work
- * independently and only use the one from the thread that wins the race
- * (the losers throw away the work they've done). */
- ret = BN_MONT_CTX_new();
- if (!ret) {
- return NULL;
- }
- if (!BN_MONT_CTX_set(ret, mod, ctx)) {
- BN_MONT_CTX_free(ret);
- return NULL;
+BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
+ const BIGNUM *mod, BN_CTX *bn_ctx) {
+ CRYPTO_MUTEX_lock_read(lock);
+ BN_MONT_CTX *ctx = *pmont;
+ CRYPTO_MUTEX_unlock(lock);
+
+ if (ctx) {
+ return ctx;
}
- /* The locked compare-and-set, after the local work is done. */
- CRYPTO_w_lock(lock);
- if (*pmont) {
- BN_MONT_CTX_free(ret);
- ret = *pmont;
- } else {
- *pmont = ret;
+ CRYPTO_MUTEX_lock_write(lock);
+ ctx = *pmont;
+ if (ctx) {
+ goto out;
}
- CRYPTO_w_unlock(lock);
+ ctx = BN_MONT_CTX_new();
+ if (ctx == NULL) {
+ goto out;
+ }
+ if (!BN_MONT_CTX_set(ctx, mod, bn_ctx)) {
+ BN_MONT_CTX_free(ctx);
+ ctx = NULL;
+ goto out;
+ }
+ *pmont = ctx;
- return ret;
+out:
+ CRYPTO_MUTEX_unlock(lock);
+ return ctx;
}
int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
@@ -514,8 +507,9 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
return 0;
}
- if (BN_copy(t, a))
+ if (BN_copy(t, a)) {
retn = BN_from_montgomery_word(ret, t, mont);
+ }
BN_CTX_end(ctx);
return retn;
diff --git a/src/crypto/bn/mul.c b/src/crypto/bn/mul.c
index 80c6288..a17d766 100644
--- a/src/crypto/bn/mul.c
+++ b/src/crypto/bn/mul.c
@@ -150,8 +150,9 @@ static BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
assert(cl >= 0);
c = bn_sub_words(r, a, b, cl);
- if (dl == 0)
+ if (dl == 0) {
return c;
+ }
r += cl;
a += cl;
@@ -330,8 +331,9 @@ static void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
/* Else do normal multiply */
if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {
bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);
- if ((dna + dnb) < 0)
+ if ((dna + dnb) < 0) {
memset(&r[2 * n2 + dna + dnb], 0, sizeof(BN_ULONG) * -(dna + dnb));
+ }
return;
}
diff --git a/src/crypto/bn/prime.c b/src/crypto/bn/prime.c
index fc9a3d5..cf3afcf 100644
--- a/src/crypto/bn/prime.c
+++ b/src/crypto/bn/prime.c
@@ -659,7 +659,13 @@ again:
/* If bits is so small that it fits into a single word then we
* additionally don't want to exceed that many bits. */
if (is_single_word) {
- BN_ULONG size_limit = (((BN_ULONG)1) << bits) - get_word(rnd) - 1;
+ BN_ULONG size_limit;
+ if (bits == BN_BITS2) {
+ /* Avoid undefined behavior. */
+ size_limit = ~((BN_ULONG)0) - get_word(rnd);
+ } else {
+ size_limit = (((BN_ULONG)1) << bits) - get_word(rnd) - 1;
+ }
if (size_limit < maxdelta) {
maxdelta = size_limit;
}
@@ -682,8 +688,9 @@ loop:
for (i = 1; i < NUMPRIMES && primes[i] < rnd_word; i++) {
if ((mods[i] + delta) % primes[i] == 0) {
delta += 2;
- if (delta > maxdelta)
+ if (delta > maxdelta) {
goto again;
+ }
goto loop;
}
}
@@ -693,8 +700,9 @@ loop:
* that gcd(rnd-1,primes) == 1 (except for 2) */
if (((mods[i] + delta) % primes[i]) <= 1) {
delta += 2;
- if (delta > maxdelta)
+ if (delta > maxdelta) {
goto again;
+ }
goto loop;
}
}
diff --git a/src/crypto/bn/random.c b/src/crypto/bn/random.c
index 285bf26..3be7510 100644
--- a/src/crypto/bn/random.c
+++ b/src/crypto/bn/random.c
@@ -321,8 +321,6 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
ret = 1;
err:
- if (k_bytes) {
- OPENSSL_free(k_bytes);
- }
+ OPENSSL_free(k_bytes);
return ret;
}
diff --git a/src/crypto/bn/sqrt.c b/src/crypto/bn/sqrt.c
index 07041f9..e71a818 100644
--- a/src/crypto/bn/sqrt.c
+++ b/src/crypto/bn/sqrt.c
@@ -420,7 +420,7 @@ vrfy:
end:
if (err) {
- if (ret != NULL && ret != in) {
+ if (ret != in) {
BN_clear_free(ret);
}
ret = NULL;
diff --git a/src/crypto/buf/CMakeLists.txt b/src/crypto/buf/CMakeLists.txt
index dabf8d1..19edf7d 100644
--- a/src/crypto/buf/CMakeLists.txt
+++ b/src/crypto/buf/CMakeLists.txt
@@ -6,5 +6,4 @@ add_library(
OBJECT
buf.c
- buf_error.c
)
diff --git a/src/crypto/buf/buf_error.c b/src/crypto/buf/buf_error.c
deleted file mode 100644
index fac6011..0000000
--- a/src/crypto/buf/buf_error.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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/buf.h>
-
-const ERR_STRING_DATA BUF_error_string_data[] = {
- {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_MEM_new, 0), "BUF_MEM_new"},
- {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_memdup, 0), "BUF_memdup"},
- {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_strndup, 0), "BUF_strndup"},
- {ERR_PACK(ERR_LIB_BUF, BUF_F_buf_mem_grow, 0), "buf_mem_grow"},
- {0, NULL},
-};
diff --git a/src/crypto/bytestring/CMakeLists.txt b/src/crypto/bytestring/CMakeLists.txt
index 8d6be7b..d1f0441 100644
--- a/src/crypto/bytestring/CMakeLists.txt
+++ b/src/crypto/bytestring/CMakeLists.txt
@@ -13,7 +13,7 @@ add_library(
add_executable(
bytestring_test
- bytestring_test.c
+ bytestring_test.cc
)
target_link_libraries(bytestring_test crypto)
diff --git a/src/crypto/bytestring/bytestring_test.c b/src/crypto/bytestring/bytestring_test.cc
index cd0155e..66e9c1e 100644
--- a/src/crypto/bytestring/bytestring_test.c
+++ b/src/crypto/bytestring/bytestring_test.cc
@@ -16,14 +16,17 @@
#include <stdlib.h>
#include <string.h>
+#include <vector>
+
#include <openssl/crypto.h>
#include <openssl/bytestring.h>
#include "internal.h"
#include "../internal.h"
+#include "../test/scoped_types.h"
-static int test_skip(void) {
+static bool TestSkip() {
static const uint8_t kData[] = {1, 2, 3};
CBS data;
@@ -36,7 +39,7 @@ static int test_skip(void) {
!CBS_skip(&data, 1);
}
-static int test_get_u(void) {
+static bool TestGetUint() {
static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
uint8_t u8;
uint16_t u16;
@@ -55,7 +58,7 @@ static int test_get_u(void) {
!CBS_get_u8(&data, &u8);
}
-static int test_get_prefixed(void) {
+static bool TestGetPrefixed() {
static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1};
uint8_t u8;
uint16_t u16;
@@ -77,7 +80,7 @@ static int test_get_prefixed(void) {
u32 == 0x30201;
}
-static int test_get_prefixed_bad(void) {
+static bool TestGetPrefixedBad() {
static const uint8_t kData1[] = {2, 1};
static const uint8_t kData2[] = {0, 2, 1};
static const uint8_t kData3[] = {0, 0, 2, 1};
@@ -85,23 +88,23 @@ static int test_get_prefixed_bad(void) {
CBS_init(&data, kData1, sizeof(kData1));
if (CBS_get_u8_length_prefixed(&data, &prefixed)) {
- return 0;
+ return false;
}
CBS_init(&data, kData2, sizeof(kData2));
if (CBS_get_u16_length_prefixed(&data, &prefixed)) {
- return 0;
+ return false;
}
CBS_init(&data, kData3, sizeof(kData3));
if (CBS_get_u24_length_prefixed(&data, &prefixed)) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int test_get_asn1(void) {
+static bool TestGetASN1() {
static const uint8_t kData1[] = {0x30, 2, 1, 2};
static const uint8_t kData2[] = {0x30, 3, 1, 2};
static const uint8_t kData3[] = {0x30, 0x80};
@@ -119,52 +122,52 @@ static int test_get_asn1(void) {
CBS_init(&data, kData1, sizeof(kData1));
if (CBS_peek_asn1_tag(&data, 0x1) ||
!CBS_peek_asn1_tag(&data, 0x30)) {
- return 0;
+ return false;
}
if (!CBS_get_asn1(&data, &contents, 0x30) ||
CBS_len(&contents) != 2 ||
memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
- return 0;
+ return false;
}
CBS_init(&data, kData2, sizeof(kData2));
- /* data is truncated */
+ // data is truncated
if (CBS_get_asn1(&data, &contents, 0x30)) {
- return 0;
+ return false;
}
CBS_init(&data, kData3, sizeof(kData3));
- /* zero byte length of length */
+ // zero byte length of length
if (CBS_get_asn1(&data, &contents, 0x30)) {
- return 0;
+ return false;
}
CBS_init(&data, kData4, sizeof(kData4));
- /* long form mistakenly used. */
+ // long form mistakenly used.
if (CBS_get_asn1(&data, &contents, 0x30)) {
- return 0;
+ return false;
}
CBS_init(&data, kData5, sizeof(kData5));
- /* length takes too many bytes. */
+ // length takes too many bytes.
if (CBS_get_asn1(&data, &contents, 0x30)) {
- return 0;
+ return false;
}
CBS_init(&data, kData1, sizeof(kData1));
- /* wrong tag. */
+ // wrong tag.
if (CBS_get_asn1(&data, &contents, 0x31)) {
- return 0;
+ return false;
}
CBS_init(&data, NULL, 0);
- /* peek at empty data. */
+ // peek at empty data.
if (CBS_peek_asn1_tag(&data, 0x30)) {
- return 0;
+ return false;
}
CBS_init(&data, NULL, 0);
- /* optional elements at empty data. */
+ // optional elements at empty data.
if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
present ||
!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
@@ -174,22 +177,22 @@ static int test_get_asn1(void) {
CBS_len(&contents) != 0 ||
!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
value != 42) {
- return 0;
+ return false;
}
CBS_init(&data, kData6, sizeof(kData6));
- /* optional element. */
+ // optional element.
if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
present ||
!CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
!present ||
CBS_len(&contents) != 3 ||
memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
- return 0;
+ return false;
}
CBS_init(&data, kData6, sizeof(kData6));
- /* optional octet string. */
+ // optional octet string.
if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
present ||
CBS_len(&contents) != 0 ||
@@ -197,97 +200,96 @@ static int test_get_asn1(void) {
!present ||
CBS_len(&contents) != 1 ||
CBS_data(&contents)[0] != 1) {
- return 0;
+ return false;
}
CBS_init(&data, kData7, sizeof(kData7));
- /* invalid optional octet string. */
+ // invalid optional octet string.
if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
- return 0;
+ return false;
}
CBS_init(&data, kData8, sizeof(kData8));
- /* optional octet string. */
+ // optional octet string.
if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
value != 42 ||
!CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
value != 1) {
- return 0;
+ return false;
}
CBS_init(&data, kData9, sizeof(kData9));
- /* invalid optional integer. */
+ // invalid optional integer.
if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int test_get_optional_asn1_bool(void) {
- CBS data;
- int val;
-
+static bool TestGetOptionalASN1Bool() {
static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01};
+ CBS data;
CBS_init(&data, NULL, 0);
- val = 2;
+ int val = 2;
if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
val != 0) {
- return 0;
+ return false;
}
CBS_init(&data, kTrue, sizeof(kTrue));
val = 2;
if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
val != 1) {
- return 0;
+ return false;
}
CBS_init(&data, kFalse, sizeof(kFalse));
val = 2;
if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) ||
val != 0) {
- return 0;
+ return false;
}
CBS_init(&data, kInvalid, sizeof(kInvalid));
if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int test_cbb_basic(void) {
+static bool TestCBBBasic() {
static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8};
uint8_t *buf;
size_t buf_len;
- int ok;
CBB cbb;
if (!CBB_init(&cbb, 100)) {
- return 0;
+ return false;
}
CBB_cleanup(&cbb);
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_u8(&cbb, 1) ||
+ if (!CBB_init(&cbb, 0)) {
+ return false;
+ }
+ if (!CBB_add_u8(&cbb, 1) ||
!CBB_add_u16(&cbb, 0x203) ||
!CBB_add_u24(&cbb, 0x40506) ||
!CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) ||
!CBB_finish(&cbb, &buf, &buf_len)) {
- return 0;
+ CBB_cleanup(&cbb);
+ return false;
}
- ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
- free(buf);
- return ok;
+ ScopedOpenSSLBytes scoper(buf);
+ return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
}
-static int test_cbb_fixed(void) {
+static bool TestCBBFixed() {
CBB cbb;
uint8_t buf[1];
uint8_t *out_buf;
@@ -298,7 +300,7 @@ static int test_cbb_fixed(void) {
!CBB_finish(&cbb, &out_buf, &out_size) ||
out_buf != NULL ||
out_size != 0) {
- return 0;
+ return false;
}
if (!CBB_init_fixed(&cbb, buf, 1) ||
@@ -308,40 +310,41 @@ static int test_cbb_fixed(void) {
out_buf != buf ||
out_size != 1 ||
buf[0] != 1) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int test_cbb_finish_child(void) {
+static bool TestCBBFinishChild() {
CBB cbb, child;
uint8_t *out_buf;
size_t out_size;
- if (!CBB_init(&cbb, 16) ||
- !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ if (!CBB_init(&cbb, 16)) {
+ return false;
+ }
+ if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
CBB_finish(&child, &out_buf, &out_size) ||
- !CBB_finish(&cbb, &out_buf, &out_size) ||
- out_size != 1 ||
- out_buf[0] != 0) {
- return 0;
+ !CBB_finish(&cbb, &out_buf, &out_size)) {
+ CBB_cleanup(&cbb);
+ return false;
}
-
- free(out_buf);
- return 1;
+ ScopedOpenSSLBytes scoper(out_buf);
+ return out_size == 1 && out_buf[0] == 0;
}
-static int test_cbb_prefixed(void) {
+static bool TestCBBPrefixed() {
static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3,
4, 5, 6, 5, 4, 1, 0, 1, 2};
uint8_t *buf;
size_t buf_len;
CBB cbb, contents, inner_contents, inner_inner_contents;
- int ok;
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_u8_length_prefixed(&cbb, &contents) ||
+ if (!CBB_init(&cbb, 0)) {
+ return false;
+ }
+ if (!CBB_add_u8_length_prefixed(&cbb, &contents) ||
!CBB_add_u8_length_prefixed(&cbb, &contents) ||
!CBB_add_u8(&contents, 1) ||
!CBB_add_u16_length_prefixed(&cbb, &contents) ||
@@ -354,28 +357,31 @@ static int test_cbb_prefixed(void) {
!CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) ||
!CBB_add_u8(&inner_inner_contents, 2) ||
!CBB_finish(&cbb, &buf, &buf_len)) {
- return 0;
+ CBB_cleanup(&cbb);
+ return false;
}
- ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
- free(buf);
- return ok;
+ ScopedOpenSSLBytes scoper(buf);
+ return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
}
-static int test_cbb_misuse(void) {
+static bool TestCBBMisuse() {
CBB cbb, child, contents;
uint8_t *buf;
size_t buf_len;
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ if (!CBB_init(&cbb, 0)) {
+ return false;
+ }
+ if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
!CBB_add_u8(&child, 1) ||
!CBB_add_u8(&cbb, 2)) {
- return 0;
+ CBB_cleanup(&cbb);
+ return false;
}
- /* Since we wrote to |cbb|, |child| is now invalid and attempts to write to
- * it should fail. */
+ // Since we wrote to |cbb|, |child| is now invalid and attempts to write to
+ // it should fail.
if (CBB_add_u8(&child, 1) ||
CBB_add_u16(&child, 1) ||
CBB_add_u24(&child, 1) ||
@@ -384,91 +390,104 @@ static int test_cbb_misuse(void) {
CBB_add_asn1(&child, &contents, 1) ||
CBB_add_bytes(&child, (const uint8_t*) "a", 1)) {
fprintf(stderr, "CBB operation on invalid CBB did not fail.\n");
- return 0;
+ CBB_cleanup(&cbb);
+ return false;
}
- if (!CBB_finish(&cbb, &buf, &buf_len) ||
- buf_len != 3 ||
- memcmp(buf, "\x01\x01\x02", 3) != 0) {
- return 0;
+ if (!CBB_finish(&cbb, &buf, &buf_len)) {
+ CBB_cleanup(&cbb);
+ return false;
}
+ ScopedOpenSSLBytes scoper(buf);
- free(buf);
-
- return 1;
+ if (buf_len != 3 ||
+ memcmp(buf, "\x01\x01\x02", 3) != 0) {
+ return false;
+ }
+ return true;
}
-static int test_cbb_asn1(void) {
+static bool TestCBBASN1() {
static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
- uint8_t *buf, *test_data;
+ uint8_t *buf;
size_t buf_len;
CBB cbb, contents, inner_contents;
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_asn1(&cbb, &contents, 0x30) ||
+ if (!CBB_init(&cbb, 0)) {
+ return false;
+ }
+ if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
!CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) ||
!CBB_finish(&cbb, &buf, &buf_len)) {
- return 0;
+ CBB_cleanup(&cbb);
+ return false;
}
+ ScopedOpenSSLBytes scoper(buf);
if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
- return 0;
+ return false;
}
- free(buf);
- test_data = malloc(100000);
- memset(test_data, 0x42, 100000);
+ std::vector<uint8_t> test_data(100000, 0x42);
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_asn1(&cbb, &contents, 0x30) ||
- !CBB_add_bytes(&contents, test_data, 130) ||
+ if (!CBB_init(&cbb, 0)) {
+ return false;
+ }
+ if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
+ !CBB_add_bytes(&contents, bssl::vector_data(&test_data), 130) ||
!CBB_finish(&cbb, &buf, &buf_len)) {
- return 0;
+ CBB_cleanup(&cbb);
+ return false;
}
+ scoper.reset(buf);
if (buf_len != 3 + 130 ||
memcmp(buf, "\x30\x81\x82", 3) != 0 ||
- memcmp(buf + 3, test_data, 130) != 0) {
- return 0;
+ memcmp(buf + 3, bssl::vector_data(&test_data), 130) != 0) {
+ return false;
}
- free(buf);
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_asn1(&cbb, &contents, 0x30) ||
- !CBB_add_bytes(&contents, test_data, 1000) ||
+ if (!CBB_init(&cbb, 0)) {
+ return false;
+ }
+ if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
+ !CBB_add_bytes(&contents, bssl::vector_data(&test_data), 1000) ||
!CBB_finish(&cbb, &buf, &buf_len)) {
- return 0;
+ CBB_cleanup(&cbb);
+ return false;
}
+ scoper.reset(buf);
if (buf_len != 4 + 1000 ||
memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
- memcmp(buf + 4, test_data, 1000)) {
- return 0;
+ memcmp(buf + 4, bssl::vector_data(&test_data), 1000)) {
+ return false;
}
- free(buf);
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_asn1(&cbb, &contents, 0x30) ||
+ if (!CBB_init(&cbb, 0)) {
+ return false;
+ }
+ if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
!CBB_add_asn1(&contents, &inner_contents, 0x30) ||
- !CBB_add_bytes(&inner_contents, test_data, 100000) ||
+ !CBB_add_bytes(&inner_contents, bssl::vector_data(&test_data), 100000) ||
!CBB_finish(&cbb, &buf, &buf_len)) {
- return 0;
+ CBB_cleanup(&cbb);
+ return false;
}
+ scoper.reset(buf);
if (buf_len != 5 + 5 + 100000 ||
memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 ||
- memcmp(buf + 10, test_data, 100000)) {
- return 0;
+ memcmp(buf + 10, bssl::vector_data(&test_data), 100000)) {
+ return false;
}
- free(buf);
- free(test_data);
- return 1;
+ return true;
}
-static int do_ber_convert(const char *name,
- const uint8_t *der_expected, size_t der_len,
- const uint8_t *ber, size_t ber_len) {
+static bool DoBerConvert(const char *name,
+ const uint8_t *der_expected, size_t der_len,
+ const uint8_t *ber, size_t ber_len) {
CBS in;
uint8_t *out;
size_t out_len;
@@ -476,44 +495,44 @@ static int do_ber_convert(const char *name,
CBS_init(&in, ber, ber_len);
if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
- return 0;
+ return false;
}
+ ScopedOpenSSLBytes scoper(out);
if (out == NULL) {
if (ber_len != der_len ||
memcmp(der_expected, ber, ber_len) != 0) {
fprintf(stderr, "%s: incorrect unconverted result.\n", name);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
if (out_len != der_len ||
memcmp(out, der_expected, der_len) != 0) {
fprintf(stderr, "%s: incorrect converted result.\n", name);
- return 0;
+ return false;
}
- free(out);
- return 1;
+ return true;
}
-static int test_ber_convert(void) {
+static bool TestBerConvert() {
static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
- /* kIndefBER contains a SEQUENCE with an indefinite length. */
+ // kIndefBER contains a SEQUENCE with an indefinite length.
static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
- /* kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
- * These parts need to be concatenated in DER form. */
+ // kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
+ // These parts need to be concatenated in DER form.
static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
0x04, 0x02, 2, 3, 0x00, 0x00};
static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
- /* kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite
- * length elements extensively. */
+ // kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite
+ // length elements extensively.
static const uint8_t kNSSBER[] = {
0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04,
@@ -536,56 +555,57 @@ static int test_ber_convert(void) {
0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
};
- return do_ber_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
- kSimpleBER, sizeof(kSimpleBER)) &&
- do_ber_convert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
- sizeof(kIndefBER)) &&
- do_ber_convert("kOctetStringBER", kOctetStringDER,
- sizeof(kOctetStringDER), kOctetStringBER,
- sizeof(kOctetStringBER)) &&
- do_ber_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
- sizeof(kNSSBER));
+ return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
+ kSimpleBER, sizeof(kSimpleBER)) &&
+ DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
+ sizeof(kIndefBER)) &&
+ DoBerConvert("kOctetStringBER", kOctetStringDER,
+ sizeof(kOctetStringDER), kOctetStringBER,
+ sizeof(kOctetStringBER)) &&
+ DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
+ sizeof(kNSSBER));
}
-typedef struct {
+struct ASN1Uint64Test {
uint64_t value;
const char *encoding;
size_t encoding_len;
-} ASN1_UINT64_TEST;
-
-static const ASN1_UINT64_TEST kAsn1Uint64Tests[] = {
- {0, "\x02\x01\x00", 3},
- {1, "\x02\x01\x01", 3},
- {127, "\x02\x01\x7f", 3},
- {128, "\x02\x02\x00\x80", 4},
- {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
- {OPENSSL_U64(0x0102030405060708),
- "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
- {OPENSSL_U64(0xffffffffffffffff),
- "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
};
-typedef struct {
+static const ASN1Uint64Test kASN1Uint64Tests[] = {
+ {0, "\x02\x01\x00", 3},
+ {1, "\x02\x01\x01", 3},
+ {127, "\x02\x01\x7f", 3},
+ {128, "\x02\x02\x00\x80", 4},
+ {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
+ {OPENSSL_U64(0x0102030405060708),
+ "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
+ {OPENSSL_U64(0xffffffffffffffff),
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
+};
+
+struct ASN1InvalidUint64Test {
const char *encoding;
size_t encoding_len;
-} ASN1_INVALID_UINT64_TEST;
-
-static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = {
- /* Bad tag. */
- {"\x03\x01\x00", 3},
- /* Empty contents. */
- {"\x02\x00", 2},
- /* Negative number. */
- {"\x02\x01\x80", 3},
- /* Overflow */
- {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
};
-static int test_asn1_uint64(void) {
- size_t i;
+static const ASN1InvalidUint64Test kASN1InvalidUint64Tests[] = {
+ // Bad tag.
+ {"\x03\x01\x00", 3},
+ // Empty contents.
+ {"\x02\x00", 2},
+ // Negative number.
+ {"\x02\x01\x80", 3},
+ // Overflow.
+ {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
+ // Leading zeros.
+ {"\x02\x02\x00\x01", 4},
+};
- for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]); i++) {
- const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i];
+static bool TestASN1Uint64() {
+ for (size_t i = 0; i < sizeof(kASN1Uint64Tests) / sizeof(kASN1Uint64Tests[0]);
+ i++) {
+ const ASN1Uint64Test *test = &kASN1Uint64Tests[i];
CBS cbs;
uint64_t value;
CBB cbb;
@@ -596,57 +616,56 @@ static int test_asn1_uint64(void) {
if (!CBS_get_asn1_uint64(&cbs, &value) ||
CBS_len(&cbs) != 0 ||
value != test->value) {
- return 0;
+ return false;
}
if (!CBB_init(&cbb, 0)) {
- return 0;
+ return false;
}
if (!CBB_add_asn1_uint64(&cbb, test->value) ||
!CBB_finish(&cbb, &out, &len)) {
CBB_cleanup(&cbb);
- return 0;
+ return false;
}
+ ScopedOpenSSLBytes scoper(out);
if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
- free(out);
- return 0;
+ return false;
}
- free(out);
}
- for (i = 0;
- i < sizeof(kAsn1InvalidUint64Tests) / sizeof(kAsn1InvalidUint64Tests[0]);
+ for (size_t i = 0;
+ i < sizeof(kASN1InvalidUint64Tests) / sizeof(kASN1InvalidUint64Tests[0]);
i++) {
- const ASN1_INVALID_UINT64_TEST *test = &kAsn1InvalidUint64Tests[i];
+ const ASN1InvalidUint64Test *test = &kASN1InvalidUint64Tests[i];
CBS cbs;
uint64_t value;
CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
if (CBS_get_asn1_uint64(&cbs, &value)) {
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
int main(void) {
CRYPTO_library_init();
- if (!test_skip() ||
- !test_get_u() ||
- !test_get_prefixed() ||
- !test_get_prefixed_bad() ||
- !test_get_asn1() ||
- !test_cbb_basic() ||
- !test_cbb_fixed() ||
- !test_cbb_finish_child() ||
- !test_cbb_misuse() ||
- !test_cbb_prefixed() ||
- !test_cbb_asn1() ||
- !test_ber_convert() ||
- !test_asn1_uint64() ||
- !test_get_optional_asn1_bool()) {
+ if (!TestSkip() ||
+ !TestGetUint() ||
+ !TestGetPrefixed() ||
+ !TestGetPrefixedBad() ||
+ !TestGetASN1() ||
+ !TestCBBBasic() ||
+ !TestCBBFixed() ||
+ !TestCBBFinishChild() ||
+ !TestCBBMisuse() ||
+ !TestCBBPrefixed() ||
+ !TestCBBASN1() ||
+ !TestBerConvert() ||
+ !TestASN1Uint64() ||
+ !TestGetOptionalASN1Bool()) {
return 1;
}
diff --git a/src/crypto/bytestring/cbb.c b/src/crypto/bytestring/cbb.c
index 4428836..f1e09a2 100644
--- a/src/crypto/bytestring/cbb.c
+++ b/src/crypto/bytestring/cbb.c
@@ -25,7 +25,6 @@ static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
if (base == NULL) {
- OPENSSL_free(buf);
return 0;
}
@@ -48,7 +47,12 @@ int CBB_init(CBB *cbb, size_t initial_capacity) {
return 0;
}
- return cbb_init(cbb, buf, initial_capacity);
+ if (!cbb_init(cbb, buf, initial_capacity)) {
+ OPENSSL_free(buf);
+ return 0;
+ }
+
+ return 1;
}
int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
@@ -62,7 +66,7 @@ int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
void CBB_cleanup(CBB *cbb) {
if (cbb->base) {
- if (cbb->base->buf && cbb->base->can_resize) {
+ if (cbb->base->can_resize) {
OPENSSL_free(cbb->base->buf);
}
OPENSSL_free(cbb->base);
@@ -276,6 +280,11 @@ int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
}
int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
+ if ((tag & 0x1f) == 0x1f) {
+ /* Long form identifier octets are not supported. */
+ return 0;
+ }
+
if (!CBB_flush(cbb) ||
!CBB_add_u8(cbb, tag)) {
return 0;
diff --git a/src/crypto/bytestring/cbs.c b/src/crypto/bytestring/cbs.c
index b417716..10f1a99 100644
--- a/src/crypto/bytestring/cbs.c
+++ b/src/crypto/bytestring/cbs.c
@@ -52,10 +52,8 @@ size_t CBS_len(const CBS *cbs) {
}
int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
- if (*out_ptr != NULL) {
- OPENSSL_free(*out_ptr);
- *out_ptr = NULL;
- }
+ OPENSSL_free(*out_ptr);
+ *out_ptr = NULL;
*out_len = 0;
if (cbs->len == 0) {
@@ -82,8 +80,9 @@ int CBS_contains_zero_byte(const CBS *cbs) {
}
int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
- if (len != cbs->len)
+ if (len != cbs->len) {
return 0;
+ }
return CRYPTO_memcmp(cbs->data, data, len) == 0;
}
@@ -290,7 +289,12 @@ int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
}
if ((data[0] & 0x80) != 0) {
- /* negative number */
+ /* Negative number. */
+ return 0;
+ }
+
+ if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) {
+ /* Extra leading zeros. */
return 0;
}
diff --git a/src/crypto/chacha/chacha_vec.c b/src/crypto/chacha/chacha_vec.c
index 88830bc..14b54a7 100644
--- a/src/crypto/chacha/chacha_vec.c
+++ b/src/crypto/chacha/chacha_vec.c
@@ -40,6 +40,7 @@ typedef unsigned vec __attribute__((vector_size(16)));
* This implementation supports parallel processing of multiple blocks,
* including potentially using general-purpose registers. */
#if __ARM_NEON__
+#include <string.h>
#include <arm_neon.h>
#define GPR_TOO 1
#define VBPI 2
@@ -158,33 +159,19 @@ void CRYPTO_chacha_20(
{
unsigned iters, i, *op=(unsigned *)out, *ip=(unsigned *)in, *kp;
#if defined(__ARM_NEON__)
- unsigned *np;
+ uint32_t np[2];
uint8_t alignment_buffer[16] __attribute__((aligned(16)));
#endif
vec s0, s1, s2, s3;
-#if !defined(__ARM_NEON__) && !defined(__SSE2__)
- __attribute__ ((aligned (16))) unsigned key[8], nonce[4];
-#endif
__attribute__ ((aligned (16))) unsigned chacha_const[] =
{0x61707865,0x3320646E,0x79622D32,0x6B206574};
-#if defined(__ARM_NEON__) || defined(__SSE2__)
- kp = (unsigned *)key;
-#else
- ((vec *)key)[0] = REVV_BE(((vec *)key)[0]);
- ((vec *)key)[1] = REVV_BE(((vec *)key)[1]);
- nonce[0] = REVW_BE(((unsigned *)nonce)[0]);
- nonce[1] = REVW_BE(((unsigned *)nonce)[1]);
- nonce[2] = REVW_BE(((unsigned *)nonce)[2]);
- nonce[3] = REVW_BE(((unsigned *)nonce)[3]);
kp = (unsigned *)key;
- np = (unsigned *)nonce;
-#endif
#if defined(__ARM_NEON__)
- np = (unsigned*) nonce;
+ memcpy(np, nonce, 8);
#endif
s0 = LOAD_ALIGNED(chacha_const);
- s1 = LOAD_ALIGNED(&((vec*)kp)[0]);
- s2 = LOAD_ALIGNED(&((vec*)kp)[1]);
+ s1 = LOAD(&((vec*)kp)[0]);
+ s2 = LOAD(&((vec*)kp)[1]);
s3 = (vec){
counter & 0xffffffff,
#if __ARM_NEON__ || defined(OPENSSL_X86)
diff --git a/src/crypto/chacha/chacha_vec_arm.S b/src/crypto/chacha/chacha_vec_arm.S
index 15d4556..ddc374e 100644
--- a/src/crypto/chacha/chacha_vec_arm.S
+++ b/src/crypto/chacha/chacha_vec_arm.S
@@ -59,131 +59,147 @@
.thumb_func
.type CRYPTO_chacha_20_neon, %function
CRYPTO_chacha_20_neon:
- @ args = 8, pretend = 0, frame = 128
+ @ args = 8, pretend = 0, frame = 152
@ frame_needed = 1, uses_anonymous_args = 0
push {r4, r5, r6, r7, r8, r9, r10, fp, lr}
- mov r4, r2
+ mov r8, r3
vpush.64 {d8, d9, d10, d11, d12, d13, d14, d15}
- movw r8, #43691
- movt r8, 43690
- mov ip, r3
- umull r8, r9, r4, r8
- sub sp, sp, #132
- add r7, sp, #0
- sub sp, sp, #112
+ mov r9, r2
+ ldr r4, .L91+16
mov fp, r0
mov r10, r1
+ mov lr, r8
+.LPIC16:
+ add r4, pc
+ sub sp, sp, #156
+ add r7, sp, #0
+ sub sp, sp, #112
+ add r6, r7, #144
+ str r0, [r7, #88]
+ str r1, [r7, #12]
str r2, [r7, #8]
+ ldmia r4, {r0, r1, r2, r3}
add r4, sp, #15
- ldr r2, .L92+16
bic r4, r4, #15
- ldr r5, [r7, #232]
- add lr, r4, #64
-.LPIC16:
- add r2, pc
- str r0, [r7, #60]
- str r1, [r7, #12]
- str r3, [r7, #44]
- ldmia r2, {r0, r1, r2, r3}
- ldr r6, [r5]
- str r4, [r7, #72]
- ldr r5, [r5, #4]
- ldr r4, [r7, #236]
- str r6, [r7, #120]
- str r5, [r7, #124]
- str r4, [r7, #112]
- stmia lr, {r0, r1, r2, r3}
- movs r3, #0
- ldr r0, [r7, #72]
- str r3, [r7, #116]
- lsrs r3, r9, #7
- vldr d22, [r7, #112]
- vldr d23, [r7, #120]
- vldr d24, [r0, #64]
- vldr d25, [r0, #72]
- vld1.64 {d26-d27}, [ip:64]
- vldr d28, [ip, #16]
- vldr d29, [ip, #24]
+ ldr ip, [r7, #256]
+ str r4, [r7, #84]
+ mov r5, r4
+ adds r4, r4, #64
+ adds r5, r5, #80
+ str r8, [r7, #68]
+ stmia r4, {r0, r1, r2, r3}
+ movw r4, #43691
+ ldr r0, [ip] @ unaligned
+ movt r4, 43690
+ ldr r1, [ip, #4] @ unaligned
+ ldr r3, [r7, #84]
+ ldr r2, [r8, #8] @ unaligned
+ mov r8, #0
+ stmia r6!, {r0, r1}
+ mov r6, r5
+ ldr r1, [lr, #4] @ unaligned
+ ldr r0, [lr] @ unaligned
+ vldr d24, [r3, #64]
+ vldr d25, [r3, #72]
+ ldr r3, [lr, #12] @ unaligned
+ str r5, [r7, #80]
+ stmia r5!, {r0, r1, r2, r3}
+ ldr r0, [lr, #16]! @ unaligned
+ ldr r2, [r7, #84]
+ umull r4, r5, r9, r4
+ vldr d26, [r2, #80]
+ vldr d27, [r2, #88]
+ ldr r1, [lr, #4] @ unaligned
+ ldr r2, [lr, #8] @ unaligned
+ ldr r3, [lr, #12] @ unaligned
+ ldr r4, [r7, #260]
+ stmia r6!, {r0, r1, r2, r3}
+ ldr r3, [ip]
+ ldr r1, [r7, #84]
+ ldr r2, [ip, #4]
+ str r3, [r7, #64]
+ vldr d28, [r1, #80]
+ vldr d29, [r1, #88]
+ str r3, [r7, #136]
+ lsrs r3, r5, #7
+ str r4, [r7, #128]
+ str r2, [r7, #140]
+ str r8, [r7, #132]
+ str r2, [r7, #60]
+ vldr d22, [r7, #128]
+ vldr d23, [r7, #136]
beq .L26
- ldr r1, [r0, #64]
lsls r2, r3, #8
+ ldr r5, [r1, #64]
sub r3, r2, r3, lsl #6
+ ldr r2, [r1, #68]
+ vldr d0, .L91
+ vldr d1, .L91+8
+ adds r4, r4, #2
+ str r5, [r7, #56]
+ str r2, [r7, #52]
+ ldr r5, [r1, #72]
+ ldr r2, [r1, #76]
str r3, [r7, #4]
- ldr r2, [r0, #72]
- str r1, [r7, #40]
- mov r1, r3
- ldr r3, [r0, #68]
- vldr d0, .L92
- vldr d1, .L92+8
- str r2, [r7, #32]
- adds r2, r4, #2
- str r3, [r7, #36]
- ldr r3, [r0, #76]
- str r2, [r7, #48]
- mov r2, r0
- mov r0, fp
- str r10, [r7, #64]
- str r3, [r7, #28]
- adds r3, r0, r1
- mov r1, r6
+ str r5, [r7, #48]
+ str r2, [r7, #44]
+ mov r2, fp
+ str r4, [r7, #72]
+ adds r3, r2, r3
+ str r10, [r7, #76]
str r3, [r7, #16]
- add r3, r2, #80
- mov r2, r5
- str r3, [r7, #68]
.L4:
- ldr r0, [r7, #44]
- add r8, r7, #28
- str r2, [r7, #108]
+ ldr r5, [r7, #68]
+ add r8, r7, #44
+ ldr r4, [r7, #72]
vadd.i32 q3, q11, q0
ldmia r8, {r8, r9, r10, fp}
vmov q8, q14 @ v4si
- ldr r3, [r0]
+ ldr r2, [r5, #4]
vmov q1, q13 @ v4si
+ ldr r3, [r5]
vmov q9, q12 @ v4si
+ ldr lr, [r5, #20]
vmov q2, q11 @ v4si
- str r3, [r7, #52]
- mov r3, r0
- ldr r5, [r3, #8]
+ mov r0, r2
+ ldr r2, [r5, #8]
+ str r3, [r7, #108]
+ mov r3, r5
+ ldr ip, [r5, #16]
vmov q15, q14 @ v4si
- ldr lr, [r3, #20]
+ mov r1, r2
+ ldr r2, [r5, #12]
+ ldr r5, [r5, #24]
vmov q5, q13 @ v4si
- ldr r6, [r3, #12]
+ ldr r6, [r3, #28]
vmov q10, q12 @ v4si
- str r5, [r7, #92]
- mov r5, r3
- ldr r4, [r5, #28]
+ ldr r3, [r7, #64]
+ str r5, [r7, #116]
movs r5, #10
- ldr ip, [r3, #16]
- ldr r3, [r3, #24]
- str r4, [r7, #104]
- ldr r4, [r7, #48]
- str r3, [r7, #100]
- mov r3, r1
- str r6, [r7, #56]
- str r4, [r7, #96]
- str r8, [r7, #80]
+ str r6, [r7, #120]
+ str r4, [r7, #112]
+ ldr r6, [r7, #60]
+ str r8, [r7, #96]
mov r8, r10
- ldr r0, [r0, #4]
+ ldr r4, [r7, #108]
mov r10, r9
- ldr r1, [r7, #92]
- ldr r2, [r7, #56]
- ldr r9, [r7, #100]
- ldr r4, [r7, #52]
- str lr, [r7, #88]
+ ldr r9, [r7, #116]
+ str lr, [r7, #104]
mov lr, r3
- str r5, [r7, #76]
+ str r5, [r7, #92]
movs r5, #0
- str r5, [r7, #84]
- b .L93
-.L94:
+ str r6, [r7, #124]
+ str r5, [r7, #100]
+ b .L92
+.L93:
.align 3
-.L92:
+.L91:
.word 1
.word 0
.word 0
.word 0
.word .LANCHOR0-(.LPIC16+4)
-.L93:
+.L92:
.L3:
vadd.i32 q9, q9, q1
add r3, r8, r0
@@ -192,8 +208,8 @@ CRYPTO_chacha_20_neon:
veor q3, q3, q9
mov r6, r3
veor q2, q2, q10
- ldr r3, [r7, #80]
- str r5, [r7, #100]
+ ldr r3, [r7, #96]
+ str r5, [r7, #116]
add r10, r10, r1
vrev32.16 q3, q3
eor lr, lr, r10
@@ -201,13 +217,13 @@ CRYPTO_chacha_20_neon:
vrev32.16 q2, q2
vadd.i32 q15, q15, q2
mov fp, r3
- ldr r3, [r7, #96]
+ ldr r3, [r7, #112]
veor q4, q8, q1
- str r6, [r7, #96]
+ str r6, [r7, #112]
veor q6, q15, q5
eors r3, r3, r5
mov r5, r6
- ldr r6, [r7, #84]
+ ldr r6, [r7, #100]
vshl.i32 q1, q4, #12
vshl.i32 q5, q6, #12
add fp, fp, r2
@@ -216,33 +232,33 @@ CRYPTO_chacha_20_neon:
vsri.32 q1, q4, #20
ror lr, lr, #16
mov r5, r6
- ldr r6, [r7, #108]
+ ldr r6, [r7, #124]
vsri.32 q5, q6, #20
- str r3, [r7, #108]
+ str r3, [r7, #124]
eor r6, r6, fp
ror r5, r5, #16
vadd.i32 q9, q9, q1
add r9, r9, lr
ror r3, r6, #16
- ldr r6, [r7, #108]
+ ldr r6, [r7, #124]
vadd.i32 q10, q10, q5
- str r3, [r7, #92]
+ str r3, [r7, #108]
veor q4, q9, q3
add ip, ip, r6
- ldr r6, [r7, #88]
+ ldr r6, [r7, #104]
veor q6, q10, q2
eor r4, ip, r4
eor r1, r9, r1
vshl.i32 q3, q4, #8
mov r8, r6
- ldr r6, [r7, #104]
+ ldr r6, [r7, #120]
vshl.i32 q2, q6, #8
ror r4, r4, #20
add r6, r6, r3
vsri.32 q3, q4, #24
- str r6, [r7, #88]
+ str r6, [r7, #104]
eors r2, r2, r6
- ldr r6, [r7, #100]
+ ldr r6, [r7, #116]
vsri.32 q2, q6, #24
add r8, r8, r5
ror r2, r2, #20
@@ -251,42 +267,42 @@ CRYPTO_chacha_20_neon:
eor r0, r8, r0
vadd.i32 q15, q15, q2
mov r3, r6
- ldr r6, [r7, #96]
+ ldr r6, [r7, #112]
veor q6, q4, q1
ror r0, r0, #20
- str r3, [r7, #96]
+ str r3, [r7, #112]
veor q5, q15, q5
adds r6, r0, r6
- str r6, [r7, #104]
+ str r6, [r7, #120]
mov r6, r3
- ldr r3, [r7, #108]
+ ldr r3, [r7, #124]
vshl.i32 q8, q6, #7
add fp, fp, r2
eors r3, r3, r6
- ldr r6, [r7, #104]
+ ldr r6, [r7, #120]
vshl.i32 q1, q5, #7
ror r1, r1, #20
eors r5, r5, r6
vsri.32 q8, q6, #25
- ldr r6, [r7, #92]
+ ldr r6, [r7, #108]
ror r3, r3, #24
ror r5, r5, #24
vsri.32 q1, q5, #25
- str r5, [r7, #100]
+ str r5, [r7, #116]
eor r6, fp, r6
- ldr r5, [r7, #100]
+ ldr r5, [r7, #116]
add r10, r10, r1
add ip, r3, ip
vext.32 q8, q8, q8, #1
- str ip, [r7, #108]
+ str ip, [r7, #124]
add ip, r5, r8
- ldr r5, [r7, #88]
+ ldr r5, [r7, #104]
eor lr, r10, lr
ror r6, r6, #24
vext.32 q1, q1, q1, #1
add r8, r6, r5
vadd.i32 q9, q9, q8
- ldr r5, [r7, #108]
+ ldr r5, [r7, #124]
vext.32 q3, q3, q3, #3
vadd.i32 q10, q10, q1
ror lr, lr, #24
@@ -295,14 +311,14 @@ CRYPTO_chacha_20_neon:
add r9, r9, lr
eors r4, r4, r5
veor q3, q9, q3
- ldr r5, [r7, #96]
+ ldr r5, [r7, #112]
eor r1, r9, r1
ror r0, r0, #25
veor q2, q10, q2
adds r5, r0, r5
vext.32 q4, q4, q4, #2
- str r5, [r7, #96]
- ldr r5, [r7, #104]
+ str r5, [r7, #112]
+ ldr r5, [r7, #120]
ror r1, r1, #25
vrev32.16 q3, q3
eor r2, r8, r2
@@ -311,10 +327,10 @@ CRYPTO_chacha_20_neon:
vadd.i32 q4, q4, q3
ror r4, r4, #25
vrev32.16 q2, q2
- str r5, [r7, #84]
+ str r5, [r7, #100]
vadd.i32 q15, q15, q2
eors r3, r3, r5
- ldr r5, [r7, #96]
+ ldr r5, [r7, #112]
add fp, fp, r4
veor q8, q4, q8
ror r2, r2, #25
@@ -322,174 +338,182 @@ CRYPTO_chacha_20_neon:
eor lr, fp, lr
eors r6, r6, r5
ror r3, r3, #16
- ldr r5, [r7, #100]
+ ldr r5, [r7, #116]
add r10, r10, r2
- str r3, [r7, #104]
+ str r3, [r7, #120]
ror lr, lr, #16
- ldr r3, [r7, #104]
+ ldr r3, [r7, #120]
eor r5, r10, r5
vshl.i32 q5, q8, #12
add ip, lr, ip
vshl.i32 q6, q1, #12
- str ip, [r7, #88]
+ str ip, [r7, #104]
add ip, r3, r8
- str ip, [r7, #100]
- ldr r3, [r7, #108]
+ str ip, [r7, #116]
+ ldr r3, [r7, #124]
ror r5, r5, #16
vsri.32 q5, q8, #20
ror r6, r6, #16
add ip, r5, r3
- ldr r3, [r7, #88]
+ ldr r3, [r7, #104]
vsri.32 q6, q1, #20
add r9, r9, r6
eor r2, ip, r2
eors r4, r4, r3
- ldr r3, [r7, #100]
+ ldr r3, [r7, #116]
eor r0, r9, r0
vadd.i32 q9, q9, q5
ror r4, r4, #20
eors r1, r1, r3
vadd.i32 q10, q10, q6
ror r3, r2, #20
- str r3, [r7, #92]
- ldr r3, [r7, #96]
+ str r3, [r7, #108]
+ ldr r3, [r7, #112]
veor q3, q9, q3
ror r0, r0, #20
add r8, r4, fp
veor q2, q10, q2
add fp, r0, r3
- ldr r3, [r7, #84]
+ ldr r3, [r7, #100]
ror r1, r1, #20
mov r2, r8
vshl.i32 q8, q3, #8
- str r8, [r7, #80]
+ str r8, [r7, #96]
add r8, r1, r3
- ldr r3, [r7, #92]
+ ldr r3, [r7, #108]
vmov q1, q6 @ v4si
vshl.i32 q6, q2, #8
eor r6, fp, r6
add r10, r10, r3
- ldr r3, [r7, #104]
+ ldr r3, [r7, #120]
vsri.32 q8, q3, #24
eor lr, r2, lr
eor r3, r8, r3
ror r2, r6, #24
vsri.32 q6, q2, #24
eor r5, r10, r5
- str r2, [r7, #108]
+ str r2, [r7, #124]
ror r2, r3, #24
- ldr r3, [r7, #88]
+ ldr r3, [r7, #104]
vmov q3, q8 @ v4si
vadd.i32 q15, q15, q6
ror lr, lr, #24
vadd.i32 q8, q4, q8
ror r6, r5, #24
add r5, lr, r3
- ldr r3, [r7, #108]
+ ldr r3, [r7, #124]
veor q4, q8, q5
add ip, ip, r6
vmov q2, q6 @ v4si
add r9, r9, r3
veor q6, q15, q1
- ldr r3, [r7, #100]
+ ldr r3, [r7, #116]
vshl.i32 q1, q4, #7
- str r2, [r7, #96]
+ str r2, [r7, #112]
add r3, r3, r2
- str r3, [r7, #104]
+ str r3, [r7, #120]
vshl.i32 q5, q6, #7
eors r1, r1, r3
- ldr r3, [r7, #92]
+ ldr r3, [r7, #108]
vsri.32 q1, q4, #25
eors r4, r4, r5
eor r0, r9, r0
eor r2, ip, r3
vsri.32 q5, q6, #25
- ldr r3, [r7, #76]
+ ldr r3, [r7, #92]
ror r4, r4, #25
- str r6, [r7, #84]
+ str r6, [r7, #100]
ror r0, r0, #25
subs r3, r3, #1
- str r5, [r7, #88]
+ str r5, [r7, #104]
ror r1, r1, #25
ror r2, r2, #25
vext.32 q15, q15, q15, #2
- str r3, [r7, #76]
+ str r3, [r7, #92]
vext.32 q2, q2, q2, #1
vext.32 q8, q8, q8, #2
vext.32 q3, q3, q3, #1
vext.32 q5, q5, q5, #3
vext.32 q1, q1, q1, #3
bne .L3
- ldr r3, [r7, #68]
+ ldr r3, [r7, #80]
vadd.i32 q4, q12, q10
- str r9, [r7, #100]
+ str r9, [r7, #116]
mov r9, r10
mov r10, r8
- ldr r8, [r7, #80]
- str lr, [r7, #80]
+ ldr r8, [r7, #96]
+ str lr, [r7, #96]
mov lr, r5
- ldr r5, [r7, #40]
+ ldr r5, [r7, #56]
vadd.i32 q5, q13, q5
- ldr r6, [r7, #64]
+ ldr r6, [r7, #76]
vadd.i32 q15, q14, q15
add fp, fp, r5
- ldr r5, [r7, #36]
- str r4, [r7, #52]
+ ldr r5, [r7, #52]
+ str r4, [r7, #108]
vadd.i32 q7, q14, q8
- ldr r4, [r7, #96]
+ ldr r4, [r7, #112]
add r5, r10, r5
- str r3, [r7, #96]
+ str r3, [r7, #112]
vadd.i32 q2, q11, q2
ldr r3, [r6, #12] @ unaligned
vadd.i32 q6, q12, q9
- str r0, [r7, #76]
+ str r0, [r7, #92]
vadd.i32 q1, q13, q1
ldr r0, [r6] @ unaligned
vadd.i32 q11, q11, q0
- str r1, [r7, #92]
- str r2, [r7, #56]
+ str r1, [r7, #40]
+ str r2, [r7, #36]
vadd.i32 q3, q11, q3
ldr r1, [r6, #4] @ unaligned
vadd.i32 q11, q11, q0
ldr r2, [r6, #8] @ unaligned
- str r5, [r7, #88]
+ str r5, [r7, #104]
vadd.i32 q11, q11, q0
- ldr r5, [r7, #96]
- ldr r10, [r7, #68]
+ ldr r5, [r7, #112]
+ ldr r10, [r7, #80]
stmia r5!, {r0, r1, r2, r3}
mov r5, r10
- ldr r2, [r7, #72]
- ldr r1, [r7, #32]
- ldr r3, [r7, #48]
- vldr d20, [r2, #80]
- vldr d21, [r2, #88]
- add r9, r9, r1
+ ldr r0, [r7, #84]
+ ldr r2, [r7, #48]
+ ldr r3, [r7, #72]
+ vldr d20, [r0, #80]
+ vldr d21, [r0, #88]
+ add r9, r9, r2
veor q10, q10, q4
- ldr r1, [r7, #28]
- add r0, r8, r1
- str r0, [r7, #24]
- vstr d20, [r2, #80]
- vstr d21, [r2, #88]
- adds r0, r4, r3
- str r0, [r7, #20]
+ ldr r2, [r7, #44]
+ adds r1, r4, r3
+ str r1, [r7, #28]
+ add r2, r8, r2
+ str r2, [r7, #32]
+ vstr d20, [r0, #80]
+ vstr d21, [r0, #88]
ldmia r5!, {r0, r1, r2, r3}
- mov r5, r10
+ ldr r4, [r7, #96]
+ ldr r5, [r7, #64]
+ add r4, r4, r5
+ ldr r5, [r7, #124]
+ str r4, [r7, #96]
ldr r4, [r7, #60]
+ add r5, r5, r4
+ ldr r4, [r7, #88]
+ str r5, [r7, #24]
+ mov r5, r10
str r0, [r4] @ unaligned
- mov r4, r10
- ldr r0, [r7, #60]
- str r1, [r0, #4] @ unaligned
+ mov r0, r4
+ str r1, [r4, #4] @ unaligned
mov r8, r0
str r2, [r0, #8] @ unaligned
+ mov r4, r10
str r3, [r0, #12] @ unaligned
ldr r0, [r6, #16]! @ unaligned
ldr r1, [r6, #4] @ unaligned
ldr r2, [r6, #8] @ unaligned
ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #64]
+ ldr r6, [r7, #76]
stmia r5!, {r0, r1, r2, r3}
mov r5, r10
- ldr r3, [r7, #72]
+ ldr r3, [r7, #84]
vldr d20, [r3, #80]
vldr d21, [r3, #88]
veor q10, q10, q5
@@ -501,21 +525,22 @@ CRYPTO_chacha_20_neon:
str r1, [r8, #20] @ unaligned
str r2, [r8, #24] @ unaligned
str r3, [r8, #28] @ unaligned
+ mov r8, r4
ldr r0, [r6, #32]! @ unaligned
+ str r10, [r7, #124]
ldr r1, [r6, #4] @ unaligned
ldr r2, [r6, #8] @ unaligned
ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #64]
+ ldr r6, [r7, #76]
stmia r5!, {r0, r1, r2, r3}
mov r5, r10
- ldr r0, [r7, #72]
- vldr d16, [r0, #80]
- vldr d17, [r0, #88]
+ ldr r2, [r7, #84]
+ vldr d16, [r2, #80]
+ vldr d17, [r2, #88]
veor q15, q8, q15
- vstr d30, [r0, #80]
- vstr d31, [r0, #88]
+ vstr d30, [r2, #80]
+ vstr d31, [r2, #88]
ldmia r10!, {r0, r1, r2, r3}
- mov r10, r5
str r0, [r4, #32] @ unaligned
str r1, [r4, #36] @ unaligned
str r2, [r4, #40] @ unaligned
@@ -524,17 +549,18 @@ CRYPTO_chacha_20_neon:
ldr r1, [r6, #4] @ unaligned
ldr r2, [r6, #8] @ unaligned
ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #64]
+ ldr r6, [r7, #76]
stmia r5!, {r0, r1, r2, r3}
- mov r5, r10
- ldr r2, [r7, #72]
- vldr d18, [r2, #80]
- vldr d19, [r2, #88]
+ ldr r1, [r7, #84]
+ vldr d18, [r1, #80]
+ vldr d19, [r1, #88]
veor q9, q9, q2
- vstr d18, [r2, #80]
- vstr d19, [r2, #88]
+ vstr d18, [r1, #80]
+ vstr d19, [r1, #88]
+ ldr r3, [r7, #112]
+ ldr r5, [r7, #80]
+ mov r10, r3
ldmia r10!, {r0, r1, r2, r3}
- mov r10, r5
str r0, [r4, #48] @ unaligned
str r1, [r4, #52] @ unaligned
str r2, [r4, #56] @ unaligned
@@ -543,34 +569,38 @@ CRYPTO_chacha_20_neon:
ldr r1, [r6, #4] @ unaligned
ldr r2, [r6, #8] @ unaligned
ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #64]
+ ldr r6, [r7, #76]
stmia r5!, {r0, r1, r2, r3}
- mov r5, r10
- ldr r2, [r7, #72]
- vldr d18, [r2, #80]
- vldr d19, [r2, #88]
+ ldr r1, [r7, #84]
+ ldr r3, [r7, #112]
+ ldr r5, [r7, #80]
+ vldr d18, [r1, #80]
+ vldr d19, [r1, #88]
veor q9, q9, q6
- vstr d18, [r2, #80]
- vstr d19, [r2, #88]
+ mov r10, r3
+ str r5, [r7, #20]
+ vstr d18, [r1, #80]
+ vstr d19, [r1, #88]
ldmia r10!, {r0, r1, r2, r3}
- mov r10, r5
- str r0, [r4, #64] @ unaligned
str r1, [r4, #68] @ unaligned
str r2, [r4, #72] @ unaligned
str r3, [r4, #76] @ unaligned
+ str r0, [r4, #64] @ unaligned
ldr r0, [r6, #80]! @ unaligned
ldr r1, [r6, #4] @ unaligned
ldr r2, [r6, #8] @ unaligned
ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #64]
+ ldr r6, [r7, #76]
stmia r5!, {r0, r1, r2, r3}
- mov r5, r10
- ldr r2, [r7, #72]
- vldr d18, [r2, #80]
- vldr d19, [r2, #88]
+ ldr r1, [r7, #84]
+ ldr r3, [r7, #20]
+ ldr r5, [r7, #80]
+ vldr d18, [r1, #80]
+ vldr d19, [r1, #88]
veor q1, q9, q1
- vstr d2, [r2, #80]
- vstr d3, [r2, #88]
+ mov r10, r3
+ vstr d2, [r1, #80]
+ vstr d3, [r1, #88]
ldmia r10!, {r0, r1, r2, r3}
mov r10, r5
str r0, [r4, #80] @ unaligned
@@ -581,17 +611,16 @@ CRYPTO_chacha_20_neon:
ldr r1, [r6, #4] @ unaligned
ldr r2, [r6, #8] @ unaligned
ldr r3, [r6, #12] @ unaligned
- ldr r6, [r7, #64]
+ ldr r6, [r7, #76]
stmia r5!, {r0, r1, r2, r3}
mov r5, r10
- ldr r3, [r7, #72]
+ ldr r3, [r7, #84]
vldr d16, [r3, #80]
vldr d17, [r3, #88]
veor q8, q8, q7
vstr d16, [r3, #80]
vstr d17, [r3, #88]
ldmia r10!, {r0, r1, r2, r3}
- mov r10, r5
str r0, [r4, #96] @ unaligned
str r1, [r4, #100] @ unaligned
str r2, [r4, #104] @ unaligned
@@ -600,140 +629,116 @@ CRYPTO_chacha_20_neon:
ldr r1, [r6, #4] @ unaligned
ldr r2, [r6, #8] @ unaligned
ldr r3, [r6, #12] @ unaligned
- stmia r5!, {r0, r1, r2, r3}
- mov r5, r10
- ldr r0, [r7, #72]
- ldr r6, [r7, #44]
- vldr d16, [r0, #80]
- vldr d17, [r0, #88]
+ mov r6, r5
+ stmia r6!, {r0, r1, r2, r3}
+ ldr r3, [r7, #84]
+ vldr d16, [r3, #80]
+ vldr d17, [r3, #88]
veor q8, q8, q3
- vstr d16, [r0, #80]
- vstr d17, [r0, #88]
+ vstr d16, [r3, #80]
+ vstr d17, [r3, #88]
ldmia r5!, {r0, r1, r2, r3}
- mov r5, r4
- mov r8, r5
str r1, [r4, #116] @ unaligned
- ldr r1, [r7, #64]
+ ldr r1, [r7, #76]
str r0, [r4, #112] @ unaligned
- mov r0, r5
str r2, [r4, #120] @ unaligned
str r3, [r4, #124] @ unaligned
ldr r3, [r1, #128]
- ldr r2, [r7, #88]
+ ldr r2, [r7, #104]
eor r3, fp, r3
str r3, [r4, #128]
ldr r3, [r1, #132]
- mov r4, r1
- mov r1, r5
eors r2, r2, r3
str r2, [r8, #132]
- ldr r3, [r4, #136]
- ldr r2, [r7, #24]
+ ldr r3, [r1, #136]
+ ldr r5, [r7, #68]
+ ldr r6, [r7, #32]
eor r3, r9, r3
- str r3, [r5, #136]
- ldr r3, [r4, #140]
- eors r3, r3, r2
- str r3, [r5, #140]
- mov r5, r4
- ldr r3, [r6]
- ldr r2, [r4, #144]
- ldr r4, [r7, #52]
- add r4, r4, r3
- eors r2, r2, r4
- mov r4, r1
- str r2, [r1, #144]
- ldr r1, [r7, #76]
- ldr r2, [r6, #4]
- ldr r3, [r5, #148]
- mov r8, r1
- add r8, r8, r2
- mov r2, r8
- eors r3, r3, r2
- str r3, [r0, #148]
- mov r0, r4
- ldr r2, [r6, #8]
- ldr r1, [r7, #92]
- ldr r3, [r5, #152]
- mov r8, r1
- add r8, r8, r2
- ldr r1, [r7, #56]
- mov r2, r8
- eors r3, r3, r2
+ str r3, [r4, #136]
+ ldr r3, [r1, #140]
+ ldr r0, [r7, #92]
+ eors r3, r3, r6
+ ldr r6, [r7, #108]
+ str r3, [r4, #140]
+ ldr r3, [r5]
+ ldr r2, [r1, #144]
+ add r6, r6, r3
+ eors r2, r2, r6
+ str r2, [r4, #144]
+ ldr r2, [r5, #4]
+ ldr r3, [r1, #148]
+ add r0, r0, r2
+ ldr r6, [r7, #36]
+ eors r3, r3, r0
+ ldr r0, [r7, #40]
+ str r3, [r4, #148]
+ ldr r2, [r5, #8]
+ ldr r3, [r1, #152]
+ add r0, r0, r2
+ eors r3, r3, r0
str r3, [r4, #152]
- mov r8, r6
- ldr r2, [r6, #12]
- mov r4, r5
- ldr r3, [r5, #156]
- add r1, r1, r2
- eors r3, r3, r1
- str r3, [r0, #156]
- ldr r2, [r6, #16]
+ ldr r2, [r5, #12]
+ mov r0, r4
+ ldr r3, [r1, #156]
+ mov r4, r1
+ add r6, r6, r2
mov r1, r0
- ldr r3, [r5, #160]
+ eors r3, r3, r6
+ str r3, [r0, #156]
+ ldr r2, [r5, #16]
+ ldr r3, [r4, #160]
add ip, ip, r2
eor r3, ip, r3
- str r3, [r0, #160]
- ldr r2, [r6, #20]
- mov ip, r0
- ldr r3, [r5, #164]
+ str r3, [r1, #160]
+ ldr r2, [r5, #20]
+ ldr r3, [r4, #164]
add lr, lr, r2
- ldr r2, [r7, #100]
+ ldr r2, [r7, #116]
eor r3, lr, r3
str r3, [r1, #164]
- ldr r6, [r6, #24]
+ ldr r6, [r5, #24]
+ mov lr, r4
ldr r3, [r4, #168]
add r2, r2, r6
+ mov r6, r4
eors r3, r3, r2
- ldr r2, [r7, #104]
- str r3, [r0, #168]
- ldr r5, [r8, #28]
+ str r3, [r1, #168]
+ ldr r5, [r5, #28]
+ mov r2, r1
ldr r3, [r4, #172]
- add r2, r2, r5
- mov r5, r4
- eors r3, r3, r2
- mov r2, r0
- str r3, [r0, #172]
- ldr r3, [r7, #48]
+ ldr r0, [r7, #120]
+ add r0, r0, r5
+ ldr r5, [r7, #24]
+ eors r3, r3, r0
+ str r3, [r1, #172]
+ ldr r3, [r7, #72]
ldr r4, [r4, #176]
- ldr r0, [r7, #20]
+ ldr r1, [r7, #28]
+ eors r4, r4, r1
adds r1, r3, #3
- ldr r3, [r7, #84]
- eors r4, r4, r0
str r4, [r2, #176]
- ldr r0, [r5, #180]
- mov r4, r2
- str r1, [r7, #48]
+ ldr r3, [r7, #100]
+ ldr r0, [lr, #180]
+ str r1, [r7, #72]
eors r3, r3, r0
mov r0, r3
- ldr r3, [r7, #232]
+ mov r3, r2
str r0, [r2, #180]
- ldr r1, [r3]
- ldr r3, [r5, #184]
- ldr r2, [r7, #80]
- add r2, r2, r1
- mov r1, r5
- eors r3, r3, r2
- str r3, [ip, #184]
- ldr r3, [r7, #232]
+ adds r3, r3, #192
+ ldr r1, [lr, #184]
+ ldr r2, [r7, #96]
+ eors r1, r1, r2
+ str r1, [r3, #-8]
+ ldr r2, [lr, #188]
+ mov r1, r6
adds r1, r1, #192
- str r1, [r7, #64]
- ldr r1, [r7, #108]
- ldr r2, [r3, #4]
- ldr r3, [r5, #188]
- add r1, r1, r2
- mov r2, r1
- eors r2, r2, r3
- str r2, [ip, #188]
- mov r3, r4
+ str r1, [r7, #76]
+ eors r2, r2, r5
+ str r2, [r3, #-4]
ldr r2, [r7, #16]
- adds r3, r3, #192
- str r3, [r7, #60]
+ str r3, [r7, #88]
cmp r2, r3
- beq .L85
- ldr r3, [r7, #232]
- ldmia r3, {r1, r2}
- b .L4
-.L85:
+ bne .L4
ldr r3, [r7, #12]
ldr r2, [r7, #4]
add r3, r3, r2
@@ -749,16 +754,14 @@ CRYPTO_chacha_20_neon:
rsb fp, fp, r1
lsrs fp, fp, #6
beq .L6
- ldr r6, [r7, #72]
ldr r5, [r7, #12]
ldr r4, [r7, #16]
- mov r3, r6
- adds r3, r3, #80
- vldr d30, .L95
- vldr d31, .L95+8
- mov lr, r3
- str fp, [r7, #104]
- str fp, [r7, #108]
+ ldr r6, [r7, #84]
+ ldr lr, [r7, #80]
+ vldr d30, .L94
+ vldr d31, .L94+8
+ str fp, [r7, #120]
+ str fp, [r7, #124]
.L8:
vmov q2, q11 @ v4si
movs r3, #10
@@ -883,22 +886,22 @@ CRYPTO_chacha_20_neon:
str r0, [r4, #-16] @ unaligned
str r1, [r4, #-12] @ unaligned
str r3, [r10, #12] @ unaligned
- ldr r3, [r7, #108]
+ ldr r3, [r7, #124]
str r2, [r10, #8] @ unaligned
cmp r3, #1
- beq .L88
+ beq .L87
movs r3, #1
- str r3, [r7, #108]
+ str r3, [r7, #124]
b .L8
-.L96:
- .align 3
.L95:
+ .align 3
+.L94:
.word 1
.word 0
.word 0
.word 0
-.L88:
- ldr fp, [r7, #104]
+.L87:
+ ldr fp, [r7, #120]
ldr r3, [r7, #12]
lsl fp, fp, #6
add r3, r3, fp
@@ -958,9 +961,9 @@ CRYPTO_chacha_20_neon:
bne .L10
cmp r5, #15
mov r9, r5
- bhi .L89
+ bhi .L88
vadd.i32 q12, q12, q10
- ldr r3, [r7, #72]
+ ldr r3, [r7, #84]
vst1.64 {d24-d25}, [r3:128]
.L14:
ldr r3, [r7, #8]
@@ -997,7 +1000,7 @@ CRYPTO_chacha_20_neon:
movcs r1, ip
cmp r1, #0
beq .L17
- ldr r5, [r7, #72]
+ ldr r5, [r7, #84]
cmp r1, #1
ldrb r0, [r0] @ zero_extendqisi2
add r3, r2, #1
@@ -1132,7 +1135,7 @@ CRYPTO_chacha_20_neon:
ldr r5, [r7, #16]
cmp r6, #1
add r0, r1, r2
- ldr r1, [r7, #72]
+ ldr r1, [r7, #84]
add r1, r1, r2
vld1.64 {d18-d19}, [r0:64]
add r2, r2, r5
@@ -1170,7 +1173,7 @@ CRYPTO_chacha_20_neon:
add r3, r3, lr
beq .L1
.L19:
- ldr r4, [r7, #72]
+ ldr r4, [r7, #84]
adds r2, r3, #1
ldr r1, [r7, #12]
cmp r2, r9
@@ -1285,7 +1288,7 @@ CRYPTO_chacha_20_neon:
eor r1, r1, r0
strb r1, [r5, r2]
bls .L1
- ldr r2, [r7, #72]
+ ldr r2, [r7, #84]
ldrb r1, [r2, r3] @ zero_extendqisi2
ldr r2, [r7, #12]
ldrb r2, [r2, r3] @ zero_extendqisi2
@@ -1293,26 +1296,23 @@ CRYPTO_chacha_20_neon:
ldr r1, [r7, #16]
strb r2, [r1, r3]
.L1:
- adds r7, r7, #132
+ adds r7, r7, #156
mov sp, r7
@ sp needed
vldm sp!, {d8-d15}
pop {r4, r5, r6, r7, r8, r9, r10, fp, pc}
-.L89:
- ldr r4, [r7, #12]
+.L88:
+ ldr r5, [r7, #12]
vadd.i32 q12, q12, q10
- ldr r5, [r7, #72]
+ ldr r4, [r7, #80]
cmp r9, #31
- ldr r0, [r4] @ unaligned
- add r6, r5, #80
- ldr r1, [r4, #4] @ unaligned
- ldr r2, [r4, #8] @ unaligned
- mov r5, r6
- ldr r3, [r4, #12] @ unaligned
- mov r4, r6
- str r6, [r7, #68]
+ ldr r0, [r5] @ unaligned
+ ldr r1, [r5, #4] @ unaligned
+ mov r6, r4
+ ldr r2, [r5, #8] @ unaligned
+ ldr r3, [r5, #12] @ unaligned
stmia r6!, {r0, r1, r2, r3}
- ldr r2, [r7, #72]
+ ldr r2, [r7, #84]
ldr r6, [r7, #16]
vldr d18, [r2, #80]
vldr d19, [r2, #88]
@@ -1325,9 +1325,9 @@ CRYPTO_chacha_20_neon:
str r0, [r6] @ unaligned
str r2, [r6, #8] @ unaligned
str r3, [r6, #12] @ unaligned
- bhi .L90
+ bhi .L89
vadd.i32 q13, q13, q15
- ldr r3, [r7, #72]
+ ldr r3, [r7, #84]
vstr d26, [r3, #16]
vstr d27, [r3, #24]
b .L14
@@ -1336,7 +1336,7 @@ CRYPTO_chacha_20_neon:
ldr r2, [r7, #12]
add r2, r2, r9
mov r5, r2
- ldr r2, [r7, #72]
+ ldr r2, [r7, #84]
add r2, r2, r3
mov r3, r2
.L24:
@@ -1346,7 +1346,7 @@ CRYPTO_chacha_20_neon:
eor r2, r2, r1
strb r2, [r4], #1
bne .L24
- adds r7, r7, #132
+ adds r7, r7, #156
mov sp, r7
@ sp needed
vldm sp!, {d8-d15}
@@ -1354,20 +1354,20 @@ CRYPTO_chacha_20_neon:
.L26:
str fp, [r7, #16]
b .L2
-.L90:
- ldr r3, [r7, #12]
+.L89:
+ mov r3, r5
+ ldr r4, [r7, #80]
+ ldr r0, [r3, #16]! @ unaligned
add lr, r1, #16
- mov r4, r5
- mov r6, r5
mov r5, r1
vadd.i32 q13, q13, q15
- ldr r0, [r3, #16]! @ unaligned
+ mov r6, r4
cmp r9, #47
ldr r1, [r3, #4] @ unaligned
ldr r2, [r3, #8] @ unaligned
ldr r3, [r3, #12] @ unaligned
stmia r6!, {r0, r1, r2, r3}
- ldr r2, [r7, #72]
+ ldr r2, [r7, #84]
vldr d18, [r2, #80]
vldr d19, [r2, #88]
veor q13, q9, q13
@@ -1378,18 +1378,18 @@ CRYPTO_chacha_20_neon:
str r1, [lr, #4] @ unaligned
str r2, [lr, #8] @ unaligned
str r3, [lr, #12] @ unaligned
- bhi .L91
+ bhi .L90
vadd.i32 q8, q14, q8
- ldr r3, [r7, #72]
+ ldr r3, [r7, #84]
vstr d16, [r3, #32]
vstr d17, [r3, #40]
b .L14
-.L91:
+.L90:
ldr r3, [r7, #12]
add lr, r5, #32
- ldr r4, [r7, #68]
+ ldr r4, [r7, #80]
vadd.i32 q8, q14, q8
- ldr r5, [r7, #72]
+ ldr r5, [r7, #84]
vadd.i32 q11, q11, q3
ldr r0, [r3, #32]! @ unaligned
mov r6, r4
diff --git a/src/crypto/chacha/chacha_vec_arm_generate.go b/src/crypto/chacha/chacha_vec_arm_generate.go
new file mode 100644
index 0000000..d681e8a
--- /dev/null
+++ b/src/crypto/chacha/chacha_vec_arm_generate.go
@@ -0,0 +1,148 @@
+// 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.
+
+// This package generates chacha_vec_arm.S from chacha_vec.c.
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+const defaultCompiler = "/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"
+
+func main() {
+ compiler := defaultCompiler
+ if len(os.Args) > 1 {
+ compiler = os.Args[1]
+ }
+
+ args := []string{
+ "-O3",
+ "-mcpu=cortex-a8",
+ "-mfpu=neon",
+ "-fpic",
+ "-DASM_GEN",
+ "-I", "../../include",
+ "-S", "chacha_vec.c",
+ "-o", "-",
+ }
+
+ output, err := os.OpenFile("chacha_vec_arm.S", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
+ if err != nil {
+ panic(err)
+ }
+ defer output.Close()
+
+ output.WriteString(preamble)
+ output.WriteString(compiler)
+ output.WriteString(" ")
+ output.WriteString(strings.Join(args, " "))
+ output.WriteString("\n\n#if !defined(OPENSSL_NO_ASM)\n\n")
+
+ cmd := exec.Command(compiler, args...)
+ cmd.Stderr = os.Stderr
+ asm, err := cmd.StdoutPipe()
+ if err != nil {
+ panic(err)
+ }
+ if err := cmd.Start(); err != nil {
+ panic(err)
+ }
+
+ attr28 := []byte(".eabi_attribute 28,")
+ globalDirective := []byte(".global\t")
+ newLine := []byte("\n")
+ attr28Handled := false
+
+ scanner := bufio.NewScanner(asm)
+ for scanner.Scan() {
+ line := scanner.Bytes()
+
+ if bytes.Contains(line, attr28) {
+ output.WriteString(attr28Block)
+ attr28Handled = true
+ continue
+ }
+
+ output.Write(line)
+ output.Write(newLine)
+
+ if i := bytes.Index(line, globalDirective); i >= 0 {
+ output.Write(line[:i])
+ output.WriteString(".hidden\t")
+ output.Write(line[i+len(globalDirective):])
+ output.Write(newLine)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ panic(err)
+ }
+
+ if !attr28Handled {
+ panic("EABI attribute 28 not seen in processing")
+ }
+
+ if err := cmd.Wait(); err != nil {
+ panic(err)
+ }
+
+ output.WriteString(trailer)
+}
+
+const preamble = `# 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.
+
+# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
+# needed to support switching on NEON code at runtime. If the whole of OpenSSL
+# were to be compiled with the needed flags to build chacha_vec.c, then it
+# wouldn't be possible to run on non-NEON systems.
+#
+# This file was generated by chacha_vec_arm_generate.go using the following
+# compiler command:
+#
+# `
+
+const attr28Block = `
+# EABI attribute 28 sets whether VFP register arguments were used to build this
+# file. If object files are inconsistent on this point, the linker will refuse
+# to link them. Thus we report whatever the compiler expects since we don't use
+# VFP arguments.
+
+#if defined(__ARM_PCS_VFP)
+ .eabi_attribute 28, 1
+#else
+ .eabi_attribute 28, 0
+#endif
+
+`
+
+const trailer = `
+#endif /* !OPENSSL_NO_ASM */
+`
diff --git a/src/crypto/cipher/CMakeLists.txt b/src/crypto/cipher/CMakeLists.txt
index bb62b72..f428e25 100644
--- a/src/crypto/cipher/CMakeLists.txt
+++ b/src/crypto/cipher/CMakeLists.txt
@@ -6,7 +6,6 @@ add_library(
OBJECT
cipher.c
- cipher_error.c
derive_key.c
aead.c
@@ -31,7 +30,8 @@ add_executable(
add_executable(
aead_test
- aead_test.c
+ aead_test.cc
+ $<TARGET_OBJECTS:test_support>
)
target_link_libraries(cipher_test crypto)
diff --git a/src/crypto/cipher/aead.c b/src/crypto/cipher/aead.c
index 263e398..20d699d 100644
--- a/src/crypto/cipher/aead.c
+++ b/src/crypto/cipher/aead.c
@@ -33,12 +33,40 @@ size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead) { return aead->max_tag_len; }
int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
const uint8_t *key, size_t key_len, size_t tag_len,
ENGINE *impl) {
- ctx->aead = aead;
+ if (!aead->init) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_init, CIPHER_R_NO_DIRECTION_SET);
+ ctx->aead = NULL;
+ return 0;
+ }
+ return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, tag_len,
+ evp_aead_open);
+}
+
+int EVP_AEAD_CTX_init_with_direction(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len,
+ enum evp_aead_direction_t dir) {
if (key_len != aead->key_len) {
- OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_init, CIPHER_R_UNSUPPORTED_KEY_SIZE);
+ OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_init_with_direction,
+ CIPHER_R_UNSUPPORTED_KEY_SIZE);
+ ctx->aead = NULL;
return 0;
}
- return aead->init(ctx, key, key_len, tag_len);
+
+ ctx->aead = aead;
+
+ int ok;
+ if (aead->init) {
+ ok = aead->init(ctx, key, key_len, tag_len);
+ } else {
+ ok = aead->init_with_direction(ctx, key, key_len, tag_len, dir);
+ }
+
+ if (!ok) {
+ ctx->aead = NULL;
+ }
+
+ return ok;
}
void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) {
@@ -117,3 +145,11 @@ error:
*out_len = 0;
return 0;
}
+
+int EVP_AEAD_CTX_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) {
+ if (ctx->aead->get_rc4_state == NULL) {
+ return 0;
+ }
+
+ return ctx->aead->get_rc4_state(ctx, out_key);
+}
diff --git a/src/crypto/cipher/aead_test.c b/src/crypto/cipher/aead_test.c
deleted file mode 100644
index 310c90c..0000000
--- a/src/crypto/cipher/aead_test.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/* 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 <stdlib.h>
-#include <string.h>
-
-#include <openssl/aead.h>
-#include <openssl/bio.h>
-#include <openssl/crypto.h>
-#include <openssl/err.h>
-
-/* This program tests an AEAD against a series of test vectors from a file. The
- * test vector file consists of key-value lines where the key and value are
- * separated by a colon and optional whitespace. The keys are listed in
- * |NAMES|, below. The values are hex-encoded data.
- *
- * After a number of key-value lines, a blank line or EOF indicates the end of
- * the test case.
- *
- * For example, here's a valid test case:
- *
- * KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
- * NONCE: 978105dfce667bf4
- * IN: 6a4583908d
- * AD: b654574932
- * CT: 5294265a60
- * TAG: 1d45758621762e061368e68868e2f929
- */
-
-#define BUF_MAX 512
-
-/* These are the different types of line that are found in the input file. */
-enum {
- KEY = 0, /* hex encoded key. */
- NONCE, /* hex encoded nonce. */
- IN, /* hex encoded plaintext. */
- AD, /* hex encoded additional data. */
- CT, /* hex encoded ciphertext (not including the authenticator,
- which is next). */
- TAG, /* hex encoded authenticator. */
- NO_SEAL, /* non-zero length if seal(IN) is not expected to be CT+TAG,
- however open(CT+TAG) should still be IN. */
- FAILS, /* non-zero length if open(CT+TAG) is expected to fail. */
- NUM_TYPES,
-};
-
-static const char NAMES[8][NUM_TYPES] = {
- "KEY", "NONCE", "IN", "AD", "CT", "TAG", "NO_SEAL", "FAILS",
-};
-
-static unsigned char hex_digit(char h) {
- if (h >= '0' && h <= '9') {
- return h - '0';
- } else if (h >= 'a' && h <= 'f') {
- return h - 'a' + 10;
- } else if (h >= 'A' && h <= 'F') {
- return h - 'A' + 10;
- } else {
- return 16;
- }
-}
-
-static int run_test_case(const EVP_AEAD *aead,
- uint8_t bufs[NUM_TYPES][BUF_MAX],
- const unsigned int lengths[NUM_TYPES],
- unsigned int line_no) {
- EVP_AEAD_CTX ctx;
- size_t ciphertext_len, plaintext_len;
- uint8_t out[BUF_MAX + EVP_AEAD_MAX_OVERHEAD + 1];
- /* Note: When calling |EVP_AEAD_CTX_open|, the "stateful" AEADs require
- * |max_out| be at least |in_len| despite the final output always being
- * smaller by at least tag length. */
- uint8_t out2[sizeof(out)];
-
- if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
- NULL)) {
- fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
- return 0;
- }
-
- if (!lengths[NO_SEAL]) {
- if (!EVP_AEAD_CTX_seal(&ctx, out, &ciphertext_len, sizeof(out), bufs[NONCE],
- lengths[NONCE], bufs[IN], lengths[IN], bufs[AD],
- lengths[AD])) {
- fprintf(stderr, "Failed to run AEAD on line %u\n", line_no);
- return 0;
- }
-
- if (ciphertext_len != lengths[CT] + lengths[TAG]) {
- fprintf(stderr, "Bad output length on line %u: %u vs %u\n", line_no,
- (unsigned)ciphertext_len, (unsigned)(lengths[CT] + lengths[TAG]));
- return 0;
- }
-
- if (memcmp(out, bufs[CT], lengths[CT]) != 0) {
- fprintf(stderr, "Bad output on line %u\n", line_no);
- return 0;
- }
-
- if (memcmp(out + lengths[CT], bufs[TAG], lengths[TAG]) != 0) {
- fprintf(stderr, "Bad tag on line %u\n", line_no);
- return 0;
- }
- } else {
- memcpy(out, bufs[CT], lengths[CT]);
- memcpy(out + lengths[CT], bufs[TAG], lengths[TAG]);
- ciphertext_len = lengths[CT] + lengths[TAG];
- }
-
- /* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
- * reset after each operation. */
- EVP_AEAD_CTX_cleanup(&ctx);
- if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
- NULL)) {
- fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
- return 0;
- }
-
- int ret = EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, sizeof(out2),
- bufs[NONCE], lengths[NONCE], out, ciphertext_len,
- bufs[AD], lengths[AD]);
- if (lengths[FAILS]) {
- if (ret) {
- fprintf(stderr, "Decrypted bad data on line %u\n", line_no);
- return 0;
- }
- ERR_clear_error();
- } else {
- if (!ret) {
- fprintf(stderr, "Failed to decrypt on line %u\n", line_no);
- return 0;
- }
-
- if (plaintext_len != lengths[IN]) {
- fprintf(stderr, "Bad decrypt on line %u: %u\n", line_no,
- (unsigned)ciphertext_len);
- return 0;
- }
-
- /* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
- * reset after each operation. */
- EVP_AEAD_CTX_cleanup(&ctx);
- if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
- NULL)) {
- fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
- return 0;
- }
-
- /* Garbage at the end isn't ignored. */
- out[ciphertext_len] = 0;
- if (EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, sizeof(out2),
- bufs[NONCE], lengths[NONCE], out, ciphertext_len + 1,
- bufs[AD], lengths[AD])) {
- fprintf(stderr, "Decrypted bad data on line %u\n", line_no);
- return 0;
- }
- ERR_clear_error();
-
- /* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
- * reset after each operation. */
- EVP_AEAD_CTX_cleanup(&ctx);
- if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
- NULL)) {
- fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
- return 0;
- }
-
- /* Verify integrity is checked. */
- out[0] ^= 0x80;
- if (EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, sizeof(out2), bufs[NONCE],
- lengths[NONCE], out, ciphertext_len, bufs[AD],
- lengths[AD])) {
- fprintf(stderr, "Decrypted bad data on line %u\n", line_no);
- return 0;
- }
- ERR_clear_error();
- }
-
- EVP_AEAD_CTX_cleanup(&ctx);
- return 1;
-}
-
-int main(int argc, char **argv) {
- FILE *f;
- const EVP_AEAD *aead = NULL;
- unsigned int line_no = 0, num_tests = 0, j;
-
- unsigned char bufs[NUM_TYPES][BUF_MAX];
- unsigned int lengths[NUM_TYPES];
-
- CRYPTO_library_init();
- ERR_load_crypto_strings();
-
- if (argc != 3) {
- fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
- return 1;
- }
-
- if (strcmp(argv[1], "aes-128-gcm") == 0) {
- aead = EVP_aead_aes_128_gcm();
- } else if (strcmp(argv[1], "aes-256-gcm") == 0) {
- aead = EVP_aead_aes_256_gcm();
- } else if (strcmp(argv[1], "chacha20-poly1305") == 0) {
- aead = EVP_aead_chacha20_poly1305();
- } else if (strcmp(argv[1], "rc4-md5-tls") == 0) {
- aead = EVP_aead_rc4_md5_tls();
- } else if (strcmp(argv[1], "rc4-sha1-tls") == 0) {
- aead = EVP_aead_rc4_sha1_tls();
- } else if (strcmp(argv[1], "aes-128-cbc-sha1-tls") == 0) {
- aead = EVP_aead_aes_128_cbc_sha1_tls();
- } else if (strcmp(argv[1], "aes-128-cbc-sha1-tls-implicit-iv") == 0) {
- aead = EVP_aead_aes_128_cbc_sha1_tls_implicit_iv();
- } else if (strcmp(argv[1], "aes-128-cbc-sha256-tls") == 0) {
- aead = EVP_aead_aes_128_cbc_sha256_tls();
- } else if (strcmp(argv[1], "aes-256-cbc-sha1-tls") == 0) {
- aead = EVP_aead_aes_256_cbc_sha1_tls();
- } else if (strcmp(argv[1], "aes-256-cbc-sha1-tls-implicit-iv") == 0) {
- aead = EVP_aead_aes_256_cbc_sha1_tls_implicit_iv();
- } else if (strcmp(argv[1], "aes-256-cbc-sha256-tls") == 0) {
- aead = EVP_aead_aes_256_cbc_sha256_tls();
- } else if (strcmp(argv[1], "aes-256-cbc-sha384-tls") == 0) {
- aead = EVP_aead_aes_256_cbc_sha384_tls();
- } else if (strcmp(argv[1], "des-ede3-cbc-sha1-tls") == 0) {
- aead = EVP_aead_des_ede3_cbc_sha1_tls();
- } else if (strcmp(argv[1], "des-ede3-cbc-sha1-tls-implicit-iv") == 0) {
- aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv();
- } else if (strcmp(argv[1], "rc4-md5-ssl3") == 0) {
- aead = EVP_aead_rc4_md5_ssl3();
- } else if (strcmp(argv[1], "rc4-sha1-ssl3") == 0) {
- aead = EVP_aead_rc4_sha1_ssl3();
- } else if (strcmp(argv[1], "aes-128-cbc-sha1-ssl3") == 0) {
- aead = EVP_aead_aes_128_cbc_sha1_ssl3();
- } else if (strcmp(argv[1], "aes-256-cbc-sha1-ssl3") == 0) {
- aead = EVP_aead_aes_256_cbc_sha1_ssl3();
- } else if (strcmp(argv[1], "des-ede3-cbc-sha1-ssl3") == 0) {
- aead = EVP_aead_des_ede3_cbc_sha1_ssl3();
- } else if (strcmp(argv[1], "aes-128-key-wrap") == 0) {
- aead = EVP_aead_aes_128_key_wrap();
- } else if (strcmp(argv[1], "aes-256-key-wrap") == 0) {
- aead = EVP_aead_aes_256_key_wrap();
- } else {
- fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
- return 2;
- }
-
- f = fopen(argv[2], "r");
- if (f == NULL) {
- perror("failed to open input");
- return 1;
- }
-
- for (j = 0; j < NUM_TYPES; j++) {
- lengths[j] = 0;
- }
-
- for (;;) {
- char line[4096];
- unsigned int i, type_len = 0;
-
- unsigned char *buf = NULL;
- unsigned int *buf_len = NULL;
-
- if (!fgets(line, sizeof(line), f)) {
- line[0] = 0;
- }
-
- line_no++;
- if (line[0] == '#') {
- continue;
- }
-
- if (line[0] == '\n' || line[0] == 0) {
- /* Run a test, if possible. */
- char any_values_set = 0;
- for (j = 0; j < NUM_TYPES; j++) {
- if (lengths[j] != 0) {
- any_values_set = 1;
- break;
- }
- }
-
- if (any_values_set) {
- if (!run_test_case(aead, bufs, lengths, line_no)) {
- BIO_print_errors_fp(stderr);
- return 4;
- }
-
- for (j = 0; j < NUM_TYPES; j++) {
- lengths[j] = 0;
- }
-
- num_tests++;
- }
-
- if (line[0] == 0) {
- break;
- }
- continue;
- }
-
- /* Each line looks like:
- * TYPE: 0123abc
- * Where "TYPE" is the type of the data on the line,
- * e.g. "KEY". */
- for (i = 0; line[i] != 0 && line[i] != '\n'; i++) {
- if (line[i] == ':') {
- type_len = i;
- break;
- }
- }
- i++;
-
- if (type_len == 0) {
- fprintf(stderr, "Parse error on line %u\n", line_no);
- return 3;
- }
-
- /* After the colon, there's optional whitespace. */
- for (; line[i] != 0 && line[i] != '\n'; i++) {
- if (line[i] != ' ' && line[i] != '\t') {
- break;
- }
- }
-
- line[type_len] = 0;
- for (j = 0; j < NUM_TYPES; j++) {
- if (strcmp(line, NAMES[j]) != 0) {
- continue;
- }
- if (lengths[j] != 0) {
- fprintf(stderr, "Duplicate value on line %u\n", line_no);
- return 3;
- }
- buf = bufs[j];
- buf_len = &lengths[j];
- }
-
- if (buf == NULL) {
- fprintf(stderr, "Unknown line type on line %u\n", line_no);
- return 3;
- }
-
- j = 0;
- for (; line[i] != 0 && line[i] != '\n'; i++) {
- unsigned char v, v2;
- v = hex_digit(line[i++]);
- if (line[i] == 0 || line[i] == '\n') {
- fprintf(stderr, "Odd-length hex data on line %u\n", line_no);
- return 3;
- }
- v2 = hex_digit(line[i]);
- if (v > 15 || v2 > 15) {
- fprintf(stderr, "Invalid hex char on line %u\n", line_no);
- return 3;
- }
- v <<= 4;
- v |= v2;
-
- if (j == BUF_MAX) {
- fprintf(stderr, "Too much hex data on line %u (max is %u bytes)\n",
- line_no, (unsigned)BUF_MAX);
- return 3;
- }
- buf[j++] = v;
- *buf_len = *buf_len + 1;
- }
- }
-
- printf("Completed %u test cases\n", num_tests);
- printf("PASS\n");
- fclose(f);
-
- return 0;
-}
diff --git a/src/crypto/cipher/aead_test.cc b/src/crypto/cipher/aead_test.cc
new file mode 100644
index 0000000..e4b75d6
--- /dev/null
+++ b/src/crypto/cipher/aead_test.cc
@@ -0,0 +1,276 @@
+/* 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 <string.h>
+
+#include <vector>
+
+#include <openssl/aead.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+#include "../test/file_test.h"
+#include "../test/stl_compat.h"
+
+
+// This program tests an AEAD against a series of test vectors from a file,
+// using the FileTest format. As an example, here's a valid test case:
+//
+// KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
+// NONCE: 978105dfce667bf4
+// IN: 6a4583908d
+// AD: b654574932
+// CT: 5294265a60
+// TAG: 1d45758621762e061368e68868e2f929
+
+// EVP_AEAD_CTX lacks a zero state, so it doesn't fit easily into
+// ScopedOpenSSLContext.
+class EVP_AEAD_CTXScoper {
+ public:
+ EVP_AEAD_CTXScoper(EVP_AEAD_CTX *ctx) : ctx_(ctx) {}
+ ~EVP_AEAD_CTXScoper() {
+ EVP_AEAD_CTX_cleanup(ctx_);
+ }
+ private:
+ EVP_AEAD_CTX *ctx_;
+};
+
+static bool TestAEAD(FileTest *t, void *arg) {
+ const EVP_AEAD *aead = reinterpret_cast<const EVP_AEAD*>(arg);
+
+ std::vector<uint8_t> key, nonce, in, ad, ct, tag;
+ if (!t->GetBytes(&key, "KEY") ||
+ !t->GetBytes(&nonce, "NONCE") ||
+ !t->GetBytes(&in, "IN") ||
+ !t->GetBytes(&ad, "AD") ||
+ !t->GetBytes(&ct, "CT") ||
+ !t->GetBytes(&tag, "TAG")) {
+ return false;
+ }
+
+ EVP_AEAD_CTX ctx;
+ if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, bssl::vector_data(&key),
+ key.size(), tag.size(),
+ evp_aead_seal)) {
+ t->PrintLine("Failed to init AEAD.");
+ return false;
+ }
+ EVP_AEAD_CTXScoper cleanup(&ctx);
+
+ std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead));
+ if (!t->HasAttribute("NO_SEAL")) {
+ size_t out_len;
+ if (!EVP_AEAD_CTX_seal(&ctx, bssl::vector_data(&out), &out_len, out.size(),
+ bssl::vector_data(&nonce), nonce.size(),
+ bssl::vector_data(&in), in.size(),
+ bssl::vector_data(&ad), ad.size())) {
+ t->PrintLine("Failed to run AEAD.");
+ return false;
+ }
+ out.resize(out_len);
+
+ if (out.size() != ct.size() + tag.size()) {
+ t->PrintLine("Bad output length: %u vs %u.", (unsigned)out_len,
+ (unsigned)(ct.size() + tag.size()));
+ return false;
+ }
+ if (!t->ExpectBytesEqual(bssl::vector_data(&ct), ct.size(),
+ bssl::vector_data(&out), ct.size()) ||
+ !t->ExpectBytesEqual(bssl::vector_data(&tag), tag.size(),
+ bssl::vector_data(&out) + ct.size(), tag.size())) {
+ return false;
+ }
+ } else {
+ out.resize(ct.size() + tag.size());
+ memcpy(bssl::vector_data(&out), bssl::vector_data(&ct), ct.size());
+ memcpy(bssl::vector_data(&out) + ct.size(), bssl::vector_data(&tag),
+ tag.size());
+ }
+
+ // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
+ // reset after each operation.
+ EVP_AEAD_CTX_cleanup(&ctx);
+ if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, bssl::vector_data(&key),
+ key.size(), tag.size(),
+ evp_aead_open)) {
+ t->PrintLine("Failed to init AEAD.");
+ return false;
+ }
+
+ std::vector<uint8_t> out2(out.size());
+ size_t out2_len;
+ int ret = EVP_AEAD_CTX_open(&ctx,
+ bssl::vector_data(&out2), &out2_len, out2.size(),
+ bssl::vector_data(&nonce), nonce.size(),
+ bssl::vector_data(&out), out.size(),
+ bssl::vector_data(&ad), ad.size());
+ if (t->HasAttribute("FAILS")) {
+ if (ret) {
+ t->PrintLine("Decrypted bad data.");
+ return false;
+ }
+ ERR_clear_error();
+ return true;
+ }
+
+ if (!ret) {
+ t->PrintLine("Failed to decrypt.");
+ return false;
+ }
+ out2.resize(out2_len);
+ if (!t->ExpectBytesEqual(bssl::vector_data(&in), in.size(),
+ bssl::vector_data(&out2), out2.size())) {
+ return false;
+ }
+
+ // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
+ // reset after each operation.
+ EVP_AEAD_CTX_cleanup(&ctx);
+ if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, bssl::vector_data(&key),
+ key.size(), tag.size(),
+ evp_aead_open)) {
+ t->PrintLine("Failed to init AEAD.");
+ return false;
+ }
+
+ // Garbage at the end isn't ignored.
+ out.push_back(0);
+ out2.resize(out.size());
+ if (EVP_AEAD_CTX_open(&ctx, bssl::vector_data(&out2), &out2_len, out2.size(),
+ bssl::vector_data(&nonce), nonce.size(),
+ bssl::vector_data(&out), out.size(),
+ bssl::vector_data(&ad), ad.size())) {
+ t->PrintLine("Decrypted bad data with trailing garbage.");
+ return false;
+ }
+ ERR_clear_error();
+
+ // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
+ // reset after each operation.
+ EVP_AEAD_CTX_cleanup(&ctx);
+ if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, bssl::vector_data(&key),
+ key.size(), tag.size(),
+ evp_aead_open)) {
+ t->PrintLine("Failed to init AEAD.");
+ return false;
+ }
+
+ // Verify integrity is checked.
+ out[0] ^= 0x80;
+ out.resize(out.size() - 1);
+ out2.resize(out.size());
+ if (EVP_AEAD_CTX_open(&ctx, bssl::vector_data(&out2), &out2_len, out2.size(),
+ bssl::vector_data(&nonce), nonce.size(),
+ bssl::vector_data(&out), out.size(),
+ bssl::vector_data(&ad), ad.size())) {
+ t->PrintLine("Decrypted bad data with corrupted byte.");
+ return false;
+ }
+ ERR_clear_error();
+
+ return true;
+}
+
+static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
+ EVP_AEAD_CTX ctx;
+ uint8_t key[128];
+
+ memset(key, 0, sizeof(key));
+ const size_t key_len = EVP_AEAD_key_length(aead);
+ if (key_len > sizeof(key)) {
+ fprintf(stderr, "Key length of AEAD too long.\n");
+ return 0;
+ }
+
+ if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
+ 9999 /* a silly tag length to trigger an error */,
+ NULL /* ENGINE */) != 0) {
+ fprintf(stderr, "A silly tag length didn't trigger an error!\n");
+ return 0;
+ }
+
+ /* Running a second, failed _init should not cause a memory leak. */
+ if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
+ 9999 /* a silly tag length to trigger an error */,
+ NULL /* ENGINE */) != 0) {
+ fprintf(stderr, "A silly tag length didn't trigger an error!\n");
+ return 0;
+ }
+
+ /* Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a
+ * no-op. */
+ EVP_AEAD_CTX_cleanup(&ctx);
+ return 1;
+}
+
+struct AEADName {
+ const char name[40];
+ const EVP_AEAD *(*func)(void);
+};
+
+static const struct AEADName kAEADs[] = {
+ { "aes-128-gcm", EVP_aead_aes_128_gcm },
+ { "aes-256-gcm", EVP_aead_aes_256_gcm },
+ { "chacha20-poly1305", EVP_aead_chacha20_poly1305 },
+ { "rc4-md5-tls", EVP_aead_rc4_md5_tls },
+ { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls },
+ { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls },
+ { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv },
+ { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls },
+ { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls },
+ { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv },
+ { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls },
+ { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls },
+ { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls },
+ { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv },
+ { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3 },
+ { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3 },
+ { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3 },
+ { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3 },
+ { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3 },
+ { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap },
+ { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap },
+ { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256 },
+ { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256 },
+ { "", NULL },
+};
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+
+ if (argc != 3) {
+ fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
+ return 1;
+ }
+
+ const EVP_AEAD *aead;
+ for (unsigned i = 0;; i++) {
+ const struct AEADName &aead_name = kAEADs[i];
+ if (aead_name.func == NULL) {
+ fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
+ return 2;
+ }
+ if (strcmp(aead_name.name, argv[1]) == 0) {
+ aead = aead_name.func();
+ break;
+ }
+ }
+
+ if (!TestCleanupAfterInitFailure(aead)) {
+ return 1;
+ }
+
+ return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
+}
diff --git a/src/crypto/cipher/cipher.c b/src/crypto/cipher/cipher.c
index 4bb4196..1dcfd06 100644
--- a/src/crypto/cipher/cipher.c
+++ b/src/crypto/cipher/cipher.c
@@ -94,8 +94,8 @@ EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) {
}
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) {
- if (c->cipher != NULL && c->cipher->cleanup && !c->cipher->cleanup(c)) {
- return 0;
+ if (c->cipher != NULL && c->cipher->cleanup) {
+ c->cipher->cleanup(c);
}
if (c->cipher_data) {
@@ -197,7 +197,6 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
break;
case EVP_CIPH_CFB_MODE:
- case EVP_CIPH_OFB_MODE:
ctx->num = 0;
/* fall-through */
@@ -210,6 +209,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
break;
case EVP_CIPH_CTR_MODE:
+ case EVP_CIPH_OFB_MODE:
ctx->num = 0;
/* Don't reuse IV for CTR mode */
if (iv) {
@@ -582,10 +582,6 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, unsigned key_len) {
int EVP_CIPHER_nid(const EVP_CIPHER *cipher) { return cipher->nid; }
-const char *EVP_CIPHER_name(const EVP_CIPHER *cipher) {
- return OBJ_nid2sn(cipher->nid);
-}
-
unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher) {
return cipher->block_size;
}
diff --git a/src/crypto/cipher/cipher_error.c b/src/crypto/cipher/cipher_error.c
deleted file mode 100644
index 95230f6..0000000
--- a/src/crypto/cipher/cipher_error.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* 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/cipher.h>
-
-const ERR_STRING_DATA CIPHER_error_string_data[] = {
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_AEAD_CTX_init, 0), "EVP_AEAD_CTX_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_AEAD_CTX_open, 0), "EVP_AEAD_CTX_open"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_AEAD_CTX_seal, 0), "EVP_AEAD_CTX_seal"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_copy, 0), "EVP_CIPHER_CTX_copy"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_ctrl, 0), "EVP_CIPHER_CTX_ctrl"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_set_key_length, 0), "EVP_CIPHER_CTX_set_key_length"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CipherInit_ex, 0), "EVP_CipherInit_ex"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_DecryptFinal_ex, 0), "EVP_DecryptFinal_ex"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_EncryptFinal_ex, 0), "EVP_EncryptFinal_ex"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_gcm_init, 0), "aead_aes_gcm_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_gcm_open, 0), "aead_aes_gcm_open"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_gcm_seal, 0), "aead_aes_gcm_seal"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_key_wrap_init, 0), "aead_aes_key_wrap_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_key_wrap_open, 0), "aead_aes_key_wrap_open"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_key_wrap_seal, 0), "aead_aes_key_wrap_seal"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_chacha20_poly1305_init, 0), "aead_chacha20_poly1305_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_chacha20_poly1305_open, 0), "aead_chacha20_poly1305_open"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_chacha20_poly1305_seal, 0), "aead_chacha20_poly1305_seal"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_rc4_md5_tls_init, 0), "aead_rc4_md5_tls_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_rc4_md5_tls_open, 0), "aead_rc4_md5_tls_open"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_rc4_md5_tls_seal, 0), "aead_rc4_md5_tls_seal"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_ssl3_ensure_cipher_init, 0), "aead_ssl3_ensure_cipher_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_ssl3_init, 0), "aead_ssl3_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_ssl3_open, 0), "aead_ssl3_open"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_ssl3_seal, 0), "aead_ssl3_seal"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_tls_ensure_cipher_init, 0), "aead_tls_ensure_cipher_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_tls_init, 0), "aead_tls_init"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_tls_open, 0), "aead_tls_open"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_tls_seal, 0), "aead_tls_seal"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aes_init_key, 0), "aes_init_key"},
- {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aesni_init_key, 0), "aesni_init_key"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_AES_KEY_SETUP_FAILED), "AES_KEY_SETUP_FAILED"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_BAD_DECRYPT), "BAD_DECRYPT"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_BAD_KEY_LENGTH), "BAD_KEY_LENGTH"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_CTRL_NOT_IMPLEMENTED), "CTRL_NOT_IMPLEMENTED"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED), "CTRL_OPERATION_NOT_IMPLEMENTED"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH), "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INITIALIZATION_ERROR), "INITIALIZATION_ERROR"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INPUT_NOT_INITIALIZED), "INPUT_NOT_INITIALIZED"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_AD), "INVALID_AD"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_AD_SIZE), "INVALID_AD_SIZE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_KEY_LENGTH), "INVALID_KEY_LENGTH"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_NONCE_SIZE), "INVALID_NONCE_SIZE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_OPERATION), "INVALID_OPERATION"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_IV_TOO_LARGE), "IV_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_NO_CIPHER_SET), "NO_CIPHER_SET"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_OUTPUT_ALIASES_INPUT), "OUTPUT_ALIASES_INPUT"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_TAG_TOO_LARGE), "TAG_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_TOO_LARGE), "TOO_LARGE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_AD_SIZE), "UNSUPPORTED_AD_SIZE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_INPUT_SIZE), "UNSUPPORTED_INPUT_SIZE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_KEY_SIZE), "UNSUPPORTED_KEY_SIZE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_NONCE_SIZE), "UNSUPPORTED_NONCE_SIZE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_TAG_SIZE), "UNSUPPORTED_TAG_SIZE"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_WRAP_MODE_NOT_ALLOWED), "WRAP_MODE_NOT_ALLOWED"},
- {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_WRONG_FINAL_BLOCK_LENGTH), "WRONG_FINAL_BLOCK_LENGTH"},
- {0, NULL},
-};
diff --git a/src/crypto/cipher/cipher_test.c b/src/crypto/cipher/cipher_test.c
index 2b04ad5..390262f 100644
--- a/src/crypto/cipher/cipher_test.c
+++ b/src/crypto/cipher/cipher_test.c
@@ -54,10 +54,9 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
-#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <openssl/bio.h>
#include <openssl/cipher.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
@@ -68,8 +67,9 @@ static void hexdump(FILE *f, const char *title, const uint8_t *s, int l) {
fprintf(f, "%s", title);
for (; n < l; ++n) {
- if ((n % 16) == 0)
+ if ((n % 16) == 0) {
fprintf(f, "\n%04x", n);
+ }
fprintf(f, " %02x", s[n]);
}
fprintf(f, "\n");
@@ -123,15 +123,16 @@ static uint8_t *ustrsep(char **p, const char *sep) {
return (uint8_t *)sstrsep(p, sep);
}
-static void test1(const EVP_CIPHER *c, const uint8_t *key, int kn,
- const uint8_t *iv, int in, const uint8_t *plaintext, int pn,
- const uint8_t *ciphertext, int cn, const uint8_t *aad, int an,
- const uint8_t *tag, int tn, int encdec) {
+static void test1(const char* cipher_name, const EVP_CIPHER *c,
+ const uint8_t *key, int kn, const uint8_t *iv, int in,
+ const uint8_t *plaintext, int pn, const uint8_t *ciphertext,
+ int cn, const uint8_t *aad, int an, const uint8_t *tag,
+ int tn, int encdec) {
EVP_CIPHER_CTX ctx;
uint8_t out[4096];
int outl, outl2, mode;
- printf("Testing cipher %s%s\n", EVP_CIPHER_name(c),
+ printf("Testing cipher %s%s\n", cipher_name,
(encdec == 1 ? "(encrypt)"
: (encdec == 0 ? "(decrypt)" : "(encrypt/decrypt)")));
hexdump(stdout, "Key", key, kn);
@@ -157,39 +158,39 @@ static void test1(const EVP_CIPHER *c, const uint8_t *key, int kn,
if (mode == EVP_CIPH_GCM_MODE) {
if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
fprintf(stderr, "EncryptInit failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(10);
}
if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
fprintf(stderr, "IV length set failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(11);
}
if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) {
fprintf(stderr, "Key/IV set failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(12);
}
if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) {
fprintf(stderr, "AAD set failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(13);
}
} else if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, iv)) {
fprintf(stderr, "EncryptInit failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(10);
}
EVP_CIPHER_CTX_set_padding(&ctx, 0);
if (!EVP_EncryptUpdate(&ctx, out, &outl, plaintext, pn)) {
fprintf(stderr, "Encrypt failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(6);
}
if (!EVP_EncryptFinal_ex(&ctx, out + outl, &outl2)) {
fprintf(stderr, "EncryptFinal failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(7);
}
@@ -212,7 +213,7 @@ static void test1(const EVP_CIPHER *c, const uint8_t *key, int kn,
*/
if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tn, rtag)) {
fprintf(stderr, "Get tag failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(14);
}
if (memcmp(rtag, tag, tn)) {
@@ -228,45 +229,45 @@ static void test1(const EVP_CIPHER *c, const uint8_t *key, int kn,
if (mode == EVP_CIPH_GCM_MODE) {
if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
fprintf(stderr, "EncryptInit failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(10);
}
if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
fprintf(stderr, "IV length set failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(11);
}
if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) {
fprintf(stderr, "Key/IV set failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(12);
}
if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, tn, (void *)tag)) {
fprintf(stderr, "Set tag failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(14);
}
if (an && !EVP_DecryptUpdate(&ctx, NULL, &outl, aad, an)) {
fprintf(stderr, "AAD set failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(13);
}
} else if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, iv)) {
fprintf(stderr, "DecryptInit failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(11);
}
EVP_CIPHER_CTX_set_padding(&ctx, 0);
if (!EVP_DecryptUpdate(&ctx, out, &outl, ciphertext, cn)) {
fprintf(stderr, "Decrypt failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(6);
}
outl2 = 0;
if (!EVP_DecryptFinal_ex(&ctx, out + outl, &outl2)) {
fprintf(stderr, "DecryptFinal failed\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
exit(7);
}
@@ -310,6 +311,12 @@ static int test_cipher(const char *cipher, const uint8_t *key, int kn,
c = EVP_aes_128_cbc();
} else if (strcmp(cipher, "AES-128-GCM") == 0) {
c = EVP_aes_128_gcm();
+ } else if (strcmp(cipher, "AES-128-OFB") == 0) {
+ c = EVP_aes_128_ofb();
+ } else if (strcmp(cipher, "AES-192-CBC") == 0) {
+ c = EVP_aes_192_cbc();
+ } else if (strcmp(cipher, "AES-192-ECB") == 0) {
+ c = EVP_aes_192_ecb();
} else if (strcmp(cipher, "AES-256-CBC") == 0) {
c = EVP_aes_256_cbc();
} else if (strcmp(cipher, "AES-128-CTR") == 0) {
@@ -318,13 +325,15 @@ static int test_cipher(const char *cipher, const uint8_t *key, int kn,
c = EVP_aes_256_ctr();
} else if (strcmp(cipher, "AES-256-GCM") == 0) {
c = EVP_aes_256_gcm();
+ } else if (strcmp(cipher, "AES-256-OFB") == 0) {
+ c = EVP_aes_256_ofb();
} else {
fprintf(stderr, "Unknown cipher type %s\n", cipher);
return 0;
}
- test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, aad, an, tag, tn,
- encdec);
+ test1(cipher, c, key, kn, iv, in, plaintext, pn, ciphertext, cn, aad, an,
+ tag, tn, encdec);
return 1;
}
@@ -388,8 +397,9 @@ int main(int argc, char **argv) {
if (p[-1] == '\n') {
encdec = -1;
p[-1] = '\0';
- } else
+ } else {
encdec = atoi(sstrsep(&p, "\n"));
+ }
}
kn = convert(key);
diff --git a/src/crypto/cipher/e_aes.c b/src/crypto/cipher/e_aes.c
index a86e830..eacbd10 100644
--- a/src/crypto/cipher/e_aes.c
+++ b/src/crypto/cipher/e_aes.c
@@ -57,8 +57,10 @@
#include <openssl/modes.h>
#include <openssl/obj.h>
#include <openssl/rand.h>
+#include <openssl/sha.h>
#include "internal.h"
+#include "../internal.h"
#include "../modes/internal.h"
#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
@@ -281,7 +283,8 @@ void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
#endif
static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
- const uint8_t *iv, int enc) {
+ const uint8_t *iv, int enc)
+ OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
int ret, mode;
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
@@ -342,8 +345,8 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
return 1;
}
-static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t len) {
+static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t len) {
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
if (dat->stream.cbc) {
@@ -357,8 +360,8 @@ static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t len) {
+static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t len) {
size_t bl = ctx->cipher->block_size;
size_t i;
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
@@ -374,8 +377,8 @@ static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t len) {
+static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t len) {
unsigned int num = ctx->num;
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
@@ -390,28 +393,71 @@ static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-static ctr128_f aes_gcm_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
- const uint8_t *key, size_t key_len) {
+static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t len) {
+ EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+ CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num, dat->block);
+ return 1;
+}
+
+static char aesni_capable(void);
+
+static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
+ block128_f *out_block, const uint8_t *key,
+ size_t key_len)
+ OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
+ if (aesni_capable()) {
+ aesni_set_encrypt_key(key, key_len * 8, aes_key);
+ if (gcm_ctx != NULL) {
+ CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aesni_encrypt);
+ }
+ if (out_block) {
+ *out_block = (block128_f) aesni_encrypt;
+ }
+ return (ctr128_f)aesni_ctr32_encrypt_blocks;
+ }
+
if (hwaes_capable()) {
aes_v8_set_encrypt_key(key, key_len * 8, aes_key);
- CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_v8_encrypt);
+ if (gcm_ctx != NULL) {
+ CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_v8_encrypt);
+ }
+ if (out_block) {
+ *out_block = (block128_f) aes_v8_encrypt;
+ }
return (ctr128_f)aes_v8_ctr32_encrypt_blocks;
}
if (bsaes_capable()) {
AES_set_encrypt_key(key, key_len * 8, aes_key);
- CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt);
+ if (gcm_ctx != NULL) {
+ CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt);
+ }
+ if (out_block) {
+ *out_block = (block128_f) AES_encrypt;
+ }
return (ctr128_f)bsaes_ctr32_encrypt_blocks;
}
if (vpaes_capable()) {
vpaes_set_encrypt_key(key, key_len * 8, aes_key);
- CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt);
+ if (out_block) {
+ *out_block = (block128_f) vpaes_encrypt;
+ }
+ if (gcm_ctx != NULL) {
+ CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt);
+ }
return NULL;
}
AES_set_encrypt_key(key, key_len * 8, aes_key);
- CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt);
+ if (gcm_ctx != NULL) {
+ CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt);
+ }
+ if (out_block) {
+ *out_block = (block128_f) AES_encrypt;
+ }
return NULL;
}
@@ -422,7 +468,8 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
return 1;
}
if (key) {
- gctx->ctr = aes_gcm_set_key(&gctx->ks.ks, &gctx->gcm, key, ctx->key_len);
+ gctx->ctr =
+ aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm, NULL, key, ctx->key_len);
/* If we have an iv can set it directly, otherwise use saved IV. */
if (iv == NULL && gctx->iv_set) {
iv = gctx->iv;
@@ -445,13 +492,12 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
return 1;
}
-static int aes_gcm_cleanup(EVP_CIPHER_CTX *c) {
+static void aes_gcm_cleanup(EVP_CIPHER_CTX *c) {
EVP_AES_GCM_CTX *gctx = c->cipher_data;
OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
if (gctx->iv != c->iv) {
OPENSSL_free(gctx->iv);
}
- return 1;
}
/* increment counter (64-bit int) by 1 */
@@ -697,6 +743,12 @@ static const EVP_CIPHER aes_128_ecb = {
NULL /* app_data */, aes_init_key, aes_ecb_cipher,
NULL /* cleanup */, NULL /* ctrl */};
+static const EVP_CIPHER aes_128_ofb = {
+ NID_aes_128_ofb128, 1 /* block_size */, 16 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE,
+ NULL /* app_data */, aes_init_key, aes_ofb_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
static const EVP_CIPHER aes_128_gcm = {
NID_aes_128_gcm, 1 /* block_size */, 16 /* key_size */, 12 /* iv_len */,
sizeof(EVP_AES_GCM_CTX),
@@ -736,25 +788,31 @@ static const EVP_CIPHER aes_192_gcm = {
static const EVP_CIPHER aes_256_cbc = {
- NID_aes_128_cbc, 16 /* block_size */, 32 /* key_size */,
+ NID_aes_256_cbc, 16 /* block_size */, 32 /* key_size */,
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
NULL /* app_data */, aes_init_key, aes_cbc_cipher,
NULL /* cleanup */, NULL /* ctrl */};
static const EVP_CIPHER aes_256_ctr = {
- NID_aes_128_ctr, 1 /* block_size */, 32 /* key_size */,
+ NID_aes_256_ctr, 1 /* block_size */, 32 /* key_size */,
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
NULL /* app_data */, aes_init_key, aes_ctr_cipher,
NULL /* cleanup */, NULL /* ctrl */};
static const EVP_CIPHER aes_256_ecb = {
- NID_aes_128_ecb, 16 /* block_size */, 32 /* key_size */,
+ NID_aes_256_ecb, 16 /* block_size */, 32 /* key_size */,
0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
NULL /* app_data */, aes_init_key, aes_ecb_cipher,
NULL /* cleanup */, NULL /* ctrl */};
+static const EVP_CIPHER aes_256_ofb = {
+ NID_aes_256_ofb128, 1 /* block_size */, 32 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE,
+ NULL /* app_data */, aes_init_key, aes_ofb_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
static const EVP_CIPHER aes_256_gcm = {
- NID_aes_128_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */,
+ NID_aes_256_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */,
sizeof(EVP_AES_GCM_CTX),
EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
@@ -873,6 +931,12 @@ static const EVP_CIPHER aesni_128_ecb = {
NULL /* app_data */, aesni_init_key, aesni_ecb_cipher,
NULL /* cleanup */, NULL /* ctrl */};
+static const EVP_CIPHER aesni_128_ofb = {
+ NID_aes_128_ofb128, 1 /* block_size */, 16 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE,
+ NULL /* app_data */, aesni_init_key, aes_ofb_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
static const EVP_CIPHER aesni_128_gcm = {
NID_aes_128_gcm, 1 /* block_size */, 16 /* key_size */, 12 /* iv_len */,
sizeof(EVP_AES_GCM_CTX),
@@ -912,23 +976,29 @@ static const EVP_CIPHER aesni_192_gcm = {
static const EVP_CIPHER aesni_256_cbc = {
- NID_aes_128_cbc, 16 /* block_size */, 32 /* key_size */,
+ NID_aes_256_cbc, 16 /* block_size */, 32 /* key_size */,
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
NULL /* app_data */, aesni_init_key, aesni_cbc_cipher,
NULL /* cleanup */, NULL /* ctrl */};
static const EVP_CIPHER aesni_256_ctr = {
- NID_aes_128_ctr, 1 /* block_size */, 32 /* key_size */,
+ NID_aes_256_ctr, 1 /* block_size */, 32 /* key_size */,
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
NULL /* app_data */, aesni_init_key, aes_ctr_cipher,
NULL /* cleanup */, NULL /* ctrl */};
static const EVP_CIPHER aesni_256_ecb = {
- NID_aes_128_ecb, 16 /* block_size */, 32 /* key_size */,
+ NID_aes_256_ecb, 16 /* block_size */, 32 /* key_size */,
0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
NULL /* app_data */, aesni_init_key, aesni_ecb_cipher,
NULL /* cleanup */, NULL /* ctrl */};
+static const EVP_CIPHER aesni_256_ofb = {
+ NID_aes_256_ofb128, 1 /* block_size */, 32 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE,
+ NULL /* app_data */, aesni_init_key, aes_ofb_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
static const EVP_CIPHER aesni_256_gcm = {
NID_aes_256_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */,
sizeof(EVP_AES_GCM_CTX),
@@ -963,6 +1033,7 @@ static char aesni_capable(void) {
EVP_CIPHER_FUNCTION(128, cbc)
EVP_CIPHER_FUNCTION(128, ctr)
EVP_CIPHER_FUNCTION(128, ecb)
+EVP_CIPHER_FUNCTION(128, ofb)
EVP_CIPHER_FUNCTION(128, gcm)
EVP_CIPHER_FUNCTION(192, cbc)
@@ -973,6 +1044,7 @@ EVP_CIPHER_FUNCTION(192, gcm)
EVP_CIPHER_FUNCTION(256, cbc)
EVP_CIPHER_FUNCTION(256, ctr)
EVP_CIPHER_FUNCTION(256, ecb)
+EVP_CIPHER_FUNCTION(256, ofb)
EVP_CIPHER_FUNCTION(256, gcm)
@@ -1012,15 +1084,8 @@ static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
return 0;
}
- if (aesni_capable()) {
- aesni_set_encrypt_key(key, key_len * 8, &gcm_ctx->ks.ks);
- CRYPTO_gcm128_init(&gcm_ctx->gcm, &gcm_ctx->ks.ks,
- (block128_f)aesni_encrypt);
- gcm_ctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
- } else {
- gcm_ctx->ctr =
- aes_gcm_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, key, key_len);
- }
+ gcm_ctx->ctr =
+ aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, NULL, key, key_len);
gcm_ctx->tag_len = tag_len;
ctx->aead_state = gcm_ctx;
@@ -1133,8 +1198,12 @@ static const EVP_AEAD aead_aes_128_gcm = {
12, /* nonce len */
EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
- aead_aes_gcm_init, aead_aes_gcm_cleanup,
- aead_aes_gcm_seal, aead_aes_gcm_open,
+ aead_aes_gcm_init,
+ NULL, /* init_with_direction */
+ aead_aes_gcm_cleanup,
+ aead_aes_gcm_seal,
+ aead_aes_gcm_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_256_gcm = {
@@ -1142,8 +1211,12 @@ static const EVP_AEAD aead_aes_256_gcm = {
12, /* nonce len */
EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
- aead_aes_gcm_init, aead_aes_gcm_cleanup,
- aead_aes_gcm_seal, aead_aes_gcm_open,
+ aead_aes_gcm_init,
+ NULL, /* init_with_direction */
+ aead_aes_gcm_cleanup,
+ aead_aes_gcm_seal,
+ aead_aes_gcm_open,
+ NULL, /* get_rc4_state */
};
const EVP_AEAD *EVP_aead_aes_128_gcm(void) { return &aead_aes_128_gcm; }
@@ -1347,7 +1420,7 @@ static int aead_aes_key_wrap_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
}
if (in_len < 24) {
- OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BAD_DECRYPT);
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open, CIPHER_R_BAD_DECRYPT);
return 0;
}
@@ -1384,7 +1457,7 @@ static int aead_aes_key_wrap_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
}
if (CRYPTO_memcmp(A, nonce, 8) != 0) {
- OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BAD_DECRYPT);
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open, CIPHER_R_BAD_DECRYPT);
return 0;
}
@@ -1397,8 +1470,12 @@ static const EVP_AEAD aead_aes_128_key_wrap = {
8, /* nonce len */
8, /* overhead */
8, /* max tag length */
- aead_aes_key_wrap_init, aead_aes_key_wrap_cleanup,
- aead_aes_key_wrap_seal, aead_aes_key_wrap_open,
+ aead_aes_key_wrap_init,
+ NULL, /* init_with_direction */
+ aead_aes_key_wrap_cleanup,
+ aead_aes_key_wrap_seal,
+ aead_aes_key_wrap_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_256_key_wrap = {
@@ -1406,14 +1483,297 @@ static const EVP_AEAD aead_aes_256_key_wrap = {
8, /* nonce len */
8, /* overhead */
8, /* max tag length */
- aead_aes_key_wrap_init, aead_aes_key_wrap_cleanup,
- aead_aes_key_wrap_seal, aead_aes_key_wrap_open,
+ aead_aes_key_wrap_init,
+ NULL, /* init_with_direction */
+ aead_aes_key_wrap_cleanup,
+ aead_aes_key_wrap_seal,
+ aead_aes_key_wrap_open,
+ NULL, /* get_rc4_state */
};
const EVP_AEAD *EVP_aead_aes_128_key_wrap(void) { return &aead_aes_128_key_wrap; }
const EVP_AEAD *EVP_aead_aes_256_key_wrap(void) { return &aead_aes_256_key_wrap; }
+
+#define EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN SHA256_DIGEST_LENGTH
+#define EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN 12
+
+struct aead_aes_ctr_hmac_sha256_ctx {
+ union {
+ double align;
+ AES_KEY ks;
+ } ks;
+ ctr128_f ctr;
+ block128_f block;
+ SHA256_CTX inner_init_state;
+ SHA256_CTX outer_init_state;
+ uint8_t tag_len;
+};
+
+static void hmac_init(SHA256_CTX *out_inner, SHA256_CTX *out_outer,
+ const uint8_t hmac_key[32]) {
+ static const size_t hmac_key_len = 32;
+ uint8_t block[SHA256_CBLOCK];
+ memcpy(block, hmac_key, hmac_key_len);
+ memset(block + hmac_key_len, 0x36, sizeof(block) - hmac_key_len);
+
+ unsigned i;
+ for (i = 0; i < hmac_key_len; i++) {
+ block[i] ^= 0x36;
+ }
+
+ SHA256_Init(out_inner);
+ SHA256_Update(out_inner, block, sizeof(block));
+
+ memset(block + hmac_key_len, 0x5c, sizeof(block) - hmac_key_len);
+ for (i = 0; i < hmac_key_len; i++) {
+ block[i] ^= (0x36 ^ 0x5c);
+ }
+
+ SHA256_Init(out_outer);
+ SHA256_Update(out_outer, block, sizeof(block));
+}
+
+static int aead_aes_ctr_hmac_sha256_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx;
+ static const size_t hmac_key_len = 32;
+
+ if (key_len < hmac_key_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_init,
+ CIPHER_R_BAD_KEY_LENGTH);
+ return 0; /* EVP_AEAD_CTX_init should catch this. */
+ }
+
+ const size_t aes_key_len = key_len - hmac_key_len;
+ if (aes_key_len != 16 && aes_key_len != 32) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_init,
+ CIPHER_R_BAD_KEY_LENGTH);
+ return 0; /* EVP_AEAD_CTX_init should catch this. */
+ }
+
+ if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
+ tag_len = EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN;
+ }
+
+ if (tag_len > EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_init,
+ CIPHER_R_TAG_TOO_LARGE);
+ return 0;
+ }
+
+ aes_ctx = OPENSSL_malloc(sizeof(struct aead_aes_ctr_hmac_sha256_ctx));
+ if (aes_ctx == NULL) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_init,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ aes_ctx->ctr =
+ aes_ctr_set_key(&aes_ctx->ks.ks, NULL, &aes_ctx->block, key, aes_key_len);
+ aes_ctx->tag_len = tag_len;
+ hmac_init(&aes_ctx->inner_init_state, &aes_ctx->outer_init_state,
+ key + aes_key_len);
+
+ ctx->aead_state = aes_ctx;
+
+ return 1;
+}
+
+static void aead_aes_ctr_hmac_sha256_cleanup(EVP_AEAD_CTX *ctx) {
+ struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
+ OPENSSL_cleanse(aes_ctx, sizeof(struct aead_aes_ctr_hmac_sha256_ctx));
+ OPENSSL_free(aes_ctx);
+}
+
+static void hmac_update_uint64(SHA256_CTX *sha256, uint64_t value) {
+ unsigned i;
+ uint8_t bytes[8];
+
+ for (i = 0; i < sizeof(bytes); i++) {
+ bytes[i] = value & 0xff;
+ value >>= 8;
+ }
+ SHA256_Update(sha256, bytes, sizeof(bytes));
+}
+
+static void hmac_calculate(uint8_t out[SHA256_DIGEST_LENGTH],
+ const SHA256_CTX *inner_init_state,
+ const SHA256_CTX *outer_init_state,
+ const uint8_t *ad, size_t ad_len,
+ const uint8_t *nonce, const uint8_t *ciphertext,
+ size_t ciphertext_len) {
+ SHA256_CTX sha256;
+ memcpy(&sha256, inner_init_state, sizeof(sha256));
+ hmac_update_uint64(&sha256, ad_len);
+ hmac_update_uint64(&sha256, ciphertext_len);
+ SHA256_Update(&sha256, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
+ SHA256_Update(&sha256, ad, ad_len);
+
+ /* Pad with zeros to the end of the SHA-256 block. */
+ const unsigned num_padding =
+ (SHA256_CBLOCK - ((sizeof(uint64_t)*2 +
+ EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN + ad_len) %
+ SHA256_CBLOCK)) %
+ SHA256_CBLOCK;
+ uint8_t padding[SHA256_CBLOCK];
+ memset(padding, 0, num_padding);
+ SHA256_Update(&sha256, padding, num_padding);
+
+ SHA256_Update(&sha256, ciphertext, ciphertext_len);
+
+ uint8_t inner_digest[SHA256_DIGEST_LENGTH];
+ SHA256_Final(inner_digest, &sha256);
+
+ memcpy(&sha256, outer_init_state, sizeof(sha256));
+ SHA256_Update(&sha256, inner_digest, sizeof(inner_digest));
+ SHA256_Final(out, &sha256);
+}
+
+static void aead_aes_ctr_hmac_sha256_crypt(
+ const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx, uint8_t *out,
+ const uint8_t *in, size_t len, const uint8_t *nonce) {
+ /* Since the AEAD operation is one-shot, keeping a buffer of unused keystream
+ * bytes is pointless. However, |CRYPTO_ctr128_encrypt| requires it. */
+ uint8_t partial_block_buffer[AES_BLOCK_SIZE];
+ unsigned partial_block_offset = 0;
+ memset(partial_block_buffer, 0, sizeof(partial_block_buffer));
+
+ uint8_t counter[AES_BLOCK_SIZE];
+ memcpy(counter, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
+ memset(counter + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN, 0, 4);
+
+ if (aes_ctx->ctr) {
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len, &aes_ctx->ks.ks, counter,
+ partial_block_buffer, &partial_block_offset,
+ aes_ctx->ctr);
+ } else {
+ CRYPTO_ctr128_encrypt(in, out, len, &aes_ctx->ks.ks, counter,
+ partial_block_buffer, &partial_block_offset,
+ aes_ctx->block);
+ }
+}
+
+static int aead_aes_ctr_hmac_sha256_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
+ const uint64_t in_len_64 = in_len;
+
+ if (in_len + aes_ctx->tag_len < in_len ||
+ /* This input is so large it would overflow the 32-bit block counter. */
+ in_len_64 >= (OPENSSL_U64(1) << 32) * AES_BLOCK_SIZE) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_seal,
+ CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + aes_ctx->tag_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_seal,
+ CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_seal,
+ CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+ return 0;
+ }
+
+ aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, in_len, nonce);
+
+ uint8_t hmac_result[SHA256_DIGEST_LENGTH];
+ hmac_calculate(hmac_result, &aes_ctx->inner_init_state,
+ &aes_ctx->outer_init_state, ad, ad_len, nonce, out, in_len);
+ memcpy(out + in_len, hmac_result, aes_ctx->tag_len);
+ *out_len = in_len + aes_ctx->tag_len;
+
+ return 1;
+}
+
+static int aead_aes_ctr_hmac_sha256_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
+ size_t plaintext_len;
+
+ if (in_len < aes_ctx->tag_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_open,
+ CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ plaintext_len = in_len - aes_ctx->tag_len;
+
+ if (max_out_len < plaintext_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_open,
+ CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_open,
+ CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+ return 0;
+ }
+
+ uint8_t hmac_result[SHA256_DIGEST_LENGTH];
+ hmac_calculate(hmac_result, &aes_ctx->inner_init_state,
+ &aes_ctx->outer_init_state, ad, ad_len, nonce, in,
+ plaintext_len);
+ if (CRYPTO_memcmp(hmac_result, in + plaintext_len, aes_ctx->tag_len) != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_ctr_hmac_sha256_open,
+ CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, plaintext_len, nonce);
+
+ *out_len = plaintext_len;
+ return 1;
+}
+
+static const EVP_AEAD aead_aes_128_ctr_hmac_sha256 = {
+ 16 /* AES key */ + 32 /* HMAC key */,
+ 12, /* nonce length */
+ EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */
+
+ aead_aes_ctr_hmac_sha256_init,
+ NULL /* init_with_direction */,
+ aead_aes_ctr_hmac_sha256_cleanup,
+ aead_aes_ctr_hmac_sha256_seal,
+ aead_aes_ctr_hmac_sha256_open,
+ NULL /* get_rc4_state */,
+};
+
+static const EVP_AEAD aead_aes_256_ctr_hmac_sha256 = {
+ 32 /* AES key */ + 32 /* HMAC key */,
+ 12, /* nonce length */
+ EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */
+
+ aead_aes_ctr_hmac_sha256_init,
+ NULL /* init_with_direction */,
+ aead_aes_ctr_hmac_sha256_cleanup,
+ aead_aes_ctr_hmac_sha256_seal,
+ aead_aes_ctr_hmac_sha256_open,
+ NULL /* get_rc4_state */,
+};
+
+const EVP_AEAD *EVP_aead_aes_128_ctr_hmac_sha256(void) {
+ return &aead_aes_128_ctr_hmac_sha256;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void) {
+ return &aead_aes_256_ctr_hmac_sha256;
+}
+
int EVP_has_aes_hardware(void) {
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
return aesni_capable() && crypto_gcm_clmul_enabled();
diff --git a/src/crypto/cipher/e_chacha20poly1305.c b/src/crypto/cipher/e_chacha20poly1305.c
index 1cdcbca..ebf0088 100644
--- a/src/crypto/cipher/e_chacha20poly1305.c
+++ b/src/crypto/cipher/e_chacha20poly1305.c
@@ -209,8 +209,12 @@ static const EVP_AEAD aead_chacha20_poly1305 = {
CHACHA20_NONCE_LEN, /* nonce len */
POLY1305_TAG_LEN, /* overhead */
POLY1305_TAG_LEN, /* max tag length */
- aead_chacha20_poly1305_init, aead_chacha20_poly1305_cleanup,
- aead_chacha20_poly1305_seal, aead_chacha20_poly1305_open,
+ aead_chacha20_poly1305_init,
+ NULL, /* init_with_direction */
+ aead_chacha20_poly1305_cleanup,
+ aead_chacha20_poly1305_seal,
+ aead_chacha20_poly1305_open,
+ NULL, /* get_rc4_state */
};
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
diff --git a/src/crypto/cipher/e_des.c b/src/crypto/cipher/e_des.c
index d4b04f4..74e1fce 100644
--- a/src/crypto/cipher/e_des.c
+++ b/src/crypto/cipher/e_des.c
@@ -61,8 +61,6 @@
#include "internal.h"
-#define EVP_MAXCHUNK (1<<30)
-
typedef struct {
union {
double align;
@@ -83,18 +81,8 @@ static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
size_t in_len) {
EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data;
- while (in_len >= EVP_MAXCHUNK) {
- DES_ncbc_encrypt(in, out, EVP_MAXCHUNK, &dat->ks.ks, (DES_cblock *)ctx->iv,
- ctx->encrypt);
- in_len -= EVP_MAXCHUNK;
- in += EVP_MAXCHUNK;
- out += EVP_MAXCHUNK;
- }
-
- if (in_len) {
- DES_ncbc_encrypt(in, out, (long)in_len, &dat->ks.ks,
- (DES_cblock *)ctx->iv, ctx->encrypt);
- }
+ DES_ncbc_encrypt(in, out, in_len, &dat->ks.ks, (DES_cblock *)ctx->iv,
+ ctx->encrypt);
return 1;
}
@@ -132,18 +120,8 @@ static int des_ede3_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
const uint8_t *in, size_t in_len) {
DES_EDE_KEY *dat = (DES_EDE_KEY*) ctx->cipher_data;
- while (in_len >= EVP_MAXCHUNK) {
- DES_ede3_cbc_encrypt(in, out, EVP_MAXCHUNK, &dat->ks.ks[0], &dat->ks.ks[1],
- &dat->ks.ks[2], (DES_cblock *)ctx->iv, ctx->encrypt);
- in_len -= EVP_MAXCHUNK;
- in += EVP_MAXCHUNK;
- out += EVP_MAXCHUNK;
- }
-
- if (in_len) {
- DES_ede3_cbc_encrypt(in, out, in_len, &dat->ks.ks[0], &dat->ks.ks[1],
- &dat->ks.ks[2], (DES_cblock *)ctx->iv, ctx->encrypt);
- }
+ DES_ede3_cbc_encrypt(in, out, in_len, &dat->ks.ks[0], &dat->ks.ks[1],
+ &dat->ks.ks[2], (DES_cblock *)ctx->iv, ctx->encrypt);
return 1;
}
diff --git a/src/crypto/cipher/e_rc4.c b/src/crypto/cipher/e_rc4.c
index 04ddcb6..80dea36 100644
--- a/src/crypto/cipher/e_rc4.c
+++ b/src/crypto/cipher/e_rc4.c
@@ -299,7 +299,9 @@ static int aead_rc4_md5_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}
- if (max_out_len < plaintext_len) {
+ if (max_out_len < in_len) {
+ /* This requires that the caller provide space for the MAC, even though it
+ * will always be removed on return. */
OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_open, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
@@ -372,13 +374,24 @@ static int aead_rc4_md5_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 1;
}
+static int aead_rc4_md5_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
+ const RC4_KEY **out_key) {
+ struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
+ *out_key = &rc4_ctx->rc4;
+ return 1;
+}
+
static const EVP_AEAD aead_rc4_md5_tls = {
16 + MD5_DIGEST_LENGTH, /* key len (RC4 + MD5) */
0, /* nonce len */
MD5_DIGEST_LENGTH, /* overhead */
MD5_DIGEST_LENGTH, /* max tag length */
- aead_rc4_md5_tls_init, aead_rc4_md5_tls_cleanup,
- aead_rc4_md5_tls_seal, aead_rc4_md5_tls_open,
+ aead_rc4_md5_tls_init,
+ NULL, /* init_with_direction */
+ aead_rc4_md5_tls_cleanup,
+ aead_rc4_md5_tls_seal,
+ aead_rc4_md5_tls_open,
+ aead_rc4_md5_tls_get_rc4_state,
};
const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }
diff --git a/src/crypto/cipher/e_ssl3.c b/src/crypto/cipher/e_ssl3.c
index d9dec68..1031d9b 100644
--- a/src/crypto/cipher/e_ssl3.c
+++ b/src/crypto/cipher/e_ssl3.c
@@ -30,17 +30,6 @@
typedef struct {
EVP_CIPHER_CTX cipher_ctx;
EVP_MD_CTX md_ctx;
- /* enc_key is the portion of the key used for the stream or block cipher. It
- * is retained separately to allow the EVP_CIPHER_CTX to be initialized once
- * the direction is known. */
- uint8_t enc_key[EVP_MAX_KEY_LENGTH];
- uint8_t enc_key_len;
- /* iv is the portion of the key used for the fixed IV. It is retained
- * separately to allow the EVP_CIPHER_CTX to be initialized once the direction
- * is known. */
- uint8_t iv[EVP_MAX_IV_LENGTH];
- uint8_t iv_len;
- char initialized;
} AEAD_SSL3_CTX;
static int ssl3_mac(AEAD_SSL3_CTX *ssl3_ctx, uint8_t *out, unsigned *out_len,
@@ -87,15 +76,13 @@ static void aead_ssl3_cleanup(EVP_AEAD_CTX *ctx) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
EVP_CIPHER_CTX_cleanup(&ssl3_ctx->cipher_ctx);
EVP_MD_CTX_cleanup(&ssl3_ctx->md_ctx);
- OPENSSL_cleanse(&ssl3_ctx->enc_key, sizeof(ssl3_ctx->enc_key));
- OPENSSL_cleanse(&ssl3_ctx->iv, sizeof(ssl3_ctx->iv));
OPENSSL_free(ssl3_ctx);
ctx->aead_state = NULL;
}
static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
- size_t tag_len, const EVP_CIPHER *cipher,
- const EVP_MD *md) {
+ size_t tag_len, enum evp_aead_direction_t dir,
+ const EVP_CIPHER *cipher, const EVP_MD *md) {
if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
tag_len != EVP_MD_size(md)) {
OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_init, CIPHER_R_UNSUPPORTED_TAG_SIZE);
@@ -109,11 +96,7 @@ static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
size_t mac_key_len = EVP_MD_size(md);
size_t enc_key_len = EVP_CIPHER_key_length(cipher);
- size_t iv_len = EVP_CIPHER_iv_length(cipher);
- assert(mac_key_len + enc_key_len + iv_len == key_len);
- assert(mac_key_len < 256);
- assert(enc_key_len < 256);
- assert(iv_len < 256);
+ assert(mac_key_len + enc_key_len + EVP_CIPHER_iv_length(cipher) == key_len);
/* Although EVP_rc4() is a variable-length cipher, the default key size is
* correct for SSL3. */
@@ -124,17 +107,15 @@ static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
}
EVP_CIPHER_CTX_init(&ssl3_ctx->cipher_ctx);
EVP_MD_CTX_init(&ssl3_ctx->md_ctx);
- memcpy(ssl3_ctx->enc_key, &key[mac_key_len], enc_key_len);
- ssl3_ctx->enc_key_len = (uint8_t)enc_key_len;
- memcpy(ssl3_ctx->iv, &key[mac_key_len + enc_key_len], iv_len);
- ssl3_ctx->iv_len = (uint8_t)iv_len;
- ssl3_ctx->initialized = 0;
ctx->aead_state = ssl3_ctx;
- if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, NULL, NULL, 0) ||
+ if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len],
+ &key[mac_key_len + enc_key_len],
+ dir == evp_aead_seal) ||
!EVP_DigestInit_ex(&ssl3_ctx->md_ctx, md, NULL) ||
!EVP_DigestUpdate(&ssl3_ctx->md_ctx, key, mac_key_len)) {
aead_ssl3_cleanup(ctx);
+ ctx->aead_state = NULL;
return 0;
}
EVP_CIPHER_CTX_set_padding(&ssl3_ctx->cipher_ctx, 0);
@@ -142,31 +123,6 @@ static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
return 1;
}
-/* aead_ssl3_ensure_cipher_init initializes |ssl3_ctx| for encryption (or
- * decryption, if |encrypt| is zero). If it has already been initialized, it
- * ensures the direction matches and fails otherwise. It returns one on success
- * and zero on failure.
- *
- * Note that, unlike normal AEADs, legacy SSL3 AEADs may not be used concurrently
- * due to this (and bulk-cipher-internal) statefulness. */
-static int aead_ssl3_ensure_cipher_init(AEAD_SSL3_CTX *ssl3_ctx, int encrypt) {
- if (!ssl3_ctx->initialized) {
- /* Finish initializing the EVP_CIPHER_CTX now that the direction is
- * known. */
- if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, NULL, NULL, ssl3_ctx->enc_key,
- ssl3_ctx->iv, encrypt)) {
- return 0;
- }
- ssl3_ctx->initialized = 1;
- } else if (ssl3_ctx->cipher_ctx.encrypt != encrypt) {
- /* Unlike a normal AEAD, using an SSL3 AEAD once freezes the direction. */
- OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_ensure_cipher_init,
- CIPHER_R_INVALID_OPERATION);
- return 0;
- }
- return 1;
-}
-
static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
@@ -175,6 +131,12 @@ static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
size_t total = 0;
+ if (!ssl3_ctx->cipher_ctx.encrypt) {
+ /* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_seal, CIPHER_R_INVALID_OPERATION);
+ return 0;
+ }
+
if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
in_len > INT_MAX) {
/* EVP_CIPHER takes int as input. */
@@ -197,10 +159,6 @@ static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}
- if (!aead_ssl3_ensure_cipher_init(ssl3_ctx, 1)) {
- return 0;
- }
-
/* Compute the MAC. This must be first in case the operation is being done
* in-place. */
uint8_t mac[EVP_MAX_MD_SIZE];
@@ -257,6 +215,12 @@ static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *ad, size_t ad_len) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
+ if (ssl3_ctx->cipher_ctx.encrypt) {
+ /* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_INVALID_OPERATION);
+ return 0;
+ }
+
size_t mac_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
if (in_len < mac_len) {
OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_BAD_DECRYPT);
@@ -286,10 +250,6 @@ static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}
- if (!aead_ssl3_ensure_cipher_init(ssl3_ctx, 0)) {
- return 0;
- }
-
/* Decrypt to get the plaintext + MAC + padding. */
size_t total = 0;
int len;
@@ -337,31 +297,46 @@ static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 1;
}
+static int aead_ssl3_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) {
+ AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
+ if (EVP_CIPHER_CTX_cipher(&ssl3_ctx->cipher_ctx) != EVP_rc4()) {
+ return 0;
+ }
+
+ *out_key = (RC4_KEY*) ssl3_ctx->cipher_ctx.cipher_data;
+ return 1;
+}
+
static int aead_rc4_md5_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
- size_t key_len, size_t tag_len) {
- return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_md5());
+ size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5());
}
static int aead_rc4_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
- size_t key_len, size_t tag_len) {
- return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_sha1());
+ size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_sha1());
}
static int aead_aes_128_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
- size_t key_len, size_t tag_len) {
- return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
+ size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1());
}
static int aead_aes_256_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
- size_t key_len, size_t tag_len) {
- return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1());
}
static int aead_des_ede3_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx,
- const uint8_t *key, size_t key_len,
- size_t tag_len) {
- return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
+ const uint8_t *key, size_t key_len,
+ size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1());
}
@@ -370,10 +345,12 @@ static const EVP_AEAD aead_rc4_md5_ssl3 = {
0, /* nonce len */
MD5_DIGEST_LENGTH, /* overhead */
MD5_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_rc4_md5_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
aead_ssl3_open,
+ aead_ssl3_get_rc4_state,
};
static const EVP_AEAD aead_rc4_sha1_ssl3 = {
@@ -381,10 +358,12 @@ static const EVP_AEAD aead_rc4_sha1_ssl3 = {
0, /* nonce len */
SHA_DIGEST_LENGTH, /* overhead */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_rc4_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
aead_ssl3_open,
+ aead_ssl3_get_rc4_state,
};
static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = {
@@ -392,10 +371,12 @@ static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = {
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_128_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
aead_ssl3_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_256_cbc_sha1_ssl3 = {
@@ -403,10 +384,12 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_ssl3 = {
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_256_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
aead_ssl3_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_des_ede3_cbc_sha1_ssl3 = {
@@ -414,10 +397,12 @@ static const EVP_AEAD aead_des_ede3_cbc_sha1_ssl3 = {
0, /* nonce len */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_des_ede3_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
aead_ssl3_open,
+ NULL, /* get_rc4_state */
};
const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void) { return &aead_rc4_md5_ssl3; }
diff --git a/src/crypto/cipher/e_tls.c b/src/crypto/cipher/e_tls.c
index 8ac1aae..bed02cb 100644
--- a/src/crypto/cipher/e_tls.c
+++ b/src/crypto/cipher/e_tls.c
@@ -22,6 +22,7 @@
#include <openssl/hmac.h>
#include <openssl/mem.h>
#include <openssl/sha.h>
+#include <openssl/type_check.h>
#include "../crypto/internal.h"
#include "internal.h"
@@ -34,37 +35,26 @@ typedef struct {
* separately for the constant-time CBC code. */
uint8_t mac_key[EVP_MAX_MD_SIZE];
uint8_t mac_key_len;
- /* enc_key is the portion of the key used for the stream or block
- * cipher. It is retained separately to allow the EVP_CIPHER_CTX to be
- * initialized once the direction is known. */
- uint8_t enc_key[EVP_MAX_KEY_LENGTH];
- uint8_t enc_key_len;
- /* iv is the portion of the key used for the fixed IV. It is retained
- * separately to allow the EVP_CIPHER_CTX to be initialized once the direction
- * is known. */
- uint8_t iv[EVP_MAX_IV_LENGTH];
- uint8_t iv_len;
/* implicit_iv is one iff this is a pre-TLS-1.1 CBC cipher without an explicit
* IV. */
char implicit_iv;
- char initialized;
} AEAD_TLS_CTX;
+OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE < 256, mac_key_len_fits_in_uint8_t);
static void aead_tls_cleanup(EVP_AEAD_CTX *ctx) {
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
EVP_CIPHER_CTX_cleanup(&tls_ctx->cipher_ctx);
HMAC_CTX_cleanup(&tls_ctx->hmac_ctx);
OPENSSL_cleanse(&tls_ctx->mac_key, sizeof(tls_ctx->mac_key));
- OPENSSL_cleanse(&tls_ctx->enc_key, sizeof(tls_ctx->enc_key));
- OPENSSL_cleanse(&tls_ctx->iv, sizeof(tls_ctx->iv));
OPENSSL_free(tls_ctx);
ctx->aead_state = NULL;
}
static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
- size_t tag_len, const EVP_CIPHER *cipher,
- const EVP_MD *md, char implicit_iv) {
+ size_t tag_len, enum evp_aead_direction_t dir,
+ const EVP_CIPHER *cipher, const EVP_MD *md,
+ char implicit_iv) {
if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
tag_len != EVP_MD_size(md)) {
OPENSSL_PUT_ERROR(CIPHER, aead_tls_init, CIPHER_R_UNSUPPORTED_TAG_SIZE);
@@ -78,11 +68,8 @@ static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
size_t mac_key_len = EVP_MD_size(md);
size_t enc_key_len = EVP_CIPHER_key_length(cipher);
- size_t iv_len = implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0;
- assert(mac_key_len + enc_key_len + iv_len == key_len);
- assert(mac_key_len < 256);
- assert(enc_key_len < 256);
- assert(iv_len < 256);
+ assert(mac_key_len + enc_key_len +
+ (implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == key_len);
/* Although EVP_rc4() is a variable-length cipher, the default key size is
* correct for TLS. */
@@ -93,19 +80,18 @@ static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
}
EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx);
HMAC_CTX_init(&tls_ctx->hmac_ctx);
+ assert(mac_key_len <= EVP_MAX_MD_SIZE);
memcpy(tls_ctx->mac_key, key, mac_key_len);
tls_ctx->mac_key_len = (uint8_t)mac_key_len;
- memcpy(tls_ctx->enc_key, &key[mac_key_len], enc_key_len);
- tls_ctx->enc_key_len = (uint8_t)enc_key_len;
- memcpy(tls_ctx->iv, &key[mac_key_len + enc_key_len], iv_len);
- tls_ctx->iv_len = (uint8_t)iv_len;
tls_ctx->implicit_iv = implicit_iv;
- tls_ctx->initialized = 0;
ctx->aead_state = tls_ctx;
- if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, NULL, NULL, 0) ||
+ if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len],
+ implicit_iv ? &key[mac_key_len + enc_key_len] : NULL,
+ dir == evp_aead_seal) ||
!HMAC_Init_ex(&tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) {
aead_tls_cleanup(ctx);
+ ctx->aead_state = NULL;
return 0;
}
EVP_CIPHER_CTX_set_padding(&tls_ctx->cipher_ctx, 0);
@@ -113,32 +99,6 @@ static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
return 1;
}
-/* aead_tls_ensure_cipher_init initializes |tls_ctx| for encryption (or
- * decryption, if |encrypt| is zero). If it has already been initialized, it
- * ensures the direction matches and fails otherwise. It returns one on success
- * and zero on failure.
- *
- * Note that, unlike normal AEADs, legacy TLS AEADs may not be used concurrently
- * due to this (and bulk-cipher-internal) statefulness. */
-static int aead_tls_ensure_cipher_init(AEAD_TLS_CTX *tls_ctx, int encrypt) {
- if (!tls_ctx->initialized) {
- /* Finish initializing the EVP_CIPHER_CTX now that the direction is
- * known. */
- if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, tls_ctx->enc_key,
- tls_ctx->implicit_iv ? tls_ctx->iv : NULL,
- encrypt)) {
- return 0;
- }
- tls_ctx->initialized = 1;
- } else if (tls_ctx->cipher_ctx.encrypt != encrypt) {
- /* Unlike a normal AEAD, using a TLS AEAD once freezes the direction. */
- OPENSSL_PUT_ERROR(CIPHER, aead_tls_ensure_cipher_init,
- CIPHER_R_INVALID_OPERATION);
- return 0;
- }
- return 1;
-}
-
static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
@@ -147,6 +107,13 @@ static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
size_t total = 0;
+ if (!tls_ctx->cipher_ctx.encrypt) {
+ /* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_seal, CIPHER_R_INVALID_OPERATION);
+ return 0;
+
+ }
+
if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
in_len > INT_MAX) {
/* EVP_CIPHER takes int as input. */
@@ -169,10 +136,6 @@ static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}
- if (!aead_tls_ensure_cipher_init(tls_ctx, 1)) {
- return 0;
- }
-
/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
* length for legacy ciphers. */
uint8_t ad_extra[2];
@@ -249,6 +212,13 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *ad, size_t ad_len) {
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
+ if (tls_ctx->cipher_ctx.encrypt) {
+ /* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_INVALID_OPERATION);
+ return 0;
+
+ }
+
if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) {
OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_BAD_DECRYPT);
return 0;
@@ -277,10 +247,6 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}
- if (!aead_tls_ensure_cipher_init(tls_ctx, 0)) {
- return 0;
- }
-
/* Configure the explicit IV. */
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
!tls_ctx->implicit_iv &&
@@ -394,83 +360,101 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
}
static int aead_rc4_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
- size_t key_len, size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_sha1(), 0);
+ size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_sha1(),
+ 0);
}
static int aead_aes_128_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
- size_t key_len, size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
+ size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1(), 0);
}
-static int aead_aes_128_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
- const uint8_t *key,
- size_t key_len,
- size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
+static int aead_aes_128_cbc_sha1_tls_implicit_iv_init(
+ EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1(), 1);
}
static int aead_aes_128_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
- size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
+ size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha256(), 0);
}
static int aead_aes_256_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
- size_t key_len, size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1(), 0);
}
-static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
- const uint8_t *key,
- size_t key_len,
- size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(
+ EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1(), 1);
}
static int aead_aes_256_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
- size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha256(), 0);
}
static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
- size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha384(), 0);
}
static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
- size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
+ size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1(), 0);
}
-static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
- const uint8_t *key,
- size_t key_len,
- size_t tag_len) {
- return aead_tls_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
+static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(
+ EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir) {
+ return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1(), 1);
}
+static int aead_rc4_sha1_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
+ const RC4_KEY **out_key) {
+ const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state;
+ if (EVP_CIPHER_CTX_cipher(&tls_ctx->cipher_ctx) != EVP_rc4()) {
+ return 0;
+ }
+
+ *out_key = (const RC4_KEY*) tls_ctx->cipher_ctx.cipher_data;
+ return 1;
+}
+
static const EVP_AEAD aead_rc4_sha1_tls = {
SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */
0, /* nonce len */
SHA_DIGEST_LENGTH, /* overhead */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_rc4_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ aead_rc4_sha1_tls_get_rc4_state, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
@@ -478,10 +462,12 @@ static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
16, /* nonce len (IV) */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_128_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_128_cbc_sha1_tls_implicit_iv = {
@@ -489,10 +475,12 @@ static const EVP_AEAD aead_aes_128_cbc_sha1_tls_implicit_iv = {
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_128_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_128_cbc_sha256_tls = {
@@ -500,10 +488,12 @@ static const EVP_AEAD aead_aes_128_cbc_sha256_tls = {
16, /* nonce len (IV) */
16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_128_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_256_cbc_sha1_tls = {
@@ -511,10 +501,12 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_tls = {
16, /* nonce len (IV) */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_256_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = {
@@ -522,10 +514,12 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = {
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_256_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_256_cbc_sha256_tls = {
@@ -533,10 +527,12 @@ static const EVP_AEAD aead_aes_256_cbc_sha256_tls = {
16, /* nonce len (IV) */
16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_256_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_aes_256_cbc_sha384_tls = {
@@ -544,10 +540,12 @@ static const EVP_AEAD aead_aes_256_cbc_sha384_tls = {
16, /* nonce len (IV) */
16 + SHA384_DIGEST_LENGTH, /* overhead (padding + SHA384) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_aes_256_cbc_sha384_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = {
@@ -555,10 +553,12 @@ static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = {
8, /* nonce len (IV) */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_des_ede3_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
static const EVP_AEAD aead_des_ede3_cbc_sha1_tls_implicit_iv = {
@@ -566,10 +566,12 @@ static const EVP_AEAD aead_des_ede3_cbc_sha1_tls_implicit_iv = {
0, /* nonce len */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ NULL, /* init */
aead_des_ede3_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_seal,
aead_tls_open,
+ NULL, /* get_rc4_state */
};
const EVP_AEAD *EVP_aead_rc4_sha1_tls(void) { return &aead_rc4_sha1_tls; }
diff --git a/src/crypto/cipher/internal.h b/src/crypto/cipher/internal.h
index bc1e2de..605b8cb 100644
--- a/src/crypto/cipher/internal.h
+++ b/src/crypto/cipher/internal.h
@@ -59,7 +59,7 @@
#include <openssl/base.h>
-#include <openssl/asn1t.h>
+#include <openssl/aead.h>
#if defined(__cplusplus)
extern "C" {
@@ -79,8 +79,13 @@ struct evp_aead_st {
uint8_t overhead;
uint8_t max_tag_len;
+ /* init initialises an |evp_aead_ctx_st|. If this call returns zero then
+ * |cleanup| will not be called for that context. */
int (*init)(struct evp_aead_ctx_st *, const uint8_t *key,
size_t key_len, size_t tag_len);
+ int (*init_with_direction)(struct evp_aead_ctx_st *, const uint8_t *key,
+ size_t key_len, size_t tag_len,
+ enum evp_aead_direction_t dir);
void (*cleanup)(struct evp_aead_ctx_st *);
int (*seal)(const struct evp_aead_ctx_st *ctx, uint8_t *out,
@@ -92,6 +97,9 @@ struct evp_aead_st {
size_t *out_len, size_t max_out_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len);
+
+ int (*get_rc4_state)(const struct evp_aead_ctx_st *ctx,
+ const RC4_KEY **out_key);
};
diff --git a/src/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt b/src/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt
new file mode 100644
index 0000000..d4803a0
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_ctr_hmac_sha256.txt
@@ -0,0 +1,336 @@
+KEY: 067b841a2540cb467b75f2188f5da4b5aeb7e0e44582a2b668b5b1ff39e21c4e65745470fb1be1aa909c62fabcf0e6ac
+NONCE: 10e0ecb00da5345127407150
+IN:
+AD:
+CT:
+TAG: a82a891565e466957ad5a499d45b579d31acaf582f54d518f8f9c128936dac4c
+
+KEY: c9d9ef2c808c3f8b22f659c12147104b08cec2390a84f0c4b887ca4c247c8c9dd45e72f48b30b67a8545750387232344
+NONCE: 58bddf96158a3a588bf3ec05
+IN:
+AD: 5d
+CT:
+TAG: 3580c1601d1c9a5b1595d3dee35b0cd9e1b115d8b0abee557b2c207b8d0df5ee
+
+KEY: f755dc6786e21f39b595389a51d36673e1ffb94ffc066c03873eb31839be6fa319fd31c8bea29f03ff28831861e60b6e
+NONCE: bd6c80797f1f4c563b06fd3b
+IN:
+AD: 78d88005136e312639572343a2d0daf7483d8235291ee3ac002469456b075243dc03380c387030d546c2b1
+CT:
+TAG: dede80d810fc449a769c79a5ecd2c0d68e9e0fae567781e623ab2098c88d8a86
+
+KEY: 43a0a28fef8b89b8fb0f76de01d802935ad561e27ca9c9fa629347be676a6af758501b6a652f369045da5fef751b56bb
+NONCE: 0f6472f1e589c16ca5ad45b2
+IN:
+AD: 78e4eafccfc87631f0314c442ba4c07bca36f996a5b3408f9e445d6009a87ded16b33a4af9537a4619cab70d
+CT:
+TAG: 11fa62dd8374aabe728ebf7e9aa1c02cf8f2dbc29f9aaf1940313f0b7c3e0301
+
+KEY: acf8e5f1bd64e6289370650b5b3fd773320025c8b229fd335d9461768cd0a17b4bcc946919932efdc9fc84a7f50768bf
+NONCE: 1aecfc90d28bcdcc5a8e3578
+IN:
+AD: 6daedbdc69133b56f6a8f098f9f70cdb7e129e51115df385a6d86204a53412cd999cf2e69f45e168efed4742b6
+CT:
+TAG: fbe0511ba0ec5709def9966a9b05facf171cddd81ee2cd56e7afc867af465f31
+
+KEY: 2773c92e6cddc9a5e5dcaf3893080fd2153f009d807df0b175c76615645f2087539e299d8411b27badb749a9845c5e29
+NONCE: 6d04ed129299651aec0465f8
+IN:
+AD: 44219577e361a7a4681172d120a2d653a53ec74bc487ccde4954835943bca413d55c65dc665310148654d8c1e2e6bc2f06ec344473120ad1f95739b993a57f9ec0b3299cc088f385894fff876fc2ce8ce6b77ca253f177ba615101e84e17ad0e60704cff195dcd50eb48c77de409797e0b1c8c4c5b9215a4a0399954a008267b
+CT:
+TAG: 6ab61ac4493e58e48d071d994a000f1c1f498d22f83c8d2af56b03c155afc57e
+
+KEY: 23189bf23bc4b734410d1c7ae321c42e144a25347a8029bb925e3d8ac1b92f4eb97227c1dece86ae9dea7d127eb33f9b
+NONCE: 30681944cd5d78f46d36ed8a
+IN: 59
+AD:
+CT: 92
+TAG: 986aa8438da3cf4a98f478f90d24908c6a4e848f299873e649b256f5499d89d9
+
+KEY: 463d1148325c5f57af670877068a78203571b8b19f40e9f0373156b7448ab315df86c77d7c85ba6e54b9bc329399f687
+NONCE: cc9d015a4b5a888b36b14d05
+IN: 28
+AD: 6a
+CT: 05
+TAG: f66e8dc794b142944fa46d5c04a3e3fe00291668374846d763f2beeffd4ca4a0
+
+KEY: 937eaab44e7c7d2cd5bbb053c12e6255e0aaa42cbe7d83025b7a2887eff8f098d019c80af849b0ed7da54a5ba5b39200
+NONCE: 2b160d24df579836e1572ea2
+IN: 9a
+AD: 35841a33ba3a6ed3d89a1f76d06c61613d09834847e5a41f8616748e30c14335e5baa43d49fceaf85aeb22
+CT: 80
+TAG: 5e5799c147be0329dbcabf7ecdba6ac595ebc2d06b9d757426fbb31e8b39f62a
+
+KEY: 68a746f382fcc11c02af7b352b9d710c137a9f59bc5886dc374ca88cdc01b86fe5678fde16cfa846846539f67a429276
+NONCE: b94346c033ac1a3d709c4f09
+IN: ad
+AD: ad61c9168debf9974e19759088944e888346aff99f3e2e4522549c8ae332a0f41922972fb7c1d5ff24e7ae4b
+CT: 46
+TAG: 62ae92ff64710a9f260da2562e246356e9d749c3584fb9f40d9572307ccbbd31
+
+KEY: 6622579d1d6350fd5dff432b69d172cc51f99bdaff50b0a1c0f4cda8d5904581ba8657ba61c6936407243d7fb64b00da
+NONCE: a880caa7157a13540d2b724f
+IN: 2a
+AD: 95a23eafcff892deecaf093109d30290d819851ad5c91061510e54baa2b039b114c815da20f0e3ba2ba4875bdd
+CT: ce
+TAG: 33f09666f9fd1d92f137d9f3f7092b47b2bd71a7e3139dcd19a803a6b17f2a3a
+
+KEY: 91ce9dd87c7d11d2c4da41863b6851c40fba786a612e0fbf0d1956a71286dfc61fa10bf7d148cecd72b6ceeb82b68d3f
+NONCE: a50dc3d8fd63d3076cc70ff6
+IN: da
+AD: 9ce8e1a777c159ec775abbd67d85e84f3550c3296e848dec18b61bbd713a98a033805bfe6e2f2a011dd7fd754708e524168142aeee579cae19c7eab78fa7c42fa335f0c725baf556160beef9e4afd1050a2c8813be6bd14cc6982116d0229d53e9b4de923abf6ba99bdffe1d5f21748ae74caddb077d9f7488b394436222beca
+CT: 2b
+TAG: 1541cd745bc0259dd72a212474f5c7b8c121dd0289d674e5ba8d56a220d1f1d0
+
+KEY: 1ad577d3b47e3fff8528e336a43a7ffef72f811e05b5c69ccfe777b10f29061e289178e394a1c87ba483c7f98ea5431d
+NONCE: 1fcaa4757a9e48ed2cb3be62
+IN: 46d30dac550103006c292a9ac05d31
+AD:
+CT: 37616eba30c55595fa0ad5d50f91ca
+TAG: 5c3ac4010f75adf90f81e775b07ab939e7551a9b8e0486ba33766728ed498245
+
+KEY: 6df310dc1847b42c68e50b03d154b73d7f3823354b32759c5369bce1a1b4cd63ccdb911c2dc792acf84b8b8f3fdfb89d
+NONCE: 92e6759a31dd556ff9124d73
+IN: 6daba76658db642209e276ff7c8d46
+AD: 32
+CT: ce1814c03037078b6be3252460af48
+TAG: 46e61913f2a1ff6e77faade9a7cd37a82eff3ebec4276fbddff9266b9c9bd873
+
+KEY: f848c2300995f5c98dcd0db24574d7c61459ca64c084421c6ad156e80e398904417ee745245ddae91be20fb07e66bdb6
+NONCE: 3b177e11063445717f417d14
+IN: bbf225131c821a6a60817cc65bf699
+AD: 4c5ab4fdbe0018344629349feed5d8c3ae0c5b64f2b093576a2aaa1225e7a50eca01a9962c9b4f8fc5c12a
+CT: 1538957e78f3ab0fed77906153d715
+TAG: 2c7760d47407ad7b0d5b85fa4967eaa7b6c0bb6eb16619adde7a191abfdf3da3
+
+KEY: d406cac07630ce2c071732a0ec95f55123486d2677465768dc7db13f90902cf172f92e19f57f5cf7c68cd7bde7ee4b4b
+NONCE: 766aede0120b634a4be6fa12
+IN: 3804d40090a38d4c97a5fff631068c
+AD: 7707b7d0f266284e84c2ecdd5a18832650c3e27d66697616c9e9bb2f8a09a3295de0119582ca3614b9608548
+CT: 91e96462a5dfbe8b7af201158a36dc
+TAG: 56623e5813070a0e2f5184aed83b9863301ca02e3108f7afc478d48305e397f8
+
+KEY: 42bb22a317ed9f9df8119746e9a1257217e5b0144051ca56f39587021d969bc0acc02795f3bd201031e8c05af08ad079
+NONCE: 0a9f6bace71a1ab21f4917df
+IN: 013f7b8c75307158f4f300450e7a78
+AD: cd95a649ae215fe73442a6991e157232cbcabecff6042b87d41557e35b97606d606c3ded54f5d3db7aa2773f67
+CT: e588dbcecbdb7667dccf7fe34f8387
+TAG: b04461748109ed9068c7e9c0446528ef09b01613c3b3aa1ffeed6685ebb550f5
+
+KEY: e1cfcbaba3a04b5108ce2a87099a6aae936ee38acd92b7e6b7df0e3bcb9ad18fc579b5d470ef3e04c23459f509852458
+NONCE: 112dd267174bcd81e6fbd924
+IN: 288a1e44b406aebec7b418674f81e7
+AD: 7809d8011c5a963df14fb8981e874119c60b7a9d897d13a05651759db5835deffdd991fbf98b9aa71c79e48bd701b228ba248b6bed874b02da7fcf28a04c38b81c0ff628846015258af30dbf28ea4f3283f664f888fca545f5fc57dccc4ad1dd476c52fba341182ecf783706c5c458bf0ee5ec83454afba78eb8b5ca17af88ec
+CT: 80f4e1012d76f6180ca00fd32c8fec
+TAG: 6de00bf2fd3c88ab34ca9390f7e559875e43e0f938303816a3a75a35729bc453
+
+KEY: 84172547d8608bd9e788a7bb60df2982963716e45f8e63f0c5033327d85c920c5e3776e314246b1694b739c39abfa29f
+NONCE: a3f1643bb504b7ce9e5b43c2
+IN: 7e76323eb13e64da9b240a57c95c855b
+AD:
+CT: 966487c18f025d67b42a04c30d3ff4c3
+TAG: 8bb03d893f0ce8ea4a6a47245bc7f20c72acf8caa466edd01365d0f74c929463
+
+KEY: 02dee8f2e63b37fe3cbae9101fed0946e05e5090510bef3324a82e3f27456a45ab1b6cdeddb1fe515ad07aefeee6ccbc
+NONCE: 64723d21365d62926d5c2262
+IN: 4f1f132c50a01ad48882ce88655b33f7
+AD: d8
+CT: b102082e14cd9ecc0895f7a6f08ab522
+TAG: 2c09651c1a51cb8a375746236fe258a36e725936ccedbc4dfafee6c3084a4716
+
+KEY: 5db57cf6301bab815d38879b35c9db72fd40ac576d259ad5074d0828364050554e9fc08335b5f2bf066b09e50fbe6ba4
+NONCE: 36e5340d844de213c312177a
+IN: 41a6e910b14388740ea351eb1df980c9
+AD: 8316a6b9b155b2de5e724f7593ecdcee442eaef7b9ad204eda4744a5e648c2dd84f48ee81397e485953465
+CT: ee21d4d47042415ca27d2ecb11b13d79
+TAG: 5015da5a3339389d39d0fcafb56ef4005b342e69ba47930e84408d33aadf5f2a
+
+KEY: a493dd6de6fd6584599096442dd9345f6f2d8fc2d426c78eee2b992b4071aba4ce463f3ca293c84b2faf3e8644b6ec25
+NONCE: 4f9be6f788ee960adc650d86
+IN: 4de6e244251091cf13762d20685e9085
+AD: d15da312b7522c18384acdbf6348b5e105557f1790a6a203a65acd73397524681666743f3145048775ad84e3
+CT: bb1296457daa39d889c8f986938d6a39
+TAG: b93548cea90c34d03d6f5683ae2cc78814531b803d42cfe57623fd4bdc8f084c
+
+KEY: 8cc59ebe2c7375a70915c48d2978a1f720bc0aa2775ce9189ae7b3d5dda9a81e56cde0e0a29939599409b71f0b65f346
+NONCE: b0ab041f37ea1e594f1eddb3
+IN: cd0aeaf6806cb99e6bc1c8c5d830de8c
+AD: 8f4b5a9609df757826dbe7e51bb6a2c6f45f601263cf668836193513cf008ab6b36a7d5447039f1268821ec37e
+CT: 5d5375b9d9cff6d0c1dbd14221509a0d
+TAG: d8850bbc838e068b817c24d018f8f1e1cb8aac0a68392a700f48099f81b6c37c
+
+KEY: f3e9c507478d3f99dbf3e2421e45929b096ab3f3d4aa4ef9c338c5a1a2425c9936b7df602502d33cbafcf781350da77e
+NONCE: d4872a30c9d1fa9001a25afe
+IN: 25e05ea69a956b12a9be4ef03ae9d30c
+AD: 8b346c20e7c64b805d9c8d325829201753069c60b3f221f31474f55cb20315373ccd7c2a8f215e9efc407ae91b05d8b6d693a3780fdd65d7715cdded86c3d6204055812f3fce897f829d1df9ffaaf48885291701ac1765090c383162dd13d6bac88baa0cb2d748363bbb79843a1594ec6d8778854a63b7c9ffeb6d1fb17e90f1
+CT: 61325c7e0d29e9ad50b9c0fec02d7ef4
+TAG: 4b2d0caece46ce2496445883c03234e900189c22b54390b399d78ee4ebfbb7d4
+
+KEY: 3d9b651e65e9239c9e33aafb091b348161ab797901fd0468aedd014e4d5683c8f3f54f20ea6bb07bb25dd258df7bcd5e
+NONCE: 32bcf856a14437114e7814cc
+IN: 08a667c2923f87a7db6502478d32280bdc
+AD:
+CT: 5e8e02cc91c732356bb9f1fc599426a379
+TAG: 5449e878d558beff4bc7dfbb5f0195444705cfb259773b4faec524fbaca37ea0
+
+KEY: 2124cedb5f3f2558f8b9a2304a29c0df6102333cb4aa10625aa82cd76ab645c73f3b7cbf7c96cacdcb9e0b738e40c042
+NONCE: 7ae419446a3a105beb2fbcc5
+IN: a305dc4a2e50cc8e7a65a4b10b73849636
+AD: 70
+CT: fcaea620f7e9ed1337214c4b432d9869d2
+TAG: bfc739c8504a4d9033ab1915f46c1bf65c5382fe9ed1c134026ba32c63ca131e
+
+KEY: b027feb1aced8fb3af27a9fd7f531c30991ec1abd9f230a3e5d6ee9fc6a77747013f8e14dcdbd07b0083d0ce23dfa711
+NONCE: a30a6520f933ff5265e6e305
+IN: a705f842d542cb6957fbce21854755c6dc
+AD: 447bdaf34dfab9cc3dd7777ebaf80077f391093bac9817bf02ad98db9d3f271282ecaf0ff19652f92076d1
+CT: 3ddcb07c121b498f1abb73bedb527d4df4
+TAG: 55957a0e884dea22d6ace10e5936cdac891f5b54225349ede5c44715f1064b5e
+
+KEY: ffefb7770a7cf125395703985823f3e926f3722ca0764518fd2b8996577bec03648c8d542af1c6e36b51174b0ba88316
+NONCE: 4c31394b4b24f6251a839891
+IN: f026a1d352c37b204c6c1138abee9a9a75
+AD: 1e7c0f71a3aacd87ea785521ea31f93b1efd0bdf97952e0b84ecd50c706806deffc19caea312b5a9988454d2
+CT: 23c8bae37db93ed9f55f2903e04b7c6a8e
+TAG: 89d0a7e7d921dea5bb54c28e79b612688e42506aa69b141de830c8d63bdefcee
+
+KEY: 453cf5e4f48ce5a961c94af0e1639c156965970f561ac17fe08d5b75975abe3db87412640972e463290800666be80441
+NONCE: b3e3f9708a86c7cdf139e496
+IN: 53f1b11de497cc6ecb411a777dc3d60197
+AD: afe29e074dcce850ac6640230e6b9f66a64587c5fbe8679144e065d3b1700c721833ba8f918e926c9142f5f362
+CT: 15d5f597be46a19566a72c5e843b77f70c
+TAG: a561c3375c096a116a721e9404e555a2deaf3f677a8611694281663274708f58
+
+KEY: 3d497f81d0652d475bcd85cf53bda13f79ef0afeaec09dd679a6e5ea58f87ba6576269f836096d5ac034594b17073331
+NONCE: 3fb1664830821e2b524890c8
+IN: bd75c313f5c8f6007a2185bc39d0af01bb
+AD: 50744ed959e2b8ba5b5f4807e2997ea0b96ebfcdeaa1c6b33853219844592e82ad67abf6ccbb272cfdba6a3e45c07fec4d4a0ebe4235f11d916771a764d9a129d39f6b84f0b5fb4cdf789ca2f5ea306b25d047a9b1a1e2e90905b6fba472e70b2fa25c96602cfa0031f31c68954d7487507081b8e70f8aa1342cb8b4a98ce9c2
+CT: abe3869ac43fd8b429ee8b8539c970bc86
+TAG: 33fcd301c2bf624bccb92a986c2dd5f2ecafc32649ff550eb5312fc81cbce46e
+
+KEY: 353c3e9f87b40fc0281869c68d9d9bee5c95771dd79998c059bc5ceda71f139fe447cfdf340e9eac57f232b9d230e45d
+NONCE: cc7a4b46b02f4e7f96fd34e3
+IN: 44bcb61332930f606276268ddbf3287bcaedb5b25704489cbee63ec839d7a69533dbfb6e95fe5b4694eb485beb1437f0777774868ecf45c8a5b3edafa1d62a
+AD:
+CT: d038d67b8b690519fafa7467c9fb94135f9bf0bcd8247cd2c30da62ddf37a6d9a3a9bdcf8ec081fb4469c0fc2798e2e30afede7cda384438fd01e5d672dcb8
+TAG: db2c685a59cdf304c1fb57b66966a5ca1cc3536fe21eb1113c25868428640c7d
+
+KEY: 3b3786e38e110ec0c8b05fbdb3d9b6d117d1ebcdc0e7d942249fea6baafa31fe5caac227979fc833b104641e8e9ed01e
+NONCE: 53bf31912a3ededc01c91f84
+IN: 6de5890028382aafb186042864c5cca1a77ff80ba4f7f0942dcffa1579711093fb652c8d475dfca81a976be8ca77eb9c7a6b49dca1425610c945bf404ba65b
+AD: a9
+CT: 886939354fa117139f5e077baa186825ee7e2955c3a74f88af3a86b260ee9f9959a90409e7d602e36cea31e606aeaa8b9229e28f7fa58ace6fd217e5cce1e7
+TAG: 91a769003ec900dbb40ea9c9b959882d822421b510ba85ca826bc4af3b5c42e0
+
+KEY: 5a75c97f3583983bbc5eee4a882b766a6708d798a46f71e63b7509af69afd7cf86f9b42df04b626940914007078a8b9b
+NONCE: 426e8bcbcffb6b425706dae0
+IN: c24fa29a66197cad518c5a1a76abd9446a8f24c2dd81e953bfc5c00544c119d67986781a1c754224af234b0ec5e44e78610a4420eb78c283e9a56637c35c24
+AD: 6376835513967e4ccaff9a0c56b4d27a2bd0d013cd54abf95fe9a162d036af285ebc9567a16ed5abfa69aa
+CT: bc4daeef3ccdf9abdaa75591781685eee3fd7825bfe63132817a7e0f93817f22bfca30ed775a773f5bb290aac3a381a01085e861cab7b9fe4c5143138e17a5
+TAG: 79c779bfcb974ad9a8ac88dce5027df5691a3a1163a5d5893b4cdb1663b17aa1
+
+KEY: d1b301c029fe3b81e4b97e08e84dbc03b138f422161c0e74ccbda3172c034b99610f09a9e611f0e9a3ca40af4fcb3c56
+NONCE: 4032c79eb3ee4b63e44fa932
+IN: 71bcf5a5198787b85a66221c22e7bdb9d038dd3e10000555ec9271e54bfefc460ef4e71729ff7ae52859015b49f45df89ddf183fe1e19de3acb032dbaa4d57
+AD: f1cd18ff1e5ad2b65de41e083b5175966625ebebb3031e1027761e407dae4e8e193ffe7dea52ff61147f1b4e
+CT: 7c521a703b7d1cbd086bdc316d4f2ff0852c462eeaa1d7a586c561354be9ed412d9d9bd1f78cc85468750f1af09b7b17dc1ee84c926760d63504cd3a1dfa3a
+TAG: 831f3552890d997f0a8f2d832b6e92e26f6e865424699f0364a82d86ab7734d0
+
+KEY: fdd24bf37b36666a4f641115581ab4bd6b896dd3017006031b3675beed33f21a314363e3a07bbbf4359d9ac02eec847f
+NONCE: 7767cff1a096a9f7d8a9b32c
+IN: e62b7695dd41baf49d1b356e64c6d5504784380b75724b86f5f3185d1a530664aea0e5f9aeef347e1ea4754acaa7f3c233638db234c0e93db02e0bf988e7ab
+AD: 2d650f3daed2564b0df86fa23ed0343634663adfae2c422f80f9d5674bbb63e824f01ad3994834f889133bbc0e
+CT: a51f50a6ce77a22ec472bc18c37d08fb28e77efe55065b600e3edbd9ac97f0fd0eec93cd312ec7ef886cb04e1849526f0a38b14d862bcd578b99bf9a007c2e
+TAG: 89d83264364c9c84ba705e5549abcd496abed3900f65e3daa012275fed18a7da
+
+KEY: 0f88e2d00d2c4bd682f1591ea5f4c1a1090180e1195809cb363b27c863360a85b27814e6a724effa44f298430d6c9628
+NONCE: 6e2e62ecb2aa47c7e5921d25
+IN: 91efc710a57adb57017725cfa26d17d3e2993c5ee66942ca42e770a83763e9df8a455bd408dc1e2661cf301f1dd669cd6d5b4d92a886be0f54527779bae8f9
+AD: d060cbe84271e85f25a3dcb6dbf299551f0dcd5783e3df80468636e491c0100f3ec8316f24240482a88bc430a398b0ecaee5c48a274ffb2d835e200bc39ec0aa86a1c90c9e2dcb4217595d48826a81de90eb949846a33fc26bf8886ca0554e1b8f12cbeee36e65e33cbbf610c2d24264619fa93c44c88e0e3d9d368fdece461b
+CT: 10d99b98ed67d85a44fa57e706a8b028c61ef17f35f6713613d158cad90e826f90ef036a2190ba123f9b68b352ca94fbebf8ea947e569ad45f00e6a36975f8
+TAG: e345bebcc4a8ac01528bc5f317e5c378236b292c2baab6ae8654245da35d90d6
+
+KEY: 1ccec52c77239bdf6ca50e5b702943b23015d08cb1d9bac592b3dec4c96be904110713e52e114a8bc294df26530a758a
+NONCE: 38554b7c40027afe9721e14a
+IN: dac91fcdb3768df8d5ae9ddba1fe5917c084a5d9e6b14eee9a609cab2da34ec9f95cf2d10fff77108477e694c76f362e29b9a9287d8b190a748ed0a929967ff8
+AD:
+CT: e6bcb38b3bfd0b428a14bb3aca01a4a9e54b0853f10bd7750f5bb58d0e7dd18006f8929d7d862e5d6601ef63be8442334b4d51a99219cfedaa31f7ab19028459
+TAG: c4f05d9415840c2325dabbcd12dbeda31e47637437514c606dedfb8ce622edd0
+
+KEY: c82ad4c6f248bc51d3a51b958ecc2460a3c64d669f6c485c2309d26abb3fa84644a0d8c28da8091f90184b53cd556413
+NONCE: 35a29938fb7a31225b08d0e4
+IN: bb0045cec5587e50b148b140b6969612425243ed1412e812aa9f4b471ed34ced6dfa9e0acf3e31455893e4ee7e66b4661c6e1f80b7d6f1159c11387ce579b80f
+AD: 12
+CT: 5f1854fc2fb11fd721755445a1efa5a28607a725ad71cda9a3464860a6a0efe3f58727c0e0cd315f867611232abd72034dfc2b9deace8cf6cb507b1cd4032b59
+TAG: e40429ca19a88da73a7654d7ed8e0621ac2e504b0245615e262ac70bd05a3f47
+
+KEY: b01bec74fe97e5af7db2a0b1432f8b4c069447d2b56dc2668371387f753b03465412213999d2394a4b79873db06c590a
+NONCE: fec7de97d54dec8d36c9f253
+IN: 88ab078d03ffacd128edbceea7ace2e6465f4076097445a5db7f0e61ed817b6e24f22874489049bee0c58d0aa2b42b4db0bbef6ec88d032da9c82ebef57c424d
+AD: cf0ceb3e80a76d1a75f6e070f5d3fee1cd1e2699434f96e7cb3adce12d4a3148dd433b08c68b9d66962f24
+CT: 8aa3c7478b0cd86fa30870957fb5307345f89346a869d508da9d3a4fe36fb3d6a9b0c3c1bc2d44c8ea31ec028012098d6032085af0b54603dc2fa65ff091fdd6
+TAG: acb670172ec3754064b366566bdccf5056eae132e2041f1a285c5883e7eff4f3
+
+KEY: 699a94f6e6eb457b186af58c25118fcea81c8f0ad265e7c16bd6cdca15c9db64bb9a537580ca0474a4b4d54d47412d88
+NONCE: ac3fb6525f4357d831529407
+IN: a7300aa94f3d357cdb272f0a739979e08aad9551dd3bfcd0b5aca6a0972a71b502639e79e1b9e0d22db2f3220b982800d9cebbac3d10d9bf86ea25d3d417fc57
+AD: 19c3d34bb9d57d0f63f14bdd3da06a43a5afe6a8c505f038cb403515876a2765c2d61aa7e4c84e11c999b81d
+CT: 8b472f1069ace78172611369b03073f751e5206dcd2ce3b45c431095f303e70c59bfad3af8006e66e4a68f8fa2ffa534bd76bdef089d07dd38988cbf723393c6
+TAG: 8e7c3c2c41b1117928ca1cd0cd48c25c319c18e009804c007d1aab0967c0d0d4
+
+KEY: f3a7b8c2a39531d5fb3c97bc9224168aa835973f48243d6f046d00937ed428e5d672e22af26e734f0c24f989fe62621a
+NONCE: 65c61af60769672f0eeda005
+IN: 59667fceb2594e002c844a47d2b3935d2c99570b1639f0887fb082499e1d36f9699ff9ef53be3b4236136aa9e441abdc63dfe536e6fc9fa8f332baa1dad577ad
+AD: f79036742501f1ac19dbb2984e09cf5000bc4bc0424082376c307b8f1e5bf74dd29c802139d7ea93d55d336464
+CT: 9375a81f016c2dc59a8e99dc33fc0db7ef99ab2f9ade4b0ba000a614ff2bd13bfbee2d4a2338109c98c1147edca6023cea43570adc503da98379326ace89d796
+TAG: f563869420699dfa0aa84751526bd75af1473bd88311001e49230b09b8ef2797
+
+KEY: 27611a8f11cb57d08648ec816b5f3c45882dae394200cdfc803d1a52bb03f225206574ea63b63423da6972bf5a994332
+NONCE: a7f617fe7a52dd76ee443dff
+IN: d6ccb950515a4a2de7c3cf5a73b568f32fe30567bb22b3b46feb7ef07205d3215a3d689b96d4b9dbaac5a5bd6ecac6ba50314b19b37179fff2557c869950e162
+AD: 777282a98b2f262ed9456fed3610a2028bcc4433eb8f028597d3bfa220bdb0c04882de03a276d0191cd1a125270ce1630c1b94e2ec0021ce5c494d2e0bdb8745e6e94a387cbb31a0898965174bcff8bba105f94dbf080059b49dee71c3194fefe679ef6c00065154ea809293b088c0c3f2ed7824aac72319a4c4ad85ea990844
+CT: 41eacc31aa3c3a282ae7638d48fc7541d2f129e4cb3455df7e60259be9a814c8e1642ea826ac1ec7ed1fcc216a6624e79845521e7a8b16702566f27f7a7f3317
+TAG: b959992feb7005410f9ea6963525e3d9244f038731ffab8da8c4ebc72489f17a
+
+KEY: 0d9322713cd132c339c38ec7a75862860de304c70486b89b0f587095c66bfd1abe56f0b34f9ca0dac577fd4262616600
+NONCE: 3298d02dd4eb85a98cb935e3
+IN: 5dfedb1d168fe262d35f78d797560b2634f71d40f438c21cdcb8e73cf9884c11570554f55a6abd23d0e7775a9ab385ae6c9bbd67f08d1aec57347a8fad5a4b8c7b042b03c25facbffc76f0b1ce2e6c07d427eaebe71255d661ac8e8bfe8867e2d947d496ce2318a601d0beed02426311ca678d036deb3b4c65b1f89bd644a410
+AD:
+CT: ff09fe27f12a87d5208bf246378ee0740e848262442b8b9c7670c8a73fe6732192cde43c1a1246743ed49e15ec63c87dc06eb3e0c92c1f286108b2c7e0754dcf1b9c3fc87efe3683289daabf2db71d8742061f93098788c3c6f26328b86e358507a03af296d2c29009562cad3763399e0e2b89ed440f756c16214c8ab7ddfb84
+TAG: 5076c80fc76c67d6e4f9b9d470cc184db62ea7da49cae44cb3ce9e46c2f2ca9e
+
+KEY: 2695671fe86f1658d8b01ec856fb4c9d09a0c51a1b994fc87a3f72bec12052537b7429f11f7eb4aef0b128302ec8f336
+NONCE: 9739e577595418c47b9c10b7
+IN: c723c39be334a0761db795076e81e3dd85e37a57258c7e0e10fe0f48dc31bd5e683430aa70531b7c8e3a904e49bec838e760d07afa9f86b2cf78ae90f612c4560632acb7ea2d89fb1fd5396d0337111c429cdba99c6a52e863e8603aac24a83302ebf86ae69a212cb938e12085cbf73a28f75e4422995a5ec8705b12d4aa8b6d
+AD: 31
+CT: 1569b20732ee6395e605217e1cb419ce57496ba6f6e889bdfa3c93575e969eb7a0410c7930b7ea146e88577376d84f0e824b62890eb84bfe768a1513a12c2958ad1835bc1eabe602cf40f7812c7dd7da955567242cd7512090fca685fdd7306bd98a908b09464961114abbdcd610c153637400a1f81825cfdf06505947fe54ee
+TAG: d07e14a62a32ef1933abc2127cc5bfc1e43bbca663e460409c6faa3a4ccf99f3
+
+KEY: 1785ef6e7016733dd1952b3268639f231e7afa973c0a3db8780b81084c67a1783200149a1ed849ca8b5c14c7b1798b4b
+NONCE: cdf48b73c3c8d8625e52fe11
+IN: 14002f17e056d7f5524537cee6c2061e2741c01a6f9a82e2cb1747887875860d51bebf8d9b63950a051f6b228ad7567227f8a45b9fa7c4ab47eab410125303defa7e3141bd9bc5bf4ed56550801ff3bfc2dfaaf499c192b1e18879b2f59e1230778132818df8f6ad8a3dce9a1d11c98075b8b4e560edd9b5ea180f0424ab3706
+AD: a35e86e22e9a3df65e4c08e5175b4216fa9895a1be6252de911cf98349841494617eefaa007759dad7f337
+CT: 99eae989435578cb57715a7457da31b807b8078a59c2332a0a866eee9da5188baed3f517b6808095f0067e9b4b91cc1424a464f0a09fc946adbe4135a17b0e8e545d2046f81cdfdb233aa3520797319c0884ccbade8235c32d195e7b802017f88ddd86fb630de19eb97f4bf91029c001fc8f1cd2189a8ee6c120e9f1682a8703
+TAG: 1848f0b163e7b0d270e2a0ced288ea6525697170aae15038f3dcbb4ea49ef843
+
+KEY: ba9aed2bfa90eaed9b27a697bb44c715c0209cae6b2c4ddffc684bcf07ab51b0e096dbcfa26c18fc24b63408317da567
+NONCE: 4b850d6bfa64520f1aa1e79e
+IN: 5bcc2ea4d729c84340c5ceb827f239578971c595e915f0bd9d49ed51d723f8d0e8362e69fd11466230bda0dad57ad724307edcc621ebde1e57fa91fee206d81d2bb6ead94b4a804f74b6cae979f66bdfa4ad93d107ccf114c59cd3d261aa6e2fc0dfbd0df5f7c18e80d0699cc1712abbefab5029e35549d2919d0f937d444051
+AD: f80c759062e9ed0ee597406aedbcda9a14261d66a9546f1c939d20cb1d0d0974fe7a9b33d8c93287a6a8d60a
+CT: dae4fc873d302c51e55910e67482bb80ac68e9bc6ef77cb3e57a31d85fe75f9071d0b64026ba16d0b68fa9c0b7e958cf7682bcd329c4174ea0e3f3f9d2e65d82aae1350a53ea7cdcf9ab848b85cd731751f0e2917628e5066f5b1ddebc7dbda5d2d37e46a7a7ee62bb49c4431af730f9cd3da4c1d0e5f8593d8c99803f781bee
+TAG: 58b42e9117fc8cc2ba5cff74b0d92e8b381a444fa837018b15e9514fc4319fb4
+
+KEY: 37235623acb0d650f905f106dc3bfe6fd83192e53056de8795ed8d20c6e58e5efd84584007ecb17de9e76b392e12fcd7
+NONCE: dc441f1c743a92c4b975c6b6
+IN: 960ceb8d80774bd88b7c5f17042ad2e4baac71b4021c548458cffcd9a049291cb0df93076c115b54f9af878745acebc6e8f04666d053b1ed980728043c4fe7f67b2bcb0341d8a4973ed126342f9add14279f8402cbbffcecfc847379dca8a68ba4f2f26141acfca7f3ef558dbaf04629f0f46e43246b19d875be452f14e7bf56
+AD: 32579218062560f15ff966932838460f99099782e79f1f8c41cd9f6eb59b4c2c3d2dae9cd199fe66d74c7a9940
+CT: 49ad8e24a31e90ab1f8dc37dc51dff0f93f1420e79eb108f90f800274a5aa573f64e274cd52f1dbfdee363e4f86e1457bfb8f87ce57aefd34c3a5a3a93db4ebde3f73a3b4c202c993903ab378ae71042ad238e94f400c7ac1891a9890b19d445eb1db60773a3ea165f7c4b2bb2071faaf588daebac7ce09ebfc88f4d9232d9ca
+TAG: 82f908b837a5768598982f860ecea16aee84427371c4de1f1314749b70ffc173
+
+KEY: e7fc36c9fe87a38f9bb4ca67723267e80e16bf39740eb1090234a473d68aed9c96fe2f96e539795eb042276aec5d7505
+NONCE: 83d768746d40dcd695e49ff4
+IN: e61f0e02a70249b62ec9a8fdbaf6622c9c6316599daff421f1b19815707b67587d196b7e1452c7d7609f108ea946675ac5d97ed215b92a451aa6a11717ab7819f84848151007f37e2cdc8aa99969c3d5652aeeb65fc21b621865f47f44eb2c528ee1142d11f513761a6bb2d169126503db5b263a410cadd2773ff931a032a885
+AD: 59114e9f21b380ae6068609ac36688e6aa7c2533cbfe07013ad1b6663bfa42e39f20e62b45c0faa256c1d33caa9f59b1e30d8502bb7148d051451b3d0265cb9fd0d82e4f4e0489ac606956762d8e7b70abd7eca413ddb708f119c342b3d0d5df673769d8df281656d909b68b6f6438edd60339fd84ff69918b6036ad12a0a588
+CT: 4f12807736c9ab32a2be2e00c9a0236394a8bcfcec6037e7582af462a73bf10aa73bd90e2bc24b97f7001ccf653574aea294bc7b30b77540f475e0e846ab78ffcfa1fef28058e540fea43d9017d4efa05c837611b2eacf0034f26cb7903eff7874973c6da7843892bfc676170a75f839e297dc7f04c74b40f4bda20a45b2a352
+TAG: 9b05aab44ba4d1451f14e087be626232ed11c4ed04081f0d4d47ab593fc619b1
+
diff --git a/src/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt b/src/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt
new file mode 100644
index 0000000..2a72e1c
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_ctr_hmac_sha256.txt
@@ -0,0 +1,336 @@
+KEY: a5060fecb0a738d8ff6dd50009a757c6e58db73228534d03f32c26baa1c209f402c3e03a6947c1d9421d63ce43f6df26d30ce783f5ed0d6b88edd389d9f92d8d
+NONCE: b52227e92203630a79ec7f5c
+IN:
+AD:
+CT:
+TAG: e61a28f5df7061b4236834d2034d2b62cb63c660b7de696c26b345e66b34d222
+
+KEY: d676047046bd5be9263ae39caaa0f688abb1bc67c083658894da6aeeff80b6d58ffc7ca1a1c88f49e629bf5544b2cc7669367202b158fce83fc4a4826dd90a7c
+NONCE: eabef87a00fd99ebb6ed6d25
+IN:
+AD: 83
+CT:
+TAG: 473cf728899cd5fdd54f18d6f934c3901f7ca118fc5ab2cbb837feefa7852a67
+
+KEY: 5eaef3b8e068fbb652bd37df4dfad6490095642cd49761a35476dffc2b5b5f75236d0351d96a9028660788893323a777ea8a2ac88bb5e500b334af02b1c2a648
+NONCE: 34d049342b9db5ffa039eac0
+IN:
+AD: 7578949699d44dec9188a7f7e14b0a23637cddb9107dbb1f8e2a968aad0443356d7eeceff4316ba7b2e8fe
+CT:
+TAG: 4d2612c21357638bada9290d2a272f10fb5f070337bf87bae396a1e7253633ae
+
+KEY: eb7b3d7eeb5f26010915a36837dc83da2bad07eba714566584bf1ce62fa9b61210b0ead7182bc28c8f0427699bf04786583fa32f3c3a8a6582cdc254930043bc
+NONCE: 3bee5ebcdfc72f4ab0023211
+IN:
+AD: efecb57e79a326c6b2ce0ae74d7656992a005fbb8da5a55b9595fc5348a5489ee2e69541ec0e8a727a560625
+CT:
+TAG: f457db1e274adabe5fc898fb1eb7c4a5a8e9a2b66f964d0958aa058c1f9e15ba
+
+KEY: 1c1abffa8a2667a8c1ab347860528162d316d58e3966050dc140fd360e6ff7c557520a8982aae97c5db5495d8951eaa485e1cac4cd8f448a13d071d759885474
+NONCE: 4fdce4e59bfdf5d9b57c78e9
+IN:
+AD: 55125cefc919379b3b4b2a24ee1794f44ac66fd99b8b68f98d4abd45ba50a5b76e5375d08abe3b8b8d3c576bc8
+CT:
+TAG: c021d2c73737e54ac6e7f61f9bb44818e5bdbf8d81d43842fd25a535790fafba
+
+KEY: 366cf53bc185473acf62610b74231e53aace84e9c5d6fbf71fc24db4f42956065d3eec01ecc72a6c89266565ff530075f4532c860e3192e866b41aee98c5c42a
+NONCE: 9ff54bd7b10f4fdfd8db76c7
+IN:
+AD: 853ef59ae873bf0bfe1465e9dd8c2cddfcf123d213ba4f599d984e4ea69d3c85a23508ec7941ca740a9157ca2a788e9b519291240b307d6c5a8c6860a96b4be698659d19e31ab0ac7ae6ba31dcd609c1db67ad580fe4422e42d368c3e93a56f2a087b0d587188462310c2ebe58ecfcf7178412223808eeb2eda76446168730fe
+CT:
+TAG: 12d869dc4bd4ac4ce9ed643cccda9e11a1ade65c76f7c1535fa4ec2bcc5eb4c3
+
+KEY: 147b41369bed390f0a9561586fd975474e3b3bbf7f7ebb7a35e5cc43b516c044dce93e154ac790a109709ac5299bb17b709a913d33fd57ebfef2b48ed66393b3
+NONCE: 85b81732d2863b41d2551763
+IN: 73
+AD:
+CT: bc
+TAG: 47fd81f6eed8d3c66afe06d788ffe40717847785f4b4c617d75a11171690a60c
+
+KEY: 9bf35c1194659c1da634eab6707c55b853c8f61d087187162e926adbae02f8bd4d15bae5b05865d0e2236d64715fc39f32e4e3679a0309396c37eab13d1c637b
+NONCE: 8da14a98ee741a5fce0de732
+IN: 10
+AD: 8e
+CT: 17
+TAG: b76af41002a946af4947f98f42a873b7da0871f482990a70bda8f005274ca179
+
+KEY: 0befac10caec674c9f23676d121f065dbcc8c91852dd5eb4e80c41076995a2138077592fec665954d21fd6787234d32d3d54bf9c220cf2bf018b374bde29926e
+NONCE: a96bfb49f3a136840a0e32ff
+IN: 59
+AD: 236adab55e1bb8a8db384c01bb2afd30ff35da71f955fb217b8305a45ee075e7f8d863d4c0e5dbe36e297c
+CT: ac
+TAG: 7bb634357e0835b02a0642352a834ff6598c2ded1af8e8ab60b9ef0641fe863d
+
+KEY: acc672aecf6f10119ee77070abbc2b4fade7e910efd1f93a5716161f88606469a49df05b40332b390d3ac289abfdf6bf7c37c033b1671082922d939139de0d42
+NONCE: af0f57b55f1a73794b3ce5cc
+IN: ee
+AD: f385a50ef027e532635878a4df0deb23369774be47c42f17cbd44925b668f628338ea5f8256c5ad8219c13cf
+CT: 71
+TAG: 13a5296075ef23216c2f2e83b940d24e8e1e6a01967af96599360f11499ac0a6
+
+KEY: 6195ef5ce3ee01188c48b04ce7a28b3ddd04b78711a6d1233121fc8ec3db3a7a0e496d1b6a416675b1e666b9a3df167efb8ade29e4f22fc77111f32ba8bd1ec2
+NONCE: 092070b2f8b65fcfe646f6bc
+IN: 26
+AD: 98526dba4437d88f657c0b7ce2a2be44ef4951711a40747a7d14b195e4c0eae97247256bba7dbd93d6a8f738c1
+CT: 83
+TAG: b6aad3f91a26a38245031d6a7eb97be0d386939d4536b2a27c90a2ddb891de73
+
+KEY: 40335487f9958dfc00b76ff06dfec162ae5c6be4e26918bd12e3f21760cb0bd364521a11f5bfae11dee989627525ab5295ee404bce476c280d13d238dea1bd40
+NONCE: ecf77c7c827a34efd8cdf79d
+IN: 34
+AD: f6e661254bf235c7d5b8ee330cb754087480dec5fe4c31dee65d1ab4479642101404bb563522937fb2e41d3aa8a4d269a222e6e0bcfd07ec4b29c1185f99fff7cb5bd2ca8c5b38742270e586c8db19138b446833f2ee07a11dae5b6a1a4c28657f3380e84bffe1bafeccad57d9cfea3da7f728119ec5bb18b79e002954f4379c
+CT: 5c
+TAG: f3420d4cecae2c1ad79d977abbe408045bd87525c0da2b93e0af3e6c53ba7d74
+
+KEY: bf32ef44c7ca9851f397e70df736d7e0e6243cfd875ebb81d76ad7612dbcfd084cab6b0d67c6a6e8b567c93fd0c3abb78ae121fdb3051a62ccfa045692d3453c
+NONCE: 46e0cc64d6e431c1efc2bd2d
+IN: 959348a8ad6912d7d6c8eae52f19b1
+AD:
+CT: 55e8cb6fd958f18b3c19451c5c79a7
+TAG: af09194071cb0ed4488d27e79700f938ce77386e5d772f9853b17b719f2b1ebc
+
+KEY: a6b5b8b051edf5cea0353ead88ea887fab048ef32f8303275e93d8f926da0d4b0e34b9447cf44fa70c24c9ab964380065398336bbb20be167fc6cd5e591ef50e
+NONCE: 371363612c4675a2e59ebd39
+IN: 443d16621b0cf9a12552216f9558ca
+AD: 32
+CT: b7f432eeda8e4b8a25f0445f17ca7c
+TAG: 649934922826febab4d59dfb52a7558e6d30d56e273602b98f3c55fd8e24f4da
+
+KEY: 075b75434269a3fcc57922ee8cc55b5bbe1b90516a3b71838ade73d41ed1d1f33ae1e0e86f88f6ed7e091cae3ccb05144b3ef239831554d6e79ff97c4d8f150e
+NONCE: 754d5c4ccbfb291133859de3
+IN: 62a151add825077c59459fbf82b708
+AD: c8db27487de71124a95eb6359270a8363908159200333b46ee74e2709b308878779686bd43c24e9ecabfc3
+CT: 2ffb9a9f65c9fe3daad13768ab56bf
+TAG: 4430a90fed7d4b5b2adf5a60d6854956be4feef497781ac7d864a04259e99516
+
+KEY: e787fdeca1095f2f2760a1c5e0f302e07d6b08de39ce31fe6a0db2f76e4626eb0968768ae04d37082c114573c307699707630b8c7ceef60abe3b7831d2adcd6e
+NONCE: 9dc9bcfe8b4e2ea059e349bb
+IN: 3ad57105144e544f95b82d485f80bb
+AD: 96bce5dcaf4a90f6638a7e30cfd840a1e8dbc60cb70ab9592803f8799f909cafe71a83c2d884e1e289cc61e7
+CT: e504109cdbf57b0e8a87080379e00d
+TAG: 1798a64b5261761ecd88f36eaf7f86ed3db62100aed20dc6e337bc93c459487e
+
+KEY: b43ab650bdd201cf05e0436afe89ac54867383f04c5ed2faea5db8e6784c720d905234f1f5443c550ca14edd8d697fa2d9e288aa58c9a337b30e6d41cfa56545
+NONCE: 4e3dd3efe527902b9de45a5f
+IN: e386663e249b241fb8249cfec33ac2
+AD: 3cf7a396e1bd034ea77a54ffca789f206f94263d90d98bf3e69cb42205fc5c95cfbd0481b0ec490ea447299159
+CT: 94aacf00092723e778d25ba78e9d27
+TAG: bd5fcf90b9532e7abfa858aed90d5170f08edcdd28ff2c673e0ab45b8c0a0f39
+
+KEY: b22a7c5bb38715025cd59cc0feed9ad8e51101200000168052b294fb1ead545a517dee636a7acd22b8283afb33d30adbe02c1c8557715eea7147f3d98a97cbb9
+NONCE: 3b4244c9ad9fedd3f10fdf7a
+IN: da79e1ed131856cec3250fde7bda4b
+AD: 4b77472ade3f06500169405b86a793d63cfa58f57bde0dd706f369b391142c2fa8a3e6345ccf0a9c29b2182f578e22f55c576f155a05be5e81997fbe06410034ecddd871e5ed94b5eeffc6dbd90a8e66449da01f8ef47d28a4a4bd253ffc427f868867c73b5c709b01732bd8035b1a23ff0a903def1eb136fc90d8b3c8279769
+CT: 5d8ad7abc047bfdf9d9cd0b0aaa53e
+TAG: 41d050d518d0e51ce16bc2920aa6c76eb8eabd4ed76373c59618c6354885f47a
+
+KEY: 04b3fd8126d65f851f47b3dea22cd6e32506f21effaa3e29820ac7825e01b51c5a2816f0298154f2d8addefa2fdc34c0635d4d6b80ad23eb320c4d4f2aa1de1c
+NONCE: fae1b1da40471dbdcec64d4e
+IN: 509f116ef7435b0640cf141d5b958aaf
+AD:
+CT: ecf553eba80e6dd1fae2eab24d772a89
+TAG: 11473566e80cff5d7421f65949c34301f34de378e91ad50928cf2caeadc466d4
+
+KEY: 413d154dadc7d8869e9e0f24b3320019a04b7a37620dd9e7aa40b5c08d70dea03c12ccf7faad7009e972680e81544b647650c6ff033f56e5bcdac9a35bd7f804
+NONCE: 6a4404adae3f4a7bd2bef95c
+IN: 3539fe02b75981fad4f8762772b3c11f
+AD: eb
+CT: 3f8a96905609a4ef1a95fdb87337503d
+TAG: 8ee076fd624d90e1f6336a92165e80408ca6f0e165b201547d351177c95e8d51
+
+KEY: ddc10df673e720c00f28fdfb69f1b8fba99696f23b6f29704a0114444cc0c8a6c8606e8d37fa95aabfd65b29c655678fcec50966c8758a3fb15332a1854a8eac
+NONCE: 06331613842b4af86c13f8a2
+IN: 55d74bcfc3d1cfc716c6e6b7153c6369
+AD: acc264344ae79959f9dd5130664273ba6f345c3fc7bc33c6c1ce33312bfbd5f181a3c7a24f15e7acf72ccf
+CT: 20650d9e846eb42854692d438b21d5e8
+TAG: 973857523e7ff600cf9bcfcc98403b34ab38d939a6d76716beac42678ca5f5bd
+
+KEY: be0c884db54cf761fc24ff3dd572362910dedacece5e1d93a916df277f923f78e7dcd908e60beb0043503c5b4877a9d962a7de37cacc7387a7553949b52894ec
+NONCE: 3f027a93e2716668c7634195
+IN: 1ba8f3a87ac6738167aac1491b602ddd
+AD: d06dd1b9360a68afa3de5d239b6d91d212c5c555567545a4f133bf5a3b0f26addb9379e1cc1cd690cd427c57
+CT: 3596cc50ae72db932dd83bbc8661641d
+TAG: 44a1834b1587d0f88e34137dcebbca059dfb8f65ddab18f338a8a30152167be0
+
+KEY: 2ee848726730c64332877a4f88ad7fb241a73b71fbee8eeb4d9d6485855ea32b487e03968e1a7b9e8ac8ab7fbd84257efbce0aa207aeefa67302d5847e0d9c05
+NONCE: 526b0a79b6359d133ad51011
+IN: a0c0477e8a9ebfd275b674ed33230d42
+AD: ded2f0f3f28aea28b17aa58d4b906c6a9b3078f97ffe95b7e161b0c3dbf66879bea7603a046da4945c802ac8b3
+CT: b1691c8275f12f7d9af85e71dde9dd5d
+TAG: 65a5742dcbc49295c4805387e0a15f986ae47e51add9389dfabb6468a6e83013
+
+KEY: f4a7c0e29ff510c034778e47bb30a468a92140a707936d381b1554d421af107c578e74c53ea08c7f7d93cf67612061359ae458408a9c79250f776ca4192016c0
+NONCE: 025bc10dc99346c4d0766a7d
+IN: d449a2e812429beb5c466d344f5b5eec
+AD: 304dbf9a59bfd33b777d8dec9dddce4c365e72aed851210eb964c1da18119bd13248266a67408e88ac2eadfc54def0fb57f23743d376b11293377565d253d2bffe0309f2946cb78d4e9536dde4691fe1eef9ce2dc916a773d06b42fe2b014e7974d4aeffce25a0902c9b44265e5d6d26809b5f24875e80cc13f1f8872b04a237
+CT: f366e7b66683f52586e1c363c15b7fb1
+TAG: e0e1bb733471f150ddce1b83f3fc2d88589d286ca052574b7f0735bb598362d2
+
+KEY: eb78ea626b219e12937057155884547cb7578718f569dc8f2b370c0fea80e7f0d0f5cb590f0b7341d20c775bcd6a3c818e23b6cea949cf99eb94a23a81cd2249
+NONCE: 75a10f16d429b809cf12b9ef
+IN: 6b0203316e8108ff01b12df91ba6644382
+AD:
+CT: 7ee07054f76471115be159259340c24391
+TAG: ab970669d1603767d588a93cf215673ad307244f9179f46fca56e97f64a5fbac
+
+KEY: 3221167926be262b7bd0591f56be6bf030365d45ab84a93a94ea41a5e07735b17245ad43787e8791e7ceaa0472b562ed17e3b609c66c868c9b08304c8bb328b1
+NONCE: a94d8417d2bb0323bcfd354d
+IN: cec81bac7b85c441b6261163d67921eb49
+AD: dd
+CT: ddd8860fa9e2e8087db30c9da1ec9f9487
+TAG: 26a3b9bc4d4cd802cc22e7647a19fc2a5092293c9f5b1c84bdab7245a6d8f4ab
+
+KEY: 4b16e2d62294f76cd2a6c8e0928279d9de40f0b169ef9465738cbfa064c520128ee89cf657da27e4e532d8c4709d992970bfc9daab2f31b3a67e53200d3d6710
+NONCE: e746d498b9031007332447f7
+IN: 16841e3fc1f53990d33f7ba525dab121a0
+AD: a785917bc9f3aaadfd170abe83bb30c0c5d595fc8b491d983131aeab1a7b8d8771f1a963c251976152dd63
+CT: 6bcf5eac15ef74cb8a706856f62eb5e8c7
+TAG: 9dc84b06e8ec8921be4bc7762e8cebb61a95ac5660022520f9438e8f77b45796
+
+KEY: ff2f5944111226df1d9a300533d3e871694fe15a418b2090265cd8c0111b249dfb7ee86bd9228f7ea5d89d8afcf10bf69942ee4c29bfa8409b63c00c2213629e
+NONCE: 477060f0c61555873bbeb225
+IN: f091891c43e2374c2755a88a11b04beb4a
+AD: f1323fd1ac4de9719dc5966dae45dd7b8ddbee3f8da4f4f4d5f25d06bdb8ebf57328dde76d0bdb9bdc5f6b12
+CT: e0d96f6f3ed0493a289d4c3b79238b9ed6
+TAG: 71276c05b52bab0063108dbf4e8ff57cf3e15079055a309d725f14bb86671ce1
+
+KEY: 1ce841bcf2ad8accc458a2d94774c3aa53a99e7dbec587376212101303ca2b42272a23fe28514be190b82e503e7772a3713800f4360fdb767e85ea5e1f7b8eca
+NONCE: a2f8afc5ceb5382882907630
+IN: 620fece1e843d1d0b5c5a541a6f615a81d
+AD: ded910647464d0fbb0a5d93ffb9839de3360c675179c5991ad3470285d79071436025111153628c563ad1b595e
+CT: 34431c3422e009373c50f3ee6c5b3fcc2d
+TAG: 6e4e8a3967307f47e233a36ce05a4826a698fada2ac19543bab7c9ac4f79451b
+
+KEY: 6bafd28a32690851fda667eb2d3c5993f13df52b2e97630527f26c498fd5019f26177a78f27c0c41616d2a4a73757fcaf9cd92a7da8498f90315d41e7479d90a
+NONCE: 75166c506c8e1d10da4da8b9
+IN: 697bea4d6eed5e6ed243cf01cc79bfd3a5
+AD: c0fa663961c3f7e09a8c7bc73e252a232977dd6c9483f02067b34fe695f341d05338ea2002952439ce08295ee5c12f38dafffeb5716908d3f1d4bfbf9eb0e4077bf8e534f19568ed04fca3bbff95da9088cb939f7a20cc97cc0994f9308e184219bf12c8af0d66df436c296ad39832d661b88c98cbb168c751719ac1383c9124
+CT: 8f37885b9602725385fd9a244ab2a156ea
+TAG: 7fa5cedd330887900f4a44d098e04d5eca16cf94e21f897fa54b0fc116b711b6
+
+KEY: 815786c7744d15afe1d6ab452cb6696fead8b88269ba3eb35c458f6248bad77b404acc744ebb74612c4f97deaccb99a7bcc6ad41917d61057c05b30c581dc4a0
+NONCE: 12342e4704f02336ebfc91df
+IN: 7f15e696b49ae5104ced5bebbf58a9d8ddcfaf46ddce9df88fe0d58a2f8546feeb83b975c66e4dafddb7fd9d17e80127e70af06b3b8b13c3390f1f50a227e7
+AD:
+CT: 22e7c5d54a7b622c47a9edb77cfe7c094e500b0ef9595bc346de736e0088e5934dc07160aea34f24d3ab21440878213d28059551cbfdaa418af40d344674f7
+TAG: 8c271ea5c15aa771c900388267efb2f435f001c2e83f4ec297e77c608de2d579
+
+KEY: 66d87d2b18e46257476456a1f87123424477decf196b88b09acfd3ca74bdebef4c98f1b93803098a141e0acc3ce8eede065417a0c1eda9b4614558d2383762b6
+NONCE: 1ec0ca1d3b09ef186ac4bb1a
+IN: cbb59e14098c2a8ab7e84ace913515c74e056e0fb272c7b88d0dddfb62e395afb695647d97d1071eb09cc1e1776b609fceaf4e30e92640379bb8f0e762ca9c
+AD: ec
+CT: 832804b8003b0ca1b4eff1dc4da6f6a9649e5a582854bb72cd74357476bf38d81ea3bc8ac0463f21fe37683bcbe07360d0ec2d7ab90b588adf669099303ac1
+TAG: 9fecafc768fca71ffe7d640dbb7a052d97d6c8e2fc86001d71feaf284ab609f0
+
+KEY: fbff97085351f4500e73190ac139dd3ac91e268042b5926b57e0394c750b10348b47641d195d5fb5b0846256ab229f102538b81e209db5d93b4d55f30c453d9c
+NONCE: d4868c918de2af7d3e3f57d3
+IN: 4f14aa5a680d66ae15ce0ce4739888f64d827def862572f9a6cd620badbe4ee9d75f4f9bc1f73d409f519a657f53a50d50e68e22f33a8ef5aa08b1212889e5
+AD: c41253e96696a948ce500030af27086842aacb79c04cc02a42b858a65c630065a5292bb9b2e69ea5fe5a7a
+CT: 08596ac0550574e352edc13d7e390d8fd0a57406dd61e1543066b4aa0ea06670f356e26ada0d6c61c1e41de1b4fd7a251c961fae44b23523ce227eec99a338
+TAG: 72f58de3e6697c8419ef518748fe0bb3cb930907c71b6d682c5e61068206d991
+
+KEY: c78c550aba82b571d39ce21d6ecf5e5f7c2a7bf921c6162c64ec1fdff4d0b8c41bfcea0e2486cc86b9ed9e9ceb73c4ec228a2ecbcfa0379174e76475cc21ae31
+NONCE: b5adf4de19980a71cb8ae8e6
+IN: 3d5e43ce95ff9d7f797f27b904c07291a35678fe76a9c57f0c0cba724f38acbb22c6c185db864a2a17b7ef2d67a04810ee5a45fd5a4e28a15a1ae16971451d
+AD: b5eeb9a18d436ada7bd5601944784f50fb0a989397b5c781a2cdf29337315dc7664f3c1cbf17f37fd0cc8b30
+CT: f91f1f20d06ad4480ff233480228994cfa052f9bf3038d06d997d31eb68bffa4960341b93eb5ed2260341e6816519c47bf231db2a41ad8a9719f4de6a33de5
+TAG: 6e5eabda421961e26dc17a7e1f750425235df4eaf9a97934c1e1b4439fc22791
+
+KEY: 17b90dec44546d9dbc489e55a01f2cc64452a9b0e50506a8ad7c81bc6fb21328285cafed901a7204048866ff3bd543003fdcbeb3e9e2f3d580f9062362879633
+NONCE: f0c0cb247d210031f9b233bc
+IN: 75b9b524cbfd1287259da116f536aff56112a406f069aa08f545b5372d45b66d7a5d05e02728c4bc2c779609dfe251386f78c5f48b9dad90b363d324826cd6
+AD: 8a604a9b06ad595ce0b9ad1644a596c7d3cde81490abc80840c764c40d6df08fc71d1e8196eae0802f8c8dfc24
+CT: 23ad62a668f942e613c3b5a7828142048f1f6a67f7f0e0cc8bf3fffb2d1dd967da472d080353dc9c23b900a566f20afb850e4a47688ee507faa6178fef2afd
+TAG: e9e82d3221f964d9e6c09d761afa3f05d1316d39c82618a82dafa23607bb40a3
+
+KEY: d5c09fe24201fcc3ad4c9a9c4b759345f643e930301c3714f62c8dd4974bb15a026b217ac637b4f0e8d6ef40f36be967c50aaea83b2e72df18eeb9576865f1d8
+NONCE: 9cfa0df1fe0910b33ee9849d
+IN: bfeb3d86ce3f4c5ccd0c3945e1da0e75dd057aa5b4e1f070593394f4a0227abedac0b77478e04d498506245b162e909cb711d8b875d33f9c4578e80a0e2113
+AD: b874a8523799554436a1174ab124677dc2ae2042a436c85065c50d5b5e7519623379ffed9a9c2b84b9626214b13c1806b65a432ba79066ff28ed94d17628f5ff84618593954389181e997ebd245d31f520539e250b31c86b99992983820f79e74aeaacb3a95e690e2841aba5a384d0333ebaa5d1fde06b4b8e3e1cabc6639459
+CT: afa649ea47db94936f89612ece681bb175664a97aa6faae5745f49ac9fcbfd4287b73cb58e8d8aa12eccf309182f075098f339db697fc60540481dad0cd82e
+TAG: 9909335130df0326650823de5a4f5b6f45e6941a6a72ceaf80ef32fe67363944
+
+KEY: a13c4654606f532a8df47c367dab1b214166e4f7188c20560831ac30ba5e58d316d29764e4c716ec0126657c926ba2e4541da062447228ae61340a951101b4a0
+NONCE: a2df3417ebb86bbb2f954939
+IN: f1954e59a319547d32e81f846e0c79db41c681166b43eb9c10458948606ced50a44df26fad5654a7c25d3fb52539cf25fcc1c11707c4b5aca7910a76e2374740
+AD:
+CT: 374726a4691f178a4c0a6f96108ba30c4ca8a30242c14e84380969473879d4a5de580fab4cf6ef6e465560a15028ba78a1a88f9e62322cb698b15ccce6ba83a8
+TAG: 683e5a3e61d9d9c8b170f1d4eaa4f74dcbecb1a4cb1551dc364bbb336d4e4109
+
+KEY: 0c1751677a9b7373e0c2ceab2c8e4dab50af22e2230be3187c21ed46069168d173c28a7474d8f7c3cab39401663405aebdcc474ce136e1fff9cfc520bfe17ca6
+NONCE: 38bc2efcd97998de1528b064
+IN: 8a3c6212240bdcb86da98f0e3ab3e9e78f7f61f0627ea088ab283e739a0bed5c360eeed26cea43ec09b4f3556049a1d7f8ef86abfd1118f9c0e34cc6eea4544a
+AD: 20
+CT: a1a9f7f4750be3d89fc4f25917f8ffa7dd462ce712ddf61792a01b1840bc8e428000372252f1b41055416a961db3be8fbe774f0a0a71a82e79e74927522703a0
+TAG: ae24708df0d5893a902765f6c6c2eebae0c11312936cd415bf4a74bb8498a367
+
+KEY: 154c21eb43d8d556e5f782ddd64d577ac8066fa172c2936fc2b2e875aa437f941819d9ecfaefa2e388fdeea81a0ece8dcb7647f2c68da48884aeb1315b577c09
+NONCE: e14d1bd8681373d41702a762
+IN: a2c880fcda87d9d4681a735a6790d93a1c9c68e55b87d5f7b3146665a6b2051398eb9895e1f5d522841668b9915633aa8cb40048c619baf6d63ca2da486cdeb8
+AD: b0b725cf634349ce1d3ac49d48313a09697efd9996cc5afd06b1d0817181d0374db05825dc2f08207bfb3b
+CT: 1cc0db5980863df7a40c78e323a78be6c6d556d4e3b5f930d8d0f2c6a10c6477e31c000d3f0563b46e1a4aa566a4ef4b433e17e94c43338b51a7a3f862739b6e
+TAG: fe005424112de2a5ca6e68ada40984df1ae5ac666cf5fee19e9a0f203dd69f52
+
+KEY: c34482341724ee431b5272ee2964b245d7657778f7927cad4b5a1bc30a176b1eb88a83ac9faf58215a72855edf94f8e86fade58c5b5907994bb8381c9f21b753
+NONCE: 4934d9afc32fc7e2d8851594
+IN: aa3d32adc47b0b84d1b038ddcaeb007a7d5c96cc06a943eba5da6d0d367625330556e67da099c84086b3f46bb4b72986e076eb426913e415cd20bee34e434bd0
+AD: 076a7bc587b306f3da3ba88e66a55cb8125bbf8aa000dda266e950f381e35ac938ac86f8a15a83022a25f28b
+CT: cf017d87da8927e42c1f10fd3d73cf483bae43f4e110363159a9fbb7cba363930a0364cd42a5de2c70171edc4caf15bfc7238f7087bf1402b32c7bdb1f493393
+TAG: 3961efea656aab1b83082522b801fafdae346f7d4be70db1981283f323e5b5dd
+
+KEY: 363e10d8b3fe349014d6222761bba7af86545dcd1812fe2e5ada564c5008f8ea1850f374208e87362afa135f20f9e79dd0ad32f86448263416086d3afc5d37c0
+NONCE: cc545928edd3b21c0e8bc0f1
+IN: b68e3a54d17dab6eb41b03de2df14e792201d78a9c1cbf341da421da82b026ff471d4305ede5c6baae162a098c73da5cab93f30d6d540b4eaa0ee772448dade8
+AD: e21498edf4e25ada2dd6a382eceaf737623e501db34f5c5bd5c963f45818b146a6e45aa92db2a2069e55d46a4c
+CT: e4920c1fddb5dfed2268781fbb17e9ad2ea88bf2a0f116fbb7b309b25a5b9f989e1abc334999ab175b65f87e874d8ba80792044b458dc27d2b24c989d24385e1
+TAG: f0dcfa064cdf042e0b9a0443d634c38695dd09b99dadc647195fc2ad53dde547
+
+KEY: ae93f58aefa94e4e0622f2e962529fd2efdab840fd0bce62e163ca0fb004ec3b22e246073614203d9b63fe2842ef5903ed08b3e52abf7ea18acbe16fa8f66368
+NONCE: c9ac237c87270f2d88b91b64
+IN: a75f49778a6c03b0f8915f5d09efe99c5f4e9cd928713882e6b9b78bab3541812db41792b893c7e2259debc6c660ce708851912a5b9eaf91416d86b5de114ce1
+AD: a4b198a329e9c5bb6d9f31a6415811eb33c79422b0db130b78d788c38c0b9a5122688cbc50fea811afa20789465f9ee4362336cc3701ece701179af96eb7c86d5a00ed8582f24364393287d5dbc3e83a82b7a585cee5b152b5da40aa45ccd46dc841004778998c7efe9eb43c9762d1c8581eee64e18c5a961bda5aafdd5cfec8
+CT: 453fad9395106a703ccbfe811bf775f1827ea960c71d79242d2ea0e3e31b14baa76eb6d107dfc6e484f4e5146f8cad5b389e4c0fa18260c96a193edbc8091a36
+TAG: b67082c21557b31392a9821fbce4b93706f96856d2581c92e7fb65dd2166624f
+
+KEY: a145adafac46280e1cee8696903c5f3866540f27f17a519637373d95dca4ac5ac0bfd85ca6e1f8df8ae3fcfc9158421581669db52c20a3e19c5d251952f63218
+NONCE: 90bd43611f235ff225b23208
+IN: cbe5f3a5b7a94b8665cac1a4d173a225679e1a3926d8596b5adc0ef4fd00f7d93a432ff141cc04f877be60b6a17fff40ac845a91bcee3b483862f67d9a76ef498ce5e49c361bfc018e401aff47b397e96b2982d4fdcd043ca09905be9634e83dc22a667c955bc992ec96ca1b76f73631767f64fc7151284d5aa81c1aa42eb3aa
+AD:
+CT: 604f718dbce17dfca1fc5e0f400151cb65bea9d7d8f26d56687a76a23f89201aab01ef928006d15493f5b1501bb99c517cf123acd956ab575e687298488a88d5739c266e67ca6a20a5dbe5f5f27ac778816f04e7b1764cb716477f3aa01482cb6b25fe034ab5d942013164aa124608cacf13d6cc9487446cfba54315fc6bfc42
+TAG: 8e3e1a01945bfd9e1aa4eff1cdd0a6da6d8fdd5446e6d732a673effe8e44d76a
+
+KEY: 63ac8e2561341587bc066c87cd23f7f33e6023bdc1521a91d6ce63d3ab213825d95d674928b56da1741aad8e85a8b703239ad74e0304ad555eeadebf4ae30aa6
+NONCE: 4f3073c3b780ebb146e136c7
+IN: 7f9a05b1aead29b4d5361c2606e5db8a48122858842679cd46f8386ef9359f998cd2c6c266791429624ff634a160d08faf1523b650c30b2fcd71517da5f377000251ef23cfd2510a0630215ad45fa6d2313f9add040a07df8259b82d3f29cf1ab8477cd114c9ee579d3e2ce60c5da2f3375b68b4d6e0913d39dac9399c00bd32
+AD: 22
+CT: d4ed811c8db932348e0c311e9278ef22f22cec8af88b3ac0cef77f13bbd9b8cca037c1ea87590a0ce3f3e7b3ffe1dcc4c7cd9e721baa5f126a3e0afb26dcfa02bf44428846c0f1e07ba0e026c23a39877de1e69e16a2766ff4fa3d4e8d3a97ba28f407f459ae3520dd840e8f9e149ea582048dc6e3d0227bd86a9c26ddd59895
+TAG: 0abc9111229bcb725953d139a2dcb1aa0cb9d3d6c01ef4733482dc5edcc88958
+
+KEY: 355454fbe12f125edbc13550a7494f37efbe12b843058d29f892e1524289c2868ef0050a75a232d3083c381289e4950e352d68d64bf05f0608d694763c36641c
+NONCE: 0a344bb3da1c4260f2daf256
+IN: 362e97f8ef09f30e5db2f21d40568d347d9bc42d4c94a563484b12eb109886ccfd2c61c40dfe93eb836bb6aa4f828e77c137485da2df494cbeb6a9a0192c3777b4d7a927fba11a8eaf604b85a81ac4719ce8b595a74656286fd0b80d1ad3f3393e6038b258af97af9a77f6760d486d9caf5a451ba26dee51bda0f76d75bfc26e
+AD: c7c2e8196f37185b44515480d5d9451d79d07df4c1256bff6382f942727ce9b3a4f81ae964d8af2cd9f638
+CT: 32a67922947fd6b1c1bfaf3e1d41397173b97095e55307cae1c574daca275778d4aa4313fb1fe5b3997ff18800903ce044c7d0976abbb03b6cc1f7498d8b56d00672bd74f7cb152b677c632ef7a6f6fc13e95e82b6e35d663eb47f27c229c81174fd7c62c94c414e47216af2580fe822643e54907af77ae18e903fe856a02173
+TAG: 72d0fe5baee8090c5f8e79890b77f6d72a4213a7d1a81e0d1f1c9e6731e44d54
+
+KEY: 664478c9d30d2cbc39351ec3b3494f3edb81e32e48bd4ef05969da07e770e4181a9ada3b2f83b46f40fc2d9ad35fd8ee6864ff3d70436d6cca3f8e0563cc3b06
+NONCE: 7313df9679181ffad2972a6b
+IN: 142f073f2ce443c68822f120b5009e39bea3453017dc04c1b091adfddcb2a7e361c2b79eab1bf0818bc86e9d7964834d3775698b56a11ee07a0c9c03cb7bb895bf1a1dde3975c3662d233052824f1539f58cd6ad5cadb58fecaf2b34935ff711c45a639d642fb8fc3a52929b1296683bb13e67f2cc8ed9090126cdf28a4395c6
+AD: d0d78b94505793af546912f3780699dd72e288c775bfc75da6e306defcd868f6d40c6d6ce34fab9c11574ef5
+CT: cb913e40ea5dfe76beae612e9732d23ce352789987134822b2324db585179bf90d0ee20bee102e93a49a55fc978d19e99ba316cf8d9a10d2f2bcb75da4b135d1fcb8057edc33a180586015d8829a128f8fdc87b72497016c280f54f4d974c2c7e9d32ae137eaa1bcb670be237269fa73c3a0f273da9e70d89600ae7c231fc9d4
+TAG: dcc158c254ff7e131ad854a2158d51c643c281dfd7df342d5481384ab236a685
+
+KEY: 409d1b4e1c187c8b1c053e999f2af648583e1045d56d553cce9270d08c5643ef365eb35e3bdeaedcd164b0122ad185e71c75146a9807104d9b65b56d9bc1dc55
+NONCE: 1cce3f08a5aa5824d063a6f2
+IN: a255239e4065f3effe6aa5e88814d516236d016c51cd8eb35af7cee86418966559802f8ff7ac39c6a45acc1f1b18cc28d7cc32ae66dff43289fe44c3a2a72fbadf3a7249d76c1ba9671dfc420ddf513539f2da5f31030f2b6775c57432c2c3486621d841e80dd4894229debc12ef47d74716838f2d807e208f0fdaf733bce76e
+AD: 8f34f8b676e71844841c6a7b63fef1ad3061f2449c1044e1a281595da2d9e9fd141aea7350bd8cf9774d375e67
+CT: 969fc2c64261db415e51eee8cc5e0cf5185b8e3325dea516a70e32115a5b72233a44458c40f2daff3594d71e42ca2e3fc1c444ce171d22ef40009d798456613fa4b76beaa6d469e235997a302ac468c8bcfb8ef5de5cda58d7e554a9eab6cb568945dc37f28b0dbd674c083dfbd2e42fda1b42d0c1966e9652a21b32af71e2d5
+TAG: fa0789a83c255412501944a67bdceaff3f01d9a23b0c749be38abc956e2acae6
+
+KEY: e6fd8144cdb305bf9e62a2c901764c62902f354409d8c5b9c8cbfc0ba8ac7d0859ff8994e573e46784395d89c355a91a313f601b56e86ed3fd10ba428a5481ce
+NONCE: bae080718d3e5c5998542f15
+IN: 2258ffcd6fcf91b1723f8db0047525d61cc8ffc440acf3290690685d16384292493807312b7dfc23ac9d9c3ee1405baab21a3770a05875cfe325268b65fc877463e3208c842ea4a32cf144cc46d57afd91f6b6b5d85fb2dedb0702f0c4e7f742cf4c9b4aec02f07267ec1f7b96a5a3ef25f6c1b4c27bd829e86583e239cd854b
+AD: 51ae57749b7757718aef9b9c47da5794659516e7f98bc80e6c18c89253f8617963331f54d4f009f087d1d2bd69a083f3a4b98f2a51ce24ffc6079774f7c7b01638b6131bfccebe21fea67bc839c259a50fcc0a16a69ada3c5adee4097d9e053a03266cb9b4b39ee2a465ec1aa058e61a0b9888b93bfcfd103f91ca3a7b274a10
+CT: 5b2fe8eea3313cc04d5ec75d75d05b3242b6e3b65c6fa1761716780c9529ff8ca523096dd037c5bda27984aa93c702ce9c01c63569a90657cc6373ad5d4473028b7eef69dd79c44c38d0063e8a8b7f1aa2bf6b646711ecd4eea3fa27408e089d9c4c4aceedff29a25baa6a9069eb7eac83a53212c0b387d700547c46cdc525e3
+TAG: 60319de093aec5c0bb8d5f17e950b0f4df0dfd20ad96490f6f12db461b2a4a84
+
diff --git a/src/crypto/cipher/test/cipher_test.txt b/src/crypto/cipher/test/cipher_test.txt
index b250df3..f3c6d35 100644
--- a/src/crypto/cipher/test/cipher_test.txt
+++ b/src/crypto/cipher/test/cipher_test.txt
@@ -76,6 +76,43 @@ AES-128-GCM:00000000000000000000000000000000:000000000000000000000000:0000000000
AES-128-GCM:00000000000000000000000000000000:000000000000000000000000:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40::cac45f60e31efd3b5a43b98a22ce1aa1
# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
AES-128-GCM:00000000000000000000000000000000:ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606::566f8ef683078bfdeeffa869d751a017
+# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
+AES-128-GCM:00000000000000000000000000000000:ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c::8b307f6b33286d0ab026a9ed3fe1e85f
# 80 bytes plaintext, submitted by Intel
AES-128-GCM:843ffcf5d2b72694d19ed01d01249412:dbcca32ebf9b804617c3aa9e:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f:6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5:00000000000000000000000000000000101112131415161718191a1b1c1d1e1f:3b629ccfbc1119b7319e1dce2cd6fd6d
+# OFB tests from OpenSSL upstream.
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:1
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:1
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:1
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:1
+# OFB-AES128.Decrypt
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:0
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:0
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:0
+AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:0
+# OFB-AES256.Encrypt
+AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:1
+AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:4FEBDC6740D20B3AC88F6AD82A4FB08D:1
+AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:71AB47A086E86EEDF39D1C5BBA97C408:1
+AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0126141D67F37BE8538F5A8BE740E484:1
+# OFB-AES256.Decrypt
+AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:0
+AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:4FEBDC6740D20B3AC88F6AD82A4FB08D:0
+AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:71AB47A086E86EEDF39D1C5BBA97C408:0
+AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0126141D67F37BE8538F5A8BE740E484:0
+
+# AES-192 CBC-mode test from upstream OpenSSL.
+AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:4F021DB243BC633D7178183A9FA071E8
+AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:4F021DB243BC633D7178183A9FA071E8:AE2D8A571E03AC9C9EB76FAC45AF8E51:B4D9ADA9AD7DEDF4E5E738763F69145A
+AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:B4D9ADA9AD7DEDF4E5E738763F69145A:30C81C46A35CE411E5FBC1191A0A52EF:571B242012FB7AE07FA9BAAC3DF102E0
+AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:571B242012FB7AE07FA9BAAC3DF102E0:F69F2445DF4F9B17AD2B417BE66C3710:08B0E27988598881D920A9E64F5615CD
+
+# AES-192-ECB tests from FIPS-197
+AES-192-ECB:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF:DDA97CA4864CDFE06EAF70A0EC0D7191:1
+
+# AES-192-ECB tests from NIST document SP800-38A
+AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::6BC1BEE22E409F96E93D7E117393172A:BD334F1D6E45F25FF712A214571FA5CC:1
+AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::AE2D8A571E03AC9C9EB76FAC45AF8E51:974104846D0AD3AD7734ECB3ECEE4EEF:1
+AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::30C81C46A35CE411E5FBC1191A0A52EF:EF7AFD2270E2E60ADCE0BA2FACE6444E:1
+AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::F69F2445DF4F9B17AD2B417BE66C3710:9A4B41BA738D6C72FB16691603C18E0E:1
diff --git a/src/crypto/cmac/CMakeLists.txt b/src/crypto/cmac/CMakeLists.txt
new file mode 100644
index 0000000..8ebd80c
--- /dev/null
+++ b/src/crypto/cmac/CMakeLists.txt
@@ -0,0 +1,17 @@
+include_directories(. .. ../../include)
+
+add_library(
+ cmac
+
+ OBJECT
+
+ cmac.c
+)
+
+add_executable(
+ cmac_test
+
+ cmac_test.cc
+)
+
+target_link_libraries(cmac_test crypto)
diff --git a/src/crypto/cmac/cmac.c b/src/crypto/cmac/cmac.c
new file mode 100644
index 0000000..fa4c3c4
--- /dev/null
+++ b/src/crypto/cmac/cmac.c
@@ -0,0 +1,239 @@
+/* ====================================================================
+ * Copyright (c) 2010 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ==================================================================== */
+
+#include <openssl/cmac.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/aes.h>
+#include <openssl/cipher.h>
+#include <openssl/mem.h>
+
+
+struct cmac_ctx_st {
+ EVP_CIPHER_CTX cipher_ctx;
+ /* k1 and k2 are the CMAC subkeys. See
+ * https://tools.ietf.org/html/rfc4493#section-2.3 */
+ uint8_t k1[AES_BLOCK_SIZE];
+ uint8_t k2[AES_BLOCK_SIZE];
+ /* Last (possibly partial) scratch */
+ uint8_t block[AES_BLOCK_SIZE];
+ /* block_used contains the number of valid bytes in |block|. */
+ unsigned block_used;
+};
+
+static void CMAC_CTX_init(CMAC_CTX *ctx) {
+ EVP_CIPHER_CTX_init(&ctx->cipher_ctx);
+}
+
+static void CMAC_CTX_cleanup(CMAC_CTX *ctx) {
+ EVP_CIPHER_CTX_cleanup(&ctx->cipher_ctx);
+ OPENSSL_cleanse(ctx->k1, sizeof(ctx->k1));
+ OPENSSL_cleanse(ctx->k2, sizeof(ctx->k2));
+ OPENSSL_cleanse(ctx->block, sizeof(ctx->block));
+}
+
+int AES_CMAC(uint8_t out[16], const uint8_t *key, size_t key_len,
+ const uint8_t *in, size_t in_len) {
+ const EVP_CIPHER *cipher;
+ switch (key_len) {
+ case 16:
+ cipher = EVP_aes_128_cbc();
+ break;
+ case 32:
+ cipher = EVP_aes_256_cbc();
+ break;
+ default:
+ return 0;
+ }
+
+ size_t scratch_out_len;
+ CMAC_CTX ctx;
+ CMAC_CTX_init(&ctx);
+
+ const int ok = CMAC_Init(&ctx, key, key_len, cipher, NULL /* engine */) &&
+ CMAC_Update(&ctx, in, in_len) &&
+ CMAC_Final(&ctx, out, &scratch_out_len);
+
+ CMAC_CTX_cleanup(&ctx);
+ return ok;
+}
+
+CMAC_CTX *CMAC_CTX_new(void) {
+ CMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
+ if (ctx != NULL) {
+ CMAC_CTX_init(ctx);
+ }
+ return ctx;
+}
+
+void CMAC_CTX_free(CMAC_CTX *ctx) {
+ if (ctx == NULL) {
+ return;
+ }
+
+ CMAC_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+
+/* binary_field_mul_x treats the 128 bits at |in| as an element of GF(2¹²â¸)
+ * with a hard-coded reduction polynomial and sets |out| as x times the
+ * input.
+ *
+ * See https://tools.ietf.org/html/rfc4493#section-2.3 */
+static void binary_field_mul_x(uint8_t out[16], const uint8_t in[16]) {
+ unsigned i;
+
+ /* Shift |in| to left, including carry. */
+ for (i = 0; i < 15; i++) {
+ out[i] = (in[i] << 1) | (in[i+1] >> 7);
+ }
+
+ /* If MSB set fixup with R. */
+ const uint8_t carry = in[0] >> 7;
+ out[i] = (in[i] << 1) ^ ((0 - carry) & 0x87);
+}
+
+static const uint8_t kZeroIV[AES_BLOCK_SIZE] = {0};
+
+int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t key_len,
+ const EVP_CIPHER *cipher, ENGINE *engine) {
+ uint8_t scratch[AES_BLOCK_SIZE];
+
+ if (EVP_CIPHER_block_size(cipher) != AES_BLOCK_SIZE ||
+ EVP_CIPHER_key_length(cipher) != key_len ||
+ !EVP_EncryptInit_ex(&ctx->cipher_ctx, cipher, NULL, key, kZeroIV) ||
+ !EVP_Cipher(&ctx->cipher_ctx, scratch, kZeroIV, AES_BLOCK_SIZE) ||
+ /* Reset context again ready for first data. */
+ !EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV)) {
+ return 0;
+ }
+
+ binary_field_mul_x(ctx->k1, scratch);
+ binary_field_mul_x(ctx->k2, ctx->k1);
+ ctx->block_used = 0;
+
+ return 1;
+}
+
+int CMAC_Reset(CMAC_CTX *ctx) {
+ ctx->block_used = 0;
+ return EVP_EncryptInit_ex(&ctx->cipher_ctx, NULL, NULL, NULL, kZeroIV);
+}
+
+int CMAC_Update(CMAC_CTX *ctx, const uint8_t *in, size_t in_len) {
+ uint8_t scratch[AES_BLOCK_SIZE];
+
+ if (ctx->block_used > 0) {
+ size_t todo = AES_BLOCK_SIZE - ctx->block_used;
+ if (in_len < todo) {
+ todo = in_len;
+ }
+
+ memcpy(ctx->block + ctx->block_used, in, todo);
+ in += todo;
+ in_len -= todo;
+ ctx->block_used += todo;
+
+ /* If |in_len| is zero then either |ctx->block_used| is less than
+ * |AES_BLOCK_SIZE|, in which case we can stop here, or |ctx->block_used|
+ * is exactly |AES_BLOCK_SIZE| but there's no more data to process. In the
+ * latter case we don't want to process this block now because it might be
+ * the last block and that block is treated specially. */
+ if (in_len == 0) {
+ return 1;
+ }
+
+ assert(ctx->block_used == AES_BLOCK_SIZE);
+
+ if (!EVP_Cipher(&ctx->cipher_ctx, scratch, ctx->block, AES_BLOCK_SIZE)) {
+ return 0;
+ }
+ }
+
+ /* Encrypt all but one of the remaining blocks. */
+ while (in_len > AES_BLOCK_SIZE) {
+ if (!EVP_Cipher(&ctx->cipher_ctx, scratch, in, AES_BLOCK_SIZE)) {
+ return 0;
+ }
+ in += AES_BLOCK_SIZE;
+ in_len -= AES_BLOCK_SIZE;
+ }
+
+ memcpy(ctx->block, in, in_len);
+ ctx->block_used = in_len;
+
+ return 1;
+}
+
+int CMAC_Final(CMAC_CTX *ctx, uint8_t *out, size_t *out_len) {
+ *out_len = AES_BLOCK_SIZE;
+ if (out == NULL) {
+ return 1;
+ }
+
+ const uint8_t *mask = ctx->k1;
+
+ if (ctx->block_used != AES_BLOCK_SIZE) {
+ /* If the last block is incomplete, terminate it with a single 'one' bit
+ * followed by zeros. */
+ ctx->block[ctx->block_used] = 0x80;
+ memset(ctx->block + ctx->block_used + 1, 0,
+ AES_BLOCK_SIZE - (ctx->block_used + 1));
+
+ mask = ctx->k2;
+ }
+
+ unsigned i;
+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
+ out[i] = ctx->block[i] ^ mask[i];
+ }
+
+ return EVP_Cipher(&ctx->cipher_ctx, out, out, AES_BLOCK_SIZE);
+}
diff --git a/src/crypto/cmac/cmac_test.cc b/src/crypto/cmac/cmac_test.cc
new file mode 100644
index 0000000..0f06860
--- /dev/null
+++ b/src/crypto/cmac/cmac_test.cc
@@ -0,0 +1,154 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+
+#include <algorithm>
+
+#include <openssl/cmac.h>
+
+#include "../test/scoped_types.h"
+
+
+static void dump(const uint8_t *got, const uint8_t *expected, size_t len) {
+ ScopedBIO bio(BIO_new_fp(stderr, 0 /* don't close */));
+
+ BIO_puts(bio.get(), "\nGot:\n");
+ BIO_hexdump(bio.get(), got, len, 2 /* indent */);
+ BIO_puts(bio.get(), "Expected:\n");
+ BIO_hexdump(bio.get(), expected, len, 2 /* indent */);
+ BIO_flush(bio.get());
+}
+
+static int test(const char *name, const uint8_t *key, size_t key_len,
+ const uint8_t *msg, size_t msg_len, const uint8_t *expected) {
+ uint8_t out[16];
+
+ if (!AES_CMAC(out, key, key_len, msg, msg_len)) {
+ fprintf(stderr, "%s: AES_CMAC failed\n", name);
+ return 0;
+ }
+
+ if (CRYPTO_memcmp(out, expected, sizeof(out)) != 0) {
+ fprintf(stderr, "%s: CMAC result differs:\n", name);
+ dump(out, expected, sizeof(out));
+ return 0;
+ }
+
+ ScopedCMAC_CTX ctx(CMAC_CTX_new());
+ if (!CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) {
+ fprintf(stderr, "%s: CMAC_Init failed.\n", name);
+ return 0;
+ }
+
+ for (unsigned chunk_size = 1; chunk_size <= msg_len; chunk_size++) {
+ if (!CMAC_Reset(ctx.get())) {
+ fprintf(stderr, "%s/%u: CMAC_Reset failed.\n", name, chunk_size);
+ return 0;
+ }
+
+ size_t done = 0;
+ while (done < msg_len) {
+ size_t todo = std::min(msg_len - done, static_cast<size_t>(chunk_size));
+ if (!CMAC_Update(ctx.get(), msg + done, todo)) {
+ fprintf(stderr, "%s/%u: CMAC_Update failed.\n", name, chunk_size);
+ return 0;
+ }
+
+ done += todo;
+ }
+
+ size_t out_len;
+ if (!CMAC_Final(ctx.get(), out, &out_len)) {
+ fprintf(stderr, "%s/%u: CMAC_Final failed.\n", name, chunk_size);
+ return 0;
+ }
+
+ if (out_len != sizeof(out)) {
+ fprintf(stderr, "%s/%u: incorrect out_len: %u.\n", name, chunk_size,
+ static_cast<unsigned>(out_len));
+ return 0;
+ }
+
+ if (CRYPTO_memcmp(out, expected, sizeof(out)) != 0) {
+ fprintf(stderr, "%s/%u: CMAC result differs:\n", name, chunk_size);
+ dump(out, expected, sizeof(out));
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int rfc_4493_test_vectors(void) {
+ static const uint8_t kKey[16] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
+ };
+ static const uint8_t kOut1[16] = {
+ 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+ 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46,
+ };
+ static const uint8_t kMsg2[] = {
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ };
+ static const uint8_t kOut2[16] = {
+ 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+ 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c,
+ };
+ static const uint8_t kMsg3[] = {
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ };
+ static const uint8_t kOut3[16] = {
+ 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+ 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27,
+ };
+ static const uint8_t kMsg4[] = {
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
+ };
+ static const uint8_t kOut4[16] = {
+ 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+ 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe,
+ };
+
+ if (!test("RFC 4493 #1", kKey, sizeof(kKey), NULL, 0, kOut1) ||
+ !test("RFC 4493 #2", kKey, sizeof(kKey), kMsg2, sizeof(kMsg2), kOut2) ||
+ !test("RFC 4493 #3", kKey, sizeof(kKey), kMsg3, sizeof(kMsg3), kOut3) ||
+ !test("RFC 4493 #4", kKey, sizeof(kKey), kMsg4, sizeof(kMsg4), kOut4)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ if (!rfc_4493_test_vectors()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/conf/CMakeLists.txt b/src/crypto/conf/CMakeLists.txt
index f54d904..8046bb8 100644
--- a/src/crypto/conf/CMakeLists.txt
+++ b/src/crypto/conf/CMakeLists.txt
@@ -6,5 +6,4 @@ add_library(
OBJECT
conf.c
- conf_error.c
)
diff --git a/src/crypto/conf/conf.c b/src/crypto/conf/conf.c
index b8dab95..213efc5 100644
--- a/src/crypto/conf/conf.c
+++ b/src/crypto/conf/conf.c
@@ -90,9 +90,13 @@ static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b) {
}
}
-CONF *NCONF_new(void) {
+CONF *NCONF_new(void *method) {
CONF *conf;
+ if (method != NULL) {
+ return NULL;
+ }
+
conf = OPENSSL_malloc(sizeof(CONF));
if (conf == NULL) {
return NULL;
@@ -530,20 +534,22 @@ static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
BIO_gets(in, p, CONFBUFSIZE - 1);
p[CONFBUFSIZE - 1] = '\0';
ii = i = strlen(p);
- if (i == 0 && !again)
+ if (i == 0 && !again) {
break;
+ }
again = 0;
while (i > 0) {
- if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
+ if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) {
break;
- else
+ } else {
i--;
+ }
}
/* we removed some trailing stuff so there is a new
* line on the end. */
- if (ii && i == ii)
+ if (ii && i == ii) {
again = 1; /* long line */
- else {
+ } else {
p[i] = '\0';
eline++; /* another input line */
}
@@ -564,15 +570,17 @@ static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
again = 1;
}
}
- if (again)
+ if (again) {
continue;
+ }
bufnum = 0;
buf = buff->data;
clear_comments(conf, buf);
s = eat_ws(conf, buf);
- if (IS_EOF(conf, *s))
+ if (IS_EOF(conf, *s)) {
continue; /* blank line */
+ }
if (*s == '[') {
char *ss;
@@ -591,10 +599,12 @@ static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
goto err;
}
*end = '\0';
- if (!str_copy(conf, NULL, &section, start))
+ if (!str_copy(conf, NULL, &section, start)) {
goto err;
- if ((sv = get_section(conf, section)) == NULL)
+ }
+ if ((sv = get_section(conf, section)) == NULL) {
sv = NCONF_new_section(conf, section);
+ }
if (sv == NULL) {
OPENSSL_PUT_ERROR(CONF, def_load_bio, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
@@ -619,11 +629,13 @@ static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
*end = '\0';
p++;
start = eat_ws(conf, p);
- while (!IS_EOF(conf, *p))
+ while (!IS_EOF(conf, *p)) {
p++;
+ }
p--;
- while ((p != start) && (IS_WS(conf, *p)))
+ while ((p != start) && (IS_WS(conf, *p))) {
p--;
+ }
p++;
*p = '\0';
@@ -631,8 +643,9 @@ static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
OPENSSL_PUT_ERROR(CONF, def_load_bio, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (psection == NULL)
+ if (psection == NULL) {
psection = section;
+ }
v->name = (char *)OPENSSL_malloc(strlen(pname) + 1);
v->value = NULL;
if (v->name == NULL) {
@@ -640,18 +653,21 @@ static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
goto err;
}
BUF_strlcpy(v->name, pname, strlen(pname) + 1);
- if (!str_copy(conf, psection, &(v->value), start))
+ if (!str_copy(conf, psection, &(v->value), start)) {
goto err;
+ }
if (strcmp(psection, section) != 0) {
- if ((tv = get_section(conf, psection)) == NULL)
+ if ((tv = get_section(conf, psection)) == NULL) {
tv = NCONF_new_section(conf, psection);
+ }
if (tv == NULL) {
OPENSSL_PUT_ERROR(CONF, def_load_bio, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
- } else
+ } else {
tv = sv;
+ }
if (add_string(conf, tv, v) == 0) {
OPENSSL_PUT_ERROR(CONF, def_load_bio, ERR_R_MALLOC_FAILURE);
goto err;
@@ -659,29 +675,37 @@ static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
v = NULL;
}
}
- if (buff != NULL)
+ if (buff != NULL) {
BUF_MEM_free(buff);
- if (section != NULL)
+ }
+ if (section != NULL) {
OPENSSL_free(section);
+ }
return 1;
err:
- if (buff != NULL)
+ if (buff != NULL) {
BUF_MEM_free(buff);
- if (section != NULL)
+ }
+ if (section != NULL) {
OPENSSL_free(section);
- if (out_error_line != NULL)
+ }
+ if (out_error_line != NULL) {
*out_error_line = eline;
+ }
BIO_snprintf(btmp, sizeof btmp, "%ld", eline);
ERR_add_error_data(2, "line ", btmp);
if (v != NULL) {
- if (v->name != NULL)
+ if (v->name != NULL) {
OPENSSL_free(v->name);
- if (v->value != NULL)
+ }
+ if (v->value != NULL) {
OPENSSL_free(v->value);
- if (v != NULL)
+ }
+ if (v != NULL) {
OPENSSL_free(v);
+ }
}
return 0;
}
@@ -701,6 +725,10 @@ int NCONF_load(CONF *conf, const char *filename, long *out_error_line) {
return ret;
}
+int NCONF_load_bio(CONF *conf, BIO *bio, long *out_error_line) {
+ return def_load_bio(conf, bio, out_error_line);
+}
+
int CONF_parse_list(const char *list, char sep, int remove_whitespace,
int (*list_cb)(const char *elem, int len, void *usr),
void *arg) {
diff --git a/src/crypto/conf/conf_error.c b/src/crypto/conf/conf_error.c
deleted file mode 100644
index b5dd001..0000000
--- a/src/crypto/conf/conf_error.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 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/conf.h>
-
-const ERR_STRING_DATA CONF_error_string_data[] = {
- {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_parse_list, 0), "CONF_parse_list"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_load, 0), "NCONF_load"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_def_load_bio, 0), "def_load_bio"},
- {ERR_PACK(ERR_LIB_CONF, CONF_F_str_copy, 0), "str_copy"},
- {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_LIST_CANNOT_BE_NULL), "LIST_CANNOT_BE_NULL"},
- {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_CLOSE_SQUARE_BRACKET), "MISSING_CLOSE_SQUARE_BRACKET"},
- {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_EQUAL_SIGN), "MISSING_EQUAL_SIGN"},
- {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_CLOSE_BRACE), "NO_CLOSE_BRACE"},
- {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_UNABLE_TO_CREATE_NEW_SECTION), "UNABLE_TO_CREATE_NEW_SECTION"},
- {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_VARIABLE_HAS_NO_VALUE), "VARIABLE_HAS_NO_VALUE"},
- {0, NULL},
-};
diff --git a/src/crypto/cpu-arm-asm.S b/src/crypto/cpu-arm-asm.S
new file mode 100644
index 0000000..faf3ad8
--- /dev/null
+++ b/src/crypto/cpu-arm-asm.S
@@ -0,0 +1,32 @@
+# 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.
+
+#if !defined(OPENSSL_NO_ASM) && defined(__arm__)
+
+.syntax unified
+.cpu cortex-a8
+.fpu neon
+.text
+.thumb
+.align 2
+.global CRYPTO_arm_neon_probe
+.hidden CRYPTO_arm_neon_probe
+.type CRYPTO_arm_neon_probe, %function
+.thumb_func
+CRYPTO_arm_neon_probe:
+ vorr q1, q1, q1
+ bx lr
+.section .note.GNU-stack,"",%progbits
+
+#endif /* !OPENSSL_NO_ASM && __arm__ */
diff --git a/src/crypto/cpu-arm.c b/src/crypto/cpu-arm.c
index 96392d8..74e937b 100644
--- a/src/crypto/cpu-arm.c
+++ b/src/crypto/cpu-arm.c
@@ -17,7 +17,12 @@
#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
#include <inttypes.h>
-#include <stdio.h>
+#include <string.h>
+
+#if !defined(OPENSSL_TRUSTY)
+#include <setjmp.h>
+#include <signal.h>
+#endif
#include "arm_arch.h"
@@ -28,14 +33,15 @@
unsigned long getauxval(unsigned long type) __attribute__((weak));
-static const unsigned long AT_HWCAP = 16;
-static const unsigned long AT_HWCAP2 = 26;
-
char CRYPTO_is_NEON_capable(void) {
return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
}
+static char g_set_neon_called = 0;
+
void CRYPTO_set_NEON_capable(char neon_capable) {
+ g_set_neon_called = 1;
+
if (neon_capable) {
OPENSSL_armcap_P |= ARMV7_NEON;
} else {
@@ -56,11 +62,81 @@ void CRYPTO_set_NEON_functional(char neon_functional) {
}
}
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM) && !defined(OPENSSL_TRUSTY)
+
+static sigjmp_buf sigill_jmp;
+
+static void sigill_handler(int signal) {
+ siglongjmp(sigill_jmp, signal);
+}
+
+void CRYPTO_arm_neon_probe();
+
+// probe_for_NEON returns 1 if a NEON instruction runs successfully. Because
+// getauxval doesn't exist on Android until Jelly Bean, supporting NEON on
+// older devices requires this.
+static int probe_for_NEON() {
+ int supported = 0;
+
+ sigset_t sigmask;
+ sigfillset(&sigmask);
+ sigdelset(&sigmask, SIGILL);
+ sigdelset(&sigmask, SIGTRAP);
+ sigdelset(&sigmask, SIGFPE);
+ sigdelset(&sigmask, SIGBUS);
+ sigdelset(&sigmask, SIGSEGV);
+
+ struct sigaction sigill_original_action, sigill_action;
+ memset(&sigill_action, 0, sizeof(sigill_action));
+ sigill_action.sa_handler = sigill_handler;
+ sigill_action.sa_mask = sigmask;
+
+ sigset_t original_sigmask;
+ sigprocmask(SIG_SETMASK, &sigmask, &original_sigmask);
+
+ if (sigsetjmp(sigill_jmp, 1 /* save signals */) == 0) {
+ sigaction(SIGILL, &sigill_action, &sigill_original_action);
+
+ // This function cannot be inline asm because GCC will refuse to compile
+ // inline NEON instructions unless building with -mfpu=neon, which would
+ // defeat the point of probing for support at runtime.
+ CRYPTO_arm_neon_probe();
+ supported = 1;
+ }
+ // Note that Android up to and including Lollipop doesn't restore the signal
+ // mask correctly after returning from a sigsetjmp. So that would need to be
+ // set again here if more probes were added.
+ // See https://android-review.googlesource.com/#/c/127624/
+
+ sigaction(SIGILL, &sigill_original_action, NULL);
+ sigprocmask(SIG_SETMASK, &original_sigmask, NULL);
+
+ return supported;
+}
+
+#else
+
+static int probe_for_NEON(void) {
+ return 0;
+}
+
+#endif /* !OPENSSL_NO_ASM && OPENSSL_ARM && !OPENSSL_TRUSTY */
+
void OPENSSL_cpuid_setup(void) {
if (getauxval == NULL) {
+ // On ARM, but not AArch64, try a NEON instruction and see whether it works
+ // in order to probe for NEON support.
+ //
+ // Note that |CRYPTO_is_NEON_capable| can be true even if
+ // |CRYPTO_set_NEON_capable| has never been called if the code was compiled
+ // with NEON support enabled (e.g. -mfpu=neon).
+ if (!g_set_neon_called && !CRYPTO_is_NEON_capable() && probe_for_NEON()) {
+ OPENSSL_armcap_P |= ARMV7_NEON;
+ }
return;
}
+ static const unsigned long AT_HWCAP = 16;
unsigned long hwcap = getauxval(AT_HWCAP);
#if defined(OPENSSL_ARM)
@@ -71,6 +147,7 @@ void OPENSSL_cpuid_setup(void) {
/* In 32-bit mode, the ARMv8 feature bits are in a different aux vector
* value. */
+ static const unsigned long AT_HWCAP2 = 26;
hwcap = getauxval(AT_HWCAP2);
/* See /usr/include/asm/hwcap.h on an ARM installation for the source of
@@ -93,7 +170,7 @@ void OPENSSL_cpuid_setup(void) {
}
#endif
- OPENSSL_armcap_P |= ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
+ OPENSSL_armcap_P |= ARMV7_NEON;
if (hwcap & kAES) {
OPENSSL_armcap_P |= ARMV8_AES;
diff --git a/src/crypto/cpu-intel.c b/src/crypto/cpu-intel.c
index 69f4570..df0e127 100644
--- a/src/crypto/cpu-intel.c
+++ b/src/crypto/cpu-intel.c
@@ -64,6 +64,7 @@
#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
#include <inttypes.h>
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
diff --git a/src/crypto/cpu-x86-asm.pl b/src/crypto/cpu-x86-asm.pl
index 1ac7d84..319c436 100644
--- a/src/crypto/cpu-x86-asm.pl
+++ b/src/crypto/cpu-x86-asm.pl
@@ -110,10 +110,6 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
&cmp ("ebp",0);
&jne (&label("notintel"));
&or ("edx",1<<30); # set reserved bit#30 on Intel CPUs
- &and (&HB("eax"),15); # familiy ID
- &cmp (&HB("eax"),15); # P4?
- &jne (&label("notintel"));
- &or ("edx",1<<20); # set reserved bit#20 to engage RC4_CHAR
&set_label("notintel");
&bt ("edx",28); # test hyper-threading bit
&jnc (&label("generic"));
diff --git a/src/crypto/cpu-x86_64-asm.pl b/src/crypto/cpu-x86_64-asm.pl
index 59cfd18..89d7a6c 100644
--- a/src/crypto/cpu-x86_64-asm.pl
+++ b/src/crypto/cpu-x86_64-asm.pl
@@ -122,10 +122,6 @@ OPENSSL_ia32_cpuid:
cmp \$0,%r9d
jne .Lnotintel
or \$0x40000000,%edx # set reserved bit#30 on Intel CPUs
- and \$15,%ah
- cmp \$15,%ah # examine Family ID
- jne .Lnotintel
- or \$0x00100000,%edx # set reserved bit#20 to engage RC4_CHAR
.Lnotintel:
bt \$28,%edx # test hyper-threading bit
jnc .Lgeneric
diff --git a/src/crypto/crypto_error.c b/src/crypto/crypto_error.c
deleted file mode 100644
index 3e63dca..0000000
--- a/src/crypto/crypto_error.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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/crypto.h>
-
-const ERR_STRING_DATA CRYPTO_error_string_data[] = {
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_set_ex_data, 0), "CRYPTO_set_ex_data"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_get_class, 0), "get_class"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_get_func_pointers, 0), "get_func_pointers"},
- {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_get_new_index, 0), "get_new_index"},
- {0, NULL},
-};
diff --git a/src/crypto/crypto_error.h b/src/crypto/crypto_error.h
deleted file mode 100644
index c0cb2bd..0000000
--- a/src/crypto/crypto_error.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* 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. */
-
-#define CRYPTO_F_CRYPTO_set_ex_data 100
-#define CRYPTO_F_get_class 101
-#define CRYPTO_F_get_new_index 102
-#define CRYPTO_F_get_func_pointers 103
diff --git a/src/crypto/des/des.c b/src/crypto/des/des.c
index 6d00011..56a2996 100644
--- a/src/crypto/des/des.c
+++ b/src/crypto/des/des.c
@@ -56,6 +56,8 @@
#include <openssl/des.h>
+#include <stdlib.h>
+
#include "internal.h"
@@ -349,6 +351,35 @@ void DES_set_key(const DES_cblock *key, DES_key_schedule *schedule) {
}
}
+static const uint8_t kOddParity[256] = {
+ 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14,
+ 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28,
+ 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44,
+ 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59,
+ 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74,
+ 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88,
+ 91, 91, 93, 93, 94, 94, 97, 97, 98, 98, 100, 100, 103, 103, 104,
+ 104, 107, 107, 109, 109, 110, 110, 112, 112, 115, 115, 117, 117, 118, 118,
+ 121, 121, 122, 122, 124, 124, 127, 127, 128, 128, 131, 131, 133, 133, 134,
+ 134, 137, 137, 138, 138, 140, 140, 143, 143, 145, 145, 146, 146, 148, 148,
+ 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 161, 161, 162, 162, 164,
+ 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174, 176, 176, 179, 179,
+ 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191, 193, 193, 194,
+ 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206, 208, 208,
+ 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223, 224,
+ 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239,
+ 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254,
+ 254
+};
+
+void DES_set_odd_parity(DES_cblock *key) {
+ unsigned i;
+
+ for (i = 0; i < DES_KEY_SZ; i++) {
+ key->bytes[i] = kOddParity[key->bytes[i]];
+ }
+}
+
static void DES_encrypt1(uint32_t *data, const DES_key_schedule *ks, int enc) {
uint32_t l, r, t, u;
const uint32_t *s;
@@ -609,6 +640,29 @@ void DES_ncbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
tin[0] = tin[1] = 0;
}
+void DES_ecb3_encrypt(const DES_cblock *input, DES_cblock *output,
+ const DES_key_schedule *ks1, const DES_key_schedule *ks2,
+ const DES_key_schedule *ks3, int enc) {
+ uint32_t l0, l1;
+ uint32_t ll[2];
+ const uint8_t *in = input->bytes;
+ uint8_t *out = output->bytes;
+
+ c2l(in, l0);
+ c2l(in, l1);
+ ll[0] = l0;
+ ll[1] = l1;
+ if (enc) {
+ DES_encrypt3(ll, ks1, ks2, ks3);
+ } else {
+ DES_decrypt3(ll, ks1, ks2, ks3);
+ }
+ l0 = ll[0];
+ l1 = ll[1];
+ l2c(l0, out);
+ l2c(l1, out);
+}
+
void DES_ede3_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const DES_key_schedule *ks1,
const DES_key_schedule *ks2,
diff --git a/src/crypto/dh/CMakeLists.txt b/src/crypto/dh/CMakeLists.txt
index 4e31206..9e487d5 100644
--- a/src/crypto/dh/CMakeLists.txt
+++ b/src/crypto/dh/CMakeLists.txt
@@ -10,13 +10,12 @@ add_library(
params.c
check.c
dh_asn1.c
- dh_error.c
)
add_executable(
dh_test
- dh_test.c
+ dh_test.cc
)
target_link_libraries(dh_test crypto)
diff --git a/src/crypto/dh/dh.c b/src/crypto/dh/dh.c
index 7a50da7..ab7ed8b 100644
--- a/src/crypto/dh/dh.c
+++ b/src/crypto/dh/dh.c
@@ -66,10 +66,13 @@
#include <openssl/thread.h>
#include "internal.h"
+#include "../internal.h"
extern const DH_METHOD DH_default_method;
+static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
+
DH *DH_new(void) { return DH_new_method(NULL); }
DH *DH_new_method(const ENGINE *engine) {
@@ -90,14 +93,16 @@ DH *DH_new_method(const ENGINE *engine) {
}
METHOD_ref(dh->meth);
+ CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
+
dh->references = 1;
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data)) {
+ if (!CRYPTO_new_ex_data(&g_ex_data_class, dh, &dh->ex_data)) {
OPENSSL_free(dh);
return NULL;
}
if (dh->meth->init && !dh->meth->init(dh)) {
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data);
+ CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data);
METHOD_unref(dh->meth);
OPENSSL_free(dh);
return NULL;
@@ -120,7 +125,7 @@ void DH_free(DH *dh) {
}
METHOD_unref(dh->meth);
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data);
+ CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data);
if (dh->method_mont_p) BN_MONT_CTX_free(dh->method_mont_p);
if (dh->p != NULL) BN_clear_free(dh->p);
@@ -131,6 +136,7 @@ void DH_free(DH *dh) {
if (dh->counter != NULL) BN_clear_free(dh->counter);
if (dh->pub_key != NULL) BN_clear_free(dh->pub_key);
if (dh->priv_key != NULL) BN_clear_free(dh->priv_key);
+ CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
OPENSSL_free(dh);
}
@@ -173,9 +179,7 @@ static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) {
}
}
- if (*dst) {
- BN_free(*dst);
- }
+ BN_free(*dst);
*dst = a;
return 1;
}
@@ -198,11 +202,10 @@ static int int_dh_param_copy(DH *to, const DH *from, int is_x942) {
return 0;
}
- if (to->seed) {
- OPENSSL_free(to->seed);
- to->seed = NULL;
- to->seedlen = 0;
- }
+ OPENSSL_free(to->seed);
+ to->seed = NULL;
+ to->seedlen = 0;
+
if (from->seed) {
to->seed = BUF_memdup(from->seed, from->seedlen);
if (!to->seed) {
@@ -230,8 +233,12 @@ DH *DHparams_dup(const DH *dh) {
int DH_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_DH, argl, argp, new_func,
- dup_func, free_func);
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
+ dup_func, free_func)) {
+ return -1;
+ }
+ return index;
}
int DH_set_ex_data(DH *d, int idx, void *arg) {
diff --git a/src/crypto/dh/dh_error.c b/src/crypto/dh/dh_error.c
deleted file mode 100644
index 5ecc5d1..0000000
--- a/src/crypto/dh/dh_error.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* 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/dh.h>
-
-const ERR_STRING_DATA DH_error_string_data[] = {
- {ERR_PACK(ERR_LIB_DH, DH_F_DH_new_method, 0), "DH_new_method"},
- {ERR_PACK(ERR_LIB_DH, DH_F_compute_key, 0), "compute_key"},
- {ERR_PACK(ERR_LIB_DH, DH_F_generate_key, 0), "generate_key"},
- {ERR_PACK(ERR_LIB_DH, DH_F_generate_parameters, 0), "generate_parameters"},
- {ERR_PACK(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR), "BAD_GENERATOR"},
- {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PUBKEY), "INVALID_PUBKEY"},
- {ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_LARGE), "MODULUS_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PRIVATE_VALUE), "NO_PRIVATE_VALUE"},
- {0, NULL},
-};
diff --git a/src/crypto/dh/dh_impl.c b/src/crypto/dh/dh_impl.c
index 9f416b7..f269412 100644
--- a/src/crypto/dh/dh_impl.c
+++ b/src/crypto/dh/dh_impl.c
@@ -58,9 +58,11 @@
#include <openssl/bn.h>
#include <openssl/err.h>
+#include <openssl/thread.h>
#include "internal.h"
+
#define OPENSSL_DH_MAX_MODULUS_BITS 10000
static int generate_parameters(DH *ret, int prime_bits, int generator, BN_GENCB *cb) {
@@ -206,8 +208,8 @@ static int generate_key(DH *dh) {
pub_key = dh->pub_key;
}
- mont =
- BN_MONT_CTX_set_locked(&dh->method_mont_p, CRYPTO_LOCK_DH, dh->p, ctx);
+ mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
+ dh->p, ctx);
if (!mont) {
goto err;
}
@@ -243,10 +245,10 @@ err:
OPENSSL_PUT_ERROR(DH, generate_key, ERR_R_BN_LIB);
}
- if (pub_key != NULL && dh->pub_key == NULL) {
+ if (dh->pub_key == NULL) {
BN_free(pub_key);
}
- if (priv_key != NULL && dh->priv_key == NULL) {
+ if (dh->priv_key == NULL) {
BN_free(priv_key);
}
BN_CTX_free(ctx);
@@ -281,8 +283,8 @@ static int compute_key(DH *dh, unsigned char *out, const BIGNUM *pub_key) {
goto err;
}
- mont =
- BN_MONT_CTX_set_locked(&dh->method_mont_p, CRYPTO_LOCK_DH, dh->p, ctx);
+ mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
+ dh->p, ctx);
if (!mont) {
goto err;
}
diff --git a/src/crypto/dh/dh_test.c b/src/crypto/dh/dh_test.cc
index 3575f34..16a5ae0 100644
--- a/src/crypto/dh/dh_test.c
+++ b/src/crypto/dh/dh_test.cc
@@ -59,151 +59,153 @@
#include <stdio.h>
#include <string.h>
-#include <openssl/bio.h>
+#include <vector>
+
#include <openssl/bn.h>
#include <openssl/crypto.h>
+#include <openssl/err.h>
#include <openssl/mem.h>
#include "internal.h"
+#include "../test/scoped_types.h"
+#include "../test/stl_compat.h"
+
+
+static bool RunBasicTests();
+static bool RunRFC5114Tests();
+
+int main(int argc, char *argv[]) {
+ CRYPTO_library_init();
+ if (!RunBasicTests() ||
+ !RunRFC5114Tests()) {
+ ERR_print_errors_fp(stderr);
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
-static int cb(int p, int n, BN_GENCB *arg) {
+static int GenerateCallback(int p, int n, BN_GENCB *arg) {
char c = '*';
- if (p == 0)
+ if (p == 0) {
c = '.';
- if (p == 1)
+ } else if (p == 1) {
c = '+';
- if (p == 2)
+ } else if (p == 2) {
c = '*';
- if (p == 3)
+ } else if (p == 3) {
c = '\n';
- BIO_write(arg->arg, &c, 1);
- (void)BIO_flush(arg->arg);
+ }
+ FILE *out = reinterpret_cast<FILE*>(arg->arg);
+ fputc(c, out);
+ fflush(out);
return 1;
}
-static int run_rfc5114_tests(void);
-
-int main(int argc, char *argv[]) {
- BN_GENCB _cb;
- DH *a;
- DH *b = NULL;
- char buf[12];
- unsigned char *abuf = NULL, *bbuf = NULL;
- int i, alen, blen, aout, bout, ret = 1;
- BIO *out;
-
- CRYPTO_library_init();
-
- out = BIO_new(BIO_s_file());
- if (out == NULL) {
- return 1;
+static bool RunBasicTests() {
+ BN_GENCB cb;
+ BN_GENCB_set(&cb, &GenerateCallback, stdout);
+ ScopedDH a(DH_new());
+ if (!a || !DH_generate_parameters_ex(a.get(), 64, DH_GENERATOR_5, &cb)) {
+ return false;
}
- BIO_set_fp(out, stdout, BIO_NOCLOSE);
- BN_GENCB_set(&_cb, &cb, out);
- if (((a = DH_new()) == NULL) ||
- !DH_generate_parameters_ex(a, 64, DH_GENERATOR_5, &_cb)) {
- goto err;
+ int check_result;
+ if (!DH_check(a.get(), &check_result)) {
+ return false;
+ }
+ if (check_result & DH_CHECK_P_NOT_PRIME) {
+ printf("p value is not prime\n");
+ }
+ if (check_result & DH_CHECK_P_NOT_SAFE_PRIME) {
+ printf("p value is not a safe prime\n");
}
+ if (check_result & DH_CHECK_UNABLE_TO_CHECK_GENERATOR) {
+ printf("unable to check the generator value\n");
+ }
+ if (check_result & DH_CHECK_NOT_SUITABLE_GENERATOR) {
+ printf("the g value is not a generator\n");
+ }
+
+ printf("\np = ");
+ BN_print_fp(stdout, a->p);
+ printf("\ng = ");
+ BN_print_fp(stdout, a->g);
+ printf("\n");
- if (!DH_check(a, &i))
- goto err;
- if (i & DH_CHECK_P_NOT_PRIME)
- BIO_puts(out, "p value is not prime\n");
- if (i & DH_CHECK_P_NOT_SAFE_PRIME)
- BIO_puts(out, "p value is not a safe prime\n");
- if (i & DH_CHECK_UNABLE_TO_CHECK_GENERATOR)
- BIO_puts(out, "unable to check the generator value\n");
- if (i & DH_CHECK_NOT_SUITABLE_GENERATOR)
- BIO_puts(out, "the g value is not a generator\n");
-
- BIO_puts(out, "\np =");
- BN_print(out, a->p);
- BIO_puts(out, "\ng =");
- BN_print(out, a->g);
- BIO_puts(out, "\n");
-
- b = DH_new();
- if (b == NULL) {
- goto err;
+ ScopedDH b(DH_new());
+ if (!b) {
+ return false;
}
b->p = BN_dup(a->p);
b->g = BN_dup(a->g);
- if (b->p == NULL || b->g == NULL) {
- goto err;
+ if (b->p == nullptr || b->g == nullptr) {
+ return false;
}
- if (!DH_generate_key(a))
- goto err;
- BIO_puts(out, "pri 1=");
- BN_print(out, a->priv_key);
- BIO_puts(out, "\npub 1=");
- BN_print(out, a->pub_key);
- BIO_puts(out, "\n");
-
- if (!DH_generate_key(b))
- goto err;
- BIO_puts(out, "pri 2=");
- BN_print(out, b->priv_key);
- BIO_puts(out, "\npub 2=");
- BN_print(out, b->pub_key);
- BIO_puts(out, "\n");
-
- alen = DH_size(a);
- abuf = (unsigned char *)OPENSSL_malloc(alen);
- aout = DH_compute_key(abuf, b->pub_key, a);
-
- BIO_puts(out, "key1 =");
- for (i = 0; i < aout; i++) {
- sprintf(buf, "%02X", abuf[i]);
- BIO_puts(out, buf);
+ if (!DH_generate_key(a.get())) {
+ return false;
}
- BIO_puts(out, "\n");
+ printf("pri1 = ");
+ BN_print_fp(stdout, a->priv_key);
+ printf("\npub1 = ");
+ BN_print_fp(stdout, a->pub_key);
+ printf("\n");
+
+ if (!DH_generate_key(b.get())) {
+ return false;
+ }
+ printf("pri2 = ");
+ BN_print_fp(stdout, b->priv_key);
+ printf("\npub2 = ");
+ BN_print_fp(stdout, b->pub_key);
+ printf("\n");
+
+ std::vector<uint8_t> key1(DH_size(a.get()));
+ int ret = DH_compute_key(bssl::vector_data(&key1), b->pub_key, a.get());
+ if (ret < 0) {
+ return false;
+ }
+ key1.resize(ret);
+
+ printf("key1 = ");
+ for (size_t i = 0; i < key1.size(); i++) {
+ printf("%02x", key1[i]);
+ }
+ printf("\n");
- blen = DH_size(b);
- bbuf = (unsigned char *)OPENSSL_malloc(blen);
- bout = DH_compute_key(bbuf, a->pub_key, b);
+ std::vector<uint8_t> key2(DH_size(b.get()));
+ ret = DH_compute_key(bssl::vector_data(&key2), a->pub_key, b.get());
+ if (ret < 0) {
+ return false;
+ }
+ key2.resize(ret);
- BIO_puts(out, "key2 =");
- for (i = 0; i < bout; i++) {
- sprintf(buf, "%02X", bbuf[i]);
- BIO_puts(out, buf);
+ printf("key2 = ");
+ for (size_t i = 0; i < key2.size(); i++) {
+ printf("%02x", key2[i]);
}
- BIO_puts(out, "\n");
- if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
+ printf("\n");
+
+ if (key1.size() < 4 || key1 != key2) {
fprintf(stderr, "Error in DH routines\n");
- ret = 1;
- } else
- ret = 0;
-
- if (!run_rfc5114_tests())
- ret = 1;
-
-err:
- BIO_print_errors_fp(stderr);
-
- if (abuf != NULL)
- OPENSSL_free(abuf);
- if (bbuf != NULL)
- OPENSSL_free(bbuf);
- if (b != NULL)
- DH_free(b);
- if (a != NULL)
- DH_free(a);
- BIO_free(out);
- return ret;
+ return false;
+ }
+
+ return true;
}
/* Test data from RFC 5114 */
-static const unsigned char dhtest_1024_160_xA[] = {
+static const uint8_t kDHTest1024_160_xA[] = {
0xB9, 0xA3, 0xB3, 0xAE, 0x8F, 0xEF, 0xC1, 0xA2, 0x93, 0x04,
0x96, 0x50, 0x70, 0x86, 0xF8, 0x45, 0x5D, 0x48, 0x94, 0x3E};
-static const unsigned char dhtest_1024_160_yA[] = {
+static const uint8_t kDHTest1024_160_yA[] = {
0x2A, 0x85, 0x3B, 0x3D, 0x92, 0x19, 0x75, 0x01, 0xB9, 0x01, 0x5B, 0x2D,
0xEB, 0x3E, 0xD8, 0x4F, 0x5E, 0x02, 0x1D, 0xCC, 0x3E, 0x52, 0xF1, 0x09,
0xD3, 0x27, 0x3D, 0x2B, 0x75, 0x21, 0x28, 0x1C, 0xBA, 0xBE, 0x0E, 0x76,
@@ -215,10 +217,10 @@ static const unsigned char dhtest_1024_160_yA[] = {
0x8F, 0x9D, 0x45, 0x96, 0x5F, 0x75, 0xA5, 0xF3, 0xD1, 0xDF, 0x37, 0x01,
0x16, 0x5F, 0xC9, 0xE5, 0x0C, 0x42, 0x79, 0xCE, 0xB0, 0x7F, 0x98, 0x95,
0x40, 0xAE, 0x96, 0xD5, 0xD8, 0x8E, 0xD7, 0x76};
-static const unsigned char dhtest_1024_160_xB[] = {
+static const uint8_t kDHTest1024_160_xB[] = {
0x93, 0x92, 0xC9, 0xF9, 0xEB, 0x6A, 0x7A, 0x6A, 0x90, 0x22,
0xF7, 0xD8, 0x3E, 0x72, 0x23, 0xC6, 0x83, 0x5B, 0xBD, 0xDA};
-static const unsigned char dhtest_1024_160_yB[] = {
+static const uint8_t kDHTest1024_160_yB[] = {
0x71, 0x7A, 0x6C, 0xB0, 0x53, 0x37, 0x1F, 0xF4, 0xA3, 0xB9, 0x32, 0x94,
0x1C, 0x1E, 0x56, 0x63, 0xF8, 0x61, 0xA1, 0xD6, 0xAD, 0x34, 0xAE, 0x66,
0x57, 0x6D, 0xFB, 0x98, 0xF6, 0xC6, 0xCB, 0xF9, 0xDD, 0xD5, 0xA5, 0x6C,
@@ -230,7 +232,7 @@ static const unsigned char dhtest_1024_160_yB[] = {
0x31, 0x1E, 0x53, 0xFD, 0x2C, 0x14, 0xB5, 0x74, 0xE6, 0xA3, 0x10, 0x9A,
0x3D, 0xA1, 0xBE, 0x41, 0xBD, 0xCE, 0xAA, 0x18, 0x6F, 0x5C, 0xE0, 0x67,
0x16, 0xA2, 0xB6, 0xA0, 0x7B, 0x3C, 0x33, 0xFE};
-static const unsigned char dhtest_1024_160_Z[] = {
+static const uint8_t kDHTest1024_160_Z[] = {
0x5C, 0x80, 0x4F, 0x45, 0x4D, 0x30, 0xD9, 0xC4, 0xDF, 0x85, 0x27, 0x1F,
0x93, 0x52, 0x8C, 0x91, 0xDF, 0x6B, 0x48, 0xAB, 0x5F, 0x80, 0xB3, 0xB5,
0x9C, 0xAA, 0xC1, 0xB2, 0x8F, 0x8A, 0xCB, 0xA9, 0xCD, 0x3E, 0x39, 0xF3,
@@ -242,11 +244,11 @@ static const unsigned char dhtest_1024_160_Z[] = {
0x5B, 0xD8, 0x3A, 0x19, 0xFB, 0x0B, 0x5E, 0x96, 0xBF, 0x8F, 0xA4, 0xD0,
0x9E, 0x34, 0x55, 0x25, 0x16, 0x7E, 0xCD, 0x91, 0x55, 0x41, 0x6F, 0x46,
0xF4, 0x08, 0xED, 0x31, 0xB6, 0x3C, 0x6E, 0x6D};
-static const unsigned char dhtest_2048_224_xA[] = {
+static const uint8_t kDHTest2048_224_xA[] = {
0x22, 0xE6, 0x26, 0x01, 0xDB, 0xFF, 0xD0, 0x67, 0x08, 0xA6,
0x80, 0xF7, 0x47, 0xF3, 0x61, 0xF7, 0x6D, 0x8F, 0x4F, 0x72,
0x1A, 0x05, 0x48, 0xE4, 0x83, 0x29, 0x4B, 0x0C};
-static const unsigned char dhtest_2048_224_yA[] = {
+static const uint8_t kDHTest2048_224_yA[] = {
0x1B, 0x3A, 0x63, 0x45, 0x1B, 0xD8, 0x86, 0xE6, 0x99, 0xE6, 0x7B, 0x49,
0x4E, 0x28, 0x8B, 0xD7, 0xF8, 0xE0, 0xD3, 0x70, 0xBA, 0xDD, 0xA7, 0xA0,
0xEF, 0xD2, 0xFD, 0xE7, 0xD8, 0xF6, 0x61, 0x45, 0xCC, 0x9F, 0x28, 0x04,
@@ -269,11 +271,11 @@ static const unsigned char dhtest_2048_224_yA[] = {
0xB7, 0x0E, 0x71, 0x03, 0x92, 0x0A, 0xA1, 0x6D, 0x85, 0xE5, 0x2B, 0xCB,
0xAB, 0x8D, 0x78, 0x6A, 0x68, 0x17, 0x8F, 0xA8, 0xFF, 0x7C, 0x2F, 0x5C,
0x71, 0x64, 0x8D, 0x6F};
-static const unsigned char dhtest_2048_224_xB[] = {
+static const uint8_t kDHTest2048_224_xB[] = {
0x4F, 0xF3, 0xBC, 0x96, 0xC7, 0xFC, 0x6A, 0x6D, 0x71, 0xD3,
0xB3, 0x63, 0x80, 0x0A, 0x7C, 0xDF, 0xEF, 0x6F, 0xC4, 0x1B,
0x44, 0x17, 0xEA, 0x15, 0x35, 0x3B, 0x75, 0x90};
-static const unsigned char dhtest_2048_224_yB[] = {
+static const uint8_t kDHTest2048_224_yB[] = {
0x4D, 0xCE, 0xE9, 0x92, 0xA9, 0x76, 0x2A, 0x13, 0xF2, 0xF8, 0x38, 0x44,
0xAD, 0x3D, 0x77, 0xEE, 0x0E, 0x31, 0xC9, 0x71, 0x8B, 0x3D, 0xB6, 0xC2,
0x03, 0x5D, 0x39, 0x61, 0x18, 0x2C, 0x3E, 0x0B, 0xA2, 0x47, 0xEC, 0x41,
@@ -296,7 +298,7 @@ static const unsigned char dhtest_2048_224_yB[] = {
0xB8, 0x56, 0xF9, 0x68, 0x27, 0x73, 0x4C, 0x18, 0x41, 0x38, 0xE9, 0x15,
0xD9, 0xC3, 0x00, 0x2E, 0xBC, 0xE5, 0x31, 0x20, 0x54, 0x6A, 0x7E, 0x20,
0x02, 0x14, 0x2B, 0x6C};
-static const unsigned char dhtest_2048_224_Z[] = {
+static const uint8_t kDHTest2048_224_Z[] = {
0x34, 0xD9, 0xBD, 0xDC, 0x1B, 0x42, 0x17, 0x6C, 0x31, 0x3F, 0xEA, 0x03,
0x4C, 0x21, 0x03, 0x4D, 0x07, 0x4A, 0x63, 0x13, 0xBB, 0x4E, 0xCD, 0xB3,
0x70, 0x3F, 0xFF, 0x42, 0x45, 0x67, 0xA4, 0x6B, 0xDF, 0x75, 0x53, 0x0E,
@@ -319,11 +321,11 @@ static const unsigned char dhtest_2048_224_Z[] = {
0x03, 0xE1, 0x3F, 0x95, 0x29, 0x95, 0xFB, 0x03, 0xC6, 0x9D, 0x3C, 0xC4,
0x7F, 0xCB, 0x51, 0x0B, 0x69, 0x98, 0xFF, 0xD3, 0xAA, 0x6D, 0xE7, 0x3C,
0xF9, 0xF6, 0x38, 0x69};
-static const unsigned char dhtest_2048_256_xA[] = {
+static const uint8_t kDHTest2048_256_xA[] = {
0x08, 0x81, 0x38, 0x2C, 0xDB, 0x87, 0x66, 0x0C, 0x6D, 0xC1, 0x3E,
0x61, 0x49, 0x38, 0xD5, 0xB9, 0xC8, 0xB2, 0xF2, 0x48, 0x58, 0x1C,
0xC5, 0xE3, 0x1B, 0x35, 0x45, 0x43, 0x97, 0xFC, 0xE5, 0x0E};
-static const unsigned char dhtest_2048_256_yA[] = {
+static const uint8_t kDHTest2048_256_yA[] = {
0x2E, 0x93, 0x80, 0xC8, 0x32, 0x3A, 0xF9, 0x75, 0x45, 0xBC, 0x49, 0x41,
0xDE, 0xB0, 0xEC, 0x37, 0x42, 0xC6, 0x2F, 0xE0, 0xEC, 0xE8, 0x24, 0xA6,
0xAB, 0xDB, 0xE6, 0x6C, 0x59, 0xBE, 0xE0, 0x24, 0x29, 0x11, 0xBF, 0xB9,
@@ -346,11 +348,11 @@ static const unsigned char dhtest_2048_256_yA[] = {
0x4E, 0x90, 0x52, 0x69, 0x34, 0x1D, 0xC0, 0x71, 0x14, 0x26, 0x68, 0x5F,
0x4E, 0xF3, 0x7E, 0x86, 0x8A, 0x81, 0x26, 0xFF, 0x3F, 0x22, 0x79, 0xB5,
0x7C, 0xA6, 0x7E, 0x29};
-static const unsigned char dhtest_2048_256_xB[] = {
+static const uint8_t kDHTest2048_256_xB[] = {
0x7D, 0x62, 0xA7, 0xE3, 0xEF, 0x36, 0xDE, 0x61, 0x7B, 0x13, 0xD1,
0xAF, 0xB8, 0x2C, 0x78, 0x0D, 0x83, 0xA2, 0x3B, 0xD4, 0xEE, 0x67,
0x05, 0x64, 0x51, 0x21, 0xF3, 0x71, 0xF5, 0x46, 0xA5, 0x3D};
-static const unsigned char dhtest_2048_256_yB[] = {
+static const uint8_t kDHTest2048_256_yB[] = {
0x57, 0x5F, 0x03, 0x51, 0xBD, 0x2B, 0x1B, 0x81, 0x74, 0x48, 0xBD, 0xF8,
0x7A, 0x6C, 0x36, 0x2C, 0x1E, 0x28, 0x9D, 0x39, 0x03, 0xA3, 0x0B, 0x98,
0x32, 0xC5, 0x74, 0x1F, 0xA2, 0x50, 0x36, 0x3E, 0x7A, 0xCB, 0xC7, 0xF7,
@@ -373,7 +375,7 @@ static const unsigned char dhtest_2048_256_yB[] = {
0x90, 0xB8, 0x9D, 0x24, 0xF7, 0x1B, 0x0A, 0xB6, 0x97, 0x82, 0x3D, 0x7D,
0xEB, 0x1A, 0xFF, 0x5B, 0x0E, 0x8E, 0x4A, 0x45, 0xD4, 0x9F, 0x7F, 0x53,
0x75, 0x7E, 0x19, 0x13};
-static const unsigned char dhtest_2048_256_Z[] = {
+static const uint8_t kDHTest2048_256_Z[] = {
0x86, 0xC7, 0x0B, 0xF8, 0xD0, 0xBB, 0x81, 0xBB, 0x01, 0x07, 0x8A, 0x17,
0x21, 0x9C, 0xB7, 0xD2, 0x72, 0x03, 0xDB, 0x2A, 0x19, 0xC8, 0x77, 0xF1,
0xD1, 0xF1, 0x9F, 0xD7, 0xD7, 0x7E, 0xF2, 0x25, 0x46, 0xA6, 0x8F, 0x00,
@@ -397,106 +399,82 @@ static const unsigned char dhtest_2048_256_Z[] = {
0xEA, 0x87, 0xFE, 0xBE, 0x63, 0xB6, 0xC8, 0xF8, 0x46, 0xEC, 0x6D, 0xB0,
0xC2, 0x6C, 0x5D, 0x7C};
-typedef struct {
+struct RFC5114TestData {
DH *(*get_param)(const ENGINE *engine);
- const unsigned char *xA;
+ const uint8_t *xA;
size_t xA_len;
- const unsigned char *yA;
+ const uint8_t *yA;
size_t yA_len;
- const unsigned char *xB;
+ const uint8_t *xB;
size_t xB_len;
- const unsigned char *yB;
+ const uint8_t *yB;
size_t yB_len;
- const unsigned char *Z;
+ const uint8_t *Z;
size_t Z_len;
-} rfc5114_td;
+};
-#define make_rfc5114_td(pre) \
+#define MAKE_RFC5114_TEST_DATA(pre) \
{ \
- DH_get_##pre, dhtest_##pre##_xA, sizeof(dhtest_##pre##_xA), \
- dhtest_##pre##_yA, sizeof(dhtest_##pre##_yA), dhtest_##pre##_xB, \
- sizeof(dhtest_##pre##_xB), dhtest_##pre##_yB, \
- sizeof(dhtest_##pre##_yB), dhtest_##pre##_Z, sizeof(dhtest_##pre##_Z) \
+ DH_get_##pre, kDHTest##pre##_xA, sizeof(kDHTest##pre##_xA), \
+ kDHTest##pre##_yA, sizeof(kDHTest##pre##_yA), kDHTest##pre##_xB, \
+ sizeof(kDHTest##pre##_xB), kDHTest##pre##_yB, \
+ sizeof(kDHTest##pre##_yB), kDHTest##pre##_Z, sizeof(kDHTest##pre##_Z) \
}
-static const rfc5114_td rfctd[] = {make_rfc5114_td(1024_160),
- make_rfc5114_td(2048_224),
- make_rfc5114_td(2048_256)};
-
-static int run_rfc5114_tests(void) {
- int i;
- DH *dhA = NULL, *dhB = NULL;
- unsigned char *Z1 = NULL, *Z2 = NULL;
+static const RFC5114TestData kRFCTestData[] = {
+ MAKE_RFC5114_TEST_DATA(1024_160),
+ MAKE_RFC5114_TEST_DATA(2048_224),
+ MAKE_RFC5114_TEST_DATA(2048_256),
+ };
- for (i = 0; i < (int)(sizeof(rfctd) / sizeof(rfc5114_td)); i++) {
- const rfc5114_td *td = rfctd + i;
+static bool RunRFC5114Tests() {
+ for (unsigned i = 0; i < sizeof(kRFCTestData) / sizeof(RFC5114TestData); i++) {
+ const RFC5114TestData *td = kRFCTestData + i;
/* Set up DH structures setting key components */
- dhA = td->get_param(NULL);
- dhB = td->get_param(NULL);
- if (!dhA || !dhB)
- goto bad_err;
-
- dhA->priv_key = BN_bin2bn(td->xA, td->xA_len, NULL);
- dhA->pub_key = BN_bin2bn(td->yA, td->yA_len, NULL);
-
- dhB->priv_key = BN_bin2bn(td->xB, td->xB_len, NULL);
- dhB->pub_key = BN_bin2bn(td->yB, td->yB_len, NULL);
-
- if (!dhA->priv_key || !dhA->pub_key || !dhB->priv_key || !dhB->pub_key)
- goto bad_err;
-
- if ((td->Z_len != (size_t)DH_size(dhA)) ||
- (td->Z_len != (size_t)DH_size(dhB)))
- goto err;
-
- Z1 = OPENSSL_malloc(DH_size(dhA));
- Z2 = OPENSSL_malloc(DH_size(dhB));
+ ScopedDH dhA(td->get_param(nullptr));
+ ScopedDH dhB(td->get_param(nullptr));
+ if (!dhA || !dhB) {
+ fprintf(stderr, "Initialisation error RFC5114 set %u\n", i + 1);
+ return false;
+ }
+
+ dhA->priv_key = BN_bin2bn(td->xA, td->xA_len, nullptr);
+ dhA->pub_key = BN_bin2bn(td->yA, td->yA_len, nullptr);
+
+ dhB->priv_key = BN_bin2bn(td->xB, td->xB_len, nullptr);
+ dhB->pub_key = BN_bin2bn(td->yB, td->yB_len, nullptr);
+
+ if (!dhA->priv_key || !dhA->pub_key || !dhB->priv_key || !dhB->pub_key) {
+ fprintf(stderr, "BN_bin2bn error RFC5114 set %u\n", i + 1);
+ return false;
+ }
+
+ if ((td->Z_len != (size_t)DH_size(dhA.get())) ||
+ (td->Z_len != (size_t)DH_size(dhB.get()))) {
+ return false;
+ }
+
+ std::vector<uint8_t> Z1(DH_size(dhA.get()));
+ std::vector<uint8_t> Z2(DH_size(dhB.get()));
/* Work out shared secrets using both sides and compare
- * with expected values.
- */
- if (!DH_compute_key(Z1, dhB->pub_key, dhA))
- goto bad_err;
- if (!DH_compute_key(Z2, dhA->pub_key, dhB))
- goto bad_err;
-
- if (memcmp(Z1, td->Z, td->Z_len))
- goto err;
- if (memcmp(Z2, td->Z, td->Z_len))
- goto err;
-
- printf("RFC5114 parameter test %d OK\n", i + 1);
-
- DH_free(dhA);
- dhA = NULL;
- DH_free(dhB);
- dhB = NULL;
- OPENSSL_free(Z1);
- Z1 = NULL;
- OPENSSL_free(Z2);
- Z2 = NULL;
+ * with expected values. */
+ int ret1 = DH_compute_key(bssl::vector_data(&Z1), dhB->pub_key, dhA.get());
+ int ret2 = DH_compute_key(bssl::vector_data(&Z2), dhA->pub_key, dhB.get());
+ if (ret1 < 0 || ret2 < 0) {
+ fprintf(stderr, "DH_compute_key error RFC5114 set %u\n", i + 1);
+ return false;
+ }
+
+ if (static_cast<size_t>(ret1) != td->Z_len ||
+ memcmp(bssl::vector_data(&Z1), td->Z, td->Z_len) != 0 ||
+ static_cast<size_t>(ret2) != td->Z_len ||
+ memcmp(bssl::vector_data(&Z2), td->Z, td->Z_len) != 0) {
+ fprintf(stderr, "Test failed RFC5114 set %u\n", i + 1);
+ return false;
+ }
+
+ printf("RFC5114 parameter test %u OK\n", i + 1);
}
- printf("PASS\n");
return 1;
-
-bad_err:
- fprintf(stderr, "Initalisation error RFC5114 set %d\n", i + 1);
- BIO_print_errors_fp(stderr);
-
-err:
- if (Z1 != NULL) {
- OPENSSL_free(Z1);
- }
- if (Z2 != NULL) {
- OPENSSL_free(Z2);
- }
- if (dhA != NULL) {
- DH_free(dhA);
- }
- if (dhB != NULL) {
- DH_free(dhB);
- }
-
- fprintf(stderr, "Test failed RFC5114 set %d\n", i + 1);
- return 0;
}
diff --git a/src/crypto/digest/CMakeLists.txt b/src/crypto/digest/CMakeLists.txt
index 6426399..8cab46a 100644
--- a/src/crypto/digest/CMakeLists.txt
+++ b/src/crypto/digest/CMakeLists.txt
@@ -7,13 +7,12 @@ add_library(
digest.c
digests.c
- digest_error.c
)
add_executable(
digest_test
- digest_test.c
+ digest_test.cc
)
target_link_libraries(digest_test crypto)
diff --git a/src/crypto/digest/digest.c b/src/crypto/digest/digest.c
index 3897c60..e32eafd 100644
--- a/src/crypto/digest/digest.c
+++ b/src/crypto/digest/digest.c
@@ -68,8 +68,6 @@
int EVP_MD_type(const EVP_MD *md) { return md->type; }
-const char *EVP_MD_name(const EVP_MD *md) { return OBJ_nid2sn(md->type); }
-
uint32_t EVP_MD_flags(const EVP_MD *md) { return md->flags; }
size_t EVP_MD_size(const EVP_MD *md) { return md->md_size; }
diff --git a/src/crypto/digest/digest_error.c b/src/crypto/digest/digest_error.c
deleted file mode 100644
index 0cc6702..0000000
--- a/src/crypto/digest/digest_error.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/* 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/digest.h>
-
-const ERR_STRING_DATA DIGEST_error_string_data[] = {
- {ERR_PACK(ERR_LIB_DIGEST, DIGEST_F_EVP_DigestInit_ex, 0), "EVP_DigestInit_ex"},
- {ERR_PACK(ERR_LIB_DIGEST, DIGEST_F_EVP_MD_CTX_copy_ex, 0), "EVP_MD_CTX_copy_ex"},
- {ERR_PACK(ERR_LIB_DIGEST, 0, DIGEST_R_INPUT_NOT_INITIALIZED), "INPUT_NOT_INITIALIZED"},
- {0, NULL},
-};
diff --git a/src/crypto/digest/digest_test.c b/src/crypto/digest/digest_test.cc
index 6c73e95..dcb569c 100644
--- a/src/crypto/digest/digest_test.c
+++ b/src/crypto/digest/digest_test.cc
@@ -23,102 +23,118 @@
#include <openssl/md5.h>
#include <openssl/sha.h>
+#include "../test/scoped_types.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. */
+
+struct MD {
+ // name is the name of the digest.
+ const char* name;
+ // md_func is the digest to test.
+ const EVP_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. */
+};
+
+static const MD md4 = { "MD4", &EVP_md4, nullptr };
+static const MD md5 = { "MD5", &EVP_md5, &MD5 };
+static const MD sha1 = { "SHA1", &EVP_sha1, &SHA1 };
+static const MD sha224 = { "SHA224", &EVP_sha224, &SHA224 };
+static const MD sha256 = { "SHA256", &EVP_sha256, &SHA256 };
+static const MD sha384 = { "SHA384", &EVP_sha384, &SHA384 };
+static const MD sha512 = { "SHA512", &EVP_sha512, &SHA512 };
+static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr };
+
+struct TestVector {
+ // md is the digest to test.
+ const MD &md;
+ // input is a NUL-terminated string to hash.
const char *input;
- /* repeat is the number of times to repeat input. */
+ // repeat is the number of times to repeat input.
size_t repeat;
- /* expected_hex is the expected digest in hexadecimal. */
+ // 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,
+};
+
+static const TestVector kTestVectors[] = {
+ // MD4 tests, from RFC 1320. (crypto/md4 does not provide a
+ // one-shot MD4 function.)
+ { md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0" },
+ { md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24" },
+ { md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d" },
+ { md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b" },
+ { md4, "abcdefghijklmnopqrstuvwxyz", 1,
"d79e1c308aa5bbcdeea8ed63df412da9" },
- { &EVP_md4, NULL,
+ { md4,
"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,
+ { md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536" },
+
+ // MD5 tests, from RFC 1321.
+ { md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e" },
+ { md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661" },
+ { md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72" },
+ { md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0" },
+ { md5, "abcdefghijklmnopqrstuvwxyz", 1,
"c3fcd3d76192e4007dfb496cca67e13b" },
- { &EVP_md5, &MD5,
+ { md5,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
"d174ab98d277d9f5a5611c2c9f419d9f" },
- { &EVP_md5, &MD5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" },
+ { md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" },
- /* SHA-1 tests, from RFC 3174. */
- { &EVP_sha1, &SHA1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" },
- { &EVP_sha1, &SHA1,
+ // SHA-1 tests, from RFC 3174.
+ { sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" },
+ { sha1,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"84983e441c3bd26ebaae4aa1f95129e5e54670f1" },
- { &EVP_sha1, &SHA1, "a", 1000000,
- "34aa973cd4c4daa4f61eeb2bdbad27316534016f" },
- { &EVP_sha1, &SHA1,
+ { sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f" },
+ { sha1,
"0123456701234567012345670123456701234567012345670123456701234567", 10,
"dea356a2cddd90c7a7ecedc5ebb563934f460452" },
- /* SHA-224 tests, from RFC 3874. */
- { &EVP_sha224, &SHA224, "abc", 1,
+ // SHA-224 tests, from RFC 3874.
+ { sha224, "abc", 1,
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" },
- { &EVP_sha224, &SHA224,
+ { sha224,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" },
- { &EVP_sha224, &SHA224,
+ { sha224,
"a", 1000000,
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" },
- /* SHA-256 tests, from NIST. */
- { &EVP_sha256, &SHA256, "abc", 1,
+ // SHA-256 tests, from NIST.
+ { sha256, "abc", 1,
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" },
- { &EVP_sha256, &SHA256,
+ { sha256,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" },
- /* SHA-384 tests, from NIST. */
- { &EVP_sha384, &SHA384, "abc", 1,
+ // SHA-384 tests, from NIST.
+ { sha384, "abc", 1,
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
"8086072ba1e7cc2358baeca134c825a7" },
- { &EVP_sha384, &SHA384,
+ { sha384,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
"fcc7c71a557e2db966c3e9fa91746039" },
- /* SHA-512 tests, from NIST. */
- { &EVP_sha512, &SHA512, "abc", 1,
+ // SHA-512 tests, from NIST.
+ { sha512, "abc", 1,
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" },
- { &EVP_sha512, &SHA512,
+ { sha512,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
- /* MD5-SHA1 tests. */
- { &EVP_md5_sha1, NULL, "abc", 1,
+ // MD5-SHA1 tests.
+ { md5_sha1, "abc", 1,
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
};
-static int compare_digest(const TEST_VECTOR *test,
+static bool CompareDigest(const TestVector *test,
const uint8_t *digest,
size_t digest_len) {
static const char kHexTable[] = "0123456789abcdef";
@@ -133,107 +149,96 @@ static int compare_digest(const TEST_VECTOR *test,
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,
+ test->md.name, test->input, (int)test->repeat,
digest_hex, test->expected_hex);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-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);
+static int TestDigest(const TestVector *test) {
+ ScopedEVP_MD_CTX ctx;
- /* Test the input provided. */
- if (!EVP_DigestInit_ex(&ctx, test->md_func(), NULL)) {
+ // Test the input provided.
+ if (!EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)) {
fprintf(stderr, "EVP_DigestInit_ex failed\n");
- goto done;
+ return false;
}
- for (i = 0; i < test->repeat; i++) {
- if (!EVP_DigestUpdate(&ctx, test->input, strlen(test->input))) {
+ for (size_t i = 0; i < test->repeat; i++) {
+ if (!EVP_DigestUpdate(ctx.get(), test->input, strlen(test->input))) {
fprintf(stderr, "EVP_DigestUpdate failed\n");
- goto done;
+ return false;
}
}
- if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) {
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned digest_len;
+ if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) {
fprintf(stderr, "EVP_DigestFinal_ex failed\n");
- goto done;
+ return false;
}
- if (!compare_digest(test, digest, digest_len)) {
- goto done;
+ if (!CompareDigest(test, digest, digest_len)) {
+ return false;
}
- /* Test the input one character at a time. */
- if (!EVP_DigestInit_ex(&ctx, test->md_func(), NULL)) {
+ // Test the input one character at a time.
+ if (!EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)) {
fprintf(stderr, "EVP_DigestInit_ex failed\n");
- goto done;
+ return false;
}
- if (!EVP_DigestUpdate(&ctx, NULL, 0)) {
+ if (!EVP_DigestUpdate(ctx.get(), NULL, 0)) {
fprintf(stderr, "EVP_DigestUpdate failed\n");
- goto done;
+ return false;
}
- for (i = 0; i < test->repeat; i++) {
- const char *p;
- for (p = test->input; *p; p++) {
- if (!EVP_DigestUpdate(&ctx, p, 1)) {
+ for (size_t i = 0; i < test->repeat; i++) {
+ for (const char *p = test->input; *p; p++) {
+ if (!EVP_DigestUpdate(ctx.get(), p, 1)) {
fprintf(stderr, "EVP_DigestUpdate failed\n");
- goto done;
+ return false;
}
}
}
- if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) {
+ if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) {
fprintf(stderr, "EVP_DigestFinal_ex failed\n");
- goto done;
+ return false;
}
- if (digest_len != EVP_MD_size(test->md_func())) {
+ if (digest_len != EVP_MD_size(test->md.func())) {
fprintf(stderr, "EVP_MD_size output incorrect\n");
- goto done;
+ return false;
}
- if (!compare_digest(test, digest, digest_len)) {
- goto done;
+ if (!CompareDigest(test, digest, digest_len)) {
+ return false;
}
- /* 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);
+ // Test the one-shot function.
+ if (test->md.one_shot_func && test->repeat == 1) {
+ uint8_t *out = test->md.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;
+ return false;
}
- if (!compare_digest(test, digest, EVP_MD_size(test->md_func()))) {
- goto done;
+ if (!CompareDigest(test, digest, EVP_MD_size(test->md.func()))) {
+ return false;
}
- /* 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;
+ // Test the deprecated static buffer variant, until it's removed.
+ out = test->md.one_shot_func((const uint8_t *)test->input,
+ strlen(test->input), NULL);
+ if (!CompareDigest(test, out, EVP_MD_size(test->md.func()))) {
+ return false;
}
}
- ret = 1;
-
-done:
- EVP_MD_CTX_cleanup(&ctx);
- return ret;
+ return true;
}
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])) {
+ for (size_t i = 0; i < sizeof(kTestVectors) / sizeof(kTestVectors[0]); i++) {
+ if (!TestDigest(&kTestVectors[i])) {
fprintf(stderr, "Test %d failed\n", (int)i);
return 1;
}
diff --git a/src/crypto/digest/md32_common.h b/src/crypto/digest/md32_common.h
index a4ce355..d7caba2 100644
--- a/src/crypto/digest/md32_common.h
+++ b/src/crypto/digest/md32_common.h
@@ -51,8 +51,6 @@
#include <openssl/base.h>
-#include <string.h>
-
#if defined(__cplusplus)
extern "C" {
@@ -74,8 +72,7 @@ extern "C" {
* HASH_CBLOCK
* size of a unit chunk HASH_BLOCK operates on.
* HASH_LONG
- * has to be at lest 32 bit wide, if it's wider, then
- * HASH_LONG_LOG2 *has to* be defined along
+ * has to be at least 32 bit wide.
* HASH_CTX
* context structure that at least contains following
* members:
@@ -103,19 +100,6 @@ extern "C" {
* HASH_MAKE_STRING
* macro convering context variables to an ASCII hash string.
*
- * MD5 example:
- *
- * #define DATA_ORDER_IS_LITTLE_ENDIAN
- *
- * #define HASH_LONG MD5_LONG
- * #define HASH_LONG_LOG2 MD5_LONG_LOG2
- * #define HASH_CTX MD5_CTX
- * #define HASH_CBLOCK MD5_CBLOCK
- * #define HASH_UPDATE MD5_Update
- * #define HASH_TRANSFORM MD5_Transform
- * #define HASH_FINAL MD5_Final
- * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
- *
* <appro@fy.chalmers.se>
*/
diff --git a/src/crypto/directory_posix.c b/src/crypto/directory_posix.c
index c16701d..b944b69 100644
--- a/src/crypto/directory_posix.c
+++ b/src/crypto/directory_posix.c
@@ -35,6 +35,7 @@
#include <dirent.h>
#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#if defined(OPENSSL_PNACL)
diff --git a/src/crypto/directory_win.c b/src/crypto/directory_win.c
index 2e4600f..4ebacf2 100644
--- a/src/crypto/directory_win.c
+++ b/src/crypto/directory_win.c
@@ -41,6 +41,9 @@
#define NAME_MAX 255
#endif
+#include <openssl/mem.h>
+
+
struct OPENSSL_dir_context_st {
WIN32_FIND_DATA ctx;
HANDLE handle;
diff --git a/src/crypto/dsa/CMakeLists.txt b/src/crypto/dsa/CMakeLists.txt
index fbc053e..dab2c4c 100644
--- a/src/crypto/dsa/CMakeLists.txt
+++ b/src/crypto/dsa/CMakeLists.txt
@@ -8,7 +8,6 @@ add_library(
dsa.c
dsa_impl.c
dsa_asn1.c
- dsa_error.c
)
add_executable(
diff --git a/src/crypto/dsa/dsa.c b/src/crypto/dsa/dsa.c
index 8816b63..e8e3d73 100644
--- a/src/crypto/dsa/dsa.c
+++ b/src/crypto/dsa/dsa.c
@@ -67,12 +67,16 @@
#include <openssl/err.h>
#include <openssl/ex_data.h>
#include <openssl/mem.h>
+#include <openssl/thread.h>
#include "internal.h"
+#include "../internal.h"
extern const DSA_METHOD DSA_default_method;
+static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
+
DSA *DSA_new(void) { return DSA_new_method(NULL); }
DSA *DSA_new_method(const ENGINE *engine) {
@@ -96,14 +100,16 @@ DSA *DSA_new_method(const ENGINE *engine) {
dsa->write_params = 1;
dsa->references = 1;
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data)) {
+ CRYPTO_MUTEX_init(&dsa->method_mont_p_lock);
+
+ if (!CRYPTO_new_ex_data(&g_ex_data_class, dsa, &dsa->ex_data)) {
METHOD_unref(dsa->meth);
OPENSSL_free(dsa);
return NULL;
}
if (dsa->meth->init && !dsa->meth->init(dsa)) {
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data);
+ CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data);
METHOD_unref(dsa->meth);
OPENSSL_free(dsa);
return NULL;
@@ -126,22 +132,16 @@ void DSA_free(DSA *dsa) {
}
METHOD_unref(dsa->meth);
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data);
-
- if (dsa->p != NULL)
- BN_clear_free(dsa->p);
- if (dsa->q != NULL)
- BN_clear_free(dsa->q);
- if (dsa->g != NULL)
- BN_clear_free(dsa->g);
- if (dsa->pub_key != NULL)
- BN_clear_free(dsa->pub_key);
- if (dsa->priv_key != NULL)
- BN_clear_free(dsa->priv_key);
- if (dsa->kinv != NULL)
- BN_clear_free(dsa->kinv);
- if (dsa->r != NULL)
- BN_clear_free(dsa->r);
+ CRYPTO_free_ex_data(&g_ex_data_class, dsa, &dsa->ex_data);
+
+ BN_clear_free(dsa->p);
+ BN_clear_free(dsa->q);
+ BN_clear_free(dsa->g);
+ BN_clear_free(dsa->pub_key);
+ BN_clear_free(dsa->priv_key);
+ BN_clear_free(dsa->kinv);
+ BN_clear_free(dsa->r);
+ CRYPTO_MUTEX_cleanup(&dsa->method_mont_p_lock);
OPENSSL_free(dsa);
}
@@ -184,12 +184,8 @@ void DSA_SIG_free(DSA_SIG *sig) {
return;
}
- if (sig->r) {
- BN_free(sig->r);
- }
- if (sig->s) {
- BN_free(sig->s);
- }
+ BN_free(sig->r);
+ BN_free(sig->s);
OPENSSL_free(sig);
}
@@ -268,12 +264,8 @@ int DSA_check_signature(int *out_valid, const uint8_t *digest,
ret = DSA_do_check_signature(out_valid, digest, digest_len, s, dsa);
err:
- if (der != NULL) {
- OPENSSL_free(der);
- }
- if (s) {
- DSA_SIG_free(s);
- }
+ OPENSSL_free(der);
+ DSA_SIG_free(s);
return ret;
}
@@ -309,8 +301,12 @@ int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx, BIGNUM **out_kinv,
int DSA_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_DSA, argl, argp, new_func,
- dup_func, free_func);
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
+ dup_func, free_func)) {
+ return -1;
+ }
+ return index;
}
int DSA_set_ex_data(DSA *d, int idx, void *arg) {
@@ -347,8 +343,6 @@ DH *DSA_dup_DH(const DSA *r) {
return ret;
err:
- if (ret != NULL) {
- DH_free(ret);
- }
+ DH_free(ret);
return NULL;
}
diff --git a/src/crypto/dsa/dsa_error.c b/src/crypto/dsa/dsa_error.c
deleted file mode 100644
index 5a83908..0000000
--- a/src/crypto/dsa/dsa_error.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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/dsa.h>
-
-const ERR_STRING_DATA DSA_error_string_data[] = {
- {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_new_method, 0), "DSA_new_method"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_dsa_sig_cb, 0), "dsa_sig_cb"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_sign, 0), "sign"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_sign_setup, 0), "sign_setup"},
- {ERR_PACK(ERR_LIB_DSA, DSA_F_verify, 0), "verify"},
- {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BAD_Q_VALUE), "BAD_Q_VALUE"},
- {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
- {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MODULUS_TOO_LARGE), "MODULUS_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NEED_NEW_SETUP_VALUES), "NEED_NEW_SETUP_VALUES"},
- {0, NULL},
-};
diff --git a/src/crypto/dsa/dsa_impl.c b/src/crypto/dsa/dsa_impl.c
index 6719758..b7e1fd8 100644
--- a/src/crypto/dsa/dsa_impl.c
+++ b/src/crypto/dsa/dsa_impl.c
@@ -66,6 +66,7 @@
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
+#include <openssl/thread.h>
#include "internal.h"
@@ -122,14 +123,16 @@ static int sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BN_set_flags(&k, BN_FLG_CONSTTIME);
- if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
- CRYPTO_LOCK_DSA, dsa->p, ctx)) {
+ if (BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p,
+ ctx) == NULL) {
goto err;
}
/* Compute r = (g^k mod p) mod q */
- if (!BN_copy(&kq, &k))
+ if (!BN_copy(&kq, &k)) {
goto err;
+ }
/* We do not want timing information to leak the length of k,
* so we compute g^k using an equivalent exponent of fixed length.
@@ -137,11 +140,11 @@ static int sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
* (This is a kludge that we need because the BN_mod_exp_mont()
* does not let us specify the desired timing behaviour.) */
- if (!BN_add(&kq, &kq, dsa->q))
+ if (!BN_add(&kq, &kq, dsa->q)) {
+ goto err;
+ }
+ if (BN_num_bits(&kq) <= BN_num_bits(dsa->q) && !BN_add(&kq, &kq, dsa->q)) {
goto err;
- if (BN_num_bits(&kq) <= BN_num_bits(dsa->q)) {
- if (!BN_add(&kq, &kq, dsa->q))
- goto err;
}
K = &kq;
@@ -159,14 +162,10 @@ static int sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
goto err;
}
- if (*kinvp != NULL) {
- BN_clear_free(*kinvp);
- }
+ BN_clear_free(*kinvp);
*kinvp = kinv;
kinv = NULL;
- if (*rp != NULL) {
- BN_clear_free(*rp);
- }
+ BN_clear_free(*rp);
*rp = r;
ret = 1;
@@ -274,15 +273,10 @@ err:
BN_free(r);
BN_free(s);
}
- if (ctx != NULL) {
- BN_CTX_free(ctx);
- }
+ BN_CTX_free(ctx);
BN_clear_free(&m);
BN_clear_free(&xr);
- if (kinv != NULL) {
- /* dsa->kinv is NULL now if we used it */
- BN_clear_free(kinv);
- }
+ BN_clear_free(kinv);
return ret;
}
@@ -363,12 +357,14 @@ static int verify(int *out_valid, const uint8_t *dgst, size_t digest_len,
}
mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
- CRYPTO_LOCK_DSA, dsa->p, ctx);
+ (CRYPTO_MUTEX *)&dsa->method_mont_p_lock,
+ dsa->p, ctx);
if (!mont) {
goto err;
}
- if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, mont)) {
+ if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx,
+ mont)) {
goto err;
}
@@ -387,9 +383,7 @@ err:
if (ret != 1) {
OPENSSL_PUT_ERROR(DSA, verify, ERR_R_BN_LIB);
}
- if (ctx != NULL) {
- BN_CTX_free(ctx);
- }
+ BN_CTX_free(ctx);
BN_free(&u1);
BN_free(&u2);
BN_free(&t1);
@@ -442,15 +436,13 @@ static int keygen(DSA *dsa) {
ok = 1;
err:
- if (pub_key != NULL && dsa->pub_key == NULL) {
+ if (dsa->pub_key == NULL) {
BN_free(pub_key);
}
- if (priv_key != NULL && dsa->priv_key == NULL) {
+ if (dsa->priv_key == NULL) {
BN_free(priv_key);
}
- if (ctx != NULL) {
- BN_CTX_free(ctx);
- }
+ BN_CTX_free(ctx);
return ok;
}
@@ -701,15 +693,9 @@ end:
err:
if (ok) {
- if (ret->p) {
- BN_free(ret->p);
- }
- if (ret->q) {
- BN_free(ret->q);
- }
- if (ret->g) {
- BN_free(ret->g);
- }
+ BN_free(ret->p);
+ BN_free(ret->q);
+ BN_free(ret->g);
ret->p = BN_dup(p);
ret->q = BN_dup(q);
ret->g = BN_dup(g);
@@ -730,9 +716,7 @@ err:
BN_CTX_free(ctx);
}
- if (mont != NULL) {
- BN_MONT_CTX_free(mont);
- }
+ BN_MONT_CTX_free(mont);
return ok;
}
diff --git a/src/crypto/dsa/dsa_test.c b/src/crypto/dsa/dsa_test.c
index 1273638..9b70dbe 100644
--- a/src/crypto/dsa/dsa_test.c
+++ b/src/crypto/dsa/dsa_test.c
@@ -61,7 +61,6 @@
#include <string.h>
-#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
@@ -166,9 +165,6 @@ static const uint8_t fips_sig_bad_r[] = {
0xdc, 0xd8, 0xc8,
};
-static BIO *bio_err = NULL;
-static BIO *bio_out = NULL;
-
static DSA *get_fips_dsa(void) {
DSA *dsa = DSA_new();
if (!dsa) {
@@ -187,7 +183,7 @@ static DSA *get_fips_dsa(void) {
return dsa;
}
-static int test_generate(void) {
+static int test_generate(FILE *out) {
BN_GENCB cb;
DSA *dsa = NULL;
int counter, ok = 0, i, j;
@@ -196,49 +192,49 @@ static int test_generate(void) {
uint8_t sig[256];
unsigned int siglen;
- BIO_printf(bio_out, "test generation of DSA parameters\n");
+ fprintf(out, "test generation of DSA parameters\n");
- BN_GENCB_set(&cb, dsa_cb, bio_out);
+ BN_GENCB_set(&cb, dsa_cb, out);
dsa = DSA_new();
if (dsa == NULL ||
!DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, &cb)) {
goto end;
}
- BIO_printf(bio_out, "seed\n");
+ fprintf(out, "seed\n");
for (i = 0; i < 20; i += 4) {
- BIO_printf(bio_out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2],
- seed[i + 3]);
+ fprintf(out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2],
+ seed[i + 3]);
}
- BIO_printf(bio_out, "\ncounter=%d h=%ld\n", counter, h);
+ fprintf(out, "\ncounter=%d h=%ld\n", counter, h);
if (counter != 105) {
- BIO_printf(bio_err, "counter should be 105\n");
+ fprintf(stderr, "counter should be 105\n");
goto end;
}
if (h != 2) {
- BIO_printf(bio_err, "h should be 2\n");
+ fprintf(stderr, "h should be 2\n");
goto end;
}
i = BN_bn2bin(dsa->q, buf);
j = sizeof(fips_q);
if (i != j || memcmp(buf, fips_q, i) != 0) {
- BIO_printf(bio_err, "q value is wrong\n");
+ fprintf(stderr, "q value is wrong\n");
goto end;
}
i = BN_bn2bin(dsa->p, buf);
j = sizeof(fips_p);
if (i != j || memcmp(buf, fips_p, i) != 0) {
- BIO_printf(bio_err, "p value is wrong\n");
+ fprintf(stderr, "p value is wrong\n");
goto end;
}
i = BN_bn2bin(dsa->g, buf);
j = sizeof(fips_g);
if (i != j || memcmp(buf, fips_g, i) != 0) {
- BIO_printf(bio_err, "g value is wrong\n");
+ fprintf(stderr, "g value is wrong\n");
goto end;
}
@@ -247,13 +243,11 @@ static int test_generate(void) {
if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa) == 1) {
ok = 1;
} else {
- BIO_printf(bio_err, "verification failure\n");
+ fprintf(stderr, "verification failure\n");
}
end:
- if (dsa != NULL) {
- DSA_free(dsa);
- }
+ DSA_free(dsa);
return ok;
}
@@ -267,7 +261,7 @@ static int test_verify(const uint8_t *sig, size_t sig_len, int expect) {
int ret = DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa);
if (ret != expect) {
- BIO_printf(bio_err, "DSA_verify returned %d, want %d\n", ret, expect);
+ fprintf(stderr, "DSA_verify returned %d, want %d\n", ret, expect);
goto end;
}
ok = 1;
@@ -275,9 +269,7 @@ static int test_verify(const uint8_t *sig, size_t sig_len, int expect) {
ERR_clear_error();
end:
- if (dsa != NULL) {
- DSA_free(dsa);
- }
+ DSA_free(dsa);
return ok;
}
@@ -285,23 +277,16 @@ end:
int main(int argc, char **argv) {
CRYPTO_library_init();
- bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
- bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
-
- if (!test_generate() ||
+ if (!test_generate(stdout) ||
!test_verify(fips_sig, sizeof(fips_sig), 1) ||
!test_verify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
!test_verify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
!test_verify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
!test_verify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
- BIO_print_errors(bio_err);
- BIO_free(bio_err);
- BIO_free(bio_out);
+ ERR_print_errors_fp(stderr);
return 1;
}
- BIO_free(bio_err);
- BIO_free(bio_out);
printf("PASS\n");
return 0;
}
@@ -326,11 +311,11 @@ static int dsa_cb(int p, int n, BN_GENCB *arg) {
c = '\n';
}
- BIO_write(arg->arg, &c, 1);
- (void)BIO_flush(arg->arg);
+ fputc(c, arg->arg);
+ fflush(arg->arg);
if (!ok && p == 0 && num > 1) {
- BIO_printf((BIO *)arg, "error in dsatest\n");
+ fprintf(stderr, "error in dsatest\n");
return 0;
}
diff --git a/src/crypto/ec/CMakeLists.txt b/src/crypto/ec/CMakeLists.txt
index 11266c6..a218c0d 100644
--- a/src/crypto/ec/CMakeLists.txt
+++ b/src/crypto/ec/CMakeLists.txt
@@ -6,13 +6,14 @@ add_library(
OBJECT
ec.c
+ ec_asn1.c
+ ec_key.c
+ ec_montgomery.c
oct.c
+ p256-64.c
+ util-64.c
simple.c
- ec_montgomery.c
wnaf.c
- ec_key.c
- ec_asn1.c
- ec_error.c
)
add_executable(
@@ -24,7 +25,7 @@ add_executable(
add_executable(
ec_test
- ec_test.c
+ ec_test.cc
)
target_link_libraries(example_mul crypto)
diff --git a/src/crypto/ec/ec.c b/src/crypto/ec/ec.c
index 6e676c9..5426b8f 100644
--- a/src/crypto/ec/ec.c
+++ b/src/crypto/ec/ec.c
@@ -219,11 +219,18 @@ static const struct curve_data P521 = {
0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09}};
const struct built_in_curve OPENSSL_built_in_curves[] = {
- {NID_secp224r1, &P224, 0},
- {NID_X9_62_prime256v1, &P256, 0},
- {NID_secp384r1, &P384, 0},
- {NID_secp521r1, &P521, 0},
- {NID_undef, 0, 0},
+ {NID_secp224r1, &P224, 0},
+ {
+ NID_X9_62_prime256v1, &P256,
+#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS)
+ EC_GFp_nistp256_method,
+#else
+ 0,
+#endif
+ },
+ {NID_secp384r1, &P384, 0},
+ {NID_secp521r1, &P521, 0},
+ {NID_undef, 0, 0},
};
EC_GROUP *ec_group_new(const EC_METHOD *meth) {
@@ -357,22 +364,14 @@ err:
EC_GROUP_free(group);
group = NULL;
}
- if (P)
- EC_POINT_free(P);
- if (ctx)
- BN_CTX_free(ctx);
- if (p)
- BN_free(p);
- if (a)
- BN_free(a);
- if (b)
- BN_free(b);
- if (order)
- BN_free(order);
- if (x)
- BN_free(x);
- if (y)
- BN_free(y);
+ EC_POINT_free(P);
+ BN_CTX_free(ctx);
+ BN_free(p);
+ BN_free(a);
+ BN_free(b);
+ BN_free(order);
+ BN_free(x);
+ BN_free(y);
return group;
}
@@ -409,16 +408,14 @@ void EC_GROUP_free(EC_GROUP *group) {
ec_pre_comp_free(group->pre_comp);
- if (group->generator != NULL) {
- EC_POINT_free(group->generator);
- }
+ EC_POINT_free(group->generator);
BN_free(&group->order);
BN_free(&group->cofactor);
OPENSSL_free(group);
}
-int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) {
+int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
if (dest->meth->group_copy == 0) {
OPENSSL_PUT_ERROR(EC, EC_GROUP_copy, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
@@ -474,7 +471,7 @@ EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
if (t == NULL) {
return NULL;
}
- if (!EC_GROUP_copy(t, a)) {
+ if (!ec_group_copy(t, a)) {
goto err;
}
@@ -482,9 +479,7 @@ EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
err:
if (!ok) {
- if (t) {
- EC_GROUP_free(t);
- }
+ EC_GROUP_free(t);
return NULL;
} else {
return t;
diff --git a/src/crypto/ec/ec_asn1.c b/src/crypto/ec/ec_asn1.c
index ce9b3f4..ff3dca6 100644
--- a/src/crypto/ec/ec_asn1.c
+++ b/src/crypto/ec/ec_asn1.c
@@ -172,9 +172,7 @@ ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
return NULL;
}
} else {
- if (ret->value.named_curve) {
- ASN1_OBJECT_free(ret->value.named_curve);
- }
+ ASN1_OBJECT_free(ret->value.named_curve);
}
/* use the ASN.1 OID to describe the the elliptic curve parameters. */
@@ -257,10 +255,8 @@ static EC_GROUP *d2i_ECPKParameters(EC_GROUP **groupp, const uint8_t **inp,
return NULL;
}
- if (groupp && *groupp) {
- EC_GROUP_free(*groupp);
- }
if (groupp) {
+ EC_GROUP_free(*groupp);
*groupp = group;
}
@@ -290,16 +286,9 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **in, long len) {
EC_KEY *ret = NULL;
EC_PRIVATEKEY *priv_key = NULL;
- priv_key = EC_PRIVATEKEY_new();
- if (priv_key == NULL) {
- OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len);
+ priv_key = d2i_EC_PRIVATEKEY(NULL, in, len);
if (priv_key == NULL) {
OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
- EC_PRIVATEKEY_free(priv_key);
return NULL;
}
@@ -309,17 +298,12 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **in, long len) {
OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (a) {
- *a = ret;
- }
} else {
ret = *a;
}
if (priv_key->parameters) {
- if (ret->group) {
- EC_GROUP_free(ret->group);
- }
+ EC_GROUP_free(ret->group);
ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
}
@@ -343,9 +327,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **in, long len) {
goto err;
}
- if (ret->pub_key) {
- EC_POINT_free(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);
@@ -380,22 +362,20 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **in, long len) {
ret->enc_flag |= EC_PKEY_NO_PUBKEY;
}
+ if (a) {
+ *a = ret;
+ }
ok = 1;
err:
if (!ok) {
- if (ret) {
+ if (a == NULL || *a != ret) {
EC_KEY_free(ret);
}
ret = NULL;
- if (a) {
- *a = ret;
- }
}
- if (priv_key) {
- EC_PRIVATEKEY_free(priv_key);
- }
+ EC_PRIVATEKEY_free(priv_key);
return ret;
}
@@ -419,14 +399,14 @@ int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
priv_key->version = key->version;
- buf_len = BN_num_bytes(key->priv_key);
+ buf_len = BN_num_bytes(&key->group->order);
buffer = OPENSSL_malloc(buf_len);
if (buffer == NULL) {
OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!BN_bn2bin(key->priv_key, buffer)) {
+ if (!BN_bn2bin_padded(buffer, buf_len, key->priv_key)) {
OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_BN_LIB);
goto err;
}
@@ -488,12 +468,8 @@ int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
ok = 1;
err:
- if (buffer) {
- OPENSSL_free(buffer);
- }
- if (priv_key) {
- EC_PRIVATEKEY_free(priv_key);
- }
+ OPENSSL_free(buffer);
+ EC_PRIVATEKEY_free(priv_key);
return (ok ? ret : 0);
}
@@ -519,18 +495,21 @@ EC_KEY *d2i_ECParameters(EC_KEY **key, const uint8_t **inp, long len) {
OPENSSL_PUT_ERROR(EC, d2i_ECParameters, ERR_R_MALLOC_FAILURE);
return NULL;
}
- if (key) {
- *key = ret;
- }
} else {
ret = *key;
}
if (!d2i_ECPKParameters(&ret->group, inp, len)) {
OPENSSL_PUT_ERROR(EC, d2i_ECParameters, ERR_R_EC_LIB);
+ if (key == NULL || *key == NULL) {
+ EC_KEY_free(ret);
+ }
return NULL;
}
+ if (key) {
+ *key = ret;
+ }
return ret;
}
diff --git a/src/crypto/ec/ec_error.c b/src/crypto/ec/ec_error.c
deleted file mode 100644
index 73807c7..0000000
--- a/src/crypto/ec/ec_error.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* 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/ec.h>
-
-const ERR_STRING_DATA EC_error_string_data[] = {
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_copy, 0), "EC_GROUP_copy"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_get_curve_GFp, 0), "EC_GROUP_get_curve_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_get_degree, 0), "EC_GROUP_get_degree"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_new_by_curve_name, 0), "EC_GROUP_new_by_curve_name"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_check_key, 0), "EC_KEY_check_key"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_copy, 0), "EC_KEY_copy"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_generate_key, 0), "EC_KEY_generate_key"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_new_method, 0), "EC_KEY_new_method"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_set_public_key_affine_coordinates, 0), "EC_KEY_set_public_key_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_add, 0), "EC_POINT_add"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_cmp, 0), "EC_POINT_cmp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_copy, 0), "EC_POINT_copy"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_dbl, 0), "EC_POINT_dbl"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_dup, 0), "EC_POINT_dup"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_get_affine_coordinates_GFp, 0), "EC_POINT_get_affine_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_invert, 0), "EC_POINT_invert"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_is_at_infinity, 0), "EC_POINT_is_at_infinity"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_is_on_curve, 0), "EC_POINT_is_on_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_make_affine, 0), "EC_POINT_make_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_new, 0), "EC_POINT_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_oct2point, 0), "EC_POINT_oct2point"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_point2oct, 0), "EC_POINT_point2oct"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_set_affine_coordinates_GFp, 0), "EC_POINT_set_affine_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_set_compressed_coordinates_GFp, 0), "EC_POINT_set_compressed_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_set_to_infinity, 0), "EC_POINT_set_to_infinity"},
- {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTs_make_affine, 0), "EC_POINTs_make_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_compute_wNAF, 0), "compute_wNAF"},
- {ERR_PACK(ERR_LIB_EC, EC_F_d2i_ECPKParameters, 0), "d2i_ECPKParameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_d2i_ECParameters, 0), "d2i_ECParameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_d2i_ECPrivateKey, 0), "d2i_ECPrivateKey"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_decode, 0), "ec_GFp_mont_field_decode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_encode, 0), "ec_GFp_mont_field_encode"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_mul, 0), "ec_GFp_mont_field_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_set_to_one, 0), "ec_GFp_mont_field_set_to_one"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_sqr, 0), "ec_GFp_mont_field_sqr"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_group_set_curve, 0), "ec_GFp_mont_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_group_check_discriminant, 0), "ec_GFp_simple_group_check_discriminant"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_group_set_curve, 0), "ec_GFp_simple_group_set_curve"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_make_affine, 0), "ec_GFp_simple_make_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_oct2point, 0), "ec_GFp_simple_oct2point"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_point2oct, 0), "ec_GFp_simple_point2oct"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_point_get_affine_coordinates, 0), "ec_GFp_simple_point_get_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_point_set_affine_coordinates, 0), "ec_GFp_simple_point_set_affine_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_points_make_affine, 0), "ec_GFp_simple_points_make_affine"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_set_compressed_coordinates, 0), "ec_GFp_simple_set_compressed_coordinates"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_asn1_group2pkparameters, 0), "ec_asn1_group2pkparameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_asn1_pkparameters2group, 0), "ec_asn1_pkparameters2group"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_group_new, 0), "ec_group_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_group_new_curve_GFp, 0), "ec_group_new_curve_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_group_new_from_data, 0), "ec_group_new_from_data"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_point_set_Jprojective_coordinates_GFp, 0), "ec_point_set_Jprojective_coordinates_GFp"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_pre_comp_new, 0), "ec_pre_comp_new"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_wNAF_mul, 0), "ec_wNAF_mul"},
- {ERR_PACK(ERR_LIB_EC, EC_F_ec_wNAF_precompute_mult, 0), "ec_wNAF_precompute_mult"},
- {ERR_PACK(ERR_LIB_EC, EC_F_i2d_ECPKParameters, 0), "i2d_ECPKParameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_i2d_ECParameters, 0), "i2d_ECParameters"},
- {ERR_PACK(ERR_LIB_EC, EC_F_i2d_ECPrivateKey, 0), "i2d_ECPrivateKey"},
- {ERR_PACK(ERR_LIB_EC, EC_F_i2o_ECPublicKey, 0), "i2o_ECPublicKey"},
- {ERR_PACK(ERR_LIB_EC, EC_F_o2i_ECPublicKey, 0), "o2i_ECPublicKey"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_COORDINATES_OUT_OF_RANGE), "COORDINATES_OUT_OF_RANGE"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_D2I_ECPKPARAMETERS_FAILURE), "D2I_ECPKPARAMETERS_FAILURE"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE), "EC_GROUP_NEW_BY_NAME_FAILURE"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_GF2M_NOT_SUPPORTED), "GF2M_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_GROUP2PKPARAMETERS_FAILURE), "GROUP2PKPARAMETERS_FAILURE"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_I2D_ECPKPARAMETERS_FAILURE), "I2D_ECPKPARAMETERS_FAILURE"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_INCOMPATIBLE_OBJECTS), "INCOMPATIBLE_OBJECTS"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSED_POINT), "INVALID_COMPRESSED_POINT"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSION_BIT), "INVALID_COMPRESSION_BIT"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ENCODING), "INVALID_ENCODING"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FIELD), "INVALID_FIELD"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FORM), "INVALID_FORM"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_GROUP_ORDER), "INVALID_GROUP_ORDER"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PRIVATE_KEY), "INVALID_PRIVATE_KEY"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PRIVATE_KEY), "MISSING_PRIVATE_KEY"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_NON_NAMED_CURVE), "NON_NAMED_CURVE"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_INITIALIZED), "NOT_INITIALIZED"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_PKPARAMETERS2GROUP_FAILURE), "PKPARAMETERS2GROUP_FAILURE"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_AT_INFINITY), "POINT_AT_INFINITY"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_IS_NOT_ON_CURVE), "POINT_IS_NOT_ON_CURVE"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_SLOT_FULL), "SLOT_FULL"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_GENERATOR), "UNDEFINED_GENERATOR"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_GROUP), "UNKNOWN_GROUP"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_ORDER), "UNKNOWN_ORDER"},
- {ERR_PACK(ERR_LIB_EC, 0, EC_R_WRONG_ORDER), "WRONG_ORDER"},
- {0, NULL},
-};
diff --git a/src/crypto/ec/ec_key.c b/src/crypto/ec/ec_key.c
index 471ea9c..3652ba5 100644
--- a/src/crypto/ec/ec_key.c
+++ b/src/crypto/ec/ec_key.c
@@ -74,10 +74,14 @@
#include <openssl/err.h>
#include <openssl/ex_data.h>
#include <openssl/mem.h>
+#include <openssl/thread.h>
#include "internal.h"
+#include "../internal.h"
+static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
+
EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); }
EC_KEY *EC_KEY_new_method(const ENGINE *engine) {
@@ -100,7 +104,7 @@ EC_KEY *EC_KEY_new_method(const ENGINE *engine) {
ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
ret->references = 1;
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) {
+ if (!CRYPTO_new_ex_data(&g_ex_data_class, ret, &ret->ex_data)) {
goto err1;
}
@@ -111,7 +115,7 @@ EC_KEY *EC_KEY_new_method(const ENGINE *engine) {
return ret;
err2:
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data);
+ CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data);
err1:
if (ret->ecdsa_meth) {
METHOD_unref(ret->ecdsa_meth);
@@ -123,6 +127,7 @@ err1:
EC_KEY *EC_KEY_new_by_curve_name(int nid) {
EC_KEY *ret = EC_KEY_new();
if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_new_by_curve_name, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->group = EC_GROUP_new_by_curve_name(nid);
@@ -149,17 +154,11 @@ void EC_KEY_free(EC_KEY *r) {
METHOD_unref(r->ecdsa_meth);
}
- if (r->group != NULL) {
- EC_GROUP_free(r->group);
- }
- if (r->pub_key != NULL) {
- EC_POINT_free(r->pub_key);
- }
- if (r->priv_key != NULL) {
- BN_clear_free(r->priv_key);
- }
+ EC_GROUP_free(r->group);
+ EC_POINT_free(r->pub_key);
+ BN_clear_free(r->priv_key);
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
+ CRYPTO_free_ex_data(&g_ex_data_class, r, &r->ex_data);
OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
OPENSSL_free(r);
@@ -170,35 +169,23 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) {
OPENSSL_PUT_ERROR(EC, EC_KEY_copy, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
- /* copy the parameters */
+ /* Copy the parameters. */
if (src->group) {
/* TODO(fork): duplicating the group seems wasteful. */
- const EC_METHOD *meth = src->group->meth;
- /* clear the old group */
- if (dest->group) {
- EC_GROUP_free(dest->group);
- }
- dest->group = ec_group_new(meth);
+ EC_GROUP_free(dest->group);
+ dest->group = EC_GROUP_dup(src->group);
if (dest->group == NULL) {
return NULL;
}
- if (!EC_GROUP_copy(dest->group, src->group)) {
- return NULL;
- }
}
- /* copy the public key */
+ /* Copy the public key. */
if (src->pub_key && src->group) {
- if (dest->pub_key) {
- EC_POINT_free(dest->pub_key);
- }
- dest->pub_key = EC_POINT_new(src->group);
+ EC_POINT_free(dest->pub_key);
+ dest->pub_key = EC_POINT_dup(src->pub_key, src->group);
if (dest->pub_key == NULL) {
return NULL;
}
- if (!EC_POINT_copy(dest->pub_key, src->pub_key)) {
- return NULL;
- }
}
/* copy the private key */
@@ -214,8 +201,8 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) {
}
}
/* copy method/extra data */
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, dest, &dest->ex_data);
- if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data,
+ CRYPTO_free_ex_data(&g_ex_data_class, dest, &dest->ex_data);
+ if (!CRYPTO_dup_ex_data(&g_ex_data_class, &dest->ex_data,
&src->ex_data)) {
return NULL;
}
@@ -252,9 +239,7 @@ int EC_KEY_is_opaque(const EC_KEY *key) {
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; }
int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) {
- if (key->group != NULL) {
- EC_GROUP_free(key->group);
- }
+ EC_GROUP_free(key->group);
/* TODO(fork): duplicating the group seems wasteful but see
* |EC_KEY_set_conv_form|. */
key->group = EC_GROUP_dup(group);
@@ -266,9 +251,7 @@ const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) {
}
int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) {
- if (key->priv_key) {
- BN_clear_free(key->priv_key);
- }
+ BN_clear_free(key->priv_key);
key->priv_key = BN_dup(priv_key);
return (key->priv_key == NULL) ? 0 : 1;
}
@@ -278,9 +261,7 @@ const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) {
}
int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) {
- if (key->pub_key != NULL) {
- EC_POINT_free(key->pub_key);
- }
+ EC_POINT_free(key->pub_key);
key->pub_key = EC_POINT_dup(pub_key, key->group);
return (key->pub_key == NULL) ? 0 : 1;
}
@@ -371,10 +352,8 @@ int EC_KEY_check_key(const EC_KEY *eckey) {
ok = 1;
err:
- if (ctx != NULL)
- BN_CTX_free(ctx);
- if (point != NULL)
- EC_POINT_free(point);
+ BN_CTX_free(ctx);
+ EC_POINT_free(point);
return ok;
}
@@ -425,10 +404,8 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
ok = 1;
err:
- if (ctx)
- BN_CTX_free(ctx);
- if (point)
- EC_POINT_free(point);
+ BN_CTX_free(ctx);
+ EC_POINT_free(point);
return ok;
}
@@ -489,22 +466,26 @@ int EC_KEY_generate_key(EC_KEY *eckey) {
ok = 1;
err:
- if (order)
- BN_free(order);
- if (pub_key != NULL && eckey->pub_key == NULL)
+ BN_free(order);
+ if (eckey->pub_key == NULL) {
EC_POINT_free(pub_key);
- if (priv_key != NULL && eckey->priv_key == NULL)
+ }
+ if (eckey->priv_key == NULL) {
BN_free(priv_key);
- if (ctx != NULL)
- BN_CTX_free(ctx);
+ }
+ BN_CTX_free(ctx);
return ok;
}
int EC_KEY_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_EC_KEY, argl, argp, new_func,
- dup_func, free_func);
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
+ dup_func, free_func)) {
+ return -1;
+ }
+ return index;
}
int EC_KEY_set_ex_data(EC_KEY *d, int idx, void *arg) {
diff --git a/src/crypto/ec/ec_montgomery.c b/src/crypto/ec/ec_montgomery.c
index ab04556..74dbc6c 100644
--- a/src/crypto/ec/ec_montgomery.c
+++ b/src/crypto/ec/ec_montgomery.c
@@ -121,68 +121,58 @@ int ec_GFp_mont_group_init(EC_GROUP *group) {
int ok;
ok = ec_GFp_simple_group_init(group);
- group->field_data1 = NULL;
- group->field_data2 = NULL;
+ group->mont = NULL;
+ group->one = NULL;
return ok;
}
void ec_GFp_mont_group_finish(EC_GROUP *group) {
- if (group->field_data1 != NULL) {
- BN_MONT_CTX_free(group->field_data1);
- group->field_data1 = NULL;
- }
- if (group->field_data2 != NULL) {
- BN_free(group->field_data2);
- group->field_data2 = NULL;
- }
+ BN_MONT_CTX_free(group->mont);
+ group->mont = NULL;
+ BN_free(group->one);
+ group->one = NULL;
ec_GFp_simple_group_finish(group);
}
void ec_GFp_mont_group_clear_finish(EC_GROUP *group) {
- if (group->field_data1 != NULL) {
- BN_MONT_CTX_free(group->field_data1);
- group->field_data1 = NULL;
- }
- if (group->field_data2 != NULL) {
- BN_clear_free(group->field_data2);
- group->field_data2 = NULL;
- }
+ BN_MONT_CTX_free(group->mont);
+ group->mont = NULL;
+ BN_clear_free(group->one);
+ group->one = NULL;
ec_GFp_simple_group_clear_finish(group);
}
int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
- if (dest->field_data1 != NULL) {
- BN_MONT_CTX_free(dest->field_data1);
- dest->field_data1 = NULL;
- }
- if (dest->field_data2 != NULL) {
- BN_clear_free(dest->field_data2);
- dest->field_data2 = NULL;
- }
+ BN_MONT_CTX_free(dest->mont);
+ dest->mont = NULL;
+ BN_clear_free(dest->one);
+ dest->one = NULL;
- if (!ec_GFp_simple_group_copy(dest, src))
+ if (!ec_GFp_simple_group_copy(dest, src)) {
return 0;
+ }
- if (src->field_data1 != NULL) {
- dest->field_data1 = BN_MONT_CTX_new();
- if (dest->field_data1 == NULL)
+ if (src->mont != NULL) {
+ dest->mont = BN_MONT_CTX_new();
+ if (dest->mont == NULL) {
return 0;
- if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1))
+ }
+ if (!BN_MONT_CTX_copy(dest->mont, src->mont)) {
goto err;
+ }
}
- if (src->field_data2 != NULL) {
- dest->field_data2 = BN_dup(src->field_data2);
- if (dest->field_data2 == NULL)
+ if (src->one != NULL) {
+ dest->one = BN_dup(src->one);
+ if (dest->one == NULL) {
goto err;
+ }
}
return 1;
err:
- if (dest->field_data1 != NULL) {
- BN_MONT_CTX_free(dest->field_data1);
- dest->field_data1 = NULL;
- }
+ BN_MONT_CTX_free(dest->mont);
+ dest->mont = NULL;
return 0;
}
@@ -193,104 +183,101 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
BIGNUM *one = NULL;
int ret = 0;
- if (group->field_data1 != NULL) {
- BN_MONT_CTX_free(group->field_data1);
- group->field_data1 = NULL;
- }
- if (group->field_data2 != NULL) {
- BN_free(group->field_data2);
- group->field_data2 = NULL;
- }
+ BN_MONT_CTX_free(group->mont);
+ group->mont = NULL;
+ BN_free(group->one);
+ group->one = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
mont = BN_MONT_CTX_new();
- if (mont == NULL)
+ if (mont == NULL) {
goto err;
+ }
if (!BN_MONT_CTX_set(mont, p, ctx)) {
OPENSSL_PUT_ERROR(EC, ec_GFp_mont_group_set_curve, ERR_R_BN_LIB);
goto err;
}
one = BN_new();
- if (one == NULL)
- goto err;
- if (!BN_to_montgomery(one, BN_value_one(), mont, ctx))
+ if (one == NULL || !BN_to_montgomery(one, BN_value_one(), mont, ctx)) {
goto err;
+ }
- group->field_data1 = mont;
+ group->mont = mont;
mont = NULL;
- group->field_data2 = one;
+ group->one = one;
one = NULL;
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
if (!ret) {
- BN_MONT_CTX_free(group->field_data1);
- group->field_data1 = NULL;
- BN_free(group->field_data2);
- group->field_data2 = NULL;
+ BN_MONT_CTX_free(group->mont);
+ group->mont = NULL;
+ BN_free(group->one);
+ group->one = NULL;
}
err:
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
- if (mont != NULL)
- BN_MONT_CTX_free(mont);
+ BN_CTX_free(new_ctx);
+ BN_MONT_CTX_free(mont);
+ BN_free(one);
return ret;
}
int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx) {
- if (group->field_data1 == NULL) {
+ if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_mul, EC_R_NOT_INITIALIZED);
return 0;
}
- return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);
+ return BN_mod_mul_montgomery(r, a, b, group->mont, ctx);
}
int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx) {
- if (group->field_data1 == NULL) {
+ if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_sqr, EC_R_NOT_INITIALIZED);
return 0;
}
- return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);
+ return BN_mod_mul_montgomery(r, a, a, group->mont, ctx);
}
int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx) {
- if (group->field_data1 == NULL) {
+ if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_encode, EC_R_NOT_INITIALIZED);
return 0;
}
- return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);
+ return BN_to_montgomery(r, a, group->mont, ctx);
}
int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx) {
- if (group->field_data1 == NULL) {
+ if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_decode, EC_R_NOT_INITIALIZED);
return 0;
}
- return BN_from_montgomery(r, a, group->field_data1, ctx);
+ return BN_from_montgomery(r, a, group->mont, ctx);
}
int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
BN_CTX *ctx) {
- if (group->field_data2 == NULL) {
+ if (group->one == NULL) {
OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_set_to_one, EC_R_NOT_INITIALIZED);
return 0;
}
- if (!BN_copy(r, group->field_data2))
+ if (!BN_copy(r, group->one)) {
return 0;
+ }
return 1;
}
diff --git a/src/crypto/ec/ec_test.c b/src/crypto/ec/ec_test.c
deleted file mode 100644
index 8d53f87..0000000
--- a/src/crypto/ec/ec_test.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/* 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;
-}
diff --git a/src/crypto/ec/ec_test.cc b/src/crypto/ec/ec_test.cc
new file mode 100644
index 0000000..74685eb
--- /dev/null
+++ b/src/crypto/ec/ec_test.cc
@@ -0,0 +1,185 @@
+/* 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 <vector>
+
+#include <openssl/crypto.h>
+#include <openssl/ec_key.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "../test/scoped_types.h"
+#include "../test/stl_compat.h"
+
+
+// kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
+// omitted.
+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,
+};
+
+// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
+// the private key is one. The private key is incorrectly encoded without zero
+// padding.
+static const uint8_t kECKeyMissingZeros[] = {
+ 0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
+ 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
+ 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1,
+ 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
+ 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
+ 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
+};
+
+// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
+// the private key is one. The private key is encoded with the required zero
+// padding.
+static const uint8_t kECKeyWithZeros[] = {
+ 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1,
+ 0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
+ 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d,
+ 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3,
+ 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
+ 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
+ 0x37, 0xbf, 0x51, 0xf5,
+};
+
+// DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
+// result or nullptr on error.
+static ScopedEC_KEY DecodeECPrivateKey(const uint8_t *in, size_t in_len) {
+ const uint8_t *inp = in;
+ ScopedEC_KEY ret(d2i_ECPrivateKey(NULL, &inp, in_len));
+ if (!ret || inp != in + in_len) {
+ return nullptr;
+ }
+ return ret;
+}
+
+// EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
+// returns true on success or false on error.
+static bool EncodeECPrivateKey(std::vector<uint8_t> *out, EC_KEY *key) {
+ int len = i2d_ECPrivateKey(key, NULL);
+ out->resize(len);
+ uint8_t *outp = bssl::vector_data(out);
+ return i2d_ECPrivateKey(key, &outp) == len;
+}
+
+bool Testd2i_ECPrivateKey() {
+ ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithoutPublic,
+ sizeof(kECKeyWithoutPublic));
+ if (!key) {
+ fprintf(stderr, "Failed to parse private key.\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ std::vector<uint8_t> out;
+ if (!EncodeECPrivateKey(&out, key.get())) {
+ fprintf(stderr, "Failed to serialize private key.\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (std::vector<uint8_t>(kECKeyWithoutPublic,
+ kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) !=
+ out) {
+ fprintf(stderr, "Serialisation of key doesn't match original.\n");
+ return false;
+ }
+
+ const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
+ if (pub_key == NULL) {
+ fprintf(stderr, "Public key missing.\n");
+ return false;
+ }
+
+ ScopedBIGNUM x(BN_new());
+ ScopedBIGNUM y(BN_new());
+ if (!x || !y) {
+ return false;
+ }
+ if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
+ pub_key, x.get(), y.get(), NULL)) {
+ fprintf(stderr, "Failed to get public key in affine coordinates.\n");
+ return false;
+ }
+ ScopedOpenSSLString x_hex(BN_bn2hex(x.get()));
+ ScopedOpenSSLString y_hex(BN_bn2hex(y.get()));
+ if (0 != strcmp(
+ x_hex.get(),
+ "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681") ||
+ 0 != strcmp(
+ y_hex.get(),
+ "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88")) {
+ fprintf(stderr, "Incorrect public key: %s %s\n", x_hex.get(), y_hex.get());
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestZeroPadding() {
+ // Check that the correct encoding round-trips.
+ ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithZeros,
+ sizeof(kECKeyWithZeros));
+ std::vector<uint8_t> out;
+ if (!key || !EncodeECPrivateKey(&out, key.get())) {
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (std::vector<uint8_t>(kECKeyWithZeros,
+ kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) {
+ fprintf(stderr, "Serialisation of key was incorrect.\n");
+ return false;
+ }
+
+ // Keys without leading zeros also parse, but they encode correctly.
+ key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
+ if (!key || !EncodeECPrivateKey(&out, key.get())) {
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (std::vector<uint8_t>(kECKeyWithZeros,
+ kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) {
+ fprintf(stderr, "Serialisation of key was incorrect.\n");
+ return false;
+ }
+
+ return true;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (!Testd2i_ECPrivateKey() ||
+ !TestZeroPadding()) {
+ fprintf(stderr, "failed\n");
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/ec/internal.h b/src/crypto/ec/internal.h
index da116c4..0a8bf24 100644
--- a/src/crypto/ec/internal.h
+++ b/src/crypto/ec/internal.h
@@ -81,8 +81,6 @@ extern "C" {
/* Use default functions for poin2oct, oct2point and compressed coordinates */
#define EC_FLAGS_DEFAULT_OCT 0x1
-typedef struct ec_method_st EC_METHOD;
-
struct ec_method_st {
/* Various method flags */
int flags;
@@ -205,35 +203,14 @@ struct ec_group_st {
/* The following members are handled by the method functions,
* even if they appear generic */
- BIGNUM field; /* Field specification.
- * For curves over GF(p), this is the modulus;
- * for curves over GF(2^m), this is the
- * irreducible polynomial defining the field. */
-
- int poly[6]; /* Field specification for curves over GF(2^m).
- * The irreducible f(t) is then of the form:
- * t^poly[0] + t^poly[1] + ... + t^poly[k]
- * where m = poly[0] > poly[1] > ... > poly[k] = 0.
- * The array is terminated with poly[k+1]=-1.
- * All elliptic curve irreducibles have at most 5
- * non-zero terms. */
-
- BIGNUM a, b; /* Curve coefficients.
- * (Here the assumption is that BIGNUMs can be used
- * or abused for all kinds of fields, not just GF(p).)
- * For characteristic > 3, the curve is defined
- * by a Weierstrass equation of the form
- * y^2 = x^3 + a*x + b.
- * For characteristic 2, the curve is defined by
- * an equation of the form
- * y^2 + x*y = x^3 + a*x^2 + b. */
+ BIGNUM field; /* For curves over GF(p), this is the modulus. */
+
+ BIGNUM a, b; /* Curve coefficients. */
int a_is_minus3; /* enable optimized point arithmetics for special case */
- void *field_data1; /* method-specific (e.g., Montgomery structure) */
- void *field_data2; /* method-specific */
- int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *,
- BN_CTX *); /* method-specific */
+ BN_MONT_CTX *mont; /* Montgomery structure. */
+ BIGNUM *one; /* The value one */
} /* EC_GROUP */;
struct ec_point_st {
@@ -250,6 +227,7 @@ struct ec_point_st {
} /* EC_POINT */;
EC_GROUP *ec_group_new(const EC_METHOD *meth);
+int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src);
int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
@@ -329,6 +307,19 @@ int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
const BIGNUM *y, const BIGNUM *z,
BN_CTX *ctx);
+void ec_GFp_nistp_points_make_affine_internal(
+ size_t num, void *point_array, size_t felem_size, void *tmp_felems,
+ void (*felem_one)(void *out), int (*felem_is_zero)(const void *in),
+ void (*felem_assign)(void *out, const void *in),
+ void (*felem_square)(void *out, const void *in),
+ void (*felem_mul)(void *out, const void *in1, const void *in2),
+ void (*felem_inv)(void *out, const void *in),
+ void (*felem_contract)(void *out, const void *in));
+
+void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in);
+
+const EC_METHOD *EC_GFp_nistp256_method(void);
+
struct ec_key_st {
int version;
diff --git a/src/crypto/ec/oct.c b/src/crypto/ec/oct.c
index c4729ef..816a42f 100644
--- a/src/crypto/ec/oct.c
+++ b/src/crypto/ec/oct.c
@@ -164,18 +164,14 @@ static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
if (used_ctx) {
BN_CTX_end(ctx);
}
- if (new_ctx != NULL) {
- BN_CTX_free(new_ctx);
- }
+ BN_CTX_free(new_ctx);
return ret;
err:
if (used_ctx) {
BN_CTX_end(ctx);
}
- if (new_ctx != NULL) {
- BN_CTX_free(new_ctx);
- }
+ BN_CTX_free(new_ctx);
return 0;
}
@@ -227,40 +223,46 @@ static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
- if (y == NULL)
+ if (y == NULL) {
goto err;
+ }
- if (!BN_bin2bn(buf + 1, field_len, x))
+ if (!BN_bin2bn(buf + 1, field_len, x)) {
goto err;
+ }
if (BN_ucmp(x, &group->field) >= 0) {
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
goto err;
}
if (form == POINT_CONVERSION_COMPRESSED) {
- if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx))
+ if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) {
goto err;
+ }
} else {
- if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
+ if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) {
goto err;
+ }
if (BN_ucmp(y, &group->field) >= 0) {
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))
+ if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
goto err;
+ }
}
- if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
- {
+ /* test required by X9.62 */
+ if (!EC_POINT_is_on_curve(group, point, ctx)) {
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_POINT_IS_NOT_ON_CURVE);
goto err;
}
@@ -269,8 +271,7 @@ static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
err:
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -441,15 +442,15 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
goto err;
}
- if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
goto err;
+ }
ret = 1;
err:
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
diff --git a/src/crypto/ec/p256-64.c b/src/crypto/ec/p256-64.c
new file mode 100644
index 0000000..8f824de
--- /dev/null
+++ b/src/crypto/ec/p256-64.c
@@ -0,0 +1,1936 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+/* A 64-bit implementation of the NIST P-256 elliptic curve point
+ * multiplication
+ *
+ * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
+ * Otherwise based on Emilia's P224 work, which was inspired by my curve25519
+ * work which got its smarts from Daniel J. Bernstein's work on the same. */
+
+#include <openssl/base.h>
+
+#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS)
+
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include <string.h>
+
+#include "internal.h"
+
+
+typedef uint8_t u8;
+typedef uint64_t u64;
+typedef int64_t s64;
+typedef __uint128_t uint128_t;
+typedef __int128_t int128_t;
+
+/* The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We
+ * can serialise an element of this field into 32 bytes. We call this an
+ * felem_bytearray. */
+typedef u8 felem_bytearray[32];
+
+/* These are the parameters of P256, taken from FIPS 186-3, page 86. These
+ * values are big-endian. */
+static const felem_bytearray nistp256_curve_params[5] = {
+ {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* a = -3 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xfc}, /* b */
+ {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55,
+ 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6,
+ 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b},
+ {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */
+ 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81,
+ 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96},
+ {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */
+ 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
+ 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}};
+
+/* The representation of field elements.
+ * ------------------------------------
+ *
+ * We represent field elements with either four 128-bit values, eight 128-bit
+ * values, or four 64-bit values. The field element represented is:
+ * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192 (mod p)
+ * or:
+ * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512 (mod p)
+ *
+ * 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits
+ * apart, but are 128-bits wide, the most significant bits of each limb overlap
+ * with the least significant bits of the next.
+ *
+ * A field element with four limbs is an 'felem'. One with eight limbs is a
+ * 'longfelem'
+ *
+ * A field element with four, 64-bit values is called a 'smallfelem'. Small
+ * values are used as intermediate values before multiplication. */
+
+#define NLIMBS 4
+
+typedef uint128_t limb;
+typedef limb felem[NLIMBS];
+typedef limb longfelem[NLIMBS * 2];
+typedef u64 smallfelem[NLIMBS];
+
+/* This is the value of the prime as four 64-bit words, little-endian. */
+static const u64 kPrime[4] = {0xfffffffffffffffful, 0xffffffff, 0,
+ 0xffffffff00000001ul};
+static const u64 bottom63bits = 0x7ffffffffffffffful;
+
+/* bin32_to_felem takes a little-endian byte array and converts it into felem
+ * form. This assumes that the CPU is little-endian. */
+static void bin32_to_felem(felem out, const u8 in[32]) {
+ out[0] = *((u64 *)&in[0]);
+ out[1] = *((u64 *)&in[8]);
+ out[2] = *((u64 *)&in[16]);
+ out[3] = *((u64 *)&in[24]);
+}
+
+/* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian,
+ * 32 byte array. This assumes that the CPU is little-endian. */
+static void smallfelem_to_bin32(u8 out[32], const smallfelem in) {
+ *((u64 *)&out[0]) = in[0];
+ *((u64 *)&out[8]) = in[1];
+ *((u64 *)&out[16]) = in[2];
+ *((u64 *)&out[24]) = in[3];
+}
+
+/* To preserve endianness when using BN_bn2bin and BN_bin2bn. */
+static void flip_endian(u8 *out, const u8 *in, unsigned len) {
+ unsigned i;
+ for (i = 0; i < len; ++i) {
+ out[i] = in[len - 1 - i];
+ }
+}
+
+/* BN_to_felem converts an OpenSSL BIGNUM into an felem. */
+static int BN_to_felem(felem out, const BIGNUM *bn) {
+ if (BN_is_negative(bn)) {
+ OPENSSL_PUT_ERROR(EC, BN_to_felem, EC_R_BIGNUM_OUT_OF_RANGE);
+ return 0;
+ }
+
+ felem_bytearray b_out;
+ /* BN_bn2bin eats leading zeroes */
+ memset(b_out, 0, sizeof(b_out));
+ unsigned num_bytes = BN_num_bytes(bn);
+ if (num_bytes > sizeof(b_out)) {
+ OPENSSL_PUT_ERROR(EC, BN_to_felem, EC_R_BIGNUM_OUT_OF_RANGE);
+ return 0;
+ }
+
+ felem_bytearray b_in;
+ num_bytes = BN_bn2bin(bn, b_in);
+ flip_endian(b_out, b_in, num_bytes);
+ bin32_to_felem(out, b_out);
+ return 1;
+}
+
+/* felem_to_BN converts an felem into an OpenSSL BIGNUM. */
+static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in) {
+ felem_bytearray b_in, b_out;
+ smallfelem_to_bin32(b_in, in);
+ flip_endian(b_out, b_in, sizeof(b_out));
+ return BN_bin2bn(b_out, sizeof(b_out), out);
+}
+
+/* Field operations. */
+
+static void smallfelem_one(smallfelem out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+}
+
+static void smallfelem_assign(smallfelem out, const smallfelem in) {
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static void felem_assign(felem out, const felem in) {
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+/* felem_sum sets out = out + in. */
+static void felem_sum(felem out, const felem in) {
+ out[0] += in[0];
+ out[1] += in[1];
+ out[2] += in[2];
+ out[3] += in[3];
+}
+
+/* felem_small_sum sets out = out + in. */
+static void felem_small_sum(felem out, const smallfelem in) {
+ out[0] += in[0];
+ out[1] += in[1];
+ out[2] += in[2];
+ out[3] += in[3];
+}
+
+/* felem_scalar sets out = out * scalar */
+static void felem_scalar(felem out, const u64 scalar) {
+ out[0] *= scalar;
+ out[1] *= scalar;
+ out[2] *= scalar;
+ out[3] *= scalar;
+}
+
+/* longfelem_scalar sets out = out * scalar */
+static void longfelem_scalar(longfelem out, const u64 scalar) {
+ out[0] *= scalar;
+ out[1] *= scalar;
+ out[2] *= scalar;
+ out[3] *= scalar;
+ out[4] *= scalar;
+ out[5] *= scalar;
+ out[6] *= scalar;
+ out[7] *= scalar;
+}
+
+#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)
+#define two105 (((limb)1) << 105)
+#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)
+
+/* zero105 is 0 mod p */
+static const felem zero105 = {two105m41m9, two105, two105m41p9, two105m41p9};
+
+/* smallfelem_neg sets |out| to |-small|
+ * On exit:
+ * out[i] < out[i] + 2^105 */
+static void smallfelem_neg(felem out, const smallfelem small) {
+ /* In order to prevent underflow, we subtract from 0 mod p. */
+ out[0] = zero105[0] - small[0];
+ out[1] = zero105[1] - small[1];
+ out[2] = zero105[2] - small[2];
+ out[3] = zero105[3] - small[3];
+}
+
+/* felem_diff subtracts |in| from |out|
+ * On entry:
+ * in[i] < 2^104
+ * On exit:
+ * out[i] < out[i] + 2^105. */
+static void felem_diff(felem out, const felem in) {
+ /* In order to prevent underflow, we add 0 mod p before subtracting. */
+ out[0] += zero105[0];
+ out[1] += zero105[1];
+ out[2] += zero105[2];
+ out[3] += zero105[3];
+
+ out[0] -= in[0];
+ out[1] -= in[1];
+ out[2] -= in[2];
+ out[3] -= in[3];
+}
+
+#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)
+#define two107 (((limb)1) << 107)
+#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)
+
+/* zero107 is 0 mod p */
+static const felem zero107 = {two107m43m11, two107, two107m43p11, two107m43p11};
+
+/* An alternative felem_diff for larger inputs |in|
+ * felem_diff_zero107 subtracts |in| from |out|
+ * On entry:
+ * in[i] < 2^106
+ * On exit:
+ * out[i] < out[i] + 2^107. */
+static void felem_diff_zero107(felem out, const felem in) {
+ /* In order to prevent underflow, we add 0 mod p before subtracting. */
+ out[0] += zero107[0];
+ out[1] += zero107[1];
+ out[2] += zero107[2];
+ out[3] += zero107[3];
+
+ out[0] -= in[0];
+ out[1] -= in[1];
+ out[2] -= in[2];
+ out[3] -= in[3];
+}
+
+/* longfelem_diff subtracts |in| from |out|
+ * On entry:
+ * in[i] < 7*2^67
+ * On exit:
+ * out[i] < out[i] + 2^70 + 2^40. */
+static void longfelem_diff(longfelem out, const longfelem in) {
+ static const limb two70m8p6 =
+ (((limb)1) << 70) - (((limb)1) << 8) + (((limb)1) << 6);
+ static const limb two70p40 = (((limb)1) << 70) + (((limb)1) << 40);
+ static const limb two70 = (((limb)1) << 70);
+ static const limb two70m40m38p6 = (((limb)1) << 70) - (((limb)1) << 40) -
+ (((limb)1) << 38) + (((limb)1) << 6);
+ static const limb two70m6 = (((limb)1) << 70) - (((limb)1) << 6);
+
+ /* add 0 mod p to avoid underflow */
+ out[0] += two70m8p6;
+ out[1] += two70p40;
+ out[2] += two70;
+ out[3] += two70m40m38p6;
+ out[4] += two70m6;
+ out[5] += two70m6;
+ out[6] += two70m6;
+ out[7] += two70m6;
+
+ /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */
+ out[0] -= in[0];
+ out[1] -= in[1];
+ out[2] -= in[2];
+ out[3] -= in[3];
+ out[4] -= in[4];
+ out[5] -= in[5];
+ out[6] -= in[6];
+ out[7] -= in[7];
+}
+
+#define two64m0 (((limb)1) << 64) - 1
+#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1
+#define two64m46 (((limb)1) << 64) - (((limb)1) << 46)
+#define two64m32 (((limb)1) << 64) - (((limb)1) << 32)
+
+/* zero110 is 0 mod p. */
+static const felem zero110 = {two64m0, two110p32m0, two64m46, two64m32};
+
+/* felem_shrink converts an felem into a smallfelem. The result isn't quite
+ * minimal as the value may be greater than p.
+ *
+ * On entry:
+ * in[i] < 2^109
+ * On exit:
+ * out[i] < 2^64. */
+static void felem_shrink(smallfelem out, const felem in) {
+ felem tmp;
+ u64 a, b, mask;
+ s64 high, low;
+ static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */
+
+ /* Carry 2->3 */
+ tmp[3] = zero110[3] + in[3] + ((u64)(in[2] >> 64));
+ /* tmp[3] < 2^110 */
+
+ tmp[2] = zero110[2] + (u64)in[2];
+ tmp[0] = zero110[0] + in[0];
+ tmp[1] = zero110[1] + in[1];
+ /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */
+
+ /* We perform two partial reductions where we eliminate the high-word of
+ * tmp[3]. We don't update the other words till the end. */
+ a = tmp[3] >> 64; /* a < 2^46 */
+ tmp[3] = (u64)tmp[3];
+ tmp[3] -= a;
+ tmp[3] += ((limb)a) << 32;
+ /* tmp[3] < 2^79 */
+
+ b = a;
+ a = tmp[3] >> 64; /* a < 2^15 */
+ b += a; /* b < 2^46 + 2^15 < 2^47 */
+ tmp[3] = (u64)tmp[3];
+ tmp[3] -= a;
+ tmp[3] += ((limb)a) << 32;
+ /* tmp[3] < 2^64 + 2^47 */
+
+ /* This adjusts the other two words to complete the two partial
+ * reductions. */
+ tmp[0] += b;
+ tmp[1] -= (((limb)b) << 32);
+
+ /* In order to make space in tmp[3] for the carry from 2 -> 3, we
+ * conditionally subtract kPrime if tmp[3] is large enough. */
+ high = tmp[3] >> 64;
+ /* As tmp[3] < 2^65, high is either 1 or 0 */
+ high <<= 63;
+ high >>= 63;
+ /* high is:
+ * all ones if the high word of tmp[3] is 1
+ * all zeros if the high word of tmp[3] if 0 */
+ low = tmp[3];
+ mask = low >> 63;
+ /* mask is:
+ * all ones if the MSB of low is 1
+ * all zeros if the MSB of low if 0 */
+ low &= bottom63bits;
+ low -= kPrime3Test;
+ /* if low was greater than kPrime3Test then the MSB is zero */
+ low = ~low;
+ low >>= 63;
+ /* low is:
+ * all ones if low was > kPrime3Test
+ * all zeros if low was <= kPrime3Test */
+ mask = (mask & low) | high;
+ tmp[0] -= mask & kPrime[0];
+ tmp[1] -= mask & kPrime[1];
+ /* kPrime[2] is zero, so omitted */
+ tmp[3] -= mask & kPrime[3];
+ /* tmp[3] < 2**64 - 2**32 + 1 */
+
+ tmp[1] += ((u64)(tmp[0] >> 64));
+ tmp[0] = (u64)tmp[0];
+ tmp[2] += ((u64)(tmp[1] >> 64));
+ tmp[1] = (u64)tmp[1];
+ tmp[3] += ((u64)(tmp[2] >> 64));
+ tmp[2] = (u64)tmp[2];
+ /* tmp[i] < 2^64 */
+
+ out[0] = tmp[0];
+ out[1] = tmp[1];
+ out[2] = tmp[2];
+ out[3] = tmp[3];
+}
+
+/* smallfelem_expand converts a smallfelem to an felem */
+static void smallfelem_expand(felem out, const smallfelem in) {
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+/* smallfelem_square sets |out| = |small|^2
+ * On entry:
+ * small[i] < 2^64
+ * On exit:
+ * out[i] < 7 * 2^64 < 2^67 */
+static void smallfelem_square(longfelem out, const smallfelem small) {
+ limb a;
+ u64 high, low;
+
+ a = ((uint128_t)small[0]) * small[0];
+ low = a;
+ high = a >> 64;
+ out[0] = low;
+ out[1] = high;
+
+ a = ((uint128_t)small[0]) * small[1];
+ low = a;
+ high = a >> 64;
+ out[1] += low;
+ out[1] += low;
+ out[2] = high;
+
+ a = ((uint128_t)small[0]) * small[2];
+ low = a;
+ high = a >> 64;
+ out[2] += low;
+ out[2] *= 2;
+ out[3] = high;
+
+ a = ((uint128_t)small[0]) * small[3];
+ low = a;
+ high = a >> 64;
+ out[3] += low;
+ out[4] = high;
+
+ a = ((uint128_t)small[1]) * small[2];
+ low = a;
+ high = a >> 64;
+ out[3] += low;
+ out[3] *= 2;
+ out[4] += high;
+
+ a = ((uint128_t)small[1]) * small[1];
+ low = a;
+ high = a >> 64;
+ out[2] += low;
+ out[3] += high;
+
+ a = ((uint128_t)small[1]) * small[3];
+ low = a;
+ high = a >> 64;
+ out[4] += low;
+ out[4] *= 2;
+ out[5] = high;
+
+ a = ((uint128_t)small[2]) * small[3];
+ low = a;
+ high = a >> 64;
+ out[5] += low;
+ out[5] *= 2;
+ out[6] = high;
+ out[6] += high;
+
+ a = ((uint128_t)small[2]) * small[2];
+ low = a;
+ high = a >> 64;
+ out[4] += low;
+ out[5] += high;
+
+ a = ((uint128_t)small[3]) * small[3];
+ low = a;
+ high = a >> 64;
+ out[6] += low;
+ out[7] = high;
+}
+
+/*felem_square sets |out| = |in|^2
+ * On entry:
+ * in[i] < 2^109
+ * On exit:
+ * out[i] < 7 * 2^64 < 2^67. */
+static void felem_square(longfelem out, const felem in) {
+ u64 small[4];
+ felem_shrink(small, in);
+ smallfelem_square(out, small);
+}
+
+/* smallfelem_mul sets |out| = |small1| * |small2|
+ * On entry:
+ * small1[i] < 2^64
+ * small2[i] < 2^64
+ * On exit:
+ * out[i] < 7 * 2^64 < 2^67. */
+static void smallfelem_mul(longfelem out, const smallfelem small1,
+ const smallfelem small2) {
+ limb a;
+ u64 high, low;
+
+ a = ((uint128_t)small1[0]) * small2[0];
+ low = a;
+ high = a >> 64;
+ out[0] = low;
+ out[1] = high;
+
+ a = ((uint128_t)small1[0]) * small2[1];
+ low = a;
+ high = a >> 64;
+ out[1] += low;
+ out[2] = high;
+
+ a = ((uint128_t)small1[1]) * small2[0];
+ low = a;
+ high = a >> 64;
+ out[1] += low;
+ out[2] += high;
+
+ a = ((uint128_t)small1[0]) * small2[2];
+ low = a;
+ high = a >> 64;
+ out[2] += low;
+ out[3] = high;
+
+ a = ((uint128_t)small1[1]) * small2[1];
+ low = a;
+ high = a >> 64;
+ out[2] += low;
+ out[3] += high;
+
+ a = ((uint128_t)small1[2]) * small2[0];
+ low = a;
+ high = a >> 64;
+ out[2] += low;
+ out[3] += high;
+
+ a = ((uint128_t)small1[0]) * small2[3];
+ low = a;
+ high = a >> 64;
+ out[3] += low;
+ out[4] = high;
+
+ a = ((uint128_t)small1[1]) * small2[2];
+ low = a;
+ high = a >> 64;
+ out[3] += low;
+ out[4] += high;
+
+ a = ((uint128_t)small1[2]) * small2[1];
+ low = a;
+ high = a >> 64;
+ out[3] += low;
+ out[4] += high;
+
+ a = ((uint128_t)small1[3]) * small2[0];
+ low = a;
+ high = a >> 64;
+ out[3] += low;
+ out[4] += high;
+
+ a = ((uint128_t)small1[1]) * small2[3];
+ low = a;
+ high = a >> 64;
+ out[4] += low;
+ out[5] = high;
+
+ a = ((uint128_t)small1[2]) * small2[2];
+ low = a;
+ high = a >> 64;
+ out[4] += low;
+ out[5] += high;
+
+ a = ((uint128_t)small1[3]) * small2[1];
+ low = a;
+ high = a >> 64;
+ out[4] += low;
+ out[5] += high;
+
+ a = ((uint128_t)small1[2]) * small2[3];
+ low = a;
+ high = a >> 64;
+ out[5] += low;
+ out[6] = high;
+
+ a = ((uint128_t)small1[3]) * small2[2];
+ low = a;
+ high = a >> 64;
+ out[5] += low;
+ out[6] += high;
+
+ a = ((uint128_t)small1[3]) * small2[3];
+ low = a;
+ high = a >> 64;
+ out[6] += low;
+ out[7] = high;
+}
+
+/* felem_mul sets |out| = |in1| * |in2|
+ * On entry:
+ * in1[i] < 2^109
+ * in2[i] < 2^109
+ * On exit:
+ * out[i] < 7 * 2^64 < 2^67 */
+static void felem_mul(longfelem out, const felem in1, const felem in2) {
+ smallfelem small1, small2;
+ felem_shrink(small1, in1);
+ felem_shrink(small2, in2);
+ smallfelem_mul(out, small1, small2);
+}
+
+/* felem_small_mul sets |out| = |small1| * |in2|
+ * On entry:
+ * small1[i] < 2^64
+ * in2[i] < 2^109
+ * On exit:
+ * out[i] < 7 * 2^64 < 2^67 */
+static void felem_small_mul(longfelem out, const smallfelem small1,
+ const felem in2) {
+ smallfelem small2;
+ felem_shrink(small2, in2);
+ smallfelem_mul(out, small1, small2);
+}
+
+#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)
+#define two100 (((limb)1) << 100)
+#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)
+
+/* zero100 is 0 mod p */
+static const felem zero100 = {two100m36m4, two100, two100m36p4, two100m36p4};
+
+/* Internal function for the different flavours of felem_reduce.
+ * felem_reduce_ reduces the higher coefficients in[4]-in[7].
+ * On entry:
+ * out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7]
+ * out[1] >= in[7] + 2^32*in[4]
+ * out[2] >= in[5] + 2^32*in[5]
+ * out[3] >= in[4] + 2^32*in[5] + 2^32*in[6]
+ * On exit:
+ * out[0] <= out[0] + in[4] + 2^32*in[5]
+ * out[1] <= out[1] + in[5] + 2^33*in[6]
+ * out[2] <= out[2] + in[7] + 2*in[6] + 2^33*in[7]
+ * out[3] <= out[3] + 2^32*in[4] + 3*in[7] */
+static void felem_reduce_(felem out, const longfelem in) {
+ int128_t c;
+ /* combine common terms from below */
+ c = in[4] + (in[5] << 32);
+ out[0] += c;
+ out[3] -= c;
+
+ c = in[5] - in[7];
+ out[1] += c;
+ out[2] -= c;
+
+ /* the remaining terms */
+ /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */
+ out[1] -= (in[4] << 32);
+ out[3] += (in[4] << 32);
+
+ /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */
+ out[2] -= (in[5] << 32);
+
+ /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */
+ out[0] -= in[6];
+ out[0] -= (in[6] << 32);
+ out[1] += (in[6] << 33);
+ out[2] += (in[6] * 2);
+ out[3] -= (in[6] << 32);
+
+ /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */
+ out[0] -= in[7];
+ out[0] -= (in[7] << 32);
+ out[2] += (in[7] << 33);
+ out[3] += (in[7] * 3);
+}
+
+/* felem_reduce converts a longfelem into an felem.
+ * To be called directly after felem_square or felem_mul.
+ * On entry:
+ * in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64
+ * in[4] < 7*2^64, in[5] < 5*2^64, in[6] < 3*2^64, in[7] < 2*64
+ * On exit:
+ * out[i] < 2^101 */
+static void felem_reduce(felem out, const longfelem in) {
+ out[0] = zero100[0] + in[0];
+ out[1] = zero100[1] + in[1];
+ out[2] = zero100[2] + in[2];
+ out[3] = zero100[3] + in[3];
+
+ felem_reduce_(out, in);
+
+ /* out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0
+ * out[1] > 2^100 - 2^64 - 7*2^96 > 0
+ * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0
+ * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0
+ *
+ * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101
+ * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101
+ * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101
+ * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101 */
+}
+
+/* felem_reduce_zero105 converts a larger longfelem into an felem.
+ * On entry:
+ * in[0] < 2^71
+ * On exit:
+ * out[i] < 2^106 */
+static void felem_reduce_zero105(felem out, const longfelem in) {
+ out[0] = zero105[0] + in[0];
+ out[1] = zero105[1] + in[1];
+ out[2] = zero105[2] + in[2];
+ out[3] = zero105[3] + in[3];
+
+ felem_reduce_(out, in);
+
+ /* out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0
+ * out[1] > 2^105 - 2^71 - 2^103 > 0
+ * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0
+ * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0
+ *
+ * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106
+ * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106
+ * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106
+ * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106 */
+}
+
+/* subtract_u64 sets *result = *result - v and *carry to one if the
+ * subtraction underflowed. */
+static void subtract_u64(u64 *result, u64 *carry, u64 v) {
+ uint128_t r = *result;
+ r -= v;
+ *carry = (r >> 64) & 1;
+ *result = (u64)r;
+}
+
+/* felem_contract converts |in| to its unique, minimal representation. On
+ * entry: in[i] < 2^109. */
+static void felem_contract(smallfelem out, const felem in) {
+ u64 all_equal_so_far = 0, result = 0;
+
+ felem_shrink(out, in);
+ /* small is minimal except that the value might be > p */
+
+ all_equal_so_far--;
+ /* We are doing a constant time test if out >= kPrime. We need to compare
+ * each u64, from most-significant to least significant. For each one, if
+ * all words so far have been equal (m is all ones) then a non-equal
+ * result is the answer. Otherwise we continue. */
+ unsigned i;
+ for (i = 3; i < 4; i--) {
+ u64 equal;
+ uint128_t a = ((uint128_t)kPrime[i]) - out[i];
+ /* if out[i] > kPrime[i] then a will underflow and the high 64-bits
+ * will all be set. */
+ result |= all_equal_so_far & ((u64)(a >> 64));
+
+ /* if kPrime[i] == out[i] then |equal| will be all zeros and the
+ * decrement will make it all ones. */
+ equal = kPrime[i] ^ out[i];
+ equal--;
+ equal &= equal << 32;
+ equal &= equal << 16;
+ equal &= equal << 8;
+ equal &= equal << 4;
+ equal &= equal << 2;
+ equal &= equal << 1;
+ equal = ((s64)equal) >> 63;
+
+ all_equal_so_far &= equal;
+ }
+
+ /* if all_equal_so_far is still all ones then the two values are equal
+ * and so out >= kPrime is true. */
+ result |= all_equal_so_far;
+
+ /* if out >= kPrime then we subtract kPrime. */
+ u64 carry;
+ subtract_u64(&out[0], &carry, result & kPrime[0]);
+ subtract_u64(&out[1], &carry, carry);
+ subtract_u64(&out[2], &carry, carry);
+ subtract_u64(&out[3], &carry, carry);
+
+ subtract_u64(&out[1], &carry, result & kPrime[1]);
+ subtract_u64(&out[2], &carry, carry);
+ subtract_u64(&out[3], &carry, carry);
+
+ subtract_u64(&out[2], &carry, result & kPrime[2]);
+ subtract_u64(&out[3], &carry, carry);
+
+ subtract_u64(&out[3], &carry, result & kPrime[3]);
+}
+
+static void smallfelem_square_contract(smallfelem out, const smallfelem in) {
+ longfelem longtmp;
+ felem tmp;
+
+ smallfelem_square(longtmp, in);
+ felem_reduce(tmp, longtmp);
+ felem_contract(out, tmp);
+}
+
+static void smallfelem_mul_contract(smallfelem out, const smallfelem in1,
+ const smallfelem in2) {
+ longfelem longtmp;
+ felem tmp;
+
+ smallfelem_mul(longtmp, in1, in2);
+ felem_reduce(tmp, longtmp);
+ felem_contract(out, tmp);
+}
+
+/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
+ * otherwise.
+ * On entry:
+ * small[i] < 2^64 */
+static limb smallfelem_is_zero(const smallfelem small) {
+ limb result;
+ u64 is_p;
+
+ u64 is_zero = small[0] | small[1] | small[2] | small[3];
+ is_zero--;
+ is_zero &= is_zero << 32;
+ is_zero &= is_zero << 16;
+ is_zero &= is_zero << 8;
+ is_zero &= is_zero << 4;
+ is_zero &= is_zero << 2;
+ is_zero &= is_zero << 1;
+ is_zero = ((s64)is_zero) >> 63;
+
+ is_p = (small[0] ^ kPrime[0]) | (small[1] ^ kPrime[1]) |
+ (small[2] ^ kPrime[2]) | (small[3] ^ kPrime[3]);
+ is_p--;
+ is_p &= is_p << 32;
+ is_p &= is_p << 16;
+ is_p &= is_p << 8;
+ is_p &= is_p << 4;
+ is_p &= is_p << 2;
+ is_p &= is_p << 1;
+ is_p = ((s64)is_p) >> 63;
+
+ is_zero |= is_p;
+
+ result = is_zero;
+ result |= ((limb)is_zero) << 64;
+ return result;
+}
+
+static int smallfelem_is_zero_int(const smallfelem small) {
+ return (int)(smallfelem_is_zero(small) & ((limb)1));
+}
+
+/* felem_inv calculates |out| = |in|^{-1}
+ *
+ * Based on Fermat's Little Theorem:
+ * a^p = a (mod p)
+ * a^{p-1} = 1 (mod p)
+ * a^{p-2} = a^{-1} (mod p) */
+static void felem_inv(felem out, const felem in) {
+ felem ftmp, ftmp2;
+ /* each e_I will hold |in|^{2^I - 1} */
+ felem e2, e4, e8, e16, e32, e64;
+ longfelem tmp;
+ unsigned i;
+
+ felem_square(tmp, in);
+ felem_reduce(ftmp, tmp); /* 2^1 */
+ felem_mul(tmp, in, ftmp);
+ felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */
+ felem_assign(e2, ftmp);
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp); /* 2^4 - 2^2 */
+ felem_mul(tmp, ftmp, e2);
+ felem_reduce(ftmp, tmp); /* 2^4 - 2^0 */
+ felem_assign(e4, ftmp);
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp); /* 2^5 - 2^1 */
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp); /* 2^6 - 2^2 */
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp); /* 2^7 - 2^3 */
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp); /* 2^8 - 2^4 */
+ felem_mul(tmp, ftmp, e4);
+ felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */
+ felem_assign(e8, ftmp);
+ for (i = 0; i < 8; i++) {
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp);
+ } /* 2^16 - 2^8 */
+ felem_mul(tmp, ftmp, e8);
+ felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */
+ felem_assign(e16, ftmp);
+ for (i = 0; i < 16; i++) {
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp);
+ } /* 2^32 - 2^16 */
+ felem_mul(tmp, ftmp, e16);
+ felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */
+ felem_assign(e32, ftmp);
+ for (i = 0; i < 32; i++) {
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp);
+ } /* 2^64 - 2^32 */
+ felem_assign(e64, ftmp);
+ felem_mul(tmp, ftmp, in);
+ felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */
+ for (i = 0; i < 192; i++) {
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp);
+ } /* 2^256 - 2^224 + 2^192 */
+
+ felem_mul(tmp, e64, e32);
+ felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */
+ for (i = 0; i < 16; i++) {
+ felem_square(tmp, ftmp2);
+ felem_reduce(ftmp2, tmp);
+ } /* 2^80 - 2^16 */
+ felem_mul(tmp, ftmp2, e16);
+ felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */
+ for (i = 0; i < 8; i++) {
+ felem_square(tmp, ftmp2);
+ felem_reduce(ftmp2, tmp);
+ } /* 2^88 - 2^8 */
+ felem_mul(tmp, ftmp2, e8);
+ felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */
+ for (i = 0; i < 4; i++) {
+ felem_square(tmp, ftmp2);
+ felem_reduce(ftmp2, tmp);
+ } /* 2^92 - 2^4 */
+ felem_mul(tmp, ftmp2, e4);
+ felem_reduce(ftmp2, tmp); /* 2^92 - 2^0 */
+ felem_square(tmp, ftmp2);
+ felem_reduce(ftmp2, tmp); /* 2^93 - 2^1 */
+ felem_square(tmp, ftmp2);
+ felem_reduce(ftmp2, tmp); /* 2^94 - 2^2 */
+ felem_mul(tmp, ftmp2, e2);
+ felem_reduce(ftmp2, tmp); /* 2^94 - 2^0 */
+ felem_square(tmp, ftmp2);
+ felem_reduce(ftmp2, tmp); /* 2^95 - 2^1 */
+ felem_square(tmp, ftmp2);
+ felem_reduce(ftmp2, tmp); /* 2^96 - 2^2 */
+ felem_mul(tmp, ftmp2, in);
+ felem_reduce(ftmp2, tmp); /* 2^96 - 3 */
+
+ felem_mul(tmp, ftmp2, ftmp);
+ felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */
+}
+
+static void smallfelem_inv_contract(smallfelem out, const smallfelem in) {
+ felem tmp;
+
+ smallfelem_expand(tmp, in);
+ felem_inv(tmp, tmp);
+ felem_contract(out, tmp);
+}
+
+/* Group operations
+ * ----------------
+ *
+ * Building on top of the field operations we have the operations on the
+ * elliptic curve group itself. Points on the curve are represented in Jacobian
+ * coordinates. */
+
+/* point_double calculates 2*(x_in, y_in, z_in)
+ *
+ * The method is taken from:
+ * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
+ *
+ * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed.
+ * while x_out == y_in is not (maybe this works, but it's not tested). */
+static void point_double(felem x_out, felem y_out, felem z_out,
+ const felem x_in, const felem y_in, const felem z_in) {
+ longfelem tmp, tmp2;
+ felem delta, gamma, beta, alpha, ftmp, ftmp2;
+ smallfelem small1, small2;
+
+ felem_assign(ftmp, x_in);
+ /* ftmp[i] < 2^106 */
+ felem_assign(ftmp2, x_in);
+ /* ftmp2[i] < 2^106 */
+
+ /* delta = z^2 */
+ felem_square(tmp, z_in);
+ felem_reduce(delta, tmp);
+ /* delta[i] < 2^101 */
+
+ /* gamma = y^2 */
+ felem_square(tmp, y_in);
+ felem_reduce(gamma, tmp);
+ /* gamma[i] < 2^101 */
+ felem_shrink(small1, gamma);
+
+ /* beta = x*gamma */
+ felem_small_mul(tmp, small1, x_in);
+ felem_reduce(beta, tmp);
+ /* beta[i] < 2^101 */
+
+ /* alpha = 3*(x-delta)*(x+delta) */
+ felem_diff(ftmp, delta);
+ /* ftmp[i] < 2^105 + 2^106 < 2^107 */
+ felem_sum(ftmp2, delta);
+ /* ftmp2[i] < 2^105 + 2^106 < 2^107 */
+ felem_scalar(ftmp2, 3);
+ /* ftmp2[i] < 3 * 2^107 < 2^109 */
+ felem_mul(tmp, ftmp, ftmp2);
+ felem_reduce(alpha, tmp);
+ /* alpha[i] < 2^101 */
+ felem_shrink(small2, alpha);
+
+ /* x' = alpha^2 - 8*beta */
+ smallfelem_square(tmp, small2);
+ felem_reduce(x_out, tmp);
+ felem_assign(ftmp, beta);
+ felem_scalar(ftmp, 8);
+ /* ftmp[i] < 8 * 2^101 = 2^104 */
+ felem_diff(x_out, ftmp);
+ /* x_out[i] < 2^105 + 2^101 < 2^106 */
+
+ /* z' = (y + z)^2 - gamma - delta */
+ felem_sum(delta, gamma);
+ /* delta[i] < 2^101 + 2^101 = 2^102 */
+ felem_assign(ftmp, y_in);
+ felem_sum(ftmp, z_in);
+ /* ftmp[i] < 2^106 + 2^106 = 2^107 */
+ felem_square(tmp, ftmp);
+ felem_reduce(z_out, tmp);
+ felem_diff(z_out, delta);
+ /* z_out[i] < 2^105 + 2^101 < 2^106 */
+
+ /* y' = alpha*(4*beta - x') - 8*gamma^2 */
+ felem_scalar(beta, 4);
+ /* beta[i] < 4 * 2^101 = 2^103 */
+ felem_diff_zero107(beta, x_out);
+ /* beta[i] < 2^107 + 2^103 < 2^108 */
+ felem_small_mul(tmp, small2, beta);
+ /* tmp[i] < 7 * 2^64 < 2^67 */
+ smallfelem_square(tmp2, small1);
+ /* tmp2[i] < 7 * 2^64 */
+ longfelem_scalar(tmp2, 8);
+ /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */
+ longfelem_diff(tmp, tmp2);
+ /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */
+ felem_reduce_zero105(y_out, tmp);
+ /* y_out[i] < 2^106 */
+}
+
+/* point_double_small is the same as point_double, except that it operates on
+ * smallfelems. */
+static void point_double_small(smallfelem x_out, smallfelem y_out,
+ smallfelem z_out, const smallfelem x_in,
+ const smallfelem y_in, const smallfelem z_in) {
+ felem felem_x_out, felem_y_out, felem_z_out;
+ felem felem_x_in, felem_y_in, felem_z_in;
+
+ smallfelem_expand(felem_x_in, x_in);
+ smallfelem_expand(felem_y_in, y_in);
+ smallfelem_expand(felem_z_in, z_in);
+ point_double(felem_x_out, felem_y_out, felem_z_out, felem_x_in, felem_y_in,
+ felem_z_in);
+ felem_shrink(x_out, felem_x_out);
+ felem_shrink(y_out, felem_y_out);
+ felem_shrink(z_out, felem_z_out);
+}
+
+/* copy_conditional copies in to out iff mask is all ones. */
+static void copy_conditional(felem out, const felem in, limb mask) {
+ unsigned i;
+ for (i = 0; i < NLIMBS; ++i) {
+ const limb tmp = mask & (in[i] ^ out[i]);
+ out[i] ^= tmp;
+ }
+}
+
+/* copy_small_conditional copies in to out iff mask is all ones. */
+static void copy_small_conditional(felem out, const smallfelem in, limb mask) {
+ unsigned i;
+ const u64 mask64 = mask;
+ for (i = 0; i < NLIMBS; ++i) {
+ out[i] = ((limb)(in[i] & mask64)) | (out[i] & ~mask);
+ }
+}
+
+/* point_add calcuates (x1, y1, z1) + (x2, y2, z2)
+ *
+ * The method is taken from:
+ * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl,
+ * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
+ *
+ * This function includes a branch for checking whether the two input points
+ * are equal, (while not equal to the point at infinity). This case never
+ * happens during single point multiplication, so there is no timing leak for
+ * ECDH or ECDSA signing. */
+static void point_add(felem x3, felem y3, felem z3, const felem x1,
+ const felem y1, const felem z1, const int mixed,
+ const smallfelem x2, const smallfelem y2,
+ const smallfelem z2) {
+ felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out;
+ longfelem tmp, tmp2;
+ smallfelem small1, small2, small3, small4, small5;
+ limb x_equal, y_equal, z1_is_zero, z2_is_zero;
+
+ felem_shrink(small3, z1);
+
+ z1_is_zero = smallfelem_is_zero(small3);
+ z2_is_zero = smallfelem_is_zero(z2);
+
+ /* ftmp = z1z1 = z1**2 */
+ smallfelem_square(tmp, small3);
+ felem_reduce(ftmp, tmp);
+ /* ftmp[i] < 2^101 */
+ felem_shrink(small1, ftmp);
+
+ if (!mixed) {
+ /* ftmp2 = z2z2 = z2**2 */
+ smallfelem_square(tmp, z2);
+ felem_reduce(ftmp2, tmp);
+ /* ftmp2[i] < 2^101 */
+ felem_shrink(small2, ftmp2);
+
+ felem_shrink(small5, x1);
+
+ /* u1 = ftmp3 = x1*z2z2 */
+ smallfelem_mul(tmp, small5, small2);
+ felem_reduce(ftmp3, tmp);
+ /* ftmp3[i] < 2^101 */
+
+ /* ftmp5 = z1 + z2 */
+ felem_assign(ftmp5, z1);
+ felem_small_sum(ftmp5, z2);
+ /* ftmp5[i] < 2^107 */
+
+ /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */
+ felem_square(tmp, ftmp5);
+ felem_reduce(ftmp5, tmp);
+ /* ftmp2 = z2z2 + z1z1 */
+ felem_sum(ftmp2, ftmp);
+ /* ftmp2[i] < 2^101 + 2^101 = 2^102 */
+ felem_diff(ftmp5, ftmp2);
+ /* ftmp5[i] < 2^105 + 2^101 < 2^106 */
+
+ /* ftmp2 = z2 * z2z2 */
+ smallfelem_mul(tmp, small2, z2);
+ felem_reduce(ftmp2, tmp);
+
+ /* s1 = ftmp2 = y1 * z2**3 */
+ felem_mul(tmp, y1, ftmp2);
+ felem_reduce(ftmp6, tmp);
+ /* ftmp6[i] < 2^101 */
+ } else {
+ /* We'll assume z2 = 1 (special case z2 = 0 is handled later). */
+
+ /* u1 = ftmp3 = x1*z2z2 */
+ felem_assign(ftmp3, x1);
+ /* ftmp3[i] < 2^106 */
+
+ /* ftmp5 = 2z1z2 */
+ felem_assign(ftmp5, z1);
+ felem_scalar(ftmp5, 2);
+ /* ftmp5[i] < 2*2^106 = 2^107 */
+
+ /* s1 = ftmp2 = y1 * z2**3 */
+ felem_assign(ftmp6, y1);
+ /* ftmp6[i] < 2^106 */
+ }
+
+ /* u2 = x2*z1z1 */
+ smallfelem_mul(tmp, x2, small1);
+ felem_reduce(ftmp4, tmp);
+
+ /* h = ftmp4 = u2 - u1 */
+ felem_diff_zero107(ftmp4, ftmp3);
+ /* ftmp4[i] < 2^107 + 2^101 < 2^108 */
+ felem_shrink(small4, ftmp4);
+
+ x_equal = smallfelem_is_zero(small4);
+
+ /* z_out = ftmp5 * h */
+ felem_small_mul(tmp, small4, ftmp5);
+ felem_reduce(z_out, tmp);
+ /* z_out[i] < 2^101 */
+
+ /* ftmp = z1 * z1z1 */
+ smallfelem_mul(tmp, small1, small3);
+ felem_reduce(ftmp, tmp);
+
+ /* s2 = tmp = y2 * z1**3 */
+ felem_small_mul(tmp, y2, ftmp);
+ felem_reduce(ftmp5, tmp);
+
+ /* r = ftmp5 = (s2 - s1)*2 */
+ felem_diff_zero107(ftmp5, ftmp6);
+ /* ftmp5[i] < 2^107 + 2^107 = 2^108 */
+ felem_scalar(ftmp5, 2);
+ /* ftmp5[i] < 2^109 */
+ felem_shrink(small1, ftmp5);
+ y_equal = smallfelem_is_zero(small1);
+
+ if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
+ point_double(x3, y3, z3, x1, y1, z1);
+ return;
+ }
+
+ /* I = ftmp = (2h)**2 */
+ felem_assign(ftmp, ftmp4);
+ felem_scalar(ftmp, 2);
+ /* ftmp[i] < 2*2^108 = 2^109 */
+ felem_square(tmp, ftmp);
+ felem_reduce(ftmp, tmp);
+
+ /* J = ftmp2 = h * I */
+ felem_mul(tmp, ftmp4, ftmp);
+ felem_reduce(ftmp2, tmp);
+
+ /* V = ftmp4 = U1 * I */
+ felem_mul(tmp, ftmp3, ftmp);
+ felem_reduce(ftmp4, tmp);
+
+ /* x_out = r**2 - J - 2V */
+ smallfelem_square(tmp, small1);
+ felem_reduce(x_out, tmp);
+ felem_assign(ftmp3, ftmp4);
+ felem_scalar(ftmp4, 2);
+ felem_sum(ftmp4, ftmp2);
+ /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */
+ felem_diff(x_out, ftmp4);
+ /* x_out[i] < 2^105 + 2^101 */
+
+ /* y_out = r(V-x_out) - 2 * s1 * J */
+ felem_diff_zero107(ftmp3, x_out);
+ /* ftmp3[i] < 2^107 + 2^101 < 2^108 */
+ felem_small_mul(tmp, small1, ftmp3);
+ felem_mul(tmp2, ftmp6, ftmp2);
+ longfelem_scalar(tmp2, 2);
+ /* tmp2[i] < 2*2^67 = 2^68 */
+ longfelem_diff(tmp, tmp2);
+ /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */
+ felem_reduce_zero105(y_out, tmp);
+ /* y_out[i] < 2^106 */
+
+ copy_small_conditional(x_out, x2, z1_is_zero);
+ copy_conditional(x_out, x1, z2_is_zero);
+ copy_small_conditional(y_out, y2, z1_is_zero);
+ copy_conditional(y_out, y1, z2_is_zero);
+ copy_small_conditional(z_out, z2, z1_is_zero);
+ copy_conditional(z_out, z1, z2_is_zero);
+ felem_assign(x3, x_out);
+ felem_assign(y3, y_out);
+ felem_assign(z3, z_out);
+}
+
+/* point_add_small is the same as point_add, except that it operates on
+ * smallfelems. */
+static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3,
+ smallfelem x1, smallfelem y1, smallfelem z1,
+ smallfelem x2, smallfelem y2, smallfelem z2) {
+ felem felem_x3, felem_y3, felem_z3;
+ felem felem_x1, felem_y1, felem_z1;
+ smallfelem_expand(felem_x1, x1);
+ smallfelem_expand(felem_y1, y1);
+ smallfelem_expand(felem_z1, z1);
+ point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, x2,
+ y2, z2);
+ felem_shrink(x3, felem_x3);
+ felem_shrink(y3, felem_y3);
+ felem_shrink(z3, felem_z3);
+}
+
+/* Base point pre computation
+ * --------------------------
+ *
+ * Two different sorts of precomputed tables are used in the following code.
+ * Each contain various points on the curve, where each point is three field
+ * elements (x, y, z).
+ *
+ * For the base point table, z is usually 1 (0 for the point at infinity).
+ * This table has 2 * 16 elements, starting with the following:
+ * index | bits | point
+ * ------+---------+------------------------------
+ * 0 | 0 0 0 0 | 0G
+ * 1 | 0 0 0 1 | 1G
+ * 2 | 0 0 1 0 | 2^64G
+ * 3 | 0 0 1 1 | (2^64 + 1)G
+ * 4 | 0 1 0 0 | 2^128G
+ * 5 | 0 1 0 1 | (2^128 + 1)G
+ * 6 | 0 1 1 0 | (2^128 + 2^64)G
+ * 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G
+ * 8 | 1 0 0 0 | 2^192G
+ * 9 | 1 0 0 1 | (2^192 + 1)G
+ * 10 | 1 0 1 0 | (2^192 + 2^64)G
+ * 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G
+ * 12 | 1 1 0 0 | (2^192 + 2^128)G
+ * 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G
+ * 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G
+ * 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G
+ * followed by a copy of this with each element multiplied by 2^32.
+ *
+ * The reason for this is so that we can clock bits into four different
+ * locations when doing simple scalar multiplies against the base point,
+ * and then another four locations using the second 16 elements.
+ *
+ * Tables for other points have table[i] = iG for i in 0 .. 16. */
+
+/* gmul is the table of precomputed base points */
+static const smallfelem gmul[2][16][3] = {
+ {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
+ {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2,
+ 0x6b17d1f2e12c4247},
+ {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16,
+ 0x4fe342e2fe1a7f9b},
+ {1, 0, 0, 0}},
+ {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de,
+ 0x0fa822bc2811aaa5},
+ {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b,
+ 0xbff44ae8f5dba80d},
+ {1, 0, 0, 0}},
+ {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789,
+ 0x300a4bbc89d6726f},
+ {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f,
+ 0x72aac7e0d09b4644},
+ {1, 0, 0, 0}},
+ {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e,
+ 0x447d739beedb5e67},
+ {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7,
+ 0x2d4825ab834131ee},
+ {1, 0, 0, 0}},
+ {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60,
+ 0xef9519328a9c72ff},
+ {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c,
+ 0x611e9fc37dbb2c9b},
+ {1, 0, 0, 0}},
+ {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf,
+ 0x550663797b51f5d8},
+ {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5,
+ 0x157164848aecb851},
+ {1, 0, 0, 0}},
+ {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391,
+ 0xeb5d7745b21141ea},
+ {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee,
+ 0xeafd72ebdbecc17b},
+ {1, 0, 0, 0}},
+ {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5,
+ 0xa6d39677a7849276},
+ {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf,
+ 0x674f84749b0b8816},
+ {1, 0, 0, 0}},
+ {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb,
+ 0x4e769e7672c9ddad},
+ {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281,
+ 0x42b99082de830663},
+ {1, 0, 0, 0}},
+ {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478,
+ 0x78878ef61c6ce04d},
+ {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def,
+ 0xb6cb3f5d7b72c321},
+ {1, 0, 0, 0}},
+ {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae,
+ 0x0c88bc4d716b1287},
+ {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa,
+ 0xdd5ddea3f3901dc6},
+ {1, 0, 0, 0}},
+ {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3,
+ 0x68f344af6b317466},
+ {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3,
+ 0x31b9c405f8540a20},
+ {1, 0, 0, 0}},
+ {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0,
+ 0x4052bf4b6f461db9},
+ {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8,
+ 0xfecf4d5190b0fc61},
+ {1, 0, 0, 0}},
+ {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a,
+ 0x1eddbae2c802e41a},
+ {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0,
+ 0x43104d86560ebcfc},
+ {1, 0, 0, 0}},
+ {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a,
+ 0xb48e26b484f7a21c},
+ {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668,
+ 0xfac015404d4d3dab},
+ {1, 0, 0, 0}}},
+ {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
+ {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da,
+ 0x7fe36b40af22af89},
+ {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1,
+ 0xe697d45825b63624},
+ {1, 0, 0, 0}},
+ {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902,
+ 0x4a5b506612a677a6},
+ {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40,
+ 0xeb13461ceac089f1},
+ {1, 0, 0, 0}},
+ {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857,
+ 0x0781b8291c6a220a},
+ {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434,
+ 0x690cde8df0151593},
+ {1, 0, 0, 0}},
+ {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326,
+ 0x8a535f566ec73617},
+ {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf,
+ 0x0455c08468b08bd7},
+ {1, 0, 0, 0}},
+ {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279,
+ 0x06bada7ab77f8276},
+ {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70,
+ 0x5b476dfd0e6cb18a},
+ {1, 0, 0, 0}},
+ {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8,
+ 0x3e29864e8a2ec908},
+ {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed,
+ 0x239b90ea3dc31e7e},
+ {1, 0, 0, 0}},
+ {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4,
+ 0x820f4dd949f72ff7},
+ {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3,
+ 0x140406ec783a05ec},
+ {1, 0, 0, 0}},
+ {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe,
+ 0x68f6b8542783dfee},
+ {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028,
+ 0xcbe1feba92e40ce6},
+ {1, 0, 0, 0}},
+ {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927,
+ 0xd0b2f94d2f420109},
+ {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a,
+ 0x971459828b0719e5},
+ {1, 0, 0, 0}},
+ {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687,
+ 0x961610004a866aba},
+ {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c,
+ 0x7acb9fadcee75e44},
+ {1, 0, 0, 0}},
+ {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea,
+ 0x24eb9acca333bf5b},
+ {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d,
+ 0x69f891c5acd079cc},
+ {1, 0, 0, 0}},
+ {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514,
+ 0xe51f547c5972a107},
+ {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06,
+ 0x1c309a2b25bb1387},
+ {1, 0, 0, 0}},
+ {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828,
+ 0x20b87b8aa2c4e503},
+ {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044,
+ 0xf5c6fa49919776be},
+ {1, 0, 0, 0}},
+ {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56,
+ 0x1ed7d1b9332010b9},
+ {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24,
+ 0x3a2b03f03217257a},
+ {1, 0, 0, 0}},
+ {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b,
+ 0x15fee545c78dd9f6},
+ {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb,
+ 0x4ab5b6b2b8753f81},
+ {1, 0, 0, 0}}}};
+
+/* select_point selects the |idx|th point from a precomputation table and
+ * copies it to out. */
+static void select_point(const u64 idx, unsigned int size,
+ const smallfelem pre_comp[16][3], smallfelem out[3]) {
+ unsigned i, j;
+ u64 *outlimbs = &out[0][0];
+ memset(outlimbs, 0, 3 * sizeof(smallfelem));
+
+ for (i = 0; i < size; i++) {
+ const u64 *inlimbs = (u64 *)&pre_comp[i][0][0];
+ u64 mask = i ^ idx;
+ mask |= mask >> 4;
+ mask |= mask >> 2;
+ mask |= mask >> 1;
+ mask &= 1;
+ mask--;
+ for (j = 0; j < NLIMBS * 3; j++) {
+ outlimbs[j] |= inlimbs[j] & mask;
+ }
+ }
+}
+
+/* get_bit returns the |i|th bit in |in| */
+static char get_bit(const felem_bytearray in, int i) {
+ if (i < 0 || i >= 256) {
+ return 0;
+ }
+ return (in[i >> 3] >> (i & 7)) & 1;
+}
+
+/* Interleaved point multiplication using precomputed point multiples: The
+ * small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[], the scalars
+ * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the
+ * generator, using certain (large) precomputed multiples in g_pre_comp.
+ * Output point (X, Y, Z) is stored in x_out, y_out, z_out. */
+static void batch_mul(felem x_out, felem y_out, felem z_out,
+ const felem_bytearray scalars[],
+ const unsigned num_points, const u8 *g_scalar,
+ const int mixed, const smallfelem pre_comp[][17][3],
+ const smallfelem g_pre_comp[2][16][3]) {
+ int i, skip;
+ unsigned num, gen_mul = (g_scalar != NULL);
+ felem nq[3], ftmp;
+ smallfelem tmp[3];
+ u64 bits;
+ u8 sign, digit;
+
+ /* set nq to the point at infinity */
+ memset(nq, 0, 3 * sizeof(felem));
+
+ /* Loop over all scalars msb-to-lsb, interleaving additions of multiples
+ * of the generator (two in each of the last 32 rounds) and additions of
+ * other points multiples (every 5th round). */
+
+ skip = 1; /* save two point operations in the first
+ * round */
+ for (i = (num_points ? 255 : 31); i >= 0; --i) {
+ /* double */
+ if (!skip) {
+ point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
+ }
+
+ /* add multiples of the generator */
+ if (gen_mul && i <= 31) {
+ /* first, look 32 bits upwards */
+ bits = get_bit(g_scalar, i + 224) << 3;
+ bits |= get_bit(g_scalar, i + 160) << 2;
+ bits |= get_bit(g_scalar, i + 96) << 1;
+ bits |= get_bit(g_scalar, i + 32);
+ /* select the point to add, in constant time */
+ select_point(bits, 16, g_pre_comp[1], tmp);
+
+ if (!skip) {
+ /* Arg 1 below is for "mixed" */
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1, tmp[0], tmp[1],
+ tmp[2]);
+ } else {
+ smallfelem_expand(nq[0], tmp[0]);
+ smallfelem_expand(nq[1], tmp[1]);
+ smallfelem_expand(nq[2], tmp[2]);
+ skip = 0;
+ }
+
+ /* second, look at the current position */
+ bits = get_bit(g_scalar, i + 192) << 3;
+ bits |= get_bit(g_scalar, i + 128) << 2;
+ bits |= get_bit(g_scalar, i + 64) << 1;
+ bits |= get_bit(g_scalar, i);
+ /* select the point to add, in constant time */
+ select_point(bits, 16, g_pre_comp[0], tmp);
+ /* Arg 1 below is for "mixed" */
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1, tmp[0], tmp[1],
+ tmp[2]);
+ }
+
+ /* do other additions every 5 doublings */
+ if (num_points && (i % 5 == 0)) {
+ /* loop over all scalars */
+ for (num = 0; num < num_points; ++num) {
+ bits = get_bit(scalars[num], i + 4) << 5;
+ bits |= get_bit(scalars[num], i + 3) << 4;
+ bits |= get_bit(scalars[num], i + 2) << 3;
+ bits |= get_bit(scalars[num], i + 1) << 2;
+ bits |= get_bit(scalars[num], i) << 1;
+ bits |= get_bit(scalars[num], i - 1);
+ ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
+
+ /* select the point to add or subtract, in constant time. */
+ select_point(digit, 17, pre_comp[num], tmp);
+ smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative
+ * point */
+ copy_small_conditional(ftmp, tmp[1], (((limb)sign) - 1));
+ felem_contract(tmp[1], ftmp);
+
+ if (!skip) {
+ point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], mixed, tmp[0],
+ tmp[1], tmp[2]);
+ } else {
+ smallfelem_expand(nq[0], tmp[0]);
+ smallfelem_expand(nq[1], tmp[1]);
+ smallfelem_expand(nq[2], tmp[2]);
+ skip = 0;
+ }
+ }
+ }
+ }
+ felem_assign(x_out, nq[0]);
+ felem_assign(y_out, nq[1]);
+ felem_assign(z_out, nq[2]);
+}
+
+/* Precomputation for the group generator. */
+typedef struct {
+ smallfelem g_pre_comp[2][16][3];
+ int references;
+} NISTP256_PRE_COMP;
+
+/******************************************************************************/
+/*
+ * OPENSSL EC_METHOD FUNCTIONS
+ */
+
+int ec_GFp_nistp256_group_init(EC_GROUP *group) {
+ int ret = ec_GFp_simple_group_init(group);
+ group->a_is_minus3 = 1;
+ return ret;
+}
+
+int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx) {
+ int ret = 0;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *curve_p, *curve_a, *curve_b;
+
+ if (ctx == NULL) {
+ if ((ctx = new_ctx = BN_CTX_new()) == NULL) {
+ return 0;
+ }
+ }
+ BN_CTX_start(ctx);
+ if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
+ ((curve_a = BN_CTX_get(ctx)) == NULL) ||
+ ((curve_b = BN_CTX_get(ctx)) == NULL)) {
+ goto err;
+ }
+ BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p);
+ BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a);
+ BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b);
+ if (BN_cmp(curve_p, p) ||
+ BN_cmp(curve_a, a) ||
+ BN_cmp(curve_b, b)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_group_set_curve,
+ EC_R_WRONG_CURVE_PARAMETERS);
+ goto err;
+ }
+ ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
+ * (X/Z^2, Y/Z^3). */
+int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx) {
+ felem z1, z2, x_in, y_in;
+ smallfelem x_out, y_out;
+ longfelem tmp;
+
+ if (EC_POINT_is_at_infinity(group, point)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_point_get_affine_coordinates,
+ EC_R_POINT_AT_INFINITY);
+ return 0;
+ }
+ if (!BN_to_felem(x_in, &point->X) ||
+ !BN_to_felem(y_in, &point->Y) ||
+ !BN_to_felem(z1, &point->Z)) {
+ return 0;
+ }
+ felem_inv(z2, z1);
+ felem_square(tmp, z2);
+ felem_reduce(z1, tmp);
+ felem_mul(tmp, x_in, z1);
+ felem_reduce(x_in, tmp);
+ felem_contract(x_out, x_in);
+ if (x != NULL && !smallfelem_to_BN(x, x_out)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_point_get_affine_coordinates,
+ ERR_R_BN_LIB);
+ return 0;
+ }
+ felem_mul(tmp, z1, z2);
+ felem_reduce(z1, tmp);
+ felem_mul(tmp, y_in, z1);
+ felem_reduce(y_in, tmp);
+ felem_contract(y_out, y_in);
+ if (y != NULL && !smallfelem_to_BN(y, y_out)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_point_get_affine_coordinates,
+ ERR_R_BN_LIB);
+ return 0;
+ }
+ return 1;
+}
+
+/* points below is of size |num|, and tmp_smallfelems is of size |num+1| */
+static void make_points_affine(size_t num, smallfelem points[][3],
+ smallfelem tmp_smallfelems[]) {
+ /* Runs in constant time, unless an input is the point at infinity (which
+ * normally shouldn't happen). */
+ ec_GFp_nistp_points_make_affine_internal(
+ num, points, sizeof(smallfelem), tmp_smallfelems,
+ (void (*)(void *))smallfelem_one,
+ (int (*)(const void *))smallfelem_is_zero_int,
+ (void (*)(void *, const void *))smallfelem_assign,
+ (void (*)(void *, const void *))smallfelem_square_contract,
+ (void (*)(void *, const void *, const void *))smallfelem_mul_contract,
+ (void (*)(void *, const void *))smallfelem_inv_contract,
+ /* nothing to contract */
+ (void (*)(void *, const void *))smallfelem_assign);
+}
+
+/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL
+ * values Result is stored in r (r can equal one of the inputs). */
+int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar, size_t num,
+ const EC_POINT *points[],
+ const BIGNUM *scalars[], BN_CTX *ctx) {
+ int ret = 0;
+ int j;
+ int mixed = 0;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *x, *y, *z, *tmp_scalar;
+ felem_bytearray g_secret;
+ felem_bytearray *secrets = NULL;
+ smallfelem(*pre_comp)[17][3] = NULL;
+ smallfelem *tmp_smallfelems = NULL;
+ felem_bytearray tmp;
+ unsigned i, num_bytes;
+ int have_pre_comp = 0;
+ size_t num_points = num;
+ smallfelem x_in, y_in, z_in;
+ felem x_out, y_out, z_out;
+ const smallfelem(*g_pre_comp)[16][3] = NULL;
+ EC_POINT *generator = NULL;
+ const EC_POINT *p = NULL;
+ const BIGNUM *p_scalar = NULL;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ }
+
+ BN_CTX_start(ctx);
+ if ((x = BN_CTX_get(ctx)) == NULL ||
+ (y = BN_CTX_get(ctx)) == NULL ||
+ (z = BN_CTX_get(ctx)) == NULL ||
+ (tmp_scalar = BN_CTX_get(ctx)) == NULL) {
+ goto err;
+ }
+
+ if (scalar != NULL) {
+ /* try to use the standard precomputation */
+ g_pre_comp = &gmul[0];
+ generator = EC_POINT_new(group);
+ if (generator == NULL) {
+ goto err;
+ }
+ /* get the generator from precomputation */
+ if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) ||
+ !smallfelem_to_BN(y, g_pre_comp[0][1][1]) ||
+ !smallfelem_to_BN(z, g_pre_comp[0][1][2])) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_points_mul, ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!ec_point_set_Jprojective_coordinates_GFp(group, generator, x, y, z,
+ ctx)) {
+ goto err;
+ }
+ if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) {
+ /* precomputation matches generator */
+ have_pre_comp = 1;
+ } else {
+ /* we don't have valid precomputation: treat the generator as a
+ * random point. */
+ num_points++;
+ }
+ }
+
+ if (num_points > 0) {
+ if (num_points >= 3) {
+ /* unless we precompute multiples for just one or two points,
+ * converting those into affine form is time well spent */
+ mixed = 1;
+ }
+ secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
+ pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(smallfelem));
+ if (mixed) {
+ tmp_smallfelems =
+ OPENSSL_malloc((num_points * 17 + 1) * sizeof(smallfelem));
+ }
+ if (secrets == NULL || pre_comp == NULL ||
+ (mixed && tmp_smallfelems == NULL)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_points_mul, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* we treat NULL scalars as 0, and NULL points as points at infinity,
+ * i.e., they contribute nothing to the linear combination. */
+ memset(secrets, 0, num_points * sizeof(felem_bytearray));
+ memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem));
+ for (i = 0; i < num_points; ++i) {
+ if (i == num) {
+ /* we didn't have a valid precomputation, so we pick the generator. */
+ p = EC_GROUP_get0_generator(group);
+ p_scalar = scalar;
+ } else {
+ /* the i^th point */
+ p = points[i];
+ p_scalar = scalars[i];
+ }
+ if (p_scalar != NULL && p != NULL) {
+ /* reduce scalar to 0 <= scalar < 2^256 */
+ if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) {
+ /* this is an unusual input, and we don't guarantee
+ * constant-timeness. */
+ if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_points_mul, ERR_R_BN_LIB);
+ goto err;
+ }
+ num_bytes = BN_bn2bin(tmp_scalar, tmp);
+ } else {
+ num_bytes = BN_bn2bin(p_scalar, tmp);
+ }
+ flip_endian(secrets[i], tmp, num_bytes);
+ /* precompute multiples */
+ if (!BN_to_felem(x_out, &p->X) ||
+ !BN_to_felem(y_out, &p->Y) ||
+ !BN_to_felem(z_out, &p->Z)) {
+ goto err;
+ }
+ felem_shrink(pre_comp[i][1][0], x_out);
+ felem_shrink(pre_comp[i][1][1], y_out);
+ felem_shrink(pre_comp[i][1][2], z_out);
+ for (j = 2; j <= 16; ++j) {
+ if (j & 1) {
+ point_add_small(pre_comp[i][j][0], pre_comp[i][j][1],
+ pre_comp[i][j][2], pre_comp[i][1][0],
+ pre_comp[i][1][1], pre_comp[i][1][2],
+ pre_comp[i][j - 1][0], pre_comp[i][j - 1][1],
+ pre_comp[i][j - 1][2]);
+ } else {
+ point_double_small(pre_comp[i][j][0], pre_comp[i][j][1],
+ pre_comp[i][j][2], pre_comp[i][j / 2][0],
+ pre_comp[i][j / 2][1], pre_comp[i][j / 2][2]);
+ }
+ }
+ }
+ }
+ if (mixed) {
+ make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems);
+ }
+ }
+
+ /* the scalar for the generator */
+ if (scalar != NULL && have_pre_comp) {
+ memset(g_secret, 0, sizeof(g_secret));
+ /* reduce scalar to 0 <= scalar < 2^256 */
+ if (BN_num_bits(scalar) > 256 || BN_is_negative(scalar)) {
+ /* this is an unusual input, and we don't guarantee
+ * constant-timeness. */
+ if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_points_mul, ERR_R_BN_LIB);
+ goto err;
+ }
+ num_bytes = BN_bn2bin(tmp_scalar, tmp);
+ } else {
+ num_bytes = BN_bn2bin(scalar, tmp);
+ }
+ flip_endian(g_secret, tmp, num_bytes);
+ /* do the multiplication with generator precomputation */
+ batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets,
+ num_points, g_secret, mixed, (const smallfelem(*)[17][3])pre_comp,
+ g_pre_comp);
+ } else {
+ /* do the multiplication without generator precomputation */
+ batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets,
+ num_points, NULL, mixed, (const smallfelem(*)[17][3])pre_comp,
+ NULL);
+ }
+
+ /* reduce the output to its unique minimal representation */
+ felem_contract(x_in, x_out);
+ felem_contract(y_in, y_out);
+ felem_contract(z_in, z_out);
+ if (!smallfelem_to_BN(x, x_in) ||
+ !smallfelem_to_BN(y, y_in) ||
+ !smallfelem_to_BN(z, z_in)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_nistp256_points_mul, ERR_R_BN_LIB);
+ goto err;
+ }
+ ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
+
+err:
+ BN_CTX_end(ctx);
+ EC_POINT_free(generator);
+ BN_CTX_free(new_ctx);
+ OPENSSL_free(secrets);
+ OPENSSL_free(pre_comp);
+ OPENSSL_free(tmp_smallfelems);
+ return ret;
+}
+
+const EC_METHOD *EC_GFp_nistp256_method(void) {
+ static const EC_METHOD ret = {
+ EC_FLAGS_DEFAULT_OCT,
+ ec_GFp_nistp256_group_init,
+ ec_GFp_simple_group_finish,
+ ec_GFp_simple_group_clear_finish,
+ ec_GFp_simple_group_copy, ec_GFp_nistp256_group_set_curve,
+ ec_GFp_simple_group_get_curve, ec_GFp_simple_group_get_degree,
+ ec_GFp_simple_group_check_discriminant, ec_GFp_simple_point_init,
+ ec_GFp_simple_point_finish, ec_GFp_simple_point_clear_finish,
+ ec_GFp_simple_point_copy, ec_GFp_simple_point_set_to_infinity,
+ ec_GFp_simple_set_Jprojective_coordinates_GFp,
+ ec_GFp_simple_get_Jprojective_coordinates_GFp,
+ ec_GFp_simple_point_set_affine_coordinates,
+ ec_GFp_nistp256_point_get_affine_coordinates,
+ 0 /* point_set_compressed_coordinates */, 0 /* point2oct */,
+ 0 /* oct2point */, ec_GFp_simple_add, ec_GFp_simple_dbl,
+ ec_GFp_simple_invert, ec_GFp_simple_is_at_infinity,
+ ec_GFp_simple_is_on_curve, ec_GFp_simple_cmp, ec_GFp_simple_make_affine,
+ ec_GFp_simple_points_make_affine, ec_GFp_nistp256_points_mul,
+ 0 /* precompute_mult */, 0 /* have_precompute_mult */,
+ ec_GFp_simple_field_mul, ec_GFp_simple_field_sqr, 0 /* field_div */,
+ 0 /* field_encode */, 0 /* field_decode */, 0 /* field_set_to_one */
+ };
+
+ return &ret;
+}
+
+#endif /* 64_BIT && !WINDOWS */
diff --git a/src/crypto/ec/simple.c b/src/crypto/ec/simple.c
index b3f96fa..69fd2e4 100644
--- a/src/crypto/ec/simple.c
+++ b/src/crypto/ec/simple.c
@@ -178,47 +178,55 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
BN_CTX_start(ctx);
tmp_a = BN_CTX_get(ctx);
- if (tmp_a == NULL)
+ if (tmp_a == NULL) {
goto err;
+ }
/* group->field */
- if (!BN_copy(&group->field, p))
+ if (!BN_copy(&group->field, p)) {
goto err;
+ }
BN_set_negative(&group->field, 0);
/* group->a */
- if (!BN_nnmod(tmp_a, a, p, ctx))
+ if (!BN_nnmod(tmp_a, a, p, ctx)) {
goto err;
+ }
if (group->meth->field_encode) {
- if (!group->meth->field_encode(group, &group->a, tmp_a, ctx))
+ if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) {
goto err;
- } else if (!BN_copy(&group->a, tmp_a))
+ }
+ } else if (!BN_copy(&group->a, tmp_a)) {
goto err;
+ }
/* group->b */
- if (!BN_nnmod(&group->b, b, p, ctx))
+ if (!BN_nnmod(&group->b, b, p, ctx)) {
goto err;
- if (group->meth->field_encode)
- if (!group->meth->field_encode(group, &group->b, &group->b, ctx))
- goto err;
+ }
+ if (group->meth->field_encode &&
+ !group->meth->field_encode(group, &group->b, &group->b, ctx)) {
+ goto err;
+ }
/* group->a_is_minus3 */
- if (!BN_add_word(tmp_a, 3))
+ if (!BN_add_word(tmp_a, 3)) {
goto err;
+ }
group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
ret = 1;
err:
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -227,34 +235,30 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
int ret = 0;
BN_CTX *new_ctx = NULL;
- if (p != NULL) {
- if (!BN_copy(p, &group->field))
- return 0;
+ if (p != NULL && !BN_copy(p, &group->field)) {
+ return 0;
}
if (a != NULL || b != NULL) {
if (group->meth->field_decode) {
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
- if (a != NULL) {
- if (!group->meth->field_decode(group, a, &group->a, ctx))
- goto err;
+ if (a != NULL && !group->meth->field_decode(group, a, &group->a, ctx)) {
+ goto err;
}
- if (b != NULL) {
- if (!group->meth->field_decode(group, b, &group->b, ctx))
- goto err;
+ if (b != NULL && !group->meth->field_decode(group, b, &group->b, ctx)) {
+ goto err;
}
} else {
- if (a != NULL) {
- if (!BN_copy(a, &group->a))
- goto err;
+ if (a != NULL && !BN_copy(a, &group->a)) {
+ goto err;
}
- if (b != NULL) {
- if (!BN_copy(b, &group->b))
- goto err;
+ if (b != NULL && !BN_copy(b, &group->b)) {
+ goto err;
}
}
}
@@ -262,8 +266,7 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
ret = 1;
err:
- if (new_ctx)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -291,54 +294,54 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) {
tmp_1 = BN_CTX_get(ctx);
tmp_2 = BN_CTX_get(ctx);
order = BN_CTX_get(ctx);
- if (order == NULL)
+ if (order == NULL) {
goto err;
+ }
if (group->meth->field_decode) {
- if (!group->meth->field_decode(group, a, &group->a, ctx))
- goto err;
- if (!group->meth->field_decode(group, b, &group->b, ctx))
+ if (!group->meth->field_decode(group, a, &group->a, ctx) ||
+ !group->meth->field_decode(group, b, &group->b, ctx)) {
goto err;
+ }
} else {
- if (!BN_copy(a, &group->a))
- goto err;
- if (!BN_copy(b, &group->b))
+ if (!BN_copy(a, &group->a) || !BN_copy(b, &group->b)) {
goto err;
+ }
}
/* check the discriminant:
* y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
* 0 =< a, b < p */
if (BN_is_zero(a)) {
- if (BN_is_zero(b))
+ if (BN_is_zero(b)) {
goto err;
+ }
} else if (!BN_is_zero(b)) {
- if (!BN_mod_sqr(tmp_1, a, p, ctx))
- goto err;
- if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
- goto err;
- if (!BN_lshift(tmp_1, tmp_2, 2))
+ if (!BN_mod_sqr(tmp_1, a, p, ctx) ||
+ !BN_mod_mul(tmp_2, tmp_1, a, p, ctx) ||
+ !BN_lshift(tmp_1, tmp_2, 2)) {
goto err;
+ }
/* tmp_1 = 4*a^3 */
- if (!BN_mod_sqr(tmp_2, b, p, ctx))
- goto err;
- if (!BN_mul_word(tmp_2, 27))
+ if (!BN_mod_sqr(tmp_2, b, p, ctx) ||
+ !BN_mul_word(tmp_2, 27)) {
goto err;
+ }
/* tmp_2 = 27*b^2 */
- if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
- goto err;
- if (BN_is_zero(a))
+ if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx) ||
+ BN_is_zero(a)) {
goto err;
+ }
}
ret = 1;
err:
- if (ctx != NULL)
+ if (ctx != NULL) {
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ }
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -365,12 +368,11 @@ void ec_GFp_simple_point_clear_finish(EC_POINT *point) {
}
int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) {
- if (!BN_copy(&dest->X, &src->X))
- return 0;
- if (!BN_copy(&dest->Y, &src->Y))
- return 0;
- if (!BN_copy(&dest->Z, &src->Z))
+ if (!BN_copy(&dest->X, &src->X) ||
+ !BN_copy(&dest->Y, &src->Y) ||
+ !BN_copy(&dest->Z, &src->Z)) {
return 0;
+ }
dest->Z_is_one = src->Z_is_one;
return 1;
@@ -391,41 +393,45 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
if (x != NULL) {
- if (!BN_nnmod(&point->X, x, &group->field, ctx))
+ if (!BN_nnmod(&point->X, x, &group->field, ctx)) {
+ goto err;
+ }
+ if (group->meth->field_encode &&
+ !group->meth->field_encode(group, &point->X, &point->X, ctx)) {
goto err;
- if (group->meth->field_encode) {
- if (!group->meth->field_encode(group, &point->X, &point->X, ctx))
- goto err;
}
}
if (y != NULL) {
- if (!BN_nnmod(&point->Y, y, &group->field, ctx))
+ if (!BN_nnmod(&point->Y, y, &group->field, ctx)) {
+ goto err;
+ }
+ if (group->meth->field_encode &&
+ !group->meth->field_encode(group, &point->Y, &point->Y, ctx)) {
goto err;
- if (group->meth->field_encode) {
- if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx))
- goto err;
}
}
if (z != NULL) {
int Z_is_one;
- if (!BN_nnmod(&point->Z, z, &group->field, ctx))
+ if (!BN_nnmod(&point->Z, z, &group->field, ctx)) {
goto err;
+ }
Z_is_one = BN_is_one(&point->Z);
if (group->meth->field_encode) {
if (Z_is_one && (group->meth->field_set_to_one != 0)) {
- if (!group->meth->field_set_to_one(group, &point->Z, ctx))
- goto err;
- } else {
- if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx))
+ if (!group->meth->field_set_to_one(group, &point->Z, ctx)) {
goto err;
+ }
+ } else if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) {
+ goto err;
}
}
point->Z_is_one = Z_is_one;
@@ -434,8 +440,7 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(
ret = 1;
err:
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -449,42 +454,36 @@ int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
if (group->meth->field_decode != 0) {
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
- if (x != NULL) {
- if (!group->meth->field_decode(group, x, &point->X, ctx))
- goto err;
+ if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) {
+ goto err;
}
- if (y != NULL) {
- if (!group->meth->field_decode(group, y, &point->Y, ctx))
- goto err;
+ if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) {
+ goto err;
}
- if (z != NULL) {
- if (!group->meth->field_decode(group, z, &point->Z, ctx))
- goto err;
+ if (z != NULL && !group->meth->field_decode(group, z, &point->Z, ctx)) {
+ goto err;
}
} else {
- if (x != NULL) {
- if (!BN_copy(x, &point->X))
- goto err;
+ if (x != NULL && !BN_copy(x, &point->X)) {
+ goto err;
}
- if (y != NULL) {
- if (!BN_copy(y, &point->Y))
- goto err;
+ if (y != NULL && !BN_copy(y, &point->Y)) {
+ goto err;
}
- if (z != NULL) {
- if (!BN_copy(z, &point->Z))
- goto err;
+ if (z != NULL && !BN_copy(z, &point->Z)) {
+ goto err;
}
}
ret = 1;
err:
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -518,8 +517,9 @@ int ec_GFp_simple_point_get_affine_coordinates(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);
@@ -527,14 +527,16 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
Z_1 = BN_CTX_get(ctx);
Z_2 = BN_CTX_get(ctx);
Z_3 = BN_CTX_get(ctx);
- if (Z_3 == NULL)
+ if (Z_3 == NULL) {
goto err;
+ }
/* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
if (group->meth->field_decode) {
- if (!group->meth->field_decode(group, Z, &point->Z, ctx))
+ if (!group->meth->field_decode(group, Z, &point->Z, ctx)) {
goto err;
+ }
Z_ = Z;
} else {
Z_ = &point->Z;
@@ -542,22 +544,18 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
if (BN_is_one(Z_)) {
if (group->meth->field_decode) {
- if (x != NULL) {
- if (!group->meth->field_decode(group, x, &point->X, ctx))
- goto err;
+ if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) {
+ goto err;
}
- if (y != NULL) {
- if (!group->meth->field_decode(group, y, &point->Y, ctx))
- goto err;
+ if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) {
+ goto err;
}
} else {
- if (x != NULL) {
- if (!BN_copy(x, &point->X))
- goto err;
+ if (x != NULL && !BN_copy(x, &point->X)) {
+ goto err;
}
- if (y != NULL) {
- if (!BN_copy(y, &point->Y))
- goto err;
+ if (y != NULL && !BN_copy(y, &point->Y)) {
+ goto err;
}
}
} else {
@@ -569,34 +567,34 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
if (group->meth->field_encode == 0) {
/* field_sqr works on standard representation */
- if (!group->meth->field_sqr(group, Z_2, Z_1, ctx))
- goto err;
- } else {
- if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx))
+ if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) {
goto err;
+ }
+ } else if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) {
+ goto err;
}
- if (x != NULL) {
- /* in the Montgomery case, field_mul will cancel out Montgomery factor in
- * X: */
- if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx))
- goto err;
+ /* in the Montgomery case, field_mul will cancel out Montgomery factor in
+ * X: */
+ if (x != NULL && !group->meth->field_mul(group, x, &point->X, Z_2, ctx)) {
+ goto err;
}
if (y != NULL) {
if (group->meth->field_encode == 0) {
/* field_mul works on standard representation */
- if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx))
- goto err;
- } else {
- if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx))
+ if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) {
goto err;
+ }
+ } else if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) {
+ goto err;
}
/* in the Montgomery case, field_mul will cancel out Montgomery factor in
* Y: */
- if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx))
+ if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) {
goto err;
+ }
}
}
@@ -604,8 +602,7 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
err:
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -619,12 +616,15 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
int ret = 0;
- if (a == b)
+ if (a == b) {
return EC_POINT_dbl(group, r, a, ctx);
- if (EC_POINT_is_at_infinity(group, a))
+ }
+ if (EC_POINT_is_at_infinity(group, a)) {
return EC_POINT_copy(r, b);
- if (EC_POINT_is_at_infinity(group, b))
+ }
+ if (EC_POINT_is_at_infinity(group, b)) {
return EC_POINT_copy(r, a);
+ }
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
@@ -632,8 +632,9 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
BN_CTX_start(ctx);
@@ -644,8 +645,9 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
n4 = BN_CTX_get(ctx);
n5 = BN_CTX_get(ctx);
n6 = BN_CTX_get(ctx);
- if (n6 == NULL)
+ if (n6 == NULL) {
goto end;
+ }
/* Note that in this function we must not read components of 'a' or 'b'
* once we have written the corresponding components of 'r'.
@@ -654,53 +656,51 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
/* n1, n2 */
if (b->Z_is_one) {
- if (!BN_copy(n1, &a->X))
- goto end;
- if (!BN_copy(n2, &a->Y))
+ if (!BN_copy(n1, &a->X) || !BN_copy(n2, &a->Y)) {
goto end;
+ }
/* n1 = X_a */
/* n2 = Y_a */
} else {
- if (!field_sqr(group, n0, &b->Z, ctx))
- goto end;
- if (!field_mul(group, n1, &a->X, n0, ctx))
+ if (!field_sqr(group, n0, &b->Z, ctx) ||
+ !field_mul(group, n1, &a->X, n0, ctx)) {
goto end;
+ }
/* n1 = X_a * Z_b^2 */
- if (!field_mul(group, n0, n0, &b->Z, ctx))
- goto end;
- if (!field_mul(group, n2, &a->Y, n0, ctx))
+ if (!field_mul(group, n0, n0, &b->Z, ctx) ||
+ !field_mul(group, n2, &a->Y, n0, ctx)) {
goto end;
+ }
/* n2 = Y_a * Z_b^3 */
}
/* n3, n4 */
if (a->Z_is_one) {
- if (!BN_copy(n3, &b->X))
- goto end;
- if (!BN_copy(n4, &b->Y))
+ if (!BN_copy(n3, &b->X) || !BN_copy(n4, &b->Y)) {
goto end;
+ }
/* n3 = X_b */
/* n4 = Y_b */
} else {
- if (!field_sqr(group, n0, &a->Z, ctx))
- goto end;
- if (!field_mul(group, n3, &b->X, n0, ctx))
+ if (!field_sqr(group, n0, &a->Z, ctx) ||
+ !field_mul(group, n3, &b->X, n0, ctx)) {
goto end;
+ }
/* n3 = X_b * Z_a^2 */
- if (!field_mul(group, n0, n0, &a->Z, ctx))
- goto end;
- if (!field_mul(group, n4, &b->Y, n0, ctx))
+ if (!field_mul(group, n0, n0, &a->Z, ctx) ||
+ !field_mul(group, n4, &b->Y, n0, ctx)) {
goto end;
+ }
/* n4 = Y_b * Z_a^3 */
}
/* n5, n6 */
- if (!BN_mod_sub_quick(n5, n1, n3, p))
- goto end;
- if (!BN_mod_sub_quick(n6, n2, n4, p))
+ if (!BN_mod_sub_quick(n5, n1, n3, p) ||
+ !BN_mod_sub_quick(n6, n2, n4, p)) {
goto end;
+ }
/* n5 = n1 - n3 */
/* n6 = n2 - n4 */
@@ -721,76 +721,79 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
}
/* 'n7', 'n8' */
- if (!BN_mod_add_quick(n1, n1, n3, p))
- goto end;
- if (!BN_mod_add_quick(n2, n2, n4, p))
+ if (!BN_mod_add_quick(n1, n1, n3, p) ||
+ !BN_mod_add_quick(n2, n2, n4, p)) {
goto end;
+ }
/* 'n7' = n1 + n3 */
/* 'n8' = n2 + n4 */
/* Z_r */
if (a->Z_is_one && b->Z_is_one) {
- if (!BN_copy(&r->Z, n5))
+ if (!BN_copy(&r->Z, n5)) {
goto end;
+ }
} else {
if (a->Z_is_one) {
- if (!BN_copy(n0, &b->Z))
+ if (!BN_copy(n0, &b->Z)) {
goto end;
+ }
} else if (b->Z_is_one) {
- if (!BN_copy(n0, &a->Z))
- goto end;
- } else {
- if (!field_mul(group, n0, &a->Z, &b->Z, ctx))
+ if (!BN_copy(n0, &a->Z)) {
goto end;
+ }
+ } else if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) {
+ goto end;
}
- if (!field_mul(group, &r->Z, n0, n5, ctx))
+ if (!field_mul(group, &r->Z, n0, n5, ctx)) {
goto end;
+ }
}
r->Z_is_one = 0;
/* Z_r = Z_a * Z_b * n5 */
/* X_r */
- if (!field_sqr(group, n0, n6, ctx))
- goto end;
- if (!field_sqr(group, n4, n5, ctx))
- goto end;
- if (!field_mul(group, n3, n1, n4, ctx))
- goto end;
- if (!BN_mod_sub_quick(&r->X, n0, n3, p))
+ if (!field_sqr(group, n0, n6, ctx) ||
+ !field_sqr(group, n4, n5, ctx) ||
+ !field_mul(group, n3, n1, n4, ctx) ||
+ !BN_mod_sub_quick(&r->X, n0, n3, p)) {
goto end;
+ }
/* X_r = n6^2 - n5^2 * 'n7' */
/* 'n9' */
- if (!BN_mod_lshift1_quick(n0, &r->X, p))
- goto end;
- if (!BN_mod_sub_quick(n0, n3, n0, p))
+ if (!BN_mod_lshift1_quick(n0, &r->X, p) ||
+ !BN_mod_sub_quick(n0, n3, n0, p)) {
goto end;
+ }
/* n9 = n5^2 * 'n7' - 2 * X_r */
/* Y_r */
- if (!field_mul(group, n0, n0, n6, ctx))
- goto end;
- if (!field_mul(group, n5, n4, n5, ctx))
+ if (!field_mul(group, n0, n0, n6, ctx) ||
+ !field_mul(group, n5, n4, n5, ctx)) {
goto end; /* now n5 is n5^3 */
- if (!field_mul(group, n1, n2, n5, ctx))
+ }
+ if (!field_mul(group, n1, n2, n5, ctx) ||
+ !BN_mod_sub_quick(n0, n0, n1, p)) {
goto end;
- if (!BN_mod_sub_quick(n0, n0, n1, p))
+ }
+ if (BN_is_odd(n0) && !BN_add(n0, n0, p)) {
goto end;
- if (BN_is_odd(n0))
- if (!BN_add(n0, n0, p))
- goto end;
+ }
/* now 0 <= n0 < 2*p, and n0 is even */
- if (!BN_rshift1(&r->Y, n0))
+ if (!BN_rshift1(&r->Y, n0)) {
goto end;
+ }
/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
ret = 1;
end:
- if (ctx) /* otherwise we already called BN_CTX_end */
+ if (ctx) {
+ /* otherwise we already called BN_CTX_end */
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ }
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -816,8 +819,9 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
BN_CTX_start(ctx);
@@ -825,8 +829,9 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
n1 = BN_CTX_get(ctx);
n2 = BN_CTX_get(ctx);
n3 = BN_CTX_get(ctx);
- if (n3 == NULL)
+ if (n3 == NULL) {
goto err;
+ }
/* Note that in this function we must not read components of 'a'
* once we have written the corresponding components of 'r'.
@@ -835,108 +840,95 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
/* n1 */
if (a->Z_is_one) {
- if (!field_sqr(group, n0, &a->X, ctx))
- goto err;
- if (!BN_mod_lshift1_quick(n1, n0, p))
- goto err;
- if (!BN_mod_add_quick(n0, n0, n1, p))
- goto err;
- if (!BN_mod_add_quick(n1, n0, &group->a, p))
+ if (!field_sqr(group, n0, &a->X, ctx) ||
+ !BN_mod_lshift1_quick(n1, n0, p) ||
+ !BN_mod_add_quick(n0, n0, n1, p) ||
+ !BN_mod_add_quick(n1, n0, &group->a, p)) {
goto err;
+ }
/* n1 = 3 * X_a^2 + a_curve */
} else if (group->a_is_minus3) {
- if (!field_sqr(group, n1, &a->Z, ctx))
- goto err;
- if (!BN_mod_add_quick(n0, &a->X, n1, p))
- goto err;
- if (!BN_mod_sub_quick(n2, &a->X, n1, p))
- goto err;
- if (!field_mul(group, n1, n0, n2, ctx))
- goto err;
- if (!BN_mod_lshift1_quick(n0, n1, p))
- goto err;
- if (!BN_mod_add_quick(n1, n0, n1, p))
+ if (!field_sqr(group, n1, &a->Z, ctx) ||
+ !BN_mod_add_quick(n0, &a->X, n1, p) ||
+ !BN_mod_sub_quick(n2, &a->X, n1, p) ||
+ !field_mul(group, n1, n0, n2, ctx) ||
+ !BN_mod_lshift1_quick(n0, n1, p) ||
+ !BN_mod_add_quick(n1, n0, n1, p)) {
goto err;
+ }
/* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
* = 3 * X_a^2 - 3 * Z_a^4 */
} else {
- if (!field_sqr(group, n0, &a->X, ctx))
- goto err;
- if (!BN_mod_lshift1_quick(n1, n0, p))
- goto err;
- if (!BN_mod_add_quick(n0, n0, n1, p))
- goto err;
- if (!field_sqr(group, n1, &a->Z, ctx))
- goto err;
- if (!field_sqr(group, n1, n1, ctx))
- goto err;
- if (!field_mul(group, n1, n1, &group->a, ctx))
- goto err;
- if (!BN_mod_add_quick(n1, n1, n0, p))
+ if (!field_sqr(group, n0, &a->X, ctx) ||
+ !BN_mod_lshift1_quick(n1, n0, p) ||
+ !BN_mod_add_quick(n0, n0, n1, p) ||
+ !field_sqr(group, n1, &a->Z, ctx) ||
+ !field_sqr(group, n1, n1, ctx) ||
+ !field_mul(group, n1, n1, &group->a, ctx) ||
+ !BN_mod_add_quick(n1, n1, n0, p)) {
goto err;
+ }
/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
}
/* Z_r */
if (a->Z_is_one) {
- if (!BN_copy(n0, &a->Y))
- goto err;
- } else {
- if (!field_mul(group, n0, &a->Y, &a->Z, ctx))
+ if (!BN_copy(n0, &a->Y)) {
goto err;
+ }
+ } else if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) {
+ goto err;
}
- if (!BN_mod_lshift1_quick(&r->Z, n0, p))
+ if (!BN_mod_lshift1_quick(&r->Z, n0, p)) {
goto err;
+ }
r->Z_is_one = 0;
/* Z_r = 2 * Y_a * Z_a */
/* n2 */
- if (!field_sqr(group, n3, &a->Y, ctx))
- goto err;
- if (!field_mul(group, n2, &a->X, n3, ctx))
- goto err;
- if (!BN_mod_lshift_quick(n2, n2, 2, p))
+ if (!field_sqr(group, n3, &a->Y, ctx) ||
+ !field_mul(group, n2, &a->X, n3, ctx) ||
+ !BN_mod_lshift_quick(n2, n2, 2, p)) {
goto err;
+ }
/* n2 = 4 * X_a * Y_a^2 */
/* X_r */
- if (!BN_mod_lshift1_quick(n0, n2, p))
- goto err;
- if (!field_sqr(group, &r->X, n1, ctx))
- goto err;
- if (!BN_mod_sub_quick(&r->X, &r->X, n0, p))
+ if (!BN_mod_lshift1_quick(n0, n2, p) ||
+ !field_sqr(group, &r->X, n1, ctx) ||
+ !BN_mod_sub_quick(&r->X, &r->X, n0, p)) {
goto err;
+ }
/* X_r = n1^2 - 2 * n2 */
/* n3 */
- if (!field_sqr(group, n0, n3, ctx))
- goto err;
- if (!BN_mod_lshift_quick(n3, n0, 3, p))
+ if (!field_sqr(group, n0, n3, ctx) ||
+ !BN_mod_lshift_quick(n3, n0, 3, p)) {
goto err;
+ }
/* n3 = 8 * Y_a^4 */
/* Y_r */
- if (!BN_mod_sub_quick(n0, n2, &r->X, p))
- goto err;
- if (!field_mul(group, n0, n1, n0, ctx))
- goto err;
- if (!BN_mod_sub_quick(&r->Y, n0, n3, p))
+ if (!BN_mod_sub_quick(n0, n2, &r->X, p) ||
+ !field_mul(group, n0, n1, n0, ctx) ||
+ !BN_mod_sub_quick(&r->Y, n0, n3, p)) {
goto err;
+ }
/* Y_r = n1 * (n2 - X_r) - n3 */
ret = 1;
err:
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
- if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
+ if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) {
/* point is its own inverse */
return 1;
+ }
return BN_usub(&point->Y, &group->field, &point->Y);
}
@@ -955,8 +947,9 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BIGNUM *rh, *tmp, *Z4, *Z6;
int ret = -1;
- if (EC_POINT_is_at_infinity(group, point))
+ if (EC_POINT_is_at_infinity(group, point)) {
return 1;
+ }
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
@@ -964,8 +957,9 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return -1;
+ }
}
BN_CTX_start(ctx);
@@ -973,8 +967,9 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
tmp = BN_CTX_get(ctx);
Z4 = BN_CTX_get(ctx);
Z6 = BN_CTX_get(ctx);
- if (Z6 == NULL)
+ if (Z6 == NULL) {
goto err;
+ }
/* We have a curve defined by a Weierstrass equation
* y^2 = x^3 + a*x + b.
@@ -987,64 +982,62 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
*/
/* rh := X^2 */
- if (!field_sqr(group, rh, &point->X, ctx))
+ if (!field_sqr(group, rh, &point->X, ctx)) {
goto err;
+ }
if (!point->Z_is_one) {
- if (!field_sqr(group, tmp, &point->Z, ctx))
- goto err;
- if (!field_sqr(group, Z4, tmp, ctx))
- goto err;
- if (!field_mul(group, Z6, Z4, tmp, ctx))
+ if (!field_sqr(group, tmp, &point->Z, ctx) ||
+ !field_sqr(group, Z4, tmp, ctx) ||
+ !field_mul(group, Z6, Z4, tmp, ctx)) {
goto err;
+ }
/* rh := (rh + a*Z^4)*X */
if (group->a_is_minus3) {
- if (!BN_mod_lshift1_quick(tmp, Z4, p))
- goto err;
- if (!BN_mod_add_quick(tmp, tmp, Z4, p))
- goto err;
- if (!BN_mod_sub_quick(rh, rh, tmp, p))
- goto err;
- if (!field_mul(group, rh, rh, &point->X, ctx))
+ if (!BN_mod_lshift1_quick(tmp, Z4, p) ||
+ !BN_mod_add_quick(tmp, tmp, Z4, p) ||
+ !BN_mod_sub_quick(rh, rh, tmp, p) ||
+ !field_mul(group, rh, rh, &point->X, ctx)) {
goto err;
+ }
} else {
- if (!field_mul(group, tmp, Z4, &group->a, ctx))
- goto err;
- if (!BN_mod_add_quick(rh, rh, tmp, p))
- goto err;
- if (!field_mul(group, rh, rh, &point->X, ctx))
+ if (!field_mul(group, tmp, Z4, &group->a, ctx) ||
+ !BN_mod_add_quick(rh, rh, tmp, p) ||
+ !field_mul(group, rh, rh, &point->X, ctx)) {
goto err;
+ }
}
/* rh := rh + b*Z^6 */
- if (!field_mul(group, tmp, &group->b, Z6, ctx))
- goto err;
- if (!BN_mod_add_quick(rh, rh, tmp, p))
+ if (!field_mul(group, tmp, &group->b, Z6, ctx) ||
+ !BN_mod_add_quick(rh, rh, tmp, p)) {
goto err;
+ }
} else {
/* point->Z_is_one */
/* rh := (rh + a)*X */
- if (!BN_mod_add_quick(rh, rh, &group->a, p))
- goto err;
- if (!field_mul(group, rh, rh, &point->X, ctx))
+ if (!BN_mod_add_quick(rh, rh, &group->a, p) ||
+ !field_mul(group, rh, rh, &point->X, ctx)) {
goto err;
+ }
/* rh := rh + b */
- if (!BN_mod_add_quick(rh, rh, &group->b, p))
+ if (!BN_mod_add_quick(rh, rh, &group->b, p)) {
goto err;
+ }
}
/* 'lh' := Y^2 */
- if (!field_sqr(group, tmp, &point->Y, ctx))
+ if (!field_sqr(group, tmp, &point->Y, ctx)) {
goto err;
+ }
ret = (0 == BN_ucmp(tmp, rh));
err:
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -1068,8 +1061,9 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
}
- if (EC_POINT_is_at_infinity(group, b))
+ if (EC_POINT_is_at_infinity(group, b)) {
return 1;
+ }
if (a->Z_is_one && b->Z_is_one) {
return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
@@ -1080,8 +1074,9 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return -1;
+ }
}
BN_CTX_start(ctx);
@@ -1089,8 +1084,9 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
tmp2 = BN_CTX_get(ctx);
Za23 = BN_CTX_get(ctx);
Zb23 = BN_CTX_get(ctx);
- if (Zb23 == NULL)
+ if (Zb23 == NULL) {
goto end;
+ }
/* We have to decide whether
* (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
@@ -1099,21 +1095,23 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
*/
if (!b->Z_is_one) {
- if (!field_sqr(group, Zb23, &b->Z, ctx))
- goto end;
- if (!field_mul(group, tmp1, &a->X, Zb23, ctx))
+ if (!field_sqr(group, Zb23, &b->Z, ctx) ||
+ !field_mul(group, tmp1, &a->X, Zb23, ctx)) {
goto end;
+ }
tmp1_ = tmp1;
- } else
+ } else {
tmp1_ = &a->X;
+ }
if (!a->Z_is_one) {
- if (!field_sqr(group, Za23, &a->Z, ctx))
- goto end;
- if (!field_mul(group, tmp2, &b->X, Za23, ctx))
+ if (!field_sqr(group, Za23, &a->Z, ctx) ||
+ !field_mul(group, tmp2, &b->X, Za23, ctx)) {
goto end;
+ }
tmp2_ = tmp2;
- } else
+ } else {
tmp2_ = &b->X;
+ }
/* compare X_a*Z_b^2 with X_b*Z_a^2 */
if (BN_cmp(tmp1_, tmp2_) != 0) {
@@ -1123,21 +1121,23 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
if (!b->Z_is_one) {
- if (!field_mul(group, Zb23, Zb23, &b->Z, ctx))
- goto end;
- if (!field_mul(group, tmp1, &a->Y, Zb23, ctx))
+ if (!field_mul(group, Zb23, Zb23, &b->Z, ctx) ||
+ !field_mul(group, tmp1, &a->Y, Zb23, ctx)) {
goto end;
+ }
/* tmp1_ = tmp1 */
- } else
+ } else {
tmp1_ = &a->Y;
+ }
if (!a->Z_is_one) {
- if (!field_mul(group, Za23, Za23, &a->Z, ctx))
- goto end;
- if (!field_mul(group, tmp2, &b->Y, Za23, ctx))
+ if (!field_mul(group, Za23, Za23, &a->Z, ctx) ||
+ !field_mul(group, tmp2, &b->Y, Za23, ctx)) {
goto end;
+ }
/* tmp2_ = tmp2 */
- } else
+ } else {
tmp2_ = &b->Y;
+ }
/* compare Y_a*Z_b^3 with Y_b*Z_a^3 */
if (BN_cmp(tmp1_, tmp2_) != 0) {
@@ -1150,8 +1150,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
end:
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -1161,25 +1160,28 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
BIGNUM *x, *y;
int ret = 0;
- if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
+ if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) {
return 1;
+ }
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
return 0;
+ }
}
BN_CTX_start(ctx);
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))
- goto err;
- if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
+ if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) ||
+ !EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
goto err;
+ }
if (!point->Z_is_one) {
OPENSSL_PUT_ERROR(EC, ec_GFp_simple_make_affine, ERR_R_INTERNAL_ERROR);
goto err;
@@ -1189,8 +1191,7 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
err:
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
@@ -1335,9 +1336,7 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
err:
BN_CTX_end(ctx);
- if (new_ctx != NULL) {
- BN_CTX_free(new_ctx);
- }
+ BN_CTX_free(new_ctx);
if (prod_Z != NULL) {
for (i = 0; i < num; i++) {
if (prod_Z[i] == NULL) {
diff --git a/src/crypto/ec/util-64.c b/src/crypto/ec/util-64.c
new file mode 100644
index 0000000..171b063
--- /dev/null
+++ b/src/crypto/ec/util-64.c
@@ -0,0 +1,183 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/base.h>
+
+
+#if defined(OPENSSL_64_BIT) && !defined(OPENSSL_WINDOWS)
+
+#include <openssl/ec.h>
+
+#include "internal.h"
+
+/* Convert an array of points into affine coordinates. (If the point at
+ * infinity is found (Z = 0), it remains unchanged.) This function is
+ * essentially an equivalent to EC_POINTs_make_affine(), but works with the
+ * internal representation of points as used by ecp_nistp###.c rather than
+ * with (BIGNUM-based) EC_POINT data structures. point_array is the
+ * input/output buffer ('num' points in projective form, i.e. three
+ * coordinates each), based on an internal representation of field elements
+ * of size 'felem_size'. tmp_felems needs to point to a temporary array of
+ * 'num'+1 field elements for storage of intermediate values. */
+void ec_GFp_nistp_points_make_affine_internal(
+ size_t num, void *point_array, size_t felem_size, void *tmp_felems,
+ void (*felem_one)(void *out), int (*felem_is_zero)(const void *in),
+ void (*felem_assign)(void *out, const void *in),
+ void (*felem_square)(void *out, const void *in),
+ void (*felem_mul)(void *out, const void *in1, const void *in2),
+ void (*felem_inv)(void *out, const void *in),
+ void (*felem_contract)(void *out, const void *in)) {
+ int i = 0;
+
+#define tmp_felem(I) (&((char *)tmp_felems)[(I)*felem_size])
+#define X(I) (&((char *)point_array)[3 * (I)*felem_size])
+#define Y(I) (&((char *)point_array)[(3 * (I) + 1) * felem_size])
+#define Z(I) (&((char *)point_array)[(3 * (I) + 2) * felem_size])
+
+ if (!felem_is_zero(Z(0))) {
+ felem_assign(tmp_felem(0), Z(0));
+ } else {
+ felem_one(tmp_felem(0));
+ }
+
+ for (i = 1; i < (int)num; i++) {
+ if (!felem_is_zero(Z(i))) {
+ felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i));
+ } else {
+ felem_assign(tmp_felem(i), tmp_felem(i - 1));
+ }
+ }
+ /* Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any
+ * zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1. */
+
+ felem_inv(tmp_felem(num - 1), tmp_felem(num - 1));
+ for (i = num - 1; i >= 0; i--) {
+ if (i > 0) {
+ /* tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i)
+ * is the inverse of the product of Z(0) .. Z(i). */
+ /* 1/Z(i) */
+ felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i));
+ } else {
+ felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
+ }
+
+ if (!felem_is_zero(Z(i))) {
+ if (i > 0) {
+ /* For next iteration, replace tmp_felem(i-1) by its inverse. */
+ felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i));
+ }
+
+ /* Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1). */
+ felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */
+ felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */
+ felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
+ felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */
+ felem_contract(X(i), X(i));
+ felem_contract(Y(i), Y(i));
+ felem_one(Z(i));
+ } else {
+ if (i > 0) {
+ /* For next iteration, replace tmp_felem(i-1) by its inverse. */
+ felem_assign(tmp_felem(i - 1), tmp_felem(i));
+ }
+ }
+ }
+}
+
+/* This function looks at 5+1 scalar bits (5 current, 1 adjacent less
+ * significant bit), and recodes them into a signed digit for use in fast point
+ * multiplication: the use of signed rather than unsigned digits means that
+ * fewer points need to be precomputed, given that point inversion is easy (a
+ * precomputed point dP makes -dP available as well).
+ *
+ * BACKGROUND:
+ *
+ * Signed digits for multiplication were introduced by Booth ("A signed binary
+ * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV,
+ * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers.
+ * Booth's original encoding did not generally improve the density of nonzero
+ * digits over the binary representation, and was merely meant to simplify the
+ * handling of signed factors given in two's complement; but it has since been
+ * shown to be the basis of various signed-digit representations that do have
+ * further advantages, including the wNAF, using the following general
+ * approach:
+ *
+ * (1) Given a binary representation
+ *
+ * b_k ... b_2 b_1 b_0,
+ *
+ * of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1
+ * by using bit-wise subtraction as follows:
+ *
+ * b_k b_(k-1) ... b_2 b_1 b_0
+ * - b_k ... b_3 b_2 b_1 b_0
+ * -------------------------------------
+ * s_k b_(k-1) ... s_3 s_2 s_1 s_0
+ *
+ * A left-shift followed by subtraction of the original value yields a new
+ * representation of the same value, using signed bits s_i = b_(i+1) - b_i.
+ * This representation from Booth's paper has since appeared in the
+ * literature under a variety of different names including "reversed binary
+ * form", "alternating greedy expansion", "mutual opposite form", and
+ * "sign-alternating {+-1}-representation".
+ *
+ * An interesting property is that among the nonzero bits, values 1 and -1
+ * strictly alternate.
+ *
+ * (2) Various window schemes can be applied to the Booth representation of
+ * integers: for example, right-to-left sliding windows yield the wNAF
+ * (a signed-digit encoding independently discovered by various researchers
+ * in the 1990s), and left-to-right sliding windows yield a left-to-right
+ * equivalent of the wNAF (independently discovered by various researchers
+ * around 2004).
+ *
+ * To prevent leaking information through side channels in point multiplication,
+ * we need to recode the given integer into a regular pattern: sliding windows
+ * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few
+ * decades older: we'll be using the so-called "modified Booth encoding" due to
+ * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49
+ * (1961), pp. 67-91), in a radix-2^5 setting. That is, we always combine five
+ * signed bits into a signed digit:
+ *
+ * s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j)
+ *
+ * The sign-alternating property implies that the resulting digit values are
+ * integers from -16 to 16.
+ *
+ * Of course, we don't actually need to compute the signed digits s_i as an
+ * intermediate step (that's just a nice way to see how this scheme relates
+ * to the wNAF): a direct computation obtains the recoded digit from the
+ * six bits b_(4j + 4) ... b_(4j - 1).
+ *
+ * This function takes those five bits as an integer (0 .. 63), writing the
+ * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute
+ * value, in the range 0 .. 8). Note that this integer essentially provides the
+ * input bits "shifted to the left" by one position: for example, the input to
+ * compute the least significant recoded digit, given that there's no bit b_-1,
+ * has to be b_4 b_3 b_2 b_1 b_0 0. */
+void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit,
+ uint8_t in) {
+ uint8_t s, d;
+
+ s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as
+ * 6-bit value */
+ d = (1 << 6) - in - 1;
+ d = (d & s) | (in & ~s);
+ d = (d >> 1) + (d & 1);
+
+ *sign = s & 1;
+ *digit = d;
+}
+
+#endif /* 64_BIT && !WINDOWS */
diff --git a/src/crypto/ec/wnaf.c b/src/crypto/ec/wnaf.c
index 9016328..d87a7d9 100644
--- a/src/crypto/ec/wnaf.c
+++ b/src/crypto/ec/wnaf.c
@@ -72,6 +72,7 @@
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
+#include <openssl/thread.h>
#include "internal.h"
@@ -84,7 +85,6 @@
/* structure for precomputed multiples of the generator */
typedef struct ec_pre_comp_st {
- const EC_GROUP *group; /* parent EC_GROUP object */
size_t blocksize; /* block size for wNAF splitting */
size_t numblocks; /* max. number of blocks for which we have precomputation */
size_t w; /* window size */
@@ -94,18 +94,14 @@ typedef struct ec_pre_comp_st {
int references;
} EC_PRE_COMP;
-static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) {
+static EC_PRE_COMP *ec_pre_comp_new(void) {
EC_PRE_COMP *ret = NULL;
- if (!group)
- return NULL;
-
ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP));
if (!ret) {
OPENSSL_PUT_ERROR(EC, ec_pre_comp_new, ERR_R_MALLOC_FAILURE);
return ret;
}
- ret->group = group;
ret->blocksize = 8; /* default */
ret->numblocks = 0;
ret->w = 4; /* default */
@@ -125,14 +121,8 @@ void *ec_pre_comp_dup(EC_PRE_COMP *pre_comp) {
}
void ec_pre_comp_free(EC_PRE_COMP *pre_comp) {
- int i;
-
- if (!pre_comp) {
- return;
- }
-
- i = CRYPTO_add(&pre_comp->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
- if (i > 0) {
+ if (pre_comp == NULL ||
+ CRYPTO_add(&pre_comp->references, -1, CRYPTO_LOCK_EC_PRE_COMP) > 0) {
return;
}
@@ -272,8 +262,9 @@ err:
OPENSSL_free(r);
r = NULL;
}
- if (ok)
+ if (ok) {
*ret_len = len;
+ }
return r;
}
@@ -341,8 +332,9 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
goto err;
+ }
}
if (scalar != NULL) {
@@ -365,8 +357,9 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
numblocks = (BN_num_bits(scalar) / blocksize) + 1;
/* we cannot use more blocks than we have precomputation for */
- if (numblocks > pre_comp->numblocks)
+ if (numblocks > pre_comp->numblocks) {
numblocks = pre_comp->numblocks;
+ }
pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
@@ -413,10 +406,12 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
wNAF[i + 1] = NULL; /* make sure we always have a pivot */
wNAF[i] =
compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i]);
- if (wNAF[i] == NULL)
+ if (wNAF[i] == NULL) {
goto err;
- if (wNAF_len[i] > max_len)
+ }
+ if (wNAF_len[i] > max_len) {
max_len = wNAF_len[i];
+ }
}
if (numblocks) {
@@ -440,8 +435,9 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
/* use the window size for which we have precomputation */
wsize[num] = pre_comp->w;
tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len);
- if (!tmp_wNAF)
+ if (!tmp_wNAF) {
goto err;
+ }
if (tmp_len <= max_len) {
/* One of the other wNAFs is at least as long
@@ -484,10 +480,11 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
goto err;
}
tmp_len -= blocksize;
- } else
+ } else {
/* last block gets whatever is left
* (this could be more or less than 'blocksize'!) */
wNAF_len[i] = tmp_len;
+ }
wNAF[i + 1] = NULL;
wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
@@ -497,8 +494,9 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
goto err;
}
memcpy(wNAF[i], pp, wNAF_len[i]);
- if (wNAF_len[i] > max_len)
+ if (wNAF_len[i] > max_len) {
max_len = wNAF_len[i];
+ }
if (*tmp_points == NULL) {
OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_INTERNAL_ERROR);
@@ -531,8 +529,9 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
val_sub[i] = v;
for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) {
*v = EC_POINT_new(group);
- if (*v == NULL)
+ if (*v == NULL) {
goto err;
+ }
v++;
}
}
@@ -541,8 +540,9 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
goto err;
}
- if (!(tmp = EC_POINT_new(group)))
+ if (!(tmp = EC_POINT_new(group))) {
goto err;
+ }
/* prepare precomputed values:
* val_sub[i][0] := points[i]
@@ -552,34 +552,36 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
*/
for (i = 0; i < num + num_scalar; i++) {
if (i < num) {
- if (!EC_POINT_copy(val_sub[i][0], points[i]))
- goto err;
- } else {
- if (!EC_POINT_copy(val_sub[i][0], generator))
+ if (!EC_POINT_copy(val_sub[i][0], points[i])) {
goto err;
+ }
+ } else if (!EC_POINT_copy(val_sub[i][0], generator)) {
+ goto err;
}
if (wsize[i] > 1) {
- if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx))
+ if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) {
goto err;
+ }
for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) {
- if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx))
+ if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) {
goto err;
+ }
}
}
}
#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */
- if (!EC_POINTs_make_affine(group, num_val, val, ctx))
+ if (!EC_POINTs_make_affine(group, num_val, val, ctx)) {
goto err;
+ }
#endif
r_is_at_infinity = 1;
for (k = max_len - 1; k >= 0; k--) {
- if (!r_is_at_infinity) {
- if (!EC_POINT_dbl(group, r, r, ctx))
- goto err;
+ if (!r_is_at_infinity && !EC_POINT_dbl(group, r, r, ctx)) {
+ goto err;
}
for (i = 0; i < totalnum; i++) {
@@ -590,13 +592,13 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
if (digit) {
is_neg = digit < 0;
- if (is_neg)
+ if (is_neg) {
digit = -digit;
+ }
if (is_neg != r_is_inverted) {
- if (!r_is_at_infinity) {
- if (!EC_POINT_invert(group, r, ctx))
- goto err;
+ if (!r_is_at_infinity && !EC_POINT_invert(group, r, ctx)) {
+ goto err;
}
r_is_inverted = !r_is_inverted;
}
@@ -604,12 +606,14 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
/* digit > 0 */
if (r_is_at_infinity) {
- if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))
+ if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) {
goto err;
+ }
r_is_at_infinity = 0;
} else {
- if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx))
+ if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx)) {
goto err;
+ }
}
}
}
@@ -617,42 +621,37 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
}
if (r_is_at_infinity) {
- if (!EC_POINT_set_to_infinity(group, r))
+ if (!EC_POINT_set_to_infinity(group, r)) {
goto err;
- } else {
- if (r_is_inverted)
- if (!EC_POINT_invert(group, r, ctx))
- goto err;
+ }
+ } else if (r_is_inverted && !EC_POINT_invert(group, r, ctx)) {
+ goto err;
}
ret = 1;
err:
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
- if (tmp != NULL)
- EC_POINT_free(tmp);
- if (wsize != NULL)
- OPENSSL_free(wsize);
- if (wNAF_len != NULL)
- OPENSSL_free(wNAF_len);
+ BN_CTX_free(new_ctx);
+ EC_POINT_free(tmp);
+ OPENSSL_free(wsize);
+ OPENSSL_free(wNAF_len);
if (wNAF != NULL) {
signed char **w;
- for (w = wNAF; *w != NULL; w++)
+ for (w = wNAF; *w != NULL; w++) {
OPENSSL_free(*w);
+ }
OPENSSL_free(wNAF);
}
if (val != NULL) {
- for (v = val; *v != NULL; v++)
+ for (v = val; *v != NULL; v++) {
EC_POINT_clear_free(*v);
+ }
OPENSSL_free(val);
}
- if (val_sub != NULL) {
- OPENSSL_free(val_sub);
- }
+ OPENSSL_free(val_sub);
return ret;
}
@@ -690,33 +689,36 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
int ret = 0;
/* if there is an old EC_PRE_COMP object, throw it away */
- if (group->pre_comp) {
- ec_pre_comp_free(group->pre_comp);
- group->pre_comp = NULL;
- }
-
- if ((pre_comp = ec_pre_comp_new(group)) == NULL)
- return 0;
+ ec_pre_comp_free(group->pre_comp);
+ group->pre_comp = NULL;
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
OPENSSL_PUT_ERROR(EC, ec_wNAF_precompute_mult, EC_R_UNDEFINED_GENERATOR);
- goto err;
+ return 0;
+ }
+
+ pre_comp = ec_pre_comp_new();
+ if (pre_comp == NULL) {
+ return 0;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
+ if (ctx == NULL) {
goto err;
+ }
}
BN_CTX_start(ctx);
order = BN_CTX_get(ctx);
- if (order == NULL)
+ if (order == NULL) {
goto err;
+ }
- if (!EC_GROUP_get_order(group, order, ctx))
+ if (!EC_GROUP_get_order(group, order, ctx)) {
goto err;
+ }
if (BN_is_zero(order)) {
OPENSSL_PUT_ERROR(EC, ec_wNAF_precompute_mult, EC_R_UNKNOWN_ORDER);
goto err;
@@ -764,23 +766,27 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
goto err;
}
- if (!EC_POINT_copy(base, generator))
+ if (!EC_POINT_copy(base, generator)) {
goto err;
+ }
/* do the precomputation */
for (i = 0; i < numblocks; i++) {
size_t j;
- if (!EC_POINT_dbl(group, tmp_point, base, ctx))
+ if (!EC_POINT_dbl(group, tmp_point, base, ctx)) {
goto err;
+ }
- if (!EC_POINT_copy(*var++, base))
+ if (!EC_POINT_copy(*var++, base)) {
goto err;
+ }
for (j = 1; j < pre_points_per_block; j++, var++) {
/* calculate odd multiples of the current base point */
- if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))
+ if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx)) {
goto err;
+ }
}
if (i < numblocks - 1) {
@@ -792,19 +798,21 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
goto err;
}
- if (!EC_POINT_dbl(group, base, tmp_point, ctx))
+ if (!EC_POINT_dbl(group, base, tmp_point, ctx)) {
goto err;
+ }
for (k = 2; k < blocksize; k++) {
- if (!EC_POINT_dbl(group, base, base, ctx))
+ if (!EC_POINT_dbl(group, base, base, ctx)) {
goto err;
+ }
}
}
}
- if (!EC_POINTs_make_affine(group, num, points, ctx))
+ if (!EC_POINTs_make_affine(group, num, points, ctx)) {
goto err;
+ }
- pre_comp->group = group;
pre_comp->blocksize = blocksize;
pre_comp->numblocks = numblocks;
pre_comp->w = w;
@@ -818,23 +826,21 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
ret = 1;
err:
- if (ctx != NULL)
+ if (ctx != NULL) {
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
- if (pre_comp)
- ec_pre_comp_free(pre_comp);
+ }
+ BN_CTX_free(new_ctx);
+ ec_pre_comp_free(pre_comp);
if (points) {
EC_POINT **p;
- for (p = points; *p != NULL; p++)
+ for (p = points; *p != NULL; p++) {
EC_POINT_free(*p);
+ }
OPENSSL_free(points);
}
- if (tmp_point)
- EC_POINT_free(tmp_point);
- if (base)
- EC_POINT_free(base);
+ EC_POINT_free(tmp_point);
+ EC_POINT_free(base);
return ret;
}
diff --git a/src/crypto/ecdh/CMakeLists.txt b/src/crypto/ecdh/CMakeLists.txt
index b312148..346e72d 100644
--- a/src/crypto/ecdh/CMakeLists.txt
+++ b/src/crypto/ecdh/CMakeLists.txt
@@ -6,5 +6,4 @@ add_library(
OBJECT
ecdh.c
- ecdh_error.c
)
diff --git a/src/crypto/ecdh/ecdh.c b/src/crypto/ecdh/ecdh.c
index d4497f1..a011bab 100644
--- a/src/crypto/ecdh/ecdh.c
+++ b/src/crypto/ecdh/ecdh.c
@@ -145,13 +145,17 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
}
err:
- if (tmp)
+ if (tmp) {
EC_POINT_free(tmp);
- if (ctx)
+ }
+ if (ctx) {
BN_CTX_end(ctx);
- if (ctx)
+ }
+ if (ctx) {
BN_CTX_free(ctx);
- if (buf)
+ }
+ if (buf) {
OPENSSL_free(buf);
+ }
return ret;
}
diff --git a/src/crypto/ecdh/ecdh_error.c b/src/crypto/ecdh/ecdh_error.c
deleted file mode 100644
index 8ba1854..0000000
--- a/src/crypto/ecdh/ecdh_error.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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/ecdh.h>
-
-const ERR_STRING_DATA ECDH_error_string_data[] = {
- {ERR_PACK(ERR_LIB_ECDH, ECDH_F_ECDH_compute_key, 0), "ECDH_compute_key"},
- {ERR_PACK(ERR_LIB_ECDH, 0, ECDH_R_KDF_FAILED), "KDF_FAILED"},
- {ERR_PACK(ERR_LIB_ECDH, 0, ECDH_R_NO_PRIVATE_VALUE), "NO_PRIVATE_VALUE"},
- {ERR_PACK(ERR_LIB_ECDH, 0, ECDH_R_POINT_ARITHMETIC_FAILURE), "POINT_ARITHMETIC_FAILURE"},
- {0, NULL},
-};
diff --git a/src/crypto/ecdsa/CMakeLists.txt b/src/crypto/ecdsa/CMakeLists.txt
index 4bddd27..c8645d1 100644
--- a/src/crypto/ecdsa/CMakeLists.txt
+++ b/src/crypto/ecdsa/CMakeLists.txt
@@ -7,14 +7,13 @@ add_library(
ecdsa.c
ecdsa_asn1.c
- ecdsa_error.c
)
add_executable(
ecdsa_test
- ecdsa_test.c
+ ecdsa_test.cc
)
target_link_libraries(ecdsa_test crypto)
diff --git a/src/crypto/ecdsa/ecdsa.c b/src/crypto/ecdsa/ecdsa.c
index d389799..b71799e 100644
--- a/src/crypto/ecdsa/ecdsa.c
+++ b/src/crypto/ecdsa/ecdsa.c
@@ -57,7 +57,6 @@
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-#include <openssl/thread.h>
#include "../ec/internal.h"
@@ -98,12 +97,8 @@ int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
ret = ECDSA_do_verify(digest, digest_len, s, eckey);
err:
- if (der != NULL) {
- OPENSSL_free(der);
- }
- if (s != NULL) {
- ECDSA_SIG_free(s);
- }
+ OPENSSL_free(der);
+ ECDSA_SIG_free(s);
return ret;
}
@@ -232,9 +227,7 @@ int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
- if (point) {
- EC_POINT_free(point);
- }
+ EC_POINT_free(point);
return ret;
}
@@ -334,12 +327,8 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
goto err;
}
/* clear old values if necessary */
- if (*rp != NULL) {
- BN_clear_free(*rp);
- }
- if (*kinvp != NULL) {
- BN_clear_free(*kinvp);
- }
+ BN_clear_free(*rp);
+ BN_clear_free(*kinvp);
/* save the pre-computed values */
*rp = r;
@@ -348,21 +337,15 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
err:
if (!ret) {
- if (k != NULL) {
- BN_clear_free(k);
- }
- if (r != NULL) {
- BN_clear_free(r);
- }
+ BN_clear_free(k);
+ BN_clear_free(r);
}
- if (ctx_in == NULL)
+ if (ctx_in == NULL) {
BN_CTX_free(ctx);
- if (order != NULL)
- BN_free(order);
- if (tmp_point != NULL)
- EC_POINT_free(tmp_point);
- if (X)
- BN_clear_free(X);
+ }
+ BN_free(order);
+ EC_POINT_free(tmp_point);
+ BN_clear_free(X);
return ret;
}
@@ -461,16 +444,11 @@ err:
ECDSA_SIG_free(ret);
ret = NULL;
}
- if (ctx)
- BN_CTX_free(ctx);
- if (m)
- BN_clear_free(m);
- if (tmp)
- BN_clear_free(tmp);
- if (order)
- BN_free(order);
- if (kinv)
- BN_clear_free(kinv);
+ BN_CTX_free(ctx);
+ BN_clear_free(m);
+ BN_clear_free(tmp);
+ BN_free(order);
+ BN_clear_free(kinv);
return ret;
}
diff --git a/src/crypto/ecdsa/ecdsa_asn1.c b/src/crypto/ecdsa/ecdsa_asn1.c
index b3c6a87..f557ca7 100644
--- a/src/crypto/ecdsa/ecdsa_asn1.c
+++ b/src/crypto/ecdsa/ecdsa_asn1.c
@@ -55,6 +55,7 @@
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/ec_key.h>
+#include <openssl/mem.h>
#include "../ec/internal.h"
@@ -67,7 +68,7 @@ ASN1_SEQUENCE(ECDSA_SIG) = {
ASN1_SIMPLE(ECDSA_SIG, s, CBIGNUM),
} ASN1_SEQUENCE_END(ECDSA_SIG);
-IMPLEMENT_ASN1_FUNCTIONS_const(ECDSA_SIG);
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ECDSA_SIG, ECDSA_SIG, ECDSA_SIG);
size_t ECDSA_size(const EC_KEY *key) {
size_t ret, i, group_order_size;
@@ -114,3 +115,27 @@ size_t ECDSA_size(const EC_KEY *key) {
BN_clear_free(order);
return ret;
}
+
+ECDSA_SIG *ECDSA_SIG_new(void) {
+ ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG));
+ if (sig == NULL) {
+ return NULL;
+ }
+ sig->r = BN_new();
+ sig->s = BN_new();
+ if (sig->r == NULL || sig->s == NULL) {
+ ECDSA_SIG_free(sig);
+ return NULL;
+ }
+ return sig;
+}
+
+void ECDSA_SIG_free(ECDSA_SIG *sig) {
+ if (sig == NULL) {
+ return;
+ }
+
+ BN_free(sig->r);
+ BN_free(sig->s);
+ OPENSSL_free(sig);
+}
diff --git a/src/crypto/ecdsa/ecdsa_error.c b/src/crypto/ecdsa/ecdsa_error.c
deleted file mode 100644
index cbd69ce..0000000
--- a/src/crypto/ecdsa/ecdsa_error.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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/ecdsa.h>
-
-const ERR_STRING_DATA ECDSA_error_string_data[] = {
- {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_do_sign_ex, 0), "ECDSA_do_sign_ex"},
- {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_do_verify, 0), "ECDSA_do_verify"},
- {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_sign_ex, 0), "ECDSA_sign_ex"},
- {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_sign_setup, 0), "ECDSA_sign_setup"},
- {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_digest_to_bn, 0), "digest_to_bn"},
- {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ecdsa_sign_setup, 0), "ecdsa_sign_setup"},
- {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_BAD_SIGNATURE), "BAD_SIGNATURE"},
- {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
- {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_NEED_NEW_SETUP_VALUES), "NEED_NEW_SETUP_VALUES"},
- {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_NOT_IMPLEMENTED), "NOT_IMPLEMENTED"},
- {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED), "RANDOM_NUMBER_GENERATION_FAILED"},
- {0, NULL},
-};
diff --git a/src/crypto/ecdsa/ecdsa_test.c b/src/crypto/ecdsa/ecdsa_test.c
deleted file mode 100644
index d48f9c3..0000000
--- a/src/crypto/ecdsa/ecdsa_test.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* ====================================================================
- * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * openssl-core@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com). */
-
-#include <openssl/ecdsa.h>
-
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/crypto.h>
-#include <openssl/ec.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-
-
-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, r_len, s_len, bn_len, buf_len;
- int nid, ret = 0;
-
- /* fill digest values with some random data */
- 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,
- "\ntesting ECDSA_sign() and ECDSA_verify() "
- "with some internal curves:\n");
-
- static const int kCurveNIDs[] = {NID_secp224r1, NID_X9_62_prime256v1,
- NID_secp384r1, NID_secp521r1, NID_undef};
-
- /* now create and verify a signature for every curve */
- for (n = 0; kCurveNIDs[n] != NID_undef; n++) {
- unsigned char dirt, offset;
-
- nid = kCurveNIDs[n];
- /* create new ecdsa key (== EC_KEY) */
- eckey = EC_KEY_new();
- if (eckey == NULL) {
- goto builtin_err;
- }
- group = EC_GROUP_new_by_curve_name(nid);
- if (group == NULL) {
- goto builtin_err;
- }
- if (!EC_KEY_set_group(eckey, group)) {
- goto builtin_err;
- }
- EC_GROUP_free(group);
- 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;
- continue;
- }
-
- BIO_printf(out, "%s: ", OBJ_nid2sn(nid));
- /* create key */
- if (!EC_KEY_generate_key(eckey)) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- /* create second key */
- wrong_eckey = EC_KEY_new();
- if (wrong_eckey == NULL) {
- goto builtin_err;
- }
- group = EC_GROUP_new_by_curve_name(nid);
- if (group == NULL) {
- goto builtin_err;
- }
- if (EC_KEY_set_group(wrong_eckey, group) == 0) {
- goto builtin_err;
- }
- EC_GROUP_free(group);
- if (!EC_KEY_generate_key(wrong_eckey)) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
-
- BIO_printf(out, ".");
- (void)BIO_flush(out);
- /* check key */
- if (!EC_KEY_check_key(eckey)) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- BIO_printf(out, ".");
- (void)BIO_flush(out);
- /* create signature */
- sig_len = ECDSA_size(eckey);
- signature = OPENSSL_malloc(sig_len);
- if (signature == NULL) {
- goto builtin_err;
- }
- if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- BIO_printf(out, ".");
- (void)BIO_flush(out);
- /* verify signature */
- if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- BIO_printf(out, ".");
- (void)BIO_flush(out);
- /* verify signature with the wrong key */
- if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- BIO_printf(out, ".");
- (void)BIO_flush(out);
- /* wrong digest */
- if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- BIO_printf(out, ".");
- (void)BIO_flush(out);
- /* wrong length */
- if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey) == 1) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- BIO_printf(out, ".");
- (void)BIO_flush(out);
-
- /* Modify a single byte of the signature: to ensure we don't
- * garble the ASN1 structure, we read the raw signature and
- * modify a byte in one of the bignums directly. */
- sig_ptr = signature;
- ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len);
- if (ecdsa_sig == NULL) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
-
- /* 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 = 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(2 * bn_len);
- if (raw_buf == NULL) {
- goto builtin_err;
- }
- /* Pad the bignums with leading zeroes. */
- 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;
- dirt = raw_buf[11] ? raw_buf[11] : 1;
- raw_buf[offset] ^= dirt;
- /* Now read the BIGNUMs back in from raw_buf. */
- if (BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL ||
- BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL) {
- goto builtin_err;
- }
-
- sig_ptr2 = signature;
- sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
- if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- /* Sanity check: undo the modification and verify signature. */
- raw_buf[offset] ^= dirt;
- if (BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL ||
- BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL) {
- goto builtin_err;
- }
-
- sig_ptr2 = signature;
- sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
- if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) {
- BIO_printf(out, " failed\n");
- goto builtin_err;
- }
- BIO_printf(out, ".");
- (void)BIO_flush(out);
-
- BIO_printf(out, " ok\n");
- /* cleanup */
- /* clean bogus errors */
- ERR_clear_error();
- OPENSSL_free(signature);
- signature = NULL;
- EC_KEY_free(eckey);
- eckey = NULL;
- EC_KEY_free(wrong_eckey);
- wrong_eckey = NULL;
- ECDSA_SIG_free(ecdsa_sig);
- ecdsa_sig = NULL;
- OPENSSL_free(raw_buf);
- raw_buf = NULL;
- }
-
- ret = 1;
-builtin_err:
- if (eckey) {
- EC_KEY_free(eckey);
- }
- if (order) {
- BN_free(order);
- }
- if (wrong_eckey) {
- EC_KEY_free(wrong_eckey);
- }
- if (ecdsa_sig) {
- ECDSA_SIG_free(ecdsa_sig);
- }
- if (signature) {
- OPENSSL_free(signature);
- }
- if (raw_buf) {
- OPENSSL_free(raw_buf);
- }
-
- return ret;
-}
-
-int main(void) {
- int ret = 1;
- BIO *out;
-
- CRYPTO_library_init();
- ERR_load_crypto_strings();
-
- out = BIO_new_fp(stdout, BIO_NOCLOSE);
-
- if (!test_builtin(out))
- goto err;
-
- ret = 0;
-
-err:
- if (ret)
- BIO_printf(out, "\nECDSA test failed\n");
- else
- BIO_printf(out, "\nPASS\n");
- if (ret)
- BIO_print_errors(out);
-
- if (out != NULL)
- BIO_free(out);
-
- return ret;
-}
diff --git a/src/crypto/ecdsa/ecdsa_test.cc b/src/crypto/ecdsa/ecdsa_test.cc
new file mode 100644
index 0000000..a6bd7a1
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa_test.cc
@@ -0,0 +1,340 @@
+/* ====================================================================
+ * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/ecdsa.h>
+
+#include <vector>
+
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+
+#include "../test/scoped_types.h"
+#include "../test/stl_compat.h"
+
+enum Api {
+ kEncodedApi,
+ kRawApi,
+};
+
+// VerifyECDSASig returns true on success, false on failure.
+static bool VerifyECDSASig(Api api, const uint8_t *digest,
+ size_t digest_len, const ECDSA_SIG *ecdsa_sig,
+ EC_KEY *eckey, int expected_result) {
+ int actual_result;
+
+ switch (api) {
+ case kEncodedApi: {
+ int sig_len = i2d_ECDSA_SIG(ecdsa_sig, NULL);
+ if (sig_len <= 0) {
+ return false;
+ }
+ std::vector<uint8_t> signature(static_cast<size_t>(sig_len));
+ uint8_t *sig_ptr = bssl::vector_data(&signature);
+ sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr);
+ if (sig_len <= 0) {
+ return false;
+ }
+ actual_result = ECDSA_verify(0, digest, digest_len, bssl::vector_data(&signature),
+ signature.size(), eckey);
+ break;
+ }
+
+ case kRawApi:
+ actual_result = ECDSA_do_verify(digest, digest_len, ecdsa_sig, eckey);
+ break;
+
+ default:
+ return false;
+ }
+ return expected_result == actual_result;
+}
+
+// TestTamperedSig verifies that signature verification fails when a valid
+// signature is tampered with. |ecdsa_sig| must be a valid signature, which will
+// be modified. TestTamperedSig returns true on success, false on failure.
+static bool TestTamperedSig(FILE *out, Api api, const uint8_t *digest,
+ size_t digest_len, ECDSA_SIG *ecdsa_sig,
+ EC_KEY *eckey, const BIGNUM *order) {
+ // Modify a single byte of the signature: to ensure we don't
+ // garble the ASN1 structure, we read the raw signature and
+ // modify a byte in one of the bignums directly.
+
+ // Store the two BIGNUMs in raw_buf.
+ size_t r_len = BN_num_bytes(ecdsa_sig->r);
+ size_t s_len = BN_num_bytes(ecdsa_sig->s);
+ size_t bn_len = BN_num_bytes(order);
+ if (r_len > bn_len || s_len > bn_len) {
+ return false;
+ }
+ size_t buf_len = 2 * bn_len;
+ std::vector<uint8_t> raw_buf(buf_len);
+ // Pad the bignums with leading zeroes.
+ if (!BN_bn2bin_padded(bssl::vector_data(&raw_buf), bn_len, ecdsa_sig->r) ||
+ !BN_bn2bin_padded(bssl::vector_data(&raw_buf) + bn_len, bn_len,
+ ecdsa_sig->s)) {
+ return false;
+ }
+
+ // Modify a single byte in the buffer.
+ size_t offset = raw_buf[10] % buf_len;
+ uint8_t dirt = raw_buf[11] ? raw_buf[11] : 1;
+ raw_buf[offset] ^= dirt;
+ // Now read the BIGNUMs back in from raw_buf.
+ if (BN_bin2bn(bssl::vector_data(&raw_buf), bn_len, ecdsa_sig->r) == NULL ||
+ BN_bin2bn(bssl::vector_data(&raw_buf) + bn_len, bn_len,
+ ecdsa_sig->s) == NULL ||
+ !VerifyECDSASig(api, digest, digest_len, ecdsa_sig, eckey, 0)) {
+ return false;
+ }
+
+ // Sanity check: Undo the modification and verify signature.
+ raw_buf[offset] ^= dirt;
+ if (BN_bin2bn(bssl::vector_data(&raw_buf), bn_len, ecdsa_sig->r) == NULL ||
+ BN_bin2bn(bssl::vector_data(&raw_buf) + bn_len, bn_len,
+ ecdsa_sig->s) == NULL ||
+ !VerifyECDSASig(api, digest, digest_len, ecdsa_sig, eckey, 1)) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestBuiltin(FILE *out) {
+ // Fill digest values with some random data.
+ uint8_t digest[20], wrong_digest[20];
+ if (!RAND_bytes(digest, 20) || !RAND_bytes(wrong_digest, 20)) {
+ fprintf(out, "ERROR: unable to get random data\n");
+ return false;
+ }
+
+ static const struct {
+ int nid;
+ const char *name;
+ } kCurves[] = {
+ { NID_secp224r1, "secp224r1" },
+ { NID_X9_62_prime256v1, "secp256r1" },
+ { NID_secp384r1, "secp384r1" },
+ { NID_secp521r1, "secp521r1" },
+ { NID_undef, NULL }
+ };
+
+ // Create and verify ECDSA signatures with every available curve.
+ fputs("\ntesting ECDSA_sign(), ECDSA_verify(), ECDSA_do_sign(), and "
+ "ECDSA_do_verify() with some internal curves:\n", out);
+
+ for (size_t n = 0; kCurves[n].nid != NID_undef; n++) {
+ fprintf(out, "%s: ", kCurves[n].name);
+
+ int nid = kCurves[n].nid;
+ ScopedEC_GROUP group(EC_GROUP_new_by_curve_name(nid));
+ if (!group) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ ScopedBIGNUM order(BN_new());
+ if (!order || !EC_GROUP_get_order(group.get(), order.get(), NULL)) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ if (BN_num_bits(order.get()) < 160) {
+ // Too small to test.
+ fprintf(out, " skipped\n");
+ continue;
+ }
+
+ // Create a new ECDSA key.
+ ScopedEC_KEY eckey(EC_KEY_new());
+ if (!eckey || !EC_KEY_set_group(eckey.get(), group.get()) ||
+ !EC_KEY_generate_key(eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ // Create a second key.
+ ScopedEC_KEY wrong_eckey(EC_KEY_new());
+ if (!wrong_eckey || !EC_KEY_set_group(wrong_eckey.get(), group.get()) ||
+ !EC_KEY_generate_key(wrong_eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+
+ fprintf(out, ".");
+ fflush(out);
+
+ // Check the key.
+ if (!EC_KEY_check_key(eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+
+ // Test ASN.1-encoded signatures.
+ // Create a signature.
+ unsigned sig_len = ECDSA_size(eckey.get());
+ std::vector<uint8_t> signature(sig_len);
+ if (!ECDSA_sign(0, digest, 20, bssl::vector_data(&signature), &sig_len,
+ eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ signature.resize(sig_len);
+ fprintf(out, ".");
+ fflush(out);
+ // Verify the signature.
+ if (!ECDSA_verify(0, digest, 20, bssl::vector_data(&signature),
+ signature.size(), eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+ // Verify the signature with the wrong key.
+ if (ECDSA_verify(0, digest, 20, bssl::vector_data(&signature),
+ signature.size(), wrong_eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+ // Verify the signature using the wrong digest.
+ if (ECDSA_verify(0, wrong_digest, 20, bssl::vector_data(&signature),
+ signature.size(), eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+ // Verify a truncated signature.
+ if (ECDSA_verify(0, digest, 20, bssl::vector_data(&signature),
+ signature.size() - 1, eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+ // Verify a tampered signature.
+ const uint8_t *sig_ptr = bssl::vector_data(&signature);
+ ScopedECDSA_SIG ecdsa_sig(d2i_ECDSA_SIG(NULL, &sig_ptr, signature.size()));
+ if (!ecdsa_sig ||
+ !TestTamperedSig(out, kEncodedApi, digest, 20, ecdsa_sig.get(),
+ eckey.get(), order.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+
+ // Test ECDSA_SIG signing and verification.
+ // Create a signature.
+ ecdsa_sig.reset(ECDSA_do_sign(digest, 20, eckey.get()));
+ if (!ecdsa_sig) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+ // Verify the signature using the correct key.
+ if (!ECDSA_do_verify(digest, 20, ecdsa_sig.get(), eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+ // Verify the signature with the wrong key.
+ if (ECDSA_do_verify(digest, 20, ecdsa_sig.get(), wrong_eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+ // Verify the signature using the wrong digest.
+ if (ECDSA_do_verify(wrong_digest, 20, ecdsa_sig.get(), eckey.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+ // Verify a tampered signature.
+ if (!TestTamperedSig(out, kRawApi, digest, 20, ecdsa_sig.get(), eckey.get(),
+ order.get())) {
+ fprintf(out, " failed\n");
+ return false;
+ }
+ fprintf(out, ".");
+ fflush(out);
+
+ fprintf(out, " ok\n");
+ // Clear bogus errors.
+ ERR_clear_error();
+ }
+
+ return true;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (!TestBuiltin(stdout)) {
+ printf("\nECDSA test failed\n");
+ ERR_print_errors_fp(stdout);
+ return 1;
+ }
+
+ printf("\nPASS\n");
+ return 0;
+}
diff --git a/src/crypto/engine/CMakeLists.txt b/src/crypto/engine/CMakeLists.txt
index cea6566..e03650e 100644
--- a/src/crypto/engine/CMakeLists.txt
+++ b/src/crypto/engine/CMakeLists.txt
@@ -6,5 +6,4 @@ add_library(
OBJECT
engine.c
- engine_error.c
)
diff --git a/src/crypto/engine/engine.c b/src/crypto/engine/engine.c
index 5b8cf1c..6c3300d 100644
--- a/src/crypto/engine/engine.c
+++ b/src/crypto/engine/engine.c
@@ -15,6 +15,7 @@
#include <openssl/engine.h>
#include <string.h>
+#include <assert.h>
#include <openssl/dh.h>
#include <openssl/dsa.h>
@@ -43,33 +44,23 @@ ENGINE *ENGINE_new(void) {
}
void ENGINE_free(ENGINE *engine) {
- if (engine->dh_method != NULL) {
- METHOD_unref(engine->dh_method);
- }
-
+ /* Methods are currently required to be static so are not unref'ed. */
OPENSSL_free(engine);
}
/* set_method takes a pointer to a method and its given size and sets
- * |*out_member| to point to a copy of it. The copy is |compiled_size| bytes
- * long and has zero padding if needed. */
+ * |*out_member| to point to it. This function might want to be extended in the
+ * future to support making a copy of the method so that a stable ABI for
+ * ENGINEs can be supported. But, for the moment, all *_METHODS must be
+ * static. */
static int set_method(void **out_member, const void *method, size_t method_size,
size_t compiled_size) {
- void *copy = OPENSSL_malloc(compiled_size);
- if (copy == NULL) {
+ const struct openssl_method_common_st *common = method;
+ if (method_size != compiled_size || !common->is_static) {
return 0;
}
- memset(copy, 0, compiled_size);
-
- if (method_size > compiled_size) {
- method_size = compiled_size;
- }
- memcpy(copy, method, method_size);
-
- METHOD_unref(*out_member);
- *out_member = copy;
-
+ *out_member = (void*) method;
return 1;
}
@@ -114,25 +105,16 @@ ECDSA_METHOD *ENGINE_get_ECDSA_method(const ENGINE *engine) {
}
void METHOD_ref(void *method_in) {
- struct openssl_method_common_st *method = method_in;
-
- if (method->is_static) {
- return;
- }
-
- CRYPTO_add(&method->references, 1, CRYPTO_LOCK_ENGINE);
+ assert(((struct openssl_method_common_st*) method_in)->is_static);
}
void METHOD_unref(void *method_in) {
struct openssl_method_common_st *method = method_in;
- if (method == NULL || method->is_static) {
+ if (method == NULL) {
return;
}
-
- if (CRYPTO_add(&method->references, -1, CRYPTO_LOCK_ENGINE) == 0) {
- OPENSSL_free(method);
- }
+ assert(method->is_static);
}
OPENSSL_DECLARE_ERROR_REASON(ENGINE, OPERATION_NOT_SUPPORTED);
diff --git a/src/crypto/engine/engine_error.c b/src/crypto/engine/engine_error.c
deleted file mode 100644
index 9f65f70..0000000
--- a/src/crypto/engine/engine_error.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* 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/engine.h>
-
-const ERR_STRING_DATA ENGINE_error_string_data[] = {
- {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_OPERATION_NOT_SUPPORTED), "OPERATION_NOT_SUPPORTED"},
- {0, NULL},
-};
diff --git a/src/crypto/err/CMakeLists.txt b/src/crypto/err/CMakeLists.txt
index 53dccea..89f96bd 100644
--- a/src/crypto/err/CMakeLists.txt
+++ b/src/crypto/err/CMakeLists.txt
@@ -1,18 +1,49 @@
include_directories(. .. ../../include)
+add_custom_command(
+ OUTPUT err_data.c
+ COMMAND ${GO_EXECUTABLE} run err_data_generate.go > ${CMAKE_CURRENT_BINARY_DIR}/err_data.c
+ DEPENDS
+ err_data_generate.go
+ asn1.errordata
+ bio.errordata
+ bn.errordata
+ buf.errordata
+ cipher.errordata
+ conf.errordata
+ crypto.errordata
+ dh.errordata
+ digest.errordata
+ dsa.errordata
+ ecdh.errordata
+ ecdsa.errordata
+ ec.errordata
+ engine.errordata
+ evp.errordata
+ hkdf.errordata
+ obj.errordata
+ pem.errordata
+ pkcs8.errordata
+ rsa.errordata
+ ssl.errordata
+ x509.errordata
+ x509v3.errordata
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
add_library(
err
OBJECT
err.c
- err_impl.c
+ err_data.c
)
add_executable(
err_test
- err_test.c
+ err_test.cc
)
target_link_libraries(err_test crypto)
diff --git a/src/crypto/err/asn1.errordata b/src/crypto/err/asn1.errordata
new file mode 100644
index 0000000..44b9c73
--- /dev/null
+++ b/src/crypto/err/asn1.errordata
@@ -0,0 +1,152 @@
+ASN1,function,100,ASN1_BIT_STRING_set_bit
+ASN1,function,101,ASN1_ENUMERATED_set
+ASN1,function,102,ASN1_ENUMERATED_to_BN
+ASN1,function,103,ASN1_GENERALIZEDTIME_adj
+ASN1,function,104,ASN1_INTEGER_set
+ASN1,function,105,ASN1_INTEGER_to_BN
+ASN1,function,106,ASN1_OBJECT_new
+ASN1,function,107,ASN1_PCTX_new
+ASN1,function,108,ASN1_STRING_TABLE_add
+ASN1,function,109,ASN1_STRING_set
+ASN1,function,110,ASN1_STRING_type_new
+ASN1,function,111,ASN1_TIME_adj
+ASN1,function,112,ASN1_UTCTIME_adj
+ASN1,function,113,ASN1_d2i_fp
+ASN1,function,114,ASN1_dup
+ASN1,function,115,ASN1_generate_v3
+ASN1,function,116,ASN1_get_object
+ASN1,function,117,ASN1_i2d_bio
+ASN1,function,118,ASN1_i2d_fp
+ASN1,function,119,ASN1_item_d2i_fp
+ASN1,function,120,ASN1_item_dup
+ASN1,function,121,ASN1_item_ex_d2i
+ASN1,function,122,ASN1_item_i2d_bio
+ASN1,function,123,ASN1_item_i2d_fp
+ASN1,function,124,ASN1_item_pack
+ASN1,function,125,ASN1_item_unpack
+ASN1,function,126,ASN1_mbstring_ncopy
+ASN1,function,127,ASN1_template_new
+ASN1,function,128,BIO_new_NDEF
+ASN1,function,129,BN_to_ASN1_ENUMERATED
+ASN1,function,130,BN_to_ASN1_INTEGER
+ASN1,function,131,a2d_ASN1_OBJECT
+ASN1,function,132,a2i_ASN1_ENUMERATED
+ASN1,function,133,a2i_ASN1_INTEGER
+ASN1,function,134,a2i_ASN1_STRING
+ASN1,function,135,append_exp
+ASN1,function,136,asn1_cb
+ASN1,function,137,asn1_check_tlen
+ASN1,function,138,asn1_collate_primitive
+ASN1,function,139,asn1_collect
+ASN1,function,140,asn1_d2i_ex_primitive
+ASN1,function,141,asn1_d2i_read_bio
+ASN1,function,142,asn1_do_adb
+ASN1,function,143,asn1_ex_c2i
+ASN1,function,144,asn1_find_end
+ASN1,function,145,asn1_item_ex_combine_new
+ASN1,function,146,asn1_str2type
+ASN1,function,147,asn1_template_ex_d2i
+ASN1,function,148,asn1_template_noexp_d2i
+ASN1,function,149,bitstr_cb
+ASN1,function,150,c2i_ASN1_BIT_STRING
+ASN1,function,151,c2i_ASN1_INTEGER
+ASN1,function,152,c2i_ASN1_OBJECT
+ASN1,function,153,collect_data
+ASN1,function,154,d2i_ASN1_BOOLEAN
+ASN1,function,155,d2i_ASN1_OBJECT
+ASN1,function,156,d2i_ASN1_UINTEGER
+ASN1,function,157,d2i_ASN1_UTCTIME
+ASN1,function,158,d2i_ASN1_bytes
+ASN1,function,159,d2i_ASN1_type_bytes
+ASN1,function,160,i2d_ASN1_TIME
+ASN1,function,161,i2d_PrivateKey
+ASN1,function,162,long_c2i
+ASN1,function,163,parse_tagging
+ASN1,reason,100,ASN1_LENGTH_MISMATCH
+ASN1,reason,101,AUX_ERROR
+ASN1,reason,102,BAD_GET_ASN1_OBJECT_CALL
+ASN1,reason,103,BAD_OBJECT_HEADER
+ASN1,reason,104,BMPSTRING_IS_WRONG_LENGTH
+ASN1,reason,105,BN_LIB
+ASN1,reason,106,BOOLEAN_IS_WRONG_LENGTH
+ASN1,reason,107,BUFFER_TOO_SMALL
+ASN1,reason,108,DECODE_ERROR
+ASN1,reason,109,DEPTH_EXCEEDED
+ASN1,reason,110,ENCODE_ERROR
+ASN1,reason,111,ERROR_GETTING_TIME
+ASN1,reason,112,EXPECTING_AN_ASN1_SEQUENCE
+ASN1,reason,113,EXPECTING_AN_INTEGER
+ASN1,reason,114,EXPECTING_AN_OBJECT
+ASN1,reason,115,EXPECTING_A_BOOLEAN
+ASN1,reason,116,EXPECTING_A_TIME
+ASN1,reason,117,EXPLICIT_LENGTH_MISMATCH
+ASN1,reason,118,EXPLICIT_TAG_NOT_CONSTRUCTED
+ASN1,reason,119,FIELD_MISSING
+ASN1,reason,120,FIRST_NUM_TOO_LARGE
+ASN1,reason,121,HEADER_TOO_LONG
+ASN1,reason,122,ILLEGAL_BITSTRING_FORMAT
+ASN1,reason,123,ILLEGAL_BOOLEAN
+ASN1,reason,124,ILLEGAL_CHARACTERS
+ASN1,reason,125,ILLEGAL_FORMAT
+ASN1,reason,126,ILLEGAL_HEX
+ASN1,reason,127,ILLEGAL_IMPLICIT_TAG
+ASN1,reason,128,ILLEGAL_INTEGER
+ASN1,reason,129,ILLEGAL_NESTED_TAGGING
+ASN1,reason,130,ILLEGAL_NULL
+ASN1,reason,131,ILLEGAL_NULL_VALUE
+ASN1,reason,132,ILLEGAL_OBJECT
+ASN1,reason,133,ILLEGAL_OPTIONAL_ANY
+ASN1,reason,134,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE
+ASN1,reason,135,ILLEGAL_TAGGED_ANY
+ASN1,reason,136,ILLEGAL_TIME_VALUE
+ASN1,reason,137,INTEGER_NOT_ASCII_FORMAT
+ASN1,reason,138,INTEGER_TOO_LARGE_FOR_LONG
+ASN1,reason,139,INVALID_BIT_STRING_BITS_LEFT
+ASN1,reason,140,INVALID_BMPSTRING_LENGTH
+ASN1,reason,141,INVALID_DIGIT
+ASN1,reason,142,INVALID_MODIFIER
+ASN1,reason,143,INVALID_NUMBER
+ASN1,reason,144,INVALID_OBJECT_ENCODING
+ASN1,reason,145,INVALID_SEPARATOR
+ASN1,reason,146,INVALID_TIME_FORMAT
+ASN1,reason,147,INVALID_UNIVERSALSTRING_LENGTH
+ASN1,reason,148,INVALID_UTF8STRING
+ASN1,reason,149,LIST_ERROR
+ASN1,reason,150,MALLOC_FAILURE
+ASN1,reason,151,MISSING_ASN1_EOS
+ASN1,reason,152,MISSING_EOC
+ASN1,reason,153,MISSING_SECOND_NUMBER
+ASN1,reason,154,MISSING_VALUE
+ASN1,reason,155,MSTRING_NOT_UNIVERSAL
+ASN1,reason,156,MSTRING_WRONG_TAG
+ASN1,reason,157,NESTED_ASN1_ERROR
+ASN1,reason,158,NESTED_ASN1_STRING
+ASN1,reason,159,NON_HEX_CHARACTERS
+ASN1,reason,160,NOT_ASCII_FORMAT
+ASN1,reason,161,NOT_ENOUGH_DATA
+ASN1,reason,162,NO_MATCHING_CHOICE_TYPE
+ASN1,reason,163,NULL_IS_WRONG_LENGTH
+ASN1,reason,164,OBJECT_NOT_ASCII_FORMAT
+ASN1,reason,165,ODD_NUMBER_OF_CHARS
+ASN1,reason,166,SECOND_NUMBER_TOO_LARGE
+ASN1,reason,167,SEQUENCE_LENGTH_MISMATCH
+ASN1,reason,168,SEQUENCE_NOT_CONSTRUCTED
+ASN1,reason,169,SEQUENCE_OR_SET_NEEDS_CONFIG
+ASN1,reason,170,SHORT_LINE
+ASN1,reason,171,STREAMING_NOT_SUPPORTED
+ASN1,reason,172,STRING_TOO_LONG
+ASN1,reason,173,STRING_TOO_SHORT
+ASN1,reason,174,TAG_VALUE_TOO_HIGH
+ASN1,reason,175,TIME_NOT_ASCII_FORMAT
+ASN1,reason,176,TOO_LONG
+ASN1,reason,177,TYPE_NOT_CONSTRUCTED
+ASN1,reason,178,TYPE_NOT_PRIMITIVE
+ASN1,reason,179,UNEXPECTED_EOC
+ASN1,reason,180,UNIVERSALSTRING_IS_WRONG_LENGTH
+ASN1,reason,181,UNKNOWN_FORMAT
+ASN1,reason,182,UNKNOWN_TAG
+ASN1,reason,183,UNSUPPORTED_ANY_DEFINED_BY_TYPE
+ASN1,reason,184,UNSUPPORTED_PUBLIC_KEY_TYPE
+ASN1,reason,185,UNSUPPORTED_TYPE
+ASN1,reason,186,WRONG_TAG
+ASN1,reason,187,WRONG_TYPE
diff --git a/src/crypto/err/bio.errordata b/src/crypto/err/bio.errordata
new file mode 100644
index 0000000..cd7286a
--- /dev/null
+++ b/src/crypto/err/bio.errordata
@@ -0,0 +1,35 @@
+BIO,function,100,BIO_callback_ctrl
+BIO,function,101,BIO_ctrl
+BIO,function,102,BIO_new
+BIO,function,103,BIO_new_file
+BIO,function,104,BIO_new_mem_buf
+BIO,function,105,BIO_zero_copy_get_read_buf
+BIO,function,106,BIO_zero_copy_get_read_buf_done
+BIO,function,107,BIO_zero_copy_get_write_buf
+BIO,function,108,BIO_zero_copy_get_write_buf_done
+BIO,function,109,bio_io
+BIO,function,110,bio_make_pair
+BIO,function,111,bio_write
+BIO,function,112,buffer_ctrl
+BIO,function,113,conn_ctrl
+BIO,function,114,conn_state
+BIO,function,115,file_ctrl
+BIO,function,116,file_read
+BIO,function,117,mem_write
+BIO,reason,100,BAD_FOPEN_MODE
+BIO,reason,101,BROKEN_PIPE
+BIO,reason,102,CONNECT_ERROR
+BIO,reason,103,ERROR_SETTING_NBIO
+BIO,reason,104,INVALID_ARGUMENT
+BIO,reason,105,IN_USE
+BIO,reason,106,KEEPALIVE
+BIO,reason,107,NBIO_CONNECT_ERROR
+BIO,reason,108,NO_HOSTNAME_SPECIFIED
+BIO,reason,109,NO_PORT_SPECIFIED
+BIO,reason,110,NO_SUCH_FILE
+BIO,reason,111,NULL_PARAMETER
+BIO,reason,112,SYS_LIB
+BIO,reason,113,UNABLE_TO_CREATE_SOCKET
+BIO,reason,114,UNINITIALIZED
+BIO,reason,115,UNSUPPORTED_METHOD
+BIO,reason,116,WRITE_TO_READ_ONLY_BIO
diff --git a/src/crypto/err/bn.errordata b/src/crypto/err/bn.errordata
new file mode 100644
index 0000000..ab74073
--- /dev/null
+++ b/src/crypto/err/bn.errordata
@@ -0,0 +1,42 @@
+BN,function,100,BN_CTX_get
+BN,function,101,BN_CTX_new
+BN,function,102,BN_CTX_start
+BN,function,103,BN_bn2dec
+BN,function,104,BN_bn2hex
+BN,function,105,BN_div
+BN,function,106,BN_div_recp
+BN,function,107,BN_exp
+BN,function,108,BN_generate_dsa_nonce
+BN,function,109,BN_generate_prime_ex
+BN,function,110,BN_mod_exp2_mont
+BN,function,111,BN_mod_exp_mont
+BN,function,112,BN_mod_exp_mont_consttime
+BN,function,113,BN_mod_exp_mont_word
+BN,function,114,BN_mod_inverse
+BN,function,115,BN_mod_inverse_no_branch
+BN,function,116,BN_mod_lshift_quick
+BN,function,117,BN_mod_sqrt
+BN,function,118,BN_new
+BN,function,119,BN_rand
+BN,function,120,BN_rand_range
+BN,function,121,BN_sqrt
+BN,function,122,BN_usub
+BN,function,123,bn_wexpand
+BN,function,124,mod_exp_recp
+BN,reason,100,ARG2_LT_ARG3
+BN,reason,101,BAD_RECIPROCAL
+BN,reason,102,BIGNUM_TOO_LONG
+BN,reason,103,BITS_TOO_SMALL
+BN,reason,104,CALLED_WITH_EVEN_MODULUS
+BN,reason,105,DIV_BY_ZERO
+BN,reason,106,EXPAND_ON_STATIC_BIGNUM_DATA
+BN,reason,107,INPUT_NOT_REDUCED
+BN,reason,108,INVALID_RANGE
+BN,reason,109,NEGATIVE_NUMBER
+BN,reason,110,NOT_A_SQUARE
+BN,reason,111,NOT_INITIALIZED
+BN,reason,112,NO_INVERSE
+BN,reason,113,PRIVATE_KEY_TOO_LARGE
+BN,reason,114,P_IS_NOT_PRIME
+BN,reason,115,TOO_MANY_ITERATIONS
+BN,reason,116,TOO_MANY_TEMPORARY_VARIABLES
diff --git a/src/crypto/err/buf.errordata b/src/crypto/err/buf.errordata
new file mode 100644
index 0000000..01b6c9a
--- /dev/null
+++ b/src/crypto/err/buf.errordata
@@ -0,0 +1,4 @@
+BUF,function,100,BUF_MEM_new
+BUF,function,101,BUF_memdup
+BUF,function,102,BUF_strndup
+BUF,function,103,buf_mem_grow
diff --git a/src/crypto/err/cipher.errordata b/src/crypto/err/cipher.errordata
new file mode 100644
index 0000000..ce8459b
--- /dev/null
+++ b/src/crypto/err/cipher.errordata
@@ -0,0 +1,60 @@
+CIPHER,function,100,EVP_AEAD_CTX_init
+CIPHER,function,131,EVP_AEAD_CTX_init_with_direction
+CIPHER,function,101,EVP_AEAD_CTX_open
+CIPHER,function,102,EVP_AEAD_CTX_seal
+CIPHER,function,103,EVP_CIPHER_CTX_copy
+CIPHER,function,104,EVP_CIPHER_CTX_ctrl
+CIPHER,function,105,EVP_CIPHER_CTX_set_key_length
+CIPHER,function,106,EVP_CipherInit_ex
+CIPHER,function,107,EVP_DecryptFinal_ex
+CIPHER,function,108,EVP_EncryptFinal_ex
+CIPHER,function,132,aead_aes_ctr_hmac_sha256_init
+CIPHER,function,133,aead_aes_ctr_hmac_sha256_open
+CIPHER,function,134,aead_aes_ctr_hmac_sha256_seal
+CIPHER,function,109,aead_aes_gcm_init
+CIPHER,function,110,aead_aes_gcm_open
+CIPHER,function,111,aead_aes_gcm_seal
+CIPHER,function,112,aead_aes_key_wrap_init
+CIPHER,function,113,aead_aes_key_wrap_open
+CIPHER,function,114,aead_aes_key_wrap_seal
+CIPHER,function,115,aead_chacha20_poly1305_init
+CIPHER,function,116,aead_chacha20_poly1305_open
+CIPHER,function,117,aead_chacha20_poly1305_seal
+CIPHER,function,118,aead_rc4_md5_tls_init
+CIPHER,function,119,aead_rc4_md5_tls_open
+CIPHER,function,120,aead_rc4_md5_tls_seal
+CIPHER,function,121,aead_ssl3_ensure_cipher_init
+CIPHER,function,122,aead_ssl3_init
+CIPHER,function,123,aead_ssl3_open
+CIPHER,function,124,aead_ssl3_seal
+CIPHER,function,125,aead_tls_ensure_cipher_init
+CIPHER,function,126,aead_tls_init
+CIPHER,function,127,aead_tls_open
+CIPHER,function,128,aead_tls_seal
+CIPHER,function,129,aes_init_key
+CIPHER,function,130,aesni_init_key
+CIPHER,reason,100,AES_KEY_SETUP_FAILED
+CIPHER,reason,101,BAD_DECRYPT
+CIPHER,reason,102,BAD_KEY_LENGTH
+CIPHER,reason,103,BUFFER_TOO_SMALL
+CIPHER,reason,104,CTRL_NOT_IMPLEMENTED
+CIPHER,reason,105,CTRL_OPERATION_NOT_IMPLEMENTED
+CIPHER,reason,106,DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
+CIPHER,reason,107,INITIALIZATION_ERROR
+CIPHER,reason,108,INPUT_NOT_INITIALIZED
+CIPHER,reason,109,INVALID_AD_SIZE
+CIPHER,reason,110,INVALID_KEY_LENGTH
+CIPHER,reason,111,INVALID_NONCE_SIZE
+CIPHER,reason,112,INVALID_OPERATION
+CIPHER,reason,113,IV_TOO_LARGE
+CIPHER,reason,114,NO_CIPHER_SET
+CIPHER,reason,124,NO_DIRECTION_SET
+CIPHER,reason,115,OUTPUT_ALIASES_INPUT
+CIPHER,reason,116,TAG_TOO_LARGE
+CIPHER,reason,117,TOO_LARGE
+CIPHER,reason,118,UNSUPPORTED_AD_SIZE
+CIPHER,reason,119,UNSUPPORTED_INPUT_SIZE
+CIPHER,reason,120,UNSUPPORTED_KEY_SIZE
+CIPHER,reason,121,UNSUPPORTED_NONCE_SIZE
+CIPHER,reason,122,UNSUPPORTED_TAG_SIZE
+CIPHER,reason,123,WRONG_FINAL_BLOCK_LENGTH
diff --git a/src/crypto/err/conf.errordata b/src/crypto/err/conf.errordata
new file mode 100644
index 0000000..0b96a32
--- /dev/null
+++ b/src/crypto/err/conf.errordata
@@ -0,0 +1,10 @@
+CONF,function,100,CONF_parse_list
+CONF,function,101,NCONF_load
+CONF,function,102,def_load_bio
+CONF,function,103,str_copy
+CONF,reason,100,LIST_CANNOT_BE_NULL
+CONF,reason,101,MISSING_CLOSE_SQUARE_BRACKET
+CONF,reason,102,MISSING_EQUAL_SIGN
+CONF,reason,103,NO_CLOSE_BRACE
+CONF,reason,104,UNABLE_TO_CREATE_NEW_SECTION
+CONF,reason,105,VARIABLE_HAS_NO_VALUE
diff --git a/src/crypto/err/crypto.errordata b/src/crypto/err/crypto.errordata
new file mode 100644
index 0000000..1e0e9d5
--- /dev/null
+++ b/src/crypto/err/crypto.errordata
@@ -0,0 +1,4 @@
+CRYPTO,function,100,CRYPTO_get_ex_new_index
+CRYPTO,function,101,CRYPTO_set_ex_data
+CRYPTO,function,102,get_class
+CRYPTO,function,103,get_func_pointers
diff --git a/src/crypto/err/dh.errordata b/src/crypto/err/dh.errordata
new file mode 100644
index 0000000..1fd675b
--- /dev/null
+++ b/src/crypto/err/dh.errordata
@@ -0,0 +1,8 @@
+DH,function,100,DH_new_method
+DH,function,101,compute_key
+DH,function,102,generate_key
+DH,function,103,generate_parameters
+DH,reason,100,BAD_GENERATOR
+DH,reason,101,INVALID_PUBKEY
+DH,reason,102,MODULUS_TOO_LARGE
+DH,reason,103,NO_PRIVATE_VALUE
diff --git a/src/crypto/err/digest.errordata b/src/crypto/err/digest.errordata
new file mode 100644
index 0000000..95a3622
--- /dev/null
+++ b/src/crypto/err/digest.errordata
@@ -0,0 +1,3 @@
+DIGEST,function,100,EVP_DigestInit_ex
+DIGEST,function,101,EVP_MD_CTX_copy_ex
+DIGEST,reason,100,INPUT_NOT_INITIALIZED
diff --git a/src/crypto/err/dsa.errordata b/src/crypto/err/dsa.errordata
new file mode 100644
index 0000000..c2dff23
--- /dev/null
+++ b/src/crypto/err/dsa.errordata
@@ -0,0 +1,9 @@
+DSA,function,100,DSA_new_method
+DSA,function,101,dsa_sig_cb
+DSA,function,102,sign
+DSA,function,103,sign_setup
+DSA,function,104,verify
+DSA,reason,100,BAD_Q_VALUE
+DSA,reason,101,MISSING_PARAMETERS
+DSA,reason,102,MODULUS_TOO_LARGE
+DSA,reason,103,NEED_NEW_SETUP_VALUES
diff --git a/src/crypto/err/ec.errordata b/src/crypto/err/ec.errordata
new file mode 100644
index 0000000..3b815c8
--- /dev/null
+++ b/src/crypto/err/ec.errordata
@@ -0,0 +1,93 @@
+EC,function,159,BN_to_felem
+EC,function,100,EC_GROUP_copy
+EC,function,101,EC_GROUP_get_curve_GFp
+EC,function,102,EC_GROUP_get_degree
+EC,function,103,EC_GROUP_new_by_curve_name
+EC,function,104,EC_KEY_check_key
+EC,function,105,EC_KEY_copy
+EC,function,106,EC_KEY_generate_key
+EC,function,107,EC_KEY_new_method
+EC,function,108,EC_KEY_set_public_key_affine_coordinates
+EC,function,109,EC_POINT_add
+EC,function,110,EC_POINT_cmp
+EC,function,111,EC_POINT_copy
+EC,function,112,EC_POINT_dbl
+EC,function,113,EC_POINT_dup
+EC,function,114,EC_POINT_get_affine_coordinates_GFp
+EC,function,115,EC_POINT_invert
+EC,function,116,EC_POINT_is_at_infinity
+EC,function,117,EC_POINT_is_on_curve
+EC,function,118,EC_POINT_make_affine
+EC,function,119,EC_POINT_new
+EC,function,120,EC_POINT_oct2point
+EC,function,121,EC_POINT_point2oct
+EC,function,122,EC_POINT_set_affine_coordinates_GFp
+EC,function,123,EC_POINT_set_compressed_coordinates_GFp
+EC,function,124,EC_POINT_set_to_infinity
+EC,function,125,EC_POINTs_make_affine
+EC,function,126,compute_wNAF
+EC,function,127,d2i_ECPKParameters
+EC,function,128,d2i_ECParameters
+EC,function,129,d2i_ECPrivateKey
+EC,function,130,ec_GFp_mont_field_decode
+EC,function,131,ec_GFp_mont_field_encode
+EC,function,132,ec_GFp_mont_field_mul
+EC,function,133,ec_GFp_mont_field_set_to_one
+EC,function,134,ec_GFp_mont_field_sqr
+EC,function,135,ec_GFp_mont_group_set_curve
+EC,function,160,ec_GFp_nistp256_group_set_curve
+EC,function,161,ec_GFp_nistp256_point_get_affine_coordinates
+EC,function,162,ec_GFp_nistp256_points_mul
+EC,function,136,ec_GFp_simple_group_check_discriminant
+EC,function,137,ec_GFp_simple_group_set_curve
+EC,function,138,ec_GFp_simple_make_affine
+EC,function,139,ec_GFp_simple_oct2point
+EC,function,140,ec_GFp_simple_point2oct
+EC,function,141,ec_GFp_simple_point_get_affine_coordinates
+EC,function,142,ec_GFp_simple_point_set_affine_coordinates
+EC,function,143,ec_GFp_simple_points_make_affine
+EC,function,144,ec_GFp_simple_set_compressed_coordinates
+EC,function,145,ec_asn1_group2pkparameters
+EC,function,146,ec_asn1_pkparameters2group
+EC,function,163,ec_group_copy
+EC,function,147,ec_group_new
+EC,function,148,ec_group_new_curve_GFp
+EC,function,149,ec_group_new_from_data
+EC,function,150,ec_point_set_Jprojective_coordinates_GFp
+EC,function,151,ec_pre_comp_new
+EC,function,152,ec_wNAF_mul
+EC,function,153,ec_wNAF_precompute_mult
+EC,function,154,i2d_ECPKParameters
+EC,function,155,i2d_ECParameters
+EC,function,156,i2d_ECPrivateKey
+EC,function,157,i2o_ECPublicKey
+EC,function,164,nistp256_pre_comp_new
+EC,function,158,o2i_ECPublicKey
+EC,reason,126,BIGNUM_OUT_OF_RANGE
+EC,reason,100,BUFFER_TOO_SMALL
+EC,reason,101,COORDINATES_OUT_OF_RANGE
+EC,reason,102,D2I_ECPKPARAMETERS_FAILURE
+EC,reason,103,EC_GROUP_NEW_BY_NAME_FAILURE
+EC,reason,104,GROUP2PKPARAMETERS_FAILURE
+EC,reason,105,I2D_ECPKPARAMETERS_FAILURE
+EC,reason,106,INCOMPATIBLE_OBJECTS
+EC,reason,107,INVALID_COMPRESSED_POINT
+EC,reason,108,INVALID_COMPRESSION_BIT
+EC,reason,109,INVALID_ENCODING
+EC,reason,110,INVALID_FIELD
+EC,reason,111,INVALID_FORM
+EC,reason,112,INVALID_GROUP_ORDER
+EC,reason,113,INVALID_PRIVATE_KEY
+EC,reason,114,MISSING_PARAMETERS
+EC,reason,115,MISSING_PRIVATE_KEY
+EC,reason,116,NON_NAMED_CURVE
+EC,reason,117,NOT_INITIALIZED
+EC,reason,118,PKPARAMETERS2GROUP_FAILURE
+EC,reason,119,POINT_AT_INFINITY
+EC,reason,120,POINT_IS_NOT_ON_CURVE
+EC,reason,121,SLOT_FULL
+EC,reason,122,UNDEFINED_GENERATOR
+EC,reason,123,UNKNOWN_GROUP
+EC,reason,124,UNKNOWN_ORDER
+EC,reason,127,WRONG_CURVE_PARAMETERS
+EC,reason,125,WRONG_ORDER
diff --git a/src/crypto/err/ecdh.errordata b/src/crypto/err/ecdh.errordata
new file mode 100644
index 0000000..0f1215e
--- /dev/null
+++ b/src/crypto/err/ecdh.errordata
@@ -0,0 +1,4 @@
+ECDH,function,100,ECDH_compute_key
+ECDH,reason,100,KDF_FAILED
+ECDH,reason,101,NO_PRIVATE_VALUE
+ECDH,reason,102,POINT_ARITHMETIC_FAILURE
diff --git a/src/crypto/err/ecdsa.errordata b/src/crypto/err/ecdsa.errordata
new file mode 100644
index 0000000..97c213e
--- /dev/null
+++ b/src/crypto/err/ecdsa.errordata
@@ -0,0 +1,10 @@
+ECDSA,function,100,ECDSA_do_sign_ex
+ECDSA,function,101,ECDSA_do_verify
+ECDSA,function,102,ECDSA_sign_ex
+ECDSA,function,103,digest_to_bn
+ECDSA,function,104,ecdsa_sign_setup
+ECDSA,reason,100,BAD_SIGNATURE
+ECDSA,reason,101,MISSING_PARAMETERS
+ECDSA,reason,102,NEED_NEW_SETUP_VALUES
+ECDSA,reason,103,NOT_IMPLEMENTED
+ECDSA,reason,104,RANDOM_NUMBER_GENERATION_FAILED
diff --git a/src/crypto/err/engine.errordata b/src/crypto/err/engine.errordata
new file mode 100644
index 0000000..1185e88
--- /dev/null
+++ b/src/crypto/err/engine.errordata
@@ -0,0 +1 @@
+ENGINE,reason,100,OPERATION_NOT_SUPPORTED
diff --git a/src/crypto/err/err.c b/src/crypto/err/err.c
index 55b1363..b879a22 100644
--- a/src/crypto/err/err.c
+++ b/src/crypto/err/err.c
@@ -111,8 +111,6 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
#include <string.h>
#if defined(OPENSSL_WINDOWS)
@@ -121,37 +119,23 @@
#pragma warning(pop)
#endif
-#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/thread.h>
+#include "../internal.h"
-/* err_fns contains a pointer to the current error implementation. */
-static const struct ERR_FNS_st *err_fns = NULL;
-extern const struct ERR_FNS_st openssl_err_default_impl;
-#define ERRFN(a) err_fns->a
+extern const uint32_t kOpenSSLFunctionValues[];
+extern const size_t kOpenSSLFunctionValuesLen;
+extern const char kOpenSSLFunctionStringData[];
-/* err_fns_check is an internal function that checks whether "err_fns" is set
- * and if not, sets it to the default. */
-static void err_fns_check(void) {
- /* In practice, this is not a race problem because loading the error strings
- * at init time will cause this pointer to be set before the process goes
- * multithreaded. */
- if (err_fns) {
- return;
- }
-
- CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- if (!err_fns) {
- err_fns = &openssl_err_default_impl;
- }
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-}
+extern const uint32_t kOpenSSLReasonValues[];
+extern const size_t kOpenSSLReasonValuesLen;
+extern const char kOpenSSLReasonStringData[];
/* err_clear_data frees the optional |data| member of the given error. */
static void err_clear_data(struct err_error_st *error) {
- if (error->data != NULL && (error->flags & ERR_FLAG_MALLOCED) != 0) {
+ if ((error->flags & ERR_FLAG_MALLOCED) != 0) {
OPENSSL_free(error->data);
}
error->data = NULL;
@@ -164,10 +148,45 @@ static void err_clear(struct err_error_st *error) {
memset(error, 0, sizeof(struct err_error_st));
}
+/* global_next_library contains the next custom library value to return. */
+static int global_next_library = ERR_NUM_LIBS;
+
+/* global_next_library_mutex protects |global_next_library| from concurrent
+ * updates. */
+static struct CRYPTO_STATIC_MUTEX global_next_library_mutex =
+ CRYPTO_STATIC_MUTEX_INIT;
+
+static void err_state_free(void *statep) {
+ ERR_STATE *state = statep;
+
+ if (state == NULL) {
+ return;
+ }
+
+ unsigned i;
+ for (i = 0; i < ERR_NUM_ERRORS; i++) {
+ err_clear(&state->errors[i]);
+ }
+ OPENSSL_free(state->to_free);
+ OPENSSL_free(state);
+}
+
/* err_get_state gets the ERR_STATE object for the current thread. */
static ERR_STATE *err_get_state(void) {
- err_fns_check();
- return ERRFN(get_state)();
+ ERR_STATE *state = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_ERR);
+ if (state == NULL) {
+ state = OPENSSL_malloc(sizeof(ERR_STATE));
+ if (state == NULL) {
+ return NULL;
+ }
+ memset(state, 0, sizeof(ERR_STATE));
+ if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_ERR, state,
+ err_state_free)) {
+ return NULL;
+ }
+ }
+
+ return state;
}
static uint32_t get_error_values(int inc, int top, const char **file, int *line,
@@ -221,9 +240,7 @@ static uint32_t get_error_values(int inc, int top, const char **file, int *line,
* error queue. */
if (inc) {
if (error->flags & ERR_FLAG_MALLOCED) {
- if (state->to_free) {
- OPENSSL_free(state->to_free);
- }
+ OPENSSL_free(state->to_free);
state->to_free = error->data;
}
error->data = NULL;
@@ -291,47 +308,29 @@ void ERR_clear_error(void) {
for (i = 0; i < ERR_NUM_ERRORS; i++) {
err_clear(&state->errors[i]);
}
- if (state->to_free) {
- OPENSSL_free(state->to_free);
- state->to_free = NULL;
- }
+ OPENSSL_free(state->to_free);
+ state->to_free = NULL;
state->top = state->bottom = 0;
}
-static void err_state_free(ERR_STATE *state) {
- unsigned i;
-
- for (i = 0; i < ERR_NUM_ERRORS; i++) {
- err_clear(&state->errors[i]);
- }
- if (state->to_free) {
- OPENSSL_free(state->to_free);
- }
- OPENSSL_free(state);
-}
-
void ERR_remove_thread_state(const CRYPTO_THREADID *tid) {
- CRYPTO_THREADID current;
- ERR_STATE *state;
-
- if (tid == NULL) {
- CRYPTO_THREADID_current(&current);
- tid = &current;
- }
-
- err_fns_check();
- state = ERRFN(release_state)(tid);
- if (state == NULL) {
+ if (tid != NULL) {
+ assert(0);
return;
}
- err_state_free(state);
+ ERR_clear_error();
}
int ERR_get_next_error_library(void) {
- err_fns_check();
- return ERRFN(get_next_library)();
+ int ret;
+
+ CRYPTO_STATIC_MUTEX_lock_write(&global_next_library_mutex);
+ ret = global_next_library++;
+ CRYPTO_STATIC_MUTEX_unlock(&global_next_library_mutex);
+
+ return ret;
}
void ERR_clear_system_error(void) {
@@ -423,53 +422,177 @@ void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
}
}
-/* err_component_error_string returns the error string associated with
- * |packed_error|, which must be of a special form matching the keys inserted
- * into the error hash table. */
-static const char *err_component_error_string(uint32_t packed_error) {
- ERR_STRING_DATA *p;
+// err_string_cmp is a compare function for searching error values with
+// |bsearch| in |err_string_lookup|.
+static int err_string_cmp(const void *a, const void *b) {
+ const uint32_t a_key = *((const uint32_t*) a) >> 15;
+ const uint32_t b_key = *((const uint32_t*) b) >> 15;
- err_fns_check();
- p = ERRFN(get_item)(packed_error);
+ if (a_key < b_key) {
+ return -1;
+ } else if (a_key > b_key) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
- if (p == NULL) {
+/* err_string_lookup looks up the string associated with |lib| and |key| in
+ * |values| and |string_data|. It returns the string or NULL if not found. */
+static const char *err_string_lookup(uint32_t lib, uint32_t key,
+ const uint32_t *values,
+ size_t num_values,
+ const char *string_data) {
+ /* |values| points to data in err_data.h, which is generated by
+ * err_data_generate.go. It's an array of uint32_t values. Each value has the
+ * following structure:
+ * | lib | key | offset |
+ * |6 bits| 11 bits | 15 bits |
+ *
+ * The |lib| value is a library identifier: one of the |ERR_LIB_*| values.
+ * The |key| is either a function or a reason code, depending on the context.
+ * The |offset| is the number of bytes from the start of |string_data| where
+ * the (NUL terminated) string for this value can be found.
+ *
+ * Values are sorted based on treating the |lib| and |key| part as an
+ * unsigned integer. */
+ if (lib >= (1 << 6) || key >= (1 << 11)) {
return NULL;
}
- return p->string;
+ uint32_t search_key = lib << 26 | key << 15;
+ const uint32_t *result = bsearch(&search_key, values, num_values,
+ sizeof(uint32_t), err_string_cmp);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ return &string_data[(*result) & 0x7fff];
}
+static const char *const kLibraryNames[ERR_NUM_LIBS] = {
+ "invalid library (0)",
+ "unknown library", /* ERR_LIB_NONE */
+ "system library", /* ERR_LIB_SYS */
+ "bignum routines", /* ERR_LIB_BN */
+ "RSA routines", /* ERR_LIB_RSA */
+ "Diffie-Hellman routines", /* ERR_LIB_DH */
+ "public key routines", /* ERR_LIB_EVP */
+ "memory buffer routines", /* ERR_LIB_BUF */
+ "object identifier routines", /* ERR_LIB_OBJ */
+ "PEM routines", /* ERR_LIB_PEM */
+ "DSA routines", /* ERR_LIB_DSA */
+ "X.509 certificate routines", /* ERR_LIB_X509 */
+ "ASN.1 encoding routines", /* ERR_LIB_ASN1 */
+ "configuration file routines", /* ERR_LIB_CONF */
+ "common libcrypto routines", /* ERR_LIB_CRYPTO */
+ "elliptic curve routines", /* ERR_LIB_EC */
+ "SSL routines", /* ERR_LIB_SSL */
+ "BIO routines", /* ERR_LIB_BIO */
+ "PKCS7 routines", /* ERR_LIB_PKCS7 */
+ "PKCS8 routines", /* ERR_LIB_PKCS8 */
+ "X509 V3 routines", /* ERR_LIB_X509V3 */
+ "random number generator", /* ERR_LIB_RAND */
+ "ENGINE routines", /* ERR_LIB_ENGINE */
+ "OCSP routines", /* ERR_LIB_OCSP */
+ "UI routines", /* ERR_LIB_UI */
+ "COMP routines", /* ERR_LIB_COMP */
+ "ECDSA routines", /* ERR_LIB_ECDSA */
+ "ECDH routines", /* ERR_LIB_ECDH */
+ "HMAC routines", /* ERR_LIB_HMAC */
+ "Digest functions", /* ERR_LIB_DIGEST */
+ "Cipher functions", /* ERR_LIB_CIPHER */
+ "User defined functions", /* ERR_LIB_USER */
+ "HKDF functions", /* ERR_LIB_HKDF */
+};
+
const char *ERR_lib_error_string(uint32_t packed_error) {
- return err_component_error_string(ERR_PACK(ERR_GET_LIB(packed_error), 0, 0));
+ const uint32_t lib = ERR_GET_LIB(packed_error);
+
+ if (lib >= ERR_NUM_LIBS) {
+ return NULL;
+ }
+ return kLibraryNames[lib];
}
const char *ERR_func_error_string(uint32_t packed_error) {
- return err_component_error_string(
- ERR_PACK(ERR_GET_LIB(packed_error), ERR_GET_FUNC(packed_error), 0));
+ const uint32_t lib = ERR_GET_LIB(packed_error);
+ const uint32_t func = ERR_GET_FUNC(packed_error);
+
+ if (lib == ERR_LIB_SYS) {
+ switch (func) {
+ case SYS_F_fopen:
+ return "fopen";
+ case SYS_F_fclose:
+ return "fclose";
+ case SYS_F_fread:
+ return "fread";
+ case SYS_F_fwrite:
+ return "fwrite";
+ case SYS_F_socket:
+ return "socket";
+ case SYS_F_setsockopt:
+ return "setsockopt";
+ case SYS_F_connect:
+ return "connect";
+ case SYS_F_getaddrinfo:
+ return "getaddrinfo";
+ default:
+ return NULL;
+ }
+ }
+
+ return err_string_lookup(ERR_GET_LIB(packed_error),
+ ERR_GET_FUNC(packed_error), kOpenSSLFunctionValues,
+ kOpenSSLFunctionValuesLen,
+ kOpenSSLFunctionStringData);
}
const char *ERR_reason_error_string(uint32_t packed_error) {
- const char *reason_str = err_component_error_string(
- ERR_PACK(ERR_GET_LIB(packed_error), 0, ERR_GET_REASON(packed_error)));
+ const uint32_t lib = ERR_GET_LIB(packed_error);
+ const uint32_t reason = ERR_GET_REASON(packed_error);
- if (reason_str != NULL) {
- return reason_str;
+ if (lib == ERR_LIB_SYS) {
+ if (reason < 127) {
+ return strerror(reason);
+ }
+ return NULL;
}
- return err_component_error_string(
- ERR_PACK(0, 0, ERR_GET_REASON(packed_error)));
+ if (reason < ERR_NUM_LIBS) {
+ return kLibraryNames[reason];
+ }
+
+ if (reason < 100) {
+ switch (reason) {
+ case ERR_R_MALLOC_FAILURE:
+ return "malloc failure";
+ case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED:
+ return "function should not have been called";
+ case ERR_R_PASSED_NULL_PARAMETER:
+ return "passed a null parameter";
+ case ERR_R_INTERNAL_ERROR:
+ return "internal error";
+ case ERR_R_OVERFLOW:
+ return "overflow";
+ default:
+ return NULL;
+ }
+ }
+
+ return err_string_lookup(lib, reason, kOpenSSLReasonValues,
+ kOpenSSLReasonValuesLen, kOpenSSLReasonStringData);
}
void ERR_print_errors_cb(ERR_print_errors_callback_t callback, void *ctx) {
- CRYPTO_THREADID current_thread;
char buf[ERR_ERROR_STRING_BUF_LEN];
char buf2[1024];
- unsigned long thread_hash;
const char *file, *data;
int line, flags;
uint32_t packed_error;
- CRYPTO_THREADID_current(&current_thread);
- thread_hash = CRYPTO_THREADID_hash(&current_thread);
+ /* thread_hash is the least-significant bits of the |ERR_STATE| pointer value
+ * for this thread. */
+ const unsigned long thread_hash = (uintptr_t) err_get_state();
for (;;) {
packed_error = ERR_get_error_line_data(&file, &line, &data, &flags);
@@ -486,6 +609,17 @@ void ERR_print_errors_cb(ERR_print_errors_callback_t callback, void *ctx) {
}
}
+static int print_errors_to_file(const char* msg, size_t msg_len, void* ctx) {
+ assert(msg[msg_len] == '\0');
+ FILE* fp = ctx;
+ int res = fputs(msg, fp);
+ return res < 0 ? 0 : 1;
+}
+
+void ERR_print_errors_fp(FILE *file) {
+ ERR_print_errors_cb(print_errors_to_file, file);
+}
+
/* err_set_error_data sets the data on the most recent error. The |flags|
* argument is a combination of the |ERR_FLAG_*| values. */
static void err_set_error_data(char *data, int flags) {
@@ -648,162 +782,10 @@ int ERR_pop_to_mark(void) {
return 0;
}
-static const char *const kLibraryNames[ERR_NUM_LIBS] = {
- "invalid library (0)",
- "unknown library", /* ERR_LIB_NONE */
- "system library", /* ERR_LIB_SYS */
- "bignum routines", /* ERR_LIB_BN */
- "RSA routines", /* ERR_LIB_RSA */
- "Diffie-Hellman routines", /* ERR_LIB_DH */
- "public key routines", /* ERR_LIB_EVP */
- "memory buffer routines", /* ERR_LIB_BUF */
- "object identifier routines", /* ERR_LIB_OBJ */
- "PEM routines", /* ERR_LIB_PEM */
- "DSA routines", /* ERR_LIB_DSA */
- "X.509 certificate routines", /* ERR_LIB_X509 */
- "ASN.1 encoding routines", /* ERR_LIB_ASN1 */
- "configuration file routines", /* ERR_LIB_CONF */
- "common libcrypto routines", /* ERR_LIB_CRYPTO */
- "elliptic curve routines", /* ERR_LIB_EC */
- "SSL routines", /* ERR_LIB_SSL */
- "BIO routines", /* ERR_LIB_BIO */
- "PKCS7 routines", /* ERR_LIB_PKCS7 */
- "PKCS8 routines", /* ERR_LIB_PKCS8 */
- "X509 V3 routines", /* ERR_LIB_X509V3 */
- "random number generator", /* ERR_LIB_RAND */
- "ENGINE routines", /* ERR_LIB_ENGINE */
- "OCSP routines", /* ERR_LIB_OCSP */
- "UI routines", /* ERR_LIB_UI */
- "COMP routines", /* ERR_LIB_COMP */
- "ECDSA routines", /* ERR_LIB_ECDSA */
- "ECDH routines", /* ERR_LIB_ECDH */
- "HMAC routines", /* ERR_LIB_HMAC */
- "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
-
-/* kStaticErrors provides storage for ERR_STRING_DATA values that are created
- * at init time because we assume that ERR_STRING_DATA structures aren't
- * allocated on the heap. */
-static ERR_STRING_DATA kStaticErrors[ERR_NUM_LIBS * 2 + NUM_SYS_ERRNOS];
-
-static const ERR_STRING_DATA kGlobalErrors[] = {
- {ERR_R_MALLOC_FAILURE, "malloc failure"},
- {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, "function should not be called"},
- {ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"},
- {ERR_R_INTERNAL_ERROR, "internal error"},
- {ERR_R_OVERFLOW, "overflow"},
-
- {ERR_PACK(ERR_LIB_SYS, SYS_F_fopen, 0), "fopen"},
- {ERR_PACK(ERR_LIB_SYS, SYS_F_fclose, 0), "fclose"},
- {ERR_PACK(ERR_LIB_SYS, SYS_F_fread, 0), "fread"},
- {ERR_PACK(ERR_LIB_SYS, SYS_F_fwrite, 0), "fwrite"},
- {ERR_PACK(ERR_LIB_SYS, SYS_F_socket, 0), "socket"},
- {ERR_PACK(ERR_LIB_SYS, SYS_F_setsockopt, 0), "setsockopt"},
- {ERR_PACK(ERR_LIB_SYS, SYS_F_connect, 0), "connect"},
- {ERR_PACK(ERR_LIB_SYS, SYS_F_getaddrinfo, 0), "getaddrinfo"},
-
- {0, NULL},
-};
-
+void ERR_load_crypto_strings(void) {}
-extern const ERR_STRING_DATA ASN1_error_string_data[];
-extern const ERR_STRING_DATA BIO_error_string_data[];
-extern const ERR_STRING_DATA BN_error_string_data[];
-extern const ERR_STRING_DATA BUF_error_string_data[];
-extern const ERR_STRING_DATA CIPHER_error_string_data[];
-extern const ERR_STRING_DATA CONF_error_string_data[];
-extern const ERR_STRING_DATA CRYPTO_error_string_data[];
-extern const ERR_STRING_DATA DH_error_string_data[];
-extern const ERR_STRING_DATA DIGEST_error_string_data[];
-extern const ERR_STRING_DATA DSA_error_string_data[];
-extern const ERR_STRING_DATA ECDH_error_string_data[];
-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[];
-extern const ERR_STRING_DATA RSA_error_string_data[];
-extern const ERR_STRING_DATA X509V3_error_string_data[];
-extern const ERR_STRING_DATA X509_error_string_data[];
-
-static void err_load_strings(void) {
- unsigned i, j = 0;
-
- err_fns_check();
-
- /* This loop loads strings for the libraries for the ERR_R_*_LIB
- * reasons. */
- for (i = ERR_LIB_NONE; i < ERR_NUM_LIBS; i++) {
- ERR_STRING_DATA *data = &kStaticErrors[j++];
- data->string = kLibraryNames[i];
- data->error = ERR_PACK(i, 0, 0);
- ERRFN(set_item)(data);
-
- data = &kStaticErrors[j++];
- data->string = kLibraryNames[i];
- data->error = ERR_PACK(0, 0, i);
- ERRFN(set_item)(data);
- }
-
- for (i = 1; i < 1 + NUM_SYS_ERRNOS; i++) {
- /* The "SYS" library sets errno values as the reason for its errors.
- * Thus we load the first |NUM_SYS_ERRNOS| errno strings as the
- * reason strings for that library. */
-
- ERR_STRING_DATA *data = &kStaticErrors[j++];
- data->string = strerror(i);
- data->error = ERR_PACK(ERR_LIB_SYS, 0, i);
- ERRFN(set_item)(data);
- }
-
- ERR_load_strings(kGlobalErrors);
-
- ERR_load_strings(ASN1_error_string_data);
- ERR_load_strings(BIO_error_string_data);
- ERR_load_strings(BN_error_string_data);
- ERR_load_strings(BUF_error_string_data);
- ERR_load_strings(CIPHER_error_string_data);
- ERR_load_strings(CONF_error_string_data);
- ERR_load_strings(CRYPTO_error_string_data);
- ERR_load_strings(DH_error_string_data);
- ERR_load_strings(DIGEST_error_string_data);
- ERR_load_strings(DSA_error_string_data);
- ERR_load_strings(ECDH_error_string_data);
- ERR_load_strings(ECDSA_error_string_data);
- 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);
- ERR_load_strings(RSA_error_string_data);
- ERR_load_strings(X509V3_error_string_data);
- ERR_load_strings(X509_error_string_data);
-}
-
-void ERR_load_strings(const ERR_STRING_DATA *str) {
- err_fns_check();
-
- while (str->error) {
- ERRFN(set_item)(str);
- str++;
- }
-}
-
-void ERR_load_crypto_strings(void) { err_load_strings(); }
-
-void ERR_free_strings(void) {
- err_fns_check();
- ERRFN(shutdown)(err_state_free);
-}
+void ERR_free_strings(void) {}
void ERR_load_BIO_strings(void) {}
+
+void ERR_load_ERR_strings(void) {}
diff --git a/src/crypto/err/err_data_generate.go b/src/crypto/err/err_data_generate.go
new file mode 100644
index 0000000..a5b4cb5
--- /dev/null
+++ b/src/crypto/err/err_data_generate.go
@@ -0,0 +1,287 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+// libraryNames must be kept in sync with the enum in err.h. The generated code
+// will contain static assertions to enforce this.
+var libraryNames = []string{
+ "NONE",
+ "SYS",
+ "BN",
+ "RSA",
+ "DH",
+ "EVP",
+ "BUF",
+ "OBJ",
+ "PEM",
+ "DSA",
+ "X509",
+ "ASN1",
+ "CONF",
+ "CRYPTO",
+ "EC",
+ "SSL",
+ "BIO",
+ "PKCS7",
+ "PKCS8",
+ "X509V3",
+ "RAND",
+ "ENGINE",
+ "OCSP",
+ "UI",
+ "COMP",
+ "ECDSA",
+ "ECDH",
+ "HMAC",
+ "DIGEST",
+ "CIPHER",
+ "USER",
+ "HKDF",
+}
+
+// stringList is a map from uint32 -> string which can output data for a sorted
+// list as C literals.
+type stringList struct {
+ // entries is an array of keys and offsets into |stringData|. The
+ // offsets are in the bottom 15 bits of each uint32 and the key is the
+ // top 17 bits.
+ entries []uint32
+ // internedStrings contains the same strings as are in |stringData|,
+ // but allows for easy deduplication. It maps a string to its offset in
+ // |stringData|.
+ internedStrings map[string]uint32
+ stringData []byte
+}
+
+func newStringList() *stringList {
+ return &stringList{
+ internedStrings: make(map[string]uint32),
+ }
+}
+
+// offsetMask is the bottom 15 bits. It's a mask that selects the offset from a
+// uint32 in entries.
+const offsetMask = 0x7fff
+
+func (st *stringList) Add(key uint32, value string) error {
+ if key&offsetMask != 0 {
+ return errors.New("need bottom 15 bits of the key for the offset")
+ }
+ offset, ok := st.internedStrings[value]
+ if !ok {
+ offset = uint32(len(st.stringData))
+ if offset&offsetMask != offset {
+ return errors.New("stringList overflow")
+ }
+ st.stringData = append(st.stringData, []byte(value)...)
+ st.stringData = append(st.stringData, 0)
+ st.internedStrings[value] = offset
+ }
+
+ for _, existing := range st.entries {
+ if existing>>15 == key>>15 {
+ panic("duplicate entry")
+ }
+ }
+ st.entries = append(st.entries, key|offset)
+ return nil
+}
+
+// keySlice is a type that implements sorting of entries values.
+type keySlice []uint32
+
+func (ks keySlice) Len() int {
+ return len(ks)
+}
+
+func (ks keySlice) Less(i, j int) bool {
+ return (ks[i] >> 15) < (ks[j] >> 15)
+}
+
+func (ks keySlice) Swap(i, j int) {
+ ks[i], ks[j] = ks[j], ks[i]
+}
+
+func (st *stringList) buildList() []uint32 {
+ sort.Sort(keySlice(st.entries))
+ return st.entries
+}
+
+type stringWriter interface {
+ io.Writer
+ WriteString(string) (int, error)
+}
+
+func (st *stringList) WriteTo(out stringWriter, name string) {
+ list := st.buildList()
+ fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData))
+
+ values := "kOpenSSL" + name + "Values"
+ out.WriteString("const uint32_t " + values + "[] = {\n")
+ for _, v := range list {
+ fmt.Fprintf(out, " 0x%x,\n", v)
+ }
+ out.WriteString("};\n\n")
+ out.WriteString("const size_t " + values + "Len = sizeof(" + values + ") / sizeof(" + values + "[0]);\n\n");
+
+ stringData := "kOpenSSL" + name + "StringData"
+ out.WriteString("const char " + stringData + "[] =\n \"")
+ for i, c := range st.stringData {
+ if c == 0 {
+ out.WriteString("\\0\"\n \"")
+ continue
+ }
+ out.Write(st.stringData[i : i+1])
+ }
+ out.WriteString("\";\n\n")
+}
+
+type errorData struct {
+ functions, reasons *stringList
+ libraryMap map[string]uint32
+}
+
+func (e *errorData) readErrorDataFile(filename string) error {
+ inFile, err := os.Open(filename)
+ if err != nil {
+ return err
+ }
+ defer inFile.Close()
+
+ scanner := bufio.NewScanner(inFile)
+ comma := []byte(",")
+
+ lineNo := 0
+ for scanner.Scan() {
+ lineNo++
+
+ line := scanner.Bytes()
+ if len(line) == 0 {
+ continue
+ }
+ parts := bytes.Split(line, comma)
+ if len(parts) != 4 {
+ return fmt.Errorf("bad line %d in %s: found %d values but want 4", lineNo, filename, len(parts))
+ }
+ libNum, ok := e.libraryMap[string(parts[0])]
+ if !ok {
+ return fmt.Errorf("bad line %d in %s: unknown library", lineNo, filename)
+ }
+ if libNum >= 64 {
+ return fmt.Errorf("bad line %d in %s: library value too large", lineNo, filename)
+ }
+ key, err := strconv.ParseUint(string(parts[2]), 10 /* base */, 32 /* bit size */)
+ if err != nil {
+ return fmt.Errorf("bad line %d in %s: %s", lineNo, filename, err)
+ }
+ if key >= 2048 {
+ return fmt.Errorf("bad line %d in %s: key too large", lineNo, filename)
+ }
+ value := string(parts[3])
+
+ listKey := libNum<<26 | uint32(key)<<15
+
+ switch string(parts[1]) {
+ case "function":
+ err = e.functions.Add(listKey, value)
+ case "reason":
+ err = e.reasons.Add(listKey, value)
+ default:
+ return fmt.Errorf("bad line %d in %s: bad value type", lineNo, filename)
+ }
+
+ if err != nil {
+ return err
+ }
+ }
+
+ return scanner.Err()
+}
+
+func main() {
+ e := &errorData{
+ functions: newStringList(),
+ reasons: newStringList(),
+ libraryMap: make(map[string]uint32),
+ }
+ for i, name := range libraryNames {
+ e.libraryMap[name] = uint32(i) + 1
+ }
+
+ cwd, err := os.Open(".")
+ if err != nil {
+ panic(err)
+ }
+ names, err := cwd.Readdirnames(-1)
+ if err != nil {
+ panic(err)
+ }
+
+ sort.Strings(names)
+ for _, name := range names {
+ if !strings.HasSuffix(name, ".errordata") {
+ continue
+ }
+ if err := e.readErrorDataFile(name); err != nil {
+ panic(err)
+ }
+ }
+
+ out := os.Stdout
+
+ out.WriteString(`/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+ /* This file was generated by err_data_generate.go. */
+
+#include <openssl/base.h>
+#include <openssl/err.h>
+#include <openssl/type_check.h>
+
+
+`)
+
+ for i, name := range libraryNames {
+ fmt.Fprintf(out, "OPENSSL_COMPILE_ASSERT(ERR_LIB_%s == %d, library_values_changed_%d);\n", name, i+1, i+1)
+ }
+ fmt.Fprintf(out, "OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == %d, library_values_changed_num);\n", len(libraryNames) + 1)
+ out.WriteString("\n")
+
+ e.functions.WriteTo(out, "Function")
+ e.reasons.WriteTo(out, "Reason")
+}
diff --git a/src/crypto/err/err_impl.c b/src/crypto/err/err_impl.c
deleted file mode 100644
index 32cff35..0000000
--- a/src/crypto/err/err_impl.c
+++ /dev/null
@@ -1,323 +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.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com). */
-
-#include <openssl/err.h>
-
-#include <assert.h>
-#include <string.h>
-
-#include <openssl/lhash.h>
-#include <openssl/mem.h>
-
-
-DEFINE_LHASH_OF(ERR_STATE);
-DEFINE_LHASH_OF(ERR_STRING_DATA);
-
-/* state_hash is a map from thread ID to ERR_STATE. It works like thread-local
- * storage. */
-static LHASH_OF(ERR_STATE) *state_hash = NULL;
-
-/* error_hash maps from a packed error to the string for that library /
- * function / reason. */
-static LHASH_OF(ERR_STRING_DATA) *error_hash = NULL;
-
-/* global_next_library contains the next custom library value to return. */
-static int global_next_library = ERR_NUM_LIBS;
-
-/* err_string_data_hash is an lhash hash function for ERR_STRING_DATA. */
-static uint32_t err_string_data_hash(const ERR_STRING_DATA *a) {
- return OPENSSL_hash32(&a->error, sizeof(a->error));
-}
-
-/* err_string_data_cmp is an lhash compare function for ERR_STRING_DATA. */
-static int err_string_data_cmp(const ERR_STRING_DATA *a,
- const ERR_STRING_DATA *b) {
- return ((int)a->error) - ((int)b->error);
-}
-
-/* error_hash_get_write_locked returns the hash that maps from packed error to
- * error string and creates it if need be. The caller must hold a write lock on
- * LOCK_ERR. */
-static LHASH_OF(ERR_STRING_DATA) * error_hash_get_write_locked(void) {
- if (!error_hash) {
- error_hash = lh_ERR_STRING_DATA_new(err_string_data_hash, err_string_data_cmp);
- }
-
- return error_hash;
-}
-
-/* err_get_item returns an ERR_STRING_DATA with an |error| member that
- * equals |packed_error|, or NULL if none can be found. */
-static ERR_STRING_DATA *err_get_item(uint32_t packed_error) {
- ERR_STRING_DATA *ret = NULL, pattern;
-
- pattern.error = packed_error;
-
- CRYPTO_r_lock(CRYPTO_LOCK_ERR);
- if (error_hash) {
- ret = lh_ERR_STRING_DATA_retrieve(error_hash, &pattern);
- }
- CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-
- return ret;
-}
-
-/* err_set_item adds an ERR_STRING_DATA to the global hash of error strings and
- * returns the previous entry with the same |err->error| value, if any. */
-static ERR_STRING_DATA *err_set_item(const ERR_STRING_DATA *err) {
- ERR_STRING_DATA *old_item = NULL;
- LHASH_OF(ERR_STRING_DATA) *hash;
-
- CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- hash = error_hash_get_write_locked();
- if (hash) {
- lh_ERR_STRING_DATA_insert(hash, &old_item, (ERR_STRING_DATA*) err);
- }
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
- return old_item;
-}
-
-/* err_set_item removes an item from the global hash of error strings for
- * |packed_error| and returns the removed entry, if any. */
-static ERR_STRING_DATA *err_del_item(uint32_t packed_error) {
- ERR_STRING_DATA *old_item = NULL, pattern;
-
- pattern.error = packed_error;
-
- CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- if (error_hash) {
- old_item = lh_ERR_STRING_DATA_delete(error_hash, &pattern);
- }
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
- return old_item;
-}
-
-
-/* err_state_hash is an lhash hash function for ERR_STATE. */
-static uint32_t err_state_hash(const ERR_STATE *a) {
- return CRYPTO_THREADID_hash(&a->tid);
-}
-
-/* err_state_cmp is an lhash compare function for ERR_STATE. */
-static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b) {
- return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
-}
-
-
-static ERR_STATE *err_get_state(void) {
- CRYPTO_THREADID tid;
- ERR_STATE pattern, *state, *race_state;
- int insert_result;
- static ERR_STATE fallback;
-
- CRYPTO_THREADID_current(&tid);
- memset(&pattern, 0, sizeof(pattern));
- CRYPTO_THREADID_cpy(&pattern.tid, &tid);
-
- CRYPTO_r_lock(CRYPTO_LOCK_ERR);
- if (state_hash == NULL) {
- CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
- CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- if (state_hash == NULL) {
- state_hash = lh_ERR_STATE_new(err_state_hash, err_state_cmp);
- }
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
- 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) {
- return state;
- }
-
- state = OPENSSL_malloc(sizeof(ERR_STATE));
- if (state == NULL) {
- CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
- /* The other error functions don't cope with a failure to get the error
- * state, so we return a dummy value. */
- return &fallback;
- }
-
- memset(state, 0, sizeof(ERR_STATE));
- CRYPTO_THREADID_cpy(&state->tid, &tid);
-
- CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- insert_result = lh_ERR_STATE_insert(state_hash, &race_state, state);
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
- if (!insert_result) {
- /* Insertion failed because of malloc failure. */
- OPENSSL_free(state);
- return &fallback;
- }
-
- /* We cannot have raced with another thread to insert an ERR_STATE because no
- * other thread should be inserting values for this thread. */
- assert(race_state == NULL);
-
- return state;
-}
-
-static ERR_STATE *err_release_state(const CRYPTO_THREADID *tid) {
- ERR_STATE pattern, *state;
-
- CRYPTO_THREADID_cpy(&pattern.tid, tid);
-
- CRYPTO_r_lock(CRYPTO_LOCK_ERR);
- if (state_hash == NULL) {
- CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
- return NULL;
- }
-
- state = lh_ERR_STATE_delete(state_hash, &pattern);
- CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-
- return state;
-}
-
-static void err_shutdown(void (*err_state_free_cb)(ERR_STATE*)) {
- CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- if (error_hash) {
- lh_ERR_STRING_DATA_free(error_hash);
- error_hash = NULL;
- }
- if (state_hash) {
- lh_ERR_STATE_doall(state_hash, err_state_free_cb);
- lh_ERR_STATE_free(state_hash);
- state_hash = NULL;
- }
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-}
-
-static int err_get_next_library(void) {
- int ret;
-
- CRYPTO_w_lock(CRYPTO_LOCK_ERR);
- ret = global_next_library++;
- CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
- return ret;
-}
-
-const struct ERR_FNS_st openssl_err_default_impl = {
- err_shutdown,
- err_get_item,
- err_set_item,
- err_del_item,
- err_get_state,
- err_release_state,
- err_get_next_library,
-};
diff --git a/src/crypto/err/err_test.c b/src/crypto/err/err_test.cc
index bf36201..98dfb85 100644
--- a/src/crypto/err/err_test.c
+++ b/src/crypto/err/err_test.cc
@@ -20,55 +20,52 @@
#include <openssl/mem.h>
-static int test_overflow(void) {
- unsigned i;
-
- for (i = 0; i < ERR_NUM_ERRORS*2; i++) {
+static bool TestOverflow() {
+ for (unsigned i = 0; i < ERR_NUM_ERRORS*2; i++) {
ERR_put_error(1, 2, i+1, "test", 1);
}
- for (i = 0; i < ERR_NUM_ERRORS - 1; i++) {
+ for (unsigned i = 0; i < ERR_NUM_ERRORS - 1; i++) {
uint32_t err = ERR_get_error();
/* Errors are returned in order they were pushed, with the least recent ones
* removed, up to |ERR_NUM_ERRORS - 1| errors. So the errors returned are
* |ERR_NUM_ERRORS + 2| through |ERR_NUM_ERRORS * 2|, inclusive. */
if (err == 0 || ERR_GET_REASON(err) != i + ERR_NUM_ERRORS + 2) {
fprintf(stderr, "ERR_get_error failed at %u\n", i);
- return 0;
+ return false;
}
}
if (ERR_get_error() != 0) {
fprintf(stderr, "ERR_get_error more than the expected number of values.\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int test_put_error(void) {
- uint32_t peeked_packed_error, packed_error;
- int peeked_line, line, peeked_flags, flags;
- const char *peeked_file, *file, *peeked_data, *data;
-
+static bool TestPutError() {
if (ERR_get_error() != 0) {
fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
- return 0;
+ return false;
}
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);
+ int peeked_line, line, peeked_flags, flags;
+ const char *peeked_file, *file, *peeked_data, *data;
+ uint32_t peeked_packed_error =
+ ERR_peek_error_line_data(&peeked_file, &peeked_line, &peeked_data,
+ &peeked_flags);
+ uint32_t 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;
+ return false;
}
if (strcmp(file, "test") != 0 ||
@@ -79,16 +76,16 @@ static int test_put_error(void) {
ERR_GET_REASON(packed_error) != 3 ||
strcmp(data, "testing") != 0) {
fprintf(stderr, "Bad error data returned.\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int test_clear_error(void) {
+static bool TestClearError() {
if (ERR_get_error() != 0) {
fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
- return 0;
+ return false;
}
ERR_put_error(1, 2, 3, "test", 4);
@@ -96,42 +93,39 @@ static int test_clear_error(void) {
if (ERR_get_error() != 0) {
fprintf(stderr, "Error remained after clearing.\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int test_print(void) {
- size_t i;
- char buf[256];
- uint32_t packed_error;
-
+static bool TestPrint() {
ERR_put_error(1, 2, 3, "test", 4);
ERR_add_error_data(1, "testing");
- packed_error = ERR_get_error();
+ uint32_t packed_error = ERR_get_error();
- for (i = 0; i <= sizeof(buf); i++) {
+ char buf[256];
+ for (size_t i = 0; i <= sizeof(buf); i++) {
ERR_error_string_n(packed_error, buf, i);
}
- return 1;
+ return true;
}
-static int test_release(void) {
+static bool TestRelease() {
ERR_put_error(1, 2, 3, "test", 4);
ERR_remove_thread_state(NULL);
- return 1;
+ return true;
}
-int main(void) {
+int main() {
CRYPTO_library_init();
- if (!test_overflow() ||
- !test_put_error() ||
- !test_clear_error() ||
- !test_print() ||
- !test_release()) {
+ if (!TestOverflow() ||
+ !TestPutError() ||
+ !TestClearError() ||
+ !TestPrint() ||
+ !TestRelease()) {
return 1;
}
diff --git a/src/crypto/err/evp.errordata b/src/crypto/err/evp.errordata
new file mode 100644
index 0000000..14dd27b
--- /dev/null
+++ b/src/crypto/err/evp.errordata
@@ -0,0 +1,114 @@
+EVP,function,160,EVP_DigestSignAlgorithm
+EVP,function,161,EVP_DigestVerifyInitFromAlgorithm
+EVP,function,162,EVP_PKEY_CTX_ctrl
+EVP,function,163,EVP_PKEY_CTX_dup
+EVP,function,159,EVP_PKEY_CTX_get0_rsa_oaep_label
+EVP,function,164,EVP_PKEY_copy_parameters
+EVP,function,165,EVP_PKEY_decrypt
+EVP,function,166,EVP_PKEY_decrypt_init
+EVP,function,167,EVP_PKEY_derive
+EVP,function,108,EVP_PKEY_derive_init
+EVP,function,168,EVP_PKEY_derive_set_peer
+EVP,function,110,EVP_PKEY_encrypt
+EVP,function,111,EVP_PKEY_encrypt_init
+EVP,function,112,EVP_PKEY_get1_DH
+EVP,function,169,EVP_PKEY_get1_DSA
+EVP,function,114,EVP_PKEY_get1_EC_KEY
+EVP,function,115,EVP_PKEY_get1_RSA
+EVP,function,116,EVP_PKEY_keygen
+EVP,function,170,EVP_PKEY_keygen_init
+EVP,function,171,EVP_PKEY_new
+EVP,function,172,EVP_PKEY_set_type
+EVP,function,120,EVP_PKEY_sign
+EVP,function,121,EVP_PKEY_sign_init
+EVP,function,122,EVP_PKEY_verify
+EVP,function,123,EVP_PKEY_verify_init
+EVP,function,173,check_padding_md
+EVP,function,125,d2i_AutoPrivateKey
+EVP,function,126,d2i_PrivateKey
+EVP,function,127,do_EC_KEY_print
+EVP,function,174,do_dsa_print
+EVP,function,175,do_rsa_print
+EVP,function,129,do_sigver_init
+EVP,function,176,dsa_param_decode
+EVP,function,177,dsa_priv_decode
+EVP,function,178,dsa_priv_encode
+EVP,function,179,dsa_pub_decode
+EVP,function,180,dsa_pub_encode
+EVP,function,181,dsa_sig_print
+EVP,function,130,eckey_param2type
+EVP,function,131,eckey_param_decode
+EVP,function,132,eckey_priv_decode
+EVP,function,133,eckey_priv_encode
+EVP,function,134,eckey_pub_decode
+EVP,function,135,eckey_pub_encode
+EVP,function,136,eckey_type2param
+EVP,function,137,evp_pkey_ctx_new
+EVP,function,138,hmac_signctx
+EVP,function,139,i2d_PublicKey
+EVP,function,182,old_dsa_priv_decode
+EVP,function,140,old_ec_priv_decode
+EVP,function,141,old_rsa_priv_decode
+EVP,function,142,pkey_ec_ctrl
+EVP,function,143,pkey_ec_derive
+EVP,function,144,pkey_ec_keygen
+EVP,function,145,pkey_ec_paramgen
+EVP,function,146,pkey_ec_sign
+EVP,function,158,pkey_hmac_ctrl
+EVP,function,147,pkey_rsa_ctrl
+EVP,function,148,pkey_rsa_decrypt
+EVP,function,149,pkey_rsa_encrypt
+EVP,function,150,pkey_rsa_sign
+EVP,function,151,rsa_algor_to_md
+EVP,function,152,rsa_digest_verify_init_from_algorithm
+EVP,function,153,rsa_mgf1_to_md
+EVP,function,154,rsa_priv_decode
+EVP,function,155,rsa_priv_encode
+EVP,function,156,rsa_pss_to_ctx
+EVP,function,157,rsa_pub_decode
+EVP,reason,151,BN_DECODE_ERROR
+EVP,reason,100,BUFFER_TOO_SMALL
+EVP,reason,101,COMMAND_NOT_SUPPORTED
+EVP,reason,146,CONTEXT_NOT_INITIALISED
+EVP,reason,143,DECODE_ERROR
+EVP,reason,104,DIFFERENT_KEY_TYPES
+EVP,reason,105,DIFFERENT_PARAMETERS
+EVP,reason,147,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED
+EVP,reason,107,EXPECTING_AN_EC_KEY_KEY
+EVP,reason,141,EXPECTING_AN_RSA_KEY
+EVP,reason,109,EXPECTING_A_DH_KEY
+EVP,reason,110,EXPECTING_A_DSA_KEY
+EVP,reason,111,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE
+EVP,reason,112,INVALID_CURVE
+EVP,reason,113,INVALID_DIGEST_LENGTH
+EVP,reason,114,INVALID_DIGEST_TYPE
+EVP,reason,115,INVALID_KEYBITS
+EVP,reason,116,INVALID_MGF1_MD
+EVP,reason,142,INVALID_OPERATION
+EVP,reason,118,INVALID_PADDING_MODE
+EVP,reason,119,INVALID_PSS_PARAMETERS
+EVP,reason,144,INVALID_PSS_SALTLEN
+EVP,reason,121,INVALID_SALT_LENGTH
+EVP,reason,122,INVALID_TRAILER
+EVP,reason,123,KEYS_NOT_SET
+EVP,reason,124,MISSING_PARAMETERS
+EVP,reason,125,NO_DEFAULT_DIGEST
+EVP,reason,126,NO_KEY_SET
+EVP,reason,127,NO_MDC2_SUPPORT
+EVP,reason,128,NO_NID_FOR_CURVE
+EVP,reason,129,NO_OPERATION_SET
+EVP,reason,130,NO_PARAMETERS_SET
+EVP,reason,131,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
+EVP,reason,132,OPERATON_NOT_INITIALIZED
+EVP,reason,152,PARAMETER_ENCODING_ERROR
+EVP,reason,133,UNKNOWN_DIGEST
+EVP,reason,134,UNKNOWN_MASK_DIGEST
+EVP,reason,150,UNKNOWN_MESSAGE_DIGEST_ALGORITHM
+EVP,reason,145,UNKNOWN_PUBLIC_KEY_TYPE
+EVP,reason,149,UNKNOWN_SIGNATURE_ALGORITHM
+EVP,reason,138,UNSUPPORTED_ALGORITHM
+EVP,reason,139,UNSUPPORTED_MASK_ALGORITHM
+EVP,reason,140,UNSUPPORTED_MASK_PARAMETER
+EVP,reason,153,UNSUPPORTED_PUBLIC_KEY_TYPE
+EVP,reason,154,UNSUPPORTED_SIGNATURE_TYPE
+EVP,reason,148,WRONG_PUBLIC_KEY_TYPE
diff --git a/src/crypto/err/hkdf.errordata b/src/crypto/err/hkdf.errordata
new file mode 100644
index 0000000..878a802
--- /dev/null
+++ b/src/crypto/err/hkdf.errordata
@@ -0,0 +1,2 @@
+HKDF,function,100,HKDF
+HKDF,reason,100,OUTPUT_TOO_LARGE
diff --git a/src/crypto/err/obj.errordata b/src/crypto/err/obj.errordata
new file mode 100644
index 0000000..74e4629
--- /dev/null
+++ b/src/crypto/err/obj.errordata
@@ -0,0 +1,5 @@
+OBJ,function,100,OBJ_create
+OBJ,function,101,OBJ_dup
+OBJ,function,102,OBJ_nid2obj
+OBJ,function,103,OBJ_txt2obj
+OBJ,reason,100,UNKNOWN_NID
diff --git a/src/crypto/err/pem.errordata b/src/crypto/err/pem.errordata
new file mode 100644
index 0000000..42216a7
--- /dev/null
+++ b/src/crypto/err/pem.errordata
@@ -0,0 +1,39 @@
+PEM,function,100,PEM_ASN1_read
+PEM,function,101,PEM_ASN1_read_bio
+PEM,function,102,PEM_ASN1_write
+PEM,function,103,PEM_ASN1_write_bio
+PEM,function,104,PEM_X509_INFO_read
+PEM,function,105,PEM_X509_INFO_read_bio
+PEM,function,106,PEM_X509_INFO_write_bio
+PEM,function,107,PEM_do_header
+PEM,function,108,PEM_get_EVP_CIPHER_INFO
+PEM,function,109,PEM_read
+PEM,function,110,PEM_read_DHparams
+PEM,function,111,PEM_read_PrivateKey
+PEM,function,112,PEM_read_bio
+PEM,function,113,PEM_read_bio_DHparams
+PEM,function,114,PEM_read_bio_Parameters
+PEM,function,115,PEM_read_bio_PrivateKey
+PEM,function,116,PEM_write
+PEM,function,117,PEM_write_PrivateKey
+PEM,function,118,PEM_write_bio
+PEM,function,119,d2i_PKCS8PrivateKey_bio
+PEM,function,120,d2i_PKCS8PrivateKey_fp
+PEM,function,121,do_pk8pkey
+PEM,function,122,do_pk8pkey_fp
+PEM,function,123,load_iv
+PEM,reason,100,BAD_BASE64_DECODE
+PEM,reason,101,BAD_DECRYPT
+PEM,reason,102,BAD_END_LINE
+PEM,reason,103,BAD_IV_CHARS
+PEM,reason,104,BAD_PASSWORD_READ
+PEM,reason,105,CIPHER_IS_NULL
+PEM,reason,106,ERROR_CONVERTING_PRIVATE_KEY
+PEM,reason,107,NOT_DEK_INFO
+PEM,reason,108,NOT_ENCRYPTED
+PEM,reason,109,NOT_PROC_TYPE
+PEM,reason,110,NO_START_LINE
+PEM,reason,111,READ_KEY
+PEM,reason,112,SHORT_HEADER
+PEM,reason,113,UNSUPPORTED_CIPHER
+PEM,reason,114,UNSUPPORTED_ENCRYPTION
diff --git a/src/crypto/err/pkcs8.errordata b/src/crypto/err/pkcs8.errordata
new file mode 100644
index 0000000..936f3c5
--- /dev/null
+++ b/src/crypto/err/pkcs8.errordata
@@ -0,0 +1,43 @@
+PKCS8,function,100,EVP_PKCS82PKEY
+PKCS8,function,101,EVP_PKEY2PKCS8
+PKCS8,function,102,PKCS12_get_key_and_certs
+PKCS8,function,103,PKCS12_handle_content_info
+PKCS8,function,104,PKCS12_handle_content_infos
+PKCS8,function,105,PKCS5_pbe2_set_iv
+PKCS8,function,106,PKCS5_pbe_set
+PKCS8,function,107,PKCS5_pbe_set0_algor
+PKCS8,function,108,PKCS5_pbkdf2_set
+PKCS8,function,109,PKCS8_decrypt
+PKCS8,function,110,PKCS8_encrypt
+PKCS8,function,111,PKCS8_encrypt_pbe
+PKCS8,function,112,pbe_cipher_init
+PKCS8,function,113,pbe_crypt
+PKCS8,function,114,pkcs12_item_decrypt_d2i
+PKCS8,function,115,pkcs12_item_i2d_encrypt
+PKCS8,function,116,pkcs12_key_gen_raw
+PKCS8,function,117,pkcs12_pbe_keyivgen
+PKCS8,reason,100,BAD_PKCS12_DATA
+PKCS8,reason,101,BAD_PKCS12_VERSION
+PKCS8,reason,102,CIPHER_HAS_NO_OBJECT_IDENTIFIER
+PKCS8,reason,103,CRYPT_ERROR
+PKCS8,reason,104,DECODE_ERROR
+PKCS8,reason,105,ENCODE_ERROR
+PKCS8,reason,106,ENCRYPT_ERROR
+PKCS8,reason,107,ERROR_SETTING_CIPHER_PARAMS
+PKCS8,reason,108,INCORRECT_PASSWORD
+PKCS8,reason,109,KEYGEN_FAILURE
+PKCS8,reason,110,KEY_GEN_ERROR
+PKCS8,reason,111,METHOD_NOT_SUPPORTED
+PKCS8,reason,112,MISSING_MAC
+PKCS8,reason,113,MULTIPLE_PRIVATE_KEYS_IN_PKCS12
+PKCS8,reason,114,PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED
+PKCS8,reason,115,PKCS12_TOO_DEEPLY_NESTED
+PKCS8,reason,116,PRIVATE_KEY_DECODE_ERROR
+PKCS8,reason,117,PRIVATE_KEY_ENCODE_ERROR
+PKCS8,reason,118,TOO_LONG
+PKCS8,reason,119,UNKNOWN_ALGORITHM
+PKCS8,reason,120,UNKNOWN_CIPHER
+PKCS8,reason,121,UNKNOWN_CIPHER_ALGORITHM
+PKCS8,reason,122,UNKNOWN_DIGEST
+PKCS8,reason,123,UNKNOWN_HASH
+PKCS8,reason,124,UNSUPPORTED_PRIVATE_KEY_ALGORITHM
diff --git a/src/crypto/err/rsa.errordata b/src/crypto/err/rsa.errordata
new file mode 100644
index 0000000..64b390d
--- /dev/null
+++ b/src/crypto/err/rsa.errordata
@@ -0,0 +1,69 @@
+RSA,function,100,BN_BLINDING_convert_ex
+RSA,function,101,BN_BLINDING_create_param
+RSA,function,102,BN_BLINDING_invert_ex
+RSA,function,103,BN_BLINDING_new
+RSA,function,104,BN_BLINDING_update
+RSA,function,105,RSA_check_key
+RSA,function,106,RSA_new_method
+RSA,function,107,RSA_padding_add_PKCS1_OAEP_mgf1
+RSA,function,108,RSA_padding_add_PKCS1_PSS_mgf1
+RSA,function,109,RSA_padding_add_PKCS1_type_1
+RSA,function,110,RSA_padding_add_PKCS1_type_2
+RSA,function,111,RSA_padding_add_none
+RSA,function,112,RSA_padding_check_PKCS1_OAEP_mgf1
+RSA,function,113,RSA_padding_check_PKCS1_type_1
+RSA,function,114,RSA_padding_check_PKCS1_type_2
+RSA,function,115,RSA_padding_check_none
+RSA,function,116,RSA_recover_crt_params
+RSA,function,117,RSA_sign
+RSA,function,118,RSA_verify
+RSA,function,119,RSA_verify_PKCS1_PSS_mgf1
+RSA,function,120,decrypt
+RSA,function,121,encrypt
+RSA,function,122,keygen
+RSA,function,123,pkcs1_prefixed_msg
+RSA,function,124,private_transform
+RSA,function,125,rsa_setup_blinding
+RSA,function,126,sign_raw
+RSA,function,127,verify_raw
+RSA,reason,100,BAD_E_VALUE
+RSA,reason,101,BAD_FIXED_HEADER_DECRYPT
+RSA,reason,102,BAD_PAD_BYTE_COUNT
+RSA,reason,103,BAD_RSA_PARAMETERS
+RSA,reason,104,BAD_SIGNATURE
+RSA,reason,105,BLOCK_TYPE_IS_NOT_01
+RSA,reason,106,BN_NOT_INITIALIZED
+RSA,reason,107,CRT_PARAMS_ALREADY_GIVEN
+RSA,reason,108,CRT_VALUES_INCORRECT
+RSA,reason,109,DATA_LEN_NOT_EQUAL_TO_MOD_LEN
+RSA,reason,110,DATA_TOO_LARGE
+RSA,reason,111,DATA_TOO_LARGE_FOR_KEY_SIZE
+RSA,reason,112,DATA_TOO_LARGE_FOR_MODULUS
+RSA,reason,113,DATA_TOO_SMALL
+RSA,reason,114,DATA_TOO_SMALL_FOR_KEY_SIZE
+RSA,reason,115,DIGEST_TOO_BIG_FOR_RSA_KEY
+RSA,reason,116,D_E_NOT_CONGRUENT_TO_1
+RSA,reason,117,EMPTY_PUBLIC_KEY
+RSA,reason,118,FIRST_OCTET_INVALID
+RSA,reason,119,INCONSISTENT_SET_OF_CRT_VALUES
+RSA,reason,120,INTERNAL_ERROR
+RSA,reason,121,INVALID_MESSAGE_LENGTH
+RSA,reason,122,KEY_SIZE_TOO_SMALL
+RSA,reason,123,LAST_OCTET_INVALID
+RSA,reason,124,MODULUS_TOO_LARGE
+RSA,reason,125,NO_PUBLIC_EXPONENT
+RSA,reason,126,NULL_BEFORE_BLOCK_MISSING
+RSA,reason,127,N_NOT_EQUAL_P_Q
+RSA,reason,128,OAEP_DECODING_ERROR
+RSA,reason,129,ONLY_ONE_OF_P_Q_GIVEN
+RSA,reason,130,OUTPUT_BUFFER_TOO_SMALL
+RSA,reason,131,PADDING_CHECK_FAILED
+RSA,reason,132,PKCS_DECODING_ERROR
+RSA,reason,133,SLEN_CHECK_FAILED
+RSA,reason,134,SLEN_RECOVERY_FAILED
+RSA,reason,135,TOO_LONG
+RSA,reason,136,TOO_MANY_ITERATIONS
+RSA,reason,137,UNKNOWN_ALGORITHM_TYPE
+RSA,reason,138,UNKNOWN_PADDING_TYPE
+RSA,reason,139,VALUE_MISSING
+RSA,reason,140,WRONG_SIGNATURE_LENGTH
diff --git a/src/crypto/err/ssl.errordata b/src/crypto/err/ssl.errordata
new file mode 100644
index 0000000..afeaaeb
--- /dev/null
+++ b/src/crypto/err/ssl.errordata
@@ -0,0 +1,376 @@
+SSL,function,100,SSL_CTX_check_private_key
+SSL,function,101,SSL_CTX_new
+SSL,function,272,SSL_CTX_set1_tls_channel_id
+SSL,function,102,SSL_CTX_set_cipher_list
+SSL,function,103,SSL_CTX_set_cipher_list_tls11
+SSL,function,104,SSL_CTX_set_session_id_context
+SSL,function,268,SSL_CTX_set_tmp_dh
+SSL,function,269,SSL_CTX_set_tmp_ecdh
+SSL,function,105,SSL_CTX_use_PrivateKey
+SSL,function,106,SSL_CTX_use_PrivateKey_ASN1
+SSL,function,107,SSL_CTX_use_PrivateKey_file
+SSL,function,108,SSL_CTX_use_RSAPrivateKey
+SSL,function,109,SSL_CTX_use_RSAPrivateKey_ASN1
+SSL,function,110,SSL_CTX_use_RSAPrivateKey_file
+SSL,function,111,SSL_CTX_use_certificate
+SSL,function,112,SSL_CTX_use_certificate_ASN1
+SSL,function,113,SSL_CTX_use_certificate_chain_file
+SSL,function,114,SSL_CTX_use_certificate_file
+SSL,function,115,SSL_CTX_use_psk_identity_hint
+SSL,function,116,SSL_SESSION_new
+SSL,function,117,SSL_SESSION_print_fp
+SSL,function,118,SSL_SESSION_set1_id_context
+SSL,function,119,SSL_SESSION_to_bytes_full
+SSL,function,120,SSL_accept
+SSL,function,121,SSL_add_dir_cert_subjects_to_stack
+SSL,function,122,SSL_add_file_cert_subjects_to_stack
+SSL,function,123,SSL_check_private_key
+SSL,function,124,SSL_clear
+SSL,function,125,SSL_connect
+SSL,function,126,SSL_do_handshake
+SSL,function,127,SSL_load_client_CA_file
+SSL,function,128,SSL_new
+SSL,function,129,SSL_peek
+SSL,function,130,SSL_read
+SSL,function,131,SSL_renegotiate
+SSL,function,273,SSL_set1_tls_channel_id
+SSL,function,132,SSL_set_cipher_list
+SSL,function,133,SSL_set_fd
+SSL,function,134,SSL_set_rfd
+SSL,function,135,SSL_set_session_id_context
+SSL,function,274,SSL_set_tlsext_host_name
+SSL,function,270,SSL_set_tmp_dh
+SSL,function,271,SSL_set_tmp_ecdh
+SSL,function,136,SSL_set_wfd
+SSL,function,137,SSL_shutdown
+SSL,function,138,SSL_use_PrivateKey
+SSL,function,139,SSL_use_PrivateKey_ASN1
+SSL,function,140,SSL_use_PrivateKey_file
+SSL,function,141,SSL_use_RSAPrivateKey
+SSL,function,142,SSL_use_RSAPrivateKey_ASN1
+SSL,function,143,SSL_use_RSAPrivateKey_file
+SSL,function,144,SSL_use_certificate
+SSL,function,145,SSL_use_certificate_ASN1
+SSL,function,146,SSL_use_certificate_file
+SSL,function,147,SSL_use_psk_identity_hint
+SSL,function,148,SSL_write
+SSL,function,149,d2i_SSL_SESSION
+SSL,function,150,d2i_SSL_SESSION_get_octet_string
+SSL,function,151,d2i_SSL_SESSION_get_string
+SSL,function,152,do_ssl3_write
+SSL,function,153,dtls1_accept
+SSL,function,154,dtls1_buffer_record
+SSL,function,155,dtls1_check_timeout_num
+SSL,function,156,dtls1_connect
+SSL,function,157,dtls1_do_write
+SSL,function,263,dtls1_get_buffered_message
+SSL,function,158,dtls1_get_hello_verify
+SSL,function,159,dtls1_get_message
+SSL,function,160,dtls1_get_message_fragment
+SSL,function,265,dtls1_hm_fragment_new
+SSL,function,161,dtls1_preprocess_fragment
+SSL,function,264,dtls1_process_fragment
+SSL,function,162,dtls1_process_record
+SSL,function,163,dtls1_read_bytes
+SSL,function,164,dtls1_send_hello_verify_request
+SSL,function,165,dtls1_write_app_data_bytes
+SSL,function,166,i2d_SSL_SESSION
+SSL,function,167,ssl3_accept
+SSL,function,169,ssl3_cert_verify_hash
+SSL,function,170,ssl3_check_cert_and_algorithm
+SSL,function,171,ssl3_connect
+SSL,function,172,ssl3_ctrl
+SSL,function,173,ssl3_ctx_ctrl
+SSL,function,174,ssl3_digest_cached_records
+SSL,function,175,ssl3_do_change_cipher_spec
+SSL,function,176,ssl3_expect_change_cipher_spec
+SSL,function,177,ssl3_get_cert_status
+SSL,function,178,ssl3_get_cert_verify
+SSL,function,179,ssl3_get_certificate_request
+SSL,function,180,ssl3_get_channel_id
+SSL,function,181,ssl3_get_client_certificate
+SSL,function,182,ssl3_get_client_hello
+SSL,function,183,ssl3_get_client_key_exchange
+SSL,function,184,ssl3_get_finished
+SSL,function,185,ssl3_get_initial_bytes
+SSL,function,186,ssl3_get_message
+SSL,function,187,ssl3_get_new_session_ticket
+SSL,function,188,ssl3_get_next_proto
+SSL,function,189,ssl3_get_record
+SSL,function,190,ssl3_get_server_certificate
+SSL,function,191,ssl3_get_server_done
+SSL,function,192,ssl3_get_server_hello
+SSL,function,193,ssl3_get_server_key_exchange
+SSL,function,194,ssl3_get_v2_client_hello
+SSL,function,195,ssl3_handshake_mac
+SSL,function,275,ssl3_output_cert_chain
+SSL,function,196,ssl3_prf
+SSL,function,197,ssl3_read_bytes
+SSL,function,198,ssl3_read_n
+SSL,function,267,ssl3_record_sequence_update
+SSL,function,266,ssl3_seal_record
+SSL,function,199,ssl3_send_cert_verify
+SSL,function,200,ssl3_send_certificate_request
+SSL,function,201,ssl3_send_channel_id
+SSL,function,202,ssl3_send_client_certificate
+SSL,function,203,ssl3_send_client_hello
+SSL,function,204,ssl3_send_client_key_exchange
+SSL,function,205,ssl3_send_server_certificate
+SSL,function,206,ssl3_send_server_hello
+SSL,function,207,ssl3_send_server_key_exchange
+SSL,function,208,ssl3_setup_read_buffer
+SSL,function,209,ssl3_setup_write_buffer
+SSL,function,210,ssl3_write_bytes
+SSL,function,211,ssl3_write_pending
+SSL,function,212,ssl_add_cert_chain
+SSL,function,213,ssl_add_cert_to_buf
+SSL,function,214,ssl_add_clienthello_renegotiate_ext
+SSL,function,215,ssl_add_clienthello_tlsext
+SSL,function,216,ssl_add_clienthello_use_srtp_ext
+SSL,function,217,ssl_add_serverhello_renegotiate_ext
+SSL,function,218,ssl_add_serverhello_tlsext
+SSL,function,219,ssl_add_serverhello_use_srtp_ext
+SSL,function,220,ssl_build_cert_chain
+SSL,function,221,ssl_bytes_to_cipher_list
+SSL,function,222,ssl_cert_dup
+SSL,function,223,ssl_cert_inst
+SSL,function,224,ssl_cert_new
+SSL,function,225,ssl_check_serverhello_tlsext
+SSL,function,226,ssl_check_srvr_ecc_cert_and_alg
+SSL,function,227,ssl_cipher_process_rulestr
+SSL,function,228,ssl_cipher_strength_sort
+SSL,function,229,ssl_create_cipher_list
+SSL,function,230,ssl_ctx_log_master_secret
+SSL,function,231,ssl_ctx_log_rsa_client_key_exchange
+SSL,function,232,ssl_ctx_make_profiles
+SSL,function,233,ssl_get_new_session
+SSL,function,234,ssl_get_prev_session
+SSL,function,235,ssl_get_server_cert_index
+SSL,function,236,ssl_get_sign_pkey
+SSL,function,237,ssl_init_wbio_buffer
+SSL,function,238,ssl_parse_clienthello_renegotiate_ext
+SSL,function,239,ssl_parse_clienthello_tlsext
+SSL,function,240,ssl_parse_clienthello_use_srtp_ext
+SSL,function,241,ssl_parse_serverhello_renegotiate_ext
+SSL,function,242,ssl_parse_serverhello_tlsext
+SSL,function,243,ssl_parse_serverhello_use_srtp_ext
+SSL,function,244,ssl_scan_clienthello_tlsext
+SSL,function,245,ssl_scan_serverhello_tlsext
+SSL,function,246,ssl_sess_cert_new
+SSL,function,247,ssl_set_cert
+SSL,function,248,ssl_set_pkey
+SSL,function,252,ssl_verify_cert_chain
+SSL,function,253,tls12_check_peer_sigalg
+SSL,function,254,tls1_aead_ctx_init
+SSL,function,255,tls1_cert_verify_mac
+SSL,function,256,tls1_change_cipher_state
+SSL,function,257,tls1_change_cipher_state_aead
+SSL,function,258,tls1_check_duplicate_extensions
+SSL,function,259,tls1_enc
+SSL,function,260,tls1_export_keying_material
+SSL,function,261,tls1_prf
+SSL,function,262,tls1_setup_key_block
+SSL,reason,100,APP_DATA_IN_HANDSHAKE
+SSL,reason,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT
+SSL,reason,102,BAD_ALERT
+SSL,reason,103,BAD_CHANGE_CIPHER_SPEC
+SSL,reason,104,BAD_DATA_RETURNED_BY_CALLBACK
+SSL,reason,105,BAD_DH_P_LENGTH
+SSL,reason,106,BAD_DIGEST_LENGTH
+SSL,reason,107,BAD_ECC_CERT
+SSL,reason,108,BAD_ECPOINT
+SSL,reason,109,BAD_HANDSHAKE_LENGTH
+SSL,reason,110,BAD_HANDSHAKE_RECORD
+SSL,reason,111,BAD_HELLO_REQUEST
+SSL,reason,112,BAD_LENGTH
+SSL,reason,113,BAD_PACKET_LENGTH
+SSL,reason,114,BAD_RSA_ENCRYPT
+SSL,reason,115,BAD_SIGNATURE
+SSL,reason,116,BAD_SRTP_MKI_VALUE
+SSL,reason,117,BAD_SRTP_PROTECTION_PROFILE_LIST
+SSL,reason,118,BAD_SSL_FILETYPE
+SSL,reason,119,BAD_WRITE_RETRY
+SSL,reason,120,BIO_NOT_SET
+SSL,reason,121,BN_LIB
+SSL,reason,272,BUFFER_TOO_SMALL
+SSL,reason,122,CANNOT_SERIALIZE_PUBLIC_KEY
+SSL,reason,123,CA_DN_LENGTH_MISMATCH
+SSL,reason,124,CA_DN_TOO_LONG
+SSL,reason,125,CCS_RECEIVED_EARLY
+SSL,reason,126,CERTIFICATE_VERIFY_FAILED
+SSL,reason,127,CERT_CB_ERROR
+SSL,reason,128,CERT_LENGTH_MISMATCH
+SSL,reason,129,CHANNEL_ID_NOT_P256
+SSL,reason,130,CHANNEL_ID_SIGNATURE_INVALID
+SSL,reason,131,CIPHER_CODE_WRONG_LENGTH
+SSL,reason,132,CIPHER_OR_HASH_UNAVAILABLE
+SSL,reason,133,CLIENTHELLO_PARSE_FAILED
+SSL,reason,134,CLIENTHELLO_TLSEXT
+SSL,reason,135,CONNECTION_REJECTED
+SSL,reason,136,CONNECTION_TYPE_NOT_SET
+SSL,reason,137,COOKIE_MISMATCH
+SSL,reason,138,D2I_ECDSA_SIG
+SSL,reason,139,DATA_BETWEEN_CCS_AND_FINISHED
+SSL,reason,140,DATA_LENGTH_TOO_LONG
+SSL,reason,141,DECODE_ERROR
+SSL,reason,142,DECRYPTION_FAILED
+SSL,reason,143,DECRYPTION_FAILED_OR_BAD_RECORD_MAC
+SSL,reason,144,DH_PUBLIC_VALUE_LENGTH_IS_WRONG
+SSL,reason,145,DIGEST_CHECK_FAILED
+SSL,reason,146,DTLS_MESSAGE_TOO_BIG
+SSL,reason,147,ECC_CERT_NOT_FOR_SIGNING
+SSL,reason,148,EMPTY_SRTP_PROTECTION_PROFILE_LIST
+SSL,reason,149,ENCRYPTED_LENGTH_TOO_LONG
+SSL,reason,150,ERROR_IN_RECEIVED_CIPHER_LIST
+SSL,reason,151,EVP_DIGESTSIGNFINAL_FAILED
+SSL,reason,152,EVP_DIGESTSIGNINIT_FAILED
+SSL,reason,153,EXCESSIVE_MESSAGE_SIZE
+SSL,reason,154,EXTRA_DATA_IN_MESSAGE
+SSL,reason,271,FRAGMENT_MISMATCH
+SSL,reason,155,GOT_A_FIN_BEFORE_A_CCS
+SSL,reason,156,GOT_CHANNEL_ID_BEFORE_A_CCS
+SSL,reason,157,GOT_NEXT_PROTO_BEFORE_A_CCS
+SSL,reason,158,GOT_NEXT_PROTO_WITHOUT_EXTENSION
+SSL,reason,159,HANDSHAKE_FAILURE_ON_CLIENT_HELLO
+SSL,reason,160,HANDSHAKE_RECORD_BEFORE_CCS
+SSL,reason,161,HTTPS_PROXY_REQUEST
+SSL,reason,162,HTTP_REQUEST
+SSL,reason,163,INAPPROPRIATE_FALLBACK
+SSL,reason,164,INVALID_COMMAND
+SSL,reason,165,INVALID_MESSAGE
+SSL,reason,166,INVALID_SSL_SESSION
+SSL,reason,167,INVALID_TICKET_KEYS_LENGTH
+SSL,reason,168,LENGTH_MISMATCH
+SSL,reason,169,LIBRARY_HAS_NO_CIPHERS
+SSL,reason,170,MISSING_DH_KEY
+SSL,reason,171,MISSING_ECDSA_SIGNING_CERT
+SSL,reason,172,MISSING_RSA_CERTIFICATE
+SSL,reason,173,MISSING_RSA_ENCRYPTING_CERT
+SSL,reason,174,MISSING_RSA_SIGNING_CERT
+SSL,reason,175,MISSING_TMP_DH_KEY
+SSL,reason,176,MISSING_TMP_ECDH_KEY
+SSL,reason,177,MIXED_SPECIAL_OPERATOR_WITH_GROUPS
+SSL,reason,178,MTU_TOO_SMALL
+SSL,reason,179,NESTED_GROUP
+SSL,reason,180,NO_CERTIFICATES_RETURNED
+SSL,reason,181,NO_CERTIFICATE_ASSIGNED
+SSL,reason,182,NO_CERTIFICATE_SET
+SSL,reason,183,NO_CIPHERS_AVAILABLE
+SSL,reason,184,NO_CIPHERS_PASSED
+SSL,reason,185,NO_CIPHERS_SPECIFIED
+SSL,reason,186,NO_CIPHER_MATCH
+SSL,reason,187,NO_COMPRESSION_SPECIFIED
+SSL,reason,188,NO_METHOD_SPECIFIED
+SSL,reason,189,NO_P256_SUPPORT
+SSL,reason,190,NO_PRIVATE_KEY_ASSIGNED
+SSL,reason,191,NO_RENEGOTIATION
+SSL,reason,192,NO_REQUIRED_DIGEST
+SSL,reason,193,NO_SHARED_CIPHER
+SSL,reason,194,NO_SHARED_SIGATURE_ALGORITHMS
+SSL,reason,195,NO_SRTP_PROFILES
+SSL,reason,196,NULL_SSL_CTX
+SSL,reason,197,NULL_SSL_METHOD_PASSED
+SSL,reason,198,OLD_SESSION_CIPHER_NOT_RETURNED
+SSL,reason,273,OLD_SESSION_VERSION_NOT_RETURNED
+SSL,reason,199,PACKET_LENGTH_TOO_LONG
+SSL,reason,200,PARSE_TLSEXT
+SSL,reason,201,PATH_TOO_LONG
+SSL,reason,202,PEER_DID_NOT_RETURN_A_CERTIFICATE
+SSL,reason,203,PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE
+SSL,reason,204,PROTOCOL_IS_SHUTDOWN
+SSL,reason,205,PSK_IDENTITY_NOT_FOUND
+SSL,reason,206,PSK_NO_CLIENT_CB
+SSL,reason,207,PSK_NO_SERVER_CB
+SSL,reason,208,READ_BIO_NOT_SET
+SSL,reason,209,READ_TIMEOUT_EXPIRED
+SSL,reason,210,RECORD_LENGTH_MISMATCH
+SSL,reason,211,RECORD_TOO_LARGE
+SSL,reason,212,RENEGOTIATE_EXT_TOO_LONG
+SSL,reason,213,RENEGOTIATION_ENCODING_ERR
+SSL,reason,214,RENEGOTIATION_MISMATCH
+SSL,reason,215,REQUIRED_CIPHER_MISSING
+SSL,reason,216,SCSV_RECEIVED_WHEN_RENEGOTIATING
+SSL,reason,217,SERVERHELLO_TLSEXT
+SSL,reason,218,SESSION_ID_CONTEXT_UNINITIALIZED
+SSL,reason,219,SESSION_MAY_NOT_BE_CREATED
+SSL,reason,220,SIGNATURE_ALGORITHMS_ERROR
+SSL,reason,221,SRTP_COULD_NOT_ALLOCATE_PROFILES
+SSL,reason,222,SRTP_PROTECTION_PROFILE_LIST_TOO_LONG
+SSL,reason,223,SRTP_UNKNOWN_PROTECTION_PROFILE
+SSL,reason,224,SSL3_EXT_INVALID_SERVERNAME
+SSL,reason,225,SSL3_EXT_INVALID_SERVERNAME_TYPE
+SSL,reason,1042,SSLV3_ALERT_BAD_CERTIFICATE
+SSL,reason,1020,SSLV3_ALERT_BAD_RECORD_MAC
+SSL,reason,1045,SSLV3_ALERT_CERTIFICATE_EXPIRED
+SSL,reason,1044,SSLV3_ALERT_CERTIFICATE_REVOKED
+SSL,reason,1046,SSLV3_ALERT_CERTIFICATE_UNKNOWN
+SSL,reason,1000,SSLV3_ALERT_CLOSE_NOTIFY
+SSL,reason,1030,SSLV3_ALERT_DECOMPRESSION_FAILURE
+SSL,reason,1040,SSLV3_ALERT_HANDSHAKE_FAILURE
+SSL,reason,1047,SSLV3_ALERT_ILLEGAL_PARAMETER
+SSL,reason,1041,SSLV3_ALERT_NO_CERTIFICATE
+SSL,reason,1010,SSLV3_ALERT_UNEXPECTED_MESSAGE
+SSL,reason,1043,SSLV3_ALERT_UNSUPPORTED_CERTIFICATE
+SSL,reason,226,SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION
+SSL,reason,227,SSL_HANDSHAKE_FAILURE
+SSL,reason,228,SSL_SESSION_ID_CALLBACK_FAILED
+SSL,reason,229,SSL_SESSION_ID_CONFLICT
+SSL,reason,230,SSL_SESSION_ID_CONTEXT_TOO_LONG
+SSL,reason,231,SSL_SESSION_ID_HAS_BAD_LENGTH
+SSL,reason,1049,TLSV1_ALERT_ACCESS_DENIED
+SSL,reason,1050,TLSV1_ALERT_DECODE_ERROR
+SSL,reason,1021,TLSV1_ALERT_DECRYPTION_FAILED
+SSL,reason,1051,TLSV1_ALERT_DECRYPT_ERROR
+SSL,reason,1060,TLSV1_ALERT_EXPORT_RESTRICTION
+SSL,reason,1086,TLSV1_ALERT_INAPPROPRIATE_FALLBACK
+SSL,reason,1071,TLSV1_ALERT_INSUFFICIENT_SECURITY
+SSL,reason,1080,TLSV1_ALERT_INTERNAL_ERROR
+SSL,reason,1100,TLSV1_ALERT_NO_RENEGOTIATION
+SSL,reason,1070,TLSV1_ALERT_PROTOCOL_VERSION
+SSL,reason,1022,TLSV1_ALERT_RECORD_OVERFLOW
+SSL,reason,1048,TLSV1_ALERT_UNKNOWN_CA
+SSL,reason,1090,TLSV1_ALERT_USER_CANCELLED
+SSL,reason,1114,TLSV1_BAD_CERTIFICATE_HASH_VALUE
+SSL,reason,1113,TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE
+SSL,reason,1111,TLSV1_CERTIFICATE_UNOBTAINABLE
+SSL,reason,1112,TLSV1_UNRECOGNIZED_NAME
+SSL,reason,1110,TLSV1_UNSUPPORTED_EXTENSION
+SSL,reason,232,TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER
+SSL,reason,233,TLS_ILLEGAL_EXPORTER_LABEL
+SSL,reason,234,TLS_INVALID_ECPOINTFORMAT_LIST
+SSL,reason,235,TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST
+SSL,reason,236,TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG
+SSL,reason,237,TOO_MANY_EMPTY_FRAGMENTS
+SSL,reason,238,UNABLE_TO_FIND_ECDH_PARAMETERS
+SSL,reason,239,UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS
+SSL,reason,240,UNEXPECTED_GROUP_CLOSE
+SSL,reason,241,UNEXPECTED_MESSAGE
+SSL,reason,242,UNEXPECTED_OPERATOR_IN_GROUP
+SSL,reason,243,UNEXPECTED_RECORD
+SSL,reason,244,UNINITIALIZED
+SSL,reason,245,UNKNOWN_ALERT_TYPE
+SSL,reason,246,UNKNOWN_CERTIFICATE_TYPE
+SSL,reason,247,UNKNOWN_CIPHER_RETURNED
+SSL,reason,248,UNKNOWN_CIPHER_TYPE
+SSL,reason,249,UNKNOWN_DIGEST
+SSL,reason,250,UNKNOWN_KEY_EXCHANGE_TYPE
+SSL,reason,251,UNKNOWN_PROTOCOL
+SSL,reason,252,UNKNOWN_SSL_VERSION
+SSL,reason,253,UNKNOWN_STATE
+SSL,reason,254,UNPROCESSED_HANDSHAKE_DATA
+SSL,reason,255,UNSAFE_LEGACY_RENEGOTIATION_DISABLED
+SSL,reason,256,UNSUPPORTED_CIPHER
+SSL,reason,257,UNSUPPORTED_COMPRESSION_ALGORITHM
+SSL,reason,258,UNSUPPORTED_ELLIPTIC_CURVE
+SSL,reason,259,UNSUPPORTED_PROTOCOL
+SSL,reason,260,UNSUPPORTED_SSL_VERSION
+SSL,reason,261,USE_SRTP_NOT_NEGOTIATED
+SSL,reason,262,WRONG_CERTIFICATE_TYPE
+SSL,reason,263,WRONG_CIPHER_RETURNED
+SSL,reason,264,WRONG_CURVE
+SSL,reason,265,WRONG_MESSAGE_TYPE
+SSL,reason,266,WRONG_SIGNATURE_TYPE
+SSL,reason,267,WRONG_SSL_VERSION
+SSL,reason,268,WRONG_VERSION_NUMBER
+SSL,reason,269,X509_LIB
+SSL,reason,270,X509_VERIFICATION_SETUP_PROBLEMS
diff --git a/src/crypto/err/x509.errordata b/src/crypto/err/x509.errordata
new file mode 100644
index 0000000..1b50e36
--- /dev/null
+++ b/src/crypto/err/x509.errordata
@@ -0,0 +1,96 @@
+X509,function,100,ASN1_digest
+X509,function,101,ASN1_item_sign_ctx
+X509,function,102,ASN1_item_verify
+X509,function,103,NETSCAPE_SPKI_b64_decode
+X509,function,104,NETSCAPE_SPKI_b64_encode
+X509,function,158,PKCS7_get_CRLs
+X509,function,105,PKCS7_get_certificates
+X509,function,106,X509_ATTRIBUTE_create_by_NID
+X509,function,107,X509_ATTRIBUTE_create_by_OBJ
+X509,function,108,X509_ATTRIBUTE_create_by_txt
+X509,function,109,X509_ATTRIBUTE_get0_data
+X509,function,110,X509_ATTRIBUTE_set1_data
+X509,function,111,X509_CRL_add0_revoked
+X509,function,112,X509_CRL_diff
+X509,function,113,X509_CRL_print_fp
+X509,function,114,X509_EXTENSION_create_by_NID
+X509,function,115,X509_EXTENSION_create_by_OBJ
+X509,function,116,X509_INFO_new
+X509,function,117,X509_NAME_ENTRY_create_by_NID
+X509,function,118,X509_NAME_ENTRY_create_by_txt
+X509,function,119,X509_NAME_ENTRY_set_object
+X509,function,120,X509_NAME_add_entry
+X509,function,121,X509_NAME_oneline
+X509,function,122,X509_NAME_print
+X509,function,123,X509_PKEY_new
+X509,function,124,X509_PUBKEY_get
+X509,function,125,X509_PUBKEY_set
+X509,function,126,X509_REQ_check_private_key
+X509,function,127,X509_REQ_to_X509
+X509,function,128,X509_STORE_CTX_get1_issuer
+X509,function,129,X509_STORE_CTX_init
+X509,function,130,X509_STORE_CTX_new
+X509,function,131,X509_STORE_CTX_purpose_inherit
+X509,function,132,X509_STORE_add_cert
+X509,function,133,X509_STORE_add_crl
+X509,function,134,X509_TRUST_add
+X509,function,135,X509_TRUST_set
+X509,function,136,X509_check_private_key
+X509,function,137,X509_get_pubkey_parameters
+X509,function,138,X509_load_cert_crl_file
+X509,function,139,X509_load_cert_file
+X509,function,140,X509_load_crl_file
+X509,function,141,X509_print_ex_fp
+X509,function,142,X509_to_X509_REQ
+X509,function,143,X509_verify_cert
+X509,function,144,X509at_add1_attr
+X509,function,145,X509v3_add_ext
+X509,function,146,add_cert_dir
+X509,function,147,by_file_ctrl
+X509,function,148,check_policy
+X509,function,149,dir_ctrl
+X509,function,150,get_cert_by_subject
+X509,function,151,i2d_DSA_PUBKEY
+X509,function,152,i2d_EC_PUBKEY
+X509,function,153,i2d_RSA_PUBKEY
+X509,function,157,pkcs7_parse_header
+X509,function,154,x509_name_encode
+X509,function,155,x509_name_ex_d2i
+X509,function,156,x509_name_ex_new
+X509,reason,100,AKID_MISMATCH
+X509,reason,101,BAD_PKCS7_VERSION
+X509,reason,102,BAD_X509_FILETYPE
+X509,reason,103,BASE64_DECODE_ERROR
+X509,reason,104,CANT_CHECK_DH_KEY
+X509,reason,105,CERT_ALREADY_IN_HASH_TABLE
+X509,reason,106,CRL_ALREADY_DELTA
+X509,reason,107,CRL_VERIFY_FAILURE
+X509,reason,108,IDP_MISMATCH
+X509,reason,109,INVALID_BIT_STRING_BITS_LEFT
+X509,reason,110,INVALID_DIRECTORY
+X509,reason,111,INVALID_FIELD_NAME
+X509,reason,112,INVALID_TRUST
+X509,reason,113,ISSUER_MISMATCH
+X509,reason,114,KEY_TYPE_MISMATCH
+X509,reason,115,KEY_VALUES_MISMATCH
+X509,reason,116,LOADING_CERT_DIR
+X509,reason,117,LOADING_DEFAULTS
+X509,reason,118,METHOD_NOT_SUPPORTED
+X509,reason,119,NEWER_CRL_NOT_NEWER
+X509,reason,120,NOT_PKCS7_SIGNED_DATA
+X509,reason,121,NO_CERTIFICATES_INCLUDED
+X509,reason,122,NO_CERT_SET_FOR_US_TO_VERIFY
+X509,reason,136,NO_CRLS_INCLUDED
+X509,reason,123,NO_CRL_NUMBER
+X509,reason,124,PUBLIC_KEY_DECODE_ERROR
+X509,reason,125,PUBLIC_KEY_ENCODE_ERROR
+X509,reason,126,SHOULD_RETRY
+X509,reason,127,UNABLE_TO_FIND_PARAMETERS_IN_CHAIN
+X509,reason,128,UNABLE_TO_GET_CERTS_PUBLIC_KEY
+X509,reason,129,UNKNOWN_KEY_TYPE
+X509,reason,130,UNKNOWN_NID
+X509,reason,131,UNKNOWN_PURPOSE_ID
+X509,reason,132,UNKNOWN_TRUST_ID
+X509,reason,133,UNSUPPORTED_ALGORITHM
+X509,reason,134,WRONG_LOOKUP_TYPE
+X509,reason,135,WRONG_TYPE
diff --git a/src/crypto/err/x509v3.errordata b/src/crypto/err/x509v3.errordata
new file mode 100644
index 0000000..059e677
--- /dev/null
+++ b/src/crypto/err/x509v3.errordata
@@ -0,0 +1,120 @@
+X509V3,function,100,SXNET_add_id_INTEGER
+X509V3,function,101,SXNET_add_id_asc
+X509V3,function,102,SXNET_add_id_ulong
+X509V3,function,103,SXNET_get_id_asc
+X509V3,function,104,SXNET_get_id_ulong
+X509V3,function,105,X509V3_EXT_add
+X509V3,function,106,X509V3_EXT_add_alias
+X509V3,function,107,X509V3_EXT_free
+X509V3,function,108,X509V3_EXT_i2d
+X509V3,function,109,X509V3_EXT_nconf
+X509V3,function,110,X509V3_add1_i2d
+X509V3,function,111,X509V3_add_value
+X509V3,function,112,X509V3_get_section
+X509V3,function,113,X509V3_get_string
+X509V3,function,114,X509V3_get_value_bool
+X509V3,function,115,X509V3_parse_list
+X509V3,function,116,X509_PURPOSE_add
+X509V3,function,117,X509_PURPOSE_set
+X509V3,function,118,a2i_GENERAL_NAME
+X509V3,function,119,copy_email
+X509V3,function,120,copy_issuer
+X509V3,function,121,do_dirname
+X509V3,function,122,do_ext_i2d
+X509V3,function,123,do_ext_nconf
+X509V3,function,124,gnames_from_sectname
+X509V3,function,125,hex_to_string
+X509V3,function,126,i2s_ASN1_ENUMERATED
+X509V3,function,127,i2s_ASN1_IA5STRING
+X509V3,function,128,i2s_ASN1_INTEGER
+X509V3,function,129,i2v_AUTHORITY_INFO_ACCESS
+X509V3,function,130,notice_section
+X509V3,function,131,nref_nos
+X509V3,function,132,policy_section
+X509V3,function,133,process_pci_value
+X509V3,function,134,r2i_certpol
+X509V3,function,135,r2i_pci
+X509V3,function,136,s2i_ASN1_IA5STRING
+X509V3,function,137,s2i_ASN1_INTEGER
+X509V3,function,138,s2i_ASN1_OCTET_STRING
+X509V3,function,139,s2i_skey_id
+X509V3,function,140,set_dist_point_name
+X509V3,function,141,string_to_hex
+X509V3,function,142,v2i_ASN1_BIT_STRING
+X509V3,function,143,v2i_AUTHORITY_INFO_ACCESS
+X509V3,function,144,v2i_AUTHORITY_KEYID
+X509V3,function,145,v2i_BASIC_CONSTRAINTS
+X509V3,function,146,v2i_EXTENDED_KEY_USAGE
+X509V3,function,147,v2i_GENERAL_NAMES
+X509V3,function,148,v2i_GENERAL_NAME_ex
+X509V3,function,149,v2i_NAME_CONSTRAINTS
+X509V3,function,150,v2i_POLICY_CONSTRAINTS
+X509V3,function,151,v2i_POLICY_MAPPINGS
+X509V3,function,152,v2i_crld
+X509V3,function,153,v2i_idp
+X509V3,function,154,v2i_issuer_alt
+X509V3,function,155,v2i_subject_alt
+X509V3,function,156,v3_generic_extension
+X509V3,reason,100,BAD_IP_ADDRESS
+X509V3,reason,101,BAD_OBJECT
+X509V3,reason,102,BN_DEC2BN_ERROR
+X509V3,reason,103,BN_TO_ASN1_INTEGER_ERROR
+X509V3,reason,104,CANNOT_FIND_FREE_FUNCTION
+X509V3,reason,105,DIRNAME_ERROR
+X509V3,reason,106,DISTPOINT_ALREADY_SET
+X509V3,reason,107,DUPLICATE_ZONE_ID
+X509V3,reason,108,ERROR_CONVERTING_ZONE
+X509V3,reason,109,ERROR_CREATING_EXTENSION
+X509V3,reason,110,ERROR_IN_EXTENSION
+X509V3,reason,111,EXPECTED_A_SECTION_NAME
+X509V3,reason,112,EXTENSION_EXISTS
+X509V3,reason,113,EXTENSION_NAME_ERROR
+X509V3,reason,114,EXTENSION_NOT_FOUND
+X509V3,reason,115,EXTENSION_SETTING_NOT_SUPPORTED
+X509V3,reason,116,EXTENSION_VALUE_ERROR
+X509V3,reason,117,ILLEGAL_EMPTY_EXTENSION
+X509V3,reason,118,ILLEGAL_HEX_DIGIT
+X509V3,reason,119,INCORRECT_POLICY_SYNTAX_TAG
+X509V3,reason,120,INVALID_BOOLEAN_STRING
+X509V3,reason,121,INVALID_EXTENSION_STRING
+X509V3,reason,122,INVALID_MULTIPLE_RDNS
+X509V3,reason,123,INVALID_NAME
+X509V3,reason,124,INVALID_NULL_ARGUMENT
+X509V3,reason,125,INVALID_NULL_NAME
+X509V3,reason,126,INVALID_NULL_VALUE
+X509V3,reason,127,INVALID_NUMBER
+X509V3,reason,128,INVALID_NUMBERS
+X509V3,reason,129,INVALID_OBJECT_IDENTIFIER
+X509V3,reason,130,INVALID_OPTION
+X509V3,reason,131,INVALID_POLICY_IDENTIFIER
+X509V3,reason,132,INVALID_PROXY_POLICY_SETTING
+X509V3,reason,133,INVALID_PURPOSE
+X509V3,reason,134,INVALID_SECTION
+X509V3,reason,135,INVALID_SYNTAX
+X509V3,reason,136,ISSUER_DECODE_ERROR
+X509V3,reason,137,MISSING_VALUE
+X509V3,reason,138,NEED_ORGANIZATION_AND_NUMBERS
+X509V3,reason,139,NO_CONFIG_DATABASE
+X509V3,reason,140,NO_ISSUER_CERTIFICATE
+X509V3,reason,141,NO_ISSUER_DETAILS
+X509V3,reason,142,NO_POLICY_IDENTIFIER
+X509V3,reason,143,NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED
+X509V3,reason,144,NO_PUBLIC_KEY
+X509V3,reason,145,NO_SUBJECT_DETAILS
+X509V3,reason,146,ODD_NUMBER_OF_DIGITS
+X509V3,reason,147,OPERATION_NOT_DEFINED
+X509V3,reason,148,OTHERNAME_ERROR
+X509V3,reason,149,POLICY_LANGUAGE_ALREADY_DEFINED
+X509V3,reason,150,POLICY_PATH_LENGTH
+X509V3,reason,151,POLICY_PATH_LENGTH_ALREADY_DEFINED
+X509V3,reason,152,POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY
+X509V3,reason,153,SECTION_NOT_FOUND
+X509V3,reason,154,UNABLE_TO_GET_ISSUER_DETAILS
+X509V3,reason,155,UNABLE_TO_GET_ISSUER_KEYID
+X509V3,reason,156,UNKNOWN_BIT_STRING_ARGUMENT
+X509V3,reason,157,UNKNOWN_EXTENSION
+X509V3,reason,158,UNKNOWN_EXTENSION_NAME
+X509V3,reason,159,UNKNOWN_OPTION
+X509V3,reason,160,UNSUPPORTED_OPTION
+X509V3,reason,161,UNSUPPORTED_TYPE
+X509V3,reason,162,USER_TOO_LONG
diff --git a/src/crypto/evp/CMakeLists.txt b/src/crypto/evp/CMakeLists.txt
index 9854a18..6db9752 100644
--- a/src/crypto/evp/CMakeLists.txt
+++ b/src/crypto/evp/CMakeLists.txt
@@ -10,7 +10,7 @@ add_library(
digestsign.c
evp.c
evp_ctx.c
- evp_error.c
+ p_dsa_asn1.c
p_ec.c
p_ec_asn1.c
p_hmac.c
@@ -23,16 +23,24 @@ add_library(
add_executable(
+ evp_extra_test
+
+ evp_extra_test.cc
+)
+
+add_executable(
evp_test
- evp_test.c
+ evp_test.cc
+ $<TARGET_OBJECTS:test_support>
)
add_executable(
pbkdf_test
- pbkdf_test.c
+ pbkdf_test.cc
)
+target_link_libraries(evp_extra_test crypto)
target_link_libraries(evp_test crypto)
target_link_libraries(pbkdf_test crypto)
diff --git a/src/crypto/evp/asn1.c b/src/crypto/evp/asn1.c
index 27ae017..3df9f52 100644
--- a/src/crypto/evp/asn1.c
+++ b/src/crypto/evp/asn1.c
@@ -105,7 +105,7 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
return ret;
err:
- if (ret != NULL && (out == NULL || *out != ret)) {
+ if (out == NULL || *out != ret) {
EVP_PKEY_free(ret);
}
return NULL;
diff --git a/src/crypto/evp/digestsign.c b/src/crypto/evp/digestsign.c
index c86b805..c163d40 100644
--- a/src/crypto/evp/digestsign.c
+++ b/src/crypto/evp/digestsign.c
@@ -65,9 +65,8 @@
/* md_begin_digset is a callback from the |EVP_MD_CTX| code that is called when
* a new digest is begun. */
static int md_begin_digest(EVP_MD_CTX *ctx) {
- int r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
- EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
- return r > 0 || r == -2;
+ return EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
}
static const struct evp_md_pctx_ops md_pctx_ops = {
@@ -98,24 +97,24 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
if (is_verify) {
if (ctx->pctx->pmeth->verifyctx_init) {
- if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <= 0) {
+ if (!ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx)) {
return 0;
}
ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX;
- } else if (EVP_PKEY_verify_init(ctx->pctx) <= 0) {
+ } else if (!EVP_PKEY_verify_init(ctx->pctx)) {
return 0;
}
} else {
if (ctx->pctx->pmeth->signctx_init) {
- if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0) {
+ if (!ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx)) {
return 0;
}
ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX;
- } else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) {
+ } else if (!EVP_PKEY_sign_init(ctx->pctx)) {
return 0;
}
}
- if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0) {
+ if (!EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) {
return 0;
}
if (pctx) {
@@ -163,12 +162,12 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx, out_sig, out_sig_len, &tmp_ctx);
} else {
r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
+ if (r) {
+ r = EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
+ }
}
EVP_MD_CTX_cleanup(&tmp_ctx);
- if (has_signctx || !r) {
- return r;
- }
- return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
+ return r;
} else {
if (has_signctx) {
return ctx->pctx->pmeth->signctx(ctx->pctx, out_sig, out_sig_len, ctx);
@@ -185,21 +184,21 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
uint8_t md[EVP_MAX_MD_SIZE];
int r;
unsigned int mdlen;
- const int has_verifyctx = ctx->pctx->pmeth->verifyctx != NULL;
EVP_MD_CTX_init(&tmp_ctx);
if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) {
return 0;
}
- if (has_verifyctx) {
+ if (ctx->pctx->pmeth->verifyctx) {
r = tmp_ctx.pctx->pmeth->verifyctx(tmp_ctx.pctx, sig, sig_len, &tmp_ctx);
} else {
r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
+ if (r) {
+ r = EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen);
+ }
}
EVP_MD_CTX_cleanup(&tmp_ctx);
- if (has_verifyctx || !r) {
- return r;
- }
- return EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen);
+
+ return r;
}
diff --git a/src/crypto/evp/evp.c b/src/crypto/evp/evp.c
index 8a1d513..58fd9a9 100644
--- a/src/crypto/evp/evp.c
+++ b/src/crypto/evp/evp.c
@@ -67,10 +67,12 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/rsa.h>
+#include <openssl/thread.h>
#include "internal.h"
+extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth;
@@ -109,15 +111,14 @@ void EVP_PKEY_free(EVP_PKEY *pkey) {
}
free_it(pkey);
- if (pkey->attributes) {
- /* TODO(fork): layering: X509_ATTRIBUTE_free is an X.509 function. In
- * practice this path isn't called but should be removed in the future. */
- /*sk_X509_ATTRIBUTE_pop_free(pkey->attributes, X509_ATTRIBUTE_free);*/
- assert(0);
- }
OPENSSL_free(pkey);
}
+EVP_PKEY *EVP_PKEY_up_ref(EVP_PKEY *pkey) {
+ CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+ return pkey;
+}
+
int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
if (pkey->ameth && pkey->ameth->pkey_opaque) {
return pkey->ameth->pkey_opaque(pkey);
@@ -142,8 +143,9 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
/* Compare parameters if the algorithm has them */
if (a->ameth->param_cmp) {
ret = a->ameth->param_cmp(a, b);
- if (ret <= 0)
+ if (ret <= 0) {
return ret;
+ }
}
if (a->ameth->pub_cmp) {
@@ -154,11 +156,6 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
return -2;
}
-EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey) {
- CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
- return pkey;
-}
-
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
if (to->type != from->type) {
OPENSSL_PUT_ERROR(EVP, EVP_PKEY_copy_parameters, EVP_R_DIFFERENT_KEY_TYPES);
@@ -213,6 +210,8 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine, int nid) {
return &hmac_asn1_meth;
case EVP_PKEY_EC:
return &ec_asn1_meth;
+ case EVP_PKEY_DSA:
+ return &dsa_asn1_meth;
default:
return NULL;
}
@@ -236,18 +235,19 @@ EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, const uint8_t *mac_key,
return NULL;
}
- if (EVP_PKEY_keygen_init(mac_ctx) <= 0 ||
- EVP_PKEY_CTX_ctrl(mac_ctx, -1, EVP_PKEY_OP_KEYGEN,
- EVP_PKEY_CTRL_SET_MAC_KEY, mac_key_len,
- (uint8_t *)mac_key) <= 0 ||
- EVP_PKEY_keygen(mac_ctx, &ret) <= 0) {
+ if (!EVP_PKEY_keygen_init(mac_ctx) ||
+ !EVP_PKEY_CTX_ctrl(mac_ctx, -1, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_SET_MAC_KEY, mac_key_len,
+ (uint8_t *)mac_key) ||
+ !EVP_PKEY_keygen(mac_ctx, &ret)) {
ret = NULL;
goto merr;
}
merr:
- if (mac_ctx)
+ if (mac_ctx) {
EVP_PKEY_CTX_free(mac_ctx);
+ }
return ret;
}
@@ -323,7 +323,7 @@ int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) {
}
int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key) {
- return EVP_PKEY_assign(pkey, EVP_PKEY_EC, key);
+ return EVP_PKEY_assign(pkey, EVP_PKEY_DH, key);
}
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) {
@@ -435,6 +435,10 @@ int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
0, (void *)out_md);
}
+EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey) {
+ return EVP_PKEY_up_ref(pkey);
+}
+
void OpenSSL_add_all_algorithms(void) {}
void EVP_cleanup(void) {}
diff --git a/src/crypto/evp/evp_ctx.c b/src/crypto/evp/evp_ctx.c
index a383725..9f42274 100644
--- a/src/crypto/evp/evp_ctx.c
+++ b/src/crypto/evp/evp_ctx.c
@@ -120,14 +120,12 @@ static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) {
ret->operation = EVP_PKEY_OP_UNDEFINED;
if (pkey) {
- ret->pkey = EVP_PKEY_dup(pkey);
+ ret->pkey = EVP_PKEY_up_ref(pkey);
}
if (pmeth->init) {
if (pmeth->init(ret) <= 0) {
- if (pkey) {
- EVP_PKEY_free(ret->pkey);
- }
+ EVP_PKEY_free(ret->pkey);
OPENSSL_free(ret);
return NULL;
}
@@ -151,12 +149,8 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) {
if (ctx->pmeth && ctx->pmeth->cleanup) {
ctx->pmeth->cleanup(ctx);
}
- if (ctx->pkey) {
- EVP_PKEY_free(ctx->pkey);
- }
- if (ctx->peerkey) {
- EVP_PKEY_free(ctx->peerkey);
- }
+ EVP_PKEY_free(ctx->pkey);
+ EVP_PKEY_free(ctx->peerkey);
OPENSSL_free(ctx);
}
@@ -179,14 +173,14 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) {
rctx->operation = pctx->operation;
if (pctx->pkey) {
- rctx->pkey = EVP_PKEY_dup(pctx->pkey);
+ rctx->pkey = EVP_PKEY_up_ref(pctx->pkey);
if (rctx->pkey == NULL) {
goto err;
}
}
if (pctx->peerkey) {
- rctx->peerkey = EVP_PKEY_dup(pctx->peerkey);
+ rctx->peerkey = EVP_PKEY_up_ref(pctx->peerkey);
if (rctx->peerkey == NULL) {
goto err;
}
@@ -212,32 +206,25 @@ void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx) { return ctx->app_data; }
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd,
int p1, void *p2) {
- int ret;
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_ctrl, EVP_R_COMMAND_NOT_SUPPORTED);
- return -2;
+ return 0;
}
if (keytype != -1 && ctx->pmeth->pkey_id != keytype) {
- return -1;
+ return 0;
}
if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_ctrl, EVP_R_NO_OPERATION_SET);
- return -1;
+ return 0;
}
if (optype != -1 && !(ctx->operation & optype)) {
OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_ctrl, EVP_R_INVALID_OPERATION);
- return -1;
- }
-
- ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
-
- if (ret == -2) {
- OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_ctrl, EVP_R_COMMAND_NOT_SUPPORTED);
+ return 0;
}
- return ret;
+ return ctx->pmeth->ctrl(ctx, cmd, p1, p2);
}
int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) {
@@ -434,9 +421,7 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) {
return 0;
}
- if (ctx->peerkey) {
- EVP_PKEY_free(ctx->peerkey);
- }
+ EVP_PKEY_free(ctx->peerkey);
ctx->peerkey = peer;
ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
@@ -446,7 +431,7 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) {
return 0;
}
- EVP_PKEY_dup(peer);
+ EVP_PKEY_up_ref(peer);
return 1;
}
diff --git a/src/crypto/evp/evp_error.c b/src/crypto/evp/evp_error.c
deleted file mode 100644
index b0d311e..0000000
--- a/src/crypto/evp/evp_error.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/* 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/evp.h>
-
-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"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_derive, 0), "EVP_PKEY_derive"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_derive_init, 0), "EVP_PKEY_derive_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_derive_set_peer, 0), "EVP_PKEY_derive_set_peer"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_encrypt, 0), "EVP_PKEY_encrypt"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_encrypt_init, 0), "EVP_PKEY_encrypt_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_get1_DH, 0), "EVP_PKEY_get1_DH"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_get1_DSA, 0), "EVP_PKEY_get1_DSA"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_get1_EC_KEY, 0), "EVP_PKEY_get1_EC_KEY"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_get1_RSA, 0), "EVP_PKEY_get1_RSA"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_keygen, 0), "EVP_PKEY_keygen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_keygen_init, 0), "EVP_PKEY_keygen_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_new, 0), "EVP_PKEY_new"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_set_type, 0), "EVP_PKEY_set_type"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_sign, 0), "EVP_PKEY_sign"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_sign_init, 0), "EVP_PKEY_sign_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_verify, 0), "EVP_PKEY_verify"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_verify_init, 0), "EVP_PKEY_verify_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_check_padding_md, 0), "check_padding_md"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_d2i_AutoPrivateKey, 0), "d2i_AutoPrivateKey"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_d2i_PrivateKey, 0), "d2i_PrivateKey"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_do_EC_KEY_print, 0), "do_EC_KEY_print"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_do_rsa_print, 0), "do_rsa_print"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_do_sigver_init, 0), "do_sigver_init"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_param2type, 0), "eckey_param2type"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_param_decode, 0), "eckey_param_decode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_priv_decode, 0), "eckey_priv_decode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_priv_encode, 0), "eckey_priv_encode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_pub_decode, 0), "eckey_pub_decode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_pub_encode, 0), "eckey_pub_encode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_type2param, 0), "eckey_type2param"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_evp_pkey_ctx_new, 0), "evp_pkey_ctx_new"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_hmac_signctx, 0), "hmac_signctx"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_i2d_PublicKey, 0), "i2d_PublicKey"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_old_ec_priv_decode, 0), "old_ec_priv_decode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_old_rsa_priv_decode, 0), "old_rsa_priv_decode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_ctrl, 0), "pkey_ec_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_derive, 0), "pkey_ec_derive"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_keygen, 0), "pkey_ec_keygen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_paramgen, 0), "pkey_ec_paramgen"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_sign, 0), "pkey_ec_sign"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_rsa_ctrl, 0), "pkey_rsa_ctrl"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_rsa_decrypt, 0), "pkey_rsa_decrypt"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_rsa_encrypt, 0), "pkey_rsa_encrypt"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_rsa_sign, 0), "pkey_rsa_sign"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_algor_to_md, 0), "rsa_algor_to_md"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_digest_verify_init_from_algorithm, 0), "rsa_digest_verify_init_from_algorithm"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_item_verify, 0), "rsa_item_verify"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_mgf1_to_md, 0), "rsa_mgf1_to_md"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_priv_decode, 0), "rsa_priv_decode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_priv_encode, 0), "rsa_priv_encode"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_pss_to_ctx, 0), "rsa_pss_to_ctx"},
- {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_pub_decode, 0), "rsa_pub_decode"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COMMAND_NOT_SUPPORTED), "COMMAND_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR), "DECODE_ERROR"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_KEY_TYPES), "DIFFERENT_KEY_TYPES"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_PARAMETERS), "DIFFERENT_PARAMETERS"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED), "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIGEST_DOES_NOT_MATCH), "DIGEST_DOES_NOT_MATCH"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_DSA_KEY), "EXPECTING_AN_DSA_KEY"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_EC_KEY_KEY), "EXPECTING_AN_EC_KEY_KEY"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY), "EXPECTING_AN_RSA_KEY"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DH_KEY), "EXPECTING_A_DH_KEY"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DSA_KEY), "EXPECTING_A_DSA_KEY"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPLICIT_EC_PARAMETERS_NOT_SUPPORTED), "EXPLICIT_EC_PARAMETERS_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_CURVE), "INVALID_CURVE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST_LENGTH), "INVALID_DIGEST_LENGTH"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST_TYPE), "INVALID_DIGEST_TYPE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEYBITS), "INVALID_KEYBITS"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_MGF1_MD), "INVALID_MGF1_MD"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "INVALID_OPERATION"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PADDING_MODE), "INVALID_PADDING_MODE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PSS_PARAMETERS), "INVALID_PSS_PARAMETERS"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PSS_SALTLEN), "INVALID_PSS_SALTLEN"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH), "INVALID_SALT_LENGTH"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_TRAILER), "INVALID_TRAILER"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KDF_PARAMETER_ERROR), "KDF_PARAMETER_ERROR"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYS_NOT_SET), "KEYS_NOT_SET"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "NO_DEFAULT_DIGEST"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEY_SET), "NO_KEY_SET"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_MDC2_SUPPORT), "NO_MDC2_SUPPORT"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_NID_FOR_CURVE), "NO_NID_FOR_CURVE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_OPERATION_SET), "NO_OPERATION_SET"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_PARAMETERS_SET), "NO_PARAMETERS_SET"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATON_NOT_INITIALIZED), "OPERATON_NOT_INITIALIZED"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PEER_KEY_ERROR), "PEER_KEY_ERROR"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SHARED_INFO_ERROR), "SHARED_INFO_ERROR"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "UNKNOWN_DIGEST"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_MASK_DIGEST), "UNKNOWN_MASK_DIGEST"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM), "UNKNOWN_MESSAGE_DIGEST_ALGORITHM"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE), "UNKNOWN_PUBLIC_KEY_TYPE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_SIGNATURE_ALGORITHM), "UNKNOWN_SIGNATURE_ALGORITHM"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_ALGORITHM), "UNSUPPORTED_ALGORITHM"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_MASK_ALGORITHM), "UNSUPPORTED_MASK_ALGORITHM"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_MASK_PARAMETER), "UNSUPPORTED_MASK_PARAMETER"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "UNSUPPORTED_PUBLIC_KEY_TYPE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_SIGNATURE_TYPE), "UNSUPPORTED_SIGNATURE_TYPE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_PUBLIC_KEY_TYPE), "WRONG_PUBLIC_KEY_TYPE"},
- {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_X931_UNSUPPORTED), "X931_UNSUPPORTED"},
- {0, NULL},
-};
diff --git a/src/crypto/evp/evp_test.c b/src/crypto/evp/evp_extra_test.cc
index 3e74cd5..674547d 100644
--- a/src/crypto/evp/evp_test.c
+++ b/src/crypto/evp/evp_extra_test.cc
@@ -16,7 +16,8 @@
#include <stdio.h>
#include <stdlib.h>
-#include <openssl/bio.h>
+#include <vector>
+
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
@@ -25,9 +26,11 @@
#include <openssl/rsa.h>
#include <openssl/x509.h>
+#include "../test/scoped_types.h"
+
-/* kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
- * should never use this key anywhere but in an example. */
+// kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
+// should never use this key anywhere but in an example.
static const uint8_t kExampleRSAKeyDER[] = {
0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xf8,
0xb8, 0x6c, 0x83, 0xb4, 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59,
@@ -82,6 +85,81 @@ static const uint8_t kExampleRSAKeyDER[] = {
0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf,
};
+static const uint8_t kExampleDSAKeyDER[] = {
+ 0x30, 0x82, 0x03, 0x56, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0x9e, 0x12, 0xfa, 0xb3, 0xde, 0x12, 0x21, 0x35, 0x01, 0xdd, 0x82, 0xaa,
+ 0x10, 0xca, 0x2d, 0x10, 0x1d, 0x2d, 0x4e, 0xbf, 0xef, 0x4d, 0x2a, 0x3f,
+ 0x8d, 0xaa, 0x0f, 0xe0, 0xce, 0xda, 0xd8, 0xd6, 0xaf, 0x85, 0x61, 0x6a,
+ 0xa2, 0xf3, 0x25, 0x2c, 0x0a, 0x2b, 0x5a, 0x6d, 0xb0, 0x9e, 0x6f, 0x14,
+ 0x90, 0x0e, 0x0d, 0xdb, 0x83, 0x11, 0x87, 0x6d, 0xd8, 0xf9, 0x66, 0x95,
+ 0x25, 0xf9, 0x9e, 0xd6, 0x59, 0x49, 0xe1, 0x84, 0xd5, 0x06, 0x47, 0x93,
+ 0x27, 0x11, 0x69, 0xa2, 0x28, 0x68, 0x0b, 0x95, 0xec, 0x12, 0xf5, 0x9a,
+ 0x8e, 0x20, 0xb2, 0x1f, 0x2b, 0x58, 0xeb, 0x2a, 0x20, 0x12, 0xd3, 0x5b,
+ 0xde, 0x2e, 0xe3, 0x51, 0x82, 0x2f, 0xe8, 0xf3, 0x2d, 0x0a, 0x33, 0x05,
+ 0x65, 0xdc, 0xce, 0x5c, 0x67, 0x2b, 0x72, 0x59, 0xc1, 0x4b, 0x24, 0x33,
+ 0xd0, 0xb5, 0xb2, 0xca, 0x2b, 0x2d, 0xb0, 0xab, 0x62, 0x6e, 0x8f, 0x13,
+ 0xf4, 0x7f, 0xe0, 0x34, 0x5d, 0x90, 0x4e, 0x72, 0x94, 0xbb, 0x03, 0x8e,
+ 0x9c, 0xe2, 0x1a, 0x9e, 0x58, 0x0b, 0x83, 0x35, 0x62, 0x78, 0x70, 0x6c,
+ 0xfe, 0x76, 0x84, 0x36, 0xc6, 0x9d, 0xe1, 0x49, 0xcc, 0xff, 0x98, 0xb4,
+ 0xaa, 0xb8, 0xcb, 0x4f, 0x63, 0x85, 0xc9, 0xf1, 0x02, 0xce, 0x59, 0x34,
+ 0x6e, 0xae, 0xef, 0x27, 0xe0, 0xad, 0x22, 0x2d, 0x53, 0xd6, 0xe8, 0x9c,
+ 0xc8, 0xcd, 0xe5, 0x77, 0x6d, 0xd0, 0x00, 0x57, 0xb0, 0x3f, 0x2d, 0x88,
+ 0xab, 0x3c, 0xed, 0xba, 0xfd, 0x7b, 0x58, 0x5f, 0x0b, 0x7f, 0x78, 0x35,
+ 0xe1, 0x7a, 0x37, 0x28, 0xbb, 0xf2, 0x5e, 0xa6, 0x25, 0x72, 0xf2, 0x45,
+ 0xdc, 0x11, 0x1f, 0x3c, 0xe3, 0x9c, 0xb6, 0xff, 0xac, 0xc3, 0x1b, 0x0a,
+ 0x27, 0x90, 0xe7, 0xbd, 0xe9, 0x02, 0x24, 0xea, 0x9b, 0x09, 0x31, 0x53,
+ 0x62, 0xaf, 0x3d, 0x2b, 0x02, 0x21, 0x00, 0xf3, 0x81, 0xdc, 0xf5, 0x3e,
+ 0xbf, 0x72, 0x4f, 0x8b, 0x2e, 0x5c, 0xa8, 0x2c, 0x01, 0x0f, 0xb4, 0xb5,
+ 0xed, 0xa9, 0x35, 0x8d, 0x0f, 0xd8, 0x8e, 0xd2, 0x78, 0x58, 0x94, 0x88,
+ 0xb5, 0x4f, 0xc3, 0x02, 0x82, 0x01, 0x00, 0x0c, 0x40, 0x2a, 0x72, 0x5d,
+ 0xcc, 0x3a, 0x62, 0xe0, 0x2b, 0xf4, 0xcf, 0x43, 0xcd, 0x17, 0xf4, 0xa4,
+ 0x93, 0x59, 0x12, 0x20, 0x22, 0x36, 0x69, 0xcf, 0x41, 0x93, 0xed, 0xab,
+ 0x42, 0x3a, 0xd0, 0x8d, 0xfb, 0x55, 0x2e, 0x30, 0x8a, 0x6a, 0x57, 0xa5,
+ 0xff, 0xbc, 0x7c, 0xd0, 0xfb, 0x20, 0x87, 0xf8, 0x1f, 0x8d, 0xf0, 0xcb,
+ 0x08, 0xab, 0x21, 0x33, 0x28, 0x7d, 0x2b, 0x69, 0x68, 0x71, 0x4a, 0x94,
+ 0xf6, 0x33, 0xc9, 0x40, 0x84, 0x5a, 0x48, 0xa3, 0xe1, 0x67, 0x08, 0xdd,
+ 0xe7, 0x61, 0xcc, 0x6a, 0x8e, 0xab, 0x2d, 0x84, 0xdb, 0x21, 0xb6, 0xea,
+ 0x5b, 0x07, 0x68, 0x14, 0x93, 0xcc, 0x9c, 0x31, 0xfb, 0xc3, 0x68, 0xb2,
+ 0x43, 0xf6, 0xdd, 0xf8, 0xc9, 0x32, 0xa8, 0xb4, 0x03, 0x8f, 0x44, 0xe7,
+ 0xb1, 0x5c, 0xa8, 0x76, 0x34, 0x4a, 0x14, 0x78, 0x59, 0xf2, 0xb4, 0x3b,
+ 0x39, 0x45, 0x86, 0x68, 0xad, 0x5e, 0x0a, 0x1a, 0x9a, 0x66, 0x95, 0x46,
+ 0xdd, 0x28, 0x12, 0xe3, 0xb3, 0x61, 0x7a, 0x0a, 0xef, 0x99, 0xd5, 0x8e,
+ 0x3b, 0xb4, 0xcc, 0x87, 0xfd, 0x94, 0x22, 0x5e, 0x01, 0xd2, 0xdc, 0xc4,
+ 0x69, 0xa7, 0x72, 0x68, 0x14, 0x6c, 0x51, 0x91, 0x8f, 0x18, 0xe8, 0xb4,
+ 0xd7, 0x0a, 0xa1, 0xf0, 0xc7, 0x62, 0x3b, 0xcc, 0x52, 0xcf, 0x37, 0x31,
+ 0xd3, 0x86, 0x41, 0xb2, 0xd2, 0x83, 0x0b, 0x7e, 0xec, 0xb2, 0xf0, 0x95,
+ 0x52, 0xff, 0x13, 0x7d, 0x04, 0x6e, 0x49, 0x4e, 0x7f, 0x33, 0xc3, 0x59,
+ 0x00, 0x02, 0xb1, 0x6d, 0x1b, 0x97, 0xd9, 0x36, 0xfd, 0xa2, 0x8f, 0x90,
+ 0xc3, 0xed, 0x3c, 0xa3, 0x53, 0x38, 0x16, 0x8a, 0xc1, 0x6f, 0x77, 0xc3,
+ 0xc5, 0x7a, 0xdc, 0x2e, 0x8f, 0x7c, 0x6c, 0x22, 0x56, 0xe4, 0x1a, 0x5f,
+ 0x65, 0x45, 0x05, 0x90, 0xdb, 0xb5, 0xbc, 0xf0, 0x6d, 0x66, 0x61, 0x02,
+ 0x82, 0x01, 0x00, 0x31, 0x97, 0x31, 0xa1, 0x4e, 0x38, 0x56, 0x88, 0xdb,
+ 0x94, 0x1d, 0xbf, 0x65, 0x5c, 0xda, 0x4b, 0xc2, 0x10, 0xde, 0x74, 0x20,
+ 0x03, 0xce, 0x13, 0x60, 0xf2, 0x25, 0x1d, 0x55, 0x7c, 0x5d, 0x94, 0x82,
+ 0x54, 0x08, 0x53, 0xdb, 0x85, 0x95, 0xbf, 0xdd, 0x5e, 0x50, 0xd5, 0x96,
+ 0xe0, 0x79, 0x51, 0x1b, 0xbf, 0x4d, 0x4e, 0xb9, 0x3a, 0xc5, 0xee, 0xc4,
+ 0x5e, 0x98, 0x75, 0x7b, 0xbe, 0xff, 0x30, 0xe6, 0xd0, 0x7b, 0xa6, 0xf1,
+ 0xbc, 0x29, 0xea, 0xdf, 0xec, 0xf3, 0x8b, 0xfa, 0x83, 0x11, 0x9f, 0x3f,
+ 0xf0, 0x5d, 0x06, 0x51, 0x32, 0xaa, 0x21, 0xfc, 0x26, 0x17, 0xe7, 0x50,
+ 0xc2, 0x16, 0xba, 0xfa, 0x54, 0xb7, 0x7e, 0x1d, 0x2c, 0xa6, 0xa3, 0x41,
+ 0x66, 0x33, 0x94, 0x83, 0xb9, 0xbf, 0xa0, 0x4f, 0xbd, 0xa6, 0xfd, 0x2c,
+ 0x81, 0x58, 0x35, 0x33, 0x39, 0xc0, 0x6d, 0x33, 0x40, 0x56, 0x64, 0x12,
+ 0x5a, 0xcd, 0x35, 0x53, 0x21, 0x78, 0x8f, 0x27, 0x24, 0x37, 0x66, 0x8a,
+ 0xdf, 0x5e, 0x5f, 0x63, 0xfc, 0x8b, 0x2d, 0xef, 0x57, 0xdb, 0x40, 0x25,
+ 0xd5, 0x17, 0x53, 0x0b, 0xe4, 0xa5, 0xae, 0x54, 0xbf, 0x46, 0x4f, 0xa6,
+ 0x79, 0xc3, 0x74, 0xfa, 0x1f, 0x85, 0x34, 0x64, 0x6d, 0xc5, 0x03, 0xeb,
+ 0x72, 0x98, 0x80, 0x7b, 0xc0, 0x8f, 0x35, 0x11, 0xa7, 0x09, 0xeb, 0x51,
+ 0xe0, 0xb0, 0xac, 0x92, 0x14, 0xf2, 0xad, 0x37, 0x95, 0x5a, 0xba, 0x8c,
+ 0xc4, 0xdb, 0xed, 0xc4, 0x4e, 0x8b, 0x8f, 0x84, 0x33, 0x64, 0xf8, 0x57,
+ 0x12, 0xd7, 0x08, 0x7e, 0x90, 0x66, 0xdf, 0x91, 0x50, 0x23, 0xf2, 0x73,
+ 0xc0, 0x6b, 0xb1, 0x15, 0xdd, 0x64, 0xd7, 0xc9, 0x75, 0x17, 0x73, 0x72,
+ 0xda, 0x33, 0xc4, 0x6f, 0xa5, 0x47, 0xa1, 0xcc, 0xd1, 0xc6, 0x62, 0xe5,
+ 0xca, 0xab, 0x5f, 0x2a, 0x8f, 0x6b, 0xcc, 0x02, 0x21, 0x00, 0xb0, 0xc7,
+ 0x68, 0x70, 0x27, 0x43, 0xbc, 0x51, 0x24, 0x29, 0x93, 0xa9, 0x71, 0xa5,
+ 0x28, 0x89, 0x79, 0x54, 0x44, 0xf7, 0xc6, 0x45, 0x22, 0x03, 0xd0, 0xce,
+ 0x84, 0xfe, 0x61, 0x17, 0xd4, 0x6e,
+};
+
static const uint8_t kMsg[] = {1, 2, 3, 4};
static const uint8_t kSignature[] = {
@@ -98,8 +176,8 @@ static const uint8_t kSignature[] = {
0x55, 0xa7, 0xab, 0x45, 0x02, 0x97, 0x60, 0x42,
};
-/* kExamplePSSCert is an example self-signed certificate, signed with
- * kExampleRSAKeyDER using RSA-PSS with default hash functions. */
+// kExamplePSSCert is an example self-signed certificate, signed with
+// kExampleRSAKeyDER using RSA-PSS with default hash functions.
static const uint8_t kExamplePSSCert[] = {
0x30, 0x82, 0x02, 0x62, 0x30, 0x82, 0x01, 0xc6, 0xa0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x09, 0x00, 0x8d, 0xea, 0x53, 0x24, 0xfa, 0x48, 0x87, 0xf3,
@@ -155,8 +233,8 @@ static const uint8_t kExamplePSSCert[] = {
0x8c, 0x16,
};
-/* kExampleRSAKeyPKCS8 is kExampleRSAKeyDER encoded in a PKCS #8
- * PrivateKeyInfo. */
+// kExampleRSAKeyPKCS8 is kExampleRSAKeyDER encoded in a PKCS #8
+// PrivateKeyInfo.
static const uint8_t kExampleRSAKeyPKCS8[] = {
0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
@@ -213,8 +291,8 @@ static const uint8_t kExampleRSAKeyPKCS8[] = {
0x08, 0xf1, 0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf,
};
-/* kExampleECKeyDER is a sample EC private key encoded as an ECPrivateKey
- * structure. */
+// kExampleECKeyDER is a sample EC private key encoded as an ECPrivateKey
+// structure.
static const uint8_t kExampleECKeyDER[] = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x07, 0x0f, 0x08, 0x72, 0x7a,
0xd4, 0xa0, 0x4a, 0x9c, 0xdd, 0x59, 0xc9, 0x4d, 0x89, 0x68, 0x77, 0x08,
@@ -229,8 +307,8 @@ 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 */
+// 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,
@@ -243,237 +321,143 @@ static const uint8_t kExampleBadECKeyDER[] = {
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
};
-static EVP_PKEY *load_example_rsa_key(void) {
- EVP_PKEY *ret = NULL;
+static ScopedEVP_PKEY LoadExampleRSAKey() {
const uint8_t *derp = kExampleRSAKeyDER;
- EVP_PKEY *pkey = NULL;
- RSA *rsa = NULL;
-
- if (!d2i_RSAPrivateKey(&rsa, &derp, sizeof(kExampleRSAKeyDER))) {
- return NULL;
- }
-
- pkey = EVP_PKEY_new();
- if (pkey == NULL || !EVP_PKEY_set1_RSA(pkey, rsa)) {
- goto out;
- }
-
- ret = pkey;
- pkey = NULL;
-
-out:
- if (pkey) {
- EVP_PKEY_free(pkey);
+ ScopedRSA rsa(d2i_RSAPrivateKey(nullptr, &derp, sizeof(kExampleRSAKeyDER)));
+ if (!rsa) {
+ return nullptr;
}
- if (rsa) {
- RSA_free(rsa);
+ ScopedEVP_PKEY pkey(EVP_PKEY_new());
+ if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) {
+ return nullptr;
}
-
- return ret;
+ return pkey;
}
-static int test_EVP_DigestSignInit(void) {
- int ret = 0;
- EVP_PKEY *pkey = NULL;
- uint8_t *sig = NULL;
- size_t sig_len = 0;
- EVP_MD_CTX md_ctx, md_ctx_verify;
-
- EVP_MD_CTX_init(&md_ctx);
- EVP_MD_CTX_init(&md_ctx_verify);
-
- pkey = load_example_rsa_key();
- if (pkey == NULL ||
- !EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
- !EVP_DigestSignUpdate(&md_ctx, kMsg, sizeof(kMsg))) {
- goto out;
+static bool TestEVP_DigestSignInit(void) {
+ ScopedEVP_PKEY pkey = LoadExampleRSAKey();
+ ScopedEVP_MD_CTX md_ctx;
+ if (!pkey ||
+ !EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
+ !EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg))) {
+ return false;
}
- /* Determine the size of the signature. */
- if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) {
- goto out;
+ // Determine the size of the signature.
+ size_t sig_len = 0;
+ if (!EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len)) {
+ return false;
}
- /* Sanity check for testing. */
- if (sig_len != EVP_PKEY_size(pkey)) {
+ // Sanity check for testing.
+ if (sig_len != (size_t)EVP_PKEY_size(pkey.get())) {
fprintf(stderr, "sig_len mismatch\n");
- goto out;
+ return false;
}
- sig = malloc(sig_len);
- if (sig == NULL || !EVP_DigestSignFinal(&md_ctx, sig, &sig_len)) {
- goto out;
+ std::vector<uint8_t> sig;
+ sig.resize(sig_len);
+ if (!EVP_DigestSignFinal(md_ctx.get(), bssl::vector_data(&sig), &sig_len)) {
+ return false;
}
+ sig.resize(sig_len);
- /* Ensure that the signature round-trips. */
- if (!EVP_DigestVerifyInit(&md_ctx_verify, NULL, EVP_sha256(), NULL, pkey) ||
- !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
- !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
- goto out;
+ // Ensure that the signature round-trips.
+ md_ctx.Reset();
+ if (!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
+ !EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(md_ctx.get(), bssl::vector_data(&sig), sig_len)) {
+ return false;
}
- ret = 1;
-
-out:
- if (!ret) {
- BIO_print_errors_fp(stderr);
- }
-
- EVP_MD_CTX_cleanup(&md_ctx);
- EVP_MD_CTX_cleanup(&md_ctx_verify);
- if (pkey) {
- EVP_PKEY_free(pkey);
- }
- if (sig) {
- free(sig);
- }
-
- return ret;
+ return true;
}
-static int test_EVP_DigestVerifyInit(void) {
- int ret = 0;
- EVP_PKEY *pkey = NULL;
- EVP_MD_CTX md_ctx;
-
- EVP_MD_CTX_init(&md_ctx);
-
- pkey = load_example_rsa_key();
- if (pkey == NULL ||
- !EVP_DigestVerifyInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
- !EVP_DigestVerifyUpdate(&md_ctx, kMsg, sizeof(kMsg)) ||
- !EVP_DigestVerifyFinal(&md_ctx, kSignature, sizeof(kSignature))) {
- goto out;
- }
- ret = 1;
-
-out:
- if (!ret) {
- BIO_print_errors_fp(stderr);
- }
-
- EVP_MD_CTX_cleanup(&md_ctx);
- if (pkey) {
- EVP_PKEY_free(pkey);
- }
-
- return ret;
+static bool TestEVP_DigestVerifyInit(void) {
+ ScopedEVP_PKEY pkey = LoadExampleRSAKey();
+ ScopedEVP_MD_CTX md_ctx;
+ if (!pkey ||
+ !EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
+ pkey.get()) ||
+ !EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature))) {
+ return false;
+ }
+ return true;
}
-/* test_algorithm_roundtrip signs a message using an already-initialized
- * |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
- * AlgorithmIdentifier to verify the signature. */
-static int test_algorithm_roundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
- int ret = 0;
- uint8_t *sig = NULL;
- size_t sig_len = 0;
- EVP_MD_CTX md_ctx_verify;
- X509_ALGOR *algor = NULL;
-
- EVP_MD_CTX_init(&md_ctx_verify);
-
+// TestAlgorithmRoundtrip signs a message using an already-initialized
+// |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
+// AlgorithmIdentifier to verify the signature.
+static bool TestAlgorithmRoundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
if (!EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
- goto out;
+ return false;
}
- /* Save the algorithm. */
- algor = X509_ALGOR_new();
- if (algor == NULL || !EVP_DigestSignAlgorithm(md_ctx, algor)) {
- goto out;
+ // Save the algorithm.
+ ScopedX509_ALGOR algor(X509_ALGOR_new());
+ if (!algor || !EVP_DigestSignAlgorithm(md_ctx, algor.get())) {
+ return false;
}
- /* Determine the size of the signature. */
+ // Determine the size of the signature.
+ size_t sig_len = 0;
if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
- goto out;
+ return false;
}
- /* Sanity check for testing. */
- if (sig_len != EVP_PKEY_size(pkey)) {
+ // Sanity check for testing.
+ if (sig_len != (size_t)EVP_PKEY_size(pkey)) {
fprintf(stderr, "sig_len mismatch\n");
- goto out;
+ return false;
}
- sig = malloc(sig_len);
- if (sig == NULL || !EVP_DigestSignFinal(md_ctx, sig, &sig_len)) {
- goto out;
+ std::vector<uint8_t> sig;
+ sig.resize(sig_len);
+ if (!EVP_DigestSignFinal(md_ctx, bssl::vector_data(&sig), &sig_len)) {
+ return false;
}
+ sig.resize(sig_len);
- /* Ensure that the signature round-trips. */
- if (!EVP_DigestVerifyInitFromAlgorithm(&md_ctx_verify, algor, pkey) ||
- !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
- !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
- goto out;
+ // Ensure that the signature round-trips.
+ ScopedEVP_MD_CTX md_ctx_verify;
+ if (!EVP_DigestVerifyInitFromAlgorithm(md_ctx_verify.get(), algor.get(),
+ pkey) ||
+ !EVP_DigestVerifyUpdate(md_ctx_verify.get(), kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(md_ctx_verify.get(), bssl::vector_data(&sig),
+ sig_len)) {
+ return false;
}
- ret = 1;
-
-out:
- EVP_MD_CTX_cleanup(&md_ctx_verify);
- if (sig) {
- free(sig);
- }
- if (algor) {
- X509_ALGOR_free(algor);
- }
-
- return ret;
+ return true;
}
-static int test_EVP_DigestSignAlgorithm(void) {
- int ret = 0;
- EVP_PKEY *pkey = NULL;
- EVP_MD_CTX md_ctx;
- EVP_PKEY_CTX *pkey_ctx;
-
- EVP_MD_CTX_init(&md_ctx);
-
- pkey = load_example_rsa_key();
- if (pkey == NULL) {
- goto out;
- }
+static bool TestEVP_DigestSignAlgorithm(void) {
+ ScopedEVP_PKEY pkey = LoadExampleRSAKey();
- /* Test a simple AlgorithmIdentifier. */
- if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) ||
- !test_algorithm_roundtrip(&md_ctx, pkey)) {
+ // Test a simple AlgorithmIdentifier.
+ ScopedEVP_MD_CTX md_ctx;
+ if (!pkey ||
+ !EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
+ !TestAlgorithmRoundtrip(md_ctx.get(), pkey.get())) {
fprintf(stderr, "RSA with SHA-256 failed\n");
- goto out;
+ return false;
}
- EVP_MD_CTX_cleanup(&md_ctx);
- EVP_MD_CTX_init(&md_ctx);
-
- /* Test RSA-PSS with custom parameters. */
- if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) ||
- EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1 ||
- EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) != 1 ||
- !test_algorithm_roundtrip(&md_ctx, pkey)) {
+ // Test RSA-PSS with custom parameters.
+ md_ctx.Reset();
+ EVP_PKEY_CTX *pkey_ctx;
+ if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
+ pkey.get()) ||
+ !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) ||
+ !TestAlgorithmRoundtrip(md_ctx.get(), pkey.get())) {
fprintf(stderr, "RSA-PSS failed\n");
- goto out;
- }
-
- ret = 1;
-
-out:
- if (!ret) {
- BIO_print_errors_fp(stderr);
+ return false;
}
- EVP_MD_CTX_cleanup(&md_ctx);
- if (pkey) {
- EVP_PKEY_free(pkey);
- }
-
- return ret;
+ return true;
}
-static int test_EVP_DigestVerifyInitFromAlgorithm(void) {
- int ret = 0;
+static bool TestEVP_DigestVerifyInitFromAlgorithm(void) {
CBS cert, cert_body, tbs_cert, algorithm, signature;
- uint8_t padding;
- X509_ALGOR *algor = NULL;
- const uint8_t *derp;
- EVP_PKEY *pkey = NULL;
- EVP_MD_CTX md_ctx;
-
- EVP_MD_CTX_init(&md_ctx);
-
CBS_init(&cert, kExamplePSSCert, sizeof(kExamplePSSCert));
if (!CBS_get_asn1(&cert, &cert_body, CBS_ASN1_SEQUENCE) ||
CBS_len(&cert) != 0 ||
@@ -482,155 +466,133 @@ static int test_EVP_DigestVerifyInitFromAlgorithm(void) {
!CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) ||
CBS_len(&cert_body) != 0) {
fprintf(stderr, "Failed to parse certificate\n");
- goto out;
+ return false;
}
- /* Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the
- leading phase byte is just a zero. */
+ // Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the
+ // leading phase byte is just a zero.
+ uint8_t padding;
if (!CBS_get_u8(&signature, &padding) || padding != 0) {
fprintf(stderr, "Invalid signature padding\n");
- goto out;
+ return false;
}
- derp = CBS_data(&algorithm);
- if (!d2i_X509_ALGOR(&algor, &derp, CBS_len(&algorithm)) ||
- derp != CBS_data(&algorithm) + CBS_len(&algorithm)) {
+ const uint8_t *derp = CBS_data(&algorithm);
+ ScopedX509_ALGOR algor(d2i_X509_ALGOR(NULL, &derp, CBS_len(&algorithm)));
+ if (!algor || derp != CBS_data(&algorithm) + CBS_len(&algorithm)) {
fprintf(stderr, "Failed to parse algorithm\n");
+ return false;
}
- pkey = load_example_rsa_key();
- if (pkey == NULL ||
- !EVP_DigestVerifyInitFromAlgorithm(&md_ctx, algor, pkey) ||
- !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&tbs_cert),
+ ScopedEVP_PKEY pkey = LoadExampleRSAKey();
+ ScopedEVP_MD_CTX md_ctx;
+ if (!pkey ||
+ !EVP_DigestVerifyInitFromAlgorithm(md_ctx.get(), algor.get(),
+ pkey.get()) ||
+ !EVP_DigestVerifyUpdate(md_ctx.get(), CBS_data(&tbs_cert),
CBS_len(&tbs_cert)) ||
- !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
+ !EVP_DigestVerifyFinal(md_ctx.get(), CBS_data(&signature),
CBS_len(&signature))) {
- goto out;
- }
- ret = 1;
-
-out:
- if (!ret) {
- BIO_print_errors_fp(stderr);
+ return false;
}
-
- EVP_MD_CTX_cleanup(&md_ctx);
- if (pkey) {
- EVP_PKEY_free(pkey);
- }
-
- return ret;
+ return true;
}
-static int test_d2i_AutoPrivateKey(const uint8_t *input, size_t input_len,
+static bool Testd2i_AutoPrivateKey(const uint8_t *input, size_t input_len,
int expected_id) {
- int ret = 0;
- const uint8_t *p;
- EVP_PKEY *pkey = NULL;
-
- p = input;
- pkey = d2i_AutoPrivateKey(NULL, &p, input_len);
- if (pkey == NULL || p != input + input_len) {
+ const uint8_t *p = input;
+ ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, input_len));
+ if (!pkey || p != input + input_len) {
fprintf(stderr, "d2i_AutoPrivateKey failed\n");
- goto done;
+ return false;
}
- if (EVP_PKEY_id(pkey) != expected_id) {
+ if (EVP_PKEY_id(pkey.get()) != expected_id) {
fprintf(stderr, "Did not decode expected type\n");
- goto done;
+ return false;
}
- ret = 1;
-
-done:
- if (!ret) {
- BIO_print_errors_fp(stderr);
- }
-
- if (pkey != NULL) {
- EVP_PKEY_free(pkey);
- }
- return ret;
+ return true;
}
-/* Tests loading a bad key in PKCS8 format */
-static int test_EVP_PKCS82PKEY(void) {
- int ret = 0;
+// TestEVP_PKCS82PKEY tests loading a bad key in PKCS8 format.
+static bool TestEVP_PKCS82PKEY(void) {
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));
-
+ ScopedPKCS8_PRIV_KEY_INFO 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;
+ return false;
}
- pkey = EVP_PKCS82PKEY(p8inf);
+ ScopedEVP_PKEY pkey(EVP_PKCS82PKEY(p8inf.get()));
if (pkey) {
fprintf(stderr, "Imported invalid EC key\n");
- goto done;
+ return false;
}
- ret = 1;
-
-done:
- if (p8inf != NULL) {
- PKCS8_PRIV_KEY_INFO_free(p8inf);
- }
-
- if (pkey != NULL) {
- EVP_PKEY_free(pkey);
- }
-
- return ret;
+ return true;
}
int main(void) {
CRYPTO_library_init();
ERR_load_crypto_strings();
- if (!test_EVP_DigestSignInit()) {
+ if (!TestEVP_DigestSignInit()) {
fprintf(stderr, "EVP_DigestSignInit failed\n");
+ ERR_print_errors_fp(stderr);
return 1;
}
- if (!test_EVP_DigestVerifyInit()) {
+ if (!TestEVP_DigestVerifyInit()) {
fprintf(stderr, "EVP_DigestVerifyInit failed\n");
+ ERR_print_errors_fp(stderr);
return 1;
}
- if (!test_EVP_DigestSignAlgorithm()) {
+ if (!TestEVP_DigestSignAlgorithm()) {
fprintf(stderr, "EVP_DigestSignInit failed\n");
+ ERR_print_errors_fp(stderr);
return 1;
}
- if (!test_EVP_DigestVerifyInitFromAlgorithm()) {
+ if (!TestEVP_DigestVerifyInitFromAlgorithm()) {
fprintf(stderr, "EVP_DigestVerifyInitFromAlgorithm failed\n");
+ ERR_print_errors_fp(stderr);
return 1;
}
- if (!test_d2i_AutoPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
- EVP_PKEY_RSA)) {
+ if (!Testd2i_AutoPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
+ EVP_PKEY_RSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n");
+ ERR_print_errors_fp(stderr);
return 1;
}
- if (!test_d2i_AutoPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
- EVP_PKEY_RSA)) {
+ if (!Testd2i_AutoPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
+ EVP_PKEY_RSA)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n");
+ ERR_print_errors_fp(stderr);
return 1;
}
- if (!test_d2i_AutoPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER),
- EVP_PKEY_EC)) {
+ if (!Testd2i_AutoPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER),
+ EVP_PKEY_EC)) {
fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n");
+ ERR_print_errors_fp(stderr);
+ return 1;
+ }
+
+ if (!Testd2i_AutoPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
+ EVP_PKEY_DSA)) {
+ fprintf(stderr, "d2i_AutoPrivateKey(kExampleDSAKeyDER) failed\n");
+ ERR_print_errors_fp(stderr);
return 1;
}
- if (!test_EVP_PKCS82PKEY()) {
- fprintf(stderr, "test_EVP_PKCS82PKEY failed\n");
+ if (!TestEVP_PKCS82PKEY()) {
+ fprintf(stderr, "TestEVP_PKCS82PKEY failed\n");
+ ERR_print_errors_fp(stderr);
return 1;
}
diff --git a/src/crypto/evp/evp_test.cc b/src/crypto/evp/evp_test.cc
new file mode 100644
index 0000000..239f868
--- /dev/null
+++ b/src/crypto/evp/evp_test.cc
@@ -0,0 +1,262 @@
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2015 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
+#include "../test/file_test.h"
+#include "../test/scoped_types.h"
+#include "../test/stl_compat.h"
+
+
+// evp_test dispatches between multiple test types. HMAC tests test the legacy
+// EVP_PKEY_HMAC API. PrivateKey tests take a key name parameter and single
+// block, decode it as a PEM private key, and save it under that key name.
+// Decrypt, Sign, and Verify tests take a previously imported key name as
+// parameter and test their respective operations.
+
+static const EVP_MD *GetDigest(FileTest *t, const std::string &name) {
+ if (name == "MD5") {
+ return EVP_md5();
+ } else if (name == "SHA1") {
+ return EVP_sha1();
+ } else if (name == "SHA224") {
+ return EVP_sha224();
+ } else if (name == "SHA256") {
+ return EVP_sha256();
+ } else if (name == "SHA384") {
+ return EVP_sha384();
+ } else if (name == "SHA512") {
+ return EVP_sha512();
+ }
+ t->PrintLine("Unknown digest: '%s'", name.c_str());
+ return nullptr;
+}
+
+using KeyMap = std::map<std::string, EVP_PKEY*>;
+
+// ImportPrivateKey evaluates a PrivateKey test in |t| and writes the resulting
+// private key to |key_map|.
+static bool ImportPrivateKey(FileTest *t, KeyMap *key_map) {
+ const std::string &key_name = t->GetParameter();
+ if (key_map->count(key_name) > 0) {
+ t->PrintLine("Duplicate key '%s'.", key_name.c_str());
+ return false;
+ }
+ const std::string &block = t->GetBlock();
+ ScopedBIO bio(BIO_new_mem_buf(const_cast<char*>(block.data()), block.size()));
+ if (!bio) {
+ return false;
+ }
+ ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), nullptr, 0, nullptr));
+ if (!pkey) {
+ t->PrintLine("Error reading private key.");
+ return false;
+ }
+ (*key_map)[key_name] = pkey.release();
+ return true;
+}
+
+static bool TestHMAC(FileTest *t) {
+ std::string digest_str;
+ if (!t->GetAttribute(&digest_str, "HMAC")) {
+ return false;
+ }
+ const EVP_MD *digest = GetDigest(t, digest_str);
+ if (digest == nullptr) {
+ return false;
+ }
+
+ std::vector<uint8_t> key, input, output;
+ if (!t->GetBytes(&key, "Key") ||
+ !t->GetBytes(&input, "Input") ||
+ !t->GetBytes(&output, "Output")) {
+ return false;
+ }
+
+ ScopedEVP_PKEY pkey(EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr,
+ bssl::vector_data(&key),
+ key.size()));
+ ScopedEVP_MD_CTX mctx;
+ if (!pkey ||
+ !EVP_DigestSignInit(mctx.get(), nullptr, digest, nullptr, pkey.get()) ||
+ !EVP_DigestSignUpdate(mctx.get(), bssl::vector_data(&input),
+ input.size())) {
+ return false;
+ }
+
+ size_t len;
+ std::vector<uint8_t> actual;
+ if (!EVP_DigestSignFinal(mctx.get(), nullptr, &len)) {
+ return false;
+ }
+ actual.resize(len);
+ if (!EVP_DigestSignFinal(mctx.get(), bssl::vector_data(&actual), &len)) {
+ return false;
+ }
+ actual.resize(len);
+ return t->ExpectBytesEqual(bssl::vector_data(&output), output.size(),
+ bssl::vector_data(&actual), actual.size());
+}
+
+static bool TestEVP(FileTest *t, void *arg) {
+ KeyMap *key_map = reinterpret_cast<KeyMap*>(arg);
+ if (t->GetType() == "PrivateKey") {
+ return ImportPrivateKey(t, key_map);
+ } else if (t->GetType() == "HMAC") {
+ return TestHMAC(t);
+ }
+
+ int (*key_op_init)(EVP_PKEY_CTX *ctx);
+ int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
+ const uint8_t *in, size_t in_len);
+ if (t->GetType() == "Decrypt") {
+ key_op_init = EVP_PKEY_decrypt_init;
+ key_op = EVP_PKEY_decrypt;
+ } else if (t->GetType() == "Sign") {
+ key_op_init = EVP_PKEY_sign_init;
+ key_op = EVP_PKEY_sign;
+ } else if (t->GetType() == "Verify") {
+ key_op_init = EVP_PKEY_verify_init;
+ key_op = nullptr; // EVP_PKEY_verify is handled differently.
+ } else {
+ t->PrintLine("Unknown test '%s'", t->GetType().c_str());
+ return false;
+ }
+
+ // Load the key.
+ const std::string &key_name = t->GetParameter();
+ if (key_map->count(key_name) == 0) {
+ t->PrintLine("Could not find key '%s'.", key_name.c_str());
+ return false;
+ }
+ EVP_PKEY *key = (*key_map)[key_name];
+
+ std::vector<uint8_t> input, output;
+ if (!t->GetBytes(&input, "Input") ||
+ !t->GetBytes(&output, "Output")) {
+ return false;
+ }
+
+ // Set up the EVP_PKEY_CTX.
+ ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(key, nullptr));
+ if (!ctx || !key_op_init(ctx.get())) {
+ return false;
+ }
+ if (t->HasAttribute("Digest")) {
+ const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("Digest"));
+ if (digest == nullptr ||
+ !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) {
+ return false;
+ }
+ }
+
+ if (t->GetType() == "Verify") {
+ if (!EVP_PKEY_verify(ctx.get(), bssl::vector_data(&output), output.size(),
+ bssl::vector_data(&input), input.size())) {
+ // ECDSA sometimes doesn't push an error code. Push one on the error queue
+ // so it's distinguishable from other errors.
+ ERR_put_error(ERR_LIB_USER, 0, ERR_R_EVP_LIB, __FILE__, __LINE__);
+ return false;
+ }
+ return true;
+ }
+
+ size_t len;
+ std::vector<uint8_t> actual;
+ if (!key_op(ctx.get(), nullptr, &len, bssl::vector_data(&input),
+ input.size())) {
+ return false;
+ }
+ actual.resize(len);
+ if (!key_op(ctx.get(), bssl::vector_data(&actual), &len,
+ bssl::vector_data(&input), input.size())) {
+ return false;
+ }
+ actual.resize(len);
+ if (!t->ExpectBytesEqual(bssl::vector_data(&output), output.size(),
+ bssl::vector_data(&actual), len)) {
+ return false;
+ }
+ return true;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+ if (argc != 2) {
+ fprintf(stderr, "%s <test file.txt>\n", argv[0]);
+ return 1;
+ }
+
+ KeyMap map;
+ int ret = FileTestMain(TestEVP, &map, argv[1]);
+ // TODO(davidben): When we can rely on a move-aware std::map, make KeyMap a
+ // map of ScopedEVP_PKEY instead.
+ for (const auto &pair : map) {
+ EVP_PKEY_free(pair.second);
+ }
+ return ret;
+}
diff --git a/src/crypto/evp/evp_tests.txt b/src/crypto/evp/evp_tests.txt
new file mode 100644
index 0000000..cccfa4f
--- /dev/null
+++ b/src/crypto/evp/evp_tests.txt
@@ -0,0 +1,174 @@
+# Public key algorithm tests
+
+# Private keys used for PKEY operations.
+
+# RSA 2048 bit key.
+
+PrivateKey = RSA-2048
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDNAIHqeyrh6gbV
+n3xz2f+5SglhXC5Lp8Y2zvCN01M+wxhVJbAVx2m5mnfWclv5w1Mqm25fZifV+4UW
+B2jT3anL01l0URcX3D0wnS/EfuQfl+Mq23+d2GShxHZ6Zm7NcbwarPXnUX9LOFlP
+6psF5C1a2pkSAIAT5FMWpNm7jtCGuI0odYusr5ItRqhotIXSOcm66w4rZFknEPQr
+LR6gpLSALAvsqzKPimiwBzvbVG/uqYCdKEmRKzkMFTK8finHZY+BdfrkbzQzL/h7
+yrPkBkm5hXeGnaDqcYNT8HInVIhpE2SHYNEivmduD8SD3SD/wxvalqMZZsmqLnWt
+A95H4cRPAgMBAAECggEAYCl6x5kbFnoG1rJHWLjL4gi+ubLZ7Jc4vYD5Ci41AF3X
+ziktnim6iFvTFv7x8gkTvArJDWsICLJBTYIQREHYYkozzgIzyPeApIs3Wv8C12cS
+IopwJITbP56+zM+77hcJ26GCgA2Unp5CFuC/81WDiPi9kNo3Oh2CdD7D+90UJ/0W
+glplejFpEuhpU2URfKL4RckJQF/KxV+JX8FdIDhsJu54yemQdQKaF4psHkzwwgDo
+qc+yfp0Vb4bmwq3CKxqEoc1cpbJ5CHXXlAfISzUjlcuBzD/tW7BDtp7eDAcgRVAC
+XO6MX0QBcLYSC7SOD3R7zY9SIRCFDfBDxCjf0YcFMQKBgQD2+WG0fLwDXTrt68fe
+hQqVa2Xs25z2B2QGPxWqSFU8WNly/mZ1BW413f3De/O58vYi7icTNyVoScm+8hdv
+6PfD+LuRujdN1TuvPeyBTSvewQwf3IjN0Wh28mse36PwlBl+301C/x+ylxEDuJjK
+hZxCcocIaoQqtBC7ac8tNa9r4wKBgQDUfnJKf/QQSLJwwlJKQQGHi3MVm7c9PbwY
+eyIOY1s1NPluJDoYTZP4YLa/u2txwe2aHh9FhYMCPDAelqaSwaCLU9DsnKkQEA2A
+RR47fcagG6xK7O+N95iEa8I1oIy7os9MBoBMwRIZ6VYIxxTj8UMNSR+tu6MqV1Gg
+T5d0WDTJpQKBgCHyRSu5uV39AoyRS/eZ8cp36JqV1Q08FtOE+EVfi9evnrPfo9WR
+2YQt7yNfdjCo5IwIj/ZkLhAXlFNakz4el2+oUJ/HKLLaDEoaCNf883q6rh/zABrK
+HcG7sF2d/7qhoJ9/se7zgjfZ68zHIrkzhDbd5xGREnmMJoCcGo3sQyBhAoGAH3UQ
+qmLC2N5KPFMoJ4H0HgLQ6LQCrnhDLkScSBEBYaEUA/AtAYgKjcyTgVLXlyGkcRpg
+esRHHr+WSBD5W+R6ReYEmeKfTJdzyDdzQE9gZjdyjC0DUbsDwybIu3OnIef6VEDq
+IXK7oUZfzDDcsNn4mTDoFaoff5cpqFfgDgM43VkCgYBNHw11b+d+AQmaZS9QqIt7
+aF3FvwCYHV0jdv0Mb+Kc1bY4c0R5MFpzrTwVmdOerjuuA1+9b+0Hwo3nBZM4eaBu
+SOamA2hu2OJWCl9q8fLCT69KqWDjghhvFe7c6aJJGucwaA3Uz3eLcPqoaCarMiNH
+fMkTd7GabVourqIZdgvu1Q==
+-----END PRIVATE KEY-----
+
+# EC P-256 key
+
+PrivateKey = P-256
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiocvtiiTxNH/xbnw
++RdYBp+DUuCPoFpJ+NuSbLVyhyWhRANCAAQsFQ9CnOcPIWwlLPXgYs4fY5zV0WXH
++JQkBywnGX14szuSDpXNtmTpkNzwz+oNlOKo5q+dDlgFbmUxBJJbn+bJ
+-----END PRIVATE KEY-----
+
+# RSA tests
+
+Sign = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad
+
+Verify = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad
+
+# Digest too long
+Sign = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF12345"
+Output =
+Error = INVALID_DIGEST_LENGTH
+
+# Digest too short
+Sign = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF12345"
+Output =
+Error = INVALID_DIGEST_LENGTH
+
+# Mismatched digest
+Verify = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1233"
+Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad
+Error = BAD_SIGNATURE
+
+# Corrupted signature
+Verify = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1233"
+Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ae
+Error = BLOCK_TYPE_IS_NOT_01
+
+# parameter missing (NOTE: this differs from upstream)
+Verify = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 3ec3fc29eb6e122bd7aa361cd09fe1bcbe85311096a7b9e4799cedfb2351ce0ab7fe4e75b4f6b37f67edd9c60c800f9ab941c0c157d7d880ca9de40c951d60fd293ae220d4bc510b1572d6e85a1bbbd8605b52e05f1c64fafdae59a1c2fbed214b7844d0134619de62851d5a0522e32e556e5950f3f97b8150e3f0dffee612c924201c27cd9bc8b423a71533380c276d3d59fcba35a2e80a1a192ec266a6c2255012cd86a349fe90a542b355fa3355b04da6cdf1df77f0e7bd44a90e880e1760266d233e465226f5db1c68857847d82072861ee266ddfc2e596845b77e1803274a579835ab5e4975d81d20b7df9cec7795489e4a2bdb8c1cf6a6b359945ac92c
+Error = BAD_SIGNATURE
+
+# embedded digest too long
+Verify = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = afec9a0d5330a08f54283bb4a9d4e7e7e70fc1342336c4c766fba713f66970151c6e27413c48c33864ea45a0238787004f338ed3e21b53b0fe9c1151c42c388cbc7cba5a06b706c407a5b48324fbe994dc7afc3a19fb3d2841e66222596c14cd72a0f0a7455a019d8eb554f59c0183f9552b75aa96fee8bf935945e079ca283d2bd3534a86f11351f6d6181fbf433e5b01a6d1422145c7a72214d3aacdd5d3af12b2d6bf6438f9f9a64010d8aeed801c87f0859412b236150b86a545f7239be022f4a7ad246b59df87514294cb4a4c7c5a997ee53c66054d9f38ca4e76c1f7af83c30f737ef70f83a45aebe18238ddb95e1998814ca4fc72388f1533147c169d
+Error = BAD_SIGNATURE
+
+# embedded digest too short
+Verify = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = afec9a0d5330a08f54283bb4a9d4e7e7e70fc1342336c4c766fba713f66970151c6e27413c48c33864ea45a0238787004f338ed3e21b53b0fe9c1151c42c388cbc7cba5a06b706c407a5b48324fbe994dc7afc3a19fb3d2841e66222596c14cd72a0f0a7455a019d8eb554f59c0183f9552b75aa96fee8bf935945e079ca283d2bd3534a86f11351f6d6181fbf433e5b01a6d1422145c7a72214d3aacdd5d3af12b2d6bf6438f9f9a64010d8aeed801c87f0859412b236150b86a545f7239be022f4a7ad246b59df87514294cb4a4c7c5a997ee53c66054d9f38ca4e76c1f7af83c30f737ef70f83a45aebe18238ddb95e1998814ca4fc72388f1533147c169d
+Error = BAD_SIGNATURE
+
+# Garbage after DigestInfo
+Verify = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 9ee34872d4271a7d8808af0a4052a145a6d6a8437d00da3ed14428c7f087cd39f4d43334c41af63e7fa1ba363fee7bcef401d9d36a662abbab55ce89a696e1be0dfa19a5d09ca617dd488787b6048baaefeb29bc8688b2fe3882de2b77c905b5a8b56cf9616041e5ec934ba6de863efe93acc4eef783fe7f72a00fa65d6093ed32bf98ce527e62ccb1d56317f4be18b7e0f55d7c36617d2d0678a306e3350956b662ac15df45215dd8f6b314babb9788e6c272fa461e4c9b512a11a4b92bc77c3a4c95c903fccb238794eca5c750477bf56ea6ee6a167367d881b485ae3889e7c489af8fdf38e0c0f2aed780831182e34abedd43c39281b290774bf35cc25274
+Error = BAD_SIGNATURE
+
+# invalid tag for parameter
+Verify = RSA-2048
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 49525db4d44c755e560cba980b1d85ea604b0e077fcadd4ba44072a3487bbddb835016200a7d8739cce2dc3223d9c20cbdd25059ab02277f1f21318efd18e21038ec89aa9d40680987129e8b41ba33bceb86518bdf47268b921cce2037acabca6575d832499538d6f40cdba0d40bd7f4d8ea6ca6e2eec87f294efc971407857f5d7db09f6a7b31e301f571c6d82a5e3d08d2bb3a36e673d28b910f5bec57f0fcc4d968fd7c94d0b9226dec17f5192ad8b42bcab6f26e1bea1fdc3b958199acb00f14ebcb2a352f3afcedd4c09000128a603bbeb9696dea13040445253972d46237a25c7845e3b464e6984c2348ea1f1210a9ff0b00d2d72b50db00c009bb39f9
+Error = BAD_SIGNATURE
+
+# EC tests
+
+Verify = P-256
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8
+
+# Digest too long
+Verify = P-256
+Digest = SHA1
+Input = "0123456789ABCDEF12345"
+Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8
+# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced.
+Error = public key routines
+
+# Digest too short
+Verify = P-256
+Digest = SHA1
+Input = "0123456789ABCDEF123"
+Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8
+# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced.
+Error = public key routines
+
+# Digest invalid
+Verify = P-256
+Digest = SHA1
+Input = "0123456789ABCDEF1235"
+Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8
+# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced.
+Error = public key routines
+
+# Invalid signature
+Verify = P-256
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec7
+# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced.
+Error = public key routines
+
+# Garbage after signature
+Verify = P-256
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec800
+# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced.
+Error = public key routines
+
+# BER signature
+Verify = P-256
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000
+# This operation fails without an error code, so ERR_R_EVP_LIB is surfaced.
+Error = public key routines
diff --git a/src/crypto/evp/internal.h b/src/crypto/evp/internal.h
index 2b0f608..08a7bfb 100644
--- a/src/crypto/evp/internal.h
+++ b/src/crypto/evp/internal.h
@@ -170,8 +170,49 @@ typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
#define EVP_PKEY_OP_TYPE_GEN (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN)
+/* EVP_PKEY_CTX_ctrl performs |cmd| on |ctx|. The |keytype| and |optype|
+ * arguments can be -1 to specify that any type and operation are acceptable,
+ * otherwise |keytype| must match the type of |ctx| and the bits of |optype|
+ * must intersect the operation flags set on |ctx|.
+ *
+ * The |p1| and |p2| arguments depend on the value of |cmd|.
+ *
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
+ int cmd, int p1, void *p2);
+
+/* EVP_PKEY_CTRL_DIGESTINIT is an internal value. It's called by
+ * EVP_DigestInit_ex to signal the |EVP_PKEY| that a digest operation is
+ * starting.
+ *
+ * TODO(davidben): This is only needed to support the deprecated HMAC |EVP_PKEY|
+ * types. */
+#define EVP_PKEY_CTRL_DIGESTINIT 3
+
+/* EVP_PKEY_CTRL_PEER_KEY is called with different values of |p1|:
+ * 0: Is called from |EVP_PKEY_derive_set_peer| and |p2| contains a peer key.
+ * If the return value is <= 0, the key is rejected.
+ * 1: Is called at the end of |EVP_PKEY_derive_set_peer| and |p2| contains a
+ * peer key. If the return value is <= 0, the key is rejected.
+ * 2: Is called with |p2| == NULL to test whether the peer's key was used.
+ * (EC)DH always return one in this case.
+ * 3: Is called with |p2| == NULL to set whether the peer's key was used.
+ * (EC)DH always return one in this case. This was only used for GOST. */
+#define EVP_PKEY_CTRL_PEER_KEY 4
+
+/* EVP_PKEY_CTRL_SET_MAC_KEY sets a MAC key. For example, this can be done an
+ * |EVP_PKEY_CTX| prior to calling |EVP_PKEY_keygen| in order to generate an
+ * HMAC |EVP_PKEY| with the given key. It returns one on success and zero on
+ * error. */
+#define EVP_PKEY_CTRL_SET_MAC_KEY 5
+
+/* EVP_PKEY_ALG_CTRL is the base value from which key-type specific ctrl
+ * commands are numbered. */
+#define EVP_PKEY_ALG_CTRL 0x1000
+
#define EVP_PKEY_CTRL_MD 1
#define EVP_PKEY_CTRL_GET_MD 2
+
#define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1)
#define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 2)
#define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 3)
@@ -185,6 +226,8 @@ typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
#define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11)
#define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
+#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
+
struct evp_pkey_ctx_st {
/* Method associated with this operation */
const EVP_PKEY_METHOD *pmeth;
diff --git a/src/crypto/evp/p_dsa_asn1.c b/src/crypto/evp/p_dsa_asn1.c
new file mode 100644
index 0000000..0ac7da7
--- /dev/null
+++ b/src/crypto/evp/p_dsa_asn1.c
@@ -0,0 +1,569 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/evp.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/digest.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "../dsa/internal.h"
+#include "internal.h"
+
+
+static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
+ const uint8_t *p, *pm;
+ int pklen, pmlen;
+ int ptype;
+ void *pval;
+ ASN1_STRING *pstr;
+ X509_ALGOR *palg;
+ ASN1_INTEGER *public_key = NULL;
+
+ DSA *dsa = NULL;
+
+ if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) {
+ return 0;
+ }
+ X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+ if (ptype == V_ASN1_SEQUENCE) {
+ pstr = pval;
+ pm = pstr->data;
+ pmlen = pstr->length;
+
+ dsa = d2i_DSAparams(NULL, &pm, pmlen);
+ if (dsa == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_pub_decode, EVP_R_DECODE_ERROR);
+ goto err;
+ }
+ } else if (ptype == V_ASN1_NULL || ptype == V_ASN1_UNDEF) {
+ dsa = DSA_new();
+ if (dsa == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_pub_decode, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(EVP, dsa_pub_decode, EVP_R_PARAMETER_ENCODING_ERROR);
+ goto err;
+ }
+
+ public_key = d2i_ASN1_INTEGER(NULL, &p, pklen);
+ if (public_key == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_pub_decode, EVP_R_DECODE_ERROR);
+ goto err;
+ }
+
+ dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL);
+ if (dsa->pub_key == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_pub_decode, EVP_R_BN_DECODE_ERROR);
+ goto err;
+ }
+
+ ASN1_INTEGER_free(public_key);
+ EVP_PKEY_assign_DSA(pkey, dsa);
+ return 1;
+
+err:
+ ASN1_INTEGER_free(public_key);
+ DSA_free(dsa);
+ return 0;
+}
+
+static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
+ DSA *dsa;
+ void *pval = NULL;
+ uint8_t *penc = NULL;
+ int penclen;
+
+ dsa = pkey->pkey.dsa;
+ dsa->write_params = 0;
+
+ penclen = i2d_DSAPublicKey(dsa, &penc);
+
+ if (penclen <= 0) {
+ OPENSSL_PUT_ERROR(EVP, dsa_pub_encode, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA), V_ASN1_UNDEF, pval,
+ penc, penclen)) {
+ return 1;
+ }
+
+err:
+ OPENSSL_free(penc);
+ ASN1_STRING_free(pval);
+
+ return 0;
+}
+
+static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
+ const uint8_t *p, *pm;
+ int pklen, pmlen;
+ int ptype;
+ void *pval;
+ ASN1_STRING *pstr;
+ X509_ALGOR *palg;
+ ASN1_INTEGER *privkey = NULL;
+ BN_CTX *ctx = NULL;
+
+ /* In PKCS#8 DSA: you just get a private key integer and parameters in the
+ * AlgorithmIdentifier the pubkey must be recalculated. */
+
+ STACK_OF(ASN1_TYPE) *ndsa = NULL;
+ DSA *dsa = NULL;
+
+ if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
+ return 0;
+ }
+ X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+ /* Check for broken DSA PKCS#8, UGH! */
+ if (*p == (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) {
+ ASN1_TYPE *t1, *t2;
+ ndsa = d2i_ASN1_SEQUENCE_ANY(NULL, &p, pklen);
+ if (ndsa == NULL) {
+ goto decerr;
+ }
+ if (sk_ASN1_TYPE_num(ndsa) != 2) {
+ goto decerr;
+ }
+
+ /* Handle Two broken types:
+ * SEQUENCE {parameters, priv_key}
+ * SEQUENCE {pub_key, priv_key}. */
+
+ t1 = sk_ASN1_TYPE_value(ndsa, 0);
+ t2 = sk_ASN1_TYPE_value(ndsa, 1);
+ if (t1->type == V_ASN1_SEQUENCE) {
+ p8->broken = PKCS8_EMBEDDED_PARAM;
+ pval = t1->value.ptr;
+ } else if (ptype == V_ASN1_SEQUENCE) {
+ p8->broken = PKCS8_NS_DB;
+ } else {
+ goto decerr;
+ }
+
+ if (t2->type != V_ASN1_INTEGER) {
+ goto decerr;
+ }
+
+ privkey = t2->value.integer;
+ } else {
+ const uint8_t *q = p;
+ privkey = d2i_ASN1_INTEGER(NULL, &p, pklen);
+ if (privkey == NULL) {
+ goto decerr;
+ }
+ if (privkey->type == V_ASN1_NEG_INTEGER) {
+ p8->broken = PKCS8_NEG_PRIVKEY;
+ ASN1_INTEGER_free(privkey);
+ privkey = d2i_ASN1_UINTEGER(NULL, &q, pklen);
+ if (privkey == NULL) {
+ goto decerr;
+ }
+ }
+ if (ptype != V_ASN1_SEQUENCE) {
+ goto decerr;
+ }
+ }
+
+ pstr = pval;
+ pm = pstr->data;
+ pmlen = pstr->length;
+ dsa = d2i_DSAparams(NULL, &pm, pmlen);
+ if (dsa == NULL) {
+ goto decerr;
+ }
+ /* We have parameters. Now set private key */
+ dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL);
+ if (dsa->priv_key == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_decode, ERR_LIB_BN);
+ goto dsaerr;
+ }
+ /* Calculate public key. */
+ dsa->pub_key = BN_new();
+ if (dsa->pub_key == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_decode, ERR_R_MALLOC_FAILURE);
+ goto dsaerr;
+ }
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_decode, ERR_R_MALLOC_FAILURE);
+ goto dsaerr;
+ }
+
+ if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_decode, ERR_LIB_BN);
+ goto dsaerr;
+ }
+
+ EVP_PKEY_assign_DSA(pkey, dsa);
+ BN_CTX_free(ctx);
+ sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
+ ASN1_INTEGER_free(privkey);
+
+ return 1;
+
+decerr:
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_decode, EVP_R_DECODE_ERROR);
+
+dsaerr:
+ BN_CTX_free(ctx);
+ ASN1_INTEGER_free(privkey);
+ sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
+ DSA_free(dsa);
+ return 0;
+}
+
+static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
+ ASN1_STRING *params = NULL;
+ ASN1_INTEGER *prkey = NULL;
+ uint8_t *dp = NULL;
+ int dplen;
+
+ if (!pkey->pkey.dsa || !pkey->pkey.dsa->priv_key) {
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_encode, EVP_R_MISSING_PARAMETERS);
+ goto err;
+ }
+
+ params = ASN1_STRING_new();
+ if (!params) {
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_encode, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
+ if (params->length <= 0) {
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_encode, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ params->type = V_ASN1_SEQUENCE;
+
+ /* Get private key into integer. */
+ prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
+
+ if (!prkey) {
+ OPENSSL_PUT_ERROR(EVP, dsa_priv_encode, ERR_LIB_BN);
+ goto err;
+ }
+
+ dplen = i2d_ASN1_INTEGER(prkey, &dp);
+
+ ASN1_INTEGER_free(prkey);
+
+ if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_dsa), 0,
+ V_ASN1_SEQUENCE, params, dp, dplen)) {
+ goto err;
+ }
+
+ return 1;
+
+err:
+ OPENSSL_free(dp);
+ ASN1_STRING_free(params);
+ ASN1_INTEGER_free(prkey);
+ return 0;
+}
+
+static int int_dsa_size(const EVP_PKEY *pkey) {
+ return DSA_size(pkey->pkey.dsa);
+}
+
+static int dsa_bits(const EVP_PKEY *pkey) {
+ return BN_num_bits(pkey->pkey.dsa->p);
+}
+
+static int dsa_missing_parameters(const EVP_PKEY *pkey) {
+ DSA *dsa;
+ dsa = pkey->pkey.dsa;
+ if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
+ return 1;
+ }
+ return 0;
+}
+
+static int dup_bn_into(BIGNUM **out, BIGNUM *src) {
+ BIGNUM *a;
+
+ a = BN_dup(src);
+ if (a == NULL) {
+ return 0;
+ }
+ BN_free(*out);
+ *out = a;
+
+ return 1;
+}
+
+static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
+ if (!dup_bn_into(&to->pkey.dsa->p, from->pkey.dsa->p) ||
+ !dup_bn_into(&to->pkey.dsa->q, from->pkey.dsa->q) ||
+ !dup_bn_into(&to->pkey.dsa->g, from->pkey.dsa->g)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
+ return BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) == 0 &&
+ BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) == 0 &&
+ BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g) == 0;
+}
+
+static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
+ return BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0;
+}
+
+static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); }
+
+static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
+ size_t i;
+
+ if (!b) {
+ return;
+ }
+ i = BN_num_bytes(b);
+ if (*pbuflen < i) {
+ *pbuflen = i;
+ }
+}
+
+static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
+ uint8_t *m = NULL;
+ int ret = 0;
+ size_t buf_len = 0;
+ const char *ktype = NULL;
+
+ const BIGNUM *priv_key, *pub_key;
+
+ priv_key = NULL;
+ if (ptype == 2) {
+ priv_key = x->priv_key;
+ }
+
+ pub_key = NULL;
+ if (ptype > 0) {
+ pub_key = x->pub_key;
+ }
+
+ ktype = "DSA-Parameters";
+ if (ptype == 2) {
+ ktype = "Private-Key";
+ } else if (ptype == 1) {
+ ktype = "Public-Key";
+ }
+
+ update_buflen(x->p, &buf_len);
+ update_buflen(x->q, &buf_len);
+ update_buflen(x->g, &buf_len);
+ update_buflen(priv_key, &buf_len);
+ update_buflen(pub_key, &buf_len);
+
+ m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
+ if (m == NULL) {
+ OPENSSL_PUT_ERROR(EVP, do_dsa_print, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (priv_key) {
+ if (!BIO_indent(bp, off, 128) ||
+ BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
+ goto err;
+ }
+ }
+
+ if (!ASN1_bn_print(bp, "priv:", priv_key, m, off) ||
+ !ASN1_bn_print(bp, "pub: ", pub_key, m, off) ||
+ !ASN1_bn_print(bp, "P: ", x->p, m, off) ||
+ !ASN1_bn_print(bp, "Q: ", x->q, m, off) ||
+ !ASN1_bn_print(bp, "G: ", x->g, m, off)) {
+ goto err;
+ }
+ ret = 1;
+
+err:
+ OPENSSL_free(m);
+ return ret;
+}
+
+static int dsa_param_decode(EVP_PKEY *pkey, const uint8_t **pder, int derlen) {
+ DSA *dsa;
+ dsa = d2i_DSAparams(NULL, pder, derlen);
+ if (dsa == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_param_decode, ERR_R_DSA_LIB);
+ return 0;
+ }
+ EVP_PKEY_assign_DSA(pkey, dsa);
+ return 1;
+}
+
+static int dsa_param_encode(const EVP_PKEY *pkey, uint8_t **pder) {
+ return i2d_DSAparams(pkey->pkey.dsa, pder);
+}
+
+static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
+}
+
+static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
+}
+
+static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
+}
+
+static int old_dsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
+ int derlen) {
+ DSA *dsa;
+ dsa = d2i_DSAPrivateKey(NULL, pder, derlen);
+ if (dsa == NULL) {
+ OPENSSL_PUT_ERROR(EVP, old_dsa_priv_decode, ERR_R_DSA_LIB);
+ return 0;
+ }
+ EVP_PKEY_assign_DSA(pkey, dsa);
+ return 1;
+}
+
+static int old_dsa_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
+ return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
+}
+
+static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
+ const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) {
+ DSA_SIG *dsa_sig;
+ const uint8_t *p;
+
+ if (!sig) {
+ return BIO_puts(bp, "\n") > 0;
+ }
+
+ p = sig->data;
+ dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
+ if (dsa_sig == NULL) {
+ return X509_signature_dump(bp, sig, indent);
+ }
+
+ int rv = 0;
+ size_t buf_len = 0;
+ uint8_t *m = NULL;
+
+ update_buflen(dsa_sig->r, &buf_len);
+ update_buflen(dsa_sig->s, &buf_len);
+ m = OPENSSL_malloc(buf_len + 10);
+ if (m == NULL) {
+ OPENSSL_PUT_ERROR(EVP, dsa_sig_print, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (BIO_write(bp, "\n", 1) != 1 ||
+ !ASN1_bn_print(bp, "r: ", dsa_sig->r, m, indent) ||
+ !ASN1_bn_print(bp, "s: ", dsa_sig->s, m, indent)) {
+ goto err;
+ }
+ rv = 1;
+
+err:
+ OPENSSL_free(m);
+ DSA_SIG_free(dsa_sig);
+ return rv;
+}
+
+const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
+ EVP_PKEY_DSA,
+ EVP_PKEY_DSA,
+ 0,
+
+ "DSA",
+ "OpenSSL DSA method",
+
+ dsa_pub_decode,
+ dsa_pub_encode,
+ dsa_pub_cmp,
+ dsa_pub_print,
+
+ dsa_priv_decode,
+ dsa_priv_encode,
+ dsa_priv_print,
+
+ NULL /* pkey_opaque */,
+ NULL /* pkey_supports_digest */,
+
+ int_dsa_size,
+ dsa_bits,
+
+ dsa_param_decode,
+ dsa_param_encode,
+ dsa_missing_parameters,
+ dsa_copy_parameters,
+ dsa_cmp_parameters,
+ dsa_param_print,
+ dsa_sig_print,
+
+ int_dsa_free,
+ old_dsa_priv_decode,
+ old_dsa_priv_encode,
+};
diff --git a/src/crypto/evp/p_ec.c b/src/crypto/evp/p_ec.c
index c274131..73c00d8 100644
--- a/src/crypto/evp/p_ec.c
+++ b/src/crypto/evp/p_ec.c
@@ -119,9 +119,7 @@ static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) {
return;
}
- if (dctx->gen_group) {
- EC_GROUP_free(dctx->gen_group);
- }
+ EC_GROUP_free(dctx->gen_group);
OPENSSL_free(dctx);
}
@@ -212,8 +210,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_INVALID_CURVE);
return 0;
}
- if (dctx->gen_group)
- EC_GROUP_free(dctx->gen_group);
+ EC_GROUP_free(dctx->gen_group);
dctx->gen_group = group;
return 1;
@@ -240,7 +237,8 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
return 1;
default:
- return -2;
+ OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_COMMAND_NOT_SUPPORTED);
+ return 0;
}
}
diff --git a/src/crypto/evp/p_ec_asn1.c b/src/crypto/evp/p_ec_asn1.c
index 914cc2f..fbbf4e7 100644
--- a/src/crypto/evp/p_ec_asn1.c
+++ b/src/crypto/evp/p_ec_asn1.c
@@ -142,23 +142,13 @@ static EC_KEY *eckey_type2param(int ptype, void *pval) {
}
} else if (ptype == V_ASN1_OBJECT) {
ASN1_OBJECT *poid = pval;
- EC_GROUP *group;
/* type == V_ASN1_OBJECT => the parameters are given
* by an asn1 OID */
- eckey = EC_KEY_new();
+ eckey = EC_KEY_new_by_curve_name(OBJ_obj2nid(poid));
if (eckey == NULL) {
- OPENSSL_PUT_ERROR(EVP, eckey_type2param, ERR_R_MALLOC_FAILURE);
goto err;
}
- group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
- if (group == NULL) {
- goto err;
- }
- if (EC_KEY_set_group(eckey, group) == 0) {
- goto err;
- }
- EC_GROUP_free(group);
} else {
OPENSSL_PUT_ERROR(EVP, eckey_type2param, EVP_R_DECODE_ERROR);
goto err;
@@ -201,8 +191,9 @@ static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
return 1;
err:
- if (eckey)
+ if (eckey) {
EC_KEY_free(eckey);
+ }
return 0;
}
@@ -235,8 +226,9 @@ static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
eckey = eckey_type2param(ptype, pval);
- if (!eckey)
+ if (!eckey) {
goto ecliberr;
+ }
/* We have parameters now set private key */
if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
@@ -282,8 +274,9 @@ static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
ecliberr:
OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB);
ecerr:
- if (eckey)
+ if (eckey) {
EC_KEY_free(eckey);
+ }
return 0;
}
@@ -439,10 +432,12 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
if (ktype == 2) {
priv_key = EC_KEY_get0_private_key(x);
- if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
+ if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
buf_len = i;
- } else
+ }
+ } else {
priv_key = NULL;
+ }
if (ktype > 0) {
buf_len += 10;
@@ -451,24 +446,27 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
goto err;
}
}
- if (ktype == 2)
+ if (ktype == 2) {
ecstr = "Private-Key";
- else if (ktype == 1)
+ } else if (ktype == 1) {
ecstr = "Public-Key";
- else
+ } else {
ecstr = "ECDSA-Parameters";
+ }
- if (!BIO_indent(bp, off, 128))
- goto err;
- if ((order = BN_new()) == NULL)
- goto err;
- if (!EC_GROUP_get_order(group, order, NULL))
+ if (!BIO_indent(bp, off, 128)) {
goto err;
- if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0)
+ }
+ order = BN_new();
+ if (order == NULL || !EC_GROUP_get_order(group, order, NULL) ||
+ BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
goto err;
+ }
- if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, buffer, off))
+ if ((priv_key != NULL) &&
+ !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) {
goto err;
+ }
if (pub_key_bytes != NULL) {
BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
}
@@ -479,16 +477,13 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
ret = 1;
err:
- if (!ret)
+ if (!ret) {
OPENSSL_PUT_ERROR(EVP, do_EC_KEY_print, reason);
- if (pub_key_bytes)
- OPENSSL_free(pub_key_bytes);
- if (order)
- BN_free(order);
- if (ctx)
- BN_CTX_free(ctx);
- if (buffer != NULL)
- OPENSSL_free(buffer);
+ }
+ OPENSSL_free(pub_key_bytes);
+ BN_free(order);
+ BN_CTX_free(ctx);
+ OPENSSL_free(buffer);
return ret;
}
diff --git a/src/crypto/evp/p_hmac.c b/src/crypto/evp/p_hmac.c
index 6d9a909..21703ed 100644
--- a/src/crypto/evp/p_hmac.c
+++ b/src/crypto/evp/p_hmac.c
@@ -204,7 +204,8 @@ static int pkey_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
break;
default:
- return -2;
+ OPENSSL_PUT_ERROR(EVP, pkey_hmac_ctrl, EVP_R_COMMAND_NOT_SUPPORTED);
+ return 0;
}
return 1;
}
diff --git a/src/crypto/evp/p_rsa.c b/src/crypto/evp/p_rsa.c
index 31f5aaa..5abc075 100644
--- a/src/crypto/evp/p_rsa.c
+++ b/src/crypto/evp/p_rsa.c
@@ -55,10 +55,12 @@
#include <openssl/evp.h>
+#include <limits.h>
#include <string.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
+#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -125,9 +127,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
dctx->md = sctx->md;
dctx->mgf1md = sctx->mgf1md;
if (sctx->oaep_label) {
- if (dctx->oaep_label) {
- OPENSSL_free(dctx->oaep_label);
- }
+ OPENSSL_free(dctx->oaep_label);
dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen);
if (!dctx->oaep_label) {
return 0;
@@ -145,15 +145,9 @@ static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx) {
return;
}
- if (rctx->pub_exp) {
- BN_free(rctx->pub_exp);
- }
- if (rctx->tbuf) {
- OPENSSL_free(rctx->tbuf);
- }
- if (rctx->oaep_label) {
- OPENSSL_free(rctx->oaep_label);
- }
+ BN_free(rctx->pub_exp);
+ OPENSSL_free(rctx->tbuf);
+ OPENSSL_free(rctx->oaep_label);
OPENSSL_free(rctx);
}
@@ -369,7 +363,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
0 == (ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))) {
OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl,
EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
- return -2;
+ return 0;
}
if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) &&
rctx->md == NULL) {
@@ -386,13 +380,13 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PSS_SALTLEN);
- return -2;
+ return 0;
}
if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
*(int *)p2 = rctx->saltlen;
} else {
if (p1 < -2) {
- return -2;
+ return 0;
}
rctx->saltlen = p1;
}
@@ -401,14 +395,14 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
if (p1 < 256) {
OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_KEYBITS);
- return -2;
+ return 0;
}
rctx->nbits = p1;
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
if (!p2) {
- return -2;
+ return 0;
}
BN_free(rctx->pub_exp);
rctx->pub_exp = p2;
@@ -418,7 +412,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
- return -2;
+ return 0;
}
if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD) {
*(const EVP_MD **)p2 = rctx->md;
@@ -443,7 +437,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING &&
rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_MGF1_MD);
- return -2;
+ return 0;
}
if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
if (rctx->mgf1md) {
@@ -459,11 +453,9 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
- return -2;
- }
- if (rctx->oaep_label) {
- OPENSSL_free(rctx->oaep_label);
+ return 0;
}
+ OPENSSL_free(rctx->oaep_label);
if (p2 && p1 > 0) {
/* TODO(fork): this seems wrong. Shouldn't it take a copy of the
* buffer? */
@@ -478,16 +470,17 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
- return -2;
+ return 0;
}
- *(uint8_t **)p2 = rctx->oaep_label;
- return rctx->oaep_labellen;
+ CBS_init((CBS *)p2, rctx->oaep_label, rctx->oaep_labellen);
+ return 1;
case EVP_PKEY_CTRL_DIGESTINIT:
return 1;
default:
- return -2;
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_COMMAND_NOT_SUPPORTED);
+ return 0;
}
}
@@ -497,8 +490,9 @@ static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
if (!rctx->pub_exp) {
rctx->pub_exp = BN_new();
- if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4))
+ if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4)) {
return 0;
+ }
}
rsa = RSA_new();
if (!rsa) {
@@ -583,7 +577,7 @@ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, const uint8_t *label,
size_t label_len) {
int label_len_int = label_len;
if (((size_t) label_len_int) != label_len) {
- return -2;
+ return 0;
}
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
@@ -593,6 +587,15 @@ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, const uint8_t *label,
int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
const uint8_t **out_label) {
- return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
- EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *) out_label);
+ CBS label;
+ if (!EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, &label)) {
+ return -1;
+ }
+ if (CBS_len(&label) > INT_MAX) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_get0_rsa_oaep_label, ERR_R_OVERFLOW);
+ return -1;
+ }
+ *out_label = CBS_data(&label);
+ return (int)CBS_len(&label);
}
diff --git a/src/crypto/evp/p_rsa_asn1.c b/src/crypto/evp/p_rsa_asn1.c
index f478d50..1e2d3f6 100644
--- a/src/crypto/evp/p_rsa_asn1.c
+++ b/src/crypto/evp/p_rsa_asn1.c
@@ -245,9 +245,7 @@ static int do_rsa_print(BIO *out, const RSA *rsa, int off,
ret = 1;
err:
- if (m != NULL) {
- OPENSSL_free(m);
- }
+ OPENSSL_free(m);
return ret;
}
@@ -394,12 +392,8 @@ static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
pss = rsa_pss_decode(sigalg, &maskHash);
rv = rsa_pss_param_print(bp, pss, maskHash, indent);
- if (pss) {
- RSA_PSS_PARAMS_free(pss);
- }
- if (maskHash) {
- X509_ALGOR_free(maskHash);
- }
+ RSA_PSS_PARAMS_free(pss);
+ X509_ALGOR_free(maskHash);
if (!rv) {
return 0;
}
@@ -463,12 +457,11 @@ static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
stmp = NULL;
err:
- if (stmp)
- ASN1_STRING_free(stmp);
- if (algtmp)
- X509_ALGOR_free(algtmp);
- if (*palg)
+ ASN1_STRING_free(stmp);
+ X509_ALGOR_free(algtmp);
+ if (*palg) {
return 1;
+ }
return 0;
}
@@ -518,8 +511,8 @@ static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) {
EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
int saltlen, rv = 0;
- if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0 ||
- EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0 ||
+ if (!EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) ||
+ !EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) ||
!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen)) {
goto err;
}
@@ -560,12 +553,15 @@ static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) {
rv = 1;
err:
- if (pss)
+ if (pss) {
RSA_PSS_PARAMS_free(pss);
- if (rv)
+ }
+ if (rv) {
return os;
- if (os)
+ }
+ if (os) {
ASN1_STRING_free(os);
+ }
return NULL;
}
@@ -619,9 +615,9 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
}
if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
- EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
- EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0 ||
- EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) {
+ !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) ||
+ !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) {
goto err;
}
@@ -653,7 +649,7 @@ static evp_digest_sign_algorithm_result_t rsa_digest_sign_algorithm(
EVP_MD_CTX *ctx, X509_ALGOR *sigalg) {
int pad_mode;
EVP_PKEY_CTX *pkctx = ctx->pctx;
- if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) {
+ if (!EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode)) {
return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
}
if (pad_mode == RSA_PKCS1_PSS_PADDING) {
diff --git a/src/crypto/evp/pbkdf_test.cc b/src/crypto/evp/pbkdf_test.cc
new file mode 100644
index 0000000..ae2f405
--- /dev/null
+++ b/src/crypto/evp/pbkdf_test.cc
@@ -0,0 +1,179 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+
+// Prints out the data buffer as a sequence of hex bytes.
+static void PrintDataHex(const void *data, size_t len) {
+ for (size_t i = 0; i < len; ++i) {
+ fprintf(stderr, "%02x", (int)((const uint8_t *)data)[i]);
+ }
+}
+
+// Helper for testing that PBKDF2 derives the expected key from the given
+// inputs. Returns 1 on success, 0 otherwise.
+static bool TestPBKDF2(const void *password, size_t password_len,
+ const void *salt, size_t salt_len, unsigned iterations,
+ const EVP_MD *digest, size_t key_len,
+ const uint8_t *expected_key) {
+ uint8_t key[64];
+
+ if (key_len > sizeof(key)) {
+ fprintf(stderr, "Output buffer is not large enough.\n");
+ return false;
+ }
+
+ if (!PKCS5_PBKDF2_HMAC((const char *)password, password_len,
+ (const uint8_t *)salt, salt_len, iterations, digest,
+ key_len, key)) {
+ fprintf(stderr, "Call to PKCS5_PBKDF2_HMAC failed\n");
+ ERR_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (memcmp(key, expected_key, key_len) != 0) {
+ fprintf(stderr, "Resulting key material does not match expectation\n");
+ fprintf(stderr, "Expected:\n ");
+ PrintDataHex(expected_key, key_len);
+ fprintf(stderr, "\nActual:\n ");
+ PrintDataHex(key, key_len);
+ fprintf(stderr, "\n");
+ return false;
+ }
+
+ return true;
+}
+
+// Tests deriving a key using an empty password (specified both as NULL and as
+// non-NULL). Note that NULL has special meaning to HMAC initialization.
+static bool TestEmptyPassword() {
+ const uint8_t kKey[] = {0xa3, 0x3d, 0xdd, 0xc3, 0x04, 0x78, 0x18,
+ 0x55, 0x15, 0x31, 0x1f, 0x87, 0x52, 0x89,
+ 0x5d, 0x36, 0xea, 0x43, 0x63, 0xa2};
+
+ if (!TestPBKDF2(NULL, 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey) ||
+ !TestPBKDF2("", 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey)) {
+ return false;
+ }
+
+ return true;
+}
+
+// Tests deriving a key using an empty salt. Note that the expectation was
+// generated using OpenSSL itself, and hence is not verified.
+static bool TestEmptySalt() {
+ const uint8_t kKey[] = {0x8b, 0xc2, 0xf9, 0x16, 0x7a, 0x81, 0xcd, 0xcf,
+ 0xad, 0x12, 0x35, 0xcd, 0x90, 0x47, 0xf1, 0x13,
+ 0x62, 0x71, 0xc1, 0xf9, 0x78, 0xfc, 0xfc, 0xb3,
+ 0x5e, 0x22, 0xdb, 0xea, 0xfa, 0x46, 0x34, 0xf6};
+
+ if (!TestPBKDF2("password", 8, NULL, 0, 2, EVP_sha256(), sizeof(kKey),
+ kKey) ||
+ !TestPBKDF2("password", 8, "", 0, 2, EVP_sha256(), sizeof(kKey), kKey)) {
+ return false;
+ }
+
+ return true;
+}
+
+// Exercises test vectors taken from https://tools.ietf.org/html/rfc6070.
+// Note that each of these test vectors uses SHA-1 as the digest.
+static bool TestRFC6070Vectors() {
+ const uint8_t kKey1[] = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e,
+ 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60,
+ 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6};
+ const uint8_t kKey2[] = {0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f,
+ 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d,
+ 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57};
+ const uint8_t kKey3[] = {0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+ 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3};
+
+ if (!TestPBKDF2("password", 8, "salt", 4, 1, EVP_sha1(), sizeof(kKey1),
+ kKey1) ||
+ !TestPBKDF2("password", 8, "salt", 4, 2, EVP_sha1(), sizeof(kKey2),
+ kKey2) ||
+ !TestPBKDF2("pass\0word", 9, "sa\0lt", 5, 4096, EVP_sha1(),
+ sizeof(kKey3), kKey3)) {
+ return false;
+ }
+
+ return true;
+}
+
+// Tests key derivation using SHA-2 digests.
+static bool TestSHA2() {
+ // This test was taken from:
+ // http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors.
+ const uint8_t kKey1[] = {0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
+ 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
+ 0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf,
+ 0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43};
+
+ // This test was taken from:
+ // http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors.
+ const uint8_t kKey2[] = {
+ 0x8c, 0x05, 0x11, 0xf4, 0xc6, 0xe5, 0x97, 0xc6, 0xac, 0x63, 0x15,
+ 0xd8, 0xf0, 0x36, 0x2e, 0x22, 0x5f, 0x3c, 0x50, 0x14, 0x95, 0xba,
+ 0x23, 0xb8, 0x68, 0xc0, 0x05, 0x17, 0x4d, 0xc4, 0xee, 0x71, 0x11,
+ 0x5b, 0x59, 0xf9, 0xe6, 0x0c, 0xd9, 0x53, 0x2f, 0xa3, 0x3e, 0x0f,
+ 0x75, 0xae, 0xfe, 0x30, 0x22, 0x5c, 0x58, 0x3a, 0x18, 0x6c, 0xd8,
+ 0x2b, 0xd4, 0xda, 0xea, 0x97, 0x24, 0xa3, 0xd3, 0xb8};
+
+ if (!TestPBKDF2("password", 8, "salt", 4, 2, EVP_sha256(), sizeof(kKey1),
+ kKey1) ||
+ !TestPBKDF2("passwordPASSWORDpassword", 24,
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096,
+ EVP_sha512(), sizeof(kKey2), kKey2)) {
+ return false;
+ }
+
+ return true;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (!TestEmptyPassword()) {
+ fprintf(stderr, "TestEmptyPassword failed\n");
+ return 1;
+ }
+
+ if (!TestEmptySalt()) {
+ fprintf(stderr, "TestEmptySalt failed\n");
+ return 1;
+ }
+
+ if (!TestRFC6070Vectors()) {
+ fprintf(stderr, "TestRFC6070Vectors failed\n");
+ return 1;
+ }
+
+ if (!TestSHA2()) {
+ fprintf(stderr, "TestSHA2 failed\n");
+ return 1;
+ }
+
+ printf("PASS\n");
+ ERR_free_strings();
+ return 0;
+}
diff --git a/src/crypto/evp/sign.c b/src/crypto/evp/sign.c
index 1faf7c6..ced86bd 100644
--- a/src/crypto/evp/sign.c
+++ b/src/crypto/evp/sign.c
@@ -92,9 +92,9 @@ int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig,
EVP_MD_CTX_cleanup(&tmp_ctx);
pkctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (!pkctx || EVP_PKEY_sign_init(pkctx) <= 0 ||
- EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0 ||
- EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len) <= 0) {
+ if (!pkctx || !EVP_PKEY_sign_init(pkctx) ||
+ !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) ||
+ !EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len)) {
goto out;
}
*out_sig_len = sig_len;
@@ -138,8 +138,8 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
pkctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!pkctx ||
- EVP_PKEY_verify_init(pkctx) <= 0 ||
- EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0) {
+ !EVP_PKEY_verify_init(pkctx) ||
+ !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest)) {
goto out;
}
ret = EVP_PKEY_verify(pkctx, sig, sig_len, m, m_len);
diff --git a/src/crypto/ex_data.c b/src/crypto/ex_data.c
index 0c2503e..10fefc8 100644
--- a/src/crypto/ex_data.c
+++ b/src/crypto/ex_data.c
@@ -108,47 +108,65 @@
#include <openssl/ex_data.h>
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/stack.h>
#include <openssl/thread.h>
-#include "crypto_error.h"
#include "internal.h"
-/* global_impl is the implementation that we use at runtime. */
-static const CRYPTO_EX_DATA_IMPL *global_impl = NULL;
+struct crypto_ex_data_func_st {
+ long argl; /* Arbitary long */
+ void *argp; /* Arbitary void pointer */
+ CRYPTO_EX_new *new_func;
+ CRYPTO_EX_free *free_func;
+ CRYPTO_EX_dup *dup_func;
+};
+
+int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class, int *out_index,
+ long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func) {
+ CRYPTO_EX_DATA_FUNCS *funcs;
+ int ret = 0;
-/* ex_data_default_impl is a the default implementation, defined in
- * ex_data_impl.c. */
-extern const CRYPTO_EX_DATA_IMPL ex_data_default_impl;
+ funcs = OPENSSL_malloc(sizeof(CRYPTO_EX_DATA_FUNCS));
+ if (funcs == NULL) {
+ OPENSSL_PUT_ERROR(CRYPTO, CRYPTO_get_ex_new_index, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
-/* get_impl returns the current ex_data implementatation. */
-static const CRYPTO_EX_DATA_IMPL *get_impl(void) {
- const CRYPTO_EX_DATA_IMPL *impl;
+ funcs->argl = argl;
+ funcs->argp = argp;
+ funcs->new_func = new_func;
+ funcs->dup_func = dup_func;
+ funcs->free_func = free_func;
- CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
- impl = global_impl;
- CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
+ CRYPTO_STATIC_MUTEX_lock_write(&ex_data_class->lock);
- if (impl != NULL) {
- return impl;
+ if (ex_data_class->meth == NULL) {
+ ex_data_class->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null();
}
- CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
- if (global_impl == NULL) {
- global_impl = &ex_data_default_impl;
+ if (ex_data_class->meth == NULL ||
+ !sk_CRYPTO_EX_DATA_FUNCS_push(ex_data_class->meth, funcs)) {
+ OPENSSL_PUT_ERROR(CRYPTO, CRYPTO_get_ex_new_index, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(funcs);
+ goto err;
}
- impl = global_impl;
- CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
- return impl;
-}
-int CRYPTO_get_ex_new_index(int class_value, long argl, void *argp,
- CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
- CRYPTO_EX_free *free_func) {
- const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
- return impl->get_new_index(class_value, argl, argp, new_func, dup_func,
- free_func);
+ *out_index = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth) - 1;
+ ret = 1;
+
+err:
+ CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock);
+ return ret;
}
int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val) {
@@ -183,45 +201,113 @@ void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) {
return sk_void_value(ad->sk, idx);
}
-int CRYPTO_ex_data_new_class(void) {
- const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
- return impl->new_class();
+/* get_func_pointers takes a copy of the CRYPTO_EX_DATA_FUNCS pointers, if any,
+ * for the given class. If there are some pointers, it sets |*out| to point to
+ * a fresh stack of them. Otherwise it sets |*out| to NULL. It returns one on
+ * success or zero on error. */
+static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out,
+ CRYPTO_EX_DATA_CLASS *ex_data_class) {
+ size_t n;
+
+ *out = NULL;
+
+ /* CRYPTO_EX_DATA_FUNCS structures are static once set, so we can take a
+ * shallow copy of the list under lock and then use the structures without
+ * the lock held. */
+ CRYPTO_STATIC_MUTEX_lock_read(&ex_data_class->lock);
+ n = sk_CRYPTO_EX_DATA_FUNCS_num(ex_data_class->meth);
+ if (n > 0) {
+ *out = sk_CRYPTO_EX_DATA_FUNCS_dup(ex_data_class->meth);
+ }
+ CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock);
+
+ if (n > 0 && *out == NULL) {
+ OPENSSL_PUT_ERROR(CRYPTO, get_func_pointers, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
}
-int CRYPTO_new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
- const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
- return impl->new_ex_data(class_value, obj, ad);
+int CRYPTO_new_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, void *obj,
+ CRYPTO_EX_DATA *ad) {
+ STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
+ size_t i;
+
+ ad->sk = NULL;
+
+ if (!get_func_pointers(&func_pointers, ex_data_class)) {
+ return 0;
+ }
+
+ for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
+ CRYPTO_EX_DATA_FUNCS *func_pointer =
+ sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
+ if (func_pointer->new_func) {
+ func_pointer->new_func(obj, NULL, ad, i, func_pointer->argl,
+ func_pointer->argp);
+ }
+ }
+
+ sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
+
+ return 1;
}
-int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to,
+int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, CRYPTO_EX_DATA *to,
const CRYPTO_EX_DATA *from) {
- const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
- return impl->dup_ex_data(class_value, to, from);
-}
+ STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
+ size_t i;
-void CRYPTO_free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
- const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
- impl->free_ex_data(class_value, obj, ad);
-}
+ if (!from->sk) {
+ /* In this case, |from| is blank, which is also the initial state of |to|,
+ * so there's nothing to do. */
+ return 1;
+ }
+
+ if (!get_func_pointers(&func_pointers, ex_data_class)) {
+ return 0;
+ }
-const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void) {
- return get_impl();
+ for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
+ CRYPTO_EX_DATA_FUNCS *func_pointer =
+ sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
+ void *ptr = CRYPTO_get_ex_data(from, i);
+ if (func_pointer->dup_func) {
+ func_pointer->dup_func(to, from, &ptr, i, func_pointer->argl,
+ func_pointer->argp);
+ }
+ CRYPTO_set_ex_data(to, i, ptr);
+ }
+
+ sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
+
+ return 1;
}
-int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *impl) {
- int ret = 0;
+void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, void *obj,
+ CRYPTO_EX_DATA *ad) {
+ STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
+ size_t i;
- CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
- if (global_impl == NULL) {
- ret = 1;
- global_impl = impl;
+ if (!get_func_pointers(&func_pointers, ex_data_class)) {
+ return;
}
- CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
- return ret;
-}
+ for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
+ CRYPTO_EX_DATA_FUNCS *func_pointer =
+ sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
+ if (func_pointer->free_func) {
+ void *ptr = CRYPTO_get_ex_data(ad, i);
+ func_pointer->free_func(obj, ptr, ad, i, func_pointer->argl,
+ func_pointer->argp);
+ }
+ }
-void CRYPTO_cleanup_all_ex_data(void) {
- const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
- impl->cleanup();
+ sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
+
+ sk_void_free(ad->sk);
+ ad->sk = NULL;
}
+
+void CRYPTO_cleanup_all_ex_data(void) {}
diff --git a/src/crypto/ex_data_impl.c b/src/crypto/ex_data_impl.c
deleted file mode 100644
index f55b369..0000000
--- a/src/crypto/ex_data_impl.c
+++ /dev/null
@@ -1,401 +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.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com). */
-
-#include <openssl/ex_data.h>
-
-#include <assert.h>
-
-#include <openssl/err.h>
-#include <openssl/lhash.h>
-#include <openssl/mem.h>
-#include <openssl/stack.h>
-#include <openssl/thread.h>
-
-#include "crypto_error.h"
-#include "internal.h"
-
-typedef struct crypto_ex_data_func_st {
- long argl; /* Arbitary long */
- void *argp; /* Arbitary void pointer */
- CRYPTO_EX_new *new_func;
- CRYPTO_EX_free *free_func;
- CRYPTO_EX_dup *dup_func;
-} CRYPTO_EX_DATA_FUNCS;
-
-typedef struct st_ex_class_item {
- STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth;
- int class_value;
-} EX_CLASS_ITEM;
-
-static LHASH_OF(EX_CLASS_ITEM) *global_classes = NULL;
-
-static int global_next_class = 100;
-
-static int new_class(void) {
- int ret;
- CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
- ret = global_next_class++;
- CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
-
- return ret;
-}
-
-/* class_hash is a hash function used by an LHASH of |EX_CLASS_ITEM|
- * structures. */
-static uint32_t class_hash(const EX_CLASS_ITEM *a) {
- return a->class_value;
-}
-
-/* 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;
-}
-
-/* data_funcs_free is a callback function from |sk_pop_free| that frees a
- * |CRYPTO_EX_DATA_FUNCS|. */
-static void data_funcs_free(CRYPTO_EX_DATA_FUNCS *funcs) {
- OPENSSL_free(funcs);
-}
-
-/* class_free is a callback function from lh_doall to free the EX_CLASS_ITEM
- * structures. */
-static void class_free(EX_CLASS_ITEM *item) {
- sk_CRYPTO_EX_DATA_FUNCS_pop_free(item->meth, data_funcs_free);
- OPENSSL_free(item);
-}
-
-static LHASH_OF(EX_CLASS_ITEM) *get_classes(void) {
- LHASH_OF(EX_CLASS_ITEM) *ret;
-
- CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
- ret = global_classes;
- CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
-
- if (ret != NULL) {
- return ret;
- }
-
- CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
- if (global_classes == NULL) {
- global_classes = lh_EX_CLASS_ITEM_new(class_hash, class_cmp);
- }
- ret = global_classes;
- CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
-
- return ret;
-}
-
-static void cleanup(void) {
- LHASH_OF(EX_CLASS_ITEM) *classes = get_classes();
-
- if (classes != NULL) {
- lh_EX_CLASS_ITEM_doall(classes, class_free);
- lh_EX_CLASS_ITEM_free(classes);
- }
-
- global_classes = NULL;
-}
-
-static EX_CLASS_ITEM *get_class(int class_value) {
- LHASH_OF(EX_CLASS_ITEM) *const classes = get_classes();
- 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);
- if (class_item != NULL) {
- ok = 1;
- } else {
- class_item = OPENSSL_malloc(sizeof(EX_CLASS_ITEM));
- if (class_item) {
- class_item->class_value = class_value;
- class_item->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null();
- if (class_item->meth != NULL) {
- EX_CLASS_ITEM *old_data;
- ok = lh_EX_CLASS_ITEM_insert(classes, &old_data, class_item);
- assert(old_data == NULL);
- }
- }
- }
- CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
-
- if (!ok) {
- if (class_item) {
- if (class_item->meth) {
- sk_CRYPTO_EX_DATA_FUNCS_free(class_item->meth);
- }
- OPENSSL_free(class_item);
- class_item = NULL;
- }
-
- OPENSSL_PUT_ERROR(CRYPTO, get_class, ERR_R_MALLOC_FAILURE);
- }
-
- return class_item;
-}
-
-static int get_new_index(int class_value, long argl, void *argp,
- CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
- CRYPTO_EX_free *free_func) {
- EX_CLASS_ITEM *const item = get_class(class_value);
- CRYPTO_EX_DATA_FUNCS *funcs;
- int ret = -1;
-
- if (!item) {
- return -1;
- }
-
- funcs = OPENSSL_malloc(sizeof(CRYPTO_EX_DATA_FUNCS));
- if (funcs == NULL) {
- OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE);
- return -1;
- }
-
- funcs->argl = argl;
- funcs->argp = argp;
- funcs->new_func = new_func;
- funcs->dup_func = dup_func;
- funcs->free_func = free_func;
-
- CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
-
- if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, funcs)) {
- OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(funcs);
- goto err;
- }
-
- ret = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth) - 1;
-
-err:
- CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
- return ret;
-}
-
-/* get_func_pointers takes a copy of the CRYPTO_EX_DATA_FUNCS pointers, if any,
- * for the given class. If there are some pointers, it sets |*out| to point to
- * a fresh stack of them. Otherwise it sets |*out| to NULL. It returns one on
- * success or zero on error. */
-static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out,
- int class_value) {
- EX_CLASS_ITEM *const item = get_class(class_value);
- size_t n;
-
- if (!item) {
- return 0;
- }
-
- *out = NULL;
-
- /* CRYPTO_EX_DATA_FUNCS structures are static once set, so we can take a
- * shallow copy of the list under lock and then use the structures without
- * the lock held. */
- CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
- n = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth);
- if (n > 0) {
- *out = sk_CRYPTO_EX_DATA_FUNCS_dup(item->meth);
- }
- CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
-
- if (n > 0 && *out == NULL) {
- OPENSSL_PUT_ERROR(CRYPTO, get_func_pointers, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- return 1;
-}
-
-static int new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
- STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
- size_t i;
-
- ad->sk = NULL;
-
- if (!get_func_pointers(&func_pointers, class_value)) {
- return 0;
- }
-
- for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
- CRYPTO_EX_DATA_FUNCS *func_pointer =
- sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
- if (func_pointer->new_func) {
- func_pointer->new_func(obj, NULL, ad, i, func_pointer->argl,
- func_pointer->argp);
- }
- }
-
- sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
-
- return 1;
-}
-
-static int dup_ex_data(int class_value, CRYPTO_EX_DATA *to,
- const CRYPTO_EX_DATA *from) {
- STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
- size_t i;
-
- if (!from->sk) {
- /* In this case, |from| is blank, which is also the initial state of |to|,
- * so there's nothing to do. */
- return 1;
- }
-
- if (!get_func_pointers(&func_pointers, class_value)) {
- return 0;
- }
-
- for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
- CRYPTO_EX_DATA_FUNCS *func_pointer =
- sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
- void *ptr = CRYPTO_get_ex_data(from, i);
- if (func_pointer->dup_func) {
- func_pointer->dup_func(to, from, &ptr, i, func_pointer->argl,
- func_pointer->argp);
- }
- CRYPTO_set_ex_data(to, i, ptr);
- }
-
- sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
-
- return 1;
-}
-
-static void free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
- STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
- size_t i;
-
- if (!get_func_pointers(&func_pointers, class_value)) {
- return;
- }
-
- for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
- CRYPTO_EX_DATA_FUNCS *func_pointer =
- sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
- if (func_pointer->free_func) {
- void *ptr = CRYPTO_get_ex_data(ad, i);
- func_pointer->free_func(obj, ptr, ad, i, func_pointer->argl,
- func_pointer->argp);
- }
- }
-
- sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
-
- if (ad->sk) {
- sk_void_free(ad->sk);
- ad->sk = NULL;
- }
-}
-
-const CRYPTO_EX_DATA_IMPL ex_data_default_impl = {
- new_class, cleanup, get_new_index, new_ex_data, dup_ex_data, free_ex_data};
diff --git a/src/crypto/hkdf/CMakeLists.txt b/src/crypto/hkdf/CMakeLists.txt
index 9666172..f8dd748 100644
--- a/src/crypto/hkdf/CMakeLists.txt
+++ b/src/crypto/hkdf/CMakeLists.txt
@@ -6,7 +6,6 @@ add_library(
OBJECT
hkdf.c
- hkdf_error.c
)
add_executable(
diff --git a/src/crypto/hkdf/hkdf_error.c b/src/crypto/hkdf/hkdf_error.c
deleted file mode 100644
index e1928d6..0000000
--- a/src/crypto/hkdf/hkdf_error.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* 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},
-};
diff --git a/src/crypto/hkdf/hkdf_test.c b/src/crypto/hkdf/hkdf_test.c
index 7467fe0..63070dc 100644
--- a/src/crypto/hkdf/hkdf_test.c
+++ b/src/crypto/hkdf/hkdf_test.c
@@ -15,7 +15,6 @@
#include <stdio.h>
#include <string.h>
-#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@@ -224,7 +223,7 @@ int main(void) {
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);
+ ERR_print_errors_fp(stderr);
return 1;
}
if (memcmp(buf, test->out, test->out_len) != 0) {
diff --git a/src/crypto/hmac/CMakeLists.txt b/src/crypto/hmac/CMakeLists.txt
index e15c956..1a08c55 100644
--- a/src/crypto/hmac/CMakeLists.txt
+++ b/src/crypto/hmac/CMakeLists.txt
@@ -12,7 +12,8 @@ add_library(
add_executable(
hmac_test
- hmac_test.c
+ hmac_test.cc
+ $<TARGET_OBJECTS:test_support>
)
target_link_libraries(hmac_test crypto)
diff --git a/src/crypto/hmac/hmac.c b/src/crypto/hmac/hmac.c
index f179fed..b1b2623 100644
--- a/src/crypto/hmac/hmac.c
+++ b/src/crypto/hmac/hmac.c
@@ -76,7 +76,7 @@ uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len,
}
HMAC_CTX_init(&ctx);
- if (!HMAC_Init(&ctx, key, key_len, evp_md) ||
+ if (!HMAC_Init_ex(&ctx, key, key_len, evp_md, NULL) ||
!HMAC_Update(&ctx, data, data_len) ||
!HMAC_Final(&ctx, out, out_len)) {
out = NULL;
@@ -88,7 +88,6 @@ uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len,
void HMAC_CTX_init(HMAC_CTX *ctx) {
ctx->md = NULL;
- ctx->key_length = 0;
EVP_MD_CTX_init(&ctx->i_ctx);
EVP_MD_CTX_init(&ctx->o_ctx);
EVP_MD_CTX_init(&ctx->md_ctx);
@@ -103,71 +102,66 @@ void HMAC_CTX_cleanup(HMAC_CTX *ctx) {
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
const EVP_MD *md, ENGINE *impl) {
- unsigned i, reset = 0;
- uint8_t pad[HMAC_MAX_MD_CBLOCK];
-
- if (md != NULL) {
- if (ctx->md == NULL && key == NULL && ctx->key_length == 0) {
- /* TODO(eroman): Change the API instead of this hack.
- * If a key hasn't yet been assigned to the context, then default to using
- * an all-zero key. This is to work around callers of
- * HMAC_Init_ex(key=NULL, key_len=0) intending to set a zero-length key.
- * Rather than resulting in uninitialized memory reads, it will
- * predictably use a zero key. */
- memset(ctx->key, 0, sizeof(ctx->key));
- }
- reset = 1;
- ctx->md = md;
- } else {
+ if (md == NULL) {
md = ctx->md;
}
- if (key != NULL) {
+ /* If either |key| is non-NULL or |md| has changed, initialize with a new key
+ * rather than rewinding the previous one.
+ *
+ * TODO(davidben,eroman): Passing the previous |md| with a NULL |key| is
+ * ambiguous between using the empty key and reusing the previous key. There
+ * exist callers which intend the latter, but the former is an awkward edge
+ * case. Fix to API to avoid this. */
+ if (md != ctx->md || key != NULL) {
+ size_t i;
+ uint8_t pad[HMAC_MAX_MD_CBLOCK];
+ uint8_t key_block[HMAC_MAX_MD_CBLOCK];
+ unsigned key_block_len;
+
size_t block_size = EVP_MD_block_size(md);
- reset = 1;
- assert(block_size <= sizeof(ctx->key));
+ assert(block_size <= sizeof(key_block));
if (block_size < key_len) {
+ /* Long keys are hashed. */
if (!EVP_DigestInit_ex(&ctx->md_ctx, md, impl) ||
!EVP_DigestUpdate(&ctx->md_ctx, key, key_len) ||
- !EVP_DigestFinal_ex(&(ctx->md_ctx), ctx->key, &ctx->key_length)) {
- goto err;
+ !EVP_DigestFinal_ex(&ctx->md_ctx, key_block, &key_block_len)) {
+ return 0;
}
} else {
- assert(key_len >= 0 && key_len <= sizeof(ctx->key));
- memcpy(ctx->key, key, key_len);
- ctx->key_length = key_len;
+ assert(key_len >= 0 && key_len <= sizeof(key_block));
+ memcpy(key_block, key, key_len);
+ key_block_len = (unsigned)key_len;
}
- if (ctx->key_length != HMAC_MAX_MD_CBLOCK) {
- memset(&ctx->key[ctx->key_length], 0, sizeof(ctx->key) - ctx->key_length);
+ /* Keys are then padded with zeros. */
+ if (key_block_len != HMAC_MAX_MD_CBLOCK) {
+ memset(&key_block[key_block_len], 0, sizeof(key_block) - key_block_len);
}
- }
- if (reset) {
for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) {
- pad[i] = 0x36 ^ ctx->key[i];
+ pad[i] = 0x36 ^ key_block[i];
}
if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) ||
!EVP_DigestUpdate(&ctx->i_ctx, pad, EVP_MD_block_size(md))) {
- goto err;
+ return 0;
}
for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) {
- pad[i] = 0x5c ^ ctx->key[i];
+ pad[i] = 0x5c ^ key_block[i];
}
if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) ||
!EVP_DigestUpdate(&ctx->o_ctx, pad, EVP_MD_block_size(md))) {
- goto err;
+ return 0;
}
+
+ ctx->md = md;
}
if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->i_ctx)) {
- goto err;
+ return 0;
}
return 1;
-
-err:
- return 0;
}
int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data, size_t data_len) {
@@ -200,8 +194,6 @@ int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src) {
return 0;
}
- memcpy(dest->key, src->key, HMAC_MAX_MD_CBLOCK);
- dest->key_length = src->key_length;
dest->md = src->md;
return 1;
}
diff --git a/src/crypto/hmac/hmac_test.c b/src/crypto/hmac/hmac_test.c
deleted file mode 100644
index ecc418a..0000000
--- a/src/crypto/hmac/hmac_test.c
+++ /dev/null
@@ -1,223 +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 <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/crypto.h>
-#include <openssl/digest.h>
-#include <openssl/hmac.h>
-
-
-struct test_st {
- uint8_t key[16];
- size_t key_len;
- uint8_t data[64];
- size_t data_len;
- const char *hex_digest;
-};
-
-#define NUM_TESTS 4
-
-static const struct test_st kTests[NUM_TESTS] = {
- {
- "", 0, "More text test vectors to stuff up EBCDIC machines :-)", 54,
- "e9139d1e6ee064ef8cf514fc7dc83e86",
- },
- {
- {
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b,
- },
- 16,
- "Hi There",
- 8,
- "9294727a3638bb1c13f48ef8158bfc9d",
- },
- {
- "Jefe", 4, "what do ya want for nothing?", 28,
- "750c783e6ab0b503eaa86e310a5db738",
- },
- {
- {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa,
- },
- 16,
- {
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
- 0xdd, 0xdd,
- },
- 50,
- "56be34521d144c88dbb8c733f0e8b3f6",
- },
-};
-
-static char *to_hex(const uint8_t *md, size_t md_len) {
- size_t i;
- static char buf[80];
-
- for (i = 0; i < md_len; i++) {
- sprintf(&(buf[i * 2]), "%02x", md[i]);
- }
- return buf;
-}
-
-int main(int argc, char *argv[]) {
- unsigned i;
- char *p;
- int err = 0;
- uint8_t out[EVP_MAX_MD_SIZE];
- unsigned out_len;
-
- CRYPTO_library_init();
-
- for (i = 0; i < NUM_TESTS; i++) {
- const struct test_st *test = &kTests[i];
-
- /* Test using the one-shot API. */
- if (NULL == HMAC(EVP_md5(), test->key, test->key_len, test->data,
- test->data_len, out, &out_len)) {
- fprintf(stderr, "%u: HMAC failed.\n", i);
- err++;
- continue;
- }
- p = to_hex(out, out_len);
- if (strcmp(p, test->hex_digest) != 0) {
- fprintf(stderr, "%u: got %s instead of %s\n", i, p, test->hex_digest);
- err++;
- }
-
- /* Test using HMAC_CTX. */
- HMAC_CTX ctx;
- HMAC_CTX_init(&ctx);
- if (!HMAC_Init_ex(&ctx, test->key, test->key_len, EVP_md5(), NULL) ||
- !HMAC_Update(&ctx, test->data, test->data_len) ||
- !HMAC_Final(&ctx, out, &out_len)) {
- fprintf(stderr, "%u: HMAC failed.\n", i);
- err++;
- HMAC_CTX_cleanup(&ctx);
- continue;
- }
- p = to_hex(out, out_len);
- if (strcmp(p, test->hex_digest) != 0) {
- fprintf(stderr, "%u: got %s instead of %s\n", i, p, test->hex_digest);
- err++;
- }
-
- /* Test that an HMAC_CTX may be reset with the same key. */
- if (!HMAC_Init_ex(&ctx, NULL, 0, EVP_md5(), NULL) ||
- !HMAC_Update(&ctx, test->data, test->data_len) ||
- !HMAC_Final(&ctx, out, &out_len)) {
- fprintf(stderr, "%u: HMAC failed.\n", i);
- err++;
- HMAC_CTX_cleanup(&ctx);
- continue;
- }
- p = to_hex(out, out_len);
- if (strcmp(p, test->hex_digest) != 0) {
- fprintf(stderr, "%u: got %s instead of %s\n", i, p, test->hex_digest);
- err++;
- }
-
- HMAC_CTX_cleanup(&ctx);
- }
-
- /* Test that HMAC() uses the empty key when called with key = NULL. */
- const struct test_st *test = &kTests[0];
- assert(test->key_len == 0);
- if (NULL == HMAC(EVP_md5(), NULL, 0, test->data, test->data_len, out,
- &out_len)) {
- fprintf(stderr, "HMAC failed.\n");
- err++;
- } else {
- p = to_hex(out, out_len);
- if (strcmp(p, test->hex_digest) != 0) {
- fprintf(stderr, "got %s instead of %s\n", p, test->hex_digest);
- err++;
- }
- }
-
- /* Test that HMAC_Init, etc., uses the empty key when called initially with
- * key = NULL. */
- assert(test->key_len == 0);
- HMAC_CTX ctx;
- HMAC_CTX_init(&ctx);
- if (!HMAC_Init_ex(&ctx, NULL, 0, EVP_md5(), NULL) ||
- !HMAC_Update(&ctx, test->data, test->data_len) ||
- !HMAC_Final(&ctx, out, &out_len)) {
- fprintf(stderr, "HMAC failed.\n");
- err++;
- } else {
- p = to_hex(out, out_len);
- if (strcmp(p, test->hex_digest) != 0) {
- fprintf(stderr, "got %s instead of %s\n", p, test->hex_digest);
- err++;
- }
- }
- HMAC_CTX_cleanup(&ctx);
-
- if (err) {
- return 1;
- }
-
- printf("PASS\n");
- return 0;
-}
diff --git a/src/crypto/hmac/hmac_test.cc b/src/crypto/hmac/hmac_test.cc
new file mode 100644
index 0000000..d438b70
--- /dev/null
+++ b/src/crypto/hmac/hmac_test.cc
@@ -0,0 +1,171 @@
+/* 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 <string.h>
+
+#include <string>
+#include <vector>
+
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/hmac.h>
+
+#include "../test/file_test.h"
+#include "../test/scoped_types.h"
+#include "../test/stl_compat.h"
+
+
+static const EVP_MD *GetDigest(const std::string &name) {
+ if (name == "MD5") {
+ return EVP_md5();
+ } else if (name == "SHA1") {
+ return EVP_sha1();
+ } else if (name == "SHA224") {
+ return EVP_sha224();
+ } else if (name == "SHA256") {
+ return EVP_sha256();
+ } else if (name == "SHA384") {
+ return EVP_sha384();
+ } else if (name == "SHA512") {
+ return EVP_sha512();
+ }
+ return nullptr;
+}
+
+static bool TestHMAC(FileTest *t, void *arg) {
+ std::string digest_str;
+ if (!t->GetAttribute(&digest_str, "HMAC")) {
+ return false;
+ }
+ const EVP_MD *digest = GetDigest(digest_str);
+ if (digest == nullptr) {
+ t->PrintLine("Unknown digest '%s'", digest_str.c_str());
+ return false;
+ }
+
+ std::vector<uint8_t> key, input, output;
+ if (!t->GetBytes(&key, "Key") ||
+ !t->GetBytes(&input, "Input") ||
+ !t->GetBytes(&output, "Output")) {
+ return false;
+ }
+
+ // Test using the one-shot API.
+ uint8_t mac[EVP_MAX_MD_SIZE];
+ unsigned mac_len;
+ if (nullptr == HMAC(digest, bssl::vector_data(&key), key.size(),
+ bssl::vector_data(&input), input.size(), mac,
+ &mac_len) ||
+ !t->ExpectBytesEqual(bssl::vector_data(&output), output.size(), mac,
+ mac_len)) {
+ t->PrintLine("One-shot API failed.");
+ return false;
+ }
+
+ // Test using HMAC_CTX.
+ ScopedHMAC_CTX ctx;
+ if (!HMAC_Init_ex(ctx.get(), bssl::vector_data(&key), key.size(), digest,
+ nullptr) ||
+ !HMAC_Update(ctx.get(), bssl::vector_data(&input), input.size()) ||
+ !HMAC_Final(ctx.get(), mac, &mac_len) ||
+ !t->ExpectBytesEqual(bssl::vector_data(&output), output.size(), mac,
+ mac_len)) {
+ t->PrintLine("HMAC_CTX failed.");
+ return false;
+ }
+
+ // Test that an HMAC_CTX may be reset with the same key.
+ if (!HMAC_Init_ex(ctx.get(), nullptr, 0, digest, nullptr) ||
+ !HMAC_Update(ctx.get(), bssl::vector_data(&input), input.size()) ||
+ !HMAC_Final(ctx.get(), mac, &mac_len) ||
+ !t->ExpectBytesEqual(bssl::vector_data(&output), output.size(), mac,
+ mac_len)) {
+ t->PrintLine("HMAC_CTX with reset failed.");
+ return false;
+ }
+
+ // Test feeding the input in byte by byte.
+ if (!HMAC_Init_ex(ctx.get(), nullptr, 0, nullptr, nullptr)) {
+ t->PrintLine("HMAC_CTX streaming failed.");
+ return false;
+ }
+ for (size_t i = 0; i < input.size(); i++) {
+ if (!HMAC_Update(ctx.get(), &input[i], 1)) {
+ t->PrintLine("HMAC_CTX streaming failed.");
+ return false;
+ }
+ }
+ if (!HMAC_Final(ctx.get(), mac, &mac_len) ||
+ !t->ExpectBytesEqual(bssl::vector_data(&output), output.size(), mac,
+ mac_len)) {
+ t->PrintLine("HMAC_CTX streaming failed.");
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char *argv[]) {
+ CRYPTO_library_init();
+
+ if (argc != 2) {
+ fprintf(stderr, "%s <test file.txt>\n", argv[0]);
+ return 1;
+ }
+
+ return FileTestMain(TestHMAC, nullptr, argv[1]);
+}
diff --git a/src/crypto/hmac/hmac_tests.txt b/src/crypto/hmac/hmac_tests.txt
new file mode 100644
index 0000000..9caa3c9
--- /dev/null
+++ b/src/crypto/hmac/hmac_tests.txt
@@ -0,0 +1,102 @@
+# This test file is shared between evp_test and hmac_test, to test the legacy
+# EVP_PKEY_HMAC API.
+
+HMAC = MD5
+# Note: The empty key results in passing NULL to HMAC_Init_ex, so this tests
+# that HMAC_CTX and HMAC treat NULL as the empty key initially.
+Key =
+Input = "More text test vectors to stuff up EBCDIC machines :-)"
+Output = e9139d1e6ee064ef8cf514fc7dc83e86
+
+# HMAC tests from RFC2104
+HMAC = MD5
+Key = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+Input = "Hi There"
+Output = 9294727a3638bb1c13f48ef8158bfc9d
+
+HMAC = MD5
+Key = "Jefe"
+Input = "what do ya want for nothing?"
+Output = 750c783e6ab0b503eaa86e310a5db738
+
+HMAC = MD5
+Key = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+Input = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
+Output = 56be34521d144c88dbb8c733f0e8b3f6
+
+# HMAC tests from NIST test data
+
+HMAC = SHA1
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F
+Output = 5FD596EE78D5553C8FF4E72D266DFD192366DA29
+
+HMAC = SHA1
+Input = "Sample message for keylen<blocklen"
+Key = 000102030405060708090A0B0C0D0E0F10111213
+Output = 4C99FF0CB1B31BD33F8431DBAF4D17FCD356A807
+
+HMAC = SHA1
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263
+Output = 2D51B2F7750E410584662E38F133435F4C4FD42A
+
+HMAC = SHA224
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F
+Output = C7405E3AE058E8CD30B08B4140248581ED174CB34E1224BCC1EFC81B
+
+HMAC = SHA224
+Input = "Sample message for keylen<blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B
+Output = E3D249A8CFB67EF8B7A169E9A0A599714A2CECBA65999A51BEB8FBBE
+
+HMAC = SHA224
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263
+Output = 91C52509E5AF8531601AE6230099D90BEF88AAEFB961F4080ABC014D
+
+HMAC = SHA256
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F
+Output = 8BB9A1DB9806F20DF7F77B82138C7914D174D59E13DC4D0169C9057B133E1D62
+
+HMAC = SHA256
+Input = "Sample message for keylen<blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Output = A28CF43130EE696A98F14A37678B56BCFCBDD9E5CF69717FECF5480F0EBDF790
+
+HMAC = SHA256
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60616263
+Output = BDCCB6C72DDEADB500AE768386CB38CC41C63DBB0878DDB9C7A38A431B78378D
+
+HMAC = SHA384
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F
+Output = 63C5DAA5E651847CA897C95814AB830BEDEDC7D25E83EEF9195CD45857A37F448947858F5AF50CC2B1B730DDF29671A9
+
+HMAC = SHA384
+Input = "Sample message for keylen<blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F
+Output = 6EB242BDBB582CA17BEBFA481B1E23211464D2B7F8C20B9FF2201637B93646AF5AE9AC316E98DB45D9CAE773675EEED0
+
+HMAC = SHA384
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7
+Output = 5B664436DF69B0CA22551231A3F0A3D5B4F97991713CFA84BFF4D0792EFF96C27DCCBBB6F79B65D548B40E8564CEF594
+
+HMAC = SHA512
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F
+Output = FC25E240658CA785B7A811A8D3F7B4CA48CFA26A8A366BF2CD1F836B05FCB024BD36853081811D6CEA4216EBAD79DA1CFCB95EA4586B8A0CE356596A55FB1347
+
+HMAC = SHA512
+Input = "Sample message for keylen<blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F
+Output = FD44C18BDA0BB0A6CE0E82B031BF2818F6539BD56EC00BDC10A8A2D730B3634DE2545D639B0F2CF710D0692C72A1896F1F211C2B922D1A96C392E07E7EA9FEDC
+
+HMAC = SHA512
+Input = "Sample message for keylen=blocklen"
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7
+Output = D93EC8D2DE1AD2A9957CB9B83F14E76AD6B5E0CCE285079A127D3B14BCCB7AA7286D4AC0D4CE64215F2BC9E6870B33D97438BE4AAA20CDA5C5A912B48B8E27F3
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index 4336e65..42125db 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -110,26 +110,62 @@
#define OPENSSL_HEADER_CRYPTO_INTERNAL_H
#include <openssl/ex_data.h>
+#include <openssl/thread.h>
+
+#if defined(OPENSSL_NO_THREADS)
+#elif defined(OPENSSL_WINDOWS)
+#pragma warning(push, 3)
+#include <windows.h>
+#pragma warning(pop)
+#else
+#include <pthread.h>
+#endif
#if defined(__cplusplus)
extern "C" {
#endif
-/* st_CRYPTO_EX_DATA_IMPL contains an ex_data implementation. See the comments
- * in ex_data.h for details of the behaviour of each of the functions. */
-struct st_CRYPTO_EX_DATA_IMPL {
- int (*new_class)(void);
- void (*cleanup)(void);
+/* MSVC's C4701 warning about the use of *potentially*--as opposed to
+ * *definitely*--uninitialized values sometimes has false positives. Usually
+ * the false positives can and should be worked around by simplifying the
+ * control flow. When that is not practical, annotate the function containing
+ * the code that triggers the warning with
+ * OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS after its parameters:
+ *
+ * void f() OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS {
+ * ...
+ * }
+ *
+ * Note that MSVC's control flow analysis seems to operate on a whole-function
+ * basis, so the annotation must be placed on the entire function, not just a
+ * block within the function. */
+#if defined(_MSC_VER)
+#define OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS \
+ __pragma(warning(suppress:4701))
+#else
+#define OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
+#endif
- int (*get_new_index)(int class_value, long argl, void *argp,
- CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
- CRYPTO_EX_free *free_func);
- int (*new_ex_data)(int class_value, void *obj, CRYPTO_EX_DATA *ad);
- int (*dup_ex_data)(int class_value, CRYPTO_EX_DATA *to,
- const CRYPTO_EX_DATA *from);
- void (*free_ex_data)(int class_value, void *obj, CRYPTO_EX_DATA *ad);
-};
+/* MSVC will sometimes correctly detect unreachable code and issue a warning,
+ * which breaks the build since we treat errors as warnings, in some rare cases
+ * where we want to allow the dead code to continue to exist. In these
+ * situations, annotate the function containing the unreachable code with
+ * OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS after its parameters:
+ *
+ * void f() OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
+ * ...
+ * }
+ *
+ * Note that MSVC's reachability analysis seems to operate on a whole-function
+ * basis, so the annotation must be placed on the entire function, not just a
+ * block within the function. */
+#if defined(_MSC_VER)
+#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS \
+ __pragma(warning(suppress:4702))
+#else
+#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS
+#endif
#if defined(_MSC_VER)
@@ -295,6 +331,185 @@ static inline int constant_time_select_int(unsigned int mask, int a, int b) {
}
+/* Thread-safe initialisation. */
+
+#if defined(OPENSSL_NO_THREADS)
+typedef uint32_t CRYPTO_once_t;
+#define CRYPTO_ONCE_INIT 0
+#elif defined(OPENSSL_WINDOWS)
+typedef LONG CRYPTO_once_t;
+#define CRYPTO_ONCE_INIT 0
+#else
+typedef pthread_once_t CRYPTO_once_t;
+#define CRYPTO_ONCE_INIT PTHREAD_ONCE_INIT
+#endif
+
+/* CRYPTO_once calls |init| exactly once per process. This is thread-safe: if
+ * concurrent threads call |CRYPTO_once| with the same |CRYPTO_once_t| argument
+ * then they will block until |init| completes, but |init| will have only been
+ * called once.
+ *
+ * The |once| argument must be a |CRYPTO_once_t| that has been initialised with
+ * the value |CRYPTO_ONCE_INIT|. */
+OPENSSL_EXPORT void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void));
+
+
+/* Locks.
+ *
+ * Two types of locks are defined: |CRYPTO_MUTEX|, which can be used in
+ * structures as normal, and |struct CRYPTO_STATIC_MUTEX|, which can be used as
+ * a global lock. A global lock must be initialised to the value
+ * |CRYPTO_STATIC_MUTEX_INIT|.
+ *
+ * |CRYPTO_MUTEX| can appear in public structures and so is defined in
+ * thread.h.
+ *
+ * The global lock is a different type because there's no static initialiser
+ * value on Windows for locks, so global locks have to be coupled with a
+ * |CRYPTO_once_t| to ensure that the lock is setup before use. This is done
+ * automatically by |CRYPTO_STATIC_MUTEX_lock_*|. */
+
+#if defined(OPENSSL_NO_THREADS)
+struct CRYPTO_STATIC_MUTEX {};
+#define CRYPTO_STATIC_MUTEX_INIT {}
+#elif defined(OPENSSL_WINDOWS)
+struct CRYPTO_STATIC_MUTEX {
+ CRYPTO_once_t once;
+ CRITICAL_SECTION lock;
+};
+#define CRYPTO_STATIC_MUTEX_INIT { CRYPTO_ONCE_INIT, { 0 } }
+#else
+struct CRYPTO_STATIC_MUTEX {
+ pthread_rwlock_t lock;
+};
+#define CRYPTO_STATIC_MUTEX_INIT { PTHREAD_RWLOCK_INITIALIZER }
+#endif
+
+/* CRYPTO_MUTEX_init initialises |lock|. If |lock| is a static variable, use a
+ * |CRYPTO_STATIC_MUTEX|. */
+void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock);
+
+/* CRYPTO_MUTEX_lock_read locks |lock| such that other threads may also have a
+ * read lock, but none may have a write lock. (On Windows, read locks are
+ * actually fully exclusive.) */
+void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock);
+
+/* CRYPTO_MUTEX_lock_write locks |lock| such that no other thread has any type
+ * of lock on it. */
+void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock);
+
+/* CRYPTO_MUTEX_unlock unlocks |lock|. */
+void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock);
+
+/* CRYPTO_MUTEX_cleanup releases all resources held by |lock|. */
+void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock);
+
+/* CRYPTO_STATIC_MUTEX_lock_read locks |lock| such that other threads may also
+ * have a read lock, but none may have a write lock. The |lock| variable does
+ * not need to be initialised by any function, but must have been statically
+ * initialised with |CRYPTO_STATIC_MUTEX_INIT|. */
+void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock);
+
+/* CRYPTO_STATIC_MUTEX_lock_write locks |lock| such that no other thread has
+ * any type of lock on it. The |lock| variable does not need to be initialised
+ * by any function, but must have been statically initialised with
+ * |CRYPTO_STATIC_MUTEX_INIT|. */
+void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock);
+
+/* CRYPTO_STATIC_MUTEX_unlock unlocks |lock|. */
+void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock);
+
+
+/* Thread local storage. */
+
+/* thread_local_data_t enumerates the types of thread-local data that can be
+ * stored. */
+typedef enum {
+ OPENSSL_THREAD_LOCAL_ERR = 0,
+ OPENSSL_THREAD_LOCAL_RAND,
+ OPENSSL_THREAD_LOCAL_TEST,
+ NUM_OPENSSL_THREAD_LOCALS,
+} thread_local_data_t;
+
+/* thread_local_destructor_t is the type of a destructor function that will be
+ * called when a thread exits and its thread-local storage needs to be freed. */
+typedef void (*thread_local_destructor_t)(void *);
+
+/* CRYPTO_get_thread_local gets the pointer value that is stored for the
+ * current thread for the given index, or NULL if none has been set. */
+OPENSSL_EXPORT void *CRYPTO_get_thread_local(thread_local_data_t value);
+
+/* CRYPTO_set_thread_local sets a pointer value for the current thread at the
+ * given index. This function should only be called once per thread for a given
+ * |index|: rather than update the pointer value itself, update the data that
+ * is pointed to.
+ *
+ * The destructor function will be called when a thread exits to free this
+ * thread-local data. All calls to |CRYPTO_set_thread_local| with the same
+ * |index| should have the same |destructor| argument. The destructor may be
+ * called with a NULL argument if a thread that never set a thread-local
+ * pointer for |index|, exits. The destructor may be called concurrently with
+ * different arguments.
+ *
+ * This function returns one on success or zero on error. If it returns zero
+ * then |destructor| has been called with |value| already. */
+OPENSSL_EXPORT int CRYPTO_set_thread_local(
+ thread_local_data_t index, void *value,
+ thread_local_destructor_t destructor);
+
+
+/* ex_data */
+
+typedef struct crypto_ex_data_func_st CRYPTO_EX_DATA_FUNCS;
+
+/* CRYPTO_EX_DATA_CLASS tracks the ex_indices registered for a type which
+ * supports ex_data. It should defined as a static global within the module
+ * which defines that type. */
+typedef struct {
+ struct CRYPTO_STATIC_MUTEX lock;
+ STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth;
+} CRYPTO_EX_DATA_CLASS;
+
+#define CRYPTO_EX_DATA_CLASS_INIT {CRYPTO_STATIC_MUTEX_INIT, NULL}
+
+/* CRYPTO_get_ex_new_index allocates a new index for |ex_data_class| and writes
+ * it to |*out_index|. Each class of object should provide a wrapper function
+ * that uses the correct |CRYPTO_EX_DATA_CLASS|. It returns one on success and
+ * zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_get_ex_new_index(CRYPTO_EX_DATA_CLASS *ex_data_class,
+ int *out_index, long argl,
+ void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func);
+
+/* CRYPTO_set_ex_data sets an extra data pointer on a given object. Each class
+ * of object should provide a wrapper function. */
+OPENSSL_EXPORT int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val);
+
+/* CRYPTO_get_ex_data returns an extra data pointer for a given object, or NULL
+ * if no such index exists. Each class of object should provide a wrapper
+ * function. */
+OPENSSL_EXPORT void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int index);
+
+/* CRYPTO_new_ex_data initialises a newly allocated |CRYPTO_EX_DATA| which is
+ * embedded inside of |obj| which is of class |ex_data_class|. Returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_new_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class,
+ void *obj, CRYPTO_EX_DATA *ad);
+
+/* CRYPTO_dup_ex_data duplicates |from| into a freshly allocated
+ * |CRYPTO_EX_DATA|, |to|. Both of which are inside objects of the given
+ * class. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_dup_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class,
+ CRYPTO_EX_DATA *to,
+ const CRYPTO_EX_DATA *from);
+
+/* CRYPTO_free_ex_data frees |ad|, which is embedded inside |obj|, which is an
+ * object of the given class. */
+OPENSSL_EXPORT void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class,
+ void *obj, CRYPTO_EX_DATA *ad);
+
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/src/crypto/lhash/make_macros.sh b/src/crypto/lhash/make_macros.sh
index 79d1e57..8a876af 100644
--- a/src/crypto/lhash/make_macros.sh
+++ b/src/crypto/lhash/make_macros.sh
@@ -1,6 +1,9 @@
#!/bin/sh
-cat > lhash_macros.h << EOF
+include_dir=../../include/openssl
+out=${include_dir}/lhash_macros.h
+
+cat > $out << EOF
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -24,7 +27,7 @@ EOF
output_lhash () {
type=$1
- cat >> lhash_macros.h << EOF
+ cat >> $out << EOF
/* ${type} */
#define lh_${type}_new(hash, comp)\\
((LHASH_OF(${type})*) lh_new(CHECKED_CAST(lhash_hash_func, uint32_t (*) (const ${type} *), hash), CHECKED_CAST(lhash_cmp_func, int (*) (const ${type} *a, const ${type} *b), comp)))
@@ -54,11 +57,11 @@ output_lhash () {
EOF
}
-lhash_types=$(cat lhash.h | grep '^ \* LHASH_OF:' | sed -e 's/.*LHASH_OF://' -e 's/ .*//')
+lhash_types=$(cat ${include_dir}/lhash.h | grep '^ \* LHASH_OF:' | sed -e 's/.*LHASH_OF://' -e 's/ .*//')
for type in $lhash_types; do
echo Hash of ${type}
output_lhash "${type}"
done
-clang-format -i lhash_macros.h
+clang-format -i $out
diff --git a/src/crypto/md4/md4.c b/src/crypto/md4/md4.c
index 8fb357b..6150b96 100644
--- a/src/crypto/md4/md4.c
+++ b/src/crypto/md4/md4.c
@@ -56,6 +56,7 @@
#include <openssl/md4.h>
+#include <stdlib.h>
#include <string.h>
diff --git a/src/crypto/modes/asm/ghash-armv4.pl b/src/crypto/modes/asm/ghash-armv4.pl
index b324641..25a4e27 100644
--- a/src/crypto/modes/asm/ghash-armv4.pl
+++ b/src/crypto/modes/asm/ghash-armv4.pl
@@ -42,8 +42,8 @@
# below and combine it with reduction algorithm from x86 module.
# Performance improvement over previous version varies from 65% on
# Snapdragon S4 to 110% on Cortex A9. In absolute terms Cortex A8
-# processes one byte in 8.45 cycles, A9 - in 10.2, Snapdragon S4 -
-# in 9.33.
+# processes one byte in 8.45 cycles, A9 - in 10.2, A15 - in 7.63,
+# Snapdragon S4 - in 9.33.
#
# Câmara, D.; Gouvêa, C. P. L.; López, J. & Dahab, R.: Fast Software
# Polynomial Multiplication on ARM Processors using the NEON Engine.
@@ -71,8 +71,20 @@
# *native* byte order on current platform. See gcm128.c for working
# example...
-while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
$Xi="r0"; # argument block
$Htbl="r1";
@@ -129,6 +141,11 @@ $code=<<___;
.text
.code 32
+#ifdef __APPLE__
+#define ldrplb ldrbpl
+#define ldrneb ldrbne
+#endif
+
.type rem_4bit,%object
.align 5
rem_4bit:
@@ -370,7 +387,8 @@ ___
}
$code.=<<___;
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
.fpu neon
.global gcm_init_neon
@@ -378,9 +396,9 @@ $code.=<<___;
.type gcm_init_neon,%function
.align 4
gcm_init_neon:
- vld1.64 $IN#hi,[r1,:64]! @ load H
+ vld1.64 $IN#hi,[r1]! @ load H
vmov.i8 $t0,#0xe1
- vld1.64 $IN#lo,[r1,:64]
+ vld1.64 $IN#lo,[r1]
vshl.i64 $t0#hi,#57
vshr.u64 $t0#lo,#63 @ t0=0xc2....01
vdup.8 $t1,$IN#hi[7]
@@ -392,7 +410,7 @@ gcm_init_neon:
veor $IN,$IN,$t0 @ twisted H
vstmia r0,{$IN}
- bx lr
+ ret @ bx lr
.size gcm_init_neon,.-gcm_init_neon
.global gcm_gmult_neon
@@ -400,8 +418,8 @@ gcm_init_neon:
.type gcm_gmult_neon,%function
.align 4
gcm_gmult_neon:
- vld1.64 $IN#hi,[$Xi,:64]! @ load Xi
- vld1.64 $IN#lo,[$Xi,:64]!
+ vld1.64 $IN#hi,[$Xi]! @ load Xi
+ vld1.64 $IN#lo,[$Xi]!
vmov.i64 $k48,#0x0000ffffffffffff
vldmia $Htbl,{$Hlo-$Hhi} @ load twisted H
vmov.i64 $k32,#0x00000000ffffffff
@@ -419,8 +437,8 @@ gcm_gmult_neon:
.type gcm_ghash_neon,%function
.align 4
gcm_ghash_neon:
- vld1.64 $Xl#hi,[$Xi,:64]! @ load Xi
- vld1.64 $Xl#lo,[$Xi,:64]!
+ vld1.64 $Xl#hi,[$Xi]! @ load Xi
+ vld1.64 $Xl#lo,[$Xi]!
vmov.i64 $k48,#0x0000ffffffffffff
vldmia $Htbl,{$Hlo-$Hhi} @ load twisted H
vmov.i64 $k32,#0x00000000ffffffff
@@ -475,10 +493,10 @@ $code.=<<___;
vrev64.8 $Xl,$Xl
#endif
sub $Xi,#16
- vst1.64 $Xl#hi,[$Xi,:64]! @ write out Xi
- vst1.64 $Xl#lo,[$Xi,:64]
+ vst1.64 $Xl#hi,[$Xi]! @ write out Xi
+ vst1.64 $Xl#lo,[$Xi]
- bx lr
+ ret @ bx lr
.size gcm_ghash_neon,.-gcm_ghash_neon
#endif
___
@@ -494,6 +512,7 @@ foreach (split("\n",$code)) {
s/\`([^\`]*)\`/eval $1/geo;
s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
+ s/\bret\b/bx lr/go or
s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4
print $_,"\n";
diff --git a/src/crypto/modes/asm/ghash-x86.pl b/src/crypto/modes/asm/ghash-x86.pl
index eb6d55e..23a5527 100644
--- a/src/crypto/modes/asm/ghash-x86.pl
+++ b/src/crypto/modes/asm/ghash-x86.pl
@@ -131,8 +131,8 @@ require "x86asm.pl";
&asm_init($ARGV[0],"ghash-x86.pl",$x86only = $ARGV[$#ARGV] eq "386");
-$sse2=1;
-#for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+$sse2=0;
+for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
($Zhh,$Zhl,$Zlh,$Zll) = ("ebp","edx","ecx","ebx");
$inp = "edi";
diff --git a/src/crypto/modes/asm/ghashv8-armx.pl b/src/crypto/modes/asm/ghashv8-armx.pl
index 08c8775..686951f 100644
--- a/src/crypto/modes/asm/ghashv8-armx.pl
+++ b/src/crypto/modes/asm/ghashv8-armx.pl
@@ -16,17 +16,31 @@
# other assembly modules. Just like aesv8-armx.pl this module
# supports both AArch32 and AArch64 execution modes.
#
+# July 2014
+#
+# Implement 2x aggregated reduction [see ghash-x86.pl for background
+# information].
+#
# Current performance in cycles per processed byte:
#
# PMULL[2] 32-bit NEON(*)
-# Apple A7 1.76 5.62
-# Cortex-A53 1.45 8.39
-# Cortex-A57 2.22 7.61
+# Apple A7 0.92 5.62
+# Cortex-A53 1.01 8.39
+# Cortex-A57 1.17 7.61
+# Denver 0.71 6.02
#
# (*) presented for reference/comparison purposes;
$flavour = shift;
-open STDOUT,">".shift;
+$output = shift;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
$Xi="x0"; # argument block
$Htbl="x1";
@@ -37,128 +51,291 @@ $inc="x12";
{
my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3));
-my ($t0,$t1,$t2,$t3,$H,$Hhl)=map("q$_",(8..14));
+my ($t0,$t1,$t2,$xC2,$H,$Hhl,$H2)=map("q$_",(8..14));
$code=<<___;
#include "arm_arch.h"
.text
___
-$code.=<<___ if ($flavour =~ /64/);
+$code.=<<___ if ($flavour =~ /64/);
#if !defined(__clang__)
-.arch armv8-a+crypto
+.arch armv8-a+crypto
#endif
___
$code.=".fpu neon\n.code 32\n" if ($flavour !~ /64/);
+################################################################################
+# void gcm_init_v8(u128 Htable[16],const u64 H[2]);
+#
+# input: 128-bit H - secret parameter E(K,0^128)
+# output: precomputed table filled with degrees of twisted H;
+# H is twisted to handle reverse bitness of GHASH;
+# only few of 16 slots of Htable[16] are used;
+# data is opaque to outside world (which allows to
+# optimize the code independently);
+#
$code.=<<___;
.global gcm_init_v8
.type gcm_init_v8,%function
.align 4
gcm_init_v8:
- vld1.64 {$t1},[x1] @ load H
- vmov.i8 $t0,#0xe1
+ vld1.64 {$t1},[x1] @ load input H
+ vmov.i8 $xC2,#0xe1
+ vshl.i64 $xC2,$xC2,#57 @ 0xc2.0
vext.8 $IN,$t1,$t1,#8
- vshl.i64 $t0,$t0,#57
- vshr.u64 $t2,$t0,#63
- vext.8 $t0,$t2,$t0,#8 @ t0=0xc2....01
+ vshr.u64 $t2,$xC2,#63
vdup.32 $t1,${t1}[1]
- vshr.u64 $t3,$IN,#63
+ vext.8 $t0,$t2,$xC2,#8 @ t0=0xc2....01
+ vshr.u64 $t2,$IN,#63
vshr.s32 $t1,$t1,#31 @ broadcast carry bit
- vand $t3,$t3,$t0
+ vand $t2,$t2,$t0
vshl.i64 $IN,$IN,#1
- vext.8 $t3,$t3,$t3,#8
+ vext.8 $t2,$t2,$t2,#8
vand $t0,$t0,$t1
- vorr $IN,$IN,$t3 @ H<<<=1
- veor $IN,$IN,$t0 @ twisted H
- vst1.64 {$IN},[x0]
+ vorr $IN,$IN,$t2 @ H<<<=1
+ veor $H,$IN,$t0 @ twisted H
+ vst1.64 {$H},[x0],#16 @ store Htable[0]
+
+ @ calculate H^2
+ vext.8 $t0,$H,$H,#8 @ Karatsuba pre-processing
+ vpmull.p64 $Xl,$H,$H
+ veor $t0,$t0,$H
+ vpmull2.p64 $Xh,$H,$H
+ vpmull.p64 $Xm,$t0,$t0
+
+ vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing
+ veor $t2,$Xl,$Xh
+ veor $Xm,$Xm,$t1
+ veor $Xm,$Xm,$t2
+ vpmull.p64 $t2,$Xl,$xC2 @ 1st phase
+
+ vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result
+ vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl
+ veor $Xl,$Xm,$t2
+
+ vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase
+ vpmull.p64 $Xl,$Xl,$xC2
+ veor $t2,$t2,$Xh
+ veor $H2,$Xl,$t2
+
+ vext.8 $t1,$H2,$H2,#8 @ Karatsuba pre-processing
+ veor $t1,$t1,$H2
+ vext.8 $Hhl,$t0,$t1,#8 @ pack Karatsuba pre-processed
+ vst1.64 {$Hhl-$H2},[x0] @ store Htable[1..2]
ret
.size gcm_init_v8,.-gcm_init_v8
-
+___
+################################################################################
+# void gcm_gmult_v8(u64 Xi[2],const u128 Htable[16]);
+#
+# input: Xi - current hash value;
+# Htable - table precomputed in gcm_init_v8;
+# output: Xi - next hash value Xi;
+#
+$code.=<<___;
.global gcm_gmult_v8
.type gcm_gmult_v8,%function
.align 4
gcm_gmult_v8:
vld1.64 {$t1},[$Xi] @ load Xi
- vmov.i8 $t3,#0xe1
- vld1.64 {$H},[$Htbl] @ load twisted H
- vshl.u64 $t3,$t3,#57
+ vmov.i8 $xC2,#0xe1
+ vld1.64 {$H-$Hhl},[$Htbl] @ load twisted H, ...
+ vshl.u64 $xC2,$xC2,#57
#ifndef __ARMEB__
vrev64.8 $t1,$t1
#endif
- vext.8 $Hhl,$H,$H,#8
- mov $len,#0
vext.8 $IN,$t1,$t1,#8
- mov $inc,#0
- veor $Hhl,$Hhl,$H @ Karatsuba pre-processing
- mov $inp,$Xi
- b .Lgmult_v8
-.size gcm_gmult_v8,.-gcm_gmult_v8
+ vpmull.p64 $Xl,$H,$IN @ H.lo·Xi.lo
+ veor $t1,$t1,$IN @ Karatsuba pre-processing
+ vpmull2.p64 $Xh,$H,$IN @ H.hi·Xi.hi
+ vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi)
+
+ vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing
+ veor $t2,$Xl,$Xh
+ veor $Xm,$Xm,$t1
+ veor $Xm,$Xm,$t2
+ vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction
+
+ vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result
+ vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl
+ veor $Xl,$Xm,$t2
+
+ vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction
+ vpmull.p64 $Xl,$Xl,$xC2
+ veor $t2,$t2,$Xh
+ veor $Xl,$Xl,$t2
+
+#ifndef __ARMEB__
+ vrev64.8 $Xl,$Xl
+#endif
+ vext.8 $Xl,$Xl,$Xl,#8
+ vst1.64 {$Xl},[$Xi] @ write out Xi
+
+ ret
+.size gcm_gmult_v8,.-gcm_gmult_v8
+___
+################################################################################
+# void gcm_ghash_v8(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
+#
+# input: table precomputed in gcm_init_v8;
+# current hash value Xi;
+# pointer to input data;
+# length of input data in bytes, but divisible by block size;
+# output: next hash value Xi;
+#
+$code.=<<___;
.global gcm_ghash_v8
.type gcm_ghash_v8,%function
.align 4
gcm_ghash_v8:
+___
+$code.=<<___ if ($flavour !~ /64/);
+ vstmdb sp!,{d8-d15} @ 32-bit ABI says so
+___
+$code.=<<___;
vld1.64 {$Xl},[$Xi] @ load [rotated] Xi
- subs $len,$len,#16
- vmov.i8 $t3,#0xe1
- mov $inc,#16
- vld1.64 {$H},[$Htbl] @ load twisted H
- cclr $inc,eq
- vext.8 $Xl,$Xl,$Xl,#8
- vshl.u64 $t3,$t3,#57
- vld1.64 {$t1},[$inp],$inc @ load [rotated] inp
- vext.8 $Hhl,$H,$H,#8
+ @ "[rotated]" means that
+ @ loaded value would have
+ @ to be rotated in order to
+ @ make it appear as in
+ @ alorithm specification
+ subs $len,$len,#32 @ see if $len is 32 or larger
+ mov $inc,#16 @ $inc is used as post-
+ @ increment for input pointer;
+ @ as loop is modulo-scheduled
+ @ $inc is zeroed just in time
+ @ to preclude oversteping
+ @ inp[len], which means that
+ @ last block[s] are actually
+ @ loaded twice, but last
+ @ copy is not processed
+ vld1.64 {$H-$Hhl},[$Htbl],#32 @ load twisted H, ..., H^2
+ vmov.i8 $xC2,#0xe1
+ vld1.64 {$H2},[$Htbl]
+ cclr $inc,eq @ is it time to zero $inc?
+ vext.8 $Xl,$Xl,$Xl,#8 @ rotate Xi
+ vld1.64 {$t0},[$inp],#16 @ load [rotated] I[0]
+ vshl.u64 $xC2,$xC2,#57 @ compose 0xc2.0 constant
#ifndef __ARMEB__
+ vrev64.8 $t0,$t0
vrev64.8 $Xl,$Xl
+#endif
+ vext.8 $IN,$t0,$t0,#8 @ rotate I[0]
+ b.lo .Lodd_tail_v8 @ $len was less than 32
+___
+{ my ($Xln,$Xmn,$Xhn,$In) = map("q$_",(4..7));
+ #######
+ # Xi+2 =[H*(Ii+1 + Xi+1)] mod P =
+ # [(H*Ii+1) + (H*Xi+1)] mod P =
+ # [(H*Ii+1) + H^2*(Ii+Xi)] mod P
+ #
+$code.=<<___;
+ vld1.64 {$t1},[$inp],$inc @ load [rotated] I[1]
+#ifndef __ARMEB__
vrev64.8 $t1,$t1
#endif
- veor $Hhl,$Hhl,$H @ Karatsuba pre-processing
- vext.8 $IN,$t1,$t1,#8
- b .Loop_v8
+ vext.8 $In,$t1,$t1,#8
+ veor $IN,$IN,$Xl @ I[i]^=Xi
+ vpmull.p64 $Xln,$H,$In @ H·Ii+1
+ veor $t1,$t1,$In @ Karatsuba pre-processing
+ vpmull2.p64 $Xhn,$H,$In
+ b .Loop_mod2x_v8
.align 4
-.Loop_v8:
+.Loop_mod2x_v8:
+ vext.8 $t2,$IN,$IN,#8
+ subs $len,$len,#32 @ is there more data?
+ vpmull.p64 $Xl,$H2,$IN @ H^2.lo·Xi.lo
+ cclr $inc,lo @ is it time to zero $inc?
+
+ vpmull.p64 $Xmn,$Hhl,$t1
+ veor $t2,$t2,$IN @ Karatsuba pre-processing
+ vpmull2.p64 $Xh,$H2,$IN @ H^2.hi·Xi.hi
+ veor $Xl,$Xl,$Xln @ accumulate
+ vpmull2.p64 $Xm,$Hhl,$t2 @ (H^2.lo+H^2.hi)·(Xi.lo+Xi.hi)
+ vld1.64 {$t0},[$inp],$inc @ load [rotated] I[i+2]
+
+ veor $Xh,$Xh,$Xhn
+ cclr $inc,eq @ is it time to zero $inc?
+ veor $Xm,$Xm,$Xmn
+
+ vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing
+ veor $t2,$Xl,$Xh
+ veor $Xm,$Xm,$t1
+ vld1.64 {$t1},[$inp],$inc @ load [rotated] I[i+3]
+#ifndef __ARMEB__
+ vrev64.8 $t0,$t0
+#endif
+ veor $Xm,$Xm,$t2
+ vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction
+
+#ifndef __ARMEB__
+ vrev64.8 $t1,$t1
+#endif
+ vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result
+ vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl
+ vext.8 $In,$t1,$t1,#8
+ vext.8 $IN,$t0,$t0,#8
+ veor $Xl,$Xm,$t2
+ vpmull.p64 $Xln,$H,$In @ H·Ii+1
+ veor $IN,$IN,$Xh @ accumulate $IN early
+
+ vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction
+ vpmull.p64 $Xl,$Xl,$xC2
+ veor $IN,$IN,$t2
+ veor $t1,$t1,$In @ Karatsuba pre-processing
+ veor $IN,$IN,$Xl
+ vpmull2.p64 $Xhn,$H,$In
+ b.hs .Loop_mod2x_v8 @ there was at least 32 more bytes
+
+ veor $Xh,$Xh,$t2
+ vext.8 $IN,$t0,$t0,#8 @ re-construct $IN
+ adds $len,$len,#32 @ re-construct $len
+ veor $Xl,$Xl,$Xh @ re-construct $Xl
+ b.eq .Ldone_v8 @ is $len zero?
+___
+}
+$code.=<<___;
+.Lodd_tail_v8:
vext.8 $t2,$Xl,$Xl,#8
veor $IN,$IN,$Xl @ inp^=Xi
- veor $t1,$t1,$t2 @ $t1 is rotated inp^Xi
+ veor $t1,$t0,$t2 @ $t1 is rotated inp^Xi
-.Lgmult_v8:
vpmull.p64 $Xl,$H,$IN @ H.lo·Xi.lo
veor $t1,$t1,$IN @ Karatsuba pre-processing
vpmull2.p64 $Xh,$H,$IN @ H.hi·Xi.hi
- subs $len,$len,#16
vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi)
- cclr $inc,eq
vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing
veor $t2,$Xl,$Xh
veor $Xm,$Xm,$t1
- vld1.64 {$t1},[$inp],$inc @ load [rotated] inp
veor $Xm,$Xm,$t2
- vpmull.p64 $t2,$Xl,$t3 @ 1st phase
+ vpmull.p64 $t2,$Xl,$xC2 @ 1st phase of reduction
vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result
vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl
-#ifndef __ARMEB__
- vrev64.8 $t1,$t1
-#endif
veor $Xl,$Xm,$t2
- vext.8 $IN,$t1,$t1,#8
- vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase
- vpmull.p64 $Xl,$Xl,$t3
+ vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase of reduction
+ vpmull.p64 $Xl,$Xl,$xC2
veor $t2,$t2,$Xh
veor $Xl,$Xl,$t2
- b.hs .Loop_v8
+.Ldone_v8:
#ifndef __ARMEB__
vrev64.8 $Xl,$Xl
#endif
vext.8 $Xl,$Xl,$Xl,#8
vst1.64 {$Xl},[$Xi] @ write out Xi
+___
+$code.=<<___ if ($flavour !~ /64/);
+ vldmia sp!,{d8-d15} @ 32-bit ABI says so
+___
+$code.=<<___;
ret
.size gcm_ghash_v8,.-gcm_ghash_v8
___
@@ -226,7 +403,7 @@ if ($flavour =~ /64/) { ######## 64-bit code
foreach(split("\n",$code)) {
s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers
s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers
- s/\/\/\s?/@ /o; # new->old style commentary
+ s/\/\/\s?/@ /o; # new->old style commentary
# fix up remainig new-style suffixes
s/\],#[0-9]+/]!/o;
@@ -238,7 +415,7 @@ if ($flavour =~ /64/) { ######## 64-bit code
s/^(\s+)b\./$1b/o or
s/^(\s+)ret/$1bx\tlr/o;
- print $_,"\n";
+ print $_,"\n";
}
}
diff --git a/src/crypto/modes/cbc.c b/src/crypto/modes/cbc.c
index a2ad26c..ba4805b 100644
--- a/src/crypto/modes/cbc.c
+++ b/src/crypto/modes/cbc.c
@@ -128,8 +128,9 @@ void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
while (len >= 16) {
(*block)(in, out, key);
- for (n = 0; n < 16; ++n)
+ for (n = 0; n < 16; ++n) {
out[n] ^= iv[n];
+ }
iv = in;
len -= 16;
in += 16;
@@ -140,8 +141,9 @@ void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
size_t *out_t = (size_t *)out, *iv_t = (size_t *)iv;
(*block)(in, out, key);
- for (n = 0; n < 16 / sizeof(size_t); n++)
+ for (n = 0; n < 16 / sizeof(size_t); n++) {
out_t[n] ^= iv_t[n];
+ }
iv = in;
len -= 16;
in += 16;
diff --git a/src/crypto/modes/ctr.c b/src/crypto/modes/ctr.c
index 61832ba..306b6f7 100644
--- a/src/crypto/modes/ctr.c
+++ b/src/crypto/modes/ctr.c
@@ -121,8 +121,9 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
while (len >= 16) {
(*block)(ivec, ecount_buf, key);
ctr128_inc(ivec);
- for (; n < 16; n += sizeof(size_t))
+ for (; n < 16; n += sizeof(size_t)) {
*(size_t *)(out + n) = *(size_t *)(in + n) ^ *(size_t *)(ecount_buf + n);
+ }
len -= 16;
out += 16;
in += 16;
@@ -162,7 +163,8 @@ void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out,
unsigned int *num, ctr128_f func) {
unsigned int n, ctr32;
- assert(in && out && key && ecount_buf && num);
+ assert(key && ecount_buf && num);
+ assert(len == 0 || (in && out));
assert(*num < 16);
n = *num;
@@ -179,8 +181,9 @@ void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out,
/* 1<<28 is just a not-so-small yet not-so-large number...
* Below condition is practically never met, but it has to
* be checked for code correctness. */
- if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28))
+ if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28)) {
blocks = (1U << 28);
+ }
/* As (*func) operates on 32-bit counter, caller
* has to handle overflow. 'if' below detects the
* overflow, which is then handled by limiting the
@@ -194,8 +197,9 @@ void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out,
/* (*func) does not update ivec, caller does: */
PUTU32(ivec + 12, ctr32);
/* ... overflow was detected, propogate carry. */
- if (ctr32 == 0)
+ if (ctr32 == 0) {
ctr96_inc(ivec);
+ }
blocks *= 16;
len -= blocks;
out += blocks;
diff --git a/src/crypto/modes/gcm.c b/src/crypto/modes/gcm.c
index eeaeeff..b1c10b3 100644
--- a/src/crypto/modes/gcm.c
+++ b/src/crypto/modes/gcm.c
@@ -620,8 +620,9 @@ int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) {
#endif
if (len) {
n = (unsigned int)len;
- for (i = 0; i < len; ++i)
+ for (i = 0; i < len; ++i) {
ctx->Xi.c[i] ^= aad[i];
+ }
}
ctx->ares = n;
@@ -1123,10 +1124,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const uint8_t *in,
GHASH(ctx, in, GHASH_CHUNK);
(*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
ctr += GHASH_CHUNK / 16;
- if (is_endian.little)
+ if (is_endian.little) {
PUTU32(ctx->Yi.c + 12, ctr);
- else
+ } else {
ctx->Yi.d[3] = ctr;
+ }
out += GHASH_CHUNK;
in += GHASH_CHUNK;
len -= GHASH_CHUNK;
@@ -1140,8 +1142,9 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const uint8_t *in,
#else
while (j--) {
size_t k;
- for (k = 0; k < 16; ++k)
+ for (k = 0; k < 16; ++k) {
ctx->Xi.c[k] ^= in[k];
+ }
GCM_MUL(ctx, Xi);
in += 16;
}
@@ -1150,10 +1153,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const uint8_t *in,
#endif
(*stream)(in, out, j, key, ctx->Yi.c);
ctr += (unsigned int)j;
- if (is_endian.little)
+ if (is_endian.little) {
PUTU32(ctx->Yi.c + 12, ctr);
- else
+ } else {
ctx->Yi.d[3] = ctr;
+ }
out += i;
in += i;
len -= i;
@@ -1161,10 +1165,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const uint8_t *in,
if (len) {
(*ctx->block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little)
+ if (is_endian.little) {
PUTU32(ctx->Yi.c + 12, ctr);
- else
+ } else {
ctx->Yi.d[3] = ctr;
+ }
while (len--) {
uint8_t c = in[n];
ctx->Xi.c[n] ^= c;
diff --git a/src/crypto/modes/gcm_test.c b/src/crypto/modes/gcm_test.c
index 29f9d95..3548c81 100644
--- a/src/crypto/modes/gcm_test.c
+++ b/src/crypto/modes/gcm_test.c
@@ -294,9 +294,7 @@ static int decode_hex(uint8_t **out, size_t *out_len, const char *in,
return 1;
err:
- if (buf) {
- OPENSSL_free(buf);
- }
+ OPENSSL_free(buf);
return 0;
}
@@ -391,27 +389,13 @@ static int run_test_case(unsigned test_num, const struct test_case *test) {
ret = 1;
out:
- if (key) {
- OPENSSL_free(key);
- }
- if (plaintext) {
- OPENSSL_free(plaintext);
- }
- if (additional_data) {
- OPENSSL_free(additional_data);
- }
- if (nonce) {
- OPENSSL_free(nonce);
- }
- if (ciphertext) {
- OPENSSL_free(ciphertext);
- }
- if (tag) {
- OPENSSL_free(tag);
- }
- if (out) {
- OPENSSL_free(out);
- }
+ OPENSSL_free(key);
+ OPENSSL_free(plaintext);
+ OPENSSL_free(additional_data);
+ OPENSSL_free(nonce);
+ OPENSSL_free(ciphertext);
+ OPENSSL_free(tag);
+ OPENSSL_free(out);
return ret;
}
diff --git a/src/crypto/modes/internal.h b/src/crypto/modes/internal.h
index 9662e0d..d12405e 100644
--- a/src/crypto/modes/internal.h
+++ b/src/crypto/modes/internal.h
@@ -121,6 +121,9 @@ extern "C" {
#endif
#elif defined(_MSC_VER)
#if _MSC_VER >= 1300
+#pragma warning(push, 3)
+#include <intrin.h>
+#pragma warning(pop)
#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
#define BSWAP8(x) _byteswap_uint64((uint64_t)(x))
#define BSWAP4(x) _byteswap_ulong((uint32_t)(x))
diff --git a/src/crypto/obj/CMakeLists.txt b/src/crypto/obj/CMakeLists.txt
index ade603d..a27e504 100644
--- a/src/crypto/obj/CMakeLists.txt
+++ b/src/crypto/obj/CMakeLists.txt
@@ -7,5 +7,4 @@ add_library(
obj.c
obj_xref.c
- obj_error.c
)
diff --git a/src/crypto/obj/obj.c b/src/crypto/obj/obj.c
index b04321b..511aba3 100644
--- a/src/crypto/obj/obj.c
+++ b/src/crypto/obj/obj.c
@@ -68,21 +68,26 @@
#include <openssl/thread.h>
#include "obj_dat.h"
+#include "../internal.h"
-/* These globals are protected by CRYPTO_LOCK_OBJ. */
+
+static struct CRYPTO_STATIC_MUTEX global_added_lock = CRYPTO_STATIC_MUTEX_INIT;
+/* These globals are protected by |global_added_lock|. */
static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL;
static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL;
static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
+static struct CRYPTO_STATIC_MUTEX global_next_nid_lock =
+ CRYPTO_STATIC_MUTEX_INIT;
static unsigned global_next_nid = NUM_NID;
static int obj_next_nid(void) {
int ret;
- CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock);
ret = global_next_nid++;
- CRYPTO_w_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_next_nid_lock);
return ret;
}
@@ -130,7 +135,7 @@ ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
if (o->sn != NULL) {
sn = OPENSSL_strdup(o->sn);
- if (sn) {
+ if (sn == NULL) {
goto err;
}
}
@@ -145,15 +150,9 @@ ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
err:
OPENSSL_PUT_ERROR(OBJ, OBJ_dup, ERR_R_MALLOC_FAILURE);
- if (ln != NULL) {
- OPENSSL_free(ln);
- }
- if (sn != NULL) {
- OPENSSL_free(sn);
- }
- if (data != NULL) {
- OPENSSL_free(data);
- }
+ OPENSSL_free(ln);
+ OPENSSL_free(sn);
+ OPENSSL_free(data);
OPENSSL_free(r);
return NULL;
}
@@ -195,17 +194,17 @@ int OBJ_obj2nid(const ASN1_OBJECT *obj) {
return obj->nid;
}
- CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
if (global_added_by_data != NULL) {
ASN1_OBJECT *match;
match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
if (match != NULL) {
- CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
return match->nid;
}
}
- CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp);
if (nid_ptr == NULL) {
@@ -237,18 +236,18 @@ static int short_name_cmp(const void *key, const void *element) {
int OBJ_sn2nid(const char *short_name) {
const unsigned int *nid_ptr;
- CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
if (global_added_by_short_name != NULL) {
ASN1_OBJECT *match, template;
template.sn = short_name;
match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
if (match != NULL) {
- CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
return match->nid;
}
}
- CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp);
if (nid_ptr == NULL) {
@@ -271,18 +270,18 @@ static int long_name_cmp(const void *key, const void *element) {
int OBJ_ln2nid(const char *long_name) {
const unsigned int *nid_ptr;
- CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
if (global_added_by_long_name != NULL) {
ASN1_OBJECT *match, template;
template.ln = long_name;
match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
if (match != NULL) {
- CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
return match->nid;
}
}
- CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp);
if (nid_ptr == NULL) {
@@ -324,18 +323,18 @@ const ASN1_OBJECT *OBJ_nid2obj(int nid) {
return &kObjects[nid];
}
- CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
if (global_added_by_nid != NULL) {
ASN1_OBJECT *match, template;
template.nid = nid;
match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
if (match != NULL) {
- CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
return match;
}
}
- CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
err:
OPENSSL_PUT_ERROR(OBJ, OBJ_nid2obj, OBJ_R_UNKNOWN_NID);
@@ -543,15 +542,11 @@ int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, int dont_return_
}
}
- if (bl) {
- BN_free(bl);
- }
+ BN_free(bl);
return n;
err:
- if (bl) {
- BN_free(bl);
- }
+ BN_free(bl);
return -1;
}
@@ -600,7 +595,7 @@ static int obj_add_object(ASN1_OBJECT *obj) {
obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
ASN1_OBJECT_FLAG_DYNAMIC_DATA);
- CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_lock_write(&global_added_lock);
if (global_added_by_nid == NULL) {
global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data);
@@ -623,7 +618,7 @@ static int obj_add_object(ASN1_OBJECT *obj) {
if (obj->ln != NULL) {
ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
}
- CRYPTO_w_unlock(CRYPTO_LOCK_OBJ);
+ CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
return ok;
}
@@ -662,12 +657,8 @@ int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
op = NULL;
err:
- if (op != NULL) {
- ASN1_OBJECT_free(op);
- }
- if (buf != NULL) {
- OPENSSL_free(buf);
- }
+ ASN1_OBJECT_free(op);
+ OPENSSL_free(buf);
return ret;
}
diff --git a/src/crypto/obj/obj_error.c b/src/crypto/obj/obj_error.c
deleted file mode 100644
index 1ec9771..0000000
--- a/src/crypto/obj/obj_error.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* 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/obj.h>
-
-const ERR_STRING_DATA OBJ_error_string_data[] = {
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_create, 0), "OBJ_create"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_dup, 0), "OBJ_dup"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_nid2obj, 0), "OBJ_nid2obj"},
- {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_txt2obj, 0), "OBJ_txt2obj"},
- {ERR_PACK(ERR_LIB_OBJ, 0, OBJ_R_UNKNOWN_NID), "UNKNOWN_NID"},
- {0, NULL},
-};
diff --git a/src/crypto/pem/CMakeLists.txt b/src/crypto/pem/CMakeLists.txt
index 3275b15..720ba2f 100644
--- a/src/crypto/pem/CMakeLists.txt
+++ b/src/crypto/pem/CMakeLists.txt
@@ -6,7 +6,6 @@ add_library(
OBJECT
pem_all.c
- pem_error.c
pem_info.c
pem_lib.c
pem_oth.c
diff --git a/src/crypto/pem/pem_error.c b/src/crypto/pem/pem_error.c
deleted file mode 100644
index 2745f4c..0000000
--- a/src/crypto/pem/pem_error.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* 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/pem.h>
-
-const ERR_STRING_DATA PEM_error_string_data[] = {
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_read, 0), "PEM_ASN1_read"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_read_bio, 0), "PEM_ASN1_read_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_write, 0), "PEM_ASN1_write"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_write_bio, 0), "PEM_ASN1_write_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_read, 0), "PEM_X509_INFO_read"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_read_bio, 0), "PEM_X509_INFO_read_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_write_bio, 0), "PEM_X509_INFO_write_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_do_header, 0), "PEM_do_header"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_get_EVP_CIPHER_INFO, 0), "PEM_get_EVP_CIPHER_INFO"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read, 0), "PEM_read"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_DHparams, 0), "PEM_read_DHparams"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_PrivateKey, 0), "PEM_read_PrivateKey"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_bio, 0), "PEM_read_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_bio_DHparams, 0), "PEM_read_bio_DHparams"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_bio_Parameters, 0), "PEM_read_bio_Parameters"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_bio_PrivateKey, 0), "PEM_read_bio_PrivateKey"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_write, 0), "PEM_write"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_write_PrivateKey, 0), "PEM_write_PrivateKey"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_write_bio, 0), "PEM_write_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_d2i_PKCS8PrivateKey_bio, 0), "d2i_PKCS8PrivateKey_bio"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_d2i_PKCS8PrivateKey_fp, 0), "d2i_PKCS8PrivateKey_fp"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_do_pk8pkey, 0), "do_pk8pkey"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_do_pk8pkey_fp, 0), "do_pk8pkey_fp"},
- {ERR_PACK(ERR_LIB_PEM, PEM_F_load_iv, 0), "load_iv"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_BASE64_DECODE), "BAD_BASE64_DECODE"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_DECRYPT), "BAD_DECRYPT"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_END_LINE), "BAD_END_LINE"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_IV_CHARS), "BAD_IV_CHARS"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_MAGIC_NUMBER), "BAD_MAGIC_NUMBER"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_PASSWORD_READ), "BAD_PASSWORD_READ"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_VERSION_NUMBER), "BAD_VERSION_NUMBER"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BIO_WRITE_FAILURE), "BIO_WRITE_FAILURE"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_CIPHER_IS_NULL), "CIPHER_IS_NULL"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_ERROR_CONVERTING_PRIVATE_KEY), "ERROR_CONVERTING_PRIVATE_KEY"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_PRIVATE_KEY_BLOB), "EXPECTING_PRIVATE_KEY_BLOB"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_PUBLIC_KEY_BLOB), "EXPECTING_PUBLIC_KEY_BLOB"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_INCONSISTENT_HEADER), "INCONSISTENT_HEADER"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_KEYBLOB_HEADER_PARSE_ERROR), "KEYBLOB_HEADER_PARSE_ERROR"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_KEYBLOB_TOO_SHORT), "KEYBLOB_TOO_SHORT"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_DEK_INFO), "NOT_DEK_INFO"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_ENCRYPTED), "NOT_ENCRYPTED"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_PROC_TYPE), "NOT_PROC_TYPE"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NO_START_LINE), "NO_START_LINE"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PROBLEMS_GETTING_PASSWORD), "PROBLEMS_GETTING_PASSWORD"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PUBLIC_KEY_NO_RSA), "PUBLIC_KEY_NO_RSA"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PVK_DATA_TOO_SHORT), "PVK_DATA_TOO_SHORT"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PVK_TOO_SHORT), "PVK_TOO_SHORT"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_READ_KEY), "READ_KEY"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_SHORT_HEADER), "SHORT_HEADER"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_CIPHER), "UNSUPPORTED_CIPHER"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_ENCRYPTION), "UNSUPPORTED_ENCRYPTION"},
- {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_KEY_COMPONENTS), "UNSUPPORTED_KEY_COMPONENTS"},
- {0, NULL},
-};
diff --git a/src/crypto/pem/pem_lib.c b/src/crypto/pem/pem_lib.c
index ff72c44..48e3297 100644
--- a/src/crypto/pem/pem_lib.c
+++ b/src/crypto/pem/pem_lib.c
@@ -363,10 +363,11 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
|| !EVP_EncryptUpdate(&ctx,data,&j,data,i)
|| !EVP_EncryptFinal_ex(&ctx,&(data[j]),&i))
ret = 0;
+ else
+ i += j;
EVP_CIPHER_CTX_cleanup(&ctx);
if (ret == 0)
goto err;
- i+=j;
}
else
{
diff --git a/src/crypto/pem/pem_pk8.c b/src/crypto/pem/pem_pk8.c
index 18cfb92..383a524 100644
--- a/src/crypto/pem/pem_pk8.c
+++ b/src/crypto/pem/pem_pk8.c
@@ -59,6 +59,7 @@
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
+#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/pkcs8.h>
#include <openssl/rand.h>
diff --git a/src/crypto/perlasm/arm-xlate.pl b/src/crypto/perlasm/arm-xlate.pl
new file mode 100755
index 0000000..81ceb31
--- /dev/null
+++ b/src/crypto/perlasm/arm-xlate.pl
@@ -0,0 +1,165 @@
+#!/usr/bin/env perl
+
+# ARM assembler distiller by <appro>.
+
+my $flavour = shift;
+my $output = shift;
+open STDOUT,">$output" || die "can't open $output: $!";
+
+$flavour = "linux32" if (!$flavour or $flavour eq "void");
+
+my %GLOBALS;
+my $dotinlocallabels=($flavour=~/linux/)?1:0;
+
+################################################################
+# directives which need special treatment on different platforms
+################################################################
+my $arch = sub {
+ if ($flavour =~ /linux/) { ".arch\t".join(',',@_); }
+ else { ""; }
+};
+my $fpu = sub {
+ if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); }
+ else { ""; }
+};
+my $hidden = sub {
+ if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); }
+ else { ".hidden\t".join(',',@_); }
+};
+my $comm = sub {
+ my @args = split(/,\s*/,shift);
+ my $name = @args[0];
+ my $global = \$GLOBALS{$name};
+ my $ret;
+
+ if ($flavour =~ /ios32/) {
+ $ret = ".comm\t_$name,@args[1]\n";
+ $ret .= ".non_lazy_symbol_pointer\n";
+ $ret .= "$name:\n";
+ $ret .= ".indirect_symbol\t_$name\n";
+ $ret .= ".long\t0";
+ $name = "_$name";
+ } else { $ret = ".comm\t".join(',',@args); }
+
+ $$global = $name;
+ $ret;
+};
+my $globl = sub {
+ my $name = shift;
+ my $global = \$GLOBALS{$name};
+ my $ret;
+
+ SWITCH: for ($flavour) {
+ /ios/ && do { $name = "_$name";
+ last;
+ };
+ }
+
+ $ret = ".globl $name" if (!$ret);
+ $$global = $name;
+ $ret;
+};
+my $global = $globl;
+my $extern = sub {
+ &$globl(@_);
+ return; # return nothing
+};
+my $type = sub {
+ if ($flavour =~ /linux/) { ".type\t".join(',',@_); }
+ else { ""; }
+};
+my $size = sub {
+ if ($flavour =~ /linux/) { ".size\t".join(',',@_); }
+ else { ""; }
+};
+my $inst = sub {
+ if ($flavour =~ /linux/) { ".inst\t".join(',',@_); }
+ else { ".long\t".join(',',@_); }
+};
+my $asciz = sub {
+ my $line = join(",",@_);
+ if ($line =~ /^"(.*)"$/)
+ { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; }
+ else
+ { ""; }
+};
+
+sub range {
+ my ($r,$sfx,$start,$end) = @_;
+
+ join(",",map("$r$_$sfx",($start..$end)));
+}
+
+sub expand_line {
+ my $line = shift;
+ my @ret = ();
+
+ pos($line)=0;
+
+ while ($line =~ m/\G[^@\/\{\"]*/g) {
+ if ($line =~ m/\G(@|\/\/|$)/gc) {
+ last;
+ }
+ elsif ($line =~ m/\G\{/gc) {
+ my $saved_pos = pos($line);
+ $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e;
+ pos($line) = $saved_pos;
+ $line =~ m/\G[^\}]*\}/g;
+ }
+ elsif ($line =~ m/\G\"/gc) {
+ $line =~ m/\G[^\"]*\"/g;
+ }
+ }
+
+ $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge;
+
+ return $line;
+}
+
+while($line=<>) {
+
+ if ($line =~ m/^\s*(#|@|\/\/)/) { print $line; next; }
+
+ $line =~ s|/\*.*\*/||; # get rid of C-style comments...
+ $line =~ s|^\s+||; # ... and skip white spaces in beginning...
+ $line =~ s|\s+$||; # ... and at the end
+
+ {
+ $line =~ s|[\b\.]L(\w{2,})|L$1|g; # common denominator for Locallabel
+ $line =~ s|\bL(\w{2,})|\.L$1|g if ($dotinlocallabels);
+ }
+
+ {
+ $line =~ s|(^[\.\w]+)\:\s*||;
+ my $label = $1;
+ if ($label) {
+ printf "%s:",($GLOBALS{$label} or $label);
+ }
+ }
+
+ if ($line !~ m/^[#@]/) {
+ $line =~ s|^\s*(\.?)(\S+)\s*||;
+ my $c = $1; $c = "\t" if ($c eq "");
+ my $mnemonic = $2;
+ my $opcode;
+ if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) {
+ $opcode = eval("\$$1_$2");
+ } else {
+ $opcode = eval("\$$mnemonic");
+ }
+
+ my $arg=expand_line($line);
+
+ if (ref($opcode) eq 'CODE') {
+ $line = &$opcode($arg);
+ } elsif ($mnemonic) {
+ $line = $c.$mnemonic;
+ $line.= "\t$arg" if ($arg ne "");
+ }
+ }
+
+ print $line if ($line);
+ print "\n";
+}
+
+close STDOUT;
diff --git a/src/crypto/perlasm/ppc-xlate.pl b/src/crypto/perlasm/ppc-xlate.pl
deleted file mode 100755
index 3c1caac..0000000
--- a/src/crypto/perlasm/ppc-xlate.pl
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/env perl
-
-# PowerPC assembler distiller by <appro>.
-
-my $flavour = shift;
-my $output = shift;
-open STDOUT,">$output" || die "can't open $output: $!";
-
-my %GLOBALS;
-my $dotinlocallabels=($flavour=~/linux/)?1:0;
-
-################################################################
-# directives which need special treatment on different platforms
-################################################################
-my $globl = sub {
- my $junk = shift;
- my $name = shift;
- my $global = \$GLOBALS{$name};
- my $ret;
-
- $name =~ s|^[\.\_]||;
-
- SWITCH: for ($flavour) {
- /aix/ && do { $name = ".$name";
- last;
- };
- /osx/ && do { $name = "_$name";
- last;
- };
- /linux.*(32|64le)/
- && do { $ret .= ".globl $name\n";
- $ret .= ".type $name,\@function";
- last;
- };
- /linux.*64/ && do { $ret .= ".globl $name\n";
- $ret .= ".type $name,\@function\n";
- $ret .= ".section \".opd\",\"aw\"\n";
- $ret .= ".align 3\n";
- $ret .= "$name:\n";
- $ret .= ".quad .$name,.TOC.\@tocbase,0\n";
- $ret .= ".previous\n";
-
- $name = ".$name";
- last;
- };
- }
-
- $ret = ".globl $name" if (!$ret);
- $$global = $name;
- $ret;
-};
-my $text = sub {
- my $ret = ($flavour =~ /aix/) ? ".csect" : ".text";
- $ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64le/);
- $ret;
-};
-my $machine = sub {
- my $junk = shift;
- my $arch = shift;
- if ($flavour =~ /osx/)
- { $arch =~ s/\"//g;
- $arch = ($flavour=~/64/) ? "ppc970-64" : "ppc970" if ($arch eq "any");
- }
- ".machine $arch";
-};
-my $size = sub {
- if ($flavour =~ /linux/)
- { shift;
- my $name = shift; $name =~ s|^[\.\_]||;
- my $ret = ".size $name,.-".($flavour=~/64$/?".":"").$name;
- $ret .= "\n.size .$name,.-.$name" if ($flavour=~/64$/);
- $ret;
- }
- else
- { ""; }
-};
-my $asciz = sub {
- shift;
- my $line = join(",",@_);
- if ($line =~ /^"(.*)"$/)
- { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; }
- else
- { ""; }
-};
-
-################################################################
-# simplified mnemonics not handled by at least one assembler
-################################################################
-my $cmplw = sub {
- my $f = shift;
- my $cr = 0; $cr = shift if ($#_>1);
- # Some out-of-date 32-bit GNU assembler just can't handle cmplw...
- ($flavour =~ /linux.*32/) ?
- " .long ".sprintf "0x%x",31<<26|$cr<<23|$_[0]<<16|$_[1]<<11|64 :
- " cmplw ".join(',',$cr,@_);
-};
-my $bdnz = sub {
- my $f = shift;
- my $bo = $f=~/[\+\-]/ ? 16+9 : 16; # optional "to be taken" hint
- " bc $bo,0,".shift;
-} if ($flavour!~/linux/);
-my $bltlr = sub {
- my $f = shift;
- my $bo = $f=~/\-/ ? 12+2 : 12; # optional "not to be taken" hint
- ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
- " .long ".sprintf "0x%x",19<<26|$bo<<21|16<<1 :
- " bclr $bo,0";
-};
-my $bnelr = sub {
- my $f = shift;
- my $bo = $f=~/\-/ ? 4+2 : 4; # optional "not to be taken" hint
- ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
- " .long ".sprintf "0x%x",19<<26|$bo<<21|2<<16|16<<1 :
- " bclr $bo,2";
-};
-my $beqlr = sub {
- my $f = shift;
- my $bo = $f=~/-/ ? 12+2 : 12; # optional "not to be taken" hint
- ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
- " .long ".sprintf "0x%X",19<<26|$bo<<21|2<<16|16<<1 :
- " bclr $bo,2";
-};
-# GNU assembler can't handle extrdi rA,rS,16,48, or when sum of last two
-# arguments is 64, with "operand out of range" error.
-my $extrdi = sub {
- my ($f,$ra,$rs,$n,$b) = @_;
- $b = ($b+$n)&63; $n = 64-$n;
- " rldicl $ra,$rs,$b,$n";
-};
-
-while($line=<>) {
-
- $line =~ s|[#!;].*$||; # get rid of asm-style comments...
- $line =~ s|/\*.*\*/||; # ... and C-style comments...
- $line =~ s|^\s+||; # ... and skip white spaces in beginning...
- $line =~ s|\s+$||; # ... and at the end
-
- {
- $line =~ s|\b\.L(\w+)|L$1|g; # common denominator for Locallabel
- $line =~ s|\bL(\w+)|\.L$1|g if ($dotinlocallabels);
- }
-
- {
- $line =~ s|(^[\.\w]+)\:\s*||;
- my $label = $1;
- if ($label) {
- printf "%s:",($GLOBALS{$label} or $label);
- printf "\n.localentry\t$GLOBALS{$label},0" if ($GLOBALS{$label} && $flavour =~ /linux.*64le/);
- }
- }
-
- {
- $line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s*||;
- my $c = $1; $c = "\t" if ($c eq "");
- my $mnemonic = $2;
- my $f = $3;
- my $opcode = eval("\$$mnemonic");
- $line =~ s|\bc?[rf]([0-9]+)\b|$1|g if ($c ne "." and $flavour !~ /osx/);
- if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(',',$line)); }
- elsif ($mnemonic) { $line = $c.$mnemonic.$f."\t".$line; }
- }
-
- print $line if ($line);
- print "\n";
-}
-
-close STDOUT;
diff --git a/src/crypto/perlasm/sparcv9_modes.pl b/src/crypto/perlasm/sparcv9_modes.pl
deleted file mode 100644
index 6b47bb1..0000000
--- a/src/crypto/perlasm/sparcv9_modes.pl
+++ /dev/null
@@ -1,1680 +0,0 @@
-#!/usr/bin/env perl
-
-# Specific modes implementations for SPARC Architecture 2011. There
-# is T4 dependency though, an ASI value that is not specified in the
-# Architecture Manual. But as SPARC universe is rather monocultural,
-# we imply that processor capable of executing crypto instructions
-# can handle the ASI in question as well. This means that we ought to
-# keep eyes open when new processors emerge...
-#
-# As for above mentioned ASI. It's so called "block initializing
-# store" which cancels "read" in "read-update-write" on cache lines.
-# This is "cooperative" optimization, as it reduces overall pressure
-# on memory interface. Benefits can't be observed/quantified with
-# usual benchmarks, on the contrary you can notice that single-thread
-# performance for parallelizable modes is ~1.5% worse for largest
-# block sizes [though few percent better for not so long ones]. All
-# this based on suggestions from David Miller.
-
-sub asm_init { # to be called with @ARGV as argument
- for (@_) { $::abibits=64 if (/\-m64/ || /\-xarch\=v9/); }
- if ($::abibits==64) { $::bias=2047; $::frame=192; $::size_t_cc="%xcc"; }
- else { $::bias=0; $::frame=112; $::size_t_cc="%icc"; }
-}
-
-# unified interface
-my ($inp,$out,$len,$key,$ivec)=map("%i$_",(0..5));
-# local variables
-my ($ileft,$iright,$ooff,$omask,$ivoff,$blk_init)=map("%l$_",(0..7));
-
-sub alg_cbc_encrypt_implement {
-my ($alg,$bits) = @_;
-
-$::code.=<<___;
-.globl ${alg}${bits}_t4_cbc_encrypt
-.align 32
-${alg}${bits}_t4_cbc_encrypt:
- save %sp, -$::frame, %sp
- sub $inp, $out, $blk_init ! $inp!=$out
-___
-$::code.=<<___ if (!$::evp);
- andcc $ivec, 7, $ivoff
- alignaddr $ivec, %g0, $ivec
-
- ldd [$ivec + 0], %f0 ! load ivec
- bz,pt %icc, 1f
- ldd [$ivec + 8], %f2
- ldd [$ivec + 16], %f4
- faligndata %f0, %f2, %f0
- faligndata %f2, %f4, %f2
-1:
-___
-$::code.=<<___ if ($::evp);
- ld [$ivec + 0], %f0
- ld [$ivec + 4], %f1
- ld [$ivec + 8], %f2
- ld [$ivec + 12], %f3
-___
-$::code.=<<___;
- prefetch [$inp], 20
- prefetch [$inp + 63], 20
- call _${alg}${bits}_load_enckey
- and $inp, 7, $ileft
- andn $inp, 7, $inp
- sll $ileft, 3, $ileft
- mov 64, $iright
- mov 0xff, $omask
- sub $iright, $ileft, $iright
- and $out, 7, $ooff
- cmp $len, 127
- movrnz $ooff, 0, $blk_init ! if ( $out&7 ||
- movleu $::size_t_cc, 0, $blk_init ! $len<128 ||
- brnz,pn $blk_init, .L${bits}cbc_enc_blk ! $inp==$out)
- srl $omask, $ooff, $omask
-
- alignaddrl $out, %g0, $out
- srlx $len, 4, $len
- prefetch [$out], 22
-
-.L${bits}_cbc_enc_loop:
- ldx [$inp + 0], %o0
- brz,pt $ileft, 4f
- ldx [$inp + 8], %o1
-
- ldx [$inp + 16], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
-4:
- xor %g4, %o0, %o0 ! ^= rk[0]
- xor %g5, %o1, %o1
- movxtod %o0, %f12
- movxtod %o1, %f14
-
- fxor %f12, %f0, %f0 ! ^= ivec
- fxor %f14, %f2, %f2
- prefetch [$out + 63], 22
- prefetch [$inp + 16+63], 20
- call _${alg}${bits}_encrypt_1x
- add $inp, 16, $inp
-
- brnz,pn $ooff, 2f
- sub $len, 1, $len
-
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- brnz,pt $len, .L${bits}_cbc_enc_loop
- add $out, 16, $out
-___
-$::code.=<<___ if ($::evp);
- st %f0, [$ivec + 0]
- st %f1, [$ivec + 4]
- st %f2, [$ivec + 8]
- st %f3, [$ivec + 12]
-___
-$::code.=<<___ if (!$::evp);
- brnz,pn $ivoff, 3f
- nop
-
- std %f0, [$ivec + 0] ! write out ivec
- std %f2, [$ivec + 8]
-___
-$::code.=<<___;
- ret
- restore
-
-.align 16
-2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
- ! and ~3x deterioration
- ! in inp==out case
- faligndata %f0, %f0, %f4 ! handle unaligned output
- faligndata %f0, %f2, %f6
- faligndata %f2, %f2, %f8
-
- stda %f4, [$out + $omask]0xc0 ! partial store
- std %f6, [$out + 8]
- add $out, 16, $out
- orn %g0, $omask, $omask
- stda %f8, [$out + $omask]0xc0 ! partial store
-
- brnz,pt $len, .L${bits}_cbc_enc_loop+4
- orn %g0, $omask, $omask
-___
-$::code.=<<___ if ($::evp);
- st %f0, [$ivec + 0]
- st %f1, [$ivec + 4]
- st %f2, [$ivec + 8]
- st %f3, [$ivec + 12]
-___
-$::code.=<<___ if (!$::evp);
- brnz,pn $ivoff, 3f
- nop
-
- std %f0, [$ivec + 0] ! write out ivec
- std %f2, [$ivec + 8]
- ret
- restore
-
-.align 16
-3: alignaddrl $ivec, $ivoff, %g0 ! handle unaligned ivec
- mov 0xff, $omask
- srl $omask, $ivoff, $omask
- faligndata %f0, %f0, %f4
- faligndata %f0, %f2, %f6
- faligndata %f2, %f2, %f8
- stda %f4, [$ivec + $omask]0xc0
- std %f6, [$ivec + 8]
- add $ivec, 16, $ivec
- orn %g0, $omask, $omask
- stda %f8, [$ivec + $omask]0xc0
-___
-$::code.=<<___;
- ret
- restore
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-.align 32
-.L${bits}cbc_enc_blk:
- add $out, $len, $blk_init
- and $blk_init, 63, $blk_init ! tail
- sub $len, $blk_init, $len
- add $blk_init, 15, $blk_init ! round up to 16n
- srlx $len, 4, $len
- srl $blk_init, 4, $blk_init
-
-.L${bits}_cbc_enc_blk_loop:
- ldx [$inp + 0], %o0
- brz,pt $ileft, 5f
- ldx [$inp + 8], %o1
-
- ldx [$inp + 16], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
-5:
- xor %g4, %o0, %o0 ! ^= rk[0]
- xor %g5, %o1, %o1
- movxtod %o0, %f12
- movxtod %o1, %f14
-
- fxor %f12, %f0, %f0 ! ^= ivec
- fxor %f14, %f2, %f2
- prefetch [$inp + 16+63], 20
- call _${alg}${bits}_encrypt_1x
- add $inp, 16, $inp
- sub $len, 1, $len
-
- stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- brnz,pt $len, .L${bits}_cbc_enc_blk_loop
- add $out, 8, $out
-
- membar #StoreLoad|#StoreStore
- brnz,pt $blk_init, .L${bits}_cbc_enc_loop
- mov $blk_init, $len
-___
-$::code.=<<___ if ($::evp);
- st %f0, [$ivec + 0]
- st %f1, [$ivec + 4]
- st %f2, [$ivec + 8]
- st %f3, [$ivec + 12]
-___
-$::code.=<<___ if (!$::evp);
- brnz,pn $ivoff, 3b
- nop
-
- std %f0, [$ivec + 0] ! write out ivec
- std %f2, [$ivec + 8]
-___
-$::code.=<<___;
- ret
- restore
-.type ${alg}${bits}_t4_cbc_encrypt,#function
-.size ${alg}${bits}_t4_cbc_encrypt,.-${alg}${bits}_t4_cbc_encrypt
-___
-}
-
-sub alg_cbc_decrypt_implement {
-my ($alg,$bits) = @_;
-
-$::code.=<<___;
-.globl ${alg}${bits}_t4_cbc_decrypt
-.align 32
-${alg}${bits}_t4_cbc_decrypt:
- save %sp, -$::frame, %sp
- sub $inp, $out, $blk_init ! $inp!=$out
-___
-$::code.=<<___ if (!$::evp);
- andcc $ivec, 7, $ivoff
- alignaddr $ivec, %g0, $ivec
-
- ldd [$ivec + 0], %f12 ! load ivec
- bz,pt %icc, 1f
- ldd [$ivec + 8], %f14
- ldd [$ivec + 16], %f0
- faligndata %f12, %f14, %f12
- faligndata %f14, %f0, %f14
-1:
-___
-$::code.=<<___ if ($::evp);
- ld [$ivec + 0], %f12 ! load ivec
- ld [$ivec + 4], %f13
- ld [$ivec + 8], %f14
- ld [$ivec + 12], %f15
-___
-$::code.=<<___;
- prefetch [$inp], 20
- prefetch [$inp + 63], 20
- call _${alg}${bits}_load_deckey
- and $inp, 7, $ileft
- andn $inp, 7, $inp
- sll $ileft, 3, $ileft
- mov 64, $iright
- mov 0xff, $omask
- sub $iright, $ileft, $iright
- and $out, 7, $ooff
- cmp $len, 255
- movrnz $ooff, 0, $blk_init ! if ( $out&7 ||
- movleu $::size_t_cc, 0, $blk_init ! $len<256 ||
- brnz,pn $blk_init, .L${bits}cbc_dec_blk ! $inp==$out)
- srl $omask, $ooff, $omask
-
- andcc $len, 16, %g0 ! is number of blocks even?
- srlx $len, 4, $len
- alignaddrl $out, %g0, $out
- bz %icc, .L${bits}_cbc_dec_loop2x
- prefetch [$out], 22
-.L${bits}_cbc_dec_loop:
- ldx [$inp + 0], %o0
- brz,pt $ileft, 4f
- ldx [$inp + 8], %o1
-
- ldx [$inp + 16], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
-4:
- xor %g4, %o0, %o2 ! ^= rk[0]
- xor %g5, %o1, %o3
- movxtod %o2, %f0
- movxtod %o3, %f2
-
- prefetch [$out + 63], 22
- prefetch [$inp + 16+63], 20
- call _${alg}${bits}_decrypt_1x
- add $inp, 16, $inp
-
- fxor %f12, %f0, %f0 ! ^= ivec
- fxor %f14, %f2, %f2
- movxtod %o0, %f12
- movxtod %o1, %f14
-
- brnz,pn $ooff, 2f
- sub $len, 1, $len
-
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- brnz,pt $len, .L${bits}_cbc_dec_loop2x
- add $out, 16, $out
-___
-$::code.=<<___ if ($::evp);
- st %f12, [$ivec + 0]
- st %f13, [$ivec + 4]
- st %f14, [$ivec + 8]
- st %f15, [$ivec + 12]
-___
-$::code.=<<___ if (!$::evp);
- brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec
- nop
-
- std %f12, [$ivec + 0] ! write out ivec
- std %f14, [$ivec + 8]
-___
-$::code.=<<___;
- ret
- restore
-
-.align 16
-2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
- ! and ~3x deterioration
- ! in inp==out case
- faligndata %f0, %f0, %f4 ! handle unaligned output
- faligndata %f0, %f2, %f6
- faligndata %f2, %f2, %f8
-
- stda %f4, [$out + $omask]0xc0 ! partial store
- std %f6, [$out + 8]
- add $out, 16, $out
- orn %g0, $omask, $omask
- stda %f8, [$out + $omask]0xc0 ! partial store
-
- brnz,pt $len, .L${bits}_cbc_dec_loop2x+4
- orn %g0, $omask, $omask
-___
-$::code.=<<___ if ($::evp);
- st %f12, [$ivec + 0]
- st %f13, [$ivec + 4]
- st %f14, [$ivec + 8]
- st %f15, [$ivec + 12]
-___
-$::code.=<<___ if (!$::evp);
- brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec
- nop
-
- std %f12, [$ivec + 0] ! write out ivec
- std %f14, [$ivec + 8]
-___
-$::code.=<<___;
- ret
- restore
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-.align 32
-.L${bits}_cbc_dec_loop2x:
- ldx [$inp + 0], %o0
- ldx [$inp + 8], %o1
- ldx [$inp + 16], %o2
- brz,pt $ileft, 4f
- ldx [$inp + 24], %o3
-
- ldx [$inp + 32], %o4
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- or %g1, %o0, %o0
- sllx %o1, $ileft, %o1
- srlx %o2, $iright, %g1
- or %g1, %o1, %o1
- sllx %o2, $ileft, %o2
- srlx %o3, $iright, %g1
- or %g1, %o2, %o2
- sllx %o3, $ileft, %o3
- srlx %o4, $iright, %o4
- or %o4, %o3, %o3
-4:
- xor %g4, %o0, %o4 ! ^= rk[0]
- xor %g5, %o1, %o5
- movxtod %o4, %f0
- movxtod %o5, %f2
- xor %g4, %o2, %o4
- xor %g5, %o3, %o5
- movxtod %o4, %f4
- movxtod %o5, %f6
-
- prefetch [$out + 63], 22
- prefetch [$inp + 32+63], 20
- call _${alg}${bits}_decrypt_2x
- add $inp, 32, $inp
-
- movxtod %o0, %f8
- movxtod %o1, %f10
- fxor %f12, %f0, %f0 ! ^= ivec
- fxor %f14, %f2, %f2
- movxtod %o2, %f12
- movxtod %o3, %f14
- fxor %f8, %f4, %f4
- fxor %f10, %f6, %f6
-
- brnz,pn $ooff, 2f
- sub $len, 2, $len
-
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- std %f4, [$out + 16]
- std %f6, [$out + 24]
- brnz,pt $len, .L${bits}_cbc_dec_loop2x
- add $out, 32, $out
-___
-$::code.=<<___ if ($::evp);
- st %f12, [$ivec + 0]
- st %f13, [$ivec + 4]
- st %f14, [$ivec + 8]
- st %f15, [$ivec + 12]
-___
-$::code.=<<___ if (!$::evp);
- brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec
- nop
-
- std %f12, [$ivec + 0] ! write out ivec
- std %f14, [$ivec + 8]
-___
-$::code.=<<___;
- ret
- restore
-
-.align 16
-2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
- ! and ~3x deterioration
- ! in inp==out case
- faligndata %f0, %f0, %f8 ! handle unaligned output
- faligndata %f0, %f2, %f0
- faligndata %f2, %f4, %f2
- faligndata %f4, %f6, %f4
- faligndata %f6, %f6, %f6
- stda %f8, [$out + $omask]0xc0 ! partial store
- std %f0, [$out + 8]
- std %f2, [$out + 16]
- std %f4, [$out + 24]
- add $out, 32, $out
- orn %g0, $omask, $omask
- stda %f6, [$out + $omask]0xc0 ! partial store
-
- brnz,pt $len, .L${bits}_cbc_dec_loop2x+4
- orn %g0, $omask, $omask
-___
-$::code.=<<___ if ($::evp);
- st %f12, [$ivec + 0]
- st %f13, [$ivec + 4]
- st %f14, [$ivec + 8]
- st %f15, [$ivec + 12]
-___
-$::code.=<<___ if (!$::evp);
- brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec
- nop
-
- std %f12, [$ivec + 0] ! write out ivec
- std %f14, [$ivec + 8]
- ret
- restore
-
-.align 16
-.L${bits}_cbc_dec_unaligned_ivec:
- alignaddrl $ivec, $ivoff, %g0 ! handle unaligned ivec
- mov 0xff, $omask
- srl $omask, $ivoff, $omask
- faligndata %f12, %f12, %f0
- faligndata %f12, %f14, %f2
- faligndata %f14, %f14, %f4
- stda %f0, [$ivec + $omask]0xc0
- std %f2, [$ivec + 8]
- add $ivec, 16, $ivec
- orn %g0, $omask, $omask
- stda %f4, [$ivec + $omask]0xc0
-___
-$::code.=<<___;
- ret
- restore
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-.align 32
-.L${bits}cbc_dec_blk:
- add $out, $len, $blk_init
- and $blk_init, 63, $blk_init ! tail
- sub $len, $blk_init, $len
- add $blk_init, 15, $blk_init ! round up to 16n
- srlx $len, 4, $len
- srl $blk_init, 4, $blk_init
- sub $len, 1, $len
- add $blk_init, 1, $blk_init
-
-.L${bits}_cbc_dec_blk_loop2x:
- ldx [$inp + 0], %o0
- ldx [$inp + 8], %o1
- ldx [$inp + 16], %o2
- brz,pt $ileft, 5f
- ldx [$inp + 24], %o3
-
- ldx [$inp + 32], %o4
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- or %g1, %o0, %o0
- sllx %o1, $ileft, %o1
- srlx %o2, $iright, %g1
- or %g1, %o1, %o1
- sllx %o2, $ileft, %o2
- srlx %o3, $iright, %g1
- or %g1, %o2, %o2
- sllx %o3, $ileft, %o3
- srlx %o4, $iright, %o4
- or %o4, %o3, %o3
-5:
- xor %g4, %o0, %o4 ! ^= rk[0]
- xor %g5, %o1, %o5
- movxtod %o4, %f0
- movxtod %o5, %f2
- xor %g4, %o2, %o4
- xor %g5, %o3, %o5
- movxtod %o4, %f4
- movxtod %o5, %f6
-
- prefetch [$inp + 32+63], 20
- call _${alg}${bits}_decrypt_2x
- add $inp, 32, $inp
- subcc $len, 2, $len
-
- movxtod %o0, %f8
- movxtod %o1, %f10
- fxor %f12, %f0, %f0 ! ^= ivec
- fxor %f14, %f2, %f2
- movxtod %o2, %f12
- movxtod %o3, %f14
- fxor %f8, %f4, %f4
- fxor %f10, %f6, %f6
-
- stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- bgu,pt $::size_t_cc, .L${bits}_cbc_dec_blk_loop2x
- add $out, 8, $out
-
- add $blk_init, $len, $len
- andcc $len, 1, %g0 ! is number of blocks even?
- membar #StoreLoad|#StoreStore
- bnz,pt %icc, .L${bits}_cbc_dec_loop
- srl $len, 0, $len
- brnz,pn $len, .L${bits}_cbc_dec_loop2x
- nop
-___
-$::code.=<<___ if ($::evp);
- st %f12, [$ivec + 0] ! write out ivec
- st %f13, [$ivec + 4]
- st %f14, [$ivec + 8]
- st %f15, [$ivec + 12]
-___
-$::code.=<<___ if (!$::evp);
- brnz,pn $ivoff, 3b
- nop
-
- std %f12, [$ivec + 0] ! write out ivec
- std %f14, [$ivec + 8]
-___
-$::code.=<<___;
- ret
- restore
-.type ${alg}${bits}_t4_cbc_decrypt,#function
-.size ${alg}${bits}_t4_cbc_decrypt,.-${alg}${bits}_t4_cbc_decrypt
-___
-}
-
-sub alg_ctr32_implement {
-my ($alg,$bits) = @_;
-
-$::code.=<<___;
-.globl ${alg}${bits}_t4_ctr32_encrypt
-.align 32
-${alg}${bits}_t4_ctr32_encrypt:
- save %sp, -$::frame, %sp
-
- prefetch [$inp], 20
- prefetch [$inp + 63], 20
- call _${alg}${bits}_load_enckey
- sllx $len, 4, $len
-
- ld [$ivec + 0], %l4 ! counter
- ld [$ivec + 4], %l5
- ld [$ivec + 8], %l6
- ld [$ivec + 12], %l7
-
- sllx %l4, 32, %o5
- or %l5, %o5, %o5
- sllx %l6, 32, %g1
- xor %o5, %g4, %g4 ! ^= rk[0]
- xor %g1, %g5, %g5
- movxtod %g4, %f14 ! most significant 64 bits
-
- sub $inp, $out, $blk_init ! $inp!=$out
- and $inp, 7, $ileft
- andn $inp, 7, $inp
- sll $ileft, 3, $ileft
- mov 64, $iright
- mov 0xff, $omask
- sub $iright, $ileft, $iright
- and $out, 7, $ooff
- cmp $len, 255
- movrnz $ooff, 0, $blk_init ! if ( $out&7 ||
- movleu $::size_t_cc, 0, $blk_init ! $len<256 ||
- brnz,pn $blk_init, .L${bits}_ctr32_blk ! $inp==$out)
- srl $omask, $ooff, $omask
-
- andcc $len, 16, %g0 ! is number of blocks even?
- alignaddrl $out, %g0, $out
- bz %icc, .L${bits}_ctr32_loop2x
- srlx $len, 4, $len
-.L${bits}_ctr32_loop:
- ldx [$inp + 0], %o0
- brz,pt $ileft, 4f
- ldx [$inp + 8], %o1
-
- ldx [$inp + 16], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
-4:
- xor %g5, %l7, %g1 ! ^= rk[0]
- add %l7, 1, %l7
- movxtod %g1, %f2
- srl %l7, 0, %l7 ! clruw
- prefetch [$out + 63], 22
- prefetch [$inp + 16+63], 20
-___
-$::code.=<<___ if ($alg eq "aes");
- aes_eround01 %f16, %f14, %f2, %f4
- aes_eround23 %f18, %f14, %f2, %f2
-___
-$::code.=<<___ if ($alg eq "cmll");
- camellia_f %f16, %f2, %f14, %f2
- camellia_f %f18, %f14, %f2, %f0
-___
-$::code.=<<___;
- call _${alg}${bits}_encrypt_1x+8
- add $inp, 16, $inp
-
- movxtod %o0, %f10
- movxtod %o1, %f12
- fxor %f10, %f0, %f0 ! ^= inp
- fxor %f12, %f2, %f2
-
- brnz,pn $ooff, 2f
- sub $len, 1, $len
-
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- brnz,pt $len, .L${bits}_ctr32_loop2x
- add $out, 16, $out
-
- ret
- restore
-
-.align 16
-2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
- ! and ~3x deterioration
- ! in inp==out case
- faligndata %f0, %f0, %f4 ! handle unaligned output
- faligndata %f0, %f2, %f6
- faligndata %f2, %f2, %f8
- stda %f4, [$out + $omask]0xc0 ! partial store
- std %f6, [$out + 8]
- add $out, 16, $out
- orn %g0, $omask, $omask
- stda %f8, [$out + $omask]0xc0 ! partial store
-
- brnz,pt $len, .L${bits}_ctr32_loop2x+4
- orn %g0, $omask, $omask
-
- ret
- restore
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-.align 32
-.L${bits}_ctr32_loop2x:
- ldx [$inp + 0], %o0
- ldx [$inp + 8], %o1
- ldx [$inp + 16], %o2
- brz,pt $ileft, 4f
- ldx [$inp + 24], %o3
-
- ldx [$inp + 32], %o4
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- or %g1, %o0, %o0
- sllx %o1, $ileft, %o1
- srlx %o2, $iright, %g1
- or %g1, %o1, %o1
- sllx %o2, $ileft, %o2
- srlx %o3, $iright, %g1
- or %g1, %o2, %o2
- sllx %o3, $ileft, %o3
- srlx %o4, $iright, %o4
- or %o4, %o3, %o3
-4:
- xor %g5, %l7, %g1 ! ^= rk[0]
- add %l7, 1, %l7
- movxtod %g1, %f2
- srl %l7, 0, %l7 ! clruw
- xor %g5, %l7, %g1
- add %l7, 1, %l7
- movxtod %g1, %f6
- srl %l7, 0, %l7 ! clruw
- prefetch [$out + 63], 22
- prefetch [$inp + 32+63], 20
-___
-$::code.=<<___ if ($alg eq "aes");
- aes_eround01 %f16, %f14, %f2, %f8
- aes_eround23 %f18, %f14, %f2, %f2
- aes_eround01 %f16, %f14, %f6, %f10
- aes_eround23 %f18, %f14, %f6, %f6
-___
-$::code.=<<___ if ($alg eq "cmll");
- camellia_f %f16, %f2, %f14, %f2
- camellia_f %f16, %f6, %f14, %f6
- camellia_f %f18, %f14, %f2, %f0
- camellia_f %f18, %f14, %f6, %f4
-___
-$::code.=<<___;
- call _${alg}${bits}_encrypt_2x+16
- add $inp, 32, $inp
-
- movxtod %o0, %f8
- movxtod %o1, %f10
- movxtod %o2, %f12
- fxor %f8, %f0, %f0 ! ^= inp
- movxtod %o3, %f8
- fxor %f10, %f2, %f2
- fxor %f12, %f4, %f4
- fxor %f8, %f6, %f6
-
- brnz,pn $ooff, 2f
- sub $len, 2, $len
-
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- std %f4, [$out + 16]
- std %f6, [$out + 24]
- brnz,pt $len, .L${bits}_ctr32_loop2x
- add $out, 32, $out
-
- ret
- restore
-
-.align 16
-2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
- ! and ~3x deterioration
- ! in inp==out case
- faligndata %f0, %f0, %f8 ! handle unaligned output
- faligndata %f0, %f2, %f0
- faligndata %f2, %f4, %f2
- faligndata %f4, %f6, %f4
- faligndata %f6, %f6, %f6
-
- stda %f8, [$out + $omask]0xc0 ! partial store
- std %f0, [$out + 8]
- std %f2, [$out + 16]
- std %f4, [$out + 24]
- add $out, 32, $out
- orn %g0, $omask, $omask
- stda %f6, [$out + $omask]0xc0 ! partial store
-
- brnz,pt $len, .L${bits}_ctr32_loop2x+4
- orn %g0, $omask, $omask
-
- ret
- restore
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-.align 32
-.L${bits}_ctr32_blk:
- add $out, $len, $blk_init
- and $blk_init, 63, $blk_init ! tail
- sub $len, $blk_init, $len
- add $blk_init, 15, $blk_init ! round up to 16n
- srlx $len, 4, $len
- srl $blk_init, 4, $blk_init
- sub $len, 1, $len
- add $blk_init, 1, $blk_init
-
-.L${bits}_ctr32_blk_loop2x:
- ldx [$inp + 0], %o0
- ldx [$inp + 8], %o1
- ldx [$inp + 16], %o2
- brz,pt $ileft, 5f
- ldx [$inp + 24], %o3
-
- ldx [$inp + 32], %o4
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- or %g1, %o0, %o0
- sllx %o1, $ileft, %o1
- srlx %o2, $iright, %g1
- or %g1, %o1, %o1
- sllx %o2, $ileft, %o2
- srlx %o3, $iright, %g1
- or %g1, %o2, %o2
- sllx %o3, $ileft, %o3
- srlx %o4, $iright, %o4
- or %o4, %o3, %o3
-5:
- xor %g5, %l7, %g1 ! ^= rk[0]
- add %l7, 1, %l7
- movxtod %g1, %f2
- srl %l7, 0, %l7 ! clruw
- xor %g5, %l7, %g1
- add %l7, 1, %l7
- movxtod %g1, %f6
- srl %l7, 0, %l7 ! clruw
- prefetch [$inp + 32+63], 20
-___
-$::code.=<<___ if ($alg eq "aes");
- aes_eround01 %f16, %f14, %f2, %f8
- aes_eround23 %f18, %f14, %f2, %f2
- aes_eround01 %f16, %f14, %f6, %f10
- aes_eround23 %f18, %f14, %f6, %f6
-___
-$::code.=<<___ if ($alg eq "cmll");
- camellia_f %f16, %f2, %f14, %f2
- camellia_f %f16, %f6, %f14, %f6
- camellia_f %f18, %f14, %f2, %f0
- camellia_f %f18, %f14, %f6, %f4
-___
-$::code.=<<___;
- call _${alg}${bits}_encrypt_2x+16
- add $inp, 32, $inp
- subcc $len, 2, $len
-
- movxtod %o0, %f8
- movxtod %o1, %f10
- movxtod %o2, %f12
- fxor %f8, %f0, %f0 ! ^= inp
- movxtod %o3, %f8
- fxor %f10, %f2, %f2
- fxor %f12, %f4, %f4
- fxor %f8, %f6, %f6
-
- stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- bgu,pt $::size_t_cc, .L${bits}_ctr32_blk_loop2x
- add $out, 8, $out
-
- add $blk_init, $len, $len
- andcc $len, 1, %g0 ! is number of blocks even?
- membar #StoreLoad|#StoreStore
- bnz,pt %icc, .L${bits}_ctr32_loop
- srl $len, 0, $len
- brnz,pn $len, .L${bits}_ctr32_loop2x
- nop
-
- ret
- restore
-.type ${alg}${bits}_t4_ctr32_encrypt,#function
-.size ${alg}${bits}_t4_ctr32_encrypt,.-${alg}${bits}_t4_ctr32_encrypt
-___
-}
-
-sub alg_xts_implement {
-my ($alg,$bits,$dir) = @_;
-my ($inp,$out,$len,$key1,$key2,$ivec)=map("%i$_",(0..5));
-my $rem=$ivec;
-
-$::code.=<<___;
-.globl ${alg}${bits}_t4_xts_${dir}crypt
-.align 32
-${alg}${bits}_t4_xts_${dir}crypt:
- save %sp, -$::frame-16, %sp
-
- mov $ivec, %o0
- add %fp, $::bias-16, %o1
- call ${alg}_t4_encrypt
- mov $key2, %o2
-
- add %fp, $::bias-16, %l7
- ldxa [%l7]0x88, %g2
- add %fp, $::bias-8, %l7
- ldxa [%l7]0x88, %g3 ! %g3:%g2 is tweak
-
- sethi %hi(0x76543210), %l7
- or %l7, %lo(0x76543210), %l7
- bmask %l7, %g0, %g0 ! byte swap mask
-
- prefetch [$inp], 20
- prefetch [$inp + 63], 20
- call _${alg}${bits}_load_${dir}ckey
- and $len, 15, $rem
- and $len, -16, $len
-___
-$code.=<<___ if ($dir eq "de");
- mov 0, %l7
- movrnz $rem, 16, %l7
- sub $len, %l7, $len
-___
-$code.=<<___;
-
- sub $inp, $out, $blk_init ! $inp!=$out
- and $inp, 7, $ileft
- andn $inp, 7, $inp
- sll $ileft, 3, $ileft
- mov 64, $iright
- mov 0xff, $omask
- sub $iright, $ileft, $iright
- and $out, 7, $ooff
- cmp $len, 255
- movrnz $ooff, 0, $blk_init ! if ( $out&7 ||
- movleu $::size_t_cc, 0, $blk_init ! $len<256 ||
- brnz,pn $blk_init, .L${bits}_xts_${dir}blk ! $inp==$out)
- srl $omask, $ooff, $omask
-
- andcc $len, 16, %g0 ! is number of blocks even?
-___
-$code.=<<___ if ($dir eq "de");
- brz,pn $len, .L${bits}_xts_${dir}steal
-___
-$code.=<<___;
- alignaddrl $out, %g0, $out
- bz %icc, .L${bits}_xts_${dir}loop2x
- srlx $len, 4, $len
-.L${bits}_xts_${dir}loop:
- ldx [$inp + 0], %o0
- brz,pt $ileft, 4f
- ldx [$inp + 8], %o1
-
- ldx [$inp + 16], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
-4:
- movxtod %g2, %f12
- movxtod %g3, %f14
- bshuffle %f12, %f12, %f12
- bshuffle %f14, %f14, %f14
-
- xor %g4, %o0, %o0 ! ^= rk[0]
- xor %g5, %o1, %o1
- movxtod %o0, %f0
- movxtod %o1, %f2
-
- fxor %f12, %f0, %f0 ! ^= tweak[0]
- fxor %f14, %f2, %f2
-
- prefetch [$out + 63], 22
- prefetch [$inp + 16+63], 20
- call _${alg}${bits}_${dir}crypt_1x
- add $inp, 16, $inp
-
- fxor %f12, %f0, %f0 ! ^= tweak[0]
- fxor %f14, %f2, %f2
-
- srax %g3, 63, %l7 ! next tweak value
- addcc %g2, %g2, %g2
- and %l7, 0x87, %l7
- addxc %g3, %g3, %g3
- xor %l7, %g2, %g2
-
- brnz,pn $ooff, 2f
- sub $len, 1, $len
-
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- brnz,pt $len, .L${bits}_xts_${dir}loop2x
- add $out, 16, $out
-
- brnz,pn $rem, .L${bits}_xts_${dir}steal
- nop
-
- ret
- restore
-
-.align 16
-2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
- ! and ~3x deterioration
- ! in inp==out case
- faligndata %f0, %f0, %f4 ! handle unaligned output
- faligndata %f0, %f2, %f6
- faligndata %f2, %f2, %f8
- stda %f4, [$out + $omask]0xc0 ! partial store
- std %f6, [$out + 8]
- add $out, 16, $out
- orn %g0, $omask, $omask
- stda %f8, [$out + $omask]0xc0 ! partial store
-
- brnz,pt $len, .L${bits}_xts_${dir}loop2x+4
- orn %g0, $omask, $omask
-
- brnz,pn $rem, .L${bits}_xts_${dir}steal
- nop
-
- ret
- restore
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-.align 32
-.L${bits}_xts_${dir}loop2x:
- ldx [$inp + 0], %o0
- ldx [$inp + 8], %o1
- ldx [$inp + 16], %o2
- brz,pt $ileft, 4f
- ldx [$inp + 24], %o3
-
- ldx [$inp + 32], %o4
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- or %g1, %o0, %o0
- sllx %o1, $ileft, %o1
- srlx %o2, $iright, %g1
- or %g1, %o1, %o1
- sllx %o2, $ileft, %o2
- srlx %o3, $iright, %g1
- or %g1, %o2, %o2
- sllx %o3, $ileft, %o3
- srlx %o4, $iright, %o4
- or %o4, %o3, %o3
-4:
- movxtod %g2, %f12
- movxtod %g3, %f14
- bshuffle %f12, %f12, %f12
- bshuffle %f14, %f14, %f14
-
- srax %g3, 63, %l7 ! next tweak value
- addcc %g2, %g2, %g2
- and %l7, 0x87, %l7
- addxc %g3, %g3, %g3
- xor %l7, %g2, %g2
-
- movxtod %g2, %f8
- movxtod %g3, %f10
- bshuffle %f8, %f8, %f8
- bshuffle %f10, %f10, %f10
-
- xor %g4, %o0, %o0 ! ^= rk[0]
- xor %g5, %o1, %o1
- xor %g4, %o2, %o2 ! ^= rk[0]
- xor %g5, %o3, %o3
- movxtod %o0, %f0
- movxtod %o1, %f2
- movxtod %o2, %f4
- movxtod %o3, %f6
-
- fxor %f12, %f0, %f0 ! ^= tweak[0]
- fxor %f14, %f2, %f2
- fxor %f8, %f4, %f4 ! ^= tweak[0]
- fxor %f10, %f6, %f6
-
- prefetch [$out + 63], 22
- prefetch [$inp + 32+63], 20
- call _${alg}${bits}_${dir}crypt_2x
- add $inp, 32, $inp
-
- movxtod %g2, %f8
- movxtod %g3, %f10
-
- srax %g3, 63, %l7 ! next tweak value
- addcc %g2, %g2, %g2
- and %l7, 0x87, %l7
- addxc %g3, %g3, %g3
- xor %l7, %g2, %g2
-
- bshuffle %f8, %f8, %f8
- bshuffle %f10, %f10, %f10
-
- fxor %f12, %f0, %f0 ! ^= tweak[0]
- fxor %f14, %f2, %f2
- fxor %f8, %f4, %f4
- fxor %f10, %f6, %f6
-
- brnz,pn $ooff, 2f
- sub $len, 2, $len
-
- std %f0, [$out + 0]
- std %f2, [$out + 8]
- std %f4, [$out + 16]
- std %f6, [$out + 24]
- brnz,pt $len, .L${bits}_xts_${dir}loop2x
- add $out, 32, $out
-
- fsrc2 %f4, %f0
- fsrc2 %f6, %f2
- brnz,pn $rem, .L${bits}_xts_${dir}steal
- nop
-
- ret
- restore
-
-.align 16
-2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
- ! and ~3x deterioration
- ! in inp==out case
- faligndata %f0, %f0, %f8 ! handle unaligned output
- faligndata %f0, %f2, %f10
- faligndata %f2, %f4, %f12
- faligndata %f4, %f6, %f14
- faligndata %f6, %f6, %f0
-
- stda %f8, [$out + $omask]0xc0 ! partial store
- std %f10, [$out + 8]
- std %f12, [$out + 16]
- std %f14, [$out + 24]
- add $out, 32, $out
- orn %g0, $omask, $omask
- stda %f0, [$out + $omask]0xc0 ! partial store
-
- brnz,pt $len, .L${bits}_xts_${dir}loop2x+4
- orn %g0, $omask, $omask
-
- fsrc2 %f4, %f0
- fsrc2 %f6, %f2
- brnz,pn $rem, .L${bits}_xts_${dir}steal
- nop
-
- ret
- restore
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-.align 32
-.L${bits}_xts_${dir}blk:
- add $out, $len, $blk_init
- and $blk_init, 63, $blk_init ! tail
- sub $len, $blk_init, $len
- add $blk_init, 15, $blk_init ! round up to 16n
- srlx $len, 4, $len
- srl $blk_init, 4, $blk_init
- sub $len, 1, $len
- add $blk_init, 1, $blk_init
-
-.L${bits}_xts_${dir}blk2x:
- ldx [$inp + 0], %o0
- ldx [$inp + 8], %o1
- ldx [$inp + 16], %o2
- brz,pt $ileft, 5f
- ldx [$inp + 24], %o3
-
- ldx [$inp + 32], %o4
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- or %g1, %o0, %o0
- sllx %o1, $ileft, %o1
- srlx %o2, $iright, %g1
- or %g1, %o1, %o1
- sllx %o2, $ileft, %o2
- srlx %o3, $iright, %g1
- or %g1, %o2, %o2
- sllx %o3, $ileft, %o3
- srlx %o4, $iright, %o4
- or %o4, %o3, %o3
-5:
- movxtod %g2, %f12
- movxtod %g3, %f14
- bshuffle %f12, %f12, %f12
- bshuffle %f14, %f14, %f14
-
- srax %g3, 63, %l7 ! next tweak value
- addcc %g2, %g2, %g2
- and %l7, 0x87, %l7
- addxc %g3, %g3, %g3
- xor %l7, %g2, %g2
-
- movxtod %g2, %f8
- movxtod %g3, %f10
- bshuffle %f8, %f8, %f8
- bshuffle %f10, %f10, %f10
-
- xor %g4, %o0, %o0 ! ^= rk[0]
- xor %g5, %o1, %o1
- xor %g4, %o2, %o2 ! ^= rk[0]
- xor %g5, %o3, %o3
- movxtod %o0, %f0
- movxtod %o1, %f2
- movxtod %o2, %f4
- movxtod %o3, %f6
-
- fxor %f12, %f0, %f0 ! ^= tweak[0]
- fxor %f14, %f2, %f2
- fxor %f8, %f4, %f4 ! ^= tweak[0]
- fxor %f10, %f6, %f6
-
- prefetch [$inp + 32+63], 20
- call _${alg}${bits}_${dir}crypt_2x
- add $inp, 32, $inp
-
- movxtod %g2, %f8
- movxtod %g3, %f10
-
- srax %g3, 63, %l7 ! next tweak value
- addcc %g2, %g2, %g2
- and %l7, 0x87, %l7
- addxc %g3, %g3, %g3
- xor %l7, %g2, %g2
-
- bshuffle %f8, %f8, %f8
- bshuffle %f10, %f10, %f10
-
- fxor %f12, %f0, %f0 ! ^= tweak[0]
- fxor %f14, %f2, %f2
- fxor %f8, %f4, %f4
- fxor %f10, %f6, %f6
-
- stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- add $out, 8, $out
- stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
- bgu,pt $::size_t_cc, .L${bits}_xts_${dir}blk2x
- add $out, 8, $out
-
- add $blk_init, $len, $len
- andcc $len, 1, %g0 ! is number of blocks even?
- membar #StoreLoad|#StoreStore
- bnz,pt %icc, .L${bits}_xts_${dir}loop
- srl $len, 0, $len
- brnz,pn $len, .L${bits}_xts_${dir}loop2x
- nop
-
- fsrc2 %f4, %f0
- fsrc2 %f6, %f2
- brnz,pn $rem, .L${bits}_xts_${dir}steal
- nop
-
- ret
- restore
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-___
-$code.=<<___ if ($dir eq "en");
-.align 32
-.L${bits}_xts_${dir}steal:
- std %f0, [%fp + $::bias-16] ! copy of output
- std %f2, [%fp + $::bias-8]
-
- srl $ileft, 3, $ileft
- add %fp, $::bias-16, %l7
- add $inp, $ileft, $inp ! original $inp+$len&-15
- add $out, $ooff, $out ! original $out+$len&-15
- mov 0, $ileft
- nop ! align
-
-.L${bits}_xts_${dir}stealing:
- ldub [$inp + $ileft], %o0
- ldub [%l7 + $ileft], %o1
- dec $rem
- stb %o0, [%l7 + $ileft]
- stb %o1, [$out + $ileft]
- brnz $rem, .L${bits}_xts_${dir}stealing
- inc $ileft
-
- mov %l7, $inp
- sub $out, 16, $out
- mov 0, $ileft
- sub $out, $ooff, $out
- ba .L${bits}_xts_${dir}loop ! one more time
- mov 1, $len ! $rem is 0
-___
-$code.=<<___ if ($dir eq "de");
-.align 32
-.L${bits}_xts_${dir}steal:
- ldx [$inp + 0], %o0
- brz,pt $ileft, 8f
- ldx [$inp + 8], %o1
-
- ldx [$inp + 16], %o2
- sllx %o0, $ileft, %o0
- srlx %o1, $iright, %g1
- sllx %o1, $ileft, %o1
- or %g1, %o0, %o0
- srlx %o2, $iright, %o2
- or %o2, %o1, %o1
-8:
- srax %g3, 63, %l7 ! next tweak value
- addcc %g2, %g2, %o2
- and %l7, 0x87, %l7
- addxc %g3, %g3, %o3
- xor %l7, %o2, %o2
-
- movxtod %o2, %f12
- movxtod %o3, %f14
- bshuffle %f12, %f12, %f12
- bshuffle %f14, %f14, %f14
-
- xor %g4, %o0, %o0 ! ^= rk[0]
- xor %g5, %o1, %o1
- movxtod %o0, %f0
- movxtod %o1, %f2
-
- fxor %f12, %f0, %f0 ! ^= tweak[0]
- fxor %f14, %f2, %f2
-
- call _${alg}${bits}_${dir}crypt_1x
- add $inp, 16, $inp
-
- fxor %f12, %f0, %f0 ! ^= tweak[0]
- fxor %f14, %f2, %f2
-
- std %f0, [%fp + $::bias-16]
- std %f2, [%fp + $::bias-8]
-
- srl $ileft, 3, $ileft
- add %fp, $::bias-16, %l7
- add $inp, $ileft, $inp ! original $inp+$len&-15
- add $out, $ooff, $out ! original $out+$len&-15
- mov 0, $ileft
- add $out, 16, $out
- nop ! align
-
-.L${bits}_xts_${dir}stealing:
- ldub [$inp + $ileft], %o0
- ldub [%l7 + $ileft], %o1
- dec $rem
- stb %o0, [%l7 + $ileft]
- stb %o1, [$out + $ileft]
- brnz $rem, .L${bits}_xts_${dir}stealing
- inc $ileft
-
- mov %l7, $inp
- sub $out, 16, $out
- mov 0, $ileft
- sub $out, $ooff, $out
- ba .L${bits}_xts_${dir}loop ! one more time
- mov 1, $len ! $rem is 0
-___
-$code.=<<___;
- ret
- restore
-.type ${alg}${bits}_t4_xts_${dir}crypt,#function
-.size ${alg}${bits}_t4_xts_${dir}crypt,.-${alg}${bits}_t4_xts_${dir}crypt
-___
-}
-
-# Purpose of these subroutines is to explicitly encode VIS instructions,
-# so that one can compile the module without having to specify VIS
-# extentions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a.
-# Idea is to reserve for option to produce "universal" binary and let
-# programmer detect if current CPU is VIS capable at run-time.
-sub unvis {
-my ($mnemonic,$rs1,$rs2,$rd)=@_;
-my ($ref,$opf);
-my %visopf = ( "faligndata" => 0x048,
- "bshuffle" => 0x04c,
- "fnot2" => 0x066,
- "fxor" => 0x06c,
- "fsrc2" => 0x078 );
-
- $ref = "$mnemonic\t$rs1,$rs2,$rd";
-
- if ($opf=$visopf{$mnemonic}) {
- foreach ($rs1,$rs2,$rd) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
-
- return sprintf ".word\t0x%08x !%s",
- 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
-}
-
-sub unvis3 {
-my ($mnemonic,$rs1,$rs2,$rd)=@_;
-my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 );
-my ($ref,$opf);
-my %visopf = ( "addxc" => 0x011,
- "addxccc" => 0x013,
- "umulxhi" => 0x016,
- "alignaddr" => 0x018,
- "bmask" => 0x019,
- "alignaddrl" => 0x01a );
-
- $ref = "$mnemonic\t$rs1,$rs2,$rd";
-
- if ($opf=$visopf{$mnemonic}) {
- foreach ($rs1,$rs2,$rd) {
- return $ref if (!/%([goli])([0-9])/);
- $_=$bias{$1}+$2;
- }
-
- return sprintf ".word\t0x%08x !%s",
- 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
-}
-
-sub unaes_round { # 4-argument instructions
-my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
-my ($ref,$opf);
-my %aesopf = ( "aes_eround01" => 0,
- "aes_eround23" => 1,
- "aes_dround01" => 2,
- "aes_dround23" => 3,
- "aes_eround01_l"=> 4,
- "aes_eround23_l"=> 5,
- "aes_dround01_l"=> 6,
- "aes_dround23_l"=> 7,
- "aes_kexpand1" => 8 );
-
- $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
-
- if (defined($opf=$aesopf{$mnemonic})) {
- $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3;
- foreach ($rs1,$rs2,$rd) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
-
- return sprintf ".word\t0x%08x !%s",
- 2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
-}
-
-sub unaes_kexpand { # 3-argument instructions
-my ($mnemonic,$rs1,$rs2,$rd)=@_;
-my ($ref,$opf);
-my %aesopf = ( "aes_kexpand0" => 0x130,
- "aes_kexpand2" => 0x131 );
-
- $ref = "$mnemonic\t$rs1,$rs2,$rd";
-
- if (defined($opf=$aesopf{$mnemonic})) {
- foreach ($rs1,$rs2,$rd) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
-
- return sprintf ".word\t0x%08x !%s",
- 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
-}
-
-sub uncamellia_f { # 4-argument instructions
-my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
-my ($ref,$opf);
-
- $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
-
- if (1) {
- $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3;
- foreach ($rs1,$rs2,$rd) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
-
- return sprintf ".word\t0x%08x !%s",
- 2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|0xc<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
-}
-
-sub uncamellia3 { # 3-argument instructions
-my ($mnemonic,$rs1,$rs2,$rd)=@_;
-my ($ref,$opf);
-my %cmllopf = ( "camellia_fl" => 0x13c,
- "camellia_fli" => 0x13d );
-
- $ref = "$mnemonic\t$rs1,$rs2,$rd";
-
- if (defined($opf=$cmllopf{$mnemonic})) {
- foreach ($rs1,$rs2,$rd) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
-
- return sprintf ".word\t0x%08x !%s",
- 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
- $ref;
- } else {
- return $ref;
- }
-}
-
-sub unmovxtox { # 2-argument instructions
-my ($mnemonic,$rs,$rd)=@_;
-my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24, "f" => 0 );
-my ($ref,$opf);
-my %movxopf = ( "movdtox" => 0x110,
- "movstouw" => 0x111,
- "movstosw" => 0x113,
- "movxtod" => 0x118,
- "movwtos" => 0x119 );
-
- $ref = "$mnemonic\t$rs,$rd";
-
- if (defined($opf=$movxopf{$mnemonic})) {
- foreach ($rs,$rd) {
- return $ref if (!/%([fgoli])([0-9]{1,2})/);
- $_=$bias{$1}+$2;
- if ($2>=32) {
- return $ref if ($2&1);
- # re-encode for upper double register addressing
- $_=($2|$2>>5)&31;
- }
- }
-
- return sprintf ".word\t0x%08x !%s",
- 2<<30|$rd<<25|0x36<<19|$opf<<5|$rs,
- $ref;
- } else {
- return $ref;
- }
-}
-
-sub undes {
-my ($mnemonic)=shift;
-my @args=@_;
-my ($ref,$opf);
-my %desopf = ( "des_round" => 0b1001,
- "des_ip" => 0b100110100,
- "des_iip" => 0b100110101,
- "des_kexpand" => 0b100110110 );
-
- $ref = "$mnemonic\t".join(",",@_);
-
- if (defined($opf=$desopf{$mnemonic})) { # 4-arg
- if ($mnemonic eq "des_round") {
- foreach (@args[0..3]) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($1&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
- return sprintf ".word\t0x%08x !%s",
- 2<<30|0b011001<<19|$opf<<5|$args[0]<<14|$args[1]|$args[2]<<9|$args[3]<<25,
- $ref;
- } elsif ($mnemonic eq "des_kexpand") { # 3-arg
- foreach (@args[0..2]) {
- return $ref if (!/(%f)?([0-9]{1,2})/);
- $_=$2;
- if ($2>=32) {
- return $ref if ($2&1);
- # re-encode for upper double register addressing
- $_=($2|$2>>5)&31;
- }
- }
- return sprintf ".word\t0x%08x !%s",
- 2<<30|0b110110<<19|$opf<<5|$args[0]<<14|$args[1]|$args[2]<<25,
- $ref;
- } else { # 2-arg
- foreach (@args[0..1]) {
- return $ref if (!/%f([0-9]{1,2})/);
- $_=$1;
- if ($1>=32) {
- return $ref if ($2&1);
- # re-encode for upper double register addressing
- $_=($1|$1>>5)&31;
- }
- }
- return sprintf ".word\t0x%08x !%s",
- 2<<30|0b110110<<19|$opf<<5|$args[0]<<14|$args[1]<<25,
- $ref;
- }
- } else {
- return $ref;
- }
-}
-
-sub emit_assembler {
- foreach (split("\n",$::code)) {
- s/\`([^\`]*)\`/eval $1/ge;
-
- s/\b(f[a-z]+2[sd]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})\s*$/$1\t%f0,$2,$3/go;
-
- s/\b(aes_[edk][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
- &unaes_round($1,$2,$3,$4,$5)
- /geo or
- s/\b(aes_kexpand[02])\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
- &unaes_kexpand($1,$2,$3,$4)
- /geo or
- s/\b(camellia_f)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
- &uncamellia_f($1,$2,$3,$4,$5)
- /geo or
- s/\b(camellia_[^s]+)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
- &uncamellia3($1,$2,$3,$4)
- /geo or
- s/\b(des_\w+)\s+(%f[0-9]{1,2}),\s*([%fx0-9]+)(?:,\s*(%f[0-9]{1,2})(?:,\s*(%f[0-9]{1,2}))?)?/
- &undes($1,$2,$3,$4,$5)
- /geo or
- s/\b(mov[ds]to\w+)\s+(%f[0-9]{1,2}),\s*(%[goli][0-7])/
- &unmovxtox($1,$2,$3)
- /geo or
- s/\b(mov[xw]to[ds])\s+(%[goli][0-7]),\s*(%f[0-9]{1,2})/
- &unmovxtox($1,$2,$3)
- /geo or
- s/\b([fb][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
- &unvis($1,$2,$3,$4)
- /geo or
- s/\b(umulxhi|bmask|addxc[c]{0,2}|alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/
- &unvis3($1,$2,$3,$4)
- /geo;
-
- print $_,"\n";
- }
-}
-
-1;
diff --git a/src/crypto/perlasm/x86masm.pl b/src/crypto/perlasm/x86masm.pl
index a491529..b7f49d1 100644
--- a/src/crypto/perlasm/x86masm.pl
+++ b/src/crypto/perlasm/x86masm.pl
@@ -18,10 +18,10 @@ sub ::generic
if ($opcode =~ /lea/ && @arg[1] =~ s/.*PTR\s+(\(.*\))$/OFFSET $1/) # no []
{ $opcode="mov"; }
- elsif ($opcode !~ /movq/)
+ elsif ($opcode !~ /mov[dq]$/)
{ # fix xmm references
- $arg[0] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[1]=~/\bxmm[0-7]\b/i);
- $arg[1] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[0]=~/\bxmm[0-7]\b/i);
+ $arg[0] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[-1]=~/\bxmm[0-7]\b/i);
+ $arg[-1] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[0]=~/\bxmm[0-7]\b/i);
}
&::emit($opcode,@arg);
@@ -160,16 +160,13 @@ sub ::public_label
{ push(@out,"PUBLIC\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); }
sub ::data_byte
-{ push(@out,("DB\t").join(',',@_)."\n"); }
+{ push(@out,("DB\t").join(',',splice(@_,0,16))."\n") while(@_); }
sub ::data_short
-{ push(@out,("DW\t").join(',',@_)."\n"); }
+{ push(@out,("DW\t").join(',',splice(@_,0,8))."\n") while(@_); }
sub ::data_word
-{ # MASM can't handle long lines, so emit one word at a time.
- foreach(@_)
- { push(@out,"DD\t$_\n"); }
-}
+{ push(@out,("DD\t").join(',',splice(@_,0,4))."\n") while(@_); }
sub ::align
{ push(@out,"ALIGN\t$_[0]\n"); }
diff --git a/src/crypto/pkcs8/CMakeLists.txt b/src/crypto/pkcs8/CMakeLists.txt
index 1886fce..c0f2746 100644
--- a/src/crypto/pkcs8/CMakeLists.txt
+++ b/src/crypto/pkcs8/CMakeLists.txt
@@ -9,13 +9,12 @@ add_library(
p8_pkey.c
p5_pbe.c
p5_pbev2.c
- pkcs8_error.c
)
add_executable(
pkcs12_test
- pkcs12_test.c
+ pkcs12_test.cc
)
target_link_libraries(pkcs12_test crypto)
diff --git a/src/crypto/pkcs8/pkcs12_test.c b/src/crypto/pkcs8/pkcs12_test.cc
index 2292b77..8b265cd 100644
--- a/src/crypto/pkcs8/pkcs12_test.c
+++ b/src/crypto/pkcs8/pkcs12_test.cc
@@ -13,7 +13,6 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <stdio.h>
-#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/bytestring.h>
@@ -24,6 +23,8 @@
#include <openssl/stack.h>
#include <openssl/x509.h>
+#include "../test/scoped_types.h"
+
/* kPKCS12DER contains sample PKCS#12 data generated by OpenSSL with:
* openssl pkcs12 -export -inkey key.pem -in cacert.pem */
@@ -680,81 +681,76 @@ static const uint8_t kWindows[] = {
0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0,
};
-static int test(const char *name, const uint8_t *der, size_t der_len) {
- CBS pkcs12;
- EVP_PKEY *key;
- STACK_OF(X509) *certs;
-
- certs = sk_X509_new_null();
+static bool Test(const char *name, const uint8_t *der, size_t der_len) {
+ ScopedX509Stack certs(sk_X509_new_null());
+ if (!certs) {
+ return false;
+ }
+ CBS pkcs12;
+ EVP_PKEY *key = nullptr;
CBS_init(&pkcs12, der, der_len);
- if (!PKCS12_get_key_and_certs(&key, certs, &pkcs12, "foo")) {
+ if (!PKCS12_get_key_and_certs(&key, certs.get(), &pkcs12, "foo")) {
fprintf(stderr, "PKCS12 failed on %s data.\n", name);
- BIO_print_errors_fp(stderr);
- return 0;
+ ERR_print_errors_fp(stderr);
+ return false;
}
+ ScopedEVP_PKEY delete_key(key);
- if (sk_X509_num(certs) != 1 || key == NULL) {
+ if (sk_X509_num(certs.get()) != 1 || key == nullptr) {
fprintf(stderr, "Bad result from %s data.\n", name);
- return 0;
+ return false;
}
- sk_X509_pop_free(certs, X509_free);
- EVP_PKEY_free(key);
-
- return 1;
+ return true;
}
-static int test_compat(const uint8_t *der, size_t der_len) {
- PKCS12 *p12;
- X509 *cert = NULL;
- STACK_OF(X509) *ca_certs = NULL;
- EVP_PKEY *key;
- BIO *bio;
-
- bio = BIO_new_mem_buf((void*) der, der_len);
+static bool TestCompat(const uint8_t *der, size_t der_len) {
+ ScopedBIO bio(BIO_new_mem_buf((void*) der, der_len));
+ if (!bio) {
+ return false;
+ }
- p12 = d2i_PKCS12_bio(bio, NULL);
- if (p12 == NULL) {
+ ScopedPKCS12 p12(d2i_PKCS12_bio(bio.get(), nullptr));
+ if (!p12) {
fprintf(stderr, "PKCS12_parse failed.\n");
- BIO_print_errors_fp(stderr);
- return 0;
+ ERR_print_errors_fp(stderr);
+ return false;
}
- BIO_free(bio);
- if (!PKCS12_parse(p12, "foo", &key, &cert, &ca_certs)) {
+ EVP_PKEY *key = nullptr;
+ X509 *cert = nullptr;
+ STACK_OF(X509) *ca_certs = nullptr;
+ if (!PKCS12_parse(p12.get(), "foo", &key, &cert, &ca_certs)) {
fprintf(stderr, "PKCS12_parse failed.\n");
- BIO_print_errors_fp(stderr);
- return 0;
+ ERR_print_errors_fp(stderr);
+ return false;
}
+ ScopedEVP_PKEY delete_key(key);
+ ScopedX509 delete_cert(cert);
+ ScopedX509Stack delete_ca_certs(ca_certs);
- if (key == NULL || cert == NULL) {
+ if (key == nullptr || cert == nullptr) {
fprintf(stderr, "Bad result from PKCS12_parse.\n");
- return 0;
+ return false;
}
- EVP_PKEY_free(key);
- X509_free(cert);
-
if (sk_X509_num(ca_certs) != 0) {
fprintf(stderr, "Bad result from PKCS12_parse.\n");
- return 0;
+ return false;
}
- sk_X509_free(ca_certs);
-
- PKCS12_free(p12);
- return 1;
+ return true;
}
int main(int argc, char **argv) {
CRYPTO_library_init();
ERR_load_crypto_strings();
- if (!test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
- !test("NSS", kNSS, sizeof(kNSS)) ||
- !test("Windows", kWindows, sizeof(kWindows)) ||
- !test_compat(kWindows, sizeof(kWindows))) {
+ if (!Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
+ !Test("NSS", kNSS, sizeof(kNSS)) ||
+ !Test("Windows", kWindows, sizeof(kWindows)) ||
+ !TestCompat(kWindows, sizeof(kWindows))) {
return 1;
}
diff --git a/src/crypto/pkcs8/pkcs8.c b/src/crypto/pkcs8/pkcs8.c
index 0b1dfba..843c74d 100644
--- a/src/crypto/pkcs8/pkcs8.c
+++ b/src/crypto/pkcs8/pkcs8.c
@@ -123,23 +123,28 @@ static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len,
Ai = OPENSSL_malloc(u);
B = OPENSSL_malloc(v + 1);
Slen = v * ((salt_len + v - 1) / v);
- if (pass_raw_len)
+ if (pass_raw_len) {
Plen = v * ((pass_raw_len + v - 1) / v);
- else
+ } else {
Plen = 0;
+ }
Ilen = Slen + Plen;
I = OPENSSL_malloc(Ilen);
Ij = BN_new();
Bpl1 = BN_new();
- if (!D || !Ai || !B || !I || !Ij || !Bpl1)
+ if (!D || !Ai || !B || !I || !Ij || !Bpl1) {
goto err;
- for (i = 0; i < v; i++)
+ }
+ for (i = 0; i < v; i++) {
D[i] = id;
+ }
p = I;
- for (i = 0; i < Slen; i++)
+ for (i = 0; i < Slen; i++) {
*p++ = salt[i % salt_len];
- for (i = 0; i < Plen; i++)
+ }
+ for (i = 0; i < Plen; i++) {
*p++ = pass_raw[i % pass_raw_len];
+ }
for (;;) {
if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
!EVP_DigestUpdate(&ctx, D, v) ||
@@ -161,31 +166,33 @@ static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len,
}
out_len -= u;
out += u;
- for (j = 0; j < v; j++)
+ for (j = 0; j < v; j++) {
B[j] = Ai[j % u];
+ }
/* Work out B + 1 first then can use B as tmp space */
- if (!BN_bin2bn(B, v, Bpl1))
- goto err;
- if (!BN_add_word(Bpl1, 1))
+ if (!BN_bin2bn(B, v, Bpl1) ||
+ !BN_add_word(Bpl1, 1)) {
goto err;
+ }
for (j = 0; j < Ilen; j += v) {
- if (!BN_bin2bn(I + j, v, Ij))
- goto err;
- if (!BN_add(Ij, Ij, Bpl1))
- goto err;
- if (!BN_bn2bin(Ij, B))
+ if (!BN_bin2bn(I + j, v, Ij) ||
+ !BN_add(Ij, Ij, Bpl1) ||
+ !BN_bn2bin(Ij, B)) {
goto err;
+ }
Ijlen = BN_num_bytes(Ij);
/* If more than 2^(v*8) - 1 cut off MSB */
if (Ijlen > v) {
- if (!BN_bn2bin(Ij, B))
+ if (!BN_bn2bin(Ij, B)) {
goto err;
+ }
memcpy(I + j, B + 1, v);
/* If less than v bytes pad with zeroes */
} else if (Ijlen < v) {
memset(I + j, 0, v - Ijlen);
- if (!BN_bn2bin(Ij, I + j + v - Ijlen))
+ if (!BN_bn2bin(Ij, I + j + v - Ijlen)) {
goto err;
+ }
} else if (!BN_bn2bin(Ij, I + j)) {
goto err;
}
@@ -427,7 +434,7 @@ PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass,
pass_len = strlen(pass);
}
if (!ascii_to_ucs2(pass, pass_len, &pass_raw, &pass_raw_len)) {
- OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_asc, PKCS8_R_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_decrypt, PKCS8_R_DECODE_ERROR);
return NULL;
}
}
@@ -491,7 +498,7 @@ X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
pass_len = strlen(pass);
}
if (!ascii_to_ucs2(pass, pass_len, &pass_raw, &pass_raw_len)) {
- OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_asc, PKCS8_R_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt, PKCS8_R_DECODE_ERROR);
return NULL;
}
}
@@ -547,8 +554,9 @@ EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
ASN1_OBJECT *algoid;
char obj_tmp[80];
- if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8))
+ if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) {
return NULL;
+ }
pkey = EVP_PKEY_new();
if (pkey == NULL) {
@@ -683,9 +691,7 @@ static int PKCS12_handle_content_infos(CBS *content_infos,
ret = 1;
err:
- if (der_bytes != NULL) {
- OPENSSL_free(der_bytes);
- }
+ OPENSSL_free(der_bytes);
return ret;
}
@@ -699,7 +705,8 @@ static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
!CBS_get_asn1(content_info, &wrapped_contents,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
@@ -884,27 +891,28 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) ||
CBS_len(&in) != 0 ||
!CBS_get_asn1_uint64(&pfx, &version)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
if (version < 3) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_VERSION);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs,
+ PKCS8_R_BAD_PKCS12_VERSION);
goto err;
}
if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
if (CBS_len(&pfx) == 0) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_MISSING_MAC);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_MISSING_MAC);
goto err;
}
if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
@@ -913,7 +921,7 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) ||
!CBS_get_asn1(&authsafe, &wrapped_authsafes,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
@@ -921,13 +929,13 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
* latter indicates that it's signed by a public key, which isn't
* supported. */
if (OBJ_cbs2nid(&content_type) != NID_pkcs7_data) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse,
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs,
PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED);
goto err;
}
if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
@@ -935,7 +943,7 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
ctx.out_certs = out_certs;
if (!ascii_to_ucs2(password, strlen(password), &ctx.password,
&ctx.password_len)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_DECODE_ERROR);
goto err;
}
@@ -954,7 +962,7 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
!CBS_get_asn1(&hash_type_seq, &hash_oid, CBS_ASN1_OBJECT) ||
!CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) ||
!CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
@@ -963,7 +971,8 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
if (CBS_len(&mac_data) > 0) {
if (!CBS_get_asn1_uint64(&mac_data, &iterations) ||
iterations > INT_MAX) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs,
+ PKCS8_R_BAD_PKCS12_DATA);
goto err;
}
}
@@ -971,7 +980,7 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
hash_nid = OBJ_cbs2nid(&hash_oid);
if (hash_nid == NID_undef ||
(md = EVP_get_digestbynid(hash_nid)) == NULL) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_UNKNOWN_HASH);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs, PKCS8_R_UNKNOWN_HASH);
goto err;
}
@@ -987,7 +996,8 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
}
if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) {
- OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_INCORRECT_PASSWORD);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_get_key_and_certs,
+ PKCS8_R_INCORRECT_PASSWORD);
goto err;
}
}
@@ -1000,17 +1010,11 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
ret = 1;
err:
- if (ctx.password) {
- OPENSSL_free(ctx.password);
- }
- if (der_bytes) {
- OPENSSL_free(der_bytes);
- }
+ OPENSSL_free(ctx.password);
+ OPENSSL_free(der_bytes);
if (!ret) {
- if (*out_key) {
- EVP_PKEY_free(*out_key);
- *out_key = NULL;
- }
+ EVP_PKEY_free(*out_key);
+ *out_key = NULL;
while (sk_X509_num(out_certs) > original_out_certs_len) {
X509 *x509 = sk_X509_pop(out_certs);
X509_free(x509);
diff --git a/src/crypto/pkcs8/pkcs8_error.c b/src/crypto/pkcs8/pkcs8_error.c
deleted file mode 100644
index 3041658..0000000
--- a/src/crypto/pkcs8/pkcs8_error.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* 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/pkcs8.h>
-
-const ERR_STRING_DATA PKCS8_error_string_data[] = {
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_EVP_PKCS82PKEY, 0), "EVP_PKCS82PKEY"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_EVP_PKEY2PKCS8, 0), "EVP_PKEY2PKCS8"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_get_key_and_certs, 0), "PKCS12_get_key_and_certs"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_handle_content_info, 0), "PKCS12_handle_content_info"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_handle_content_infos, 0), "PKCS12_handle_content_infos"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_parse, 0), "PKCS12_parse"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe2_set_iv, 0), "PKCS5_pbe2_set_iv"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe_set, 0), "PKCS5_pbe_set"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe_set0_algor, 0), "PKCS5_pbe_set0_algor"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbkdf2_set, 0), "PKCS5_pbkdf2_set"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS8_decrypt, 0), "PKCS8_decrypt"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS8_encrypt, 0), "PKCS8_encrypt"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS8_encrypt_pbe, 0), "PKCS8_encrypt_pbe"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pbe_cipher_init, 0), "pbe_cipher_init"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pbe_crypt, 0), "pbe_crypt"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_item_decrypt_d2i, 0), "pkcs12_item_decrypt_d2i"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_item_i2d_encrypt, 0), "pkcs12_item_i2d_encrypt"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_asc, 0), "pkcs12_key_gen_asc"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_raw, 0), "pkcs12_key_gen_raw"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_uni, 0), "pkcs12_key_gen_uni"},
- {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_pbe_keyivgen, 0), "pkcs12_pbe_keyivgen"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_MAC), "BAD_MAC"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_PKCS12_DATA), "BAD_PKCS12_DATA"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_PKCS12_VERSION), "BAD_PKCS12_VERSION"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "CIPHER_HAS_NO_OBJECT_IDENTIFIER"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_CRYPT_ERROR), "CRYPT_ERROR"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_DECODE_ERROR), "DECODE_ERROR"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ENCODE_ERROR), "ENCODE_ERROR"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ENCRYPT_ERROR), "ENCRYPT_ERROR"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS), "ERROR_SETTING_CIPHER_PARAMS"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_INCORRECT_PASSWORD), "INCORRECT_PASSWORD"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_KEYGEN_FAILURE), "KEYGEN_FAILURE"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_KEY_GEN_ERROR), "KEY_GEN_ERROR"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_METHOD_NOT_SUPPORTED), "METHOD_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_MISSING_MAC), "MISSING_MAC"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12), "MULTIPLE_PRIVATE_KEYS_IN_PKCS12"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED), "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PKCS12_TOO_DEEPLY_NESTED), "PKCS12_TOO_DEEPLY_NESTED"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PRIVATE_KEY_DECODE_ERROR), "PRIVATE_KEY_DECODE_ERROR"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PRIVATE_KEY_ENCODE_ERROR), "PRIVATE_KEY_ENCODE_ERROR"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_TOO_LONG), "TOO_LONG"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_ALGORITHM), "UNKNOWN_ALGORITHM"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_CIPHER), "UNKNOWN_CIPHER"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM), "UNKNOWN_CIPHER_ALGORITHM"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_DIGEST), "UNKNOWN_DIGEST"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_HASH), "UNKNOWN_HASH"},
- {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), "UNSUPPORTED_PRIVATE_KEY_ALGORITHM"},
- {0, NULL},
-};
diff --git a/src/crypto/poly1305/poly1305.c b/src/crypto/poly1305/poly1305.c
index bf5cd5e..5a49e2d 100644
--- a/src/crypto/poly1305/poly1305.c
+++ b/src/crypto/poly1305/poly1305.c
@@ -132,19 +132,23 @@ poly1305_donna_mul:
b = (uint32_t)(t[4] >> 26);
state->h0 += b * 5;
- if (len >= 16)
+ if (len >= 16) {
goto poly1305_donna_16bytes;
+ }
/* final bytes */
poly1305_donna_atmost15bytes:
- if (!len)
+ if (!len) {
return;
+ }
- for (j = 0; j < len; j++)
+ for (j = 0; j < len; j++) {
mp[j] = in[j];
+ }
mp[j++] = 1;
- for (; j < 16; j++)
+ for (; j < 16; j++) {
mp[j] = 0;
+ }
len = 0;
t0 = U8TO32_LE(mp + 0);
@@ -221,10 +225,12 @@ void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
if (state->buf_used) {
unsigned int todo = 16 - state->buf_used;
- if (todo > in_len)
+ if (todo > in_len) {
todo = in_len;
- for (i = 0; i < todo; i++)
+ }
+ for (i = 0; i < todo; i++) {
state->buf[state->buf_used + i] = in[i];
+ }
state->buf_used += todo;
in_len -= todo;
in += todo;
@@ -243,8 +249,9 @@ void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
}
if (in_len) {
- for (i = 0; i < in_len; i++)
+ for (i = 0; i < in_len; i++) {
state->buf[i] = in[i];
+ }
state->buf_used = in_len;
}
}
@@ -262,8 +269,9 @@ void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) {
}
#endif
- if (state->buf_used)
+ if (state->buf_used) {
poly1305_update(state, state->buf, state->buf_used);
+ }
b = state->h0 >> 26;
state->h0 = state->h0 & 0x3ffffff;
diff --git a/src/crypto/poly1305/poly1305_arm.c b/src/crypto/poly1305/poly1305_arm.c
index 61ebec5..c06eded 100644
--- a/src/crypto/poly1305/poly1305_arm.c
+++ b/src/crypto/poly1305/poly1305_arm.c
@@ -135,13 +135,15 @@ static void fe1305x2_frombytearray(fe1305x2 *r, const uint8_t *x,
int i;
uint8_t t[17];
- for (i = 0; (i < 16) && (i < xlen); i++)
+ for (i = 0; (i < 16) && (i < xlen); i++) {
t[i] = x[i];
+ }
xlen -= i;
x += i;
t[i++] = 1;
- for (; i < 17; i++)
+ for (; i < 17; i++) {
t[i] = 0;
+ }
r->v[0] = 0x3ffffff & load32(t);
r->v[2] = 0x3ffffff & (load32(t + 3) >> 2);
@@ -150,19 +152,22 @@ static void fe1305x2_frombytearray(fe1305x2 *r, const uint8_t *x,
r->v[8] = load32(t + 13);
if (xlen) {
- for (i = 0; (i < 16) && (i < xlen); i++)
+ for (i = 0; (i < 16) && (i < xlen); i++) {
t[i] = x[i];
+ }
t[i++] = 1;
- for (; i < 17; i++)
+ for (; i < 17; i++) {
t[i] = 0;
+ }
r->v[1] = 0x3ffffff & load32(t);
r->v[3] = 0x3ffffff & (load32(t + 3) >> 2);
r->v[5] = 0x3ffffff & (load32(t + 6) >> 4);
r->v[7] = 0x3ffffff & (load32(t + 9) >> 6);
r->v[9] = load32(t + 13);
- } else
+ } else {
r->v[1] = r->v[3] = r->v[5] = r->v[7] = r->v[9] = 0;
+ }
}
static const fe1305x2 zero __attribute__((aligned(16)));
@@ -188,8 +193,9 @@ void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]) {
r->v[7] = r->v[6] = 0x3f03fff & ((*(uint32_t *)(key + 9)) >> 6);
r->v[9] = r->v[8] = 0x00fffff & ((*(uint32_t *)(key + 12)) >> 8);
- for (j = 0; j < 10; j++)
+ for (j = 0; j < 10; j++) {
h->v[j] = 0; /* XXX: should fast-forward a bit */
+ }
addmulmod(precomp, r, r, &zero); /* precompute r^2 */
addmulmod(precomp + 1, precomp, precomp, &zero); /* precompute r^4 */
@@ -209,10 +215,12 @@ void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
if (st->buf_used) {
unsigned int todo = 32 - st->buf_used;
- if (todo > in_len)
+ if (todo > in_len) {
todo = in_len;
- for (i = 0; i < todo; i++)
+ }
+ for (i = 0; i < todo; i++) {
st->buf[st->buf_used + i] = in[i];
+ }
st->buf_used += todo;
in_len -= todo;
in += todo;
@@ -220,24 +228,27 @@ void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
if (st->buf_used == sizeof(st->buf) && in_len) {
addmulmod(h, h, precomp, &zero);
fe1305x2_frombytearray(c, st->buf, sizeof(st->buf));
- for (i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++) {
h->v[i] += c->v[i];
+ }
st->buf_used = 0;
}
}
while (in_len > 32) {
unsigned int tlen = 1048576;
- if (in_len < tlen)
+ if (in_len < tlen) {
tlen = in_len;
+ }
tlen -= blocks(h, precomp, in, tlen);
in_len -= tlen;
in += tlen;
}
if (in_len) {
- for (i = 0; i < in_len; i++)
+ for (i = 0; i < in_len; i++) {
st->buf[i] = in[i];
+ }
st->buf_used = in_len;
}
}
diff --git a/src/crypto/poly1305/poly1305_vec.c b/src/crypto/poly1305/poly1305_vec.c
index 89fcacb..07578d0 100644
--- a/src/crypto/poly1305/poly1305_vec.c
+++ b/src/crypto/poly1305/poly1305_vec.c
@@ -727,8 +727,9 @@ void CRYPTO_poly1305_update(poly1305_state *state, const uint8_t *m,
bytes -= want;
m += want;
st->leftover += want;
- if ((st->leftover < 32) || (bytes == 0))
+ if ((st->leftover < 32) || (bytes == 0)) {
return;
+ }
poly1305_first_block(st, st->buffer);
st->leftover = 0;
}
@@ -742,8 +743,9 @@ void CRYPTO_poly1305_update(poly1305_state *state, const uint8_t *m,
bytes -= want;
m += want;
st->leftover += want;
- if (st->leftover < 64)
+ if (st->leftover < 64) {
return;
+ }
poly1305_blocks(st, st->buffer, 64);
st->leftover = 0;
}
@@ -791,8 +793,9 @@ void CRYPTO_poly1305_finish(poly1305_state *state, uint8_t mac[16]) {
s1 = r1 * (5 << 2);
s2 = r2 * (5 << 2);
- if (leftover < 16)
+ if (leftover < 16) {
goto poly1305_donna_atmost15bytes;
+ }
poly1305_donna_atleast16bytes:
t0 = U8TO64_LE(m + 0);
@@ -821,13 +824,15 @@ poly1305_donna_mul:
m += 16;
leftover -= 16;
- if (leftover >= 16)
+ if (leftover >= 16) {
goto poly1305_donna_atleast16bytes;
+ }
/* final bytes */
poly1305_donna_atmost15bytes:
- if (!leftover)
+ if (!leftover) {
goto poly1305_donna_finish;
+ }
m[leftover++] = 1;
poly1305_block_zero(m + leftover, 16 - leftover);
diff --git a/src/crypto/rand/CMakeLists.txt b/src/crypto/rand/CMakeLists.txt
index 23c1b24..374d8f1 100644
--- a/src/crypto/rand/CMakeLists.txt
+++ b/src/crypto/rand/CMakeLists.txt
@@ -1,5 +1,13 @@
include_directories(. .. ../../include)
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ RAND_ARCH_SOURCES
+
+ rdrand-x86_64.${ASM_EXT}
+ )
+endif()
+
add_library(
rand
@@ -8,4 +16,9 @@ add_library(
rand.c
urandom.c
windows.c
+ hwrand.c
+
+ ${RAND_ARCH_SOURCES}
)
+
+perlasm(rdrand-x86_64.${ASM_EXT} asm/rdrand-x86_64.pl)
diff --git a/src/crypto/rand/asm/rdrand-x86_64.pl b/src/crypto/rand/asm/rdrand-x86_64.pl
new file mode 100644
index 0000000..a917611
--- /dev/null
+++ b/src/crypto/rand/asm/rdrand-x86_64.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/env perl
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$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";
+*STDOUT=*OUT;
+
+print<<___;
+.text
+
+.globl CRYPTO_rdrand
+.type CRYPTO_rdrand,\@function,1
+.align 16
+CRYPTO_rdrand:
+ .byte 0x48, 0x0f, 0xc7, 0xf0
+ retq
+___
+
+close STDOUT; # flush
diff --git a/src/crypto/rand/hwrand.c b/src/crypto/rand/hwrand.c
new file mode 100644
index 0000000..73d3de7
--- /dev/null
+++ b/src/crypto/rand/hwrand.c
@@ -0,0 +1,56 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/rand.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/cpu.h>
+
+
+#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
+
+int CRYPTO_have_hwrand(void) {
+ return (OPENSSL_ia32cap_P[1] & (1u << 30)) != 0;
+}
+
+/* CRYPTO_rdrand is defined in asm/rdrand-x86_64.pl */
+extern uint64_t CRYPTO_rdrand(void);
+
+void CRYPTO_hwrand(uint8_t *buf, size_t len) {
+ while (len >= 8) {
+ uint64_t rand = CRYPTO_rdrand();
+ memcpy(buf, &rand, sizeof(rand));
+ len -= sizeof(rand);
+ buf += sizeof(rand);
+ }
+
+ if (len > 0) {
+ uint64_t rand = CRYPTO_rdrand();
+ memcpy(buf, &rand, len);
+ }
+}
+
+#else
+
+int CRYPTO_have_hwrand(void) {
+ return 0;
+}
+
+void CRYPTO_hwrand(uint8_t *buf, size_t len) {
+ abort();
+}
+
+#endif
diff --git a/src/crypto/rand/internal.h b/src/crypto/rand/internal.h
new file mode 100644
index 0000000..1cca7f3
--- /dev/null
+++ b/src/crypto/rand/internal.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* CRYPTO_sysrand fills |len| bytes at |buf| with entropy from the operating
+ * system. */
+void CRYPTO_sysrand(uint8_t *buf, size_t len);
+
+/* CRYPTO_have_hwrand returns one iff |CRYPTO_hwrand| can be called to generate
+ * hardware entropy. */
+int CRYPTO_have_hwrand(void);
+
+/* CRYPTO_hwrand fills |len| bytes at |buf| with entropy from the hardware.
+ * This function can only be called if |CRYPTO_have_hwrand| returns one. */
+void CRYPTO_hwrand(uint8_t *buf, size_t len);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H */
diff --git a/src/crypto/rand/rand.c b/src/crypto/rand/rand.c
index efd6c0a..ae30edb 100644
--- a/src/crypto/rand/rand.c
+++ b/src/crypto/rand/rand.c
@@ -14,6 +14,134 @@
#include <openssl/rand.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+/* It's assumed that the operating system always has an unfailing source of
+ * entropy which is accessed via |CRYPTO_sysrand|. (If the operating system
+ * entropy source fails, it's up to |CRYPTO_sysrand| to abort the process—we
+ * don't try to handle it.)
+ *
+ * In addition, the hardware may provide a low-latency RNG. Intel's rdrand
+ * instruction is the canonical example of this. When a hardware RNG is
+ * available we don't need to worry about an RNG failure arising from fork()ing
+ * the process or moving a VM, so we can keep thread-local RNG state and XOR
+ * the hardware entropy in.
+ *
+ * (We assume that the OS entropy is safe from fork()ing and VM duplication.
+ * This might be a bit of a leap of faith, esp on Windows, but there's nothing
+ * that we can do about it.) */
+
+/* rand_thread_state contains the per-thread state for the RNG. This is only
+ * used if the system has support for a hardware RNG. */
+struct rand_thread_state {
+ uint8_t key[32];
+ uint64_t calls_used;
+ size_t bytes_used;
+ uint8_t partial_block[64];
+ unsigned partial_block_used;
+};
+
+/* kMaxCallsPerRefresh is the maximum number of |RAND_bytes| calls that we'll
+ * serve before reading a new key from the operating system. This only applies
+ * if we have a hardware RNG. */
+static const unsigned kMaxCallsPerRefresh = 1024;
+
+/* kMaxBytesPerRefresh is the maximum number of bytes that we'll return from
+ * |RAND_bytes| before reading a new key from the operating system. This only
+ * applies if we have a hardware RNG. */
+static const uint64_t kMaxBytesPerRefresh = 1024 * 1024;
+
+/* rand_thread_state_free frees a |rand_thread_state|. This is called when a
+ * thread exits. */
+static void rand_thread_state_free(void *state) {
+ if (state == NULL) {
+ return;
+ }
+
+ OPENSSL_cleanse(state, sizeof(struct rand_thread_state));
+ OPENSSL_free(state);
+}
+
+extern void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint8_t key[32], const uint8_t nonce[8],
+ size_t counter);
+
+int RAND_bytes(uint8_t *buf, size_t len) {
+ if (len == 0) {
+ return 1;
+ }
+
+ if (!CRYPTO_have_hwrand()) {
+ /* Without a hardware RNG to save us from address-space duplication, the OS
+ * entropy is used directly. */
+ CRYPTO_sysrand(buf, len);
+ return 1;
+ }
+
+ struct rand_thread_state *state =
+ CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_RAND);
+ if (state == NULL) {
+ state = OPENSSL_malloc(sizeof(struct rand_thread_state));
+ if (state == NULL ||
+ !CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_RAND, state,
+ rand_thread_state_free)) {
+ CRYPTO_sysrand(buf, len);
+ return 1;
+ }
+
+ state->calls_used = kMaxCallsPerRefresh;
+ }
+
+ if (state->calls_used >= kMaxCallsPerRefresh ||
+ state->bytes_used >= kMaxBytesPerRefresh) {
+ CRYPTO_sysrand(state->key, sizeof(state->key));
+ state->calls_used = 0;
+ state->bytes_used = 0;
+ state->partial_block_used = sizeof(state->partial_block);
+ }
+
+ CRYPTO_hwrand(buf, len);
+
+ if (len >= sizeof(state->partial_block)) {
+ size_t remaining = len;
+ while (remaining > 0) {
+ // kMaxBytesPerCall is only 2GB, while ChaCha can handle 256GB. But this
+ // is sufficient and easier on 32-bit.
+ static const size_t kMaxBytesPerCall = 0x80000000;
+ size_t todo = remaining;
+ if (todo > kMaxBytesPerCall) {
+ todo = kMaxBytesPerCall;
+ }
+ CRYPTO_chacha_20(buf, buf, todo, state->key,
+ (uint8_t *)&state->calls_used, 0);
+ buf += todo;
+ remaining -= todo;
+ state->calls_used++;
+ }
+ } else {
+ if (sizeof(state->partial_block) - state->partial_block_used < len) {
+ CRYPTO_chacha_20(state->partial_block, state->partial_block,
+ sizeof(state->partial_block), state->key,
+ (uint8_t *)&state->calls_used, 0);
+ state->partial_block_used = 0;
+ }
+
+ unsigned i;
+ for (i = 0; i < len; i++) {
+ buf[i] ^= state->partial_block[state->partial_block_used++];
+ }
+ state->calls_used++;
+ }
+ state->bytes_used += len;
+
+ return 1;
+}
int RAND_pseudo_bytes(uint8_t *buf, size_t len) {
return RAND_bytes(buf, len);
diff --git a/src/crypto/rand/urandom.c b/src/crypto/rand/urandom.c
index 2ad4af0..788a979 100644
--- a/src/crypto/rand/urandom.c
+++ b/src/crypto/rand/urandom.c
@@ -19,13 +19,15 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
-#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/thread.h>
#include <openssl/mem.h>
+#include "internal.h"
+#include "../internal.h"
+
/* This file implements a PRNG by reading from /dev/urandom, optionally with a
* fork-safe buffer.
@@ -73,23 +75,26 @@ struct rand_buffer {
/* rand_bytes_per_buf is the number of actual entropy bytes in a buffer. */
static const size_t rand_bytes_per_buf = BUF_SIZE - sizeof(struct rand_buffer);
+static struct CRYPTO_STATIC_MUTEX global_lock = CRYPTO_STATIC_MUTEX_INIT;
+
/* list_head is the start of a global, linked-list of rand_buffer objects. It's
- * protected by CRYPTO_LOCK_RAND. */
+ * protected by |global_lock|. */
static struct rand_buffer *list_head;
/* urandom_fd is a file descriptor to /dev/urandom. It's protected by
- * CRYPTO_LOCK_RAND. */
+ * |global_lock|. */
static int urandom_fd = -2;
/* urandom_buffering controls whether buffering is enabled (1) or not (0). This
- * is protected by CRYPTO_LOCK_RAND. */
+ * is protected by |global_lock|. */
static int urandom_buffering = 0;
/* urandom_get_fd_locked returns a file descriptor to /dev/urandom. The caller
- * of this function must hold CRYPTO_LOCK_RAND. */
+ * of this function must hold |global_lock|. */
static int urandom_get_fd_locked(void) {
- if (urandom_fd != -2)
+ if (urandom_fd != -2) {
return urandom_fd;
+ }
urandom_fd = open("/dev/urandom", O_RDONLY);
return urandom_fd;
@@ -100,7 +105,7 @@ static int urandom_get_fd_locked(void) {
void RAND_cleanup(void) {
struct rand_buffer *cur;
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ CRYPTO_STATIC_MUTEX_lock_write(&global_lock);
while ((cur = list_head)) {
list_head = cur->next;
OPENSSL_free(cur);
@@ -110,7 +115,7 @@ void RAND_cleanup(void) {
}
urandom_fd = -2;
list_head = NULL;
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ CRYPTO_STATIC_MUTEX_unlock(&global_lock);
}
/* read_full reads exactly |len| bytes from |fd| into |out| and returns 1. In
@@ -133,36 +138,34 @@ static char read_full(int fd, uint8_t *out, size_t len) {
return 1;
}
-/* urandom_rand_pseudo_bytes puts |num| random bytes into |out|. It returns
- * one on success and zero otherwise. */
-int RAND_bytes(uint8_t *out, size_t requested) {
+/* CRYPTO_sysrand puts |num| random bytes into |out|. */
+void CRYPTO_sysrand(uint8_t *out, size_t requested) {
int fd;
struct rand_buffer *buf;
size_t todo;
pid_t pid, ppid;
if (requested == 0) {
- return 1;
+ return;
}
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ CRYPTO_STATIC_MUTEX_lock_write(&global_lock);
fd = urandom_get_fd_locked();
if (fd < 0) {
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ CRYPTO_STATIC_MUTEX_unlock(&global_lock);
abort();
- return 0;
+ return;
}
/* If buffering is not enabled, or if the request is large, then the
* result comes directly from urandom. */
if (!urandom_buffering || requested > BUF_SIZE / 2) {
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ CRYPTO_STATIC_MUTEX_unlock(&global_lock);
if (!read_full(fd, out, requested)) {
abort();
- return 0;
}
- return 1;
+ return;
}
pid = getpid();
@@ -174,8 +177,8 @@ int RAND_bytes(uint8_t *out, size_t requested) {
rand_bytes_per_buf - buf->used >= requested) {
memcpy(out, &buf->rand[buf->used], requested);
buf->used += requested;
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
- return 1;
+ CRYPTO_STATIC_MUTEX_unlock(&global_lock);
+ return;
}
/* If we don't immediately have enough entropy with the correct
@@ -184,10 +187,14 @@ int RAND_bytes(uint8_t *out, size_t requested) {
if (buf) {
list_head = buf->next;
}
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ CRYPTO_STATIC_MUTEX_unlock(&global_lock);
if (!buf) {
buf = (struct rand_buffer *)OPENSSL_malloc(BUF_SIZE);
+ if (!buf) {
+ abort();
+ return;
+ }
/* The buffer doesn't contain any random bytes yet
* so we mark it as fully used so that it will be
* filled below. */
@@ -204,7 +211,7 @@ int RAND_bytes(uint8_t *out, size_t requested) {
/* We have forked and so cannot use these bytes as they
* may have been used in another process. */
OPENSSL_free(buf);
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ CRYPTO_STATIC_MUTEX_lock_write(&global_lock);
}
while (requested > 0) {
@@ -224,18 +231,17 @@ int RAND_bytes(uint8_t *out, size_t requested) {
if (!read_full(fd, buf->rand, rand_bytes_per_buf)) {
OPENSSL_free(buf);
abort();
- return 0;
+ return;
}
buf->used = 0;
}
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ CRYPTO_STATIC_MUTEX_lock_write(&global_lock);
assert(list_head != buf);
buf->next = list_head;
list_head = buf;
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
- return 1;
+ CRYPTO_STATIC_MUTEX_unlock(&global_lock);
}
#endif /* !OPENSSL_WINDOWS */
diff --git a/src/crypto/rand/windows.c b/src/crypto/rand/windows.c
index e8b2d78..7bfcb1d 100644
--- a/src/crypto/rand/windows.c
+++ b/src/crypto/rand/windows.c
@@ -27,16 +27,18 @@
* "Community Additions" comment on MSDN here:
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
#define SystemFunction036 NTAPI SystemFunction036
-#include <ntsecapi.h>
+#include <NTSecAPI.h>
#undef SystemFunction036
#pragma warning(pop)
+#include "internal.h"
+
void RAND_cleanup(void) {
}
-int RAND_bytes(uint8_t *out, size_t requested) {
+void CRYPTO_sysrand(uint8_t *out, size_t requested) {
while (requested > 0) {
ULONG output_bytes_this_pass = ULONG_MAX;
if (requested < output_bytes_this_pass) {
@@ -48,7 +50,7 @@ int RAND_bytes(uint8_t *out, size_t requested) {
requested -= output_bytes_this_pass;
out += output_bytes_this_pass;
}
- return 1;
+ return;
}
#endif /* OPENSSL_WINDOWS */
diff --git a/src/crypto/rc4/asm/rc4-x86_64.pl b/src/crypto/rc4/asm/rc4-x86_64.pl
index 2c52ac0..db46242 100644
--- a/src/crypto/rc4/asm/rc4-x86_64.pl
+++ b/src/crypto/rc4/asm/rc4-x86_64.pl
@@ -502,32 +502,6 @@ asm_RC4_set_key:
mov %eax,-4($dat)
ret
.size asm_RC4_set_key,.-asm_RC4_set_key
-
-.globl RC4_options
-.type RC4_options,\@abi-omnipotent
-.align 16
-RC4_options:
- lea .Lopts(%rip),%rax
- mov OPENSSL_ia32cap_P(%rip),%rdx
- mov (%rdx),%edx
- bt \$20,%edx
- jc .L8xchar
- bt \$30,%edx
- jnc .Ldone
- add \$25,%rax
- ret
-.L8xchar:
- add \$12,%rax
-.Ldone:
- ret
-.align 64
-.Lopts:
-.asciz "rc4(8x,int)"
-.asciz "rc4(8x,char)"
-.asciz "rc4(16x,int)"
-.asciz "RC4 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
-.align 64
-.size RC4_options,.-RC4_options
___
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
diff --git a/src/crypto/rc4/rc4.c b/src/crypto/rc4/rc4.c
index 00b59c8..2a98fd0 100644
--- a/src/crypto/rc4/rc4.c
+++ b/src/crypto/rc4/rc4.c
@@ -67,8 +67,6 @@
#error "Unknown word size"
#endif
-#define RC4_INT uint32_t
-
/* RC4 as implemented from a posting from
* Newsgroups: sci.crypt
@@ -78,44 +76,14 @@
* Date: Wed, 14 Sep 1994 06:35:31 GMT */
void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
- register RC4_INT *d;
- register RC4_INT x, y, tx, ty;
+ uint32_t *d;
+ uint32_t x, y, tx, ty;
size_t i;
x = key->x;
y = key->y;
d = key->data;
-#if defined(RC4_CHUNK)
-/* The original reason for implementing this(*) was the fact that
- * pre-21164a Alpha CPUs don't have byte load/store instructions
- * and e.g. a byte store has to be done with 64-bit load, shift,
- * and, or and finally 64-bit store. Peaking data and operating
- * at natural word size made it possible to reduce amount of
- * instructions as well as to perform early read-ahead without
- * suffering from RAW (read-after-write) hazard. This resulted
- * in ~40%(**) performance improvement on 21064 box with gcc.
- * But it's not only Alpha users who win here:-) Thanks to the
- * early-n-wide read-ahead this implementation also exhibits
- * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending
- * on sizeof(RC4_INT)).
- *
- * (*) "this" means code which recognizes the case when input
- * and output pointers appear to be aligned at natural CPU
- * word boundary
- * (**) i.e. according to 'apps/openssl speed rc4' benchmark,
- * crypto/rc4/rc4speed.c exhibits almost 70% speed-up...
- *
- * Cavets.
- *
- * - RC4_CHUNK="unsigned long long" should be a #1 choice for
- * UltraSPARC. Unfortunately gcc generates very slow code
- * (2.5-3 times slower than one generated by Sun's WorkShop
- * C) and therefore gcc (at least 2.95 and earlier) should
- * always be told that RC4_CHUNK="unsigned long".
- *
- * <appro@fy.chalmers.se> */
-
#define RC4_STEP \
(x = (x + 1) & 0xff, tx = d[x], y = (tx + y) & 0xff, ty = d[y], d[y] = tx, \
d[x] = ty, (RC4_CHUNK)d[(tx + ty) & 0xff])
@@ -255,7 +223,6 @@ void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
return;
}
}
-#endif
#define LOOP(in, out) \
x = ((x + 1) & 0xff); \
tx = d[x]; \
@@ -285,34 +252,42 @@ void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
in += 8;
out += 8;
#endif
- if (--i == 0)
+ if (--i == 0) {
break;
+ }
}
}
i = len & 0x07;
if (i) {
for (;;) {
RC4_LOOP(in, out, 0);
- if (--i == 0)
+ if (--i == 0) {
break;
+ }
RC4_LOOP(in, out, 1);
- if (--i == 0)
+ if (--i == 0) {
break;
+ }
RC4_LOOP(in, out, 2);
- if (--i == 0)
+ if (--i == 0) {
break;
+ }
RC4_LOOP(in, out, 3);
- if (--i == 0)
+ if (--i == 0) {
break;
+ }
RC4_LOOP(in, out, 4);
- if (--i == 0)
+ if (--i == 0) {
break;
+ }
RC4_LOOP(in, out, 5);
- if (--i == 0)
+ if (--i == 0) {
break;
+ }
RC4_LOOP(in, out, 6);
- if (--i == 0)
+ if (--i == 0) {
break;
+ }
}
}
key->x = x;
@@ -320,9 +295,9 @@ void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
}
void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) {
- register RC4_INT tmp;
- register int id1, id2;
- register RC4_INT *d;
+ uint32_t tmp;
+ int id1, id2;
+ uint32_t *d;
unsigned int i;
d = &rc4key->data[0];
diff --git a/src/crypto/rsa/CMakeLists.txt b/src/crypto/rsa/CMakeLists.txt
index b3d8fa4..c438e1d 100644
--- a/src/crypto/rsa/CMakeLists.txt
+++ b/src/crypto/rsa/CMakeLists.txt
@@ -10,7 +10,6 @@ add_library(
blinding.c
padding.c
rsa_asn1.c
- rsa_error.c
)
add_executable(
diff --git a/src/crypto/rsa/blinding.c b/src/crypto/rsa/blinding.c
index 06f87a7..245142b 100644
--- a/src/crypto/rsa/blinding.c
+++ b/src/crypto/rsa/blinding.c
@@ -113,6 +113,7 @@
#include <openssl/bn.h>
#include <openssl/mem.h>
#include <openssl/err.h>
+#include <openssl/thread.h>
#include "internal.h"
@@ -124,7 +125,6 @@ struct bn_blinding_st {
BIGNUM *Ai;
BIGNUM *e;
BIGNUM *mod; /* just a reference */
- CRYPTO_THREADID tid;
int counter;
unsigned long flags;
BN_MONT_CTX *m_ctx;
@@ -167,13 +167,10 @@ BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) {
* to indicate that this is never-used fresh blinding
* that does not need updating before first use. */
ret->counter = -1;
- CRYPTO_THREADID_current(&ret->tid);
return ret;
err:
- if (ret != NULL) {
- BN_BLINDING_free(ret);
- }
+ BN_BLINDING_free(ret);
return NULL;
}
@@ -182,14 +179,10 @@ void BN_BLINDING_free(BN_BLINDING *r) {
return;
}
- if (r->A != NULL)
- BN_free(r->A);
- if (r->Ai != NULL)
- BN_free(r->Ai);
- if (r->e != NULL)
- BN_free(r->e);
- if (r->mod != NULL)
- BN_free(r->mod);
+ BN_free(r->A);
+ BN_free(r->Ai);
+ BN_free(r->e);
+ BN_free(r->mod);
OPENSSL_free(r);
}
@@ -282,8 +275,6 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
return ret;
}
-CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *b) { return &b->tid; }
-
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b) { return b->flags; }
void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags) {
@@ -316,9 +307,7 @@ BN_BLINDING *BN_BLINDING_create_param(
}
if (e != NULL) {
- if (ret->e != NULL) {
- BN_free(ret->e);
- }
+ BN_free(ret->e);
ret->e = BN_dup(e);
}
if (ret->e == NULL) {
@@ -367,7 +356,7 @@ BN_BLINDING *BN_BLINDING_create_param(
return ret;
err:
- if (b == NULL && ret != NULL) {
+ if (b == NULL) {
BN_BLINDING_free(ret);
ret = NULL;
}
@@ -413,6 +402,7 @@ BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx) {
BIGNUM *e, *n;
BN_CTX *ctx;
BN_BLINDING *ret = NULL;
+ BN_MONT_CTX *mont_ctx = NULL;
if (in_ctx == NULL) {
ctx = BN_CTX_new();
@@ -444,19 +434,19 @@ BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx) {
BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n,
- ctx)) {
+ mont_ctx =
+ BN_MONT_CTX_set_locked(&rsa->_method_mod_n, &rsa->lock, rsa->n, ctx);
+ if (mont_ctx == NULL) {
goto err;
}
}
ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp,
- rsa->_method_mod_n);
+ mont_ctx);
if (ret == NULL) {
OPENSSL_PUT_ERROR(RSA, rsa_setup_blinding, ERR_R_BN_LIB);
goto err;
}
- CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret));
err:
BN_CTX_end(ctx);
diff --git a/src/crypto/rsa/internal.h b/src/crypto/rsa/internal.h
index 3dd4f04..d15f2a5 100644
--- a/src/crypto/rsa/internal.h
+++ b/src/crypto/rsa/internal.h
@@ -60,7 +60,7 @@
#include <openssl/base.h>
#include <openssl/asn1.h>
-#include <openssl/thread.h>
+
#if defined(__cplusplus)
extern "C" {
@@ -81,7 +81,6 @@ int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
-CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *);
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
BN_BLINDING *BN_BLINDING_create_param(
diff --git a/src/crypto/rsa/padding.c b/src/crypto/rsa/padding.c
index 66fdf13..0a725f1 100644
--- a/src/crypto/rsa/padding.c
+++ b/src/crypto/rsa/padding.c
@@ -443,9 +443,7 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
ret = 1;
out:
- if (dbmask != NULL) {
- OPENSSL_free(dbmask);
- }
+ OPENSSL_free(dbmask);
return ret;
}
@@ -544,9 +542,7 @@ decoding_err:
OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_OAEP_mgf1,
RSA_R_OAEP_DECODING_ERROR);
err:
- if (db != NULL) {
- OPENSSL_free(db);
- }
+ OPENSSL_free(db);
return -1;
}
@@ -620,8 +616,9 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
if (MSBits) {
DB[0] &= 0xFF >> (8 - MSBits);
}
- for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++)
+ for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) {
;
+ }
if (DB[i++] != 0x1) {
OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1,
RSA_R_SLEN_RECOVERY_FAILED);
@@ -652,9 +649,7 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
}
err:
- if (DB) {
- OPENSSL_free(DB);
- }
+ OPENSSL_free(DB);
EVP_MD_CTX_cleanup(&ctx);
return ret;
@@ -771,9 +766,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
ret = 1;
err:
- if (salt) {
- OPENSSL_free(salt);
- }
+ OPENSSL_free(salt);
return ret;
}
diff --git a/src/crypto/rsa/rsa.c b/src/crypto/rsa/rsa.c
index 66002cc..5cc48ed 100644
--- a/src/crypto/rsa/rsa.c
+++ b/src/crypto/rsa/rsa.c
@@ -64,12 +64,16 @@
#include <openssl/ex_data.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
+#include <openssl/thread.h>
#include "internal.h"
+#include "../internal.h"
extern const RSA_METHOD RSA_default_method;
+static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
+
RSA *RSA_new(void) { return RSA_new_method(NULL); }
RSA *RSA_new_method(const ENGINE *engine) {
@@ -92,15 +96,16 @@ RSA *RSA_new_method(const ENGINE *engine) {
rsa->references = 1;
rsa->flags = rsa->meth->flags;
+ CRYPTO_MUTEX_init(&rsa->lock);
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, rsa, &rsa->ex_data)) {
+ if (!CRYPTO_new_ex_data(&g_ex_data_class, rsa, &rsa->ex_data)) {
METHOD_unref(rsa->meth);
OPENSSL_free(rsa);
return NULL;
}
if (rsa->meth->init && !rsa->meth->init(rsa)) {
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, rsa, &rsa->ex_data);
+ CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data);
METHOD_unref(rsa->meth);
OPENSSL_free(rsa);
return NULL;
@@ -125,31 +130,22 @@ void RSA_free(RSA *rsa) {
}
METHOD_unref(rsa->meth);
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, rsa, &rsa->ex_data);
-
- if (rsa->n != NULL)
- BN_clear_free(rsa->n);
- if (rsa->e != NULL)
- BN_clear_free(rsa->e);
- if (rsa->d != NULL)
- BN_clear_free(rsa->d);
- if (rsa->p != NULL)
- BN_clear_free(rsa->p);
- if (rsa->q != NULL)
- BN_clear_free(rsa->q);
- if (rsa->dmp1 != NULL)
- BN_clear_free(rsa->dmp1);
- if (rsa->dmq1 != NULL)
- BN_clear_free(rsa->dmq1);
- if (rsa->iqmp != NULL)
- BN_clear_free(rsa->iqmp);
+ CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data);
+
+ BN_clear_free(rsa->n);
+ BN_clear_free(rsa->e);
+ BN_clear_free(rsa->d);
+ BN_clear_free(rsa->p);
+ BN_clear_free(rsa->q);
+ BN_clear_free(rsa->dmp1);
+ BN_clear_free(rsa->dmq1);
+ BN_clear_free(rsa->iqmp);
for (u = 0; u < rsa->num_blindings; u++) {
BN_BLINDING_free(rsa->blindings[u]);
}
- if (rsa->blindings != NULL)
- OPENSSL_free(rsa->blindings);
- if (rsa->blindings_inuse != NULL)
- OPENSSL_free(rsa->blindings_inuse);
+ OPENSSL_free(rsa->blindings);
+ OPENSSL_free(rsa->blindings_inuse);
+ CRYPTO_MUTEX_cleanup(&rsa->lock);
OPENSSL_free(rsa);
}
@@ -271,8 +267,12 @@ int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) {
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,
- dup_func, free_func);
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
+ dup_func, free_func)) {
+ return -1;
+ }
+ return index;
}
int RSA_set_ex_data(RSA *d, int idx, void *arg) {
@@ -338,12 +338,6 @@ static const struct pkcs1_sig_prefix kPKCS1SigPrefixes[] = {
0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
},
{
- NID_ripemd160,
- 14,
- {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31,
- 0x04, 0x14},
- },
- {
NID_undef, 0, {0},
},
};
@@ -357,15 +351,11 @@ static int pkcs1_prefixed_msg(uint8_t **out_msg, size_t *out_msg_len,
int *is_alloced, int hash_nid, const uint8_t *msg,
size_t msg_len) {
unsigned i;
- const uint8_t* prefix = NULL;
- unsigned prefix_len;
- uint8_t *signed_msg;
- unsigned signed_msg_len;
if (hash_nid == NID_md5_sha1) {
/* Special case: SSL signature, just check the length. */
if (msg_len != SSL_SIG_LENGTH) {
- OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_INVALID_MESSAGE_LENGTH);
+ OPENSSL_PUT_ERROR(RSA, pkcs1_prefixed_msg, RSA_R_INVALID_MESSAGE_LENGTH);
return 0;
}
@@ -377,38 +367,39 @@ static int pkcs1_prefixed_msg(uint8_t **out_msg, size_t *out_msg_len,
for (i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) {
const struct pkcs1_sig_prefix *sig_prefix = &kPKCS1SigPrefixes[i];
- if (sig_prefix->nid == hash_nid) {
- prefix = sig_prefix->bytes;
- prefix_len = sig_prefix->len;
- break;
+ if (sig_prefix->nid != hash_nid) {
+ continue;
}
- }
- if (prefix == NULL) {
- OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE);
- return 0;
- }
+ const uint8_t* prefix = sig_prefix->bytes;
+ unsigned prefix_len = sig_prefix->len;
+ unsigned signed_msg_len;
+ uint8_t *signed_msg;
- signed_msg_len = prefix_len + msg_len;
- if (signed_msg_len < prefix_len) {
- OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_TOO_LONG);
- return 0;
- }
+ signed_msg_len = prefix_len + msg_len;
+ if (signed_msg_len < prefix_len) {
+ OPENSSL_PUT_ERROR(RSA, pkcs1_prefixed_msg, RSA_R_TOO_LONG);
+ return 0;
+ }
- signed_msg = OPENSSL_malloc(signed_msg_len);
- if (!signed_msg) {
- OPENSSL_PUT_ERROR(RSA, RSA_sign, ERR_R_MALLOC_FAILURE);
- return 0;
- }
+ signed_msg = OPENSSL_malloc(signed_msg_len);
+ if (!signed_msg) {
+ OPENSSL_PUT_ERROR(RSA, pkcs1_prefixed_msg, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
- memcpy(signed_msg, prefix, prefix_len);
- memcpy(signed_msg + prefix_len, msg, msg_len);
+ memcpy(signed_msg, prefix, prefix_len);
+ memcpy(signed_msg + prefix_len, msg, msg_len);
- *out_msg = signed_msg;
- *out_msg_len = signed_msg_len;
- *is_alloced = 1;
+ *out_msg = signed_msg;
+ *out_msg_len = signed_msg_len;
+ *is_alloced = 1;
- return 1;
+ return 1;
+ }
+
+ OPENSSL_PUT_ERROR(RSA, pkcs1_prefixed_msg, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
}
int RSA_sign(int hash_nid, const uint8_t *in, unsigned in_len, uint8_t *out,
@@ -495,9 +486,7 @@ int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
ret = 1;
out:
- if (buf != NULL) {
- OPENSSL_free(buf);
- }
+ OPENSSL_free(buf);
if (signed_msg_is_alloced) {
OPENSSL_free(signed_msg);
}
@@ -505,10 +494,6 @@ out:
}
static void bn_free_and_null(BIGNUM **bn) {
- if (*bn == NULL) {
- return;
- }
-
BN_free(*bn);
*bn = NULL;
}
diff --git a/src/crypto/rsa/rsa_error.c b/src/crypto/rsa/rsa_error.c
deleted file mode 100644
index 3c8ebe4..0000000
--- a/src/crypto/rsa/rsa_error.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/* 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/rsa.h>
-
-const ERR_STRING_DATA RSA_error_string_data[] = {
- {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_convert_ex, 0), "BN_BLINDING_convert_ex"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_create_param, 0), "BN_BLINDING_create_param"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_invert_ex, 0), "BN_BLINDING_invert_ex"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_new, 0), "BN_BLINDING_new"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_update, 0), "BN_BLINDING_update"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_check_key, 0), "RSA_check_key"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_new_method, 0), "RSA_new_method"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_PKCS1_OAEP_mgf1, 0), "RSA_padding_add_PKCS1_OAEP_mgf1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_PKCS1_PSS_mgf1, 0), "RSA_padding_add_PKCS1_PSS_mgf1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_PKCS1_type_1, 0), "RSA_padding_add_PKCS1_type_1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_PKCS1_type_2, 0), "RSA_padding_add_PKCS1_type_2"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_SSLv23, 0), "RSA_padding_add_SSLv23"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_none, 0), "RSA_padding_add_none"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_PKCS1_OAEP_mgf1, 0), "RSA_padding_check_PKCS1_OAEP_mgf1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_PKCS1_type_1, 0), "RSA_padding_check_PKCS1_type_1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_PKCS1_type_2, 0), "RSA_padding_check_PKCS1_type_2"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_SSLv23, 0), "RSA_padding_check_SSLv23"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_none, 0), "RSA_padding_check_none"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_recover_crt_params, 0), "RSA_recover_crt_params"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_sign, 0), "RSA_sign"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_verify, 0), "RSA_verify"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_verify_PKCS1_PSS_mgf1, 0), "RSA_verify_PKCS1_PSS_mgf1"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_decrypt, 0), "decrypt"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_encrypt, 0), "encrypt"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_keygen, 0), "keygen"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_pkcs1_prefixed_msg, 0), "pkcs1_prefixed_msg"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_private_transform, 0), "private_transform"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_rsa_setup_blinding, 0), "rsa_setup_blinding"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_sign_raw, 0), "sign_raw"},
- {ERR_PACK(ERR_LIB_RSA, RSA_F_verify_raw, 0), "verify_raw"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_E_VALUE), "BAD_E_VALUE"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_FIXED_HEADER_DECRYPT), "BAD_FIXED_HEADER_DECRYPT"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_PAD_BYTE_COUNT), "BAD_PAD_BYTE_COUNT"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_RSA_PARAMETERS), "BAD_RSA_PARAMETERS"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_SIGNATURE), "BAD_SIGNATURE"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BLOCK_TYPE_IS_NOT_01), "BLOCK_TYPE_IS_NOT_01"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BLOCK_TYPE_IS_NOT_02), "BLOCK_TYPE_IS_NOT_02"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BN_NOT_INITIALIZED), "BN_NOT_INITIALIZED"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_CRT_PARAMS_ALREADY_GIVEN), "CRT_PARAMS_ALREADY_GIVEN"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_CRT_VALUES_INCORRECT), "CRT_VALUES_INCORRECT"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN), "DATA_LEN_NOT_EQUAL_TO_MOD_LEN"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE), "DATA_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE), "DATA_TOO_LARGE_FOR_KEY_SIZE"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE_FOR_MODULUS), "DATA_TOO_LARGE_FOR_MODULUS"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_SMALL), "DATA_TOO_SMALL"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE), "DATA_TOO_SMALL_FOR_KEY_SIZE"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY), "DIGEST_TOO_BIG_FOR_RSA_KEY"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_D_E_NOT_CONGRUENT_TO_1), "D_E_NOT_CONGRUENT_TO_1"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_EMPTY_PUBLIC_KEY), "EMPTY_PUBLIC_KEY"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_FIRST_OCTET_INVALID), "FIRST_OCTET_INVALID"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES), "INCONSISTENT_SET_OF_CRT_VALUES"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INTERNAL_ERROR), "INTERNAL_ERROR"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MESSAGE_LENGTH), "INVALID_MESSAGE_LENGTH"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_KEY_SIZE_TOO_SMALL), "KEY_SIZE_TOO_SMALL"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_LAST_OCTET_INVALID), "LAST_OCTET_INVALID"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MODULUS_TOO_LARGE), "MODULUS_TOO_LARGE"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NO_PUBLIC_EXPONENT), "NO_PUBLIC_EXPONENT"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NULL_BEFORE_BLOCK_MISSING), "NULL_BEFORE_BLOCK_MISSING"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_NOT_EQUAL_P_Q), "N_NOT_EQUAL_P_Q"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OAEP_DECODING_ERROR), "OAEP_DECODING_ERROR"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_ONLY_ONE_OF_P_Q_GIVEN), "ONLY_ONE_OF_P_Q_GIVEN"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OUTPUT_BUFFER_TOO_SMALL), "OUTPUT_BUFFER_TOO_SMALL"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PADDING_CHECK_FAILED), "PADDING_CHECK_FAILED"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PKCS_DECODING_ERROR), "PKCS_DECODING_ERROR"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_CHECK_FAILED), "SLEN_CHECK_FAILED"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_RECOVERY_FAILED), "SLEN_RECOVERY_FAILED"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SSLV3_ROLLBACK_ATTACK), "SSLV3_ROLLBACK_ATTACK"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_TOO_LONG), "TOO_LONG"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_TOO_MANY_ITERATIONS), "TOO_MANY_ITERATIONS"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_ALGORITHM_TYPE), "UNKNOWN_ALGORITHM_TYPE"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_PADDING_TYPE), "UNKNOWN_PADDING_TYPE"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_VALUE_MISSING), "VALUE_MISSING"},
- {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_WRONG_SIGNATURE_LENGTH), "WRONG_SIGNATURE_LENGTH"},
- {0, NULL},
-};
diff --git a/src/crypto/rsa/rsa_impl.c b/src/crypto/rsa/rsa_impl.c
index d950d50..e14f0f5 100644
--- a/src/crypto/rsa/rsa_impl.c
+++ b/src/crypto/rsa/rsa_impl.c
@@ -61,8 +61,10 @@
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
+#include <openssl/thread.h>
#include "internal.h"
+#include "../internal.h"
#define OPENSSL_RSA_MAX_MODULUS_BITS 16384
@@ -72,15 +74,9 @@
static int finish(RSA *rsa) {
- if (rsa->_method_mod_n != NULL) {
- BN_MONT_CTX_free(rsa->_method_mod_n);
- }
- if (rsa->_method_mod_p != NULL) {
- BN_MONT_CTX_free(rsa->_method_mod_p);
- }
- if (rsa->_method_mod_q != NULL) {
- BN_MONT_CTX_free(rsa->_method_mod_q);
- }
+ BN_MONT_CTX_free(rsa->_method_mod_n);
+ BN_MONT_CTX_free(rsa->_method_mod_p);
+ BN_MONT_CTX_free(rsa->_method_mod_q);
return 1;
}
@@ -165,13 +161,14 @@ static int encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n,
- ctx)) {
+ if (BN_MONT_CTX_set_locked(&rsa->_method_mod_n, &rsa->lock, rsa->n, ctx) ==
+ NULL) {
goto err;
}
}
- if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->_method_mod_n)) {
+ if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx,
+ rsa->_method_mod_n)) {
goto err;
}
@@ -217,37 +214,20 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
uint8_t *new_blindings_inuse;
char overflow = 0;
- CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
- if (rsa->num_blindings > 0) {
- unsigned i, starting_index;
- CRYPTO_THREADID threadid;
-
- /* We start searching the array at a value based on the
- * threadid in order to try avoid bouncing the BN_BLINDING
- * values around different threads. It's harmless if
- * threadid.val is always set to zero. */
- CRYPTO_THREADID_current(&threadid);
- starting_index = threadid.val % rsa->num_blindings;
-
- for (i = starting_index;;) {
- if (rsa->blindings_inuse[i] == 0) {
- rsa->blindings_inuse[i] = 1;
- ret = rsa->blindings[i];
- *index_used = i;
- break;
- }
- i++;
- if (i == rsa->num_blindings) {
- i = 0;
- }
- if (i == starting_index) {
- break;
- }
+ CRYPTO_MUTEX_lock_write(&rsa->lock);
+
+ unsigned i;
+ for (i = 0; i < rsa->num_blindings; i++) {
+ if (rsa->blindings_inuse[i] == 0) {
+ rsa->blindings_inuse[i] = 1;
+ ret = rsa->blindings[i];
+ *index_used = i;
+ break;
}
}
if (ret != NULL) {
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_MUTEX_unlock(&rsa->lock);
return ret;
}
@@ -256,7 +236,7 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
/* We didn't find a free BN_BLINDING to use so increase the length of
* the arrays by one and use the newly created element. */
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_MUTEX_unlock(&rsa->lock);
ret = rsa_setup_blinding(rsa, ctx);
if (ret == NULL) {
return NULL;
@@ -269,7 +249,7 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
return ret;
}
- CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_MUTEX_lock_write(&rsa->lock);
new_blindings =
OPENSSL_malloc(sizeof(BN_BLINDING *) * (rsa->num_blindings + 1));
@@ -288,24 +268,20 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
new_blindings_inuse[rsa->num_blindings] = 1;
*index_used = rsa->num_blindings;
- if (rsa->blindings != NULL) {
- OPENSSL_free(rsa->blindings);
- }
+ OPENSSL_free(rsa->blindings);
rsa->blindings = new_blindings;
- if (rsa->blindings_inuse != NULL) {
- OPENSSL_free(rsa->blindings_inuse);
- }
+ OPENSSL_free(rsa->blindings_inuse);
rsa->blindings_inuse = new_blindings_inuse;
rsa->num_blindings++;
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_MUTEX_unlock(&rsa->lock);
return ret;
err2:
OPENSSL_free(new_blindings);
err1:
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_MUTEX_unlock(&rsa->lock);
BN_BLINDING_free(ret);
return NULL;
}
@@ -320,9 +296,9 @@ static void rsa_blinding_release(RSA *rsa, BN_BLINDING *blinding,
return;
}
- CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_MUTEX_lock_write(&rsa->lock);
rsa->blindings_inuse[blinding_index] = 0;
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_MUTEX_unlock(&rsa->lock);
}
/* signing */
@@ -360,8 +336,7 @@ static int sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
}
if (!RSA_private_transform(rsa, out, buf, rsa_size)) {
- OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
- goto err;
+ goto err;
}
*out_len = rsa_size;
@@ -400,7 +375,6 @@ static int decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
}
if (!RSA_private_transform(rsa, buf, in, rsa_size)) {
- OPENSSL_PUT_ERROR(RSA, decrypt, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -497,8 +471,8 @@ static int verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n,
- ctx)) {
+ if (BN_MONT_CTX_set_locked(&rsa->_method_mod_n, &rsa->lock, rsa->n, ctx) ==
+ NULL) {
goto err;
}
}
@@ -601,8 +575,8 @@ static int private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n,
- ctx)) {
+ if (BN_MONT_CTX_set_locked(&rsa->_method_mod_n, &rsa->lock, rsa->n,
+ ctx) == NULL) {
goto err;
}
}
@@ -663,18 +637,20 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p, CRYPTO_LOCK_RSA, p, ctx)) {
+ if (BN_MONT_CTX_set_locked(&rsa->_method_mod_p, &rsa->lock, p, ctx) ==
+ NULL) {
goto err;
}
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_q, CRYPTO_LOCK_RSA, q, ctx)) {
+ if (BN_MONT_CTX_set_locked(&rsa->_method_mod_q, &rsa->lock, q, ctx) ==
+ NULL) {
goto err;
}
}
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n,
- ctx)) {
+ if (BN_MONT_CTX_set_locked(&rsa->_method_mod_n, &rsa->lock, rsa->n, ctx) ==
+ NULL) {
goto err;
}
}
@@ -814,65 +790,79 @@ static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
bitsq = bits - bitsp;
/* We need the RSA components non-NULL */
- if (!rsa->n && ((rsa->n = BN_new()) == NULL))
+ if (!rsa->n && ((rsa->n = BN_new()) == NULL)) {
goto err;
- if (!rsa->d && ((rsa->d = BN_new()) == NULL))
+ }
+ if (!rsa->d && ((rsa->d = BN_new()) == NULL)) {
goto err;
- if (!rsa->e && ((rsa->e = BN_new()) == NULL))
+ }
+ if (!rsa->e && ((rsa->e = BN_new()) == NULL)) {
goto err;
- if (!rsa->p && ((rsa->p = BN_new()) == NULL))
+ }
+ if (!rsa->p && ((rsa->p = BN_new()) == NULL)) {
goto err;
- if (!rsa->q && ((rsa->q = BN_new()) == NULL))
+ }
+ if (!rsa->q && ((rsa->q = BN_new()) == NULL)) {
goto err;
- if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL))
+ }
+ if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL)) {
goto err;
- if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL))
+ }
+ if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL)) {
goto err;
- if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL))
+ }
+ if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL)) {
goto err;
+ }
BN_copy(rsa->e, e_value);
/* generate p and q */
for (;;) {
- if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb))
- goto err;
- if (!BN_sub(r2, rsa->p, BN_value_one()))
- goto err;
- if (!BN_gcd(r1, r2, rsa->e, ctx))
+ if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb) ||
+ !BN_sub(r2, rsa->p, BN_value_one()) ||
+ !BN_gcd(r1, r2, rsa->e, ctx)) {
goto err;
- if (BN_is_one(r1))
+ }
+ if (BN_is_one(r1)) {
break;
- if (!BN_GENCB_call(cb, 2, n++))
+ }
+ if (!BN_GENCB_call(cb, 2, n++)) {
goto err;
+ }
}
- if (!BN_GENCB_call(cb, 3, 0))
+ if (!BN_GENCB_call(cb, 3, 0)) {
goto err;
+ }
for (;;) {
/* When generating ridiculously small keys, we can get stuck
* continually regenerating the same prime values. Check for
* this and bail if it happens 3 times. */
unsigned int degenerate = 0;
do {
- if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, cb))
+ if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, cb)) {
goto err;
+ }
} while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3));
if (degenerate == 3) {
ok = 0; /* we set our own err */
OPENSSL_PUT_ERROR(RSA, keygen, RSA_R_KEY_SIZE_TOO_SMALL);
goto err;
}
- if (!BN_sub(r2, rsa->q, BN_value_one()))
- goto err;
- if (!BN_gcd(r1, r2, rsa->e, ctx))
+ if (!BN_sub(r2, rsa->q, BN_value_one()) ||
+ !BN_gcd(r1, r2, rsa->e, ctx)) {
goto err;
- if (BN_is_one(r1))
+ }
+ if (BN_is_one(r1)) {
break;
- if (!BN_GENCB_call(cb, 2, n++))
+ }
+ if (!BN_GENCB_call(cb, 2, n++)) {
goto err;
+ }
}
- if (!BN_GENCB_call(cb, 3, 1))
+ if (!BN_GENCB_call(cb, 3, 1)) {
goto err;
+ }
if (BN_cmp(rsa->p, rsa->q) < 0) {
tmp = rsa->p;
rsa->p = rsa->q;
@@ -880,39 +870,47 @@ static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
}
/* calculate n */
- if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
+ if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx)) {
goto err;
+ }
/* calculate d */
- if (!BN_sub(r1, rsa->p, BN_value_one()))
+ if (!BN_sub(r1, rsa->p, BN_value_one())) {
goto err; /* p-1 */
- if (!BN_sub(r2, rsa->q, BN_value_one()))
+ }
+ if (!BN_sub(r2, rsa->q, BN_value_one())) {
goto err; /* q-1 */
- if (!BN_mul(r0, r1, r2, ctx))
+ }
+ if (!BN_mul(r0, r1, r2, ctx)) {
goto err; /* (p-1)(q-1) */
+ }
pr0 = &local_r0;
BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
- if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx))
+ if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
goto err; /* d */
+ }
/* set up d for correct BN_FLG_CONSTTIME flag */
d = &local_d;
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
/* calculate d mod (p-1) */
- if (!BN_mod(rsa->dmp1, d, r1, ctx))
+ if (!BN_mod(rsa->dmp1, d, r1, ctx)) {
goto err;
+ }
/* calculate d mod (q-1) */
- if (!BN_mod(rsa->dmq1, d, r2, ctx))
+ if (!BN_mod(rsa->dmq1, d, r2, ctx)) {
goto err;
+ }
/* calculate inverse of q mod p */
p = &local_p;
BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
- if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx))
+ if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) {
goto err;
+ }
ok = 1;
diff --git a/src/crypto/rsa/rsa_test.c b/src/crypto/rsa/rsa_test.c
index 75489e0..318cf3f 100644
--- a/src/crypto/rsa/rsa_test.c
+++ b/src/crypto/rsa/rsa_test.c
@@ -56,9 +56,9 @@
#include <openssl/rsa.h>
+#include <stdlib.h>
#include <string.h>
-#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
@@ -249,13 +249,13 @@ static int test_bad_key(void) {
if (!RSA_generate_key_ex(key, 512, &e, NULL)) {
fprintf(stderr, "RSA_generate_key_ex failed.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
return 0;
}
if (!BN_add(key->p, key->p, BN_value_one())) {
fprintf(stderr, "BN error.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
return 0;
}
@@ -292,19 +292,21 @@ static int test_only_d_given(void) {
if (!RSA_check_key(key)) {
fprintf(stderr, "RSA_check_key failed with only d given.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
goto err;
}
- if (!RSA_sign(NID_md5, kDummyHash, sizeof(kDummyHash), buf, &buf_len, key)) {
+ if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
+ key)) {
fprintf(stderr, "RSA_sign failed with only d given.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
goto err;
}
- if (!RSA_verify(NID_md5, kDummyHash, sizeof(kDummyHash), buf, buf_len, key)) {
+ if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len,
+ key)) {
fprintf(stderr, "RSA_verify failed with only d given.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
goto err;
}
@@ -331,13 +333,13 @@ static int test_recover_crt_params(void) {
key1 = RSA_new();
if (!RSA_generate_key_ex(key1, 512, e, NULL)) {
fprintf(stderr, "RSA_generate_key_ex failed.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
return 0;
}
if (!RSA_check_key(key1)) {
fprintf(stderr, "RSA_check_key failed with original key.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
return 0;
}
@@ -349,7 +351,7 @@ static int test_recover_crt_params(void) {
if (!RSA_recover_crt_params(key2)) {
fprintf(stderr, "RSA_recover_crt_params failed.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
return 0;
}
@@ -359,21 +361,21 @@ static int test_recover_crt_params(void) {
if (!RSA_check_key(key2)) {
fprintf(stderr, "RSA_check_key failed with recovered key.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
return 0;
}
- if (!RSA_sign(NID_md5, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
+ if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
key2)) {
fprintf(stderr, "RSA_sign failed with recovered key.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
return 0;
}
- if (!RSA_verify(NID_md5, kDummyHash, sizeof(kDummyHash), buf, buf_len,
+ if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len,
key2)) {
fprintf(stderr, "RSA_verify failed with recovered key.\n");
- BIO_print_errors_fp(stderr);
+ ERR_print_errors_fp(stderr);
return 0;
}
@@ -478,8 +480,9 @@ int main(int argc, char *argv[]) {
int b;
unsigned char saved = ctext[n];
for (b = 0; b < 256; ++b) {
- if (b == saved)
+ if (b == saved) {
continue;
+ }
ctext[n] = b;
num =
RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_OAEP_PADDING);
diff --git a/src/crypto/sha/asm/sha1-586.pl b/src/crypto/sha/asm/sha1-586.pl
index 8377299..4895eb3 100644
--- a/src/crypto/sha/asm/sha1-586.pl
+++ b/src/crypto/sha/asm/sha1-586.pl
@@ -450,7 +450,7 @@ sub sha1msg2 { sha1op38(0xca,@_); }
&sub ("esp",32);
&movdqu ($ABCD,&QWP(0,$ctx));
- &movd ($E,&QWP(16,$ctx));
+ &movd ($E,&DWP(16,$ctx));
&and ("esp",-32);
&movdqa ($BSWAP,&QWP(0x50,$tmp1)); # byte-n-word swap
diff --git a/src/crypto/sha/asm/sha1-armv4-large.pl b/src/crypto/sha/asm/sha1-armv4-large.pl
index 1ffa041..a20d336 100644
--- a/src/crypto/sha/asm/sha1-armv4-large.pl
+++ b/src/crypto/sha/asm/sha1-armv4-large.pl
@@ -60,14 +60,28 @@
# is ~2.5x larger and there are some redundant instructions executed
# when processing last block, improvement is not as big for smallest
# blocks, only ~30%. Snapdragon S4 is a tad faster, 6.4 cycles per
-# byte, which is also >80% faster than integer-only code.
+# byte, which is also >80% faster than integer-only code. Cortex-A15
+# is even faster spending 5.6 cycles per byte outperforming integer-
+# only code by factor of 2.
# May 2014.
#
# Add ARMv8 code path performing at 2.35 cpb on Apple A7.
-while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
$ctx="r0";
$inp="r1";
@@ -178,6 +192,9 @@ sha1_block_data_order:
sub r3,pc,#8 @ sha1_block_data_order
ldr r12,.LOPENSSL_armcap
ldr r12,[r3,r12] @ OPENSSL_armcap_P
+#ifdef __APPLE__
+ ldr r12,[r12]
+#endif
tst r12,#ARMV8_SHA1
bne .LARMv8
tst r12,#ARMV7_NEON
diff --git a/src/crypto/sha/asm/sha1-armv8.pl b/src/crypto/sha/asm/sha1-armv8.pl
index deb1238..a8c08c2 100644
--- a/src/crypto/sha/asm/sha1-armv8.pl
+++ b/src/crypto/sha/asm/sha1-armv8.pl
@@ -14,13 +14,25 @@
#
# hardware-assisted software(*)
# Apple A7 2.31 4.13 (+14%)
-# Cortex-A53 2.19 8.73 (+108%)
+# Cortex-A53 2.24 8.03 (+97%)
# Cortex-A57 2.35 7.88 (+74%)
+# Denver 2.13 3.97 (+0%)(**)
+# X-Gene 8.80 (+200%)
#
# (*) Software results are presented mostly for reference purposes.
+# (**) Keep in mind that Denver relies on binary translation, which
+# optimizes compiler output at run-time.
$flavour = shift;
-open STDOUT,">".shift;
+$output = shift;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
($ctx,$inp,$num)=("x0","x1","x2");
@Xw=map("w$_",(3..17,19));
@@ -154,6 +166,7 @@ $code.=<<___;
.text
+.extern OPENSSL_armcap_P
.globl sha1_block_data_order
.type sha1_block_data_order,%function
.align 6
diff --git a/src/crypto/sha/asm/sha256-armv4.pl b/src/crypto/sha/asm/sha256-armv4.pl
index 398376e..778c3d9 100644
--- a/src/crypto/sha/asm/sha256-armv4.pl
+++ b/src/crypto/sha/asm/sha256-armv4.pl
@@ -5,6 +5,8 @@
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
+#
+# Permission to use under GPL terms is granted.
# ====================================================================
# SHA256 block procedure for ARMv4. May 2007.
@@ -35,8 +37,20 @@
#
# Add ARMv8 code path performing at 2.0 cpb on Apple A7.
-while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
$ctx="r0"; $t0="r0";
$inp="r1"; $t4="r1";
@@ -71,7 +85,9 @@ $code.=<<___ if ($i<16);
eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]`
add $a,$a,$t2 @ h+=Maj(a,b,c) from the past
eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e)
+# ifndef __ARMEB__
rev $t1,$t1
+# endif
#else
@ ldrb $t1,[$inp,#3] @ $i
add $a,$a,$t2 @ h+=Maj(a,b,c) from the past
@@ -151,10 +167,25 @@ ___
}
$code=<<___;
-#include "arm_arch.h"
+#ifndef __KERNEL__
+# include "arm_arch.h"
+#else
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
+#endif
.text
+#if __ARM_ARCH__<7
.code 32
+#else
+.syntax unified
+# if defined(__thumb2__) && !defined(__APPLE__)
+# define adrl adr
+.thumb
+# else
+.code 32
+# endif
+#endif
.type K256,%object
.align 5
@@ -177,25 +208,33 @@ K256:
.word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
.size K256,.-K256
.word 0 @ terminator
-#if __ARM_MAX_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap:
-.word OPENSSL_armcap_P-sha256_block_data_order
+.word OPENSSL_armcap_P-.Lsha256_block_data_order
#endif
.align 5
.global sha256_block_data_order
.type sha256_block_data_order,%function
sha256_block_data_order:
+.Lsha256_block_data_order:
+#if __ARM_ARCH__<7
sub r3,pc,#8 @ sha256_block_data_order
- add $len,$inp,$len,lsl#6 @ len to point at the end of inp
-#if __ARM_MAX_ARCH__>=7
+#else
+ adr r3,sha256_block_data_order
+#endif
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
ldr r12,[r3,r12] @ OPENSSL_armcap_P
+#ifdef __APPLE__
+ ldr r12,[r12]
+#endif
tst r12,#ARMV8_SHA256
bne .LARMv8
tst r12,#ARMV7_NEON
bne .LNEON
#endif
+ add $len,$inp,$len,lsl#6 @ len to point at the end of inp
stmdb sp!,{$ctx,$inp,$len,r4-r11,lr}
ldmia $ctx,{$A,$B,$C,$D,$E,$F,$G,$H}
sub $Ktbl,r3,#256+32 @ K256
@@ -213,6 +252,9 @@ for($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); }
$code.=".Lrounds_16_xx:\n";
for (;$i<32;$i++) { &BODY_16_XX($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
+#if __ARM_ARCH__>=7
+ ite eq @ Thumb2 thing, sanity check in ARM
+#endif
ldreq $t3,[sp,#16*4] @ pull ctx
bne .Lrounds_16_xx
@@ -429,16 +471,19 @@ $code.=<<___;
.arch armv7-a
.fpu neon
+.global sha256_block_data_order_neon
.type sha256_block_data_order_neon,%function
.align 4
sha256_block_data_order_neon:
.LNEON:
stmdb sp!,{r4-r12,lr}
+ sub $H,sp,#16*4+16
+ adr $Ktbl,K256
+ bic $H,$H,#15 @ align for 128-bit stores
mov $t2,sp
- sub sp,sp,#16*4+16 @ alloca
- sub $Ktbl,r3,#256+32 @ K256
- bic sp,sp,#15 @ align for 128-bit stores
+ mov sp,$H @ alloca
+ add $len,$inp,$len,lsl#6 @ len to point at the end of inp
vld1.8 {@X[0]},[$inp]!
vld1.8 {@X[1]},[$inp]!
@@ -490,11 +535,13 @@ $code.=<<___;
ldr $t0,[sp,#72]
sub $Ktbl,$Ktbl,#256 @ rewind $Ktbl
teq $inp,$t0
+ it eq
subeq $inp,$inp,#64 @ avoid SEGV
vld1.8 {@X[0]},[$inp]! @ load next input block
vld1.8 {@X[1]},[$inp]!
vld1.8 {@X[2]},[$inp]!
vld1.8 {@X[3]},[$inp]!
+ it ne
strne $inp,[sp,#68]
mov $Xfer,sp
___
@@ -526,10 +573,12 @@ $code.=<<___;
str $D,[$t1],#4
stmia $t1,{$E-$H}
+ ittte ne
movne $Xfer,sp
ldrne $t1,[sp,#0]
eorne $t2,$t2,$t2
ldreq sp,[sp,#76] @ restore original sp
+ itt ne
eorne $t3,$B,$C
bne .L_00_48
@@ -548,13 +597,28 @@ my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15));
my $Ktbl="r3";
$code.=<<___;
-#if __ARM_MAX_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
+
+# if defined(__thumb2__) && !defined(__APPLE__)
+# define INST(a,b,c,d) .byte c,d|0xc,a,b
+# else
+# define INST(a,b,c,d) .byte a,b,c,d
+# endif
+
.type sha256_block_data_order_armv8,%function
.align 5
sha256_block_data_order_armv8:
.LARMv8:
vld1.32 {$ABCD,$EFGH},[$ctx]
- sub $Ktbl,r3,#sha256_block_data_order-K256
+# ifdef __APPLE__
+ sub $Ktbl,$Ktbl,#256+32
+# elif defined(__thumb2__)
+ adr $Ktbl,.LARMv8
+ sub $Ktbl,$Ktbl,#.LARMv8-K256
+# else
+ adrl $Ktbl,K256
+# endif
+ add $len,$inp,$len,lsl#6 @ len to point at the end of inp
.Loop_v8:
vld1.8 {@MSG[0]-@MSG[1]},[$inp]!
@@ -607,6 +671,7 @@ $code.=<<___;
vadd.i32 $ABCD,$ABCD,$ABCD_SAVE
vadd.i32 $EFGH,$EFGH,$EFGH_SAVE
+ it ne
bne .Loop_v8
vst1.32 {$ABCD,$EFGH},[$ctx]
@@ -619,12 +684,20 @@ ___
$code.=<<___;
.asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
-#if __ARM_MAX_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.comm OPENSSL_armcap_P,4,4
.hidden OPENSSL_armcap_P
#endif
___
+open SELF,$0;
+while(<SELF>) {
+ next if (/^#!/);
+ last if (!s/^#/@/ and !/^$/);
+ print;
+}
+close SELF;
+
{ my %opcode = (
"sha256h" => 0xf3000c40, "sha256h2" => 0xf3100c40,
"sha256su0" => 0xf3ba03c0, "sha256su1" => 0xf3200c40 );
@@ -639,7 +712,7 @@ ___
# since ARMv7 instructions are always encoded little-endian.
# correct solution is to use .inst directive, but older
# assemblers don't implement it:-(
- sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
+ sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
$word&0xff,($word>>8)&0xff,
($word>>16)&0xff,($word>>24)&0xff,
$mnemonic,$arg;
diff --git a/src/crypto/sha/asm/sha512-armv4.pl b/src/crypto/sha/asm/sha512-armv4.pl
index bfe28c4..2964a39 100644
--- a/src/crypto/sha/asm/sha512-armv4.pl
+++ b/src/crypto/sha/asm/sha512-armv4.pl
@@ -5,6 +5,8 @@
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
+#
+# Permission to use under GPL terms is granted.
# ====================================================================
# SHA512 block procedure for ARMv4. September 2007.
@@ -34,16 +36,9 @@
# terms it's 22.6 cycles per byte, which is disappointing result.
# Technical writers asserted that 3-way S4 pipeline can sustain
# multiple NEON instructions per cycle, but dual NEON issue could
-# not be observed, and for NEON-only sequences IPC(*) was found to
-# be limited by 1:-( 0.33 and 0.66 were measured for sequences with
-# ILPs(*) of 1 and 2 respectively. This in turn means that you can
-# even find yourself striving, as I did here, for achieving IPC
-# adequate to one delivered by Cortex A8 [for reference, it's
-# 0.5 for ILP of 1, and 1 for higher ILPs].
-#
-# (*) ILP, instruction-level parallelism, how many instructions
-# *can* execute at the same time. IPC, instructions per cycle,
-# indicates how many instructions actually execute.
+# not be observed, see http://www.openssl.org/~appro/Snapdragon-S4.html
+# for further details. On side note Cortex-A15 processes one byte in
+# 16 cycles.
# Byte order [in]dependence. =========================================
#
@@ -55,8 +50,20 @@ $hi="HI";
$lo="LO";
# ====================================================================
-while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
-open STDOUT,">$output";
+$flavour = shift;
+if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+ open STDOUT,">$output";
+}
$ctx="r0"; # parameter block
$inp="r1";
@@ -143,6 +150,9 @@ $code.=<<___;
teq $t0,#$magic
ldr $t3,[sp,#$Coff+0] @ c.lo
+#if __ARM_ARCH__>=7
+ it eq @ Thumb2 thing, sanity check in ARM
+#endif
orreq $Ktbl,$Ktbl,#1
@ Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
@ LO lo>>28^hi<<4 ^ hi>>2^lo<<30 ^ hi>>7^lo<<25
@@ -180,7 +190,17 @@ $code.=<<___;
___
}
$code=<<___;
-#include "arm_arch.h"
+#ifndef __KERNEL__
+# include "arm_arch.h"
+# define VFP_ABI_PUSH vstmdb sp!,{d8-d15}
+# define VFP_ABI_POP vldmia sp!,{d8-d15}
+#else
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
+# define VFP_ABI_PUSH
+# define VFP_ABI_POP
+#endif
+
#ifdef __ARMEL__
# define LO 0
# define HI 4
@@ -192,7 +212,18 @@ $code=<<___;
#endif
.text
+#if __ARM_ARCH__<7 || defined(__APPLE__)
.code 32
+#else
+.syntax unified
+# ifdef __thumb2__
+# define adrl adr
+.thumb
+# else
+.code 32
+# endif
+#endif
+
.type K512,%object
.align 5
K512:
@@ -237,9 +268,9 @@ WORD64(0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c)
WORD64(0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a)
WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817)
.size K512,.-K512
-#if __ARM_MAX_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap:
-.word OPENSSL_armcap_P-sha512_block_data_order
+.word OPENSSL_armcap_P-.Lsha512_block_data_order
.skip 32-4
#else
.skip 32
@@ -248,14 +279,22 @@ WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817)
.global sha512_block_data_order
.type sha512_block_data_order,%function
sha512_block_data_order:
+.Lsha512_block_data_order:
+#if __ARM_ARCH__<7
sub r3,pc,#8 @ sha512_block_data_order
- add $len,$inp,$len,lsl#7 @ len to point at the end of inp
-#if __ARM_MAX_ARCH__>=7
+#else
+ adr r3,sha512_block_data_order
+#endif
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
ldr r12,[r3,r12] @ OPENSSL_armcap_P
+#ifdef __APPLE__
+ ldr r12,[r12]
+#endif
tst r12,#1
bne .LNEON
#endif
+ add $len,$inp,$len,lsl#7 @ len to point at the end of inp
stmdb sp!,{r4-r12,lr}
sub $Ktbl,r3,#672 @ K512
sub sp,sp,#9*8
@@ -369,6 +408,9 @@ $code.=<<___;
___
&BODY_00_15(0x17);
$code.=<<___;
+#if __ARM_ARCH__>=7
+ ittt eq @ Thumb2 thing, sanity check in ARM
+#endif
ldreq $t0,[sp,#`$Xoff+8*(16-1)`+0]
ldreq $t1,[sp,#`$Xoff+8*(16-1)`+4]
beq .L16_79
@@ -453,6 +495,7 @@ $code.=<<___;
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
#endif
+.size sha512_block_data_order,.-sha512_block_data_order
___
{
@@ -559,11 +602,15 @@ $code.=<<___;
.arch armv7-a
.fpu neon
+.global sha512_block_data_order_neon
+.type sha512_block_data_order_neon,%function
.align 4
+sha512_block_data_order_neon:
.LNEON:
dmb @ errata #451034 on early Cortex A8
- vstmdb sp!,{d8-d15} @ ABI specification says so
- sub $Ktbl,r3,#672 @ K512
+ add $len,$inp,$len,lsl#7 @ len to point at the end of inp
+ adr $Ktbl,K512
+ VFP_ABI_PUSH
vldmia $ctx,{$A-$H} @ load context
.Loop_neon:
___
@@ -588,16 +635,16 @@ $code.=<<___;
sub $Ktbl,#640 @ rewind K512
bne .Loop_neon
- vldmia sp!,{d8-d15} @ epilogue
+ VFP_ABI_POP
ret @ bx lr
+.size sha512_block_data_order_neon,.-sha512_block_data_order_neon
#endif
___
}
$code.=<<___;
-.size sha512_block_data_order,.-sha512_block_data_order
.asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
-#if __ARM_MAX_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.comm OPENSSL_armcap_P,4,4
.hidden OPENSSL_armcap_P
#endif
@@ -606,5 +653,14 @@ ___
$code =~ s/\`([^\`]*)\`/eval $1/gem;
$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
$code =~ s/\bret\b/bx lr/gm;
+
+open SELF,$0;
+while(<SELF>) {
+ next if (/^#!/);
+ last if (!s/^#/@/ and !/^$/);
+ print;
+}
+close SELF;
+
print $code;
close STDOUT; # enforce flush
diff --git a/src/crypto/sha/asm/sha512-armv8.pl b/src/crypto/sha/asm/sha512-armv8.pl
index 5a9c812..43e7293 100644
--- a/src/crypto/sha/asm/sha512-armv8.pl
+++ b/src/crypto/sha/asm/sha512-armv8.pl
@@ -14,8 +14,10 @@
#
# SHA256-hw SHA256(*) SHA512
# Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**))
-# Cortex-A53 2.38 15.6 (+110%) 10.1 (+190%(***))
+# Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***))
# Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***))
+# Denver 2.01 10.5 (+26%) 6.70 (+8%)
+# X-Gene 20.0 (+100%) 12.8 (+300%(***))
#
# (*) Software SHA256 results are of lesser relevance, presented
# mostly for informational purposes.
@@ -25,12 +27,24 @@
# (***) Super-impressive coefficients over gcc-generated code are
# indication of some compiler "pathology", most notably code
# generated with -mgeneral-regs-only is significanty faster
-# and lags behind assembly only by 50-90%.
+# and the gap is only 40-90%.
$flavour=shift;
+# Unlike most perlasm files, sha512-armv8.pl takes an additional argument to
+# determine which hash function to emit. This differs from upstream OpenSSL so
+# that the script may continue to output to stdout.
+$variant=shift;
$output=shift;
-if ($output =~ /512/) {
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+if ($variant eq "sha512") {
$BITS=512;
$SZ=8;
@Sigma0=(28,34,39);
@@ -39,7 +53,7 @@ if ($output =~ /512/) {
@sigma1=(19,61, 6);
$rounds=80;
$reg_t="x";
-} else {
+} elsif ($variant eq "sha256") {
$BITS=256;
$SZ=4;
@Sigma0=( 2,13,22);
@@ -48,6 +62,8 @@ if ($output =~ /512/) {
@sigma1=(17,19,10);
$rounds=64;
$reg_t="w";
+} else {
+ die "Unknown variant: $variant";
}
$func="sha${BITS}_block_data_order";
@@ -152,6 +168,7 @@ $code.=<<___;
.text
+.extern OPENSSL_armcap_P
.globl $func
.type $func,%function
.align 6
@@ -181,7 +198,7 @@ $code.=<<___;
ldp $E,$F,[$ctx,#4*$SZ]
add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input
ldp $G,$H,[$ctx,#6*$SZ]
- adr $Ktbl,K$BITS
+ adr $Ktbl,.LK$BITS
stp $ctx,$num,[x29,#96]
.Loop:
@@ -231,8 +248,8 @@ $code.=<<___;
.size $func,.-$func
.align 6
-.type K$BITS,%object
-K$BITS:
+.type .LK$BITS,%object
+.LK$BITS:
___
$code.=<<___ if ($SZ==8);
.quad 0x428a2f98d728ae22,0x7137449123ef65cd
@@ -297,7 +314,7 @@ $code.=<<___ if ($SZ==4);
.long 0 //terminator
___
$code.=<<___;
-.size K$BITS,.-K$BITS
+.size .LK$BITS,.-.LK$BITS
.align 3
.LOPENSSL_armcap_P:
.quad OPENSSL_armcap_P-.
@@ -322,7 +339,7 @@ sha256_block_armv8:
add x29,sp,#0
ld1.32 {$ABCD,$EFGH},[$ctx]
- adr $Ktbl,K256
+ adr $Ktbl,.LK256
.Loop_hw:
ld1 {@MSG[0]-@MSG[3]},[$inp],#64
diff --git a/src/crypto/sha/sha1.c b/src/crypto/sha/sha1.c
index 7595bc8..60d09f6 100644
--- a/src/crypto/sha/sha1.c
+++ b/src/crypto/sha/sha1.c
@@ -367,8 +367,9 @@ static void HASH_BLOCK_DATA_ORDER(SHA_CTX *c, const void *p, size_t num) {
c->h3 = (c->h3 + B) & 0xffffffffL;
c->h4 = (c->h4 + C) & 0xffffffffL;
- if (--num == 0)
+ if (--num == 0) {
break;
+ }
A = c->h0;
B = c->h1;
diff --git a/src/crypto/sha/sha512.c b/src/crypto/sha/sha512.c
index 59be8c1..2acefb1 100644
--- a/src/crypto/sha/sha512.c
+++ b/src/crypto/sha/sha512.c
@@ -189,8 +189,9 @@ int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) {
uint8_t *p = c->u.p;
const uint8_t *data = (const uint8_t *)in_data;
- if (len == 0)
+ if (len == 0) {
return 1;
+ }
l = (c->Nl + (((uint64_t)len) << 3)) & OPENSSL_U64(0xffffffffffffffff);
if (l < c->Nl) {
@@ -218,14 +219,21 @@ int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) {
if (len >= sizeof(c->u)) {
#ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA
- if ((size_t)data % sizeof(c->u.d[0]) != 0)
- while (len >= sizeof(c->u))
- memcpy(p, data, sizeof(c->u)), sha512_block_data_order(c, p, 1),
- len -= sizeof(c->u), data += sizeof(c->u);
- else
+ if ((size_t)data % sizeof(c->u.d[0]) != 0) {
+ while (len >= sizeof(c->u)) {
+ memcpy(p, data, sizeof(c->u));
+ sha512_block_data_order(c, p, 1);
+ len -= sizeof(c->u);
+ data += sizeof(c->u);
+ }
+ } else
#endif
- sha512_block_data_order(c, data, len / sizeof(c->u)), data += len,
- len %= sizeof(c->u), data -= len;
+ {
+ sha512_block_data_order(c, data, len / sizeof(c->u));
+ data += len;
+ len %= sizeof(c->u);
+ data -= len;
+ }
}
if (len != 0) {
diff --git a/src/crypto/stack/make_macros.sh b/src/crypto/stack/make_macros.sh
index f72aa33..4837e44 100644
--- a/src/crypto/stack/make_macros.sh
+++ b/src/crypto/stack/make_macros.sh
@@ -86,6 +86,9 @@ output_stack () {
#define sk_${type}_set_cmp_func(sk, comp)\\
((int (*) (const ${type} **a, const ${type} **b)) sk_set_cmp_func(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(stack_cmp_func, int (*) (const ${type} **a, const ${type} **b), comp)))
+#define sk_${type}_deep_copy(sk, copy_func, free_func)\\
+((STACK_OF(${type})*) sk_deep_copy(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk), CHECKED_CAST(void* (*) (void*), ${ptrtype} (*) (${ptrtype}), copy_func), CHECKED_CAST(void (*) (void*), void (*) (${ptrtype}), free_func)))
+
EOF
}
diff --git a/src/crypto/stack/stack.c b/src/crypto/stack/stack.c
index 0b336ba..c584515 100644
--- a/src/crypto/stack/stack.c
+++ b/src/crypto/stack/stack.c
@@ -86,9 +86,7 @@ _STACK *sk_new(stack_cmp_func comp) {
return ret;
err:
- if (ret) {
- OPENSSL_free(ret);
- }
+ OPENSSL_free(ret);
return NULL;
}
@@ -232,7 +230,7 @@ int sk_find(_STACK *sk, size_t *out_index, void *p) {
int (*comp_func)(const void *,const void *);
if (sk == NULL) {
- return -1;
+ return 0;
}
if (sk->comp == NULL) {
@@ -324,9 +322,7 @@ _STACK *sk_dup(const _STACK *sk) {
return ret;
err:
- if (ret) {
- sk_free(ret);
- }
+ sk_free(ret);
return NULL;
}
@@ -360,3 +356,31 @@ stack_cmp_func sk_set_cmp_func(_STACK *sk, stack_cmp_func comp) {
return old;
}
+
+_STACK *sk_deep_copy(const _STACK *sk, void *(*copy_func)(void *),
+ void (*free_func)(void *)) {
+ _STACK *ret = sk_dup(sk);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ size_t i;
+ for (i = 0; i < ret->num; i++) {
+ if (ret->data[i] == NULL) {
+ continue;
+ }
+ ret->data[i] = copy_func(ret->data[i]);
+ if (ret->data[i] == NULL) {
+ size_t j;
+ for (j = 0; j < i; j++) {
+ if (ret->data[j] != NULL) {
+ free_func(ret->data[j]);
+ }
+ }
+ sk_free(ret);
+ return NULL;
+ }
+ }
+
+ return ret;
+}
diff --git a/src/crypto/test/CMakeLists.txt b/src/crypto/test/CMakeLists.txt
new file mode 100644
index 0000000..0d5ca81
--- /dev/null
+++ b/src/crypto/test/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_library(
+ test_support
+
+ OBJECT
+
+ file_test.cc
+)
diff --git a/src/crypto/test/file_test.cc b/src/crypto/test/file_test.cc
new file mode 100644
index 0000000..12405f2
--- /dev/null
+++ b/src/crypto/test/file_test.cc
@@ -0,0 +1,326 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "file_test.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <openssl/err.h>
+
+#include "stl_compat.h"
+
+
+FileTest::FileTest(const char *path) {
+ file_ = fopen(path, "r");
+ if (file_ == nullptr) {
+ fprintf(stderr, "Could not open file %s: %s.\n", path, strerror(errno));
+ }
+}
+
+FileTest::~FileTest() {
+ if (file_ != nullptr) {
+ fclose(file_);
+ }
+}
+
+// FindDelimiter returns a pointer to the first '=' or ':' in |str| or nullptr
+// if there is none.
+static const char *FindDelimiter(const char *str) {
+ while (*str) {
+ if (*str == ':' || *str == '=') {
+ return str;
+ }
+ str++;
+ }
+ return nullptr;
+}
+
+// StripSpace returns a string containing up to |len| characters from |str| with
+// leading and trailing whitespace removed.
+static std::string StripSpace(const char *str, size_t len) {
+ // Remove leading space.
+ while (len > 0 && isspace(*str)) {
+ str++;
+ len--;
+ }
+ while (len > 0 && isspace(str[len-1])) {
+ len--;
+ }
+ return std::string(str, len);
+}
+
+FileTest::ReadResult FileTest::ReadNext() {
+ // If the previous test had unused attributes or block, it is an error.
+ if (!unused_attributes_.empty()) {
+ for (const std::string &key : unused_attributes_) {
+ PrintLine("Unused attribute: %s", key.c_str());
+ }
+ return kReadError;
+ }
+ if (!block_.empty() && !used_block_) {
+ PrintLine("Unused block");
+ return kReadError;
+ }
+
+ ClearTest();
+
+ bool in_block = false;
+ while (true) {
+ // Read the next line.
+ char buf[4096];
+ if (fgets(buf, sizeof(buf), file_) == nullptr) {
+ if (feof(file_)) {
+ if (in_block) {
+ fprintf(stderr, "Unterminated block.\n");
+ return kReadError;
+ }
+ // EOF is a valid terminator for a test.
+ return start_line_ > 0 ? kReadSuccess : kReadEOF;
+ }
+ fprintf(stderr, "Error reading from input.\n");
+ return kReadError;
+ }
+
+ line_++;
+ size_t len = strlen(buf);
+ // Check for truncation.
+ if (len > 0 && buf[len - 1] != '\n' && !feof(file_)) {
+ fprintf(stderr, "Line %u too long.\n", line_);
+ return kReadError;
+ }
+
+ bool is_delimiter = strncmp(buf, "---", 3) == 0;
+ if (in_block) {
+ block_ += buf;
+ if (is_delimiter) {
+ // Ending the block completes the test.
+ return kReadSuccess;
+ }
+ } else if (is_delimiter) {
+ if (start_line_ == 0) {
+ fprintf(stderr, "Line %u: Unexpected block.\n", line_);
+ return kReadError;
+ }
+ in_block = true;
+ block_ += buf;
+ } else if (buf[0] == '\n' || buf[0] == '\0') {
+ // Empty lines delimit tests.
+ if (start_line_ > 0) {
+ return kReadSuccess;
+ }
+ } else if (buf[0] != '#') { // Comment lines are ignored.
+ // Parse the line as an attribute.
+ const char *delimiter = FindDelimiter(buf);
+ if (delimiter == nullptr) {
+ fprintf(stderr, "Line %u: Could not parse attribute.\n", line_);
+ }
+ std::string key = StripSpace(buf, delimiter - buf);
+ std::string value = StripSpace(delimiter + 1,
+ buf + len - delimiter - 1);
+
+ unused_attributes_.insert(key);
+ attributes_[key] = value;
+ if (start_line_ == 0) {
+ // This is the start of a test.
+ type_ = key;
+ parameter_ = value;
+ start_line_ = line_;
+ }
+ }
+ }
+}
+
+void FileTest::PrintLine(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+
+ fprintf(stderr, "Line %u: ", start_line_);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+
+ va_end(args);
+}
+
+const std::string &FileTest::GetType() {
+ OnKeyUsed(type_);
+ return type_;
+}
+
+const std::string &FileTest::GetParameter() {
+ OnKeyUsed(type_);
+ return parameter_;
+}
+
+const std::string &FileTest::GetBlock() {
+ used_block_ = true;
+ return block_;
+}
+
+bool FileTest::HasAttribute(const std::string &key) {
+ OnKeyUsed(key);
+ return attributes_.count(key) > 0;
+}
+
+bool FileTest::GetAttribute(std::string *out_value, const std::string &key) {
+ OnKeyUsed(key);
+ auto iter = attributes_.find(key);
+ if (iter == attributes_.end()) {
+ PrintLine("Missing attribute '%s'.", key.c_str());
+ return false;
+ }
+ *out_value = iter->second;
+ return true;
+}
+
+const std::string &FileTest::GetAttributeOrDie(const std::string &key) {
+ if (!HasAttribute(key)) {
+ abort();
+ }
+ return attributes_[key];
+}
+
+static bool FromHexDigit(uint8_t *out, char c) {
+ if ('0' <= c && c <= '9') {
+ *out = c - '0';
+ return true;
+ }
+ if ('a' <= c && c <= 'f') {
+ *out = c - 'a' + 10;
+ return true;
+ }
+ if ('A' <= c && c <= 'F') {
+ *out = c - 'A' + 10;
+ return true;
+ }
+ return false;
+}
+
+bool FileTest::GetBytes(std::vector<uint8_t> *out, const std::string &key) {
+ std::string value;
+ if (!GetAttribute(&value, key)) {
+ return false;
+ }
+
+ if (value.size() >= 2 && value[0] == '"' && value[value.size() - 1] == '"') {
+ out->assign(value.begin() + 1, value.end() - 1);
+ return true;
+ }
+
+ if (value.size() % 2 != 0) {
+ PrintLine("Error decoding value: %s", value.c_str());
+ return false;
+ }
+ out->reserve(value.size() / 2);
+ for (size_t i = 0; i < value.size(); i += 2) {
+ uint8_t hi, lo;
+ if (!FromHexDigit(&hi, value[i]) || !FromHexDigit(&lo, value[i+1])) {
+ PrintLine("Error decoding value: %s", value.c_str());
+ return false;
+ }
+ out->push_back((hi << 4) | lo);
+ }
+ return true;
+}
+
+static std::string EncodeHex(const uint8_t *in, size_t in_len) {
+ static const char kHexDigits[] = "0123456789abcdef";
+ std::string ret;
+ ret.reserve(in_len * 2);
+ for (size_t i = 0; i < in_len; i++) {
+ ret += kHexDigits[in[i] >> 4];
+ ret += kHexDigits[in[i] & 0xf];
+ }
+ return ret;
+}
+
+bool FileTest::ExpectBytesEqual(const uint8_t *expected, size_t expected_len,
+ const uint8_t *actual, size_t actual_len) {
+ if (expected_len == actual_len &&
+ memcmp(expected, actual, expected_len) == 0) {
+ return true;
+ }
+
+ std::string expected_hex = EncodeHex(expected, expected_len);
+ std::string actual_hex = EncodeHex(actual, actual_len);
+ PrintLine("Expected: %s", expected_hex.c_str());
+ PrintLine("Actual: %s", actual_hex.c_str());
+ return false;
+}
+
+void FileTest::ClearTest() {
+ start_line_ = 0;
+ type_.clear();
+ parameter_.clear();
+ attributes_.clear();
+ block_.clear();
+ unused_attributes_.clear();
+ used_block_ = false;
+}
+
+void FileTest::OnKeyUsed(const std::string &key) {
+ unused_attributes_.erase(key);
+}
+
+int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg,
+ const char *path) {
+ FileTest t(path);
+ if (!t.is_open()) {
+ return 1;
+ }
+
+ bool failed = false;
+ while (true) {
+ FileTest::ReadResult ret = t.ReadNext();
+ if (ret == FileTest::kReadError) {
+ return 1;
+ } else if (ret == FileTest::kReadEOF) {
+ break;
+ }
+
+ bool result = run_test(&t, arg);
+ if (t.HasAttribute("Error")) {
+ if (result) {
+ t.PrintLine("Operation unexpectedly succeeded.");
+ failed = true;
+ continue;
+ }
+ uint32_t err = ERR_peek_error();
+ if (ERR_reason_error_string(err) != t.GetAttributeOrDie("Error")) {
+ t.PrintLine("Unexpected error; wanted '%s', got '%s'.",
+ t.GetAttributeOrDie("Error").c_str(),
+ ERR_reason_error_string(err));
+ failed = true;
+ continue;
+ }
+ ERR_clear_error();
+ } else if (!result) {
+ // In case the test itself doesn't print output, print something so the
+ // line number is reported.
+ t.PrintLine("Test failed");
+ ERR_print_errors_fp(stderr);
+ failed = true;
+ continue;
+ }
+ }
+
+ if (failed) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/test/file_test.h b/src/crypto/test/file_test.h
new file mode 100644
index 0000000..7303d8a
--- /dev/null
+++ b/src/crypto/test/file_test.h
@@ -0,0 +1,166 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H
+#define OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+
+
+// File-based test framework.
+//
+// This module provides a file-based test framework. The file format is based on
+// that of OpenSSL upstream's evp_test and BoringSSL's aead_test. Each input
+// file is a sequence of attributes, blocks, and blank lines.
+//
+// Each attribute has the form:
+//
+// Name = Value
+//
+// Either '=' or ':' may be used to delimit the name from the value. Both the
+// name and value have leading and trailing spaces stripped.
+//
+// Blocks are delimited by lines beginning with three hyphens, "---". One such
+// line begins a block and another ends it. Blocks are intended as a convenient
+// way to embed PEM data and include their delimiters.
+//
+// Outside a block, lines beginning with # are ignored.
+//
+// A test is a sequence of one or more attributes followed by a block or blank
+// line. Blank lines are otherwise ignored. For tests that process multiple
+// kinds of test cases, the first attribute is parsed out as the test's type and
+// parameter. Otherwise, attributes are unordered. The first attribute is also
+// included in the set of attributes, so tests which do not dispatch may ignore
+// this mechanism.
+//
+// Functions in this module freely output to |stderr| on failure. Tests should
+// also do so, and it is recommended they include the corresponding test's line
+// number in any output. |PrintLine| does this automatically.
+//
+// Each attribute in a test must be consumed. When a test completes, if any
+// attributes haven't been processed, the framework reports an error.
+
+
+class FileTest {
+ public:
+ explicit FileTest(const char *path);
+ ~FileTest();
+
+ // is_open returns true if the file was successfully opened.
+ bool is_open() const { return file_ != nullptr; }
+
+ enum ReadResult {
+ kReadSuccess,
+ kReadEOF,
+ kReadError,
+ };
+
+ // ReadNext reads the next test from the file. It returns |kReadSuccess| if
+ // successfully reading a test and |kReadEOF| at the end of the file. On
+ // error or if the previous test had unconsumed attributes, it returns
+ // |kReadError|.
+ ReadResult ReadNext();
+
+ // PrintLine is a variant of printf which prepends the line number and appends
+ // a trailing newline.
+ void PrintLine(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__((__format__(__printf__, 2, 3)))
+#endif
+ ;
+
+ unsigned start_line() const { return start_line_; }
+
+ // GetType returns the name of the first attribute of the current test.
+ const std::string &GetType();
+ // GetParameter returns the value of the first attribute of the current test.
+ const std::string &GetParameter();
+ // GetBlock returns the optional block of the current test, or the empty
+ // if there was no block.
+ const std::string &GetBlock();
+
+ // HasAttribute returns true if the current test has an attribute named |key|.
+ bool HasAttribute(const std::string &key);
+
+ // GetAttribute looks up the attribute with key |key|. It sets |*out_value| to
+ // the value and returns true if it exists and returns false with an error to
+ // |stderr| otherwise.
+ bool GetAttribute(std::string *out_value, const std::string &key);
+
+ // GetAttributeOrDie looks up the attribute with key |key| and aborts if it is
+ // missing. It only be used after a |HasAttribute| call.
+ const std::string &GetAttributeOrDie(const std::string &key);
+
+ // GetBytes looks up the attribute with key |key| and decodes it as a byte
+ // string. On success, it writes the result to |*out| and returns
+ // true. Otherwise it returns false with an error to |stderr|. The value may
+ // be either a hexadecimal string or a quoted ASCII string. It returns true on
+ // success and returns false with an error to |stderr| on failure.
+ bool GetBytes(std::vector<uint8_t> *out, const std::string &key);
+
+ // ExpectBytesEqual returns true if |expected| and |actual| are equal.
+ // Otherwise, it returns false and prints a message to |stderr|.
+ bool ExpectBytesEqual(const uint8_t *expected, size_t expected_len,
+ const uint8_t *actual, size_t actual_len);
+
+ private:
+ void ClearTest();
+ void OnKeyUsed(const std::string &key);
+
+ FILE *file_ = nullptr;
+ // line_ is the number of lines read.
+ unsigned line_ = 0;
+
+ // start_line_ is the line number of the first attribute of the test.
+ unsigned start_line_ = 0;
+ // type_ is the name of the first attribute of the test.
+ std::string type_;
+ // parameter_ is the value of the first attribute.
+ std::string parameter_;
+ // attributes_ contains all attributes in the test, including the first.
+ std::map<std::string, std::string> attributes_;
+ // block_, if non-empty, is the test's optional trailing block.
+ std::string block_;
+
+ // unused_attributes_ is the set of attributes that have been queried.
+ std::set<std::string> unused_attributes_;
+ // used_block_ is true if the block has been queried.
+ bool used_block_ = false;
+
+ FileTest(const FileTest&) = delete;
+ FileTest &operator=(const FileTest&) = delete;
+};
+
+// FileTestMain runs a file-based test out of |path| and returns an exit code
+// suitable to return out of |main|. |run_test| should return true on pass and
+// false on failure. FileTestMain also implements common handling of the 'Error'
+// attribute. A test with that attribute is expected to fail. The value of the
+// attribute is the reason string of the expected OpenSSL error code.
+//
+// Tests are guaranteed to run serially and may affect global state if need be.
+// It is legal to use "tests" which, for example, import a private key into a
+// list of keys. This may be used to initialize a shared set of keys for many
+// tests. However, if one test fails, the framework will continue to run
+// subsequent tests.
+int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg,
+ const char *path);
+
+
+#endif /* OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H */
diff --git a/src/crypto/test/scoped_types.h b/src/crypto/test/scoped_types.h
new file mode 100644
index 0000000..eb04c18
--- /dev/null
+++ b/src/crypto/test/scoped_types.h
@@ -0,0 +1,120 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
+#define OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
+
+#include <stdint.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/cmac.h>
+#include <openssl/dh.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+#include <openssl/pkcs8.h>
+#include <openssl/rsa.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+#include "stl_compat.h"
+
+
+template<typename T, void (*func)(T*)>
+struct OpenSSLDeleter {
+ void operator()(T *obj) {
+ func(obj);
+ }
+};
+
+template<typename StackType, typename T, void (*func)(T*)>
+struct OpenSSLStackDeleter {
+ void operator()(StackType *obj) {
+ sk_pop_free(reinterpret_cast<_STACK*>(obj),
+ reinterpret_cast<void (*)(void *)>(func));
+ }
+};
+
+template<typename T>
+struct OpenSSLFree {
+ void operator()(T *buf) {
+ OPENSSL_free(buf);
+ }
+};
+
+template<typename T, void (*func)(T*)>
+using ScopedOpenSSLType = bssl::unique_ptr<T, OpenSSLDeleter<T, func>>;
+
+template<typename StackType, typename T, void (*func)(T*)>
+using ScopedOpenSSLStack =
+ bssl::unique_ptr<StackType, OpenSSLStackDeleter<StackType, T, func>>;
+
+template<typename T, typename CleanupRet, void (*init_func)(T*),
+ CleanupRet (*cleanup_func)(T*)>
+class ScopedOpenSSLContext {
+ public:
+ ScopedOpenSSLContext() {
+ init_func(&ctx_);
+ }
+ ~ScopedOpenSSLContext() {
+ cleanup_func(&ctx_);
+ }
+
+ T *get() { return &ctx_; }
+ const T *get() const { return &ctx_; }
+
+ void Reset() {
+ cleanup_func(&ctx_);
+ init_func(&ctx_);
+ }
+
+ private:
+ T ctx_;
+};
+
+using ScopedBIO = ScopedOpenSSLType<BIO, BIO_vfree>;
+using ScopedBIGNUM = ScopedOpenSSLType<BIGNUM, BN_free>;
+using ScopedBN_CTX = ScopedOpenSSLType<BN_CTX, BN_CTX_free>;
+using ScopedBN_MONT_CTX = ScopedOpenSSLType<BN_MONT_CTX, BN_MONT_CTX_free>;
+using ScopedCMAC_CTX = ScopedOpenSSLType<CMAC_CTX, CMAC_CTX_free>;
+using ScopedDH = ScopedOpenSSLType<DH, DH_free>;
+using ScopedECDSA_SIG = ScopedOpenSSLType<ECDSA_SIG, ECDSA_SIG_free>;
+using ScopedEC_GROUP = ScopedOpenSSLType<EC_GROUP, EC_GROUP_free>;
+using ScopedEC_KEY = ScopedOpenSSLType<EC_KEY, EC_KEY_free>;
+using ScopedEC_POINT = ScopedOpenSSLType<EC_POINT, EC_POINT_free>;
+using ScopedEVP_PKEY = ScopedOpenSSLType<EVP_PKEY, EVP_PKEY_free>;
+using ScopedEVP_PKEY_CTX = ScopedOpenSSLType<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
+using ScopedPKCS8_PRIV_KEY_INFO = ScopedOpenSSLType<PKCS8_PRIV_KEY_INFO,
+ PKCS8_PRIV_KEY_INFO_free>;
+using ScopedPKCS12 = ScopedOpenSSLType<PKCS12, PKCS12_free>;
+using ScopedRSA = ScopedOpenSSLType<RSA, RSA_free>;
+using ScopedX509 = ScopedOpenSSLType<X509, X509_free>;
+using ScopedX509_ALGOR = ScopedOpenSSLType<X509_ALGOR, X509_ALGOR_free>;
+
+using ScopedX509Stack = ScopedOpenSSLStack<STACK_OF(X509), X509, X509_free>;
+
+using ScopedEVP_MD_CTX = ScopedOpenSSLContext<EVP_MD_CTX, int, EVP_MD_CTX_init,
+ EVP_MD_CTX_cleanup>;
+using ScopedHMAC_CTX = ScopedOpenSSLContext<HMAC_CTX, void, HMAC_CTX_init,
+ HMAC_CTX_cleanup>;
+
+using ScopedOpenSSLBytes = bssl::unique_ptr<uint8_t, OpenSSLFree<uint8_t>>;
+using ScopedOpenSSLString = bssl::unique_ptr<char, OpenSSLFree<char>>;
+
+
+#endif // OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
diff --git a/src/crypto/test/stl_compat.h b/src/crypto/test/stl_compat.h
new file mode 100644
index 0000000..1997a45
--- /dev/null
+++ b/src/crypto/test/stl_compat.h
@@ -0,0 +1,144 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_CRYPTO_TEST_STL_COMPAT_H
+#define OPENSSL_HEADER_CRYPTO_TEST_STL_COMPAT_H
+
+#include <assert.h>
+
+#include <vector>
+
+
+// This header contains re-implementations of library functions from C++11. They
+// will be replaced with their standard counterparts once Chromium has C++11
+// library support in its toolchain.
+
+namespace bssl {
+
+// vector_data is a reimplementation of |std::vector::data| from C++11.
+template <class T>
+static T *vector_data(std::vector<T> *out) {
+ return out->empty() ? nullptr : &(*out)[0];
+}
+
+template <class T>
+static const T *vector_data(const std::vector<T> *out) {
+ return out->empty() ? nullptr : &(*out)[0];
+}
+
+// remove_reference is a reimplementation of |std::remove_reference| from C++11.
+template <class T>
+struct remove_reference {
+ using type = T;
+};
+
+template <class T>
+struct remove_reference<T&> {
+ using type = T;
+};
+
+template <class T>
+struct remove_reference<T&&> {
+ using type = T;
+};
+
+// move is a reimplementation of |std::move| from C++11.
+template <class T>
+typename remove_reference<T>::type &&move(T &&t) {
+ return static_cast<typename remove_reference<T>::type&&>(t);
+}
+
+// default_delete is a partial reimplementation of |std::default_delete| from
+// C++11.
+template <class T>
+struct default_delete {
+ void operator()(T *t) const {
+ enum { type_must_be_complete = sizeof(T) };
+ delete t;
+ }
+};
+
+// nullptr_t is |std::nullptr_t| from C++11.
+using nullptr_t = decltype(nullptr);
+
+// unique_ptr is a partial reimplementation of |std::unique_ptr| from C++11. It
+// intentionally does not support stateful deleters to avoid having to bother
+// with the empty member optimization.
+template <class T, class Deleter = default_delete<T>>
+class unique_ptr {
+ public:
+ unique_ptr() : ptr_(nullptr) {}
+ unique_ptr(nullptr_t) : ptr_(nullptr) {}
+ unique_ptr(T *ptr) : ptr_(ptr) {}
+ unique_ptr(const unique_ptr &u) = delete;
+
+ unique_ptr(unique_ptr &&u) : ptr_(nullptr) {
+ reset(u.release());
+ }
+
+ ~unique_ptr() {
+ reset();
+ }
+
+ unique_ptr &operator=(nullptr_t) {
+ reset();
+ return *this;
+ }
+
+ unique_ptr &operator=(unique_ptr &&u) {
+ reset(u.release());
+ return *this;
+ }
+
+ unique_ptr& operator=(const unique_ptr &u) = delete;
+
+ explicit operator bool() const {
+ return ptr_ != nullptr;
+ }
+
+ T &operator*() const {
+ assert(ptr_ != nullptr);
+ return *ptr_;
+ }
+
+ T *operator->() const {
+ assert(ptr_ != nullptr);
+ return ptr_;
+ }
+
+ T *get() const {
+ return ptr_;
+ }
+
+ T *release() {
+ T *ptr = ptr_;
+ ptr_ = nullptr;
+ return ptr;
+ }
+
+ void reset(T *ptr = nullptr) {
+ if (ptr_ != nullptr) {
+ Deleter()(ptr_);
+ }
+ ptr_ = ptr;
+ }
+
+ private:
+ T *ptr_;
+};
+
+} // namespace bssl
+
+
+#endif // OPENSSL_HEADER_CRYPTO_TEST_STL_COMPAT_H
diff --git a/src/crypto/thread.c b/src/crypto/thread.c
index 024993e..abc8b6f 100644
--- a/src/crypto/thread.c
+++ b/src/crypto/thread.c
@@ -56,44 +56,34 @@
#include <openssl/thread.h>
-#include <errno.h>
#include <string.h>
-#if defined(OPENSSL_WINDOWS)
+#if !defined(OPENSSL_WINDOWS)
+#include <errno.h>
+#else
#pragma warning(push, 3)
#include <windows.h>
#pragma warning(pop)
#endif
#include <openssl/mem.h>
-#include <openssl/type_check.h>
+#define CRYPTO_LOCK_ITEM(x) #x
+
/* lock_names contains the names of all the locks defined in thread.h. */
static const char *const lock_names[] = {
- "<<ERROR>>", "err", "ex_data", "x509",
- "x509_info", "x509_pkey", "x509_crl", "x509_req",
- "dsa", "rsa", "evp_pkey", "x509_store",
- "ssl_ctx", "ssl_cert", "ssl_session", "ssl_sess_cert",
- "ssl", "ssl_method", "rand", "rand2",
- "debug_malloc", "BIO", "gethostbyname", "getservbyname",
- "readdir", "RSA_blinding", "dh", "debug_malloc2",
- "dso", "dynlock", "engine", "ui",
- "ecdsa", "ec", "ecdh", "bn",
- "ec_pre_comp", "store", "comp", "fips",
- "fips2", "obj",
+ CRYPTO_LOCK_LIST
};
-OPENSSL_COMPILE_ASSERT(CRYPTO_NUM_LOCKS ==
- sizeof(lock_names) / sizeof(lock_names[0]),
- CRYPTO_NUM_LOCKS_inconsistent);
+#undef CRYPTO_LOCK_ITEM
+
+#define CRYPTO_NUM_LOCKS (sizeof(lock_names) / sizeof(lock_names[0]))
static void (*locking_callback)(int mode, int lock_num, const char *file,
int line) = 0;
static int (*add_lock_callback)(int *pointer, int amount, int lock_num,
const char *file, int line) = 0;
-static void (*threadid_callback)(CRYPTO_THREADID *) = 0;
-
int CRYPTO_num_locks(void) { return CRYPTO_NUM_LOCKS; }
@@ -115,23 +105,13 @@ const char *CRYPTO_get_lock_name(int lock_num) {
}
}
-int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *)) {
- if (threadid_callback) {
- return 0;
- }
- threadid_callback = func;
- return 1;
-}
+int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *)) { return 1; }
-void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val) {
- memset(id, 0, sizeof(*id));
- id->val = val;
-}
+void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val) {}
-void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr) {
- memset(id, 0, sizeof(*id));
- id->ptr = ptr;
-}
+void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr) {}
+
+void CRYPTO_THREADID_current(CRYPTO_THREADID *id) {}
void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
const char *file, int line) {
@@ -165,32 +145,6 @@ int CRYPTO_add_lock(int *pointer, int amount, int lock_num, const char *file,
return ret;
}
-void CRYPTO_THREADID_current(CRYPTO_THREADID *id) {
- if (threadid_callback) {
- threadid_callback(id);
- return;
- }
-
-#if defined(OPENSSL_WINDOWS)
- CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
-#else
- /* For everything else, default to using the address of 'errno' */
- CRYPTO_THREADID_set_pointer(id, (void *)&errno);
-#endif
-}
-
-int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b) {
- return memcmp(a, b, sizeof(*a));
-}
-
-void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src) {
- memcpy(dest, src, sizeof(*src));
-}
-
-uint32_t CRYPTO_THREADID_hash(const CRYPTO_THREADID *id) {
- return OPENSSL_hash32(id, sizeof(CRYPTO_THREADID));
-}
-
void CRYPTO_set_id_callback(unsigned long (*func)(void)) {}
void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(
diff --git a/src/crypto/thread_none.c b/src/crypto/thread_none.c
new file mode 100644
index 0000000..cf4e85a
--- /dev/null
+++ b/src/crypto/thread_none.c
@@ -0,0 +1,55 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+#if defined(OPENSSL_NO_THREADS)
+
+void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {}
+
+void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {}
+
+void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {}
+
+void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {}
+
+void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {}
+
+void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {}
+
+void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {}
+
+void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {}
+
+void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
+ if (*once) {
+ return;
+ }
+ *once = 1;
+ init();
+}
+
+static void *g_thread_locals[NUM_OPENSSL_THREAD_LOCALS];
+
+void *CRYPTO_get_thread_local(thread_local_data_t index) {
+ return g_thread_locals[index];
+}
+
+int CRYPTO_set_thread_local(thread_local_data_t index, void *value,
+ thread_local_destructor_t destructor) {
+ g_thread_locals[index] = value;
+ return 1;
+}
+
+#endif /* OPENSSL_NO_THREADS */
diff --git a/src/crypto/thread_pthread.c b/src/crypto/thread_pthread.c
new file mode 100644
index 0000000..59c4b8d
--- /dev/null
+++ b/src/crypto/thread_pthread.c
@@ -0,0 +1,162 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS)
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+#include <openssl/type_check.h>
+
+
+OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(pthread_rwlock_t),
+ CRYPTO_MUTEX_too_small);
+
+void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {
+ if (pthread_rwlock_init((pthread_rwlock_t *) lock, NULL) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {
+ if (pthread_rwlock_rdlock((pthread_rwlock_t *) lock) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {
+ if (pthread_rwlock_wrlock((pthread_rwlock_t *) lock) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {
+ if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {
+ pthread_rwlock_destroy((pthread_rwlock_t *) lock);
+}
+
+void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {
+ if (pthread_rwlock_rdlock(&lock->lock) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {
+ if (pthread_rwlock_wrlock(&lock->lock) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
+ if (pthread_rwlock_unlock(&lock->lock) != 0) {
+ abort();
+ }
+}
+
+void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
+ pthread_once(once, init);
+}
+
+static pthread_mutex_t g_destructors_lock = PTHREAD_MUTEX_INITIALIZER;
+static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS];
+
+static void thread_local_destructor(void *arg) {
+ if (arg == NULL) {
+ return;
+ }
+
+ thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS];
+ if (pthread_mutex_lock(&g_destructors_lock) != 0) {
+ return;
+ }
+ memcpy(destructors, g_destructors, sizeof(destructors));
+ pthread_mutex_unlock(&g_destructors_lock);
+
+ unsigned i;
+ void **pointers = arg;
+ for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) {
+ if (destructors[i] != NULL) {
+ destructors[i](pointers[i]);
+ }
+ }
+
+ OPENSSL_free(pointers);
+}
+
+static pthread_once_t g_thread_local_init_once = PTHREAD_ONCE_INIT;
+static pthread_key_t g_thread_local_key;
+static int g_thread_local_failed = 0;
+
+static void thread_local_init(void) {
+ g_thread_local_failed =
+ pthread_key_create(&g_thread_local_key, thread_local_destructor) != 0;
+}
+
+void *CRYPTO_get_thread_local(thread_local_data_t index) {
+ CRYPTO_once(&g_thread_local_init_once, thread_local_init);
+ if (g_thread_local_failed) {
+ return NULL;
+ }
+
+ void **pointers = pthread_getspecific(g_thread_local_key);
+ if (pointers == NULL) {
+ return NULL;
+ }
+ return pointers[index];
+}
+
+int CRYPTO_set_thread_local(thread_local_data_t index, void *value,
+ thread_local_destructor_t destructor) {
+ CRYPTO_once(&g_thread_local_init_once, thread_local_init);
+ if (g_thread_local_failed) {
+ destructor(value);
+ return 0;
+ }
+
+ void **pointers = pthread_getspecific(g_thread_local_key);
+ if (pointers == NULL) {
+ pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
+ if (pointers == NULL) {
+ destructor(value);
+ return 0;
+ }
+ memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
+ if (pthread_setspecific(g_thread_local_key, pointers) != 0) {
+ OPENSSL_free(pointers);
+ destructor(value);
+ return 0;
+ }
+ }
+
+ if (pthread_mutex_lock(&g_destructors_lock) != 0) {
+ destructor(value);
+ return 0;
+ }
+ g_destructors[index] = destructor;
+ pthread_mutex_unlock(&g_destructors_lock);
+
+ pointers[index] = value;
+ return 1;
+}
+
+#endif /* !OPENSSL_WINDOWS && !OPENSSL_NO_THREADS */
diff --git a/src/crypto/thread_test.c b/src/crypto/thread_test.c
new file mode 100644
index 0000000..cecda88
--- /dev/null
+++ b/src/crypto/thread_test.c
@@ -0,0 +1,202 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+#include <stdio.h>
+
+
+#if !defined(OPENSSL_NO_THREADS)
+
+#if defined(OPENSSL_WINDOWS)
+
+#pragma warning(push, 3)
+#include <Windows.h>
+#pragma warning(pop)
+
+typedef HANDLE thread_t;
+
+static DWORD WINAPI thread_run(LPVOID arg) {
+ void (*thread_func)(void);
+ /* VC really doesn't like casting between data and function pointers. */
+ memcpy(&thread_func, &arg, sizeof(thread_func));
+ thread_func();
+ return 0;
+}
+
+static int run_thread(thread_t *out_thread, void (*thread_func)(void)) {
+ void *arg;
+ /* VC really doesn't like casting between data and function pointers. */
+ memcpy(&arg, &thread_func, sizeof(arg));
+
+ *out_thread = CreateThread(NULL /* security attributes */,
+ 0 /* default stack size */, thread_run, arg,
+ 0 /* run immediately */, NULL /* ignore id */);
+ return *out_thread != NULL;
+}
+
+static int wait_for_thread(thread_t thread) {
+ return WaitForSingleObject(thread, INFINITE) == 0;
+}
+
+#else
+
+#include <pthread.h>
+
+typedef pthread_t thread_t;
+
+static void *thread_run(void *arg) {
+ void (*thread_func)(void) = arg;
+ thread_func();
+ return NULL;
+}
+
+static int run_thread(thread_t *out_thread, void (*thread_func)(void)) {
+ return pthread_create(out_thread, NULL /* default attributes */, thread_run,
+ thread_func) == 0;
+}
+
+static int wait_for_thread(thread_t thread) {
+ return pthread_join(thread, NULL) == 0;
+}
+
+#endif /* OPENSSL_WINDOWS */
+
+static unsigned g_once_init_called = 0;
+
+static void once_init(void) {
+ g_once_init_called++;
+}
+
+static CRYPTO_once_t g_test_once = CRYPTO_ONCE_INIT;
+
+static void call_once_thread(void) {
+ CRYPTO_once(&g_test_once, once_init);
+}
+
+static int test_once(void) {
+ if (g_once_init_called != 0) {
+ fprintf(stderr, "g_once_init_called was non-zero at start.\n");
+ return 0;
+ }
+
+ thread_t thread;
+ if (!run_thread(&thread, call_once_thread) ||
+ !wait_for_thread(thread)) {
+ fprintf(stderr, "thread failed.\n");
+ return 0;
+ }
+
+ CRYPTO_once(&g_test_once, once_init);
+
+ if (g_once_init_called != 1) {
+ fprintf(stderr, "Expected init function to be called once, but found %u.\n",
+ g_once_init_called);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int g_test_thread_ok = 0;
+static unsigned g_destructor_called_count = 0;
+
+static void thread_local_destructor(void *arg) {
+ if (arg == NULL) {
+ return;
+ }
+
+ unsigned *count = arg;
+ (*count)++;
+}
+
+static void thread_local_test_thread(void) {
+ void *ptr = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST);
+ if (ptr != NULL) {
+ return;
+ }
+
+ if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_TEST,
+ &g_destructor_called_count,
+ thread_local_destructor)) {
+ return;
+ }
+
+ if (CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST) !=
+ &g_destructor_called_count) {
+ return;
+ }
+
+ g_test_thread_ok = 1;
+}
+
+static void thread_local_test2_thread(void) {}
+
+static int test_thread_local(void) {
+ void *ptr = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_TEST);
+ if (ptr != NULL) {
+ fprintf(stderr, "Thread-local data was non-NULL at start.\n");
+ }
+
+ thread_t thread;
+ if (!run_thread(&thread, thread_local_test_thread) ||
+ !wait_for_thread(thread)) {
+ fprintf(stderr, "thread failed.\n");
+ return 0;
+ }
+
+ if (!g_test_thread_ok) {
+ fprintf(stderr, "Thread-local data didn't work in thread.\n");
+ return 0;
+ }
+
+ if (g_destructor_called_count != 1) {
+ fprintf(stderr,
+ "Destructor should have been called once, but actually called %u "
+ "times.\n",
+ g_destructor_called_count);
+ return 0;
+ }
+
+ /* thread_local_test2_thread doesn't do anything, but it tests that the
+ * thread destructor function works even if thread-local storage wasn't used
+ * for a thread. */
+ if (!run_thread(&thread, thread_local_test2_thread) ||
+ !wait_for_thread(thread)) {
+ fprintf(stderr, "thread failed.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ if (!test_once() ||
+ !test_thread_local()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
+
+#else /* OPENSSL_NO_THREADS */
+
+int main(int argc, char **argv) {
+ printf("PASS\n");
+ return 0;
+}
+
+#endif
diff --git a/src/crypto/thread_win.c b/src/crypto/thread_win.c
new file mode 100644
index 0000000..5efd8be
--- /dev/null
+++ b/src/crypto/thread_win.c
@@ -0,0 +1,282 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include "internal.h"
+
+#if defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS)
+
+#pragma warning(push, 3)
+#include <windows.h>
+#pragma warning(pop)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+#include <openssl/type_check.h>
+
+
+OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(CRITICAL_SECTION),
+ CRYPTO_MUTEX_too_small);
+
+static void run_once(CRYPTO_once_t *in_once, void (*init)(void *), void *arg) {
+ volatile LONG *once = in_once;
+
+ /* Values must be aligned. */
+ assert((((uintptr_t) once) & 3) == 0);
+
+ /* This assumes that reading *once has acquire semantics. This should be true
+ * on x86 and x86-64, where we expect Windows to run. */
+#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
+#error "Windows once code may not work on other platforms." \
+ "You can use InitOnceBeginInitialize on >=Vista"
+#endif
+ if (*once == 1) {
+ return;
+ }
+
+ for (;;) {
+ switch (InterlockedCompareExchange(once, 2, 0)) {
+ case 0:
+ /* The value was zero so we are the first thread to call |CRYPTO_once|
+ * on it. */
+ init(arg);
+ /* Write one to indicate that initialisation is complete. */
+ InterlockedExchange(once, 1);
+ return;
+
+ case 1:
+ /* Another thread completed initialisation between our fast-path check
+ * and |InterlockedCompareExchange|. */
+ return;
+
+ case 2:
+ /* Another thread is running the initialisation. Switch to it then try
+ * again. */
+ SwitchToThread();
+ break;
+
+ default:
+ abort();
+ }
+ }
+}
+
+static void call_once_init(void *arg) {
+ void (*init_func)(void);
+ /* MSVC does not like casting between data and function pointers. */
+ memcpy(&init_func, &arg, sizeof(void *));
+ init_func();
+}
+
+void CRYPTO_once(CRYPTO_once_t *in_once, void (*init)(void)) {
+ void *arg;
+ /* MSVC does not like casting between data and function pointers. */
+ memcpy(&arg, &init, sizeof(void *));
+ run_once(in_once, call_once_init, arg);
+}
+
+void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {
+ if (!InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION *) lock, 0x400)) {
+ abort();
+ }
+}
+
+void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {
+ /* Since we have to support Windows XP, read locks are actually exclusive. */
+ EnterCriticalSection((CRITICAL_SECTION *) lock);
+}
+
+void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {
+ EnterCriticalSection((CRITICAL_SECTION *) lock);
+}
+
+void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {
+ LeaveCriticalSection((CRITICAL_SECTION *) lock);
+}
+
+void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {
+ DeleteCriticalSection((CRITICAL_SECTION *) lock);
+}
+
+static void static_lock_init(void *arg) {
+ struct CRYPTO_STATIC_MUTEX *lock = arg;
+ if (!InitializeCriticalSectionAndSpinCount(&lock->lock, 0x400)) {
+ abort();
+ }
+}
+
+void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {
+ /* Since we have to support Windows XP, read locks are actually exclusive. */
+ run_once(&lock->once, static_lock_init, lock);
+ EnterCriticalSection(&lock->lock);
+}
+
+void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {
+ CRYPTO_STATIC_MUTEX_lock_read(lock);
+}
+
+void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
+ LeaveCriticalSection(&lock->lock);
+}
+
+static CRITICAL_SECTION g_destructors_lock;
+static thread_local_destructor_t g_destructors[NUM_OPENSSL_THREAD_LOCALS];
+
+static CRYPTO_once_t g_thread_local_init_once = CRYPTO_ONCE_INIT;
+static DWORD g_thread_local_key;
+static int g_thread_local_failed;
+
+static void thread_local_init(void) {
+ if (!InitializeCriticalSectionAndSpinCount(&g_destructors_lock, 0x400)) {
+ g_thread_local_failed = 1;
+ return;
+ }
+ g_thread_local_key = TlsAlloc();
+ g_thread_local_failed = (g_thread_local_key == TLS_OUT_OF_INDEXES);
+}
+
+static void NTAPI thread_local_destructor(PVOID module,
+ DWORD reason, PVOID reserved) {
+ if (DLL_THREAD_DETACH != reason && DLL_PROCESS_DETACH != reason) {
+ return;
+ }
+
+ CRYPTO_once(&g_thread_local_init_once, thread_local_init);
+ if (g_thread_local_failed) {
+ return;
+ }
+
+ void **pointers = (void**) TlsGetValue(g_thread_local_key);
+ if (pointers == NULL) {
+ return;
+ }
+
+ thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS];
+
+ EnterCriticalSection(&g_destructors_lock);
+ memcpy(destructors, g_destructors, sizeof(destructors));
+ LeaveCriticalSection(&g_destructors_lock);
+
+ unsigned i;
+ for (i = 0; i < NUM_OPENSSL_THREAD_LOCALS; i++) {
+ if (destructors[i] != NULL) {
+ destructors[i](pointers[i]);
+ }
+ }
+
+ OPENSSL_free(pointers);
+}
+
+/* Thread Termination Callbacks.
+ *
+ * Windows doesn't support a per-thread destructor with its TLS primitives.
+ * So, we build it manually by inserting a function to be called on each
+ * thread's exit. This magic is from http://www.codeproject.com/threads/tls.asp
+ * and it works for VC++ 7.0 and later.
+ *
+ * Force a reference to _tls_used to make the linker create the TLS directory
+ * if it's not already there. (E.g. if __declspec(thread) is not used). Force
+ * a reference to p_thread_callback_boringssl to prevent whole program
+ * optimization from discarding the variable. */
+#ifdef _WIN64
+#pragma comment(linker, "/INCLUDE:_tls_used")
+#pragma comment(linker, "/INCLUDE:p_thread_callback_boringssl")
+#else
+#pragma comment(linker, "/INCLUDE:__tls_used")
+#pragma comment(linker, "/INCLUDE:_p_thread_callback_boringssl")
+#endif
+
+/* .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are
+ * called automatically by the OS loader code (not the CRT) when the module is
+ * loaded and on thread creation. They are NOT called if the module has been
+ * loaded by a LoadLibrary() call. It must have implicitly been loaded at
+ * process startup.
+ *
+ * By implicitly loaded, I mean that it is directly referenced by the main EXE
+ * or by one of its dependent DLLs. Delay-loaded DLL doesn't count as being
+ * implicitly loaded.
+ *
+ * See VC\crt\src\tlssup.c for reference. */
+
+/* The linker must not discard p_thread_callback_boringssl. (We force a reference
+ * to this variable with a linker /INCLUDE:symbol pragma to ensure that.) If
+ * this variable is discarded, the OnThreadExit function will never be
+ * called. */
+#ifdef _WIN64
+
+/* .CRT section is merged with .rdata on x64 so it must be constant data. */
+#pragma const_seg(".CRT$XLC")
+/* When defining a const variable, it must have external linkage to be sure the
+ * linker doesn't discard it. */
+extern const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl;
+const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor;
+/* Reset the default section. */
+#pragma const_seg()
+
+#else
+
+#pragma data_seg(".CRT$XLC")
+PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor;
+/* Reset the default section. */
+#pragma data_seg()
+
+#endif /* _WIN64 */
+
+void *CRYPTO_get_thread_local(thread_local_data_t index) {
+ CRYPTO_once(&g_thread_local_init_once, thread_local_init);
+ if (g_thread_local_failed) {
+ return NULL;
+ }
+
+ void **pointers = TlsGetValue(g_thread_local_key);
+ if (pointers == NULL) {
+ return NULL;
+ }
+ return pointers[index];
+}
+
+int CRYPTO_set_thread_local(thread_local_data_t index, void *value,
+ thread_local_destructor_t destructor) {
+ CRYPTO_once(&g_thread_local_init_once, thread_local_init);
+ if (g_thread_local_failed) {
+ destructor(value);
+ return 0;
+ }
+
+ void **pointers = TlsGetValue(g_thread_local_key);
+ if (pointers == NULL) {
+ pointers = OPENSSL_malloc(sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
+ if (pointers == NULL) {
+ destructor(value);
+ return 0;
+ }
+ memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
+ if (TlsSetValue(g_thread_local_key, pointers) == 0) {
+ OPENSSL_free(pointers);
+ destructor(value);
+ return 0;
+ }
+ }
+
+ EnterCriticalSection(&g_destructors_lock);
+ g_destructors[index] = destructor;
+ LeaveCriticalSection(&g_destructors_lock);
+
+ pointers[index] = value;
+ return 1;
+}
+
+#endif /* OPENSSL_WINDOWS && !OPENSSL_NO_THREADS */
diff --git a/src/crypto/time_support.c b/src/crypto/time_support.c
index 9302ebf..bf9daed 100644
--- a/src/crypto/time_support.c
+++ b/src/crypto/time_support.c
@@ -67,6 +67,9 @@
#include <openssl/time_support.h>
+#include <time.h>
+
+
#define SECS_PER_DAY (24 * 60 * 60)
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result) {
@@ -135,8 +138,9 @@ static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
/* Work out Julian day of new date */
time_jd += offset_day;
- if (time_jd < 0)
+ if (time_jd < 0) {
return 0;
+ }
*pday = time_jd;
*psec = offset_hms;
@@ -148,15 +152,17 @@ int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
long time_jd;
/* Convert time and offset into julian day and seconds */
- if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec))
+ if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) {
return 0;
+ }
/* Convert Julian day back to date */
julian_to_date(time_jd, &time_year, &time_month, &time_day);
- if (time_year < 1900 || time_year > 9999)
+ if (time_year < 1900 || time_year > 9999) {
return 0;
+ }
/* Update tm structure */
diff --git a/src/crypto/x509/CMakeLists.txt b/src/crypto/x509/CMakeLists.txt
index f00e28a..96cf35c 100644
--- a/src/crypto/x509/CMakeLists.txt
+++ b/src/crypto/x509/CMakeLists.txt
@@ -22,7 +22,6 @@ add_library(
x509_cmp.c
x509_d2.c
x509_def.c
- x509_error.c
x509_ext.c
x509_lu.c
x509_obj.c
diff --git a/src/crypto/x509/asn1_gen.c b/src/crypto/x509/asn1_gen.c
index 750701e..d4d1ee6 100644
--- a/src/crypto/x509/asn1_gen.c
+++ b/src/crypto/x509/asn1_gen.c
@@ -64,6 +64,11 @@
#include <openssl/obj.h>
#include <openssl/x509v3.h>
+#include "../internal.h"
+
+
+/* Although this file is in crypto/x509 for layering purposes, it emits errors
+ * from the ASN.1 module for OpenSSL compatibility. */
#define ASN1_GEN_FLAG 0x10000
#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1)
@@ -138,6 +143,7 @@ ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
}
ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
+ OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
{
ASN1_TYPE *ret;
tag_exp_arg asn1_tags;
@@ -165,7 +171,7 @@ ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
{
if (!cnf)
{
- OPENSSL_PUT_ERROR(X509, ASN1_generate_v3, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
+ OPENSSL_PUT_ERROR(ASN1, ASN1_generate_v3, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
return NULL;
}
ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
@@ -308,7 +314,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
if (utype == -1)
{
- OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_UNKNOWN_TAG);
+ OPENSSL_PUT_ERROR(ASN1, asn1_cb, ASN1_R_UNKNOWN_TAG);
ERR_add_error_data(2, "tag=", elem);
return -1;
}
@@ -321,7 +327,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
/* If no value and not end of string, error */
if (!vstart && elem[len])
{
- OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_MISSING_VALUE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_cb, ASN1_R_MISSING_VALUE);
return -1;
}
return 0;
@@ -334,7 +340,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
/* Check for illegal multiple IMPLICIT tagging */
if (arg->imp_tag != -1)
{
- OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_ILLEGAL_NESTED_TAGGING);
+ OPENSSL_PUT_ERROR(ASN1, asn1_cb, ASN1_R_ILLEGAL_NESTED_TAGGING);
return -1;
}
if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
@@ -370,17 +376,22 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
break;
case ASN1_GEN_FLAG_FORMAT:
+ if (!vstart)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_cb, ASN1_R_UNKNOWN_FORMAT);
+ return -1;
+ }
if (!strncmp(vstart, "ASCII", 5))
arg->format = ASN1_GEN_FORMAT_ASCII;
else if (!strncmp(vstart, "UTF8", 4))
arg->format = ASN1_GEN_FORMAT_UTF8;
else if (!strncmp(vstart, "HEX", 3))
arg->format = ASN1_GEN_FORMAT_HEX;
- else if (!strncmp(vstart, "BITLIST", 3))
+ else if (!strncmp(vstart, "BITLIST", 7))
arg->format = ASN1_GEN_FORMAT_BITLIST;
else
{
- OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_UNKNOWN_FORMAT);
+ OPENSSL_PUT_ERROR(ASN1, asn1_cb, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
break;
@@ -404,7 +415,7 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
return 0;
if (tag_num < 0)
{
- OPENSSL_PUT_ERROR(X509, parse_tagging, ASN1_R_INVALID_NUMBER);
+ OPENSSL_PUT_ERROR(ASN1, parse_tagging, ASN1_R_INVALID_NUMBER);
return 0;
}
*ptag = tag_num;
@@ -437,7 +448,7 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
default:
erch[0] = *eptr;
erch[1] = 0;
- OPENSSL_PUT_ERROR(X509, parse_tagging, ASN1_R_INVALID_MODIFIER);
+ OPENSSL_PUT_ERROR(ASN1, parse_tagging, ASN1_R_INVALID_MODIFIER);
ERR_add_error_data(2, "Char=", erch);
return 0;
break;
@@ -523,13 +534,13 @@ static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_cons
/* Can only have IMPLICIT if permitted */
if ((arg->imp_tag != -1) && !imp_ok)
{
- OPENSSL_PUT_ERROR(X509, append_exp, ASN1_R_ILLEGAL_IMPLICIT_TAG);
+ OPENSSL_PUT_ERROR(ASN1, append_exp, ASN1_R_ILLEGAL_IMPLICIT_TAG);
return 0;
}
if (arg->exp_count == ASN1_FLAG_EXP_MAX)
{
- OPENSSL_PUT_ERROR(X509, append_exp, ASN1_R_DEPTH_EXCEEDED);
+ OPENSSL_PUT_ERROR(ASN1, append_exp, ASN1_R_DEPTH_EXCEEDED);
return 0;
}
@@ -647,7 +658,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
if (!(atmp = ASN1_TYPE_new()))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ERR_R_MALLOC_FAILURE);
return NULL;
}
@@ -660,7 +671,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_NULL:
if (str && *str)
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_NULL_VALUE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_ILLEGAL_NULL_VALUE);
goto bad_form;
}
break;
@@ -668,7 +679,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_BOOLEAN:
if (format != ASN1_GEN_FORMAT_ASCII)
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_NOT_ASCII_FORMAT);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_NOT_ASCII_FORMAT);
goto bad_form;
}
vtmp.name = NULL;
@@ -676,7 +687,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
vtmp.value = (char *)str;
if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_BOOLEAN);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_ILLEGAL_BOOLEAN);
goto bad_str;
}
break;
@@ -685,12 +696,12 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_ENUMERATED:
if (format != ASN1_GEN_FORMAT_ASCII)
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
goto bad_form;
}
if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str)))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_INTEGER);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_ILLEGAL_INTEGER);
goto bad_str;
}
break;
@@ -698,12 +709,12 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_OBJECT:
if (format != ASN1_GEN_FORMAT_ASCII)
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
goto bad_form;
}
if (!(atmp->value.object = OBJ_txt2obj(str, 0)))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_OBJECT);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_ILLEGAL_OBJECT);
goto bad_str;
}
break;
@@ -712,23 +723,23 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
case V_ASN1_GENERALIZEDTIME:
if (format != ASN1_GEN_FORMAT_ASCII)
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_TIME_NOT_ASCII_FORMAT);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_TIME_NOT_ASCII_FORMAT);
goto bad_form;
}
if (!(atmp->value.asn1_string = ASN1_STRING_new()))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
atmp->value.asn1_string->type = utype;
if (!ASN1_TIME_check(atmp->value.asn1_string))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_TIME_VALUE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_ILLEGAL_TIME_VALUE);
goto bad_str;
}
@@ -750,7 +761,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
format = MBSTRING_UTF8;
else
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_FORMAT);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_ILLEGAL_FORMAT);
goto bad_form;
}
@@ -758,7 +769,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
-1, format, ASN1_tag2bit(utype)) <= 0)
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ERR_R_MALLOC_FAILURE);
goto bad_str;
}
@@ -771,7 +782,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
if (!(atmp->value.asn1_string = ASN1_STRING_new()))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ERR_R_MALLOC_FAILURE);
goto bad_form;
}
@@ -780,7 +791,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
if (!(rdata = string_to_hex((char *)str, &rdlen)))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_HEX);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_ILLEGAL_HEX);
goto bad_str;
}
@@ -795,7 +806,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
{
if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string))
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_LIST_ERROR);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_LIST_ERROR);
goto bad_str;
}
no_unused = 0;
@@ -803,7 +814,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
}
else
{
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
goto bad_form;
}
@@ -819,7 +830,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
break;
default:
- OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_UNSUPPORTED_TYPE);
+ OPENSSL_PUT_ERROR(ASN1, asn1_str2type, ASN1_R_UNSUPPORTED_TYPE);
goto bad_str;
break;
}
@@ -849,12 +860,12 @@ static int bitstr_cb(const char *elem, int len, void *bitstr)
return 0;
if (bitnum < 0)
{
- OPENSSL_PUT_ERROR(X509, bitstr_cb, ASN1_R_INVALID_NUMBER);
+ OPENSSL_PUT_ERROR(ASN1, bitstr_cb, ASN1_R_INVALID_NUMBER);
return 0;
}
if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1))
{
- OPENSSL_PUT_ERROR(X509, bitstr_cb, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(ASN1, bitstr_cb, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
diff --git a/src/crypto/x509/by_dir.c b/src/crypto/x509/by_dir.c
index 5a77b81..098c1bd 100644
--- a/src/crypto/x509/by_dir.c
+++ b/src/crypto/x509/by_dir.c
@@ -63,6 +63,7 @@
#include <openssl/err.h>
#include <openssl/lhash.h>
#include <openssl/mem.h>
+#include <openssl/thread.h>
#include <openssl/x509.h>
@@ -442,6 +443,12 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
if (!hent)
{
hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
+ if (hent == NULL)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ ok = 0;
+ goto finish;
+ }
hent->hash = h;
hent->suffix = k;
if (!sk_BY_DIR_HASH_push(ent->hashes, hent))
diff --git a/src/crypto/x509/by_file.c b/src/crypto/x509/by_file.c
index 2649631..2fdbce4 100644
--- a/src/crypto/x509/by_file.c
+++ b/src/crypto/x509/by_file.c
@@ -55,11 +55,14 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
+#include <stdlib.h>
+
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/lhash.h>
#include <openssl/pem.h>
-#include <openssl/x509.h>
+#include <openssl/thread.h>
+
#ifndef OPENSSL_NO_STDIO
diff --git a/src/crypto/x509/i2d_pr.c b/src/crypto/x509/i2d_pr.c
index 8896565..443ca53 100644
--- a/src/crypto/x509/i2d_pr.c
+++ b/src/crypto/x509/i2d_pr.c
@@ -57,8 +57,7 @@
#include <openssl/x509.h>
-#include <stdio.h>
-
+#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/evp.h>
@@ -77,7 +76,9 @@ int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
PKCS8_PRIV_KEY_INFO_free(p8);
return ret;
}
- OPENSSL_PUT_ERROR(X509, i2d_PrivateKey, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ /* Although this file is in crypto/x509 for layering reasons, it emits
+ * an error code from ASN1 for OpenSSL compatibility. */
+ OPENSSL_PUT_ERROR(ASN1, i2d_PrivateKey, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return -1;
}
diff --git a/src/crypto/x509/pkcs7.c b/src/crypto/x509/pkcs7.c
index bb86077..99ee3da 100644
--- a/src/crypto/x509/pkcs7.c
+++ b/src/crypto/x509/pkcs7.c
@@ -18,6 +18,7 @@
#include <openssl/bytestring.h>
#include <openssl/err.h>
+#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/pem.h>
#include <openssl/stack.h>
diff --git a/src/crypto/x509/pkcs7_test.c b/src/crypto/x509/pkcs7_test.c
index bac9fb2..38beb3e 100644
--- a/src/crypto/x509/pkcs7_test.c
+++ b/src/crypto/x509/pkcs7_test.c
@@ -18,6 +18,7 @@
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
+#include <openssl/mem.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
diff --git a/src/crypto/x509/vpm_int.h b/src/crypto/x509/vpm_int.h
index d18a4d4..9edbd5a 100644
--- a/src/crypto/x509/vpm_int.h
+++ b/src/crypto/x509/vpm_int.h
@@ -60,10 +60,10 @@
struct X509_VERIFY_PARAM_ID_st
{
- unsigned char *host; /* If not NULL hostname to match */
- size_t hostlen;
+ STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */
unsigned int hostflags; /* Flags to control matching features */
- unsigned char *email; /* If not NULL email address to match */
+ char *peername; /* Matching hostname in peer certificate */
+ char *email; /* If not NULL email address to match */
size_t emaillen;
unsigned char *ip; /* If not NULL IP address to match */
size_t iplen; /* Length of IP address */
diff --git a/src/crypto/x509/x509_att.c b/src/crypto/x509/x509_att.c
index 3613c35..90e7810 100644
--- a/src/crypto/x509/x509_att.c
+++ b/src/crypto/x509/x509_att.c
@@ -273,7 +273,7 @@ int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj)
return(0);
ASN1_OBJECT_free(attr->object);
attr->object=OBJ_dup(obj);
- return(1);
+ return attr->object != NULL;
}
int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len)
diff --git a/src/crypto/x509/x509_error.c b/src/crypto/x509/x509_error.c
deleted file mode 100644
index 6669a7a..0000000
--- a/src/crypto/x509/x509_error.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* 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/x509.h>
-
-const ERR_STRING_DATA X509_error_string_data[] = {
- {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_digest, 0), "ASN1_digest"},
- {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_generate_v3, 0), "ASN1_generate_v3"},
- {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_item_sign_ctx, 0), "ASN1_item_sign_ctx"},
- {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_item_verify, 0), "ASN1_item_verify"},
- {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_sign, 0), "ASN1_sign"},
- {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_b64_decode, 0), "NETSCAPE_SPKI_b64_decode"},
- {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_b64_encode, 0), "NETSCAPE_SPKI_b64_encode"},
- {ERR_PACK(ERR_LIB_X509, X509_F_PKCS7_get_CRLs, 0), "PKCS7_get_CRLs"},
- {ERR_PACK(ERR_LIB_X509, X509_F_PKCS7_get_certificates, 0), "PKCS7_get_certificates"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_NID, 0), "X509_ATTRIBUTE_create_by_NID"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_OBJ, 0), "X509_ATTRIBUTE_create_by_OBJ"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_txt, 0), "X509_ATTRIBUTE_create_by_txt"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_get0_data, 0), "X509_ATTRIBUTE_get0_data"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_set1_data, 0), "X509_ATTRIBUTE_set1_data"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_add0_revoked, 0), "X509_CRL_add0_revoked"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_diff, 0), "X509_CRL_diff"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_print_fp, 0), "X509_CRL_print_fp"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_create_by_NID, 0), "X509_EXTENSION_create_by_NID"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_create_by_OBJ, 0), "X509_EXTENSION_create_by_OBJ"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_INFO_new, 0), "X509_INFO_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_create_by_NID, 0), "X509_NAME_ENTRY_create_by_NID"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_create_by_txt, 0), "X509_NAME_ENTRY_create_by_txt"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_set_object, 0), "X509_NAME_ENTRY_set_object"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_add_entry, 0), "X509_NAME_add_entry"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_oneline, 0), "X509_NAME_oneline"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_print, 0), "X509_NAME_print"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_PKEY_new, 0), "X509_PKEY_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_get, 0), "X509_PUBKEY_get"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_set, 0), "X509_PUBKEY_set"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_check_private_key, 0), "X509_REQ_check_private_key"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_to_X509, 0), "X509_REQ_to_X509"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_get1_issuer, 0), "X509_STORE_CTX_get1_issuer"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_init, 0), "X509_STORE_CTX_init"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_new, 0), "X509_STORE_CTX_new"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_purpose_inherit, 0), "X509_STORE_CTX_purpose_inherit"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_add_cert, 0), "X509_STORE_add_cert"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_add_crl, 0), "X509_STORE_add_crl"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_add, 0), "X509_TRUST_add"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_set, 0), "X509_TRUST_set"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_check_private_key, 0), "X509_check_private_key"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_get_pubkey_parameters, 0), "X509_get_pubkey_parameters"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_cert_crl_file, 0), "X509_load_cert_crl_file"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_cert_file, 0), "X509_load_cert_file"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_crl_file, 0), "X509_load_crl_file"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_print_ex_fp, 0), "X509_print_ex_fp"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_to_X509_REQ, 0), "X509_to_X509_REQ"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509_verify_cert, 0), "X509_verify_cert"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509at_add1_attr, 0), "X509at_add1_attr"},
- {ERR_PACK(ERR_LIB_X509, X509_F_X509v3_add_ext, 0), "X509v3_add_ext"},
- {ERR_PACK(ERR_LIB_X509, X509_F_add_cert_dir, 0), "add_cert_dir"},
- {ERR_PACK(ERR_LIB_X509, X509_F_append_exp, 0), "append_exp"},
- {ERR_PACK(ERR_LIB_X509, X509_F_asn1_cb, 0), "asn1_cb"},
- {ERR_PACK(ERR_LIB_X509, X509_F_asn1_str2type, 0), "asn1_str2type"},
- {ERR_PACK(ERR_LIB_X509, X509_F_bitstr_cb, 0), "bitstr_cb"},
- {ERR_PACK(ERR_LIB_X509, X509_F_by_file_ctrl, 0), "by_file_ctrl"},
- {ERR_PACK(ERR_LIB_X509, X509_F_check_policy, 0), "check_policy"},
- {ERR_PACK(ERR_LIB_X509, X509_F_d2i_X509_PKEY, 0), "d2i_X509_PKEY"},
- {ERR_PACK(ERR_LIB_X509, X509_F_dir_ctrl, 0), "dir_ctrl"},
- {ERR_PACK(ERR_LIB_X509, X509_F_get_cert_by_subject, 0), "get_cert_by_subject"},
- {ERR_PACK(ERR_LIB_X509, X509_F_i2d_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"},
- {ERR_PACK(ERR_LIB_X509, X509_F_i2d_EC_PUBKEY, 0), "i2d_EC_PUBKEY"},
- {ERR_PACK(ERR_LIB_X509, X509_F_i2d_PrivateKey, 0), "i2d_PrivateKey"},
- {ERR_PACK(ERR_LIB_X509, X509_F_i2d_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"},
- {ERR_PACK(ERR_LIB_X509, X509_F_parse_tagging, 0), "parse_tagging"},
- {ERR_PACK(ERR_LIB_X509, X509_F_pkcs7_parse_header, 0), "pkcs7_parse_header"},
- {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_encode, 0), "x509_name_encode"},
- {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_ex_d2i, 0), "x509_name_ex_d2i"},
- {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_ex_new, 0), "x509_name_ex_new"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_AKID_MISMATCH), "AKID_MISMATCH"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_PKCS7_VERSION), "BAD_PKCS7_VERSION"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_X509_FILETYPE), "BAD_X509_FILETYPE"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_BASE64_DECODE_ERROR), "BASE64_DECODE_ERROR"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "CANT_CHECK_DH_KEY"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE), "CERT_ALREADY_IN_HASH_TABLE"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "CRL_ALREADY_DELTA"},
- {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"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_ISSUER_MISMATCH), "ISSUER_MISMATCH"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_TYPE_MISMATCH), "KEY_TYPE_MISMATCH"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_VALUES_MISMATCH), "KEY_VALUES_MISMATCH"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_CERT_DIR), "LOADING_CERT_DIR"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_DEFAULTS), "LOADING_DEFAULTS"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_METHOD_NOT_SUPPORTED), "METHOD_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_NEWER_CRL_NOT_NEWER), "NEWER_CRL_NOT_NEWER"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_NOT_PKCS7_SIGNED_DATA), "NOT_PKCS7_SIGNED_DATA"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATES_INCLUDED), "NO_CERTIFICATES_INCLUDED"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY), "NO_CERT_SET_FOR_US_TO_VERIFY"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRLS_INCLUDED), "NO_CRLS_INCLUDED"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_NUMBER), "NO_CRL_NUMBER"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_DECODE_ERROR), "PUBLIC_KEY_DECODE_ERROR"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_ENCODE_ERROR), "PUBLIC_KEY_ENCODE_ERROR"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_SHOULD_RETRY), "SHOULD_RETRY"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN), "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY), "UNABLE_TO_GET_CERTS_PUBLIC_KEY"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_KEY_TYPE), "UNKNOWN_KEY_TYPE"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_NID), "UNKNOWN_NID"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_PURPOSE_ID), "UNKNOWN_PURPOSE_ID"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "UNKNOWN_TRUST_ID"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM), "UNSUPPORTED_ALGORITHM"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_LOOKUP_TYPE), "WRONG_LOOKUP_TYPE"},
- {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_TYPE), "WRONG_TYPE"},
- {0, NULL},
-};
diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c
index 090d341..34ef26e 100644
--- a/src/crypto/x509/x509_lu.c
+++ b/src/crypto/x509/x509_lu.c
@@ -60,6 +60,7 @@
#include <openssl/err.h>
#include <openssl/lhash.h>
#include <openssl/mem.h>
+#include <openssl/thread.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
@@ -191,9 +192,6 @@ X509_STORE *X509_STORE_new(void)
if ((ret->param = X509_VERIFY_PARAM_new()) == NULL)
goto err;
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data))
- goto err;
-
ret->references = 1;
return ret;
err:
@@ -261,7 +259,6 @@ void X509_STORE_free(X509_STORE *vfy)
sk_X509_LOOKUP_free(sk);
sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
if (vfy->param)
X509_VERIFY_PARAM_free(vfy->param);
OPENSSL_free(vfy);
diff --git a/src/crypto/x509/x509_req.c b/src/crypto/x509/x509_req.c
index daaedb6..2732d6e 100644
--- a/src/crypto/x509/x509_req.c
+++ b/src/crypto/x509/x509_req.c
@@ -92,6 +92,8 @@ X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
goto err;
pktmp = X509_get_pubkey(x);
+ if (pktmp == NULL)
+ goto err;
i=X509_REQ_set_pubkey(ret,pktmp);
EVP_PKEY_free(pktmp);
if (!i) goto err;
diff --git a/src/crypto/x509/x509_v3.c b/src/crypto/x509/x509_v3.c
index 95fe729..0fc9a9a 100644
--- a/src/crypto/x509/x509_v3.c
+++ b/src/crypto/x509/x509_v3.c
@@ -231,7 +231,7 @@ int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj)
return(0);
ASN1_OBJECT_free(ex->object);
ex->object=OBJ_dup(obj);
- return(1);
+ return ex->object != NULL;
}
int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit)
diff --git a/src/crypto/x509/x509_vfy.c b/src/crypto/x509/x509_vfy.c
index 285bcaf..a0cd9fc 100644
--- a/src/crypto/x509/x509_vfy.c
+++ b/src/crypto/x509/x509_vfy.c
@@ -64,10 +64,15 @@
#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
+#include <openssl/thread.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "vpm_int.h"
+#include "../internal.h"
+
+
+static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
/* CRL score values */
@@ -410,9 +415,6 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
if (!ok) goto end;
- /* We may as well copy down any DSA parameters that are required */
- X509_get_pubkey_parameters(NULL,ctx->chain);
-
/* Check revocation status: we do this after copying parameters
* because they may be needed for CRL signature verification.
*/
@@ -441,12 +443,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
/* If we get this far evaluate policies */
if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
ok = ctx->check_policy(ctx);
- if(!ok) goto end;
- if (0)
- {
+
end:
- X509_get_pubkey_parameters(NULL,ctx->chain);
- }
if (sktmp != NULL) sk_X509_free(sktmp);
if (chain_ss != NULL) X509_free(chain_ss);
return ok;
@@ -704,23 +702,38 @@ static int check_id_error(X509_STORE_CTX *ctx, int errcode)
return ctx->verify_cb(0, ctx);
}
+static int check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id)
+ {
+ size_t i;
+ size_t n = sk_OPENSSL_STRING_num(id->hosts);
+ char *name;
+
+ for (i = 0; i < n; ++i)
+ {
+ name = sk_OPENSSL_STRING_value(id->hosts, i);
+ if (X509_check_host(x, name, strlen(name), id->hostflags,
+ &id->peername) > 0)
+ return 1;
+ }
+ return n == 0;
+ }
+
static int check_id(X509_STORE_CTX *ctx)
{
X509_VERIFY_PARAM *vpm = ctx->param;
X509_VERIFY_PARAM_ID *id = vpm->id;
X509 *x = ctx->cert;
- if (id->host && !X509_check_host(x, id->host, id->hostlen,
- id->hostflags))
+ if (id->hosts && check_hosts(x, id) <= 0)
{
if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
return 0;
}
- if (id->email && !X509_check_email(x, id->email, id->emaillen, 0))
+ if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 0)
{
if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
return 0;
}
- if (id->ip && !X509_check_ip(x, id->ip, id->iplen, 0))
+ if (id->ip && X509_check_ip(x, id->ip, id->iplen, 0) <= 0)
{
if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
return 0;
@@ -805,6 +818,7 @@ static int check_revocation(X509_STORE_CTX *ctx)
}
static int check_cert(X509_STORE_CTX *ctx)
+ OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
{
X509_CRL *crl = NULL, *dcrl = NULL;
X509 *x;
@@ -1917,48 +1931,6 @@ ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
return ASN1_TIME_adj(s, t, offset_day, offset_sec);
}
-int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
- {
- EVP_PKEY *ktmp=NULL,*ktmp2;
- size_t i,j;
-
- if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return 1;
-
- for (i=0; i<sk_X509_num(chain); i++)
- {
- ktmp=X509_get_pubkey(sk_X509_value(chain,i));
- if (ktmp == NULL)
- {
- OPENSSL_PUT_ERROR(X509, X509_get_pubkey_parameters, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
- return 0;
- }
- if (!EVP_PKEY_missing_parameters(ktmp))
- break;
- else
- {
- EVP_PKEY_free(ktmp);
- ktmp=NULL;
- }
- }
- if (ktmp == NULL)
- {
- OPENSSL_PUT_ERROR(X509, X509_get_pubkey_parameters, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
- return 0;
- }
-
- /* first, populate the other certs */
- for (j=i-1; j < i; j--)
- {
- ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
- EVP_PKEY_copy_parameters(ktmp2,ktmp);
- EVP_PKEY_free(ktmp2);
- }
-
- if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
- EVP_PKEY_free(ktmp);
- return 1;
- }
-
/* Make a delta CRL as the diff between two full CRLs */
X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
@@ -2084,8 +2056,13 @@ int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_fu
{
/* This function is (usually) called only once, by
* SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
- return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp,
- new_func, dup_func, free_func);
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
+ new_func, dup_func, free_func))
+ {
+ return -1;
+ }
+ return index;
}
int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
@@ -2255,7 +2232,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
ctx->cert=x509;
ctx->untrusted=chain;
- if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
+ if(!CRYPTO_new_ex_data(&g_ex_data_class, ctx,
&ctx->ex_data))
{
goto err;
@@ -2346,7 +2323,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
err:
if (ex_data_allocated)
{
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &ctx->ex_data);
+ CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data);
}
if (ctx->param != NULL)
{
@@ -2387,7 +2364,7 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
sk_X509_pop_free(ctx->chain,X509_free);
ctx->chain=NULL;
}
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
+ CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data));
memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
}
diff --git a/src/crypto/x509/x509_vpm.c b/src/crypto/x509/x509_vpm.c
index 3daaf61..8c8f98e 100644
--- a/src/crypto/x509/x509_vpm.c
+++ b/src/crypto/x509/x509_vpm.c
@@ -58,6 +58,7 @@
#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
+#include <openssl/stack.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
@@ -66,6 +67,59 @@
/* X509_VERIFY_PARAM functions */
+#define SET_HOST 0
+#define ADD_HOST 1
+
+static char *str_copy(char *s) { return OPENSSL_strdup(s); }
+static void str_free(char *s) { OPENSSL_free(s); }
+
+#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
+
+static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
+ const char *name, size_t namelen)
+ {
+ char *copy;
+
+ /*
+ * Refuse names with embedded NUL bytes.
+ * XXX: Do we need to push an error onto the error stack?
+ */
+ if (name && memchr(name, '\0', namelen))
+ return 0;
+
+ if (mode == SET_HOST && id->hosts)
+ {
+ string_stack_free(id->hosts);
+ id->hosts = NULL;
+ }
+ if (name == NULL || namelen == 0)
+ return 1;
+
+ copy = BUF_strndup(name, namelen);
+ if (copy == NULL)
+ return 0;
+
+ if (id->hosts == NULL &&
+ (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL)
+ {
+ OPENSSL_free(copy);
+ return 0;
+ }
+
+ if (!sk_OPENSSL_STRING_push(id->hosts, copy))
+ {
+ OPENSSL_free(copy);
+ if (sk_OPENSSL_STRING_num(id->hosts) == 0)
+ {
+ sk_OPENSSL_STRING_free(id->hosts);
+ id->hosts = NULL;
+ }
+ return 0;
+ }
+
+ return 1;
+ }
+
static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
{
X509_VERIFY_PARAM_ID *paramid;
@@ -84,11 +138,15 @@ static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
param->policies = NULL;
}
paramid = param->id;
- if (paramid->host)
+ if (paramid->hosts)
{
- OPENSSL_free(paramid->host);
- paramid->host = NULL;
- paramid->hostlen = 0;
+ string_stack_free(paramid->hosts);
+ paramid->hosts = NULL;
+ }
+ if (paramid->peername)
+ {
+ OPENSSL_free(paramid->peername);
+ paramid->peername = NULL;
}
if (paramid->email)
{
@@ -127,6 +185,8 @@ X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
{
+ if (param == NULL)
+ return;
x509_verify_param_zero(param);
OPENSSL_free(param->id);
OPENSSL_free(param);
@@ -232,11 +292,23 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
return 0;
}
- if (test_x509_verify_param_copy_id(host, NULL))
+ /* Copy the host flags if and only if we're copying the host list */
+ if (test_x509_verify_param_copy_id(hosts, NULL))
{
- if (!X509_VERIFY_PARAM_set1_host(dest, id->host, id->hostlen))
- return 0;
- dest->id->hostflags = id->hostflags;
+ if (dest->id->hosts)
+ {
+ string_stack_free(dest->id->hosts);
+ dest->id->hosts = NULL;
+ }
+ if (id->hosts)
+ {
+ dest->id->hosts =
+ sk_OPENSSL_STRING_deep_copy(id->hosts,
+ str_copy, str_free);
+ if (dest->id->hosts == NULL)
+ return 0;
+ dest->id->hostflags = id->hostflags;
+ }
}
if (test_x509_verify_param_copy_id(email, NULL))
@@ -265,16 +337,16 @@ int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
return ret;
}
-static int int_x509_param_set1(unsigned char **pdest, size_t *pdestlen,
- const unsigned char *src, size_t srclen)
+static int int_x509_param_set1(char **pdest, size_t *pdestlen,
+ const char *src, size_t srclen)
{
void *tmp;
if (src)
{
if (srclen == 0)
{
- tmp = BUF_strdup((char *)src);
- srclen = strlen((char *)src);
+ tmp = BUF_strdup(src);
+ srclen = strlen(src);
}
else
tmp = BUF_memdup(src, srclen);
@@ -394,10 +466,15 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
}
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
- const unsigned char *name, size_t namelen)
+ const char *name, size_t namelen)
+ {
+ return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
+ }
+
+int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
+ const char *name, size_t namelen)
{
- return int_x509_param_set1(&param->id->host, &param->id->hostlen,
- name, namelen);
+ return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
}
void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
@@ -406,8 +483,13 @@ void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
param->id->hostflags = flags;
}
+char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
+ {
+ return param->id->peername;
+ }
+
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
- const unsigned char *email, size_t emaillen)
+ const char *email, size_t emaillen)
{
return int_x509_param_set1(&param->id->email, &param->id->emaillen,
email, emaillen);
@@ -418,17 +500,19 @@ int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
{
if (iplen != 0 && iplen != 4 && iplen != 16)
return 0;
- return int_x509_param_set1(&param->id->ip, &param->id->iplen, ip, iplen);
+ return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen,
+ (char *)ip, iplen);
}
int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
{
unsigned char ipout[16];
- int iplen;
- iplen = a2i_ipadd(ipout, ipasc);
+ size_t iplen;
+
+ iplen = (size_t) a2i_ipadd(ipout, ipasc);
if (iplen == 0)
return 0;
- return X509_VERIFY_PARAM_set1_ip(param, ipout, (size_t)iplen);
+ return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
}
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
@@ -441,7 +525,7 @@ const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
return param->name;
}
-static const X509_VERIFY_PARAM_ID _empty_id = {NULL, 0, 0U, NULL, 0, NULL, 0};
+static const X509_VERIFY_PARAM_ID _empty_id = {NULL, 0U, NULL, NULL, 0, NULL, 0};
#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
diff --git a/src/crypto/x509/x_crl.c b/src/crypto/x509/x_crl.c
index bb23b57..aa92fa9 100644
--- a/src/crypto/x509/x_crl.c
+++ b/src/crypto/x509/x_crl.c
@@ -61,6 +61,7 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/stack.h>
+#include <openssl/thread.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
diff --git a/src/crypto/x509/x_info.c b/src/crypto/x509/x_info.c
index 8047c71..6807b24 100644
--- a/src/crypto/x509/x_info.c
+++ b/src/crypto/x509/x_info.c
@@ -59,6 +59,7 @@
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
+#include <openssl/thread.h>
X509_INFO *X509_INFO_new(void)
diff --git a/src/crypto/x509/x_name.c b/src/crypto/x509/x_name.c
index 211f68f..5cfb3ae 100644
--- a/src/crypto/x509/x_name.c
+++ b/src/crypto/x509/x_name.c
@@ -175,6 +175,16 @@ static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
*pval = NULL;
}
+static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
+{
+ sk_X509_NAME_ENTRY_free(ne);
+}
+
+static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
+{
+ sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
+}
+
static int x509_name_ex_d2i(ASN1_VALUE **val,
const unsigned char **in, long len, const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx)
@@ -197,9 +207,14 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
if(ret <= 0) return ret;
if(*val) x509_name_ex_free(val, NULL);
- if(!x509_name_ex_new(&nm.a, NULL)) goto err;
/* We've decoded it: now cache encoding */
- if(!BUF_MEM_grow(nm.x->bytes, p - q)) goto err;
+ if (!x509_name_ex_new(&nm.a, NULL) ||
+ !BUF_MEM_grow(nm.x->bytes, p - q))
+ {
+ sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+ local_sk_X509_NAME_ENTRY_pop_free);
+ goto err;
+ }
memcpy(nm.x->bytes->data, q, p - q);
/* Convert internal representation to X509_NAME structure */
@@ -248,16 +263,6 @@ static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_IT
return ret;
}
-static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
- {
- sk_X509_NAME_ENTRY_free(ne);
- }
-
-static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
- {
- sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
- }
-
static int x509_name_encode(X509_NAME *a)
{
union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
diff --git a/src/crypto/x509/x_pkey.c b/src/crypto/x509/x_pkey.c
index 550078b..5acbe5b 100644
--- a/src/crypto/x509/x_pkey.c
+++ b/src/crypto/x509/x_pkey.c
@@ -59,8 +59,9 @@
#include <string.h>
#include <openssl/asn1.h>
-#include <openssl/mem.h>
#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/thread.h>
X509_PKEY *X509_PKEY_new(void)
diff --git a/src/crypto/x509/x_pubkey.c b/src/crypto/x509/x_pubkey.c
index c285aa6..d6512ae 100644
--- a/src/crypto/x509/x_pubkey.c
+++ b/src/crypto/x509/x_pubkey.c
@@ -60,6 +60,7 @@
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
+#include <openssl/thread.h>
#include <openssl/x509.h>
#include "../evp/internal.h"
@@ -133,7 +134,7 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
if (key->pkey != NULL)
{
- return EVP_PKEY_dup(key->pkey);
+ return EVP_PKEY_up_ref(key->pkey);
}
if (key->public_key == NULL) goto error;
@@ -178,7 +179,7 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
}
- return EVP_PKEY_dup(ret);
+ return EVP_PKEY_up_ref(ret);
error:
if (ret != NULL)
diff --git a/src/crypto/x509/x_x509.c b/src/crypto/x509/x_x509.c
index 5cda3c7..234494d 100644
--- a/src/crypto/x509/x_x509.c
+++ b/src/crypto/x509/x_x509.c
@@ -65,6 +65,10 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include "../internal.h"
+
+
+static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
@@ -100,7 +104,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ret->akid = NULL;
ret->aux = NULL;
ret->crldp = NULL;
- CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
+ CRYPTO_new_ex_data(&g_ex_data_class, ret, &ret->ex_data);
break;
case ASN1_OP_D2I_POST:
@@ -109,7 +113,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
break;
case ASN1_OP_FREE_POST:
- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
+ CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data);
X509_CERT_AUX_free(ret->aux);
ASN1_OCTET_STRING_free(ret->skid);
AUTHORITY_KEYID_free(ret->akid);
@@ -145,8 +149,13 @@ X509 *X509_up_ref(X509 *x)
int X509_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_X509, argl, argp,
- new_func, dup_func, free_func);
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
+ new_func, dup_func, free_func))
+ {
+ return -1;
+ }
+ return index;
}
int X509_set_ex_data(X509 *r, int idx, void *arg)
@@ -171,8 +180,13 @@ X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
{
const unsigned char *q;
X509 *ret;
+ int freeret = 0;
+
/* Save start position */
q = *pp;
+
+ if (!a || *a == NULL)
+ freeret = 1;
ret = d2i_X509(a, pp, length);
/* If certificate unreadable then forget it */
if(!ret) return NULL;
@@ -182,7 +196,12 @@ X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
if(!d2i_X509_CERT_AUX(&ret->aux, pp, length)) goto err;
return ret;
err:
- X509_free(ret);
+ if (freeret)
+ {
+ X509_free(ret);
+ if (a)
+ *a = NULL;
+ }
return NULL;
}
diff --git a/src/crypto/x509v3/CMakeLists.txt b/src/crypto/x509v3/CMakeLists.txt
index 26de0ed..ffa5a4a 100644
--- a/src/crypto/x509v3/CMakeLists.txt
+++ b/src/crypto/x509v3/CMakeLists.txt
@@ -41,7 +41,6 @@ add_library(
v3_skey.c
v3_sxnet.c
v3_utl.c
- x509v3_error.c
)
add_executable(
@@ -50,11 +49,12 @@ add_executable(
v3nametest.c
)
+target_link_libraries(v3name_test crypto)
+
add_executable(
tab_test
tabtest.c
)
-target_link_libraries(v3name_test crypto)
target_link_libraries(tab_test crypto)
diff --git a/src/crypto/x509v3/tabtest.c b/src/crypto/x509v3/tabtest.c
index 26ecc6c..6b97e91 100644
--- a/src/crypto/x509v3/tabtest.c
+++ b/src/crypto/x509v3/tabtest.c
@@ -62,13 +62,17 @@
#include <stdio.h>
+#include <openssl/base.h>
#include <openssl/crypto.h>
#include <openssl/x509v3.h>
+#if !defined(BORINGSSL_SHARED_LIBRARY)
#include "ext_dat.h"
+#endif
int main(void)
{
+#if !defined(BORINGSSL_SHARED_LIBRARY)
int i, prev = -1, bad = 0;
const X509V3_EXT_METHOD *const *tmp;
CRYPTO_library_init();
@@ -91,4 +95,9 @@ int main(void)
printf("PASS\n");
return 0;
}
+#else
+ /* TODO(davidben): Fix this test in the shared library build. */
+ printf("PASS\n");
+ return 0;
+#endif
}
diff --git a/src/crypto/x509v3/v3_alt.c b/src/crypto/x509v3/v3_alt.c
index 113cf45..f547316 100644
--- a/src/crypto/x509v3/v3_alt.c
+++ b/src/crypto/x509v3/v3_alt.c
@@ -583,6 +583,8 @@ static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
return 0;
objlen = p - value;
objtmp = OPENSSL_malloc(objlen + 1);
+ if (objtmp == NULL)
+ return 0;
strncpy(objtmp, value, objlen);
objtmp[objlen] = 0;
gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
diff --git a/src/crypto/x509v3/v3_conf.c b/src/crypto/x509v3/v3_conf.c
index 7606ac1..cb6569f 100644
--- a/src/crypto/x509v3/v3_conf.c
+++ b/src/crypto/x509v3/v3_conf.c
@@ -67,6 +67,8 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include "../internal.h"
+
static int v3_check_critical(char **value);
static int v3_check_generic(char **value);
@@ -260,6 +262,7 @@ static int v3_check_generic(char **value)
static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
int crit, int gen_type,
X509V3_CTX *ctx)
+ OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
{
unsigned char *ext_der=NULL;
long ext_len;
@@ -454,76 +457,3 @@ void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
ctx->flags = flags;
}
-/* TODO(fork): remove */
-#if 0
-/* Old conf compatibility functions */
-
-X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- char *name, char *value)
- {
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_nconf(&ctmp, ctx, name, value);
- }
-
-/* LHASH *conf: Config file */
-/* char *value: Value */
-X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- int ext_nid, char *value)
- {
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_nconf_nid(&ctmp, ctx, ext_nid, value);
- }
-
-static char *conf_lhash_get_string(void *db, char *section, char *value)
- {
- return CONF_get_string(db, section, value);
- }
-
-static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section)
- {
- return CONF_get_section(db, section);
- }
-
-static const X509V3_CONF_METHOD conf_lhash_method = {
-conf_lhash_get_string,
-conf_lhash_get_section,
-NULL,
-NULL
-};
-
-void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash)
- {
- ctx->db_meth = &conf_lhash_method;
- ctx->db = lhash;
- }
-
-int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- char *section, X509 *cert)
- {
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_add_nconf(&ctmp, ctx, section, cert);
- }
-
-/* Same as above but for a CRL */
-
-int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- char *section, X509_CRL *crl)
- {
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl);
- }
-
-/* Add extensions to certificate request */
-
-int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- char *section, X509_REQ *req)
- {
- CONF ctmp;
- CONF_set_nconf(&ctmp, conf);
- return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req);
- }
-#endif
diff --git a/src/crypto/x509v3/v3_cpols.c b/src/crypto/x509v3/v3_cpols.c
index d5a8c3c..cbe596b 100644
--- a/src/crypto/x509v3/v3_cpols.c
+++ b/src/crypto/x509v3/v3_cpols.c
@@ -228,7 +228,14 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx,
goto merr;
/* TODO(fork): const correctness */
qual->pqualid = (ASN1_OBJECT*) OBJ_nid2obj(NID_id_qt_cps);
+ if (qual->pqualid == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, policy_section, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
qual->d.cpsuri = M_ASN1_IA5STRING_new();
+ if (qual->d.cpsuri == NULL) {
+ goto err;
+ }
if(!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
strlen(cnf->value))) goto merr;
} else if(!name_cmp(cnf->name, "userNotice")) {
@@ -287,12 +294,19 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
if(!(qual = POLICYQUALINFO_new())) goto merr;
/* TODO(fork): const correctness */
qual->pqualid = (ASN1_OBJECT *) OBJ_nid2obj(NID_id_qt_unotice);
+ if (qual->pqualid == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509V3, notice_section, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
if(!(not = USERNOTICE_new())) goto merr;
qual->d.usernotice = not;
for(i = 0; i < sk_CONF_VALUE_num(unot); i++) {
cnf = sk_CONF_VALUE_value(unot, i);
if(!strcmp(cnf->name, "explicitText")) {
not->exptext = M_ASN1_VISIBLESTRING_new();
+ if (not->exptext == NULL)
+ goto merr;
if(!ASN1_STRING_set(not->exptext, cnf->value,
strlen(cnf->value))) goto merr;
} else if(!strcmp(cnf->name, "organization")) {
diff --git a/src/crypto/x509v3/v3_purp.c b/src/crypto/x509v3/v3_purp.c
index 6daf632..3f175c9 100644
--- a/src/crypto/x509v3/v3_purp.c
+++ b/src/crypto/x509v3/v3_purp.c
@@ -63,6 +63,7 @@
#include <openssl/digest.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
+#include <openssl/thread.h>
#include <openssl/x509_vfy.h>
#include <openssl/x509v3.h>
@@ -200,7 +201,7 @@ int X509_PURPOSE_add(int id, int trust, int flags,
name_dup = BUF_strdup(name);
sname_dup = BUF_strdup(sname);
if (name_dup == NULL || sname_dup == NULL) {
- OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_add, ERR_R_MALLOC_FAILURE);
if (name_dup != NULL)
OPENSSL_free(name_dup);
if (sname_dup != NULL)
diff --git a/src/crypto/x509v3/v3_utl.c b/src/crypto/x509v3/v3_utl.c
index d081c1c..27a91ff 100644
--- a/src/crypto/x509v3/v3_utl.c
+++ b/src/crypto/x509v3/v3_utl.c
@@ -262,6 +262,8 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
int state;
/* We are going to modify the line so copy it first */
linebuf = BUF_strdup(line);
+ if (linebuf == NULL)
+ goto err;
state = HDR_NAME;
ntmp = NULL;
/* Go through all characters */
@@ -850,9 +852,11 @@ static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
*/
static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
- unsigned int flags,
- const unsigned char *b, size_t blen)
+ unsigned int flags, const char *b, size_t blen,
+ char **peername)
{
+ int rv = 0;
+
if (!a->data || !a->length)
return 0;
if (cmp_type > 0)
@@ -860,27 +864,31 @@ static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
if (cmp_type != a->type)
return 0;
if (cmp_type == V_ASN1_IA5STRING)
- return equal(a->data, a->length, b, blen, flags);
- if (a->length == (int)blen && !memcmp(a->data, b, blen))
- return 1;
- else
- return 0;
+ rv = equal(a->data, a->length,
+ (unsigned char *)b, blen, flags);
+ else if (a->length == (int)blen && !memcmp(a->data, b, blen))
+ rv = 1;
+ if (rv > 0 && peername)
+ *peername = BUF_strndup((char *)a->data, a->length);
}
else
{
- int astrlen, rv;
+ int astrlen;
unsigned char *astr;
astrlen = ASN1_STRING_to_UTF8(&astr, a);
if (astrlen < 0)
return -1;
- rv = equal(astr, astrlen, b, blen, flags);
+ rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
OPENSSL_free(astr);
- return rv;
+ if (rv > 0 && peername)
+ *peername = BUF_strndup((char *)astr, astrlen);
}
+ return rv;
}
-static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags, int check_type)
+static int do_x509_check(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags, int check_type,
+ char **peername)
{
GENERAL_NAMES *gens = NULL;
X509_NAME *name = NULL;
@@ -889,6 +897,7 @@ static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen,
int cnid;
int alt_type;
int san_present = 0;
+ int rv = 0;
equal_fn equal;
/* See below, this flag is internal-only */
@@ -918,13 +927,9 @@ static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen,
equal = equal_case;
}
- if (chklen == 0)
- chklen = strlen((const char *)chk);
-
gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
if (gens)
{
- int rv = 0;
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
{
GENERAL_NAME *gen;
@@ -939,16 +944,14 @@ static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen,
cstr = gen->d.dNSName;
else
cstr = gen->d.iPAddress;
- if (do_check_string(cstr, alt_type, equal, flags,
- chk, chklen))
- {
- rv = 1;
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(cstr, alt_type, equal, flags,
+ chk, chklen, peername)) != 0)
break;
- }
}
GENERAL_NAMES_free(gens);
- if (rv)
- return 1;
+ if (rv != 0)
+ return rv;
if (!cnid
|| (san_present
&& !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
@@ -962,38 +965,53 @@ static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen,
ASN1_STRING *str;
ne = X509_NAME_get_entry(name, j);
str = X509_NAME_ENTRY_get_data(ne);
- if (do_check_string(str, -1, equal, flags, chk, chklen))
- return 1;
+ /* Positive on success, negative on error! */
+ if ((rv = do_check_string(str, -1, equal, flags,
+ chk, chklen, peername)) != 0)
+ return rv;
}
return 0;
}
-int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags)
+int X509_check_host(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags, char **peername)
{
- return do_x509_check(x, chk, chklen, flags, GEN_DNS);
+ if (chk == NULL)
+ return -2;
+ if (memchr(chk, '\0', chklen))
+ return -2;
+ return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
}
-int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen,
- unsigned int flags)
+int X509_check_email(X509 *x, const char *chk, size_t chklen,
+ unsigned int flags)
{
- return do_x509_check(x, chk, chklen, flags, GEN_EMAIL);
+ if (chk == NULL)
+ return -2;
+ if (memchr(chk, '\0', chklen))
+ return -2;
+ return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
}
int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags)
{
- return do_x509_check(x, chk, chklen, flags, GEN_IPADD);
+ if (chk == NULL)
+ return -2;
+ return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
}
int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
{
unsigned char ipout[16];
- int iplen;
- iplen = a2i_ipadd(ipout, ipasc);
+ size_t iplen;
+
+ if (ipasc == NULL)
+ return -2;
+ iplen = (size_t) a2i_ipadd(ipout, ipasc);
if (iplen == 0)
return -2;
- return do_x509_check(x, ipout, (size_t)iplen, flags, GEN_IPADD);
+ return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
}
/* Convert IP addresses both IPv4 and IPv6 into an
diff --git a/src/crypto/x509v3/v3nametest.c b/src/crypto/x509v3/v3nametest.c
index b2e9c09..a3197e6 100644
--- a/src/crypto/x509v3/v3nametest.c
+++ b/src/crypto/x509v3/v3nametest.c
@@ -52,6 +52,7 @@
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
+#include <stdarg.h>
#include <string.h>
#include <openssl/crypto.h>
@@ -332,8 +333,7 @@ static void run_cert(X509 *crt, const char *nameincert,
int match, ret;
memcpy(name, *pname, namelen);
- ret = X509_check_host(crt, (const unsigned char *)name,
- namelen, 0);
+ ret = X509_check_host(crt, name, namelen, 0, NULL);
match = -1;
if (ret < 0)
{
@@ -351,8 +351,8 @@ static void run_cert(X509 *crt, const char *nameincert,
match = 1;
check_message(fn, "host", nameincert, match, *pname);
- ret = X509_check_host(crt, (const unsigned char *)name,
- namelen, X509_CHECK_FLAG_NO_WILDCARDS);
+ ret = X509_check_host(crt, name, namelen,
+ X509_CHECK_FLAG_NO_WILDCARDS, NULL);
match = -1;
if (ret < 0)
{
@@ -371,8 +371,7 @@ static void run_cert(X509 *crt, const char *nameincert,
check_message(fn, "host-no-wildcards",
nameincert, match, *pname);
- ret = X509_check_email(crt, (const unsigned char *)name,
- namelen, 0);
+ ret = X509_check_email(crt, name, namelen, 0);
match = -1;
if (fn->email)
{
diff --git a/src/crypto/x509v3/x509v3_error.c b/src/crypto/x509v3/x509v3_error.c
deleted file mode 100644
index 9fbca5f..0000000
--- a/src/crypto/x509v3/x509v3_error.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/* 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/x509v3.h>
-
-const ERR_STRING_DATA X509V3_error_string_data[] = {
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_add_id_INTEGER, 0), "SXNET_add_id_INTEGER"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_add_id_asc, 0), "SXNET_add_id_asc"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_add_id_ulong, 0), "SXNET_add_id_ulong"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_get_id_asc, 0), "SXNET_get_id_asc"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_get_id_ulong, 0), "SXNET_get_id_ulong"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_add, 0), "X509V3_EXT_add"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_add_alias, 0), "X509V3_EXT_add_alias"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_free, 0), "X509V3_EXT_free"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_i2d, 0), "X509V3_EXT_i2d"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_nconf, 0), "X509V3_EXT_nconf"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_add1_i2d, 0), "X509V3_add1_i2d"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_add_value, 0), "X509V3_add_value"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_get_section, 0), "X509V3_get_section"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_get_string, 0), "X509V3_get_string"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_get_value_bool, 0), "X509V3_get_value_bool"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_parse_list, 0), "X509V3_parse_list"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509_PURPOSE_add, 0), "X509_PURPOSE_add"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509_PURPOSE_set, 0), "X509_PURPOSE_set"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_a2i_GENERAL_NAME, 0), "a2i_GENERAL_NAME"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_copy_email, 0), "copy_email"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_copy_issuer, 0), "copy_issuer"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_do_dirname, 0), "do_dirname"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_do_ext_i2d, 0), "do_ext_i2d"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_do_ext_nconf, 0), "do_ext_nconf"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_gnames_from_sectname, 0), "gnames_from_sectname"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_hex_to_string, 0), "hex_to_string"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_i2s_ASN1_ENUMERATED, 0), "i2s_ASN1_ENUMERATED"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_i2s_ASN1_IA5STRING, 0), "i2s_ASN1_IA5STRING"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_i2s_ASN1_INTEGER, 0), "i2s_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_i2v_AUTHORITY_INFO_ACCESS, 0), "i2v_AUTHORITY_INFO_ACCESS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_notice_section, 0), "notice_section"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_nref_nos, 0), "nref_nos"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_policy_section, 0), "policy_section"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_process_pci_value, 0), "process_pci_value"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_r2i_certpol, 0), "r2i_certpol"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_r2i_pci, 0), "r2i_pci"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_s2i_ASN1_IA5STRING, 0), "s2i_ASN1_IA5STRING"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_s2i_ASN1_INTEGER, 0), "s2i_ASN1_INTEGER"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_s2i_ASN1_OCTET_STRING, 0), "s2i_ASN1_OCTET_STRING"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_s2i_skey_id, 0), "s2i_skey_id"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_set_dist_point_name, 0), "set_dist_point_name"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_string_to_hex, 0), "string_to_hex"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_ASN1_BIT_STRING, 0), "v2i_ASN1_BIT_STRING"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_AUTHORITY_INFO_ACCESS, 0), "v2i_AUTHORITY_INFO_ACCESS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_AUTHORITY_KEYID, 0), "v2i_AUTHORITY_KEYID"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_BASIC_CONSTRAINTS, 0), "v2i_BASIC_CONSTRAINTS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_EXTENDED_KEY_USAGE, 0), "v2i_EXTENDED_KEY_USAGE"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_GENERAL_NAMES, 0), "v2i_GENERAL_NAMES"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_GENERAL_NAME_ex, 0), "v2i_GENERAL_NAME_ex"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_NAME_CONSTRAINTS, 0), "v2i_NAME_CONSTRAINTS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_POLICY_CONSTRAINTS, 0), "v2i_POLICY_CONSTRAINTS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_POLICY_MAPPINGS, 0), "v2i_POLICY_MAPPINGS"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_crld, 0), "v2i_crld"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_idp, 0), "v2i_idp"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_issuer_alt, 0), "v2i_issuer_alt"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_subject_alt, 0), "v2i_subject_alt"},
- {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v3_generic_extension, 0), "v3_generic_extension"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_IP_ADDRESS), "BAD_IP_ADDRESS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_OBJECT), "BAD_OBJECT"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_DEC2BN_ERROR), "BN_DEC2BN_ERROR"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_TO_ASN1_INTEGER_ERROR), "BN_TO_ASN1_INTEGER_ERROR"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_CANNOT_FIND_FREE_FUNCTION), "CANNOT_FIND_FREE_FUNCTION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DIRNAME_ERROR), "DIRNAME_ERROR"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DISTPOINT_ALREADY_SET), "DISTPOINT_ALREADY_SET"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DUPLICATE_ZONE_ID), "DUPLICATE_ZONE_ID"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CONVERTING_ZONE), "ERROR_CONVERTING_ZONE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CREATING_EXTENSION), "ERROR_CREATING_EXTENSION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_IN_EXTENSION), "ERROR_IN_EXTENSION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXPECTED_A_SECTION_NAME), "EXPECTED_A_SECTION_NAME"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_EXISTS), "EXTENSION_EXISTS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NAME_ERROR), "EXTENSION_NAME_ERROR"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NOT_FOUND), "EXTENSION_NOT_FOUND"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED), "EXTENSION_SETTING_NOT_SUPPORTED"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_VALUE_ERROR), "EXTENSION_VALUE_ERROR"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_EMPTY_EXTENSION), "ILLEGAL_EMPTY_EXTENSION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_HEX_DIGIT), "ILLEGAL_HEX_DIGIT"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG), "INCORRECT_POLICY_SYNTAX_TAG"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASNUMBER), "INVALID_ASNUMBER"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASRANGE), "INVALID_ASRANGE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_BOOLEAN_STRING), "INVALID_BOOLEAN_STRING"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EXTENSION_STRING), "INVALID_EXTENSION_STRING"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_INHERITANCE), "INVALID_INHERITANCE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_IPADDRESS), "INVALID_IPADDRESS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_MULTIPLE_RDNS), "INVALID_MULTIPLE_RDNS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NAME), "INVALID_NAME"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_ARGUMENT), "INVALID_NULL_ARGUMENT"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_NAME), "INVALID_NULL_NAME"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_VALUE), "INVALID_NULL_VALUE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBER), "INVALID_NUMBER"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBERS), "INVALID_NUMBERS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OBJECT_IDENTIFIER), "INVALID_OBJECT_IDENTIFIER"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OPTION), "INVALID_OPTION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_POLICY_IDENTIFIER), "INVALID_POLICY_IDENTIFIER"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PROXY_POLICY_SETTING), "INVALID_PROXY_POLICY_SETTING"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PURPOSE), "INVALID_PURPOSE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SAFI), "INVALID_SAFI"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SECTION), "INVALID_SECTION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SYNTAX), "INVALID_SYNTAX"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ISSUER_DECODE_ERROR), "ISSUER_DECODE_ERROR"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_MISSING_VALUE), "MISSING_VALUE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS), "NEED_ORGANIZATION_AND_NUMBERS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_CONFIG_DATABASE), "NO_CONFIG_DATABASE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_CERTIFICATE), "NO_ISSUER_CERTIFICATE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_DETAILS), "NO_ISSUER_DETAILS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_POLICY_IDENTIFIER), "NO_POLICY_IDENTIFIER"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED), "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PUBLIC_KEY), "NO_PUBLIC_KEY"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_SUBJECT_DETAILS), "NO_SUBJECT_DETAILS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ODD_NUMBER_OF_DIGITS), "ODD_NUMBER_OF_DIGITS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OPERATION_NOT_DEFINED), "OPERATION_NOT_DEFINED"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OTHERNAME_ERROR), "OTHERNAME_ERROR"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED), "POLICY_LANGUAGE_ALREADY_DEFINED"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH), "POLICY_PATH_LENGTH"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED), "POLICY_PATH_LENGTH_ALREADY_DEFINED"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED), "POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY), "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_SECTION_NOT_FOUND), "SECTION_NOT_FOUND"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS), "UNABLE_TO_GET_ISSUER_DETAILS"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID), "UNABLE_TO_GET_ISSUER_KEYID"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT), "UNKNOWN_BIT_STRING_ARGUMENT"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION), "UNKNOWN_EXTENSION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION_NAME), "UNKNOWN_EXTENSION_NAME"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_OPTION), "UNKNOWN_OPTION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_OPTION), "UNSUPPORTED_OPTION"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_TYPE), "UNSUPPORTED_TYPE"},
- {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_USER_TOO_LONG), "USER_TOO_LONG"},
- {0, NULL},
-};