blob: 7ab3e3b9c6effee4126151a4a45c5caf96566d3a [file] [log] [blame]
// Copyright 2018 Google Inc.
//
// 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/subtle/rsa_ssa_pkcs1_sign_boringssl.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/escaping.h"
#include "openssl/base.h"
#include "openssl/bn.h"
#include "openssl/rsa.h"
#include "tink/subtle/rsa_ssa_pkcs1_verify_boringssl.h"
#include "tink/subtle/subtle_util_boringssl.h"
#include "tink/util/test_matchers.h"
namespace crypto {
namespace tink {
namespace subtle {
namespace {
using ::crypto::tink::test::IsOk;
using ::crypto::tink::test::StatusIs;
using ::testing::IsEmpty;
using ::testing::Not;
class RsaPkcs1SignBoringsslTest : public ::testing::Test {
public:
RsaPkcs1SignBoringsslTest() : rsa_f4_(BN_new()) {
EXPECT_TRUE(BN_set_u64(rsa_f4_.get(), RSA_F4));
EXPECT_THAT(SubtleUtilBoringSSL::GetNewRsaKeyPair(
2048, rsa_f4_.get(), &private_key_, &public_key_),
IsOk());
}
protected:
bssl::UniquePtr<BIGNUM> rsa_f4_;
SubtleUtilBoringSSL::RsaPrivateKey private_key_;
SubtleUtilBoringSSL::RsaPublicKey public_key_;
};
TEST_F(RsaPkcs1SignBoringsslTest, EncodesPkcs1) {
SubtleUtilBoringSSL::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256};
auto signer_or = RsaSsaPkcs1SignBoringSsl::New(private_key_, params);
ASSERT_THAT(signer_or.status(), IsOk());
auto signature_or = signer_or.ValueOrDie()->Sign("testdata");
ASSERT_THAT(signature_or.status(), IsOk());
EXPECT_THAT(signature_or.ValueOrDie(), Not(IsEmpty()));
auto verifier_or = RsaSsaPkcs1VerifyBoringSsl::New(public_key_, params);
ASSERT_THAT(verifier_or.status(), IsOk());
EXPECT_THAT(
verifier_or.ValueOrDie()->Verify(signature_or.ValueOrDie(), "testdata"),
IsOk());
}
TEST_F(RsaPkcs1SignBoringsslTest, EncodesPkcs1WithSeparateHashes) {
SubtleUtilBoringSSL::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256};
auto signer_or = RsaSsaPkcs1SignBoringSsl::New(private_key_, params);
ASSERT_THAT(signer_or.status(), IsOk());
auto signature_or = signer_or.ValueOrDie()->Sign("testdata");
ASSERT_THAT(signature_or.status(), IsOk());
EXPECT_THAT(signature_or.ValueOrDie(), Not(IsEmpty()));
auto verifier_or = RsaSsaPkcs1VerifyBoringSsl::New(public_key_, params);
ASSERT_THAT(verifier_or.status(), IsOk());
EXPECT_THAT(
verifier_or.ValueOrDie()->Verify(signature_or.ValueOrDie(), "testdata"),
IsOk());
}
TEST_F(RsaPkcs1SignBoringsslTest, RejectsUnsafeHash) {
SubtleUtilBoringSSL::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA1};
ASSERT_THAT(RsaSsaPkcs1SignBoringSsl::New(private_key_, params).status(),
StatusIs(util::error::INVALID_ARGUMENT));
}
TEST_F(RsaPkcs1SignBoringsslTest, RejectsInvalidCrtParams) {
SubtleUtilBoringSSL::RsaSsaPkcs1Params params{/*sig_hash=*/HashType::SHA256};
ASSERT_THAT(private_key_.crt, Not(IsEmpty()));
ASSERT_THAT(private_key_.dq, Not(IsEmpty()));
ASSERT_THAT(private_key_.dp, Not(IsEmpty()));
// Flip a few bits in the CRT parameters; check that creation fails.
{
SubtleUtilBoringSSL::RsaPrivateKey key = private_key_;
key.crt[0] ^= 0x80;
auto signer_or = RsaSsaPkcs1SignBoringSsl::New(key, params);
EXPECT_THAT(signer_or.status(), StatusIs(util::error::INVALID_ARGUMENT));
}
{
SubtleUtilBoringSSL::RsaPrivateKey key = private_key_;
key.dq[0] ^= 0x08;
auto signer_or = RsaSsaPkcs1SignBoringSsl::New(key, params);
EXPECT_THAT(signer_or.status(), StatusIs(util::error::INVALID_ARGUMENT));
}
{
SubtleUtilBoringSSL::RsaPrivateKey key = private_key_;
key.dp[0] ^= 0x04;
auto signer_or = RsaSsaPkcs1SignBoringSsl::New(key, params);
EXPECT_THAT(signer_or.status(), StatusIs(util::error::INVALID_ARGUMENT));
}
}
} // namespace
} // namespace subtle
} // namespace tink
} // namespace crypto