1 /* 2 * Copyright (c) 2023-2023 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.codesigning.utils; 17 18 import org.bouncycastle.cert.X509CertificateHolder; 19 import org.bouncycastle.cms.CMSException; 20 import org.bouncycastle.cms.CMSProcessableByteArray; 21 import org.bouncycastle.cms.CMSSignedData; 22 import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; 23 import org.bouncycastle.jce.provider.BouncyCastleProvider; 24 import org.bouncycastle.operator.OperatorCreationException; 25 26 import java.security.Security; 27 import java.security.cert.CertificateException; 28 import java.util.Collection; 29 30 /** 31 * CMS utils class 32 * 33 * @since 2023/06/05 34 */ 35 public class CmsUtils { 36 static { 37 if (Security.getProvider("BC") == null) { Security.addProvider(new BouncyCastleProvider())38 Security.addProvider(new BouncyCastleProvider()); 39 } 40 } 41 42 /** 43 * Private constructor 44 */ CmsUtils()45 private CmsUtils() { 46 } 47 isCollectionValid(Collection<X509CertificateHolder> collection)48 private static void isCollectionValid(Collection<X509CertificateHolder> collection) 49 throws OperatorCreationException { 50 if (collection == null) { 51 throw new OperatorCreationException("No matched cert: " + collection); 52 } 53 if (collection.size() != 1) { 54 throw new OperatorCreationException( 55 "More than one matched certs, matched certs size: " + collection.size()); 56 } 57 } 58 59 @SuppressWarnings("unchecked") verifyCmsSignedData(CMSSignedData cmsSignedData)60 private static boolean verifyCmsSignedData(CMSSignedData cmsSignedData) throws CMSException { 61 return cmsSignedData.verifySignatures(signId -> { 62 Collection<X509CertificateHolder> collection = cmsSignedData.getCertificates().getMatches(signId); 63 isCollectionValid(collection); 64 X509CertificateHolder cert = collection.iterator().next(); 65 try { 66 return new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert); 67 } catch (CertificateException e) { 68 throw new OperatorCreationException("Verify BC signatures failed: " + e.getMessage(), e); 69 } 70 }); 71 } 72 73 /** 74 * Verify signed data using an unsigned data digest 75 * 76 * @param unsignedDataDigest unsigned data digest 77 * @param signedData signed data 78 * @return true if verify success 79 * @throws CMSException if error 80 */ verifySignDataWithUnsignedDataDigest(byte[] unsignedDataDigest, byte[] signedData)81 public static boolean verifySignDataWithUnsignedDataDigest(byte[] unsignedDataDigest, byte[] signedData) 82 throws CMSException { 83 CMSSignedData cmsSignedData = new CMSSignedData(new CMSProcessableByteArray(unsignedDataDigest), signedData); 84 return verifyCmsSignedData(cmsSignedData); 85 } 86 } 87