1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package libcore.util; 18 19 import sun.security.pkcs.PKCS7; 20 import sun.security.pkcs.SignerInfo; 21 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.security.NoSuchAlgorithmException; 25 import java.security.PublicKey; 26 import java.security.SignatureException; 27 import java.security.cert.X509Certificate; 28 import java.util.Set; 29 30 public class RecoverySystem { RecoverySystem()31 private RecoverySystem() { 32 } 33 34 /** 35 * Verifies that the signature computed from {@code contentStream} matches 36 * that specified in {@code blockStream}. The public key of the certificates specified 37 * in the PCKS7 block must match 38 */ verify(InputStream blockStream, InputStream contentStream, Set<X509Certificate> trustedCerts)39 public static void verify(InputStream blockStream, InputStream contentStream, 40 Set<X509Certificate> trustedCerts) 41 throws IOException, SignatureException, NoSuchAlgorithmException { 42 PKCS7 block = new PKCS7(blockStream); 43 44 // Take the first certificate from the signature (packages 45 // should contain only one). 46 X509Certificate[] certificates = block.getCertificates(); 47 if (certificates == null || certificates.length == 0) { 48 throw new SignatureException("signature contains no certificates"); 49 } 50 X509Certificate cert = certificates[0]; 51 PublicKey signatureKey = cert.getPublicKey(); 52 53 SignerInfo[] signerInfos = block.getSignerInfos(); 54 if (signerInfos == null || signerInfos.length == 0) { 55 throw new SignatureException("signature contains no signedData"); 56 } 57 SignerInfo signerInfo = signerInfos[0]; 58 59 boolean verified = false; 60 for (X509Certificate c : trustedCerts) { 61 if (c.getPublicKey().equals(signatureKey)) { 62 verified = true; 63 break; 64 } 65 } 66 67 if (!verified) { 68 throw new SignatureException("signature doesn't match any trusted key"); 69 } 70 71 SignerInfo verifyResult = block.verify(signerInfo, contentStream); 72 if (verifyResult == null) { 73 throw new SignatureException("signature digest verification failed"); 74 } 75 } 76 } 77