Reorganise supported signature algorithm extension processing.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 25 Jun 2012 14:32:30 +0000 (14:32 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 25 Jun 2012 14:32:30 +0000 (14:32 +0000)
Only store encoded versions of peer and configured signature algorithms.
Determine shared signature algorithms and cache the result along with NID
equivalents of each algorithm.

CHANGES
apps/s_apps.h
apps/s_cb.c
apps/s_client.c
apps/s_server.c
ssl/ssl.h
ssl/ssl_cert.c
ssl/ssl_err.c
ssl/ssl_locl.h
ssl/t1_lib.c
ssl/tls1.h

diff --git a/CHANGES b/CHANGES
index 30018c80bd9e292a98e6e9abe1f7d452587099bc..33956e2c18645601f58f66ae8350a93f496aec2c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
+  *) Update and tidy signature algorithm extension processing. Work out
+     shared signature algorithms based on preferences and peer algorithms
+     and print them out in s_client and s_server. Abort handshake if no
+     shared signature algorithms.
+     [Steve Henson]
+
   *) Add new functions to allow customised supported signature algorithms
      for SSL and SSL_CTX structures. Add options to s_client and s_server
      to support them.
   *) Add new functions to allow customised supported signature algorithms
      for SSL and SSL_CTX structures. Add options to s_client and s_server
      to support them.
index 4effcd21d7057486252116f0fc986bfcedc90f09..8c644ec7dbb20c24ef534b8afc750ee266150eff 100644 (file)
@@ -160,7 +160,7 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
 int set_cert_key_and_authz(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
                            unsigned char *authz, size_t authz_length);
 # endif
 int set_cert_key_and_authz(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
                            unsigned char *authz, size_t authz_length);
 # endif
-int ssl_print_sigalgs(BIO *out, SSL *s);
+int ssl_print_sigalgs(BIO *out, SSL *s, int client);
 int ssl_print_curves(BIO *out, SSL *s);
 #endif
 int init_client(int *sock, char *server, int port, int type);
 int ssl_print_curves(BIO *out, SSL *s);
 #endif
 int init_client(int *sock, char *server, int port, int type);
index c07066b6b6b6372679cd7f650e72a6199fd6ffb0..79e8ae55a7795ef168697dc14be971aab199f81c 100644 (file)
@@ -285,20 +285,33 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
        return 1;
        }
 
        return 1;
        }
 
-int ssl_print_sigalgs(BIO *out, SSL *s)
+static int do_print_sigalgs(BIO *out, SSL *s, int client, int shared)
        {
        int i, nsig;
        {
        int i, nsig;
-       nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
+       if (shared)
+               nsig = SSL_get_shared_sigalgs(s, -1, NULL, NULL, NULL,
+                                                       NULL, NULL);
+       else
+               nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
        if (nsig == 0)
                return 1;
 
        if (nsig == 0)
                return 1;
 
+       if (shared)
+               BIO_puts(out, "Shared ");
+
+       if (client)
+               BIO_puts(out, "Requested ");
        BIO_puts(out, "Signature Algorithms: ");
        for (i = 0; i < nsig; i++)
                {
                int hash_nid, sign_nid;
                unsigned char rhash, rsign;
                const char *sstr = NULL;
        BIO_puts(out, "Signature Algorithms: ");
        for (i = 0; i < nsig; i++)
                {
                int hash_nid, sign_nid;
                unsigned char rhash, rsign;
                const char *sstr = NULL;
-               SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
+               if (shared)
+                       SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
+                                                       &rsign, &rhash);
+               else
+                       SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
                                                        &rsign, &rhash);
                if (i)
                        BIO_puts(out, ":");
                                                        &rsign, &rhash);
                if (i)
                        BIO_puts(out, ":");
@@ -321,6 +334,13 @@ int ssl_print_sigalgs(BIO *out, SSL *s)
        return 1;
        }
 
        return 1;
        }
 
+int ssl_print_sigalgs(BIO *out, SSL *s, int client)
+       {
+       do_print_sigalgs(out, s, client, 0);
+       do_print_sigalgs(out, s, client, 1);
+       return 1;
+       }
+
 int ssl_print_curves(BIO *out, SSL *s)
        {
        int i, ncurves, *curves, nid;
 int ssl_print_curves(BIO *out, SSL *s)
        {
        int i, ncurves, *curves, nid;
index c2dce1febfa641ca971b932ec5e7c27e9fb5a67e..a971ad6a61491542a78631921985c864c658ebe2 100644 (file)
@@ -2064,7 +2064,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
                        BIO_write(bio,"\n",1);
                        }
 
                        BIO_write(bio,"\n",1);
                        }
 
-               ssl_print_sigalgs(bio, s);
+               ssl_print_sigalgs(bio, s, 1);
 
                BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n",
                        BIO_number_read(SSL_get_rbio(s)),
 
                BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n",
                        BIO_number_read(SSL_get_rbio(s)),
index 9467e28a416c438a865f5e7f5f2f6608f0ad4f84..e679f3e5895ea7098a8fdf195e1f5497e9960341 100644 (file)
@@ -2572,7 +2572,7 @@ static int init_ssl_connection(SSL *con)
        if (SSL_get_shared_ciphers(con,buf,sizeof buf) != NULL)
                BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf);
        str=SSL_CIPHER_get_name(SSL_get_current_cipher(con));
        if (SSL_get_shared_ciphers(con,buf,sizeof buf) != NULL)
                BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf);
        str=SSL_CIPHER_get_name(SSL_get_current_cipher(con));
-       ssl_print_sigalgs(bio_s_out, con);
+       ssl_print_sigalgs(bio_s_out, con, 0);
        ssl_print_curves(bio_s_out, con);
        BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)");
 
        ssl_print_curves(bio_s_out, con);
        BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)");
 
@@ -2915,7 +2915,7 @@ static int www_body(char *hostname, int s, unsigned char *context)
                                        }
                                BIO_puts(io,"\n");
                                }
                                        }
                                BIO_puts(io,"\n");
                                }
-                       ssl_print_sigalgs(io, con);
+                       ssl_print_sigalgs(io, con, 0);
                        ssl_print_curves(io, con);
                        BIO_printf(io,(SSL_cache_hit(con)
                                ?"---\nReused, "
                        ssl_print_curves(io, con);
                        BIO_printf(io,(SSL_cache_hit(con)
                                ?"---\nReused, "
index 2fbc6ba61995b2aa632f942494f7773797b1e9f8..2095d0f2849af460f77ed5678958b6322626d420 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2551,6 +2551,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_NO_RENEGOTIATION                          339
 #define SSL_R_NO_REQUIRED_DIGEST                        324
 #define SSL_R_NO_SHARED_CIPHER                          193
 #define SSL_R_NO_RENEGOTIATION                          339
 #define SSL_R_NO_REQUIRED_DIGEST                        324
 #define SSL_R_NO_SHARED_CIPHER                          193
+#define SSL_R_NO_SHARED_SIGATURE_ALGORITHMS             376
 #define SSL_R_NO_SRTP_PROFILES                          359
 #define SSL_R_NO_VERIFY_CALLBACK                        194
 #define SSL_R_NULL_SSL_CTX                              195
 #define SSL_R_NO_SRTP_PROFILES                          359
 #define SSL_R_NO_VERIFY_CALLBACK                        194
 #define SSL_R_NULL_SSL_CTX                              195
index 72443ec1f549964cdf179a45efb7d0154a9449eb..4205f6e6cccee320c6d662e0a60d341547199b8d 100644 (file)
@@ -160,7 +160,7 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
        return ssl_x509_store_ctx_idx;
        }
 
        return ssl_x509_store_ctx_idx;
        }
 
-static void ssl_cert_set_default_md(CERT *cert)
+void ssl_cert_set_default_md(CERT *cert)
        {
        /* Set digest values to defaults */
 #ifndef OPENSSL_NO_DSA
        {
        /* Set digest values to defaults */
 #ifndef OPENSSL_NO_DSA
@@ -373,6 +373,8 @@ CERT *ssl_cert_dup(CERT *cert)
                }
        else
                ret->conf_sigalgs = NULL;
                }
        else
                ret->conf_sigalgs = NULL;
+       /* Shared sigalgs also NULL */
+       ret->shared_sigalgs = NULL;
 
        return(ret);
        
 
        return(ret);
        
@@ -464,6 +466,8 @@ void ssl_cert_free(CERT *c)
                OPENSSL_free(c->peer_sigalgs);
        if (c->conf_sigalgs)
                OPENSSL_free(c->conf_sigalgs);
                OPENSSL_free(c->peer_sigalgs);
        if (c->conf_sigalgs)
                OPENSSL_free(c->conf_sigalgs);
+       if (c->shared_sigalgs)
+               OPENSSL_free(c->shared_sigalgs);
        OPENSSL_free(c);
        }
 
        OPENSSL_free(c);
        }
 
index e6736fb101ae2c200ab61efe4580e670d4b505d4..3b32f55e44696eb749eb0ac233912013f1e95394 100644 (file)
@@ -462,6 +462,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_NO_RENEGOTIATION)      ,"no renegotiation"},
 {ERR_REASON(SSL_R_NO_REQUIRED_DIGEST)    ,"digest requred for handshake isn't computed"},
 {ERR_REASON(SSL_R_NO_SHARED_CIPHER)      ,"no shared cipher"},
 {ERR_REASON(SSL_R_NO_RENEGOTIATION)      ,"no renegotiation"},
 {ERR_REASON(SSL_R_NO_REQUIRED_DIGEST)    ,"digest requred for handshake isn't computed"},
 {ERR_REASON(SSL_R_NO_SHARED_CIPHER)      ,"no shared cipher"},
+{ERR_REASON(SSL_R_NO_SHARED_SIGATURE_ALGORITHMS),"no shared sigature algorithms"},
 {ERR_REASON(SSL_R_NO_SRTP_PROFILES)      ,"no srtp profiles"},
 {ERR_REASON(SSL_R_NO_VERIFY_CALLBACK)    ,"no verify callback"},
 {ERR_REASON(SSL_R_NULL_SSL_CTX)          ,"null ssl ctx"},
 {ERR_REASON(SSL_R_NO_SRTP_PROFILES)      ,"no srtp profiles"},
 {ERR_REASON(SSL_R_NO_VERIFY_CALLBACK)    ,"no verify callback"},
 {ERR_REASON(SSL_R_NULL_SSL_CTX)          ,"null ssl ctx"},
index 671b2dfe04d490255bd497bca11d121613649f03..16fa9436485c09f4bf92f955efe01cb41502eaa5 100644 (file)
@@ -521,15 +521,20 @@ typedef struct cert_st
         * algorithms extension for server or as part of a certificate
         * request for client.
         */
         * algorithms extension for server or as part of a certificate
         * request for client.
         */
-       TLS_SIGALGS *peer_sigalgs;
+       unsigned char *peer_sigalgs;
        /* Size of above array */
        size_t peer_sigalgslen;
        /* configured signature algorithms (can be NULL for default).
         * sent in signature algorithms extension or certificate request.
         */
        /* Size of above array */
        size_t peer_sigalgslen;
        /* configured signature algorithms (can be NULL for default).
         * sent in signature algorithms extension or certificate request.
         */
-       TLS_SIGALGS *conf_sigalgs;
+       unsigned char *conf_sigalgs;
        /* Size of above array */
        size_t conf_sigalgslen;
        /* Size of above array */
        size_t conf_sigalgslen;
+       /* Signature algorithms shared by client and server: cached
+        * because these are used most often
+        */
+       TLS_SIGALGS *shared_sigalgs;
+       size_t shared_sigalgslen;
 
        int references; /* >1 only if SSL_copy_session_id is used */
        } CERT;
 
        int references; /* >1 only if SSL_copy_session_id is used */
        } CERT;
@@ -839,6 +844,7 @@ void ssl_clear_cipher_ctx(SSL *s);
 int ssl_clear_bad_session(SSL *s);
 CERT *ssl_cert_new(void);
 CERT *ssl_cert_dup(CERT *cert);
 int ssl_clear_bad_session(SSL *s);
 CERT *ssl_cert_new(void);
 CERT *ssl_cert_dup(CERT *cert);
+void ssl_cert_set_default_md(CERT *cert);
 int ssl_cert_inst(CERT **o);
 void ssl_cert_clear_certs(CERT *c);
 void ssl_cert_free(CERT *c);
 int ssl_cert_inst(CERT **o);
 void ssl_cert_clear_certs(CERT *c);
 void ssl_cert_free(CERT *c);
index dcfecf4f5b79b077215bfd268d286bc5fc210c7f..5fae9fb4260bb972484e6c5e8a19440cd98d8b56 100644 (file)
@@ -631,35 +631,26 @@ static unsigned char tls12_sigalgs[] = {
 
 size_t tls12_get_sig_algs(SSL *s, unsigned char *p)
        {
 
 size_t tls12_get_sig_algs(SSL *s, unsigned char *p)
        {
-       TLS_SIGALGS *sptr = s->cert->conf_sigalgs;
-       size_t slen;
+       const unsigned char *sigs;
+       size_t sigslen;
+       sigs = s->cert->conf_sigalgs;
 
 
-       /* Use custom signature algorithms if any are set */
-
-       if (sptr)
+       if (sigs)
+               sigslen = s->cert->conf_sigalgslen;
+       else
                {
                {
-               slen = s->cert->conf_sigalgslen;
-               if (p)
-                       {
-                       size_t i;
-                       for (i = 0; i < slen; i++, sptr++)
-                               {
-                               *p++ = sptr->rhash;
-                               *p++ = sptr->rsign;
-                               }
-                       }
-               return slen * 2;
-               }
-               
-       slen = sizeof(tls12_sigalgs);
+               sigs = tls12_sigalgs;
+               sigslen = sizeof(tls12_sigalgs);
 #ifdef OPENSSL_FIPS
 #ifdef OPENSSL_FIPS
-       /* If FIPS mode don't include MD5 which is last */
-       if (FIPS_mode())
-               slen -= 2;
+               /* If FIPS mode don't include MD5 which is last */
+               if (FIPS_mode())
+                       sigslen -= 2;
 #endif
 #endif
+               }
+
        if (p)
        if (p)
-               memcpy(p, tls12_sigalgs, slen);
-       return slen;
+               memcpy(p, sigs, sigslen);
+       return sigslen;
        }
 
 /* byte_compare is a compare function for qsort(3) that compares bytes. */
        }
 
 /* byte_compare is a compare function for qsort(3) that compares bytes. */
@@ -1312,7 +1303,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
        unsigned short len;
        unsigned char *data = *p;
        int renegotiate_seen = 0;
        unsigned short len;
        unsigned char *data = *p;
        int renegotiate_seen = 0;
-       int sigalg_seen = 0;
 
        s->servername_done = 0;
        s->tlsext_status_type = -1;
 
        s->servername_done = 0;
        s->tlsext_status_type = -1;
@@ -1324,6 +1314,18 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
        s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
                               SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
 #endif
        s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
                               SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
 #endif
+       /* Clear any signature algorithms extension received */
+       if (s->cert->peer_sigalgs)
+               {
+               OPENSSL_free(s->cert->peer_sigalgs);
+               s->cert->peer_sigalgs = NULL;
+               }
+       /* Clear any shared sigtnature algorithms */
+       if (s->cert->shared_sigalgs)
+               {
+               OPENSSL_free(s->cert->shared_sigalgs);
+               s->cert->shared_sigalgs = NULL;
+               }
 
        if (data >= (d+n-2))
                goto ri_check;
 
        if (data >= (d+n-2))
                goto ri_check;
@@ -1599,15 +1601,14 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                else if (type == TLSEXT_TYPE_signature_algorithms)
                        {
                        int dsize;
                else if (type == TLSEXT_TYPE_signature_algorithms)
                        {
                        int dsize;
-                       if (sigalg_seen || size < 2) 
+                       if (s->cert->peer_sigalgs || size < 2) 
                                {
                                *al = SSL_AD_DECODE_ERROR;
                                return 0;
                                }
                                {
                                *al = SSL_AD_DECODE_ERROR;
                                return 0;
                                }
-                       sigalg_seen = 1;
                        n2s(data,dsize);
                        size -= 2;
                        n2s(data,dsize);
                        size -= 2;
-                       if (dsize != size || dsize & 1) 
+                       if (dsize != size || dsize & 1 || !dsize
                                {
                                *al = SSL_AD_DECODE_ERROR;
                                return 0;
                                {
                                *al = SSL_AD_DECODE_ERROR;
                                return 0;
@@ -1617,6 +1618,16 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                                *al = SSL_AD_DECODE_ERROR;
                                return 0;
                                }
                                *al = SSL_AD_DECODE_ERROR;
                                return 0;
                                }
+                       /* If sigalgs received and no shared algorithms fatal
+                        * error.
+                        */
+                       if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs)
+                               {
+                               SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT,
+                                       SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
+                               *al = SSL_AD_ILLEGAL_PARAMETER;
+                               return 0;
+                               }
                        }
                else if (type == TLSEXT_TYPE_status_request &&
                         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
                        }
                else if (type == TLSEXT_TYPE_status_request &&
                         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
@@ -1855,6 +1866,9 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                                SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
                return 0;
                }
                                SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
                return 0;
                }
+       /* If no signature algorithms extension set default values */
+       if (!s->cert->peer_sigalgs)
+               ssl_cert_set_default_md(s->cert);
 
        return 1;
        }
 
        return 1;
        }
@@ -2861,11 +2875,145 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg)
                }
        }
 
                }
        }
 
+static int tls12_get_pkey_idx(unsigned char sig_alg)
+       {
+       switch(sig_alg)
+               {
+#ifndef OPENSSL_NO_RSA
+       case TLSEXT_signature_rsa:
+               return SSL_PKEY_RSA_SIGN;
+#endif
+#ifndef OPENSSL_NO_DSA
+       case TLSEXT_signature_dsa:
+               return SSL_PKEY_DSA_SIGN;
+#endif
+#ifndef OPENSSL_NO_ECDSA
+       case TLSEXT_signature_ecdsa:
+               return SSL_PKEY_ECC;
+#endif
+               }
+       return -1;
+       }
+
+/* Convert TLS 1.2 signature algorithm extension values into NIDs */
+static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
+                       int *psignhash_nid, const unsigned char *data)
+       {
+       int sign_nid, hash_nid;
+       if (!phash_nid && !psign_nid && !psignhash_nid)
+               return;
+       if (phash_nid || psignhash_nid)
+               {
+               hash_nid = tls12_find_nid(data[0], tls12_md,
+                                       sizeof(tls12_md)/sizeof(tls12_lookup));
+               if (phash_nid)
+                       *phash_nid = hash_nid;
+               }
+       if (psign_nid || psignhash_nid)
+               {
+               sign_nid = tls12_find_nid(data[1], tls12_sig,
+                                       sizeof(tls12_sig)/sizeof(tls12_lookup));
+               if (psign_nid)
+                       *psign_nid = sign_nid;
+               }
+       if (psignhash_nid)
+               {
+               if (sign_nid && hash_nid)
+                       OBJ_find_sigid_by_algs(psignhash_nid,
+                                                       hash_nid, sign_nid);
+               else
+                       *psignhash_nid = NID_undef;
+               }
+       }
+/* Given preference and allowed sigalgs set shared sigalgs */
+static int tls12_do_shared_sigalgs(TLS_SIGALGS *shsig,
+                               const unsigned char *pref, size_t preflen,
+                               const unsigned char *allow, size_t allowlen)
+       {
+       const unsigned char *ptmp, *atmp;
+       size_t i, j, nmatch = 0;
+       for (i = 0, ptmp = pref; i < preflen; i+=2, ptmp+=2)
+               {
+               /* Skip disabled hashes or signature algorithms */
+               if (tls12_get_hash(ptmp[0]) == NULL)
+                       continue;
+               if (tls12_get_pkey_idx(ptmp[1]) == -1)
+                       continue;
+               for (j = 0, atmp = allow; j < allowlen; j+=2, atmp+=2)
+                       {
+                       if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1])
+                               {
+                               nmatch++;
+                               if (shsig)
+                                       {
+                                       shsig->rhash = ptmp[0];
+                                       shsig->rsign = ptmp[1];
+                                       tls1_lookup_sigalg(&shsig->hash_nid,
+                                               &shsig->sign_nid,
+                                               &shsig->signandhash_nid,
+                                               ptmp);
+                                       shsig++;
+                                       }
+                               break;
+                               }
+                       }
+               }
+       return nmatch;
+       }
+
+/* Set shared signature algorithms for SSL structures */
+static int tls1_set_shared_sigalgs(SSL *s)
+       {
+       const unsigned char *pref, *allow, *conf;
+       size_t preflen, allowlen, conflen;
+       size_t nmatch;
+       TLS_SIGALGS *salgs = NULL;
+       CERT *c = s->cert;
+       conf = c->conf_sigalgs;
+       if (conf)
+               conflen = c->conf_sigalgslen;
+       else
+               {
+               conf = tls12_sigalgs;
+               conflen = sizeof(tls12_sigalgs);
+#ifdef OPENSSL_FIPS
+               if (FIPS_mode())
+                       conflen -= 2;
+#endif
+               }
+       if(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+               {
+               pref = conf;
+               preflen = conflen;
+               allow = c->peer_sigalgs;
+               allowlen = c->peer_sigalgslen;
+               }
+       else
+               {
+               allow = conf;
+               allowlen = conflen;
+               pref = c->peer_sigalgs;
+               preflen = c->peer_sigalgslen;
+               }
+       nmatch = tls12_do_shared_sigalgs(NULL, pref, preflen, allow, allowlen);
+       if (!nmatch)
+               return 1;
+       salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS));
+       if (!salgs)
+               return 0;
+       nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen);
+       c->shared_sigalgs = salgs;
+       c->shared_sigalgslen = nmatch;
+       return 1;
+       }
+               
+
 /* Set preferred digest for each key type */
 
 int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
        {
 /* Set preferred digest for each key type */
 
 int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
        {
-       int i, idx;
+       int idx;
+       size_t i;
        const EVP_MD *md;
        CERT *c = s->cert;
        TLS_SIGALGS *sigptr;
        const EVP_MD *md;
        CERT *c = s->cert;
        TLS_SIGALGS *sigptr;
@@ -2881,60 +3029,27 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
        c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
        c->pkeys[SSL_PKEY_ECC].digest = NULL;
 
        c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
        c->pkeys[SSL_PKEY_ECC].digest = NULL;
 
-       if (c->peer_sigalgs)
-               OPENSSL_free(c->peer_sigalgs);
-       c->peer_sigalgs = OPENSSL_malloc((dsize/2) * sizeof(TLS_SIGALGS));
+       c->peer_sigalgs = OPENSSL_malloc(dsize);
        if (!c->peer_sigalgs)
                return 0;
        if (!c->peer_sigalgs)
                return 0;
-       c->peer_sigalgslen = dsize/2;
+       c->peer_sigalgslen = dsize;
+       memcpy(c->peer_sigalgs, data, dsize);
 
 
-       for (i = 0, sigptr = c->peer_sigalgs; i < dsize; i += 2, sigptr++)
-               {
-               sigptr->rhash = data[i];
-               sigptr->rsign = data[i + 1];
-               sigptr->hash_nid = tls12_find_nid(sigptr->rhash, tls12_md,
-                                       sizeof(tls12_md)/sizeof(tls12_lookup));
-               sigptr->sign_nid = tls12_find_nid(sigptr->rsign, tls12_sig,
-                                       sizeof(tls12_sig)/sizeof(tls12_lookup));
-               if (!OBJ_find_sigid_by_algs(&sigptr->signandhash_nid,
-                                               sigptr->hash_nid,
-                                               sigptr->sign_nid))
-                       sigptr->signandhash_nid = NID_undef;
-               switch(sigptr->rsign)
-                       {
-#ifndef OPENSSL_NO_RSA
-                       case TLSEXT_signature_rsa:
-                       idx = SSL_PKEY_RSA_SIGN;
-                       break;
-#endif
-#ifndef OPENSSL_NO_DSA
-                       case TLSEXT_signature_dsa:
-                       idx = SSL_PKEY_DSA_SIGN;
-                       break;
-#endif
-#ifndef OPENSSL_NO_ECDSA
-                       case TLSEXT_signature_ecdsa:
-                       idx = SSL_PKEY_ECC;
-                       break;
-#endif
-                       default:
-                       continue;
-                       }
+       tls1_set_shared_sigalgs(s);
 
 
-               if (c->pkeys[idx].digest == NULL)
+       for (i = 0, sigptr = c->shared_sigalgs;
+                       i < c->shared_sigalgslen; i++, sigptr++)
+               {
+               idx = tls12_get_pkey_idx(sigptr->rsign);
+               if (idx > 0 && c->pkeys[idx].digest == NULL)
                        {
                        md = tls12_get_hash(sigptr->rhash);
                        {
                        md = tls12_get_hash(sigptr->rhash);
-                       if (md)
-                               {
-                               c->pkeys[idx].digest = md;
-                               if (idx == SSL_PKEY_RSA_SIGN)
-                                       c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
-                               }
+                       c->pkeys[idx].digest = md;
+                       if (idx == SSL_PKEY_RSA_SIGN)
+                               c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
                        }
 
                }
                        }
 
                }
-
-
        /* Set any remaining keys to default values. NOTE: if alg is not
         * supported it stays as NULL.
         */
        /* Set any remaining keys to default values. NOTE: if alg is not
         * supported it stays as NULL.
         */
@@ -2956,32 +3071,48 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
        return 1;
        }
 
        return 1;
        }
 
-#endif
 
 int SSL_get_sigalgs(SSL *s, int idx,
 
 int SSL_get_sigalgs(SSL *s, int idx,
-                       int *psign, int *phash, int *psignandhash,
+                       int *psign, int *phash, int *psignhash,
                        unsigned char *rsig, unsigned char *rhash)
        {
                        unsigned char *rsig, unsigned char *rhash)
        {
-       if (s->cert->peer_sigalgs == NULL)
+       const unsigned char *psig = s->cert->peer_sigalgs;
+       if (psig == NULL)
                return 0;
        if (idx >= 0)
                {
                return 0;
        if (idx >= 0)
                {
-               TLS_SIGALGS *psig;
+               idx <<= 1;
                if (idx >= (int)s->cert->peer_sigalgslen)
                        return 0;
                if (idx >= (int)s->cert->peer_sigalgslen)
                        return 0;
-               psig = s->cert->peer_sigalgs + idx;
-               if (psign)
-                       *psign = psig->sign_nid;
-               if (phash)
-                       *phash = psig->hash_nid;
-               if (psignandhash)
-                       *psignandhash = psig->signandhash_nid;
-               if (rsig)
-                       *rsig = psig->rsign;
+               psig += idx;
                if (rhash)
                if (rhash)
-                       *rhash = psig->rhash;
+                       *rhash = psig[0];
+               if (rsig)
+                       *rsig = psig[1];
+               tls1_lookup_sigalg(phash, psign, psignhash, psig);
                }
                }
-       return s->cert->peer_sigalgslen;
+       return s->cert->peer_sigalgslen / 2;
+       }
+
+int SSL_get_shared_sigalgs(SSL *s, int idx,
+                       int *psign, int *phash, int *psignhash,
+                       unsigned char *rsig, unsigned char *rhash)
+       {
+       TLS_SIGALGS *shsigalgs = s->cert->shared_sigalgs;
+       if (!shsigalgs || idx >= (int)s->cert->shared_sigalgslen)
+               return 0;
+       shsigalgs += idx;
+       if (phash)
+               *phash = shsigalgs->hash_nid;
+       if (psign)
+               *psign = shsigalgs->sign_nid;
+       if (psignhash)
+               *psignhash = shsigalgs->signandhash_nid;
+       if (rsig)
+               *rsig = shsigalgs->rsign;
+       if (rhash)
+               *rhash = shsigalgs->rhash;
+       return s->cert->shared_sigalgslen;
        }
        
 
        }
        
 
@@ -3130,7 +3261,7 @@ tls1_heartbeat(SSL *s)
        }
 #endif
 
        }
 #endif
 
-#define MAX_SIGALGLEN  (TLSEXT_hash_num * TLSEXT_signature_num *2)
+#define MAX_SIGALGLEN  (TLSEXT_hash_num * TLSEXT_signature_num * 2)
 
 typedef struct
        {
 
 typedef struct
        {
@@ -3194,35 +3325,27 @@ int tls1_set_sigalgs_list(CERT *c, const char *str)
        return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt);
        }
 
        return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt);
        }
 
-int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen)
+int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen)
        {
        {
-       TLS_SIGALGS *sigalgs, *sptr;
+       unsigned char *sigalgs, *sptr;
        int rhash, rsign;
        size_t i;
        if (salglen & 1)
                return 0;
        int rhash, rsign;
        size_t i;
        if (salglen & 1)
                return 0;
-       salglen /= 2;
-       sigalgs = OPENSSL_malloc(sizeof(TLS_SIGALGS) * salglen);
+       sigalgs = OPENSSL_malloc(salglen);
        if (sigalgs == NULL)
                return 0;
        if (sigalgs == NULL)
                return 0;
-       for (i = 0, sptr = sigalgs; i < salglen; i++, sptr++)
+       for (i = 0, sptr = sigalgs; i < salglen; i+=2)
                {
                {
-               sptr->hash_nid = *salg++;
-               sptr->sign_nid = *salg++;
-               rhash = tls12_find_id(sptr->hash_nid, tls12_md,
+               rhash = tls12_find_id(*psig_nids++, tls12_md,
                                        sizeof(tls12_md)/sizeof(tls12_lookup));
                                        sizeof(tls12_md)/sizeof(tls12_lookup));
-               rsign = tls12_find_id(sptr->sign_nid, tls12_sig,
+               rsign = tls12_find_id(*psig_nids++, tls12_sig,
                                sizeof(tls12_sig)/sizeof(tls12_lookup));
 
                if (rhash == -1 || rsign == -1)
                        goto err;
                                sizeof(tls12_sig)/sizeof(tls12_lookup));
 
                if (rhash == -1 || rsign == -1)
                        goto err;
-
-               if (!OBJ_find_sigid_by_algs(&sptr->signandhash_nid,
-                                               sptr->hash_nid,
-                                               sptr->sign_nid))
-                       sptr->signandhash_nid = NID_undef;
-               sptr->rhash = rhash;
-               sptr->rsign = rsign;
+               *sptr++ = rhash;
+               *sptr++ = rsign;
                }
 
        if (c->conf_sigalgs)
                }
 
        if (c->conf_sigalgs)
@@ -3236,3 +3359,5 @@ int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen)
        OPENSSL_free(sigalgs);
        return 0;
        }
        OPENSSL_free(sigalgs);
        return 0;
        }
+
+#endif
index 2f6a34c48182950d06f050ac3104e12e26808c98..e2acad4d70505481d48242eb9140bee271b8df93 100644 (file)
@@ -314,6 +314,10 @@ int SSL_get_sigalgs(SSL *s, int idx,
                        int *psign, int *phash, int *psignandhash,
                        unsigned char *rsig, unsigned char *rhash);
 
                        int *psign, int *phash, int *psignandhash,
                        unsigned char *rsig, unsigned char *rhash);
 
+int SSL_get_shared_sigalgs(SSL *s, int idx,
+                       int *psign, int *phash, int *psignandhash,
+                       unsigned char *rsig, unsigned char *rhash);
+
 #define SSL_set_tlsext_host_name(s,name) \
 SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)
 
 #define SSL_set_tlsext_host_name(s,name) \
 SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)