| /* |
| * Copyright 2020 The Android Open Source Project |
| * |
| * 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 <keymint_support/authorization_set.h> |
| |
| #include <aidl/android/hardware/security/keymint/Algorithm.h> |
| #include <aidl/android/hardware/security/keymint/BlockMode.h> |
| #include <aidl/android/hardware/security/keymint/Digest.h> |
| #include <aidl/android/hardware/security/keymint/KeyParameter.h> |
| #include <aidl/android/hardware/security/keymint/KeyPurpose.h> |
| |
| namespace aidl::android::hardware::security::keymint { |
| |
| void AuthorizationSet::Sort() { |
| std::sort(data_.begin(), data_.end()); |
| } |
| |
| void AuthorizationSet::Deduplicate() { |
| if (data_.empty()) return; |
| |
| Sort(); |
| std::vector<KeyParameter> result; |
| |
| auto curr = data_.begin(); |
| auto prev = curr++; |
| for (; curr != data_.end(); ++prev, ++curr) { |
| if (prev->tag == Tag::INVALID) continue; |
| |
| if (*prev != *curr) { |
| result.push_back(std::move(*prev)); |
| } |
| } |
| result.push_back(std::move(*prev)); |
| |
| std::swap(data_, result); |
| } |
| |
| void AuthorizationSet::Union(const AuthorizationSet& other) { |
| data_.insert(data_.end(), other.data_.begin(), other.data_.end()); |
| Deduplicate(); |
| } |
| |
| void AuthorizationSet::Subtract(const AuthorizationSet& other) { |
| Deduplicate(); |
| |
| auto i = other.begin(); |
| while (i != other.end()) { |
| int pos = -1; |
| do { |
| pos = find(i->tag, pos); |
| if (pos != -1 && (*i == data_[pos])) { |
| data_.erase(data_.begin() + pos); |
| break; |
| } |
| } while (pos != -1); |
| ++i; |
| } |
| } |
| |
| KeyParameter& AuthorizationSet::operator[](int at) { |
| return data_[at]; |
| } |
| |
| const KeyParameter& AuthorizationSet::operator[](int at) const { |
| return data_[at]; |
| } |
| |
| void AuthorizationSet::Clear() { |
| data_.clear(); |
| } |
| |
| size_t AuthorizationSet::GetTagCount(Tag tag) const { |
| size_t count = 0; |
| for (int pos = -1; (pos = find(tag, pos)) != -1;) ++count; |
| return count; |
| } |
| |
| int AuthorizationSet::find(Tag tag, int begin) const { |
| auto iter = data_.begin() + (1 + begin); |
| |
| while (iter != data_.end() && iter->tag != tag) ++iter; |
| |
| if (iter != data_.end()) return iter - data_.begin(); |
| return -1; |
| } |
| |
| bool AuthorizationSet::erase(int index) { |
| auto pos = data_.begin() + index; |
| if (pos != data_.end()) { |
| data_.erase(pos); |
| return true; |
| } |
| return false; |
| } |
| |
| std::optional<std::reference_wrapper<const KeyParameter>> AuthorizationSet::GetEntry( |
| Tag tag) const { |
| int pos = find(tag); |
| if (pos == -1) return {}; |
| return std::reference_wrapper(data_[pos]); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size, |
| uint64_t public_exponent) { |
| Authorization(TAG_ALGORITHM, Algorithm::RSA); |
| Authorization(TAG_KEY_SIZE, key_size); |
| Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent); |
| return *this; |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) { |
| Authorization(TAG_ALGORITHM, Algorithm::EC); |
| Authorization(TAG_KEY_SIZE, key_size); |
| return *this; |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(EcCurve curve) { |
| Authorization(TAG_ALGORITHM, Algorithm::EC); |
| Authorization(TAG_EC_CURVE, curve); |
| return *this; |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) { |
| Authorization(TAG_ALGORITHM, Algorithm::AES); |
| return Authorization(TAG_KEY_SIZE, key_size); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesKey(uint32_t key_size) { |
| Authorization(TAG_ALGORITHM, Algorithm::TRIPLE_DES); |
| return Authorization(TAG_KEY_SIZE, key_size); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) { |
| Authorization(TAG_ALGORITHM, Algorithm::HMAC); |
| Authorization(TAG_KEY_SIZE, key_size); |
| return SigningKey(); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size, |
| uint64_t public_exponent) { |
| RsaKey(key_size, public_exponent); |
| return SigningKey(); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, |
| uint64_t public_exponent) { |
| RsaKey(key_size, public_exponent); |
| return EncryptionKey(); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(EcCurve curve) { |
| EcdsaKey(curve); |
| return SigningKey(); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) { |
| AesKey(key_size); |
| return EncryptionKey(); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesEncryptionKey(uint32_t key_size) { |
| TripleDesKey(key_size); |
| return EncryptionKey(); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() { |
| Authorization(TAG_PURPOSE, KeyPurpose::SIGN); |
| return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() { |
| Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT); |
| return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::AttestKey() { |
| return Authorization(TAG_PURPOSE, KeyPurpose::ATTEST_KEY); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() { |
| Authorization(TAG_DIGEST, Digest::NONE); |
| return Authorization(TAG_PADDING, PaddingMode::NONE); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() { |
| return Authorization(TAG_BLOCK_MODE, BlockMode::ECB); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMinMacLen(uint32_t minMacLength) { |
| return BlockMode(BlockMode::GCM) |
| .Padding(PaddingMode::NONE) |
| .Authorization(TAG_MIN_MAC_LENGTH, minMacLength); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMacLen(uint32_t macLength) { |
| return BlockMode(BlockMode::GCM) |
| .Padding(PaddingMode::NONE) |
| .Authorization(TAG_MAC_LENGTH, macLength); |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::BlockMode( |
| std::initializer_list<aidl::android::hardware::security::keymint::BlockMode> blockModes) { |
| for (auto mode : blockModes) { |
| push_back(TAG_BLOCK_MODE, mode); |
| } |
| return *this; |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(std::vector<keymint::Digest> digests) { |
| for (auto digest : digests) { |
| push_back(TAG_DIGEST, digest); |
| } |
| return *this; |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::OaepMGFDigest( |
| const std::vector<android::hardware::security::keymint::Digest>& digests) { |
| for (auto digest : digests) { |
| push_back(TAG_RSA_OAEP_MGF_DIGEST, digest); |
| } |
| return *this; |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::Padding( |
| std::initializer_list<PaddingMode> paddingModes) { |
| for (auto paddingMode : paddingModes) { |
| push_back(TAG_PADDING, paddingMode); |
| } |
| return *this; |
| } |
| |
| AuthorizationSetBuilder& AuthorizationSetBuilder::SetDefaultValidity() { |
| // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to |
| // GeneralizedTime 999912312359559, which is 253402300799000 ms from Jan 1, 1970. |
| constexpr uint64_t kUndefinedExpirationDateTime = 253402300799000; |
| Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0); |
| return Authorization(TAG_CERTIFICATE_NOT_AFTER, kUndefinedExpirationDateTime); |
| } |
| |
| } // namespace aidl::android::hardware::security::keymint |