1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15 #include "hitls_build.h"
16 #ifdef HITLS_CRYPTO_SLH_DSA
17
18 #include <stdint.h>
19 #include "securec.h"
20 #include "bsl_err_internal.h"
21 #include "bsl_sal.h"
22 #include "crypt_errno.h"
23 #include "slh_dsa_local.h"
24 #include "slh_dsa_xmss.h"
25 #include "slh_dsa_hypertree.h"
26
HypertreeSign(const uint8_t * msg,uint32_t msgLen,uint64_t treeIdx,uint32_t leafIdx,const CryptSlhDsaCtx * ctx,uint8_t * sig,uint32_t * sigLen)27 int32_t HypertreeSign(const uint8_t *msg, uint32_t msgLen, uint64_t treeIdx, uint32_t leafIdx,
28 const CryptSlhDsaCtx *ctx, uint8_t *sig, uint32_t *sigLen)
29 {
30 int32_t ret;
31 uint32_t n = ctx->para.n;
32 uint32_t hp = ctx->para.hp;
33 uint32_t d = ctx->para.d;
34 uint32_t len = 2 * n + 3;
35 uint32_t retLen = (len + hp) * n * d;
36 uint32_t leafIdxTmp = leafIdx;
37 uint64_t treeIdxTmp = treeIdx;
38
39 if (*sigLen < retLen) {
40 return CRYPT_SLHDSA_ERR_SIG_LEN_NOT_ENOUGH;
41 }
42
43 SlhDsaAdrs adrs = {0};
44
45 uint32_t offset = 0;
46 uint32_t tmpLen = *sigLen;
47 uint8_t root[SLH_DSA_MAX_N] = {0};
48 // the msgLen is actually n.
49 (void)memcpy_s(root, sizeof(root), msg, msgLen);
50
51 for (uint32_t j = 0; j < d; j++) {
52 if (j != 0) {
53 leafIdxTmp = (uint32_t)(treeIdxTmp & ((1UL << hp) - 1));
54 treeIdxTmp = treeIdxTmp >> hp;
55 ctx->adrsOps.setLayerAddr(&adrs, j);
56 }
57 ctx->adrsOps.setTreeAddr(&adrs, treeIdxTmp);
58 tmpLen = retLen - offset;
59 ret = XmssSign(root, n, leafIdxTmp, &adrs, ctx, sig + offset, &tmpLen);
60 if (ret != CRYPT_SUCCESS) {
61 return ret;
62 }
63 ret = XmssPkFromSig(leafIdxTmp, sig + offset, tmpLen, root, n, &adrs, ctx, root);
64 if (ret != CRYPT_SUCCESS) {
65 return ret;
66 }
67 offset += tmpLen;
68 }
69 *sigLen = retLen;
70 return CRYPT_SUCCESS;
71 }
72
HypertreeVerify(const uint8_t * msg,uint32_t msgLen,const uint8_t * sig,uint32_t sigLen,uint64_t treeIdx,uint32_t leafIdx,const CryptSlhDsaCtx * ctx)73 int32_t HypertreeVerify(const uint8_t *msg, uint32_t msgLen, const uint8_t *sig, uint32_t sigLen, uint64_t treeIdx,
74 uint32_t leafIdx, const CryptSlhDsaCtx *ctx)
75 {
76 int32_t ret;
77 uint32_t n = ctx->para.n;
78 uint32_t hp = ctx->para.hp;
79 uint32_t d = ctx->para.d;
80 uint32_t len = 2 * n + 3;
81 uint32_t retLen = (len + hp) * n * d;
82 uint32_t leafIdxTmp = leafIdx;
83 uint64_t treeIdxTmp = treeIdx;
84
85 if (sigLen < retLen) {
86 return CRYPT_SLHDSA_ERR_SIG_LEN_NOT_ENOUGH;
87 }
88
89 SlhDsaAdrs adrs = {0};
90 uint32_t offset = 0;
91
92 uint8_t node[SLH_DSA_MAX_N] = {0};
93 // the msgLen is actually n.
94 (void)memcpy_s(node, sizeof(node), msg, msgLen);
95 for (uint32_t j = 0; j < d; j++) {
96 if (j != 0) {
97 leafIdxTmp = (uint32_t)(treeIdxTmp & ((1UL << hp) - 1));
98 treeIdxTmp = treeIdxTmp >> hp;
99 ctx->adrsOps.setLayerAddr(&adrs, j);
100 }
101 ctx->adrsOps.setTreeAddr(&adrs, treeIdxTmp);
102 ret = XmssPkFromSig(leafIdxTmp, sig + offset, sigLen - offset, node, n, &adrs, ctx, node);
103 if (ret != CRYPT_SUCCESS) {
104 return ret;
105 }
106 offset += (len + hp) * n;
107 }
108
109 if (memcmp(node, ctx->prvKey.pub.root, n) != 0) {
110 return CRYPT_SLHDSA_ERR_HYPERTREE_VERIFY_FAIL;
111 }
112 return CRYPT_SUCCESS;
113 }
114
115 #endif // HITLS_CRYPTO_SLH_DSA
116