summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-10-02 22:15:02 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-10-02 23:26:45 +0200
commit256f3817f97398d89f59d20b654445b07eab6cdc (patch)
treed0e68ebad16646f64aa89db035c40f4457e18dd7
parentc42016790a175c3c46c435fed15331ba2b033813 (diff)
downloadgnutls-256f3817f97398d89f59d20b654445b07eab6cdc.tar.gz
Updated cryptodev code to support the linux cryptodev extensions.
Removed the clone() capability from HMAC. It was never used and having it prevents using it with hardware accelerators that might not have this capability.
-rw-r--r--lib/cryptodev.c243
-rw-r--r--lib/gcrypt/mac.c1
-rw-r--r--lib/gnutls_hash_int.c2
-rw-r--r--lib/includes/gnutls/crypto.h13
-rw-r--r--lib/nettle/mac.c20
5 files changed, 196 insertions, 83 deletions
diff --git a/lib/cryptodev.c b/lib/cryptodev.c
index 3001a59cc2..29f2ee9cca 100644
--- a/lib/cryptodev.c
+++ b/lib/cryptodev.c
@@ -42,9 +42,10 @@
# define EALG_MAX_BLOCK_LEN 16
#endif
-
static int cryptodev_fd = -1;
+static int register_mac (int cfd);
+
struct cryptodev_ctx
{
struct session_op sess;
@@ -79,18 +80,7 @@ cryptodev_cipher_init (gnutls_cipher_algorithm_t algorithm, void **_ctx)
ctx = *_ctx;
- if (ioctl (cryptodev_fd, CRIOGET, &ctx->cfd))
- {
- gnutls_assert ();
- return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
- }
-
- if (fcntl (ctx->cfd, F_SETFD, 1) == -1)
- {
- gnutls_assert ();
- return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
- }
-
+ ctx->cfd = cryptodev_fd;
ctx->sess.cipher = cipher;
ctx->sess.key = ctx->key;
ctx->cryp.iv = ctx->iv;
@@ -99,7 +89,7 @@ cryptodev_cipher_init (gnutls_cipher_algorithm_t algorithm, void **_ctx)
}
static int
-cryptodev_setkey (void *_ctx, const void *key, size_t keysize)
+cryptodev_cipher_setkey (void *_ctx, const void *key, size_t keysize)
{
struct cryptodev_ctx *ctx = _ctx;
@@ -114,7 +104,6 @@ cryptodev_setkey (void *_ctx, const void *key, size_t keysize)
ctx->cryp.ses = ctx->sess.ses;
return 0;
-
}
static int
@@ -169,37 +158,18 @@ cryptodev_deinit (void *_ctx)
struct cryptodev_ctx *ctx = _ctx;
ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess);
- close (ctx->cfd);
gnutls_free (ctx);
}
static const gnutls_crypto_cipher_st cipher_struct = {
.init = cryptodev_cipher_init,
- .setkey = cryptodev_setkey,
+ .setkey = cryptodev_cipher_setkey,
.setiv = cryptodev_setiv,
.encrypt = cryptodev_encrypt,
.decrypt = cryptodev_decrypt,
.deinit = cryptodev_deinit,
};
-struct cipher_map
-{
- gnutls_cipher_algorithm_t gnutls_cipher;
- int cryptodev_cipher;
- int keylen;
-};
-
-static const struct cipher_map cipher_map[] = {
- {GNUTLS_CIPHER_3DES_CBC, CRYPTO_3DES_CBC, 21},
- {GNUTLS_CIPHER_AES_128_CBC, CRYPTO_AES_CBC, 16},
- {GNUTLS_CIPHER_AES_192_CBC, CRYPTO_AES_CBC, 24},
- {GNUTLS_CIPHER_AES_256_CBC, CRYPTO_AES_CBC, 32},
- {GNUTLS_CIPHER_CAMELLIA_128_CBC, CRYPTO_CAMELLIA_CBC, 16},
- {GNUTLS_CIPHER_CAMELLIA_256_CBC, CRYPTO_CAMELLIA_CBC, 24},
- {GNUTLS_CIPHER_DES_CBC, CRYPTO_DES_CBC, 8},
- {GNUTLS_CIPHER_UNKNOWN, 0}
-};
-
static int
register_crypto (int cfd)
{
@@ -208,11 +178,14 @@ register_crypto (int cfd)
int i = 0, ret;
memset (&sess, 0, sizeof (sess));
- do
+
+ for (i=0;i<sizeof(gnutls_cipher_map)/sizeof(gnutls_cipher_map[0]);i++)
{
+ if (gnutls_cipher_map[i] == 0) continue;
+
/* test if a cipher is support it and if yes register it */
- sess.cipher = cipher_map[i].cryptodev_cipher;
- sess.keylen = cipher_map[i].keylen;
+ sess.cipher = gnutls_cipher_map[i];
+ sess.keylen = gnutls_cipher_get_key_size(i);
sess.key = fake_key;
if (ioctl (cfd, CIOCGSESSION, &sess))
@@ -222,10 +195,9 @@ register_crypto (int cfd)
ioctl(cfd, CIOCFSESSION, &sess);
- _gnutls_debug_log("/dev/crypto: registering: %s\n", gnutls_cipher_get_name(cipher_map[i].gnutls_cipher));
+ _gnutls_debug_log("/dev/crypto: registering: %s\n", gnutls_cipher_get_name(i));
ret =
- gnutls_crypto_single_cipher_register (cipher_map[i].gnutls_cipher, 90,
- &cipher_struct);
+ gnutls_crypto_single_cipher_register (i, 90, &cipher_struct);
if (ret < 0)
{
gnutls_assert ();
@@ -233,15 +205,13 @@ register_crypto (int cfd)
}
}
- while (cipher_map[i++].gnutls_cipher != GNUTLS_CIPHER_UNKNOWN);
return 0;
}
-int
-_gnutls_cryptodev_init (void)
+int _gnutls_cryptodev_init (void)
{
- int cfd = -1, ret;
+ int ret;
/* Open the crypto device */
cryptodev_fd = open ("/dev/crypto", O_RDWR, 0);
@@ -251,34 +221,195 @@ _gnutls_cryptodev_init (void)
return GNUTLS_E_CRYPTODEV_DEVICE_ERROR;
}
- /* Clone file descriptor */
- if (ioctl (cryptodev_fd, CRIOGET, &cfd))
+#ifndef CRIOGET_NOT_NEEDED
+ {
+ int cfd = -1;
+ /* Clone file descriptor */
+ if (ioctl (cryptodev_fd, CRIOGET, &cfd))
+ {
+ gnutls_assert ();
+ return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl (cfd, F_SETFD, 1) == -1)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
+ }
+
+ close(cryptodev_fd);
+ cryptodev_fd = cfd;
+ }
+#endif
+
+ ret = register_crypto (cryptodev_fd);
+ if (ret < 0)
+ gnutls_assert();
+
+ if (ret >= 0)
+ {
+ ret = register_mac (cryptodev_fd);
+ if (ret < 0)
+ gnutls_assert();
+ }
+
+ if (ret < 0)
+ {
+ gnutls_assert();
+ close(cryptodev_fd);
+ }
+
+ return ret;
+}
+
+void _gnutls_cryptodev_deinit(void)
+{
+ close (cryptodev_fd);
+}
+
+/* MAC and digest stuff */
+
+/* if we are using linux /dev/crypto
+ */
+#if defined(COP_FLAG_UPDATE)
+
+static const int gnutls_mac_map[] = {
+ [GNUTLS_MAC_MD5] = CRYPTO_MD5_HMAC,
+ [GNUTLS_MAC_SHA1] = CRYPTO_SHA1_HMAC,
+ [GNUTLS_MAC_SHA256] = CRYPTO_SHA2_256_HMAC,
+ [GNUTLS_MAC_SHA384] = CRYPTO_SHA2_384_HMAC,
+ [GNUTLS_MAC_SHA512] = CRYPTO_SHA2_512_HMAC,
+};
+
+static int cryptodev_mac_init(gnutls_mac_algorithm_t algorithm, void **_ctx)
+{
+ struct cryptodev_ctx *ctx;
+ int mac = gnutls_mac_map[algorithm];
+
+ *_ctx = gnutls_calloc (1, sizeof (struct cryptodev_ctx));
+ if (*_ctx == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ctx = *_ctx;
+
+ ctx->cfd = cryptodev_fd;
+
+ ctx->sess.mac = mac;
+ ctx->sess.mackey = ctx->key;
+
+ return 0;
+}
+
+static int
+cryptodev_mac_setkey (void *_ctx, const void *key, size_t keysize)
+{
+ struct cryptodev_ctx *ctx = _ctx;
+
+ ctx->sess.mackeylen = keysize;
+ memcpy (ctx->key, key, keysize);
+
+ if (ioctl (ctx->cfd, CIOCGSESSION, &ctx->sess))
{
gnutls_assert ();
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
}
+ ctx->cryp.ses = ctx->sess.ses;
- /* Set close-on-exec (not really neede here) */
- if (fcntl (cfd, F_SETFD, 1) == -1)
+ return 0;
+}
+
+static int cryptodev_mac_hash (void *_ctx, const void *text, size_t textsize)
+{
+ struct cryptodev_ctx *ctx = _ctx;
+ ctx->cryp.len = textsize;
+ ctx->cryp.src = (void *) text;
+ ctx->cryp.dst = NULL;
+ ctx->cryp.op = COP_ENCRYPT;
+ ctx->cryp.flags = COP_FLAG_UPDATE;
+ if (ioctl (ctx->cfd, CIOCCRYPT, &ctx->cryp))
{
gnutls_assert ();
return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
}
+ return 0;
+}
- /* Run the test itself */
- ret = register_crypto (cfd);
+static int cryptodev_mac_output (void *_ctx, void *digest, size_t digestsize)
+{
+ struct cryptodev_ctx *ctx = _ctx;
+ ctx->cryp.len = 0;
+ ctx->cryp.src = NULL;
+ ctx->cryp.mac = digest;
+ ctx->cryp.op = COP_ENCRYPT;
+ ctx->cryp.flags = COP_FLAG_FINAL;
+ if (ioctl (ctx->cfd, CIOCCRYPT, &ctx->cryp))
+ {
+ gnutls_assert ();
+ return GNUTLS_E_CRYPTODEV_IOCTL_ERROR;
+ }
- close (cfd);
- return ret;
+ return 0;
}
-void
-_gnutls_cryptodev_deinit ()
+#define cryptodev_mac_deinit cryptodev_deinit
+
+static const gnutls_crypto_mac_st mac_struct = {
+ .init = cryptodev_mac_init,
+ .setkey = cryptodev_mac_setkey,
+ .hash = cryptodev_mac_hash,
+ .output = cryptodev_mac_output,
+ .deinit = cryptodev_mac_deinit
+};
+
+static int register_mac (int cfd)
{
- close (cryptodev_fd);
+ struct session_op sess;
+ char fake_key[CRYPTO_CIPHER_MAX_KEY_LEN];
+ int i = 0, ret;
+
+ memset (&sess, 0, sizeof (sess));
+ for (i=0;i<sizeof(gnutls_mac_map)/sizeof(gnutls_mac_map[0]);i++)
+ {
+ if (gnutls_mac_map[i] == 0) continue;
+
+ sess.mac = gnutls_mac_map[i];
+ sess.keylen = 8;
+ sess.key = fake_key;
+
+ if (ioctl (cfd, CIOCGSESSION, &sess))
+ {
+ continue;
+ }
+
+ ioctl(cfd, CIOCFSESSION, &sess);
+
+ _gnutls_debug_log("/dev/crypto: registering: %s\n", gnutls_mac_get_name(i));
+ ret =
+ gnutls_crypto_single_mac_register (i, 90, &mac_struct);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ }
+
+ return 0;
}
#else
+static int register_mac (int cfd)
+{
+ return 0;
+}
+
+#endif /* defined(CIOCSESSIONCLONE) && defined(COP_FLAG_UPDATE) */
+
+#else /* ENABLE_CRYPTODEV */
int
_gnutls_cryptodev_init ()
{
diff --git a/lib/gcrypt/mac.c b/lib/gcrypt/mac.c
index 703d68b316..d4075d8e62 100644
--- a/lib/gcrypt/mac.c
+++ b/lib/gcrypt/mac.c
@@ -164,7 +164,6 @@ gnutls_crypto_mac_st _gnutls_mac_ops = {
.init = wrap_gcry_mac_init,
.setkey = wrap_gcry_md_setkey,
.hash = wrap_gcry_md_write,
- .copy = wrap_gcry_md_copy,
.output = wrap_gcry_mac_output,
.deinit = wrap_gcry_md_close,
};
diff --git a/lib/gnutls_hash_int.c b/lib/gnutls_hash_int.c
index 5cf1956925..38883c5acb 100644
--- a/lib/gnutls_hash_int.c
+++ b/lib/gnutls_hash_int.c
@@ -254,7 +254,6 @@ _gnutls_hmac_init (digest_hd_st * dig, gnutls_mac_algorithm_t algorithm,
}
dig->hash = cc->hash;
- dig->copy = cc->copy;
dig->output = cc->output;
dig->deinit = cc->deinit;
@@ -271,7 +270,6 @@ _gnutls_hmac_init (digest_hd_st * dig, gnutls_mac_algorithm_t algorithm,
_gnutls_mac_ops.setkey (dig->handle, key, keylen);
dig->hash = _gnutls_mac_ops.hash;
- dig->copy = _gnutls_mac_ops.copy;
dig->output = _gnutls_mac_ops.output;
dig->deinit = _gnutls_mac_ops.deinit;
diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
index d121490f0d..61279597dc 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -69,7 +69,7 @@ int gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
/* register ciphers */
-#define GNUTLS_CRYPTO_API_VERSION 0x02
+#define GNUTLS_CRYPTO_API_VERSION 0x03
#define gnutls_crypto_single_cipher_st gnutls_crypto_cipher_st
#define gnutls_crypto_single_mac_st gnutls_crypto_mac_st
@@ -92,13 +92,18 @@ typedef struct
int (*init) (gnutls_mac_algorithm_t, void **ctx);
int (*setkey) (void *ctx, const void *key, size_t keysize);
int (*hash) (void *ctx, const void *text, size_t textsize);
- int (*copy) (void **dst_ctx, void *src_ctx);
int (*output) (void *src_ctx, void *digest, size_t digestsize);
void (*deinit) (void *ctx);
} gnutls_crypto_mac_st;
-/* the same... setkey should be null */
-typedef gnutls_crypto_mac_st gnutls_crypto_digest_st;
+typedef struct
+{
+ int (*init) (gnutls_mac_algorithm_t, void **ctx);
+ int (*hash) (void *ctx, const void *text, size_t textsize);
+ int (*copy) (void **dst_ctx, void *src_ctx);
+ int (*output) (void *src_ctx, void *digest, size_t digestsize);
+ void (*deinit) (void *ctx);
+} gnutls_crypto_digest_st;
/**
* gnutls_rnd_level_t:
diff --git a/lib/nettle/mac.c b/lib/nettle/mac.c
index 2eb8a63880..71b9d012cb 100644
--- a/lib/nettle/mac.c
+++ b/lib/nettle/mac.c
@@ -186,25 +186,6 @@ static int wrap_nettle_hash_copy(void **bhd, void *ahd)
return 0;
}
-static int wrap_nettle_hmac_copy(void **bhd, void *ahd)
-{
- struct nettle_hmac_ctx *ctx = ahd;
- struct nettle_hmac_ctx *dst_ctx;
- int ret;
-
- ret = wrap_nettle_hmac_init(ctx->algo, bhd);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- dst_ctx = *bhd;
-
- memcpy(&dst_ctx->ctx, &ctx->ctx, sizeof(ctx->ctx));
-
- return 0;
-}
-
static void wrap_nettle_md_close(void *hd)
{
gnutls_free(hd);
@@ -318,7 +299,6 @@ gnutls_crypto_mac_st _gnutls_mac_ops = {
.init = wrap_nettle_hmac_init,
.setkey = wrap_nettle_hmac_setkey,
.hash = wrap_nettle_hmac_update,
- .copy = wrap_nettle_hmac_copy,
.output = wrap_nettle_hmac_output,
.deinit = wrap_nettle_md_close,
};