1/* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "key_manager.h" 17 18#include "alg_defs.h" 19#include "alg_loader.h" 20#include "common_defs.h" 21#include "device_auth_defines.h" 22#include "hc_dev_info.h" 23#include "hc_log.h" 24#include "hc_types.h" 25#include "json_utils.h" 26#include "pseudonym_manager.h" 27#include "uint8buff_utils.h" 28 29#define PAKE_X25519_KEY_PAIR_LEN 32 30#define MK_LEN 32 31#define MK_DERIVE_INFO "dev_auth_mk_derivation" 32#define PAKE_KEY_ALIAS_LEN 64 33#define MK_ALIAS_PREFIX "MK_" 34#define PSEUDONYM_PSK_ALIAS_PREFIX "PSEUDONYM_" 35 36static int32_t ConvertHashToAlias(const Uint8Buff *keyAliasHash, Uint8Buff *outKeyAlias) 37{ 38 uint32_t keyAliasHexLen = keyAliasHash->length * BYTE_TO_HEX_OPER_LENGTH + 1; 39 char *keyAliasHex = (char *)HcMalloc(keyAliasHexLen, 0); 40 if (keyAliasHex == NULL) { 41 LOGE("Failed to alloc key alias hex memory!"); 42 return HC_ERR_ALLOC_MEMORY; 43 } 44 int32_t res = ByteToHexString(keyAliasHash->val, keyAliasHash->length, keyAliasHex, keyAliasHexLen); 45 if (res != HC_SUCCESS) { 46 LOGE("Failed to convert key alias hash to hex!"); 47 HcFree(keyAliasHex); 48 return res; 49 } 50 if (memcpy_s(outKeyAlias->val, outKeyAlias->length, keyAliasHex, HcStrlen(keyAliasHex)) != EOK) { 51 LOGE("Failed to copy key alias hex!"); 52 HcFree(keyAliasHex); 53 return HC_ERR_MEMORY_COPY; 54 } 55 HcFree(keyAliasHex); 56 return HC_SUCCESS; 57} 58 59static int32_t ConvertHashToAliasWithPrefix(const char *prefix, const Uint8Buff *keyAliasHash, Uint8Buff *keyAlias) 60{ 61 uint32_t keyAliasHexLen = keyAliasHash->length * BYTE_TO_HEX_OPER_LENGTH + 1; 62 char *keyAliasHex = (char *)HcMalloc(keyAliasHexLen, 0); 63 if (keyAliasHex == NULL) { 64 LOGE("Failed to alloc key alias hex memory!"); 65 return HC_ERR_ALLOC_MEMORY; 66 } 67 int32_t res = ByteToHexString(keyAliasHash->val, keyAliasHash->length, keyAliasHex, keyAliasHexLen); 68 if (res != HC_SUCCESS) { 69 LOGE("Failed to convert key alias hash to hex!"); 70 HcFree(keyAliasHex); 71 return res; 72 } 73 uint32_t prefixLen = HcStrlen(prefix); 74 if (memcpy_s(keyAlias->val, keyAlias->length, prefix, prefixLen) != EOK) { 75 LOGE("Failed to copy key alias prefix!"); 76 HcFree(keyAliasHex); 77 return HC_ERR_MEMORY_COPY; 78 } 79 // The remaining key alias len is less than keyAliasHexLen len after substract prefixLen, 80 // so copy the remaining len other than keyAliasHexLen in order that the key alias len is 64. 81 if (memcpy_s(keyAlias->val + prefixLen, keyAlias->length - prefixLen, keyAliasHex, 82 keyAlias->length - prefixLen) != EOK) { 83 LOGE("Failed to copy key alias hex!"); 84 HcFree(keyAliasHex); 85 return HC_ERR_MEMORY_COPY; 86 } 87 HcFree(keyAliasHex); 88 return HC_SUCCESS; 89} 90 91static int32_t GenerateDevKeyAlias(Uint8Buff *outKeyAlias) 92{ 93 char selfUdid[INPUT_UDID_LEN] = { 0 }; 94 int32_t res = HcGetUdid((uint8_t *)selfUdid, INPUT_UDID_LEN); 95 if (res != HC_SUCCESS) { 96 LOGE("Failed to get local udid!"); 97 return res; 98 } 99 uint8_t hashValue[SHA256_LEN] = { 0 }; 100 Uint8Buff keyAliasHash = { hashValue, SHA256_LEN }; 101 Uint8Buff msgBuff = { (uint8_t *)selfUdid, HcStrlen(selfUdid) }; 102 res = GetLoaderInstance()->sha256(&msgBuff, &keyAliasHash); 103 if (res != HC_SUCCESS) { 104 LOGE("Failed to generate key alias hash!"); 105 return res; 106 } 107 res = ConvertHashToAlias(&keyAliasHash, outKeyAlias); 108 if (res != HC_SUCCESS) { 109 LOGE("Failed to convert hash to alias!"); 110 } 111 return res; 112} 113 114static int32_t GenerateMkAlias(const char *peerDeviceId, Uint8Buff *keyAlias) 115{ 116 Uint8Buff peerDevIdBuff = { (uint8_t *)peerDeviceId, HcStrlen(peerDeviceId) }; 117 uint8_t hashValue[SHA256_LEN] = { 0 }; 118 Uint8Buff keyAliasHash = { hashValue, SHA256_LEN }; 119 int32_t res = GetLoaderInstance()->sha256(&peerDevIdBuff, &keyAliasHash); 120 if (res != HC_SUCCESS) { 121 LOGE("Failed to generate key alias hash!"); 122 return res; 123 } 124 res = ConvertHashToAliasWithPrefix(MK_ALIAS_PREFIX, &keyAliasHash, keyAlias); 125 if (res != HC_SUCCESS) { 126 LOGE("Failed to convert hash to alias!"); 127 } 128 return res; 129} 130 131static int32_t GeneratePseudonymPskAlias(const char *peerDeviceId, Uint8Buff *keyAlias) 132{ 133 uint8_t hashValue[SHA256_LEN] = { 0 }; 134 Uint8Buff keyAliasHash = { hashValue, SHA256_LEN }; 135 Uint8Buff peerDevIdBuff = { (uint8_t *)peerDeviceId, HcStrlen(peerDeviceId) }; 136 int32_t res = GetLoaderInstance()->sha256(&peerDevIdBuff, &keyAliasHash); 137 if (res != HC_SUCCESS) { 138 LOGE("Failed to generate key alias hash!"); 139 return res; 140 } 141 142 res = ConvertHashToAliasWithPrefix(PSEUDONYM_PSK_ALIAS_PREFIX, &keyAliasHash, keyAlias); 143 if (res != HC_SUCCESS) { 144 LOGE("Failed to convert hash to alias!"); 145 } 146 return res; 147} 148 149static int32_t KeyDerivation(int32_t osAccountId, const Uint8Buff *baseAlias, const Uint8Buff *salt, bool isAlias, 150 Uint8Buff *returnKey) 151{ 152 Uint8Buff keyInfo = { (uint8_t *)MK_DERIVE_INFO, HcStrlen(MK_DERIVE_INFO) }; 153 KeyParams keyAliasParams = { { baseAlias->val, baseAlias->length, isAlias }, false, osAccountId }; 154 int32_t res = GetLoaderInstance()->computeHkdf(&keyAliasParams, salt, &keyInfo, returnKey); 155 if (res != HC_SUCCESS) { 156 LOGE("Failed to compute hkdf!"); 157 } 158 return res; 159} 160 161int32_t GenerateDeviceKeyPair(int32_t osAccountId) 162{ 163 uint8_t keyAlias[PAKE_KEY_ALIAS_LEN] = { 0 }; 164 Uint8Buff keyAliasBuff = { keyAlias, PAKE_KEY_ALIAS_LEN }; 165 int32_t res = GenerateDevKeyAlias(&keyAliasBuff); 166 if (res != HC_SUCCESS) { 167 LOGE("Failed to generate device key alias!"); 168 return res; 169 } 170 if (GetLoaderInstance()->checkKeyExist(&keyAliasBuff, false, osAccountId) == HC_SUCCESS) { 171 LOGI("Device Key pair already exists!"); 172 return HC_SUCCESS; 173 } 174 175 char selfUdid[INPUT_UDID_LEN] = { 0 }; 176 res = HcGetUdid((uint8_t *)selfUdid, INPUT_UDID_LEN); 177 if (res != HC_SUCCESS) { 178 LOGE("Failed to get local udid!"); 179 return res; 180 } 181 Uint8Buff authIdBuff = { (uint8_t *)selfUdid, HcStrlen(selfUdid) }; 182 ExtraInfo exInfo = { authIdBuff, -1, -1 }; 183 KeyParams keyParams = { { keyAliasBuff.val, keyAliasBuff.length, true }, false, osAccountId }; 184 res = GetLoaderInstance()->generateKeyPairWithStorage(&keyParams, PAKE_X25519_KEY_PAIR_LEN, X25519, 185 KEY_PURPOSE_SIGN_VERIFY, &exInfo); 186 if (res != HC_SUCCESS) { 187 LOGE("Failed to generate device key pair!"); 188 return res; 189 } 190 LOGI("Generate device key pair successfully!"); 191 return HC_SUCCESS; 192} 193 194int32_t GenerateMk(int32_t osAccountId, const char *peerDeviceId, const Uint8Buff *peerPubKey) 195{ 196 if (peerDeviceId == NULL || peerPubKey == NULL) { 197 LOGE("Invalid input params!"); 198 return HC_ERR_INVALID_PARAMS; 199 } 200 uint8_t mkAlias[PAKE_KEY_ALIAS_LEN] = { 0 }; 201 Uint8Buff mkAliasBuff = { mkAlias, PAKE_KEY_ALIAS_LEN }; 202 int32_t res = GenerateMkAlias(peerDeviceId, &mkAliasBuff); 203 if (res != HC_SUCCESS) { 204 LOGE("Failed to generate mk alias!"); 205 return res; 206 } 207 uint8_t devKeyAlias[PAKE_KEY_ALIAS_LEN] = { 0 }; 208 Uint8Buff devKeyAliasBuff = { devKeyAlias, PAKE_KEY_ALIAS_LEN }; 209 res = GenerateDevKeyAlias(&devKeyAliasBuff); 210 if (res != HC_SUCCESS) { 211 LOGE("Failed to generate device key alias!"); 212 return res; 213 } 214 KeyParams selfKeyParams = { { devKeyAliasBuff.val, devKeyAliasBuff.length, true }, false, osAccountId }; 215 KeyBuff peerKeyBuff = { peerPubKey->val, peerPubKey->length, false }; 216 res = GetLoaderInstance()->agreeSharedSecretWithStorage(&selfKeyParams, &peerKeyBuff, X25519, 217 MK_LEN, &mkAliasBuff); 218 if (res != HC_SUCCESS) { 219 LOGE("Failed to agree sharedSecret!"); 220 return res; 221 } 222 LOGI("Generate mk successfully!"); 223 return HC_SUCCESS; 224} 225 226int32_t DeleteMk(int32_t osAccountId, const char *peerDeviceId) 227{ 228 if (peerDeviceId == NULL) { 229 LOGE("Invalid input param!"); 230 return HC_ERR_INVALID_PARAMS; 231 } 232 uint8_t mkAlias[PAKE_KEY_ALIAS_LEN] = { 0 }; 233 Uint8Buff mkAliasBuff = { mkAlias, PAKE_KEY_ALIAS_LEN }; 234 int32_t res = GenerateMkAlias(peerDeviceId, &mkAliasBuff); 235 if (res != HC_SUCCESS) { 236 LOGE("Failed to generate mk alias!"); 237 return res; 238 } 239 if (GetLoaderInstance()->checkKeyExist(&mkAliasBuff, false, osAccountId) != HC_SUCCESS) { 240 LOGI("mk does not exist, no need to delete!"); 241 return HC_SUCCESS; 242 } 243 res = GetLoaderInstance()->deleteKey(&mkAliasBuff, false, osAccountId); 244 if (res != HC_SUCCESS) { 245 LOGE("Failed to delete mk!"); 246 return res; 247 } 248 LOGI("Delete mk successfully!"); 249 return HC_SUCCESS; 250} 251 252int32_t GeneratePseudonymPsk(int32_t osAccountId, const char *peerDeviceId, const Uint8Buff *salt) 253{ 254 if (peerDeviceId == NULL || salt == NULL) { 255 LOGE("Invalid input params!"); 256 return HC_ERR_INVALID_PARAMS; 257 } 258 uint8_t pseudonymPskAlias[PAKE_KEY_ALIAS_LEN] = { 0 }; 259 Uint8Buff pskAliasBuff = { pseudonymPskAlias, PAKE_KEY_ALIAS_LEN }; 260 int32_t res = GeneratePseudonymPskAlias(peerDeviceId, &pskAliasBuff); 261 if (res != HC_SUCCESS) { 262 LOGE("Failed to generate pseudonym psk alias!"); 263 return res; 264 } 265 uint8_t mkAlias[PAKE_KEY_ALIAS_LEN] = { 0 }; 266 Uint8Buff mkAliasBuff = { mkAlias, PAKE_KEY_ALIAS_LEN }; 267 res = GenerateMkAlias(peerDeviceId, &mkAliasBuff); 268 if (res != HC_SUCCESS) { 269 LOGE("Failed to generate mk alias!"); 270 return res; 271 } 272 Uint8Buff pskBuff = { NULL, 0 }; 273 if (InitUint8Buff(&pskBuff, MK_LEN) != HC_SUCCESS) { 274 LOGE("Failed to init pseudonym psk!"); 275 return HC_ERR_ALLOC_MEMORY; 276 } 277 res = KeyDerivation(osAccountId, &mkAliasBuff, salt, true, &pskBuff); 278 if (res != HC_SUCCESS) { 279 LOGE("Failed to derive pseudonym psk!"); 280 FreeUint8Buff(&pskBuff); 281 return res; 282 } 283 KeyParams keyParams = { { pskAliasBuff.val, pskAliasBuff.length, true }, false, osAccountId }; 284 res = GetLoaderInstance()->importSymmetricKey(&keyParams, &pskBuff, KEY_PURPOSE_MAC, NULL); 285 ClearFreeUint8Buff(&pskBuff); 286 if (res != HC_SUCCESS) { 287 LOGE("Failed to import pseudonym psk!"); 288 return res; 289 } 290 LOGI("Generate and save pseudonym psk successfully!"); 291 return HC_SUCCESS; 292} 293 294int32_t DeletePseudonymPsk(int32_t osAccountId, const char *peerDeviceId) 295{ 296 if (peerDeviceId == NULL) { 297 LOGE("Invalid input param!"); 298 return HC_ERR_INVALID_PARAMS; 299 } 300 uint8_t pseudonymPskAlias[PAKE_KEY_ALIAS_LEN] = { 0 }; 301 Uint8Buff pskAliasBuff = { pseudonymPskAlias, PAKE_KEY_ALIAS_LEN }; 302 int32_t res = GeneratePseudonymPskAlias(peerDeviceId, &pskAliasBuff); 303 if (res != HC_SUCCESS) { 304 LOGE("Failed to generate psk alias!"); 305 return res; 306 } 307 if (GetLoaderInstance()->checkKeyExist(&pskAliasBuff, false, osAccountId) != HC_SUCCESS) { 308 LOGI("Pseudonym psk does not exist, no need to delete!"); 309 return HC_SUCCESS; 310 } 311 res = GetLoaderInstance()->deleteKey(&pskAliasBuff, false, osAccountId); 312 if (res != HC_SUCCESS) { 313 LOGE("Failed to delete pseudonym psk!"); 314 return res; 315 } 316 LOGI("Delete pseudonym psk successfully!"); 317 return HC_SUCCESS; 318} 319 320int32_t GenerateAndSavePseudonymId(int32_t osAccountId, const char *peerDeviceId, const PseudonymKeyInfo *info, 321 const Uint8Buff *saltBuff, Uint8Buff *returnHmac) 322{ 323 if (peerDeviceId == NULL || info == NULL || saltBuff == NULL || returnHmac == NULL) { 324 LOGE("Invalid input params!"); 325 return HC_ERR_INVALID_PARAMS; 326 } 327 uint8_t pskAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 }; 328 Uint8Buff pskAliasBuff = { pskAliasVal, PAKE_KEY_ALIAS_LEN }; 329 int32_t res = GeneratePseudonymPskAlias(peerDeviceId, &pskAliasBuff); 330 if (res != HC_SUCCESS) { 331 LOGE("Failed to generate pseudonym psk alias!"); 332 return res; 333 } 334 uint8_t pseudonymIdVal[MK_LEN] = { 0 }; 335 Uint8Buff pseudonymIdBuff = { pseudonymIdVal, MK_LEN }; 336 KeyParams keyParams = { { pskAliasBuff.val, pskAliasBuff.length, true }, false, osAccountId }; 337 res = GetLoaderInstance()->computeHmac(&keyParams, saltBuff, &pseudonymIdBuff); 338 if (res != HC_SUCCESS) { 339 LOGE("Failed to compute hmac!"); 340 return res; 341 } 342 if (DeepCopyUint8Buff(&pseudonymIdBuff, returnHmac) != HC_SUCCESS) { 343 LOGE("Failed to copy hmac!"); 344 return HC_ERR_ALLOC_MEMORY; 345 } 346 uint32_t pdidLen = pseudonymIdBuff.length * BYTE_TO_HEX_OPER_LENGTH + 1; 347 char *pdid = (char *)HcMalloc(pdidLen, 0); 348 if (pdid == NULL) { 349 LOGE("Failed to alloc memory for pdid!"); 350 ClearFreeUint8Buff(returnHmac); 351 return HC_ERR_ALLOC_MEMORY; 352 } 353 res = ByteToHexString(pseudonymIdBuff.val, pseudonymIdBuff.length, pdid, pdidLen); 354 if (res != HC_SUCCESS) { 355 LOGE("Failed to convert pdid from byte to hex string!"); 356 ClearFreeUint8Buff(returnHmac); 357 HcFree(pdid); 358 return res; 359 } 360 res = GetPseudonymInstance()->savePseudonymId(osAccountId, pdid, info->peerInfo, peerDeviceId, info->pdidIndex); 361 HcFree(pdid); 362 if (res != HC_SUCCESS) { 363 LOGE("Failed to save pdid!"); 364 ClearFreeUint8Buff(returnHmac); 365 return res; 366 } 367 LOGI("Generate and save pdid successfully!"); 368 return HC_SUCCESS; 369} 370 371int32_t GetDevicePubKey(int32_t osAccountId, Uint8Buff *devicePk) 372{ 373 if (devicePk == NULL) { 374 LOGE("Invalid input param!"); 375 return HC_ERR_INVALID_PARAMS; 376 } 377 uint8_t keyAlias[PAKE_KEY_ALIAS_LEN] = { 0 }; 378 Uint8Buff keyAliasBuff = { keyAlias, PAKE_KEY_ALIAS_LEN }; 379 int32_t res = GenerateDevKeyAlias(&keyAliasBuff); 380 if (res != HC_SUCCESS) { 381 LOGE("Failed to generate device key alias!"); 382 return res; 383 } 384 KeyParams keyParams = { { keyAliasBuff.val, keyAliasBuff.length, true }, false, osAccountId }; 385 res = GetLoaderInstance()->exportPublicKey(&keyParams, devicePk); 386 if (res != HC_SUCCESS) { 387 LOGE("Failed to export device pk!"); 388 } 389 return res; 390}