Merge lp:~hipl-core/hipl/hipv2-dh-ecdh into lp:hipl
- hipv2-dh-ecdh
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 6437 |
Proposed branch: | lp:~hipl-core/hipl/hipv2-dh-ecdh |
Merge into: | lp:hipl |
Diff against target: |
2283 lines (+1434/-318) 15 files modified
libcore/builder.c (+6/-5) libcore/crypto.c (+178/-1) libcore/crypto.h (+33/-6) libcore/protodefs.h (+1/-0) libhipl/cookie.c (+79/-56) libhipl/cookie.h (+8/-17) libhipl/dh.c (+299/-70) libhipl/dh.h (+14/-6) libhipl/hidb.c (+6/-11) libhipl/hidb.h (+19/-3) libhipl/input.c (+115/-24) libhipl/netdev.c (+19/-2) libhipl/output.c (+324/-114) libhipl/output.h (+12/-2) test/libcore/crypto.c (+321/-1) |
To merge this branch: | bzr merge lp:~hipl-core/hipl/hipv2-dh-ecdh |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Diego Biurrun | Needs Information | ||
Christof Mroz | Approve | ||
Miika Komu | Pending | ||
Review via email: mp+131786@code.launchpad.net |
This proposal supersedes a proposal from 2012-09-08.
Commit message
Description of the change
Hi,
I haven't heard from Xin for a while. I fixed two things on this branch:
* The cookie indexing bug that Christof discovered
* The code passes now commit hooks
We need this code for HIPv2. At the moment, I don't have much time to restructure/
8 September 2012
Revise code based on Diego's review comments.
Sorry for my delay.
=======
This branch includes new ECDH functions and implements the new DH negotiation
mechanism for HIPv2:
ECDH is implemented using the library of openssl. (check libcore/cypto.c), I
also added some tests for those functions (test/libcore/
The DH_GROUP_LIST parameter (511) is added to the protocol for DH negotiation
in HIPv2. This new parameter changes the format of I1 and R1, and new functions
for handling this parameter and DH negotiation process are added.
NOTE: Other new parameters introduced by HIPv2 is not implemented in this
branch.
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal | # |
review needs-fixing
On Sat, Sep 08, 2012 at 08:35:22AM +0000, Xin wrote:
> Xin has proposed merging lp:~hipl-core/hipl/hipv2-dh-ecdh into lp:hipl.
>
> Requested reviews:
> HIPL core team (hipl-core)
>
> For more details, see:
> https:/
>
> 8 September 2012
>
> Revise code based on Diego's review comments.
> Sorry for my delay.
You sort of addressed my comments, but I'm really not sure how thorough.
In order to check for simple oversights I searched this email for "llips"
and immediately caught an error I pointed out but you failed to fix.
It seems that all newly-added memory allocations are checked now. This
is good; unfortunately unchecked memory allocations still happen left
and right in HIPL.
This whole review business is rather pointless if the comments are not
addressed. If I can find mistakes in your revised code literally within
seconds then we have serious quality control issues as a project.
Maybe this is just a minor oversight about a minor issue, maybe not.
Bugs tend to appear in clusters, so I'm suspicious. How could we fix
this? Would some sort of checklist or a list of common mistakes to
look out for help?
> --- libhipl/cookie.c 2012-06-03 10:26:55 +0000
> +++ libhipl/cookie.c 2012-09-08 08:34:18 +0000
> @@ -219,41 +218,93 @@
>
> +struct hip_common *hip_get_
> + struct in6_addr *our_hit, const int dh_group_id)
> +{
> + /* Create a copy of the found entry */
> + len = hip_get_
> + if (len <= 0) {
> + HIP_ERROR("Invalid r1_v2 entry at %d, %d\n", dh_group_id, idx);
> + return NULL;
> + }
> +
> + if((r1 = hip_msg_alloc()) == NULL) {
if (
Is your uncrustify hook not working?
Diego
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal | # |
Looks good overall, I found one potential bug though (the thing about possibly mismatched indices below), but I'm not sure.
The other comments are not critical.
> === modified file 'libcore/builder.c'
> --- libcore/builder.c 2012-07-13 13:16:17 +0000
> +++ libcore/builder.c 2012-09-08 08:34:18 +0000
> @@ -119,7 +119,8 @@
> * @param content the buffer to hold all the items
> * @param count the number of items in the buffer
> * @param item_size the size of each item in bytes. The function only supports
> - * items in 2 bytes or 4 bytes.
> + * byte conversion for items in 2 bytes or 4 bytes. For items
> + * with other size, no conversion will be applied.
> * @param flag the flag to decide the byte conversion order
> */
> static void convert_
> @@ -128,14 +129,12 @@
> uint32_t (*f32)(uint32_t) = (flag == CBO_HTON) ? htonl : ntohl;
> uint16_t (*f16)(uint16_t) = (flag == CBO_HTON) ? htons : ntohs;
>
> - HIP_ASSERT(
> -
Why do you let this pass now? Does it make sense to specify anything other than 16 or 32 bit?
> @@ -325,6 +331,10 @@
> sizeof(
> sizeof(
> sizeof(
> + 64, /* NIST P-256 */
> + 96, /* NIST P-384 */
> + 132, /* NIST P-512 */
> + 0, /* SECP 160R1, unsupported */
> };
Can you easily avoid magic numbers here?
> @@ -701,6 +711,172 @@
> + gettimeofday(&tv, NULL);
> + sprintf(rnd_seed, "%x%x", (unsigned int) tv.tv_usec,
> + (unsigned int) tv.tv_sec);
> + RAND_seed(rnd_seed, sizeof(rnd_seed));
Would
RAND_seed(&tv.sec, sizeof(tv.sec));
RAND_seed(&tv.usec, sizeof(tv.usec));
or even
RAND_seed(&tv, sizeof(tv)); // many predictable bytes though. RAND_add()?
work too? I don't know about crypto, but the number of different byte sequences
you can produce this way should be exactly the same as with sprintf().
> + if (EC_METHOD_
> + != NID_X9_
> + HIP_ERROR("Invalid group method, only prime curve is supported.\n");
> + return 0;
> + }
> +
> + peer_pub = EC_POINT_
Can this fail? Also applies to the other openssl *_new() functions.
> + out = ECDH_compute_
> + HIP_IFEL(out == 0 || out != peer_len, 0,
> + "Failed to compute the ECDH shared key\n");
Does checking for "out != peer_len" suffice?
> + if (key == NULL || out == NULL || outlen < 0 ||
> + EC_KEY_
> + HIP_ERROR("Invalid input\n");
> + return -1;
> + }
The first three conditions look like they should be assertions, to me.
The last one too perhaps, because you should have checked the key up to this point anyway.
> === modified file 'libcore/crypto.h'
> --- libcore/crypto.h 2012-05-12 10:21:32 +0000
> +++ libcore/crypto.h 2012-09-08 08:34:18 +0000
> @@ -51,15 +52,25 @@
>
> /* These should be c...
Xin (eric-nevup) wrote : Posted in a previous version of this proposal | # |
Hi,
On 09/10/2012 03:19 PM, Diego Biurrun wrote:
> review needs-fixing
> You sort of addressed my comments, but I'm really not sure how thorough.
> In order to check for simple oversights I searched this email for "llips"
> and immediately caught an error I pointed out but you failed to fix.
oops, I read the merge diff line by line before I commit it, but it
seems that I still miss some points.
>
> It seems that all newly-added memory allocations are checked now. This
> is good; unfortunately unchecked memory allocations still happen left
> and right in HIPL.
This is not related to this merge right? If we should discuss how to fix
them, I think it is better to put it into another mail thread, or fire a
bug?
>
> This whole review business is rather pointless if the comments are not
> addressed. If I can find mistakes in your revised code literally within
> seconds then we have serious quality control issues as a project.
People do make mistakes, if you check how many "llips" I have fixed and
how I fix your other comments, maybe you will feel a sense of relief.
>> --- libhipl/cookie.c 2012-06-03 10:26:55 +0000
>> +++ libhipl/cookie.c 2012-09-08 08:34:18 +0000
>> @@ -219,41 +218,93 @@
>>
>> +struct hip_common *hip_get_
>> + struct in6_addr *our_hit, const int dh_group_id)
>> +{
>> + /* Create a copy of the found entry */
>> + len = hip_get_
>> + if (len <= 0) {
>> + HIP_ERROR("Invalid r1_v2 entry at %d, %d\n", dh_group_id, idx);
>> + return NULL;
>> + }
>> +
>> + if((r1 = hip_msg_alloc()) == NULL) {
> if (
>
> Is your uncrustify hook not working?
Yeah, I turned it off because some of code changes will violate it, but
I should have checked other codes. you have my apology.
--
Best regards,
Xin Gu
Xin (eric-nevup) wrote : Posted in a previous version of this proposal | # |
Hi,
On 09/13/2012 06:33 AM, Christof Mroz wrote:
> Review: Needs Information
>
> Looks good overall, I found one potential bug though (the thing about possibly mismatched indices below), but I'm not sure.
> The other comments are not critical.
>
>> === modified file 'libcore/builder.c'
>> --- libcore/builder.c 2012-07-13 13:16:17 +0000
>> +++ libcore/builder.c 2012-09-08 08:34:18 +0000
>> @@ -119,7 +119,8 @@
>> * @param content the buffer to hold all the items
>> * @param count the number of items in the buffer
>> * @param item_size the size of each item in bytes. The function only supports
>> - * items in 2 bytes or 4 bytes.
>> + * byte conversion for items in 2 bytes or 4 bytes. For items
>> + * with other size, no conversion will be applied.
>> * @param flag the flag to decide the byte conversion order
>> */
>> static void convert_
>> @@ -128,14 +129,12 @@
>> uint32_t (*f32)(uint32_t) = (flag == CBO_HTON) ? htonl : ntohl;
>> uint16_t (*f16)(uint16_t) = (flag == CBO_HTON) ? htons : ntohs;
>>
>> - HIP_ASSERT(
>> -
> Why do you let this pass now? Does it make sense to specify anything other than 16 or 32 bit?
I use this function to build the DH_GROUP_LIST parameter, which is a
list of 8bit items, so I remove this assertion because otherwise you
need to do something like:
if (item_size != sizeof(uint16_t) || item_size != sizeof(uint32_t)) {
convert_
}
I think this extra if statement is unnecessary since in the
convert_byte_order function we have checked it already.
====
Thanks for your other comments. I recently have stacked many mails and
realized that I have blocked many processes. My problem is that I have
went back to China and started to work for a startup company. We have a
quite tight development timetable on which I have to spend most of my
time. I will try to fix the HIPL ECDH branch as soon as possible, but it
is really difficult for me to give a time guarantee. If it is urgent,
maybe someone can continue this work since the branch is already owned
by hipl-core,
--
Best regards,
Xin Gu
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal | # |
On 15.09.2012 18:46, Xin wrote:
>>> - HIP_ASSERT(
>> Why do you let this pass now? Does it make sense to specify anything other than 16 or 32 bit?
>
> I use this function to build the DH_GROUP_LIST parameter, which is a
> list of 8bit items, so I remove this assertion because otherwise you
> need to do something like:
Ah yes sorry, you wrote that in the docs. Okay then.
> Thanks for your other comments. I recently have stacked many mails and
> realized that I have blocked many processes. My problem is that I have
> went back to China and started to work for a startup company. We have a
> quite tight development timetable on which I have to spend most of my
> time. I will try to fix the HIPL ECDH branch as soon as possible, but it
> is really difficult for me to give a time guarantee. If it is urgent,
> maybe someone can continue this work since the branch is already owned
> by hipl-core,
Only one of my comments was critical I think, and maybe it is no bug at
all. It's the one concerning the possible mixup of array indices. I'll
repeat the one:
On 13.09.2012 00:33, Christof Mroz wrote:
>> + for (j = 0; j < HIP_DH_
>> + group_id = HIP_DH_
>> + for (i = 0; i < HIP_R1TABLESIZE; i++) {
>> + cookie_k = get_cookie_
>> + hip_msg_
>> +
>> + if (hip_create_
>> + privkey, pubkey, cookie_k, group_id)) {
>> + HIP_ERROR("Unable to precreate R1_v2\n");
>> + return -1;
>> + }
>
> You use index j for hip_msg_init(), but index group_id for hip_create_r1_v2(). Is this intentional?
Good luck with the startup.
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
Hi,
On 09/15/2012 07:46 PM, Xin wrote:
> Thanks for your other comments. I recently have stacked many mails and
> realized that I have blocked many processes. My problem is that I have
> went back to China and started to work for a startup company. We have a
> quite tight development timetable on which I have to spend most of my
> time. I will try to fix the HIPL ECDH branch as soon as possible, but it
> is really difficult for me to give a time guarantee. If it is urgent,
> maybe someone can continue this work since the branch is already owned
> by hipl-core,
Xin, you efforts are highly appreciated. Thanks for contributing even
though you're not working for us anymore. Let's try to get this code
integrated so that we start interoperating the code with OpenHIP at some
point - this is important also for the standardization.
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal | # |
On Sun, Sep 16, 2012 at 12:15:22AM +0800, Xin Gu wrote:
> On 09/10/2012 03:19 PM, Diego Biurrun wrote:
> > review needs-fixing
> >You sort of addressed my comments, but I'm really not sure how thorough.
> >In order to check for simple oversights I searched this email for "llips"
> >and immediately caught an error I pointed out but you failed to fix.
>
> oops, I read the merge diff line by line before I commit it, but it
> seems that I still miss some points.
>
> >It seems that all newly-added memory allocations are checked now. This
> >is good; unfortunately unchecked memory allocations still happen left
> >and right in HIPL.
>
> This is not related to this merge right? If we should discuss how to
> fix them, I think it is better to put it into another mail thread,
> or fire a bug?
Yes. While we do have the boyscout rule, we cannot expect you to fix
all unchecked memory allocation problems in HIPL. Of course you should
not make the problem worse by adding new ones though.
> >This whole review business is rather pointless if the comments are not
> >addressed. If I can find mistakes in your revised code literally within
> >seconds then we have serious quality control issues as a project.
>
> People do make mistakes, if you check how many "llips" I have fixed
> and how I fix your other comments, maybe you will feel a sense of
> relief.
I don't mean to imply that you're not making an effort. Your effort and
contribution is very much appreciated. Nonetheless we need to keep up
code quality and doublecheck each other's work.
If I review your code, notice an issue and find it again in the next
iteration you send, then I have not found a bug in the code, but in your
workflow. What we need to fix then is both the bug and the workflow so
that more such bugs don't reappear again. Everybody wins.
As a general rule, bugs appear in clusters. If I or one of my reviewers
notices a bug in some code I work on, I don't just fix that instance of
the bug. I make an effort to doublecheck the rest of the code I work on
and ideally all of the codebase for similar problems. In 99% of the
cases I stumble over more issues in this way.
How you look for similar issues depends on the case. For typos you can
grep, for other issues you might want to use a regexp grep or look through
relevant files manually.
In the case of your typo, you should not just look at my review comments
and fix all of the ones I pointed out. I could have overlooked one,
reviewers make mistakes as well; grep does not. Plus, it could even be
faster, so everybody wins.
> >>--- libhipl/cookie.c 2012-06-03 10:26:55 +0000
> >>+++ libhipl/cookie.c 2012-09-08 08:34:18 +0000
> >>@@ -219,41 +218,93 @@
> >>+struct hip_common *hip_get_
> >>+ struct in6_addr *our_hit, const int dh_group_id)
> >>+{
> >>+ /* Create a copy of the found entry */
> >>+ len = hip_get_
> >>+ if (len <= 0) {
> >>+ HIP_ERROR("Invalid r1_v2 entry at %d, %d\n", dh_group_id, idx);
> >>+ return NULL;
> >>+ }
> >>+
> >>+ if((r1 = hip_msg_alloc()) == NUL...
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
I tried a local merge+commit and the following things break with the hook:
The following differences were found between the code to commit and the rules in '.uncrustify-
--- /home/mkomu/
+++ - 2012-09-17 15:37:59.286725479 +0300
@@ -250,7 +250,7 @@
return NULL;
}
- if((r1 = hip_msg_alloc()) == NULL) {
+ if ((r1 = hip_msg_alloc()) == NULL) {
return NULL;
}
--- /home/mkomu/
+++ - 2012-09-17 15:37:59.438372623 +0300
@@ -341,7 +341,7 @@
static int add_echo_
{
int param_type = sign ? HIP_PARAM_
- : HIP_PARAM_
+ : HIP_PARAM_
const struct hip_echo_msg *ping = hip_get_
Christof Mroz (christof-mroz) wrote : | # |
On 28.10.2012 17:35, Miika Komu wrote:
> We need this code for HIPv2. At the moment, I don't have much time to restructure/
I looked through your recent commits but not the whole thing.
> + for (j = 0; j < HIP_DH_
> + group_id = HIP_DH_
> + for (i = 0; i < HIP_R1TABLESIZE; i++) {
> + cookie_k = get_cookie_
> + hip_msg_
> +
> + if (hip_create_
> + privkey, pubkey, cookie_k, group_id)) {
> + HIP_ERROR("Unable to precreate R1_v2\n");
> + return -1;
> + }
> + HIP_DEBUG("R1_v2 Packets %d created for group: %d\n", i, group_id);
> + }
> + }
Looks good now, as long as the array bounds for id_entry->r1_v2 and HIP_DH_GROUP_LIST match.
On a minor note, the assignment to cookie_k could be moved out of the loop (and another one in the same function) unless get_cookie_
- 6265. By Miika Komu
-
Reducing code size of hip_precreate_r1() function in cookie.c
Christof Mroz noticed in the merge request #131786 in launchpad that
a variable was assigned unnecessarily in hip_precreate_r1().
Miika Komu (miika-iki) wrote : | # |
I have now moved cookie_k outside of the loop. Good catch!
Unless there are further comments by Friday, I'll merge the code by then.
Diego Biurrun (diego-biurrun) wrote : | # |
review needs-fixing
On Sun, Oct 28, 2012 at 04:35:25PM +0000, Miika Komu wrote:
>
> I haven't heard from Xin for a while. I fixed two things on this branch:
> * The cookie indexing bug that Christof discovered
> * The code passes now commit hooks
>
> We need this code for HIPv2. At the moment, I don't have much time to
> restructure/
> or high level comments, only specific ones! Thanks.
This branch should not be merged before the code duplication is addressed
IMNSHO. It's just too much and too much of a sin.
> --- libcore/crypto.c 2012-05-12 06:54:33 +0000
> +++ libcore/crypto.c 2012-10-28 16:34:23 +0000
> @@ -68,6 +69,11 @@
> #include "crypto.h"
>
>
> +const uint8_t HIP_DH_
> + HIP_DH_NIST_P_384,
> + HIP_DH_OAKLEY_15,
> + HIP_DH_OAKLEY_5
> +};
> /*
> * Diffie-Hellman primes
> */
This could use an empty line before the comment block.
> @@ -701,6 +711,172 @@
> +/**
> + * Generate a new Elliptic Curve Diffie-Hellman key.
> + *
> + * @param group_id the group ID of the DH_GROUP defined in HIPv2
> + * @return a new ECDH key (caller deallocates), or NULL on error.
> + */
> +EC_KEY *hip_generate_
> +{
> + char rnd_seed[20];
> + struct timeval tv;
> + EC_KEY *key;
> + int nid;
> +
> + if (group_id == HIP_DH_NIST_P_256) {
> + nid = NID_X9_
> + } else if (group_id == HIP_DH_NIST_P_384) {
> + nid = NID_secp384r1;
> + } else if (group_id == HIP_DH_NIST_P_521) {
> + nid = NID_secp521r1;
> + } else {
> + HIP_ERROR(
> + return NULL;
> + }
This calls for a switch statement.
> +int hip_gen_
> + const uint8_t *const peer_pub_x,
> + const uint8_t *const peer_pub_y,
> + const size_t peer_len,
> + uint8_t *const shared_key,
> + const size_t outlen)
> +{
> + const EC_GROUP *group;
> + BIGNUM *peer_pubx = NULL;
> + BIGNUM *peer_puby = NULL;
> + EC_POINT *peer_pub = NULL;
> + int err = 1;
> + unsigned int out;
> +
> + out = ECDH_compute_
> + HIP_IFEL(out == 0 || out != peer_len, 0,
> + "Failed to compute the ECDH shared key\n");
> + err = out;
The indirection through out seems quite pointless, why not assign to
err in the first place? Since ECDH_compute_key() returns int, this
is doubly weird.
> +int hip_encode_
> +{
> + BIGNUM *pubx = NULL;
> + BIGNUM *puby = NULL;
> + int len;
> + int err = 0;
> +
> + pubx = BN_new();
> + puby = BN_new();
> + HIP_IFEL(pubx == NULL || puby == NULL, -1, "Failed to initialize Big Number\n");
This rather looks like memory allocation failure and should return -ENOMEM.
> + if (EC_POINT_
> + ...
Xin (eric-nevup) wrote : | # |
On 10/30/2012 03:52 AM, Diego Biurrun wrote:
> Review: Needs Fixing
>> + if (EC_POINT_
>> + EC_KEY_
>> + pubx, puby, NULL) == 0) {
>> + HIP_ERROR("Failed to get x,y coordinates from the ECDH key\n");
>> + return -1;
>> + }
>> +
>> + len = BN_num_bytes(pubx);
>> + HIP_IFEL(outlen < len * 2, -1, "Output buffer too small\n");
>> +
>> + bn2bin_safe(pubx, out, outlen / 2);
>> + bn2bin_safe(puby, out + outlen / 2, outlen / 2);
>> +
>> + return outlen;
>> +
>> +out_err:
>> + BN_free(pubx);
>> + BN_free(puby);
>> + return err;
>> +}
> The use of the "err" variable is completely silly; it is never assigned
> to after initialization. Just get rid of it.
The "err" is used by HIP_IFEL.
BTW, I found another problem that I shouldn't do "return -1" after
"EC_POINT_
EC_POINT function will cause memleak on pubx and puby. It should be
fixed now.
>> --- libhipl/dh.c 2012-05-12 10:21:32 +0000
>> +++ libhipl/dh.c 2012-10-28 16:34:23 +0000
>> @@ -95,66 +97,288 @@
>> }
>>
>> /**
>> - * create a shared secret based on the public key of the peer
>> + * Store the bytes of the current ECDH public key in the given buffer.
>> + *
>> + * A new ECDH key will be created if it doesn't exist,
>> + *
>> + * @param buffer buffer to store the public part of the ECDH key
>> + * @param bufsize size of the @c buffer
>> + * @param group_id group ID of the ECDH key
>> + * @return the number of bytes written to the buffer, -1 on error.
>> + */
>> +int hip_insert_
>> +{
>> + EC_KEY *key;
>> + int ret;
>> +
>> + if (!hip_is_
>> + HIP_ERROR("Invalid group id for ECDH: %d\n", group_id);
>> + return -1;
>> + }
>> +
>> + if (ecdh_table[
>> + key = hip_generate_
>> + if (key == NULL) {
>> + HIP_ERROR("Failed to generate an ECDH key for group: %d\n",
>> + group_id);
>> + return -1;
>> + }
>> + ecdh_table[
>> + }
>> +
>> + key = ecdh_table[
>> + if ((ret = hip_encode_
>> + HIP_ERROR("Failed to encode the ECDH public key\n");
>> + return -1;
>> + }
>> +
>> + return ret;
>> +}
> This looks awfully similar to hip_insert_dh().
>
>> +static int regen_dh_key(const int group_id)
>> {
>> DH *tmp, *okey;
>> +
>> + tmp = hip_generate_
>> + if (!tmp) {
>> + HIP_INFO("Failed to generate a DH key for group: %d\n", group_id);
>> + return -1;
>> + }
>> +
>> + okey = dh_table[group_id];
>> + dh_table[group_id] = tmp;
>> +
>> + DH_free(okey);
>> + return 0;
>> +}
>> +
>> +#ifdef HAVE_EC_CRYPTO
>> +static int regen_ecdh_
>> +{
>> + EC_KEY *tmp, *okey;
>> +
>> + tmp = hip_generate_
>> + if (!tmp) {
>> + ...
Diego Biurrun (diego-biurrun) wrote : | # |
review needs-info
On Thu, Nov 01, 2012 at 03:16:20PM +0000, Xin wrote:
> On 10/30/2012 03:52 AM, Diego Biurrun wrote:
> > [...]
> >
> For these two comments, I don't think they are so similar that worth
> merging together. They have similar logic but operate on different data
> structures, also they are quite short.
We lack proper abstraction for the different crypto primitives.
> All other comments should be fixed. See
> http://
> <http://
> for my changes. Thanks.
This is looking much better now, thanks. Did you run your branch through
valgrind to check for memory handling errors? Also, did you try runnning
the unit tests through valgrind. That's a good way to spot errors, also,
the unit tests should be valgrind clean so that each new warning that
appears in the future is a clear bug and not a false positive.
Diego
- 6270. By Miika Komu
-
Synchronized with trunk revision 6406
- 6271. By Miika Komu
-
Synchronized with trunk revision 6436
Miika Komu (miika-iki) wrote : | # |
It's time to wrap this up. I did not detect any difference in leak counts when running valgrind through hipd or when running the unit tests through valgrind. I am going to merge this code because checking of memory leaks was the remaining task.
Preview Diff
1 | === modified file 'libcore/builder.c' |
2 | --- libcore/builder.c 2013-08-19 18:30:29 +0000 |
3 | +++ libcore/builder.c 2013-10-22 12:34:40 +0000 |
4 | @@ -119,7 +119,8 @@ |
5 | * @param content the buffer to hold all the items |
6 | * @param count the number of items in the buffer |
7 | * @param item_size the size of each item in bytes. The function only supports |
8 | - * items in 2 bytes or 4 bytes. |
9 | + * byte conversion for items in 2 bytes or 4 bytes. For items |
10 | + * with other size, no conversion will be applied. |
11 | * @param flag the flag to decide the byte conversion order |
12 | */ |
13 | static void convert_byte_order(void *content, unsigned count, |
14 | @@ -128,14 +129,12 @@ |
15 | uint32_t (*f32)(uint32_t) = (flag == CBO_HTON) ? htonl : ntohl; |
16 | uint16_t (*f16)(uint16_t) = (flag == CBO_HTON) ? htons : ntohs; |
17 | |
18 | - HIP_ASSERT(item_size == sizeof(uint16_t) || item_size == sizeof(uint32_t)); |
19 | - |
20 | if (item_size == sizeof(uint16_t)) { |
21 | uint16_t *p = content; |
22 | for (unsigned i = 0; i < count; i++) { |
23 | p[i] = f16(p[i]); |
24 | } |
25 | - } else { |
26 | + } else if (item_size == sizeof(uint32_t)) { |
27 | uint32_t *p = content; |
28 | for (unsigned i = 0; i < count; i++) { |
29 | p[i] = f32(p[i]); |
30 | @@ -730,7 +729,8 @@ |
31 | HIP_PARAM_ESP_PROT_ANCHOR, |
32 | HIP_PARAM_ESP_PROT_BRANCH, |
33 | HIP_PARAM_ESP_PROT_SECRET, |
34 | - HIP_PARAM_ESP_PROT_ROOT |
35 | + HIP_PARAM_ESP_PROT_ROOT, |
36 | + HIP_PARAM_DH_GROUP_LIST |
37 | }; |
38 | hip_tlv type = hip_get_param_type(param); |
39 | |
40 | @@ -1200,6 +1200,7 @@ |
41 | case HIP_PARAM_CERT: return "HIP_PARAM_CERT"; |
42 | case HIP_PARAM_CERT_X509_REQ: return "HIP_PARAM_CERT_X509_REQ"; |
43 | case HIP_PARAM_CERT_X509_RESP: return "HIP_PARAM_CERT_X509_RESP"; |
44 | + case HIP_PARAM_DH_GROUP_LIST: return "HIP_PARAM_DH_GROUP_LIST"; |
45 | case HIP_PARAM_DH_SHARED_KEY: return "HIP_PARAM_DH_SHARED_KEY"; |
46 | case HIP_PARAM_DIFFIE_HELLMAN: return "HIP_PARAM_DIFFIE_HELLMAN"; |
47 | case HIP_PARAM_DSA_SIGN_DATA: return "HIP_PARAM_DSA_SIGN_DATA"; |
48 | |
49 | === modified file 'libcore/crypto.c' |
50 | --- libcore/crypto.c 2013-09-20 06:29:24 +0000 |
51 | +++ libcore/crypto.c 2013-10-22 12:34:40 +0000 |
52 | @@ -46,6 +46,7 @@ |
53 | */ |
54 | |
55 | #include <errno.h> |
56 | +#include <stdbool.h> |
57 | #include <stdint.h> |
58 | #include <stdio.h> |
59 | #include <stdlib.h> |
60 | @@ -68,6 +69,12 @@ |
61 | #include "crypto.h" |
62 | |
63 | |
64 | +const uint8_t HIP_DH_GROUP_LIST[HIP_DH_GROUP_LIST_SIZE] = { |
65 | + HIP_DH_NIST_P_384, |
66 | + HIP_DH_OAKLEY_15, |
67 | + HIP_DH_OAKLEY_5 |
68 | +}; |
69 | + |
70 | /* |
71 | * Diffie-Hellman primes |
72 | */ |
73 | @@ -325,6 +332,10 @@ |
74 | sizeof(dhprime_modp_3072), |
75 | sizeof(dhprime_modp_6144), |
76 | sizeof(dhprime_modp_8192), |
77 | + 64, /* NIST P-256 */ |
78 | + 96, /* NIST P-384 */ |
79 | + 132, /* NIST P-512 */ |
80 | + 0, /* SECP 160R1, unsupported */ |
81 | }; |
82 | |
83 | static unsigned char dhgen[HIP_MAX_DH_GROUP_ID] = { 0, |
84 | @@ -701,6 +712,172 @@ |
85 | return dh; |
86 | } |
87 | |
88 | +#ifdef HAVE_EC_CRYPTO |
89 | + |
90 | +/** |
91 | + * Test if the current DH group ID belongs to an ECDH group. |
92 | + * |
93 | + * @param group_id the Diffie-Hellman group ID |
94 | + * @return True if the given group is an ECDH group, False otherwise. |
95 | + */ |
96 | +bool hip_is_ecdh_group(const int group_id) |
97 | +{ |
98 | + return group_id == HIP_DH_NIST_P_256 || |
99 | + group_id == HIP_DH_NIST_P_384 || |
100 | + group_id == HIP_DH_NIST_P_521; |
101 | +} |
102 | + |
103 | +/** |
104 | + * Generate a new Elliptic Curve Diffie-Hellman key. |
105 | + * |
106 | + * @param group_id the group ID of the DH_GROUP defined in HIPv2 |
107 | + * @return a new ECDH key (caller deallocates), or NULL on error. |
108 | + */ |
109 | +EC_KEY *hip_generate_ecdh_key(const int group_id) |
110 | +{ |
111 | + char rnd_seed[20]; |
112 | + struct timeval tv; |
113 | + EC_KEY *key; |
114 | + int nid; |
115 | + |
116 | + switch (group_id) { |
117 | + case HIP_DH_NIST_P_256: |
118 | + nid = NID_X9_62_prime256v1; |
119 | + break; |
120 | + case HIP_DH_NIST_P_384: |
121 | + nid = NID_secp384r1; |
122 | + break; |
123 | + case HIP_DH_NIST_P_521: |
124 | + nid = NID_secp521r1; |
125 | + break; |
126 | + default: |
127 | + HIP_ERROR("Unsupported ECDH group: %d\n", group_id); |
128 | + return NULL; |
129 | + } |
130 | + |
131 | + gettimeofday(&tv, NULL); |
132 | + sprintf(rnd_seed, "%x%x", (unsigned int) tv.tv_usec, |
133 | + (unsigned int) tv.tv_sec); |
134 | + RAND_seed(rnd_seed, sizeof(rnd_seed)); |
135 | + |
136 | + if ((key = EC_KEY_new_by_curve_name(nid)) == NULL) { |
137 | + HIP_ERROR("Failed to create a new EC_KEY from nid: %d\n", nid); |
138 | + return NULL; |
139 | + } |
140 | + |
141 | + if (EC_KEY_generate_key(key) == 0) { |
142 | + HIP_ERROR("Failed to generate parameters for the new EC_KEY.\n"); |
143 | + EC_KEY_free(key); |
144 | + return NULL; |
145 | + } |
146 | + |
147 | + return key; |
148 | +} |
149 | + |
150 | +/** |
151 | + * Generate a shared key using Elliptic Curve Diffie-Hellman. |
152 | + * This method only supports keys using Prime Curve. |
153 | + * |
154 | + * @param key the Elliptic Curve Diffie-Hellman key |
155 | + * @param peer_pub_x the x coordinator of the peer's public key |
156 | + * @param peer_pub_y the y coordinator of the peer's public key |
157 | + * @param peer_len length of the @c peer_pub_x or @c peer_pub_y (these two |
158 | + * length values are identical) |
159 | + * @param shared_key shared key to generate |
160 | + * @param outlen the length of the @c shared_key |
161 | + * @return the length of the shared key on success, 0 otherwise |
162 | + */ |
163 | +int hip_gen_ecdh_shared_key(EC_KEY *const key, |
164 | + const uint8_t *const peer_pub_x, |
165 | + const uint8_t *const peer_pub_y, |
166 | + const size_t peer_len, |
167 | + uint8_t *const shared_key, |
168 | + const size_t outlen) |
169 | +{ |
170 | + const EC_GROUP *group; |
171 | + BIGNUM *peer_pubx = NULL; |
172 | + BIGNUM *peer_puby = NULL; |
173 | + EC_POINT *peer_pub = NULL; |
174 | + unsigned int err = 1; |
175 | + |
176 | + if (EC_KEY_check_key(key) == 0) { |
177 | + HIP_ERROR("Invalid input EC_KEY\n"); |
178 | + return 0; |
179 | + } |
180 | + |
181 | + group = EC_KEY_get0_group(key); |
182 | + |
183 | + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) |
184 | + != NID_X9_62_prime_field) { |
185 | + HIP_ERROR("Invalid group method, only prime curve is supported.\n"); |
186 | + return 0; |
187 | + } |
188 | + |
189 | + peer_pub = EC_POINT_new(group); |
190 | + peer_pubx = BN_bin2bn(peer_pub_x, peer_len, NULL); |
191 | + peer_puby = BN_bin2bn(peer_pub_y, peer_len, NULL); |
192 | + |
193 | + HIP_IFEL(EC_POINT_set_affine_coordinates_GFp(group, peer_pub, peer_pubx, |
194 | + peer_puby, NULL) == 0, |
195 | + 0, "Failed to create peer's public key.\n"); |
196 | + |
197 | + err = ECDH_compute_key(shared_key, outlen, peer_pub, key, NULL); |
198 | + HIP_IFEL(err == 0 || err != peer_len, 0, |
199 | + "Failed to compute the ECDH shared key\n"); |
200 | + |
201 | +out_err: |
202 | + BN_free(peer_pubx); |
203 | + BN_free(peer_puby); |
204 | + EC_POINT_free(peer_pub); |
205 | + return err; |
206 | +} |
207 | + |
208 | +/** |
209 | + * Encode an ECDH public key into a character array. |
210 | + * |
211 | + * @param key the ECDH key |
212 | + * @param[out] out the character array |
213 | + * @param outlen the length of @c out in bytes |
214 | + * @return the number of bytes written |
215 | + */ |
216 | +int hip_encode_ecdh_publickey(EC_KEY *key, uint8_t *out, int outlen) |
217 | +{ |
218 | + BIGNUM *pubx = NULL; |
219 | + BIGNUM *puby = NULL; |
220 | + int len; |
221 | + int err = 0; |
222 | + |
223 | + if (key == NULL || out == NULL || outlen < 0 || |
224 | + EC_KEY_check_key(key) == 0) { |
225 | + HIP_ERROR("Invalid input\n"); |
226 | + return -1; |
227 | + } |
228 | + |
229 | + pubx = BN_new(); |
230 | + puby = BN_new(); |
231 | + HIP_IFEL(pubx == NULL || puby == NULL, -1, "Failed to initialize Big Number\n"); |
232 | + |
233 | + err = EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key), |
234 | + EC_KEY_get0_public_key(key), |
235 | + pubx, puby, NULL); |
236 | + HIP_IFEL(err == 0, -1, |
237 | + "Failed to get x,y coordinates from the ECDH key\n"); |
238 | + |
239 | + len = BN_num_bytes(pubx); |
240 | + HIP_IFEL(outlen < len * 2, -1, "Output buffer too small\n"); |
241 | + |
242 | + bn2bin_safe(pubx, out, outlen / 2); |
243 | + bn2bin_safe(puby, out + outlen / 2, outlen / 2); |
244 | + err = outlen; |
245 | + |
246 | +out_err: |
247 | + BN_free(pubx); |
248 | + BN_free(puby); |
249 | + return err; |
250 | +} |
251 | + |
252 | +#endif /* HAVE_EC_CRYPTO */ |
253 | + |
254 | /** |
255 | * Determine the size for required to store DH shared secret. |
256 | * @param hip_dh_group_type the group type from DIFFIE_HELLMAN parameter |
257 | @@ -714,7 +891,7 @@ |
258 | if (hip_dh_group_type == 0) { |
259 | HIP_ERROR("Trying to use reserved DH group type 0\n"); |
260 | } else if (hip_dh_group_type > ARRAY_SIZE(dhprime_len)) { |
261 | - HIP_ERROR("Unknown/unsupported MODP group %d\n", hip_dh_group_type); |
262 | + HIP_ERROR("Unknown/unsupported DH or ECDH group %d\n", hip_dh_group_type); |
263 | } else { |
264 | ret = dhprime_len[hip_dh_group_type]; |
265 | } |
266 | |
267 | === modified file 'libcore/crypto.h' |
268 | --- libcore/crypto.h 2012-05-12 10:21:32 +0000 |
269 | +++ libcore/crypto.h 2013-10-22 12:34:40 +0000 |
270 | @@ -1,5 +1,5 @@ |
271 | /* |
272 | - * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University. |
273 | + * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University. |
274 | * |
275 | * Permission is hereby granted, free of charge, to any person |
276 | * obtaining a copy of this software and associated documentation |
277 | @@ -28,6 +28,7 @@ |
278 | |
279 | #include "config.h" |
280 | |
281 | +#include <stdbool.h> |
282 | #include <stdint.h> |
283 | #include <netinet/in.h> |
284 | #include <sys/types.h> |
285 | @@ -51,15 +52,25 @@ |
286 | |
287 | /* These should be consistent with the table length in crypto.c and |
288 | * crypto/dh.c */ |
289 | -#define HIP_DH_384 1 /* 384-bit group */ |
290 | -#define HIP_DH_OAKLEY_1 2 /* 768-bit OAKLEY well known group 1 */ |
291 | +/* 384-bit group, DEPRECATED from HIPv2 */ |
292 | +#define HIP_DH_384 1 |
293 | +/* 768-bit OAKLEY well known group 1, DEPRECATED from HIPv2 */ |
294 | +#define HIP_DH_OAKLEY_1 2 |
295 | #define HIP_DH_OAKLEY_5 3 /* 1536-bit MODP group */ |
296 | #define HIP_DH_OAKLEY_15 4 /* 3072-bit MODP group */ |
297 | -#define HIP_DH_OAKLEY_17 5 /* 6144-bit MODP group */ |
298 | -#define HIP_DH_OAKLEY_18 6 /* 8192-bit MODP group */ |
299 | +/* 6144-bit MODP group, DEPRECATED from HIPv2 */ |
300 | +#define HIP_DH_OAKLEY_17 5 |
301 | +/* 8192-bit MODP group, DEPRECATED from HIPv2 */ |
302 | +#define HIP_DH_OAKLEY_18 6 |
303 | +/* Group 7 to 10 are new groups defined in HIPv2, among which group 7,8 and 9 |
304 | + * are Ellipse Curve groups. */ |
305 | +#define HIP_DH_NIST_P_256 7 |
306 | +#define HIP_DH_NIST_P_384 8 |
307 | +#define HIP_DH_NIST_P_521 9 |
308 | +#define HIP_DH_SECP_160_R1 10 |
309 | #define HIP_FIRST_DH_GROUP_ID HIP_DH_OAKLEY_5 |
310 | #define HIP_SECOND_DH_GROUP_ID HIP_DH_384 |
311 | -#define HIP_MAX_DH_GROUP_ID 7 |
312 | +#define HIP_MAX_DH_GROUP_ID 11 |
313 | |
314 | #define DSA_KEY_DEFAULT_BITS 1024 |
315 | #define RSA_KEY_DEFAULT_BITS 1024 |
316 | @@ -86,6 +97,13 @@ |
317 | #define HIP_SHA(buffer, total_len, hash) SHA((buffer), (total_len), (hash)) |
318 | #endif |
319 | |
320 | +/* HIPv2: default value for DH_GROUP_LIST parameter */ |
321 | +#define HIP_DH_GROUP_LIST_SIZE 3 |
322 | +const uint8_t HIP_DH_GROUP_LIST[HIP_DH_GROUP_LIST_SIZE]; |
323 | + |
324 | +/* HIPv2: max acceptable size of DH group list, longer part will be ignored */ |
325 | +#define HIP_DH_GROUP_MAX_RECV_SIZE 6 |
326 | + |
327 | int ssl_rsa_verify(uint8_t *digest, uint8_t *public_key, uint8_t *signature, int pub_klen); |
328 | int ssl_dsa_verify(uint8_t *digest, uint8_t *public_key, uint8_t *signature); |
329 | /* In kernel these come from crypto/dh.h, included above */ |
330 | @@ -121,6 +139,15 @@ |
331 | int impl_ecdsa_verify(const unsigned char *const digest, |
332 | EC_KEY *const ecdsa, |
333 | const unsigned char *const signature); |
334 | +bool hip_is_ecdh_group(const int group_id); |
335 | +EC_KEY *hip_generate_ecdh_key(const int group_id); |
336 | +int hip_encode_ecdh_publickey(EC_KEY *key, uint8_t *out, int outlen); |
337 | +int hip_gen_ecdh_shared_key(EC_KEY *const key, |
338 | + const uint8_t *const peer_pub_x, |
339 | + const uint8_t *const peer_pub_y, |
340 | + const size_t peer_len, |
341 | + uint8_t *const shared_key, |
342 | + const size_t outlen); |
343 | #endif /* HAVE_EC_CRYPTO */ |
344 | |
345 | #endif /* HIPL_LIBCORE_CRYPTO_H */ |
346 | |
347 | === modified file 'libcore/protodefs.h' |
348 | --- libcore/protodefs.h 2012-07-12 11:32:14 +0000 |
349 | +++ libcore/protodefs.h 2013-10-22 12:34:40 +0000 |
350 | @@ -143,6 +143,7 @@ |
351 | #define HIP_PARAM_SOLUTION 321 |
352 | #define HIP_PARAM_SEQ 385 |
353 | #define HIP_PARAM_ACK 449 |
354 | +#define HIP_PARAM_DH_GROUP_LIST 511 |
355 | #define HIP_PARAM_DIFFIE_HELLMAN 513 |
356 | #define HIP_PARAM_HIP_TRANSFORM 577 |
357 | #define HIP_PARAM_ENCRYPTED 641 |
358 | |
359 | === modified file 'libhipl/cookie.c' |
360 | --- libhipl/cookie.c 2012-06-03 10:26:55 +0000 |
361 | +++ libhipl/cookie.c 2013-10-22 12:34:40 +0000 |
362 | @@ -177,83 +177,99 @@ |
363 | } |
364 | |
365 | /** |
366 | - * get a copy of R1entry structure |
367 | + * Get a copy of R1entry structure. |
368 | * |
369 | * @param ip_i Initiator's IPv6 |
370 | * @param ip_r Responder's IPv6 |
371 | * @param our_hit Our HIT |
372 | - * @param hip_version HIP message version |
373 | - * |
374 | - * @note Comments for the if 0 code are inlined below. |
375 | - * |
376 | - * Returns NULL if error. |
377 | + * @param dh_group_id Diffie Hellman group ID. -1 for HIPv1, otherwise return |
378 | + R1 for HIPv2 |
379 | + * @return A R1 packet copy on success, NULL on error |
380 | */ |
381 | struct hip_common *hip_get_r1(struct in6_addr *ip_i, struct in6_addr *ip_r, |
382 | - struct in6_addr *our_hit, uint8_t hip_version) |
383 | + struct in6_addr *our_hit, const int dh_group_id) |
384 | { |
385 | - struct hip_common *err = NULL, *r1 = NULL; |
386 | - struct hip_r1entry *hip_r1table = NULL; |
387 | - struct local_host_id *hid = NULL; |
388 | + struct hip_common *r1 = NULL; |
389 | + struct hip_common *r1_matched = NULL; |
390 | + struct local_host_id *hid = NULL; |
391 | int idx, len; |
392 | |
393 | /* Find the proper R1 table and copy the R1 message from the table */ |
394 | - HIP_IFEL(!(hid = hip_get_hostid_entry_by_lhi_and_algo(our_hit, HIP_ANY_ALGO, -1)), |
395 | - NULL, "Unknown HIT\n"); |
396 | + hid = hip_get_hostid_entry_by_lhi_and_algo(our_hit, HIP_ANY_ALGO, -1); |
397 | + if (hid == NULL) { |
398 | + HIP_ERROR("Unknown HIT\n"); |
399 | + return NULL; |
400 | + } |
401 | |
402 | - hip_r1table = hid->r1[hip_version]; |
403 | - idx = calc_cookie_idx(ip_i, ip_r); |
404 | + idx = calc_cookie_idx(ip_i, ip_r); |
405 | HIP_DEBUG("Calculated index: %d\n", idx); |
406 | |
407 | + if (dh_group_id == -1) { |
408 | + r1_matched = &hid->r1[idx].buf.msg; |
409 | + } else { |
410 | + r1_matched = &hid->r1_v2[dh_group_id][idx].buf.msg; |
411 | + } |
412 | /* Create a copy of the found entry */ |
413 | - len = hip_get_msg_total_len(&hip_r1table[idx].buf.msg); |
414 | - r1 = hip_msg_alloc(); |
415 | - memcpy(r1, &hip_r1table[idx].buf.msg, len); |
416 | - err = r1; |
417 | - |
418 | -out_err: |
419 | - if (!err) { |
420 | - free(r1); |
421 | - } |
422 | - |
423 | - return err; |
424 | + len = hip_get_msg_total_len(r1_matched); |
425 | + if (len <= 0) { |
426 | + HIP_ERROR("Invalid r1 entry\n"); |
427 | + return NULL; |
428 | + } |
429 | + |
430 | + if ((r1 = hip_msg_alloc()) == NULL) { |
431 | + return NULL; |
432 | + } |
433 | + |
434 | + memcpy(r1, r1_matched, len); |
435 | + |
436 | + return r1; |
437 | } |
438 | |
439 | /** |
440 | - * precreate an R1 packet |
441 | + * HIPv1 & HIPv2: precreate R1 entries |
442 | * |
443 | - * @param r1table a pointer to R1 table structure |
444 | + * @param id_entry a pointer to host ID entry |
445 | * @param hit the local HIT |
446 | * @param sign a signing callback function |
447 | * @param privkey the private key to use for signing |
448 | * @param pubkey the host id (public key) |
449 | - * @param hip_version HIP message version |
450 | * @return zero on success and non-zero on error |
451 | */ |
452 | -int hip_precreate_r1(struct hip_r1entry *const r1table, |
453 | - const struct in6_addr *const hit, |
454 | +int hip_precreate_r1(struct local_host_id *id_entry, |
455 | + const hip_hit_t *const hit, |
456 | int (*sign)(void *const key, struct hip_common *const m), |
457 | void *const privkey, |
458 | - const struct hip_host_id *const pubkey, |
459 | - const uint8_t hip_version) |
460 | + const struct hip_host_id *const pubkey) |
461 | { |
462 | - int i = 0; |
463 | + const uint8_t cookie_k = get_cookie_difficulty(); |
464 | + int i, j, group_id; |
465 | + |
466 | for (i = 0; i < HIP_R1TABLESIZE; i++) { |
467 | - int cookie_k; |
468 | - |
469 | - cookie_k = get_cookie_difficulty(); |
470 | - |
471 | - hip_msg_init(&r1table[i].buf.msg); |
472 | - |
473 | - if (hip_create_r1(&r1table[i].buf.msg, hit, sign, privkey, pubkey, |
474 | - cookie_k, hip_version)) { |
475 | + hip_msg_init(&id_entry->r1[i].buf.msg); |
476 | + |
477 | + if (hip_create_r1(&id_entry->r1[i].buf.msg, hit, sign, privkey, |
478 | + pubkey, cookie_k)) { |
479 | HIP_ERROR("Unable to precreate R1s\n"); |
480 | - return 0; |
481 | - } |
482 | - |
483 | - HIP_DEBUG("Packet %d created\n", i); |
484 | - } |
485 | - |
486 | - return 1; |
487 | + return -1; |
488 | + } |
489 | + HIP_DEBUG("R1 Packet %d created\n", i); |
490 | + } |
491 | + |
492 | + for (j = 0; j < HIP_DH_GROUP_LIST_SIZE; j++) { |
493 | + group_id = HIP_DH_GROUP_LIST[j]; |
494 | + for (i = 0; i < HIP_R1TABLESIZE; i++) { |
495 | + hip_msg_init(&id_entry->r1_v2[group_id][i].buf.msg); |
496 | + |
497 | + if (hip_create_r1_v2(&id_entry->r1_v2[group_id][i].buf.msg, hit, sign, |
498 | + privkey, pubkey, cookie_k, group_id)) { |
499 | + HIP_ERROR("Unable to precreate R1_v2\n"); |
500 | + return -1; |
501 | + } |
502 | + HIP_DEBUG("R1_v2 Packets %d created for group: %d\n", i, group_id); |
503 | + } |
504 | + } |
505 | + |
506 | + return 0; |
507 | } |
508 | |
509 | /** |
510 | @@ -266,13 +282,17 @@ |
511 | * @param hdr a pointer to HIP packet common header |
512 | * @param solution a pointer to a solution structure |
513 | * @param hip_version HIP message version |
514 | + * @param dh_group_id the Diffie-Hellman group ID of the R1 entry. This |
515 | + * parameter is required for a HIPv2 cookie verification. |
516 | + * For v1, this parameter will be ignored. |
517 | * @return Zero if the cookie was verified successfully, negative |
518 | * otherwise. |
519 | */ |
520 | int hip_verify_cookie(struct in6_addr *ip_i, struct in6_addr *ip_r, |
521 | struct hip_common *hdr, |
522 | const struct hip_solution *solution, |
523 | - const uint8_t hip_version) |
524 | + const uint8_t hip_version, |
525 | + const int dh_group_id) |
526 | { |
527 | /* In a effort to conform the HIPL coding convention, the return value |
528 | * of this function was inverted. I.e. This function now returns |
529 | @@ -289,7 +309,12 @@ |
530 | HIP_ANY_ALGO, |
531 | -1)), |
532 | -1, "Requested source HIT not (any more) available.\n"); |
533 | - result = &hid->r1[hip_version][calc_cookie_idx(ip_i, ip_r)]; |
534 | + |
535 | + if (hip_version == HIP_V1) { |
536 | + result = &hid->r1[calc_cookie_idx(ip_i, ip_r)]; |
537 | + } else { |
538 | + result = &hid->r1_v2[dh_group_id][calc_cookie_idx(ip_i, ip_r)]; |
539 | + } |
540 | |
541 | puzzle = hip_get_param(&result->buf.msg, HIP_PARAM_PUZZLE); |
542 | HIP_IFEL(!puzzle, -1, "Internal error: could not find the cookie\n"); |
543 | @@ -344,7 +369,6 @@ |
544 | static int recreate_r1s_for_entry_move(struct local_host_id *entry, |
545 | UNUSED void *opaque) |
546 | { |
547 | - int i; |
548 | int (*signature_func)(void *const key, struct hip_common *const m); |
549 | |
550 | switch (hip_get_host_id_algo(&entry->host_id)) { |
551 | @@ -364,11 +388,10 @@ |
552 | return -1; |
553 | } |
554 | |
555 | - for (i = 1; i < HIP_MAX_VERSION; i++) { |
556 | - if (!hip_precreate_r1(entry->r1[i], &entry->hit, signature_func, |
557 | - entry->private_key, &entry->host_id, i)) { |
558 | - return -1; |
559 | - } |
560 | + if (hip_precreate_r1(entry, &entry->hit, signature_func, |
561 | + entry->private_key, &entry->host_id) < 0) { |
562 | + HIP_ERROR("Precreate r1 failed\n"); |
563 | + return -1; |
564 | } |
565 | |
566 | return 0; |
567 | |
568 | === modified file 'libhipl/cookie.h' |
569 | --- libhipl/cookie.h 2012-06-03 10:26:55 +0000 |
570 | +++ libhipl/cookie.h 2013-10-22 12:34:40 +0000 |
571 | @@ -30,32 +30,23 @@ |
572 | #include <netinet/in.h> |
573 | |
574 | #include "libcore/protodefs.h" |
575 | - |
576 | -#define HIP_R1TABLESIZE 3 /* precreate only this many R1s */ |
577 | - |
578 | -struct hip_r1entry { |
579 | - union hip_msg_bfr buf; |
580 | - uint32_t generation; |
581 | - uint8_t Ci[PUZZLE_LENGTH]; |
582 | - uint8_t Ck; |
583 | - uint8_t Copaque[HIP_PUZZLE_OPAQUE_LEN]; |
584 | -}; |
585 | +#include "libhipl/hidb.h" |
586 | |
587 | struct hip_common *hip_get_r1(struct in6_addr *ip_i, |
588 | struct in6_addr *ip_r, |
589 | - struct in6_addr *peer_hit, |
590 | - uint8_t hip_version); |
591 | + struct in6_addr *our_hit, |
592 | + const int dh_group_id); |
593 | int hip_recreate_all_precreated_r1_packets(void); |
594 | -int hip_precreate_r1(struct hip_r1entry *const r1table, |
595 | - const struct in6_addr *const hit, |
596 | +int hip_precreate_r1(struct local_host_id *id_entry, |
597 | + const hip_hit_t *const hit, |
598 | int (*sign)(void *const key, struct hip_common *const m), |
599 | void *const privkey, |
600 | - const struct hip_host_id *const pubkey, |
601 | - const uint8_t hip_version); |
602 | + const struct hip_host_id *const pubkey); |
603 | int hip_verify_cookie(struct in6_addr *ip_i, struct in6_addr *ip_r, |
604 | struct hip_common *hdr, |
605 | const struct hip_solution *cookie, |
606 | - const uint8_t hip_version); |
607 | + const uint8_t hip_version, |
608 | + const int dh_group_id); |
609 | int hip_inc_cookie_difficulty(void); |
610 | int hip_dec_cookie_difficulty(void); |
611 | int hip_get_puzzle_difficulty_msg(struct hip_common *msg); |
612 | |
613 | === modified file 'libhipl/dh.c' |
614 | --- libhipl/dh.c 2012-05-12 10:21:32 +0000 |
615 | +++ libhipl/dh.c 2013-10-22 12:34:40 +0000 |
616 | @@ -1,5 +1,5 @@ |
617 | /* |
618 | - * Copyright (c) 2010 Aalto University and RWTH Aachen University. |
619 | + * Copyright (c) 2010, 2012 Aalto University and RWTH Aachen University. |
620 | * |
621 | * Permission is hereby granted, free of charge, to any person |
622 | * obtaining a copy of this software and associated documentation |
623 | @@ -47,6 +47,8 @@ |
624 | */ |
625 | static DH *dh_table[HIP_MAX_DH_GROUP_ID] = { 0 }; |
626 | |
627 | +static EC_KEY *ecdh_table[HIP_MAX_DH_GROUP_ID] = { 0 }; |
628 | + |
629 | /** |
630 | * insert the current DH-key into the buffer |
631 | * |
632 | @@ -95,66 +97,288 @@ |
633 | } |
634 | |
635 | /** |
636 | - * create a shared secret based on the public key of the peer |
637 | + * Store the bytes of the current ECDH public key in the given buffer. |
638 | + * |
639 | + * A new ECDH key will be created if it doesn't exist, |
640 | + * |
641 | + * @param buffer buffer to store the public part of the ECDH key |
642 | + * @param bufsize size of the @c buffer |
643 | + * @param group_id group ID of the ECDH key |
644 | + * @return the number of bytes written to the buffer, -1 on error. |
645 | + */ |
646 | +int hip_insert_ecdh(uint8_t *buffer, int bufsize, int group_id) |
647 | +{ |
648 | + EC_KEY *key; |
649 | + int ret; |
650 | + |
651 | + if (!hip_is_ecdh_group(group_id)) { |
652 | + HIP_ERROR("Invalid group id for ECDH: %d\n", group_id); |
653 | + return -1; |
654 | + } |
655 | + |
656 | + if (ecdh_table[group_id] == NULL) { |
657 | + key = hip_generate_ecdh_key(group_id); |
658 | + if (key == NULL) { |
659 | + HIP_ERROR("Failed to generate an ECDH key for group: %d\n", |
660 | + group_id); |
661 | + return -1; |
662 | + } |
663 | + ecdh_table[group_id] = key; |
664 | + } |
665 | + |
666 | + key = ecdh_table[group_id]; |
667 | + if ((ret = hip_encode_ecdh_publickey(key, buffer, bufsize)) < 0) { |
668 | + HIP_ERROR("Failed to encode the ECDH public key\n"); |
669 | + return -1; |
670 | + } |
671 | + |
672 | + return ret; |
673 | +} |
674 | + |
675 | +/** |
676 | + * HIPv2: Store the bytes of the current ECDH/DH public key to the given buffer. |
677 | + * |
678 | + * An ECDH/DH key will be created if it does not exist. |
679 | + * |
680 | + * @param buffer the buffer to store the ECDH/DH public key |
681 | + * @param bufsize the size of the @c buffer |
682 | + * @param group_id the group ID of the ECDH/DH key |
683 | + * @return the number of bytes written to the buffer |
684 | + */ |
685 | +int hip_insert_dh_v2(uint8_t *buffer, int bufsize, int group_id) |
686 | +{ |
687 | + if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) { |
688 | + HIP_ERROR("Invalid DH_GROUP_ID: %d\n", group_id); |
689 | + return -1; |
690 | + } |
691 | + |
692 | + if (hip_is_ecdh_group(group_id)) { |
693 | + return hip_insert_ecdh(buffer, bufsize, group_id); |
694 | + } else { |
695 | + return hip_insert_dh(buffer, bufsize, group_id); |
696 | + } |
697 | +} |
698 | + |
699 | +/** |
700 | + * Match the first identical DH group ID in local and peer's list. |
701 | + * |
702 | + * @param dh_group_list the DH_GROUP_LIST parameter sent from the peer |
703 | + * @param our_dh_group the local DH list |
704 | + * @param our_group_size the size of the @c our_dh_group |
705 | + * @return ID of the matched group on success, -1 otherwise. |
706 | + */ |
707 | +int hip_match_dh_group_list(const struct hip_tlv_common *const dh_group_list, |
708 | + const uint8_t *const our_dh_group, |
709 | + const int our_group_size) |
710 | +{ |
711 | + int list_size = HIP_DH_GROUP_MAX_RECV_SIZE; |
712 | + uint8_t list[list_size]; |
713 | + int i, j; |
714 | + |
715 | + list_size = hip_get_list_from_param(dh_group_list, list, list_size, |
716 | + sizeof(uint8_t)); |
717 | + for (i = 0; i < list_size; i++) { |
718 | + for (j = 0; j < our_group_size; j++) { |
719 | + if (our_dh_group[j] == list[i]) { |
720 | + return our_dh_group[j]; |
721 | + } |
722 | + } |
723 | + } |
724 | + |
725 | + return -1; |
726 | +} |
727 | + |
728 | +/** |
729 | + * Calculate a Diffie-Hellman shared secret based on the public key of the peer |
730 | * (passed as an argument) and own DH private key (created beforehand). |
731 | * |
732 | - * @param public_value Peer's Diffie-Hellman public key |
733 | + * @param group_id the Diffie-Hellman group ID |
734 | + * @param public_value the Diffie-Hellman public key of the peer |
735 | + * @param len the length of the @c public_value |
736 | + * @param buffer the buffer that holds enough space for the shared secret |
737 | + * @param bufsize the size of the @c buffer |
738 | + * |
739 | + * @return the length of the shared secret in octets if successful, |
740 | + * or -1 if an error occurred. |
741 | + */ |
742 | +static int hip_calculate_dh_shared_secret(const uint16_t group_id, |
743 | + const uint8_t *const public_value, |
744 | + const int len, |
745 | + unsigned char *const buffer, |
746 | + const int bufsize) |
747 | +{ |
748 | + DH *key; |
749 | + int secret_len; |
750 | + |
751 | + if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) { |
752 | + HIP_ERROR("Invalid Group ID: %d.\n", group_id); |
753 | + return -1; |
754 | + } |
755 | + |
756 | + if (dh_table[group_id] == NULL) { |
757 | + if (NULL == (key = hip_generate_dh_key(group_id))) { |
758 | + HIP_ERROR("Failed to generate a DH key for group: %d\n", group_id); |
759 | + return -1; |
760 | + } |
761 | + dh_table[group_id] = key; |
762 | + } |
763 | + key = dh_table[group_id]; |
764 | + |
765 | + secret_len = hip_gen_dh_shared_key(dh_table[group_id], public_value, len, |
766 | + buffer, bufsize); |
767 | + if (secret_len < 0) { |
768 | + HIP_ERROR("failed to create a DH shared secret\n"); |
769 | + return -1; |
770 | + } |
771 | + |
772 | + return secret_len; |
773 | +} |
774 | + |
775 | +/** |
776 | + * Calculate an Elliptic Curve Diffie-Hellman shared secret. |
777 | + * |
778 | + * The length of the public value should match the corresponding ECDH group; The |
779 | + * buffer to hold the shared secret should be at least larger than the length of |
780 | + * the public value divided by 2. |
781 | + * |
782 | + * @param group_id the ECDH group ID |
783 | + * @param public_value Peer's ECDH public key |
784 | + * @param pubkey_len the length of the @c public_value |
785 | + * @param buffer Buffer that holds enough space for the shared secret |
786 | + * @param bufsize size of the @c buffer |
787 | + * |
788 | + * @return the length of the shared secret in octets if successful, |
789 | + * or -1 if an error occurred. |
790 | + */ |
791 | +static int hip_calculate_ecdh_shared_secret(const uint16_t group_id, |
792 | + const uint8_t *const public_value, |
793 | + const int pubkey_len, |
794 | + unsigned char *const buffer, |
795 | + const int bufsize) |
796 | +{ |
797 | + EC_KEY *key; |
798 | + int key_len; |
799 | + |
800 | + if (ecdh_table[group_id] == NULL) { |
801 | + if (NULL == (key = hip_generate_ecdh_key(group_id))) { |
802 | + HIP_ERROR("Failed to generate an ECDH key for group: %d\n", |
803 | + group_id); |
804 | + return -1; |
805 | + } |
806 | + ecdh_table[group_id] = key; |
807 | + } |
808 | + key = ecdh_table[group_id]; |
809 | + |
810 | + key_len = hip_get_dh_size(group_id); |
811 | + if (key_len != pubkey_len || key_len / 2 > bufsize) { |
812 | + HIP_ERROR("Invalid public key length (%d) or buffer size (%d)\n", |
813 | + pubkey_len, bufsize); |
814 | + return -1; |
815 | + } |
816 | + int out = hip_gen_ecdh_shared_key(key, public_value, |
817 | + public_value + key_len / 2, |
818 | + key_len / 2, |
819 | + buffer, |
820 | + bufsize); |
821 | + if (out <= 0) { |
822 | + HIP_ERROR("Failed to generate a shared secret\n"); |
823 | + return -1; |
824 | + } |
825 | + |
826 | + return out; |
827 | +} |
828 | + |
829 | +/** |
830 | + * Calculate a shared secret for Diffie-Hellman exchange. |
831 | + * |
832 | + * This function supports both normal DH and ECDH groups. The DH private key |
833 | + * is created beforehand. |
834 | + * |
835 | + * @param group_id the Diffie-Hellman group ID |
836 | + * @param public_value the Diffie-Hellman public key of the peer |
837 | + * @param len the length of the @c public_value |
838 | + * @param buffer Buffer that holds the shared secret |
839 | + * @param bufsize size of the @c buffer |
840 | + * |
841 | + * @return the length of the shared secret in octets if successful, |
842 | + * or -1 if an error occurred. |
843 | + */ |
844 | +int hip_calculate_shared_secret(const uint16_t group_id, |
845 | + const uint8_t *const public_value, |
846 | + const int len, |
847 | + unsigned char *const buffer, |
848 | + const int bufsize) |
849 | +{ |
850 | + if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) { |
851 | + HIP_ERROR("Invalid Diffie-Hellman group ID: %d\n", group_id); |
852 | + return -1; |
853 | + } |
854 | + |
855 | + if (hip_is_ecdh_group(group_id)) { |
856 | + return hip_calculate_ecdh_shared_secret(group_id, public_value, len, |
857 | + buffer, bufsize); |
858 | + } else { |
859 | + return hip_calculate_dh_shared_secret(group_id, public_value, len, |
860 | + buffer, bufsize); |
861 | + } |
862 | +} |
863 | + |
864 | +/** |
865 | + * Re-generate a DH key for a given group ID. |
866 | + * |
867 | * @param group_id the Diffie-Hellman group ID |
868 | - * @param len the length of the public value |
869 | - * @param buffer Buffer that holds enough space for the shared secret. |
870 | - * @param bufsize size of the buffer |
871 | - * |
872 | - * @return the length of the shared secret in octets if successful, |
873 | - * or -1 if an error occured. |
874 | - */ |
875 | -int hip_calculate_shared_secret(const uint8_t *public_value, |
876 | - uint8_t group_id, |
877 | - signed int len, |
878 | - unsigned char *buffer, |
879 | - int bufsize) |
880 | -{ |
881 | - int err = 0; |
882 | - DH *tmp; |
883 | - |
884 | - if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) { |
885 | - HIP_ERROR("The Group ID %d is invalid\n", group_id); |
886 | - return -1; |
887 | - } |
888 | - |
889 | - /* |
890 | - * First check that we have the key available. |
891 | - * Then encode it into the buffer |
892 | - */ |
893 | - |
894 | - if (dh_table[group_id] == NULL) { |
895 | - tmp = hip_generate_dh_key(group_id); |
896 | - dh_table[group_id] = tmp; |
897 | - |
898 | - if (dh_table[group_id] == NULL) { |
899 | - HIP_ERROR("Unsupported DH group: %d\n", group_id); |
900 | - return -1; |
901 | - } |
902 | - } |
903 | - |
904 | - err = hip_gen_dh_shared_key(dh_table[group_id], public_value, |
905 | - len, buffer, bufsize); |
906 | - if (err < 0) { |
907 | - HIP_ERROR("Could not create shared secret\n"); |
908 | - return -1; |
909 | - } |
910 | - |
911 | - return err; |
912 | -} |
913 | - |
914 | -/** |
915 | - * regenerate Diffie-Hellman keys for HIP |
916 | - * @param bitmask Mask of groups to generate. |
917 | - * |
918 | - * @note Use only this function to generate DH keys. |
919 | - */ |
920 | -static void regen_dh_keys(uint32_t bitmask) |
921 | + * @return 0 on success, -1 otherwise |
922 | + */ |
923 | +static int regen_dh_key(const int group_id) |
924 | { |
925 | DH *tmp, *okey; |
926 | + |
927 | + tmp = hip_generate_dh_key(group_id); |
928 | + if (!tmp) { |
929 | + HIP_INFO("Failed to generate a DH key for group: %d\n", group_id); |
930 | + return -1; |
931 | + } |
932 | + |
933 | + okey = dh_table[group_id]; |
934 | + dh_table[group_id] = tmp; |
935 | + |
936 | + DH_free(okey); |
937 | + return 0; |
938 | +} |
939 | + |
940 | +#ifdef HAVE_EC_CRYPTO |
941 | +/** |
942 | + * Re-generate DH key for a given ECDH group ID. |
943 | + * |
944 | + * @param group_id the ECDH group ID |
945 | + * @return 0 on success, -1 otherwise |
946 | + */ |
947 | +static int regen_ecdh_key(const int group_id) |
948 | +{ |
949 | + EC_KEY *tmp, *okey; |
950 | + |
951 | + tmp = hip_generate_ecdh_key(group_id); |
952 | + if (!tmp) { |
953 | + HIP_INFO("Failed to generate an ECDH key for group: %d\n", group_id); |
954 | + return -1; |
955 | + } |
956 | + |
957 | + okey = ecdh_table[group_id]; |
958 | + ecdh_table[group_id] = tmp; |
959 | + |
960 | + EC_KEY_free(okey); |
961 | + return 0; |
962 | +} |
963 | + |
964 | +#endif /* HAVE_EC_CRYPTO */ |
965 | + |
966 | +/** |
967 | + * HIPv2: regenerate Diffie-Hellman keys. |
968 | + * |
969 | + * @param bitmask the mask of groups to generate |
970 | + */ |
971 | +static void regen_dh_keys_v2(uint32_t bitmask) |
972 | +{ |
973 | int maxmask, i; |
974 | int cnt = 0; |
975 | |
976 | @@ -164,19 +388,13 @@ |
977 | |
978 | for (i = 1; i < HIP_MAX_DH_GROUP_ID; i++) { |
979 | if (bitmask & (1 << i)) { |
980 | - tmp = hip_generate_dh_key(i); |
981 | - if (!tmp) { |
982 | - HIP_INFO("Error while generating group: %d\n", i); |
983 | - continue; |
984 | + if (hip_is_ecdh_group(i)) { |
985 | + regen_ecdh_key(i); |
986 | + } else { |
987 | + regen_dh_key(i); |
988 | } |
989 | |
990 | - okey = dh_table[i]; |
991 | - dh_table[i] = tmp; |
992 | - |
993 | - DH_free(okey); |
994 | - |
995 | cnt++; |
996 | - |
997 | HIP_DEBUG("DH key for group %d generated\n", i); |
998 | } |
999 | } |
1000 | @@ -193,6 +411,14 @@ |
1001 | DH_free(dh_table[i]); |
1002 | dh_table[i] = NULL; |
1003 | } |
1004 | + |
1005 | +#ifdef HAVE_EC_CRYPTO |
1006 | + for (i = 1; i < HIP_MAX_DH_GROUP_ID; i++) { |
1007 | + EC_KEY_free(ecdh_table[i]); |
1008 | + ecdh_table[i] = NULL; |
1009 | + } |
1010 | +#endif /* HAVE_EC_CRYPTO */ |
1011 | + |
1012 | CRYPTO_cleanup_all_ex_data(); |
1013 | } |
1014 | |
1015 | @@ -203,12 +429,15 @@ |
1016 | { |
1017 | uint32_t supported_groups; |
1018 | |
1019 | - supported_groups = (1 << HIP_DH_OAKLEY_1 | |
1020 | - 1 << HIP_DH_OAKLEY_5 | |
1021 | - 1 << HIP_DH_384); |
1022 | + supported_groups = (1 << HIP_DH_OAKLEY_1 | |
1023 | + 1 << HIP_DH_OAKLEY_5 | |
1024 | + 1 << HIP_DH_384 | |
1025 | + 1 << HIP_DH_NIST_P_256 | |
1026 | + 1 << HIP_DH_NIST_P_384 | |
1027 | + 1 << HIP_DH_NIST_P_521); |
1028 | |
1029 | HIP_DEBUG("Generating DH keys\n"); |
1030 | - regen_dh_keys(supported_groups); |
1031 | + regen_dh_keys_v2(supported_groups); |
1032 | |
1033 | return 1; |
1034 | } |
1035 | |
1036 | === modified file 'libhipl/dh.h' |
1037 | --- libhipl/dh.h 2012-05-12 10:21:32 +0000 |
1038 | +++ libhipl/dh.h 2013-10-22 12:34:40 +0000 |
1039 | @@ -1,5 +1,5 @@ |
1040 | /* |
1041 | - * Copyright (c) 2010 Aalto University and RWTH Aachen University. |
1042 | + * Copyright (c) 2010, 2012 Aalto University and RWTH Aachen University. |
1043 | * |
1044 | * Permission is hereby granted, free of charge, to any person |
1045 | * obtaining a copy of this software and associated documentation |
1046 | @@ -28,13 +28,21 @@ |
1047 | |
1048 | #include <stdint.h> |
1049 | |
1050 | +#include "libcore/protodefs.h" |
1051 | + |
1052 | + |
1053 | int hip_insert_dh(uint8_t *buffer, int bufsize, int group_id); |
1054 | void hip_dh_uninit(void); |
1055 | -int hip_calculate_shared_secret(const uint8_t *public_value, |
1056 | - uint8_t group_id, |
1057 | - signed int len, |
1058 | - unsigned char *buffer, |
1059 | - int bufsize); |
1060 | +int hip_calculate_shared_secret(const uint16_t group_id, |
1061 | + const uint8_t *const pulic_value, |
1062 | + const int len, |
1063 | + unsigned char *const buffer, |
1064 | + const int bufsize); |
1065 | int hip_init_cipher(void); |
1066 | |
1067 | +int hip_insert_dh_v2(uint8_t *buffer, int bufsize, int group_id); |
1068 | +int hip_insert_ecdh(uint8_t *buffer, int bufsize, int group_id); |
1069 | +int hip_match_dh_group_list(const struct hip_tlv_common *const dh_group_list, |
1070 | + const uint8_t *our_dh_group, const int our_group_size); |
1071 | + |
1072 | #endif /* HIPL_LIBHIPL_DH_H */ |
1073 | |
1074 | === modified file 'libhipl/hidb.c' |
1075 | --- libhipl/hidb.c 2012-06-03 10:26:55 +0000 |
1076 | +++ libhipl/hidb.c 2013-10-22 12:34:40 +0000 |
1077 | @@ -429,7 +429,6 @@ |
1078 | hip_lsi_t *lsi, |
1079 | const struct hip_host_id_priv *host_id) |
1080 | { |
1081 | - int i; |
1082 | int err = 0; |
1083 | struct local_host_id *id_entry = NULL; |
1084 | struct local_host_id *old_entry; |
1085 | @@ -493,16 +492,12 @@ |
1086 | err = -1; |
1087 | goto out_err; |
1088 | } |
1089 | - for (i = 1; i < HIP_MAX_VERSION; i++) { |
1090 | - HIP_IFEL(!hip_precreate_r1(id_entry->r1[i], |
1091 | - &hit, |
1092 | - signature_func, |
1093 | - id_entry->private_key, |
1094 | - &id_entry->host_id, |
1095 | - i), |
1096 | - -ENOENT, |
1097 | - "Unable to precreate R1s.\n"); |
1098 | - } |
1099 | + |
1100 | + HIP_IFEL(hip_precreate_r1(id_entry, &hit, signature_func, |
1101 | + id_entry->private_key, |
1102 | + &id_entry->host_id) < 0, |
1103 | + -ENOENT, |
1104 | + "Unable to precreate R1s.\n"); |
1105 | |
1106 | out_err: |
1107 | if (err && id_entry) { |
1108 | |
1109 | === modified file 'libhipl/hidb.h' |
1110 | --- libhipl/hidb.h 2012-06-03 10:26:55 +0000 |
1111 | +++ libhipl/hidb.h 2013-10-22 12:34:40 +0000 |
1112 | @@ -35,9 +35,19 @@ |
1113 | #include <stdbool.h> |
1114 | #include <netinet/in.h> |
1115 | |
1116 | +#include "libcore/crypto.h" |
1117 | #include "libcore/protodefs.h" |
1118 | -#include "cookie.h" |
1119 | - |
1120 | + |
1121 | + |
1122 | +#define HIP_R1TABLESIZE 3 /* precreate only this many R1s */ |
1123 | + |
1124 | +struct hip_r1entry { |
1125 | + union hip_msg_bfr buf; |
1126 | + uint32_t generation; |
1127 | + uint8_t Ci[PUZZLE_LENGTH]; |
1128 | + uint8_t Ck; |
1129 | + uint8_t Copaque[HIP_PUZZLE_OPAQUE_LEN]; |
1130 | +}; |
1131 | |
1132 | struct local_host_id { |
1133 | hip_hit_t hit; |
1134 | @@ -45,7 +55,13 @@ |
1135 | hip_lsi_t lsi; |
1136 | struct hip_host_id host_id; |
1137 | void *private_key; /* RSA or DSA */ |
1138 | - struct hip_r1entry r1[HIP_MAX_VERSION][HIP_R1TABLESIZE]; /* precreated R1s */ |
1139 | + |
1140 | + /* precreated R1 entries. |
1141 | + * Due to the introduction of DH_GROUP_LIST in HIPv2, R1's DIFFIE_HELLMAN |
1142 | + * parameter must match one of the group ID of initiator's I1. Therefore we |
1143 | + * precreate R1 for all DH groups we support. */ |
1144 | + struct hip_r1entry r1[HIP_R1TABLESIZE]; |
1145 | + struct hip_r1entry r1_v2[HIP_MAX_DH_GROUP_ID][HIP_R1TABLESIZE]; |
1146 | }; |
1147 | |
1148 | struct local_host_id *hip_get_hostid_entry_by_lhi_and_algo(const struct in6_addr *const hit, |
1149 | |
1150 | === modified file 'libhipl/input.c' |
1151 | --- libhipl/input.c 2012-07-13 13:16:17 +0000 |
1152 | +++ libhipl/input.c 2013-10-22 12:34:40 +0000 |
1153 | @@ -110,6 +110,43 @@ |
1154 | } |
1155 | |
1156 | /** |
1157 | + * HIPv2: Check potential downgrade possibility for DH group selection by |
1158 | + * matching our DH list with the peer's DH list. If the peer doesn't select |
1159 | + * the strongest group, DH downgrade occurs. |
1160 | + * |
1161 | + * @param peer_group the DH group peer has selected |
1162 | + * @param peer_param the peer's DH group list parameter |
1163 | + * @return 0 if no downgrade detected, -1 otherwise. |
1164 | + */ |
1165 | +static int check_dh_downgrade_v2(const uint8_t peer_group, |
1166 | + const struct hip_tlv_common *const peer_param) |
1167 | +{ |
1168 | + int i, j; |
1169 | + int list_size = HIP_DH_GROUP_MAX_RECV_SIZE; |
1170 | + uint8_t list[list_size]; |
1171 | + |
1172 | + list_size = hip_get_list_from_param(peer_param, list, list_size, |
1173 | + sizeof(list[0])); |
1174 | + for (i = 0; i < HIP_DH_GROUP_LIST_SIZE; i++) { |
1175 | + for (j = 0; j < list_size; j++) { |
1176 | + if (HIP_DH_GROUP_LIST[i] == list[j]) { |
1177 | + if (list[j] == peer_group) { |
1178 | + return 0; |
1179 | + } else { |
1180 | + HIP_ERROR("Detect DH group downgrade. " |
1181 | + "Expect group: %d, Got: %d\n", |
1182 | + list[j], peer_group); |
1183 | + return -1; |
1184 | + } |
1185 | + } |
1186 | + } |
1187 | + } |
1188 | + |
1189 | + HIP_ERROR("No identical group in the DH group lists\n"); |
1190 | + return -1; |
1191 | +} |
1192 | + |
1193 | +/** |
1194 | * Verifies gerenal HMAC in HIP msg |
1195 | * |
1196 | * @param msg HIP packet |
1197 | @@ -325,11 +362,14 @@ |
1198 | HIP_DEBUG("Start PERF_DH_CREATE\n"); |
1199 | hip_perf_start_benchmark(perf_set, PERF_DH_CREATE); |
1200 | #endif |
1201 | - HIP_IFEL((dh_shared_len = hip_calculate_shared_secret(dhpv->public_value, dhpv->group_id, |
1202 | - ntohs(dhpv->pub_len), |
1203 | - (unsigned char *) dh_shared_key, |
1204 | - dh_shared_len)) < 0, |
1205 | - -EINVAL, "Calculation of shared secret failed.\n"); |
1206 | + |
1207 | + dh_shared_len = hip_calculate_shared_secret(dhpv->group_id, dhpv->public_value, |
1208 | + ntohs(dhpv->pub_len), |
1209 | + (unsigned char *) dh_shared_key, |
1210 | + dh_shared_len); |
1211 | + HIP_IFEL(dh_shared_len <= 0, -EINVAL, "Calculation of shared secret failed.\n"); |
1212 | + HIP_DEBUG("DH group %d, shared secret length is %d\n", |
1213 | + dhpv->group_id, dh_shared_len); |
1214 | |
1215 | hip_make_keymat(dh_shared_key, |
1216 | dh_shared_len, |
1217 | @@ -763,6 +803,24 @@ |
1218 | HIP_IFE(hip_init_peer(ctx->hadb_entry, &peer_host_id), |
1219 | -EINVAL); |
1220 | |
1221 | + /* HIPv2: check possible DH group downgrade */ |
1222 | + if (ctx->hadb_entry->hip_version == HIP_V2) { |
1223 | + const struct hip_tlv_common *dh_list_param; |
1224 | + const struct hip_diffie_hellman *dh_param; |
1225 | + |
1226 | + dh_list_param = hip_get_param(ctx->input_msg, HIP_PARAM_DH_GROUP_LIST); |
1227 | + HIP_IFEL(dh_list_param == NULL, -ENOENT, |
1228 | + "No DH_GROUP_LIST parameter found in R1\n"); |
1229 | + |
1230 | + dh_param = hip_get_param(ctx->input_msg, HIP_PARAM_DIFFIE_HELLMAN); |
1231 | + HIP_IFEL(dh_param == NULL, -ENOENT, |
1232 | + "No DIFFIE_HELLMAN parameter found in R1\n"); |
1233 | + |
1234 | + HIP_IFEL(check_dh_downgrade_v2(dh_param->pub_val.group_id, |
1235 | + dh_list_param) < 0, |
1236 | + -EINVAL, "DH group downgrade check failed.\n"); |
1237 | + } |
1238 | + |
1239 | #ifdef CONFIG_HIP_PERFORMANCE |
1240 | HIP_DEBUG("Start PERF_VERIFY\n"); |
1241 | hip_perf_start_benchmark(perf_set, PERF_VERIFY); |
1242 | @@ -945,7 +1003,8 @@ |
1243 | HIP_ERROR("Failed to allocate memory for public value\n"); |
1244 | return -ENOMEM; |
1245 | } |
1246 | - if ((pub_len = hip_insert_dh(public_value, pub_len, dhpv->group_id)) < 0) { |
1247 | + |
1248 | + if ((pub_len = hip_insert_dh_v2(public_value, pub_len, dhpv->group_id)) < 0) { |
1249 | HIP_ERROR("Could not extract the DH public key\n"); |
1250 | return -1; |
1251 | } |
1252 | @@ -1363,19 +1422,22 @@ |
1253 | UNUSED const enum hip_state ha_state, |
1254 | struct hip_packet_context *ctx) |
1255 | { |
1256 | - int hip_version = 0; |
1257 | - int err = 0, is_loopback = 0; |
1258 | - bool skip_key_creation = false; |
1259 | - uint16_t mask = HIP_PACKET_CTRL_ANON; |
1260 | - uint16_t crypto_len = 0; |
1261 | - char *tmp_enc = NULL; |
1262 | - const char *enc = NULL; |
1263 | - unsigned char *iv = NULL; |
1264 | - const struct hip_solution *solution = NULL; |
1265 | - const struct hip_r1_counter *r1cntr = NULL; |
1266 | - const struct hip_hip_transform *hip_transform = NULL; |
1267 | - struct hip_host_id *host_id_in_enc = NULL; |
1268 | - struct hip_host_id host_id; |
1269 | + int hip_version = 0; |
1270 | + int err = 0, is_loopback = 0; |
1271 | + bool skip_key_creation = false; |
1272 | + uint16_t mask = HIP_PACKET_CTRL_ANON; |
1273 | + uint16_t crypto_len = 0; |
1274 | + char *tmp_enc = NULL; |
1275 | + const char *enc = NULL; |
1276 | + unsigned char *iv = NULL; |
1277 | + const struct hip_solution *solution = NULL; |
1278 | + const struct hip_diffie_hellman *dh_param = NULL; |
1279 | + const struct hip_r1_counter *r1cntr = NULL; |
1280 | + const struct hip_hip_transform *hip_transform = NULL; |
1281 | + struct hip_host_id *host_id_in_enc = NULL; |
1282 | + struct hip_host_id host_id; |
1283 | + int dh_group_id, i; |
1284 | + |
1285 | #ifdef CONFIG_HIP_PERFORMANCE |
1286 | HIP_DEBUG("Start PERF_I2\n"); |
1287 | hip_perf_start_benchmark(perf_set, PERF_I2); |
1288 | @@ -1464,11 +1526,40 @@ |
1289 | -ENODATA, |
1290 | "SOLUTION parameter missing from I2 packet. Dropping\n"); |
1291 | |
1292 | - HIP_IFEL(hip_verify_cookie(&ctx->src_addr, |
1293 | - &ctx->dst_addr, |
1294 | - ctx->input_msg, |
1295 | - solution, |
1296 | - ctx->hadb_entry->hip_version), |
1297 | + /* Validate DIFFIE_HELLMAN parameter */ |
1298 | + if (NULL == (dh_param = hip_get_param(ctx->input_msg, |
1299 | + HIP_PARAM_DIFFIE_HELLMAN))) { |
1300 | + HIP_ERROR("DIFFIE_HELLMAN parameter missing from I2 packet\n"); |
1301 | + ctx->error = -ENODATA; |
1302 | + return ctx->error; |
1303 | + } |
1304 | + dh_group_id = dh_param->pub_val.group_id; |
1305 | + for (i = 0; i < HIP_DH_GROUP_LIST_SIZE; i++) { |
1306 | + if (dh_group_id == HIP_DH_GROUP_LIST[i]) { |
1307 | + break; |
1308 | + } |
1309 | + } |
1310 | + if (i == HIP_DH_GROUP_LIST_SIZE) { |
1311 | + HIP_ERROR("Invalid group %d for DIFFIE_HELLMAN parameter.\n", |
1312 | + dh_group_id); |
1313 | + ctx->error = -EINVAL; |
1314 | + return ctx->error; |
1315 | + } |
1316 | + if (hip_get_dh_size(dh_group_id) != ntohs(dh_param->pub_val.pub_len)) { |
1317 | + HIP_ERROR("Invalid public key length for DIFFIE_HELLMAN parameter. " |
1318 | + "Expect: %d, Got: %d\n", hip_get_dh_size(dh_group_id), |
1319 | + ntohs(dh_param->pub_val.pub_len)); |
1320 | + ctx->error = -EINVAL; |
1321 | + return ctx->error; |
1322 | + } |
1323 | + |
1324 | + /* Verify cookie */ |
1325 | + if (hip_version == HIP_V1) { |
1326 | + dh_group_id = 0; |
1327 | + } |
1328 | + HIP_IFEL(hip_verify_cookie(&ctx->src_addr, &ctx->dst_addr, |
1329 | + ctx->input_msg, solution, |
1330 | + hip_version, dh_group_id), |
1331 | -EPROTO, |
1332 | "Cookie solution rejected. Dropping the I2 packet.\n"); |
1333 | |
1334 | |
1335 | === modified file 'libhipl/netdev.c' |
1336 | --- libhipl/netdev.c 2012-06-03 10:26:55 +0000 |
1337 | +++ libhipl/netdev.c 2013-10-22 12:34:40 +0000 |
1338 | @@ -987,8 +987,25 @@ |
1339 | |
1340 | HIP_DEBUG("Using ifindex %d\n", if_index); |
1341 | |
1342 | - HIP_IFEL(hip_send_i1(&entry->hit_our, &entry->hit_peer, entry), -1, |
1343 | - "Sending of I1 failed\n"); |
1344 | + switch (entry->hip_version) { |
1345 | + case HIP_V1: |
1346 | + if (hip_send_i1(&entry->hit_our, &entry->hit_peer, entry) < 0) { |
1347 | + HIP_ERROR("Failed to send the I1(v1) message.\n"); |
1348 | + return -1; |
1349 | + } |
1350 | + break; |
1351 | + |
1352 | + case HIP_V2: |
1353 | + if (hip_send_i1_v2(&entry->hit_our, &entry->hit_peer, entry) < 0) { |
1354 | + HIP_ERROR("Failed to send the I1(v2) message.\n"); |
1355 | + return -1; |
1356 | + } |
1357 | + break; |
1358 | + |
1359 | + default: |
1360 | + HIP_ERROR("Unknown HIP version: %d\n", entry->hip_version); |
1361 | + return -1; |
1362 | + } |
1363 | |
1364 | out_err: |
1365 | |
1366 | |
1367 | === modified file 'libhipl/output.c' |
1368 | --- libhipl/output.c 2013-08-19 18:30:29 +0000 |
1369 | +++ libhipl/output.c 2013-10-22 12:34:40 +0000 |
1370 | @@ -161,7 +161,111 @@ |
1371 | } |
1372 | |
1373 | /** |
1374 | - * Send an I1 packet to the Responder |
1375 | + * Send an I1 packet to the responder. |
1376 | + * |
1377 | + * This method checks the shotgun status and decides whether to use shotgun |
1378 | + * mode or not for I1 sending. |
1379 | + * |
1380 | + * @param i1 the I1 packet to be sent |
1381 | + * @param entry a pointer to the current host association database state. |
1382 | + * @return zero on success, or negative error value on error. |
1383 | + */ |
1384 | +static int send_i1_internal(struct hip_common *const i1, |
1385 | + struct hip_hadb_state *const entry) |
1386 | +{ |
1387 | + struct in6_addr *local_addr = NULL; |
1388 | + struct in6_addr peer_addr; |
1389 | + LHASH_NODE *item = NULL, *tmp = NULL; |
1390 | + struct hip_peer_addr_list_item *addr; |
1391 | + int err = 0, i = 0; |
1392 | + |
1393 | + HIP_DEBUG("Sending I1 to the following addresses:\n"); |
1394 | + print_peer_addresses_to_be_added(entry); |
1395 | + |
1396 | + if (hip_shotgun_status == HIP_MSG_SHOTGUN_OFF || |
1397 | + (entry->peer_addr_list_to_be_added == NULL)) { |
1398 | + if (hip_hadb_get_peer_addr(entry, &peer_addr)) { |
1399 | + HIP_ERROR("No preferred IP address for the peer.\n"); |
1400 | + return -1; |
1401 | + } |
1402 | + |
1403 | + local_addr = &entry->our_addr; |
1404 | + return send_i1_pkt(i1, local_addr, &peer_addr, entry->local_udp_port, |
1405 | + entry->peer_udp_port, entry); |
1406 | + } else { |
1407 | + HIP_DEBUG("Number of items in the peer addr list: %d ", |
1408 | + ((struct lhash_st *) entry->peer_addr_list_to_be_added)->num_items); |
1409 | + list_for_each_safe(item, tmp, entry->peer_addr_list_to_be_added, i) |
1410 | + { |
1411 | + addr = list_entry(item); |
1412 | + ipv6_addr_copy(&peer_addr, &addr->address); |
1413 | + |
1414 | + err = send_i1_pkt(i1, NULL, &peer_addr, entry->local_udp_port, |
1415 | + entry->peer_udp_port, entry); |
1416 | + } |
1417 | + return err; |
1418 | + } |
1419 | +} |
1420 | + |
1421 | +/** |
1422 | + * HIPv2: send an I1 packet to the responder. |
1423 | + * |
1424 | + * @param src_hit a pointer to the source host identity tag. |
1425 | + * @param dst_hit a pointer to the destination host identity tag. |
1426 | + * @param entry a pointer to the host association database state reserved for |
1427 | + * the peer. |
1428 | + * @return zero on success, or negative value on error. |
1429 | + */ |
1430 | +int hip_send_i1_v2(hip_hit_t *const src_hit, const hip_hit_t *const dst_hit, |
1431 | + struct hip_hadb_state *const entry) |
1432 | +{ |
1433 | + struct hip_common *i1 = NULL; |
1434 | + int err = 0; |
1435 | + |
1436 | + int group_size = HIP_DH_GROUP_LIST_SIZE; |
1437 | + uint8_t dh_group[group_size]; |
1438 | + |
1439 | + memcpy(dh_group, HIP_DH_GROUP_LIST, group_size); |
1440 | + |
1441 | + if (entry->state == HIP_STATE_ESTABLISHED) { |
1442 | + HIP_DEBUG("HIP association established, not triggering bex\n"); |
1443 | + return 0; |
1444 | + } |
1445 | + |
1446 | + /* Assign a local private key, public key and HIT to HA */ |
1447 | + HIP_DEBUG_HIT("src_hit", src_hit); |
1448 | + HIP_DEBUG_HIT("entry->src_hit", &entry->hit_our); |
1449 | + HIP_IFEL(hip_init_us(entry, src_hit), -EINVAL, |
1450 | + "Could not assign a local host id\n"); |
1451 | + HIP_DEBUG_HIT("entry->src_hit", &entry->hit_our); |
1452 | + |
1453 | + if ((i1 = hip_msg_alloc()) == NULL) { |
1454 | + return -1; |
1455 | + } |
1456 | + |
1457 | + hip_build_network_hdr(i1, HIP_I1, 0, &entry->hit_our, |
1458 | + dst_hit, entry->hip_version); |
1459 | + |
1460 | + /* Calculate the HIP header length */ |
1461 | + hip_calc_hdr_len(i1); |
1462 | + |
1463 | + /* Build DH_GROUP_LIST */ |
1464 | + HIP_IFEL(hip_build_param_list(i1, HIP_PARAM_DH_GROUP_LIST, dh_group, |
1465 | + group_size, sizeof(uint8_t)), |
1466 | + -1, "Failed to build param: DH_GROUP_LIST\n"); |
1467 | + |
1468 | + HIP_DEBUG_HIT("HIT source", &i1->hit_sender); |
1469 | + HIP_DEBUG_HIT("HIT dest", &i1->hit_receiver); |
1470 | + |
1471 | + HIP_IFEL(send_i1_internal(i1, entry), -1, "send_i1_internal() failed\n"); |
1472 | + |
1473 | +out_err: |
1474 | + free(i1); |
1475 | + return err; |
1476 | +} |
1477 | + |
1478 | +/** |
1479 | + * HIPv1: send an I1 packet to the responder. |
1480 | * |
1481 | * @param src_hit a pointer to source host identity tag. |
1482 | * @param dst_hit a pointer to destination host identity tag. |
1483 | @@ -172,13 +276,8 @@ |
1484 | int hip_send_i1(hip_hit_t *src_hit, const hip_hit_t *dst_hit, |
1485 | struct hip_hadb_state *entry) |
1486 | { |
1487 | - struct hip_common *i1 = 0; |
1488 | - uint16_t mask = 0; |
1489 | - int err = 0, i = 0; |
1490 | - LHASH_NODE *item = NULL, *tmp = NULL; |
1491 | - struct hip_peer_addr_list_item *addr; |
1492 | - struct in6_addr *local_addr = NULL; |
1493 | - struct in6_addr peer_addr; |
1494 | + struct hip_common *i1 = 0; |
1495 | + int err = 0; |
1496 | |
1497 | #ifdef CONFIG_HIP_PERFORMANCE |
1498 | HIP_DEBUG("Start PERF_I1_SEND, PERF_BASE\n"); |
1499 | @@ -209,7 +308,7 @@ |
1500 | |
1501 | i1 = hip_msg_alloc(); |
1502 | |
1503 | - hip_build_network_hdr(i1, HIP_I1, mask, &entry->hit_our, |
1504 | + hip_build_network_hdr(i1, HIP_I1, 0, &entry->hit_our, |
1505 | dst_hit, entry->hip_version); |
1506 | |
1507 | /* Calculate the HIP header length */ |
1508 | @@ -218,30 +317,8 @@ |
1509 | HIP_DEBUG_HIT("HIT source", &i1->hit_sender); |
1510 | HIP_DEBUG_HIT("HIT dest", &i1->hit_receiver); |
1511 | |
1512 | - HIP_DEBUG("Sending I1 to the following addresses:\n"); |
1513 | - print_peer_addresses_to_be_added(entry); |
1514 | - |
1515 | - if (hip_shotgun_status == HIP_MSG_SHOTGUN_OFF || |
1516 | - (entry->peer_addr_list_to_be_added == NULL)) { |
1517 | - HIP_IFEL(hip_hadb_get_peer_addr(entry, &peer_addr), -1, |
1518 | - "No preferred IP address for the peer.\n"); |
1519 | - |
1520 | - local_addr = &entry->our_addr; |
1521 | - err = send_i1_pkt(i1, local_addr, &peer_addr, |
1522 | - entry->local_udp_port, |
1523 | - entry->peer_udp_port, entry); |
1524 | - } else { |
1525 | - HIP_DEBUG("Number of items in the peer addr list: %d ", |
1526 | - ((struct lhash_st *) entry->peer_addr_list_to_be_added)->num_items); |
1527 | - list_for_each_safe(item, tmp, entry->peer_addr_list_to_be_added, i) |
1528 | - { |
1529 | - addr = list_entry(item); |
1530 | - ipv6_addr_copy(&peer_addr, &addr->address); |
1531 | - |
1532 | - err = send_i1_pkt(i1, NULL, &peer_addr, entry->local_udp_port, |
1533 | - entry->peer_udp_port, entry); |
1534 | - } |
1535 | - } |
1536 | + HIP_IFEL(send_i1_internal(i1, entry), -1, "send_i1_internal() failed\n"); |
1537 | + |
1538 | #ifdef CONFIG_HIP_PERFORMANCE |
1539 | HIP_DEBUG("Stop and write PERF_I1_SEND\n"); |
1540 | hip_perf_stop_benchmark(perf_set, PERF_I1_SEND); |
1541 | @@ -263,8 +340,8 @@ |
1542 | */ |
1543 | static int add_echo_response(struct hip_packet_context *ctx, int sign) |
1544 | { |
1545 | - int param_type = sign ? HIP_PARAM_ECHO_REQUEST_SIGN |
1546 | - : HIP_PARAM_ECHO_REQUEST; |
1547 | + int param_type = |
1548 | + sign ? HIP_PARAM_ECHO_REQUEST_SIGN : HIP_PARAM_ECHO_REQUEST; |
1549 | |
1550 | const struct hip_echo_msg *ping = hip_get_param(ctx->input_msg, param_type); |
1551 | |
1552 | @@ -595,38 +672,25 @@ |
1553 | } |
1554 | |
1555 | /** |
1556 | - * Construct a new R1 packet payload |
1557 | + * Continue to build R1 packet after the Diffie-Hellman parameter. |
1558 | * |
1559 | - * @param msg points to a message object backed by HIP_MAX_PACKET bytes |
1560 | - * of memory to which the R1 message is written. |
1561 | - * @param src_hit a pointer to the source host identity tag used in the |
1562 | - * packet. |
1563 | + * @param msg pointer to a message backed by HIP_MAX_PACKET bytes of |
1564 | + * memory to which the R1 message is written. |
1565 | * @param sign a funtion pointer to a signature funtion. |
1566 | * @param private_key a pointer to the local host private key |
1567 | * @param host_id_pub a pointer to the public host id of the local host |
1568 | - * @param cookie_k the difficulty value for the puzzle |
1569 | - * @param hip_version HIP message version |
1570 | * @return 0 on success, a non-zero value on error. |
1571 | */ |
1572 | -int hip_create_r1(struct hip_common *const msg, |
1573 | - const struct in6_addr *const src_hit, |
1574 | - int (*sign)(void *const key, struct hip_common *const m), |
1575 | - void *const private_key, |
1576 | - const struct hip_host_id *const host_id_pub, |
1577 | - const int cookie_k, |
1578 | - const uint8_t hip_version) |
1579 | +static int build_r1_after_dh_param(struct hip_common *const msg, |
1580 | + int (*sign)(void *const key, struct hip_common *const m), |
1581 | + void *const private_key, |
1582 | + const struct hip_host_id *const host_id_pub) |
1583 | { |
1584 | - int err = 0; |
1585 | struct hip_srv service_list[HIP_TOTAL_EXISTING_SERVICES]; |
1586 | - uint8_t *dh_data1 = NULL, *dh_data2 = NULL; |
1587 | + unsigned int service_count = 0; |
1588 | + int err = 0; |
1589 | char order[] = "000"; |
1590 | - int dh_size1 = 0, dh_size2 = 0; |
1591 | - int mask = 0, i = 0, written1 = 0, written2 = 0; |
1592 | - unsigned int service_count = 0; |
1593 | - |
1594 | - enum number_dh_keys_t { ONE, TWO }; |
1595 | - enum number_dh_keys_t number_dh_keys = TWO; |
1596 | - |
1597 | + int i = 0; |
1598 | |
1599 | /* Supported HIP and ESP transforms. */ |
1600 | hip_transform_suite transform_hip_suite[] = { |
1601 | @@ -662,6 +726,102 @@ |
1602 | } |
1603 | } |
1604 | |
1605 | + /* Parameter HIP transform. */ |
1606 | + err = hip_build_param_hip_transform(msg, |
1607 | + transform_hip_suite, |
1608 | + sizeof(transform_hip_suite) / |
1609 | + sizeof(hip_transform_suite)); |
1610 | + if (err) { |
1611 | + HIP_ERROR("Building of HIP transform failed\n"); |
1612 | + return err; |
1613 | + } |
1614 | + |
1615 | + /* Parameter HOST_ID */ |
1616 | + if ((err = hip_build_param_host_id(msg, host_id_pub))) { |
1617 | + HIP_ERROR("Building of host id failed\n"); |
1618 | + return err; |
1619 | + } |
1620 | + |
1621 | + /* Parameter REG_INFO */ |
1622 | + hip_get_active_services(service_list, &service_count); |
1623 | + HIP_DEBUG("Found %d active service(s) \n", service_count); |
1624 | + hip_build_param_reg_info(msg, service_list, service_count); |
1625 | + |
1626 | + /* Parameter ESP-ENC transform. */ |
1627 | + err = hip_build_param_esp_transform(msg, transform_esp_suite, |
1628 | + sizeof(transform_esp_suite) / |
1629 | + sizeof(hip_transform_suite)); |
1630 | + if (err) { |
1631 | + HIP_ERROR("Building of ESP transform failed\n"); |
1632 | + return err; |
1633 | + } |
1634 | + |
1635 | + /********** ESP-PROT transform (OPTIONAL) **********/ |
1636 | + |
1637 | + if ((err = esp_prot_r1_add_transforms(msg))) { |
1638 | + HIP_ERROR("failed to add optional esp transform parameter\n"); |
1639 | + return err; |
1640 | + } |
1641 | + |
1642 | + /********** ECHO_REQUEST_SIGN (OPTIONAL) *********/ |
1643 | + |
1644 | + //HIP_HEXDUMP("Pubkey:", host_id_pub, hip_get_param_total_len(host_id_pub)); |
1645 | + |
1646 | + /* Parameter Signature 2 */ |
1647 | + |
1648 | + if ((err = sign(private_key, msg))) { |
1649 | + HIP_ERROR("Signing of R1 failed.\n"); |
1650 | + return err; |
1651 | + } |
1652 | + |
1653 | + /* Parameter ECHO_REQUEST (OPTIONAL) */ |
1654 | + |
1655 | + /* Fill puzzle parameters */ |
1656 | + { |
1657 | + struct hip_puzzle *pz; |
1658 | + |
1659 | + if (!(pz = hip_get_param_readwrite(msg, HIP_PARAM_PUZZLE))) { |
1660 | + HIP_ERROR("Internal error\n"); |
1661 | + return -1; |
1662 | + } |
1663 | + |
1664 | + /* hardcode kludge */ |
1665 | + pz->opaque[0] = 'H'; |
1666 | + pz->opaque[1] = 'I'; |
1667 | + get_random_bytes(pz->I, PUZZLE_LENGTH); |
1668 | + } |
1669 | + |
1670 | + return 0; |
1671 | +} |
1672 | + |
1673 | +/** |
1674 | + * Construct a new R1 packet payload |
1675 | + * |
1676 | + * @param msg pointer to a message backed by HIP_MAX_PACKET bytes of |
1677 | + * memory to which the R1 message is written. |
1678 | + * @param src_hit a pointer to the source host identity tag used in the |
1679 | + * packet. |
1680 | + * @param sign a funtion pointer to a signature funtion. |
1681 | + * @param private_key a pointer to the local host private key |
1682 | + * @param host_id_pub a pointer to the public host id of the local host |
1683 | + * @param cookie_k the difficulty value for the puzzle |
1684 | + * @return 0 on success, a non-zero value on error. |
1685 | + */ |
1686 | +int hip_create_r1(struct hip_common *const msg, |
1687 | + const struct in6_addr *const src_hit, |
1688 | + int (*sign)(void *const key, struct hip_common *const m), |
1689 | + void *const private_key, |
1690 | + const struct hip_host_id *const host_id_pub, |
1691 | + const int cookie_k) |
1692 | +{ |
1693 | + int err = 0; |
1694 | + uint8_t *dh_data1 = NULL, *dh_data2 = NULL; |
1695 | + int dh_size1 = 0, dh_size2 = 0; |
1696 | + int mask = 0, written1 = 0, written2 = 0; |
1697 | + |
1698 | + enum number_dh_keys_t { ONE, TWO }; |
1699 | + enum number_dh_keys_t number_dh_keys = TWO; |
1700 | + |
1701 | /* Initialize the message buffer as the message builder depends on it. */ |
1702 | hip_msg_init(msg); |
1703 | |
1704 | @@ -682,7 +842,7 @@ |
1705 | /** @todo TH: hip_build_network_hdr has to be replaced with an |
1706 | * appropriate function pointer */ |
1707 | HIP_DEBUG_HIT("src_hit used to build r1 network header", src_hit); |
1708 | - hip_build_network_hdr(msg, HIP_R1, mask, src_hit, NULL, hip_version); |
1709 | + hip_build_network_hdr(msg, HIP_R1, mask, src_hit, NULL, HIP_V1); |
1710 | |
1711 | /********** R1_COUNTER (OPTIONAL) *********/ |
1712 | |
1713 | @@ -714,58 +874,9 @@ |
1714 | err, "Building of DH failed.\n"); |
1715 | } |
1716 | |
1717 | - /* Parameter HIP transform. */ |
1718 | - HIP_IFEL((err = hip_build_param_hip_transform(msg, |
1719 | - transform_hip_suite, |
1720 | - sizeof(transform_hip_suite) / |
1721 | - sizeof(hip_transform_suite))), |
1722 | - err, "Building of HIP transform failed\n"); |
1723 | - |
1724 | - /* Parameter HOST_ID */ |
1725 | - HIP_IFEL((err = hip_build_param_host_id(msg, host_id_pub)), |
1726 | - err, "Building of host id failed\n"); |
1727 | - |
1728 | - /* Parameter REG_INFO */ |
1729 | - hip_get_active_services(service_list, &service_count); |
1730 | - HIP_DEBUG("Found %d active service(s) \n", service_count); |
1731 | - hip_build_param_reg_info(msg, service_list, service_count); |
1732 | - |
1733 | - /* Parameter ESP-ENC transform. */ |
1734 | - HIP_IFEL((err = hip_build_param_esp_transform(msg, |
1735 | - transform_esp_suite, |
1736 | - sizeof(transform_esp_suite) / |
1737 | - sizeof(hip_transform_suite))), |
1738 | - err, "Building of ESP transform failed\n"); |
1739 | - |
1740 | - /********** ESP-PROT transform (OPTIONAL) **********/ |
1741 | - |
1742 | - HIP_IFEL((err = esp_prot_r1_add_transforms(msg)), err, |
1743 | - "failed to add optional esp transform parameter\n"); |
1744 | - |
1745 | - /********** ECHO_REQUEST_SIGN (OPTIONAL) *********/ |
1746 | - |
1747 | - //HIP_HEXDUMP("Pubkey:", host_id_pub, hip_get_param_total_len(host_id_pub)); |
1748 | - |
1749 | - /* Parameter Signature 2 */ |
1750 | - |
1751 | - HIP_IFEL((err = sign(private_key, msg)), err, "Signing of R1 failed.\n"); |
1752 | - |
1753 | - /* Parameter ECHO_REQUEST (OPTIONAL) */ |
1754 | - |
1755 | - /* Fill puzzle parameters */ |
1756 | - { |
1757 | - struct hip_puzzle *pz; |
1758 | - |
1759 | - HIP_IFEL(!(pz = hip_get_param_readwrite(msg, HIP_PARAM_PUZZLE)), -1, |
1760 | - "Internal error\n"); |
1761 | - |
1762 | - /* hardcode kludge */ |
1763 | - pz->opaque[0] = 'H'; |
1764 | - pz->opaque[1] = 'I'; |
1765 | - //pz->opaque[2] = 'P'; |
1766 | - get_random_bytes(pz->I, PUZZLE_LENGTH); |
1767 | + if ((err = build_r1_after_dh_param(msg, sign, private_key, host_id_pub)) != 0) { |
1768 | + HIP_ERROR("Failed to build R1 after the DH parameter."); |
1769 | } |
1770 | - |
1771 | /* Packet ready */ |
1772 | |
1773 | out_err: |
1774 | @@ -776,6 +887,86 @@ |
1775 | } |
1776 | |
1777 | /** |
1778 | + * Construct a new R1 packet payload. |
1779 | + * |
1780 | + * @param msg pointer to a message backed by HIP_MAX_PACKET bytes |
1781 | + * of memory to which the R1 message is written |
1782 | + * @param src_hit a pointer to the source HIT used in the packet |
1783 | + * @param sign a function pointer to a signature function |
1784 | + * @param private_key a pointer to the local host private key |
1785 | + * @param host_id_pub a pointer to the public host id of the local host |
1786 | + * @param cookie_k the difficulty value for the puzzle |
1787 | + * @param dh_group_id the Diffie-Hellman group ID which will be used by this |
1788 | + * new R1 entry |
1789 | + * @return 0 on success, a non-zero value on error |
1790 | + */ |
1791 | +int hip_create_r1_v2(struct hip_common *const msg, |
1792 | + const struct in6_addr *const src_hit, |
1793 | + int (*sign)(void *const key, struct hip_common *const m), |
1794 | + void *const private_key, |
1795 | + const struct hip_host_id *const host_id_pub, |
1796 | + const int cookie_k, |
1797 | + const int dh_group_id) |
1798 | +{ |
1799 | + int err = 0; |
1800 | + uint8_t *dh_data = NULL; |
1801 | + int dh_size = 0; |
1802 | + int mask = 0, written = 0; |
1803 | + |
1804 | + /* Initialize the message buffer as the message builder depends on it. */ |
1805 | + hip_msg_init(msg); |
1806 | + |
1807 | + /* Allocate memory for writing the Diffie-Hellman public value */ |
1808 | + if ((dh_size = hip_get_dh_size(dh_group_id)) == 0) { |
1809 | + HIP_ERROR("Could not get dh_size\n"); |
1810 | + return -1; |
1811 | + } |
1812 | + if ((dh_data = calloc(1, dh_size)) == NULL) { |
1813 | + HIP_ERROR("Failed to allocate memory for dh_data\n"); |
1814 | + return -1; |
1815 | + } |
1816 | + |
1817 | + /* Ready to begin building of the R1 packet */ |
1818 | + HIP_DEBUG_HIT("src_hit used to build r1 network header", src_hit); |
1819 | + hip_build_network_hdr(msg, HIP_R1, mask, src_hit, NULL, HIP_V2); |
1820 | + |
1821 | + /********** R1_COUNTER (OPTIONAL) *********/ |
1822 | + |
1823 | + /********** Parameter PUZZLE ************/ |
1824 | + const uint8_t zero_i[PUZZLE_LENGTH] = { 0 }; |
1825 | + //2^(42-32) sec lifetime |
1826 | + err = hip_build_param_puzzle(msg, cookie_k, 42, 0, zero_i); |
1827 | + HIP_IFEL(err, err, "Cookies were burned. Bummer!\n"); |
1828 | + |
1829 | + /* Parameter DH_GROUP_LIST */ |
1830 | + uint8_t dh_group[HIP_DH_GROUP_LIST_SIZE]; |
1831 | + memcpy(dh_group, HIP_DH_GROUP_LIST, HIP_DH_GROUP_LIST_SIZE); |
1832 | + HIP_IFEL(hip_build_param_list(msg, HIP_PARAM_DH_GROUP_LIST, dh_group, |
1833 | + HIP_DH_GROUP_LIST_SIZE, sizeof(uint8_t)), |
1834 | + -1, "Failed to build param DH_GROUP_LIST.\n"); |
1835 | + |
1836 | + /******** Parameter DIFFIE_HELLMAN ********/ |
1837 | + HIP_IFEL((written = hip_insert_dh_v2(dh_data, dh_size, dh_group_id)) < 0, |
1838 | + written, "Could not extract DH public key\n"); |
1839 | + |
1840 | + HIP_IFEL((err = hip_build_param_diffie_hellman_contents(msg, dh_group_id, |
1841 | + dh_data, written, |
1842 | + HIP_MAX_DH_GROUP_ID, |
1843 | + NULL, 0)), |
1844 | + err, "Building of DH failed.\n"); |
1845 | + |
1846 | + if ((err = build_r1_after_dh_param(msg, sign, private_key, host_id_pub)) != 0) { |
1847 | + HIP_ERROR("Failed to build R1 after the DH parameter."); |
1848 | + } |
1849 | + /* Packet ready */ |
1850 | + |
1851 | +out_err: |
1852 | + free(dh_data); |
1853 | + |
1854 | + return err; |
1855 | +} |
1856 | + |
1857 | +/** |
1858 | * Transmit an R1 packet to the network. |
1859 | * |
1860 | * Send an R1 packet to the peer and store the cookie information that was |
1861 | @@ -866,10 +1057,29 @@ |
1862 | } |
1863 | } |
1864 | |
1865 | - HIP_IFEL(!(r1pkt = hip_get_r1(r1_dst_addr, &ctx->dst_addr, |
1866 | - &ctx->input_msg->hit_receiver, |
1867 | - hip_get_msg_version(ctx->input_msg))), |
1868 | - -ENOENT, "No precreated R1\n"); |
1869 | + if (hip_get_msg_version(ctx->input_msg) == HIP_V1) { |
1870 | + HIP_IFEL(!(r1pkt = hip_get_r1(r1_dst_addr, &ctx->dst_addr, |
1871 | + &ctx->input_msg->hit_receiver, -1)), |
1872 | + -ENOENT, "No precreated R1\n"); |
1873 | + } else { |
1874 | + const struct hip_tlv_common *dh_group_list; |
1875 | + int selected_group; |
1876 | + |
1877 | + dh_group_list = hip_get_param(ctx->input_msg, HIP_PARAM_DH_GROUP_LIST); |
1878 | + HIP_IFEL(dh_group_list == NULL, -1, "No DH_GROUP_LIST parameter in r1\n"); |
1879 | + |
1880 | + selected_group = hip_match_dh_group_list(dh_group_list, |
1881 | + HIP_DH_GROUP_LIST, |
1882 | + HIP_DH_GROUP_LIST_SIZE); |
1883 | + HIP_IFEL(selected_group == -1, -1, |
1884 | + "Cannot find a matchness for DH_GROUP_LIST\n"); |
1885 | + HIP_DEBUG("Selected DH group: %d\n", selected_group); |
1886 | + |
1887 | + r1pkt = hip_get_r1(r1_dst_addr, &ctx->dst_addr, |
1888 | + &ctx->input_msg->hit_receiver, selected_group); |
1889 | + HIP_IFEL(r1pkt == NULL, -ENOENT, "No precreated R1_v2 for group: %d\n", |
1890 | + selected_group); |
1891 | + } |
1892 | |
1893 | if (&ctx->input_msg->hit_sender) { |
1894 | ipv6_addr_copy(&r1pkt->hit_receiver, &ctx->input_msg->hit_sender); |
1895 | |
1896 | === modified file 'libhipl/output.h' |
1897 | --- libhipl/output.h 2012-06-03 10:26:55 +0000 |
1898 | +++ libhipl/output.h 2013-10-22 12:34:40 +0000 |
1899 | @@ -52,8 +52,15 @@ |
1900 | int (*sign)(void *const key, struct hip_common *const m), |
1901 | void *const private_key, |
1902 | const struct hip_host_id *const host_id_pub, |
1903 | - const int cookie_k, |
1904 | - const uint8_t hip_version); |
1905 | + const int cookie_k); |
1906 | + |
1907 | +int hip_create_r1_v2(struct hip_common *const msg, |
1908 | + const struct in6_addr *const src_hit, |
1909 | + int (*sign)(void *const key, struct hip_common *const m), |
1910 | + void *const private_key, |
1911 | + const struct hip_host_id *const host_id_pub, |
1912 | + const int cookie_k, |
1913 | + const int dh_group_id); |
1914 | |
1915 | int hip_send_r1(const uint8_t packet_type, |
1916 | const enum hip_state ha_state, |
1917 | @@ -81,6 +88,9 @@ |
1918 | |
1919 | int hip_send_i1(hip_hit_t *, const hip_hit_t *, struct hip_hadb_state *); |
1920 | |
1921 | +int hip_send_i1_v2(hip_hit_t *const src_hit, const hip_hit_t *const dst_hit, |
1922 | + struct hip_hadb_state *const entry); |
1923 | + |
1924 | int hip_add_signed_echo_response(const uint8_t packet_type, |
1925 | const enum hip_state ha_state, |
1926 | struct hip_packet_context *ctx); |
1927 | |
1928 | === modified file 'test/libcore/crypto.c' |
1929 | --- test/libcore/crypto.c 2012-05-12 06:54:33 +0000 |
1930 | +++ test/libcore/crypto.c 2013-10-22 12:34:40 +0000 |
1931 | @@ -1,5 +1,5 @@ |
1932 | /* |
1933 | - * Copyright (c) 2011 Aalto University and RWTH Aachen University. |
1934 | + * Copyright (c) 2011-2012 Aalto University and RWTH Aachen University. |
1935 | * |
1936 | * Permission is hereby granted, free of charge, to any person |
1937 | * obtaining a copy of this software and associated documentation |
1938 | @@ -28,12 +28,225 @@ |
1939 | #include <string.h> |
1940 | #include <stdio.h> |
1941 | #include <unistd.h> |
1942 | +#ifdef HAVE_EC_CRYPTO |
1943 | +#include <openssl/ecdh.h> |
1944 | +#endif |
1945 | |
1946 | #include "libcore/crypto.h" |
1947 | #include "config.h" |
1948 | #include "test_suites.h" |
1949 | |
1950 | #ifdef HAVE_EC_CRYPTO |
1951 | + |
1952 | +static const int TEST_ECDH_PRIV_A = 0; |
1953 | +static const int TEST_ECDH_PUBX_A = 1; |
1954 | +static const int TEST_ECDH_PUBY_A = 2; |
1955 | +static const int TEST_ECDH_PRIV_B = 3; |
1956 | +static const int TEST_ECDH_PUBX_B = 4; |
1957 | +static const int TEST_ECDH_PUBY_B = 5; |
1958 | +static const int TEST_ECDH_SHARED = 6; |
1959 | + |
1960 | +/* An example for testing from RFC5903, section 8.1 */ |
1961 | +static unsigned char TEST_ECDH_NIST_P_256[] = { |
1962 | + 0xC8, 0x8F, 0x01, 0xF5, 0x10, 0xD9, 0xAC, 0x3F, 0x70, 0xA2, |
1963 | + 0x92, 0xDA, 0xA2, 0x31, 0x6D, 0xE5, 0x44, 0xE9, 0xAA, 0xB8, |
1964 | + 0xAF, 0xE8, 0x40, 0x49, 0xC6, 0x2A, 0x9C, 0x57, 0x86, 0x2D, |
1965 | + 0x14, 0x33, |
1966 | + |
1967 | + 0xDA, 0xD0, 0xB6, 0x53, 0x94, 0x22, 0x1C, 0xF9, 0xB0, 0x51, |
1968 | + 0xE1, 0xFE, 0xCA, 0x57, 0x87, 0xD0, 0x98, 0xDF, 0xE6, 0x37, |
1969 | + 0xFC, 0x90, 0xB9, 0xEF, 0x94, 0x5D, 0x0C, 0x37, 0x72, 0x58, |
1970 | + 0x11, 0x80, |
1971 | + |
1972 | + 0x52, 0x71, 0xA0, 0x46, 0x1C, 0xDB, 0x82, 0x52, 0xD6, 0x1F, |
1973 | + 0x1C, 0x45, 0x6F, 0xA3, 0xE5, 0x9A, 0xB1, 0xF4, 0x5B, 0x33, |
1974 | + 0xAC, 0xCF, 0x5F, 0x58, 0x38, 0x9E, 0x05, 0x77, 0xB8, 0x99, |
1975 | + 0x0B, 0xB3, |
1976 | + |
1977 | + 0xC6, 0xEF, 0x9C, 0x5D, 0x78, 0xAE, 0x01, 0x2A, 0x01, 0x11, |
1978 | + 0x64, 0xAC, 0xB3, 0x97, 0xCE, 0x20, 0x88, 0x68, 0x5D, 0x8F, |
1979 | + 0x06, 0xBF, 0x9B, 0xE0, 0xB2, 0x83, 0xAB, 0x46, 0x47, 0x6B, |
1980 | + 0xEE, 0x53, |
1981 | + |
1982 | + 0xD1, 0x2D, 0xFB, 0x52, 0x89, 0xC8, 0xD4, 0xF8, 0x12, 0x08, |
1983 | + 0xB7, 0x02, 0x70, 0x39, 0x8C, 0x34, 0x22, 0x96, 0x97, 0x0A, |
1984 | + 0x0B, 0xCC, 0xB7, 0x4C, 0x73, 0x6F, 0xC7, 0x55, 0x44, 0x94, |
1985 | + 0xBF, 0x63, |
1986 | + |
1987 | + 0x56, 0xFB, 0xF3, 0xCA, 0x36, 0x6C, 0xC2, 0x3E, 0x81, 0x57, |
1988 | + 0x85, 0x4C, 0x13, 0xC5, 0x8D, 0x6A, 0xAC, 0x23, 0xF0, 0x46, |
1989 | + 0xAD, 0xA3, 0x0F, 0x83, 0x53, 0xE7, 0x4F, 0x33, 0x03, 0x98, |
1990 | + 0x72, 0xAB, |
1991 | + |
1992 | + 0xD6, 0x84, 0x0F, 0x6B, 0x42, 0xF6, 0xED, 0xAF, 0xD1, 0x31, |
1993 | + 0x16, 0xE0, 0xE1, 0x25, 0x65, 0x20, 0x2F, 0xEF, 0x8E, 0x9E, |
1994 | + 0xCE, 0x7D, 0xCE, 0x03, 0x81, 0x24, 0x64, 0xD0, 0x4B, 0x94, |
1995 | + 0x42, 0xDE, |
1996 | +}; |
1997 | + |
1998 | +/* An example for testing from RFC5903, section 8.2 */ |
1999 | +static unsigned char TEST_ECDH_NIST_P_384[] = { |
2000 | + 0x09, 0x9F, 0x3C, 0x70, 0x34, 0xD4, 0xA2, 0xC6, 0x99, 0x88, |
2001 | + 0x4D, 0x73, 0xA3, 0x75, 0xA6, 0x7F, 0x76, 0x24, 0xEF, 0x7C, |
2002 | + 0x6B, 0x3C, 0x0F, 0x16, 0x06, 0x47, 0xB6, 0x74, 0x14, 0xDC, |
2003 | + 0xE6, 0x55, 0xE3, 0x5B, 0x53, 0x80, 0x41, 0xE6, 0x49, 0xEE, |
2004 | + 0x3F, 0xAE, 0xF8, 0x96, 0x78, 0x3A, 0xB1, 0x94, |
2005 | + |
2006 | + 0x66, 0x78, 0x42, 0xD7, 0xD1, 0x80, 0xAC, 0x2C, 0xDE, 0x6F, |
2007 | + 0x74, 0xF3, 0x75, 0x51, 0xF5, 0x57, 0x55, 0xC7, 0x64, 0x5C, |
2008 | + 0x20, 0xEF, 0x73, 0xE3, 0x16, 0x34, 0xFE, 0x72, 0xB4, 0xC5, |
2009 | + 0x5E, 0xE6, 0xDE, 0x3A, 0xC8, 0x08, 0xAC, 0xB4, 0xBD, 0xB4, |
2010 | + 0xC8, 0x87, 0x32, 0xAE, 0xE9, 0x5F, 0x41, 0xAA, |
2011 | + |
2012 | + 0x94, 0x82, 0xED, 0x1F, 0xC0, 0xEE, 0xB9, 0xCA, 0xFC, 0x49, |
2013 | + 0x84, 0x62, 0x5C, 0xCF, 0xC2, 0x3F, 0x65, 0x03, 0x21, 0x49, |
2014 | + 0xE0, 0xE1, 0x44, 0xAD, 0xA0, 0x24, 0x18, 0x15, 0x35, 0xA0, |
2015 | + 0xF3, 0x8E, 0xEB, 0x9F, 0xCF, 0xF3, 0xC2, 0xC9, 0x47, 0xDA, |
2016 | + 0xE6, 0x9B, 0x4C, 0x63, 0x45, 0x73, 0xA8, 0x1C, |
2017 | + |
2018 | + 0x41, 0xCB, 0x07, 0x79, 0xB4, 0xBD, 0xB8, 0x5D, 0x47, 0x84, |
2019 | + 0x67, 0x25, 0xFB, 0xEC, 0x3C, 0x94, 0x30, 0xFA, 0xB4, 0x6C, |
2020 | + 0xC8, 0xDC, 0x50, 0x60, 0x85, 0x5C, 0xC9, 0xBD, 0xA0, 0xAA, |
2021 | + 0x29, 0x42, 0xE0, 0x30, 0x83, 0x12, 0x91, 0x6B, 0x8E, 0xD2, |
2022 | + 0x96, 0x0E, 0x4B, 0xD5, 0x5A, 0x74, 0x48, 0xFC, |
2023 | + |
2024 | + 0xE5, 0x58, 0xDB, 0xEF, 0x53, 0xEE, 0xCD, 0xE3, 0xD3, 0xFC, |
2025 | + 0xCF, 0xC1, 0xAE, 0xA0, 0x8A, 0x89, 0xA9, 0x87, 0x47, 0x5D, |
2026 | + 0x12, 0xFD, 0x95, 0x0D, 0x83, 0xCF, 0xA4, 0x17, 0x32, 0xBC, |
2027 | + 0x50, 0x9D, 0x0D, 0x1A, 0xC4, 0x3A, 0x03, 0x36, 0xDE, 0xF9, |
2028 | + 0x6F, 0xDA, 0x41, 0xD0, 0x77, 0x4A, 0x35, 0x71, |
2029 | + |
2030 | + 0xDC, 0xFB, 0xEC, 0x7A, 0xAC, 0xF3, 0x19, 0x64, 0x72, 0x16, |
2031 | + 0x9E, 0x83, 0x84, 0x30, 0x36, 0x7F, 0x66, 0xEE, 0xBE, 0x3C, |
2032 | + 0x6E, 0x70, 0xC4, 0x16, 0xDD, 0x5F, 0x0C, 0x68, 0x75, 0x9D, |
2033 | + 0xD1, 0xFF, 0xF8, 0x3F, 0xA4, 0x01, 0x42, 0x20, 0x9D, 0xFF, |
2034 | + 0x5E, 0xAA, 0xD9, 0x6D, 0xB9, 0xE6, 0x38, 0x6C, |
2035 | + |
2036 | + 0x11, 0x18, 0x73, 0x31, 0xC2, 0x79, 0x96, 0x2D, 0x93, 0xD6, |
2037 | + 0x04, 0x24, 0x3F, 0xD5, 0x92, 0xCB, 0x9D, 0x0A, 0x92, 0x6F, |
2038 | + 0x42, 0x2E, 0x47, 0x18, 0x75, 0x21, 0x28, 0x7E, 0x71, 0x56, |
2039 | + 0xC5, 0xC4, 0xD6, 0x03, 0x13, 0x55, 0x69, 0xB9, 0xE9, 0xD0, |
2040 | + 0x9C, 0xF5, 0xD4, 0xA2, 0x70, 0xF5, 0x97, 0x46 |
2041 | +}; |
2042 | + |
2043 | +/* An example for testing from RFC5903, section 8.3 */ |
2044 | +static unsigned char TEST_ECDH_NIST_P_521[] = { |
2045 | + 0x00, 0x37, 0xAD, 0xE9, 0x31, 0x9A, 0x89, 0xF4, 0xDA, 0xBD, |
2046 | + 0xB3, 0xEF, 0x41, 0x1A, 0xAC, 0xCC, 0xA5, 0x12, 0x3C, 0x61, |
2047 | + 0xAC, 0xAB, 0x57, 0xB5, 0x39, 0x3D, 0xCE, 0x47, 0x60, 0x81, |
2048 | + 0x72, 0xA0, 0x95, 0xAA, 0x85, 0xA3, 0x0F, 0xE1, 0xC2, 0x95, |
2049 | + 0x2C, 0x67, 0x71, 0xD9, 0x37, 0xBA, 0x97, 0x77, 0xF5, 0x95, |
2050 | + 0x7B, 0x26, 0x39, 0xBA, 0xB0, 0x72, 0x46, 0x2F, 0x68, 0xC2, |
2051 | + 0x7A, 0x57, 0x38, 0x2D, 0x4A, 0x52, |
2052 | + |
2053 | + 0x00, 0x15, 0x41, 0x7E, 0x84, 0xDB, 0xF2, 0x8C, 0x0A, 0xD3, |
2054 | + 0xC2, 0x78, 0x71, 0x33, 0x49, 0xDC, 0x7D, 0xF1, 0x53, 0xC8, |
2055 | + 0x97, 0xA1, 0x89, 0x1B, 0xD9, 0x8B, 0xAB, 0x43, 0x57, 0xC9, |
2056 | + 0xEC, 0xBE, 0xE1, 0xE3, 0xBF, 0x42, 0xE0, 0x0B, 0x8E, 0x38, |
2057 | + 0x0A, 0xEA, 0xE5, 0x7C, 0x2D, 0x10, 0x75, 0x64, 0x94, 0x18, |
2058 | + 0x85, 0x94, 0x2A, 0xF5, 0xA7, 0xF4, 0x60, 0x17, 0x23, 0xC4, |
2059 | + 0x19, 0x5D, 0x17, 0x6C, 0xED, 0x3E, |
2060 | + |
2061 | + 0x01, 0x7C, 0xAE, 0x20, 0xB6, 0x64, 0x1D, 0x2E, 0xEB, 0x69, |
2062 | + 0x57, 0x86, 0xD8, 0xC9, 0x46, 0x14, 0x62, 0x39, 0xD0, 0x99, |
2063 | + 0xE1, 0x8E, 0x1D, 0x5A, 0x51, 0x4C, 0x73, 0x9D, 0x7C, 0xB4, |
2064 | + 0xA1, 0x0A, 0xD8, 0xA7, 0x88, 0x01, 0x5A, 0xC4, 0x05, 0xD7, |
2065 | + 0x79, 0x9D, 0xC7, 0x5E, 0x7B, 0x7D, 0x5B, 0x6C, 0xF2, 0x26, |
2066 | + 0x1A, 0x6A, 0x7F, 0x15, 0x07, 0x43, 0x8B, 0xF0, 0x1B, 0xEB, |
2067 | + 0x6C, 0xA3, 0x92, 0x6F, 0x95, 0x82, |
2068 | + |
2069 | + 0x01, 0x45, 0xBA, 0x99, 0xA8, 0x47, 0xAF, 0x43, 0x79, 0x3F, |
2070 | + 0xDD, 0x0E, 0x87, 0x2E, 0x7C, 0xDF, 0xA1, 0x6B, 0xE3, 0x0F, |
2071 | + 0xDC, 0x78, 0x0F, 0x97, 0xBC, 0xCC, 0x3F, 0x07, 0x83, 0x80, |
2072 | + 0x20, 0x1E, 0x9C, 0x67, 0x7D, 0x60, 0x0B, 0x34, 0x37, 0x57, |
2073 | + 0xA3, 0xBD, 0xBF, 0x2A, 0x31, 0x63, 0xE4, 0xC2, 0xF8, 0x69, |
2074 | + 0xCC, 0xA7, 0x45, 0x8A, 0xA4, 0xA4, 0xEF, 0xFC, 0x31, 0x1F, |
2075 | + 0x5C, 0xB1, 0x51, 0x68, 0x5E, 0xB9, |
2076 | + |
2077 | + 0x00, 0xD0, 0xB3, 0x97, 0x5A, 0xC4, 0xB7, 0x99, 0xF5, 0xBE, |
2078 | + 0xA1, 0x6D, 0x5E, 0x13, 0xE9, 0xAF, 0x97, 0x1D, 0x5E, 0x9B, |
2079 | + 0x98, 0x4C, 0x9F, 0x39, 0x72, 0x8B, 0x5E, 0x57, 0x39, 0x73, |
2080 | + 0x5A, 0x21, 0x9B, 0x97, 0xC3, 0x56, 0x43, 0x6A, 0xDC, 0x6E, |
2081 | + 0x95, 0xBB, 0x03, 0x52, 0xF6, 0xBE, 0x64, 0xA6, 0xC2, 0x91, |
2082 | + 0x2D, 0x4E, 0xF2, 0xD0, 0x43, 0x3C, 0xED, 0x2B, 0x61, 0x71, |
2083 | + 0x64, 0x00, 0x12, 0xD9, 0x46, 0x0F, |
2084 | + |
2085 | + 0x01, 0x5C, 0x68, 0x22, 0x63, 0x83, 0x95, 0x6E, 0x3B, 0xD0, |
2086 | + 0x66, 0xE7, 0x97, 0xB6, 0x23, 0xC2, 0x7C, 0xE0, 0xEA, 0xC2, |
2087 | + 0xF5, 0x51, 0xA1, 0x0C, 0x2C, 0x72, 0x4D, 0x98, 0x52, 0x07, |
2088 | + 0x7B, 0x87, 0x22, 0x0B, 0x65, 0x36, 0xC5, 0xC4, 0x08, 0xA1, |
2089 | + 0xD2, 0xAE, 0xBB, 0x8E, 0x86, 0xD6, 0x78, 0xAE, 0x49, 0xCB, |
2090 | + 0x57, 0x09, 0x1F, 0x47, 0x32, 0x29, 0x65, 0x79, 0xAB, 0x44, |
2091 | + 0xFC, 0xD1, 0x7F, 0x0F, 0xC5, 0x6A, |
2092 | + |
2093 | + 0x01, 0x14, 0x4C, 0x7D, 0x79, 0xAE, 0x69, 0x56, 0xBC, 0x8E, |
2094 | + 0xDB, 0x8E, 0x7C, 0x78, 0x7C, 0x45, 0x21, 0xCB, 0x08, 0x6F, |
2095 | + 0xA6, 0x44, 0x07, 0xF9, 0x78, 0x94, 0xE5, 0xE6, 0xB2, 0xD7, |
2096 | + 0x9B, 0x04, 0xD1, 0x42, 0x7E, 0x73, 0xCA, 0x4B, 0xAA, 0x24, |
2097 | + 0x0A, 0x34, 0x78, 0x68, 0x59, 0x81, 0x0C, 0x06, 0xB3, 0xC7, |
2098 | + 0x15, 0xA3, 0xA8, 0xCC, 0x31, 0x51, 0xF2, 0xBE, 0xE4, 0x17, |
2099 | + 0x99, 0x6D, 0x19, 0xF3, 0xDD, 0xEA, |
2100 | +}; |
2101 | + |
2102 | +enum ecdh_data { SIDE_A_KEY, SIDE_B_KEY, SHARED_SECRET }; |
2103 | +static void *generate_test_ecdh_data(const int group_id, |
2104 | + enum ecdh_data request_data) |
2105 | +{ |
2106 | + uint8_t *data_set; |
2107 | + int size; |
2108 | + EC_KEY *key; |
2109 | + const EC_GROUP *group; |
2110 | + const BIGNUM *k_priv = NULL; |
2111 | + const BIGNUM *k_pubx = NULL; |
2112 | + const BIGNUM *k_puby = NULL; |
2113 | + EC_POINT *k_pub = NULL; |
2114 | + |
2115 | + switch (group_id) { |
2116 | + case HIP_DH_NIST_P_256: |
2117 | + data_set = TEST_ECDH_NIST_P_256; |
2118 | + break; |
2119 | + case HIP_DH_NIST_P_384: |
2120 | + data_set = TEST_ECDH_NIST_P_384; |
2121 | + break; |
2122 | + case HIP_DH_NIST_P_521: |
2123 | + data_set = TEST_ECDH_NIST_P_521; |
2124 | + break; |
2125 | + default: |
2126 | + return NULL; |
2127 | + } |
2128 | + |
2129 | + size = hip_get_dh_size(group_id) / 2; |
2130 | + |
2131 | + switch (request_data) { |
2132 | + case SIDE_A_KEY: |
2133 | + key = hip_generate_ecdh_key(group_id); |
2134 | + group = EC_KEY_get0_group(key); |
2135 | + k_priv = BN_bin2bn(data_set + size * TEST_ECDH_PRIV_A, size, NULL); |
2136 | + k_pubx = BN_bin2bn(data_set + size * TEST_ECDH_PUBX_A, size, NULL); |
2137 | + k_puby = BN_bin2bn(data_set + size * TEST_ECDH_PUBY_A, size, NULL); |
2138 | + k_pub = EC_POINT_new(group); |
2139 | + EC_POINT_set_affine_coordinates_GFp(group, k_pub, k_pubx, k_puby, NULL); |
2140 | + EC_KEY_set_public_key(key, k_pub); |
2141 | + EC_KEY_set_private_key(key, k_priv); |
2142 | + return key; |
2143 | + case SIDE_B_KEY: |
2144 | + key = hip_generate_ecdh_key(group_id); |
2145 | + group = EC_KEY_get0_group(key); |
2146 | + k_priv = BN_bin2bn(data_set + size * TEST_ECDH_PRIV_B, size, NULL); |
2147 | + k_pubx = BN_bin2bn(data_set + size * TEST_ECDH_PUBX_B, size, NULL); |
2148 | + k_puby = BN_bin2bn(data_set + size * TEST_ECDH_PUBY_B, size, NULL); |
2149 | + k_pub = EC_POINT_new(group); |
2150 | + EC_POINT_set_affine_coordinates_GFp(group, k_pub, k_pubx, k_puby, NULL); |
2151 | + EC_KEY_set_public_key(key, k_pub); |
2152 | + EC_KEY_set_private_key(key, k_priv); |
2153 | + return key; |
2154 | + case SHARED_SECRET: |
2155 | + return data_set + size * TEST_ECDH_SHARED; |
2156 | + } |
2157 | + |
2158 | + return NULL; |
2159 | +} |
2160 | + |
2161 | START_TEST(test_create_ecdsa_key_invalid_id) |
2162 | { |
2163 | HIP_DEBUG("Trying to create some invalid ECDSA keys.\n"); |
2164 | @@ -244,6 +457,108 @@ |
2165 | } |
2166 | END_TEST |
2167 | |
2168 | +#define TEST_ECDH_GROUP_SIZE 3 |
2169 | +static int TEST_ECDH_GROUPS[TEST_ECDH_GROUP_SIZE] = { HIP_DH_NIST_P_256, |
2170 | + HIP_DH_NIST_P_384, |
2171 | + HIP_DH_NIST_P_521 }; |
2172 | + |
2173 | +START_TEST(test_generate_ecdh_key_invalid_group_id) |
2174 | +{ |
2175 | + fail_unless(hip_generate_ecdh_key(0) == NULL); |
2176 | + fail_unless(hip_generate_ecdh_key(-1) == NULL); |
2177 | + fail_unless(hip_generate_ecdh_key(HIP_MAX_DH_GROUP_ID) == NULL); |
2178 | +} |
2179 | +END_TEST |
2180 | + |
2181 | +START_TEST(test_generate_ecdh_key_valid_group_id) |
2182 | +{ |
2183 | + EC_KEY *key; |
2184 | + int i; |
2185 | + |
2186 | + for (i = 0; i < TEST_ECDH_GROUP_SIZE; i++) { |
2187 | + key = hip_generate_ecdh_key(TEST_ECDH_GROUPS[i]); |
2188 | + fail_if(key == NULL || EC_KEY_check_key(key) == 0); |
2189 | + } |
2190 | +} |
2191 | +END_TEST |
2192 | + |
2193 | +START_TEST(test_ecdh_generate_2_keys_and_share_secret) |
2194 | +{ |
2195 | + EC_KEY *key1; |
2196 | + EC_KEY *key2; |
2197 | + int out1, out2; |
2198 | + int len1, len2; |
2199 | + int i; |
2200 | + int group_id; |
2201 | + int pubkey_size; |
2202 | + |
2203 | + for (i = 0; i < TEST_ECDH_GROUP_SIZE; i++) { |
2204 | + group_id = TEST_ECDH_GROUPS[i]; |
2205 | + pubkey_size = hip_get_dh_size(group_id); |
2206 | + fail_if(pubkey_size <= 0); |
2207 | + |
2208 | + key1 = hip_generate_ecdh_key(group_id); |
2209 | + key2 = hip_generate_ecdh_key(group_id); |
2210 | + fail_if(key1 == NULL || key2 == NULL); |
2211 | + |
2212 | + const EC_POINT *k1pub = EC_KEY_get0_public_key(key1); |
2213 | + const EC_POINT *k2pub = EC_KEY_get0_public_key(key2); |
2214 | + |
2215 | + len1 = len2 = pubkey_size / 2; |
2216 | + unsigned char share1[len1]; |
2217 | + unsigned char share2[len2]; |
2218 | + |
2219 | + out1 = ECDH_compute_key(share1, len1, k2pub, key1, NULL); |
2220 | + out2 = ECDH_compute_key(share2, len2, k1pub, key2, NULL); |
2221 | + fail_if(out1 <= 0 || out2 <= 0); |
2222 | + fail_if(out1 != len1 && out2 != len2); |
2223 | + fail_if(memcmp(share1, share2, len1) != 0); |
2224 | + } |
2225 | +} |
2226 | +END_TEST |
2227 | + |
2228 | +START_TEST(test_ecdh_encode_publickey) |
2229 | +{ |
2230 | + int i, group_id, key_size; |
2231 | + |
2232 | + for (i = 0; i < TEST_ECDH_GROUP_SIZE; i++) { |
2233 | + group_id = TEST_ECDH_GROUPS[i]; |
2234 | + key_size = hip_get_dh_size(group_id); |
2235 | + uint8_t out[key_size]; |
2236 | + EC_KEY *key = hip_generate_ecdh_key(group_id); |
2237 | + fail_if(hip_encode_ecdh_publickey(key, out, key_size) != key_size); |
2238 | + } |
2239 | +} |
2240 | +END_TEST |
2241 | + |
2242 | +START_TEST(test_ecdh_gen_shared_key) |
2243 | +{ |
2244 | + int i, group_id, size, res; |
2245 | + |
2246 | + for (i = 0; i < TEST_ECDH_GROUP_SIZE; i++) { |
2247 | + group_id = TEST_ECDH_GROUPS[i]; |
2248 | + size = hip_get_dh_size(group_id) / 2; |
2249 | + uint8_t pub[size * 2]; |
2250 | + uint8_t out[size]; |
2251 | + EC_KEY *a = generate_test_ecdh_data(group_id, SIDE_A_KEY); |
2252 | + EC_KEY *b = generate_test_ecdh_data(group_id, SIDE_B_KEY); |
2253 | + void *secret = generate_test_ecdh_data(group_id, SHARED_SECRET); |
2254 | + fail_if(a == NULL || b == NULL || secret == NULL); |
2255 | + fail_if(EC_KEY_check_key(a) == 0 || EC_KEY_check_key(b) == 0); |
2256 | + |
2257 | + hip_encode_ecdh_publickey(b, pub, size * 2); |
2258 | + res = hip_gen_ecdh_shared_key(a, pub, pub + size, size, out, size); |
2259 | + fail_if(res != size); |
2260 | + fail_if(memcmp(secret, out, size) != 0); |
2261 | + |
2262 | + hip_encode_ecdh_publickey(a, pub, size * 2); |
2263 | + res = hip_gen_ecdh_shared_key(b, pub, pub + size, size, out, size); |
2264 | + fail_if(res != size); |
2265 | + fail_if(memcmp(secret, out, size) != 0); |
2266 | + } |
2267 | +} |
2268 | +END_TEST |
2269 | + |
2270 | Suite *libcore_crypto(void) |
2271 | { |
2272 | Suite *s = suite_create("libcore/crypto"); |
2273 | @@ -257,6 +572,11 @@ |
2274 | tcase_add_test(tc_core, test_load_invalid_ecdsa_key); |
2275 | tcase_add_test(tc_core, test_impl_ecdsa_sign_verify); |
2276 | tcase_add_test(tc_core, test_invalid_impl_ecdsa_sign_verify); |
2277 | + tcase_add_test(tc_core, test_generate_ecdh_key_invalid_group_id); |
2278 | + tcase_add_test(tc_core, test_generate_ecdh_key_valid_group_id); |
2279 | + tcase_add_test(tc_core, test_ecdh_generate_2_keys_and_share_secret); |
2280 | + tcase_add_test(tc_core, test_ecdh_encode_publickey); |
2281 | + tcase_add_test(tc_core, test_ecdh_gen_shared_key); |
2282 | |
2283 | suite_add_tcase(s, tc_core); |
2284 |
Seems ok to me. I would suggest merging on in a week, let's say 14.9.2012, unless somebody has comments or requests more time.