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