2
* Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4
* Author: Nikos Mavrogiannopoulos
6
* This file is part of GnuTLS.
8
* The GnuTLS is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public License
10
* as published by the Free Software Foundation; either version 2.1 of
11
* the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25
#include <gnutls_errors.h>
26
#include <gnutls_int.h>
27
#include <gnutls/crypto.h>
28
#include <gnutls_cryptodev.h>
30
#ifdef ENABLE_CRYPTODEV
33
#include <sys/ioctl.h>
34
#include <crypto/cryptodev.h>
36
#ifndef CRYPTO_CIPHER_MAX_KEY_LEN
37
# define CRYPTO_CIPHER_MAX_KEY_LEN 64
40
#ifndef EALG_MAX_BLOCK_LEN
41
# define EALG_MAX_BLOCK_LEN 16
45
static int cryptodev_fd = -1;
49
struct session_op sess;
51
opaque iv[EALG_MAX_BLOCK_LEN];
52
opaque key[CRYPTO_CIPHER_MAX_KEY_LEN];
56
static const int gnutls_cipher_map[] = {
57
[GNUTLS_CIPHER_AES_128_CBC] = CRYPTO_AES_CBC,
58
[GNUTLS_CIPHER_AES_192_CBC] = CRYPTO_AES_CBC,
59
[GNUTLS_CIPHER_AES_256_CBC] = CRYPTO_AES_CBC,
60
[GNUTLS_CIPHER_3DES_CBC] = CRYPTO_3DES_CBC,
61
[GNUTLS_CIPHER_CAMELLIA_128_CBC] = CRYPTO_CAMELLIA_CBC,
62
[GNUTLS_CIPHER_CAMELLIA_256_CBC] = CRYPTO_CAMELLIA_CBC,
63
[GNUTLS_CIPHER_DES_CBC] = CRYPTO_DES_CBC,
67
cryptodev_cipher_init (gnutls_cipher_algorithm_t algorithm, void **_ctx)
69
struct cryptodev_ctx *ctx;
70
int cipher = gnutls_cipher_map[algorithm];
72
*_ctx = gnutls_calloc (1, sizeof (struct cryptodev_ctx));
76
return GNUTLS_E_MEMORY_ERROR;
81
if (ioctl (cryptodev_fd, CRIOGET, &ctx->cfd))
84
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
87
if (fcntl (ctx->cfd, F_SETFD, 1) == -1)
90
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
93
ctx->sess.cipher = cipher;
94
ctx->sess.key = ctx->key;
95
ctx->cryp.iv = ctx->iv;
101
cryptodev_setkey (void *_ctx, const void *key, size_t keysize)
103
struct cryptodev_ctx *ctx = _ctx;
105
ctx->sess.keylen = keysize;
106
memcpy (ctx->key, key, keysize);
108
if (ioctl (ctx->cfd, CIOCGSESSION, &ctx->sess))
111
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
113
ctx->cryp.ses = ctx->sess.ses;
120
cryptodev_setiv (void *_ctx, const void *iv, size_t iv_size)
122
struct cryptodev_ctx *ctx = _ctx;
124
memcpy (ctx->iv, iv, iv_size);
130
cryptodev_encrypt (void *_ctx, const void *plain, size_t plainsize,
131
void *encr, size_t encrsize)
133
struct cryptodev_ctx *ctx = _ctx;
134
ctx->cryp.len = plainsize;
135
ctx->cryp.src = (void *) plain;
136
ctx->cryp.dst = encr;
137
ctx->cryp.op = COP_ENCRYPT;
138
if (ioctl (ctx->cfd, CIOCCRYPT, &ctx->cryp))
141
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
147
cryptodev_decrypt (void *_ctx, const void *encr, size_t encrsize,
148
void *plain, size_t plainsize)
150
struct cryptodev_ctx *ctx = _ctx;
152
ctx->cryp.len = encrsize;
153
ctx->cryp.src = (void *) encr;
154
ctx->cryp.dst = plain;
155
ctx->cryp.op = COP_DECRYPT;
156
if (ioctl (ctx->cfd, CIOCCRYPT, &ctx->cryp))
159
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
166
cryptodev_deinit (void *_ctx)
168
struct cryptodev_ctx *ctx = _ctx;
174
static const gnutls_crypto_cipher_st cipher_struct = {
175
.init = cryptodev_cipher_init,
176
.setkey = cryptodev_setkey,
177
.setiv = cryptodev_setiv,
178
.encrypt = cryptodev_encrypt,
179
.decrypt = cryptodev_decrypt,
180
.deinit = cryptodev_deinit,
185
gnutls_cipher_algorithm_t gnutls_cipher;
186
int cryptodev_cipher;
190
static const struct cipher_map cipher_map[] = {
191
{GNUTLS_CIPHER_3DES_CBC, CRYPTO_3DES_CBC, 21},
192
{GNUTLS_CIPHER_AES_128_CBC, CRYPTO_AES_CBC, 16},
193
{GNUTLS_CIPHER_AES_192_CBC, CRYPTO_AES_CBC, 24},
194
{GNUTLS_CIPHER_AES_256_CBC, CRYPTO_AES_CBC, 32},
195
{GNUTLS_CIPHER_CAMELLIA_128_CBC, CRYPTO_CAMELLIA_CBC, 16},
196
{GNUTLS_CIPHER_CAMELLIA_256_CBC, CRYPTO_CAMELLIA_CBC, 24},
197
{GNUTLS_CIPHER_DES_CBC, CRYPTO_DES_CBC, 8},
198
{GNUTLS_CIPHER_UNKNOWN, 0}
202
register_crypto (int cfd)
204
struct session_op sess;
205
char fake_key[CRYPTO_CIPHER_MAX_KEY_LEN];
208
memset (&sess, 0, sizeof (sess));
211
/* test if a cipher is support it and if yes register it */
212
sess.cipher = cipher_map[i].cryptodev_cipher;
213
sess.keylen = cipher_map[i].keylen;
216
if (ioctl (cfd, CIOCGSESSION, &sess))
222
gnutls_crypto_single_cipher_register (cipher_map[i].gnutls_cipher, 90,
231
while (cipher_map[i++].gnutls_cipher != GNUTLS_CIPHER_UNKNOWN);
237
_gnutls_cryptodev_init (void)
241
/* Open the crypto device */
242
cryptodev_fd = open ("/dev/crypto", O_RDWR, 0);
243
if (cryptodev_fd < 0)
246
return GNUTLS_E_CRYPTODEV_DEVICE_ERROR;
249
/* Clone file descriptor */
250
if (ioctl (cryptodev_fd, CRIOGET, &cfd))
253
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
256
/* Set close-on-exec (not really neede here) */
257
if (fcntl (cfd, F_SETFD, 1) == -1)
260
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
263
/* Run the test itself */
264
ret = register_crypto (cfd);
271
_gnutls_cryptodev_deinit ()
273
close (cryptodev_fd);
278
_gnutls_cryptodev_init ()
284
_gnutls_cryptodev_deinit ()
288
#endif /* ENABLE_CRYPTODEV */