| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.net; |
| |
| import org.chromium.base.Log; |
| import org.chromium.base.annotations.CalledByNative; |
| import org.chromium.base.annotations.JNINamespace; |
| |
| import java.security.InvalidKeyException; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.PrivateKey; |
| import java.security.Signature; |
| |
| import javax.crypto.Cipher; |
| import javax.crypto.NoSuchPaddingException; |
| |
| /** |
| * Specifies all the dependencies from the native OpenSSL engine on an Android KeyStore. |
| */ |
| @JNINamespace("net::android") |
| public class AndroidKeyStore { |
| private static final String TAG = "AndroidKeyStore"; |
| |
| @CalledByNative |
| private static String getPrivateKeyClassName(PrivateKey privateKey) { |
| return privateKey.getClass().getName(); |
| } |
| |
| /** |
| * Check if a given PrivateKey object supports a signature algorithm. |
| * |
| * @param privateKey The PrivateKey handle. |
| * @param algorithm The signature algorithm to use. |
| * @return whether the algorithm is supported. |
| */ |
| @CalledByNative |
| private static boolean privateKeySupportsSignature(PrivateKey privateKey, String algorithm) { |
| try { |
| Signature signature = Signature.getInstance(algorithm); |
| signature.initSign(privateKey); |
| } catch (NoSuchAlgorithmException | InvalidKeyException e) { |
| return false; |
| } catch (Exception e) { |
| Log.e(TAG, "Exception while checking support for " + algorithm + ": " + e); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Check if a given PrivateKey object supports an encryption algorithm. |
| * |
| * @param privateKey The PrivateKey handle. |
| * @param algorithm The signature algorithm to use. |
| * @return whether the algorithm is supported. |
| */ |
| @CalledByNative |
| private static boolean privateKeySupportsCipher(PrivateKey privateKey, String algorithm) { |
| try { |
| Cipher cipher = Cipher.getInstance(algorithm); |
| cipher.init(Cipher.ENCRYPT_MODE, privateKey); |
| } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) { |
| return false; |
| } catch (Exception e) { |
| Log.e(TAG, "Exception while checking support for " + algorithm + ": " + e); |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Sign a given message with a given PrivateKey object. |
| * |
| * @param privateKey The PrivateKey handle. |
| * @param algorithm The signature algorithm to use. |
| * @param message The message to sign. |
| * @return signature as a byte buffer. |
| * |
| * Note: NONEwithRSA is not implemented in Android < 4.2. See |
| * getOpenSSLHandleForPrivateKey() below for a work-around. |
| */ |
| @CalledByNative |
| private static byte[] signWithPrivateKey( |
| PrivateKey privateKey, String algorithm, byte[] message) { |
| // Hint: Algorithm names come from: |
| // http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html |
| Signature signature = null; |
| try { |
| signature = Signature.getInstance(algorithm); |
| } catch (NoSuchAlgorithmException e) { |
| Log.e(TAG, "Signature algorithm " + algorithm + " not supported: " + e); |
| return null; |
| } |
| |
| try { |
| signature.initSign(privateKey); |
| signature.update(message); |
| return signature.sign(); |
| } catch (Exception e) { |
| Log.e(TAG, |
| "Exception while signing message with " + algorithm + " and " |
| + privateKey.getAlgorithm() + " private key (" |
| + privateKey.getClass().getName() + "): " + e); |
| return null; |
| } |
| } |
| |
| /** |
| * Encrypts a given input with a given PrivateKey object. |
| * |
| * @param privateKey The PrivateKey handle. |
| * @param algorithm The cipher to use. |
| * @param input The input to encrypt. |
| * @return ciphertext as a byte buffer. |
| * |
| * Note: NONEwithRSA is not implemented in Android < 4.2. See |
| * getOpenSSLHandleForPrivateKey() below for a work-around. |
| */ |
| @CalledByNative |
| private static byte[] encryptWithPrivateKey( |
| PrivateKey privateKey, String algorithm, byte[] message) { |
| Cipher cipher = null; |
| try { |
| cipher = Cipher.getInstance(algorithm); |
| } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { |
| Log.e(TAG, "Cipher " + algorithm + " not supported: " + e); |
| return null; |
| } |
| |
| try { |
| cipher.init(Cipher.ENCRYPT_MODE, privateKey); |
| return cipher.doFinal(message); |
| } catch (Exception e) { |
| Log.e(TAG, |
| "Exception while encrypting input with " + algorithm + " and " |
| + privateKey.getAlgorithm() + " private key (" |
| + privateKey.getClass().getName() + "): " + e); |
| return null; |
| } |
| } |
| } |