1 // Copyright 2018 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/rsa_ssa_pkcs1_verify_boringssl.h"
18
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "absl/status/status.h"
24 #include "absl/strings/str_cat.h"
25 #include "openssl/bn.h"
26 #include "openssl/evp.h"
27 #include "openssl/rsa.h"
28 #include "tink/internal/md_util.h"
29 #include "tink/internal/rsa_util.h"
30 #include "tink/internal/ssl_unique_ptr.h"
31 #include "tink/internal/util.h"
32 #include "tink/subtle/common_enums.h"
33 #include "tink/util/errors.h"
34 #include "tink/util/statusor.h"
35
36 namespace crypto {
37 namespace tink {
38 namespace subtle {
39
40 util::StatusOr<std::unique_ptr<RsaSsaPkcs1VerifyBoringSsl>>
New(const internal::RsaPublicKey & pub_key,const internal::RsaSsaPkcs1Params & params)41 RsaSsaPkcs1VerifyBoringSsl::New(const internal::RsaPublicKey& pub_key,
42 const internal::RsaSsaPkcs1Params& params) {
43 util::Status status =
44 internal::CheckFipsCompatibility<RsaSsaPkcs1VerifyBoringSsl>();
45 if (!status.ok()) {
46 return status;
47 }
48
49 // Check if the hash type is safe to use.
50 util::Status is_safe = internal::IsHashTypeSafeForSignature(params.hash_type);
51 if (!is_safe.ok()) {
52 return is_safe;
53 }
54
55 util::StatusOr<const EVP_MD*> sig_hash =
56 internal::EvpHashFromHashType(params.hash_type);
57 if (!sig_hash.ok()) {
58 return sig_hash.status();
59 }
60
61 // The RSA modulus and exponent are checked as part of the conversion to
62 // internal::SslUniquePtr<RSA>.
63 util::StatusOr<internal::SslUniquePtr<RSA>> rsa =
64 internal::RsaPublicKeyToRsa(pub_key);
65 if (!rsa.ok()) {
66 return rsa.status();
67 }
68
69 std::unique_ptr<RsaSsaPkcs1VerifyBoringSsl> verify(
70 new RsaSsaPkcs1VerifyBoringSsl(*std::move(rsa), *sig_hash));
71 return std::move(verify);
72 }
73
Verify(absl::string_view signature,absl::string_view data) const74 util::Status RsaSsaPkcs1VerifyBoringSsl::Verify(absl::string_view signature,
75 absl::string_view data) const {
76 // BoringSSL expects a non-null pointer for data,
77 // regardless of whether the size is 0.
78 data = internal::EnsureStringNonNull(data);
79
80 util::StatusOr<std::string> digest = internal::ComputeHash(data, *sig_hash_);
81 if (!digest.ok()) {
82 return digest.status();
83 }
84
85 if (RSA_verify(EVP_MD_type(sig_hash_),
86 /*digest=*/reinterpret_cast<const uint8_t*>(digest->data()),
87 /*digest_len=*/digest->size(),
88 /*sig=*/reinterpret_cast<const uint8_t*>(signature.data()),
89 /*sig_len=*/signature.length(),
90 /*rsa=*/rsa_.get()) != 1) {
91 // Signature is invalid.
92 return util::Status(absl::StatusCode::kInvalidArgument,
93 "Signature is not valid.");
94 }
95
96 return util::OkStatus();
97 }
98
99 } // namespace subtle
100 } // namespace tink
101 } // namespace crypto
102