monotone

monotone Mtn Source Tree

Root/botan/pbes1.cpp

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

Archive Download this file

Branches

Tags

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