Add support for certificate stores in CERT structure. This makes it
[openssl.git] / ssl / s3_lib.c
index dad84dca007bb5438cbf2be620f9ec0267c2aeae..3bc5ce952ad329454759bd207c08603b750c1f55 100644 (file)
@@ -3089,6 +3089,8 @@ static char * MS_CALLBACK srp_password_from_info_cb(SSL *s, void *arg)
        }
 #endif
 
+static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len);
+
 long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
        {
        int ret=0;
@@ -3415,10 +3417,46 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
                break;
 
        case SSL_CTRL_SET_SIGALGS:
-               return tls1_set_sigalgs(s->cert, parg, larg);
+               return tls1_set_sigalgs(s->cert, parg, larg, 0);
 
        case SSL_CTRL_SET_SIGALGS_LIST:
-               return tls1_set_sigalgs_list(s->cert, parg);
+               return tls1_set_sigalgs_list(s->cert, parg, 0);
+
+       case SSL_CTRL_SET_CLIENT_SIGALGS:
+               return tls1_set_sigalgs(s->cert, parg, larg, 1);
+
+       case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
+               return tls1_set_sigalgs_list(s->cert, parg, 1);
+
+       case SSL_CTRL_GET_CLIENT_CERT_TYPES:
+               {
+               const unsigned char **pctype = parg;
+               if (s->server || !s->s3->tmp.cert_req)
+                       return 0;
+               if (s->cert->ctypes)
+                       {
+                       if (pctype)
+                               *pctype = s->cert->ctypes;
+                       return (int)s->cert->ctype_num;
+                       }
+               if (pctype)
+                       *pctype = (unsigned char *)s->s3->tmp.ctype;
+               return s->s3->tmp.ctype_num;
+               }
+
+       case SSL_CTRL_SET_CLIENT_CERT_TYPES:
+               if (!s->server)
+                       return 0;
+               return ssl3_set_req_cert_type(s->cert, parg, larg);
+
+       case SSL_CTRL_BUILD_CERT_CHAIN:
+               return ssl_build_cert_chain(s->cert, s->ctx->cert_store, larg);
+
+       case SSL_CTRL_SET_VERIFY_CERT_STORE:
+               return ssl_cert_set_cert_store(s->cert, parg, 0, larg);
+
+       case SSL_CTRL_SET_CHAIN_CERT_STORE:
+               return ssl_cert_set_cert_store(s->cert, parg, 1, larg);
 
        default:
                break;
@@ -3703,10 +3741,28 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
                break;
 
        case SSL_CTRL_SET_SIGALGS:
-               return tls1_set_sigalgs(ctx->cert, parg, larg);
+               return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
 
        case SSL_CTRL_SET_SIGALGS_LIST:
-               return tls1_set_sigalgs_list(ctx->cert, parg);
+               return tls1_set_sigalgs_list(ctx->cert, parg, 0);
+
+       case SSL_CTRL_SET_CLIENT_SIGALGS:
+               return tls1_set_sigalgs(ctx->cert, parg, larg, 1);
+
+       case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
+               return tls1_set_sigalgs_list(ctx->cert, parg, 1);
+
+       case SSL_CTRL_SET_CLIENT_CERT_TYPES:
+               return ssl3_set_req_cert_type(ctx->cert, parg, larg);
+
+       case SSL_CTRL_BUILD_CERT_CHAIN:
+               return ssl_build_cert_chain(ctx->cert, ctx->cert_store, larg);
+
+       case SSL_CTRL_SET_VERIFY_CERT_STORE:
+               return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg);
+
+       case SSL_CTRL_SET_CHAIN_CERT_STORE:
+               return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg);
 
        case SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB_ARG:
                ctx->tlsext_authz_server_audit_proof_cb_arg = parg;
@@ -3921,6 +3977,8 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
                allow = srvr;
                }
 
+       tls1_set_cert_validity(s);
+
        for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
                {
                c=sk_SSL_CIPHER_value(prio,i);
@@ -3979,10 +4037,6 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
 
 #ifndef OPENSSL_NO_TLSEXT
 #ifndef OPENSSL_NO_EC
-               /* if we are considering an ECC cipher suite that uses our
-                * certificate check it */
-               if (alg_a & (SSL_aECDSA|SSL_aECDH))
-                       ok = ok && tls1_check_ec_server_key(s);
                /* if we are considering an ECC cipher suite that uses
                 * an ephemeral EC key check it */
                if (alg_k & SSL_kEECDH)
@@ -4004,8 +4058,61 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
 int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
        {
        int ret=0;
+       const unsigned char *sig;
+       size_t siglen;
+       int have_rsa_sign = 0, have_dsa_sign = 0, have_ecdsa_sign = 0;
+       int nostrict = 1;
        unsigned long alg_k;
 
+       /* If we have custom certificate types set, use them */
+       if (s->cert->ctypes)
+               {
+               memcpy(p, s->cert->ctypes, s->cert->ctype_num);
+               return (int)s->cert->ctype_num;
+               }
+       /* Else see if we have any signature algorithms configured */
+       if (s->cert->client_sigalgs)
+               {
+               sig = s->cert->client_sigalgs;
+               siglen = s->cert->client_sigalgslen;
+               }
+       else
+               {
+               sig = s->cert->conf_sigalgs;
+               siglen = s->cert->conf_sigalgslen;
+               }
+       /* If we have sigalgs work out if we can sign with RSA, DSA, ECDSA */
+       if (sig)
+               {
+               size_t i;
+               if (s->cert->cert_flags & SSL_CERT_FLAG_TLS_STRICT)
+                       nostrict = 0;
+               for (i = 0; i < siglen; i+=2, sig+=2)
+                       {
+                       switch(sig[1])
+                               {
+                       case TLSEXT_signature_rsa:
+                               have_rsa_sign = 1;
+                               break;
+
+                       case TLSEXT_signature_dsa:
+                               have_dsa_sign = 1;
+                               break;
+
+                       case TLSEXT_signature_ecdsa:
+                               have_ecdsa_sign = 1;
+                               break;
+                               }
+                       }
+               }
+       /* Otherwise allow anything */
+       else
+               {
+               have_rsa_sign = 1;
+               have_dsa_sign = 1;
+               have_ecdsa_sign = 1;
+               }
+
        alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
 #ifndef OPENSSL_NO_GOST
@@ -4024,10 +4131,15 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
        if (alg_k & (SSL_kDHr|SSL_kEDH))
                {
 #  ifndef OPENSSL_NO_RSA
-               p[ret++]=SSL3_CT_RSA_FIXED_DH;
+               /* Since this refers to a certificate signed with an RSA
+                * algorithm, only check for rsa signing in strict mode.
+                */
+               if (nostrict || have_rsa_sign)
+                       p[ret++]=SSL3_CT_RSA_FIXED_DH;
 #  endif
 #  ifndef OPENSSL_NO_DSA
-               p[ret++]=SSL3_CT_DSS_FIXED_DH;
+               if (nostrict || have_dsa_sign)
+                       p[ret++]=SSL3_CT_DSS_FIXED_DH;
 #  endif
                }
        if ((s->version == SSL3_VERSION) &&
@@ -4042,16 +4154,20 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
                }
 #endif /* !OPENSSL_NO_DH */
 #ifndef OPENSSL_NO_RSA
-       p[ret++]=SSL3_CT_RSA_SIGN;
+       if (have_rsa_sign)
+               p[ret++]=SSL3_CT_RSA_SIGN;
 #endif
 #ifndef OPENSSL_NO_DSA
-       p[ret++]=SSL3_CT_DSS_SIGN;
+       if (have_dsa_sign)
+               p[ret++]=SSL3_CT_DSS_SIGN;
 #endif
 #ifndef OPENSSL_NO_ECDH
        if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->version >= TLS1_VERSION))
                {
-               p[ret++]=TLS_CT_RSA_FIXED_ECDH;
-               p[ret++]=TLS_CT_ECDSA_FIXED_ECDH;
+               if (nostrict || have_rsa_sign)
+                       p[ret++]=TLS_CT_RSA_FIXED_ECDH;
+               if (nostrict || have_ecdsa_sign)
+                       p[ret++]=TLS_CT_ECDSA_FIXED_ECDH;
                }
 #endif
 
@@ -4061,12 +4177,32 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
         */
        if (s->version >= TLS1_VERSION)
                {
-               p[ret++]=TLS_CT_ECDSA_SIGN;
+               if (have_ecdsa_sign)
+                       p[ret++]=TLS_CT_ECDSA_SIGN;
                }
 #endif 
        return(ret);
        }
 
+static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len)
+       {
+       if (c->ctypes)
+               {
+               OPENSSL_free(c->ctypes);
+               c->ctypes = NULL;
+               }
+       if (!p || !len)
+               return 1;
+       if (len > 0xff)
+               return 0;
+       c->ctypes = OPENSSL_malloc(len);
+       if (!c->ctypes)
+               return 0;
+       memcpy(c->ctypes, p, len);
+       c->ctype_num = len;
+       return 1;
+       }
+
 int ssl3_shutdown(SSL *s)
        {
        int ret;