Botan 1.10.17
cms_ealg.cpp
Go to the documentation of this file.
1/*
2* CMS Encoding Operations
3* (C) 1999-2007 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/cms_enc.h>
9#include <botan/bigint.h>
10#include <botan/cbc.h>
11#include <botan/der_enc.h>
12#include <botan/hash.h>
13#include <botan/libstate.h>
14#include <botan/oids.h>
15#include <botan/pipe.h>
16#include <botan/pubkey.h>
17#include <memory>
18
19namespace Botan {
20
21namespace {
22
23/*
24* Choose an algorithm
25*/
26std::string choose_algo(const std::string& user_algo,
27 const std::string& default_algo)
28 {
29 if(user_algo == "")
30 return global_state().deref_alias(default_algo);
31 return global_state().deref_alias(user_algo);
32 }
33
34/*
35* Encode a SignerIdentifier/RecipientIdentifier
36*/
37DER_Encoder& encode_si(DER_Encoder& der, const X509_Certificate& cert,
38 bool use_skid_encoding = false)
39 {
40 if(cert.subject_key_id().size() && use_skid_encoding)
41 der.encode(cert.subject_key_id(), OCTET_STRING, ASN1_Tag(0));
42 else
43 {
44 der.start_cons(SEQUENCE).
45 encode(cert.issuer_dn()).
46 encode(BigInt::decode(cert.serial_number())).
47 end_cons();
48 }
49
50 return der;
51 }
52
53/*
54* Compute the hash of some content
55*/
56SecureVector<byte> hash_of(const SecureVector<byte>& content,
57 const std::string& hash_name)
58 {
60 std::auto_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name));
61 return hash_fn->process(content);
62 }
63
64/*
65* Encode Attributes containing info on content
66*/
67SecureVector<byte> encode_attr(const SecureVector<byte>& data,
68 const std::string& type,
69 const std::string& hash)
70 {
71 SecureVector<byte> digest = hash_of(data, hash);
72
73 DER_Encoder encoder;
74 encoder.encode(OIDS::lookup(type));
75 Attribute content_type("PKCS9.ContentType", encoder.get_contents());
76
77 encoder.encode(digest, OCTET_STRING);
78 Attribute message_digest("PKCS9.MessageDigest", encoder.get_contents());
79
80 encoder.start_cons(SET)
81 .encode(content_type)
82 .encode(message_digest)
83 .end_cons();
84
85 return encoder.get_contents();
86 }
87
88}
89
90/*
91* Encrypt a message
92*/
94 const X509_Certificate& to,
95 const std::string user_cipher)
96 {
97 const std::string cipher = choose_algo(user_cipher, "TripleDES");
98
99 std::auto_ptr<Public_Key> key(to.subject_public_key());
100 const std::string algo = key->algo_name();
101
102 Key_Constraints constraints = to.constraints();
103
104 if(algo == "RSA")
105 {
106 if(constraints != NO_CONSTRAINTS && !(constraints & KEY_ENCIPHERMENT))
107 throw Invalid_Argument("CMS: Constraints not set for encryption");
108
109 encrypt_ktri(rng, to, key.get(), cipher);
110 }
111 else if(algo == "DH")
112 {
113 if(constraints != NO_CONSTRAINTS && !(constraints & KEY_AGREEMENT))
114 throw Invalid_Argument("CMS: Constraints not set for key agreement");
115
116 encrypt_kari(rng, to, key.get(), cipher);
117 }
118 else
119 throw Invalid_Argument("Unknown CMS PK encryption algorithm " + algo);
120 }
121
122/*
123* Encrypt a message with a key transport algo
124*/
125void CMS_Encoder::encrypt_ktri(RandomNumberGenerator& rng,
126 const X509_Certificate& to,
127 Public_Key* pub_key,
128 const std::string& cipher)
129 {
130 const std::string padding = "EME-PKCS1-v1_5";
131 const std::string pk_algo = pub_key->algo_name();
132
133 PK_Encryptor_EME encryptor(*pub_key, padding);
134
135 SymmetricKey cek = setup_key(rng, cipher);
136
137 AlgorithmIdentifier alg_id(OIDS::lookup(pk_algo + '/' + padding),
139
140 DER_Encoder encoder;
141
142 encoder.start_cons(SEQUENCE)
143 .encode(static_cast<size_t>(0))
146 .encode(static_cast<size_t>(0));
147 encode_si(encoder, to)
148 .encode(alg_id)
149 .encode(encryptor.encrypt(cek.bits_of(), rng), OCTET_STRING)
150 .end_cons()
151 .end_cons()
152 .raw_bytes(do_encrypt(rng, cek, cipher))
153 .end_cons();
154
155 add_layer("CMS.EnvelopedData", encoder);
156 }
157
158/*
159* Encrypt a message with a key agreement algo
160*/
161void CMS_Encoder::encrypt_kari(RandomNumberGenerator&,
162 const X509_Certificate&,
163 Public_Key*,
164 const std::string&)
165 {
166 throw Internal_Error("FIXME: unimplemented");
167
168#if 0
169 SymmetricKey cek = setup_key(rng, cipher);
170
171 DER_Encoder encoder;
172 encoder.start_cons(SEQUENCE);
173 encoder.encode(2);
174 encoder.start_cons(SET);
175 encoder.start_sequence(ASN1_Tag(1));
176 encoder.encode(3);
177 encode_si(encoder, to);
178 encoder.encode(AlgorithmIdentifier(pk_algo + "/" + padding));
179 encoder.encode(encrypted_cek, OCTET_STRING);
180 encoder.end_cons();
181 encoder.end_cons();
182 encoder.raw_bytes(do_encrypt(rng, cek, cipher));
183 encoder.end_cons();
184
185 add_layer("CMS.EnvelopedData", encoder);
186#endif
187 }
188
189/*
190* Encrypt a message with a shared key
191*/
193 const SymmetricKey& kek,
194 const std::string& user_cipher)
195 {
196 throw Internal_Error("FIXME: untested");
197
198 const std::string cipher = choose_algo(user_cipher, "TripleDES");
199 SymmetricKey cek = setup_key(rng, cipher);
200
201 SecureVector<byte> kek_id; // FIXME: ?
202
203 DER_Encoder encoder;
204
205 encoder.start_cons(SEQUENCE)
206 .encode(static_cast<size_t>(2))
208 .encode(static_cast<size_t>(4))
210 .encode(kek_id, OCTET_STRING)
211 .end_cons()
212 .encode(AlgorithmIdentifier(OIDS::lookup("KeyWrap." + cipher),
214 .encode(wrap_key(rng, cipher, cek, kek), OCTET_STRING)
215 .end_cons()
216 .raw_bytes(do_encrypt(rng, cek, cipher))
217 .end_cons();
218
219 add_layer("CMS.EnvelopedData", encoder);
220 }
221
222/*
223* Encrypt a message with a passphrase
224*/
226 const std::string&,
227 const std::string& user_cipher)
228 {
229 const std::string cipher = choose_algo(user_cipher, "TripleDES");
230 throw Internal_Error("FIXME: unimplemented");
231 /*
232 SymmetricKey cek = setup_key(key);
233
234 DER_Encoder encoder;
235 encoder.start_cons(SEQUENCE);
236 encoder.encode(0);
237 encoder.raw_bytes(do_encrypt(rng, cek, cipher));
238 encoder.end_cons();
239
240 add_layer("CMS.EnvelopedData", encoder);
241 */
242 }
243
244/*
245* Encrypt the content with the chosen key/cipher
246*/
247SecureVector<byte> CMS_Encoder::do_encrypt(RandomNumberGenerator& rng,
248 const SymmetricKey& key,
249 const std::string& cipher_name)
250 {
252
253 const BlockCipher* cipher = af.prototype_block_cipher(cipher_name);
254
255 if(!cipher)
256 throw Invalid_Argument("CMS: Can't encrypt with non-existent cipher " + cipher_name);
257
258 if(!OIDS::have_oid(cipher->name() + "/CBC"))
259 throw Encoding_Error("CMS: No OID assigned for " + cipher_name + "/CBC");
260
261 InitializationVector iv(rng, cipher->block_size());
262
263 AlgorithmIdentifier content_cipher;
264 content_cipher.oid = OIDS::lookup(cipher->name() + "/CBC");
265 content_cipher.parameters = encode_params(cipher->name(), key, iv);
266
267 Pipe pipe(new CBC_Encryption(cipher->clone(), new PKCS7_Padding, key, iv));
268
269 pipe.process_msg(data);
270
271 DER_Encoder encoder;
272 encoder.start_cons(SEQUENCE);
273 encoder.encode(OIDS::lookup(type));
274 encoder.encode(content_cipher);
275 encoder.encode(pipe.read_all(), OCTET_STRING, ASN1_Tag(0));
276 encoder.end_cons();
277
278 return encoder.get_contents();
279 }
280
281/*
282* Sign a message
283*/
285 const Private_Key& key,
287 const std::vector<X509_Certificate>& chain,
288 const std::string& hash,
289 const std::string& pad_algo)
290 {
291 std::string padding = pad_algo + "(" + hash + ")";
292
294
295 PK_Signer signer(key, padding, format);
296
297 AlgorithmIdentifier sig_algo(OIDS::lookup(key.algo_name() + "/" + padding),
299
300 SecureVector<byte> signed_attr = encode_attr(data, type, hash);
301 signer.update(signed_attr);
302 SecureVector<byte> signature = signer.signature(rng);
303 signed_attr[0] = 0xA0;
304
305 const size_t SI_VERSION = cert.subject_key_id().size() ? 3 : 1;
306 const size_t CMS_VERSION = (type != "CMS.DataContent") ? 3 : SI_VERSION;
307
308 DER_Encoder encoder;
309
310 encoder.start_cons(SEQUENCE)
311 .encode(CMS_VERSION)
315 .end_cons()
316 .raw_bytes(make_econtent(data, type));
317
319 for(size_t j = 0; j != chain.size(); j++)
320 encoder.raw_bytes(chain[j].BER_encode());
321 encoder.raw_bytes(cert.BER_encode()).end_cons();
322
323 encoder.start_cons(SET)
325 .encode(SI_VERSION);
326 encode_si(encoder, cert, ((SI_VERSION == 3) ? true : false))
327 .encode(
330 )
331 .raw_bytes(signed_attr)
332 .encode(sig_algo)
333 .encode(signature, OCTET_STRING)
334 .end_cons()
335 .end_cons()
336 .end_cons();
337
338 add_layer("CMS.SignedData", encoder);
339 }
340
341/*
342* Digest a message
343*/
344void CMS_Encoder::digest(const std::string& user_hash)
345 {
346 const std::string hash = choose_algo(user_hash, "SHA-1");
347 if(!OIDS::have_oid(hash))
348 throw Encoding_Error("CMS: No OID assigned for " + hash);
349
350 const size_t VERSION = (type != "CMS.DataContent") ? 2 : 0;
351
352 DER_Encoder encoder;
353 encoder.start_cons(SEQUENCE)
354 .encode(VERSION)
357 .raw_bytes(make_econtent(data, type))
358 .encode(hash_of(data, hash), OCTET_STRING)
359 .end_cons();
360
361 add_layer("CMS.DigestedData", encoder);
362 }
363
364/*
365* MAC a message with an encrypted key
366*/
368 const std::string& mac_algo)
369 {
370 const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
371 throw Internal_Error("FIXME: unimplemented");
372 }
373
374/*
375* MAC a message with a shared key
376*/
378 const std::string& mac_algo)
379 {
380 const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
381 throw Internal_Error("FIXME: unimplemented");
382 }
383
384/*
385* MAC a message with a passphrase
386*/
387void CMS_Encoder::authenticate(const std::string&,
388 const std::string& mac_algo)
389 {
390 const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
391 throw Internal_Error("FIXME: unimplemented");
392 }
393
394}
SecureVector< byte > parameters
Definition alg_id.h:36
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
virtual std::string name() const =0
static BigInt decode(const byte buf[], size_t length, Base base=Binary)
Definition big_code.cpp:102
virtual BlockCipher * clone() const =0
virtual size_t block_size() const =0
CBC_Encryption(BlockCipher *cipher, BlockCipherModePaddingMethod *padding)
Definition cbc.cpp:17
void digest(const std::string &="")
Definition cms_ealg.cpp:344
void encrypt(RandomNumberGenerator &, const X509_Certificate &, const std::string="")
Definition cms_ealg.cpp:93
void sign(const X509_Certificate &cert, const Private_Key &key, RandomNumberGenerator &rng, const std::vector< X509_Certificate > &cert_chain, const std::string &hash, const std::string &padding)
Definition cms_ealg.cpp:284
void authenticate(const X509_Certificate &, const std::string &="")
Definition cms_ealg.cpp:367
DER_Encoder & start_explicit(u16bit type_tag)
Definition der_enc.cpp:159
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition der_enc.cpp:135
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition der_enc.cpp:188
SecureVector< byte > get_contents()
Definition der_enc.cpp:122
DER_Encoder & end_cons()
Definition der_enc.cpp:145
DER_Encoder & encode(bool b)
Definition der_enc.cpp:209
Algorithm_Factory & algorithm_factory() const
Definition libstate.cpp:173
std::string deref_alias(const std::string &alias) const
Definition libstate.cpp:162
size_t size() const
Definition secmem.h:29
SecureVector< byte > bits_of() const
Definition symkey.h:30
void update(byte in)
Definition pubkey.h:150
SecureVector< byte > signature(RandomNumberGenerator &rng)
Definition pubkey.cpp:210
virtual std::string algo_name() const =0
Key_Constraints constraints() const
Definition x509cert.cpp:225
Public_Key * subject_public_key() const
Definition x509cert.cpp:196
MemoryVector< byte > subject_key_id() const
Definition x509cert.cpp:258
MemoryVector< byte > BER_encode() const
Definition x509_obj.cpp:100
std::string lookup(const OID &oid)
Definition oids.cpp:31
bool have_oid(const std::string &name)
Definition oids.cpp:61
std::string encode(const byte der[], size_t length, const std::string &label, size_t width)
Definition pem.cpp:19
OctetString SymmetricKey
Definition symkey.h:147
std::invalid_argument Invalid_Argument
Definition exceptn.h:20
ASN1_Tag
Definition asn1_int.h:19
@ SEQUENCE
Definition asn1_int.h:35
@ CONTEXT_SPECIFIC
Definition asn1_int.h:22
@ OCTET_STRING
Definition asn1_int.h:31
@ SET
Definition asn1_int.h:36
Library_State & global_state()
OctetString InitializationVector
Definition symkey.h:152
Signature_Format
Definition pubkey.h:24
@ IEEE_1363
Definition pubkey.h:24
Key_Constraints
@ NO_CONSTRAINTS
@ KEY_AGREEMENT
@ KEY_ENCIPHERMENT
Encoding_Error(const std::string &name)
Definition exceptn.h:131
Internal_Error(const std::string &err)
Definition exceptn.h:47