1
0

slh_hash.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * Copyright 2024-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. #include "internal/deprecated.h" /* PKCS1_MGF1() */
  10. #include <string.h>
  11. #include <openssl/evp.h>
  12. #include <openssl/core_names.h>
  13. #include <openssl/rsa.h> /* PKCS1_MGF1() */
  14. #include "slh_dsa_local.h"
  15. #include "slh_dsa_key.h"
  16. #define MAX_DIGEST_SIZE 64 /* SHA-512 is used for security category 3 & 5 */
  17. static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_sha2;
  18. static OSSL_SLH_HASHFUNC_PRF slh_prf_sha2;
  19. static OSSL_SLH_HASHFUNC_PRF_MSG slh_prf_msg_sha2;
  20. static OSSL_SLH_HASHFUNC_F slh_f_sha2;
  21. static OSSL_SLH_HASHFUNC_H slh_h_sha2;
  22. static OSSL_SLH_HASHFUNC_T slh_t_sha2;
  23. static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_shake;
  24. static OSSL_SLH_HASHFUNC_PRF slh_prf_shake;
  25. static OSSL_SLH_HASHFUNC_PRF_MSG slh_prf_msg_shake;
  26. static OSSL_SLH_HASHFUNC_F slh_f_shake;
  27. static OSSL_SLH_HASHFUNC_H slh_h_shake;
  28. static OSSL_SLH_HASHFUNC_T slh_t_shake;
  29. static ossl_inline int xof_digest_3(EVP_MD_CTX *ctx,
  30. const uint8_t *in1, size_t in1_len,
  31. const uint8_t *in2, size_t in2_len,
  32. const uint8_t *in3, size_t in3_len,
  33. uint8_t *out, size_t out_len)
  34. {
  35. return (EVP_DigestInit_ex2(ctx, NULL, NULL) == 1
  36. && EVP_DigestUpdate(ctx, in1, in1_len) == 1
  37. && EVP_DigestUpdate(ctx, in2, in2_len) == 1
  38. && EVP_DigestUpdate(ctx, in3, in3_len) == 1
  39. && EVP_DigestFinalXOF(ctx, out, out_len) == 1);
  40. }
  41. static ossl_inline int xof_digest_4(EVP_MD_CTX *ctx,
  42. const uint8_t *in1, size_t in1_len,
  43. const uint8_t *in2, size_t in2_len,
  44. const uint8_t *in3, size_t in3_len,
  45. const uint8_t *in4, size_t in4_len,
  46. uint8_t *out, size_t out_len)
  47. {
  48. return (EVP_DigestInit_ex2(ctx, NULL, NULL) == 1
  49. && EVP_DigestUpdate(ctx, in1, in1_len) == 1
  50. && EVP_DigestUpdate(ctx, in2, in2_len) == 1
  51. && EVP_DigestUpdate(ctx, in3, in3_len) == 1
  52. && EVP_DigestUpdate(ctx, in4, in4_len) == 1
  53. && EVP_DigestFinalXOF(ctx, out, out_len) == 1);
  54. }
  55. /* See FIPS 205 Section 11.1 */
  56. static int
  57. slh_hmsg_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *r,
  58. const uint8_t *pk_seed, const uint8_t *pk_root,
  59. const uint8_t *msg, size_t msg_len,
  60. uint8_t *out, size_t out_len)
  61. {
  62. const SLH_DSA_PARAMS *params = ctx->key->params;
  63. size_t m = params->m;
  64. size_t n = params->n;
  65. return xof_digest_4(ctx->md_ctx, r, n, pk_seed, n, pk_root, n,
  66. msg, msg_len, out, m);
  67. }
  68. static int
  69. slh_prf_shake(SLH_DSA_HASH_CTX *ctx,
  70. const uint8_t *pk_seed, const uint8_t *sk_seed,
  71. const uint8_t *adrs, uint8_t *out, size_t out_len)
  72. {
  73. const SLH_DSA_PARAMS *params = ctx->key->params;
  74. size_t n = params->n;
  75. return xof_digest_3(ctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE,
  76. sk_seed, n, out, n);
  77. }
  78. static int
  79. slh_prf_msg_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *sk_prf,
  80. const uint8_t *opt_rand, const uint8_t *msg, size_t msg_len,
  81. WPACKET *pkt)
  82. {
  83. unsigned char out[SLH_MAX_N];
  84. const SLH_DSA_PARAMS *params = ctx->key->params;
  85. size_t n = params->n;
  86. return xof_digest_3(ctx->md_ctx, sk_prf, n, opt_rand, n, msg, msg_len, out, n)
  87. && WPACKET_memcpy(pkt, out, n);
  88. }
  89. static int
  90. slh_f_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *pk_seed, const uint8_t *adrs,
  91. const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
  92. {
  93. const SLH_DSA_PARAMS *params = ctx->key->params;
  94. size_t n = params->n;
  95. return xof_digest_3(ctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, m1, m1_len, out, n);
  96. }
  97. static int
  98. slh_h_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *pk_seed, const uint8_t *adrs,
  99. const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
  100. {
  101. const SLH_DSA_PARAMS *params = ctx->key->params;
  102. size_t n = params->n;
  103. return xof_digest_4(ctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, m1, n, m2, n, out, n);
  104. }
  105. static int
  106. slh_t_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *pk_seed, const uint8_t *adrs,
  107. const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
  108. {
  109. const SLH_DSA_PARAMS *params = ctx->key->params;
  110. size_t n = params->n;
  111. return xof_digest_3(ctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, ml, ml_len, out, n);
  112. }
  113. static ossl_inline int
  114. digest_4(EVP_MD_CTX *ctx,
  115. const uint8_t *in1, size_t in1_len, const uint8_t *in2, size_t in2_len,
  116. const uint8_t *in3, size_t in3_len, const uint8_t *in4, size_t in4_len,
  117. uint8_t *out)
  118. {
  119. return (EVP_DigestInit_ex2(ctx, NULL, NULL) == 1
  120. && EVP_DigestUpdate(ctx, in1, in1_len) == 1
  121. && EVP_DigestUpdate(ctx, in2, in2_len) == 1
  122. && EVP_DigestUpdate(ctx, in3, in3_len) == 1
  123. && EVP_DigestUpdate(ctx, in4, in4_len) == 1
  124. && EVP_DigestFinal_ex(ctx, out, NULL) == 1);
  125. }
  126. /* FIPS 205 Section 11.2.1 and 11.2.2 */
  127. static int
  128. slh_hmsg_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
  129. const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
  130. uint8_t *out, size_t out_len)
  131. {
  132. const SLH_DSA_PARAMS *params = hctx->key->params;
  133. size_t m = params->m;
  134. size_t n = params->n;
  135. uint8_t seed[2 * SLH_MAX_N + MAX_DIGEST_SIZE];
  136. int sz = EVP_MD_get_size(hctx->key->md_big);
  137. size_t seed_len = (size_t)sz + 2 * n;
  138. if (sz <= 0)
  139. return 0;
  140. memcpy(seed, r, n);
  141. memcpy(seed + n, pk_seed, n);
  142. return digest_4(hctx->md_big_ctx, r, n, pk_seed, n, pk_root, n, msg, msg_len,
  143. seed + 2 * n)
  144. && (PKCS1_MGF1(out, m, seed, seed_len, hctx->key->md_big) == 0);
  145. }
  146. static int
  147. slh_prf_msg_sha2(SLH_DSA_HASH_CTX *hctx,
  148. const uint8_t *sk_prf, const uint8_t *opt_rand,
  149. const uint8_t *msg, size_t msg_len, WPACKET *pkt)
  150. {
  151. int ret;
  152. const SLH_DSA_KEY *key = hctx->key;
  153. EVP_MAC_CTX *mctx = hctx->hmac_ctx;
  154. const SLH_DSA_PARAMS *prms = key->params;
  155. size_t n = prms->n;
  156. uint8_t mac[MAX_DIGEST_SIZE] = {0};
  157. OSSL_PARAM *p = NULL;
  158. OSSL_PARAM params[3];
  159. /*
  160. * Due to the way HMAC works, it is not possible to do this code early
  161. * in hmac_ctx_new() since it requires a key in order to set the digest.
  162. * So we do a lazy update here on the first call.
  163. */
  164. if (hctx->hmac_digest_used == 0) {
  165. p = params;
  166. /* The underlying digest to be used */
  167. *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
  168. (char *)EVP_MD_get0_name(key->md_big), 0);
  169. if (key->propq != NULL)
  170. *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
  171. (char *)key->propq, 0);
  172. *p = OSSL_PARAM_construct_end();
  173. p = params;
  174. hctx->hmac_digest_used = 1;
  175. }
  176. ret = EVP_MAC_init(mctx, sk_prf, n, p) == 1
  177. && EVP_MAC_update(mctx, opt_rand, n) == 1
  178. && EVP_MAC_update(mctx, msg, msg_len) == 1
  179. && EVP_MAC_final(mctx, mac, NULL, sizeof(mac)) == 1
  180. && WPACKET_memcpy(pkt, mac, n); /* Truncate output to n bytes */
  181. return ret;
  182. }
  183. static ossl_inline int
  184. do_hash(EVP_MD_CTX *ctx, size_t n, const uint8_t *pk_seed, const uint8_t *adrs,
  185. const uint8_t *m, size_t m_len, size_t b, uint8_t *out, size_t out_len)
  186. {
  187. int ret;
  188. uint8_t zeros[128] = { 0 };
  189. uint8_t digest[MAX_DIGEST_SIZE];
  190. ret = digest_4(ctx, pk_seed, n, zeros, b - n, adrs, SLH_ADRSC_SIZE,
  191. m, m_len, digest);
  192. /* Truncated returned value is n = 16 bytes */
  193. memcpy(out, digest, n);
  194. return ret;
  195. }
  196. static int
  197. slh_prf_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed,
  198. const uint8_t *sk_seed, const uint8_t *adrs,
  199. uint8_t *out, size_t out_len)
  200. {
  201. size_t n = hctx->key->params->n;
  202. return do_hash(hctx->md_ctx, n, pk_seed, adrs, sk_seed, n,
  203. OSSL_SLH_DSA_SHA2_NUM_ZEROS_H_AND_T_BOUND1, out, out_len);
  204. }
  205. static int
  206. slh_f_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
  207. const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
  208. {
  209. return do_hash(hctx->md_ctx, hctx->key->params->n, pk_seed, adrs, m1, m1_len,
  210. OSSL_SLH_DSA_SHA2_NUM_ZEROS_H_AND_T_BOUND1, out, out_len);
  211. }
  212. static int
  213. slh_h_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
  214. const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
  215. {
  216. uint8_t m[SLH_MAX_N * 2];
  217. const SLH_DSA_PARAMS *prms = hctx->key->params;
  218. size_t n = prms->n;
  219. memcpy(m, m1, n);
  220. memcpy(m + n, m2, n);
  221. return do_hash(hctx->md_big_ctx, n, pk_seed, adrs, m, 2 * n,
  222. prms->sha2_h_and_t_bound, out, out_len);
  223. }
  224. static int
  225. slh_t_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
  226. const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
  227. {
  228. const SLH_DSA_PARAMS *prms = hctx->key->params;
  229. return do_hash(hctx->md_big_ctx, prms->n, pk_seed, adrs, ml, ml_len,
  230. prms->sha2_h_and_t_bound, out, out_len);
  231. }
  232. const SLH_HASH_FUNC *ossl_slh_get_hash_fn(int is_shake)
  233. {
  234. static const SLH_HASH_FUNC methods[] = {
  235. {
  236. slh_hmsg_shake,
  237. slh_prf_shake,
  238. slh_prf_msg_shake,
  239. slh_f_shake,
  240. slh_h_shake,
  241. slh_t_shake
  242. },
  243. {
  244. slh_hmsg_sha2,
  245. slh_prf_sha2,
  246. slh_prf_msg_sha2,
  247. slh_f_sha2,
  248. slh_h_sha2,
  249. slh_t_sha2
  250. }
  251. };
  252. return &methods[is_shake ? 0 : 1];
  253. }