bool EAC_Signed_Object::check_signature(Public_Key& pub_key, const MemoryRegion<byte>& sig) const { try { std::vector<std::string> sig_info = split_on(OIDS::lookup(sig_algo.oid), '/'); if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) { return false; } std::string padding = sig_info[1]; Signature_Format format = (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; SecureVector<byte> to_sign = tbs_data(); PK_Verifier verifier(pub_key, padding, format); return verifier.verify_message(to_sign, sig); } catch(...) { return false; } }
std::vector<byte> BER_encode(const Public_Key& key) { return DER_Encoder() .start_cons(SEQUENCE) .encode(key.algorithm_identifier()) .encode(key.x509_subject_public_key(), BIT_STRING) .end_cons() .get_contents_unlocked(); }
/* * Make sure the given key constraints are permitted for the given key type */ void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key, Key_Constraints constraints) { const std::string name = pub_key.algo_name(); size_t permitted = 0; if(name == "DH" || name == "ECDH") { permitted |= KEY_AGREEMENT | ENCIPHER_ONLY | DECIPHER_ONLY; } if(name == "RSA" || name == "ElGamal") { permitted |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT; } if(name == "RSA" || name == "DSA" || name == "ECDSA" || name == "ECGDSA" || name == "ECKCDSA" || name == "GOST-34.10" || name == "Ed25519") { permitted |= DIGITAL_SIGNATURE | NON_REPUDIATION | KEY_CERT_SIGN | CRL_SIGN; } if((constraints & permitted) != constraints) { throw Exception("Invalid " + name + " constraints " + key_constraints_to_string(constraints)); } }
/* * Check the signature on an object */ bool X509_Object::check_signature(const Public_Key& pub_key) const { try { std::vector<std::string> sig_info = split_on(OIDS::lookup(m_sig_algo.oid), '/'); if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) return false; std::string padding = sig_info[1]; Signature_Format format = (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; PK_Verifier verifier(pub_key, padding, format); return verifier.verify_message(tbs_data(), signature()); } catch(std::exception&) { return false; } }
void Policy::check_peer_key_acceptable(const Public_Key& public_key) const { const std::string algo_name = public_key.algo_name(); const size_t keylength = public_key.key_length(); size_t expected_keylength = 0; if(algo_name == "RSA") { expected_keylength = minimum_rsa_bits(); } else if(algo_name == "DH") { expected_keylength = minimum_dh_group_size(); } else if(algo_name == "DSA") { expected_keylength = minimum_dsa_group_size(); } else if(algo_name == "ECDH" || algo_name == "Curve25519") { expected_keylength = minimum_ecdh_group_size(); } else if(algo_name == "ECDSA") { expected_keylength = minimum_ecdsa_group_size(); } // else some other algo, so leave expected_keylength as zero and the check is a no-op if(keylength < expected_keylength) throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, "Peer sent " + std::to_string(keylength) + " bit " + algo_name + " key" ", policy requires at least " + std::to_string(expected_keylength)); }
std::pair<std::string, Signature_Format> Handshake_State::parse_sig_format(const Public_Key& key, const std::string& input_hash_algo, const std::string& input_sig_algo, bool for_client_auth, const Policy& policy) const { const std::string key_type = key.algo_name(); if(!policy.allowed_signature_method(key_type)) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Rejecting " + key_type + " signature"); } std::string hash_algo; if(this->version().supports_negotiable_signature_algorithms()) { if(input_sig_algo != key_type) throw Decoding_Error("Counterparty sent inconsistent key and sig types"); if(input_hash_algo == "") throw Decoding_Error("Counterparty did not send hash/sig IDS"); hash_algo = input_hash_algo; if(for_client_auth && !cert_req()) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "No certificate verify set"); } /* Confirm the signature type we just received against the supported_algos list that we sent; it better be there. */ const auto supported_algos = for_client_auth ? cert_req()->supported_algos() : client_hello()->supported_algos(); if(!supported_algos_include(supported_algos, key_type, hash_algo)) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "TLS signature extension did not allow for " + key_type + "/" + hash_algo + " signature"); } } else { if(input_hash_algo != "" || input_sig_algo != "") throw Decoding_Error("Counterparty sent hash/sig IDs with old version"); if(key_type == "RSA") { hash_algo = "Parallel(MD5,SHA-160)"; } else if(key_type == "DSA" || key_type == "ECDSA") { hash_algo = "SHA-1"; } else { throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures"); } /* There is no check on the acceptability of a v1.0/v1.1 hash type, since it's implicit with use of the protocol */ } if(key_type == "RSA") { const std::string padding = "EMSA3(" + hash_algo + ")"; return std::make_pair(padding, IEEE_1363); } else if(key_type == "DSA" || key_type == "ECDSA") { const std::string padding = "EMSA1(" + hash_algo + ")"; return std::make_pair(padding, DER_SEQUENCE); } throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures"); }
Certificate_Status_Code X509_Object::verify_signature(const Public_Key& pub_key) const { const std::vector<std::string> sig_info = split_on(OIDS::lookup(m_sig_algo.get_oid()), '/'); if(sig_info.size() < 1 || sig_info.size() > 2 || sig_info[0] != pub_key.algo_name()) return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS; std::string padding; if(sig_info.size() == 2) padding = sig_info[1]; else if(sig_info[0] == "Ed25519") padding = "Pure"; else return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS; const Signature_Format format = (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; if(padding == "EMSA4") { // "MUST contain RSASSA-PSS-params" if(signature_algorithm().parameters.empty()) { return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS; } Pss_params pss_parameter = decode_pss_params(signature_algorithm().parameters); // hash_algo must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512 const std::string hash_algo = OIDS::lookup(pss_parameter.hash_algo.oid); if(hash_algo != "SHA-160" && hash_algo != "SHA-224" && hash_algo != "SHA-256" && hash_algo != "SHA-384" && hash_algo != "SHA-512") { return Certificate_Status_Code::UNTRUSTED_HASH; } const std::string mgf_algo = OIDS::lookup(pss_parameter.mask_gen_algo.oid); if(mgf_algo != "MGF1") { return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS; } // For MGF1, it is strongly RECOMMENDED that the underlying hash function be the same as the one identified by hashAlgorithm // Must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512 if(pss_parameter.mask_gen_hash.oid != pss_parameter.hash_algo.oid) { return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS; } if(pss_parameter.trailer_field != 1) { return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS; } // salt_len is actually not used for verification. Length is inferred from the signature padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")"; } try { PK_Verifier verifier(pub_key, padding, format); const bool valid = verifier.verify_message(tbs_data(), signature()); if(valid) return Certificate_Status_Code::VERIFIED; else return Certificate_Status_Code::SIGNATURE_ERROR; } catch(Algorithm_Not_Found&) { return Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN; } catch(...) { // This shouldn't happen, fallback to generic signature error return Certificate_Status_Code::SIGNATURE_ERROR; } }