diff options
author | Gordon Ross <gwr@racktopsystems.com> | 2022-01-08 14:44:01 -0500 |
---|---|---|
committer | Toomas Soome <tsoome@me.com> | 2022-09-29 21:00:33 +0300 |
commit | e472a1cd85bffae230f8546d46fa757bade533e9 (patch) | |
tree | 036df80b5fc4ed24523e9a56b79050384087d2b0 | |
parent | 17e9e0ae7132604963fd5a20e8ece5f2630e7fdf (diff) | |
download | illumos-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-x | usr/src/cmd/smbsrv/fksmbd/Run.sh | 2 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c | 131 |
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); } |