blob: 69a24a2d0878928773eb1079c35e4fb91af67d6e [file] [log] [blame]
Damjan Mariona447c662024-04-09 12:37:25 +00001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright(c) 2024 Cisco Systems, Inc.
Damjan Marion04bd0ea2023-03-16 16:37:56 +00003 */
4
5#ifndef included_sha2_h
6#define included_sha2_h
7
8#include <vppinfra/clib.h>
Damjan Marion7ad751b2024-03-03 22:12:21 +00009#include <vppinfra/vector.h>
Damjan Mariona447c662024-04-09 12:37:25 +000010#include <vppinfra/string.h>
Damjan Marion04bd0ea2023-03-16 16:37:56 +000011
Damjan Marion04bd0ea2023-03-16 16:37:56 +000012#define SHA256_ROTR(x, y) ((x >> y) | (x << (32 - y)))
13#define SHA256_CH(a, b, c) ((a & b) ^ (~a & c))
14#define SHA256_MAJ(a, b, c) ((a & b) ^ (a & c) ^ (b & c))
15#define SHA256_CSIGMA0(x) \
16 (SHA256_ROTR (x, 2) ^ SHA256_ROTR (x, 13) ^ SHA256_ROTR (x, 22));
17#define SHA256_CSIGMA1(x) \
18 (SHA256_ROTR (x, 6) ^ SHA256_ROTR (x, 11) ^ SHA256_ROTR (x, 25));
19#define SHA256_SSIGMA0(x) (SHA256_ROTR (x, 7) ^ SHA256_ROTR (x, 18) ^ (x >> 3))
20#define SHA256_SSIGMA1(x) \
21 (SHA256_ROTR (x, 17) ^ SHA256_ROTR (x, 19) ^ (x >> 10))
22
23#define SHA256_MSG_SCHED(w, j) \
24 { \
25 w[j] = w[j - 7] + w[j - 16]; \
26 w[j] += SHA256_SSIGMA0 (w[j - 15]); \
27 w[j] += SHA256_SSIGMA1 (w[j - 2]); \
28 }
29
30#define SHA256_TRANSFORM(s, w, i, k) \
31 { \
32 __typeof__ (s[0]) t1, t2; \
33 t1 = k + w[i] + s[7]; \
34 t1 += SHA256_CSIGMA1 (s[4]); \
35 t1 += SHA256_CH (s[4], s[5], s[6]); \
36 t2 = SHA256_CSIGMA0 (s[0]); \
37 t2 += SHA256_MAJ (s[0], s[1], s[2]); \
38 s[7] = s[6]; \
39 s[6] = s[5]; \
40 s[5] = s[4]; \
41 s[4] = s[3] + t1; \
42 s[3] = s[2]; \
43 s[2] = s[1]; \
44 s[1] = s[0]; \
45 s[0] = t1 + t2; \
46 }
47
Damjan Marion04bd0ea2023-03-16 16:37:56 +000048#define SHA512_ROTR(x, y) ((x >> y) | (x << (64 - y)))
49#define SHA512_CH(a, b, c) ((a & b) ^ (~a & c))
50#define SHA512_MAJ(a, b, c) ((a & b) ^ (a & c) ^ (b & c))
51#define SHA512_CSIGMA0(x) \
52 (SHA512_ROTR (x, 28) ^ SHA512_ROTR (x, 34) ^ SHA512_ROTR (x, 39))
53#define SHA512_CSIGMA1(x) \
54 (SHA512_ROTR (x, 14) ^ SHA512_ROTR (x, 18) ^ SHA512_ROTR (x, 41))
55#define SHA512_SSIGMA0(x) (SHA512_ROTR (x, 1) ^ SHA512_ROTR (x, 8) ^ (x >> 7))
56#define SHA512_SSIGMA1(x) \
57 (SHA512_ROTR (x, 19) ^ SHA512_ROTR (x, 61) ^ (x >> 6))
58
59#define SHA512_MSG_SCHED(w, j) \
60 { \
61 w[j] = w[j - 7] + w[j - 16]; \
62 w[j] += SHA512_SSIGMA0 (w[j - 15]); \
63 w[j] += SHA512_SSIGMA1 (w[j - 2]); \
64 }
65
66#define SHA512_TRANSFORM(s, w, i, k) \
67 { \
68 __typeof__ (s[0]) t1, t2; \
69 t1 = k + w[i] + s[7]; \
70 t1 += SHA512_CSIGMA1 (s[4]); \
71 t1 += SHA512_CH (s[4], s[5], s[6]); \
72 t2 = SHA512_CSIGMA0 (s[0]); \
73 t2 += SHA512_MAJ (s[0], s[1], s[2]); \
74 s[7] = s[6]; \
75 s[6] = s[5]; \
76 s[5] = s[4]; \
77 s[4] = s[3] + t1; \
78 s[3] = s[2]; \
79 s[2] = s[1]; \
80 s[1] = s[0]; \
81 s[0] = t1 + t2; \
82 }
83
Damjan Marion7ad751b2024-03-03 22:12:21 +000084#if defined(__SHA__) && defined(__x86_64__)
85#define CLIB_SHA256_ISA_INTEL
86#define CLIB_SHA256_ISA
87#endif
88
89#ifdef __ARM_FEATURE_SHA2
90#define CLIB_SHA256_ISA_ARM
91#define CLIB_SHA256_ISA
92#endif
93
Damjan Marion04bd0ea2023-03-16 16:37:56 +000094static const u32 sha224_h[8] = { 0xc1059ed8, 0x367cd507, 0x3070dd17,
95 0xf70e5939, 0xffc00b31, 0x68581511,
96 0x64f98fa7, 0xbefa4fa4 };
97
98static const u32 sha256_h[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372,
99 0xa54ff53a, 0x510e527f, 0x9b05688c,
100 0x1f83d9ab, 0x5be0cd19 };
101
Damjan Mariona447c662024-04-09 12:37:25 +0000102static const u32 clib_sha2_256_k[64] = {
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000103 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
104 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
105 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
106 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
107 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
108 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
109 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
110 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
111 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
112 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
113 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
114};
115
116static const u64 sha384_h[8] = { 0xcbbb9d5dc1059ed8, 0x629a292a367cd507,
117 0x9159015a3070dd17, 0x152fecd8f70e5939,
118 0x67332667ffc00b31, 0x8eb44a8768581511,
119 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4 };
120
121static const u64 sha512_h[8] = { 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
122 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
123 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
124 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 };
125
126static const u64 sha512_224_h[8] = { 0x8c3d37c819544da2, 0x73e1996689dcd4d6,
127 0x1dfab7ae32ff9c82, 0x679dd514582f9fcf,
128 0x0f6d2b697bd44da8, 0x77e36f7304c48942,
129 0x3f9d85a86a1d36c8, 0x1112e6ad91d692a1 };
130
131static const u64 sha512_256_h[8] = { 0x22312194fc2bf72c, 0x9f555fa3c84c64c2,
132 0x2393b86b6f53b151, 0x963877195940eabd,
133 0x96283ee2a88effe3, 0xbe5e1e2553863992,
134 0x2b0199fc2c85b8aa, 0x0eb72ddc81c52ca2 };
135
Damjan Mariona447c662024-04-09 12:37:25 +0000136static const u64 clib_sha2_512_k[80] = {
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000137 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
138 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
139 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
140 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
141 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
142 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
143 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
144 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
145 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
146 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
147 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
148 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
149 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
150 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
151 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
152 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
153 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
154 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
155 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
156 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
157 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
158 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
159 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
160 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
161 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
162 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
163 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
164};
165
166typedef enum
167{
168 CLIB_SHA2_224,
169 CLIB_SHA2_256,
170 CLIB_SHA2_384,
171 CLIB_SHA2_512,
172 CLIB_SHA2_512_224,
173 CLIB_SHA2_512_256,
174} clib_sha2_type_t;
175
Damjan Mariona447c662024-04-09 12:37:25 +0000176#define CLIB_SHA2_256_BLOCK_SIZE 64
177#define CLIB_SHA2_512_BLOCK_SIZE 128
178#define SHA2_MAX_BLOCK_SIZE CLIB_SHA2_512_BLOCK_SIZE
179#define SHA2_MAX_DIGEST_SIZE 64
180
181static const struct
182{
183 u8 block_size;
184 u8 digest_size;
185 const u32 *h32;
186 const u64 *h64;
187} clib_sha2_variants[] = {
188 [CLIB_SHA2_224] = {
189 .block_size = CLIB_SHA2_256_BLOCK_SIZE,
190 .digest_size = 28,
191 .h32 = sha224_h,
192 },
193 [CLIB_SHA2_256] = {
194 .block_size = CLIB_SHA2_256_BLOCK_SIZE,
195 .digest_size = 32,
196 .h32 = sha256_h,
197 },
198 [CLIB_SHA2_384] = {
199 .block_size = CLIB_SHA2_512_BLOCK_SIZE,
200 .digest_size = 48,
201 .h64 = sha384_h,
202 },
203 [CLIB_SHA2_512] = {
204 .block_size = CLIB_SHA2_512_BLOCK_SIZE,
205 .digest_size = 64,
206 .h64 = sha512_h,
207 },
208 [CLIB_SHA2_512_224] = {
209 .block_size = CLIB_SHA2_512_BLOCK_SIZE,
210 .digest_size = 28,
211 .h64 = sha512_224_h,
212 },
213 [CLIB_SHA2_512_256] = {
214 .block_size = CLIB_SHA2_512_BLOCK_SIZE,
215 .digest_size = 32,
216 .h64 = sha512_256_h,
217 },
218};
219
220typedef union
221{
222 u32 h32[8];
223 u64 h64[8];
224#ifdef CLIB_SHA256_ISA
225 u32x4 h32x4[2];
226#endif
227} clib_sha2_h_t;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000228
229typedef struct
230{
231 u64 total_bytes;
232 u16 n_pending;
Damjan Mariona447c662024-04-09 12:37:25 +0000233 clib_sha2_h_t h;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000234 union
235 {
236 u8 as_u8[SHA2_MAX_BLOCK_SIZE];
237 u64 as_u64[SHA2_MAX_BLOCK_SIZE / sizeof (u64)];
238 uword as_uword[SHA2_MAX_BLOCK_SIZE / sizeof (uword)];
239 } pending;
Damjan Mariona447c662024-04-09 12:37:25 +0000240} clib_sha2_state_t;
241
242typedef struct
243{
244 clib_sha2_type_t type;
245 u8 block_size;
246 u8 digest_size;
247 clib_sha2_state_t state;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000248} clib_sha2_ctx_t;
249
250static_always_inline void
Damjan Mariona447c662024-04-09 12:37:25 +0000251clib_sha2_state_init (clib_sha2_state_t *state, clib_sha2_type_t type)
252{
253 clib_sha2_state_t st = {};
254
255 if (clib_sha2_variants[type].block_size == CLIB_SHA2_256_BLOCK_SIZE)
256 for (int i = 0; i < 8; i++)
257 st.h.h32[i] = clib_sha2_variants[type].h32[i];
258 else
259 for (int i = 0; i < 8; i++)
260 st.h.h64[i] = clib_sha2_variants[type].h64[i];
261
262 *state = st;
263}
264
265static_always_inline void
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000266clib_sha2_init (clib_sha2_ctx_t *ctx, clib_sha2_type_t type)
267{
Damjan Mariona447c662024-04-09 12:37:25 +0000268 clib_sha2_state_init (&ctx->state, type);
269 ctx->block_size = clib_sha2_variants[type].block_size;
270 ctx->digest_size = clib_sha2_variants[type].digest_size;
271 ctx->type = type;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000272}
273
Damjan Marion7ad751b2024-03-03 22:12:21 +0000274#ifdef CLIB_SHA256_ISA
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000275static inline void
Damjan Marion7ad751b2024-03-03 22:12:21 +0000276clib_sha256_vec_cycle_w (u32x4 w[], u8 i)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000277{
Damjan Marion7ad751b2024-03-03 22:12:21 +0000278 u8 j = (i + 1) % 4;
279 u8 k = (i + 2) % 4;
280 u8 l = (i + 3) % 4;
281#ifdef CLIB_SHA256_ISA_INTEL
282 w[i] = (u32x4) _mm_sha256msg1_epu32 ((__m128i) w[i], (__m128i) w[j]);
283 w[i] += (u32x4) _mm_alignr_epi8 ((__m128i) w[l], (__m128i) w[k], 4);
284 w[i] = (u32x4) _mm_sha256msg2_epu32 ((__m128i) w[i], (__m128i) w[l]);
285#elif defined(CLIB_SHA256_ISA_ARM)
286 w[i] = vsha256su1q_u32 (vsha256su0q_u32 (w[i], w[j]), w[k], w[l]);
287#endif
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000288}
289
290static inline void
Damjan Marion7ad751b2024-03-03 22:12:21 +0000291clib_sha256_vec_4_rounds (u32x4 w, u8 n, u32x4 s[])
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000292{
Damjan Marion7ad751b2024-03-03 22:12:21 +0000293#ifdef CLIB_SHA256_ISA_INTEL
Damjan Mariona447c662024-04-09 12:37:25 +0000294 u32x4 r = *(u32x4 *) (clib_sha2_256_k + 4 * n) + w;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000295 s[0] = (u32x4) _mm_sha256rnds2_epu32 ((__m128i) s[0], (__m128i) s[1],
296 (__m128i) r);
297 r = (u32x4) u64x2_interleave_hi ((u64x2) r, (u64x2) r);
298 s[1] = (u32x4) _mm_sha256rnds2_epu32 ((__m128i) s[1], (__m128i) s[0],
299 (__m128i) r);
Damjan Marion7ad751b2024-03-03 22:12:21 +0000300#elif defined(CLIB_SHA256_ISA_ARM)
301 u32x4 r0, s0;
Damjan Mariona447c662024-04-09 12:37:25 +0000302 const u32x4u *k = (u32x4u *) clib_sha2_256_k;
Damjan Marion7ad751b2024-03-03 22:12:21 +0000303
304 r0 = w + k[n];
305 s0 = s[0];
306 s[0] = vsha256hq_u32 (s[0], s[1], r0);
307 s[1] = vsha256h2q_u32 (s[1], s0, r0);
308#endif
309}
310#endif
311
312#if defined(CLIB_SHA256_ISA)
313static inline u32x4
314clib_sha256_vec_load (u32x4 r)
315{
316#if defined(CLIB_SHA256_ISA_INTEL)
317 return u32x4_byte_swap (r);
318#elif defined(CLIB_SHA256_ISA_ARM)
319 return vreinterpretq_u32_u8 (vrev32q_u8 (vreinterpretq_u8_u32 (r)));
320#endif
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000321}
322
323static inline void
Damjan Marion7ad751b2024-03-03 22:12:21 +0000324clib_sha256_vec_shuffle (u32x4 d[2])
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000325{
Damjan Marion7ad751b2024-03-03 22:12:21 +0000326#if defined(CLIB_SHA256_ISA_INTEL)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000327 /* {0, 1, 2, 3}, {4, 5, 6, 7} -> {7, 6, 3, 2}, {5, 4, 1, 0} */
Damjan Marion7ad751b2024-03-03 22:12:21 +0000328 u32x4 r;
329 r = (u32x4) _mm_shuffle_ps ((__m128) d[1], (__m128) d[0], 0xbb);
330 d[1] = (u32x4) _mm_shuffle_ps ((__m128) d[1], (__m128) d[0], 0x11);
331 d[0] = r;
332#endif
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000333}
334#endif
335
336static inline void
Damjan Mariona447c662024-04-09 12:37:25 +0000337clib_sha256_block (clib_sha2_state_t *st, const u8 *msg, uword n_blocks)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000338{
Damjan Marion7ad751b2024-03-03 22:12:21 +0000339#if defined(CLIB_SHA256_ISA)
340 u32x4 h[2];
341 u32x4u *m = (u32x4u *) msg;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000342
Damjan Mariona447c662024-04-09 12:37:25 +0000343 h[0] = st->h.h32x4[0];
344 h[1] = st->h.h32x4[1];
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000345
Damjan Marion7ad751b2024-03-03 22:12:21 +0000346 clib_sha256_vec_shuffle (h);
347
348 for (; n_blocks; m += 4, n_blocks--)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000349 {
Damjan Marion7ad751b2024-03-03 22:12:21 +0000350 u32x4 s[2], w[4];
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000351
352 s[0] = h[0];
353 s[1] = h[1];
354
Damjan Marion7ad751b2024-03-03 22:12:21 +0000355 w[0] = clib_sha256_vec_load (m[0]);
356 w[1] = clib_sha256_vec_load (m[1]);
357 w[2] = clib_sha256_vec_load (m[2]);
358 w[3] = clib_sha256_vec_load (m[3]);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000359
Damjan Marion7ad751b2024-03-03 22:12:21 +0000360 clib_sha256_vec_4_rounds (w[0], 0, s);
361 clib_sha256_vec_4_rounds (w[1], 1, s);
362 clib_sha256_vec_4_rounds (w[2], 2, s);
363 clib_sha256_vec_4_rounds (w[3], 3, s);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000364
Damjan Marion7ad751b2024-03-03 22:12:21 +0000365 clib_sha256_vec_cycle_w (w, 0);
366 clib_sha256_vec_4_rounds (w[0], 4, s);
367 clib_sha256_vec_cycle_w (w, 1);
368 clib_sha256_vec_4_rounds (w[1], 5, s);
369 clib_sha256_vec_cycle_w (w, 2);
370 clib_sha256_vec_4_rounds (w[2], 6, s);
371 clib_sha256_vec_cycle_w (w, 3);
372 clib_sha256_vec_4_rounds (w[3], 7, s);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000373
Damjan Marion7ad751b2024-03-03 22:12:21 +0000374 clib_sha256_vec_cycle_w (w, 0);
375 clib_sha256_vec_4_rounds (w[0], 8, s);
376 clib_sha256_vec_cycle_w (w, 1);
377 clib_sha256_vec_4_rounds (w[1], 9, s);
378 clib_sha256_vec_cycle_w (w, 2);
379 clib_sha256_vec_4_rounds (w[2], 10, s);
380 clib_sha256_vec_cycle_w (w, 3);
381 clib_sha256_vec_4_rounds (w[3], 11, s);
382
383 clib_sha256_vec_cycle_w (w, 0);
384 clib_sha256_vec_4_rounds (w[0], 12, s);
385 clib_sha256_vec_cycle_w (w, 1);
386 clib_sha256_vec_4_rounds (w[1], 13, s);
387 clib_sha256_vec_cycle_w (w, 2);
388 clib_sha256_vec_4_rounds (w[2], 14, s);
389 clib_sha256_vec_cycle_w (w, 3);
390 clib_sha256_vec_4_rounds (w[3], 15, s);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000391
392 h[0] += s[0];
393 h[1] += s[1];
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000394 }
395
Damjan Marion7ad751b2024-03-03 22:12:21 +0000396 clib_sha256_vec_shuffle (h);
397
Damjan Mariona447c662024-04-09 12:37:25 +0000398 st->h.h32x4[0] = h[0];
399 st->h.h32x4[1] = h[1];
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000400#else
401 u32 w[64], s[8], i;
Damjan Mariona447c662024-04-09 12:37:25 +0000402 clib_sha2_h_t h;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000403
Damjan Mariona447c662024-04-09 12:37:25 +0000404 h = st->h;
405
406 for (; n_blocks; msg += CLIB_SHA2_256_BLOCK_SIZE, n_blocks--)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000407 {
408 for (i = 0; i < 8; i++)
Damjan Mariona447c662024-04-09 12:37:25 +0000409 s[i] = h.h32[i];
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000410
411 for (i = 0; i < 16; i++)
412 {
Damjan Mariona447c662024-04-09 12:37:25 +0000413 w[i] = clib_net_to_host_u32 ((((u32u *) msg)[i]));
414 SHA256_TRANSFORM (s, w, i, clib_sha2_256_k[i]);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000415 }
416
417 for (i = 16; i < 64; i++)
418 {
419 SHA256_MSG_SCHED (w, i);
Damjan Mariona447c662024-04-09 12:37:25 +0000420 SHA256_TRANSFORM (s, w, i, clib_sha2_256_k[i]);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000421 }
422
423 for (i = 0; i < 8; i++)
Damjan Mariona447c662024-04-09 12:37:25 +0000424 h.h32[i] += s[i];
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000425 }
Damjan Mariona447c662024-04-09 12:37:25 +0000426
427 st->h = h;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000428#endif
429}
430
431static_always_inline void
Damjan Mariona447c662024-04-09 12:37:25 +0000432clib_sha512_block (clib_sha2_state_t *st, const u8 *msg, uword n_blocks)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000433{
434 u64 w[80], s[8], i;
Damjan Mariona447c662024-04-09 12:37:25 +0000435 clib_sha2_h_t h;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000436
Damjan Mariona447c662024-04-09 12:37:25 +0000437 h = st->h;
438
439 for (; n_blocks; msg += CLIB_SHA2_512_BLOCK_SIZE, n_blocks--)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000440 {
441 for (i = 0; i < 8; i++)
Damjan Mariona447c662024-04-09 12:37:25 +0000442 s[i] = h.h64[i];
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000443
444 for (i = 0; i < 16; i++)
445 {
Damjan Mariona447c662024-04-09 12:37:25 +0000446 w[i] = clib_net_to_host_u64 ((((u64u *) msg)[i]));
447 SHA512_TRANSFORM (s, w, i, clib_sha2_512_k[i]);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000448 }
449
450 for (i = 16; i < 80; i++)
451 {
452 SHA512_MSG_SCHED (w, i);
Damjan Mariona447c662024-04-09 12:37:25 +0000453 SHA512_TRANSFORM (s, w, i, clib_sha2_512_k[i]);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000454 }
455
456 for (i = 0; i < 8; i++)
Damjan Mariona447c662024-04-09 12:37:25 +0000457 h.h64[i] += s[i];
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000458 }
Damjan Mariona447c662024-04-09 12:37:25 +0000459
460 st->h = h;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000461}
462
463static_always_inline void
Damjan Mariona447c662024-04-09 12:37:25 +0000464clib_sha2_update_internal (clib_sha2_state_t *st, u8 block_size, const u8 *msg,
465 uword n_bytes)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000466{
467 uword n_blocks;
Damjan Mariona447c662024-04-09 12:37:25 +0000468 if (st->n_pending)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000469 {
Damjan Mariona447c662024-04-09 12:37:25 +0000470 uword n_left = block_size - st->n_pending;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000471 if (n_bytes < n_left)
472 {
Damjan Mariona447c662024-04-09 12:37:25 +0000473 clib_memcpy_fast (st->pending.as_u8 + st->n_pending, msg, n_bytes);
474 st->n_pending += n_bytes;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000475 return;
476 }
477 else
478 {
Damjan Mariona447c662024-04-09 12:37:25 +0000479 clib_memcpy_fast (st->pending.as_u8 + st->n_pending, msg, n_left);
480 if (block_size == CLIB_SHA2_512_BLOCK_SIZE)
481 clib_sha512_block (st, st->pending.as_u8, 1);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000482 else
Damjan Mariona447c662024-04-09 12:37:25 +0000483 clib_sha256_block (st, st->pending.as_u8, 1);
484 st->n_pending = 0;
485 st->total_bytes += block_size;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000486 n_bytes -= n_left;
487 msg += n_left;
488 }
489 }
490
Damjan Mariona447c662024-04-09 12:37:25 +0000491 if ((n_blocks = n_bytes / block_size))
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000492 {
Damjan Mariona447c662024-04-09 12:37:25 +0000493 if (block_size == CLIB_SHA2_512_BLOCK_SIZE)
494 clib_sha512_block (st, msg, n_blocks);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000495 else
Damjan Mariona447c662024-04-09 12:37:25 +0000496 clib_sha256_block (st, msg, n_blocks);
497 n_bytes -= n_blocks * block_size;
498 msg += n_blocks * block_size;
499 st->total_bytes += n_blocks * block_size;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000500 }
501
502 if (n_bytes)
503 {
Damjan Mariona447c662024-04-09 12:37:25 +0000504 clib_memset_u8 (st->pending.as_u8, 0, block_size);
505 clib_memcpy_fast (st->pending.as_u8, msg, n_bytes);
506 st->n_pending = n_bytes;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000507 }
508 else
Damjan Mariona447c662024-04-09 12:37:25 +0000509 st->n_pending = 0;
510}
511
512static_always_inline void
513clib_sha2_update (clib_sha2_ctx_t *ctx, const u8 *msg, uword n_bytes)
514{
515 clib_sha2_update_internal (&ctx->state, ctx->block_size, msg, n_bytes);
516}
517
518static_always_inline void
519clib_sha2_final_internal (clib_sha2_state_t *st, u8 block_size, u8 digest_size,
520 u8 *digest)
521{
522 int i;
523
524 st->total_bytes += st->n_pending;
525 if (st->n_pending == 0)
526 {
527 clib_memset (st->pending.as_u8, 0, block_size);
528 st->pending.as_u8[0] = 0x80;
529 }
530 else if (st->n_pending + sizeof (u64) + sizeof (u8) > block_size)
531 {
532 st->pending.as_u8[st->n_pending] = 0x80;
533 if (block_size == CLIB_SHA2_512_BLOCK_SIZE)
534 clib_sha512_block (st, st->pending.as_u8, 1);
535 else
536 clib_sha256_block (st, st->pending.as_u8, 1);
537 clib_memset (st->pending.as_u8, 0, block_size);
538 }
539 else
540 st->pending.as_u8[st->n_pending] = 0x80;
541
542 st->pending.as_u64[block_size / 8 - 1] =
543 clib_net_to_host_u64 (st->total_bytes * 8);
544
545 if (block_size == CLIB_SHA2_512_BLOCK_SIZE)
546 {
547 clib_sha512_block (st, st->pending.as_u8, 1);
548 for (i = 0; i < digest_size / sizeof (u64); i++)
549 ((u64 *) digest)[i] = clib_net_to_host_u64 (st->h.h64[i]);
550
551 /* sha512-224 case - write half of u64 */
552 if (i * sizeof (u64) < digest_size)
553 ((u32 *) digest)[2 * i] = clib_net_to_host_u32 (st->h.h64[i] >> 32);
554 }
555 else
556 {
557 clib_sha256_block (st, st->pending.as_u8, 1);
558 for (i = 0; i < digest_size / sizeof (u32); i++)
559 *((u32 *) digest + i) = clib_net_to_host_u32 (st->h.h32[i]);
560 }
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000561}
562
563static_always_inline void
564clib_sha2_final (clib_sha2_ctx_t *ctx, u8 *digest)
565{
Damjan Mariona447c662024-04-09 12:37:25 +0000566 clib_sha2_final_internal (&ctx->state, ctx->block_size, ctx->digest_size,
567 digest);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000568}
569
570static_always_inline void
571clib_sha2 (clib_sha2_type_t type, const u8 *msg, uword len, u8 *digest)
572{
573 clib_sha2_ctx_t ctx;
574 clib_sha2_init (&ctx, type);
575 clib_sha2_update (&ctx, msg, len);
576 clib_sha2_final (&ctx, digest);
577}
578
579#define clib_sha224(...) clib_sha2 (CLIB_SHA2_224, __VA_ARGS__)
580#define clib_sha256(...) clib_sha2 (CLIB_SHA2_256, __VA_ARGS__)
581#define clib_sha384(...) clib_sha2 (CLIB_SHA2_384, __VA_ARGS__)
582#define clib_sha512(...) clib_sha2 (CLIB_SHA2_512, __VA_ARGS__)
583#define clib_sha512_224(...) clib_sha2 (CLIB_SHA2_512_224, __VA_ARGS__)
584#define clib_sha512_256(...) clib_sha2 (CLIB_SHA2_512_256, __VA_ARGS__)
585
Damjan Mariona447c662024-04-09 12:37:25 +0000586/*
587 * HMAC
588 */
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000589
Damjan Mariona447c662024-04-09 12:37:25 +0000590typedef struct
591{
592 clib_sha2_h_t ipad_h;
593 clib_sha2_h_t opad_h;
594} clib_sha2_hmac_key_data_t;
595
596typedef struct
597{
598 clib_sha2_type_t type;
599 u8 block_size;
600 u8 digest_size;
601 clib_sha2_state_t ipad_state;
602 clib_sha2_state_t opad_state;
603} clib_sha2_hmac_ctx_t;
604
605static_always_inline void
606clib_sha2_hmac_key_data (clib_sha2_type_t type, const u8 *key, uword key_len,
607 clib_sha2_hmac_key_data_t *kd)
608{
609 u8 block_size = clib_sha2_variants[type].block_size;
610 u8 data[SHA2_MAX_BLOCK_SIZE] = {};
611 u8 ikey[SHA2_MAX_BLOCK_SIZE];
612 u8 okey[SHA2_MAX_BLOCK_SIZE];
613 clib_sha2_state_t ipad_state;
614 clib_sha2_state_t opad_state;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000615
616 /* key */
Damjan Mariona447c662024-04-09 12:37:25 +0000617 if (key_len > block_size)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000618 {
619 /* key is longer than block, calculate hash of key */
Damjan Mariona447c662024-04-09 12:37:25 +0000620 clib_sha2_ctx_t ctx;
621 clib_sha2_init (&ctx, type);
622 clib_sha2_update (&ctx, key, key_len);
623 clib_sha2_final (&ctx, (u8 *) data);
624 }
625 else
626 clib_memcpy_fast (data, key, key_len);
627
628 for (int i = 0, w = 0; w < block_size; w += sizeof (uword), i++)
629 {
630 ((uwordu *) ikey)[i] = ((uwordu *) data)[i] ^ 0x3636363636363636UL;
631 ((uwordu *) okey)[i] = ((uwordu *) data)[i] ^ 0x5c5c5c5c5c5c5c5cUL;
632 }
633
634 clib_sha2_state_init (&ipad_state, type);
635 clib_sha2_state_init (&opad_state, type);
636
637 if (block_size == CLIB_SHA2_512_BLOCK_SIZE)
638 {
639 clib_sha512_block (&ipad_state, ikey, 1);
640 clib_sha512_block (&opad_state, okey, 1);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000641 }
642 else
643 {
Damjan Mariona447c662024-04-09 12:37:25 +0000644 clib_sha256_block (&ipad_state, ikey, 1);
645 clib_sha256_block (&opad_state, okey, 1);
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000646 }
647
Damjan Mariona447c662024-04-09 12:37:25 +0000648 kd->ipad_h = ipad_state.h;
649 kd->opad_h = opad_state.h;
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000650}
651
Damjan Mariona447c662024-04-09 12:37:25 +0000652static_always_inline void
653clib_sha2_hmac_init (clib_sha2_hmac_ctx_t *ctx, clib_sha2_type_t type,
654 clib_sha2_hmac_key_data_t *kd)
655{
656 u8 block_size = clib_sha2_variants[type].block_size;
657 u8 digest_size = clib_sha2_variants[type].digest_size;
658
659 *ctx = (clib_sha2_hmac_ctx_t) {
660 .type = type,
661 .block_size = block_size,
662 .digest_size = digest_size,
663 .ipad_state = {
664 .h = kd->ipad_h,
665 .total_bytes = block_size,
666 },
667 .opad_state = {
668 .h = kd->opad_h,
669 .total_bytes = block_size,
670 },
671 };
672}
673
674static_always_inline void
675clib_sha2_hmac_update (clib_sha2_hmac_ctx_t *ctx, const u8 *msg, uword len)
676{
677 clib_sha2_update_internal (&ctx->ipad_state, ctx->block_size, msg, len);
678}
679
680static_always_inline void
681clib_sha2_hmac_final (clib_sha2_hmac_ctx_t *ctx, u8 *digest)
682{
683 u8 i_digest[SHA2_MAX_DIGEST_SIZE];
684
685 clib_sha2_final_internal (&ctx->ipad_state, ctx->block_size,
686 ctx->digest_size, i_digest);
687 clib_sha2_update_internal (&ctx->opad_state, ctx->block_size, i_digest,
688 ctx->digest_size);
689 clib_sha2_final_internal (&ctx->opad_state, ctx->block_size,
690 ctx->digest_size, digest);
691}
692
693static_always_inline void
694clib_sha2_hmac (clib_sha2_type_t type, const u8 *key, uword key_len,
695 const u8 *msg, uword len, u8 *digest)
696{
697 clib_sha2_hmac_ctx_t _ctx, *ctx = &_ctx;
698 clib_sha2_hmac_key_data_t kd;
699
700 clib_sha2_hmac_key_data (type, key, key_len, &kd);
701 clib_sha2_hmac_init (ctx, type, &kd);
702 clib_sha2_hmac_update (ctx, msg, len);
703 clib_sha2_hmac_final (ctx, digest);
704}
705
706#define clib_hmac_sha224(...) clib_sha2_hmac (CLIB_SHA2_224, __VA_ARGS__)
707#define clib_hmac_sha256(...) clib_sha2_hmac (CLIB_SHA2_256, __VA_ARGS__)
708#define clib_hmac_sha384(...) clib_sha2_hmac (CLIB_SHA2_384, __VA_ARGS__)
709#define clib_hmac_sha512(...) clib_sha2_hmac (CLIB_SHA2_512, __VA_ARGS__)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000710#define clib_hmac_sha512_224(...) \
Damjan Mariona447c662024-04-09 12:37:25 +0000711 clib_sha2_hmac (CLIB_SHA2_512_224, __VA_ARGS__)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000712#define clib_hmac_sha512_256(...) \
Damjan Mariona447c662024-04-09 12:37:25 +0000713 clib_sha2_hmac (CLIB_SHA2_512_256, __VA_ARGS__)
Damjan Marion04bd0ea2023-03-16 16:37:56 +0000714
715#endif /* included_sha2_h */