]>
Commit | Line | Data |
---|---|---|
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 | 13 | void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r, int next); |
d5e5e2ff | 14 | |
b68a947f | 15 | void 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 | 22 | int 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 | 37 | int 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 | 46 | int 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 | */ | |
97 | int 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 | */ | |
134 | int 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 | } |