* 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>
#define SSL_ENC_IDEA_IDX 4
#define SSL_ENC_eFZA_IDX 5
#define SSL_ENC_NULL_IDX 6
-#define SSL_ENC_NUM_IDX 7
+#define SSL_ENC_AES128_IDX 7
+#define SSL_ENC_AES256_IDX 8
+#define SSL_ENC_NUM_IDX 9
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
} CIPHER_ORDER;
static const SSL_CIPHER cipher_aliases[]={
- /* Don't include eNULL unless specifically enabled */
- {0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL, SSL_ALL ,0,0,0,SSL_ALL,SSL_ALL}, /* must be first */
+ /* 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},
{0,SSL_TXT_aFZA,0,SSL_aFZA, 0,0,0,0,SSL_AUTH_MASK,0},
{0,SSL_TXT_IDEA,0,SSL_IDEA, 0,0,0,0,SSL_ENC_MASK,0},
{0,SSL_TXT_eNULL,0,SSL_eNULL,0,0,0,0,SSL_ENC_MASK,0},
{0,SSL_TXT_eFZA,0,SSL_eFZA, 0,0,0,0,SSL_ENC_MASK,0},
+ {0,SSL_TXT_AES, 0,SSL_AES, 0,0,0,0,SSL_ENC_MASK,0},
{0,SSL_TXT_MD5, 0,SSL_MD5, 0,0,0,0,SSL_MAC_MASK,0},
{0,SSL_TXT_SHA1,0,SSL_SHA1, 0,0,0,0,SSL_MAC_MASK,0},
{0,SSL_TXT_SHA, 0,SSL_SHA, 0,0,0,0,SSL_MAC_MASK,0},
{0,SSL_TXT_NULL,0,SSL_NULL, 0,0,0,0,SSL_ENC_MASK,0},
+ {0,SSL_TXT_KRB5,0,SSL_KRB5, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0},
{0,SSL_TXT_RSA, 0,SSL_RSA, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0},
{0,SSL_TXT_ADH, 0,SSL_ADH, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0},
{0,SSL_TXT_FZA, 0,SSL_FZA, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK,0},
EVP_get_cipherbyname(SN_rc2_cbc);
ssl_cipher_methods[SSL_ENC_IDEA_IDX]=
EVP_get_cipherbyname(SN_idea_cbc);
+ ssl_cipher_methods[SSL_ENC_AES128_IDX]=
+ EVP_get_cipherbyname(SN_aes_128_cbc);
+ ssl_cipher_methods[SSL_ENC_AES256_IDX]=
+ EVP_get_cipherbyname(SN_aes_256_cbc);
ssl_digest_methods[SSL_MD_MD5_IDX]=
EVP_get_digestbyname(SN_md5);
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)
{
{
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);
case SSL_eNULL:
i=SSL_ENC_NULL_IDX;
break;
+ case SSL_AES:
+ switch(c->alg_bits)
+ {
+ case 128: i=SSL_ENC_AES128_IDX; break;
+ case 256: i=SSL_ENC_AES256_IDX; break;
+ default: i=-1; break;
+ }
+ break;
default:
i= -1;
break;
unsigned long mask;
mask = SSL_kFZA;
-#ifdef NO_RSA
+#ifdef OPENSSL_NO_RSA
mask |= SSL_aRSA|SSL_kRSA;
#endif
-#ifdef NO_DSA
+#ifdef OPENSSL_NO_DSA
mask |= SSL_aDSS;
#endif
-#ifdef NO_DH
+#ifdef OPENSSL_NO_DH
mask |= SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH;
#endif
-
+#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
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_cipher_methods[SSL_ENC_AES128_IDX] == NULL) ? SSL_AES:0;
mask |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0;
mask |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0;
list[list_num].prev = NULL;
list[list_num].active = 0;
list_num++;
+#ifdef KSSL_DEBUG
+ printf("\t%d: %s %lx %lx\n",i,c->name,c->id,c->algorithms);
+#endif /* KSSL_DEBUG */
/*
if (!sk_push(ca_list,(char *)c)) goto err;
*/
* 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;
*/
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
* it is used for allocation.
*/
num_of_ciphers = ssl_method->num_ciphers();
+#ifdef KSSL_DEBUG
+ printf("ssl_create_cipher_list() for %d ciphers\n", num_of_ciphers);
+#endif /* KSSL_DEBUG */
list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers);
if (list == NULL)
{
char *ver,*exp;
char *kx,*au,*enc,*mac;
unsigned long alg,alg2,alg_s;
+#ifdef KSSL_DEBUG
+ static char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s AL=%lx\n";
+#else
static char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s\n";
-
+#endif /* KSSL_DEBUG */
+
alg=cipher->algorithms;
alg_s=cipher->algo_strength;
alg2=cipher->algorithm2;
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)
case SSL_kDHd:
kx="DH/DSS";
break;
+ case SSL_kKRB5: /* VRS */
+ case SSL_KRB5: /* VRS */
+ kx="KRB5";
+ break;
case SSL_kFZA:
kx="Fortezza";
break;
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";
}
case SSL_aDH:
au="DH";
break;
+ case SSL_aKRB5: /* VRS */
+ case SSL_KRB5: /* VRS */
+ au="KRB5";
+ break;
case SSL_aFZA:
case SSL_aNULL:
au="None";
break;
+ case SSL_aECDSA:
+ au="ECDSA";
+ break;
default:
au="unknown";
break;
case SSL_eNULL:
enc="None";
break;
+ case SSL_AES:
+ switch(cipher->strength_bits)
+ {
+ case 128: enc="AES(128)"; break;
+ case 192: enc="AES(192)"; break;
+ case 256: enc="AES(256)"; break;
+ default: enc="AES(?""?""?)"; break;
+ }
+ break;
default:
enc="unknown";
break;
else if (len < 128)
return("Buffer too small");
+#ifdef KSSL_DEBUG
+ BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,exp,alg);
+#else
BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,exp);
+#endif /* KSSL_DEBUG */
return(buf);
}
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);