mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-02-04 08:04:49 +00:00
ENGR00112200 Add cryptodev device
Linux driver for /dev/crypto (aka CryptoDev) See http://www.logix.cz/michal/devel/cryptodev for details. Signed-off-by: Michal Ludvig <mludvig@suse.cz> Signed-off-by: Rob Herring <r.herring@freescale.com>
This commit is contained in:
committed by
Matt Sealey
parent
2a61116644
commit
16da9e7485
@@ -143,6 +143,14 @@ config CRYPTO_TEST
|
||||
help
|
||||
Quick & dirty crypto test module.
|
||||
|
||||
config CRYPTO_CRYPTODEV
|
||||
tristate "Cryptodev (/dev/crypto) interface"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Device /dev/crypto gives userspace programs access to
|
||||
kernel crypto algorithms.
|
||||
|
||||
comment "Authenticated Encryption with Associated Data"
|
||||
|
||||
config CRYPTO_CCM
|
||||
|
||||
@@ -84,6 +84,8 @@ obj-$(CONFIG_CRYPTO_RNG2) += krng.o
|
||||
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
|
||||
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_CRYPTODEV) += cryptodev.o
|
||||
|
||||
#
|
||||
# generic algorithms and the async_tx api
|
||||
#
|
||||
|
||||
558
crypto/cryptodev.c
Normal file
558
crypto/cryptodev.c
Normal file
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* Driver for /dev/crypto device (aka CryptoDev)
|
||||
*
|
||||
* Copyright (c) 2004 Michal Ludvig <mludvig@suse.cz>, SuSE Labs
|
||||
*
|
||||
* Device /dev/crypto provides an interface for
|
||||
* accessing kernel CryptoAPI algorithms (ciphers,
|
||||
* hashes) from userspace programs.
|
||||
*
|
||||
* /dev/crypto interface was originally introduced in
|
||||
* OpenBSD and this module attempts to keep the API,
|
||||
* although a bit extended.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/cryptodev.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/ioctl.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
MODULE_AUTHOR("Michal Ludvig <mludvig@suse.cz>");
|
||||
MODULE_DESCRIPTION("CryptoDev driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* ====== Compile-time config ====== */
|
||||
|
||||
#define CRYPTODEV_STATS
|
||||
|
||||
/* ====== Module parameters ====== */
|
||||
|
||||
static int verbosity = 0;
|
||||
module_param(verbosity, int, 0644);
|
||||
MODULE_PARM_DESC(verbosity, "0: normal, 1: verbose, 2: debug");
|
||||
|
||||
#ifdef CRYPTODEV_STATS
|
||||
static int enable_stats = 0;
|
||||
module_param(enable_stats, int, 0644);
|
||||
MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev usage");
|
||||
#endif
|
||||
|
||||
/* ====== Debug helpers ====== */
|
||||
|
||||
#define PFX "cryptodev: "
|
||||
#define dprintk(level,severity,format,a...) \
|
||||
do { \
|
||||
if (level <= verbosity) \
|
||||
printk(severity PFX "%s[%u]: " format, \
|
||||
current->comm, current->pid, \
|
||||
##a); \
|
||||
} while (0)
|
||||
|
||||
/* ====== CryptoAPI ====== */
|
||||
|
||||
struct csession {
|
||||
struct list_head entry;
|
||||
struct semaphore sem;
|
||||
struct crypto_blkcipher *tfm;
|
||||
uint32_t sid;
|
||||
#ifdef CRYPTODEV_STATS
|
||||
#if ! ((COP_ENCRYPT < 2) && (COP_DECRYPT < 2))
|
||||
#error Struct csession.stat uses COP_{ENCRYPT,DECRYPT} as indices. Do something!
|
||||
#endif
|
||||
unsigned long long stat[2];
|
||||
size_t stat_max_size, stat_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fcrypt {
|
||||
struct list_head list;
|
||||
struct semaphore sem;
|
||||
};
|
||||
|
||||
/* Prepare session for future use. */
|
||||
static int
|
||||
crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
|
||||
{
|
||||
struct csession *ses_new, *ses_ptr;
|
||||
struct crypto_blkcipher *tfm;
|
||||
int ret = 0;
|
||||
char alg_name[MAX_ALG_NAME_LEN+1];
|
||||
char alg_full_name[MAX_ALG_NAME_LEN+1];
|
||||
const char *mode;
|
||||
u8 *keyp;
|
||||
|
||||
/* Does the request make sense? */
|
||||
if (!sop->cipher == !sop->mac) {
|
||||
dprintk(1, KERN_DEBUG, "Both 'cipher' and 'mac' set or unset.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Copy-in the algorithm name if necessary. */
|
||||
if (!sop->alg_namelen) {
|
||||
/* Hmm, compatibility with OpenBSD CRYPTO_* constants...
|
||||
Should we support it? */
|
||||
dprintk(2, KERN_DEBUG, "OpenBSD constants are not (yet?) supported.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(sop->alg_namelen > MAX_ALG_NAME_LEN) {
|
||||
dprintk(1, KERN_DEBUG, "Algorithm name too long (%zu > %u)\n",
|
||||
sop->alg_namelen, MAX_ALG_NAME_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
copy_from_user(alg_name, sop->alg_name, sop->alg_namelen);
|
||||
alg_name[sop->alg_namelen] = '\0';
|
||||
|
||||
if(!sop->cipher) {
|
||||
dprintk(2, KERN_DEBUG, "Hashes are not yet supported.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (sop->cipher & CRYPTO_FLAG_MASK) {
|
||||
case CRYPTO_FLAG_ECB: mode = "ebc"; break;
|
||||
case CRYPTO_FLAG_CBC: mode = "cbc"; break;
|
||||
case CRYPTO_FLAG_CFB: mode = "cfb"; break;
|
||||
case CRYPTO_FLAG_CTR: mode = "ctr"; break;
|
||||
#if 0
|
||||
/* These modes are not yet supported. */
|
||||
case CRYPTO_FLAG_OFB: mode = "ofb"; break;
|
||||
#endif
|
||||
default: return -EINVAL;
|
||||
}
|
||||
snprintf(alg_full_name, sizeof(alg_full_name) - 1, "%s(%s)", mode, alg_name);
|
||||
|
||||
/* Set-up crypto transform. */
|
||||
tfm = crypto_alloc_blkcipher(alg_full_name, 0, 0);
|
||||
if (!tfm) {
|
||||
dprintk(1, KERN_DEBUG, "Failed to load transform for %s %s\n",
|
||||
alg_name, mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Was correct key length supplied? */
|
||||
if ((sop->keylen < crypto_tfm_alg_min_keysize(tfm)) ||
|
||||
(sop->keylen > crypto_tfm_alg_max_keysize(tfm))) {
|
||||
dprintk(1, KERN_DEBUG,
|
||||
"Wrong keylen '%zu' for algorithm '%s'. Use %u to %u.\n",
|
||||
sop->keylen, alg_name, crypto_tfm_alg_min_keysize(tfm),
|
||||
crypto_tfm_alg_max_keysize(tfm));
|
||||
crypto_free_blkcipher(tfm);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Copy the key from user and set to TFM. */
|
||||
keyp = kmalloc(sop->keylen, GFP_KERNEL);
|
||||
if (keyp == NULL) {
|
||||
dprintk(1, KERN_ERR,
|
||||
"Unable to allocate key buffer.\n");
|
||||
crypto_free_blkcipher(tfm);
|
||||
return -ENOMEM;
|
||||
}
|
||||
copy_from_user(keyp, sop->key, sop->keylen);
|
||||
ret = crypto_blkcipher_setkey(tfm, keyp, sop->keylen);
|
||||
kfree(keyp);
|
||||
if (ret) {
|
||||
dprintk(2, KERN_DEBUG,
|
||||
"Setting key failed for %s-%zu-%s: flags=0x%X\n",
|
||||
alg_name, sop->keylen*8, mode, crypto_blkcipher_tfm(tfm)->crt_flags);
|
||||
dprintk(2, KERN_DEBUG,
|
||||
"(see CRYPTO_TFM_RES_* in <linux/crypto.h> for details)\n");
|
||||
crypto_free_blkcipher(tfm);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Create a session and put it to the list. */
|
||||
ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL);
|
||||
if(!ses_new)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(ses_new, 0, sizeof(*ses_new));
|
||||
get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
|
||||
ses_new->tfm = tfm;
|
||||
init_MUTEX(&ses_new->sem);
|
||||
|
||||
down(&fcr->sem);
|
||||
restart:
|
||||
list_for_each_entry(ses_ptr, &fcr->list, entry) {
|
||||
/* Check for duplicate SID */
|
||||
if (unlikely(ses_new->sid == ses_ptr->sid)) {
|
||||
get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
|
||||
/* Unless we have a broken RNG this
|
||||
shouldn't loop forever... ;-) */
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
list_add(&ses_new->entry, &fcr->list);
|
||||
up(&fcr->sem);
|
||||
|
||||
dprintk(2, KERN_DEBUG, "Added session 0x%08X (%s-%zu-%s)\n",
|
||||
ses_new->sid, alg_name, sop->keylen*8, mode);
|
||||
|
||||
/* Fill in some values for the user. */
|
||||
sop->ses = ses_new->sid;
|
||||
sop->blocksize = crypto_blkcipher_blocksize(tfm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Everything that needs to be done when remowing a session. */
|
||||
static inline void
|
||||
crypto_destroy_session(struct csession *ses_ptr)
|
||||
{
|
||||
if(down_trylock(&ses_ptr->sem)) {
|
||||
dprintk(2, KERN_DEBUG, "Waiting for semaphore of sid=0x%08X\n",
|
||||
ses_ptr->sid);
|
||||
down(&ses_ptr->sem);
|
||||
}
|
||||
dprintk(2, KERN_DEBUG, "Removed session 0x%08X\n", ses_ptr->sid);
|
||||
#if defined(CRYPTODEV_STATS)
|
||||
if(enable_stats)
|
||||
dprintk(2, KERN_DEBUG,
|
||||
"Usage in Bytes: enc=%llu, dec=%llu, max=%zu, avg=%lu, cnt=%zu\n",
|
||||
ses_ptr->stat[COP_ENCRYPT], ses_ptr->stat[COP_DECRYPT],
|
||||
ses_ptr->stat_max_size, ses_ptr->stat_count > 0
|
||||
? ((unsigned long)(ses_ptr->stat[COP_ENCRYPT]+
|
||||
ses_ptr->stat[COP_DECRYPT]) /
|
||||
ses_ptr->stat_count) : 0,
|
||||
ses_ptr->stat_count);
|
||||
#endif
|
||||
crypto_free_blkcipher(ses_ptr->tfm);
|
||||
ses_ptr->tfm = NULL;
|
||||
up(&ses_ptr->sem);
|
||||
kfree(ses_ptr);
|
||||
}
|
||||
|
||||
/* Look up a session by ID and remove. */
|
||||
static int
|
||||
crypto_finish_session(struct fcrypt *fcr, uint32_t sid)
|
||||
{
|
||||
struct csession *tmp, *ses_ptr;
|
||||
struct list_head *head;
|
||||
int ret = 0;
|
||||
|
||||
down(&fcr->sem);
|
||||
head = &fcr->list;
|
||||
list_for_each_entry_safe(ses_ptr, tmp, head, entry) {
|
||||
if(ses_ptr->sid == sid) {
|
||||
list_del(&ses_ptr->entry);
|
||||
crypto_destroy_session(ses_ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ses_ptr) {
|
||||
dprintk(1, KERN_ERR, "Session with sid=0x%08X not found!\n", sid);
|
||||
ret = -ENOENT;
|
||||
}
|
||||
up(&fcr->sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Remove all sessions when closing the file */
|
||||
static int
|
||||
crypto_finish_all_sessions(struct fcrypt *fcr)
|
||||
{
|
||||
struct csession *tmp, *ses_ptr;
|
||||
|
||||
down(&fcr->sem);
|
||||
list_for_each_entry_safe(ses_ptr, tmp, &fcr->list, entry) {
|
||||
list_del(&ses_ptr->entry);
|
||||
crypto_destroy_session(ses_ptr);
|
||||
}
|
||||
up(&fcr->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look up session by session ID. The returned session is locked. */
|
||||
static struct csession *
|
||||
crypto_get_session_by_sid(struct fcrypt *fcr, uint32_t sid)
|
||||
{
|
||||
struct csession *ses_ptr;
|
||||
|
||||
down(&fcr->sem);
|
||||
list_for_each_entry(ses_ptr, &fcr->list, entry) {
|
||||
if(ses_ptr->sid == sid) {
|
||||
down(&ses_ptr->sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&fcr->sem);
|
||||
|
||||
return ses_ptr;
|
||||
}
|
||||
|
||||
/* This is the main crypto function - feed it with plaintext
|
||||
and get a ciphertext (or vice versa :-) */
|
||||
static int
|
||||
crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
|
||||
{
|
||||
char *data, *ivp;
|
||||
char __user *src, __user *dst;
|
||||
struct scatterlist sg;
|
||||
struct csession *ses_ptr;
|
||||
unsigned int ivsize;
|
||||
size_t nbytes, bufsize;
|
||||
int ret = 0;
|
||||
struct blkcipher_desc desc;
|
||||
|
||||
nbytes = cop->len;
|
||||
|
||||
if (cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT) {
|
||||
dprintk(1, KERN_DEBUG, "invalid operation op=%u\n", cop->op);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ses_ptr = crypto_get_session_by_sid(fcr, cop->ses);
|
||||
if (!ses_ptr) {
|
||||
dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", cop->ses);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (nbytes % crypto_blkcipher_blocksize(ses_ptr->tfm)) {
|
||||
dprintk(1, KERN_ERR,
|
||||
"data size (%zu) isn't a multiple of block size (%u)\n",
|
||||
nbytes, crypto_blkcipher_blocksize(ses_ptr->tfm));
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes;
|
||||
data = (char*)__get_free_page(GFP_KERNEL);
|
||||
|
||||
if (unlikely(!data)) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ivsize = crypto_blkcipher_ivsize(ses_ptr->tfm);
|
||||
|
||||
ivp = kmalloc(ivsize, GFP_KERNEL);
|
||||
if (unlikely(!ivp)) {
|
||||
free_page((unsigned long)data);
|
||||
ret = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (cop->iv) {
|
||||
copy_from_user(ivp, cop->iv, ivsize);
|
||||
crypto_blkcipher_set_iv(ses_ptr->tfm, ivp, ivsize);
|
||||
}
|
||||
|
||||
src = cop->src;
|
||||
dst = cop->dst;
|
||||
|
||||
desc.tfm = ses_ptr->tfm;
|
||||
desc.info = NULL;
|
||||
desc.flags = 0;
|
||||
|
||||
while (nbytes > 0) {
|
||||
size_t current_len = nbytes > bufsize ? bufsize : nbytes;
|
||||
|
||||
copy_from_user(data, src, current_len);
|
||||
|
||||
sg_set_buf(&sg, data, current_len);
|
||||
|
||||
if (cop->op == COP_DECRYPT)
|
||||
ret = crypto_blkcipher_decrypt(&desc, &sg, &sg, current_len);
|
||||
else
|
||||
ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, current_len);
|
||||
|
||||
if (unlikely(ret)) {
|
||||
dprintk(0, KERN_ERR, "CryptoAPI failure: flags=0x%x\n",
|
||||
crypto_blkcipher_tfm(ses_ptr->tfm)->crt_flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
copy_to_user(dst, data, current_len);
|
||||
|
||||
nbytes -= current_len;
|
||||
src += current_len;
|
||||
dst += current_len;
|
||||
}
|
||||
|
||||
#if defined(CRYPTODEV_STATS)
|
||||
if (enable_stats) {
|
||||
/* this is safe - we check cop->op at the function entry */
|
||||
ses_ptr->stat[cop->op] += cop->len;
|
||||
if (ses_ptr->stat_max_size < cop->len)
|
||||
ses_ptr->stat_max_size = cop->len;
|
||||
ses_ptr->stat_count++;
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
free_page((unsigned long)data);
|
||||
|
||||
kfree(ivp);
|
||||
|
||||
out_unlock:
|
||||
up(&ses_ptr->sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ====== /dev/crypto ====== */
|
||||
|
||||
static int
|
||||
cryptodev_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct fcrypt *fcr;
|
||||
|
||||
fcr = kmalloc(sizeof(*fcr), GFP_KERNEL);
|
||||
if(!fcr)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(fcr, 0, sizeof(*fcr));
|
||||
init_MUTEX(&fcr->sem);
|
||||
INIT_LIST_HEAD(&fcr->list);
|
||||
filp->private_data = fcr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cryptodev_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct fcrypt *fcr = filp->private_data;
|
||||
|
||||
if(fcr) {
|
||||
crypto_finish_all_sessions(fcr);
|
||||
kfree(fcr);
|
||||
filp->private_data = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
clonefd(struct file *filp)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = get_unused_fd();
|
||||
if (fd >= 0) {
|
||||
get_file(filp);
|
||||
fd_install(fd, filp);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
cryptodev_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct session_op sop;
|
||||
struct crypt_op cop;
|
||||
struct fcrypt *fcr = filp->private_data;
|
||||
uint32_t ses;
|
||||
int ret, fd;
|
||||
|
||||
if (!fcr)
|
||||
BUG();
|
||||
|
||||
switch (cmd) {
|
||||
case CRIOGET:
|
||||
fd = clonefd(filp);
|
||||
put_user(fd, (int*)arg);
|
||||
return 0;
|
||||
|
||||
case CIOCGSESSION:
|
||||
copy_from_user(&sop, (void*)arg, sizeof(sop));
|
||||
ret = crypto_create_session(fcr, &sop);
|
||||
if (ret)
|
||||
return ret;
|
||||
copy_to_user((void*)arg, &sop, sizeof(sop));
|
||||
return 0;
|
||||
|
||||
case CIOCFSESSION:
|
||||
get_user(ses, (uint32_t*)arg);
|
||||
ret = crypto_finish_session(fcr, ses);
|
||||
return ret;
|
||||
|
||||
case CIOCCRYPT:
|
||||
copy_from_user(&cop, (void*)arg, sizeof(cop));
|
||||
ret = crypto_run(fcr, &cop);
|
||||
copy_to_user((void*)arg, &cop, sizeof(cop));
|
||||
return ret;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
struct file_operations cryptodev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cryptodev_open,
|
||||
.release = cryptodev_release,
|
||||
.ioctl = cryptodev_ioctl,
|
||||
};
|
||||
|
||||
struct miscdevice cryptodev = {
|
||||
.minor = CRYPTODEV_MINOR,
|
||||
.name = "crypto",
|
||||
.fops = &cryptodev_fops,
|
||||
};
|
||||
|
||||
static int
|
||||
cryptodev_register(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = misc_register (&cryptodev);
|
||||
if (rc) {
|
||||
printk(KERN_ERR PFX "registeration of /dev/crypto failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cryptodev_deregister(void)
|
||||
{
|
||||
misc_deregister(&cryptodev);
|
||||
}
|
||||
|
||||
/* ====== Module init/exit ====== */
|
||||
|
||||
int __init
|
||||
init_cryptodev(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cryptodev_register();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
printk(KERN_INFO PFX "driver loaded.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit
|
||||
exit_cryptodev(void)
|
||||
{
|
||||
cryptodev_deregister();
|
||||
printk(KERN_INFO PFX "driver unloaded.\n");
|
||||
}
|
||||
|
||||
module_init(init_cryptodev);
|
||||
module_exit(exit_cryptodev);
|
||||
@@ -51,6 +51,7 @@ header-y += comstats.h
|
||||
header-y += const.h
|
||||
header-y += cgroupstats.h
|
||||
header-y += cramfs_fs.h
|
||||
header-y += cryptodev.h
|
||||
header-y += cycx_cfm.h
|
||||
header-y += dcbnl.h
|
||||
header-y += dlmconstants.h
|
||||
|
||||
82
include/linux/cryptodev.h
Normal file
82
include/linux/cryptodev.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Driver for /dev/crypto device (aka CryptoDev)
|
||||
*
|
||||
* Copyright (c) 2004 Michal Ludvig <mludvig@suse.cz>, SuSE Labs
|
||||
*
|
||||
* Structures and ioctl command names were taken from
|
||||
* OpenBSD to preserve compatibility with their API.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTODEV_H
|
||||
#define _CRYPTODEV_H
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#define CRYPTODEV_MINOR MISC_DYNAMIC_MINOR
|
||||
|
||||
#define CRYPTO_FLAG_ECB 0x0000
|
||||
#define CRYPTO_FLAG_CBC 0x0001
|
||||
#define CRYPTO_FLAG_CFB 0x0002
|
||||
#define CRYPTO_FLAG_OFB 0x0003
|
||||
#define CRYPTO_FLAG_CTR 0x0004
|
||||
#define CRYPTO_FLAG_HMAC 0x0010
|
||||
#define CRYPTO_FLAG_MASK 0x00FF
|
||||
|
||||
#define CRYPTO_CIPHER_NAME 0x0100
|
||||
#define CRYPTO_CIPHER_NAME_CBC (CRYPTO_CIPHER_NAME | CRYPTO_FLAG_CBC)
|
||||
#define CRYPTO_HASH_NAME 0x0200
|
||||
#define CRYPTO_HASH_NAME_HMAC (CRYPTO_HASH_NAME | CRYPTO_FLAG_HMAC)
|
||||
|
||||
/* ioctl parameter to create a session */
|
||||
struct session_op {
|
||||
unsigned int cipher; /* e.g. CRYPTO_DES_CBC */
|
||||
unsigned int mac; /* e.g. CRYPTO_MD5_HMAC */
|
||||
char *alg_name; /* set cipher=CRYPTO_CIPHER_NAME
|
||||
or mac=CRYPTO_HASH_NAME */
|
||||
#define MAX_ALG_NAME_LEN 128
|
||||
size_t alg_namelen;
|
||||
|
||||
size_t keylen; /* cipher key */
|
||||
char *key;
|
||||
int mackeylen; /* mac key */
|
||||
char *mackey;
|
||||
|
||||
/* Return values */
|
||||
unsigned int blocksize; /* selected algorithm's block size */
|
||||
uint32_t ses; /* session ID */
|
||||
};
|
||||
|
||||
/* ioctl parameter to request a crypt/decrypt operation against a session */
|
||||
struct crypt_op {
|
||||
uint32_t ses; /* from session_op->ses */
|
||||
#define COP_DECRYPT 0
|
||||
#define COP_ENCRYPT 1
|
||||
uint32_t op; /* ie. COP_ENCRYPT */
|
||||
uint32_t flags; /* unused */
|
||||
|
||||
size_t len;
|
||||
char *src, *dst;
|
||||
char *mac;
|
||||
char *iv;
|
||||
};
|
||||
|
||||
/* clone original filedescriptor */
|
||||
#define CRIOGET _IOWR('c', 100, uint32_t)
|
||||
|
||||
/* create crypto session */
|
||||
#define CIOCGSESSION _IOWR('c', 101, struct session_op)
|
||||
|
||||
/* finish crypto session */
|
||||
#define CIOCFSESSION _IOW('c', 102, uint32_t)
|
||||
|
||||
/* request encryption/decryptions of a given buffer */
|
||||
#define CIOCCRYPT _IOWR('c', 103, struct crypt_op)
|
||||
|
||||
/* ioctl()s for asym-crypto. Not yet supported. */
|
||||
#define CIOCKEY _IOWR('c', 104, void *)
|
||||
#define CIOCASYMFEAT _IOR('c', 105, uint32_t)
|
||||
|
||||
#endif /* _CRYPTODEV_H */
|
||||
Reference in New Issue
Block a user