- conceal-master
- benchmarks
- src
- com
- facebook
- crypto
- benchmarks
- BenchmarkNativeCryptoLibrary.java
- CipherReadBenchmark.java
- CipherWriteBenchmark.java
- MacBenchmark.java
- cipher
- AESCipher.java
- BaseCipher.java
- BouncyCastleCCMCipher.java
- BouncyCastleGCMCipher.java
- NativeGCMCipherHelper.java
- mac
- BaseMac.java
- HMAC.java
- NativeMacHelper.java
- streams
- MacLayeredInputStream.java
- MacLayeredOutputStream.java
- instrumentTest
- crypto
- src
- com
- facebook
- crypto
- BouncyCastleHelper.java
- Cipher128BitsTest.java
- Cipher256BitsTest.java
- CryptoSerializerHelper.java
- CryptoTestUtils.java
- EntityFactoryTest.java
- FakeKeyChain.java
- FbInstrumentationTestRunner.java
- NativeGCMCipherInputStreamTest.java
- NativeGCMCipherOutputStreamTest.java
- NativeMacLayeredInputStreamTest.java
- NativeMacLayeredOutputStreamTest.java
- PasswordBasedKeyDerivationTest.java
- SharedPrefsBackedKeyChainTest.java
- SimpleDecryptTest.java
- SimpleEncryptTest.java
- UtilsTest.java
- java
- com
- facebook
- android
- crypto
- keychain
- AndroidConceal.java
- SecureRandomFix.java
- SharedPrefsBackedKeyChain.java
- crypto
- CheckedKeyChain.java
- Conceal.java
- Crypto.java
- CryptoAlgo.java
- CryptoAlgoGcm.java
- CryptoConfig.java
- Entity.java
- VersionCodes.java
- cipher
- NativeGCMCipher.java
- NativeGCMCipherException.java
- exception
- CryptoInitializationException.java
- KeyChainException.java
- keychain
- keygen
- PasswordBasedKeyDerivation.java
- mac
- proguard
- annotations
- DoNotStrip.java
- InternalBuildOnly.java
- KeepGettersAndSetters.java
- streams
- BetterCipherInputStream.java
- FixedSizeByteArrayOutputStream.java
- NativeGCMCipherInputStream.java
- NativeGCMCipherOutputStream.java
- NativeMacLayeredInputStream.java
- NativeMacLayeredOutputStream.java
- TailInputStream.java
- util
- Assertions.java
- NativeCryptoLibrary.java
- SystemNativeCryptoLibrary.java
- javatests
- com
- facebook
- android
- keychain
- SharedPrefsBackedKeyChainTest.java
- crypto
- streams
- BetterCipherInputStreamTest.java
- FixedSizeByteArrayOutputStreamTest.java
- TailBufferHelper.java
- TailInputStreamTest.java
/* * Copyright (c) 2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ package com.facebook.crypto.cipher; import java.util.Locale; import com.facebook.crypto.CryptoConfig; import com.facebook.crypto.exception.CryptoInitializationException; import com.facebook.crypto.util.Assertions; import com.facebook.crypto.util.NativeCryptoLibrary; import com.facebook.crypto.proguard.annotations.DoNotStrip; /** * Various native functions to encrypt/decrypt data using GCM. */ @DoNotStrip public class NativeGCMCipher { public static final String FAILURE = "Failure"; private static final String CIPHER_ALREADY_INIT = "Cipher has already been initialized"; private static final String CIPHER_NOT_INIT = "Cipher has not been initialized"; private static final String CIPHER_NOT_FINALIZED = "Cipher has not been finalized"; private STATE mCurrentState = STATE.UNINITIALIZED; private final NativeCryptoLibrary mNativeCryptoLibrary; private enum STATE { UNINITIALIZED, ENCRYPT_INITIALIZED, DECRYPT_INITIALIZED, ENCRYPT_FINALIZED, DECRYPT_FINALIZED, }; public NativeGCMCipher(NativeCryptoLibrary nativeCryptoLibrary) { mNativeCryptoLibrary = nativeCryptoLibrary; } public void encryptInit(byte[] key, byte[] iv) throws NativeGCMCipherException, CryptoInitializationException { Assertions.checkState(mCurrentState == STATE.UNINITIALIZED, CIPHER_ALREADY_INIT); mNativeCryptoLibrary.ensureCryptoLoaded(); if (nativeEncryptInit(key, iv) == nativeFailure()) { throw new NativeGCMCipherException("encryptInit"); } mCurrentState = STATE.ENCRYPT_INITIALIZED; } public void decryptInit(byte[] key, byte[] iv) throws NativeGCMCipherException, CryptoInitializationException { Assertions.checkState(mCurrentState == STATE.UNINITIALIZED, CIPHER_ALREADY_INIT); mNativeCryptoLibrary.ensureCryptoLoaded(); if (nativeDecryptInit(key, iv) == nativeFailure()) { throw new NativeGCMCipherException("decryptInit"); } mCurrentState = STATE.DECRYPT_INITIALIZED; } public int update(byte[] data, int offset, int dataLen, byte[] output, int outputOffset) throws NativeGCMCipherException { ensureInInitalizedState(); int bytesRead = nativeUpdate(data, offset, dataLen, output, outputOffset); if (bytesRead < 0) { throw new NativeGCMCipherException( formatStrLocaleSafe( "update: Offset = %d; DataLen = %d; Result = %d", offset, dataLen, bytesRead)); } return bytesRead; } public void updateAad(byte[] data, int dataLength) throws NativeGCMCipherException { ensureInInitalizedState(); if (nativeUpdateAad(data, dataLength) < 0) { throw new NativeGCMCipherException( formatStrLocaleSafe("updateAAd: DataLen = %d", dataLength)); } } public void encryptFinal(byte[] tag, int tagLen) throws NativeGCMCipherException { Assertions.checkState(mCurrentState == STATE.ENCRYPT_INITIALIZED, CIPHER_NOT_INIT); mCurrentState = STATE.ENCRYPT_FINALIZED; if (nativeEncryptFinal(tag, tagLen) == nativeFailure()) { throw new NativeGCMCipherException( formatStrLocaleSafe("encryptFinal: %d", tagLen)); } } public void decryptFinal(byte[] expectedTag, int tagLen) throws NativeGCMCipherException { Assertions.checkState(mCurrentState == STATE.DECRYPT_INITIALIZED, CIPHER_NOT_INIT); mCurrentState = STATE.DECRYPT_FINALIZED; if (nativeDecryptFinal(expectedTag, tagLen) == nativeFailure()) { throw new NativeGCMCipherException( "The message could not be decrypted successfully." + "It has either been tampered with or the wrong resource is being decrypted."); } } public void destroy() throws NativeGCMCipherException { ensureInFinalizedState(); if (nativeDestroy() == nativeFailure()) { throw new NativeGCMCipherException("destroy"); } mCurrentState = STATE.UNINITIALIZED; } public int getCipherBlockSize() { ensureInInitalizedState(); return nativeGetCipherBlockSize(); } private void ensureInInitalizedState() { boolean initialized = mCurrentState == STATE.DECRYPT_INITIALIZED || mCurrentState == STATE.ENCRYPT_INITIALIZED; Assertions.checkState(initialized, CIPHER_NOT_INIT); } private void ensureInFinalizedState() { boolean finalized = mCurrentState == STATE.DECRYPT_FINALIZED || mCurrentState == STATE.ENCRYPT_FINALIZED; Assertions.checkState(finalized, CIPHER_NOT_FINALIZED); } private String formatStrLocaleSafe(String format, Object... args) { return String.format((Locale)null, format, args); } // Used to store the GCM cipher context. @DoNotStrip private long mCtxPtr; // The integer value representing failure in JNI world. private static native int nativeFailure(); private native int nativeEncryptInit(byte[] key, byte[] iv); private native int nativeDecryptInit(byte[] key, byte[] iv); private native int nativeUpdate(byte[] data, int offset, int dataLen, byte[] output, int outputOffset); private native int nativeUpdateAad(byte[] data, int dataLength); private native int nativeEncryptFinal(byte[] tag, int tagLen); private native int nativeDecryptFinal(byte[] tag, int tagLength); private native int nativeDestroy(); private native int nativeGetCipherBlockSize(); }