Home | History | Annotate | Download | only in src
      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 
    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 
    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 
    136 static inline uint32_t appSecGetCurState(const struct AppSecState *state)
    137 {
    138     return state->curState;
    139 }
    140 
    141 //init/deinit
    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 
    161 void appSecDeinit(struct AppSecState *state)
    162 {
    163     heapFree(state);
    164 }
    165 
    166 //if needed, decrypt and hash incoming data
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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