This commit was generated by cvs2svn to track changes on a CVS vendor
[openssl.git] / ssl / ssl_ciph.c
1 /* ssl/ssl_ciph.c */
2 /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include "objects.h"
61 #include "ssl_locl.h"
62
63 #define SSL_ENC_DES_IDX         0
64 #define SSL_ENC_3DES_IDX        1
65 #define SSL_ENC_RC4_IDX         2
66 #define SSL_ENC_RC2_IDX         3
67 #define SSL_ENC_IDEA_IDX        4
68 #define SSL_ENC_eFZA_IDX        5
69 #define SSL_ENC_NULL_IDX        6
70 #define SSL_ENC_NUM_IDX         7
71
72 static EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={
73         NULL,NULL,NULL,NULL,NULL,NULL,
74         };
75
76 #define SSL_MD_MD5_IDX  0
77 #define SSL_MD_SHA0_IDX 1
78 #define SSL_MD_SHA1_IDX 2
79 #define SSL_MD_NUM_IDX  3
80 static EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={
81         NULL,NULL,NULL,
82         };
83
84 typedef struct cipher_sort_st
85         {
86         SSL_CIPHER *cipher;
87         int pref;
88         } CIPHER_SORT;
89
90 #define CIPHER_ADD      1
91 #define CIPHER_KILL     2
92 #define CIPHER_DEL      3
93 #define CIPHER_ORDER    4
94
95 typedef struct cipher_choice_st
96         {
97         int type;
98         unsigned long algorithms;
99         unsigned long mask;
100         STACK *order;
101         } CIPHER_CHOICE;
102
103 static SSL_CIPHER cipher_aliases[]={
104         {0,SSL_TXT_ALL, 0,SSL_ALL,   0,SSL_ALL},        /* must be first */
105         {0,SSL_TXT_kRSA,0,SSL_kRSA,  0,SSL_MKEY_MASK},
106         {0,SSL_TXT_kDHr,0,SSL_kDHr,  0,SSL_MKEY_MASK},
107         {0,SSL_TXT_kDHd,0,SSL_kDHd,  0,SSL_MKEY_MASK},
108         {0,SSL_TXT_kEDH,0,SSL_kEDH,  0,SSL_MKEY_MASK},
109         {0,SSL_TXT_kFZA,0,SSL_kFZA,  0,SSL_MKEY_MASK},
110         {0,SSL_TXT_DH,  0,SSL_DH,    0,SSL_MKEY_MASK},
111         {0,SSL_TXT_EDH, 0,SSL_EDH,   0,SSL_MKEY_MASK|SSL_AUTH_MASK},
112
113         {0,SSL_TXT_aRSA,0,SSL_aRSA,  0,SSL_AUTH_MASK},
114         {0,SSL_TXT_aDSS,0,SSL_aDSS,  0,SSL_AUTH_MASK},
115         {0,SSL_TXT_aFZA,0,SSL_aFZA,  0,SSL_AUTH_MASK},
116         {0,SSL_TXT_aNULL,0,SSL_aNULL,0,SSL_AUTH_MASK},
117         {0,SSL_TXT_aDH, 0,SSL_aDH,   0,SSL_AUTH_MASK},
118         {0,SSL_TXT_DSS, 0,SSL_DSS,   0,SSL_AUTH_MASK},
119
120         {0,SSL_TXT_DES, 0,SSL_DES,   0,SSL_ENC_MASK},
121         {0,SSL_TXT_3DES,0,SSL_3DES,  0,SSL_ENC_MASK},
122         {0,SSL_TXT_RC4, 0,SSL_RC4,   0,SSL_ENC_MASK},
123         {0,SSL_TXT_RC2, 0,SSL_RC2,   0,SSL_ENC_MASK},
124         {0,SSL_TXT_IDEA,0,SSL_IDEA,  0,SSL_ENC_MASK},
125         {0,SSL_TXT_eNULL,0,SSL_eNULL,0,SSL_ENC_MASK},
126         {0,SSL_TXT_eFZA,0,SSL_eFZA,  0,SSL_ENC_MASK},
127
128         {0,SSL_TXT_MD5, 0,SSL_MD5,   0,SSL_MAC_MASK},
129         {0,SSL_TXT_SHA0,0,SSL_SHA0,  0,SSL_MAC_MASK},
130         {0,SSL_TXT_SHA1,0,SSL_SHA1,  0,SSL_MAC_MASK},
131         {0,SSL_TXT_SHA, 0,SSL_SHA,   0,SSL_MAC_MASK},
132
133         {0,SSL_TXT_NULL,0,SSL_NULL,  0,SSL_ENC_MASK},
134         {0,SSL_TXT_RSA, 0,SSL_RSA,   0,SSL_AUTH_MASK|SSL_MKEY_MASK},
135         {0,SSL_TXT_ADH, 0,SSL_ADH,   0,SSL_AUTH_MASK|SSL_MKEY_MASK},
136         {0,SSL_TXT_FZA, 0,SSL_FZA,   0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK},
137
138         {0,SSL_TXT_EXP, 0,SSL_EXP,   0,SSL_EXP_MASK},
139         {0,SSL_TXT_EXPORT,0,SSL_EXPORT,0,SSL_EXP_MASK},
140         {0,SSL_TXT_SSLV2,0,SSL_SSLV2,0,SSL_SSL_MASK},
141         {0,SSL_TXT_SSLV3,0,SSL_SSLV3,0,SSL_SSL_MASK},
142         {0,SSL_TXT_LOW,  0,SSL_LOW,0,SSL_STRONG_MASK},
143         {0,SSL_TXT_MEDIUM,0,SSL_MEDIUM,0,SSL_STRONG_MASK},
144         {0,SSL_TXT_HIGH, 0,SSL_HIGH,0,SSL_STRONG_MASK},
145         };
146
147 static int init_ciphers=1;
148 static void load_ciphers();
149
150 static int cmp_by_name(a,b)
151 SSL_CIPHER **a,**b;
152         {
153         return(strcmp((*a)->name,(*b)->name));
154         }
155
156 static void load_ciphers()
157         {
158         init_ciphers=0;
159         ssl_cipher_methods[SSL_ENC_DES_IDX]= 
160                 EVP_get_cipherbyname(SN_des_cbc);
161         ssl_cipher_methods[SSL_ENC_3DES_IDX]=
162                 EVP_get_cipherbyname(SN_des_ede3_cbc);
163         ssl_cipher_methods[SSL_ENC_RC4_IDX]=
164                 EVP_get_cipherbyname(SN_rc4);
165         ssl_cipher_methods[SSL_ENC_RC2_IDX]= 
166                 EVP_get_cipherbyname(SN_rc2_cbc);
167         ssl_cipher_methods[SSL_ENC_IDEA_IDX]= 
168                 EVP_get_cipherbyname(SN_idea_cbc);
169
170         ssl_digest_methods[SSL_MD_MD5_IDX]=
171                 EVP_get_digestbyname(SN_md5);
172         ssl_digest_methods[SSL_MD_SHA0_IDX]=
173                 EVP_get_digestbyname(SN_sha);
174         ssl_digest_methods[SSL_MD_SHA1_IDX]=
175                 EVP_get_digestbyname(SN_sha1);
176         }
177
178 int ssl_cipher_get_evp(c,enc,md)
179 SSL_CIPHER *c;
180 EVP_CIPHER **enc;
181 EVP_MD **md;
182         {
183         int i;
184
185         if (c == NULL) return(0);
186
187         switch (c->algorithms & SSL_ENC_MASK)
188                 {
189         case SSL_DES:
190                 i=SSL_ENC_DES_IDX;
191                 break;
192         case SSL_3DES:
193                 i=SSL_ENC_3DES_IDX;
194                 break;
195         case SSL_RC4:
196                 i=SSL_ENC_RC4_IDX;
197                 break;
198         case SSL_RC2:
199                 i=SSL_ENC_RC2_IDX;
200                 break;
201         case SSL_IDEA:
202                 i=SSL_ENC_IDEA_IDX;
203                 break;
204         case SSL_eNULL:
205                 i=SSL_ENC_NULL_IDX;
206                 break;
207                 break;
208         default:
209                 i= -1;
210                 break;
211                 }
212
213         if ((i < 0) || (i > SSL_ENC_NUM_IDX))
214                 *enc=NULL;
215         else
216                 {
217                 if (i == SSL_ENC_NULL_IDX)
218                         *enc=EVP_enc_null();
219                 else
220                         *enc=ssl_cipher_methods[i];
221                 }
222
223         switch (c->algorithms & SSL_MAC_MASK)
224                 {
225         case SSL_MD5:
226                 i=SSL_MD_MD5_IDX;
227                 break;
228         case SSL_SHA0:
229                 i=SSL_MD_SHA0_IDX;
230                 break;
231         case SSL_SHA1:
232                 i=SSL_MD_SHA1_IDX;
233                 break;
234         default:
235                 i= -1;
236                 break;
237                 }
238         if ((i < 0) || (i > SSL_MD_NUM_IDX))
239                 *md=NULL;
240         else
241                 *md=ssl_digest_methods[i];
242
243         if ((*enc != NULL) && (*md != NULL))
244                 return(1);
245         else
246                 return(0);
247         }
248
249 STACK *ssl_create_cipher_list(ssl_method,cipher_list,cipher_list_by_id,str)
250 SSL_METHOD *ssl_method;
251 STACK **cipher_list,**cipher_list_by_id;
252 char *str;
253         {
254         SSL_CIPHER *c;
255         char *l;
256         STACK *ret=NULL,*ok=NULL;
257 #define CL_BUF  40
258         char buf[CL_BUF];
259         char *tmp_str=NULL;
260         unsigned long mask,algorithms,ma;
261         char *start;
262         int i,j,k,num=0,ch,multi;
263         unsigned long al;
264         STACK *ca_list=NULL;
265         STACK *c_list=NULL;
266         int old_x,old_y,current_x,num_x;
267         CIPHER_CHOICE *ops=NULL;
268         SSL_CIPHER c_tmp,*cp;
269
270         if (str == NULL) return(NULL);
271
272         if (strncmp(str,"DEFAULT",7) == 0)
273                 {
274                 i=strlen(str)+2+strlen(SSL_DEFAULT_CIPHER_LIST);
275                 if ((tmp_str=Malloc(i)) == NULL)
276                         {
277                         SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
278                         goto err;
279                         }
280                 strcpy(tmp_str,SSL_DEFAULT_CIPHER_LIST);
281                 strcat(tmp_str,&(str[7]));
282                 str=tmp_str;
283                 }
284         if (init_ciphers) load_ciphers();
285
286         num=ssl_method->num_ciphers();
287
288         if ((ret=(STACK *)sk_new(NULL)) == NULL) goto err;
289         if ((c_list=(STACK *)sk_new(NULL)) == NULL) goto err;
290         if ((ca_list=(STACK *)sk_new(cmp_by_name)) == NULL) goto err;
291
292         mask =SSL_kFZA;
293 #ifdef NO_RSA
294         mask|=SSL_aRSA|SSL_kRSA;
295 #endif
296 #ifdef NO_DSA
297         mask|=SSL_aDSS;
298 #endif
299 #ifdef NO_DH
300         mask|=SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH;
301 #endif
302
303 #ifndef SSL_ALLOW_ENULL
304         mask|=SSL_eNULL;
305 #endif
306
307         mask|=(ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL)?SSL_DES :0;
308         mask|=(ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL)?SSL_3DES:0;
309         mask|=(ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL)?SSL_RC4 :0;
310         mask|=(ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL)?SSL_RC2 :0;
311         mask|=(ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL)?SSL_IDEA:0;
312         mask|=(ssl_cipher_methods[SSL_ENC_eFZA_IDX] == NULL)?SSL_eFZA:0;
313
314         mask|=(ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL)?SSL_MD5 :0;
315         mask|=(ssl_digest_methods[SSL_MD_SHA0_IDX] == NULL)?SSL_SHA0:0;
316         mask|=(ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL)?SSL_SHA1:0;
317
318         /* Get the initial list of ciphers */
319         for (i=0; i<num; i++)
320                 {
321                 c=ssl_method->get_cipher((unsigned int)i);
322                 /* drop those that use any of that is not available */
323                 if ((c != NULL) && c->valid && !(c->algorithms & mask))
324                         {
325                         if (!sk_push(c_list,(char *)c)) goto err;
326                         if (!sk_push(ca_list,(char *)c)) goto err;
327                         }
328                 }
329
330         /* special case */
331         cipher_aliases[0].algorithms= ~mask;
332
333         /* get the aliases */
334         k=sizeof(cipher_aliases)/sizeof(SSL_CIPHER);
335         for (j=0; j<k; j++)
336                 {
337                 al=cipher_aliases[j].algorithms;
338                 /* Drop those that are not relevent */
339                 if ((al & mask) == al) continue;
340                 if (!sk_push(ca_list,(char *)&(cipher_aliases[j]))) goto err;
341                 }
342
343         /* ca_list now holds a 'stack' of SSL_CIPHERS, some real, some
344          * 'aliases' */
345
346         /* how many parameters are there? */
347         num=1;
348         for (l=str; *l; l++)
349                 if (*l == ':') num++;
350         ops=(CIPHER_CHOICE *)Malloc(sizeof(CIPHER_CHOICE)*num);
351         if (ops == NULL) goto err;
352         memset(ops,0,sizeof(CIPHER_CHOICE)*num);
353         for (i=0; i<num; i++)
354                 if ((ops[i].order=sk_new_null()) == NULL) goto err;
355
356         /* we now parse the input string and create our operations */
357         l=str;
358         i=0;
359         current_x=0;
360
361         for (;;)
362                 {
363                 ch= *l;
364                 if (ch == '-')
365                         { j=CIPHER_DEL; l++; }
366                 else if (ch == '+')
367                         { j=CIPHER_ORDER; l++; }
368                 else if (ch == '!')
369                         { j=CIPHER_KILL; l++; }
370                 else    
371                         { j=CIPHER_ADD; }
372
373                 if (*l == ':')
374                         {
375                         l++;
376                         continue;
377                         }
378                 ops[current_x].type=j;
379                 ops[current_x].algorithms=0;
380                 ops[current_x].mask=0;
381
382                 start=l;
383                 for (;;)
384                         {
385                         ch= *l;
386                         i=0;
387                         while ( ((ch >= 'A') && (ch <= 'Z')) ||
388                                 ((ch >= '0') && (ch <= '9')) ||
389                                 ((ch >= 'a') && (ch <= 'z')) ||
390                                  (ch == '-'))
391                                  {
392                                  buf[i]=ch;
393                                  ch= *(++l);
394                                  i++;
395                                  if (i >= (CL_BUF-2)) break;
396                                  }
397                         buf[i]='\0';
398                         if (ch != '\0') l++;
399
400                         /* check for multi-part specification */
401                         multi=(ch == '+')?1:0;
402
403                         c_tmp.name=buf;
404                         j=sk_find(ca_list,(char *)&c_tmp);
405                         if (j < 0)
406                                 {
407                                 if (ch == '\0')
408                                         break;
409                                 else
410                                         continue;
411                                 }
412
413                         cp=(SSL_CIPHER *)sk_value(ca_list,j);
414                         ops[current_x].algorithms|=cp->algorithms;
415                         /* We add the SSL_SSL_MASK so we can match the
416                          * SSLv2 and SSLv3 versions of RC4-MD5 */
417                         ops[current_x].mask|=cp->mask;
418                         if (!multi) break;
419                         }
420                 current_x++;
421                 if (ch == '\0') break;
422                 }
423
424         num_x=current_x;
425         current_x=0;
426
427 #ifdef CIPHER_DEBUG
428         printf("<--->\n");
429 #endif
430
431         for (i=0; i<sk_num(c_list); i++)
432                 {
433                 old_x= -1;
434                 old_y= -1;
435                 cp=(SSL_CIPHER *)sk_value(c_list,i);
436 #ifdef CIPHER_DEBUG
437                 printf("[%s]\n",cp->name);
438 #endif
439                 for (j=0; j<num_x; j++)
440                         {
441                         algorithms=ops[j].algorithms;
442                         ma=ops[j].mask & cp->algorithms;
443 #ifdef CIPHER_DEBUG
444                         printf("  %s %08lX&%08lX==0 || %08lX != %08lX \n",
445                                 cp->name,ops[j].mask,cp->algorithms,ma,algorithms);
446 #endif
447                         if ((ma == 0) || ((ma & algorithms) != ma))
448                                 {
449                                 continue;
450                                 }
451                         k=ops[j].type;
452 #ifdef CIPHER_DEBUG
453                         printf(">>%s\n",cp->name);
454 #endif
455
456                         /* add the cipher if it has not been added yet. */
457                         if (k == CIPHER_ADD)
458                                 {
459                                 if (old_x < 0)
460                                         {
461                                         old_x=j;
462                                         old_y=sk_num(ops[j].order);
463                                         sk_push(ops[j].order,(char *)cp);
464                                         }
465                                 }
466                         /* Move the added cipher to this location */
467                         else if (k == CIPHER_ORDER)
468                                 {
469                                 if (old_x >= 0)
470                                         {
471                                         sk_value(ops[old_x].order,old_y)=NULL;
472                                         old_y=sk_num(ops[j].order);
473                                         sk_push(ops[j].order,(char *)cp);
474                                         old_x=j;
475                                         }
476                                 }
477                         /* Remove added cipher */
478                         else if ((k == CIPHER_DEL) || (k == CIPHER_KILL))
479                                 {
480                                 if (old_x >= 0)
481                                         {
482                                         sk_value(ops[old_x].order,old_y)=NULL;
483                                         old_x= -1;
484                                         }
485                                 if (k == CIPHER_KILL)
486                                         break;
487                                 }
488                         }
489                 }
490
491         for (i=0; i<num_x; i++)
492                 {
493                 for (j=0; j<sk_num(ops[i].order); j++)
494                         {
495                         cp=(SSL_CIPHER *)sk_value(ops[i].order,j);
496                         if (cp != NULL)
497                                 {
498                                 sk_push(ret,(char *)cp);
499 #ifdef CIPHER_DEBUG
500                                 printf("<%s>\n",cp->name);
501 #endif
502                                 }
503                         }
504                 }
505
506         if (cipher_list != NULL)
507                 {
508                 if (*cipher_list != NULL)
509                         sk_free(*cipher_list);
510                 *cipher_list=ret;
511                 }
512
513         if (cipher_list_by_id != NULL)
514                 {
515                 if (*cipher_list_by_id != NULL)
516                         sk_free(*cipher_list_by_id);
517                 *cipher_list_by_id=sk_dup(ret);
518                 }
519
520         if (    (cipher_list_by_id == NULL) ||
521                 (*cipher_list_by_id == NULL) ||
522                 (cipher_list == NULL) ||
523                 (*cipher_list == NULL))
524                 goto err;
525         sk_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
526
527         ok=ret;
528         ret=NULL;
529 err:
530         if (tmp_str) Free(tmp_str);
531         if (ops != NULL)
532                 {
533                 for (i=0; i<num; i++)
534                         if (ops[i].order != NULL)
535                                 sk_free(ops[i].order);
536                 Free(ops);
537                 }
538         if (ret != NULL) sk_free(ret);
539         if (c_list != NULL) sk_free(c_list);
540         if (ca_list != NULL) sk_free(ca_list);
541         return(ok);
542         }
543
544 char *SSL_CIPHER_description(cipher,buf,len)
545 SSL_CIPHER *cipher;
546 char *buf;
547 int len;
548         {
549         int export;
550         char *ver,*exp;
551         char *kx,*au,*enc,*mac;
552         unsigned long alg,alg2;
553         static char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s\n";
554         
555         alg=cipher->algorithms;
556         alg2=cipher->algorithm2;
557
558         export=(alg&SSL_EXP)?1:0;
559         exp=(export)?" export":"";
560
561         if (alg & SSL_SSLV2)
562                 ver="SSLv2";
563         else if (alg & SSL_SSLV3)
564                 ver="SSLv3";
565         else
566                 ver="unknown";
567
568         switch (alg&SSL_MKEY_MASK)
569                 {
570         case SSL_kRSA:
571                 kx=(export)?"RSA(512)":"RSA";
572                 break;
573         case SSL_kDHr:
574                 kx="DH/RSA";
575                 break;
576         case SSL_kDHd:
577                 kx="DH/DSS";
578                 break;
579         case SSL_kFZA:
580                 kx="Fortezza";
581                 break;
582         case SSL_kEDH:
583                 kx=(export)?"DH(512)":"DH";
584                 break;
585         default:
586                 kx="unknown";
587                 }
588
589         switch (alg&SSL_AUTH_MASK)
590                 {
591         case SSL_aRSA:
592                 au="RSA";
593                 break;
594         case SSL_aDSS:
595                 au="DSS";
596                 break;
597         case SSL_aDH:
598                 au="DH";
599                 break;
600         case SSL_aFZA:
601         case SSL_aNULL:
602                 au="None";
603                 break;
604         default:
605                 au="unknown";
606                 break;
607                 }
608
609         switch (alg&SSL_ENC_MASK)
610                 {
611         case SSL_DES:
612                 enc=export?"DES(40)":"DES(56)";
613                 break;
614         case SSL_3DES:
615                 enc="3DES(168)";
616                 break;
617         case SSL_RC4:
618                 enc=export?"RC4(40)":((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)");
619                 break;
620         case SSL_RC2:
621                 enc=export?"RC2(40)":"RC2(128)";
622                 break;
623         case SSL_IDEA:
624                 enc="IDEA(128)";
625                 break;
626         case SSL_eFZA:
627                 enc="Fortezza";
628                 break;
629         case SSL_eNULL:
630                 enc="None";
631                 break;
632         default:
633                 enc="unknown";
634                 break;
635                 }
636
637         switch (alg&SSL_MAC_MASK)
638                 {
639         case SSL_MD5:
640                 mac="MD5";
641                 break;
642         case SSL_SHA0:
643                 mac="SHA0";
644                 break;
645         case SSL_SHA1:
646                 mac="SHA1";
647                 break;
648         default:
649                 mac="unknown";
650                 break;
651                 }
652
653         if (buf == NULL)
654                 {
655                 buf=Malloc(128);
656                 if (buf == NULL) return("Malloc Error");
657                 }
658         else if (len < 128)
659                 return("Buffer too small");
660
661         sprintf(buf,format,cipher->name,ver,kx,au,enc,mac,exp);
662         return(buf);
663         }
664
665 char *SSL_CIPHER_get_version(c)
666 SSL_CIPHER *c;
667         {
668         int i;
669
670         i=(int)(c->id>>24L);
671         if (i == 3)
672                 return("SSLv3");
673         else if (i == 2)
674                 return("SSLv2");
675         else
676                 return("unknown");
677         }
678
679 /* return the actual cipher being used */
680 char *SSL_CIPHER_get_name(c)
681 SSL_CIPHER *c;
682         {
683         if (c != NULL)
684                 return(c->name);
685         return("(NONE)");
686         }
687
688 /* number of bits for symetric cipher */
689 int SSL_CIPHER_get_bits(c,alg_bits)
690 SSL_CIPHER *c;
691 int *alg_bits;
692         {
693         int ret=0,a=0;
694         EVP_CIPHER *enc;
695         EVP_MD *md;
696
697         if (c != NULL)
698                 {
699                 if (!ssl_cipher_get_evp(c,&enc,&md))
700                         return(0);
701
702                 a=EVP_CIPHER_key_length(enc)*8;
703
704                 if (c->algorithms & SSL_EXP)
705                         {
706                         ret=40;
707                         }
708                 else
709                         {
710                         if (c->algorithm2 & SSL2_CF_8_BYTE_ENC)
711                                 ret=64;
712                         else
713                                 ret=a;
714                         }
715                 }
716
717         if (alg_bits != NULL) *alg_bits=a;
718         
719         return(ret);
720         }
721