monotone

monotone Mtn Source Tree

Root/botan/pbes1.cpp

1/*************************************************
2* PKCS #5 PBES1 Source File *
3* (C) 1999-2006 The Botan Project *
4*************************************************/
5
6#include <botan/pbe_pkcs.h>
7#include <botan/der_enc.h>
8#include <botan/ber_dec.h>
9#include <botan/parsing.h>
10#include <botan/lookup.h>
11#include <botan/rng.h>
12#include <algorithm>
13#include <memory>
14
15namespace Botan {
16
17/*************************************************
18* Encrypt some bytes using PBES1 *
19*************************************************/
20void PBE_PKCS5v15::write(const byte input[], u32bit length)
21 {
22 while(length)
23 {
24 u32bit put = std::min(DEFAULT_BUFFERSIZE, length);
25 pipe.write(input, length);
26 flush_pipe(true);
27 length -= put;
28 }
29 }
30
31/*************************************************
32* Start encrypting with PBES1 *
33*************************************************/
34void PBE_PKCS5v15::start_msg()
35 {
36 pipe.append(get_cipher(cipher, key, iv, direction));
37 pipe.start_msg();
38 if(pipe.message_count() > 1)
39 pipe.set_default_msg(pipe.default_msg() + 1);
40 }
41
42/*************************************************
43* Finish encrypting with PBES1 *
44*************************************************/
45void PBE_PKCS5v15::end_msg()
46 {
47 pipe.end_msg();
48 flush_pipe(false);
49 pipe.reset();
50 }
51
52/*************************************************
53* Flush the pipe *
54*************************************************/
55void PBE_PKCS5v15::flush_pipe(bool safe_to_skip)
56 {
57 if(safe_to_skip && pipe.remaining() < 64)
58 return;
59
60 SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
61 while(pipe.remaining())
62 {
63 u32bit got = pipe.read(buffer, buffer.size());
64 send(buffer, got);
65 }
66 }
67
68/*************************************************
69* Set the passphrase to use *
70*************************************************/
71void PBE_PKCS5v15::set_key(const std::string& passphrase)
72 {
73 std::auto_ptr<S2K> pbkdf(get_s2k("PBKDF1(" + digest + ")"));
74 pbkdf->set_iterations(iterations);
75 pbkdf->change_salt(salt, salt.size());
76 SymmetricKey key_and_iv = pbkdf->derive_key(16, passphrase);
77
78 key.set(key_and_iv.begin(), 8);
79 iv.set(key_and_iv.begin() + 8, 8);
80 }
81
82/*************************************************
83* Create a new set of PBES1 parameters *
84*************************************************/
85void PBE_PKCS5v15::new_params()
86 {
87 iterations = 2048;
88 salt.create(8);
89 Global_RNG::randomize(salt, salt.size());
90 }
91
92/*************************************************
93* Encode PKCS#5 PBES1 parameters *
94*************************************************/
95MemoryVector<byte> PBE_PKCS5v15::encode_params() const
96 {
97 return DER_Encoder()
98 .start_cons(SEQUENCE)
99 .encode(salt, OCTET_STRING)
100 .encode(iterations)
101 .end_cons()
102 .get_contents();
103 }
104
105/*************************************************
106* Decode PKCS#5 PBES1 parameters *
107*************************************************/
108void PBE_PKCS5v15::decode_params(DataSource& source)
109 {
110 BER_Decoder(source)
111 .start_cons(SEQUENCE)
112 .decode(salt, OCTET_STRING)
113 .decode(iterations)
114 .verify_end()
115 .end_cons();
116
117 if(salt.size() != 8)
118 throw Decoding_Error("PBES1: Encoded salt is not 8 octets");
119 }
120
121/*************************************************
122* Return an OID for this PBES1 type *
123*************************************************/
124OID PBE_PKCS5v15::get_oid() const
125 {
126 const OID base_pbes1_oid("1.2.840.113549.1.5");
127 if(cipher == "DES/CBC" && digest == "MD2")
128 return (base_pbes1_oid + 1);
129 else if(cipher == "DES/CBC" && digest == "MD5")
130 return (base_pbes1_oid + 3);
131 else if(cipher == "DES/CBC" && digest == "SHA-160")
132 return (base_pbes1_oid + 10);
133 else if(cipher == "RC2/CBC" && digest == "MD2")
134 return (base_pbes1_oid + 4);
135 else if(cipher == "RC2/CBC" && digest == "MD5")
136 return (base_pbes1_oid + 6);
137 else if(cipher == "RC2/CBC" && digest == "SHA-160")
138 return (base_pbes1_oid + 11);
139 else
140 throw Internal_Error("PBE-PKCS5 v1.5: get_oid() has run out of options");
141 }
142
143/*************************************************
144* PKCS#5 v1.5 PBE Constructor *
145*************************************************/
146PBE_PKCS5v15::PBE_PKCS5v15(const std::string& d_algo,
147 const std::string& c_algo, Cipher_Dir dir) :
148 direction(dir), digest(deref_alias(d_algo)), cipher(c_algo)
149 {
150 std::vector<std::string> cipher_spec = split_on(c_algo, '/');
151 if(cipher_spec.size() != 2)
152 throw Invalid_Argument("PBE-PKCS5 v1.5: Invalid cipher spec " + c_algo);
153 const std::string cipher_algo = deref_alias(cipher_spec[0]);
154 const std::string cipher_mode = cipher_spec[1];
155
156 if(!have_block_cipher(cipher_algo))
157 throw Algorithm_Not_Found(cipher_algo);
158 if(!have_hash(digest))
159 throw Algorithm_Not_Found(digest);
160
161 if((cipher_algo != "DES" && cipher_algo != "RC2") || (cipher_mode != "CBC"))
162 throw Invalid_Argument("PBE-PKCS5 v1.5: Invalid cipher " + cipher);
163 if(digest != "MD2" && digest != "MD5" && digest != "SHA-160")
164 throw Invalid_Argument("PBE-PKCS5 v1.5: Invalid digest " + digest);
165 }
166
167}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status