Skip to content

Commit

Permalink
Adding AES-CMAC to Tink's supported macs in C++.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 259600688
  • Loading branch information
ise-crypto authored and copybara-github committed Jul 23, 2019
1 parent fc0712e commit 7a500ef
Show file tree
Hide file tree
Showing 18 changed files with 1,182 additions and 2 deletions.
47 changes: 47 additions & 0 deletions cc/mac/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ cc_library(
include_prefix = "tink",
strip_include_prefix = "/cc",
deps = [
":aes_cmac_key_manager",
":hmac_key_manager",
"//cc:catalogue",
"//cc/util:status",
Expand Down Expand Up @@ -76,12 +77,37 @@ cc_library(
strip_include_prefix = "/cc",
visibility = ["//visibility:public"],
deps = [
"//proto:aes_cmac_cc_proto",
"//proto:common_cc_proto",
"//proto:hmac_cc_proto",
"//proto:tink_cc_proto",
],
)

cc_library(
name = "aes_cmac_key_manager",
srcs = ["aes_cmac_key_manager.cc"],
hdrs = ["aes_cmac_key_manager.h"],
include_prefix = "tink",
strip_include_prefix = "/cc",
deps = [
"//cc:key_manager",
"//cc:key_manager_base",
"//cc:mac",
"//cc/subtle:aes_cmac_boringssl",
"//cc/subtle:random",
"//cc/util:enums",
"//cc/util:errors",
"//cc/util:protobuf_helper",
"//cc/util:status",
"//cc/util:statusor",
"//cc/util:validation",
"//proto:aes_cmac_cc_proto",
"//proto:common_cc_proto",
"//proto:tink_cc_proto",
],
)

cc_library(
name = "hmac_key_manager",
srcs = ["hmac_key_manager.cc"],
Expand Down Expand Up @@ -191,15 +217,36 @@ cc_test(
srcs = ["mac_key_templates_test.cc"],
copts = ["-Iexternal/gtest/include"],
deps = [
":aes_cmac_key_manager",
":hmac_key_manager",
":mac_key_templates",
"//proto:aes_cmac_cc_proto",
"//proto:common_cc_proto",
"//proto:hmac_cc_proto",
"//proto:tink_cc_proto",
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "aes_cmac_key_manager_test",
size = "small",
srcs = ["aes_cmac_key_manager_test.cc"],
copts = ["-Iexternal/gtest/include"],
deps = [
":aes_cmac_key_manager",
"//cc:mac",
"//cc/util:status",
"//cc/util:statusor",
"//proto:aes_cmac_cc_proto",
"//proto:aes_ctr_cc_proto",
"//proto:aes_ctr_hmac_aead_cc_proto",
"//proto:common_cc_proto",
"//proto:tink_cc_proto",
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "hmac_key_manager_test",
size = "small",
Expand Down
41 changes: 41 additions & 0 deletions cc/mac/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ tink_cc_library(
mac_catalogue.cc
mac_catalogue.h
DEPS
tink::mac::aes_cmac_key_manager
tink::mac::hmac_key_manager
tink::core::catalogue
tink::util::status
Expand Down Expand Up @@ -63,11 +64,34 @@ tink_cc_library(
mac_key_templates.cc
mac_key_templates.h
DEPS
tink::proto::aes_cmac_cc_proto
tink::proto::common_cc_proto
tink::proto::hmac_cc_proto
tink::proto::tink_cc_proto
)

tink_cc_library(
NAME aes_cmac_key_manager
SRCS
aes_cmac_key_manager.cc
aes_cmac_key_manager.h
DEPS
tink::core::key_manager
tink::core::key_manager_base
tink::core::mac
tink::subtle::aes_cmac_boringssl
tink::subtle::random
tink::util::enums
tink::util::errors
tink::util::protobuf_helper
tink::util::status
tink::util::statusor
tink::util::validation
tink::proto::common_cc_proto
tink::proto::aes_cmac_cc_proto
tink::proto::tink_cc_proto
)

tink_cc_library(
NAME hmac_key_manager
SRCS
Expand Down Expand Up @@ -157,13 +181,30 @@ tink_cc_test(
NAME mac_key_templates_test
SRCS mac_key_templates_test.cc
DEPS
tink::mac::aes_cmac_key_manager
tink::mac::hmac_key_manager
tink::mac::mac_key_templates
tink::proto::aes_cmac_cc_proto
tink::proto::common_cc_proto
tink::proto::hmac_cc_proto
tink::proto::tink_cc_proto
)

tink_cc_test(
NAME aes_cmac_key_manager_test
SRCS aes_cmac_key_manager_test.cc
DEPS
tink::mac::aes_cmac_key_manager
tink::core::mac
tink::util::status
tink::util::statusor
tink::proto::aes_ctr_cc_proto
tink::proto::aes_ctr_hmac_aead_cc_proto
tink::proto::common_cc_proto
tink::proto::aes_cmac_cc_proto
tink::proto::tink_cc_proto
)

tink_cc_test(
NAME hmac_key_manager_test
SRCS hmac_key_manager_test.cc
Expand Down
133 changes: 133 additions & 0 deletions cc/mac/aes_cmac_key_manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Copyright 2017 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/mac/aes_cmac_key_manager.h"

#include <map>

#include "absl/strings/string_view.h"
#include "tink/key_manager.h"
#include "tink/mac.h"
#include "tink/subtle/aes_cmac_boringssl.h"
#include "tink/subtle/random.h"
#include "tink/util/enums.h"
#include "tink/util/errors.h"
#include "tink/util/protobuf_helper.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"
#include "tink/util/validation.h"
#include "proto/aes_cmac.pb.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {

using crypto::tink::util::Enums;
using crypto::tink::util::Status;
using crypto::tink::util::StatusOr;
using google::crypto::tink::AesCmacKey;
using google::crypto::tink::AesCmacKeyFormat;
using google::crypto::tink::AesCmacParams;
using google::crypto::tink::KeyData;

constexpr uint32_t AesCmacKeyManager::kVersion;
// Due to https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf, we
// only allow key sizes of 256 bit.
constexpr int kKeySizeInBytes = 32;
constexpr int kMaxTagSizeInBytes = 16;
constexpr int kMinTagSizeInBytes = 10;

class AesCmacKeyFactory : public KeyFactoryBase<AesCmacKey, AesCmacKeyFormat> {
public:
AesCmacKeyFactory() {}

KeyData::KeyMaterialType key_material_type() const override {
return KeyData::SYMMETRIC;
}

protected:
StatusOr<std::unique_ptr<AesCmacKey>> NewKeyFromFormat(
const AesCmacKeyFormat& cmac_key_format) const override;
};

StatusOr<std::unique_ptr<AesCmacKey>> AesCmacKeyFactory::NewKeyFromFormat(
const AesCmacKeyFormat& cmac_key_format) const {
Status status = AesCmacKeyManager::Validate(cmac_key_format);
if (!status.ok()) return status;
auto cmac_key = absl::make_unique<AesCmacKey>();
cmac_key->set_version(AesCmacKeyManager::kVersion);
cmac_key->set_key_value(
subtle::Random::GetRandomBytes(cmac_key_format.key_size()));
return absl::implicit_cast<StatusOr<std::unique_ptr<AesCmacKey>>>(
std::move(cmac_key));
}

AesCmacKeyManager::AesCmacKeyManager()
: key_factory_(new AesCmacKeyFactory()) {}

uint32_t AesCmacKeyManager::get_version() const { return kVersion; }

const KeyFactory& AesCmacKeyManager::get_key_factory() const {
return *key_factory_;
}

StatusOr<std::unique_ptr<Mac>> AesCmacKeyManager::GetPrimitiveFromKey(
const AesCmacKey& cmac_key) const {
Status status = Validate(cmac_key);
if (!status.ok()) return status;
auto cmac_result = subtle::AesCmacBoringSsl::New(
cmac_key.key_value(), cmac_key.params().tag_size());
if (!cmac_result.ok()) return cmac_result.status();
return std::move(cmac_result.ValueOrDie());
}

// static
Status AesCmacKeyManager::Validate(const AesCmacParams& params) {
if (params.tag_size() < kMinTagSizeInBytes) {
return ToStatusF(util::error::INVALID_ARGUMENT,
"Invalid AesCmacParams: tag_size %d is too small.",
params.tag_size());
}
if (params.tag_size() > kMaxTagSizeInBytes) {
return ToStatusF(util::error::INVALID_ARGUMENT,
"Invalid AesCmacParams: tag_size %d is too big.",
params.tag_size());
}
return Status::OK;
}

// static
Status AesCmacKeyManager::Validate(const AesCmacKey& key) {
Status status = ValidateVersion(key.version(), kVersion);
if (!status.ok()) return status;
if (key.key_value().size() != kKeySizeInBytes) {
return ToStatusF(util::error::INVALID_ARGUMENT,
"Invalid AesCmacKey: key_value wrong length.");
}
return Validate(key.params());
}

// static
Status AesCmacKeyManager::Validate(const AesCmacKeyFormat& key_format) {
if (key_format.key_size() != kKeySizeInBytes) {
return ToStatusF(util::error::INVALID_ARGUMENT,
"Invalid AesCmacKeyFormat: invalid key_size.");
}
return Validate(key_format.params());
}

} // namespace tink
} // namespace crypto
72 changes: 72 additions & 0 deletions cc/mac/aes_cmac_key_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2017 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef TINK_MAC_AES_CMAC_KEY_MANAGER_H_
#define TINK_MAC_AES_CMAC_KEY_MANAGER_H_

#include <algorithm>
#include <vector>

#include "absl/strings/string_view.h"
#include "tink/core/key_manager_base.h"
#include "tink/key_manager.h"
#include "tink/mac.h"
#include "tink/util/errors.h"
#include "tink/util/protobuf_helper.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"
#include "proto/aes_cmac.pb.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {

class AesCmacKeyManager
: public KeyManagerBase<Mac, google::crypto::tink::AesCmacKey> {
public:
static constexpr uint32_t kVersion = 0;

AesCmacKeyManager();

// Returns the version of this key manager.
uint32_t get_version() const override;

// Returns a factory that generates keys of the key type
// handled by this manager.
const KeyFactory& get_key_factory() const override;

~AesCmacKeyManager() override {}

protected:
crypto::tink::util::StatusOr<std::unique_ptr<Mac>> GetPrimitiveFromKey(
const google::crypto::tink::AesCmacKey& cmac_key) const override;

private:
friend class AesCmacKeyFactory;

std::unique_ptr<KeyFactory> key_factory_;

static crypto::tink::util::Status Validate(
const google::crypto::tink::AesCmacParams& params);
static crypto::tink::util::Status Validate(
const google::crypto::tink::AesCmacKey& key);
static crypto::tink::util::Status Validate(
const google::crypto::tink::AesCmacKeyFormat& key_format);
};

} // namespace tink
} // namespace crypto

#endif // TINK_MAC_AES_CMAC_KEY_MANAGER_H_
Loading

0 comments on commit 7a500ef

Please sign in to comment.