Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * Copyright (c) 2016-2017 Nest Labs, Inc.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 : #include <lib/core/CHIPKeyIds.h>
19 :
20 : #include <lib/support/CodeUtils.h>
21 :
22 : namespace chip {
23 :
24 : /**
25 : * Determine whether the specified key ID belongs to one of the application
26 : * group key types (static or rotating).
27 : *
28 : * @param[in] keyId CHIP key identifier.
29 : * @return true if the keyId is of rotating or static key type.
30 : *
31 : */
32 0 : bool ChipKeyId::IsAppGroupKey(uint32_t keyId)
33 : {
34 0 : return IsAppStaticKey(keyId) || IsAppRotatingKey(keyId);
35 : }
36 :
37 : /**
38 : * Determine whether the specified application group key ID uses "current" epoch key.
39 : *
40 : * @param[in] keyId CHIP application group key identifier.
41 : * @return true if the keyId indicates usage of the current epoch key.
42 : *
43 : */
44 0 : bool ChipKeyId::UsesCurrentEpochKey(uint32_t keyId)
45 : {
46 0 : return IncorporatesEpochKey(keyId) && ((keyId & kFlag_UseCurrentEpochKey) != 0);
47 : }
48 :
49 : /**
50 : * Determine whether the specified application group key ID incorporates root key.
51 : *
52 : * @param[in] keyId CHIP application group key identifier.
53 : * @return true if the keyId incorporates root key.
54 : *
55 : */
56 0 : bool ChipKeyId::IncorporatesRootKey(uint32_t keyId)
57 : {
58 0 : uint32_t keyType = GetType(keyId);
59 0 : return keyType == kType_AppStaticKey || keyType == kType_AppRotatingKey || keyType == kType_AppRootKey ||
60 0 : keyType == kType_AppIntermediateKey;
61 : }
62 :
63 : /**
64 : * Determine whether the specified application group key ID incorporates group master key.
65 : *
66 : * @param[in] keyId CHIP application group key identifier.
67 : * @return true if the keyId incorporates group master key.
68 : *
69 : */
70 0 : bool ChipKeyId::IncorporatesAppGroupMasterKey(uint32_t keyId)
71 : {
72 0 : uint32_t keyType = GetType(keyId);
73 0 : return keyType == kType_AppStaticKey || keyType == kType_AppRotatingKey || keyType == kType_AppGroupMasterKey;
74 : }
75 :
76 : /**
77 : * Construct application group key ID given constituent key IDs and other information.
78 : *
79 : * @param[in] keyType Derived application group key type.
80 : * @param[in] rootKeyId Root key ID used to derive application group key.
81 : * @param[in] epochKeyId Epoch key ID used to derive application group key.
82 : * @param[in] appGroupMasterKeyId Application group master key ID used to derive
83 : * application group key.
84 : * @param[in] useCurrentEpochKey A boolean flag that indicates if key should be derived
85 : * using "current" epoch key.
86 : * @return application group key ID.
87 : *
88 : */
89 0 : uint32_t ChipKeyId::MakeAppKeyId(uint32_t keyType, uint32_t rootKeyId, uint32_t epochKeyId, uint32_t appGroupMasterKeyId,
90 : bool useCurrentEpochKey)
91 : {
92 0 : return (keyType | (rootKeyId & kMask_RootKeyNumber) | (appGroupMasterKeyId & kMask_GroupLocalNumber) |
93 0 : (useCurrentEpochKey ? static_cast<uint32_t>(kFlag_UseCurrentEpochKey) : (epochKeyId & kMask_EpochKeyNumber)));
94 : }
95 :
96 : /**
97 : * Construct application intermediate key ID given constituent key IDs.
98 : *
99 : * @param[in] rootKeyId Root key ID used to derive application intermediate key.
100 : * @param[in] epochKeyId Epoch key ID used to derive application intermediate key.
101 : * @param[in] useCurrentEpochKey A boolean flag that indicates if key should be derived
102 : * using "current" epoch key.
103 : * @return application intermediate key ID.
104 : *
105 : */
106 0 : uint32_t ChipKeyId::MakeAppIntermediateKeyId(uint32_t rootKeyId, uint32_t epochKeyId, bool useCurrentEpochKey)
107 : {
108 0 : return MakeAppKeyId(kType_AppIntermediateKey, rootKeyId, epochKeyId, kNone, useCurrentEpochKey);
109 : }
110 :
111 : /**
112 : * Construct application rotating key ID given constituent key IDs and other information.
113 : *
114 : * @param[in] rootKeyId Root key ID used to derive application rotating key.
115 : * @param[in] epochKeyId Epoch key ID used to derive application rotating key.
116 : * @param[in] appGroupMasterKeyId Application group master key ID used to derive
117 : * application rotating key.
118 : * @param[in] useCurrentEpochKey A boolean flag that indicates if key should be derived
119 : * using "current" epoch key.
120 : * @return application rotating key ID.
121 : *
122 : */
123 0 : uint32_t ChipKeyId::MakeAppRotatingKeyId(uint32_t rootKeyId, uint32_t epochKeyId, uint32_t appGroupMasterKeyId,
124 : bool useCurrentEpochKey)
125 : {
126 0 : return MakeAppKeyId(kType_AppRotatingKey, rootKeyId, epochKeyId, appGroupMasterKeyId, useCurrentEpochKey);
127 : }
128 :
129 : /**
130 : * Construct application static key ID given constituent key IDs.
131 : *
132 : * @param[in] rootKeyId Root key ID used to derive application static key.
133 : * @param[in] appGroupMasterKeyId Application group master key ID used to derive
134 : * application static key.
135 : * @return application static key ID.
136 : *
137 : */
138 0 : uint32_t ChipKeyId::MakeAppStaticKeyId(uint32_t rootKeyId, uint32_t appGroupMasterKeyId)
139 : {
140 0 : return MakeAppKeyId(kType_AppStaticKey, rootKeyId, kNone, appGroupMasterKeyId, false);
141 : }
142 :
143 : /**
144 : * Convert application key ID to application static key ID.
145 : *
146 : * @param[in] keyId Application key ID.
147 : * @return application static key ID.
148 : *
149 : */
150 0 : uint32_t ChipKeyId::ConvertToStaticAppKeyId(uint32_t keyId)
151 : {
152 0 : return MakeAppStaticKeyId(GetRootKeyId(keyId), GetAppGroupMasterKeyId(keyId));
153 : }
154 :
155 : /**
156 : * Update application group key ID with new epoch key number.
157 : *
158 : * @param[in] keyId Application key ID.
159 : * @param[in] epochKeyId Epoch key ID, which will be used in construction
160 : * of the updated application key ID.
161 : * @return application key ID.
162 : *
163 : */
164 0 : uint32_t ChipKeyId::UpdateEpochKeyId(uint32_t keyId, uint32_t epochKeyId)
165 : {
166 0 : return (keyId & ~(kFlag_UseCurrentEpochKey | kMask_EpochKeyNumber)) | (epochKeyId & kMask_EpochKeyNumber);
167 : }
168 :
169 : /**
170 : * Determine whether key identifier has valid (legal) value.
171 : *
172 : * @param[in] keyId CHIP key ID.
173 : * @return true if key ID value is valid.
174 : *
175 : */
176 0 : bool ChipKeyId::IsValidKeyId(uint32_t keyId)
177 : {
178 0 : unsigned int usedBits = kMask_KeyType;
179 :
180 0 : switch (GetType(keyId))
181 : {
182 0 : case kType_None:
183 0 : return false;
184 0 : case kType_General:
185 : case kType_Session:
186 0 : usedBits |= kMask_KeyNumber;
187 0 : break;
188 0 : case kType_AppStaticKey:
189 0 : usedBits |= kMask_RootKeyNumber | kMask_GroupLocalNumber;
190 0 : break;
191 0 : case kType_AppRotatingKey:
192 0 : usedBits |= kFlag_UseCurrentEpochKey | kMask_RootKeyNumber | kMask_GroupLocalNumber;
193 0 : if (!UsesCurrentEpochKey(keyId))
194 : {
195 0 : usedBits |= kMask_EpochKeyNumber;
196 : }
197 0 : break;
198 0 : case kType_AppRootKey:
199 0 : usedBits |= kMask_RootKeyNumber;
200 0 : break;
201 0 : case kType_AppIntermediateKey:
202 0 : usedBits |= kFlag_UseCurrentEpochKey | kMask_RootKeyNumber;
203 0 : if (!UsesCurrentEpochKey(keyId))
204 : {
205 0 : usedBits |= kMask_EpochKeyNumber;
206 : }
207 0 : break;
208 0 : case kType_AppEpochKey:
209 0 : usedBits |= kFlag_UseCurrentEpochKey;
210 0 : if (!UsesCurrentEpochKey(keyId))
211 : {
212 0 : usedBits |= kMask_EpochKeyNumber;
213 : }
214 0 : break;
215 0 : case kType_AppGroupMasterKey:
216 0 : usedBits |= kMask_GroupLocalNumber;
217 0 : break;
218 0 : default:
219 0 : return false;
220 : }
221 :
222 0 : if (IncorporatesRootKey(keyId))
223 : {
224 0 : uint32_t rootKeyId = GetRootKeyId(keyId);
225 0 : VerifyOrReturnError(rootKeyId == kFabricRootKey || rootKeyId == kClientRootKey || rootKeyId == kServiceRootKey, false);
226 : }
227 :
228 0 : return (keyId & ~usedBits) == 0;
229 : }
230 :
231 : /**
232 : * Determine whether a given key ID identifies a key that is suitable for CHIP message encryption.
233 : *
234 : * @param[in] keyId CHIP key ID.
235 : * @param[in] allowLogicalKeys Specifies whether logical keys IDs (such as the "current" rotating key)
236 : * should be considered suitable for message encryption.
237 : * @return true If the identified key can be used to encrypt CHIP messages.
238 : *
239 : */
240 0 : bool ChipKeyId::IsMessageSessionId(uint32_t keyId, bool allowLogicalKeys)
241 : {
242 0 : switch (GetType(keyId))
243 : {
244 0 : case kType_Session:
245 : case kType_AppStaticKey:
246 0 : return true;
247 0 : case kType_AppRotatingKey:
248 0 : return allowLogicalKeys || !UsesCurrentEpochKey(keyId);
249 0 : default:
250 0 : return false;
251 : }
252 : }
253 :
254 : /**
255 : * Determines whether two key IDs identify the same key, or in the case of rotating keys, the same
256 : * group of keys independent of any particular epoch.
257 : *
258 : * @param[in] keyId1 The first key ID to test.
259 : * @param[in] keyId2 The second key ID to test.
260 : *
261 : * @return True if the keys IDs represent the same key.
262 : */
263 0 : bool ChipKeyId::IsSameKeyOrGroup(uint32_t keyId1, uint32_t keyId2)
264 : {
265 : enum
266 : {
267 : kIgnoreEpochMask = ~(kMask_EpochKeyNumber | kFlag_UseCurrentEpochKey)
268 : };
269 :
270 : // If the key ids are identical then they represent the same key.
271 0 : if (keyId1 == keyId2)
272 0 : return true;
273 :
274 : // For rotating keys, treat the key ids as the same if they differ only in their choice of epoch
275 : // key number.
276 0 : if (IncorporatesEpochKey(keyId1) && !IsAppEpochKey(keyId1) && (keyId1 & kIgnoreEpochMask) == (keyId2 & kIgnoreEpochMask))
277 0 : return true;
278 :
279 : // Otherwise the key ids identify different keys.
280 0 : return false;
281 : }
282 :
283 : /**
284 : * Decode a CHIP key identifier with a descriptive string.
285 : *
286 : * @param[in] keyId CHIP key ID to decode and for which to return
287 : * a descriptive string.
288 : *
289 : * @return A pointer to a NULL-terminated string describing the specified key ID.
290 : *
291 : */
292 0 : const char * ChipKeyId::DescribeKey(uint32_t keyId)
293 : {
294 : const char * retval;
295 :
296 0 : switch (GetType(keyId))
297 : {
298 0 : case kType_None:
299 0 : retval = "No Key";
300 0 : break;
301 0 : case kType_General:
302 0 : if (keyId == kFabricSecret)
303 : {
304 0 : retval = "Fabric Secret";
305 : }
306 : else
307 : {
308 0 : retval = "Other General Key";
309 : }
310 0 : break;
311 0 : case kType_Session:
312 0 : retval = "Session Key";
313 0 : break;
314 0 : case kType_AppStaticKey:
315 0 : retval = "Application Static Key";
316 0 : break;
317 0 : case kType_AppRotatingKey:
318 0 : retval = "Application Rotating Key";
319 0 : break;
320 0 : case kType_AppRootKey:
321 0 : if (keyId == kFabricRootKey)
322 : {
323 0 : retval = "Fabric Root Key";
324 : }
325 0 : else if (keyId == kClientRootKey)
326 : {
327 0 : retval = "Client Root Key";
328 : }
329 0 : else if (keyId == kServiceRootKey)
330 : {
331 0 : retval = "Service Root Key";
332 : }
333 : else
334 : {
335 0 : retval = "Other Root Key";
336 : }
337 0 : break;
338 0 : case kType_AppIntermediateKey:
339 0 : retval = "Application Intermediate Key";
340 0 : break;
341 0 : case kType_AppEpochKey:
342 0 : retval = "Application Epoch Key";
343 0 : break;
344 0 : case kType_AppGroupMasterKey:
345 0 : retval = "Application Group Master Key";
346 0 : break;
347 0 : default:
348 0 : retval = "Unknown Key Type";
349 : }
350 :
351 0 : return retval;
352 : }
353 :
354 : } // namespace chip
|