blob: 11266c5467acc730aa54fa79195d8944bc953711 [file] [log] [blame]
// 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/streamingaead/aes_ctr_hmac_streaming_key_manager.h"
#include "tink/subtle/aes_ctr_hmac_streaming.h"
#include "tink/subtle/random.h"
#include "tink/util/status.h"
#include "tink/util/validation.h"
namespace crypto {
namespace tink {
using ::crypto::tink::subtle::AesCtrHmacStreaming;
using ::crypto::tink::util::Status;
using ::crypto::tink::util::StatusOr;
using ::google::crypto::tink::AesCtrHmacStreamingKey;
using ::google::crypto::tink::AesCtrHmacStreamingKeyFormat;
using ::google::crypto::tink::AesCtrHmacStreamingParams;
using ::google::crypto::tink::HashType;
namespace {
Status ValidateParams(const AesCtrHmacStreamingParams& params) {
if (!(params.hkdf_hash_type() == HashType::SHA1 ||
params.hkdf_hash_type() == HashType::SHA256 ||
params.hkdf_hash_type() == HashType::SHA512)) {
return Status(util::error::INVALID_ARGUMENT, "unsupported hkdf_hash_type");
}
if (!(params.hmac_params().hash() == HashType::SHA1 ||
params.hmac_params().hash() == HashType::SHA256 ||
params.hmac_params().hash() == HashType::SHA512)) {
return Status(util::error::INVALID_ARGUMENT,
"unsupported hmac_params.hash");
}
if (params.hmac_params().tag_size() < 10) {
return Status(util::error::INVALID_ARGUMENT,
"hmac_params.tag_size too small");
}
if ((params.hmac_params().hash() == HashType::SHA1 &&
params.hmac_params().tag_size() > 20) ||
(params.hmac_params().hash() == HashType::SHA256 &&
params.hmac_params().tag_size() > 32) ||
(params.hmac_params().hash() == HashType::SHA512 &&
params.hmac_params().tag_size() > 64)) {
return Status(util::error::INVALID_ARGUMENT,
"hmac_params.tag_size too big");
}
int header_size = 1 + params.derived_key_size() +
AesCtrHmacStreaming::kNoncePrefixSizeInBytes;
if (params.ciphertext_segment_size() <=
header_size + params.hmac_params().tag_size()) {
return Status(util::error::INVALID_ARGUMENT,
"ciphertext_segment_size too small");
}
return ValidateAesKeySize(params.derived_key_size());
}
} // namespace
crypto::tink::util::StatusOr<google::crypto::tink::AesCtrHmacStreamingKey>
AesCtrHmacStreamingKeyManager::CreateKey(
const google::crypto::tink::AesCtrHmacStreamingKeyFormat& key_format)
const {
AesCtrHmacStreamingKey key;
key.set_version(get_version());
key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size()));
*key.mutable_params() = key_format.params();
return key;
};
Status AesCtrHmacStreamingKeyManager::ValidateKey(
const AesCtrHmacStreamingKey& key) const {
Status status = ValidateVersion(key.version(), get_version());
if (!status.ok()) return status;
if (key.key_value().size() < key.params().derived_key_size()) {
return Status(util::error::INVALID_ARGUMENT,
"key_value (i.e. ikm) too short");
}
return ValidateParams(key.params());
}
Status AesCtrHmacStreamingKeyManager::ValidateKeyFormat(
const AesCtrHmacStreamingKeyFormat& key_format) const {
if (key_format.key_size() < key_format.params().derived_key_size()) {
return Status(util::error::INVALID_ARGUMENT,
"key_size must not be smaller than derived_key_size");
}
return ValidateParams(key_format.params());
}
} // namespace tink
} // namespace crypto