Botan  1.11.15
src/lib/cert/x509/x509self.cpp
Go to the documentation of this file.
00001 /*
00002 * PKCS #10/Self Signed Cert Creation
00003 * (C) 1999-2008 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/x509self.h>
00009 #include <botan/x509_ext.h>
00010 #include <botan/x509_ca.h>
00011 #include <botan/der_enc.h>
00012 #include <botan/oids.h>
00013 
00014 namespace Botan {
00015 
00016 namespace {
00017 
00018 /*
00019 * Load information from the X509_Cert_Options
00020 */
00021 void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn,
00022                AlternativeName& subject_alt)
00023    {
00024    subject_dn.add_attribute("X520.CommonName", opts.common_name);
00025    subject_dn.add_attribute("X520.Country", opts.country);
00026    subject_dn.add_attribute("X520.State", opts.state);
00027    subject_dn.add_attribute("X520.Locality", opts.locality);
00028    subject_dn.add_attribute("X520.Organization", opts.organization);
00029    subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit);
00030    subject_dn.add_attribute("X520.SerialNumber", opts.serial_number);
00031    subject_alt = AlternativeName(opts.email, opts.uri, opts.dns, opts.ip);
00032    subject_alt.add_othername(OIDS::lookup("PKIX.XMPPAddr"),
00033                              opts.xmpp, UTF8_STRING);
00034    }
00035 
00036 }
00037 
00038 namespace X509 {
00039 
00040 /*
00041 * Create a new self-signed X.509 certificate
00042 */
00043 X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
00044                                          const Private_Key& key,
00045                                          const std::string& hash_fn,
00046                                          RandomNumberGenerator& rng)
00047    {
00048    AlgorithmIdentifier sig_algo;
00049    X509_DN subject_dn;
00050    AlternativeName subject_alt;
00051 
00052    opts.sanity_check();
00053 
00054    std::vector<byte> pub_key = X509::BER_encode(key);
00055    std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo));
00056    load_info(opts, subject_dn, subject_alt);
00057 
00058    Key_Constraints constraints;
00059    if(opts.is_CA)
00060       constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
00061    else
00062       constraints = find_constraints(key, opts.constraints);
00063 
00064    Extensions extensions;
00065 
00066    extensions.add(
00067       new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit),
00068       true);
00069 
00070    extensions.add(new Cert_Extension::Key_Usage(constraints), true);
00071 
00072    extensions.add(new Cert_Extension::Subject_Key_ID(pub_key));
00073 
00074    extensions.add(
00075       new Cert_Extension::Subject_Alternative_Name(subject_alt));
00076 
00077    extensions.add(
00078       new Cert_Extension::Extended_Key_Usage(opts.ex_constraints));
00079 
00080    return X509_CA::make_cert(signer.get(), rng, sig_algo, pub_key,
00081                              opts.start, opts.end,
00082                              subject_dn, subject_dn,
00083                              extensions);
00084    }
00085 
00086 /*
00087 * Create a PKCS #10 certificate request
00088 */
00089 PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
00090                                const Private_Key& key,
00091                                const std::string& hash_fn,
00092                                RandomNumberGenerator& rng)
00093    {
00094    AlgorithmIdentifier sig_algo;
00095    X509_DN subject_dn;
00096    AlternativeName subject_alt;
00097 
00098    opts.sanity_check();
00099 
00100    std::vector<byte> pub_key = X509::BER_encode(key);
00101    std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo));
00102    load_info(opts, subject_dn, subject_alt);
00103 
00104    const size_t PKCS10_VERSION = 0;
00105 
00106    Extensions extensions;
00107 
00108    extensions.add(
00109       new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit));
00110    extensions.add(
00111       new Cert_Extension::Key_Usage(
00112          opts.is_CA ? Key_Constraints(KEY_CERT_SIGN | CRL_SIGN) :
00113                       find_constraints(key, opts.constraints)
00114          )
00115       );
00116    extensions.add(
00117       new Cert_Extension::Extended_Key_Usage(opts.ex_constraints));
00118    extensions.add(
00119       new Cert_Extension::Subject_Alternative_Name(subject_alt));
00120 
00121    DER_Encoder tbs_req;
00122 
00123    tbs_req.start_cons(SEQUENCE)
00124       .encode(PKCS10_VERSION)
00125       .encode(subject_dn)
00126       .raw_bytes(pub_key)
00127       .start_explicit(0);
00128 
00129    if(opts.challenge != "")
00130       {
00131       ASN1_String challenge(opts.challenge, DIRECTORY_STRING);
00132 
00133       tbs_req.encode(
00134          Attribute("PKCS9.ChallengePassword",
00135                    DER_Encoder().encode(challenge).get_contents_unlocked()
00136             )
00137          );
00138       }
00139 
00140    tbs_req.encode(
00141       Attribute("PKCS9.ExtensionRequest",
00142                 DER_Encoder()
00143                    .start_cons(SEQUENCE)
00144                       .encode(extensions)
00145                    .end_cons()
00146                .get_contents_unlocked()
00147          )
00148       )
00149       .end_explicit()
00150       .end_cons();
00151 
00152    const std::vector<byte> req =
00153       X509_Object::make_signed(signer.get(), rng, sig_algo,
00154                                tbs_req.get_contents());
00155 
00156    return PKCS10_Request(req);
00157    }
00158 
00159 }
00160 
00161 }