Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f00cdf68 authored by Alex Klyubin's avatar Alex Klyubin Committed by Android Git Automerger
Browse files

am c6cc9d82: Merge "A way to obtain KeyStore operation handle from crypto primitives."

* commit 'c6cc9d82':
  A way to obtain KeyStore operation handle from crypto primitives.
parents 4e88ecf4 c6cc9d82
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -16,8 +16,12 @@

package android.security;

import java.lang.reflect.Method;
import java.security.Provider;

import javax.crypto.Cipher;
import javax.crypto.Mac;

/**
 * A provider focused on providing JCA interfaces for the Android KeyStore.
 *
@@ -71,4 +75,42 @@ public class AndroidKeyStoreProvider extends Provider {
        put("Cipher." + transformation, implClass);
        put("Cipher." + transformation + " SupportedKeyClasses", KeyStoreSecretKey.class.getName());
    }

    /**
     * Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto
     * primitive.
     *
     * <p>The following primitives are supported: {@link Cipher} and {@link Mac}.
     *
     * @return KeyStore operation handle or {@code null} if the provided primitive's KeyStore
     *         operation is not in progress.
     *
     * @throws IllegalArgumentException if the provided primitive is not supported or is not backed
     *         by AndroidKeyStore provider.
     */
    public static Long getKeyStoreOperationHandle(Object cryptoPrimitive) {
        if (cryptoPrimitive == null) {
            throw new NullPointerException();
        }
        if ((!(cryptoPrimitive instanceof Mac)) && (!(cryptoPrimitive instanceof Cipher))) {
            throw new IllegalArgumentException("Unsupported crypto primitive: " + cryptoPrimitive);
        }
        Object spi;
        // TODO: Replace this Reflection based codewith direct invocations once the libcore changes
        // are in.
        try {
            Method getSpiMethod = cryptoPrimitive.getClass().getDeclaredMethod("getSpi");
            getSpiMethod.setAccessible(true);
            spi = getSpiMethod.invoke(cryptoPrimitive);
        } catch (ReflectiveOperationException e) {
            throw new IllegalArgumentException(
                    "Unsupported crypto primitive: " + cryptoPrimitive, e);
        }
        if (!(spi instanceof KeyStoreCryptoOperation)) {
            throw new IllegalArgumentException(
                    "Crypto primitive not backed by Android KeyStore: " + cryptoPrimitive
                    + ", spi: " + spi);
        }
        return ((KeyStoreCryptoOperation) spi).getOperationHandle();
    }
}
+21 −1
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ import javax.crypto.spec.IvParameterSpec;
 *
 * @hide
 */
public abstract class KeyStoreCipherSpi extends CipherSpi {
public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCryptoOperation {

    public abstract static class AES extends KeyStoreCipherSpi {
        protected AES(@KeyStoreKeyConstraints.BlockModeEnum int blockMode,
@@ -129,6 +129,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
     * error conditions in between.
     */
    private IBinder mOperationToken;
    private Long mOperationHandle;
    private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;

    protected KeyStoreCipherSpi(
@@ -192,6 +193,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
            mOperationToken = null;
            mKeyStore.abort(operationToken);
        }
        mOperationHandle = null;
        mMainDataStreamer = null;
        mAdditionalEntropyForBegin = null;
    }
@@ -230,6 +232,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
            throw new CryptoOperationException("Keystore returned null operation token");
        }
        mOperationToken = opResult.token;
        mOperationHandle = opResult.operationHandle;
        loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
        mFirstOperationInitiated = true;
        mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
@@ -348,6 +351,23 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
        throw new UnsupportedOperationException();
    }

    @Override
    public void finalize() throws Throwable {
        try {
            IBinder operationToken = mOperationToken;
            if (operationToken != null) {
                mKeyStore.abort(operationToken);
            }
        } finally {
            super.finalize();
        }
    }

    @Override
    public Long getOperationHandle() {
        return mOperationHandle;
    }

    // The methods below may need to be overridden by subclasses that use algorithm-specific
    // parameters.

+31 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.security;

/**
 * Cryptographic operation backed by {@link KeyStore}.
 *
 * @hide
 */
public interface KeyStoreCryptoOperation {
    /**
     * Gets the KeyStore operation handle of this crypto operation.
     *
     * @return handle or {@code null} if the KeyStore operation is not in progress.
     */
    Long getOperationHandle();
}
+9 −2
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ import javax.crypto.MacSpi;
 *
 * @hide
 */
public abstract class KeyStoreHmacSpi extends MacSpi {
public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOperation {

    public static class HmacSHA256 extends KeyStoreHmacSpi {
        public HmacSHA256() {
@@ -50,6 +50,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
    // The fields below are reset by the engineReset operation.
    private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer;
    private IBinder mOperationToken;
    private Long mOperationHandle;

    protected KeyStoreHmacSpi(@KeyStoreKeyConstraints.DigestEnum int digest, int macSizeBytes) {
        mDigest = digest;
@@ -87,6 +88,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
            mOperationToken = null;
            mKeyStore.abort(operationToken);
        }
        mOperationHandle = null;
        mChunkedStreamer = null;

        KeymasterArguments keymasterArgs = new KeymasterArguments();
@@ -108,6 +110,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
        if (mOperationToken == null) {
            throw new CryptoOperationException("Keystore returned null operation token");
        }
        mOperationHandle = opResult.operationHandle;
        mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
                        mKeyStore, mOperationToken));
@@ -157,11 +160,15 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
        try {
            IBinder operationToken = mOperationToken;
            if (operationToken != null) {
                mOperationToken = null;
                mKeyStore.abort(operationToken);
            }
        } finally {
            super.finalize();
        }
    }

    @Override
    public Long getOperationHandle() {
        return mOperationHandle;
    }
}