• 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_sign_boringssl.h"
18 
19 #include <memory>
20 #include <string>
21 #include <utility>
22 #include <vector>
23 
24 #include "absl/memory/memory.h"
25 #include "absl/status/status.h"
26 #include "absl/strings/str_cat.h"
27 #include "openssl/evp.h"
28 #include "openssl/rsa.h"
29 #include "tink/internal/bn_util.h"
30 #include "tink/internal/err_util.h"
31 #include "tink/internal/md_util.h"
32 #include "tink/internal/rsa_util.h"
33 #include "tink/internal/ssl_unique_ptr.h"
34 #include "tink/internal/util.h"
35 #include "tink/subtle/subtle_util.h"
36 #include "tink/util/statusor.h"
37 
38 namespace crypto {
39 namespace tink {
40 namespace subtle {
41 
New(const internal::RsaPrivateKey & private_key,const internal::RsaSsaPkcs1Params & params)42 util::StatusOr<std::unique_ptr<PublicKeySign>> RsaSsaPkcs1SignBoringSsl::New(
43     const internal::RsaPrivateKey& private_key,
44     const internal::RsaSsaPkcs1Params& params) {
45   util::Status status =
46       internal::CheckFipsCompatibility<RsaSsaPkcs1SignBoringSsl>();
47   if (!status.ok()) {
48     return status;
49   }
50 
51   // Check if the hash type is safe to use.
52   util::Status is_safe = internal::IsHashTypeSafeForSignature(params.hash_type);
53   if (!is_safe.ok()) {
54     return is_safe;
55   }
56 
57   util::StatusOr<const EVP_MD*> sig_hash =
58       internal::EvpHashFromHashType(params.hash_type);
59   if (!sig_hash.ok()) {
60     return sig_hash.status();
61   }
62 
63   // Check RSA's modulus.
64   util::StatusOr<internal::SslUniquePtr<BIGNUM>> n =
65       internal::StringToBignum(private_key.n);
66   if (!n.ok()) {
67     return n.status();
68   }
69   auto modulus_status = internal::ValidateRsaModulusSize(BN_num_bits(n->get()));
70   if (!modulus_status.ok()) {
71     return modulus_status;
72   }
73 
74   // The RSA modulus and exponent are checked as part of the conversion to
75   // internal::SslUniquePtr<RSA>.
76   util::StatusOr<internal::SslUniquePtr<RSA>> rsa =
77       internal::RsaPrivateKeyToRsa(private_key);
78   if (!rsa.ok()) {
79     return rsa.status();
80   }
81 
82   return {absl::WrapUnique(
83       new RsaSsaPkcs1SignBoringSsl(*std::move(rsa), *sig_hash))};
84 }
85 
Sign(absl::string_view data) const86 util::StatusOr<std::string> RsaSsaPkcs1SignBoringSsl::Sign(
87     absl::string_view data) const {
88   data = internal::EnsureStringNonNull(data);
89   util::StatusOr<std::string> digest = internal::ComputeHash(data, *sig_hash_);
90   if (!digest.ok()) {
91     return digest.status();
92   }
93 
94   std::string signature;
95   ResizeStringUninitialized(&signature, RSA_size(private_key_.get()));
96   unsigned int signature_length = 0;
97 
98   if (RSA_sign(/*hash_nid=*/EVP_MD_type(sig_hash_),
99                /*digest=*/reinterpret_cast<const uint8_t*>(digest->data()),
100                /*digest_len=*/digest->size(),
101                /*out=*/reinterpret_cast<uint8_t*>(&signature[0]),
102                /*out_len=*/&signature_length,
103                /*rsa=*/private_key_.get()) != 1) {
104     // TODO(b/112581512): Decide if it's safe to propagate the BoringSSL error.
105     // For now, just empty the error stack.
106     internal::GetSslErrors();
107     return util::Status(absl::StatusCode::kInternal, "Signing failed.");
108   }
109   signature.resize(signature_length);
110   return signature;
111 }
112 
113 }  // namespace subtle
114 }  // namespace tink
115 }  // namespace crypto
116