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 consistent with the table length in crypto.c and > * crypto/dh.c */ > -#define HIP_DH_384 1 /* 384-bit group */ > -#define HIP_DH_OAKLEY_1 2 /* 768-bit OAKLEY well known group 1 */ > > +/* 384-bit group, DEPRECATED from HIPv2 */ > +#define HIP_DH_384 1 > +/* 768-bit OAKLEY well known group 1, DEPRECATED from HIPv2 */ > +#define HIP_DH_OAKLEY_1 2 > #define HIP_DH_OAKLEY_5 3 /* 1536-bit MODP group */ > #define HIP_DH_OAKLEY_15 4 /* 3072-bit MODP group */ > -#define HIP_DH_OAKLEY_17 5 /* 6144-bit MODP group */ > -#define HIP_DH_OAKLEY_18 6 /* 8192-bit MODP group */ > +/* 6144-bit MODP group, DEPRECATED from HIPv2 */ > +#define HIP_DH_OAKLEY_17 5 > +/* 8192-bit MODP group, DEPRECATED from HIPv2 */ > +#define HIP_DH_OAKLEY_18 6 > +/* Group 7 to 10 are new groups defined in HIPv2, among which group 7,8 and 9 > + * are Ellipse Curve groups. */ > +#define HIP_DH_NIST_P_256 7 > +#define HIP_DH_NIST_P_384 8 > +#define HIP_DH_NIST_P_521 9 > +#define HIP_DH_SECP_160_R1 10 > #define HIP_FIRST_DH_GROUP_ID HIP_DH_OAKLEY_5 > #define HIP_SECOND_DH_GROUP_ID HIP_DH_384 > -#define HIP_MAX_DH_GROUP_ID 7 > +#define HIP_MAX_DH_GROUP_ID 11 Unrelated: this looks like an enum to me. > +/* HIPv2: default value for DH_GROUP_LIST parameter */ > +#define HIP_DH_GROUP_LIST_SIZE 3 > +const uint8_t HIP_DH_GROUP_LIST[HIP_DH_GROUP_LIST_SIZE]; There should be a macro named ARRAY_SIZE or similar somewhere in HIPL, which you can use instead of potentially forgetting about adjusting HIP_DH_GROUP_LIST_SIZE when the array changes. I do not remember the name of ARRAY_SIZE (and don't have a checkout here to search), but it's defined somewhat like this: #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) > @@ -219,41 +218,93 @@ > } > > /** > + * 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 A R1 packet copy on success, NULL on error > + */ > +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) const? > + 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? > @@ -266,13 +317,17 @@ > int hip_verify_cookie(struct in6_addr *ip_i, struct in6_addr *ip_r, > struct hip_common *hdr, > const struct hip_solution *solution, > - const uint8_t hip_version) > + const uint8_t hip_version, > + const int dh_group_id) > { > /* In a effort to conform the HIPL coding convention, the return value > * of this function was inverted. I.e. This function now returns Unrelated: this comment looks outdated. If it's important, it should perhaps be moved into the @return documentation. > +int hip_match_dh_group_list(const struct hip_tlv_common *const dh_group_list, > + const uint8_t *const our_dh_group, > + const int our_group_size) > +{ > + int list_size = HIP_DH_GROUP_MAX_RECV_SIZE; > + uint8_t list[list_size]; > + int i, j; > + > + list_size = hip_get_list_from_param(dh_group_list, list, list_size, > + sizeof(uint8_t)); This overwrites the initial value of list_size. (There are more instances of this) > + DH *key; > + int secret_len; > + > + if (group_id <= 0 || group_id >= HIP_MAX_DH_GROUP_ID) { > + HIP_ERROR("Invalid Group ID: %d.\n", group_id); > + return -1; > + } > + > + if (dh_table[group_id] == NULL) { > + if (NULL == (key = hip_generate_dh_key(group_id))) { > + HIP_ERROR("Failed to generate a DH key for group: %d\n", group_id); > + return -1; > + } > + dh_table[group_id] = key; > + } > + key = dh_table[group_id]; > + > + secret_len = hip_gen_dh_shared_key(dh_table[group_id], public_value, len, > + buffer, bufsize); > + if (secret_len < 0) { > + HIP_ERROR("failed to create a DH shared secret\n"); > + return -1; > + } > + > + return secret_len; > +} You assign to key but do not use it. > +static int hip_calculate_ecdh_shared_secret(const uint16_t group_id, > + const uint8_t *const public_value, > + const int pubkey_len, > + unsigned char *const buffer, > + const int bufsize) > +{ > + EC_KEY *key; > + int key_len; > + > + if (ecdh_table[group_id] == NULL) { > + if (NULL == (key = hip_generate_ecdh_key(group_id))) { > + 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]; You checked group_id above, in hip_calculate_dh_shared_secret(), but not here. I assume that group_id is a signed int due to API compatibility, but if it's not then you can get rid of all the <= 0 checks by using an unsigned int. > + okey = dh_table[group_id]; > + dh_table[group_id] = tmp; > + > + DH_free(okey); Can the temporary be avoided? Like this: DH_free(dh_table[group_id]); dh_table[group_id] = tmp; > === modified file 'libhipl/hidb.c' > --- libhipl/hidb.c 2012-06-03 10:26:55 +0000 > +++ libhipl/hidb.c 2012-09-08 08:34:18 +0000 > @@ -429,7 +429,6 @@ > + HIP_IFEL(hip_precreate_r1(id_entry, &hit, signature_func, > + id_entry->private_key, > + &id_entry->host_id) < 0, > + -ENOENT, > + "Unable to precreate R1s.\n"); In the docs of hip_precreate_r1, you specified "non-zero" (not "negative") as the error condition. > + for (i = 0; i < 3; i++) { > + switch (order[i]) { > + case '1': > + transform_hip_suite[i] = HIP_HIP_AES_SHA1; > + transform_esp_suite[i] = HIP_ESP_AES_SHA1; > + HIP_DEBUG("Transform order index %d is AES\n", i); > + break; > + case '2': > + transform_hip_suite[i] = HIP_HIP_3DES_SHA1; > + transform_esp_suite[i] = HIP_ESP_3DES_SHA1; > + HIP_DEBUG("Transform order index %d is 3DES\n", i); > + break; > + case '3': > + transform_hip_suite[i] = HIP_HIP_NULL_SHA1; > + transform_esp_suite[i] = HIP_ESP_NULL_SHA1; > + HIP_DEBUG("Transform order index %d is NULL_SHA1\n", i); > + break; > + } > + } While you did not introduce hip_transform_order in this branch, I wonder why this is no simple array of integers.