Browse Source

qcacmn: Add support for AES ctr mode for kernel 3.18

Add changes to support AES CTR modes for FILS encryption and
decryption.

Change-Id: I418e85987bfa96efb7b9dc10e9b2125290299c89
CRs-Fixed: 2039626
Kapil Gupta 8 years ago
parent
commit
7401104431
2 changed files with 64 additions and 1 deletions
  1. 3 0
      qdf/inc/qdf_crypto.h
  2. 61 1
      qdf/linux/src/qdf_crypto.c

+ 3 - 0
qdf/inc/qdf_crypto.h

@@ -47,6 +47,9 @@ extern "C" {
 #define FIXED_PARAM_OFFSET_ASSOC_REQ 4
 #define FIXED_PARAM_OFFSET_ASSOC_RSP 6
 
+#define IS_VALID_CTR_KEY_LEN(len) ((((len) == 16) || ((len) == 32) || \
+	((len) == 48)) ? 1 : 0)
+
 /* Function declarations and documenation */
 
 /**

+ 61 - 1
qdf/linux/src/qdf_crypto.c

@@ -270,7 +270,7 @@ int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv,
 	struct scatterlist sg_in, sg_out;
 	int ret;
 
-	if (key_len != 16 && key_len != 24 && key_len != 32) {
+	if (!IS_VALID_CTR_KEY_LEN(key_len)) {
 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
 			  FL("Invalid key length: %u"), key_len);
 		return -EINVAL;
@@ -320,6 +320,66 @@ int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv,
 	crypto_free_skcipher(tfm);
 	return ret;
 }
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv,
+		const uint8_t *src, size_t src_len, uint8_t *dest, bool enc)
+{
+	struct crypto_ablkcipher *tfm;
+	struct ablkcipher_request *req = NULL;
+	struct scatterlist sg_in, sg_out;
+	int ret;
+
+	if (!IS_VALID_CTR_KEY_LEN(key_len)) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  FL("Invalid key length: %u"), key_len);
+		return -EINVAL;
+	}
+
+	tfm = crypto_alloc_ablkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm)) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  FL("Failed to alloc transformation for ctr(aes):%ld"),
+			  PTR_ERR(tfm));
+		return -EAGAIN;
+	}
+
+	req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+	if (!req) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  FL("Failed to allocate request for ctr(aes)"));
+		crypto_free_ablkcipher(tfm);
+		return -EAGAIN;
+	}
+
+	ret = crypto_ablkcipher_setkey(tfm, key, key_len);
+	if (ret) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  FL("Set key failed for ctr(aes), ret:%d"), -ret);
+		ablkcipher_request_free(req);
+		crypto_free_ablkcipher(tfm);
+		return ret;
+	}
+
+	sg_init_one(&sg_in, src, src_len);
+	sg_init_one(&sg_out, dest, src_len);
+	ablkcipher_request_set_crypt(req, &sg_in, &sg_out, src_len, siv);
+
+	if (enc)
+		ret = crypto_ablkcipher_encrypt(req);
+	else
+		ret = crypto_ablkcipher_decrypt(req);
+
+	if (ret) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  FL("%s failed for ctr(aes), ret:%d"),
+			  enc ? "Encryption" : "Decryption", -ret);
+	}
+
+	ablkcipher_request_free(req);
+	crypto_free_ablkcipher(tfm);
+
+	return ret;
+}
 #else
 int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv,
 		const uint8_t *src, size_t src_len, uint8_t *dest, bool enc)