1 /*
2 * Copyright (c) 2020-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 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21
22 #ifdef _CUT_AUTHENTICATE_
23 #undef HKS_SUPPORT_ED25519_C
24 #endif
25
26 #ifdef HKS_SUPPORT_ED25519_C
27
28 #include "hks_crypto_ed25519.h"
29
30
31 #include "hks_crypto_hal.h"
32 #include "hks_log.h"
33 #include "hks_mem.h"
34 #include "hks_template.h"
35
36 #include <crypto/ecx.h>
37 #include <securec.h>
38
39 #define CRYPTO_SUCCESS 1
40 #define ED25519_PRIVATE_KEY_LEN 32
41 #define ED25519_PUBLIC_KEY_LEN 32
42
43 #ifdef HKS_SUPPORT_ED25519_GENERATE_KEY
SaveEd25519KeyMaterial(const struct HksBlob * pubKey,const struct HksBlob * priKey,struct HksBlob * keyOut)44 static int32_t SaveEd25519KeyMaterial(const struct HksBlob *pubKey, const struct HksBlob *priKey,
45 struct HksBlob *keyOut)
46 {
47 uint32_t totalSize = sizeof(struct KeyMaterial25519) + pubKey->size + priKey->size;
48 uint8_t *buffer = (uint8_t *)HksMalloc(totalSize);
49 HKS_IF_NULL_RETURN(buffer, HKS_ERROR_MALLOC_FAIL)
50
51 struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)buffer;
52 keyMaterial->keyAlg = HKS_ALG_ED25519;
53 keyMaterial->keySize = HKS_CURVE25519_KEY_SIZE_256;
54 keyMaterial->pubKeySize = pubKey->size;
55 keyMaterial->priKeySize = priKey->size;
56 keyMaterial->reserved = 0;
57
58 uint32_t offset = sizeof(struct KeyMaterial25519);
59 if (memcpy_s(buffer + offset, totalSize - offset, pubKey->data, pubKey->size) != EOK) {
60 HKS_LOG_E("copy ed25519 public key failed");
61 (void)memset_s(buffer, totalSize, 0, totalSize);
62 HKS_FREE(buffer);
63 return HKS_ERROR_INSUFFICIENT_MEMORY;
64 }
65
66 offset += pubKey->size;
67 if (memcpy_s(buffer + offset, totalSize - offset, priKey->data, priKey->size) != EOK) {
68 HKS_LOG_E("copy ed25519 private key failed");
69 (void)memset_s(buffer, totalSize, 0, totalSize);
70 HKS_FREE(buffer);
71 return HKS_ERROR_INSUFFICIENT_MEMORY;
72 }
73
74 keyOut->data = buffer;
75 keyOut->size = totalSize;
76 return HKS_SUCCESS;
77 }
78
IsBlobZero(const struct HksBlob * key)79 static bool IsBlobZero(const struct HksBlob *key)
80 {
81 for (uint32_t i = 0; i < key->size; ++i) {
82 if (key->data[i] != 0) {
83 return false;
84 }
85 }
86 return true;
87 }
88
HksEd25519GenerateKey(const struct HksKeySpec * spec,struct HksBlob * keyOut)89 int32_t HksEd25519GenerateKey(const struct HksKeySpec *spec, struct HksBlob *keyOut)
90 {
91 (void)spec;
92 uint8_t pubKey[ED25519_PUBLIC_KEY_LEN] = {0};
93 uint8_t priKey[ED25519_PRIVATE_KEY_LEN] = {0};
94 struct HksBlob pubKeyBlob = { ED25519_PUBLIC_KEY_LEN, pubKey };
95 struct HksBlob priKeyBlob = { ED25519_PRIVATE_KEY_LEN, priKey };
96
97 struct HksBlob tmp = { ED25519_PUBLIC_KEY_LEN, priKeyBlob.data };
98 int32_t ret = HksCryptoHalFillPrivRandom(&tmp);
99 HKS_IF_NOT_SUCC_RETURN(ret, ret)
100
101 ossl_ed25519_public_from_private(NULL, pubKeyBlob.data, priKeyBlob.data, NULL);
102 if (IsBlobZero(&pubKeyBlob) || IsBlobZero(&priKeyBlob)) {
103 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
104 }
105
106 ret = SaveEd25519KeyMaterial(&pubKeyBlob, &priKeyBlob, keyOut);
107 (void)memset_s(priKeyBlob.data, ED25519_PRIVATE_KEY_LEN, 0, ED25519_PRIVATE_KEY_LEN);
108 return ret;
109 }
110 #endif /* HKS_SUPPORT_ED25519_GENERATE_KEY */
111
CheckEd25519Material(const struct HksBlob * key)112 static int32_t CheckEd25519Material(const struct HksBlob *key)
113 {
114 uint32_t totalSize = sizeof(struct KeyMaterial25519);
115 if (key->size < totalSize) {
116 HKS_LOG_E("Ed25519 key material too small");
117 return HKS_ERROR_INVALID_KEY_INFO;
118 }
119
120 struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)key->data;
121 if (((key->size - totalSize) < km->pubKeySize) ||
122 ((key->size - totalSize) < km->priKeySize) ||
123 (km->pubKeySize > (UINT32_MAX - km->priKeySize)) ||
124 ((key->size - totalSize) < (km->pubKeySize + km->priKeySize))) {
125 HKS_LOG_E("Ed25519 key material wrong pub and pri key size %" LOG_PUBLIC "u, %" LOG_PUBLIC "u, "
126 "%" LOG_PUBLIC "u", key->size, km->pubKeySize, km->priKeySize);
127 return HKS_ERROR_INVALID_KEY_INFO;
128 }
129
130 return HKS_SUCCESS;
131 }
132
133 #ifdef HKS_SUPPORT_ED2519_GET_PUBLIC_KEY
GetEd25519PubKeyCheck(const struct HksBlob * key,const struct HksBlob * keyOut)134 static int32_t GetEd25519PubKeyCheck(const struct HksBlob *key, const struct HksBlob *keyOut)
135 {
136 int32_t ret = CheckEd25519Material(key);
137 HKS_IF_NOT_SUCC_RETURN(ret, ret)
138
139 /* check keyOut */
140 struct KeyMaterial25519 *km = (struct KeyMaterial25519 *)key->data;
141 if ((km->pubKeySize > (UINT32_MAX - sizeof(struct KeyMaterial25519))) ||
142 (keyOut->size < (sizeof(struct KeyMaterial25519) + km->pubKeySize))) {
143 HKS_LOG_E("Ecc public keyOut size too small! keyOut size = 0x%" LOG_PUBLIC "X", keyOut->size);
144 return HKS_ERROR_BUFFER_TOO_SMALL;
145 }
146
147 return HKS_SUCCESS;
148 }
149
HksGetEd25519PubKey(const struct HksBlob * input,struct HksBlob * output)150 int32_t HksGetEd25519PubKey(const struct HksBlob *input, struct HksBlob *output)
151 {
152 int32_t ret = GetEd25519PubKeyCheck(input, output);
153 HKS_IF_NOT_SUCC_RETURN(ret, ret)
154
155 struct KeyMaterial25519 *key = (struct KeyMaterial25519 *)input->data;
156 uint32_t outLen = sizeof(struct KeyMaterial25519) + key->pubKeySize;
157 if (memcpy_s(output->data, output->size, key, outLen) != EOK) {
158 HKS_LOG_E("memcpy_s ed25519 pub key failed");
159 return HKS_ERROR_INSUFFICIENT_MEMORY;
160 }
161
162 ((struct KeyMaterial25519 *)output->data)->priKeySize = 0;
163 output->size = outLen;
164 return HKS_SUCCESS;
165 }
166 #endif
167
168 #ifdef HKS_SUPPORT_ED25519_SIGN_VERIFY
HksEd25519Sign(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * signature)169 int32_t HksEd25519Sign(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
170 const struct HksBlob *message, struct HksBlob *signature)
171 {
172 (void)usageSpec;
173 int32_t ret = CheckEd25519Material(key);
174 HKS_IF_NOT_SUCC_RETURN(ret, ret)
175 if (signature->size < HKS_SIGNATURE_MIN_SIZE ||
176 key->size <= (sizeof(struct KeyMaterial25519) + ED25519_PUBLIC_KEY_LEN)) {
177 HKS_LOG_E("invalid param : signature size = %" LOG_PUBLIC "u, key size = %" LOG_PUBLIC "u",
178 signature->size, key->size);
179 return HKS_ERROR_INVALID_ARGUMENT;
180 }
181
182 ret = ossl_ed25519_sign(signature->data, message->data, message->size,
183 key->data + sizeof(struct KeyMaterial25519),
184 key->data + sizeof(struct KeyMaterial25519) + ED25519_PUBLIC_KEY_LEN, NULL, NULL);
185 if (ret != CRYPTO_SUCCESS) {
186 HKS_LOG_E("ED25519_sign failed");
187 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
188 }
189 signature->size = HKS_SIGNATURE_MIN_SIZE;
190
191 return HKS_SUCCESS;
192 }
193
HksEd25519Verify(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,const struct HksBlob * signature)194 int32_t HksEd25519Verify(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
195 const struct HksBlob *message, const struct HksBlob *signature)
196 {
197 (void)usageSpec;
198 int32_t ret = CheckEd25519Material(key);
199 HKS_IF_NOT_SUCC_RETURN(ret, ret)
200 if (signature->size < HKS_SIGNATURE_MIN_SIZE) {
201 return HKS_ERROR_INVALID_ARGUMENT;
202 }
203
204 ret = ossl_ed25519_verify(message->data, message->size, signature->data,
205 key->data + sizeof(struct KeyMaterial25519), NULL, NULL);
206 if (ret != CRYPTO_SUCCESS) {
207 HKS_LOG_E("ED25519_verify failed");
208 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
209 }
210
211 return HKS_SUCCESS;
212 }
213 #endif /* HKS_SUPPORT_ED25519_SIGN_VERIFY */
214 #endif /* HKS_SUPPORT_ED25519_C */
215