Implementation details
This page outlines some high-level details how Themis objects are implemented. This can be used as starting point in reading code. We hope that this section will get extended soon.
Secure Message
Secure Message is data protection, integrity and authenticity method, available in a very simple wrapper.
Secure Message may be used in two modes:
- sign/verify (integrity and authenticity only)
- encrypt/decrypt (confidentiality, integrity and authenticity)
In sign/verify mode message will be signed by appropriate signature algorithm (ECDSA by default) and packed in THEMIS_SIGNED_MESSAGE_CONTAINER
.
In encrypt/decrypt mode message will be encrypted by randomly generated (in RSA) or derived by ECDH (in ECDSA) symmetric key. All additional necessary data for encryption will be derived by Themis and packed to THEMIS_ENCRYPTED_MESSAGE_CONTAINER
.
Selection of secure message mode can be made by setting key parameters to themis_secure_message_wrap function. If peer_public_key parameter set to NULL secure message will work in sign/verify mode, message will be signed and packet in THEMIS_SIGNED_MESSAGE_CONTAINER
:
themis_secure_message_wrap(
private_key,
private_key_length,
NULL, // peer_public_key
0, // peer_public_key_length
message,
message_length,
wrapped_message,
&wrapped_message_length);
If peer_public_key
parameter is set to peer's public key secure message will work in encrypt/decrypt mode, message will be encrypted and packed in THEMIS_ENCRYPTED_MESSAGE_CONTAINER
:
themis_secure_message_wrap(
private_key,
private_key_length,
peer_public_key,
peer_public_key_length
message,
message_length,
wrapped_message,
&wrapped_message_length);
Unwrapping mode is selected by parsing wrapped_message
header.
themis_secure_message_unwrap(
peer_private_key ,
peer_private_key_length,
public_key,
public_key_length,
wrapped_message,
wrapped_message_length,
unwrapped_message,
&unwrapped_message_length);
Secure Session
Secure Session depends on transport object which must be set by secure_session_create(init)
method:
themis_status_t secure_session_init(
secure_session_t *session_ctx,
const void *id, size_t id_length,
const void *sign_key,
size_t sign_key_length,
const secure_session_user_callbacks_t *user_callbacks);
secure_session_t* secure_session_create(
const void *id,
size_t id_length,
const void *sign_key,
size_t sign_key_length,
const secure_session_user_callbacks_t *user_callbacks);
transport object is represented by following stucture:
struct secure_session_user_callbacks_type
{
send_protocol_data_callback send_data;
receive_protocol_data_callback receive_data;
protocol_state_changed_callback state_changed;
get_public_key_for_id_callback get_public_key_for_id;
void *user_data;
};
with callbacks function pointers:
ssize_t (*send_protocol_data_callback)(
const uint8_t *data,
size_t data_length,
void *user_data);
ssize_t (*receive_protocol_data_callback)(
uint8_t *data,
size_t data_length,
void *user_data);
void (*protocol_state_changed_callback)(
int event,
void *user_data);
int (*get_public_key_for_id_callback)(
const void *id,
size_t id_length,
void *key_buffer,
size_t key_buffer_length,
void *user_data);
Function get_public_key_for_id_callback
is used to get public key for client id as necessary. This callback is mandatory, otherwise secure session will have no means to authenticate key exchange.
Functions send_protocol_data_callback
and receive_protocol_data_callback
used for sending and receiving data from communication channel respectively. send_protocol_data_callback
, if set, may be triggered by key exchange on session establishment, both send_protocol_data_callback
and receive_protocol_data_callback
will be triggered by secure_session_send
and secure_session_receive
to communicate over actual communication channel. If these functions are not set secure session object can still be used in wrap/unwrap mode (see below).
function protocol_state_changed_callback
is an optional callback which delivers secure_session state transitions to client applications.
Secure session object may be used in two modes:
- send/receive In this mode secure session object manage communication channel by itself with the help of
send_protocol_data_callback
andreceive_protocol_data_callback
methods.
ssize_t secure_session_send(
secure_session_t *session_ctx,
const void *message,
size_t message_length);
ssize_t secure_session_receive(
secure_session_t *session_ctx,
void *message,
size_t message_length);
- wrap/unwrap In this mode
send_protocol_data_callback
andreceive_protocol_data_callback
methods are not used. Wrapped message will be returned to the user in a buffer.
themis_status_t secure_session_wrap(
secure_session_t *session_ctx,
const void *message,
size_t message_length,
void *wrapped_message,
size_t *wrapped_message_length);
themis_status_t secure_session_unwrap(
secure_session_t *session_ctx,
const void *wrapped_message,
size_t wrapped_message_length,
void *message,
size_t *message_length);
- mixed mode. Any combination of the above may work as well. For example,
send_protocol_data_callback
may be set andsecure_session_send
may be used to send data, andsecure_session_unwrap
may be used to decrypt data in application receive path.
Secure Cell
Secure cell may work in three modes:
seal mode - all output data (encrypted message, auth tag, iv etc.) will be generated by themis and packed in one output buffer
/* encrypt */
themis_secure_cell_encrypt_full(passwd, passwd_length, message, message_length, encrypted_message, &encrypted_message_length);
/* decrypt */
themis_secure_cell_decrypt_full(passwd, passwd_length, encrypted_message, encrypted_message_length, decrypted_message, &decrypted_message_length);
token-protect mode - additional encrypting data (auth_tag, iv etc.) named as token is generated by themis and stored in separate buffer from encrypted message (preserving the length of the original message).
/* encrypt */
themis_secure_cell_encrypt_auto_split(passwd, passwd_length, message, message_length, additional_encrypting_data, &additional_encrypting_data_length, encrypted_message, &encrypted_message_length);
/* decrypt */
themis_secure_cell_decrypt_auto_split(passwd, passwd_length, encrypted_message, encrypted_message_length, additional_encrypting_data, additional_encrypting_data_length, decrypted_message, &decrypted_message_length);
context-imprint mode - all necessary additional encrypting data is derived from user`s context data:
/* encrypt */
themis_secure_cell_encrypt_user_split(passwd, passwd_length, message, message_length, user_context, user_context_length, encrypted_message, &encrypted_message_length);
/* decrypt */
themis_secure_cell_decrypt_user_split(passwd, passwd_length, encrypted_message, encrypted_message_length, user_context, user_context_length, decrypted_message, &decrypted_message_length);