xref: /aosp_15_r20/external/tink/cc/subtle/random.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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