int _gnutls_recv_server_certificate_request (gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; if (session->internals. auth_struct->gnutls_process_server_certificate_request != NULL) { ret = _gnutls_recv_handshake (session, GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST, OPTIONAL_PACKET, &buf); if (ret < 0) return ret; if (ret == 0 && buf.length == 0) { _gnutls_buffer_clear(&buf); return 0; /* ignored */ } ret = session->internals. auth_struct->gnutls_process_server_certificate_request (session, buf.data, buf.length); _gnutls_buffer_clear (&buf); if (ret < 0) return ret; } return ret; }
/** * gnutls_deinit: * @session: is a #gnutls_session_t structure. * * This function clears all buffers associated with the @session. * This function will also remove session data from the session * database if the session was terminated abnormally. **/ void gnutls_deinit (gnutls_session_t session) { unsigned int i; if (session == NULL) return; _gnutls_rnd_refresh(); /* remove auth info firstly */ _gnutls_free_auth_info (session); _gnutls_handshake_internal_state_clear (session); _gnutls_handshake_io_buffer_clear (session); _gnutls_ext_free_session_data (session); for (i = 0; i < MAX_EPOCH_INDEX; i++) if (session->record_parameters[i] != NULL) { _gnutls_epoch_free (session, session->record_parameters[i]); session->record_parameters[i] = NULL; } _gnutls_buffer_clear (&session->internals.handshake_hash_buffer); _gnutls_buffer_clear (&session->internals.hb_remote_data); _gnutls_buffer_clear (&session->internals.hb_local_data); _gnutls_buffer_clear (&session->internals.record_presend_buffer); _mbuffer_head_clear (&session->internals.record_buffer); _mbuffer_head_clear (&session->internals.record_recv_buffer); _mbuffer_head_clear (&session->internals.record_send_buffer); gnutls_credentials_clear (session); _gnutls_selected_certs_deinit (session); gnutls_pk_params_release(&session->key.ecdh_params); _gnutls_mpi_release (&session->key.ecdh_x); _gnutls_mpi_release (&session->key.ecdh_y); _gnutls_mpi_release (&session->key.KEY); _gnutls_mpi_release (&session->key.client_Y); _gnutls_mpi_release (&session->key.client_p); _gnutls_mpi_release (&session->key.client_g); _gnutls_mpi_release (&session->key.u); _gnutls_mpi_release (&session->key.a); _gnutls_mpi_release (&session->key.x); _gnutls_mpi_release (&session->key.A); _gnutls_mpi_release (&session->key.B); _gnutls_mpi_release (&session->key.b); /* RSA */ _gnutls_mpi_release (&session->key.rsa[0]); _gnutls_mpi_release (&session->key.rsa[1]); _gnutls_mpi_release (&session->key.dh_secret); gnutls_free (session); }
int _gnutls_recv_server_kx_message(gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; unsigned int optflag = 0; if (session->internals.auth_struct->gnutls_process_server_kx != NULL) { /* Server key exchange packet is optional for PSK. */ if (_gnutls_session_is_psk(session)) optflag = 1; ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE, optflag, &buf); if (ret < 0) { gnutls_assert(); return ret; } ret = session->internals.auth_struct-> gnutls_process_server_kx(session, buf.data, buf.length); _gnutls_buffer_clear(&buf); if (ret < 0) { gnutls_assert(); return ret; } } return ret; }
/* This is called when we want send our certificate */ int _gnutls_send_server_certificate(gnutls_session_t session, int again) { gnutls_buffer_st data; int ret = 0; if (session->internals.auth_struct-> gnutls_generate_server_certificate == NULL) return 0; _gnutls_buffer_init(&data); if (again == 0) { ret = session->internals.auth_struct-> gnutls_generate_server_certificate(session, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = send_handshake(session, data.data, data.length, GNUTLS_HANDSHAKE_CERTIFICATE_PKT); if (ret < 0) { gnutls_assert(); } cleanup: _gnutls_buffer_clear(&data); return ret; }
/* This is the function for the client to send the key * exchange message */ int _gnutls_send_client_kx_message (gnutls_session_t session, int again) { gnutls_buffer_st data; int ret = 0; if (session->internals.auth_struct->gnutls_generate_client_kx == NULL) return 0; _gnutls_buffer_init( &data); if (again == 0) { ret = session->internals.auth_struct->gnutls_generate_client_kx (session, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = send_handshake (session, data.data, data.length, GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE); if (ret < 0) { gnutls_assert (); } cleanup: _gnutls_buffer_clear (&data); return ret; }
int _gnutls_recv_client_kx_message (gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; /* Do key exchange only if the algorithm permits it */ if (session->internals.auth_struct->gnutls_process_client_kx != NULL) { ret = _gnutls_recv_handshake (session, GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE, MANDATORY_PACKET, &buf); if (ret < 0) return ret; ret = session->internals.auth_struct->gnutls_process_client_kx (session, buf.data, buf.length); _gnutls_buffer_clear (&buf); if (ret < 0) return ret; } return ret; }
int _gnutls_recv_server_certificate (gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; if (session->internals.auth_struct->gnutls_process_server_certificate != NULL) { ret = _gnutls_recv_handshake (session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, MANDATORY_PACKET, &buf); if (ret < 0) { gnutls_assert (); return ret; } ret = session->internals. auth_struct->gnutls_process_server_certificate (session, buf.data, buf.length); _gnutls_buffer_clear(&buf); if (ret < 0) { gnutls_assert (); return ret; } } return ret; }
/* converts the buffer to a datum if possible. After this call the buffer * is at an usable state and might not be used or deinitialized */ int _gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data) { if (str->length == 0) { data->data = NULL; data->size = 0; return 0; } if (str->allocd != str->data) { data->data = gnutls_malloc (str->length); if (data->data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } memcpy (data->data, str->data, str->length); data->size = str->length; _gnutls_buffer_clear (str); } else { data->data = str->data; data->size = str->length; } return 0; }
/* This is called when we want send our certificate */ int _gnutls_send_client_certificate (gnutls_session_t session, int again) { gnutls_buffer_st data; int ret = 0; if (session->key->certificate_requested == 0) return 0; if (session->internals.auth_struct->gnutls_generate_client_certificate == NULL) return 0; _gnutls_buffer_init( &data); if (again == 0) { if (gnutls_protocol_get_version (session) != GNUTLS_SSL3 || session->internals.selected_cert_list_length > 0) { /* TLS 1.0 or SSL 3.0 with a valid certificate */ ret = session->internals. auth_struct->gnutls_generate_client_certificate (session, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } } } /* In the SSL 3.0 protocol we need to send a * no certificate alert instead of an * empty certificate. */ if (gnutls_protocol_get_version (session) == GNUTLS_SSL3 && session->internals.selected_cert_list_length == 0) { ret = gnutls_alert_send (session, GNUTLS_AL_WARNING, GNUTLS_A_SSL3_NO_CERTIFICATE); } else { /* TLS 1.0 or SSL 3.0 with a valid certificate */ ret = send_handshake (session, data.data, data.length, GNUTLS_HANDSHAKE_CERTIFICATE_PKT); } cleanup: _gnutls_buffer_clear (&data); return ret; }
/** * gnutls_deinit: * @session: is a #gnutls_session_t structure. * * This function clears all buffers associated with the @session. * This function will also remove session data from the session * database if the session was terminated abnormally. **/ void gnutls_deinit (gnutls_session_t session) { unsigned int i; if (session == NULL) return; /* remove auth info firstly */ _gnutls_free_auth_info (session); _gnutls_handshake_internal_state_clear (session); _gnutls_handshake_io_buffer_clear (session); _gnutls_ext_free_session_data (session); for (i = 0; i < MAX_EPOCH_INDEX; i++) if (session->record_parameters[i] != NULL) { _gnutls_epoch_free (session, session->record_parameters[i]); session->record_parameters[i] = NULL; } _gnutls_buffer_clear (&session->internals.handshake_hash_buffer); _mbuffer_head_clear (&session->internals.record_buffer); _mbuffer_head_clear (&session->internals.record_recv_buffer); _mbuffer_head_clear (&session->internals.record_send_buffer); gnutls_credentials_clear (session); _gnutls_selected_certs_deinit (session); if (session->key != NULL) { _gnutls_mpi_release (&session->key->KEY); _gnutls_mpi_release (&session->key->client_Y); _gnutls_mpi_release (&session->key->client_p); _gnutls_mpi_release (&session->key->client_g); _gnutls_mpi_release (&session->key->u); _gnutls_mpi_release (&session->key->a); _gnutls_mpi_release (&session->key->x); _gnutls_mpi_release (&session->key->A); _gnutls_mpi_release (&session->key->B); _gnutls_mpi_release (&session->key->b); /* RSA */ _gnutls_mpi_release (&session->key->rsa[0]); _gnutls_mpi_release (&session->key->rsa[1]); _gnutls_mpi_release (&session->key->dh_secret); gnutls_free (session->key); session->key = NULL; } memset (session, 0, sizeof (struct gnutls_session_int)); gnutls_free (session); }
int _gnutls_handshake_buffer_clear (gnutls_session_t session) { _gnutls_buffers_log ("BUF[HSK]: Cleared Data from buffer\n"); _gnutls_buffer_clear (&session->internals.handshake_hash_buffer); return 0; }
/* This is the function for the client to send the certificate * verify message */ int _gnutls_send_client_certificate_verify (gnutls_session_t session, int again) { gnutls_buffer_st data; int ret = 0; /* This is a packet that is only sent by the client */ if (session->security_parameters.entity == GNUTLS_SERVER) return 0; /* if certificate verify is not needed just exit */ if (session->key->certificate_requested == 0) return 0; if (session->internals.auth_struct->gnutls_generate_client_cert_vrfy == NULL) { gnutls_assert (); return 0; /* this algorithm does not support cli_cert_vrfy */ } _gnutls_buffer_init( &data); if (again == 0) { ret = session->internals. auth_struct->gnutls_generate_client_cert_vrfy (session, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } if (ret == 0) goto cleanup; } ret = send_handshake (session, data.data, data.length, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY); if (ret < 0) { gnutls_assert (); } cleanup: _gnutls_buffer_clear (&data); return ret; }
/** * gnutls_deinit: * @session: is a #gnutls_session_t type. * * This function clears all buffers associated with the @session. * This function will also remove session data from the session * database if the session was terminated abnormally. **/ void gnutls_deinit(gnutls_session_t session) { unsigned int i; if (session == NULL) return; /* remove auth info firstly */ _gnutls_free_auth_info(session); _gnutls_handshake_internal_state_clear(session); _gnutls_handshake_io_buffer_clear(session); _gnutls_ext_free_session_data(session); for (i = 0; i < MAX_EPOCH_INDEX; i++) if (session->record_parameters[i] != NULL) { _gnutls_epoch_free(session, session->record_parameters[i]); session->record_parameters[i] = NULL; } _gnutls_buffer_clear(&session->internals.handshake_hash_buffer); _gnutls_buffer_clear(&session->internals.hb_remote_data); _gnutls_buffer_clear(&session->internals.hb_local_data); _gnutls_buffer_clear(&session->internals.record_presend_buffer); _mbuffer_head_clear(&session->internals.record_buffer); _mbuffer_head_clear(&session->internals.record_recv_buffer); _mbuffer_head_clear(&session->internals.record_send_buffer); _gnutls_free_datum(&session->internals.resumption_data); gnutls_free(session->internals.rexts); gnutls_free(session->internals.rsup); gnutls_credentials_clear(session); _gnutls_selected_certs_deinit(session); gnutls_free(session); }
int _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_datum_t * dn, unsigned flags) { gnutls_buffer_st out_str; int i, k1, result; _gnutls_buffer_init(&out_str); result = asn1_number_of_elements(asn1_struct, asn1_rdn_name, &k1); if (result != ASN1_SUCCESS) { if (result == ASN1_ELEMENT_NOT_FOUND || result == ASN1_VALUE_NOT_FOUND) { result = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); } else { gnutls_assert(); result = _gnutls_asn2err(result); } goto cleanup; } if (k1 == 0) { gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto cleanup; } if (flags & GNUTLS_X509_DN_FLAG_COMPAT) { for (i=0;i<k1;i++) { result = append_elements(asn1_struct, asn1_rdn_name, &out_str, i+1, (i==(k1-1))?1:0); if (result < 0) { gnutls_assert(); goto cleanup; } } } else { while (k1 > 0) { result = append_elements(asn1_struct, asn1_rdn_name, &out_str, k1, k1==1?1:0); if (result < 0) { gnutls_assert(); goto cleanup; } k1--; } } return _gnutls_buffer_to_datum(&out_str, dn, 1); cleanup: _gnutls_buffer_clear(&out_str); return result; }
int _gnutls_recv_server_kx_message (gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; optional_t optflag = MANDATORY_PACKET; if (session->internals.auth_struct->gnutls_process_server_kx != NULL) { /* EXCEPTION FOR RSA_EXPORT cipher suite */ if (_gnutls_session_is_export (session) != 0 && _gnutls_peers_cert_less_512 (session) != 0) { gnutls_assert (); return 0; } /* Server key exchange packet is optional for PSK. */ if (_gnutls_session_is_psk (session)) optflag = OPTIONAL_PACKET; ret = _gnutls_recv_handshake (session, GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE, optflag, &buf); if (ret < 0) { gnutls_assert (); return ret; } ret = session->internals.auth_struct->gnutls_process_server_kx (session, buf.data, buf.length); _gnutls_buffer_clear(&buf); if (ret < 0) { gnutls_assert (); return ret; } } return ret; }
int _gnutls_krb5_der_to_principal(const gnutls_datum_t * der, gnutls_datum_t * name) { int ret, result; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; gnutls_buffer_st str; _gnutls_buffer_init(&str); result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.KRB5PrincipalName", &c2); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } result = asn1_der_decoding(&c2, der->data, der->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } ret = principal_to_str(c2, &str); if (ret < 0) { /* for some reason we cannot convert to a human readable string * the principal. Then we use the #HEX format. */ _gnutls_buffer_reset(&str); ret = _gnutls_buffer_append_data(&str, "#", 1); if (ret < 0) { gnutls_assert(); goto cleanup; } _gnutls_buffer_hexprint(&str, der->data, der->size); } asn1_delete_structure(&c2); return _gnutls_buffer_to_datum(&str, name, 1); cleanup: _gnutls_buffer_clear(&str); asn1_delete_structure(&c2); return ret; }
static int unescape_string(char *output, const char *input, size_t * size, char terminator) { gnutls_buffer_st str; int ret = 0; char *p; int len; _gnutls_buffer_init(&str); /* find terminator */ p = strchr(input, terminator); if (p != NULL) len = p - input; else len = strlen(input); ret = _gnutls_buffer_append_data(&str, input, len); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_buffer_unescape(&str); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_buffer_append_data(&str, "", 1); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_buffer_pop_data(&str, output, str.length); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_buffer_clear(&str); return ret; }
/* Recv the client certificate verify. This packet may not * arrive if the peer did not send us a certificate. */ int _gnutls_recv_client_certificate_verify_message (gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; if (session->internals.auth_struct->gnutls_process_client_cert_vrfy == NULL) return 0; if (session->internals.send_cert_req == 0 || session->key->certificate_requested == 0) { return 0; } ret = _gnutls_recv_handshake (session, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY, OPTIONAL_PACKET, &buf); if (ret < 0) return ret; if (ret == 0 && buf.length == 0 && session->internals.send_cert_req == GNUTLS_CERT_REQUIRE) { /* certificate was required */ gnutls_assert (); ret = GNUTLS_E_NO_CERTIFICATE_FOUND; goto cleanup; } ret = session->internals. auth_struct->gnutls_process_client_cert_vrfy (session, buf.data, buf.length); cleanup: _gnutls_buffer_clear(&buf); return ret; }
/* * Return zero if session tickets haven't been enabled. */ int _gnutls_recv_new_session_ticket(gnutls_session_t session) { uint8_t *p; int data_size; gnutls_buffer_st buf; uint16_t ticket_len; int ret; session_ticket_ext_st *priv = NULL; gnutls_ext_priv_data_t epriv; if (session->internals.flags & GNUTLS_NO_TICKETS) return 0; if (!session->internals.session_ticket_renew) return 0; /* This is the last flight and peer cannot be sure * we have received it unless we notify him. So we * wait for a message and retransmit if needed. */ if (IS_DTLS(session) && !_dtls_is_async(session)) { unsigned have; mbuffer_st *bufel = NULL; have = gnutls_record_check_pending(session) + record_check_unprocessed(session); if (have != 0) { bufel = _mbuffer_head_get_first(&session->internals.record_buffer, NULL); } if (have == 0 || (bufel && bufel->type != GNUTLS_HANDSHAKE)) { ret = _dtls_wait_and_retransmit(session); if (ret < 0) return gnutls_assert_val(ret); } } ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, 0, &buf); if (ret < 0) return gnutls_assert_val_fatal(ret); p = buf.data; data_size = buf.length; DECR_LENGTH_COM(data_size, 4, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); /* skip over lifetime hint */ p += 4; DECR_LENGTH_COM(data_size, 2, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); ticket_len = _gnutls_read_uint16(p); p += 2; DECR_LENGTH_COM(data_size, ticket_len, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); priv = gnutls_calloc(1, sizeof(*priv)); if (!priv) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto error; } priv->session_ticket = gnutls_realloc_fast(priv->session_ticket, ticket_len); if (!priv->session_ticket) { gnutls_free(priv); gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto error; } memcpy(priv->session_ticket, p, ticket_len); priv->session_ticket_len = ticket_len; epriv = priv; /* Discard the current session ID. (RFC5077 3.4) */ ret = _gnutls_generate_session_id(session->security_parameters. session_id, &session->security_parameters. session_id_size); if (ret < 0) { gnutls_assert(); session_ticket_deinit_data(epriv); ret = GNUTLS_E_INTERNAL_ERROR; goto error; } ret = 0; _gnutls_handshake_log ("HSK[%p]: received session ticket\n", session); session->internals.hsk_flags |= HSK_TICKET_RECEIVED; _gnutls_hello_ext_set_priv(session, GNUTLS_EXTENSION_SESSION_TICKET, epriv); error: _gnutls_buffer_clear(&buf); return ret; }
int _gnutls_recv_client_certificate (gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; int optional; if (session->internals.auth_struct->gnutls_process_client_certificate == NULL) return 0; /* if we have not requested a certificate then just return */ if (session->internals.send_cert_req == 0) { return 0; } if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE) optional = MANDATORY_PACKET; else optional = OPTIONAL_PACKET; ret = _gnutls_recv_handshake (session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, optional, &buf); if (ret < 0) { /* Handle the case of old SSL3 clients who send * a warning alert instead of an empty certificate to indicate * no certificate. */ if (optional == OPTIONAL_PACKET && ret == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_protocol_get_version (session) == GNUTLS_SSL3 && gnutls_alert_get (session) == GNUTLS_A_SSL3_NO_CERTIFICATE) { /* SSL3 does not send an empty certificate, * but this alert. So we just ignore it. */ gnutls_assert (); return 0; } /* certificate was required */ if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) && optional == MANDATORY_PACKET) { gnutls_assert (); return GNUTLS_E_NO_CERTIFICATE_FOUND; } return ret; } if (ret == 0 && buf.length == 0 && optional == OPTIONAL_PACKET) { /* Client has not sent the certificate message. * well I'm not sure we should accept this * behaviour. */ gnutls_assert (); ret = 0; goto cleanup; } ret = session->internals. auth_struct->gnutls_process_client_certificate (session, buf.data, buf.length); if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND) { gnutls_assert (); goto cleanup; } /* ok we should expect a certificate verify message now */ if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional == OPTIONAL_PACKET) ret = 0; else session->key->certificate_requested = 1; cleanup: _gnutls_buffer_clear(&buf); return ret; }
int _gnutls_recv_server_certificate_status(gnutls_session_t session) { uint8_t *data; int data_size; size_t r_size; gnutls_buffer_st buf; int ret; status_request_ext_st *priv = NULL; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_STATUS_REQUEST, &epriv); if (ret < 0) return 0; priv = epriv.ptr; if (!priv->expect_cstatus) return 0; ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_CERTIFICATE_STATUS, 0, &buf); if (ret < 0) return gnutls_assert_val_fatal(ret); priv->expect_cstatus = 0; data = buf.data; data_size = buf.length; /* minimum message is type (1) + response (3) + data */ if (data_size == 0) return 0; else if (data_size < 4) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); if (data[0] != 0x01) { gnutls_assert(); _gnutls_handshake_log("EXT[%p]: unknown status_type %d\n", session, data[0]); return 0; } DECR_LENGTH_COM(data_size, 1, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); data++; DECR_LENGTH_COM(data_size, 3, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); r_size = _gnutls_read_uint24(data); data += 3; DECR_LENGTH_COM(data_size, r_size, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); ret = _gnutls_set_datum(&priv->response, data, r_size); if (ret < 0) goto error; ret = 0; error: _gnutls_buffer_clear(&buf); return ret; }
/* Since auth_info structures contain malloced data, this function * is required in order to pack these structures in a vector in * order to store them to the DB. * * packed_session will contain the session data. * * The data will be in a platform independent format. */ int _gnutls_session_pack (gnutls_session_t session, gnutls_datum_t * packed_session) { int ret; gnutls_buffer_st sb; opaque id; if (packed_session == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } _gnutls_buffer_init (&sb); id = gnutls_auth_get_type (session); BUFFER_APPEND (&sb, &id, 1); switch (id) { #ifdef ENABLE_SRP case GNUTLS_CRD_SRP: ret = pack_srp_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); return ret; } break; #endif #ifdef ENABLE_PSK case GNUTLS_CRD_PSK: ret = pack_psk_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); return ret; } break; #endif #ifdef ENABLE_ANON case GNUTLS_CRD_ANON: ret = pack_anon_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); return ret; } break; #endif case GNUTLS_CRD_CERTIFICATE: ret = pack_certificate_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); return ret; } break; default: return GNUTLS_E_INTERNAL_ERROR; } /* Auth_info structures copied. Now copy security_parameters_st. * packed_session must have allocated space for the security parameters. */ ret = pack_security_parameters (session, &sb); if (ret < 0) { gnutls_assert (); _gnutls_buffer_clear (&sb); return ret; } ret = _gnutls_ext_pack (session, &sb); if (ret < 0) { gnutls_assert (); _gnutls_buffer_clear (&sb); return ret; } ret = _gnutls_buffer_to_datum (&sb, packed_session); return ret; }
static int get_win_urls(const CERT_CONTEXT * cert, char **cert_url, char **key_url, char **label, gnutls_datum_t * der) { BOOL r; int ret; DWORD tl_size; gnutls_datum_t tmp_label = { NULL, 0 }; char name[MAX_CN * 2]; char hex[MAX_WID_SIZE * 2 + 1]; gnutls_buffer_st str; #ifdef WORDS_BIGENDIAN const unsigned bigendian = 1; #else const unsigned bigendian = 0; #endif if (cert == NULL) return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); if (der) { der->data = gnutls_malloc(cert->cbCertEncoded); if (der->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); memcpy(der->data, cert->pbCertEncoded, cert->cbCertEncoded); der->size = cert->cbCertEncoded; } _gnutls_buffer_init(&str); if (label) *label = NULL; if (key_url) *key_url = NULL; if (cert_url) *cert_url = NULL; tl_size = sizeof(name); r = CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, name, &tl_size); if (r != 0) { /* optional */ ret = _gnutls_ucs2_to_utf8(name, tl_size, &tmp_label, bigendian); if (ret < 0) { gnutls_assert(); goto fail; } if (label) *label = (char *)tmp_label.data; } tl_size = sizeof(name); r = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, name, &tl_size); if (r == 0) { gnutls_assert(); ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto fail; } if (_gnutls_bin2hex(name, tl_size, hex, sizeof(hex), 0) == NULL) { ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR); goto fail; } ret = _gnutls_buffer_append_printf(&str, WIN_URL "id=%s;type=cert", hex); if (ret < 0) { gnutls_assert(); goto fail; } if (tmp_label.data) { ret = _gnutls_buffer_append_str(&str, ";name="); if (ret < 0) { gnutls_assert(); goto fail; } ret = _gnutls_buffer_append_escape(&str, tmp_label.data, tmp_label.size, " "); if (ret < 0) { gnutls_assert(); goto fail; } } ret = _gnutls_buffer_append_data(&str, "\x00", 1); if (ret < 0) { gnutls_assert(); goto fail; } if (cert_url) *cert_url = (char *)str.data; _gnutls_buffer_init(&str); ret = _gnutls_buffer_append_printf(&str, WIN_URL "id=%s;type=privkey", hex); if (ret < 0) { gnutls_assert(); goto fail; } if (tmp_label.data) { ret = _gnutls_buffer_append_str(&str, ";name="); if (ret < 0) { gnutls_assert(); goto fail; } ret = _gnutls_buffer_append_escape(&str, tmp_label.data, tmp_label.size, " "); if (ret < 0) { gnutls_assert(); goto fail; } } ret = _gnutls_buffer_append_data(&str, "\x00", 1); if (ret < 0) { gnutls_assert(); goto fail; } if (key_url) *key_url = (char *)str.data; _gnutls_buffer_init(&str); ret = 0; goto cleanup; fail: if (der) gnutls_free(der->data); if (cert_url) gnutls_free(*cert_url); if (key_url) gnutls_free(*key_url); if (label) gnutls_free(*label); cleanup: _gnutls_buffer_clear(&str); return ret; }
int _gnutls13_send_certificate(gnutls_session_t session, unsigned again) { int ret; gnutls_pcert_st *apr_cert_list = NULL; gnutls_privkey_t apr_pkey = NULL; int apr_cert_list_length = 0; mbuffer_st *bufel = NULL; gnutls_buffer_st buf; unsigned pos_mark, ext_pos_mark; unsigned i; struct ocsp_req_ctx_st ctx; gnutls_certificate_credentials_t cred; if (again == 0) { if (!session->internals.initial_negotiation_completed && session->internals.hsk_flags & HSK_PSK_SELECTED) return 0; if (session->security_parameters.entity == GNUTLS_SERVER && session->internals.resumed) return 0; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->security_parameters.entity == GNUTLS_CLIENT && !(session->internals.hsk_flags & HSK_CRT_ASKED)) { return 0; } ret = _gnutls_get_selected_cert(session, &apr_cert_list, &apr_cert_list_length, &apr_pkey); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_init_handshake_mbuffer(&buf); if (ret < 0) return gnutls_assert_val(ret); if (session->security_parameters.entity == GNUTLS_CLIENT) { ret = _gnutls_buffer_append_data_prefix(&buf, 8, session->internals.post_handshake_cr_context.data, session->internals.post_handshake_cr_context.size); if (ret < 0) { gnutls_assert(); goto cleanup; } } else { ret = _gnutls_buffer_append_prefix(&buf, 8, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } } /* mark total size */ pos_mark = buf.length; ret = _gnutls_buffer_append_prefix(&buf, 24, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } for (i=0;i<(unsigned)apr_cert_list_length;i++) { ret = _gnutls_buffer_append_data_prefix(&buf, 24, apr_cert_list[i].cert.data, apr_cert_list[i].cert.size); if (ret < 0) { gnutls_assert(); goto cleanup; } #ifdef ENABLE_OCSP if ((session->internals.selected_ocsp_length > 0 || session->internals.selected_ocsp_func) && _gnutls_hello_ext_is_present(session, GNUTLS_EXTENSION_STATUS_REQUEST)) { /* append status response if available */ ret = _gnutls_extv_append_init(&buf); if (ret < 0) { gnutls_assert(); goto cleanup; } ext_pos_mark = ret; ctx.pcert = &apr_cert_list[i]; ctx.cert_index = i; ctx.session = session; ctx.cred = cred; ret = _gnutls_extv_append(&buf, STATUS_REQUEST_TLS_ID, &ctx, append_status_request); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_extv_append_final(&buf, ext_pos_mark, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } } else #endif { ret = _gnutls_buffer_append_prefix(&buf, 16, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } } } _gnutls_write_uint24(buf.length-pos_mark-3, &buf.data[pos_mark]); bufel = _gnutls_buffer_to_mbuffer(&buf); } return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_PKT); cleanup: _gnutls_buffer_clear(&buf); return ret; }
/** * gnutls_deinit - clear all buffers associated with a session * @session: is a #gnutls_session_t structure. * * This function clears all buffers associated with the @session. * This function will also remove session data from the session * database if the session was terminated abnormally. **/ void gnutls_deinit (gnutls_session_t session) { if (session == NULL) return; /* remove auth info firstly */ _gnutls_free_auth_info (session); _gnutls_handshake_internal_state_clear (session); _gnutls_handshake_io_buffer_clear (session); _gnutls_free_datum (&session->connection_state.read_mac_secret); _gnutls_free_datum (&session->connection_state.write_mac_secret); _gnutls_buffer_clear (&session->internals.ia_data_buffer); _gnutls_buffer_clear (&session->internals.handshake_hash_buffer); _gnutls_buffer_clear (&session->internals.handshake_data_buffer); _gnutls_buffer_clear (&session->internals.application_data_buffer); _gnutls_buffer_clear (&session->internals.record_recv_buffer); _gnutls_buffer_clear (&session->internals.record_send_buffer); gnutls_credentials_clear (session); _gnutls_selected_certs_deinit (session); _gnutls_cipher_deinit (&session->connection_state.read_cipher_state); _gnutls_cipher_deinit (&session->connection_state.write_cipher_state); if (session->connection_state.read_compression_state != NULL) _gnutls_comp_deinit (session->connection_state.read_compression_state, 1); if (session->connection_state.write_compression_state != NULL) _gnutls_comp_deinit (session->connection_state.write_compression_state, 0); _gnutls_free_datum (&session->cipher_specs.server_write_mac_secret); _gnutls_free_datum (&session->cipher_specs.client_write_mac_secret); _gnutls_free_datum (&session->cipher_specs.server_write_IV); _gnutls_free_datum (&session->cipher_specs.client_write_IV); _gnutls_free_datum (&session->cipher_specs.server_write_key); _gnutls_free_datum (&session->cipher_specs.client_write_key); if (session->key != NULL) { _gnutls_mpi_release (&session->key->KEY); _gnutls_mpi_release (&session->key->client_Y); _gnutls_mpi_release (&session->key->client_p); _gnutls_mpi_release (&session->key->client_g); _gnutls_mpi_release (&session->key->u); _gnutls_mpi_release (&session->key->a); _gnutls_mpi_release (&session->key->x); _gnutls_mpi_release (&session->key->A); _gnutls_mpi_release (&session->key->B); _gnutls_mpi_release (&session->key->b); /* RSA */ _gnutls_mpi_release (&session->key->rsa[0]); _gnutls_mpi_release (&session->key->rsa[1]); _gnutls_mpi_release (&session->key->dh_secret); gnutls_free (session->key); session->key = NULL; } gnutls_free (session->internals.srp_username); if (session->internals.srp_password) { memset (session->internals.srp_password, 0, strlen (session->internals.srp_password)); gnutls_free (session->internals.srp_password); } memset (session, 0, sizeof (struct gnutls_session_int)); gnutls_free (session); }
int _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_datum_t * dn) { gnutls_buffer_st out_str; int k2, k1, result; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; uint8_t value[MAX_STRING_LEN]; gnutls_datum_t td = { NULL, 0 }, tvd = { NULL, 0}; const char *ldap_desc; char oid[MAX_OID_SIZE]; int len; _gnutls_buffer_init(&out_str); k1 = 0; do { k1++; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { if (k1 == 1) { gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto cleanup; } break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); len = 0; result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &tvd); if (result < 0) { gnutls_assert(); goto cleanup; } #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( &out_str, x,y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } /* The encodings of adjoining RelativeDistinguishedNames are separated * by a comma character (',' ASCII 44). */ /* Where there is a multi-valued RDN, the outputs from adjoining * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) * character. */ if (k1 != 1) { /* the first time do not append a comma */ if (k2 != 1) { /* adjoining multi-value RDN */ STR_APPEND("+"); } else { STR_APPEND(","); } } ldap_desc = gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID); STR_APPEND(ldap_desc); STR_APPEND("="); result = _gnutls_x509_dn_to_string(oid, tvd.data, tvd.size, &td); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Cannot parse OID: '%s' with value '%s'\n", oid, _gnutls_bin2hex(tvd.data, tvd.size, tmpbuffer3, sizeof (tmpbuffer3), NULL)); goto cleanup; } DATA_APPEND(td.data, td.size); _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); } while (1); } while (1); result = _gnutls_buffer_to_datum(&out_str, dn, 1); if (result < 0) gnutls_assert(); goto cleanup1; cleanup: _gnutls_buffer_clear(&out_str); cleanup1: _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); return result; }
static int compute_psk_binder(gnutls_session_t session, const mac_entry_st *prf, unsigned binders_length, int exts_length, int ext_offset, const gnutls_datum_t *psk, const gnutls_datum_t *client_hello, bool resuming, void *out) { int ret; unsigned client_hello_pos, extensions_len_pos; gnutls_buffer_st handshake_buf; uint8_t binder_key[MAX_HASH_SIZE]; _gnutls_buffer_init(&handshake_buf); if (session->security_parameters.entity == GNUTLS_CLIENT) { if (session->internals.hsk_flags & HSK_HRR_RECEIVED) { ret = gnutls_buffer_append_data(&handshake_buf, (const void *) session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length); if (ret < 0) { gnutls_assert(); goto error; } } client_hello_pos = handshake_buf.length; ret = gnutls_buffer_append_data(&handshake_buf, client_hello->data, client_hello->size); if (ret < 0) { gnutls_assert(); goto error; } /* This is a ClientHello message */ handshake_buf.data[client_hello_pos] = GNUTLS_HANDSHAKE_CLIENT_HELLO; /* At this point we have not yet added the binders to the ClientHello, * but we have to overwrite the size field, pretending as if binders * of the correct length were present. */ _gnutls_write_uint24(handshake_buf.length - client_hello_pos + binders_length - 2, &handshake_buf.data[client_hello_pos + 1]); _gnutls_write_uint16(handshake_buf.length - client_hello_pos + binders_length - ext_offset, &handshake_buf.data[client_hello_pos + ext_offset]); extensions_len_pos = handshake_buf.length - client_hello_pos - exts_length - 2; _gnutls_write_uint16(exts_length + binders_length + 2, &handshake_buf.data[client_hello_pos + extensions_len_pos]); } else { if (session->internals.hsk_flags & HSK_HRR_SENT) { if (unlikely(session->internals.handshake_hash_buffer.length <= client_hello->size)) { ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); goto error; } ret = gnutls_buffer_append_data(&handshake_buf, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length - client_hello->size); if (ret < 0) { gnutls_assert(); goto error; } } if (unlikely(client_hello->size <= binders_length)) { ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); goto error; } ret = gnutls_buffer_append_data(&handshake_buf, (const void *) client_hello->data, client_hello->size - binders_length); if (ret < 0) { gnutls_assert(); goto error; } } ret = compute_binder_key(prf, psk->data, psk->size, resuming, binder_key); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls13_compute_finished(prf, binder_key, &handshake_buf, out); if (ret < 0) { gnutls_assert(); goto error; } ret = 0; error: _gnutls_buffer_clear(&handshake_buf); return ret; }
static int encode_tpmkey_url(char **url, const TSS_UUID * uuid, TSS_FLAG storage) { size_t size = (UUID_SIZE * 2 + 4) * 2 + 32; uint8_t u1[UUID_SIZE]; gnutls_buffer_st buf; gnutls_datum_t dret; int ret; *url = gnutls_malloc(size); if (*url == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_buffer_init(&buf); memcpy(u1, &uuid->ulTimeLow, 4); memcpy(&u1[4], &uuid->usTimeMid, 2); memcpy(&u1[6], &uuid->usTimeHigh, 2); u1[8] = uuid->bClockSeqHigh; u1[9] = uuid->bClockSeqLow; memcpy(&u1[10], uuid->rgbNode, 6); ret = _gnutls_buffer_append_str(&buf, "tpmkey:uuid="); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_printf(&buf, "%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x", (unsigned int) u1[0], (unsigned int) u1[1], (unsigned int) u1[2], (unsigned int) u1[3], (unsigned int) u1[4], (unsigned int) u1[5], (unsigned int) u1[6], (unsigned int) u1[7], (unsigned int) u1[8], (unsigned int) u1[9], (unsigned int) u1[10], (unsigned int) u1[11], (unsigned int) u1[12], (unsigned int) u1[13], (unsigned int) u1[14], (unsigned int) u1[15]); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_printf(&buf, ";storage=%s", (storage == TSS_PS_TYPE_USER) ? "user" : "system"); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_to_datum(&buf, &dret); if (ret < 0) { gnutls_assert(); goto cleanup; } *url = (char *) dret.data; return 0; cleanup: _gnutls_buffer_clear(&buf); return ret; }
int _gnutls13_recv_certificate(gnutls_session_t session) { int ret; gnutls_buffer_st buf; unsigned optional = 0; if (!session->internals.initial_negotiation_completed && session->internals.hsk_flags & HSK_PSK_SELECTED) return 0; if (session->security_parameters.entity == GNUTLS_SERVER) { /* if we didn't request a certificate, there will not be any */ if (session->internals.send_cert_req == 0) return 0; if (session->internals.send_cert_req != GNUTLS_CERT_REQUIRE) optional = 1; } ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, 0, &buf); if (ret < 0) { if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET && session->internals.send_cert_req) return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND); return gnutls_assert_val(ret); } if (buf.length == 0) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto cleanup; } if (session->internals.initial_negotiation_completed && session->internals.post_handshake_cr_context.size > 0) { gnutls_datum_t context; /* verify whether the context matches */ ret = _gnutls_buffer_pop_datum_prefix8(&buf, &context); if (ret < 0) { gnutls_assert(); goto cleanup; } if (context.size != session->internals.post_handshake_cr_context.size || memcmp(context.data, session->internals.post_handshake_cr_context.data, context.size) != 0) { ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; gnutls_assert(); goto cleanup; } } else { if (buf.data[0] != 0) { /* The context field must be empty during handshake */ gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto cleanup; } /* buf.length is positive */ buf.data++; buf.length--; } _gnutls_handshake_log("HSK[%p]: parsing certificate message\n", session); ret = parse_cert_list(session, buf.data, buf.length); if (ret < 0) { if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND) { if (optional) ret = 0; else if (session->security_parameters.entity == GNUTLS_SERVER) ret = GNUTLS_E_CERTIFICATE_REQUIRED; } gnutls_assert(); goto cleanup; } session->internals.hsk_flags |= HSK_CRT_VRFY_EXPECTED; ret = 0; cleanup: _gnutls_buffer_clear(&buf); return ret; }
/* Load session data from a buffer. */ int _gnutls_session_unpack (gnutls_session_t session, const gnutls_datum_t * packed_session) { int ret; gnutls_buffer_st sb; opaque id; _gnutls_buffer_init (&sb); if (packed_session == NULL || packed_session->size == 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_buffer_append_data (&sb, packed_session->data, packed_session->size); if (ret < 0) { gnutls_assert (); return ret; } if (_gnutls_get_auth_info (session) != NULL) { _gnutls_free_auth_info (session); } BUFFER_POP (&sb, &id, 1); switch (id) { #ifdef ENABLE_SRP case GNUTLS_CRD_SRP: ret = unpack_srp_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); goto error; } break; #endif #ifdef ENABLE_PSK case GNUTLS_CRD_PSK: ret = unpack_psk_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); goto error; } break; #endif #ifdef ENABLE_ANON case GNUTLS_CRD_ANON: ret = unpack_anon_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); return ret; } break; #endif case GNUTLS_CRD_CERTIFICATE: ret = unpack_certificate_auth_info (session, &sb); if (ret < 0) { gnutls_assert (); goto error; } break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto error; } /* Auth_info structures copied. Now copy security_parameters_st. * packed_session must have allocated space for the security parameters. */ ret = unpack_security_parameters (session, &sb); if (ret < 0) { gnutls_assert (); goto error; } ret = _gnutls_ext_unpack (session, &sb); if (ret < 0) { gnutls_assert (); goto error; } ret = 0; error: _gnutls_buffer_clear (&sb); return ret; }