예제 #1
0
파일: t_hmac.c 프로젝트: aosm/Kerberos
static krb5_error_code hmac1(const struct krb5_hash_provider *h, 
			     krb5_keyblock *key,
			     krb5_data *in, krb5_data *out)
{
    char tmp[40];
    size_t blocksize, hashsize;
    krb5_error_code err;

    printk(" test key", key);
    blocksize = h->blocksize;
    hashsize = h->hashsize;
    if (hashsize > sizeof(tmp))
	abort();
    if (key->length > blocksize) {
	krb5_data d, d2;
	d.data = (char *) key->contents;
	d.length = key->length;
	d2.data = tmp;
	d2.length = hashsize;
	err = h->hash (1, &d, &d2);
	if (err) {
	    com_err(whoami, err, "hashing key before calling hmac");
	    exit(1);
	}
	key->length = d2.length;
	key->contents = (krb5_octet *) d2.data;
	printk(" pre-hashed key", key);
    }
    printd(" hmac input", in);
    err = krb5_hmac(h, key, 1, in, out);
    if (err == 0)
	printd(" hmac output", out);
    return err;
}
예제 #2
0
static krb5_error_code
arcfour_mic_key(krb5_context context, krb5_keyblock *key,
		void *cksum_data, size_t cksum_size,
		void *key6_data, size_t key6_size)
{
    krb5_error_code ret;

    Checksum cksum_k5;
    krb5_keyblock key5;
    char k5_data[16];

    Checksum cksum_k6;

    char T[4];

    memset(T, 0, 4);
    cksum_k5.checksum.data = k5_data;
    cksum_k5.checksum.length = sizeof(k5_data);

    if (key->keytype == KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56) {
	char L40[14] = "fortybits";

	memcpy(L40 + 10, T, sizeof(T));
	ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
			L40, 14, 0, key, &cksum_k5);
	memset(&k5_data[7], 0xAB, 9);
    } else {
	ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
			T, 4, 0, key, &cksum_k5);
    }
    if (ret)
	return ret;

    key5.keytype = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5;
    key5.keyvalue = cksum_k5.checksum;

    cksum_k6.checksum.data = key6_data;
    cksum_k6.checksum.length = key6_size;

    return krb5_hmac(context, CKSUMTYPE_RSA_MD5,
		     cksum_data, cksum_size, 0, &key5, &cksum_k6);
}
예제 #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);
}
예제 #4
0
krb5_error_code
krb5_dk_make_checksum(const struct krb5_hash_provider *hash,
		      const krb5_keyblock *key, krb5_keyusage usage,
		      const krb5_data *input, krb5_data *output)
{
    int i;
    const struct krb5_enc_provider *enc;
    size_t blocksize, keybytes, keylength;
    krb5_error_code ret;
    unsigned char constantdata[K5CLENGTH];
    krb5_data datain;
    unsigned char *kcdata;
    krb5_keyblock kc;

    for (i=0; i<krb5_enctypes_length; i++) {
	if (krb5_enctypes_list[i].etype == key->enctype)
	    break;
    }

    if (i == krb5_enctypes_length)
	return(KRB5_BAD_ENCTYPE);

    enc = krb5_enctypes_list[i].enc;

    /* allocate and set to-be-derived keys */

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

    /* key->length will be tested in enc->encrypt
       output->length will be tested in krb5_hmac */

    if ((kcdata = (unsigned char *) malloc(keylength)) == NULL)
	return(ENOMEM);

    kc.contents = kcdata;
    kc.length = keylength;

    /* derive the key */
 
    datain.data = (char *) constantdata;
    datain.length = K5CLENGTH;

    store_32_be(usage, constantdata);

    datain.data[4] = (char) 0x99;

    if ((ret = krb5_derive_key(enc, key, &kc, &datain)) != 0)
	goto cleanup;

    /* hash the data */

    datain = *input;

    if ((ret = krb5_hmac(hash, &kc, 1, &datain, output)) != 0)
	memset(output->data, 0, output->length);

    /* ret is set correctly by the prior call */

cleanup:
    memset(kcdata, 0, keylength);

    free(kcdata);

    return(ret);
}
예제 #5
0
static krb5_error_code
krb5_dk_decrypt_maybe_trunc_hmac(
				 krb5_context context,
				 const struct krb5_enc_provider *enc,
				 const struct krb5_hash_provider *hash,
				 const krb5_keyblock *key, krb5_keyusage usage,
				 const krb5_data *ivec, const krb5_data *input,
				 krb5_data *output, size_t hmacsize)
{
    krb5_error_code ret;
    size_t hashsize, blocksize, enclen, plainlen;
    unsigned char *plaindata = NULL, *cksum = NULL, *cn;
    krb5_data d1, d2;
    krb5_keyblock *derived_encr_key = NULL;
    krb5_keyblock *derived_hmac_key = NULL;

    KRB5_LOG0(KRB5_INFO, "krb5_dk_decrypt() start\n");

    /*
     * Derive the encryption and hmac keys.
     * This routine is optimized to fetch the DK
     * from the original key's DK list.
     */
    ret = init_derived_keydata(context, enc,
			    (krb5_keyblock *)key,
			    usage,
			    &derived_encr_key,
			    &derived_hmac_key);
    if (ret)
	    return (ret);

    hashsize = hash->hashsize;
    blocksize = enc->block_size;

    if (hmacsize == 0)
	hmacsize = hashsize;
    else if (hmacsize > hashsize)
	return (KRB5KRB_AP_ERR_BAD_INTEGRITY);

    enclen = input->length - hmacsize;

    if ((plaindata = (unsigned char *) MALLOC(enclen)) == NULL) {
	    ret = ENOMEM;
	    goto cleanup;
    }

    /* decrypt the ciphertext */

    d1.length = enclen;
    d1.data = input->data;

    d2.length = enclen;
    d2.data = (char *) plaindata;

    if ((ret = ((*(enc->decrypt))(context, derived_encr_key,
			ivec, &d1, &d2))) != 0)
	goto cleanup;

    if (ivec != NULL && ivec->length == blocksize) {
	cn = (unsigned char *) d1.data + d1.length - blocksize;
    } else {
	cn = NULL;
    }

    /* verify the hash */

    if ((cksum = (unsigned char *) MALLOC(hashsize)) == NULL) {
	    ret = ENOMEM;
	    goto cleanup;
    }
    d1.length = hashsize;
    d1.data = (char *) cksum;

#ifdef _KERNEL
    if ((ret = krb5_hmac(context, derived_hmac_key, &d2, &d1)) != 0)
	goto cleanup;
#else
    if ((ret = krb5_hmac(context, hash, derived_hmac_key,
			1, &d2, &d1)) != 0)
	goto cleanup;
#endif /* _KERNEL */

    if (memcmp(cksum, input->data+enclen, hmacsize) != 0) {
	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
	goto cleanup;
    }

    /* because this encoding isn't self-describing wrt length, the
       best we can do here is to compute the length minus the
       confounder. */

    plainlen = enclen - blocksize;

    if (output->length < plainlen) {
	ret = KRB5_BAD_MSIZE;
	goto cleanup;
    }

    output->length = plainlen;

    (void) memcpy(output->data, d2.data+blocksize, output->length);

    /*
     * AES crypto updates the ivec differently, it is handled
     * in the AES crypto routines directly.
     */
    if (cn != NULL &&
	key->enctype != ENCTYPE_AES128_CTS_HMAC_SHA1_96 &&
	key->enctype != ENCTYPE_AES256_CTS_HMAC_SHA1_96) {
	(void) memcpy(ivec->data, cn, blocksize);
    }

    ret = 0;

cleanup:
    if (plaindata) {
	    (void) memset(plaindata, 0, enclen);
	    FREE(plaindata, enclen);
    }
    if (cksum) {
	    (void) memset(cksum, 0, hashsize);
	    FREE(cksum, hashsize);
    }

    KRB5_LOG(KRB5_INFO, "krb5_dk_decrypt() end, ret=%d\n", ret);
    return(ret);
}
예제 #6
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;
}
예제 #7
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;
}