forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto update from Herbert Xu: "Here is the crypto update for 3.20: - Added 192/256-bit key support to aesni GCM. - Added MIPS OCTEON MD5 support. - Fixed hwrng starvation and race conditions. - Added note that memzero_explicit is not a subsitute for memset. - Added user-space interface for crypto_rng. - Misc fixes" * git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (71 commits) crypto: tcrypt - do not allocate iv on stack for aead speed tests crypto: testmgr - limit IV copy length in aead tests crypto: tcrypt - fix buflen reminder calculation crypto: testmgr - mark rfc4106(gcm(aes)) as fips_allowed crypto: caam - fix resource clean-up on error path for caam_jr_init crypto: caam - pair irq map and dispose in the same function crypto: ccp - terminate ccp_support array with empty element crypto: caam - remove unused local variable crypto: caam - remove dead code crypto: caam - don't emit ICV check failures to dmesg hwrng: virtio - drop extra empty line crypto: replace scatterwalk_sg_next with sg_next crypto: atmel - Free memory in error path crypto: doc - remove colons in comments crypto: seqiv - Ensure that IV size is at least 8 bytes crypto: cts - Weed out non-CBC algorithms MAINTAINERS: add linux-crypto to hw random crypto: cts - Remove bogus use of seqiv crypto: qat - don't need qat_auth_state struct crypto: algif_rng - fix sparse non static symbol warning ...
- Loading branch information
Showing
70 changed files
with
1,785 additions
and
709 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4434,6 +4434,7 @@ F: include/linux/hwmon*.h | |
HARDWARE RANDOM NUMBER GENERATOR CORE | ||
M: Matt Mackall <[email protected]> | ||
M: Herbert Xu <[email protected]> | ||
L: [email protected] | ||
S: Odd fixes | ||
F: Documentation/hw_random.txt | ||
F: drivers/char/hw_random/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# | ||
# OCTEON-specific crypto modules. | ||
# | ||
|
||
obj-y += octeon-crypto.o | ||
|
||
obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file "COPYING" in the main directory of this archive | ||
* for more details. | ||
* | ||
* Copyright (C) 2004-2012 Cavium Networks | ||
*/ | ||
|
||
#include <asm/cop2.h> | ||
#include <linux/module.h> | ||
#include <linux/interrupt.h> | ||
|
||
#include "octeon-crypto.h" | ||
|
||
/** | ||
* Enable access to Octeon's COP2 crypto hardware for kernel use. Wrap any | ||
* crypto operations in calls to octeon_crypto_enable/disable in order to make | ||
* sure the state of COP2 isn't corrupted if userspace is also performing | ||
* hardware crypto operations. Allocate the state parameter on the stack. | ||
* Preemption must be disabled to prevent context switches. | ||
* | ||
* @state: Pointer to state structure to store current COP2 state in. | ||
* | ||
* Returns: Flags to be passed to octeon_crypto_disable() | ||
*/ | ||
unsigned long octeon_crypto_enable(struct octeon_cop2_state *state) | ||
{ | ||
int status; | ||
unsigned long flags; | ||
|
||
local_irq_save(flags); | ||
status = read_c0_status(); | ||
write_c0_status(status | ST0_CU2); | ||
if (KSTK_STATUS(current) & ST0_CU2) { | ||
octeon_cop2_save(&(current->thread.cp2)); | ||
KSTK_STATUS(current) &= ~ST0_CU2; | ||
status &= ~ST0_CU2; | ||
} else if (status & ST0_CU2) { | ||
octeon_cop2_save(state); | ||
} | ||
local_irq_restore(flags); | ||
return status & ST0_CU2; | ||
} | ||
EXPORT_SYMBOL_GPL(octeon_crypto_enable); | ||
|
||
/** | ||
* Disable access to Octeon's COP2 crypto hardware in the kernel. This must be | ||
* called after an octeon_crypto_enable() before any context switch or return to | ||
* userspace. | ||
* | ||
* @state: Pointer to COP2 state to restore | ||
* @flags: Return value from octeon_crypto_enable() | ||
*/ | ||
void octeon_crypto_disable(struct octeon_cop2_state *state, | ||
unsigned long crypto_flags) | ||
{ | ||
unsigned long flags; | ||
|
||
local_irq_save(flags); | ||
if (crypto_flags & ST0_CU2) | ||
octeon_cop2_restore(state); | ||
else | ||
write_c0_status(read_c0_status() & ~ST0_CU2); | ||
local_irq_restore(flags); | ||
} | ||
EXPORT_SYMBOL_GPL(octeon_crypto_disable); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file "COPYING" in the main directory of this archive | ||
* for more details. | ||
* | ||
* Copyright (C) 2012-2013 Cavium Inc., All Rights Reserved. | ||
* | ||
* MD5 instruction definitions added by Aaro Koskinen <[email protected]>. | ||
* | ||
*/ | ||
#ifndef __LINUX_OCTEON_CRYPTO_H | ||
#define __LINUX_OCTEON_CRYPTO_H | ||
|
||
#include <linux/sched.h> | ||
#include <asm/mipsregs.h> | ||
|
||
#define OCTEON_CR_OPCODE_PRIORITY 300 | ||
|
||
extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); | ||
extern void octeon_crypto_disable(struct octeon_cop2_state *state, | ||
unsigned long flags); | ||
|
||
/* | ||
* Macros needed to implement MD5: | ||
*/ | ||
|
||
/* | ||
* The index can be 0-1. | ||
*/ | ||
#define write_octeon_64bit_hash_dword(value, index) \ | ||
do { \ | ||
__asm__ __volatile__ ( \ | ||
"dmtc2 %[rt],0x0048+" STR(index) \ | ||
: \ | ||
: [rt] "d" (value)); \ | ||
} while (0) | ||
|
||
/* | ||
* The index can be 0-1. | ||
*/ | ||
#define read_octeon_64bit_hash_dword(index) \ | ||
({ \ | ||
u64 __value; \ | ||
\ | ||
__asm__ __volatile__ ( \ | ||
"dmfc2 %[rt],0x0048+" STR(index) \ | ||
: [rt] "=d" (__value) \ | ||
: ); \ | ||
\ | ||
__value; \ | ||
}) | ||
|
||
/* | ||
* The index can be 0-6. | ||
*/ | ||
#define write_octeon_64bit_block_dword(value, index) \ | ||
do { \ | ||
__asm__ __volatile__ ( \ | ||
"dmtc2 %[rt],0x0040+" STR(index) \ | ||
: \ | ||
: [rt] "d" (value)); \ | ||
} while (0) | ||
|
||
/* | ||
* The value is the final block dword (64-bit). | ||
*/ | ||
#define octeon_md5_start(value) \ | ||
do { \ | ||
__asm__ __volatile__ ( \ | ||
"dmtc2 %[rt],0x4047" \ | ||
: \ | ||
: [rt] "d" (value)); \ | ||
} while (0) | ||
|
||
#endif /* __LINUX_OCTEON_CRYPTO_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
/* | ||
* Cryptographic API. | ||
* | ||
* MD5 Message Digest Algorithm (RFC1321). | ||
* | ||
* Adapted for OCTEON by Aaro Koskinen <[email protected]>. | ||
* | ||
* Based on crypto/md5.c, which is: | ||
* | ||
* Derived from cryptoapi implementation, originally based on the | ||
* public domain implementation written by Colin Plumb in 1993. | ||
* | ||
* Copyright (c) Cryptoapi developers. | ||
* Copyright (c) 2002 James Morris <[email protected]> | ||
* | ||
* 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. | ||
*/ | ||
|
||
#include <crypto/md5.h> | ||
#include <linux/init.h> | ||
#include <linux/types.h> | ||
#include <linux/module.h> | ||
#include <linux/string.h> | ||
#include <asm/byteorder.h> | ||
#include <linux/cryptohash.h> | ||
#include <asm/octeon/octeon.h> | ||
#include <crypto/internal/hash.h> | ||
|
||
#include "octeon-crypto.h" | ||
|
||
/* | ||
* We pass everything as 64-bit. OCTEON can handle misaligned data. | ||
*/ | ||
|
||
static void octeon_md5_store_hash(struct md5_state *ctx) | ||
{ | ||
u64 *hash = (u64 *)ctx->hash; | ||
|
||
write_octeon_64bit_hash_dword(hash[0], 0); | ||
write_octeon_64bit_hash_dword(hash[1], 1); | ||
} | ||
|
||
static void octeon_md5_read_hash(struct md5_state *ctx) | ||
{ | ||
u64 *hash = (u64 *)ctx->hash; | ||
|
||
hash[0] = read_octeon_64bit_hash_dword(0); | ||
hash[1] = read_octeon_64bit_hash_dword(1); | ||
} | ||
|
||
static void octeon_md5_transform(const void *_block) | ||
{ | ||
const u64 *block = _block; | ||
|
||
write_octeon_64bit_block_dword(block[0], 0); | ||
write_octeon_64bit_block_dword(block[1], 1); | ||
write_octeon_64bit_block_dword(block[2], 2); | ||
write_octeon_64bit_block_dword(block[3], 3); | ||
write_octeon_64bit_block_dword(block[4], 4); | ||
write_octeon_64bit_block_dword(block[5], 5); | ||
write_octeon_64bit_block_dword(block[6], 6); | ||
octeon_md5_start(block[7]); | ||
} | ||
|
||
static int octeon_md5_init(struct shash_desc *desc) | ||
{ | ||
struct md5_state *mctx = shash_desc_ctx(desc); | ||
|
||
mctx->hash[0] = cpu_to_le32(0x67452301); | ||
mctx->hash[1] = cpu_to_le32(0xefcdab89); | ||
mctx->hash[2] = cpu_to_le32(0x98badcfe); | ||
mctx->hash[3] = cpu_to_le32(0x10325476); | ||
mctx->byte_count = 0; | ||
|
||
return 0; | ||
} | ||
|
||
static int octeon_md5_update(struct shash_desc *desc, const u8 *data, | ||
unsigned int len) | ||
{ | ||
struct md5_state *mctx = shash_desc_ctx(desc); | ||
const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); | ||
struct octeon_cop2_state state; | ||
unsigned long flags; | ||
|
||
mctx->byte_count += len; | ||
|
||
if (avail > len) { | ||
memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), | ||
data, len); | ||
return 0; | ||
} | ||
|
||
memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, | ||
avail); | ||
|
||
local_bh_disable(); | ||
preempt_disable(); | ||
flags = octeon_crypto_enable(&state); | ||
octeon_md5_store_hash(mctx); | ||
|
||
octeon_md5_transform(mctx->block); | ||
data += avail; | ||
len -= avail; | ||
|
||
while (len >= sizeof(mctx->block)) { | ||
octeon_md5_transform(data); | ||
data += sizeof(mctx->block); | ||
len -= sizeof(mctx->block); | ||
} | ||
|
||
octeon_md5_read_hash(mctx); | ||
octeon_crypto_disable(&state, flags); | ||
preempt_enable(); | ||
local_bh_enable(); | ||
|
||
memcpy(mctx->block, data, len); | ||
|
||
return 0; | ||
} | ||
|
||
static int octeon_md5_final(struct shash_desc *desc, u8 *out) | ||
{ | ||
struct md5_state *mctx = shash_desc_ctx(desc); | ||
const unsigned int offset = mctx->byte_count & 0x3f; | ||
char *p = (char *)mctx->block + offset; | ||
int padding = 56 - (offset + 1); | ||
struct octeon_cop2_state state; | ||
unsigned long flags; | ||
|
||
*p++ = 0x80; | ||
|
||
local_bh_disable(); | ||
preempt_disable(); | ||
flags = octeon_crypto_enable(&state); | ||
octeon_md5_store_hash(mctx); | ||
|
||
if (padding < 0) { | ||
memset(p, 0x00, padding + sizeof(u64)); | ||
octeon_md5_transform(mctx->block); | ||
p = (char *)mctx->block; | ||
padding = 56; | ||
} | ||
|
||
memset(p, 0, padding); | ||
mctx->block[14] = cpu_to_le32(mctx->byte_count << 3); | ||
mctx->block[15] = cpu_to_le32(mctx->byte_count >> 29); | ||
octeon_md5_transform(mctx->block); | ||
|
||
octeon_md5_read_hash(mctx); | ||
octeon_crypto_disable(&state, flags); | ||
preempt_enable(); | ||
local_bh_enable(); | ||
|
||
memcpy(out, mctx->hash, sizeof(mctx->hash)); | ||
memset(mctx, 0, sizeof(*mctx)); | ||
|
||
return 0; | ||
} | ||
|
||
static int octeon_md5_export(struct shash_desc *desc, void *out) | ||
{ | ||
struct md5_state *ctx = shash_desc_ctx(desc); | ||
|
||
memcpy(out, ctx, sizeof(*ctx)); | ||
return 0; | ||
} | ||
|
||
static int octeon_md5_import(struct shash_desc *desc, const void *in) | ||
{ | ||
struct md5_state *ctx = shash_desc_ctx(desc); | ||
|
||
memcpy(ctx, in, sizeof(*ctx)); | ||
return 0; | ||
} | ||
|
||
static struct shash_alg alg = { | ||
.digestsize = MD5_DIGEST_SIZE, | ||
.init = octeon_md5_init, | ||
.update = octeon_md5_update, | ||
.final = octeon_md5_final, | ||
.export = octeon_md5_export, | ||
.import = octeon_md5_import, | ||
.descsize = sizeof(struct md5_state), | ||
.statesize = sizeof(struct md5_state), | ||
.base = { | ||
.cra_name = "md5", | ||
.cra_driver_name= "octeon-md5", | ||
.cra_priority = OCTEON_CR_OPCODE_PRIORITY, | ||
.cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
.cra_blocksize = MD5_HMAC_BLOCK_SIZE, | ||
.cra_module = THIS_MODULE, | ||
} | ||
}; | ||
|
||
static int __init md5_mod_init(void) | ||
{ | ||
if (!octeon_has_crypto()) | ||
return -ENOTSUPP; | ||
return crypto_register_shash(&alg); | ||
} | ||
|
||
static void __exit md5_mod_fini(void) | ||
{ | ||
crypto_unregister_shash(&alg); | ||
} | ||
|
||
module_init(md5_mod_init); | ||
module_exit(md5_mod_fini); | ||
|
||
MODULE_LICENSE("GPL"); | ||
MODULE_DESCRIPTION("MD5 Message Digest Algorithm (OCTEON)"); | ||
MODULE_AUTHOR("Aaro Koskinen <[email protected]>"); |
Oops, something went wrong.