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