]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/sha/sha3.c
Raise an error on syscall failure in tls_retry_write_records
[thirdparty/openssl.git] / crypto / sha / sha3.c
CommitLineData
d5e5e2ff 1/*
605856d7 2 * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
d5e5e2ff
SL
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#include <string.h>
11#include "internal/sha3.h"
12
53664908 13void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r, int next);
d5e5e2ff 14
b68a947f 15void ossl_sha3_reset(KECCAK1600_CTX *ctx)
d5e5e2ff
SL
16{
17 memset(ctx->A, 0, sizeof(ctx->A));
18 ctx->bufsz = 0;
53664908 19 ctx->xof_state = XOF_STATE_INIT;
d5e5e2ff
SL
20}
21
b68a947f 22int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
d5e5e2ff
SL
23{
24 size_t bsz = SHA3_BLOCKSIZE(bitlen);
25
26 if (bsz <= sizeof(ctx->buf)) {
b68a947f 27 ossl_sha3_reset(ctx);
d5e5e2ff
SL
28 ctx->block_size = bsz;
29 ctx->md_size = bitlen / 8;
30 ctx->pad = pad;
31 return 1;
32 }
33
34 return 0;
35}
36
b68a947f 37int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
d5e5e2ff 38{
b68a947f 39 int ret = ossl_sha3_init(ctx, pad, bitlen);
d5e5e2ff
SL
40
41 if (ret)
42 ctx->md_size *= 2;
43 return ret;
44}
45
b68a947f 46int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
d5e5e2ff
SL
47{
48 const unsigned char *inp = _inp;
49 size_t bsz = ctx->block_size;
50 size_t num, rem;
51
52 if (len == 0)
53 return 1;
54
53664908 55 if (ctx->xof_state == XOF_STATE_SQUEEZE
56 || ctx->xof_state == XOF_STATE_FINAL)
57 return 0;
58
d5e5e2ff
SL
59 if ((num = ctx->bufsz) != 0) { /* process intermediate buffer? */
60 rem = bsz - num;
61
62 if (len < rem) {
63 memcpy(ctx->buf + num, inp, len);
64 ctx->bufsz += len;
65 return 1;
66 }
67 /*
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...
71 */
72 memcpy(ctx->buf + num, inp, rem);
73 inp += rem, len -= rem;
74 (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
75 ctx->bufsz = 0;
76 /* ctx->buf is processed, ctx->num is guaranteed to be zero */
77 }
78
79 if (len >= bsz)
80 rem = SHA3_absorb(ctx->A, inp, len, bsz);
81 else
82 rem = len;
83
84 if (rem) {
85 memcpy(ctx->buf, inp + len - rem, rem);
86 ctx->bufsz = rem;
87 }
88
89 return 1;
90}
91
53664908 92/*
93 * ossl_sha3_final()is a single shot method
94 * (Use ossl_sha3_squeeze for multiple calls).
95 * outlen is the variable size output.
96 */
97int ossl_sha3_final(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen)
d5e5e2ff
SL
98{
99 size_t bsz = ctx->block_size;
100 size_t num = ctx->bufsz;
101
53664908 102 if (outlen == 0)
a890ef83 103 return 1;
53664908 104 if (ctx->xof_state == XOF_STATE_SQUEEZE
105 || ctx->xof_state == XOF_STATE_FINAL)
106 return 0;
a890ef83 107
d5e5e2ff
SL
108 /*
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
111 * same byte...
112 */
113 memset(ctx->buf + num, 0, bsz - num);
114 ctx->buf[num] = ctx->pad;
115 ctx->buf[bsz - 1] |= 0x80;
116
117 (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
118
53664908 119 ctx->xof_state = XOF_STATE_FINAL;
120 SHA3_squeeze(ctx->A, out, outlen, bsz, 0);
121 return 1;
122}
123
124/*
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.
133 */
134int ossl_sha3_squeeze(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen)
135{
136 size_t bsz = ctx->block_size;
137 size_t num = ctx->bufsz;
138 size_t len;
139 int next = 1;
140
141 if (outlen == 0)
142 return 1;
143
144 if (ctx->xof_state == XOF_STATE_FINAL)
145 return 0;
146
147 /*
148 * On the first squeeze call, finish the absorb process,
149 * by adding the trailing padding and then doing
150 * a final absorb.
151 */
152 if (ctx->xof_state != XOF_STATE_SQUEEZE) {
153 /*
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
156 * same byte...
157 */
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;
164 next = 0;
165 }
166
167 /*
168 * Step 1. Consume any bytes left over from a previous squeeze
169 * (See Step 4 below).
170 */
171 if (num != 0) {
172 if (outlen > ctx->bufsz)
173 len = ctx->bufsz;
174 else
175 len = outlen;
176 memcpy(out, ctx->buf + bsz - ctx->bufsz, len);
177 out += len;
178 outlen -= len;
179 ctx->bufsz -= len;
180 }
181 if (outlen == 0)
182 return 1;
183
184 /* Step 2. Copy full sized squeezed blocks to the output buffer directly */
185 if (outlen >= bsz) {
186 len = bsz * (outlen / bsz);
187 SHA3_squeeze(ctx->A, out, len, bsz, next);
188 next = 1;
189 out += len;
190 outlen -= len;
191 }
192 if (outlen > 0) {
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;
198 }
d5e5e2ff
SL
199
200 return 1;
201}