smb_crypt.c revision 124087
1139825Simp/* 21541Srgrimes * Copyright (c) 2000-2001, Boris Popov 31541Srgrimes * All rights reserved. 41541Srgrimes * 51541Srgrimes * Copyright (c) 2003, 2004 Tim J. Robbins. 61541Srgrimes * All rights reserved. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms, with or without 91541Srgrimes * modification, are permitted provided that the following conditions 101541Srgrimes * are met: 111541Srgrimes * 1. Redistributions of source code must retain the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer. 131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer in the 151541Srgrimes * documentation and/or other materials provided with the distribution. 161541Srgrimes * 3. All advertising materials mentioning features or use of this software 171541Srgrimes * must display the following acknowledgement: 181541Srgrimes * This product includes software developed by Boris Popov. 191541Srgrimes * 4. Neither the name of the author nor the names of any co-contributors 201541Srgrimes * may be used to endorse or promote products derived from this software 211541Srgrimes * without specific prior written permission. 221541Srgrimes * 231541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 241541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 251541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 261541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 271541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 281541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 291541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 301541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 311541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32116226Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33116226Sobrien * SUCH DAMAGE. 34116226Sobrien */ 351541Srgrimes 361541Srgrimes#include <sys/cdefs.h> 371541Srgrimes__FBSDID("$FreeBSD: head/sys/netsmb/smb_crypt.c 124087 2004-01-02 22:38:42Z tjr $"); 3876166Smarkm 3976166Smarkm#include <sys/param.h> 4076166Smarkm#include <sys/malloc.h> 4134924Sbde#include <sys/kernel.h> 4274927Sjhb#include <sys/systm.h> 4312662Sdg#include <sys/conf.h> 4493823Sdillon#include <sys/proc.h> 4512662Sdg#include <sys/fcntl.h> 461541Srgrimes#include <sys/socket.h> 4740794Speter#include <sys/socketvar.h> 4812726Sbde#include <sys/sysctl.h> 4912662Sdg#include <sys/endian.h> 5012662Sdg#include <sys/mbuf.h> 5112662Sdg#include <sys/mchain.h> 5212662Sdg#include <sys/md4.h> 531541Srgrimes#include <sys/md5.h> 541541Srgrimes#include <sys/iconv.h> 559759Sbde 561541Srgrimes#include <netsmb/smb.h> 5776778Sjhb#include <netsmb/smb_conn.h> 581541Srgrimes#include <netsmb/smb_subr.h> 5962622Sjhb#include <netsmb/smb_rq.h> 6012286Sphk#include <netsmb/smb_dev.h> 6162622Sjhb 6212286Sphk#include "opt_netsmb.h" 6362622Sjhb 6412286Sphk#ifdef NETSMBCRYPTO 6562622Sjhb 6612286Sphk#include <crypto/des/des.h> 6762622Sjhb 6812286Sphkstatic u_char N8[] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; 6962622Sjhb 7012286Sphk 7162622Sjhbstatic void 7212286Sphksmb_E(const u_char *key, u_char *data, u_char *dest) 7362622Sjhb{ 7451337Sdillon des_key_schedule *ksp; 7512286Sphk u_char kk[8]; 76136404Speter 77136404Speter kk[0] = key[0] & 0xfe; 78136404Speter kk[1] = key[0] << 7 | (key[1] >> 1 & 0xfe); 79136404Speter kk[2] = key[1] << 6 | (key[2] >> 2 & 0xfe); 80136404Speter kk[3] = key[2] << 5 | (key[3] >> 3 & 0xfe); 811541Srgrimes kk[4] = key[3] << 4 | (key[4] >> 4 & 0xfe); 82136404Speter kk[5] = key[4] << 3 | (key[5] >> 5 & 0xfe); 83136404Speter kk[6] = key[5] << 2 | (key[6] >> 6 & 0xfe); 84136404Speter kk[7] = key[6] << 1; 85136404Speter ksp = malloc(sizeof(des_key_schedule), M_SMBTEMP, M_WAITOK); 86136404Speter des_set_key((des_cblock *)kk, *ksp); 87136404Speter des_ecb_encrypt((des_cblock *)data, (des_cblock *)dest, *ksp, 1); 88136404Speter free(ksp, M_SMBTEMP); 89136404Speter} 90136404Speter#endif 91136404Speter 92136404Speter 93136404Speterint 94136404Spetersmb_encrypt(const u_char *apwd, u_char *C8, u_char *RN) 9512286Sphk{ 9662573Sphk#ifdef NETSMBCRYPTO 971541Srgrimes u_char *p, *P14, *S21; 9899072Sjulian 9912286Sphk p = malloc(14 + 21, M_SMBTEMP, M_WAITOK); 100164437Sru bzero(p, 14 + 21); 10112286Sphk P14 = p; 10212286Sphk S21 = p + 14; 10312286Sphk bcopy(apwd, P14, min(14, strlen(apwd))); 1041541Srgrimes /* 10599072Sjulian * S21 = concat(Ex(P14, N8), zeros(5)); 106159054Stegge */ 1071541Srgrimes smb_E(P14, N8, S21); 108164437Sru smb_E(P14 + 7, N8, S21 + 8); 1091541Srgrimes 1101541Srgrimes smb_E(S21, C8, RN); 1111541Srgrimes smb_E(S21 + 7, C8, RN + 8); 11279224Sdillon smb_E(S21 + 14, C8, RN + 16); 11395112Salc free(p, M_SMBTEMP); 114108551Salc return 0; 115124083Salc#else 116124083Salc SMBERROR("password encryption is not available\n"); 117124083Salc bzero(RN, 24); 118124083Salc return EAUTH; 119124083Salc#endif 120124083Salc} 121124083Salc 122124083Salcint 12338517Sdfrsmb_ntencrypt(const u_char *apwd, u_char *C8, u_char *RN) 124113448Salc{ 125108551Salc#ifdef NETSMBCRYPTO 12695112Salc u_char S21[21]; 1271541Srgrimes u_int16_t *unipwd; 1281541Srgrimes MD4_CTX *ctxp; 1291541Srgrimes int len; 13074927Sjhb 13183366Sjulian len = strlen(apwd); 1321541Srgrimes unipwd = malloc((len + 1) * sizeof(u_int16_t), M_SMBTEMP, M_WAITOK); 1331541Srgrimes /* 13472200Sbmilekic * S21 = concat(MD4(U(apwd)), zeros(5)); 13599072Sjulian */ 13699072Sjulian smb_strtouni(unipwd, apwd); 13772200Sbmilekic ctxp = malloc(sizeof(MD4_CTX), M_SMBTEMP, M_WAITOK); 1381541Srgrimes MD4Init(ctxp); 1391541Srgrimes MD4Update(ctxp, (u_char*)unipwd, len * sizeof(u_int16_t)); 14099072Sjulian free(unipwd, M_SMBTEMP); 14199072Sjulian bzero(S21, 21); 142103216Sjulian MD4Final(S21, ctxp); 14399072Sjulian free(ctxp, M_SMBTEMP); 144103216Sjulian 145104387Sjhb smb_E(S21, C8, RN); 146103216Sjulian smb_E(S21 + 7, C8, RN + 8); 147103216Sjulian smb_E(S21 + 14, C8, RN + 16); 148164437Sru return 0; 149103216Sjulian#else 150103216Sjulian SMBERROR("password encryption is not available\n"); 151103216Sjulian bzero(RN, 24); 15299072Sjulian return EAUTH; 153164437Sru#endif 154103216Sjulian} 155164437Sru 15699072Sjulian/* 15799072Sjulian * Calculate message authentication code (MAC) key for virtual circuit. 1581541Srgrimes */ 159103216Sjulianint 160164437Srusmb_calcmackey(struct smb_vc *vcp) 161103216Sjulian{ 16299072Sjulian#ifdef NETSMBCRYPTO 16399072Sjulian const char *pwd; 164164437Sru u_int16_t *unipwd; 16599072Sjulian int len; 16699072Sjulian MD4_CTX md4; 16799072Sjulian u_char S16[16], S21[21]; 16899072Sjulian 16971572Sjhb KASSERT(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE, 1701541Srgrimes ("signatures not enabled")); 17172200Sbmilekic 1721541Srgrimes if (vcp->vc_mackey != NULL) { 1731541Srgrimes free(vcp->vc_mackey, M_SMBTEMP); 1741541Srgrimes vcp->vc_mackey = NULL; 1751541Srgrimes vcp->vc_mackeylen = 0; 176159054Stegge vcp->vc_seqno = 0; 177159054Stegge } 178159054Stegge 179159054Stegge /* 180108585Salc * The partial MAC key is the concatenation of the 16 byte session 181108585Salc * key and the 24 byte challenge response. 1825455Sdg */ 18343748Sdillon vcp->vc_mackeylen = 16 + 24; 184108585Salc vcp->vc_mackey = malloc(vcp->vc_mackeylen, M_SMBTEMP, M_WAITOK); 1851541Srgrimes 186113448Salc /* 187108585Salc * Calculate session key: 188108585Salc * MD4(MD4(U(PN))) 189113448Salc */ 1901541Srgrimes pwd = smb_vc_getpass(vcp); 191108585Salc len = strlen(pwd); 192159054Stegge unipwd = malloc((len + 1) * sizeof(u_int16_t), M_SMBTEMP, M_WAITOK); 1931541Srgrimes smb_strtouni(unipwd, pwd); 194164437Sru MD4Init(&md4); 1951541Srgrimes MD4Update(&md4, (u_char *)unipwd, len * sizeof(u_int16_t)); 19674927Sjhb MD4Final(S16, &md4); 1971541Srgrimes MD4Init(&md4); 1981541Srgrimes MD4Update(&md4, S16, 16); 1991541Srgrimes MD4Final(vcp->vc_mackey, &md4); 20095112Salc free(unipwd, M_SMBTEMP); 20175523Salfred 20242957Sdillon /* 203124083Salc * Calculate response to challenge: 204124083Salc * Ex(concat(MD4(U(pass)), zeros(5)), C8) 205124083Salc */ 206124083Salc bzero(S21, 21); 20742957Sdillon bcopy(S16, S21, 16); 208108585Salc smb_E(S21, vcp->vc_ch, vcp->vc_mackey + 16); 209124083Salc smb_E(S21 + 7, vcp->vc_ch, vcp->vc_mackey + 24); 210124083Salc smb_E(S21 + 14, vcp->vc_ch, vcp->vc_mackey + 32); 211124083Salc 21242957Sdillon return (0); 213108585Salc#else 214164429Sru panic("smb_calcmackey: encryption not available"); 215164429Sru return (0); 216164429Sru#endif /* NETSMBCRYPTO */ 217164429Sru} 218164429Sru 219164429Sru/* 220164429Sru * Sign request with MAC. 221164437Sru */ 222164437Sruint 2231541Srgrimessmb_rq_sign(struct smb_rq *rqp) 224164437Sru{ 225164437Sru#ifdef NETSMBCRYPTO 2261541Srgrimes struct smb_vc *vcp = rqp->sr_vc; 22718169Sdyson struct mbchain *mbp; 2281541Srgrimes struct mbuf *mb; 229164437Sru MD5_CTX md5; 230164437Sru u_char digest[16]; 2311541Srgrimes 232164437Sru KASSERT(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE, 233164437Sru ("signatures not enabled")); 2341541Srgrimes 2351541Srgrimes if (vcp->vc_mackey == NULL) 2361541Srgrimes /* XXX Should assert that cmd == SMB_COM_NEGOTIATE. */ 23795112Salc return (0); 238164437Sru 239164437Sru /* 2401541Srgrimes * This is a bit of a kludge. If the request is non-TRANSACTION, 24112286Sphk * or it is the first request of a transaction, give it the next 24293823Sdillon * sequence number, and expect the reply to have the sequence number 24393823Sdillon * following that one. Otherwise, it is a secondary request in 24493823Sdillon * a transaction, and it gets the same sequence numbers as the 24593823Sdillon * primary request. 24693823Sdillon */ 24793823Sdillon if (rqp->sr_t2 == NULL || 24893823Sdillon (rqp->sr_t2->t2_flags & SMBT2_SECONDARY) == 0) { 24993823Sdillon rqp->sr_seqno = vcp->vc_seqno++; 25093823Sdillon rqp->sr_rseqno = vcp->vc_seqno++; 25193823Sdillon } else { 25293823Sdillon /* 25393823Sdillon * Sequence numbers are already in the struct because 25493823Sdillon * smb_t2_request_int() uses the same one for all the 25593823Sdillon * requests in the transaction. 25693823Sdillon * (At least we hope so.) 25793823Sdillon */ 258144970Sjhb KASSERT(rqp->sr_t2 == NULL || 25993823Sdillon (rqp->sr_t2->t2_flags & SMBT2_SECONDARY) == 0 || 26093823Sdillon rqp->sr_t2->t2_rq == rqp, 26193823Sdillon ("sec t2 rq not using same smb_rq")); 26293823Sdillon } 26393823Sdillon 26493823Sdillon /* Initialize sec. signature field to sequence number + zeros. */ 26593823Sdillon *(u_int32_t *)rqp->sr_rqsig = htole32(rqp->sr_seqno); 266108171Sdillon *(u_int32_t *)(rqp->sr_rqsig + 4) = 0; 267108171Sdillon 26893823Sdillon /* 269144970Sjhb * Compute HMAC-MD5 of packet data, keyed by MAC key. 27093823Sdillon * Store the first 8 bytes in the sec. signature field. 27193823Sdillon */ 272109097Sdillon smb_rq_getrequest(rqp, &mbp); 27346381Sbillf MD5Init(&md5); 27446381Sbillf MD5Update(&md5, vcp->vc_mackey, vcp->vc_mackeylen); 275141696Sphk for (mb = mbp->mb_top; mb != NULL; mb = mb->m_next) 276141630Sphk MD5Update(&md5, mtod(mb, void *), mb->m_len); 277141630Sphk MD5Final(digest, &md5); 278141630Sphk bcopy(digest, rqp->sr_rqsig, 8); 279141630Sphk 28040794Speter return (0); 28193823Sdillon#else 28293823Sdillon panic("smb_rq_sign: encryption not available"); 28393823Sdillon return (0); 28493823Sdillon#endif /* NETSMBCRYPTO */ 28593823Sdillon} 28693823Sdillon 28793823Sdillon/* 28893823Sdillon * Verify reply signature. 28993823Sdillon */ 29093823Sdillonint 29193823Sdillonsmb_rq_verify(struct smb_rq *rqp) 29293823Sdillon{ 29393823Sdillon#ifdef NETSMBCRYPTO 29493823Sdillon struct smb_vc *vcp = rqp->sr_vc; 29593823Sdillon struct mdchain *mdp; 29693823Sdillon u_char sigbuf[8]; 29793823Sdillon MD5_CTX md5; 29893823Sdillon u_char digest[16]; 29993823Sdillon struct mbuf *mb; 30093823Sdillon 30193823Sdillon KASSERT(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE, 30293823Sdillon ("signatures not enabled")); 30393823Sdillon 30493823Sdillon if (vcp->vc_mackey == NULL) 30593823Sdillon /* XXX Should check that this is a SMB_COM_NEGOTIATE reply. */ 30693823Sdillon return (0); 30793823Sdillon 30893823Sdillon /* 30993823Sdillon * Compute HMAC-MD5 of packet data, keyed by MAC key. 31093823Sdillon * We play games to pretend the security signature field 31193823Sdillon * contains their sequence number, to avoid modifying 31293823Sdillon * the packet itself. 31393823Sdillon */ 31493823Sdillon smb_rq_getreply(rqp, &mdp); 31593823Sdillon mb = mdp->md_top; 31693823Sdillon KASSERT(mb->m_len >= SMB_HDRLEN, ("forgot to m_pullup")); 31793823Sdillon MD5Init(&md5); 31893823Sdillon MD5Update(&md5, vcp->vc_mackey, vcp->vc_mackeylen); 31993823Sdillon MD5Update(&md5, mtod(mb, void *), 14); 32093823Sdillon *(u_int32_t *)sigbuf = htole32(rqp->sr_rseqno); 32193823Sdillon *(u_int32_t *)(sigbuf + 4) = 0; 32293823Sdillon MD5Update(&md5, sigbuf, 8); 32393823Sdillon MD5Update(&md5, mtod(mb, u_char *) + 22, mb->m_len - 22); 32493823Sdillon for (mb = mb->m_next; mb != NULL; mb = mb->m_next) 32593823Sdillon MD5Update(&md5, mtod(mb, void *), mb->m_len); 32693823Sdillon MD5Final(digest, &md5); 32793823Sdillon 32893823Sdillon /* 32993823Sdillon * Now verify the signature. 33093823Sdillon */ 33193823Sdillon if (bcmp(mtod(mdp->md_top, u_char *) + 14, digest, 8) != 0) 33293823Sdillon return (EAUTH); 33393823Sdillon 33493823Sdillon return (0); 33593823Sdillon#else 33693823Sdillon panic("smb_rq_verify: encryption not available"); 33793823Sdillon return (0); 33893823Sdillon#endif /* NETSMBCRYPTO */ 33993823Sdillon} 34093823Sdillon