summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Ross <gwr@racktopsystems.com>2022-01-08 14:44:01 -0500
committerToomas Soome <tsoome@me.com>2022-09-29 21:00:33 +0300
commite472a1cd85bffae230f8546d46fa757bade533e9 (patch)
tree036df80b5fc4ed24523e9a56b79050384087d2b0
parent17e9e0ae7132604963fd5a20e8ece5f2630e7fdf (diff)
downloadillumos-joyent-e472a1cd85bffae230f8546d46fa757bade533e9.tar.gz
15006 Implement pre-auth integrity for fksmbd
Reviewed by: Matt Barden <mbarden@tintri.com> Approved by: Patrick Mooney <pmooney@pfmooney.com>
-rwxr-xr-xusr/src/cmd/smbsrv/fksmbd/Run.sh2
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c131
2 files changed, 127 insertions, 6 deletions
diff --git a/usr/src/cmd/smbsrv/fksmbd/Run.sh b/usr/src/cmd/smbsrv/fksmbd/Run.sh
index fb76e791e6..32ec31c08f 100755
--- a/usr/src/cmd/smbsrv/fksmbd/Run.sh
+++ b/usr/src/cmd/smbsrv/fksmbd/Run.sh
@@ -56,7 +56,7 @@ LD_LIBRARY_PATH=$ROOT/usr/lib/smbsrv:$ROOT/usr/lib:$ROOT/lib
export LD_LIBRARY_PATH
# Enable everything, for debugging
-export SMB_MAX_PROTOCOL=300
+export SMB_MAX_PROTOCOL=311
export SMB_SIGNING=require
# normally runs with cwd=/ but this is more careful
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c
index 5abb8535c3..a792dcca21 100644
--- a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c
@@ -10,28 +10,149 @@
*/
/*
- * Copyright 2020 RackTop Systems, Inc.
+ * Copyright 2021 RackTop Systems, Inc.
*/
-#include <smbsrv/smb_ktypes.h>
-#include <smbsrv/mbuf.h>
+#include <stdlib.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_kcrypt.h>
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
/*
- * not implemented yet
+ * SMB 3.1.1 Preauth Integrity
+ */
+static int
+getmech_sha512(smb_crypto_mech_t *mech)
+{
+ ulong_t mid = CKM_SHA512;
+ CK_SESSION_HANDLE hdl;
+ CK_RV rv;
+
+ rv = SUNW_C_GetMechSession(mid, &hdl);
+ if (rv != CKR_OK) {
+ cmn_err(CE_NOTE, "PKCS#11: no mech 0x%x",
+ (unsigned int)mid);
+ return (-1);
+ }
+ (void) C_CloseSession(hdl);
+
+ mech->mechanism = mid;
+ mech->pParameter = NULL;
+ mech->ulParameterLen = 0;
+ return (0);
+}
+
+/*
+ * (called from smb2_negotiate_common)
*/
void
smb31_preauth_init_mech(smb_session_t *s)
{
+ smb_crypto_mech_t *mech;
+ int rc;
+
+ ASSERT3S(s->dialect, >=, SMB_VERS_3_11);
+
+ if (s->preauth_mech != NULL)
+ return;
+
+ mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
+ rc = getmech_sha512(mech);
+ if (rc != 0) {
+ kmem_free(mech, sizeof (*mech));
+ return;
+ }
+ s->preauth_mech = mech;
}
void
smb31_preauth_fini(smb_session_t *s)
{
+ smb_crypto_mech_t *mech;
+
+ if ((mech = s->preauth_mech) != NULL) {
+ kmem_free(mech, sizeof (*mech));
+ s->preauth_mech = NULL;
+ }
+}
+
+/*
+ * Start the KCF session, load the key
+ */
+int
+smb_sha512_init(smb_sign_ctx_t *ctxp, smb_crypto_mech_t *mech)
+{
+ CK_RV rv;
+
+ rv = SUNW_C_GetMechSession(mech->mechanism, ctxp);
+ if (rv != CKR_OK)
+ return (-1);
+
+ rv = C_DigestInit(*ctxp, mech);
+
+ return (rv == CKR_OK ? 0 : -1);
+}
+
+/*
+ * Digest one segment
+ */
+int
+smb_sha512_update(smb_sign_ctx_t ctx, void *buf, size_t len)
+{
+ CK_RV rv;
+
+ rv = C_DigestUpdate(ctx, buf, len);
+ if (rv != CKR_OK)
+ (void) C_CloseSession(ctx);
+
+ return (rv == CKR_OK ? 0 : -1);
+}
+
+/*
+ * Get the final digest.
+ */
+int
+smb_sha512_final(smb_sign_ctx_t ctx, uint8_t *digest)
+{
+ CK_ULONG len = SHA512_DIGEST_LENGTH;
+ CK_RV rv;
+
+ rv = C_DigestFinal(ctx, digest, &len);
+ (void) C_CloseSession(ctx);
+
+ return (rv == CKR_OK ? 0 : -1);
}
int
smb31_preauth_sha512_calc(smb_request_t *sr, struct mbuf_chain *mbc,
uint8_t *in_hashval, uint8_t *out_hashval)
{
- return (0);
+ smb_session_t *s = sr->session;
+ smb_sign_ctx_t ctx = 0;
+ struct mbuf *mbuf = mbc->chain;
+ int rc;
+
+ ASSERT3U(s->smb31_preauth_hashid, !=, 0);
+
+ if (s->preauth_mech == NULL)
+ return (-1);
+
+ if ((rc = smb_sha512_init(&ctx, s->preauth_mech)) != 0)
+ return (rc);
+
+ /* Digest current hashval */
+ rc = smb_sha512_update(ctx, in_hashval, SHA512_DIGEST_LENGTH);
+ if (rc != 0)
+ return (rc);
+
+ while (mbuf != NULL) {
+ rc = smb_sha512_update(ctx, mbuf->m_data, mbuf->m_len);
+ if (rc != 0)
+ return (rc);
+ mbuf = mbuf->m_next;
+ }
+
+ rc = smb_sha512_final(ctx, out_hashval);
+ return (rc);
}