Skip to content

Commit c4f0555

Browse files
Tobianasihrasko
authored andcommitted
Use GCM mode as default
Use GCM to resolve: https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY JIRA: LIGHTY-193 Signed-off-by: tobias.pobocik <tobias.pobocik@pantheon.tech>
1 parent 7bf0a2b commit c4f0555

File tree

8 files changed

+114
-67
lines changed

8 files changed

+114
-67
lines changed

lighty-applications/lighty-rcgnmi-app-aggregator/lighty-rcgnmi-app-module/src/main/java/io/lighty/applications/rcgnmi/module/RcGnmiAppModule.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
import javax.crypto.NoSuchPaddingException;
4040
import javax.crypto.SecretKey;
4141
import javax.crypto.SecretKeyFactory;
42-
import javax.crypto.spec.IvParameterSpec;
42+
import javax.crypto.spec.GCMParameterSpec;
4343
import javax.crypto.spec.PBEKeySpec;
4444
import javax.crypto.spec.SecretKeySpec;
4545
import org.eclipse.jdt.annotation.Nullable;
@@ -190,15 +190,16 @@ private AAAEncryptionServiceImpl createEncryptionService() throws NoSuchPaddingE
190190
encrySrvConfig.getEncryptIterationCount(), encrySrvConfig.getEncryptKeyLength());
191191
final SecretKey key
192192
= new SecretKeySpec(keyFactory.generateSecret(keySpec).getEncoded(), encrySrvConfig.getEncryptType());
193-
final IvParameterSpec ivParameterSpec = new IvParameterSpec(encryptionKeySalt);
193+
final GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(encrySrvConfig.getAuthTagLength(),
194+
encryptionKeySalt);
194195

195196
final Cipher encryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
196-
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
197+
encryptCipher.init(Cipher.ENCRYPT_MODE, key, gcmParameterSpec);
197198

198199
final Cipher decryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
199-
decryptCipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
200+
decryptCipher.init(Cipher.DECRYPT_MODE, key, gcmParameterSpec);
200201

201-
return new AAAEncryptionServiceImpl(encryptCipher, decryptCipher);
202+
return new AAAEncryptionServiceImpl(gcmParameterSpec, encrySrvConfig.getCipherTransforms(), key);
202203
}
203204

204205
private AaaEncryptServiceConfig getDefaultAaaEncryptServiceConfig() {
@@ -209,6 +210,6 @@ private AaaEncryptServiceConfig getDefaultAaaEncryptServiceConfig() {
209210
.setPasswordLength(12).setEncryptSalt(salt)
210211
.setEncryptMethod("PBKDF2WithHmacSHA1").setEncryptType("AES")
211212
.setEncryptIterationCount(32768).setEncryptKeyLength(128)
212-
.setCipherTransforms("AES/CBC/PKCS5Padding").build();
213+
.setAuthTagLength(128).setCipherTransforms("AES/GCM/NoPadding").build();
213214
}
214215
}

lighty-modules/lighty-aaa-aggregator/lighty-aaa-encryption-service/src/main/java/io/lighty/aaa/encrypt/service/impl/AAAEncryptionServiceImpl.java

+74-20
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,20 @@
77
*/
88
package io.lighty.aaa.encrypt.service.impl;
99

10+
import static java.util.Objects.requireNonNull;
11+
12+
import java.nio.ByteBuffer;
13+
import java.security.GeneralSecurityException;
14+
import java.security.InvalidAlgorithmParameterException;
15+
import java.security.InvalidKeyException;
16+
import java.security.NoSuchAlgorithmException;
17+
import java.security.SecureRandom;
1018
import javax.crypto.BadPaddingException;
1119
import javax.crypto.Cipher;
1220
import javax.crypto.IllegalBlockSizeException;
21+
import javax.crypto.NoSuchPaddingException;
22+
import javax.crypto.SecretKey;
23+
import javax.crypto.spec.GCMParameterSpec;
1324
import org.opendaylight.aaa.encrypt.AAAEncryptionService;
1425
import org.slf4j.Logger;
1526
import org.slf4j.LoggerFactory;
@@ -18,44 +29,87 @@ public class AAAEncryptionServiceImpl implements AAAEncryptionService {
1829

1930
private static final Logger LOG = LoggerFactory.getLogger(AAAEncryptionServiceImpl.class);
2031

21-
private final Cipher encryptCipher;
22-
private final Cipher decryptCipher;
32+
private final String cipherTransforms;
33+
private final SecretKey key;
34+
private final byte[] iv;
35+
private final int tagLength;
36+
final SecureRandom random;
2337

24-
public AAAEncryptionServiceImpl(Cipher encryptCipher, Cipher decryptCipher) {
25-
this.encryptCipher = encryptCipher;
26-
this.decryptCipher = decryptCipher;
38+
public AAAEncryptionServiceImpl(GCMParameterSpec gcmParameterSpec, String cipherTransforms, SecretKey key) {
39+
this.iv = gcmParameterSpec.getIV();
40+
this.tagLength = gcmParameterSpec.getTLen();
41+
this.cipherTransforms = cipherTransforms;
42+
this.key = key;
43+
this.random = new SecureRandom();
2744
}
2845

2946
@Override
30-
public byte[] encrypt(byte[] data) {
47+
public byte[] encrypt(final byte[] data) {
3148
if (data != null && data.length != 0) {
49+
final Cipher encryptCipher;
50+
try {
51+
encryptCipher = initCipher(Cipher.ENCRYPT_MODE, iv);
52+
} catch (GeneralSecurityException e) {
53+
throw new IllegalStateException("Failed to create encrypt cipher.", e);
54+
}
55+
final byte[] encryptedData;
3256
try {
33-
synchronized (encryptCipher) {
34-
return encryptCipher.doFinal(data);
35-
}
36-
} catch (IllegalBlockSizeException | BadPaddingException e) {
57+
encryptedData = encryptCipher.doFinal(requireNonNull(data));
58+
return ByteBuffer.allocate(iv.length + encryptedData.length)
59+
.put(iv)
60+
.put(encryptedData)
61+
.array();
62+
} catch (final IllegalBlockSizeException | BadPaddingException e) {
3763
LOG.error("Failed to encrypt data.", e);
3864
return data;
3965
}
40-
} else {
41-
LOG.warn("data is empty or null.");
66+
}
67+
else {
68+
LOG.warn("encrypt data is empty or null.");
4269
return data;
4370
}
4471
}
4572

4673
@Override
47-
public byte[] decrypt(byte[] encryptedData) {
48-
if (encryptedData != null && encryptedData.length != 0) {
74+
public byte[] decrypt(final byte[] encryptedDataWithIv) {
75+
if (encryptedDataWithIv != null && encryptedDataWithIv.length != 0) {
76+
final var ivLength = iv.length;
77+
if (encryptedDataWithIv.length < ivLength) {
78+
LOG.error("Invalid encrypted data length.");
79+
return encryptedDataWithIv;
80+
}
81+
final var byteBuffer = ByteBuffer.wrap(encryptedDataWithIv);
82+
83+
final var localIv = new byte[ivLength];
84+
byteBuffer.get(localIv);
85+
86+
final var encryptedData = new byte[byteBuffer.remaining()];
87+
byteBuffer.get(encryptedData);
88+
89+
final Cipher decryptCipher;
90+
try {
91+
decryptCipher = initCipher(Cipher.DECRYPT_MODE, iv);
92+
} catch (GeneralSecurityException e) {
93+
throw new IllegalStateException("Failed to create decrypt cipher.", e);
94+
}
4995
try {
50-
return decryptCipher.doFinal(encryptedData);
51-
} catch (IllegalBlockSizeException | BadPaddingException e) {
52-
LOG.error("Failed to decrypt encoded data", e);
96+
return decryptCipher.doFinal(requireNonNull(encryptedData));
97+
} catch (final IllegalBlockSizeException | BadPaddingException e) {
98+
LOG.error("Failed to decrypt data", e);
5399
return encryptedData;
54100
}
55-
} else {
56-
LOG.warn("encryptedData is empty or null.");
57-
return encryptedData;
58101
}
102+
else {
103+
LOG.warn("decrypt data is empty or null.");
104+
return encryptedDataWithIv;
105+
}
106+
}
107+
108+
private Cipher initCipher(final int mode, final byte[] localIv) throws
109+
NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException {
110+
final var cipher = Cipher.getInstance(cipherTransforms);
111+
cipher.init(mode, key, new GCMParameterSpec(tagLength, localIv));
112+
return cipher;
59113
}
60114

61115
}

lighty-modules/lighty-aaa-aggregator/lighty-aaa/src/main/java/io/lighty/aaa/config/CertificateManagerConfig.java

+9-15
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,15 @@
88
package io.lighty.aaa.config;
99

1010
import io.lighty.aaa.encrypt.service.impl.AAAEncryptionServiceImpl;
11-
import java.security.InvalidAlgorithmParameterException;
12-
import java.security.InvalidKeyException;
1311
import java.security.NoSuchAlgorithmException;
1412
import java.security.spec.InvalidKeySpecException;
1513
import java.security.spec.KeySpec;
1614
import java.util.ArrayList;
1715
import java.util.Base64;
1816
import java.util.List;
19-
import javax.crypto.Cipher;
20-
import javax.crypto.NoSuchPaddingException;
2117
import javax.crypto.SecretKey;
2218
import javax.crypto.SecretKeyFactory;
23-
import javax.crypto.spec.IvParameterSpec;
19+
import javax.crypto.spec.GCMParameterSpec;
2420
import javax.crypto.spec.PBEKeySpec;
2521
import javax.crypto.spec.SecretKeySpec;
2622
import org.opendaylight.aaa.cert.api.ICertificateManager;
@@ -75,7 +71,8 @@ public static ICertificateManager getDefault(final DataBroker bindingDataBroker,
7571
.setEncryptType("AES")
7672
.setEncryptIterationCount(32768)
7773
.setEncryptKeyLength(128)
78-
.setCipherTransforms("AES/CBC/PKCS5Padding")
74+
.setCipherTransforms("AES/GCM/NoPadding")
75+
.setAuthTagLength(128)
7976
.build();
8077

8178
final byte[] encryptionKeySalt = Base64.getDecoder().decode(encrySrvConfig.getEncryptSalt());
@@ -86,19 +83,16 @@ public static ICertificateManager getDefault(final DataBroker bindingDataBroker,
8683
encrySrvConfig.getEncryptIterationCount(), encrySrvConfig.getEncryptKeyLength());
8784
SecretKey key = new SecretKeySpec(keyFactory.generateSecret(keySpec).getEncoded(),
8885
encrySrvConfig.getEncryptType());
89-
IvParameterSpec ivParameterSpec = new IvParameterSpec(encryptionKeySalt);
86+
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(encrySrvConfig.getAuthTagLength(),
87+
encryptionKeySalt);
9088

91-
Cipher encryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
92-
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
93-
94-
Cipher decryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
95-
decryptCipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
96-
final AAAEncryptionService encryptionSrv = new AAAEncryptionServiceImpl(encryptCipher, decryptCipher);
89+
final AAAEncryptionService encryptionSrv = new AAAEncryptionServiceImpl(gcmParameterSpec,
90+
encrySrvConfig.getCipherTransforms(), key);
9791

9892
return new CertificateManagerService(rpcProviderService, bindingDataBroker, encryptionSrv,
9993
aaaCertServiceConfig);
100-
} catch (InvalidAlgorithmParameterException | InvalidKeyException | InvalidKeySpecException
101-
| NoSuchAlgorithmException | NoSuchPaddingException e) {
94+
} catch (InvalidKeySpecException
95+
| NoSuchAlgorithmException e) {
10296
return null;
10397
}
10498
}

lighty-modules/lighty-aaa-aggregator/lighty-aaa/src/main/resources/aaa-encrypt-service-config.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
<encrypt-type>AES</encrypt-type>
77
<encrypt-iteration-count>32768</encrypt-iteration-count>
88
<encrypt-key-length>128</encrypt-key-length>
9-
<cipher-transforms>AES/CBC/PKCS5Padding</cipher-transforms>
9+
<cipher-transforms>AES/GCM/NoPadding</cipher-transforms>
1010
</aaa-encrypt-service-config>

lighty-modules/lighty-gnmi/lighty-gnmi-sb/src/test/java/io/lighty/gnmi/southbound/device/KeystoreGnmiSecurityTest.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
import javax.crypto.NoSuchPaddingException;
5151
import javax.crypto.SecretKey;
5252
import javax.crypto.SecretKeyFactory;
53-
import javax.crypto.spec.IvParameterSpec;
53+
import javax.crypto.spec.GCMParameterSpec;
5454
import javax.crypto.spec.PBEKeySpec;
5555
import javax.crypto.spec.SecretKeySpec;
5656
import javax.xml.bind.DatatypeConverter;
@@ -465,22 +465,23 @@ private static AAAEncryptionServiceImpl createEncryptionService() throws NoSuchP
465465
encrySrvConfig.getEncryptIterationCount(), encrySrvConfig.getEncryptKeyLength());
466466
final SecretKey key = new SecretKeySpec(keyFactory.generateSecret(keySpec).getEncoded(),
467467
encrySrvConfig.getEncryptType());
468-
final IvParameterSpec ivParameterSpec = new IvParameterSpec(encryptionKeySalt);
468+
final GCMParameterSpec ivParameterSpec = new GCMParameterSpec(encrySrvConfig.getAuthTagLength(),
469+
encryptionKeySalt);
469470

470471
final Cipher encryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
471472
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
472473

473474
final Cipher decryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
474475
decryptCipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
475476

476-
return new AAAEncryptionServiceImpl(encryptCipher, decryptCipher);
477+
return new AAAEncryptionServiceImpl(ivParameterSpec, encrySrvConfig.getCipherTransforms(), key);
477478
}
478479

479480
private static AaaEncryptServiceConfig getDefaultAaaEncryptServiceConfig() {
480481
return new AaaEncryptServiceConfigBuilder().setEncryptKey("V1S1ED4OMeEh")
481482
.setPasswordLength(12).setEncryptSalt("TdtWeHbch/7xP52/rp3Usw==")
482483
.setEncryptMethod("PBKDF2WithHmacSHA1").setEncryptType("AES")
483484
.setEncryptIterationCount(32768).setEncryptKeyLength(128)
484-
.setCipherTransforms("AES/CBC/PKCS5Padding").build();
485+
.setAuthTagLength(128).setCipherTransforms("AES/GCM/NoPadding").build();
485486
}
486487
}

lighty-modules/lighty-gnmi/lighty-gnmi-sb/src/test/java/io/lighty/gnmi/southbound/lightymodule/GnmiSouthBoundModuleTest.java

+6-11
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@
2525
import java.util.List;
2626
import java.util.concurrent.Executors;
2727
import java.util.concurrent.TimeUnit;
28-
import javax.crypto.Cipher;
2928
import javax.crypto.NoSuchPaddingException;
3029
import javax.crypto.SecretKey;
3130
import javax.crypto.SecretKeyFactory;
32-
import javax.crypto.spec.IvParameterSpec;
31+
import javax.crypto.spec.GCMParameterSpec;
3332
import javax.crypto.spec.PBEKeySpec;
3433
import javax.crypto.spec.SecretKeySpec;
3534
import org.junit.jupiter.api.Assertions;
@@ -79,23 +78,19 @@ private static AAAEncryptionServiceImpl createEncryptionService() throws NoSuchP
7978
encrySrvConfig.getEncryptIterationCount(), encrySrvConfig.getEncryptKeyLength());
8079
final SecretKey key
8180
= new SecretKeySpec(keyFactory.generateSecret(keySpec).getEncoded(), encrySrvConfig.getEncryptType());
82-
final IvParameterSpec ivParameterSpec = new IvParameterSpec(encryptionKeySalt);
81+
final GCMParameterSpec ivParameterSpec = new GCMParameterSpec(encrySrvConfig.getAuthTagLength(),
82+
encryptionKeySalt);
8383

84-
final Cipher encryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
85-
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
86-
87-
final Cipher decryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
88-
decryptCipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
89-
90-
return new AAAEncryptionServiceImpl(encryptCipher, decryptCipher);
84+
return new AAAEncryptionServiceImpl(ivParameterSpec, encrySrvConfig.getCipherTransforms(), key);
9185
}
9286

9387
private static AaaEncryptServiceConfig getDefaultAaaEncryptServiceConfig() {
9488
return new AaaEncryptServiceConfigBuilder().setEncryptKey("V1S1ED4OMeEh")
9589
.setPasswordLength(12).setEncryptSalt("TdtWeHbch/7xP52/rp3Usw==")
9690
.setEncryptMethod("PBKDF2WithHmacSHA1").setEncryptType("AES")
9791
.setEncryptIterationCount(32768).setEncryptKeyLength(128)
98-
.setCipherTransforms("AES/CBC/PKCS5Padding").build();
92+
.setAuthTagLength(128)
93+
.setCipherTransforms("AES/GCM/NoPadding").build();
9994
}
10095
}
10196

lighty-modules/lighty-gnmi/lighty-gnmi-test/src/test/java/io/lighty/modules/gnmi/test/gnmi/GnmiWithoutRestconfTest.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
import javax.crypto.NoSuchPaddingException;
4949
import javax.crypto.SecretKey;
5050
import javax.crypto.SecretKeyFactory;
51-
import javax.crypto.spec.IvParameterSpec;
51+
import javax.crypto.spec.GCMParameterSpec;
5252
import javax.crypto.spec.PBEKeySpec;
5353
import javax.crypto.spec.SecretKeySpec;
5454
import org.awaitility.Awaitility;
@@ -509,23 +509,24 @@ private static AAAEncryptionServiceImpl createEncryptionService() throws NoSuchP
509509
encrySrvConfig.getEncryptIterationCount(), encrySrvConfig.getEncryptKeyLength());
510510
final SecretKey key
511511
= new SecretKeySpec(keyFactory.generateSecret(keySpec).getEncoded(), encrySrvConfig.getEncryptType());
512-
final IvParameterSpec ivParameterSpec = new IvParameterSpec(encryptionKeySalt);
512+
final GCMParameterSpec ivParameterSpec = new GCMParameterSpec(encrySrvConfig.getAuthTagLength(),
513+
encryptionKeySalt);
513514

514515
final Cipher encryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
515516
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
516517

517518
final Cipher decryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
518519
decryptCipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
519520

520-
return new AAAEncryptionServiceImpl(encryptCipher, decryptCipher);
521+
return new AAAEncryptionServiceImpl(ivParameterSpec, encrySrvConfig.getCipherTransforms(), key);
521522
}
522523

523524
private static AaaEncryptServiceConfig getDefaultAaaEncryptServiceConfig() {
524525
return new AaaEncryptServiceConfigBuilder().setEncryptKey("V1S1ED4OMeEh")
525526
.setPasswordLength(12).setEncryptSalt("TdtWeHbch/7xP52/rp3Usw==")
526527
.setEncryptMethod("PBKDF2WithHmacSHA1").setEncryptType("AES")
527528
.setEncryptIterationCount(32768).setEncryptKeyLength(128)
528-
.setCipherTransforms("AES/CBC/PKCS5Padding").build();
529+
.setAuthTagLength(128).setCipherTransforms("AES/GCM/NoPadding").build();
529530
}
530531

531532
private static SimulatedGnmiDevice getUnsecureGnmiDevice(final String host, final int port) {

lighty-modules/lighty-netconf-sb/src/main/java/io/lighty/modules/southbound/netconf/impl/util/NetconfConfigUtils.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import javax.crypto.NoSuchPaddingException;
3030
import javax.crypto.SecretKey;
3131
import javax.crypto.SecretKeyFactory;
32-
import javax.crypto.spec.IvParameterSpec;
32+
import javax.crypto.spec.GCMParameterSpec;
3333
import javax.crypto.spec.PBEKeySpec;
3434
import javax.crypto.spec.SecretKeySpec;
3535
import org.opendaylight.aaa.encrypt.AAAEncryptionService;
@@ -157,7 +157,7 @@ public static AaaEncryptServiceConfig getDefaultAaaEncryptServiceConfig() {
157157
.setPasswordLength(12).setEncryptSalt(salt)
158158
.setEncryptMethod("PBKDF2WithHmacSHA1").setEncryptType("AES")
159159
.setEncryptIterationCount(32768).setEncryptKeyLength(128)
160-
.setCipherTransforms("AES/CBC/PKCS5Padding").build();
160+
.setAuthTagLength(128).setCipherTransforms("AES/GCM/NoPadding").build();
161161
}
162162

163163
/**
@@ -176,15 +176,16 @@ public static AAAEncryptionService createAAAEncryptionService(AaaEncryptServiceC
176176
encrySrvConfig.getEncryptIterationCount(), encrySrvConfig.getEncryptKeyLength());
177177
SecretKey key = new SecretKeySpec(keyFactory.generateSecret(keySpec).getEncoded(),
178178
encrySrvConfig.getEncryptType());
179-
IvParameterSpec ivParameterSpec = new IvParameterSpec(encryptionKeySalt);
179+
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(encrySrvConfig.getAuthTagLength(),
180+
encryptionKeySalt);
180181

181182
Cipher encryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
182-
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
183+
encryptCipher.init(Cipher.ENCRYPT_MODE, key, gcmParameterSpec);
183184

184185
Cipher decryptCipher = Cipher.getInstance(encrySrvConfig.getCipherTransforms());
185-
decryptCipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
186+
decryptCipher.init(Cipher.DECRYPT_MODE, key, gcmParameterSpec);
186187

187-
return new AAAEncryptionServiceImpl(encryptCipher, decryptCipher);
188+
return new AAAEncryptionServiceImpl(gcmParameterSpec, encrySrvConfig.getCipherTransforms(), key);
188189

189190
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException
190191
| InvalidAlgorithmParameterException | InvalidKeyException e) {

0 commit comments

Comments
 (0)