Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions toxcore/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,19 @@ cc_library(
],
)

cc_library(
name = "crypto_core_pack",
srcs = ["crypto_core_pack.c"],
hdrs = ["crypto_core_pack.h"],
visibility = ["//c-toxcore:__subpackages__"],
deps = [
":attributes",
":bin_pack",
":bin_unpack",
":crypto_core",
],
)

cc_library(
name = "crypto_core_test_util",
testonly = True,
Expand Down Expand Up @@ -920,6 +933,7 @@ cc_library(
":bin_unpack",
":ccompat",
":crypto_core",
":crypto_core_pack",
":forwarding",
":friend_connection",
":friend_requests",
Expand Down
6 changes: 3 additions & 3 deletions toxcore/Messenger.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ bool m_create_group_connection(Messenger *m, GC_Chat *chat)
const int onion_friend_number = friend_conn_get_onion_friendnum(connection);
Onion_Friend *onion_friend = onion_get_friend(m->onion_c, (uint16_t)onion_friend_number);

onion_friend_set_gc_public_key(onion_friend, get_chat_id(chat->chat_public_key));
onion_friend_set_gc_public_key(onion_friend, get_chat_id(&chat->chat_public_key));
onion_friend_set_gc_data(onion_friend, nullptr, 0);

return true;
Expand Down Expand Up @@ -2594,8 +2594,8 @@ static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend
memcpy(&announce.base_announce.ip_port, &chat->self_ip_port, sizeof(IP_Port));
}

memcpy(announce.base_announce.peer_public_key, chat->self_public_key, ENC_PUBLIC_KEY_SIZE);
memcpy(announce.chat_public_key, get_chat_id(chat->chat_public_key), ENC_PUBLIC_KEY_SIZE);
announce.base_announce.peer_public_key = chat->self_public_key.enc;
announce.chat_public_key = chat->chat_public_key.enc;

uint8_t gc_data[GCA_MAX_DATA_LENGTH];
const int length = gca_pack_public_announce(m->log, gc_data, GCA_MAX_DATA_LENGTH, &announce);
Expand Down
38 changes: 20 additions & 18 deletions toxcore/crypto_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,43 +45,45 @@ static_assert(CRYPTO_SIGN_PUBLIC_KEY_SIZE == crypto_sign_PUBLICKEYBYTES,
static_assert(CRYPTO_SIGN_SECRET_KEY_SIZE == crypto_sign_SECRETKEYBYTES,
"CRYPTO_SIGN_SECRET_KEY_SIZE should be equal to crypto_sign_SECRETKEYBYTES");

bool create_extended_keypair(uint8_t pk[EXT_PUBLIC_KEY_SIZE], uint8_t sk[EXT_SECRET_KEY_SIZE])
bool create_extended_keypair(Extended_Public_Key *pk, Extended_Secret_Key *sk, const Random *rng)
{
/* create signature key pair */
crypto_sign_keypair(pk + ENC_PUBLIC_KEY_SIZE, sk + ENC_SECRET_KEY_SIZE);
uint8_t seed[crypto_sign_SEEDBYTES];
random_bytes(rng, seed, crypto_sign_SEEDBYTES);
crypto_sign_seed_keypair(pk->sig.data, sk->sig.data, seed);

/* convert public signature key to public encryption key */
const int res1 = crypto_sign_ed25519_pk_to_curve25519(pk, pk + ENC_PUBLIC_KEY_SIZE);
const int res1 = crypto_sign_ed25519_pk_to_curve25519(pk->enc.data, pk->sig.data);

/* convert secret signature key to secret encryption key */
const int res2 = crypto_sign_ed25519_sk_to_curve25519(sk, sk + ENC_SECRET_KEY_SIZE);
const int res2 = crypto_sign_ed25519_sk_to_curve25519(sk->enc.data, sk->sig.data);

return res1 == 0 && res2 == 0;
}

const uint8_t *get_enc_key(const uint8_t *key)
const uint8_t *get_enc_key(const Extended_Public_Key *key)
{
return key;
return key->enc.data;
}

const uint8_t *get_sig_pk(const uint8_t *key)
const uint8_t *get_sig_pk(const Extended_Public_Key *key)
{
return key + ENC_PUBLIC_KEY_SIZE;
return key->sig.data;
}

void set_sig_pk(uint8_t *key, const uint8_t *sig_pk)
void set_sig_pk(Extended_Public_Key *key, const uint8_t *sig_pk)
{
memcpy(key + ENC_PUBLIC_KEY_SIZE, sig_pk, SIG_PUBLIC_KEY_SIZE);
memcpy(key->sig.data, sig_pk, SIG_PUBLIC_KEY_SIZE);
}

const uint8_t *get_sig_sk(const uint8_t *key)
const uint8_t *get_sig_sk(const Extended_Secret_Key *key)
{
return key + ENC_SECRET_KEY_SIZE;
return key->sig.data;
}

const uint8_t *get_chat_id(const uint8_t *key)
const uint8_t *get_chat_id(const Extended_Public_Key *key)
{
return key + ENC_PUBLIC_KEY_SIZE;
return key->sig.data;
}

#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
Expand Down Expand Up @@ -207,16 +209,16 @@ uint32_t random_range_u32(const Random *rng, uint32_t upper_bound)

bool crypto_signature_create(uint8_t signature[CRYPTO_SIGNATURE_SIZE],
const uint8_t *message, uint64_t message_length,
const uint8_t secret_key[SIG_SECRET_KEY_SIZE])
const Sign_Secret_Key *secret_key)
{
return crypto_sign_detached(signature, nullptr, message, message_length, secret_key) == 0;
return crypto_sign_detached(signature, nullptr, message, message_length, secret_key->data) == 0;
}

bool crypto_signature_verify(const uint8_t signature[CRYPTO_SIGNATURE_SIZE],
const uint8_t *message, uint64_t message_length,
const uint8_t public_key[SIG_PUBLIC_KEY_SIZE])
const Sign_Public_Key *public_key)
{
return crypto_sign_verify_detached(signature, message, message_length, public_key) == 0;
return crypto_sign_verify_detached(signature, message, message_length, public_key->data) == 0;
}

bool public_key_valid(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE])
Expand Down
43 changes: 35 additions & 8 deletions toxcore/crypto_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,32 @@ const Random *os_random(void);
*/
#define CRYPTO_HMAC_KEY_SIZE 32

typedef struct Public_Key {
uint8_t data[CRYPTO_PUBLIC_KEY_SIZE];
} Public_Key;

typedef struct Secret_Key {
uint8_t data[CRYPTO_SECRET_KEY_SIZE];
} Secret_Key;

typedef struct Sign_Public_Key {
uint8_t data[CRYPTO_SIGN_PUBLIC_KEY_SIZE];
} Sign_Public_Key;

typedef struct Sign_Secret_Key {
uint8_t data[CRYPTO_SIGN_SECRET_KEY_SIZE];
} Sign_Secret_Key;

typedef struct Extended_Public_Key {
Public_Key enc;
Sign_Public_Key sig;
} Extended_Public_Key;

typedef struct Extended_Secret_Key {
Secret_Key enc;
Sign_Secret_Key sig;
} Extended_Secret_Key;

/**
* @brief A `bzero`-like function which won't be optimised away by the compiler.
*
Expand Down Expand Up @@ -285,7 +311,7 @@ uint32_t random_range_u32(const Random *rng, uint32_t upper_bound);
non_null()
bool crypto_signature_create(uint8_t signature[CRYPTO_SIGNATURE_SIZE],
const uint8_t *message, uint64_t message_length,
const uint8_t secret_key[SIG_SECRET_KEY_SIZE]);
const Sign_Secret_Key *secret_key);

/** @brief Verifies that the given signature was produced by a given message and public key.
*
Expand All @@ -300,7 +326,7 @@ bool crypto_signature_create(uint8_t signature[CRYPTO_SIGNATURE_SIZE],
non_null()
bool crypto_signature_verify(const uint8_t signature[CRYPTO_SIGNATURE_SIZE],
const uint8_t *message, uint64_t message_length,
const uint8_t public_key[SIG_PUBLIC_KEY_SIZE]);
const Sign_Public_Key *public_key);

/**
* @brief Fill the given nonce with random bytes.
Expand Down Expand Up @@ -333,18 +359,19 @@ bool public_key_valid(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]);
*
* @param[out] pk The buffer where the public key will be stored. Must have room for EXT_PUBLIC_KEY_SIZE bytes.
* @param[out] sk The buffer where the secret key will be stored. Must have room for EXT_SECRET_KEY_SIZE bytes.
* @param rng The random number generator to use for the key generator seed.
*
* @retval true on success.
*/
non_null()
bool create_extended_keypair(uint8_t pk[EXT_PUBLIC_KEY_SIZE], uint8_t sk[EXT_SECRET_KEY_SIZE]);
bool create_extended_keypair(Extended_Public_Key *pk, Extended_Secret_Key *sk, const Random *rng);

/** Functions for groupchat extended keys */
non_null() const uint8_t *get_enc_key(const uint8_t *key);
non_null() const uint8_t *get_sig_pk(const uint8_t *key);
non_null() void set_sig_pk(uint8_t *key, const uint8_t *sig_pk);
non_null() const uint8_t *get_sig_sk(const uint8_t *key);
non_null() const uint8_t *get_chat_id(const uint8_t *key);
non_null() const uint8_t *get_enc_key(const Extended_Public_Key *key);
non_null() const uint8_t *get_sig_pk(const Extended_Public_Key *key);
non_null() void set_sig_pk(Extended_Public_Key *key, const uint8_t *sig_pk);
non_null() const uint8_t *get_sig_sk(const Extended_Secret_Key *key);
non_null() const uint8_t *get_chat_id(const Extended_Public_Key *key);

/**
* @brief Generate a new random keypair.
Expand Down
58 changes: 58 additions & 0 deletions toxcore/crypto_core_pack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2024 The TokTok team.
* Copyright © 2013 Tox project.
*/

#include "crypto_core_pack.h"

#include <string.h>

#include "crypto_core.h"
#include "bin_pack.h"
#include "bin_unpack.h"

bool pack_extended_public_key(const Extended_Public_Key *key, Bin_Pack *bp)
{
uint8_t ext_key[EXT_PUBLIC_KEY_SIZE];
memcpy(ext_key, key->enc.data, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(ext_key + CRYPTO_PUBLIC_KEY_SIZE, key->sig.data, CRYPTO_SIGN_PUBLIC_KEY_SIZE);

return bin_pack_bin(bp, ext_key, EXT_PUBLIC_KEY_SIZE);
}

bool pack_extended_secret_key(const Extended_Secret_Key *key, Bin_Pack *bp)
{
uint8_t ext_key[EXT_SECRET_KEY_SIZE];
memcpy(ext_key, key->enc.data, CRYPTO_SECRET_KEY_SIZE);
memcpy(ext_key + CRYPTO_SECRET_KEY_SIZE, key->sig.data, CRYPTO_SIGN_SECRET_KEY_SIZE);

return bin_pack_bin(bp, ext_key, EXT_SECRET_KEY_SIZE);
}

bool unpack_extended_public_key(Extended_Public_Key *key, Bin_Unpack *bu)
{
uint8_t ext_key[EXT_PUBLIC_KEY_SIZE];

if (!bin_unpack_bin_fixed(bu, ext_key, EXT_PUBLIC_KEY_SIZE)) {
return false;
}

memcpy(key->enc.data, ext_key, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(key->sig.data, ext_key + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_SIGN_PUBLIC_KEY_SIZE);

return true;
}

bool unpack_extended_secret_key(Extended_Secret_Key *key, Bin_Unpack *bu)
{
uint8_t ext_key[EXT_SECRET_KEY_SIZE];

if (!bin_unpack_bin_fixed(bu, ext_key, EXT_SECRET_KEY_SIZE)) {
return false;
}

memcpy(key->enc.data, ext_key, CRYPTO_SECRET_KEY_SIZE);
memcpy(key->sig.data, ext_key + CRYPTO_SECRET_KEY_SIZE, CRYPTO_SIGN_SECRET_KEY_SIZE);

return true;
}
31 changes: 31 additions & 0 deletions toxcore/crypto_core_pack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2024 The TokTok team.
* Copyright © 2013 Tox project.
*/

#ifndef C_TOXCORE_TOXCORE_CRYPTO_CORE_PACK_H
#define C_TOXCORE_TOXCORE_CRYPTO_CORE_PACK_H

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "attributes.h"
#include "bin_pack.h"
#include "bin_unpack.h"
#include "crypto_core.h"

#ifdef __cplusplus
extern "C" {
#endif

non_null() bool pack_extended_public_key(const Extended_Public_Key *key, Bin_Pack *bp);
non_null() bool pack_extended_secret_key(const Extended_Secret_Key *key, Bin_Pack *bp);
non_null() bool unpack_extended_public_key(Extended_Public_Key *key, Bin_Unpack *bu);
non_null() bool unpack_extended_secret_key(Extended_Secret_Key *key, Bin_Unpack *bu);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* C_TOXCORE_TOXCORE_CRYPTO_CORE_H */
16 changes: 7 additions & 9 deletions toxcore/crypto_core_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ namespace {
using HmacKey = std::array<uint8_t, CRYPTO_HMAC_KEY_SIZE>;
using Hmac = std::array<uint8_t, CRYPTO_HMAC_SIZE>;
using SecretKey = std::array<uint8_t, CRYPTO_SECRET_KEY_SIZE>;
using ExtPublicKey = std::array<uint8_t, EXT_PUBLIC_KEY_SIZE>;
using ExtSecretKey = std::array<uint8_t, EXT_SECRET_KEY_SIZE>;
using Signature = std::array<uint8_t, CRYPTO_SIGNATURE_SIZE>;
using Nonce = std::array<uint8_t, CRYPTO_NONCE_SIZE>;

Expand Down Expand Up @@ -72,21 +70,21 @@ TEST(CryptoCore, Signatures)
{
Test_Random rng;

ExtPublicKey pk;
ExtSecretKey sk;
Extended_Public_Key pk;
Extended_Secret_Key sk;

EXPECT_TRUE(create_extended_keypair(pk.data(), sk.data()));
EXPECT_TRUE(create_extended_keypair(&pk, &sk, rng));

std::vector<uint8_t> message{0};
message.clear();

// Try a few different sizes, including empty 0 length message.
for (uint8_t i = 0; i < 100; ++i) {
Signature signature;
EXPECT_TRUE(crypto_signature_create(
signature.data(), message.data(), message.size(), get_sig_sk(sk.data())));
EXPECT_TRUE(crypto_signature_verify(
signature.data(), message.data(), message.size(), get_sig_pk(pk.data())));
EXPECT_TRUE(
crypto_signature_create(signature.data(), message.data(), message.size(), &sk.sig));
EXPECT_TRUE(
crypto_signature_verify(signature.data(), message.data(), message.size(), &pk.sig));

message.push_back(random_u08(rng));
}
Expand Down
Loading