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