147645577SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
247645577SJerome Forissier /*
347645577SJerome Forissier * Copyright (c) 2019 Huawei Technologies Co., Ltd
447645577SJerome Forissier */
547645577SJerome Forissier /*
647645577SJerome Forissier * SM3 Hash algorithm
747645577SJerome Forissier * thanks to Xyssl
847645577SJerome Forissier * author:goldboar
947645577SJerome Forissier * email:goldboar@163.com
1047645577SJerome Forissier * 2011-10-26
1147645577SJerome Forissier */
1247645577SJerome Forissier
13664463b3SJens Wiklander #include <compiler.h>
14664463b3SJens Wiklander #include <crypto/crypto_accel.h>
1547645577SJerome Forissier #include <string_ext.h>
16664463b3SJens Wiklander #include <string.h>
1747645577SJerome Forissier
1847645577SJerome Forissier #include "sm3.h"
1947645577SJerome Forissier
20664463b3SJens Wiklander #define SM3_BLOCK_SIZE 64
21664463b3SJens Wiklander
2247645577SJerome Forissier #define GET_UINT32_BE(n, b, i) \
2347645577SJerome Forissier do { \
2447645577SJerome Forissier (n) = ((uint32_t)(b)[(i)] << 24) | \
2547645577SJerome Forissier ((uint32_t)(b)[(i) + 1] << 16) | \
2647645577SJerome Forissier ((uint32_t)(b)[(i) + 2] << 8) | \
2747645577SJerome Forissier ((uint32_t)(b)[(i) + 3]); \
2847645577SJerome Forissier } while (0)
2947645577SJerome Forissier
3047645577SJerome Forissier #define PUT_UINT32_BE(n, b, i) \
3147645577SJerome Forissier do { \
3247645577SJerome Forissier (b)[(i)] = (uint8_t)((n) >> 24); \
3347645577SJerome Forissier (b)[(i) + 1] = (uint8_t)((n) >> 16); \
3447645577SJerome Forissier (b)[(i) + 2] = (uint8_t)((n) >> 8); \
3547645577SJerome Forissier (b)[(i) + 3] = (uint8_t)((n)); \
3647645577SJerome Forissier } while (0)
3747645577SJerome Forissier
sm3_init(struct sm3_context * ctx)3847645577SJerome Forissier void sm3_init(struct sm3_context *ctx)
3947645577SJerome Forissier {
4047645577SJerome Forissier ctx->total[0] = 0;
4147645577SJerome Forissier ctx->total[1] = 0;
4247645577SJerome Forissier
4347645577SJerome Forissier ctx->state[0] = 0x7380166F;
4447645577SJerome Forissier ctx->state[1] = 0x4914B2B9;
4547645577SJerome Forissier ctx->state[2] = 0x172442D7;
4647645577SJerome Forissier ctx->state[3] = 0xDA8A0600;
4747645577SJerome Forissier ctx->state[4] = 0xA96F30BC;
4847645577SJerome Forissier ctx->state[5] = 0x163138AA;
4947645577SJerome Forissier ctx->state[6] = 0xE38DEE4D;
5047645577SJerome Forissier ctx->state[7] = 0xB0FB0E4E;
5147645577SJerome Forissier }
5247645577SJerome Forissier
53*e429c45fSClement Faure #define SHL(x, n) ((x) << (n))
54*e429c45fSClement Faure
rotl(uint32_t val,int shift)55*e429c45fSClement Faure static uint32_t rotl(uint32_t val, int shift)
56*e429c45fSClement Faure {
57*e429c45fSClement Faure shift &= 0x1F;
58*e429c45fSClement Faure
59*e429c45fSClement Faure if (shift == 0)
60*e429c45fSClement Faure return val;
61*e429c45fSClement Faure
62*e429c45fSClement Faure return SHL(val, shift) | (val >> (32 - shift));
63*e429c45fSClement Faure }
64*e429c45fSClement Faure
65*e429c45fSClement Faure #define ROTL(x, n) rotl((x), (n))
66*e429c45fSClement Faure
sm3_process(struct sm3_context * ctx,const uint8_t data[64])67664463b3SJens Wiklander static void __maybe_unused sm3_process(struct sm3_context *ctx,
68664463b3SJens Wiklander const uint8_t data[64])
6947645577SJerome Forissier {
7047645577SJerome Forissier uint32_t SS1, SS2, TT1, TT2, W[68], W1[64];
7147645577SJerome Forissier uint32_t A, B, C, D, E, F, G, H;
7247645577SJerome Forissier uint32_t T[64];
7347645577SJerome Forissier uint32_t Temp1, Temp2, Temp3, Temp4, Temp5;
7447645577SJerome Forissier int j;
7547645577SJerome Forissier
7647645577SJerome Forissier for (j = 0; j < 16; j++)
7747645577SJerome Forissier T[j] = 0x79CC4519;
7847645577SJerome Forissier for (j = 16; j < 64; j++)
7947645577SJerome Forissier T[j] = 0x7A879D8A;
8047645577SJerome Forissier
8147645577SJerome Forissier GET_UINT32_BE(W[0], data, 0);
8247645577SJerome Forissier GET_UINT32_BE(W[1], data, 4);
8347645577SJerome Forissier GET_UINT32_BE(W[2], data, 8);
8447645577SJerome Forissier GET_UINT32_BE(W[3], data, 12);
8547645577SJerome Forissier GET_UINT32_BE(W[4], data, 16);
8647645577SJerome Forissier GET_UINT32_BE(W[5], data, 20);
8747645577SJerome Forissier GET_UINT32_BE(W[6], data, 24);
8847645577SJerome Forissier GET_UINT32_BE(W[7], data, 28);
8947645577SJerome Forissier GET_UINT32_BE(W[8], data, 32);
9047645577SJerome Forissier GET_UINT32_BE(W[9], data, 36);
9147645577SJerome Forissier GET_UINT32_BE(W[10], data, 40);
9247645577SJerome Forissier GET_UINT32_BE(W[11], data, 44);
9347645577SJerome Forissier GET_UINT32_BE(W[12], data, 48);
9447645577SJerome Forissier GET_UINT32_BE(W[13], data, 52);
9547645577SJerome Forissier GET_UINT32_BE(W[14], data, 56);
9647645577SJerome Forissier GET_UINT32_BE(W[15], data, 60);
9747645577SJerome Forissier
9847645577SJerome Forissier #define FF0(x, y, z) ((x) ^ (y) ^ (z))
9947645577SJerome Forissier #define FF1(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
10047645577SJerome Forissier
10147645577SJerome Forissier #define GG0(x, y, z) ((x) ^ (y) ^ (z))
10247645577SJerome Forissier #define GG1(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
10347645577SJerome Forissier
10447645577SJerome Forissier #define P0(x) ((x) ^ ROTL((x), 9) ^ ROTL((x), 17))
10547645577SJerome Forissier #define P1(x) ((x) ^ ROTL((x), 15) ^ ROTL((x), 23))
10647645577SJerome Forissier
10747645577SJerome Forissier for (j = 16; j < 68; j++) {
10847645577SJerome Forissier /*
10947645577SJerome Forissier * W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15)) ^
11047645577SJerome Forissier * ROTL(W[j - 13],7 ) ^ W[j-6];
11147645577SJerome Forissier */
11247645577SJerome Forissier
11347645577SJerome Forissier Temp1 = W[j - 16] ^ W[j - 9];
11447645577SJerome Forissier Temp2 = ROTL(W[j - 3], 15);
11547645577SJerome Forissier Temp3 = Temp1 ^ Temp2;
11647645577SJerome Forissier Temp4 = P1(Temp3);
11747645577SJerome Forissier Temp5 = ROTL(W[j - 13], 7) ^ W[j - 6];
11847645577SJerome Forissier W[j] = Temp4 ^ Temp5;
11947645577SJerome Forissier }
12047645577SJerome Forissier
12147645577SJerome Forissier for (j = 0; j < 64; j++)
12247645577SJerome Forissier W1[j] = W[j] ^ W[j + 4];
12347645577SJerome Forissier
12447645577SJerome Forissier A = ctx->state[0];
12547645577SJerome Forissier B = ctx->state[1];
12647645577SJerome Forissier C = ctx->state[2];
12747645577SJerome Forissier D = ctx->state[3];
12847645577SJerome Forissier E = ctx->state[4];
12947645577SJerome Forissier F = ctx->state[5];
13047645577SJerome Forissier G = ctx->state[6];
13147645577SJerome Forissier H = ctx->state[7];
13247645577SJerome Forissier
13347645577SJerome Forissier for (j = 0; j < 16; j++) {
13447645577SJerome Forissier SS1 = ROTL(ROTL(A, 12) + E + ROTL(T[j], j), 7);
13547645577SJerome Forissier SS2 = SS1 ^ ROTL(A, 12);
13647645577SJerome Forissier TT1 = FF0(A, B, C) + D + SS2 + W1[j];
13747645577SJerome Forissier TT2 = GG0(E, F, G) + H + SS1 + W[j];
13847645577SJerome Forissier D = C;
13947645577SJerome Forissier C = ROTL(B, 9);
14047645577SJerome Forissier B = A;
14147645577SJerome Forissier A = TT1;
14247645577SJerome Forissier H = G;
14347645577SJerome Forissier G = ROTL(F, 19);
14447645577SJerome Forissier F = E;
14547645577SJerome Forissier E = P0(TT2);
14647645577SJerome Forissier }
14747645577SJerome Forissier
14847645577SJerome Forissier for (j = 16; j < 64; j++) {
14947645577SJerome Forissier SS1 = ROTL(ROTL(A, 12) + E + ROTL(T[j], j), 7);
15047645577SJerome Forissier SS2 = SS1 ^ ROTL(A, 12);
15147645577SJerome Forissier TT1 = FF1(A, B, C) + D + SS2 + W1[j];
15247645577SJerome Forissier TT2 = GG1(E, F, G) + H + SS1 + W[j];
15347645577SJerome Forissier D = C;
15447645577SJerome Forissier C = ROTL(B, 9);
15547645577SJerome Forissier B = A;
15647645577SJerome Forissier A = TT1;
15747645577SJerome Forissier H = G;
15847645577SJerome Forissier G = ROTL(F, 19);
15947645577SJerome Forissier F = E;
16047645577SJerome Forissier E = P0(TT2);
16147645577SJerome Forissier }
16247645577SJerome Forissier
16347645577SJerome Forissier ctx->state[0] ^= A;
16447645577SJerome Forissier ctx->state[1] ^= B;
16547645577SJerome Forissier ctx->state[2] ^= C;
16647645577SJerome Forissier ctx->state[3] ^= D;
16747645577SJerome Forissier ctx->state[4] ^= E;
16847645577SJerome Forissier ctx->state[5] ^= F;
16947645577SJerome Forissier ctx->state[6] ^= G;
17047645577SJerome Forissier ctx->state[7] ^= H;
17147645577SJerome Forissier }
17247645577SJerome Forissier
sm3_process_blocks(struct sm3_context * ctx,const uint8_t * input,unsigned int block_count)173664463b3SJens Wiklander static void sm3_process_blocks(struct sm3_context *ctx, const uint8_t *input,
174664463b3SJens Wiklander unsigned int block_count)
175664463b3SJens Wiklander {
176664463b3SJens Wiklander #ifdef CFG_CRYPTO_SM3_ARM_CE
177664463b3SJens Wiklander if (block_count)
178664463b3SJens Wiklander crypto_accel_sm3_compress(ctx->state, input, block_count);
179664463b3SJens Wiklander #else
180664463b3SJens Wiklander unsigned int n = 0;
181664463b3SJens Wiklander
182664463b3SJens Wiklander for (n = 0; n < block_count; n++)
183664463b3SJens Wiklander sm3_process(ctx, input + n * SM3_BLOCK_SIZE);
184664463b3SJens Wiklander #endif
185664463b3SJens Wiklander }
186664463b3SJens Wiklander
sm3_update(struct sm3_context * ctx,const uint8_t * input,size_t ilen)18747645577SJerome Forissier void sm3_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen)
18847645577SJerome Forissier {
189664463b3SJens Wiklander unsigned int block_count = 0;
190664463b3SJens Wiklander size_t fill = 0;
191664463b3SJens Wiklander size_t left = 0;
19247645577SJerome Forissier
19347645577SJerome Forissier if (!ilen)
19447645577SJerome Forissier return;
19547645577SJerome Forissier
19647645577SJerome Forissier left = ctx->total[0] & 0x3F;
19747645577SJerome Forissier fill = 64 - left;
19847645577SJerome Forissier
19947645577SJerome Forissier ctx->total[0] += ilen;
20047645577SJerome Forissier
20147645577SJerome Forissier if (ctx->total[0] < ilen)
20247645577SJerome Forissier ctx->total[1]++;
20347645577SJerome Forissier
20447645577SJerome Forissier if (left && ilen >= fill) {
20547645577SJerome Forissier memcpy(ctx->buffer + left, input, fill);
206664463b3SJens Wiklander sm3_process_blocks(ctx, ctx->buffer, 1);
20747645577SJerome Forissier input += fill;
20847645577SJerome Forissier ilen -= fill;
20947645577SJerome Forissier left = 0;
21047645577SJerome Forissier }
21147645577SJerome Forissier
212664463b3SJens Wiklander block_count = ilen / SM3_BLOCK_SIZE;
213664463b3SJens Wiklander sm3_process_blocks(ctx, input, block_count);
214664463b3SJens Wiklander ilen -= block_count * SM3_BLOCK_SIZE;
215664463b3SJens Wiklander input += block_count * SM3_BLOCK_SIZE;
21647645577SJerome Forissier
21747645577SJerome Forissier if (ilen > 0)
21847645577SJerome Forissier memcpy(ctx->buffer + left, input, ilen);
21947645577SJerome Forissier }
22047645577SJerome Forissier
22147645577SJerome Forissier static const uint8_t sm3_padding[64] = {
22247645577SJerome Forissier 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22347645577SJerome Forissier 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22447645577SJerome Forissier 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22547645577SJerome Forissier 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
22647645577SJerome Forissier };
22747645577SJerome Forissier
sm3_final(struct sm3_context * ctx,uint8_t output[32])22847645577SJerome Forissier void sm3_final(struct sm3_context *ctx, uint8_t output[32])
22947645577SJerome Forissier {
23047645577SJerome Forissier uint32_t last, padn;
23147645577SJerome Forissier uint32_t high, low;
23247645577SJerome Forissier uint8_t msglen[8];
23347645577SJerome Forissier
23447645577SJerome Forissier high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
23547645577SJerome Forissier low = ctx->total[0] << 3;
23647645577SJerome Forissier
23747645577SJerome Forissier PUT_UINT32_BE(high, msglen, 0);
23847645577SJerome Forissier PUT_UINT32_BE(low, msglen, 4);
23947645577SJerome Forissier
24047645577SJerome Forissier last = ctx->total[0] & 0x3F;
24147645577SJerome Forissier padn = (last < 56) ? (56 - last) : (120 - last);
24247645577SJerome Forissier
24347645577SJerome Forissier sm3_update(ctx, sm3_padding, padn);
24447645577SJerome Forissier sm3_update(ctx, msglen, 8);
24547645577SJerome Forissier
24647645577SJerome Forissier PUT_UINT32_BE(ctx->state[0], output, 0);
24747645577SJerome Forissier PUT_UINT32_BE(ctx->state[1], output, 4);
24847645577SJerome Forissier PUT_UINT32_BE(ctx->state[2], output, 8);
24947645577SJerome Forissier PUT_UINT32_BE(ctx->state[3], output, 12);
25047645577SJerome Forissier PUT_UINT32_BE(ctx->state[4], output, 16);
25147645577SJerome Forissier PUT_UINT32_BE(ctx->state[5], output, 20);
25247645577SJerome Forissier PUT_UINT32_BE(ctx->state[6], output, 24);
25347645577SJerome Forissier PUT_UINT32_BE(ctx->state[7], output, 28);
25447645577SJerome Forissier }
25547645577SJerome Forissier
sm3(const uint8_t * input,size_t ilen,uint8_t output[32])25647645577SJerome Forissier void sm3(const uint8_t *input, size_t ilen, uint8_t output[32])
25747645577SJerome Forissier {
25847645577SJerome Forissier struct sm3_context ctx = { };
25947645577SJerome Forissier
26047645577SJerome Forissier sm3_init(&ctx);
26147645577SJerome Forissier sm3_update(&ctx, input, ilen);
26247645577SJerome Forissier sm3_final(&ctx, output);
26347645577SJerome Forissier
26447645577SJerome Forissier memzero_explicit(&ctx, sizeof(ctx));
26547645577SJerome Forissier }
26647645577SJerome Forissier
sm3_hmac_init(struct sm3_context * ctx,const uint8_t * key,size_t keylen)26747645577SJerome Forissier void sm3_hmac_init(struct sm3_context *ctx, const uint8_t *key, size_t keylen)
26847645577SJerome Forissier {
26947645577SJerome Forissier size_t i;
27047645577SJerome Forissier uint8_t sum[32];
27147645577SJerome Forissier
27247645577SJerome Forissier if (keylen > 64) {
27347645577SJerome Forissier sm3(key, keylen, sum);
27447645577SJerome Forissier keylen = 32;
27547645577SJerome Forissier key = sum;
27647645577SJerome Forissier }
27747645577SJerome Forissier
27847645577SJerome Forissier memset(ctx->ipad, 0x36, 64);
27947645577SJerome Forissier memset(ctx->opad, 0x5C, 64);
28047645577SJerome Forissier
28147645577SJerome Forissier for (i = 0; i < keylen; i++) {
28247645577SJerome Forissier ctx->ipad[i] ^= key[i];
28347645577SJerome Forissier ctx->opad[i] ^= key[i];
28447645577SJerome Forissier }
28547645577SJerome Forissier
28647645577SJerome Forissier sm3_init(ctx);
28747645577SJerome Forissier sm3_update(ctx, ctx->ipad, 64);
28847645577SJerome Forissier
28947645577SJerome Forissier memzero_explicit(sum, sizeof(sum));
29047645577SJerome Forissier }
29147645577SJerome Forissier
sm3_hmac_update(struct sm3_context * ctx,const uint8_t * input,size_t ilen)29247645577SJerome Forissier void sm3_hmac_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen)
29347645577SJerome Forissier {
29447645577SJerome Forissier sm3_update(ctx, input, ilen);
29547645577SJerome Forissier }
29647645577SJerome Forissier
sm3_hmac_final(struct sm3_context * ctx,uint8_t output[32])29747645577SJerome Forissier void sm3_hmac_final(struct sm3_context *ctx, uint8_t output[32])
29847645577SJerome Forissier {
29947645577SJerome Forissier uint8_t tmpbuf[32];
30047645577SJerome Forissier
30147645577SJerome Forissier sm3_final(ctx, tmpbuf);
30247645577SJerome Forissier sm3_init(ctx);
30347645577SJerome Forissier sm3_update(ctx, ctx->opad, 64);
30447645577SJerome Forissier sm3_update(ctx, tmpbuf, 32);
30547645577SJerome Forissier sm3_final(ctx, output);
30647645577SJerome Forissier
30747645577SJerome Forissier memzero_explicit(tmpbuf, sizeof(tmpbuf));
30847645577SJerome Forissier }
30947645577SJerome Forissier
sm3_hmac(const uint8_t * key,size_t keylen,const uint8_t * input,size_t ilen,uint8_t output[32])31047645577SJerome Forissier void sm3_hmac(const uint8_t *key, size_t keylen, const uint8_t *input,
31147645577SJerome Forissier size_t ilen, uint8_t output[32])
31247645577SJerome Forissier {
31347645577SJerome Forissier struct sm3_context ctx;
31447645577SJerome Forissier
31547645577SJerome Forissier sm3_hmac_init(&ctx, key, keylen);
31647645577SJerome Forissier sm3_hmac_update(&ctx, input, ilen);
31747645577SJerome Forissier sm3_hmac_final(&ctx, output);
31847645577SJerome Forissier
31947645577SJerome Forissier memzero_explicit(&ctx, sizeof(ctx));
32047645577SJerome Forissier }
321