• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package com.ohos.hapsigntool.utils;
17 
18 import com.ohos.hapsigntool.error.CustomException;
19 import com.ohos.hapsigntool.error.ERROR;
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 
23 import javax.security.auth.x500.X500Principal;
24 import java.io.IOException;
25 import java.math.BigInteger;
26 import java.security.InvalidAlgorithmParameterException;
27 import java.security.KeyStore;
28 import java.security.KeyStoreException;
29 import java.security.NoSuchAlgorithmException;
30 import java.security.cert.CertPath;
31 import java.security.cert.CertPathBuilder;
32 import java.security.cert.CertPathBuilderException;
33 import java.security.cert.CertPathValidator;
34 import java.security.cert.CertPathValidatorException;
35 import java.security.cert.CertPathValidatorResult;
36 import java.security.cert.CertStore;
37 import java.security.cert.CertificateException;
38 import java.security.cert.CertificateFactory;
39 import java.security.cert.CollectionCertStoreParameters;
40 import java.security.cert.PKIXBuilderParameters;
41 import java.security.cert.PKIXCertPathBuilderResult;
42 import java.security.cert.PKIXCertPathValidatorResult;
43 import java.security.cert.PKIXParameters;
44 import java.security.cert.X509CertSelector;
45 import java.security.cert.X509Certificate;
46 import java.time.LocalDateTime;
47 import java.time.ZoneId;
48 import java.util.Base64;
49 import java.util.Date;
50 import java.util.List;
51 
52 /**
53  * Check cert list is cert chain.
54  */
55 public class CertChainUtils {
56     private static final Logger LOGGER = LogManager.getLogger(CertUtils.class);
57 
CertChainUtils()58     private CertChainUtils() {
59     }
60 
getCertPath(List<X509Certificate> certificates, KeyStore trustStore, X500Principal issuer, BigInteger serial)61     private static CertPath getCertPath(List<X509Certificate> certificates, KeyStore trustStore, X500Principal issuer,
62                                         BigInteger serial) throws KeyStoreException, InvalidAlgorithmParameterException,
63             NoSuchAlgorithmException, CertPathBuilderException, CertificateException {
64         if (certificates.size() != 1 && (issuer != null || serial != null)) {
65             X509CertSelector targetCertSelector = new X509CertSelector();
66             targetCertSelector.setIssuer(issuer);
67             targetCertSelector.setSerialNumber(serial);
68             PKIXBuilderParameters params = new PKIXBuilderParameters(trustStore, targetCertSelector);
69             CertStore certStore = CertStore.getInstance("Collection",
70                     new CollectionCertStoreParameters(certificates));
71             params.addCertStore(certStore);
72             params.setDate(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
73             params.setRevocationEnabled(false);
74             CertPathBuilder certPathBuilder = CertPathBuilder.getInstance("PKIX");
75             PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) certPathBuilder.build(params);
76             return result.getCertPath();
77         } else {
78             CertificateFactory factory = CertificateFactory.getInstance("X.509");
79             return factory.generateCertPath(certificates);
80         }
81     }
82 
83 
84     /**
85      * Check cert list is cert chain.
86      *
87      * @param certificates cert list to be verified
88      * @param issuer       issuer
89      * @param serial       serial number
90      * @param root         root cert
91      */
verifyCertChain(List<X509Certificate> certificates, X500Principal issuer, BigInteger serial, X509Certificate root)92     public static void verifyCertChain(List<X509Certificate> certificates, X500Principal issuer, BigInteger serial,
93                                        X509Certificate root) {
94         try {
95             KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
96             trustStore.load(null, null);
97             trustStore.setCertificateEntry("root", root);
98             CertPath certPath = getCertPath(certificates, trustStore, issuer, serial);
99             PKIXParameters params = new PKIXParameters(trustStore);
100             params.setRevocationEnabled(false);
101             params.setDate(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
102             CertStore certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters());
103             params.addCertStore(certStore);
104             CertPathValidator validator = CertPathValidator.getInstance("PKIX");
105             CertPathValidatorResult validatorResult = validator.validate(certPath, params);
106             ValidateUtils.throwIfNotMatches(validatorResult instanceof PKIXCertPathValidatorResult,
107                     ERROR.VERIFY_ERROR, "Validator result not target type");
108             if (validatorResult instanceof PKIXCertPathValidatorResult) {
109                 PKIXCertPathValidatorResult pkixValidatorResult = (PKIXCertPathValidatorResult) validatorResult;
110                 ValidateUtils.throwIfNotMatches(params.getTrustAnchors().contains(pkixValidatorResult.getTrustAnchor()),
111                         ERROR.VERIFY_ERROR, "Anchor is not trusted: " + Base64.getEncoder().encodeToString(
112                                 pkixValidatorResult.getTrustAnchor().getTrustedCert().getEncoded()));
113             } else {
114                 CustomException.throwException(ERROR.VERIFY_ERROR, "Validator result not target type");
115             }
116         } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | IOException | CertificateException
117                 | KeyStoreException | CertPathBuilderException | CertPathValidatorException exception) {
118             LOGGER.debug(exception.getMessage(), exception);
119             CustomException.throwException(ERROR.VERIFY_ERROR, "Failed to verify signature: " + exception.getMessage());
120         }
121     }
122 }
123