|
1 | 1 | package org.bouncycastle.openpgp.operator.jcajce; |
2 | 2 |
|
| 3 | +import java.security.GeneralSecurityException; |
3 | 4 | import java.security.InvalidAlgorithmParameterException; |
4 | 5 | import java.security.InvalidKeyException; |
5 | 6 | import java.security.Provider; |
|
12 | 13 | import javax.crypto.spec.IvParameterSpec; |
13 | 14 | import javax.crypto.spec.SecretKeySpec; |
14 | 15 |
|
| 16 | +import org.bouncycastle.bcpg.AEADAlgorithmTags; |
15 | 17 | import org.bouncycastle.bcpg.S2K; |
| 18 | +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; |
16 | 19 | import org.bouncycastle.bcpg.SymmetricKeyUtils; |
17 | | -import org.bouncycastle.crypto.InvalidCipherTextException; |
18 | | -import org.bouncycastle.crypto.modes.AEADCipher; |
19 | | -import org.bouncycastle.crypto.params.AEADParameters; |
20 | | -import org.bouncycastle.crypto.params.KeyParameter; |
| 20 | +import org.bouncycastle.jcajce.spec.AEADParameterSpec; |
21 | 21 | import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; |
22 | 22 | import org.bouncycastle.jcajce.util.NamedJcaJceHelper; |
23 | 23 | import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; |
24 | 24 | import org.bouncycastle.openpgp.PGPException; |
25 | 25 | import org.bouncycastle.openpgp.PGPUtil; |
26 | 26 | import org.bouncycastle.openpgp.operator.PBEKeyEncryptionMethodGenerator; |
27 | 27 | import org.bouncycastle.openpgp.operator.PGPDigestCalculator; |
28 | | -import org.bouncycastle.openpgp.operator.bc.BcAEADUtil; |
29 | 28 |
|
30 | 29 | /** |
31 | 30 | * JCE based generator for password based encryption (PBE) data protection methods. |
@@ -152,26 +151,82 @@ protected byte[] encryptSessionInfo(int encAlgorithm, byte[] key, byte[] session |
152 | 151 | } |
153 | 152 |
|
154 | 153 | protected byte[] generateV6KEK(int kekAlgorithm, byte[] ikm, byte[] info) |
155 | | - { |
156 | | - return JceAEADUtil.generateHKDFBytes(ikm, null, info, SymmetricKeyUtils.getKeyLengthInOctets(kekAlgorithm)); |
157 | | - } |
158 | | - |
159 | | - protected byte[] getEskAndTag(int kekAlgorithm, int aeadAlgorithm, byte[] sessionKey, byte[] key, byte[] iv, byte[] info) |
160 | | - throws PGPException |
161 | | - { |
162 | | - AEADCipher aeadCipher = BcAEADUtil.createAEADCipher(kekAlgorithm, aeadAlgorithm); |
163 | | - aeadCipher.init(true, new AEADParameters(new KeyParameter(key), 128, iv, info)); |
164 | | - int outLen = aeadCipher.getOutputSize(sessionKey.length); |
165 | | - byte[] eskAndTag = new byte[outLen]; |
166 | | - int len = aeadCipher.processBytes(sessionKey, 0, sessionKey.length, eskAndTag, 0); |
167 | | - try |
168 | | - { |
169 | | - len += aeadCipher.doFinal(eskAndTag, len); |
170 | | - } |
171 | | - catch (InvalidCipherTextException e) |
172 | | - { |
173 | | - throw new PGPException("cannot encrypt session info", e); |
174 | | - } |
175 | | - return eskAndTag; |
176 | | - } |
| 154 | + { |
| 155 | + return JceAEADUtil.generateHKDFBytes(ikm, null, info, SymmetricKeyUtils.getKeyLengthInOctets(kekAlgorithm)); |
| 156 | + } |
| 157 | + |
| 158 | + protected byte[] getEskAndTag(int kekAlgorithm, int aeadAlgorithm, byte[] sessionKey, byte[] key, byte[] iv, byte[] info) |
| 159 | + throws PGPException |
| 160 | + { |
| 161 | + String algorithm = getBaseAEADAlgorithm(kekAlgorithm); |
| 162 | + |
| 163 | + Cipher aeadCipher = createAEADCipher(algorithm, aeadAlgorithm); |
| 164 | + |
| 165 | + try |
| 166 | + { |
| 167 | + aeadCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, algorithm), new AEADParameterSpec(iv, 128, info)); |
| 168 | + int outLen = aeadCipher.getOutputSize(sessionKey.length); |
| 169 | + byte[] eskAndTag = new byte[outLen]; |
| 170 | + |
| 171 | + int len = aeadCipher.update(sessionKey, 0, sessionKey.length, eskAndTag, 0); |
| 172 | + |
| 173 | + len += aeadCipher.doFinal(eskAndTag, len); |
| 174 | + |
| 175 | + if (len < eskAndTag.length) |
| 176 | + { |
| 177 | + byte[] rv = new byte[len]; |
| 178 | + System.arraycopy(eskAndTag, 0, rv, 0, len); |
| 179 | + return rv; |
| 180 | + } |
| 181 | + |
| 182 | + return eskAndTag; |
| 183 | + } |
| 184 | + catch (GeneralSecurityException e) |
| 185 | + { |
| 186 | + throw new PGPException("cannot encrypt session info", e); |
| 187 | + } |
| 188 | + |
| 189 | + } |
| 190 | + |
| 191 | + public static String getBaseAEADAlgorithm(int encAlgorithm) |
| 192 | + throws PGPException |
| 193 | + { |
| 194 | + if (encAlgorithm == SymmetricKeyAlgorithmTags.AES_128 |
| 195 | + || encAlgorithm == SymmetricKeyAlgorithmTags.AES_192 |
| 196 | + || encAlgorithm == SymmetricKeyAlgorithmTags.AES_256) |
| 197 | + { |
| 198 | + return "AES"; |
| 199 | + } |
| 200 | + else if (encAlgorithm == SymmetricKeyAlgorithmTags.CAMELLIA_128 |
| 201 | + || encAlgorithm == SymmetricKeyAlgorithmTags.CAMELLIA_192 |
| 202 | + || encAlgorithm == SymmetricKeyAlgorithmTags.CAMELLIA_256) |
| 203 | + { |
| 204 | + return "Camellia"; |
| 205 | + } |
| 206 | + throw new PGPException("AEAD only supported for AES and Camellia based algorithms"); |
| 207 | + } |
| 208 | + |
| 209 | + public static Cipher createAEADCipher(String algorithm, int aeadAlgorithm) |
| 210 | + throws PGPException |
| 211 | + { |
| 212 | + // Block Cipher must work on 16 byte blocks |
| 213 | + try |
| 214 | + { |
| 215 | + switch (aeadAlgorithm) |
| 216 | + { |
| 217 | + case AEADAlgorithmTags.EAX: |
| 218 | + return Cipher.getInstance(algorithm + "/EAX/NoPadding", "BC"); |
| 219 | + case AEADAlgorithmTags.OCB: |
| 220 | + return Cipher.getInstance(algorithm + "/OCB/NoPadding", "BC"); |
| 221 | + case AEADAlgorithmTags.GCM: |
| 222 | + return Cipher.getInstance(algorithm + "/GCM/NoPadding", "BC"); |
| 223 | + default: |
| 224 | + throw new PGPException("unrecognised AEAD algorithm: " + aeadAlgorithm); |
| 225 | + } |
| 226 | + } |
| 227 | + catch (GeneralSecurityException e) |
| 228 | + { |
| 229 | + throw new PGPException("unrecognised AEAD algorithm: " + e.getMessage(), e); |
| 230 | + } |
| 231 | + } |
177 | 232 | } |
0 commit comments