Home | History | Annotate | Download | only in verity
      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 
     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 
     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 
     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 
     97     static PrivateKey loadPEMPrivateKey(byte[] pem) throws Exception {
     98         byte[] der = pemToDer(new String(pem));
     99         return loadDERPrivateKey(der);
    100     }
    101 
    102     static PrivateKey loadPEMPrivateKeyFromFile(String keyFname) throws Exception {
    103         return loadPEMPrivateKey(read(keyFname));
    104     }
    105 
    106     static PrivateKey loadDERPrivateKeyFromFile(String keyFname) throws Exception {
    107         return loadDERPrivateKey(read(keyFname));
    108     }
    109 
    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 
    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 
    123     static PublicKey loadPEMPublicKeyFromFile(String keyFname) throws Exception {
    124         return loadPEMPublicKey(read(keyFname));
    125     }
    126 
    127     static PublicKey loadDERPublicKeyFromFile(String keyFname) throws Exception {
    128         return loadDERPublicKey(read(keyFname));
    129     }
    130 
    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 
    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 
    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 }