Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passphrase-based API of Secure Cell #577

Merged
merged 16 commits into from
Feb 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
Changes that are currently in development and have not been released yet.

**TL;DR:**
- Added API for generating symmetric keys for use with Secure Cell;
- Added API for generating symmetric keys for use with Secure Cell
- Added API for Secure Cell encryption with human-readable passphrases

_Code:_

Expand All @@ -19,6 +20,15 @@ _Code:_

- New function `themis_gen_sym_key()` can be used to securely generate symmetric keys for Secure Cell ([#560](https://github.com/cossacklabs/themis/pull/560)).

- **Secure Cell**

- New functions:

- `themis_secure_cell_encrypt_seal_with_passphrase()`
- `themis_secure_cell_decrypt_seal_with_passphrase()`

provide Seal mode API that is safe to use with passphrases ([#577](https://github.com/cossacklabs/themis/pull/577)).

- **C++**

- New function `themispp::gen_sym_key()` can be used to generate symmetric keys for Secure Cell ([#561](https://github.com/cossacklabs/themis/pull/561)).
Expand Down
8 changes: 8 additions & 0 deletions Themis.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@
9F4A2620223ABEF2005CB63A /* secure_session_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F4A242E223A74AF005CB63A /* secure_session_utils.c */; };
9F4A2621223ABEF2005CB63A /* secure_session.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F4A2438223A74AF005CB63A /* secure_session.c */; };
9F4A2622223ABEF2005CB63A /* sym_enc_message.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F4A2431223A74AF005CB63A /* sym_enc_message.c */; };
9F6B385523D9D11600EA5D1B /* secure_cell_seal_passphrase.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F6B385423D9D11600EA5D1B /* secure_cell_seal_passphrase.c */; };
9F6B385623D9D11600EA5D1B /* secure_cell_seal_passphrase.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F6B385423D9D11600EA5D1B /* secure_cell_seal_passphrase.c */; };
9F874AB322CCB0D100E8DECA /* soter_ec_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F874AB122CCB0D100E8DECA /* soter_ec_key.c */; };
9F874AB422CCB0D100E8DECA /* soter_ec_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F874AB122CCB0D100E8DECA /* soter_ec_key.c */; };
9F874AB522CCB0D100E8DECA /* soter_rsa_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 9F874AB222CCB0D100E8DECA /* soter_rsa_key.c */; };
Expand Down Expand Up @@ -256,6 +258,7 @@
9F00E8D7223C197900EC1EF3 /* themis.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = themis.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9F00E940223C1AFA00EC1EF3 /* openssl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = openssl.framework; path = Carthage/Build/Mac/openssl.framework; sourceTree = "<group>"; };
9F33485723B38D9B00368291 /* soter_kdf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = soter_kdf.c; path = src/soter/openssl/soter_kdf.c; sourceTree = "<group>"; };
9F34EA3023D9CA0A0079A1D7 /* secure_cell_seal_passphrase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = secure_cell_seal_passphrase.h; path = src/themis/secure_cell_seal_passphrase.h; sourceTree = "<group>"; };
9F4A2342223A73B0005CB63A /* soter_hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = soter_hash.h; path = src/soter/soter_hash.h; sourceTree = "<group>"; };
9F4A2343223A73B0005CB63A /* soter_asym_cipher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = soter_asym_cipher.h; path = src/soter/soter_asym_cipher.h; sourceTree = "<group>"; };
9F4A2344223A73B0005CB63A /* soter_sign_rsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = soter_sign_rsa.h; path = src/soter/soter_sign_rsa.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -405,6 +408,7 @@
9F4A24C1223A8FA8005CB63A /* skeygen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = skeygen.h; path = "src/wrappers/themis/Obj-C/objcthemis/skeygen.h"; sourceTree = "<group>"; };
9F4A24C2223A8FA8005CB63A /* smessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = smessage.h; path = "src/wrappers/themis/Obj-C/objcthemis/smessage.h"; sourceTree = "<group>"; };
9F4A24C3223A8FA8005CB63A /* scell_token.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scell_token.h; path = "src/wrappers/themis/Obj-C/objcthemis/scell_token.h"; sourceTree = "<group>"; };
9F6B385423D9D11600EA5D1B /* secure_cell_seal_passphrase.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = secure_cell_seal_passphrase.c; path = src/themis/secure_cell_seal_passphrase.c; sourceTree = "<group>"; };
9F874AB122CCB0D100E8DECA /* soter_ec_key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = soter_ec_key.c; path = src/soter/soter_ec_key.c; sourceTree = "<group>"; };
9F874AB222CCB0D100E8DECA /* soter_rsa_key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = soter_rsa_key.c; path = src/soter/soter_rsa_key.c; sourceTree = "<group>"; };
9F98F32422CCEA5D008E14E6 /* soter_wipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = soter_wipe.h; path = src/soter/soter_wipe.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -591,6 +595,8 @@
9F4A2430223A74AF005CB63A /* secure_cell_alg.h */,
9F4A241E223A74AE005CB63A /* secure_cell.c */,
9F4A242C223A74AF005CB63A /* secure_cell.h */,
9F6B385423D9D11600EA5D1B /* secure_cell_seal_passphrase.c */,
9F34EA3023D9CA0A0079A1D7 /* secure_cell_seal_passphrase.h */,
9F4A241F223A74AE005CB63A /* secure_comparator_t.h */,
9F4A2432223A74AF005CB63A /* secure_comparator.c */,
9F4A2434223A74AF005CB63A /* secure_comparator.h */,
Expand Down Expand Up @@ -808,6 +814,7 @@
9F00E925223C1AC000EC1EF3 /* soter_hash.c in Sources */,
9F00E926223C1AC000EC1EF3 /* soter_rand.c in Sources */,
9F874AB422CCB0D100E8DECA /* soter_ec_key.c in Sources */,
9F6B385623D9D11600EA5D1B /* secure_cell_seal_passphrase.c in Sources */,
9F00E927223C1AC000EC1EF3 /* soter_rsa_common.c in Sources */,
9F00E928223C1AC000EC1EF3 /* soter_rsa_key_pair_gen.c in Sources */,
9F00E929223C1AC000EC1EF3 /* soter_rsa_key.c in Sources */,
Expand Down Expand Up @@ -901,6 +908,7 @@
9F4A2608223ABECC005CB63A /* soter_hash.c in Sources */,
9F4A2609223ABECC005CB63A /* soter_rand.c in Sources */,
9F874AB322CCB0D100E8DECA /* soter_ec_key.c in Sources */,
9F6B385523D9D11600EA5D1B /* secure_cell_seal_passphrase.c in Sources */,
9F4A260A223ABECC005CB63A /* soter_rsa_common.c in Sources */,
9F4A260B223ABECC005CB63A /* soter_rsa_key_pair_gen.c in Sources */,
9F4A260C223ABECC005CB63A /* soter_rsa_key.c in Sources */,
Expand Down
116 changes: 116 additions & 0 deletions src/themis/secure_cell.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "themis/secure_cell.h"

#include "themis/secure_cell_seal_passphrase.h"
#include "themis/sym_enc_message.h"

themis_status_t themis_secure_cell_encrypt_seal(const uint8_t* master_key,
Expand Down Expand Up @@ -101,6 +102,121 @@ themis_status_t themis_secure_cell_decrypt_seal(const uint8_t* master_key,
plain_message_length);
}

themis_status_t themis_secure_cell_encrypt_seal_with_passphrase(const uint8_t* passphrase,
size_t passphrase_length,
const uint8_t* user_context,
size_t user_context_length,
const uint8_t* message,
size_t message_length,
uint8_t* encrypted_message,
size_t* encrypted_message_length)
{
themis_status_t res = THEMIS_FAIL;
size_t auth_token_length = 0;
size_t ciphertext_length = 0;
size_t total_length = 0;

THEMIS_CHECK_PARAM(encrypted_message_length != NULL);

/*
* Since Seal mode prepends authentication token to the message
* we need to get the size of this token at first.
*/
res = themis_auth_sym_encrypt_message_with_passphrase(passphrase,
passphrase_length,
message,
message_length,
user_context,
user_context_length,
NULL,
&auth_token_length,
NULL,
&ciphertext_length);
if (res != THEMIS_BUFFER_TOO_SMALL) {
return res;
}

total_length = auth_token_length + ciphertext_length;
if (!encrypted_message || *encrypted_message_length < total_length) {
*encrypted_message_length = total_length;
return THEMIS_BUFFER_TOO_SMALL;
}

res = themis_auth_sym_encrypt_message_with_passphrase(passphrase,
passphrase_length,
message,
message_length,
user_context,
user_context_length,
encrypted_message,
&auth_token_length,
encrypted_message + auth_token_length,
&ciphertext_length);
if (res == THEMIS_SUCCESS || res == THEMIS_BUFFER_TOO_SMALL) {
*encrypted_message_length = auth_token_length + ciphertext_length;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reuse total_length here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional because the themis_auth_sym_encrypt_message_with_passphrase() call might have modified those values. Of course, it does not modify them and accurately reports required lengths so we could reuse the value. But I'd leave that for future-proofing.

For all functions that return buffers, it's not strictly incorrect behavior to return slightly bigger required buffer size during measurement stage (BUFFER_TOO_SMALL) and then return accurate – and possibly smaller – actual size of the buffer used on SUCCESS. Currently we are able to accurately determine required length without actually processing the data, but it might not be the case in the future.

}
return res;
}

themis_status_t themis_secure_cell_decrypt_seal_with_passphrase(const uint8_t* passphrase,
size_t passphrase_length,
const uint8_t* user_context,
size_t user_context_length,
const uint8_t* encrypted_message,
size_t encrypted_message_length,
uint8_t* plain_message,
size_t* plain_message_length)
{
themis_status_t res = THEMIS_FAIL;
size_t auth_token_length = 0;
size_t message_length = 0;

THEMIS_CHECK_PARAM(plain_message_length != NULL);

/*
* Since Seal mode prepends authentication token to the message we need
* to get the size of this token at first. Token size is not available
* directly so we infer it from the size of encrypted message and
* plaintext message length embedded in the token.
*
* Note that this might fail if the encrypted message does not start with
* a valid token. It also might produce a false positive if the data looks
* like a token but does not contain valid measurements. This will lead to
* a decryption failure later.
*/
res = themis_auth_sym_decrypt_message_with_passphrase(passphrase,
passphrase_length,
user_context,
user_context_length,
encrypted_message,
encrypted_message_length,
NULL,
0,
NULL,
&message_length);
if (res != THEMIS_BUFFER_TOO_SMALL) {
return res;
}

/* We should not overflow here. If we do then the message is corrupted. */
if (encrypted_message_length < message_length) {
return THEMIS_FAIL;
}
auth_token_length = encrypted_message_length - message_length;

res = themis_auth_sym_decrypt_message_with_passphrase(passphrase,
passphrase_length,
user_context,
user_context_length,
encrypted_message,
auth_token_length,
encrypted_message + auth_token_length,
message_length,
plain_message,
plain_message_length);
return res;
}

themis_status_t themis_secure_cell_encrypt_token_protect(const uint8_t* master_key,
const size_t master_key_length,
const uint8_t* user_context,
Expand Down
Loading