derive.c
krb5_error_code
SP800_108_HMAC(const struct krb5_hash_provider *hash,
	       krb5_key inkey, krb5_data *outrnd,
	       const krb5_data *label, const krb5_data *context)
{
    krb5_crypto_iov iov[5];
    krb5_error_code ret;
    krb5_data prf;
    unsigned char ibuf[4], lbuf[4];

    if (hash == NULL || outrnd->length > hash->hashsize)
        return KRB5_CRYPTO_INTERNAL;

    /* Allocate encryption data buffer. */
    ret = alloc_data(&prf, hash->hashsize);
    if (ret)
        return ret;

    /* [i]2: four-byte big-endian binary string giving the block counter (1) */
    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[0].data = make_data(ibuf, sizeof(ibuf));
    encode_be_uint32(1, ibuf);
    /* Label */
    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[1].data = *label;
    /* 0x00: separator byte */
    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[2].data = make_data((uint8_t *)"", 1);
    /* Context */
    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[3].data = *context;
    /* [L]2: four-byte big-endian binary string giving the output length */
    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[4].data = make_data(lbuf, sizeof(lbuf));
    encode_be_uint32(outrnd->length * 8, lbuf);

    ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
    if (ret == 0)
        memcpy(outrnd->data, prf.data, outrnd->length);

    secure_zero_memory(prf.data, prf.length);
    free(prf.data);

    return ret;
}
/*
 * NIST SP800-108 KDF in counter mode (section 5.1).
 * Parameters:
 *   - HMAC (with hash as the hash provider) is the PRF.
 *   - A block counter of four bytes is used.
 *   - Four bytes are used to encode the output length in the PRF input.
 *
 * There are no uses requiring more than a single PRF invocation.
 */
NIST SP800-108 KDF in counter mode (section 5.1).
Parameters:
- HMAC (with hash as the hash provider) is the PRF.
- A block counter of four bytes is used.
- Four bytes are used to encode the output length in the PRF input.

There are no uses requiring more than a single PRF invocation.
NIST SP800 - 108 KDF in counter mode ( section 5 . 1 ) . Parameters : - HMAC ( with hash as the hash provider ) is the PRF . - A block counter of four bytes is used . - Four bytes are used to encode the output length in the PRF input . There are no uses requiring more than a single PRF invocation .
krb5_error_code
SP800_108_HMAC(const struct krb5_hash_provider *hash,
	       krb5_key inkey, krb5_data *outrnd,
	       const krb5_data *label, const krb5_data *context)
{
    krb5_crypto_iov iov[5];
    krb5_error_code ret;
    krb5_data prf;
    unsigned char ibuf[4], lbuf[4];
    if (hash == NULL || outrnd->length > hash->hashsize)
        return KRB5_CRYPTO_INTERNAL;
    ret = alloc_data(&prf, hash->hashsize);
    if (ret)
        return ret;
    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[0].data = make_data(ibuf, sizeof(ibuf));
    encode_be_uint32(1, ibuf);
    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[1].data = *label;
    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[2].data = make_data((uint8_t *)"", 1);
    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[3].data = *context;
    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[4].data = make_data(lbuf, sizeof(lbuf));
    encode_be_uint32(outrnd->length * 8, lbuf);
    ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
    if (ret == 0)
        memcpy(outrnd->data, prf.data, outrnd->length);
    secure_zero_memory(prf.data, prf.length);
    free(prf.data);
    return ret;
}
krb5_error_code SP800_108_HMAC ( const struct krb5_hash_provider * hash , krb5_key inkey , krb5_data * outrnd , const krb5_data * label , const krb5_data * context ) { krb5_crypto_iov iov [ 5 ] ; krb5_error_code ret ; krb5_data prf ; unsigned char ibuf [ 4 ] , lbuf [ 4 ] ; if ( hash == NULL || outrnd -> length > hash -> hashsize ) return KRB5_CRYPTO_INTERNAL ; ret = alloc_data ( & prf , hash -> hashsize ) ; if ( ret ) return ret ; iov [ 0 ] . flags = KRB5_CRYPTO_TYPE_DATA ; iov [ 0 ] . data = make_data ( ibuf , sizeof ( ibuf ) ) ; encode_be_uint32 ( 1 , ibuf ) ; iov [ 1 ] . flags = KRB5_CRYPTO_TYPE_DATA ; iov [ 1 ] . data = * label ; iov [ 2 ] . flags = KRB5_CRYPTO_TYPE_DATA ; iov [ 2 ] . data = make_data ( ( uint8_t * ) " " , 1 ) ; iov [ 3 ] . flags = KRB5_CRYPTO_TYPE_DATA ; iov [ 3 ] . data = * context ; iov [ 4 ] . flags = KRB5_CRYPTO_TYPE_DATA ; iov [ 4 ] . data = make_data ( lbuf , sizeof ( lbuf ) ) ; encode_be_uint32 ( outrnd -> length * 8 , lbuf ) ; ret = krb5int_hmac ( hash , inkey , iov , 5 , & prf ) ; if ( ret == 0 ) memcpy ( outrnd -> data , prf . data , outrnd -> length ) ; secure_zero_memory ( prf . data , prf . length ) ; free ( prf . data ) ; return ret ; }
NIST SP800-108 KDF in counter mode (section 5.1).
NIST SP800 - 108 KDF in counter mode ( section 5 . 1 ) .
/* Allocate encryption data buffer. */ /* [i]2: four-byte big-endian binary string giving the block counter (1) */ /* Label */ /* 0x00: separator byte */ /* Context */ /* [L]2: four-byte big-endian binary string giving the output length */