Botan: src/cms/cms_algo.cpp Source File

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
19 namespace Botan {
20
21 namespace {
22
23 /*
24 * Wrap a key as specified in RFC 3217
25 */
26 SecureVector<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
52 Algorithm_Factory& af = global_state().algorithm_factory();
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 */
81 SecureVector<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 */
116 SecureVector<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 */
149 SymmetricKey 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 }
Botan::Library_State::algorithm_factory
Algorithm_Factory & algorithm_factory() const
Definition: libstate.cpp:173
Botan::Algorithm_Factory::prototype_block_cipher
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:193
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::SymmetricKey
OctetString SymmetricKey
Definition: symkey.h:147
Botan::OCTET_STRING
Definition: asn1_int.h:31
Botan::Global_State_Management::global_state
Library_State & global_state()
Definition: global_state.cpp:32
Botan::SEQUENCE
Definition: asn1_int.h:35
Botan
Definition: algo_base.h:14
Botan::PEM_Code::encode
std::string encode(const byte der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:19
Botan::RC2::EKB_code
static byte EKB_code(size_t bits)
Definition: rc2.cpp:144
Botan::InitializationVector
OctetString InitializationVector
Definition: symkey.h:152
Botan::OctetString::set_odd_parity
void set_odd_parity()
Definition: symkey.cpp:47