Example #1
0
/**
 * Convert the opaque value in the CHALLENGE_REQUEST to the seed value I of a
 * HIP puzzle.
 *
 * The opaque value plays a dual role in a CHALLENGE_REQUEST:
 * i)  it is a challenge that needs to be echoed back by the responder and
 * ii) it is used to derive the seed value for a cryptographic puzzle. The
 *     puzzle is defined in RFC5201.
 *
 * @param opaque            the nonce (challenge) in the CHALLENGE_REQUEST
 * @param opaque_len        the length of the nonce
 * @param puzzle_value      the puzzle value generated from the nonce
 * @return zero on success, -1 in case of an error
 */
int hip_midauth_puzzle_seed(const uint8_t opaque[],
                            const unsigned int opaque_len,
                            uint8_t puzzle_value[PUZZLE_LENGTH])
{
    unsigned char sha_digest[SHA_DIGEST_LENGTH];

    HIP_ASSERT(puzzle_value != NULL);

    // the hashed opaque field is used as puzzle seed
    if (hip_build_digest(HIP_DIGEST_SHA1,
                         opaque,
                         opaque_len,
                         sha_digest)) {
        HIP_ERROR("Building of SHA1 random seed I failed\n");
        return -1;
    }

    memcpy(puzzle_value,
           &sha_digest[SHA_DIGEST_LENGTH - PUZZLE_LENGTH],
           PUZZLE_LENGTH);

    return 0;
}
Example #2
0
/**
 * generate HIP keying material
 * @param kij Diffie-Hellman Kij (as in the HIP drafts)
 * @param kij_len the length of the Kij material
 * @param keymat pointer to a keymat structure which will be updated according
 *           to the generated keymaterial
 * @param dstbuf the generated keymaterial will be written here
 * @param dstbuflen the length of the buffer to which to write to
 * @param hit1 source HIT
 * @param hit2 destination HIT
 * @param calc_index where the one byte index is stored (n of Kn)
 * @param I the I value
 * @param J the J value
 *
 */
void hip_make_keymat(char *kij,
                     size_t kij_len,
                     struct hip_keymat_keymat *keymat,
                     void *dstbuf,
                     size_t dstbuflen,
                     struct in6_addr *hit1,
                     struct in6_addr *hit2,
                     uint8_t *calc_index,
                     const uint8_t I[PUZZLE_LENGTH],
                     const uint8_t J[PUZZLE_LENGTH])
{
    int              bufsize;
    uint8_t          index_nbr = 1;
    size_t           dstoffset = 0;
    void            *seedkey;
    struct in6_addr *smaller_hit, *bigger_hit;
    int              hit1_is_bigger;
    uint8_t         *shabuffer = NULL;

    HIP_DEBUG("\n");
    if (dstbuflen < HIP_AH_SHA_LEN) {
        HIP_ERROR("dstbuf is too short (%d)\n", dstbuflen);
        return;
    }

    HIP_ASSERT(sizeof(index_nbr) == HIP_KEYMAT_INDEX_NBR_SIZE);

    hit1_is_bigger = hip_hit_is_bigger(hit1, hit2);

    bigger_hit  = hit1_is_bigger ? hit1 : hit2;
    smaller_hit = hit1_is_bigger ? hit2 : hit1;
    shabuffer   = hip_create_keymat_buffer(kij, kij_len, HIP_AH_SHA_LEN,
                                           smaller_hit, bigger_hit, I, J);
    if (!shabuffer) {
        HIP_ERROR("No memory for keymat\n");
        return;
    }

    bufsize = kij_len + 2 * sizeof(struct in6_addr) +
              2 * sizeof(uint64_t) + 1;

    // XX FIXME: is this correct
    hip_build_digest(HIP_DIGEST_SHA1, shabuffer, bufsize, dstbuf);

    dstoffset = HIP_AH_SHA_LEN;
    index_nbr++;

    /*
     * K2 = SHA1(Kij | K1 | 2)
     * K3 = SHA1(Kij | K2 | 3)
     * ...
     */
    seedkey = dstbuf;
    hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
                             kij_len, index_nbr);

    while (dstoffset < dstbuflen) {
        hip_build_digest(HIP_DIGEST_SHA1, shabuffer,
                         kij_len + HIP_AH_SHA_LEN + 1,
                         (uint8_t *) dstbuf + dstoffset);
        seedkey    = (uint8_t *) dstbuf + dstoffset;
        dstoffset += HIP_AH_SHA_LEN;
        index_nbr++;
        hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
                                 kij_len, index_nbr);
    }

    keymat->offset    = 0;
    keymat->keymatlen = dstoffset;
    keymat->keymatdst = dstbuf;

    if (calc_index) {
        *calc_index = index_nbr;
    } else {
        HIP_ERROR("NULL calc_index\n");
    }

    free(shabuffer);
}
Example #3
0
File: keymat.c Project: surki/hipl
/**
 * hip_make_keymat - generate HIP keying material
 * @param kij Diffie-Hellman Kij (as in the HIP drafts)
 * @param kij_len the length of the Kij material
 * @param keymat pointer to a keymat structure which will be updated according
 *           to the generated keymaterial
 * @param dstbuf the generated keymaterial will be written here
 * @param hit1 source HIT
 * @param hit2 destination HIT
 * @param calc_index where the one byte index is stored (n of Kn)
 *
 */
void hip_make_keymat(char *kij, size_t kij_len,
		     struct hip_keymat_keymat *keymat, 
		     void *dstbuf, size_t dstbuflen, struct in6_addr *hit1,
		     struct in6_addr *hit2, u8 *calc_index,
		     uint64_t I, uint64_t J)
{
	int bufsize, err = 0;
	uint8_t index_nbr = 1;
	int dstoffset = 0;
	void *seedkey;
	struct in6_addr *smaller_hit, *bigger_hit;
	int hit1_is_bigger;
	u8 *shabuffer = NULL;

	HIP_DEBUG("\n");
	if (dstbuflen < HIP_AH_SHA_LEN) {
		HIP_ERROR("dstbuf is too short (%d)\n", dstbuflen);
		return;
	}

	_HIP_ASSERT(dstbuflen % 32 == 0);
	HIP_ASSERT(sizeof(index_nbr) == HIP_KEYMAT_INDEX_NBR_SIZE);

	hit1_is_bigger = hip_hit_is_bigger(hit1, hit2);

	bigger_hit =  hit1_is_bigger ? hit1 : hit2;
	smaller_hit = hit1_is_bigger ? hit2 : hit1;

	_HIP_HEXDUMP("kij", kij, kij_len);
	_HIP_DEBUG("I=0x%llx J=0x%llx\n", I, J);
	_HIP_HEXDUMP("bigger hit", bigger_hit, 16);
	_HIP_HEXDUMP("smaller hit", smaller_hit, 16);
	_HIP_HEXDUMP("index_nbr", (char *) &index_nbr,
		     HIP_KEYMAT_INDEX_NBR_SIZE);

	shabuffer = hip_create_keymat_buffer(kij, kij_len, HIP_AH_SHA_LEN,
					     smaller_hit, bigger_hit, I, J);
	if (!shabuffer) {
		HIP_ERROR("No memory for keymat\n");
		return;
	}

	bufsize = kij_len + 2 * sizeof(struct in6_addr) +
		2 * sizeof(uint64_t) + 1;
	//bufsize = kij_len+2*sizeof(struct in6_addr)+ 1;

	// XX FIXME: is this correct
	hip_build_digest(HIP_DIGEST_SHA1, shabuffer, bufsize, dstbuf);

	_HIP_HEXDUMP("keymat digest", dstbuf, HIP_AH_SHA_LEN);

	dstoffset = HIP_AH_SHA_LEN;
	index_nbr++;

	/*
	 * K2 = SHA1(Kij | K1 | 2)
	 * K3 = SHA1(Kij | K2 | 3)
	 * ...
	 */
	seedkey = dstbuf;
	hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
				 kij_len, index_nbr);

	while (dstoffset < dstbuflen) {
		hip_build_digest(HIP_DIGEST_SHA1, shabuffer,
				 kij_len + HIP_AH_SHA_LEN + 1,
				 dstbuf + dstoffset);
		seedkey = dstbuf + dstoffset;
		dstoffset += HIP_AH_SHA_LEN;
		index_nbr++;
		hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
					 kij_len, index_nbr);
	}

	keymat->offset = 0;
	keymat->keymatlen = dstoffset;
	keymat->keymatdst = dstbuf;

	if (calc_index)
		*calc_index = index_nbr;
	else
		HIP_ERROR("NULL calc_index\n");

	_HIP_DEBUG("keymat index_nbr=%u\n", index_nbr);
	_HIP_HEXDUMP("GENERATED KEYMAT: ", dstbuf, dstbuflen);
	if (shabuffer)
		HIP_FREE(shabuffer);

	return;
}
Example #4
0
File: keymat.c Project: surki/hipl
/** 
 * Calculates new keying material.
 *
 * This function gets next @c key_len bytes of KEYMAT to @c key starting from
 * requested offset @c keymat_index. On entry of this function @c calc_index
 * tells the one byte index value which is related to @c calc_index_keymat (for
 * example, if @c calc_index_keymat is K3, then @c calc_index is 3).
 *
 * On successful return, @c keymat_index and @c calc_index contain the values
 * used in the last round of calculating Kn of KEYMAT, @c calc_index_keymat
 * contains the last Kn, and @c Kn_is_at contains the byte offset value of
 * @c calc_index_keymat.
 *
 * @param key               buffer where the created KEYMAT is stored.
 * @param key_len           length of @c key in bytes.
 * @param kij               shared key.
 * @param kij_len           length of @c kij in bytes.
 * @param keymat_index      keymat index.
 * @param calc_index        the one byte index value.
 * @param calc_index_keymat Kn.
 * @param Kn_is_at          the byte offset where @c calc_index_keymat starts.
 * @return                  0 on success, < 0 otherwise.
 */
int hip_keymat_get_new(void *key, size_t key_len, char *kij, size_t kij_len,
		       uint16_t *keymat_index, uint8_t *calc_index,
		       unsigned char *calc_index_keymat, uint16_t *Kn_is_at)
{
	/* must have the hadb lock when calling this function */
	int err = 0;
	int copied = 0;
	u8 *tmp_data = NULL;
	size_t tmp_data_len;

	_HIP_DEBUG("key_len=%d, requested keymat_index=%u calc_index=%u Kn_is_at=%u\n",
		   key_len, *keymat_index, *calc_index, *Kn_is_at);
	_HIP_HEXDUMP("calc_index_keymat", calc_index_keymat, HIP_AH_SHA_LEN);

 	if (key_len == 0 || kij_len == 0) {
		HIP_ERROR("key_len = 0 or kij_len = 0\n");
		err = -EINVAL;
		goto out_err;
	}

	_HIP_DEBUG("one byte index at req'd index in the end should be %u\n",
		  (*keymat_index / HIP_AH_SHA_LEN + 1) % 256);

	if (*keymat_index < *Kn_is_at) {
		HIP_ERROR("requested keymat index %u is lower than lowest keymat index of Kn (%u)\n",
			  *keymat_index, *Kn_is_at);
		err = -EINVAL;
		goto out_err;
	}
	/** @todo Check here if we have to test *keymat_index <
	    entry->current_keymat_index ? */
	
	/* before calculating any hashes test if we already have
	 * needed amount of ready keymat
	 *
	 * must first check that the requested keymat_index is within the ready keymat
	 */
	if (*keymat_index - *Kn_is_at < HIP_AH_SHA_LEN) {
		int tmp = HIP_AH_SHA_LEN - (*keymat_index - *Kn_is_at);
		_HIP_DEBUG("test: can copy %d bytes from the end of sha K\n", tmp);
		if (tmp > HIP_AH_SHA_LEN) {
			HIP_ERROR("bug: tmp > 20\n");
			err = -EINVAL;
			goto out_err;
		}

		if (tmp > 0) {
			memcpy(key, calc_index_keymat + HIP_AH_SHA_LEN - tmp, tmp);
			copied += tmp;
		}
	}

	_HIP_DEBUG("copied=%d\n", copied);
	_HIP_HEXDUMP("KEY (0)", key, copied);

	if (copied == key_len) {
		_HIP_DEBUG("copied all, return\n");
		goto out;
	}

	_HIP_DEBUG("need %d bytes more data\n", key_len-copied);

	tmp_data_len = kij_len + HIP_AH_SHA_LEN + 1;
	tmp_data = (u8 *)HIP_MALLOC(tmp_data_len, GFP_KERNEL);
	if (!tmp_data) {
		HIP_ERROR("HIP_MALLOC failed\n");
		err = -ENOMEM;
		goto out_err;
	}

	memcpy(tmp_data, kij, kij_len); /* fixed part of every Kn round */

	while (copied < key_len) {
		(*calc_index)++;
		_HIP_DEBUG("calc_index=%u\n", *calc_index);
		/* create Kn = SHA-1( Kij | Kn-1 | calc_index) */

		/* Kij | Kn-1 */
		memcpy(tmp_data+kij_len, calc_index_keymat, HIP_AH_SHA_LEN);
		/* Kij | Kn-1 | calc_index */
		memcpy(tmp_data+kij_len+HIP_AH_SHA_LEN, calc_index, HIP_KEYMAT_INDEX_NBR_SIZE);
		/* SHA-1( Kij | Kn-1 | calc_index) */
		err = hip_build_digest(HIP_DIGEST_SHA1, tmp_data, tmp_data_len, calc_index_keymat);
		if (err) {
			HIP_ERROR("build_digest failed (K%u)\n", *calc_index);
			goto out_err;
		}
		*Kn_is_at += HIP_AH_SHA_LEN;
		if (*Kn_is_at + HIP_AH_SHA_LEN < *keymat_index) {
			HIP_DEBUG("skip until we are at right offset\n");
			continue;
		}

		_HIP_DEBUG("copied=%u, key_len=%u calc_index=%u dst to 0x%p\n", copied, key_len, *calc_index, key+copied);
		if (copied + HIP_AH_SHA_LEN <= key_len) {
			_HIP_DEBUG("copy whole sha block\n");
			memcpy(key+copied, calc_index_keymat, HIP_AH_SHA_LEN);
			copied += HIP_AH_SHA_LEN;
		} else {
			int t = HIP_AH_SHA_LEN - key_len % HIP_AH_SHA_LEN;
			t = key_len - copied;
			_HIP_DEBUG("copy partial %d bytes\n", t);
			memcpy(key+copied, calc_index_keymat, t);
			copied += t;
		}
	}

	_HIP_DEBUG("end: copied=%u\n", copied);

 out:
	_HIP_HEXDUMP("CALCULATED KEY", key, key_len);
	_HIP_DEBUG("at end: *keymat_index=%u *calc_index=%u\n",
		   *keymat_index, *calc_index);
 out_err:
	if(tmp_data)
		HIP_FREE(tmp_data);
	return err;
}