Path: blob/master/src/java.base/share/classes/sun/security/util/JarConstraintsParameters.java
67760 views
/*1* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.util;2627import java.security.CodeSigner;28import java.security.Key;29import java.security.Timestamp;30import java.security.cert.CertPath;31import java.security.cert.X509Certificate;32import java.util.Date;33import java.util.HashSet;34import java.util.List;35import java.util.Set;36import sun.security.util.AnchorCertificates;37import sun.security.util.ConstraintsParameters;38import sun.security.validator.Validator;3940/**41* This class contains parameters for checking signed JARs against42* constraints specified in the jdk.jar.disabledAlgorithms security43* property.44*/45public class JarConstraintsParameters implements ConstraintsParameters {4647// true if chain is anchored by a JDK root CA48private boolean anchorIsJdkCA;49private boolean anchorIsJdkCASet;50// The timestamp of the signed JAR file, if timestamped51private Date timestamp;52// The keys of the signers and TSA53private final Set<Key> keys;54// The certs in the signers and TSA chain that are issued by the trust anchor55private final Set<X509Certificate> certsIssuedByAnchor;56// The extended exception message57private String message;5859/**60* Create a JarConstraintsParameters.61*62* @param signers the CodeSigners that signed the JAR63*/64public JarConstraintsParameters(CodeSigner[] signers) {65this.keys = new HashSet<>();66this.certsIssuedByAnchor = new HashSet<>();67Date latestTimestamp = null;68boolean skipTimestamp = false;6970// Iterate over the signers and extract the keys, the latest71// timestamp, and the last certificate of each chain which can be72// used for checking if the signer's certificate chains back to a73// JDK root CA74for (CodeSigner signer : signers) {75addToCertsAndKeys(signer.getSignerCertPath());76Timestamp timestamp = signer.getTimestamp();77if (timestamp == null) {78// this means one of the signers doesn't have a timestamp79// and the JAR should be treated as if it isn't timestamped80latestTimestamp = null;81skipTimestamp = true;82} else {83// add the key and last cert of TSA too84addToCertsAndKeys(timestamp.getSignerCertPath());85if (!skipTimestamp) {86Date timestampDate = timestamp.getTimestamp();87if (latestTimestamp == null) {88latestTimestamp = timestampDate;89} else {90if (latestTimestamp.before(timestampDate)) {91latestTimestamp = timestampDate;92}93}94}95}96}97this.timestamp = latestTimestamp;98}99100public JarConstraintsParameters(List<X509Certificate> chain, Timestamp timestamp) {101this.keys = new HashSet<>();102this.certsIssuedByAnchor = new HashSet<>();103addToCertsAndKeys(chain);104if (timestamp != null) {105addToCertsAndKeys(timestamp.getSignerCertPath());106this.timestamp = timestamp.getTimestamp();107} else {108this.timestamp = null;109}110}111112// extract last certificate and signer's public key from chain113private void addToCertsAndKeys(CertPath cp) {114@SuppressWarnings("unchecked")115List<X509Certificate> chain =116(List<X509Certificate>)cp.getCertificates();117addToCertsAndKeys(chain);118}119120private void addToCertsAndKeys(List<X509Certificate> chain) {121if (!chain.isEmpty()) {122this.certsIssuedByAnchor.add(chain.get(chain.size() - 1));123this.keys.add(chain.get(0).getPublicKey());124}125}126127@Override128public String getVariant() {129return Validator.VAR_GENERIC;130}131132/**133* Since loading the cacerts keystore can be an expensive operation,134* this is only performed if this method is called during a "jdkCA"135* constraints check of a disabled algorithm, and the result is cached.136*137* @return true if at least one of the certificates are issued by a138* JDK root CA139*/140@Override141public boolean anchorIsJdkCA() {142if (anchorIsJdkCASet) {143return anchorIsJdkCA;144}145for (X509Certificate cert : certsIssuedByAnchor) {146if (AnchorCertificates.issuerOf(cert)) {147anchorIsJdkCA = true;148break;149}150}151anchorIsJdkCASet = true;152return anchorIsJdkCA;153}154155@Override156public Date getDate() {157return timestamp;158}159160@Override161public Set<Key> getKeys() {162return keys;163}164165/**166* Sets the extended error message. Note: this should be used167* carefully as it is specific to the attribute/entry/file being checked.168*169* @param file the name of the signature related file being verified170* @param target the attribute containing the algorithm that is being171* checked172*/173public void setExtendedExceptionMsg(String file, String target) {174message = " used" + (target != null ? " with " + target : "") +175" in " + file + " file.";176}177178@Override179public String extendedExceptionMsg() {180return message;181}182183@Override184public String toString() {185StringBuilder sb = new StringBuilder("[\n");186sb.append(" Variant: ").append(getVariant());187sb.append("\n Certs Issued by Anchor:");188for (X509Certificate cert : certsIssuedByAnchor) {189sb.append("\n Cert Issuer: ")190.append(cert.getIssuerX500Principal());191sb.append("\n Cert Subject: ")192.append(cert.getSubjectX500Principal());193}194for (Key key : keys) {195sb.append("\n Key: ").append(key.getAlgorithm());196}197if (timestamp != null) {198sb.append("\n Timestamp: ").append(timestamp);199}200sb.append("\n]");201return sb.toString();202}203}204205206