• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "mbedtls_ec_adapter.h"
17 
18 #include <mbedtls/ctr_drbg.h>
19 #include <mbedtls/entropy.h>
20 #include <mbedtls/error.h>
21 #include <mbedtls/pk.h>
22 #include <mbedtls/x509.h>
23 
24 #include "hal_error.h"
25 #include "hc_log.h"
26 #include "huks_adapter.h"
27 
28 #define LOG_AND_RETURN_IF_MBED_FAIL(ret, fmt, ...) \
29 do { \
30     if ((ret) != 0) { \
31         LOGE(fmt, ##__VA_ARGS__); \
32         return HAL_ERR_MBEDTLS; \
33     } \
34 } while (0)
35 
36 #define LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, fmt, ...) \
37 do { \
38     if ((ret) != 0) { \
39         LOGE(fmt, ##__VA_ARGS__); \
40         goto CLEAN_UP; \
41     } \
42 } while (0)
43 
44 #define BITS_PER_BYTE 8
45 #define EC_LEN 64
46 #define SHA256_HASH_LEN 32
47 #define P256_KEY_SIZE 32
48 #define P256_PUBLIC_SIZE 64 // P256_KEY_SIZE * 2
49 
50 typedef struct Blob {
51     uint32_t dataSize;
52     uint8_t *data;
53 } Blob;
54 
55 static const uint8_t POINT_A[] = {
56     0x04, 0x53, 0xf9, 0xe4, 0xf4, 0xbc, 0x3a, 0xb5, 0x9d, 0x44, 0x78, 0x45, 0x21, 0x13, 0x8b, 0x49,
57     0xba, 0xa3, 0x1c, 0xe2, 0xa8, 0xdb, 0xbd, 0xb8, 0xd6, 0x73, 0x31, 0x46, 0x3a, 0x69, 0x53, 0xf1,
58     0xed, 0xef, 0x96, 0x1e, 0xdb, 0x42, 0xbe, 0x3a, 0x24, 0x43, 0xc4, 0x08, 0x23, 0xfb, 0x58, 0xee,
59     0x61, 0x24, 0x8b, 0x59, 0x64, 0x65, 0x2d, 0xbc, 0x6b, 0xa5, 0x1d, 0x6e, 0x04, 0x22, 0x53, 0xae,
60     0x27
61 };
62 static const uint8_t POINT_B[] = {
63     0x04, 0x03, 0x4d, 0x11, 0x11, 0xa6, 0x3f, 0x5f, 0x72, 0x43, 0x59, 0x73, 0x8b, 0x46, 0xc3, 0xfd,
64     0x70, 0x58, 0xb0, 0xb6, 0x11, 0xd3, 0x4f, 0xf3, 0x49, 0xa0, 0xd2, 0x86, 0xd7, 0x35, 0x33, 0xc5,
65     0x36, 0xe4, 0x99, 0xcc, 0x13, 0x47, 0xe4, 0xab, 0xde, 0x8f, 0x3a, 0xd6, 0x65, 0x1a, 0x77, 0x0b,
66     0xc4, 0x82, 0xd5, 0xac, 0x4b, 0x5d, 0xe4, 0xcc, 0x48, 0xb0, 0x54, 0x6c, 0x9b, 0x76, 0x76, 0x1a,
67     0xba
68 };
69 
70 static const uint8_t RANDOM_SEED_CUSTOM[] = { 0x4C, 0x54, 0x4B, 0x53 }; // LTKS means LiteKeystore
71 
IsInvalidBlob(const Blob * blob)72 static bool IsInvalidBlob(const Blob *blob)
73 {
74     return (blob == NULL) || (blob->data == NULL) || (blob->dataSize == 0);
75 }
76 
InitPointParams(mbedtls_mpi * scalarA,mbedtls_mpi * scalarB,mbedtls_ecp_point * pointA,mbedtls_ecp_point * pointB,mbedtls_ecp_point * result)77 static void InitPointParams(mbedtls_mpi *scalarA, mbedtls_mpi *scalarB, mbedtls_ecp_point *pointA,
78     mbedtls_ecp_point *pointB, mbedtls_ecp_point *result)
79 {
80     mbedtls_mpi_init(scalarA);
81     mbedtls_mpi_init(scalarB);
82     mbedtls_ecp_point_init(pointA);
83     mbedtls_ecp_point_init(pointB);
84     mbedtls_ecp_point_init(result);
85 }
86 
FreePointParams(mbedtls_mpi * scalarA,mbedtls_mpi * scalarB,mbedtls_ecp_point * pointA,mbedtls_ecp_point * pointB,mbedtls_ecp_point * result)87 static void FreePointParams(mbedtls_mpi *scalarA, mbedtls_mpi *scalarB, mbedtls_ecp_point *pointA,
88     mbedtls_ecp_point *pointB, mbedtls_ecp_point *result)
89 {
90     mbedtls_mpi_free(scalarA);
91     mbedtls_mpi_free(scalarB);
92     mbedtls_ecp_point_free(pointA);
93     mbedtls_ecp_point_free(pointB);
94     mbedtls_ecp_point_free(result);
95 }
96 
CalculateMessageDigest(mbedtls_md_type_t type,const Blob * input,Blob * output)97 static int32_t CalculateMessageDigest(mbedtls_md_type_t type, const Blob *input, Blob *output)
98 {
99     const mbedtls_md_info_t *info = mbedtls_md_info_from_type(type);
100     if (info == NULL) {
101         return HAL_ERR_NOT_SUPPORTED;
102     }
103 
104     uint32_t outSize = mbedtls_md_get_size(info);
105     if (output->dataSize < outSize) {
106         return HAL_ERR_SHORT_BUFFER;
107     }
108 
109     int32_t ret = mbedtls_md(info, input->data, input->dataSize, output->data);
110     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Calculate message digest failed.\n");
111 
112     output->dataSize = outSize;
113     return HAL_SUCCESS;
114 }
115 
Sha256(const Blob * input,Blob * output)116 static int32_t Sha256(const Blob *input, Blob *output)
117 {
118     if (IsInvalidBlob(input) || IsInvalidBlob(output)) {
119         LOGE("Input params for sha256 is invalid.");
120         return HAL_ERR_INVALID_PARAM;
121     }
122     return CalculateMessageDigest(MBEDTLS_MD_SHA256, input, output);
123 }
124 
ReadBigNums(mbedtls_mpi * x,mbedtls_mpi * y,const Blob * blob)125 static int32_t ReadBigNums(mbedtls_mpi *x, mbedtls_mpi *y, const Blob *blob)
126 {
127     int32_t ret = mbedtls_mpi_read_binary(x, blob->data, P256_KEY_SIZE);
128     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Read x coordinate of public key failed.");
129     ret = mbedtls_mpi_read_binary(y, blob->data + P256_KEY_SIZE, P256_KEY_SIZE);
130     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Read y coordinate of public key failed.");
131     return HAL_SUCCESS;
132 }
133 
ReadEcPublicKey(mbedtls_ecp_point * point,const Blob * publicKey)134 static int32_t ReadEcPublicKey(mbedtls_ecp_point *point, const Blob *publicKey)
135 {
136     int32_t ret = ReadBigNums(&point->MBEDTLS_PRIVATE(X), &point->MBEDTLS_PRIVATE(Y), publicKey);
137     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Read coordinate of public key failed.");
138     ret = mbedtls_mpi_lset(&point->MBEDTLS_PRIVATE(Z), 1);
139     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Lset point z failed.");
140     return HAL_SUCCESS;
141 }
142 
WriteOutBigNums(const mbedtls_mpi * x,const mbedtls_mpi * y,Blob * out)143 static int32_t WriteOutBigNums(const mbedtls_mpi *x, const mbedtls_mpi *y, Blob *out)
144 {
145     int32_t ret = mbedtls_mpi_write_binary(x, out->data, P256_KEY_SIZE);
146     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Write x coordinate of public key failed.");
147 
148     ret = mbedtls_mpi_write_binary(y, out->data + P256_KEY_SIZE, P256_KEY_SIZE);
149     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Write y coordinate of public key failed.");
150 
151     out->dataSize = P256_PUBLIC_SIZE;
152     return HAL_SUCCESS;
153 }
154 
WriteOutEcPublicKey(const mbedtls_ecp_point * point,Blob * publicKey)155 static int32_t WriteOutEcPublicKey(const mbedtls_ecp_point *point, Blob *publicKey)
156 {
157     return WriteOutBigNums(&point->MBEDTLS_PRIVATE(X), &point->MBEDTLS_PRIVATE(Y), publicKey);
158 }
159 
EcKeyAgreementLog(mbedtls_ecp_keypair * keyPair,mbedtls_ecp_point * p,mbedtls_ctr_drbg_context * ctrDrbg)160 static int EcKeyAgreementLog(mbedtls_ecp_keypair *keyPair, mbedtls_ecp_point *p, mbedtls_ctr_drbg_context *ctrDrbg)
161 {
162     return mbedtls_ecp_mul_restartable(&keyPair->MBEDTLS_PRIVATE(grp), p, &keyPair->MBEDTLS_PRIVATE(d),
163         &keyPair->MBEDTLS_PRIVATE(Q), mbedtls_ctr_drbg_random, ctrDrbg, NULL);
164 }
165 
EcKeyAgreement(const Blob * privateKey,const Blob * publicKey,Blob * secretKey)166 static int32_t EcKeyAgreement(const Blob *privateKey, const Blob *publicKey, Blob *secretKey)
167 {
168     if (IsInvalidBlob(publicKey) || publicKey->dataSize != P256_PUBLIC_SIZE || IsInvalidBlob(secretKey) ||
169         secretKey->dataSize != P256_PUBLIC_SIZE || IsInvalidBlob(privateKey)) {
170         LOGE("Input params for ec key agree is invalid.");
171         return HAL_ERR_INVALID_PARAM;
172     }
173     mbedtls_mpi *secret = HcMalloc(sizeof(mbedtls_mpi), 0);
174     mbedtls_ecp_keypair *keyPair = HcMalloc(sizeof(mbedtls_ecp_keypair), 0);
175     mbedtls_entropy_context *entropy = HcMalloc(sizeof(mbedtls_entropy_context), 0);
176     mbedtls_ctr_drbg_context *ctrDrbg = HcMalloc(sizeof(mbedtls_ctr_drbg_context), 0);
177     if ((secret == NULL) || (keyPair == NULL) || (entropy == NULL) || (ctrDrbg == NULL)) {
178         LOGE("Malloc for mbedtls ec key param failed.");
179         HcFree(secret);
180         HcFree(keyPair);
181         HcFree(entropy);
182         HcFree(ctrDrbg);
183         return HAL_ERR_BAD_ALLOC;
184     }
185     mbedtls_mpi_init(secret);
186     mbedtls_ecp_keypair_init(keyPair);
187     mbedtls_entropy_init(entropy);
188     mbedtls_ctr_drbg_init(ctrDrbg);
189     mbedtls_ecp_point p;
190     mbedtls_ecp_point_init(&p);
191     int32_t ret = ReadEcPublicKey(&keyPair->MBEDTLS_PRIVATE(Q), publicKey);
192     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read the public key failed.\n");
193     ret = mbedtls_ecp_group_load(&keyPair->MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
194     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Load the ecp group failed.\n");
195     ret = mbedtls_mpi_read_binary(&keyPair->MBEDTLS_PRIVATE(d), privateKey->data, privateKey->dataSize);
196     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read the private key failed.\n");
197     ret = mbedtls_ctr_drbg_seed(ctrDrbg, mbedtls_entropy_func, entropy,
198         RANDOM_SEED_CUSTOM, sizeof(RANDOM_SEED_CUSTOM));
199     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Set custom string failed.\n");
200     LOG_AND_GOTO_CLEANUP_IF_FAIL(EcKeyAgreementLog(keyPair, &p, ctrDrbg), "Compute secret key failed.\n");
201     LOG_AND_GOTO_CLEANUP_IF_FAIL(mbedtls_mpi_copy(secret, &p.MBEDTLS_PRIVATE(X)), "Copy secret failed.\n");
202     LOG_AND_GOTO_CLEANUP_IF_FAIL(WriteOutEcPublicKey(&p, secretKey), "Write out ec public key failed.\n");
203 CLEAN_UP:
204     mbedtls_mpi_free(secret);
205     mbedtls_ecp_keypair_free(keyPair);
206     mbedtls_entropy_free(entropy);
207     mbedtls_ctr_drbg_free(ctrDrbg);
208     mbedtls_ecp_point_free(&p);
209     HcFree(secret);
210     HcFree(keyPair);
211     HcFree(entropy);
212     HcFree(ctrDrbg);
213     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Ec key agree failed.");
214     return HAL_SUCCESS;
215 }
216 
EcHashToPoint(const Blob * hash,Blob * point)217 static int32_t EcHashToPoint(const Blob *hash, Blob *point)
218 {
219     if (IsInvalidBlob(hash) || IsInvalidBlob(point)) {
220         return HAL_ERR_INVALID_PARAM;
221     }
222 
223     if (point->dataSize < P256_PUBLIC_SIZE) {
224         return HAL_ERR_SHORT_BUFFER;
225     }
226 
227     mbedtls_mpi scalarA;
228     mbedtls_mpi scalarB;
229     mbedtls_ecp_point pointA;
230     mbedtls_ecp_point pointB;
231     mbedtls_ecp_point result;
232     InitPointParams(&scalarA, &scalarB, &pointA, &pointB, &result);
233 
234     mbedtls_ecp_group grp;
235     mbedtls_ecp_group_init(&grp);
236     uint8_t digest[SHA256_HASH_LEN] = { 0 };
237     Blob digestBlob = { sizeof(digest), digest };
238 
239     int32_t ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
240     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Load ecp group failed.\n");
241     ret = mbedtls_ecp_point_read_binary(&grp, &pointA, POINT_A, sizeof(POINT_A));
242     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read point A failed.\n");
243     ret = mbedtls_ecp_point_read_binary(&grp, &pointB, POINT_B, sizeof(POINT_B));
244     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read point B failed.\n");
245     ret = Sha256(hash, &digestBlob);
246     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Compute message digest failed.\n");
247     ret = mbedtls_mpi_lset(&scalarA, 1);
248     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Set number one failed.\n");
249     ret = mbedtls_mpi_read_binary(&scalarB, digest, SHA256_HASH_LEN);
250     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read digest failed.\n");
251     ret = mbedtls_ecp_muladd(&grp, &result, &scalarA, &pointA, &scalarB, &pointB);
252     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Double-scalar multiplication failed.\n");
253     ret = mbedtls_ecp_check_pubkey(&grp, &result);
254     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Invalid point on P256 is returned.\n");
255     ret = WriteOutEcPublicKey(&result, point);
256     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Write out public key failed.\n");
257 CLEAN_UP:
258     FreePointParams(&scalarA, &scalarB, &pointA, &pointB, &result);
259     mbedtls_ecp_group_free(&grp);
260     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Ec hash to point failed.");
261     return HAL_SUCCESS;
262 }
263 
264 // only support P256 HashToPoint for standard system
MbedtlsHashToPoint(const Uint8Buff * hash,Uint8Buff * outEcPoint)265 int32_t MbedtlsHashToPoint(const Uint8Buff *hash, Uint8Buff *outEcPoint)
266 {
267     CHECK_PTR_RETURN_HAL_ERROR_CODE(hash, "hash");
268     CHECK_PTR_RETURN_HAL_ERROR_CODE(hash->val, "hash->val");
269     CHECK_LEN_EQUAL_RETURN(hash->length, SHA256_LEN, "hash->length");
270     CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint, "outEcPoint");
271     CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint->val, "outEcPoint->val");
272     CHECK_LEN_EQUAL_RETURN(outEcPoint->length, EC_LEN, "outEcPoint->length");
273 
274     struct Blob hashBlob = {
275         .dataSize = hash->length,
276         .data = hash->val
277     };
278     struct Blob pointBlob = {
279         .dataSize = outEcPoint->length,
280         .data = outEcPoint->val
281     };
282 
283     int32_t ret = EcHashToPoint(&hashBlob, &pointBlob);
284     if (ret != 0 || pointBlob.dataSize != EC_LEN) {
285         LOGE("HashToPoint with mbedtls for P256 failed, ret: %d", ret);
286         return HAL_FAILED;
287     }
288 
289     return HAL_SUCCESS;
290 }
291 
292 // only support P256 AgreeSharedSecret for standard system
MbedtlsAgreeSharedSecret(const KeyBuff * priKey,const KeyBuff * pubKey,Uint8Buff * sharedKey)293 int32_t MbedtlsAgreeSharedSecret(const KeyBuff *priKey, const KeyBuff *pubKey, Uint8Buff *sharedKey)
294 {
295     CHECK_PTR_RETURN_HAL_ERROR_CODE(priKey, "priKey");
296     CHECK_PTR_RETURN_HAL_ERROR_CODE(priKey->key, "priKey->key");
297     CHECK_LEN_ZERO_RETURN_ERROR_CODE(priKey->keyLen, "priKey->keyLen");
298     CHECK_PTR_RETURN_HAL_ERROR_CODE(pubKey, "devicePk");
299     CHECK_PTR_RETURN_HAL_ERROR_CODE(pubKey->key, "devicePk->key");
300     CHECK_LEN_ZERO_RETURN_ERROR_CODE(pubKey->keyLen, "devicePk->keyLen");
301     CHECK_PTR_RETURN_HAL_ERROR_CODE(sharedKey, "sharedKey");
302     CHECK_PTR_RETURN_HAL_ERROR_CODE(sharedKey->val, "sharedKey->val");
303     CHECK_LEN_ZERO_RETURN_ERROR_CODE(sharedKey->length, "sharedKey->length");
304 
305     struct Blob priKeyBlob = {
306         .dataSize = priKey->keyLen,
307         .data = priKey->key
308     };
309     struct Blob pubKeyBlob = {
310         .dataSize = pubKey->keyLen,
311         .data = pubKey->key
312     };
313     struct Blob sharedKeyBlob = {
314         .dataSize = sharedKey->length,
315         .data = sharedKey->val
316     };
317     int32_t ret = EcKeyAgreement(&priKeyBlob, &pubKeyBlob, &sharedKeyBlob);
318     if (ret != 0) {
319         LOGE("Agree key failed, ret = %d", ret);
320         return HAL_FAILED;
321     }
322     return HAL_SUCCESS;
323 }
324