From: Nikos Mavrogiannopoulos Date: Tue, 8 Feb 2011 17:53:54 +0000 (+0100) Subject: Several updates in signature algorithms parsing and sending to avoid sending invalid... X-Git-Tag: gnutls_2_99_0~294 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ea683ee362fb13fa7515a2cd5f9c31c99c0366a4;p=thirdparty%2Fgnutls.git Several updates in signature algorithms parsing and sending to avoid sending invalid signature algorithms. --- diff --git a/lib/auth_cert.c b/lib/auth_cert.c index 760db40566..033d3d7085 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -1532,7 +1532,7 @@ _gnutls_gen_cert_client_cert_vrfy (gnutls_session_t session, opaque ** data) gnutls_cert *apr_cert_list; gnutls_privkey_t apr_pkey; int apr_cert_list_length, size; - gnutls_datum_t signature; + gnutls_datum_t signature = { NULL, 0 }; int total_data; opaque *p; gnutls_sign_algorithm_t sign_algo; @@ -1584,11 +1584,17 @@ _gnutls_gen_cert_client_cert_vrfy (gnutls_session_t session, opaque ** data) p = *data; if (_gnutls_version_has_selectable_sighash (ver)) { - sign_algorithm_st aid; + const sign_algorithm_st *aid; /* error checking is not needed here since we have used those algorithms */ aid = _gnutls_sign_to_tls_aid (sign_algo); - p[0] = aid.hash_algorithm; - p[1] = aid.sign_algorithm; + if (aid == NULL) + { + ret = GNUTLS_E_UNKNOWN_ALGORITHM; + goto cleanup; + } + + p[0] = aid->hash_algorithm; + p[1] = aid->sign_algorithm; p += 2; } @@ -1601,6 +1607,11 @@ _gnutls_gen_cert_client_cert_vrfy (gnutls_session_t session, opaque ** data) _gnutls_free_datum (&signature); return total_data; + +cleanup: + _gnutls_free_datum (&signature); + gnutls_free(*data); + return ret; } int diff --git a/lib/auth_dhe.c b/lib/auth_dhe.c index 82a8df6569..87de68489c 100644 --- a/lib/auth_dhe.c +++ b/lib/auth_dhe.c @@ -89,7 +89,7 @@ gen_dhe_server_kx (gnutls_session_t session, opaque ** data) gnutls_cert *apr_cert_list; gnutls_privkey_t apr_pkey; int apr_cert_list_length; - gnutls_datum_t signature, ddata; + gnutls_datum_t signature = { NULL, 0 }, ddata; gnutls_certificate_credentials_t cred; gnutls_dh_params_t dh_params; gnutls_sign_algorithm_t sign_algo; @@ -154,38 +154,44 @@ gen_dhe_server_kx (gnutls_session_t session, opaque ** data) &sign_algo)) < 0) { gnutls_assert (); - gnutls_free (*data); - return ret; + goto cleanup; } } else { gnutls_assert (); - return data_size; /* do not put a signature - ILLEGAL! */ + ret = data_size; /* do not put a signature - ILLEGAL! */ + goto cleanup; } *data = gnutls_realloc_fast (*data, data_size + signature.size + 4); if (*data == NULL) { - _gnutls_free_datum (&signature); gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; } if (_gnutls_version_has_selectable_sighash (ver)) { - sign_algorithm_st aid; + const sign_algorithm_st *aid; if (sign_algo == GNUTLS_SIGN_UNKNOWN) { - _gnutls_free_datum (&signature); - gnutls_assert (); - return GNUTLS_E_UNKNOWN_PK_ALGORITHM; + ret = GNUTLS_E_UNKNOWN_ALGORITHM; + goto cleanup; } aid = _gnutls_sign_to_tls_aid (sign_algo); - (*data)[data_size++] = aid.hash_algorithm; - (*data)[data_size++] = aid.sign_algorithm; + if (aid == NULL) + { + gnutls_assert(); + ret = GNUTLS_E_UNKNOWN_ALGORITHM; + goto cleanup; + } + + (*data)[data_size++] = aid->hash_algorithm; + (*data)[data_size++] = aid->sign_algorithm; } _gnutls_write_datum16 (&(*data)[data_size], signature); @@ -194,6 +200,12 @@ gen_dhe_server_kx (gnutls_session_t session, opaque ** data) _gnutls_free_datum (&signature); return data_size; + +cleanup: + _gnutls_free_datum (&signature); + gnutls_free(*data); + return ret; + } static int diff --git a/lib/ext_signature.c b/lib/ext_signature.c index 6eebd39d6a..af6328b758 100644 --- a/lib/ext_signature.c +++ b/lib/ext_signature.c @@ -72,31 +72,41 @@ int _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data, size_t max_data_size) { - opaque *p = data; + opaque *p = data, *len_p; int len, i, j; - sign_algorithm_st aid; + const sign_algorithm_st *aid; - len = session->internals.priorities.sign_algo.algorithms * 2; - if (max_data_size < len + 2) + if (max_data_size < (session->internals.priorities.sign_algo.algorithms*2) + 2) { gnutls_assert (); return GNUTLS_E_SHORT_MEMORY_BUFFER; } - _gnutls_write_uint16 (len, p); + len = 0; + len_p = p; + p += 2; - for (i = j = 0; i < len; i += 2, j++) + for (i = j = 0; i < session->internals.priorities.sign_algo.algorithms; i += 2, j++) { aid = _gnutls_sign_to_tls_aid (session->internals.priorities. sign_algo.priority[j]); - *p = aid.hash_algorithm; + + if (aid == NULL) + continue; + + _gnutls_debug_log ("EXT[SIGA]: sent signature algo (%d.%d) %s\n", aid->hash_algorithm, + aid->sign_algorithm, gnutls_sign_get_name(session->internals.priorities.sign_algo.priority[j])); + *p = aid->hash_algorithm; p++; - *p = aid.sign_algorithm; + *p = aid->sign_algorithm; p++; - + len+=2; } + + _gnutls_write_uint16 (len, len_p); + return len + 2; } @@ -127,6 +137,10 @@ _gnutls_sign_algorithm_parse_data (gnutls_session_t session, aid.sign_algorithm = data[i + 1]; sig = _gnutls_tls_aid_to_sign (&aid); + + _gnutls_debug_log ("EXT[SIGA]: rcvd signature algo (%d.%d) %s\n", aid.hash_algorithm, + aid.sign_algorithm, gnutls_sign_get_name(sig)); + if (sig != GNUTLS_SIGN_UNKNOWN) { priv->sign_algorithms[priv->sign_algorithms_size++] = sig; diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index 027bf5d99c..cf9a314390 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -1941,11 +1941,12 @@ struct gnutls_sign_entry gnutls_mac_algorithm_t mac; /* See RFC 5246 HashAlgorithm and SignatureAlgorithm for values to use in aid struct. */ - sign_algorithm_st aid; + const sign_algorithm_st aid; }; typedef struct gnutls_sign_entry gnutls_sign_entry; #define TLS_SIGN_AID_UNKNOWN {255, 255} +static const sign_algorithm_st unknown_tls_aid = TLS_SIGN_AID_UNKNOWN; static const gnutls_sign_entry sign_algorithms[] = { {"RSA-SHA1", SIG_RSA_SHA1_OID, GNUTLS_SIGN_RSA_SHA1, GNUTLS_PK_RSA, @@ -2147,21 +2148,31 @@ _gnutls_tls_aid_to_sign (const sign_algorithm_st * aid) { gnutls_sign_algorithm_t ret = GNUTLS_SIGN_UNKNOWN; + if (memcmp(aid, &unknown_tls_aid, sizeof(aid))==0) + return ret; + GNUTLS_SIGN_LOOP (if (p->aid.hash_algorithm == aid->hash_algorithm && p->aid.sign_algorithm == aid->sign_algorithm) { - ret = p->id; break;} + ret = p->id; break; + } ); + return ret; } -sign_algorithm_st +/* Returns NULL if a valid AID is not found + */ +const sign_algorithm_st* _gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign) { - sign_algorithm_st ret = TLS_SIGN_AID_UNKNOWN; + const sign_algorithm_st * ret = NULL; + + GNUTLS_SIGN_ALG_LOOP (ret = &p->aid); - GNUTLS_SIGN_ALG_LOOP (ret = p->aid); + if (ret != NULL && memcmp(ret, &unknown_tls_aid, sizeof(*ret))==0) + return NULL; return ret; } diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h index 50504f360a..4e6b5402bb 100644 --- a/lib/gnutls_algorithms.h +++ b/lib/gnutls_algorithms.h @@ -114,7 +114,7 @@ const char *_gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t, gnutls_mac_algorithm_t mac); gnutls_sign_algorithm_t _gnutls_tls_aid_to_sign (const sign_algorithm_st * aid); -sign_algorithm_st _gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign); +const sign_algorithm_st* _gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign); gnutls_mac_algorithm_t _gnutls_sign_get_hash_algorithm (gnutls_sign_algorithm_t); gnutls_pk_algorithm_t _gnutls_sign_get_pk_algorithm (gnutls_sign_algorithm_t);