xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_sign_kcf.c (revision eba274b9392a53f991f6ca04d624533172d46fd4)
1b819cea2SGordon Ross /*
2b819cea2SGordon Ross  * This file and its contents are supplied under the terms of the
3b819cea2SGordon Ross  * Common Development and Distribution License ("CDDL"), version 1.0.
4b819cea2SGordon Ross  * You may only use this file in accordance with the terms of version
5b819cea2SGordon Ross  * 1.0 of the CDDL.
6b819cea2SGordon Ross  *
7b819cea2SGordon Ross  * A full copy of the text of the CDDL should have accompanied this
8b819cea2SGordon Ross  * source.  A copy of the CDDL is also available via the Internet at
9b819cea2SGordon Ross  * http://www.illumos.org/license/CDDL.
10b819cea2SGordon Ross  */
11b819cea2SGordon Ross 
12b819cea2SGordon Ross /*
13c51c88bdSMatt Barden  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
14b819cea2SGordon Ross  */
15b819cea2SGordon Ross 
16b819cea2SGordon Ross /*
17a90cf9f2SGordon Ross  * Helper functions for SMB signing using the
18b819cea2SGordon Ross  * Kernel Cryptographic Framework (KCF)
19b819cea2SGordon Ross  *
20b819cea2SGordon Ross  * There are two implementations of these functions:
21b819cea2SGordon Ross  * This one (for kernel) and another for user space:
22b819cea2SGordon Ross  * See: lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c
23b819cea2SGordon Ross  */
24b819cea2SGordon Ross 
25b819cea2SGordon Ross #include <sys/types.h>
26b819cea2SGordon Ross #include <sys/kmem.h>
27b819cea2SGordon Ross #include <sys/crypto/api.h>
28b819cea2SGordon Ross #include <smbsrv/smb_kproto.h>
291160dcf7SMatt Barden #include <smbsrv/smb_kcrypt.h>
30b819cea2SGordon Ross 
31b819cea2SGordon Ross /*
32c51c88bdSMatt Barden  * Common function to see if a mech is available.
33c51c88bdSMatt Barden  */
34c51c88bdSMatt Barden static int
35*eba274b9SToomas Soome find_mech(smb_crypto_mech_t *mech, const char *name)
36c51c88bdSMatt Barden {
37c51c88bdSMatt Barden 	crypto_mech_type_t t;
38c51c88bdSMatt Barden 
39c51c88bdSMatt Barden 	t = crypto_mech2id(name);
40c51c88bdSMatt Barden 	if (t == CRYPTO_MECH_INVALID) {
41c51c88bdSMatt Barden 		cmn_err(CE_NOTE, "smb: no kcf mech: %s", name);
42c51c88bdSMatt Barden 		return (-1);
43c51c88bdSMatt Barden 	}
44c51c88bdSMatt Barden 	mech->cm_type = t;
45c51c88bdSMatt Barden 	return (0);
46c51c88bdSMatt Barden }
47c51c88bdSMatt Barden 
48c51c88bdSMatt Barden /*
49b819cea2SGordon Ross  * SMB1 signing helpers:
50b819cea2SGordon Ross  * (getmech, init, update, final)
51b819cea2SGordon Ross  */
52b819cea2SGordon Ross 
53b819cea2SGordon Ross int
541160dcf7SMatt Barden smb_md5_getmech(smb_crypto_mech_t *mech)
55b819cea2SGordon Ross {
56c51c88bdSMatt Barden 	return (find_mech(mech, SUN_CKM_MD5));
57b819cea2SGordon Ross }
58b819cea2SGordon Ross 
59b819cea2SGordon Ross /*
60b819cea2SGordon Ross  * Start the KCF session, load the key
61b819cea2SGordon Ross  */
62b819cea2SGordon Ross int
631160dcf7SMatt Barden smb_md5_init(smb_sign_ctx_t *ctxp, smb_crypto_mech_t *mech)
64b819cea2SGordon Ross {
65b819cea2SGordon Ross 	int rv;
66b819cea2SGordon Ross 
67b819cea2SGordon Ross 	rv = crypto_digest_init(mech, ctxp, NULL);
68b819cea2SGordon Ross 
69b819cea2SGordon Ross 	return (rv == CRYPTO_SUCCESS ? 0 : -1);
70b819cea2SGordon Ross }
71b819cea2SGordon Ross 
72b819cea2SGordon Ross /*
73b819cea2SGordon Ross  * Digest one segment
74b819cea2SGordon Ross  */
75b819cea2SGordon Ross int
76b819cea2SGordon Ross smb_md5_update(smb_sign_ctx_t ctx, void *buf, size_t len)
77b819cea2SGordon Ross {
78b819cea2SGordon Ross 	crypto_data_t data;
79b819cea2SGordon Ross 	int rv;
80b819cea2SGordon Ross 
81b819cea2SGordon Ross 	bzero(&data, sizeof (data));
82b819cea2SGordon Ross 	data.cd_format = CRYPTO_DATA_RAW;
83b819cea2SGordon Ross 	data.cd_length = len;
84b819cea2SGordon Ross 	data.cd_raw.iov_base = buf;
85b819cea2SGordon Ross 	data.cd_raw.iov_len = len;
86b819cea2SGordon Ross 
87b819cea2SGordon Ross 	rv = crypto_digest_update(ctx, &data, 0);
88b819cea2SGordon Ross 
89c51c88bdSMatt Barden 	if (rv != CRYPTO_SUCCESS) {
90c51c88bdSMatt Barden 		crypto_cancel_ctx(ctx);
91c51c88bdSMatt Barden 		return (-1);
92c51c88bdSMatt Barden 	}
93c51c88bdSMatt Barden 
94c51c88bdSMatt Barden 	return (0);
95b819cea2SGordon Ross }
96b819cea2SGordon Ross 
97b819cea2SGordon Ross /*
98b819cea2SGordon Ross  * Get the final digest.
99b819cea2SGordon Ross  */
100b819cea2SGordon Ross int
101b819cea2SGordon Ross smb_md5_final(smb_sign_ctx_t ctx, uint8_t *digest16)
102b819cea2SGordon Ross {
103b819cea2SGordon Ross 	crypto_data_t out;
104b819cea2SGordon Ross 	int rv;
105b819cea2SGordon Ross 
106b819cea2SGordon Ross 	bzero(&out, sizeof (out));
107b819cea2SGordon Ross 	out.cd_format = CRYPTO_DATA_RAW;
108b819cea2SGordon Ross 	out.cd_length = MD5_DIGEST_LENGTH;
109b819cea2SGordon Ross 	out.cd_raw.iov_len = MD5_DIGEST_LENGTH;
110b819cea2SGordon Ross 	out.cd_raw.iov_base = (void *)digest16;
111b819cea2SGordon Ross 
112b819cea2SGordon Ross 	rv = crypto_digest_final(ctx, &out, 0);
113b819cea2SGordon Ross 
114b819cea2SGordon Ross 	return (rv == CRYPTO_SUCCESS ? 0 : -1);
115b819cea2SGordon Ross }
116a90cf9f2SGordon Ross 
117a90cf9f2SGordon Ross /*
118a90cf9f2SGordon Ross  * SMB2 signing helpers:
119a90cf9f2SGordon Ross  * (getmech, init, update, final)
120a90cf9f2SGordon Ross  */
121a90cf9f2SGordon Ross 
122a90cf9f2SGordon Ross int
1231160dcf7SMatt Barden smb2_hmac_getmech(smb_crypto_mech_t *mech)
124a90cf9f2SGordon Ross {
125c51c88bdSMatt Barden 	return (find_mech(mech, SUN_CKM_SHA256_HMAC));
126a90cf9f2SGordon Ross }
127a90cf9f2SGordon Ross 
128a90cf9f2SGordon Ross /*
129a90cf9f2SGordon Ross  * Start the KCF session, load the key
130a90cf9f2SGordon Ross  */
131a90cf9f2SGordon Ross int
1321160dcf7SMatt Barden smb2_hmac_init(smb_sign_ctx_t *ctxp, smb_crypto_mech_t *mech,
133a90cf9f2SGordon Ross     uint8_t *key, size_t key_len)
134a90cf9f2SGordon Ross {
135a90cf9f2SGordon Ross 	crypto_key_t ckey;
136a90cf9f2SGordon Ross 	int rv;
137a90cf9f2SGordon Ross 
138a90cf9f2SGordon Ross 	bzero(&ckey, sizeof (ckey));
139a90cf9f2SGordon Ross 	ckey.ck_format = CRYPTO_KEY_RAW;
140a90cf9f2SGordon Ross 	ckey.ck_data = key;
141a90cf9f2SGordon Ross 	ckey.ck_length = key_len * 8; /* in bits */
142a90cf9f2SGordon Ross 
143a90cf9f2SGordon Ross 	rv = crypto_mac_init(mech, &ckey, NULL, ctxp, NULL);
144a90cf9f2SGordon Ross 
145a90cf9f2SGordon Ross 	return (rv == CRYPTO_SUCCESS ? 0 : -1);
146a90cf9f2SGordon Ross }
147a90cf9f2SGordon Ross 
148a90cf9f2SGordon Ross /*
149a90cf9f2SGordon Ross  * Digest one segment
150a90cf9f2SGordon Ross  */
151a90cf9f2SGordon Ross int
152a90cf9f2SGordon Ross smb2_hmac_update(smb_sign_ctx_t ctx, uint8_t *in, size_t len)
153a90cf9f2SGordon Ross {
154a90cf9f2SGordon Ross 	crypto_data_t data;
155a90cf9f2SGordon Ross 	int rv;
156a90cf9f2SGordon Ross 
157a90cf9f2SGordon Ross 	bzero(&data, sizeof (data));
158a90cf9f2SGordon Ross 	data.cd_format = CRYPTO_DATA_RAW;
159a90cf9f2SGordon Ross 	data.cd_length = len;
160a90cf9f2SGordon Ross 	data.cd_raw.iov_base = (void *)in;
161a90cf9f2SGordon Ross 	data.cd_raw.iov_len = len;
162a90cf9f2SGordon Ross 
163a90cf9f2SGordon Ross 	rv = crypto_mac_update(ctx, &data, 0);
164a90cf9f2SGordon Ross 
165c51c88bdSMatt Barden 	if (rv != CRYPTO_SUCCESS) {
166c51c88bdSMatt Barden 		crypto_cancel_ctx(ctx);
167c51c88bdSMatt Barden 		return (-1);
168c51c88bdSMatt Barden 	}
169c51c88bdSMatt Barden 
170c51c88bdSMatt Barden 	return (0);
171a90cf9f2SGordon Ross }
172a90cf9f2SGordon Ross 
173a90cf9f2SGordon Ross /*
174a90cf9f2SGordon Ross  * Note, the SMB2 signature is the first 16 bytes of the
175a90cf9f2SGordon Ross  * 32-byte SHA256 HMAC digest.
176a90cf9f2SGordon Ross  */
177a90cf9f2SGordon Ross int
178a90cf9f2SGordon Ross smb2_hmac_final(smb_sign_ctx_t ctx, uint8_t *digest16)
179a90cf9f2SGordon Ross {
180a90cf9f2SGordon Ross 	uint8_t full_digest[SHA256_DIGEST_LENGTH];
181a90cf9f2SGordon Ross 	crypto_data_t out;
182a90cf9f2SGordon Ross 	int rv;
183a90cf9f2SGordon Ross 
184a90cf9f2SGordon Ross 	bzero(&out, sizeof (out));
185a90cf9f2SGordon Ross 	out.cd_format = CRYPTO_DATA_RAW;
186a90cf9f2SGordon Ross 	out.cd_length = SHA256_DIGEST_LENGTH;
187a90cf9f2SGordon Ross 	out.cd_raw.iov_len = SHA256_DIGEST_LENGTH;
188a90cf9f2SGordon Ross 	out.cd_raw.iov_base = (void *)full_digest;
189a90cf9f2SGordon Ross 
190a90cf9f2SGordon Ross 	rv = crypto_mac_final(ctx, &out, 0);
191a90cf9f2SGordon Ross 	if (rv == CRYPTO_SUCCESS)
192a90cf9f2SGordon Ross 		bcopy(full_digest, digest16, 16);
193a90cf9f2SGordon Ross 
194a90cf9f2SGordon Ross 	return (rv == CRYPTO_SUCCESS ? 0 : -1);
195a90cf9f2SGordon Ross }
196c51c88bdSMatt Barden 
197c51c88bdSMatt Barden /*
198c51c88bdSMatt Barden  * SMB3 signing helpers:
199c51c88bdSMatt Barden  * (getmech, init, update, final)
200c51c88bdSMatt Barden  */
201c51c88bdSMatt Barden 
202c51c88bdSMatt Barden int
2031160dcf7SMatt Barden smb3_cmac_getmech(smb_crypto_mech_t *mech)
204c51c88bdSMatt Barden {
205c51c88bdSMatt Barden 	return (find_mech(mech, SUN_CKM_AES_CMAC));
206c51c88bdSMatt Barden }
207c51c88bdSMatt Barden 
208c51c88bdSMatt Barden /*
209c51c88bdSMatt Barden  * Start the KCF session, load the key
210c51c88bdSMatt Barden  */
211c51c88bdSMatt Barden int
2121160dcf7SMatt Barden smb3_cmac_init(smb_sign_ctx_t *ctxp, smb_crypto_mech_t *mech,
213c51c88bdSMatt Barden     uint8_t *key, size_t key_len)
214c51c88bdSMatt Barden {
215c51c88bdSMatt Barden 	crypto_key_t ckey;
216c51c88bdSMatt Barden 	int rv;
217c51c88bdSMatt Barden 
218c51c88bdSMatt Barden 	bzero(&ckey, sizeof (ckey));
219c51c88bdSMatt Barden 	ckey.ck_format = CRYPTO_KEY_RAW;
220c51c88bdSMatt Barden 	ckey.ck_data = key;
221c51c88bdSMatt Barden 	ckey.ck_length = key_len * 8; /* in bits */
222c51c88bdSMatt Barden 
223c51c88bdSMatt Barden 	rv = crypto_mac_init(mech, &ckey, NULL, ctxp, NULL);
224c51c88bdSMatt Barden 
225c51c88bdSMatt Barden 	return (rv == CRYPTO_SUCCESS ? 0 : -1);
226c51c88bdSMatt Barden }
227c51c88bdSMatt Barden 
228c51c88bdSMatt Barden /*
229c51c88bdSMatt Barden  * Digest one segment
230c51c88bdSMatt Barden  */
231c51c88bdSMatt Barden int
232c51c88bdSMatt Barden smb3_cmac_update(smb_sign_ctx_t ctx, uint8_t *in, size_t len)
233c51c88bdSMatt Barden {
234c51c88bdSMatt Barden 	crypto_data_t data;
235c51c88bdSMatt Barden 	int rv;
236c51c88bdSMatt Barden 
237c51c88bdSMatt Barden 	bzero(&data, sizeof (data));
238c51c88bdSMatt Barden 	data.cd_format = CRYPTO_DATA_RAW;
239c51c88bdSMatt Barden 	data.cd_length = len;
240c51c88bdSMatt Barden 	data.cd_raw.iov_base = (void *)in;
241c51c88bdSMatt Barden 	data.cd_raw.iov_len = len;
242c51c88bdSMatt Barden 
243c51c88bdSMatt Barden 	rv = crypto_mac_update(ctx, &data, 0);
244c51c88bdSMatt Barden 
245c51c88bdSMatt Barden 	if (rv != CRYPTO_SUCCESS) {
246c51c88bdSMatt Barden 		crypto_cancel_ctx(ctx);
247c51c88bdSMatt Barden 		return (-1);
248c51c88bdSMatt Barden 	}
249c51c88bdSMatt Barden 
250c51c88bdSMatt Barden 	return (0);
251c51c88bdSMatt Barden }
252c51c88bdSMatt Barden 
253c51c88bdSMatt Barden /*
254c51c88bdSMatt Barden  * Note, the SMB2 signature is just the AES CMAC digest.
255c51c88bdSMatt Barden  * (both are 16 bytes long)
256c51c88bdSMatt Barden  */
257c51c88bdSMatt Barden int
258c51c88bdSMatt Barden smb3_cmac_final(smb_sign_ctx_t ctx, uint8_t *digest16)
259c51c88bdSMatt Barden {
260c51c88bdSMatt Barden 	crypto_data_t out;
261c51c88bdSMatt Barden 	int rv;
262c51c88bdSMatt Barden 
263c51c88bdSMatt Barden 	bzero(&out, sizeof (out));
264c51c88bdSMatt Barden 	out.cd_format = CRYPTO_DATA_RAW;
265c51c88bdSMatt Barden 	out.cd_length = SMB2_SIG_SIZE;
266c51c88bdSMatt Barden 	out.cd_raw.iov_len = SMB2_SIG_SIZE;
267c51c88bdSMatt Barden 	out.cd_raw.iov_base = (void *)digest16;
268c51c88bdSMatt Barden 
269c51c88bdSMatt Barden 	rv = crypto_mac_final(ctx, &out, 0);
270c51c88bdSMatt Barden 
271c51c88bdSMatt Barden 	return (rv == CRYPTO_SUCCESS ? 0 : -1);
272c51c88bdSMatt Barden }
273