Botan
1.11.15
|
00001 /* 00002 * X.509 SIGNED Object 00003 * (C) 1999-2007 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/x509_obj.h> 00009 #include <botan/x509_key.h> 00010 #include <botan/pubkey.h> 00011 #include <botan/oids.h> 00012 #include <botan/der_enc.h> 00013 #include <botan/ber_dec.h> 00014 #include <botan/parsing.h> 00015 #include <botan/pem.h> 00016 #include <algorithm> 00017 00018 namespace Botan { 00019 00020 /* 00021 * Create a generic X.509 object 00022 */ 00023 X509_Object::X509_Object(DataSource& stream, const std::string& labels) 00024 { 00025 init(stream, labels); 00026 } 00027 00028 /* 00029 * Create a generic X.509 object 00030 */ 00031 X509_Object::X509_Object(const std::string& file, const std::string& labels) 00032 { 00033 DataSource_Stream stream(file, true); 00034 init(stream, labels); 00035 } 00036 00037 /* 00038 * Create a generic X.509 object 00039 */ 00040 X509_Object::X509_Object(const std::vector<byte>& vec, const std::string& labels) 00041 { 00042 DataSource_Memory stream(&vec[0], vec.size()); 00043 init(stream, labels); 00044 } 00045 00046 /* 00047 * Read a PEM or BER X.509 object 00048 */ 00049 void X509_Object::init(DataSource& in, const std::string& labels) 00050 { 00051 PEM_labels_allowed = split_on(labels, '/'); 00052 if(PEM_labels_allowed.size() < 1) 00053 throw Invalid_Argument("Bad labels argument to X509_Object"); 00054 00055 PEM_label_pref = PEM_labels_allowed[0]; 00056 std::sort(PEM_labels_allowed.begin(), PEM_labels_allowed.end()); 00057 00058 try { 00059 if(ASN1::maybe_BER(in) && !PEM_Code::matches(in)) 00060 { 00061 BER_Decoder dec(in); 00062 decode_from(dec); 00063 } 00064 else 00065 { 00066 std::string got_label; 00067 DataSource_Memory ber(PEM_Code::decode(in, got_label)); 00068 00069 if(!std::binary_search(PEM_labels_allowed.begin(), 00070 PEM_labels_allowed.end(), got_label)) 00071 throw Decoding_Error("Invalid PEM label: " + got_label); 00072 00073 BER_Decoder dec(ber); 00074 decode_from(dec); 00075 } 00076 } 00077 catch(Decoding_Error& e) 00078 { 00079 throw Decoding_Error(PEM_label_pref + " decoding failed: " + e.what()); 00080 } 00081 } 00082 00083 00084 void X509_Object::encode_into(DER_Encoder& to) const 00085 { 00086 to.start_cons(SEQUENCE) 00087 .start_cons(SEQUENCE) 00088 .raw_bytes(tbs_bits) 00089 .end_cons() 00090 .encode(sig_algo) 00091 .encode(sig, BIT_STRING) 00092 .end_cons(); 00093 } 00094 00095 /* 00096 * Read a BER encoded X.509 object 00097 */ 00098 void X509_Object::decode_from(BER_Decoder& from) 00099 { 00100 from.start_cons(SEQUENCE) 00101 .start_cons(SEQUENCE) 00102 .raw_bytes(tbs_bits) 00103 .end_cons() 00104 .decode(sig_algo) 00105 .decode(sig, BIT_STRING) 00106 .verify_end() 00107 .end_cons(); 00108 } 00109 00110 /* 00111 * Return a BER encoded X.509 object 00112 */ 00113 std::vector<byte> X509_Object::BER_encode() const 00114 { 00115 DER_Encoder der; 00116 encode_into(der); 00117 return der.get_contents_unlocked(); 00118 } 00119 00120 /* 00121 * Return a PEM encoded X.509 object 00122 */ 00123 std::string X509_Object::PEM_encode() const 00124 { 00125 return PEM_Code::encode(BER_encode(), PEM_label_pref); 00126 } 00127 00128 /* 00129 * Return the TBS data 00130 */ 00131 std::vector<byte> X509_Object::tbs_data() const 00132 { 00133 return ASN1::put_in_sequence(tbs_bits); 00134 } 00135 00136 /* 00137 * Return the signature of this object 00138 */ 00139 std::vector<byte> X509_Object::signature() const 00140 { 00141 return sig; 00142 } 00143 00144 /* 00145 * Return the algorithm used to sign this object 00146 */ 00147 AlgorithmIdentifier X509_Object::signature_algorithm() const 00148 { 00149 return sig_algo; 00150 } 00151 00152 /* 00153 * Return the hash used in generating the signature 00154 */ 00155 std::string X509_Object::hash_used_for_signature() const 00156 { 00157 std::vector<std::string> sig_info = 00158 split_on(OIDS::lookup(sig_algo.oid), '/'); 00159 00160 if(sig_info.size() != 2) 00161 throw Internal_Error("Invalid name format found for " + 00162 sig_algo.oid.as_string()); 00163 00164 std::vector<std::string> pad_and_hash = 00165 parse_algorithm_name(sig_info[1]); 00166 00167 if(pad_and_hash.size() != 2) 00168 throw Internal_Error("Invalid name format " + sig_info[1]); 00169 00170 return pad_and_hash[1]; 00171 } 00172 00173 /* 00174 * Check the signature on an object 00175 */ 00176 bool X509_Object::check_signature(const Public_Key* pub_key) const 00177 { 00178 if(!pub_key) 00179 throw std::runtime_error("No key provided for " + PEM_label_pref + " signature check"); 00180 std::unique_ptr<const Public_Key> key(pub_key); 00181 return check_signature(*key); 00182 } 00183 00184 /* 00185 * Check the signature on an object 00186 */ 00187 bool X509_Object::check_signature(const Public_Key& pub_key) const 00188 { 00189 try { 00190 std::vector<std::string> sig_info = 00191 split_on(OIDS::lookup(sig_algo.oid), '/'); 00192 00193 if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) 00194 return false; 00195 00196 std::string padding = sig_info[1]; 00197 Signature_Format format = 00198 (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; 00199 00200 PK_Verifier verifier(pub_key, padding, format); 00201 00202 return verifier.verify_message(tbs_data(), signature()); 00203 } 00204 catch(std::exception& e) 00205 { 00206 return false; 00207 } 00208 } 00209 00210 /* 00211 * Apply the X.509 SIGNED macro 00212 */ 00213 std::vector<byte> X509_Object::make_signed(PK_Signer* signer, 00214 RandomNumberGenerator& rng, 00215 const AlgorithmIdentifier& algo, 00216 const secure_vector<byte>& tbs_bits) 00217 { 00218 return DER_Encoder() 00219 .start_cons(SEQUENCE) 00220 .raw_bytes(tbs_bits) 00221 .encode(algo) 00222 .encode(signer->sign_message(tbs_bits, rng), BIT_STRING) 00223 .end_cons() 00224 .get_contents_unlocked(); 00225 } 00226 00227 /* 00228 * Try to decode the actual information 00229 */ 00230 void X509_Object::do_decode() 00231 { 00232 try { 00233 force_decode(); 00234 } 00235 catch(Decoding_Error& e) 00236 { 00237 throw Decoding_Error(PEM_label_pref + " decoding failed (" + 00238 e.what() + ")"); 00239 } 00240 catch(Invalid_Argument& e) 00241 { 00242 throw Decoding_Error(PEM_label_pref + " decoding failed (" + 00243 e.what() + ")"); 00244 } 00245 } 00246 00247 }