xref: /openssl/test/evp_xof_test.c (revision dc5afb7e)
1 /*
2  * Copyright 2023-2024 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 
10 #include <openssl/evp.h>
11 #include <openssl/rand.h>
12 #include <openssl/core_names.h>
13 #include "testutil.h"
14 #include "internal/nelem.h"
15 
16 static const unsigned char shake256_input[] = {
17     0x8d, 0x80, 0x01, 0xe2, 0xc0, 0x96, 0xf1, 0xb8,
18     0x8e, 0x7c, 0x92, 0x24, 0xa0, 0x86, 0xef, 0xd4,
19     0x79, 0x7f, 0xbf, 0x74, 0xa8, 0x03, 0x3a, 0x2d,
20     0x42, 0x2a, 0x2b, 0x6b, 0x8f, 0x67, 0x47, 0xe4
21 };
22 
23 /*
24  * This KAT output is 250 bytes, which is more than
25  * the SHAKE256 block size (136 bytes).
26  */
27 static const unsigned char shake256_output[] = {
28     0x2e, 0x97, 0x5f, 0x6a, 0x8a, 0x14, 0xf0, 0x70,
29     0x4d, 0x51, 0xb1, 0x36, 0x67, 0xd8, 0x19, 0x5c,
30     0x21, 0x9f, 0x71, 0xe6, 0x34, 0x56, 0x96, 0xc4,
31     0x9f, 0xa4, 0xb9, 0xd0, 0x8e, 0x92, 0x25, 0xd3,
32     0xd3, 0x93, 0x93, 0x42, 0x51, 0x52, 0xc9, 0x7e,
33     0x71, 0xdd, 0x24, 0x60, 0x1c, 0x11, 0xab, 0xcf,
34     0xa0, 0xf1, 0x2f, 0x53, 0xc6, 0x80, 0xbd, 0x3a,
35     0xe7, 0x57, 0xb8, 0x13, 0x4a, 0x9c, 0x10, 0xd4,
36     0x29, 0x61, 0x58, 0x69, 0x21, 0x7f, 0xdd, 0x58,
37     0x85, 0xc4, 0xdb, 0x17, 0x49, 0x85, 0x70, 0x3a,
38     0x6d, 0x6d, 0xe9, 0x4a, 0x66, 0x7e, 0xac, 0x30,
39     0x23, 0x44, 0x3a, 0x83, 0x37, 0xae, 0x1b, 0xc6,
40     0x01, 0xb7, 0x6d, 0x7d, 0x38, 0xec, 0x3c, 0x34,
41     0x46, 0x31, 0x05, 0xf0, 0xd3, 0x94, 0x9d, 0x78,
42     0xe5, 0x62, 0xa0, 0x39, 0xe4, 0x46, 0x95, 0x48,
43     0xb6, 0x09, 0x39, 0x5d, 0xe5, 0xa4, 0xfd, 0x43,
44     0xc4, 0x6c, 0xa9, 0xfd, 0x6e, 0xe2, 0x9a, 0xda,
45     0x5e, 0xfc, 0x07, 0xd8, 0x4d, 0x55, 0x32, 0x49,
46     0x45, 0x0d, 0xab, 0x4a, 0x49, 0xc4, 0x83, 0xde,
47     0xd2, 0x50, 0xc9, 0x33, 0x8f, 0x85, 0xcd, 0x93,
48     0x7a, 0xe6, 0x6b, 0xb4, 0x36, 0xf3, 0xb4, 0x02,
49     0x6e, 0x85, 0x9f, 0xda, 0x1c, 0xa5, 0x71, 0x43,
50     0x2f, 0x3b, 0xfc, 0x09, 0xe7, 0xc0, 0x3c, 0xa4,
51     0xd1, 0x83, 0xb7, 0x41, 0x11, 0x1c, 0xa0, 0x48,
52     0x3d, 0x0e, 0xda, 0xbc, 0x03, 0xfe, 0xb2, 0x3b,
53     0x17, 0xee, 0x48, 0xe8, 0x44, 0xba, 0x24, 0x08,
54     0xd9, 0xdc, 0xfd, 0x01, 0x39, 0xd2, 0xe8, 0xc7,
55     0x31, 0x01, 0x25, 0xae, 0xe8, 0x01, 0xc6, 0x1a,
56     0xb7, 0x90, 0x0d, 0x1e, 0xfc, 0x47, 0xc0, 0x78,
57     0x28, 0x17, 0x66, 0xf3, 0x61, 0xc5, 0xe6, 0x11,
58     0x13, 0x46, 0x23, 0x5e, 0x1d, 0xc3, 0x83, 0x25,
59     0x66, 0x6c
60 };
61 
62 static const unsigned char shake256_largemsg_input[] = {
63     0xb2, 0xd2, 0x38, 0x65, 0xaf, 0x8f, 0x25, 0x6e,
64     0x64, 0x40, 0xe2, 0x0d, 0x49, 0x8e, 0x3e, 0x64,
65     0x46, 0xd2, 0x03, 0xa4, 0x19, 0xe3, 0x7b, 0x80,
66     0xf7, 0x2b, 0x32, 0xe2, 0x76, 0x01, 0xfe, 0xdd,
67     0xaa, 0x33, 0x3d, 0xe4, 0x8e, 0xe1, 0x5e, 0x39,
68     0xa6, 0x92, 0xa3, 0xa7, 0xe3, 0x81, 0x24, 0x74,
69     0xc7, 0x38, 0x18, 0x92, 0xc9, 0x60, 0x50, 0x15,
70     0xfb, 0xd8, 0x04, 0xea, 0xea, 0x04, 0xd2, 0xc5,
71     0xc6, 0x68, 0x04, 0x5b, 0xc3, 0x75, 0x12, 0xd2,
72     0xbe, 0xa2, 0x67, 0x75, 0x24, 0xbf, 0x68, 0xad,
73     0x10, 0x86, 0xb3, 0x2c, 0xb3, 0x74, 0xa4, 0x6c,
74     0xf9, 0xd7, 0x1e, 0x58, 0x69, 0x27, 0x88, 0x49,
75     0x4e, 0x99, 0x15, 0x33, 0x14, 0xf2, 0x49, 0x21,
76     0xf4, 0x99, 0xb9, 0xde, 0xd4, 0xf1, 0x12, 0xf5,
77     0x68, 0xe5, 0x5c, 0xdc, 0x9e, 0xc5, 0x80, 0x6d,
78     0x39, 0x50, 0x08, 0x95, 0xbb, 0x12, 0x27, 0x50,
79     0x89, 0xf0, 0xf9, 0xd5, 0x4a, 0x01, 0x0b, 0x0d,
80     0x90, 0x9f, 0x1e, 0x4a, 0xba, 0xbe, 0x28, 0x36,
81     0x19, 0x7d, 0x9c, 0x0a, 0x51, 0xfb, 0xeb, 0x00,
82     0x02, 0x6c, 0x4b, 0x0a, 0xa8, 0x6c, 0xb7, 0xc4,
83     0xc0, 0x92, 0x37, 0xa7, 0x2d, 0x49, 0x61, 0x80,
84     0xd9, 0xdb, 0x20, 0x21, 0x9f, 0xcf, 0xb4, 0x57,
85     0x69, 0x75, 0xfa, 0x1c, 0x95, 0xbf, 0xee, 0x0d,
86     0x9e, 0x52, 0x6e, 0x1e, 0xf8, 0xdd, 0x41, 0x8c,
87     0x3b, 0xaa, 0x57, 0x13, 0x84, 0x73, 0x52, 0x62,
88     0x18, 0x76, 0x46, 0xcc, 0x4b, 0xcb, 0xbd, 0x40,
89     0xa1, 0xf6, 0xff, 0x7b, 0x32, 0xb9, 0x90, 0x7c,
90     0x53, 0x2c, 0xf9, 0x38, 0x72, 0x0f, 0xcb, 0x90,
91     0x42, 0x5e, 0xe2, 0x80, 0x19, 0x26, 0xe7, 0x99,
92     0x96, 0x98, 0x18, 0xb1, 0x86, 0x5b, 0x4c, 0xd9,
93     0x08, 0x27, 0x31, 0x8f, 0xf0, 0x90, 0xd9, 0x35,
94     0x6a, 0x1f, 0x75, 0xc2, 0xe0, 0xa7, 0x60, 0xb8,
95     0x1d, 0xd6, 0x5f, 0x56, 0xb2, 0x0b, 0x27, 0x0e,
96     0x98, 0x67, 0x1f, 0x39, 0x18, 0x27, 0x68, 0x0a,
97     0xe8, 0x31, 0x1b, 0xc0, 0x97, 0xec, 0xd1, 0x20,
98     0x2a, 0x55, 0x69, 0x23, 0x08, 0x50, 0x05, 0xec,
99     0x13, 0x3b, 0x56, 0xfc, 0x18, 0xc9, 0x1a, 0xa9,
100     0x69, 0x0e, 0xe2, 0xcc, 0xc8, 0xd6, 0x19, 0xbb,
101     0x87, 0x3b, 0x42, 0x77, 0xee, 0x77, 0x81, 0x26,
102     0xdd, 0xf6, 0x5d, 0xc3, 0xb2, 0xb0, 0xc4, 0x14,
103     0x6d, 0xb5, 0x4f, 0xdc, 0x13, 0x09, 0xc8, 0x53,
104     0x50, 0xb3, 0xea, 0xd3, 0x5f, 0x11, 0x67, 0xd4,
105     0x2f, 0x6e, 0x30, 0x1a, 0xbe, 0xd6, 0xf0, 0x2d,
106     0xc9, 0x29, 0xd9, 0x0a, 0xa8, 0x6f, 0xa4, 0x18,
107     0x74, 0x6b, 0xd3, 0x5d, 0x6a, 0x73, 0x3a, 0xf2,
108     0x94, 0x7f, 0xbd, 0xb4, 0xa6, 0x7f, 0x5b, 0x3d,
109     0x26, 0xf2, 0x6c, 0x13, 0xcf, 0xb4, 0x26, 0x1e,
110     0x38, 0x17, 0x66, 0x60, 0xb1, 0x36, 0xae, 0xe0,
111     0x6d, 0x86, 0x69, 0xe7, 0xe7, 0xae, 0x77, 0x6f,
112     0x7e, 0x99, 0xe5, 0xd9, 0x62, 0xc9, 0xfc, 0xde,
113     0xb4, 0xee, 0x7e, 0xc8, 0xe9, 0xb7, 0x2c, 0xe2,
114     0x70, 0xe8, 0x8b, 0x2d, 0x94, 0xad, 0xe8, 0x54,
115     0xa3, 0x2d, 0x9a, 0xe2, 0x50, 0x63, 0x87, 0xb3,
116     0x56, 0x29, 0xea, 0xa8, 0x5e, 0x96, 0x53, 0x9f,
117     0x23, 0x8a, 0xef, 0xa3, 0xd4, 0x87, 0x09, 0x5f,
118     0xba, 0xc3, 0xd1, 0xd9, 0x1a, 0x7b, 0x5c, 0x5d,
119     0x5d, 0x89, 0xed, 0xb6, 0x6e, 0x39, 0x73, 0xa5,
120     0x64, 0x59, 0x52, 0x8b, 0x61, 0x8f, 0x66, 0x69,
121     0xb9, 0xf0, 0x45, 0x0a, 0x57, 0xcd, 0xc5, 0x7f,
122     0x5d, 0xd0, 0xbf, 0xcc, 0x0b, 0x48, 0x12, 0xe1,
123     0xe2, 0xc2, 0xea, 0xcc, 0x09, 0xd9, 0x42, 0x2c,
124     0xef, 0x4f, 0xa7, 0xe9, 0x32, 0x5c, 0x3f, 0x22,
125     0xc0, 0x45, 0x0b, 0x67, 0x3c, 0x31, 0x69, 0x29,
126     0xa3, 0x39, 0xdd, 0x6e, 0x2f, 0xbe, 0x10, 0xc9,
127     0x7b, 0xff, 0x19, 0x8a, 0xe9, 0xea, 0xfc, 0x32,
128     0x41, 0x33, 0x70, 0x2a, 0x9a, 0xa4, 0xe6, 0xb4,
129     0x7e, 0xb4, 0xc6, 0x21, 0x49, 0x5a, 0xfc, 0x45,
130     0xd2, 0x23, 0xb3, 0x28, 0x4d, 0x83, 0x60, 0xfe,
131     0x70, 0x68, 0x03, 0x59, 0xd5, 0x15, 0xaa, 0x9e,
132     0xa0, 0x2e, 0x36, 0xb5, 0x61, 0x0f, 0x61, 0x05,
133     0x3c, 0x62, 0x00, 0xa0, 0x47, 0xf1, 0x86, 0xba,
134     0x33, 0xb8, 0xca, 0x60, 0x2f, 0x3f, 0x0a, 0x67,
135     0x09, 0x27, 0x2f, 0xa2, 0x96, 0x02, 0x52, 0x58,
136     0x55, 0x68, 0x80, 0xf4, 0x4f, 0x47, 0xba, 0xff,
137     0x41, 0x7a, 0x40, 0x4c, 0xfd, 0x9d, 0x10, 0x72,
138     0x0e, 0x20, 0xa9, 0x7f, 0x9b, 0x9b, 0x14, 0xeb,
139     0x8e, 0x61, 0x25, 0xcb, 0xf4, 0x58, 0xff, 0x47,
140     0xa7, 0x08, 0xd6, 0x4e, 0x2b, 0xf1, 0xf9, 0x89,
141     0xd7, 0x22, 0x0f, 0x8d, 0x35, 0x07, 0xa0, 0x54,
142     0xab, 0x83, 0xd8, 0xee, 0x5a, 0x3e, 0x88, 0x74,
143     0x46, 0x41, 0x6e, 0x3e, 0xb7, 0xc0, 0xb6, 0x55,
144     0xe0, 0x36, 0xc0, 0x2b, 0xbf, 0xb8, 0x24, 0x8a,
145     0x44, 0x82, 0xf4, 0xcb, 0xb5, 0xd7, 0x41, 0x48,
146     0x51, 0x08, 0xe0, 0x14, 0x34, 0xd2, 0x6d, 0xe9,
147     0x7a, 0xec, 0x91, 0x61, 0xa7, 0xe1, 0x81, 0x69,
148     0x47, 0x1c, 0xc7, 0xf3
149 };
150 
151 static const unsigned char shake256_largemsg_output[] = {
152     0x64, 0xea, 0x24, 0x6a, 0xab, 0x80, 0x37, 0x9e,
153     0x08, 0xe2, 0x19, 0x9e, 0x09, 0x69, 0xe2, 0xee,
154     0x1a, 0x5d, 0xd1, 0x68, 0x68, 0xec, 0x8d, 0x42,
155     0xd0, 0xf8, 0xb8, 0x44, 0x74, 0x54, 0x87, 0x3e,
156 };
157 
shake_setup(const char * name)158 static EVP_MD_CTX *shake_setup(const char *name)
159 {
160     EVP_MD_CTX *ctx = NULL;
161     EVP_MD *md = NULL;
162 
163     if (!TEST_ptr(md = EVP_MD_fetch(NULL, name, NULL)))
164         return NULL;
165 
166     if (!TEST_ptr(ctx = EVP_MD_CTX_new()))
167         goto err;
168     if (!TEST_true(EVP_DigestInit_ex2(ctx, md, NULL)))
169         goto err;
170     EVP_MD_free(md);
171     return ctx;
172 err:
173     EVP_MD_free(md);
174     EVP_MD_CTX_free(ctx);
175     return NULL;
176 }
177 
shake_kat_test(void)178 static int shake_kat_test(void)
179 {
180     int ret = 0;
181     EVP_MD_CTX *ctx = NULL;
182     unsigned char out[sizeof(shake256_output)];
183 
184     if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
185         return 0;
186     if (!TEST_true(EVP_DigestUpdate(ctx, shake256_input,
187                                     sizeof(shake256_input)))
188         || !TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out)))
189         || !TEST_mem_eq(out, sizeof(out),
190                         shake256_output,sizeof(shake256_output))
191         /* Test that a second call to EVP_DigestFinalXOF fails */
192         || !TEST_false(EVP_DigestFinalXOF(ctx, out, sizeof(out)))
193         /* Test that a call to EVP_DigestSqueeze fails */
194         || !TEST_false(EVP_DigestSqueeze(ctx, out, sizeof(out))))
195         goto err;
196     ret = 1;
197 err:
198     EVP_MD_CTX_free(ctx);
199     return ret;
200 }
201 
shake_kat_digestfinal_test(void)202 static int shake_kat_digestfinal_test(void)
203 {
204     int ret = 0;
205     unsigned int digest_length = 0;
206     EVP_MD_CTX *ctx = NULL;
207     unsigned char out[sizeof(shake256_output)];
208 
209     /* Test that EVP_DigestFinal without setting XOFLEN fails */
210     if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
211         return 0;
212     if (!TEST_true(EVP_DigestUpdate(ctx, shake256_input,
213                    sizeof(shake256_input))))
214         return 0;
215     ERR_set_mark();
216     if (!TEST_false(EVP_DigestFinal(ctx, out, &digest_length))) {
217         ERR_clear_last_mark();
218         return 0;
219     }
220     ERR_pop_to_mark();
221     EVP_MD_CTX_free(ctx);
222 
223     /* However EVP_DigestFinalXOF must work */
224     if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
225         return 0;
226     if (!TEST_true(EVP_DigestUpdate(ctx, shake256_input,
227                    sizeof(shake256_input))))
228         return 0;
229     if (!TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out)))
230         || !TEST_mem_eq(out, sizeof(out),
231                         shake256_output, sizeof(shake256_output))
232         || !TEST_false(EVP_DigestFinalXOF(ctx, out, sizeof(out))))
233         goto err;
234     ret = 1;
235 err:
236     EVP_MD_CTX_free(ctx);
237     return ret;
238 }
239 
240 /*
241  * Test that EVP_DigestFinal() returns the output length
242  * set by the OSSL_DIGEST_PARAM_XOFLEN param.
243  */
shake_kat_digestfinal_xoflen_test(void)244 static int shake_kat_digestfinal_xoflen_test(void)
245 {
246     int ret = 0;
247     unsigned int digest_length = 0;
248     EVP_MD_CTX *ctx = NULL;
249     const EVP_MD *md;
250     unsigned char out[sizeof(shake256_output)];
251     OSSL_PARAM params[2];
252     size_t sz = 12;
253 
254     if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
255         return 0;
256     md = EVP_MD_CTX_get0_md(ctx);
257 
258     memset(out, 0, sizeof(out));
259     params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &sz);
260     params[1] = OSSL_PARAM_construct_end();
261 
262     if (!TEST_int_eq(EVP_MD_CTX_size(ctx), -1)
263         || !TEST_int_eq(EVP_MD_CTX_set_params(ctx, params), 1)
264         || !TEST_int_eq(EVP_MD_CTX_size(ctx), sz)
265         || !TEST_int_eq(EVP_MD_get_size(md), 0)
266         || !TEST_true(EVP_MD_xof(md))
267         || !TEST_true(EVP_DigestUpdate(ctx, shake256_input,
268                                        sizeof(shake256_input)))
269         || !TEST_true(EVP_DigestFinal(ctx, out, &digest_length))
270         || !TEST_uint_eq(digest_length, (unsigned int)sz)
271         || !TEST_mem_eq(out, digest_length,
272                         shake256_output, digest_length)
273         || !TEST_uchar_eq(out[digest_length], 0))
274         goto err;
275     ret = 1;
276 err:
277     EVP_MD_CTX_free(ctx);
278     return ret;
279 }
280 
281 /*
282  * Test that multiple absorb calls gives the expected result.
283  * This is a nested test that uses multiple strides for the input.
284  */
shake_absorb_test(void)285 static int shake_absorb_test(void)
286 {
287     int ret = 0;
288     EVP_MD_CTX *ctx = NULL;
289     unsigned char out[sizeof(shake256_largemsg_output)];
290     size_t total = sizeof(shake256_largemsg_input);
291     size_t i, stride, sz;
292 
293     if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
294         return 0;
295 
296     for (stride = 1; stride < total; ++stride) {
297         sz = 0;
298         for (i = 0; i < total; i += sz) {
299             sz += stride;
300             if ((i + sz) > total)
301                 sz = total - i;
302             if (!TEST_true(EVP_DigestUpdate(ctx, shake256_largemsg_input + i,
303                                             sz)))
304                 goto err;
305         }
306         if (!TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out)))
307             || !TEST_mem_eq(out, sizeof(out),
308                             shake256_largemsg_output,
309                             sizeof(shake256_largemsg_output)))
310             goto err;
311         if (!TEST_true(EVP_DigestInit_ex2(ctx, NULL, NULL)))
312             goto err;
313     }
314     ret = 1;
315 err:
316     EVP_MD_CTX_free(ctx);
317     return ret;
318 }
319 
320 /*
321  * Table containing the size of the output to squeeze for the
322  * initially call, followed by a size for each subsequent call.
323  */
324 static const struct {
325     size_t startsz, incsz;
326 } stride_tests[] = {
327     { 1, 1 },
328     { 1, 136 },
329     { 1, 136/2 },
330     { 1, 136/2-1 },
331     { 1, 136/2+1 },
332     { 1, 136*3 },
333     { 8, 8 },
334     { 9, 9 },
335     { 10, 10 },
336     { 136/2 - 1, 136 },
337     { 136/2 - 1, 136-1 },
338     { 136/2 - 1, 136+1 },
339     { 136/2, 136 },
340     { 136/2, 136-1 },
341     { 136/2, 136+1 },
342     { 136/2 + 1, 136 },
343     { 136/2 + 1, 136-1 },
344     { 136/2 + 1, 136+1 },
345     { 136, 2 },
346     { 136, 136 },
347     { 136-1, 136 },
348     { 136-1, 136-1 },
349     { 136-1, 136+1 },
350     { 136+1, 136 },
351     { 136+1, 136-1 },
352     { 136+1, 136+1 },
353     { 136*3, 136 },
354     { 136*3, 136 + 1 },
355     { 136*3, 136 - 1 },
356     { 136*3, 136/2 },
357     { 136*3, 136/2 + 1 },
358     { 136*3, 136/2 - 1 },
359 };
360 
361 /*
362  * Helper to do multiple squeezes of output data using SHAKE256.
363  * tst is an index into the stride_tests[] containing an initial starting
364  * output length, followed by a second output length to use for all remaining
365  * squeezes. expected_outlen contains the total number of bytes to squeeze.
366  * in and inlen represent the input to absorb. expected_out and expected_outlen
367  * represent the expected output.
368  */
do_shake_squeeze_test(int tst,const unsigned char * in,size_t inlen,const unsigned char * expected_out,size_t expected_outlen)369 static int do_shake_squeeze_test(int tst,
370                                  const unsigned char *in, size_t inlen,
371                                  const unsigned char *expected_out,
372                                  size_t expected_outlen)
373 {
374     int ret = 0;
375     EVP_MD_CTX *ctx = NULL;
376     unsigned char *out = NULL;
377     size_t i = 0, sz = stride_tests[tst].startsz;
378 
379     if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
380         return 0;
381     if (!TEST_ptr(out = OPENSSL_malloc(expected_outlen)))
382         goto err;
383     if (!TEST_true(EVP_DigestUpdate(ctx, in, inlen)))
384         goto err;
385 
386     while (i < expected_outlen) {
387         if ((i + sz) > expected_outlen)
388             sz = expected_outlen - i;
389         if (!TEST_true(EVP_DigestSqueeze(ctx, out + i, sz)))
390             goto err;
391         i += sz;
392         sz = stride_tests[tst].incsz;
393     }
394     if (!TEST_mem_eq(out, expected_outlen, expected_out, expected_outlen))
395         goto err;
396     ret = 1;
397 err:
398     OPENSSL_free(out);
399     EVP_MD_CTX_free(ctx);
400     return ret;
401 }
402 
shake_squeeze_kat_test(int tst)403 static int shake_squeeze_kat_test(int tst)
404 {
405     return do_shake_squeeze_test(tst, shake256_input, sizeof(shake256_input),
406                                  shake256_output, sizeof(shake256_output));
407 }
408 
409 /*
410  * Generate some random input to absorb, and then
411  * squeeze it out in one operation to get a expected
412  * output. Use this to test that multiple squeeze calls
413  * on the same input gives the same output.
414  */
shake_squeeze_large_test(int tst)415 static int shake_squeeze_large_test(int tst)
416 {
417     int ret = 0;
418     EVP_MD_CTX *ctx = NULL;
419     unsigned char msg[16];
420     unsigned char out[2000];
421 
422     if (!TEST_int_gt(RAND_bytes(msg, sizeof(msg)), 0)
423         || !TEST_ptr(ctx = shake_setup("SHAKE256"))
424         || !TEST_true(EVP_DigestUpdate(ctx, msg, sizeof(msg)))
425         || !TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out))))
426         goto err;
427 
428     ret = do_shake_squeeze_test(tst, msg, sizeof(msg), out, sizeof(out));
429 err:
430     EVP_MD_CTX_free(ctx);
431     return ret;
432 }
433 
434 static const size_t dupoffset_tests[] = {
435     1, 135, 136, 137, 136*3-1, 136*3, 136*3+1
436 };
437 
438 /* Helper function to test that EVP_MD_CTX_dup() copies the internal state */
do_shake_squeeze_dup_test(int tst,const char * alg,const unsigned char * in,size_t inlen,const unsigned char * expected_out,size_t expected_outlen)439 static int do_shake_squeeze_dup_test(int tst, const char *alg,
440                                      const unsigned char *in, size_t inlen,
441                                      const unsigned char *expected_out,
442                                      size_t expected_outlen)
443 {
444     int ret = 0;
445     EVP_MD_CTX *cur, *ctx = NULL, *dupctx = NULL;
446     unsigned char *out = NULL;
447     size_t i = 0, sz = 10;
448     size_t dupoffset = dupoffset_tests[tst];
449 
450     if (!TEST_ptr(ctx = shake_setup(alg)))
451         return 0;
452     cur = ctx;
453     if (!TEST_ptr(out = OPENSSL_malloc(expected_outlen)))
454         goto err;
455     if (!TEST_true(EVP_DigestUpdate(ctx, in, inlen)))
456         goto err;
457 
458     while (i < expected_outlen) {
459         if ((i + sz) > expected_outlen)
460             sz = expected_outlen - i;
461         if (!TEST_true(EVP_DigestSqueeze(cur, out + i, sz)))
462             goto err;
463         i += sz;
464         /* At a certain offset we swap to a new ctx that copies the state */
465         if (dupctx == NULL && i >= dupoffset) {
466             if (!TEST_ptr(dupctx = EVP_MD_CTX_dup(ctx)))
467                 goto err;
468             cur = dupctx;
469         }
470     }
471     if (!TEST_mem_eq(out, expected_outlen, expected_out, expected_outlen))
472         goto err;
473     ret = 1;
474 err:
475     OPENSSL_free(out);
476     EVP_MD_CTX_free(ctx);
477     EVP_MD_CTX_free(dupctx);
478     return ret;
479 }
480 
481 /* Test that the internal state can be copied */
shake_squeeze_dup_test(int tst)482 static int shake_squeeze_dup_test(int tst)
483 {
484     int ret = 0;
485     EVP_MD_CTX *ctx = NULL;
486     unsigned char msg[16];
487     unsigned char out[1000];
488     const char *alg = "SHAKE128";
489 
490     if (!TEST_int_gt(RAND_bytes(msg, sizeof(msg)), 0)
491         || !TEST_ptr(ctx = shake_setup(alg))
492         || !TEST_true(EVP_DigestUpdate(ctx, msg, sizeof(msg)))
493         || !TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out))))
494         goto err;
495 
496     ret = do_shake_squeeze_dup_test(tst, alg, msg, sizeof(msg),
497                                     out, sizeof(out));
498 err:
499     EVP_MD_CTX_free(ctx);
500     return ret;
501 }
502 
503 /* Test that a squeeze without a preceding absorb works */
shake_squeeze_no_absorb_test(void)504 static int shake_squeeze_no_absorb_test(void)
505 {
506     int ret = 0;
507     EVP_MD_CTX *ctx = NULL;
508     unsigned char out[1000];
509     unsigned char out2[1000];
510     const char *alg = "SHAKE128";
511 
512     if (!TEST_ptr(ctx = shake_setup(alg))
513         || !TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out))))
514         goto err;
515 
516     if (!TEST_true(EVP_DigestInit_ex2(ctx, NULL, NULL))
517         || !TEST_true(EVP_DigestSqueeze(ctx, out2, sizeof(out2) / 2))
518         || !TEST_true(EVP_DigestSqueeze(ctx, out2 + sizeof(out2) / 2,
519                                         sizeof(out2) / 2)))
520         goto err;
521 
522     if (!TEST_mem_eq(out2, sizeof(out2), out, sizeof(out)))
523         goto err;
524     ret = 1;
525 
526 err:
527     EVP_MD_CTX_free(ctx);
528     return ret;
529 }
530 
xof_fail_test(void)531 static int xof_fail_test(void)
532 {
533     int ret;
534     EVP_MD *md = NULL;
535 
536     ret = TEST_ptr(md = EVP_MD_fetch(NULL, "SHA256", NULL))
537             && TEST_false(EVP_MD_xof(md));
538     EVP_MD_free(md);
539     return ret;
540 }
541 
setup_tests(void)542 int setup_tests(void)
543 {
544     ADD_TEST(shake_kat_test);
545     ADD_TEST(shake_kat_digestfinal_test);
546     ADD_TEST(shake_kat_digestfinal_xoflen_test);
547     ADD_TEST(shake_absorb_test);
548     ADD_ALL_TESTS(shake_squeeze_kat_test, OSSL_NELEM(stride_tests));
549     ADD_ALL_TESTS(shake_squeeze_large_test, OSSL_NELEM(stride_tests));
550     ADD_ALL_TESTS(shake_squeeze_dup_test, OSSL_NELEM(dupoffset_tests));
551     ADD_TEST(xof_fail_test);
552     ADD_TEST(shake_squeeze_no_absorb_test);
553     return 1;
554 }
555