diff options
Diffstat (limited to 'src/pkcs10.cpp')
-rw-r--r-- | src/pkcs10.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/src/pkcs10.cpp b/src/pkcs10.cpp new file mode 100644 index 000000000..a567f5a00 --- /dev/null +++ b/src/pkcs10.cpp @@ -0,0 +1,228 @@ +/************************************************* +* PKCS #10 Source File * +* (C) 1999-2006 The Botan Project * +*************************************************/ + +#include <botan/pkcs10.h> +#include <botan/asn1_int.h> +#include <botan/parsing.h> +#include <botan/x509stor.h> +#include <botan/oids.h> + +namespace Botan { + +/************************************************* +* PKCS10_Request Constructor * +*************************************************/ +PKCS10_Request::PKCS10_Request(DataSource& in) : + X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") + { + is_ca = false; + max_path_len = 0; + constraints_value = NO_CONSTRAINTS; + + do_decode(); + } + +/************************************************* +* PKCS10_Request Constructor * +*************************************************/ +PKCS10_Request::PKCS10_Request(const std::string& in) : + X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") + { + is_ca = false; + max_path_len = 0; + + do_decode(); + } + +/************************************************* +* Deocde the CertificateRequestInfo * +*************************************************/ +void PKCS10_Request::force_decode() + { + BER_Decoder cert_req_info(tbs_bits); + + u32bit version; + cert_req_info.decode(version); + if(version != 0) + throw Decoding_Error("Unknown version code in PKCS #10 request: " + + to_string(version)); + + BER::decode(cert_req_info, dn); + + 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); + pub_key = ASN1::put_in_sequence(public_key.value); + + 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; + BER::decode(attributes, 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(); + + std::vector<std::string> emails = dn.get_attribute("PKCS9.EmailAddress"); + for(u32bit j = 0; j != emails.size(); ++j) + subject_alt.add_attribute("RFC822", emails[j]); + + X509_Code sig_check = X509_Store::check_sig(*this, subject_public_key()); + if(sig_check != VERIFIED) + 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; + BER::decode(value, email); + subject_alt.add_attribute("RFC822", email.value()); + } + else if(attr.oid == OIDS::lookup("PKCS9.ChallengePassword")) + { + ASN1_String challenge_password; + BER::decode(value, challenge_password); + challenge = challenge_password.value(); + } + else if(attr.oid == OIDS::lookup("PKCS9.ExtensionRequest")) + { + BER_Decoder sequence = BER::get_subsequence(value); + + while(sequence.more_items()) + { + Extension extn; + BER::decode(sequence, extn); + handle_v3_extension(extn); + } + sequence.verify_end(); + } + } + +/************************************************* +* Decode a requested X.509v3 extension * +*************************************************/ +void PKCS10_Request::handle_v3_extension(const Extension& extn) + { + BER_Decoder value(extn.value); + + if(extn.oid == OIDS::lookup("X509v3.KeyUsage")) + BER::decode(value, constraints_value); + else if(extn.oid == OIDS::lookup("X509v3.ExtendedKeyUsage")) + { + BER_Decoder key_usage = BER::get_subsequence(value); + while(key_usage.more_items()) + { + OID usage_oid; + BER::decode(key_usage, usage_oid); + ex_constraints_list.push_back(usage_oid); + } + } + else if(extn.oid == OIDS::lookup("X509v3.BasicConstraints")) + { + BER_Decoder constraints = BER::get_subsequence(value); + BER::decode_optional(constraints, is_ca, BOOLEAN, UNIVERSAL, false); + BER::decode_optional(constraints, max_path_len, + INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT); + } + else if(extn.oid == OIDS::lookup("X509v3.SubjectAlternativeName")) + BER::decode(value, subject_alt); + else + return; + + value.verify_end(); + } + +/************************************************* +* Return the public key of the requestor * +*************************************************/ +MemoryVector<byte> PKCS10_Request::raw_public_key() const + { + return pub_key; + } + +/************************************************* +* Return the public key of the requestor * +*************************************************/ +X509_PublicKey* PKCS10_Request::subject_public_key() const + { + return X509::load_key(pub_key); + } + +/************************************************* +* Return the name of the requestor * +*************************************************/ +X509_DN PKCS10_Request::subject_dn() const + { + return dn; + } + +/************************************************* +* Return the alternative names of the requestor * +*************************************************/ +AlternativeName PKCS10_Request::subject_alt_name() const + { + return subject_alt; + } + +/************************************************* +* Return the challenge password (if any) * +*************************************************/ +std::string PKCS10_Request::challenge_password() const + { + return challenge; + } + +/************************************************* +* Return the key constraints (if any) * +*************************************************/ +Key_Constraints PKCS10_Request::constraints() const + { + return constraints_value; + } + +/************************************************* +* Return the extendend key constraints (if any) * +*************************************************/ +std::vector<OID> PKCS10_Request::ex_constraints() const + { + return ex_constraints_list; + } + +/************************************************* +* Return is a CA certificate is requested * +*************************************************/ +bool PKCS10_Request::is_CA() const + { + return is_ca; + } + +/************************************************* +* Return the desired path limit (if any) * +*************************************************/ +u32bit PKCS10_Request::path_limit() const + { + return max_path_len; + } + +} |