diff options
author | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
commit | a2c99d3270eb73ef2db5704fc54356c6b75096f8 (patch) | |
tree | ad3d6c4fcc8dd0f403f8105598943616246fe172 /src/x509self.cpp |
Initial checkin1.5.6
Diffstat (limited to 'src/x509self.cpp')
-rw-r--r-- | src/x509self.cpp | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/x509self.cpp b/src/x509self.cpp new file mode 100644 index 000000000..281251bef --- /dev/null +++ b/src/x509self.cpp @@ -0,0 +1,198 @@ +/************************************************* +* PKCS #10/Self Signed Cert Creation Source File * +* (C) 1999-2006 The Botan Project * +*************************************************/ + +#include <botan/x509self.h> +#include <botan/x509_ext.h> +#include <botan/x509_ca.h> +#include <botan/conf.h> +#include <botan/look_pk.h> +#include <botan/oids.h> +#include <botan/pipe.h> +#include <memory> + +namespace Botan { + +namespace { + +/************************************************* +* Shared setup for self-signed items * +*************************************************/ +MemoryVector<byte> shared_setup(const X509_Cert_Options& opts, + const PKCS8_PrivateKey& key) + { + const PKCS8_PrivateKey* key_pointer = &key; + if(!dynamic_cast<const PK_Signing_Key*>(key_pointer)) + throw Invalid_Argument("Key type " + key.algo_name() + " cannot sign"); + + opts.sanity_check(); + + Pipe key_encoder; + key_encoder.start_msg(); + X509::encode(key, key_encoder, RAW_BER); + key_encoder.end_msg(); + + return key_encoder.read_all(); + } + +/************************************************* +* Load information from the X509_Cert_Options * +*************************************************/ +void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn, + AlternativeName& subject_alt) + { + subject_dn.add_attribute("X520.CommonName", opts.common_name); + subject_dn.add_attribute("X520.Country", opts.country); + subject_dn.add_attribute("X520.State", opts.state); + subject_dn.add_attribute("X520.Locality", opts.locality); + subject_dn.add_attribute("X520.Organization", opts.organization); + subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit); + subject_dn.add_attribute("X520.SerialNumber", opts.serial_number); + subject_alt = AlternativeName(opts.email, opts.uri, opts.dns); + subject_alt.add_othername(OIDS::lookup("PKIX.XMPPAddr"), + opts.xmpp, UTF8_STRING); + } + +/************************************************* +* Choose a signing format for the key * +*************************************************/ +PK_Signer* choose_sig_format(const PKCS8_PrivateKey& key, + AlgorithmIdentifier& sig_algo) + { + std::string padding; + Signature_Format format; + Config::choose_sig_format(key.algo_name(), padding, format); + + sig_algo.oid = OIDS::lookup(key.algo_name() + "/" + padding); + sig_algo.parameters = key.DER_encode_params(); + + const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key); + + return get_pk_signer(sig_key, padding, format); + } + +} + +namespace X509 { + +/************************************************* +* Create a new self-signed X.509 certificate * +*************************************************/ +X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts, + const PKCS8_PrivateKey& key) + { + AlgorithmIdentifier sig_algo; + X509_DN subject_dn; + AlternativeName subject_alt; + + MemoryVector<byte> pub_key = shared_setup(opts, key); + std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo)); + load_info(opts, subject_dn, subject_alt); + + Key_Constraints constraints; + if(opts.is_CA) + constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN); + else + constraints = find_constraints(key, opts.constraints); + + return X509_CA::make_cert(signer.get(), sig_algo, pub_key, + MemoryVector<byte>(), opts.start, opts.end, + subject_dn, subject_dn, + opts.is_CA, opts.path_limit, + subject_alt, subject_alt, + constraints, opts.ex_constraints); + } + +/************************************************* +* Create a PKCS #10 certificate request * +*************************************************/ +PKCS10_Request create_cert_req(const X509_Cert_Options& opts, + const PKCS8_PrivateKey& key) + { + AlgorithmIdentifier sig_algo; + X509_DN subject_dn; + AlternativeName subject_alt; + + MemoryVector<byte> pub_key = shared_setup(opts, key); + std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo)); + load_info(opts, subject_dn, subject_alt); + + const u32bit PKCS10_VERSION = 0; + + Extensions extensions; + + extensions.add( + new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit)); + extensions.add( + new Cert_Extension::Key_Usage( + opts.is_CA ? Key_Constraints(KEY_CERT_SIGN | CRL_SIGN) : + find_constraints(key, opts.constraints) + ) + ); + extensions.add( + new Cert_Extension::Extended_Key_Usage(opts.ex_constraints)); + extensions.add( + new Cert_Extension::Alternative_Name(subject_alt, + "X509v3.SubjectAlternativeName", + "subject_alternative_name") + ); + + DER_Encoder tbs_req; + + tbs_req.start_sequence() + .encode(PKCS10_VERSION) + .encode(subject_dn) + .add_raw_octets(pub_key) + .start_explicit(ASN1_Tag(0)); + + if(opts.challenge != "") + { + ASN1_String challenge(opts.challenge, DIRECTORY_STRING); + +#if 0 + DER_Encoder attr_encoder; + attr_encoder.encode(challenge); + tbs_req.encode( + Attribute("PKCS9.ChallengePassword", attr_encoder.get_contents()) + ); +#else + tbs_req.encode( + Attribute("PKCS9.ChallengePassword", + DER_Encoder().encode(challenge).get_contents() + ) + ); +#endif + } + + tbs_req.encode( + Attribute("PKCS9.ExtensionRequest", + DER_Encoder() + .start_sequence() + .encode(extensions) + .end_sequence() + .get_contents() + ) + ) + .end_explicit(ASN1_Tag(0)) + .end_sequence(); + + MemoryVector<byte> tbs_bits = tbs_req.get_contents(); + MemoryVector<byte> sig = signer->sign_message(tbs_bits); + + DataSource_Memory source( + DER_Encoder() + .start_sequence() + .add_raw_octets(tbs_bits) + .encode(sig_algo) + .encode(sig, BIT_STRING) + .end_sequence() + .get_contents() + ); + + return PKCS10_Request(source); + } + +} + +} |