sha3.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright 2017-2020 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 <string.h>
  10. #include "internal/sha3.h"
  11. void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r, int next);
  12. void ossl_sha3_reset(KECCAK1600_CTX *ctx)
  13. {
  14. memset(ctx->A, 0, sizeof(ctx->A));
  15. ctx->bufsz = 0;
  16. ctx->xof_state = XOF_STATE_INIT;
  17. }
  18. int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
  19. {
  20. size_t bsz = SHA3_BLOCKSIZE(bitlen);
  21. if (bsz <= sizeof(ctx->buf)) {
  22. ossl_sha3_reset(ctx);
  23. ctx->block_size = bsz;
  24. ctx->md_size = bitlen / 8;
  25. ctx->pad = pad;
  26. return 1;
  27. }
  28. return 0;
  29. }
  30. int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
  31. {
  32. int ret = ossl_sha3_init(ctx, pad, bitlen);
  33. if (ret)
  34. ctx->md_size *= 2;
  35. return ret;
  36. }
  37. int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
  38. {
  39. const unsigned char *inp = _inp;
  40. size_t bsz = ctx->block_size;
  41. size_t num, rem;
  42. if (len == 0)
  43. return 1;
  44. if (ctx->xof_state == XOF_STATE_SQUEEZE
  45. || ctx->xof_state == XOF_STATE_FINAL)
  46. return 0;
  47. if ((num = ctx->bufsz) != 0) { /* process intermediate buffer? */
  48. rem = bsz - num;
  49. if (len < rem) {
  50. memcpy(ctx->buf + num, inp, len);
  51. ctx->bufsz += len;
  52. return 1;
  53. }
  54. /*
  55. * We have enough data to fill or overflow the intermediate
  56. * buffer. So we append |rem| bytes and process the block,
  57. * leaving the rest for later processing...
  58. */
  59. memcpy(ctx->buf + num, inp, rem);
  60. inp += rem, len -= rem;
  61. (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
  62. ctx->bufsz = 0;
  63. /* ctx->buf is processed, ctx->num is guaranteed to be zero */
  64. }
  65. if (len >= bsz)
  66. rem = SHA3_absorb(ctx->A, inp, len, bsz);
  67. else
  68. rem = len;
  69. if (rem) {
  70. memcpy(ctx->buf, inp + len - rem, rem);
  71. ctx->bufsz = rem;
  72. }
  73. return 1;
  74. }
  75. /*
  76. * ossl_sha3_final()is a single shot method
  77. * (Use ossl_sha3_squeeze for multiple calls).
  78. * outlen is the variable size output.
  79. */
  80. int ossl_sha3_final(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen)
  81. {
  82. size_t bsz = ctx->block_size;
  83. size_t num = ctx->bufsz;
  84. if (outlen == 0)
  85. return 1;
  86. if (ctx->xof_state == XOF_STATE_SQUEEZE
  87. || ctx->xof_state == XOF_STATE_FINAL)
  88. return 0;
  89. /*
  90. * Pad the data with 10*1. Note that |num| can be |bsz - 1|
  91. * in which case both byte operations below are performed on
  92. * same byte...
  93. */
  94. memset(ctx->buf + num, 0, bsz - num);
  95. ctx->buf[num] = ctx->pad;
  96. ctx->buf[bsz - 1] |= 0x80;
  97. (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
  98. ctx->xof_state = XOF_STATE_FINAL;
  99. SHA3_squeeze(ctx->A, out, outlen, bsz, 0);
  100. return 1;
  101. }
  102. /*
  103. * This method can be called multiple times.
  104. * Rather than heavily modifying assembler for SHA3_squeeze(),
  105. * we instead just use the limitations of the existing function.
  106. * i.e. Only request multiples of the ctx->block_size when calling
  107. * SHA3_squeeze(). For output length requests smaller than the
  108. * ctx->block_size just request a single ctx->block_size bytes and
  109. * buffer the results. The next request will use the buffer first
  110. * to grab output bytes.
  111. */
  112. int ossl_sha3_squeeze(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen)
  113. {
  114. size_t bsz = ctx->block_size;
  115. size_t num = ctx->bufsz;
  116. size_t len;
  117. int next = 1;
  118. if (outlen == 0)
  119. return 1;
  120. if (ctx->xof_state == XOF_STATE_FINAL)
  121. return 0;
  122. /*
  123. * On the first squeeze call, finish the absorb process,
  124. * by adding the trailing padding and then doing
  125. * a final absorb.
  126. */
  127. if (ctx->xof_state != XOF_STATE_SQUEEZE) {
  128. /*
  129. * Pad the data with 10*1. Note that |num| can be |bsz - 1|
  130. * in which case both byte operations below are performed on
  131. * same byte...
  132. */
  133. memset(ctx->buf + num, 0, bsz - num);
  134. ctx->buf[num] = ctx->pad;
  135. ctx->buf[bsz - 1] |= 0x80;
  136. (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
  137. ctx->xof_state = XOF_STATE_SQUEEZE;
  138. num = ctx->bufsz = 0;
  139. next = 0;
  140. }
  141. /*
  142. * Step 1. Consume any bytes left over from a previous squeeze
  143. * (See Step 4 below).
  144. */
  145. if (num != 0) {
  146. if (outlen > ctx->bufsz)
  147. len = ctx->bufsz;
  148. else
  149. len = outlen;
  150. memcpy(out, ctx->buf + bsz - ctx->bufsz, len);
  151. out += len;
  152. outlen -= len;
  153. ctx->bufsz -= len;
  154. }
  155. if (outlen == 0)
  156. return 1;
  157. /* Step 2. Copy full sized squeezed blocks to the output buffer directly */
  158. if (outlen >= bsz) {
  159. len = bsz * (outlen / bsz);
  160. SHA3_squeeze(ctx->A, out, len, bsz, next);
  161. next = 1;
  162. out += len;
  163. outlen -= len;
  164. }
  165. if (outlen > 0) {
  166. /* Step 3. Squeeze one more block into a buffer */
  167. SHA3_squeeze(ctx->A, ctx->buf, bsz, bsz, next);
  168. memcpy(out, ctx->buf, outlen);
  169. /* Step 4. Remember the leftover part of the squeezed block */
  170. ctx->bufsz = bsz - outlen;
  171. }
  172. return 1;
  173. }