1 2 #include <stddef.h> 3 4 #include "core.h" 5 #include "crypto_generichash.h" 6 #include "crypto_kx.h" 7 #include "crypto_scalarmult.h" 8 #include "private/common.h" 9 #include "randombytes.h" 10 #include "utils.h" 11 12 int 13 crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], 14 unsigned char sk[crypto_kx_SECRETKEYBYTES], 15 const unsigned char seed[crypto_kx_SEEDBYTES]) 16 { 17 crypto_generichash(sk, crypto_kx_SECRETKEYBYTES, 18 seed, crypto_kx_SEEDBYTES, NULL, 0); 19 return crypto_scalarmult_base(pk, sk); 20 } 21 22 int 23 crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], 24 unsigned char sk[crypto_kx_SECRETKEYBYTES]) 25 { 26 COMPILER_ASSERT(crypto_kx_SECRETKEYBYTES == crypto_scalarmult_SCALARBYTES); 27 COMPILER_ASSERT(crypto_kx_PUBLICKEYBYTES == crypto_scalarmult_BYTES); 28 29 randombytes_buf(sk, crypto_kx_SECRETKEYBYTES); 30 return crypto_scalarmult_base(pk, sk); 31 } 32 33 int 34 crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], 35 unsigned char tx[crypto_kx_SESSIONKEYBYTES], 36 const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES], 37 const unsigned char client_sk[crypto_kx_SECRETKEYBYTES], 38 const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES]) 39 { 40 crypto_generichash_state h; 41 unsigned char q[crypto_scalarmult_BYTES]; 42 unsigned char keys[2 * crypto_kx_SESSIONKEYBYTES]; 43 int i; 44 45 if (rx == NULL) { 46 rx = tx; 47 } 48 if (tx == NULL) { 49 tx = rx; 50 } 51 if (rx == NULL) { 52 sodium_misuse(); /* LCOV_EXCL_LINE */ 53 } 54 if (crypto_scalarmult(q, client_sk, server_pk) != 0) { 55 return -1; 56 } 57 COMPILER_ASSERT(sizeof keys <= crypto_generichash_BYTES_MAX); 58 crypto_generichash_init(&h, NULL, 0U, sizeof keys); 59 crypto_generichash_update(&h, q, crypto_scalarmult_BYTES); 60 sodium_memzero(q, sizeof q); 61 crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES); 62 crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES); 63 crypto_generichash_final(&h, keys, sizeof keys); 64 sodium_memzero(&h, sizeof h); 65 for (i = 0; i < crypto_kx_SESSIONKEYBYTES; i++) { 66 rx[i] = keys[i]; 67 tx[i] = keys[i + crypto_kx_SESSIONKEYBYTES]; 68 } 69 sodium_memzero(keys, sizeof keys); 70 71 return 0; 72 } 73 74 int 75 crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], 76 unsigned char tx[crypto_kx_SESSIONKEYBYTES], 77 const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES], 78 const unsigned char server_sk[crypto_kx_SECRETKEYBYTES], 79 const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES]) 80 { 81 crypto_generichash_state h; 82 unsigned char q[crypto_scalarmult_BYTES]; 83 unsigned char keys[2 * crypto_kx_SESSIONKEYBYTES]; 84 int i; 85 86 if (rx == NULL) { 87 rx = tx; 88 } 89 if (tx == NULL) { 90 tx = rx; 91 } 92 if (rx == NULL) { 93 sodium_misuse(); /* LCOV_EXCL_LINE */ 94 } 95 if (crypto_scalarmult(q, server_sk, client_pk) != 0) { 96 return -1; 97 } 98 COMPILER_ASSERT(sizeof keys <= crypto_generichash_BYTES_MAX); 99 crypto_generichash_init(&h, NULL, 0U, sizeof keys); 100 crypto_generichash_update(&h, q, crypto_scalarmult_BYTES); 101 sodium_memzero(q, sizeof q); 102 crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES); 103 crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES); 104 crypto_generichash_final(&h, keys, sizeof keys); 105 sodium_memzero(&h, sizeof h); 106 for (i = 0; i < crypto_kx_SESSIONKEYBYTES; i++) { 107 tx[i] = keys[i]; 108 rx[i] = keys[i + crypto_kx_SESSIONKEYBYTES]; 109 } 110 sodium_memzero(keys, sizeof keys); 111 112 return 0; 113 } 114 115 size_t 116 crypto_kx_publickeybytes(void) 117 { 118 return crypto_kx_PUBLICKEYBYTES; 119 } 120 121 size_t 122 crypto_kx_secretkeybytes(void) 123 { 124 return crypto_kx_SECRETKEYBYTES; 125 } 126 127 size_t 128 crypto_kx_seedbytes(void) 129 { 130 return crypto_kx_SEEDBYTES; 131 } 132 133 size_t 134 crypto_kx_sessionkeybytes(void) 135 { 136 return crypto_kx_SESSIONKEYBYTES; 137 } 138 139 const char * 140 crypto_kx_primitive(void) 141 { 142 return crypto_kx_PRIMITIVE; 143 } 144