Пример #1
0
isc_result_t
isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target,
		isc_uint32_t algorithm, isccc_region_t *secret)
{
	unsigned char *hmac_rstart, *signed_rstart;
	isc_result_t result;

	if (algorithm == ISCCC_ALG_HMACMD5) {
		if (REGION_SIZE(*target) < 4 + sizeof(auth_hmd5))
			return (ISC_R_NOSPACE);
	} else {
		if (REGION_SIZE(*target) < 4 + sizeof(auth_hsha))
			return (ISC_R_NOSPACE);
	}

	/*
	 * Emit protocol version.
	 */
	PUT32(1, target->rstart);
	if (secret != NULL) {
		/*
		 * Emit _auth section with zeroed HMAC signature.
		 * We'll replace the zeros with the real signature once
		 * we know what it is.
		 */
		if (algorithm == ISCCC_ALG_HMACMD5) {
			hmac_rstart = target->rstart + HMD5_OFFSET;
			PUT_MEM(auth_hmd5, sizeof(auth_hmd5), target->rstart);
		} else {
			unsigned char *hmac_alg;

			hmac_rstart = target->rstart + HSHA_OFFSET;
			hmac_alg = hmac_rstart - 1;
			PUT_MEM(auth_hsha, sizeof(auth_hsha), target->rstart);
			PUT8(algorithm, hmac_alg);
		}
	} else
		hmac_rstart = NULL;
	signed_rstart = target->rstart;
	/*
	 * Delete any existing _auth section so that we don't try
	 * to encode it.
	 */
	isccc_alist_delete(alist, "_auth");
	/*
	 * Emit the message.
	 */
	result = table_towire(alist, target);
	if (result != ISC_R_SUCCESS)
		return (result);
	if (secret != NULL)
		return (sign(signed_rstart,
			     (unsigned int)(target->rstart - signed_rstart),
			     hmac_rstart, algorithm, secret));
	return (ISC_R_SUCCESS);
}
Пример #2
0
static isc_result_t
table_towire(isccc_sexpr_t *alist, isccc_region_t *target)
{
	isccc_sexpr_t *kv, *elt, *k, *v;
	char *ks;
	isc_result_t result;
	size_t len;

	for (elt = isccc_alist_first(alist);
	     elt != NULL;
	     elt = ISCCC_SEXPR_CDR(elt)) {
		kv = ISCCC_SEXPR_CAR(elt);
		k = ISCCC_SEXPR_CAR(kv);
		ks = isccc_sexpr_tostring(k);
		v = ISCCC_SEXPR_CDR(kv);
		len = strlen(ks);
		INSIST(len <= 255U);
		/*
		 * Emit the key name.
		 */
		if (REGION_SIZE(*target) < 1 + len)
			return (ISC_R_NOSPACE);
		PUT8(len, target->rstart);
		PUT_MEM(ks, len, target->rstart);
		/*
		 * Emit the value.
		 */
		result = value_towire(v, target);
		if (result != ISC_R_SUCCESS)
			return (result);
	}

	return (ISC_R_SUCCESS);
}
Пример #3
0
static isc_result_t
sign(unsigned char *data, unsigned int length, unsigned char *hmd5,
     isccc_region_t *secret)
{
	isc_hmacmd5_t ctx;
	isc_result_t result;
	isccc_region_t source, target;
	unsigned char digest[ISC_MD5_DIGESTLENGTH];
	unsigned char digestb64[ISC_MD5_DIGESTLENGTH * 4];

	isc_hmacmd5_init(&ctx, secret->rstart, REGION_SIZE(*secret));
	isc_hmacmd5_update(&ctx, data, length);
	isc_hmacmd5_sign(&ctx, digest);
	source.rstart = digest;
	source.rend = digest + ISC_MD5_DIGESTLENGTH;
	target.rstart = digestb64;
	target.rend = digestb64 + ISC_MD5_DIGESTLENGTH * 4;
	result = isccc_base64_encode(&source, 64, "", &target);
	if (result != ISC_R_SUCCESS)
		return (result);
	PUT_MEM(digestb64, HMD5_LENGTH, hmd5);

	return (ISC_R_SUCCESS);
}
Пример #4
0
static isc_result_t
value_towire(isccc_sexpr_t *elt, isccc_region_t *target)
{
	size_t len;
	unsigned char *lenp;
	isccc_region_t *vr;
	isc_result_t result;

	if (isccc_sexpr_binaryp(elt)) {
		vr = isccc_sexpr_tobinary(elt);
		len = REGION_SIZE(*vr);
		if (REGION_SIZE(*target) < 1 + 4 + len)
			return (ISC_R_NOSPACE);
		PUT8(ISCCC_CCMSGTYPE_BINARYDATA, target->rstart);
		PUT32(len, target->rstart);
		if (REGION_SIZE(*target) < len)
			return (ISC_R_NOSPACE);
		PUT_MEM(vr->rstart, len, target->rstart);
	} else if (isccc_alist_alistp(elt)) {
		if (REGION_SIZE(*target) < 1 + 4)
			return (ISC_R_NOSPACE);
		PUT8(ISCCC_CCMSGTYPE_TABLE, target->rstart);
		/*
		 * Emit a placeholder length.
		 */
		lenp = target->rstart;
		PUT32(0, target->rstart);
		/*
		 * Emit the table.
		 */
		result = table_towire(elt, target);
		if (result != ISC_R_SUCCESS)
			return (result);
		len = (size_t)(target->rstart - lenp);
		/*
		 * 'len' is 4 bytes too big, since it counts
		 * the placeholder length too.  Adjust and
		 * emit.
		 */
		INSIST(len >= 4U);
		len -= 4;
		PUT32(len, lenp);
	} else if (isccc_sexpr_listp(elt)) {
		if (REGION_SIZE(*target) < 1 + 4)
			return (ISC_R_NOSPACE);
		PUT8(ISCCC_CCMSGTYPE_LIST, target->rstart);
		/*
		 * Emit a placeholder length and count.
		 */
		lenp = target->rstart;
		PUT32(0, target->rstart);
		/*
		 * Emit the list.
		 */
		result = list_towire(elt, target);
		if (result != ISC_R_SUCCESS)
			return (result);
		len = (size_t)(target->rstart - lenp);
		/*
		 * 'len' is 4 bytes too big, since it counts
		 * the placeholder length.  Adjust and emit.
		 */
		INSIST(len >= 4U);
		len -= 4;
		PUT32(len, lenp);
	}

	return (ISC_R_SUCCESS);
}
Пример #5
0
static isc_result_t
sign(unsigned char *data, unsigned int length, unsigned char *hmac,
     isc_uint32_t algorithm, isccc_region_t *secret)
{
	union {
		isc_hmacmd5_t hmd5;
		isc_hmacsha1_t hsha;
		isc_hmacsha224_t h224;
		isc_hmacsha256_t h256;
		isc_hmacsha384_t h384;
		isc_hmacsha512_t h512;
	} ctx;
	isc_result_t result;
	isccc_region_t source, target;
	unsigned char digest[ISC_SHA512_DIGESTLENGTH];
	unsigned char digestb64[HSHA_LENGTH + 4];

	source.rstart = digest;

	switch (algorithm) {
	case ISCCC_ALG_HMACMD5:
		isc_hmacmd5_init(&ctx.hmd5, secret->rstart,
				 REGION_SIZE(*secret));
		isc_hmacmd5_update(&ctx.hmd5, data, length);
		isc_hmacmd5_sign(&ctx.hmd5, digest);
		source.rend = digest + ISC_MD5_DIGESTLENGTH;
		break;

	case ISCCC_ALG_HMACSHA1:
		isc_hmacsha1_init(&ctx.hsha, secret->rstart,
				    REGION_SIZE(*secret));
		isc_hmacsha1_update(&ctx.hsha, data, length);
		isc_hmacsha1_sign(&ctx.hsha, digest,
				    ISC_SHA1_DIGESTLENGTH);
		source.rend = digest + ISC_SHA1_DIGESTLENGTH;
		break;

	case ISCCC_ALG_HMACSHA224:
		isc_hmacsha224_init(&ctx.h224, secret->rstart,
				    REGION_SIZE(*secret));
		isc_hmacsha224_update(&ctx.h224, data, length);
		isc_hmacsha224_sign(&ctx.h224, digest,
				    ISC_SHA224_DIGESTLENGTH);
		source.rend = digest + ISC_SHA224_DIGESTLENGTH;
		break;

	case ISCCC_ALG_HMACSHA256:
		isc_hmacsha256_init(&ctx.h256, secret->rstart,
				    REGION_SIZE(*secret));
		isc_hmacsha256_update(&ctx.h256, data, length);
		isc_hmacsha256_sign(&ctx.h256, digest,
				    ISC_SHA256_DIGESTLENGTH);
		source.rend = digest + ISC_SHA256_DIGESTLENGTH;
		break;

	case ISCCC_ALG_HMACSHA384:
		isc_hmacsha384_init(&ctx.h384, secret->rstart,
				    REGION_SIZE(*secret));
		isc_hmacsha384_update(&ctx.h384, data, length);
		isc_hmacsha384_sign(&ctx.h384, digest,
				    ISC_SHA384_DIGESTLENGTH);
		source.rend = digest + ISC_SHA384_DIGESTLENGTH;
		break;

	case ISCCC_ALG_HMACSHA512:
		isc_hmacsha512_init(&ctx.h512, secret->rstart,
				    REGION_SIZE(*secret));
		isc_hmacsha512_update(&ctx.h512, data, length);
		isc_hmacsha512_sign(&ctx.h512, digest,
				    ISC_SHA512_DIGESTLENGTH);
		source.rend = digest + ISC_SHA512_DIGESTLENGTH;
		break;

	default:
		return (ISC_R_FAILURE);
	}

	memset(digestb64, 0, sizeof(digestb64));
	target.rstart = digestb64;
	target.rend = digestb64 + sizeof(digestb64);
	result = isccc_base64_encode(&source, 64, "", &target);
	if (result != ISC_R_SUCCESS)
		return (result);
	if (algorithm == ISCCC_ALG_HMACMD5)
		PUT_MEM(digestb64, HMD5_LENGTH, hmac);
	else
		PUT_MEM(digestb64, HSHA_LENGTH, hmac);
	return (ISC_R_SUCCESS);
}