Skip to content

Commit

Permalink
crypto: Added support for random generation
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Boquard <[email protected]>
  • Loading branch information
michael-redpanda committed Mar 5, 2024
1 parent 282e665 commit ec0b9ac
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/v/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ v_cc_library(
digest.cc
hmac.cc
key.cc
random.cc
signature.cc
ssl_utils.cc
DEPS
Expand Down
28 changes: 19 additions & 9 deletions src/v/crypto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ auto key = crypto::key::load_rsa_public_key(modulus, public_exponent);

## Signature Verification

Performing signature verification can be done either one-shot or multi part.
Performing signature verification can be done either one-shot or multi part.

One-shot:
One-shot:

```c++
#include "crypto/crypto.h"
```c++
#include "crypto/crypto.h"

auto key = {...};
bytes msg {...};
Expand All @@ -123,12 +123,12 @@ auto sig_verified = crypto::verify_signature(
msg,
sig
);
```
```
For multi-part:
For multi-part:
```c++
#include "crypto/crypto.h"
```c++
#include "crypto/crypto.h"
auto key = {...};
bytes msg {...};
Expand All @@ -137,4 +137,14 @@ bytes sig {...};
crypto::verify_ctx ctx(crypto::digest_type::SHA256, key);
ctx.update(msg);
bool verified = std::move(ctx).final(sig);
```
```

## RNG Generation

To get cryptographically secure random data, please use
`crypto::generate_random`. There are two functions you can use. One will
place random data into the provided buffer and another will return an allocated
buffer with random data. Both functions also have a flag to indicate if the caller
wants to use the 'private' DRBG. For more information on this please refer to
OpenSSL's [documentation](https://www.openssl.org/docs/man3.0/man3/RAND_priv_bytes.html)
on this.
32 changes: 32 additions & 0 deletions src/v/crypto/include/crypto/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,36 @@ bool verify_signature(
digest_type type, const key& key, bytes_view msg, bytes_view sig);
bool verify_signature(
digest_type type, const key& key, std::string_view msg, std::string_view sig);

///////////////////////////////////////////////////////////////////////////////
/// DRBG operation
///////////////////////////////////////////////////////////////////////////////

using use_private_rng = ss::bool_class<struct use_private_rng_tag>;

/**
* Used to generate some random data and stick it into a provided buffer
*
* @param buf The buffer to place random data into
* @param private_rng Whether or not to use the 'private' DRBG
* @note For private vs public, please see:
* https://www.openssl.org/docs/man3.0/man3/RAND_priv_bytes.html
* @return bytes_span<> The buffer
* @throws crypto::exception On internal error
*/
bytes_span<> generate_random(
bytes_span<> buf, use_private_rng private_rng = use_private_rng::no);

/**
* Generates the requested number of random bytes
*
* @param len The amount of data to generate
* @param private_rng Whether or not to use the 'private' DRBG
* @note For private vs public, please see:
* https://www.openssl.org/docs/man3.0/man3/RAND_priv_bytes.html
* @return bytes The buffer of random data
* @throws crypto::exception On internal error
*/
bytes generate_random(
size_t len, use_private_rng private_rng = use_private_rng::no);
} // namespace crypto
40 changes: 40 additions & 0 deletions src/v/crypto/random.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2024 Redpanda Data, Inc.
*
* Use of this software is governed by the Business Source License
* included in the file licenses/BSL.md
*
* As of the Change Date specified in that file, in accordance with
* the Business Source License, use of this software will be governed
* by the Apache License, Version 2.0
*/

#include "crypto/crypto.h"
#include "crypto/ssl_utils.h"
#include "internal.h"

#include <openssl/rand.h>

namespace crypto {
bytes_span<> generate_random(bytes_span<> buf, use_private_rng private_rng) {
if (private_rng) {
if (1 != RAND_priv_bytes_ex(nullptr, buf.data(), buf.size(), 0)) {
throw internal::ossl_error(
"Failed to get random output from private RNG");
}
} else {
if (1 != RAND_bytes_ex(nullptr, buf.data(), buf.size(), 0)) {
throw internal::ossl_error(
"Failed to get random output from public RNG");
}
}

return buf;
}

bytes generate_random(size_t len, use_private_rng private_rng) {
bytes ret(bytes::initialized_later(), len);
generate_random(ret, private_rng);
return ret;
}
} // namespace crypto
1 change: 1 addition & 0 deletions src/v/crypto/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ rp_test(
digest_tests.cc
hmac_tests.cc
key_tests.cc
random_tests.cc
signature_tests.cc
LIBRARIES
v::crypto
Expand Down
41 changes: 41 additions & 0 deletions src/v/crypto/test/random_tests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2024 Redpanda Data, Inc.
*
* Use of this software is governed by the Business Source License
* included in the file licenses/BSL.md
*
* As of the Change Date specified in that file, in accordance with
* the Business Source License, use of this software will be governed
* by the Apache License, Version 2.0
*/

#include "crypto/crypto.h"
#include "test_utils/test.h"

#include <gtest/gtest.h>

TEST(crypto_rand, generate_rand) {
const size_t len = 32;
auto ret = crypto::generate_random(len, crypto::use_private_rng::no);
ASSERT_EQ(ret.size(), len);
}

TEST(crypto_rand, generate_rand_priv) {
const size_t len = 32;
auto ret = crypto::generate_random(len, crypto::use_private_rng::yes);
ASSERT_EQ(ret.size(), len);
}

TEST(crypto_rand, generate_rand_span) {
std::vector<uint8_t> rand_data(32);
auto copy_of_orig = rand_data;
crypto::generate_random(rand_data, crypto::use_private_rng::no);
ASSERT_NE(copy_of_orig, rand_data);
}

TEST(crypto_rand, generate_rand_span_private) {
std::vector<uint8_t> rand_data(32);
auto copy_of_orig = rand_data;
crypto::generate_random(rand_data, crypto::use_private_rng::yes);
ASSERT_NE(copy_of_orig, rand_data);
}

0 comments on commit ec0b9ac

Please sign in to comment.