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

Proposed by Xin
Status: Rejected
Rejected by: Xin
Proposed branch: lp:~hipl-core/hipl/hipv2-dh-ecdh
Merge into: lp:hipl
Diff against target: 2184 lines (+1443/-225)
15 files modified
libcore/builder.c (+6/-5)
libcore/crypto.c (+177/-1)
libcore/crypto.h (+33/-6)
libcore/protodefs.h (+1/-0)
libhipl/cookie.c (+92/-34)
libhipl/cookie.h (+11/-17)
libhipl/dh.c (+297/-68)
libhipl/dh.h (+14/-6)
libhipl/hidb.c (+6/-11)
libhipl/hidb.h (+19/-3)
libhipl/input.c (+122/-26)
libhipl/netdev.c (+19/-2)
libhipl/output.c (+303/-43)
libhipl/output.h (+12/-2)
test/libcore/crypto.c (+331/-1)
To merge this branch: bzr merge lp:~hipl-core/hipl/hipv2-dh-ecdh
Reviewer Review Type Date Requested Status
Diego Biurrun Needs Fixing
Miika Komu Approve
Review via email: mp+120283@code.launchpad.net

Description of the change

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 :

Thanks, we need this! I quickly tested legacy compatibility both ways with HIPv1 as well as "make check" and both seem work.

I'd suggest to wait until next Friday and merge the code then. That is, unless somebody has comments or requests more time.

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

 review needs-fixing

On Sun, Aug 19, 2012 at 07:42:23AM +0000, Xin wrote:
> --- libcore/crypto.c 2012-05-12 06:54:33 +0000
> +++ libcore/crypto.c 2012-08-19 07:41:21 +0000
> @@ -701,6 +711,173 @@
> +
> +/**
> + * Generate a new Ellipse Curve Diffie-Hellman key.

Elliptic

You should know what the abbreviations stand for :)

There are more instances below, I won't point them all out.

> + * @param peer_len length of the @c peer_pub_x or @c peer_pub_y (these two
> + * length values are indentical)

identical

Please try a spellchecker.

> + HIP_IFEL(0 == (EC_POINT_set_affine_coordinates_GFp(group, peer_pub,
> + peer_pubx, peer_puby,
> + NULL)),

pointless ()

I think we mostly write "expr == 0" instead of "0 == expr"; more below,
I won't point them all out.

> + HIP_IFEL(out == 0 || out != peer_len, 0,
> + "Failed to compute the ECDH share key\n");

share_d_

> +/**
> + * Encode an ECDH public key into a character array.
> + *
> + * @param key the ECDH key
> + * @param out output argument: a character array

Doxygen has syntax for marking up input/output arguments.

> + if (key == NULL || out == NULL || outlen < 0
> + || EC_KEY_check_key(key) == 0) {

We usually have operators at the end of lines, not that I really care...

> --- libhipl/cookie.c 2012-06-03 10:26:55 +0000
> +++ libhipl/cookie.c 2012-08-19 07:41:21 +0000
> @@ -219,41 +218,90 @@
>
> /**
> + * HIPv2: get a copy of R1entry structure.
> + *
> + * @param ip_i Initiator's IPv6
> + * @param ip_r Responder's IPv6
> + * @param our_hit Our HIT
> + * @param dh_group_id Diffie Hellman group ID
> + * @return NULL on error
> + */

What is returned on success?

> + idx = calc_cookie_idx(ip_i, ip_r);
> + HIP_DEBUG("Calculated index: %d\n", idx);
> +
> + /* Create a copy of the found entry */
> + len = hip_get_msg_total_len(&(hid->r1_v2[dh_group_id][idx].buf.msg));

pointless ()

> + r1 = hip_msg_alloc();
> + memcpy(r1, &(hid->r1_v2[dh_group_id][idx].buf.msg), len);

pointless ()

hip_msg_alloc() can fail.

> - if (hip_create_r1(&r1table[i].buf.msg, hit, sign, privkey, pubkey,
> - cookie_k, hip_version)) {
> + hip_msg_init(&(id_entry->r1[i].buf.msg));
> +
> + if (hip_create_r1(&(id_entry->r1[i].buf.msg), hit, sign, privkey,
> + pubkey, cookie_k)) {

pointless (), why did you add them?

> + 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));

more

> + if (hip_create_r1_v2(&(id_entry->r1_v2[group_id][i].buf.msg), hit, sign,

and more

> --- libhipl/dh.c 2012-05-12 10:21:32 +0000
> +++ libhipl/dh.c 2012-08-19 07:41:21 +0000
> @@ -95,66 +97,288 @@
>
> /**
> + * Store the bytes of the current ECDH public key to the given buffer.

s/to/in/

> + * A new ECDH key will be created if it doesn't exist,
>...

Read more...

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

Revise code & document based on review feedback.

6261. By Xin

Fix code style and comments.

Unmerged revisions

Preview Diff

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

Subscribers

People subscribed via source and target branches

to all changes: