赞
踩
主要是ecc算法在鸿蒙系统中的代码实现,以及相关知识点注意事项
文件路径(security_huks\frameworks\huks_standard\main\crypto_engine\mbedtls\src\hks_mbedtls_ecc.c)
ecc算法介绍传送门
密钥size检查函数
#define HKS_ECC_KEYPAIR_CNT 3
//检查密钥size是否为256和384
static int32_t HksMbedtlsEccCheckKeySize(const uint32_t keySize)
{
if ((keySize != HKS_ECC_KEY_SIZE_256) && (keySize != HKS_ECC_KEY_SIZE_384)) {
HKS_LOG_E("Invalid ecc keySize! keySize = 0x%X", keySize);
return HKS_ERROR_INVALID_KEY_SIZE;
}
return HKS_SUCCESS;
}
曲线群id的获取
该函数通过传入的keylen,得到不通的grpid。
参数介绍
//获取曲线群的id信息 int32_t GetEccGroupId(const uint32_t keyLen, mbedtls_ecp_group_id *grpId) { switch (keyLen) { //通过不同的keylen就可以判断出曲线的不同分支 case HKS_ECC_KEY_SIZE_256: *grpId = MBEDTLS_ECP_DP_SECP256R1; //256长度的对应MBEDTLS_ECP_DP_SECP256R1 break; case HKS_ECC_KEY_SIZE_384: *grpId = MBEDTLS_ECP_DP_SECP384R1; //384长度的对应MBEDTLS_ECP_DP_SECP384R1 break; default: HKS_LOG_E("Unsupported key length! keyLen: 0x%X", keyLen); return HKS_ERROR_INVALID_KEY_SIZE; } return HKS_SUCCESS; }
检查密钥材料三个维度的size信息
static int32_t EccKeyMaterialXyzSizeCheck(const struct KeyMaterialEcc *keyMaterial)
{
const uint32_t maxKeyByteLen = HKS_ECC_KEY_SIZE_384 / HKS_BITS_PER_BYTE; //计算密钥最大位数
//计算位数方式密钥最大长度除以每位对应的字节数
if ((keyMaterial->xSize > maxKeyByteLen) ||
(keyMaterial->ySize > maxKeyByteLen) || (keyMaterial->zSize > maxKeyByteLen)) {
HKS_LOG_E("Invalid ecc keyMaterial! xSize = 0x%X, ySize = 0x%X, zSize = 0x%X",
keyMaterial->xSize, keyMaterial->ySize, keyMaterial->zSize);
return HKS_ERROR_INVALID_ARGUMENT;
}
//密钥材料的三个维度xyz只要有一个的长度大于计算得到的maxKeyByteLen,函数就返回错误值
return HKS_SUCCESS;
}
根据密钥材料信息来计算密钥信息并实现参数的检查
//检查ecc密钥 int32_t EccKeyCheck(const struct HksBlob *key) { const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(key->data); int32_t ret = HksMbedtlsEccCheckKeySize(keyMaterial->keySize); //先检查keyMaterial->keySize的大小 if (ret != HKS_SUCCESS) { return ret; } ret = EccKeyMaterialXyzSizeCheck(keyMaterial); //检查密钥材料三个维度的大小 if (ret != HKS_SUCCESS) { return ret; } if (key->size < (sizeof(struct KeyMaterialEcc) + keyMaterial->xSize + keyMaterial->ySize + keyMaterial->zSize)) { HKS_LOG_E("Ecc key size too small! key size = 0x%X", key->size); return HKS_ERROR_INVALID_KEY_INFO; } //检查key->size大小,如果小于密钥材料的三个维度的size大小之和就返回错误值 return HKS_SUCCESS; }
获取密钥的曲线nist信息
//获取密钥曲线nist
int32_t HksMbedtlsEccGetKeyCurveNist(const struct KeyMaterialEcc *keyMaterial, mbedtls_ecp_group_id *curve)
{
if ((keyMaterial->keyAlg != HKS_ALG_ECC) && (keyMaterial->keyAlg != HKS_ALG_ECDH)) {
HKS_LOG_E("Invalid param key! key mode = 0x%X", keyMaterial->keyAlg);
return HKS_ERROR_INVALID_ARGUMENT;
}
//检查算法是否是ecc或者ecdh当中过的一个
return GetEccGroupId(keyMaterial->keySize, curve);
//将曲线群的id写进curve
}
公钥转换
//将ecc密钥材料转换为公钥 int32_t HksEccKeyMaterialToPub(const struct HksBlob *key, mbedtls_ecp_point *pub) { const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(key->data); uint32_t offset = sizeof(*keyMaterial);//定义偏置 int32_t ret = mbedtls_mpi_read_binary(&(pub->X), key->data + offset, keyMaterial->xSize); //从二进制读取信息,写进pub->X if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Ecc keyMaterial to public key read X failed! mbedtls ret = 0x%X", ret); return ret; } offset = offset + keyMaterial->xSize; //更新偏置信息 ret = mbedtls_mpi_read_binary(&(pub->Y), key->data + offset, keyMaterial->ySize); //将材料中y维度的数据读进公钥的Y部分 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Ecc keyMaterial to public key read Y failed! mbedtls ret = 0x%X", ret); return ret; } /* Z = 1, X and Y are its standard (affine) coordinates */ ret = mbedtls_mpi_lset(&(pub->Z), 1); //初始化公钥的Z维度为1 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Ecc keyMaterial to public key set Z failed! mbedtls ret = 0x%X", ret); return ret; } return HKS_SUCCESS; }
私钥转换
//将密钥材料转换为私钥 int32_t HksEccKeyMaterialToPri(const struct HksBlob *key, mbedtls_mpi *pri) { const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(key->data); uint32_t offset = sizeof(*keyMaterial) + keyMaterial->xSize + keyMaterial->ySize; //定义偏置offset为x维度和y维度长度加keyMaterial所占长度 int32_t ret = mbedtls_mpi_read_binary(pri, key->data + offset, keyMaterial->zSize); //将结果写进pri私钥 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Ecc keyMaterial to private key read Z failed! mbedtls ret = 0x%X", ret); return ret; } return HKS_SUCCESS; } #endif /* HKS_SUPPORT_ECDH_C or HKS_SUPPORT_ECDSA_C */
密钥参数的保存
#ifdef HKS_SUPPORT_ECC_GENERATE_KEY static int32_t EccSaveKeyMaterial(const mbedtls_ecp_keypair *ecp, const uint32_t keySize, struct HksBlob *key) { /* public exponent x and y, and private exponent, so need size is: key_size / 8 * 3 */ //x和y为公共参数 const uint32_t keyByteLen = keySize / HKS_BITS_PER_BYTE; //计算密钥字节数 const uint32_t rawMaterialLen = sizeof(struct KeyMaterialEcc) + keyByteLen * HKS_ECC_KEYPAIR_CNT; //定义长度用来申请内存 uint8_t *rawMaterial = (uint8_t *)HksMalloc(rawMaterialLen); //申请内存空间,大小rawMaterialLen if (rawMaterial == NULL) { return HKS_ERROR_MALLOC_FAIL; } (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen); //初始化刚刚申请的空间 /* ECC key data internel struct: struct KeyMaterialEcc + pubXData + pubYData + priData */ struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)rawMaterial; keyMaterial->keyAlg = HKS_ALG_ECC; keyMaterial->keySize = keySize; keyMaterial->xSize = keyByteLen; keyMaterial->ySize = keyByteLen; keyMaterial->zSize = keyByteLen; //对keyMaterial的各个属性进行赋值 int32_t ret; do { uint32_t offset = sizeof(struct KeyMaterialEcc); //定义偏置变量 ret = mbedtls_mpi_write_binary(&(ecp->Q.X), rawMaterial + offset, keyMaterial->xSize); //从rawMaterial以指定偏置和长度读取信息进ecp->Q.X if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Save ecc keyMaterial write X failed! mbedtls ret = 0x%X", ret); break; } offset = offset + keyMaterial->xSize; //更新偏置 ret = mbedtls_mpi_write_binary(&(ecp->Q.Y), rawMaterial + offset, keyMaterial->ySize); //从rawMaterial以指定偏置和长度读取信息进ecp->Q.Y if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Save ecc keyMaterial write Y failed! mbedtls ret = 0x%X", ret); break; } offset = offset + keyMaterial->ySize; //更新偏置 ret = mbedtls_mpi_write_binary(&(ecp->d), rawMaterial + offset, keyMaterial->zSize); //从rawMaterial以指定偏置和长度读取信息进ecp->Q.Z if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Save ecc keyMaterial write D failed! mbedtls ret = 0x%X", ret); break; } key->data = rawMaterial; key->size = rawMaterialLen; //最后将最终结果写进key中 } while (0); if (ret != HKS_MBEDTLS_SUCCESS) { (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen); HKS_FREE_PTR(rawMaterial); } return ret; }
生成ecc中的密钥
//生成ecc密钥 int32_t HksMbedtlsEccGenerateKey(const struct HksKeySpec *spec, struct HksBlob *key) { mbedtls_ecp_group_id grpId;//定义曲线群 int32_t ret = GetEccGroupId(spec->keyLen, &grpId); //获取算法对应曲线群id if (ret != HKS_SUCCESS) { return ret; } mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctrDrbg; ret = HksCtrDrbgSeed(&ctrDrbg, &entropy); //伪随机数的生成 if (ret != HKS_SUCCESS) { return ret; } mbedtls_ecp_keypair ecp; mbedtls_ecp_keypair_init(&ecp); //定义初始化一对密钥(公钥加私钥) do { ret = mbedtls_ecp_gen_key(grpId, &ecp, mbedtls_ctr_drbg_random, &ctrDrbg); //生成密钥信息,在ecp中 if (ret != HKS_MBEDTLS_SUCCESS) { HKS_LOG_E("Mbedtls ecc generate key failed! ret = 0x%X", ret); break; } ret = EccSaveKeyMaterial(&ecp, spec->keyLen, key); //保存密钥信息在ecp中 } while (0); mbedtls_ctr_drbg_free(&ctrDrbg); mbedtls_entropy_free(&entropy); mbedtls_ecp_keypair_free(&ecp); //释放相关空间 return ret; }
下面主要是参数的检查的密钥的获取
//获取公钥并检查参数(size) static int32_t GetEccPubKeyCheckParams(const struct HksBlob *keyIn, const struct HksBlob *keyOut) { int32_t ret = EccKeyCheck(keyIn); if (ret != HKS_SUCCESS) { return ret; } /* check keyOut size */ const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(keyIn->data); if (keyOut->size < (sizeof(struct KeyMaterialEcc) + keyMaterial->xSize + keyMaterial->ySize)) { HKS_LOG_E("Ecc public keyOut size too small! keyOut size = 0x%X", keyOut->size); return HKS_ERROR_BUFFER_TOO_SMALL; } //如果keyOut->size小于sizeof(struct KeyMaterialEcc)+xsize+ysize函数就返回报错 return HKS_SUCCESS; }
//获取公钥信息 int32_t HksMbedtlsGetEccPubKey(const struct HksBlob *keyIn, struct HksBlob *keyOut) { int32_t ret = GetEccPubKeyCheckParams(keyIn, keyOut); //检查keyin的参数 if (ret != HKS_SUCCESS) { return ret; } /* x + y, so need size is: sizeof(struct HksPubKeyInfo) + xSize + ySize */ const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(keyIn->data); uint32_t outLen = sizeof(struct KeyMaterialEcc) + keyMaterial->xSize + keyMaterial->ySize; //定义outlen = sizeof(struct HksPubKeyInfo) + xSize + ySize if (memcpy_s(keyOut->data, keyOut->size, (void *)keyMaterial, outLen) != EOK) { //初始化keyOut->data中的内容为keyMaterial HKS_LOG_E("Memcpy ecc public key fail!"); (void)memset_s(keyOut->data, keyOut->size, 0, keyOut->size); return HKS_ERROR_BAD_STATE; } ((struct KeyMaterialEcc *)(keyOut->data))->zSize = 0; //将材料z维度初始化为全0 keyOut->size = outLen; return HKS_SUCCESS; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。