Delete MD2 from algorithm tables as in 0.9.8-stable. However since this is
[openssl.git] / ssl / ssl_ciph.c
index d2e648bf3071ff88403d45781fb63bc76f9bc527..87c5f61670007305f8c7777068b9c6fb294e2056 100644 (file)
 
 #include <stdio.h>
 #include <openssl/objects.h>
+#ifndef OPENSSL_NO_COMP
 #include <openssl/comp.h>
+#endif
+#ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
+#endif
 #include "ssl_locl.h"
 
 #define SSL_ENC_DES_IDX                0
@@ -175,7 +179,10 @@ static STACK_OF(SSL_COMP) *ssl_comp_methods=NULL;
 #define SSL_MD_SHA1_IDX        1
 #define SSL_MD_GOST94_IDX 2
 #define SSL_MD_GOST89MAC_IDX 3
-#define SSL_MD_NUM_IDX 4
+/*Constant SSL_MAX_DIGEST equal to size of digests array should be 
+ * defined in the
+ * ssl_locl.h */
+#define SSL_MD_NUM_IDX SSL_MAX_DIGEST 
 static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={
        NULL,NULL,NULL,NULL
        };
@@ -191,6 +198,11 @@ static int ssl_mac_secret_size[SSL_MD_NUM_IDX]={
        0,0,0,0
        };
 
+static int ssl_handshake_digest_flag[SSL_MD_NUM_IDX]={
+       SSL_HANDSHAKE_MAC_MD5,SSL_HANDSHAKE_MAC_SHA,
+       SSL_HANDSHAKE_MAC_GOST94,0
+       };
+
 #define CIPHER_ADD     1
 #define CIPHER_KILL    2
 #define CIPHER_DEL     3
@@ -199,7 +211,7 @@ static int ssl_mac_secret_size[SSL_MD_NUM_IDX]={
 
 typedef struct cipher_order_st
        {
-       SSL_CIPHER *cipher;
+       const SSL_CIPHER *cipher;
        int active;
        int dead;
        struct cipher_order_st *next,*prev;
@@ -235,7 +247,7 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_ECDH,0,    SSL_kECDHr|SSL_kECDHe|SSL_kEECDH,0,0,0,0,0,0,0,0},
 
         {0,SSL_TXT_kPSK,0,    SSL_kPSK,  0,0,0,0,0,0,0,0},
-
+       {0,SSL_TXT_kGOST,0, SSL_kGOST,0,0,0,0,0,0,0,0},
 
        /* server authentication aliases */
        {0,SSL_TXT_aRSA,0,    0,SSL_aRSA,  0,0,0,0,0,0,0},
@@ -248,7 +260,9 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_aECDSA,0,  0,SSL_aECDSA,0,0,0,0,0,0,0},
        {0,SSL_TXT_ECDSA,0,   0,SSL_aECDSA, 0,0,0,0,0,0,0},
         {0,SSL_TXT_aPSK,0,    0,SSL_aPSK,  0,0,0,0,0,0,0},
-
+       {0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0},
+       {0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0},
+       {0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0},
 
        /* aliases combining key exchange and server authentication */
        {0,SSL_TXT_EDH,0,     SSL_kEDH,~SSL_aNULL,0,0,0,0,0,0,0},
@@ -298,7 +312,43 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_LOW,0,     0,0,0,0,0,SSL_LOW,   0,0,0},
        {0,SSL_TXT_MEDIUM,0,  0,0,0,0,0,SSL_MEDIUM,0,0,0},
        {0,SSL_TXT_HIGH,0,    0,0,0,0,0,SSL_HIGH,  0,0,0},
+       /* FIPS 140-2 approved ciphersuite */
+       {0,SSL_TXT_FIPS,0,    0,0,~SSL_eNULL,0,0,SSL_FIPS,  0,0,0},
        };
+/* Search for public key algorithm with given name and 
+ * return its pkey_id if it is available. Otherwise return 0
+ */
+#ifdef OPENSSL_NO_ENGINE
+
+static int get_optional_pkey_id(const char *pkey_name)
+       {
+       const EVP_PKEY_ASN1_METHOD *ameth;
+       int pkey_id=0;
+       ameth = EVP_PKEY_asn1_find_str(NULL,pkey_name,-1);
+       if (ameth) 
+               {
+               EVP_PKEY_asn1_get0_info(&pkey_id, NULL,NULL,NULL,NULL,ameth);
+               }               
+       return pkey_id;
+       }
+
+#else
+
+static int get_optional_pkey_id(const char *pkey_name)
+       {
+       const EVP_PKEY_ASN1_METHOD *ameth;
+       ENGINE *tmpeng = NULL;
+       int pkey_id=0;
+       ameth = EVP_PKEY_asn1_find_str(&tmpeng,pkey_name,-1);
+       if (ameth)
+               {
+               EVP_PKEY_asn1_get0_info(&pkey_id, NULL,NULL,NULL,NULL,ameth);
+               }
+       if (tmpeng) ENGINE_finish(tmpeng);
+       return pkey_id;
+       }
+
+#endif
 
 void ssl_load_ciphers(void)
        {
@@ -333,32 +383,26 @@ void ssl_load_ciphers(void)
                EVP_get_digestbyname(SN_md5);
        ssl_mac_secret_size[SSL_MD_MD5_IDX]=
                EVP_MD_size(ssl_digest_methods[SSL_MD_MD5_IDX]);
+       OPENSSL_assert(ssl_mac_secret_size[SSL_MD_MD5_IDX] >= 0);
        ssl_digest_methods[SSL_MD_SHA1_IDX]=
                EVP_get_digestbyname(SN_sha1);
        ssl_mac_secret_size[SSL_MD_SHA1_IDX]=
                EVP_MD_size(ssl_digest_methods[SSL_MD_SHA1_IDX]);
+       OPENSSL_assert(ssl_mac_secret_size[SSL_MD_SHA1_IDX] >= 0);
        ssl_digest_methods[SSL_MD_GOST94_IDX]=
                EVP_get_digestbyname(SN_id_GostR3411_94);
        if (ssl_digest_methods[SSL_MD_GOST94_IDX])
                {       
                ssl_mac_secret_size[SSL_MD_GOST94_IDX]=
                        EVP_MD_size(ssl_digest_methods[SSL_MD_GOST94_IDX]);
+               OPENSSL_assert(ssl_mac_secret_size[SSL_MD_GOST94_IDX] >= 0);
                }
        ssl_digest_methods[SSL_MD_GOST89MAC_IDX]=
                EVP_get_digestbyname(SN_id_Gost28147_89_MAC);
-               {
-               const EVP_PKEY_ASN1_METHOD *ameth;
-               ENGINE *tmpeng = NULL;
-               int pkey_id;
-               ameth = EVP_PKEY_asn1_find_str(&tmpeng,"gost-mac",-1);
-               if (ameth) 
-                       {
-                       EVP_PKEY_asn1_get0_info(&pkey_id, NULL,NULL,NULL,NULL,ameth);
-                       ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]= pkey_id;
+               ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac");
+               if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]) {
                        ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX]=32;
-                       }               
-               if (tmpeng) ENGINE_finish(tmpeng);      
-               }
+               }               
 
        }
 #ifndef OPENSSL_NO_COMP
@@ -418,7 +462,7 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
             const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size,SSL_COMP **comp)
        {
        int i;
-       SSL_CIPHER *c;
+       const SSL_CIPHER *c;
 
        c=s->cipher;
        if (c == NULL) return(0);
@@ -534,6 +578,18 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
                return(0);
        }
 
+int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md) 
+{
+       if (idx <0||idx>=SSL_MD_NUM_IDX) 
+               {
+               return 0;
+               }
+       if (ssl_handshake_digest_flag[idx]==0) return 0;
+       *mask = ssl_handshake_digest_flag[idx];
+       *md = ssl_digest_methods[idx];
+       return 1;
+}
+
 #define ITEM_SEP(a) \
        (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
 
@@ -605,9 +661,23 @@ static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, un
        *mkey |= SSL_kPSK;
        *auth |= SSL_aPSK;
 #endif
+       /* Check for presence of GOST 34.10 algorithms, and if they
+        * do not present, disable  appropriate auth and key exchange */
+       if (!get_optional_pkey_id("gost94")) {
+               *auth |= SSL_aGOST94;
+       }
+       if (!get_optional_pkey_id("gost2001")) {
+               *auth |= SSL_aGOST01;
+       }
+       /* Disable GOST key exchange if no GOST signature algs are available * */
+       if ((*auth & (SSL_aGOST94|SSL_aGOST01)) == (SSL_aGOST94|SSL_aGOST01)) {
+               *mkey |= SSL_kGOST;
+       }       
 #ifdef SSL_FORBID_ENULL
        *enc |= SSL_eNULL;
 #endif
+               
+
 
        *enc |= (ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL) ? SSL_DES :0;
        *enc |= (ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL) ? SSL_3DES:0;
@@ -637,7 +707,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
                 CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
        {
        int i, co_list_num;
-       SSL_CIPHER *c;
+       const SSL_CIPHER *c;
 
        /*
         * We have num_of_ciphers descriptions compiled in, depending on the
@@ -700,7 +770,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
                }
        }
 
-static void ssl_cipher_collect_aliases(SSL_CIPHER **ca_list,
+static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
                         int num_of_group_aliases,
                         unsigned long disabled_mkey, unsigned long disabled_auth,
                         unsigned long disabled_enc, unsigned long disabled_mac,
@@ -708,7 +778,7 @@ static void ssl_cipher_collect_aliases(SSL_CIPHER **ca_list,
                        CIPHER_ORDER *head)
        {
        CIPHER_ORDER *ciph_curr;
-       SSL_CIPHER **ca_curr;
+       const SSL_CIPHER **ca_curr;
        int i;
        unsigned long mask_mkey = ~disabled_mkey;
        unsigned long mask_auth = ~disabled_auth;
@@ -778,7 +848,7 @@ static void ssl_cipher_apply_rule(unsigned long cipher_id,
                CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
        {
        CIPHER_ORDER *head, *tail, *curr, *curr2, *last;
-       SSL_CIPHER *cp;
+       const SSL_CIPHER *cp;
        int reverse = 0;
 
 #ifdef CIPHER_DEBUG
@@ -954,7 +1024,7 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
 
 static int ssl_cipher_process_rulestr(const char *rule_str,
                 CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p,
-                SSL_CIPHER **ca_list)
+                const SSL_CIPHER **ca_list)
        {
        unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength;
        const char *l, *start, *buf;
@@ -1213,7 +1283,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
        STACK_OF(SSL_CIPHER) *cipherstack, *tmp_cipher_list;
        const char *rule_p;
        CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
-       SSL_CIPHER **ca_list = NULL;
+       const SSL_CIPHER **ca_list = NULL;
 
        /*
         * Return with error if nothing to do.
@@ -1300,8 +1370,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
         */
        num_of_group_aliases = sizeof(cipher_aliases) / sizeof(SSL_CIPHER);
        num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
-       ca_list =
-               (SSL_CIPHER **)OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max);
+       ca_list = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max);
        if (ca_list == NULL)
                {
                OPENSSL_free(co_list);
@@ -1309,8 +1378,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
                return(NULL);   /* Failure */
                }
        ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
-                                  disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl,
-                                  head);
+                                  disabled_mkey, disabled_auth, disabled_enc,
+                                  disabled_mac, disabled_ssl, head);
 
        /*
         * If the rule_string begins with DEFAULT, apply the default rule
@@ -1330,7 +1399,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
        if (ok && (strlen(rule_p) > 0))
                ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list);
 
-       OPENSSL_free(ca_list);  /* Not needed anymore */
+       OPENSSL_free((void *)ca_list);  /* Not needed anymore */
 
        if (!ok)
                {       /* Rule processing failure */
@@ -1376,8 +1445,9 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
        if (*cipher_list_by_id != NULL)
                sk_SSL_CIPHER_free(*cipher_list_by_id);
        *cipher_list_by_id = tmp_cipher_list;
-       sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
+       (void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
 
+       sk_SSL_CIPHER_sort(*cipher_list_by_id);
        return(cipherstack);
        }
 
@@ -1646,7 +1716,7 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
        comp->method=cm;
        load_builtin_compressions();
        if (ssl_comp_methods
-               && !sk_SSL_COMP_find(ssl_comp_methods,comp))
+               && sk_SSL_COMP_find(ssl_comp_methods,comp) >= 0)
                {
                OPENSSL_free(comp);
                MemCheck_on();