/* * Copyright (C) 2016 Samsung Electronics Co., Ltd. * * This program 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. */ #ifndef _EXYNOS_FMP_H_ #define _EXYNOS_FMP_H_ #include #include #include #include #define FMP_DRV_VERSION "4.0.1" #define FMP_KEY_SIZE_16 16 #define FMP_KEY_SIZE_32 32 #define FMP_IV_SIZE_16 16 #define FMP_CBC_MAX_KEY_SIZE FMP_KEY_SIZE_16 #define FMP_XTS_MAX_KEY_SIZE ((FMP_KEY_SIZE_32) * (2)) #define FMP_MAX_KEY_SIZE FMP_XTS_MAX_KEY_SIZE #define FMP_HOST_TYPE_NAME_LEN 8 #define FMP_BLOCK_TYPE_NAME_LEN 8 #define FMP_SECTOR_SIZE 0x1000 #define FMP_MIN_SECTOR_SIZE 0x200 #define NUM_SECTOR_UNIT ((FMP_SECTOR_SIZE)/(FMP_MIN_SECTOR_SIZE)) #define MAX_AES_XTS_TRANSFER_SIZE 0x1000 #define CMDQ_DISABLED 0 #define MAX_RETRY_COUNT 0x100 #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif enum fmp_crypto_fips_algo_mode { EXYNOS_FMP_BYPASS_MODE = 0, EXYNOS_FMP_ALGO_MODE_AES_CBC = 1, EXYNOS_FMP_ALGO_MODE_AES_XTS = 2, }; enum fmp_crypto_key_size { EXYNOS_FMP_KEY_SIZE_16 = 16, EXYNOS_FMP_KEY_SIZE_32 = 32, }; enum fmp_crypto_enc_mode { EXYNOS_FMP_FILE_ENC = 0, EXYNOS_FMP_ENC_MAX }; struct fmp_crypto_info { /* This field's stongly aligned 'crypto_diskcipher->algo' */ u8 key[FMP_MAX_KEY_SIZE]; u32 key_size; enum fmp_crypto_key_size fmp_key_size; enum fmp_crypto_enc_mode enc_mode; enum fmp_crypto_fips_algo_mode algo_mode; void *ctx; }; struct fmp_data_setting { struct fmp_crypto_info crypt[EXYNOS_FMP_ENC_MAX]; struct fmp_table_setting *table; bool cmdq_enabled; }; struct fips_result { bool overall; bool aes_xts; bool sha256; bool hmac; bool integrity; }; #define EXYNOS_FMP_ALGO_MODE_MASK (0x3) #define EXYNOS_FMP_ALGO_MODE_TEST_OFFSET (0xf) #define EXYNOS_FMP_ALGO_MODE_TEST (1 << EXYNOS_FMP_ALGO_MODE_TEST_OFFSET) struct fmp_test_data { char block_type[FMP_BLOCK_TYPE_NAME_LEN]; struct block_device *bdev; sector_t sector; dev_t devt; uint32_t test_block_offset; /* iv to submitted */ u8 iv[FMP_IV_SIZE_16]; /* diskcipher for test */ struct fmp_crypto_info ci; u64 DataUnitSeqNumber; }; struct exynos_fmp { struct device *dev; struct fmp_test_data *test_data; atomic_t fips_start; struct fips_result result; struct miscdevice miscdev; void *test_vops; int fips_run; u8 dun_swap; int fips_fin; struct buffer_head *bh; }; struct fmp_sg_entry { /* The first four fields correspond to those of ufshcd_sg_entry. */ __le32 des0; __le32 des1; __le32 des2; /* * The algorithm and key length are configured in the high bits of des3, * whose low bits already contain ufshcd_sg_entry::size. */ __le32 des3; /* The IV with all bytes reversed */ __be32 file_iv[4]; /* * The key with all bytes reversed. For XTS, the two halves of the key * are given separately and are byte-reversed separately. */ __be32 file_enckey[8]; __be32 file_twkey[8]; /* Not used */ __be32 disk_iv[4]; __le32 reserved[4]; }; #define ACCESS_CONTROL_ABORT 0x14 #ifndef SMC_CMD_FMP_SECURITY /* For FMP/SMU Ctrl */ #define SMC_CMD_FMP_SECURITY (0xC2001810) #define SMC_CMD_SMU (0xC2001850) #define SMC_CMD_FMP_SMU_RESUME (0xC2001860) #define SMC_CMD_FMP_SMU_DUMP (0xC2001870) #define SMC_CMD_UFS_LOG (0xC2001880) #endif /* Keyslot Selftest */ #define FMP_KW_SECUREKEY 0x8000 #define FMP_KW_SECUREKEY_OFFSET 0x80 #define EXYNOS_FMP_FIPS_KEYSLOT 0xF #define AES_256_XTS_KEY_SIZE 64 #define AES_256_XTS_TWK_OFFSET 8 #define FMP_KW_KEYVALID 0xA00C #define FMP_EMBEDDED 0 #define DEFAULT_KWMODE (1 | (1 << 4)) struct exynos_fmp *get_fmp(void); int get_fmp_fips_state(void); void exynos_fmp_fips_test(struct exynos_fmp *fmp); #ifndef CONFIG_KEYS_IN_PRDT unsigned long exynos_fmp_set_kw_mode(uint64_t kw_mode); unsigned long exynos_fmp_get_kw_mode(dma_addr_t kw_mode_addr); #endif /* CONFIG_KEYS_IN_PRDT */ #endif /* _EXYNOS_FMP_H_ */