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 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21
22 #ifdef HKS_SUPPORT_DSA_C
23
24 #include "hks_openssl_dsa.h"
25
26 #include <openssl/bn.h>
27 #include <openssl/dsa.h>
28 #include <openssl/evp.h>
29 #include <openssl/ossl_typ.h>
30 #include <stdbool.h>
31 #include <stddef.h>
32
33 #include "hks_common_check.h"
34 #include "hks_log.h"
35 #include "hks_mem.h"
36 #include "hks_openssl_engine.h"
37 #include "hks_template.h"
38 #include "securec.h"
39
40 #define OPENSSL_KEY_BLOCK 8
41 #define OPENSSL_DSA_MIN_KEY_LEN 64
42 #define OPENSSL_DSA_KEY_LEN_DIVID (2048 / HKS_BITS_PER_BYTE)
43
GetOpensslKeyBlocksLen(uint32_t keylen)44 static uint32_t GetOpensslKeyBlocksLen(uint32_t keylen)
45 {
46 return (keylen + OPENSSL_KEY_BLOCK - 1) / OPENSSL_KEY_BLOCK * OPENSSL_KEY_BLOCK;
47 }
48
InitDsaStructKey(const struct HksBlob * key,const bool needPrivateExponent,DSA * dsa,uint32_t * offset)49 static int InitDsaStructKey(const struct HksBlob *key, const bool needPrivateExponent, DSA *dsa, uint32_t *offset)
50 {
51 int ret;
52 const struct KeyMaterialDsa *keyMaterial = (struct KeyMaterialDsa *)(key->data);
53 uint8_t *buff = (uint8_t *)HksMalloc(HKS_KEY_BYTES(keyMaterial->keySize));
54 HKS_IF_NULL_RETURN(buff, HKS_ERROR_MALLOC_FAIL)
55
56 BIGNUM *x = NULL;
57 if (needPrivateExponent) {
58 if (keyMaterial->xSize == 0) {
59 HKS_FREE(buff);
60 return HKS_ERROR_INVALID_ARGUMENT;
61 } else {
62 if (memcpy_s(buff, HKS_KEY_BYTES(keyMaterial->keySize), key->data + *offset, keyMaterial->xSize) != EOK) {
63 HKS_FREE(buff);
64 return HKS_ERROR_INSUFFICIENT_MEMORY;
65 }
66 x = BN_bin2bn(buff, keyMaterial->xSize, NULL);
67 }
68 }
69 *offset += keyMaterial->xSize;
70 if (memcpy_s(buff, HKS_KEY_BYTES(keyMaterial->keySize), key->data + *offset, keyMaterial->ySize) != EOK) {
71 HKS_FREE(buff);
72 SELF_FREE_PTR(x, BN_free);
73 return HKS_ERROR_INSUFFICIENT_MEMORY;
74 }
75 BIGNUM *y = BN_bin2bn(buff, keyMaterial->ySize, NULL);
76 *offset += keyMaterial->ySize;
77 if (DSA_set0_key(dsa, y, x) != HKS_OPENSSL_SUCCESS) {
78 SELF_FREE_PTR(x, BN_free);
79 SELF_FREE_PTR(y, BN_free);
80 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
81 } else {
82 ret = HKS_SUCCESS;
83 }
84
85 (void)memset_s(buff, HKS_KEY_BYTES(keyMaterial->keySize), 0, HKS_KEY_BYTES(keyMaterial->keySize));
86 HKS_FREE(buff);
87 return ret;
88 }
89
InitDsaStructParameter(const struct HksBlob * key,const bool needPrivateExponent,DSA * dsa,uint32_t * offset)90 static int InitDsaStructParameter(const struct HksBlob *key, const bool needPrivateExponent, DSA *dsa, uint32_t* offset)
91 {
92 int ret;
93 const struct KeyMaterialDsa *keyMaterial = (struct KeyMaterialDsa *)(key->data);
94 uint8_t *buff = HksMalloc(HKS_KEY_BYTES(keyMaterial->keySize));
95 HKS_IF_NULL_RETURN(buff, HKS_ERROR_INSUFFICIENT_MEMORY)
96
97 if (memcpy_s(buff, HKS_KEY_BYTES(keyMaterial->keySize), key->data + *offset, keyMaterial->pSize) != EOK) {
98 HKS_FREE(buff);
99 return HKS_ERROR_INSUFFICIENT_MEMORY;
100 }
101 BIGNUM *p = BN_bin2bn(buff, keyMaterial->pSize, NULL);
102 *offset += keyMaterial->pSize;
103 if (memcpy_s(buff, HKS_KEY_BYTES(keyMaterial->keySize), key->data + *offset, keyMaterial->qSize) != EOK) {
104 HKS_FREE(buff);
105 SELF_FREE_PTR(p, BN_free);
106 return HKS_ERROR_INSUFFICIENT_MEMORY;
107 }
108 BIGNUM *q = BN_bin2bn(buff, keyMaterial->qSize, NULL);
109 *offset += keyMaterial->qSize;
110 if (memcpy_s(buff, HKS_KEY_BYTES(keyMaterial->keySize), key->data + *offset, keyMaterial->gSize) != EOK) {
111 (void)memset_s(buff, HKS_KEY_BYTES(keyMaterial->keySize), 0, HKS_KEY_BYTES(keyMaterial->keySize));
112 HKS_FREE(buff);
113 SELF_FREE_PTR(p, BN_free);
114 SELF_FREE_PTR(q, BN_free);
115 return HKS_ERROR_INSUFFICIENT_MEMORY;
116 }
117 BIGNUM *g = BN_bin2bn(buff, keyMaterial->gSize, NULL);
118
119 if (DSA_set0_pqg(dsa, p, q, g) != HKS_OPENSSL_SUCCESS) {
120 SELF_FREE_PTR(p, BN_free);
121 SELF_FREE_PTR(q, BN_free);
122 SELF_FREE_PTR(g, BN_free);
123 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
124 } else {
125 ret = HKS_SUCCESS;
126 }
127
128 (void)memset_s(buff, HKS_KEY_BYTES(keyMaterial->keySize), 0, HKS_KEY_BYTES(keyMaterial->keySize));
129 HKS_FREE(buff);
130 return ret;
131 }
132
InitDsaStruct(const struct HksBlob * key,const bool needPrivateExponent)133 static DSA *InitDsaStruct(const struct HksBlob *key, const bool needPrivateExponent)
134 {
135 DSA *dsa = DSA_new();
136 HKS_IF_NULL_RETURN(dsa, NULL)
137
138 uint32_t offset = sizeof(struct KeyMaterialDsa);
139 if (InitDsaStructKey(key, needPrivateExponent, dsa, &offset) != HKS_SUCCESS) {
140 SELF_FREE_PTR(dsa, DSA_free);
141 return NULL;
142 }
143
144 if (InitDsaStructParameter(key, needPrivateExponent, dsa, &offset) != HKS_SUCCESS) {
145 SELF_FREE_PTR(dsa, DSA_free);
146 return NULL;
147 }
148
149 return dsa;
150 }
151
152 #ifdef HKS_SUPPORT_DSA_GENERATE_KEY
DsaGetKeyParamLen(uint32_t keyLen,uint32_t * xlen,uint32_t * ylen,uint32_t * plen,uint32_t * qlen,uint32_t * glen)153 static void DsaGetKeyParamLen(
154 uint32_t keyLen, uint32_t *xlen, uint32_t *ylen, uint32_t *plen, uint32_t *qlen, uint32_t *glen)
155 {
156 *xlen = (keyLen >= OPENSSL_DSA_KEY_LEN_DIVID) ? HKS_DIGEST_SHA256_LEN : HKS_DIGEST_SHA1_LEN;
157 *ylen = keyLen;
158 *plen = keyLen;
159 *qlen = (keyLen >= OPENSSL_DSA_KEY_LEN_DIVID) ? HKS_DIGEST_SHA256_LEN : HKS_DIGEST_SHA1_LEN;
160 *glen = keyLen;
161 }
162
DsaCalculateMaterialLen(uint32_t keySize,uint32_t * dsaKeyLen)163 static uint32_t DsaCalculateMaterialLen(uint32_t keySize, uint32_t *dsaKeyLen)
164 {
165 uint32_t opensslKeyByteLen = HKS_KEY_BYTES(keySize);
166 if (opensslKeyByteLen < OPENSSL_DSA_MIN_KEY_LEN) {
167 opensslKeyByteLen = OPENSSL_DSA_MIN_KEY_LEN;
168 }
169
170 opensslKeyByteLen = GetOpensslKeyBlocksLen(opensslKeyByteLen);
171
172 uint32_t xlen = (opensslKeyByteLen > OPENSSL_DSA_KEY_LEN_DIVID) ? HKS_DIGEST_SHA256_LEN : HKS_DIGEST_SHA1_LEN;
173 uint32_t ylen = opensslKeyByteLen;
174 uint32_t plen = opensslKeyByteLen;
175 uint32_t qlen = (opensslKeyByteLen > OPENSSL_DSA_KEY_LEN_DIVID) ? HKS_DIGEST_SHA256_LEN : HKS_DIGEST_SHA1_LEN;
176 uint32_t glen = opensslKeyByteLen;
177 DsaGetKeyParamLen(opensslKeyByteLen, &xlen, &ylen, &plen, &qlen, &glen);
178
179 if (dsaKeyLen != NULL) {
180 *dsaKeyLen = opensslKeyByteLen;
181 }
182
183 return sizeof(struct KeyMaterialDsa) + xlen + ylen + plen + qlen + glen;
184 }
185
DsaKeyMaterialParam(uint8_t * rawMaterial,const DSA * dsa,uint32_t keyLen)186 static int32_t DsaKeyMaterialParam(uint8_t *rawMaterial, const DSA *dsa, uint32_t keyLen)
187 {
188 struct KeyMaterialDsa *keyMaterial = (struct KeyMaterialDsa *)rawMaterial;
189 keyMaterial->keyAlg = HKS_ALG_DSA;
190 keyMaterial->keySize = keyLen * HKS_BITS_PER_BYTE;
191 DsaGetKeyParamLen(keyLen,
192 &keyMaterial->xSize,
193 &keyMaterial->ySize,
194 &keyMaterial->pSize,
195 &keyMaterial->qSize,
196 &keyMaterial->gSize);
197 return HKS_SUCCESS;
198 }
199
DsaKeyMaterialData(uint8_t * rawMaterial,const DSA * dsa)200 static int32_t DsaKeyMaterialData(uint8_t *rawMaterial, const DSA *dsa)
201 {
202 int32_t ret;
203 struct KeyMaterialDsa *keyMaterial = (struct KeyMaterialDsa *)rawMaterial;
204 const BIGNUM *x = DSA_get0_priv_key(dsa);
205 const BIGNUM *y = DSA_get0_pub_key(dsa);
206 const BIGNUM *p = DSA_get0_p(dsa);
207 const BIGNUM *q = DSA_get0_q(dsa);
208 const BIGNUM *g = DSA_get0_g(dsa);
209
210 uint32_t offset = sizeof(struct KeyMaterialDsa);
211 ret = BN_bn2bin(x, rawMaterial + offset + (keyMaterial->xSize - (uint32_t)BN_num_bytes(x)));
212 if (ret <= 0) {
213 HksLogOpensslError();
214 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
215 }
216 offset += keyMaterial->xSize;
217 ret = BN_bn2bin(y, rawMaterial + offset + (keyMaterial->ySize - (uint32_t)BN_num_bytes(y)));
218 if (ret <= 0) {
219 HksLogOpensslError();
220 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
221 }
222 offset += keyMaterial->ySize;
223 ret = BN_bn2bin(p, rawMaterial + offset + (keyMaterial->pSize - (uint32_t)BN_num_bytes(p)));
224 if (ret <= 0) {
225 HksLogOpensslError();
226 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
227 }
228 offset += keyMaterial->pSize;
229 ret = BN_bn2bin(q, rawMaterial + offset + (keyMaterial->qSize - (uint32_t)BN_num_bytes(q)));
230 if (ret <= 0) {
231 HksLogOpensslError();
232 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
233 }
234 offset += keyMaterial->qSize;
235 ret = BN_bn2bin(g, rawMaterial + offset + (keyMaterial->gSize - (uint32_t)BN_num_bytes(g)));
236 if (ret <= 0) {
237 HksLogOpensslError();
238 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
239 }
240 return HKS_SUCCESS;
241 }
242
DsaSaveKeyMaterial(const DSA * dsa,const uint32_t keySize,uint8_t ** output,uint32_t * outputSize)243 static int32_t DsaSaveKeyMaterial(const DSA *dsa, const uint32_t keySize, uint8_t **output, uint32_t *outputSize)
244 {
245 uint32_t keyLen;
246 uint32_t rawMaterialLen = DsaCalculateMaterialLen(keySize, &keyLen);
247 uint8_t *rawMaterial = (uint8_t *)HksMalloc(rawMaterialLen);
248 HKS_IF_NULL_LOGE_RETURN(rawMaterial, HKS_ERROR_MALLOC_FAIL, "malloc buffer failed!")
249
250 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
251
252 if (DsaKeyMaterialParam(rawMaterial, dsa, keyLen) != HKS_SUCCESS) {
253 HKS_FREE(rawMaterial);
254 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
255 }
256 if (DsaKeyMaterialData(rawMaterial, dsa) != HKS_SUCCESS) {
257 HKS_FREE(rawMaterial);
258 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
259 }
260
261 *output = rawMaterial;
262 *outputSize = rawMaterialLen;
263 return HKS_SUCCESS;
264 }
265
HksOpensslDsaGenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)266 int32_t HksOpensslDsaGenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
267 {
268 int32_t ret;
269 if ((spec->keyLen == 0) || (spec->keyLen % HKS_BITS_PER_BYTE != 0)) {
270 return HKS_ERROR_INVALID_ARGUMENT;
271 }
272
273 DSA *dsa = DSA_new();
274 HKS_IF_NULL_LOGE_RETURN(dsa, HKS_ERROR_CRYPTO_ENGINE_ERROR, "DSA structure is NULL.")
275
276 do {
277 HKS_LOG_I("spec->keyLen = %" LOG_PUBLIC "u", spec->keyLen);
278 ret = DSA_generate_parameters_ex(dsa, spec->keyLen, NULL, 0, NULL, NULL, NULL);
279 if (ret != HKS_OPENSSL_SUCCESS) {
280 HKS_LOG_E("DSA_generate_parameters_ex fail %" LOG_PUBLIC "d", ret);
281 HksLogOpensslError();
282 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
283 break;
284 }
285
286 ret = DSA_generate_key(dsa);
287 if (ret != HKS_OPENSSL_SUCCESS) {
288 HKS_LOG_E("DSA_generate_key fail %" LOG_PUBLIC "d", ret);
289 HksLogOpensslError();
290 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
291 break;
292 }
293
294 ret = DsaSaveKeyMaterial(dsa, spec->keyLen, &key->data, &key->size);
295 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "save dsa key material failed! ret=0x%" LOG_PUBLIC "x", ret)
296 } while (0);
297
298 if (dsa != NULL) {
299 DSA_free(dsa);
300 }
301
302 return ret;
303 }
304 #endif
305
306 #ifdef HKS_SUPPORT_DSA_GET_PUBLIC_KEY
HksOpensslGetDsaPubKey(const struct HksBlob * input,struct HksBlob * output)307 int32_t HksOpensslGetDsaPubKey(const struct HksBlob *input, struct HksBlob *output)
308 {
309 struct KeyMaterialDsa *keyMaterial = (struct KeyMaterialDsa *)input->data;
310
311 output->size = sizeof(struct KeyMaterialDsa) + keyMaterial->ySize + keyMaterial->pSize + keyMaterial->qSize +
312 keyMaterial->gSize;
313
314 struct KeyMaterialDsa *publickeyMaterial = (struct KeyMaterialDsa *)output->data;
315 publickeyMaterial->keyAlg = keyMaterial->keyAlg;
316 publickeyMaterial->keySize = keyMaterial->keySize;
317 publickeyMaterial->xSize = 0;
318 publickeyMaterial->ySize = keyMaterial->ySize;
319 publickeyMaterial->pSize = keyMaterial->pSize;
320 publickeyMaterial->qSize = keyMaterial->qSize;
321 publickeyMaterial->gSize = keyMaterial->gSize;
322
323 if (memcpy_s(output->data + sizeof(struct KeyMaterialDsa) + publickeyMaterial->xSize,
324 output->size - (sizeof(struct KeyMaterialDsa) + publickeyMaterial->xSize),
325 input->data + sizeof(struct KeyMaterialDsa) + keyMaterial->xSize,
326 keyMaterial->ySize + keyMaterial->pSize + keyMaterial->qSize + keyMaterial->gSize) != EOK) {
327 return HKS_ERROR_INSUFFICIENT_MEMORY;
328 }
329
330 return HKS_SUCCESS;
331 }
332 #endif
333
334 #ifdef HKS_SUPPORT_DSA_SIGN_VERIFY
InitDSACtx(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,bool signing,uint32_t len)335 static EVP_PKEY_CTX *InitDSACtx(const struct HksBlob *key, const struct HksUsageSpec *usageSpec, bool signing,
336 uint32_t len)
337 {
338 const EVP_MD *opensslAlg = GetOpensslAlg(usageSpec->digest);
339 if (usageSpec->digest == HKS_DIGEST_NONE) {
340 opensslAlg = GetOpensslAlgFromLen(len);
341 }
342 if (opensslAlg == NULL) {
343 HKS_LOG_E("get openssl algorithm fail");
344 return NULL;
345 }
346
347 DSA *dsa = InitDsaStruct(key, signing);
348 HKS_IF_NULL_LOGE_RETURN(dsa, NULL, "initialize dsa key failed")
349
350 EVP_PKEY *pkey = EVP_PKEY_new();
351 if (pkey == NULL) {
352 HksLogOpensslError();
353 DSA_free(dsa);
354 return NULL;
355 }
356
357 if (EVP_PKEY_assign_DSA(pkey, dsa) != HKS_OPENSSL_SUCCESS) {
358 HksLogOpensslError();
359 DSA_free(dsa);
360 EVP_PKEY_free(pkey);
361 return NULL;
362 }
363
364 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
365 if (ctx == NULL) {
366 HksLogOpensslError();
367 EVP_PKEY_free(pkey);
368 return NULL;
369 }
370
371 int32_t ret;
372 if (signing) {
373 ret = EVP_PKEY_sign_init(ctx);
374 } else {
375 ret = EVP_PKEY_verify_init(ctx);
376 }
377 EVP_PKEY_free(pkey);
378 if (ret != HKS_OPENSSL_SUCCESS) {
379 HksLogOpensslError();
380 EVP_PKEY_CTX_free(ctx);
381 return NULL;
382 }
383
384 if (EVP_PKEY_CTX_set_signature_md(ctx, opensslAlg) != HKS_OPENSSL_SUCCESS) {
385 HksLogOpensslError();
386 EVP_PKEY_CTX_free(ctx);
387 return NULL;
388 }
389
390 return ctx;
391 }
392
HksOpensslDsaSign(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * signature)393 int32_t HksOpensslDsaSign(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
394 const struct HksBlob *message, struct HksBlob *signature)
395 {
396 EVP_PKEY_CTX *ctx = InitDSACtx(key, usageSpec, true, message->size);
397 HKS_IF_NULL_LOGE_RETURN(ctx, HKS_ERROR_INVALID_KEY_INFO, "initialize dsa context failed")
398
399 size_t sigSize = (size_t)signature->size;
400 if (EVP_PKEY_sign(ctx, signature->data, &sigSize, message->data, message->size) != HKS_OPENSSL_SUCCESS) {
401 HksLogOpensslError();
402 EVP_PKEY_CTX_free(ctx);
403 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
404 }
405 signature->size = (uint32_t)sigSize;
406 EVP_PKEY_CTX_free(ctx);
407 return HKS_SUCCESS;
408 }
409
HksOpensslDsaVerify(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,const struct HksBlob * signature)410 int32_t HksOpensslDsaVerify(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
411 const struct HksBlob *message, const struct HksBlob *signature)
412 {
413 EVP_PKEY_CTX *ctx = InitDSACtx(key, usageSpec, false, message->size);
414 HKS_IF_NULL_LOGE_RETURN(ctx, HKS_ERROR_INVALID_KEY_INFO, "initialize dsa context failed")
415
416 if (EVP_PKEY_verify(ctx, signature->data, signature->size, message->data, message->size) != HKS_OPENSSL_SUCCESS) {
417 HksLogOpensslError();
418 EVP_PKEY_CTX_free(ctx);
419 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
420 }
421
422 EVP_PKEY_CTX_free(ctx);
423 return HKS_SUCCESS;
424 }
425 #endif
426 #endif
427