diff options
Diffstat (limited to 'src/lib/x509/pkcs10.cpp')
-rw-r--r-- | src/lib/x509/pkcs10.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/src/lib/x509/pkcs10.cpp b/src/lib/x509/pkcs10.cpp new file mode 100644 index 000000000..ccd22454b --- /dev/null +++ b/src/lib/x509/pkcs10.cpp @@ -0,0 +1,210 @@ +/* +* PKCS #10 +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/pkcs10.h> +#include <botan/x509_ext.h> +#include <botan/x509cert.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/parsing.h> +#include <botan/oids.h> +#include <botan/pem.h> + +namespace Botan { + +/* +* PKCS10_Request Constructor +*/ +PKCS10_Request::PKCS10_Request(DataSource& in) : + X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") + { + do_decode(); + } + +#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) +/* +* PKCS10_Request Constructor +*/ +PKCS10_Request::PKCS10_Request(const std::string& fsname) : + X509_Object(fsname, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") + { + do_decode(); + } +#endif + +/* +* PKCS10_Request Constructor +*/ +PKCS10_Request::PKCS10_Request(const std::vector<byte>& in) : + X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") + { + do_decode(); + } + +/* +* Deocde the CertificateRequestInfo +*/ +void PKCS10_Request::force_decode() + { + BER_Decoder cert_req_info(m_tbs_bits); + + size_t version; + cert_req_info.decode(version); + if(version != 0) + throw Decoding_Error("Unknown version code in PKCS #10 request: " + + std::to_string(version)); + + X509_DN dn_subject; + cert_req_info.decode(dn_subject); + + m_info.add(dn_subject.contents()); + + BER_Object public_key = cert_req_info.get_next_object(); + if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED) + throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key", + public_key.type_tag, public_key.class_tag); + + m_info.add("X509.Certificate.public_key", + PEM_Code::encode( + ASN1::put_in_sequence(unlock(public_key.value)), + "PUBLIC KEY" + ) + ); + + BER_Object attr_bits = cert_req_info.get_next_object(); + + if(attr_bits.type_tag == 0 && + attr_bits.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) + { + BER_Decoder attributes(attr_bits.value); + while(attributes.more_items()) + { + Attribute attr; + attributes.decode(attr); + handle_attribute(attr); + } + attributes.verify_end(); + } + else if(attr_bits.type_tag != NO_OBJECT) + throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes", + attr_bits.type_tag, attr_bits.class_tag); + + cert_req_info.verify_end(); + + if(!this->check_signature(subject_public_key())) + throw Decoding_Error("PKCS #10 request: Bad signature detected"); + } + +/* +* Handle attributes in a PKCS #10 request +*/ +void PKCS10_Request::handle_attribute(const Attribute& attr) + { + BER_Decoder value(attr.parameters); + + if(attr.oid == OIDS::lookup("PKCS9.EmailAddress")) + { + ASN1_String email; + value.decode(email); + m_info.add("RFC822", email.value()); + } + else if(attr.oid == OIDS::lookup("PKCS9.ChallengePassword")) + { + ASN1_String challenge_password; + value.decode(challenge_password); + m_info.add("PKCS9.ChallengePassword", challenge_password.value()); + } + else if(attr.oid == OIDS::lookup("PKCS9.ExtensionRequest")) + { + Extensions extensions; + value.decode(extensions).verify_end(); + + Data_Store issuer_info; + extensions.contents_to(m_info, issuer_info); + } + } + +/* +* Return the challenge password (if any) +*/ +std::string PKCS10_Request::challenge_password() const + { + return m_info.get1("PKCS9.ChallengePassword"); + } + +/* +* Return the name of the requestor +*/ +X509_DN PKCS10_Request::subject_dn() const + { + return create_dn(m_info); + } + +/* +* Return the public key of the requestor +*/ +std::vector<byte> PKCS10_Request::raw_public_key() const + { + DataSource_Memory source(m_info.get1("X509.Certificate.public_key")); + return unlock(PEM_Code::decode_check_label(source, "PUBLIC KEY")); + } + +/* +* Return the public key of the requestor +*/ +Public_Key* PKCS10_Request::subject_public_key() const + { + DataSource_Memory source(m_info.get1("X509.Certificate.public_key")); + return X509::load_key(source); + } + +/* +* Return the alternative names of the requestor +*/ +AlternativeName PKCS10_Request::subject_alt_name() const + { + return create_alt_name(m_info); + } + +/* +* Return the key constraints (if any) +*/ +Key_Constraints PKCS10_Request::constraints() const + { + return Key_Constraints(m_info.get1_u32bit("X509v3.KeyUsage", NO_CONSTRAINTS)); + } + +/* +* Return the extendend key constraints (if any) +*/ +std::vector<OID> PKCS10_Request::ex_constraints() const + { + std::vector<std::string> oids = m_info.get("X509v3.ExtendedKeyUsage"); + + std::vector<OID> result; + for(size_t i = 0; i != oids.size(); ++i) + result.push_back(OID(oids[i])); + return result; + } + +/* +* Return is a CA certificate is requested +*/ +bool PKCS10_Request::is_CA() const + { + return (m_info.get1_u32bit("X509v3.BasicConstraints.is_ca") > 0); + } + +/* +* Return the desired path limit (if any) +*/ +u32bit PKCS10_Request::path_limit() const + { + return m_info.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0); + } + +} |