2 * Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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 <sys/ioctl.h>
29 #include <gnutls/crypto.h>
30 #include <gnutls_cryptodev.h>
32 #ifdef ENABLE_CRYPTODEV
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;
47 struct cryptodev_ctx
{
48 struct session_op sess
;
50 opaque iv
[EALG_MAX_BLOCK_LEN
];
51 opaque key
[CRYPTO_CIPHER_MAX_KEY_LEN
];
55 static const int gnutls_cipher_map
[] = {
56 [GNUTLS_CIPHER_AES_128_CBC
] = CRYPTO_AES_CBC
,
57 [GNUTLS_CIPHER_AES_192_CBC
] = CRYPTO_AES_CBC
,
58 [GNUTLS_CIPHER_AES_256_CBC
] = CRYPTO_AES_CBC
,
59 [GNUTLS_CIPHER_3DES_CBC
] = CRYPTO_3DES_CBC
,
60 [GNUTLS_CIPHER_CAMELLIA_128_CBC
] = CRYPTO_CAMELLIA_CBC
,
61 [GNUTLS_CIPHER_CAMELLIA_256_CBC
] = CRYPTO_CAMELLIA_CBC
,
62 [GNUTLS_CIPHER_DES_CBC
] = CRYPTO_DES_CBC
,
65 static int cryptodev_cipher_init(gnutls_cipher_algorithm_t algorithm
, void** _ctx
)
67 struct cryptodev_ctx
* ctx
;
68 int cipher
= gnutls_cipher_map
[algorithm
];
70 *_ctx
= gnutls_calloc(1, sizeof(struct cryptodev_ctx
));
73 return GNUTLS_E_MEMORY_ERROR
;
78 if (ioctl(cryptodev_fd
, CRIOGET
, &ctx
->cfd
)) {
80 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
83 if (fcntl(ctx
->cfd
, F_SETFD
, 1) == -1) {
85 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
88 ctx
->sess
.cipher
= cipher
;
89 ctx
->sess
.key
= ctx
->key
;
90 ctx
->cryp
.iv
= ctx
->iv
;
95 static int cryptodev_setkey( void* _ctx
, const void *key
, size_t keysize
)
97 struct cryptodev_ctx
* ctx
= _ctx
;
99 ctx
->sess
.keylen
= keysize
;
100 memcpy(ctx
->key
, key
, keysize
);
102 if (ioctl(ctx
->cfd
, CIOCGSESSION
, &ctx
->sess
)) {
104 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
106 ctx
->cryp
.ses
= ctx
->sess
.ses
;
112 static int cryptodev_setiv( void* _ctx
, const void* iv
, size_t iv_size
)
114 struct cryptodev_ctx
* ctx
= _ctx
;
116 memcpy(ctx
->iv
, iv
, iv_size
);
121 static int cryptodev_encrypt(void* _ctx
, const void* plain
, size_t plainsize
,
122 void* encr
, size_t encrsize
)
124 struct cryptodev_ctx
* ctx
= _ctx
;
125 ctx
->cryp
.len
= plainsize
;
126 ctx
->cryp
.src
= (void*)plain
;
127 ctx
->cryp
.dst
= encr
;
128 ctx
->cryp
.op
= COP_ENCRYPT
;
129 if (ioctl(ctx
->cfd
, CIOCCRYPT
, &ctx
->cryp
)) {
131 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
136 static int cryptodev_decrypt(void* _ctx
, const void* encr
, size_t encrsize
,
137 void* plain
, size_t plainsize
)
139 struct cryptodev_ctx
* ctx
= _ctx
;
141 ctx
->cryp
.len
= encrsize
;
142 ctx
->cryp
.src
= (void*)encr
;
143 ctx
->cryp
.dst
= plain
;
144 ctx
->cryp
.op
= COP_DECRYPT
;
145 if (ioctl(ctx
->cfd
, CIOCCRYPT
, &ctx
->cryp
)) {
147 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
153 static void cryptodev_deinit(void* _ctx
)
155 struct cryptodev_ctx
* ctx
= _ctx
;
161 static const gnutls_crypto_cipher_st cipher_struct
= {
162 .init
= cryptodev_cipher_init
,
163 .setkey
= cryptodev_setkey
,
164 .setiv
= cryptodev_setiv
,
165 .encrypt
= cryptodev_encrypt
,
166 .decrypt
= cryptodev_decrypt
,
167 .deinit
= cryptodev_deinit
,
171 gnutls_cipher_algorithm_t gnutls_cipher
;
172 int cryptodev_cipher
;
176 static const struct cipher_map cipher_map
[] = {
177 {GNUTLS_CIPHER_3DES_CBC
, CRYPTO_3DES_CBC
, 21},
178 {GNUTLS_CIPHER_AES_128_CBC
, CRYPTO_AES_CBC
, 16},
179 {GNUTLS_CIPHER_AES_192_CBC
, CRYPTO_AES_CBC
, 24},
180 {GNUTLS_CIPHER_AES_256_CBC
, CRYPTO_AES_CBC
, 32},
181 {GNUTLS_CIPHER_CAMELLIA_128_CBC
, CRYPTO_CAMELLIA_CBC
, 16},
182 {GNUTLS_CIPHER_CAMELLIA_256_CBC
, CRYPTO_CAMELLIA_CBC
, 24},
183 {GNUTLS_CIPHER_DES_CBC
, CRYPTO_DES_CBC
, 8},
184 {GNUTLS_CIPHER_UNKNOWN
, 0}
187 static int register_crypto(int cfd
)
189 struct session_op sess
;
190 char fake_key
[CRYPTO_CIPHER_MAX_KEY_LEN
];
193 memset(&sess
, 0, sizeof(sess
));
195 /* test if a cipher is support it and if yes register it */
196 sess
.cipher
= cipher_map
[i
].cryptodev_cipher
;
197 sess
.keylen
= cipher_map
[i
].keylen
;
200 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
204 ret
= gnutls_crypto_single_cipher_register(cipher_map
[i
].gnutls_cipher
, 90, &cipher_struct
);
210 } while(cipher_map
[i
++].gnutls_cipher
!= GNUTLS_CIPHER_UNKNOWN
);
215 int _gnutls_cryptodev_init(void)
219 /* Open the crypto device */
220 cryptodev_fd
= open("/dev/crypto", O_RDWR
, 0);
221 if (cryptodev_fd
< 0) {
223 return GNUTLS_E_CRYPTODEV_DEVICE_ERROR
;
226 /* Clone file descriptor */
227 if (ioctl(cryptodev_fd
, CRIOGET
, &cfd
)) {
229 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
232 /* Set close-on-exec (not really neede here) */
233 if (fcntl(cfd
, F_SETFD
, 1) == -1) {
235 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
238 /* Run the test itself */
239 ret
= register_crypto(cfd
);
245 void _gnutls_cryptodev_deinit()
251 int _gnutls_cryptodev_init()
256 void _gnutls_cryptodev_deinit()
260 #endif /* ENABLE_CRYPTODEV */