-
Notifications
You must be signed in to change notification settings - Fork 144
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
Symmetric keygen: Themis Core #560
Conversation
Properly group and document all members of this file. The definition of themis_key_kind_t is tweaked a bit so that Doxygen does not generate two entries for both the enum and the typedef. However, we still keep the "enum themis_key_kind" tag available.
Implement themis_gen_sym_key() function in Themis Core. Add tests. It's pretty much documented in doxygen comments. This is the actual key generation implementation which will be used by all wrappers.
THEMIS_KEY_INVALID, | ||
/** Private RSA key. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for what these comment lines which duplicate enum values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for what these comment lines which duplicate enum values?
Doxygen output looks better this way. If we describe enumerators then the enumeration gets a 'detailed description' section like all other declarations.
Though yeah, it does feel like infamous Java getter docs:
/**
* Returns success value.
*
* Use this method to get success value as boolean.
*
* @return boolean value `true` if successful, `false` if not successful.
*/
public boolean getSuccess() {
return succes;
}
🙄
tests/themis/themis_secure_cell.c
Outdated
|
||
res = themis_gen_sym_key(master_key, &master_key_length); | ||
testsuite_fail_unless(res == THEMIS_SUCCESS, "keygen: generate new key"); | ||
testsuite_fail_unless(master_key_length > 0, "keygen: key length returned"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will be better to more precisely compare result key length and check that master_key_length == MAX_KEY_SIZE
plus in tests of key generation, we should check that our generation function did something. for example compare that values of an array were changed after generation and not equal to previous values. plus we should check that each call of function return new random values and user can call this function as many times as he want to get new key, without calling somehing like RAND_seed(...)
in openssl. So we should check at least 2 calls and verify that it return different values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should check that each call of function return new random values
Sounds fair. It seems a good idea to test whether the cryptographic backend is sane. Standby for more tests.
Verify that we can generate big keys too, up to MAX_KEY_SIZE. Verify that key generation routines actually fill in the key buffer when they return THEMIS_SUCCESS, and that every invocation returns a different key.
tests/themis/themis_secure_cell.c
Outdated
|
||
res = themis_gen_sym_key(NULL, &master_key_1_length); | ||
testsuite_fail_unless(res == THEMIS_BUFFER_TOO_SMALL, "keygen: query key size"); | ||
testsuite_fail_unless(master_key_1_length > 0, "keygen: recommends non-empty key"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe will be better to check that result length is THEMIS_SYM_KEY_LENGTH
. with this check we will be sure that our generation function use this definition, not some hardcoded values or took elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This constant is not exported by design so that the users won't think that keys always have some fixed length, won't start preallocating fixed buffers, etc. We don't export key length constants for asymmetric keys too. The users just need to know that key length is some positive number. Currently we allow anything other than zero.
This check ensures that we never return zero length as it fails both key generation (in its current implementation) and future use of invalid key with Secure Cell (which does not allow zero-sized keys). I don't consider this a particular magic number.
If anything, I'd probably check that it's >= 32
— so that we never shorten the keys, only expand them — but that will be a magic number for real. If we export and use a constant directly then this check will allow us to redefine it to 16 without breaking tests.
Thus... I'd leave it as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't export but we should be sure that this define
used there and works as expected. it is not integration tests, it is unit test that verifies that function works as expected. we as authors expect that the key should be generated with predefined default value and check that it is expected value imho
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really have a suitable header to put it into, like <themis/secure_keygen_t.h> and I don't really want to introduce a new one just for this constant. Putting it into some random private header like <themis/secure_session_t.h> is also not nice.
I'd like to have this constant not visible when including <themis/themis.h> so that we don't have to maintain it as a part of public API. If it's visible then someone will notice it and use it, they could very well put a uint8_t themis_key[THEMIS_SYM_KEY_LENGTH]
somewhere into their data structures, then write them to disk, and now we cannot ever change this length to 64 because this breaks binary compatibility for the users.
If anything, I'd probably go with a copy for tests:
#define DEFAULT_SYM_KEY_LENGTH 32
then check that we return this value when the buffer is too small. It's not the same macro constant, but it has the same value, so if anyone changes THEMIS_SYM_KEY_LENGTH then they'll have to change it in the other place as well to fix the test. It's a bit more strict than checking for > 0
and avoids unnecessary exports.
Any second opinion? @vixentael, @ignatk, @storojs72?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
anyway, we will describe this in our docs, that default behavior of our function for key generation is to use random key with length=32. imho it's not some private value. it's the same as we describe that we use aes with 256 block size.
and yes, more opinion will be great to choose the final decision)
src/themis/secure_keygen.c
Outdated
return THEMIS_INVALID_PARAMETER; | ||
} | ||
if (key != NULL && *key_length == 0) { | ||
return THEMIS_INVALID_PARAMETER; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be "buffer too small" as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be "buffer too small" as well?
Mmm... Yeah, it probably should.
My reasoning was that requesting zero-length key is an error, but it can be equally understood as "zero-length buffer is too small, please expand".
I've checked asymmetric key generation API and it returns THEMIS_BUFFER_TOO_SMALL when given non-NULL buffer and zero length. It also outputs proper length into the provided pointer (like when buffer is NULL). So I guess we'll use the same behavior:
- if (key != NULL && *key_length == 0) {
- return THEMIS_INVALID_PARAMETER;
- }
-
- if (key == NULL) {
+ if (key == NULL || *key_length == 0) {
*key_length = THEMIS_SYM_KEY_LENGTH;
return THEMIS_BUFFER_TOO_SMALL;
}
Thanks for noticing!
Asymmetric key generation API considers zero length "too small", not an error, and outputs a proper length while returning approriate error code. Update symmetric key generation behavior for consistency.
After fierce discussion we have reached a compromise: we should do a more strict check than "returns length greater that zero", but we do not want to export THEMIS_SYM_KEY_LENGTH constant. Copying its value for tests is acceptable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Fantastic work! Merge 'em all! 👾 |
Implement symmetric key generation utilities described in RFC 1 (not available publicly at the moment). This is new API.
We are going to need a way to let our users generate strong symmetric keys for use with Secure Cell. This core function is the implementation of key generation. High-level wrappers will be using it to implement key generation.
The API has the usual “check – allocate – output” style found in other places in Themis:
The users are expected to first pass NULL for key to learn the default length, then allocate a suitable buffer and call the function again to receive key bytes. After that the key can be immediately used with Secure Cell. (Tests and examples for Secure Cell will be updated in next pull requests.)
Checklist
Benchmark results are attached(not interesting)Example projects and code samples are updated(will do later)