crypto: Add MSM crypto drivers

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
This commit is contained in:
Stephen Boyd 2013-01-11 10:09:31 -08:00
parent 64990c839b
commit ffda655125
21 changed files with 14026 additions and 0 deletions

View File

@ -0,0 +1,228 @@
Introduction:
=============
The Qualcomm crypto engine (qce) driver is a module that
provides common services for accessing the Qualcomm crypto device.
Currently, the two main clients of qce are
-qcrypto driver (module provided for accessing CE HW by kernel space apps)
-qcedev driver (module provided for accessing CE HW by user space apps)
The crypto engine (qce) driver is a client to the DMA driver for the Qualcomm
DMA device - Application Data Mover (ADM). ADM is used to provide the DMA
transfer capability between Qualcomm crypto device hardware and DDR memory
for crypto operations.
Figure 1.
---------
Linux kernel
(ex:IPSec)<--*Qualcomm crypto driver----+
(qcrypto) |
(for kernel space app) |
|
+-->|
|
| *qce <----> Qualcomm
| driver ADM driver <---> ADM HW
+-->| | |
| | |
| | |
| | |
Linux kernel | | |
misc device <--- *QCEDEV Driver-------+ | |
interface (qcedev) (Reg interface) (DMA interface)
(for user space app) \ /
\ /
\ /
\ /
\ /
\ /
\ /
Qualcomm crypto CE3 HW
The entities marked with (*) in the Figure 1, are the software components of
the Linux Qualcomm crypto modules.
===============
IMPORTANT NOTE:
===============
(1) The CE hardware can be accessed either from user space OR kernel space,
at one time. Both user space and kernel space clients cannot access the
qce driver (and the CE hardware) at the same time.
- If your device has user space apps that needs to access the crypto
hardware, make sure to have the qcrypto module disabled/unloaded.
This will result in the kernel space apps to use the registered
software implementation of the crypto algorithms.
- If your device has kernel space apps that needs to access the
crypto hardware, make sure to have qcedev module disabled/unloaded
and implement your user space application to use the software
implemenation (ex: openssl/crypto) of the crypto algorithms.
(2) If your device has Playready(Windows Media DRM) application enabled and
uses the qcedev module to access the crypto hardware accelarator,
please be informed that for performance reasons, the CE hardware will need
to be dedicated to playready application. Any other user space application
should be implemented to use the software implemenation (ex: openssl/crypto)
of the crypto algorithms.
Hardware description:
=====================
Qualcomm Crypto HW device family provides a series of algorithms implemented
in the device hardware.
Crypto 2 hardware provides hashing - SHA-1, SHA-256, ciphering - DES, 3DES, AES
algorithms, and concurrent operations of hashing, and ciphering.
In addition to those functions provided by Crypto 2 HW, Crypto 3 HW provides
fast AES algorithms.
In addition to those functions provided by Crypto 3 HW, Crypto 3E provides
HMAC-SHA1 hashing algorithm, and Over The Air (OTA) f8/f9 algorithms as
defined by the 3GPP forum.
Software description
====================
The crypto device is defined as a platform device. The driver is
independent of the platform. The driver supports multiple instances of
crypto HW.
All the platform specific parameters are defined in the board init
file, eg. arch/arm/mach-msm/board-msm7x30.c for MSM7x30.
The qce driver provide the common services of HW crypto
access to the two drivers as listed above (qcedev, qcrypto. It sets up
the crypto HW device for the operation, then it requests ADM driver for
the DMA of the crypto operation.
Two ADM channels and two command lists (one command list for each
channel) are involved in an operation.
The setting up of the command lists and the procedure of the operation
of the crypto device are described in the following sections.
The command list for the first DMA channel is set up as follows:
1st command of the list is for the DMA transfer from DDR memory to the
crypto device to input data to crypto device. The dst crci of the command
is set for crci-in for this crypto device.
2nd command is for the DMA tansfer is from crypto device to DDR memory for
the authentication result. The src crci is set as crci-hash-done of the
crypto device. If authentication is not required in the operation,
the 2nd command is not used.
The command list for the second DMA channel is set up as follows:
One command to DMA data from crypto device to DDR memory for encryption or
decryption output from crypto device.
To accomplish ciphering and authentication concurrent operations, the driver
performs the following steps:
(a). set up HW crypto device
(b). hit the crypto go register.
(c). issue the DMA command of first channel to the ADM driver,
(d). issue the DMA command of 2nd channel to the ADM driver.
SHA1/SHA256 is an authentication/integrity hash algorithm. To accomplish
hash operation (or any authentication only algorithm), 2nd DMA channel is
not required. Only steps (a) to (c) are performed.
At the completion of the DMA operation (for (c) and (d)) ADM driver
invokes the callback registered to the DMA driver. This signifies the end of
the DMA operation(s). The driver reads the status and other information from
the CE hardware register and then invokes the callback to the qce driver client.
This signal the completion and the results of the DMA along with the status of
the CE hardware to the qce driver client. This completes a crypto operation.
In the qce driver initialization, memory for the two command lists, descriptor
lists for each crypto device are allocated out of coherent memory, using Linux
DMA API. The driver pre-configures most of the two ADM command lists
in the initialization. During each crypto operation, minimal set up is required.
src_dscr or/and dst_dscr descriptor list of the ADM command are populated
from the information obtained from the corresponding data structure. eg: for
AEAD request, the following data structure provides the information:
struct aead_request *req
......
req->assoc
req->src
req->dst
The DMA address of a scatter list will be retrieved and set up in the
descriptor list of an ADM command.
Power Management
================
none
Interface:
==========
The interface is defined in kernel/drivers/crypto/msm/inc/qce.h
The clients qcrypto, qcedev drivers are the clients using
the interfaces.
The following services are provided by the qce driver -
qce_open(), qce_close(), qce_ablk_cipher_req(),
qce_hw_support(), qce_process_sha_req()
qce_open() is the first request from the client, ex. Qualcomm crypto
driver (qcedev, qcrypto), to open a crypto engine. It is normally
called at the probe function of the client for a device. During the
probe,
- ADM command list structure will be set up
- Crypto device will be initialized.
- Resource associated with the crypto engine is retrieved by doing
platform_get_resource() or platform_get_resource_byname().
The resources for a device are
- crci-in, crci-out, crci-hash-done
- two DMA channel IDs, one for encryption and decryption input, one for
output.
- base address of the HW crypto device.
qce_close() is the last request from the client. Normally, it is
called from the remove function of the client.
qce_hw_support() allows the client to query what is supported
by the crypto engine hardware.
qce_ablk_cipher_req() provides ciphering service to the client.
qce_process_sha_req() provide hashing service to the client.
qce_aead_req() provide aead service to the client.
Module parameters:
==================
The following module parameters are defined in the board init file.
-CE hardware nase register address
-Data mover channel used for transfer to/from CE hardware
These parameters differ in each platform.
Dependencies:
=============
Existing DMA driver.
The transfers are DMA'ed between the crypto hardware and DDR memory via the
data mover, ADM. The data transfers are set up to use the existing dma driver.
User space utilities:
=====================
n/a
Known issues:
=============
n/a
To do:
======
n/a

View File

@ -0,0 +1,241 @@
Introduction:
=============
The Qualcomm crypto engine (qce40) driver is a module that
provides common services for accessing the Qualcomm crypto device.
Currently, the two main clients of qce40 are
-qcrypto driver (module provided for accessing CE HW by kernel space apps)
-qcedev driver (module provided for accessing CE HW by user space apps)
This module provides the same interface to the clients as does qce.c and is
based off qce.c. Following are the updates from qce.c
- Add support for AES XTS mode
- Add support for CMAC mode
- Add support for AES CCM mode
- Add support for SHA1/SHA256 HMAC
- Read HASH/MAC information directly from CE hardware registers instead of
using datamover.
The crypto engine (qce40) module is a client to the DMA driver for the Qualcomm
DMA device - Application Data Mover (ADM). ADM is used to provide the DMA
transfer capability between Qualcomm crypto device hardware and DDR memory
for crypto operations.
Figure 1.
---------
Linux kernel
(ex:IPSec)<--*Qualcomm crypto driver----+
(qcrypto) |
(for kernel space app) |
|
+-->|
|
| *qce40 <----> Qualcomm
| driver ADM driver <---> ADM HW
+-->| | |
| | |
| | |
| | |
Linux kernel | | |
misc device <--- *QCEDEV Driver-------+ | |
interface (qcedev) (Reg interface) (DMA interface)
(for user space app) \ /
\ /
\ /
\ /
\ /
\ /
\ /
Qualcomm crypto CE3 HW
The entities marked with (*) in the Figure 1, are the software components of
the Linux Qualcomm crypto modules.
===============
IMPORTANT NOTE:
===============
(1) The CE hardware can be accessed either from user space OR kernel space,
at one time. Both user space and kernel space clients cannot access the
qce driver (and the CE hardware) at the same time.
- If your device has user space apps that needs to access the crypto
hardware, make sure to have the qcrypto module disabled/unloaded.
This will result in the kernel space apps to use the registered
software implementation of the crypto algorithms.
- If your device has kernel space apps that needs to access the
crypto hardware, make sure to have qcedev module disabled/unloaded
and implement your user space application to use the software
implemenation (ex: openssl/crypto) of the crypto algorithms.
(2) If your device has Playready(Windows Media DRM) application enabled and
uses the qcedev module to access the crypto hardware accelarator,
please be informed that for performance reasons, the CE hardware will need
to be dedicated to playready application. Any other user space application
should be implemented to use the software implemenation (ex: openssl/crypto)
of the crypto algorithms.
Hardware description:
=====================
Qualcomm Crypto HW device family provides a series of algorithms implemented
in the device hardware.
Crypto 2 hardware provides hashing - SHA-1, SHA-256, ciphering - DES, 3DES, AES
algorithms, and concurrent operations of hashing and ciphering.
In addition to those functions provided by Crypto 2 HW, Crypto 3 HW provides
fast AES algorithms.
In addition to those functions provided by Crypto 3 HW, Crypto 3E provides
HMAC-SHA1 hashing algorithm, and Over The Air (OTA) f8/f9 algorithms as
defined by the 3GPP forum.
Software description
====================
The crypto device is defined as a platform device. The driver is
independent of the platform. The driver supports multiple instances of
crypto HW.
All the platform specific parameters are defined in the board init
file, eg. arch/arm/mach-msm/board-msm8960.c for MSM8960.
The qce40 driver provide the common services of HW crypto
access to the two drivers as listed above (qcedev, qcrypto. It sets up
the crypto HW device for the operation, then it requests ADM driver for
the DMA of the crypto operation.
Two ADM channels and two command lists (one command list for each
channel) are involved in an operation.
The setting up of the command lists and the procedure of the operation
of the crypto device are described in the following sections.
The command lists contains a single command. For the first DMA channel it
is set up as follows:
The command is for the DMA transfer from DDR memory to the
crypto device to input data to crypto device. The dst crci of the command
is set for crci-in for this crypto device.
The command list for the second DMA channel is set up as follows:
One command to DMA data from crypto device to DDR memory for encryption or
decryption output from crypto device.
To accomplish ciphering and authentication concurrent operations, the driver
performs the following steps:
(a). set up HW crypto device
(b). hit the crypto go register.
(c). issue the DMA command of first channel to the ADM driver,
(d). issue the DMA command of 2nd channel to the ADM driver.
SHA1/SHA256 is an authentication/integrity hash algorithm. To accomplish
hash operation (or any authentication only algorithm), 2nd DMA channel is
not required. Only steps (a) to (c) are performed.
At the completion of the DMA operation (for (c) and (d)) ADM driver
invokes the callback registered to the DMA driver. This signifies the end of
the DMA operation(s). The driver reads the status and other information from
the CE hardware register. For HASH functions (SHA1/SHA256, HMAC, CMAC and
CCM) were the MAC/HASH information is read off hardware registers.
[ NOTE: This is different from what is done in the qce module that support
CE3.x hardware. In CE4.0 there is not CRCI_HASH and hence we cannot rely
on the data mover to populate the HMAC/SHA information. This information
is acquired fromte h ahrdware by reading directly from some registers that
hold this information ]
The driver than nvokes the callback to the qce driver client.
This signal the completion and the results of the DMA along with the status of
the CE hardware to the qce40 driver client. This completes a crypto operation.
In the qce40 driver initialization, memory for the two command lists, descriptor
lists for each crypto device are allocated out of coherent memory, using Linux
DMA API. The driver pre-configures most of the two ADM command lists
in the initialization. During each crypto operation, minimal set up is required.
src_dscr or/and dst_dscr descriptor list of the ADM command are populated
from the information obtained from the corresponding data structure. eg: for
AEAD request, the following data structure provides the information:
struct aead_request *req
......
req->assoc
req->src
req->dst
The DMA address of a scatter list will be retrieved and set up in the
descriptor list of an ADM command.
Power Management
================
none
Interface:
==========
The interface is defined in kernel/drivers/crypto/msm/inc/qce.h
The clients qcrypto, qcedev drivers are the clients using
the interfaces.
The following services are provided by the qce driver -
qce_open(), qce_close(), qce_ablk_cipher_req(),
qce_hw_support(), qce_process_sha_req()
qce_open() is the first request from the client, ex. Qualcomm crypto
driver (qcedev, qcrypto), to open a crypto engine. It is normally
called at the probe function of the client for a device. During the
probe,
- ADM command list structure will be set up
- Crypto device will be initialized.
- Resource associated with the crypto engine is retrieved by doing
platform_get_resource() or platform_get_resource_byname().
The resources for a device are
- crci-in, crci-out, crci-hash-done
- two DMA channel IDs, one for encryption and decryption input, one for
output.
- base address of the HW crypto device.
qce_close() is the last request from the client. Normally, it is
called from the remove function of the client.
qce_hw_support() allows the client to query what is supported
by the crypto engine hardware.
qce_ablk_cipher_req() provides ciphering service to the client.
qce_process_sha_req() provides hashing service to the client.
qce_aead_req() provides aead service to the client.
Module parameters:
==================
The following module parameters are defined in the board init file.
-CE hardware base register address
-Data mover channel used for transfer to/from CE hardware
These parameters differ in each platform.
Dependencies:
=============
Existing DMA driver.
The transfers are DMA'ed between the crypto hardware and DDR memory via the
data mover, ADM. The data transfers are set up to use the existing dma driver.
User space utilities:
=====================
n/a
Known issues:
=============
n/a
To do:
======
n/a

View File

@ -0,0 +1,232 @@
Introduction:
=============
This driver provides IOCTLS for user space application to access crypto
engine hardware for the qcedev crypto services. The driver supports the
following crypto algorithms
- AES-128, AES-256 (ECB, CBC and CTR mode)
- AES-192, (ECB, CBC and CTR mode)
(support exists on platform supporting CE 3.x hardware)
- SHA1/SHA256
- AES-128, AES-256 (XTS), AES CMAC, SHA1/SHA256 HMAC
(support exists on platform supporting CE 4.x hardware)
Hardware description:
=====================
Crypto 3E provides cipher and hash algorithms as defined in the
3GPP forum specifications.
Software description
====================
The driver is a Linux platform device driver. For an msm target,
there can be multiple crypto devices assigned for QCEDEV.
The driver is a misc device driver as well.
The following operations are registered in the driver,
-qcedev_ioctl()
-qcedev_open()
-qcedev_release()
The following IOCTLS are available to the user space application(s)-
Cipher IOCTLs:
--------------
QCEDEV_IOCTL_ENC_REQ is for encrypting data.
QCEDEV_IOCTL_DEC_REQ is for decrypting data.
Hashing/HMAC IOCTLs
-------------------
QCEDEV_IOCTL_SHA_INIT_REQ is for initializing a hash/hmac request.
QCEDEV_IOCTL_SHA_UPDATE_REQ is for updating hash/hmac.
QCEDEV_IOCTL_SHA_FINAL_REQ is for ending the hash/mac request.
QCEDEV_IOCTL_GET_SHA_REQ is for retrieving the hash/hmac for data
packet of known size.
QCEDEV_IOCTL_GET_CMAC_REQ is for retrieving the MAC (using AES CMAC
algorithm) for data packet of known size.
The requests are synchronous. The driver will put the process to
sleep, waiting for the completion of the requests using wait_for_completion().
Since the requests are coming out of user space application, before giving
the requests to the low level qce driver, the ioctl requests and the
associated input/output buffer will have to be safe checked, and copied
to/from kernel space.
The extra copying of requests/buffer can affect the performance. The issue
with copying the data buffer is resolved by having the client use PMEM
allocated buffers.
NOTE: Using memory allocated via PMEM is supported only for in place
operations where source and destination buffers point to the same
location. Support for different source and destination buffers
is not supported currently.
Furthermore, when using PMEM, and in AES CTR mode, when issuing an
encryption or decryption request, a non-zero byteoffset is not
supported.
The design of the driver is to allow multiple open, and multiple requests
to be issued from application(s). Therefore, the driver will internally queue
the requests, and serialize the requests to the low level qce (or qce40) driver.
On an IOCTL request from an application, if there is no outstanding
request, a the driver will issue a "qce" request, otherwise,
the request is queued in the driver queue. The process is suspended
waiting for completion.
On completion of a request by the low level qce driver, the internal
tasklet (done_tasklet) is scheduled. The sole purpose of done_tasklet is
to call the completion of the current active request (complete()), and
issue more requests to the qce, if any.
When the process wakes up from wait_for_completion(), it will collect the
return code, and return the ioctl.
A spin lock is used to protect the critical section of internal queue to
be accessed from multiple tasks, SMP, and completion callback
from qce.
The driver maintains a set of statistics using debug fs. The files are
in /debug/qcedev/stats1, /debug/qcedev/stats2, /debug/qcedev/stats3;
one for each instance of device. Reading the file associated with
a device will retrieve the driver statistics for that device.
Any write to the file will clear the statistics.
Power Management
================
n/a
Interface:
==========
Linux user space applications will need to open a handle
(file desrciptor) to the qcedev device. This is achieved by doing
the following to retrieve a file desrciptor to the device.
fd = open("/dev/qce", O_RDWR);
..
ioctl(fd, ...);
Once a valid fd is retrieved, user can call the following ioctls with
the fd as the first parameter and a pointer to an appropriate data
structure, qcedev_cipher_op_req or qcedev_sha_op_req (depending on
cipher/hash functionality) as the second parameter.
The following IOCTLS are available to the user space application(s)-
Cipher IOCTLs:
--------------
QCEDEV_IOCTL_ENC_REQ is for encrypting data.
QCEDEV_IOCTL_DEC_REQ is for decrypting data.
The caller of the IOCTL passes a pointer to the structure shown
below, as the second parameter.
struct qcedev_cipher_op_req {
int use_pmem;
union{
struct qcedev_pmem_info pmem;
struct qcedev_vbuf_info vbuf;
};
uint32_t entries;
uint32_t data_len;
uint8_t in_place_op;
uint8_t enckey[QCEDEV_MAX_KEY_SIZE];
uint32_t encklen;
uint8_t iv[QCEDEV_MAX_IV_SIZE];
uint32_t ivlen;
uint32_t byteoffset;
enum qcedev_cipher_alg_enum alg;
enum qcedev_cipher_mode_enum mode;
enum qcedev_oper_enum op;
};
Hashing/HMAC IOCTLs
-------------------
QCEDEV_IOCTL_SHA_INIT_REQ is for initializing a hash/hmac request.
QCEDEV_IOCTL_SHA_UPDATE_REQ is for updating hash/hmac.
QCEDEV_IOCTL_SHA_FINAL_REQ is for ending the hash/mac request.
QCEDEV_IOCTL_GET_SHA_REQ is for retrieving the hash/hmac for data
packet of known size.
QCEDEV_IOCTL_GET_CMAC_REQ is for retrieving the MAC (using AES CMAC
algorithm) for data packet of known size.
The caller of the IOCTL passes a pointer to the structure shown
below, as the second parameter.
struct qcedev_sha_op_req {
struct buf_info data[QCEDEV_MAX_BUFFERS];
uint32_t entries;
uint32_t data_len;
uint8_t digest[QCEDEV_MAX_SHA_DIGEST];
uint32_t diglen;
uint8_t *authkey;
uint32_t authklen;
enum qcedev_sha_alg_enum alg;
struct qcedev_sha_ctxt ctxt;
};
The IOCTLs and associated request data structures are defined in
kernel/drivers/crypto/msm/inc/qcedev.h..
Module parameters:
==================
The following module parameters are defined in the board init file.
-CE hardware nase register address
-Data mover channel used for transfer to/from CE hardware
These parameters differ in each platform.
Dependencies:
=============
qce driver. Please see Documentation/arm/msm/qce.txt.
User space utilities:
=====================
none
Known issues:
=============
none.
To do:
======
Enhance Cipher functionality:
(1) Add support for handling > 32KB for ciphering functionality when
- operation is not an "in place" operation (source != destination).
(when using PMEM allocated memory)
Limitations:
============
(1) In case of cipher functionality, Driver does not support
a combination of different memory sources for source/destination.
In other words, memory pointed to by src and dst,
must BOTH (src/dst) be "pmem" or BOTH(src/dst) be "vbuf".
(2) In case of hash functionality, driver does not support handling data
buffers allocated via PMEM.
(3) Do not load this driver if your device already has kernel space apps
that need to access the crypto hardware.
Make sure to have qcedev module disabled/unloaded and implement your user
space application to use the software implemenation (ex: openssl/crypto)
of the crypto algorithms.
(NOTE: Please refer to details on the limitations listed in qce.txt)
(4) If your device has Playready (Windows Media DRM) application enabled
and uses the qcedev module to access the crypto hardware accelarator,
please be informed that for performance reasons, the CE hardware will
need to be dedicated to playready application. Any other user space
application should be implemented to use the software implemenation
(ex: openssl/crypto) of the crypto algorithms.

View File

@ -0,0 +1,144 @@
Introduction:
=============
Qualcomm Crypto (qcrypto) driver is a Linux crypto driver which interfaces
with the Linux kernel crypto API layer to provide the HW crypto functions.
This driver is accessed by kernel space apps via the kernel crypto API layer.
At present there is no means for user space apps to access this module.
Hardware description:
=====================
Qualcomm Crypto HW device family provides a series of algorithms implemented
in the device.
Crypto 2 hardware provides hashing - SHA-1, SHA-256, ciphering - DES, 3DES, AES
algorithms, and concurrent operations of hashing, and ciphering.
In addition to those functions provided by Crypto 2 HW, Crypto 3 provides fast
AES algorithms.
In addition to those functions provided by Crypto 3 HW, Crypto 3E provides
HMAC-SHA1 hashing algorithm.
In addition to those functions provided by Crypto 3 HW, Crypto 4.0 provides
HMAC-SHA1/SHA256, AES CBC-MAC hashing algorithm and AES XTS/CCM cipher
algorithms.
Software description
====================
The module init function (_qcrypto_init()), does a platform_register(),
to register the driver. As the result, the driver probe function,
_qcrypto_probe(), will be invoked for each registered device.
In the probe function, driver opens the low level CE (qce_open), and
registers the supported algorithms to the kernel crypto API layer.
Currently, qcrypto supports the following algorithms.
ablkcipher -
cbc(aes),ecb(aes),ctr(aes)
ahash -
sha1, sha256
aead -
authenc(hmac(sha1),cbc(aes))
The hmac(sha1), hmac(sha256, authenc(hmac(sha1),cbc(aes)), ccm(aes)
and xts(aes) algorithms are registered for some platforms that
support these in the CE hardware
The HW device can support various algorithms. However, the most important
algorithms to gain the performance using a HW crypto accelerator are
AEAD, and ABLKCIPHER.
AEAD stands for "authentication encryption with association data".
ABLKCIPHER stands of "asynchronous block cipher".
The AEAD structure is described in the following header file
LINUX/opensource/kernel/include/crypto/aead.h
The design of the driver is to allow multiple requests
issued from kernel client SW (eg IPSec).
Therefore, the driver will have to internally queue the requests, and
serialize the requests to the low level qce driver.
When a request is received from the client, if there is no outstanding
request, a qce (or qce40) request is issued, otherwise, the request is
queued in the driver queue.
On completion of a request, the qce (or qce40) invokes the registered
callback from the qcrypto. The internal tasklet (done_tasklet) is scheduled
in this callback function. The sole purpose of done_tasklet is
to call the completion of the current active request, and
issue more requests to the qce (or qce40), if any exists.
A spin lock is used to protect the critical section of internal queue to
be accessed from multiple tasks, SMP, and completion callback
from qce.
The driver maintains a set of statistics using debug fs. The files are
in /debug/qcrypto/stats1, /debug/qcrypto/stats2, /debug/qcrypto/stats3;
one for each instance of device. Reading the file associated with
a device will retrieve the driver statistics for that device.
Any write to the file will clear the statistics.
Test vectors for authenc(hmac(sha1),cbc(aes)) algorithm are
developed offline, and imported to crypto/testmgr.c, and crypto/testmgr.h.
Power Management
================
none
Interface:
==========
The kernel interface is defined in
LINUX/opensource/kernel/include/linux/crypto.h.
Module parameters:
==================
All the platform specific parameters are defined in the board init
file, eg. arch/arm/mach-msm/board-mssm7x30.c for msm7x30.
Dependencies:
=============
qce driver.
User space utilities:
=====================
n/a
Known issues:
=============
n/a
To do:
======
Add Hashing algorithms.
Limitations:
===============
(1) Each packet transfer size (for cipher and hash) is limited to maximum of
32KB. This is a limitation in the crypto engine hardware. Client will
have to break packets larger than 32KB into multiple requests of smaller
size data packets.
(2) Do not load this driver if your device has user space apps that needs to
access the crypto hardware. Please make sure to have the qcrypto module
disabled/unloaded.
Not having the driver loaded, will result in the kernel space apps to use
the registered software implementation of the crypto algorithms.
(3) If your device has Playready application enabled and uses the qcedev module
to access the crypto hardware accelarator, please be informed that for
performance reasons, the CE hardware will need to be dedicated to playready
application. Any other user space or kernel application should be implemented
to use the software implemenation of the crypto algorithms.
(NOTE: Please refer to details on the limitations listed in qce/40.txt)

View File

@ -285,6 +285,49 @@ config CRYPTO_DEV_S5P
Select this to offload Samsung S5PV210 or S5PC110 from AES
algorithms execution.
config CRYPTO_DEV_QCE40
bool
config CRYPTO_DEV_QCRYPTO
tristate "Qualcomm Crypto accelerator"
select CRYPTO_DES
select CRYPTO_ALGAPI
select CRYPTO_AUTHENC
select CRYPTO_BLKCIPHER
default n
help
This driver supports Qualcomm crypto acceleration.
To compile this driver as a module, choose M here: the
module will be called qcrypto.
config CRYPTO_DEV_QCE
tristate "Qualcomm Crypto Engine (QCE) module"
select CRYPTO_DEV_QCE40 if ARCH_MSM8960 || ARCH_MSM9615
default n
help
This driver supports Qualcomm Crypto Engine in MSM7x30, MSM8660
MSM8x55, MSM8960 and MSM9615
To compile this driver as a module, choose M here: the
For MSM7x30 MSM8660 and MSM8x55 the module is called qce
For MSM8960 and MSM9615 the module is called qce40
config CRYPTO_DEV_QCEDEV
tristate "QCEDEV Interface to CE module"
default n
help
This driver supports Qualcomm QCEDEV Crypto in MSM7x30, MSM8660,
MSM8960 and MSM9615.
This exposes the interface to the QCE hardware accelerator via IOCTLs
To compile this driver as a module, choose M here: the
module will be called qcedev.
config CRYPTO_DEV_OTA_CRYPTO
tristate "OTA Crypto module"
help
This driver supports Qualcomm OTA Crypto in the FSM9xxx.
To compile this driver as a module, choose M here: the
module will be called ota_crypto.
config CRYPTO_DEV_TEGRA_AES
tristate "Support for TEGRA AES hw engine"
depends on ARCH_TEGRA

View File

@ -9,6 +9,7 @@ obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam/
obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o
obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
obj-$(CONFIG_CRYPTO_DEV_QCE) += msm/
obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o

View File

@ -0,0 +1,8 @@
obj-$(CONFIG_CRYPTO_DEV_QCEDEV) += qcedev.o
ifeq ($(CONFIG_CRYPTO_DEV_QCE40), y)
obj-$(CONFIG_CRYPTO_DEV_QCE) += qce40.o
else
obj-$(CONFIG_CRYPTO_DEV_QCE) += qce.o
endif
obj-$(CONFIG_CRYPTO_DEV_QCRYPTO) += qcrypto.o
obj-$(CONFIG_CRYPTO_DEV_OTA_CRYPTO) += ota_crypto.o

View File

@ -0,0 +1,731 @@
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/* Qualcomm Over the Air (OTA) Crypto driver */
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/dmapool.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/debugfs.h>
#include <linux/qcota.h>
#include "qce.h"
#include "qce_ota.h"
enum qce_ota_oper_enum {
QCE_OTA_F8_OPER = 0,
QCE_OTA_MPKT_F8_OPER = 1,
QCE_OTA_F9_OPER = 2,
QCE_OTA_OPER_LAST
};
struct ota_dev_control;
struct ota_async_req {
struct list_head list;
struct completion complete;
int err;
enum qce_ota_oper_enum op;
union {
struct qce_f9_req f9_req;
struct qce_f8_req f8_req;
struct qce_f8_multi_pkt_req f8_mp_req;
} req;
struct ota_dev_control *podev;
};
/*
* Register ourselves as a misc device to be able to access the ota
* from userspace.
*/
#define QCOTA_DEV "qcota"
struct ota_dev_control {
/* misc device */
struct miscdevice miscdevice;
/* qce handle */
void *qce;
/* platform device */
struct platform_device *pdev;
unsigned magic;
struct list_head ready_commands;
struct ota_async_req *active_command;
spinlock_t lock;
struct tasklet_struct done_tasklet;
};
#define OTA_MAGIC 0x4f544143
static long qcota_ioctl(struct file *file,
unsigned cmd, unsigned long arg);
static int qcota_open(struct inode *inode, struct file *file);
static int qcota_release(struct inode *inode, struct file *file);
static int start_req(struct ota_dev_control *podev);
static const struct file_operations qcota_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = qcota_ioctl,
.open = qcota_open,
.release = qcota_release,
};
static struct ota_dev_control qcota_dev[] = {
{
.miscdevice = {
.minor = MISC_DYNAMIC_MINOR,
.name = "qcota0",
.fops = &qcota_fops,
},
.magic = OTA_MAGIC,
},
{
.miscdevice = {
.minor = MISC_DYNAMIC_MINOR,
.name = "qcota1",
.fops = &qcota_fops,
},
.magic = OTA_MAGIC,
},
{
.miscdevice = {
.minor = MISC_DYNAMIC_MINOR,
.name = "qcota2",
.fops = &qcota_fops,
},
.magic = OTA_MAGIC,
}
};
#define MAX_OTA_DEVICE ARRAY_SIZE(qcota_dev)
#define DEBUG_MAX_FNAME 16
#define DEBUG_MAX_RW_BUF 1024
struct qcota_stat {
u32 f8_req;
u32 f8_mp_req;
u32 f9_req;
u32 f8_op_success;
u32 f8_op_fail;
u32 f8_mp_op_success;
u32 f8_mp_op_fail;
u32 f9_op_success;
u32 f9_op_fail;
};
static struct qcota_stat _qcota_stat[MAX_OTA_DEVICE];
static struct dentry *_debug_dent;
static char _debug_read_buf[DEBUG_MAX_RW_BUF];
static int _debug_qcota[MAX_OTA_DEVICE];
static struct ota_dev_control *qcota_minor_to_control(unsigned n)
{
int i;
for (i = 0; i < MAX_OTA_DEVICE; i++) {
if (qcota_dev[i].miscdevice.minor == n)
return &qcota_dev[i];
}
return NULL;
}
static int qcota_open(struct inode *inode, struct file *file)
{
struct ota_dev_control *podev;
podev = qcota_minor_to_control(MINOR(inode->i_rdev));
if (podev == NULL) {
pr_err("%s: no such device %d\n", __func__,
MINOR(inode->i_rdev));
return -ENOENT;
}
file->private_data = podev;
return 0;
}
static int qcota_release(struct inode *inode, struct file *file)
{
struct ota_dev_control *podev;
podev = file->private_data;
if (podev != NULL && podev->magic != OTA_MAGIC) {
pr_err("%s: invalid handle %p\n",
__func__, podev);
}
file->private_data = NULL;
return 0;
}
static void req_done(unsigned long data)
{
struct ota_dev_control *podev = (struct ota_dev_control *)data;
struct ota_async_req *areq;
unsigned long flags;
struct ota_async_req *new_req = NULL;
int ret = 0;
spin_lock_irqsave(&podev->lock, flags);
areq = podev->active_command;
podev->active_command = NULL;
again:
if (!list_empty(&podev->ready_commands)) {
new_req = container_of(podev->ready_commands.next,
struct ota_async_req, list);
list_del(&new_req->list);
podev->active_command = new_req;
new_req->err = 0;
ret = start_req(podev);
}
spin_unlock_irqrestore(&podev->lock, flags);
if (areq)
complete(&areq->complete);
if (new_req && ret) {
complete(&new_req->complete);
spin_lock_irqsave(&podev->lock, flags);
podev->active_command = NULL;
areq = NULL;
ret = 0;
new_req = NULL;
goto again;
}
return;
}
static void f9_cb(void *cookie, unsigned char *icv, unsigned char *iv,
int ret)
{
struct ota_async_req *areq = (struct ota_async_req *) cookie;
struct ota_dev_control *podev;
struct qcota_stat *pstat;
podev = areq->podev;
pstat = &_qcota_stat[podev->pdev->id];
areq->req.f9_req.mac_i = (uint32_t) icv;
if (ret)
areq->err = -ENXIO;
else
areq->err = 0;
tasklet_schedule(&podev->done_tasklet);
};
static void f8_cb(void *cookie, unsigned char *icv, unsigned char *iv,
int ret)
{
struct ota_async_req *areq = (struct ota_async_req *) cookie;
struct ota_dev_control *podev;
struct qcota_stat *pstat;
podev = areq->podev;
pstat = &_qcota_stat[podev->pdev->id];
if (ret)
areq->err = -ENXIO;
else
areq->err = 0;
tasklet_schedule(&podev->done_tasklet);
};
static int start_req(struct ota_dev_control *podev)
{
struct ota_async_req *areq;
struct qce_f9_req *pf9;
struct qce_f8_multi_pkt_req *p_mp_f8;
struct qce_f8_req *pf8;
int ret = 0;
/* start the command on the podev->active_command */
areq = podev->active_command;
areq->podev = podev;
switch (areq->op) {
case QCE_OTA_F8_OPER:
pf8 = &areq->req.f8_req;
ret = qce_f8_req(podev->qce, pf8, areq, f8_cb);
break;
case QCE_OTA_MPKT_F8_OPER:
p_mp_f8 = &areq->req.f8_mp_req;
ret = qce_f8_multi_pkt_req(podev->qce, p_mp_f8, areq, f8_cb);
break;
case QCE_OTA_F9_OPER:
pf9 = &areq->req.f9_req;
ret = qce_f9_req(podev->qce, pf9, areq, f9_cb);
break;
default:
ret = -ENOTSUPP;
break;
};
areq->err = ret;
return ret;
};
static int submit_req(struct ota_async_req *areq, struct ota_dev_control *podev)
{
unsigned long flags;
int ret = 0;
struct qcota_stat *pstat;
areq->err = 0;
spin_lock_irqsave(&podev->lock, flags);
if (podev->active_command == NULL) {
podev->active_command = areq;
ret = start_req(podev);
} else {
list_add_tail(&areq->list, &podev->ready_commands);
}
if (ret != 0)
podev->active_command = NULL;
spin_unlock_irqrestore(&podev->lock, flags);
if (ret == 0)
wait_for_completion(&areq->complete);
pstat = &_qcota_stat[podev->pdev->id];
switch (areq->op) {
case QCE_OTA_F8_OPER:
if (areq->err)
pstat->f8_op_fail++;
else
pstat->f8_op_success++;
break;
case QCE_OTA_MPKT_F8_OPER:
if (areq->err)
pstat->f8_mp_op_fail++;
else
pstat->f8_mp_op_success++;
break;
case QCE_OTA_F9_OPER:
default:
if (areq->err)
pstat->f9_op_fail++;
else
pstat->f9_op_success++;
break;
};
return areq->err;
};
static long qcota_ioctl(struct file *file,
unsigned cmd, unsigned long arg)
{
int err = 0;
struct ota_dev_control *podev;
uint8_t *user_src;
uint8_t *user_dst;
uint8_t *k_buf = NULL;
struct ota_async_req areq;
uint32_t total;
struct qcota_stat *pstat;
podev = file->private_data;
if (podev == NULL || podev->magic != OTA_MAGIC) {
pr_err("%s: invalid handle %p\n",
__func__, podev);
return -ENOENT;
}
/* Verify user arguments. */
if (_IOC_TYPE(cmd) != QCOTA_IOC_MAGIC)
return -ENOTTY;
init_completion(&areq.complete);
pstat = &_qcota_stat[podev->pdev->id];
switch (cmd) {
case QCOTA_F9_REQ:
if (!access_ok(VERIFY_WRITE, (void __user *)arg,
sizeof(struct qce_f9_req)))
return -EFAULT;
if (__copy_from_user(&areq.req.f9_req, (void __user *)arg,
sizeof(struct qce_f9_req)))
return -EFAULT;
user_src = areq.req.f9_req.message;
if (!access_ok(VERIFY_READ, (void __user *)user_src,
areq.req.f9_req.msize))
return -EFAULT;
k_buf = kmalloc(areq.req.f9_req.msize, GFP_KERNEL);
if (k_buf == NULL)
return -ENOMEM;
if (__copy_from_user(k_buf, (void __user *)user_src,
areq.req.f9_req.msize)) {
kfree(k_buf);
return -EFAULT;
}
areq.req.f9_req.message = k_buf;
areq.op = QCE_OTA_F9_OPER;
pstat->f9_req++;
err = submit_req(&areq, podev);
areq.req.f9_req.message = user_src;
if (err == 0 && __copy_to_user((void __user *)arg,
&areq.req.f9_req, sizeof(struct qce_f9_req))) {
err = -EFAULT;
}
kfree(k_buf);
break;
case QCOTA_F8_REQ:
if (!access_ok(VERIFY_WRITE, (void __user *)arg,
sizeof(struct qce_f8_req)))
return -EFAULT;
if (__copy_from_user(&areq.req.f8_req, (void __user *)arg,
sizeof(struct qce_f8_req)))
return -EFAULT;
total = areq.req.f8_req.data_len;
user_src = areq.req.f8_req.data_in;
if (user_src != NULL) {
if (!access_ok(VERIFY_READ, (void __user *)
user_src, total))
return -EFAULT;
};
user_dst = areq.req.f8_req.data_out;
if (!access_ok(VERIFY_WRITE, (void __user *)
user_dst, total))
return -EFAULT;
k_buf = kmalloc(total, GFP_KERNEL);
if (k_buf == NULL)
return -ENOMEM;
/* k_buf returned from kmalloc should be cache line aligned */
if (user_src && __copy_from_user(k_buf,
(void __user *)user_src, total)) {
kfree(k_buf);
return -EFAULT;
}
if (user_src)
areq.req.f8_req.data_in = k_buf;
else
areq.req.f8_req.data_in = NULL;
areq.req.f8_req.data_out = k_buf;
areq.op = QCE_OTA_F8_OPER;
pstat->f8_req++;
err = submit_req(&areq, podev);
if (err == 0 && __copy_to_user(user_dst, k_buf, total))
err = -EFAULT;
kfree(k_buf);
break;
case QCOTA_F8_MPKT_REQ:
if (!access_ok(VERIFY_WRITE, (void __user *)arg,
sizeof(struct qce_f8_multi_pkt_req)))
return -EFAULT;
if (__copy_from_user(&areq.req.f8_mp_req, (void __user *)arg,
sizeof(struct qce_f8_multi_pkt_req)))
return -EFAULT;
total = areq.req.f8_mp_req.num_pkt *
areq.req.f8_mp_req.qce_f8_req.data_len;
user_src = areq.req.f8_mp_req.qce_f8_req.data_in;
if (!access_ok(VERIFY_READ, (void __user *)
user_src, total))
return -EFAULT;
user_dst = areq.req.f8_mp_req.qce_f8_req.data_out;
if (!access_ok(VERIFY_WRITE, (void __user *)
user_dst, total))
return -EFAULT;
k_buf = kmalloc(total, GFP_KERNEL);
if (k_buf == NULL)
return -ENOMEM;
/* k_buf returned from kmalloc should be cache line aligned */
if (__copy_from_user(k_buf, (void __user *)user_src, total)) {
kfree(k_buf);
return -EFAULT;
}
areq.req.f8_mp_req.qce_f8_req.data_out = k_buf;
areq.req.f8_mp_req.qce_f8_req.data_in = k_buf;
areq.op = QCE_OTA_MPKT_F8_OPER;
pstat->f8_mp_req++;
err = submit_req(&areq, podev);
if (err == 0 && __copy_to_user(user_dst, k_buf, total))
err = -EFAULT;
kfree(k_buf);
break;
default:
return -ENOTTY;
}
return err;
}
static int qcota_probe(struct platform_device *pdev)
{
void *handle = NULL;
int rc = 0;
struct ota_dev_control *podev;
struct ce_hw_support ce_support;
if (pdev->id >= MAX_OTA_DEVICE) {
pr_err("%s: device id %d exceeds allowed %d\n",
__func__, pdev->id, MAX_OTA_DEVICE);
return -ENOENT;
}
podev = &qcota_dev[pdev->id];
INIT_LIST_HEAD(&podev->ready_commands);
podev->active_command = NULL;
spin_lock_init(&podev->lock);
tasklet_init(&podev->done_tasklet, req_done, (unsigned long)podev);
/* open qce */
handle = qce_open(pdev, &rc);
if (handle == NULL) {
pr_err("%s: device id %d, can not open qce\n",
__func__, pdev->id);
platform_set_drvdata(pdev, NULL);
return rc;
}
if (qce_hw_support(handle, &ce_support) < 0 ||
ce_support.ota == false) {
pr_err("%s: device id %d, qce does not support ota capability\n",
__func__, pdev->id);
rc = -ENODEV;
goto err;
}
podev->qce = handle;
podev->pdev = pdev;
platform_set_drvdata(pdev, podev);
rc = misc_register(&podev->miscdevice);
if (rc < 0)
goto err;
return 0;
err:
if (handle)
qce_close(handle);
platform_set_drvdata(pdev, NULL);
podev->qce = NULL;
podev->pdev = NULL;
return rc;
};
static int qcota_remove(struct platform_device *pdev)
{
struct ota_dev_control *podev;
podev = platform_get_drvdata(pdev);
if (!podev)
return 0;
if (podev->qce)
qce_close(podev->qce);
if (podev->miscdevice.minor != MISC_DYNAMIC_MINOR)
misc_deregister(&podev->miscdevice);
tasklet_kill(&podev->done_tasklet);
return 0;
};
static struct platform_driver qcota_plat_driver = {
.probe = qcota_probe,
.remove = qcota_remove,
.driver = {
.name = "qcota",
.owner = THIS_MODULE,
},
};
static int _disp_stats(int id)
{
struct qcota_stat *pstat;
int len = 0;
pstat = &_qcota_stat[id];
len = snprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
"\nQualcomm OTA crypto accelerator %d Statistics:\n",
id + 1);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F8 request : %d\n",
pstat->f8_req);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F8 operation success : %d\n",
pstat->f8_op_success);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F8 operation fail : %d\n",
pstat->f8_op_fail);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F8 MP request : %d\n",
pstat->f8_mp_req);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F8 MP operation success: %d\n",
pstat->f8_mp_op_success);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F8 MP operation fail : %d\n",
pstat->f8_mp_op_fail);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F9 request : %d\n",
pstat->f9_req);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F9 operation success : %d\n",
pstat->f9_op_success);
len += snprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
" F9 operation fail : %d\n",
pstat->f9_op_fail);
return len;
}
static int _debug_stats_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static ssize_t _debug_stats_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
int rc = -EINVAL;
int qcota = *((int *) file->private_data);
int len;
len = _disp_stats(qcota);
rc = simple_read_from_buffer((void __user *) buf, len,
ppos, (void *) _debug_read_buf, len);
return rc;
}
static ssize_t _debug_stats_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
int qcota = *((int *) file->private_data);
memset((char *)&_qcota_stat[qcota], 0, sizeof(struct qcota_stat));
return count;
};
static const struct file_operations _debug_stats_ops = {
.open = _debug_stats_open,
.read = _debug_stats_read,
.write = _debug_stats_write,
};
static int _qcota_debug_init(void)
{
int rc;
char name[DEBUG_MAX_FNAME];
int i;
struct dentry *dent;
_debug_dent = debugfs_create_dir("qcota", NULL);
if (IS_ERR(_debug_dent)) {
pr_err("qcota debugfs_create_dir fail, error %ld\n",
PTR_ERR(_debug_dent));
return PTR_ERR(_debug_dent);
}
for (i = 0; i < MAX_OTA_DEVICE; i++) {
snprintf(name, DEBUG_MAX_FNAME-1, "stats-%d", i+1);
_debug_qcota[i] = i;
dent = debugfs_create_file(name, 0644, _debug_dent,
&_debug_qcota[i], &_debug_stats_ops);
if (dent == NULL) {
pr_err("qcota debugfs_create_file fail, error %ld\n",
PTR_ERR(dent));
rc = PTR_ERR(dent);
goto err;
}
}
return 0;
err:
debugfs_remove_recursive(_debug_dent);
return rc;
}
static int __init qcota_init(void)
{
int rc;
rc = _qcota_debug_init();
if (rc)
return rc;
return platform_driver_register(&qcota_plat_driver);
}
static void __exit qcota_exit(void)
{
debugfs_remove_recursive(_debug_dent);
platform_driver_unregister(&qcota_plat_driver);
}
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Rohit Vaswani <rvaswani@codeaurora.org>");
MODULE_DESCRIPTION("Qualcomm Ota Crypto driver");
MODULE_VERSION("1.01");
module_init(qcota_init);
module_exit(qcota_exit);

2709
drivers/crypto/msm/qce.c Normal file

File diff suppressed because it is too large Load Diff

160
drivers/crypto/msm/qce.h Normal file
View File

@ -0,0 +1,160 @@
/* Qualcomm Crypto Engine driver API
*
* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __CRYPTO_MSM_QCE_H
#define __CRYPTO_MSM_QCE_H
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/crypto.h>
#include <crypto/algapi.h>
#include <crypto/aes.h>
#include <crypto/des.h>
#include <crypto/sha.h>
#include <crypto/aead.h>
#include <crypto/authenc.h>
#include <crypto/scatterwalk.h>
/* SHA digest size in bytes */
#define SHA256_DIGESTSIZE 32
#define SHA1_DIGESTSIZE 20
/* key size in bytes */
#define HMAC_KEY_SIZE (SHA1_DIGESTSIZE) /* hmac-sha1 */
#define SHA_HMAC_KEY_SIZE 64
#define DES_KEY_SIZE 8
#define TRIPLE_DES_KEY_SIZE 24
#define AES128_KEY_SIZE 16
#define AES192_KEY_SIZE 24
#define AES256_KEY_SIZE 32
#define MAX_CIPHER_KEY_SIZE AES256_KEY_SIZE
/* iv length in bytes */
#define AES_IV_LENGTH 16
#define DES_IV_LENGTH 8
#define MAX_IV_LENGTH AES_IV_LENGTH
/* Maximum number of bytes per transfer */
#define QCE_MAX_OPER_DATA 0xFF00
/* Maximum Nonce bytes */
#define MAX_NONCE 16
typedef void (*qce_comp_func_ptr_t)(void *areq,
unsigned char *icv, unsigned char *iv, int ret);
/* Cipher algorithms supported */
enum qce_cipher_alg_enum {
CIPHER_ALG_DES = 0,
CIPHER_ALG_3DES = 1,
CIPHER_ALG_AES = 2,
CIPHER_ALG_LAST
};
/* Hash and hmac algorithms supported */
enum qce_hash_alg_enum {
QCE_HASH_SHA1 = 0,
QCE_HASH_SHA256 = 1,
QCE_HASH_SHA1_HMAC = 2,
QCE_HASH_SHA256_HMAC = 3,
QCE_HASH_AES_CMAC = 4,
QCE_HASH_LAST
};
/* Cipher encryption/decryption operations */
enum qce_cipher_dir_enum {
QCE_ENCRYPT = 0,
QCE_DECRYPT = 1,
QCE_CIPHER_DIR_LAST
};
/* Cipher algorithms modes */
enum qce_cipher_mode_enum {
QCE_MODE_CBC = 0,
QCE_MODE_ECB = 1,
QCE_MODE_CTR = 2,
QCE_MODE_XTS = 3,
QCE_MODE_CCM = 4,
QCE_CIPHER_MODE_LAST
};
/* Cipher operation type */
enum qce_req_op_enum {
QCE_REQ_ABLK_CIPHER = 0,
QCE_REQ_ABLK_CIPHER_NO_KEY = 1,
QCE_REQ_AEAD = 2,
QCE_REQ_LAST
};
/* Algorithms/features supported in CE HW engine */
struct ce_hw_support {
bool sha1_hmac_20; /* Supports 20 bytes of HMAC key*/
bool sha1_hmac; /* supports max HMAC key of 64 bytes*/
bool sha256_hmac; /* supports max HMAC key of 64 bytes*/
bool sha_hmac; /* supports SHA1 and SHA256 MAX HMAC key of 64 bytes*/
bool cmac;
bool aes_key_192;
bool aes_xts;
bool aes_ccm;
bool ota;
};
/* Sha operation parameters */
struct qce_sha_req {
qce_comp_func_ptr_t qce_cb; /* call back */
enum qce_hash_alg_enum alg; /* sha algorithm */
unsigned char *digest; /* sha digest */
struct scatterlist *src; /* pointer to scatter list entry */
uint32_t auth_data[4]; /* byte count */
unsigned char *authkey; /* auth key */
unsigned int authklen; /* auth key length */
bool first_blk; /* first block indicator */
bool last_blk; /* last block indicator */
unsigned int size; /* data length in bytes */
void *areq;
};
struct qce_req {
enum qce_req_op_enum op; /* operation type */
qce_comp_func_ptr_t qce_cb; /* call back */
void *areq;
enum qce_cipher_alg_enum alg; /* cipher algorithms*/
enum qce_cipher_dir_enum dir; /* encryption? decryption? */
enum qce_cipher_mode_enum mode; /* algorithm mode */
unsigned char *authkey; /* authentication key */
unsigned int authklen; /* authentication key kength */
unsigned int authsize; /* authentication key kength */
unsigned char nonce[MAX_NONCE];/* nonce for ccm mode */
unsigned char *assoc; /* Ptr to formatted associated data */
unsigned int assoclen; /* Formatted associated data length */
struct scatterlist *asg; /* Formatted associated data sg */
unsigned char *enckey; /* cipher key */
unsigned int encklen; /* cipher key length */
unsigned char *iv; /* initialization vector */
unsigned int ivsize; /* initialization vector size*/
unsigned int cryptlen; /* data length */
unsigned int use_pmem; /* is source of data PMEM allocated? */
struct qcedev_pmem_info *pmem; /* pointer to pmem_info structure*/
};
void *qce_open(struct platform_device *pdev, int *rc);
int qce_close(void *handle);
int qce_aead_req(void *handle, struct qce_req *req);
int qce_ablk_cipher_req(void *handle, struct qce_req *req);
int qce_hw_support(void *handle, struct ce_hw_support *support);
int qce_process_sha_req(void *handle, struct qce_sha_req *s_req);
#endif /* __CRYPTO_MSM_QCE_H */

2609
drivers/crypto/msm/qce40.c Normal file

File diff suppressed because it is too large Load Diff

240
drivers/crypto/msm/qce40.h Normal file
View File

@ -0,0 +1,240 @@
/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _DRIVERS_CRYPTO_MSM_QCE40_H_
#define _DRIVERS_CRYPTO_MSM_QCE40_H_
#define GET_VIRT_ADDR(x) \
((uint32_t)pce_dev->coh_vmem + \
((uint32_t)x - pce_dev->coh_pmem))
#define GET_PHYS_ADDR(x) \
(pce_dev->coh_pmem + ((unsigned char *)x - \
pce_dev->coh_vmem))
/* Sets the adddress of a command list in command pointer list */
#define QCE_SET_CMD_PTR(x) \
(uint32_t)(DMOV_CMD_ADDR(GET_PHYS_ADDR((unsigned char *)x)))
/* Sets the adddress of the last command list in command pointer list */
#define SET_LAST_CMD_PTR(x) \
((DMOV_CMD_ADDR(x)) | CMD_PTR_LP)
/* Get the adddress of the last command list in command pointer list */
#define QCE_SET_LAST_CMD_PTR(x) \
SET_LAST_CMD_PTR((GET_PHYS_ADDR((unsigned char *)x)))
/* MAX Data xfer block size between DM and CE */
#define MAX_ADM_CE_BLOCK_SIZE 64
#define ADM_DESC_LENGTH_MASK 0xffff
#define ADM_DESC_LENGTH(x) (x & ADM_DESC_LENGTH_MASK)
#define ADM_STATUS_OK 0x80000002
/* QCE max number of descriptor in a descriptor list */
#define QCE_MAX_NUM_DESC 128
#define CRYPTO_REG_SIZE 0x4
struct dmov_desc {
uint32_t addr;
uint32_t len;
};
/* State of DM channel */
enum qce_chan_st_enum {
QCE_CHAN_STATE_IDLE = 0,
QCE_CHAN_STATE_IN_PROG = 1,
QCE_CHAN_STATE_COMP = 2,
QCE_CHAN_STATE_LAST
};
/* CE buffers */
struct ce_reg_buffer_addr {
unsigned char *reset_buf_64;
unsigned char *version;
unsigned char *encr_seg_cfg_size_start;
unsigned char *encr_key;
unsigned char *encr_xts_key;
unsigned char *encr_cntr_iv;
unsigned char *encr_mask;
unsigned char *encr_xts_du_size;
unsigned char *auth_seg_cfg_size_start;
unsigned char *auth_key;
unsigned char *auth_iv;
unsigned char *auth_result;
unsigned char *auth_nonce_info;
unsigned char *auth_byte_count;
unsigned char *seg_size;
unsigned char *go_proc;
unsigned char *status;
unsigned char *pad;
unsigned char *ignore_data;
};
/* CE buffers */
struct ce_reg_buffers {
unsigned char reset_buf_64[64];
unsigned char version[CRYPTO_REG_SIZE];
unsigned char encr_seg_cfg_size_start[3 * CRYPTO_REG_SIZE];
unsigned char encr_key[8 * CRYPTO_REG_SIZE];
unsigned char encr_xts_key[8 * CRYPTO_REG_SIZE];
unsigned char encr_cntr_iv[4 * CRYPTO_REG_SIZE];
unsigned char encr_mask[CRYPTO_REG_SIZE];
unsigned char encr_xts_du_size[CRYPTO_REG_SIZE];
unsigned char auth_seg_cfg_size_start[3 * CRYPTO_REG_SIZE];
unsigned char auth_key[16 * CRYPTO_REG_SIZE];
unsigned char auth_iv[16 * CRYPTO_REG_SIZE];
unsigned char auth_result[16 * CRYPTO_REG_SIZE];
unsigned char auth_nonce_info[4 * CRYPTO_REG_SIZE];
unsigned char auth_byte_count[4 * CRYPTO_REG_SIZE];
unsigned char seg_size[CRYPTO_REG_SIZE];
unsigned char go_proc[CRYPTO_REG_SIZE];
unsigned char status[CRYPTO_REG_SIZE];
unsigned char pad[2 * MAX_ADM_CE_BLOCK_SIZE];
};
/* CE Command lists */
struct ce_cmdlists {
dmov_s *get_hw_version;
dmov_s *clear_status;
dmov_s *get_status_ocu;
dmov_s *set_cipher_cfg;
dmov_s *set_cipher_aes_128_key;
dmov_s *set_cipher_aes_256_key;
dmov_s *set_cipher_des_key;
dmov_s *set_cipher_3des_key;
dmov_s *set_cipher_aes_128_xts_key;
dmov_s *set_cipher_aes_256_xts_key;
dmov_s *set_cipher_xts_du_size;
dmov_s *set_cipher_aes_iv;
dmov_s *set_cipher_aes_xts_iv;
dmov_s *set_cipher_des_iv;
dmov_s *get_cipher_iv;
dmov_s *set_cipher_mask;
dmov_s *set_auth_cfg;
dmov_s *set_auth_key_128;
dmov_s *set_auth_key_256;
dmov_s *set_auth_key_512;
dmov_s *set_auth_iv_16;
dmov_s *get_auth_result_16;
dmov_s *set_auth_iv_20;
dmov_s *get_auth_result_20;
dmov_s *set_auth_iv_32;
dmov_s *get_auth_result_32;
dmov_s *set_auth_byte_count;
dmov_s *get_auth_byte_count;
dmov_s *set_auth_nonce_info;
dmov_s *reset_cipher_key;
dmov_s *reset_cipher_xts_key;
dmov_s *reset_cipher_iv;
dmov_s *reset_cipher_cfg;
dmov_s *reset_auth_key;
dmov_s *reset_auth_iv;
dmov_s *reset_auth_cfg;
dmov_s *reset_auth_byte_count;
dmov_s *set_seg_size_ocb;
dmov_s *get_status_wait;
dmov_s *set_go_proc;
dmov_sg *ce_data_in;
dmov_sg *ce_data_out;
};
/* Command pointer lists */
struct ce_cmdptrlists_ops {
uint32_t probe_ce_hw;
uint32_t cipher_aes_128_cbc_ctr;
uint32_t cipher_aes_256_cbc_ctr;
uint32_t cipher_aes_128_ecb;
uint32_t cipher_aes_256_ecb;
uint32_t cipher_aes_128_xts;
uint32_t cipher_aes_256_xts;
uint32_t cipher_des_cbc;
uint32_t cipher_des_ecb;
uint32_t cipher_3des_cbc;
uint32_t cipher_3des_ecb;
uint32_t auth_sha1;
uint32_t auth_sha256;
uint32_t auth_sha1_hmac;
uint32_t auth_sha256_hmac;
uint32_t auth_aes_128_cmac;
uint32_t auth_aes_256_cmac;
uint32_t aead_aes_128_ccm;
uint32_t aead_aes_256_ccm;
uint32_t cipher_ce_out;
uint32_t cipher_ce_out_get_iv;
uint32_t aead_ce_out;
};
/* DM data structure with buffers, commandlists & commmand pointer lists */
struct ce_dm_data {
unsigned int chan_ce_in; /* ADM channel used for CE input
* and auth result if authentication
* only operation. */
unsigned int chan_ce_out; /* ADM channel used for CE output,
* and icv for esp */
unsigned int crci_in; /* CRCI for CE DM IN Channel */
unsigned int crci_out; /* CRCI for CE DM OUT Channel */
enum qce_chan_st_enum chan_ce_in_state; /* chan ce_in state */
enum qce_chan_st_enum chan_ce_out_state; /* chan ce_out state */
int chan_ce_in_status; /* chan ce_in status */
int chan_ce_out_status; /* chan ce_out status */
struct dmov_desc *ce_out_src_desc;
struct dmov_desc *ce_out_dst_desc;
struct dmov_desc *ce_in_src_desc;
struct dmov_desc *ce_in_dst_desc;
int ce_out_src_desc_index;
int ce_out_dst_desc_index;
int ce_in_src_desc_index;
int ce_in_dst_desc_index;
int ce_block_size;
dma_addr_t phy_ce_out_ignore;
dma_addr_t phy_ce_pad;
struct ce_reg_buffer_addr buffer;
struct ce_cmdlists cmdlist;
struct ce_cmdptrlists_ops cmdptrlist;
struct msm_dmov_cmd *chan_ce_in_cmd;
struct msm_dmov_cmd *chan_ce_out_cmd;
};
#endif /* _DRIVERS_CRYPTO_MSM_QCE40_H */

View File

@ -0,0 +1,30 @@
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/* Qualcomm Crypto Engine driver OTA APIi */
#ifndef __CRYPTO_MSM_QCE_OTA_H
#define __CRYPTO_MSM_QCE_OTA_H
#include <linux/platform_device.h>
#include <linux/qcota.h>
int qce_f8_req(void *handle, struct qce_f8_req *req,
void *cookie, qce_comp_func_ptr_t qce_cb);
int qce_f8_multi_pkt_req(void *handle, struct qce_f8_multi_pkt_req *req,
void *cookie, qce_comp_func_ptr_t qce_cb);
int qce_f9_req(void *handle, struct qce_f9_req *req,
void *cookie, qce_comp_func_ptr_t qce_cb);
#endif /* __CRYPTO_MSM_QCE_OTA_H */

2228
drivers/crypto/msm/qcedev.c Normal file

File diff suppressed because it is too large Load Diff

3367
drivers/crypto/msm/qcrypto.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,308 @@
/* Copyright (c)2009- 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _DRIVERS_CRYPTO_MSM_QCRYPTOHW_30_H_
#define _DRIVERS_CRYPTO_MSM_QCRYPTOHW_30_H_
#define QCE_AUTH_REG_BYTE_COUNT 2
#define CRYPTO_DATA_IN_REG 0x0
#define CRYPTO_DATA_OUT_REG 0x10
#define CRYPTO_STATUS_REG 0x20
#define CRYPTO_CONFIG_REG 0x24
#define CRYPTO_DEBUG_REG 0x28
#define CRYPTO_REGISTER_LOCK_REG 0x2C
#define CRYPTO_SEG_CFG_REG 0x30
#define CRYPTO_ENCR_SEG_CFG_REG 0x34
#define CRYPTO_AUTH_SEG_CFG_REG 0x38
#define CRYPTO_SEG_SIZE_REG 0x3C
#define CRYPTO_GOPROC_REG 0x40
#define CRYPTO_ENGINES_AVAIL 0x44
#define CRYPTO_DES_KEY0_REG 0x50
#define CRYPTO_DES_KEY1_REG 0x54
#define CRYPTO_DES_KEY2_REG 0x58
#define CRYPTO_DES_KEY3_REG 0x5C
#define CRYPTO_DES_KEY4_REG 0x60
#define CRYPTO_DES_KEY5_REG 0x64
#define CRYPTO_CNTR0_IV0_REG 0x70
#define CRYPTO_CNTR1_IV1_REG 0x74
#define CRYPTO_CNTR2_IV2_REG 0x78
#define CRYPTO_CNTR3_IV3_REG 0x7C
#define CRYPTO_CNTR_MASK_REG 0x80
#define CRYPTO_AUTH_BYTECNT0_REG 0x90
#define CRYPTO_AUTH_BYTECNT1_REG 0x94
#define CRYPTO_AUTH_BYTECNT2_REG 0x98
#define CRYPTO_AUTH_BYTECNT3_REG 0x9C
#define CRYPTO_AUTH_IV0_REG 0x100
#define CRYPTO_AUTH_IV1_REG 0x104
#define CRYPTO_AUTH_IV2_REG 0x108
#define CRYPTO_AUTH_IV3_REG 0x10C
#define CRYPTO_AUTH_IV4_REG 0x110
#define CRYPTO_AUTH_IV5_REG 0x114
#define CRYPTO_AUTH_IV6_REG 0x118
#define CRYPTO_AUTH_IV7_REG 0x11C
#define CRYPTO_AUTH_IV8_REG 0x120
#define CRYPTO_AUTH_IV9_REG 0x124
#define CRYPTO_AUTH_IV10_REG 0x128
#define CRYPTO_AUTH_IV11_REG 0x12C
#define CRYPTO_AUTH_IV12_REG 0x130
#define CRYPTO_AUTH_IV13_REG 0x134
#define CRYPTO_AUTH_IV14_REG 0x138
#define CRYPTO_AUTH_IV15_REG 0x13C
#define CRYPTO_AES_RNDKEY0 0x200
#define CRYPTO_AES_RNDKEY1 0x204
#define CRYPTO_AES_RNDKEY2 0x208
#define CRYPTO_AES_RNDKEY3 0x20C
#define CRYPTO_AES_RNDKEY4 0x210
#define CRYPTO_AES_RNDKEY5 0x214
#define CRYPTO_AES_RNDKEY6 0x218
#define CRYPTO_AES_RNDKEY7 0x21C
#define CRYPTO_AES_RNDKEY8 0x220
#define CRYPTO_AES_RNDKEY9 0x224
#define CRYPTO_AES_RNDKEY10 0x228
#define CRYPTO_AES_RNDKEY11 0x22c
#define CRYPTO_AES_RNDKEY12 0x230
#define CRYPTO_AES_RNDKEY13 0x234
#define CRYPTO_AES_RNDKEY14 0x238
#define CRYPTO_AES_RNDKEY15 0x23C
#define CRYPTO_AES_RNDKEY16 0x240
#define CRYPTO_AES_RNDKEY17 0x244
#define CRYPTO_AES_RNDKEY18 0x248
#define CRYPTO_AES_RNDKEY19 0x24C
#define CRYPTO_AES_RNDKEY20 0x250
#define CRYPTO_AES_RNDKEY21 0x254
#define CRYPTO_AES_RNDKEY22 0x258
#define CRYPTO_AES_RNDKEY23 0x25C
#define CRYPTO_AES_RNDKEY24 0x260
#define CRYPTO_AES_RNDKEY25 0x264
#define CRYPTO_AES_RNDKEY26 0x268
#define CRYPTO_AES_RNDKEY27 0x26C
#define CRYPTO_AES_RNDKEY28 0x270
#define CRYPTO_AES_RNDKEY29 0x274
#define CRYPTO_AES_RNDKEY30 0x278
#define CRYPTO_AES_RNDKEY31 0x27C
#define CRYPTO_AES_RNDKEY32 0x280
#define CRYPTO_AES_RNDKEY33 0x284
#define CRYPTO_AES_RNDKEY34 0x288
#define CRYPTO_AES_RNDKEY35 0x28c
#define CRYPTO_AES_RNDKEY36 0x290
#define CRYPTO_AES_RNDKEY37 0x294
#define CRYPTO_AES_RNDKEY38 0x298
#define CRYPTO_AES_RNDKEY39 0x29C
#define CRYPTO_AES_RNDKEY40 0x2A0
#define CRYPTO_AES_RNDKEY41 0x2A4
#define CRYPTO_AES_RNDKEY42 0x2A8
#define CRYPTO_AES_RNDKEY43 0x2AC
#define CRYPTO_AES_RNDKEY44 0x2B0
#define CRYPTO_AES_RNDKEY45 0x2B4
#define CRYPTO_AES_RNDKEY46 0x2B8
#define CRYPTO_AES_RNDKEY47 0x2BC
#define CRYPTO_AES_RNDKEY48 0x2C0
#define CRYPTO_AES_RNDKEY49 0x2C4
#define CRYPTO_AES_RNDKEY50 0x2C8
#define CRYPTO_AES_RNDKEY51 0x2CC
#define CRYPTO_AES_RNDKEY52 0x2D0
#define CRYPTO_AES_RNDKEY53 0x2D4
#define CRYPTO_AES_RNDKEY54 0x2D8
#define CRYPTO_AES_RNDKEY55 0x2DC
#define CRYPTO_AES_RNDKEY56 0x2E0
#define CRYPTO_AES_RNDKEY57 0x2E4
#define CRYPTO_AES_RNDKEY58 0x2E8
#define CRYPTO_AES_RNDKEY59 0x2EC
#define CRYPTO_DATA_SHADOW0 0x8000
#define CRYPTO_DATA_SHADOW8191 0x8FFC
/* status reg */
#define CRYPTO_CORE_REV 28 /* bit 31-28 */
#define CRYPTO_CORE_REV_MASK (0xf << CRYPTO_CORE_REV)
#define CRYPTO_DOUT_SIZE_AVAIL 22 /* bit 24-22 */
#define CRYPTO_DOUT_SIZE_AVAIL_MASK (0x7 << CRYPTO_DOUT_SIZE_AVAIL)
#define CRYPTO_DIN_SIZE_AVAIL 19 /* bit 21-19 */
#define CRYPTO_DIN_SIZE_AVAIL_MASK (0x7 << CRYPTO_DIN_SIZE_AVAIL)
#define CRYPTO_ACCESS_VIOL 18
#define CRYPTO_SEG_CHNG_ERR 17
#define CRYPTO_CFH_CHNG_ERR 16
#define CRYPTO_DOUT_ERR 15
#define CRYPTO_DIN_ERR 14
#define CRYPTO_LOCKED 13
#define CRYPTO_CRYPTO_STATE 10 /* bit 12-10 */
#define CRYPTO_CRYPTO_STATE_MASK (0x7 << CRYPTO_CRYPTO_STATE)
#define CRYPTO_ENCR_BUSY 9
#define CRYPTO_AUTH_BUSY 8
#define CRYPTO_DOUT_INTR 7
#define CRYPTO_DIN_INTR 6
#define CRYPTO_AUTH_DONE_INTR 5
#define CRYPTO_ERR_INTR 4
#define CRYPTO_DOUT_RDY 3
#define CRYPTO_DIN_RDY 2
#define CRYPTO_AUTH_DONE 1
#define CRYPTO_SW_ERR 0
#define CRYPTO_CRYPTO_STATE_IDLE 0
#define CRYPTO_CRYPTO_STATE_LOCKED 1
#define CRYPTO_CRYPTO_STATE_GO 3
#define CRYPTO_CRYPTO_STATE_PROCESSING 4
#define CRYPTO_CRYPTO_STATE_FINAL_READ 5
#define CRYPTO_CRYPTO_STATE_CTXT_CLEARING 6
#define CRYPTO_CRYPTO_STATE_UNLOCKING 7
/* config reg */
#define CRYPTO_HIGH_SPD_HASH_EN_N 15
#define CRYPTO_HIGH_SPD_OUT_EN_N 14
#define CRYPTO_HIGH_SPD_IN_EN_N 13
#define CRYPTO_DBG_EN 12
#define CRYPTO_DBG_SEL 7 /* bit 11:7 */
#define CRYPTO_DBG_SEL_MASK (0x1F << CRYPTO_DBG_SEL)
#define CRYPTO_MASK_DOUT_INTR 6
#define CRYPTO_MASK_DIN_INTR 5
#define CRYPTO_MASK_AUTH_DONE_INTR 4
#define CRYPTO_MASK_ERR_INTR 3
#define CRYPTO_AUTO_SHUTDOWN_EN 2
#define CRYPTO_CLK_EN_N 1
#define CRYPTO_SW_RST 0
/* seg_cfg reg */
#define CRYPTO_F8_KEYSTREAM_ENABLE 25
#define CRYPTO_F9_DIRECTION 24
#define CRYPTO_F8_DIRECTION 23
#define CRYPTO_USE_HW_KEY 22
#define CRYPTO_CNTR_ALG 20 /* bit 21-20 */
#define CRYPTO_CNTR_ALG_MASK (3 << efine CRYPTO_CNTR_ALG)
#define CRYPTO_CLR_CNTXT 19
#define CRYPTO_LAST 18
#define CRYPTO_FIRST 17
#define CRYPTO_ENCODE 16
#define CRYPTO_AUTH_POS 14 /* bit 15-14 */
#define CRYPTO_AUTH_POS_MASK (3 << CRYPTO_AUTH_POS)
#define CRYPTO_AUTH_SIZE 11 /* bit 13-11 */
#define CRYPTO_AUTH_SIZE_MASK (7 << CRYPTO_AUTH_SIZE)
#define CRYPTO_AUTH_ALG 9 /* bit 10-9 */
#define CRYPTO_AUTH_ALG_MASK (3 << CRYPTO_AUTH_ALG)
#define CRYPTO_ENCR_MODE 6 /* bit 8-6 */
#define CRYPTO_ENCR_MODE_MASK (7 << CRYPTO_ENCR_MODE)
#define CRYPTO_ENCR_KEY_SZ 3 /* bit 5-3 */
#define CRYPTO_ENCR_KEY_SZ_MASK (7 << CRYPTO_ENCR_KEY_SZ)
#define CRYPTO_ENCR_ALG 0 /* bit 2-0 */
#define CRYPTO_ENCR_ALG_MASK (7 << CRYPTO_ENCR_ALG)
#define CRYPTO_CNTR_ALG_NIST 0
#define CRYPTO_CNTR_ALG_UMB 1
#define CRYPTO_CNTR_ALG_VAR2 2
#define CRYPTO_AUTH_POS_BEFORE 0
#define CRYPTO_AUTH_POS_AFTER 1
#define CRYPTO_AUTH_SIZE_SHA1 0
#define CRYPTO_AUTH_SIZE_SHA256 1
#define CRYPTO_AUTH_SIZE_SHA384 2
#define CRYPTO_AUTH_SIZE_SHA512 3
#define CRYPTO_AUTH_SIZE_HMAC_SHA1 4
#define CRYPTO_AUTH_SIZE_UIA1 0
#define CRYPTO_AUTH_SIZE_UIA2 1
#define CRYPTO_AUTH_ALG_NONE 0
#define CRYPTO_AUTH_ALG_SHA 1
#define CRYPTO_AUTH_ALG_F9 2
#define CRYPTO_AUTH_ALG_RESERVED1 3
#define CRYPTO_ENCR_MODE_ECB 0
#define CRYPTO_ENCR_MODE_CBC 1
/* only valid when AES */
#define CRYPTO_ENCR_MODE_CTR 2
#define CRYPTO_ENCR_KEY_SZ_DES 0
#define CRYPTO_ENCR_KEY_SZ_3DES 1
#define CRYPTO_ENCR_KEY_SZ_AES128 0
#define CRYPTO_ENCR_KEY_SZ_AES192 1
#define CRYPTO_ENCR_KEY_SZ_AES256 2
#define CRYPTO_ENCR_KEY_SZ_UEA1 0
#define CRYPTO_ENCR_KEY_SZ_UEA2 1
#define CRYPTO_ENCR_ALG_NONE 0
#define CRYPTO_ENCR_ALG_DES 1
#define CRYPTO_ENCR_ALG_AES 2
#define CRYPTO_ENCR_ALG_C2 3
#define CRYPTO_ENCR_ALG_F8 4
/* encr_seg_cfg reg */
#define CRYPTO_ENCR_SEG_SIZE 16 /* bit 31-16 */
#define CRYPTO_ENCR_SEG_SIZE_MASK (0xffff << CRYPTO_ENCR_SEG_SIZE)
#define CRYPTO_ENCR_START 0
#define CRYPTO_ENCR_START_MASK (0xffff << CRYPTO_ENCR_START)
/* auth_seg_cfg reg */
#define CRYPTO_AUTH_SEG_SIZE 16 /* bit 31-16 */
#define CRYPTO_AUTH_SEG_SIZE_MASK (0xffff << CRYPTO_AUTH_SEG_SIZE)
#define CRYPTO_AUTH_START 0
#define CRYPTO_AUTH_START_MASK (0xffff << CRYPTO_AUTH_START)
/* seg_size reg */
#define CRYPTO_SEG_SIZE 0
#define CRYPTO_SEG_SIZE_MASK (0xffff << CRYPTO_SEG_SIZE)
/* goproc reg */
#define CRYPTO_GO 0
/* engines_avail */
#define CRYPTO_F9_SEL 8
#define CRYPTO_F8_SEL 7
#define CRYPTO_HMAC_SEL 6
#define CRYPTO_SHA512_SEL 5
#define CRYPTO_SHA_SEL 4
#define CRYPTO_DES_SEL 3
#define CRYPTO_C2_SEL 2
#define CRYPTO_AES_SEL 0 /* bit 1-0 */
#define CRYPTO_AES_SEL_MASK (3 << CRYPTO_AES_SEL)
#define CRYPTO_AES_SEL_NO 0
#define CRYPTO_AES_SEL_SLOW 1
#define CRYPTO_AES_SEL_FAST 2
#define CRYPTO_AES_SEL_RESERVED 3
/* F8 definition of CRYPTO_CNTR1_IV1_REG */
#define CRYPTO_CNTR1_IV1_REG_F8_PKT_CNT 16 /* bit 31 - 16 */
#define CRYPTO_CNTR1_IV1_REG_F8_PKT_CNT_MASK \
(0xffff << CRYPTO_CNTR1_IV1_REG_F8_PKT_CNT)
#define CRYPTO_CNTR1_IV1_REG_F8_BEARER 0 /* bit 4 - 0 */
#define CRYPTO_CNTR1_IV1_REG_F8_BEARER_MASK \
(0x1f << CRYPTO_CNTR1_IV1_REG_F8_BEARER)
/* F9 definition of CRYPTO_AUTH_IV4_REG */
#define CRYPTO_AUTH_IV4_REG_F9_VALID_BIS 0 /* bit 2 - 0 */
#define CRYPTO_AUTH_IV4_REG_F9_VALID_BIS_MASK \
(0x7 << CRYPTO_AUTH_IV4_REG_F9_VALID_BIS)
/* misc */
#define CRYPTO_AES_RNDKEYS 60
#endif /* _DRIVERS_CRYPTO_MSM_QCRYPTOHW_30_H_ */

View File

@ -0,0 +1,316 @@
/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _DRIVERS_CRYPTO_MSM_QCRYPTOHW_40_H_
#define _DRIVERS_CRYPTO_MSM_QCRYPTOHW_40_H_
#define QCE_AUTH_REG_BYTE_COUNT 4
#define CRYPTO_VERSION_REG 0x0
#define CRYPTO_DATA_IN_REG 0x008
#define CRYPTO_DATA_OUT_REG 0x010
#define CRYPTO_STATUS_REG 0x100
#define CRYPTO_ENGINES_AVAIL 0x104
#define CRYPTO3_VERSION_REG 0x108
#define CRYPTO_SEG_SIZE_REG 0x200
#define CRYPTO_GOPROC_REG 0x204
#define CRYPTO_ENCR_SEG_CFG_REG 0x300
#define CRYPTO_ENCR_SEG_SIZE_REG 0x304
#define CRYPTO_ENCR_SEG_START_REG 0x308
#define CRYPTO_ENCR_KEY0_REG 0x310
#define CRYPTO_ENCR_KEY1_REG 0x314
#define CRYPTO_ENCR_KEY2_REG 0x318
#define CRYPTO_ENCR_KEY3_REG 0x31C
#define CRYPTO_ENCR_KEY4_REG 0x320
#define CRYPTO_ENCR_KEY5_REG 0x324
#define CRYPTO_ENCR_KEY6_REG 0x328
#define CRYPTO_ENCR_KEY7_REG 0x32C
#define CRYPTO_ENCR_XTS_KEY0_REG 0x330
#define CRYPTO_ENCR_XTS_KEY1_REG 0x334
#define CRYPTO_ENCR_XTS_KEY2_REG 0x338
#define CRYPTO_ENCR_XTS_KEY3_REG 0x33C
#define CRYPTO_ENCR_XTS_KEY4_REG 0x340
#define CRYPTO_ENCR_XTS_KEY5_REG 0x344
#define CRYPTO_ENCR_XTS_KEY6_REG 0x348
#define CRYPTO_ENCR_XTS_KEY7_REG 0x34C
#define CRYPTO_CNTR0_IV0_REG 0x350
#define CRYPTO_CNTR1_IV1_REG 0x354
#define CRYPTO_CNTR2_IV2_REG 0x358
#define CRYPTO_CNTR3_IV3_REG 0x35C
#define CRYPTO_CNTR_MASK_REG 0x360
#define CRYPTO_ENCR_XTS_DU_SIZE_REG 0x364
#define CRYPTO_AUTH_SEG_CFG_REG 0x400
#define CRYPTO_AUTH_SEG_SIZE_REG 0x404
#define CRYPTO_AUTH_SEG_START_REG 0x408
#define CRYPTO_AUTH_KEY0_REG 0x410
#define CRYPTO_AUTH_KEY1_REG 0x414
#define CRYPTO_AUTH_KEY2_REG 0x418
#define CRYPTO_AUTH_KEY3_REG 0x41C
#define CRYPTO_AUTH_KEY4_REG 0x420
#define CRYPTO_AUTH_KEY5_REG 0x424
#define CRYPTO_AUTH_KEY6_REG 0x428
#define CRYPTO_AUTH_KEY7_REG 0x42C
#define CRYPTO_AUTH_KEY8_REG 0x430
#define CRYPTO_AUTH_KEY9_REG 0x434
#define CRYPTO_AUTH_KEY10_REG 0x438
#define CRYPTO_AUTH_KEY11_REG 0x43C
#define CRYPTO_AUTH_KEY12_REG 0x440
#define CRYPTO_AUTH_KEY13_REG 0x444
#define CRYPTO_AUTH_KEY14_REG 0x448
#define CRYPTO_AUTH_KEY15_REG 0x44C
#define CRYPTO_AUTH_IV0_REG 0x450
#define CRYPTO_AUTH_IV1_REG 0x454
#define CRYPTO_AUTH_IV2_REG 0x458
#define CRYPTO_AUTH_IV3_REG 0x45C
#define CRYPTO_AUTH_IV4_REG 0x460
#define CRYPTO_AUTH_IV5_REG 0x464
#define CRYPTO_AUTH_IV6_REG 0x468
#define CRYPTO_AUTH_IV7_REG 0x46C
#define CRYPTO_AUTH_IV8_REG 0x470
#define CRYPTO_AUTH_IV9_REG 0x474
#define CRYPTO_AUTH_IV10_REG 0x478
#define CRYPTO_AUTH_IV11_REG 0x47C
#define CRYPTO_AUTH_IV12_REG 0x480
#define CRYPTO_AUTH_IV13_REG 0x484
#define CRYPTO_AUTH_IV14_REG 0x488
#define CRYPTO_AUTH_IV15_REG 0x48C
#define CRYPTO_AUTH_INFO_NONCE0_REG 0x490
#define CRYPTO_AUTH_INFO_NONCE1_REG 0x494
#define CRYPTO_AUTH_INFO_NONCE2_REG 0x498
#define CRYPTO_AUTH_INFO_NONCE3_REG 0x49C
#define CRYPTO_AUTH_BYTECNT0_REG 0x4A0
#define CRYPTO_AUTH_BYTECNT1_REG 0x4A4
#define CRYPTO_AUTH_BYTECNT2_REG 0x4A8
#define CRYPTO_AUTH_BYTECNT3_REG 0x4AC
#define CRYPTO_AUTH_EXP_MAC0_REG 0x4B0
#define CRYPTO_AUTH_EXP_MAC1_REG 0x4B4
#define CRYPTO_AUTH_EXP_MAC2_REG 0x4B8
#define CRYPTO_AUTH_EXP_MAC3_REG 0x4BC
#define CRYPTO_AUTH_EXP_MAC4_REG 0x4C0
#define CRYPTO_AUTH_EXP_MAC5_REG 0x4C4
#define CRYPTO_AUTH_EXP_MAC6_REG 0x4C8
#define CRYPTO_AUTH_EXP_MAC7_REG 0x4CC
#define CRYPTO_CONFIG_REG 0x500
#define CRYPTO_SACR_REG 0x504
#define CRYPTO_DEBUG_REG 0x508
#define CRYPTO_DATA_SHADOW0 0x8000
#define CRYPTO_DATA_SHADOW8191 0x8FFC
/* Register bits */
#define CRYPTO_CORE_MAJOR_REV 4 /* bit 7-4 */
#define CRYPTO_CORE_MAJOR_REV_MASK (0xF << CRYPTO_CORE_MAJOR_REV)
#define CRYPTO_CORE_MINOR_REV 0 /* bit 3-0 */
#define CRYPTO_CORE_MINOR_REV_MASK (0xF << CRYPTO_CORE_MINOR_REV)
#define CRYPTO_CORE_REV_MASK 0xFF
/* status reg */
#define CRYPTO_MAC_FAILED 25
#define CRYPTO_DOUT_SIZE_AVAIL 22 /* bit 24-22 */
#define CRYPTO_DOUT_SIZE_AVAIL_MASK (0x7 << CRYPTO_DOUT_SIZE_AVAIL)
#define CRYPTO_DIN_SIZE_AVAIL 19 /* bit 21-19 */
#define CRYPTO_DIN_SIZE_AVAIL_MASK (0x7 << CRYPTO_DIN_SIZE_AVAIL)
#define CRYPTO_ACCESS_VIOL 18
#define CRYPTO_SEG_CHNG_ERR 17
#define CRYPTO_CFH_CHNG_ERR 16
#define CRYPTO_DOUT_ERR 15
#define CRYPTO_DIN_ERR 14
#define CRYPTO_LOCKED 13
#define CRYPTO_CRYPTO_STATE 10 /* bit 12-10 */
#define CRYPTO_CRYPTO_STATE_MASK (0x7 << CRYPTO_CRYPTO_STATE)
#define CRYPTO_ENCR_BUSY 9
#define CRYPTO_AUTH_BUSY 8
#define CRYPTO_DOUT_INTR 7
#define CRYPTO_DIN_INTR 6
#define CRYPTO_OP_DONE_INTR 5
#define CRYPTO_ERR_INTR 4
#define CRYPTO_DOUT_RDY 3
#define CRYPTO_DIN_RDY 2
#define CRYPTO_OPERATION_DONE 1
#define CRYPTO_SW_ERR 0
/* config reg */
#define CRYPTO_REQ_SIZE 30 /* bit 31-30 */
#define CRYPTO_REQ_SIZE_MASK (0x3 << CRYPTO_REQ_SIZE)
#define CRYPTO_REQ_SIZE_ENUM_16_BYTES 0
#define CRYPTO_REQ_SIZE_ENUM_32_BYTES 1
#define CRYPTO_REQ_SIZE_ENUM_64_BYTES 2
#define CRYPTO_MAX_QUEUED_REQ 27 /* bit 29-27 */
#define CRYPTO_MAX_QUEUED_REQ_MASK (0x7 << CRYPTO_MAX_QUEUED_REQ)
#define CRYPTO_ENUM1_QUEUED_REQS 0
#define CRYPTO_ENUM2_QUEUED_REQS 1
#define CRYPTO_ENUM3_QUEUED_REQS 2
#define CRYPTO_ENUM4_QUEUED_REQS 3
#define CRYPTO_FIFO_THRESHOLD 24 /* bit 26-24 */
#define CRYPTO_FIFO_THRESHOLD_MASK (0x7 << CRYPTO_FIFO_THRESHOLD)
#define CRYPTO_FIFO_ENUM_16_BYTES 0
#define CRYPTO_FIFO_ENUM_32_BYTES 1
#define CRYPTO_FIFO_ENUM_48_BYTES 2
#define CRYPTO_FIFO_ENUM_64_BYTES 3
#define CRYPTO_IRQ_ENABLES 20 /* bit 23-20 */
#define CRYPTO_IRQ_ENABLES_MASK (0xF << CRYPTO_IRQ_ENABLES)
#define CRYPTO_ACR_EN 18
#define CRYPTO_BAM_MODE 17
#define CRYPTO_LITTLE_ENDIAN_MODE 16
#define CRYPTO_HIGH_SPD_OUT_EN_N 14
#define CRYPTO_HIGH_SPD_IN_EN_N 13
#define CRYPTO_DBG_EN 12
#define CRYPTO_DBG_SEL 7 /* bit 11:7 */
#define CRYPTO_DBG_SEL_MASK (0x1F << CRYPTO_DBG_SEL)
#define CRYPTO_MASK_DOUT_INTR 6
#define CRYPTO_MASK_DIN_INTR 5
#define CRYPTO_MASK_OP_DONE_INTR 4
#define CRYPTO_MASK_ERR_INTR 3
#define CRYPTO_AUTO_SHUTDOWN_EN 2
#define CRYPTO_CLK_EN_N 1
/* auth_seg_cfg reg */
#define CRYPTO_COMP_EXP_MAC 20
#define CRYPTO_COMP_EXP_MAC_DISABLED 0
#define CRYPTO_COMP_EXP_MAC_ENABLED 1
#define CRYPTO_F9_DIRECTION 19
#define CRYPTO_F9_DIRECTION_UPLINK 0
#define CRYPTO_F9_DIRECTION_DOWNLINK 1
#define CRYPTO_AUTH_NONCE_NUM_WORDS 16
#define CRYPTO_AUTH_NONCE_NUM_WORDS_MASK \
(0x7 << CRYPTO_AUTH_NONCE_NUM_WORDS)
#define CRYPTO_USE_HW_KEY_AUTH 15
#define CRYPTO_LAST 14
#define CRYPTO_AUTH_POS 12 /* bit 13 .. 12*/
#define CRYPTO_AUTH_POS_MASK (0x3 << CRYPTO_AUTH_POS)
#define CRYPTO_AUTH_POS_BEFORE 0
#define CRYPTO_AUTH_POS_AFTER 1
#define CRYPTO_AUTH_SIZE 9 /* bits 11 .. 9*/
#define CRYPTO_AUTH_SIZE_MASK (0x7 << CRYPTO_AUTH_SIZE)
#define CRYPTO_AUTH_SIZE_SHA1 0
#define CRYPTO_AUTH_SIZE_SHA256 1
#define CRYPTO_AUTH_SIZE_ENUM_4_BYTES 0
#define CRYPTO_AUTH_SIZE_ENUM_6_BYTES 1
#define CRYPTO_AUTH_SIZE_ENUM_8_BYTES 2
#define CRYPTO_AUTH_SIZE_ENUM_10_BYTES 3
#define CRYPTO_AUTH_SIZE_ENUM_12_BYTES 4
#define CRYPTO_AUTH_SIZE_ENUM_14_BYTES 5
#define CRYPTO_AUTH_SIZE_ENUM_16_BYTES 6
#define CRYPTO_AUTH_MODE 6 /* bit 8 .. 6*/
#define CRYPTO_AUTH_MODE_MASK (0x7 << CRYPTO_AUTH_MODE)
#define CRYPTO_AUTH_MODE_HASH 0
#define CRYPTO_AUTH_MODE_HMAC 1
#define CRYPTO_AUTH_MODE_CCM 0
#define CRYPTO_AUTH_MODE_CMAC 1
#define CRYPTO_AUTH_KEY_SIZE 3
#define CRYPTO_AUTH_KEY_SIZE_MASK (0x7 << CRYPTO_AUTH_KEY_SIZE)
#define CRYPTO_AUTH_KEY_SZ_AES128 0
#define CRYPTO_AUTH_KEY_SZ_AES256 2
#define CRYPTO_AUTH_ALG 0 /* bit 2 .. 0*/
#define CRYPTO_AUTH_ALG_MASK 7
#define CRYPTO_AUTH_ALG_NONE 0
#define CRYPTO_AUTH_ALG_SHA 1
#define CRYPTO_AUTH_ALG_AES 2
#define CRYPTO_AUTH_ALG_KASUMI 3
#define CRYPTO_AUTH_ALG_SNOW3G 4
/* encr_xts_du_size reg */
#define CRYPTO_ENCR_XTS_DU_SIZE 0 /* bit 19-0 */
#define CRYPTO_ENCR_XTS_DU_SIZE_MASK 0xfffff
/* encr_seg_cfg reg */
#define CRYPTO_F8_KEYSTREAM_ENABLE 15
#define CRYPTO_F8_KEYSTREAM_DISABLED 0
#define CRYPTO_F8_KEYSTREAM_ENABLED 1
#define CRYPTO_F8_DIRECTION 14
#define CRYPTO_F8_DIRECTION_UPLINK 0
#define CRYPTO_F8_DIRECTION_DOWNLINK 1
#define CRYPTO_USE_HW_KEY_ENCR 13
#define CRYPTO_USE_HW_KEY_REG 0
#define CRYPTO_USE_HW_KEY 1
#define CRYPTO_CNTR_ALG 11 /* bit 12-11 */
#define CRYPTO_CNTR_ALG_MASK (3 << CRYPTO_CNTR_ALG)
#define CRYPTO_CNTR_ALG_NIST 0
#define CRYPTO_ENCODE 10
#define CRYPTO_ENCR_MODE 6 /* bit 9-6 */
#define CRYPTO_ENCR_MODE_MASK (0xF << CRYPTO_ENCR_MODE)
/* only valid when AES */
#define CRYPTO_ENCR_MODE_ECB 0
#define CRYPTO_ENCR_MODE_CBC 1
#define CRYPTO_ENCR_MODE_CTR 2
#define CRYPTO_ENCR_MODE_XTS 3
#define CRYPTO_ENCR_MODE_CCM 4
#define CRYPTO_ENCR_KEY_SZ 3 /* bit 5-3 */
#define CRYPTO_ENCR_KEY_SZ_MASK (7 << CRYPTO_ENCR_KEY_SZ)
#define CRYPTO_ENCR_KEY_SZ_DES 0
#define CRYPTO_ENCR_KEY_SZ_3DES 1
#define CRYPTO_ENCR_KEY_SZ_AES128 0
#define CRYPTO_ENCR_KEY_SZ_AES256 2
#define CRYPTO_ENCR_KEY_SZ_UEA1 0
#define CRYPTO_ENCR_KEY_SZ_UEA2 1
#define CRYPTO_ENCR_ALG 0 /* bit 2-0 */
#define CRYPTO_ENCR_ALG_MASK (7 << CRYPTO_ENCR_ALG)
#define CRYPTO_ENCR_ALG_NONE 0
#define CRYPTO_ENCR_ALG_DES 1
#define CRYPTO_ENCR_ALG_AES 2
#define CRYPTO_ENCR_ALG_KASUMI 3
#define CRYPTO_ENCR_ALG_SNOW_3G 5
/* goproc reg */
#define CRYPTO_GO 0
#define CRYPTO_CLR_CNTXT 1
/* engines_avail */
#define CRYPTO_ENCR_AES_SEL 0
#define CRYPTO_DES_SEL 3
#define CRYPTO_ENCR_SNOW3G_SEL 4
#define CRYPTO_ENCR_KASUMI_SEL 5
#define CRYPTO_SHA_SEL 6
#define CRYPTO_SHA512_SEL 7
#define CRYPTO_AUTH_AES_SEL 8
#define CRYPTO_AUTH_SNOW3G_SEL 9
#define CRYPTO_AUTH_KASUMI_SEL 10
#define CRYPTO_BAM_SEL 11
#endif /* _DRIVERS_CRYPTO_MSM_QCRYPTOHW_40_H_ */

View File

@ -413,4 +413,5 @@ header-y += xattr.h
header-y += xfrm.h
header-y += msm_mdp.h
header-y += msm_rotator.h
header-y += qcedev.h
header-y += genlock.h

View File

@ -0,0 +1,24 @@
/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __QCOM_CRYPTO_DEVICE__H
#define __QCOM_CRYPTO_DEVICE__H
struct msm_ce_hw_support {
uint32_t ce_shared;
uint32_t shared_ce_resource;
uint32_t hw_key_support;
uint32_t sha_hmac;
void *bus_scale_table;
};
#endif /* __QCOM_CRYPTO_DEVICE__H */

241
include/linux/qcedev.h Normal file
View File

@ -0,0 +1,241 @@
#ifndef __QCEDEV__H
#define __QCEDEV__H
#include <linux/types.h>
#include <linux/ioctl.h>
#define QCEDEV_MAX_SHA_BLOCK_SIZE 64
#define QCEDEV_MAX_BEARER 31
#define QCEDEV_MAX_KEY_SIZE 64
#define QCEDEV_MAX_IV_SIZE 32
#define QCEDEV_MAX_BUFFERS 16
#define QCEDEV_MAX_SHA_DIGEST 32
#define QCEDEV_USE_PMEM 1
#define QCEDEV_NO_PMEM 0
#define QCEDEV_AES_KEY_128 16
#define QCEDEV_AES_KEY_192 24
#define QCEDEV_AES_KEY_256 32
/**
*qcedev_oper_enum: Operation types
* @QCEDEV_OPER_ENC: Encrypt
* @QCEDEV_OPER_DEC: Decrypt
* @QCEDEV_OPER_ENC_NO_KEY: Encrypt. Do not need key to be specified by
* user. Key already set by an external processor.
* @QCEDEV_OPER_DEC_NO_KEY: Decrypt. Do not need the key to be specified by
* user. Key already set by an external processor.
*/
enum qcedev_oper_enum {
QCEDEV_OPER_DEC = 0,
QCEDEV_OPER_ENC = 1,
QCEDEV_OPER_DEC_NO_KEY = 2,
QCEDEV_OPER_ENC_NO_KEY = 3,
QCEDEV_OPER_LAST
};
/**
*qcedev_oper_enum: Cipher algorithm types
* @QCEDEV_ALG_DES: DES
* @QCEDEV_ALG_3DES: 3DES
* @QCEDEV_ALG_AES: AES
*/
enum qcedev_cipher_alg_enum {
QCEDEV_ALG_DES = 0,
QCEDEV_ALG_3DES = 1,
QCEDEV_ALG_AES = 2,
QCEDEV_ALG_LAST
};
/**
*qcedev_cipher_mode_enum : AES mode
* @QCEDEV_AES_MODE_CBC: CBC
* @QCEDEV_AES_MODE_ECB: ECB
* @QCEDEV_AES_MODE_CTR: CTR
* @QCEDEV_AES_MODE_XTS: XTS
* @QCEDEV_AES_MODE_CCM: CCM
* @QCEDEV_DES_MODE_CBC: CBC
* @QCEDEV_DES_MODE_ECB: ECB
*/
enum qcedev_cipher_mode_enum {
QCEDEV_AES_MODE_CBC = 0,
QCEDEV_AES_MODE_ECB = 1,
QCEDEV_AES_MODE_CTR = 2,
QCEDEV_AES_MODE_XTS = 3,
QCEDEV_AES_MODE_CCM = 4,
QCEDEV_DES_MODE_CBC = 5,
QCEDEV_DES_MODE_ECB = 6,
QCEDEV_AES_DES_MODE_LAST
};
/**
*enum qcedev_sha_alg_enum : Secure Hashing Algorithm
* @QCEDEV_ALG_SHA1: Digest returned: 20 bytes (160 bits)
* @QCEDEV_ALG_SHA256: Digest returned: 32 bytes (256 bit)
* @QCEDEV_ALG_SHA1_HMAC: HMAC returned 20 bytes (160 bits)
* @QCEDEV_ALG_SHA256_HMAC: HMAC returned 32 bytes (256 bit)
* @QCEDEV_ALG_AES_CMAC: Configurable MAC size
*/
enum qcedev_sha_alg_enum {
QCEDEV_ALG_SHA1 = 0,
QCEDEV_ALG_SHA256 = 1,
QCEDEV_ALG_SHA1_HMAC = 2,
QCEDEV_ALG_SHA256_HMAC = 3,
QCEDEV_ALG_AES_CMAC = 4,
QCEDEV_ALG_SHA_ALG_LAST
};
/**
* struct buf_info - Buffer information
* @offset: Offset from the base address of the buffer
* (Used when buffer is allocated using PMEM)
* @vaddr: Virtual buffer address pointer
* @len: Size of the buffer
*/
struct buf_info {
union {
uint32_t offset;
uint8_t *vaddr;
};
uint32_t len;
};
/**
* struct qcedev_vbuf_info - Source and destination Buffer information
* @src: Array of buf_info for input/source
* @dst: Array of buf_info for output/destination
*/
struct qcedev_vbuf_info {
struct buf_info src[QCEDEV_MAX_BUFFERS];
struct buf_info dst[QCEDEV_MAX_BUFFERS];
};
/**
* struct qcedev_pmem_info - Stores PMEM buffer information
* @fd_src: Handle to /dev/adsp_pmem used to allocate
* memory for input/src buffer
* @src: Array of buf_info for input/source
* @fd_dst: Handle to /dev/adsp_pmem used to allocate
* memory for output/dst buffer
* @dst: Array of buf_info for output/destination
* @pmem_src_offset: The offset from input/src buffer
* (allocated by PMEM)
*/
struct qcedev_pmem_info {
int fd_src;
struct buf_info src[QCEDEV_MAX_BUFFERS];
int fd_dst;
struct buf_info dst[QCEDEV_MAX_BUFFERS];
};
/**
* struct qcedev_cipher_op_req - Holds the ciphering request information
* @use_pmem (IN): Flag to indicate if buffer source is PMEM
* QCEDEV_USE_PMEM/QCEDEV_NO_PMEM
* @pmem (IN): Stores PMEM buffer information.
* Refer struct qcedev_pmem_info
* @vbuf (IN/OUT): Stores Source and destination Buffer information
* Refer to struct qcedev_vbuf_info
* @data_len (IN): Total Length of input/src and output/dst in bytes
* @in_place_op (IN): Indicates whether the operation is inplace where
* source == destination
* When using PMEM allocated memory, must set this to 1
* @enckey (IN): 128 bits of confidentiality key
* enckey[0] bit 127-120, enckey[1] bit 119-112,..
* enckey[15] bit 7-0
* @encklen (IN): Length of the encryption key(set to 128 bits/16
* bytes in the driver)
* @iv (IN/OUT): Initialisation vector data
* This is updated by the driver, incremented by
* number of blocks encrypted/decrypted.
* @ivlen (IN): Length of the IV
* @byteoffset (IN): Offset in the Cipher BLOCK (applicable and to be set
* for AES-128 CTR mode only)
* @alg (IN): Type of ciphering algorithm: AES/DES/3DES
* @mode (IN): Mode use when using AES algorithm: ECB/CBC/CTR
* Apllicabel when using AES algorithm only
* @op (IN): Type of operation: QCEDEV_OPER_DEC/QCEDEV_OPER_ENC or
* QCEDEV_OPER_ENC_NO_KEY/QCEDEV_OPER_DEC_NO_KEY
*
*If use_pmem is set to 0, the driver assumes that memory was not allocated
* via PMEM, and kernel will need to allocate memory and copy data from user
* space buffer (data_src/dta_dst) and process accordingly and copy data back
* to the user space buffer
*
* If use_pmem is set to 1, the driver assumes that memory was allocated via
* PMEM.
* The kernel driver will use the fd_src to determine the kernel virtual address
* base that maps to the user space virtual address base for the buffer
* allocated in user space.
* The final input/src and output/dst buffer pointer will be determined
* by adding the offsets to the kernel virtual addr.
*
* If use of hardware key is supported in the target, user can configure the
* key paramters (encklen, enckey) to use the hardware key.
* In order to use the hardware key, set encklen to 0 and set the enckey
* data array to 0.
*/
struct qcedev_cipher_op_req {
uint8_t use_pmem;
union {
struct qcedev_pmem_info pmem;
struct qcedev_vbuf_info vbuf;
};
uint32_t entries;
uint32_t data_len;
uint8_t in_place_op;
uint8_t enckey[QCEDEV_MAX_KEY_SIZE];
uint32_t encklen;
uint8_t iv[QCEDEV_MAX_IV_SIZE];
uint32_t ivlen;
uint32_t byteoffset;
enum qcedev_cipher_alg_enum alg;
enum qcedev_cipher_mode_enum mode;
enum qcedev_oper_enum op;
};
/**
* struct qcedev_sha_op_req - Holds the hashing request information
* @data (IN): Array of pointers to the data to be hashed
* @entries (IN): Number of buf_info entries in the data array
* @data_len (IN): Length of data to be hashed
* @digest (IN/OUT): Returns the hashed data information
* @diglen (OUT): Size of the hashed/digest data
* @authkey (IN): Pointer to authentication key for HMAC
* @authklen (IN): Size of the authentication key
* @alg (IN): Secure Hash algorithm
*/
struct qcedev_sha_op_req {
struct buf_info data[QCEDEV_MAX_BUFFERS];
uint32_t entries;
uint32_t data_len;
uint8_t digest[QCEDEV_MAX_SHA_DIGEST];
uint32_t diglen;
uint8_t *authkey;
uint32_t authklen;
enum qcedev_sha_alg_enum alg;
};
#define QCEDEV_IOC_MAGIC 0x87
#define QCEDEV_IOCTL_ENC_REQ \
_IOWR(QCEDEV_IOC_MAGIC, 1, struct qcedev_cipher_op_req)
#define QCEDEV_IOCTL_DEC_REQ \
_IOWR(QCEDEV_IOC_MAGIC, 2, struct qcedev_cipher_op_req)
#define QCEDEV_IOCTL_SHA_INIT_REQ \
_IOWR(QCEDEV_IOC_MAGIC, 3, struct qcedev_sha_op_req)
#define QCEDEV_IOCTL_SHA_UPDATE_REQ \
_IOWR(QCEDEV_IOC_MAGIC, 4, struct qcedev_sha_op_req)
#define QCEDEV_IOCTL_SHA_FINAL_REQ \
_IOWR(QCEDEV_IOC_MAGIC, 5, struct qcedev_sha_op_req)
#define QCEDEV_IOCTL_GET_SHA_REQ \
_IOWR(QCEDEV_IOC_MAGIC, 6, struct qcedev_sha_op_req)
#define QCEDEV_IOCTL_LOCK_CE \
_IO(QCEDEV_IOC_MAGIC, 7)
#define QCEDEV_IOCTL_UNLOCK_CE \
_IO(QCEDEV_IOC_MAGIC, 8)
#define QCEDEV_IOCTL_GET_CMAC_REQ \
_IOWR(QCEDEV_IOC_MAGIC, 9, struct qcedev_cipher_op_req)
#endif /* _QCEDEV__H */

165
include/linux/qcota.h Normal file
View File

@ -0,0 +1,165 @@
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __QCOTA__H
#define __QCOTA__H
#include <linux/types.h>
#include <linux/ioctl.h>
#define QCE_OTA_MAX_BEARER 31
#define OTA_KEY_SIZE 16 /* 128 bits of keys. */
enum qce_ota_dir_enum {
QCE_OTA_DIR_UPLINK = 0,
QCE_OTA_DIR_DOWNLINK = 1,
QCE_OTA_DIR_LAST
};
enum qce_ota_algo_enum {
QCE_OTA_ALGO_KASUMI = 0,
QCE_OTA_ALGO_SNOW3G = 1,
QCE_OTA_ALGO_LAST
};
/**
* struct qce_f8_req - qce f8 request
* @data_in: packets input data stream to be ciphered.
* If NULL, streaming mode operation.
* @data_out: ciphered packets output data.
* @data_len: length of data_in and data_out in bytes.
* @count_c: count-C, ciphering sequence number, 32 bit
* @bearer: 5 bit of radio bearer identifier.
* @ckey: 128 bits of confidentiality key,
* ckey[0] bit 127-120, ckey[1] bit 119-112,.., ckey[15] bit 7-0.
* @direction: uplink or donwlink.
* @algorithm: Kasumi, or Snow3G.
*
* If data_in is NULL, the engine will run in a special mode called
* key stream mode. In this special mode, the engine will generate
* key stream output for the number of bytes specified in the
* data_len, based on the input parameters of direction, algorithm,
* ckey, bearer, and count_c. The data_len is restricted to
* the length of multiple of 16 bytes. Application can then take the
* output stream, do a exclusive or to the input data stream, and
* generate the final cipher data stream.
*/
struct qce_f8_req {
uint8_t *data_in;
uint8_t *data_out;
uint16_t data_len;
uint32_t count_c;
uint8_t bearer;
uint8_t ckey[OTA_KEY_SIZE];
enum qce_ota_dir_enum direction;
enum qce_ota_algo_enum algorithm;
};
/**
* struct qce_f8_multi_pkt_req - qce f8 multiple packet request
* Muliptle packets with uniform size, and
* F8 ciphering parameters can be ciphered in a
* single request.
*
* @num_pkt: number of packets.
*
* @cipher_start: ciphering starts offset within a packet.
*
* @cipher_size: number of bytes to be ciphered within a packet.
*
* @qce_f8_req: description of the packet and F8 parameters.
* The following fields have special meaning for
* multiple packet operation,
*
* @data_len: data_len indicates the length of a packet.
*
* @data_in: packets are concatenated together in a byte
* stream started at data_in.
*
* @data_out: The returned ciphered output for multiple
* packets.
* Each packet ciphered output are concatenated
* together into a byte stream started at data_out.
* Note, each ciphered packet output area from
* offset 0 to cipher_start-1, and from offset
* cipher_size to data_len -1 are remained
* unaltered from packet input area.
* @count_c: count-C of the first packet, 32 bit.
*
*
* In one request, multiple packets can be ciphered, and output to the
* data_out stream.
*
* Packet data are layed out contiguously in sequence in data_in,
* and data_out area. Every packet is identical size.
* If the PDU is not byte aligned, set the data_len value of
* to the rounded up value of the packet size. Eg, PDU size of
* 253 bits, set the packet size to 32 bytes. Next packet starts on
* the next byte boundary.
*
* For each packet, data from offset 0 to cipher_start
* will be left unchanged and output to the data_out area.
* This area of the packet can be for the RLC header, which is not
* to be ciphered.
*
* The ciphering of a packet starts from offset cipher_start, for
* cipher_size bytes of data. Data starting from
* offset cipher_start + cipher_size to the end of packet will be left
* unchanged and output to the dataOut area.
*
* For each packet the input arguments of bearer, direction,
* ckey, algoritm have to be the same. count_c is the ciphering sequence
* number of the first packet. The 2nd packet's ciphering sequence
* number is assumed to be count_c + 1. The 3rd packet's ciphering sequence
* number is count_c + 2.....
*
*/
struct qce_f8_multi_pkt_req {
uint16_t num_pkt;
uint16_t cipher_start;
uint16_t cipher_size;
struct qce_f8_req qce_f8_req;
};
/**
* struct qce_f9_req - qce f9 request
* @message: message
* @msize: message size in bytes (include the last partial byte).
* @last_bits: valid bits in the last byte of message.
* @mac_i: 32 bit message authentication code, to be returned.
* @fresh: random 32 bit number, one per user.
* @count_i: 32 bit count-I integrity sequence number.
* @direction: uplink or donwlink.
* @ikey: 128 bits of integrity key,
* ikey[0] bit 127-120, ikey[1] bit 119-112,.., ikey[15] bit 7-0.
* @algorithm: Kasumi, or Snow3G.
*/
struct qce_f9_req {
uint8_t *message;
uint16_t msize;
uint8_t last_bits;
uint32_t mac_i;
uint32_t fresh;
uint32_t count_i;
enum qce_ota_dir_enum direction;
uint8_t ikey[OTA_KEY_SIZE];
enum qce_ota_algo_enum algorithm;
};
#define QCOTA_IOC_MAGIC 0x85
#define QCOTA_F8_REQ _IOWR(QCOTA_IOC_MAGIC, 1, struct qce_f8_req)
#define QCOTA_F8_MPKT_REQ _IOWR(QCOTA_IOC_MAGIC, 2, struct qce_f8_multi_pkt_req)
#define QCOTA_F9_REQ _IOWR(QCOTA_IOC_MAGIC, 3, struct qce_f9_req)
#endif /* __QCOTA__H */