From 4c95c5f31a498f7c88dabeaebb837d13173dd916 Mon Sep 17 00:00:00 2001 From: Greg Rubin Date: Thu, 7 Nov 2019 00:38:49 +0000 Subject: [PATCH 1/2] Initial commit to build on ARM --- CHANGELOG.md | 1 + CMakeLists.txt | 27 ++++++++++++------ README.md | 6 ++-- THIRD-PARTY | 15 ++++++++++ arm.patch | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ build.gradle | 4 +++ csrc/rdrand.cpp | 26 +++++++++++++++--- csrc/util.h | 16 ++--------- 8 files changed, 139 insertions(+), 29 deletions(-) create mode 100644 arm.patch diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d4e9b3b..d4c05f7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Improvements * Now uses [OpenSSL 1.1.1f](https://www.openssl.org/source/openssl-1.1.1f.tar.gz). [PR #97](https://github.com/corretto/amazon-corretto-crypto-provider/pull/97) +* **EXPERIMENTAL** support for aarch64 added. [PR #99](https://github.com/corretto/amazon-corretto-crypto-provider/pull/99) ### Maintenance * Test code reuses instances of `SecureRandom` for better efficiency on platforms with slow entropy. [PR #96](https://github.com/corretto/amazon-corretto-crypto-provider/pull/96) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73e0c51d..9522f14e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,13 +265,17 @@ add_custom_command( add_custom_target(accp-jar-source DEPENDS ${ACCP_JAR_SOURCE}) if(ENABLE_NATIVE_TEST_HOOKS) + if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") add_executable(test_rdrand EXCLUDE_FROM_ALL csrc/test_rdrand.cpp ) - add_executable(test_keyutils EXCLUDE_FROM_ALL + + target_link_libraries(test_rdrand amazonCorrettoCryptoProvider) + endif () + + add_executable(test_keyutils EXCLUDE_FROM_ALL csrc/test_keyutils.cpp ) - target_link_libraries(test_rdrand amazonCorrettoCryptoProvider) target_link_libraries(test_keyutils amazonCorrettoCryptoProvider) endif() @@ -655,7 +659,7 @@ add_custom_target(check-install-via-properties-with-debug -Dcom.amazon.corretto.crypto.provider.inTestSuite=hunter2 -Dtest.data.dir=${TEST_DATA_DIR} -Djava.security.properties=${ORIG_SRCROOT}/etc/amazon-corretto-crypto-provider.security - -Djava.security.debug=all + -Djava.security.debug=all ${TEST_JAVA_ARGS} com.amazon.corretto.crypto.provider.test.SecurityPropertyTester @@ -665,13 +669,16 @@ add_custom_target(check DEPENDS check-recursive-init check-install-via-properties check-install-via-properties-with-debug check-junit) if(ENABLE_NATIVE_TEST_HOOKS) - add_custom_target(check-rdrand - COMMAND $ - ) + if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + add_custom_target(check-rdrand + COMMAND $ + ) + add_dependencies(check check-rdrand) + endif() add_custom_target(check-keyutils COMMAND $ ) - add_dependencies(check check-rdrand check-keyutils) + add_dependencies(check check-keyutils) endif() add_custom_target(coverage @@ -689,7 +696,7 @@ add_custom_target(coverage add_custom_target(check-integration-extra-checks COMMAND ${TEST_JAVA_EXECUTABLE} -cp $:$:${TEST_CLASSPATH} -Djava.library.path=$ - -Dcom.amazon.corretto.crypto.provider.extrachecks=ALL + -Dcom.amazon.corretto.crypto.provider.extrachecks=ALL ${TEST_JAVA_ARGS} com.amazon.corretto.crypto.provider.test.TestRunner --suite integration @@ -716,6 +723,8 @@ add_custom_target(run-benchmark set_target_properties(run-benchmark PROPERTIES EXCLUDE_FROM_ALL 1) +if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + add_custom_target(run-dieharder COMMAND ${TEST_JAVA_EXECUTABLE} -cp $:$:${TEST_CLASSPATH} -Djava.library.path=$ @@ -813,6 +822,6 @@ add_custom_target(check-dieharder-threads COMMAND ! grep rdseed /proc/cpuinfo || grep PASSED dieharder-threads-results-rdseed-tail.txt DEPENDS run-dieharder-threads-tail run-dieharder-threads-rdrand-tail run-dieharder-threads-rdseed-tail run-dieharder-threads) - +endif() # End of Dieharder targets # Do this at the end, after we finish all our feature tests, or it'll be missing flags configure_file(${CMAKE_CURRENT_SOURCE_DIR}/csrc/config.h.in ${JNI_HEADER_DIR}/config.h) diff --git a/README.md b/README.md index 6526b30b..b5fd9c01 100644 --- a/README.md +++ b/README.md @@ -75,11 +75,13 @@ This library is compatible with: * OpenJDK 8 or newer (This includes [Amazon Corretto](https://aws.amazon.com/corretto/)) * OracleJDK 8 or newer * Linux x86_64 +* Linux ARM64/aarch64 **(EXPERIMENTAL)** If ACCP is used/installed on a system it does not support, it will disable itself and the JVM will behave as if ACCP weren't installed at all. -## Future Compatibility (Soon) -* ARM64 +ARM64/aarch64 support is currently experimental and not distributed via Maven. +If you want to experiment with ACCP on aarch64 platforms you will need to build it yourself as described later in this document. + # Using the provider ## Installation diff --git a/THIRD-PARTY b/THIRD-PARTY index dbe85cce..a9bbe937 100644 --- a/THIRD-PARTY +++ b/THIRD-PARTY @@ -363,3 +363,18 @@ To the extent that NIST may hold copyright in countries other than the United St You may improve, modify, and create derivative works of the data or any portion of the data, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the data and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the data: Data citation recommendations are provided at https://www.nist.gov/open/license. Permission to use this data is contingent upon your acceptance of the terms of this agreement and upon your providing appropriate acknowledgments of NIST’s creation of the data/work. + +----- + +** arm.patch + +This patch file was written by szelei.t@gmail.com and released by him under an MIT license at +https://github.com/openssl/openssl/issues/10842#issuecomment-608287665 + +Copyright 2020 szelei.t@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/arm.patch b/arm.patch new file mode 100644 index 00000000..f064c3ee --- /dev/null +++ b/arm.patch @@ -0,0 +1,73 @@ +This patch file was written by szelei.t@gmail.com and released by him under an MIT license at +https://github.com/openssl/openssl/issues/10842#issuecomment-608287665 + +--- a/crypto/sha/asm/sha1-armv8.pl 2020-01-10 15:51:40.284641928 +0100 ++++ b/crypto/sha/asm/sha1-armv8.pl 2020-01-10 15:52:46.924618409 +0100 +@@ -329,7 +329,7 @@ + #endif + .asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by " + .align 2 +-.comm OPENSSL_armcap_P,4,4 ++.hidden OPENSSL_armcap_P + ___ + }}} + +--- a/crypto/sha/asm/sha512-armv8.pl 2019-09-10 15:13:07.000000000 +0200 ++++ b/crypto/sha/asm/sha512-armv8.pl 2020-01-10 16:03:59.641110272 +0100 +@@ -842,7 +842,7 @@ + + $code.=<<___; + #ifndef __KERNEL__ +-.comm OPENSSL_armcap_P,4,4 ++.hidden OPENSSL_armcap_P + #endif + ___ + +--- a/crypto/poly1305/asm/poly1305-armv8.pl 2019-09-10 15:13:07.000000000 +0200 ++++ b/crypto/poly1305/asm/poly1305-armv8.pl 2020-01-13 09:11:50.915315471 +0100 +@@ -93,9 +93,9 @@ + + tst w17,#ARMV7_NEON + +- adr $d0,poly1305_blocks ++ adr $d0,.Lpoly1305_blocks + adr $r0,poly1305_blocks_neon +- adr $d1,poly1305_emit ++ adr $d1,.Lpoly1305_emit + adr $r1,poly1305_emit_neon + + csel $d0,$d0,$r0,eq +@@ -115,6 +115,7 @@ + .type poly1305_blocks,%function + .align 5 + poly1305_blocks: ++.Lpoly1305_blocks: + ands $len,$len,#-16 + b.eq .Lno_data + +@@ -179,6 +180,7 @@ + .type poly1305_emit,%function + .align 5 + poly1305_emit: ++.Lpoly1305_emit: + ldp $h0,$h1,[$ctx] // load hash base 2^64 + ldr $h2,[$ctx,#16] + ldp $t0,$t1,[$nonce] // load nonce +@@ -288,7 +290,7 @@ + ldr $is_base2_26,[$ctx,#24] + cmp $len,#128 + b.hs .Lblocks_neon +- cbz $is_base2_26,poly1305_blocks ++ cbz $is_base2_26,.Lpoly1305_blocks + + .Lblocks_neon: + .inst 0xd503233f // paciasp +@@ -869,7 +871,7 @@ + .align 5 + poly1305_emit_neon: + ldr $is_base2_26,[$ctx,#24] +- cbz $is_base2_26,poly1305_emit ++ cbz $is_base2_26,.Lpoly1305_emit + + ldp w10,w11,[$ctx] // load hash value base 2^26 + ldp w12,w13,[$ctx,#8] diff --git a/build.gradle b/build.gradle index 8c494faa..30b0b0df 100644 --- a/build.gradle +++ b/build.gradle @@ -59,6 +59,10 @@ task buildOpenSsl { outputs.file("${buildDir}/openssl/bin/lib/libcrypto.a") dependsOn getOpensslSrc doLast { + // Remove this once the patch is incorporated into an official OpenSSL release + ant.patch(patchfile: "${projectDir}/arm.patch", + dir: "${buildDir}/openssl/src", + strip: 1) exec { workingDir "${buildDir}/openssl/src" commandLine './config', '-fPIC', '-ffunction-sections', '-fdata-sections', "--prefix=${buildDir}/openssl/bin", 'no-autoload-config', 'no-capieng', 'no-cms', 'no-comp', 'no-ct', 'no-dgram', 'no-devcryptoeng', 'no-gost', 'no-hw-padlock', 'no-nextprotoneg', 'no-ocsp', 'no-psk', 'no-rfc3779', 'no-shared', 'no-sock', 'no-srp', 'no-srtp', 'threads', 'no-ts', "no-bf", "no-cast", "no-md2", "no-rc2", "no-rc4", "no-rc5", "no-srp", 'no-comp', 'no-hw', 'no-mdc2' diff --git a/csrc/rdrand.cpp b/csrc/rdrand.cpp index 20a43416..ca31ecad 100644 --- a/csrc/rdrand.cpp +++ b/csrc/rdrand.cpp @@ -9,6 +9,7 @@ #include "rdrand.h" #include "keyutils.h" #include +#include #define DEFAULT_RETRY_COUNT 100 @@ -114,12 +115,15 @@ uint32_t get_cpuinfo() { return info; } + bool rng_rdrand(uint64_t *out) { if (unlikely(hook_rdrand)) { return (*hook_rdrand)(out); } bool success = 0; + +#if defined(__x86_64__) __asm__ __volatile__( ASM_RDRAND_RCX "setc %%al\n" // rax = 1 if success, 0 if fail @@ -127,7 +131,7 @@ bool rng_rdrand(uint64_t *out) { : "c" (0), "a" (0) : "cc" // clobbers condition codes ); - +#endif return success; } @@ -142,7 +146,9 @@ bool rng_rdseed(uint64_t *out) { return false; } - bool success; + bool success = 0; + +#if defined(__x86_64__) __asm__ __volatile__( ASM_RDSEED_RCX "setc %%al\n" // rax = 1 if success, 0 if fail @@ -150,13 +156,15 @@ bool rng_rdseed(uint64_t *out) { : "c" (0), "a" (0) : "cc" // clobbers condition codes ); - +#endif return success; } namespace { void pause_and_decrement(int &counter) { +#if defined(__x86_64__) + __asm__ __volatile__( // Intel recommends putting the PAUSE instruction (REP NOP) between rdrand/rdseed polls // c.f. https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide @@ -171,6 +179,9 @@ void pause_and_decrement(int &counter) { : : "cc" ); +#else + counter--; +#endif } bool rdseed_fallback(uint64_t *dest) COLD NOINLINE; @@ -324,6 +335,7 @@ bool rng_retry_rdseed(uint64_t *dest) { bool rd_into_buf(bool (*rng)(uint64_t *), unsigned char *buf, int len) { unsigned char *original_buf = buf; int original_len = len; +#if defined(__i386__) || defined(__x86_64__) while (len >= 8) { if (unlikely(!rng(reinterpret_cast(buf)))) { @@ -343,7 +355,9 @@ bool rd_into_buf(bool (*rng)(uint64_t *), unsigned char *buf, int len) { memcpy(buf, &remain, len); secureZero(&remain, 0); } - +#else + goto fail; +#endif return true; fail: // Wipe the buffer to make sure it's obvious if something is ignoring the return value @@ -356,7 +370,11 @@ bool rd_into_buf(bool (*rng)(uint64_t *), unsigned char *buf, int len) { // C++ Exported methods: bool supportsRdRand() { +#if defined(__i386__) || defined(__x86_64__) return !!(get_cpuinfo() & CPUID_HAS_RDRAND); +#else + return 0; +#endif } bool supportsRdSeed() { diff --git a/csrc/util.h b/csrc/util.h index 05136f2d..b5b70bf3 100644 --- a/csrc/util.h +++ b/csrc/util.h @@ -122,25 +122,13 @@ class pthread_lock_auto { }; #if __BYTE_ORDER == __LITTLE_ENDIAN -#define hostToBigEndian64(x) swapEndian(x) -#define bigEndianToHost64(x) swapEndian(x) +#define hostToBigEndian64(x) __builtin_bswap64(x) +#define bigEndianToHost64(x) __builtin_bswap64(x) #else #define hostToBigEndian64(x) (x) #define bigEndianToHost64(x) (x) #endif - -#if defined(__x86_64__) -static inline uint64_t swapEndian(uint64_t val) { - uint64_t result = val; - __asm__( - "bswap %0" - : "+r"(result) - ); - return result; -} -#endif - static inline void* fast_xor(void* dest, const void* src, int len) { int idx = 0; uint8_t* dest8 = (uint8_t*) dest; From 73a3949f999b56523d3744e7f315da652dd38fe0 Mon Sep 17 00:00:00 2001 From: Greg Rubin Date: Thu, 9 Apr 2020 17:32:17 +0000 Subject: [PATCH 2/2] Clarify requirements in README --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b5fd9c01..e5c19332 100644 --- a/README.md +++ b/README.md @@ -70,19 +70,18 @@ SecureRandom algorithms: * NIST800-90A/AES-CTR-256 (Used as the default and only enabled if your CPU supports RDRAND) -# Compatibility -This library is compatible with: -* OpenJDK 8 or newer (This includes [Amazon Corretto](https://aws.amazon.com/corretto/)) -* OracleJDK 8 or newer -* Linux x86_64 -* Linux ARM64/aarch64 **(EXPERIMENTAL)** +# Compatibility & Requirements +ACCP has the following requirements: +* JDK8 or newer (This includes both OracleJDK and [Amazon Corretto](https://aws.amazon.com/corretto/)) +* 64-bit Linux running on x86_64 (also known as x64 or AMD64) If ACCP is used/installed on a system it does not support, it will disable itself and the JVM will behave as if ACCP weren't installed at all. -ARM64/aarch64 support is currently experimental and not distributed via Maven. +**Experimental** support for aarch64 (64-bit ARM) Linux systems was added in version 1.4.0. +(This is as an alternative to fully supported 64-bit Linux on x86_64.) +aarch64 support is still **experimental** and is not yet distributed via Maven. If you want to experiment with ACCP on aarch64 platforms you will need to build it yourself as described later in this document. - # Using the provider ## Installation Installing via Maven or Gradle is the easiest way to get ACCP and ensure you