Botan  1.10.9
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 
19 namespace Botan {
20 
21 namespace {
22 
23 /*
24 * Choose an algorithm
25 */
26 std::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 */
37 DER_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 */
56 SecureVector<byte> hash_of(const SecureVector<byte>& content,
57  const std::string& hash_name)
58  {
59  Algorithm_Factory& af = global_state().algorithm_factory();
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 */
67 SecureVector<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 */
125 void 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))
144  .start_cons(SET)
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 */
161 void 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 */
247 SecureVector<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 
293  Signature_Format format = IEEE_1363;
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)
312  .start_cons(SET)
315  .end_cons()
316  .raw_bytes(make_econtent(data, type));
317 
318  encoder.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC);
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 */
344 void 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 */
387 void 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 > get_contents()
Definition: der_enc.cpp:122
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition: der_enc.cpp:188
SecureVector< byte > signature(RandomNumberGenerator &rng)
Definition: pubkey.cpp:210
Signature_Format
Definition: pubkey.h:24
virtual BlockCipher * clone() const =0
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
Key_Constraints constraints() const
Definition: x509cert.cpp:225
virtual std::string algo_name() const =0
void digest(const std::string &="")
Definition: cms_ealg.cpp:344
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
DER_Encoder & start_explicit(u16bit type_tag)
Definition: der_enc.cpp:159
DER_Encoder & end_cons()
Definition: der_enc.cpp:145
void encrypt(RandomNumberGenerator &, const X509_Certificate &, const std::string="")
Definition: cms_ealg.cpp:93
Algorithm_Factory & algorithm_factory() const
Definition: libstate.cpp:173
OctetString SymmetricKey
Definition: symkey.h:147
SecureVector< byte > bits_of() const
Definition: symkey.h:30
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:209
RandomNumberGenerator * rng
Definition: global_rng.cpp:165
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
MessageAuthenticationCode * mac
Definition: fpe_fe1.cpp:94
Library_State & global_state()
std::string lookup(const OID &oid)
Definition: oids.cpp:31
ASN1_Tag
Definition: asn1_int.h:19
std::string deref_alias(const std::string &alias) const
Definition: libstate.cpp:162
size_t size() const
Definition: secmem.h:29
virtual std::string name() const =0
MemoryVector< byte > subject_key_id() const
Definition: x509cert.cpp:258
std::string encode(const byte der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:19
static BigInt decode(const byte buf[], size_t length, Base base=Binary)
Definition: big_code.cpp:102
MemoryVector< byte > BER_encode() const
Definition: x509_obj.cpp:100
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:135
std::string cipher_name
Definition: ossl_bc.cpp:42
Public_Key * subject_public_key() const
Definition: x509cert.cpp:196
bool have_oid(const std::string &name)
Definition: oids.cpp:61
Key_Constraints
Definition: pubkey_enums.h:18
void authenticate(const X509_Certificate &, const std::string &="")
Definition: cms_ealg.cpp:367
virtual size_t block_size() const =0
void update(byte in)
Definition: pubkey.h:150