fix typo
[openssl.git] / ssl / ssl_ciph.c
index cdd8dde128bdca9815194a618df0608086d3629a..f175dc875618bdf5fbbf48e191c686c79f1f6015 100644 (file)
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
-
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
 #include <stdio.h>
 #include <openssl/objects.h>
 #include <openssl/comp.h>
@@ -76,6 +80,10 @@ static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={
        NULL,NULL,NULL,NULL,NULL,NULL,
        };
 
+#define SSL_COMP_NULL_IDX      0
+#define SSL_COMP_ZLIB_IDX      1
+#define SSL_COMP_NUM_IDX       2
+
 static STACK_OF(SSL_COMP) *ssl_comp_methods=NULL;
 
 #define SSL_MD_MD5_IDX 0
@@ -100,18 +108,21 @@ typedef struct cipher_order_st
        } CIPHER_ORDER;
 
 static const SSL_CIPHER cipher_aliases[]={
-       /* Don't include eNULL unless specifically enabled.
-        * Similarly, don't include AES in ALL because these ciphers are not yet official. */
-       {0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL & ~SSL_AES, SSL_ALL ,0,0,0,SSL_ALL,SSL_ALL}, /* must be first */
-        {0,SSL_TXT_kKRB5,0,SSL_kKRB5,0,0,0,0,SSL_MKEY_MASK,0},  /* VRS Kerberos5 */
+       /* Don't include eNULL unless specifically enabled. */
+       /* Don't include ECC in ALL because these ciphers are not yet official. */
+       {0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL & ~SSL_kECDH & ~SSL_kECDHE, SSL_ALL ,0,0,0,SSL_ALL,SSL_ALL}, /* must be first */
+       /* TODO: COMPLEMENT OF ALL and COMPLEMENT OF DEFAULT do not have ECC cipher suites handled properly. */
+       {0,SSL_TXT_CMPALL,0,SSL_eNULL,0,0,0,0,SSL_ENC_MASK,0},  /* COMPLEMENT OF ALL */
+       {0,SSL_TXT_CMPDEF,0,SSL_ADH, 0,0,0,0,SSL_AUTH_MASK,0},
+       {0,SSL_TXT_kKRB5,0,SSL_kKRB5,0,0,0,0,SSL_MKEY_MASK,0},  /* VRS Kerberos5 */
        {0,SSL_TXT_kRSA,0,SSL_kRSA,  0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_kDHr,0,SSL_kDHr,  0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_kDHd,0,SSL_kDHd,  0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_kEDH,0,SSL_kEDH,  0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_kFZA,0,SSL_kFZA,  0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_DH,  0,SSL_DH,    0,0,0,0,SSL_MKEY_MASK,0},
+       {0,SSL_TXT_ECC, 0,(SSL_kECDH|SSL_kECDHE), 0,0,0,0,SSL_MKEY_MASK,0},
        {0,SSL_TXT_EDH, 0,SSL_EDH,   0,0,0,0,SSL_MKEY_MASK|SSL_AUTH_MASK,0},
-
        {0,SSL_TXT_aKRB5,0,SSL_aKRB5,0,0,0,0,SSL_AUTH_MASK,0},  /* VRS Kerberos5 */
        {0,SSL_TXT_aRSA,0,SSL_aRSA,  0,0,0,0,SSL_AUTH_MASK,0},
        {0,SSL_TXT_aDSS,0,SSL_aDSS,  0,0,0,0,SSL_AUTH_MASK,0},
@@ -178,6 +189,46 @@ static void load_ciphers(void)
                EVP_get_digestbyname(SN_sha1);
        }
 
+static int sk_comp_cmp(const SSL_COMP * const *a,
+                       const SSL_COMP * const *b)
+       {
+       return((*a)->id-(*b)->id);
+       }
+
+static void load_builtin_compressions(void)
+       {
+       if (ssl_comp_methods != NULL)
+               return;
+
+       CRYPTO_w_lock(CRYPTO_LOCK_SSL);
+       if (ssl_comp_methods == NULL)
+               {
+               SSL_COMP *comp = NULL;
+
+               MemCheck_off();
+               ssl_comp_methods=sk_SSL_COMP_new(sk_comp_cmp);
+               if (ssl_comp_methods != NULL)
+                       {
+                       comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP));
+                       if (comp != NULL)
+                               {
+                               comp->method=COMP_zlib();
+                               if (comp->method
+                                       && comp->method->type == NID_undef)
+                                       OPENSSL_free(comp);
+                               else
+                                       {
+                                       comp->id=SSL_COMP_ZLIB_IDX;
+                                       comp->name=comp->method->name;
+                                       sk_SSL_COMP_push(ssl_comp_methods,comp);
+                                       }
+                               }
+                       }
+               MemCheck_on();
+               }
+       CRYPTO_w_unlock(CRYPTO_LOCK_SSL);
+       }
+
 int ssl_cipher_get_evp(SSL_SESSION *s, const EVP_CIPHER **enc,
             const EVP_MD **md, SSL_COMP **comp)
        {
@@ -190,17 +241,12 @@ int ssl_cipher_get_evp(SSL_SESSION *s, const EVP_CIPHER **enc,
                {
                SSL_COMP ctmp;
 
-               if (s->compress_meth == 0)
-                       *comp=NULL;
-               else if (ssl_comp_methods == NULL)
-                       {
-                       /* bad */
-                       *comp=NULL;
-                       }
-               else
-                       {
+               load_builtin_compressions();
 
-                       ctmp.id=s->compress_meth;
+               *comp=NULL;
+               ctmp.id=s->compress_meth;
+               if (ssl_comp_methods != NULL)
+                       {
                        i=sk_SSL_COMP_find(ssl_comp_methods,&ctmp);
                        if (i >= 0)
                                *comp=sk_SSL_COMP_value(ssl_comp_methods,i);
@@ -313,7 +359,9 @@ static unsigned long ssl_cipher_get_disabled(void)
 #ifdef OPENSSL_NO_KRB5
        mask |= SSL_kKRB5|SSL_aKRB5;
 #endif
-
+#ifdef OPENSSL_NO_ECDH
+       mask |= SSL_kECDH|SSL_kECDHE;
+#endif
 #ifdef SSL_FORBID_ENULL
        mask |= SSL_eNULL;
 #endif
@@ -667,13 +715,14 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
                         * So additionally check whether the cipher name found
                         * has the correct length. We can save a strlen() call:
                         * just checking for the '\0' at the right place is
-                        * sufficient, we have to strncmp() anyway.
+                        * sufficient, we have to strncmp() anyway. (We cannot
+                        * use strcmp(), because buf is not '\0' terminated.)
                         */
                         j = found = 0;
                         while (ca_list[j])
                                {
-                               if ((ca_list[j]->name[buflen] == '\0') &&
-                                   !strncmp(buf, ca_list[j]->name, buflen))
+                               if (!strncmp(buf, ca_list[j]->name, buflen) &&
+                                   (ca_list[j]->name[buflen] == '\0'))
                                        {
                                        found = 1;
                                        break;
@@ -750,7 +799,12 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
         */
        if (rule_str == NULL) return(NULL);
 
-       if (init_ciphers) load_ciphers();
+       if (init_ciphers)
+               {
+               CRYPTO_w_lock(CRYPTO_LOCK_SSL);
+               if (init_ciphers) load_ciphers();
+               CRYPTO_w_unlock(CRYPTO_LOCK_SSL);
+               }
 
        /*
         * To reduce the work to do we only want to process the compiled
@@ -915,7 +969,7 @@ char *SSL_CIPHER_description(SSL_CIPHER *cipher, char *buf, int len)
        pkl=SSL_C_EXPORT_PKEYLENGTH(cipher);
        kl=SSL_C_EXPORT_KEYLENGTH(cipher);
        exp=is_export?" export":"";
-
+       
        if (alg & SSL_SSLV2)
                ver="SSLv2";
        else if (alg & SSL_SSLV3)
@@ -944,6 +998,10 @@ char *SSL_CIPHER_description(SSL_CIPHER *cipher, char *buf, int len)
        case SSL_kEDH:
                kx=is_export?(pkl == 512 ? "DH(512)" : "DH(1024)"):"DH";
                break;
+       case SSL_kECDH:
+       case SSL_kECDHE:
+               kx=is_export?"ECDH(<=163)":"ECDH";
+               break;
        default:
                kx="unknown";
                }
@@ -967,6 +1025,9 @@ char *SSL_CIPHER_description(SSL_CIPHER *cipher, char *buf, int len)
        case SSL_aNULL:
                au="None";
                break;
+       case SSL_aECDSA:
+               au="ECDSA";
+               break;
        default:
                au="unknown";
                break;
@@ -999,10 +1060,10 @@ char *SSL_CIPHER_description(SSL_CIPHER *cipher, char *buf, int len)
        case SSL_AES:
                switch(cipher->strength_bits)
                        {
-               case 128: enc="AESdraft(128)"; break;
-               case 192: enc="AESdraft(192)"; break;
-               case 256: enc="AESdraft(256)"; break;
-               default: enc="AESdraft(?""?""?)"; break;
+               case 128: enc="AES(128)"; break;
+               case 192: enc="AES(192)"; break;
+               case 256: enc="AES(256)"; break;
+               default: enc="AES(?""?""?)"; break;
                        }
                break;
        default:
@@ -1091,35 +1152,40 @@ SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n)
        return(NULL);
        }
 
-static int sk_comp_cmp(const SSL_COMP * const *a,
-                       const SSL_COMP * const *b)
-       {
-       return((*a)->id-(*b)->id);
-       }
-
 STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
        {
+       load_builtin_compressions();
        return(ssl_comp_methods);
        }
 
 int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
        {
        SSL_COMP *comp;
-       STACK_OF(SSL_COMP) *sk;
 
         if (cm == NULL || cm->type == NID_undef)
                 return 1;
 
+       /* According to draft-ietf-tls-compression-04.txt, the
+          compression number ranges should be the following:
+
+          0 to 63:    methods defined by the IETF
+          64 to 192:  external party methods assigned by IANA
+          193 to 255: reserved for private use */
+       if (id < 193 || id > 255)
+               {
+               SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE);
+               return 0;
+               }
+
        MemCheck_off();
        comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP));
        comp->id=id;
        comp->method=cm;
-       if (ssl_comp_methods == NULL)
-               sk=ssl_comp_methods=sk_SSL_COMP_new(sk_comp_cmp);
-       else
-               sk=ssl_comp_methods;
-       if ((sk == NULL) || !sk_SSL_COMP_push(sk,comp))
+       load_builtin_compressions();
+       if ((ssl_comp_methods == NULL)
+               || !sk_SSL_COMP_push(ssl_comp_methods,comp))
                {
+               OPENSSL_free(comp);
                MemCheck_on();
                SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,ERR_R_MALLOC_FAILURE);
                return(0);