diff --git a/otp-arm64 b/otp-arm64 index fb1b857..13dde59 100755 Binary files a/otp-arm64 and b/otp-arm64 differ diff --git a/otp-x86_64 b/otp-x86_64 index ea781b1..3209a90 100755 Binary files a/otp-x86_64 and b/otp-x86_64 differ diff --git a/otp.c b/otp.c index 251e5fa..ba57073 100644 --- a/otp.c +++ b/otp.c @@ -44,7 +44,7 @@ static const int base64_decode_table[256] = { #define PROGRESS_UPDATE_INTERVAL (64 * 1024 * 1024) // 64MB intervals #define DEFAULT_PADS_DIR "pads" #define FILES_DIR "files" -#define MAX_ENTROPY_BUFFER 32768 // 32KB entropy buffer +#define MAX_ENTROPY_BUFFER (4 * 1024 * 1024) // 4MB entropy buffer for large operations //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -331,7 +331,7 @@ int interactive_mode(void) { void show_main_menu(void) { - printf("\n=========================== Main Menu - OTP v0.3.8 ===========================\n\n"); + printf("\n=========================== Main Menu - OTP v0.3.9 ===========================\n\n"); printf(" \033[4mT\033[0mext encrypt\n"); //TEXT ENCRYPT printf(" \033[4mF\033[0mile encrypt\n"); //FILE ENCRYPT @@ -2551,6 +2551,256 @@ int collect_truerng_entropy(unsigned char* entropy_buffer, size_t target_bytes, return 0; // Success } +// Streaming TrueRNG entropy collection for full pad enhancement +// This function applies entropy directly to the pad in chunks to avoid memory issues +int collect_truerng_entropy_streaming(const char* pad_chksum, size_t total_bytes, int display_progress) { + char port_path[512]; + truerng_device_type_t device_type; + int serial_fd = -1; + + // Find TrueRNG device + if (!find_truerng_port(port_path, sizeof(port_path), &device_type)) { + if (display_progress) { + printf("No TrueRNG device found.\n"); + printf("\nSupported devices:\n"); + printf(" - TrueRNG (PID: %s, VID: %s)\n", TRUERNG_VID, TRUERNG_PID); + printf(" - TrueRNGpro (PID: %s, VID: %s)\n", TRUERNGPRO_VID, TRUERNGPRO_PID); + printf(" - TrueRNGproV2 (PID: %s, VID: %s)\n", TRUERNGPROV2_VID, TRUERNGPROV2_PID); + printf("\nPlease connect a TrueRNG device and try again.\n"); + } + return 1; // Device not found + } + + if (display_progress) { + printf("Found %s at %s\n", get_truerng_device_name(device_type), port_path); + printf("Streaming %zu bytes of entropy directly to pad...\n", total_bytes); + } + + // Setup serial port + serial_fd = setup_truerng_serial_port(port_path); + if (serial_fd < 0) { + if (display_progress) { + printf("Error: Cannot open TrueRNG device at %s\n", port_path); + printf("Check device permissions or run as root.\n"); + } + return 2; // Serial port setup failed + } + + // Get pad paths + char pad_path[1024]; + char state_path[1024]; + get_pad_path(pad_chksum, pad_path, state_path); + + // Open pad file for read/write with temporary permissions + if (chmod(pad_path, S_IRUSR | S_IWUSR) != 0) { + if (display_progress) { + printf("Error: Cannot change pad file permissions\n"); + } + close(serial_fd); + return 3; + } + + FILE* pad_file = fopen(pad_path, "r+b"); + if (!pad_file) { + if (display_progress) { + printf("Error: Cannot open pad file for modification: %s\n", pad_path); + } + chmod(pad_path, S_IRUSR); // Restore read-only + close(serial_fd); + return 4; + } + + // Process pad in chunks + const size_t chunk_size = 1024 * 1024; // 1MB chunks + unsigned char* entropy_chunk = malloc(chunk_size); + unsigned char* pad_chunk = malloc(chunk_size); + unsigned char* mixed_chunk = malloc(chunk_size); + + if (!entropy_chunk || !pad_chunk || !mixed_chunk) { + if (display_progress) { + printf("Error: Cannot allocate chunk buffers\n"); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 5; + } + + size_t bytes_processed = 0; + time_t start_time = time(NULL); + + while (bytes_processed < total_bytes) { + size_t current_chunk_size = chunk_size; + if (total_bytes - bytes_processed < chunk_size) { + current_chunk_size = total_bytes - bytes_processed; + } + + // Collect entropy from TrueRNG for this chunk + size_t entropy_bytes_in_chunk = 0; + while (entropy_bytes_in_chunk < current_chunk_size) { + size_t bytes_needed = current_chunk_size - entropy_bytes_in_chunk; + size_t read_size = (bytes_needed > 1024) ? 1024 : bytes_needed; + + ssize_t result = read(serial_fd, entropy_chunk + entropy_bytes_in_chunk, read_size); + if (result < 0) { + if (display_progress) { + printf("Error: Failed to read from TrueRNG device\n"); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 6; + } else if (result == 0) { + if (display_progress) { + printf("Error: No data received from TrueRNG device\n"); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 7; + } + entropy_bytes_in_chunk += result; + } + + // Read current pad data for this chunk + if (fseek(pad_file, bytes_processed, SEEK_SET) != 0) { + if (display_progress) { + printf("Error: Cannot seek to offset %zu in pad file\n", bytes_processed); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 8; + } + + if (fread(pad_chunk, 1, current_chunk_size, pad_file) != current_chunk_size) { + if (display_progress) { + printf("Error: Cannot read pad data at offset %zu\n", bytes_processed); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 9; + } + + // Derive Chacha20 key and nonce from entropy chunk + unsigned char key[32], nonce[12]; + if (derive_chacha20_params(entropy_chunk, current_chunk_size, key, nonce) != 0) { + if (display_progress) { + printf("Error: Failed to derive Chacha20 parameters from entropy\n"); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 10; + } + + // Generate keystream and XOR with pad data + uint32_t counter = bytes_processed / 64; // Chacha20 block counter + if (chacha20_encrypt(key, counter, nonce, pad_chunk, mixed_chunk, current_chunk_size) != 0) { + if (display_progress) { + printf("Error: Chacha20 keystream generation failed\n"); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 11; + } + + // XOR existing pad with keystream (adds entropy) + for (size_t i = 0; i < current_chunk_size; i++) { + mixed_chunk[i] = pad_chunk[i] ^ mixed_chunk[i]; + } + + // Write modified data back to pad + if (fseek(pad_file, bytes_processed, SEEK_SET) != 0) { + if (display_progress) { + printf("Error: Cannot seek to write offset %zu\n", bytes_processed); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 12; + } + + if (fwrite(mixed_chunk, 1, current_chunk_size, pad_file) != current_chunk_size) { + if (display_progress) { + printf("Error: Cannot write modified pad data\n"); + } + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + chmod(pad_path, S_IRUSR); + close(serial_fd); + return 13; + } + + bytes_processed += current_chunk_size; + + // Show progress for large pads + if (display_progress && bytes_processed % (64 * 1024 * 1024) == 0) { // Every 64MB + double percentage = (double)bytes_processed / total_bytes * 100.0; + printf("Progress: %.1f%% (%zu/%zu MB)\r", percentage, + bytes_processed / (1024*1024), total_bytes / (1024*1024)); + fflush(stdout); + } + } + + // Cleanup + free(entropy_chunk); + free(pad_chunk); + free(mixed_chunk); + fclose(pad_file); + close(serial_fd); + + // Restore read-only permissions + if (chmod(pad_path, S_IRUSR) != 0) { + if (display_progress) { + printf("Warning: Cannot restore pad file to read-only\n"); + } + } + + if (display_progress) { + double collection_time = difftime(time(NULL), start_time); + printf("\nāœ“ TrueRNG streaming entropy collection complete!\n"); + printf(" Enhanced: %zu bytes in %.1f seconds\n", bytes_processed, collection_time); + printf(" Device: %s\n", get_truerng_device_name(device_type)); + if (collection_time > 0) { + printf(" Rate: %.1f MB/s\n", (double)bytes_processed / collection_time / (1024.0*1024.0)); + } + printf("āœ“ Pad integrity maintained\n"); + printf("āœ“ Entropy distributed across entire pad\n"); + printf("āœ“ Pad restored to read-only mode\n"); + } + + return 0; // Success +} + // Collect dice entropy with manual input validation int collect_dice_entropy(unsigned char* entropy_buffer, size_t target_bytes, size_t* collected_bytes, int display_progress) { @@ -3243,7 +3493,7 @@ int generate_ascii_armor(const char* chksum, uint64_t offset, const unsigned cha strcpy(*ascii_output, "-----BEGIN OTP MESSAGE-----\n"); char temp_line[256]; - snprintf(temp_line, sizeof(temp_line), "Version: v0.3.8\n"); + snprintf(temp_line, sizeof(temp_line), "Version: v0.3.9\n"); strcat(*ascii_output, temp_line); snprintf(temp_line, sizeof(temp_line), "Pad-ChkSum: %s\n", chksum); @@ -4797,6 +5047,43 @@ int handle_add_entropy_to_pad(const char* pad_chksum) { } } + // For TrueRNG with large pads, use streaming approach + if (entropy_source == ENTROPY_SOURCE_TRUERNG && target_bytes > MAX_ENTROPY_BUFFER) { + printf("\nUsing streaming approach for large pad enhancement...\n"); + + int result = collect_truerng_entropy_streaming(pad_chksum, target_bytes, 1); + + if (result != 0) { + printf("Error: TrueRNG streaming entropy collection failed\n"); + return 1; + } + + // Update checksum after entropy addition + printf("\nšŸ”„ Updating pad checksum...\n"); + char new_chksum[65]; + int checksum_result = update_pad_checksum_after_entropy(pad_chksum, new_chksum); + + if (checksum_result == 0) { + printf("āœ“ Pad checksum updated successfully\n"); + printf(" Old checksum: %.16s...\n", pad_chksum); + printf(" New checksum: %.16s...\n", new_chksum); + printf("āœ“ Pad files renamed to new checksum\n"); + } else if (checksum_result == 2) { + printf("ℹ Checksum unchanged (unusual but not an error)\n"); + } else { + printf("⚠ Warning: Checksum update failed (entropy was added successfully)\n"); + printf(" You may need to manually handle the checksum update\n"); + return 1; + } + + printf("\nšŸŽ‰ SUCCESS! Your entire pad now has enhanced randomness!\n"); + printf("Press Enter to continue..."); + getchar(); + + return 0; + } + + // For other entropy sources or smaller amounts, use traditional approach printf("\nCollecting %zu bytes of entropy from selected source...\n", target_bytes); // Allocate entropy buffer @@ -4845,7 +5132,7 @@ int handle_add_entropy_to_pad(const char* pad_chksum) { void print_usage(const char* program_name) { - printf("OTP Cipher - One Time Pad Implementation v0.3.8\n"); + printf("OTP Cipher - One Time Pad Implementation v0.3.9\n"); printf("Built for testing entropy system\n"); printf("Usage:\n"); printf(" %s - Interactive mode\n", program_name);