Coverage Report

Created: 2026-02-22 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/sha/sha3_encode.c
Line
Count
Source
1
/*
2
 * Copyright 2025 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
0
{
27
0
    unsigned int cnt = 0, sz = sizeof(size_t);
28
29
0
    while (bits && (cnt < sz)) {
30
0
        ++cnt;
31
0
        bits >>= 8;
32
0
    }
33
    /* If bits is zero 1 byte is required */
34
0
    if (cnt == 0)
35
0
        cnt = 1;
36
0
    return cnt;
37
0
}
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
0
{
50
0
    unsigned int len = get_encode_size(bits);
51
0
    int i;
52
53
0
    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
0
    for (i = len - 1; i >= 0; --i) {
60
0
        out[i] = (unsigned char)(bits & 0xFF);
61
0
        bits >>= 8;
62
0
    }
63
    /* Tack the length onto the end */
64
0
    out[len] = (unsigned char)len;
65
66
    /* The Returned length includes the tacked on byte */
67
0
    *out_len = len + 1;
68
0
    return 1;
69
0
}
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
0
{
82
0
    if (in == NULL) {
83
0
        *out_len = 0;
84
0
    } else {
85
0
        size_t i, bits, len, sz;
86
87
0
        bits = 8 * in_len;
88
0
        len = get_encode_size(bits);
89
0
        sz = 1 + len + in_len;
90
91
0
        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
0
        out[0] = (unsigned char)len;
97
0
        for (i = len; i > 0; --i) {
98
0
            out[i] = (bits & 0xFF);
99
0
            bits >>= 8;
100
0
        }
101
0
        memcpy(out + len + 1, in, in_len);
102
0
        *out_len = sz;
103
0
    }
104
0
    return 1;
105
0
}
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
0
{
120
0
    size_t len;
121
0
    unsigned char *p = out;
122
0
    size_t sz;
123
124
0
    if (!ossl_assert(w <= 255))
125
0
        return 0;
126
0
    sz = (2 + in1_len + (in2 != NULL ? in2_len : 0) + w - 1) / w * w;
127
0
    if (out_len_max != 0 && sz > out_len_max)
128
0
        return 0;
129
130
0
    if (out == NULL) {
131
0
        if (out_len == NULL) {
132
0
            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
133
0
            return 0;
134
0
        }
135
0
        *out_len = sz;
136
0
        return 1;
137
0
    }
138
139
    /* Left encoded w */
140
0
    *p++ = 1;
141
0
    *p++ = (unsigned char)w;
142
    /* || in1 */
143
0
    memcpy(p, in1, in1_len);
144
0
    p += in1_len;
145
    /* [ || in2 ] */
146
0
    if (in2 != NULL && in2_len > 0) {
147
0
        memcpy(p, in2, in2_len);
148
0
        p += in2_len;
149
0
    }
150
    /* Figure out the pad size (divisible by w) */
151
0
    len = p - out;
152
    /* zero pad the end of the buffer */
153
0
    if (sz != len)
154
0
        memset(p, 0, sz - len);
155
0
    if (out_len != NULL)
156
0
        *out_len = sz;
157
0
    return 1;
158
0
}