Blame view
drivers/crypto/padlock-sha.c
9.05 KB
6c8332751 [CRYPTO] padlock:... |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* * Cryptographic API. * * Support for VIA PadLock hardware crypto engine. * * Copyright (c) 2006 Michal Ludvig <michal@logix.cz> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * */ |
7d0246082 crypto: padlock -... |
14 |
#include <crypto/internal/hash.h> |
5265eeb2b [CRYPTO] sha: Add... |
15 |
#include <crypto/sha.h> |
6010439f4 [CRYPTO] padlock:... |
16 |
#include <linux/err.h> |
6c8332751 [CRYPTO] padlock:... |
17 18 19 |
#include <linux/module.h> #include <linux/init.h> #include <linux/errno.h> |
6c8332751 [CRYPTO] padlock:... |
20 21 22 |
#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/scatterlist.h> |
e49140120 crypto: padlock -... |
23 |
#include <asm/i387.h> |
6c8332751 [CRYPTO] padlock:... |
24 |
#include "padlock.h" |
4c6ab3ee4 crypto: padlock-s... |
25 26 27 28 29 |
#ifdef CONFIG_64BIT #define STACK_ALIGN 16 #else #define STACK_ALIGN 4 #endif |
bbbee4679 crypto: padlock -... |
30 31 |
struct padlock_sha_desc { struct shash_desc fallback; |
6c8332751 [CRYPTO] padlock:... |
32 |
}; |
bbbee4679 crypto: padlock -... |
33 34 35 |
struct padlock_sha_ctx { struct crypto_shash *fallback; }; |
6c8332751 [CRYPTO] padlock:... |
36 |
|
bbbee4679 crypto: padlock -... |
37 |
static int padlock_sha_init(struct shash_desc *desc) |
6c8332751 [CRYPTO] padlock:... |
38 |
{ |
bbbee4679 crypto: padlock -... |
39 40 |
struct padlock_sha_desc *dctx = shash_desc_ctx(desc); struct padlock_sha_ctx *ctx = crypto_shash_ctx(desc->tfm); |
6c8332751 [CRYPTO] padlock:... |
41 |
|
bbbee4679 crypto: padlock -... |
42 43 44 |
dctx->fallback.tfm = ctx->fallback; dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; return crypto_shash_init(&dctx->fallback); |
6c8332751 [CRYPTO] padlock:... |
45 |
} |
bbbee4679 crypto: padlock -... |
46 47 |
static int padlock_sha_update(struct shash_desc *desc, const u8 *data, unsigned int length) |
6c8332751 [CRYPTO] padlock:... |
48 |
{ |
bbbee4679 crypto: padlock -... |
49 |
struct padlock_sha_desc *dctx = shash_desc_ctx(desc); |
6c8332751 [CRYPTO] padlock:... |
50 |
|
bbbee4679 crypto: padlock -... |
51 52 |
dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; return crypto_shash_update(&dctx->fallback, data, length); |
6c8332751 [CRYPTO] padlock:... |
53 |
} |
a8d7ac279 crypto: padlock-s... |
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
static int padlock_sha_export(struct shash_desc *desc, void *out) { struct padlock_sha_desc *dctx = shash_desc_ctx(desc); return crypto_shash_export(&dctx->fallback, out); } static int padlock_sha_import(struct shash_desc *desc, const void *in) { struct padlock_sha_desc *dctx = shash_desc_ctx(desc); struct padlock_sha_ctx *ctx = crypto_shash_ctx(desc->tfm); dctx->fallback.tfm = ctx->fallback; dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; return crypto_shash_import(&dctx->fallback, in); } |
6c8332751 [CRYPTO] padlock:... |
70 71 72 73 74 75 |
static inline void padlock_output_block(uint32_t *src, uint32_t *dst, size_t count) { while (count--) *dst++ = swab32(*src++); } |
bbbee4679 crypto: padlock -... |
76 77 |
static int padlock_sha1_finup(struct shash_desc *desc, const u8 *in, unsigned int count, u8 *out) |
6c8332751 [CRYPTO] padlock:... |
78 79 80 81 |
{ /* We can't store directly to *out as it may be unaligned. */ /* BTW Don't reduce the buffer size below 128 Bytes! * PadLock microcode needs it that big. */ |
4c6ab3ee4 crypto: padlock-s... |
82 83 84 |
char buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__ ((aligned(STACK_ALIGN))); char *result = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); |
bbbee4679 crypto: padlock -... |
85 86 87 88 |
struct padlock_sha_desc *dctx = shash_desc_ctx(desc); struct sha1_state state; unsigned int space; unsigned int leftover; |
e49140120 crypto: padlock -... |
89 |
int ts_state; |
bbbee4679 crypto: padlock -... |
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
int err; dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; err = crypto_shash_export(&dctx->fallback, &state); if (err) goto out; if (state.count + count > ULONG_MAX) return crypto_shash_finup(&dctx->fallback, in, count, out); leftover = ((state.count - 1) & (SHA1_BLOCK_SIZE - 1)) + 1; space = SHA1_BLOCK_SIZE - leftover; if (space) { if (count > space) { err = crypto_shash_update(&dctx->fallback, in, space) ?: crypto_shash_export(&dctx->fallback, &state); if (err) goto out; count -= space; in += space; } else { memcpy(state.buffer + leftover, in, count); in = state.buffer; count += leftover; |
e9b25f16c crypto: padlock -... |
114 |
state.count &= ~(SHA1_BLOCK_SIZE - 1); |
bbbee4679 crypto: padlock -... |
115 116 117 118 |
} } memcpy(result, &state.state, SHA1_DIGEST_SIZE); |
6c8332751 [CRYPTO] padlock:... |
119 |
|
e49140120 crypto: padlock -... |
120 121 |
/* prevent taking the spurious DNA fault with padlock. */ ts_state = irq_ts_save(); |
6c8332751 [CRYPTO] padlock:... |
122 |
asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" /* rep xsha1 */ |
bbbee4679 crypto: padlock -... |
123 |
: \ |
faae89088 crypto: padlock -... |
124 125 |
: "c"((unsigned long)state.count + count), \ "a"((unsigned long)state.count), \ |
bbbee4679 crypto: padlock -... |
126 |
"S"(in), "D"(result)); |
e49140120 crypto: padlock -... |
127 |
irq_ts_restore(ts_state); |
6c8332751 [CRYPTO] padlock:... |
128 129 |
padlock_output_block((uint32_t *)result, (uint32_t *)out, 5); |
bbbee4679 crypto: padlock -... |
130 131 132 |
out: return err; |
6c8332751 [CRYPTO] padlock:... |
133 |
} |
bbbee4679 crypto: padlock -... |
134 135 136 137 138 139 140 141 142 |
static int padlock_sha1_final(struct shash_desc *desc, u8 *out) { u8 buf[4]; return padlock_sha1_finup(desc, buf, 0, out); } static int padlock_sha256_finup(struct shash_desc *desc, const u8 *in, unsigned int count, u8 *out) |
6c8332751 [CRYPTO] padlock:... |
143 144 145 146 |
{ /* We can't store directly to *out as it may be unaligned. */ /* BTW Don't reduce the buffer size below 128 Bytes! * PadLock microcode needs it that big. */ |
4c6ab3ee4 crypto: padlock-s... |
147 148 149 |
char buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__ ((aligned(STACK_ALIGN))); char *result = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); |
bbbee4679 crypto: padlock -... |
150 151 152 153 |
struct padlock_sha_desc *dctx = shash_desc_ctx(desc); struct sha256_state state; unsigned int space; unsigned int leftover; |
e49140120 crypto: padlock -... |
154 |
int ts_state; |
bbbee4679 crypto: padlock -... |
155 |
int err; |
6c8332751 [CRYPTO] padlock:... |
156 |
|
bbbee4679 crypto: padlock -... |
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; err = crypto_shash_export(&dctx->fallback, &state); if (err) goto out; if (state.count + count > ULONG_MAX) return crypto_shash_finup(&dctx->fallback, in, count, out); leftover = ((state.count - 1) & (SHA256_BLOCK_SIZE - 1)) + 1; space = SHA256_BLOCK_SIZE - leftover; if (space) { if (count > space) { err = crypto_shash_update(&dctx->fallback, in, space) ?: crypto_shash_export(&dctx->fallback, &state); if (err) goto out; count -= space; in += space; } else { memcpy(state.buf + leftover, in, count); in = state.buf; count += leftover; |
e9b25f16c crypto: padlock -... |
179 |
state.count &= ~(SHA1_BLOCK_SIZE - 1); |
bbbee4679 crypto: padlock -... |
180 181 182 183 |
} } memcpy(result, &state.state, SHA256_DIGEST_SIZE); |
6c8332751 [CRYPTO] padlock:... |
184 |
|
e49140120 crypto: padlock -... |
185 186 |
/* prevent taking the spurious DNA fault with padlock. */ ts_state = irq_ts_save(); |
6c8332751 [CRYPTO] padlock:... |
187 |
asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" /* rep xsha256 */ |
bbbee4679 crypto: padlock -... |
188 |
: \ |
faae89088 crypto: padlock -... |
189 190 |
: "c"((unsigned long)state.count + count), \ "a"((unsigned long)state.count), \ |
bbbee4679 crypto: padlock -... |
191 |
"S"(in), "D"(result)); |
e49140120 crypto: padlock -... |
192 |
irq_ts_restore(ts_state); |
6c8332751 [CRYPTO] padlock:... |
193 194 |
padlock_output_block((uint32_t *)result, (uint32_t *)out, 8); |
bbbee4679 crypto: padlock -... |
195 196 197 |
out: return err; |
6c8332751 [CRYPTO] padlock:... |
198 |
} |
bbbee4679 crypto: padlock -... |
199 |
static int padlock_sha256_final(struct shash_desc *desc, u8 *out) |
6c8332751 [CRYPTO] padlock:... |
200 |
{ |
bbbee4679 crypto: padlock -... |
201 |
u8 buf[4]; |
6c8332751 [CRYPTO] padlock:... |
202 |
|
bbbee4679 crypto: padlock -... |
203 |
return padlock_sha256_finup(desc, buf, 0, out); |
6c8332751 [CRYPTO] padlock:... |
204 |
} |
6010439f4 [CRYPTO] padlock:... |
205 |
static int padlock_cra_init(struct crypto_tfm *tfm) |
6c8332751 [CRYPTO] padlock:... |
206 |
{ |
bbbee4679 crypto: padlock -... |
207 |
struct crypto_shash *hash = __crypto_shash_cast(tfm); |
6010439f4 [CRYPTO] padlock:... |
208 |
const char *fallback_driver_name = tfm->__crt_alg->cra_name; |
bbbee4679 crypto: padlock -... |
209 |
struct padlock_sha_ctx *ctx = crypto_tfm_ctx(tfm); |
7d0246082 crypto: padlock -... |
210 211 |
struct crypto_shash *fallback_tfm; int err = -ENOMEM; |
6010439f4 [CRYPTO] padlock:... |
212 |
|
6c8332751 [CRYPTO] padlock:... |
213 |
/* Allocate a fallback and abort if it failed. */ |
7d0246082 crypto: padlock -... |
214 215 |
fallback_tfm = crypto_alloc_shash(fallback_driver_name, 0, CRYPTO_ALG_NEED_FALLBACK); |
6010439f4 [CRYPTO] padlock:... |
216 |
if (IS_ERR(fallback_tfm)) { |
6c8332751 [CRYPTO] padlock:... |
217 218 219 |
printk(KERN_WARNING PFX "Fallback driver '%s' could not be loaded! ", fallback_driver_name); |
7d0246082 crypto: padlock -... |
220 |
err = PTR_ERR(fallback_tfm); |
bbbee4679 crypto: padlock -... |
221 |
goto out; |
6c8332751 [CRYPTO] padlock:... |
222 |
} |
bbbee4679 crypto: padlock -... |
223 224 |
ctx->fallback = fallback_tfm; hash->descsize += crypto_shash_descsize(fallback_tfm); |
6c8332751 [CRYPTO] padlock:... |
225 |
return 0; |
7d0246082 crypto: padlock -... |
226 |
|
7d0246082 crypto: padlock -... |
227 228 |
out: return err; |
6c8332751 [CRYPTO] padlock:... |
229 |
} |
6c8332751 [CRYPTO] padlock:... |
230 231 |
static void padlock_cra_exit(struct crypto_tfm *tfm) { |
bbbee4679 crypto: padlock -... |
232 |
struct padlock_sha_ctx *ctx = crypto_tfm_ctx(tfm); |
7d0246082 crypto: padlock -... |
233 |
|
bbbee4679 crypto: padlock -... |
234 |
crypto_free_shash(ctx->fallback); |
6c8332751 [CRYPTO] padlock:... |
235 |
} |
bbbee4679 crypto: padlock -... |
236 237 238 239 240 241 |
static struct shash_alg sha1_alg = { .digestsize = SHA1_DIGEST_SIZE, .init = padlock_sha_init, .update = padlock_sha_update, .finup = padlock_sha1_finup, .final = padlock_sha1_final, |
a8d7ac279 crypto: padlock-s... |
242 243 |
.export = padlock_sha_export, .import = padlock_sha_import, |
bbbee4679 crypto: padlock -... |
244 |
.descsize = sizeof(struct padlock_sha_desc), |
a8d7ac279 crypto: padlock-s... |
245 |
.statesize = sizeof(struct sha1_state), |
bbbee4679 crypto: padlock -... |
246 247 248 249 250 251 252 253 254 255 256 |
.base = { .cra_name = "sha1", .cra_driver_name = "sha1-padlock", .cra_priority = PADLOCK_CRA_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_SHASH | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct padlock_sha_ctx), .cra_module = THIS_MODULE, .cra_init = padlock_cra_init, .cra_exit = padlock_cra_exit, |
6c8332751 [CRYPTO] padlock:... |
257 258 |
} }; |
bbbee4679 crypto: padlock -... |
259 260 261 262 263 264 |
static struct shash_alg sha256_alg = { .digestsize = SHA256_DIGEST_SIZE, .init = padlock_sha_init, .update = padlock_sha_update, .finup = padlock_sha256_finup, .final = padlock_sha256_final, |
a8d7ac279 crypto: padlock-s... |
265 266 |
.export = padlock_sha_export, .import = padlock_sha_import, |
bbbee4679 crypto: padlock -... |
267 |
.descsize = sizeof(struct padlock_sha_desc), |
a8d7ac279 crypto: padlock-s... |
268 |
.statesize = sizeof(struct sha256_state), |
bbbee4679 crypto: padlock -... |
269 270 271 272 273 274 275 276 277 278 279 |
.base = { .cra_name = "sha256", .cra_driver_name = "sha256-padlock", .cra_priority = PADLOCK_CRA_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_SHASH | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct padlock_sha_ctx), .cra_module = THIS_MODULE, .cra_init = padlock_cra_init, .cra_exit = padlock_cra_exit, |
6c8332751 [CRYPTO] padlock:... |
280 281 |
} }; |
6c8332751 [CRYPTO] padlock:... |
282 283 284 285 286 |
static int __init padlock_init(void) { int rc = -ENODEV; if (!cpu_has_phe) { |
b43e726b3 crypto: padlock -... |
287 288 |
printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected. "); |
6c8332751 [CRYPTO] padlock:... |
289 290 291 292 |
return -ENODEV; } if (!cpu_has_phe_enabled) { |
b43e726b3 crypto: padlock -... |
293 294 |
printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange... "); |
6c8332751 [CRYPTO] padlock:... |
295 296 |
return -ENODEV; } |
bbbee4679 crypto: padlock -... |
297 |
rc = crypto_register_shash(&sha1_alg); |
6c8332751 [CRYPTO] padlock:... |
298 299 |
if (rc) goto out; |
bbbee4679 crypto: padlock -... |
300 |
rc = crypto_register_shash(&sha256_alg); |
6c8332751 [CRYPTO] padlock:... |
301 302 303 304 305 306 307 308 309 |
if (rc) goto out_unreg1; printk(KERN_NOTICE PFX "Using VIA PadLock ACE for SHA1/SHA256 algorithms. "); return 0; out_unreg1: |
bbbee4679 crypto: padlock -... |
310 |
crypto_unregister_shash(&sha1_alg); |
6c8332751 [CRYPTO] padlock:... |
311 312 313 314 315 316 317 318 |
out: printk(KERN_ERR PFX "VIA PadLock SHA1/SHA256 initialization failed. "); return rc; } static void __exit padlock_fini(void) { |
bbbee4679 crypto: padlock -... |
319 320 |
crypto_unregister_shash(&sha1_alg); crypto_unregister_shash(&sha256_alg); |
6c8332751 [CRYPTO] padlock:... |
321 322 323 324 325 326 327 328 |
} module_init(padlock_init); module_exit(padlock_fini); MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support."); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Ludvig"); |
a760a6656 crypto: api - Fix... |
329 330 |
MODULE_ALIAS("sha1-all"); MODULE_ALIAS("sha256-all"); |
6c8332751 [CRYPTO] padlock:... |
331 332 |
MODULE_ALIAS("sha1-padlock"); MODULE_ALIAS("sha256-padlock"); |