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 2020 RackTop Systems, Inc. 23 */ 24 25 #include <smbsrv/smb2_kproto.h> 26 #include <smbsrv/smb2.h> 27 #include <sys/crypto/api.h> 28 #include <smbsrv/smb_kproto.h> 29 #include <smbsrv/smb_kcrypt.h> 30 31 /* 32 * SMB 3.1.1 Preauth Integrity 33 */ 34 int 35 smb3_sha512_getmech(smb_crypto_mech_t *mech) 36 { 37 crypto_mech_type_t t; 38 39 t = crypto_mech2id(SUN_CKM_SHA512); 40 if (t == CRYPTO_MECH_INVALID) { 41 cmn_err(CE_NOTE, "smb: no kcf mech: %s", SUN_CKM_SHA512); 42 return (-1); 43 } 44 mech->cm_type = t; 45 return (0); 46 } 47 48 /* 49 * (called from smb2_negotiate_common) 50 */ 51 void 52 smb31_preauth_init_mech(smb_session_t *s) 53 { 54 smb_crypto_mech_t *mech; 55 int rc; 56 57 ASSERT3S(s->dialect, >=, SMB_VERS_3_11); 58 59 if (s->preauth_mech != NULL) 60 return; 61 62 mech = kmem_zalloc(sizeof (*mech), KM_SLEEP); 63 rc = smb3_sha512_getmech(mech); 64 if (rc != 0) { 65 kmem_free(mech, sizeof (*mech)); 66 return; 67 } 68 s->preauth_mech = mech; 69 } 70 71 void 72 smb31_preauth_fini(smb_session_t *s) 73 { 74 smb_crypto_mech_t *mech; 75 76 if ((mech = s->preauth_mech) != NULL) { 77 kmem_free(mech, sizeof (*mech)); 78 s->preauth_mech = NULL; 79 } 80 } 81 82 /* 83 * Start the KCF session, load the key 84 */ 85 int 86 smb_sha512_init(smb_sign_ctx_t *ctxp, smb_crypto_mech_t *mech) 87 { 88 int rv; 89 90 rv = crypto_digest_init(mech, ctxp, NULL); 91 92 return (rv == CRYPTO_SUCCESS ? 0 : -1); 93 } 94 95 /* 96 * Digest one segment 97 */ 98 int 99 smb_sha512_update(smb_sign_ctx_t ctx, void *buf, size_t len) 100 { 101 crypto_data_t data; 102 int rv; 103 104 bzero(&data, sizeof (data)); 105 data.cd_format = CRYPTO_DATA_RAW; 106 data.cd_length = len; 107 data.cd_raw.iov_base = buf; 108 data.cd_raw.iov_len = len; 109 110 rv = crypto_digest_update(ctx, &data, 0); 111 112 if (rv != CRYPTO_SUCCESS) { 113 crypto_cancel_ctx(ctx); 114 return (-1); 115 } 116 117 return (0); 118 } 119 120 /* 121 * Get the final digest. 122 */ 123 int 124 smb_sha512_final(smb_sign_ctx_t ctx, uint8_t *digest) 125 { 126 crypto_data_t out; 127 int rv; 128 129 bzero(&out, sizeof (out)); 130 out.cd_format = CRYPTO_DATA_RAW; 131 out.cd_length = SHA512_DIGEST_LENGTH; 132 out.cd_raw.iov_len = SHA512_DIGEST_LENGTH; 133 out.cd_raw.iov_base = (void *)digest; 134 135 rv = crypto_digest_final(ctx, &out, 0); 136 137 return (rv == CRYPTO_SUCCESS ? 0 : -1); 138 } 139 140 int 141 smb31_preauth_sha512_calc(smb_request_t *sr, struct mbuf_chain *mbc, 142 uint8_t *hashval) 143 { 144 smb_session_t *s = sr->session; 145 smb_sign_ctx_t ctx = 0; 146 struct mbuf *mbuf = mbc->chain; 147 int rc; 148 149 if (s->preauth_mech == NULL) 150 return (-1); 151 152 if ((rc = smb_sha512_init(&ctx, s->preauth_mech)) != 0) 153 return (rc); 154 155 /* Digest current hashval */ 156 rc = smb_sha512_update(ctx, hashval, SHA512_DIGEST_LENGTH); 157 if (rc != 0) 158 return (rc); 159 160 while (mbuf != NULL) { 161 rc = smb_sha512_update(ctx, mbuf->m_data, mbuf->m_len); 162 if (rc != 0) 163 return (rc); 164 mbuf = mbuf->m_next; 165 } 166 167 rc = smb_sha512_final(ctx, hashval); 168 return (rc); 169 }