S2N_RESULT s2n_resume_encrypt_session_ticket()

in tls/s2n_resume.c [819:890]


S2N_RESULT s2n_resume_encrypt_session_ticket(struct s2n_connection *conn,
        struct s2n_ticket_key *key, struct s2n_stuffer *to)
{
    RESULT_ENSURE_REF(conn);
    RESULT_ENSURE_REF(to);

    RESULT_ENSURE(key != NULL, S2N_ERR_NO_TICKET_ENCRYPT_DECRYPT_KEY);

    /* Generate unique per-ticket encryption key */
    struct s2n_unique_ticket_key ticket_key = { 0 };
    RESULT_GUARD_POSIX(s2n_blob_init(&ticket_key.initial_key, key->aes_key, sizeof(key->aes_key)));
    struct s2n_blob info_blob = { 0 };
    RESULT_GUARD_POSIX(s2n_blob_init(&info_blob, ticket_key.info, sizeof(ticket_key.info)));
    RESULT_GUARD(s2n_get_public_random_data(&info_blob));
    RESULT_GUARD(s2n_resume_generate_unique_ticket_key(&ticket_key));

    /* Initialize AES key */
    struct s2n_blob aes_key_blob = { 0 };
    RESULT_GUARD_POSIX(s2n_blob_init(&aes_key_blob, ticket_key.output_key, sizeof(ticket_key.output_key)));
    DEFER_CLEANUP(struct s2n_session_key aes_ticket_key = { 0 }, s2n_session_key_free);
    RESULT_GUARD_POSIX(s2n_session_key_alloc(&aes_ticket_key));
    RESULT_GUARD(s2n_aes256_gcm.init(&aes_ticket_key));
    RESULT_GUARD(s2n_aes256_gcm.set_encryption_key(&aes_ticket_key, &aes_key_blob));

    /* Ensure we never encrypt with a zero-filled key */
    uint8_t zero_block[S2N_AES256_KEY_LEN] = { 0 };
    RESULT_ENSURE(!s2n_constant_time_equals(key->aes_key, zero_block, S2N_AES256_KEY_LEN),
            S2N_ERR_KEY_CHECK);

    /* Initialize Additional Authenticated Data */
    uint8_t aad_data[S2N_TICKET_AAD_LEN] = { 0 };
    struct s2n_blob aad_blob = { 0 };
    RESULT_GUARD_POSIX(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
    struct s2n_stuffer aad = { 0 };
    RESULT_GUARD_POSIX(s2n_stuffer_init(&aad, &aad_blob));
    RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&aad, key->implicit_aad, sizeof(key->implicit_aad)));
    RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&aad, key->key_name, sizeof(key->key_name)));

    /* Write version number */
    RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(to, S2N_PRE_ENCRYPTED_STATE_V1));

    /* Write key name */
    RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(to, key->key_name, sizeof(key->key_name)));

    /* Write parameter needed to generate unique ticket key */
    RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(to, ticket_key.info, sizeof(ticket_key.info)));

    /* Write IV */
    uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 };
    struct s2n_blob iv = { 0 };
    RESULT_GUARD_POSIX(s2n_blob_init(&iv, iv_data, sizeof(iv_data)));
    RESULT_GUARD(s2n_get_public_random_data(&iv));
    RESULT_GUARD_POSIX(s2n_stuffer_write(to, &iv));

    /* Write serialized session state */
    uint32_t plaintext_state_size = s2n_stuffer_data_available(to);
    RESULT_GUARD(s2n_serialize_resumption_state(conn, to));
    RESULT_GUARD_POSIX(s2n_stuffer_skip_write(to, S2N_TLS_GCM_TAG_LEN));

    /* Initialize blob to be encrypted */
    struct s2n_blob state_blob = { 0 };
    struct s2n_stuffer copy_for_encryption = *to;
    RESULT_GUARD_POSIX(s2n_stuffer_skip_read(&copy_for_encryption, plaintext_state_size));
    uint32_t state_blob_size = s2n_stuffer_data_available(&copy_for_encryption);
    uint8_t *state_blob_data = s2n_stuffer_raw_read(&copy_for_encryption, state_blob_size);
    RESULT_ENSURE_REF(state_blob_data);
    RESULT_GUARD_POSIX(s2n_blob_init(&state_blob, state_blob_data, state_blob_size));

    RESULT_GUARD_POSIX(s2n_aes256_gcm.io.aead.encrypt(&aes_ticket_key, &iv, &aad_blob, &state_blob, &state_blob));

    return S2N_RESULT_OK;
}