enum ssl_private_key_result_t tls13_prepare_certificate_verify( SSL *ssl, int is_first_run) { enum ssl_private_key_result_t ret = ssl_private_key_failure; uint8_t *msg = NULL; size_t msg_len; CBB cbb, body; CBB_zero(&cbb); uint16_t signature_algorithm; if (!tls1_choose_signature_algorithm(ssl, &signature_algorithm)) { goto err; } if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE_VERIFY) || !CBB_add_u16(&body, signature_algorithm)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } /* Sign the digest. */ CBB child; const size_t max_sig_len = ssl_private_key_max_signature_len(ssl); uint8_t *sig; size_t sig_len; if (!CBB_add_u16_length_prefixed(&body, &child) || !CBB_reserve(&child, &sig, max_sig_len)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } enum ssl_private_key_result_t sign_result; if (is_first_run) { if (!tls13_get_cert_verify_signature_input(ssl, &msg, &msg_len, ssl->server)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } sign_result = ssl_private_key_sign(ssl, sig, &sig_len, max_sig_len, signature_algorithm, msg, msg_len); } else { sign_result = ssl_private_key_complete(ssl, sig, &sig_len, max_sig_len); } if (sign_result != ssl_private_key_success) { ret = sign_result; goto err; } if (!CBB_did_write(&child, sig_len) || !ssl->method->finish_message(ssl, &cbb)) { goto err; } ret = ssl_private_key_success; err: CBB_cleanup(&cbb); OPENSSL_free(msg); return ret; }
int ssl_private_key_supports_signature_algorithm(SSL *ssl, uint16_t signature_algorithm) { const EVP_MD *md; if (is_rsa_pkcs1(&md, signature_algorithm) && ssl3_protocol_version(ssl) < TLS1_3_VERSION) { return ssl_private_key_type(ssl) == NID_rsaEncryption; } int curve; if (is_ecdsa(&curve, &md, signature_algorithm)) { int type = ssl_private_key_type(ssl); if (!ssl_is_ecdsa_key_type(type)) { return 0; } /* Prior to TLS 1.3, ECDSA curves did not match the signature algorithm. */ if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) { return 1; } return curve != NID_undef && type == curve; } if (is_rsa_pss(&md, signature_algorithm)) { if (ssl_private_key_type(ssl) != NID_rsaEncryption) { return 0; } /* Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that * emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the * hash in TLS. Reasonable RSA key sizes are large enough for the largest * defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too large for * SHA-512. 1024-bit RSA is sometimes used for test credentials, so check * the size to fall back to another algorithm. */ if (ssl_private_key_max_signature_len(ssl) < 2 * EVP_MD_size(md) + 2) { return 0; } /* RSA-PSS is only supported by message-based private keys. */ if (ssl->cert->key_method != NULL && ssl->cert->key_method->sign == NULL) { return 0; } return 1; } return 0; }
int ssl_private_key_supports_signature_algorithm(SSL *ssl, uint16_t signature_algorithm) { const EVP_MD *md; if (is_rsa_pkcs1(&md, signature_algorithm)) { return ssl_private_key_type(ssl) == EVP_PKEY_RSA; } int curve; if (is_ecdsa(&curve, &md, signature_algorithm)) { if (ssl_private_key_type(ssl) != EVP_PKEY_EC) { return 0; } /* For non-custom keys, also check the curve matches. Custom private keys * must instead configure the signature algorithms accordingly. */ if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION && ssl->cert->key_method == NULL) { EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey); if (curve == NID_undef || EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve) { return 0; } } return 1; } if (is_rsa_pss(&md, signature_algorithm)) { if (ssl3_protocol_version(ssl) < TLS1_3_VERSION || ssl_private_key_type(ssl) != EVP_PKEY_RSA) { return 0; } /* Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that * emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the * hash in TLS. Reasonable RSA key sizes are large enough for the largest * defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too large for * SHA-512. 1024-bit RSA is sometimes used for test credentials, so check * the size to fall back to another algorithm. */ if (ssl_private_key_max_signature_len(ssl) < 2 * EVP_MD_size(md) + 2) { return 0; } return 1; } return 0; }