Re: Looking for comments on a Linux driver for HW accelerated Kasumi+F8+F9 algorithms.

M.T.Reddy <[email protected]>
Newsgroups gmane.linux.cryptography,gmane.linux.kernel.cryptoapi
Message-ID <[email protected]>
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/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.