From fdff7d618958162b3a30d63c9c50bd71faace530 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Sat, 29 Oct 2016 07:52:36 +0200 Subject: [PATCH 1/2] Reformatted SecurityDataRecoveryService.serviceRequest(). The code in SecurityDataRecoveryService.serviceRequest() has been reformatted for clarity. https://fedorahosted.org/pki/ticket/2500 (cherry picked from commit 613d8e8281cc336d7e1c8291abedb4b2321f93ec) (cherry picked from commit ec165a0d6cd805d1b5d4fbd4fff44ff00bfcaee0) --- .../netscape/kra/SecurityDataRecoveryService.java | 30 ++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java b/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java index f12222b..478f7a8 100644 --- a/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java +++ b/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java @@ -24,6 +24,7 @@ import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; import java.security.spec.AlgorithmParameterSpec; import java.util.Arrays; import java.util.Hashtable; @@ -31,9 +32,6 @@ import java.util.Random; import javax.crypto.spec.RC2ParameterSpec; -import netscape.security.util.DerValue; -import netscape.security.x509.X509Key; - import org.dogtagpki.server.kra.rest.KeyRequestService; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.OCTET_STRING; @@ -73,6 +71,9 @@ import com.netscape.certsrv.security.ITransportKeyUnit; import com.netscape.cmscore.dbs.KeyRecord; import com.netscape.cmsutil.util.Utils; +import netscape.security.util.DerValue; +import netscape.security.x509.X509Key; + /** * This implementation services SecurityData Recovery requests. *

@@ -184,6 +185,7 @@ public class SecurityDataRecoveryService implements IService { } catch (Exception e) { iv = iv_default; } + String ivStr = Utils.base64encode(iv); KeyRecord keyRecord = (KeyRecord) mStorage.readKeyRecord(serialno); @@ -200,20 +202,27 @@ public class SecurityDataRecoveryService implements IService { if (allowEncDecrypt_recovery == true) { CMS.debug("Recover symmetric key by decrypting as per allowEncDecrypt_recovery: true."); unwrappedSecData = recoverSecurityData(keyRecord); + } else { symKey = recoverSymKey(keyRecord); } } else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) { unwrappedSecData = recoverSecurityData(keyRecord); + } else if (dataType.equals(KeyRequestResource.ASYMMETRIC_KEY_TYPE)) { try { if (allowEncDecrypt_recovery == true) { CMS.debug("Recover asymmetric key by decrypting as per allowEncDecrypt_recovery: true."); unwrappedSecData = recoverSecurityData(keyRecord); + } else { - privateKey = mStorageUnit.unwrap(keyRecord.getPrivateKeyData(), - X509Key.parsePublicKey(new DerValue(keyRecord.getPublicKeyData()))); + + byte[] publicKeyData = keyRecord.getPublicKeyData(); + byte[] privateKeyData = keyRecord.getPrivateKeyData(); + + PublicKey publicKey = X509Key.parsePublicKey(new DerValue(publicKeyData)); + privateKey = mStorageUnit.unwrap(privateKeyData, publicKey); } } catch (IOException e) { @@ -244,22 +253,29 @@ public class SecurityDataRecoveryService implements IService { passStr = null; if (dataType.equals(KeyRequestResource.SYMMETRIC_KEY_TYPE)) { + CMS.debug("SecurityDataRecoveryService: wrap or encrypt stored symmetric key with transport passphrase"); if (allowEncDecrypt_recovery == true) { CMS.debug("SecurityDataRecoveryServic: allowEncDecyypt_recovery: true, symmetric key: create blob with unwrapped key."); pbeWrappedData = createEncryptedContentInfo(ct, null, unwrappedSecData, null, pass); + } else { pbeWrappedData = createEncryptedContentInfo(ct, symKey, null, null, pass); } + } else if (dataType.equals(KeyRequestResource.PASS_PHRASE_TYPE)) { + CMS.debug("SecurityDataRecoveryService: encrypt stored passphrase with transport passphrase"); pbeWrappedData = createEncryptedContentInfo(ct, null, unwrappedSecData, null, pass); + } else if (dataType.equals(KeyRequestResource.ASYMMETRIC_KEY_TYPE)) { + if (allowEncDecrypt_recovery == true) { CMS.debug("SecurityDataRecoveryService: allowEncDecyypt_recovery: true, asymmetric key: create blob with unwrapped key."); pbeWrappedData = createEncryptedContentInfo(ct, null, unwrappedSecData, null, pass); + } else { CMS.debug("SecurityDataRecoveryService: wrap stored private key with transport passphrase"); pbeWrappedData = createEncryptedContentInfo(ct, null, null, privateKey, @@ -294,9 +310,11 @@ public class SecurityDataRecoveryService implements IService { CMS.debug("SecurityDataRecoveryService: encrypt symmetric key with session key as per allowEncDecrypt_recovery: true."); unwrappedSess = mTransportUnit.unwrap_sym(wrappedSessKey, SymmetricKey.Usage.ENCRYPT); Cipher encryptor = ct.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); + if (encryptor != null) { encryptor.initEncrypt(unwrappedSess, new IVParameterSpec(iv)); key_data = encryptor.doFinal(unwrappedSecData); + } else { auditRecoveryRequestProcessed(auditSubjectID, ILogger.FAILURE, requestID, serialno.toString(), "Failed to create cipher encrypting symmetric key"); @@ -344,9 +362,11 @@ public class SecurityDataRecoveryService implements IService { CMS.debug("SecurityDataRecoveryService: encrypt symmetric key with session key as per allowEncDecrypt_recovery: true."); unwrappedSess = mTransportUnit.unwrap_sym(wrappedSessKey, SymmetricKey.Usage.ENCRYPT); Cipher encryptor = ct.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); + if (encryptor != null) { encryptor.initEncrypt(unwrappedSess, new IVParameterSpec(iv)); key_data = encryptor.doFinal(unwrappedSecData); + } else { auditRecoveryRequestProcessed(auditSubjectID, ILogger.FAILURE, requestID, serialno.toString(), "Failed to create cipher encrypting asymmetric key"); -- 1.8.3.1 From 7fe0c22d09017fc45b251fd4fb2dd5f5dd23c603 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Tue, 1 Nov 2016 22:49:22 +0100 Subject: [PATCH 2/2] Fixed KRA key recovery via CLI in FIPS mode. Based on investigation and solution provided by cfu and jmagne, the SecurityDataRecoveryService.serviceRequest() has been modified to use EncryptionUnit.unwrap_temp() for key recovery via CLI in FIPS mode. https://fedorahosted.org/pki/ticket/2500 (cherry picked from commit 650b00dc57bb0c51c1e327ec3064531c26f80c43) (cherry picked from commit 8bef45df5e3d287111df8e0a33519a065e3e7b70) --- base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java | 3 +++ base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java b/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java index 23a1f77..575dda7 100644 --- a/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java +++ b/base/common/src/com/netscape/certsrv/security/IEncryptionUnit.java @@ -142,6 +142,9 @@ public interface IEncryptionUnit extends IToken { public SymmetricKey unwrap_sym(byte encSymmKey[], SymmetricKey.Usage usage); + public PrivateKey unwrap_temp(byte privateKey[], PublicKey pubKey) + throws EBaseException; + /** * Unwraps data. This method rebuilds the private key by * unwrapping the private key data. diff --git a/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java b/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java index 478f7a8..83c1fb1 100644 --- a/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java +++ b/base/kra/src/com/netscape/kra/SecurityDataRecoveryService.java @@ -222,7 +222,7 @@ public class SecurityDataRecoveryService implements IService { byte[] privateKeyData = keyRecord.getPrivateKeyData(); PublicKey publicKey = X509Key.parsePublicKey(new DerValue(publicKeyData)); - privateKey = mStorageUnit.unwrap(privateKeyData, publicKey); + privateKey = mStorageUnit.unwrap_temp(privateKeyData, publicKey); } } catch (IOException e) { -- 1.8.3.1