void JVM_end_signal_setting() { signal_lock(); jvm_signal_installed = true; jvm_signal_installing = false; pthread_cond_broadcast(&cond); signal_unlock(); }
int session_cipher_get_remote_registration_id(session_cipher *cipher, uint32_t *remote_id) { int result = 0; uint32_t id_result = 0; session_record *record = 0; session_state *state = 0; assert(cipher); signal_lock(cipher->global_context); result = signal_protocol_session_load_session(cipher->store, &record, cipher->remote_address); if(result < 0) { goto complete; } state = session_record_get_state(record); if(!state) { result = SG_ERR_UNKNOWN; goto complete; } id_result = session_state_get_remote_registration_id(state); complete: if(result >= 0) { *remote_id = id_result; } signal_unlock(cipher->global_context); return result; }
/* The three functions for the jvm to call into. */ void JVM_begin_signal_setting() { signal_lock(); sigemptyset(&jvmsigs); jvm_signal_installing = true; tid = pthread_self(); signal_unlock(); }
int session_cipher_decrypt_signal_message(session_cipher *cipher, signal_message *ciphertext, void *decrypt_context, signal_buffer **plaintext) { int result = 0; signal_buffer *result_buf = 0; session_record *record = 0; assert(cipher); signal_lock(cipher->global_context); if(cipher->inside_callback == 1) { result = SG_ERR_INVAL; goto complete; } result = signal_protocol_session_contains_session(cipher->store, cipher->remote_address); if(result == 0) { signal_log(cipher->global_context, SG_LOG_WARNING, "No session for: %s:%d", cipher->remote_address->name, cipher->remote_address->device_id); result = SG_ERR_NO_SESSION; goto complete; } else if(result < 0) { goto complete; } result = signal_protocol_session_load_session(cipher->store, &record, cipher->remote_address); if(result < 0) { goto complete; } result = session_cipher_decrypt_from_record_and_signal_message( cipher, record, ciphertext, &result_buf); if(result < 0) { goto complete; } result = session_cipher_decrypt_callback(cipher, result_buf, decrypt_context); if(result < 0) { goto complete; } result = signal_protocol_session_store_session(cipher->store, cipher->remote_address, record); complete: SIGNAL_UNREF(record); if(result >= 0) { *plaintext = result_buf; } else { signal_buffer_free(result_buf); } signal_unlock(cipher->global_context); return result; }
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { int res; bool sigused; struct sigaction oldAct; check_status(pthread_once(&reentry_key_init_once, reentry_tls_init)); if (pthread_getspecific(reentry_flag_key) != NULL) { return call_os_sigaction(sig, act, oact); } signal_lock(); sigused = (MASK(sig) & jvmsigs) != 0; if (jvm_signal_installed && sigused) { /* jvm has installed its signal handler for this signal. */ /* Save the handler. Don't really install it. */ if (oact != NULL) { *oact = sact[sig]; } if (act != NULL) { sact[sig] = *act; } signal_unlock(); return 0; } else if (jvm_signal_installing) { /* jvm is installing its signal handlers. Install the new * handlers and save the old ones. */ res = call_os_sigaction(sig, act, &oldAct); sact[sig] = oldAct; if (oact != NULL) { *oact = oldAct; } /* Record the signals used by jvm */ jvmsigs |= MASK(sig); signal_unlock(); return res; } else { /* jvm has no relation with this signal (yet). Install the * the handler. */ res = call_os_sigaction(sig, act, oact); signal_unlock(); return res; } }
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { int res; bool sigused; struct sigaction oldAct; signal_lock(); sigused = sigismember(&jvmsigs, sig); if (jvm_signal_installed && sigused) { /* jvm has installed its signal handler for this signal. */ /* Save the handler. Don't really install it. */ if (oact != NULL) { *oact = sact[sig]; } if (act != NULL) { sact[sig] = *act; } signal_unlock(); return 0; } else if (jvm_signal_installing) { /* jvm is installing its signal handlers. Install the new * handlers and save the old ones. */ res = call_os_sigaction(sig, act, &oldAct); sact[sig] = oldAct; if (oact != NULL) { *oact = oldAct; } /* Record the signals used by jvm. */ sigaddset(&jvmsigs, sig); signal_unlock(); return res; } else { /* jvm has no relation with this signal (yet). Install the * the handler. */ res = call_os_sigaction(sig, act, oact); signal_unlock(); return res; } }
int session_cipher_get_session_version(session_cipher *cipher, uint32_t *version) { int result = 0; uint32_t version_result = 0; session_record *record = 0; session_state *state = 0; assert(cipher); signal_lock(cipher->global_context); result = signal_protocol_session_contains_session(cipher->store, cipher->remote_address); if(result != 1) { if(result == 0) { signal_log(cipher->global_context, SG_LOG_WARNING, "No session for: %s:%d", cipher->remote_address->name, cipher->remote_address->device_id); result = SG_ERR_NO_SESSION; } goto complete; } result = signal_protocol_session_load_session(cipher->store, &record, cipher->remote_address); if(result < 0) { goto complete; } state = session_record_get_state(record); if(!state) { result = SG_ERR_UNKNOWN; goto complete; } version_result = session_state_get_session_version(state); complete: if(result >= 0) { *version = version_result; } signal_unlock(cipher->global_context); return result; }
static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { sa_handler_t oldhandler; bool sigused; signal_lock(); sigused = (MASK(sig) & jvmsigs) != 0; if (jvm_signal_installed && sigused) { /* jvm has installed its signal handler for this signal. */ /* Save the handler. Don't really install it. */ oldhandler = sact[sig].sa_handler; save_signal_handler(sig, disp); signal_unlock(); return oldhandler; } else if (jvm_signal_installing) { /* jvm is installing its signal handlers. Install the new * handlers and save the old ones. jvm uses sigaction(). * Leave the piece here just in case. */ oldhandler = call_os_signal(sig, disp, is_sigset); save_signal_handler(sig, oldhandler); /* Record the signals used by jvm */ jvmsigs |= MASK(sig); signal_unlock(); return oldhandler; } else { /* jvm has no relation with this signal (yet). Install the * the handler. */ oldhandler = call_os_signal(sig, disp, is_sigset); signal_unlock(); return oldhandler; } }
int session_cipher_encrypt(session_cipher *cipher, const uint8_t *padded_message, size_t padded_message_len, ciphertext_message **encrypted_message) { int result = 0; session_record *record = 0; session_state *state = 0; ratchet_chain_key *chain_key = 0; ratchet_chain_key *next_chain_key = 0; ratchet_message_keys message_keys; ec_public_key *sender_ephemeral = 0; uint32_t previous_counter = 0; uint32_t session_version = 0; signal_buffer *ciphertext = 0; uint32_t chain_key_index = 0; ec_public_key *local_identity_key = 0; ec_public_key *remote_identity_key = 0; signal_message *message = 0; pre_key_signal_message *pre_key_message = 0; uint8_t *ciphertext_data = 0; size_t ciphertext_len = 0; assert(cipher); signal_lock(cipher->global_context); if(cipher->inside_callback == 1) { result = SG_ERR_INVAL; goto complete; } result = signal_protocol_session_load_session(cipher->store, &record, cipher->remote_address); if(result < 0) { goto complete; } state = session_record_get_state(record); if(!state) { result = SG_ERR_UNKNOWN; goto complete; } chain_key = session_state_get_sender_chain_key(state); if(!chain_key) { result = SG_ERR_UNKNOWN; goto complete; } result = ratchet_chain_key_get_message_keys(chain_key, &message_keys); if(result < 0) { goto complete; } sender_ephemeral = session_state_get_sender_ratchet_key(state); if(!sender_ephemeral) { result = SG_ERR_UNKNOWN; goto complete; } previous_counter = session_state_get_previous_counter(state); session_version = session_state_get_session_version(state); result = session_cipher_get_ciphertext(cipher, &ciphertext, session_version, &message_keys, padded_message, padded_message_len); if(result < 0) { goto complete; } ciphertext_data = signal_buffer_data(ciphertext); ciphertext_len = signal_buffer_len(ciphertext); chain_key_index = ratchet_chain_key_get_index(chain_key); local_identity_key = session_state_get_local_identity_key(state); if(!local_identity_key) { result = SG_ERR_UNKNOWN; goto complete; } remote_identity_key = session_state_get_remote_identity_key(state); if(!remote_identity_key) { result = SG_ERR_UNKNOWN; goto complete; } result = signal_message_create(&message, session_version, message_keys.mac_key, sizeof(message_keys.mac_key), sender_ephemeral, chain_key_index, previous_counter, ciphertext_data, ciphertext_len, local_identity_key, remote_identity_key, cipher->global_context); if(result < 0) { goto complete; } if(session_state_has_unacknowledged_pre_key_message(state) == 1) { uint32_t local_registration_id = session_state_get_local_registration_id(state); int has_pre_key_id = 0; uint32_t pre_key_id = 0; uint32_t signed_pre_key_id; ec_public_key *base_key; if(session_state_unacknowledged_pre_key_message_has_pre_key_id(state)) { has_pre_key_id = 1; pre_key_id = session_state_unacknowledged_pre_key_message_get_pre_key_id(state); } signed_pre_key_id = session_state_unacknowledged_pre_key_message_get_signed_pre_key_id(state); base_key = session_state_unacknowledged_pre_key_message_get_base_key(state); if(!base_key) { result = SG_ERR_UNKNOWN; goto complete; } result = pre_key_signal_message_create(&pre_key_message, session_version, local_registration_id, (has_pre_key_id ? &pre_key_id : 0), signed_pre_key_id, base_key, local_identity_key, message, cipher->global_context); if(result < 0) { goto complete; } SIGNAL_UNREF(message); message = 0; } result = ratchet_chain_key_create_next(chain_key, &next_chain_key); if(result < 0) { goto complete; } result = session_state_set_sender_chain_key(state, next_chain_key); if(result < 0) { goto complete; } result = signal_protocol_session_store_session(cipher->store, cipher->remote_address, record); complete: if(result >= 0) { if(pre_key_message) { *encrypted_message = (ciphertext_message *)pre_key_message; } else { *encrypted_message = (ciphertext_message *)message; } } else { SIGNAL_UNREF(pre_key_message); SIGNAL_UNREF(message); } signal_buffer_free(ciphertext); SIGNAL_UNREF(next_chain_key); SIGNAL_UNREF(record); signal_explicit_bzero(&message_keys, sizeof(ratchet_message_keys)); signal_unlock(cipher->global_context); return result; }
static int session_cipher_decrypt_from_record_and_signal_message(session_cipher *cipher, session_record *record, signal_message *ciphertext, signal_buffer **plaintext) { int result = 0; signal_buffer *result_buf = 0; session_state *state = 0; session_state *state_copy = 0; session_record_state_node *previous_states_node = 0; assert(cipher); signal_lock(cipher->global_context); state = session_record_get_state(record); if(state) { result = session_state_copy(&state_copy, state, cipher->global_context); if(result < 0) { goto complete; } //TODO Collect and log invalid message errors if totally unsuccessful result = session_cipher_decrypt_from_state_and_signal_message(cipher, state_copy, ciphertext, &result_buf); if(result < 0 && result != SG_ERR_INVALID_MESSAGE) { goto complete; } if(result >= SG_SUCCESS) { session_record_set_state(record, state_copy); goto complete; } SIGNAL_UNREF(state_copy); } previous_states_node = session_record_get_previous_states_head(record); while(previous_states_node) { state = session_record_get_previous_states_element(previous_states_node); result = session_state_copy(&state_copy, state, cipher->global_context); if(result < 0) { goto complete; } result = session_cipher_decrypt_from_state_and_signal_message(cipher, state_copy, ciphertext, &result_buf); if(result < 0 && result != SG_ERR_INVALID_MESSAGE) { goto complete; } if(result >= SG_SUCCESS) { session_record_get_previous_states_remove(record, previous_states_node); result = session_record_promote_state(record, state_copy); goto complete; } SIGNAL_UNREF(state_copy); previous_states_node = session_record_get_previous_states_next(previous_states_node); } signal_log(cipher->global_context, SG_LOG_WARNING, "No valid sessions"); result = SG_ERR_INVALID_MESSAGE; complete: SIGNAL_UNREF(state_copy); if(result >= 0) { *plaintext = result_buf; } else { signal_buffer_free(result_buf); } signal_unlock(cipher->global_context); return result; }
int session_cipher_decrypt_pre_key_signal_message(session_cipher *cipher, pre_key_signal_message *ciphertext, void *decrypt_context, signal_buffer **plaintext) { int result = 0; signal_buffer *result_buf = 0; session_record *record = 0; int has_unsigned_pre_key_id = 0; uint32_t unsigned_pre_key_id = 0; assert(cipher); signal_lock(cipher->global_context); if(cipher->inside_callback == 1) { result = SG_ERR_INVAL; goto complete; } result = signal_protocol_session_load_session(cipher->store, &record, cipher->remote_address); if(result < 0) { goto complete; } result = session_builder_process_pre_key_signal_message(cipher->builder, record, ciphertext, &unsigned_pre_key_id); if(result < 0) { goto complete; } has_unsigned_pre_key_id = result; result = session_cipher_decrypt_from_record_and_signal_message(cipher, record, pre_key_signal_message_get_signal_message(ciphertext), &result_buf); if(result < 0) { goto complete; } result = session_cipher_decrypt_callback(cipher, result_buf, decrypt_context); if(result < 0) { goto complete; } result = signal_protocol_session_store_session(cipher->store, cipher->remote_address, record); if(result < 0) { goto complete; } if(has_unsigned_pre_key_id) { result = signal_protocol_pre_key_remove_key(cipher->store, unsigned_pre_key_id); if(result < 0) { goto complete; } } complete: SIGNAL_UNREF(record); if(result >= 0) { *plaintext = result_buf; } else { signal_buffer_free(result_buf); } signal_unlock(cipher->global_context); return result; }