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