Search in sources :

Example 36 with ProviderException

use of java.security.ProviderException in project android_frameworks_base by AOSPA.

the class KeyStoreCryptoOperationChunkedStreamer method flush.

public byte[] flush() throws KeyStoreException {
    if (mBufferedLength <= 0) {
        return EmptyArray.BYTE;
    }
    // Keep invoking the update operation with remaining buffered data until either all of the
    // buffered data is consumed or until update fails to consume anything.
    ByteArrayOutputStream bufferedOutput = null;
    while (mBufferedLength > 0) {
        byte[] chunk = ArrayUtils.subarray(mBuffered, mBufferedOffset, mBufferedLength);
        OperationResult opResult = mKeyStoreStream.update(chunk);
        if (opResult == null) {
            throw new KeyStoreConnectException();
        } else if (opResult.resultCode != KeyStore.NO_ERROR) {
            throw KeyStore.getKeyStoreException(opResult.resultCode);
        }
        if (opResult.inputConsumed <= 0) {
            // Nothing was consumed. Break out of the loop to avoid an infinite loop.
            break;
        }
        if (opResult.inputConsumed >= chunk.length) {
            // All of the input was consumed
            mBuffered = EmptyArray.BYTE;
            mBufferedOffset = 0;
            mBufferedLength = 0;
        } else {
            // Some of the input was not consumed
            mBuffered = chunk;
            mBufferedOffset = opResult.inputConsumed;
            mBufferedLength = chunk.length - opResult.inputConsumed;
        }
        if (opResult.inputConsumed > chunk.length) {
            throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, "Keystore consumed more input than provided. Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed);
        }
        if ((opResult.output != null) && (opResult.output.length > 0)) {
            // Some output was produced by this update operation
            if (bufferedOutput == null) {
                // No output buffered yet.
                if (mBufferedLength == 0) {
                    // No more output will be produced by this flush operation
                    mProducedOutputSizeBytes += opResult.output.length;
                    return opResult.output;
                } else {
                    // More output might be produced by this flush operation -- buffer output.
                    bufferedOutput = new ByteArrayOutputStream();
                }
            }
            // Buffer the output from this update operation
            try {
                bufferedOutput.write(opResult.output);
            } catch (IOException e) {
                throw new ProviderException("Failed to buffer output", e);
            }
        }
    }
    if (mBufferedLength > 0) {
        throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH, "Keystore failed to consume last " + ((mBufferedLength != 1) ? (mBufferedLength + " bytes") : "byte") + " of input");
    }
    byte[] result = (bufferedOutput != null) ? bufferedOutput.toByteArray() : EmptyArray.BYTE;
    mProducedOutputSizeBytes += result.length;
    return result;
}
Also used : ProviderException(java.security.ProviderException) OperationResult(android.security.keymaster.OperationResult) ByteArrayOutputStream(java.io.ByteArrayOutputStream) KeyStoreException(android.security.KeyStoreException) IOException(java.io.IOException)

Example 37 with ProviderException

use of java.security.ProviderException in project android_frameworks_base by AOSPA.

the class KeymasterUtils method addUserAuthArgs.

/**
     * Adds keymaster arguments to express the key's authorization policy supported by user
     * authentication.
     *
     * @param userAuthenticationRequired whether user authentication is required to authorize the
     *        use of the key.
     * @param userAuthenticationValidityDurationSeconds duration of time (seconds) for which user
     *        authentication is valid as authorization for using the key or {@code -1} if every
     *        use of the key needs authorization.
     *
     * @throws IllegalStateException if user authentication is required but the system is in a wrong
     *         state (e.g., secure lock screen not set up) for generating or importing keys that
     *         require user authentication.
     */
public static void addUserAuthArgs(KeymasterArguments args, boolean userAuthenticationRequired, int userAuthenticationValidityDurationSeconds, boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment) {
    if (!userAuthenticationRequired) {
        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
        return;
    }
    if (userAuthenticationValidityDurationSeconds == -1) {
        // Every use of this key needs to be authorized by the user. This currently means
        // fingerprint-only auth.
        FingerprintManager fingerprintManager = KeyStore.getApplicationContext().getSystemService(FingerprintManager.class);
        // TODO: Restore USE_FINGERPRINT permission check in
        // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
        long fingerprintOnlySid = (fingerprintManager != null) ? fingerprintManager.getAuthenticatorId() : 0;
        if (fingerprintOnlySid == 0) {
            throw new IllegalStateException("At least one fingerprint must be enrolled to create keys requiring user" + " authentication for every use");
        }
        long sid;
        if (invalidatedByBiometricEnrollment) {
            // The fingerprint-only SID will change on fingerprint enrollment or removal of all,
            // enrolled fingerprints, invalidating the key.
            sid = fingerprintOnlySid;
        } else {
            // The root SID will *not* change on fingerprint enrollment, or removal of all
            // enrolled fingerprints, allowing the key to remain valid.
            sid = getRootSid();
        }
        args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid));
        args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
        if (userAuthenticationValidWhileOnBody) {
            throw new ProviderException("Key validity extension while device is on-body is not " + "supported for keys requiring fingerprint authentication");
        }
    } else {
        // The key is authorized for use for the specified amount of time after the user has
        // authenticated. Whatever unlocks the secure lock screen should authorize this key.
        long rootSid = getRootSid();
        args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(rootSid));
        args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
        args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, userAuthenticationValidityDurationSeconds);
        if (userAuthenticationValidWhileOnBody) {
            args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
        }
    }
}
Also used : ProviderException(java.security.ProviderException) FingerprintManager(android.hardware.fingerprint.FingerprintManager)

Example 38 with ProviderException

use of java.security.ProviderException in project android_frameworks_base by AOSPA.

the class AndroidKeyStoreKeyGeneratorSpi method engineGenerateKey.

@Override
protected SecretKey engineGenerateKey() {
    KeyGenParameterSpec spec = mSpec;
    if (spec == null) {
        throw new IllegalStateException("Not initialized");
    }
    KeymasterArguments args = new KeymasterArguments();
    args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
    args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
    args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
    args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
    args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
    args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
    if (spec.isUseSecureProcessor())
        args.addBoolean(KeymasterDefs.KM_TAG_USE_SECURE_PROCESSOR);
    KeymasterUtils.addUserAuthArgs(args, spec.isUserAuthenticationRequired(), spec.getUserAuthenticationValidityDurationSeconds(), spec.isUserAuthenticationValidWhileOnBody(), spec.isInvalidatedByBiometricEnrollment());
    KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(args, mKeymasterAlgorithm, mKeymasterBlockModes, mKeymasterDigests);
    args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
    args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, spec.getKeyValidityForOriginationEnd());
    args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, spec.getKeyValidityForConsumptionEnd());
    if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0) && (!spec.isRandomizedEncryptionRequired())) {
        // Permit caller-provided IV when encrypting with this key
        args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
    }
    byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(mRng, (mKeySizeBits + 7) / 8);
    int flags = 0;
    String keyAliasInKeystore = Credentials.USER_SECRET_KEY + spec.getKeystoreAlias();
    KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
    boolean success = false;
    try {
        Credentials.deleteAllTypesForAlias(mKeyStore, spec.getKeystoreAlias(), spec.getUid());
        int errorCode = mKeyStore.generateKey(keyAliasInKeystore, args, additionalEntropy, spec.getUid(), flags, resultingKeyCharacteristics);
        if (errorCode != KeyStore.NO_ERROR) {
            throw new ProviderException("Keystore operation failed", KeyStore.getKeyStoreException(errorCode));
        }
        @KeyProperties.KeyAlgorithmEnum String keyAlgorithmJCA;
        try {
            keyAlgorithmJCA = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(mKeymasterAlgorithm, mKeymasterDigest);
        } catch (IllegalArgumentException e) {
            throw new ProviderException("Failed to obtain JCA secret key algorithm name", e);
        }
        SecretKey result = new AndroidKeyStoreSecretKey(keyAliasInKeystore, spec.getUid(), keyAlgorithmJCA);
        success = true;
        return result;
    } finally {
        if (!success) {
            Credentials.deleteAllTypesForAlias(mKeyStore, spec.getKeystoreAlias(), spec.getUid());
        }
    }
}
Also used : KeymasterArguments(android.security.keymaster.KeymasterArguments) KeyGenParameterSpec(android.security.keystore.KeyGenParameterSpec) ProviderException(java.security.ProviderException) SecretKey(javax.crypto.SecretKey) KeyCharacteristics(android.security.keymaster.KeyCharacteristics)

Example 39 with ProviderException

use of java.security.ProviderException in project android_frameworks_base by AOSPA.

the class AndroidKeyStoreKeyPairGeneratorSpi method generateSelfSignedCertificateWithFakeSignature.

@SuppressWarnings("deprecation")
private X509Certificate generateSelfSignedCertificateWithFakeSignature(PublicKey publicKey) throws IOException, CertificateParsingException {
    V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator();
    ASN1ObjectIdentifier sigAlgOid;
    AlgorithmIdentifier sigAlgId;
    byte[] signature;
    switch(mKeymasterAlgorithm) {
        case KeymasterDefs.KM_ALGORITHM_EC:
            sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256;
            sigAlgId = new AlgorithmIdentifier(sigAlgOid);
            ASN1EncodableVector v = new ASN1EncodableVector();
            v.add(new DERInteger(0));
            v.add(new DERInteger(0));
            signature = new DERSequence().getEncoded();
            break;
        case KeymasterDefs.KM_ALGORITHM_RSA:
            sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption;
            sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE);
            signature = new byte[1];
            break;
        default:
            throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm);
    }
    try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) {
        tbsGenerator.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject()));
    }
    tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber()));
    X509Principal subject = new X509Principal(mSpec.getCertificateSubject().getEncoded());
    tbsGenerator.setSubject(subject);
    tbsGenerator.setIssuer(subject);
    tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore()));
    tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter()));
    tbsGenerator.setSignature(sigAlgId);
    TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate();
    ASN1EncodableVector result = new ASN1EncodableVector();
    result.add(tbsCertificate);
    result.add(sigAlgId);
    result.add(new DERBitString(signature));
    return new X509CertificateObject(Certificate.getInstance(new DERSequence(result)));
}
Also used : ASN1InputStream(com.android.org.bouncycastle.asn1.ASN1InputStream) ProviderException(java.security.ProviderException) Time(com.android.org.bouncycastle.asn1.x509.Time) DERBitString(com.android.org.bouncycastle.asn1.DERBitString) ASN1Integer(com.android.org.bouncycastle.asn1.ASN1Integer) AlgorithmIdentifier(com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier) DERInteger(com.android.org.bouncycastle.asn1.DERInteger) DERSequence(com.android.org.bouncycastle.asn1.DERSequence) X509CertificateObject(com.android.org.bouncycastle.jce.provider.X509CertificateObject) X509Principal(com.android.org.bouncycastle.jce.X509Principal) ASN1EncodableVector(com.android.org.bouncycastle.asn1.ASN1EncodableVector) V3TBSCertificateGenerator(com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator) TBSCertificate(com.android.org.bouncycastle.asn1.x509.TBSCertificate) ASN1ObjectIdentifier(com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier)

Example 40 with ProviderException

use of java.security.ProviderException in project android_frameworks_base by AOSPA.

the class AndroidKeyStoreKeyPairGeneratorSpi method initialize.

@SuppressWarnings("deprecation")
@Override
public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException {
    resetAll();
    boolean success = false;
    try {
        if (params == null) {
            throw new InvalidAlgorithmParameterException("Must supply params of type " + KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName());
        }
        KeyGenParameterSpec spec;
        boolean encryptionAtRestRequired = false;
        int keymasterAlgorithm = mOriginalKeymasterAlgorithm;
        if (params instanceof KeyGenParameterSpec) {
            spec = (KeyGenParameterSpec) params;
        } else if (params instanceof KeyPairGeneratorSpec) {
            // Legacy/deprecated spec
            KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params;
            try {
                KeyGenParameterSpec.Builder specBuilder;
                String specKeyAlgorithm = legacySpec.getKeyType();
                if (specKeyAlgorithm != null) {
                    // Spec overrides the generator's default key algorithm
                    try {
                        keymasterAlgorithm = KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(specKeyAlgorithm);
                    } catch (IllegalArgumentException e) {
                        throw new InvalidAlgorithmParameterException("Invalid key type in parameters", e);
                    }
                }
                switch(keymasterAlgorithm) {
                    case KeymasterDefs.KM_ALGORITHM_EC:
                        specBuilder = new KeyGenParameterSpec.Builder(legacySpec.getKeystoreAlias(), KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY);
                        // Authorized to be used with any digest (including no digest).
                        // MD5 was never offered for Android Keystore for ECDSA.
                        specBuilder.setDigests(KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA224, KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512);
                        break;
                    case KeymasterDefs.KM_ALGORITHM_RSA:
                        specBuilder = new KeyGenParameterSpec.Builder(legacySpec.getKeystoreAlias(), KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY);
                        // Authorized to be used with any digest (including no digest).
                        specBuilder.setDigests(KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_MD5, KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA224, KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512);
                        // Authorized to be used with any encryption and signature padding
                        // schemes (including no padding).
                        specBuilder.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE, KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1, KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
                        specBuilder.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1, KeyProperties.SIGNATURE_PADDING_RSA_PSS);
                        // Disable randomized encryption requirement to support encryption
                        // padding NONE above.
                        specBuilder.setRandomizedEncryptionRequired(false);
                        break;
                    default:
                        throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
                }
                if (legacySpec.getKeySize() != -1) {
                    specBuilder.setKeySize(legacySpec.getKeySize());
                }
                if (legacySpec.getAlgorithmParameterSpec() != null) {
                    specBuilder.setAlgorithmParameterSpec(legacySpec.getAlgorithmParameterSpec());
                }
                specBuilder.setCertificateSubject(legacySpec.getSubjectDN());
                specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber());
                specBuilder.setCertificateNotBefore(legacySpec.getStartDate());
                specBuilder.setCertificateNotAfter(legacySpec.getEndDate());
                encryptionAtRestRequired = legacySpec.isEncryptionRequired();
                specBuilder.setUserAuthenticationRequired(false);
                spec = specBuilder.build();
            } catch (NullPointerException | IllegalArgumentException e) {
                throw new InvalidAlgorithmParameterException(e);
            }
        } else {
            throw new InvalidAlgorithmParameterException("Unsupported params class: " + params.getClass().getName() + ". Supported: " + KeyGenParameterSpec.class.getName() + ", " + KeyPairGeneratorSpec.class.getName());
        }
        mEntryAlias = spec.getKeystoreAlias();
        mEntryUid = spec.getUid();
        mSpec = spec;
        mKeymasterAlgorithm = keymasterAlgorithm;
        mEncryptionAtRestRequired = encryptionAtRestRequired;
        mKeySizeBits = spec.getKeySize();
        initAlgorithmSpecificParameters();
        if (mKeySizeBits == -1) {
            mKeySizeBits = getDefaultKeySize(keymasterAlgorithm);
        }
        checkValidKeySize(keymasterAlgorithm, mKeySizeBits);
        if (spec.isUseSecureProcessor()) {
            checkSecureProcessorValidKeySize(keymasterAlgorithm, mKeySizeBits);
        }
        if (spec.getKeystoreAlias() == null) {
            throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
        }
        String jcaKeyAlgorithm;
        try {
            jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(keymasterAlgorithm);
            mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes());
            mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes());
            mKeymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster(spec.getEncryptionPaddings());
            if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0) && (spec.isRandomizedEncryptionRequired())) {
                for (int keymasterPadding : mKeymasterEncryptionPaddings) {
                    if (!KeymasterUtils.isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(keymasterPadding)) {
                        throw new InvalidAlgorithmParameterException("Randomized encryption (IND-CPA) required but may be violated" + " by padding scheme: " + KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding) + ". See " + KeyGenParameterSpec.class.getName() + " documentation.");
                    }
                }
            }
            mKeymasterSignaturePaddings = KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings());
            if (spec.isDigestsSpecified()) {
                mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
            } else {
                mKeymasterDigests = EmptyArray.INT;
            }
            // Check that user authentication related parameters are acceptable. This method
            // will throw an IllegalStateException if there are issues (e.g., secure lock screen
            // not set up).
            KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), mSpec.isUserAuthenticationRequired(), mSpec.getUserAuthenticationValidityDurationSeconds(), mSpec.isUserAuthenticationValidWhileOnBody(), mSpec.isInvalidatedByBiometricEnrollment());
        } catch (IllegalArgumentException | IllegalStateException e) {
            throw new InvalidAlgorithmParameterException(e);
        }
        mJcaKeyAlgorithm = jcaKeyAlgorithm;
        mRng = random;
        mKeyStore = KeyStore.getInstance();
        success = true;
    } finally {
        if (!success) {
            resetAll();
        }
    }
}
Also used : KeyPairGeneratorSpec(android.security.KeyPairGeneratorSpec) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) KeymasterArguments(android.security.keymaster.KeymasterArguments) RSAKeyGenParameterSpec(java.security.spec.RSAKeyGenParameterSpec) ProviderException(java.security.ProviderException) DERBitString(com.android.org.bouncycastle.asn1.DERBitString)

Aggregations

ProviderException (java.security.ProviderException)128 KeymasterArguments (android.security.keymaster.KeymasterArguments)30 InvalidKeyException (java.security.InvalidKeyException)26 OperationResult (android.security.keymaster.OperationResult)25 KeyStoreException (android.security.KeyStoreException)20 KeyCharacteristics (android.security.keymaster.KeyCharacteristics)20 DERBitString (com.android.org.bouncycastle.asn1.DERBitString)15 InvalidAlgorithmParameterException (java.security.InvalidAlgorithmParameterException)15 BigInteger (java.math.BigInteger)13 IOException (java.io.IOException)12 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)12 ASN1Integer (com.android.org.bouncycastle.asn1.ASN1Integer)10 DERInteger (com.android.org.bouncycastle.asn1.DERInteger)10 ByteArrayOutputStream (java.io.ByteArrayOutputStream)10 RSAKeyGenParameterSpec (java.security.spec.RSAKeyGenParameterSpec)10 GeneralSecurityException (java.security.GeneralSecurityException)6 KeyStoreException (java.security.KeyStoreException)6 NoSuchProviderException (java.security.NoSuchProviderException)6 KeymasterCertificateChain (android.security.keymaster.KeymasterCertificateChain)5 KeyProtection (android.security.keystore.KeyProtection)5