/**
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
*
* Copyright 2014-2016 Ruhr University Bochum / Hackmanit GmbH
*
* Licensed under Apache License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*/
package de.rub.nds.tlsattacker.tls.crypto;
import de.rub.nds.tlsattacker.tls.constants.PRFAlgorithm;
import de.rub.nds.tlsattacker.tls.exceptions.CryptoException;
import de.rub.nds.tlsattacker.util.ArrayConverter;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.crypto.tls.TlsUtils;
/**
* Pseudo random function computation for TLS 1.0 - 1.2 (for TLS 1.0, bouncy
* castle TlsUtils are used)
*
* @author Juraj Somorovsky <juraj.somorovsky@rub.de>
*/
public final class PseudoRandomFunction {
/** master secret label */
public static final String MASTER_SECRET_LABEL = "master secret";
/** client finished label */
public static final String CLIENT_FINISHED_LABEL = "client finished";
/** server finished label */
public static final String SERVER_FINISHED_LABEL = "server finished";
/** key expansion label */
public static final String KEY_EXPANSION_LABEL = "key expansion";
private PseudoRandomFunction() {
}
/**
* Computes PRF output of the provided size using the given mac algorithm
*
* @param prfAlgorithm
* @param secret
* @param label
* @param seed
* @param size
* @return
*/
public static byte[] compute(PRFAlgorithm prfAlgorithm, byte[] secret, String label, byte[] seed, int size) {
switch (prfAlgorithm) {
case TLS_PRF_SHA256:
case TLS_PRF_SHA384:
return computeTls12(secret, label, seed, size, prfAlgorithm.getMacAlgorithm().getJavaName());
case TLS_PRF_LEGACY:
// prf legacy is the prf computation function for older protocol
// versions, it works by default with sha1 and md5
return TlsUtils.PRF_legacy(secret, label, seed, size);
default:
throw new UnsupportedOperationException("PRF computation for different"
+ " protocol versions is not supported yet");
}
}
/**
* PRF computation for TLS 1.2
*
* @param secret
* @param label
* @param seed
* @param size
* @param macAlgorithm
* @return
*/
private static byte[] computeTls12(byte[] secret, String label, byte[] seed, int size, String macAlgorithm) {
try {
byte[] labelSeed = ArrayConverter.concatenate(label.getBytes(), seed);
SecretKeySpec keySpec = new SecretKeySpec(secret, macAlgorithm);
Mac mac = Mac.getInstance(macAlgorithm);
mac.init(keySpec);
byte[] out = new byte[0];
byte[] ai = labelSeed;
byte[] buf;
byte[] buf2;
while (out.length < size) {
mac.update(ai);
buf = mac.doFinal();
ai = buf;
mac.update(ai);
mac.update(labelSeed);
buf2 = mac.doFinal();
out = ArrayConverter.concatenate(out, buf2);
}
return Arrays.copyOf(out, size);
} catch (NoSuchAlgorithmException | InvalidKeyException ex) {
throw new CryptoException(ex);
}
}
}