/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <appSec.h>
#include <string.h>
#include <stdio.h>
#include <heap.h>
#include <sha2.h>
#include <rsa.h>
#include <aes.h>


#define APP_HDR_SIZE                32                                    //headers are this size
#define APP_DATA_CHUNK_SIZE         (AES_BLOCK_WORDS * sizeof(uint32_t))  //data blocks are this size
#define APP_SIG_SIZE                RSA_BYTES

#define RSA_WORDS                   (RSA_BYTES / sizeof(uint32_t))

#define APP_SEC_SIG_ALIGN           APP_DATA_CHUNK_SIZE
#define APP_SEC_ENCR_ALIGN          APP_DATA_CHUNK_SIZE

#define STATE_INIT                  0 //nothing gotten yet
#define STATE_RXING_HEADERS         1 //each is APP_HDR_SIZE bytes
#define STATE_RXING_DATA            2 //each data block is AES_BLOCK_WORDS 32-bit words (for AES reasons)
#define STATE_RXING_SIG_HASH        3 //each is RSA_BYTES bytes
#define STATE_RXING_SIG_PUBKEY      4 //each is RSA_BYTES bytes
#define STATE_DONE                  5 //all is finished and well
#define STATE_BAD                   6 //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

struct AppSecState {

    union { //we save some memory by reusing this space.
        struct {
            struct AesCbcContext cbc;
            struct Sha2state sha;
        };
        struct RsaState rsa;
    };
    uint32_t rsaTmp[RSA_WORDS];
    uint32_t lastHash[SHA2_HASH_WORDS];

    AppSecWriteCbk writeCbk;
    AppSecPubKeyFindCbk pubKeyFindCbk;
    AppSecGetAesKeyCbk aesKeyAccessCbk;

    union {
        union { //make the compiler work to make sure we have enough space
            uint8_t placeholderAppHdr[APP_HDR_SIZE];
            uint8_t placeholderDataChunk[APP_DATA_CHUNK_SIZE];
            uint8_t placeholderSigChunk[APP_SIG_SIZE];
            uint8_t placeholderAesKey[AES_KEY_WORDS * sizeof(uint32_t)];
        };
        uint8_t dataBytes[0]; //we actually use these two for access
        uint32_t dataWords[0];
    };

    uint32_t signedBytesIn;
    uint32_t encryptedBytesIn;
    uint32_t signedBytesOut;
    uint32_t encryptedBytesOut;
    uint32_t numSigs;

    uint16_t haveBytes;       //in dataBytes...
    uint8_t curState;
    uint8_t needSig    :1;
    uint8_t haveSig    :1;
    uint8_t haveEncr   :1;
};

struct AppSecSigHdr {
    uint8_t magic[8];
    uint32_t appDataLen;
    uint32_t numSigs;
};

struct AppSecEncrHdr {
    uint8_t magic[4];
    uint32_t dataLen;
    uint64_t keyID;
    uint32_t IV[AES_BLOCK_WORDS];
};

//init/deinit
struct AppSecState *appSecInit(AppSecWriteCbk writeCbk, AppSecPubKeyFindCbk pubKeyFindCbk, AppSecGetAesKeyCbk aesKeyAccessCbk, bool mandateSigning)
{
    struct AppSecState *state = heapAlloc(sizeof(struct AppSecState));

    if (!state)
        return NULL;

    memset(state, 0, sizeof(struct AppSecState));

    state->writeCbk = writeCbk;
    state->pubKeyFindCbk = pubKeyFindCbk;
    state->aesKeyAccessCbk = aesKeyAccessCbk;
    state->curState = STATE_INIT;
    if (mandateSigning)
        state->needSig = 1;

    return state;
}

void appSecDeinit(struct AppSecState *state)
{
    heapFree(state);
}


//if needed, decrypt and hash incoming data
static AppSecErr appSecBlockRx(struct AppSecState *state)
{
    //if signatures are on, hash it
    if (state->haveSig) {

        //make sure we do not get too much data & account for the data we got
        if (state->haveBytes > state->signedBytesIn)
            return APP_SEC_TOO_MUCH_DATA;
        state->signedBytesIn -= state->haveBytes;

        //make sure we do not produce too much data (discard padding) & make sure we account for it
        if (state->signedBytesOut < state->haveBytes)
            state->haveBytes = state->signedBytesOut;
        state->signedBytesOut -= state->haveBytes;

        //hash the data
        sha2processBytes(&state->sha, state->dataBytes, state->haveBytes);
    }

    //decrypt if encryption is on
    if (state->haveEncr) {

        uint32_t *dataP = state->dataWords;
        uint32_t i, numBlocks = state->haveBytes / APP_DATA_CHUNK_SIZE;

        //we should not be called with partial encr blocks
        if (state->haveBytes % APP_DATA_CHUNK_SIZE)
            return APP_SEC_TOO_LITTLE_DATA;

        //make sure we do not get too much data & account for the data we got
        if (state->haveBytes > state->encryptedBytesIn)
            return APP_SEC_TOO_MUCH_DATA;
        state->encryptedBytesIn -= state->haveBytes;

        //decrypt
        for (i = 0; i < numBlocks; i++, dataP += AES_BLOCK_WORDS)
            aesCbcDecr(&state->cbc, dataP, dataP);

        //make sure we do not produce too much data (discard padding) & make sure we account for it
        if (state->encryptedBytesOut < state->haveBytes)
            state->haveBytes = state->encryptedBytesOut;
        state->encryptedBytesOut -= state->haveBytes;
    }

    return APP_SEC_NO_ERROR;
}

static AppSecErr appSecProcessIncomingHdr(struct AppSecState *state, bool *sendDataToDataHandlerP)
{
    static const char hdrAddEncrKey[] = "EncrKey+";
    static const char hdrDelEncrKey[] = "EncrKey+";
    static const char hdrNanoApp[] = "GoogleNanoApp\x00\xff\xff"; //we check marker is set to 0xFF and version set to 0, as we must as per spec
    static const char hdrEncrHdr[] = "Encr";
    static const char hdrSigHdr[] = "SigndApp";

    //check for signature header
    if (!memcmp(state->dataBytes, hdrSigHdr, sizeof(hdrSigHdr) - 1)) {

        struct AppSecSigHdr *sigHdr = (struct AppSecSigHdr*)state->dataBytes;

        if (state->haveSig)    //we do not allow signing of already-signed data
            return APP_SEC_INVALID_DATA;

        if (state->haveEncr) //we do not allow encryption of signed data, only signing of encrypted data
            return APP_SEC_INVALID_DATA;

        if (!sigHdr->appDataLen || !sigHdr->numSigs) //no data bytes or no sigs?
            return APP_SEC_INVALID_DATA;

        state->signedBytesOut = sigHdr->appDataLen;
        state->signedBytesIn = ((state->signedBytesOut + APP_SEC_SIG_ALIGN - 1) / APP_SEC_SIG_ALIGN) * APP_SEC_SIG_ALIGN;
        state->numSigs = sigHdr->numSigs;
        state->haveSig = 1;
        sha2init(&state->sha);

        return APP_SEC_NO_ERROR;
    }

    //check for encryption header
    if (!memcmp(state->dataBytes, hdrEncrHdr, sizeof(hdrEncrHdr) - 1)) {

        struct AppSecEncrHdr *encrHdr = (struct AppSecEncrHdr*)state->dataBytes;
	uint32_t k[AES_KEY_WORDS];
        AppSecErr ret;

        if (state->haveEncr) //we do not allow encryption of already-encrypted data
            return APP_SEC_INVALID_DATA;

        if (!encrHdr->dataLen || !encrHdr->keyID)
            return APP_SEC_INVALID_DATA;

        ret = state->aesKeyAccessCbk(encrHdr->keyID, k);
        if (ret)
            return ret;

        aesCbcInitForDecr(&state->cbc, k, encrHdr->IV);
        state->encryptedBytesOut = encrHdr->dataLen;
        state->encryptedBytesIn = ((state->encryptedBytesOut + APP_SEC_ENCR_ALIGN - 1) / APP_SEC_ENCR_ALIGN) * APP_SEC_ENCR_ALIGN;
        state->haveEncr = 1;

        return APP_SEC_NO_ERROR;
    }

    //check for valid app or something else that we pass directly to caller
    if (memcmp(state->dataBytes, hdrAddEncrKey, sizeof(hdrAddEncrKey) - 1) && memcmp(state->dataBytes, hdrDelEncrKey, sizeof(hdrDelEncrKey) - 1) && memcmp(state->dataBytes, hdrNanoApp, sizeof(hdrNanoApp) - 1))
        return APP_SEC_HEADER_ERROR;

    //if we are in must-sign mode and no signature was provided, fail
    if (!state->haveSig && state->needSig)
        return APP_SEC_SIG_VERIFY_FAIL;

    //we're now in data-accepting state
    state->curState = STATE_RXING_DATA;

    //send data to caller as is
    *sendDataToDataHandlerP = true;
    return APP_SEC_NO_ERROR;
}

static AppSecErr appSecProcessIncomingData(struct AppSecState *state)
{
    //check for data-ending conditions
    if (state->haveSig && !state->signedBytesIn) {      //we're all done with the signed portion of the data, now come the signatures
        if (state->haveEncr && state->encryptedBytesIn) //somehow we still have more "encrypted" bytes now - this is not valid
            return APP_SEC_INVALID_DATA;
        state->curState = STATE_RXING_SIG_HASH;

        //collect the hash
        memcpy(state->lastHash, sha2finish(&state->sha), SHA2_HASH_SIZE);
    }
    else if (state->haveEncr && !state->encryptedBytesIn) { //we're all done with encrypted bytes
        if (state->haveSig && state->signedBytesIn)           //somehow we still have more "signed" bytes now - this is not valid
            return APP_SEC_INVALID_DATA;
        state->curState = STATE_DONE;
    }

    //pass to caller
    return state->writeCbk(state->dataBytes, state->haveBytes);
}

static AppSecErr appSecProcessIncomingSigData(struct AppSecState *state)
{
    const uint32_t *result;
    uint32_t i;

    //if we're RXing the hash, just stash it away and move on
    if (state->curState == STATE_RXING_SIG_HASH) {
        if (!state->numSigs)
            return APP_SEC_TOO_MUCH_DATA;

        state->numSigs--;
        memcpy(state->rsaTmp, state->dataWords, APP_SIG_SIZE);
        state->curState = STATE_RXING_SIG_PUBKEY;
        return APP_SEC_NO_ERROR;
    }

    //if we just got the last sig, verify it is a known root
    if (!state->numSigs) {
        bool keyFound = false;
        AppSecErr ret;

        ret = state->pubKeyFindCbk(state->dataWords, &keyFound);
        if (ret != APP_SEC_NO_ERROR)
            return ret;
        if (!keyFound)
            return APP_SEC_SIG_ROOT_UNKNOWN;
    }

    //we now have the pubKey. decrypt.
    result = rsaPubOp(&state->rsa, state->rsaTmp, state->dataWords);

    //verify padding: all by first and last word of padding MUST have no zero bytes
    for (i = SHA2_HASH_WORDS + 1; i < RSA_WORDS - 1; i++) {
        if (!(uint8_t)(result[i] >>  0))
            return APP_SEC_SIG_DECODE_FAIL;
        if (!(uint8_t)(result[i] >>  8))
            return APP_SEC_SIG_DECODE_FAIL;
        if (!(uint8_t)(result[i] >> 16))
            return APP_SEC_SIG_DECODE_FAIL;
        if (!(uint8_t)(result[i] >> 24))
            return APP_SEC_SIG_DECODE_FAIL;
    }

    //verify padding: first padding word must have all nonzero bytes except low byte
    if ((result[SHA2_HASH_WORDS] & 0xff) || !(result[SHA2_HASH_WORDS] & 0xff00) || !(result[SHA2_HASH_WORDS] & 0xff0000) || !(result[SHA2_HASH_WORDS] & 0xff000000))
        return APP_SEC_SIG_DECODE_FAIL;

    //verify padding: last padding word must have 0x0002 in top 16 bits and nonzero random bytes in lower bytes
    if ((result[RSA_WORDS - 1] >> 16) != 2)
        return APP_SEC_SIG_DECODE_FAIL;
    if (!(result[RSA_WORDS - 1] & 0xff00) || !(result[RSA_WORDS - 1] & 0xff))
        return APP_SEC_SIG_DECODE_FAIL;

    //check if hashes match
    if (memcmp(state->lastHash, result, SHA2_HASH_SIZE))
        return APP_SEC_SIG_VERIFY_FAIL;

    //hash the provided pubkey if it is not the last
    if (state->numSigs) {
        sha2init(&state->sha);
        sha2processBytes(&state->sha, state->dataBytes, APP_SIG_SIZE);
        memcpy(state->lastHash, sha2finish(&state->sha), SHA2_HASH_SIZE);
        state->curState = STATE_RXING_SIG_HASH;
    }
    else
        state->curState = STATE_DONE;

    return APP_SEC_NO_ERROR;
}

AppSecErr appSecRxData(struct AppSecState *state, const void *dataP, uint32_t len)
{
    const uint8_t *data = (const uint8_t*)dataP;
    AppSecErr ret = APP_SEC_NO_ERROR;
    bool sendToDataHandler = false;

    if (state->curState == STATE_INIT)
        state->curState = STATE_RXING_HEADERS;

    while (len--) {
        state->dataBytes[state->haveBytes++] = *data++;
        switch (state->curState) {

        case STATE_RXING_HEADERS:
            if (state->haveBytes == APP_HDR_SIZE) {

                ret = appSecBlockRx(state);
                if (ret != APP_SEC_NO_ERROR)
                    break;

                ret = appSecProcessIncomingHdr(state, &sendToDataHandler);
                if (ret != APP_SEC_NO_ERROR)
                    break;
                if (!sendToDataHandler) {
                    state->haveBytes = 0;
                    break;
                }
                //fallthrough
            }
            else
                break;

        case STATE_RXING_DATA:
            if (state->haveBytes >= APP_DATA_CHUNK_SIZE) {

                //if data is already processed, do not re-process it
                if (sendToDataHandler)
                    sendToDataHandler = false;
                else {
                    ret = appSecBlockRx(state);
                    if (ret != APP_SEC_NO_ERROR)
                        break;
                }

                ret = appSecProcessIncomingData(state);
                state->haveBytes = 0;
                if (ret != APP_SEC_NO_ERROR)
                    break;
            }
            break;

        case STATE_RXING_SIG_HASH:
        case STATE_RXING_SIG_PUBKEY:

            //no need for calling appSecBlockRx() as sigs are not signed, and encryption cannot be done after signing
            if (state->haveBytes == APP_SIG_SIZE) {
                ret = appSecProcessIncomingSigData(state);
                state->haveBytes = 0;
                if (ret != APP_SEC_NO_ERROR)
                    break;
            }
            break;

        default:
            state->curState = STATE_BAD;
            state->haveBytes = 0;
            return APP_SEC_BAD;
        }
    }

    if (ret != APP_SEC_NO_ERROR)
        state->curState = STATE_BAD;

    return ret;
}

AppSecErr appSecRxDataOver(struct AppSecState *state)
{
    AppSecErr ret;

    //Feed remianing data to data processor, if any
    if (state->haveBytes) {

        //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)
        if (state->curState != STATE_RXING_DATA) {
            state->curState = STATE_BAD;
            return APP_SEC_TOO_LITTLE_DATA;
        }

        //feed the remaining data to the data processor
        ret = appSecProcessIncomingData(state);
        if (ret != APP_SEC_NO_ERROR) {
            state->curState = STATE_BAD;
            return ret;
        }
    }

    //for unsigned/unencrypted case we have no way to judge length, so we assume it is over when we're told it is
    //this is potentially dangerous, but then again so is allowing unsigned uploads in general.
    if (!state->haveSig && !state->haveEncr && state->curState == STATE_RXING_DATA)
        state->curState = STATE_DONE;

    //Check the state and return our verdict
    if(state->curState == STATE_DONE)
        return APP_SEC_NO_ERROR;

    state->curState = STATE_BAD;
    return APP_SEC_TOO_LITTLE_DATA;
}










