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