-
Notifications
You must be signed in to change notification settings - Fork 485
ECC-step2: curves y^2 = x^3 + ax + b #236
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
Conversation
|
A note (#65 (comment)) related to this PR:
|
|
Another note related to this PR: We will need |
856a405 to
0499f30
Compare
sjaeckel
left a comment
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.
First part of a review... To Be Continued
src/headers/tomcrypt_pk.h
Outdated
| int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); | ||
| int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); | ||
| int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp); | ||
| int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key *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.
especially since this has the same signature as ecc_export(), how about re-using the same pattern that introduced PK_STD?
#define PK_RAW 0x2000
#define PK_COMPRESSED 0x4000
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.
With EC things are a bit tricky as we have couple more scenarios:
- there is just one way of exporting RAW private key
- RAW public key can be exported in full/long form
- of compressed/short form
we have our old DER format (basically compatible just with LTC) where the curve is identified just by its size - later when dealing with OpenSSL compatible DER format we can export the key + curve OID
- or the key + all curve params
I am not yet sure what would be the best approach here. But yes we can handle all of them in one single ecc_(import|export).
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.
On the other hand in ECC part 2 we call ecc_(import|export)_raw during importing/exporting OpenSSL keys as ecc_(import|export)_raw is kind of a lower level action.
src/headers/tomcrypt_pk.h
Outdated
| PK_PUBLIC=0, | ||
| PK_PRIVATE=1 | ||
| PK_PRIVATE=1, | ||
| PK_PUBLIC_COMPRESSED=2 /* used only when exporting public ECC 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.
c.f. my comment to ecc_export_raw()
|
|
||
| int ecc_verify_key(ecc_key *key); | ||
|
|
||
| #ifdef LTC_SOURCE |
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.
👍
src/pk/ecc/ecc_dp_find_by_name.c
Outdated
|
|
||
| for (i = 0; ltc_ecc_sets[i].size != 0; i++) { | ||
| if (ltc_ecc_sets[i].name != NULL && XSTRCMP(ltc_ecc_sets[i].name, curve_name) == 0) { | ||
| return (ltc_ecc_set_type*)<c_ecc_sets[i]; |
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.
why is this cast required?
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.
If you mean ecc_dp_find_by_name it is for convenience like:
dp = ecc_dp_find_by_name("SECP160R2");
err = ecc_make_key_ex(prng, wprng, key, dp);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.
what I meant was "why is this return (ltc_ecc_set_type*)<c_ecc_sets[i]; cast required?"
and I just got the answer... because the API signature is lying and you're returning a const object as non-const
src/pk/ecc/ecc_dp_find_by_name.c: In function ‘ecc_dp_find_by_name’:
src/pk/ecc/ecc_dp_find_by_name.c:20:17: warning: return discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
return <c_ecc_sets[i];
three possibilities to solve this in order of preference:
- make the return value a
const ltc_ecc_set_type* - make a copy of the object you want to return before returning it as non-const (which the caller then has to free)
- make
ltc_ecc_setsnot const
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 stuff gets even more complicated in ECC part 2 where we are importing keys in OpenSSL compatible DER format:
- one scenario is that the imported key has curve specified by OID - in this case we use
ecc_dp_find_by_oid(..)which finds correspondingltc_ecc_sets[i]item (const) - the other scenario is that the imported key has explicitly defined curve parametes - here we can try whether these curve params do exist in our
ltc_ecc_sets- this is the idea behindecc_dp_find_by_params(..)- otherwise we have to allocate and properly fillltc_ecc_set_typestructure and free it during the key destruction inecc_free(here it is tricky asecc_freehas no idea whether theltc_ecc_set_typestructure was dynamically allocated or not)
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.
and suddenly possibility 2 seems to become the preferred one, simply always allocate a copy so we can always free
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.
Yes, and it should be perhaps better named ecc_dp_new_by_name
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.
I have created some draft related to "possibility 2"
But it turned into a question: Why do we make copies of hexadecimal strings? It would make IMO more sense to convert those hex string into bignums during making a "copy":
src/pk/ecc/ecc_dp_find_by_oid.c
Outdated
| for (i = 0; ltc_ecc_sets[i].size != 0; i++) { | ||
| if ((oidsize == ltc_ecc_sets[i].oid.OIDlen) && | ||
| (XMEM_NEQ(oid, ltc_ecc_sets[i].oid.OID, sizeof(unsigned long) * ltc_ecc_sets[i].oid.OIDlen) == 0)) { | ||
| return (ltc_ecc_set_type*)<c_ecc_sets[i]; |
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.
same
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 can be moved to ECC part2, where it is required as some DER formats do not contain all curve parameters but only OID of the curve
src/pk/ecc/ecc_dp_find_by_params.c
Outdated
| _hexstrcmp(ltc_ecc_sets[i].Gx, hex_Gx) == 0 && | ||
| _hexstrcmp(ltc_ecc_sets[i].Gy, hex_Gy) == 0 && | ||
| ltc_ecc_sets[i].cofactor == cofactor) { | ||
| return (ltc_ecc_set_type*)<c_ecc_sets[i]; |
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.
same
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.
I'll will also move this to ECC part 2 (this one might end up removed completely)
src/pk/ecc/ecc_make_key.c
Outdated
| orderbits = mp_count_bits(order); | ||
| do { | ||
| if ((err = rand_bn_bits(key->k, orderbits, prng, wprng)) != CRYPT_OK) { goto errkey; } | ||
| } while (mp_iszero(key->k) || mp_cmp(key->k, order) != LTC_MP_LT); |
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.
looks like we'll loop here forever as well and that the standard says to do so...
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.
OK, I'll apply PK_MAX_RETRIES here
81a5ec5 to
85bda1e
Compare
|
Some thoughts about applying similar API ideas as we did in RSA, DSA, DH. This is what we have in 1.18-rc1 (and probably want to keep it for backwards compatibility): void ecc_sizes(int *low, int *high);
int ecc_get_size(ecc_key *key);
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp);
void ecc_free(ecc_key *key);
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp);
int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen);
int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);
int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, unsigned char *out, unsigned long *outlen);
int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, int hash, ecc_key *key);
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, ecc_key *key);
int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, ecc_key *key);
int ecc_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, ecc_key *key);
int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, ecc_key *key);
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, ecc_key *key);I propose the following new additions to public API in the "next" (UPDATED): int ecc_set_dp(const ltc_ecc_set_type *set, ecc_key *key);
int ecc_set_dp_name(const char *curve_name, ecc_key *key);
int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key);
int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key);
int ecc_export_key(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); |
34783be to
1e2f6f9
Compare
|
This PR was re-factored as proposed here: #236 (comment) Currently it is ready only for API review (I did my best to keep the API as much backwards compatible as possible). Definitely needs at least one more pass to check/add more LTC_ARGCHK's + check whether we correctly free what has to be freed etc. |
8f49290 to
5eb5544
Compare
5be9fa6 to
6277924
Compare
|
Just for record - the idea: int ecc_get_set(const char *curve_name, const ltc_ecc_set_type** dp);
/* or */
const ltc_ecc_set_type* ecc_get_set(const char *curve_name); |
12b889e to
9823d3f
Compare
|
UPDATE: the latest version of this PR adds the following to the public API int ecc_get_set_by_name(const char* name, const ltc_ecc_set_type** dp);
int ecc_set_dp(const ltc_ecc_set_type *set, ecc_key *key);
int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key);
int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key);
int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); |
99cd128 to
8874f75
Compare
|
closing this one? AFAICT it is still unmerged. |
|
sorry, already reopened |
8874f75 to
f54b702
Compare
b0dfaaa to
991d9e3
Compare
|
In the end I have decided for:
int ecc_get_curve(const char* name_or_oid, const ltc_ecc_curve** cu);
I just saw that. Bingo!
|
b41ed27 to
bbf2487
Compare
|
@fperrad could you please check (const params + usual stuff) with your linter |
84d8906 to
19c009b
Compare
|
@karel-m here, the harvest: |
|
@fperrad I have fixed all of them except: These look like false positives. Please re-run the check again. |
|
I agree look like false positive. There are 2 new ones: |
|
I missed this one: |
2db998a to
d112b0d
Compare
src/headers/tomcrypt_custom.h
Outdated
| #define LTC_ECC_SECP256R1 | ||
| #define LTC_ECC_SECP384R1 | ||
| #define LTC_ECC_SECP521R1 | ||
| /* OLD deprecated (but still working) defines */ |
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.
0001-don-t-use-deprecated-LTC_ECCxxx-defines-anymore.patch.txt
what do you think about applying this patch?
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.
The patch is good. Please commit&push it to this branch.
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.
applied & I was a bit surprised when the ./test ecc-run returned a nop instead of a passed :)
1a6cf0e to
54ba133
Compare
|
Should I start working on doc update or do we plan more changes to API / struct & co. ? |
|
Go for the docs! 👍 |
|
And feel free to squash again :) |
e0c7170 to
885f81d
Compare
|
FYI: I have tried to build dropbear with the API changes included in this PR. Unfortunately we are going to break dropbear build quite severely. I'll try to investigate whether we can somehow lower the impact. Or maybe we should simply submit a patch for dropbear alongside the release of this new API. |
I'll have a look and probably @mkj can add his two cents as well :) |
|
I'm fine with updating Dropbear to work with the new API - I've only had a quick look over it so far though. My main concern is how the ABI breakage happens if people have built Dropbear using system libtomcrypt on Debian - I guess the shared library version number will bump? |
0cd0205 to
362275e
Compare
|
@mkj my first draft (not in a pull-request quality yet) is here karel-m/dropbear@4530ff6 Ad ABI breakage we definitely will bump ABI & SO versions (as it turned out it is necessary even with smaller API changes than this one) |
sjaeckel
left a comment
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.
After the Xth try to review I arrived at the end of the PR :)
|
Great I'll squash it to a single commit and merge to develop. I'll open a separate PR for doc changes |
362275e to
24c0eb8
Compare
While hacking on
ecc_sign+verify_hash_rfc7518earlier today I realized that it would be possible to extract from my branchmiko-ecc-enhancementsthe crucial part implementing generalized elliptic curvesy^2 = x^3 + ax + b(currentdevelopbranch supports onlyy^2 = x^3 - 3x + b).The API changes comprise of the following new functions:
These are missing due to #187
ecc_export_full- export EC key in OpenSSL compatible formatecc_import_full- import EC key in OpenSSL compatible formatecc_import_pkcs8- import EC key in PKCS#8 format