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 2022 RackTop Systems, Inc. 25 */ 26 27 #include <smbsrv/smb_kcrypt.h> 28 #include <sys/types.h> 29 #include <sys/sysmacros.h> 30 #include <sys/ddi.h> 31 #include <sys/sunddi.h> 32 #include <sys/byteorder.h> 33 #include <sys/debug.h> 34 35 /* 36 * Derive SMB3 key as described in [MS-SMB2] 3.1.4.2 37 * and [NIST SP800-108] 38 * 39 * r = 32, PRF = HMAC-SHA256, key = (session key), 40 * L = 128 or 256 41 */ 42 43 /* 44 * SMB 3.0.2 KDF Input 45 * 46 * Session.SigningKey for binding a session: 47 * - Session.SessionKey as K1 48 * - label = "SMB2AESCMAC" (size 12) 49 * - context = "SmbSign" (size 8) 50 * Channel.SigningKey for for all other requests 51 * - if SMB2_SESSION_FLAG_BINDING, GSS key (in Session.SessionKey?) as K1; 52 * - otherwise, Session.SessionKey as K1 53 * - label = "SMB2AESCMAC" (size 12) 54 * - context = "SmbSign" (size 8) 55 * Session.ApplicationKey for ... (not sure what yet) 56 * - Session.SessionKey as K1 57 * - label = "SMB2APP" (size 8) 58 * - context = "SmbRpc" (size 7) 59 * Session.EncryptionKey for encrypting server messages 60 * - Session.SessionKey as K1 61 * - label = "SMB2AESCCM" (size 11) 62 * - context = "ServerOut" (size 10) 63 * Session.DecryptionKey for decrypting client requests 64 * - Session.SessionKey as K1 65 * - label = "SMB2AESCCM" (size 11) 66 * - context = "ServerIn " (size 10) (Note the space) 67 */ 68 69 /* 70 * SMB 3.1.1 KDF Input 71 * 72 * Session.SigningKey for binding a session: 73 * - Session.SessionKey as K1 74 * - label = "SMBSigningKey" (size 14) 75 * - context = preauth hashval 76 * Channel.SigningKey for for all other requests 77 * - if SMB2_SESSION_FLAG_BINDING, GSS key (in Session.SessionKey?) as K1; 78 * - otherwise, Session.SessionKey as K1 79 * - label = "SMBSigningKey" (size 14) 80 * - context = preauth hashval 81 * Session.EncryptionKey for encrypting server messages 82 * - Session.SessionKey as K1 83 * - label = "SMBS2CCipherKey" (size 16) 84 * - context = preauth hashval 85 * Session.DecryptionKey for decrypting client requests 86 * - Session.SessionKey as K1 87 * - label = "SMBC2SCipherKey" (size 16) 88 * - context = preauth hashval 89 */ 90 91 #define KDF_LABEL_MAXLEN 16 92 #define KDF_CONTEXT_MAXLEN 64 93 #define KDF_FIXEDPART_LEN 9 94 #define KDF_BUFLEN 89 /* total of above */ 95 96 /* 97 * SMB3KDF(Ki, Label, Context) 98 * counter || Label || 0x00 || Context || L 99 */ 100 int 101 smb3_kdf(uint8_t *outbuf, uint32_t keylen, 102 uint8_t *ssn_key, size_t ssn_keylen, 103 uint8_t *label, size_t label_len, 104 uint8_t *context, size_t context_len) 105 { 106 smb_crypto_mech_t mech; 107 uint8_t digest32[SHA256_DIGEST_LENGTH]; 108 uint8_t kdfbuf[KDF_BUFLEN]; 109 uint32_t L = keylen << 3; /* key len in bits */ 110 int pos = 0; 111 int rc; 112 113 if (label_len > KDF_LABEL_MAXLEN || 114 context_len > KDF_CONTEXT_MAXLEN) { 115 ASSERT(0); 116 return (-1); 117 } 118 119 /* Counter=1 (big-endian) */ 120 kdfbuf[pos++] = 0; 121 kdfbuf[pos++] = 0; 122 kdfbuf[pos++] = 0; 123 kdfbuf[pos++] = 1; 124 125 bcopy(label, &kdfbuf[pos], label_len); 126 pos += label_len; 127 128 kdfbuf[pos++] = 0; 129 130 bcopy(context, &kdfbuf[pos], context_len); 131 pos += context_len; 132 133 /* Key lemgth in bits, big-endian, possibly misaligned */ 134 kdfbuf[pos++] = 0; 135 kdfbuf[pos++] = 0; 136 kdfbuf[pos++] = (uint8_t)(L >> 8); 137 kdfbuf[pos++] = (uint8_t)L; 138 139 bzero(&mech, sizeof (mech)); 140 if ((rc = smb2_hmac_getmech(&mech)) != 0) 141 return (rc); 142 143 rc = smb2_hmac_one(&mech, 144 ssn_key, ssn_keylen, 145 kdfbuf, pos, 146 digest32, SHA256_DIGEST_LENGTH); 147 if (rc != 0) 148 return (rc); 149 150 bcopy(digest32, outbuf, keylen); 151 return (0); 152 } 153