Fix memory leaks in tls_decrypt_ticket
[openssl.git] / ssl / t1_lib.c
index e0e0cb95ac7985ae77d23271ba5be78b773d48da..586048acd4d8708807a183cc99944c26ef418419 100644 (file)
@@ -221,9 +221,16 @@ typedef struct {
     unsigned int flags;         /* Flags: currently just field type */
 } tls_curve_info;
 
     unsigned int flags;         /* Flags: currently just field type */
 } tls_curve_info;
 
+# define TLS_CURVE_TYPE          0x1
 # define TLS_CURVE_CHAR2         0x1
 # define TLS_CURVE_PRIME         0x0
 
 # define TLS_CURVE_CHAR2         0x1
 # define TLS_CURVE_PRIME         0x0
 
+/*
+ * Table of curve information.
+ * NB: do not delete entries or reorder this array. It is used as a lookup
+ * table: the index of each entry is one less than the TLS curve id.
+ */
+
 static const tls_curve_info nid_list[] = {
     {NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */
     {NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */
 static const tls_curve_info nid_list[] = {
     {NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */
     {NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */
@@ -335,67 +342,12 @@ int tls1_ec_curve_id2nid(int curve_id)
 
 int tls1_ec_nid2curve_id(int nid)
 {
 
 int tls1_ec_nid2curve_id(int nid)
 {
-    /* ECC curves from RFC 4492 and RFC 7027 */
-    switch (nid) {
-    case NID_sect163k1:        /* sect163k1 (1) */
-        return 1;
-    case NID_sect163r1:        /* sect163r1 (2) */
-        return 2;
-    case NID_sect163r2:        /* sect163r2 (3) */
-        return 3;
-    case NID_sect193r1:        /* sect193r1 (4) */
-        return 4;
-    case NID_sect193r2:        /* sect193r2 (5) */
-        return 5;
-    case NID_sect233k1:        /* sect233k1 (6) */
-        return 6;
-    case NID_sect233r1:        /* sect233r1 (7) */
-        return 7;
-    case NID_sect239k1:        /* sect239k1 (8) */
-        return 8;
-    case NID_sect283k1:        /* sect283k1 (9) */
-        return 9;
-    case NID_sect283r1:        /* sect283r1 (10) */
-        return 10;
-    case NID_sect409k1:        /* sect409k1 (11) */
-        return 11;
-    case NID_sect409r1:        /* sect409r1 (12) */
-        return 12;
-    case NID_sect571k1:        /* sect571k1 (13) */
-        return 13;
-    case NID_sect571r1:        /* sect571r1 (14) */
-        return 14;
-    case NID_secp160k1:        /* secp160k1 (15) */
-        return 15;
-    case NID_secp160r1:        /* secp160r1 (16) */
-        return 16;
-    case NID_secp160r2:        /* secp160r2 (17) */
-        return 17;
-    case NID_secp192k1:        /* secp192k1 (18) */
-        return 18;
-    case NID_X9_62_prime192v1: /* secp192r1 (19) */
-        return 19;
-    case NID_secp224k1:        /* secp224k1 (20) */
-        return 20;
-    case NID_secp224r1:        /* secp224r1 (21) */
-        return 21;
-    case NID_secp256k1:        /* secp256k1 (22) */
-        return 22;
-    case NID_X9_62_prime256v1: /* secp256r1 (23) */
-        return 23;
-    case NID_secp384r1:        /* secp384r1 (24) */
-        return 24;
-    case NID_secp521r1:        /* secp521r1 (25) */
-        return 25;
-    case NID_brainpoolP256r1:  /* brainpoolP256r1 (26) */
-        return 26;
-    case NID_brainpoolP384r1:  /* brainpoolP384r1 (27) */
-        return 27;
-    case NID_brainpoolP512r1:  /* brainpool512r1 (28) */
-        return 28;
-    default:
-        return 0;
+    size_t i;
+    for (i = 0; i < OSSL_NELEM(nid_list); i++) {
+        if (nid_list[i].nid == nid)
+            return i + 1;
     }
     }
+    return 0;
 }
 
 /*
 }
 
 /*
@@ -666,46 +618,33 @@ int tls1_set_curves_list(unsigned char **pext, size_t *pextlen,
 static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id,
                           EC_KEY *ec)
 {
 static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id,
                           EC_KEY *ec)
 {
-    int is_prime, id;
+    int id;
     const EC_GROUP *grp;
     const EC_GROUP *grp;
-    const EC_METHOD *meth;
     if (!ec)
         return 0;
     /* Determine if it is a prime field */
     grp = EC_KEY_get0_group(ec);
     if (!grp)
         return 0;
     if (!ec)
         return 0;
     /* Determine if it is a prime field */
     grp = EC_KEY_get0_group(ec);
     if (!grp)
         return 0;
-    meth = EC_GROUP_method_of(grp);
-    if (!meth)
-        return 0;
-    if (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field)
-        is_prime = 1;
-    else
-        is_prime = 0;
     /* Determine curve ID */
     id = EC_GROUP_get_curve_name(grp);
     id = tls1_ec_nid2curve_id(id);
     /* Determine curve ID */
     id = EC_GROUP_get_curve_name(grp);
     id = tls1_ec_nid2curve_id(id);
-    /* If we have an ID set it, otherwise set arbitrary explicit curve */
-    if (id) {
-        curve_id[0] = 0;
-        curve_id[1] = (unsigned char)id;
-    } else {
-        curve_id[0] = 0xff;
-        if (is_prime)
-            curve_id[1] = 0x01;
-        else
-            curve_id[1] = 0x02;
-    }
+    /* If no id return error: we don't support arbitrary explicit curves */
+    if (id == 0)
+        return 0;
+    curve_id[0] = 0;
+    curve_id[1] = (unsigned char)id;
     if (comp_id) {
         if (EC_KEY_get0_public_key(ec) == NULL)
             return 0;
     if (comp_id) {
         if (EC_KEY_get0_public_key(ec) == NULL)
             return 0;
-        if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) {
-            if (is_prime)
+        if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) {
+            *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
+        } else {
+            if ((nid_list[id - 1].flags & TLS_CURVE_TYPE) == TLS_CURVE_PRIME)
                 *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
             else
                 *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
                 *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
             else
                 *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
-        } else
-            *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
+        }
     }
     return 1;
 }
     }
     return 1;
 }
@@ -1072,14 +1011,6 @@ void ssl_set_client_disabled(SSL *s)
     if (s->client_version == SSL3_VERSION)
         s->s3->tmp.mask_ssl |= SSL_TLSV1;
     ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
     if (s->client_version == SSL3_VERSION)
         s->s3->tmp.mask_ssl |= SSL_TLSV1;
     ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK);
-    /*
-     * Disable static DH if we don't include any appropriate signature
-     * algorithms.
-     */
-    if (s->s3->tmp.mask_a & SSL_aRSA)
-        s->s3->tmp.mask_k |= SSL_kECDHr;
-    if (s->s3->tmp.mask_a & SSL_aECDSA)
-        s->s3->tmp.mask_k |= SSL_kECDHe;
 # ifndef OPENSSL_NO_PSK
     /* with PSK there must be client callback set */
     if (!s->psk_client_callback) {
 # ifndef OPENSSL_NO_PSK
     /* with PSK there must be client callback set */
     if (!s->psk_client_callback) {
@@ -1130,8 +1061,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
 
             alg_k = c->algorithm_mkey;
             alg_a = c->algorithm_auth;
 
             alg_k = c->algorithm_mkey;
             alg_a = c->algorithm_auth;
-            if ((alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)
-                 || (alg_a & SSL_aECDSA))) {
+            if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
+                 || (alg_a & SSL_aECDSA)) {
                 using_ecc = 1;
                 break;
             }
                 using_ecc = 1;
                 break;
             }
@@ -1507,8 +1438,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
 #ifndef OPENSSL_NO_EC
     unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
     unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
 #ifndef OPENSSL_NO_EC
     unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
     unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-    int using_ecc = (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe))
-        || (alg_a & SSL_aECDSA);
+    int using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA);
     using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
 #endif
 
     using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
 #endif
 
@@ -2815,8 +2745,7 @@ int ssl_check_serverhello_tlsext(SSL *s)
         && (s->tlsext_ecpointformatlist_length > 0)
         && (s->session->tlsext_ecpointformatlist != NULL)
         && (s->session->tlsext_ecpointformatlist_length > 0)
         && (s->tlsext_ecpointformatlist_length > 0)
         && (s->session->tlsext_ecpointformatlist != NULL)
         && (s->session->tlsext_ecpointformatlist_length > 0)
-        && ((alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe))
-            || (alg_a & SSL_aECDSA))) {
+        && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) {
         /* we are using an ECC cipher */
         size_t i;
         unsigned char *list;
         /* we are using an ECC cipher */
         size_t i;
         unsigned char *list;
@@ -3058,7 +2987,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
     SSL_SESSION *sess;
     unsigned char *sdec;
     const unsigned char *p;
     SSL_SESSION *sess;
     unsigned char *sdec;
     const unsigned char *p;
-    int slen, mlen, renew_ticket = 0;
+    int slen, mlen, renew_ticket = 0, ret = -1;
     unsigned char tick_hmac[EVP_MAX_MD_SIZE];
     HMAC_CTX *hctx = NULL;
     EVP_CIPHER_CTX *ctx;
     unsigned char tick_hmac[EVP_MAX_MD_SIZE];
     HMAC_CTX *hctx = NULL;
     EVP_CIPHER_CTX *ctx;
@@ -3071,20 +3000,28 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
     if (hctx == NULL)
         return -2;
     ctx = EVP_CIPHER_CTX_new();
     if (hctx == NULL)
         return -2;
     ctx = EVP_CIPHER_CTX_new();
+    if (ctx == NULL) {
+        ret = -2;
+        goto err;
+    }
     if (tctx->tlsext_ticket_key_cb) {
         unsigned char *nctick = (unsigned char *)etick;
         int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
                                             ctx, hctx, 0);
         if (rv < 0)
     if (tctx->tlsext_ticket_key_cb) {
         unsigned char *nctick = (unsigned char *)etick;
         int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
                                             ctx, hctx, 0);
         if (rv < 0)
-            return -1;
-        if (rv == 0)
-            return 2;
+            goto err;
+        if (rv == 0) {
+            ret = 2;
+            goto err;
+        }
         if (rv == 2)
             renew_ticket = 1;
     } else {
         /* Check key name matches */
         if (rv == 2)
             renew_ticket = 1;
     } else {
         /* Check key name matches */
-        if (memcmp(etick, tctx->tlsext_tick_key_name, 16))
-            return 2;
+        if (memcmp(etick, tctx->tlsext_tick_key_name, 16)) {
+            ret = 2;
+            goto err;
+        }
         if (HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, 16,
                          EVP_sha256(), NULL) <= 0
                 || EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL,
         if (HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, 16,
                          EVP_sha256(), NULL) <= 0
                 || EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL,
@@ -3158,7 +3095,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
 err:
     EVP_CIPHER_CTX_free(ctx);
     HMAC_CTX_free(hctx);
 err:
     EVP_CIPHER_CTX_free(ctx);
     HMAC_CTX_free(hctx);
-    return -1;
+    return ret;
 }
 
 /* Tables to translate from NIDs to TLS v1.2 ids */
 }
 
 /* Tables to translate from NIDs to TLS v1.2 ids */
@@ -4122,6 +4059,9 @@ static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
 {
     /* Lookup signature algorithm digest */
     int secbits = -1, md_nid = NID_undef, sig_nid;
 {
     /* Lookup signature algorithm digest */
     int secbits = -1, md_nid = NID_undef, sig_nid;
+    /* Don't check signature if self signed */
+    if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0)
+        return 1;
     sig_nid = X509_get_signature_nid(x);
     if (sig_nid && OBJ_find_sigid_algs(sig_nid, &md_nid, NULL)) {
         const EVP_MD *md;
     sig_nid = X509_get_signature_nid(x);
     if (sig_nid && OBJ_find_sigid_algs(sig_nid, &md_nid, NULL)) {
         const EVP_MD *md;