jcifs.internal.smb2.Smb3KeyDerivation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcifs-ng Show documentation
Show all versions of jcifs-ng Show documentation
A pure-java CIFS/SMB client library
/*
* © 2017 AgNO3 Gmbh & Co. KG
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jcifs.internal.smb2;
import java.nio.charset.StandardCharsets;
import org.bouncycastle.crypto.DerivationParameters;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.generators.KDFCounterBytesGenerator;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KDFCounterParameters;
/**
* SMB3 SP800-108 Counter Mode Key Derivation
*
* @author mbechler
*
*/
final class Smb3KeyDerivation {
private static final byte[] SIGNCONTEXT_300 = toCBytes("SmbSign");
private static final byte[] SIGNLABEL_300 = toCBytes("SMB2AESCMAC");
private static final byte[] SIGNLABEL_311 = toCBytes("SMBSigningKey");
private static final byte[] APPCONTEXT_300 = toCBytes("SmbRpc");
private static final byte[] APPLABEL_300 = toCBytes("SMB2APP");
private static final byte[] APPLABEL_311 = toCBytes("SMBAppKey");
private static final byte[] ENCCONTEXT_300 = toCBytes("ServerIn "); // there really is a space there
private static final byte[] ENCLABEL_300 = toCBytes("SMB2AESCCM");
private static final byte[] ENCLABEL_311 = toCBytes("SMB2C2SCipherKey");
private static final byte[] DECCONTEXT_300 = toCBytes("ServerOut");
private static final byte[] DECLABEL_300 = toCBytes("SMB2AESCCM");
private static final byte[] DECLABEL_311 = toCBytes("SMB2S2CCipherKey");
/**
*
*/
private Smb3KeyDerivation () {}
/**
*
* @param dialect
* @param sessionKey
* @param preauthIntegrity
* @return derived signing key
*/
public static byte[] deriveSigningKey ( int dialect, byte[] sessionKey, byte[] preauthIntegrity ) {
return derive(
sessionKey,
dialect == Smb2Constants.SMB2_DIALECT_0311 ? SIGNLABEL_311 : SIGNLABEL_300,
dialect == Smb2Constants.SMB2_DIALECT_0311 ? preauthIntegrity : SIGNCONTEXT_300);
}
/**
*
* @param dialect
* @param sessionKey
* @param preauthIntegrity
* @return derived application key
*/
public static byte[] dervieApplicationKey ( int dialect, byte[] sessionKey, byte[] preauthIntegrity ) {
return derive(
sessionKey,
dialect == Smb2Constants.SMB2_DIALECT_0311 ? APPLABEL_311 : APPLABEL_300,
dialect == Smb2Constants.SMB2_DIALECT_0311 ? preauthIntegrity : APPCONTEXT_300);
}
/**
*
* @param dialect
* @param sessionKey
* @param preauthIntegrity
* @return derived encryption key
*/
public static byte[] deriveEncryptionKey ( int dialect, byte[] sessionKey, byte[] preauthIntegrity ) {
return derive(
sessionKey,
dialect == Smb2Constants.SMB2_DIALECT_0311 ? ENCLABEL_311 : ENCLABEL_300,
dialect == Smb2Constants.SMB2_DIALECT_0311 ? preauthIntegrity : ENCCONTEXT_300);
}
/**
*
* @param dialect
* @param sessionKey
* @param preauthIntegrity
* @return derived decryption key
*/
public static byte[] deriveDecryptionKey ( int dialect, byte[] sessionKey, byte[] preauthIntegrity ) {
return derive(
sessionKey,
dialect == Smb2Constants.SMB2_DIALECT_0311 ? DECLABEL_311 : DECLABEL_300,
dialect == Smb2Constants.SMB2_DIALECT_0311 ? preauthIntegrity : DECCONTEXT_300);
}
/**
* @param sessionKey
* @param label
* @param context
*/
private static byte[] derive ( byte[] sessionKey, byte[] label, byte[] context ) {
KDFCounterBytesGenerator gen = new KDFCounterBytesGenerator(new HMac(new SHA256Digest()));
int r = 32;
byte[] suffix = new byte[label.length + context.length + 5];
// per bouncycastle
// 1: K(i) := PRF( KI, [i]_2 || Label || 0x00 || Context || [L]_2 ) with the counter at the very beginning
// of the fixedInputData (The default implementation has this format)
// with the parameters
// 1. KDFCounterParameters(ki, null, "Label || 0x00 || Context || [L]_2]", 8);
// all fixed inputs go into the suffix:
// + label
System.arraycopy(label, 0, suffix, 0, label.length);
// + 1 byte 0x00
// + context
System.arraycopy(context, 0, suffix, label.length + 1, context.length);
// + 4 byte (== r bits) big endian encoding of L
suffix[ suffix.length - 1 ] = (byte) 128;
DerivationParameters param = new KDFCounterParameters(sessionKey, null /* prefix */, suffix /* suffix */, r /* r */);
gen.init(param);
byte[] derived = new byte[16];
gen.generateBytes(derived, 0, 16);
return derived;
}
/**
* @param string
* @return null terminated ASCII bytes
*/
private static byte[] toCBytes ( String string ) {
byte[] data = new byte[string.length() + 1];
System.arraycopy(string.getBytes(StandardCharsets.US_ASCII), 0, data, 0, string.length());
return data;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy