Skip to content

Commit

Permalink
Add RsaSsaPssParameters object in C++.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 581240807
Change-Id: Ib416d27028e60a08e09eb3423767b4f826d14f7a
  • Loading branch information
ioannanedelcu authored and copybara-github committed Nov 10, 2023
1 parent d018008 commit 6042a12
Show file tree
Hide file tree
Showing 5 changed files with 1,005 additions and 0 deletions.
38 changes: 38 additions & 0 deletions tink/signature/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,28 @@ cc_library(
],
)

cc_library(
name = "rsa_ssa_pss_parameters",
srcs = ["rsa_ssa_pss_parameters.cc"],
hdrs = ["rsa_ssa_pss_parameters.h"],
include_prefix = "tink/signature",
deps = [
":signature_parameters",
"//tink:big_integer",
"//tink:parameters",
"//tink/internal:bn_util",
"//tink/internal:rsa_util",
"//tink/internal:ssl_unique_ptr",
"//tink/util:status",
"//tink/util:statusor",
"@boringssl//:crypto",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:string_view",
"@com_google_absl//absl/types:optional",
],
)

# tests

cc_test(
Expand Down Expand Up @@ -1206,3 +1228,19 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "rsa_ssa_pss_parameters_test",
srcs = ["rsa_ssa_pss_parameters_test.cc"],
deps = [
":rsa_ssa_pss_parameters",
"//tink:big_integer",
"//tink/internal:bn_util",
"//tink/internal:ssl_unique_ptr",
"//tink/util:statusor",
"//tink/util:test_matchers",
"@boringssl//:crypto",
"@com_google_absl//absl/status",
"@com_google_googletest//:gtest_main",
],
)
37 changes: 37 additions & 0 deletions tink/signature/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,27 @@ tink_cc_library(
tink::proto::tink_cc_proto
)

tink_cc_library(
NAME rsa_ssa_pss_parameters
SRCS
rsa_ssa_pss_parameters.cc
rsa_ssa_pss_parameters.h
DEPS
tink::signature::signature_parameters
absl::status
absl::strings
absl::string_view
absl::optional
crypto
tink::core::big_integer
tink::core::parameters
tink::internal::bn_util
tink::internal::rsa_util
tink::internal::ssl_unique_ptr
tink::util::status
tink::util::statusor
)

# tests

tink_cc_test(
Expand Down Expand Up @@ -1160,3 +1181,19 @@ tink_cc_test(
tink::proto::rsa_ssa_pkcs1_cc_proto
tink::proto::tink_cc_proto
)

tink_cc_test(
NAME rsa_ssa_pss_parameters_test
SRCS
rsa_ssa_pss_parameters_test.cc
DEPS
tink::signature::rsa_ssa_pss_parameters
gmock
absl::status
crypto
tink::core::big_integer
tink::internal::bn_util
tink::internal::ssl_unique_ptr
tink::util::statusor
tink::util::test_matchers
)
204 changes: 204 additions & 0 deletions tink/signature/rsa_ssa_pss_parameters.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

#include "tink/signature/rsa_ssa_pss_parameters.h"

#include <set>
#include <string>

#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#ifdef OPENSSL_IS_BORINGSSL
#include "openssl/base.h"
#else
#include "openssl/bn.h"
#endif
#include "tink/big_integer.h"
#include "tink/internal/bn_util.h"
#include "tink/internal/rsa_util.h"
#include "tink/internal/ssl_unique_ptr.h"
#include "tink/parameters.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"

namespace crypto {
namespace tink {
namespace {

constexpr int kF4 = 65537;

} // namespace

RsaSsaPssParameters::Builder&
RsaSsaPssParameters::Builder::SetModulusSizeInBits(int modulus_size_in_bits) {
modulus_size_in_bits_ = modulus_size_in_bits;
return *this;
}

RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetPublicExponent(
const BigInteger& public_exponent) {
public_exponent_ = public_exponent;
return *this;
}

RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetSigHashType(
HashType sig_hash_type) {
sig_hash_type_ = sig_hash_type;
return *this;
}

RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetMgf1HashType(
HashType mgf1_hash_type) {
mgf1_hash_type_ = mgf1_hash_type;
return *this;
}

RsaSsaPssParameters::Builder&
RsaSsaPssParameters::Builder::SetSaltLengthInBytes(int salt_length_in_bytes) {
salt_length_in_bytes_ = salt_length_in_bytes;
return *this;
}

RsaSsaPssParameters::Builder& RsaSsaPssParameters::Builder::SetVariant(
Variant variant) {
variant_ = variant;
return *this;
}

util::StatusOr<RsaSsaPssParameters> RsaSsaPssParameters::Builder::Build() {
if (!modulus_size_in_bits_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Key size is not set.");
}

if (!sig_hash_type_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Signature hash type is not set.");
}

if (!mgf1_hash_type_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"MGF1 hash type is not set.");
}

if (!salt_length_in_bytes_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Salt length is not set.");
}

if (!variant_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Variant is not set.");
}

if (*salt_length_in_bytes_ < 0) {
return util::Status(
absl::StatusCode::kInvalidArgument,
absl::StrCat("Invalid salt length in bytes: ", *salt_length_in_bytes_,
". Salt length must be positive."));
}

// Validate hash.
static const std::set<HashType>* supported_hashes = new std::set<HashType>(
{HashType::kSha256, HashType::kSha384, HashType::kSha512});

if (supported_hashes->find(*sig_hash_type_) == supported_hashes->end()) {
return util::Status(
absl::StatusCode::kInvalidArgument,
"Cannot create RsaSsaPss parameters with unknown SigHashType.");
}

if (supported_hashes->find(*mgf1_hash_type_) == supported_hashes->end()) {
return util::Status(
absl::StatusCode::kInvalidArgument,
"Cannot create RsaSsaPss parameters with unknown Mgf1HashType.");
}

if (*sig_hash_type_ != *mgf1_hash_type_) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Signature hash type and MGF1 hash type should match.");
}

// Validate modulus size.
if (*modulus_size_in_bits_ < 2048) {
return util::Status(
absl::StatusCode::kInvalidArgument,
absl::StrCat("Invalid key size: must be at least 2048 bits, got ",
*modulus_size_in_bits_, " bits."));
}

// Validate the public exponent: public exponent needs to be odd, greater than
// 65536 and (for consistency with BoringSSL), smaller that 32 bits.
util::Status exponent_status =
internal::ValidateRsaPublicExponent(public_exponent_.GetValue());
if (!exponent_status.ok()) {
return exponent_status;
}

// Validate variant.
static const std::set<Variant>* supported_variants =
new std::set<Variant>({Variant::kTink, Variant::kCrunchy,
Variant::kLegacy, Variant::kNoPrefix});
if (supported_variants->find(*variant_) == supported_variants->end()) {
return util::Status(
absl::StatusCode::kInvalidArgument,
"Cannot create RsaSsaPss parameters with unknown variant.");
}
return RsaSsaPssParameters(*modulus_size_in_bits_, public_exponent_,
*sig_hash_type_, *mgf1_hash_type_,
*salt_length_in_bytes_, *variant_);
}

bool RsaSsaPssParameters::operator==(const Parameters& other) const {
const RsaSsaPssParameters* that =
dynamic_cast<const RsaSsaPssParameters*>(&other);
if (that == nullptr) {
return false;
}
if (modulus_size_in_bits_ != that->modulus_size_in_bits_) {
return false;
}
if (public_exponent_ != that->public_exponent_) {
return false;
}
if (sig_hash_type_ != that->sig_hash_type_) {
return false;
}
if (mgf1_hash_type_ != that->mgf1_hash_type_) {
return false;
}
if (salt_length_in_bytes_ != that->salt_length_in_bytes_) {
return false;
}
if (variant_ != that->variant_) {
return false;
}
return true;
}

// Returns the big endian encoded F4 value as a public exponent default.
BigInteger RsaSsaPssParameters::Builder::CreateDefaultPublicExponent() {
internal::SslUniquePtr<BIGNUM> e(BN_new());
BN_set_word(e.get(), kF4);

std::string F4_string =
internal::BignumToString(e.get(), BN_num_bytes(e.get())).value();
return BigInteger(F4_string);
}

} // namespace tink
} // namespace crypto
Loading

0 comments on commit 6042a12

Please sign in to comment.