blob: c1b155d025cd3075ba1321fc03c208cb657deddf [file] [log] [blame]
// 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;
}
}
}