/* Motenpoche 
 *
 * (c) 2023 Daniele Lacamera <root@danielinux.net>
 *
 *
 * Motenpoche is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Motenpoche is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
 *
 */
#ifndef CRYPTOENGINE_H
#define CRYPTOENGINE_H
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/sha512.h>
#define CRYPTO_KEY_SIZE 32
#define PK_SIGNATURE_SIZE 64
#define SEED_LEN 24

#define SALT_LEN 64

/* Use lower half of flash */
#define VAULT_FLASH_OFFSET 0x00000000
#define VAULT_FLASH_SIZE   (512 * 1024)

#define VAULT_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
#define SHA_PAYLOAD_SIZE (sizeof(struct vault_header) - (PK_SIGNATURE_SIZE + VAULT_DIGEST_SIZE))


#define VAULT_MAGIC 0x5AFECA5E
int cryptoengine_verify_passphrase(const char *passphrase, int *res);
int cryptoengine_check_vault(void);
struct __attribute__((packed)) vault_header {
    uint32_t magic; /* 0x5afeca5e */
    uint32_t size; /* Including magic and size */
    uint32_t id[2];
    uint8_t  auth_pubkey[2 * CRYPTO_KEY_SIZE]; /* pc-signP, used to authenticate header on rekey/changes */
    uint8_t  host_salt[SALT_LEN]; /* current PBKDF2 salt. vS = PBKDF2(passphrase, SALT) */
    uint8_t  host_seed[SEED_LEN]; /* current 'seed' used for IV */
    uint8_t  digest[VAULT_DIGEST_SIZE]; /* SHA digest of this header */
    uint8_t  signature[PK_SIGNATURE_SIZE]; /* Signature of the digest */
};


struct __attribute__((packed)) vault_status {
    uint32_t id[2];
    uint8_t salt[SALT_LEN];
    uint8_t seed[SEED_LEN];
    uint16_t state;
    uint16_t services_active;
    uint16_t first_avail;
};

struct __attribute__((packed)) cdc_packet_hdr
{
    uint32_t magic; /* 0x5AFECA5E */
    uint16_t cmd;
    uint16_t len;
};

#define CDC_STATUS    0x0000
#define CDC_TOFU_INIT 0x0001
#define CDC_CHALLENGE 0x0002
#define CDC_REKEY     0x0003
#define CDC_ADDSERV   0x0004
#define CDC_DELSERV   0x0005

#define CDC_OK        0x0100
#define CDC_FAIL      0x0800

#define MAX_CDC_CMD   512


#define SETTINGS_FLASH_OFFSET       0x300
#define SVC_FLASH_OFFSET            0x400

#define SVC_NAME_SIZE_LIMIT 16
#define SVC_USER_NAME_MAX 32
#define SVC_PASSWORD_MAX  64

#define SVC_FLAG_UNUSED  0xFFFFFFFF
#define SVC_FLAG_ERASED  0xDEADC0DE
#define SVC_FLAG_ACTIVE  0xAAAAAAAA


struct __attribute__((packed)) vault_service
{
    uint32_t flags;
    uint32_t reserved;
    char name[24];
    char user[32];
    char pass[64];
    uint8_t dig[64];
    uint8_t sig[64];
};

#define SVC_ENC_SIZE (256 - 8)
#define SVC_ENC_OFF  (8)
#define SVC_SIZE (256)

int cryptoengine_hdr_sha_check(const struct vault_header *vh);
int cryptoengine_svc_sha_check(const struct vault_service *vs);
int cryptoengine_svc_sig_verify(const struct vault_service *vs, int *res);
int cryptoengine_import_service(struct vault_service *vs, uint32_t idx);

int cryptoengine_service_count(uint16_t *n_srv, uint16_t *first_avail);
int cryptoengine_fill_vault_status(struct vault_status *vst);
int flash_decrypt_read_svc(struct vault_service *out, uint32_t addr);

#endif
