/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 | } |