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;
}
示例#4
0
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;
}
示例#8
0
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;
}