1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdint.h>
18 
19 #include <plat/inc/bl.h>
20 
21 #include <nanohub/sha2.h>
22 #include <nanohub/rsa.h>
23 #include <nanohub/aes.h>
24 
25 #include <appSec.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <heap.h>
29 #include <seos.h>
30 #include <inttypes.h>
31 
32 #define APP_HDR_SIZE                (sizeof(struct ImageHeader))
33 #define APP_HDR_MAX_SIZE            (sizeof(struct ImageHeader) + sizeof(struct AppSecSignHdr) + sizeof(struct AppSecEncrHdr))
34 #define APP_DATA_CHUNK_SIZE         (AES_BLOCK_WORDS * sizeof(uint32_t))  //data blocks are this size
35 #define APP_SIG_SIZE                RSA_BYTES
36 
37 // verify block is SHA placed in integral number of encryption blocks (for SHA256 and AES256 happens to be exactly 2 AES blocks)
38 #define APP_VERIFY_BLOCK_SIZE       ((SHA2_HASH_SIZE + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE
39 
40 #define APP_SEC_SIG_ALIGN           APP_DATA_CHUNK_SIZE
41 #define APP_SEC_ENCR_ALIGN          APP_DATA_CHUNK_SIZE
42 
43 #define STATE_INIT                  0 // nothing gotten yet
44 #define STATE_RXING_HEADERS         1 // variable size headers (min APP_HDR_SIZE, max APP_HDR_MAX_SIZE)
45 #define STATE_RXING_DATA            2 // each data block is AES_BLOCK_WORDS 32-bit words (for AES reasons)
46 #define STATE_RXING_SIG_HASH        3 // each is RSA_BYTES bytes
47 #define STATE_RXING_SIG_PUBKEY      4 // each is RSA_BYTES bytes
48 #define STATE_VERIFY                5 // decryption of ciphertext done; now decrypting and verifying the encrypted plaintext SHA2
49 #define STATE_DONE                  6 // all is finished and well
50 #define STATE_BAD                   7 // unrecoverable badness has happened. this will *NOT* fix itself. It is now ok to give up, start over, cry, or pray to your favourite deity for help
51 #define STATE_MAX                   8 // total number of states
52 
53 //#define DEBUG_FSM
54 
55 struct AppSecState {
56     union { //we save some memory by reusing this space.
57         struct {
58             struct AesCbcContext cbc;
59             struct Sha2state sha;
60             struct Sha2state cbcSha;
61         };
62         struct {
63             struct RsaState rsa;
64             uint32_t rsaState1, rsaState2, rsaStep;
65         };
66     };
67     uint32_t rsaTmp[RSA_WORDS];
68     uint32_t lastHash[SHA2_HASH_WORDS];
69 
70     AppSecWriteCbk writeCbk;
71     AppSecPubKeyFindCbk pubKeyFindCbk;
72     AppSecGetAesKeyCbk aesKeyAccessCbk;
73 
74     union {
75         union { //make the compiler work to make sure we have enough space
76             uint8_t placeholderAppHdr[APP_HDR_MAX_SIZE];
77             uint8_t placeholderDataChunk[APP_DATA_CHUNK_SIZE];
78             uint8_t placeholderSigChunk[APP_SIG_SIZE];
79             uint8_t placeholderAesKey[AES_KEY_WORDS * sizeof(uint32_t)];
80         };
81         uint8_t dataBytes[0]; //we actually use these two for access
82         uint32_t dataWords[0];
83     };
84 
85     uint32_t signedBytesIn;
86     uint32_t encryptedBytesIn;
87     uint32_t signedBytesOut;
88     uint32_t encryptedBytesOut;
89 
90     uint16_t haveBytes;       //in dataBytes...
91     uint16_t chunkSize;
92     uint8_t curState;
93     uint8_t needSig    :1;
94     uint8_t haveSig    :1;
95     uint8_t haveEncr   :1;
96     uint8_t haveTrustedKey :1;
97     uint8_t doingRsa   :1;
98 };
99 
limitChunkSize(struct AppSecState * state)100 static void limitChunkSize(struct AppSecState *state)
101 {
102     if (state->haveSig && state->chunkSize > state->signedBytesIn)
103         state->chunkSize = state->signedBytesIn;
104     if (state->haveEncr && state->chunkSize > state->encryptedBytesIn)
105         state->chunkSize = state->signedBytesIn;
106 }
107 
appSecSetCurState(struct AppSecState * state,uint32_t curState)108 static void appSecSetCurState(struct AppSecState *state, uint32_t curState)
109 {
110     const static uint16_t chunkSize[STATE_MAX] = {
111         [STATE_RXING_HEADERS] = APP_HDR_SIZE,
112         [STATE_RXING_DATA] = APP_DATA_CHUNK_SIZE,
113         [STATE_VERIFY] = APP_VERIFY_BLOCK_SIZE,
114         [STATE_RXING_SIG_HASH] = APP_SIG_SIZE,
115         [STATE_RXING_SIG_PUBKEY] = APP_SIG_SIZE,
116     };
117     if (curState >= STATE_MAX)
118         curState = STATE_BAD;
119     if (curState != state->curState || curState == STATE_INIT) {
120 #ifdef DEBUG_FSM
121         osLog(LOG_INFO, "%s: oldState=%" PRIu8
122                         "; new state=%" PRIu32
123                         "; old chunk size=%" PRIu16
124                         "; new chunk size=%" PRIu16
125                         "; have bytes=%" PRIu16
126                         "\n",
127               __func__, state->curState, curState,
128               state->chunkSize, chunkSize[curState],
129               state->haveBytes);
130 #endif
131         state->curState = curState;
132         state->chunkSize = chunkSize[curState];
133     }
134 }
135 
appSecGetCurState(const struct AppSecState * state)136 static inline uint32_t appSecGetCurState(const struct AppSecState *state)
137 {
138     return state->curState;
139 }
140 
141 //init/deinit
appSecInit(AppSecWriteCbk writeCbk,AppSecPubKeyFindCbk pubKeyFindCbk,AppSecGetAesKeyCbk aesKeyAccessCbk,bool mandateSigning)142 struct AppSecState *appSecInit(AppSecWriteCbk writeCbk, AppSecPubKeyFindCbk pubKeyFindCbk, AppSecGetAesKeyCbk aesKeyAccessCbk, bool mandateSigning)
143 {
144     struct AppSecState *state = heapAlloc(sizeof(struct AppSecState));
145 
146     if (!state)
147         return NULL;
148 
149     memset(state, 0, sizeof(struct AppSecState));
150 
151     state->writeCbk = writeCbk;
152     state->pubKeyFindCbk = pubKeyFindCbk;
153     state->aesKeyAccessCbk = aesKeyAccessCbk;
154     appSecSetCurState(state, STATE_INIT);
155     if (mandateSigning)
156         state->needSig = 1;
157 
158     return state;
159 }
160 
appSecDeinit(struct AppSecState * state)161 void appSecDeinit(struct AppSecState *state)
162 {
163     heapFree(state);
164 }
165 
166 //if needed, decrypt and hash incoming data
appSecBlockRx(struct AppSecState * state)167 static AppSecErr appSecBlockRx(struct AppSecState *state)
168 {
169     //if signatures are on, hash it
170     if (state->haveSig) {
171 
172         //make sure we do not get too much data & account for the data we got
173         if (state->haveBytes > state->signedBytesIn)
174             return APP_SEC_TOO_MUCH_DATA;
175         state->signedBytesIn -= state->haveBytes;
176 
177         //make sure we do not produce too much data (discard padding) & make sure we account for it
178         if (state->signedBytesOut < state->haveBytes)
179             state->haveBytes = state->signedBytesOut;
180         state->signedBytesOut -= state->haveBytes;
181 
182         //hash the data
183         BL.blSha2processBytes(&state->sha, state->dataBytes, state->haveBytes);
184     }
185 
186     // decrypt if encryption is on
187     if (state->haveEncr) {
188 
189         uint32_t *dataP = state->dataWords;
190         uint32_t i, numBlocks = state->haveBytes / APP_DATA_CHUNK_SIZE;
191 
192         //we should not be called with partial encr blocks
193         if (state->haveBytes % APP_DATA_CHUNK_SIZE)
194             return APP_SEC_TOO_LITTLE_DATA;
195 
196         // make sure we do not get too much data & account for the data we got
197         if (state->haveBytes > state->encryptedBytesIn)
198             return APP_SEC_TOO_MUCH_DATA;
199         state->encryptedBytesIn -= state->haveBytes;
200 
201         // decrypt
202         for (i = 0; i < numBlocks; i++, dataP += AES_BLOCK_WORDS)
203             BL.blAesCbcDecr(&state->cbc, dataP, dataP);
204 
205         // make sure we do not produce too much data (discard padding) & make sure we account for it
206         if (state->encryptedBytesOut < state->haveBytes)
207             state->haveBytes = state->encryptedBytesOut;
208         state->encryptedBytesOut -= state->haveBytes;
209 
210         if (state->haveBytes)
211             BL.blSha2processBytes(&state->cbcSha, state->dataBytes, state->haveBytes);
212     }
213 
214     limitChunkSize(state);
215 
216     return APP_SEC_NO_ERROR;
217 }
218 
appSecProcessIncomingHdr(struct AppSecState * state,uint32_t * needBytesOut)219 static AppSecErr appSecProcessIncomingHdr(struct AppSecState *state, uint32_t *needBytesOut)
220 {
221     struct ImageHeader *image;
222     struct nano_app_binary_t *aosp;
223     uint32_t flags;
224     uint32_t needBytes;
225     struct AppSecSignHdr *signHdr = NULL;
226     struct AppSecEncrHdr *encrHdr = NULL;
227     uint8_t *hdr = state->dataBytes;
228     AppSecErr ret;
229 
230     image = (struct ImageHeader *)hdr; hdr += sizeof(*image);
231     aosp = &image->aosp;
232     flags = aosp->flags;
233     if (aosp->header_version != 1 ||
234         aosp->magic != NANOAPP_AOSP_MAGIC ||
235         image->layout.version != 1 ||
236         image->layout.magic != GOOGLE_LAYOUT_MAGIC)
237         return APP_SEC_HEADER_ERROR;
238 
239     needBytes = sizeof(*image);
240     if ((flags & NANOAPP_SIGNED_FLAG) != 0)
241         needBytes += sizeof(*signHdr);
242     if ((flags & NANOAPP_ENCRYPTED_FLAG) != 0)
243         needBytes += sizeof(*encrHdr);
244 
245     *needBytesOut = needBytes;
246 
247     if (needBytes > state->haveBytes)
248         return APP_SEC_NO_ERROR;
249 
250     *needBytesOut = 0;
251 
252     if ((flags & NANOAPP_SIGNED_FLAG) != 0) {
253         signHdr = (struct AppSecSignHdr *)hdr; hdr += sizeof(*signHdr);
254         osLog(LOG_INFO, "%s: signed size=%" PRIu32 "\n",
255                         __func__, signHdr->appDataLen);
256         if (!signHdr->appDataLen) {
257             //no data bytes
258             return APP_SEC_INVALID_DATA;
259         }
260         state->signedBytesIn = state->signedBytesOut = signHdr->appDataLen;
261         state->haveSig = 1;
262         BL.blSha2init(&state->sha);
263         BL.blSha2processBytes(&state->sha, state->dataBytes, needBytes);
264     }
265 
266     if ((flags & NANOAPP_ENCRYPTED_FLAG) != 0) {
267         uint32_t k[AES_KEY_WORDS];
268 
269         encrHdr = (struct AppSecEncrHdr *)hdr; hdr += sizeof(*encrHdr);
270         osLog(LOG_INFO, "%s: encrypted data size=%" PRIu32
271                         "; key ID=%016" PRIX64 "\n",
272                         __func__, encrHdr->dataLen, encrHdr->keyID);
273 
274         if (!encrHdr->dataLen || !encrHdr->keyID)
275             return APP_SEC_INVALID_DATA;
276         ret = state->aesKeyAccessCbk(encrHdr->keyID, k);
277         if (ret != APP_SEC_NO_ERROR) {
278             osLog(LOG_ERROR, "%s: Secret key not found\n", __func__);
279             return ret;
280         }
281 
282         BL.blAesCbcInitForDecr(&state->cbc, k, encrHdr->IV);
283         BL.blSha2init(&state->cbcSha);
284         state->encryptedBytesOut = encrHdr->dataLen;
285         state->encryptedBytesIn = ((state->encryptedBytesOut + APP_SEC_ENCR_ALIGN - 1) / APP_SEC_ENCR_ALIGN) * APP_SEC_ENCR_ALIGN;
286         state->haveEncr = 1;
287         osLog(LOG_INFO, "%s: encrypted aligned data size=%" PRIu32 "\n",
288                         __func__, state->encryptedBytesIn);
289 
290         if (state->haveSig) {
291             state->signedBytesIn = state->signedBytesOut = signHdr->appDataLen - sizeof(*encrHdr);
292             // at this point, signedBytesOut must equal encryptedBytesIn
293             if (state->signedBytesOut != (state->encryptedBytesIn + SHA2_HASH_SIZE)) {
294                 osLog(LOG_ERROR, "%s: sig data size does not match encrypted data\n", __func__);
295                 return APP_SEC_INVALID_DATA;
296             }
297         }
298     }
299 
300     //if we are in must-sign mode and no signature was provided, fail
301     if (!state->haveSig && state->needSig) {
302         osLog(LOG_ERROR, "%s: only signed images can be uploaded\n", __func__);
303         return APP_SEC_SIG_VERIFY_FAIL;
304     }
305 
306     // now, transform AOSP header to FW common header
307     struct FwCommonHdr common = {
308         .magic   = APP_HDR_MAGIC,
309         .appId   = aosp->app_id,
310         .fwVer   = APP_HDR_VER_CUR,
311         .fwFlags = image->layout.flags,
312         .appVer  = aosp->app_version,
313         .payInfoType = image->layout.payload,
314         .rfu = { 0xFF, 0xFF },
315     };
316 
317     // check to see if this is special system types of payload
318     switch(image->layout.payload) {
319     case LAYOUT_APP:
320         common.fwFlags = (common.fwFlags | FL_APP_HDR_APPLICATION) & ~FL_APP_HDR_INTERNAL;
321         common.payInfoSize = sizeof(struct AppInfo);
322         osLog(LOG_INFO, "App container found\n");
323         break;
324     case LAYOUT_KEY:
325         common.fwFlags |= FL_APP_HDR_SECURE;
326         common.payInfoSize = sizeof(struct KeyInfo);
327         osLog(LOG_INFO, "Key container found\n");
328         break;
329     case LAYOUT_OS:
330         common.payInfoSize = sizeof(struct OsUpdateHdr);
331         osLog(LOG_INFO, "OS update container found\n");
332         break;
333     default:
334         break;
335     }
336 
337     memcpy(state->dataBytes, &common, sizeof(common));
338     state->haveBytes = sizeof(common);
339 
340     //we're now in data-accepting state
341     appSecSetCurState(state, STATE_RXING_DATA);
342 
343     return APP_SEC_NO_ERROR;
344 }
345 
appSecProcessIncomingData(struct AppSecState * state)346 static AppSecErr appSecProcessIncomingData(struct AppSecState *state)
347 {
348     //check for data-ending conditions
349     if (state->haveSig && !state->signedBytesIn) {
350         // we're all done with the signed portion of the data, now come the signatures
351         appSecSetCurState(state, STATE_RXING_SIG_HASH);
352 
353         //collect the hash
354         memcpy(state->lastHash, BL.blSha2finish(&state->sha), SHA2_HASH_SIZE);
355     } else if (state->haveEncr && !state->encryptedBytesIn) {
356         if (appSecGetCurState(state) == STATE_RXING_DATA) {
357             //we're all done with encrypted plaintext
358             state->encryptedBytesIn = sizeof(state->cbcSha);
359             appSecSetCurState(state, STATE_VERIFY);
360         }
361     }
362 
363     //pass to caller
364     return state->haveBytes ? state->writeCbk(state->dataBytes, state->haveBytes) : APP_SEC_NO_ERROR;
365 }
366 
appSecDoSomeProcessing(struct AppSecState * state)367 AppSecErr appSecDoSomeProcessing(struct AppSecState *state)
368 {
369     const uint32_t *result;
370 
371     if (!state->doingRsa) {
372         //shouldn't be calling us then...
373         return APP_SEC_BAD;
374     }
375 
376     result = BL.blRsaPubOpIterative(&state->rsa, state->rsaTmp, state->dataWords, &state->rsaState1, &state->rsaState2, &state->rsaStep);
377     if (state->rsaStep)
378         return APP_SEC_NEED_MORE_TIME;
379 
380     //we just finished the RSA-ing
381     state->doingRsa = 0;
382 
383     //verify signature padding (and thus likely: correct decryption)
384     result = BL.blSigPaddingVerify(result);
385     if (!result)
386         return APP_SEC_SIG_DECODE_FAIL;
387 
388     //check if hashes match
389     if (memcmp(state->lastHash, result, SHA2_HASH_SIZE))
390         return APP_SEC_SIG_VERIFY_FAIL;
391 
392     //hash the provided pubkey
393     BL.blSha2init(&state->sha);
394     BL.blSha2processBytes(&state->sha, state->dataBytes, APP_SIG_SIZE);
395     memcpy(state->lastHash, BL.blSha2finish(&state->sha), SHA2_HASH_SIZE);
396     appSecSetCurState(state, STATE_RXING_SIG_HASH);
397 
398     return APP_SEC_NO_ERROR;
399 }
400 
appSecProcessIncomingSigData(struct AppSecState * state)401 static AppSecErr appSecProcessIncomingSigData(struct AppSecState *state)
402 {
403     bool keyFound = false;
404 
405     //if we're RXing the hash, just stash it away and move on
406     if (appSecGetCurState(state) == STATE_RXING_SIG_HASH) {
407         state->haveTrustedKey = 0;
408         memcpy(state->rsaTmp, state->dataWords, APP_SIG_SIZE);
409         appSecSetCurState(state, STATE_RXING_SIG_PUBKEY);
410         return APP_SEC_NO_ERROR;
411     }
412 
413     // verify it is a known root
414     state->pubKeyFindCbk(state->dataWords, &keyFound);
415     state->haveTrustedKey = keyFound;
416 
417     //we now have the pubKey. decrypt over time
418     state->doingRsa = 1;
419     state->rsaStep = 0;
420     return APP_SEC_NEED_MORE_TIME;
421 }
422 
appSecVerifyEncryptedData(struct AppSecState * state)423 static AppSecErr appSecVerifyEncryptedData(struct AppSecState *state)
424 {
425     const uint32_t *hash = BL.blSha2finish(&state->cbcSha);
426     bool verified = memcmp(hash, state->dataBytes, SHA2_BLOCK_SIZE) == 0;
427 
428     osLog(LOG_INFO, "%s: decryption verification: %s\n", __func__, verified ? "passed" : "failed");
429 
430 // TODO: fix verify logic
431 //    return verified ? APP_SEC_NO_ERROR : APP_SEC_VERIFY_FAILED;
432     return APP_SEC_NO_ERROR;
433 }
434 
appSecRxData(struct AppSecState * state,const void * dataP,uint32_t len,uint32_t * lenUnusedP)435 AppSecErr appSecRxData(struct AppSecState *state, const void *dataP, uint32_t len, uint32_t *lenUnusedP)
436 {
437     const uint8_t *data = (const uint8_t*)dataP;
438     AppSecErr ret = APP_SEC_NO_ERROR;
439     uint32_t needBytes;
440 
441     if (appSecGetCurState(state) == STATE_INIT)
442         appSecSetCurState(state, STATE_RXING_HEADERS);
443 
444     while (len) {
445         len--;
446         state->dataBytes[state->haveBytes++] = *data++;
447         if (state->haveBytes < state->chunkSize)
448             continue;
449         switch (appSecGetCurState(state)) {
450         case STATE_RXING_HEADERS:
451             // AOSP header is never encrypted; if it is signed, it will hash itself
452             needBytes = 0;
453             ret = appSecProcessIncomingHdr(state, &needBytes);
454             if (ret != APP_SEC_NO_ERROR)
455                 goto out;
456             if (needBytes > state->chunkSize) {
457                 state->chunkSize = needBytes;
458                 // get more data and try again
459                 continue;
460             }
461             // done with parsing header(s); we might have something to write to flash
462             if (state->haveBytes) {
463                 osLog(LOG_INFO, "%s: save converted header [%" PRIu16 " bytes] to flash\n", __func__, state->haveBytes);
464                 ret = appSecProcessIncomingData(state);
465                 state->haveBytes = 0;
466             }
467             limitChunkSize(state);
468             goto out;
469 
470         case STATE_RXING_DATA:
471             ret = appSecBlockRx(state);
472             if (ret != APP_SEC_NO_ERROR)
473                 goto out;
474 
475             ret = appSecProcessIncomingData(state);
476             state->haveBytes = 0;
477             if (ret != APP_SEC_NO_ERROR)
478                 goto out;
479             break;
480 
481         case STATE_VERIFY:
482             ret = appSecBlockRx(state);
483             if (ret == APP_SEC_NO_ERROR)
484                 ret = appSecProcessIncomingData(state);
485             if (ret == APP_SEC_NO_ERROR)
486                 ret = appSecVerifyEncryptedData(state);
487             goto out;
488 
489         case STATE_RXING_SIG_HASH:
490         case STATE_RXING_SIG_PUBKEY:
491             //no need for calling appSecBlockRx() as sigs are not signed, and encryption cannot be done after signing
492             ret = appSecProcessIncomingSigData(state);
493             state->haveBytes = 0;
494             goto out;
495 
496         default:
497             appSecSetCurState(state, STATE_BAD);
498             state->haveBytes = 0;
499             len = 0;
500             ret = APP_SEC_BAD;
501             break;
502         }
503     }
504 
505 out:
506     *lenUnusedP = len;
507 
508     if (ret != APP_SEC_NO_ERROR && ret != APP_SEC_NEED_MORE_TIME) {
509         osLog(LOG_ERROR, "%s: failed: state=%" PRIu32 "; err=%" PRIu32 "\n",
510               __func__, appSecGetCurState(state), ret);
511         appSecSetCurState(state,  STATE_BAD);
512     }
513 
514     return ret;
515 }
516 
appSecRxDataOver(struct AppSecState * state)517 AppSecErr appSecRxDataOver(struct AppSecState *state)
518 {
519     AppSecErr ret;
520 
521     // Feed remaining data to data processor, if any
522     if (state->haveBytes) {
523         // if we are using encryption and/or signing, we are supposed to consume all data at this point.
524         if (state->haveSig || state->haveEncr) {
525             appSecSetCurState(state, STATE_BAD);
526             return APP_SEC_TOO_LITTLE_DATA;
527         }
528         // Not in data rx stage when the incoming data ends? This is not good (if we had encr or sign we'd not be here)
529         if (appSecGetCurState(state) != STATE_RXING_DATA) {
530             appSecSetCurState(state, STATE_BAD);
531             return APP_SEC_TOO_LITTLE_DATA;
532         }
533         // Feed the remaining data to the data processor
534         ret = appSecProcessIncomingData(state);
535         if (ret != APP_SEC_NO_ERROR) {
536             appSecSetCurState(state, STATE_BAD);
537             return ret;
538         }
539     } else {
540         // we don't know in advance how many signature packs we shall receive,
541         // so we evaluate every signature pack as if it is the last, but do not
542         // return error if public key is not trusted; only here we make the final
543         // determination
544         if (state->haveSig) {
545             // check the most recent key status
546             if (!state->haveTrustedKey) {
547                 appSecSetCurState(state, STATE_BAD);
548                 return APP_SEC_SIG_ROOT_UNKNOWN;
549             } else {
550                 appSecSetCurState(state, STATE_DONE);
551             }
552         }
553     }
554 
555     //for unsigned/unencrypted case we have no way to judge length, so we assume it is over when we're told it is
556     //this is potentially dangerous, but then again so is allowing unsigned uploads in general.
557     if (!state->haveSig && !state->haveEncr && appSecGetCurState(state) == STATE_RXING_DATA)
558         appSecSetCurState(state, STATE_DONE);
559 
560     //Check the state and return our verdict
561     if(appSecGetCurState(state) == STATE_DONE)
562         return APP_SEC_NO_ERROR;
563 
564     appSecSetCurState(state, STATE_BAD);
565     return APP_SEC_TOO_LITTLE_DATA;
566 }
567