fde.h (10170B)
1 /* FDE - Full Disk Encryption for LuajitOS 2 * 3 * Provides transparent disk encryption using cascaded ciphers: 4 * AES-256-GCM (inner) + XChaCha20-Poly1305 (outer) 5 * 6 * Features: 7 * - Cascaded encryption for defense in depth 8 * - Per-sector encryption with unique nonces 9 * - Argon2id key derivation (memory-hard) 10 * - Integrity verification via auth tags 11 * - Random-access read/write support 12 */ 13 14 #ifndef FDE_H 15 #define FDE_H 16 17 #include <stdint.h> 18 #include <stddef.h> 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /* ============================================================================ 25 * Constants 26 * ========================================================================= */ 27 28 #define FDE_MAGIC "LJOS_FDE" 29 #define FDE_MAGIC_SIZE 8 30 #define FDE_VERSION 1 31 32 #define FDE_SECTOR_SIZE 512 33 #define FDE_KEY_SIZE 32 /* 256 bits per cipher */ 34 #define FDE_MASTER_KEY_SIZE 64 /* Two 256-bit keys */ 35 #define FDE_SALT_SIZE 32 36 #define FDE_NONCE_AES_SIZE 12 /* AES-GCM nonce */ 37 #define FDE_NONCE_XCHACHA_SIZE 24 /* XChaCha20 nonce */ 38 #define FDE_TAG_SIZE 16 /* Auth tag size per cipher */ 39 #define FDE_TAGS_PER_SECTOR 32 /* 16 + 16 bytes for both tags */ 40 41 /* Header is stored in sector 0 */ 42 #define FDE_HEADER_SECTOR 0 43 44 /* KDF parameters */ 45 #define FDE_KDF_MEMORY 4096 /* 4 MB for Argon2id (reduced for bare metal) */ 46 #define FDE_KDF_TIME 3 /* 3 iterations */ 47 #define FDE_KDF_PARALLELISM 1 /* Single-threaded for bare metal */ 48 #define FDE_KDF_ITERATIONS_DEFAULT 100000 /* For PBKDF2 fallback */ 49 50 /* Cipher modes */ 51 #define FDE_CIPHER_NONE 0 /* No encryption (plaintext) */ 52 #define FDE_CIPHER_AES_GCM 1 /* AES-256-GCM only */ 53 #define FDE_CIPHER_XCHACHA 2 /* XChaCha20-Poly1305 only */ 54 #define FDE_CIPHER_CASCADE 3 /* AES-256-GCM + XChaCha20-Poly1305 */ 55 56 /* Error codes */ 57 #define FDE_OK 0 58 #define FDE_ERR_INVALID_PARAM -1 59 #define FDE_ERR_NO_MEMORY -2 60 #define FDE_ERR_IO -3 61 #define FDE_ERR_CRYPTO -4 62 #define FDE_ERR_BAD_PASSWORD -5 63 #define FDE_ERR_CORRUPT -6 64 #define FDE_ERR_NOT_FORMATTED -7 65 #define FDE_ERR_ALREADY_OPEN -8 66 #define FDE_ERR_NOT_OPEN -9 67 #define FDE_ERR_AUTH_FAILED -10 68 69 /* ============================================================================ 70 * Structures 71 * ========================================================================= */ 72 73 /* Disk header (stored in sector 0) - 512 bytes */ 74 /* NOTE: header_hash MUST be at the end so sha256 can hash everything before it */ 75 typedef struct __attribute__((packed)) { 76 char magic[FDE_MAGIC_SIZE]; /* "LJOS_FDE" */ 77 uint32_t version; /* Header version */ 78 uint32_t cipher_mode; /* Cipher mode (0-3) */ 79 uint32_t kdf_iterations; /* KDF iteration count */ 80 uint32_t total_sectors; /* Total sectors on disk */ 81 uint32_t data_start_sector; /* First data sector */ 82 uint32_t tag_start_sector; /* First tag sector */ 83 uint8_t salt[FDE_SALT_SIZE]; /* KDF salt */ 84 uint8_t encrypted_master_key[FDE_MASTER_KEY_SIZE + FDE_TAG_SIZE * 2]; 85 /* Encrypted master key + tags */ 86 uint8_t reserved[512 - 8 - 4*6 - 32 - (64+32) - 32]; /* Padding to 512 */ 87 uint8_t header_hash[32]; /* SHA-256 of header (excluding this field) - MUST BE LAST */ 88 } fde_header_t; 89 90 /* FDE context (runtime state) */ 91 typedef struct { 92 uint8_t bus; /* ATA bus */ 93 uint8_t drive; /* ATA drive */ 94 uint8_t is_open; /* Is disk open? */ 95 uint8_t cipher_mode; /* Active cipher mode */ 96 uint32_t partition_start; /* Start sector of partition (0 if whole disk) */ 97 uint32_t partition_size; /* Size of partition in sectors */ 98 uint32_t total_sectors; /* Total usable data sectors */ 99 uint32_t data_start_sector; /* First data sector (relative to partition) */ 100 uint32_t tag_start_sector; /* First tag sector (relative to partition) */ 101 uint8_t aes_key[FDE_KEY_SIZE]; /* AES-256 key */ 102 uint8_t xchacha_key[FDE_KEY_SIZE]; /* XChaCha20 key */ 103 } fde_context_t; 104 105 /* Sector tags (stored in tag area) */ 106 typedef struct __attribute__((packed)) { 107 uint8_t aes_tag[FDE_TAG_SIZE]; /* AES-GCM auth tag */ 108 uint8_t xchacha_tag[FDE_TAG_SIZE]; /* XChaCha20 auth tag */ 109 } fde_sector_tags_t; 110 111 /* ============================================================================ 112 * API Functions 113 * ========================================================================= */ 114 115 /** 116 * Format a disk/partition with FDE 117 * 118 * @param bus ATA bus (0 = primary, 1 = secondary) 119 * @param drive ATA drive (0 = master, 1 = slave) 120 * @param password Encryption password 121 * @param pass_len Password length 122 * @param cipher Cipher mode (FDE_CIPHER_*) 123 * @return FDE_OK on success, error code on failure 124 */ 125 int fde_format(uint8_t bus, uint8_t drive, 126 const char *password, size_t pass_len, 127 uint8_t cipher); 128 129 /** 130 * Format a partition with FDE 131 * 132 * @param bus ATA bus (0 = primary, 1 = secondary) 133 * @param drive ATA drive (0 = master, 1 = slave) 134 * @param part_start Partition start sector 135 * @param part_size Partition size in sectors 136 * @param password Encryption password 137 * @param pass_len Password length 138 * @param cipher Cipher mode (FDE_CIPHER_*) 139 * @return FDE_OK on success, error code on failure 140 */ 141 int fde_format_partition(uint8_t bus, uint8_t drive, 142 uint32_t part_start, uint32_t part_size, 143 const char *password, size_t pass_len, 144 uint8_t cipher); 145 146 /** 147 * Open an encrypted disk 148 * 149 * @param ctx Context to initialize 150 * @param bus ATA bus 151 * @param drive ATA drive 152 * @param password Encryption password 153 * @param pass_len Password length 154 * @return FDE_OK on success, error code on failure 155 */ 156 int fde_open(fde_context_t *ctx, uint8_t bus, uint8_t drive, 157 const char *password, size_t pass_len); 158 159 /** 160 * Open an encrypted partition 161 * 162 * @param ctx Context to initialize 163 * @param bus ATA bus 164 * @param drive ATA drive 165 * @param part_start Partition start sector 166 * @param password Encryption password 167 * @param pass_len Password length 168 * @return FDE_OK on success, error code on failure 169 */ 170 int fde_open_partition(fde_context_t *ctx, uint8_t bus, uint8_t drive, 171 uint32_t part_start, 172 const char *password, size_t pass_len); 173 174 /** 175 * Close an encrypted disk 176 * 177 * @param ctx Context to close 178 * @return FDE_OK on success, error code on failure 179 */ 180 int fde_close(fde_context_t *ctx); 181 182 /** 183 * Read a decrypted sector 184 * 185 * @param ctx Open FDE context 186 * @param sector Logical sector number (0-based, in data area) 187 * @param buffer Output buffer (512 bytes) 188 * @return FDE_OK on success, error code on failure 189 */ 190 int fde_read_sector(fde_context_t *ctx, uint32_t sector, void *buffer); 191 192 /** 193 * Write and encrypt a sector 194 * 195 * @param ctx Open FDE context 196 * @param sector Logical sector number (0-based, in data area) 197 * @param buffer Input buffer (512 bytes) 198 * @return FDE_OK on success, error code on failure 199 */ 200 int fde_write_sector(fde_context_t *ctx, uint32_t sector, const void *buffer); 201 202 /** 203 * Read multiple decrypted sectors 204 * 205 * @param ctx Open FDE context 206 * @param start Starting logical sector 207 * @param count Number of sectors to read 208 * @param buffer Output buffer (count * 512 bytes) 209 * @return FDE_OK on success, error code on failure 210 */ 211 int fde_read_sectors(fde_context_t *ctx, uint32_t start, uint32_t count, void *buffer); 212 213 /** 214 * Write and encrypt multiple sectors 215 * 216 * @param ctx Open FDE context 217 * @param start Starting logical sector 218 * @param count Number of sectors to write 219 * @param buffer Input buffer (count * 512 bytes) 220 * @return FDE_OK on success, error code on failure 221 */ 222 int fde_write_sectors(fde_context_t *ctx, uint32_t start, uint32_t count, const void *buffer); 223 224 /** 225 * Get information about an encrypted disk 226 * 227 * @param bus ATA bus 228 * @param drive ATA drive 229 * @param cipher Output: cipher mode 230 * @param sectors Output: total data sectors 231 * @return FDE_OK if disk is FDE formatted, error otherwise 232 */ 233 int fde_get_info(uint8_t bus, uint8_t drive, uint8_t *cipher, uint32_t *sectors); 234 235 /** 236 * Check if a disk is FDE formatted 237 * 238 * @param bus ATA bus 239 * @param drive ATA drive 240 * @return 1 if FDE formatted, 0 otherwise 241 */ 242 int fde_is_formatted(uint8_t bus, uint8_t drive); 243 244 /** 245 * Change the password on an encrypted disk 246 * 247 * @param ctx Open FDE context 248 * @param old_password Current password 249 * @param old_len Current password length 250 * @param new_password New password 251 * @param new_len New password length 252 * @return FDE_OK on success, error code on failure 253 */ 254 int fde_change_password(fde_context_t *ctx, 255 const char *old_password, size_t old_len, 256 const char *new_password, size_t new_len); 257 258 /** 259 * Get error string for error code 260 * 261 * @param error Error code 262 * @return Human-readable error string 263 */ 264 const char *fde_error_string(int error); 265 266 /** 267 * Get cipher mode name 268 * 269 * @param cipher Cipher mode 270 * @return Cipher name string 271 */ 272 const char *fde_cipher_name(uint8_t cipher); 273 274 /* ============================================================================ 275 * Lua Bindings 276 * ========================================================================= */ 277 278 struct lua_State; 279 int luaopen_fde(struct lua_State *L); 280 281 #ifdef __cplusplus 282 } 283 #endif 284 285 #endif /* FDE_H */