a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * See the License for the specific language governing permissions
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and limitations under the License.
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 * CDDL HEADER END
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 * 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 * The following table describes the client server
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * signing registry relationship
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 * Called during session destroy.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb2_sign_begin
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 Rosssmb2_sign_begin(smb_request_t *sr, smb_token_t *token)
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 if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Session-level initialization (once per session)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Get mech handle, sign_fini function.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Compute and store the signing key, which lives in
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the user structure.
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 if (s->secmode & SMB2_NEGOTIATE_SIGNING_ENABLED)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (s->secmode & SMB2_NEGOTIATE_SIGNING_REQUIRED)
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 * smb2_sign_calc
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Calculates MAC signature for the given buffer and returns
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * it in the mac_sign parameter.
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 * Return 0 if success else -1
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb2_hmac_init(&ctx, s->sign_mech, sign_key->key, sign_key->len);
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 if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if ((rc = smb2_hmac_update(ctx, tmp_hdr, tlen)) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Digest the rest of the SMB packet, starting at the data
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * just after the SMB header.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Advance to the src mbuf where we start digesting.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross while (mbuf != NULL && (offset >= mbuf->m_len)) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
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 rc = smb2_hmac_update(ctx, (uint8_t *)mbuf->m_data + offset, tlen);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Digest any more mbufs in the chain.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross while (resid > 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb2_hmac_update(ctx, (uint8_t *)mbuf->m_data, tlen);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Note: digest is _always_ SMB2_SIG_SIZE,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * even if the mech uses a longer one.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb2_sign_check_request
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 * 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 * Return 0 if the signature verifies, otherwise, returns -1;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Don't check commands with a zero session ID.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * [MS-SMB2] 3.3.4.1.1
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* Get the request signature. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb_mbc_peek(mbc, sig_off, "#c", SMB2_SIG_SIZE, req_sig) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (-1);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Compute the correct signature and compare.
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 * smb2_sign_reply
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Calculates MAC signature for the given mbuf chain,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * and write it to the signature field in the mbuf.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross msg_len = sr->reply.chain_offset - sr->smb2_reply_hdr;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Calculate the MAC signature for this reply.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (smb2_sign_calc(sr, &tmp_mbc, reply_sig) != 0)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Poke the signature into the response.