1 /*
2 * Copyright (c) 2020-2021 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 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21
22 #ifdef _CUT_AUTHENTICATE_
23 #undef HKS_SUPPORT_ECC_C
24 #endif /* _CUT_AUTHENTICATE_ */
25
26 #ifdef HKS_SUPPORT_ECC_C
27
28 #include "hks_mbedtls_ecc.h"
29
30 #include <mbedtls/bignum.h>
31 #include <mbedtls/ctr_drbg.h>
32 #include <mbedtls/ecp.h>
33 #include <mbedtls/entropy.h>
34
35 #include "hks_log.h"
36 #include "hks_mbedtls_common.h"
37 #include "hks_mem.h"
38 #include "hks_template.h"
39
40 #define HKS_ECC_KEYPAIR_CNT 3
41
HksMbedtlsEccCheckKeySize(const uint32_t keySize)42 static int32_t HksMbedtlsEccCheckKeySize(const uint32_t keySize)
43 {
44 if ((keySize != HKS_ECC_KEY_SIZE_224) && (keySize != HKS_ECC_KEY_SIZE_256) && (keySize != HKS_ECC_KEY_SIZE_384) &&
45 (keySize != HKS_ECC_KEY_SIZE_521)) {
46 HKS_LOG_E("Invalid ecc keySize! keySize = 0x%" LOG_PUBLIC "X", keySize);
47 return HKS_ERROR_INVALID_KEY_SIZE;
48 }
49
50 return HKS_SUCCESS;
51 }
52
GetEccGroupId(const uint32_t keyLen,mbedtls_ecp_group_id * grpId)53 int32_t GetEccGroupId(const uint32_t keyLen, mbedtls_ecp_group_id *grpId)
54 {
55 switch (keyLen) {
56 case HKS_ECC_KEY_SIZE_224:
57 *grpId = MBEDTLS_ECP_DP_SECP224R1;
58 break;
59 case HKS_ECC_KEY_SIZE_256:
60 *grpId = MBEDTLS_ECP_DP_SECP256R1;
61 break;
62 case HKS_ECC_KEY_SIZE_384:
63 *grpId = MBEDTLS_ECP_DP_SECP384R1;
64 break;
65 case HKS_ECC_KEY_SIZE_521:
66 *grpId = MBEDTLS_ECP_DP_SECP521R1;
67 break;
68 default:
69 HKS_LOG_E("Unsupported key length! keyLen: 0x%" LOG_PUBLIC "X", keyLen);
70 return HKS_ERROR_INVALID_KEY_SIZE;
71 }
72 return HKS_SUCCESS;
73 }
74
EccKeyMaterialXyzSizeCheck(const struct KeyMaterialEcc * keyMaterial)75 static int32_t EccKeyMaterialXyzSizeCheck(const struct KeyMaterialEcc *keyMaterial)
76 {
77 const uint32_t maxKeyByteLen = HKS_KEY_BYTES(HKS_ECC_KEY_SIZE_521);
78 if ((keyMaterial->xSize > maxKeyByteLen) ||
79 (keyMaterial->ySize > maxKeyByteLen) || (keyMaterial->zSize > maxKeyByteLen)) {
80 HKS_LOG_E("Invalid ecc keyMaterial! xSize = 0x%" LOG_PUBLIC "X, ySize = 0x%" LOG_PUBLIC "X, "
81 "zSize = 0x%" LOG_PUBLIC "X", keyMaterial->xSize, keyMaterial->ySize, keyMaterial->zSize);
82 return HKS_ERROR_INVALID_ARGUMENT;
83 }
84
85 return HKS_SUCCESS;
86 }
87
EccKeyCheck(const struct HksBlob * key)88 int32_t EccKeyCheck(const struct HksBlob *key)
89 {
90 const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(key->data);
91 int32_t ret = HksMbedtlsEccCheckKeySize(keyMaterial->keySize);
92 HKS_IF_NOT_SUCC_RETURN(ret, ret)
93
94 ret = EccKeyMaterialXyzSizeCheck(keyMaterial);
95 HKS_IF_NOT_SUCC_RETURN(ret, ret)
96
97 if (key->size < (sizeof(struct KeyMaterialEcc) + keyMaterial->xSize + keyMaterial->ySize + keyMaterial->zSize)) {
98 HKS_LOG_E("Ecc key size too small! key size = 0x%" LOG_PUBLIC "X", key->size);
99 return HKS_ERROR_INVALID_KEY_INFO;
100 }
101
102 return HKS_SUCCESS;
103 }
104
105 #if defined(HKS_SUPPORT_ECDH_C) || defined(HKS_SUPPORT_ECDSA_C)
HksMbedtlsEccGetKeyCurveNist(const struct KeyMaterialEcc * keyMaterial,mbedtls_ecp_group_id * curve)106 int32_t HksMbedtlsEccGetKeyCurveNist(const struct KeyMaterialEcc *keyMaterial, mbedtls_ecp_group_id *curve)
107 {
108 if ((keyMaterial->keyAlg != HKS_ALG_ECC) && (keyMaterial->keyAlg != HKS_ALG_ECDH)) {
109 HKS_LOG_E("Invalid param key! key mode = 0x%" LOG_PUBLIC "X", keyMaterial->keyAlg);
110 return HKS_ERROR_INVALID_ARGUMENT;
111 }
112
113 return GetEccGroupId(keyMaterial->keySize, curve);
114 }
115
HksEccKeyMaterialToPub(const struct HksBlob * key,mbedtls_ecp_point * pub)116 int32_t HksEccKeyMaterialToPub(const struct HksBlob *key, mbedtls_ecp_point *pub)
117 {
118 const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(key->data);
119
120 uint32_t offset = sizeof(*keyMaterial);
121 int32_t ret = mbedtls_mpi_read_binary(&(pub->MBEDTLS_PRIVATE(X)), key->data + offset, keyMaterial->xSize);
122 if (ret != HKS_MBEDTLS_SUCCESS) {
123 HKS_LOG_E("Ecc keyMaterial to public key read X failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
124 return ret;
125 }
126
127 offset = offset + keyMaterial->xSize;
128 ret = mbedtls_mpi_read_binary(&(pub->MBEDTLS_PRIVATE(Y)), key->data + offset, keyMaterial->ySize);
129 if (ret != HKS_MBEDTLS_SUCCESS) {
130 HKS_LOG_E("Ecc keyMaterial to public key read Y failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
131 return ret;
132 }
133
134 /* Z = 1, X and Y are its standard (affine) coordinates */
135 ret = mbedtls_mpi_lset(&(pub->MBEDTLS_PRIVATE(Z)), 1);
136 if (ret != HKS_MBEDTLS_SUCCESS) {
137 HKS_LOG_E("Ecc keyMaterial to public key set Z failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
138 return ret;
139 }
140
141 return HKS_SUCCESS;
142 }
143
HksEccKeyMaterialToPri(const struct HksBlob * key,mbedtls_mpi * pri)144 int32_t HksEccKeyMaterialToPri(const struct HksBlob *key, mbedtls_mpi *pri)
145 {
146 const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(key->data);
147
148 uint32_t offset = sizeof(*keyMaterial) + keyMaterial->xSize + keyMaterial->ySize;
149 int32_t ret = mbedtls_mpi_read_binary(pri, key->data + offset, keyMaterial->zSize);
150 if (ret != HKS_MBEDTLS_SUCCESS) {
151 HKS_LOG_E("Ecc keyMaterial to private key read Z failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
152 return ret;
153 }
154
155 return HKS_SUCCESS;
156 }
157 #endif /* HKS_SUPPORT_ECDH_C or HKS_SUPPORT_ECDSA_C */
158
159 #ifdef HKS_SUPPORT_ECC_GENERATE_KEY
EccSaveKeyMaterial(const mbedtls_ecp_keypair * ecp,const uint32_t keySize,struct HksBlob * key)160 static int32_t EccSaveKeyMaterial(const mbedtls_ecp_keypair *ecp,
161 const uint32_t keySize, struct HksBlob *key)
162 {
163 /* public exponent x and y, and private exponent, so need size is: key_size / 8 * 3 */
164 const uint32_t keyByteLen = HKS_KEY_BYTES(keySize);
165 const uint32_t rawMaterialLen = sizeof(struct KeyMaterialEcc) + keyByteLen * HKS_ECC_KEYPAIR_CNT;
166 uint8_t *rawMaterial = (uint8_t *)HksMalloc(rawMaterialLen);
167 HKS_IF_NULL_RETURN(rawMaterial, HKS_ERROR_MALLOC_FAIL)
168 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
169
170 /* ECC key data internal struct: struct KeyMaterialEcc + pubXData + pubYData + priData */
171 struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)rawMaterial;
172 keyMaterial->keyAlg = HKS_ALG_ECC;
173 keyMaterial->keySize = keySize;
174 keyMaterial->xSize = keyByteLen;
175 keyMaterial->ySize = keyByteLen;
176 keyMaterial->zSize = keyByteLen;
177
178 int32_t ret;
179 do {
180 uint32_t offset = sizeof(struct KeyMaterialEcc);
181 ret = mbedtls_mpi_write_binary(&(ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), rawMaterial + offset,
182 keyMaterial->xSize);
183 if (ret != HKS_MBEDTLS_SUCCESS) {
184 HKS_LOG_E("Save ecc keyMaterial write X failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
185 break;
186 }
187
188 offset = offset + keyMaterial->xSize;
189 ret = mbedtls_mpi_write_binary(&(ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), rawMaterial + offset,
190 keyMaterial->ySize);
191 if (ret != HKS_MBEDTLS_SUCCESS) {
192 HKS_LOG_E("Save ecc keyMaterial write Y failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
193 break;
194 }
195
196 offset = offset + keyMaterial->ySize;
197 ret = mbedtls_mpi_write_binary(&(ecp->MBEDTLS_PRIVATE(d)), rawMaterial + offset, keyMaterial->zSize);
198 if (ret != HKS_MBEDTLS_SUCCESS) {
199 HKS_LOG_E("Save ecc keyMaterial write D failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
200 break;
201 }
202
203 key->data = rawMaterial;
204 key->size = rawMaterialLen;
205 } while (0);
206
207 if (ret != HKS_MBEDTLS_SUCCESS) {
208 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
209 HKS_FREE(rawMaterial);
210 }
211
212 return ret;
213 }
214
HksMbedtlsEccGenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)215 int32_t HksMbedtlsEccGenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
216 {
217 mbedtls_ecp_group_id grpId;
218 int32_t ret = GetEccGroupId(spec->keyLen, &grpId);
219 HKS_IF_NOT_SUCC_RETURN(ret, ret)
220
221 mbedtls_entropy_context entropy;
222 mbedtls_ctr_drbg_context ctrDrbg;
223 (void)memset_s(&entropy, sizeof(mbedtls_entropy_context), 0, sizeof(mbedtls_entropy_context));
224 (void)memset_s(&ctrDrbg, sizeof(mbedtls_ctr_drbg_context), 0, sizeof(mbedtls_ctr_drbg_context));
225 ret = HksCtrDrbgSeed(&ctrDrbg, &entropy);
226 HKS_IF_NOT_SUCC_RETURN(ret, ret)
227
228 mbedtls_ecp_keypair ecp;
229 mbedtls_ecp_keypair_init(&ecp);
230
231 do {
232 ret = mbedtls_ecp_gen_key(grpId, &ecp, mbedtls_ctr_drbg_random, &ctrDrbg);
233 if (ret != HKS_MBEDTLS_SUCCESS) {
234 HKS_LOG_E("Mbedtls ecc generate key failed! ret = 0x%" LOG_PUBLIC "X", ret);
235 break;
236 }
237
238 ret = EccSaveKeyMaterial(&ecp, spec->keyLen, key);
239 } while (0);
240
241 mbedtls_ctr_drbg_free(&ctrDrbg);
242 mbedtls_entropy_free(&entropy);
243 mbedtls_ecp_keypair_free(&ecp);
244 return ret;
245 }
246 #endif /* HKS_SUPPORT_ECC_GENERATE_KEY */
247
248 #ifdef HKS_SUPPORT_ECC_GET_PUBLIC_KEY
GetEccPubKeyCheckParams(const struct HksBlob * keyIn,const struct HksBlob * keyOut)249 static int32_t GetEccPubKeyCheckParams(const struct HksBlob *keyIn, const struct HksBlob *keyOut)
250 {
251 int32_t ret = EccKeyCheck(keyIn);
252 HKS_IF_NOT_SUCC_RETURN(ret, ret)
253
254 /* check keyOut size */
255 const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(keyIn->data);
256 if ((keyMaterial->xSize == 0) || (keyMaterial->ySize == 0)) {
257 HKS_LOG_E("not support get pubkey");
258 return HKS_ERROR_NOT_SUPPORTED;
259 }
260
261 if (keyOut->size < (sizeof(struct KeyMaterialEcc) + keyMaterial->xSize + keyMaterial->ySize)) {
262 HKS_LOG_E("Ecc public keyOut size too small! keyOut size = 0x%" LOG_PUBLIC "X", keyOut->size);
263 return HKS_ERROR_BUFFER_TOO_SMALL;
264 }
265
266 return HKS_SUCCESS;
267 }
268
HksMbedtlsGetEccPubKey(const struct HksBlob * keyIn,struct HksBlob * keyOut)269 int32_t HksMbedtlsGetEccPubKey(const struct HksBlob *keyIn, struct HksBlob *keyOut)
270 {
271 int32_t ret = GetEccPubKeyCheckParams(keyIn, keyOut);
272 HKS_IF_NOT_SUCC_RETURN(ret, ret)
273
274 /* x + y, so need size is: sizeof(struct HksPubKeyInfo) + xSize + ySize */
275 const struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)(keyIn->data);
276 uint32_t outLen = sizeof(struct KeyMaterialEcc) + keyMaterial->xSize + keyMaterial->ySize;
277 if (memcpy_s(keyOut->data, keyOut->size, (void *)keyMaterial, outLen) != EOK) {
278 HKS_LOG_E("Memcpy ecc public key fail!");
279 (void)memset_s(keyOut->data, keyOut->size, 0, keyOut->size);
280 return HKS_ERROR_INSUFFICIENT_MEMORY;
281 }
282 ((struct KeyMaterialEcc *)(keyOut->data))->zSize = 0;
283 keyOut->size = outLen;
284
285 return HKS_SUCCESS;
286 }
287 #endif /* HKS_SUPPORT_ECC_GET_PUBLIC_KEY */
288 #endif /* HKS_SUPPORT_ECC_C */
289