1 /*
2  * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 /* @brief Internal LMS helper functions */
11 
12 #include "internal/packet.h"
13 #include <openssl/params.h>
14 #include <openssl/core_names.h>
15 #include <openssl/evp.h>
16 
17 /*
18  * This LMS implementation assumes that the hash algorithm must be the same for
19  * LMS params and OTS params. Since OpenSSL does not have a "SHAKE256-192"
20  * algorithm, we have to check the digest size as well as the name.
21  * This macro can be used to compare 2 LMS_PARAMS, LMS_PARAMS and LM_OTS_PARAMS.
22  */
23 #define HASH_NOT_MATCHED(a, b) \
24     (a)->n != (b)->n || (strcmp((a)->digestname, (b)->digestname) != 0)
25 
26 /*
27  * See RFC 8554 Section 3.1.3: Strings of w-bit Elements
28  * w: Is one of {1,2,4,8}
29  */
30 static ossl_unused ossl_inline
lms_ots_coef(const unsigned char * S,uint16_t i,uint8_t w)31 uint8_t lms_ots_coef(const unsigned char *S, uint16_t i, uint8_t w)
32 {
33     uint8_t bitmask = (1 << w) - 1;
34     uint8_t shift = 8 - (w * (i % (8 / w)) + w);
35     int id = (i * w) / 8;
36 
37     return (S[id] >> shift) & bitmask;
38 }
39 
40 static ossl_unused ossl_inline
lms_evp_md_ctx_init(EVP_MD_CTX * ctx,const EVP_MD * md,const LMS_PARAMS * lms_params)41 int lms_evp_md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *md,
42                         const LMS_PARAMS *lms_params)
43 {
44     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
45     OSSL_PARAM *p = NULL;
46 
47     /* The OpenSSL SHAKE implementation requires the xoflen to be set */
48     if (strncmp(lms_params->digestname, "SHAKE", 5) == 0) {
49         params[0] = OSSL_PARAM_construct_uint32(OSSL_DIGEST_PARAM_XOFLEN,
50                                                 (uint32_t *)&lms_params->n);
51         p = params;
52     }
53     return EVP_DigestInit_ex2(ctx, md, p);
54 }
55