xref: /illumos-gate/usr/src/uts/common/fs/smbclnt/netsmb/nsmb_kdf.c (revision 48e11a6ea0245c522078ddb86a73f16c8c28b949)
1*48e11a6eSGordon Ross /*
2*48e11a6eSGordon Ross  * CDDL HEADER START
3*48e11a6eSGordon Ross  *
4*48e11a6eSGordon Ross  * The contents of this file are subject to the terms of the
5*48e11a6eSGordon Ross  * Common Development and Distribution License (the "License").
6*48e11a6eSGordon Ross  * You may not use this file except in compliance with the License.
7*48e11a6eSGordon Ross  *
8*48e11a6eSGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*48e11a6eSGordon Ross  * or http://www.opensolaris.org/os/licensing.
10*48e11a6eSGordon Ross  * See the License for the specific language governing permissions
11*48e11a6eSGordon Ross  * and limitations under the License.
12*48e11a6eSGordon Ross  *
13*48e11a6eSGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
14*48e11a6eSGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*48e11a6eSGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
16*48e11a6eSGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
17*48e11a6eSGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
18*48e11a6eSGordon Ross  *
19*48e11a6eSGordon Ross  * CDDL HEADER END
20*48e11a6eSGordon Ross  */
21*48e11a6eSGordon Ross /*
22*48e11a6eSGordon Ross  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*48e11a6eSGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
24*48e11a6eSGordon Ross  * Copyright 2022-2024 RackTop Systems, Inc.
25*48e11a6eSGordon Ross  */
26*48e11a6eSGordon Ross 
27*48e11a6eSGordon Ross #include <netsmb/nsmb_kcrypt.h>
28*48e11a6eSGordon Ross #include <sys/types.h>
29*48e11a6eSGordon Ross #include <sys/sysmacros.h>
30*48e11a6eSGordon Ross #include <sys/ddi.h>
31*48e11a6eSGordon Ross #include <sys/sunddi.h>
32*48e11a6eSGordon Ross #include <sys/byteorder.h>
33*48e11a6eSGordon Ross #include <sys/debug.h>
34*48e11a6eSGordon Ross 
35*48e11a6eSGordon Ross /*
36*48e11a6eSGordon Ross  * Derive SMB3 key as described in [MS-SMB2] 3.1.4.2
37*48e11a6eSGordon Ross  * and [NIST SP800-108]
38*48e11a6eSGordon Ross  *
39*48e11a6eSGordon Ross  * r = 32, PRF = HMAC-SHA256, key = (session key),
40*48e11a6eSGordon Ross  * L = 128 or 256
41*48e11a6eSGordon Ross  */
42*48e11a6eSGordon Ross 
43*48e11a6eSGordon Ross /*
44*48e11a6eSGordon Ross  * SMB 3.0.2 KDF Input
45*48e11a6eSGordon Ross  *
46*48e11a6eSGordon Ross  * Session.SigningKey for binding a session:
47*48e11a6eSGordon Ross  * - Session.SessionKey as K1
48*48e11a6eSGordon Ross  * - label = "SMB2AESCMAC" (size 12)
49*48e11a6eSGordon Ross  * - context = "SmbSign" (size 8)
50*48e11a6eSGordon Ross  * Channel.SigningKey for for all other requests
51*48e11a6eSGordon Ross  * - if SMB2_SESSION_FLAG_BINDING, GSS key (in Session.SessionKey?) as K1;
52*48e11a6eSGordon Ross  * - otherwise, Session.SessionKey as K1
53*48e11a6eSGordon Ross  * - label = "SMB2AESCMAC" (size 12)
54*48e11a6eSGordon Ross  * - context = "SmbSign" (size 8)
55*48e11a6eSGordon Ross  * Session.ApplicationKey for ... (not sure what yet)
56*48e11a6eSGordon Ross  * - Session.SessionKey as K1
57*48e11a6eSGordon Ross  * - label = "SMB2APP" (size 8)
58*48e11a6eSGordon Ross  * - context = "SmbRpc" (size 7)
59*48e11a6eSGordon Ross  * Session.EncryptionKey for encrypting server messages
60*48e11a6eSGordon Ross  * - Session.SessionKey as K1
61*48e11a6eSGordon Ross  * - label = "SMB2AESCCM" (size 11)
62*48e11a6eSGordon Ross  * - context = "ServerOut" (size 10)
63*48e11a6eSGordon Ross  * Session.DecryptionKey for decrypting client requests
64*48e11a6eSGordon Ross  * - Session.SessionKey as K1
65*48e11a6eSGordon Ross  * - label = "SMB2AESCCM" (size 11)
66*48e11a6eSGordon Ross  * - context = "ServerIn " (size 10) (Note the space)
67*48e11a6eSGordon Ross  */
68*48e11a6eSGordon Ross 
69*48e11a6eSGordon Ross /*
70*48e11a6eSGordon Ross  * SMB 3.1.1 KDF Input
71*48e11a6eSGordon Ross  *
72*48e11a6eSGordon Ross  * Session.SigningKey for binding a session:
73*48e11a6eSGordon Ross  * - Session.SessionKey as K1
74*48e11a6eSGordon Ross  * - label = "SMBSigningKey" (size 14)
75*48e11a6eSGordon Ross  * - context = preauth hashval
76*48e11a6eSGordon Ross  * Channel.SigningKey for for all other requests
77*48e11a6eSGordon Ross  * - if SMB2_SESSION_FLAG_BINDING, GSS key (in Session.SessionKey?) as K1;
78*48e11a6eSGordon Ross  * - otherwise, Session.SessionKey as K1
79*48e11a6eSGordon Ross  * - label = "SMBSigningKey" (size 14)
80*48e11a6eSGordon Ross  * - context = preauth hashval
81*48e11a6eSGordon Ross  * Session.EncryptionKey for encrypting server messages
82*48e11a6eSGordon Ross  * - Session.SessionKey as K1
83*48e11a6eSGordon Ross  * - label = "SMBS2CCipherKey" (size 16)
84*48e11a6eSGordon Ross  * - context = preauth hashval
85*48e11a6eSGordon Ross  * Session.DecryptionKey for decrypting client requests
86*48e11a6eSGordon Ross  * - Session.SessionKey as K1
87*48e11a6eSGordon Ross  * - label = "SMBC2SCipherKey" (size 16)
88*48e11a6eSGordon Ross  * - context = preauth hashval
89*48e11a6eSGordon Ross  */
90*48e11a6eSGordon Ross 
91*48e11a6eSGordon Ross #define	KDF_LABEL_MAXLEN	16
92*48e11a6eSGordon Ross #define	KDF_CONTEXT_MAXLEN	64
93*48e11a6eSGordon Ross #define	KDF_FIXEDPART_LEN	9
94*48e11a6eSGordon Ross #define	KDF_BUFLEN		89	/* total of above */
95*48e11a6eSGordon Ross 
96*48e11a6eSGordon Ross /*
97*48e11a6eSGordon Ross  * SMB3KDF(Ki, Label, Context)
98*48e11a6eSGordon Ross  * counter || Label || 0x00 || Context || L
99*48e11a6eSGordon Ross  */
100*48e11a6eSGordon Ross int
nsmb_kdf(uint8_t * outbuf,uint32_t keylen,uint8_t * ssn_key,size_t ssn_keylen,uint8_t * label,size_t label_len,uint8_t * context,size_t context_len)101*48e11a6eSGordon Ross nsmb_kdf(uint8_t *outbuf, uint32_t keylen,
102*48e11a6eSGordon Ross     uint8_t *ssn_key, size_t ssn_keylen,
103*48e11a6eSGordon Ross     uint8_t *label, size_t label_len,
104*48e11a6eSGordon Ross     uint8_t *context, size_t context_len)
105*48e11a6eSGordon Ross {
106*48e11a6eSGordon Ross 	smb_crypto_mech_t mech;
107*48e11a6eSGordon Ross 	uint8_t digest32[SHA256_DIGEST_LENGTH];
108*48e11a6eSGordon Ross 	uint8_t kdfbuf[KDF_BUFLEN];
109*48e11a6eSGordon Ross 	uint32_t L = keylen << 3; /* key len in bits */
110*48e11a6eSGordon Ross 	int pos = 0;
111*48e11a6eSGordon Ross 	int rc;
112*48e11a6eSGordon Ross 
113*48e11a6eSGordon Ross 	if (label_len > KDF_LABEL_MAXLEN ||
114*48e11a6eSGordon Ross 	    context_len > KDF_CONTEXT_MAXLEN) {
115*48e11a6eSGordon Ross 		ASSERT(0);
116*48e11a6eSGordon Ross 		return (-1);
117*48e11a6eSGordon Ross 	}
118*48e11a6eSGordon Ross 
119*48e11a6eSGordon Ross 	/* Counter=1 (big-endian) */
120*48e11a6eSGordon Ross 	kdfbuf[pos++] = 0;
121*48e11a6eSGordon Ross 	kdfbuf[pos++] = 0;
122*48e11a6eSGordon Ross 	kdfbuf[pos++] = 0;
123*48e11a6eSGordon Ross 	kdfbuf[pos++] = 1;
124*48e11a6eSGordon Ross 
125*48e11a6eSGordon Ross 	bcopy(label, &kdfbuf[pos], label_len);
126*48e11a6eSGordon Ross 	pos += label_len;
127*48e11a6eSGordon Ross 
128*48e11a6eSGordon Ross 	kdfbuf[pos++] = 0;
129*48e11a6eSGordon Ross 
130*48e11a6eSGordon Ross 	bcopy(context, &kdfbuf[pos], context_len);
131*48e11a6eSGordon Ross 	pos += context_len;
132*48e11a6eSGordon Ross 
133*48e11a6eSGordon Ross 	/* Key length in bits, big-endian, possibly misaligned */
134*48e11a6eSGordon Ross 	kdfbuf[pos++] = 0;
135*48e11a6eSGordon Ross 	kdfbuf[pos++] = 0;
136*48e11a6eSGordon Ross 	kdfbuf[pos++] = (uint8_t)(L >> 8);
137*48e11a6eSGordon Ross 	kdfbuf[pos++] = (uint8_t)L;
138*48e11a6eSGordon Ross 
139*48e11a6eSGordon Ross 	bzero(&mech, sizeof (mech));
140*48e11a6eSGordon Ross 	if ((rc = nsmb_hmac_getmech(&mech)) != 0)
141*48e11a6eSGordon Ross 		return (rc);
142*48e11a6eSGordon Ross 
143*48e11a6eSGordon Ross 	rc = nsmb_hmac_one(&mech,
144*48e11a6eSGordon Ross 	    ssn_key, ssn_keylen,
145*48e11a6eSGordon Ross 	    kdfbuf, pos,
146*48e11a6eSGordon Ross 	    digest32, SHA256_DIGEST_LENGTH);
147*48e11a6eSGordon Ross 	if (rc != 0)
148*48e11a6eSGordon Ross 		return (rc);
149*48e11a6eSGordon Ross 
150*48e11a6eSGordon Ross 	bcopy(digest32, outbuf, keylen);
151*48e11a6eSGordon Ross 	return (0);
152*48e11a6eSGordon Ross }
153