Projects/3BIT/winter-semester/ISA/include/protocol.h
2026-04-14 19:28:46 +02:00

647 lines
22 KiB
C

/*
* ==================================================================================
* IFTP Protocol Header - ICMP File Transfer Protocol specification
*
* ISA Project
* Author: Roman Necas (xnecasr00)
* Date: 13. October 2025
*
* PURPOSE:
* This module defines IFTP (ICMP File Transfer Protocol), a custom application-
* layer protocol for transferring encrypted files through ICMP Echo-Request/Reply
* messages. IFTP provides reliable, ordered delivery with integrity checking.
*
* PROTOCOL OVERVIEW:
* IFTP is layered on top of ICMP and provides:
* - Session management (unique session IDs)
* - Reliable delivery (sequence numbers, ACKs)
* - Fragmentation support (for large files)
* - Integrity checking (CRC32 checksums)
* - Metadata transmission (filename, size, crypto parameters)
*
* PACKET STRUCTURE:
* ┌─────────────────────────────────────────┐
* │ ICMP Header (8 bytes) │
* ├─────────────────────────────────────────┤
* │ IFTP Header (26 bytes) │
* │ - Magic, Session ID │
* │ - Message Type, Flags │
* │ - Sequence Number, Fragment Info │
* │ - Payload Length, CRC32 │
* ├─────────────────────────────────────────┤
* │ IFTP Payload (0-1400 bytes) │
* │ - START: iftp_metadata_t │
* │ - DATA: Encrypted file chunk │
* │ - END: Empty │
* │ - ACK/NACK: Optional error info │
* └─────────────────────────────────────────┘
*
* TRANSFER FLOW:
* 1. Client → Server: START packet (metadata: filename, size, IV, salt)
* 2. Server → Client: ACK
* 3. Client → Server: DATA packet(s) with encrypted file chunks
* 4. Server → Client: ACK for each DATA packet
* 5. Client → Server: END packet
* 6. Server → Client: ACK
*
* ERROR HANDLING:
* - NACK packets sent for errors (bad checksum, wrong sequence, etc.)
* - Client retries on timeout or NACK with exponential backoff
* - Maximum retry attempts enforced (MAX_RETRIES)
*
* MESSAGE TYPES:
* - START (0x01): Initiate transfer with metadata
* - DATA (0x02): Transfer encrypted file chunk
* - END (0x03): Signal completion
* - ACK (0x04): Acknowledge received packet
* - NACK (0x05): Negative acknowledgment (error)
* - HEARTBEAT (0x06): Keep-alive (reserved for future use)
* ==================================================================================
*/
#ifndef PROTOCOL_H
#define PROTOCOL_H
#include "common.h"
#include "crypto.h"
/*
* ==================================================================================
* PROTOCOL CONSTANTS
* ==================================================================================
*/
/*
* IFTP Magic Number (0xDEADBEEF)
*
* This 32-bit value appears at the start of every IFTP header to identify
* packets as belonging to our protocol. It helps:
* - Distinguish IFTP packets from other ICMP traffic
* - Detect corruption (if magic is wrong, packet is invalid)
*
* The value 0xDEADBEEF is commonly used in debugging/networking as it's
* easily recognizable in hex dumps and unlikely to appear by accident.
*/
#define IFTP_MAGIC 0xDEADBEEF
/*
* ==================================================================================
* MESSAGE TYPES
* ==================================================================================
*/
/*
* iftp_msg_type_t - IFTP message type enumeration
*
* Defines all possible message types in the IFTP protocol. Each message type
* has a specific purpose in the file transfer process.
*/
typedef enum {
/*
* START (0x01) - Transfer initiation packet
*
* Sent by client to begin a new file transfer session.
* Payload: iftp_metadata_t containing filename, size, IV, salt
* Response: ACK from server
* Sequence: Must be seq_num = 0
*/
IFTP_START = 0x01,
/*
* DATA (0x02) - File data chunk packet
*
* Sent by client to transmit encrypted file data.
* Payload: Encrypted file chunk (max 1400 bytes)
* Response: ACK from server
* Sequence: Increments for each DATA packet (1, 2, 3, ...)
* Fragmentation: May be fragmented if chunk doesn't fit in one packet
*/
IFTP_DATA = 0x02,
/*
* END (0x03) - Transfer completion packet
*
* Sent by client to signal successful completion of file transfer.
* Payload: Empty (payload_len = 0)
* Response: ACK from server
* Sequence: Final sequence number (after last DATA packet)
*/
IFTP_END = 0x03,
/*
* ACK (0x04) - Acknowledgment packet
*
* Sent by server to acknowledge receipt of START, DATA, or END packet.
* Payload: Empty (payload_len = 0)
* Sequence: Echoes the seq_num from the packet being acknowledged
* Purpose: Confirms successful receipt and processing
*/
IFTP_ACK = 0x04,
/*
* NACK (0x05) - Negative acknowledgment packet
*
* Sent by server to indicate an error occurred.
* Payload: iftp_error_t containing error code and message
* Sequence: Echoes the seq_num from the failed packet
* Causes: Checksum error, sequence mismatch, crypto error, etc.
*/
IFTP_NACK = 0x05,
/*
* HEARTBEAT (0x06) - Keep-alive message
*
* Reserved for future use to detect dead connections.
* Not currently used in the implementation.
*/
IFTP_HEARTBEAT = 0x06
} iftp_msg_type_t;
/*
* ==================================================================================
* PROTOCOL FLAGS
* ==================================================================================
*/
/*
* IFTP Control Flags
*
* 8-bit flag field in IFTP header for optional features. Multiple flags can
* be combined using bitwise OR. Currently defined but not all are used.
*/
/* COMPRESSED flag (0x01) - Payload is compressed
* Reserved for future use. Current implementation does not compress data. */
#define IFTP_FLAG_COMPRESSED 0x01
/* URGENT flag (0x02) - High priority packet
* Reserved for future use. Not currently implemented. */
#define IFTP_FLAG_URGENT 0x02
/* FRAGMENTED flag (0x04) - Packet is part of a fragmented message
* Set when a large encrypted chunk must be split across multiple ICMP packets.
* fragment_current and fragment_total fields indicate fragment position. */
#define IFTP_FLAG_FRAGMENTED 0x04
/* ENCRYPTED flag (0x08) - Payload contains encrypted data
* Set for DATA packets containing AES-encrypted file chunks.
* Not set for START, END, ACK, NACK packets. */
#define IFTP_FLAG_ENCRYPTED 0x08
/*
* ==================================================================================
* IFTP HEADER STRUCTURE
* ==================================================================================
*/
/*
* iftp_header_t - IFTP protocol header (26 bytes fixed)
*
* This structure defines the fixed-size header that appears at the start of
* every IFTP packet. The header is packed to ensure consistent layout across
* platforms and compilers.
*
* MEMORY LAYOUT (26 bytes total):
* Offset | Size | Field
* -------|------|------------------
* 0 | 4 | magic (0xDEADBEEF)
* 4 | 2 | session_id
* 6 | 1 | msg_type
* 7 | 1 | flags
* 8 | 4 | seq_num
* 12 | 4 | fragment_current
* 16 | 4 | fragment_total
* 20 | 2 | payload_len
* 22 | 4 | crc32
*
* PACKING:
* __attribute__((packed)) ensures no padding bytes are inserted between fields.
* This is critical for network protocols where exact byte layout matters.
*
* BYTE ORDER:
* All multi-byte fields use network byte order (big-endian).
* Use htons/htonl for writing, ntohs/ntohl for reading.
*/
typedef struct {
/*
* Magic number (4 bytes) - Protocol identifier
*
* Must always be 0xDEADBEEF. Used to:
* - Identify IFTP packets among other ICMP traffic
* - Detect header corruption
* - Quick rejection of non-IFTP packets
*/
uint32_t magic;
/*
* Session ID (2 bytes) - Unique transfer session identifier
*
* Randomly generated by client at start of transfer.
* Used to:
* - Distinguish between concurrent transfers
* - Detect stale packets from previous sessions
* - Match ACKs to requests
*
* Generated by: generate_secure_session_id() using RAND_bytes()
* Range: 1-65535 (0 is invalid)
*/
uint16_t session_id;
/*
* Message type (1 byte) - Type of IFTP message
*
* One of: START, DATA, END, ACK, NACK, HEARTBEAT
* Determines how payload is interpreted.
*/
uint8_t msg_type;
/*
* Flags (1 byte) - Control flags
*
* Bitwise OR of IFTP_FLAG_* constants.
* Currently used: FRAGMENTED, ENCRYPTED
* Reserved: COMPRESSED, URGENT
*/
uint8_t flags;
/*
* Sequence number (4 bytes) - Packet ordering
*
* Used for:
* - Ordering packets (especially DATA packets)
* - Detecting duplicates
* - Matching ACKs to requests
*
* Sequence:
* - START: seq_num = 0
* - First DATA: seq_num = 1
* - Subsequent DATA: seq_num = 2, 3, 4, ...
* - END: seq_num = (last DATA seq_num + 1)
* - ACK: echoes seq_num of packet being acknowledged
*/
uint32_t seq_num;
/*
* Current fragment number (4 bytes)
*
* For FRAGMENTED packets: 0-based index of this fragment
* For non-fragmented packets: 0
*
* Example: If a 3000-byte encrypted chunk is split into 3 fragments:
* Fragment 0: bytes 0-1399
* Fragment 1: bytes 1400-2799
* Fragment 2: bytes 2800-2999
*/
uint32_t fragment_current;
/*
* Total fragment count (4 bytes)
*
* For FRAGMENTED packets: Total number of fragments in this message
* For non-fragmented packets: 1
*
* Server uses this to know when all fragments have been received.
*/
uint32_t fragment_total;
/*
* Payload length (2 bytes) - Actual bytes in payload
*
* Number of bytes following this header.
* Range: 0-1400 bytes (MAX_PAYLOAD_SIZE)
*
* Examples:
* - START: sizeof(iftp_metadata_t) (~350 bytes)
* - DATA: Encrypted chunk size (variable, max 1400)
* - END: 0 (no payload)
* - ACK: 0 (no payload)
* - NACK: sizeof(iftp_error_t) (~70 bytes)
*/
uint16_t payload_len;
/*
* CRC32 checksum (4 bytes) - Integrity verification
*
* CRC32 checksum of header + payload for corruption detection.
* Calculated over:
* 1. All header fields EXCEPT crc32 field itself (set to 0 during calc)
* 2. Entire payload
*
* Algorithm: CRC-32 (polynomial 0xEDB88320)
* Verification: Recalculate on receipt and compare
* Mismatch: Send NACK with IFTP_ERROR_CHECKSUM_ERROR
*/
uint32_t crc32;
} __attribute__((packed)) iftp_header_t;
/*
* ==================================================================================
* IFTP METADATA STRUCTURE
* ==================================================================================
*/
/*
* iftp_metadata_t - File transfer metadata (START packet payload)
*
* This structure is transmitted in the payload of START packets to provide
* the server with all information needed to receive and decrypt the file.
*
* SIZE: ~350 bytes (varies with filename length)
* TRANSMISSION: Once per transfer, in START packet
* USAGE: Server extracts this to initialize crypto engine and file writer
*/
typedef struct {
/*
* Filename (256 bytes) - Name of file being transferred
*
* Null-terminated string, max 255 chars + null.
* Contains only the basename (no directory path).
*
* Security: Server validates this to prevent:
* - Path traversal attacks (..)
* - Absolute paths (/)
* - Invalid characters
*
* Server may rename if file exists (appends _1, _2, etc.)
*/
char filename[MAX_FILENAME_LEN + 1];
/*
* File size (8 bytes) - Total size of plaintext file
*
* Size in bytes of the original file before encryption.
* Used by:
* - Server to allocate buffer/track progress
* - Client to calculate total packets needed
* - Progress reporting
*
* Note: Encrypted size will be larger due to AES padding (up to 16 bytes)
*/
uint64_t file_size;
/*
* Initialization Vector (16 bytes) - AES-CBC IV
*
* Randomly generated IV for AES-256-CBC encryption.
* Must be unique for each file transfer.
* Generated by: RAND_bytes() on client
* Used by: Server to initialize decryption (crypto_init)
*
* Security: IV does not need to be secret, only unpredictable.
*/
uint8_t iv[AES_IV_SIZE];
/*
* PBKDF2 Salt (32 bytes) - Key derivation salt
*
* Randomly generated salt for PBKDF2 key derivation.
* Ensures each transfer has a unique encryption key.
* Generated by: RAND_bytes() on client
* Used by: Server to derive decryption key from login
*
* Security: Salt does not need to be secret, only unique.
*/
uint8_t salt[PBKDF2_SALT_SIZE];
/*
* Chunk size (4 bytes) - Size of encryption chunks
*
* Currently not used in implementation but reserved for:
* - Configurable chunk sizes
* - Adaptive sizing based on network conditions
* - Future optimizations
*/
uint32_t chunk_size;
/*
* Compression type (1 byte)
*
* Reserved for future use. Currently always 0 (no compression).
* Could indicate compression algorithm if IFTP_FLAG_COMPRESSED is used.
*/
uint8_t compression_type;
/*
* Reserved (7 bytes) - Padding for future extensions
*
* Set to zero. Available for future protocol extensions without
* breaking compatibility. Could be used for:
* - Additional crypto parameters
* - Checksums
* - Feature flags
* - Timestamps
*/
uint8_t reserved[7];
} __attribute__((packed)) iftp_metadata_t;
/*
* ==================================================================================
* ERROR HANDLING
* ==================================================================================
*/
/*
* iftp_error_code_t - Error codes for NACK packets
*
* Specific error codes sent in NACK packets to indicate why a packet failed.
* Helps client understand what went wrong and whether retry might succeed.
*/
typedef enum {
IFTP_ERROR_NONE = 0, /* No error (should not appear in NACK) */
IFTP_ERROR_INVALID_PACKET = 1, /* Malformed packet (bad header, etc.) */
IFTP_ERROR_SEQUENCE_ERROR = 2, /* Wrong sequence number (out of order) */
IFTP_ERROR_CHECKSUM_ERROR = 3, /* CRC32 validation failed (corruption) */
IFTP_ERROR_CRYPTO_ERROR = 4, /* Decryption failed (wrong key, padding) */
IFTP_ERROR_FILE_ERROR = 5, /* File I/O error (disk full, permissions) */
IFTP_ERROR_TIMEOUT = 6, /* Operation timed out */
IFTP_ERROR_SESSION_ERROR = 7 /* Invalid or expired session */
} iftp_error_code_t;
/*
* iftp_error_t - Error information structure (NACK packet payload)
*
* Detailed error information sent in NACK packet payload.
* Helps client diagnose problems and decide on retry strategy.
*/
typedef struct {
/*
* Error code (1 byte) - Type of error that occurred
* One of the iftp_error_code_t values
*/
uint8_t error_code;
/*
* Failed sequence number (4 bytes) - Which packet failed
* Sequence number of the packet that caused this error
*/
uint32_t failed_seq_num;
/*
* Error message (64 bytes) - Human-readable description
* Null-terminated string with additional details about the error
* Example: "CRC mismatch: expected 0x12345678, got 0x87654321"
*/
char error_message[64];
} __attribute__((packed)) iftp_error_t;
/*
* ==================================================================================
* PACKET CREATION AND PARSING
* ==================================================================================
*/
/*
* create_iftp_packet - Construct IFTP packet from header and payload
*
* Low-level function that combines header and payload into a complete packet.
* Calculates and fills in the CRC32 checksum.
*
* @param header: Pointer to filled-in IFTP header
* @param payload: Pointer to payload data (or NULL if no payload)
* @param packet_buffer: Output buffer for complete packet
* @param packet_len: Output parameter for total packet length
* @return: 0 on success, -1 on error
*/
int create_iftp_packet(const iftp_header_t *header, const void *payload,
uint8_t *packet_buffer, size_t *packet_len);
/*
* parse_iftp_packet - Extract header and payload from received packet
*
* Parses a received packet, validates magic/CRC, and extracts
* header and payload into separate structures.
*
* VALIDATION:
* - Checks magic number (0xDEADBEEF)
* - Validates CRC32 checksum
* - Validates payload length
*
* @param packet_buffer: Raw packet data from network
* @param packet_len: Total packet length
* @param header: Output parameter for parsed header
* @param payload: Output buffer for payload data
* @param payload_len: Output parameter for payload length
* @return: 0 on success, -1 on error
*/
int parse_iftp_packet(const uint8_t *packet_buffer, size_t packet_len,
iftp_header_t *header, uint8_t *payload, size_t *payload_len);
/*
* ==================================================================================
* HIGH-LEVEL PACKET CREATION FUNCTIONS
* ==================================================================================
*/
/* Create START packet with metadata */
int create_start_packet(uint16_t session_id, const iftp_metadata_t *metadata,
uint8_t *packet_buffer, size_t *packet_len);
/* Create DATA packet with file chunk */
int create_data_packet(uint16_t session_id, uint32_t seq_num, uint32_t frag_current,
uint32_t frag_total, const void *data, size_t data_len,
uint8_t *packet_buffer, size_t *packet_len);
/* Create END packet (no payload) */
int create_end_packet(uint16_t session_id, uint32_t seq_num,
uint8_t *packet_buffer, size_t *packet_len);
/* Create ACK packet (no payload) */
int create_ack_packet(uint16_t session_id, uint32_t seq_num,
uint8_t *packet_buffer, size_t *packet_len);
/* Create NACK packet with error information */
int create_nack_packet(uint16_t session_id, uint32_t seq_num, iftp_error_code_t error_code,
const char *error_message, uint8_t *packet_buffer, size_t *packet_len);
/* Create HEARTBEAT packet (reserved for future use) */
int create_heartbeat_packet(uint16_t session_id, uint32_t seq_num,
uint8_t *packet_buffer, size_t *packet_len);
/*
* ==================================================================================
* UTILITY FUNCTIONS
* ==================================================================================
*/
/*
* calculate_crc32 - Compute CRC32 checksum
*
* Calculates CRC32 checksum using standard polynomial (0xEDB88320).
* Used for integrity checking of IFTP packets.
*
* ALGORITHM: CRC-32 (used in Ethernet, ZIP, PNG, etc.)
*
* @param data: Data to checksum
* @param len: Length of data in bytes
* @return: 32-bit CRC value
*/
uint32_t calculate_crc32(const void *data, size_t len);
/*
* validate_iftp_header - Validate IFTP header fields
*
* Checks header for validity:
* - Magic number matches IFTP_MAGIC
* - Message type is valid
* - Payload length is within bounds
*
* @param header: Header to validate
* @return: 0 if valid, -1 if invalid
*/
int validate_iftp_header(const iftp_header_t *header);
/*
* iftp_msg_type_to_string - Convert message type to string
*
* Returns human-readable name for message type.
* Useful for logging and debugging.
*
* @param msg_type: Message type enum value
* @return: String representation (e.g., "START", "DATA", "ACK")
*/
const char *iftp_msg_type_to_string(iftp_msg_type_t msg_type);
/*
* iftp_error_to_string - Convert error code to string
*
* Returns human-readable description of error code.
*
* @param error_code: Error code enum value
* @return: String description (e.g., "Checksum error", "Sequence error")
*/
const char *iftp_error_to_string(iftp_error_code_t error_code);
/*
* ==================================================================================
* SESSION MANAGEMENT
* ==================================================================================
*/
/*
* protocol_session_t - Session state tracking
*
* Maintains protocol state for a transfer session.
* Tracks sequence numbers and detects protocol violations.
*/
typedef struct {
uint16_t session_id; /* Session identifier */
uint32_t next_seq_send; /* Next sequence number to send */
uint32_t next_seq_recv; /* Next sequence number expected */
uint32_t last_ack_sent; /* Last ACK sent */
uint32_t last_ack_recv; /* Last ACK received */
time_t last_activity; /* Last activity timestamp (for timeouts) */
} protocol_session_t;
/* Initialize protocol session */
int protocol_session_init(protocol_session_t *session, uint16_t session_id);
/* Update session after sending a packet */
int protocol_session_update_send(protocol_session_t *session, uint32_t seq_num);
/* Update session after receiving a packet */
int protocol_session_update_recv(protocol_session_t *session, uint32_t seq_num);
/* Check if session has timed out */
int protocol_session_check_timeout(const protocol_session_t *session, int timeout_seconds);
#endif /* PROTOCOL_H */