Botan 1.10.17

x509_obj.cpp
Go to the documentation of this file.
1 /*
2 * X.509 SIGNED Object
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7
8 #include <botan/x509_obj.h>
9 #include <botan/x509_key.h>
10 #include <botan/pubkey.h>
11 #include <botan/oids.h>
12 #include <botan/der_enc.h>
13 #include <botan/ber_dec.h>
14 #include <botan/parsing.h>
15 #include <botan/pem.h>
16 #include <algorithm>
17 #include <memory>
18
19 namespace Botan {
20
21 /*
22 * Create a generic X.509 object
23 */
24 X509_Object::X509_Object(DataSource& stream, const std::string& labels)
25 {
26 init(stream, labels);
27 }
28
29 /*
30 * Createa a generic X.509 object
31 */
32 X509_Object::X509_Object(const std::string& file, const std::string& labels)
33 {
34 DataSource_Stream stream(file, true);
35 init(stream, labels);
36 }
37
38 /*
39 * Read a PEM or BER X.509 object
40 */
41 void X509_Object::init(DataSource& in, const std::string& labels)
42 {
43 PEM_labels_allowed = split_on(labels, '/');
44 if(PEM_labels_allowed.size() < 1)
45 throw Invalid_Argument("Bad labels argument to X509_Object");
46
47 PEM_label_pref = PEM_labels_allowed[0];
48 std::sort(PEM_labels_allowed.begin(), PEM_labels_allowed.end());
49
50 try {
51 if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
52 decode_info(in);
53 else
54 {
55 std::string got_label;
56 DataSource_Memory ber(PEM_Code::decode(in, got_label));
57
58 if(!std::binary_search(PEM_labels_allowed.begin(),
59 PEM_labels_allowed.end(), got_label))
60 throw Decoding_Error("Invalid PEM label: " + got_label);
61 decode_info(ber);
62 }
63 }
64 catch(Decoding_Error& e)
65 {
66 throw Decoding_Error(PEM_label_pref + " decoding failed: " + e.what());
67 }
68 }
69
70 /*
71 * Read a BER encoded X.509 object
72 */
73 void X509_Object::decode_info(DataSource& source)
74 {
75 BER_Decoder(source)
76 .start_cons(SEQUENCE)
77 .start_cons(SEQUENCE)
78 .raw_bytes(tbs_bits)
79 .end_cons()
80 .decode(sig_algo)
81 .decode(sig, BIT_STRING)
82 .verify_end()
83 .end_cons();
84 }
85
86 /*
87 * Return a BER or PEM encoded X.509 object
88 */
89 void X509_Object::encode(Pipe& out, X509_Encoding encoding) const
90 {
91 if(encoding == PEM)
92 out.write(this->PEM_encode());
93 else
94 out.write(this->BER_encode());
95 }
96
97 /*
98 * Return a BER encoded X.509 object
99 */
100 MemoryVector<byte> X509_Object::BER_encode() const
101 {
102 return DER_Encoder()
103 .start_cons(SEQUENCE)
104 .start_cons(SEQUENCE)
105 .raw_bytes(tbs_bits)
106 .end_cons()
107 .encode(sig_algo)
108 .encode(sig, BIT_STRING)
109 .end_cons()
110 .get_contents();
111 }
112
113 /*
114 * Return a PEM encoded X.509 object
115 */
116 std::string X509_Object::PEM_encode() const
117 {
118 return PEM_Code::encode(BER_encode(), PEM_label_pref);
119 }
120
121 /*
122 * Return the TBS data
123 */
124 MemoryVector<byte> X509_Object::tbs_data() const
125 {
126 return ASN1::put_in_sequence(tbs_bits);
127 }
128
129 /*
130 * Return the signature of this object
131 */
132 MemoryVector<byte> X509_Object::signature() const
133 {
134 return sig;
135 }
136
137 /*
138 * Return the algorithm used to sign this object
139 */
140 AlgorithmIdentifier X509_Object::signature_algorithm() const
141 {
142 return sig_algo;
143 }
144
145 /*
146 * Return the hash used in generating the signature
147 */
148 std::string X509_Object::hash_used_for_signature() const
149 {
150 std::vector<std::string> sig_info =
151 split_on(OIDS::lookup(sig_algo.oid), '/');
152
153 if(sig_info.size() != 2)
154 throw Internal_Error("Invalid name format found for " +
155 sig_algo.oid.as_string());
156
157 std::vector<std::string> pad_and_hash =
158 parse_algorithm_name(sig_info[1]);
159
160 if(pad_and_hash.size() != 2)
161 throw Internal_Error("Invalid name format " + sig_info[1]);
162
163 return pad_and_hash[1];
164 }
165
166 /*
167 * Check the signature on an object
168 */
169 bool X509_Object::check_signature(Public_Key* pub_key) const
170 {
171 std::auto_ptr<Public_Key> key(pub_key);
172 return check_signature(*key);
173 }
174
175 /*
176 * Check the signature on an object
177 */
178 bool X509_Object::check_signature(Public_Key& pub_key) const
179 {
180 try {
181 std::vector<std::string> sig_info =
182 split_on(OIDS::lookup(sig_algo.oid), '/');
183
184 if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
185 return false;
186
187 std::string padding = sig_info[1];
188 Signature_Format format =
189 (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
190
191 PK_Verifier verifier(pub_key, padding, format);
192
193 return verifier.verify_message(tbs_data(), signature());
194 }
195 catch(...)
196 {
197 return false;
198 }
199 }
200
201 /*
202 * Apply the X.509 SIGNED macro
203 */
204 MemoryVector<byte> X509_Object::make_signed(PK_Signer* signer,
205 RandomNumberGenerator& rng,
206 const AlgorithmIdentifier& algo,
207 const MemoryRegion<byte>& tbs_bits)
208 {
209 return DER_Encoder()
210 .start_cons(SEQUENCE)
211 .raw_bytes(tbs_bits)
212 .encode(algo)
213 .encode(signer->sign_message(tbs_bits, rng), BIT_STRING)
214 .end_cons()
215 .get_contents();
216 }
217
218 /*
219 * Try to decode the actual information
220 */
221 void X509_Object::do_decode()
222 {
223 try {
224 force_decode();
225 }
226 catch(Decoding_Error& e)
227 {
228 throw Decoding_Error(PEM_label_pref + " decoding failed (" +
229 e.what() + ")");
230 }
231 catch(Invalid_Argument& e)
232 {
233 throw Decoding_Error(PEM_label_pref + " decoding failed (" +
234 e.what() + ")");
235 }
236 }
237
238 }
Botan::parse_algorithm_name
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:96
Botan::DataSource_Stream
Definition: data_src.h:128
Botan::DER_Encoder::get_contents
SecureVector< byte > get_contents()
Definition: der_enc.cpp:122
Botan::X509_Object::tbs_bits
MemoryVector< byte > tbs_bits
Definition: x509_obj.h:102
Botan::X509_Object::tbs_data
MemoryVector< byte > tbs_data() const
Definition: x509_obj.cpp:124
Botan::DER_Encoder::raw_bytes
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition: der_enc.cpp:188
Botan::RandomNumberGenerator
Definition: rng.h:20
Botan::Pipe::write
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:34
Botan::OID::as_string
std::string as_string() const
Definition: asn1_oid.cpp:50
Botan::Signature_Format
Signature_Format
Definition: pubkey.h:24
Botan::Internal_Error
Definition: exceptn.h:45
Botan::split_on
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:152
Botan::X509_Encoding
X509_Encoding
Definition: pubkey_enums.h:67
Botan::Public_Key::algo_name
virtual std::string algo_name() const =0
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::ASN1::maybe_BER
bool maybe_BER(DataSource &source)
Definition: asn1_int.cpp:55
Botan::DER_Encoder::end_cons
DER_Encoder & end_cons()
Definition: der_enc.cpp:145
Botan::DataSource
Definition: data_src.h:20
Botan::X509_Object::check_signature
bool check_signature(class Public_Key &key) const
Definition: x509_obj.cpp:178
Botan::X509_Object::BER_encode
MemoryVector< byte > BER_encode() const
Definition: x509_obj.cpp:100
Botan::PEM_Code::decode
SecureVector< byte > decode(DataSource &source, std::string &label)
Definition: pem.cpp:56
Botan::DER_Encoder::encode
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:209
Botan::DER_Encoder
Definition: der_enc.h:22
Botan::X509_Object::signature_algorithm
AlgorithmIdentifier signature_algorithm() const
Definition: x509_obj.cpp:140
Botan::PK_Signer::sign_message
SecureVector< byte > sign_message(const byte in[], size_t length, RandomNumberGenerator &rng)
Definition: pubkey.cpp:160
Botan::X509_Object::sig_algo
AlgorithmIdentifier sig_algo
Definition: x509_obj.h:101
Botan::X509_Object::X509_Object
X509_Object()
Definition: x509_obj.h:100
Botan::X509_Object::do_decode
void do_decode()
Definition: x509_obj.cpp:221
Botan::OIDS::lookup
std::string lookup(const OID &oid)
Definition: oids.cpp:31
Botan::AlgorithmIdentifier::oid
OID oid
Definition: alg_id.h:35
Botan::PK_Verifier::verify_message
bool verify_message(const byte msg[], size_t msg_length, const byte sig[], size_t sig_length)
Definition: pubkey.cpp:283
Botan::X509_Object::signature
MemoryVector< byte > signature() const
Definition: x509_obj.cpp:132
Botan::Decoding_Error
Definition: exceptn.h:138
Botan::SEQUENCE
Definition: asn1_int.h:35
Botan::MemoryRegion< byte >
Botan
Definition: algo_base.h:14
Botan::PEM
Definition: pubkey_enums.h:67
Botan::PK_Verifier
Definition: pubkey.h:211
Botan::MemoryVector< byte >
Botan::PEM_Code::matches
bool matches(DataSource &source, const std::string &extra, size_t search_range)
Definition: pem.cpp:116
Botan::X509_Object::make_signed
static MemoryVector< byte > make_signed(class PK_Signer *signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, const MemoryRegion< byte > &tbs)
Definition: x509_obj.cpp:204
Botan::Public_Key
Definition: pk_keys.h:21
Botan::IEEE_1363
Definition: pubkey.h:24
Botan::X509_Object::sig
MemoryVector< byte > sig
Definition: x509_obj.h:102
Botan::ASN1::put_in_sequence
SecureVector< byte > put_in_sequence(const MemoryRegion< byte > &contents)
Definition: asn1_int.cpp:34
Botan::X509_Object::hash_used_for_signature
std::string hash_used_for_signature() const
Definition: x509_obj.cpp:148
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::BIT_STRING
Definition: asn1_int.h:30
Botan::DataSource_Memory
Definition: data_src.h:94
Botan::X509_Object::encode
void encode(Pipe &out, X509_Encoding encoding=PEM) const
Definition: x509_obj.cpp:89
Botan::AlgorithmIdentifier
Definition: alg_id.h:20
Botan::DER_Encoder::start_cons
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:135
Botan::DER_SEQUENCE
Definition: pubkey.h:24
Botan::Pipe
Definition: pipe.h:25
Botan::PK_Signer
Definition: pubkey.h:123
Botan::X509_Object::PEM_encode
std::string PEM_encode() const
Definition: x509_obj.cpp:116
Botan::Public_Key::message_parts
virtual size_t message_parts() const
Definition: pk_keys.h:50