diff options
Diffstat (limited to 'target/linux/patches/2.6.35/ocf-20100325.patch')
-rw-r--r-- | target/linux/patches/2.6.35/ocf-20100325.patch | 87546 |
1 files changed, 87546 insertions, 0 deletions
diff --git a/target/linux/patches/2.6.35/ocf-20100325.patch b/target/linux/patches/2.6.35/ocf-20100325.patch new file mode 100644 index 000000000..ccd6961f0 --- /dev/null +++ b/target/linux/patches/2.6.35/ocf-20100325.patch @@ -0,0 +1,87546 @@ +diff -Nur linux-2.6.35.orig/crypto/Kconfig linux-2.6.35/crypto/Kconfig +--- linux-2.6.35.orig/crypto/Kconfig 2010-08-02 00:11:14.000000000 +0200 ++++ linux-2.6.35/crypto/Kconfig 2010-08-05 22:02:04.194867989 +0200 +@@ -832,3 +832,6 @@ + source "drivers/crypto/Kconfig" + + endif # if CRYPTO ++ ++source "crypto/ocf/Kconfig" ++ +diff -Nur linux-2.6.35.orig/crypto/Makefile linux-2.6.35/crypto/Makefile +--- linux-2.6.35.orig/crypto/Makefile 2010-08-02 00:11:14.000000000 +0200 ++++ linux-2.6.35/crypto/Makefile 2010-08-05 22:02:04.963633162 +0200 +@@ -86,6 +86,8 @@ + obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o + obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o + ++obj-$(CONFIG_OCF_OCF) += ocf/ ++ + # + # generic algorithms and the async_tx api + # +diff -Nur linux-2.6.35.orig/crypto/ocf/c7108/aes-7108.c linux-2.6.35/crypto/ocf/c7108/aes-7108.c +--- linux-2.6.35.orig/crypto/ocf/c7108/aes-7108.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.35/crypto/ocf/c7108/aes-7108.c 2010-08-05 22:02:05.163624527 +0200 +@@ -0,0 +1,839 @@ ++/* ++ * Copyright (C) 2006 Micronas USA ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * Effort sponsored in part by the Defense Advanced Research Projects ++ * Agency (DARPA) and Air Force Research Laboratory, Air Force ++ * Materiel Command, USAF, under agreement number F30602-01-2-0537. ++ * ++ */ ++ ++//#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/list.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include <linux/wait.h> ++#include <linux/crypto.h> ++#include <linux/mm.h> ++#include <linux/skbuff.h> ++#include <linux/random.h> ++#include <asm/io.h> ++#include <asm/delay.h> ++//#include <asm/scatterlist.h> ++#include <linux/scatterlist.h> ++#include <linux/dma-mapping.h> ++#include <linux/highmem.h> ++#include <cryptodev.h> ++#include <uio.h> ++#include <aes-7108.h> ++ ++/* Runtime mode */ ++static int c7108_crypto_mode = C7108_AES_CTRL_MODE_CTR; ++//static int c7108_crypto_mode = C7108_AES_CTRL_MODE_CBC; ++ ++static int32_t c7108_id = -1; ++static struct cipher_7108 **c7108_sessions = NULL; ++static u_int32_t c7108_sesnum = 0; ++static unsigned long iobar; ++ ++/* Crypto entry points */ ++static int c7108_process(void *, struct cryptop *, int); ++static int c7108_newsession(void *, u_int32_t *, struct cryptoini *); ++static int c7108_freesession(void *, u_int64_t); ++ ++/* Globals */ ++static int debug = 0; ++static spinlock_t csr_mutex; ++ ++/* Generic controller-based lock */ ++#define AES_LOCK()\ ++ spin_lock(&csr_mutex) ++#define AES_UNLOCK()\ ++ spin_unlock(&csr_mutex) ++ ++/* 7108 AES register access */ ++#define c7108_reg_wr8(a,d) iowrite8(d, (void*)(iobar+(a))) ++#define c7108_reg_wr16(a,d) iowrite16(d, (void*)(iobar+(a))) ++#define c7108_reg_wr32(a,d) iowrite32(d, (void*)(iobar+(a))) ++#define c7108_reg_rd8(a) ioread8((void*)(iobar+(a))) ++#define c7108_reg_rd16(a) ioread16((void*)(iobar+(a))) ++#define c7108_reg_rd32(a) ioread32((void*)(iobar+(a))) ++ ++static int ++c7108_xlate_key(int klen, u8* k8ptr, u32* k32ptr) ++{ ++ int i, nw=0; ++ nw = ((klen >= 256) ? 8 : (klen >= 192) ? 6 : 4); ++ for ( i = 0; i < nw; i++) { ++ k32ptr[i] = (k8ptr[i+3] << 24) | (k8ptr[i+2] << 16) | ++ (k8ptr[i+1] << 8) | k8ptr[i]; ++ ++ } ++ return 0; ++} ++ ++static int ++c7108_cache_key(int klen, u32* k32ptr, u8* k8ptr) ++{ ++ int i, nb=0; ++ u8* ptr = (u8*)k32ptr; ++ nb = ((klen >= 256) ? 32 : (klen >= 192) ? 24 : 16); ++ for ( i = 0; i < nb; i++) ++ k8ptr[i] = ptr[i]; ++ return 0; ++} ++ ++static int ++c7108_aes_setup_dma(u32 src, u32 dst, u32 len) ++{ ++ if (len < 16) { ++ printk("len < 16\n"); ++ return -10; ++ } ++ if (len % 16) { ++ printk("len not multiple of 16\n"); ++ return -11; ++ } ++ c7108_reg_wr16(C7108_AES_DMA_SRC0_LO, (u16) src); ++ c7108_reg_wr16(C7108_AES_DMA_SRC0_HI, (u16)((src & 0xffff0000) >> 16)); ++ c7108_reg_wr16(C7108_AES_DMA_DST0_LO, (u16) dst); ++ c7108_reg_wr16(C7108_AES_DMA_DST0_HI, (u16)((dst & 0xffff0000) >> 16)); ++ c7108_reg_wr16(C7108_AES_DMA_LEN, (u16) ((len / 16) - 1)); ++ ++ return 0; ++} ++ ++static int ++c7108_aes_set_hw_iv(u8 iv[16]) ++{ ++ c7108_reg_wr16(C7108_AES_IV0_LO, (u16) ((iv[1] << 8) | iv[0])); ++ c7108_reg_wr16(C7108_AES_IV0_HI, (u16) ((iv[3] << 8) | iv[2])); ++ c7108_reg_wr16(C7108_AES_IV1_LO, (u16) ((iv[5] << 8) | iv[4])); ++ c7108_reg_wr16(C7108_AES_IV1_HI, (u16) ((iv[7] << 8) | iv[6])); ++ c7108_reg_wr16(C7108_AES_IV2_LO, (u16) ((iv[9] << 8) | iv[8])); ++ c7108_reg_wr16(C7108_AES_IV2_HI, (u16) ((iv[11] << 8) | iv[10])); ++ c7108_reg_wr16(C7108_AES_IV3_LO, (u16) ((iv[13] << 8) | iv[12])); ++ c7108_reg_wr16(C7108_AES_IV3_HI, (u16) ((iv[15] << 8) | iv[14])); ++ ++ return 0; ++} ++ ++static void ++c7108_aes_read_dkey(u32 * dkey) ++{ ++ dkey[0] = (c7108_reg_rd16(C7108_AES_EKEY0_HI) << 16) | ++ c7108_reg_rd16(C7108_AES_EKEY0_LO); ++ dkey[1] = (c7108_reg_rd16(C7108_AES_EKEY1_HI) << 16) | ++ c7108_reg_rd16(C7108_AES_EKEY1_LO); ++ dkey[2] = (c7108_reg_rd16(C7108_AES_EKEY2_HI) << 16) | ++ c7108_reg_rd16(C7108_AES_EKEY2_LO); ++ dkey[3] = (c7108_reg_rd16(C7108_AES_EKEY3_HI) << 16) | ++ c7108_reg_rd16(C7108_AES_EKEY3_LO); ++ dkey[4] = (c7108_reg_rd16(C7108_AES_EKEY4_HI) << 16) | ++ c7108_reg_rd16(C7108_AES_EKEY4_LO); ++ dkey[5] = (c7108_reg_rd16(C7108_AES_EKEY5_HI) << 16) | ++ c7108_reg_rd16(C7108_AES_EKEY5_LO); ++ dkey[6] = (c7108_reg_rd16(C7108_AES_EKEY6_HI) << 16) | ++ c7108_reg_rd16(C7108_AES_EKEY6_LO); ++ dkey[7] = (c7108_reg_rd16(C7108_AES_EKEY7_HI) << 16) | ++ c7108_reg_rd16(C7108_AES_EKEY7_LO); ++} ++ ++static int ++c7108_aes_cipher(int op, ++ u32 dst, ++ u32 src, ++ u32 len, ++ int klen, ++ u16 mode, ++ u32 key[8], ++ u8 iv[16]) ++{ ++ int rv = 0, cnt=0; ++ u16 ctrl = 0, stat = 0; ++ ++ AES_LOCK(); ++ ++ /* Setup key length */ ++ if (klen == 128) { ++ ctrl |= C7108_AES_KEY_LEN_128; ++ } else if (klen == 192) { ++ ctrl |= C7108_AES_KEY_LEN_192; ++ } else if (klen == 256) { ++ ctrl |= C7108_AES_KEY_LEN_256; ++ } else { ++ AES_UNLOCK(); ++ return -3; ++ } ++ ++ /* Check opcode */ ++ if (C7108_AES_ENCRYPT == op) { ++ ctrl |= C7108_AES_ENCRYPT; ++ } else if (C7108_AES_DECRYPT == op) { ++ ctrl |= C7108_AES_DECRYPT; ++ } else { ++ AES_UNLOCK(); ++ return -4; ++ } ++ ++ /* check mode */ ++ if ( (mode != C7108_AES_CTRL_MODE_CBC) && ++ (mode != C7108_AES_CTRL_MODE_CFB) && ++ (mode != C7108_AES_CTRL_MODE_OFB) && ++ (mode != C7108_AES_CTRL_MODE_CTR) && ++ (mode != C7108_AES_CTRL_MODE_ECB) ) { ++ AES_UNLOCK(); ++ return -5; ++ } ++ ++ /* Now set mode */ ++ ctrl |= mode; ++ ++ /* For CFB, OFB, and CTR, neither backward key ++ * expansion nor key inversion is required. ++ */ ++ if ( (C7108_AES_DECRYPT == op) && ++ (C7108_AES_CTRL_MODE_CBC == mode || ++ C7108_AES_CTRL_MODE_ECB == mode ) ){ ++ ++ /* Program Key */ ++ c7108_reg_wr16(C7108_AES_KEY0_LO, (u16) key[4]); ++ c7108_reg_wr16(C7108_AES_KEY0_HI, (u16) (key[4] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY1_LO, (u16) key[5]); ++ c7108_reg_wr16(C7108_AES_KEY1_HI, (u16) (key[5] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY2_LO, (u16) key[6]); ++ c7108_reg_wr16(C7108_AES_KEY2_HI, (u16) (key[6] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY3_LO, (u16) key[7]); ++ c7108_reg_wr16(C7108_AES_KEY3_HI, (u16) (key[7] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY6_LO, (u16) key[2]); ++ c7108_reg_wr16(C7108_AES_KEY6_HI, (u16) (key[2] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY7_LO, (u16) key[3]); ++ c7108_reg_wr16(C7108_AES_KEY7_HI, (u16) (key[3] >> 16)); ++ ++ ++ if (192 == klen) { ++ c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[7]); ++ c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[7] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[7]); ++ c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[7] >> 16)); ++ ++ } else if (256 == klen) { ++ /* 256 */ ++ c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[0]); ++ c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[0] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[1]); ++ c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[1] >> 16)); ++ ++ } ++ ++ } else { ++ /* Program Key */ ++ c7108_reg_wr16(C7108_AES_KEY0_LO, (u16) key[0]); ++ c7108_reg_wr16(C7108_AES_KEY0_HI, (u16) (key[0] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY1_LO, (u16) key[1]); ++ c7108_reg_wr16(C7108_AES_KEY1_HI, (u16) (key[1] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY2_LO, (u16) key[2]); ++ c7108_reg_wr16(C7108_AES_KEY2_HI, (u16) (key[2] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY3_LO, (u16) key[3]); ++ c7108_reg_wr16(C7108_AES_KEY3_HI, (u16) (key[3] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[4]); ++ c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[4] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[5]); ++ c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[5] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY6_LO, (u16) key[6]); ++ c7108_reg_wr16(C7108_AES_KEY6_HI, (u16) (key[6] >> 16)); ++ c7108_reg_wr16(C7108_AES_KEY7_LO, (u16) key[7]); ++ c7108_reg_wr16(C7108_AES_KEY7_HI, (u16) (key[7] >> 16)); ++ ++ } ++ ++ /* Set IV always */ ++ c7108_aes_set_hw_iv(iv); ++ ++ /* Program DMA addresses */ ++ if ((rv = c7108_aes_setup_dma(src, dst, len)) < 0) { ++ AES_UNLOCK(); ++ return rv; ++ } ++ ++ ++ /* Start AES cipher */ ++ c7108_reg_wr16(C7108_AES_CTRL, ctrl | C7108_AES_GO); ++ ++ //printk("Ctrl: 0x%x\n", ctrl | C7108_AES_GO); ++ do { ++ /* TODO: interrupt mode */ ++ // printk("aes_stat=0x%x\n", stat); ++ //udelay(100); ++ } while ((cnt++ < 1000000) && ++ !((stat=c7108_reg_rd16(C7108_AES_CTRL))&C7108_AES_OP_DONE)); ++ ++ ++ if ((mode == C7108_AES_CTRL_MODE_ECB)|| ++ (mode == C7108_AES_CTRL_MODE_CBC)) { ++ /* Save out key when the lock is held ... */ ++ c7108_aes_read_dkey(key); ++ } ++ ++ AES_UNLOCK(); ++ return 0; ++ ++} ++ ++/* ++ * Generate a new crypto device session. ++ */ ++static int ++c7108_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri) ++{ ++ struct cipher_7108 **swd; ++ u_int32_t i; ++ char *algo; ++ int mode, xfm_type; ++ ++ dprintk("%s()\n", __FUNCTION__); ++ if (sid == NULL || cri == NULL) { ++ dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__); ++ return EINVAL; ++ } ++ ++ if (c7108_sessions) { ++ for (i = 1; i < c7108_sesnum; i++) ++ if (c7108_sessions[i] == NULL) ++ break; ++ } else ++ i = 1; /* NB: to silence compiler warning */ ++ ++ if (c7108_sessions == NULL || i == c7108_sesnum) { ++ if (c7108_sessions == NULL) { ++ i = 1; /* We leave c7108_sessions[0] empty */ ++ c7108_sesnum = CRYPTO_SW_SESSIONS; ++ } else ++ c7108_sesnum *= 2; ++ ++ swd = kmalloc(c7108_sesnum * sizeof(struct cipher_7108 *), ++ GFP_ATOMIC); ++ if (swd == NULL) { ++ /* Reset session number */ ++ if (c7108_sesnum == CRYPTO_SW_SESSIONS) ++ c7108_sesnum = 0; ++ else ++ c7108_sesnum /= 2; ++ dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__); ++ return ENOBUFS; ++ } ++ memset(swd, 0, c7108_sesnum * sizeof(struct cipher_7108 *)); ++ ++ /* Copy existing sessions */ ++ if (c7108_sessions) { ++ memcpy(swd, c7108_sessions, ++ (c7108_sesnum / 2) * sizeof(struct cipher_7108 *)); ++ kfree(c7108_sessions); ++ } ++ ++ c7108_sessions = swd; ++ ++ } ++ ++ swd = &c7108_sessions[i]; ++ *sid = i; ++ ++ while (cri) { ++ *swd = (struct cipher_7108 *) ++ kmalloc(sizeof(struct cipher_7108), GFP_ATOMIC); ++ if (*swd == NULL) { ++ c7108_freesession(NULL, i); ++ dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__); ++ return ENOBUFS; ++ } ++ memset(*swd, 0, sizeof(struct cipher_7108)); ++ ++ algo = NULL; ++ mode = 0; ++ xfm_type = HW_TYPE_CIPHER; ++ ++ switch (cri->cri_alg) { ++ ++ case CRYPTO_AES_CBC: ++ algo = "aes"; ++ mode = CRYPTO_TFM_MODE_CBC; ++ c7108_crypto_mode = C7108_AES_CTRL_MODE_CBC; ++ break; ++#if 0 ++ case CRYPTO_AES_CTR: ++ algo = "aes_ctr"; ++ mode = CRYPTO_TFM_MODE_CBC; ++ c7108_crypto_mode = C7108_AES_CTRL_MODE_CTR; ++ break; ++ case CRYPTO_AES_ECB: ++ algo = "aes_ecb"; ++ mode = CRYPTO_TFM_MODE_CBC; ++ c7108_crypto_mode = C7108_AES_CTRL_MODE_ECB; ++ break; ++ case CRYPTO_AES_OFB: ++ algo = "aes_ofb"; ++ mode = CRYPTO_TFM_MODE_CBC; ++ c7108_crypto_mode = C7108_AES_CTRL_MODE_OFB; ++ break; ++ case CRYPTO_AES_CFB: ++ algo = "aes_cfb"; ++ mode = CRYPTO_TFM_MODE_CBC; ++ c7108_crypto_mode = C7108_AES_CTRL_MODE_CFB; ++ break; ++#endif ++ default: ++ printk("unsupported crypto algorithm: %d\n", ++ cri->cri_alg); ++ return -EINVAL; ++ break; ++ } ++ ++ ++ if (!algo || !*algo) { ++ printk("cypher_7108_crypto: Unknown algo 0x%x\n", ++ cri->cri_alg); ++ c7108_freesession(NULL, i); ++ return EINVAL; ++ } ++ ++ if (xfm_type == HW_TYPE_CIPHER) { ++ if (debug) { ++ dprintk("%s key:", __FUNCTION__); ++ for (i = 0; i < (cri->cri_klen + 7) / 8; i++) ++ dprintk("%s0x%02x", (i % 8) ? " " : "\n ", ++ cri->cri_key[i]); ++ dprintk("\n"); ++ } ++ ++ } else if (xfm_type == SW_TYPE_HMAC || ++ xfm_type == SW_TYPE_HASH) { ++ printk("cypher_7108_crypto: HMAC unsupported!\n"); ++ return -EINVAL; ++ c7108_freesession(NULL, i); ++ } else { ++ printk("cypher_7108_crypto: " ++ "Unhandled xfm_type %d\n", xfm_type); ++ c7108_freesession(NULL, i); ++ return EINVAL; ++ } ++ ++ (*swd)->cri_alg = cri->cri_alg; ++ (*swd)->xfm_type = xfm_type; ++ ++ cri = cri->cri_next; ++ swd = &((*swd)->next); ++ } ++ return 0; ++} ++ ++/* ++ * Free a session. ++ */ ++static int ++c7108_freesession(void *arg, u_int64_t tid) ++{ ++ struct cipher_7108 *swd; ++ u_int32_t sid = CRYPTO_SESID2LID(tid); ++ ++ dprintk("%s()\n", __FUNCTION__); ++ if (sid > c7108_sesnum || c7108_sessions == NULL || ++ c7108_sessions[sid] == NULL) { ++ dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__); ++ return(EINVAL); ++ } ++ ++ /* Silently accept and return */ ++ if (sid == 0) ++ return(0); ++ ++ while ((swd = c7108_sessions[sid]) != NULL) { ++ c7108_sessions[sid] = swd->next; ++ kfree(swd); ++ } ++ return 0; ++} ++ ++/* ++ * Process a hardware request. ++ */ ++static int ++c7108_process(void *arg, struct cryptop *crp, int hint) ++{ ++ struct cryptodesc *crd; ++ struct cipher_7108 *sw; ++ u_int32_t lid; ++ int type; ++ u32 hwkey[8]; ++ ++#define SCATTERLIST_MAX 16 ++ struct scatterlist sg[SCATTERLIST_MAX]; ++ int sg_num, sg_len, skip; ++ struct sk_buff *skb = NULL; ++ struct uio *uiop = NULL; ++ ++ dprintk("%s()\n", __FUNCTION__); ++ /* Sanity check */ ++ if (crp == NULL) { ++ dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__); ++ return EINVAL; ++ } ++ ++ crp->crp_etype = 0; ++ ++ if (crp->crp_desc == NULL || crp->crp_buf == NULL) { ++ dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__); ++ crp->crp_etype = EINVAL; ++ goto done; ++ } ++ ++ lid = crp->crp_sid & 0xffffffff; ++ if (lid >= c7108_sesnum || lid == 0 || c7108_sessions == NULL || ++ c7108_sessions[lid] == NULL) { ++ crp->crp_etype = ENOENT; ++ dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__); ++ goto done; ++ } ++ ++ /* ++ * do some error checking outside of the loop for SKB and IOV ++ * processing this leaves us with valid skb or uiop pointers ++ * for later ++ */ ++ if (crp->crp_flags & CRYPTO_F_SKBUF) { ++ skb = (struct sk_buff *) crp->crp_buf; ++ if (skb_shinfo(skb)->nr_frags >= SCATTERLIST_MAX) { ++ printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", ++ __FILE__, __LINE__, ++ skb_shinfo(skb)->nr_frags); ++ goto done; ++ } ++ } else if (crp->crp_flags & CRYPTO_F_IOV) { ++ uiop = (struct uio *) crp->crp_buf; ++ if (uiop->uio_iovcnt > SCATTERLIST_MAX) { ++ printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", ++ __FILE__, __LINE__, ++ uiop->uio_iovcnt); ++ goto done; ++ } ++ } ++ ++ /* Go through crypto descriptors, processing as we go */ ++ for (crd = crp->crp_desc; crd; crd = crd->crd_next) { ++ /* ++ * Find the crypto context. ++ * ++ * XXX Note that the logic here prevents us from having ++ * XXX the same algorithm multiple times in a session ++ * XXX (or rather, we can but it won't give us the right ++ * XXX results). To do that, we'd need some way of differentiating ++ * XXX between the various instances of an algorithm (so we can ++ * XXX locate the correct crypto context). ++ */ ++ for (sw = c7108_sessions[lid]; ++ sw && sw->cri_alg != crd->crd_alg; ++ sw = sw->next) ++ ; ++ ++ /* No such context ? */ ++ if (sw == NULL) { ++ crp->crp_etype = EINVAL; ++ dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__); ++ goto done; ++ } ++ ++ skip = crd->crd_skip; ++ ++ /* ++ * setup the SG list skip from the start of the buffer ++ */ ++ memset(sg, 0, sizeof(sg)); ++ if (crp->crp_flags & CRYPTO_F_SKBUF) { ++ int i, len; ++ type = CRYPTO_BUF_SKBUF; ++ ++ sg_num = 0; ++ sg_len = 0; ++ ++ if (skip < skb_headlen(skb)) { ++ //sg[sg_num].page = virt_to_page(skb->data + skip); ++ //sg[sg_num].offset = offset_in_page(skb->data + skip); ++ len = skb_headlen(skb) - skip; ++ if (len + sg_len > crd->crd_len) ++ len = crd->crd_len - sg_len; ++ //sg[sg_num].length = len; ++ sg_set_page(&sg[sg_num], virt_to_page(skb->data + skip), len, offset_in_page(skb->data + skip)); ++ sg_len += sg[sg_num].length; ++ sg_num++; ++ skip = 0; ++ } else ++ skip -= skb_headlen(skb); ++ ++ for (i = 0; sg_len < crd->crd_len && ++ i < skb_shinfo(skb)->nr_frags && ++ sg_num < SCATTERLIST_MAX; i++) { ++ if (skip < skb_shinfo(skb)->frags[i].size) { ++ //sg[sg_num].page = skb_shinfo(skb)->frags[i].page; ++ //sg[sg_num].offset = skb_shinfo(skb)->frags[i].page_offset + skip; ++ len = skb_shinfo(skb)->frags[i].size - skip; ++ if (len + sg_len > crd->crd_len) ++ len = crd->crd_len - sg_len; ++ //sg[sg_num].length = len; ++ sg_set_page(&sg[sg_num], skb_shinfo(skb)->frags[i].page, len, skb_shinfo(skb)->frags[i].page_offset + skip); ++ sg_len += sg[sg_num].length; ++ sg_num++; ++ skip = 0; ++ } else ++ skip -= skb_shinfo(skb)->frags[i].size; ++ } ++ } else if (crp->crp_flags & CRYPTO_F_IOV) { ++ int len; ++ type = CRYPTO_BUF_IOV; ++ sg_len = 0; ++ for (sg_num = 0; sg_len < crd->crd_len && ++ sg_num < uiop->uio_iovcnt && ++ sg_num < SCATTERLIST_MAX; sg_num++) { ++ if (skip < uiop->uio_iov[sg_num].iov_len) { ++ //sg[sg_num].page = virt_to_page(uiop->uio_iov[sg_num].iov_base+skip); ++ //sg[sg_num].offset = offset_in_page(uiop->uio_iov[sg_num].iov_base+skip); ++ len = uiop->uio_iov[sg_num].iov_len - skip; ++ if (len + sg_len > crd->crd_len) ++ len = crd->crd_len - sg_len; ++ //sg[sg_num].length = len; ++ sg_set_page(&sg[sg_num], virt_to_page(uiop->uio_iov[sg_num].iov_base+skip), len, offset_in_page(uiop->uio_iov[sg_num].iov_base+skip)); ++ sg_len += sg[sg_num].length; ++ skip = 0; ++ } else ++ skip -= uiop->uio_iov[sg_num].iov_len; ++ } ++ } else { ++ type = CRYPTO_BUF_CONTIG; ++ //sg[0].page = virt_to_page(crp->crp_buf + skip); ++ //sg[0].offset = offset_in_page(crp->crp_buf + skip); ++ sg_len = (crp->crp_ilen - skip); ++ if (sg_len > crd->crd_len) ++ sg_len = crd->crd_len; ++ //sg[0].length = sg_len; ++ sg_set_page(&sg[0], virt_to_page(crp->crp_buf + skip), sg_len, offset_in_page(crp->crp_buf + skip)); ++ sg_num = 1; ++ } ++ ++ ++ switch (sw->xfm_type) { ++ ++ case HW_TYPE_CIPHER: { ++ ++ unsigned char iv[64]; ++ unsigned char *ivp = iv; ++ int i; ++ int ivsize = 16; /* fixed for AES */ ++ int blocksize = 16; /* fixed for AES */ ++ ++ if (sg_len < blocksize) { ++ crp->crp_etype = EINVAL; ++ dprintk("%s,%d: EINVAL len %d < %d\n", ++ __FILE__, __LINE__, ++ sg_len, ++ blocksize); ++ goto done; ++ } ++ ++ if (ivsize > sizeof(iv)) { ++ crp->crp_etype = EINVAL; ++ dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__); ++ goto done; ++ } ++ ++ if (crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */ ++ ++ if (crd->crd_flags & CRD_F_IV_EXPLICIT) { ++ ivp = crd->crd_iv; ++ } else { ++ get_random_bytes(ivp, ivsize); ++ } ++ /* ++ * do we have to copy the IV back to the buffer ? ++ */ ++ if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) { ++ crypto_copyback(crp->crp_buf, ++ crd->crd_inject, ++ ivsize, ++ (caddr_t)ivp); ++ } ++ ++ c7108_xlate_key(crd->crd_klen, ++ (u8*)crd->crd_key, (u32*)hwkey); ++ ++ /* Encrypt SG list */ ++ for (i = 0; i < sg_num; i++) { ++ sg[i].dma_address = ++ dma_map_single(NULL, ++ kmap(sg_page(&sg[i])) + sg[i].offset, sg_len, DMA_BIDIRECTIONAL); ++#if 0 ++ printk("sg[%d]:0x%08x, off 0x%08x " ++ "kmap 0x%08x phys 0x%08x\n", ++ i, sg[i].page, sg[i].offset, ++ kmap(sg[i].page) + sg[i].offset, ++ sg[i].dma_address); ++#endif ++ c7108_aes_cipher(C7108_AES_ENCRYPT, ++ sg[i].dma_address, ++ sg[i].dma_address, ++ sg_len, ++ crd->crd_klen, ++ c7108_crypto_mode, ++ hwkey, ++ ivp); ++ ++ if ((c7108_crypto_mode == C7108_AES_CTRL_MODE_CBC)|| ++ (c7108_crypto_mode == C7108_AES_CTRL_MODE_ECB)) { ++ /* Read back expanded key and cache it in key ++ * context. ++ * NOTE: for ECB/CBC modes only (not CTR, CFB, OFB) ++ * where you set the key once. ++ */ ++ c7108_cache_key(crd->crd_klen, ++ (u32*)hwkey, (u8*)crd->crd_key); ++#if 0 ++ printk("%s expanded key:", __FUNCTION__); ++ for (i = 0; i < (crd->crd_klen + 7) / 8; i++) ++ printk("%s0x%02x", (i % 8) ? " " : "\n ", ++ crd->crd_key[i]); ++ printk("\n"); ++#endif ++ } ++ } ++ } ++ else { /*decrypt */ ++ ++ if (crd->crd_flags & CRD_F_IV_EXPLICIT) { ++ ivp = crd->crd_iv; ++ } else { ++ crypto_copydata(crp->crp_buf, crd->crd_inject, ++ ivsize, (caddr_t)ivp); ++ } ++ ++ c7108_xlate_key(crd->crd_klen, ++ (u8*)crd->crd_key, (u32*)hwkey); ++ ++ /* Decrypt SG list */ ++ for (i = 0; i < sg_num; i++) { ++ sg[i].dma_address = ++ dma_map_single(NULL, ++ kmap(sg_page(&sg[i])) + sg[i].offset, ++ sg_len, DMA_BIDIRECTIONAL); ++ ++#if 0 ++ printk("sg[%d]:0x%08x, off 0x%08x " ++ "kmap 0x%08x phys 0x%08x\n", ++ i, sg[i].page, sg[i].offset, ++ kmap(sg[i].page) + sg[i].offset, ++ sg[i].dma_address); ++#endif ++ c7108_aes_cipher(C7108_AES_DECRYPT, ++ sg[i].dma_address, ++ sg[i].dma_address, ++ sg_len, ++ crd->crd_klen, ++ c7108_crypto_mode, ++ hwkey, ++ ivp); ++ } ++ } ++ } break; ++ case SW_TYPE_HMAC: ++ case SW_TYPE_HASH: ++ crp->crp_etype = EINVAL; ++ goto done; ++ break; ++ ++ case SW_TYPE_COMP: ++ crp->crp_etype = EINVAL; ++ goto done; ++ break; ++ ++ default: ++ /* Unknown/unsupported algorithm */ ++ dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__); ++ crp->crp_etype = EINVAL; ++ goto done; ++ } ++ } ++ ++done: ++ crypto_done(crp); ++ return 0; ++} ++ ++static struct { ++ softc_device_decl sc_dev; ++} a7108dev; ++ ++static device_method_t a7108_methods = { ++/* crypto device methods */ ++ DEVMETHOD(cryptodev_newsession, c7108_newsession), ++ DEVMETHOD(cryptodev_freesession, c7108_freesession), ++ DEVMETHOD(cryptodev_process, c7108_process), ++ DEVMETHOD(cryptodev_kprocess, NULL) ++}; ++ ++static int ++cypher_7108_crypto_init(void) ++{ ++ dprintk("%s(%p)\n", __FUNCTION__, cypher_7108_crypto_init); ++ ++ iobar = (unsigned long)ioremap(CCU_AES_REG_BASE, 0x4000); ++ printk("7108: AES @ 0x%08x (0x%08x phys) %s mode\n", ++ iobar, CCU_AES_REG_BASE, ++ c7108_crypto_mode & C7108_AES_CTRL_MODE_CBC ? "CBC" : ++ c7108_crypto_mode & C7108_AES_CTRL_MODE_ECB ? "ECB" : ++ c7108_crypto_mode & C7108_AES_CTRL_MODE_CTR ? "CTR" : ++ c7108_crypto_mode & C7108_AES_CTRL_MODE_CFB ? "CFB" : ++ c7108_crypto_mode & C7108_AES_CTRL_MODE_OFB ? "OFB" : "???"); ++ csr_mutex = SPIN_LOCK_UNLOCKED; ++ ++ memset(&a7108dev, 0, sizeof(a7108dev)); ++ softc_device_init(&a7108dev, "aes7108", 0, a7108_methods); ++ ++ c7108_id = crypto_get_driverid(softc_get_device(&a7108dev), CRYPTOCAP_F_HARDWARE); ++ if (c7108_id < 0) ++ panic("7108: crypto device cannot initialize!"); ++ ++// crypto_register(c7108_id, CRYPTO_AES_CBC, 0, 0, c7108_newsession, c7108_freesession, c7108_process, NULL); ++ crypto_register(c7108_id, CRYPTO_AES_CBC, 0, 0); ++ ++ return(0); ++} ++ ++static void ++cypher_7108_crypto_exit(void) ++{ ++ dprintk("%s()\n", __FUNCTION__); ++ crypto_unregister_all(c7108_id); ++ c7108_id = -1; ++} ++ ++module_init(cypher_7108_crypto_init); ++module_exit(cypher_7108_crypto_exit); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("Cypher 7108 Crypto (OCF module for kernel crypto)"); +diff -Nur linux-2.6.35.orig/crypto/ocf/c7108/aes-7108.h linux-2.6.35/crypto/ocf/c7108/aes-7108.h +--- linux-2.6.35.orig/crypto/ocf/c7108/aes-7108.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.35/crypto/ocf/c7108/aes-7108.h 2010-08-05 22:02:05.803621195 +0200 +@@ -0,0 +1,134 @@ ++/* ++ * Copyright (C) 2006 Micronas USA ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * Effort sponsored in part by the Defense Advanced Research Projects ++ * Agency (DARPA) and Air Force Research Laboratory, Air Force ++ * Materiel Command, USAF, under agreement number F30602-01-2-0537. ++ * ++ */ ++ ++#ifndef __AES_7108_H__ ++#define __AES_7108_H__ ++ ++/* Cypher 7108 AES Controller Hardware */ ++#define CCU_REG_BASE 0x1b500000 ++#define CCU_AES_REG_BASE (CCU_REG_BASE + 0x100) ++#define C7108_AES_KEY0_LO (0x0000) ++#define C7108_AES_KEY0_HI (0x0004) ++#define C7108_AES_KEY1_LO (0x0008) ++#define C7108_AES_KEY1_HI (0x000c) ++#define C7108_AES_KEY2_LO (0x0010) ++#define C7108_AES_KEY2_HI (0x0014) ++#define C7108_AES_KEY3_LO (0x0018) ++#define C7108_AES_KEY3_HI (0x001c) ++#define C7108_AES_KEY4_LO (0x0020) ++#define C7108_AES_KEY4_HI (0x0024) ++#define C7108_AES_KEY5_LO (0x0028) ++#define C7108_AES_KEY5_HI (0x002c) ++#define C7108_AES_KEY6_LO (0x0030) ++#define C7108_AES_KEY6_HI (0x0034) ++#define C7108_AES_KEY7_LO (0x0038) ++#define C7108_AES_KEY7_HI (0x003c) ++#define C7108_AES_IV0_LO (0x0040) ++#define C7108_AES_IV0_HI (0x0044) ++#define C7108_AES_IV1_LO (0x0048) ++#define C7108_AES_IV1_HI (0x004c) ++#define C7108_AES_IV2_LO (0x0050) ++#define C7108_AES_IV2_HI (0x0054) ++#define C7108_AES_IV3_LO (0x0058) ++#define C7108_AES_IV3_HI (0x005c) ++ ++#define C7108_AES_DMA_SRC0_LO (0x0068) /* Bits 0:15 */ ++#define C7108_AES_DMA_SRC0_HI (0x006c) /* Bits 27:16 */ ++#define C7108_AES_DMA_DST0_LO (0x0070) /* Bits 0:15 */ ++#define C7108_AES_DMA_DST0_HI (0x0074) /* Bits 27:16 */ ++#define C7108_AES_DMA_LEN (0x0078) /*Bytes:(Count+1)x16 */ ++ ++/* AES/Copy engine control register */ ++#define C7108_AES_CTRL (0x007c) /* AES control */ ++#define C7108_AES_CTRL_RS (1<<0) /* Which set of src/dst to use */ ++ ++/* AES Cipher mode, controlled by setting Bits 2:0 */ ++#define C7108_AES_CTRL_MODE_CBC 0 ++#define C7108_AES_CTRL_MODE_CFB (1<<0) ++#define C7108_AES_CTRL_MODE_OFB (1<<1) ++#define C7108_AES_CTRL_MODE_CTR ((1<<0)|(1<<1)) ++#define C7108_AES_CTRL_MODE_ECB (1<<2) ++ ++/* AES Key length , Bits 5:4 */ ++#define C7108_AES_KEY_LEN_128 0 /* 00 */ ++#define C7108_AES_KEY_LEN_192 (1<<4) /* 01 */ ++#define C7108_AES_KEY_LEN_256 (1<<5) /* 10 */ ++ ++/* AES Operation (crypt/decrypt), Bit 3 */ ++#define C7108_AES_DECRYPT (1<<3) /* Clear for encrypt */ ++#define C7108_AES_ENCRYPT 0 ++#define C7108_AES_INTR (1<<13) /* Set on done trans from 0->1*/ ++#define C7108_AES_GO (1<<14) /* Run */ ++#define C7108_AES_OP_DONE (1<<15) /* Set when complete */ ++ ++ ++/* Expanded key registers */ ++#define C7108_AES_EKEY0_LO (0x0080) ++#define C7108_AES_EKEY0_HI (0x0084) ++#define C7108_AES_EKEY1_LO (0x0088) ++#define C7108_AES_EKEY1_HI (0x008c) ++#define C7108_AES_EKEY2_LO (0x0090) ++#define C7108_AES_EKEY2_HI (0x0094) ++#define C7108_AES_EKEY3_LO (0x0098) ++#define C7108_AES_EKEY3_HI (0x009c) ++#define C7108_AES_EKEY4_LO (0x00a0) ++#define C7108_AES_EKEY4_HI (0x00a4) ++#define C7108_AES_EKEY5_LO (0x00a8) ++#define C7108_AES_EKEY5_HI (0x00ac) ++#define C7108_AES_EKEY6_LO (0x00b0) ++#define C7108_AES_EKEY6_HI (0x00b4) ++#define C7108_AES_EKEY7_LO (0x00b8) ++#define C7108_AES_EKEY7_HI (0x00bc) ++#define C7108_AES_OK (0x00fc) /* Reset: "OK" */ ++ ++#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) ++ ++/* Software session entry */ ++ ++#define HW_TYPE_CIPHER 0 ++#define SW_TYPE_HMAC 1 ++#define SW_TYPE_AUTH2 2 ++#define SW_TYPE_HASH 3 ++#define SW_TYPE_COMP 4 ++ ++struct cipher_7108 { ++ int xfm_type; ++ int cri_alg; ++ union { ++ struct { ++ char sw_key[HMAC_BLOCK_LEN]; ++ int sw_klen; ++ int sw_authlen; ++ } hmac; ++ } u; ++ struct cipher_7108 *next; ++}; ++ ++ ++ ++#endif /* __C7108_AES_7108_H__ */ +diff -Nur linux-2.6.35.orig/crypto/ocf/c7108/Makefile linux-2.6.35/crypto/ocf/c7108/Makefile +--- linux-2.6.35.orig/crypto/ocf/c7108/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.35/crypto/ocf/c7108/Makefile 2010-08-05 22:02:06.013994644 +0200 +@@ -0,0 +1,12 @@ ++# for SGlinux builds ++-include $(ROOTDIR)/modules/.config ++ ++obj-$(CONFIG_OCF_C7108) += aes-7108.o ++ ++obj ?= . ++EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/ ++ ++ifdef TOPDIR ++-include $(TOPDIR)/Rules.make ++endif ++ +diff -Nur linux-2.6.35.orig/crypto/ocf/Config.in linux-2.6.35/crypto/ocf/Config.in +--- linux-2.6.35.orig/crypto/ocf/Config.in 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.35/crypto/ocf/Config.in 2010-08-05 22:02:06.243623186 +0200 +@@ -0,0 +1,36 @@ ++############################################################################# ++ ++mainmenu_option next_comment ++comment 'OCF Configuration' ++tristate 'OCF (Open Cryptograhic Framework)' CONFIG_OCF_OCF ++dep_mbool ' enable fips RNG checks (fips check on RNG data before use)' \ ++ CONFIG_OCF_FIPS $CONFIG_OCF_OCF ++dep_mbool ' enable harvesting entropy for /dev/random' \ ++ CONFIG_OCF_RANDOMHARVEST $CONFIG_OCF_OCF ++dep_tristate ' cryptodev (user space support)' \ ++ CONFIG_OCF_CRYPTODEV $CONFIG_OCF_OCF ++dep_tristate ' cryptosoft (software crypto engine)' \ ++ CONFIG_OCF_CRYPTOSOFT $CONFIG_OCF_OCF ++dep_tristate ' safenet (HW crypto engine)' \ ++ CONFIG_OCF_SAFE $CONFIG_OCF_OCF ++dep_tristate ' IXP4xx (HW crypto engine)' \ ++ CONFIG_OCF_IXP4XX $CONFIG_OCF_OCF ++dep_mbool ' Enable IXP4xx HW to perform SHA1 and MD5 hashing (very slow)' \ |