• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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