Esempio n. 1
0
krb5_error_code
krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, krb5_key key,
                    const krb5_data *in, krb5_data *out)
{
    krb5_crypto_iov iov;
    krb5_data prfconst = make_data("prf", 3);
    krb5_key kp = NULL;
    krb5_error_code ret;

    if (ktp->prf_length != ktp->enc->block_size)
        return KRB5_BAD_MSIZE;

    iov.flags = KRB5_CRYPTO_TYPE_DATA;
    iov.data = *in;

    /* Derive a key using the PRF constant. */
    ret = krb5int_derive_key(ktp->enc, key, &kp, &prfconst,
                             DERIVE_SP800_108_CMAC);
    if (ret != 0)
        goto cleanup;

    /* PRF is CMAC of input */
    ret = krb5int_cmac_checksum(ktp->enc, kp, &iov, 1, out);
    if (ret != 0)
        goto cleanup;

cleanup:
    krb5_k_free_key(NULL, kp);
    return ret;
}
Esempio n. 2
0
int
main(int argc, char **argv)
{
#ifdef CAMELLIA
    krb5_context context = NULL;
    krb5_keyblock keyblock;
    krb5_key key;
    const struct krb5_enc_provider *enc = &krb5int_enc_camellia128;
    krb5_crypto_iov iov;
    unsigned char resultbuf[16];
    krb5_data result = make_data(resultbuf, 16);

    /* Create the example key. */
    keyblock.magic = KV5M_KEYBLOCK;
    keyblock.enctype = ENCTYPE_CAMELLIA128_CTS_CMAC;
    keyblock.length = 16;
    keyblock.contents = keybytes;
    assert(krb5_k_create_key(context, &keyblock, &key) == 0);

    /* Example 1. */
    iov.flags = KRB5_CRYPTO_TYPE_DATA;
    iov.data = make_data(input, 0);
    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
    check_result("example 1", resultbuf, cmac1);

    /* Example 2. */
    iov.data.length = 16;
    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
    check_result("example 2", resultbuf, cmac2);

    /* Example 3. */
    iov.data.length = 40;
    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
    check_result("example 3", resultbuf, cmac3);

    /* Example 4. */
    iov.data.length = 64;
    assert(krb5int_cmac_checksum(enc, key, &iov, 1, &result) == 0);
    check_result("example 4", resultbuf, cmac4);

    printf("All CMAC tests passed.\n");
    krb5_k_free_key(context, key);
#endif /* CAMELLIA */
    return 0;
}
Esempio n. 3
0
krb5_error_code
krb5int_dk_cmac_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
			krb5_keyusage usage, const krb5_data *ivec,
			krb5_crypto_iov *data, size_t num_data)
{
    const struct krb5_enc_provider *enc = ktp->enc;
    krb5_error_code ret;
    krb5_crypto_iov *header, *trailer, *padding;
    krb5_data cksum = empty_data();
    krb5_key ke = NULL, ki = NULL;

    /* E(Confounder | Plaintext | Pad) | Checksum */

    /* Validate header and trailer lengths, and zero out padding length. */
    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    if (header == NULL || header->data.length < enc->block_size)
        return KRB5_BAD_MSIZE;
    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    if (trailer == NULL || trailer->data.length < enc->block_size)
        return KRB5_BAD_MSIZE;
    padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    if (padding != NULL)
	padding->data.length = 0;

    /* Derive the encryption and integrity keys. */
    ret = derive_keys(enc, key, usage, &ke, &ki);
    if (ret != 0)
        goto cleanup;

    /* Generate confounder. */
    header->data.length = enc->block_size;
    ret = krb5_c_random_make_octets(NULL, &header->data);
    if (ret != 0)
        goto cleanup;

    /* Checksum the plaintext. */
    ret = krb5int_cmac_checksum(enc, ki, data, num_data, &trailer->data);
    if (ret != 0)
        goto cleanup;

    /* Encrypt the plaintext (header | data | padding) */
    ret = enc->encrypt(ke, ivec, data, num_data);
    if (ret != 0)
        goto cleanup;

cleanup:
    krb5_k_free_key(NULL, ke);
    krb5_k_free_key(NULL, ki);
    zapfree(cksum.data, cksum.length);
    return ret;
}
Esempio n. 4
0
krb5_error_code
krb5int_dk_cmac_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
                        krb5_keyusage usage, const krb5_data *ivec,
                        krb5_crypto_iov *data, size_t num_data)
{
    const struct krb5_enc_provider *enc = ktp->enc;
    krb5_error_code ret;
    krb5_crypto_iov *header, *trailer;
    krb5_data cksum = empty_data();
    krb5_key ke = NULL, ki = NULL;

    /* E(Confounder | Plaintext | Pad) | Checksum */

    /* Validate header and trailer lengths. */
    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    if (header == NULL || header->data.length != enc->block_size)
        return KRB5_BAD_MSIZE;
    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    if (trailer == NULL || trailer->data.length != enc->block_size)
        return KRB5_BAD_MSIZE;

    /* Derive the encryption and integrity keys. */
    ret = derive_keys(enc, key, usage, &ke, &ki);
    if (ret != 0)
        goto cleanup;

    /* Decrypt the plaintext (header | data | padding). */
    ret = enc->decrypt(ke, ivec, data, num_data);
    if (ret != 0)
        goto cleanup;

    /* Verify the hash. */
    ret = alloc_data(&cksum, enc->block_size);
    if (ret != 0)
        goto cleanup;
    ret = krb5int_cmac_checksum(enc, ki, data, num_data, &cksum);
    if (ret != 0)
        goto cleanup;
    if (k5_bcmp(cksum.data, trailer->data.data, enc->block_size) != 0)
        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;

cleanup:
    krb5_k_free_key(NULL, ke);
    krb5_k_free_key(NULL, ki);
    zapfree(cksum.data, cksum.length);
    return ret;
}
Esempio n. 5
0
/*
 * NIST SP800-108 KDF in feedback mode (section 5.2).
 * Parameters:
 *   - CMAC (with enc as the enc provider) is the PRF.
 *   - A block counter of four bytes is used.
 *   - Label is the key derivation constant.
 *   - Context is empty.
 *   - Four bytes are used to encode the output length in the PRF input.
 */
static krb5_error_code
derive_random_sp800_108_cmac(const struct krb5_enc_provider *enc,
                             krb5_key inkey, krb5_data *outrnd,
                             const krb5_data *in_constant)
{
    size_t blocksize, keybytes, n;
    krb5_crypto_iov iov[6];
    krb5_error_code ret;
    krb5_data prf;
    unsigned int i;
    unsigned char ibuf[4], Lbuf[4];

    blocksize = enc->block_size;
    keybytes = enc->keybytes;

    if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
        return KRB5_CRYPTO_INTERNAL;

    /* Allocate encryption data buffer. */
    ret = alloc_data(&prf, blocksize);
    if (ret)
        return ret;

    /* K(i-1): the previous block of PRF output, initially all-zeros. */
    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[0].data = prf;
    /* [i]2: four-byte big-endian binary string giving the block counter */
    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[1].data = make_data(ibuf, sizeof(ibuf));
    /* Label: the fixed derived-key input */
    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[2].data = *in_constant;
    /* 0x00: separator byte */
    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[3].data = make_data("", 1);
    /* Context: (unused) */
    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[4].data = empty_data();
    /* [L]2: four-byte big-endian binary string giving the output length */
    iov[5].flags = KRB5_CRYPTO_TYPE_DATA;
    iov[5].data = make_data(Lbuf, sizeof(Lbuf));
    store_32_be(outrnd->length * 8, Lbuf);

    for (i = 1, n = 0; n < keybytes; i++) {
        /* Update the block counter. */
        store_32_be(i, ibuf);

        /* Compute a CMAC checksum, storing the result into K(i-1). */
        ret = krb5int_cmac_checksum(enc, inkey, iov, 6, &prf);
        if (ret)
            goto cleanup;

        /* Copy the result into the appropriate part of the output buffer. */
        if (keybytes - n <= blocksize) {
            memcpy(outrnd->data + n, prf.data, keybytes - n);
            break;
        }
        memcpy(outrnd->data + n, prf.data, blocksize);
        n += blocksize;
    }

cleanup:
    zapfree(prf.data, blocksize);
    return ret;
}