• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "hks_openssl_curve25519.h"
17 
18 #include <openssl/evp.h>
19 #include <openssl/ossl_typ.h>
20 #include <stdbool.h>
21 #include <stddef.h>
22 
23 #include "hks_crypto_adapter.h"
24 #include "hks_log.h"
25 #include "hks_mem.h"
26 #include "hks_openssl_ed25519tox25519.h"
27 #include "hks_openssl_engine.h"
28 #include "hks_template.h"
29 #include "securec.h"
30 
SaveCurve25519KeyMaterial(uint32_t algType,const EVP_PKEY * pKey,struct HksBlob * keyOut)31 static int32_t SaveCurve25519KeyMaterial(uint32_t algType, const EVP_PKEY *pKey, struct HksBlob *keyOut)
32 {
33     uint32_t totalSize = sizeof(struct KeyMaterial25519) + (CURVE25519_KEY_LEN << 1);
34     uint8_t *buffer = (uint8_t *)HksMalloc(totalSize);
35     HKS_IF_NULL_LOGE_RETURN(buffer, HKS_ERROR_MALLOC_FAIL, "malloc size %" LOG_PUBLIC "u failed", totalSize)
36 
37     size_t tmpPubKeyLen = CURVE25519_KEY_LEN;
38     size_t tmpPriKeyLen = CURVE25519_KEY_LEN;
39     uint32_t offset = sizeof(struct KeyMaterial25519);
40 
41     if (EVP_PKEY_get_raw_public_key(pKey, buffer + offset, &tmpPubKeyLen) != HKS_OPENSSL_SUCCESS) {
42         HksLogOpensslError();
43         HksFree(buffer);
44         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
45     }
46     uint32_t pubKeyLen = (uint32_t)tmpPubKeyLen;
47 
48     offset += pubKeyLen;
49     if (EVP_PKEY_get_raw_private_key(pKey, buffer + offset, &tmpPriKeyLen) != HKS_OPENSSL_SUCCESS) {
50         HksLogOpensslError();
51         HksFree(buffer);
52         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
53     }
54     uint32_t priKeyLen = (uint32_t)tmpPriKeyLen;
55 
56     struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)buffer;
57     keyMaterial->keyAlg = algType;
58     keyMaterial->keySize = CURVE25519_KEY_BITS;
59     keyMaterial->pubKeySize = pubKeyLen;
60     keyMaterial->priKeySize = priKeyLen;
61 
62     keyOut->data = buffer;
63     keyOut->size = totalSize;
64     return HKS_SUCCESS;
65 }
66 
GetCurve25519Id(uint32_t algType)67 static int GetCurve25519Id(uint32_t algType)
68 {
69     if (algType == HKS_ALG_X25519) {
70         return EVP_PKEY_X25519;
71     }
72     return EVP_PKEY_ED25519;
73 }
74 
HksOpensslCurve25519GenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)75 int32_t HksOpensslCurve25519GenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
76 {
77     EVP_PKEY_CTX *pctx = NULL;
78     EVP_PKEY *pkey = NULL;
79 
80     int32_t ret;
81     do {
82         if ((pctx = EVP_PKEY_CTX_new_id(GetCurve25519Id(spec->algType), NULL)) == NULL) {
83             HksLogOpensslError();
84             ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
85             break;
86         }
87 
88         if (EVP_PKEY_keygen_init(pctx) != HKS_OPENSSL_SUCCESS) {
89             HksLogOpensslError();
90             ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
91             break;
92         }
93 
94         if (EVP_PKEY_keygen(pctx, &pkey) != HKS_OPENSSL_SUCCESS) {
95             HksLogOpensslError();
96             ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
97             break;
98         }
99 
100         ret = SaveCurve25519KeyMaterial(spec->algType, pkey, key);
101         HKS_IF_NOT_SUCC_LOGE(ret, "save curve25519 key material failed")
102     } while (0);
103 
104     if (pctx != NULL) {
105         EVP_PKEY_CTX_free(pctx);
106     }
107     if (pkey != NULL) {
108         EVP_PKEY_free(pkey);
109     }
110     return ret;
111 }
112 
ImportX25519EvpKey(EVP_PKEY ** ours,EVP_PKEY ** theirs,const struct HksBlob * nativeKey,const struct HksBlob * pubKey)113 static int32_t ImportX25519EvpKey(EVP_PKEY **ours, EVP_PKEY **theirs, const struct HksBlob *nativeKey,
114     const struct HksBlob *pubKey)
115 {
116     struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)nativeKey->data;
117     uint32_t offset = sizeof(struct KeyMaterial25519) + km->pubKeySize;
118 
119     *ours = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, nativeKey->data + offset, km->priKeySize);
120     if (*ours == NULL) {
121         HKS_LOG_E("invalid private key");
122         HksLogOpensslError();
123         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
124     }
125 
126     struct KeyMaterial25519 *kmPub = (struct KeyMaterial25519 *)pubKey->data;
127     offset = sizeof(struct KeyMaterial25519);
128 
129     *theirs = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, pubKey->data + offset, kmPub->pubKeySize);
130     if (*theirs == NULL) {
131         HKS_LOG_E("invalid public key");
132         HksLogOpensslError();
133         EVP_PKEY_free(*ours);
134         *ours = NULL;
135         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
136     }
137 
138     return HKS_SUCCESS;
139 }
140 
HksOpensslX25519AgreeKey(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)141 int32_t HksOpensslX25519AgreeKey(const struct HksBlob *nativeKey, const struct HksBlob *pubKey,
142     const struct HksKeySpec *spec, struct HksBlob *sharedKey)
143 {
144     (void)spec;
145     EVP_PKEY *ours = NULL;
146     EVP_PKEY *theirs = NULL;
147     EVP_PKEY_CTX *ctx = NULL;
148     size_t tmpSharedKeySize = (size_t)sharedKey->size;
149 
150     int32_t ret = ImportX25519EvpKey(&ours, &theirs, nativeKey, pubKey);
151     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "import x25519 evp key failed")
152     do {
153         ctx = EVP_PKEY_CTX_new(ours, NULL);
154         if (ctx == NULL) {
155             HksLogOpensslError();
156             ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
157             break;
158         }
159         if (EVP_PKEY_derive_init(ctx) != HKS_OPENSSL_SUCCESS) {
160             HksLogOpensslError();
161             ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
162             break;
163         }
164         if (EVP_PKEY_derive_set_peer(ctx, theirs) != HKS_OPENSSL_SUCCESS) {
165             HksLogOpensslError();
166             ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
167             break;
168         }
169         if (EVP_PKEY_derive(ctx, sharedKey->data, &tmpSharedKeySize) != HKS_OPENSSL_SUCCESS) {
170             HksLogOpensslError();
171             ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
172         }
173         sharedKey->size = (uint32_t)tmpSharedKeySize;
174     } while (0);
175     EVP_PKEY_free(theirs);
176     EVP_PKEY_free(ours);
177     if (ctx != NULL) {
178         EVP_PKEY_CTX_free(ctx);
179     }
180     return ret;
181 }
182 
FreeEd25519KeyData(uint8_t * priData,uint8_t * pubData,uint8_t * pubKmData)183 static void FreeEd25519KeyData(uint8_t *priData, uint8_t *pubData, uint8_t *pubKmData)
184 {
185     if (priData != NULL) {
186         HksFree(priData);
187     }
188 
189     if (pubData != NULL) {
190         HksFree(pubData);
191     }
192 
193     if (pubKmData != NULL) {
194         HksFree(pubKmData);
195     }
196 }
197 
HksOpensslEd25519AgreeKey(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)198 int32_t HksOpensslEd25519AgreeKey(const struct HksBlob *nativeKey, const struct HksBlob *pubKey,
199     const struct HksKeySpec *spec, struct HksBlob *sharedKey)
200 {
201     (void)spec;
202     uint32_t priSize = sizeof(struct KeyMaterial25519) + CURVE25519_KEY_LEN;
203     uint8_t *priData = (uint8_t *)HksMalloc(priSize);
204     struct HksBlob nKey = { priSize, priData };
205     uint32_t pubSize = CURVE25519_KEY_LEN;
206     uint8_t *pubData = (uint8_t *)HksMalloc(pubSize);
207     struct HksBlob pKey = { pubSize, pubData };
208     struct HksBlob pubKeyData = {0};
209     uint32_t pubKmSize = sizeof(struct KeyMaterial25519) + CURVE25519_KEY_LEN;
210     uint8_t *pubKmData = (uint8_t *)HksMalloc(pubKmSize);
211     struct HksBlob pubKm = { pubKmSize, pubKmData };
212     if (priData == NULL || pubData == NULL || pubKmData == NULL) {
213         FreeEd25519KeyData(priData, pubData, pubKmData);
214         return HKS_ERROR_MALLOC_FAIL;
215     }
216     int32_t ret;
217     do {
218         ret = ConvertPrivX25519FromED25519(nativeKey, &nKey);
219         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "convert ED25519 private key to x25519 failed")
220 
221         ret = HksGetKeyFromMaterial(HKS_ALG_X25519, true, pubKey, &pubKeyData);
222         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get key data from key material failed")
223         ret = ConvertPubkeyX25519FromED25519(&pubKeyData, &pKey);
224         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "convert ED25519 public key to x25519 failed")
225         ret = HksSetKeyToMaterial(HKS_ALG_X25519, true, &pKey, &pubKm);
226         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "set mkey data to key material failed")
227         ret = HksOpensslX25519AgreeKey(&nKey, &pubKm, NULL, sharedKey);
228         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "x25519 agree key failed")
229     } while (0);
230     (void)memset_s(nKey.data, nKey.size, 0, nKey.size);
231     FreeEd25519KeyData(nKey.data, pKey.data, pubKm.data);
232     HksFree(pubKeyData.data);
233     return ret;
234 }
235 
HksOpensslEd25519Sign(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * signature)236 int32_t HksOpensslEd25519Sign(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
237     const struct HksBlob *message, struct HksBlob *signature)
238 {
239     (void)usageSpec;
240     struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)key->data;
241     uint32_t offset = sizeof(struct KeyMaterial25519) + km->pubKeySize;
242     EVP_PKEY *edKey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, key->data + offset, km->priKeySize);
243     if (edKey == NULL) {
244         HksLogOpensslError();
245         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
246     }
247 
248     EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
249     if (mdctx == NULL) {
250         HksLogOpensslError();
251         EVP_PKEY_free(edKey);
252         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
253     }
254 
255     int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
256     do {
257         if (EVP_DigestSignInit(mdctx, NULL, NULL, NULL, edKey) != HKS_OPENSSL_SUCCESS) {
258             HksLogOpensslError();
259             break;
260         }
261 
262         size_t req = 0;
263         if (EVP_DigestSign(mdctx, NULL, &req, NULL, 0) <= 0) {
264             HksLogOpensslError();
265             break;
266         }
267 
268         if (EVP_DigestSign(mdctx, signature->data, &req, message->data, message->size) <= 0) {
269             HksLogOpensslError();
270             break;
271         }
272 
273         signature->size = req;
274         ret = HKS_SUCCESS;
275     } while (0);
276 
277     EVP_PKEY_free(edKey);
278     EVP_MD_CTX_free(mdctx);
279     return ret;
280 }
281 
HksOpensslEd25519Verify(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,const struct HksBlob * signature)282 int32_t HksOpensslEd25519Verify(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
283     const struct HksBlob *message, const struct HksBlob *signature)
284 {
285     (void)usageSpec;
286     struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)key->data;
287     EVP_PKEY *edKey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, key->data + sizeof(struct KeyMaterial25519),
288         km->pubKeySize);
289     if (edKey == NULL) {
290         HksLogOpensslError();
291         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
292     }
293 
294     EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
295     if (mdctx == NULL) {
296         HksLogOpensslError();
297         EVP_PKEY_free(edKey);
298         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
299     }
300 
301     int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
302     do {
303         if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, edKey) != HKS_OPENSSL_SUCCESS) {
304             HksLogOpensslError();
305             break;
306         }
307 
308         if (EVP_DigestVerify(mdctx, signature->data, signature->size, message->data, message->size) !=
309             HKS_OPENSSL_SUCCESS) {
310             HksLogOpensslError();
311             break;
312         }
313 
314         ret = HKS_SUCCESS;
315     } while (0);
316 
317     EVP_PKEY_free(edKey);
318     EVP_MD_CTX_free(mdctx);
319     return ret;
320 }
321 
HksOpensslGetEd25519PubKey(const struct HksBlob * input,struct HksBlob * output)322 int32_t HksOpensslGetEd25519PubKey(const struct HksBlob *input, struct HksBlob *output)
323 {
324     struct KeyMaterial25519 *key = (struct KeyMaterial25519 *)input->data;
325     uint32_t outLen = sizeof(struct KeyMaterial25519) + key->pubKeySize;
326     if (memcpy_s(output->data, output->size, key, outLen) != EOK) {
327         HKS_LOG_E("memcpy_s ed25519 pub key Fail!");
328         return HKS_ERROR_INSUFFICIENT_MEMORY;
329     }
330 
331     ((struct KeyMaterial25519 *)output->data)->priKeySize = 0;
332     output->size = outLen;
333     return HKS_SUCCESS;
334 }
335 
336