Botan  1.11.4
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  m_pipe.write(input, length);
23  flush_pipe(true);
24  }
25 
26 /*
27 * Start encrypting with PBES1
28 */
30  {
31  if(m_direction == ENCRYPTION)
32  m_pipe.append(new CBC_Encryption(m_block_cipher->clone(),
33  new PKCS7_Padding,
34  m_key, m_iv));
35  else
36  m_pipe.append(new CBC_Decryption(m_block_cipher->clone(),
37  new PKCS7_Padding,
38  m_key, m_iv));
39 
40  m_pipe.start_msg();
41  if(m_pipe.message_count() > 1)
42  m_pipe.set_default_msg(m_pipe.default_msg() + 1);
43  }
44 
45 /*
46 * Finish encrypting with PBES1
47 */
49  {
50  m_pipe.end_msg();
51  flush_pipe(false);
52  m_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 && m_pipe.remaining() < 64)
61  return;
62 
63  secure_vector<byte> buffer(DEFAULT_BUFFERSIZE);
64  while(m_pipe.remaining())
65  {
66  size_t got = m_pipe.read(&buffer[0], buffer.size());
67  send(buffer, got);
68  }
69  }
70 
71 /*
72 * Encode PKCS#5 PBES1 parameters
73 */
74 std::vector<byte> PBE_PKCS5v15::encode_params() const
75  {
76  return DER_Encoder()
78  .encode(m_salt, OCTET_STRING)
79  .encode(m_iterations)
80  .end_cons()
82  }
83 
84 /*
85 * Return an OID for this PBES1 type
86 */
88  {
89  const OID base_pbes1_oid("1.2.840.113549.1.5");
90 
91  const std::string cipher = m_block_cipher->name();
92  const std::string digest = m_hash_function->name();
93 
94  if(cipher == "DES" && digest == "MD2")
95  return (base_pbes1_oid + 1);
96  else if(cipher == "DES" && digest == "MD5")
97  return (base_pbes1_oid + 3);
98  else if(cipher == "DES" && digest == "SHA-160")
99  return (base_pbes1_oid + 10);
100  else if(cipher == "RC2" && digest == "MD2")
101  return (base_pbes1_oid + 4);
102  else if(cipher == "RC2" && digest == "MD5")
103  return (base_pbes1_oid + 6);
104  else if(cipher == "RC2" && digest == "SHA-160")
105  return (base_pbes1_oid + 11);
106  else
107  throw Internal_Error("PBE-PKCS5 v1.5: get_oid() has run out of options");
108  }
109 
110 std::string PBE_PKCS5v15::name() const
111  {
112  return "PBE-PKCS5v15(" + m_block_cipher->name() + "," +
113  m_hash_function->name() + ")";
114  }
115 
117  HashFunction* hash,
118  const std::string& passphrase,
119  std::chrono::milliseconds msec,
121  m_direction(ENCRYPTION),
122  m_block_cipher(cipher),
123  m_hash_function(hash),
124  m_salt(rng.random_vec(8))
125  {
126  if(cipher->name() != "DES" && cipher->name() != "RC2")
127  {
128  throw Invalid_Argument("PBE_PKCS5v1.5: Unknown cipher " +
129  cipher->name());
130  }
131 
132  if(hash->name() != "MD2" && hash->name() != "MD5" &&
133  hash->name() != "SHA-160")
134  {
135  throw Invalid_Argument("PBE_PKCS5v1.5: Unknown hash " +
136  hash->name());
137  }
138 
139  PKCS5_PBKDF1 pbkdf(m_hash_function->clone());
140 
141  secure_vector<byte> key_and_iv =
142  pbkdf.derive_key(16, passphrase,
143  &m_salt[0], m_salt.size(),
144  msec, m_iterations).bits_of();
145 
146  m_key.assign(&key_and_iv[0], &key_and_iv[8]);
147  m_iv.assign(&key_and_iv[8], &key_and_iv[16]);
148 
149  }
150 
152  HashFunction* hash,
153  const std::vector<byte>& params,
154  const std::string& passphrase) :
155  m_direction(DECRYPTION),
156  m_block_cipher(cipher),
157  m_hash_function(hash)
158  {
159  if(cipher->name() != "DES" && cipher->name() != "RC2")
160  {
161  throw Invalid_Argument("PBE_PKCS5v1.5: Unknown cipher " +
162  cipher->name());
163  }
164 
165  if(hash->name() != "MD2" && hash->name() != "MD5" &&
166  hash->name() != "SHA-160")
167  {
168  throw Invalid_Argument("PBE_PKCS5v1.5: Unknown hash " +
169  hash->name());
170  }
171 
172  BER_Decoder(params)
174  .decode(m_salt, OCTET_STRING)
175  .decode(m_iterations)
176  .verify_end()
177  .end_cons();
178 
179  if(m_salt.size() != 8)
180  throw Decoding_Error("PBES1: Encoded salt is not 8 octets");
181 
182  PKCS5_PBKDF1 pbkdf(m_hash_function->clone());
183 
184  secure_vector<byte> key_and_iv =
185  pbkdf.derive_key(16, passphrase,
186  &m_salt[0], m_salt.size(),
187  m_iterations).bits_of();
188 
189  m_key.assign(&key_and_iv[0], &key_and_iv[8]);
190  m_iv.assign(&key_and_iv[8], &key_and_iv[16]);
191  }
192 
194  {
195  delete m_block_cipher;
196  delete m_hash_function;
197  }
198 
199 }