Coverage Report

Created: 2024-05-21 06:33

/src/openssl/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
171
{
17
171
    memset(ctx->A, 0, sizeof(ctx->A));
18
171
    ctx->bufsz = 0;
19
171
    ctx->xof_state = XOF_STATE_INIT;
20
171
}
21
22
int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
23
57
{
24
57
    size_t bsz = SHA3_BLOCKSIZE(bitlen);
25
26
57
    if (bsz <= sizeof(ctx->buf)) {
27
57
        ossl_sha3_reset(ctx);
28
57
        ctx->block_size = bsz;
29
57
        ctx->md_size = bitlen / 8;
30
57
        ctx->pad = pad;
31
57
        return 1;
32
57
    }
33
34
0
    return 0;
35
57
}
36
37
int ossl_keccak_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen, size_t mdlen)
38
0
{
39
0
    int ret = ossl_sha3_init(ctx, pad, bitlen);
40
41
0
    if (ret)
42
0
        ctx->md_size = mdlen / 8;
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
57
{
99
57
    size_t bsz = ctx->block_size;
100
57
    size_t num = ctx->bufsz;
101
102
57
    if (outlen == 0)
103
0
        return 1;
104
57
    if (ctx->xof_state == XOF_STATE_SQUEEZE
105
57
        || 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
57
    memset(ctx->buf + num, 0, bsz - num);
114
57
    ctx->buf[num] = ctx->pad;
115
57
    ctx->buf[bsz - 1] |= 0x80;
116
117
57
    (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
118
119
57
    ctx->xof_state = XOF_STATE_FINAL;
120
57
    SHA3_squeeze(ctx->A, out, outlen, bsz, 0);
121
57
    return 1;
122
57
}
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
0
{
136
0
    size_t bsz = ctx->block_size;
137
0
    size_t num = ctx->bufsz;
138
0
    size_t len;
139
0
    int next = 1;
140
141
0
    if (outlen == 0)
142
0
        return 1;
143
144
0
    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
0
    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
0
        memset(ctx->buf + num, 0, bsz - num);
159
0
        ctx->buf[num] = ctx->pad;
160
0
        ctx->buf[bsz - 1] |= 0x80;
161
0
        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
162
0
        ctx->xof_state = XOF_STATE_SQUEEZE;
163
0
        num = ctx->bufsz = 0;
164
0
        next = 0;
165
0
    }
166
167
    /*
168
     * Step 1. Consume any bytes left over from a previous squeeze
169
     * (See Step 4 below).
170
     */
171
0
    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
0
    if (outlen == 0)
182
0
        return 1;
183
184
    /* Step 2. Copy full sized squeezed blocks to the output buffer directly */
185
0
    if (outlen >= bsz) {
186
0
        len = bsz * (outlen / bsz);
187
0
        SHA3_squeeze(ctx->A, out, len, bsz, next);
188
0
        next = 1;
189
0
        out += len;
190
0
        outlen -= len;
191
0
    }
192
0
    if (outlen > 0) {
193
        /* Step 3. Squeeze one more block into a buffer */
194
0
        SHA3_squeeze(ctx->A, ctx->buf, bsz, bsz, next);
195
0
        memcpy(out, ctx->buf, outlen);
196
        /* Step 4. Remember the leftover part of the squeezed block */
197
0
        ctx->bufsz = bsz - outlen;
198
0
    }
199
200
0
    return 1;
201
0
}