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