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