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