Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sparc/crypto/md5_glue.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* Glue code for MD5 hashing optimized for sparc64 crypto opcodes.
3
*
4
* This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c
5
* and crypto/md5.c which are:
6
*
7
* Copyright (c) Alan Smithee.
8
* Copyright (c) Andrew McDonald <[email protected]>
9
* Copyright (c) Jean-Francois Dive <[email protected]>
10
* Copyright (c) Mathias Krause <[email protected]>
11
* Copyright (c) Cryptoapi developers.
12
* Copyright (c) 2002 James Morris <[email protected]>
13
*/
14
15
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17
#include <asm/elf.h>
18
#include <asm/opcodes.h>
19
#include <asm/pstate.h>
20
#include <crypto/internal/hash.h>
21
#include <crypto/md5.h>
22
#include <linux/errno.h>
23
#include <linux/kernel.h>
24
#include <linux/module.h>
25
#include <linux/string.h>
26
#include <linux/unaligned.h>
27
28
struct sparc_md5_state {
29
__le32 hash[MD5_HASH_WORDS];
30
u64 byte_count;
31
};
32
33
asmlinkage void md5_sparc64_transform(__le32 *digest, const char *data,
34
unsigned int rounds);
35
36
static int md5_sparc64_init(struct shash_desc *desc)
37
{
38
struct sparc_md5_state *mctx = shash_desc_ctx(desc);
39
40
mctx->hash[0] = cpu_to_le32(MD5_H0);
41
mctx->hash[1] = cpu_to_le32(MD5_H1);
42
mctx->hash[2] = cpu_to_le32(MD5_H2);
43
mctx->hash[3] = cpu_to_le32(MD5_H3);
44
mctx->byte_count = 0;
45
46
return 0;
47
}
48
49
static int md5_sparc64_update(struct shash_desc *desc, const u8 *data,
50
unsigned int len)
51
{
52
struct sparc_md5_state *sctx = shash_desc_ctx(desc);
53
54
sctx->byte_count += round_down(len, MD5_HMAC_BLOCK_SIZE);
55
md5_sparc64_transform(sctx->hash, data, len / MD5_HMAC_BLOCK_SIZE);
56
return len - round_down(len, MD5_HMAC_BLOCK_SIZE);
57
}
58
59
/* Add padding and return the message digest. */
60
static int md5_sparc64_finup(struct shash_desc *desc, const u8 *src,
61
unsigned int offset, u8 *out)
62
{
63
struct sparc_md5_state *sctx = shash_desc_ctx(desc);
64
__le64 block[MD5_BLOCK_WORDS] = {};
65
u8 *p = memcpy(block, src, offset);
66
__le32 *dst = (__le32 *)out;
67
__le64 *pbits;
68
int i;
69
70
src = p;
71
p += offset;
72
*p++ = 0x80;
73
sctx->byte_count += offset;
74
pbits = &block[(MD5_BLOCK_WORDS / (offset > 55 ? 1 : 2)) - 1];
75
*pbits = cpu_to_le64(sctx->byte_count << 3);
76
md5_sparc64_transform(sctx->hash, src, (pbits - block + 1) / 8);
77
memzero_explicit(block, sizeof(block));
78
79
/* Store state in digest */
80
for (i = 0; i < MD5_HASH_WORDS; i++)
81
dst[i] = sctx->hash[i];
82
83
return 0;
84
}
85
86
static int md5_sparc64_export(struct shash_desc *desc, void *out)
87
{
88
struct sparc_md5_state *sctx = shash_desc_ctx(desc);
89
union {
90
u8 *u8;
91
u32 *u32;
92
u64 *u64;
93
} p = { .u8 = out };
94
int i;
95
96
for (i = 0; i < MD5_HASH_WORDS; i++)
97
put_unaligned(le32_to_cpu(sctx->hash[i]), p.u32++);
98
put_unaligned(sctx->byte_count, p.u64);
99
return 0;
100
}
101
102
static int md5_sparc64_import(struct shash_desc *desc, const void *in)
103
{
104
struct sparc_md5_state *sctx = shash_desc_ctx(desc);
105
union {
106
const u8 *u8;
107
const u32 *u32;
108
const u64 *u64;
109
} p = { .u8 = in };
110
int i;
111
112
for (i = 0; i < MD5_HASH_WORDS; i++)
113
sctx->hash[i] = cpu_to_le32(get_unaligned(p.u32++));
114
sctx->byte_count = get_unaligned(p.u64);
115
return 0;
116
}
117
118
static struct shash_alg alg = {
119
.digestsize = MD5_DIGEST_SIZE,
120
.init = md5_sparc64_init,
121
.update = md5_sparc64_update,
122
.finup = md5_sparc64_finup,
123
.export = md5_sparc64_export,
124
.import = md5_sparc64_import,
125
.descsize = sizeof(struct sparc_md5_state),
126
.statesize = sizeof(struct sparc_md5_state),
127
.base = {
128
.cra_name = "md5",
129
.cra_driver_name= "md5-sparc64",
130
.cra_priority = SPARC_CR_OPCODE_PRIORITY,
131
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
132
.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
133
.cra_module = THIS_MODULE,
134
}
135
};
136
137
static bool __init sparc64_has_md5_opcode(void)
138
{
139
unsigned long cfr;
140
141
if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
142
return false;
143
144
__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
145
if (!(cfr & CFR_MD5))
146
return false;
147
148
return true;
149
}
150
151
static int __init md5_sparc64_mod_init(void)
152
{
153
if (sparc64_has_md5_opcode()) {
154
pr_info("Using sparc64 md5 opcode optimized MD5 implementation\n");
155
return crypto_register_shash(&alg);
156
}
157
pr_info("sparc64 md5 opcode not available.\n");
158
return -ENODEV;
159
}
160
161
static void __exit md5_sparc64_mod_fini(void)
162
{
163
crypto_unregister_shash(&alg);
164
}
165
166
module_init(md5_sparc64_mod_init);
167
module_exit(md5_sparc64_mod_fini);
168
169
MODULE_LICENSE("GPL");
170
MODULE_DESCRIPTION("MD5 Message Digest Algorithm, sparc64 md5 opcode accelerated");
171
172
MODULE_ALIAS_CRYPTO("md5");
173
174
#include "crop_devid.c"
175
176