Botan  1.11.15
src/lib/cert/x509/x509_obj.cpp
Go to the documentation of this file.
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 }