Skip to content

Commit bb11073

Browse files
committed
Merge branch 'main' of gitlab.cryptoworkshop.com:root/bc-java
2 parents 6ca791b + 1c0d331 commit bb11073

File tree

5 files changed

+67
-19
lines changed

5 files changed

+67
-19
lines changed

docs/releasenotes.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ <h2>2.0 Release History</h2>
2424
<h3>2.1.2 Defects Fixed</h3>
2525
<ul>
2626
<li>SNOVA and MAYO are now correctly added to the JCA provider module-info file.</li>
27+
<li>TLS: Avoid nonce reuse error in JCE AEAD workaround for pre-Java7.</li>
2728
</ul>
2829
<h3>2.1.3 Additional Features and Functionality</h3>
2930
<ul>

tls/src/main/java/org/bouncycastle/jsse/provider/ProvSSLSessionBase.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
import java.security.Principal;
44
import java.security.cert.Certificate;
55
import java.security.cert.X509Certificate;
6-
import java.util.Collections;
7-
import java.util.HashMap;
8-
import java.util.Map;
6+
import java.util.concurrent.ConcurrentHashMap;
97
import java.util.concurrent.atomic.AtomicLong;
108
import java.util.concurrent.atomic.AtomicReference;
119

@@ -27,7 +25,7 @@
2725
abstract class ProvSSLSessionBase
2826
extends BCExtendedSSLSession
2927
{
30-
protected final Map<String, Object> valueMap = Collections.synchronizedMap(new HashMap<String, Object>());
28+
protected final ConcurrentHashMap<String, Object> valueMap = new ConcurrentHashMap<String, Object>();
3129

3230
protected final AtomicReference<ProvSSLSessionContext> sslSessionContext;
3331
protected final boolean fipsMode;
@@ -237,15 +235,17 @@ public SSLSessionContext getSessionContext()
237235

238236
public Object getValue(String name)
239237
{
238+
if (name == null)
239+
{
240+
throw new IllegalArgumentException("'name' cannot be null");
241+
}
242+
240243
return valueMap.get(name);
241244
}
242245

243246
public String[] getValueNames()
244247
{
245-
synchronized (valueMap)
246-
{
247-
return valueMap.keySet().toArray(new String[valueMap.size()]);
248-
}
248+
return valueMap.keySet().toArray(new String[0]);
249249
}
250250

251251
@Override
@@ -287,12 +287,26 @@ public boolean isValid()
287287

288288
public void putValue(String name, Object value)
289289
{
290+
if (name == null)
291+
{
292+
throw new IllegalArgumentException("'name' cannot be null");
293+
}
294+
if (value == null)
295+
{
296+
throw new IllegalArgumentException("'value' cannot be null");
297+
}
298+
290299
notifyUnbound(name, valueMap.put(name, value));
291300
notifyBound(name, value);
292301
}
293302

294303
public void removeValue(String name)
295304
{
305+
if (name == null)
306+
{
307+
throw new IllegalArgumentException("'name' cannot be null");
308+
}
309+
296310
notifyUnbound(name, valueMap.remove(name));
297311
}
298312

tls/src/main/java/org/bouncycastle/tls/DTLSClientProtocol.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ protected DTLSTransport clientHandshake(ClientHandshakeState state)
152152

153153
handshake.finish();
154154

155-
if (securityParameters.isExtendedMasterSecret())
155+
if (securityParameters.isExtendedMasterSecret() &&
156+
ProtocolVersion.DTLSv12.isEqualOrLaterVersionOf(securityParameters.getNegotiatedVersion()))
156157
{
157158
securityParameters.tlsUnique = securityParameters.getPeerVerifyData();
158159
}
@@ -380,7 +381,10 @@ protected DTLSTransport clientHandshake(ClientHandshakeState state)
380381

381382
state.tlsSession = TlsUtils.importSession(securityParameters.getSessionID(), state.sessionParameters);
382383

383-
securityParameters.tlsUnique = securityParameters.getLocalVerifyData();
384+
if (ProtocolVersion.DTLSv12.isEqualOrLaterVersionOf(securityParameters.getNegotiatedVersion()))
385+
{
386+
securityParameters.tlsUnique = securityParameters.getLocalVerifyData();
387+
}
384388

385389
clientContext.handshakeComplete(client, state.tlsSession);
386390

tls/src/main/java/org/bouncycastle/tls/DTLSServerProtocol.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ protected DTLSTransport serverHandshake(ServerHandshakeState state, DTLSRequest
161161

162162
handshake.finish();
163163

164-
if (securityParameters.isExtendedMasterSecret())
164+
if (securityParameters.isExtendedMasterSecret() &&
165+
ProtocolVersion.DTLSv12.isEqualOrLaterVersionOf(securityParameters.getNegotiatedVersion()))
165166
{
166167
securityParameters.tlsUnique = securityParameters.getLocalVerifyData();
167168
}
@@ -409,7 +410,10 @@ protected DTLSTransport serverHandshake(ServerHandshakeState state, DTLSRequest
409410

410411
state.tlsSession = TlsUtils.importSession(securityParameters.getSessionID(), state.sessionParameters);
411412

412-
securityParameters.tlsUnique = securityParameters.getPeerVerifyData();
413+
if (ProtocolVersion.DTLSv12.isEqualOrLaterVersionOf(securityParameters.getNegotiatedVersion()))
414+
{
415+
securityParameters.tlsUnique = securityParameters.getPeerVerifyData();
416+
}
413417

414418
serverContext.handshakeComplete(server, state.tlsSession);
415419

tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JceAEADCipherImpl.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.security.GeneralSecurityException;
77
import java.security.PrivilegedAction;
88
import java.security.SecureRandom;
9+
import java.security.spec.AlgorithmParameterSpec;
910

1011
import javax.crypto.Cipher;
1112
import javax.crypto.SecretKey;
@@ -43,6 +44,7 @@ public Object run()
4344
});
4445
}
4546

47+
// TODO[tls] Once Java 7 or higher is the baseline, this will always be true
4648
private static final boolean canDoAEAD = checkForAEAD();
4749

4850
private static String getAlgParamsName(JcaJceHelper helper, String cipherName)
@@ -68,8 +70,10 @@ private static String getAlgParamsName(JcaJceHelper helper, String cipherName)
6870
private final String algorithmParamsName;
6971

7072
private SecretKey key;
71-
private byte[] nonce;
72-
private int macSize;
73+
74+
// TODO[tls] These two are only needed while the baseline is pre-Java7
75+
private byte[] noncePre7;
76+
private int macSizePre7;
7377

7478
public JceAEADCipherImpl(JcaTlsCrypto crypto, JcaJceHelper helper, String cipherName, String algorithm, int keySize,
7579
boolean isEncrypting)
@@ -120,10 +124,27 @@ public void init(byte[] nonce, int macSize)
120124
}
121125
else
122126
{
123-
// Otherwise fall back to the BC-specific AEADParameterSpec
124-
cipher.init(cipherMode, key, new AEADParameterSpec(nonce, macSize * 8, null), random);
125-
this.nonce = Arrays.clone(nonce);
126-
this.macSize = macSize;
127+
/*
128+
* Otherwise fall back to the BC-specific AEADParameterSpec. Since updateAAD is not available, we
129+
* need to use init to pass the associated data (in doFinal), but in order to call getOutputSize we
130+
* technically need to init the cipher first. So we init with a dummy nonce to avoid duplicate nonce
131+
* error from the init in doFinal.
132+
*/
133+
134+
if (this.noncePre7 == null || this.noncePre7.length != nonce.length)
135+
{
136+
this.noncePre7 = new byte[nonce.length];
137+
}
138+
139+
System.arraycopy(nonce, 0, this.noncePre7, 0, nonce.length);
140+
this.macSizePre7 = macSize;
141+
142+
this.noncePre7[0] ^= 0x80;
143+
144+
AlgorithmParameterSpec params = new AEADParameterSpec(noncePre7, macSizePre7 * 8, null);
145+
cipher.init(cipherMode, key, params, random);
146+
147+
this.noncePre7[0] ^= 0x80;
127148
}
128149
}
129150
catch (Exception e)
@@ -150,7 +171,11 @@ public int doFinal(byte[] additionalData, byte[] input, int inputOffset, int inp
150171
{
151172
try
152173
{
153-
cipher.init(cipherMode, key, new AEADParameterSpec(nonce, macSize * 8, additionalData));
174+
// NOTE: Shouldn't need a SecureRandom, but this is cheaper if the provider would auto-create one
175+
SecureRandom random = crypto.getSecureRandom();
176+
177+
AlgorithmParameterSpec params = new AEADParameterSpec(noncePre7, macSizePre7 * 8, additionalData);
178+
cipher.init(cipherMode, key, params, random);
154179
}
155180
catch (Exception e)
156181
{

0 commit comments

Comments
 (0)