/* * PKCS #10 * (C) 1999-2007 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include #include #include #include #include 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& in) : X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") { do_decode(); } /* * Decode 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")) { value.decode(m_extensions).verify_end(); } } /* * 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 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 { if(auto ext = m_extensions.get(OIDS::lookup("X509v3.KeyUsage"))) { return dynamic_cast(*ext).get_constraints(); } return NO_CONSTRAINTS; } /* * Return the extendend key constraints (if any) */ std::vector PKCS10_Request::ex_constraints() const { if(auto ext = m_extensions.get(OIDS::lookup("X509v3.ExtendedKeyUsage"))) { return dynamic_cast(*ext).get_oids(); } return {}; } /* * Return is a CA certificate is requested */ bool PKCS10_Request::is_CA() const { if(auto ext = m_extensions.get(OIDS::lookup("X509v3.BasicConstraints"))) { return dynamic_cast(*ext).get_is_ca(); } return false; } /* * Return the desired path limit (if any) */ size_t PKCS10_Request::path_limit() const { if(auto ext = m_extensions.get(OIDS::lookup("X509v3.BasicConstraints"))) { Cert_Extension::Basic_Constraints& basic_constraints = dynamic_cast(*ext); if(basic_constraints.get_is_ca()) { return basic_constraints.get_path_limit(); } } return 0; } /* * Return the X509v3 extensions */ Extensions PKCS10_Request::extensions() const { return m_extensions; } }