18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Cryptographic API.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * RIPEMD-256 - RACE Integrity Primitives Evaluation Message Digest.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Based on the reference implementation by Antoon Bosselaers, ESAT-COSIC
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (c) 2008 Adrian-Ken Rueegsegger <ken@codelabs.ch>
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h>
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/mm.h>
158c2ecf20Sopenharmony_ci#include <linux/types.h>
168c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "ripemd.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistruct rmd256_ctx {
218c2ecf20Sopenharmony_ci	u64 byte_count;
228c2ecf20Sopenharmony_ci	u32 state[8];
238c2ecf20Sopenharmony_ci	__le32 buffer[16];
248c2ecf20Sopenharmony_ci};
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define K1  RMD_K1
278c2ecf20Sopenharmony_ci#define K2  RMD_K2
288c2ecf20Sopenharmony_ci#define K3  RMD_K3
298c2ecf20Sopenharmony_ci#define K4  RMD_K4
308c2ecf20Sopenharmony_ci#define KK1 RMD_K6
318c2ecf20Sopenharmony_ci#define KK2 RMD_K7
328c2ecf20Sopenharmony_ci#define KK3 RMD_K8
338c2ecf20Sopenharmony_ci#define KK4 RMD_K1
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define F1(x, y, z) (x ^ y ^ z)		/* XOR */
368c2ecf20Sopenharmony_ci#define F2(x, y, z) (z ^ (x & (y ^ z)))	/* x ? y : z */
378c2ecf20Sopenharmony_ci#define F3(x, y, z) ((x | ~y) ^ z)
388c2ecf20Sopenharmony_ci#define F4(x, y, z) (y ^ (z & (x ^ y)))	/* z ? x : y */
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define ROUND(a, b, c, d, f, k, x, s)  { \
418c2ecf20Sopenharmony_ci	(a) += f((b), (c), (d)) + le32_to_cpup(&(x)) + (k); \
428c2ecf20Sopenharmony_ci	(a) = rol32((a), (s)); \
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic void rmd256_transform(u32 *state, const __le32 *in)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	u32 aa, bb, cc, dd, aaa, bbb, ccc, ddd;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	/* Initialize left lane */
508c2ecf20Sopenharmony_ci	aa = state[0];
518c2ecf20Sopenharmony_ci	bb = state[1];
528c2ecf20Sopenharmony_ci	cc = state[2];
538c2ecf20Sopenharmony_ci	dd = state[3];
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	/* Initialize right lane */
568c2ecf20Sopenharmony_ci	aaa = state[4];
578c2ecf20Sopenharmony_ci	bbb = state[5];
588c2ecf20Sopenharmony_ci	ccc = state[6];
598c2ecf20Sopenharmony_ci	ddd = state[7];
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	/* round 1: left lane */
628c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F1, K1, in[0],  11);
638c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F1, K1, in[1],  14);
648c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F1, K1, in[2],  15);
658c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F1, K1, in[3],  12);
668c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F1, K1, in[4],   5);
678c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F1, K1, in[5],   8);
688c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F1, K1, in[6],   7);
698c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F1, K1, in[7],   9);
708c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F1, K1, in[8],  11);
718c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F1, K1, in[9],  13);
728c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F1, K1, in[10], 14);
738c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F1, K1, in[11], 15);
748c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F1, K1, in[12],  6);
758c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F1, K1, in[13],  7);
768c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F1, K1, in[14],  9);
778c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F1, K1, in[15],  8);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	/* round 1: right lane */
808c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F4, KK1, in[5],   8);
818c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F4, KK1, in[14],  9);
828c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F4, KK1, in[7],   9);
838c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F4, KK1, in[0],  11);
848c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F4, KK1, in[9],  13);
858c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F4, KK1, in[2],  15);
868c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F4, KK1, in[11], 15);
878c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F4, KK1, in[4],   5);
888c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F4, KK1, in[13],  7);
898c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F4, KK1, in[6],   7);
908c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F4, KK1, in[15],  8);
918c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F4, KK1, in[8],  11);
928c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F4, KK1, in[1],  14);
938c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F4, KK1, in[10], 14);
948c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F4, KK1, in[3],  12);
958c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F4, KK1, in[12],  6);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	/* Swap contents of "a" registers */
988c2ecf20Sopenharmony_ci	swap(aa, aaa);
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	/* round 2: left lane */
1018c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F2, K2, in[7],   7);
1028c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F2, K2, in[4],   6);
1038c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F2, K2, in[13],  8);
1048c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F2, K2, in[1],  13);
1058c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F2, K2, in[10], 11);
1068c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F2, K2, in[6],   9);
1078c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F2, K2, in[15],  7);
1088c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F2, K2, in[3],  15);
1098c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F2, K2, in[12],  7);
1108c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F2, K2, in[0],  12);
1118c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F2, K2, in[9],  15);
1128c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F2, K2, in[5],   9);
1138c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F2, K2, in[2],  11);
1148c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F2, K2, in[14],  7);
1158c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F2, K2, in[11], 13);
1168c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F2, K2, in[8],  12);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	/* round 2: right lane */
1198c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F3, KK2, in[6],   9);
1208c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F3, KK2, in[11], 13);
1218c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F3, KK2, in[3],  15);
1228c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F3, KK2, in[7],   7);
1238c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F3, KK2, in[0],  12);
1248c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F3, KK2, in[13],  8);
1258c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F3, KK2, in[5],   9);
1268c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F3, KK2, in[10], 11);
1278c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F3, KK2, in[14],  7);
1288c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F3, KK2, in[15],  7);
1298c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F3, KK2, in[8],  12);
1308c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F3, KK2, in[12],  7);
1318c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F3, KK2, in[4],   6);
1328c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F3, KK2, in[9],  15);
1338c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F3, KK2, in[1],  13);
1348c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F3, KK2, in[2],  11);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/* Swap contents of "b" registers */
1378c2ecf20Sopenharmony_ci	swap(bb, bbb);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	/* round 3: left lane */
1408c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F3, K3, in[3],  11);
1418c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F3, K3, in[10], 13);
1428c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F3, K3, in[14],  6);
1438c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F3, K3, in[4],   7);
1448c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F3, K3, in[9],  14);
1458c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F3, K3, in[15],  9);
1468c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F3, K3, in[8],  13);
1478c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F3, K3, in[1],  15);
1488c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F3, K3, in[2],  14);
1498c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F3, K3, in[7],   8);
1508c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F3, K3, in[0],  13);
1518c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F3, K3, in[6],   6);
1528c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F3, K3, in[13],  5);
1538c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F3, K3, in[11], 12);
1548c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F3, K3, in[5],   7);
1558c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F3, K3, in[12],  5);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* round 3: right lane */
1588c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F2, KK3, in[15],  9);
1598c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F2, KK3, in[5],   7);
1608c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F2, KK3, in[1],  15);
1618c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F2, KK3, in[3],  11);
1628c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F2, KK3, in[7],   8);
1638c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F2, KK3, in[14],  6);
1648c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F2, KK3, in[6],   6);
1658c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F2, KK3, in[9],  14);
1668c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F2, KK3, in[11], 12);
1678c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F2, KK3, in[8],  13);
1688c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F2, KK3, in[12],  5);
1698c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F2, KK3, in[2],  14);
1708c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F2, KK3, in[10], 13);
1718c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F2, KK3, in[0],  13);
1728c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F2, KK3, in[4],   7);
1738c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F2, KK3, in[13],  5);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	/* Swap contents of "c" registers */
1768c2ecf20Sopenharmony_ci	swap(cc, ccc);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	/* round 4: left lane */
1798c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F4, K4, in[1],  11);
1808c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F4, K4, in[9],  12);
1818c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F4, K4, in[11], 14);
1828c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F4, K4, in[10], 15);
1838c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F4, K4, in[0],  14);
1848c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F4, K4, in[8],  15);
1858c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F4, K4, in[12],  9);
1868c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F4, K4, in[4],   8);
1878c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F4, K4, in[13],  9);
1888c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F4, K4, in[3],  14);
1898c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F4, K4, in[7],   5);
1908c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F4, K4, in[15],  6);
1918c2ecf20Sopenharmony_ci	ROUND(aa, bb, cc, dd, F4, K4, in[14],  8);
1928c2ecf20Sopenharmony_ci	ROUND(dd, aa, bb, cc, F4, K4, in[5],   6);
1938c2ecf20Sopenharmony_ci	ROUND(cc, dd, aa, bb, F4, K4, in[6],   5);
1948c2ecf20Sopenharmony_ci	ROUND(bb, cc, dd, aa, F4, K4, in[2],  12);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	/* round 4: right lane */
1978c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F1, KK4, in[8],  15);
1988c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F1, KK4, in[6],   5);
1998c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F1, KK4, in[4],   8);
2008c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F1, KK4, in[1],  11);
2018c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F1, KK4, in[3],  14);
2028c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F1, KK4, in[11], 14);
2038c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F1, KK4, in[15],  6);
2048c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F1, KK4, in[0],  14);
2058c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F1, KK4, in[5],   6);
2068c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F1, KK4, in[12],  9);
2078c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F1, KK4, in[2],  12);
2088c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F1, KK4, in[13],  9);
2098c2ecf20Sopenharmony_ci	ROUND(aaa, bbb, ccc, ddd, F1, KK4, in[9],  12);
2108c2ecf20Sopenharmony_ci	ROUND(ddd, aaa, bbb, ccc, F1, KK4, in[7],   5);
2118c2ecf20Sopenharmony_ci	ROUND(ccc, ddd, aaa, bbb, F1, KK4, in[10], 15);
2128c2ecf20Sopenharmony_ci	ROUND(bbb, ccc, ddd, aaa, F1, KK4, in[14],  8);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	/* Swap contents of "d" registers */
2158c2ecf20Sopenharmony_ci	swap(dd, ddd);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	/* combine results */
2188c2ecf20Sopenharmony_ci	state[0] += aa;
2198c2ecf20Sopenharmony_ci	state[1] += bb;
2208c2ecf20Sopenharmony_ci	state[2] += cc;
2218c2ecf20Sopenharmony_ci	state[3] += dd;
2228c2ecf20Sopenharmony_ci	state[4] += aaa;
2238c2ecf20Sopenharmony_ci	state[5] += bbb;
2248c2ecf20Sopenharmony_ci	state[6] += ccc;
2258c2ecf20Sopenharmony_ci	state[7] += ddd;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistatic int rmd256_init(struct shash_desc *desc)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	struct rmd256_ctx *rctx = shash_desc_ctx(desc);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	rctx->byte_count = 0;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	rctx->state[0] = RMD_H0;
2358c2ecf20Sopenharmony_ci	rctx->state[1] = RMD_H1;
2368c2ecf20Sopenharmony_ci	rctx->state[2] = RMD_H2;
2378c2ecf20Sopenharmony_ci	rctx->state[3] = RMD_H3;
2388c2ecf20Sopenharmony_ci	rctx->state[4] = RMD_H5;
2398c2ecf20Sopenharmony_ci	rctx->state[5] = RMD_H6;
2408c2ecf20Sopenharmony_ci	rctx->state[6] = RMD_H7;
2418c2ecf20Sopenharmony_ci	rctx->state[7] = RMD_H8;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	memset(rctx->buffer, 0, sizeof(rctx->buffer));
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	return 0;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cistatic int rmd256_update(struct shash_desc *desc, const u8 *data,
2498c2ecf20Sopenharmony_ci			 unsigned int len)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	struct rmd256_ctx *rctx = shash_desc_ctx(desc);
2528c2ecf20Sopenharmony_ci	const u32 avail = sizeof(rctx->buffer) - (rctx->byte_count & 0x3f);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	rctx->byte_count += len;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	/* Enough space in buffer? If so copy and we're done */
2578c2ecf20Sopenharmony_ci	if (avail > len) {
2588c2ecf20Sopenharmony_ci		memcpy((char *)rctx->buffer + (sizeof(rctx->buffer) - avail),
2598c2ecf20Sopenharmony_ci		       data, len);
2608c2ecf20Sopenharmony_ci		goto out;
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	memcpy((char *)rctx->buffer + (sizeof(rctx->buffer) - avail),
2648c2ecf20Sopenharmony_ci	       data, avail);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	rmd256_transform(rctx->state, rctx->buffer);
2678c2ecf20Sopenharmony_ci	data += avail;
2688c2ecf20Sopenharmony_ci	len -= avail;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	while (len >= sizeof(rctx->buffer)) {
2718c2ecf20Sopenharmony_ci		memcpy(rctx->buffer, data, sizeof(rctx->buffer));
2728c2ecf20Sopenharmony_ci		rmd256_transform(rctx->state, rctx->buffer);
2738c2ecf20Sopenharmony_ci		data += sizeof(rctx->buffer);
2748c2ecf20Sopenharmony_ci		len -= sizeof(rctx->buffer);
2758c2ecf20Sopenharmony_ci	}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	memcpy(rctx->buffer, data, len);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ciout:
2808c2ecf20Sopenharmony_ci	return 0;
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci/* Add padding and return the message digest. */
2848c2ecf20Sopenharmony_cistatic int rmd256_final(struct shash_desc *desc, u8 *out)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	struct rmd256_ctx *rctx = shash_desc_ctx(desc);
2878c2ecf20Sopenharmony_ci	u32 i, index, padlen;
2888c2ecf20Sopenharmony_ci	__le64 bits;
2898c2ecf20Sopenharmony_ci	__le32 *dst = (__le32 *)out;
2908c2ecf20Sopenharmony_ci	static const u8 padding[64] = { 0x80, };
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	bits = cpu_to_le64(rctx->byte_count << 3);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/* Pad out to 56 mod 64 */
2958c2ecf20Sopenharmony_ci	index = rctx->byte_count & 0x3f;
2968c2ecf20Sopenharmony_ci	padlen = (index < 56) ? (56 - index) : ((64+56) - index);
2978c2ecf20Sopenharmony_ci	rmd256_update(desc, padding, padlen);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/* Append length */
3008c2ecf20Sopenharmony_ci	rmd256_update(desc, (const u8 *)&bits, sizeof(bits));
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	/* Store state in digest */
3038c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++)
3048c2ecf20Sopenharmony_ci		dst[i] = cpu_to_le32p(&rctx->state[i]);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	/* Wipe context */
3078c2ecf20Sopenharmony_ci	memset(rctx, 0, sizeof(*rctx));
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	return 0;
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic struct shash_alg alg = {
3138c2ecf20Sopenharmony_ci	.digestsize	=	RMD256_DIGEST_SIZE,
3148c2ecf20Sopenharmony_ci	.init		=	rmd256_init,
3158c2ecf20Sopenharmony_ci	.update		=	rmd256_update,
3168c2ecf20Sopenharmony_ci	.final		=	rmd256_final,
3178c2ecf20Sopenharmony_ci	.descsize	=	sizeof(struct rmd256_ctx),
3188c2ecf20Sopenharmony_ci	.base		=	{
3198c2ecf20Sopenharmony_ci		.cra_name	 =	"rmd256",
3208c2ecf20Sopenharmony_ci		.cra_driver_name =	"rmd256-generic",
3218c2ecf20Sopenharmony_ci		.cra_blocksize	 =	RMD256_BLOCK_SIZE,
3228c2ecf20Sopenharmony_ci		.cra_module	 =	THIS_MODULE,
3238c2ecf20Sopenharmony_ci	}
3248c2ecf20Sopenharmony_ci};
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic int __init rmd256_mod_init(void)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	return crypto_register_shash(&alg);
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_cistatic void __exit rmd256_mod_fini(void)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	crypto_unregister_shash(&alg);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cisubsys_initcall(rmd256_mod_init);
3378c2ecf20Sopenharmony_cimodule_exit(rmd256_mod_fini);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
3408c2ecf20Sopenharmony_ciMODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
3418c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("RIPEMD-256 Message Digest");
3428c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("rmd256");
343