From d02b48c63a58ea4367a0e905979f140b7d090f86 Mon Sep 17 00:00:00 2001 From: "Ralf S. Engelschall" Date: Mon, 21 Dec 1998 10:52:47 +0000 Subject: Import of old SSLeay release: SSLeay 0.8.1b --- ssl/ssl_ciph.c | 721 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 721 insertions(+) create mode 100644 ssl/ssl_ciph.c (limited to 'ssl/ssl_ciph.c') diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c new file mode 100644 index 0000000000..9fed3ad59a --- /dev/null +++ b/ssl/ssl_ciph.c @@ -0,0 +1,721 @@ +/* ssl/ssl_ciph.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "objects.h" +#include "ssl_locl.h" + +#define SSL_ENC_DES_IDX 0 +#define SSL_ENC_3DES_IDX 1 +#define SSL_ENC_RC4_IDX 2 +#define SSL_ENC_RC2_IDX 3 +#define SSL_ENC_IDEA_IDX 4 +#define SSL_ENC_eFZA_IDX 5 +#define SSL_ENC_NULL_IDX 6 +#define SSL_ENC_NUM_IDX 7 + +static EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={ + NULL,NULL,NULL,NULL,NULL,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 +static EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={ + NULL,NULL,NULL, + }; + +typedef struct cipher_sort_st + { + SSL_CIPHER *cipher; + int pref; + } CIPHER_SORT; + +#define CIPHER_ADD 1 +#define CIPHER_KILL 2 +#define CIPHER_DEL 3 +#define CIPHER_ORDER 4 + +typedef struct cipher_choice_st + { + int type; + unsigned long algorithms; + unsigned long mask; + STACK *order; + } CIPHER_CHOICE; + +static SSL_CIPHER cipher_aliases[]={ + {0,SSL_TXT_ALL, 0,SSL_ALL, 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}, + {0,SSL_TXT_kEDH,0,SSL_kEDH, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_kFZA,0,SSL_kFZA, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_DH, 0,SSL_DH, 0,SSL_MKEY_MASK}, + {0,SSL_TXT_EDH, 0,SSL_EDH, 0,SSL_MKEY_MASK|SSL_AUTH_MASK}, + + {0,SSL_TXT_aRSA,0,SSL_aRSA, 0,SSL_AUTH_MASK}, + {0,SSL_TXT_aDSS,0,SSL_aDSS, 0,SSL_AUTH_MASK}, + {0,SSL_TXT_aFZA,0,SSL_aFZA, 0,SSL_AUTH_MASK}, + {0,SSL_TXT_aNULL,0,SSL_aNULL,0,SSL_AUTH_MASK}, + {0,SSL_TXT_aDH, 0,SSL_aDH, 0,SSL_AUTH_MASK}, + {0,SSL_TXT_DSS, 0,SSL_DSS, 0,SSL_AUTH_MASK}, + + {0,SSL_TXT_DES, 0,SSL_DES, 0,SSL_ENC_MASK}, + {0,SSL_TXT_3DES,0,SSL_3DES, 0,SSL_ENC_MASK}, + {0,SSL_TXT_RC4, 0,SSL_RC4, 0,SSL_ENC_MASK}, + {0,SSL_TXT_RC2, 0,SSL_RC2, 0,SSL_ENC_MASK}, + {0,SSL_TXT_IDEA,0,SSL_IDEA, 0,SSL_ENC_MASK}, + {0,SSL_TXT_eNULL,0,SSL_eNULL,0,SSL_ENC_MASK}, + {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}, + + {0,SSL_TXT_NULL,0,SSL_NULL, 0,SSL_ENC_MASK}, + {0,SSL_TXT_RSA, 0,SSL_RSA, 0,SSL_AUTH_MASK|SSL_MKEY_MASK}, + {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_MEDIUM,0,SSL_MEDIUM,0,SSL_STRONG_MASK}, + {0,SSL_TXT_HIGH, 0,SSL_HIGH,0,SSL_STRONG_MASK}, + }; + +static int init_ciphers=1; +static void load_ciphers(); + +static int cmp_by_name(a,b) +SSL_CIPHER **a,**b; + { + return(strcmp((*a)->name,(*b)->name)); + } + +static void load_ciphers() + { + init_ciphers=0; + ssl_cipher_methods[SSL_ENC_DES_IDX]= + EVP_get_cipherbyname(SN_des_cbc); + ssl_cipher_methods[SSL_ENC_3DES_IDX]= + EVP_get_cipherbyname(SN_des_ede3_cbc); + ssl_cipher_methods[SSL_ENC_RC4_IDX]= + EVP_get_cipherbyname(SN_rc4); + ssl_cipher_methods[SSL_ENC_RC2_IDX]= + EVP_get_cipherbyname(SN_rc2_cbc); + ssl_cipher_methods[SSL_ENC_IDEA_IDX]= + EVP_get_cipherbyname(SN_idea_cbc); + + 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; +EVP_CIPHER **enc; +EVP_MD **md; + { + int i; + + if (c == NULL) return(0); + + switch (c->algorithms & SSL_ENC_MASK) + { + case SSL_DES: + i=SSL_ENC_DES_IDX; + break; + case SSL_3DES: + i=SSL_ENC_3DES_IDX; + break; + case SSL_RC4: + i=SSL_ENC_RC4_IDX; + break; + case SSL_RC2: + i=SSL_ENC_RC2_IDX; + break; + case SSL_IDEA: + i=SSL_ENC_IDEA_IDX; + break; + case SSL_eNULL: + i=SSL_ENC_NULL_IDX; + break; + break; + default: + i= -1; + break; + } + + if ((i < 0) || (i > SSL_ENC_NUM_IDX)) + *enc=NULL; + else + { + if (i == SSL_ENC_NULL_IDX) + *enc=EVP_enc_null(); + else + *enc=ssl_cipher_methods[i]; + } + + switch (c->algorithms & SSL_MAC_MASK) + { + 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; + default: + i= -1; + break; + } + if ((i < 0) || (i > SSL_MD_NUM_IDX)) + *md=NULL; + else + *md=ssl_digest_methods[i]; + + if ((*enc != NULL) && (*md != NULL)) + return(1); + else + return(0); + } + +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; +char *str; + { + SSL_CIPHER *c; + char *l; + STACK *ret=NULL,*ok=NULL; +#define CL_BUF 40 + char buf[CL_BUF]; + char *tmp_str=NULL; + unsigned long mask,algorithms,ma; + char *start; + 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; + CIPHER_CHOICE *ops=NULL; + SSL_CIPHER c_tmp,*cp; + + if (str == NULL) return(NULL); + + if (strncmp(str,"DEFAULT",7) == 0) + { + i=strlen(str)+2+strlen(SSL_DEFAULT_CIPHER_LIST); + if ((tmp_str=Malloc(i)) == NULL) + { + SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE); + goto err; + } + strcpy(tmp_str,SSL_DEFAULT_CIPHER_LIST); + strcat(tmp_str,&(str[7])); + str=tmp_str; + } + if (init_ciphers) load_ciphers(); + + 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; +#ifdef NO_RSA + mask|=SSL_aRSA|SSL_kRSA; +#endif +#ifdef NO_DSA + mask|=SSL_aDSS; +#endif +#ifdef NO_DH + mask|=SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH; +#endif + +#ifndef SSL_ALLOW_ENULL + mask|=SSL_eNULL; +#endif + + mask|=(ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL)?SSL_DES :0; + mask|=(ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL)?SSL_3DES:0; + mask|=(ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL)?SSL_RC4 :0; + mask|=(ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL)?SSL_RC2 :0; + mask|=(ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL)?SSL_IDEA:0; + 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; + + /* Get the initial list of ciphers */ + for (i=0; iget_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; + if (!sk_push(ca_list,(char *)c)) goto err; + } + } + + /* special case */ + cipher_aliases[0].algorithms= ~mask; + + /* get the aliases */ + k=sizeof(cipher_aliases)/sizeof(SSL_CIPHER); + for (j=0; j= 'A') && (ch <= 'Z')) || + ((ch >= '0') && (ch <= '9')) || + ((ch >= 'a') && (ch <= 'z')) || + (ch == '-')) + { + buf[i]=ch; + ch= *(++l); + i++; + if (i >= (CL_BUF-2)) break; + } + buf[i]='\0'; + if (ch != '\0') l++; + + /* check for multi-part specification */ + multi=(ch == '+')?1:0; + + c_tmp.name=buf; + j=sk_find(ca_list,(char *)&c_tmp); + if (j < 0) + { + if (ch == '\0') + break; + else + continue; + } + + cp=(SSL_CIPHER *)sk_value(ca_list,j); + ops[current_x].algorithms|=cp->algorithms; + /* We add the SSL_SSL_MASK so we can match the + * SSLv2 and SSLv3 versions of RC4-MD5 */ + ops[current_x].mask|=cp->mask; + if (!multi) break; + } + current_x++; + if (ch == '\0') break; + } + + num_x=current_x; + current_x=0; + +#ifdef CIPHER_DEBUG + printf("<--->\n"); +#endif + + for (i=0; iname); +#endif + for (j=0; jalgorithms; +#ifdef CIPHER_DEBUG + printf(" %s %08lX&%08lX==0 || %08lX != %08lX \n", + cp->name,ops[j].mask,cp->algorithms,ma,algorithms); +#endif + if ((ma == 0) || ((ma & algorithms) != ma)) + { + 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 (old_x < 0) + { + old_x=j; + old_y=sk_num(ops[j].order); + sk_push(ops[j].order,(char *)cp); + } + } + /* Move the added cipher to this location */ + else if (k == CIPHER_ORDER) + { + if (old_x >= 0) + { + 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; + } + } + /* Remove added cipher */ + else if ((k == CIPHER_DEL) || (k == CIPHER_KILL)) + { + if (old_x >= 0) + { + sk_value(ops[old_x].order,old_y)=NULL; + old_x= -1; + } + if (k == CIPHER_KILL) + break; + } + } + } + + for (i=0; i\n",cp->name); +#endif + } + } + } + + if (cipher_list != NULL) + { + if (*cipher_list != NULL) + sk_free(*cipher_list); + *cipher_list=ret; + } + + if (cipher_list_by_id != NULL) + { + if (*cipher_list_by_id != NULL) + sk_free(*cipher_list_by_id); + *cipher_list_by_id=sk_dup(ret); + } + + if ( (cipher_list_by_id == NULL) || + (*cipher_list_by_id == NULL) || + (cipher_list == NULL) || + (*cipher_list == NULL)) + goto err; + sk_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp); + + ok=ret; + ret=NULL; +err: + if (tmp_str) Free(tmp_str); + if (ops != NULL) + { + for (i=0; ialgorithms; + alg2=cipher->algorithm2; + + export=(alg&SSL_EXP)?1:0; + exp=(export)?" export":""; + + if (alg & SSL_SSLV2) + ver="SSLv2"; + else if (alg & SSL_SSLV3) + ver="SSLv3"; + else + ver="unknown"; + + switch (alg&SSL_MKEY_MASK) + { + case SSL_kRSA: + kx=(export)?"RSA(512)":"RSA"; + break; + case SSL_kDHr: + kx="DH/RSA"; + break; + case SSL_kDHd: + kx="DH/DSS"; + break; + case SSL_kFZA: + kx="Fortezza"; + break; + case SSL_kEDH: + kx=(export)?"DH(512)":"DH"; + break; + default: + kx="unknown"; + } + + switch (alg&SSL_AUTH_MASK) + { + case SSL_aRSA: + au="RSA"; + break; + case SSL_aDSS: + au="DSS"; + break; + case SSL_aDH: + au="DH"; + break; + case SSL_aFZA: + case SSL_aNULL: + au="None"; + break; + default: + au="unknown"; + break; + } + + switch (alg&SSL_ENC_MASK) + { + case SSL_DES: + enc=export?"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)"); + break; + case SSL_RC2: + enc=export?"RC2(40)":"RC2(128)"; + break; + case SSL_IDEA: + enc="IDEA(128)"; + break; + case SSL_eFZA: + enc="Fortezza"; + break; + case SSL_eNULL: + enc="None"; + break; + default: + enc="unknown"; + break; + } + + switch (alg&SSL_MAC_MASK) + { + case SSL_MD5: + mac="MD5"; + break; + case SSL_SHA0: + mac="SHA0"; + break; + case SSL_SHA1: + mac="SHA1"; + break; + default: + mac="unknown"; + break; + } + + if (buf == NULL) + { + buf=Malloc(128); + if (buf == NULL) return("Malloc Error"); + } + else if (len < 128) + return("Buffer too small"); + + sprintf(buf,format,cipher->name,ver,kx,au,enc,mac,exp); + return(buf); + } + +char *SSL_CIPHER_get_version(c) +SSL_CIPHER *c; + { + int i; + + i=(int)(c->id>>24L); + if (i == 3) + return("SSLv3"); + else if (i == 2) + return("SSLv2"); + else + return("unknown"); + } + +/* return the actual cipher being used */ +char *SSL_CIPHER_get_name(c) +SSL_CIPHER *c; + { + if (c != NULL) + return(c->name); + return("(NONE)"); + } + +/* number of bits for symetric cipher */ +int SSL_CIPHER_get_bits(c,alg_bits) +SSL_CIPHER *c; +int *alg_bits; + { + int ret=0,a=0; + EVP_CIPHER *enc; + EVP_MD *md; + + if (c != NULL) + { + if (!ssl_cipher_get_evp(c,&enc,&md)) + return(0); + + a=EVP_CIPHER_key_length(enc)*8; + + if (c->algorithms & SSL_EXP) + { + ret=40; + } + else + { + if (c->algorithm2 & SSL2_CF_8_BYTE_ENC) + ret=64; + else + ret=a; + } + } + + if (alg_bits != NULL) *alg_bits=a; + + return(ret); + } + -- cgit v1.2.3