Botan  1.10.9
pbes1.cpp
Go to the documentation of this file.
1 /*
2 * PKCS #5 PBES1
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/pbes1.h>
9 #include <botan/pbkdf1.h>
10 #include <botan/der_enc.h>
11 #include <botan/ber_dec.h>
12 #include <botan/cbc.h>
13 #include <algorithm>
14 
15 namespace Botan {
16 
17 /*
18 * Encrypt some bytes using PBES1
19 */
20 void PBE_PKCS5v15::write(const byte input[], size_t length)
21  {
22  pipe.write(input, length);
23  flush_pipe(true);
24  }
25 
26 /*
27 * Start encrypting with PBES1
28 */
30  {
31  if(direction == ENCRYPTION)
32  pipe.append(new CBC_Encryption(block_cipher->clone(),
33  new PKCS7_Padding,
34  key, iv));
35  else
36  pipe.append(new CBC_Decryption(block_cipher->clone(),
37  new PKCS7_Padding,
38  key, iv));
39 
40  pipe.start_msg();
41  if(pipe.message_count() > 1)
42  pipe.set_default_msg(pipe.default_msg() + 1);
43  }
44 
45 /*
46 * Finish encrypting with PBES1
47 */
49  {
50  pipe.end_msg();
51  flush_pipe(false);
52  pipe.reset();
53  }
54 
55 /*
56 * Flush the pipe
57 */
58 void PBE_PKCS5v15::flush_pipe(bool safe_to_skip)
59  {
60  if(safe_to_skip && pipe.remaining() < 64)
61  return;
62 
63  SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
64  while(pipe.remaining())
65  {
66  size_t got = pipe.read(&buffer[0], buffer.size());
67  send(buffer, got);
68  }
69  }
70 
71 /*
72 * Set the passphrase to use
73 */
74 void PBE_PKCS5v15::set_key(const std::string& passphrase)
75  {
76  PKCS5_PBKDF1 pbkdf(hash_function->clone());
77 
78  SecureVector<byte> key_and_iv = pbkdf.derive_key(16, passphrase,
79  &salt[0], salt.size(),
80  iterations).bits_of();
81 
82  key.resize(8);
83  iv.resize(8);
84  copy_mem(&key[0], &key_and_iv[0], 8);
85  copy_mem(&iv[0], &key_and_iv[8], 8);
86  }
87 
88 /*
89 * Create a new set of PBES1 parameters
90 */
91 void PBE_PKCS5v15::new_params(RandomNumberGenerator& rng)
92  {
93  iterations = 50000;
94  salt = rng.random_vec(8);
95  }
96 
97 /*
98 * Encode PKCS#5 PBES1 parameters
99 */
100 MemoryVector<byte> PBE_PKCS5v15::encode_params() const
101  {
102  return DER_Encoder()
103  .start_cons(SEQUENCE)
104  .encode(salt, OCTET_STRING)
105  .encode(iterations)
106  .end_cons()
107  .get_contents();
108  }
109 
110 /*
111 * Decode PKCS#5 PBES1 parameters
112 */
113 void PBE_PKCS5v15::decode_params(DataSource& source)
114  {
115  BER_Decoder(source)
116  .start_cons(SEQUENCE)
117  .decode(salt, OCTET_STRING)
118  .decode(iterations)
119  .verify_end()
120  .end_cons();
121 
122  if(salt.size() != 8)
123  throw Decoding_Error("PBES1: Encoded salt is not 8 octets");
124  }
125 
126 /*
127 * Return an OID for this PBES1 type
128 */
129 OID PBE_PKCS5v15::get_oid() const
130  {
131  const OID base_pbes1_oid("1.2.840.113549.1.5");
132 
133  const std::string cipher = block_cipher->name();
134  const std::string digest = hash_function->name();
135 
136  if(cipher == "DES" && digest == "MD2")
137  return (base_pbes1_oid + 1);
138  else if(cipher == "DES" && digest == "MD5")
139  return (base_pbes1_oid + 3);
140  else if(cipher == "DES" && digest == "SHA-160")
141  return (base_pbes1_oid + 10);
142  else if(cipher == "RC2" && digest == "MD2")
143  return (base_pbes1_oid + 4);
144  else if(cipher == "RC2" && digest == "MD5")
145  return (base_pbes1_oid + 6);
146  else if(cipher == "RC2" && digest == "SHA-160")
147  return (base_pbes1_oid + 11);
148  else
149  throw Internal_Error("PBE-PKCS5 v1.5: get_oid() has run out of options");
150  }
151 
152 std::string PBE_PKCS5v15::name() const
153  {
154  return "PBE-PKCS5v15(" + block_cipher->name() + "," +
155  hash_function->name() + ")";
156  }
157 
158 /*
159 * PKCS#5 v1.5 PBE Constructor
160 */
162  HashFunction* hash,
163  Cipher_Dir dir) :
164  direction(dir), block_cipher(cipher), hash_function(hash), iterations(0)
165  {
166  if(cipher->name() != "DES" && cipher->name() != "RC2")
167  {
168  throw Invalid_Argument("PBE_PKCS5v1.5: Unknown cipher " +
169  cipher->name());
170  }
171 
172  if(hash->name() != "MD2" && hash->name() != "MD5" &&
173  hash->name() != "SHA-160")
174  {
175  throw Invalid_Argument("PBE_PKCS5v1.5: Unknown hash " +
176  hash->name());
177  }
178  }
179 
181  {
182  delete block_cipher;
183  delete hash_function;
184  }
185 
186 }
void start_msg()
Definition: pipe.cpp:152
void resize(size_t n)
Definition: secmem.h:211
void append(Filter *filt)
Definition: pipe.cpp:215
size_t read(byte output[], size_t length)
Definition: pipe_rw.cpp:89
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:34
virtual BlockCipher * clone() const =0
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
void reset()
Definition: pipe.cpp:76
virtual HashFunction * clone() const =0
size_t remaining(message_id msg=DEFAULT_MESSAGE) const
Definition: pipe_rw.cpp:138
unsigned char byte
Definition: types.h:22
void send(const byte in[], size_t length)
Definition: filter.cpp:28
void end_msg()
Definition: pipe.cpp:166
RandomNumberGenerator * rng
Definition: global_rng.cpp:165
size_t size() const
Definition: secmem.h:29
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:22
void write(const byte[], size_t)
Definition: pbes1.cpp:20
virtual std::string name() const =0
PBE_PKCS5v15(BlockCipher *cipher, HashFunction *hash, Cipher_Dir direction)
Definition: pbes1.cpp:161
size_t default_msg() const
Definition: pipe.h:206
std::string name() const
Definition: pbes1.cpp:152
void set_default_msg(message_id msg)
Definition: pipe.cpp:106
Cipher_Dir
Definition: sym_algo.h:87
void start_msg()
Definition: pbes1.cpp:29
message_id message_count() const
Definition: pipe.cpp:282