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