Botan  2.7.0
Crypto and TLS for C++11
package.cpp
Go to the documentation of this file.
1 /*
2 * Rivest's Package Tranform
3 *
4 * (C) 2009 Jack Lloyd
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/package.h>
10 #include <botan/filters.h>
11 #include <botan/ctr.h>
12 #include <botan/loadstor.h>
13 #include <botan/rng.h>
14 
15 namespace Botan {
16 
18  BlockCipher* cipher,
19  const uint8_t input[], size_t input_len,
20  uint8_t output[])
21  {
22  if(input_len <= 1)
23  throw Encoding_Error("Package transform cannot encode small inputs");
24 
25  const size_t BLOCK_SIZE = cipher->block_size();
26 
27  if(!cipher->valid_keylength(BLOCK_SIZE))
28  throw Invalid_Argument("AONT::package: Invalid cipher");
29 
30  // The all-zero string which is used both as the CTR IV and as K0
31  const std::string all_zeros(BLOCK_SIZE*2, '0');
32 
33  SymmetricKey package_key(rng, BLOCK_SIZE);
34 
35  Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key));
36 
37  pipe.process_msg(input, input_len);
38  const size_t remaining = pipe.remaining();
39  BOTAN_ASSERT_EQUAL(remaining, pipe.read(output, remaining), "Expected read size");
40 
41  // Set K0 (the all zero key)
42  cipher->set_key(SymmetricKey(all_zeros));
43 
44  secure_vector<uint8_t> buf(BLOCK_SIZE);
45 
46  const size_t blocks =
47  (input_len + BLOCK_SIZE - 1) / BLOCK_SIZE;
48 
49  uint8_t* final_block = output + input_len;
50  clear_mem(final_block, BLOCK_SIZE);
51 
52  // XOR the hash blocks into the final block
53  for(size_t i = 0; i != blocks; ++i)
54  {
55  const size_t left = std::min<size_t>(BLOCK_SIZE,
56  input_len - BLOCK_SIZE * i);
57 
58  zeroise(buf);
59  copy_mem(buf.data(), output + (BLOCK_SIZE * i), left);
60 
61  for(size_t j = 0; j != sizeof(i); ++j)
62  buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i);
63 
64  cipher->encrypt(buf.data());
65 
66  xor_buf(final_block, buf.data(), BLOCK_SIZE);
67  }
68 
69  // XOR the random package key into the final block
70  xor_buf(final_block, package_key.begin(), BLOCK_SIZE);
71  }
72 
74  const uint8_t input[], size_t input_len,
75  uint8_t output[])
76  {
77  const size_t BLOCK_SIZE = cipher->block_size();
78 
79  if(!cipher->valid_keylength(BLOCK_SIZE))
80  throw Invalid_Argument("AONT::unpackage: Invalid cipher");
81 
82  if(input_len < BLOCK_SIZE)
83  throw Invalid_Argument("AONT::unpackage: Input too short");
84 
85  // The all-zero string which is used both as the CTR IV and as K0
86  const std::string all_zeros(BLOCK_SIZE*2, '0');
87 
88  cipher->set_key(SymmetricKey(all_zeros));
89 
90  secure_vector<uint8_t> package_key(BLOCK_SIZE);
91  secure_vector<uint8_t> buf(BLOCK_SIZE);
92 
93  // Copy the package key (masked with the block hashes)
94  copy_mem(package_key.data(),
95  input + (input_len - BLOCK_SIZE),
96  BLOCK_SIZE);
97 
98  const size_t blocks = ((input_len - 1) / BLOCK_SIZE);
99 
100  // XOR the blocks into the package key bits
101  for(size_t i = 0; i != blocks; ++i)
102  {
103  const size_t left = std::min<size_t>(BLOCK_SIZE,
104  input_len - BLOCK_SIZE * (i+1));
105 
106  zeroise(buf);
107  copy_mem(buf.data(), input + (BLOCK_SIZE * i), left);
108 
109  for(size_t j = 0; j != sizeof(i); ++j)
110  buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i);
111 
112  cipher->encrypt(buf.data());
113 
114  xor_buf(package_key.data(), buf.data(), BLOCK_SIZE);
115  }
116 
117  Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key));
118 
119  pipe.process_msg(input, input_len - BLOCK_SIZE);
120 
121  const size_t remaining = pipe.remaining();
122  BOTAN_ASSERT_EQUAL(remaining, pipe.read(output, remaining), "Expected read size");
123  }
124 
125 }
size_t remaining(message_id msg=DEFAULT_MESSAGE) const BOTAN_WARN_UNUSED_RESULT
Definition: pipe_rw.cpp:131
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:97
size_t read(uint8_t output[], size_t length) override BOTAN_WARN_UNUSED_RESULT
Definition: pipe_rw.cpp:82
bool valid_keylength(size_t length) const
Definition: sym_algo.h:56
void set_key(const SymmetricKey &key)
Definition: sym_algo.h:65
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:174
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:69
void process_msg(const uint8_t in[], size_t length)
Definition: pipe.cpp:103
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
OctetString SymmetricKey
Definition: symkey.h:136
const uint8_t * begin() const
Definition: symkey.h:36
void encrypt(const uint8_t in[], uint8_t out[]) const
Definition: block_cipher.h:81
void aont_unpackage(BlockCipher *cipher, const uint8_t input[], size_t input_len, uint8_t output[])
Definition: package.cpp:73
uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:39
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
void aont_package(RandomNumberGenerator &rng, BlockCipher *cipher, const uint8_t input[], size_t input_len, uint8_t output[])
Definition: package.cpp:17
virtual size_t block_size() const =0
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:183