Android Open Source - conceal Native G C M Cipher






From Project

Back to project page conceal.

License

The source code is released under:

BSD License For Conceal software Copyright (c) 2014, Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that...

If you think the Android project conceal listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 *  Copyright (c) 2014, Facebook, Inc.//  ww  w. j  ava2 s  .  c  om
 *  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.exception.CryptoInitializationException;
import com.facebook.crypto.util.Assertions;
import com.facebook.crypto.util.NativeCryptoLibrary;
import com.facebook.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";

  public static final int TAG_LENGTH = 16;
  public static final int KEY_LENGTH = 16;
  public static final int IV_LENGTH = 12;

  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)
      throws NativeGCMCipherException {
    ensureInInitalizedState();
    int bytesRead = nativeUpdate(data, offset, dataLen, output);
    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 int 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);
  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();
}




Java Source Code List

com.facebook.android.crypto.keychain.SecureRandomFix.java
com.facebook.android.crypto.keychain.SharedPrefsBackedKeyChainTest.java
com.facebook.android.crypto.keychain.SharedPrefsBackedKeyChain.java
com.facebook.crypto.BouncyCastleHelper.java
com.facebook.crypto.CipherHelper.java
com.facebook.crypto.CryptoSerializerHelper.java
com.facebook.crypto.CryptoTestUtils.java
com.facebook.crypto.Crypto.java
com.facebook.crypto.Entity.java
com.facebook.crypto.FakeKeyChain.java
com.facebook.crypto.FbInstrumentationTestRunner.java
com.facebook.crypto.NativeGCMCipherInputStreamTest.java
com.facebook.crypto.NativeGCMCipherOutputStreamTest.java
com.facebook.crypto.NativeMacLayeredInputStreamTest.java
com.facebook.crypto.NativeMacLayeredOutputStreamTest.java
com.facebook.crypto.SimpleDecryptTest.java
com.facebook.crypto.SimpleEncryptTest.java
com.facebook.crypto.VersionCodes.java
com.facebook.crypto.benchmarks.BenchmarkNativeCryptoLibrary.java
com.facebook.crypto.benchmarks.CipherReadBenchmark.java
com.facebook.crypto.benchmarks.CipherWriteBenchmark.java
com.facebook.crypto.benchmarks.MacBenchmark.java
com.facebook.crypto.benchmarks.cipher.AESCipher.java
com.facebook.crypto.benchmarks.cipher.BaseCipher.java
com.facebook.crypto.benchmarks.cipher.BouncyCastleCCMCipher.java
com.facebook.crypto.benchmarks.cipher.BouncyCastleGCMCipher.java
com.facebook.crypto.benchmarks.cipher.NativeGCMCipherHelper.java
com.facebook.crypto.benchmarks.mac.BaseMac.java
com.facebook.crypto.benchmarks.mac.HMAC.java
com.facebook.crypto.benchmarks.mac.NativeMacHelper.java
com.facebook.crypto.benchmarks.mac.streams.MacLayeredInputStream.java
com.facebook.crypto.benchmarks.mac.streams.MacLayeredOutputStream.java
com.facebook.crypto.cipher.NativeGCMCipherException.java
com.facebook.crypto.cipher.NativeGCMCipher.java
com.facebook.crypto.exception.CryptoInitializationException.java
com.facebook.crypto.exception.KeyChainException.java
com.facebook.crypto.keychain.KeyChain.java
com.facebook.crypto.mac.NativeMac.java
com.facebook.crypto.streams.BetterCipherInputStreamTest.java
com.facebook.crypto.streams.BetterCipherInputStream.java
com.facebook.crypto.streams.FixedSizeByteArrayOutputStream.java
com.facebook.crypto.streams.NativeGCMCipherInputStream.java
com.facebook.crypto.streams.NativeGCMCipherOutputStream.java
com.facebook.crypto.streams.NativeMacLayeredInputStream.java
com.facebook.crypto.streams.NativeMacLayeredOutputStream.java
com.facebook.crypto.streams.TailBufferHelper.java
com.facebook.crypto.streams.TailInputStreamTest.java
com.facebook.crypto.streams.TailInputStream.java
com.facebook.crypto.util.Assertions.java
com.facebook.crypto.util.NativeCryptoLibrary.java
com.facebook.crypto.util.SystemNativeCryptoLibrary.java
com.facebook.proguard.annotations.DoNotStrip.java
com.facebook.proguard.annotations.InternalBuildOnly.java
com.facebook.proguard.annotations.KeepGettersAndSetters.java