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