/* * Parse the ticket in 'data' and return the resumption master secret * and the KDF ID associated to it. */ int _gnutls13_unpack_session_ticket(gnutls_session_t session, gnutls_datum_t *data, tls13_ticket_st *ticket_data) { int ret; gnutls_datum_t decrypted = { NULL, 0 }; if (unlikely(data == NULL || ticket_data == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); /* Check MAC and decrypt ticket */ ret = _gnutls_decrypt_session_ticket(session, data, &decrypted); if (ret < 0) return gnutls_assert_val(ret); /* Return ticket parameters */ ret = unpack_ticket(session, &decrypted, ticket_data); _gnutls_free_datum(&decrypted); if (ret < 0) return ret; ret = _gnutls_check_resumed_params(session); if (ret < 0) return gnutls_assert_val(ret); return 0; }
int _gnutls_server_restore_session(gnutls_session_t session, uint8_t * session_id, int session_id_size) { gnutls_datum_t data; gnutls_datum_t key; int ret; if (session_id == NULL || session_id_size == 0) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (session->internals.premaster_set != 0) { /* hack for CISCO's DTLS-0.9 */ if (session_id_size == session->internals.resumed_security_parameters. session_id_size && memcmp(session_id, session->internals. resumed_security_parameters.session_id, session_id_size) == 0) return 0; } key.data = session_id; key.size = session_id_size; if (db_func_is_ok(session) != 0) { gnutls_assert(); return GNUTLS_E_INVALID_SESSION; } data = session->internals.db_retrieve_func(session->internals.db_ptr, key); if (data.data == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_SESSION; } /* expiration check is performed inside */ ret = gnutls_session_set_data(session, data.data, data.size); gnutls_free(data.data); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_check_resumed_params(session); if (ret < 0) return gnutls_assert_val(ret); return 0; }
static int unpack_session(gnutls_session_t session, const gnutls_datum_t *state) { int ret; if (unlikely(!state)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ret = _gnutls_session_unpack(session, state); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_check_resumed_params(session); if (ret < 0) return gnutls_assert_val(ret); session->internals.resumed = RESUME_TRUE; return 0; }
static int decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv, struct ticket_st *ticket) { cipher_hd_st cipher_hd; gnutls_datum_t key, IV, state, mac_secret; uint8_t cmac[MAC_SIZE]; time_t timestamp = gnutls_time(0); int ret; /* Check the integrity of ticket */ mac_secret.data = (void *) &priv->key[MAC_SECRET_POS]; mac_secret.size = MAC_SECRET_SIZE; ret = digest_ticket(&mac_secret, ticket, cmac); if (ret < 0) return gnutls_assert_val(ret); if (memcmp(ticket->mac, cmac, MAC_SIZE)) return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); if (ticket->encrypted_state_len % BLOCK_SIZE != 0) return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); /* Decrypt encrypted_state */ key.data = (void *) &priv->key[KEY_POS]; key.size = CIPHER_KEY_SIZE; IV.data = ticket->IV; IV.size = IV_SIZE; ret = _gnutls_cipher_init(&cipher_hd, cipher_to_entry(CIPHER), &key, &IV, 0); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_cipher_decrypt(&cipher_hd, ticket->encrypted_state, ticket->encrypted_state_len); if (ret < 0) { gnutls_assert(); goto cleanup; } /* Unpack security parameters. */ state.data = ticket->encrypted_state; state.size = ticket->encrypted_state_len; ret = _gnutls_session_unpack(session, &state); if (ret < 0) { gnutls_assert(); goto cleanup; } if (timestamp - session->internals.resumed_security_parameters.timestamp > session->internals.expire_time || session->internals.resumed_security_parameters.timestamp > timestamp) { gnutls_assert(); ret = GNUTLS_E_EXPIRED; goto cleanup; } ret = _gnutls_check_resumed_params(session); if (ret < 0) { gnutls_assert(); goto cleanup; } session->internals.resumed = RESUME_TRUE; ret = 0; cleanup: _gnutls_cipher_deinit(&cipher_hd); return ret; }