/* * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ /* @brief Internal LMS helper functions */ #include "internal/packet.h" #include #include #include /* * This LMS implementation assumes that the hash algorithm must be the same for * LMS params and OTS params. Since OpenSSL does not have a "SHAKE256-192" * algorithm, we have to check the digest size as well as the name. * This macro can be used to compare 2 LMS_PARAMS, LMS_PARAMS and LM_OTS_PARAMS. */ #define HASH_NOT_MATCHED(a, b) \ (a)->n != (b)->n || (strcmp((a)->digestname, (b)->digestname) != 0) /* * See RFC 8554 Section 3.1.3: Strings of w-bit Elements * w: Is one of {1,2,4,8} */ static ossl_unused ossl_inline uint8_t lms_ots_coef(const unsigned char *S, uint16_t i, uint8_t w) { uint8_t bitmask = (1 << w) - 1; uint8_t shift = 8 - (w * (i % (8 / w)) + w); int id = (i * w) / 8; return (S[id] >> shift) & bitmask; } static ossl_unused ossl_inline int lms_evp_md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *md, const LMS_PARAMS *lms_params) { OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; OSSL_PARAM *p = NULL; /* The OpenSSL SHAKE implementation requires the xoflen to be set */ if (strncmp(lms_params->digestname, "SHAKE", 5) == 0) { params[0] = OSSL_PARAM_construct_uint32(OSSL_DIGEST_PARAM_XOFLEN, (uint32_t *)&lms_params->n); p = params; } return EVP_DigestInit_ex2(ctx, md, p); }