コード例 #1
0
void device_consistency_signature_destroy(signal_type_base *type)
{
    device_consistency_signature *signature = (device_consistency_signature *)type;
    signal_buffer_free(signature->signature);
    signal_buffer_free(signature->vrf_output);
    free(signature);
}
コード例 #2
0
END_TEST

START_TEST(test_unique_signatures)
{
    int result;
    size_t i;
    size_t r;
    ec_key_pair *key_pair = 0;
    uint8_t *message = 0;
    signal_buffer *signature = 0;
    signal_buffer *vrf_output = 0;

    result = curve_generate_key_pair(global_context, &key_pair);
    ck_assert_int_eq(result, 0);

    message = malloc(256);
    ck_assert_ptr_ne(message, 0);

    for(i = 1; i <= 256; i++) {
        result = signal_crypto_random(global_context, message, i);
        ck_assert_int_eq(result, 0);

        result = curve_calculate_vrf_signature(global_context, &signature,
                ec_key_pair_get_private(key_pair), message, i);
        ck_assert_int_eq(result, 0);

        result = curve_verify_vrf_signature(global_context, &vrf_output,
                ec_key_pair_get_public(key_pair), message, i,
                signal_buffer_data(signature), signal_buffer_len(signature));
        ck_assert_int_eq(result, 0);

        result = curve_verify_signature(
                ec_key_pair_get_public(key_pair), message, i,
                signal_buffer_data(signature), signal_buffer_len(signature));
        ck_assert_int_ne(result, 0);

        signal_buffer_free(vrf_output);

        result = signal_crypto_random(global_context, (uint8_t *)&r, sizeof(size_t));
        ck_assert_int_eq(result, 0);

        message[r % i] ^= 0x01;

        result = curve_verify_vrf_signature(global_context, &vrf_output,
                ec_key_pair_get_public(key_pair), message, i,
                signal_buffer_data(signature), signal_buffer_len(signature));
        ck_assert_int_eq(result, SG_ERR_VRF_SIG_VERIF_FAILED);

        signal_buffer_free(signature);
    }

    /* Cleanup */
    SIGNAL_UNREF(key_pair);
    if(message) {
        free(message);
    }
}
コード例 #3
0
END_TEST

START_TEST(test_unique_signature_vector)
{
    uint8_t publicKey[] = {
            0x05,
            0x21, 0xf7, 0x34, 0x5f, 0x56, 0xd9, 0x60, 0x2f,
            0x15, 0x23, 0x29, 0x8f, 0x4f, 0x6f, 0xce, 0xcb,
            0x14, 0xdd, 0xe2, 0xd5, 0xb9, 0xa9, 0xb4, 0x8b,
            0xca, 0x82, 0x42, 0x68, 0x14, 0x92, 0xb9, 0x20};
    uint8_t privateKey[] = {
            0x38, 0x61, 0x1d, 0x25, 0x3b, 0xea, 0x85, 0xa2,
            0x03, 0x80, 0x53, 0x43, 0xb7, 0x4a, 0x93, 0x6d,
            0x3b, 0x13, 0xb9, 0xe3, 0x12, 0x14, 0x53, 0xe9,
            0x74, 0x0b, 0x6b, 0x82, 0x7e, 0x33, 0x7e, 0x5d};
    uint8_t message[] = {
            0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
            0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2e};
    uint8_t vrf[] = {
            0x75, 0xad, 0x49, 0xbc, 0x95, 0x5f, 0x38, 0xdc,
            0xf6, 0x5f, 0xb6, 0x72, 0x08, 0x6b, 0xd5, 0x09,
            0xcb, 0x4b, 0x4c, 0x41, 0x04, 0x7d, 0xb1, 0x7e,
            0xfd, 0xaf, 0xee, 0xbc, 0x33, 0x03, 0x71, 0xe6};

    int result;
    ec_public_key *public_key = 0;
    ec_private_key *private_key = 0;
    signal_buffer *signature = 0;
    signal_buffer *vrf_output = 0;

    result = curve_decode_point(&public_key, publicKey, sizeof(publicKey), global_context);
    ck_assert_int_eq(result, 0);

    result = curve_decode_private_point(&private_key, privateKey, sizeof(privateKey), global_context);
    ck_assert_int_eq(result, 0);

    result = curve_calculate_vrf_signature(global_context, &signature,
            private_key, message, sizeof(message));
    ck_assert_int_eq(result, 0);

    result = curve_verify_vrf_signature(global_context, &vrf_output,
            public_key, message, sizeof(message),
            signal_buffer_data(signature), signal_buffer_len(signature));
    ck_assert_int_eq(result, 0);

    ck_assert_int_eq(signal_buffer_len(vrf_output), sizeof(vrf));
    ck_assert_int_eq(memcmp(signal_buffer_data(vrf_output), vrf, sizeof(vrf)), 0);

    /* Cleanup */
    signal_buffer_free(signature);
    signal_buffer_free(vrf_output);
    SIGNAL_UNREF(public_key);
    SIGNAL_UNREF(private_key);
}
コード例 #4
0
void device_consistency_message_destroy(signal_type_base *type)
{
    device_consistency_message *message = (device_consistency_message *)type;
    SIGNAL_UNREF(message->signature);
    signal_buffer_free(message->serialized);
    free(message);
}
コード例 #5
0
int session_cipher_decrypt_signal_message(session_cipher *cipher,
        signal_message *ciphertext, void *decrypt_context,
        signal_buffer **plaintext)
{
    int result = 0;
    signal_buffer *result_buf = 0;
    session_record *record = 0;

    assert(cipher);
    signal_lock(cipher->global_context);

    if(cipher->inside_callback == 1) {
        result = SG_ERR_INVAL;
        goto complete;
    }

    result = signal_protocol_session_contains_session(cipher->store, cipher->remote_address);
    if(result == 0) {
        signal_log(cipher->global_context, SG_LOG_WARNING, "No session for: %s:%d", cipher->remote_address->name, cipher->remote_address->device_id);
        result = SG_ERR_NO_SESSION;
        goto complete;
    }
    else if(result < 0) {
        goto complete;
    }

    result = signal_protocol_session_load_session(cipher->store, &record,
            cipher->remote_address);
    if(result < 0) {
        goto complete;
    }

    result = session_cipher_decrypt_from_record_and_signal_message(
            cipher, record, ciphertext, &result_buf);
    if(result < 0) {
        goto complete;
    }

    result = session_cipher_decrypt_callback(cipher, result_buf, decrypt_context);
    if(result < 0) {
        goto complete;
    }

    result = signal_protocol_session_store_session(cipher->store,
            cipher->remote_address, record);

complete:
    SIGNAL_UNREF(record);
    if(result >= 0) {
        *plaintext = result_buf;
    }
    else {
        signal_buffer_free(result_buf);
    }
    signal_unlock(cipher->global_context);
    return result;
}
コード例 #6
0
int ratchet_identity_key_pair_serialize(signal_buffer **buffer, const ratchet_identity_key_pair *key_pair)
{
    int result = 0;
    size_t result_size = 0;
    signal_buffer *result_buf = 0;
    Textsecure__IdentityKeyPairStructure key_structure = TEXTSECURE__IDENTITY_KEY_PAIR_STRUCTURE__INIT;
    size_t len = 0;
    uint8_t *data = 0;

    if(!key_pair) {
        result = SG_ERR_INVAL;
        goto complete;
    }

    result = ec_public_key_serialize_protobuf(&key_structure.publickey, key_pair->public_key);
    if(result < 0) {
        goto complete;
    }
    key_structure.has_publickey = 1;

    result = ec_private_key_serialize_protobuf(&key_structure.privatekey, key_pair->private_key);
    if(result < 0) {
        goto complete;
    }
    key_structure.has_privatekey = 1;

    len = textsecure__identity_key_pair_structure__get_packed_size(&key_structure);
    result_buf = signal_buffer_alloc(len);
    if(!result_buf) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    data = signal_buffer_data(result_buf);
    result_size = textsecure__identity_key_pair_structure__pack(&key_structure, data);
    if(result_size != len) {
        signal_buffer_free(result_buf);
        result = SG_ERR_INVALID_PROTO_BUF;
        result_buf = 0;
        goto complete;
    }

complete:
    if(key_structure.has_publickey) {
        free(key_structure.publickey.data);
    }
    if(key_structure.has_privatekey) {
        free(key_structure.privatekey.data);
    }
    if(result >= 0) {
        result = 0;
        *buffer = result_buf;
    }
    return result;
}
コード例 #7
0
ssize_t ratchet_chain_key_get_base_material(const ratchet_chain_key *chain_key, uint8_t **material, const uint8_t *seed, size_t seed_len)
{
    int result = 0;
    signal_buffer *output_buffer = 0;
    uint8_t *output = 0;
    size_t output_len = 0;

    void *hmac_context = 0;
    result = signal_hmac_sha256_init(chain_key->global_context, &hmac_context, chain_key->key, chain_key->key_len);
    if(result < 0) {
        goto complete;
    }

    result = signal_hmac_sha256_update(chain_key->global_context, hmac_context, seed, seed_len);
    if(result < 0) {
        goto complete;
    }

    result = signal_hmac_sha256_final(chain_key->global_context, hmac_context, &output_buffer);
    if(result < 0) {
        goto complete;
    }

    output_len = signal_buffer_len(output_buffer);
    output = malloc(output_len);
    if(!output) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    memcpy(output, signal_buffer_data(output_buffer), output_len);

complete:
    signal_hmac_sha256_cleanup(chain_key->global_context, hmac_context);
    signal_buffer_free(output_buffer);

    if(result >= 0) {
        *material = output;
        return (ssize_t)output_len;
    }
    else {
        return result;
    }
}
コード例 #8
0
END_TEST

START_TEST(test_curve25519_large_signatures)
{
    int result;

    ec_key_pair *keys = 0;
    result = curve_generate_key_pair(global_context, &keys);
    ck_assert_int_eq(result, 0);

    uint8_t message[1048576];
    memset(message, 0, sizeof(message));

    signal_buffer *signature = 0;

    result = curve_calculate_signature(global_context, &signature,
            ec_key_pair_get_private(keys), message, sizeof(message));
    ck_assert_int_eq(result, 0);

    uint8_t *data = signal_buffer_data(signature);
    size_t len = signal_buffer_len(signature);

    result = curve_verify_signature(ec_key_pair_get_public(keys),
            message, sizeof(message), data, len);
    ck_assert_int_eq(result, 1);

    data[0] ^= 0x01;

    result = curve_verify_signature(ec_key_pair_get_public(keys),
            message, sizeof(message), data, len);
    ck_assert_int_eq(result, 0);

    /* Cleanup */
    SIGNAL_UNREF(keys);
    if(signature) {
        signal_buffer_free(signature);
    }
}
コード例 #9
0
int session_cipher_encrypt(session_cipher *cipher,
        const uint8_t *padded_message, size_t padded_message_len,
        ciphertext_message **encrypted_message)
{
    int result = 0;
    session_record *record = 0;
    session_state *state = 0;
    ratchet_chain_key *chain_key = 0;
    ratchet_chain_key *next_chain_key = 0;
    ratchet_message_keys message_keys;
    ec_public_key *sender_ephemeral = 0;
    uint32_t previous_counter = 0;
    uint32_t session_version = 0;
    signal_buffer *ciphertext = 0;
    uint32_t chain_key_index = 0;
    ec_public_key *local_identity_key = 0;
    ec_public_key *remote_identity_key = 0;
    signal_message *message = 0;
    pre_key_signal_message *pre_key_message = 0;
    uint8_t *ciphertext_data = 0;
    size_t ciphertext_len = 0;

    assert(cipher);
    signal_lock(cipher->global_context);

    if(cipher->inside_callback == 1) {
        result = SG_ERR_INVAL;
        goto complete;
    }

    result = signal_protocol_session_load_session(cipher->store, &record, cipher->remote_address);
    if(result < 0) {
        goto complete;
    }

    state = session_record_get_state(record);
    if(!state) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    chain_key = session_state_get_sender_chain_key(state);
    if(!chain_key) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    result = ratchet_chain_key_get_message_keys(chain_key, &message_keys);
    if(result < 0) {
        goto complete;
    }

    sender_ephemeral = session_state_get_sender_ratchet_key(state);
    if(!sender_ephemeral) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    previous_counter = session_state_get_previous_counter(state);
    session_version = session_state_get_session_version(state);

    result = session_cipher_get_ciphertext(cipher,
            &ciphertext,
            session_version, &message_keys,
            padded_message, padded_message_len);
    if(result < 0) {
        goto complete;
    }
    ciphertext_data = signal_buffer_data(ciphertext);
    ciphertext_len = signal_buffer_len(ciphertext);

    chain_key_index = ratchet_chain_key_get_index(chain_key);

    local_identity_key = session_state_get_local_identity_key(state);
    if(!local_identity_key) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    remote_identity_key = session_state_get_remote_identity_key(state);
    if(!remote_identity_key) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    result = signal_message_create(&message,
            session_version,
            message_keys.mac_key, sizeof(message_keys.mac_key),
            sender_ephemeral,
            chain_key_index, previous_counter,
            ciphertext_data, ciphertext_len,
            local_identity_key, remote_identity_key,
            cipher->global_context);
    if(result < 0) {
        goto complete;
    }

    if(session_state_has_unacknowledged_pre_key_message(state) == 1) {
        uint32_t local_registration_id = session_state_get_local_registration_id(state);
        int has_pre_key_id = 0;
        uint32_t pre_key_id = 0;
        uint32_t signed_pre_key_id;
        ec_public_key *base_key;
        
        if(session_state_unacknowledged_pre_key_message_has_pre_key_id(state)) {
            has_pre_key_id = 1;
            pre_key_id = session_state_unacknowledged_pre_key_message_get_pre_key_id(state);
        }
        signed_pre_key_id = session_state_unacknowledged_pre_key_message_get_signed_pre_key_id(state);
        base_key = session_state_unacknowledged_pre_key_message_get_base_key(state);

        if(!base_key) {
            result = SG_ERR_UNKNOWN;
            goto complete;
        }

        result = pre_key_signal_message_create(&pre_key_message,
                session_version, local_registration_id, (has_pre_key_id ? &pre_key_id : 0),
                signed_pre_key_id, base_key, local_identity_key,
                message,
                cipher->global_context);
        if(result < 0) {
            goto complete;
        }
        SIGNAL_UNREF(message);
        message = 0;
    }

    result = ratchet_chain_key_create_next(chain_key, &next_chain_key);
    if(result < 0) {
        goto complete;
    }

    result = session_state_set_sender_chain_key(state, next_chain_key);
    if(result < 0) {
        goto complete;
    }

    result = signal_protocol_session_store_session(cipher->store, cipher->remote_address, record);

complete:
    if(result >= 0) {
        if(pre_key_message) {
            *encrypted_message = (ciphertext_message *)pre_key_message;
        }
        else {
            *encrypted_message = (ciphertext_message *)message;
        }
    }
    else {
        SIGNAL_UNREF(pre_key_message);
        SIGNAL_UNREF(message);
    }
    signal_buffer_free(ciphertext);
    SIGNAL_UNREF(next_chain_key);
    SIGNAL_UNREF(record);
    signal_explicit_bzero(&message_keys, sizeof(ratchet_message_keys));
    signal_unlock(cipher->global_context);
    return result;
}
コード例 #10
0
static int session_cipher_decrypt_from_state_and_signal_message(session_cipher *cipher,
        session_state *state, signal_message *ciphertext, signal_buffer **plaintext)
{
    int result = 0;
    signal_buffer *result_buf = 0;
    ec_public_key *their_ephemeral = 0;
    uint32_t counter = 0;
    ratchet_chain_key *chain_key = 0;
    ratchet_message_keys message_keys;
    uint8_t message_version = 0;
    uint32_t session_version = 0;
    ec_public_key *remote_identity_key = 0;
    ec_public_key *local_identity_key = 0;
    signal_buffer *ciphertext_body = 0;

    if(!session_state_has_sender_chain(state)) {
        signal_log(cipher->global_context, SG_LOG_WARNING, "Uninitialized session!");
        result = SG_ERR_INVALID_MESSAGE;
        goto complete;
    }

    message_version = signal_message_get_message_version(ciphertext);
    session_version = session_state_get_session_version(state);

    if(message_version != session_version) {
        signal_log(cipher->global_context, SG_LOG_WARNING, "Message version %d, but session version %d", message_version, session_version);
        result = SG_ERR_INVALID_MESSAGE;
        goto complete;
    }

    their_ephemeral = signal_message_get_sender_ratchet_key(ciphertext);
    if(!their_ephemeral) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    counter = signal_message_get_counter(ciphertext);

    result = session_cipher_get_or_create_chain_key(cipher, &chain_key, state, their_ephemeral);
    if(result < 0) {
        goto complete;
    }

    result = session_cipher_get_or_create_message_keys(&message_keys, state,
            their_ephemeral, chain_key, counter, cipher->global_context);
    if(result < 0) {
        goto complete;
    }

    remote_identity_key = session_state_get_remote_identity_key(state);
    if(!remote_identity_key) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    local_identity_key = session_state_get_local_identity_key(state);
    if(!local_identity_key) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    result = signal_message_verify_mac(ciphertext,
            remote_identity_key, local_identity_key,
            message_keys.mac_key, sizeof(message_keys.mac_key),
            cipher->global_context);
    if(result != 1) {
        if(result == 0) {
            signal_log(cipher->global_context, SG_LOG_WARNING, "Message mac not verified");
            result = SG_ERR_INVALID_MESSAGE;
        }
        else if(result < 0) {
            signal_log(cipher->global_context, SG_LOG_WARNING, "Error attempting to verify message mac");
        }
        goto complete;
    }

    ciphertext_body = signal_message_get_body(ciphertext);
    if(!ciphertext_body) {
        signal_log(cipher->global_context, SG_LOG_WARNING, "Message body does not exist");
        result = SG_ERR_INVALID_MESSAGE;
        goto complete;
    }

    result = session_cipher_get_plaintext(cipher, &result_buf, message_version, &message_keys,
            signal_buffer_data(ciphertext_body), signal_buffer_len(ciphertext_body));
    if(result < 0) {
        goto complete;
    }

    session_state_clear_unacknowledged_pre_key_message(state);

complete:
    SIGNAL_UNREF(chain_key);
    if(result >= 0) {
        *plaintext = result_buf;
    }
    else {
        signal_buffer_free(result_buf);
    }
    signal_explicit_bzero(&message_keys, sizeof(ratchet_message_keys));
    return result;
}
コード例 #11
0
static int session_cipher_decrypt_from_record_and_signal_message(session_cipher *cipher,
        session_record *record, signal_message *ciphertext, signal_buffer **plaintext)
{
    int result = 0;
    signal_buffer *result_buf = 0;
    session_state *state = 0;
    session_state *state_copy = 0;
    session_record_state_node *previous_states_node = 0;

    assert(cipher);
    signal_lock(cipher->global_context);

    state = session_record_get_state(record);
    if(state) {
        result = session_state_copy(&state_copy, state, cipher->global_context);
        if(result < 0) {
            goto complete;
        }

        //TODO Collect and log invalid message errors if totally unsuccessful

        result = session_cipher_decrypt_from_state_and_signal_message(cipher, state_copy, ciphertext, &result_buf);
        if(result < 0 && result != SG_ERR_INVALID_MESSAGE) {
            goto complete;
        }

        if(result >= SG_SUCCESS) {
            session_record_set_state(record, state_copy);
            goto complete;
        }
        SIGNAL_UNREF(state_copy);
    }

    previous_states_node = session_record_get_previous_states_head(record);
    while(previous_states_node) {
        state = session_record_get_previous_states_element(previous_states_node);

        result = session_state_copy(&state_copy, state, cipher->global_context);
        if(result < 0) {
            goto complete;
        }

        result = session_cipher_decrypt_from_state_and_signal_message(cipher, state_copy, ciphertext, &result_buf);
        if(result < 0 && result != SG_ERR_INVALID_MESSAGE) {
            goto complete;
        }

        if(result >= SG_SUCCESS) {
            session_record_get_previous_states_remove(record, previous_states_node);
            result = session_record_promote_state(record, state_copy);
            goto complete;
        }

        SIGNAL_UNREF(state_copy);
        previous_states_node = session_record_get_previous_states_next(previous_states_node);
    }

    signal_log(cipher->global_context, SG_LOG_WARNING, "No valid sessions");
    result = SG_ERR_INVALID_MESSAGE;

complete:
    SIGNAL_UNREF(state_copy);
    if(result >= 0) {
        *plaintext = result_buf;
    }
    else {
        signal_buffer_free(result_buf);
    }
    signal_unlock(cipher->global_context);
    return result;
}
コード例 #12
0
/*
 * ---------------------------------------------------------------------------
 *  cleanup_unifi_sdio
 *
 *      Release any resources owned by a unifi instance.
 *
 *  Arguments:
 *      priv          Pointer to the instance to free.
 *
 *  Returns:
 *      None.
 * ---------------------------------------------------------------------------
 */
static void
cleanup_unifi_sdio(unifi_priv_t *priv)
{
    int priv_instance;
    int i;
    static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};

    /* Remove the device nodes */
    uf_destroy_device_nodes(priv);

    /* Mark this device as gone away by NULLing the entry in Unifi_instances */
    Unifi_instances[priv->instance] = NULL;

    unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: remove_proc_entry\n");
    /*
     * Free the children of priv before unifi_free_netdevice() frees
     * the priv struct
     */
    remove_proc_entry(priv->proc_entry_name, 0);


    /* Unregister netdev as a client. */
    if (priv->netdev_client) {
        unifi_trace(priv, UDBG2, "Netdev client (id:%d s:0x%X) is unregistered\n",
                priv->netdev_client->client_id, priv->netdev_client->sender_id);
        ul_deregister_client(priv->netdev_client);
    }

    /* Destroy the SME related threads and parameters */
    uf_sme_deinit(priv);

#ifdef CSR_SME_USERSPACE
    priv->smepriv = NULL;
#endif

#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
    if (log_hip_signals)
    {
        uf_unregister_hip_offline_debug(priv);
    }
#endif

    /* Free any packets left in the Rx queues */
    for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
    {
        uf_free_pending_rx_packets(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address,i);
        uf_free_pending_rx_packets(priv, UF_CONTROLLED_PORT_Q, broadcast_address,i);
    }
    /*
     * We need to free the resources held by the core, which include tx skbs,
     * otherwise we can not call unregister_netdev().
     */
    if (priv->card) {
        unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: free card\n");
        unifi_coredump_free(priv->card);
        unifi_free_card(priv->card);
        priv->card = NULL;
    }

    /*
     * Unregister the network device.
     * We can not unregister the netdev before we release
     * all pending packets in the core.
     */
    uf_unregister_netdev(priv);
    priv->totalInterfaceCount = 0;

    /* Clear the table of registered netdev_priv's */
    for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
        Unifi_netdev_instances[priv->instance * CSR_WIFI_NUM_INTERFACES + i] = NULL;
    }

    unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: uf_free_netdevice\n");
    /*
     * When uf_free_netdevice() returns, the priv is invalid
     * so we need to remember the instance to clear the global flag later.
     */
    priv_instance = priv->instance;

#ifdef CSR_WIFI_RX_PATH_SPLIT
    flush_workqueue(priv->rx_workqueue);
    destroy_workqueue(priv->rx_workqueue);
    signal_buffer_free(priv,CSR_WIFI_RX_SIGNAL_BUFFER_SIZE);
#endif

    /* Priv is freed as part of the net_device */
    uf_free_netdevice(priv);

    /*
     * Now clear the flag that says the old instance is in use.
     * This is used to prevent a new instance being started before old
     * one has finshed closing down, for example if bounce makes the card
     * appear to be ejected and re-inserted quickly.
     */
    In_use[priv_instance] = UNIFI_DEV_NOT_IN_USE;

    unifi_trace(NULL, UDBG5, "cleanup_unifi_sdio: DONE.\n");

} /* cleanup_unifi_sdio() */
コード例 #13
0
int session_cipher_decrypt_pre_key_signal_message(session_cipher *cipher,
        pre_key_signal_message *ciphertext, void *decrypt_context,
        signal_buffer **plaintext)
{
    int result = 0;
    signal_buffer *result_buf = 0;
    session_record *record = 0;
    int has_unsigned_pre_key_id = 0;
    uint32_t unsigned_pre_key_id = 0;

    assert(cipher);
    signal_lock(cipher->global_context);

    if(cipher->inside_callback == 1) {
        result = SG_ERR_INVAL;
        goto complete;
    }

    result = signal_protocol_session_load_session(cipher->store, &record, cipher->remote_address);
    if(result < 0) {
        goto complete;
    }

    result = session_builder_process_pre_key_signal_message(cipher->builder, record, ciphertext, &unsigned_pre_key_id);
    if(result < 0) {
        goto complete;
    }
    has_unsigned_pre_key_id = result;

    result = session_cipher_decrypt_from_record_and_signal_message(cipher, record,
            pre_key_signal_message_get_signal_message(ciphertext),
            &result_buf);
    if(result < 0) {
        goto complete;
    }

    result = session_cipher_decrypt_callback(cipher, result_buf, decrypt_context);
    if(result < 0) {
        goto complete;
    }

    result = signal_protocol_session_store_session(cipher->store, cipher->remote_address, record);
    if(result < 0) {
        goto complete;
    }

    if(has_unsigned_pre_key_id) {
        result = signal_protocol_pre_key_remove_key(cipher->store, unsigned_pre_key_id);
        if(result < 0) {
            goto complete;
        }
    }

complete:
    SIGNAL_UNREF(record);
    if(result >= 0) {
        *plaintext = result_buf;
    }
    else {
        signal_buffer_free(result_buf);
    }
    signal_unlock(cipher->global_context);
    return result;
}
コード例 #14
0
END_TEST

START_TEST(test_vectors)
{
    int result = 0;
    ec_public_key *alice_identity_key = 0;
    ec_public_key *bob_identity_key = 0;
    fingerprint_generator *generator = 0;
    fingerprint *alice_fingerprint = 0;
    fingerprint *bob_fingerprint = 0;
    signal_buffer *alice_buffer = 0;
    signal_buffer *bob_buffer = 0;

    uint8_t aliceIdentity[] = {
        0x05, 0x06, 0x86, 0x3b, 0xc6, 0x6d, 0x02, 0xb4,
        0x0d, 0x27, 0xb8, 0xd4, 0x9c, 0xa7, 0xc0, 0x9e,
        0x92, 0x39, 0x23, 0x6f, 0x9d, 0x7d, 0x25, 0xd6,
        0xfc, 0xca, 0x5c, 0xe1, 0x3c, 0x70, 0x64, 0xd8,
        0x68
    };

    uint8_t bobIdentity[] = {
        0x05, 0xf7, 0x81, 0xb6, 0xfb, 0x32, 0xfe, 0xd9,
        0xba, 0x1c, 0xf2, 0xde, 0x97, 0x8d, 0x4d, 0x5d,
        0xa2, 0x8d, 0xc3, 0x40, 0x46, 0xae, 0x81, 0x44,
        0x02, 0xb5, 0xc0, 0xdb, 0xd9, 0x6f, 0xda, 0x90,
        0x7b
    };

    const char *displayableFingerprint =
        "300354477692869396892869876765458257569162576843440918079131";

    uint8_t aliceScannableFingerprint[] = {
        0x08, 0x00, 0x12, 0x31, 0x0a, 0x21, 0x05, 0x06,
        0x86, 0x3b, 0xc6, 0x6d, 0x02, 0xb4, 0x0d, 0x27,
        0xb8, 0xd4, 0x9c, 0xa7, 0xc0, 0x9e, 0x92, 0x39,
        0x23, 0x6f, 0x9d, 0x7d, 0x25, 0xd6, 0xfc, 0xca,
        0x5c, 0xe1, 0x3c, 0x70, 0x64, 0xd8, 0x68, 0x12,
        0x0c, 0x2b, 0x31, 0x34, 0x31, 0x35, 0x32, 0x32,
        0x32, 0x32, 0x32, 0x32, 0x32, 0x1a, 0x31, 0x0a,
        0x21, 0x05, 0xf7, 0x81, 0xb6, 0xfb, 0x32, 0xfe,
        0xd9, 0xba, 0x1c, 0xf2, 0xde, 0x97, 0x8d, 0x4d,
        0x5d, 0xa2, 0x8d, 0xc3, 0x40, 0x46, 0xae, 0x81,
        0x44, 0x02, 0xb5, 0xc0, 0xdb, 0xd9, 0x6f, 0xda,
        0x90, 0x7b, 0x12, 0x0c, 0x2b, 0x31, 0x34, 0x31,
        0x35, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33
    };

    uint8_t bobScannableFingerprint[] = {
        0x08, 0x00, 0x12, 0x31, 0x0a, 0x21, 0x05, 0xf7,
        0x81, 0xb6, 0xfb, 0x32, 0xfe, 0xd9, 0xba, 0x1c,
        0xf2, 0xde, 0x97, 0x8d, 0x4d, 0x5d, 0xa2, 0x8d,
        0xc3, 0x40, 0x46, 0xae, 0x81, 0x44, 0x02, 0xb5,
        0xc0, 0xdb, 0xd9, 0x6f, 0xda, 0x90, 0x7b, 0x12,
        0x0c, 0x2b, 0x31, 0x34, 0x31, 0x35, 0x33, 0x33,
        0x33, 0x33, 0x33, 0x33, 0x33, 0x1a, 0x31, 0x0a,
        0x21, 0x05, 0x06, 0x86, 0x3b, 0xc6, 0x6d, 0x02,
        0xb4, 0x0d, 0x27, 0xb8, 0xd4, 0x9c, 0xa7, 0xc0,
        0x9e, 0x92, 0x39, 0x23, 0x6f, 0x9d, 0x7d, 0x25,
        0xd6, 0xfc, 0xca, 0x5c, 0xe1, 0x3c, 0x70, 0x64,
        0xd8, 0x68, 0x12, 0x0c, 0x2b, 0x31, 0x34, 0x31,
        0x35, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32
    };

    result = curve_decode_point(&alice_identity_key, aliceIdentity, sizeof(aliceIdentity), global_context);
    ck_assert_int_eq(result, 0);

    result = curve_decode_point(&bob_identity_key, bobIdentity, sizeof(bobIdentity), global_context);
    ck_assert_int_eq(result, 0);

    result = fingerprint_generator_create(&generator, 5200, global_context);
    ck_assert_int_eq(result, 0);

    result = fingerprint_generator_create_for(generator,
             "+14152222222", alice_identity_key,
             "+14153333333", bob_identity_key,
             &alice_fingerprint);
    ck_assert_int_eq(result, 0);

    result = fingerprint_generator_create_for(generator,
             "+14153333333", bob_identity_key,
             "+14152222222", alice_identity_key,
             &bob_fingerprint);
    ck_assert_int_eq(result, 0);

    displayable_fingerprint *alice_displayable = fingerprint_get_displayable(alice_fingerprint);
    ck_assert_str_eq(
        displayable_fingerprint_text(alice_displayable),
        displayableFingerprint);

    displayable_fingerprint *bob_displayable = fingerprint_get_displayable(bob_fingerprint);
    ck_assert_str_eq(
        displayable_fingerprint_text(bob_displayable),
        displayableFingerprint);

    scannable_fingerprint *alice_scannable = fingerprint_get_scannable(alice_fingerprint);
    scannable_fingerprint_serialize(&alice_buffer, alice_scannable);
    ck_assert_int_eq(result, 0);

    ck_assert_int_eq(signal_buffer_len(alice_buffer), sizeof(aliceScannableFingerprint));
    ck_assert_int_eq(memcmp(signal_buffer_data(alice_buffer), aliceScannableFingerprint, sizeof(aliceScannableFingerprint)), 0);

    scannable_fingerprint *bob_scannable = fingerprint_get_scannable(bob_fingerprint);
    scannable_fingerprint_serialize(&bob_buffer, bob_scannable);
    ck_assert_int_eq(result, 0);

    ck_assert_int_eq(signal_buffer_len(bob_buffer), sizeof(bobScannableFingerprint));
    ck_assert_int_eq(memcmp(signal_buffer_data(bob_buffer), bobScannableFingerprint, sizeof(bobScannableFingerprint)), 0);

    /* Cleanup */
    signal_buffer_free(alice_buffer);
    signal_buffer_free(bob_buffer);
    fingerprint_generator_free(generator);
    SIGNAL_UNREF(alice_identity_key);
    SIGNAL_UNREF(bob_identity_key);
    SIGNAL_UNREF(alice_fingerprint);
    SIGNAL_UNREF(bob_fingerprint);
}
コード例 #15
0
/*
 * ---------------------------------------------------------------------------
 *  register_unifi_sdio
 *
 *      This function is called from the Probe (or equivalent) method of
 *      the SDIO driver when a UniFi card is detected.
 *      We allocate the Linux net_device struct, initialise the HIP core
 *      lib, create the char device nodes and start the userspace helper
 *      to initialise the device.
 *
 *  Arguments:
 *      sdio_dev        Pointer to SDIO context handle to use for all
 *                      SDIO ops.
 *      bus_id          A small number indicating the SDIO card position on the
 *                      bus. Typically this is the slot number, e.g. 0, 1 etc.
 *                      Valid values are 0 to MAX_UNIFI_DEVS-1.
 *      dev             Pointer to kernel device manager struct.
 *
 *  Returns:
 *      Pointer to the unifi instance, or NULL on error.
 * ---------------------------------------------------------------------------
 */
static unifi_priv_t *
register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev)
{
    unifi_priv_t *priv = NULL;
    int r = -1;
    CsrResult csrResult;

    if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) {
        unifi_error(priv, "register_unifi_sdio: invalid device %d\n",
                bus_id);
        return NULL;
    }

    down(&Unifi_instance_mutex);

    if (In_use[bus_id] != UNIFI_DEV_NOT_IN_USE) {
        unifi_error(priv, "register_unifi_sdio: device %d is already in use\n",
                bus_id);
        goto failed0;
    }


    /* Allocate device private and net_device structs */
    priv = uf_alloc_netdevice(sdio_dev, bus_id);
    if (priv == NULL) {
        unifi_error(priv, "Failed to allocate driver private\n");
        goto failed0;
    }

    priv->unifi_device = dev;

    SET_NETDEV_DEV(priv->netdev[0], dev);

    /* We are not ready to send data yet. */
    netif_carrier_off(priv->netdev[0]);

    /* Allocate driver context. */
    priv->card = unifi_alloc_card(priv->sdio, priv);
    if (priv->card == NULL) {
        unifi_error(priv, "Failed to allocate UniFi driver card struct.\n");
        goto failed1;
    }

    if (Unifi_instances[bus_id]) {
        unifi_error(priv, "Internal error: instance for slot %d is already taken\n",
                bus_id);
    }
    Unifi_instances[bus_id] = priv;
    In_use[bus_id] = UNIFI_DEV_IN_USE;

    /* Save the netdev_priv for use by the netdev event callback mechanism */
    Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES] = netdev_priv(priv->netdev[0]);

    /* Initialise the mini-coredump capture buffers */
    csrResult = unifi_coredump_init(priv->card, (u16)coredump_max);
    if (csrResult != CSR_RESULT_SUCCESS) {
        unifi_error(priv, "Couldn't allocate mini-coredump buffers\n");
    }

    /* Create the character device nodes */
    r = uf_create_device_nodes(priv, bus_id);
    if (r) {
        goto failed1;
    }

    /*
     * We use the slot number as unifi device index.
     */
    scnprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance);
    /*
     * The following complex casting is in place in order to eliminate 64-bit compilation warning
     * "cast to/from pointer from/to integer of different size"
     */
    if (!proc_create_data(priv->proc_entry_name, 0, NULL,
			  &uf_proc_fops, (void *)(long)priv->instance))
    {
        unifi_error(priv, "unifi: can't create /proc/driver/unifi\n");
    }

    /* Allocate the net_device for interfaces other than 0. */
    {
        int i;
        priv->totalInterfaceCount =0;

        for(i=1;i<CSR_WIFI_NUM_INTERFACES;i++)
        {
            if( !uf_alloc_netdevice_for_other_interfaces(priv,i) )
            {
                /* error occured while allocating the net_device for interface[i]. The net_device are
                 * allocated for the interfaces with id<i. Dont worry, all the allocated net_device will
                 * be releasing chen the control goes to the label failed0.
                 */
                unifi_error(priv, "Failed to allocate driver private for interface[%d]\n",i);
                goto failed0;
            }
            else
            {
                SET_NETDEV_DEV(priv->netdev[i], dev);

                /* We are not ready to send data yet. */
                netif_carrier_off(priv->netdev[i]);

                /* Save the netdev_priv for use by the netdev event callback mechanism */
                Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES + i] = netdev_priv(priv->netdev[i]);
            }
        }

        for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
        {
            netInterface_priv_t *interfacePriv = priv->interfacePriv[i];
            interfacePriv->netdev_registered=0;
        }
    }

#ifdef CSR_WIFI_RX_PATH_SPLIT
    if (signal_buffer_init(priv, CSR_WIFI_RX_SIGNAL_BUFFER_SIZE))
    {
        unifi_error(priv,"Failed to allocate shared memory for T-H signals\n");
        goto failed2;
    }
    priv->rx_workqueue = create_singlethread_workqueue("rx_workq");
    if (priv->rx_workqueue == NULL) {
        unifi_error(priv,"create_singlethread_workqueue failed \n");
        goto failed3;
    }
    INIT_WORK(&priv->rx_work_struct, rx_wq_handler);
#endif

#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
    if (log_hip_signals)
    {
        uf_register_hip_offline_debug(priv);
    }
#endif

    /* Initialise the SME related threads and parameters */
    r = uf_sme_init(priv);
    if (r) {
        unifi_error(priv, "SME initialisation failed.\n");
        goto failed4;
    }

    /*
     * Run the userspace helper program (unififw) to perform
     * the device initialisation.
     */
    unifi_trace(priv, UDBG1, "run UniFi helper app...\n");
    r = uf_run_unifihelper(priv);
    if (r) {
        unifi_notice(priv, "unable to run UniFi helper app\n");
        /* Not a fatal error. */
    }

    up(&Unifi_instance_mutex);

    return priv;

failed4:
#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
if (log_hip_signals)
{
    uf_unregister_hip_offline_debug(priv);
}
#endif
#ifdef CSR_WIFI_RX_PATH_SPLIT
    flush_workqueue(priv->rx_workqueue);
    destroy_workqueue(priv->rx_workqueue);
failed3:
    signal_buffer_free(priv,CSR_WIFI_RX_SIGNAL_BUFFER_SIZE);
failed2:
#endif
    /* Remove the device nodes */
    uf_destroy_device_nodes(priv);
failed1:
    /* Deregister priv->netdev_client */
    ul_deregister_client(priv->netdev_client);

failed0:
    if (priv && priv->card) {
        unifi_coredump_free(priv->card);
        unifi_free_card(priv->card);
    }
    if (priv) {
        uf_free_netdevice(priv);
    }

    up(&Unifi_instance_mutex);

    return NULL;
} /* register_unifi_sdio() */
コード例 #16
0
int fingerprint_generator_create_display_string(fingerprint_generator *generator, char **display_string,
        const char *stable_identifier, ec_public_key *identity_key)
{
    int result = 0;
    char *result_string = 0;
    signal_buffer *identity_buffer = 0;
    signal_buffer *hash_buffer = 0;
    signal_buffer *hash_in_buffer = 0;
    signal_buffer *hash_out_buffer = 0;
    uint8_t *data = 0;
    size_t len = 0;
    uint8_t *in_data = 0;
    size_t in_len = 0;
    int i = 0;

    assert(generator);
    assert(stable_identifier);
    assert(identity_key);
    assert(generator->global_context->crypto_provider.sha512_digest_func);

    result = ec_public_key_serialize(&identity_buffer, identity_key);
    if(result < 0) {
        goto complete;
    }

    len = 2 + signal_buffer_len(identity_buffer) + strlen(stable_identifier);

    hash_buffer = signal_buffer_alloc(len);
    if(!hash_buffer) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    data = signal_buffer_data(hash_buffer);

    memset(data, 0, len);

    data[0] = 0;
    data[1] = (uint8_t)VERSION;
    memcpy(data + 2, signal_buffer_data(identity_buffer), signal_buffer_len(identity_buffer));
    memcpy(data + 2 + signal_buffer_len(identity_buffer), stable_identifier, strlen(stable_identifier));

    hash_in_buffer = signal_buffer_alloc(MAX(len, SHA512_DIGEST_LENGTH) + signal_buffer_len(identity_buffer));
    if(!hash_in_buffer) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    in_data = signal_buffer_data(hash_in_buffer);
    in_len = len + signal_buffer_len(identity_buffer);

    for(i = 0; i < generator->iterations; i++) {
        data = signal_buffer_data(hash_buffer);
        len = signal_buffer_len(hash_buffer);
        in_len = signal_buffer_len(hash_buffer) + signal_buffer_len(identity_buffer);
        memcpy(in_data, data, len);
        memcpy(in_data + len,
                signal_buffer_data(identity_buffer),
                signal_buffer_len(identity_buffer));

        result = signal_sha512_digest(generator->global_context,
                &hash_out_buffer, in_data, in_len);
        if(result < 0) {
            goto complete;
        }
        if(signal_buffer_len(hash_out_buffer) != SHA512_DIGEST_LENGTH) {
            result = SG_ERR_INVAL;
            goto complete;
        }

        signal_buffer_free(hash_buffer);
        hash_buffer = hash_out_buffer;
        hash_out_buffer = 0;
    }

    data = signal_buffer_data(hash_buffer);
    len = signal_buffer_len(hash_buffer);

    if(len < 30) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    result_string = malloc(31);
    if(!result_string) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    for(i = 0; i < 30; i += 5) {
        uint64_t chunk = ((uint64_t)data[i] & 0xFFL) << 32 |
                ((uint64_t)data[i + 1] & 0xFFL) << 24 |
                ((uint64_t)data[i + 2] & 0xFFL) << 16 |
                ((uint64_t)data[i + 3] & 0xFFL) << 8 |
                ((uint64_t)data[i + 4] & 0xFFL);
#if _WINDOWS
        sprintf_s(result_string + i, 6, "%05d", (int)(chunk % 100000));
#else
        snprintf(result_string + i, 6, "%05d", (int)(chunk % 100000));
#endif
    }

complete:
    signal_buffer_free(identity_buffer);
    signal_buffer_free(hash_buffer);
    signal_buffer_free(hash_in_buffer);
    signal_buffer_free(hash_out_buffer);
    if(result >= 0) {
        *display_string = result_string;
    }
    return result;
}
コード例 #17
0
int scannable_fingerprint_serialize(signal_buffer **buffer, const scannable_fingerprint *scannable)
{
    int result = 0;
    size_t result_size = 0;
    signal_buffer *result_buf = 0;
    Textsecure__CombinedFingerprint combined_fingerprint = TEXTSECURE__COMBINED_FINGERPRINT__INIT;
    Textsecure__FingerprintData local_fingerprint = TEXTSECURE__FINGERPRINT_DATA__INIT;
    Textsecure__FingerprintData remote_fingerprint = TEXTSECURE__FINGERPRINT_DATA__INIT;
    size_t len = 0;
    uint8_t *data = 0;

    combined_fingerprint.version = scannable->version;
    combined_fingerprint.has_version = 1;

    if(scannable->local_stable_identifier && scannable->local_identity_key) {
        signal_protocol_str_serialize_protobuf(&local_fingerprint.identifier, scannable->local_stable_identifier);
        local_fingerprint.has_identifier = 1;

        result = ec_public_key_serialize_protobuf(&local_fingerprint.publickey, scannable->local_identity_key);
        if(result < 0) {
            goto complete;
        }
        local_fingerprint.has_publickey = 1;

        combined_fingerprint.localfingerprint = &local_fingerprint;
    }

    if(scannable->remote_stable_identifier && scannable->remote_identity_key) {
        signal_protocol_str_serialize_protobuf(&remote_fingerprint.identifier, scannable->remote_stable_identifier);
        remote_fingerprint.has_identifier = 1;

        result = ec_public_key_serialize_protobuf(&remote_fingerprint.publickey, scannable->remote_identity_key);
        if(result < 0) {
            goto complete;
        }
        remote_fingerprint.has_publickey = 1;

        combined_fingerprint.remotefingerprint = &remote_fingerprint;
    }

    len = textsecure__combined_fingerprint__get_packed_size(&combined_fingerprint);

    result_buf = signal_buffer_alloc(len);
    if(!result_buf) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    data = signal_buffer_data(result_buf);
    result_size = textsecure__combined_fingerprint__pack(&combined_fingerprint, data);
    if(result_size != len) {
        signal_buffer_free(result_buf);
        result = SG_ERR_INVALID_PROTO_BUF;
        result_buf = 0;
        goto complete;
    }

complete:
    if(local_fingerprint.publickey.data) {
        free(local_fingerprint.publickey.data);
    }
    if(remote_fingerprint.publickey.data) {
        free(remote_fingerprint.publickey.data);
    }
    if(result >= 0) {
        *buffer = result_buf;
    }
    return result;
}
コード例 #18
0
int device_consistency_commitment_create(device_consistency_commitment **commitment,
        uint32_t generation, ec_public_key_list *identity_key_list,
        signal_context *global_context)
{
    static const char version[] = "DeviceConsistencyCommitment_V0";
    int result = 0;
    void *digest_context = 0;
    device_consistency_commitment *result_commitment = 0;
    ec_public_key_list *sorted_list = 0;
    uint8_t gen_data[4];
    unsigned int list_size;
    unsigned int i;

    result_commitment = malloc(sizeof(device_consistency_commitment));
    if(!result_commitment) {
        result = SG_ERR_NOMEM;
        goto complete;
    }
    memset(result_commitment, 0, sizeof(device_consistency_commitment));
    SIGNAL_INIT(result_commitment, device_consistency_commitment_destroy);

    sorted_list = ec_public_key_list_copy(identity_key_list);
    if(!sorted_list) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    ec_public_key_list_sort(sorted_list);

    result = signal_sha512_digest_init(global_context, &digest_context);
    if(result < 0) {
        goto complete;
    }

    result = signal_sha512_digest_update(global_context, digest_context,
            (uint8_t *)version, sizeof(version) - 1);
    if(result < 0) {
        goto complete;
    }

    gen_data[3] = (uint8_t)(generation);
    gen_data[2] = (uint8_t)(generation >> 8);
    gen_data[1] = (uint8_t)(generation >> 16);
    gen_data[0] = (uint8_t)(generation >> 24);

    result = signal_sha512_digest_update(global_context, digest_context,
            gen_data, sizeof(gen_data));
    if(result < 0) {
        goto complete;
    }

    list_size = ec_public_key_list_size(sorted_list);
    for(i = 0; i < list_size; i++) {
        signal_buffer *key_buffer = 0;
        ec_public_key *key = ec_public_key_list_at(sorted_list, i);

        result = ec_public_key_serialize(&key_buffer, key);
        if(result < 0) {
            goto complete;
        }

        result = signal_sha512_digest_update(global_context, digest_context,
                signal_buffer_data(key_buffer), signal_buffer_len(key_buffer));
        signal_buffer_free(key_buffer);
        if(result < 0) {
            goto complete;
        }
    }

    result_commitment->generation = generation;
    result = signal_sha512_digest_final(global_context, digest_context, &result_commitment->serialized);

complete:
    if(sorted_list) {
        ec_public_key_list_free(sorted_list);
    }
    if(digest_context) {
        signal_sha512_digest_cleanup(global_context, digest_context);
    }
    if(result >= 0) {
        *commitment = result_commitment;
    }
    else {
        SIGNAL_UNREF(result_commitment);
    }
    return result;
}
コード例 #19
0
int device_consistency_code_generate_for(device_consistency_commitment *commitment,
        device_consistency_signature_list *signatures,
        char **code_string,
        signal_context *global_context)
{
    int result = 0;
    char *result_string = 0;
    void *digest_context = 0;
    device_consistency_signature_list *sorted_list = 0;
    uint8_t version_data[2];
    signal_buffer *commitment_buffer;
    unsigned int list_size;
    unsigned int i;
    signal_buffer *hash_buffer = 0;
    uint8_t *data = 0;
    size_t len = 0;
    char *encoded_string = 0;

    sorted_list = device_consistency_signature_list_copy(signatures);
    if(!sorted_list) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    device_consistency_signature_list_sort(sorted_list);

    result = signal_sha512_digest_init(global_context, &digest_context);
    if(result < 0) {
        goto complete;
    }

    version_data[1] = (uint8_t)(CODE_VERSION);
    version_data[0] = (uint8_t)(CODE_VERSION >> 8);

    result = signal_sha512_digest_update(global_context, digest_context,
            version_data, sizeof(version_data));
    if(result < 0) {
        goto complete;
    }

    commitment_buffer = device_consistency_commitment_get_serialized(commitment);
    result = signal_sha512_digest_update(global_context, digest_context,
            signal_buffer_data(commitment_buffer),
            signal_buffer_len(commitment_buffer));
    if(result < 0) {
        goto complete;
    }

    list_size = device_consistency_signature_list_size(sorted_list);
    for(i = 0; i < list_size; i++) {
        device_consistency_signature *signature = device_consistency_signature_list_at(sorted_list, i);
        signal_buffer *vrf_output = device_consistency_signature_get_vrf_output(signature);

        result = signal_sha512_digest_update(global_context, digest_context,
                signal_buffer_data(vrf_output),
                signal_buffer_len(vrf_output));
        if(result < 0) {
            goto complete;
        }
    }

    result = signal_sha512_digest_final(global_context, digest_context, &hash_buffer);
    if(result < 0) {
        goto complete;
    }

    data = signal_buffer_data(hash_buffer);
    len = signal_buffer_len(hash_buffer);

    if(len < 10) {
        result = SG_ERR_UNKNOWN;
        goto complete;
    }

    encoded_string = malloc(11);
    if(!encoded_string) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    for(i = 0; i < 10; i += 5) {
        uint64_t chunk = ((uint64_t)data[i] & 0xFFL) << 32 |
                ((uint64_t)data[i + 1] & 0xFFL) << 24 |
                ((uint64_t)data[i + 2] & 0xFFL) << 16 |
                ((uint64_t)data[i + 3] & 0xFFL) << 8 |
                ((uint64_t)data[i + 4] & 0xFFL);
#if _WINDOWS
        sprintf_s(encoded_string + i, 6, "%05d", (int)(chunk % 100000));
#else
        snprintf(encoded_string + i, 6, "%05d", (int)(chunk % 100000));
#endif
    }

    result_string = malloc(7);
    if(!result_string) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    memcpy(result_string, encoded_string, 6);
    result_string[6] = '\0';

complete:
    if(sorted_list) {
        device_consistency_signature_list_free(sorted_list);
    }
    if(digest_context) {
        signal_sha512_digest_cleanup(global_context, digest_context);
    }
    signal_buffer_free(hash_buffer);
    free(encoded_string);
    if(result >= 0) {
        *code_string = result_string;
    }
    return result;
}
コード例 #20
0
void device_consistency_commitment_destroy(signal_type_base *type)
{
    device_consistency_commitment *commitment = (device_consistency_commitment *)type;
    signal_buffer_free(commitment->serialized);
    free(commitment);
}
コード例 #21
0
int device_consistency_message_create_from_serialized(device_consistency_message **message,
        device_consistency_commitment *commitment,
        const uint8_t *serialized_data, size_t serialized_len,
        ec_public_key *identity_key,
        signal_context *global_context)
{
    int result = 0;
    device_consistency_message *result_message = 0;
    Textsecure__DeviceConsistencyCodeMessage *message_structure = 0;
    signal_buffer *commitment_buffer = 0;
    signal_buffer *vrf_output_buffer = 0;

    /* Create message instance */
    result = device_consistency_message_create(&result_message);
    if(result < 0) {
        goto complete;
    }

    /* Deserialize the message */
    message_structure = textsecure__device_consistency_code_message__unpack(0, serialized_len, serialized_data);
    if(!message_structure) {
        result = SG_ERR_INVALID_PROTO_BUF;
        goto complete;
    }

    if(!message_structure->has_generation || !message_structure->has_signature) {
        result = SG_ERR_INVALID_PROTO_BUF;
        goto complete;
    }

    /* Verify VRF signature */
    commitment_buffer = device_consistency_commitment_get_serialized(commitment);
    result = curve_verify_vrf_signature(global_context, &vrf_output_buffer,
            identity_key,
            signal_buffer_data(commitment_buffer), signal_buffer_len(commitment_buffer),
            message_structure->signature.data, message_structure->signature.len);
    if(result < 0) {
        goto complete;
    }

    /* Assign the message fields */
    result_message->generation = message_structure->generation;

    result = device_consistency_signature_create(&result_message->signature,
            message_structure->signature.data, message_structure->signature.len,
            signal_buffer_data(vrf_output_buffer), signal_buffer_len(vrf_output_buffer));
    if(result < 0) {
        goto complete;
    }

    result_message->serialized = signal_buffer_create(serialized_data, serialized_len);
    if(!result_message->serialized) {
        result = SG_ERR_NOMEM;
    }

complete:
    if(message_structure) {
        textsecure__device_consistency_code_message__free_unpacked(message_structure, 0);
    }
    signal_buffer_free(vrf_output_buffer);
    if(result >= 0) {
        *message = result_message;
    }
    else {
        SIGNAL_UNREF(result_message);
    }
    if(result == SG_ERR_INVALID_PROTO_BUF
            || result == SG_ERR_INVALID_KEY
            || result == SG_ERR_VRF_SIG_VERIF_FAILED) {
        result = SG_ERR_INVALID_MESSAGE;
    }
    return result;
}
コード例 #22
0
int device_consistency_message_create_from_pair(device_consistency_message **message,
        device_consistency_commitment *commitment,
        ec_key_pair *identity_key_pair,
        signal_context *global_context)
{
    int result = 0;
    device_consistency_message *result_message = 0;
    signal_buffer *commitment_buffer = 0;
    signal_buffer *signature_buffer = 0;
    signal_buffer *vrf_output_buffer = 0;
    signal_buffer *serialized_signature_buffer = 0;
    Textsecure__DeviceConsistencyCodeMessage message_structure = TEXTSECURE__DEVICE_CONSISTENCY_CODE_MESSAGE__INIT;
    size_t len = 0;
    uint8_t *data = 0;
    size_t result_size = 0;

    /* Create message instance */
    result = device_consistency_message_create(&result_message);
    if(result < 0) {
        goto complete;
    }

    /* Calculate VRF signature */
    commitment_buffer = device_consistency_commitment_get_serialized(commitment);
    result = curve_calculate_vrf_signature(global_context, &signature_buffer,
            ec_key_pair_get_private(identity_key_pair),
            signal_buffer_data(commitment_buffer), signal_buffer_len(commitment_buffer));
    if(result < 0) {
        goto complete;
    }

    /* Verify VRF signature */
    result = curve_verify_vrf_signature(global_context, &vrf_output_buffer,
            ec_key_pair_get_public(identity_key_pair),
            signal_buffer_data(commitment_buffer), signal_buffer_len(commitment_buffer),
            signal_buffer_data(signature_buffer), signal_buffer_len(signature_buffer));
    if(result < 0) {
        goto complete;
    }

    result_message->generation = device_consistency_commitment_get_generation(commitment);

    /* Create and assign the signature */
    result = device_consistency_signature_create(&result_message->signature,
            signal_buffer_data(signature_buffer), signal_buffer_len(signature_buffer),
            signal_buffer_data(vrf_output_buffer), signal_buffer_len(vrf_output_buffer));
    if(result < 0) {
        goto complete;
    }

    serialized_signature_buffer = device_consistency_signature_get_signature(result_message->signature);

    /* Serialize the message */
    message_structure.generation = device_consistency_commitment_get_generation(commitment);
    message_structure.has_generation = 1;
    message_structure.signature.data = signal_buffer_data(serialized_signature_buffer);
    message_structure.signature.len = signal_buffer_len(serialized_signature_buffer);
    message_structure.has_signature = 1;

    len = textsecure__device_consistency_code_message__get_packed_size(&message_structure);
    result_message->serialized = signal_buffer_alloc(len);
    if(!result_message->serialized) {
        result = SG_ERR_NOMEM;
        goto complete;
    }

    data = signal_buffer_data(result_message->serialized);

    result_size = textsecure__device_consistency_code_message__pack(&message_structure, data);
    if(result_size != len) {
        result = SG_ERR_INVALID_PROTO_BUF;
        goto complete;
    }

complete:
    signal_buffer_free(signature_buffer);
    signal_buffer_free(vrf_output_buffer);
    if(result >= 0) {
        *message = result_message;
    }
    else {
        SIGNAL_UNREF(result_message);
    }
    if(result == SG_ERR_INVALID_KEY || result == SG_ERR_VRF_SIG_VERIF_FAILED) {
        result = SG_ERR_UNKNOWN;
    }
    return result;
}