• 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         HKS_FREE(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         HKS_FREE(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 
HksOpensslEd25519AgreeKey(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)183 int32_t HksOpensslEd25519AgreeKey(const struct HksBlob *nativeKey, const struct HksBlob *pubKey,
184     const struct HksKeySpec *spec, struct HksBlob *sharedKey)
185 {
186     struct HksBlob ed25519PubKey = { 0 };
187     uint32_t materialKeySize = sizeof(struct KeyMaterial25519) + CURVE25519_KEY_LEN;
188     struct HksBlob x25519PriKeyMaterial = { materialKeySize, (uint8_t *)HksMalloc(materialKeySize) };
189     struct HksBlob x25519PubKeyMaterial = { materialKeySize, (uint8_t *)HksMalloc(materialKeySize) };
190 
191     int32_t ret;
192     do {
193         if (x25519PriKeyMaterial.data == NULL || x25519PubKeyMaterial.data == NULL) {
194             HKS_LOG_E("malloc for x22519 key pair failed");
195             ret = HKS_ERROR_MALLOC_FAIL;
196             break;
197         }
198 
199         // get x25519 private key material
200         ret = ConvertPrivX25519FromED25519(nativeKey, &x25519PriKeyMaterial);
201         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "convert ED25519 private key to x25519 failed")
202 
203         // get x25519 public key material
204         ret = HksGetKeyFromMaterial(HKS_ALG_ED25519, true, pubKey, &ed25519PubKey);
205         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get public key from keymaterial failed")
206         ret = ConvertPubkeyX25519FromED25519(&ed25519PubKey, &x25519PubKeyMaterial);
207         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "convert ED25519 public key to x25519 failed")
208 
209         // x25519 key agreement
210         ret = HksOpensslX25519AgreeKey(&x25519PriKeyMaterial, &x25519PubKeyMaterial, spec, sharedKey);
211         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "x25519 agree key failed")
212     } while (0);
213 
214     HKS_MEMSET_FREE_BLOB(ed25519PubKey);
215     HKS_MEMSET_FREE_BLOB(x25519PriKeyMaterial);
216     HKS_MEMSET_FREE_BLOB(x25519PubKeyMaterial);
217     return ret;
218 }
219 
HksOpensslEd25519Sign(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * signature)220 int32_t HksOpensslEd25519Sign(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
221     const struct HksBlob *message, struct HksBlob *signature)
222 {
223     (void)usageSpec;
224     struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)key->data;
225     uint32_t offset = sizeof(struct KeyMaterial25519) + km->pubKeySize;
226     EVP_PKEY *edKeyPri = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
227         key->data + offset, km->priKeySize);
228 
229     if (edKeyPri == NULL) {
230         HksLogOpensslError();
231         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
232     }
233     EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
234     if (mdctx == NULL) {
235         HksLogOpensslError();
236         EVP_PKEY_free(edKeyPri);
237         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
238     }
239 
240     int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
241     do {
242         if (EVP_DigestSignInit(mdctx, NULL, NULL, NULL, edKeyPri) != HKS_OPENSSL_SUCCESS) {
243             HksLogOpensslError();
244             break;
245         }
246 
247         size_t req = 0;
248         if (EVP_DigestSign(mdctx, NULL, &req, NULL, 0) <= 0) {
249             HksLogOpensslError();
250             break;
251         }
252 
253         if (EVP_DigestSign(mdctx, signature->data, &req, message->data, message->size) <= 0) {
254             HksLogOpensslError();
255             break;
256         }
257 
258         signature->size = req;
259         ret = HKS_SUCCESS;
260     } while (0);
261 
262     EVP_PKEY_free(edKeyPri);
263     EVP_MD_CTX_free(mdctx);
264     return ret;
265 }
266 
HksOpensslEd25519Verify(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,const struct HksBlob * signature)267 int32_t HksOpensslEd25519Verify(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
268     const struct HksBlob *message, const struct HksBlob *signature)
269 {
270     (void)usageSpec;
271     struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)key->data;
272     EVP_PKEY *edKeyPub = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
273         key->data + sizeof(struct KeyMaterial25519), km->pubKeySize);
274 
275     if (edKeyPub == NULL) {
276         HksLogOpensslError();
277         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
278     }
279     EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
280     if (mdctx == NULL) {
281         HksLogOpensslError();
282         EVP_PKEY_free(edKeyPub);
283         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
284     }
285 
286     int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
287     do {
288         if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, edKeyPub) != HKS_OPENSSL_SUCCESS) {
289             HksLogOpensslError();
290             break;
291         }
292 
293         if (EVP_DigestVerify(mdctx, signature->data, signature->size, message->data, message->size) !=
294             HKS_OPENSSL_SUCCESS) {
295             HksLogOpensslError();
296             break;
297         }
298 
299         ret = HKS_SUCCESS;
300     } while (0);
301 
302     EVP_PKEY_free(edKeyPub);
303     EVP_MD_CTX_free(mdctx);
304     return ret;
305 }
306 
HksOpensslGetEd25519PubKey(const struct HksBlob * input,struct HksBlob * output)307 int32_t HksOpensslGetEd25519PubKey(const struct HksBlob *input, struct HksBlob *output)
308 {
309     struct KeyMaterial25519 *key = (struct KeyMaterial25519 *)input->data;
310     uint32_t outLen = sizeof(struct KeyMaterial25519) + key->pubKeySize;
311     if (memcpy_s(output->data, output->size, key, outLen) != EOK) {
312         HKS_LOG_E("memcpy_s ed25519 pub key Fail!");
313         return HKS_ERROR_INSUFFICIENT_MEMORY;
314     }
315 
316     ((struct KeyMaterial25519 *)output->data)->priKeySize = 0;
317     output->size = outLen;
318     return HKS_SUCCESS;
319 }
320 
321