mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-08-11 01:49:18 +02:00
Added logic to calculate SMB 3.x encryption / decryption keys
This commit is contained in:
parent
cdd3d182b5
commit
70bd235395
3 changed files with 107 additions and 0 deletions
53
SMBLibrary/Helpers/SP800_1008.cs
Normal file
53
SMBLibrary/Helpers/SP800_1008.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
52
SMBLibrary/SMB2/SMB2Cryptography.cs
Normal file
52
SMBLibrary/SMB2/SMB2Cryptography.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -74,6 +74,8 @@
|
|||
<Compile Include="Enums\Win32Error.cs" />
|
||||
<Compile Include="Exceptions\UnsupportedInformationLevelException.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\NameRecordType.cs" />
|
||||
<Compile Include="NetBios\NameServicePackets\Enums\NameServiceOperation.cs" />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue