• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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