Add crypto_cipher_{init,encrypt,decrypt,deinit} for GnuTLS
authorJouni Malinen <j@w1.fi>
Sat, 7 Feb 2009 10:04:45 +0000 (12:04 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 7 Feb 2009 10:04:45 +0000 (12:04 +0200)
src/crypto/crypto_gnutls.c

index 20cbc35..8023965 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / wrapper functions for libgcrypt
- * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -198,3 +198,116 @@ error:
        gcry_mpi_release(bn_result);
        return ret;
 }
+
+
+struct crypto_cipher {
+       gcry_cipher_hd_t enc;
+       gcry_cipher_hd_t dec;
+};
+
+
+struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
+                                         const u8 *iv, const u8 *key,
+                                         size_t key_len)
+{
+       struct crypto_cipher *ctx;
+       gcry_error_t res;
+       enum gcry_cipher_algos a;
+       int ivlen;
+
+       ctx = os_zalloc(sizeof(*ctx));
+       if (ctx == NULL)
+               return NULL;
+
+       switch (alg) {
+       case CRYPTO_CIPHER_ALG_RC4:
+               a = GCRY_CIPHER_ARCFOUR;
+               res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM,
+                                      0);
+               gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0);
+               break;
+       case CRYPTO_CIPHER_ALG_AES:
+               if (key_len == 24)
+                       a = GCRY_CIPHER_AES192;
+               else if (key_len == 32)
+                       a = GCRY_CIPHER_AES256;
+               else
+                       a = GCRY_CIPHER_AES;
+               res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
+               gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
+               break;
+       case CRYPTO_CIPHER_ALG_3DES:
+               a = GCRY_CIPHER_3DES;
+               res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
+               gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
+               break;
+       case CRYPTO_CIPHER_ALG_DES:
+               a = GCRY_CIPHER_DES;
+               res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
+               gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
+               break;
+       case CRYPTO_CIPHER_ALG_RC2:
+               if (key_len == 5)
+                       a = GCRY_CIPHER_RFC2268_40;
+               else
+                       a = GCRY_CIPHER_RFC2268_128;
+               res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
+               gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
+               break;
+       default:
+               os_free(ctx);
+               return NULL;
+       }
+
+       if (res != GPG_ERR_NO_ERROR) {
+               os_free(ctx);
+               return NULL;
+       }
+
+       if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR ||
+           gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) {
+               gcry_cipher_close(ctx->enc);
+               gcry_cipher_close(ctx->dec);
+               os_free(ctx);
+               return NULL;
+       }
+
+       ivlen = gcry_cipher_get_algo_blklen(a);
+       if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR ||
+           gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) {
+               gcry_cipher_close(ctx->enc);
+               gcry_cipher_close(ctx->dec);
+               os_free(ctx);
+               return NULL;
+       }
+
+       return ctx;
+}
+
+
+int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
+                         u8 *crypt, size_t len)
+{
+       if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) !=
+           GPG_ERR_NO_ERROR)
+               return -1;
+       return 0;
+}
+
+
+int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
+                         u8 *plain, size_t len)
+{
+       if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) !=
+           GPG_ERR_NO_ERROR)
+               return -1;
+       return 0;
+}
+
+
+void crypto_cipher_deinit(struct crypto_cipher *ctx)
+{
+       gcry_cipher_close(ctx->enc);
+       gcry_cipher_close(ctx->dec);
+       os_free(ctx);
+}