1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24  * Copyright 2020 RackTop Systems, Inc.
  25  */
  26 /*
  27  * These routines provide the SMB MAC signing for the SMB2 server.
  28  * The routines calculate the signature of a SMB message in an mbuf chain.
  29  *
  30  * The following table describes the client server
  31  * signing registry relationship
  32  *
  33  *              | Required      | Enabled     | Disabled
  34  * -------------+---------------+------------ +--------------
  35  * Required     | Signed        | Signed      | Fail
  36  * -------------+---------------+-------------+-----------------
  37  * Enabled      | Signed        | Signed      | Not Signed
  38  * -------------+---------------+-------------+----------------
  39  * Disabled     | Fail          | Not Signed  | Not Signed
  40  */
  41 
  42 #include <sys/uio.h>
  43 #include <smbsrv/smb2_kproto.h>
  44 #include <smbsrv/smb_kcrypt.h>
  45 #include <sys/isa_defs.h>
  46 #include <sys/byteorder.h>
  47 #include <sys/cmn_err.h>
  48 
  49 #define SMB2_SIG_OFFS   48
  50 #define SMB2_SIG_SIZE   16
  51 
  52 typedef struct mac_ops {
  53         int (*mac_init)(smb_sign_ctx_t *, smb_crypto_mech_t *,
  54                         uint8_t *, size_t);
  55         int (*mac_update)(smb_sign_ctx_t, uint8_t *, size_t);
  56         int (*mac_final)(smb_sign_ctx_t, uint8_t *);
  57 } mac_ops_t;
  58 
  59 static int smb2_sign_calc_common(smb_request_t *, struct mbuf_chain *,
  60     uint8_t *, mac_ops_t *);
  61 
  62 /*
  63  * SMB2 wrapper functions
  64  */
  65 
  66 static mac_ops_t
  67 smb2_sign_ops = {
  68         smb2_hmac_init,
  69         smb2_hmac_update,
  70         smb2_hmac_final
  71 };
  72 
  73 static int
  74 smb2_sign_calc(smb_request_t *sr,
  75     struct mbuf_chain *mbc,
  76     uint8_t *digest16)
  77 {
  78         int rv;
  79 
  80         rv = smb2_sign_calc_common(sr, mbc, digest16, &smb2_sign_ops);
  81 
  82         return (rv);
  83 }
  84 
  85 /*
  86  * Called during session destroy.
  87  */
  88 static void
  89 smb2_sign_fini(smb_session_t *s)
  90 {
  91         smb_crypto_mech_t *mech;
  92 
  93         if ((mech = s->sign_mech) != NULL) {
  94                 kmem_free(mech, sizeof (*mech));
  95                 s->sign_mech = NULL;
  96         }
  97 }
  98 
  99 /*
 100  * SMB3 wrapper functions
 101  */
 102 
 103 static struct mac_ops
 104 smb3_sign_ops = {
 105         smb3_cmac_init,
 106         smb3_cmac_update,
 107         smb3_cmac_final
 108 };
 109 
 110 static int
 111 smb3_sign_calc(smb_request_t *sr,
 112     struct mbuf_chain *mbc,
 113     uint8_t *digest16)
 114 {
 115         int rv;
 116 
 117         rv = smb2_sign_calc_common(sr, mbc, digest16, &smb3_sign_ops);
 118 
 119         return (rv);
 120 }
 121 
 122 void
 123 smb2_sign_init_mech(smb_session_t *s)
 124 {
 125         smb_crypto_mech_t *mech;
 126         int (*get_mech)(smb_crypto_mech_t *);
 127         int (*sign_calc)(smb_request_t *, struct mbuf_chain *, uint8_t *);
 128         int rc;
 129 
 130         if (s->sign_mech != NULL)
 131                 return;
 132 
 133         if (s->dialect >= SMB_VERS_3_0) {
 134                 get_mech = smb3_cmac_getmech;
 135                 sign_calc = smb3_sign_calc;
 136         } else {
 137                 get_mech = smb2_hmac_getmech;
 138                 sign_calc = smb2_sign_calc;
 139         }
 140 
 141         mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
 142         rc = get_mech(mech);
 143         if (rc != 0) {
 144                 kmem_free(mech, sizeof (*mech));
 145                 return;
 146         }
 147         s->sign_mech = mech;
 148         s->sign_calc = sign_calc;
 149         s->sign_fini = smb2_sign_fini;
 150 }
 151 
 152 /*
 153  * smb2_sign_begin
 154  * Handles both SMB2 & SMB3
 155  *
 156  * Get the mechanism info.
 157  * Intializes MAC key based on the user session key and store it in
 158  * the signing structure.  This begins signing on this session.
 159  */
 160 void
 161 smb2_sign_begin(smb_request_t *sr, smb_token_t *token)
 162 {
 163         smb_session_t *s = sr->session;
 164         smb_user_t *u = sr->uid_user;
 165         struct smb_key *sign_key = &u->u_sign_key;
 166 
 167         sign_key->len = 0;
 168 
 169         /*
 170          * We should normally have a session key here because
 171          * our caller filters out Anonymous and Guest logons.
 172          * However, buggy clients could get us here without a
 173          * session key, in which case we'll fail later when a
 174          * request that requires signing can't be checked.
 175          * Also, don't bother initializing if we don't have a mechanism.
 176          */
 177         if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0 ||
 178             s->sign_mech == NULL)
 179                 return;
 180 
 181         /*
 182          * Compute and store the signing key, which lives in
 183          * the user structure.
 184          */
 185         if (s->dialect >= SMB_VERS_3_0) {
 186                 /*
 187                  * For SMB3, the signing key is a "KDF" hash of the
 188                  * session key.
 189                  */
 190                 if (s->dialect >= SMB_VERS_3_11) {
 191                         if (smb3_kdf(sign_key->key,
 192                             token->tkn_ssnkey.val, token->tkn_ssnkey.len,
 193                             (uint8_t *)"SMBSigningKey", 14,
 194                             s->smb31_preauth_hashval, SHA512_DIGEST_LENGTH)
 195                             != 0)
 196                                 return;
 197                 } else {
 198                         if (smb3_kdf(sign_key->key,
 199                             token->tkn_ssnkey.val, token->tkn_ssnkey.len,
 200                             (uint8_t *)"SMB2AESCMAC", 12,
 201                             (uint8_t *)"SmbSign", 8)
 202                             != 0)
 203                                 return;
 204                 }
 205                 sign_key->len = SMB3_KEYLEN;
 206         } else {
 207                 /*
 208                  * For SMB2, the signing key is just the first 16 bytes
 209                  * of the session key (truncated or padded with zeros).
 210                  * [MS-SMB2] 3.2.5.3.1
 211                  */
 212                 sign_key->len = SMB2_KEYLEN;
 213                 bcopy(token->tkn_ssnkey.val, sign_key->key,
 214                     MIN(token->tkn_ssnkey.len, sign_key->len));
 215         }
 216 
 217         mutex_enter(&u->u_mutex);
 218         if ((s->srv_secmode & SMB2_NEGOTIATE_SIGNING_ENABLED) != 0)
 219                 u->u_sign_flags |= SMB_SIGNING_ENABLED;
 220         if ((s->srv_secmode & SMB2_NEGOTIATE_SIGNING_REQUIRED) != 0 ||
 221             (s->cli_secmode & SMB2_NEGOTIATE_SIGNING_REQUIRED) != 0)
 222                 u->u_sign_flags |=
 223                     SMB_SIGNING_ENABLED | SMB_SIGNING_CHECK;
 224         mutex_exit(&u->u_mutex);
 225 
 226         /*
 227          * If we just turned on signing, the current request
 228          * (an SMB2 session setup) will have come in without
 229          * SMB2_FLAGS_SIGNED (and not signed) but the response
 230          * is is supposed to be signed. [MS-SMB2] 3.3.5.5
 231          */
 232         if (u->u_sign_flags & SMB_SIGNING_ENABLED)
 233                 sr->smb2_hdr_flags |= SMB2_FLAGS_SIGNED;
 234 }
 235 
 236 /*
 237  * smb2_sign_calc_common
 238  *
 239  * Calculates MAC signature for the given buffer and returns
 240  * it in the mac_sign parameter.
 241  *
 242  * The signature algorithm is to compute HMAC SHA256 or AES_CMAC
 243  * over the entire command, with the signature field set to zeros.
 244  *
 245  * Return 0 if  success else -1
 246  */
 247 
 248 static int
 249 smb2_sign_calc_common(smb_request_t *sr, struct mbuf_chain *mbc,
 250     uint8_t *digest, mac_ops_t *ops)
 251 {
 252         uint8_t tmp_hdr[SMB2_HDR_SIZE];
 253         smb_sign_ctx_t ctx = 0;
 254         smb_session_t *s = sr->session;
 255         smb_user_t *u = sr->uid_user;
 256         struct smb_key *sign_key = &u->u_sign_key;
 257         struct mbuf *mbuf;
 258         int offset, resid, tlen, rc;
 259 
 260         if (s->sign_mech == NULL || sign_key->len == 0)
 261                 return (-1);
 262 
 263         /* smb2_hmac_init or smb3_cmac_init */
 264         rc = ops->mac_init(&ctx, s->sign_mech, sign_key->key, sign_key->len);
 265         if (rc != 0)
 266                 return (rc);
 267 
 268         /*
 269          * Work with a copy of the SMB2 header so we can
 270          * clear the signature field without modifying
 271          * the original message.
 272          */
 273         tlen = SMB2_HDR_SIZE;
 274         offset = mbc->chain_offset;
 275         resid = mbc->max_bytes - offset;
 276         if (smb_mbc_peek(mbc, offset, "#c", tlen, tmp_hdr) != 0)
 277                 return (-1);
 278         bzero(tmp_hdr + SMB2_SIG_OFFS, SMB2_SIG_SIZE);
 279         /* smb2_hmac_update or smb3_cmac_update */
 280         if ((rc = ops->mac_update(ctx, tmp_hdr, tlen)) != 0)
 281                 return (rc);
 282         offset += tlen;
 283         resid -= tlen;
 284 
 285         /*
 286          * Digest the rest of the SMB packet, starting at the data
 287          * just after the SMB header.
 288          *
 289          * Advance to the src mbuf where we start digesting.
 290          */
 291         mbuf = mbc->chain;
 292         while (mbuf != NULL && (offset >= mbuf->m_len)) {
 293                 offset -= mbuf->m_len;
 294                 mbuf = mbuf->m_next;
 295         }
 296 
 297         if (mbuf == NULL)
 298                 return (-1);
 299 
 300         /*
 301          * Digest the remainder of this mbuf, limited to the
 302          * residual count, and starting at the current offset.
 303          * (typically SMB2_HDR_SIZE)
 304          */
 305         tlen = mbuf->m_len - offset;
 306         if (tlen > resid)
 307                 tlen = resid;
 308         /* smb2_hmac_update or smb3_cmac_update */
 309         rc = ops->mac_update(ctx, (uint8_t *)mbuf->m_data + offset, tlen);
 310         if (rc != 0)
 311                 return (rc);
 312         resid -= tlen;
 313 
 314         /*
 315          * Digest any more mbufs in the chain.
 316          */
 317         while (resid > 0) {
 318                 mbuf = mbuf->m_next;
 319                 if (mbuf == NULL)
 320                         return (-1);
 321                 tlen = mbuf->m_len;
 322                 if (tlen > resid)
 323                         tlen = resid;
 324                 rc = ops->mac_update(ctx, (uint8_t *)mbuf->m_data, tlen);
 325                 if (rc != 0)
 326                         return (rc);
 327                 resid -= tlen;
 328         }
 329 
 330         /*
 331          * smb2_hmac_final or smb3_cmac_final
 332          * Note: digest is _always_ SMB2_SIG_SIZE,
 333          * even if the mech uses a longer one.
 334          *
 335          * smb2_hmac_update or smb3_cmac_update
 336          */
 337         if ((rc = ops->mac_final(ctx, digest)) != 0)
 338                 return (rc);
 339 
 340         return (0);
 341 }
 342 
 343 /*
 344  * smb2_sign_check_request
 345  *
 346  * Calculates MAC signature for the request mbuf chain
 347  * using the next expected sequence number and compares
 348  * it to the given signature.
 349  *
 350  * Note it does not check the signature for secondary transactions
 351  * as their sequence number is the same as the original request.
 352  *
 353  * Return 0 if the signature verifies, otherwise, returns -1;
 354  *
 355  */
 356 int
 357 smb2_sign_check_request(smb_request_t *sr)
 358 {
 359         uint8_t req_sig[SMB2_SIG_SIZE];
 360         uint8_t vfy_sig[SMB2_SIG_SIZE];
 361         struct mbuf_chain *mbc = &sr->smb_data;
 362         smb_session_t *s = sr->session;
 363         smb_user_t *u = sr->uid_user;
 364         int sig_off;
 365 
 366         /*
 367          * Don't check commands with a zero session ID.
 368          * [MS-SMB2] 3.3.4.1.1
 369          */
 370         if (sr->smb2_ssnid == 0 || u == NULL)
 371                 return (0);
 372 
 373         /* In case _sign_begin failed. */
 374         if (s->sign_calc == NULL)
 375                 return (-1);
 376 
 377         /* Get the request signature. */
 378         sig_off = sr->smb2_cmd_hdr + SMB2_SIG_OFFS;
 379         if (smb_mbc_peek(mbc, sig_off, "#c", SMB2_SIG_SIZE, req_sig) != 0)
 380                 return (-1);
 381 
 382         /*
 383          * Compute the correct signature and compare.
 384          * smb2_sign_calc() or smb3_sign_calc()
 385          */
 386         if (s->sign_calc(sr, mbc, vfy_sig) != 0)
 387                 return (-1);
 388         if (memcmp(vfy_sig, req_sig, SMB2_SIG_SIZE) != 0) {
 389                 cmn_err(CE_NOTE, "smb2_sign_check_request: bad signature");
 390                 return (-1);
 391         }
 392 
 393         return (0);
 394 }
 395 
 396 /*
 397  * smb2_sign_reply
 398  *
 399  * Calculates MAC signature for the given mbuf chain,
 400  * and write it to the signature field in the mbuf.
 401  *
 402  */
 403 void
 404 smb2_sign_reply(smb_request_t *sr)
 405 {
 406         uint8_t reply_sig[SMB2_SIG_SIZE];
 407         struct mbuf_chain tmp_mbc;
 408         smb_session_t *s = sr->session;
 409         smb_user_t *u = sr->uid_user;
 410         int hdr_off, msg_len;
 411 
 412         if (u == NULL)
 413                 return;
 414         if (s->sign_calc == NULL)
 415                 return;
 416 
 417         msg_len = sr->reply.chain_offset - sr->smb2_reply_hdr;
 418         (void) MBC_SHADOW_CHAIN(&tmp_mbc, &sr->reply,
 419             sr->smb2_reply_hdr, msg_len);
 420 
 421         /*
 422          * Calculate the MAC signature for this reply.
 423          * smb2_sign_calc() or smb3_sign_calc()
 424          */
 425         if (s->sign_calc(sr, &tmp_mbc, reply_sig) != 0)
 426                 return;
 427 
 428         /*
 429          * Poke the signature into the response.
 430          */
 431         hdr_off = sr->smb2_reply_hdr + SMB2_SIG_OFFS;
 432         (void) smb_mbc_poke(&sr->reply, hdr_off, "#c",
 433             SMB2_SIG_SIZE, reply_sig);
 434 }