2007-05-21 23:43:50

by M.T.Reddy

[permalink] [raw]
Subject: Re: Looking for comments on a Linux driver for HW accelerated Kasumi+F8+F9 algorithms.

On 5/21/07, M. T. Reddy <[email protected]> wrote:
> Please comment on the following patch for HW accelerated kasumi + f8 and f8 encryption engine.
> Regards,
> Marri
> ------------------------------------- patch ---------------------------------
> --- may03_denx/drivers/crypto/Kconfig 2007-05-03 08:39: 15.000000000 -0700
> +++ 0323_denx/drivers/crypto/Kconfig 2007-05-15 13:40:56.789633768 -0700
> @@ -37,6 +37,13 @@
> If unsure say M. The compiled module will be
> called padlock-aes.ko
>
> +config CRYPTO_KASUMI
> + bool "Support for Kasumi driver"
> + depends on 440EPX
> + default N
> + help
> + Used in encrypting and decrypting data.
> +
> config CRYPTO_DEV_PADLOCK_SHA
> tristate "PadLock driver for SHA1 and SHA256 algorithms"
> depends on CRYPTO_DEV_PADLOCK
> --- may03_denx/drivers/crypto/Makefile 2007-05-03 08:39:15.000000000 -0700
> +++ 0323_denx/drivers/crypto/Makefile 2007-04-25 13:39:52.000000000 -0700
> @@ -2,3 +2,4 @@
> obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
> obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
> obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
> +obj-$(CONFIG_KASUMI_CRYPTO) +=kasumi.o
> --- may03_denx/drivers/crypto/kasumi.h 1969-12-31 16:00: 00.000000000 -0800
> +++ 0323_denx/drivers/crypto/kasumi.h 2007-05-15 15:16:27.046502312 -0700
> @@ -0,0 +1,122 @@
> +/**********************************************************************
> + *
> + * kasumi.h
> + * Cryptographic Driver APIs.
> + *
> + * Support for Kasumi F8 and F9 hardware crypto engine.
> + * author: [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.
> + *
> + *
> + *
> + * DISCLAIMER
> + *
> + * This software is provided 'as is' with no explicit or implied warranties
> + * in respect of its properties, including, but not limited to, correctness
> + * and/or fitness for purpose.
> + * ---------------------------------------------------------------------------
> + */
> +#define MULTIPLE_DATA_ENC 1
> +
> +#define KASUMI_TEST 0
> +
> +/* Dynamic major number */
> +#define KASUMI_MAJOR 0
> +
> +/* IOCTL numbers */
> +#define KASUMI_IOCTL_ENCRYPT 0x100
> +#define KASUMI_IOCTL_DECRYPT 0x101
> +#define KASUMI_IOCTL_F8_MODE 0x102
> +#define KASUMI_IOCTL_F9_MODE 0x103
> +
> +#define SDR0_SRST1 0x201
> +#define DCR_PLB4A0 0x81
> +#define DCR_UIC0_SR 0xC0
> +#define DCR_UIC0_ER 0xC2
> +
> +/* Need to disable READ pipeline to avoid hang on PLB bus */
> +#define DISABLE_RD_PIPE_LINE 0xf9ffffff
> +#define KASUMI_RESET_MSK 0x00002000
> +#define KASU0_BASE 0x0E0180000ULL
> +
> +#define KASU0_DATA_IN0 0x0
> +#define KASU0_DATA_OUT0 0x0
> +#define KASU0_DATA_IN1 0x4
> +#define KASU0_DATA_OUT1 0x4
> +#define KASU0_CTRL 0x8
> +#define KASU0_STATUS 0x8
> +#define KASU0_MODE 0xc
> +#define KASU0_KEY0 0x10
> +#define KASU0_KEY1 0x14
> +#define KASU0_KEY2 0x18
> +#define KASU0_KEY3 0x1c
> +#define KASU0_COUNT 0x20
> +#define KASU0_CONFIG 0x24
> +#define KASU0_FRESH 0x28
> +
> +#define KASUMI_DEC_MODE 0x02000000
> +#define KASUMI_ENC_MODE 0x03000000
> +#define KASUMI_F8_ENC_MODE 0x05000000
> +#define KASUMI_F8_DEC_MODE 0x04000000
> +#define KASUMI_F9_ENC_MODE 0x09000000
> +#define KASUMI_F9_DEC_MODE 0x08000000
> +
> +#define KASUMI_DATA_READY 0x01000000
> +
> +#define KASUMI_VAL_KEYS 0x04000000
> +#define KASUMI_VAL_MODE 0x02000000
> +#define KASUMI_VAL_DATA 0x08000000
> +#define KASUMI_VAL_CFG 0x10000000
> +#define KASUMI_VAL_COUNT 0x20000000
> +#define KASUMI_VAL_FRESH 0x40000000
> +
> +#define kasumi_byte_swap(x) ((((uint)x & 0xff000000) >> 24) | \
> + (((uint)x & 0x00ff0000) >> 8) | \
> + (((uint)x & 0x0000ff00) << 8) | \
> + (((uint)x & 0x000000ff) << 24))
> +
> +struct kasumi_desc {
> + uint mode;
> + uint count;
> + uint config;
> + uint fresh;
> + uint key0;
> + uint key1;
> + uint key2;
> + uint key3;
> + uint *data_in;
> + uint *data_out;
> +};
> +struct kasumi_regs{
> + uint *ctrl;
> + uint *status;
> + uint *mode;
> + uint *key0;
> + uint *key1;
> + uint *key2;
> + uint *key3;
> + uint *data_in0;
> + uint *data_in1;
> + uint *data_out0;
> + uint *data_out1;
> + uint *count;
> + uint *config;
> + uint *fresh;
> +};
> +
> +struct kasumi_f8_f9_desc {
> + struct kasumi_desc kd;
> + uint len;
> + uint bearer;
> + uint direction;
> +};
> +int kasumi_f9_encrypt(struct kasumi_desc *test, uint len, uint direction);
> +int kasumi_f8_encrypt(struct kasumi_desc *test, uint len, uint bearer,
> + uint direction);
> +int kasumi_decrypt(struct kasumi_desc *test);
> +int kasumi_encrypt(struct kasumi_desc *test);
> --- may03_denx/drivers/crypto/kasumi.c 1969-12-31 16:00:00.000000000 -0800
> +++ 0323_denx/drivers/crypto/kasumi.c 2007-05-15 15:16: 27.045502464 -0700
> @@ -0,0 +1,898 @@
> +/*
> + * Cryptographic Driver APIs.
> + *
> + * Support for Kasumi F8 and F9 hardware crypto engine.
> + * author: [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.
> + *
> + *
> + *
> + * DISCLAIMER
> + *
> + * This software is provided 'as is' with no explicit or implied warranties
> + * in respect of its properties, including, but not limited to, correctness
> + * and/or fitness for purpose.
> + * ---------------------------------------------------------------------------
> + */
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <asm/io.h>
> +#include <linux/fcntl.h>
> +#include <linux/cdev.h>
> +#include <linux/seq_file.h>
> +#include <linux/fs.h> /* everything... */
> +
> +#include <asm/system.h>
> +#include <asm/uaccess.h> /* copy_*_user */
> +
> +#include <asm/ibm44x.h>
> +#include "kasumi.h "
> +
> +static int kasumi_major = KASUMI_MAJOR;
> +static uint data_in[512], data_out[512];
> +static uint *kasumi_base;
> +static struct kasumi_regs kreg;
> +
> +#ifdef KASUMI_TEST
> +/*
> +** Function to test KASUMI encrypt and decrypt modes
> +*/
> +static int kasumi_test(void)
> +{
> + struct kasumi_desc test_in, test_out;
> + uint data_in0[2], data_in1[2], data_out0[2], data_out1[2];
> +
> + test_in.key0 = 0x9F45D62B;
> + test_in.key1 = 0x00B3C582;
> + test_in.key2 = 0x10492C95;
> + test_in.key3 = 0x48FF8148;
> + data_in0[0] = 0xEA024714;
> + data_in0[1] = 0xAD5C4D84;
> + test_in.data_in = &data_in0[0];
> + test_in.data_out = &data_out0[0];
> +
> + printk(KERN_INFO "Encryption test\n");
> + kasumi_encrypt(&test_in);
> +
> + test_out.key0 = 0x9F45D62B;
> + test_out.key1 = 0x00B3C582;
> + test_out.key2 = 0x10492C95;
> + test_out.key3 = 0x48FF8148;
> + test_out.data_in = &data_in1[0];
> + test_out.data_out = &data_out1[0];
> + test_out.data_in[0] = data_out0[0];
> + test_out.data_in[1] = data_out0[1];
> +
> + printk(KERN_INFO "Decryption test\n");
> + kasumi_decrypt(&test_out);
> + printk(KERN_INFO "data_out0[0]=0x%x\n", data_out0[0]);
> + printk(KERN_INFO "data_out0[1]=0x%x\n", data_out0[1]);
> + printk(KERN_INFO "data_out1[0]=0x%x\n", data_out1[0]);
> + printk(KERN_INFO "data_out1[1]=0x%x\n", data_out1[1]);
> +
> + if (data_in0[0] == data_out1[0])
> + printk(KERN_INFO " Data 0 matched\n");
> + else
> + printk(KERN_INFO " Data 0 NOT matched\n");
> + if (data_in0[1] == data_out1[1])
> + printk(KERN_INFO " Data 1 matched\n");
> + else
> + printk(KERN_INFO " Data 1 NOT matched\n");
> + return 0;
> +}
> +
> +/*
> +** Function to test F* mode of encryption
> +*/
> +static void kasumi_test_f8_1(void)
> +{
> + int len = 0x31E, bearer = 0xc, direction = 1;
> + struct kasumi_desc test_in;
> + struct kasumi_desc test_out;
> + int i = 0;
> + uint data_in[32] = {
> + 0x7EC61272, 0x743BF161, 0x4726446A, 0x6C38CED1,
> + 0x66F6CA76, 0xEB543004, 0x4286346C, 0xEF130F92,
> + 0x922B0345, 0x0D3A9975, 0xE5BD2EA0, 0xEB55AD8E,
> + 0x1B199E3E, 0xC4316020, 0xE9A1B285, 0xE7627953,
> + 0x59B7BDFD, 0x39BEF4B2, 0x484583D5, 0xAFE082AE,
> + 0xE638BF5F, 0xD5A60619, 0x3901A08F, 0x4AB41AAB, 0x9B134880
> + };
> + uint data_cmp[32] = {
> + 0xD1E2DE70, 0xEEF86C69, 0x64FB542B, 0xC2D460AA,
> + 0xBFAA10A4, 0xA093262B, 0x7D199E70, 0x6FC2D489,
> + 0x15532969, 0x10F3A973, 0x012682E4, 0x1C4E2B02,
> + 0xBE2017B7, 0x253BBF93, 0x09DE5819, 0xCB42E819,
> + 0x56F4C99B, 0xC9765CAF, 0x53B1D0BB, 0x8279826A,
> + 0xDBBC5522, 0xE915C120, 0xA618A5A7, 0xF5E89708, 0x9339650F
> + };
> + uint data_out0[32];
> + uint data_out1[32];
> +
> + test_in.key0 = 0x2BD6459F;
> + test_in.key1 = 0x82C5B300;
> + test_in.key2 = 0x952C4910;
> + test_in.key3 = 0x4881FF48;
> +
> + test_in.count = 0x72A4F20F;
> +
> + printk(KERN_INFO "in CFG=0x%x\n", test_in.config);
> + test_in.data_in = &data_in[0];
> + test_in.data_out = &data_out0[0];
> + kasumi_f8_encrypt(&test_in, len, bearer, direction);
> +
> + i = 0;
> + for (i = 0; i < 32; i++) {
> + if (data_out0[i] != data_cmp[i])
> + printk(KERN_INFO
> + "data MISS match data recieved=0x%x expected =0x%x\n\nn",
> + data_out0[i], data_cmp[i]);
> + else
> + printk(KERN_INFO "data MATCHED\n");
> +
> + }
> +}
> +
> +/*
> +** Function to test F9 mode of encryption
> +*/
> +static void kasumi_test_f9(void)
> +{
> + struct kasumi_desc test_in;
> + int i = 0;
> + uint direction = 0, len = 189;
> + uint data_in[6] = {
> + 0x6B227737,
> + 0x296F393C,
> + 0x8079353E,
> + 0xDC87E2E8,
> + 0x05D2EC49,
> + 0xA4F2D8E0
> + };
> + uint data_out[2];
> +
> + test_in.key0 = 0x2BD6459F;
> + test_in.key1 = 0x82C5B300;
> + test_in.key2 = 0x952C4910;
> + test_in.key3 = 0x4881FF48;
> + test_in.fresh = 0x05D2EC49;
> + test_in.count = 0x38A6F056;
> +
> + for (i = 0; i < 6; i++)
> + data_in[i] = kasumi_byte_swap(data_in[i]);
> + test_in.data_in = &data_in[0];
> + test_in.data_out = &data_out[0];
> + kasumi_f9_encrypt(&test_in, len, direction);
> + if (data_out[0] == 0xf63bd72c)
> + printk(KERN_INFO
> + " F9 test passed Expected data = 0x%x data recieved=0x%x\n",
> + 0xf63bd72c, data_out[0]);
> + else
> + printk(KERN_INFO
> + " \n F9 test Failed Expected data = 0x%x data recieved=0x%x\n",
> + 0xf63bd72c, data_out[0]);
> +
> +}
> +#endif
> +
> +/*
> +**FUNCTION:kasumi_encrypt_decrypt()
> +** args: kd is kasumi descriptor which holds all the requred data to do kasumi
> +** mode encryption and decryption
> +** Description: This function follows the kasumi algorithm to encrypt and decrypt.
> +** 1. Check for interrupt bit KDA(Kasumi Data Availability)
> +** 2. check for data availability bit in CTRL register and write 1 to clear it
> +** 3. Set keys
> +** 4. set mode
> +** 5. set inputdata
> +** 6. validate keys , mode and data
> +** 7. wait for the data availability and then read the data.
> +** This function can only do 64bit data encryption at given time
> +** Please check the test() in the comment section.
> +*/
> +static int kasumi_encrypt_decrypt(struct kasumi_desc *kd)
> +{
> + uint time_out = 100;
> +
> + /*
> + * CTRL_STATUS[0] to reset the DATA out mechanism
> + */
> + printk(KERN_WARNING "kreg.ctrl 0x%x\n", kreg.ctrl);
> + out_be32(kreg.ctrl, in_be32(kreg.ctrl) | KASUMI_DATA_READY);
> + /*
> + * Check for interrupt bit for data availability bit set .
> + * if set clear it
> + */
> + if (mfdcr(DCR_UIC0_SR) & 0x08000000) {
> + mtdcr(DCR_UIC0_SR, (mfdcr(DCR_UIC0_SR) & ~0x08000000));
> + }
> +
> + /*
> + * Check if KASUMI is ready for data input
> + */
> + if (!mfdcr(DCR_UIC0_SR) & 0x10000000)
> + printk(KERN_INFO "KASUMI is ready for data\n");
> +
> + /*
> + * need keys
> + */
> + out_be32(kreg.key0, kd->key0);
> + out_be32(kreg.key1, kd->key1);
> + out_be32(kreg.key2, kd->key2);
> + out_be32(kreg.key3, kd->key3);
> + /*
> + * Check for correct mode
> + */
> + if ((kd->mode != KASUMI_ENC_MODE) && (kd->mode != KASUMI_DEC_MODE)) {
> + printk(KERN_INFO "KASUMI ERROR: invalid mode\n\n");
> + return -1;
> + }
> +
> + /*
> + * set mode
> + */
> + out_be32(kreg.mode, kd->mode);
> + /*
> + * write data
> + */
> + if ((kd->data_in != NULL) && (kd->data_in)) {
> + out_be32(kreg.data_in0 , kd->data_in[0]);
> + out_be32(kreg.data_in1, kd->data_in[1]);
> + } else {
> + printk(KERN_INFO "No data passed\n");
> + return -1;
> + }
> +
> + /*
> + * validate data CTRL_STAT[4]
> + * Validate mode CTRL_STA[1] = 1
> + * vlaidatkeys keys CTRL_STAT[2] = 1
> + */
> + out_be32(kreg.ctrl, in_be32(kreg.ctrl) | (KASUMI_VAL_DATA |
> + KASUMI_VAL_KEYS |
> + KASUMI_VAL_MODE));
> + /*
> + * Just in case DATA validation not finished
> + */
> + time_out = 100;
> + while (in_be32(kreg.ctrl) & KASUMI_VAL_DATA) {
> + time_out--;
> + mdelay(1);
> + if (time_out <= 0) {
> + printk(KERN_INFO
> + "ERROR: at line %d Timed out KASU0_CTRL=0x%x\n",
> + __LINE__, in_be32(kreg.ctrl));
> + break;
> + }
> + }
> +
> + /*
> + * Check if data available bit is set
> + */
> + if (!mfdcr(DCR_UIC0_SR) & 0x08000000)
> + printk(KERN_WARNING
> + "KASUMI data NOT available and NO KDA interrupt occured\n");
> +
> + /*
> + * Is data avaialbel
> + */
> + time_out = 100;
> + while (!(in_be32(kreg.status) & KASUMI_DATA_READY)) {
> + time_out--;
> + mdelay(1);
> + if (time_out <= 0) {
> + printk(KERN_INFO "line %d Timed out KASU0_CTRL=0x%x\n",
> + __LINE__, in_be32(kreg.ctrl));
> + break;
> + }
> + }
> +
> + if (!(in_be32(kreg.status ) & KASUMI_DATA_READY))
> + printk(KERN_WARNING "Data is not ready\n");
> +
> + kd->data_out[0] = in_be32(kreg.data_out0);
> + kd->data_out[1] = in_be32(kreg.data_out1);
> + return 0;
> +}
> +
> +/*
> +** Kasumi encryption function calls the kasumi_encrypt_decrypt()
> +**
> +*/
> +int kasumi_encrypt(struct kasumi_desc *test)
> +{
> + test->mode = KASUMI_ENC_MODE;
> + if (kasumi_encrypt_decrypt(test) != 0) {
> + printk(KERN_INFO "kasumi_encrypt_decrypt returned error");
> + return -1;
> + } else
> + return 0;
> +
> +}
> +
> +/*
> +** Kasumi encryption function calls the kasumi_encrypt_decrypt()
> +**
> +*/
> +int kasumi_decrypt(struct kasumi_desc *test)
> +{
> + test->mode = KASUMI_DEC_MODE;
> + if (kasumi_encrypt_decrypt(test) != 0) {
> + printk(KERN_INFO "kasumi_encrypt_decrypt returned error");
> + return -1;
> + } else
> + return 0;
> +
> +}
> +
> +/*
> +**
> +**FUNCTION:kasumi_encrypt_decrypt()
> +**args: kd is kasumi descriptor which holds all the requred data to do kasumi mode encryption and decryption
> +**Description: This function follows the kasumi algorithm to encrypt and decrypt.
> +** 1. Check for interrupt bit KDA(Kasumi Data Availability)
> +** 2. check for data availability bit in CTRL register and write 1 to clear it
> +** 3. Set keys
> +** 4. set mode
> +** 5. set config
> +** 6. set count
> +** 7. set inputdata
> +** 8. validate keys , mode , config , count and data
> +** 9. wait for the data availability and then read the data.
> +** This function can encrypt block data
> +** Please check the test_f8_1() in the comment section.
> +*/
> +static int kasumi_f8_encrypt_decrypt(struct kasumi_desc *kd)
> +{
> + int time_out = 10000;
> + int len = 0;
> + int i = 0;
> +
> + len = ((kd->config & 0xff) << 8) | ((kd->config & 0xff00) >> 8);
> + /*Reset data out mechanism */
> + /*CTRL_STATUS[0] to reset the DATA out mechanism */
> + out_be32(kreg.ctrl, in_be32(kreg.ctrl) | KASUMI_DATA_READY);
> +
> + if (mfdcr(DCR_UIC0_SR) & 0x08000000)
> + mtdcr(DCR_UIC0_SR, (mfdcr(DCR_UIC0_SR) & ~0x08000000));
> +
> + if (!mfdcr(DCR_UIC0_SR) & 0x10000000)
> + printk(KERN_INFO "KASUMI is NOT ready for data\n");
> +
> + /*need keys */
> +
> + out_be32(kreg.key0, kd->key0);
> + out_be32(kreg.key1, kd->key1);
> + out_be32(kreg.key2, kd->key2);
> + out_be32(kreg.key3, kd->key3);
> + /*write config */
> + out_be32(kreg.config, kd->config);
> + /* Write count */
> + out_be32(kreg.count, kd->count);
> + /*set mode */
> + if (kd->mode != KASUMI_F8_ENC_MODE) {
> + printk(KERN_INFO "KASUMI Invalid mode\n");
> + return -1;
> + }
> +
> + out_be32(kreg.mode, kd->mode);
> +
> + /*
> + * write data
> + * validate data CTRL_STAT[4]
> + * Validate mode CTRL_STA[1] = 1
> + * vlaidatkeys keys CTRL_STAT[2] = 1
> + * vlaidatkeys count and config
> + */
> + out_be32(kreg.ctrl, in_be32(kreg.ctrl) | (KASUMI_VAL_CFG |
> + KASUMI_VAL_COUNT |
> + KASUMI_VAL_KEYS |
> + KASUMI_VAL_MODE));
> + time_out = 100;
> + /*
> + ** Just in case DATA validation is not finished
> + */
> + while (in_be32( kreg.ctrl) & (KASUMI_VAL_CFG | KASUMI_VAL_COUNT |
> + KASUMI_VAL_KEYS | KASUMI_VAL_MODE)) {
> + time_out--;
> + mdelay(1);
> + if (time_out <= 0) {
> + printk(KERN_INFO
> + " KASUMI:line %d Timed out KASU0_CTRL=0x%x\n",
> + __LINE__, in_be32(kreg.ctrl));
> + break;
> + }
> +
> + }
> +
> + if (in_be32(kreg.ctrl )
> + & (KASUMI_VAL_CFG | KASUMI_VAL_COUNT |
> + KASUMI_VAL_KEYS | KASUMI_VAL_MODE))
> + printk(KERN_WARNING
> + " CFG COUNT KEYS MODE validation NOT complete\n");
> + /*
> + ** Here we encode 64bits a time till whole block is encrypted
> + */
> + while (len > 0) {
> + if ((&kd->data_in[i] != NULL) && (&kd->data_in[i + 1] != NULL)) {
> + out_be32(kreg.data_in0, kd->data_in[i]);
> + out_be32(kreg.data_in1, kd->data_in[i + 1]);
> + } else {
> + printk(KERN_INFO "No data passed\n");
> + break;
> + }
> +
> + out_be32(kreg.ctrl, in_be32(kreg.ctrl) | KASUMI_VAL_DATA);
> + time_out = 100;
> + while (in_be32(kreg.ctrl) & (KASUMI_VAL_DATA)) {
> + time_out--;
> + if (time_out <= 0) {
> + printk(KERN_INFO
> + "KASUMI: line %d Timed out KASU0_CTRL=0x%x\n",
> + __LINE__, in_be32(kreg.ctrl));
> + break;
> + }
> + }
> +
> + if (in_be32(kreg.ctrl) & (KASUMI_VAL_DATA))
> + printk(KERN_WARNING "Data validation NOT complete\n");
> +
> + time_out = 100;
> + while (!(in_be32( kreg.status) & KASUMI_DATA_READY)) {
> + mdelay(1);
> + time_out--;
> + if (time_out <= 0) {
> + printk(KERN_INFO
> + "line %d Timed out KASU0_CTRL=0x%x\n",
> + __LINE__, in_be32(kreg.ctrl));
> + break;
> + }
> +
> + }
> +
> + if (!(in_be32(kreg.status) & KASUMI_DATA_READY)) {
> + printk(KERN_WARNING "Data is not ready\n");
> + break;
> + }
> +
> + kd->data_out[i] = kasumi_byte_swap(in_be32(kreg.data_out0));
> + kd->data_out[i + 1] = kasumi_byte_swap(in_be32(kreg.data_out1));
> + /*
> + ** CTRL_STATUS[0] to reset the DATA out mechanism
> + */
> + out_be32(kreg.ctrl, KASUMI_DATA_READY);
> + if (!mfdcr(DCR_UIC0_SR) & 0x10000000)
> + printk(KERN_WARNING "KASUMI is NOT ready for data\n");
> +
> + i += 2;
> + len = len - 64;
> + }
> +
> + return 0;
> +}
> +
> +/*
> +** arg1: hte filled kasumi_desc structure pointer
> +** arg2: len
> +** arg3: bearer
> +** arg4: direction
> +*/
> +int kasumi_f8_encrypt(struct kasumi_desc *test, uint len, uint bearer,
> + uint direction)
> +{
> + int i = 0;
> +
> + test->config = (len << 16 | bearer << 1 | direction);
> + test->mode = KASUMI_F8_ENC_MODE;
> + test->key0 = kasumi_byte_swap(test->key0);
> + test->key1 = kasumi_byte_swap(test->key1);
> + test->key2 = kasumi_byte_swap(test->key2);
> + test->key3 = kasumi_byte_swap(test->key3);
> + test->count = kasumi_byte_swap(test->count);
> + test->config = kasumi_byte_swap(test->config);
> + len = len / (32);
> +
> + for (i = 0; i <= len; i++)
> + test->data_in[i] = kasumi_byte_swap(test->data_in[i]);
> +
> + if (kasumi_f8_encrypt_decrypt(test) != 0) {
> + printk(KERN_INFO
> + "kasumi_f8_encrypt_decrypt() returned error\n");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +/*
> +**
> +**FUNCTION:kasumi_encrypt_decrypt()
> +**args: kd is kasumi descriptor which holds all the requred data to do kasumi mode encryption and decryption
> +**Description: This function follows the kasumi algorithm to encrypt and decrypt.
> +** 1. Check for interrupt bit KDA(Kasumi Data Availability)
> +** 2. check for data availability bit in CTRL register and write 1 to clear it
> +** 3. Set keys
> +** 4. set mode
> +** 5. set config
> +** 6. set count
> +** 7. set inputdata
> +** 8. validate keys , mode , config , count and data
> +** 9. wait for the data availability and then read the data.
> +** This function can encrypt block data
> +** Please check the test_f9_1() in the comment section.
> +*/
> +int kasumi_f9(struct kasumi_desc *kd)
> +{
> + int time_out = 10000;
> + int len = 0;
> + int i = 0;
> +
> + /*
> + ** Get the lenght of the block we are going to encode
> + */
> + len = ((kd->config & 0xff) << 8) | ((kd->config & 0xff00) >> 8);
> +
> + /*
> + ** CTRL_STATUS[0] to reset the DATA out mechanism
> + */
> + out_be32(kreg.ctrl, in_be32(kreg.ctrl) | KASUMI_DATA_READY);
> + if (mfdcr(DCR_UIC0_SR) & 0x08000000)
> + mtdcr(DCR_UIC0_SR, (mfdcr(DCR_UIC0_SR) & ~0x08000000));
> +
> + if (!(mfdcr(DCR_UIC0_SR) & 0x10000000))
> + printk(KERN_INFO "KASUMI is ready for data\n");
> +
> + /*
> + ** need keys
> + */
> + out_be32(kreg.key0, kd->key0);
> + out_be32(kreg.key1, kd->key1);
> + out_be32(kreg.key2, kd->key2);
> + out_be32(kreg.key3, kd->key3);
> + /*
> + ** write config
> + */
> + out_be32(kreg.config, kd->config);
> + /*
> + ** Write count
> + */
> + out_be32(kreg.count, kd->count);
> + /*
> + ** set fresh
> + */
> + out_be32(kreg.fresh, kd->fresh);
> + /*
> + ** set mode
> + */
> + if (kd->mode != KASUMI_F9_ENC_MODE) {
> + printk(KERN_INFO "KASUMI Invalid mode\n");
> + return -1;
> + }
> +
> + out_be32(kreg.mode, kd->mode);
> + /*
> + * write data
> + * validate data CTRL_STAT[4]
> + * Validate mode CTRL_STA[1] = 1
> + * vlaidatkeys keys CTRL_STAT[2] = 1
> + * vlaidatkeys count and config
> + */
> + out_be32(kreg.ctrl,
> + in_be32(kreg.ctrl) |
> + (KASUMI_VAL_CFG | KASUMI_VAL_COUNT | KASUMI_VAL_KEYS |
> + KASUMI_VAL_MODE | KASUMI_VAL_FRESH));
> + time_out = 100;
> + /*
> + ** Just in case validation is not complete.
> + */
> + while (in_be32(kreg.ctrl) & (KASUMI_VAL_CFG |
> + KASUMI_VAL_COUNT | KASUMI_VAL_KEYS
> + | KASUMI_VAL_MODE | KASUMI_VAL_FRESH)) {
> + time_out--;
> + mdelay(1);
> + if (time_out <= 0) {
> + printk(KERN_INFO "line %d Timed out KASU0_CTRL=0x%x\n",
> + __LINE__, in_be32(kreg.ctrl));
> + break;
> + }
> + }
> +
> + if (in_be32(kreg.ctrl) & (KASUMI_VAL_CFG |
> + KASUMI_VAL_COUNT | KASUMI_VAL_KEYS
> + | KASUMI_VAL_MODE | KASUMI_VAL_FRESH))
> + printk(KERN_WARNING
> + " CFG COUNT KEYS MODE validation NOT complete\n");
> +
> + /*
> + ** Loop around this code till we encode all 64bit data blocks
> + */
> + while (len > 0) {
> +
> + if ((&kd->data_in[i] != NULL) && (&kd->data_in[i + 1] != NULL)) {
> + out_be32(kreg.data_in0, kd->data_in[i]);
> + out_be32( kreg.data_in1, kd->data_in[i + 1]);
> + } else {
> + printk(KERN_INFO "No data passed\n");
> + return -1;
> + }
> +
> + out_be32(kreg.ctrl, in_be32(kreg.ctrl) | KASUMI_VAL_DATA);
> + time_out = 100;
> +
> + while (in_be32(kreg.ctrl) & (KASUMI_VAL_DATA)) {
> + time_out--;
> + mdelay(1);
> + if (time_out <= 0) {
> + printk(KERN_INFO
> + "line %d Timed out KASU0_CTRL=0x%x\n",
> + __LINE__, in_be32(kreg.ctrl));
> + break;
> + }
> + }
> +
> + if (in_be32( kreg.ctrl) & (KASUMI_VAL_DATA)) {
> + printk(KERN_INFO "Data validation NOT complete\n");
> + }
> +
> + if (!(mfdcr(DCR_UIC0_SR) & 0x10000000))
> + printk(KERN_INFO "KASUMI is NOT ready for data\n");
> +
> + i += 2;
> + len = len - 64;
> + }
> +
> + if (!(mfdcr(DCR_UIC0_SR) & 0x08000000))
> + printk(KERN_INFO
> + "KASUMI data NOT available and NO KDA interrupt occured\n");
> +
> + /*
> + ** Is data avaialbel
> + */
> + time_out = 100;
> + while (!(in_be32(kreg.status) & KASUMI_DATA_READY)) {
> + time_out--;
> + mdelay(1);
> + if (time_out <= 0) {
> + printk(KERN_INFO "line %d Timed out KASU0_CTRL=0x%x\n",
> + __LINE__, in_be32(kreg.ctrl));
> + }
> +
> + }
> +
> + if (!(in_be32(kreg.status) & KASUMI_DATA_READY))
> + printk(KERN_WARNING "Data is not ready\n");
> + kd->data_out[0] = kasumi_byte_swap(in_be32(kreg.data_out0));
> + kd->data_out[1] = kasumi_byte_swap(in_be32(kreg.data_out1));
> + out_be32( kreg.ctrl, KASUMI_DATA_READY);
> + return 0;
> +}
> +
> +/*
> +** arg1: kasumi_desc structure
> +** arg2: len
> +** arg3: direction
> +*/
> +int kasumi_f9_encrypt(struct kasumi_desc *test, uint len, uint direction)
> +{
> + test->config = (len << 16 | direction);
> + test->config = (0x00BD0000);
> + test->mode = KASUMI_F9_ENC_MODE;
> + test->key0 = kasumi_byte_swap(test->key0);
> + test->key1 = kasumi_byte_swap(test->key1);
> + test->key2 = kasumi_byte_swap(test->key2);
> + test->key3 = kasumi_byte_swap(test->key3);
> + test->count = kasumi_byte_swap(test->count);
> + test->config = kasumi_byte_swap(test->config);
> + test->fresh = kasumi_byte_swap(test->fresh);
> +
> + if (kasumi_f9(test) != 0) {
> + printk(KERN_INFO
> + "kasumi_f8_encrypt_decrypt() returned error\n");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +/*
> +**IOCTL function to let this driver usaed from user space.
> +**
> +*/
> +static int kasumi_ioctl(struct inode *inode, struct file *filep,
> + unsigned int cmd, unsigned long arg)
> +{
> + int kerr = 0;
> + struct kasumi_f8_f9_desc kd_f89;
> +
> + kd_f89.kd.data_in = &data_in[0];
> + kd_f89.kd.data_out = &data_out[0];
> +
> + switch (cmd) {
> + case KASUMI_IOCTL_ENCRYPT:
> + {
> + copy_from_user(&kd_f89,
> + (struct kasumi_f8_f9_desc __user *)arg,
> + sizeof(struct kasumi_f8_f9_desc));
> + kerr = kasumi_encrypt(&kd_f89.kd);
> + copy_to_user(&kd_f89,
> + (struct kasumi_f8_f9_desc __user *)arg,
> + sizeof(struct kasumi_f8_f9_desc));
> +
> + if (kerr < 0)
> + return kerr;
> + return 0;
> + break;
> + }
> + case KASUMI_IOCTL_DECRYPT:
> + {
> + printk(KERN_INFO "kd_f89.kd.data_in[0]=0x%x\n",
> + kd_f89.kd.data_in[0]);
> + printk(KERN_INFO "kd_f89.kd.data_in[1]=0x%x\n",
> + kd_f89.kd.data_in[1]);
> + copy_from_user(&kd_f89,
> + (struct kasumi_f8_f9_desc __user *)arg,
> + sizeof(struct kasumi_f8_f9_desc));
> + kerr = kasumi_decrypt(&kd_f89.kd);
> + copy_to_user(&kd_f89,
> + (struct kasumi_f8_f9_desc __user *)arg,
> + sizeof(struct kasumi_f8_f9_desc));
> + if (kerr < 0)
> + return kerr;
> + break;
> + }
> + case KASUMI_IOCTL_F8_MODE:
> + {
> + copy_from_user(&kd_f89,
> + (struct kasumi_f8_f9_desc __user *)arg,
> + sizeof(struct kasumi_f8_f9_desc));
> + kerr =
> + kasumi_f8_encrypt(&kd_f89.kd, kd_f89.len,
> + kd_f89.bearer, kd_f89.direction);
> + copy_to_user(&kd_f89,
> + (struct kasumi_f8_f9_desc __user *)arg,
> + sizeof(struct kasumi_f8_f9_desc));
> + if (kerr < 0)
> + return kerr;
> + break;
> + }
> + case KASUMI_IOCTL_F9_MODE:
> + {
> + copy_from_user(&kd_f89,
> + (struct kasumi_f8_f9_desc __user *)arg,
> + sizeof(struct kasumi_f8_f9_desc));
> + kerr =
> + kasumi_f9_encrypt(&kd_f89.kd, kd_f89.len,
> + kd_f89.direction);
> + copy_to_user(&kd_f89,
> + (struct kasumi_f8_f9_desc __user *)arg,
> + sizeof(struct kasumi_f8_f9_desc));
> + if (kerr < 0)
> + return kerr;
> + break;
> + }
> + default:
> + return -ENOTTY;
> + }
> +
> + return 0;
> +}
> +
> +/*
> +** file operations
> +*/
> +struct file_operations kasumi_fops = {
> + .ioctl = kasumi_ioctl,
> +};
> +
> +/*
> +** Moudle initialization
> +**/
> +int kasumi_init_module(void)
> +{
> + int kerr = 0;
> + dev_t dev = MKDEV(kasumi_major, 0);
> + struct cdev *k_cdev = cdev_alloc();
> +
> + printk(KERN_INFO "Loading Kasumi Driver\n");
> + if (kasumi_major)
> + kerr = register_chrdev_region(dev, 1, "kasumi");
> + else {
> + kerr = alloc_chrdev_region(&dev, 0, 1, "kasumi");
> + kasumi_major = MAJOR(dev);
> + }
> +
> + if (kerr < 0) {
> + printk(KERN_ERR "KASUMI:Failed to get major number");
> + return kerr;
> + }
> +
> + cdev_init(k_cdev, &kasumi_fops);
> + k_cdev->owner = THIS_MODULE;
> + k_cdev->ops = &kasumi_fops;
> + kerr = cdev_add(k_cdev, MKDEV(kasumi_major, 0), 1);
> + if (kerr < 0)
> + return kerr;
> +
> + /*
> + * setup register base address
> + */
> + kasumi_base = ioremap64(0x0E0180000ULL, 0x80);
> + if (!kasumi_base) {
> + printk(KERN_INFO "ioremap falied for address 0xE0180000\n");
> + return -1;
> + }
> +
> + /*
> + **Register address assignments
> + **
> + */
> + kreg.ctrl = ((uint *) ((u8 *) kasumi_base + KASU0_CTRL));
> + kreg.status = ((uint *) ((u8 *) kasumi_base + KASU0_STATUS));
> + kreg.mode = ((uint *) ((u8 *) kasumi_base + KASU0_MODE));
> + kreg.key0 = ((uint *) ((u8 *) kasumi_base + KASU0_KEY0));
> + kreg.key1 = ((uint *) ((u8 *) kasumi_base + KASU0_KEY1));
> + kreg.key2 = ((uint *) ((u8 *) kasumi_base + KASU0_KEY2));
> + kreg.key3 = ((uint *) ((u8 *) kasumi_base + KASU0_KEY3));
> + kreg.count = ((uint *) ((u8 *) kasumi_base + KASU0_COUNT));
> + kreg.config = ((uint *) ((u8 *) kasumi_base + KASU0_CONFIG));
> + kreg.fresh = ((uint *) ((u8 *) kasumi_base + KASU0_FRESH));
> + kreg.data_in0 = ((uint *) ((u8 *) kasumi_base + KASU0_DATA_IN0));
> + kreg.data_in1 = ((uint *) ((u8 *) kasumi_base + KASU0_DATA_IN1));
> + kreg.data_out0 = ((uint *) ((u8 *) kasumi_base + KASU0_DATA_OUT0));
> + kreg.data_out1 = ((uint *) ((u8 *) kasumi_base + KASU0_DATA_OUT1));
> +
> + /*
> + ** reset KASUMI core
> + */
> + SDR_WRITE(SDR0_SRST1, SDR_READ(SDR0_SRST1) | KASUMI_RESET_MSK);
> + SDR_WRITE(SDR0_SRST1, SDR_READ(SDR0_SRST1) & (~KASUMI_RESET_MSK));
> + /*
> + ** Disable the read pipe line. Otherwise it may cause hang on PLB
> + */
> + mtdcr(DCR_PLB4A0, mfdcr(DCR_PLB4A0) & DISABLE_RD_PIPE_LINE);
> + mtdcr(DCR_UIC0_ER, (mfdcr(DCR_UIC0_ER) | 0x18000000));
> +
> + /*
> + ** Kasumi test
> + */
> +#ifdef KASUMI_TEST
> + kasumi_test();
> + /*
> + ** f8 mode
> + */
> + kasumi_test_f8_1();
> + /*
> + ** f9 mode
> + */
> + kasumi_test_f9();
> +#endif
> + return 0;
> +}
> +
> +/*
> + * Cleanup module
> + */
> +void kasumi_cleanup_module(void)
> +{
> + iounmap(kasumi_base);
> + printk(KERN_INFO "Exiting Kasumi Driver\n");
> +}
> +
> +EXPORT_SYMBOL(kasumi_f9_encrypt);
> +EXPORT_SYMBOL(kasumi_f8_encrypt);
> +EXPORT_SYMBOL(kasumi_encrypt);
> +EXPORT_SYMBOL(kasumi_decrypt);
> +module_init(kasumi_init_module);
> +module_exit(kasumi_cleanup_module);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Tirumala Marri <[email protected]>");
> +MODULE_DESCRIPTION("Kasumi security engine driver");
>
>
>
> --
> Marri T Reddy
> San Jose,CA
> No day but today



--
Marri T Reddy
San Jose,CA
No day but today

-
Linux-crypto: cryptography in and on the Linux system
Archive: http://mail.nl.linux.org/linux-crypto/


2007-05-22 01:20:45

by markus reichelt

[permalink] [raw]
Subject: Re: Looking for comments on a Linux driver for HW accelerated Kasumi+F8+F9 algorithms.

* "M.T.Reddy" <[email protected]> wrote:

> On 5/21/07, M. T. Reddy <[email protected]> wrote:
> >Please comment on the following patch for HW accelerated kasumi +
> >f8 and f8 encryption engine.

First time I hear about kasumi. Got a link handy for a rough desc?

If you are interested in feedback concerning solid crypto, consult
the sci.crypt newsgroup.

--
left blank, right bald


Attachments:
(No filename) (385.00 B)
(No filename) (189.00 B)
Download all attachments

2007-05-22 10:02:06

by Evgeniy Polyakov

[permalink] [raw]
Subject: Re: Looking for comments on a Linux driver for HW accelerated Kasumi+F8+F9 algorithms.

On Tue, May 22, 2007 at 03:20:45AM +0200, markus reichelt ([email protected]) wrote:
> * "M.T.Reddy" <[email protected]> wrote:
>
> > On 5/21/07, M. T. Reddy <[email protected]> wrote:
> > >Please comment on the following patch for HW accelerated kasumi +
> > >f8 and f8 encryption engine.
>
> First time I hear about kasumi. Got a link handy for a rough desc?

It is a crypto cipher used as a5/3 in 3gpp networks.

Was patch sent to linux-crypto@vger, since I did not see it in maillist.
If not, please resend.



--
Evgeniy Polyakov