All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jcifs.internal.smb2.Smb3KeyDerivation Maven / Gradle / Ivy

There is a newer version: 2.1.10
Show newest version
/*
 * © 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