Coverage Report

Created: 2026-10-28 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/crypto/sha/sha3_encode.c
Line
Count
Source
1
/*
2
 * Copyright 2025-2026 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
/* including crypto/sha.h requires this for SHA256_CTX */
11
#include "internal/deprecated.h"
12
13
/*
14
 * NIST.SP.800-185 Encoding/Padding Methods used for SHA3 derived functions
15
 * e.g. It is used by KMAC and cSHAKE
16
 */
17
18
#include <string.h> /* memcpy */
19
#include <openssl/err.h>
20
#include <openssl/proverr.h>
21
#include "crypto/sha.h"
22
#include "internal/common.h" /* ossl_assert */
23
24
/* Returns the number of bytes required to store 'bits' into a byte array */
25
static unsigned int get_encode_size(size_t bits)
26
898
{
27
898
    unsigned int cnt = 0, sz = sizeof(size_t);
28
29
1.86k
    while (bits && (cnt < sz)) {
30
967
        ++cnt;
31
967
        bits >>= 8;
32
967
    }
33
    /* If bits is zero 1 byte is required */
34
898
    if (cnt == 0)
35
245
        cnt = 1;
36
898
    return cnt;
37
898
}
38
39
/*
40
 * Convert an integer into bytes. The number of bytes is appended
41
 * to the end of the buffer.
42
 * Returns an array of bytes 'out' of size *out_len.
43
 *
44
 * e.g if bits = 32, out[2] = { 0x20, 0x01 }
45
 */
46
int ossl_sp800_185_right_encode(unsigned char *out,
47
    size_t out_max_len, size_t *out_len,
48
    size_t bits)
49
153
{
50
153
    unsigned int len = get_encode_size(bits);
51
153
    int i;
52
53
153
    if (len >= out_max_len) {
54
0
        ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
55
0
        return 0;
56
0
    }
57
58
    /* MSB's are at the start of the bytes array */
59
356
    for (i = len - 1; i >= 0; --i) {
60
203
        out[i] = (unsigned char)(bits & 0xFF);
61
203
        bits >>= 8;
62
203
    }
63
    /* Tack the length onto the end */
64
153
    out[len] = (unsigned char)len;
65
66
    /* The Returned length includes the tacked on byte */
67
153
    *out_len = len + 1;
68
153
    return 1;
69
153
}
70
71
/*
72
 * Encodes a string with a left encoded length added. Note that the
73
 * in_len is converted to bits (* 8).
74
 *
75
 * e.g- in="KMAC" gives out[6] = { 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 }
76
 *                                 len   bits    K     M     A     C
77
 */
78
int ossl_sp800_185_encode_string(unsigned char *out,
79
    size_t out_max_len, size_t *out_len,
80
    const unsigned char *in, size_t in_len)
81
745
{
82
745
    if (in == NULL) {
83
0
        *out_len = 0;
84
745
    } else {
85
745
        size_t i, bits, len, sz;
86
87
745
        bits = 8 * in_len;
88
745
        len = get_encode_size(bits);
89
745
        sz = 1 + len + in_len;
90
91
745
        if (sz > out_max_len) {
92
0
            ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
93
0
            return 0;
94
0
        }
95
96
745
        out[0] = (unsigned char)len;
97
1.75k
        for (i = len; i > 0; --i) {
98
1.00k
            out[i] = (bits & 0xFF);
99
1.00k
            bits >>= 8;
100
1.00k
        }
101
745
        memcpy(out + len + 1, in, in_len);
102
745
        *out_len = sz;
103
745
    }
104
745
    return 1;
105
745
}
106
107
/*
108
 * Returns a zero padded encoding of the inputs in1 and an optional
109
 * in2 (can be NULL). The padded output must be a multiple of the blocksize 'w'.
110
 * The value of w is in bytes (< 256).
111
 *
112
 * The returned output is:
113
 *    zero_padded(multiple of w, (left_encode(w) || in1 [|| in2])
114
 */
115
int ossl_sp800_185_bytepad(unsigned char *out, size_t out_len_max, size_t *out_len,
116
    const unsigned char *in1, size_t in1_len,
117
    const unsigned char *in2, size_t in2_len,
118
    size_t w)
119
1.21k
{
120
1.21k
    size_t len;
121
1.21k
    unsigned char *p = out;
122
1.21k
    size_t sz;
123
124
1.21k
    if (!ossl_assert(w <= 255))
125
0
        return 0;
126
1.21k
    sz = (2 + in1_len + (in2 != NULL ? in2_len : 0) + w - 1) / w * w;
127
1.21k
    if (out_len_max != 0 && sz > out_len_max)
128
0
        return 0;
129
130
1.21k
    if (out == NULL) {
131
605
        if (out_len == NULL) {
132
0
            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
133
0
            return 0;
134
0
        }
135
605
        *out_len = sz;
136
605
        return 1;
137
605
    }
138
139
    /* Left encoded w */
140
605
    *p++ = 1;
141
605
    *p++ = (unsigned char)w;
142
    /* || in1 */
143
605
    memcpy(p, in1, in1_len);
144
605
    p += in1_len;
145
    /* [ || in2 ] */
146
605
    if (in2 != NULL && in2_len > 0) {
147
161
        memcpy(p, in2, in2_len);
148
161
        p += in2_len;
149
161
    }
150
    /* Figure out the pad size (divisible by w) */
151
605
    len = p - out;
152
    /* zero pad the end of the buffer */
153
605
    if (sz != len)
154
579
        memset(p, 0, sz - len);
155
605
    if (out_len != NULL)
156
0
        *out_len = sz;
157
605
    return 1;
158
1.21k
}