From 9c77d7da884e41b1219cfe634f8ff622c81a16d9 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Wed, 6 Sep 2023 11:49:39 +0200 Subject: [PATCH] Kotlin conversion: HardwareSecurity --- .../HardwareSecurity.java | 105 ------------------ .../HardwareSecurity.kt | 76 +++++++++++++ 2 files changed, 76 insertions(+), 105 deletions(-) delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/decryption_verification/HardwareSecurity.java create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/HardwareSecurity.kt diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/HardwareSecurity.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/HardwareSecurity.java deleted file mode 100644 index fc88ef33..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/HardwareSecurity.java +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.decryption_verification; - -import org.bouncycastle.bcpg.AEADEncDataPacket; -import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket; -import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSessionKey; -import org.bouncycastle.openpgp.operator.PGPDataDecryptor; -import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory; -import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory; -import org.pgpainless.key.SubkeyIdentifier; - -/** - * Enable integration of hardware-backed OpenPGP keys. - */ -public class HardwareSecurity { - - public interface DecryptionCallback { - - /** - * Delegate decryption of a Public-Key-Encrypted-Session-Key (PKESK) to an external API for dealing with - * hardware security modules such as smartcards or TPMs. - * - * If decryption fails for some reason, a subclass of the {@link HardwareSecurityException} is thrown. - * - * @param keyId id of the key - * @param keyAlgorithm algorithm - * @param sessionKeyData encrypted session key - * - * @return decrypted session key - * @throws HardwareSecurityException exception - */ - byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData) - throws HardwareSecurityException; - - } - - /** - * Implementation of {@link PublicKeyDataDecryptorFactory} which delegates decryption of encrypted session keys - * to a {@link DecryptionCallback}. - * Users can provide such a callback to delegate decryption of messages to hardware security SDKs. - */ - public static class HardwareDataDecryptorFactory implements CustomPublicKeyDataDecryptorFactory { - - private final DecryptionCallback callback; - // luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument. - private final PublicKeyDataDecryptorFactory factory = - new BcPublicKeyDataDecryptorFactory(null); - private final SubkeyIdentifier subkey; - - /** - * Create a new {@link HardwareDataDecryptorFactory}. - * - * @param subkeyIdentifier identifier of the decryption subkey - * @param callback decryption callback - */ - public HardwareDataDecryptorFactory(SubkeyIdentifier subkeyIdentifier, DecryptionCallback callback) { - this.callback = callback; - this.subkey = subkeyIdentifier; - } - - @Override - public byte[] recoverSessionData(int keyAlgorithm, byte[][] secKeyData) - throws PGPException { - try { - // delegate decryption to the callback - return callback.decryptSessionKey(subkey.getSubkeyId(), keyAlgorithm, secKeyData[0]); - } catch (HardwareSecurityException e) { - throw new PGPException("Hardware-backed decryption failed.", e); - } - } - - @Override - public PGPDataDecryptor createDataDecryptor(boolean withIntegrityPacket, int encAlgorithm, byte[] key) - throws PGPException { - return factory.createDataDecryptor(withIntegrityPacket, encAlgorithm, key); - } - - @Override - public PGPDataDecryptor createDataDecryptor(AEADEncDataPacket aeadEncDataPacket, PGPSessionKey sessionKey) - throws PGPException { - return factory.createDataDecryptor(aeadEncDataPacket, sessionKey); - } - - @Override - public PGPDataDecryptor createDataDecryptor(SymmetricEncIntegrityPacket seipd, PGPSessionKey sessionKey) - throws PGPException { - return factory.createDataDecryptor(seipd, sessionKey); - } - - @Override - public SubkeyIdentifier getSubkeyIdentifier() { - return subkey; - } - } - - public static class HardwareSecurityException - extends Exception { - - } - -} diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/HardwareSecurity.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/HardwareSecurity.kt new file mode 100644 index 00000000..7d0d243a --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/HardwareSecurity.kt @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.decryption_verification + +import org.bouncycastle.bcpg.AEADEncDataPacket +import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket +import org.bouncycastle.openpgp.PGPException +import org.bouncycastle.openpgp.PGPSessionKey +import org.bouncycastle.openpgp.operator.PGPDataDecryptor +import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory +import org.pgpainless.key.SubkeyIdentifier +import kotlin.jvm.Throws + +/** + * Enable integration of hardware-backed OpenPGP keys. + */ +class HardwareSecurity { + + interface DecryptionCallback { + + /** + * Delegate decryption of a Public-Key-Encrypted-Session-Key (PKESK) to an external API for dealing with + * hardware security modules such as smartcards or TPMs. + * + * If decryption fails for some reason, a subclass of the [HardwareSecurityException] is thrown. + * + * @param keyId id of the key + * @param keyAlgorithm algorithm + * @param sessionKeyData encrypted session key + * + * @return decrypted session key + * @throws HardwareSecurityException exception + */ + @Throws(HardwareSecurityException::class) + fun decryptSessionKey(keyId: Long, keyAlgorithm: Int, sessionKeyData: ByteArray): ByteArray + } + + /** + * Implementation of [PublicKeyDataDecryptorFactory] which delegates decryption of encrypted session keys + * to a [DecryptionCallback]. + * Users can provide such a callback to delegate decryption of messages to hardware security SDKs. + */ + class HardwareDataDecryptorFactory( + override val subkeyIdentifier: SubkeyIdentifier, + private val callback: DecryptionCallback, + ) : CustomPublicKeyDataDecryptorFactory { + + // luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument. + private val factory: PublicKeyDataDecryptorFactory = BcPublicKeyDataDecryptorFactory(null) + + override fun createDataDecryptor(withIntegrityPacket: Boolean, encAlgorithm: Int, key: ByteArray?): PGPDataDecryptor { + return factory.createDataDecryptor(withIntegrityPacket, encAlgorithm, key) + } + + override fun createDataDecryptor(aeadEncDataPacket: AEADEncDataPacket?, sessionKey: PGPSessionKey?): PGPDataDecryptor { + return factory.createDataDecryptor(aeadEncDataPacket, sessionKey) + } + + override fun createDataDecryptor(seipd: SymmetricEncIntegrityPacket?, sessionKey: PGPSessionKey?): PGPDataDecryptor { + return factory.createDataDecryptor(seipd, sessionKey) + } + + override fun recoverSessionData(keyAlgorithm: Int, secKeyData: Array): ByteArray { + return try { + callback.decryptSessionKey(subkeyIdentifier.subkeyId, keyAlgorithm, secKeyData[0]) + } catch (e : HardwareSecurityException) { + throw PGPException("Hardware-backed decryption failed.", e) + } + } + } + + class HardwareSecurityException : Exception() +} \ No newline at end of file