Improve documentation of crypto_core.

This commit is contained in:
iphydf
2016-12-19 15:27:46 +00:00
parent ce29c8e7ec
commit 2328cb74ab
10 changed files with 264 additions and 148 deletions
+7 -3
View File
@@ -2,13 +2,13 @@
#include "config.h"
#endif
#include <sys/param.h>
#include <time.h>
#include "helpers.h"
#include "../toxcore/DHT.c"
#include "../toxcore/tox.h"
#include "helpers.h"
#include <sys/param.h>
#include <time.h>
// These tests currently fail.
@@ -299,6 +299,10 @@ static void test_addto_lists_good(DHT *dht,
ck_assert_msg(client_in_list(list, length, public_key) == -1, "Good client id is in the list");
}
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
static void test_addto_lists(IP ip)
{
Networking_Core *net = new_networking(NULL, ip, TOX_PORT_DEFAULT);
+22 -12
View File
@@ -14,18 +14,27 @@
#include "config.h"
#endif
#include "helpers.h"
#include "../testing/misc_tools.c" // hex_string_to_bin
#include "../toxcore/Messenger.h"
#include <check.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include "helpers.h"
#if VANILLA_NACL
#include <crypto_box.h> // crypto_box_PUBLICKEYBYTES and other defines.
#else
#include <sodium.h>
#endif
#define REALLY_BIG_NUMBER ((1) << (sizeof(uint16_t) * 7))
#define STRINGS_EQUAL(X, Y) (strcmp(X, Y) == 0)
static bool enable_broken_tests = false;
static const char *friend_id_str = "e4b3d5030bc99494605aecc33ceec8875640c1d74aa32790e821b17e98771c4a00000000f1db";
/* in case we need more than one ID for a test */
@@ -121,11 +130,10 @@ START_TEST(test_m_delfriend)
}
END_TEST
#if 0
START_TEST(test_m_addfriend)
{
char *good_data = "test";
char *bad_data = "";
const char *good_data = "test";
const char *bad_data = "";
int good_len = strlen(good_data);
int bad_len = strlen(bad_data);
@@ -134,30 +142,29 @@ START_TEST(test_m_addfriend)
+ crypto_box_ZEROBYTES + 100);
/* TODO(irungentoo): Update this properly to latest master */
if (m_addfriend(m, (uint8_t *)friend_id, (uint8_t *)good_data, really_bad_len) != FAERR_TOOLONG) {
if (m_addfriend(m, (const uint8_t *)friend_id, (const uint8_t *)good_data, really_bad_len) != FAERR_TOOLONG) {
ck_abort_msg("m_addfriend did NOT catch the following length: %d\n", really_bad_len);
}
/* this will return an error if the original m_addfriend_norequest() failed */
if (m_addfriend(m, (uint8_t *)friend_id, (uint8_t *)good_data, good_len) != FAERR_ALREADYSENT) {
if (m_addfriend(m, (const uint8_t *)friend_id, (const uint8_t *)good_data, good_len) != FAERR_ALREADYSENT) {
ck_abort_msg("m_addfriend did NOT catch adding a friend we already have.\n"
"(this can be caused by the error of m_addfriend_norequest in"
" the beginning of the suite)\n");
}
if (m_addfriend(m, (uint8_t *)good_id_b, (uint8_t *)bad_data, bad_len) != FAERR_NOMESSAGE) {
if (m_addfriend(m, (const uint8_t *)good_id_b, (const uint8_t *)bad_data, bad_len) != FAERR_NOMESSAGE) {
ck_abort_msg("m_addfriend did NOT catch the following length: %d\n", bad_len);
}
/* this should REALLY return an error */
/* TODO(irungentoo): validate client_id in m_addfriend? */
if (m_addfriend((uint8_t *)bad_id, (uint8_t *)good_data, good_len) >= 0) {
if (m_addfriend(m, (const uint8_t *)bad_id, (const uint8_t *)good_data, good_len) >= 0) {
ck_abort_msg("The following ID passed through "
"m_addfriend without an error:\n'%s'\n", bad_id_str);
}
}
END_TEST
#endif
START_TEST(test_setname)
{
@@ -193,7 +200,7 @@ END_TEST
* ideas:
* if we have access to the friends list, we could
* just add a status manually ourselves. */
/*
#if 0
START_TEST(test_m_copy_userstatus)
{
assert(m_copy_userstatus(-1, buf, MAX_USERSTATUS_LENGTH) == -1);
@@ -203,7 +210,7 @@ START_TEST(test_m_copy_userstatus)
assert(STRINGS_EQUAL(name_buf, friend_id_status));
}
END_TEST
*/
#endif
START_TEST(test_getname)
{
@@ -316,7 +323,10 @@ static Suite *messenger_suite(void)
DEFTESTCASE(m_get_userstatus_size);
DEFTESTCASE(m_set_userstatus);
/* DEFTESTCASE(m_addfriend); */
if (enable_broken_tests) {
DEFTESTCASE(m_addfriend);
}
DEFTESTCASE(m_friend_exists);
DEFTESTCASE(m_get_friend_connectionstatus);
DEFTESTCASE(m_delfriend);
+2 -1
View File
@@ -20,7 +20,8 @@
#include "../toxcore/util.h"
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#include <windows.h>
#define c_sleep(x) Sleep(1*x)
#else
#include <unistd.h>
+2 -1
View File
@@ -19,7 +19,8 @@
#include "../toxcore/tox.h"
#include "../toxcore/util.h"
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#include <windows.h>
#define c_sleep(x) Sleep(1*x)
#else
#include <pthread.h>
+2 -2
View File
@@ -197,7 +197,7 @@ int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_ke
uint8_t *nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
random_nonce(nonce);
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; // TODO(irungentoo): sodium_memzero before exit function
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; // TODO(irungentoo): crypto_memzero before exit function
memcpy(temp + 1, data, length);
temp[0] = request_id;
int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1,
@@ -238,7 +238,7 @@ int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_ke
memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
const uint8_t *nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; // TODO(irungentoo): sodium_memzero before exit function
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; // TODO(irungentoo): crypto_memzero before exit function
int len1 = decrypt_data(public_key, self_secret_key, nonce,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE,
length - (CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE + 1), temp);
+113 -55
View File
@@ -21,10 +21,12 @@
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CORE_CRYPTO_H
#define CORE_CRYPTO_H
#ifndef CRYPTO_CORE_H
#define CRYPTO_CORE_H
#include "network.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
%}
/**
@@ -38,12 +40,12 @@ const CRYPTO_PUBLIC_KEY_SIZE = 32;
const CRYPTO_SECRET_KEY_SIZE = 32;
/**
* The number of bytes in a shared key computed from public and secret key.
* The number of bytes in a shared key computed from public and secret keys.
*/
const CRYPTO_SHARED_KEY_SIZE = 32;
/**
* The number of bytes in a random symmetric key.
* The number of bytes in a symmetric key.
*/
const CRYPTO_SYMMETRIC_KEY_SIZE = CRYPTO_SHARED_KEY_SIZE;
@@ -68,20 +70,44 @@ const CRYPTO_SHA256_SIZE = 32;
*/
const CRYPTO_SHA512_SIZE = 64;
/**
* A `memcmp`-like function whose running time does not depend on the input
* bytes, only on the input length. Useful to compare sensitive data where
* timing attacks could reveal that data.
*
* This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and
* "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may
* take 1 time, because it immediately knows that the two strings are not equal.
*/
static int32_t crypto_memcmp(const void *p1, const void *p2, size_t length);
static void crypto_memzero(void *data, size_t length);
static void crypto_sha256(uint8_t *hash, const uint8_t[length] data);
static void crypto_sha512(uint8_t *hash, const uint8_t[length] data);
static void crypto_derive_public_key(uint8_t *public_key, uint8_t *secret_key);
/**
* compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to timing attacks.
* returns 0 if both mem locations of length are equal,
* return -1 if they are not.
* A `bzero`-like function which won't be optimised away by the compiler. Some
* compilers will inline `bzero` or `memset` if they can prove that there will
* be no reads to the written data. Use this function if you want to be sure the
* memory is indeed zeroed.
*/
static int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2);
static void crypto_memzero(void *data, size_t length);
/**
* Compute a SHA256 hash (32 bytes).
*/
static void crypto_sha256(uint8_t[CRYPTO_SHA256_SIZE] hash, const uint8_t[length] data);
/**
* Compute a SHA512 hash (64 bytes).
*/
static void crypto_sha512(uint8_t[CRYPTO_SHA512_SIZE] hash, const uint8_t[length] data);
/**
* Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
* timing attacks.
*
* @return 0 if both mem locations of length are equal, -1 if they are not.
*/
static int32_t public_key_cmp(
const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk1,
const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk2);
/**
* Return a random 32 bit integer.
@@ -94,88 +120,120 @@ static uint32_t random_int();
static uint64_t random_64b();
/**
* Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not.
* This should only be used for input validation.
* Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This
* should only be used for input validation.
*
* return 0 if it isn't.
* return 1 if it is.
* @return false if it isn't, true if it is.
*/
static int32_t public_key_valid(const uint8_t *public_key);
static int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key);
static bool public_key_valid(const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key);
/**
* Encrypts plain of length length to encrypted of length + 16 using the
* public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce.
* Generate a new random keypair. Every call to this function is likely to
* generate a different keypair.
*/
static int32_t crypto_new_keypair(
uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key);
/**
* Derive the public key from a given secret key.
*/
static void crypto_derive_public_key(
uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key);
/**
* Encrypt plain text of the given length to encrypted of length +
* $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of the
* receiver and the secret key of the sender and a $CRYPTO_NONCE_SIZE byte
* nonce.
*
* return -1 if there was a problem.
* return length of encrypted data if everything was fine.
* @return -1 if there was a problem, length of encrypted data if everything
* was fine.
*/
static int32_t encrypt_data(
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
const uint8_t *plain, uint32_t length, uint8_t *encrypted);
const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
const uint8_t[CRYPTO_NONCE_SIZE] nonce,
const uint8_t[length] plain,
uint8_t *encrypted);
/**
* Decrypts encrypted of length length to plain of length length - 16 using the
* public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce.
* Decrypt encrypted text of the given length to plain text of the given length
* - $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of
* the sender, the secret key of the receiver and a $CRYPTO_NONCE_SIZE byte
* nonce.
*
* return -1 if there was a problem (decryption failed).
* return length of plain data if everything was fine.
* @return -1 if there was a problem (decryption failed), length of plain text
* data if everything was fine.
*/
static int32_t decrypt_data(
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
const uint8_t *encrypted, uint32_t length, uint8_t *plain);
const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
const uint8_t[CRYPTO_NONCE_SIZE] nonce,
const uint8_t[length] encrypted,
uint8_t *plain);
/**
* Fast encrypt/decrypt operations. Use if this is not a one-time communication.
* encrypt_precompute does the shared-key generation once so it does not have
* $encrypt_precompute does the shared-key generation once so it does not have
* to be preformed on every encrypt/decrypt.
*/
static int32_t encrypt_precompute(
const uint8_t *public_key, const uint8_t *secret_key, uint8_t *enc_key);
const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key);
/**
* Encrypts plain of length length to encrypted of length + 16 using a
* secret key CRYPTO_SYMMETRIC_KEY_SIZE big and a 24 byte nonce.
* Encrypts plain of length length to encrypted of length + $CRYPTO_MAC_SIZE
* using a shared key $CRYPTO_SYMMETRIC_KEY_SIZE big and a $CRYPTO_NONCE_SIZE
* byte nonce.
*
* return -1 if there was a problem.
* return length of encrypted data if everything was fine.
* @return -1 if there was a problem, length of encrypted data if everything
* was fine.
*/
static int32_t encrypt_data_symmetric(
const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain,
uint32_t length, uint8_t *encrypted);
const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key,
const uint8_t[CRYPTO_NONCE_SIZE] nonce,
const uint8_t[length] plain,
uint8_t *encrypted);
/**
* Decrypts encrypted of length length to plain of length length - 16 using a
* secret key CRYPTO_SYMMETRIC_KEY_SIZE big and a 24 byte nonce.
* Decrypts encrypted of length length to plain of length length -
* $CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a
* $CRYPTO_NONCE_SIZE byte nonce.
*
* return -1 if there was a problem (decryption failed).
* return length of plain data if everything was fine.
* @return -1 if there was a problem (decryption failed), length of plain data
* if everything was fine.
*/
static int32_t decrypt_data_symmetric(
const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted,
uint32_t length, uint8_t *plain);
const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key,
const uint8_t[CRYPTO_NONCE_SIZE] nonce,
const uint8_t[length] encrypted,
uint8_t *plain);
/**
* Increment the given nonce by 1.
* Increment the given nonce by 1 in big endian (rightmost byte incremented
* first).
*/
static void increment_nonce(uint8_t *nonce);
static void increment_nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce);
/**
* Increment the given nonce by num.
* Increment the given nonce by a given number. The number should be in host
* byte order.
*/
static void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num);
static void increment_nonce_number(uint8_t[CRYPTO_NONCE_SIZE] nonce, uint32_t host_order_num);
/**
* Fill the given nonce with random bytes.
*/
static void random_nonce(uint8_t *nonce);
static void random_nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce);
/**
* Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.
*/
static void new_symmetric_key(uint8_t *key);
static void new_symmetric_key(uint8_t[CRYPTO_SYMMETRIC_KEY_SIZE] key);
/**
* Fill an array of bytes with random values.
@@ -183,5 +241,5 @@ static void new_symmetric_key(uint8_t *key);
static void random_bytes(uint8_t[length] bytes);
%{
#endif
#endif /* CRYPTO_CORE_H */
%}
+31 -30
View File
@@ -29,6 +29,10 @@
#include "crypto_core.h"
#include "network.h"
#include <string.h>
#ifndef VANILLA_NACL
/* We use libsodium by default. */
#include <sodium.h>
@@ -41,9 +45,6 @@
#include <crypto_verify_32.h>
#include <randombytes.h>
#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
/* I know */
#define sodium_memcmp(a, b, c) memcmp(a, b, c)
#define sodium_memzero(a, c) memset(a, 0, c)
#endif
#if CRYPTO_PUBLIC_KEY_SIZE != crypto_box_PUBLICKEYBYTES
@@ -78,19 +79,14 @@
#error CRYPTO_SHA512_SIZE should be equal to crypto_hash_sha512_BYTES
#endif
/* compare 2 public keys of length crypto_box_PUBLICKEYBYTES, not vulnerable to timing attacks.
returns 0 if both mem locations of length are equal,
return -1 if they are not. */
int public_key_cmp(const uint8_t *pk1, const uint8_t *pk2)
int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2)
{
#if crypto_box_PUBLICKEYBYTES != 32
#error crypto_box_PUBLICKEYBYTES is required to be 32 bytes for public_key_cmp to work,
#if CRYPTO_PUBLIC_KEY_SIZE != 32
#error CRYPTO_PUBLIC_KEY_SIZE is required to be 32 bytes for public_key_cmp to work,
#endif
return crypto_verify_32(pk1, pk2);
}
/* return a random number.
*/
uint32_t random_int(void)
{
uint32_t randnum;
@@ -105,13 +101,7 @@ uint64_t random_64b(void)
return randnum;
}
/* Check if a Tox public key crypto_box_PUBLICKEYBYTES is valid or not.
* This should only be used for input validation.
*
* return 0 if it isn't.
* return 1 if it is.
*/
int public_key_valid(const uint8_t *public_key)
bool public_key_valid(const uint8_t *public_key)
{
if (public_key[31] >= 128) { /* Last bit of key is always zero. */
return 0;
@@ -123,15 +113,15 @@ int public_key_valid(const uint8_t *public_key)
/* Precomputes the shared key from their public_key and our secret_key.
* This way we can avoid an expensive elliptic curve scalar multiply for each
* encrypt/decrypt operation.
* enc_key has to be crypto_box_BEFORENMBYTES bytes long.
* shared_key has to be crypto_box_BEFORENMBYTES bytes long.
*/
int encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *enc_key)
int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key)
{
return crypto_box_beforenm(enc_key, public_key, secret_key);
return crypto_box_beforenm(shared_key, public_key, secret_key);
}
int encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, uint32_t length,
uint8_t *encrypted)
int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
uint8_t *encrypted)
{
if (length == 0 || !secret_key || !nonce || !plain || !encrypted) {
return -1;
@@ -152,8 +142,8 @@ int encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, cons
return length + crypto_box_MACBYTES;
}
int decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, uint32_t length,
uint8_t *plain)
int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
uint8_t *plain)
{
if (length <= crypto_box_BOXZEROBYTES || !secret_key || !nonce || !encrypted || !plain) {
return -1;
@@ -173,8 +163,8 @@ int decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, cons
return length - crypto_box_MACBYTES;
}
int encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
const uint8_t *plain, uint32_t length, uint8_t *encrypted)
int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
const uint8_t *plain, size_t length, uint8_t *encrypted)
{
if (!public_key || !secret_key) {
return -1;
@@ -187,8 +177,8 @@ int encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uin
return ret;
}
int decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
const uint8_t *encrypted, uint32_t length, uint8_t *plain)
int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
const uint8_t *encrypted, size_t length, uint8_t *plain)
{
if (!public_key || !secret_key) {
return -1;
@@ -263,7 +253,7 @@ int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key)
return crypto_box_keypair(public_key, secret_key);
}
void crypto_derive_public_key(uint8_t *public_key, uint8_t *secret_key)
void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key)
{
crypto_scalarmult_curve25519_base(public_key, secret_key);
}
@@ -280,12 +270,23 @@ void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length)
void crypto_memzero(void *data, size_t length)
{
#ifdef VANILLA_NACL
/* TODO(c-toxcore#347): this is insecure. We need to provide our own
* secure memzero/memcmp for NaCL. */
memset(data, 0, length);
#else
sodium_memzero(data, length);
#endif
}
int32_t crypto_memcmp(const void *p1, const void *p2, size_t length)
{
#ifdef VANILLA_NACL
/* TODO(c-toxcore#347): Implement secure memcmp. */
return memcmp(p1, p2, length);
#else
return sodium_memcmp(p1, p2, length);
#endif
}
void random_bytes(uint8_t *data, size_t length)
+80 -43
View File
@@ -20,10 +20,12 @@
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CORE_CRYPTO_H
#define CORE_CRYPTO_H
#ifndef CRYPTO_CORE_H
#define CRYPTO_CORE_H
#include "network.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/**
* The number of bytes in a Tox public key.
@@ -40,14 +42,14 @@ uint32_t crypto_public_key_size(void);
uint32_t crypto_secret_key_size(void);
/**
* The number of bytes in a shared key computed from public and secret key.
* The number of bytes in a shared key computed from public and secret keys.
*/
#define CRYPTO_SHARED_KEY_SIZE 32
uint32_t crypto_shared_key_size(void);
/**
* The number of bytes in a random symmetric key.
* The number of bytes in a symmetric key.
*/
#define CRYPTO_SYMMETRIC_KEY_SIZE CRYPTO_SHARED_KEY_SIZE
@@ -82,20 +84,40 @@ uint32_t crypto_sha256_size(void);
uint32_t crypto_sha512_size(void);
/**
* A `memcmp`-like function whose running time does not depend on the input
* bytes, only on the input length. Useful to compare sensitive data where
* timing attacks could reveal that data.
*
* This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and
* "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may
* take 1 time, because it immediately knows that the two strings are not equal.
*/
int32_t crypto_memcmp(const void *p1, const void *p2, size_t length);
/**
* A `bzero`-like function which won't be optimised away by the compiler. Some
* compilers will inline `bzero` or `memset` if they can prove that there will
* be no reads to the written data. Use this function if you want to be sure the
* memory is indeed zeroed.
*/
void crypto_memzero(void *data, size_t length);
/**
* Compute a SHA256 hash (32 bytes).
*/
void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length);
/**
* Compute a SHA512 hash (64 bytes).
*/
void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length);
void crypto_derive_public_key(uint8_t *public_key, uint8_t *secret_key);
/**
* compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to timing attacks.
* returns 0 if both mem locations of length are equal,
* return -1 if they are not.
* Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
* timing attacks.
*
* @return 0 if both mem locations of length are equal, -1 if they are not.
*/
int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2);
@@ -110,70 +132,86 @@ uint32_t random_int(void);
uint64_t random_64b(void);
/**
* Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not.
* This should only be used for input validation.
* Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This
* should only be used for input validation.
*
* return 0 if it isn't.
* return 1 if it is.
* @return false if it isn't, true if it is.
*/
int32_t public_key_valid(const uint8_t *public_key);
bool public_key_valid(const uint8_t *public_key);
/**
* Generate a new random keypair. Every call to this function is likely to
* generate a different keypair.
*/
int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key);
/**
* Encrypts plain of length length to encrypted of length + 16 using the
* public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce.
*
* return -1 if there was a problem.
* return length of encrypted data if everything was fine.
* Derive the public key from a given secret key.
*/
int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain,
uint32_t length, uint8_t *encrypted);
void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key);
/**
* Decrypts encrypted of length length to plain of length length - 16 using the
* public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce.
* Encrypt plain text of the given length to encrypted of length +
* CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of the
* receiver and the secret key of the sender and a CRYPTO_NONCE_SIZE byte
* nonce.
*
* return -1 if there was a problem (decryption failed).
* return length of plain data if everything was fine.
* @return -1 if there was a problem, length of encrypted data if everything
* was fine.
*/
int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain,
size_t length, uint8_t *encrypted);
/**
* Decrypt encrypted text of the given length to plain text of the given length
* - CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of
* the sender, the secret key of the receiver and a CRYPTO_NONCE_SIZE byte
* nonce.
*
* @return -1 if there was a problem (decryption failed), length of plain text
* data if everything was fine.
*/
int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
const uint8_t *encrypted, uint32_t length, uint8_t *plain);
const uint8_t *encrypted, size_t length, uint8_t *plain);
/**
* Fast encrypt/decrypt operations. Use if this is not a one-time communication.
* encrypt_precompute does the shared-key generation once so it does not have
* to be preformed on every encrypt/decrypt.
*/
int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *enc_key);
int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key);
/**
* Encrypts plain of length length to encrypted of length + 16 using a
* secret key CRYPTO_SYMMETRIC_KEY_SIZE big and a 24 byte nonce.
* Encrypts plain of length length to encrypted of length + CRYPTO_MAC_SIZE
* using a shared key CRYPTO_SYMMETRIC_KEY_SIZE big and a CRYPTO_NONCE_SIZE
* byte nonce.
*
* return -1 if there was a problem.
* return length of encrypted data if everything was fine.
* @return -1 if there was a problem, length of encrypted data if everything
* was fine.
*/
int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, uint32_t length,
int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
uint8_t *encrypted);
/**
* Decrypts encrypted of length length to plain of length length - 16 using a
* secret key CRYPTO_SYMMETRIC_KEY_SIZE big and a 24 byte nonce.
* Decrypts encrypted of length length to plain of length length -
* CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a
* CRYPTO_NONCE_SIZE byte nonce.
*
* return -1 if there was a problem (decryption failed).
* return length of plain data if everything was fine.
* @return -1 if there was a problem (decryption failed), length of plain data
* if everything was fine.
*/
int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted,
uint32_t length, uint8_t *plain);
int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
uint8_t *plain);
/**
* Increment the given nonce by 1.
* Increment the given nonce by 1 in big endian (rightmost byte incremented
* first).
*/
void increment_nonce(uint8_t *nonce);
/**
* Increment the given nonce by num.
* Increment the given nonce by a given number. The number should be in host
* byte order.
*/
void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num);
@@ -192,5 +230,4 @@ void new_symmetric_key(uint8_t *key);
*/
void random_bytes(uint8_t *bytes, size_t length);
#endif
#endif /* CRYPTO_CORE_H */
+1
View File
@@ -29,6 +29,7 @@
#include "util.h"
#include "crypto_core.h" /* for CRYPTO_PUBLIC_KEY_SIZE */
#include "network.h" /* for current_time_monotonic */
#include <time.h>
+4 -1
View File
@@ -33,8 +33,11 @@
#ifdef VANILLA_NACL
#include <crypto_hash_sha256.h>
#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h"
#endif
#else
#include <sodium.h>
#endif
#include <string.h>
#if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES
#error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES