Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server side key gen password complexity #4950

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion base/ca/shared/conf/registry.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
types=profile,defaultPolicy,constraintPolicy,profileInput,profileOutput,profileUpdater
constraintPolicy.ids=noConstraintImpl,subjectNameConstraintImpl,uniqueSubjectNameConstraintImpl,userSubjectNameConstraintImpl,cmcSharedTokenSubjectNameConstraintImpl,cmcUserSignedSubjectNameConstraintImpl,caValidityConstraintImpl,validityConstraintImpl,keyUsageExtConstraintImpl,nsCertTypeExtConstraintImpl,extendedKeyUsageExtConstraintImpl,keyConstraintImpl,basicConstraintsExtConstraintImpl,extensionConstraintImpl,signingAlgConstraintImpl,uniqueKeyConstraintImpl,renewGracePeriodConstraintImpl,authzRealmConstraintImpl,externalProcessConstraintImpl
constraintPolicy.ids=noConstraintImpl,subjectNameConstraintImpl,uniqueSubjectNameConstraintImpl,userSubjectNameConstraintImpl,cmcSharedTokenSubjectNameConstraintImpl,cmcUserSignedSubjectNameConstraintImpl,caValidityConstraintImpl,validityConstraintImpl,keyUsageExtConstraintImpl,nsCertTypeExtConstraintImpl,extendedKeyUsageExtConstraintImpl,keyConstraintImpl,basicConstraintsExtConstraintImpl,extensionConstraintImpl,signingAlgConstraintImpl,uniqueKeyConstraintImpl,renewGracePeriodConstraintImpl,authzRealmConstraintImpl,externalProcessConstraintImpl,p12ExportPasswordConstraintImpl
constraintPolicy.signingAlgConstraintImpl.class=com.netscape.cms.profile.constraint.SigningAlgConstraint
constraintPolicy.signingAlgConstraintImpl.desc=Signing Algorithm Constraint
constraintPolicy.signingAlgConstraintImpl.name=Signing Algorithm Constraint
Expand Down Expand Up @@ -27,6 +27,9 @@ constraintPolicy.nsCertTypeExtConstraintImpl.name=Netscape Certificate Type Exte
constraintPolicy.noConstraintImpl.class=com.netscape.cms.profile.constraint.NoConstraint
constraintPolicy.noConstraintImpl.desc=No Constraint
constraintPolicy.noConstraintImpl.name=No Constraint
constraintPolicy.p12ExportPasswordConstraintImpl.class=com.netscape.cms.profile.constraint.P12ExportPasswordConstraint
constraintPolicy.p12ExportPasswordConstraintImpl.desc=Generated PKCS12 Constraint
constraintPolicy.p12ExportPasswordConstraintImpl.name=Generated PKCS12 Constraint
constraintPolicy.subjectNameConstraintImpl.class=com.netscape.cms.profile.constraint.SubjectNameConstraint
constraintPolicy.subjectNameConstraintImpl.desc=Subject Name Constraint
constraintPolicy.subjectNameConstraintImpl.name=Subject Name Constraint
Expand Down
11 changes: 10 additions & 1 deletion base/ca/shared/profiles/ca/caServerKeygen_DirUserCert.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ input.i1.class_id=serverKeygenInputImpl
output.list=o1
output.o1.class_id=pkcs12OutputImpl
policyset.list=userCertSet
policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9
policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9,11
policyset.userCertSet.1.constraint.class_id=subjectNameConstraintImpl
policyset.userCertSet.1.constraint.name=Subject Name Constraint
policyset.userCertSet.1.constraint.params.pattern=UID=.*
Expand Down Expand Up @@ -100,3 +100,12 @@ policyset.userCertSet.9.constraint.params.signingAlgsAllowed=SHA256withRSA,SHA51
policyset.userCertSet.9.default.class_id=signingAlgDefaultImpl
policyset.userCertSet.9.default.name=Signing Alg
policyset.userCertSet.9.default.params.signingAlg=-
policyset.userCertSet.11.constraint.class_id=p12ExportPasswordConstraintImpl
policyset.userCertSet.11.constraint.name=PKCS12 Password Constraint
policyset.userCertSet.11.constraint.params.password.minSize=20
policyset.userCertSet.11.constraint.params.password.minCharCategory=2,2,2,2
policyset.userCertSet.11.constraint.params.password.substringMatch=6
policyset.userCertSet.11.constraint.params.password.maxRepeatedChar=3
policyset.userCertSet.11.constraint.params.password.cracklibCheck=false
policyset.userCertSet.11.default.class_id=noDefaultImpl
policyset.userCertSet.11.default.name=No Default
11 changes: 10 additions & 1 deletion base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ input.i3.class_id=submitterInfoInputImpl
output.list=o1
output.o1.class_id=pkcs12OutputImpl
policyset.list=userCertSet
policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9
policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9,11
policyset.userCertSet.1.constraint.class_id=subjectNameConstraintImpl
policyset.userCertSet.1.constraint.name=Subject Name Constraint
policyset.userCertSet.1.constraint.params.pattern=UID=.*
Expand Down Expand Up @@ -102,3 +102,12 @@ policyset.userCertSet.9.constraint.params.signingAlgsAllowed=SHA256withRSA,SHA51
policyset.userCertSet.9.default.class_id=signingAlgDefaultImpl
policyset.userCertSet.9.default.name=Signing Alg
policyset.userCertSet.9.default.params.signingAlg=-
policyset.userCertSet.11.constraint.class_id=p12ExportPasswordConstraintImpl
policyset.userCertSet.11.constraint.name=PKCS12 Password Constraint
policyset.userCertSet.11.constraint.params.password.minSize=20
policyset.userCertSet.11.constraint.params.password.minCharCategory=2,2,2,2
policyset.userCertSet.11.constraint.params.password.substringMatch=6
policyset.userCertSet.11.constraint.params.password.maxRepeatedChar=3
policyset.userCertSet.11.constraint.params.password.cracklibCheck=false
policyset.userCertSet.11.default.class_id=noDefaultImpl
policyset.userCertSet.11.default.name=No Default
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,21 @@
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import org.dogtagpki.server.ca.CAConfig;
import org.dogtagpki.server.ca.CAEngine;
import org.dogtagpki.server.ca.CAEngineConfig;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
import org.mozilla.jss.netscape.security.x509.CertificateSubjectName;
import org.mozilla.jss.netscape.security.x509.CertificateX509Key;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.KeyIdentifier;
import org.mozilla.jss.netscape.security.x509.PKIXExtensions;
import org.mozilla.jss.netscape.security.x509.SubjectKeyIdentifierExtension;
Expand All @@ -37,10 +47,13 @@
import org.mozilla.jss.pkix.crmf.PKIArchiveOptions;

import com.netscape.ca.CAService;
import com.netscape.ca.CertificateAuthority;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.SessionContext;
import com.netscape.certsrv.ca.AuthorityID;
import com.netscape.certsrv.connector.Connector;
import com.netscape.certsrv.connector.ConnectorConfig;
import com.netscape.certsrv.connector.ConnectorsConfig;
import com.netscape.certsrv.logging.AuditFormat;
import com.netscape.certsrv.logging.event.SecurityDataArchivalRequestEvent;
import com.netscape.certsrv.logging.event.ServerSideKeygenEnrollKeyRetrievalEvent;
Expand All @@ -65,7 +78,7 @@
*/
public class CAEnrollProfile extends EnrollProfile {

public static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CAEnrollProfile.class);
public static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CAEnrollProfile.class);

public CAEnrollProfile() {
}
Expand Down Expand Up @@ -125,7 +138,7 @@ public void execute(Request request) throws EProfileException, ERejectException

// if PKI Archive Option present, send this request
// to DRM
byte optionsData[] = request.getExtDataInByteArray(Request.REQUEST_ARCHIVE_OPTIONS);
byte[] optionsData = request.getExtDataInByteArray(Request.REQUEST_ARCHIVE_OPTIONS);

byte[] transWrappedSessionKey = null;
byte[] sessionWrappedPassphrase = null;
Expand All @@ -135,19 +148,11 @@ public void execute(Request request) throws EProfileException, ERejectException
logger.info("CAEnrollProfile: Processing server-side keygen enrollment");
request.setExtData(Request.SSK_STAGE, Request.SSK_STAGE_KEYGEN);

/*
* temporarily remove the items not needed for SSK_STAGE_KEYGEN
* so not to pass them to KRA.
* They will be put back at SSK_STAGE_KEY_RETRIEVE below
*/
transWrappedSessionKey = request.getExtDataInByteArray("serverSideKeygenP12PasswdTransSession");
Map<String, byte[]> p12PasswordInfo = processP12Password(request);
transWrappedSessionKey = p12PasswordInfo.get("serverSideKeygenP12PasswdTransSession");

sessionWrappedPassphrase = request.getExtDataInByteArray("serverSideKeygenP12PasswdEnc");
sessionWrappedPassphrase = p12PasswordInfo.get("serverSideKeygenP12PasswdEnc");

request.setExtData("serverSideKeygenP12PasswdTransSession", "");
request.deleteExtData("serverSideKeygenP12PasswdTransSession");
request.setExtData("serverSideKeygenP12PasswdEnc", "");
request.deleteExtData("serverSideKeygenP12PasswdEnc");

try {
Connector kraConnector = caService.getKRAConnector();
Expand Down Expand Up @@ -342,7 +347,7 @@ public void execute(Request request) throws EProfileException, ERejectException
} catch (IOException e) {
old_ski = null;
}
if (old_ski != null) {
if (old_ski != null) {
byte[] old_ski_val = old_ski.getIdentifier();
if (old_ski_val != null) {
int old_ski_len = old_ski_val.length;
Expand Down Expand Up @@ -377,11 +382,7 @@ public void execute(Request request) throws EProfileException, ERejectException
logger.debug(method + "did not find SubjectKey_Id");
*/

} catch (IOException e) {
logger.error(method + e.getMessage(), e);
throw new EProfileException(e);

} catch (CertificateException e) {
} catch (CertificateException | IOException e) {
logger.error(method + e.getMessage(), e);
throw new EProfileException(e);
} catch (Exception e) {
Expand Down Expand Up @@ -531,4 +532,108 @@ public void execute(Request request) throws EProfileException, ERejectException
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how you group the code into a method to handle processing of the p12 password and return in a Map collection. The method "convertP12Password" could use a comment briefly describing what it does. Also, I think instead of "convertP12Password", it might be more appropriate to call it "processP12Password" since you are not changing or generating the password. It's just been processed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it appears that the code in this method was moved from def/ServerKeygenUserKeyDefault.java. I assume this is to avoid the P12 password being "processed" unnecessarily if it were to fail the password checks in the constraint.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how you group the code into a method to handle processing of the p12 password and return in a Map collection. The method "convertP12Password" could use a comment briefly describing what it does. Also, I think instead of "convertP12Password", it might be more appropriate to call it "processP12Password" since you are not changing or generating the password. It's just been processed.

I was using convert because in my mind it convert from a String to a corresponding key but I agree it is not a real conversion to I have update the names.

/**
* Read the p12 password and generate symmetric keys
*
* The password is read from the request and removed after the keys are generated.
*
* @param request
* @return symmetric keys
* @throws EProfileException
*/
private Map<String, byte[]> processP12Password (Request request) throws EProfileException {
String method = "CAEnrollProfile: processP12Password: ";
Map<String, byte[]> returnPass = null;

String p12passwd = request.getExtDataInString("serverSideKeygenP12Passwd");

org.mozilla.jss.crypto.X509Certificate transCert = null;

CAEngine engine = CAEngine.getInstance();
CertificateAuthority ca = engine.getCA();
CAConfig caConfig = ca.getConfigStore();
ConnectorsConfig connectorsConfig = caConfig.getConnectorsConfig();
ConnectorConfig kraConnectorConfig = connectorsConfig.getConnectorConfig("KRA");

try {
CryptoManager cm = CryptoManager.getInstance();
String transportNickname = kraConnectorConfig.getString("transportCertNickname", "KRA Transport Certificate");
transCert = cm.findCertByNickname(transportNickname);
} catch (Exception e) {
logger.error(method + "'KRA transport certificate' not found in nssdb; need to be manually setup for Server-Side keygen enrollment");
throw new EProfileException(CMS.getUserMessage("CMS_MISSING_KRA_TRANSPORT_CERT_IN_CA_NSSDB"));
}

try
{
// todo: make things configurable in CS.cfg or profile
CryptoToken ct =
CryptoUtil.getCryptoToken(CryptoUtil.INTERNAL_TOKEN_NAME);

EncryptionAlgorithm encryptAlgorithm =
EncryptionAlgorithm.AES_128_CBC_PAD;

CAEngineConfig caCfg = engine.getConfig();
boolean useOAEP = caCfg.getUseOAEPKeyWrap();

KeyWrapAlgorithm wrapAlgorithm = KeyWrapAlgorithm.RSA;
if(useOAEP) {
wrapAlgorithm = KeyWrapAlgorithm.RSA_OAEP;
}

logger.debug(method + "KeyWrapAlgorithm: " + wrapAlgorithm);

SymmetricKey sessionKey = CryptoUtil.generateKey(
ct,
KeyGenAlgorithm.AES,
128,
null,
true);

byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
byte[] sessionWrappedPassphrase = CryptoUtil.encryptUsingSymmetricKey(
ct,
sessionKey,
p12passwd.getBytes("UTF-8"),
encryptAlgorithm,
new IVParameterSpec(iv));

logger.debug(method + "sessionWrappedPassphrase.length=" + sessionWrappedPassphrase.length);

byte[] transWrappedSessionKey = CryptoUtil.wrapUsingPublicKey(
ct,
transCert.getPublicKey(),
sessionKey,
wrapAlgorithm);
logger.debug(method + " transWrappedSessionKey.length =" +transWrappedSessionKey.length);

CertificateSubjectName reqSubj =
request.getExtDataInCertSubjectName(Request.REQUEST_SUBJECT_NAME);
String subj = "unknown serverKeyGenUser";
if (reqSubj != null) {
X500Name xN = reqSubj.getX500Name();
subj = xN.toString();
logger.debug(method + "subj = " + subj);
}
// store in request to pass to kra
request.setExtData(Request.SECURITY_DATA_CLIENT_KEY_ID,
subj);
returnPass = new HashMap<>();

returnPass.put("serverSideKeygenP12PasswdEnc",
sessionWrappedPassphrase);
returnPass.put("serverSideKeygenP12PasswdTransSession",
transWrappedSessionKey);

// delete
request.setExtData("serverSideKeygenP12Passwd", "");
request.deleteExtData("serverSideKeygenP12Passwd");
} catch(Exception e) {
logger.debug("{}{}", method, e.toString());
throw new EProfileException(e.getMessage());

}
return returnPass;
}

}
Loading
Loading