Botan
1.11.15
|
00001 /* 00002 * Rivest's Package Tranform 00003 * 00004 * (C) 2009 Jack Lloyd 00005 * 00006 * Botan is released under the Simplified BSD License (see license.txt) 00007 */ 00008 00009 #include <botan/package.h> 00010 #include <botan/filters.h> 00011 #include <botan/ctr.h> 00012 #include <botan/get_byte.h> 00013 #include <botan/internal/xor_buf.h> 00014 00015 namespace Botan { 00016 00017 void aont_package(RandomNumberGenerator& rng, 00018 BlockCipher* cipher, 00019 const byte input[], size_t input_len, 00020 byte output[]) 00021 { 00022 const size_t BLOCK_SIZE = cipher->block_size(); 00023 00024 if(!cipher->valid_keylength(BLOCK_SIZE)) 00025 throw Invalid_Argument("AONT::package: Invalid cipher"); 00026 00027 // The all-zero string which is used both as the CTR IV and as K0 00028 const std::string all_zeros(BLOCK_SIZE*2, '0'); 00029 00030 SymmetricKey package_key(rng, BLOCK_SIZE); 00031 00032 Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key)); 00033 00034 pipe.process_msg(input, input_len); 00035 pipe.read(output, pipe.remaining()); 00036 00037 // Set K0 (the all zero key) 00038 cipher->set_key(SymmetricKey(all_zeros)); 00039 00040 secure_vector<byte> buf(BLOCK_SIZE); 00041 00042 const size_t blocks = 00043 (input_len + BLOCK_SIZE - 1) / BLOCK_SIZE; 00044 00045 byte* final_block = output + input_len; 00046 clear_mem(final_block, BLOCK_SIZE); 00047 00048 // XOR the hash blocks into the final block 00049 for(size_t i = 0; i != blocks; ++i) 00050 { 00051 const size_t left = std::min<size_t>(BLOCK_SIZE, 00052 input_len - BLOCK_SIZE * i); 00053 00054 zeroise(buf); 00055 copy_mem(&buf[0], output + (BLOCK_SIZE * i), left); 00056 00057 for(size_t j = 0; j != sizeof(i); ++j) 00058 buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i); 00059 00060 cipher->encrypt(&buf[0]); 00061 00062 xor_buf(&final_block[0], &buf[0], BLOCK_SIZE); 00063 } 00064 00065 // XOR the random package key into the final block 00066 xor_buf(&final_block[0], package_key.begin(), BLOCK_SIZE); 00067 } 00068 00069 void aont_unpackage(BlockCipher* cipher, 00070 const byte input[], size_t input_len, 00071 byte output[]) 00072 { 00073 const size_t BLOCK_SIZE = cipher->block_size(); 00074 00075 if(!cipher->valid_keylength(BLOCK_SIZE)) 00076 throw Invalid_Argument("AONT::unpackage: Invalid cipher"); 00077 00078 if(input_len < BLOCK_SIZE) 00079 throw Invalid_Argument("AONT::unpackage: Input too short"); 00080 00081 // The all-zero string which is used both as the CTR IV and as K0 00082 const std::string all_zeros(BLOCK_SIZE*2, '0'); 00083 00084 cipher->set_key(SymmetricKey(all_zeros)); 00085 00086 secure_vector<byte> package_key(BLOCK_SIZE); 00087 secure_vector<byte> buf(BLOCK_SIZE); 00088 00089 // Copy the package key (masked with the block hashes) 00090 copy_mem(&package_key[0], 00091 input + (input_len - BLOCK_SIZE), 00092 BLOCK_SIZE); 00093 00094 const size_t blocks = ((input_len - 1) / BLOCK_SIZE); 00095 00096 // XOR the blocks into the package key bits 00097 for(size_t i = 0; i != blocks; ++i) 00098 { 00099 const size_t left = std::min<size_t>(BLOCK_SIZE, 00100 input_len - BLOCK_SIZE * (i+1)); 00101 00102 zeroise(buf); 00103 copy_mem(&buf[0], input + (BLOCK_SIZE * i), left); 00104 00105 for(size_t j = 0; j != sizeof(i); ++j) 00106 buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i); 00107 00108 cipher->encrypt(&buf[0]); 00109 00110 xor_buf(&package_key[0], &buf[0], BLOCK_SIZE); 00111 } 00112 00113 Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key)); 00114 00115 pipe.process_msg(input, input_len - BLOCK_SIZE); 00116 00117 pipe.read(output, pipe.remaining()); 00118 } 00119 00120 }