Botan 1.10.17
cms_algo.cpp
Go to the documentation of this file.
1/*
2* CMS Algorithm Specific Code
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/der_enc.h>
10#include <botan/sha160.h>
11#include <botan/cbc.h>
12#include <botan/filters.h>
13#include <botan/libstate.h>
14
15#if defined(BOTAN_HAS_RC2)
16 #include <botan/rc2.h>
17#endif
18
19namespace Botan {
20
21namespace {
22
23/*
24* Wrap a key as specified in RFC 3217
25*/
26SecureVector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng,
27 const std::string& cipher_name,
28 const SymmetricKey& kek,
29 const SecureVector<byte>& input)
30 {
31 class Flip_Bytes : public Filter
32 {
33 public:
34 std::string name() const { return "Fip_Bytes"; }
35
36 void write(const byte data[], size_t length)
37 {
38 buf += std::make_pair(data, length);
39 }
40 void end_msg()
41 {
42 for(size_t j = 0; j != buf.size(); j++)
43 send(buf[buf.size()-j-1]);
44 buf.clear();
45 }
46
47 Flip_Bytes(const SecureVector<byte>& prefix) : buf(prefix) {}
48 private:
49 SecureVector<byte> buf;
50 };
51
53
54 const BlockCipher* cipher = af.prototype_block_cipher(cipher_name);
55
56 if(!cipher || cipher->block_size() != 8)
57 throw Encoding_Error("do_rfc3217_wrap: Bad cipher: " + cipher_name);
58
59 Pipe icv(new Hash_Filter(new SHA_160, 8));
60 icv.process_msg(input);
61
62 InitializationVector iv(rng, 8);
63 InitializationVector fixed("4ADDA22C79E82105");
64
65 Pipe pipe(new CBC_Encryption(cipher->clone(), new Null_Padding, kek, iv),
66 new Flip_Bytes(iv.bits_of()),
67 new CBC_Encryption(cipher->clone(), new Null_Padding, kek, iv));
68
69 pipe.start_msg();
70 pipe.write(input);
71 pipe.write(icv.read_all());
72 pipe.end_msg();
73 return pipe.read_all();
74 }
75
76}
77
78/*
79* Wrap a CEK with a KEK
80*/
81SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng,
82 const std::string& cipher,
83 const SymmetricKey& cek,
84 const SymmetricKey& kek)
85 {
86#if defined(BOTAN_HAS_DES)
87 if(cipher == "TripleDES")
88 {
89 SymmetricKey cek_parity = cek;
90 cek_parity.set_odd_parity();
91 return do_rfc3217_wrap(rng, cipher, kek, cek_parity.bits_of());
92 }
93#endif
94
95#if defined(BOTAN_HAS_RC2) || defined(BOTAN_HAS_CAST)
96 if(cipher == "RC2" || cipher == "CAST-128")
97 {
98 if(kek.length() != 16)
99 throw Encoding_Error("CMS: 128-bit KEKs must be used with " + cipher);
100
101 SecureVector<byte> lcekpad;
102 lcekpad.push_back(static_cast<byte>(cek.length()));
103 lcekpad += cek.bits_of();
104 while(lcekpad.size() % 8)
105 lcekpad.push_back(rng.next_byte());
106 return do_rfc3217_wrap(rng, cipher, kek, lcekpad);
107 }
108#endif
109
110 throw Invalid_Argument("CMS_Encoder::wrap: Unknown cipher " + cipher);
111 }
112
113/*
114* Encode the parameters for an encryption algo
115*/
116SecureVector<byte> CMS_Encoder::encode_params(const std::string& cipher,
117 const SymmetricKey& key,
118 const InitializationVector& iv)
119 {
120 DER_Encoder encoder;
121
122#if defined(BOTAN_HAS_RC2)
123 if(cipher == "RC2")
124 {
125 encoder.start_cons(SEQUENCE).
126 encode(static_cast<size_t>(RC2::EKB_code(8*key.length()))).
127 encode(iv.bits_of(), OCTET_STRING).
128 end_cons();
129 return encoder.get_contents();
130 }
131#endif
132
133 if(cipher == "CAST-128")
134 {
135 encoder.start_cons(SEQUENCE).
136 encode(iv.bits_of(), OCTET_STRING).
137 encode(8*key.length()).
138 end_cons();
139 }
140 else
141 encoder.encode(iv.bits_of(), OCTET_STRING);
142
143 return encoder.get_contents();
144 }
145
146/*
147* Generate a CEK or KEK for the cipher
148*/
149SymmetricKey CMS_Encoder::setup_key(RandomNumberGenerator& rng,
150 const std::string& cipher)
151 {
152 size_t keysize = 0;
153
154 if(cipher == "TripleDES") keysize = 24;
155 if(cipher == "RC2") keysize = 16;
156 if(cipher == "CAST-128") keysize = 16;
157
158 if(keysize == 0)
159 throw Invalid_Argument("CMS: Cannot encrypt with cipher " + cipher);
160
161 SymmetricKey key(rng, keysize);
162 if(cipher == "DES" || cipher == "TripleDES")
163 key.set_odd_parity();
164 return key;
165 }
166
167}
CBC_Encryption(BlockCipher *cipher, BlockCipherModePaddingMethod *padding)
Definition cbc.cpp:17
Hash_Filter(HashFunction *hash_fun, size_t len=0)
Definition filters.h:120
Algorithm_Factory & algorithm_factory() const
Definition libstate.cpp:173
void set_odd_parity()
Definition symkey.cpp:47
static byte EKB_code(size_t bits)
Definition rc2.cpp:144
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
@ SEQUENCE
Definition asn1_int.h:35
@ OCTET_STRING
Definition asn1_int.h:31
Library_State & global_state()
OctetString InitializationVector
Definition symkey.h:152
Encoding_Error(const std::string &name)
Definition exceptn.h:131