-/* THIS NEEDS CLEANING UP */
-CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
- {
- unsigned long alg_k,alg_a;
- CERT *c;
- int i;
-
- c=s->cert;
- ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
-
- 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.
- */
- i=SSL_PKEY_ECC;
- }
- else if (alg_a & SSL_aECDSA)
- {
- i=SSL_PKEY_ECC;
- }
- else if (alg_k & SSL_kDHr)
- i=SSL_PKEY_DH_RSA;
- else if (alg_k & SSL_kDHd)
- i=SSL_PKEY_DH_DSA;
- else if (alg_a & SSL_aDSS)
- i=SSL_PKEY_DSA_SIGN;
- else if (alg_a & SSL_aRSA)
- {
- if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
- i=SSL_PKEY_RSA_SIGN;
- else
- i=SSL_PKEY_RSA_ENC;
- }
- else if (alg_a & SSL_aKRB5)
- {
- /* VRS something else here? */
- return(NULL);
- }
- else if (alg_a & SSL_aGOST94)
- i=SSL_PKEY_GOST94;
- else if (alg_a & SSL_aGOST01)
- i=SSL_PKEY_GOST01;
- else /* if (alg_a & SSL_aNULL) */
- {
- SSLerr(SSL_F_SSL_GET_SERVER_SEND_PKEY,ERR_R_INTERNAL_ERROR);
- return(NULL);
- }
- if (c->pkeys[i].x509 == NULL) return(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;
- }
-
-void ssl_update_cache(SSL *s,int mode)
- {
- int i;
-
- /* If the session_id_length is 0, we are not supposed to cache it,
- * and it would be rather hard to do anyway :-) */
- if (s->session->session_id_length == 0) return;
-
- i=s->session_ctx->session_cache_mode;
- if ((i & mode) && (!s->hit)
- && ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
- || SSL_CTX_add_session(s->session_ctx,s->session))
- && (s->session_ctx->new_session_cb != NULL))
- {
- CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION);
- if (!s->session_ctx->new_session_cb(s,s->session))
- SSL_SESSION_free(s->session);
- }
-
- /* auto flush every 255 connections */
- if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) &&
- ((i & mode) == mode))
- {
- if ( (((mode & SSL_SESS_CACHE_CLIENT)
- ?s->session_ctx->stats.sess_connect_good
- :s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff)
- {
- SSL_CTX_flush_sessions(s->session_ctx,(unsigned long)time(NULL));
- }
- }
- }
+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;
+}
+
+#ifndef OPENSSL_NO_TLSEXT
+int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
+ size_t *serverinfo_length)
+{
+ CERT *c = NULL;
+ int i = 0;
+ *serverinfo_length = 0;
+
+ c = s->cert;
+ i = ssl_get_server_cert_index(s);
+
+ if (i == -1)
+ return 0;
+ if (c->pkeys[i].serverinfo == NULL)
+ return 0;
+
+ *serverinfo = c->pkeys[i].serverinfo;
+ *serverinfo_length = c->pkeys[i].serverinfo_length;
+ return 1;
+}
+#endif
+
+void ssl_update_cache(SSL *s, int mode)
+{
+ int i;
+
+ /*
+ * If the session_id_length is 0, we are not supposed to cache it, and it
+ * would be rather hard to do anyway :-)
+ */
+ if (s->session->session_id_length == 0)
+ return;
+
+ i = s->session_ctx->session_cache_mode;
+ if ((i & mode) && (!s->hit)
+ && ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
+ || SSL_CTX_add_session(s->session_ctx, s->session))
+ && (s->session_ctx->new_session_cb != NULL)) {
+ CRYPTO_add(&s->session->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ if (!s->session_ctx->new_session_cb(s, s->session))
+ SSL_SESSION_free(s->session);
+ }
+
+ /* auto flush every 255 connections */
+ if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
+ if ((((mode & SSL_SESS_CACHE_CLIENT)
+ ? s->session_ctx->stats.sess_connect_good
+ : s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff) {
+ SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL));
+ }
+ }
+}
+
+const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx)
+{
+ return ctx->method;
+}