e79a0d1642823b5cc7b68207b97c734cb21801c4
[safe/jmp/linux-2.6] / drivers / staging / vt6656 / aes_ccmp.c
1 /*
2  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  *
20  * File: aes_ccmp.c
21  *
22  * Purpose: AES_CCMP decryption
23  *
24  * Author: Warren Hsu
25  *
26  * Date: Feb 15, 2005
27  *
28  * Functions:
29  *      AESbGenCCMP - Parsing RX-packet
30  *
31  *
32  * Revision History:
33  *
34  */
35
36 #include "umem.h"
37 #include "device.h"
38 #include "80211hdr.h"
39
40 /*---------------------  Static Definitions -------------------------*/
41
42 /*---------------------  Static Classes  ----------------------------*/
43
44 /*---------------------  Static Variables  --------------------------*/
45
46 /*
47  * SBOX Table
48  */
49
50 BYTE sbox_table[256] =
51 {
52 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
53 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
54 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
55 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
56 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
57 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
58 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
59 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
60 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
61 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
62 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
63 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
64 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
65 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
66 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
67 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
68 };
69
70 BYTE dot2_table[256] = {
71 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
72 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
73 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
74 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
75 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
76 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
77 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
78 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
79 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
80 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
81 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
82 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
83 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
84 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
85 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
86 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
87 };
88
89 BYTE dot3_table[256] = {
90 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
91 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
92 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
93 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
94 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
95 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
96 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
97 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
98 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
99 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
100 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
101 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
102 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
103 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
104 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
105 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
106 };
107
108 /*---------------------  Static Functions  --------------------------*/
109
110 /*---------------------  Export Variables  --------------------------*/
111
112 /*---------------------  Export Functions  --------------------------*/
113
114 void xor_128(BYTE *a, BYTE *b, BYTE *out)
115 {
116 PDWORD dwPtrA = (PDWORD) a;
117 PDWORD dwPtrB = (PDWORD) b;
118 PDWORD dwPtrOut =(PDWORD) out;
119
120     (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
121     (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
122     (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
123     (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
124 }
125
126
127 void xor_32(BYTE *a, BYTE *b, BYTE *out)
128 {
129 PDWORD dwPtrA = (PDWORD) a;
130 PDWORD dwPtrB = (PDWORD) b;
131 PDWORD dwPtrOut =(PDWORD) out;
132
133     (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
134 }
135
136 void AddRoundKey(BYTE *key, int round)
137 {
138 BYTE sbox_key[4];
139 BYTE rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
140
141     sbox_key[0] = sbox_table[key[13]];
142     sbox_key[1] = sbox_table[key[14]];
143     sbox_key[2] = sbox_table[key[15]];
144     sbox_key[3] = sbox_table[key[12]];
145
146     key[0] = key[0] ^ rcon_table[round];
147     xor_32(&key[0], sbox_key, &key[0]);
148
149     xor_32(&key[4], &key[0], &key[4]);
150     xor_32(&key[8], &key[4], &key[8]);
151     xor_32(&key[12], &key[8], &key[12]);
152 }
153
154 void SubBytes(BYTE *in, BYTE *out)
155 {
156 int i;
157
158     for (i=0; i< 16; i++)
159     {
160         out[i] = sbox_table[in[i]];
161     }
162 }
163
164 void ShiftRows(BYTE *in, BYTE *out)
165 {
166     out[0]  = in[0];
167     out[1]  = in[5];
168     out[2]  = in[10];
169     out[3]  = in[15];
170     out[4]  = in[4];
171     out[5]  = in[9];
172     out[6]  = in[14];
173     out[7]  = in[3];
174     out[8]  = in[8];
175     out[9]  = in[13];
176     out[10] = in[2];
177     out[11] = in[7];
178     out[12] = in[12];
179     out[13] = in[1];
180     out[14] = in[6];
181     out[15] = in[11];
182 }
183
184 void MixColumns(BYTE *in, BYTE *out)
185 {
186
187     out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3];
188     out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3];
189     out[2] = in[0] ^ in[1] ^ dot2_table[in[2]] ^ dot3_table[in[3]];
190     out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]];
191 }
192
193
194 void AESv128(BYTE *key, BYTE *data, BYTE *ciphertext)
195 {
196 int  i;
197 int  round;
198 BYTE TmpdataA[16];
199 BYTE TmpdataB[16];
200 BYTE abyRoundKey[16];
201
202     for(i=0; i<16; i++)
203         abyRoundKey[i] = key[i];
204
205     for (round = 0; round < 11; round++)
206     {
207         if (round == 0)
208         {
209             xor_128(abyRoundKey, data, ciphertext);
210             AddRoundKey(abyRoundKey, round);
211         }
212         else if (round == 10)
213         {
214             SubBytes(ciphertext, TmpdataA);
215             ShiftRows(TmpdataA, TmpdataB);
216             xor_128(TmpdataB, abyRoundKey, ciphertext);
217         }
218         else // round 1 ~ 9
219         {
220             SubBytes(ciphertext, TmpdataA);
221             ShiftRows(TmpdataA, TmpdataB);
222             MixColumns(&TmpdataB[0], &TmpdataA[0]);
223             MixColumns(&TmpdataB[4], &TmpdataA[4]);
224             MixColumns(&TmpdataB[8], &TmpdataA[8]);
225             MixColumns(&TmpdataB[12], &TmpdataA[12]);
226             xor_128(TmpdataA, abyRoundKey, ciphertext);
227             AddRoundKey(abyRoundKey, round);
228         }
229     }
230
231 }
232
233 /*
234  * Description: AES decryption
235  *
236  * Parameters:
237  *  In:
238  *      pbyRxKey            - The key used to decrypt
239  *      pbyFrame            - Starting address of packet header
240  *      wFrameSize          - Total packet size including CRC
241  *  Out:
242  *      none
243  *
244  * Return Value: MIC compare result
245  *
246  */
247 BOOL AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize)
248 {
249 BYTE            abyNonce[13];
250 BYTE            MIC_IV[16];
251 BYTE            MIC_HDR1[16];
252 BYTE            MIC_HDR2[16];
253 BYTE            abyMIC[16];
254 BYTE            abyCTRPLD[16];
255 BYTE            abyTmp[16];
256 BYTE            abyPlainText[16];
257 BYTE            abyLastCipher[16];
258
259 PS802_11Header  pMACHeader = (PS802_11Header) pbyFrame;
260 PBYTE           pbyIV;
261 PBYTE           pbyPayload;
262 WORD            wHLen = 22;
263 WORD            wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;//8 is IV, 8 is MIC, 4 is CRC
264 BOOL            bA4 = FALSE;
265 BYTE            byTmp;
266 WORD            wCnt;
267 int             ii,jj,kk;
268
269
270     pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
271     if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) &&
272          WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) {
273          bA4 = TRUE;
274          pbyIV += 6;             // 6 is 802.11 address4
275          wHLen += 6;
276          wPayloadSize -= 6;
277     }
278     pbyPayload = pbyIV + 8; //IV-length
279
280     abyNonce[0]  = 0x00; //now is 0, if Qos here will be priority
281     MEMvCopy(&(abyNonce[1]), pMACHeader->abyAddr2, U_ETHER_ADDR_LEN);
282     abyNonce[7]  = pbyIV[7];
283     abyNonce[8]  = pbyIV[6];
284     abyNonce[9]  = pbyIV[5];
285     abyNonce[10] = pbyIV[4];
286     abyNonce[11] = pbyIV[1];
287     abyNonce[12] = pbyIV[0];
288
289     //MIC_IV
290     MIC_IV[0] = 0x59;
291     MEMvCopy(&(MIC_IV[1]), &(abyNonce[0]), 13);
292     MIC_IV[14] = (BYTE)(wPayloadSize >> 8);
293     MIC_IV[15] = (BYTE)(wPayloadSize & 0xff);
294
295     //MIC_HDR1
296     MIC_HDR1[0] = (BYTE)(wHLen >> 8);
297     MIC_HDR1[1] = (BYTE)(wHLen & 0xff);
298     byTmp = (BYTE)(pMACHeader->wFrameCtl & 0xff);
299     MIC_HDR1[2] = byTmp & 0x8f;
300     byTmp = (BYTE)(pMACHeader->wFrameCtl >> 8);
301     byTmp &= 0x87;
302     MIC_HDR1[3] = byTmp | 0x40;
303     MEMvCopy(&(MIC_HDR1[4]), pMACHeader->abyAddr1, U_ETHER_ADDR_LEN);
304     MEMvCopy(&(MIC_HDR1[10]), pMACHeader->abyAddr2, U_ETHER_ADDR_LEN);
305
306     //MIC_HDR2
307     MEMvCopy(&(MIC_HDR2[0]), pMACHeader->abyAddr3, U_ETHER_ADDR_LEN);
308     byTmp = (BYTE)(pMACHeader->wSeqCtl & 0xff);
309     MIC_HDR2[6] = byTmp & 0x0f;
310     MIC_HDR2[7] = 0;
311     if ( bA4 ) {
312         MEMvCopy(&(MIC_HDR2[8]), pMACHeader->abyAddr4, U_ETHER_ADDR_LEN);
313     } else {
314         MIC_HDR2[8]  = 0x00;
315         MIC_HDR2[9]  = 0x00;
316         MIC_HDR2[10] = 0x00;
317         MIC_HDR2[11] = 0x00;
318         MIC_HDR2[12] = 0x00;
319         MIC_HDR2[13] = 0x00;
320     }
321     MIC_HDR2[14] = 0x00;
322     MIC_HDR2[15] = 0x00;
323
324     //CCMP
325     AESv128(pbyRxKey,MIC_IV,abyMIC);
326     for ( kk=0; kk<16; kk++ ) {
327         abyTmp[kk] = MIC_HDR1[kk] ^ abyMIC[kk];
328     }
329     AESv128(pbyRxKey,abyTmp,abyMIC);
330     for ( kk=0; kk<16; kk++ ) {
331         abyTmp[kk] = MIC_HDR2[kk] ^ abyMIC[kk];
332     }
333     AESv128(pbyRxKey,abyTmp,abyMIC);
334
335     wCnt = 1;
336     abyCTRPLD[0] = 0x01;
337     MEMvCopy(&(abyCTRPLD[1]), &(abyNonce[0]), 13);
338
339     for(jj=wPayloadSize; jj>16; jj=jj-16) {
340
341         abyCTRPLD[14] = (BYTE) (wCnt >> 8);
342         abyCTRPLD[15] = (BYTE) (wCnt & 0xff);
343
344         AESv128(pbyRxKey,abyCTRPLD,abyTmp);
345
346         for ( kk=0; kk<16; kk++ ) {
347             abyPlainText[kk] = abyTmp[kk] ^ pbyPayload[kk];
348         }
349         for ( kk=0; kk<16; kk++ ) {
350             abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
351         }
352         AESv128(pbyRxKey,abyTmp,abyMIC);
353
354         MEMvCopy(pbyPayload, abyPlainText, 16);
355         wCnt++;
356         pbyPayload += 16;
357     } //for wPayloadSize
358
359     //last payload
360     MEMvCopy(&(abyLastCipher[0]), pbyPayload, jj);
361     for ( ii=jj; ii<16; ii++ ) {
362         abyLastCipher[ii] = 0x00;
363     }
364
365     abyCTRPLD[14] = (BYTE) (wCnt >> 8);
366     abyCTRPLD[15] = (BYTE) (wCnt & 0xff);
367
368     AESv128(pbyRxKey,abyCTRPLD,abyTmp);
369     for ( kk=0; kk<16; kk++ ) {
370         abyPlainText[kk] = abyTmp[kk] ^ abyLastCipher[kk];
371     }
372     MEMvCopy(pbyPayload, abyPlainText, jj);
373     pbyPayload += jj;
374
375     //for MIC calculation
376     for ( ii=jj; ii<16; ii++ ) {
377         abyPlainText[ii] = 0x00;
378     }
379     for ( kk=0; kk<16; kk++ ) {
380         abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
381     }
382     AESv128(pbyRxKey,abyTmp,abyMIC);
383
384     //=>above is the calculate MIC
385     //--------------------------------------------
386
387     wCnt = 0;
388     abyCTRPLD[14] = (BYTE) (wCnt >> 8);
389     abyCTRPLD[15] = (BYTE) (wCnt & 0xff);
390     AESv128(pbyRxKey,abyCTRPLD,abyTmp);
391     for ( kk=0; kk<8; kk++ ) {
392         abyTmp[kk] = abyTmp[kk] ^ pbyPayload[kk];
393     }
394     //=>above is the dec-MIC from packet
395     //--------------------------------------------
396
397     if ( MEMEqualMemory(abyMIC,abyTmp,8) ) {
398         return TRUE;
399     } else {
400         return FALSE;
401     }
402
403 }