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
=== modified file 'libcore/builder.c'
--- libcore/builder.c 2013-08-19 18:30:29 +0000
+++ libcore/builder.c 2013-10-22 12:34:40 +0000
@@ -119,7 +119,8 @@
119 * @param content the buffer to hold all the items119 * @param content the buffer to hold all the items
120 * @param count the number of items in the buffer120 * @param count the number of items in the buffer
121 * @param item_size the size of each item in bytes. The function only supports121 * @param item_size the size of each item in bytes. The function only supports
122 * items in 2 bytes or 4 bytes.122 * byte conversion for items in 2 bytes or 4 bytes. For items
123 * with other size, no conversion will be applied.
123 * @param flag the flag to decide the byte conversion order124 * @param flag the flag to decide the byte conversion order
124 */125 */
125static void convert_byte_order(void *content, unsigned count,126static void convert_byte_order(void *content, unsigned count,
@@ -128,14 +129,12 @@
128 uint32_t (*f32)(uint32_t) = (flag == CBO_HTON) ? htonl : ntohl;129 uint32_t (*f32)(uint32_t) = (flag == CBO_HTON) ? htonl : ntohl;
129 uint16_t (*f16)(uint16_t) = (flag == CBO_HTON) ? htons : ntohs;130 uint16_t (*f16)(uint16_t) = (flag == CBO_HTON) ? htons : ntohs;
130131
131 HIP_ASSERT(item_size == sizeof(uint16_t) || item_size == sizeof(uint32_t));
132
133 if (item_size == sizeof(uint16_t)) {132 if (item_size == sizeof(uint16_t)) {
134 uint16_t *p = content;133 uint16_t *p = content;
135 for (unsigned i = 0; i < count; i++) {134 for (unsigned i = 0; i < count; i++) {
136 p[i] = f16(p[i]);135 p[i] = f16(p[i]);
137 }136 }
138 } else {137 } else if (item_size == sizeof(uint32_t)) {
139 uint32_t *p = content;138 uint32_t *p = content;
140 for (unsigned i = 0; i < count; i++) {139 for (unsigned i = 0; i < count; i++) {
141 p[i] = f32(p[i]);140 p[i] = f32(p[i]);
@@ -730,7 +729,8 @@
730 HIP_PARAM_ESP_PROT_ANCHOR,729 HIP_PARAM_ESP_PROT_ANCHOR,
731 HIP_PARAM_ESP_PROT_BRANCH,730 HIP_PARAM_ESP_PROT_BRANCH,
732 HIP_PARAM_ESP_PROT_SECRET,731 HIP_PARAM_ESP_PROT_SECRET,
733 HIP_PARAM_ESP_PROT_ROOT732 HIP_PARAM_ESP_PROT_ROOT,
733 HIP_PARAM_DH_GROUP_LIST
734 };734 };
735 hip_tlv type = hip_get_param_type(param);735 hip_tlv type = hip_get_param_type(param);
736736
@@ -1200,6 +1200,7 @@
1200 case HIP_PARAM_CERT: return "HIP_PARAM_CERT";1200 case HIP_PARAM_CERT: return "HIP_PARAM_CERT";
1201 case HIP_PARAM_CERT_X509_REQ: return "HIP_PARAM_CERT_X509_REQ";1201 case HIP_PARAM_CERT_X509_REQ: return "HIP_PARAM_CERT_X509_REQ";
1202 case HIP_PARAM_CERT_X509_RESP: return "HIP_PARAM_CERT_X509_RESP";1202 case HIP_PARAM_CERT_X509_RESP: return "HIP_PARAM_CERT_X509_RESP";
1203 case HIP_PARAM_DH_GROUP_LIST: return "HIP_PARAM_DH_GROUP_LIST";
1203 case HIP_PARAM_DH_SHARED_KEY: return "HIP_PARAM_DH_SHARED_KEY";1204 case HIP_PARAM_DH_SHARED_KEY: return "HIP_PARAM_DH_SHARED_KEY";
1204 case HIP_PARAM_DIFFIE_HELLMAN: return "HIP_PARAM_DIFFIE_HELLMAN";1205 case HIP_PARAM_DIFFIE_HELLMAN: return "HIP_PARAM_DIFFIE_HELLMAN";
1205 case HIP_PARAM_DSA_SIGN_DATA: return "HIP_PARAM_DSA_SIGN_DATA";1206 case HIP_PARAM_DSA_SIGN_DATA: return "HIP_PARAM_DSA_SIGN_DATA";
12061207
=== modified file 'libcore/crypto.c'
--- libcore/crypto.c 2013-09-20 06:29:24 +0000
+++ libcore/crypto.c 2013-10-22 12:34:40 +0000
@@ -46,6 +46,7 @@
46 */46 */
4747
48#include <errno.h>48#include <errno.h>
49#include <stdbool.h>
49#include <stdint.h>50#include <stdint.h>
50#include <stdio.h>51#include <stdio.h>
51#include <stdlib.h>52#include <stdlib.h>
@@ -68,6 +69,12 @@
68#include "crypto.h"69#include "crypto.h"
6970
7071
72const uint8_t HIP_DH_GROUP_LIST[HIP_DH_GROUP_LIST_SIZE] = {
73 HIP_DH_NIST_P_384,
74 HIP_DH_OAKLEY_15,
75 HIP_DH_OAKLEY_5
76};
77
71/*78/*
72 * Diffie-Hellman primes79 * Diffie-Hellman primes
73 */80 */
@@ -325,6 +332,10 @@
325 sizeof(dhprime_modp_3072),332 sizeof(dhprime_modp_3072),
326 sizeof(dhprime_modp_6144),333 sizeof(dhprime_modp_6144),
327 sizeof(dhprime_modp_8192),334 sizeof(dhprime_modp_8192),
335 64, /* NIST P-256 */
336 96, /* NIST P-384 */
337 132, /* NIST P-512 */
338 0, /* SECP 160R1, unsupported */
328};339};
329340
330static unsigned char dhgen[HIP_MAX_DH_GROUP_ID] = { 0,341static unsigned char dhgen[HIP_MAX_DH_GROUP_ID] = { 0,
@@ -701,6 +712,172 @@
701 return dh;712 return dh;
702}713}
703714
715#ifdef HAVE_EC_CRYPTO
716
717/**
718 * Test if the current DH group ID belongs to an ECDH group.
719 *
720 * @param group_id the Diffie-Hellman group ID
721 * @return True if the given group is an ECDH group, False otherwise.
722 */
723bool hip_is_ecdh_group(const int group_id)
724{
725 return group_id == HIP_DH_NIST_P_256 ||
726 group_id == HIP_DH_NIST_P_384 ||
727 group_id == HIP_DH_NIST_P_521;
728}
729
730/**
731 * Generate a new Elliptic Curve Diffie-Hellman key.
732 *
733 * @param group_id the group ID of the DH_GROUP defined in HIPv2
734 * @return a new ECDH key (caller deallocates), or NULL on error.
735 */
736EC_KEY *hip_generate_ecdh_key(const int group_id)
737{
738 char rnd_seed[20];
739 struct timeval tv;
740 EC_KEY *key;
741 int nid;
742
743 switch (group_id) {
744 case HIP_DH_NIST_P_256:
745 nid = NID_X9_62_prime256v1;
746 break;
747 case HIP_DH_NIST_P_384:
748 nid = NID_secp384r1;
749 break;
750 case HIP_DH_NIST_P_521:
751 nid = NID_secp521r1;
752 break;
753 default:
754 HIP_ERROR("Unsupported ECDH group: %d\n", group_id);
755 return NULL;
756 }
757
758 gettimeofday(&tv, NULL);
759 sprintf(rnd_seed, "%x%x", (unsigned int) tv.tv_usec,
760 (unsigned int) tv.tv_sec);
761 RAND_seed(rnd_seed, sizeof(rnd_seed));
762
763 if ((key = EC_KEY_new_by_curve_name(nid)) == NULL) {
764 HIP_ERROR("Failed to create a new EC_KEY from nid: %d\n", nid);
765 return NULL;
766 }
767
768 if (EC_KEY_generate_key(key) == 0) {
769 HIP_ERROR("Failed to generate parameters for the new EC_KEY.\n");
770 EC_KEY_free(key);
771 return NULL;
772 }
773
774 return key;
775}
776
777/**
778 * Generate a shared key using Elliptic Curve Diffie-Hellman.
779 * This method only supports keys using Prime Curve.
780 *
781 * @param key the Elliptic Curve Diffie-Hellman key
782 * @param peer_pub_x the x coordinator of the peer's public key
783 * @param peer_pub_y the y coordinator of the peer's public key
784 * @param peer_len length of the @c peer_pub_x or @c peer_pub_y (these two
785 * length values are identical)
786 * @param shared_key shared key to generate
787 * @param outlen the length of the @c shared_key
788 * @return the length of the shared key on success, 0 otherwise
789 */
790int hip_gen_ecdh_shared_key(EC_KEY *const key,
791 const uint8_t *const peer_pub_x,
792 const uint8_t *const peer_pub_y,
793 const size_t peer_len,
794 uint8_t *const shared_key,
795 const size_t outlen)
796{
797 const EC_GROUP *group;
798 BIGNUM *peer_pubx = NULL;
799 BIGNUM *peer_puby = NULL;
800 EC_POINT *peer_pub = NULL;
801 unsigned int err = 1;
802
803 if (EC_KEY_check_key(key) == 0) {
804 HIP_ERROR("Invalid input EC_KEY\n");
805 return 0;
806 }
807
808 group = EC_KEY_get0_group(key);
809
810 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group))
811 != NID_X9_62_prime_field) {
812 HIP_ERROR("Invalid group method, only prime curve is supported.\n");
813 return 0;
814 }
815
816 peer_pub = EC_POINT_new(group);
817 peer_pubx = BN_bin2bn(peer_pub_x, peer_len, NULL);
818 peer_puby = BN_bin2bn(peer_pub_y, peer_len, NULL);
819
820 HIP_IFEL(EC_POINT_set_affine_coordinates_GFp(group, peer_pub, peer_pubx,
821 peer_puby, NULL) == 0,
822 0, "Failed to create peer's public key.\n");
823
824 err = ECDH_compute_key(shared_key, outlen, peer_pub, key, NULL);
825 HIP_IFEL(err == 0 || err != peer_len, 0,
826 "Failed to compute the ECDH shared key\n");
827
828out_err:
829 BN_free(peer_pubx);
830 BN_free(peer_puby);
831 EC_POINT_free(peer_pub);
832 return err;
833}
834
835/**
836 * Encode an ECDH public key into a character array.
837 *
838 * @param key the ECDH key
839 * @param[out] out the character array
840 * @param outlen the length of @c out in bytes
841 * @return the number of bytes written
842 */
843int hip_encode_ecdh_publickey(EC_KEY *key, uint8_t *out, int outlen)
844{
845 BIGNUM *pubx = NULL;
846 BIGNUM *puby = NULL;
847 int len;
848 int err = 0;
849
850 if (key == NULL || out == NULL || outlen < 0 ||
851 EC_KEY_check_key(key) == 0) {
852 HIP_ERROR("Invalid input\n");
853 return -1;
854 }
855
856 pubx = BN_new();
857 puby = BN_new();
858 HIP_IFEL(pubx == NULL || puby == NULL, -1, "Failed to initialize Big Number\n");
859
860 err = EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key),
861 EC_KEY_get0_public_key(key),
862 pubx, puby, NULL);
863 HIP_IFEL(err == 0, -1,
864 "Failed to get x,y coordinates from the ECDH key\n");
865
866 len = BN_num_bytes(pubx);
867 HIP_IFEL(outlen < len * 2, -1, "Output buffer too small\n");
868
869 bn2bin_safe(pubx, out, outlen / 2);
870 bn2bin_safe(puby, out + outlen / 2, outlen / 2);
871 err = outlen;
872
873out_err:
874 BN_free(pubx);
875 BN_free(puby);
876 return err;
877}
878
879#endif /* HAVE_EC_CRYPTO */
880
704/**881/**
705 * Determine the size for required to store DH shared secret.882 * Determine the size for required to store DH shared secret.
706 * @param hip_dh_group_type the group type from DIFFIE_HELLMAN parameter883 * @param hip_dh_group_type the group type from DIFFIE_HELLMAN parameter
@@ -714,7 +891,7 @@
714 if (hip_dh_group_type == 0) {891 if (hip_dh_group_type == 0) {
715 HIP_ERROR("Trying to use reserved DH group type 0\n");892 HIP_ERROR("Trying to use reserved DH group type 0\n");
716 } else if (hip_dh_group_type > ARRAY_SIZE(dhprime_len)) {893 } else if (hip_dh_group_type > ARRAY_SIZE(dhprime_len)) {
717 HIP_ERROR("Unknown/unsupported MODP group %d\n", hip_dh_group_type);894 HIP_ERROR("Unknown/unsupported DH or ECDH group %d\n", hip_dh_group_type);
718 } else {895 } else {
719 ret = dhprime_len[hip_dh_group_type];896 ret = dhprime_len[hip_dh_group_type];
720 }897 }
721898
=== modified file 'libcore/crypto.h'
--- libcore/crypto.h 2012-05-12 10:21:32 +0000
+++ libcore/crypto.h 2013-10-22 12:34:40 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -28,6 +28,7 @@
2828
29#include "config.h"29#include "config.h"
3030
31#include <stdbool.h>
31#include <stdint.h>32#include <stdint.h>
32#include <netinet/in.h>33#include <netinet/in.h>
33#include <sys/types.h>34#include <sys/types.h>
@@ -51,15 +52,25 @@
5152
52/* These should be consistent with the table length in crypto.c and53/* These should be consistent with the table length in crypto.c and
53 * crypto/dh.c */54 * crypto/dh.c */
54#define HIP_DH_384 1 /* 384-bit group */55/* 384-bit group, DEPRECATED from HIPv2 */
55#define HIP_DH_OAKLEY_1 2 /* 768-bit OAKLEY well known group 1 */56#define HIP_DH_384 1
57/* 768-bit OAKLEY well known group 1, DEPRECATED from HIPv2 */
58#define HIP_DH_OAKLEY_1 2
56#define HIP_DH_OAKLEY_5 3 /* 1536-bit MODP group */59#define HIP_DH_OAKLEY_5 3 /* 1536-bit MODP group */
57#define HIP_DH_OAKLEY_15 4 /* 3072-bit MODP group */60#define HIP_DH_OAKLEY_15 4 /* 3072-bit MODP group */
58#define HIP_DH_OAKLEY_17 5 /* 6144-bit MODP group */61/* 6144-bit MODP group, DEPRECATED from HIPv2 */
59#define HIP_DH_OAKLEY_18 6 /* 8192-bit MODP group */62#define HIP_DH_OAKLEY_17 5
63/* 8192-bit MODP group, DEPRECATED from HIPv2 */
64#define HIP_DH_OAKLEY_18 6
65/* Group 7 to 10 are new groups defined in HIPv2, among which group 7,8 and 9
66 * are Ellipse Curve groups. */
67#define HIP_DH_NIST_P_256 7
68#define HIP_DH_NIST_P_384 8
69#define HIP_DH_NIST_P_521 9
70#define HIP_DH_SECP_160_R1 10
60#define HIP_FIRST_DH_GROUP_ID HIP_DH_OAKLEY_571#define HIP_FIRST_DH_GROUP_ID HIP_DH_OAKLEY_5
61#define HIP_SECOND_DH_GROUP_ID HIP_DH_38472#define HIP_SECOND_DH_GROUP_ID HIP_DH_384
62#define HIP_MAX_DH_GROUP_ID 773#define HIP_MAX_DH_GROUP_ID 11
6374
64#define DSA_KEY_DEFAULT_BITS 102475#define DSA_KEY_DEFAULT_BITS 1024
65#define RSA_KEY_DEFAULT_BITS 102476#define RSA_KEY_DEFAULT_BITS 1024
@@ -86,6 +97,13 @@
86#define HIP_SHA(buffer, total_len, hash) SHA((buffer), (total_len), (hash))97#define HIP_SHA(buffer, total_len, hash) SHA((buffer), (total_len), (hash))
87#endif98#endif
8899
100/* HIPv2: default value for DH_GROUP_LIST parameter */
101#define HIP_DH_GROUP_LIST_SIZE 3
102const uint8_t HIP_DH_GROUP_LIST[HIP_DH_GROUP_LIST_SIZE];
103
104/* HIPv2: max acceptable size of DH group list, longer part will be ignored */
105#define HIP_DH_GROUP_MAX_RECV_SIZE 6
106
89int ssl_rsa_verify(uint8_t *digest, uint8_t *public_key, uint8_t *signature, int pub_klen);107int ssl_rsa_verify(uint8_t *digest, uint8_t *public_key, uint8_t *signature, int pub_klen);
90int ssl_dsa_verify(uint8_t *digest, uint8_t *public_key, uint8_t *signature);108int ssl_dsa_verify(uint8_t *digest, uint8_t *public_key, uint8_t *signature);
91/* In kernel these come from crypto/dh.h, included above */109/* In kernel these come from crypto/dh.h, included above */
@@ -121,6 +139,15 @@
121int impl_ecdsa_verify(const unsigned char *const digest,139int impl_ecdsa_verify(const unsigned char *const digest,
122 EC_KEY *const ecdsa,140 EC_KEY *const ecdsa,
123 const unsigned char *const signature);141 const unsigned char *const signature);
142bool hip_is_ecdh_group(const int group_id);
143EC_KEY *hip_generate_ecdh_key(const int group_id);
144int hip_encode_ecdh_publickey(EC_KEY *key, uint8_t *out, int outlen);
145int hip_gen_ecdh_shared_key(EC_KEY *const key,
146 const uint8_t *const peer_pub_x,
147 const uint8_t *const peer_pub_y,
148 const size_t peer_len,
149 uint8_t *const shared_key,
150 const size_t outlen);
124#endif /* HAVE_EC_CRYPTO */151#endif /* HAVE_EC_CRYPTO */
125152
126#endif /* HIPL_LIBCORE_CRYPTO_H */153#endif /* HIPL_LIBCORE_CRYPTO_H */
127154
=== modified file 'libcore/protodefs.h'
--- libcore/protodefs.h 2012-07-12 11:32:14 +0000
+++ libcore/protodefs.h 2013-10-22 12:34:40 +0000
@@ -143,6 +143,7 @@
143#define HIP_PARAM_SOLUTION 321143#define HIP_PARAM_SOLUTION 321
144#define HIP_PARAM_SEQ 385144#define HIP_PARAM_SEQ 385
145#define HIP_PARAM_ACK 449145#define HIP_PARAM_ACK 449
146#define HIP_PARAM_DH_GROUP_LIST 511
146#define HIP_PARAM_DIFFIE_HELLMAN 513147#define HIP_PARAM_DIFFIE_HELLMAN 513
147#define HIP_PARAM_HIP_TRANSFORM 577148#define HIP_PARAM_HIP_TRANSFORM 577
148#define HIP_PARAM_ENCRYPTED 641149#define HIP_PARAM_ENCRYPTED 641
149150
=== modified file 'libhipl/cookie.c'
--- libhipl/cookie.c 2012-06-03 10:26:55 +0000
+++ libhipl/cookie.c 2013-10-22 12:34:40 +0000
@@ -177,83 +177,99 @@
177}177}
178178
179/**179/**
180 * get a copy of R1entry structure180 * Get a copy of R1entry structure.
181 *181 *
182 * @param ip_i Initiator's IPv6182 * @param ip_i Initiator's IPv6
183 * @param ip_r Responder's IPv6183 * @param ip_r Responder's IPv6
184 * @param our_hit Our HIT184 * @param our_hit Our HIT
185 * @param hip_version HIP message version185 * @param dh_group_id Diffie Hellman group ID. -1 for HIPv1, otherwise return
186 *186 R1 for HIPv2
187 * @note Comments for the if 0 code are inlined below.187 * @return A R1 packet copy on success, NULL on error
188 *
189 * Returns NULL if error.
190 */188 */
191struct hip_common *hip_get_r1(struct in6_addr *ip_i, struct in6_addr *ip_r,189struct hip_common *hip_get_r1(struct in6_addr *ip_i, struct in6_addr *ip_r,
192 struct in6_addr *our_hit, uint8_t hip_version)190 struct in6_addr *our_hit, const int dh_group_id)
193{191{
194 struct hip_common *err = NULL, *r1 = NULL;192 struct hip_common *r1 = NULL;
195 struct hip_r1entry *hip_r1table = NULL;193 struct hip_common *r1_matched = NULL;
196 struct local_host_id *hid = NULL;194 struct local_host_id *hid = NULL;
197 int idx, len;195 int idx, len;
198196
199 /* Find the proper R1 table and copy the R1 message from the table */197 /* Find the proper R1 table and copy the R1 message from the table */
200 HIP_IFEL(!(hid = hip_get_hostid_entry_by_lhi_and_algo(our_hit, HIP_ANY_ALGO, -1)),198 hid = hip_get_hostid_entry_by_lhi_and_algo(our_hit, HIP_ANY_ALGO, -1);
201 NULL, "Unknown HIT\n");199 if (hid == NULL) {
200 HIP_ERROR("Unknown HIT\n");
201 return NULL;
202 }
202203
203 hip_r1table = hid->r1[hip_version];204 idx = calc_cookie_idx(ip_i, ip_r);
204 idx = calc_cookie_idx(ip_i, ip_r);
205 HIP_DEBUG("Calculated index: %d\n", idx);205 HIP_DEBUG("Calculated index: %d\n", idx);
206206
207 if (dh_group_id == -1) {
208 r1_matched = &hid->r1[idx].buf.msg;
209 } else {
210 r1_matched = &hid->r1_v2[dh_group_id][idx].buf.msg;
211 }
207 /* Create a copy of the found entry */212 /* Create a copy of the found entry */
208 len = hip_get_msg_total_len(&hip_r1table[idx].buf.msg);213 len = hip_get_msg_total_len(r1_matched);
209 r1 = hip_msg_alloc();214 if (len <= 0) {
210 memcpy(r1, &hip_r1table[idx].buf.msg, len);215 HIP_ERROR("Invalid r1 entry\n");
211 err = r1;216 return NULL;
212217 }
213out_err:218
214 if (!err) {219 if ((r1 = hip_msg_alloc()) == NULL) {
215 free(r1);220 return NULL;
216 }221 }
217222
218 return err;223 memcpy(r1, r1_matched, len);
224
225 return r1;
219}226}
220227
221/**228/**
222 * precreate an R1 packet229 * HIPv1 & HIPv2: precreate R1 entries
223 *230 *
224 * @param r1table a pointer to R1 table structure231 * @param id_entry a pointer to host ID entry
225 * @param hit the local HIT232 * @param hit the local HIT
226 * @param sign a signing callback function233 * @param sign a signing callback function
227 * @param privkey the private key to use for signing234 * @param privkey the private key to use for signing
228 * @param pubkey the host id (public key)235 * @param pubkey the host id (public key)
229 * @param hip_version HIP message version
230 * @return zero on success and non-zero on error236 * @return zero on success and non-zero on error
231 */237 */
232int hip_precreate_r1(struct hip_r1entry *const r1table,238int hip_precreate_r1(struct local_host_id *id_entry,
233 const struct in6_addr *const hit,239 const hip_hit_t *const hit,
234 int (*sign)(void *const key, struct hip_common *const m),240 int (*sign)(void *const key, struct hip_common *const m),
235 void *const privkey,241 void *const privkey,
236 const struct hip_host_id *const pubkey,242 const struct hip_host_id *const pubkey)
237 const uint8_t hip_version)
238{243{
239 int i = 0;244 const uint8_t cookie_k = get_cookie_difficulty();
245 int i, j, group_id;
246
240 for (i = 0; i < HIP_R1TABLESIZE; i++) {247 for (i = 0; i < HIP_R1TABLESIZE; i++) {
241 int cookie_k;248 hip_msg_init(&id_entry->r1[i].buf.msg);
242249
243 cookie_k = get_cookie_difficulty();250 if (hip_create_r1(&id_entry->r1[i].buf.msg, hit, sign, privkey,
244251 pubkey, cookie_k)) {
245 hip_msg_init(&r1table[i].buf.msg);
246
247 if (hip_create_r1(&r1table[i].buf.msg, hit, sign, privkey, pubkey,
248 cookie_k, hip_version)) {
249 HIP_ERROR("Unable to precreate R1s\n");252 HIP_ERROR("Unable to precreate R1s\n");
250 return 0;253 return -1;
251 }254 }
252255 HIP_DEBUG("R1 Packet %d created\n", i);
253 HIP_DEBUG("Packet %d created\n", i);256 }
254 }257
255258 for (j = 0; j < HIP_DH_GROUP_LIST_SIZE; j++) {
256 return 1;259 group_id = HIP_DH_GROUP_LIST[j];
260 for (i = 0; i < HIP_R1TABLESIZE; i++) {
261 hip_msg_init(&id_entry->r1_v2[group_id][i].buf.msg);
262
263 if (hip_create_r1_v2(&id_entry->r1_v2[group_id][i].buf.msg, hit, sign,
264 privkey, pubkey, cookie_k, group_id)) {
265 HIP_ERROR("Unable to precreate R1_v2\n");
266 return -1;
267 }
268 HIP_DEBUG("R1_v2 Packets %d created for group: %d\n", i, group_id);
269 }
270 }
271
272 return 0;
257}273}
258274
259/**275/**
@@ -266,13 +282,17 @@
266 * @param hdr a pointer to HIP packet common header282 * @param hdr a pointer to HIP packet common header
267 * @param solution a pointer to a solution structure283 * @param solution a pointer to a solution structure
268 * @param hip_version HIP message version284 * @param hip_version HIP message version
285 * @param dh_group_id the Diffie-Hellman group ID of the R1 entry. This
286 * parameter is required for a HIPv2 cookie verification.
287 * For v1, this parameter will be ignored.
269 * @return Zero if the cookie was verified successfully, negative288 * @return Zero if the cookie was verified successfully, negative
270 * otherwise.289 * otherwise.
271 */290 */
272int hip_verify_cookie(struct in6_addr *ip_i, struct in6_addr *ip_r,291int hip_verify_cookie(struct in6_addr *ip_i, struct in6_addr *ip_r,
273 struct hip_common *hdr,292 struct hip_common *hdr,
274 const struct hip_solution *solution,293 const struct hip_solution *solution,
275 const uint8_t hip_version)294 const uint8_t hip_version,
295 const int dh_group_id)
276{296{
277 /* In a effort to conform the HIPL coding convention, the return value297 /* In a effort to conform the HIPL coding convention, the return value
278 * of this function was inverted. I.e. This function now returns298 * of this function was inverted. I.e. This function now returns
@@ -289,7 +309,12 @@
289 HIP_ANY_ALGO,309 HIP_ANY_ALGO,
290 -1)),310 -1)),
291 -1, "Requested source HIT not (any more) available.\n");311 -1, "Requested source HIT not (any more) available.\n");
292 result = &hid->r1[hip_version][calc_cookie_idx(ip_i, ip_r)];312
313 if (hip_version == HIP_V1) {
314 result = &hid->r1[calc_cookie_idx(ip_i, ip_r)];
315 } else {
316 result = &hid->r1_v2[dh_group_id][calc_cookie_idx(ip_i, ip_r)];
317 }
293318
294 puzzle = hip_get_param(&result->buf.msg, HIP_PARAM_PUZZLE);319 puzzle = hip_get_param(&result->buf.msg, HIP_PARAM_PUZZLE);
295 HIP_IFEL(!puzzle, -1, "Internal error: could not find the cookie\n");320 HIP_IFEL(!puzzle, -1, "Internal error: could not find the cookie\n");
@@ -344,7 +369,6 @@
344static int recreate_r1s_for_entry_move(struct local_host_id *entry,369static int recreate_r1s_for_entry_move(struct local_host_id *entry,
345 UNUSED void *opaque)370 UNUSED void *opaque)
346{371{
347 int i;
348 int (*signature_func)(void *const key, struct hip_common *const m);372 int (*signature_func)(void *const key, struct hip_common *const m);
349373
350 switch (hip_get_host_id_algo(&entry->host_id)) {374 switch (hip_get_host_id_algo(&entry->host_id)) {
@@ -364,11 +388,10 @@
364 return -1;388 return -1;
365 }389 }
366390
367 for (i = 1; i < HIP_MAX_VERSION; i++) {391 if (hip_precreate_r1(entry, &entry->hit, signature_func,
368 if (!hip_precreate_r1(entry->r1[i], &entry->hit, signature_func,392 entry->private_key, &entry->host_id) < 0) {
369 entry->private_key, &entry->host_id, i)) {393 HIP_ERROR("Precreate r1 failed\n");
370 return -1;394 return -1;
371 }
372 }395 }
373396
374 return 0;397 return 0;
375398
=== modified file 'libhipl/cookie.h'
--- libhipl/cookie.h 2012-06-03 10:26:55 +0000
+++ libhipl/cookie.h 2013-10-22 12:34:40 +0000
@@ -30,32 +30,23 @@
30#include <netinet/in.h>30#include <netinet/in.h>
3131
32#include "libcore/protodefs.h"32#include "libcore/protodefs.h"
3333#include "libhipl/hidb.h"
34#define HIP_R1TABLESIZE 3 /* precreate only this many R1s */
35
36struct hip_r1entry {
37 union hip_msg_bfr buf;
38 uint32_t generation;
39 uint8_t Ci[PUZZLE_LENGTH];
40 uint8_t Ck;
41 uint8_t Copaque[HIP_PUZZLE_OPAQUE_LEN];
42};
4334
44struct hip_common *hip_get_r1(struct in6_addr *ip_i,35struct hip_common *hip_get_r1(struct in6_addr *ip_i,
45 struct in6_addr *ip_r,36 struct in6_addr *ip_r,
46 struct in6_addr *peer_hit,37 struct in6_addr *our_hit,
47 uint8_t hip_version);38 const int dh_group_id);
48int hip_recreate_all_precreated_r1_packets(void);39int hip_recreate_all_precreated_r1_packets(void);
49int hip_precreate_r1(struct hip_r1entry *const r1table,40int hip_precreate_r1(struct local_host_id *id_entry,
50 const struct in6_addr *const hit,41 const hip_hit_t *const hit,
51 int (*sign)(void *const key, struct hip_common *const m),42 int (*sign)(void *const key, struct hip_common *const m),
52 void *const privkey,43 void *const privkey,
53 const struct hip_host_id *const pubkey,44 const struct hip_host_id *const pubkey);
54 const uint8_t hip_version);
55int hip_verify_cookie(struct in6_addr *ip_i, struct in6_addr *ip_r,45int hip_verify_cookie(struct in6_addr *ip_i, struct in6_addr *ip_r,
56 struct hip_common *hdr,46 struct hip_common *hdr,
57 const struct hip_solution *cookie,47 const struct hip_solution *cookie,
58 const uint8_t hip_version);48 const uint8_t hip_version,
49 const int dh_group_id);
59int hip_inc_cookie_difficulty(void);50int hip_inc_cookie_difficulty(void);
60int hip_dec_cookie_difficulty(void);51int hip_dec_cookie_difficulty(void);
61int hip_get_puzzle_difficulty_msg(struct hip_common *msg);52int hip_get_puzzle_difficulty_msg(struct hip_common *msg);
6253
=== modified file 'libhipl/dh.c'
--- libhipl/dh.c 2012-05-12 10:21:32 +0000
+++ libhipl/dh.c 2013-10-22 12:34:40 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010, 2012 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -47,6 +47,8 @@
47 */47 */
48static DH *dh_table[HIP_MAX_DH_GROUP_ID] = { 0 };48static DH *dh_table[HIP_MAX_DH_GROUP_ID] = { 0 };
4949
50static EC_KEY *ecdh_table[HIP_MAX_DH_GROUP_ID] = { 0 };
51
50/**52/**
51 * insert the current DH-key into the buffer53 * insert the current DH-key into the buffer
52 *54 *
@@ -95,66 +97,288 @@
95}97}
9698
97/**99/**
98 * create a shared secret based on the public key of the peer100 * Store the bytes of the current ECDH public key in the given buffer.
101 *
102 * A new ECDH key will be created if it doesn't exist,
103 *
104 * @param buffer buffer to store the public part of the ECDH key
105 * @param bufsize size of the @c buffer
106 * @param group_id group ID of the ECDH key
107 * @return the number of bytes written to the buffer, -1 on error.
108 */
109int hip_insert_ecdh(uint8_t *buffer, int bufsize, int group_id)
110{
111 EC_KEY *key;
112 int ret;
113
114 if (!hip_is_ecdh_group(group_id)) {
115 HIP_ERROR("Invalid group id for ECDH: %d\n", group_id);
116 return -1;
117 }
118
119 if (ecdh_table[group_id] == NULL) {
120 key = hip_generate_ecdh_key(group_id);
121 if (key == NULL) {
122 HIP_ERROR("Failed to generate an ECDH key for group: %d\n",
123 group_id);
124 return -1;
125 }
126 ecdh_table[group_id] = key;
127 }
128
129 key = ecdh_table[group_id];
130 if ((ret = hip_encode_ecdh_publickey(key, buffer, bufsize)) < 0) {
131 HIP_ERROR("Failed to encode the ECDH public key\n");
132 return -1;
133 }
134
135 return ret;
136}
137
138/**
139 * HIPv2: Store the bytes of the current ECDH/DH public key to the given buffer.
140 *
141 * An ECDH/DH key will be created if it does not exist.
142 *
143 * @param buffer the buffer to store the ECDH/DH public key
144 * @param bufsize the size of the @c buffer
145 * @param group_id the group ID of the ECDH/DH key
146 * @return the number of bytes written to the buffer
147 */
148int hip_insert_dh_v2(uint8_t *buffer, int bufsize, int group_id)
149{
150 if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) {
151 HIP_ERROR("Invalid DH_GROUP_ID: %d\n", group_id);
152 return -1;
153 }
154
155 if (hip_is_ecdh_group(group_id)) {
156 return hip_insert_ecdh(buffer, bufsize, group_id);
157 } else {
158 return hip_insert_dh(buffer, bufsize, group_id);
159 }
160}
161
162/**
163 * Match the first identical DH group ID in local and peer's list.
164 *
165 * @param dh_group_list the DH_GROUP_LIST parameter sent from the peer
166 * @param our_dh_group the local DH list
167 * @param our_group_size the size of the @c our_dh_group
168 * @return ID of the matched group on success, -1 otherwise.
169 */
170int hip_match_dh_group_list(const struct hip_tlv_common *const dh_group_list,
171 const uint8_t *const our_dh_group,
172 const int our_group_size)
173{
174 int list_size = HIP_DH_GROUP_MAX_RECV_SIZE;
175 uint8_t list[list_size];
176 int i, j;
177
178 list_size = hip_get_list_from_param(dh_group_list, list, list_size,
179 sizeof(uint8_t));
180 for (i = 0; i < list_size; i++) {
181 for (j = 0; j < our_group_size; j++) {
182 if (our_dh_group[j] == list[i]) {
183 return our_dh_group[j];
184 }
185 }
186 }
187
188 return -1;
189}
190
191/**
192 * Calculate a Diffie-Hellman shared secret based on the public key of the peer
99 * (passed as an argument) and own DH private key (created beforehand).193 * (passed as an argument) and own DH private key (created beforehand).
100 *194 *
101 * @param public_value Peer's Diffie-Hellman public key195 * @param group_id the Diffie-Hellman group ID
196 * @param public_value the Diffie-Hellman public key of the peer
197 * @param len the length of the @c public_value
198 * @param buffer the buffer that holds enough space for the shared secret
199 * @param bufsize the size of the @c buffer
200 *
201 * @return the length of the shared secret in octets if successful,
202 * or -1 if an error occurred.
203 */
204static int hip_calculate_dh_shared_secret(const uint16_t group_id,
205 const uint8_t *const public_value,
206 const int len,
207 unsigned char *const buffer,
208 const int bufsize)
209{
210 DH *key;
211 int secret_len;
212
213 if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) {
214 HIP_ERROR("Invalid Group ID: %d.\n", group_id);
215 return -1;
216 }
217
218 if (dh_table[group_id] == NULL) {
219 if (NULL == (key = hip_generate_dh_key(group_id))) {
220 HIP_ERROR("Failed to generate a DH key for group: %d\n", group_id);
221 return -1;
222 }
223 dh_table[group_id] = key;
224 }
225 key = dh_table[group_id];
226
227 secret_len = hip_gen_dh_shared_key(dh_table[group_id], public_value, len,
228 buffer, bufsize);
229 if (secret_len < 0) {
230 HIP_ERROR("failed to create a DH shared secret\n");
231 return -1;
232 }
233
234 return secret_len;
235}
236
237/**
238 * Calculate an Elliptic Curve Diffie-Hellman shared secret.
239 *
240 * The length of the public value should match the corresponding ECDH group; The
241 * buffer to hold the shared secret should be at least larger than the length of
242 * the public value divided by 2.
243 *
244 * @param group_id the ECDH group ID
245 * @param public_value Peer's ECDH public key
246 * @param pubkey_len the length of the @c public_value
247 * @param buffer Buffer that holds enough space for the shared secret
248 * @param bufsize size of the @c buffer
249 *
250 * @return the length of the shared secret in octets if successful,
251 * or -1 if an error occurred.
252 */
253static int hip_calculate_ecdh_shared_secret(const uint16_t group_id,
254 const uint8_t *const public_value,
255 const int pubkey_len,
256 unsigned char *const buffer,
257 const int bufsize)
258{
259 EC_KEY *key;
260 int key_len;
261
262 if (ecdh_table[group_id] == NULL) {
263 if (NULL == (key = hip_generate_ecdh_key(group_id))) {
264 HIP_ERROR("Failed to generate an ECDH key for group: %d\n",
265 group_id);
266 return -1;
267 }
268 ecdh_table[group_id] = key;
269 }
270 key = ecdh_table[group_id];
271
272 key_len = hip_get_dh_size(group_id);
273 if (key_len != pubkey_len || key_len / 2 > bufsize) {
274 HIP_ERROR("Invalid public key length (%d) or buffer size (%d)\n",
275 pubkey_len, bufsize);
276 return -1;
277 }
278 int out = hip_gen_ecdh_shared_key(key, public_value,
279 public_value + key_len / 2,
280 key_len / 2,
281 buffer,
282 bufsize);
283 if (out <= 0) {
284 HIP_ERROR("Failed to generate a shared secret\n");
285 return -1;
286 }
287
288 return out;
289}
290
291/**
292 * Calculate a shared secret for Diffie-Hellman exchange.
293 *
294 * This function supports both normal DH and ECDH groups. The DH private key
295 * is created beforehand.
296 *
297 * @param group_id the Diffie-Hellman group ID
298 * @param public_value the Diffie-Hellman public key of the peer
299 * @param len the length of the @c public_value
300 * @param buffer Buffer that holds the shared secret
301 * @param bufsize size of the @c buffer
302 *
303 * @return the length of the shared secret in octets if successful,
304 * or -1 if an error occurred.
305 */
306int hip_calculate_shared_secret(const uint16_t group_id,
307 const uint8_t *const public_value,
308 const int len,
309 unsigned char *const buffer,
310 const int bufsize)
311{
312 if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) {
313 HIP_ERROR("Invalid Diffie-Hellman group ID: %d\n", group_id);
314 return -1;
315 }
316
317 if (hip_is_ecdh_group(group_id)) {
318 return hip_calculate_ecdh_shared_secret(group_id, public_value, len,
319 buffer, bufsize);
320 } else {
321 return hip_calculate_dh_shared_secret(group_id, public_value, len,
322 buffer, bufsize);
323 }
324}
325
326/**
327 * Re-generate a DH key for a given group ID.
328 *
102 * @param group_id the Diffie-Hellman group ID329 * @param group_id the Diffie-Hellman group ID
103 * @param len the length of the public value330 * @return 0 on success, -1 otherwise
104 * @param buffer Buffer that holds enough space for the shared secret.331 */
105 * @param bufsize size of the buffer332static int regen_dh_key(const int group_id)
106 *
107 * @return the length of the shared secret in octets if successful,
108 * or -1 if an error occured.
109 */
110int hip_calculate_shared_secret(const uint8_t *public_value,
111 uint8_t group_id,
112 signed int len,
113 unsigned char *buffer,
114 int bufsize)
115{
116 int err = 0;
117 DH *tmp;
118
119 if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) {
120 HIP_ERROR("The Group ID %d is invalid\n", group_id);
121 return -1;
122 }
123
124 /*
125 * First check that we have the key available.
126 * Then encode it into the buffer
127 */
128
129 if (dh_table[group_id] == NULL) {
130 tmp = hip_generate_dh_key(group_id);
131 dh_table[group_id] = tmp;
132
133 if (dh_table[group_id] == NULL) {
134 HIP_ERROR("Unsupported DH group: %d\n", group_id);
135 return -1;
136 }
137 }
138
139 err = hip_gen_dh_shared_key(dh_table[group_id], public_value,
140 len, buffer, bufsize);
141 if (err < 0) {
142 HIP_ERROR("Could not create shared secret\n");
143 return -1;
144 }
145
146 return err;
147}
148
149/**
150 * regenerate Diffie-Hellman keys for HIP
151 * @param bitmask Mask of groups to generate.
152 *
153 * @note Use only this function to generate DH keys.
154 */
155static void regen_dh_keys(uint32_t bitmask)
156{333{
157 DH *tmp, *okey;334 DH *tmp, *okey;
335
336 tmp = hip_generate_dh_key(group_id);
337 if (!tmp) {
338 HIP_INFO("Failed to generate a DH key for group: %d\n", group_id);
339 return -1;
340 }
341
342 okey = dh_table[group_id];
343 dh_table[group_id] = tmp;
344
345 DH_free(okey);
346 return 0;
347}
348
349#ifdef HAVE_EC_CRYPTO
350/**
351 * Re-generate DH key for a given ECDH group ID.
352 *
353 * @param group_id the ECDH group ID
354 * @return 0 on success, -1 otherwise
355 */
356static int regen_ecdh_key(const int group_id)
357{
358 EC_KEY *tmp, *okey;
359
360 tmp = hip_generate_ecdh_key(group_id);
361 if (!tmp) {
362 HIP_INFO("Failed to generate an ECDH key for group: %d\n", group_id);
363 return -1;
364 }
365
366 okey = ecdh_table[group_id];
367 ecdh_table[group_id] = tmp;
368
369 EC_KEY_free(okey);
370 return 0;
371}
372
373#endif /* HAVE_EC_CRYPTO */
374
375/**
376 * HIPv2: regenerate Diffie-Hellman keys.
377 *
378 * @param bitmask the mask of groups to generate
379 */
380static void regen_dh_keys_v2(uint32_t bitmask)
381{
158 int maxmask, i;382 int maxmask, i;
159 int cnt = 0;383 int cnt = 0;
160384
@@ -164,19 +388,13 @@
164388
165 for (i = 1; i < HIP_MAX_DH_GROUP_ID; i++) {389 for (i = 1; i < HIP_MAX_DH_GROUP_ID; i++) {
166 if (bitmask & (1 << i)) {390 if (bitmask & (1 << i)) {
167 tmp = hip_generate_dh_key(i);391 if (hip_is_ecdh_group(i)) {
168 if (!tmp) {392 regen_ecdh_key(i);
169 HIP_INFO("Error while generating group: %d\n", i);393 } else {
170 continue;394 regen_dh_key(i);
171 }395 }
172396
173 okey = dh_table[i];
174 dh_table[i] = tmp;
175
176 DH_free(okey);
177
178 cnt++;397 cnt++;
179
180 HIP_DEBUG("DH key for group %d generated\n", i);398 HIP_DEBUG("DH key for group %d generated\n", i);
181 }399 }
182 }400 }
@@ -193,6 +411,14 @@
193 DH_free(dh_table[i]);411 DH_free(dh_table[i]);
194 dh_table[i] = NULL;412 dh_table[i] = NULL;
195 }413 }
414
415#ifdef HAVE_EC_CRYPTO
416 for (i = 1; i < HIP_MAX_DH_GROUP_ID; i++) {
417 EC_KEY_free(ecdh_table[i]);
418 ecdh_table[i] = NULL;
419 }
420#endif /* HAVE_EC_CRYPTO */
421
196 CRYPTO_cleanup_all_ex_data();422 CRYPTO_cleanup_all_ex_data();
197}423}
198424
@@ -203,12 +429,15 @@
203{429{
204 uint32_t supported_groups;430 uint32_t supported_groups;
205431
206 supported_groups = (1 << HIP_DH_OAKLEY_1 |432 supported_groups = (1 << HIP_DH_OAKLEY_1 |
207 1 << HIP_DH_OAKLEY_5 |433 1 << HIP_DH_OAKLEY_5 |
208 1 << HIP_DH_384);434 1 << HIP_DH_384 |
435 1 << HIP_DH_NIST_P_256 |
436 1 << HIP_DH_NIST_P_384 |
437 1 << HIP_DH_NIST_P_521);
209438
210 HIP_DEBUG("Generating DH keys\n");439 HIP_DEBUG("Generating DH keys\n");
211 regen_dh_keys(supported_groups);440 regen_dh_keys_v2(supported_groups);
212441
213 return 1;442 return 1;
214}443}
215444
=== modified file 'libhipl/dh.h'
--- libhipl/dh.h 2012-05-12 10:21:32 +0000
+++ libhipl/dh.h 2013-10-22 12:34:40 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010, 2012 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -28,13 +28,21 @@
2828
29#include <stdint.h>29#include <stdint.h>
3030
31#include "libcore/protodefs.h"
32
33
31int hip_insert_dh(uint8_t *buffer, int bufsize, int group_id);34int hip_insert_dh(uint8_t *buffer, int bufsize, int group_id);
32void hip_dh_uninit(void);35void hip_dh_uninit(void);
33int hip_calculate_shared_secret(const uint8_t *public_value,36int hip_calculate_shared_secret(const uint16_t group_id,
34 uint8_t group_id,37 const uint8_t *const pulic_value,
35 signed int len,38 const int len,
36 unsigned char *buffer,39 unsigned char *const buffer,
37 int bufsize);40 const int bufsize);
38int hip_init_cipher(void);41int hip_init_cipher(void);
3942
43int hip_insert_dh_v2(uint8_t *buffer, int bufsize, int group_id);
44int hip_insert_ecdh(uint8_t *buffer, int bufsize, int group_id);
45int hip_match_dh_group_list(const struct hip_tlv_common *const dh_group_list,
46 const uint8_t *our_dh_group, const int our_group_size);
47
40#endif /* HIPL_LIBHIPL_DH_H */48#endif /* HIPL_LIBHIPL_DH_H */
4149
=== modified file 'libhipl/hidb.c'
--- libhipl/hidb.c 2012-06-03 10:26:55 +0000
+++ libhipl/hidb.c 2013-10-22 12:34:40 +0000
@@ -429,7 +429,6 @@
429 hip_lsi_t *lsi,429 hip_lsi_t *lsi,
430 const struct hip_host_id_priv *host_id)430 const struct hip_host_id_priv *host_id)
431{431{
432 int i;
433 int err = 0;432 int err = 0;
434 struct local_host_id *id_entry = NULL;433 struct local_host_id *id_entry = NULL;
435 struct local_host_id *old_entry;434 struct local_host_id *old_entry;
@@ -493,16 +492,12 @@
493 err = -1;492 err = -1;
494 goto out_err;493 goto out_err;
495 }494 }
496 for (i = 1; i < HIP_MAX_VERSION; i++) {495
497 HIP_IFEL(!hip_precreate_r1(id_entry->r1[i],496 HIP_IFEL(hip_precreate_r1(id_entry, &hit, signature_func,
498 &hit,497 id_entry->private_key,
499 signature_func,498 &id_entry->host_id) < 0,
500 id_entry->private_key,499 -ENOENT,
501 &id_entry->host_id,500 "Unable to precreate R1s.\n");
502 i),
503 -ENOENT,
504 "Unable to precreate R1s.\n");
505 }
506501
507out_err:502out_err:
508 if (err && id_entry) {503 if (err && id_entry) {
509504
=== modified file 'libhipl/hidb.h'
--- libhipl/hidb.h 2012-06-03 10:26:55 +0000
+++ libhipl/hidb.h 2013-10-22 12:34:40 +0000
@@ -35,9 +35,19 @@
35#include <stdbool.h>35#include <stdbool.h>
36#include <netinet/in.h>36#include <netinet/in.h>
3737
38#include "libcore/crypto.h"
38#include "libcore/protodefs.h"39#include "libcore/protodefs.h"
39#include "cookie.h"40
4041
42#define HIP_R1TABLESIZE 3 /* precreate only this many R1s */
43
44struct hip_r1entry {
45 union hip_msg_bfr buf;
46 uint32_t generation;
47 uint8_t Ci[PUZZLE_LENGTH];
48 uint8_t Ck;
49 uint8_t Copaque[HIP_PUZZLE_OPAQUE_LEN];
50};
4151
42struct local_host_id {52struct local_host_id {
43 hip_hit_t hit;53 hip_hit_t hit;
@@ -45,7 +55,13 @@
45 hip_lsi_t lsi;55 hip_lsi_t lsi;
46 struct hip_host_id host_id;56 struct hip_host_id host_id;
47 void *private_key; /* RSA or DSA */57 void *private_key; /* RSA or DSA */
48 struct hip_r1entry r1[HIP_MAX_VERSION][HIP_R1TABLESIZE]; /* precreated R1s */58
59 /* precreated R1 entries.
60 * Due to the introduction of DH_GROUP_LIST in HIPv2, R1's DIFFIE_HELLMAN
61 * parameter must match one of the group ID of initiator's I1. Therefore we
62 * precreate R1 for all DH groups we support. */
63 struct hip_r1entry r1[HIP_R1TABLESIZE];
64 struct hip_r1entry r1_v2[HIP_MAX_DH_GROUP_ID][HIP_R1TABLESIZE];
49};65};
5066
51struct local_host_id *hip_get_hostid_entry_by_lhi_and_algo(const struct in6_addr *const hit,67struct local_host_id *hip_get_hostid_entry_by_lhi_and_algo(const struct in6_addr *const hit,
5268
=== modified file 'libhipl/input.c'
--- libhipl/input.c 2012-07-13 13:16:17 +0000
+++ libhipl/input.c 2013-10-22 12:34:40 +0000
@@ -110,6 +110,43 @@
110}110}
111111
112/**112/**
113 * HIPv2: Check potential downgrade possibility for DH group selection by
114 * matching our DH list with the peer's DH list. If the peer doesn't select
115 * the strongest group, DH downgrade occurs.
116 *
117 * @param peer_group the DH group peer has selected
118 * @param peer_param the peer's DH group list parameter
119 * @return 0 if no downgrade detected, -1 otherwise.
120 */
121static int check_dh_downgrade_v2(const uint8_t peer_group,
122 const struct hip_tlv_common *const peer_param)
123{
124 int i, j;
125 int list_size = HIP_DH_GROUP_MAX_RECV_SIZE;
126 uint8_t list[list_size];
127
128 list_size = hip_get_list_from_param(peer_param, list, list_size,
129 sizeof(list[0]));
130 for (i = 0; i < HIP_DH_GROUP_LIST_SIZE; i++) {
131 for (j = 0; j < list_size; j++) {
132 if (HIP_DH_GROUP_LIST[i] == list[j]) {
133 if (list[j] == peer_group) {
134 return 0;
135 } else {
136 HIP_ERROR("Detect DH group downgrade. "
137 "Expect group: %d, Got: %d\n",
138 list[j], peer_group);
139 return -1;
140 }
141 }
142 }
143 }
144
145 HIP_ERROR("No identical group in the DH group lists\n");
146 return -1;
147}
148
149/**
113 * Verifies gerenal HMAC in HIP msg150 * Verifies gerenal HMAC in HIP msg
114 *151 *
115 * @param msg HIP packet152 * @param msg HIP packet
@@ -325,11 +362,14 @@
325 HIP_DEBUG("Start PERF_DH_CREATE\n");362 HIP_DEBUG("Start PERF_DH_CREATE\n");
326 hip_perf_start_benchmark(perf_set, PERF_DH_CREATE);363 hip_perf_start_benchmark(perf_set, PERF_DH_CREATE);
327#endif364#endif
328 HIP_IFEL((dh_shared_len = hip_calculate_shared_secret(dhpv->public_value, dhpv->group_id,365
329 ntohs(dhpv->pub_len),366 dh_shared_len = hip_calculate_shared_secret(dhpv->group_id, dhpv->public_value,
330 (unsigned char *) dh_shared_key,367 ntohs(dhpv->pub_len),
331 dh_shared_len)) < 0,368 (unsigned char *) dh_shared_key,
332 -EINVAL, "Calculation of shared secret failed.\n");369 dh_shared_len);
370 HIP_IFEL(dh_shared_len <= 0, -EINVAL, "Calculation of shared secret failed.\n");
371 HIP_DEBUG("DH group %d, shared secret length is %d\n",
372 dhpv->group_id, dh_shared_len);
333373
334 hip_make_keymat(dh_shared_key,374 hip_make_keymat(dh_shared_key,
335 dh_shared_len,375 dh_shared_len,
@@ -763,6 +803,24 @@
763 HIP_IFE(hip_init_peer(ctx->hadb_entry, &peer_host_id),803 HIP_IFE(hip_init_peer(ctx->hadb_entry, &peer_host_id),
764 -EINVAL);804 -EINVAL);
765805
806 /* HIPv2: check possible DH group downgrade */
807 if (ctx->hadb_entry->hip_version == HIP_V2) {
808 const struct hip_tlv_common *dh_list_param;
809 const struct hip_diffie_hellman *dh_param;
810
811 dh_list_param = hip_get_param(ctx->input_msg, HIP_PARAM_DH_GROUP_LIST);
812 HIP_IFEL(dh_list_param == NULL, -ENOENT,
813 "No DH_GROUP_LIST parameter found in R1\n");
814
815 dh_param = hip_get_param(ctx->input_msg, HIP_PARAM_DIFFIE_HELLMAN);
816 HIP_IFEL(dh_param == NULL, -ENOENT,
817 "No DIFFIE_HELLMAN parameter found in R1\n");
818
819 HIP_IFEL(check_dh_downgrade_v2(dh_param->pub_val.group_id,
820 dh_list_param) < 0,
821 -EINVAL, "DH group downgrade check failed.\n");
822 }
823
766#ifdef CONFIG_HIP_PERFORMANCE824#ifdef CONFIG_HIP_PERFORMANCE
767 HIP_DEBUG("Start PERF_VERIFY\n");825 HIP_DEBUG("Start PERF_VERIFY\n");
768 hip_perf_start_benchmark(perf_set, PERF_VERIFY);826 hip_perf_start_benchmark(perf_set, PERF_VERIFY);
@@ -945,7 +1003,8 @@
945 HIP_ERROR("Failed to allocate memory for public value\n");1003 HIP_ERROR("Failed to allocate memory for public value\n");
946 return -ENOMEM;1004 return -ENOMEM;
947 }1005 }
948 if ((pub_len = hip_insert_dh(public_value, pub_len, dhpv->group_id)) < 0) {1006
1007 if ((pub_len = hip_insert_dh_v2(public_value, pub_len, dhpv->group_id)) < 0) {
949 HIP_ERROR("Could not extract the DH public key\n");1008 HIP_ERROR("Could not extract the DH public key\n");
950 return -1;1009 return -1;
951 }1010 }
@@ -1363,19 +1422,22 @@
1363 UNUSED const enum hip_state ha_state,1422 UNUSED const enum hip_state ha_state,
1364 struct hip_packet_context *ctx)1423 struct hip_packet_context *ctx)
1365{1424{
1366 int hip_version = 0;1425 int hip_version = 0;
1367 int err = 0, is_loopback = 0;1426 int err = 0, is_loopback = 0;
1368 bool skip_key_creation = false;1427 bool skip_key_creation = false;
1369 uint16_t mask = HIP_PACKET_CTRL_ANON;1428 uint16_t mask = HIP_PACKET_CTRL_ANON;
1370 uint16_t crypto_len = 0;1429 uint16_t crypto_len = 0;
1371 char *tmp_enc = NULL;1430 char *tmp_enc = NULL;
1372 const char *enc = NULL;1431 const char *enc = NULL;
1373 unsigned char *iv = NULL;1432 unsigned char *iv = NULL;
1374 const struct hip_solution *solution = NULL;1433 const struct hip_solution *solution = NULL;
1375 const struct hip_r1_counter *r1cntr = NULL;1434 const struct hip_diffie_hellman *dh_param = NULL;
1376 const struct hip_hip_transform *hip_transform = NULL;1435 const struct hip_r1_counter *r1cntr = NULL;
1377 struct hip_host_id *host_id_in_enc = NULL;1436 const struct hip_hip_transform *hip_transform = NULL;
1378 struct hip_host_id host_id;1437 struct hip_host_id *host_id_in_enc = NULL;
1438 struct hip_host_id host_id;
1439 int dh_group_id, i;
1440
1379#ifdef CONFIG_HIP_PERFORMANCE1441#ifdef CONFIG_HIP_PERFORMANCE
1380 HIP_DEBUG("Start PERF_I2\n");1442 HIP_DEBUG("Start PERF_I2\n");
1381 hip_perf_start_benchmark(perf_set, PERF_I2);1443 hip_perf_start_benchmark(perf_set, PERF_I2);
@@ -1464,11 +1526,40 @@
1464 -ENODATA,1526 -ENODATA,
1465 "SOLUTION parameter missing from I2 packet. Dropping\n");1527 "SOLUTION parameter missing from I2 packet. Dropping\n");
14661528
1467 HIP_IFEL(hip_verify_cookie(&ctx->src_addr,1529 /* Validate DIFFIE_HELLMAN parameter */
1468 &ctx->dst_addr,1530 if (NULL == (dh_param = hip_get_param(ctx->input_msg,
1469 ctx->input_msg,1531 HIP_PARAM_DIFFIE_HELLMAN))) {
1470 solution,1532 HIP_ERROR("DIFFIE_HELLMAN parameter missing from I2 packet\n");
1471 ctx->hadb_entry->hip_version),1533 ctx->error = -ENODATA;
1534 return ctx->error;
1535 }
1536 dh_group_id = dh_param->pub_val.group_id;
1537 for (i = 0; i < HIP_DH_GROUP_LIST_SIZE; i++) {
1538 if (dh_group_id == HIP_DH_GROUP_LIST[i]) {
1539 break;
1540 }
1541 }
1542 if (i == HIP_DH_GROUP_LIST_SIZE) {
1543 HIP_ERROR("Invalid group %d for DIFFIE_HELLMAN parameter.\n",
1544 dh_group_id);
1545 ctx->error = -EINVAL;
1546 return ctx->error;
1547 }
1548 if (hip_get_dh_size(dh_group_id) != ntohs(dh_param->pub_val.pub_len)) {
1549 HIP_ERROR("Invalid public key length for DIFFIE_HELLMAN parameter. "
1550 "Expect: %d, Got: %d\n", hip_get_dh_size(dh_group_id),
1551 ntohs(dh_param->pub_val.pub_len));
1552 ctx->error = -EINVAL;
1553 return ctx->error;
1554 }
1555
1556 /* Verify cookie */
1557 if (hip_version == HIP_V1) {
1558 dh_group_id = 0;
1559 }
1560 HIP_IFEL(hip_verify_cookie(&ctx->src_addr, &ctx->dst_addr,
1561 ctx->input_msg, solution,
1562 hip_version, dh_group_id),
1472 -EPROTO,1563 -EPROTO,
1473 "Cookie solution rejected. Dropping the I2 packet.\n");1564 "Cookie solution rejected. Dropping the I2 packet.\n");
14741565
14751566
=== modified file 'libhipl/netdev.c'
--- libhipl/netdev.c 2012-06-03 10:26:55 +0000
+++ libhipl/netdev.c 2013-10-22 12:34:40 +0000
@@ -987,8 +987,25 @@
987987
988 HIP_DEBUG("Using ifindex %d\n", if_index);988 HIP_DEBUG("Using ifindex %d\n", if_index);
989989
990 HIP_IFEL(hip_send_i1(&entry->hit_our, &entry->hit_peer, entry), -1,990 switch (entry->hip_version) {
991 "Sending of I1 failed\n");991 case HIP_V1:
992 if (hip_send_i1(&entry->hit_our, &entry->hit_peer, entry) < 0) {
993 HIP_ERROR("Failed to send the I1(v1) message.\n");
994 return -1;
995 }
996 break;
997
998 case HIP_V2:
999 if (hip_send_i1_v2(&entry->hit_our, &entry->hit_peer, entry) < 0) {
1000 HIP_ERROR("Failed to send the I1(v2) message.\n");
1001 return -1;
1002 }
1003 break;
1004
1005 default:
1006 HIP_ERROR("Unknown HIP version: %d\n", entry->hip_version);
1007 return -1;
1008 }
9921009
993out_err:1010out_err:
9941011
9951012
=== modified file 'libhipl/output.c'
--- libhipl/output.c 2013-08-19 18:30:29 +0000
+++ libhipl/output.c 2013-10-22 12:34:40 +0000
@@ -161,7 +161,111 @@
161}161}
162162
163/**163/**
164 * Send an I1 packet to the Responder164 * Send an I1 packet to the responder.
165 *
166 * This method checks the shotgun status and decides whether to use shotgun
167 * mode or not for I1 sending.
168 *
169 * @param i1 the I1 packet to be sent
170 * @param entry a pointer to the current host association database state.
171 * @return zero on success, or negative error value on error.
172 */
173static int send_i1_internal(struct hip_common *const i1,
174 struct hip_hadb_state *const entry)
175{
176 struct in6_addr *local_addr = NULL;
177 struct in6_addr peer_addr;
178 LHASH_NODE *item = NULL, *tmp = NULL;
179 struct hip_peer_addr_list_item *addr;
180 int err = 0, i = 0;
181
182 HIP_DEBUG("Sending I1 to the following addresses:\n");
183 print_peer_addresses_to_be_added(entry);
184
185 if (hip_shotgun_status == HIP_MSG_SHOTGUN_OFF ||
186 (entry->peer_addr_list_to_be_added == NULL)) {
187 if (hip_hadb_get_peer_addr(entry, &peer_addr)) {
188 HIP_ERROR("No preferred IP address for the peer.\n");
189 return -1;
190 }
191
192 local_addr = &entry->our_addr;
193 return send_i1_pkt(i1, local_addr, &peer_addr, entry->local_udp_port,
194 entry->peer_udp_port, entry);
195 } else {
196 HIP_DEBUG("Number of items in the peer addr list: %d ",
197 ((struct lhash_st *) entry->peer_addr_list_to_be_added)->num_items);
198 list_for_each_safe(item, tmp, entry->peer_addr_list_to_be_added, i)
199 {
200 addr = list_entry(item);
201 ipv6_addr_copy(&peer_addr, &addr->address);
202
203 err = send_i1_pkt(i1, NULL, &peer_addr, entry->local_udp_port,
204 entry->peer_udp_port, entry);
205 }
206 return err;
207 }
208}
209
210/**
211 * HIPv2: send an I1 packet to the responder.
212 *
213 * @param src_hit a pointer to the source host identity tag.
214 * @param dst_hit a pointer to the destination host identity tag.
215 * @param entry a pointer to the host association database state reserved for
216 * the peer.
217 * @return zero on success, or negative value on error.
218 */
219int hip_send_i1_v2(hip_hit_t *const src_hit, const hip_hit_t *const dst_hit,
220 struct hip_hadb_state *const entry)
221{
222 struct hip_common *i1 = NULL;
223 int err = 0;
224
225 int group_size = HIP_DH_GROUP_LIST_SIZE;
226 uint8_t dh_group[group_size];
227
228 memcpy(dh_group, HIP_DH_GROUP_LIST, group_size);
229
230 if (entry->state == HIP_STATE_ESTABLISHED) {
231 HIP_DEBUG("HIP association established, not triggering bex\n");
232 return 0;
233 }
234
235 /* Assign a local private key, public key and HIT to HA */
236 HIP_DEBUG_HIT("src_hit", src_hit);
237 HIP_DEBUG_HIT("entry->src_hit", &entry->hit_our);
238 HIP_IFEL(hip_init_us(entry, src_hit), -EINVAL,
239 "Could not assign a local host id\n");
240 HIP_DEBUG_HIT("entry->src_hit", &entry->hit_our);
241
242 if ((i1 = hip_msg_alloc()) == NULL) {
243 return -1;
244 }
245
246 hip_build_network_hdr(i1, HIP_I1, 0, &entry->hit_our,
247 dst_hit, entry->hip_version);
248
249 /* Calculate the HIP header length */
250 hip_calc_hdr_len(i1);
251
252 /* Build DH_GROUP_LIST */
253 HIP_IFEL(hip_build_param_list(i1, HIP_PARAM_DH_GROUP_LIST, dh_group,
254 group_size, sizeof(uint8_t)),
255 -1, "Failed to build param: DH_GROUP_LIST\n");
256
257 HIP_DEBUG_HIT("HIT source", &i1->hit_sender);
258 HIP_DEBUG_HIT("HIT dest", &i1->hit_receiver);
259
260 HIP_IFEL(send_i1_internal(i1, entry), -1, "send_i1_internal() failed\n");
261
262out_err:
263 free(i1);
264 return err;
265}
266
267/**
268 * HIPv1: send an I1 packet to the responder.
165 *269 *
166 * @param src_hit a pointer to source host identity tag.270 * @param src_hit a pointer to source host identity tag.
167 * @param dst_hit a pointer to destination host identity tag.271 * @param dst_hit a pointer to destination host identity tag.
@@ -172,13 +276,8 @@
172int hip_send_i1(hip_hit_t *src_hit, const hip_hit_t *dst_hit,276int hip_send_i1(hip_hit_t *src_hit, const hip_hit_t *dst_hit,
173 struct hip_hadb_state *entry)277 struct hip_hadb_state *entry)
174{278{
175 struct hip_common *i1 = 0;279 struct hip_common *i1 = 0;
176 uint16_t mask = 0;280 int err = 0;
177 int err = 0, i = 0;
178 LHASH_NODE *item = NULL, *tmp = NULL;
179 struct hip_peer_addr_list_item *addr;
180 struct in6_addr *local_addr = NULL;
181 struct in6_addr peer_addr;
182281
183#ifdef CONFIG_HIP_PERFORMANCE282#ifdef CONFIG_HIP_PERFORMANCE
184 HIP_DEBUG("Start PERF_I1_SEND, PERF_BASE\n");283 HIP_DEBUG("Start PERF_I1_SEND, PERF_BASE\n");
@@ -209,7 +308,7 @@
209308
210 i1 = hip_msg_alloc();309 i1 = hip_msg_alloc();
211310
212 hip_build_network_hdr(i1, HIP_I1, mask, &entry->hit_our,311 hip_build_network_hdr(i1, HIP_I1, 0, &entry->hit_our,
213 dst_hit, entry->hip_version);312 dst_hit, entry->hip_version);
214313
215 /* Calculate the HIP header length */314 /* Calculate the HIP header length */
@@ -218,30 +317,8 @@
218 HIP_DEBUG_HIT("HIT source", &i1->hit_sender);317 HIP_DEBUG_HIT("HIT source", &i1->hit_sender);
219 HIP_DEBUG_HIT("HIT dest", &i1->hit_receiver);318 HIP_DEBUG_HIT("HIT dest", &i1->hit_receiver);
220319
221 HIP_DEBUG("Sending I1 to the following addresses:\n");320 HIP_IFEL(send_i1_internal(i1, entry), -1, "send_i1_internal() failed\n");
222 print_peer_addresses_to_be_added(entry);321
223
224 if (hip_shotgun_status == HIP_MSG_SHOTGUN_OFF ||
225 (entry->peer_addr_list_to_be_added == NULL)) {
226 HIP_IFEL(hip_hadb_get_peer_addr(entry, &peer_addr), -1,
227 "No preferred IP address for the peer.\n");
228
229 local_addr = &entry->our_addr;
230 err = send_i1_pkt(i1, local_addr, &peer_addr,
231 entry->local_udp_port,
232 entry->peer_udp_port, entry);
233 } else {
234 HIP_DEBUG("Number of items in the peer addr list: %d ",
235 ((struct lhash_st *) entry->peer_addr_list_to_be_added)->num_items);
236 list_for_each_safe(item, tmp, entry->peer_addr_list_to_be_added, i)
237 {
238 addr = list_entry(item);
239 ipv6_addr_copy(&peer_addr, &addr->address);
240
241 err = send_i1_pkt(i1, NULL, &peer_addr, entry->local_udp_port,
242 entry->peer_udp_port, entry);
243 }
244 }
245#ifdef CONFIG_HIP_PERFORMANCE322#ifdef CONFIG_HIP_PERFORMANCE
246 HIP_DEBUG("Stop and write PERF_I1_SEND\n");323 HIP_DEBUG("Stop and write PERF_I1_SEND\n");
247 hip_perf_stop_benchmark(perf_set, PERF_I1_SEND);324 hip_perf_stop_benchmark(perf_set, PERF_I1_SEND);
@@ -263,8 +340,8 @@
263 */340 */
264static int add_echo_response(struct hip_packet_context *ctx, int sign)341static int add_echo_response(struct hip_packet_context *ctx, int sign)
265{342{
266 int param_type = sign ? HIP_PARAM_ECHO_REQUEST_SIGN343 int param_type =
267 : HIP_PARAM_ECHO_REQUEST;344 sign ? HIP_PARAM_ECHO_REQUEST_SIGN : HIP_PARAM_ECHO_REQUEST;
268345
269 const struct hip_echo_msg *ping = hip_get_param(ctx->input_msg, param_type);346 const struct hip_echo_msg *ping = hip_get_param(ctx->input_msg, param_type);
270347
@@ -595,38 +672,25 @@
595}672}
596673
597/**674/**
598 * Construct a new R1 packet payload675 * Continue to build R1 packet after the Diffie-Hellman parameter.
599 *676 *
600 * @param msg points to a message object backed by HIP_MAX_PACKET bytes677 * @param msg pointer to a message backed by HIP_MAX_PACKET bytes of
601 * of memory to which the R1 message is written.678 * memory to which the R1 message is written.
602 * @param src_hit a pointer to the source host identity tag used in the
603 * packet.
604 * @param sign a funtion pointer to a signature funtion.679 * @param sign a funtion pointer to a signature funtion.
605 * @param private_key a pointer to the local host private key680 * @param private_key a pointer to the local host private key
606 * @param host_id_pub a pointer to the public host id of the local host681 * @param host_id_pub a pointer to the public host id of the local host
607 * @param cookie_k the difficulty value for the puzzle
608 * @param hip_version HIP message version
609 * @return 0 on success, a non-zero value on error.682 * @return 0 on success, a non-zero value on error.
610 */683 */
611int hip_create_r1(struct hip_common *const msg,684static int build_r1_after_dh_param(struct hip_common *const msg,
612 const struct in6_addr *const src_hit,685 int (*sign)(void *const key, struct hip_common *const m),
613 int (*sign)(void *const key, struct hip_common *const m),686 void *const private_key,
614 void *const private_key,687 const struct hip_host_id *const host_id_pub)
615 const struct hip_host_id *const host_id_pub,
616 const int cookie_k,
617 const uint8_t hip_version)
618{688{
619 int err = 0;
620 struct hip_srv service_list[HIP_TOTAL_EXISTING_SERVICES];689 struct hip_srv service_list[HIP_TOTAL_EXISTING_SERVICES];
621 uint8_t *dh_data1 = NULL, *dh_data2 = NULL;690 unsigned int service_count = 0;
691 int err = 0;
622 char order[] = "000";692 char order[] = "000";
623 int dh_size1 = 0, dh_size2 = 0;693 int i = 0;
624 int mask = 0, i = 0, written1 = 0, written2 = 0;
625 unsigned int service_count = 0;
626
627 enum number_dh_keys_t { ONE, TWO };
628 enum number_dh_keys_t number_dh_keys = TWO;
629
630694
631 /* Supported HIP and ESP transforms. */695 /* Supported HIP and ESP transforms. */
632 hip_transform_suite transform_hip_suite[] = {696 hip_transform_suite transform_hip_suite[] = {
@@ -662,6 +726,102 @@
662 }726 }
663 }727 }
664728
729 /* Parameter HIP transform. */
730 err = hip_build_param_hip_transform(msg,
731 transform_hip_suite,
732 sizeof(transform_hip_suite) /
733 sizeof(hip_transform_suite));
734 if (err) {
735 HIP_ERROR("Building of HIP transform failed\n");
736 return err;
737 }
738
739 /* Parameter HOST_ID */
740 if ((err = hip_build_param_host_id(msg, host_id_pub))) {
741 HIP_ERROR("Building of host id failed\n");
742 return err;
743 }
744
745 /* Parameter REG_INFO */
746 hip_get_active_services(service_list, &service_count);
747 HIP_DEBUG("Found %d active service(s) \n", service_count);
748 hip_build_param_reg_info(msg, service_list, service_count);
749
750 /* Parameter ESP-ENC transform. */
751 err = hip_build_param_esp_transform(msg, transform_esp_suite,
752 sizeof(transform_esp_suite) /
753 sizeof(hip_transform_suite));
754 if (err) {
755 HIP_ERROR("Building of ESP transform failed\n");
756 return err;
757 }
758
759 /********** ESP-PROT transform (OPTIONAL) **********/
760
761 if ((err = esp_prot_r1_add_transforms(msg))) {
762 HIP_ERROR("failed to add optional esp transform parameter\n");
763 return err;
764 }
765
766 /********** ECHO_REQUEST_SIGN (OPTIONAL) *********/
767
768 //HIP_HEXDUMP("Pubkey:", host_id_pub, hip_get_param_total_len(host_id_pub));
769
770 /* Parameter Signature 2 */
771
772 if ((err = sign(private_key, msg))) {
773 HIP_ERROR("Signing of R1 failed.\n");
774 return err;
775 }
776
777 /* Parameter ECHO_REQUEST (OPTIONAL) */
778
779 /* Fill puzzle parameters */
780 {
781 struct hip_puzzle *pz;
782
783 if (!(pz = hip_get_param_readwrite(msg, HIP_PARAM_PUZZLE))) {
784 HIP_ERROR("Internal error\n");
785 return -1;
786 }
787
788 /* hardcode kludge */
789 pz->opaque[0] = 'H';
790 pz->opaque[1] = 'I';
791 get_random_bytes(pz->I, PUZZLE_LENGTH);
792 }
793
794 return 0;
795}
796
797/**
798 * Construct a new R1 packet payload
799 *
800 * @param msg pointer to a message backed by HIP_MAX_PACKET bytes of
801 * memory to which the R1 message is written.
802 * @param src_hit a pointer to the source host identity tag used in the
803 * packet.
804 * @param sign a funtion pointer to a signature funtion.
805 * @param private_key a pointer to the local host private key
806 * @param host_id_pub a pointer to the public host id of the local host
807 * @param cookie_k the difficulty value for the puzzle
808 * @return 0 on success, a non-zero value on error.
809 */
810int hip_create_r1(struct hip_common *const msg,
811 const struct in6_addr *const src_hit,
812 int (*sign)(void *const key, struct hip_common *const m),
813 void *const private_key,
814 const struct hip_host_id *const host_id_pub,
815 const int cookie_k)
816{
817 int err = 0;
818 uint8_t *dh_data1 = NULL, *dh_data2 = NULL;
819 int dh_size1 = 0, dh_size2 = 0;
820 int mask = 0, written1 = 0, written2 = 0;
821
822 enum number_dh_keys_t { ONE, TWO };
823 enum number_dh_keys_t number_dh_keys = TWO;
824
665 /* Initialize the message buffer as the message builder depends on it. */825 /* Initialize the message buffer as the message builder depends on it. */
666 hip_msg_init(msg);826 hip_msg_init(msg);
667827
@@ -682,7 +842,7 @@
682 /** @todo TH: hip_build_network_hdr has to be replaced with an842 /** @todo TH: hip_build_network_hdr has to be replaced with an
683 * appropriate function pointer */843 * appropriate function pointer */
684 HIP_DEBUG_HIT("src_hit used to build r1 network header", src_hit);844 HIP_DEBUG_HIT("src_hit used to build r1 network header", src_hit);
685 hip_build_network_hdr(msg, HIP_R1, mask, src_hit, NULL, hip_version);845 hip_build_network_hdr(msg, HIP_R1, mask, src_hit, NULL, HIP_V1);
686846
687 /********** R1_COUNTER (OPTIONAL) *********/847 /********** R1_COUNTER (OPTIONAL) *********/
688848
@@ -714,58 +874,9 @@
714 err, "Building of DH failed.\n");874 err, "Building of DH failed.\n");
715 }875 }
716876
717 /* Parameter HIP transform. */877 if ((err = build_r1_after_dh_param(msg, sign, private_key, host_id_pub)) != 0) {
718 HIP_IFEL((err = hip_build_param_hip_transform(msg,878 HIP_ERROR("Failed to build R1 after the DH parameter.");
719 transform_hip_suite,
720 sizeof(transform_hip_suite) /
721 sizeof(hip_transform_suite))),
722 err, "Building of HIP transform failed\n");
723
724 /* Parameter HOST_ID */
725 HIP_IFEL((err = hip_build_param_host_id(msg, host_id_pub)),
726 err, "Building of host id failed\n");
727
728 /* Parameter REG_INFO */
729 hip_get_active_services(service_list, &service_count);
730 HIP_DEBUG("Found %d active service(s) \n", service_count);
731 hip_build_param_reg_info(msg, service_list, service_count);
732
733 /* Parameter ESP-ENC transform. */
734 HIP_IFEL((err = hip_build_param_esp_transform(msg,
735 transform_esp_suite,
736 sizeof(transform_esp_suite) /
737 sizeof(hip_transform_suite))),
738 err, "Building of ESP transform failed\n");
739
740 /********** ESP-PROT transform (OPTIONAL) **********/
741
742 HIP_IFEL((err = esp_prot_r1_add_transforms(msg)), err,
743 "failed to add optional esp transform parameter\n");
744
745 /********** ECHO_REQUEST_SIGN (OPTIONAL) *********/
746
747 //HIP_HEXDUMP("Pubkey:", host_id_pub, hip_get_param_total_len(host_id_pub));
748
749 /* Parameter Signature 2 */
750
751 HIP_IFEL((err = sign(private_key, msg)), err, "Signing of R1 failed.\n");
752
753 /* Parameter ECHO_REQUEST (OPTIONAL) */
754
755 /* Fill puzzle parameters */
756 {
757 struct hip_puzzle *pz;
758
759 HIP_IFEL(!(pz = hip_get_param_readwrite(msg, HIP_PARAM_PUZZLE)), -1,
760 "Internal error\n");
761
762 /* hardcode kludge */
763 pz->opaque[0] = 'H';
764 pz->opaque[1] = 'I';
765 //pz->opaque[2] = 'P';
766 get_random_bytes(pz->I, PUZZLE_LENGTH);
767 }879 }
768
769 /* Packet ready */880 /* Packet ready */
770881
771out_err:882out_err:
@@ -776,6 +887,86 @@
776}887}
777888
778/**889/**
890 * Construct a new R1 packet payload.
891 *
892 * @param msg pointer to a message backed by HIP_MAX_PACKET bytes
893 * of memory to which the R1 message is written
894 * @param src_hit a pointer to the source HIT used in the packet
895 * @param sign a function pointer to a signature function
896 * @param private_key a pointer to the local host private key
897 * @param host_id_pub a pointer to the public host id of the local host
898 * @param cookie_k the difficulty value for the puzzle
899 * @param dh_group_id the Diffie-Hellman group ID which will be used by this
900 * new R1 entry
901 * @return 0 on success, a non-zero value on error
902 */
903int hip_create_r1_v2(struct hip_common *const msg,
904 const struct in6_addr *const src_hit,
905 int (*sign)(void *const key, struct hip_common *const m),
906 void *const private_key,
907 const struct hip_host_id *const host_id_pub,
908 const int cookie_k,
909 const int dh_group_id)
910{
911 int err = 0;
912 uint8_t *dh_data = NULL;
913 int dh_size = 0;
914 int mask = 0, written = 0;
915
916 /* Initialize the message buffer as the message builder depends on it. */
917 hip_msg_init(msg);
918
919 /* Allocate memory for writing the Diffie-Hellman public value */
920 if ((dh_size = hip_get_dh_size(dh_group_id)) == 0) {
921 HIP_ERROR("Could not get dh_size\n");
922 return -1;
923 }
924 if ((dh_data = calloc(1, dh_size)) == NULL) {
925 HIP_ERROR("Failed to allocate memory for dh_data\n");
926 return -1;
927 }
928
929 /* Ready to begin building of the R1 packet */
930 HIP_DEBUG_HIT("src_hit used to build r1 network header", src_hit);
931 hip_build_network_hdr(msg, HIP_R1, mask, src_hit, NULL, HIP_V2);
932
933 /********** R1_COUNTER (OPTIONAL) *********/
934
935 /********** Parameter PUZZLE ************/
936 const uint8_t zero_i[PUZZLE_LENGTH] = { 0 };
937 //2^(42-32) sec lifetime
938 err = hip_build_param_puzzle(msg, cookie_k, 42, 0, zero_i);
939 HIP_IFEL(err, err, "Cookies were burned. Bummer!\n");
940
941 /* Parameter DH_GROUP_LIST */
942 uint8_t dh_group[HIP_DH_GROUP_LIST_SIZE];
943 memcpy(dh_group, HIP_DH_GROUP_LIST, HIP_DH_GROUP_LIST_SIZE);
944 HIP_IFEL(hip_build_param_list(msg, HIP_PARAM_DH_GROUP_LIST, dh_group,
945 HIP_DH_GROUP_LIST_SIZE, sizeof(uint8_t)),
946 -1, "Failed to build param DH_GROUP_LIST.\n");
947
948 /******** Parameter DIFFIE_HELLMAN ********/
949 HIP_IFEL((written = hip_insert_dh_v2(dh_data, dh_size, dh_group_id)) < 0,
950 written, "Could not extract DH public key\n");
951
952 HIP_IFEL((err = hip_build_param_diffie_hellman_contents(msg, dh_group_id,
953 dh_data, written,
954 HIP_MAX_DH_GROUP_ID,
955 NULL, 0)),
956 err, "Building of DH failed.\n");
957
958 if ((err = build_r1_after_dh_param(msg, sign, private_key, host_id_pub)) != 0) {
959 HIP_ERROR("Failed to build R1 after the DH parameter.");
960 }
961 /* Packet ready */
962
963out_err:
964 free(dh_data);
965
966 return err;
967}
968
969/**
779 * Transmit an R1 packet to the network.970 * Transmit an R1 packet to the network.
780 *971 *
781 * Send an R1 packet to the peer and store the cookie information that was972 * Send an R1 packet to the peer and store the cookie information that was
@@ -866,10 +1057,29 @@
866 }1057 }
867 }1058 }
8681059
869 HIP_IFEL(!(r1pkt = hip_get_r1(r1_dst_addr, &ctx->dst_addr,1060 if (hip_get_msg_version(ctx->input_msg) == HIP_V1) {
870 &ctx->input_msg->hit_receiver,1061 HIP_IFEL(!(r1pkt = hip_get_r1(r1_dst_addr, &ctx->dst_addr,
871 hip_get_msg_version(ctx->input_msg))),1062 &ctx->input_msg->hit_receiver, -1)),
872 -ENOENT, "No precreated R1\n");1063 -ENOENT, "No precreated R1\n");
1064 } else {
1065 const struct hip_tlv_common *dh_group_list;
1066 int selected_group;
1067
1068 dh_group_list = hip_get_param(ctx->input_msg, HIP_PARAM_DH_GROUP_LIST);
1069 HIP_IFEL(dh_group_list == NULL, -1, "No DH_GROUP_LIST parameter in r1\n");
1070
1071 selected_group = hip_match_dh_group_list(dh_group_list,
1072 HIP_DH_GROUP_LIST,
1073 HIP_DH_GROUP_LIST_SIZE);
1074 HIP_IFEL(selected_group == -1, -1,
1075 "Cannot find a matchness for DH_GROUP_LIST\n");
1076 HIP_DEBUG("Selected DH group: %d\n", selected_group);
1077
1078 r1pkt = hip_get_r1(r1_dst_addr, &ctx->dst_addr,
1079 &ctx->input_msg->hit_receiver, selected_group);
1080 HIP_IFEL(r1pkt == NULL, -ENOENT, "No precreated R1_v2 for group: %d\n",
1081 selected_group);
1082 }
8731083
874 if (&ctx->input_msg->hit_sender) {1084 if (&ctx->input_msg->hit_sender) {
875 ipv6_addr_copy(&r1pkt->hit_receiver, &ctx->input_msg->hit_sender);1085 ipv6_addr_copy(&r1pkt->hit_receiver, &ctx->input_msg->hit_sender);
8761086
=== modified file 'libhipl/output.h'
--- libhipl/output.h 2012-06-03 10:26:55 +0000
+++ libhipl/output.h 2013-10-22 12:34:40 +0000
@@ -52,8 +52,15 @@
52 int (*sign)(void *const key, struct hip_common *const m),52 int (*sign)(void *const key, struct hip_common *const m),
53 void *const private_key,53 void *const private_key,
54 const struct hip_host_id *const host_id_pub,54 const struct hip_host_id *const host_id_pub,
55 const int cookie_k,55 const int cookie_k);
56 const uint8_t hip_version);56
57int hip_create_r1_v2(struct hip_common *const msg,
58 const struct in6_addr *const src_hit,
59 int (*sign)(void *const key, struct hip_common *const m),
60 void *const private_key,
61 const struct hip_host_id *const host_id_pub,
62 const int cookie_k,
63 const int dh_group_id);
5764
58int hip_send_r1(const uint8_t packet_type,65int hip_send_r1(const uint8_t packet_type,
59 const enum hip_state ha_state,66 const enum hip_state ha_state,
@@ -81,6 +88,9 @@
8188
82int hip_send_i1(hip_hit_t *, const hip_hit_t *, struct hip_hadb_state *);89int hip_send_i1(hip_hit_t *, const hip_hit_t *, struct hip_hadb_state *);
8390
91int hip_send_i1_v2(hip_hit_t *const src_hit, const hip_hit_t *const dst_hit,
92 struct hip_hadb_state *const entry);
93
84int hip_add_signed_echo_response(const uint8_t packet_type,94int hip_add_signed_echo_response(const uint8_t packet_type,
85 const enum hip_state ha_state,95 const enum hip_state ha_state,
86 struct hip_packet_context *ctx);96 struct hip_packet_context *ctx);
8797
=== modified file 'test/libcore/crypto.c'
--- test/libcore/crypto.c 2012-05-12 06:54:33 +0000
+++ test/libcore/crypto.c 2013-10-22 12:34:40 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2011 Aalto University and RWTH Aachen University.2 * Copyright (c) 2011-2012 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -28,12 +28,225 @@
28#include <string.h>28#include <string.h>
29#include <stdio.h>29#include <stdio.h>
30#include <unistd.h>30#include <unistd.h>
31#ifdef HAVE_EC_CRYPTO
32#include <openssl/ecdh.h>
33#endif
3134
32#include "libcore/crypto.h"35#include "libcore/crypto.h"
33#include "config.h"36#include "config.h"
34#include "test_suites.h"37#include "test_suites.h"
3538
36#ifdef HAVE_EC_CRYPTO39#ifdef HAVE_EC_CRYPTO
40
41static const int TEST_ECDH_PRIV_A = 0;
42static const int TEST_ECDH_PUBX_A = 1;
43static const int TEST_ECDH_PUBY_A = 2;
44static const int TEST_ECDH_PRIV_B = 3;
45static const int TEST_ECDH_PUBX_B = 4;
46static const int TEST_ECDH_PUBY_B = 5;
47static const int TEST_ECDH_SHARED = 6;
48
49/* An example for testing from RFC5903, section 8.1 */
50static unsigned char TEST_ECDH_NIST_P_256[] = {
51 0xC8, 0x8F, 0x01, 0xF5, 0x10, 0xD9, 0xAC, 0x3F, 0x70, 0xA2,
52 0x92, 0xDA, 0xA2, 0x31, 0x6D, 0xE5, 0x44, 0xE9, 0xAA, 0xB8,
53 0xAF, 0xE8, 0x40, 0x49, 0xC6, 0x2A, 0x9C, 0x57, 0x86, 0x2D,
54 0x14, 0x33,
55
56 0xDA, 0xD0, 0xB6, 0x53, 0x94, 0x22, 0x1C, 0xF9, 0xB0, 0x51,
57 0xE1, 0xFE, 0xCA, 0x57, 0x87, 0xD0, 0x98, 0xDF, 0xE6, 0x37,
58 0xFC, 0x90, 0xB9, 0xEF, 0x94, 0x5D, 0x0C, 0x37, 0x72, 0x58,
59 0x11, 0x80,
60
61 0x52, 0x71, 0xA0, 0x46, 0x1C, 0xDB, 0x82, 0x52, 0xD6, 0x1F,
62 0x1C, 0x45, 0x6F, 0xA3, 0xE5, 0x9A, 0xB1, 0xF4, 0x5B, 0x33,
63 0xAC, 0xCF, 0x5F, 0x58, 0x38, 0x9E, 0x05, 0x77, 0xB8, 0x99,
64 0x0B, 0xB3,
65
66 0xC6, 0xEF, 0x9C, 0x5D, 0x78, 0xAE, 0x01, 0x2A, 0x01, 0x11,
67 0x64, 0xAC, 0xB3, 0x97, 0xCE, 0x20, 0x88, 0x68, 0x5D, 0x8F,
68 0x06, 0xBF, 0x9B, 0xE0, 0xB2, 0x83, 0xAB, 0x46, 0x47, 0x6B,
69 0xEE, 0x53,
70
71 0xD1, 0x2D, 0xFB, 0x52, 0x89, 0xC8, 0xD4, 0xF8, 0x12, 0x08,
72 0xB7, 0x02, 0x70, 0x39, 0x8C, 0x34, 0x22, 0x96, 0x97, 0x0A,
73 0x0B, 0xCC, 0xB7, 0x4C, 0x73, 0x6F, 0xC7, 0x55, 0x44, 0x94,
74 0xBF, 0x63,
75
76 0x56, 0xFB, 0xF3, 0xCA, 0x36, 0x6C, 0xC2, 0x3E, 0x81, 0x57,
77 0x85, 0x4C, 0x13, 0xC5, 0x8D, 0x6A, 0xAC, 0x23, 0xF0, 0x46,
78 0xAD, 0xA3, 0x0F, 0x83, 0x53, 0xE7, 0x4F, 0x33, 0x03, 0x98,
79 0x72, 0xAB,
80
81 0xD6, 0x84, 0x0F, 0x6B, 0x42, 0xF6, 0xED, 0xAF, 0xD1, 0x31,
82 0x16, 0xE0, 0xE1, 0x25, 0x65, 0x20, 0x2F, 0xEF, 0x8E, 0x9E,
83 0xCE, 0x7D, 0xCE, 0x03, 0x81, 0x24, 0x64, 0xD0, 0x4B, 0x94,
84 0x42, 0xDE,
85};
86
87/* An example for testing from RFC5903, section 8.2 */
88static unsigned char TEST_ECDH_NIST_P_384[] = {
89 0x09, 0x9F, 0x3C, 0x70, 0x34, 0xD4, 0xA2, 0xC6, 0x99, 0x88,
90 0x4D, 0x73, 0xA3, 0x75, 0xA6, 0x7F, 0x76, 0x24, 0xEF, 0x7C,
91 0x6B, 0x3C, 0x0F, 0x16, 0x06, 0x47, 0xB6, 0x74, 0x14, 0xDC,
92 0xE6, 0x55, 0xE3, 0x5B, 0x53, 0x80, 0x41, 0xE6, 0x49, 0xEE,
93 0x3F, 0xAE, 0xF8, 0x96, 0x78, 0x3A, 0xB1, 0x94,
94
95 0x66, 0x78, 0x42, 0xD7, 0xD1, 0x80, 0xAC, 0x2C, 0xDE, 0x6F,
96 0x74, 0xF3, 0x75, 0x51, 0xF5, 0x57, 0x55, 0xC7, 0x64, 0x5C,
97 0x20, 0xEF, 0x73, 0xE3, 0x16, 0x34, 0xFE, 0x72, 0xB4, 0xC5,
98 0x5E, 0xE6, 0xDE, 0x3A, 0xC8, 0x08, 0xAC, 0xB4, 0xBD, 0xB4,
99 0xC8, 0x87, 0x32, 0xAE, 0xE9, 0x5F, 0x41, 0xAA,
100
101 0x94, 0x82, 0xED, 0x1F, 0xC0, 0xEE, 0xB9, 0xCA, 0xFC, 0x49,
102 0x84, 0x62, 0x5C, 0xCF, 0xC2, 0x3F, 0x65, 0x03, 0x21, 0x49,
103 0xE0, 0xE1, 0x44, 0xAD, 0xA0, 0x24, 0x18, 0x15, 0x35, 0xA0,
104 0xF3, 0x8E, 0xEB, 0x9F, 0xCF, 0xF3, 0xC2, 0xC9, 0x47, 0xDA,
105 0xE6, 0x9B, 0x4C, 0x63, 0x45, 0x73, 0xA8, 0x1C,
106
107 0x41, 0xCB, 0x07, 0x79, 0xB4, 0xBD, 0xB8, 0x5D, 0x47, 0x84,
108 0x67, 0x25, 0xFB, 0xEC, 0x3C, 0x94, 0x30, 0xFA, 0xB4, 0x6C,
109 0xC8, 0xDC, 0x50, 0x60, 0x85, 0x5C, 0xC9, 0xBD, 0xA0, 0xAA,
110 0x29, 0x42, 0xE0, 0x30, 0x83, 0x12, 0x91, 0x6B, 0x8E, 0xD2,
111 0x96, 0x0E, 0x4B, 0xD5, 0x5A, 0x74, 0x48, 0xFC,
112
113 0xE5, 0x58, 0xDB, 0xEF, 0x53, 0xEE, 0xCD, 0xE3, 0xD3, 0xFC,
114 0xCF, 0xC1, 0xAE, 0xA0, 0x8A, 0x89, 0xA9, 0x87, 0x47, 0x5D,
115 0x12, 0xFD, 0x95, 0x0D, 0x83, 0xCF, 0xA4, 0x17, 0x32, 0xBC,
116 0x50, 0x9D, 0x0D, 0x1A, 0xC4, 0x3A, 0x03, 0x36, 0xDE, 0xF9,
117 0x6F, 0xDA, 0x41, 0xD0, 0x77, 0x4A, 0x35, 0x71,
118
119 0xDC, 0xFB, 0xEC, 0x7A, 0xAC, 0xF3, 0x19, 0x64, 0x72, 0x16,
120 0x9E, 0x83, 0x84, 0x30, 0x36, 0x7F, 0x66, 0xEE, 0xBE, 0x3C,
121 0x6E, 0x70, 0xC4, 0x16, 0xDD, 0x5F, 0x0C, 0x68, 0x75, 0x9D,
122 0xD1, 0xFF, 0xF8, 0x3F, 0xA4, 0x01, 0x42, 0x20, 0x9D, 0xFF,
123 0x5E, 0xAA, 0xD9, 0x6D, 0xB9, 0xE6, 0x38, 0x6C,
124
125 0x11, 0x18, 0x73, 0x31, 0xC2, 0x79, 0x96, 0x2D, 0x93, 0xD6,
126 0x04, 0x24, 0x3F, 0xD5, 0x92, 0xCB, 0x9D, 0x0A, 0x92, 0x6F,
127 0x42, 0x2E, 0x47, 0x18, 0x75, 0x21, 0x28, 0x7E, 0x71, 0x56,
128 0xC5, 0xC4, 0xD6, 0x03, 0x13, 0x55, 0x69, 0xB9, 0xE9, 0xD0,
129 0x9C, 0xF5, 0xD4, 0xA2, 0x70, 0xF5, 0x97, 0x46
130};
131
132/* An example for testing from RFC5903, section 8.3 */
133static unsigned char TEST_ECDH_NIST_P_521[] = {
134 0x00, 0x37, 0xAD, 0xE9, 0x31, 0x9A, 0x89, 0xF4, 0xDA, 0xBD,
135 0xB3, 0xEF, 0x41, 0x1A, 0xAC, 0xCC, 0xA5, 0x12, 0x3C, 0x61,
136 0xAC, 0xAB, 0x57, 0xB5, 0x39, 0x3D, 0xCE, 0x47, 0x60, 0x81,
137 0x72, 0xA0, 0x95, 0xAA, 0x85, 0xA3, 0x0F, 0xE1, 0xC2, 0x95,
138 0x2C, 0x67, 0x71, 0xD9, 0x37, 0xBA, 0x97, 0x77, 0xF5, 0x95,
139 0x7B, 0x26, 0x39, 0xBA, 0xB0, 0x72, 0x46, 0x2F, 0x68, 0xC2,
140 0x7A, 0x57, 0x38, 0x2D, 0x4A, 0x52,
141
142 0x00, 0x15, 0x41, 0x7E, 0x84, 0xDB, 0xF2, 0x8C, 0x0A, 0xD3,
143 0xC2, 0x78, 0x71, 0x33, 0x49, 0xDC, 0x7D, 0xF1, 0x53, 0xC8,
144 0x97, 0xA1, 0x89, 0x1B, 0xD9, 0x8B, 0xAB, 0x43, 0x57, 0xC9,
145 0xEC, 0xBE, 0xE1, 0xE3, 0xBF, 0x42, 0xE0, 0x0B, 0x8E, 0x38,
146 0x0A, 0xEA, 0xE5, 0x7C, 0x2D, 0x10, 0x75, 0x64, 0x94, 0x18,
147 0x85, 0x94, 0x2A, 0xF5, 0xA7, 0xF4, 0x60, 0x17, 0x23, 0xC4,
148 0x19, 0x5D, 0x17, 0x6C, 0xED, 0x3E,
149
150 0x01, 0x7C, 0xAE, 0x20, 0xB6, 0x64, 0x1D, 0x2E, 0xEB, 0x69,
151 0x57, 0x86, 0xD8, 0xC9, 0x46, 0x14, 0x62, 0x39, 0xD0, 0x99,
152 0xE1, 0x8E, 0x1D, 0x5A, 0x51, 0x4C, 0x73, 0x9D, 0x7C, 0xB4,
153 0xA1, 0x0A, 0xD8, 0xA7, 0x88, 0x01, 0x5A, 0xC4, 0x05, 0xD7,
154 0x79, 0x9D, 0xC7, 0x5E, 0x7B, 0x7D, 0x5B, 0x6C, 0xF2, 0x26,
155 0x1A, 0x6A, 0x7F, 0x15, 0x07, 0x43, 0x8B, 0xF0, 0x1B, 0xEB,
156 0x6C, 0xA3, 0x92, 0x6F, 0x95, 0x82,
157
158 0x01, 0x45, 0xBA, 0x99, 0xA8, 0x47, 0xAF, 0x43, 0x79, 0x3F,
159 0xDD, 0x0E, 0x87, 0x2E, 0x7C, 0xDF, 0xA1, 0x6B, 0xE3, 0x0F,
160 0xDC, 0x78, 0x0F, 0x97, 0xBC, 0xCC, 0x3F, 0x07, 0x83, 0x80,
161 0x20, 0x1E, 0x9C, 0x67, 0x7D, 0x60, 0x0B, 0x34, 0x37, 0x57,
162 0xA3, 0xBD, 0xBF, 0x2A, 0x31, 0x63, 0xE4, 0xC2, 0xF8, 0x69,
163 0xCC, 0xA7, 0x45, 0x8A, 0xA4, 0xA4, 0xEF, 0xFC, 0x31, 0x1F,
164 0x5C, 0xB1, 0x51, 0x68, 0x5E, 0xB9,
165
166 0x00, 0xD0, 0xB3, 0x97, 0x5A, 0xC4, 0xB7, 0x99, 0xF5, 0xBE,
167 0xA1, 0x6D, 0x5E, 0x13, 0xE9, 0xAF, 0x97, 0x1D, 0x5E, 0x9B,
168 0x98, 0x4C, 0x9F, 0x39, 0x72, 0x8B, 0x5E, 0x57, 0x39, 0x73,
169 0x5A, 0x21, 0x9B, 0x97, 0xC3, 0x56, 0x43, 0x6A, 0xDC, 0x6E,
170 0x95, 0xBB, 0x03, 0x52, 0xF6, 0xBE, 0x64, 0xA6, 0xC2, 0x91,
171 0x2D, 0x4E, 0xF2, 0xD0, 0x43, 0x3C, 0xED, 0x2B, 0x61, 0x71,
172 0x64, 0x00, 0x12, 0xD9, 0x46, 0x0F,
173
174 0x01, 0x5C, 0x68, 0x22, 0x63, 0x83, 0x95, 0x6E, 0x3B, 0xD0,
175 0x66, 0xE7, 0x97, 0xB6, 0x23, 0xC2, 0x7C, 0xE0, 0xEA, 0xC2,
176 0xF5, 0x51, 0xA1, 0x0C, 0x2C, 0x72, 0x4D, 0x98, 0x52, 0x07,
177 0x7B, 0x87, 0x22, 0x0B, 0x65, 0x36, 0xC5, 0xC4, 0x08, 0xA1,
178 0xD2, 0xAE, 0xBB, 0x8E, 0x86, 0xD6, 0x78, 0xAE, 0x49, 0xCB,
179 0x57, 0x09, 0x1F, 0x47, 0x32, 0x29, 0x65, 0x79, 0xAB, 0x44,
180 0xFC, 0xD1, 0x7F, 0x0F, 0xC5, 0x6A,
181
182 0x01, 0x14, 0x4C, 0x7D, 0x79, 0xAE, 0x69, 0x56, 0xBC, 0x8E,
183 0xDB, 0x8E, 0x7C, 0x78, 0x7C, 0x45, 0x21, 0xCB, 0x08, 0x6F,
184 0xA6, 0x44, 0x07, 0xF9, 0x78, 0x94, 0xE5, 0xE6, 0xB2, 0xD7,
185 0x9B, 0x04, 0xD1, 0x42, 0x7E, 0x73, 0xCA, 0x4B, 0xAA, 0x24,
186 0x0A, 0x34, 0x78, 0x68, 0x59, 0x81, 0x0C, 0x06, 0xB3, 0xC7,
187 0x15, 0xA3, 0xA8, 0xCC, 0x31, 0x51, 0xF2, 0xBE, 0xE4, 0x17,
188 0x99, 0x6D, 0x19, 0xF3, 0xDD, 0xEA,
189};
190
191enum ecdh_data { SIDE_A_KEY, SIDE_B_KEY, SHARED_SECRET };
192static void *generate_test_ecdh_data(const int group_id,
193 enum ecdh_data request_data)
194{
195 uint8_t *data_set;
196 int size;
197 EC_KEY *key;
198 const EC_GROUP *group;
199 const BIGNUM *k_priv = NULL;
200 const BIGNUM *k_pubx = NULL;
201 const BIGNUM *k_puby = NULL;
202 EC_POINT *k_pub = NULL;
203
204 switch (group_id) {
205 case HIP_DH_NIST_P_256:
206 data_set = TEST_ECDH_NIST_P_256;
207 break;
208 case HIP_DH_NIST_P_384:
209 data_set = TEST_ECDH_NIST_P_384;
210 break;
211 case HIP_DH_NIST_P_521:
212 data_set = TEST_ECDH_NIST_P_521;
213 break;
214 default:
215 return NULL;
216 }
217
218 size = hip_get_dh_size(group_id) / 2;
219
220 switch (request_data) {
221 case SIDE_A_KEY:
222 key = hip_generate_ecdh_key(group_id);
223 group = EC_KEY_get0_group(key);
224 k_priv = BN_bin2bn(data_set + size * TEST_ECDH_PRIV_A, size, NULL);
225 k_pubx = BN_bin2bn(data_set + size * TEST_ECDH_PUBX_A, size, NULL);
226 k_puby = BN_bin2bn(data_set + size * TEST_ECDH_PUBY_A, size, NULL);
227 k_pub = EC_POINT_new(group);
228 EC_POINT_set_affine_coordinates_GFp(group, k_pub, k_pubx, k_puby, NULL);
229 EC_KEY_set_public_key(key, k_pub);
230 EC_KEY_set_private_key(key, k_priv);
231 return key;
232 case SIDE_B_KEY:
233 key = hip_generate_ecdh_key(group_id);
234 group = EC_KEY_get0_group(key);
235 k_priv = BN_bin2bn(data_set + size * TEST_ECDH_PRIV_B, size, NULL);
236 k_pubx = BN_bin2bn(data_set + size * TEST_ECDH_PUBX_B, size, NULL);
237 k_puby = BN_bin2bn(data_set + size * TEST_ECDH_PUBY_B, size, NULL);
238 k_pub = EC_POINT_new(group);
239 EC_POINT_set_affine_coordinates_GFp(group, k_pub, k_pubx, k_puby, NULL);
240 EC_KEY_set_public_key(key, k_pub);
241 EC_KEY_set_private_key(key, k_priv);
242 return key;
243 case SHARED_SECRET:
244 return data_set + size * TEST_ECDH_SHARED;
245 }
246
247 return NULL;
248}
249
37START_TEST(test_create_ecdsa_key_invalid_id)250START_TEST(test_create_ecdsa_key_invalid_id)
38{251{
39 HIP_DEBUG("Trying to create some invalid ECDSA keys.\n");252 HIP_DEBUG("Trying to create some invalid ECDSA keys.\n");
@@ -244,6 +457,108 @@
244}457}
245END_TEST458END_TEST
246459
460#define TEST_ECDH_GROUP_SIZE 3
461static int TEST_ECDH_GROUPS[TEST_ECDH_GROUP_SIZE] = { HIP_DH_NIST_P_256,
462 HIP_DH_NIST_P_384,
463 HIP_DH_NIST_P_521 };
464
465START_TEST(test_generate_ecdh_key_invalid_group_id)
466{
467 fail_unless(hip_generate_ecdh_key(0) == NULL);
468 fail_unless(hip_generate_ecdh_key(-1) == NULL);
469 fail_unless(hip_generate_ecdh_key(HIP_MAX_DH_GROUP_ID) == NULL);
470}
471END_TEST
472
473START_TEST(test_generate_ecdh_key_valid_group_id)
474{
475 EC_KEY *key;
476 int i;
477
478 for (i = 0; i < TEST_ECDH_GROUP_SIZE; i++) {
479 key = hip_generate_ecdh_key(TEST_ECDH_GROUPS[i]);
480 fail_if(key == NULL || EC_KEY_check_key(key) == 0);
481 }
482}
483END_TEST
484
485START_TEST(test_ecdh_generate_2_keys_and_share_secret)
486{
487 EC_KEY *key1;
488 EC_KEY *key2;
489 int out1, out2;
490 int len1, len2;
491 int i;
492 int group_id;
493 int pubkey_size;
494
495 for (i = 0; i < TEST_ECDH_GROUP_SIZE; i++) {
496 group_id = TEST_ECDH_GROUPS[i];
497 pubkey_size = hip_get_dh_size(group_id);
498 fail_if(pubkey_size <= 0);
499
500 key1 = hip_generate_ecdh_key(group_id);
501 key2 = hip_generate_ecdh_key(group_id);
502 fail_if(key1 == NULL || key2 == NULL);
503
504 const EC_POINT *k1pub = EC_KEY_get0_public_key(key1);
505 const EC_POINT *k2pub = EC_KEY_get0_public_key(key2);
506
507 len1 = len2 = pubkey_size / 2;
508 unsigned char share1[len1];
509 unsigned char share2[len2];
510
511 out1 = ECDH_compute_key(share1, len1, k2pub, key1, NULL);
512 out2 = ECDH_compute_key(share2, len2, k1pub, key2, NULL);
513 fail_if(out1 <= 0 || out2 <= 0);
514 fail_if(out1 != len1 && out2 != len2);
515 fail_if(memcmp(share1, share2, len1) != 0);
516 }
517}
518END_TEST
519
520START_TEST(test_ecdh_encode_publickey)
521{
522 int i, group_id, key_size;
523
524 for (i = 0; i < TEST_ECDH_GROUP_SIZE; i++) {
525 group_id = TEST_ECDH_GROUPS[i];
526 key_size = hip_get_dh_size(group_id);
527 uint8_t out[key_size];
528 EC_KEY *key = hip_generate_ecdh_key(group_id);
529 fail_if(hip_encode_ecdh_publickey(key, out, key_size) != key_size);
530 }
531}
532END_TEST
533
534START_TEST(test_ecdh_gen_shared_key)
535{
536 int i, group_id, size, res;
537
538 for (i = 0; i < TEST_ECDH_GROUP_SIZE; i++) {
539 group_id = TEST_ECDH_GROUPS[i];
540 size = hip_get_dh_size(group_id) / 2;
541 uint8_t pub[size * 2];
542 uint8_t out[size];
543 EC_KEY *a = generate_test_ecdh_data(group_id, SIDE_A_KEY);
544 EC_KEY *b = generate_test_ecdh_data(group_id, SIDE_B_KEY);
545 void *secret = generate_test_ecdh_data(group_id, SHARED_SECRET);
546 fail_if(a == NULL || b == NULL || secret == NULL);
547 fail_if(EC_KEY_check_key(a) == 0 || EC_KEY_check_key(b) == 0);
548
549 hip_encode_ecdh_publickey(b, pub, size * 2);
550 res = hip_gen_ecdh_shared_key(a, pub, pub + size, size, out, size);
551 fail_if(res != size);
552 fail_if(memcmp(secret, out, size) != 0);
553
554 hip_encode_ecdh_publickey(a, pub, size * 2);
555 res = hip_gen_ecdh_shared_key(b, pub, pub + size, size, out, size);
556 fail_if(res != size);
557 fail_if(memcmp(secret, out, size) != 0);
558 }
559}
560END_TEST
561
247Suite *libcore_crypto(void)562Suite *libcore_crypto(void)
248{563{
249 Suite *s = suite_create("libcore/crypto");564 Suite *s = suite_create("libcore/crypto");
@@ -257,6 +572,11 @@
257 tcase_add_test(tc_core, test_load_invalid_ecdsa_key);572 tcase_add_test(tc_core, test_load_invalid_ecdsa_key);
258 tcase_add_test(tc_core, test_impl_ecdsa_sign_verify);573 tcase_add_test(tc_core, test_impl_ecdsa_sign_verify);
259 tcase_add_test(tc_core, test_invalid_impl_ecdsa_sign_verify);574 tcase_add_test(tc_core, test_invalid_impl_ecdsa_sign_verify);
575 tcase_add_test(tc_core, test_generate_ecdh_key_invalid_group_id);
576 tcase_add_test(tc_core, test_generate_ecdh_key_valid_group_id);
577 tcase_add_test(tc_core, test_ecdh_generate_2_keys_and_share_secret);
578 tcase_add_test(tc_core, test_ecdh_encode_publickey);
579 tcase_add_test(tc_core, test_ecdh_gen_shared_key);
260580
261 suite_add_tcase(s, tc_core);581 suite_add_tcase(s, tc_core);
262582

Subscribers

People subscribed via source and target branches

to all changes: