/*
 * (c) Copyright 2020 Samsung Research America, Inc.
 *                  All rights reserved
 *
 *  MPS Lab
 *
 * File: cipher.h
 * Author: jianwei.qian@samsung.com
 * Update Date: Aug 12, 2020
 *
 */
/*
 * Copyright (C) 2020 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Mobile Communication Division,
 * Digital Media & Communications Business, Samsung Electronics Co., Ltd.
 *
 * This software and its documentation are confidential and proprietary
 * information of Samsung Electronics Co., Ltd.  No part of the software and
 * documents may be copied, reproduced, transmitted, translated, or reduced to
 * any electronic medium or machine-readable form without the prior written
 * consent of Samsung Electronics.
 *
 * Samsung Electronics makes no representations with respect to the contents,
 * and assumes no responsibility for any errors that might appear in the
 * software and documents. This publication and the contents hereof are subject
 * to change without notice.
 */

#ifndef PEBBLE_CIPHER_H
#define PEBBLE_CIPHER_H

#include <stdint.h>
#include "pebble_core.h"

#define AES_GCM_TAG_SIZE       16
#define AES128_KEY_SIZE        16
#define AES256_KEY_SIZE        32

enum tz_error_n {
    UNSUPPORTED_CMD             = -100,

    INTEGRITY_CHECK_FAILURE_7   = -97,
    INTEGRITY_CHECK_FAILURE_6,
    INTEGRITY_CHECK_FAILURE_5,
    INTEGRITY_CHECK_FAILURE_4,
    INTEGRITY_CHECK_FAILURE_3,
    INTEGRITY_CHECK_FAILURE_2,
    INTEGRITY_CHECK_FAILURE_1,
    INTEGRITY_CHECK_FAILURE,

    INVALID_ARGUMENT,
    CRYPTO_FAILED,
    WRONG_TAG,
    TZ_RNG_FAILED,
    TZ_KDF_FAILED,
    NOT_INITIALIZED,
    BUFFER_TOO_SMALL,
    FAILED,
    SUCCESS                     = 0
};

/**
 * RSA encryption with different padding types. Implemented based on SCrypto
 * @return 0 for success
 */
uint32_t pebble_rsa_encrypt(
    uint8_t *keyMod,
    uint32_t keyModLen,
    uint8_t *keyPubExp,
    uint32_t keyPubExpLen,
    uint8_t * data,
    uint32_t dataLen,
    uint8_t * out,
    uint32_t * pOutLen,
	uint32_t padding // Padding types for encryption. Please check openssl/rsa.h
);

/**
 * RSA decryption with different padding types. Implemented based on SCrypto
 * @return 0 for success
 */
uint32_t pebble_rsa_decrypt(
    uint8_t *keyMod,
    uint32_t keyModLen,
    uint8_t *keyPubExp,
    uint32_t keyPubExpLen,
    uint8_t *keyPriExp,
    uint32_t keyPriExpLen,
    uint8_t * in,
    uint32_t inLen,
    uint8_t * out,
    uint32_t * pOutLen,
	uint32_t padding // Padding types for encryption. Please check openssl/rsa.h
);

/**
 * @brief Implemented based on SCrypto
 * @param key         - encryption key (derived from REK)
 * @param key_size    - size of encryption key (in bytes)
 * @param iv          - initial vector for GCM encryption mode
 * @param iv_size     - size of initial vector (in bytes)
 * @param aad         - aad
 * @param aad_size    - aad length (in bytes)
 * @param data         - plaintext data
 * @param input_size   - plaintext data size (in bytes)
 * @param out         - ciphertext, whose length equals input_size
 * @param tag         - tag, whose length is AES_GCM_TAG_SIZE = 16
 * @return 0 for success
 */
uint32_t pebble_aes_gcm_encrypt (const uint8_t* key, uint32_t key_size,
        const uint8_t* iv,  uint32_t iv_size,
		const uint8_t* aad, uint32_t aad_size,
		const uint8_t* data, uint32_t input_size,
		uint8_t* out, uint8_t* tag);


/**
 * @brief Implemented based on SCrypto
 * @param key         - decryption key (derived from REK)
 * @param key_size    - size of decryption key (in bytes)
 * @param iv          - initial vector for GCM decryption mode
 * @param iv_size     - size of initial vector (in bytes)
 * @param aad         - aad
 * @param aad_size    - aad length (in bytes)
 * @param data        - ciphertext data
 * @param input_size  - ciphertext data size (in bytes)
 * @param tag         - auth tag
 * @param tag_size    - auth tag size
 * @param out         - plaintext, whose length equals input_size
 * @return 0 for success
 */
uint32_t pebble_aes_gcm_decrypt (const uint8_t* key, uint32_t key_size,
        const uint8_t* iv,  uint32_t iv_size,
		const uint8_t* aad, uint32_t aad_size,
		const uint8_t* data, uint32_t input_size, // cipher text
		const uint8_t* tag, uint32_t tag_size,
		uint8_t* out);//plaintext

/**
 * Input: data
 * Output: checksum
 * Return: 1 on success, 0 on failure
 */
int gen_checksum(unsigned char *data, size_t len, unsigned char checksum[CHECKSUM_LEN]);


/**
 * Input: data and checksum
 * Return: 1 on valid checksum, 0 on invalid checksum, -1 on unable to verify (gen_checksum failed)
 */
int verify_checksum(unsigned char *data, size_t len, unsigned char checksums[CHECKSUM_LEN]);

#endif
