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