/* * Create a new self-signed X.509 certificate */ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts, const Private_Key& key, const std::string& hash_fn, RandomNumberGenerator& rng) { AlgorithmIdentifier sig_algo; X509_DN subject_dn; AlternativeName subject_alt; std::vector<byte> pub_key = X509::BER_encode(key); std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, 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 { verify_cert_constraints_valid_for_key_type(key, opts.constraints); constraints = opts.constraints; } Extensions extensions; extensions.add( new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit), true); if(constraints != NO_CONSTRAINTS) { extensions.add(new Cert_Extension::Key_Usage(constraints), true); } extensions.add(new Cert_Extension::Subject_Key_ID(pub_key)); extensions.add( new Cert_Extension::Subject_Alternative_Name(subject_alt)); extensions.add( new Cert_Extension::Extended_Key_Usage(opts.ex_constraints)); return X509_CA::make_cert(signer.get(), rng, sig_algo, pub_key, opts.start, opts.end, subject_dn, subject_dn, extensions); }
/* * Create a CRL */ X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked, u32bit crl_number, u32bit next_update, RandomNumberGenerator& rng) const { const size_t X509_CRL_VERSION = 2; if(next_update == 0) next_update = timespec_to_u32bit("7d"); // Totally stupid: ties encoding logic to the return of std::time!! auto current_time = std::chrono::system_clock::now(); auto expire_time = current_time + std::chrono::seconds(next_update); Extensions extensions; extensions.add( new Cert_Extension::Authority_Key_ID(m_cert.subject_key_id())); extensions.add(new Cert_Extension::CRL_Number(crl_number)); // clang-format off const std::vector<byte> crl = X509_Object::make_signed( m_signer, rng, m_ca_sig_algo, DER_Encoder().start_cons(SEQUENCE) .encode(X509_CRL_VERSION-1) .encode(m_ca_sig_algo) .encode(m_cert.issuer_dn()) .encode(X509_Time(current_time)) .encode(X509_Time(expire_time)) .encode_if(revoked.size() > 0, DER_Encoder() .start_cons(SEQUENCE) .encode_list(revoked) .end_cons() ) .start_explicit(0) .start_cons(SEQUENCE) .encode(extensions) .end_cons() .end_explicit() .end_cons() .get_contents()); // clang-format on return X509_CRL(crl); }
/* * DER encode a CRL_Entry */ void CRL_Entry::encode_into(DER_Encoder& der) const { Extensions extensions; extensions.add(new Cert_Extension::CRL_ReasonCode(reason)); der.start_cons(SEQUENCE) .encode(BigInt::decode(serial, serial.size())) .encode(time) .encode(extensions) .end_cons(); }
/* * Sign a PKCS #10 certificate request */ X509_Certificate X509_CA::sign_request(const PKCS10_Request& req, RandomNumberGenerator& rng, const X509_Time& not_before, const X509_Time& not_after) { Key_Constraints constraints; if(req.is_CA()) constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN); else { std::unique_ptr<Public_Key> key(req.subject_public_key()); constraints = find_constraints(*key, req.constraints()); } Extensions extensions; extensions.add( new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit()), true); extensions.add(new Cert_Extension::Key_Usage(constraints), true); extensions.add(new Cert_Extension::Authority_Key_ID(m_cert.subject_key_id())); extensions.add(new Cert_Extension::Subject_Key_ID(req.raw_public_key())); extensions.add( new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name())); extensions.add( new Cert_Extension::Extended_Key_Usage(req.ex_constraints())); return make_cert(m_signer, rng, m_ca_sig_algo, req.raw_public_key(), not_before, not_after, m_cert.subject_dn(), req.subject_dn(), extensions); }
/* * Create a PKCS #10 certificate request */ PKCS10_Request create_cert_req(const X509_Cert_Options& opts, const Private_Key& key, const std::string& hash_fn, RandomNumberGenerator& rng) { AlgorithmIdentifier sig_algo; X509_DN subject_dn; AlternativeName subject_alt; opts.sanity_check(); std::vector<byte> pub_key = X509::BER_encode(key); std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo)); load_info(opts, subject_dn, subject_alt); const size_t 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::Subject_Alternative_Name(subject_alt)); DER_Encoder tbs_req; tbs_req.start_cons(SEQUENCE) .encode(PKCS10_VERSION) .encode(subject_dn) .raw_bytes(pub_key) .start_explicit(0); if(opts.challenge != "") { ASN1_String challenge(opts.challenge, DIRECTORY_STRING); tbs_req.encode( Attribute("PKCS9.ChallengePassword", DER_Encoder().encode(challenge).get_contents_unlocked() ) ); } tbs_req.encode( Attribute("PKCS9.ExtensionRequest", DER_Encoder() .start_cons(SEQUENCE) .encode(extensions) .end_cons() .get_contents_unlocked() ) ) .end_explicit() .end_cons(); const std::vector<byte> req = X509_Object::make_signed(signer.get(), rng, sig_algo, tbs_req.get_contents()); return PKCS10_Request(req); }