blob: f0fa258d461a364c0f201e7e456da45afd4f8568 [file] [log] [blame]
// 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/streamingaead/aes_gcm_hkdf_streaming_key_manager.h"
#include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h"
#include "tink/subtle/random.h"
#include "tink/util/validation.h"
namespace crypto {
namespace tink {
using ::crypto::tink::subtle::AesGcmHkdfStreamSegmentEncrypter;
using ::crypto::tink::util::Status;
using ::crypto::tink::util::StatusOr;
using ::google::crypto::tink::AesGcmHkdfStreamingKey;
using ::google::crypto::tink::AesGcmHkdfStreamingKeyFormat;
using ::google::crypto::tink::AesGcmHkdfStreamingParams;
using ::google::crypto::tink::HashType;
namespace {
Status ValidateParams(const AesGcmHkdfStreamingParams& 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");
}
int header_size = 1 + params.derived_key_size() +
AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes;
if (params.ciphertext_segment_size() <=
header_size + AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes) {
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::AesGcmHkdfStreamingKey>
AesGcmHkdfStreamingKeyManager::CreateKey(
const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format)
const {
AesGcmHkdfStreamingKey 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 AesGcmHkdfStreamingKeyManager::ValidateKey(
const AesGcmHkdfStreamingKey& 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 AesGcmHkdfStreamingKeyManager::ValidateKeyFormat(
const AesGcmHkdfStreamingKeyFormat& 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