diff --git a/bsspeke.c b/bsspeke.c index 40aa2afd4edbf64bc349a3ac5a76c3a299418d8f..27c2906ee53d6402958ec2450d9693e6282af2ec 100644 --- a/bsspeke.c +++ b/bsspeke.c @@ -127,6 +127,8 @@ bsspeke_client_generate_message1 crypto_x25519_scalarmult(msg1->blind, client->r, curve_point, 256); print_point("blind", msg1->blind); debug(DEBUG, "Done"); + + msg1->client_id = client->client_id; return; } @@ -144,20 +146,25 @@ bsspeke_server_setup_generate_message2 ( bsspeke_setup_msg2_t *msg2, const bsspeke_setup_msg1_t *msg1, - uint8_t *salt, const size_t salt_len, + // uint8_t *salt, const size_t salt_len, + bsspeke_user_info_t *user_info, bsspeke_server_ctx *server_ctx ) { // We're setting up a new account // So we have to create a new random salt for the user debug(DEBUG, "Generating new salt"); - arc4random_buf(salt, salt_len); - print_point("salt", salt); + user_info->salt_len = 32; + arc4random_buf(user_info->salt, user_info->salt_len); + print_point("salt", user_info->salt); // Hash the salt debug(DEBUG, "Hashing the salt"); uint8_t H_salt[32]; - crypto_blake2b_general(H_salt, 32, NULL, 0, salt, salt_len); + crypto_blake2b_general(H_salt, 32, + NULL, 0, + user_info->salt, + user_info->salt_len); // Use clamp() to ensure we stay on the curve in the multiply below crypto_x25519_clamp(H_salt); print_point("H_salt", H_salt); @@ -240,9 +247,29 @@ bsspeke_client_setup_generate_message3 crypto_x25519_scalarmult(msg3->V, v, msg3->P, 256); print_point("V", msg3->V); + // Send our PHF params so the server can store them for us + msg3->phf_blocks = phf_blocks; + msg3->phf_iterations = phf_iterations; + return 0; } +void +bsspeke_server_setup_process_message3 + ( + bsspeke_setup_msg3_t *msg3, + bsspeke_user_info_t *user_info, + bsspeke_server_ctx *server + ) +{ + // Setup Message 3 contains stuff that we need to remember. + // The user info struct is where we store stuff that + // needs to persist across sessions. + memcpy(user_info->P, msg3->P, 32); + memcpy(user_info->V, msg3->V, 32); + user_info->phf_blocks = msg3->phf_blocks; + user_info->phf_iterations = msg3->phf_iterations; +} void bsspeke_client_login_generate_message1 @@ -256,16 +283,26 @@ bsspeke_client_login_generate_message1 void bsspeke_server_login_generate_message2(bsspeke_login_msg2_t *msg2, const bsspeke_login_msg1_t *msg1, - const uint8_t *salt, const size_t salt_len, - uint8_t P[32], uint8_t V[32], - uint32_t phf_blocks, - uint32_t phf_iterations, + // const uint8_t *salt, const size_t salt_len, + // uint8_t P[32], uint8_t V[32], + // uint32_t phf_blocks, + // uint32_t phf_iterations, + const bsspeke_user_info_t *user_info, bsspeke_server_ctx *server ) { + // Record the client's id + server->client_id_len = strlen(msg1->client_id); + server->client_id = (uint8_t *)malloc(server->client_id_len + 1); + strncpy(server->client_id, msg1->client_id, server->client_id_len); + printf("Server got msg1 from [%s]\n", (char *)(server->client_id)); + // Hash the salt debug(DEBUG, "Hashing the salt"); uint8_t H_salt[32]; - crypto_blake2b_general(H_salt, 32, NULL, 0, salt, salt_len); + crypto_blake2b_general(H_salt, 32, + NULL, 0, + user_info->salt, + user_info->salt_len); // Use clamp() to ensure we stay on the curve in the multiply below crypto_x25519_clamp(H_salt); print_point("H_salt", H_salt); @@ -280,20 +317,20 @@ bsspeke_server_login_generate_message2(bsspeke_login_msg2_t *msg2, crypto_x25519_clamp(server->b); print_point("b", server->b); - debug(DEBUG, "Using client's base point P"); - print_point("P", P); + debug(DEBUG, "Using user's base point P"); + print_point("P", user_info->P); // Compute public key B = b * P, save it in msg2->B debug(DEBUG, "Computing ephemeral public key B = b * P"); - crypto_x25519_scalarmult(server->B, server->b, P, 256); + crypto_x25519_scalarmult(server->B, server->b, user_info->P, 256); print_point("B", server->B); // Copy the public key into the outgoing message as well memcpy(msg2->B, server->B, 32); // Copy the PHF params too - msg2->phf_blocks = phf_blocks; - msg2->phf_iterations = phf_iterations; + msg2->phf_blocks = user_info->phf_blocks; + msg2->phf_iterations = user_info->phf_iterations; return; } @@ -426,86 +463,105 @@ bsspeke_client_login_generate_message3(bsspeke_login_msg3_t *msg3, int bsspeke_server_login_generate_message4(bsspeke_login_msg4_t *msg4, const bsspeke_login_msg3_t *msg3, - bsspeke_server_ctx *server_ctx + const bsspeke_user_info_t *user_info, + bsspeke_server_ctx *server ) { // Compute the two Diffie-Hellman shared secrets + debug(DEBUG, "Computing Diffie-Hellman shared secrets"); // DH shared secret from b * A uint8_t b_A[32]; - crypto_x25519(b_A, server_ctx->b, msg3->A); + crypto_x25519(b_A, server->b, msg3->A); + print_point("b * A", b_A); // DH shared secret from b * V + //print_point("V", user_info->V); uint8_t b_V[32]; - crypto_x25519(b_V, server_ctx->b, server_ctx->V); + crypto_x25519(b_V, server->b, user_info->V); + print_point("b * V", b_V); // Hash everything we've learned so far to generate k, save it in ctx->k + debug(DEBUG, "Hashing state so far to generate K_s"); { crypto_blake2b_ctx hash_ctx; crypto_blake2b_general_init(&hash_ctx, 32, NULL, 0); crypto_blake2b_update(&hash_ctx, - server_ctx->client_id, - server_ctx->client_id_len); + server->client_id, + server->client_id_len); crypto_blake2b_update(&hash_ctx, - server_ctx->server_id, - server_ctx->server_id_len); + server->server_id, + server->server_id_len); crypto_blake2b_update(&hash_ctx, msg3->A, 32); - crypto_blake2b_update(&hash_ctx, server_ctx->B, 32); + crypto_blake2b_update(&hash_ctx, server->B, 32); crypto_blake2b_update(&hash_ctx, b_A, 32); crypto_blake2b_update(&hash_ctx, b_V, 32); - crypto_blake2b_final(&hash_ctx, server_ctx->K_s); + crypto_blake2b_final(&hash_ctx, server->K_s); } + print_point("K_s", server->K_s); // Check that the client's hash is correct // Compute H( k || VERIFY_CLIENT_MODIFIER ) + debug(DEBUG, "Checking client's verifier hash"); uint8_t my_client_verifier[32]; { crypto_blake2b_ctx hash_ctx; crypto_blake2b_general_init(&hash_ctx, 32, NULL, 0); - crypto_blake2b_update(&hash_ctx, server_ctx->K_s, 32); + crypto_blake2b_update(&hash_ctx, server->K_s, 32); crypto_blake2b_update(&hash_ctx, (uint8_t *)BSSPEKE_VERIFY_CLIENT_MODIFIER, BSSPEKE_VERIFY_CLIENT_MODIFIER_LEN); crypto_blake2b_final(&hash_ctx, my_client_verifier); } + print_point("client's", msg3->client_verifier); + print_point("mine", my_client_verifier); // Compare vs msg3->client_verifier if( crypto_verify32(msg3->client_verifier, my_client_verifier) != 0 ) { + debug(ERROR, "Client's verifier doesn't match!"); return -1; } + debug(DEBUG, "Client's verifier checks out"); // Compute our own verifier H( k || VERIFY_SERVER_MODIFIER ), save it in msg4->server_verifier + debug(DEBUG, "Computing server verifier hash"); { crypto_blake2b_ctx hash_ctx; crypto_blake2b_general_init(&hash_ctx, 32, NULL, 0); - crypto_blake2b_update(&hash_ctx, server_ctx->K_s, 32); + crypto_blake2b_update(&hash_ctx, server->K_s, 32); crypto_blake2b_update(&hash_ctx, (uint8_t *)BSSPEKE_VERIFY_SERVER_MODIFIER, BSSPEKE_VERIFY_SERVER_MODIFIER_LEN); crypto_blake2b_final(&hash_ctx, msg4->server_verifier); } + print_point("server_v", msg4->server_verifier); // If we made it this far, return success return 0; } int -bsspeke_client_verify_message4(const bsspeke_login_msg4_t *msg4, - const bsspeke_client_ctx *client_ctx +bsspeke_client_login_verify_message4(const bsspeke_login_msg4_t *msg4, + const bsspeke_client_ctx *client ) { // Compute our own version of the server's verifier hash + debug(DEBUG, "Verifying hash from the server"); uint8_t my_server_verifier[32]; { crypto_blake2b_ctx hash_ctx; crypto_blake2b_general_init(&hash_ctx, 32, NULL, 0); - crypto_blake2b_update(&hash_ctx, client_ctx->K_c, 32); + crypto_blake2b_update(&hash_ctx, client->K_c, 32); crypto_blake2b_update(&hash_ctx, (uint8_t *)BSSPEKE_VERIFY_SERVER_MODIFIER, BSSPEKE_VERIFY_SERVER_MODIFIER_LEN); crypto_blake2b_final(&hash_ctx, my_server_verifier); } + print_point("mine", my_server_verifier); + print_point("server's", msg4->server_verifier); // If the hashes don't match, return failure if( crypto_verify32(msg4->server_verifier, my_server_verifier) != 0 ) { + debug(WARN, "Server's hash doesn't match. Aborting."); return -1; } + debug(DEBUG, "Server's hash checks out. SUCCESS!"); // Otherwise, return success return 0; diff --git a/bsspeke.h b/bsspeke.h index 8385b2afd21df55e4169a6efcd053ed1d1d343e5..29fbbaa156dd22528d2a9b3a7a5f8e01f9b01714 100644 --- a/bsspeke.h +++ b/bsspeke.h @@ -57,8 +57,8 @@ typedef struct { uint8_t *client_id; // Client's identifier (eg Matrix user_id) size_t client_id_len; - uint8_t P[32]; // Base point for the user - uint8_t V[32]; // User's long-term public key + //uint8_t P[32]; // Base point for the user + //uint8_t V[32]; // User's long-term public key uint8_t b[32]; // Ephemeral private key uint8_t B[32]; // Ephemeral public key @@ -68,6 +68,17 @@ typedef struct { uint8_t K_s[32]; // Session key } bsspeke_server_ctx; +typedef struct { + uint8_t salt[32]; + size_t salt_len; + + uint8_t P[32]; + uint8_t V[32]; + + uint32_t phf_blocks; + uint32_t phf_iterations; +} bsspeke_user_info_t; + typedef struct { char *client_id; uint8_t blind[32]; @@ -128,7 +139,8 @@ bsspeke_server_setup_generate_message2 ( bsspeke_setup_msg2_t *msg2, const bsspeke_setup_msg1_t *msg1, - uint8_t *salt, const size_t salt_len, + // uint8_t *salt, const size_t salt_len, + bsspeke_user_info_t *user_info, bsspeke_server_ctx *server_ctx ); @@ -141,6 +153,14 @@ bsspeke_client_setup_generate_message3 bsspeke_client_ctx *client ); +void +bsspeke_server_setup_process_message3 +( + bsspeke_setup_msg3_t *msg3, + bsspeke_user_info_t *user_info, + bsspeke_server_ctx *server +); + void bsspeke_client_login_generate_message1(bsspeke_login_msg1_t *msg1, bsspeke_client_ctx *client); @@ -148,11 +168,12 @@ bsspeke_client_login_generate_message1(bsspeke_login_msg1_t *msg1, void bsspeke_server_login_generate_message2(bsspeke_login_msg2_t *msg2, const bsspeke_login_msg1_t *msg1, - const uint8_t *salt, const size_t salt_len, - uint8_t P[32], uint8_t V[32], - uint32_t phf_blocks, - uint32_t phf_iterations, - bsspeke_server_ctx *server_ctx); + // const uint8_t *salt, const size_t salt_len, + // uint8_t P[32], uint8_t V[32], + // uint32_t phf_blocks, + // uint32_t phf_iterations, + const bsspeke_user_info_t *user, + bsspeke_server_ctx *server); int bsspeke_client_login_generate_message3(bsspeke_login_msg3_t *msg3, @@ -162,10 +183,11 @@ bsspeke_client_login_generate_message3(bsspeke_login_msg3_t *msg3, int bsspeke_server_login_generate_message4(bsspeke_login_msg4_t *msg4, const bsspeke_login_msg3_t *msg3, + const bsspeke_user_info_t *user_info, bsspeke_server_ctx *server_ctx); int -bsspeke_client_verify_message4(const bsspeke_login_msg4_t *msg4, - const bsspeke_client_ctx *client_ctx); +bsspeke_client_login_verify_message4(const bsspeke_login_msg4_t *msg4, + const bsspeke_client_ctx *client); #endif diff --git a/demo.c b/demo.c index c6d36f475a7c479dad1a547e990d3521f5eece9f..ce01b1cdf918f588eccc04d33d43fca6d0c4d1db 100644 --- a/demo.c +++ b/demo.c @@ -4,9 +4,7 @@ #include "bsspeke.h" -int demo_setup(uint8_t salt[32], - uint8_t P[32], - uint8_t V[32]) +int demo_setup(bsspeke_user_info_t *user_info) { bsspeke_client_ctx client; bsspeke_server_ctx server; @@ -40,7 +38,7 @@ int demo_setup(uint8_t salt[32], puts(""); puts("Setup: Server generating message 2"); bsspeke_server_setup_generate_message2(&msg2, &msg1, - salt, 32, + user_info, &server); puts(""); @@ -50,9 +48,8 @@ int demo_setup(uint8_t salt[32], &client); puts(""); - puts("Setup: Saving parameters from setup"); - memcpy(P, msg3.P, 32); - memcpy(V, msg3.V, 32); + puts("Setup: Server processing message 3"); + bsspeke_server_setup_process_message3(&msg3, user_info, &server); puts(""); puts("Setup: Done"); @@ -60,9 +57,7 @@ int demo_setup(uint8_t salt[32], return 0; } -int demo_login(uint8_t salt[32], - uint8_t P[32], - uint8_t V[32]) +int demo_login(bsspeke_user_info_t *user_info) { bsspeke_client_ctx client; bsspeke_server_ctx server; @@ -97,15 +92,23 @@ int demo_login(uint8_t salt[32], puts(""); puts("Login: Server generating message 2"); bsspeke_server_login_generate_message2(&msg2, &msg1, - salt, 32, - P, V, - 100000, 3, + // salt, 32, + // P, V, + // 100000, 3, + user_info, &server); puts(""); puts("Login: Client generating message 3"); bsspeke_client_login_generate_message3(&msg3, &msg2, &client); + puts(""); + puts("Login: Server generating message 4"); + bsspeke_server_login_generate_message4(&msg4, &msg3, user_info, &server); + + puts(""); + puts("Login: Client verifying message 4"); + bsspeke_client_login_verify_message4(&msg4, &client); return 0; @@ -114,19 +117,16 @@ int demo_login(uint8_t salt[32], int main(int argc, char *argv[]) { // Here we're pretending to be the server's long-term storage - // It needs to know the salt, V, and P for each registered user - uint8_t salt[32]; - uint8_t V[32]; - uint8_t P[32]; + bsspeke_user_info_t user_info; int rc = 0; - if( (rc = demo_setup(salt, P, V)) != 0 ) { + if( (rc = demo_setup(&user_info)) != 0 ) { puts("Setup failed :("); exit(-1); } - if( (rc = demo_login(salt, P, V)) != 0 ) { + if( (rc = demo_login(&user_info)) != 0 ) { puts("Login failed :("); exit(-1); }