aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/x509/x509_obj.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-11-03 10:30:13 -0400
committerJack Lloyd <[email protected]>2016-11-03 10:30:13 -0400
commit341fd32b46363cad4c2caee3fca166695100ba07 (patch)
tree89a98aa28a431f2625268cf61e7adf903fd24a98 /src/lib/x509/x509_obj.cpp
parent1e72720661383466807ac496b941af41d756a2ce (diff)
Move cert/x509 to top level and pem and pbes2 to pubkey.
The `cert` dir was just an artifact of having previously supported CVC (smartcard cert format), removed a long time ago. The pem and pbes2 code is directly related to the pubkey code, in fact the only caller of pbes2 (likely anywhere, not just in the library) is in pkcs8.cpp
Diffstat (limited to 'src/lib/x509/x509_obj.cpp')
-rw-r--r--src/lib/x509/x509_obj.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/lib/x509/x509_obj.cpp b/src/lib/x509/x509_obj.cpp
new file mode 100644
index 000000000..3c5d2a9b4
--- /dev/null
+++ b/src/lib/x509/x509_obj.cpp
@@ -0,0 +1,249 @@
+/*
+* X.509 SIGNED Object
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/x509_obj.h>
+#include <botan/x509_key.h>
+#include <botan/pubkey.h>
+#include <botan/oids.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/parsing.h>
+#include <botan/pem.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Create a generic X.509 object
+*/
+X509_Object::X509_Object(DataSource& stream, const std::string& labels)
+ {
+ init(stream, labels);
+ }
+
+#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
+/*
+* Create a generic X.509 object
+*/
+X509_Object::X509_Object(const std::string& file, const std::string& labels)
+ {
+ DataSource_Stream stream(file, true);
+ init(stream, labels);
+ }
+#endif
+
+/*
+* Create a generic X.509 object
+*/
+X509_Object::X509_Object(const std::vector<byte>& vec, const std::string& labels)
+ {
+ DataSource_Memory stream(vec.data(), vec.size());
+ init(stream, labels);
+ }
+
+/*
+* Read a PEM or BER X.509 object
+*/
+void X509_Object::init(DataSource& in, const std::string& labels)
+ {
+ m_PEM_labels_allowed = split_on(labels, '/');
+ if(m_PEM_labels_allowed.size() < 1)
+ throw Invalid_Argument("Bad labels argument to X509_Object");
+
+ m_PEM_label_pref = m_PEM_labels_allowed[0];
+ std::sort(m_PEM_labels_allowed.begin(), m_PEM_labels_allowed.end());
+
+ try {
+ if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
+ {
+ BER_Decoder dec(in);
+ decode_from(dec);
+ }
+ else
+ {
+ std::string got_label;
+ DataSource_Memory ber(PEM_Code::decode(in, got_label));
+
+ if(!std::binary_search(m_PEM_labels_allowed.begin(),
+ m_PEM_labels_allowed.end(), got_label))
+ throw Decoding_Error("Invalid PEM label: " + got_label);
+
+ BER_Decoder dec(ber);
+ decode_from(dec);
+ }
+ }
+ catch(Decoding_Error& e)
+ {
+ throw Decoding_Error(m_PEM_label_pref + " decoding failed: " + e.what());
+ }
+ }
+
+
+void X509_Object::encode_into(DER_Encoder& to) const
+ {
+ to.start_cons(SEQUENCE)
+ .start_cons(SEQUENCE)
+ .raw_bytes(m_tbs_bits)
+ .end_cons()
+ .encode(m_sig_algo)
+ .encode(m_sig, BIT_STRING)
+ .end_cons();
+ }
+
+/*
+* Read a BER encoded X.509 object
+*/
+void X509_Object::decode_from(BER_Decoder& from)
+ {
+ from.start_cons(SEQUENCE)
+ .start_cons(SEQUENCE)
+ .raw_bytes(m_tbs_bits)
+ .end_cons()
+ .decode(m_sig_algo)
+ .decode(m_sig, BIT_STRING)
+ .verify_end()
+ .end_cons();
+ }
+
+/*
+* Return a BER encoded X.509 object
+*/
+std::vector<byte> X509_Object::BER_encode() const
+ {
+ DER_Encoder der;
+ encode_into(der);
+ return der.get_contents_unlocked();
+ }
+
+/*
+* Return a PEM encoded X.509 object
+*/
+std::string X509_Object::PEM_encode() const
+ {
+ return PEM_Code::encode(BER_encode(), m_PEM_label_pref);
+ }
+
+/*
+* Return the TBS data
+*/
+std::vector<byte> X509_Object::tbs_data() const
+ {
+ return ASN1::put_in_sequence(m_tbs_bits);
+ }
+
+/*
+* Return the signature of this object
+*/
+std::vector<byte> X509_Object::signature() const
+ {
+ return m_sig;
+ }
+
+/*
+* Return the algorithm used to sign this object
+*/
+AlgorithmIdentifier X509_Object::signature_algorithm() const
+ {
+ return m_sig_algo;
+ }
+
+/*
+* Return the hash used in generating the signature
+*/
+std::string X509_Object::hash_used_for_signature() const
+ {
+ std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(m_sig_algo.oid), '/');
+
+ if(sig_info.size() != 2)
+ throw Internal_Error("Invalid name format found for " +
+ m_sig_algo.oid.as_string());
+
+ std::vector<std::string> pad_and_hash =
+ parse_algorithm_name(sig_info[1]);
+
+ if(pad_and_hash.size() != 2)
+ throw Internal_Error("Invalid name format " + sig_info[1]);
+
+ return pad_and_hash[1];
+ }
+
+/*
+* Check the signature on an object
+*/
+bool X509_Object::check_signature(const Public_Key* pub_key) const
+ {
+ if(!pub_key)
+ throw Exception("No key provided for " + m_PEM_label_pref + " signature check");
+ std::unique_ptr<const Public_Key> key(pub_key);
+ return check_signature(*key);
+}
+
+/*
+* Check the signature on an object
+*/
+bool X509_Object::check_signature(const Public_Key& pub_key) const
+ {
+ try {
+ std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(m_sig_algo.oid), '/');
+
+ if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
+ return false;
+
+ std::string padding = sig_info[1];
+ Signature_Format format =
+ (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+
+ PK_Verifier verifier(pub_key, padding, format);
+
+ return verifier.verify_message(tbs_data(), signature());
+ }
+ catch(std::exception&)
+ {
+ return false;
+ }
+ }
+
+/*
+* Apply the X.509 SIGNED macro
+*/
+std::vector<byte> X509_Object::make_signed(PK_Signer* signer,
+ RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& algo,
+ const secure_vector<byte>& tbs_bits)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .raw_bytes(tbs_bits)
+ .encode(algo)
+ .encode(signer->sign_message(tbs_bits, rng), BIT_STRING)
+ .end_cons()
+ .get_contents_unlocked();
+ }
+
+/*
+* Try to decode the actual information
+*/
+void X509_Object::do_decode()
+ {
+ try {
+ force_decode();
+ }
+ catch(Decoding_Error& e)
+ {
+ throw Decoding_Error(m_PEM_label_pref + " decoding failed (" +
+ e.what() + ")");
+ }
+ catch(Invalid_Argument& e)
+ {
+ throw Decoding_Error(m_PEM_label_pref + " decoding failed (" +
+ e.what() + ")");
+ }
+ }
+
+}