smb_crypt.c revision 9c9af2590af49bb395bc8d2eace0f2d4ea16d165
/*
* Copyright (c) 2000-2001, Boris Popov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Boris Popov.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: smb_crypt.c,v 1.13 2005/01/26 23:50:50 lindak Exp $
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <netsmb/smb_osdep.h>
#include <netsmb/smb_conn.h>
#include <netsmb/smb_subr.h>
#ifdef DEBUG
/*
* Set this to a small number to debug sequence numbers
* that seem to get out of step.
*/
int nsmb_signing_fudge = 0;
#endif
/* Mechanism definitions */
void
smb_crypto_mech_init(void)
{
}
static void
{
int rv;
/*
* 'Key' here is the username - 7-bytes. Convert that to
* to a 8-byte string.
*/
/* Checked this in callers */
if (rv != CRYPTO_SUCCESS)
SMBSDEBUG("crypto_encrypt failed.\n");
}
/*
* Compute the LM hash, which is used to compute the LM response.
*/
void
{
/* In case we error out. */
/* Note ASSERT in smb_E */
SMBSDEBUG("crypto_mech_des invalid\n");
return;
}
/* Convert apwd to upper case, zero extend. */
/*
* lmhash = concat(Ex(P14, N8), zeros(5));
*/
}
/*
* Compute an LM or NTLM response given the LM or NTLM hash and a
* challenge. Note: This now replaces smb_ntlmresponse which
* used to compute a different hash and then do the same
* response computation as found here. Now that the hash
* is computed by the caller, this is used for both.
*/
int
{
/* In case we error out. */
/* Note ASSERT in smb_E */
SMBSDEBUG("crypto_mech_des invalid\n");
return (ENOTSUP);
}
return (0);
}
/*
* Compute the NTLMv1 hash, which is used to compute both NTLMv1 and
* NTLMv2 responses.
*/
void
{
/*
* v1hash = concat(MD4(U(apwd)), zeros(5));
*/
}
/*
* Note: smb_ntlmresponse() is gone.
* Use: smb_lmresponse() instead.
*/
static void
{
int i;
/* if key is longer than 64 bytes use only the first 64 bytes */
if (key_len > 64)
key_len = 64;
/*
* The HMAC-MD5 (and HMACT64) transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, data))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and data is the data being protected.
*/
/* start out by storing key in pads */
/* XOR key with ipad and opad values */
for (i = 0; i < 64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* perform inner MD5
*/
/*
* perform outer MD5
*/
}
/*
* Compute an NTLMv2 hash given the NTLMv1 hash, the user name,
* the destination machine or domain name, and a challenge.
*/
void
{
int len;
/*
* v2hash = HMACT64(v1hash, 16, concat(upcase(user), upcase(dest))
* where "dest" is the domain or server name ("target name")
* We assume that user and destination are supplied to us as
* upper-case UTF-8.
*/
}
/*
* Compute an NTLMv2 response given the 16 byte NTLMv2 hash,
* a challenge, and the blob.
*/
int
{
return (0);
}
/*
* Calculate NTLMv2 message authentication code (MAC) key for
* this VC and store it in vc_mackey (allocated here).
*
* The MAC key is the concatenation of the 16 byte session key
* and the NT response.
*
* XXX: Should factor out computation of the session key
* from both this and the next function, and then use a
* common function to compute the MAC key (which then
* can do simple concatenation). Later.
*/
int
{
SMBSDEBUG("Already have MAC key!\n");
return (0);
}
/* session key uses only 1st 16 bytes of ntresp */
/* Free in: smb_vc_free, smb_smb_negotiate */
#ifdef DTRACE_PROBE
int, vcp->vc_mackeylen);
#endif
return (0);
}
/*
* Calculate message authentication code (MAC) key for virtual circuit.
* The MAC key is the concatenation of the 16 byte session key
* and the 24 byte challenge response.
*/
/*ARGSUSED*/
int
{
SMBSDEBUG("Already have MAC key!\n");
return (0);
}
/* Free in: smb_vc_free, smb_smb_negotiate */
/*
* Calculate session key:
*/
/* Response to challenge. */
#ifdef DTRACE_PROBE
int, vcp->vc_mackeylen);
#endif
return (0);
}
/*
* Compute HMAC-MD5 of packet data, using the stored MAC key.
*
* See similar code for the server side:
* uts/common/fs/smbsrv/smb_signing.c : smb_sign_calc
*/
static int
{
int status;
/*
* This union is a little bit of trickery to:
* (1) get the sequence number int aligned, and
* (2) reduce the number of digest calls, at the
* cost of a copying 32 bytes instead of 8.
* Both sides of this union are 2+32 bytes.
*/
union {
struct {
} r;
struct {
} s;
} smbhdr;
/*
* Make an aligned copy of the SMB header
* and fill in the sequence number.
*/
/*
* Compute the MAC: MD5(concat(Key, message))
*/
SMBSDEBUG("crypto_mech_md5 invalid\n");
return (CRYPTO_MECHANISM_INVALID);
}
if (status != CRYPTO_SUCCESS)
return (status);
/* Digest the MAC Key */
key.cd_miscdata = 0;
if (status != CRYPTO_SUCCESS)
return (status);
/* Digest the (copied) SMB header */
data.cd_miscdata = 0;
if (status != CRYPTO_SUCCESS)
return (status);
/* Digest rest of the SMB message. */
data.cd_miscdata = 0;
if (status != CRYPTO_SUCCESS)
return (status);
/* Final */
digest.cd_miscdata = 0;
if (status != CRYPTO_SUCCESS)
return (status);
/*
* Finally, store the signature.
* (first 8 bytes of the mac)
*/
if (signature)
return (0);
}
/*
* Sign a request with HMAC-MD5.
*/
int
{
int status;
/*
* Our mblk allocation ensures this,
* but just in case...
*/
return (0);
}
/*
* Signing is required, but we have no key yet
* fill in with the magic fake signing value.
* This happens with SPNEGO, NTLMSSP, ...
*/
return (0);
}
/*
* This will compute the MAC and store it
* directly into the message at sigloc.
*/
if (status != CRYPTO_SUCCESS) {
return (ENOTSUP);
}
return (0);
}
/*
* Verify reply signature.
*/
int
{
int status;
int fudge;
/*
* Note vc_mackey and vc_mackeylen gets initialized by
* smb_smb_ssnsetup.
*/
SMBSDEBUG("no mac key\n");
return (0);
}
/*
* Let caller deal with empty reply or short messages by
* returning zero. Caller will fail later, in parsing.
*/
SMBSDEBUG("empty reply\n");
return (0);
}
return (0);
}
if (status != CRYPTO_SUCCESS) {
/*
* If we can't compute a MAC, then there's
* no point trying other seqno values.
*/
return (EBADRPC);
}
/*
* Compare the computed signature with the
* one found in the message (at sigloc)
*/
return (0);
#ifdef DEBUG
/*
* of the sequence # has gotten a bit out of sync.
*/
break;
break;
}
}
if (fudge <= nsmb_signing_fudge) {
SMBSDEBUG("sr_rseqno=%d, but %d would have worked\n",
}
#endif
return (EBADRPC);
}