示例#1
0
/*
 * smb2_sign_check_request
 *
 * Calculates MAC signature for the request mbuf chain
 * using the next expected sequence number and compares
 * it to the given signature.
 *
 * Note it does not check the signature for secondary transactions
 * as their sequence number is the same as the original request.
 *
 * Return 0 if the signature verifies, otherwise, returns -1;
 *
 */
int
smb2_sign_check_request(smb_request_t *sr)
{
	uint8_t req_sig[SMB2_SIG_SIZE];
	uint8_t digest[SHA256_DIGEST_LENGTH];
	struct mbuf_chain *mbc = &sr->smb_data;
	struct smb_sign *sign = &sr->session->signing;
	int sig_off;

	/*
	 * Don't check commands with a zero session ID.
	 * [MS-SMB2] 3.3.4.1.1
	 */
	if (sr->smb_uid == 0)
		return (0);

	/* Get the request signature. */
	sig_off = sr->smb2_cmd_hdr + SMB2_SIG_OFFS;
	if (smb_mbc_peek(mbc, sig_off, "#c", SMB2_SIG_SIZE, req_sig) != 0)
		return (-1);

	/* Compute what we think it should be. */
	if (smb2_sign_calc(mbc, sign, digest) != 0)
		return (-1);

	if (memcmp(digest, req_sig, SMB2_SIG_SIZE) != 0) {
		cmn_err(CE_NOTE, "smb2_sign_check_request: bad signature");
		return (-1);
	}

	return (0);
}
示例#2
0
/*
 * smb2_sign_check_request
 *
 * Calculates MAC signature for the request mbuf chain
 * using the next expected sequence number and compares
 * it to the given signature.
 *
 * Note it does not check the signature for secondary transactions
 * as their sequence number is the same as the original request.
 *
 * Return 0 if the signature verifies, otherwise, returns -1;
 *
 */
int
smb2_sign_check_request(smb_request_t *sr)
{
	uint8_t req_sig[SMB2_SIG_SIZE];
	uint8_t vfy_sig[SMB2_SIG_SIZE];
	struct mbuf_chain *mbc = &sr->smb_data;
	smb_session_t *s = sr->session;
	smb_user_t *u = sr->uid_user;
	int sig_off;

	/*
	 * Don't check commands with a zero session ID.
	 * [MS-SMB2] 3.3.4.1.1
	 */
	if (sr->smb_uid == 0 || u == NULL)
		return (0);

	/* In case _sign_begin failed. */
	if (s->sign_calc == NULL)
		return (-1);

	/* Get the request signature. */
	sig_off = sr->smb2_cmd_hdr + SMB2_SIG_OFFS;
	if (smb_mbc_peek(mbc, sig_off, "#c", SMB2_SIG_SIZE, req_sig) != 0)
		return (-1);

	/*
	 * Compute the correct signature and compare.
	 * smb2_sign_calc() or smb3_sign_calc()
	 */
	if (s->sign_calc(sr, mbc, vfy_sig) != 0)
		return (-1);
	if (memcmp(vfy_sig, req_sig, SMB2_SIG_SIZE) != 0) {
		cmn_err(CE_NOTE, "smb2_sign_check_request: bad signature");
		return (-1);
	}

	return (0);
}
示例#3
0
static int
smb2_sign_calc_common(smb_request_t *sr, struct mbuf_chain *mbc,
    uint8_t *digest, mac_ops_t *ops)
{
	uint8_t tmp_hdr[SMB2_HDR_SIZE];
	smb_sign_ctx_t ctx = 0;
	smb_session_t *s = sr->session;
	smb_user_t *u = sr->uid_user;
	struct smb_key *sign_key = &u->u_sign_key;
	struct mbuf *mbuf;
	int offset, resid, tlen, rc;

	if (s->sign_mech == NULL || sign_key->len == 0)
		return (-1);

	/* smb2_hmac_init or smb3_cmac_init */
	rc = ops->mac_init(&ctx, s->sign_mech, sign_key->key, sign_key->len);
	if (rc != 0)
		return (rc);

	/*
	 * Work with a copy of the SMB2 header so we can
	 * clear the signature field without modifying
	 * the original message.
	 */
	tlen = SMB2_HDR_SIZE;
	offset = mbc->chain_offset;
	resid = mbc->max_bytes - offset;
	if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0)
		return (-1);
	bzero(tmp_hdr + SMB2_SIG_OFFS, SMB2_SIG_SIZE);
	/* smb2_hmac_update or smb3_cmac_update */
	if ((rc = ops->mac_update(ctx, tmp_hdr, tlen)) != 0)
		return (rc);
	offset += tlen;
	resid -= tlen;

	/*
	 * Digest the rest of the SMB packet, starting at the data
	 * just after the SMB header.
	 *
	 * Advance to the src mbuf where we start digesting.
	 */
	mbuf = mbc->chain;
	while (mbuf != NULL && (offset >= mbuf->m_len)) {
		offset -= mbuf->m_len;
		mbuf = mbuf->m_next;
	}

	if (mbuf == NULL)
		return (-1);

	/*
	 * Digest the remainder of this mbuf, limited to the
	 * residual count, and starting at the current offset.
	 * (typically SMB2_HDR_SIZE)
	 */
	tlen = mbuf->m_len - offset;
	if (tlen > resid)
		tlen = resid;
	/* smb2_hmac_update or smb3_cmac_update */
	rc = ops->mac_update(ctx, (uint8_t *)mbuf->m_data + offset, tlen);
	if (rc != 0)
		return (rc);
	resid -= tlen;

	/*
	 * Digest any more mbufs in the chain.
	 */
	while (resid > 0) {
		mbuf = mbuf->m_next;
		if (mbuf == NULL)
			return (-1);
		tlen = mbuf->m_len;
		if (tlen > resid)
			tlen = resid;
		rc = ops->mac_update(ctx, (uint8_t *)mbuf->m_data, tlen);
		if (rc != 0)
			return (rc);
		resid -= tlen;
	}

	/*
	 * smb2_hmac_final or smb3_cmac_final
	 * Note: digest is _always_ SMB2_SIG_SIZE,
	 * even if the mech uses a longer one.
	 *
	 * smb2_hmac_update or smb3_cmac_update
	 */
	if ((rc = ops->mac_final(ctx, digest)) != 0)
		return (rc);

	return (0);
}
示例#4
0
/*
 * smb2_sign_calc
 *
 * Calculates MAC signature for the given buffer and returns
 * it in the mac_sign parameter.
 *
 * The sequence number is in the last 16 bytes of the SMB2 header.
 * The signature algorighm is to compute HMAC SHA256 over the
 * entire command, with the signature field set to zeros.
 *
 * Return 0 if  success else -1
 */
int
smb2_sign_calc(struct mbuf_chain *mbc,
    struct smb_sign *sign,
    uint8_t *digest)
{
	sha2_hc_ctx_t hctx;
	uint8_t tmp_hdr[SMB2_HDR_SIZE];
	struct mbuf *mbuf;
	int offset = mbc->chain_offset;
	int resid = mbc->max_bytes - offset;
	int tlen;

	if (sign->mackey == NULL)
		return (-1);

	bzero(&hctx, sizeof (hctx));
	if (smb2_hmac_sha256_init(&hctx, sign->mackey, sign->mackey_len))
		return (-1);

	/*
	 * Work with a copy of the SMB2 header so we can
	 * clear the signature field without modifying
	 * the original message.
	 */
	tlen = SMB2_HDR_SIZE;
	if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0)
		return (-1);
	bzero(tmp_hdr + SMB2_SIG_OFFS, SMB2_SIG_SIZE);
	smb2_hmac_sha256_update(&hctx, tmp_hdr, tlen);
	offset += tlen;
	resid -= tlen;

	/*
	 * Digest the rest of the SMB packet, starting at the data
	 * just after the SMB header.
	 *
	 * Advance to the src mbuf where we start digesting.
	 */
	mbuf = mbc->chain;
	while (mbuf != NULL && (offset >= mbuf->m_len)) {
		offset -= mbuf->m_len;
		mbuf = mbuf->m_next;
	}

	if (mbuf == NULL)
		return (-1);

	/*
	 * Digest the remainder of this mbuf, limited to the
	 * residual count, and starting at the current offset.
	 * (typically SMB2_HDR_SIZE)
	 */
	tlen = mbuf->m_len - offset;
	if (tlen > resid)
		tlen = resid;
	smb2_hmac_sha256_update(&hctx, (uint8_t *)mbuf->m_data + offset, tlen);
	resid -= tlen;

	/*
	 * Digest any more mbufs in the chain.
	 */
	while (resid > 0) {
		mbuf = mbuf->m_next;
		if (mbuf == NULL)
			return (-1);
		tlen = mbuf->m_len;
		if (tlen > resid)
			tlen = resid;
		smb2_hmac_sha256_update(&hctx, (uint8_t *)mbuf->m_data, tlen);
		resid -= tlen;
	}

	smb2_hmac_sha256_final(&hctx, digest);
	return (0);
}