hc
2024-08-12 33276c6b0b8513a340de65b0ef99993023df46ca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
 * Bit packing and Base64 utils for EWP
 *
 * Copyright (C) 2020, Broadcom.
 *
 *      Unless you and Broadcom execute a separate written software license
 * agreement governing use of this software, this software is licensed to you
 * under the terms of the GNU General Public License version 2 (the "GPL"),
 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
 * following added to such license:
 *
 *      As a special exception, the copyright holders of this software give you
 * permission to link this software with independent modules, and to copy and
 * distribute the resulting executable under terms of your choice, provided that
 * you also meet, for each linked independent module, the terms and conditions of
 * the license of that module.  An independent module is a module which is not
 * derived from this software.  The special exception does not apply to any
 * modifications of the software.
 *
 *
 * <<Broadcom-WL-IPTag/Open:>>
 *
 * $Id$
 */
 
#include <dhd_bitpack.h>
 
#define BIT_PACK_OVERFLOW 0xFFFFFFFFu
 
const char* base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
#define BASE64_MAX_VALUE 63u
 
#define BASE64_UNIT_LEN 6u
 
#define BASE64_OFFSET0 0u
#define BASE64_OFFSET1 6u
#define BASE64_OFFSET2 12u
 
#define MASK_UPPER_6BIT 0xfc
#define MASK_LOWER_6BIT 0x3f
 
#define MASK_UPPER_4BIT 0xf0
#define MASK_LOWER_4BIT 0x0f
 
#define MASK_UPPER_2BIT 0xc0
#define MASK_LOWER_2BIT 0x03
 
#define SHIFT_2BIT 2u
#define SHIFT_4BIT 4u
#define SHIFT_6BIT 6u
 
#define BASE64_PADDING_MARGIN 4u
 
/*
 * Function:    dhd_bit_pack
 *
 * Purpose:    bit data packing to given buffer
 *
 * Input Parameters:
 *      buf        buffer to pack bit data
 *      buf_len        total buffer length
 *    bit_offset    offset in buffer (bitwise)
 *    data        data to pack (max 32 bit)
 *    bit_length    bit length to pack
 *
 * Output:
 *    Updated bit offset in buf
 */
int32
dhd_bit_pack(char *buf, int buf_len, int bit_offset, uint32 data, int32 bit_length)
{
 
   int32 byte_shift = (bit_offset / 8);
   int32 local_bit_offset = bit_offset % 8;
   int32 available_bit = 8 - local_bit_offset;
   int32 remain_bit = bit_length;
   uint32 cropped_data;
   int32 idx;
   int32 total_byte = BYTE_SIZE(local_bit_offset + bit_length);
 
   if (bit_length > 32) {
       /* exceeded max bit length, do nothing */
       return bit_offset;
   }
   if (BYTE_SIZE(bit_offset + bit_length) > buf_len) {
       /* can't pack more bits if expected offset is
        * exceeded then buffer size
        */
       return bit_offset;
   }
   if (bit_length < 32 && data >= 1<<bit_length) {
       cropped_data = BIT_PACK_OVERFLOW << (32 - bit_length);
       cropped_data = cropped_data >> (32 - bit_length);
   } else {
       cropped_data = data << (32 - bit_length);
       cropped_data = cropped_data >> (32 - bit_length);
   }
 
   buf += byte_shift;
 
   remain_bit = bit_length;
   if (total_byte > 10) {
       return bit_offset;
   }
   for (idx = 0; idx < total_byte; idx++) {
       char temp_byte = 0x00;
       if (idx == 0) {
           local_bit_offset = bit_offset % 8;
       } else {
           local_bit_offset = 0;
       }
 
       available_bit = 8 - local_bit_offset;
       remain_bit -= available_bit;
       if (remain_bit >= 0) {
           temp_byte = cropped_data >> remain_bit;
       } else {
           temp_byte = cropped_data << (-1*remain_bit);
       }
       *buf = *buf | temp_byte;
       buf ++;
   }
   bit_offset += bit_length;
 
   return bit_offset;
}
 
static char
dhd_base64_get_code(char input)
{
   if (input > BASE64_MAX_VALUE) {
       return '=';
   }
   return base64_table[(int)input];
}
 
/*
 * Function:    dhd_base64_encode
 *
 * Purpose:    base64 encoding module which converts from 8 bits to
 *        6 bit based, base64 format using base64_table
 *        eg:    input:    hex-123456
 *                bin-0001|0010|0011|0100|0101|0110
 *            encode every 6 bit :
 *                bin-000100|100011|010001|010110
 *            base64 code :
 *                base64-EjRW
 *
 * Input Parameters:
 *      in_buf        input buffer
 *      in_buf_len    length of input buffer
 *    out_buf        output buffer
 *    out_buf_len    length_ of output buffer
 *
 * Output:
 *    length of encoded base64 string
 */
int32
dhd_base64_encode(char* in_buf, int32 in_buf_len, char* out_buf, int32 out_buf_len)
{
   char* input_pos;
   char* input_end;
   char* base64_out;
   char* base64_out_pos;
   char* base64_output_end;
   char current_byte = 0;
   char masked_byte = 0;
   int32 estimated_out_len = 0;
   int32 offset = 0;
 
   if (!in_buf || !out_buf || in_buf_len == 0 || out_buf_len == 0) {
       /* wrong input parameters */
       return 0;
   }
 
   input_pos = in_buf;
   input_end = in_buf + in_buf_len;
   base64_out = out_buf;
   base64_out_pos = base64_out;
   base64_output_end = out_buf + out_buf_len - BASE64_PADDING_MARGIN;
   estimated_out_len = in_buf_len / 3 * 4;
 
   if (estimated_out_len > out_buf_len) {
       /* estimated output length is
        * larger than output buffer size
        */
       return 0;
   }
 
   while (input_pos != input_end) {
       if (base64_out_pos > base64_output_end) {
           /* outbuf buffer size exceeded, finish encoding */
           break;
       }
       if (offset == BASE64_OFFSET0) {
           current_byte = *input_pos++;
           masked_byte = (current_byte & MASK_UPPER_6BIT) >> SHIFT_2BIT;
           *base64_out_pos++ = dhd_base64_get_code(masked_byte);
           masked_byte = (current_byte & MASK_LOWER_2BIT) << SHIFT_4BIT;
           offset += BASE64_UNIT_LEN;
       } else if (offset == BASE64_OFFSET1) {
           current_byte = *input_pos++;
           masked_byte |= (current_byte & MASK_UPPER_4BIT) >> SHIFT_4BIT;
           *base64_out_pos++ = dhd_base64_get_code(masked_byte);
           masked_byte = (current_byte & MASK_LOWER_4BIT) << SHIFT_2BIT;
           offset += BASE64_UNIT_LEN;
       } else if (offset == BASE64_OFFSET2) {
           current_byte = *input_pos++;
           masked_byte |= (current_byte & MASK_UPPER_2BIT) >> SHIFT_6BIT;
           *base64_out_pos++ = dhd_base64_get_code(masked_byte);
           offset += BASE64_UNIT_LEN;
           masked_byte = (current_byte & MASK_LOWER_6BIT);
           *base64_out_pos++ = dhd_base64_get_code(masked_byte);
           offset = BASE64_OFFSET0;
       }
   }
   if (offset == BASE64_OFFSET1) {
       *base64_out_pos++ = dhd_base64_get_code(masked_byte);
       *base64_out_pos++ = '=';
       *base64_out_pos++ = '=';
   } else if (offset == BASE64_OFFSET2) {
       *base64_out_pos++ = dhd_base64_get_code(masked_byte);
       *base64_out_pos++ = '=';
   }
 
   return base64_out_pos - base64_out;
}