• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 com.android.verity;
18 
19 import java.lang.reflect.Constructor;
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.security.PrivateKey;
25 import java.security.PublicKey;
26 import java.security.KeyFactory;
27 import java.security.Provider;
28 import java.security.Security;
29 import java.security.Signature;
30 import java.security.spec.X509EncodedKeySpec;
31 import java.security.spec.PKCS8EncodedKeySpec;
32 
33 import org.bouncycastle.util.encoders.Base64;
34 
35 public class Utils {
36 
loadProviderIfNecessary(String providerClassName)37     private static void loadProviderIfNecessary(String providerClassName) {
38         if (providerClassName == null) {
39             return;
40         }
41 
42         final Class<?> klass;
43         try {
44             final ClassLoader sysLoader = ClassLoader.getSystemClassLoader();
45             if (sysLoader != null) {
46                 klass = sysLoader.loadClass(providerClassName);
47             } else {
48                 klass = Class.forName(providerClassName);
49             }
50         } catch (ClassNotFoundException e) {
51             e.printStackTrace();
52             System.exit(1);
53             return;
54         }
55 
56         Constructor<?> constructor = null;
57         for (Constructor<?> c : klass.getConstructors()) {
58             if (c.getParameterTypes().length == 0) {
59                 constructor = c;
60                 break;
61             }
62         }
63         if (constructor == null) {
64             System.err.println("No zero-arg constructor found for " + providerClassName);
65             System.exit(1);
66             return;
67         }
68 
69         final Object o;
70         try {
71             o = constructor.newInstance();
72         } catch (Exception e) {
73             e.printStackTrace();
74             System.exit(1);
75             return;
76         }
77         if (!(o instanceof Provider)) {
78             System.err.println("Not a Provider class: " + providerClassName);
79             System.exit(1);
80         }
81 
82         Security.insertProviderAt((Provider) o, 1);
83     }
84 
pemToDer(String pem)85     static byte[] pemToDer(String pem) throws Exception {
86         pem = pem.replaceAll("^-.*", "");
87         String base64_der = pem.replaceAll("-.*$", "");
88         return Base64.decode(base64_der);
89     }
90 
loadDERPrivateKey(byte[] der)91     static PrivateKey loadDERPrivateKey(byte[] der) throws Exception {
92         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(der);
93         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
94         return (PrivateKey) keyFactory.generatePrivate(keySpec);
95     }
96 
loadPEMPrivateKey(byte[] pem)97     static PrivateKey loadPEMPrivateKey(byte[] pem) throws Exception {
98         byte[] der = pemToDer(new String(pem));
99         return loadDERPrivateKey(der);
100     }
101 
loadPEMPrivateKeyFromFile(String keyFname)102     static PrivateKey loadPEMPrivateKeyFromFile(String keyFname) throws Exception {
103         return loadPEMPrivateKey(read(keyFname));
104     }
105 
loadDERPrivateKeyFromFile(String keyFname)106     static PrivateKey loadDERPrivateKeyFromFile(String keyFname) throws Exception {
107         return loadDERPrivateKey(read(keyFname));
108     }
109 
loadDERPublicKey(byte[] der)110     static PublicKey loadDERPublicKey(byte[] der) throws Exception {
111         X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(der);
112         KeyFactory factory = KeyFactory.getInstance("RSA");
113         return factory.generatePublic(publicKeySpec);
114     }
115 
loadPEMPublicKey(byte[] pem)116     static PublicKey loadPEMPublicKey(byte[] pem) throws Exception {
117         byte[] der = pemToDer(new String(pem));
118         X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(der);
119         KeyFactory factory = KeyFactory.getInstance("RSA");
120         return factory.generatePublic(publicKeySpec);
121     }
122 
loadPEMPublicKeyFromFile(String keyFname)123     static PublicKey loadPEMPublicKeyFromFile(String keyFname) throws Exception {
124         return loadPEMPublicKey(read(keyFname));
125     }
126 
loadDERPublicKeyFromFile(String keyFname)127     static PublicKey loadDERPublicKeyFromFile(String keyFname) throws Exception {
128         return loadDERPublicKey(read(keyFname));
129     }
130 
sign(PrivateKey privateKey, byte[] input)131     static byte[] sign(PrivateKey privateKey, byte[] input) throws Exception {
132         Signature signer = Signature.getInstance("SHA1withRSA");
133         signer.initSign(privateKey);
134         signer.update(input);
135         return signer.sign();
136     }
137 
read(String fname)138     static byte[] read(String fname) throws Exception {
139         long offset = 0;
140         File f = new File(fname);
141         long length = f.length();
142         byte[] image = new byte[(int)length];
143         FileInputStream fis = new FileInputStream(f);
144         while (offset < length) {
145             offset += fis.read(image, (int)offset, (int)(length - offset));
146         }
147         fis.close();
148         return image;
149     }
150 
write(byte[] data, String fname)151     static void write(byte[] data, String fname) throws Exception{
152         FileOutputStream out = new FileOutputStream(fname);
153         out.write(data);
154         out.close();
155     }
156 }