Setting up repository
[linux-libre-firmware.git] / ath9k_htc / target_firmware / wlan / ieee80211_output.c
1 /*
2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted (subject to the limitations in the
7  * disclaimer below) provided that the following conditions are met:
8  *
9  *  * Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *  * Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *  * Neither the name of Qualcomm Atheros nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
22  * GRANTED BY THIS LICENSE.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
23  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 #include <adf_os_types.h>
37 #include <adf_os_dma.h>
38 #include <adf_os_timer.h>
39 #include <adf_os_lock.h>
40 #include <adf_os_io.h>
41 #include <adf_os_mem.h>
42 #include <adf_os_module.h>
43 #include <adf_os_util.h>
44 #include <adf_os_stdtypes.h>
45 #include <adf_os_defer.h>
46 #include <adf_os_atomic.h>
47 #include <adf_nbuf.h>
48 #include <adf_net.h>
49
50 #include <if_llc.h>
51 #include "ieee80211_var.h"
52
53 #include "ieee80211.h"
54 #include <wlan_hdr.h>
55
56 a_status_t
57 ieee80211_tgt_crypto_encap(struct ieee80211_frame *wh,
58                            struct ieee80211_node_target *ni,
59                            a_uint8_t keytype)
60 {
61 #define CRYPTO_KEY_TYPE_AES          2
62 #define CRYPTO_KEY_TYPE_TKIP         3
63 #define CRYPTO_KEY_TYPE_WAPI         4
64 #define IEEE80211_WLAN_HDR_LEN      24
65
66         a_uint8_t *iv = NULL;
67         a_uint16_t tmp;
68         a_uint16_t offset = IEEE80211_WLAN_HDR_LEN;
69         a_uint8_t b1, b2;
70         struct ieee80211_qosframe_addr4 *wh_mesh;
71
72         if (IEEE80211_QOS_HAS_SEQ(wh))
73                 offset += 4;  // pad for 4 byte alignment
74
75         /* set the offset to 32 if the mesh control field is present */
76         wh_mesh = (struct ieee80211_qosframe_addr4 *)wh;
77         if (wh_mesh->i_qos[1] & 0x01)
78                 offset = 32;
79
80         iv = (a_uint8_t *) wh;
81         iv = iv + offset;
82
83         switch (keytype) {
84         case CRYPTO_KEY_TYPE_AES:
85                 ni->ni_iv16++;
86                 if (ni->ni_iv16 == 0)
87                 {
88                         ni->ni_iv32++;
89                 }
90
91                 *iv++ = (a_uint8_t) ni->ni_iv16;
92                 *iv++ = (a_uint8_t) (ni->ni_iv16 >> 8);
93                 *iv++ = 0x00;
94                 *iv++ |= 0x20;
95
96                 tmp = (a_uint16_t) ni->ni_iv32;
97                 *iv++ = (a_uint8_t) tmp;
98                 *iv++ = (a_uint8_t) (tmp >> 8);
99
100                 tmp = (a_uint16_t) (ni->ni_iv32 >> 16);
101                 *iv++ = (a_uint8_t) tmp;
102                 *iv = (a_uint8_t) (tmp >> 8);
103                 break;
104         case CRYPTO_KEY_TYPE_TKIP:
105                 ni->ni_iv16++;
106                 if (ni->ni_iv16 == 0)
107                 {
108                         ni->ni_iv32++;
109                 }
110
111                 b1 = (a_uint8_t) (ni->ni_iv16 >> 8);
112                 b2 = (b1 | 0x20) & 0x7f;
113
114                 *iv++ = b1;
115                 *iv++ = b2;
116
117                 *iv++ = (a_uint8_t) ni->ni_iv16;
118                 *iv++ |= 0x20;
119
120                 tmp = (a_uint16_t) ni->ni_iv32;
121                 *iv++ = (a_uint8_t) tmp;
122                 *iv++ = (a_uint8_t) (tmp >> 8);
123
124                 tmp = (a_uint16_t) (ni->ni_iv32 >> 16);
125                 *iv++ = (a_uint8_t) tmp;
126                 *iv = (a_uint8_t) (tmp >> 8);
127                 break;
128         default:
129                 break;
130         }
131
132         return 1;
133
134 #undef CRYPTO_KEY_TYPE_TKIP
135 #undef CRYPTO_KEY_TYPE_AES
136 #undef CRYPTO_KEY_TYPE_WAPI
137 #undef IEEE80211_WLAN_HDR_LEN
138 }
139 #undef  IEEE80211_ADDR_LEN