blob: b5440f35ceee92fec7c058d407e3d0edb22a33e5 [file] [log] [blame]
Andrew Scull9fadf342021-06-03 08:38:47 +00001/*
2 * Copyright 2021, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "MicrodroidKeymasterContext.h"
18
19#include <android-base/logging.h>
20#include <keymaster/key.h>
21#include <keymaster/key_blob_utils/auth_encrypted_key_blob.h>
22#include <keymaster/key_blob_utils/software_keyblobs.h>
23
24using namespace ::keymaster;
25
26// This value is used for the ROOT_OF_TRUST tag which is only used in
27// attestation records which aren't supported in this implementation so a
28// constant doesn't cause any hard. MicroDroid SoftWare root-of-trust.
29static uint8_t SWROT[] = {'M', 'D', 'S', 'W'};
30static const KeymasterBlob microdroidSoftwareRootOfTrust(SWROT);
31
32keymaster_error_t MicrodroidKeymasterContext::CreateKeyBlob(const AuthorizationSet& key_description,
33 keymaster_key_origin_t origin,
34 const KeymasterKeyBlob& key_material,
35 KeymasterKeyBlob* blob,
36 AuthorizationSet* hw_enforced,
37 AuthorizationSet* sw_enforced) const {
38 keymaster_error_t error;
39
40 if (key_description.GetTagValue(TAG_ROLLBACK_RESISTANCE)) {
41 return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE;
42 }
43
44 error = SetKeyBlobAuthorizations(key_description, origin, os_version_, os_patchlevel_,
45 hw_enforced, sw_enforced);
46 if (error != KM_ERROR_OK) return error;
47
48 AuthorizationSet hidden;
49 error = BuildHiddenAuthorizations(key_description, &hidden, microdroidSoftwareRootOfTrust);
50 if (error != KM_ERROR_OK) return error;
51
52 CHECK(hw_enforced->empty());
53
54 // Note that the authorizations included in the blob are not encrypted. This
55 // doesn't pose a problem for the current applications but may be a
56 // candidate for hardening.
57 auto encrypted_key = EncryptKey(key_material, AES_GCM_WITH_SW_ENFORCED, *hw_enforced,
58 *sw_enforced, hidden, root_key_, random_, &error);
59 if (error != KM_ERROR_OK) return error;
60
61 *blob = SerializeAuthEncryptedBlob(encrypted_key, *hw_enforced, *sw_enforced, &error);
62 return error;
63}
64
65keymaster_error_t MicrodroidKeymasterContext::ParseKeyBlob(
66 const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
67 UniquePtr<Key>* key) const {
68 keymaster_error_t error;
69
70 AuthorizationSet hidden;
71 error = BuildHiddenAuthorizations(additional_params, &hidden, microdroidSoftwareRootOfTrust);
72 if (error != KM_ERROR_OK) return error;
73
74 auto deserialized_key = DeserializeAuthEncryptedBlob(blob, &error);
75 if (error != KM_ERROR_OK) return error;
76
77 keymaster_algorithm_t algorithm;
78 if (!deserialized_key.sw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm)) {
79 return KM_ERROR_INVALID_ARGUMENT;
80 }
81
82 auto key_material = DecryptKey(deserialized_key, hidden, root_key_, &error);
83 if (error != KM_ERROR_OK) return error;
84
85 auto factory = GetKeyFactory(algorithm);
86 return factory->LoadKey(move(key_material), additional_params,
87 move(deserialized_key.hw_enforced), move(deserialized_key.sw_enforced),
88 key);
89}
90
91static bool UpgradeIntegerTag(keymaster_tag_t tag, uint32_t value, AuthorizationSet* set) {
92 int index = set->find(tag);
93 if (index == -1) {
94 keymaster_key_param_t param;
95 param.tag = tag;
96 param.integer = value;
97 set->push_back(param);
98 return true;
99 }
100
101 if (set->params[index].integer > value) return false;
102
103 if (set->params[index].integer != value) {
104 set->params[index].integer = value;
105 }
106 return true;
107}
108
109keymaster_error_t MicrodroidKeymasterContext::UpgradeKeyBlob(const KeymasterKeyBlob& key_to_upgrade,
110 const AuthorizationSet& upgrade_params,
111 KeymasterKeyBlob* upgraded_key) const {
112 UniquePtr<Key> key;
113 keymaster_error_t error = ParseKeyBlob(key_to_upgrade, upgrade_params, &key);
114 if (error != KM_ERROR_OK) return error;
115
116 if (os_version_ == 0) {
117 // We need to allow "upgrading" OS version to zero, to support upgrading from proper
118 // numbered releases to unnumbered development and preview releases.
119
120 int key_os_version_pos = key->sw_enforced().find(TAG_OS_VERSION);
121 if (key_os_version_pos != -1) {
122 uint32_t key_os_version = key->sw_enforced()[key_os_version_pos].integer;
123 if (key_os_version != 0) {
124 key->sw_enforced()[key_os_version_pos].integer = os_version_;
125 }
126 }
127 }
128
129 if (!UpgradeIntegerTag(TAG_OS_VERSION, os_version_, &key->sw_enforced()) ||
130 !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, os_patchlevel_, &key->sw_enforced()))
131 // One of the version fields would have been a downgrade. Not allowed.
132 return KM_ERROR_INVALID_ARGUMENT;
133
134 AuthorizationSet hidden;
135 error = BuildHiddenAuthorizations(upgrade_params, &hidden, microdroidSoftwareRootOfTrust);
136 if (error != KM_ERROR_OK) return error;
137
138 auto encrypted_key =
139 EncryptKey(key->key_material(), AES_GCM_WITH_SW_ENFORCED, key->hw_enforced(),
140 key->sw_enforced(), hidden, root_key_, random_, &error);
141 if (error != KM_ERROR_OK) return error;
142
143 *upgraded_key = SerializeAuthEncryptedBlob(encrypted_key, key->hw_enforced(),
144 key->sw_enforced(), &error);
145 return error;
146}