- {
- unsigned long alg_k, alg_a;
- EVP_PKEY *pkey = NULL;
- int keysize = 0;
- int signature_nid = 0, md_nid = 0, pk_nid = 0;
- const SSL_CIPHER *cs = s->s3->tmp.new_cipher;
-
- alg_k = cs->algorithm_mkey;
- alg_a = cs->algorithm_auth;
-
- if (SSL_C_IS_EXPORT(cs))
- {
- /* ECDH key length in export ciphers must be <= 163 bits */
- pkey = X509_get_pubkey(x);
- if (pkey == NULL) return 0;
- keysize = EVP_PKEY_bits(pkey);
- EVP_PKEY_free(pkey);
- if (keysize > 163) return 0;
- }
-
- /* This call populates the ex_flags field correctly */
- X509_check_purpose(x, -1, 0);
- if ((x->sig_alg) && (x->sig_alg->algorithm))
- {
- signature_nid = OBJ_obj2nid(x->sig_alg->algorithm);
- OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid);
- }
- if (alg_k & SSL_kECDHe || alg_k & SSL_kECDHr)
- {
- /* key usage, if present, must allow key agreement */
- if (ku_reject(x, X509v3_KU_KEY_AGREEMENT))
- {
- SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT);
- return 0;
- }
- if ((alg_k & SSL_kECDHe) && TLS1_get_version(s) < TLS1_2_VERSION)
- {
- /* signature alg must be ECDSA */
- if (pk_nid != NID_X9_62_id_ecPublicKey)
- {
- SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE);
- return 0;
- }
- }
- if ((alg_k & SSL_kECDHr) && TLS1_get_version(s) < TLS1_2_VERSION)
- {
- /* signature alg must be RSA */
-
- if (pk_nid != NID_rsaEncryption && pk_nid != NID_rsa)
- {
- SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE);
- return 0;
- }
- }
- }
- if (alg_a & SSL_aECDSA)
- {
- /* key usage, if present, must allow signing */
- if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
- {
- SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
- return 0;
- }
- }
-
- return 1; /* all checks are ok */
- }
-
-#endif
-
-/* THIS NEEDS CLEANING UP */
-static int ssl_get_server_cert_index(SSL *s)
- {
- unsigned long alg_k, alg_a;
-
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-
- if (alg_k & (SSL_kECDHr|SSL_kECDHe))
- {
- /* we don't need to look at SSL_kEECDH
- * since no certificate is needed for
- * anon ECDH and for authenticated
- * EECDH, the check for the auth
- * algorithm will set i correctly
- * NOTE: For ECDH-RSA, we need an ECC
- * not an RSA cert but for EECDH-RSA
- * we need an RSA cert. Placing the
- * checks for SSL_kECDH before RSA
- * checks ensures the correct cert is chosen.
- */
- return SSL_PKEY_ECC;
- }
- else if (alg_a & SSL_aECDSA)
- return SSL_PKEY_ECC;
- else if (alg_k & SSL_kDHr)
- return SSL_PKEY_DH_RSA;
- else if (alg_k & SSL_kDHd)
- return SSL_PKEY_DH_DSA;
- else if (alg_a & SSL_aDSS)
- return SSL_PKEY_DSA_SIGN;
- else if (alg_a & SSL_aRSA)
- {
- if (s->cert->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
- return SSL_PKEY_RSA_SIGN;
- else
- return SSL_PKEY_RSA_ENC;
- }
- else if (alg_a & SSL_aKRB5)
- /* VRS something else here? */
- return -1;
- else if (alg_a & SSL_aGOST94)
- return SSL_PKEY_GOST94;
- else if (alg_a & SSL_aGOST01)
- return SSL_PKEY_GOST01;
- else /* if (alg_a & SSL_aNULL) */
- {
- SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX,ERR_R_INTERNAL_ERROR);
- return -1;
- }
- }
-
-CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
- {
- CERT *c;
- int i;
-
- c = s->cert;
- ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
-
- i = ssl_get_server_cert_index(s);
-
- /* This may or may not be an error. */
- if (i < 0)
- return NULL;
-
- /* May be NULL. */
- return &c->pkeys[i];
- }
-
-EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
- {
- unsigned long alg_a;
- CERT *c;
- int idx = -1;
-
- alg_a = cipher->algorithm_auth;
- c=s->cert;
-
- if ((alg_a & SSL_aDSS) &&
- (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
- idx = SSL_PKEY_DSA_SIGN;
- else if (alg_a & SSL_aRSA)
- {
- if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
- idx = SSL_PKEY_RSA_SIGN;
- else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
- idx = SSL_PKEY_RSA_ENC;
- }
- else if ((alg_a & SSL_aECDSA) &&
- (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
- idx = SSL_PKEY_ECC;
- if (idx == -1)
- {
- SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
- return(NULL);
- }
- if (pmd)
- *pmd = c->pkeys[idx].digest;
- return c->pkeys[idx].privatekey;
- }
+{
+ unsigned long alg_k, alg_a;
+ EVP_PKEY *pkey = NULL;
+ int keysize = 0;
+ int signature_nid = 0, md_nid = 0, pk_nid = 0;
+ const SSL_CIPHER *cs = s->s3->tmp.new_cipher;
+
+ alg_k = cs->algorithm_mkey;
+ alg_a = cs->algorithm_auth;
+
+ if (SSL_C_IS_EXPORT(cs)) {
+ /* ECDH key length in export ciphers must be <= 163 bits */
+ pkey = X509_get_pubkey(x);
+ if (pkey == NULL)
+ return 0;
+ keysize = EVP_PKEY_bits(pkey);
+ EVP_PKEY_free(pkey);
+ if (keysize > 163)
+ return 0;
+ }
+
+ /* This call populates the ex_flags field correctly */
+ X509_check_purpose(x, -1, 0);
+ if ((x->sig_alg) && (x->sig_alg->algorithm)) {
+ signature_nid = OBJ_obj2nid(x->sig_alg->algorithm);
+ OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid);
+ }
+ if (alg_k & SSL_kECDHe || alg_k & SSL_kECDHr) {
+ /* key usage, if present, must allow key agreement */
+ if (ku_reject(x, X509v3_KU_KEY_AGREEMENT)) {
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG,
+ SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT);
+ return 0;
+ }
+ if ((alg_k & SSL_kECDHe) && TLS1_get_version(s) < TLS1_2_VERSION) {
+ /* signature alg must be ECDSA */
+ if (pk_nid != NID_X9_62_id_ecPublicKey) {
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG,
+ SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE);
+ return 0;
+ }
+ }
+ if ((alg_k & SSL_kECDHr) && TLS1_get_version(s) < TLS1_2_VERSION) {
+ /* signature alg must be RSA */
+
+ if (pk_nid != NID_rsaEncryption && pk_nid != NID_rsa) {
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG,
+ SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE);
+ return 0;
+ }
+ }
+ }
+ if (alg_a & SSL_aECDSA) {
+ /* key usage, if present, must allow signing */
+ if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) {
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG,
+ SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+ return 0;
+ }
+ }
+
+ return 1; /* all checks are ok */
+}
+
+#endif
+
+static int ssl_get_server_cert_index(const SSL *s)
+{
+ int idx;
+ idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+ if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
+ idx = SSL_PKEY_RSA_SIGN;
+ if (idx == -1)
+ SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX, ERR_R_INTERNAL_ERROR);
+ return idx;
+}
+
+CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
+{
+ CERT *c;
+ int i;
+
+ c = s->cert;
+ if (!s->s3 || !s->s3->tmp.new_cipher)
+ return NULL;
+ ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
+
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+ /*
+ * Broken protocol test: return last used certificate: which may mismatch
+ * the one expected.
+ */
+ if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+ return c->key;
+#endif
+
+ i = ssl_get_server_cert_index(s);
+
+ /* This may or may not be an error. */
+ if (i < 0)
+ return NULL;
+
+ /* May be NULL. */
+ return &c->pkeys[i];
+}
+
+EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher,
+ const EVP_MD **pmd)
+{
+ unsigned long alg_a;
+ CERT *c;
+ int idx = -1;
+
+ alg_a = cipher->algorithm_auth;
+ c = s->cert;
+
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+ /*
+ * Broken protocol test: use last key: which may mismatch the one
+ * expected.
+ */
+ if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+ idx = c->key - c->pkeys;
+ else
+#endif
+
+ if ((alg_a & SSL_aDSS) &&
+ (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
+ idx = SSL_PKEY_DSA_SIGN;
+ else if (alg_a & SSL_aRSA) {
+ if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
+ idx = SSL_PKEY_RSA_SIGN;
+ else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
+ idx = SSL_PKEY_RSA_ENC;
+ } else if ((alg_a & SSL_aECDSA) &&
+ (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
+ idx = SSL_PKEY_ECC;
+ if (idx == -1) {
+ SSLerr(SSL_F_SSL_GET_SIGN_PKEY, ERR_R_INTERNAL_ERROR);
+ return (NULL);
+ }
+ if (pmd)
+ *pmd = c->pkeys[idx].digest;
+ return c->pkeys[idx].privatekey;
+}