AlgorithmIdentifier PSSR::config_for_x509(const Private_Key& key, const std::string& cert_hash_name) const { if(cert_hash_name != m_hash->name()) throw Invalid_Argument("Hash function from opts and hash_fn argument" " need to be identical"); // check that the signature algorithm and the padding scheme fit if(!sig_algo_and_pad_ok(key.algo_name(), "EMSA4")) { throw Invalid_Argument("Encoding scheme with canonical name EMSA4" " not supported for signature algorithm " + key.algo_name()); } AlgorithmIdentifier sig_algo; // hardcoded as RSA is the only valid algorithm for EMSA4 at the moment sig_algo.oid = OIDS::lookup( "RSA/EMSA4" ); const AlgorithmIdentifier hash_id(cert_hash_name, AlgorithmIdentifier::USE_NULL_PARAM); const AlgorithmIdentifier mgf_id("MGF1", hash_id.BER_encode()); DER_Encoder(sig_algo.parameters) .start_cons(SEQUENCE) .start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).encode(hash_id).end_cons() .start_cons(ASN1_Tag(1), CONTEXT_SPECIFIC).encode(mgf_id).end_cons() .start_cons(ASN1_Tag(2), CONTEXT_SPECIFIC).encode(m_SALT_SIZE).end_cons() .start_cons(ASN1_Tag(3), CONTEXT_SPECIFIC).encode(size_t(1)).end_cons() // trailer field .end_cons(); return sig_algo; }
void EAC1_1_ADO::decode_info(DataSource& source, SecureVector<byte> & res_tbs_bits, ECDSA_Signature & res_sig) { SecureVector<byte> concat_sig; SecureVector<byte> cert_inner_bits; ASN1_Car car; BER_Decoder(source) .start_cons(ASN1_Tag(7)) .start_cons(ASN1_Tag(33)) .raw_bytes(cert_inner_bits) .end_cons() .decode(car) .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) .end_cons(); SecureVector<byte> enc_cert = DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) .raw_bytes(cert_inner_bits) .end_cons() .get_contents(); res_tbs_bits = enc_cert; res_tbs_bits += DER_Encoder().encode(car).get_contents(); res_sig = decode_concatenation(concat_sig); }
MemoryVector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer, const MemoryRegion<byte>& tbs_bits, RandomNumberGenerator& rng) { SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng); return DER_Encoder() .start_cons(ASN1_Tag(7), APPLICATION) .raw_bytes(tbs_bits) .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) .end_cons() .get_contents(); }
Response::Response(const uint8_t response_bits[], size_t response_bits_len) : m_response_bits(response_bits, response_bits + response_bits_len) { m_dummy_response_status = Certificate_Status_Code::OCSP_RESPONSE_INVALID; BER_Decoder response_outer = BER_Decoder(m_response_bits).start_cons(SEQUENCE); size_t resp_status = 0; response_outer.decode(resp_status, ENUMERATED, UNIVERSAL); if(resp_status != 0) throw Exception("OCSP response status " + std::to_string(resp_status)); if(response_outer.more_items()) { BER_Decoder response_bytes = response_outer.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).start_cons(SEQUENCE); response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"), "Unknown response type in OCSP response"); BER_Decoder basicresponse = BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE); basicresponse.start_cons(SEQUENCE) .raw_bytes(m_tbs_bits) .end_cons() .decode(m_sig_algo) .decode(m_signature, BIT_STRING); decode_optional_list(basicresponse, ASN1_Tag(0), m_certs); size_t responsedata_version = 0; Extensions extensions; BER_Decoder(m_tbs_bits) .decode_optional(responsedata_version, ASN1_Tag(0), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode_optional(m_signer_name, ASN1_Tag(1), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode_optional_string(m_key_hash, OCTET_STRING, 2, ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode(m_produced_at) .decode_list(m_responses) .decode_optional(extensions, ASN1_Tag(1), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)); } response_outer.end_cons(); }
void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const { if(encoding == PEM) throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object"); SecureVector<byte> concat_sig( EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation()); out.write(DER_Encoder() .start_cons(ASN1_Tag(7), APPLICATION) .raw_bytes(tbs_bits) .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) .end_cons() .get_contents()); }
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, const secure_vector<byte>& key_bits) { m_domain_params = EC_Group(alg_id.parameters); m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; OID key_parameters; secure_vector<byte> public_key_bits; BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode_and_check<size_t>(1, "Unknown version code for ECC key") .decode_octet_string_bigint(m_private_key) .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE) .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE) .end_cons(); if(!key_parameters.empty() && key_parameters != alg_id.oid) throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match"); if(public_key_bits.empty()) { m_public_key = domain().get_base_point() * m_private_key; BOTAN_ASSERT(m_public_key.on_the_curve(), "Public point derived from loaded key was on the curve"); } else { m_public_key = OS2ECP(public_key_bits, domain().get_curve()); // OS2ECP verifies that the point is on the curve } }
void SingleResponse::decode_from(class BER_Decoder& from) { BER_Object cert_status; Extensions extensions; from.start_cons(SEQUENCE) .decode(m_certid) .get_next(cert_status) .decode(m_thisupdate) .decode_optional(m_nextupdate, ASN1_Tag(0), ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED)) .decode_optional(extensions, ASN1_Tag(1), ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED)) .end_cons(); m_cert_status = cert_status.type_tag; }
/* * Decode the TBSCertificate data */ void EAC1_1_CVC::force_decode() { SecureVector<byte> enc_pk; SecureVector<byte> enc_chat_val; u32bit cpi; BER_Decoder tbs_cert(tbs_bits); tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION) .decode(m_car) .start_cons(ASN1_Tag(73)) .raw_bytes(enc_pk) .end_cons() .decode(m_chr) .start_cons(ASN1_Tag(76)) .decode(m_chat_oid) .decode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) .end_cons() .decode(m_ced) .decode(m_cex) .verify_end(); if(enc_chat_val.size() != 1) throw Decoding_Error("CertificateHolderAuthorizationValue was not of length 1"); if(cpi != 0) throw Decoding_Error("EAC1_1 certificate´s cpi was not 0"); // FIXME: PK algos have no notion of EAC encoder/decoder currently #if 0 ECDSA_PublicKey tmp_pk; std::auto_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); sig_algo = dec->public_key(enc_pk); m_pk = tmp_pk; m_chat_val = enc_chat_val[0]; self_signed = false; if(m_car.iso_8859() == m_chr.iso_8859()) { self_signed= true; } #endif }
void EAC1_1_ADO::force_decode() { SecureVector<byte> inner_cert; BER_Decoder(tbs_bits) .start_cons(ASN1_Tag(33)) .raw_bytes(inner_cert) .end_cons() .decode(m_car) .verify_end(); SecureVector<byte> req_bits = DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) .raw_bytes(inner_cert) .end_cons() .get_contents(); DataSource_Memory req_source(req_bits); m_req = EAC1_1_Req(req_source); sig_algo = m_req.sig_algo; }
void GeneralSubtree::decode_from(class BER_Decoder& ber) { ber.start_cons(SEQUENCE) .decode(m_base) .decode_optional(m_minimum,ASN1_Tag(0),CONTEXT_SPECIFIC,size_t(0)) .end_cons(); if(m_minimum != 0) throw Decoding_Error("GeneralSubtree minimum must be 0"); m_maximum = std::numeric_limits<std::size_t>::max(); }
/* * Deocde 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"); }
EAC1_1_CVC EAC1_1_CVC_CA::make_cert(std::auto_ptr<PK_Signer> signer, MemoryRegion<byte> const& public_key, ASN1_Car const& car, ASN1_Chr const& chr, byte holder_auth_templ, ASN1_Ced ced, ASN1_Cex cex, RandomNumberGenerator& rng) { OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); MemoryVector<byte> enc_chat_val; enc_chat_val.append(holder_auth_templ); MemoryVector<byte> enc_cpi; enc_cpi.append(0x00); MemoryVector<byte> tbs = DER_Encoder() .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi .encode(car) .raw_bytes(public_key) .encode(chr) .start_cons(ASN1_Tag(76), APPLICATION) .encode(chat_oid) .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) .end_cons() .encode(ced) .encode(cex) .get_contents(); MemoryVector<byte> signed_cert = EAC1_1_CVC::make_signed(signer, EAC1_1_CVC::build_cert_body(tbs), rng); SharedPointer<DataSource> source(new DataSource_Memory(signed_cert)); return EAC1_1_CVC(source); }
void EAC1_1_Req::force_decode() { SecureVector<byte> enc_pk; BER_Decoder tbs_cert(tbs_bits); u32bit cpi; tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION) .start_cons(ASN1_Tag(73)) .raw_bytes(enc_pk) .end_cons() .decode(m_chr) .verify_end(); if(cpi != 0) { throw Decoding_Error("EAC1_1 request´s cpi was not 0"); } // FIXME: No EAC support in ECDSA #if 0 ECDSA_PublicKey tmp_pk; std::auto_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); sig_algo = dec->public_key(enc_pk); m_pk = tmp_pk; #endif }
Response::Response(const Certificate_Store& trusted_roots, const std::vector<byte>& response_bits) { BER_Decoder response_outer = BER_Decoder(response_bits).start_cons(SEQUENCE); size_t resp_status = 0; response_outer.decode(resp_status, ENUMERATED, UNIVERSAL); if(resp_status != 0) throw std::runtime_error("OCSP response status " + std::to_string(resp_status)); if(response_outer.more_items()) { BER_Decoder response_bytes = response_outer.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).start_cons(SEQUENCE); response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"), "Unknown response type in OCSP response"); BER_Decoder basicresponse = BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE); std::vector<byte> tbs_bits; AlgorithmIdentifier sig_algo; std::vector<byte> signature; std::vector<X509_Certificate> certs; basicresponse.start_cons(SEQUENCE) .raw_bytes(tbs_bits) .end_cons() .decode(sig_algo) .decode(signature, BIT_STRING); decode_optional_list(basicresponse, ASN1_Tag(0), certs); size_t responsedata_version = 0; X509_DN name; std::vector<byte> key_hash; X509_Time produced_at; Extensions extensions; BER_Decoder(tbs_bits) .decode_optional(responsedata_version, ASN1_Tag(0), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode_optional(name, ASN1_Tag(1), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode_optional_string(key_hash, OCTET_STRING, 2, ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode(produced_at) .decode_list(m_responses) .decode_optional(extensions, ASN1_Tag(1), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)); if(certs.empty()) { if(auto cert = trusted_roots.find_cert(name, std::vector<byte>())) certs.push_back(*cert); else throw std::runtime_error("Could not find certificate that signed OCSP response"); } check_signature(tbs_bits, sig_algo, signature, trusted_roots, certs); } response_outer.end_cons(); }
ASN1_Chr::ASN1_Chr(std::string const& str) : ASN1_EAC_String(str, ASN1_Tag(32)) {}
ASN1_Car::ASN1_Car(std::string const& str) : ASN1_EAC_String(str, ASN1_Tag(2)) {}