List of usage examples for org.bouncycastle.crypto.modes GCMBlockCipher getOutputSize
public int getOutputSize(int len)
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"); }/* w ww . jav a 2 s.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 (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"); }/* ww w . j a va 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 (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]//from ww w . j a v a 2 s .c o 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 w w w . j a v a 2 s . c om*/ * 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; }