summaryrefslogtreecommitdiffstats
path: root/base/java-tools/src
diff options
context:
space:
mode:
authorChristina Fu <cfu@redhat.com>2017-05-30 14:12:06 -0700
committerChristina Fu <cfu@redhat.com>2017-06-08 18:07:49 -0700
commit698192f4f62c55142a557f6489ed2323e17401b0 (patch)
tree6be820d18391cddac9d2de50e2917bb2e9e3a1da /base/java-tools/src
parent5bf30f2f6a52b7164ba31ab12ed2317b2c572610 (diff)
downloadpki-698192f4f62c55142a557f6489ed2323e17401b0.tar.gz
pki-698192f4f62c55142a557f6489ed2323e17401b0.tar.xz
pki-698192f4f62c55142a557f6489ed2323e17401b0.zip
Ticket #2619 Allow CA to process user-signed CMC revocation requests
First of all, the original CMC revocation only supports agent-signed CMC revocation requests from the UI where CMCRevReqServlet handles it with CMCAuth. It is in violation with https://tools.ietf.org/html/rfc5273 CMC Transport Protocols, as for HTTP/HTTPS, the body of the message is the binary value of the BER encoding of the PKI Request or Response,so HTML is not an approved method.The other way is through profileSubmitCMCFullServlet (or maybe not, as it was completely broken). One thing that's much less crucial, but goes along with rfc update is the name of the revocation request ASN1 structure. In the new rfc5272, it is now called RevokeRequest insead of RevRequest. This patch revamped the CMC revocation provision and fixing what's broken and adding what's missing. On the client side: CMCRequest - Commented out the code where it made an assumption to use OtherMsg for the signer information. This makes no sense as the outer layer SignedData would have the same information when signing happens. - removed the revRequest.nickname parameter from the configuration. From the code it seems like it expects the certificate to be revoked to exist in the user database, and it uses the same certificate to sign the revocation request. The RFC does allow for self-signed revocation, but it also allows for signing with another certificate provided that it has same subject. By removing the revRequest.nickname parameter, I am using the "nickname" parameter as the signer cert, which may or may not be the same certificate specified in revRequest.serial. It is less confusing. The change also eliminate the need for the cert to be revoked to be present in the db. In addition, revRequest.issuer only needs to be specified if revRequest.sharedSecret is used. The code will extract the issuer info from the signing cert. - added support for unsigned data in support of shared secret in both CMCRequest and server; The original code assumed that a cmc revocation request that relies on shared secret still requires agent signing. CMCRevoke - The original code assumed that the nss db password is the same as Shared Secret (!!). This patch added a "-t" to accept shred secret, and keep the -p for the nss db password. - The original code printed out b64 encoded request to the screen output as well as the file CMCRevoke.out. Both are unusable directly. This patch fixes it so that the output to the screen can be directly copied and pasted into the CMC revocate ui at ee (processed by CMCRevReqServlet); Again, this is not RFC conforming, but I fixed it anyways; - The output to the file CMCRevoke.out has been fixed so that it is the BER encoding of the request, which can be fed directly into the updated server that now conforms to the RFC (see below) - This code still requires the signer certificate nickname to run, making the shared secret method moot. Since CMCRequest has been updated to work properly, we can leave this for now. On the server side. CMCUserSignedAuth has been updated to handle unsigned DATA; Recall that the original CMC revocation only handled SIGNED_DATA (making assumption that agent always signs the requests). This addition is important to support shared secrets properly. Another thing that's important change on the server side is that it now checks the revoking cert's subject against the signer's subject, if authenticated by CMCUserSignedAuth. The original code did not do that, I think it is because it always checks if it's an agent or not. Something that could be improved on is to have its own servlet. However, due to the time restriction, I only updated existing EnrollProfile, ProfileSubmitCMCServlet, and CMCOutputTemplate to handle the rfc conforming cmc revocation requests. The shared secret handling is left in the CMCOutputTemplate for now. Logically it would make sense to go into CMCUserSignedAuth. This could be left as a possible later ticket for improvement. Shared Token plugin implementation will be added in later ticket as well. Previously missed signing cert validation is also added for more complete check. Some SHA1 are turned into SHA2 Finally, some auditing are added, but it is not finalized. It will be done in the next ticket(s).
Diffstat (limited to 'base/java-tools/src')
-rw-r--r--base/java-tools/src/com/netscape/cmstools/CMCRequest.java251
-rw-r--r--base/java-tools/src/com/netscape/cmstools/CMCRevoke.java133
2 files changed, 235 insertions, 149 deletions
diff --git a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
index 4adf22ba3..00e03a7ca 100644
--- a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
+++ b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
@@ -72,15 +72,14 @@ import org.mozilla.jss.pkix.cmc.GetCert;
import org.mozilla.jss.pkix.cmc.IdentityProofV2;
import org.mozilla.jss.pkix.cmc.LraPopWitness;
import org.mozilla.jss.pkix.cmc.OtherInfo;
-import org.mozilla.jss.pkix.cmc.OtherMsg;
import org.mozilla.jss.pkix.cmc.PKIData;
import org.mozilla.jss.pkix.cmc.PendInfo;
import org.mozilla.jss.pkix.cmc.PopLinkWitnessV2;
import org.mozilla.jss.pkix.cmc.ResponseBody;
+import org.mozilla.jss.pkix.cmc.RevokeRequest;
import org.mozilla.jss.pkix.cmc.TaggedAttribute;
import org.mozilla.jss.pkix.cmc.TaggedCertificationRequest;
import org.mozilla.jss.pkix.cmc.TaggedRequest;
-import org.mozilla.jss.pkix.cmmf.RevRequest;
import org.mozilla.jss.pkix.cms.ContentInfo;
import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
import org.mozilla.jss.pkix.cms.EncryptedContentInfo;
@@ -374,14 +373,30 @@ public class CMCRequest {
/**
* getCMCBlob create and return the enrollment request.
- *
+ * It now handles two types of data input:
+ * - SignedData (which is for signed data)
+ * - data (which is for unsigned data)
* @return the CMC enrollment request encoded in base64
*
*/
- static ContentInfo getCMCBlob(SignedData req) {
+ static ContentInfo getCMCBlob(SignedData signedData, byte[] data) {
String method = "getCMCBlob: ";
System.out.println(method + "begins");
- ContentInfo fullEnrollmentReq = new ContentInfo(req);
+ ContentInfo fullEnrollmentReq = null;
+ if (signedData != null && data == null) {
+ System.out.println("getCMCBlob: generating signed data");
+ fullEnrollmentReq = new ContentInfo(signedData);
+ } else if (data != null && signedData == null) {
+ System.out.println("getCMCBlob: generating unsigned data");
+ fullEnrollmentReq = new ContentInfo(data);
+ } else if (signedData == null && data == null) {
+ System.out.println("getCMCBlob: both params are null");
+ System.exit(1);
+ } else {
+ System.out.println("getCMCBlob: both params are not null; only one of them can be used, the other must be null");
+ System.exit(1);
+ }
+
try {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(bs);
@@ -768,29 +783,32 @@ public class CMCRequest {
System.out.println("");
System.out.println("#input: full path for the PKCS10 request or CRMF request,");
System.out.println("#the content must be in Base-64 encoded format");
- System.out.println("#Multiple files are supported. They must be separated by space.");
+// System.out.println("#Multiple files are supported. They must be separated by space.");
+ System.out.println("# in case of revocation, input will be ignored");
System.out.println("input=crmf.req");
System.out.println("");
System.out.println("#output: full path for the CMC request in binary format");
System.out.println("output=cmc.req");
System.out.println("");
- System.out.println("#tokenname: name of token where agent signing cert can be found (default is internal)");
+ System.out.println("#tokenname: name of token where user signing cert can be found (default is internal)");
System.out.println("tokenname=internal");
System.out.println("");
- System.out.println("#nickname: nickname for agent certificate which will be used");
- System.out.println("#to sign the CMC full request.");
+ System.out.println("#nickname: nickname for user certificate which will be used");
+ System.out.println("#to sign the CMC full request (enrollment or revocation).");
+ System.out.println("");
System.out.println("#selfSign: if selfSign is true, the CMC request will be");
- System.out.println("#signed with the pairing private key of the request;");
+ System.out.println("#signed with the pairing private key of the enrollment request;");
System.out.println("#and in which case the nickname will be ignored");
- System.out.println("nickname=CMS Agent Certificate");
+ System.out.println("#If revRequest.sharedSecret is specified, then nickname will also be ignored.");
+ System.out.println("nickname=CMS User Signing Certificate");
System.out.println("");
System.out.println("selfSign=false");
System.out.println("");
System.out.println("#dbdir: directory for cert8.db, key3.db and secmod.db");
System.out.println("dbdir=./");
System.out.println("");
- System.out.println("#password: password for cert8.db which stores the agent");
- System.out.println("#certificate");
+ System.out.println("#password: password for cert8.db which stores the user signing");
+ System.out.println("#certificate and keys");
System.out.println("password=pass");
System.out.println("");
System.out.println("#format: request format, either pkcs10 or crmf");
@@ -844,13 +862,19 @@ public class CMCRequest {
System.out.println("#control. Otherwise, false.");
System.out.println("revRequest.enable=false");
System.out.println("");
+/*
System.out.println("#revRequest.nickname: The nickname for the revoke certificate");
System.out.println("revRequest.nickname=newuser's 102504a ID");
System.out.println("");
+*/
System.out.println("#revRequest.issuer: The issuer name for the certificate being");
- System.out.println("#revoked.");
+ System.out.println("#revoked. It only needs to be specified when the request is unsigned,;");
+ System.out.println("#as in the case when sharedSecret is used;");
System.out.println("revRequest.issuer=cn=Certificate Manager,c=us");
System.out.println("");
+ System.out.println("#revRequest.sharedSecret: The sharedSecret");
+ System.out.println("revRequest.sharedSecret=");
+ System.out.println("");
System.out.println("#revRequest.serial: The serial number for the certificate being");
System.out.println("#revoked.");
System.out.println("revRequest.serial=61");
@@ -861,9 +885,6 @@ public class CMCRequest {
System.out.println("# certificateHold, removeFromCRL");
System.out.println("revRequest.reason=unspecified");
System.out.println("");
- System.out.println("#revRequest.sharedSecret: The sharedSecret");
- System.out.println("revRequest.sharedSecret=");
- System.out.println("");
System.out.println("#revRequest.comment: The human readable comment");
System.out.println("revRequest.comment=");
System.out.println("");
@@ -972,27 +993,27 @@ public class CMCRequest {
private static ENUMERATED toCRLReason(String str) {
if (str.equalsIgnoreCase("unspecified")) {
- return RevRequest.unspecified;
+ return RevokeRequest.unspecified;
} else if (str.equalsIgnoreCase("keyCompromise")) {
- return RevRequest.keyCompromise;
+ return RevokeRequest.keyCompromise;
} else if (str.equalsIgnoreCase("caCompromise")) {
- return RevRequest.cACompromise;
+ return RevokeRequest.cACompromise;
} else if (str.equalsIgnoreCase("affiliationChanged")) {
- return RevRequest.affiliationChanged;
+ return RevokeRequest.affiliationChanged;
} else if (str.equalsIgnoreCase("superseded")) {
- return RevRequest.superseded;
+ return RevokeRequest.superseded;
} else if (str.equalsIgnoreCase("cessationOfOperation")) {
- return RevRequest.cessationOfOperation;
+ return RevokeRequest.cessationOfOperation;
} else if (str.equalsIgnoreCase("certificateHold")) {
- return RevRequest.certificateHold;
+ return RevokeRequest.certificateHold;
} else if (str.equalsIgnoreCase("removeFromCRL")) {
- return RevRequest.removeFromCRL;
+ return RevokeRequest.removeFromCRL;
}
System.out.println("Unrecognized CRL reason");
System.exit(1);
- return RevRequest.unspecified;
+ return RevokeRequest.unspecified;
}
/**
@@ -1119,42 +1140,84 @@ public class CMCRequest {
return bpid;
}
- private static int addRevRequestAttr(int bpid, SEQUENCE seq, SEQUENCE otherMsgSeq, CryptoToken token, String tokenName, String nickname,
+ /*
+ * addRevRequestAttr adds the RevokeRequest control
+ * If sharedSecret exist, issuer name needs to be supplied;
+ * else signing cert is needed to extract issuerName
+ */
+ private static int addRevRequestAttr(int bpid, SEQUENCE seq,
+ CryptoToken token, X509Certificate revokeSignCert,
String revRequestIssuer, String revRequestSerial, String revRequestReason,
String revRequestSharedSecret, String revRequestComment, String invalidityDatePresent,
CryptoManager manager) {
+
+ String method = "addRevRequestAttr: ";
try {
- if (nickname.length() <= 0) {
- System.out.println("The nickname for the certificate being revoked is null");
- System.exit(1);
- }
- String nickname1 = nickname;
UTF8String comment = null;
OCTET_STRING sharedSecret = null;
GeneralizedTime d = null;
- X500Name subjectname = new X500Name(revRequestIssuer);
+ X500Name issuerName = null;
+
+ if ((revRequestSerial == null) || (revRequestSerial.length() <= 0)) {
+ System.out.println(method + "revocation serial number must be supplied");
+ System.exit(1);
+ }
+ if ((revRequestReason == null) || (revRequestReason.length() <= 0)) {
+ System.out.println(method + "revocation reason must be supplied");
+ System.exit(1);
+ }
INTEGER snumber = new INTEGER(revRequestSerial);
ENUMERATED reason = toCRLReason(revRequestReason);
- if (revRequestSharedSecret.length() > 0)
+
+ if ((revRequestSharedSecret != null) && (revRequestSharedSecret.length() > 0)) {
sharedSecret = new OCTET_STRING(revRequestSharedSecret.getBytes());
- if (revRequestComment.length() > 0)
+ // in case of sharedSecret,
+ // issuer name will have to be provided;
+ // revokeSignCert is ignored;
+ if (revRequestIssuer == null) {
+ System.out.println(method + "issuer name must be supplied when shared secret is used");
+ System.exit(1);
+ }
+ issuerName = new X500Name(revRequestIssuer);
+ } else { // signing case; revokeSignCert is required
+ if (revokeSignCert == null) {
+ System.out.println(method + "revokeSignCert must be supplied in the signing case");
+ System.exit(1);
+ }
+ }
+
+ if (revRequestComment != null && revRequestComment.length() > 0)
comment = new UTF8String(revRequestComment);
if (invalidityDatePresent.equals("true"))
d = new GeneralizedTime(new Date());
- RevRequest revRequest =
- new RevRequest(new ANY(subjectname.getEncoded()), snumber,
- reason, d, sharedSecret, comment);
- int revokeBpid = bpid;
+
+ if (sharedSecret == null) {
+ System.out.println(method + "no sharedSecret found; request will be signed;");
+
+ // getting issuerName from revokeSignCert
+ byte[] certB = revokeSignCert.getEncoded();
+ X509CertImpl impl = new X509CertImpl(certB);
+ issuerName = (X500Name) impl.getIssuerDN();
+ } else {
+ System.out.println(method + "sharedSecret found; request will be unsigned;");
+ }
+
+ RevokeRequest revRequest = new RevokeRequest(new ANY(issuerName.getEncoded()), snumber,
+ reason, d, sharedSecret, comment);
+
TaggedAttribute revRequestControl = new TaggedAttribute(
new INTEGER(bpid++),
OBJECT_IDENTIFIER.id_cmc_revokeRequest, revRequest);
seq.addElement(revRequestControl);
+ System.out.println(method + "RevokeRequest control created.");
- if (sharedSecret != null) {
- System.out.println("Successfully create revRequest control. bpid = " + (bpid - 1));
- System.out.println("");
- return bpid;
- }
+ return bpid;
+/*
+ * Constructing OtherMsg to include the SignerInfo makes no sense here
+ * as the outer layer SignedData would have SignerInfo.
+ * It is possibly done because the original code assumed a self-signed
+ * revocation request that is subsequently signed by an agent...
+ * which is not conforming to the RFC.
EncapsulatedContentInfo revokeContent = new EncapsulatedContentInfo(
OBJECT_IDENTIFIER.id_cct_PKIData, revRequestControl);
@@ -1241,6 +1304,7 @@ public class CMCRequest {
otherMsgSeq.addElement(otherMsg);
System.out.println("Successfully create revRequest control. bpid = " + (bpid - 1));
System.out.println("");
+*/
} catch (Exception e) {
System.out.println("Error in creating revRequest control. Check the parameters. Exception="+ e.toString());
System.exit(1);
@@ -1346,9 +1410,9 @@ public class CMCRequest {
String salt = "lala123" + date.toString();
try {
- MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ MessageDigest SHA256Digest = MessageDigest.getInstance("SHA256");
- dig = SHA1Digest.digest(salt.getBytes());
+ dig = SHA256Digest.digest(salt.getBytes());
} catch (NoSuchAlgorithmException ex) {
dig = salt.getBytes();
}
@@ -1825,7 +1889,6 @@ public class CMCRequest {
String dataReturnEnable = "false", dataReturnData = null;
String transactionMgtEnable = "false", transactionMgtId = null;
String senderNonceEnable = "false", senderNonce = null;
- String revCertNickname = "";
String revRequestEnable = "false", revRequestIssuer = null, revRequestSerial = null;
String revRequestReason = null, revRequestSharedSecret = null, revRequestComment = null;
String revRequestInvalidityDatePresent = "false";
@@ -1941,8 +2004,6 @@ public class CMCRequest {
revRequestComment = val;
} else if (name.equals("revRequest.invalidityDatePresent")) {
revRequestInvalidityDatePresent = val;
- } else if (name.equals("revRequest.nickname")) {
- revCertNickname = val;
} else if (name.equals("identification.enable")) {
identificationEnable = val;
} else if (name.equals("identification")) {
@@ -1985,7 +2046,8 @@ public class CMCRequest {
printUsage();
}
- if (!selfSign.equals("true") && nickname == null) {
+ if ((!selfSign.equals("true") && (revRequestSharedSecret == null))
+ && nickname == null) {
System.out.println("Missing nickname.");
printUsage();
}
@@ -2031,11 +2093,12 @@ public class CMCRequest {
certname.append(tokenName);
certname.append(":");
}
- if (!selfSign.equals("true") && nickname != null) {
+ if ((!selfSign.equals("true") || (revRequestSharedSecret == null))
+ && nickname != null) {
certname.append(nickname);
signerCert = cm.findCertByNickname(certname.toString());
if (signerCert != null) {
- System.out.println("got signerCert: "+ certname.toString());
+ System.out.println("got signerCert: " + certname.toString());
}
}
@@ -2065,6 +2128,7 @@ public class CMCRequest {
}
}
+ boolean isSharedSecretRevoke = false;
if (decryptedPopEnable.equalsIgnoreCase("true")) {
if (encryptedPopResponseFile == null) {
System.out.println("ecryptedPop.enable = true, but encryptedPopResponseFile is not specified.");
@@ -2091,7 +2155,7 @@ public class CMCRequest {
}
} else { // !decryptedPopEnable
- if (ifilename == null) {
+ if (!revRequestEnable.equalsIgnoreCase("true") && ifilename == null) {
System.out.println("Missing input filename for PKCS10 or CRMF.");
printUsage();
}
@@ -2109,14 +2173,17 @@ public class CMCRequest {
}
}
- StringTokenizer tokenizer = new StringTokenizer(ifilename, " ");
- String[] ifiles = new String[num];
- for (int i = 0; i < num; i++) {
- String ss = tokenizer.nextToken();
- ifiles[i] = ss;
- if (ss == null) {
- System.out.println("Missing input file for the request.");
- System.exit(1);
+ String[] ifiles = null;
+ if (revRequestEnable.equalsIgnoreCase("false")) {
+ StringTokenizer tokenizer = new StringTokenizer(ifilename, " ");
+ ifiles = new String[num];
+ for (int i = 0; i < num; i++) {
+ String ss = tokenizer.nextToken();
+ ifiles[i] = ss;
+ if (ss == null) {
+ System.out.println("Missing input file for the request.");
+ System.exit(1);
+ }
}
}
@@ -2126,11 +2193,12 @@ public class CMCRequest {
}
if (format == null) {
- System.out.println("Missing format.");
- printUsage();
+ System.out.println("Missing format..assume revocation");
+ //printUsage();
}
+
String[] requests = new String[num];
- for (int i = 0; i < num; i++) {
+ for (int i = 0; i < num && revRequestEnable.equalsIgnoreCase("false") ; i++) {
BufferedReader inputBlob = null;
try {
inputBlob = new BufferedReader(new InputStreamReader(
@@ -2222,20 +2290,20 @@ public class CMCRequest {
SEQUENCE otherMsgSeq = new SEQUENCE();
if (revRequestEnable.equalsIgnoreCase("true")) {
- if (revRequestIssuer.length() == 0 || revRequestSerial.length() == 0 ||
- revRequestReason.length() == 0) {
- System.out.println("Illegal parameters for revRequest control");
- printUsage();
- System.exit(1);
+ if ((revRequestSharedSecret!= null)
+ && (revRequestSharedSecret.length() > 0)) {
+ isSharedSecretRevoke = true;
+ //this will result in unsigned data
}
- bpid = addRevRequestAttr(bpid, controlSeq, otherMsgSeq, token, tokenName, revCertNickname,
+ bpid = addRevRequestAttr(bpid, controlSeq, token, signerCert,
revRequestIssuer, revRequestSerial, revRequestReason, revRequestSharedSecret,
revRequestComment, revRequestInvalidityDatePresent, cm);
- }
+ pkidata = new PKIData(controlSeq, new SEQUENCE(), new SEQUENCE(), new SEQUENCE());
+ } else {
- // create the request PKIData
- pkidata = createPKIData(
+ // create the request PKIData
+ pkidata = createPKIData(
selfSign,
requests,
format, transactionMgtEnable, transactionMgtId,
@@ -2248,6 +2316,7 @@ public class CMCRequest {
popLinkWitnessV2keyGenAlg, popLinkWitnessV2macAlg,
controlSeq, otherMsgSeq, bpid,
token, privk);
+ }
if (pkidata == null) {
System.out.println("pkidata null after createPKIData(). Exiting with error");
@@ -2255,22 +2324,30 @@ public class CMCRequest {
}
}
- // sign the request
- SignedData signedData = null;
- if (selfSign.equalsIgnoreCase("true")) {
- // selfSign signs with private key
- System.out.println("selfSign is true...");
- signedData = signData(privk, pkidata);
+ if (isSharedSecretRevoke) {
+ cmcblob = getCMCBlob(null,
+ ASN1Util.encode(pkidata));
} else {
- // none selfSign signs with existing cert
- System.out.println("selfSign is false...");
- signedData = signData(signerCert, tokenName, nickname, cm, pkidata);
- }
- if (signedData == null) {
- System.out.println("signData() returns null. Exiting with error");
- System.exit(1);
+
+ SignedData signedData = null;
+
+ // sign the request
+ if (selfSign.equalsIgnoreCase("true")) {
+ // selfSign signs with private key
+ System.out.println("selfSign is true...");
+ signedData = signData(privk, pkidata);
+ } else {
+ // none selfSign signs with existing cert
+ System.out.println("selfSign is false...");
+ signedData = signData(signerCert, tokenName, nickname, cm, pkidata);
+ }
+ if (signedData == null) {
+ System.out.println("signData() returns null. Exiting with error");
+ System.exit(1);
+ }
+ cmcblob = getCMCBlob(signedData, null);
}
- cmcblob = getCMCBlob(signedData);
+
if (cmcblob == null) {
System.out.println("getCMCBlob() returns null. Exiting with error");
System.exit(1);
diff --git a/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java b/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java
index c2572e64b..e46e8834f 100644
--- a/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java
+++ b/base/java-tools/src/com/netscape/cmstools/CMCRevoke.java
@@ -75,6 +75,7 @@ public class CMCRevoke {
public static final String RFC7468_TRAILER = "-----END CERTIFICATE REQUEST-----";
static String dValue = null, nValue = null, iValue = null, sValue = null, mValue = null, hValue = null,
pValue = null, cValue = null;
+ static String tValue = null;
public static final String CMS_BASE_CA_SIGNINGCERT_NOT_FOUND = "CA signing certificate not found";
public static final String PR_REQUEST_CMC = "CMC";
@@ -109,8 +110,9 @@ public class CMCRevoke {
"-d<dir to cert8.db, key3.db> " +
"-n<nickname> " +
"-i<issuerName> " +
- "-s<serialName> " +
+ "-s<serialNumber> " +
"-m<reason to revoke> " +
+ "-t<shared secret> " +
"-p<password to db> " +
"-h<tokenname> " +
"-c<comment> ");
@@ -135,6 +137,8 @@ public class CMCRevoke {
mValue = cleanArgs(s[i].substring(2));
} else if (s[i].startsWith("-p")) {
pValue = cleanArgs(s[i].substring(2));
+ } else if (s[i].startsWith("-t")) {
+ tValue = cleanArgs(s[i].substring(2));
} else if (s[i].startsWith("-h")) {
hValue = cleanArgs(s[i].substring(2));
} else if (s[i].startsWith("-c")) {
@@ -143,8 +147,6 @@ public class CMCRevoke {
}
// optional parameters
- if (cValue == null)
- cValue = "";
if (hValue == null)
hValue = "";
@@ -160,7 +162,7 @@ public class CMCRevoke {
"-d<dir to cert8.db, key3.db> " +
"-n<nickname> " +
"-i<issuerName> " +
- "-s<serialName> " +
+ "-s<serialNumber> " +
"-m<reason to revoke> " +
"-p<password to db> " +
"-h<tokenname> " +
@@ -191,9 +193,9 @@ public class CMCRevoke {
token.login(pass);
X509Certificate signerCert = getCertificate(cm, hValue, nValue);
- String outBlob = createRevokeReq(hValue, signerCert, cm);
+ ContentInfo fullEnrollmentRequest = createRevokeReq(hValue, signerCert, cm);
- printCMCRevokeRequest(outBlob);
+ printCMCRevokeRequest(fullEnrollmentRequest);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
@@ -209,29 +211,48 @@ public class CMCRevoke {
*
* @param asciiBASE64Blob the ascii string of the request
*/
- static void printCMCRevokeRequest(String asciiBASE64Blob) {
+ static void printCMCRevokeRequest(ContentInfo fullEnrollmentReq) {
+ String method = "printCMCRevokeRequest: ";
- // (6) Finally, print the actual CMCSigning blob to the
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(bs);
+
+ if (fullEnrollmentReq == null) {
+ System.out.println(method + "param fullEnrollmentRequest is null");
+ System.exit(1);
+ }
+ // format is PR_REQUEST_CMC
+ try {
+ fullEnrollmentReq.encode(os);
+ } catch (IOException e) {
+ System.out.println("CMCSigning: I/O error " +
+ "encountered during write():\n" +
+ e);
+ System.exit(1);
+ }
+ //ps.print(Utils.base64encode(os.toByteArray()));
+ // no line breaks for ease of copy/paste for CA acceptance
+ System.out.println(RFC7468_HEADER);
+ ps.print(Utils.base64encodeSingleLine(os.toByteArray()));
+ ////fullEnrollmentReq.print(ps); // no header/trailer
+
+ String asciiBASE64Blob = bs.toString();
+ System.out.println(asciiBASE64Blob + "\n" + RFC7468_TRAILER);
+
+ // (6) Finally, print the actual CMCSigning binary blob to the
// specified output file
FileOutputStream outputBlob = null;
try {
outputBlob = new FileOutputStream("CMCRevoke.out");
+ fullEnrollmentReq.encode(outputBlob);
} catch (IOException e) {
System.out.println("CMCSigning: unable to open file CMCRevoke.out for writing:\n" + e);
return;
}
- System.out.println(RFC7468_HEADER);
- System.out.println(asciiBASE64Blob + RFC7468_TRAILER);
- try {
- asciiBASE64Blob = RFC7468_HEADER + "\n" + asciiBASE64Blob + RFC7468_TRAILER;
- outputBlob.write(asciiBASE64Blob.getBytes());
- } catch (IOException e) {
- System.out.println("CMCSigning: I/O error " +
- "encountered during write():\n" +
- e);
- }
+ System.out.println("\nCMC revocation binary blob written to CMCRevoke.out\n");
try {
outputBlob.close();
@@ -280,12 +301,11 @@ public class CMCRevoke {
* @param manager the crypto manger.
* @return the CMC revocation request encoded in base64
*/
- static String createRevokeReq(String tokenname, X509Certificate signerCert, CryptoManager manager) {
+ static ContentInfo createRevokeReq(String tokenname, X509Certificate signerCert, CryptoManager manager) {
java.security.PrivateKey privKey = null;
SignerIdentifier si = null;
ContentInfo fullEnrollmentReq = null;
- String asciiBASE64Blob = null;
try {
@@ -305,8 +325,8 @@ public class CMCRevoke {
if (privKey == null) {
System.out.println("CMCRevoke::createRevokeReq() - " +
- "privKey is null!");
- return "";
+ "privKey is null!");
+ return null;
}
int bpid = 1;
@@ -319,65 +339,64 @@ public class CMCRevoke {
byte[] dig;
try {
- MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ MessageDigest SHA2Digest = MessageDigest.getInstance("SHA256");
- dig = SHA1Digest.digest(salt.getBytes());
+ dig = SHA2Digest.digest(salt.getBytes());
} catch (NoSuchAlgorithmException ex) {
dig = salt.getBytes();
}
String sn = Utils.base64encode(dig);
- TaggedAttribute senderNonce =
- new TaggedAttribute(new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce,
- new OCTET_STRING(sn.getBytes()));
+ TaggedAttribute senderNonce = new TaggedAttribute(new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce,
+ new OCTET_STRING(sn.getBytes()));
controlSeq.addElement(senderNonce);
Name subjectName = new Name();
subjectName.addCommonName(iValue);
- org.mozilla.jss.pkix.cmmf.RevRequest lRevokeRequest =
- new org.mozilla.jss.pkix.cmmf.RevRequest(new ANY((new X500Name(iValue)).getEncoded()),
- new INTEGER(sValue),
- //org.mozilla.jss.pkix.cmmf.RevRequest.unspecified,
- new ENUMERATED((new Integer(mValue)).longValue()),
- null,
- new OCTET_STRING(pValue.getBytes()),
- new UTF8String(cValue.toCharArray()));
+ org.mozilla.jss.pkix.cmc.RevokeRequest lRevokeRequest = new org.mozilla.jss.pkix.cmc.RevokeRequest(
+ new ANY((new X500Name(iValue)).getEncoded()),
+ new INTEGER(sValue),
+ //org.mozilla.jss.pkix.cmc.RevokeRequest.unspecified,
+ new ENUMERATED((new Integer(mValue)).longValue()),
+ null,
+ (tValue != null) ? new OCTET_STRING(tValue.getBytes()) : null,
+ (cValue != null) ? new UTF8String(cValue.toCharArray()) : null);
//byte[] encoded = ASN1Util.encode(lRevokeRequest);
- //org.mozilla.jss.asn1.ASN1Template template = new org.mozilla.jss.pkix.cmmf.RevRequest.Template();
- //org.mozilla.jss.pkix.cmmf.RevRequest revRequest = (org.mozilla.jss.pkix.cmmf.RevRequest)
+ //org.mozilla.jss.asn1.ASN1Template template = new org.mozilla.jss.pkix.cmc.RevokeRequest.Template();
+ //org.mozilla.jss.pkix.cmc.RevokeRequest revRequest = (org.mozilla.jss.pkix.cmc.RevokeRequest)
// template.decode(new java.io.ByteArrayInputStream(
// encoded));
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- //lRevokeRequest.encode(os); // khai
- TaggedAttribute revokeRequestTag =
- new TaggedAttribute(new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_revokeRequest,
- lRevokeRequest);
+ TaggedAttribute revokeRequestTag = new TaggedAttribute(new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_revokeRequest,
+ lRevokeRequest);
controlSeq.addElement(revokeRequestTag);
PKIData pkidata = new PKIData(controlSeq, new SEQUENCE(), new SEQUENCE(), new SEQUENCE());
EncapsulatedContentInfo ci = new EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIData, pkidata);
- // SHA1 is the default digest Alg for now.
DigestAlgorithm digestAlg = null;
SignatureAlgorithm signAlg = null;
- org.mozilla.jss.crypto.PrivateKey.Type signingKeyType = ((org.mozilla.jss.crypto.PrivateKey) privKey).getType();
+ org.mozilla.jss.crypto.PrivateKey.Type signingKeyType = ((org.mozilla.jss.crypto.PrivateKey) privKey)
+ .getType();
if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.RSA)) {
- signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
+ signAlg = SignatureAlgorithm.RSASignatureWithSHA256Digest;
} else if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.EC)) {
- signAlg = SignatureAlgorithm.ECSignatureWithSHA1Digest;
- } else if (signingKeyType.equals(org.mozilla.jss.crypto.PrivateKey.Type.DSA)) {
- signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ signAlg = SignatureAlgorithm.ECSignatureWithSHA256Digest;
+ } else {
+ System.out.println("Algorithm not supported:" +
+ signingKeyType);
+ return null;
}
MessageDigest SHADigest = null;
byte[] digest = null;
try {
- SHADigest = MessageDigest.getInstance("SHA1");
- digestAlg = DigestAlgorithm.SHA1;
+ SHADigest = MessageDigest.getInstance("SHA256");
+ digestAlg = DigestAlgorithm.SHA256;
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
@@ -411,21 +430,11 @@ public class CMCRevoke {
fullEnrollmentReq = new ContentInfo(req);
- ByteArrayOutputStream bs = new ByteArrayOutputStream();
- PrintStream ps = new PrintStream(bs);
-
- if (fullEnrollmentReq != null) {
- // format is PR_REQUEST_CMC
- fullEnrollmentReq.encode(os);
- ps.print(Utils.base64encode(os.toByteArray()));
- ////fullEnrollmentReq.print(ps); // no header/trailer
- }
-
- asciiBASE64Blob = bs.toString();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
- return asciiBASE64Blob;
+
+ return fullEnrollmentReq;
}
}