Example #1
0
/* Derive a usage key from a session key and krb5 usage constant. */
static krb5_error_code
usage_key(const struct krb5_enc_provider *enc,
          const struct krb5_hash_provider *hash,
          const krb5_keyblock *session_keyblock, krb5_keyusage usage,
          krb5_keyblock *out)
{
    char salt_buf[14];
    unsigned int salt_len;
    krb5_data out_data = make_data(out->contents, out->length);
    krb5_crypto_iov iov;
    krb5_keyusage ms_usage;

    /* Generate the salt. */
    ms_usage = krb5int_arcfour_translate_usage(usage);
    if (session_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
        memcpy(salt_buf, l40, 10);
        store_32_le(ms_usage, salt_buf + 10);
        salt_len = 14;
    } else {
        store_32_le(ms_usage, salt_buf);
        salt_len = 4;
    }

    /* Compute HMAC(key, salt) to produce the usage key. */
    iov.flags = KRB5_CRYPTO_TYPE_DATA;
    iov.data = make_data(salt_buf, salt_len);
    return krb5int_hmac_keyblock(hash, session_keyblock, &iov, 1, &out_data);
}
Example #2
0
krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp,
                                         krb5_key key, krb5_keyusage usage,
                                         const krb5_crypto_iov *data,
                                         size_t num_data,
                                         krb5_data *output)
{
    krb5_keyusage ms_usage;
    krb5_error_code ret;
    krb5_keyblock ks, *keyblock;
    krb5_crypto_iov *hash_iov = NULL, iov;
    krb5_data ds = empty_data(), hashval = empty_data();
    char t[4];

    if (key == NULL || key->keyblock.length > ctp->hash->blocksize)
        return KRB5_BAD_ENCTYPE;
    if (ctp->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) {
        /* Compute HMAC(key, "signaturekey\0") to get the signing key ks. */
        ret = alloc_data(&ds, ctp->hash->hashsize);
        if (ret != 0)
            goto cleanup;

        iov.flags = KRB5_CRYPTO_TYPE_DATA;
        iov.data = make_data("signaturekey", 13);
        ret = krb5int_hmac(ctp->hash, key, &iov, 1, &ds);
        if (ret)
            goto cleanup;
        ks.length = key->keyblock.length;
        ks.contents = (krb5_octet *) ds.data;
        keyblock = &ks;
    } else  /* For md5-hmac, just use the key. */
        keyblock = &key->keyblock;

    /* Compute the MD5 value of the input. */
    ms_usage = krb5int_arcfour_translate_usage(usage);
    store_32_le(ms_usage, t);
    hash_iov = k5alloc((num_data + 1) * sizeof(krb5_crypto_iov), &ret);
    if (hash_iov == NULL)
        goto cleanup;
    hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
    hash_iov[0].data = make_data(t, 4);
    memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
    ret = alloc_data(&hashval, ctp->hash->hashsize);
    if (ret != 0)
        goto cleanup;
    ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval);
    if (ret != 0)
        goto cleanup;

    /* Compute HMAC(ks, md5value). */
    iov.flags = KRB5_CRYPTO_TYPE_DATA;
    iov.data = hashval;
    ret = krb5int_hmac_keyblock(ctp->hash, keyblock, &iov, 1, output);

cleanup:
    zapfree(ds.data, ds.length);
    zapfree(hashval.data, hashval.length);
    free(hash_iov);
    return ret;
}
Example #3
0
static  krb5_error_code
k5_md5_hmac_hash (const krb5_keyblock *key, krb5_keyusage usage,
		  const krb5_data *iv,
		  const krb5_data *input, krb5_data *output)
{
  krb5_keyusage ms_usage;
  krb5_MD5_CTX ctx;
  unsigned char t[4];
  krb5_data ds;

  krb5_MD5Init(&ctx);

  ms_usage = krb5int_arcfour_translate_usage (usage);
  store_32_le(ms_usage, t);
  krb5_MD5Update(&ctx, t, sizeof(t));
  krb5_MD5Update(&ctx, (unsigned char *)input->data, input->length);
  krb5_MD5Final(&ctx);

  ds.magic = KV5M_DATA;
  ds.length = 16;
  ds.data = (char *)ctx.digest;

  return krb5_hmac ( &krb5int_hash_md5, key, 1, &ds, output);
}
Example #4
0
static krb5_error_code
krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead,
			    const struct krb5_enc_provider *enc,
			    const struct krb5_hash_provider *hash,
			    const krb5_keyblock *key,
			    krb5_keyusage usage,
			    const krb5_data *ivec,
			    krb5_crypto_iov *data,
			    size_t num_data)
{
    krb5_error_code ret;
    krb5_crypto_iov *header, *trailer;
    krb5_keyblock k1, k2, k3;
    krb5_data d1, d2, d3;
    krb5_data checksum, confounder, header_data;
    krb5_keyusage ms_usage;
    char salt_data[14];
    krb5_data salt;
    size_t i;

    d1.length = d2.length = d3.length = 0;
    d1.data = d2.data = d3.data = NULL;

    /*
     * Caller must have provided space for the header, padding
     * and trailer; per RFC 4757 we will arrange it as:
     *
     *	    Checksum | E(Confounder | Plaintext)
     */

    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    if (header == NULL ||
	header->data.length < hash->hashsize + CONFOUNDERLENGTH)
	return KRB5_BAD_MSIZE;

    header_data = header->data;

    /* Trailer may be absent */
    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    if (trailer != NULL)
	trailer->data.length = 0;

    /* Ensure that there is no padding */
    for (i = 0; i < num_data; i++) {
	if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING)
	    data[i].data.length = 0;
    }

    ret = alloc_derived_key(enc, &k1, &d1, key);
    if (ret != 0)
	goto cleanup;

    ret = alloc_derived_key(enc, &k2, &d2, key);
    if (ret != 0)
	goto cleanup;

    ret = alloc_derived_key(enc, &k3, &d3, key);
    if (ret != 0)
	goto cleanup;

    /* Begin the encryption, compute K1 */
    salt.data = salt_data;
    salt.length = sizeof(salt_data);

    ms_usage = krb5int_arcfour_translate_usage(usage);

    if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
	strncpy(salt.data, krb5int_arcfour_l40, salt.length);
	store_32_le(ms_usage, salt.data + 10);
    } else {
	salt.length = 4;
	store_32_le(ms_usage, salt.data);
    }
    ret = krb5_hmac(hash, key, 1, &salt, &d1);
    if (ret != 0)
	goto cleanup;

    memcpy(k2.contents, k1.contents, k2.length);

    if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
	memset(k1.contents + 7, 0xAB, 9);

    header->data.length = hash->hashsize + CONFOUNDERLENGTH;

    confounder.data = header->data.data + hash->hashsize;
    confounder.length = CONFOUNDERLENGTH;

    ret = krb5_c_random_make_octets(0, &confounder);
    if (ret != 0)
	goto cleanup;

    checksum.data = header->data.data;
    checksum.length = hash->hashsize;

    /* Adjust pointers so confounder is at start of header */
    header->data.length -= hash->hashsize;
    header->data.data   += hash->hashsize;

    ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum);
    if (ret != 0)
	goto cleanup;

    ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
    if (ret != 0)
	goto cleanup;

    ret = enc->encrypt_iov(&k3, ivec, data, num_data);
    if (ret != 0)
	goto cleanup;

cleanup:
    header->data = header_data; /* restore header pointers */

    if (d1.data != NULL) {
	memset(d1.data, 0, d1.length);
	free(d1.data);
    }
    if (d2.data != NULL) {
	memset(d2.data, 0, d2.length);
	free(d2.data);
    }
    if (d3.data != NULL) {
	memset(d3.data, 0, d3.length);
	free(d3.data);
    }

    return ret;
}
Example #5
0
static krb5_error_code
krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead,
			    const struct krb5_enc_provider *enc,
			    const struct krb5_hash_provider *hash,
			    const krb5_keyblock *key,
			    krb5_keyusage usage,
			    const krb5_data *ivec,
			    krb5_crypto_iov *data,
			    size_t num_data)
{
    krb5_error_code ret;
    krb5_crypto_iov *header, *trailer;
    krb5_keyblock k1, k2, k3;
    krb5_data d1, d2, d3;
    krb5_data checksum, header_data;
    krb5_keyusage ms_usage;
    char salt_data[14];
    krb5_data salt;

    d1.length = d2.length = d3.length = 0;
    d1.data = d2.data = d3.data = NULL;

    header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    if (header == NULL ||
        header->data.length != hash->hashsize + CONFOUNDERLENGTH)
	return KRB5_BAD_MSIZE;

    header_data = header->data;

    trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    if (trailer != NULL && trailer->data.length != 0)
	return KRB5_BAD_MSIZE;

    ret = alloc_derived_key(enc, &k1, &d1, key);
    if (ret != 0)
	goto cleanup;

    ret = alloc_derived_key(enc, &k2, &d2, key);
    if (ret != 0)
	goto cleanup;

    ret = alloc_derived_key(enc, &k3, &d3, key);
    if (ret != 0)
	goto cleanup;

    /* Begin the decryption, compute K1 */
    salt.data = salt_data;
    salt.length = sizeof(salt_data);

    ms_usage = krb5int_arcfour_translate_usage(usage);

    if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
	strncpy(salt.data, krb5int_arcfour_l40, salt.length);
	store_32_le(ms_usage, (unsigned char *)salt.data + 10);
    } else {
	salt.length = 4;
	store_32_le(ms_usage, (unsigned char *)salt.data);
    }
    ret = krb5_hmac(hash, key, 1, &salt, &d1);
    if (ret != 0)
	goto cleanup;

    memcpy(k2.contents, k1.contents, k2.length);

    if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
	memset(k1.contents + 7, 0xAB, 9);

    checksum.data = header->data.data;
    checksum.length = hash->hashsize;

    /* Adjust pointers so confounder is at start of header */
    header->data.length -= hash->hashsize;
    header->data.data   += hash->hashsize;

    ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
    if (ret != 0)
	goto cleanup;

    ret = enc->decrypt_iov(&k3, ivec, data, num_data);
    if (ret != 0)
	goto cleanup;

    ret = krb5int_hmac_iov(hash, &k2, data, num_data, &d1);
    if (ret != 0)
	goto cleanup;

    if (memcmp(checksum.data, d1.data, hash->hashsize) != 0) {
	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
	goto cleanup;
    }

cleanup:
    header->data = header_data; /* restore header pointers */

    if (d1.data != NULL) {
	memset(d1.data, 0, d1.length);
	free(d1.data);
    }
    if (d2.data != NULL) {
	memset(d2.data, 0, d2.length);
	free(d2.data);
    }
    if (d3.data != NULL) {
	memset(d3.data, 0, d3.length);
	free(d3.data);
    }

    return ret;
}