exception_t* serpent_serial_encrypt(key256_t* user_key, block128_t* blocks, int block_count) { char* function_name = "serpent_serial_encrypt()"; exception_t* exception; uint32_t* subkey; // Validate parameters. #ifdef DEBUG_SERPENT if ( user_key == NULL ) { return exception_throw("user_key was NULL.", function_name); } if ( blocks == NULL ) { return exception_throw("blocks was NULL.", function_name); } #endif // Initialize the subkey. exception = serpent_init_subkey(user_key, &subkey); if ( exception != NULL ) { return exception_append(exception, function_name); } // Encrypt each block. for ( int i = 0; i < block_count; i++ ) { serpent_encrypt_block(&(blocks[i]), subkey); } // Free the subkey. exception = serpent_free_subkey(subkey); if ( exception != NULL ) { return exception_append(exception, function_name); } // Return success. return NULL; }
exception_t* serpent_parallel_decrypt(key256_t* user_key, block128_t* blocks, int block_count) { char* function_name = "serpent_parallel_decrypt()"; exception_t* exception; uint32_t* subkey; int blocks_per_thread; int thread_count; int thread_index; // Validate parameters. #ifdef DEBUG_SERPENT if ( user_key == NULL ) { return exception_throw("user_key was NULL.", function_name); } if ( blocks == NULL ) { return exception_throw("blocks was NULL.", function_name); } #endif // Initialize the subkey. exception = serpent_init_subkey(user_key, &subkey); if ( exception != NULL ) { return exception_append(exception, function_name); } // Decrypt each block. #pragma omp parallel shared(blocks, subkey, block_count, thread_count, thread_index, blocks_per_thread) { #if defined (_OPENMP) thread_count = omp_get_num_threads(); thread_index = omp_get_thread_num(); #endif // Calculate the current index. int index = thread_index; // Encrypted the minimal number of blocks. blocks_per_thread = block_count / thread_count; for ( int i = 0; i < blocks_per_thread; i++ ) { serpent_decrypt_block(&(blocks[index]), subkey); index += thread_count; } // Encrypt the extra blocks that fall outside the minimal number of block.s if ( index < block_count ) { serpent_decrypt_block(&(blocks[index]), subkey); } } // Free the subkey. exception = serpent_free_subkey(subkey); if ( exception != NULL ) { return exception_append(exception, function_name); } // Return. return NULL; }
exception_t* serpent_cuda_decrypt(key256_t* user_key, block128_t* blocks, int block_count, size_t* buffer_size) { char* function_name = "serpent_cuda_decrypt()"; exception_t* exception; uint32_t* subkey; // Validate parameters. #ifdef DEBUG_SERPENT if ( user_key == NULL ) { return exception_throw("user_key was NULL.", function_name); } if ( blocks == NULL ) { return exception_throw("blocks was NULL.", function_name); } if ( buffer_size == NULL ) { return exception_throw("buffer_size was NULL.", function_name); } #endif // Initialize the subkey. exception = serpent_init_subkey(user_key, &subkey); if ( exception != NULL ) { return exception_append(exception, function_name); } // Run the encryption algorithm from a different file. if ( serpent_cuda_decrypt_cu(subkey, blocks, block_count, buffer_size) == -1 ) { return exception_throw("CUDA encryption FAILED.", function_name); } // Free the subkey. exception = serpent_free_subkey(subkey); if ( exception != NULL ) { return exception_append(exception, function_name); } // Return success. return NULL; }
exception_t* file_free(file_t* file) { char* function_name = "file_free()"; exception_t* exception; // Validate parameters. if ( file == NULL ) { return exception_throw("file was NULL.", function_name); } // Write metadata or truncate file. // Note that file->flag reflects the file when it was opened, // and the file is now the _opposite_ of what the flag states. if ( file->flag == UNENCRYPTED ) { // Write padding to the end of the file. exception = file_write_metadata(file); if ( exception != NULL ) { return exception_append(exception, function_name); } } else if ( file->flag == ENCRYPTED ) { // Truncate the file padding. if ( ftruncate64(file->fd, (off64_t)(file->size - (off64_t)file->padding)) == -1 ) { return exception_throw("Unable to truncate file.", function_name); } } else { return exception_throw("Unexpected flag.", function_name); } // Free file name, free(file->name); // Close the file. if ( close(file->fd) == -1 ) { perror("Unable to close file."); return exception_throw("Unable to close file.", function_name); } // Set structure defaults. file->blocks = NULL; file->name = NULL; file->block_count = 0; file->size = 0; file->padding = 0; file->fd = 0; file->flag = 0; // Return success. return NULL; }
exception_t* benchmark(key256_t* key, char* input_filepath, enum algorithm algorithm, enum mode mode, enum encryption encryption, benchmark_run_t* benchmark_run ) { char* function_name = "benchmark()"; exception_t* exception; block128_t* blocks; file_t file; struct timespec clock_begin; struct timespec clock_elapsed; struct timespec clock_end; long long block_count; size_t buffer_size; // Validate parameters. if ( key == NULL ) { return exception_throw("key was NULL.", function_name); } if ( input_filepath == NULL ) { return exception_throw("input_filepath was NULL.", function_name); } if ( benchmark_run == NULL ) { return exception_throw("benchmark_run was NULL.", function_name); } // Open input file. if ( encryption == ENCRYPT ) { exception = file_init(input_filepath, UNENCRYPTED, &file); } else if ( encryption == DECRYPT ) { exception = file_init(input_filepath, ENCRYPTED, &file); } else { return exception_throw("Unhandled encryption parameter.", function_name); } if ( exception != NULL ) { return exception_append(exception, function_name); } // Get number of blocks in file. exception = file_get_block_count(&file, &block_count); if ( exception != NULL ) { return exception_append(exception, function_name); } // Read data from file. fprintf(stdout, "Reading. "); fflush(stdout); exception = file_read(&file, 0, block_count, &blocks); if ( exception != NULL ) { return exception_append(exception, function_name); } // Print message for the user. if ( encryption == ENCRYPT ) { fprintf(stdout, "Encrypting. "); } else if ( encryption == DECRYPT ) { fprintf(stdout, "Decrypting. "); } else { return exception_throw("Invalid encryption parameter.", function_name); } fflush(stdout); // Get begin time. if ( clock_gettime(CLOCK_REALTIME, &clock_begin) == -1 ) { return exception_throw("Unable to get begin time.", function_name); } // Call the algorithm. switch(algorithm) { case AES: return exception_throw("Not implemented. Sorry!", function_name); break; case SERPENT: exception = serpent(key, blocks, block_count, mode, encryption, &buffer_size); break; case TWOFISH: exception = twofish(key, blocks, block_count, mode, encryption, &buffer_size); break; default: return exception_throw("Unrecognized algorithm.", function_name); break; } if ( exception != NULL ) { return exception_append(exception, function_name); } // Get end time. if ( clock_gettime(CLOCK_REALTIME, &clock_end) == -1 ) { return exception_throw("Unable to get end time.", function_name); } // Write data to file. fprintf(stdout, "Writing. "); fflush(stdout); exception = file_write(&file, 0, block_count, blocks); if ( exception != NULL ) { return exception_append(exception, function_name); } // Close input file. exception = file_free(&file); if ( exception != NULL ) { return exception_append(exception, function_name); } // Calculate execution time. clock_elapsed.tv_sec = clock_end.tv_sec - clock_begin.tv_sec; clock_elapsed.tv_nsec = clock_end.tv_nsec - clock_begin.tv_nsec; if ( clock_elapsed.tv_nsec < 0 ) { clock_elapsed.tv_nsec += 1000000000; clock_elapsed.tv_sec -= 1; } // Assign output parameters. benchmark_run->time_elapsed.tv_sec = clock_elapsed.tv_sec; benchmark_run->time_elapsed.tv_nsec = clock_elapsed.tv_nsec; benchmark_run->buffer_size = buffer_size; // Return success. return NULL; }
exception_t* serpent(key256_t* user_key, block128_t* blocks, int block_count, enum mode mode, enum encryption encryption, size_t* buffer_size) { char* function_name = "serpent()"; exception_t* exception; // Validate parameters. #ifdef DEBUG_SERPENT if ( user_key == NULL ) { return exception_throw("user_key was NULL.", function_name); } if ( blocks == NULL ) { return exception_throw("blocks was NULL.", function_name); } if ( buffer_size == NULL ) { return exception_throw("buffer_size was NULL.", function_name); } #endif // Run the appropirate algorithm. switch(mode) { case CUDA: switch(encryption) { case DECRYPT: exception = serpent_cuda_decrypt(user_key, blocks, block_count, buffer_size); break; case ENCRYPT: exception = serpent_cuda_encrypt(user_key, blocks, block_count, buffer_size); break; default: return exception_throw("Unrecognized encryption parameter for CUDA.", function_name); } break; case PARALLEL: switch(encryption) { case DECRYPT: exception = serpent_parallel_decrypt(user_key, blocks, block_count); break; case ENCRYPT: exception = serpent_parallel_encrypt(user_key, blocks, block_count); break; default: return exception_throw("Unrecognized encryption parameter for parallel.", function_name); } break; case SERIAL: switch(encryption) { case DECRYPT: exception = serpent_serial_decrypt(user_key, blocks, block_count); break; case ENCRYPT: exception = serpent_serial_encrypt(user_key, blocks, block_count); break; default: return exception_throw("Unrecognized encryption parameter for serial.", function_name); } break; default: return exception_throw("Unknown mode.", function_name); } if ( exception != NULL ) { return exception_append(exception, function_name); } // Return success. return NULL; }
exception_t* serpent_init_subkey(key256_t* user_key, uint32_t** subkey) { char* function_name = "serpent_init_subkey()"; const int PREKEY_SIZE = 140; exception_t* exception; uint32_t* genkey; uint32_t a, b, c, d, e; // Validate parameters. #ifdef DEBUG_SERPENT if ( user_key == NULL ) { return exception_throw("user_key was NULL.", function_name); } if ( subkey == NULL ) { return exception_throw("subkey was NULL.", function_name); } #endif // Allocate space for genkey. genkey = (uint32_t*)malloc(sizeof(uint32_t) * PREKEY_SIZE); if ( genkey == NULL ) { return exception_throw("Unable to allocate genkey.", function_name); } // Assign user_key to the genkey; making sure to properly little-endianized the user key. for ( int i = 0; i < 8; i++ ) { uint32_t word; // Get the key value. exception = key256_get_word(user_key, i, &word); if ( exception != NULL ) { return exception_append(exception, function_name); } // Endianize the key value. word = mirror_bytes32(word); // Set the key value. genkey[i] = word; } // Generate the prekey by the following affine recurrence. genkey += 8; uint32_t t = genkey[-1]; for ( int i = 0; i < 132; ++i ) { genkey[i] = t = rotl_fixed(genkey[i-8] ^ genkey[i-5] ^ genkey[i-3] ^ t ^ 0x9E3779B9 ^ i, 11); } genkey -= 20; #define LK(r, a, b, c, d, e) {\ a = genkey[(8-r)*4 + 0]; \ b = genkey[(8-r)*4 + 1]; \ c = genkey[(8-r)*4 + 2]; \ d = genkey[(8-r)*4 + 3];} #define SK(r, a, b, c, d, e) {\ genkey[(8-r)*4 + 4] = a; \ genkey[(8-r)*4 + 5] = b; \ genkey[(8-r)*4 + 6] = c; \ genkey[(8-r)*4 + 7] = d;} \ // Generare the subkey using the prekey. for ( int i = 0; i < 4 ; i++ ) { afterS2(LK); afterS2(S3); afterS3(SK); afterS1(LK); afterS1(S2); afterS2(SK); afterS0(LK); afterS0(S1); afterS1(SK); beforeS0(LK); beforeS0(S0); afterS0(SK); genkey += 8*4; afterS6(LK); afterS6(S7); afterS7(SK); afterS5(LK); afterS5(S6); afterS6(SK); afterS4(LK); afterS4(S5); afterS5(SK); afterS3(LK); afterS3(S4); afterS4(SK); } afterS2(LK); afterS2(S3); afterS3(SK); genkey -= 108; // Assign output parameter. (*subkey) = genkey; // Return success. return NULL; }
exception_t* file_init(const char* file_name, enum file_encryption flag, file_t* file) { char* function_name = "file_init()"; exception_t* exception; struct stat64 buffer; int temp; // Validate parameters. if ( file_name == NULL ) { return exception_throw("file_name was NULL.", function_name); } if ( file == NULL ) { return exception_throw("file was NULL.", function_name); } // Initialize file structure. file->blocks = NULL; file->block_count = 0; file->padding = 0; file->flag = flag; // Get file name, file->name = (char*)malloc(sizeof(char)*strlen(file_name)); if ( file->name == NULL ) { return exception_throw("Malloc failed.", function_name); } strcpy(file->name, file_name); // Open the file. file->fd = open(file_name, O_RDWR | O_LARGEFILE); if ( file->fd == -1 ) { perror("Unable to open file."); return exception_throw("Unable to open file.", function_name); } // Get file size. temp = fstat64(file->fd, &buffer); if ( temp == -1 ) { perror("Unable to get stats."); return exception_throw("Unable to get stats.", function_name); } file->size = buffer.st_size; // Get file metadata or pad the file. if ( flag == ENCRYPTED ) { // Read in file metadata. exception = file_read_metadata(file); if ( exception != NULL ) { return exception_append(exception, function_name); } } else if ( flag == UNENCRYPTED ) { int temp; // Calculate file padding. temp = file->size % sizeof(block128_t); if ( temp == 0 ) { file->padding = temp; } else { file->padding = sizeof(block128_t) - temp; // Pad the file. exception = file_write_padding(file); if ( exception != NULL ) { return exception_append(exception, function_name); } } } else { return exception_throw("Unexpected flag.", function_name); } // Return success. return NULL; }