Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: aead api to reduce redundancy

Currently, the aes_ccm.c and aes_gcm.c are almost line by line copy of
each other. This patch reduce code redundancy by moving the code in these
two files to crypto/aead_api.c to make it a higher level aead api. The
file aes_ccm.c and aes_gcm.c are removed and all the functions there are
now implemented in their headers using the newly added aead api.

Signed-off-by: Xiang Gao <qasdfgtyuiop@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Xiang Gao and committed by
Johannes Berg
4133da73 8c03145a

+120 -161
+1 -2
net/mac80211/Makefile
··· 6 6 driver-ops.o \ 7 7 sta_info.o \ 8 8 wep.o \ 9 + aead_api.o \ 9 10 wpa.o \ 10 11 scan.o offchannel.o \ 11 12 ht.o agg-tx.o agg-rx.o \ ··· 16 15 rate.o \ 17 16 michael.o \ 18 17 tkip.o \ 19 - aes_ccm.o \ 20 - aes_gcm.o \ 21 18 aes_cmac.o \ 22 19 aes_gmac.o \ 23 20 fils_aead.o \
+27
net/mac80211/aead_api.h
··· 1 + /* 2 + * This program is free software; you can redistribute it and/or modify 3 + * it under the terms of the GNU General Public License version 2 as 4 + * published by the Free Software Foundation. 5 + */ 6 + 7 + #ifndef _AEAD_API_H 8 + #define _AEAD_API_H 9 + 10 + #include <crypto/aead.h> 11 + #include <linux/crypto.h> 12 + 13 + struct crypto_aead * 14 + aead_key_setup_encrypt(const char *alg, const u8 key[], 15 + size_t key_len, size_t mic_len); 16 + 17 + int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 18 + size_t aad_len, u8 *data, 19 + size_t data_len, u8 *mic); 20 + 21 + int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 22 + size_t aad_len, u8 *data, 23 + size_t data_len, u8 *mic); 24 + 25 + void aead_key_free(struct crypto_aead *tfm); 26 + 27 + #endif /* _AEAD_API_H */
-115
net/mac80211/aes_ccm.c
··· 1 - /* 2 - * Copyright 2003-2004, Instant802 Networks, Inc. 3 - * Copyright 2005-2006, Devicescape Software, Inc. 4 - * 5 - * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org> 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License version 2 as 9 - * published by the Free Software Foundation. 10 - */ 11 - 12 - #include <linux/kernel.h> 13 - #include <linux/types.h> 14 - #include <linux/err.h> 15 - #include <crypto/aead.h> 16 - 17 - #include <net/mac80211.h> 18 - #include "key.h" 19 - #include "aes_ccm.h" 20 - 21 - int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 22 - u8 *data, size_t data_len, u8 *mic, 23 - size_t mic_len) 24 - { 25 - struct scatterlist sg[3]; 26 - struct aead_request *aead_req; 27 - int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); 28 - u8 *__aad; 29 - 30 - aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); 31 - if (!aead_req) 32 - return -ENOMEM; 33 - 34 - __aad = (u8 *)aead_req + reqsize; 35 - memcpy(__aad, aad, CCM_AAD_LEN); 36 - 37 - sg_init_table(sg, 3); 38 - sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); 39 - sg_set_buf(&sg[1], data, data_len); 40 - sg_set_buf(&sg[2], mic, mic_len); 41 - 42 - aead_request_set_tfm(aead_req, tfm); 43 - aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); 44 - aead_request_set_ad(aead_req, sg[0].length); 45 - 46 - crypto_aead_encrypt(aead_req); 47 - kzfree(aead_req); 48 - 49 - return 0; 50 - } 51 - 52 - int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 53 - u8 *data, size_t data_len, u8 *mic, 54 - size_t mic_len) 55 - { 56 - struct scatterlist sg[3]; 57 - struct aead_request *aead_req; 58 - int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); 59 - u8 *__aad; 60 - int err; 61 - 62 - if (data_len == 0) 63 - return -EINVAL; 64 - 65 - aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); 66 - if (!aead_req) 67 - return -ENOMEM; 68 - 69 - __aad = (u8 *)aead_req + reqsize; 70 - memcpy(__aad, aad, CCM_AAD_LEN); 71 - 72 - sg_init_table(sg, 3); 73 - sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); 74 - sg_set_buf(&sg[1], data, data_len); 75 - sg_set_buf(&sg[2], mic, mic_len); 76 - 77 - aead_request_set_tfm(aead_req, tfm); 78 - aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); 79 - aead_request_set_ad(aead_req, sg[0].length); 80 - 81 - err = crypto_aead_decrypt(aead_req); 82 - kzfree(aead_req); 83 - 84 - return err; 85 - } 86 - 87 - struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], 88 - size_t key_len, 89 - size_t mic_len) 90 - { 91 - struct crypto_aead *tfm; 92 - int err; 93 - 94 - tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); 95 - if (IS_ERR(tfm)) 96 - return tfm; 97 - 98 - err = crypto_aead_setkey(tfm, key, key_len); 99 - if (err) 100 - goto free_aead; 101 - err = crypto_aead_setauthsize(tfm, mic_len); 102 - if (err) 103 - goto free_aead; 104 - 105 - return tfm; 106 - 107 - free_aead: 108 - crypto_free_aead(tfm); 109 - return ERR_PTR(err); 110 - } 111 - 112 - void ieee80211_aes_key_free(struct crypto_aead *tfm) 113 - { 114 - crypto_free_aead(tfm); 115 - }
+31 -11
net/mac80211/aes_ccm.h
··· 10 10 #ifndef AES_CCM_H 11 11 #define AES_CCM_H 12 12 13 - #include <linux/crypto.h> 13 + #include "aead_api.h" 14 14 15 15 #define CCM_AAD_LEN 32 16 16 17 - struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], 18 - size_t key_len, 19 - size_t mic_len); 20 - int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 21 - u8 *data, size_t data_len, u8 *mic, 22 - size_t mic_len); 23 - int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 24 - u8 *data, size_t data_len, u8 *mic, 25 - size_t mic_len); 26 - void ieee80211_aes_key_free(struct crypto_aead *tfm); 17 + static inline struct crypto_aead * 18 + ieee80211_aes_key_setup_encrypt(const u8 key[], size_t key_len, size_t mic_len) 19 + { 20 + return aead_key_setup_encrypt("ccm(aes)", key, key_len, mic_len); 21 + } 22 + 23 + static inline int 24 + ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, 25 + u8 *b_0, u8 *aad, u8 *data, 26 + size_t data_len, u8 *mic) 27 + { 28 + return aead_encrypt(tfm, b_0, aad + 2, 29 + be16_to_cpup((__be16 *)aad), 30 + data, data_len, mic); 31 + } 32 + 33 + static inline int 34 + ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, 35 + u8 *b_0, u8 *aad, u8 *data, 36 + size_t data_len, u8 *mic) 37 + { 38 + return aead_decrypt(tfm, b_0, aad + 2, 39 + be16_to_cpup((__be16 *)aad), 40 + data, data_len, mic); 41 + } 42 + 43 + static inline void ieee80211_aes_key_free(struct crypto_aead *tfm) 44 + { 45 + return aead_key_free(tfm); 46 + } 27 47 28 48 #endif /* AES_CCM_H */
+29 -23
net/mac80211/aes_gcm.c net/mac80211/aead_api.c
··· 1 1 /* 2 + * Copyright 2003-2004, Instant802 Networks, Inc. 3 + * Copyright 2005-2006, Devicescape Software, Inc. 2 4 * Copyright 2014-2015, Qualcomm Atheros, Inc. 5 + * 6 + * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org> 3 7 * 4 8 * This program is free software; you can redistribute it and/or modify 5 9 * it under the terms of the GNU General Public License version 2 as ··· 13 9 #include <linux/kernel.h> 14 10 #include <linux/types.h> 15 11 #include <linux/err.h> 12 + #include <linux/scatterlist.h> 16 13 #include <crypto/aead.h> 17 14 18 - #include <net/mac80211.h> 19 - #include "key.h" 20 - #include "aes_gcm.h" 15 + #include "aead_api.h" 21 16 22 - int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, 23 - u8 *data, size_t data_len, u8 *mic) 17 + int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len, 18 + u8 *data, size_t data_len, u8 *mic) 24 19 { 20 + size_t mic_len = tfm->authsize; 25 21 struct scatterlist sg[3]; 26 22 struct aead_request *aead_req; 27 23 int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); 28 24 u8 *__aad; 29 25 30 - aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); 26 + aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC); 31 27 if (!aead_req) 32 28 return -ENOMEM; 33 29 34 30 __aad = (u8 *)aead_req + reqsize; 35 - memcpy(__aad, aad, GCM_AAD_LEN); 31 + memcpy(__aad, aad, aad_len); 36 32 37 33 sg_init_table(sg, 3); 38 - sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); 34 + sg_set_buf(&sg[0], __aad, aad_len); 39 35 sg_set_buf(&sg[1], data, data_len); 40 - sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); 36 + sg_set_buf(&sg[2], mic, mic_len); 41 37 42 38 aead_request_set_tfm(aead_req, tfm); 43 - aead_request_set_crypt(aead_req, sg, sg, data_len, j_0); 39 + aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); 44 40 aead_request_set_ad(aead_req, sg[0].length); 45 41 46 42 crypto_aead_encrypt(aead_req); 47 43 kzfree(aead_req); 44 + 48 45 return 0; 49 46 } 50 47 51 - int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, 52 - u8 *data, size_t data_len, u8 *mic) 48 + int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len, 49 + u8 *data, size_t data_len, u8 *mic) 53 50 { 51 + size_t mic_len = tfm->authsize; 54 52 struct scatterlist sg[3]; 55 53 struct aead_request *aead_req; 56 54 int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); ··· 62 56 if (data_len == 0) 63 57 return -EINVAL; 64 58 65 - aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); 59 + aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC); 66 60 if (!aead_req) 67 61 return -ENOMEM; 68 62 69 63 __aad = (u8 *)aead_req + reqsize; 70 - memcpy(__aad, aad, GCM_AAD_LEN); 64 + memcpy(__aad, aad, aad_len); 71 65 72 66 sg_init_table(sg, 3); 73 - sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); 67 + sg_set_buf(&sg[0], __aad, aad_len); 74 68 sg_set_buf(&sg[1], data, data_len); 75 - sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); 69 + sg_set_buf(&sg[2], mic, mic_len); 76 70 77 71 aead_request_set_tfm(aead_req, tfm); 78 - aead_request_set_crypt(aead_req, sg, sg, 79 - data_len + IEEE80211_GCMP_MIC_LEN, j_0); 72 + aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); 80 73 aead_request_set_ad(aead_req, sg[0].length); 81 74 82 75 err = crypto_aead_decrypt(aead_req); ··· 84 79 return err; 85 80 } 86 81 87 - struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], 88 - size_t key_len) 82 + struct crypto_aead * 83 + aead_key_setup_encrypt(const char *alg, const u8 key[], 84 + size_t key_len, size_t mic_len) 89 85 { 90 86 struct crypto_aead *tfm; 91 87 int err; 92 88 93 - tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); 89 + tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC); 94 90 if (IS_ERR(tfm)) 95 91 return tfm; 96 92 97 93 err = crypto_aead_setkey(tfm, key, key_len); 98 94 if (err) 99 95 goto free_aead; 100 - err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN); 96 + err = crypto_aead_setauthsize(tfm, mic_len); 101 97 if (err) 102 98 goto free_aead; 103 99 ··· 109 103 return ERR_PTR(err); 110 104 } 111 105 112 - void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) 106 + void aead_key_free(struct crypto_aead *tfm) 113 107 { 114 108 crypto_free_aead(tfm); 115 109 }
+30 -8
net/mac80211/aes_gcm.h
··· 9 9 #ifndef AES_GCM_H 10 10 #define AES_GCM_H 11 11 12 - #include <linux/crypto.h> 12 + #include "aead_api.h" 13 13 14 14 #define GCM_AAD_LEN 32 15 15 16 - int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, 17 - u8 *data, size_t data_len, u8 *mic); 18 - int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, 19 - u8 *data, size_t data_len, u8 *mic); 20 - struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], 21 - size_t key_len); 22 - void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm); 16 + static inline int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, 17 + u8 *j_0, u8 *aad, u8 *data, 18 + size_t data_len, u8 *mic) 19 + { 20 + return aead_encrypt(tfm, j_0, aad + 2, 21 + be16_to_cpup((__be16 *)aad), 22 + data, data_len, mic); 23 + } 24 + 25 + static inline int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, 26 + u8 *j_0, u8 *aad, u8 *data, 27 + size_t data_len, u8 *mic) 28 + { 29 + return aead_decrypt(tfm, j_0, aad + 2, 30 + be16_to_cpup((__be16 *)aad), 31 + data, data_len, mic); 32 + } 33 + 34 + static inline struct crypto_aead * 35 + ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len) 36 + { 37 + return aead_key_setup_encrypt("gcm(aes)", key, 38 + key_len, IEEE80211_GCMP_MIC_LEN); 39 + } 40 + 41 + static inline void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) 42 + { 43 + return aead_key_free(tfm); 44 + } 23 45 24 46 #endif /* AES_GCM_H */
+2 -2
net/mac80211/wpa.c
··· 464 464 pos += IEEE80211_CCMP_HDR_LEN; 465 465 ccmp_special_blocks(skb, pn, b_0, aad); 466 466 return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, 467 - skb_put(skb, mic_len), mic_len); 467 + skb_put(skb, mic_len)); 468 468 } 469 469 470 470 ··· 543 543 key->u.ccmp.tfm, b_0, aad, 544 544 skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, 545 545 data_len, 546 - skb->data + skb->len - mic_len, mic_len)) 546 + skb->data + skb->len - mic_len)) 547 547 return RX_DROP_UNUSABLE; 548 548 } 549 549