Added logic to calculate SMB 3.x encryption / decryption keys

This commit is contained in:
TalAloni 2020-11-13 15:43:40 +02:00
parent cdd3d182b5
commit 70bd235395
3 changed files with 107 additions and 0 deletions

View file

@ -0,0 +1,53 @@
/// Adapted from https://referencesource.microsoft.com/#system.web/Security/Cryptography/SP800_108.cs
using System;
using System.Security.Cryptography;
using Utilities;
namespace SMBLibrary
{
/// <summary>
/// Implements the NIST SP800-108 key derivation routine in counter mode with an HMAC PRF.
/// See: http://csrc.nist.gov/publications/nistpubs/800-108/sp800-108.pdf
/// </summary>
internal class SP800_1008
{
public static byte[] DeriveKey(HMAC hmac, byte[] label, byte[] context, int keyLengthInBits)
{
int labelLength = (label != null) ? label.Length : 0;
int contextLength = (context != null) ? context.Length : 0;
byte[] buffer = new byte[4 /* [i]_2 */ + labelLength /* label */ + 1 /* 0x00 */ + contextLength /* context */ + 4 /* [L]_2 */];
if (labelLength != 0)
{
Buffer.BlockCopy(label, 0, buffer, 4, labelLength); // the 4 accounts for the [i]_2 length
}
if (contextLength != 0)
{
Buffer.BlockCopy(context, 0, buffer, 5 + labelLength, contextLength); // the '5 +' accounts for the [i]_2 length, the label, and the 0x00 byte
}
BigEndianWriter.WriteUInt32(buffer, 5 + labelLength + contextLength, (uint)keyLengthInBits); // the '5 +' accounts for the [i]_2 length, the label, the 0x00 byte, and the context
// Initialization
int numBytesWritten = 0;
int numBytesRemaining = keyLengthInBits / 8;
byte[] output = new byte[numBytesRemaining];
// Calculate each K_i value and copy the leftmost bits to the output buffer as appropriate.
for (uint i = 1; numBytesRemaining > 0; i++)
{
BigEndianWriter.WriteUInt32(buffer, 0, i); // set the first 32 bits of the buffer to be the current iteration value
byte[] K_i = hmac.ComputeHash(buffer);
// copy the leftmost bits of K_i into the output buffer
int numBytesToCopy = Math.Min(numBytesRemaining, K_i.Length);
Buffer.BlockCopy(K_i, 0, output, numBytesWritten, numBytesToCopy);
numBytesWritten += numBytesToCopy;
numBytesRemaining -= numBytesToCopy;
}
// finished
return output;
}
}
}

View file

@ -0,0 +1,52 @@
/* Copyright (C) 2020 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*/
using System;
using System.Security.Cryptography;
using Utilities;
namespace SMBLibrary.SMB2
{
internal class SMB2Cryptography
{
public static byte[] GenerateEncryptionKey(byte[] sessionKey, SMB2Dialect dialect, byte[] preauthIntegrityHashValue)
{
if (dialect == SMB2Dialect.SMB311 && preauthIntegrityHashValue == null)
{
throw new ArgumentNullException("preauthIntegrityHashValue");
}
string labelString = (dialect == SMB2Dialect.SMB311) ? "SMBC2SCipherKey" : "SMB2AESCCM";
byte[] label = GetNullTerminatedAnsiString(labelString);
byte[] context = (dialect == SMB2Dialect.SMB311) ? preauthIntegrityHashValue : GetNullTerminatedAnsiString("ServerIn ");
HMACSHA256 hmac = new HMACSHA256(sessionKey);
return SP800_1008.DeriveKey(hmac, label, context, 128);
}
public static byte[] GenerateDecryptionKey(byte[] sessionKey, SMB2Dialect dialect, byte[] preauthIntegrityHashValue)
{
if (dialect == SMB2Dialect.SMB311 && preauthIntegrityHashValue == null)
{
throw new ArgumentNullException("preauthIntegrityHashValue");
}
string labelString = (dialect == SMB2Dialect.SMB311) ? "SMBS2CCipherKey" : "SMB2AESCCM";
byte[] label = GetNullTerminatedAnsiString(labelString);
byte[] context = (dialect == SMB2Dialect.SMB311) ? preauthIntegrityHashValue : GetNullTerminatedAnsiString("ServerOut");
HMACSHA256 hmac = new HMACSHA256(sessionKey);
return SP800_1008.DeriveKey(hmac, label, context, 128);
}
private static byte[] GetNullTerminatedAnsiString(string value)
{
byte[] result = new byte[value.Length + 1];
ByteWriter.WriteNullTerminatedAnsiString(result, 0, value);
return result;
}
}
}

View file

@ -74,6 +74,8 @@
<Compile Include="Enums\Win32Error.cs" /> <Compile Include="Enums\Win32Error.cs" />
<Compile Include="Exceptions\UnsupportedInformationLevelException.cs" /> <Compile Include="Exceptions\UnsupportedInformationLevelException.cs" />
<Compile Include="Helpers\FileTimeHelper.cs" /> <Compile Include="Helpers\FileTimeHelper.cs" />
<Compile Include="Helpers\SP800_1008.cs" />
<Compile Include="SMB2\SMB2Cryptography.cs" />
<Compile Include="NetBios\NameServicePackets\Enums\ResourceRecordClass.cs" /> <Compile Include="NetBios\NameServicePackets\Enums\ResourceRecordClass.cs" />
<Compile Include="NetBios\NameServicePackets\Enums\NameRecordType.cs" /> <Compile Include="NetBios\NameServicePackets\Enums\NameRecordType.cs" />
<Compile Include="NetBios\NameServicePackets\Enums\NameServiceOperation.cs" /> <Compile Include="NetBios\NameServicePackets\Enums\NameServiceOperation.cs" />