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); } }
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); }
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; }
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; }