Skip to content

Commit

Permalink
Merge branch 'crlorentzen-main'
Browse files Browse the repository at this point in the history
  • Loading branch information
dghgit committed Dec 24, 2024
2 parents 7669c14 + 48167a8 commit c35119b
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.bouncycastle.jsse.provider;

import org.bouncycastle.tls.crypto.TlsNonceGenerator;

final public class GcmTls12NonceGeneratorUtil
{
private static TlsNonceGeneratorFactory tlsNonceGeneratorFactory = null;

public static void setGcmTlsNonceGeneratorFactory(final TlsNonceGeneratorFactory factory)
{
tlsNonceGeneratorFactory = factory;
}

public static boolean isGcmFipsNonceGeneratorFactorySet()
{
return tlsNonceGeneratorFactory != null;
}

public static TlsNonceGenerator createGcmFipsNonceGenerator(final byte[] baseNonce, final int counterSizeInBits)
{
return tlsNonceGeneratorFactory != null
? tlsNonceGeneratorFactory.create(baseNonce, counterSizeInBits)
: null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.bouncycastle.jsse.provider;

import org.bouncycastle.tls.crypto.TlsNonceGenerator;

public interface TlsNonceGeneratorFactory
{
TlsNonceGenerator create(byte[] baseNonce, int counterSizeInBits);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
import org.bouncycastle.tls.crypto.TlsCryptoUtils;
import org.bouncycastle.tls.crypto.TlsDecodeResult;
import org.bouncycastle.tls.crypto.TlsEncodeResult;
import org.bouncycastle.tls.crypto.TlsNonceGenerator;
import org.bouncycastle.tls.crypto.TlsSecret;
import org.bouncycastle.util.Arrays;

import static org.bouncycastle.jsse.provider.GcmTls12NonceGeneratorUtil.createGcmFipsNonceGenerator;
import static org.bouncycastle.jsse.provider.GcmTls12NonceGeneratorUtil.isGcmFipsNonceGeneratorFactorySet;

/**
* A generic TLS 1.2 AEAD cipher.
*/
Expand All @@ -30,6 +34,8 @@ public final class TlsAEADCipher
private static final int NONCE_RFC7905 = 2;
private static final long SEQUENCE_NUMBER_PLACEHOLDER = -1L;

private static final byte[] EPOCH_1 = {0x00, 0x01};

private final TlsCryptoParameters cryptoParams;
private final int keySize;
private final int macSize;
Expand All @@ -43,6 +49,7 @@ public final class TlsAEADCipher

private final boolean isTLSv13;
private final int nonceMode;
private final TlsNonceGenerator gcmFipsNonceGenerator;

public TlsAEADCipher(TlsCryptoParameters cryptoParams, TlsAEADCipherImpl encryptCipher, TlsAEADCipherImpl decryptCipher,
int keySize, int macSize, int aeadType) throws IOException
Expand Down Expand Up @@ -91,6 +98,7 @@ public TlsAEADCipher(TlsCryptoParameters cryptoParams, TlsAEADCipherImpl encrypt
final boolean isServer = cryptoParams.isServer();
if (isTLSv13)
{
gcmFipsNonceGenerator = null;
rekeyCipher(securityParameters, decryptCipher, decryptNonce, !isServer);
rekeyCipher(securityParameters, encryptCipher, encryptNonce, isServer);
return;
Expand Down Expand Up @@ -121,6 +129,28 @@ public TlsAEADCipher(TlsCryptoParameters cryptoParams, TlsAEADCipherImpl encrypt
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}

if (AEAD_GCM == aeadType && isGcmFipsNonceGeneratorFactorySet())
{
final int nonceLength = fixed_iv_length + record_iv_length;
final byte[] baseNonce = Arrays.copyOf(encryptNonce, nonceLength);
final int counterSizeInBits;
if (negotiatedVersion.isDTLS())
{
counterSizeInBits = (record_iv_length - 2) * 8; // 48
baseNonce[baseNonce.length - 8] ^= EPOCH_1[0];
baseNonce[baseNonce.length - 7] ^= EPOCH_1[1];
}
else
{
counterSizeInBits = record_iv_length * 8; // 64
}
gcmFipsNonceGenerator = createGcmFipsNonceGenerator(baseNonce, counterSizeInBits);
}
else
{
gcmFipsNonceGenerator = null;
}
}

public int getCiphertextDecodeLimit(int plaintextLimit)
Expand Down Expand Up @@ -154,24 +184,33 @@ public int getPlaintextEncodeLimit(int ciphertextLimit)
public TlsEncodeResult encodePlaintext(long seqNo, short contentType, ProtocolVersion recordVersion,
int headerAllocation, byte[] plaintext, int plaintextOffset, int plaintextLength) throws IOException
{
byte[] nonce = new byte[encryptNonce.length + record_iv_length];
final int nonceSize = encryptNonce.length + record_iv_length;
final byte[] nonce;

switch (nonceMode)
if (null != gcmFipsNonceGenerator)
{
case NONCE_RFC5288:
System.arraycopy(encryptNonce, 0, nonce, 0, encryptNonce.length);
// RFC 5288/6655: The nonce_explicit MAY be the 64-bit sequence number.
TlsUtils.writeUint64(seqNo, nonce, encryptNonce.length);
break;
case NONCE_RFC7905:
TlsUtils.writeUint64(seqNo, nonce, nonce.length - 8);
for (int i = 0; i < encryptNonce.length; ++i)
nonce = gcmFipsNonceGenerator.generateNonce(nonceSize);
}
else
{
nonce = new byte[nonceSize];
switch (nonceMode)
{
nonce[i] ^= encryptNonce[i];
case NONCE_RFC5288:
System.arraycopy(encryptNonce, 0, nonce, 0, encryptNonce.length);
// RFC 5288/6655: The nonce_explicit MAY be the 64-bit sequence number.
TlsUtils.writeUint64(seqNo, nonce, encryptNonce.length);
break;
case NONCE_RFC7905:
TlsUtils.writeUint64(seqNo, nonce, nonce.length - 8);
for (int i = 0; i < encryptNonce.length; ++i)
{
nonce[i] ^= encryptNonce[i];
}
break;
default:
throw new TlsFatalAlert(AlertDescription.internal_error);
}
break;
default:
throw new TlsFatalAlert(AlertDescription.internal_error);
}

// TODO[tls13, cid] If we support adding padding to (D)TLSInnerPlaintext, this will need review
Expand Down
8 changes: 8 additions & 0 deletions tls/src/test/java/org/bouncycastle/tls/test/AllTests.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.bouncycastle.tls.test;

import org.bouncycastle.jsse.provider.GcmTls12NonceGeneratorUtil;
import org.bouncycastle.test.PrintTestResult;

import junit.extensions.TestSetup;
Expand All @@ -14,6 +15,13 @@ public static void main(String[] args)
throws Exception
{
PrintTestResult.printResult(junit.textui.TestRunner.run(suite()));
PrintTestResult.printResult(junit.textui.TestRunner.run(suiteWithCustomNonceGeneratorForTls12()));
}

public static Test suiteWithCustomNonceGeneratorForTls12() throws Exception
{
GcmTls12NonceGeneratorUtil.setGcmTlsNonceGeneratorFactory(TestTlsNonceGeneratorFactory.INSTANCE);
return suite();
}

public static Test suite()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.bouncycastle.tls.test;

import org.bouncycastle.tls.crypto.TlsNonceGenerator;

import java.util.Arrays;

class TestNonceGenerator implements TlsNonceGenerator
{
private final byte[] baseNonce;
private final long counterMask;
private final int counterBytes;

private long counterValue;
private boolean counterExhausted;

TestNonceGenerator(final byte[] baseNonce, final int counterBits)
{
this.baseNonce = Arrays.copyOf(baseNonce, baseNonce.length);
this.counterMask = -1L >>> (64 - counterBits);
this.counterBytes = (counterBits + 7) / 8;

this.counterValue = 0L;
this.counterExhausted = false;
}

@Override
public byte[] generateNonce(final int size)
{
if (size != baseNonce.length)
{
throw new IllegalArgumentException("requested length is not equal to the length of the base nonce.");
}

if (counterExhausted)
{
throw new IllegalStateException("TLS nonce generator exhausted");
}

final byte[] nonce = Arrays.copyOf(baseNonce, baseNonce.length);
final int offset = baseNonce.length - counterBytes;

for (int i = 0; i < counterBytes; i++)
{
nonce[offset + i] ^= (byte)(counterValue >>> ((counterBytes - 1 - i) * 8));
}

counterExhausted |= ((++counterValue & counterMask) == 0);

return nonce;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.bouncycastle.tls.test;

import org.bouncycastle.jsse.provider.TlsNonceGeneratorFactory;
import org.bouncycastle.tls.crypto.TlsNonceGenerator;

class TestTlsNonceGeneratorFactory implements TlsNonceGeneratorFactory {
public static final TlsNonceGeneratorFactory INSTANCE = new TestTlsNonceGeneratorFactory();

private TestTlsNonceGeneratorFactory()
{
// no op
}

@Override
public TlsNonceGenerator create(final byte[] baseNonce, final int counterSizeInBits)
{
return new TestNonceGenerator(baseNonce, counterSizeInBits);
}
}

0 comments on commit c35119b

Please sign in to comment.