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) { uint32_t *session_id = (uint32_t *)wrapped_message; uint8_t *iv = (uint8_t *)(session_id + 1); uint32_t *length = (uint32_t *)(iv + CIPHER_MAX_BLOCK_SIZE); uint32_t *seq = length + 1; uint8_t *ts = (uint8_t *)(seq + 1); uint64_t curr_time; themis_status_t res; if ((NULL == session_ctx) || (NULL == message) || (0 == message_length) || (NULL == wrapped_message_length)) { return THEMIS_INVALID_PARAMETER; } if ((NULL == wrapped_message) || (WRAPPED_SIZE(message_length) > *wrapped_message_length)) { *wrapped_message_length = WRAPPED_SIZE(message_length); return THEMIS_BUFFER_TOO_SMALL; } curr_time = time(NULL); if (-1 == curr_time) { return THEMIS_FAIL; } *((uint64_t *)ts) = htobe64(curr_time); *wrapped_message_length = WRAPPED_SIZE(message_length); memmove(ts + 8, message, message_length); *seq = htonl(session_ctx->out_seq); *length = htonl(message_length + sizeof(uint32_t) + sizeof(uint64_t)); res = soter_rand(iv, CIPHER_MAX_BLOCK_SIZE); if (THEMIS_SUCCESS != res) { return res; } res = encrypt_gcm(session_ctx->out_cipher_key, sizeof(session_ctx->out_cipher_key), iv, CIPHER_MAX_BLOCK_SIZE, length, message_length + sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t), length, message_length + sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t) + CIPHER_AUTH_TAG_SIZE); if (THEMIS_SUCCESS != res) { return res; } *session_id = htonl(session_ctx->session_id); session_ctx->out_seq++; return THEMIS_SUCCESS; }
void encrypt_box(uint8_t *keys, box *outer, size_t len) { box *inner = (box *) outer->data; uint8_t *outer_key = keys; uint8_t *inner_key = keys + BOX_KEY_LEN; randombytes(outer->iv, BOX_IV_LEN); randombytes(inner->iv, BOX_IV_LEN); uint8_t *data = inner->tag; size_t inner_len = len + crypto_secretbox_ZEROBYTES; memset(data, 0, crypto_secretbox_ZEROBYTES); assert(crypto_secretbox(data, data, inner_len, inner->iv, inner_key) == 0); encrypt_gcm(outer_key, outer->iv, outer->data, sizeof(box) + len, outer->tag); }