2 * Copyright (C) 2009-2010, 2012 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 3 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 License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <gnutls_errors.h>
24 #include <gnutls_int.h>
25 #include <gnutls/crypto.h>
26 #include <gnutls_errors.h>
27 #include <accelerated/cryptodev.h>
29 #ifdef ENABLE_CRYPTODEV
32 #include <sys/ioctl.h>
33 #include <crypto/cryptodev.h>
35 #ifndef CRYPTO_CIPHER_MAX_KEY_LEN
36 #define CRYPTO_CIPHER_MAX_KEY_LEN 64
39 #ifndef EALG_MAX_BLOCK_LEN
40 #define EALG_MAX_BLOCK_LEN 16
43 int _gnutls_cryptodev_fd
= -1;
45 static int register_mac_digest (int cfd
);
49 struct session_op sess
;
51 uint8_t iv
[EALG_MAX_BLOCK_LEN
];
57 static const int gnutls_cipher_map
[] = {
58 [GNUTLS_CIPHER_AES_128_CBC
] = CRYPTO_AES_CBC
,
59 [GNUTLS_CIPHER_AES_192_CBC
] = CRYPTO_AES_CBC
,
60 [GNUTLS_CIPHER_AES_256_CBC
] = CRYPTO_AES_CBC
,
61 [GNUTLS_CIPHER_3DES_CBC
] = CRYPTO_3DES_CBC
,
62 [GNUTLS_CIPHER_CAMELLIA_128_CBC
] = CRYPTO_CAMELLIA_CBC
,
63 [GNUTLS_CIPHER_CAMELLIA_192_CBC
] = CRYPTO_CAMELLIA_CBC
,
64 [GNUTLS_CIPHER_CAMELLIA_256_CBC
] = CRYPTO_CAMELLIA_CBC
,
65 [GNUTLS_CIPHER_DES_CBC
] = CRYPTO_DES_CBC
,
69 cryptodev_cipher_init (gnutls_cipher_algorithm_t algorithm
, void **_ctx
, int enc
)
71 struct cryptodev_ctx
*ctx
;
72 int cipher
= gnutls_cipher_map
[algorithm
];
74 *_ctx
= gnutls_calloc (1, sizeof (struct cryptodev_ctx
));
78 return GNUTLS_E_MEMORY_ERROR
;
83 ctx
->cfd
= _gnutls_cryptodev_fd
;
84 ctx
->sess
.cipher
= cipher
;
85 ctx
->cryp
.iv
= ctx
->iv
;
91 cryptodev_cipher_setkey (void *_ctx
, const void *key
, size_t keysize
)
93 struct cryptodev_ctx
*ctx
= _ctx
;
95 ctx
->sess
.keylen
= keysize
;
96 ctx
->sess
.key
= (void*)key
;
98 if (ioctl (ctx
->cfd
, CIOCGSESSION
, &ctx
->sess
))
101 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
103 ctx
->cryp
.ses
= ctx
->sess
.ses
;
109 cryptodev_setiv (void *_ctx
, const void *iv
, size_t iv_size
)
111 struct cryptodev_ctx
*ctx
= _ctx
;
113 memcpy (ctx
->iv
, iv
, iv_size
);
119 cryptodev_encrypt (void *_ctx
, const void *src
, size_t src_size
,
120 void *dst
, size_t dst_size
)
122 struct cryptodev_ctx
*ctx
= _ctx
;
123 ctx
->cryp
.len
= src_size
;
124 ctx
->cryp
.src
= (void *) src
;
126 ctx
->cryp
.op
= COP_ENCRYPT
;
127 ctx
->cryp
.flags
= COP_FLAG_WRITE_IV
;
129 if (ioctl (ctx
->cfd
, CIOCCRYPT
, &ctx
->cryp
))
132 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
139 cryptodev_decrypt (void *_ctx
, const void *src
, size_t src_size
,
140 void *dst
, size_t dst_size
)
142 struct cryptodev_ctx
*ctx
= _ctx
;
144 ctx
->cryp
.len
= src_size
;
145 ctx
->cryp
.src
= (void *) src
;
147 ctx
->cryp
.op
= COP_DECRYPT
;
148 ctx
->cryp
.flags
= COP_FLAG_WRITE_IV
;
150 if (ioctl (ctx
->cfd
, CIOCCRYPT
, &ctx
->cryp
))
153 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
160 cryptodev_deinit (void *_ctx
)
162 struct cryptodev_ctx
*ctx
= _ctx
;
164 ioctl (ctx
->cfd
, CIOCFSESSION
, &ctx
->sess
.ses
);
168 static const gnutls_crypto_cipher_st cipher_struct
= {
169 .init
= cryptodev_cipher_init
,
170 .setkey
= cryptodev_cipher_setkey
,
171 .setiv
= cryptodev_setiv
,
172 .encrypt
= cryptodev_encrypt
,
173 .decrypt
= cryptodev_decrypt
,
174 .deinit
= cryptodev_deinit
,
178 register_crypto (int cfd
)
180 struct session_op sess
;
181 uint8_t fake_key
[CRYPTO_CIPHER_MAX_KEY_LEN
];
185 struct session_info_op siop
;
188 memset (&sess
, 0, sizeof (sess
));
190 for (i
= 0; i
< sizeof (gnutls_cipher_map
) / sizeof (gnutls_cipher_map
[0]);
193 if (gnutls_cipher_map
[i
] == 0)
196 /* test if a cipher is support it and if yes register it */
197 sess
.cipher
= gnutls_cipher_map
[i
];
198 sess
.keylen
= gnutls_cipher_get_key_size (i
);
201 if (ioctl (cfd
, CIOCGSESSION
, &sess
))
207 memset(&siop
, 0, sizeof(siop
));
209 siop
.ses
= sess
.ses
; /* do not register ciphers that are not hw accelerated */
210 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
) == 0)
212 if (!(siop
.flags
& SIOP_FLAG_KERNEL_DRIVER_ONLY
))
214 ioctl (cfd
, CIOCFSESSION
, &sess
.ses
);
220 ioctl (cfd
, CIOCFSESSION
, &sess
.ses
);
222 _gnutls_debug_log ("/dev/crypto: registering: %s\n",
223 gnutls_cipher_get_name (i
));
224 ret
= gnutls_crypto_single_cipher_register (i
, 90, &cipher_struct
);
234 return _cryptodev_register_gcm_crypto(cfd
);
241 _gnutls_cryptodev_init (void)
245 /* Open the crypto device */
246 _gnutls_cryptodev_fd
= open ("/dev/crypto", O_RDWR
, 0);
247 if (_gnutls_cryptodev_fd
< 0)
250 return GNUTLS_E_CRYPTODEV_DEVICE_ERROR
;
253 #ifndef CRIOGET_NOT_NEEDED
256 /* Clone file descriptor */
257 if (ioctl (_gnutls_cryptodev_fd
, CRIOGET
, &cfd
))
260 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
263 /* Set close-on-exec (not really neede here) */
264 if (fcntl (cfd
, F_SETFD
, 1) == -1)
267 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR
;
270 close (_gnutls_cryptodev_fd
);
271 _gnutls_cryptodev_fd
= cfd
;
275 ret
= register_crypto (_gnutls_cryptodev_fd
);
281 ret
= register_mac_digest (_gnutls_cryptodev_fd
);
289 close (_gnutls_cryptodev_fd
);
296 _gnutls_cryptodev_deinit (void)
298 if (_gnutls_cryptodev_fd
!= -1) close (_gnutls_cryptodev_fd
);
301 /* MAC and digest stuff */
303 /* if we are using linux /dev/crypto
305 #if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_RESET)
307 static const int gnutls_mac_map
[] = {
308 [GNUTLS_MAC_MD5
] = CRYPTO_MD5_HMAC
,
309 [GNUTLS_MAC_SHA1
] = CRYPTO_SHA1_HMAC
,
310 [GNUTLS_MAC_SHA256
] = CRYPTO_SHA2_256_HMAC
,
311 [GNUTLS_MAC_SHA384
] = CRYPTO_SHA2_384_HMAC
,
312 [GNUTLS_MAC_SHA512
] = CRYPTO_SHA2_512_HMAC
,
316 cryptodev_mac_fast (gnutls_mac_algorithm_t algo
,
317 const void *key
, size_t key_size
, const void *text
,
318 size_t text_size
, void *digest
)
320 struct cryptodev_ctx ctx
;
323 memset(&ctx
, 0, sizeof(ctx
));
324 ctx
.cfd
= _gnutls_cryptodev_fd
;
325 ctx
.sess
.mac
= gnutls_mac_map
[algo
];
327 ctx
.sess
.mackeylen
= key_size
;
328 ctx
.sess
.mackey
= (void*)key
;
330 if (ioctl (ctx
.cfd
, CIOCGSESSION
, &ctx
.sess
))
331 return gnutls_assert_val(GNUTLS_E_CRYPTODEV_IOCTL_ERROR
);
333 ctx
.cryp
.ses
= ctx
.sess
.ses
;
335 ctx
.cryp
.len
= text_size
;
336 ctx
.cryp
.src
= (void *) text
;
338 ctx
.cryp
.op
= COP_ENCRYPT
;
339 ctx
.cryp
.mac
= digest
;
341 ret
= ioctl (ctx
.cfd
, CIOCCRYPT
, &ctx
.cryp
);
343 ioctl (_gnutls_cryptodev_fd
, CIOCFSESSION
, &ctx
.sess
.ses
);
345 return gnutls_assert_val(GNUTLS_E_CRYPTODEV_IOCTL_ERROR
);
350 #define cryptodev_mac_deinit cryptodev_deinit
352 static const gnutls_crypto_mac_st mac_struct
= {
359 .fast
= cryptodev_mac_fast
362 /* Digest algorithms */
364 static const int gnutls_digest_map
[] = {
365 [GNUTLS_DIG_MD5
] = CRYPTO_MD5
,
366 [GNUTLS_DIG_SHA1
] = CRYPTO_SHA1
,
367 [GNUTLS_DIG_SHA256
] = CRYPTO_SHA2_256
,
368 [GNUTLS_DIG_SHA384
] = CRYPTO_SHA2_384
,
369 [GNUTLS_DIG_SHA512
] = CRYPTO_SHA2_512
,
373 cryptodev_digest_fast (gnutls_digest_algorithm_t algo
,
374 const void *text
, size_t text_size
,
377 struct cryptodev_ctx ctx
;
380 memset(&ctx
, 0, sizeof(ctx
));
381 ctx
.cfd
= _gnutls_cryptodev_fd
;
382 ctx
.sess
.mac
= gnutls_digest_map
[algo
];
384 if (ioctl (ctx
.cfd
, CIOCGSESSION
, &ctx
.sess
))
385 return gnutls_assert_val(GNUTLS_E_CRYPTODEV_IOCTL_ERROR
);
387 ctx
.cryp
.ses
= ctx
.sess
.ses
;
389 ctx
.cryp
.len
= text_size
;
390 ctx
.cryp
.src
= (void *) text
;
392 ctx
.cryp
.op
= COP_ENCRYPT
;
393 ctx
.cryp
.mac
= digest
;
395 ret
= ioctl (ctx
.cfd
, CIOCCRYPT
, &ctx
.cryp
);
397 ioctl (_gnutls_cryptodev_fd
, CIOCFSESSION
, &ctx
.sess
.ses
);
399 return gnutls_assert_val(GNUTLS_E_CRYPTODEV_IOCTL_ERROR
);
404 static const gnutls_crypto_digest_st digest_struct
= {
410 .fast
= cryptodev_digest_fast
414 register_mac_digest (int cfd
)
416 struct session_op sess
;
417 uint8_t fake_key
[CRYPTO_CIPHER_MAX_KEY_LEN
];
421 struct session_info_op siop
;
424 memset (&sess
, 0, sizeof (sess
));
425 for (i
= 0; i
< sizeof (gnutls_mac_map
) / sizeof (gnutls_mac_map
[0]); i
++)
427 if (gnutls_mac_map
[i
] == 0)
430 sess
.mac
= gnutls_mac_map
[i
];
432 sess
.mackey
= fake_key
;
434 if (ioctl (cfd
, CIOCGSESSION
, &sess
))
440 memset(&siop
, 0, sizeof(siop
));
442 siop
.ses
= sess
.ses
; /* do not register ciphers that are not hw accelerated */
443 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
) == 0)
445 if (!(siop
.flags
& SIOP_FLAG_KERNEL_DRIVER_ONLY
))
447 ioctl (cfd
, CIOCFSESSION
, &sess
.ses
);
452 _gnutls_debug_log ("/dev/crypto: registering: HMAC-%s\n",
453 gnutls_mac_get_name (i
));
455 ioctl (cfd
, CIOCFSESSION
, &sess
.ses
);
457 ret
= gnutls_crypto_single_mac_register (i
, 90, &mac_struct
);
465 memset (&sess
, 0, sizeof (sess
));
466 for (i
= 0; i
< sizeof (gnutls_digest_map
) / sizeof (gnutls_digest_map
[0]); i
++)
468 if (gnutls_digest_map
[i
] == 0)
471 sess
.mac
= gnutls_digest_map
[i
];
473 if (ioctl (cfd
, CIOCGSESSION
, &sess
))
479 memset(&siop
, 0, sizeof(siop
));
482 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
) == 0)
484 if (!(siop
.flags
& SIOP_FLAG_KERNEL_DRIVER_ONLY
))
486 ioctl (cfd
, CIOCFSESSION
, &sess
.ses
);
492 ioctl (cfd
, CIOCFSESSION
, &sess
.ses
);
494 _gnutls_debug_log ("/dev/crypto: registering: %s\n",
495 gnutls_mac_get_name (i
));
496 ret
= gnutls_crypto_single_digest_register (i
, 90, &digest_struct
);
509 register_mac_digest (int cfd
)
514 #endif /* defined(COP_FLAG_UPDATE) */
516 #else /* ENABLE_CRYPTODEV */
518 _gnutls_cryptodev_init (void)
524 _gnutls_cryptodev_deinit (void)
528 #endif /* ENABLE_CRYPTODEV */