< prev index next >
src/java.base/share/classes/sun/security/rsa/PSSParameters.java
Print this page
rev 51972 : 8215694: keytool cannot generate RSASSA-PSS certificates
Reviewed-by: xuelei
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -50,17 +50,11 @@
*
*/
public final class PSSParameters extends AlgorithmParametersSpi {
- private String mdName;
- private MGF1ParameterSpec mgfSpec;
- private int saltLength;
- private int trailerField;
-
- private static final ObjectIdentifier OID_MGF1 =
- ObjectIdentifier.newInternal(new int[] {1,2,840,113549,1,1,8});
+ private PSSParameterSpec spec;
public PSSParameters() {
}
@Override
@@ -69,95 +63,97 @@
if (!(paramSpec instanceof PSSParameterSpec)) {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
}
PSSParameterSpec spec = (PSSParameterSpec) paramSpec;
- this.mdName = spec.getDigestAlgorithm();
+
String mgfName = spec.getMGFAlgorithm();
- if (!mgfName.equalsIgnoreCase("MGF1")) {
+ if (!spec.getMGFAlgorithm().equalsIgnoreCase("MGF1")) {
throw new InvalidParameterSpecException("Unsupported mgf " +
mgfName + "; MGF1 only");
}
AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
if (!(mgfSpec instanceof MGF1ParameterSpec)) {
throw new InvalidParameterSpecException("Inappropriate mgf " +
"parameters; non-null MGF1ParameterSpec only");
}
- this.mgfSpec = (MGF1ParameterSpec) mgfSpec;
- this.saltLength = spec.getSaltLength();
- this.trailerField = spec.getTrailerField();
+ this.spec = spec;
}
@Override
protected void engineInit(byte[] encoded) throws IOException {
// first initialize with the DEFAULT values before
// retrieving from the encoding bytes
- this.mdName = DEFAULT.getDigestAlgorithm();
- this.mgfSpec = (MGF1ParameterSpec) DEFAULT.getMGFParameters();
- this.saltLength = DEFAULT.getSaltLength();
- this.trailerField = DEFAULT.getTrailerField();
+ String mdName = DEFAULT.getDigestAlgorithm();
+ MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) DEFAULT.getMGFParameters();
+ int saltLength = DEFAULT.getSaltLength();
+ int trailerField = DEFAULT.getTrailerField();
DerInputStream der = new DerInputStream(encoded);
DerValue[] datum = der.getSequence(4);
+
for (DerValue d : datum) {
if (d.isContextSpecific((byte) 0x00)) {
// hash algid
- this.mdName = AlgorithmId.parse
+ mdName = AlgorithmId.parse
(d.data.getDerValue()).getName();
} else if (d.isContextSpecific((byte) 0x01)) {
// mgf algid
AlgorithmId val = AlgorithmId.parse(d.data.getDerValue());
- if (!val.getOID().equals(OID_MGF1)) {
+ if (!val.getOID().equals(AlgorithmId.mgf1_oid)) {
throw new IOException("Only MGF1 mgf is supported");
}
AlgorithmId params = AlgorithmId.parse(
new DerValue(val.getEncodedParams()));
String mgfDigestName = params.getName();
switch (mgfDigestName) {
case "SHA-1":
- this.mgfSpec = MGF1ParameterSpec.SHA1;
+ mgfSpec = MGF1ParameterSpec.SHA1;
break;
case "SHA-224":
- this.mgfSpec = MGF1ParameterSpec.SHA224;
+ mgfSpec = MGF1ParameterSpec.SHA224;
break;
case "SHA-256":
- this.mgfSpec = MGF1ParameterSpec.SHA256;
+ mgfSpec = MGF1ParameterSpec.SHA256;
break;
case "SHA-384":
- this.mgfSpec = MGF1ParameterSpec.SHA384;
+ mgfSpec = MGF1ParameterSpec.SHA384;
break;
case "SHA-512":
- this.mgfSpec = MGF1ParameterSpec.SHA512;
+ mgfSpec = MGF1ParameterSpec.SHA512;
break;
case "SHA-512/224":
- this.mgfSpec = MGF1ParameterSpec.SHA512_224;
+ mgfSpec = MGF1ParameterSpec.SHA512_224;
break;
case "SHA-512/256":
- this.mgfSpec = MGF1ParameterSpec.SHA512_256;
+ mgfSpec = MGF1ParameterSpec.SHA512_256;
break;
default:
throw new IOException
("Unrecognized message digest algorithm " +
mgfDigestName);
}
} else if (d.isContextSpecific((byte) 0x02)) {
// salt length
- this.saltLength = d.data.getDerValue().getInteger();
- if (this.saltLength < 0) {
+ saltLength = d.data.getDerValue().getInteger();
+ if (saltLength < 0) {
throw new IOException("Negative value for saltLength");
}
} else if (d.isContextSpecific((byte) 0x03)) {
// trailer field
- this.trailerField = d.data.getDerValue().getInteger();
- if (this.trailerField != 1) {
+ trailerField = d.data.getDerValue().getInteger();
+ if (trailerField != 1) {
throw new IOException("Unsupported trailerField value " +
- this.trailerField);
+ trailerField);
}
} else {
throw new IOException("Invalid encoded PSSParameters");
}
}
+
+ this.spec = new PSSParameterSpec(mdName, "MGF1", mgfSpec,
+ saltLength, trailerField);
}
@Override
protected void engineInit(byte[] encoded, String decodingMethod)
throws IOException {
@@ -171,85 +167,108 @@
@Override
protected <T extends AlgorithmParameterSpec>
T engineGetParameterSpec(Class<T> paramSpec)
throws InvalidParameterSpecException {
if (PSSParameterSpec.class.isAssignableFrom(paramSpec)) {
- return paramSpec.cast(
- new PSSParameterSpec(mdName, "MGF1", mgfSpec,
- saltLength, trailerField));
+ return paramSpec.cast(spec);
} else {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
}
}
@Override
protected byte[] engineGetEncoded() throws IOException {
+ return getEncoded(spec);
+ }
+
+ @Override
+ protected byte[] engineGetEncoded(String encMethod) throws IOException {
+ if ((encMethod != null) &&
+ (!encMethod.equalsIgnoreCase("ASN.1"))) {
+ throw new IllegalArgumentException("Only support ASN.1 format");
+ }
+ return engineGetEncoded();
+ }
+
+ @Override
+ protected String engineToString() {
+ return spec.toString();
+ }
+
+ /**
+ * Returns the encoding of a {@link PSSParameterSpec} object. This method
+ * is used in this class and {@link AlgorithmId}.
+ *
+ * @param spec a {@code PSSParameterSpec} object
+ * @return its DER encoding
+ * @throws IOException if the name of a MessageDigest or MaskGenAlgorithm
+ * is unsupported
+ */
+ public static byte[] getEncoded(PSSParameterSpec spec) throws IOException {
+
+ AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
+ if (!(mgfSpec instanceof MGF1ParameterSpec)) {
+ throw new IOException("Cannot encode " + mgfSpec);
+ }
+
+ MGF1ParameterSpec mgf1Spec = (MGF1ParameterSpec)mgfSpec;
+
DerOutputStream tmp = new DerOutputStream();
DerOutputStream tmp2, tmp3;
// MD
AlgorithmId mdAlgId;
try {
- mdAlgId = AlgorithmId.get(mdName);
+ mdAlgId = AlgorithmId.get(spec.getDigestAlgorithm());
} catch (NoSuchAlgorithmException nsae) {
- throw new IOException("AlgorithmId " + mdName +
- " impl not found");
+ throw new IOException("AlgorithmId " + spec.getDigestAlgorithm() +
+ " impl not found");
+ }
+ if (!mdAlgId.getOID().equals(AlgorithmId.SHA_oid)) {
+ tmp2 = new DerOutputStream();
+ mdAlgId.derEncode(tmp2);
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0),
+ tmp2);
}
- tmp2 = new DerOutputStream();
- mdAlgId.derEncode(tmp2);
- tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0),
- tmp2);
// MGF
- tmp2 = new DerOutputStream();
- tmp2.putOID(OID_MGF1);
AlgorithmId mgfDigestId;
try {
- mgfDigestId = AlgorithmId.get(mgfSpec.getDigestAlgorithm());
+ mgfDigestId = AlgorithmId.get(mgf1Spec.getDigestAlgorithm());
} catch (NoSuchAlgorithmException nase) {
throw new IOException("AlgorithmId " +
- mgfSpec.getDigestAlgorithm() + " impl not found");
+ mgf1Spec.getDigestAlgorithm() + " impl not found");
+ }
+
+ if (!mgfDigestId.getOID().equals(AlgorithmId.SHA_oid)) {
+ tmp2 = new DerOutputStream();
+ tmp2.putOID(AlgorithmId.mgf1_oid);
+ mgfDigestId.encode(tmp2);
+ tmp3 = new DerOutputStream();
+ tmp3.write(DerValue.tag_Sequence, tmp2);
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 1),
+ tmp3);
}
- mgfDigestId.encode(tmp2);
- tmp3 = new DerOutputStream();
- tmp3.write(DerValue.tag_Sequence, tmp2);
- tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)1),
- tmp3);
// SaltLength
- tmp2 = new DerOutputStream();
- tmp2.putInteger(saltLength);
- tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)2),
- tmp2);
+ if (spec.getSaltLength() != 20) {
+ tmp2 = new DerOutputStream();
+ tmp2.putInteger(spec.getSaltLength());
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 2),
+ tmp2);
+ }
// TrailerField
- tmp2 = new DerOutputStream();
- tmp2.putInteger(trailerField);
- tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)3),
- tmp2);
+ if (spec.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
+ tmp2 = new DerOutputStream();
+ tmp2.putInteger(spec.getTrailerField());
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 3),
+ tmp2);
+ }
// Put all together under a SEQUENCE tag
DerOutputStream out = new DerOutputStream();
out.write(DerValue.tag_Sequence, tmp);
return out.toByteArray();
}
-
- @Override
- protected byte[] engineGetEncoded(String encMethod) throws IOException {
- if ((encMethod != null) &&
- (!encMethod.equalsIgnoreCase("ASN.1"))) {
- throw new IllegalArgumentException("Only support ASN.1 format");
- }
- return engineGetEncoded();
- }
-
- @Override
- protected String engineToString() {
- StringBuilder sb = new StringBuilder();
- sb.append("MD: " + mdName + "\n")
- .append("MGF: MGF1" + mgfSpec.getDigestAlgorithm() + "\n")
- .append("SaltLength: " + saltLength + "\n")
- .append("TrailerField: " + trailerField + "\n");
- return sb.toString();
- }
}
< prev index next >