1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #include "tink/subtle/random.h"
18
19 #include <cstdint>
20 #include <string>
21
22 #include "absl/status/status.h"
23 #include "absl/strings/str_cat.h"
24 #include "absl/types/span.h"
25 #include "openssl/rand.h"
26 #include "tink/subtle/subtle_util.h"
27 #include "tink/util/status.h"
28
29 namespace crypto {
30 namespace tink {
31 namespace subtle {
32
33 namespace {
34
35 template <typename UintType>
GetRandomUint()36 UintType GetRandomUint() {
37 UintType result;
38 Random::GetRandomBytes(
39 absl::MakeSpan(reinterpret_cast<char *>(&result), sizeof(result)))
40 .IgnoreError();
41 return result;
42 }
43
44 } // namespace
45
46 // BoringSSL documentation says that it always returns 1; while
47 // OpenSSL documentation says that it returns "1 on success, -1 if not supported
48 // by the current RAND method, or 0 on other failure"
49 // (https://www.openssl.org/docs/man1.1.1/man3/RAND_bytes.html).
50 //
51 // In case of insufficient entropy at the time of the call, BoringSSL's
52 // RAND_bytes will behave in different ways depending on the operating system,
53 // version, and FIPS mode. For Linux with a semi-recent kernel, it will block
54 // until the system has collected at least 128 bits since boot. For old
55 // kernels without getrandom support (and not in FIPS mode), it will resort to
56 // /dev/urandom.
GetRandomBytes(absl::Span<char> buffer)57 util::Status Random::GetRandomBytes(absl::Span<char> buffer) {
58 auto buffer_ptr = reinterpret_cast<uint8_t *>(buffer.data());
59 if (RAND_bytes(buffer_ptr, buffer.size()) <= 0) {
60 return util::Status(absl::StatusCode::kInternal,
61 absl::StrCat("RAND_bytes failed to generate ",
62 buffer.size(), " bytes"));
63 }
64 return util::OkStatus();
65 }
66
GetRandomBytes(size_t length)67 std::string Random::GetRandomBytes(size_t length) {
68 std::string buffer;
69 ResizeStringUninitialized(&buffer, length);
70 // TODO(b/207466225): Modify the return to be a StatusOr<std::string> as
71 // OpenSSL can return an error.
72 GetRandomBytes(absl::MakeSpan(buffer)).IgnoreError();
73 return buffer;
74 }
75
GetRandomUInt32()76 uint32_t Random::GetRandomUInt32() { return GetRandomUint<uint32_t>(); }
GetRandomUInt16()77 uint16_t Random::GetRandomUInt16() { return GetRandomUint<uint16_t>(); }
GetRandomUInt8()78 uint8_t Random::GetRandomUInt8() { return GetRandomUint<uint8_t>(); }
79
GetRandomKeyBytes(size_t length)80 util::SecretData Random::GetRandomKeyBytes(size_t length) {
81 util::SecretData buf(length, 0);
82 GetRandomBytes(
83 absl::MakeSpan(reinterpret_cast<char *>(buf.data()), buf.size()))
84 .IgnoreError();
85 return buf;
86 }
87
88 } // namespace subtle
89 } // namespace tink
90 } // namespace crypto
91