vqsort.cc (3737B)
1 // Copyright 2021 Google LLC 2 // SPDX-License-Identifier: Apache-2.0 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #include "hwy/contrib/sort/vqsort.h" 17 18 #include "hwy/base.h" 19 #include "hwy/contrib/sort/vqsort-inl.h" 20 #include "hwy/per_target.h" 21 22 // Check if we have getrandom from <sys/random.h>. Because <features.h> is 23 // unavailable on Android and non-Linux RVV, we assume that those systems lack 24 // getrandom. Note that the only supported sources of entropy are getrandom or 25 // Windows, thus VQSORT_SECURE_SEED=0 when this is 0 and we are not on Windows. 26 #if defined(ANDROID) || defined(__ANDROID__) || \ 27 (HWY_ARCH_RISCV && !HWY_OS_LINUX) 28 #define VQSORT_GETRANDOM 0 29 #endif 30 31 #if !defined(VQSORT_GETRANDOM) && HWY_OS_LINUX 32 #include <features.h> 33 34 // ---- which libc 35 #if defined(__UCLIBC__) 36 #define VQSORT_GETRANDOM 1 // added Mar 2015, before uclibc-ng 1.0 37 38 #elif defined(__GLIBC__) && defined(__GLIBC_PREREQ) 39 #if __GLIBC_PREREQ(2, 25) 40 #define VQSORT_GETRANDOM 1 41 #else 42 #define VQSORT_GETRANDOM 0 43 #endif 44 45 #else 46 // Assume MUSL, which has getrandom since 2018. There is no macro to test, see 47 // https://www.openwall.com/lists/musl/2013/03/29/13. 48 #define VQSORT_GETRANDOM 1 49 50 #endif // ---- which libc 51 #endif // linux 52 53 #if !defined(VQSORT_GETRANDOM) 54 #define VQSORT_GETRANDOM 0 55 #endif 56 57 // Choose a seed source for SFC generator: 1=getrandom, 2=CryptGenRandom. 58 // Allow user override - not all Android support the getrandom wrapper. 59 #ifndef VQSORT_SECURE_SEED 60 61 #if VQSORT_GETRANDOM 62 #define VQSORT_SECURE_SEED 1 63 #elif defined(_WIN32) || defined(_WIN64) 64 #define VQSORT_SECURE_SEED 2 65 #else 66 #define VQSORT_SECURE_SEED 0 67 #endif 68 69 #endif // VQSORT_SECURE_SEED 70 71 // Pull in dependencies of the chosen seed source. 72 #if VQSORT_SECURE_SEED == 1 73 #include <sys/random.h> 74 #elif VQSORT_SECURE_SEED == 2 75 #ifndef NOMINMAX 76 #define NOMINMAX 77 #endif // NOMINMAX 78 #ifndef WIN32_LEAN_AND_MEAN 79 #define WIN32_LEAN_AND_MEAN 80 #endif // WIN32_LEAN_AND_MEAN 81 #include <windows.h> 82 #if HWY_COMPILER_MSVC || HWY_COMPILER_CLANGCL 83 #pragma comment(lib, "advapi32.lib") 84 #endif // HWY_COMPILER_MSVC || HWY_COMPILER_CLANGCL 85 // Must come after windows.h. 86 #include <wincrypt.h> 87 #endif // VQSORT_SECURE_SEED 88 89 namespace hwy { 90 91 // Returns false or performs the equivalent of `memcpy(bytes, r, 16)`, where r 92 // is high-quality (unpredictable, uniformly distributed) random bits. 93 bool Fill16BytesSecure(void* bytes) { 94 #if VQSORT_SECURE_SEED == 1 95 // May block if urandom is not yet initialized. 96 const ssize_t ret = getrandom(bytes, 16, /*flags=*/0); 97 if (ret == 16) return true; 98 #elif VQSORT_SECURE_SEED == 2 99 HCRYPTPROV hProvider{}; 100 if (CryptAcquireContextA(&hProvider, nullptr, nullptr, PROV_RSA_FULL, 101 CRYPT_VERIFYCONTEXT)) { 102 const BOOL ok = 103 CryptGenRandom(hProvider, 16, reinterpret_cast<BYTE*>(bytes)); 104 CryptReleaseContext(hProvider, 0); 105 if (ok) return true; 106 } 107 #else 108 (void)bytes; 109 #endif 110 111 return false; 112 } 113 114 // Unused, only for ABI compatibility 115 void Sorter::Fill24Bytes(const void*, size_t, void*) {} 116 bool Sorter::HaveFloat64() { return hwy::HaveFloat64(); } 117 Sorter::Sorter() {} 118 void Sorter::Delete() {} 119 uint64_t* GetGeneratorState() { return hwy::detail::GetGeneratorStateStatic(); } 120 121 } // namespace hwy