Skip to content

Commit

Permalink
Add RsaSsaPkcs1PrivateKey in C++.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 576124993
Change-Id: I2c5c1a35a9b5174150430d0bf0ac65b2386be9fe
  • Loading branch information
ioannanedelcu authored and copybara-github committed Oct 24, 2023
1 parent 00e4b50 commit 57b84a1
Show file tree
Hide file tree
Showing 5 changed files with 1,259 additions and 0 deletions.
48 changes: 48 additions & 0 deletions tink/signature/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,30 @@ cc_library(
],
)

cc_library(
name = "rsa_ssa_pkcs1_private_key",
srcs = ["rsa_ssa_pkcs1_private_key.cc"],
hdrs = ["rsa_ssa_pkcs1_private_key.h"],
include_prefix = "tink/signature",
deps = [
":rsa_ssa_pkcs1_public_key",
":signature_private_key",
"//tink:big_integer",
"//tink:insecure_secret_key_access",
"//tink:key",
"//tink:partial_key_access_token",
"//tink:restricted_big_integer",
"//tink/internal:bn_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/types:optional",
],
)

# tests

cc_test(
Expand Down Expand Up @@ -1028,3 +1052,27 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "rsa_ssa_pkcs1_private_key_test",
srcs = ["rsa_ssa_pkcs1_private_key_test.cc"],
deps = [
":rsa_ssa_pkcs1_parameters",
":rsa_ssa_pkcs1_private_key",
":rsa_ssa_pkcs1_public_key",
"//tink:big_integer",
"//tink:insecure_secret_key_access",
"//tink:partial_key_access",
"//tink:restricted_big_integer",
"//tink/internal:bn_util",
"//tink/internal:ssl_unique_ptr",
"//tink/util:statusor",
"//tink/util:test_matchers",
"@boringssl//:crypto",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:optional",
"@com_google_googletest//:gtest_main",
],
)
47 changes: 47 additions & 0 deletions tink/signature/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,29 @@ tink_cc_library(
tink::util::statusor
)

tink_cc_library(
NAME rsa_ssa_pkcs1_private_key
SRCS
rsa_ssa_pkcs1_private_key.cc
rsa_ssa_pkcs1_private_key.h
DEPS
tink::signature::rsa_ssa_pkcs1_public_key
tink::signature::signature_private_key
absl::status
absl::strings
absl::optional
crypto
tink::core::big_integer
tink::core::insecure_secret_key_access
tink::core::key
tink::core::partial_key_access_token
tink::core::restricted_big_integer
tink::internal::bn_util
tink::internal::ssl_unique_ptr
tink::util::status
tink::util::statusor
)

# tests

tink_cc_test(
Expand Down Expand Up @@ -986,3 +1009,27 @@ tink_cc_test(
tink::util::statusor
tink::util::test_matchers
)

tink_cc_test(
NAME rsa_ssa_pkcs1_private_key_test
SRCS
rsa_ssa_pkcs1_private_key_test.cc
DEPS
tink::signature::rsa_ssa_pkcs1_parameters
tink::signature::rsa_ssa_pkcs1_private_key
tink::signature::rsa_ssa_pkcs1_public_key
gmock
absl::check
absl::status
absl::strings
absl::optional
crypto
tink::core::big_integer
tink::core::insecure_secret_key_access
tink::core::partial_key_access
tink::core::restricted_big_integer
tink::internal::bn_util
tink::internal::ssl_unique_ptr
tink::util::statusor
tink::util::test_matchers
)
244 changes: 244 additions & 0 deletions tink/signature/rsa_ssa_pkcs1_private_key.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
// 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_pkcs1_private_key.h"

#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#ifdef OPENSSL_IS_BORINGSSL
#include "openssl/base.h"
#endif
#include "openssl/rsa.h"
#include "tink/big_integer.h"
#include "tink/insecure_secret_key_access.h"
#include "tink/internal/bn_util.h"
#include "tink/internal/ssl_unique_ptr.h"
#include "tink/key.h"
#include "tink/partial_key_access_token.h"
#include "tink/restricted_big_integer.h"
#include "tink/signature/rsa_ssa_pkcs1_public_key.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"

namespace crypto {
namespace tink {
namespace {

util::Status ValidateKeyPair(
absl::string_view public_exponent, const BigInteger& modulus,
const RestrictedBigInteger& p, const RestrictedBigInteger& q,
const RestrictedBigInteger& d, const RestrictedBigInteger& dp,
const RestrictedBigInteger& dq, const RestrictedBigInteger& q_inv) {
internal::SslUniquePtr<RSA> rsa(RSA_new());
if (rsa.get() == nullptr) {
return util::Status(absl::StatusCode::kInternal,
"Internal RSA allocation error");
}

util::StatusOr<internal::SslUniquePtr<BIGNUM>> n =
internal::StringToBignum(modulus.GetValue());
if (!n.ok()) {
return n.status();
}

util::StatusOr<internal::SslUniquePtr<BIGNUM>> e =
internal::StringToBignum(public_exponent);
if (!e.ok()) {
return e.status();
}

util::StatusOr<internal::SslUniquePtr<BIGNUM>> d_bn =
internal::StringToBignum(d.GetSecret(InsecureSecretKeyAccess::Get()));
if (!d_bn.ok()) {
return d_bn.status();
}

util::StatusOr<internal::SslUniquePtr<BIGNUM>> p_bn =
internal::StringToBignum(p.GetSecret(InsecureSecretKeyAccess::Get()));
if (!p_bn.ok()) {
return p_bn.status();
}
util::StatusOr<internal::SslUniquePtr<BIGNUM>> q_bn =
internal::StringToBignum(q.GetSecret(InsecureSecretKeyAccess::Get()));
if (!q_bn.ok()) {
return q_bn.status();
}

util::StatusOr<internal::SslUniquePtr<BIGNUM>> dp_bn =
internal::StringToBignum(dp.GetSecret(InsecureSecretKeyAccess::Get()));
if (!dp_bn.ok()) {
return dp_bn.status();
}
util::StatusOr<internal::SslUniquePtr<BIGNUM>> dq_bn =
internal::StringToBignum(dq.GetSecret(InsecureSecretKeyAccess::Get()));
if (!dq_bn.ok()) {
return dq_bn.status();
}
util::StatusOr<internal::SslUniquePtr<BIGNUM>> q_inv_bn =
internal::StringToBignum(q_inv.GetSecret(InsecureSecretKeyAccess::Get()));
if (!q_inv_bn.ok()) {
return q_inv_bn.status();
}

// Build RSA key from the given values. The RSA object takes ownership of the
// given values after the call.
if (RSA_set0_key(rsa.get(), n->release(), e->release(), d_bn->release()) !=
1 ||
RSA_set0_factors(rsa.get(), p_bn->release(), q_bn->release()) != 1 ||
RSA_set0_crt_params(rsa.get(), dp_bn->release(), dq_bn->release(),
q_inv_bn->release()) != 1) {
return util::Status(absl::StatusCode::kInternal,
"Internal RSA key loading error");
}

// Validate key.
int check_key_status = RSA_check_key(rsa.get());
if (check_key_status == 0) {
return util::Status(absl::StatusCode::kInvalidArgument,
"RSA key pair is not valid");
}

if (check_key_status == -1) {
return util::Status(absl::StatusCode::kInternal,
"An error ocurred while checking the key");
}

#ifdef OPENSSL_IS_BORINGSSL
if (RSA_check_fips(rsa.get()) == 0) {
return util::Status(absl::StatusCode::kInvalidArgument,
"RSA key pair is not valid in FIPS mode");
}
#endif

return util::OkStatus();
}

} // namespace

RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPublicKey(
const RsaSsaPkcs1PublicKey& public_key) {
public_key_ = public_key;
return *this;
}

RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPrimeP(
const RestrictedBigInteger& p) {
p_ = p;
return *this;
}

RsaSsaPkcs1PrivateKey::Builder& RsaSsaPkcs1PrivateKey::Builder::SetPrimeQ(
const RestrictedBigInteger& q) {
q_ = q;
return *this;
}

RsaSsaPkcs1PrivateKey::Builder&
RsaSsaPkcs1PrivateKey::Builder::SetPrimeExponentP(
const RestrictedBigInteger& dp) {
dp_ = dp;
return *this;
}

RsaSsaPkcs1PrivateKey::Builder&
RsaSsaPkcs1PrivateKey::Builder::SetPrimeExponentQ(
const RestrictedBigInteger& dq) {
dq_ = dq;
return *this;
}

RsaSsaPkcs1PrivateKey::Builder&
RsaSsaPkcs1PrivateKey::Builder::SetPrivateExponent(
const RestrictedBigInteger& d) {
d_ = d;
return *this;
}

RsaSsaPkcs1PrivateKey::Builder&
RsaSsaPkcs1PrivateKey::Builder::SetCrtCoefficient(
const RestrictedBigInteger& q_inv) {
q_inv_ = q_inv;
return *this;
}

util::StatusOr<RsaSsaPkcs1PrivateKey> RsaSsaPkcs1PrivateKey::Builder::Build(
PartialKeyAccessToken token) {
if (!public_key_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Cannot build without setting the public key");
}

if (!p_.has_value() || !q_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Cannot build without setting both prime factors");
}

if (!dp_.has_value() || !dq_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Cannot build without setting both prime exponents");
}

if (!d_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Cannot build without setting the private exponent");
}

if (!q_inv_.has_value()) {
return util::Status(absl::StatusCode::kInvalidArgument,
"Cannot build without setting the CRT coefficient");
}

// Validate key pair.
util::Status key_pair_validation = ValidateKeyPair(
public_key_->GetParameters().GetPublicExponent(),
public_key_->GetModulus(token), *p_, *q_, *d_, *dp_, *dq_, *q_inv_);
if (!key_pair_validation.ok()) {
return key_pair_validation;
}

return RsaSsaPkcs1PrivateKey(*public_key_, *p_, *q_, *dp_, *dq_, *d_,
*q_inv_);
}

bool RsaSsaPkcs1PrivateKey::operator==(const Key& other) const {
const RsaSsaPkcs1PrivateKey* that =
dynamic_cast<const RsaSsaPkcs1PrivateKey*>(&other);
if (that == nullptr) {
return false;
}
if (GetPublicKey() != that->GetPublicKey()) {
return false;
}
if (p_ != that->p_) {
return false;
}
if (q_ != that->q_) {
return false;
}
if (dp_ != that->dp_) {
return false;
}
if (dq_ != that->dq_) {
return false;
}
if (d_ != that->d_) {
return false;
}
return q_inv_ == that->q_inv_;
}

} // namespace tink
} // namespace crypto
Loading

0 comments on commit 57b84a1

Please sign in to comment.