LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/accelerated - cryptodev.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 4 4 100.0 %
Date: 2020-10-30 04:50:48 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2009-2010, 2012 Free Software Foundation, Inc.
       3             :  *
       4             :  * Author: Nikos Mavrogiannopoulos
       5             :  *
       6             :  * This file is part of GnuTLS.
       7             :  *
       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.
      12             :  *
      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.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public License
      19             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      20             :  *
      21             :  */
      22             : 
      23             : #include "errors.h"
      24             : #include "gnutls_int.h"
      25             : #include <gnutls/crypto.h>
      26             : #include "errors.h"
      27             : #include <accelerated/cryptodev.h>
      28             : 
      29             : #ifdef ENABLE_CRYPTODEV
      30             : 
      31             : #include <assert.h>
      32             : #include <fcntl.h>
      33             : #include <sys/ioctl.h>
      34             : #include <crypto/cryptodev.h>
      35             : 
      36             : #ifndef CRYPTO_CIPHER_MAX_KEY_LEN
      37             : #define CRYPTO_CIPHER_MAX_KEY_LEN 64
      38             : #endif
      39             : 
      40             : #ifndef EALG_MAX_BLOCK_LEN
      41             : #define EALG_MAX_BLOCK_LEN 16
      42             : #endif
      43             : 
      44             : int _gnutls_cryptodev_fd = -1;
      45             : 
      46             : static int register_mac_digest(int cfd);
      47             : 
      48             : struct cryptodev_ctx {
      49             :         struct session_op sess;
      50             :         struct crypt_op cryp;
      51             :         uint8_t iv[EALG_MAX_BLOCK_LEN];
      52             : 
      53             :         int cfd;
      54             : };
      55             : 
      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_192_CBC] = CRYPTO_CAMELLIA_CBC,
      63             :         [GNUTLS_CIPHER_CAMELLIA_256_CBC] = CRYPTO_CAMELLIA_CBC,
      64             :         [GNUTLS_CIPHER_DES_CBC] = CRYPTO_DES_CBC,
      65             : };
      66             : 
      67             : static int
      68             : cryptodev_cipher_init(gnutls_cipher_algorithm_t algorithm, void **_ctx,
      69             :                       int enc)
      70             : {
      71             :         struct cryptodev_ctx *ctx;
      72             :         int cipher = gnutls_cipher_map[algorithm];
      73             : 
      74             :         *_ctx = gnutls_calloc(1, sizeof(struct cryptodev_ctx));
      75             :         if (*_ctx == NULL) {
      76             :                 gnutls_assert();
      77             :                 return GNUTLS_E_MEMORY_ERROR;
      78             :         }
      79             : 
      80             :         ctx = *_ctx;
      81             : 
      82             :         ctx->cfd = _gnutls_cryptodev_fd;
      83             :         ctx->sess.cipher = cipher;
      84             :         ctx->cryp.iv = ctx->iv;
      85             : 
      86             :         return 0;
      87             : }
      88             : 
      89             : static int
      90             : cryptodev_cipher_setkey(void *_ctx, const void *key, size_t keysize)
      91             : {
      92             :         struct cryptodev_ctx *ctx = _ctx;
      93             : 
      94             :         CHECK_AES_KEYSIZE(keysize);
      95             : 
      96             :         ctx->sess.keylen = keysize;
      97             :         ctx->sess.key = (void *) key;
      98             : 
      99             :         if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
     100             :                 gnutls_assert();
     101             :                 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
     102             :         }
     103             :         ctx->cryp.ses = ctx->sess.ses;
     104             : 
     105             :         return 0;
     106             : }
     107             : 
     108             : static int cryptodev_setiv(void *_ctx, const void *iv, size_t iv_size)
     109             : {
     110             :         struct cryptodev_ctx *ctx = _ctx;
     111             : 
     112             :         if (iv_size > EALG_MAX_BLOCK_LEN)
     113             :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     114             : 
     115             :         memcpy(ctx->iv, iv, iv_size);
     116             : 
     117             :         return 0;
     118             : }
     119             : 
     120             : static int
     121             : cryptodev_encrypt(void *_ctx, const void *src, size_t src_size,
     122             :                   void *dst, size_t dst_size)
     123             : {
     124             :         struct cryptodev_ctx *ctx = _ctx;
     125             :         ctx->cryp.len = src_size;
     126             :         ctx->cryp.src = (void *) src;
     127             :         ctx->cryp.dst = dst;
     128             :         ctx->cryp.op = COP_ENCRYPT;
     129             :         ctx->cryp.flags = COP_FLAG_WRITE_IV;
     130             : 
     131             :         if (ioctl(ctx->cfd, CIOCCRYPT, &ctx->cryp)) {
     132             :                 gnutls_assert();
     133             :                 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
     134             :         }
     135             : 
     136             :         return 0;
     137             : }
     138             : 
     139             : static int
     140             : cryptodev_decrypt(void *_ctx, const void *src, size_t src_size,
     141             :                   void *dst, size_t dst_size)
     142             : {
     143             :         struct cryptodev_ctx *ctx = _ctx;
     144             : 
     145             :         ctx->cryp.len = src_size;
     146             :         ctx->cryp.src = (void *) src;
     147             :         ctx->cryp.dst = dst;
     148             :         ctx->cryp.op = COP_DECRYPT;
     149             :         ctx->cryp.flags = COP_FLAG_WRITE_IV;
     150             : 
     151             :         if (ioctl(ctx->cfd, CIOCCRYPT, &ctx->cryp)) {
     152             :                 gnutls_assert();
     153             :                 return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
     154             :         }
     155             : 
     156             :         return 0;
     157             : }
     158             : 
     159             : static void cryptodev_deinit(void *_ctx)
     160             : {
     161             :         struct cryptodev_ctx *ctx = _ctx;
     162             : 
     163             :         ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses);
     164             :         gnutls_free(ctx);
     165             : }
     166             : 
     167             : static const gnutls_crypto_cipher_st cipher_struct = {
     168             :         .init = cryptodev_cipher_init,
     169             :         .setkey = cryptodev_cipher_setkey,
     170             :         .setiv = cryptodev_setiv,
     171             :         .encrypt = cryptodev_encrypt,
     172             :         .decrypt = cryptodev_decrypt,
     173             :         .deinit = cryptodev_deinit,
     174             : };
     175             : 
     176             : static int register_crypto(int cfd)
     177             : {
     178             :         struct session_op sess;
     179             :         uint8_t fake_key[CRYPTO_CIPHER_MAX_KEY_LEN];
     180             :         unsigned int i;
     181             :         int ret;
     182             : #ifdef CIOCGSESSINFO
     183             :         struct session_info_op siop;
     184             : #endif
     185             : 
     186             :         memset(&sess, 0, sizeof(sess));
     187             : 
     188             :         for (i = 0;
     189             :              i < sizeof(gnutls_cipher_map) / sizeof(gnutls_cipher_map[0]);
     190             :              i++) {
     191             :                 if (gnutls_cipher_map[i] == 0)
     192             :                         continue;
     193             : 
     194             :                 /* test if a cipher is supported and if yes register it */
     195             :                 sess.cipher = gnutls_cipher_map[i];
     196             :                 sess.keylen = gnutls_cipher_get_key_size(i);
     197             :                 sess.key = fake_key;
     198             : 
     199             :                 if (ioctl(cfd, CIOCGSESSION, &sess)) {
     200             :                         continue;
     201             :                 }
     202             : #ifdef CIOCGSESSINFO
     203             :                 memset(&siop, 0, sizeof(siop));
     204             : 
     205             :                 siop.ses = sess.ses;    /* do not register ciphers that are not hw accelerated */
     206             :                 if (ioctl(cfd, CIOCGSESSINFO, &siop) == 0) {
     207             :                         if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
     208             :                                 ioctl(cfd, CIOCFSESSION, &sess.ses);
     209             :                                 continue;
     210             :                         }
     211             :                 }
     212             : #endif
     213             : 
     214             :                 ioctl(cfd, CIOCFSESSION, &sess.ses);
     215             : 
     216             :                 _gnutls_debug_log("/dev/crypto: registering: %s\n",
     217             :                                   gnutls_cipher_get_name(i));
     218             :                 ret =
     219             :                     gnutls_crypto_single_cipher_register(i, 90,
     220             :                                                          &cipher_struct, 0);
     221             :                 if (ret < 0) {
     222             :                         gnutls_assert();
     223             :                         return ret;
     224             :                 }
     225             : 
     226             :         }
     227             : 
     228             : #ifdef CIOCAUTHCRYPT
     229             :         return _cryptodev_register_gcm_crypto(cfd);
     230             : #else
     231             :         return 0;
     232             : #endif
     233             : }
     234             : 
     235             : int _gnutls_cryptodev_init(void)
     236             : {
     237             :         int ret;
     238             : 
     239             :         /* Open the crypto device */
     240             :         _gnutls_cryptodev_fd = open("/dev/crypto", O_RDWR, 0);
     241             :         if (_gnutls_cryptodev_fd < 0) {
     242             :                 gnutls_assert();
     243             :                 return GNUTLS_E_CRYPTODEV_DEVICE_ERROR;
     244             :         }
     245             : #ifndef CRIOGET_NOT_NEEDED
     246             :         {
     247             :                 int cfd = -1;
     248             :                 /* Clone file descriptor */
     249             :                 if (ioctl(_gnutls_cryptodev_fd, CRIOGET, &cfd)) {
     250             :                         gnutls_assert();
     251             :                         return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
     252             :                 }
     253             : 
     254             :                 /* Set close-on-exec (not really needed here) */
     255             :                 if (fcntl(cfd, F_SETFD, 1) == -1) {
     256             :                         gnutls_assert();
     257             :                         return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
     258             :                 }
     259             : 
     260             :                 close(_gnutls_cryptodev_fd);
     261             :                 _gnutls_cryptodev_fd = cfd;
     262             :         }
     263             : #endif
     264             : 
     265             :         ret = register_crypto(_gnutls_cryptodev_fd);
     266             :         if (ret < 0)
     267             :                 gnutls_assert();
     268             : 
     269             :         if (ret >= 0) {
     270             :                 ret = register_mac_digest(_gnutls_cryptodev_fd);
     271             :                 if (ret < 0)
     272             :                         gnutls_assert();
     273             :         }
     274             : 
     275             :         if (ret < 0) {
     276             :                 gnutls_assert();
     277             :                 close(_gnutls_cryptodev_fd);
     278             :         }
     279             : 
     280             :         return ret;
     281             : }
     282             : 
     283             : void _gnutls_cryptodev_deinit(void)
     284             : {
     285             :         if (_gnutls_cryptodev_fd != -1)
     286             :                 close(_gnutls_cryptodev_fd);
     287             : }
     288             : 
     289             : /* MAC and digest stuff */
     290             : 
     291             : /* if we are using linux /dev/crypto
     292             :  */
     293             : #if defined(COP_FLAG_UPDATE) && defined(COP_FLAG_RESET)
     294             : 
     295             : static const int gnutls_mac_map[] = {
     296             :         [GNUTLS_MAC_MD5] = CRYPTO_MD5_HMAC,
     297             :         [GNUTLS_MAC_SHA1] = CRYPTO_SHA1_HMAC,
     298             :         [GNUTLS_MAC_SHA256] = CRYPTO_SHA2_256_HMAC,
     299             :         [GNUTLS_MAC_SHA384] = CRYPTO_SHA2_384_HMAC,
     300             :         [GNUTLS_MAC_SHA512] = CRYPTO_SHA2_512_HMAC,
     301             : };
     302             : 
     303             : static int
     304             : cryptodev_mac_fast(gnutls_mac_algorithm_t algo,
     305             :                    const void *nonce, size_t nonce_size,
     306             :                    const void *key, size_t key_size, const void *text,
     307             :                    size_t text_size, void *digest)
     308             : {
     309             :         struct cryptodev_ctx ctx;
     310             :         int ret;
     311             : 
     312             :         assert(nonce_size == 0);
     313             : 
     314             :         memset(&ctx, 0, sizeof(ctx));
     315             :         ctx.cfd = _gnutls_cryptodev_fd;
     316             :         ctx.sess.mac = gnutls_mac_map[algo];
     317             : 
     318             :         ctx.sess.mackeylen = key_size;
     319             :         ctx.sess.mackey = (void *) key;
     320             : 
     321             :         if (ioctl(ctx.cfd, CIOCGSESSION, &ctx.sess))
     322             :                 return gnutls_assert_val(GNUTLS_E_CRYPTODEV_IOCTL_ERROR);
     323             : 
     324             :         ctx.cryp.ses = ctx.sess.ses;
     325             : 
     326             :         ctx.cryp.len = text_size;
     327             :         ctx.cryp.src = (void *) text;
     328             :         ctx.cryp.dst = NULL;
     329             :         ctx.cryp.op = COP_ENCRYPT;
     330             :         ctx.cryp.mac = digest;
     331             : 
     332             :         ret = ioctl(ctx.cfd, CIOCCRYPT, &ctx.cryp);
     333             : 
     334             :         ioctl(_gnutls_cryptodev_fd, CIOCFSESSION, &ctx.sess.ses);
     335             :         if (ret != 0)
     336             :                 return gnutls_assert_val(GNUTLS_E_CRYPTODEV_IOCTL_ERROR);
     337             : 
     338             :         return 0;
     339             : }
     340             : 
     341             : #define cryptodev_mac_deinit cryptodev_deinit
     342             : 
     343             : static const gnutls_crypto_mac_st mac_struct = {
     344             :         .init = NULL,
     345             :         .setkey = NULL,
     346             :         .setnonce = NULL,
     347             :         .hash = NULL,
     348             :         .output = NULL,
     349             :         .deinit = NULL,
     350             :         .fast = cryptodev_mac_fast
     351             : };
     352             : 
     353             : /* Digest algorithms */
     354             : 
     355             : static const int gnutls_digest_map[] = {
     356             :         [GNUTLS_DIG_MD5] = CRYPTO_MD5,
     357             :         [GNUTLS_DIG_SHA1] = CRYPTO_SHA1,
     358             :         [GNUTLS_DIG_SHA256] = CRYPTO_SHA2_256,
     359             :         [GNUTLS_DIG_SHA384] = CRYPTO_SHA2_384,
     360             :         [GNUTLS_DIG_SHA512] = CRYPTO_SHA2_512,
     361             : };
     362             : 
     363             : static int
     364             : cryptodev_digest_fast(gnutls_digest_algorithm_t algo,
     365             :                       const void *text, size_t text_size, void *digest)
     366             : {
     367             :         struct cryptodev_ctx ctx;
     368             :         int ret;
     369             : 
     370             :         memset(&ctx, 0, sizeof(ctx));
     371             :         ctx.cfd = _gnutls_cryptodev_fd;
     372             :         ctx.sess.mac = gnutls_digest_map[algo];
     373             : 
     374             :         if (ioctl(ctx.cfd, CIOCGSESSION, &ctx.sess))
     375             :                 return gnutls_assert_val(GNUTLS_E_CRYPTODEV_IOCTL_ERROR);
     376             : 
     377             :         ctx.cryp.ses = ctx.sess.ses;
     378             : 
     379             :         ctx.cryp.len = text_size;
     380             :         ctx.cryp.src = (void *) text;
     381             :         ctx.cryp.dst = NULL;
     382             :         ctx.cryp.op = COP_ENCRYPT;
     383             :         ctx.cryp.mac = digest;
     384             : 
     385             :         ret = ioctl(ctx.cfd, CIOCCRYPT, &ctx.cryp);
     386             : 
     387             :         ioctl(_gnutls_cryptodev_fd, CIOCFSESSION, &ctx.sess.ses);
     388             :         if (ret != 0)
     389             :                 return gnutls_assert_val(GNUTLS_E_CRYPTODEV_IOCTL_ERROR);
     390             : 
     391             :         return 0;
     392             : }
     393             : 
     394             : static const gnutls_crypto_digest_st digest_struct = {
     395             :         .init = NULL,
     396             :         .hash = NULL,
     397             :         .output = NULL,
     398             :         .deinit = NULL,
     399             :         .fast = cryptodev_digest_fast
     400             : };
     401             : 
     402             : static int register_mac_digest(int cfd)
     403             : {
     404             :         struct session_op sess;
     405             :         uint8_t fake_key[CRYPTO_CIPHER_MAX_KEY_LEN];
     406             :         unsigned int i;
     407             :         int ret;
     408             : #ifdef CIOCGSESSINFO
     409             :         struct session_info_op siop;
     410             : #endif
     411             : 
     412             :         memset(&sess, 0, sizeof(sess));
     413             :         for (i = 0; i < sizeof(gnutls_mac_map) / sizeof(gnutls_mac_map[0]);
     414             :              i++) {
     415             :                 if (gnutls_mac_map[i] == 0)
     416             :                         continue;
     417             : 
     418             :                 sess.mac = gnutls_mac_map[i];
     419             :                 sess.mackeylen = 8;
     420             :                 sess.mackey = fake_key;
     421             : 
     422             :                 if (ioctl(cfd, CIOCGSESSION, &sess)) {
     423             :                         continue;
     424             :                 }
     425             : #ifdef CIOCGSESSINFO
     426             :                 memset(&siop, 0, sizeof(siop));
     427             : 
     428             :                 siop.ses = sess.ses;    /* do not register ciphers that are not hw accelerated */
     429             :                 if (ioctl(cfd, CIOCGSESSINFO, &siop) == 0) {
     430             :                         if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
     431             :                                 ioctl(cfd, CIOCFSESSION, &sess.ses);
     432             :                                 continue;
     433             :                         }
     434             :                 }
     435             : #endif
     436             :                 _gnutls_debug_log("/dev/crypto: registering: HMAC-%s\n",
     437             :                                   gnutls_mac_get_name(i));
     438             : 
     439             :                 ioctl(cfd, CIOCFSESSION, &sess.ses);
     440             : 
     441             :                 ret =
     442             :                     gnutls_crypto_single_mac_register(i, 90, &mac_struct, 0);
     443             :                 if (ret < 0) {
     444             :                         gnutls_assert();
     445             :                         return ret;
     446             :                 }
     447             :         }
     448             : 
     449             :         memset(&sess, 0, sizeof(sess));
     450             :         for (i = 0;
     451             :              i < sizeof(gnutls_digest_map) / sizeof(gnutls_digest_map[0]);
     452             :              i++) {
     453             :                 if (gnutls_digest_map[i] == 0)
     454             :                         continue;
     455             : 
     456             :                 sess.mac = gnutls_digest_map[i];
     457             : 
     458             :                 if (ioctl(cfd, CIOCGSESSION, &sess)) {
     459             :                         continue;
     460             :                 }
     461             : #ifdef CIOCGSESSINFO
     462             :                 memset(&siop, 0, sizeof(siop));
     463             : 
     464             :                 siop.ses = sess.ses;
     465             :                 if (ioctl(cfd, CIOCGSESSINFO, &siop) == 0) {
     466             :                         if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
     467             :                                 ioctl(cfd, CIOCFSESSION, &sess.ses);
     468             :                                 continue;
     469             :                         }
     470             :                 }
     471             : #endif
     472             : 
     473             :                 ioctl(cfd, CIOCFSESSION, &sess.ses);
     474             : 
     475             :                 _gnutls_debug_log("/dev/crypto: registering: %s\n",
     476             :                                   gnutls_mac_get_name(i));
     477             :                 ret =
     478             :                     gnutls_crypto_single_digest_register(i, 90,
     479             :                                                          &digest_struct, 0);
     480             :                 if (ret < 0) {
     481             :                         gnutls_assert();
     482             :                         return ret;
     483             :                 }
     484             :         }
     485             : 
     486             :         return 0;
     487             : }
     488             : 
     489             : #else
     490             : static int register_mac_digest(int cfd)
     491             : {
     492             :         return 0;
     493             : }
     494             : 
     495             : #endif                          /* defined(COP_FLAG_UPDATE) */
     496             : 
     497             : #else                           /* ENABLE_CRYPTODEV */
     498        3429 : int _gnutls_cryptodev_init(void)
     499             : {
     500        3429 :         return 0;
     501             : }
     502             : 
     503        2225 : void _gnutls_cryptodev_deinit(void)
     504             : {
     505        2225 :         return;
     506             : }
     507             : #endif                          /* ENABLE_CRYPTODEV */

Generated by: LCOV version 1.14