Merge lp:~hipl-core/hipl/hipv2-dh-ecdh into lp:hipl

Proposed by Miika Komu
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
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.

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/modularize/rewrite the entire branch, so please no generic or high level comments, only specific ones! Thanks.

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/crypto.c)

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.

To post a comment you must log in.
Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

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.

review: Approve
Revision history for this message
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://code.launchpad.net/~hipl-core/hipl/hipv2-dh-ecdh/+merge/123405
>
> 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_r1_v2(struct in6_addr *ip_i, struct in6_addr *ip_r,
> + struct in6_addr *our_hit, const int dh_group_id)
> +{
> + /* Create a copy of the found entry */
> + len = hip_get_msg_total_len(&hid->r1_v2[dh_group_id][idx].buf.msg);
> + 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

review: Needs Fixing
Revision history for this message
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal
Download full text (10.6 KiB)

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_byte_order(void *content, unsigned count,
> @@ -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(item_size == sizeof(uint16_t) || item_size == sizeof(uint32_t));
> -

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(dhprime_modp_3072),
> sizeof(dhprime_modp_6144),
> sizeof(dhprime_modp_8192),
> + 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_get_field_type(EC_GROUP_method_of(group))
> + != NID_X9_62_prime_field) {
> + HIP_ERROR("Invalid group method, only prime curve is supported.\n");
> + return 0;
> + }
> +
> + peer_pub = EC_POINT_new(group);

Can this fail? Also applies to the other openssl *_new() functions.

> + out = ECDH_compute_key(shared_key, outlen, peer_pub, key, NULL);
> + 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_check_key(key) == 0) {
> + 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...

review: Needs Information
Revision history for this message
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_r1_v2(struct in6_addr *ip_i, struct in6_addr *ip_r,
>> + struct in6_addr *our_hit, const int dh_group_id)
>> +{
>> + /* Create a copy of the found entry */
>> + len = hip_get_msg_total_len(&hid->r1_v2[dh_group_id][idx].buf.msg);
>> + 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

Revision history for this message
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_byte_order(void *content, unsigned count,
>> @@ -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(item_size == sizeof(uint16_t) || item_size == sizeof(uint32_t));
>> -
> 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_byte_order(...);
}

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

Revision history for this message
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal

On 15.09.2012 18:46, Xin wrote:
>>> - HIP_ASSERT(item_size == sizeof(uint16_t) || item_size == sizeof(uint32_t));
>> 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_LIST_SIZE; j++) {
>> + group_id = HIP_DH_GROUP_LIST[j];
>> + for (i = 0; i < HIP_R1TABLESIZE; i++) {
>> + cookie_k = get_cookie_difficulty();
>> + hip_msg_init(&id_entry->r1_v2[j][i].buf.msg);
>> +
>> + if (hip_create_r1_v2(&id_entry->r1_v2[group_id][i].buf.msg, hit, sign,
>> + 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.

Revision history for this message
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.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal
Download full text (3.4 KiB)

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_r1_v2(struct in6_addr *ip_i, struct in6_addr *ip_r,
> >>+ struct in6_addr *our_hit, const int dh_group_id)
> >>+{
> >>+ /* Create a copy of the found entry */
> >>+ len = hip_get_msg_total_len(&hid->r1_v2[dh_group_id][idx].buf.msg);
> >>+ 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...

Read more...

Revision history for this message
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-0.57.cfg':

--- /home/mkomu/projects/hipl-bzr/trunk/libhipl/cookie.c 2012-09-17 15:37:06.982202000 +0300
+++ - 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/projects/hipl-bzr/trunk/libhipl/output.c 2012-09-17 15:37:06.982202000 +0300
+++ - 2012-09-17 15:37:59.438372623 +0300
@@ -341,7 +341,7 @@
 static int add_echo_response(struct hip_packet_context *ctx, int sign)
 {
     int param_type = sign ? HIP_PARAM_ECHO_REQUEST_SIGN
- : HIP_PARAM_ECHO_REQUEST;
+ : HIP_PARAM_ECHO_REQUEST;

     const struct hip_echo_msg *ping = hip_get_param(ctx->input_msg, param_type);

review: Needs Fixing
Revision history for this message
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/modularize/rewrite the entire branch, so please no generic or high level comments, only specific ones! Thanks.

I looked through your recent commits but not the whole thing.

> + for (j = 0; j < HIP_DH_GROUP_LIST_SIZE; j++) {
> + group_id = HIP_DH_GROUP_LIST[j];
> + for (i = 0; i < HIP_R1TABLESIZE; i++) {
> + cookie_k = get_cookie_difficulty();
> + hip_msg_init(&id_entry->r1_v2[j][i].buf.msg);
> +
> + if (hip_create_r1_v2(&id_entry->r1_v2[j][i].buf.msg, hit, sign,
> + 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_difficulty() is randomized in some sense.

review: Approve
lp:~hipl-core/hipl/hipv2-dh-ecdh updated
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().

Revision history for this message
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.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (10.0 KiB)

 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/modularize/rewrite the entire branch, so please no generic
> 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_GROUP_LIST[HIP_DH_GROUP_LIST_SIZE] = {
> + 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_ecdh_key(const int group_id)
> +{
> + char rnd_seed[20];
> + struct timeval tv;
> + EC_KEY *key;
> + int nid;
> +
> + if (group_id == HIP_DH_NIST_P_256) {
> + nid = NID_X9_62_prime256v1;
> + } 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("Unsupported ECDH group: %d\n", group_id);
> + return NULL;
> + }

This calls for a switch statement.

> +int hip_gen_ecdh_shared_key(EC_KEY *const key,
> + 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_key(shared_key, outlen, peer_pub, key, NULL);
> + 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_ecdh_publickey(EC_KEY *key, uint8_t *out, int outlen)
> +{
> + 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_get_affine_coordinates_GFp(EC_KEY_get0_group(key),
> + ...

review: Needs Fixing
lp:~hipl-core/hipl/hipv2-dh-ecdh updated
6266. By Xin

Fix the cookie indexing for ECDH groups.

6267. By Xin

Revise code based on Diego's review (except 3 comments on redundant code).

6268. By Xin

Merge duplicated code for creating the R1 packet.

6269. By Xin

Fix the code duplication on hip_get_r1().

Revision history for this message
Xin (eric-nevup) wrote :
Download full text (3.9 KiB)

On 10/30/2012 03:52 AM, Diego Biurrun wrote:
> Review: Needs Fixing
>> + if (EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key),
>> + EC_KEY_get0_public_key(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_get_affine_coordinates_GFp" because the failure of the
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_ecdh(uint8_t *buffer, int bufsize, int group_id)
>> +{
>> + EC_KEY *key;
>> + int ret;
>> +
>> + if (!hip_is_ecdh_group(group_id)) {
>> + HIP_ERROR("Invalid group id for ECDH: %d\n", group_id);
>> + return -1;
>> + }
>> +
>> + if (ecdh_table[group_id] == NULL) {
>> + key = hip_generate_ecdh_key(group_id);
>> + if (key == NULL) {
>> + HIP_ERROR("Failed to generate an ECDH key for group: %d\n",
>> + group_id);
>> + return -1;
>> + }
>> + ecdh_table[group_id] = key;
>> + }
>> +
>> + key = ecdh_table[group_id];
>> + if ((ret = hip_encode_ecdh_publickey(key, buffer, bufsize)) < 0) {
>> + 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_dh_key(group_id);
>> + 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_key(const int group_id)
>> +{
>> + EC_KEY *tmp, *okey;
>> +
>> + tmp = hip_generate_ecdh_key(group_id);
>> + if (!tmp) {
>> + ...

Read more...

Revision history for this message
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://bazaar.launchpad.net/~hipl-core/hipl/hipv2-dh-ecdh/revision/6269?remember=6269&compare_revid=6265
> <http://bazaar.launchpad.net/%7Ehipl-core/hipl/hipv2-dh-ecdh/revision/6269?remember=6269&compare_revid=6265>
> 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

review: Needs Information
lp:~hipl-core/hipl/hipv2-dh-ecdh updated
6270. By Miika Komu

Synchronized with trunk revision 6406

6271. By Miika Komu

Synchronized with trunk revision 6436

Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches

to all changes: