Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

pbes2.cpp
Go to the documentation of this file.
1 /*
2 * PKCS #5 PBES2
3 * (C) 1999-2008,2014 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/pbes2.h>
9 #include <botan/cipher_mode.h>
10 #include <botan/pbkdf.h>
11 #include <botan/der_enc.h>
12 #include <botan/ber_dec.h>
13 #include <botan/parsing.h>
14 #include <botan/alg_id.h>
15 #include <botan/oids.h>
16 #include <botan/rng.h>
17 #include <algorithm>
18
19 namespace Botan {
20
21 namespace {
22
23 /*
24 * Encode PKCS#5 PBES2 parameters
25 */
26 std::vector<uint8_t> encode_pbes2_params(const std::string& cipher,
27 const std::string& prf,
28 const secure_vector<uint8_t>& salt,
29 const secure_vector<uint8_t>& iv,
30 size_t iterations,
31 size_t key_length)
32 {
33 return DER_Encoder()
34 .start_cons(SEQUENCE)
35 .encode(
36 AlgorithmIdentifier("PKCS5.PBKDF2",
37 DER_Encoder()
38 .start_cons(SEQUENCE)
39 .encode(salt, OCTET_STRING)
40 .encode(iterations)
41 .encode(key_length)
42 .encode_if(
43 prf != "HMAC(SHA-160)",
44 AlgorithmIdentifier(prf, AlgorithmIdentifier::USE_NULL_PARAM))
45 .end_cons()
46 .get_contents_unlocked()
47 )
48 )
49 .encode(
50 AlgorithmIdentifier(cipher,
51 DER_Encoder().encode(iv, OCTET_STRING).get_contents_unlocked()
52 )
53 )
54 .end_cons()
55 .get_contents_unlocked();
56 }
57
58 /*
59 * PKCS#5 v2.0 PBE Encryption
60 */
61 std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
62 pbes2_encrypt_shared(const secure_vector<uint8_t>& key_bits,
63 const std::string& passphrase,
64 size_t* msec_in_iterations_out,
65 size_t iterations_if_msec_null,
66 const std::string& cipher,
67 const std::string& digest,
68 RandomNumberGenerator& rng)
69 {
70 const std::string prf = "HMAC(" + digest + ")";
71
72 const std::vector<std::string> cipher_spec = split_on(cipher, '/');
73 if(cipher_spec.size() != 2)
74 throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
75
76 const secure_vector<uint8_t> salt = rng.random_vec(12);
77
78 if(cipher_spec[1] != "CBC" && cipher_spec[1] != "GCM")
79 throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher);
80
81 std::unique_ptr<Cipher_Mode> enc(get_cipher_mode(cipher, ENCRYPTION));
82
83 if(!enc)
84 throw Decoding_Error("PBE-PKCS5 cannot encrypt no cipher " + cipher);
85
86 std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(" + prf + ")"));
87
88 const size_t key_length = enc->key_spec().maximum_keylength();
89
90
91 secure_vector<uint8_t> iv = rng.random_vec(enc->default_nonce_length());
92
93 size_t iterations = iterations_if_msec_null;
94
95 if(msec_in_iterations_out)
96 {
97 std::chrono::milliseconds msec(*msec_in_iterations_out);
98 enc->set_key(pbkdf->derive_key(key_length, passphrase, salt.data(), salt.size(), msec, iterations).bits_of());
99 *msec_in_iterations_out = iterations;
100 }
101 else
102 {
103 enc->set_key(pbkdf->pbkdf_iterations(key_length, passphrase, salt.data(), salt.size(), iterations));
104 }
105
106 enc->start(iv);
107 secure_vector<uint8_t> buf = key_bits;
108 enc->finish(buf);
109
110 AlgorithmIdentifier id(
111 OIDS::lookup("PBE-PKCS5v20"),
112 encode_pbes2_params(cipher, prf, salt, iv, iterations, key_length));
113
114 return std::make_pair(id, unlock(buf));
115 }
116
117
118 }
119
120 std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
121 pbes2_encrypt(const secure_vector<uint8_t>& key_bits,
122 const std::string& passphrase,
123 std::chrono::milliseconds msec,
124 const std::string& cipher,
125 const std::string& digest,
126 RandomNumberGenerator& rng)
127 {
128 size_t msec_in_iterations_out = msec.count();
129 return pbes2_encrypt_shared(key_bits, passphrase, &msec_in_iterations_out, 0, cipher, digest, rng);
130 // return value msec_in_iterations_out discarded
131 }
132
133 std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
134 pbes2_encrypt_msec(const secure_vector<uint8_t>& key_bits,
135 const std::string& passphrase,
136 std::chrono::milliseconds msec,
137 size_t* out_iterations_if_nonnull,
138 const std::string& cipher,
139 const std::string& digest,
140 RandomNumberGenerator& rng)
141 {
142 size_t msec_in_iterations_out = msec.count();
143
144 auto ret = pbes2_encrypt_shared(key_bits, passphrase, &msec_in_iterations_out, 0, cipher, digest, rng);
145
146 if(out_iterations_if_nonnull)
147 *out_iterations_if_nonnull = msec_in_iterations_out;
148
149 return ret;
150 }
151
152 std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
153 pbes2_encrypt_iter(const secure_vector<uint8_t>& key_bits,
154 const std::string& passphrase,
155 size_t pbkdf_iter,
156 const std::string& cipher,
157 const std::string& digest,
158 RandomNumberGenerator& rng)
159 {
160 return pbes2_encrypt_shared(key_bits, passphrase, nullptr, pbkdf_iter, cipher, digest, rng);
161 }
162
163 secure_vector<uint8_t>
164 pbes2_decrypt(const secure_vector<uint8_t>& key_bits,
165 const std::string& passphrase,
166 const std::vector<uint8_t>& params)
167 {
168 AlgorithmIdentifier kdf_algo, enc_algo;
169
170 BER_Decoder(params)
171 .start_cons(SEQUENCE)
172 .decode(kdf_algo)
173 .decode(enc_algo)
174 .end_cons();
175
176 AlgorithmIdentifier prf_algo;
177
178 if(kdf_algo.oid != OIDS::lookup("PKCS5.PBKDF2"))
179 throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " +
180 kdf_algo.oid.as_string());
181
182 secure_vector<uint8_t> salt;
183 size_t iterations = 0, key_length = 0;
184
185 BER_Decoder(kdf_algo.parameters)
186 .start_cons(SEQUENCE)
187 .decode(salt, OCTET_STRING)
188 .decode(iterations)
189 .decode_optional(key_length, INTEGER, UNIVERSAL)
190 .decode_optional(prf_algo, SEQUENCE, CONSTRUCTED,
191 AlgorithmIdentifier("HMAC(SHA-160)",
192 AlgorithmIdentifier::USE_NULL_PARAM))
193 .end_cons();
194
195 const std::string cipher = OIDS::lookup(enc_algo.oid);
196 const std::vector<std::string> cipher_spec = split_on(cipher, '/');
197 if(cipher_spec.size() != 2)
198 throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
199 if(cipher_spec[1] != "CBC" && cipher_spec[1] != "GCM")
200 throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher);
201
202 if(salt.size() < 8)
203 throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small");
204
205 secure_vector<uint8_t> iv;
206 BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end();
207
208 const std::string prf = OIDS::lookup(prf_algo.oid);
209
210 std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(" + prf + ")"));
211
212 std::unique_ptr<Cipher_Mode> dec(get_cipher_mode(cipher, DECRYPTION));
213 if(!dec)
214 throw Decoding_Error("PBE-PKCS5 cannot decrypt no cipher " + cipher);
215
216 if(key_length == 0)
217 key_length = dec->key_spec().maximum_keylength();
218
219 dec->set_key(pbkdf->pbkdf_iterations(key_length, passphrase, salt.data(), salt.size(), iterations));
220
221 dec->start(iv);
222
223 secure_vector<uint8_t> buf = key_bits;
224 dec->finish(buf);
225
226 return buf;
227 }
228
229 }
Botan::INTEGER
Definition: asn1_obj.h:33
Botan::RandomNumberGenerator
Definition: rng.h:25
Botan::ENCRYPTION
Definition: cipher_mode.h:212
Botan::AlgorithmIdentifier::parameters
std::vector< uint8_t > parameters
Definition: alg_id.h:39
Botan::PEM_Code::encode
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
Botan::pbes2_encrypt_iter
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt_iter(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, size_t pbkdf_iter, const std::string &cipher, const std::string &digest, RandomNumberGenerator &rng)
Definition: pbes2.cpp:153
Botan::get_cipher_mode
Cipher_Mode * get_cipher_mode(const std::string &algo, Cipher_Dir direction)
Definition: cipher_mode.cpp:39
Botan::split_on
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:138
Botan::BER_Decoder::decode
BER_Decoder & decode(bool &v)
Definition: ber_dec.cpp:376
Botan::pbes2_encrypt_msec
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt_msec(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, std::chrono::milliseconds msec, size_t *out_iterations_if_nonnull, const std::string &cipher, const std::string &digest, RandomNumberGenerator &rng)
Definition: pbes2.cpp:134
Botan::DECRYPTION
Definition: cipher_mode.h:212
Botan::UNIVERSAL
Definition: asn1_obj.h:23
Botan::BER_Decoder::decode_optional
BER_Decoder & decode_optional(T &out, ASN1_Tag type_tag, ASN1_Tag class_tag, const T &default_value=T())
Definition: ber_dec.h:213
Botan::OCTET_STRING
Definition: asn1_obj.h:35
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
Botan::CONSTRUCTED
Definition: asn1_obj.h:27
Botan::BER_Decoder::end_cons
BER_Decoder & end_cons()
Definition: ber_dec.cpp:272
Botan::OIDS::lookup
std::string lookup(const OID &oid)
Definition: oids.cpp:18
Botan::AlgorithmIdentifier::oid
OID oid
Definition: alg_id.h:36
Botan::get_pbkdf
PBKDF * get_pbkdf(const std::string &algo_spec, const std::string &provider="")
Definition: pbkdf.h:216
Botan::Decoding_Error
Definition: exceptn.h:189
Botan::SEQUENCE
Definition: asn1_obj.h:39
Botan::BER_Decoder::start_cons
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:258
Botan
Definition: alg_id.cpp:13
Botan::pbes2_decrypt
secure_vector< uint8_t > pbes2_decrypt(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, const std::vector< uint8_t > &params)
Definition: pbes2.cpp:164
Botan::unlock
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:125
Botan::pbes2_encrypt
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, std::chrono::milliseconds msec, const std::string &cipher, const std::string &digest, RandomNumberGenerator &rng)
Definition: pbes2.cpp:121
Botan::BER_Decoder::verify_end
BER_Decoder & verify_end()
Definition: ber_dec.cpp:168
Botan::OID::as_string
std::string as_string() const
Definition: asn1_oid.cpp:50
Botan::AlgorithmIdentifier
Definition: alg_id.h:20
Botan::AlgorithmIdentifier::USE_NULL_PARAM
Definition: alg_id.h:23
Botan::BER_Decoder
Definition: ber_dec.h:19