Remove deleted PKCS#12 functions from pkcs12.h, get rid of object creation
[openssl.git] / ssl / ssl_ciph.c
index 9fed3ad59ac0bbabc1d8749803c1850dbc0906f7..e3f61ea0bc2a1ce734271b164338165174afeca4 100644 (file)
@@ -1,5 +1,5 @@
 /* ssl/ssl_ciph.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -58,6 +58,7 @@
 
 #include <stdio.h>
 #include "objects.h"
+#include "comp.h"
 #include "ssl_locl.h"
 
 #define SSL_ENC_DES_IDX                0
@@ -73,12 +74,13 @@ static EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={
        NULL,NULL,NULL,NULL,NULL,NULL,
        };
 
+static STACK /* SSL_COMP */ *ssl_comp_methods=NULL;
+
 #define SSL_MD_MD5_IDX 0
-#define SSL_MD_SHA0_IDX        1
-#define SSL_MD_SHA1_IDX        2
-#define SSL_MD_NUM_IDX 3
+#define SSL_MD_SHA1_IDX        1
+#define SSL_MD_NUM_IDX 2
 static EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={
-       NULL,NULL,NULL,
+       NULL,NULL,
        };
 
 typedef struct cipher_sort_st
@@ -90,18 +92,27 @@ typedef struct cipher_sort_st
 #define CIPHER_ADD     1
 #define CIPHER_KILL    2
 #define CIPHER_DEL     3
-#define CIPHER_ORDER   4
+#define CIPHER_ORD     4
 
 typedef struct cipher_choice_st
        {
        int type;
        unsigned long algorithms;
        unsigned long mask;
-       STACK *order;
+       long top;
        } CIPHER_CHOICE;
 
+typedef struct cipher_order_st
+       {
+       SSL_CIPHER *cipher;
+       int active;
+       int dead;
+       struct cipher_order_st *next,*prev;
+       } CIPHER_ORDER;
+
 static SSL_CIPHER cipher_aliases[]={
-       {0,SSL_TXT_ALL, 0,SSL_ALL,   0,SSL_ALL},        /* must be first */
+       /* Don't include eNULL unless specifically enabled */
+       {0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL, 0,SSL_ALL}, /* must be first */
        {0,SSL_TXT_kRSA,0,SSL_kRSA,  0,SSL_MKEY_MASK},
        {0,SSL_TXT_kDHr,0,SSL_kDHr,  0,SSL_MKEY_MASK},
        {0,SSL_TXT_kDHd,0,SSL_kDHd,  0,SSL_MKEY_MASK},
@@ -126,7 +137,6 @@ static SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_eFZA,0,SSL_eFZA,  0,SSL_ENC_MASK},
 
        {0,SSL_TXT_MD5, 0,SSL_MD5,   0,SSL_MAC_MASK},
-       {0,SSL_TXT_SHA0,0,SSL_SHA0,  0,SSL_MAC_MASK},
        {0,SSL_TXT_SHA1,0,SSL_SHA1,  0,SSL_MAC_MASK},
        {0,SSL_TXT_SHA, 0,SSL_SHA,   0,SSL_MAC_MASK},
 
@@ -135,13 +145,15 @@ static SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_ADH, 0,SSL_ADH,   0,SSL_AUTH_MASK|SSL_MKEY_MASK},
        {0,SSL_TXT_FZA, 0,SSL_FZA,   0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK},
 
-       {0,SSL_TXT_EXP, 0,SSL_EXP,   0,SSL_EXP_MASK},
-       {0,SSL_TXT_EXPORT,0,SSL_EXPORT,0,SSL_EXP_MASK},
-       {0,SSL_TXT_SSLV2,0,SSL_SSLV2,0,SSL_SSL_MASK},
-       {0,SSL_TXT_SSLV3,0,SSL_SSLV3,0,SSL_SSL_MASK},
-       {0,SSL_TXT_LOW,  0,SSL_LOW,0,SSL_STRONG_MASK},
+       {0,SSL_TXT_EXP40, 0,SSL_EXP40, 0,SSL_EXP_MASK},
+       {0,SSL_TXT_EXPORT,0,SSL_EXP40, 0,SSL_EXP_MASK},
+       {0,SSL_TXT_EXP56, 0,SSL_EXP56, 0,SSL_EXP_MASK},
+       {0,SSL_TXT_SSLV2, 0,SSL_SSLV2, 0,SSL_SSL_MASK},
+       {0,SSL_TXT_SSLV3, 0,SSL_SSLV3, 0,SSL_SSL_MASK},
+       {0,SSL_TXT_TLSV1, 0,SSL_TLSV1, 0,SSL_SSL_MASK},
+       {0,SSL_TXT_LOW,   0,SSL_LOW,   0,SSL_STRONG_MASK},
        {0,SSL_TXT_MEDIUM,0,SSL_MEDIUM,0,SSL_STRONG_MASK},
-       {0,SSL_TXT_HIGH, 0,SSL_HIGH,0,SSL_STRONG_MASK},
+       {0,SSL_TXT_HIGH,  0,SSL_HIGH,  0,SSL_STRONG_MASK},
        };
 
 static int init_ciphers=1;
@@ -169,20 +181,45 @@ static void load_ciphers()
 
        ssl_digest_methods[SSL_MD_MD5_IDX]=
                EVP_get_digestbyname(SN_md5);
-       ssl_digest_methods[SSL_MD_SHA0_IDX]=
-               EVP_get_digestbyname(SN_sha);
        ssl_digest_methods[SSL_MD_SHA1_IDX]=
                EVP_get_digestbyname(SN_sha1);
        }
 
-int ssl_cipher_get_evp(c,enc,md)
-SSL_CIPHER *c;
+int ssl_cipher_get_evp(s,enc,md,comp)
+SSL_SESSION *s;
 EVP_CIPHER **enc;
 EVP_MD **md;
+SSL_COMP **comp;
        {
        int i;
+       SSL_CIPHER *c;
 
+       c=s->cipher;
        if (c == NULL) return(0);
+       if (comp != NULL)
+               {
+               SSL_COMP ctmp;
+
+               if (s->compress_meth == 0)
+                       *comp=NULL;
+               else if (ssl_comp_methods == NULL)
+                       {
+                       /* bad */
+                       *comp=NULL;
+                       }
+               else
+                       {
+
+                       ctmp.id=s->compress_meth;
+                       i=sk_find(ssl_comp_methods,(char *)&ctmp);
+                       if (i >= 0)
+                               *comp=(SSL_COMP *)sk_value(ssl_comp_methods,i);
+                       else
+                               *comp=NULL;
+                       }
+               }
+
+       if ((enc == NULL) || (md == NULL)) return(0);
 
        switch (c->algorithms & SSL_ENC_MASK)
                {
@@ -204,7 +241,6 @@ EVP_MD **md;
        case SSL_eNULL:
                i=SSL_ENC_NULL_IDX;
                break;
-               break;
        default:
                i= -1;
                break;
@@ -225,9 +261,6 @@ EVP_MD **md;
        case SSL_MD5:
                i=SSL_MD_MD5_IDX;
                break;
-       case SSL_SHA0:
-               i=SSL_MD_SHA0_IDX;
-               break;
        case SSL_SHA1:
                i=SSL_MD_SHA1_IDX;
                break;
@@ -246,6 +279,25 @@ EVP_MD **md;
                return(0);
        }
 
+#define ITEM_SEP(a) \
+       (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
+
+static void ll_append_tail(head,curr,tail)
+CIPHER_ORDER **head,*curr,**tail;
+       {
+       if (curr == *tail) return;
+       if (curr == *head)
+               *head=curr->next;
+       if (curr->prev != NULL)
+               curr->prev->next=curr->next;
+       if (curr->next != NULL) /* should always be true */
+               curr->next->prev=curr->prev;
+       (*tail)->next=curr;
+       curr->prev= *tail;
+       curr->next=NULL;
+       *tail=curr;
+       }
+
 STACK *ssl_create_cipher_list(ssl_method,cipher_list,cipher_list_by_id,str)
 SSL_METHOD *ssl_method;
 STACK **cipher_list,**cipher_list_by_id;
@@ -262,9 +314,11 @@ char *str;
        int i,j,k,num=0,ch,multi;
        unsigned long al;
        STACK *ca_list=NULL;
-       STACK *c_list=NULL;
-       int old_x,old_y,current_x,num_x;
+       int current_x,num_x;
        CIPHER_CHOICE *ops=NULL;
+       CIPHER_ORDER *list=NULL,*head=NULL,*tail=NULL,*curr,*tail2,*curr2;
+       int list_num;
+       int type;
        SSL_CIPHER c_tmp,*cp;
 
        if (str == NULL) return(NULL);
@@ -278,6 +332,7 @@ char *str;
                        goto err;
                        }
                strcpy(tmp_str,SSL_DEFAULT_CIPHER_LIST);
+               strcat(tmp_str,":");
                strcat(tmp_str,&(str[7]));
                str=tmp_str;
                }
@@ -286,7 +341,6 @@ char *str;
        num=ssl_method->num_ciphers();
 
        if ((ret=(STACK *)sk_new(NULL)) == NULL) goto err;
-       if ((c_list=(STACK *)sk_new(NULL)) == NULL) goto err;
        if ((ca_list=(STACK *)sk_new(cmp_by_name)) == NULL) goto err;
 
        mask =SSL_kFZA;
@@ -300,7 +354,7 @@ char *str;
        mask|=SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH;
 #endif
 
-#ifndef SSL_ALLOW_ENULL
+#ifdef SSL_FORBID_ENULL
        mask|=SSL_eNULL;
 #endif
 
@@ -312,23 +366,45 @@ char *str;
        mask|=(ssl_cipher_methods[SSL_ENC_eFZA_IDX] == NULL)?SSL_eFZA:0;
 
        mask|=(ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL)?SSL_MD5 :0;
-       mask|=(ssl_digest_methods[SSL_MD_SHA0_IDX] == NULL)?SSL_SHA0:0;
        mask|=(ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL)?SSL_SHA1:0;
 
+       if ((list=(CIPHER_ORDER *)Malloc(sizeof(CIPHER_ORDER)*num)) == NULL)
+               goto err;
+
        /* Get the initial list of ciphers */
+       list_num=0;
        for (i=0; i<num; i++)
                {
                c=ssl_method->get_cipher((unsigned int)i);
                /* drop those that use any of that is not available */
                if ((c != NULL) && c->valid && !(c->algorithms & mask))
                        {
-                       if (!sk_push(c_list,(char *)c)) goto err;
+                       list[list_num].cipher=c;
+                       list[list_num].next=NULL;
+                       list[list_num].prev=NULL;
+                       list[list_num].active=0;
+                       list_num++;
                        if (!sk_push(ca_list,(char *)c)) goto err;
                        }
                }
+       
+       for (i=1; i<list_num-1; i++)
+               {
+               list[i].prev= &(list[i-1]);
+               list[i].next= &(list[i+1]);
+               }
+       if (list_num > 0)
+               {
+               head= &(list[0]);
+               head->prev=NULL;
+               head->next= &(list[1]);
+               tail= &(list[list_num-1]);
+               tail->prev= &(list[list_num-2]);
+               tail->next=NULL;
+               }
 
        /* special case */
-       cipher_aliases[0].algorithms= ~mask;
+       cipher_aliases[0].algorithms &= ~mask;
 
        /* get the aliases */
        k=sizeof(cipher_aliases)/sizeof(SSL_CIPHER);
@@ -346,12 +422,11 @@ char *str;
        /* how many parameters are there? */
        num=1;
        for (l=str; *l; l++)
-               if (*l == ':') num++;
+               if (ITEM_SEP(*l))
+                       num++;
        ops=(CIPHER_CHOICE *)Malloc(sizeof(CIPHER_CHOICE)*num);
        if (ops == NULL) goto err;
        memset(ops,0,sizeof(CIPHER_CHOICE)*num);
-       for (i=0; i<num; i++)
-               if ((ops[i].order=sk_new_null()) == NULL) goto err;
 
        /* we now parse the input string and create our operations */
        l=str;
@@ -361,16 +436,19 @@ char *str;
        for (;;)
                {
                ch= *l;
+
+               if (ch == '\0') break;
+
                if (ch == '-')
                        { j=CIPHER_DEL; l++; }
                else if (ch == '+')
-                       { j=CIPHER_ORDER; l++; }
+                       { j=CIPHER_ORD; l++; }
                else if (ch == '!')
                        { j=CIPHER_KILL; l++; }
                else    
                        { j=CIPHER_ADD; }
 
-               if (*l == ':')
+               if (ITEM_SEP(ch))
                        {
                        l++;
                        continue;
@@ -395,20 +473,20 @@ char *str;
                                 if (i >= (CL_BUF-2)) break;
                                 }
                        buf[i]='\0';
-                       if (ch != '\0') l++;
 
                        /* check for multi-part specification */
-                       multi=(ch == '+')?1:0;
+                       if (ch == '+')
+                               {
+                               multi=1;
+                               l++;
+                               }
+                       else
+                               multi=0;
 
                        c_tmp.name=buf;
                        j=sk_find(ca_list,(char *)&c_tmp);
                        if (j < 0)
-                               {
-                               if (ch == '\0')
-                                       break;
-                               else
-                                       continue;
-                               }
+                               goto end_loop;
 
                        cp=(SSL_CIPHER *)sk_value(ca_list,j);
                        ops[current_x].algorithms|=cp->algorithms;
@@ -419,87 +497,86 @@ char *str;
                        }
                current_x++;
                if (ch == '\0') break;
+end_loop:
+               /* Make sure we scan until the next valid start point */
+               while ((*l != '\0') && ITEM_SEP(*l))
+                       l++;
                }
 
        num_x=current_x;
        current_x=0;
 
-#ifdef CIPHER_DEBUG
-       printf("<--->\n");
-#endif
-
-       for (i=0; i<sk_num(c_list); i++)
+       /* We will now process the list of ciphers, once for each category, to
+        * decide what we should do with it. */
+       for (j=0; j<num_x; j++)
                {
-               old_x= -1;
-               old_y= -1;
-               cp=(SSL_CIPHER *)sk_value(c_list,i);
-#ifdef CIPHER_DEBUG
-               printf("[%s]\n",cp->name);
-#endif
-               for (j=0; j<num_x; j++)
+               algorithms=ops[j].algorithms;
+               type=ops[j].type;
+               mask=ops[j].mask;
+
+               curr=head;
+               curr2=head;
+               tail2=tail;
+               for (;;)
                        {
-                       algorithms=ops[j].algorithms;
-                       ma=ops[j].mask & cp->algorithms;
-#ifdef CIPHER_DEBUG
-                       printf("  %s %08lX&%08lX==0 || %08lX != %08lX \n",
-                               cp->name,ops[j].mask,cp->algorithms,ma,algorithms);
-#endif
+                       if ((curr == NULL) || (curr == tail2)) break;
+                       curr=curr2;
+                       curr2=curr->next;
+
+                       cp=curr->cipher;
+                       ma=mask & cp->algorithms;
                        if ((ma == 0) || ((ma & algorithms) != ma))
                                {
+                               /* does not apply */
                                continue;
                                }
-                       k=ops[j].type;
-#ifdef CIPHER_DEBUG
-                       printf(">>%s\n",cp->name);
-#endif
 
                        /* add the cipher if it has not been added yet. */
-                       if (k == CIPHER_ADD)
+                       if (type == CIPHER_ADD)
                                {
-                               if (old_x < 0)
+                               if (!curr->active)
                                        {
-                                       old_x=j;
-                                       old_y=sk_num(ops[j].order);
-                                       sk_push(ops[j].order,(char *)cp);
+                                       ll_append_tail(&head,curr,&tail);
+                                       curr->active=1;
                                        }
                                }
                        /* Move the added cipher to this location */
-                       else if (k == CIPHER_ORDER)
+                       else if (type == CIPHER_ORD)
                                {
-                               if (old_x >= 0)
+                               if (curr->active)
                                        {
-                                       sk_value(ops[old_x].order,old_y)=NULL;
-                                       old_y=sk_num(ops[j].order);
-                                       sk_push(ops[j].order,(char *)cp);
-                                       old_x=j;
+                                       ll_append_tail(&head,curr,&tail);
                                        }
                                }
-                       /* Remove added cipher */
-                       else if ((k == CIPHER_DEL) || (k == CIPHER_KILL))
+                       else if (type == CIPHER_DEL)
+                               curr->active=0;
+                       if (type == CIPHER_KILL)
                                {
-                               if (old_x >= 0)
-                                       {
-                                       sk_value(ops[old_x].order,old_y)=NULL;
-                                       old_x= -1;
-                                       }
-                               if (k == CIPHER_KILL)
-                                       break;
+                               if (head == curr)
+                                       head=curr->next;
+                               else
+                                       curr->prev->next=curr->next;
+                               if (tail == curr)
+                                       tail=curr->prev;
+                               curr->active=0;
+                               if (curr->next != NULL)
+                                       curr->next->prev=curr->prev;
+                               if (curr->prev != NULL)
+                                       curr->prev->next=curr->next;
+                               curr->next=NULL;
+                               curr->prev=NULL;
                                }
                        }
                }
 
-       for (i=0; i<num_x; i++)
+       for (curr=head; curr != NULL; curr=curr->next)
                {
-               for (j=0; j<sk_num(ops[i].order); j++)
+               if (curr->active)
                        {
-                       cp=(SSL_CIPHER *)sk_value(ops[i].order,j);
-                       if (cp != NULL)
-                               {
-                               sk_push(ret,(char *)cp);
+                       sk_push(ret,(char *)curr->cipher);
 #ifdef CIPHER_DEBUG
-                               printf("<%s>\n",cp->name);
+                       printf("<%s>\n",curr->cipher->name);
 #endif
-                               }
                        }
                }
 
@@ -528,16 +605,10 @@ char *str;
        ret=NULL;
 err:
        if (tmp_str) Free(tmp_str);
-       if (ops != NULL)
-               {
-               for (i=0; i<num; i++)
-                       if (ops[i].order != NULL)
-                               sk_free(ops[i].order);
-               Free(ops);
-               }
+       if (ops != NULL) Free(ops);
        if (ret != NULL) sk_free(ret);
-       if (c_list != NULL) sk_free(c_list);
        if (ca_list != NULL) sk_free(ca_list);
+       if (list != NULL) Free(list);
        return(ok);
        }
 
@@ -546,7 +617,7 @@ SSL_CIPHER *cipher;
 char *buf;
 int len;
        {
-       int export;
+        int is_export,pkl,kl;
        char *ver,*exp;
        char *kx,*au,*enc,*mac;
        unsigned long alg,alg2;
@@ -555,8 +626,10 @@ int len;
        alg=cipher->algorithms;
        alg2=cipher->algorithm2;
 
-       export=(alg&SSL_EXP)?1:0;
-       exp=(export)?" export":"";
+        is_export=SSL_IS_EXPORT(alg);
+       pkl=SSL_EXPORT_PKEYLENGTH(alg);
+       kl=SSL_EXPORT_KEYLENGTH(alg);
+        exp=is_export?" export":"";
 
        if (alg & SSL_SSLV2)
                ver="SSLv2";
@@ -568,7 +641,7 @@ int len;
        switch (alg&SSL_MKEY_MASK)
                {
        case SSL_kRSA:
-               kx=(export)?"RSA(512)":"RSA";
+                kx=is_export?(pkl == 512 ? "RSA(512)" : "RSA(1024)"):"RSA";
                break;
        case SSL_kDHr:
                kx="DH/RSA";
@@ -580,7 +653,7 @@ int len;
                kx="Fortezza";
                break;
        case SSL_kEDH:
-               kx=(export)?"DH(512)":"DH";
+                kx=is_export?(pkl == 512 ? "DH(512)" : "DH(1024)"):"DH";
                break;
        default:
                kx="unknown";
@@ -609,16 +682,17 @@ int len;
        switch (alg&SSL_ENC_MASK)
                {
        case SSL_DES:
-               enc=export?"DES(40)":"DES(56)";
+                enc=(is_export && kl == 5)?"DES(40)":"DES(56)";
                break;
        case SSL_3DES:
                enc="3DES(168)";
                break;
        case SSL_RC4:
-               enc=export?"RC4(40)":((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)");
+                enc=is_export?(kl == 5 ? "RC4(40)" : "RC4(56)")
+                 :((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)");
                break;
        case SSL_RC2:
-               enc=export?"RC2(40)":"RC2(128)";
+                enc=is_export?(kl == 5 ? "RC2(40)" : "RC2(56)"):"RC2(128)";
                break;
        case SSL_IDEA:
                enc="IDEA(128)";
@@ -639,9 +713,6 @@ int len;
        case SSL_MD5:
                mac="MD5";
                break;
-       case SSL_SHA0:
-               mac="SHA0";
-               break;
        case SSL_SHA1:
                mac="SHA1";
                break;
@@ -667,9 +738,10 @@ SSL_CIPHER *c;
        {
        int i;
 
+       if (c == NULL) return("(NONE)");
        i=(int)(c->id>>24L);
        if (i == 3)
-               return("SSLv3");
+               return("TLSv1/SSLv3");
        else if (i == 2)
                return("SSLv2");
        else
@@ -693,17 +765,19 @@ int *alg_bits;
        int ret=0,a=0;
        EVP_CIPHER *enc;
        EVP_MD *md;
+       SSL_SESSION ss;
 
        if (c != NULL)
                {
-               if (!ssl_cipher_get_evp(c,&enc,&md))
+               ss.cipher=c;
+               if (!ssl_cipher_get_evp(&ss,&enc,&md,NULL))
                        return(0);
 
                a=EVP_CIPHER_key_length(enc)*8;
 
-               if (c->algorithms & SSL_EXP)
+               if (SSL_C_IS_EXPORT(c))
                        {
-                       ret=40;
+                       ret=SSL_C_EXPORT_KEYLENGTH(c)*8;
                        }
                else
                        {
@@ -719,3 +793,55 @@ int *alg_bits;
        return(ret);
        }
 
+SSL_COMP *ssl3_comp_find(sk,n)
+STACK *sk;
+int n;
+       {
+       SSL_COMP *ctmp;
+       int i,nn;
+
+       if ((n == 0) || (sk == NULL)) return(NULL);
+       nn=sk_num(sk);
+       for (i=0; i<nn; i++)
+               {
+               ctmp=(SSL_COMP *)sk_value(sk,i);
+               if (ctmp->id == n)
+                       return(ctmp);
+               }
+       return(NULL);
+       }
+
+static int sk_comp_cmp(a,b)
+SSL_COMP **a,**b;
+       {
+       return((*a)->id-(*b)->id);
+       }
+
+STACK *SSL_COMP_get_compression_methods()
+       {
+       return(ssl_comp_methods);
+       }
+
+int SSL_COMP_add_compression_method(id,cm)
+int id;
+COMP_METHOD *cm;
+       {
+       SSL_COMP *comp;
+       STACK *sk;
+
+       comp=(SSL_COMP *)Malloc(sizeof(SSL_COMP));
+       comp->id=id;
+       comp->method=cm;
+       if (ssl_comp_methods == NULL)
+               sk=ssl_comp_methods=sk_new(sk_comp_cmp);
+       else
+               sk=ssl_comp_methods;
+       if ((sk == NULL) || !sk_push(sk,(char *)comp))
+               {
+               SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,ERR_R_MALLOC_FAILURE);
+               return(0);
+               }
+       else
+               return(1);
+       }
+