1 // Copyright 2014 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.net; 6 7 import org.chromium.base.Log; 8 import org.chromium.base.annotations.CalledByNative; 9 import org.chromium.base.annotations.JNINamespace; 10 11 import java.security.InvalidKeyException; 12 import java.security.NoSuchAlgorithmException; 13 import java.security.PrivateKey; 14 import java.security.Signature; 15 16 import javax.crypto.Cipher; 17 import javax.crypto.NoSuchPaddingException; 18 19 /** 20 * Specifies all the dependencies from the native OpenSSL engine on an Android KeyStore. 21 */ 22 @JNINamespace("net::android") 23 public class AndroidKeyStore { 24 private static final String TAG = "AndroidKeyStore"; 25 26 @CalledByNative getPrivateKeyClassName(PrivateKey privateKey)27 private static String getPrivateKeyClassName(PrivateKey privateKey) { 28 return privateKey.getClass().getName(); 29 } 30 31 /** 32 * Check if a given PrivateKey object supports a signature algorithm. 33 * 34 * @param privateKey The PrivateKey handle. 35 * @param algorithm The signature algorithm to use. 36 * @return whether the algorithm is supported. 37 */ 38 @CalledByNative privateKeySupportsSignature(PrivateKey privateKey, String algorithm)39 private static boolean privateKeySupportsSignature(PrivateKey privateKey, String algorithm) { 40 try { 41 Signature signature = Signature.getInstance(algorithm); 42 signature.initSign(privateKey); 43 } catch (NoSuchAlgorithmException | InvalidKeyException e) { 44 return false; 45 } catch (Exception e) { 46 Log.e(TAG, "Exception while checking support for " + algorithm + ": " + e); 47 return false; 48 } 49 return true; 50 } 51 52 /** 53 * Check if a given PrivateKey object supports an encryption algorithm. 54 * 55 * @param privateKey The PrivateKey handle. 56 * @param algorithm The signature algorithm to use. 57 * @return whether the algorithm is supported. 58 */ 59 @CalledByNative privateKeySupportsCipher(PrivateKey privateKey, String algorithm)60 private static boolean privateKeySupportsCipher(PrivateKey privateKey, String algorithm) { 61 try { 62 Cipher cipher = Cipher.getInstance(algorithm); 63 cipher.init(Cipher.ENCRYPT_MODE, privateKey); 64 } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) { 65 return false; 66 } catch (Exception e) { 67 Log.e(TAG, "Exception while checking support for " + algorithm + ": " + e); 68 return false; 69 } 70 return true; 71 } 72 73 /** 74 * Sign a given message with a given PrivateKey object. 75 * 76 * @param privateKey The PrivateKey handle. 77 * @param algorithm The signature algorithm to use. 78 * @param message The message to sign. 79 * @return signature as a byte buffer. 80 */ 81 @CalledByNative signWithPrivateKey( PrivateKey privateKey, String algorithm, byte[] message)82 private static byte[] signWithPrivateKey( 83 PrivateKey privateKey, String algorithm, byte[] message) { 84 // Hint: Algorithm names come from: 85 // http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html 86 Signature signature = null; 87 try { 88 signature = Signature.getInstance(algorithm); 89 } catch (NoSuchAlgorithmException e) { 90 Log.e(TAG, "Signature algorithm " + algorithm + " not supported: " + e); 91 return null; 92 } 93 94 try { 95 signature.initSign(privateKey); 96 signature.update(message); 97 return signature.sign(); 98 } catch (Exception e) { 99 Log.e(TAG, 100 "Exception while signing message with " + algorithm + " and " 101 + privateKey.getAlgorithm() + " private key (" 102 + privateKey.getClass().getName() + "): " + e); 103 return null; 104 } 105 } 106 107 /** 108 * Encrypts a given input with a given PrivateKey object. 109 * 110 * @param privateKey The PrivateKey handle. 111 * @param algorithm The cipher to use. 112 * @param input The input to encrypt. 113 * @return ciphertext as a byte buffer. 114 */ 115 @CalledByNative encryptWithPrivateKey( PrivateKey privateKey, String algorithm, byte[] message)116 private static byte[] encryptWithPrivateKey( 117 PrivateKey privateKey, String algorithm, byte[] message) { 118 Cipher cipher = null; 119 try { 120 cipher = Cipher.getInstance(algorithm); 121 } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { 122 Log.e(TAG, "Cipher " + algorithm + " not supported: " + e); 123 return null; 124 } 125 126 try { 127 cipher.init(Cipher.ENCRYPT_MODE, privateKey); 128 return cipher.doFinal(message); 129 } catch (Exception e) { 130 Log.e(TAG, 131 "Exception while encrypting input with " + algorithm + " and " 132 + privateKey.getAlgorithm() + " private key (" 133 + privateKey.getClass().getName() + "): " + e); 134 return null; 135 } 136 } 137 } 138