Skip to content

Commit

Permalink
fix(common): incorrect key length used for AES algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
Zmax0 committed Aug 11, 2024
1 parent 9c05178 commit 0c651dd
Show file tree
Hide file tree
Showing 18 changed files with 152 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws E
@Override
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (bodyDecoder == null) {
CipherMethod cipher = CipherMethods.AES_GCM.get();
CipherMethod cipher = CipherMethods.AES_128_GCM.get();
int tagSize = cipher.tagSize();
int nonceSize = cipher.nonceSize();
byte[] aeadResponseHeaderLengthEncryptionKey = KDF.kdf16(session.getResponseBodyKey(), KDF_SALT_AEAD_RESP_HEADER_LEN_KEY.getBytes());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@
import com.urbanspork.common.codec.NonceGenerator;
import org.bouncycastle.crypto.InvalidCipherTextException;

public record Authenticator(CipherMethod method, byte[] key, NonceGenerator nonceGenerator, BytesGenerator associatedTextGenerator) {
import java.util.Arrays;

public record Authenticator(byte[] key, CipherMethod method, NonceGenerator nonceGenerator, BytesGenerator associatedTextGenerator) {
public Authenticator(byte[] key, CipherMethod method, NonceGenerator nonceGenerator, BytesGenerator associatedTextGenerator) {
int keySize = method.keySize();
this.key = keySize == key.length ? key : Arrays.copyOf(key, keySize);
this.method = method;
this.nonceGenerator = nonceGenerator;
this.associatedTextGenerator = associatedTextGenerator;
}

public int overhead() {
return method.tagSize();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public interface CipherMethod {

AEADCipher cipher();

int keySize();

int macSize();

int nonceSize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,80 @@

public enum CipherMethods implements Supplier<CipherMethod> {

AES_GCM, CHACHA20_POLY1305;
AES_128_GCM, AES_265_GCM, CHACHA20_POLY1305;

@Override
public CipherMethod get() {
if (CHACHA20_POLY1305 == this) {
return new CipherMethod() {
@Override
public AEADCipher cipher() {
return new ChaCha20Poly1305();
}

@Override
public int macSize() {
return 128;
}

@Override
public int nonceSize() {
return 12;
}
};
} else {
return new CipherMethod() {
@Override
public AEADCipher cipher() {
return GCMBlockCipher.newInstance(AESEngine.newInstance());
}

@Override
public int macSize() {
return 128;
}

@Override
public int nonceSize() {
return 12;
}
};
switch (this) {
case AES_128_GCM -> {
return new CipherMethod() {
@Override
public int keySize() {
return 16;
}

@Override
public AEADCipher cipher() {
return GCMBlockCipher.newInstance(AESEngine.newInstance());
}

@Override
public int macSize() {
return 128;
}

@Override
public int nonceSize() {
return 12;
}
};
}
case AES_265_GCM -> {
return new CipherMethod() {
@Override
public int keySize() {
return 32;
}

@Override
public AEADCipher cipher() {
return GCMBlockCipher.newInstance(AESEngine.newInstance());
}

@Override
public int macSize() {
return 128;
}

@Override
public int nonceSize() {
return 12;
}
};
}
default -> {
return new CipherMethod() {
@Override
public AEADCipher cipher() {
return new ChaCha20Poly1305();
}

@Override
public int keySize() {
return 32;
}

@Override
public int macSize() {
return 128;
}

@Override
public int nonceSize() {
return 12;
}
};
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,18 @@ class AeadCipherCodec {
public void encode(Session session, ByteBuf msg, ByteBuf out) throws InvalidCipherTextException {
boolean isAead2022 = cipherKind.isAead2022();
if (payloadEncoder == null) {
initTcpPayloadEncoder(session, isAead2022, out);
initPayloadEncoder(session, isAead2022, out);
logger.trace("[tcp][encode identity]{}", session.identity());
if (Mode.Client == session.mode()) {
msg = handleRequestHeader(session, isAead2022, msg, out);
msg = handleClientHeader(session, isAead2022, msg, out);
} else {
handleResponseHeader(session, isAead2022, msg, out);
handleServerHeader(session, isAead2022, msg, out);
}
}
payloadEncoder.encodePayload(msg, out);
}

private void initTcpPayloadEncoder(Session session, boolean isAead2022, ByteBuf out) {
private void initPayloadEncoder(Session session, boolean isAead2022, ByteBuf out) {
withIdentity(session, cipherKind, keys, out);
byte[] salt = session.identity().salt();
if (isAead2022) {
Expand All @@ -75,7 +75,7 @@ private void initTcpPayloadEncoder(Session session, boolean isAead2022, ByteBuf
}
}

private ByteBuf handleRequestHeader(Session session, boolean isAead2022, ByteBuf msg, ByteBuf out) throws InvalidCipherTextException {
private ByteBuf handleClientHeader(Session session, boolean isAead2022, ByteBuf msg, ByteBuf out) throws InvalidCipherTextException {
ByteBuf temp = Unpooled.buffer();
Address.encode(session.request(), temp);
if (isAead2022) {
Expand All @@ -93,7 +93,7 @@ private ByteBuf handleRequestHeader(Session session, boolean isAead2022, ByteBuf
return temp;
}

private void handleResponseHeader(Session session, boolean isAead2022, ByteBuf msg, ByteBuf out) throws InvalidCipherTextException {
private void handleServerHeader(Session session, boolean isAead2022, ByteBuf msg, ByteBuf out) throws InvalidCipherTextException {
if (isAead2022) {
for (byte[] bytes : AEAD2022.TCP.newHeader(session.mode(), session.identity().getRequestSalt(), msg)) {
out.writeBytes(payloadEncoder.auth().seal(bytes));
Expand Down Expand Up @@ -219,7 +219,7 @@ static void withIdentity(Session session, CipherKind kind, Keys keys, ByteBuf ou
byte[] salt = session.identity().salt();
out.writeBytes(salt); // salt should be sent with the first chunk
if (Mode.Client == session.mode() && kind.supportEih()) {
AEAD2022.TCP.withEih(keys, salt, out);
AEAD2022.TCP.withEih(kind, keys, salt, out);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ private AeadCipherCodecs() {}
static AeadCipherCodec get(ServerConfig config) {
CipherKind kind = config.getCipher();
Keys keys = Keys.from(kind, config.getPassword());
if (CipherKind.chacha20_poly1305 == kind) {
return new AeadCipherCodec(kind, CipherMethods.CHACHA20_POLY1305.get(), keys);
} else {
return new AeadCipherCodec(kind, CipherMethods.AES_GCM.get(), keys);
CipherMethods methods;
switch (kind) {
case aes_128_gcm, aead2022_blake3_aes_128_gcm -> methods = CipherMethods.AES_128_GCM;
case chacha20_poly1305 -> methods = CipherMethods.CHACHA20_POLY1305;
default -> methods = CipherMethods.AES_265_GCM;
}
return new AeadCipherCodec(kind, methods.get(), keys);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private void encodeClientPacketAead2022(Context context, ByteBuf msg, ByteBuf ou
if (requireEih) {
byte[] sessionIdPacketId = new byte[16];
temp.getBytes(nonceLength, sessionIdPacketId);
AEAD2022.UDP.withEih(keys.encKey(), identityKeys, sessionIdPacketId, temp);
AEAD2022.UDP.withEih(cipherKind, keys.encKey(), identityKeys, sessionIdPacketId, temp);
}
temp.writeByte(Mode.Client.getValue());
temp.writeLong(AEAD2022.newTimestamp());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ private AeadCipherCodecs() {}
static AeadCipherCodec get(ServerConfig config) {
CipherKind kind = config.getCipher();
Keys keys = Keys.from(kind, config.getPassword());
CipherMethods methods = CipherKind.chacha20_poly1305 == kind ? CipherMethods.CHACHA20_POLY1305 : CipherMethods.AES_GCM;
CipherMethods methods;
switch (kind) {
case aes_128_gcm, aead2022_blake3_aes_128_gcm -> methods = CipherMethods.AES_128_GCM;
case chacha20_poly1305 -> methods = CipherMethods.CHACHA20_POLY1305;
default -> methods = CipherMethods.AES_265_GCM;
}
if (kind.isAead2022()) {
return new Aead2022CipherCodecImpl(kind, methods.get(), keys);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private static CipherMethod getAEADCipherCodec(SecurityType security) {
if (SecurityType.CHACHA20_POLY1305 == security) {
return CipherMethods.CHACHA20_POLY1305.get();
} else {
return CipherMethods.AES_GCM.get();
return CipherMethods.AES_128_GCM.get();
}
}

Expand All @@ -77,7 +77,7 @@ private static byte[] getIV(Session session, Predicate<Session> predicate) {
}

private static Authenticator newAEADAuthenticator(CipherMethod codec, byte[] key, byte[] nonce) {
return new Authenticator(codec, key, NonceGenerator.generateCountingNonce(nonce, codec.nonceSize()), BytesGenerator.generateEmptyBytes());
return new Authenticator(key, codec, NonceGenerator.generateCountingNonce(nonce, codec.nonceSize()), BytesGenerator.generateEmptyBytes());
}

private static ChunkSizeCodec newAEADChunkSizeCodec(CipherMethod codec, byte[] key, byte[] nonce) {
Expand Down
16 changes: 8 additions & 8 deletions urban-spork-common/src/com/urbanspork/common/crypto/AES.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@
public class AES {
private AES() {}

public static byte[] encrypt(byte[] key, byte[] in) {
public static byte[] encrypt(byte[] key, byte[] in, int keyLen) {
MultiBlockCipher cipher = AESEngine.newInstance();
byte[] out = new byte[cipher.getBlockSize()];
cipher.init(true, new KeyParameter(key));
cipher.init(true, new KeyParameter(key, 0, keyLen));
cipher.processBlock(in, 0, out, 0);
return out;
}

public static void encrypt(byte[] key, byte[] in, byte[] out) {
public static void encrypt(byte[] key, byte[] in, int keyLen, byte[] out) {
MultiBlockCipher cipher = AESEngine.newInstance();
cipher.init(true, new KeyParameter(key));
cipher.init(true, new KeyParameter(key, 0, keyLen));
cipher.processBlock(in, 0, out, 0);
}

public static byte[] decrypt(byte[] key, byte[] in) {
public static byte[] decrypt(byte[] key, byte[] in, int keyLen) {
MultiBlockCipher cipher = AESEngine.newInstance();
byte[] out = new byte[cipher.getBlockSize()];
cipher.init(false, new KeyParameter(key));
cipher.init(false, new KeyParameter(key, 0, keyLen));
cipher.processBlock(in, 0, out, 0);
return out;
}

public static void decrypt(byte[] key, byte[] in, byte[] out) {
public static void decrypt(byte[] key, byte[] in, int keyLen, byte[] out) {
MultiBlockCipher cipher = AESEngine.newInstance();
cipher.init(false, new KeyParameter(key));
cipher.init(false, new KeyParameter(key, 0, keyLen));
cipher.processBlock(in, 0, out, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,26 @@ static byte[] opensslBytesToKey(byte[] password, int size) {

interface TCP {
static PayloadEncoder newPayloadEncoder(CipherMethod cipherMethod, byte[] key, byte[] salt) {
Authenticator auth = new Authenticator(cipherMethod, hkdfsha1(key, salt), NonceGenerator.generateInitialAEADNonce(), BytesGenerator.generateEmptyBytes());
Authenticator auth = new Authenticator(hkdfsha1(key, salt), cipherMethod, NonceGenerator.generateInitialAEADNonce(), BytesGenerator.generateEmptyBytes());
AEADChunkSizeParser sizeCodec = new AEADChunkSizeParser(auth);
return new PayloadEncoder(auth, sizeCodec, EmptyPaddingLengthGenerator.INSTANCE, 0x3fff);
}

static PayloadDecoder newPayloadDecoder(CipherMethod cipherMethod, byte[] key, byte[] salt) {
Authenticator auth = new Authenticator(cipherMethod, hkdfsha1(key, salt), NonceGenerator.generateInitialAEADNonce(), BytesGenerator.generateEmptyBytes());
Authenticator auth = new Authenticator(hkdfsha1(key, salt), cipherMethod, NonceGenerator.generateInitialAEADNonce(), BytesGenerator.generateEmptyBytes());
AEADChunkSizeParser sizeCodec = new AEADChunkSizeParser(auth);
return new PayloadDecoder(auth, sizeCodec, EmptyPaddingLengthGenerator.INSTANCE);
}
}

interface UDP {
static PayloadEncoder newPayloadEncoder(CipherMethod cipherMethod, byte[] key, byte[] salt) {
Authenticator auth = new Authenticator(cipherMethod, hkdfsha1(key, salt), NonceGenerator.generateInitialAEADNonce(), BytesGenerator.generateEmptyBytes());
Authenticator auth = new Authenticator(hkdfsha1(key, salt), cipherMethod, NonceGenerator.generateInitialAEADNonce(), BytesGenerator.generateEmptyBytes());
return new PayloadEncoder(auth, EmptyChunkSizeParser.INSTANCE, EmptyPaddingLengthGenerator.INSTANCE, 0x3fff);
}

static PayloadDecoder newPayloadDecoder(CipherMethod cipherMethod, byte[] key, byte[] salt) {
Authenticator auth = new Authenticator(cipherMethod, hkdfsha1(key, salt), NonceGenerator.generateInitialAEADNonce(), BytesGenerator.generateEmptyBytes());
Authenticator auth = new Authenticator(hkdfsha1(key, salt), cipherMethod, NonceGenerator.generateInitialAEADNonce(), BytesGenerator.generateEmptyBytes());
return new PayloadDecoder(auth, EmptyChunkSizeParser.INSTANCE, EmptyPaddingLengthGenerator.INSTANCE);
}
}
Expand Down
Loading

0 comments on commit 0c651dd

Please sign in to comment.