int main(void) { void *buf; size_t size; #ifdef SIGSEGV signal(SIGSEGV, segv_handler); #endif #ifdef SIGBUS signal(SIGBUS, segv_handler); #endif #ifdef SIGABRT signal(SIGABRT, segv_handler); #endif size = 1U + randombytes_uniform(100000U); buf = sodium_malloc(size); assert(buf != NULL); sodium_mprotect_noaccess(buf); sodium_mprotect_readwrite(buf); #ifndef __EMSCRIPTEN__ sodium_memzero(((unsigned char *)buf) - 8, 8U); sodium_mprotect_readonly(buf); sodium_free(buf); printf("Underflow not caught\n"); #endif return 0; }
int main(void) { void *buf; size_t size; unsigned int i; if (sodium_malloc(SIZE_MAX - 1U) != NULL) { return 1; } if (sodium_allocarray(SIZE_MAX / 2U + 1U, SIZE_MAX / 2U) != NULL) { return 1; } sodium_free(sodium_allocarray(0U, 0U)); sodium_free(sodium_allocarray(0U, 1U)); sodium_free(sodium_allocarray(1U, 0U)); buf = sodium_allocarray(1000U, 50U); memset(buf, 0, 50000U); sodium_free(buf); sodium_free(sodium_malloc(0U)); sodium_free(NULL); for (i = 0U; i < 10000U; i++) { size = randombytes_uniform(100000U); buf = sodium_malloc(size); assert(buf != NULL); memset(buf, i, size); sodium_mprotect_noaccess(buf); sodium_free(buf); } printf("OK\n"); #ifdef SIGSEGV signal(SIGSEGV, segv_handler); #endif #ifdef SIGBUS signal(SIGBUS, segv_handler); #endif #ifdef SIGABRT signal(SIGABRT, segv_handler); #endif size = randombytes_uniform(100000U); buf = sodium_malloc(size); assert(buf != NULL); sodium_mprotect_readonly(buf); sodium_mprotect_readwrite(buf); #ifndef __EMSCRIPTEN__ sodium_memzero(((unsigned char *)buf) + size, 1U); sodium_mprotect_noaccess(buf); sodium_free(buf); printf("Overflow not caught\n"); #endif return 0; }
/* * Sign a piece of data. Returns the data and signature in one output buffer. */ return_status master_keys_sign( master_keys * const keys, const buffer_t * const data, buffer_t * const signed_data) { //output, length of data + SIGNATURE_SIZE return_status status = return_status_init(); if ((keys == NULL) || (data == NULL) || (signed_data == NULL) || (signed_data->buffer_length < (data->content_length + SIGNATURE_SIZE))) { throw(INVALID_INPUT, "Invalid input to master_keys_sign."); } sodium_mprotect_readonly(keys); int status_int = 0; unsigned long long signed_message_length; status_int = crypto_sign( signed_data->content, &signed_message_length, data->content, data->content_length, keys->private_signing_key->content); if (status_int != 0) { throw(SIGN_ERROR, "Failed to sign message."); } signed_data->content_length = (size_t) signed_message_length; cleanup: if (keys != NULL) { sodium_mprotect_noaccess(keys); } on_error { if (signed_data != NULL) { signed_data->content_length = 0; } } return status; }
/* * Get the public identity key. */ return_status master_keys_get_identity_key( master_keys * const keys, buffer_t * const public_identity_key) { return_status status = return_status_init(); //check input if ((keys == NULL) || (public_identity_key == NULL) || (public_identity_key->buffer_length < PUBLIC_KEY_SIZE)) { throw(INVALID_INPUT, "Invalid input to master_keys_get_identity_key."); } sodium_mprotect_readonly(keys); if (buffer_clone(public_identity_key, keys->public_identity_key) != 0) { goto cleanup; } cleanup: if (keys != NULL) { sodium_mprotect_noaccess(keys); } return status; }
/* * Get the public signing key. */ return_status master_keys_get_signing_key( master_keys * const keys, buffer_t * const public_signing_key) { return_status status = return_status_init(); //check input if ((keys == NULL) || (public_signing_key == NULL) || (public_signing_key->buffer_length < PUBLIC_MASTER_KEY_SIZE)) { throw(INVALID_INPUT, "Invalid input to master_keys_get_signing_key."); } sodium_mprotect_readonly(keys); if (buffer_clone(public_signing_key, keys->public_signing_key) != 0) { throw(BUFFER_ERROR, "Failed to copy public signing key."); } cleanup: if (keys != NULL) { sodium_mprotect_noaccess(keys); } return status; }
int main(void) { sodium_init(); //create a user_store user_store *store = user_store_create(); //check the content buffer_t *list = user_store_list(store); if (list->content_length != 0) { fprintf(stderr, "ERROR: List of users is not empty.\n"); user_store_destroy(store); buffer_destroy_from_heap(list); return EXIT_FAILURE; } buffer_destroy_from_heap(list); int status; //create three users with prekeys and identity keys //first alice //alice identity key buffer_t *alice_private_identity = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *alice_public_identity = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); status = generate_and_print_keypair( alice_public_identity, alice_private_identity, buffer_create_from_string("Alice"), buffer_create_from_string("identity")); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Alice's identity keypair.\n"); buffer_clear(alice_private_identity); return status; } //alice prekeys buffer_t *alice_private_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES, PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES); buffer_t *alice_public_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES, PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES); status = generate_prekeys(alice_private_prekeys, alice_public_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Alice's prekeys.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); return status; } //then bob //bob's identity key buffer_t *bob_private_identity = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *bob_public_identity = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); status = generate_and_print_keypair( bob_public_identity, bob_private_identity, buffer_create_from_string("Bob"), buffer_create_from_string("identity")); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Bob's identity keypair.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); return status; } //bob's prekeys buffer_t *bob_private_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES, PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES); buffer_t *bob_public_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES, PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES); status = generate_prekeys(bob_private_prekeys, bob_public_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Bob's prekeys.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); return status; } //then charlie //charlie's identity key buffer_t *charlie_private_identity = buffer_create(crypto_box_SECRETKEYBYTES, crypto_box_SECRETKEYBYTES); buffer_t *charlie_public_identity = buffer_create(crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); status = generate_and_print_keypair( charlie_public_identity, charlie_private_identity, buffer_create_from_string("Charlie"), buffer_create_from_string("identity")); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Charlie's identity keypair.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); return status; } //charlie's prekeys buffer_t *charlie_private_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES, PREKEY_AMOUNT * crypto_box_SECRETKEYBYTES); buffer_t *charlie_public_prekeys = buffer_create(PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES, PREKEY_AMOUNT * crypto_box_PUBLICKEYBYTES); status = generate_prekeys(charlie_private_prekeys, charlie_public_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to generate Charlie's prekeys.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); return status; } //add alice to the user store status = user_store_add( store, alice_public_identity, alice_private_identity, alice_public_prekeys, alice_private_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to add Alice to the user store.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return status; } printf("Successfully added Alice to the user store.\n"); //check length of the user store sodium_mprotect_readonly(store); if (store->length != 1) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //list user store list = user_store_list(store); if (buffer_compare(list, alice_public_identity) != 0) { fprintf(stderr, "ERROR: Failed to list users.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); buffer_destroy_from_heap(list); user_store_destroy(store); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully listed users.\n"); //add bob to the user store status = user_store_add( store, bob_public_identity, bob_private_identity, bob_public_prekeys, bob_private_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to add Bob to the user store.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return status; } printf("Successfully added Bob to the user store.\n"); //check length of the user store sodium_mprotect_readonly(store); if (store->length != 2) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //list user store list = user_store_list(store); if ((buffer_compare_partial(list, 0, alice_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, crypto_box_PUBLICKEYBYTES, bob_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0)) { fprintf(stderr, "ERROR: Failed to list users.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); buffer_destroy_from_heap(list); user_store_destroy(store); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully listed users.\n"); //add charlie to the user store status = user_store_add( store, charlie_public_identity, charlie_private_identity, charlie_public_prekeys, charlie_private_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to add Charlie to the user store.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return status; } printf("Successfully added Charlie to the user store.\n"); //check length of the user store sodium_mprotect_readonly(store); if (store->length != 3) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //list user store list = user_store_list(store); if ((buffer_compare_partial(list, 0, alice_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, crypto_box_PUBLICKEYBYTES, bob_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, 2 * crypto_box_PUBLICKEYBYTES, charlie_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0)) { fprintf(stderr, "ERROR: Failed to list users.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); buffer_destroy_from_heap(list); user_store_destroy(store); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully listed users.\n"); //find node user_store_node *bob_node = user_store_find_node(store, bob_public_identity); if (bob_node == NULL) { fprintf(stderr, "ERROR: Failed to find Bob's node.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } printf("Node found.\n"); sodium_mprotect_readonly(bob_node); if ((buffer_compare(&(bob_node->public_identity_key), bob_public_identity) != 0) || (buffer_compare(&(bob_node->private_identity_key), bob_private_identity) != 0) || (buffer_compare(&(bob_node->public_prekeys), bob_public_prekeys) != 0) || (buffer_compare(&(bob_node->private_prekeys), bob_private_prekeys) != 0)) { fprintf(stderr, "ERROR: Bob's data from the user store doesn't match.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(bob_node); printf("Data from the node matches.\n"); //remove a user identified by it's key user_store_remove_by_key(store, bob_public_identity); //check the length sodium_mprotect_readonly(store); if (store->length != 2) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //check the user list list = user_store_list(store); if ((buffer_compare_partial(list, 0, alice_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, crypto_box_PUBLICKEYBYTES, charlie_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0)) { fprintf(stderr, "ERROR: Removing user failed.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); buffer_destroy_from_heap(list); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully removed user.\n"); //readd bob status = user_store_add( store, bob_public_identity, bob_private_identity, bob_public_prekeys, bob_private_prekeys); if (status != 0) { fprintf(stderr, "ERROR: Failed to readd Bob to the user store.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return status; } printf("Successfully readded Bob to the user store.\n"); //now find bob again bob_node = user_store_find_node(store, bob_public_identity); if (bob_node == NULL) { fprintf(stderr, "ERROR: Failed to find Bob's node.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } printf("Bob's node found again.\n"); //remove bob by it's node user_store_remove(store, bob_node); //check the length sodium_mprotect_readonly(store); if (store->length != 2) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); return EXIT_FAILURE; } sodium_mprotect_noaccess(store); printf("Length of the user store matches."); //check the user list list = user_store_list(store); if ((buffer_compare_partial(list, 0, alice_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0) || (buffer_compare_partial(list, crypto_box_PUBLICKEYBYTES, charlie_public_identity, 0, crypto_box_PUBLICKEYBYTES) != 0)) { fprintf(stderr, "ERROR: Removing user failed.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); user_store_destroy(store); buffer_destroy_from_heap(list); return EXIT_FAILURE; } buffer_destroy_from_heap(list); printf("Successfully removed user.\n"); buffer_clear(alice_private_identity); buffer_clear(alice_private_prekeys); buffer_clear(bob_private_identity); buffer_clear(bob_private_prekeys); buffer_clear(charlie_private_identity); buffer_clear(charlie_private_prekeys); //clear the user store user_store_clear(store); //check the length sodium_mprotect_readonly(store); if (store->length != 0) { fprintf(stderr, "ERROR: User store has incorrect length.\n"); user_store_destroy(store); return EXIT_FAILURE; } printf("Successfully cleared user store.\n"); sodium_mprotect_noaccess(store); user_store_destroy(store); return EXIT_SUCCESS; }
return_status master_keys_export( master_keys * const keys, Key ** const public_signing_key, Key ** const private_signing_key, Key ** const public_identity_key, Key ** const private_identity_key) { return_status status = return_status_init(); //check input if ((keys == NULL) || (public_signing_key == NULL) || (private_signing_key == NULL) || (public_identity_key == NULL) || (private_identity_key == NULL)) { throw(INVALID_INPUT, "Invalid input to keys_export"); } //allocate the structs *public_signing_key = zeroed_malloc(sizeof(Key)); throw_on_failed_alloc(*public_signing_key); key__init(*public_signing_key); *private_signing_key = zeroed_malloc(sizeof(Key)); throw_on_failed_alloc(*private_signing_key); key__init(*private_signing_key); *public_identity_key = zeroed_malloc(sizeof(Key)); throw_on_failed_alloc(*public_identity_key); key__init(*public_identity_key); *private_identity_key = zeroed_malloc(sizeof(Key)); throw_on_failed_alloc(*private_identity_key); key__init(*private_identity_key); //allocate the key buffers (*public_signing_key)->key.data = zeroed_malloc(PUBLIC_MASTER_KEY_SIZE); throw_on_failed_alloc((*public_signing_key)->key.data); (*public_signing_key)->key.len = PUBLIC_MASTER_KEY_SIZE; (*private_signing_key)->key.data = zeroed_malloc(PRIVATE_MASTER_KEY_SIZE); throw_on_failed_alloc((*private_signing_key)->key.data); (*private_signing_key)->key.len = PRIVATE_MASTER_KEY_SIZE; (*public_identity_key)->key.data = zeroed_malloc(PUBLIC_KEY_SIZE); throw_on_failed_alloc((*public_identity_key)->key.data); (*public_identity_key)->key.len = PUBLIC_KEY_SIZE; (*private_identity_key)->key.data = zeroed_malloc(PUBLIC_KEY_SIZE); throw_on_failed_alloc((*private_identity_key)->key.data); (*private_identity_key)->key.len = PUBLIC_KEY_SIZE; //unlock the master keys sodium_mprotect_readonly(keys); //copy the keys if (buffer_clone_to_raw((*public_signing_key)->key.data, (*public_signing_key)->key.len, keys->public_signing_key) != 0) { throw(BUFFER_ERROR, "Failed to export public signing key."); } if (buffer_clone_to_raw((*private_signing_key)->key.data, (*private_signing_key)->key.len, keys->private_signing_key) != 0) { throw(BUFFER_ERROR, "Failed to export private signing key."); } if (buffer_clone_to_raw((*public_identity_key)->key.data, (*public_identity_key)->key.len, keys->public_identity_key) != 0) { throw(BUFFER_ERROR, "Failed to export public identity key."); } if (buffer_clone_to_raw((*private_identity_key)->key.data, (*private_identity_key)->key.len, keys->private_identity_key) != 0) { throw(BUFFER_ERROR, "Failed to export private identity key."); } cleanup: on_error { if ((public_signing_key != NULL) && (*public_signing_key != NULL)) { key__free_unpacked(*public_signing_key, &protobuf_c_allocators); *public_signing_key = NULL; } if ((private_signing_key != NULL) && (*private_signing_key != NULL)) { key__free_unpacked(*private_signing_key, &protobuf_c_allocators); *private_signing_key = NULL; } if ((public_identity_key != NULL) && (*public_identity_key != NULL)) { key__free_unpacked(*public_identity_key, &protobuf_c_allocators); *public_identity_key = NULL; } if ((private_identity_key != NULL) && (*private_identity_key != NULL)) { key__free_unpacked(*private_identity_key, &protobuf_c_allocators); *private_identity_key = NULL; } } if (keys != NULL) { sodium_mprotect_noaccess(keys); } return status; }