| package org.bouncycastle.crypto.tls; |
| |
| import java.security.SecureRandom; |
| |
| import org.bouncycastle.crypto.Digest; |
| import org.bouncycastle.crypto.prng.DigestRandomGenerator; |
| import org.bouncycastle.crypto.prng.RandomGenerator; |
| import org.bouncycastle.util.Times; |
| |
| abstract class AbstractTlsContext |
| implements TlsContext |
| { |
| private static long counter = Times.nanoTime(); |
| |
| private synchronized static long nextCounterValue() |
| { |
| return ++counter; |
| } |
| |
| private RandomGenerator nonceRandom; |
| private SecureRandom secureRandom; |
| private SecurityParameters securityParameters; |
| |
| private ProtocolVersion clientVersion = null; |
| private ProtocolVersion serverVersion = null; |
| private TlsSession session = null; |
| private Object userObject = null; |
| |
| AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters) |
| { |
| Digest d = TlsUtils.createHash(HashAlgorithm.sha256); |
| byte[] seed = new byte[d.getDigestSize()]; |
| secureRandom.nextBytes(seed); |
| |
| this.nonceRandom = new DigestRandomGenerator(d); |
| nonceRandom.addSeedMaterial(nextCounterValue()); |
| nonceRandom.addSeedMaterial(Times.nanoTime()); |
| nonceRandom.addSeedMaterial(seed); |
| |
| this.secureRandom = secureRandom; |
| this.securityParameters = securityParameters; |
| } |
| |
| public RandomGenerator getNonceRandomGenerator() |
| { |
| return nonceRandom; |
| } |
| |
| public SecureRandom getSecureRandom() |
| { |
| return secureRandom; |
| } |
| |
| public SecurityParameters getSecurityParameters() |
| { |
| return securityParameters; |
| } |
| |
| public ProtocolVersion getClientVersion() |
| { |
| return clientVersion; |
| } |
| |
| void setClientVersion(ProtocolVersion clientVersion) |
| { |
| this.clientVersion = clientVersion; |
| } |
| |
| public ProtocolVersion getServerVersion() |
| { |
| return serverVersion; |
| } |
| |
| void setServerVersion(ProtocolVersion serverVersion) |
| { |
| this.serverVersion = serverVersion; |
| } |
| |
| public TlsSession getResumableSession() |
| { |
| return session; |
| } |
| |
| void setResumableSession(TlsSession session) |
| { |
| this.session = session; |
| } |
| |
| public Object getUserObject() |
| { |
| return userObject; |
| } |
| |
| public void setUserObject(Object userObject) |
| { |
| this.userObject = userObject; |
| } |
| |
| public byte[] exportKeyingMaterial(String asciiLabel, byte[] context_value, int length) |
| { |
| if (context_value != null && !TlsUtils.isValidUint16(context_value.length)) |
| { |
| throw new IllegalArgumentException("'context_value' must have length less than 2^16 (or be null)"); |
| } |
| |
| SecurityParameters sp = getSecurityParameters(); |
| if (!sp.isExtendedMasterSecret()) |
| { |
| /* |
| * RFC 7627 5.4. If a client or server chooses to continue with a full handshake without |
| * the extended master secret extension, [..] the client or server MUST NOT export any |
| * key material based on the new master secret for any subsequent application-level |
| * authentication. In particular, it MUST disable [RFC5705] [..]. |
| */ |
| throw new IllegalStateException("cannot export keying material without extended_master_secret"); |
| } |
| |
| byte[] cr = sp.getClientRandom(), sr = sp.getServerRandom(); |
| |
| int seedLength = cr.length + sr.length; |
| if (context_value != null) |
| { |
| seedLength += (2 + context_value.length); |
| } |
| |
| byte[] seed = new byte[seedLength]; |
| int seedPos = 0; |
| |
| System.arraycopy(cr, 0, seed, seedPos, cr.length); |
| seedPos += cr.length; |
| System.arraycopy(sr, 0, seed, seedPos, sr.length); |
| seedPos += sr.length; |
| if (context_value != null) |
| { |
| TlsUtils.writeUint16(context_value.length, seed, seedPos); |
| seedPos += 2; |
| System.arraycopy(context_value, 0, seed, seedPos, context_value.length); |
| seedPos += context_value.length; |
| } |
| |
| if (seedPos != seedLength) |
| { |
| throw new IllegalStateException("error in calculation of seed for export"); |
| } |
| |
| return TlsUtils.PRF(this, sp.getMasterSecret(), asciiLabel, seed, length); |
| } |
| } |