|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package com.sun.crypto.provider; |
|
|
|
import java.security.*; |
|
import java.security.spec.AlgorithmParameterSpec; |
|
|
|
import javax.crypto.*; |
|
|
|
import sun.security.internal.interfaces.TlsMasterSecret; |
|
import sun.security.internal.spec.TlsMasterSecretParameterSpec; |
|
|
|
import static com.sun.crypto.provider.TlsPrfGenerator.*; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class TlsMasterSecretGenerator extends KeyGeneratorSpi { |
|
|
|
private final static String MSG = "TlsMasterSecretGenerator must be " |
|
+ "initialized using a TlsMasterSecretParameterSpec"; |
|
|
|
private TlsMasterSecretParameterSpec spec; |
|
|
|
private int protocolVersion; |
|
|
|
public TlsMasterSecretGenerator() { |
|
} |
|
|
|
protected void engineInit(SecureRandom random) { |
|
throw new InvalidParameterException(MSG); |
|
} |
|
|
|
protected void engineInit(AlgorithmParameterSpec params, |
|
SecureRandom random) throws InvalidAlgorithmParameterException { |
|
if (params instanceof TlsMasterSecretParameterSpec == false) { |
|
throw new InvalidAlgorithmParameterException(MSG); |
|
} |
|
this.spec = (TlsMasterSecretParameterSpec)params; |
|
if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) { |
|
throw new InvalidAlgorithmParameterException( |
|
"Key format must be RAW"); |
|
} |
|
protocolVersion = (spec.getMajorVersion() << 8) |
|
| spec.getMinorVersion(); |
|
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) { |
|
throw new InvalidAlgorithmParameterException( |
|
"Only SSL 3.0, TLS 1.0/1.1/1.2 supported"); |
|
} |
|
} |
|
|
|
protected void engineInit(int keysize, SecureRandom random) { |
|
throw new InvalidParameterException(MSG); |
|
} |
|
|
|
protected SecretKey engineGenerateKey() { |
|
if (spec == null) { |
|
throw new IllegalStateException( |
|
"TlsMasterSecretGenerator must be initialized"); |
|
} |
|
SecretKey premasterKey = spec.getPremasterSecret(); |
|
byte[] premaster = premasterKey.getEncoded(); |
|
|
|
int premasterMajor, premasterMinor; |
|
if (premasterKey.getAlgorithm().equals("TlsRsaPremasterSecret")) { |
|
|
|
premasterMajor = premaster[0] & 0xff; |
|
premasterMinor = premaster[1] & 0xff; |
|
} else { |
|
|
|
premasterMajor = -1; |
|
premasterMinor = -1; |
|
} |
|
|
|
try { |
|
byte[] master; |
|
if (protocolVersion >= 0x0301) { |
|
byte[] label; |
|
byte[] seed; |
|
byte[] extendedMasterSecretSessionHash = |
|
spec.getExtendedMasterSecretSessionHash(); |
|
if (extendedMasterSecretSessionHash.length != 0) { |
|
label = LABEL_EXTENDED_MASTER_SECRET; |
|
seed = extendedMasterSecretSessionHash; |
|
} else { |
|
byte[] clientRandom = spec.getClientRandom(); |
|
byte[] serverRandom = spec.getServerRandom(); |
|
label = LABEL_MASTER_SECRET; |
|
seed = concat(clientRandom, serverRandom); |
|
} |
|
master = ((protocolVersion >= 0x0303) ? |
|
doTLS12PRF(premaster, label, seed, 48, |
|
spec.getPRFHashAlg(), spec.getPRFHashLength(), |
|
spec.getPRFBlockSize()) : |
|
doTLS10PRF(premaster, label, seed, 48)); |
|
} else { |
|
master = new byte[48]; |
|
MessageDigest md5 = MessageDigest.getInstance("MD5"); |
|
MessageDigest sha = MessageDigest.getInstance("SHA"); |
|
|
|
byte[] clientRandom = spec.getClientRandom(); |
|
byte[] serverRandom = spec.getServerRandom(); |
|
byte[] tmp = new byte[20]; |
|
for (int i = 0; i < 3; i++) { |
|
sha.update(SSL3_CONST[i]); |
|
sha.update(premaster); |
|
sha.update(clientRandom); |
|
sha.update(serverRandom); |
|
sha.digest(tmp, 0, 20); |
|
|
|
md5.update(premaster); |
|
md5.update(tmp); |
|
md5.digest(master, i << 4, 16); |
|
} |
|
|
|
} |
|
|
|
return new TlsMasterSecretKey(master, premasterMajor, |
|
premasterMinor); |
|
} catch (NoSuchAlgorithmException e) { |
|
throw new ProviderException(e); |
|
} catch (DigestException e) { |
|
throw new ProviderException(e); |
|
} |
|
} |
|
|
|
private static final class TlsMasterSecretKey implements TlsMasterSecret { |
|
private static final long serialVersionUID = 1019571680375368880L; |
|
|
|
private byte[] key; |
|
private final int majorVersion, minorVersion; |
|
|
|
TlsMasterSecretKey(byte[] key, int majorVersion, int minorVersion) { |
|
this.key = key; |
|
this.majorVersion = majorVersion; |
|
this.minorVersion = minorVersion; |
|
} |
|
|
|
public int getMajorVersion() { |
|
return majorVersion; |
|
} |
|
|
|
public int getMinorVersion() { |
|
return minorVersion; |
|
} |
|
|
|
public String getAlgorithm() { |
|
return "TlsMasterSecret"; |
|
} |
|
|
|
public String getFormat() { |
|
return "RAW"; |
|
} |
|
|
|
public byte[] getEncoded() { |
|
return key.clone(); |
|
} |
|
|
|
} |
|
} |
|
|