Add support for broken protocol tests (backport from master branch)
authorDr. Stephen Henson <steve@openssl.org>
Tue, 15 Jan 2013 16:18:13 +0000 (16:18 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 15 Jan 2013 16:18:13 +0000 (16:18 +0000)
ssl/s3_lib.c
ssl/ssl.h
ssl/ssl_ciph.c
ssl/ssl_lib.c
ssl/t1_lib.c

index 7c535875afb710c79a2a9fc9e75b6503221f757b..d71c819b00e2adf548216d237d83ca571199f336 100644 (file)
@@ -2011,6 +2011,22 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
        256,
        256,
        },
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+       {
+       1,
+       "SCSV",
+       SSL3_CK_SCSV,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0
+       },
+#endif
 
 #ifndef OPENSSL_NO_ECDH
        /* Cipher C001 */
index e05077c2c568f704ee0a4c4d7f013afa17d3142e..6cb1546821cedbb590d1d0738b6169a24a7f41e7 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -667,7 +667,8 @@ struct ssl_session_st
 /* Suite B 128 bit mode allowing 192 bit algorithms */
 #define SSL_CERT_FLAG_SUITEB_128_LOS           0x30000
 
-
+/* Perform all sorts of protocol violations for testing purposes */
+#define SSL_CERT_FLAG_BROKEN_PROTOCOL          0x10000000
 
 /* Flags for building certificate chains */
 /* Treat any existing certificates as untrusted CAs */
index 159d010c24f6c5729df6b1dcba62a43d45a7a0d7..4d87d2dbc4bf7f4b0b8a8f13c39e9cf41fe79e9b 100644 (file)
@@ -972,7 +972,10 @@ static void ssl_cipher_apply_rule(unsigned long cipher_id,
 #ifdef CIPHER_DEBUG
                        printf("\nName: %s:\nAlgo = %08lx/%08lx/%08lx/%08lx/%08lx Algo_strength = %08lx\n", cp->name, cp->algorithm_mkey, cp->algorithm_auth, cp->algorithm_enc, cp->algorithm_mac, cp->algorithm_ssl, cp->algo_strength);
 #endif
-
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+                       if (cipher_id && cipher_id != cp->id)
+                               continue;
+#endif
                        if (alg_mkey && !(alg_mkey & cp->algorithm_mkey))
                                continue;
                        if (alg_auth && !(alg_auth & cp->algorithm_auth))
index cf435d080c5e259507424d57b6de0800e75b4efa..f9907130c69b398bd7f23fcb3a1b5c93eed0c8d7 100644 (file)
@@ -1436,6 +1436,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
        SSL_CIPHER *c;
        CERT *ct = s->cert;
        unsigned char *q;
+       int no_scsv = s->renegotiate;
        /* Set disabled masks for this session */
        ssl_set_client_disabled(s);
 
@@ -1450,13 +1451,22 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
                        c->algorithm_mkey & ct->mask_k ||
                        c->algorithm_auth & ct->mask_a)
                        continue;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+               if (c->id == SSL3_CK_SCSV)
+                       {
+                       if (no_scsv)
+                               continue;
+                       else
+                               no_scsv = 1;
+                       }
+#endif
                j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
                p+=j;
                }
        /* If p == q, no ciphers and caller indicates an error. Otherwise
         * add SCSV if not renegotiating.
         */
-       if (p != q && !s->renegotiate)
+       if (p != q && !no_scsv)
                {
                static SSL_CIPHER scsv =
                        {
@@ -2389,6 +2399,14 @@ CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
        c = s->cert;
        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. */
@@ -2408,6 +2426,15 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
        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;
index c74605af5fd62591e04f671219d4924cc306330b..a2f5a7fa254b8ff428cd11eb727d128cf98d5173 100644 (file)
@@ -707,6 +707,11 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
        {
        unsigned char curve_id[2];
        EC_KEY *ec = s->cert->ecdh_tmp;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+       /* Allow any curve: not just those peer supports */
+       if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+               return 1;
+#endif
        /* If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384,
         * no other curves permitted.
         */
@@ -3424,6 +3429,32 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
 
        tls1_set_shared_sigalgs(s);
 
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+       if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+               {
+               /* Use first set signature preference to force message
+                * digest, ignoring any peer preferences.
+                */
+               const unsigned char *sigs = NULL;
+               if (s->server)
+                       sigs = c->conf_sigalgs;
+               else
+                       sigs = c->client_sigalgs;
+               if (sigs)
+                       {
+                       idx = tls12_get_pkey_idx(sigs[1]);
+                       md = tls12_get_hash(sigs[0]);
+                       c->pkeys[idx].digest = md;
+                       c->pkeys[idx].valid_flags = CERT_PKEY_EXPLICIT_SIGN;
+                       if (idx == SSL_PKEY_RSA_SIGN)
+                               {
+                               c->pkeys[SSL_PKEY_RSA_ENC].valid_flags = CERT_PKEY_EXPLICIT_SIGN;
+                               c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
+                               }
+                       }
+               }
+#endif
+
        for (i = 0, sigptr = c->shared_sigalgs;
                        i < c->shared_sigalgslen; i++, sigptr++)
                {
@@ -3719,6 +3750,8 @@ int tls1_set_sigalgs_list(CERT *c, const char *str, int client)
        sig.sigalgcnt = 0;
        if (!CONF_parse_list(str, ':', 1, sig_cb, &sig))
                return 0;
+       if (c == NULL)
+               return 1;
        return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
        }
 
@@ -3837,6 +3870,15 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
                /* If no cert or key, forget it */
                if (!x || !pk)
                        goto end;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+               /* Allow any certificate to pass test */
+               if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+                       {
+                       rv = CERT_PKEY_STRICT_FLAGS|CERT_PKEY_EXPLICIT_SIGN|CERT_PKEY_VALID|CERT_PKEY_SIGN;
+                       cpk->valid_flags = rv;
+                       return rv;
+                       }
+#endif
                }
        else
                {