]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/sha/sha3.c
2 * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
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
11 #include "internal/sha3.h"
13 void SHA3_squeeze(uint64_t A
[5][5], unsigned char *out
, size_t len
, size_t r
, int next
);
15 void ossl_sha3_reset(KECCAK1600_CTX
*ctx
)
17 memset(ctx
->A
, 0, sizeof(ctx
->A
));
19 ctx
->xof_state
= XOF_STATE_INIT
;
22 int ossl_sha3_init(KECCAK1600_CTX
*ctx
, unsigned char pad
, size_t bitlen
)
24 size_t bsz
= SHA3_BLOCKSIZE(bitlen
);
26 if (bsz
<= sizeof(ctx
->buf
)) {
28 ctx
->block_size
= bsz
;
29 ctx
->md_size
= bitlen
/ 8;
37 int ossl_keccak_kmac_init(KECCAK1600_CTX
*ctx
, unsigned char pad
, size_t bitlen
)
39 int ret
= ossl_sha3_init(ctx
, pad
, bitlen
);
46 int ossl_sha3_update(KECCAK1600_CTX
*ctx
, const void *_inp
, size_t len
)
48 const unsigned char *inp
= _inp
;
49 size_t bsz
= ctx
->block_size
;
55 if (ctx
->xof_state
== XOF_STATE_SQUEEZE
56 || ctx
->xof_state
== XOF_STATE_FINAL
)
59 if ((num
= ctx
->bufsz
) != 0) { /* process intermediate buffer? */
63 memcpy(ctx
->buf
+ num
, inp
, len
);
68 * We have enough data to fill or overflow the intermediate
69 * buffer. So we append |rem| bytes and process the block,
70 * leaving the rest for later processing...
72 memcpy(ctx
->buf
+ num
, inp
, rem
);
73 inp
+= rem
, len
-= rem
;
74 (void)SHA3_absorb(ctx
->A
, ctx
->buf
, bsz
, bsz
);
76 /* ctx->buf is processed, ctx->num is guaranteed to be zero */
80 rem
= SHA3_absorb(ctx
->A
, inp
, len
, bsz
);
85 memcpy(ctx
->buf
, inp
+ len
- rem
, rem
);
93 * ossl_sha3_final()is a single shot method
94 * (Use ossl_sha3_squeeze for multiple calls).
95 * outlen is the variable size output.
97 int ossl_sha3_final(KECCAK1600_CTX
*ctx
, unsigned char *out
, size_t outlen
)
99 size_t bsz
= ctx
->block_size
;
100 size_t num
= ctx
->bufsz
;
104 if (ctx
->xof_state
== XOF_STATE_SQUEEZE
105 || ctx
->xof_state
== XOF_STATE_FINAL
)
109 * Pad the data with 10*1. Note that |num| can be |bsz - 1|
110 * in which case both byte operations below are performed on
113 memset(ctx
->buf
+ num
, 0, bsz
- num
);
114 ctx
->buf
[num
] = ctx
->pad
;
115 ctx
->buf
[bsz
- 1] |= 0x80;
117 (void)SHA3_absorb(ctx
->A
, ctx
->buf
, bsz
, bsz
);
119 ctx
->xof_state
= XOF_STATE_FINAL
;
120 SHA3_squeeze(ctx
->A
, out
, outlen
, bsz
, 0);
125 * This method can be called multiple times.
126 * Rather than heavily modifying assembler for SHA3_squeeze(),
127 * we instead just use the limitations of the existing function.
128 * i.e. Only request multiples of the ctx->block_size when calling
129 * SHA3_squeeze(). For output length requests smaller than the
130 * ctx->block_size just request a single ctx->block_size bytes and
131 * buffer the results. The next request will use the buffer first
132 * to grab output bytes.
134 int ossl_sha3_squeeze(KECCAK1600_CTX
*ctx
, unsigned char *out
, size_t outlen
)
136 size_t bsz
= ctx
->block_size
;
137 size_t num
= ctx
->bufsz
;
144 if (ctx
->xof_state
== XOF_STATE_FINAL
)
148 * On the first squeeze call, finish the absorb process,
149 * by adding the trailing padding and then doing
152 if (ctx
->xof_state
!= XOF_STATE_SQUEEZE
) {
154 * Pad the data with 10*1. Note that |num| can be |bsz - 1|
155 * in which case both byte operations below are performed on
158 memset(ctx
->buf
+ num
, 0, bsz
- num
);
159 ctx
->buf
[num
] = ctx
->pad
;
160 ctx
->buf
[bsz
- 1] |= 0x80;
161 (void)SHA3_absorb(ctx
->A
, ctx
->buf
, bsz
, bsz
);
162 ctx
->xof_state
= XOF_STATE_SQUEEZE
;
163 num
= ctx
->bufsz
= 0;
168 * Step 1. Consume any bytes left over from a previous squeeze
169 * (See Step 4 below).
172 if (outlen
> ctx
->bufsz
)
176 memcpy(out
, ctx
->buf
+ bsz
- ctx
->bufsz
, len
);
184 /* Step 2. Copy full sized squeezed blocks to the output buffer directly */
186 len
= bsz
* (outlen
/ bsz
);
187 SHA3_squeeze(ctx
->A
, out
, len
, bsz
, next
);
193 /* Step 3. Squeeze one more block into a buffer */
194 SHA3_squeeze(ctx
->A
, ctx
->buf
, bsz
, bsz
, next
);
195 memcpy(out
, ctx
->buf
, outlen
);
196 /* Step 4. Remember the leftover part of the squeezed block */
197 ctx
->bufsz
= bsz
- outlen
;