• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stddef.h>
20 #include "securec.h"
21 #include "bsl_err_internal.h"
22 #include "bsl_sal.h"
23 #include "crypt_errno.h"
24 #include "slh_dsa_local.h"
25 #include "slh_dsa_xmss.h"
26 #include "slh_dsa_wots.h"
27 
XmssNode(uint8_t * node,uint32_t idx,uint32_t height,SlhDsaAdrs * adrs,const CryptSlhDsaCtx * ctx)28 int32_t XmssNode(uint8_t *node, uint32_t idx, uint32_t height, SlhDsaAdrs *adrs, const CryptSlhDsaCtx *ctx)
29 {
30     int32_t ret;
31     if (node == NULL || adrs == NULL || ctx == NULL) {
32         return CRYPT_NULL_INPUT;
33     }
34 
35     uint32_t n = ctx->para.n;
36 
37     // If height is 0, compute WOTS+ public key
38     if (height == 0) {
39         ctx->adrsOps.setType(adrs, WOTS_HASH);
40         ctx->adrsOps.setKeyPairAddr(adrs, idx);
41         return WotsGeneratePublicKey(node, adrs, ctx);
42     }
43     // Compute internal node
44     uint8_t leftNode[SLH_DSA_MAX_N] = {0};
45     uint8_t rightNode[SLH_DSA_MAX_N] = {0};
46 
47     // Compute left child
48     ret = XmssNode(leftNode, 2 * idx, height - 1, adrs, ctx);
49     if (ret != CRYPT_SUCCESS) {
50         return ret;
51     }
52 
53     // Compute right child
54     ret = XmssNode(rightNode, 2 * idx + 1, height - 1, adrs, ctx);
55     if (ret != CRYPT_SUCCESS) {
56         return ret;
57     }
58 
59     // Hash children to get parent node
60     ctx->adrsOps.setType(adrs, TREE);
61     ctx->adrsOps.setTreeHeight(adrs, height);
62     ctx->adrsOps.setTreeIndex(adrs, idx);
63 
64     uint8_t tmp[SLH_DSA_MAX_N * 2];
65     (void)memcpy_s(tmp, SLH_DSA_MAX_N * 2, leftNode, n);
66     (void)memcpy_s(tmp + n, SLH_DSA_MAX_N * 2 - n, rightNode, n);
67 
68     return ctx->hashFuncs.h(ctx, adrs, tmp, 2 * n, node);
69 }
70 
XmssSign(const uint8_t * msg,size_t msgLen,uint32_t idx,SlhDsaAdrs * adrs,const CryptSlhDsaCtx * ctx,uint8_t * sig,uint32_t * sigLen)71 int32_t XmssSign(const uint8_t *msg, size_t msgLen, uint32_t idx, SlhDsaAdrs *adrs, const CryptSlhDsaCtx *ctx,
72                  uint8_t *sig, uint32_t *sigLen)
73 {
74     int32_t ret;
75 
76     uint32_t n = ctx->para.n;
77     uint32_t hp = ctx->para.hp;
78     uint32_t len = 2 * n + 3;
79 
80     if (*sigLen < (len + hp) * n) {
81         return CRYPT_SLHDSA_ERR_SIG_LEN_NOT_ENOUGH;
82     }
83 
84     for (uint32_t j = 0; j < hp; j++) {
85         uint32_t k = (idx >> j) ^ 1;
86         uint8_t node[SLH_DSA_MAX_N] = {0};
87         ret = XmssNode(node, k, j, adrs, ctx);
88         if (ret != CRYPT_SUCCESS) {
89             return ret;
90         }
91         (void)memcpy_s((sig + (len + j) * n), n, node, n);
92     }
93 
94     ctx->adrsOps.setType(adrs, WOTS_HASH);
95     ctx->adrsOps.setKeyPairAddr(adrs, idx);
96     uint32_t tmpLen = len * n;
97     ret = WotsSign(sig, &tmpLen, msg, (uint32_t)msgLen, adrs, ctx);
98     if (ret != CRYPT_SUCCESS) {
99         return ret;
100     }
101     *sigLen = (len + hp) * n;
102     return CRYPT_SUCCESS;
103 }
104 
XmssPkFromSig(uint32_t idx,const uint8_t * sig,uint32_t sigLen,const uint8_t * msg,uint32_t msgLen,SlhDsaAdrs * adrs,const CryptSlhDsaCtx * ctx,uint8_t * pk)105 int32_t XmssPkFromSig(uint32_t idx, const uint8_t *sig, uint32_t sigLen, const uint8_t *msg, uint32_t msgLen,
106                       SlhDsaAdrs *adrs, const CryptSlhDsaCtx *ctx, uint8_t *pk)
107 {
108     int32_t ret;
109     uint32_t n = ctx->para.n;
110     uint32_t hp = ctx->para.hp;
111     uint32_t len = 2 * n + 3;
112 
113     if (sigLen < (len + hp) * n) {
114         return CRYPT_SLHDSA_ERR_SIG_LEN_NOT_ENOUGH;
115     }
116 
117     ctx->adrsOps.setType(adrs, WOTS_HASH);
118     ctx->adrsOps.setKeyPairAddr(adrs, idx);
119     uint8_t node0[SLH_DSA_MAX_N] = {0};
120     uint8_t node1[SLH_DSA_MAX_N] = {0};
121     ret = WotsPubKeyFromSig(msg, msgLen, sig, sigLen, adrs, ctx, node0);
122     if (ret != CRYPT_SUCCESS) {
123         return ret;
124     }
125     ctx->adrsOps.setType(adrs, TREE);
126     ctx->adrsOps.setTreeIndex(adrs, idx);
127     for (uint32_t k = 0; k < hp; k++) {
128         ctx->adrsOps.setTreeHeight(adrs, k + 1);
129         uint8_t tmp[SLH_DSA_MAX_N * 2];
130         if (((idx >> k) & 1) != 0) {
131             (void)memcpy_s(tmp, sizeof(tmp), sig + (len + k) * n, n);
132             (void)memcpy_s(tmp + n, sizeof(tmp) - n, node0, n);
133             ctx->adrsOps.setTreeIndex(adrs, (ctx->adrsOps.getTreeIndex(adrs) - 1) >> 1);
134         } else {
135             (void)memcpy_s(tmp, sizeof(tmp), node0, n);
136             (void)memcpy_s(tmp + n, sizeof(tmp) - n, sig + (len + k) * n, n);
137             ctx->adrsOps.setTreeIndex(adrs, ctx->adrsOps.getTreeIndex(adrs) >> 1);
138         }
139         ret = ctx->hashFuncs.h(ctx, adrs, tmp, 2 * n, node1);
140         if (ret != CRYPT_SUCCESS) {
141             return ret;
142         }
143         (void)memcpy_s(node0, sizeof(node0), node1, sizeof(node1));
144     }
145     (void)memcpy_s(pk, n, node0, n);
146     return CRYPT_SUCCESS;
147 }
148 
149 #endif // HITLS_CRYPTO_SLH_DSA