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