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