Files
otp/src/padding.c
T

93 lines
3.1 KiB
C

#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "main.h"
////////////////////////////////////////////////////////////////////////////////
// MESSAGE PADDING IMPLEMENTATION
// ISO/IEC 9797-1 Method 2 (Padmé Padding)
// with Exponential Bucketing for Traffic Analysis Resistance
////////////////////////////////////////////////////////////////////////////////
// Calculate required chunk size using exponential bucketing
// Starting at 256 bytes, doubling each time
// Provides strong protection against length analysis attacks
size_t calculate_chunk_size(size_t msg_len) {
size_t chunk = 256; // Minimum chunk size: 256 bytes
// Need space for message + 0x80 byte (minimum 1 byte padding)
while (chunk < msg_len + 1) {
chunk *= 2;
}
return chunk;
}
// Apply ISO/IEC 9797-1 Method 2 (Padmé) padding
// Appends 0x80 byte followed by 0x00 bytes to reach chunk boundary
// Returns 0 on success, non-zero on error
int apply_padme_padding(unsigned char* buffer, size_t msg_len, size_t chunk_size) {
if (!buffer) {
return 1; // Error: null pointer
}
if (chunk_size < msg_len + 1) {
return 2; // Error: chunk size too small for message + padding
}
// Apply padding: 0x80 followed by 0x00 bytes
buffer[msg_len] = 0x80;
// Fill remaining bytes with 0x00
if (chunk_size > msg_len + 1) {
memset(buffer + msg_len + 1, 0x00, chunk_size - msg_len - 1);
}
return 0; // Success
}
// Remove ISO/IEC 9797-1 Method 2 (Padmé) padding
// Scans backwards for 0x80 marker, validates padding
// Returns 0 on success, non-zero on error
// Sets msg_len to the actual message length (excluding padding)
int remove_padme_padding(const unsigned char* buffer, size_t chunk_size, size_t* msg_len) {
if (!buffer || !msg_len) {
return 1; // Error: null pointer
}
if (chunk_size == 0) {
return 2; // Error: invalid chunk size
}
// Scan backwards from end to find 0x80 marker
for (int i = chunk_size - 1; i >= 0; i--) {
if (buffer[i] == 0x80) {
// Found the padding marker
*msg_len = i;
return 0; // Success
} else if (buffer[i] != 0x00) {
// Found non-zero, non-0x80 byte - invalid padding
return 3; // Error: invalid padding (corrupted or tampered data)
}
}
// No 0x80 marker found - invalid padding
return 4; // Error: no padding marker found
}
// Helper function to get human-readable chunk size
// Useful for debugging and user feedback
void format_chunk_size(size_t chunk_size, char* buffer, size_t buffer_size) {
if (!buffer || buffer_size == 0) return;
if (chunk_size < 1024) {
snprintf(buffer, buffer_size, "%zu bytes", chunk_size);
} else if (chunk_size < 1024 * 1024) {
snprintf(buffer, buffer_size, "%.1f KB", chunk_size / 1024.0);
} else if (chunk_size < 1024 * 1024 * 1024) {
snprintf(buffer, buffer_size, "%.1f MB", chunk_size / (1024.0 * 1024.0));
} else {
snprintf(buffer, buffer_size, "%.1f GB", chunk_size / (1024.0 * 1024.0 * 1024.0));
}
}