Botan
1.11.15
|
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 }