254 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * 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
 |