Coverage Report

Created: 2025-08-28 07:07

/src/openssl33/crypto/sha/sha3.c
Line
Count
Source (jump to first uncovered line)
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
10
#include <string.h>
11
#include "internal/sha3.h"
12
13
void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r, int next);
14
15
void ossl_sha3_reset(KECCAK1600_CTX *ctx)
16
262M
{
17
262M
    memset(ctx->A, 0, sizeof(ctx->A));
18
262M
    ctx->bufsz = 0;
19
262M
    ctx->xof_state = XOF_STATE_INIT;
20
262M
}
21
22
int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
23
302k
{
24
302k
    size_t bsz = SHA3_BLOCKSIZE(bitlen);
25
26
302k
    if (bsz <= sizeof(ctx->buf)) {
27
302k
        ossl_sha3_reset(ctx);
28
302k
        ctx->block_size = bsz;
29
302k
        ctx->md_size = bitlen / 8;
30
302k
        ctx->pad = pad;
31
302k
        return 1;
32
302k
    }
33
34
0
    return 0;
35
302k
}
36
37
int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
38
0
{
39
0
    int ret = ossl_sha3_init(ctx, pad, bitlen);
40
41
0
    if (ret)
42
0
        ctx->md_size *= 2;
43
0
    return ret;
44
0
}
45
46
int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
47
0
{
48
0
    const unsigned char *inp = _inp;
49
0
    size_t bsz = ctx->block_size;
50
0
    size_t num, rem;
51
52
0
    if (len == 0)
53
0
        return 1;
54
55
0
    if (ctx->xof_state == XOF_STATE_SQUEEZE
56
0
        || ctx->xof_state == XOF_STATE_FINAL)
57
0
        return 0;
58
59
0
    if ((num = ctx->bufsz) != 0) {      /* process intermediate buffer? */
60
0
        rem = bsz - num;
61
62
0
        if (len < rem) {
63
0
            memcpy(ctx->buf + num, inp, len);
64
0
            ctx->bufsz += len;
65
0
            return 1;
66
0
        }
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
0
        memcpy(ctx->buf + num, inp, rem);
73
0
        inp += rem, len -= rem;
74
0
        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
75
0
        ctx->bufsz = 0;
76
        /* ctx->buf is processed, ctx->num is guaranteed to be zero */
77
0
    }
78
79
0
    if (len >= bsz)
80
0
        rem = SHA3_absorb(ctx->A, inp, len, bsz);
81
0
    else
82
0
        rem = len;
83
84
0
    if (rem) {
85
0
        memcpy(ctx->buf, inp + len - rem, rem);
86
0
        ctx->bufsz = rem;
87
0
    }
88
89
0
    return 1;
90
0
}
91
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)
98
261M
{
99
261M
    size_t bsz = ctx->block_size;
100
261M
    size_t num = ctx->bufsz;
101
102
261M
    if (outlen == 0)
103
0
        return 1;
104
261M
    if (ctx->xof_state == XOF_STATE_SQUEEZE
105
261M
        || ctx->xof_state == XOF_STATE_FINAL)
106
0
        return 0;
107
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
261M
    memset(ctx->buf + num, 0, bsz - num);
114
261M
    ctx->buf[num] = ctx->pad;
115
261M
    ctx->buf[bsz - 1] |= 0x80;
116
117
261M
    (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
118
119
261M
    ctx->xof_state = XOF_STATE_FINAL;
120
261M
    SHA3_squeeze(ctx->A, out, outlen, bsz, 0);
121
261M
    return 1;
122
261M
}
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
1.19M
{
136
1.19M
    size_t bsz = ctx->block_size;
137
1.19M
    size_t num = ctx->bufsz;
138
1.19M
    size_t len;
139
1.19M
    int next = 1;
140
141
1.19M
    if (outlen == 0)
142
0
        return 1;
143
144
1.19M
    if (ctx->xof_state == XOF_STATE_FINAL)
145
0
        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
1.19M
    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
376k
        memset(ctx->buf + num, 0, bsz - num);
159
376k
        ctx->buf[num] = ctx->pad;
160
376k
        ctx->buf[bsz - 1] |= 0x80;
161
376k
        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
162
376k
        ctx->xof_state = XOF_STATE_SQUEEZE;
163
376k
        num = ctx->bufsz = 0;
164
376k
        next = 0;
165
376k
    }
166
167
    /*
168
     * Step 1. Consume any bytes left over from a previous squeeze
169
     * (See Step 4 below).
170
     */
171
1.19M
    if (num != 0) {
172
0
        if (outlen > ctx->bufsz)
173
0
            len = ctx->bufsz;
174
0
        else
175
0
            len = outlen;
176
0
        memcpy(out, ctx->buf + bsz - ctx->bufsz, len);
177
0
        out += len;
178
0
        outlen -= len;
179
0
        ctx->bufsz -= len;
180
0
    }
181
1.19M
    if (outlen == 0)
182
0
        return 1;
183
184
    /* Step 2. Copy full sized squeezed blocks to the output buffer directly */
185
1.19M
    if (outlen >= bsz) {
186
1.18M
        len = bsz * (outlen / bsz);
187
1.18M
        SHA3_squeeze(ctx->A, out, len, bsz, next);
188
1.18M
        next = 1;
189
1.18M
        out += len;
190
1.18M
        outlen -= len;
191
1.18M
    }
192
1.19M
    if (outlen > 0) {
193
        /* Step 3. Squeeze one more block into a buffer */
194
14.2k
        SHA3_squeeze(ctx->A, ctx->buf, bsz, bsz, next);
195
14.2k
        memcpy(out, ctx->buf, outlen);
196
        /* Step 4. Remember the leftover part of the squeezed block */
197
14.2k
        ctx->bufsz = bsz - outlen;
198
14.2k
    }
199
200
1.19M
    return 1;
201
1.19M
}