blob: 06ea6c34396e60239ad9c238e153a18a01da6802 [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
#include "android/misc/Random.h"
#include "android/base/files/ScopedStdioFile.h"
#include "android/utils/debug.h"
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
#endif
#define E(...) derror(__VA_ARGS__)
using android::base::ScopedStdioFile;
namespace android {
bool generateRandomBytes(char* buf, size_t buf_len) {
#ifdef _WIN32
HCRYPTPROV hCryptProv;
DWORD dwFlags = CRYPT_VERIFYCONTEXT | CRYPT_SILENT;
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, dwFlags)) {
if (GetLastError() == (DWORD)NTE_BAD_KEYSET) {
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
dwFlags | CRYPT_NEWKEYSET)) {
return false;
}
}
}
BOOL ok = CryptGenRandom(hCryptProv, buf_len, (BYTE*)buf);
CryptReleaseContext(hCryptProv, 0);
if (!ok) {
E("Can't read from CryptGenRandom");
return false;
}
return true;
#else
ScopedStdioFile fp(fopen("/dev/urandom", "rb"));
if (fp.get() == nullptr) {
E("Can't open /dev/urandom");
return false;
}
size_t err = fread(buf, 1, buf_len, fp.get());
if (err != buf_len) {
E("Can't read from /dev/urandom");
return false;
}
return true;
#endif
}
} // namespace android