Frank Denis
7 years ago
24 changed files with 419 additions and 8 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,136 @@ |
|||
|
|||
#include <stddef.h> |
|||
|
|||
#include "crypto_generichash.h" |
|||
#include "crypto_kx.h" |
|||
#include "crypto_scalarmult.h" |
|||
#include "private/common.h" |
|||
#include "randombytes.h" |
|||
#include "utils.h" |
|||
|
|||
int |
|||
crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], |
|||
unsigned char sk[crypto_kx_SECRETKEYBYTES], |
|||
const unsigned char seed[crypto_kx_SEEDBYTES]) |
|||
{ |
|||
crypto_generichash(sk, crypto_kx_SECRETKEYBYTES, |
|||
seed, crypto_kx_SEEDBYTES, NULL, 0); |
|||
return crypto_scalarmult_base(pk, sk); |
|||
} |
|||
|
|||
int |
|||
crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], |
|||
unsigned char sk[crypto_kx_SECRETKEYBYTES]) |
|||
{ |
|||
COMPILER_ASSERT(crypto_kx_SECRETKEYBYTES == crypto_scalarmult_SCALARBYTES); |
|||
COMPILER_ASSERT(crypto_kx_PUBLICKEYBYTES == crypto_scalarmult_BYTES); |
|||
|
|||
randombytes_buf(sk, crypto_kx_SECRETKEYBYTES); |
|||
return crypto_scalarmult_base(pk, sk); |
|||
} |
|||
|
|||
int |
|||
crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], |
|||
unsigned char tx[crypto_kx_SESSIONKEYBYTES], |
|||
const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES], |
|||
const unsigned char client_sk[crypto_kx_SECRETKEYBYTES], |
|||
const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES]) |
|||
{ |
|||
crypto_generichash_state h; |
|||
unsigned char q[crypto_scalarmult_BYTES]; |
|||
unsigned char keys[2 * crypto_kx_SESSIONKEYBYTES]; |
|||
int i; |
|||
|
|||
if (rx == NULL) { |
|||
rx = tx; |
|||
} |
|||
if (tx == NULL) { |
|||
tx = rx; |
|||
} |
|||
if (crypto_scalarmult(q, client_sk, server_pk) != 0) { |
|||
return -1; |
|||
} |
|||
COMPILER_ASSERT(sizeof keys <= crypto_generichash_BYTES_MAX); |
|||
crypto_generichash_init(&h, NULL, 0U, sizeof keys); |
|||
crypto_generichash_update(&h, q, crypto_scalarmult_BYTES); |
|||
sodium_memzero(q, sizeof q); |
|||
crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES); |
|||
crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES); |
|||
crypto_generichash_final(&h, keys, sizeof keys); |
|||
sodium_memzero(&h, sizeof h); |
|||
for (i = 0; i < crypto_kx_SESSIONKEYBYTES; i++) { |
|||
rx[i] = keys[i]; |
|||
tx[i] = keys[i + crypto_kx_SESSIONKEYBYTES]; |
|||
} |
|||
sodium_memzero(keys, sizeof keys); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], |
|||
unsigned char tx[crypto_kx_SESSIONKEYBYTES], |
|||
const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES], |
|||
const unsigned char server_sk[crypto_kx_SECRETKEYBYTES], |
|||
const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES]) |
|||
{ |
|||
crypto_generichash_state h; |
|||
unsigned char q[crypto_scalarmult_BYTES]; |
|||
unsigned char keys[2 * crypto_kx_SESSIONKEYBYTES]; |
|||
int i; |
|||
|
|||
if (rx == NULL) { |
|||
rx = tx; |
|||
} |
|||
if (tx == NULL) { |
|||
tx = rx; |
|||
} |
|||
if (crypto_scalarmult(q, server_sk, client_pk) != 0) { |
|||
return -1; |
|||
} |
|||
COMPILER_ASSERT(sizeof keys <= crypto_generichash_BYTES_MAX); |
|||
crypto_generichash_init(&h, NULL, 0U, sizeof keys); |
|||
crypto_generichash_update(&h, q, crypto_scalarmult_BYTES); |
|||
sodium_memzero(q, sizeof q); |
|||
crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES); |
|||
crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES); |
|||
crypto_generichash_final(&h, keys, sizeof keys); |
|||
sodium_memzero(&h, sizeof h); |
|||
for (i = 0; i < crypto_kx_SESSIONKEYBYTES; i++) { |
|||
tx[i] = keys[i]; |
|||
rx[i] = keys[i + crypto_kx_SESSIONKEYBYTES]; |
|||
} |
|||
sodium_memzero(keys, sizeof keys); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
size_t |
|||
crypto_kx_publickeybytes(void) |
|||
{ |
|||
return crypto_kx_PUBLICKEYBYTES; |
|||
} |
|||
|
|||
size_t |
|||
crypto_kx_secretkeybytes(void) |
|||
{ |
|||
return crypto_kx_SECRETKEYBYTES; |
|||
} |
|||
|
|||
size_t |
|||
crypto_kx_seedbytes(void) |
|||
{ |
|||
return crypto_kx_SEEDBYTES; |
|||
} |
|||
|
|||
size_t |
|||
crypto_kx_sessionkeybytes(void) |
|||
{ |
|||
return crypto_kx_SESSIONKEYBYTES; |
|||
} |
|||
|
|||
const char * |
|||
crypto_kx_primitive(void) |
|||
{ |
|||
return crypto_kx_PRIMITIVE; |
|||
} |
@ -0,0 +1,64 @@ |
|||
#ifndef crypto_kx_H |
|||
#define crypto_kx_H |
|||
|
|||
#include <stddef.h> |
|||
|
|||
#include "export.h" |
|||
|
|||
#ifdef __cplusplus |
|||
# ifdef __GNUC__ |
|||
# pragma GCC diagnostic ignored "-Wlong-long" |
|||
# endif |
|||
extern "C" { |
|||
#endif |
|||
|
|||
#define crypto_kx_PUBLICKEYBYTES 32 |
|||
SODIUM_EXPORT |
|||
size_t crypto_kx_publickeybytes(void); |
|||
|
|||
#define crypto_kx_SECRETKEYBYTES 32 |
|||
SODIUM_EXPORT |
|||
size_t crypto_kx_secretkeybytes(void); |
|||
|
|||
#define crypto_kx_SEEDBYTES 32 |
|||
SODIUM_EXPORT |
|||
size_t crypto_kx_seedbytes(void); |
|||
|
|||
#define crypto_kx_SESSIONKEYBYTES 32 |
|||
SODIUM_EXPORT |
|||
size_t crypto_kx_sessionkeybytes(void); |
|||
|
|||
#define crypto_kx_PRIMITIVE "x25519blake2b" |
|||
SODIUM_EXPORT |
|||
const char *crypto_kx_primitive(void); |
|||
|
|||
SODIUM_EXPORT |
|||
int crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], |
|||
unsigned char sk[crypto_kx_SECRETKEYBYTES], |
|||
const unsigned char seed[crypto_kx_SEEDBYTES]); |
|||
|
|||
SODIUM_EXPORT |
|||
int crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], |
|||
unsigned char sk[crypto_kx_SECRETKEYBYTES]); |
|||
|
|||
SODIUM_EXPORT |
|||
int crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], |
|||
unsigned char tx[crypto_kx_SESSIONKEYBYTES], |
|||
const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES], |
|||
const unsigned char client_sk[crypto_kx_SECRETKEYBYTES], |
|||
const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES]) |
|||
__attribute__ ((warn_unused_result)); |
|||
|
|||
SODIUM_EXPORT |
|||
int crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], |
|||
unsigned char tx[crypto_kx_SESSIONKEYBYTES], |
|||
const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES], |
|||
const unsigned char server_sk[crypto_kx_SECRETKEYBYTES], |
|||
const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES]) |
|||
__attribute__ ((warn_unused_result)); |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif |
@ -0,0 +1,119 @@ |
|||
|
|||
#define TEST_NAME "kx" |
|||
#include "cmptest.h" |
|||
|
|||
static void |
|||
tv_kx(void) |
|||
{ |
|||
unsigned char *seed; |
|||
unsigned char *client_pk, *client_sk; |
|||
unsigned char *client_rx, *client_tx; |
|||
unsigned char *server_pk, *server_sk; |
|||
unsigned char *server_rx, *server_tx; |
|||
char hex[65]; |
|||
int i; |
|||
|
|||
seed = (unsigned char *) sodium_malloc(crypto_kx_SEEDBYTES); |
|||
for (i = 0; i < crypto_kx_SEEDBYTES; i++) { |
|||
seed[i] = (unsigned char) i; |
|||
} |
|||
client_pk = (unsigned char *) sodium_malloc(crypto_kx_PUBLICKEYBYTES); |
|||
client_sk = (unsigned char *) sodium_malloc(crypto_kx_SECRETKEYBYTES); |
|||
crypto_kx_seed_keypair(client_pk, client_sk, seed); |
|||
|
|||
sodium_bin2hex(hex, sizeof hex, client_pk, crypto_kx_PUBLICKEYBYTES); |
|||
printf("client_pk: [%s]\n", hex); |
|||
sodium_bin2hex(hex, sizeof hex, client_sk, crypto_kx_SECRETKEYBYTES); |
|||
printf("client_sk: [%s]\n", hex); |
|||
|
|||
server_pk = (unsigned char *) sodium_malloc(crypto_kx_PUBLICKEYBYTES); |
|||
server_sk = (unsigned char *) sodium_malloc(crypto_kx_SECRETKEYBYTES); |
|||
crypto_kx_keypair(server_pk, server_sk); |
|||
|
|||
client_rx = (unsigned char *) sodium_malloc(crypto_kx_SESSIONKEYBYTES); |
|||
client_tx = (unsigned char *) sodium_malloc(crypto_kx_SESSIONKEYBYTES); |
|||
|
|||
if (crypto_kx_client_session_keys(client_rx, client_tx, |
|||
client_pk, client_sk, server_pk) != 0) { |
|||
printf("crypto_kx_client_session_keys() failed\n"); |
|||
} |
|||
|
|||
server_rx = (unsigned char *) sodium_malloc(crypto_kx_SESSIONKEYBYTES); |
|||
server_tx = (unsigned char *) sodium_malloc(crypto_kx_SESSIONKEYBYTES); |
|||
|
|||
if (crypto_kx_server_session_keys(server_rx, server_tx, |
|||
server_pk, server_sk, client_pk) != 0) { |
|||
printf("crypto_kx_server_session_keys() failed\n"); |
|||
} |
|||
if (memcmp(server_rx, client_tx, crypto_kx_SESSIONKEYBYTES) != 0 || |
|||
memcmp(server_tx, client_rx, crypto_kx_SESSIONKEYBYTES) != 0) { |
|||
printf("client session keys != server session keys\n"); |
|||
} |
|||
|
|||
sodium_increment(client_pk, crypto_kx_PUBLICKEYBYTES); |
|||
if (crypto_kx_server_session_keys(server_rx, server_tx, |
|||
server_pk, server_sk, client_pk) != 0) { |
|||
printf("crypto_kx_server_session_keys() failed\n"); |
|||
} |
|||
if (memcmp(server_rx, client_tx, crypto_kx_SESSIONKEYBYTES) == 0 && |
|||
memcmp(server_tx, client_rx, crypto_kx_SESSIONKEYBYTES) == 0) { |
|||
printf("peer's public key is ignored\n"); |
|||
} |
|||
|
|||
crypto_kx_keypair(client_pk, client_sk); |
|||
if (crypto_kx_server_session_keys(server_rx, server_tx, |
|||
server_pk, server_sk, client_pk) != 0) { |
|||
printf("crypto_kx_server_session_keys() failed\n"); |
|||
} |
|||
if (memcmp(server_rx, client_tx, crypto_kx_SESSIONKEYBYTES) == 0 || |
|||
memcmp(server_tx, client_rx, crypto_kx_SESSIONKEYBYTES) == 0) { |
|||
printf("session keys are constant\n"); |
|||
} |
|||
|
|||
crypto_kx_seed_keypair(client_pk, client_sk, seed); |
|||
sodium_increment(seed, crypto_kx_SEEDBYTES); |
|||
crypto_kx_seed_keypair(server_pk, server_sk, seed); |
|||
if (crypto_kx_server_session_keys(server_rx, server_tx, |
|||
server_pk, server_sk, client_pk) != 0) { |
|||
printf("crypto_kx_server_session_keys() failed\n"); |
|||
} |
|||
sodium_bin2hex(hex, sizeof hex, server_rx, crypto_kx_SESSIONKEYBYTES); |
|||
printf("server_rx: [%s]\n", hex); |
|||
sodium_bin2hex(hex, sizeof hex, server_tx, crypto_kx_SESSIONKEYBYTES); |
|||
printf("server_tx: [%s]\n", hex); |
|||
|
|||
if (crypto_kx_client_session_keys(client_rx, client_tx, |
|||
client_pk, client_sk, server_pk) != 0) { |
|||
printf("crypto_kx_client_session_keys() failed\n"); |
|||
} |
|||
sodium_bin2hex(hex, sizeof hex, client_rx, crypto_kx_SESSIONKEYBYTES); |
|||
printf("client_rx: [%s]\n", hex); |
|||
sodium_bin2hex(hex, sizeof hex, client_tx, crypto_kx_SESSIONKEYBYTES); |
|||
printf("client_tx: [%s]\n", hex); |
|||
|
|||
sodium_free(client_rx); |
|||
sodium_free(client_tx); |
|||
sodium_free(server_rx); |
|||
sodium_free(server_tx); |
|||
sodium_free(server_sk); |
|||
sodium_free(server_pk); |
|||
sodium_free(client_sk); |
|||
sodium_free(client_pk); |
|||
sodium_free(seed); |
|||
|
|||
assert(strcmp(crypto_kx_primitive(), crypto_kx_PRIMITIVE) == 0); |
|||
assert(crypto_kx_publickeybytes() == crypto_kx_PUBLICKEYBYTES); |
|||
assert(crypto_kx_secretkeybytes() == crypto_kx_SECRETKEYBYTES); |
|||
assert(crypto_kx_seedbytes() == crypto_kx_SEEDBYTES); |
|||
assert(crypto_kx_sessionkeybytes() == crypto_kx_SESSIONKEYBYTES); |
|||
|
|||
printf("tv_kx: ok\n"); |
|||
} |
|||
|
|||
int |
|||
main(void) |
|||
{ |
|||
tv_kx(); |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,7 @@ |
|||
client_pk: [0e0216223f147143d32615a91189c288c1728cba3cc5f9f621b1026e03d83129] |
|||
client_sk: [cb2f5160fc1f7e05a55ef49d340b48da2e5a78099d53393351cd579dd42503d6] |
|||
server_rx: [62c8f4fa81800abd0577d99918d129b65deb789af8c8351f391feb0cbf238604] |
|||
server_tx: [749519c68059bce69f7cfcc7b387a3de1a1e8237d110991323bf62870115731a] |
|||
client_rx: [749519c68059bce69f7cfcc7b387a3de1a1e8237d110991323bf62870115731a] |
|||
client_tx: [62c8f4fa81800abd0577d99918d129b65deb789af8c8351f391feb0cbf238604] |
|||
tv_kx: ok |
Loading…
Reference in new issue