Example usage for org.bouncycastle.crypto.modes GCMBlockCipher init

List of usage examples for org.bouncycastle.crypto.modes GCMBlockCipher init

Introduction

In this page you can find the example usage for org.bouncycastle.crypto.modes GCMBlockCipher init.

Prototype

public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException 

Source Link

Document

NOTE: MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported.

Usage

From source file:org.openmuc.jdlms.internal.security.CipheringGcm.java

License:Open Source License

public static byte[] encrypt(byte[] plaintext, int off, int len, byte[] systemTitle, int frameCounter,
        byte[] encryptionKey, byte[] authenticationKey, byte tag) throws IOException {

    byte[] frameCounterBytes = intToByteArray(frameCounter);

    byte[] iv = concat(systemTitle, frameCounterBytes);

    byte[] associatedData = new byte[authenticationKey.length + 1];
    associatedData[0] = SECURITY_CONTROL_BYTES_AUTH_CIPH;
    System.arraycopy(authenticationKey, 0, associatedData, 1, authenticationKey.length);

    AEADParameters parameters = new AEADParameters(new KeyParameter(encryptionKey), 96, iv, associatedData);

    GCMBlockCipher encCipher = new GCMBlockCipher(new AESFastEngine(), new BasicGCMMultiplier());
    encCipher.init(true, parameters);

    byte[] enc = new byte[encCipher.getOutputSize(len)];
    int length = encCipher.processBytes(plaintext, off, len, enc, 0);
    try {// w  w  w .  ja v  a 2s.  com
        length += encCipher.doFinal(enc, length);
    } catch (IllegalStateException e) {
        throw new IOException("Unable to cipher/encrypt xDLMS pdu", e);
    } catch (InvalidCipherTextException e) {
        throw new IOException("Unable to cipher/encrypt xDLMS pdu", e);
    }

    byte[] result = new byte[enc.length + 7];
    result[0] = tag;
    result[1] = (byte) (enc.length + 5);
    result[2] = SECURITY_CONTROL_BYTES_AUTH_CIPH;
    System.arraycopy(frameCounterBytes, 0, result, 3, 4);
    System.arraycopy(enc, 0, result, 7, enc.length);

    return result;
}

From source file:org.openmuc.jdlms.internal.security.CipheringGcm.java

License:Open Source License

public static byte[] decrypt(byte[] ciphertext, byte[] systemTitle, byte[] encryptionKey,
        byte[] authenticationKey) throws IOException {

    byte[] iv = new byte[12];
    System.arraycopy(systemTitle, 0, iv, 0, systemTitle.length);
    // copy frame counter
    System.arraycopy(ciphertext, 1, iv, 8, 4);

    byte[] associatedData = new byte[authenticationKey.length + 1];
    associatedData[0] = SECURITY_CONTROL_BYTES_AUTH_CIPH;
    System.arraycopy(authenticationKey, 0, associatedData, 1, authenticationKey.length);

    AEADParameters parameters = new AEADParameters(new KeyParameter(encryptionKey), 96, iv, associatedData);

    GCMBlockCipher decCipher = new GCMBlockCipher(new AESFastEngine(), new BasicGCMMultiplier());
    decCipher.init(false, parameters);

    byte[] dec = new byte[decCipher.getOutputSize(ciphertext.length - 5)];
    int len = decCipher.processBytes(ciphertext, 5, ciphertext.length - 5, dec, 0);
    try {//w  w  w . java 2s . c  o m
        len += decCipher.doFinal(dec, len);
    } catch (IllegalStateException e) {
        throw new IOException("Unable to decipher/decrypt xDLMS pdu", e);
    } catch (InvalidCipherTextException e) {
        throw new IOException("Unable to decipher/decrypt xDLMS pdu", e);
    }

    return dec;
}

From source file:org.panbox.core.crypto.io.AESGCMRandomAccessFileCompat.java

License:Open Source License

@Override
protected byte[] _readChunk(long index) throws IOException, FileEncryptionException, FileIntegrityException {
    // first, get chunk iv for decryption
    long oldpos = backingRandomAccessFile.getFilePointer();
    backingRandomAccessFile.seek(chunkOffset(index));

    // read iv//from   w  ww .jav a  2  s . co  m
    byte[] iv = new byte[CHUNK_IV_SIZE];
    int ret = backingRandomAccessFile.read(iv);
    if (ret != CHUNK_IV_SIZE) {
        throw new FileEncryptionException("Size mismatch reading chunk IV!");
    }

    // prepare params for GCM decryption
    // retrieve key bytes from SecretKey
    byte[] key = getFileKeyBytes();
    if ((key == null) || (key.length != KeyConstants.SYMMETRIC_FILE_KEY_SIZE_BYTES)) {
        throw new FileEncryptionException("Invalid encryption key format!");
    }

    // prepare additional authenticated data (index and lastchunkflag as
    // bytes) for verifying metadata integrity
    // byte[] indexAsBytes = IntByteConv.int2byte(index);
    byte[] indexAsBytes = LongByteConv.long2Bytes(index);
    byte[] lastchunkflagAsBytes = BooleanByteConv.bool2byte(false);

    if ((indexAsBytes == null) || (lastchunkflagAsBytes == null) || (indexAsBytes.length == 0)
            || (lastchunkflagAsBytes.length == 0)) {
        throw new FileEncryptionException("Invalid additional autenticated data!");
    }

    byte[] associatedText = new byte[indexAsBytes.length + lastchunkflagAsBytes.length];
    System.arraycopy(indexAsBytes, 0, associatedText, 0, indexAsBytes.length);
    System.arraycopy(lastchunkflagAsBytes, 0, associatedText, indexAsBytes.length, lastchunkflagAsBytes.length);

    AEADParameters gcmParams = new AEADParameters(new KeyParameter(key), GCM_AUTHENTICATION_TAG_LEN, iv,
            associatedText);

    GCMBlockCipher gcmEngine = new GCMBlockCipher(new AESFastEngine());
    gcmEngine.init(false, gcmParams);

    byte[] decMsg = new byte[gcmEngine.getOutputSize(CHUNK_ENC_DATA_SIZE)];
    byte[] encMsg = new byte[CHUNK_ENC_DATA_SIZE];

    ret = backingRandomAccessFile.read(encMsg);
    backingRandomAccessFile.seek(oldpos);

    if (ret != CHUNK_ENC_DATA_SIZE) {
        throw new FileEncryptionException("Size mismatch reading encrypted chunk data!");
    }

    int decLen = gcmEngine.processBytes(encMsg, 0, encMsg.length, decMsg, 0);
    try {
        decLen += gcmEngine.doFinal(decMsg, decLen);
    } catch (IllegalStateException | InvalidCipherTextException e) {
        if ((e instanceof InvalidCipherTextException) && (e.getMessage().contains("mac check in GCM failed"))) {
            throw new FileIntegrityException(
                    "Decryption error in chunk " + index + ". Possible file integrity violation.", e);
        } else {
            throw new FileEncryptionException("Decryption error in chunk " + index + ": " + e.getMessage(), e);
        }
    }

    if ((decMsg == null) || (decMsg.length != CHUNK_DATA_SIZE)) {
        throw new FileEncryptionException("Decryption error or chunk size mismatch during decryption!");
    } else {
        if (implementsAuthentication()) {
            // check authentication tag for integrity
            byte[] tag = Arrays.copyOfRange(encMsg, decMsg.length, encMsg.length);
            if (!getAuthTagVerifier().verifyChunkAuthTag((int) index, tag)) {
                throw new FileIntegrityException(
                        "File authentication tag verification failed in chunk " + index);
            }
        }
        return decMsg;
    }
}

From source file:org.picketlink.json.jose.crypto.AESGCM.java

License:Open Source License

/**
 * Creates a new AES/GCM/NoPadding cipher.
 *
 * @param secretKey The AES key. Must not be {@code null}.
 * @param forEncryption If {@code true} creates an encryption cipher, else creates a decryption cipher.
 * @param iv The initialisation vector (IV). Must not be {@code null}.
 * @param authData The authenticated data. Must not be {@code null}.
 *
 * @return The AES/GCM/NoPadding cipher.
 *//*from  www.j a  v  a 2  s . com*/
private static GCMBlockCipher createAESGCMCipher(final SecretKey secretKey, final boolean forEncryption,
        final byte[] iv, final byte[] authData) {

    // Initialize AES cipher
    BlockCipher cipher = AES.createCipher(secretKey, forEncryption);

    // Create GCM cipher with AES
    GCMBlockCipher gcm = new GCMBlockCipher(cipher);

    AEADParameters aeadParams = new AEADParameters(new KeyParameter(secretKey.getEncoded()),
            AUTH_TAG_BIT_LENGTH, iv, authData);
    gcm.init(forEncryption, aeadParams);

    return gcm;
}

From source file:org.springframework.security.crypto.encrypt.BouncyCastleAesGcmBytesEncryptor.java

License:Apache License

@Override
public byte[] encrypt(byte[] bytes) {
    byte[] iv = this.ivGenerator.generateKey();

    GCMBlockCipher blockCipher = new GCMBlockCipher(new AESFastEngine());
    blockCipher.init(true, new AEADParameters(secretKey, 128, iv, null));

    byte[] encrypted = process(blockCipher, bytes);
    return iv != null ? concatenate(iv, encrypted) : encrypted;
}

From source file:org.springframework.security.crypto.encrypt.BouncyCastleAesGcmBytesEncryptor.java

License:Apache License

@Override
public byte[] decrypt(byte[] encryptedBytes) {
    byte[] iv = subArray(encryptedBytes, 0, this.ivGenerator.getKeyLength());
    encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), encryptedBytes.length);

    GCMBlockCipher blockCipher = new GCMBlockCipher(new AESFastEngine());
    blockCipher.init(false, new AEADParameters(secretKey, 128, iv, null));
    return process(blockCipher, encryptedBytes);
}

From source file:org.xdi.oxauth.model.jwe.JweDecrypterImpl.java

License:MIT License

@Override
public String decryptCipherText(String encodedCipherText, byte[] contentMasterKey, byte[] initializationVector,
        byte[] authenticationTag, byte[] additionalAuthenticatedData) throws InvalidJweException {
    if (getBlockEncryptionAlgorithm() == null) {
        throw new InvalidJweException("The block encryption algorithm is null");
    }//ww  w .  j  av a  2s. com
    if (contentMasterKey == null) {
        throw new InvalidJweException("The content master key (CMK) is null");
    }
    if (initializationVector == null) {
        throw new InvalidJweException("The initialization vector is null");
    }
    if (authenticationTag == null) {
        throw new InvalidJweException("The authentication tag is null");
    }
    if (additionalAuthenticatedData == null) {
        throw new InvalidJweException("The additional authentication data is null");
    }

    try {
        if (getBlockEncryptionAlgorithm() == BlockEncryptionAlgorithm.A128GCM
                || getBlockEncryptionAlgorithm() == BlockEncryptionAlgorithm.A256GCM) {
            final int MAC_SIZE_BITS = 128;
            byte[] cipherText = Base64Util.base64urldecode(encodedCipherText);

            KeyParameter key = new KeyParameter(contentMasterKey);
            AEADParameters aeadParameters = new AEADParameters(key, MAC_SIZE_BITS, initializationVector,
                    additionalAuthenticatedData);
            SecretKeySpec sks = new SecretKeySpec(contentMasterKey, "AES");

            BlockCipher blockCipher = new AESEngine();
            CipherParameters params = new KeyParameter(sks.getEncoded());
            blockCipher.init(false, params);
            GCMBlockCipher aGCMBlockCipher = new GCMBlockCipher(blockCipher);
            aGCMBlockCipher.init(false, aeadParameters);
            byte[] input = new byte[cipherText.length + authenticationTag.length];
            System.arraycopy(cipherText, 0, input, 0, cipherText.length);
            System.arraycopy(authenticationTag, 0, input, cipherText.length, authenticationTag.length);
            int len = aGCMBlockCipher.getOutputSize(input.length);
            byte[] out = new byte[len];
            int outOff = aGCMBlockCipher.processBytes(input, 0, input.length, out, 0);
            aGCMBlockCipher.doFinal(out, outOff);

            String plaintext = new String(out, Charset.forName(Util.UTF8_STRING_ENCODING));

            return plaintext;
        } else if (getBlockEncryptionAlgorithm() == BlockEncryptionAlgorithm.A128CBC_PLUS_HS256
                || getBlockEncryptionAlgorithm() == BlockEncryptionAlgorithm.A256CBC_PLUS_HS512) {
            byte[] cipherText = Base64Util.base64urldecode(encodedCipherText);

            byte[] cek = KeyDerivationFunction.generateCek(contentMasterKey, getBlockEncryptionAlgorithm());
            Cipher cipher = Cipher.getInstance(getBlockEncryptionAlgorithm().getAlgorithm());
            IvParameterSpec ivParameter = new IvParameterSpec(initializationVector);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cek, "AES"), ivParameter);
            byte[] decodedPlainTextBytes = cipher.doFinal(cipherText);
            String decodedPlainText = new String(decodedPlainTextBytes,
                    Charset.forName(Util.UTF8_STRING_ENCODING));

            // Integrity check
            String securedInputValue = new String(additionalAuthenticatedData,
                    Charset.forName(Util.UTF8_STRING_ENCODING)) + "." + encodedCipherText;
            byte[] cik = KeyDerivationFunction.generateCik(contentMasterKey, getBlockEncryptionAlgorithm());
            SecretKey secretKey = new SecretKeySpec(cik,
                    getBlockEncryptionAlgorithm().getIntegrityValueAlgorithm());
            Mac mac = Mac.getInstance(getBlockEncryptionAlgorithm().getIntegrityValueAlgorithm());
            mac.init(secretKey);
            byte[] integrityValue = mac.doFinal(securedInputValue.getBytes(Util.UTF8_STRING_ENCODING));
            if (!Arrays.equals(integrityValue, authenticationTag)) {
                throw new InvalidJweException("The authentication tag is not valid");
            }

            return decodedPlainText;
        } else {
            throw new InvalidJweException("The block encryption algorithm is not supported");
        }
    } catch (InvalidCipherTextException e) {
        throw new InvalidJweException(e);
    } catch (NoSuchPaddingException e) {
        throw new InvalidJweException(e);
    } catch (BadPaddingException e) {
        throw new InvalidJweException(e);
    } catch (InvalidAlgorithmParameterException e) {
        throw new InvalidJweException(e);
    } catch (NoSuchAlgorithmException e) {
        throw new InvalidJweException(e);
    } catch (IllegalBlockSizeException e) {
        throw new InvalidJweException(e);
    } catch (UnsupportedEncodingException e) {
        throw new InvalidJweException(e);
    } catch (NoSuchProviderException e) {
        throw new InvalidJweException(e);
    } catch (InvalidKeyException e) {
        throw new InvalidJweException(e);
    } catch (InvalidParameterException e) {
        throw new InvalidJweException(e);
    }
}

From source file:org.xdi.oxauth.model.jwe.JweEncrypterImpl.java

License:MIT License

@Override
public Pair<String, String> generateCipherTextAndIntegrityValue(byte[] contentMasterKey,
        byte[] initializationVector, byte[] additionalAuthenticatedData, byte[] plainText)
        throws InvalidJweException {
    if (getBlockEncryptionAlgorithm() == null) {
        throw new InvalidJweException("The block encryption algorithm is null");
    }/* www  .  j a v a  2s.c  om*/
    if (contentMasterKey == null) {
        throw new InvalidJweException("The content master key (CMK) is null");
    }
    if (initializationVector == null) {
        throw new InvalidJweException("The initialization vector is null");
    }
    if (additionalAuthenticatedData == null) {
        throw new InvalidJweException("The additional authentication data is null");
    }
    if (plainText == null) {
        throw new InvalidJweException("The plain text to encrypt is null");
    }

    try {
        if (getBlockEncryptionAlgorithm() == BlockEncryptionAlgorithm.A128GCM
                || getBlockEncryptionAlgorithm() == BlockEncryptionAlgorithm.A256GCM) {
            SecretKey secretKey = new SecretKeySpec(contentMasterKey, "AES");
            KeyParameter key = new KeyParameter(contentMasterKey);
            final int MAC_SIZE_BITS = 128;
            AEADParameters aeadParameters = new AEADParameters(key, MAC_SIZE_BITS, initializationVector,
                    additionalAuthenticatedData);

            final int macSize = aeadParameters.getMacSize() / 8;
            BlockCipher blockCipher = new AESEngine();
            CipherParameters params = new KeyParameter(secretKey.getEncoded());
            blockCipher.init(true, params);
            GCMBlockCipher aGCMBlockCipher = new GCMBlockCipher(blockCipher);
            aGCMBlockCipher.init(true, aeadParameters);
            int len = aGCMBlockCipher.getOutputSize(plainText.length);
            byte[] out = new byte[len];
            int outOff = aGCMBlockCipher.processBytes(plainText, 0, plainText.length, out, 0);
            outOff += aGCMBlockCipher.doFinal(out, outOff);
            byte[] cipherText = new byte[outOff - macSize];
            System.arraycopy(out, 0, cipherText, 0, cipherText.length);
            byte[] authenticationTag = new byte[macSize];
            System.arraycopy(out, outOff - macSize, authenticationTag, 0, authenticationTag.length);

            String encodedCipherText = Base64Util.base64urlencode(cipherText);
            String encodedAuthenticationTag = Base64Util.base64urlencode(authenticationTag);

            return new Pair<String, String>(encodedCipherText, encodedAuthenticationTag);
        } else if (getBlockEncryptionAlgorithm() == BlockEncryptionAlgorithm.A128CBC_PLUS_HS256
                || getBlockEncryptionAlgorithm() == BlockEncryptionAlgorithm.A256CBC_PLUS_HS512) {
            byte[] cek = KeyDerivationFunction.generateCek(contentMasterKey, getBlockEncryptionAlgorithm());
            IvParameterSpec parameters = new IvParameterSpec(initializationVector);
            Cipher cipher = Cipher.getInstance(getBlockEncryptionAlgorithm().getAlgorithm(), "BC");
            //Cipher cipher = Cipher.getInstance(getBlockEncryptionAlgorithm().getAlgorithm());
            SecretKeySpec secretKeySpec = new SecretKeySpec(cek, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, parameters);
            byte[] cipherText = cipher.doFinal(plainText);

            String encodedCipherText = Base64Util.base64urlencode(cipherText);

            String securedInputValue = new String(additionalAuthenticatedData,
                    Charset.forName(Util.UTF8_STRING_ENCODING)) + "." + encodedCipherText;

            byte[] cik = KeyDerivationFunction.generateCik(contentMasterKey, getBlockEncryptionAlgorithm());
            SecretKey secretKey = new SecretKeySpec(cik,
                    getBlockEncryptionAlgorithm().getIntegrityValueAlgorithm());
            Mac mac = Mac.getInstance(getBlockEncryptionAlgorithm().getIntegrityValueAlgorithm());
            mac.init(secretKey);
            byte[] integrityValue = mac.doFinal(securedInputValue.getBytes(Util.UTF8_STRING_ENCODING));

            String encodedIntegrityValue = Base64Util.base64urlencode(integrityValue);

            return new Pair<String, String>(encodedCipherText, encodedIntegrityValue);
        } else {
            throw new InvalidJweException("The block encryption algorithm is not supported");
        }
    } catch (InvalidCipherTextException e) {
        throw new InvalidJweException(e);
    } catch (NoSuchAlgorithmException e) {
        throw new InvalidJweException(e);
    } catch (UnsupportedEncodingException e) {
        throw new InvalidJweException(e);
    } catch (NoSuchProviderException e) {
        throw new InvalidJweException(e);
    } catch (IllegalBlockSizeException e) {
        throw new InvalidJweException(e);
    } catch (InvalidKeyException e) {
        throw new InvalidJweException(e);
    } catch (BadPaddingException e) {
        throw new InvalidJweException(e);
    } catch (InvalidAlgorithmParameterException e) {
        throw new InvalidJweException(e);
    } catch (NoSuchPaddingException e) {
        throw new InvalidJweException(e);
    } catch (InvalidParameterException e) {
        throw new InvalidJweException(e);
    }
}

From source file:se.kth.ssvl.tslab.wsn.general.servlib.security.Ciphersuite_C3.java

License:Apache License

/**
 * "Validate the block. This is called after all blocks in the bundle have
 * been fully received."[DTN2]/*ww w . j  a  v  a 2s .co m*/
 * 
 * @param bundle
 * @param block_list
 * @param block
 *            (IN): the block with the BP_Local_CS data already loaded.
 * @param reception_reason
 * @param deletion_reason
 * @return : true if the block passes validation
 */
public boolean validate(final Bundle bundle, BlockInfoVec block_list, BlockInfo block,
        status_report_reason_t[] reception_reason, status_report_reason_t[] deletion_reason) {
    /*
     * 1. do we have security-dest? If yes, get it, otherwise get
     * bundle-dest 2. does it match local_eid ?? 3. if not, return true 4.
     * if it does match, parse and validate the block 5. the actions must
     * exactly reverse the transforming changes made in finalize()
     */
    Bundle deliberate_const_cast_bundle = bundle;
    BP_Local_CS locals = (BP_Local_CS) (block.locals());
    int offset;
    int len;
    IByteBuffer key = new SerializableByteBuffer(key_len); // use AES128
    // 16-byte key
    IByteBuffer salt = new SerializableByteBuffer(salt_len); // salt for GCM
    IByteBuffer iv = new SerializableByteBuffer(iv_len); // GCM "iv" length
    // is 8 bytes
    IByteBuffer nonce = new SerializableByteBuffer(nonce_len); // 12 bytes
    // recommended
    IByteBuffer buf;
    IByteBuffer ptr;
    int sdnv_len = 0; // use an int to handle -1 return values
    ciphersuite_fields_t item_type;
    long field_length = 0;
    long frag_offset_; // Offset of fragment in the original bundle
    long orig_length_; // Length of original bundle
    IByteBuffer db;

    BPF.getInstance().getBPFLogger().debug(TAG, "validate()");

    if (locals == null) // FAIL_IF_NULL
    {
        return false;
    }

    if (Ciphersuite.destination_is_local_node(bundle, block)) { // yes,
        // this is
        // ours so
        // go to
        // work

        /*
         * we expect this to be the "first" block, and there might or might
         * not be others. But we should get to this one first and, during
         * the processing, convert any other C3 blocks to their
         * unencapsulated form. That is, when this call is over, there
         * should be no more blocks for us to deal with. Any remaining C3
         * block should be for a nested instance
         */

        // get pieces from params -- salt, iv, range,
        buf = new SerializableByteBuffer(locals.security_params().capacity());
        BufferHelper.copy_data(buf, buf.position(), locals.security_params(), 0,
                locals.security_params().capacity());

        len = locals.security_params().capacity();

        BPF.getInstance().getBPFLogger().debug(TAG, "validate() locals.correlator() " + locals.correlator());
        BPF.getInstance().getBPFLogger().debug(TAG, "validate() security params, len = " + len);

        while (len > 0) {
            // we parse the params: type-length-value

            // we obtain the ciphersuite_fields_t (IV, key info, etc) inside
            // the params field.
            item_type = ciphersuite_fields_t.get(buf.get());
            --len;

            long[] value = new long[1];
            sdnv_len = read_sdnv(buf, value);
            field_length = value[0];
            len -= sdnv_len;

            switch (item_type) {
            case CS_IV_field: {
                BPF.getInstance().getBPFLogger().debug(TAG, "validate() iv item, len = " + field_length);
                BufferHelper.copy_data(iv, 0, buf, buf.position(), iv_len);

                buf.position((int) (buf.position() + field_length));
                len -= field_length;
            }
                break;

            case CS_C_block_salt: {

                BPF.getInstance().getBPFLogger().debug(TAG, "validate() salt item, len = " + field_length);

                BufferHelper.copy_data(salt, 0, buf, buf.position(), nonce_len - iv_len);
                buf.position((int) (buf.position() + field_length));
                len -= field_length;
            }
                break;

            case CS_fragment_offset_and_length_field: {
                BPF.getInstance().getBPFLogger().debug(TAG, "validate() frag info item, len = " + field_length);

                value = new long[1];
                sdnv_len = read_sdnv(buf, value);
                frag_offset_ = value[0];

                len -= sdnv_len;

                value = new long[1];
                sdnv_len = read_sdnv(buf, value);
                orig_length_ = value[0];

                len -= sdnv_len;
            }
                break;

            default: // deal with improper items
                BPF.getInstance().getBPFLogger().error(TAG,
                        "validate: unexpected item type " + item_type + " in security_params");
                if (locals != null) // GOTO FAIL
                    locals.set_proc_flags((short) (proc_flags_t.CS_BLOCK_FAILED_VALIDATION.getCode()
                            | proc_flags_t.CS_BLOCK_COMPLETED_DO_NOT_FORWARD.getCode()));
                return false;
            }
        }

        // We parse the security-result field.
        // get pieces from results -- key, icv

        buf = new SerializableByteBuffer(locals.security_result().capacity());
        BufferHelper.copy_data(buf, buf.position(), locals.security_result(), 0,
                locals.security_result().capacity());

        len = locals.security_result().capacity();

        BPF.getInstance().getBPFLogger().debug(TAG, "validate(). security result, len = " + len);
        while (len > 0) {
            BPF.getInstance().getBPFLogger().debug(TAG, "remaining len = " + len);
            // we get the type of the tuple (type-length-value)
            item_type = ciphersuite_fields_t.get(buf.get());
            --len;

            // we get the length
            long[] value = new long[1];
            sdnv_len = read_sdnv(buf, value);

            field_length = value[0];
            BPF.getInstance().getBPFLogger().debug(TAG, "field length: " + field_length);
            len -= sdnv_len;

            // we process the value (type-length-value)
            switch (item_type) {
            case CS_key_ID_field: {
                BPF.getInstance().getBPFLogger().debug(TAG, "validate() key ID item");
                BPF.getInstance().getBPFLogger().error(TAG, "not in specs!!!");
            }
                break;

            case CS_encoded_key_field: {
                BPF.getInstance().getBPFLogger().debug(TAG, "validate(). Parsing encoded key item");
                db = new SerializableByteBuffer(16);

                try {
                    KeySteward.decrypt(buf, field_length, db);
                } catch (Exception e) {
                    BPF.getInstance().getBPFLogger().error(TAG,
                            "The key could not be decrypted. Exception: " + e.getMessage());
                    e.printStackTrace();
                    return false;
                }
                // decrypt DOES NOT MOVE the buf position!
                BufferHelper.copy_data(key, 0, db, 0, key_len);
                buf.position((int) (buf.position() + field_length));
                len -= field_length;
            }
                break;

            case CS_C_block_ICV_field: {
                BPF.getInstance().getBPFLogger().debug(TAG, "validate(). Parsing icv item");

                BufferHelper.copy_data(tag, tag.position(), buf, buf.position(), tag_len);
                buf.position((int) (buf.position() + field_length));
                len -= field_length;
            }
                break;

            case CS_encap_block_field: {
                // don't think we should have one of these here,
                // only in the correlated blocks
                BPF.getInstance().getBPFLogger().error(TAG,
                        "validate(). unexpected encap block in security_result");
                if (locals != null) // GOTO FAIL
                    locals.set_proc_flags((short) (proc_flags_t.CS_BLOCK_FAILED_VALIDATION.getCode()
                            | proc_flags_t.CS_BLOCK_COMPLETED_DO_NOT_FORWARD.getCode()));
                return false;
            }

            default: // deal with improper items
                BPF.getInstance().getBPFLogger().error(TAG,
                        "validate: unexpected item type item_type in security_result");
                if (locals != null) // GOTO FAIL
                    locals.set_proc_flags((short) (proc_flags_t.CS_BLOCK_FAILED_VALIDATION.getCode()
                            | proc_flags_t.CS_BLOCK_COMPLETED_DO_NOT_FORWARD.getCode()));
                return false;
            }
        }

        // prepare context - one time for all usage here
        // gcm_init_and_key(key, key_len, (ctx_ex.c));
        // ctx_ex.operation = op_decrypt;

        // we have the necessary pieces from params and result so now
        // walk all the blocks and do the various processing things needed.
        // First is to get the iterator to where we are (see note in
        // "generate()"
        // for why we do this)

        BPF.getInstance().getBPFLogger().debug(TAG, "validate(). walk block list");

        boolean process_blocks = false; // flag to skip the correlated
        // blocks in the for loop

        Iterator<BlockInfo> blocks_iter = block_list.iterator();
        assert (blocks_iter.hasNext());
        BlockInfo iter;
        while (blocks_iter.hasNext()) {
            iter = blocks_iter.next();

            // step over all blocks up to and including the one which
            // prompted this call, pointed at by "block" argument
            if (!process_blocks) {
                if (iter == block)
                    process_blocks = true;
                continue;
            }

            switch (iter.type()) {

            case CONFIDENTIALITY_BLOCK: // for Nested Confidentiality blocks
            {
                BPF.getInstance().getBPFLogger().debug(TAG, "validate() C block");
                BPF.getInstance().getBPFLogger().debug(TAG, "Nested Confidentiality blocks. Skipping...");
            }

                break;

            case PAYLOAD_BLOCK: {
                System.gc();
                BPF.getInstance().getBPFLogger().debug(TAG, "validate(). PAYLOAD_BLOCK");

                // nonce is 12 bytes, first 4 are salt (same for all blocks)
                // and last 8 bytes are per-block IV. The final 4 bytes in
                // the full block-sized field are, of course, the counter
                // which is not represented here

                ptr = nonce;

                BufferHelper.copy_data(ptr, ptr.position(), salt, 0, salt_len);
                ptr.position(ptr.position() + salt_len);

                BufferHelper.copy_data(ptr, ptr.position(), iv, 0, iv_len);

                BPF.getInstance().getBPFLogger().debug(TAG, String.format(
                        "validate(). Nonce: 0x %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h ",
                        unsignedByteToInt(nonce.get(0)), unsignedByteToInt(nonce.get(1)),
                        unsignedByteToInt(nonce.get(2)), unsignedByteToInt(nonce.get(3)),
                        unsignedByteToInt(nonce.get(4)), unsignedByteToInt(nonce.get(5)),
                        unsignedByteToInt(nonce.get(6)), unsignedByteToInt(nonce.get(7)),
                        unsignedByteToInt(nonce.get(8)), unsignedByteToInt(nonce.get(9)),
                        unsignedByteToInt(nonce.get(10)), unsignedByteToInt(nonce.get(11))));

                offset = iter.data_offset();
                len = iter.data_length();

                byte[] temp_key_array = new byte[key_len];
                key.get(temp_key_array);
                key.rewind();

                byte[] temp_nonce_array = new byte[iv_len + salt_len];
                nonce.rewind();
                nonce.get(temp_nonce_array);
                nonce.rewind();

                BPF.getInstance().getBPFLogger().debug(TAG, String.format(
                        "validate() symmetric key: 0x %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h",
                        unsignedByteToInt(temp_key_array[0]), unsignedByteToInt(temp_key_array[1]),
                        unsignedByteToInt(temp_key_array[2]), unsignedByteToInt(temp_key_array[3]),
                        unsignedByteToInt(temp_key_array[4]), unsignedByteToInt(temp_key_array[5]),
                        unsignedByteToInt(temp_key_array[6]), unsignedByteToInt(temp_key_array[7]),
                        unsignedByteToInt(temp_key_array[8]), unsignedByteToInt(temp_key_array[9]),
                        unsignedByteToInt(temp_key_array[10]), unsignedByteToInt(temp_key_array[11]),
                        unsignedByteToInt(temp_key_array[12]), unsignedByteToInt(temp_key_array[13]),
                        unsignedByteToInt(temp_key_array[14]), unsignedByteToInt(temp_key_array[15])));

                AEADParameters parameters = new AEADParameters(new KeyParameter(temp_key_array), 128,
                        temp_nonce_array, null);
                GCMBlockCipher gcmEngine = new GCMBlockCipher(new AESEngine());
                gcmEngine.init(false, parameters);

                offset = iter.data_offset();
                len = iter.data_length();

                // crypto function
                mutate_func do_encrypt = new mutate_func() {

                    /**
                     * do_crypt decryption
                     * 
                     * @param bundle
                     * @param caller_block
                     * @param target_block
                     * @param buf
                     *            (IN/OUT): contains the payload, and after
                     *            encryption, contains the encrypted data.
                     * @param len
                     *            (IN): length to decrypt
                     */
                    @Override
                    public boolean action(ServlibEventData data) {
                        // initialization
                        mutate_func_event_data do_crypt_data = (mutate_func_event_data) data;

                        int len = bundle.payload().length();
                        GCMBlockCipher gcmEngine = do_crypt_data.context();
                        System.gc();
                        decMsg = new byte[gcmEngine.getOutputSize(len + tag_len)];

                        byte[] encMsg = new byte[bundle.payload().length() + tag_len];
                        bundle.payload().read_data(0, bundle.payload().length(), encMsg);
                        int in_array_off = 0;

                        for (int i = len; i < len + tag_len; i++)
                            encMsg[i] = tag.get(i - len);

                        assert (in_array_off == 0);

                        String encr_payl = "";
                        for (int i = 0; i < len && i < 10; i++)
                            encr_payl = new String(
                                    encr_payl + String.format("%2.2h ", unsignedByteToInt(encMsg[i])));

                        BPF.getInstance().getBPFLogger().debug(TAG,
                                "do_crypt(): Encrypted payload (first 10 bytes max): 0x " + encr_payl);

                        decLen = gcmEngine.processBytes(encMsg, 0, encMsg.length, decMsg, 0);

                        BPF.getInstance().getBPFLogger().debug(TAG,
                                "do_crypt(): operation decryption, len " + len);

                        return (len > 0) ? true : false;
                    }
                };

                iter.owner().mutate(do_encrypt, deliberate_const_cast_bundle, block, iter, offset, len,
                        gcmEngine);

                try {
                    decLen += gcmEngine.doFinal(decMsg, decLen);

                    BPF.getInstance().getBPFLogger().info(TAG, String.format(
                            "validate(): Tag comparison successful for tag: 0x %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h ",
                            unsignedByteToInt(tag.get(0)), unsignedByteToInt(tag.get(1)),
                            unsignedByteToInt(tag.get(2)), unsignedByteToInt(tag.get(3)),
                            unsignedByteToInt(tag.get(4)), unsignedByteToInt(tag.get(5)),
                            unsignedByteToInt(tag.get(6)), unsignedByteToInt(tag.get(7)),
                            unsignedByteToInt(tag.get(8)), unsignedByteToInt(tag.get(9)),
                            unsignedByteToInt(tag.get(10)), unsignedByteToInt(tag.get(11)),
                            unsignedByteToInt(tag.get(12)), unsignedByteToInt(tag.get(13)),
                            unsignedByteToInt(tag.get(14)), unsignedByteToInt(tag.get(15))));
                } catch (Exception e) {
                    BPF.getInstance().getBPFLogger().error(TAG, "validate: tag comparison failed");
                    if (locals != null) // GOTO FAIL
                        locals.set_proc_flags((short) (proc_flags_t.CS_BLOCK_FAILED_VALIDATION.getCode()
                                | proc_flags_t.CS_BLOCK_COMPLETED_DO_NOT_FORWARD.getCode()));
                    return false;
                }

                // update payload, swapping the new with the old.
                IByteBuffer temp_buf = new SerializableByteBuffer(decMsg.length);
                String payload_hex = "";
                String payload_str = "";
                for (int i = 0; i < decMsg.length; i++) {
                    temp_buf.put(decMsg[i]);

                }

                for (int i = 0; i < decMsg.length && i < 10; i++) {

                    payload_hex = new String(
                            payload_hex + String.format("%2.2h ", unsignedByteToInt(decMsg[i])));
                    payload_str = new String(payload_str + String.format("%c ", unsignedByteToInt(decMsg[i])));
                }

                BPF.getInstance().getBPFLogger().debug(TAG,
                        "validate(): Decrypted Plaintext (first 10 max)[hex]: 0x " + payload_hex);
                BPF.getInstance().getBPFLogger().debug(TAG,
                        "validate(): Decrypted Plaintext message (first 10 max)[string]: " + payload_str);

                temp_buf.rewind();

                bundle.payload().write_data(temp_buf, 0, decMsg.length); // (from
                // payloadblockprocessor)

                temp_buf = null;
                decMsg = null;
                buf = null;
                encMsg = null;
                System.gc();
            }
                break;

            default:
                continue;

            } // end switch
        } // end for
        BPF.getInstance().getBPFLogger().debug(TAG, "validate() walk block list done");
        locals.set_proc_flag((proc_flags_t.CS_BLOCK_PASSED_VALIDATION.getCode()
                | proc_flags_t.CS_BLOCK_COMPLETED_DO_NOT_FORWARD.getCode()));
    } else {
        // not for here so we didn't check this block
        locals.set_proc_flag(proc_flags_t.CS_BLOCK_DID_NOT_FAIL.getCode());
    }

    BPF.getInstance().getBPFLogger().debug(TAG, "validate()  done");
    return true;
}

From source file:se.kth.ssvl.tslab.wsn.general.servlib.security.Ciphersuite_C3.java

License:Apache License

/**
 * Third callback for transmitting a bundle. This pass walks over the
 * xmit_blocks and generates security signatures for the security block that
 * may depend on other blocks' contents.
 * /*from   ww  w  .j  av a  2s  .c o  m*/
 * For payload blocks, it encrypts the contents (by previously generating an
 * IV), changing the payload. Also, it generates the ICV for this payload
 * block, and places/updates the total ICV in the security-result field of
 * the first PCB.
 */
public int finalize(final Bundle bundle, BlockInfoVec xmit_blocks, BlockInfo block, final Link link) {
    int result = BP_FAIL;
    Bundle deliberate_const_cast_bundle = bundle;
    int offset;
    int len;

    /**
     * symetric key. use AES128 16-byte key
     */
    IByteBuffer key = new SerializableByteBuffer(key_len);

    IByteBuffer nonce = new SerializableByteBuffer(nonce_len);// 12 bytes
    // recommended
    /**
     * Authentication tag, also called ICV. Result of the encryption, to
     * check the integrity of the data.
     */
    IByteBuffer tag = new SerializableByteBuffer(tag_len); // 128 bits
    // recommended

    IByteBuffer buf = new SerializableByteBuffer(256);

    /**
     * aux var to populate the IbyteBuffer fields.
     */
    IByteBuffer ptr = new SerializableByteBuffer(256);
    BP_Local_CS locals = null;
    BP_Local_CS target_locals = null;

    ArrayList<Long> correlator_list = new ArrayList<Long>();

    int sdnv_len = 0; // use an int to handle -1 return values

    BPF.getInstance().getBPFLogger().debug(TAG, "finalize()");

    locals = (BP_Local_CS) (block.locals());

    if (locals == null)
        return BP_FAIL;

    // if this is a received block then we're done
    if (locals.list_owner() == BlockInfo.list_owner_t.LIST_RECEIVED)
        return BP_SUCCESS;

    BufferHelper.copy_data(key, key.position(), locals.key(), 0, key_len);

    // Walk the list and process each of the blocks.
    // We only change PS, C3 and the payload data,
    // all others are unmodified

    // Note that we can only process PSBs and C3s that follow this block
    // as doing otherwise would mean that there would be a
    // correlator block preceding its parent

    // However this causes a problem if the PS is a two-block scheme,
    // as we'll convert the second, correlated block to C and then
    // the PS processor won't have its second block.

    // There can also be tunneling issues, depending upon the
    // exact sequencing of blocks. It seems best to add C blocks
    // as early as possible in order to mitigate this problem.
    // That has its own drawbacks unfortunately

    BPF.getInstance().getBPFLogger().debug(TAG, "finalize()  we start walking the list of blocks");

    Iterator<BlockInfo> blocks_iter = xmit_blocks.iterator();
    assert (blocks_iter.hasNext());
    boolean process_blocks = false; // flag to skip the correlated blocks in
    // the for loop.

    while (blocks_iter.hasNext()) {
        BlockInfo iter = blocks_iter.next();

        BPF.getInstance().getBPFLogger().debug(TAG,
                "finalize()  iteration.next. type of block: " + iter.type().toString());
        BPF.getInstance().getBPFLogger().debug(TAG,
                "data offset: " + iter.data_offset() + " data_length: " + iter.data_length());

        // Advance the iterator to our current position.
        // While we do it, we also remember the correlator values
        // of any PSBs or C3 blocks we encounter.
        // We do this to avoid processing any related correlated blocks
        // Note that we include the current block in the test below
        // in order to prevent encapsulating it !!

        if (!process_blocks) {
            if (iter.type() == BundleProtocol.bundle_block_type_t.CONFIDENTIALITY_BLOCK) {
                BPF.getInstance().getBPFLogger().debug(TAG,
                        "finalize()  we got a confidentialiity block.skiping");
                target_locals = (BP_Local_CS) (iter.locals());

                if (target_locals == null)// FAIL_IF_NULL
                {
                    if (locals != null)
                        locals.set_proc_flag(proc_flags_t.CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND.getCode());
                    return BP_FAIL;
                }

                if (target_locals.owner_cs_num() == CSNUM_C3) {
                    correlator_list.add(target_locals.correlator());
                }
            }

            if (iter == block) {
                BPF.getInstance().getBPFLogger().debug(TAG,
                        "finalize() this block was our payload security block! Next should be payload");
                process_blocks = true;
            }

            continue;
        }

        switch (iter.type()) {

        case CONFIDENTIALITY_BLOCK:

        /*
         * For each PIB or PCB to be protected, the entire original block is
         * encapsulated in a "replacing" PCB. This replacing PCB is placed
         * in the outgoing bundle in the same position as the original
         * block, PIB or PCB. As mentioned above, this is one-for-one
         * replacement and there is no consolidation of blocks or mixing of
         * data in any way.
         */
        {
            BPF.getInstance().getBPFLogger().debug(TAG,
                    "finalize() PSB or CB after our block. we are going to encapsulate it");
            BPF.getInstance().getBPFLogger().debug(TAG, "Encapsulated blocks. Skipping...");
        }
            break;

        case PAYLOAD_BLOCK: {
            BPF.getInstance().getBPFLogger().debug(TAG,
                    "finalize(). Payload block after our block. we are going to encrypt it");
            /*
             * prepare context -- key supplied already nonce is 12 bytes,
             * first 4 are salt (same for all blocks) and last 8 bytes are
             * per-block IV. The final 4 bytes in the full block-sized field
             * are, of course, the counter which is not represented here
             * 
             * "For the payload, only the bytes of the bundle payload field
             * are affected, being replaced by ciphertext. The salt, IV and
             * key values specified in the first PCB are used to encrypt the
             * payload, and the resultant authentication tag (ICV) is placed
             * in an ICV item in the security-result field of that first
             * PCB. The other bytes of the payload block, such as type,
             * flags and length, are not modified." [dtn-sec draft15]
             */
            int rem;
            ciphersuite_fields_t type;
            long field_len;

            ptr = nonce; // Ibytebuffer, empty

            BPF.getInstance().getBPFLogger().debug(TAG, "finalize() PAYLOAD_BLOCK");

            // we copy the salt from the ASB to the work buffer
            BufferHelper.copy_data(ptr, ptr.position(), locals.salt(), 0, salt_len);

            ptr.position(ptr.position() + salt_len);

            // we copy the IV from the ASB to the work buffer (generated in
            // 2nd pass)
            BufferHelper.copy_data(ptr, ptr.position(), locals.iv(), 0, iv_len);

            ptr.position(ptr.position() + iv_len);

            // We have created the prepare context
            BPF.getInstance().getBPFLogger().debug(TAG, String.format(
                    "finalize(). nonce: 0x %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h ",
                    unsignedByteToInt(nonce.get(0)), unsignedByteToInt(nonce.get(1)),
                    unsignedByteToInt(nonce.get(2)), unsignedByteToInt(nonce.get(3)),
                    unsignedByteToInt(nonce.get(4)), unsignedByteToInt(nonce.get(5)),
                    unsignedByteToInt(nonce.get(6)), unsignedByteToInt(nonce.get(7)),
                    unsignedByteToInt(nonce.get(8)), unsignedByteToInt(nonce.get(9)),
                    unsignedByteToInt(nonce.get(10)), unsignedByteToInt(nonce.get(11))));

            byte[] temp_key_array = new byte[key_len];

            key.get(temp_key_array);
            key.rewind();

            byte[] temp_nonce_array = new byte[iv_len + salt_len];
            nonce.rewind();
            nonce.get(temp_nonce_array);
            nonce.rewind();

            BPF.getInstance().getBPFLogger().debug(TAG, String.format(
                    "finalize() random key: 0x %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h",
                    unsignedByteToInt(temp_key_array[0]), unsignedByteToInt(temp_key_array[1]),
                    unsignedByteToInt(temp_key_array[2]), unsignedByteToInt(temp_key_array[3]),
                    unsignedByteToInt(temp_key_array[4]), unsignedByteToInt(temp_key_array[5]),
                    unsignedByteToInt(temp_key_array[6]), unsignedByteToInt(temp_key_array[7]),
                    unsignedByteToInt(temp_key_array[8]), unsignedByteToInt(temp_key_array[9]),
                    unsignedByteToInt(temp_key_array[10]), unsignedByteToInt(temp_key_array[11]),
                    unsignedByteToInt(temp_key_array[12]), unsignedByteToInt(temp_key_array[13]),
                    unsignedByteToInt(temp_key_array[14]), unsignedByteToInt(temp_key_array[15])));

            AEADParameters parameters = new AEADParameters(new KeyParameter(temp_key_array), 128,
                    temp_nonce_array, null);
            GCMBlockCipher gcmEngine = new GCMBlockCipher(new AESEngine());
            gcmEngine.init(true, parameters);

            offset = iter.data_offset();
            len = iter.data_length();

            // crypto function
            mutate_func do_crypt = new mutate_func() {

                /**
                 * do_crypt for encryption
                 * 
                 * @param bundle
                 * @param caller_block
                 * @param target_block
                 * @param buf
                 *            (IN/OUT): contains the payload, and after
                 *            encryption, contains the encrypted data.
                 * @param len
                 *            (IN): length to encrypt
                 */
                @Override
                public boolean action(ServlibEventData data) {
                    // initialization
                    mutate_func_event_data do_crypt_data = (mutate_func_event_data) data;

                    int len = do_crypt_data.len();
                    GCMBlockCipher gcmEngine = do_crypt_data.context();
                    System.gc();
                    encMsg = new byte[gcmEngine.getOutputSize(len)];

                    byte[] inMsg = new byte[bundle.payload().length()];
                    bundle.payload().read_data(0, bundle.payload().length(), inMsg);
                    int in_array_off = 0;

                    assert (in_array_off == 0);
                    assert (inMsg.length == len);

                    String key_str = "";
                    for (int i = 0; (i < inMsg.length && i < 10); i++)
                        key_str = new String(key_str + String.format("%2.2h ", unsignedByteToInt(inMsg[i])));

                    BPF.getInstance().getBPFLogger().debug(TAG,
                            "finalize(). Plaintext message (first 10 char max): 0x " + key_str);

                    in_encr_length = inMsg.length;
                    encLen = gcmEngine.processBytes(inMsg, in_array_off, len, encMsg, 0);

                    BPF.getInstance().getBPFLogger().debug(TAG,
                            "Ciphersuite_C3::do_crypt() operation encryption len " + len);

                    return (len > 0) ? true : false;
                }
            };

            iter.owner().mutate(do_crypt, deliberate_const_cast_bundle, block, iter, offset, len, gcmEngine);

            try {
                encLen += gcmEngine.doFinal(encMsg, encLen);
            } catch (Exception e) {
                BPF.getInstance().getBPFLogger().error(TAG, e.toString());
            }

            System.gc();
            String encr_payl = "";
            for (int i = 0; i < in_encr_length && i < 10; i++)
                encr_payl = new String(encr_payl + String.format("%2.2h ", unsignedByteToInt(encMsg[i])));

            BPF.getInstance().getBPFLogger().debug(TAG,
                    "generate(): Encrypted payload using symmetric key (10 char max): 0x " + encr_payl);

            // update payload, swapping the new with the old.
            IByteBuffer temp_buf = new SerializableByteBuffer(in_encr_length);
            for (int i = 0; i < in_encr_length; i++)
                temp_buf.put(encMsg[i]);
            temp_buf.rewind();
            bundle.payload().setIsEncrypted(true);
            bundle.payload()
                    .setFile(new File(bundle.payload().file().getParentFile().getAbsolutePath() + "/"
                            + bundle.payload().file().getName() + "_"
                            + Integer.toString((int) (Math.random() * 10000))));
            bundle.payload().write_data(temp_buf, 0, in_encr_length);

            // need to update the hash list here ?
            // BundleStore.getInstance().updateHash(bundle);

            tag.rewind();
            assert (tag.capacity() == encMsg.length - in_encr_length);
            for (int i = in_encr_length; i < encMsg.length; i++) {
                tag.put(encMsg[i]);
            }

            decMsg_length = encMsg.length;
            encMsg = null;
            System.gc();

            tag.rewind();

            BPF.getInstance().getBPFLogger().debug(TAG, String.format(
                    "finalize(): tag: 0x %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h %2.2h ",
                    unsignedByteToInt(tag.get(0)), unsignedByteToInt(tag.get(1)), unsignedByteToInt(tag.get(2)),
                    unsignedByteToInt(tag.get(3)), unsignedByteToInt(tag.get(4)), unsignedByteToInt(tag.get(5)),
                    unsignedByteToInt(tag.get(6)), unsignedByteToInt(tag.get(7)), unsignedByteToInt(tag.get(8)),
                    unsignedByteToInt(tag.get(9)), unsignedByteToInt(tag.get(10)),
                    unsignedByteToInt(tag.get(11)), unsignedByteToInt(tag.get(12)),
                    unsignedByteToInt(tag.get(13)), unsignedByteToInt(tag.get(14)),
                    unsignedByteToInt(tag.get(15))));
            // get the security-result item, and step over the encrypted key
            // item
            IByteBuffer result_buf = new SerializableByteBuffer(256);
            result_buf = locals.writable_security_result();

            ptr = result_buf;

            rem = result_buf.capacity(); // we save the last position. its
            // the remaining code.
            ptr.rewind();

            long[] value = new long[1];
            SDNV.decode(ptr, ptr.capacity(), value); // type: 3. encoded key
            type = Ciphersuite.ciphersuite_fields_t.get((byte) value[0]);

            if (!(type.equals(Ciphersuite.ciphersuite_fields_t.CS_encoded_key_field)))// FAIL_IF
            {
                if (locals != null)
                    locals.set_proc_flag(proc_flags_t.CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND.getCode());
                BPF.getInstance().getBPFLogger().error(TAG,
                        "finalize(). We should have found CS_encoded_key_field!!");
                return BP_FAIL;
            }

            rem--;
            value = new long[1];
            sdnv_len = SDNV.decode(ptr, rem, value);// length= 2. (512)
            field_len = value[0]; // length of the encrypted key field

            rem -= sdnv_len;

            // We jump the enc_key field.
            ptr.position((int) (ptr.position() + field_len));

            rem -= field_len;

            if (rem != 1 + 1 + tag_len)// FAIL_IF. remaining code should be
            // type-length-value of ICV.
            {
                if (locals != null)
                    locals.set_proc_flag(proc_flags_t.CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND.getCode());
                BPF.getInstance().getBPFLogger().error(TAG, "finalize(). error in if (rem != 1 + 1 + tag_len)");
                return BP_FAIL;
            }

            // we are going to create the tuple type-length-value to update
            // the ICV signature field (which is a security result field) in
            // the first PCB.

            // we create and insert the type into the work buffer.
            ptr.put(ciphersuite_fields_t.CS_C_block_ICV_field.getCode());
            rem--;

            // we insert the tag length into the work buffer

            SDNV.encode(tag_len, ptr);

            rem--;

            // we insert the tag data into the work buffer
            BufferHelper.copy_data(ptr, ptr.position(), tag, 0, tag_len);
            ptr.position(ptr.position() + tag_len);

            // now put the security-result field into the security block
            // binary contents
            // which is block.writable_contents();

            IByteBuffer contents = new SerializableByteBuffer(256);
            ;
            contents = block.writable_contents();
            buf = contents;
            rem = contents.position();

            // buf.position(block.data_offset());// we need to add
            // data_offset as well,

            rem -= block.data_offset(); // since we're pointing at the whole
            // buffer

            buf.position(block.data_offset() + locals.security_result_offset()); // and this offset
            // is just within
            // the data portion
            // of the buffer
            rem -= locals.security_result_offset();

            sdnv_len = SDNV.len(buf); // size of result-length field (sdnv)
            buf.position(buf.position() + sdnv_len); // "step over that length field".
            // (we have already
            // added it in
            // generate() )
            rem -= sdnv_len;
            BufferHelper.copy_data(buf, buf.position(), result_buf, 0, result_buf.position());

            BPF.getInstance().getBPFLogger().debug(TAG, "finalize(). PAYLOAD_BLOCK done");

        }
            break; // break from switch, continue for "for" loop

        default:
            continue;
        } // end of switch
    }
    BPF.getInstance().getBPFLogger().debug(TAG, "finalize() done");

    result = BP_SUCCESS;
    return result;
}