• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Google LLC
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/stateful_hmac_boringssl.h"
18 
19 #include <memory>
20 #include <string>
21 #include <utility>
22 
23 #include "absl/memory/memory.h"
24 #include "absl/status/status.h"
25 #include "openssl/evp.h"
26 #include "tink/internal/md_util.h"
27 #include "tink/internal/ssl_unique_ptr.h"
28 #include "tink/internal/util.h"
29 #include "tink/util/status.h"
30 
31 namespace crypto {
32 namespace tink {
33 namespace subtle {
34 
New(HashType hash_type,uint32_t tag_size,const util::SecretData & key_value)35 util::StatusOr<std::unique_ptr<StatefulMac>> StatefulHmacBoringSsl::New(
36     HashType hash_type, uint32_t tag_size, const util::SecretData& key_value) {
37   util::StatusOr<const EVP_MD*> md = internal::EvpHashFromHashType(hash_type);
38   if (!md.ok()) {
39     return md.status();
40   }
41   if (EVP_MD_size(*md) < tag_size) {
42     // The key manager is responsible to security policies.
43     // The checks here just ensure the preconditions of the primitive.
44     // If this fails then something is wrong with the key manager.
45     return util::Status(absl::StatusCode::kInvalidArgument, "invalid tag size");
46   }
47   if (key_value.size() < kMinKeySize) {
48     return util::Status(absl::StatusCode::kInvalidArgument, "invalid key size");
49   }
50 
51   // Create and initialize the HMAC context
52   internal::SslUniquePtr<HMAC_CTX> ctx(HMAC_CTX_new());
53   // Initialize the HMAC
54   if (!HMAC_Init(ctx.get(), key_value.data(), key_value.size(), *md)) {
55     return util::Status(absl::StatusCode::kFailedPrecondition,
56                         "HMAC initialization failed");
57   }
58 
59   return std::unique_ptr<StatefulMac>(
60       new StatefulHmacBoringSsl(tag_size, std::move(ctx)));
61 }
62 
Update(absl::string_view data)63 util::Status StatefulHmacBoringSsl::Update(absl::string_view data) {
64   // BoringSSL expects a non-null pointer for data,
65   // regardless of whether the size is 0.
66   data = internal::EnsureStringNonNull(data);
67 
68   if (!HMAC_Update(hmac_context_.get(),
69                    reinterpret_cast<const uint8_t*>(data.data()),
70                    data.size())) {
71     return util::Status(absl::StatusCode::kFailedPrecondition,
72                         "Inputs to HMAC Update invalid");
73   }
74   return util::OkStatus();
75 }
76 
Finalize()77 util::StatusOr<std::string> StatefulHmacBoringSsl::Finalize() {
78   uint8_t buf[EVP_MAX_MD_SIZE];
79   unsigned int out_len;
80 
81   if (!HMAC_Final(hmac_context_.get(), buf, &out_len)) {
82     return util::Status(absl::StatusCode::kInternal,
83                         "HMAC finalization failed");
84   }
85   return std::string(reinterpret_cast<char*>(buf), tag_size_);
86 }
87 
StatefulHmacBoringSslFactory(HashType hash_type,uint32_t tag_size,const util::SecretData & key_value)88 StatefulHmacBoringSslFactory::StatefulHmacBoringSslFactory(
89     HashType hash_type, uint32_t tag_size, const util::SecretData& key_value)
90     : hash_type_(hash_type), tag_size_(tag_size), key_value_(key_value) {}
91 
92 util::StatusOr<std::unique_ptr<StatefulMac>>
Create() const93 StatefulHmacBoringSslFactory::Create() const {
94   return StatefulHmacBoringSsl::New(hash_type_, tag_size_, key_value_);
95 }
96 
97 }  // namespace subtle
98 }  // namespace tink
99 }  // namespace crypto
100