a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * CDDL HEADER START
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The contents of this file are subject to the terms of the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Common Development and Distribution License (the "License").
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * You may not use this file except in compliance with the License.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * or http://www.opensolaris.org/os/licensing.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * See the License for the specific language governing permissions
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and limitations under the License.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * When distributing Covered Code, include this CDDL HEADER in each
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If applicable, add the following below this CDDL HEADER, with the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * CDDL HEADER END
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * These routines provide the SMB MAC signing for the SMB2 server.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The routines calculate the signature of a SMB message in an mbuf chain.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The following table describes the client server
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * signing registry relationship
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * | Required | Enabled | Disabled
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * -------------+---------------+------------ +--------------
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Required | Signed | Signed | Fail
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * -------------+---------------+-------------+-----------------
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Enabled | Signed | Signed | Not Signed
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * -------------+---------------+-------------+----------------
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Disabled | Fail | Not Signed | Not Signed
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#include <sys/uio.h>
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#include <smbsrv/smb_kproto.h>
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#include <smbsrv/smb_signing.h>
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#include <sys/isa_defs.h>
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#include <sys/byteorder.h>
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#include <sys/cmn_err.h>
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#define SMB2_SIG_OFFS 48
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#define SMB2_SIG_SIZE 16
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Called during session destroy.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic void
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_sign_fini(smb_session_t *s)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_sign_mech_t *mech;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if ((mech = s->sign_mech) != NULL) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross kmem_free(mech, sizeof (*mech));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross s->sign_mech = NULL;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb2_sign_begin
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Get the mechanism info.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Intializes MAC key based on the user session key and store it in
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the signing structure. This begins signing on this session.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossint
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_sign_begin(smb_request_t *sr, smb_token_t *token)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_session_t *s = sr->session;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_user_t *u = sr->uid_user;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross struct smb_key *sign_key = &u->u_sign_key;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_sign_mech_t *mech;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int rc;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * We should normally have a session key here because
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * our caller filters out Anonymous and Guest logons.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * However, buggy clients could get us here without a
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * session key, in which case we'll fail later when a
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * request that requires signing can't be checked.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Session-level initialization (once per session)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Get mech handle, sign_fini function.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_rwx_rwenter(&s->s_lock, RW_WRITER);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (s->sign_mech == NULL) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb2_hmac_getmech(mech);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc != 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross kmem_free(mech, sizeof (*mech));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_rwx_rwexit(&s->s_lock);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (rc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross s->sign_mech = mech;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross s->sign_fini = smb2_sign_fini;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_rwx_rwexit(&s->s_lock);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Compute and store the signing key, which lives in
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the user structure.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sign_key->len = SMB2_SIG_SIZE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * For SMB2, the signing key is just the first 16 bytes
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * of the session key (truncated or padded with zeros).
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * [MS-SMB2] 3.2.5.3.1
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bcopy(token->tkn_ssnkey.val, sign_key->key,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross MIN(token->tkn_ssnkey.len, sign_key->len));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mutex_enter(&u->u_mutex);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (s->secmode & SMB2_NEGOTIATE_SIGNING_ENABLED)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross u->u_sign_flags |= SMB_SIGNING_ENABLED;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (s->secmode & SMB2_NEGOTIATE_SIGNING_REQUIRED)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross u->u_sign_flags |=
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross SMB_SIGNING_ENABLED | SMB_SIGNING_CHECK;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mutex_exit(&u->u_mutex);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If we just turned on signing, the current request
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * (an SMB2 session setup) will have come in without
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB2_FLAGS_SIGNED (and not signed) but the response
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * is is supposed to be signed. [MS-SMB2] 3.3.5.5
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (u->u_sign_flags & SMB_SIGNING_ENABLED)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->smb2_hdr_flags |= SMB2_FLAGS_SIGNED;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb2_sign_calc
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Calculates MAC signature for the given buffer and returns
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * it in the mac_sign parameter.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The signature is in the last 16 bytes of the SMB2 header.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The signature algorighm is to compute HMAC SHA256 over the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * entire command, with the signature field set to zeros.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Return 0 if success else -1
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic int
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint8_t *digest)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint8_t tmp_hdr[SMB2_HDR_SIZE];
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_sign_ctx_t ctx = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_session_t *s = sr->session;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_user_t *u = sr->uid_user;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross struct smb_key *sign_key = &u->u_sign_key;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross struct mbuf *mbuf;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int offset, resid, tlen, rc;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (s->sign_mech == NULL || sign_key->len == 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb2_hmac_init(&ctx, s->sign_mech, sign_key->key, sign_key->len);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (rc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Work with a copy of the SMB2 header so we can
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * clear the signature field without modifying
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the original message.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross tlen = SMB2_HDR_SIZE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross offset = mbc->chain_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resid = mbc->max_bytes - offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bzero(tmp_hdr + SMB2_SIG_OFFS, SMB2_SIG_SIZE);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if ((rc = smb2_hmac_update(ctx, tmp_hdr, tlen)) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (rc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross offset += tlen;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resid -= tlen;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Digest the rest of the SMB packet, starting at the data
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * just after the SMB header.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Advance to the src mbuf where we start digesting.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mbuf = mbc->chain;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross while (mbuf != NULL && (offset >= mbuf->m_len)) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross offset -= mbuf->m_len;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mbuf = mbuf->m_next;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (mbuf == NULL)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Digest the remainder of this mbuf, limited to the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * residual count, and starting at the current offset.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * (typically SMB2_HDR_SIZE)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross tlen = mbuf->m_len - offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (tlen > resid)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross tlen = resid;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb2_hmac_update(ctx, (uint8_t *)mbuf->m_data + offset, tlen);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (rc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resid -= tlen;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Digest any more mbufs in the chain.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross while (resid > 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mbuf = mbuf->m_next;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (mbuf == NULL)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross tlen = mbuf->m_len;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (tlen > resid)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross tlen = resid;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb2_hmac_update(ctx, (uint8_t *)mbuf->m_data, tlen);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (rc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross resid -= tlen;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Note: digest is _always_ SMB2_SIG_SIZE,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * even if the mech uses a longer one.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if ((rc = smb2_hmac_final(ctx, digest)) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (rc);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb2_sign_check_request
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Calculates MAC signature for the request mbuf chain
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * using the next expected sequence number and compares
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * it to the given signature.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Note it does not check the signature for secondary transactions
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * as their sequence number is the same as the original request.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Return 0 if the signature verifies, otherwise, returns -1;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossint
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_sign_check_request(smb_request_t *sr)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint8_t req_sig[SMB2_SIG_SIZE];
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint8_t vfy_sig[SMB2_SIG_SIZE];
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross struct mbuf_chain *mbc = &sr->smb_data;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_user_t *u = sr->uid_user;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int sig_off;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Don't check commands with a zero session ID.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * [MS-SMB2] 3.3.4.1.1
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (sr->smb_uid == 0 || u == NULL)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* Get the request signature. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sig_off = sr->smb2_cmd_hdr + SMB2_SIG_OFFS;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_mbc_peek(mbc, sig_off, "#c", SMB2_SIG_SIZE, req_sig) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Compute the correct signature and compare.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb2_sign_calc(sr, mbc, vfy_sig) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (memcmp(vfy_sig, req_sig, SMB2_SIG_SIZE) != 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross cmn_err(CE_NOTE, "smb2_sign_check_request: bad signature");
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (0);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb2_sign_reply
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Calculates MAC signature for the given mbuf chain,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and write it to the signature field in the mbuf.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossvoid
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_sign_reply(smb_request_t *sr)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint8_t reply_sig[SMB2_SIG_SIZE];
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross struct mbuf_chain tmp_mbc;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_user_t *u = sr->uid_user;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int hdr_off, msg_len;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (u == NULL)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross msg_len = sr->reply.chain_offset - sr->smb2_reply_hdr;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) MBC_SHADOW_CHAIN(&tmp_mbc, &sr->reply,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->smb2_reply_hdr, msg_len);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Calculate the MAC signature for this reply.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb2_sign_calc(sr, &tmp_mbc, reply_sig) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Poke the signature into the response.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross hdr_off = sr->smb2_reply_hdr + SMB2_SIG_OFFS;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_poke(&sr->reply, hdr_off, "#c",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross SMB2_SIG_SIZE, reply_sig);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}