Search in sources :

Example 1 with OtrTlvHandler

use of net.java.otr4j.crypto.OtrTlvHandler in project Zom-Android by zom.

the class SessionImpl method handleDataMessage.

private synchronized String handleDataMessage(DataMessage data, List<TLV> tlvs) throws OtrException {
    if (DEBUG_ENABLED)
        Log.d(LOG_TAG, getSessionID().getLocalUserId() + " received a data message from " + getSessionID().getRemoteUserId() + ".");
    switch(this.getSessionStatus()) {
        case ENCRYPTED:
            if (DEBUG_ENABLED)
                Log.d(LOG_TAG, "Message state is ENCRYPTED. Trying to decrypt message.");
            // Find matching session keys.
            int senderKeyID = data.senderKeyID;
            int receipientKeyID = data.recipientKeyID;
            SessionKeys matchingKeys = this.getSessionKeysByID(receipientKeyID, senderKeyID);
            if (matchingKeys == null) {
                throw new OtrException("no matching keys found");
            }
            // Verify received MAC with a locally calculated MAC.
            if (DEBUG_ENABLED)
                Log.d(LOG_TAG, "Transforming T to byte[] to calculate it's HmacSHA1.");
            byte[] serializedT;
            try {
                serializedT = SerializationUtils.toByteArray(data.getT());
            } catch (IOException e) {
                throw new OtrException(e);
            }
            OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
            byte[] computedMAC = otrCryptoEngine.sha1Hmac(serializedT, matchingKeys.getReceivingMACKey(), SerializationConstants.TYPE_LEN_MAC);
            String decryptedMsgContent = null;
            if (!Arrays.equals(computedMAC, data.mac)) {
                // throw new OtrException("MAC verification failed, ignoring message");
                if (DEBUG_ENABLED)
                    Log.d(LOG_TAG, "MAC verification failed, ignoring message");
            } else {
                if (DEBUG_ENABLED)
                    Log.d(LOG_TAG, "Computed HmacSHA1 value matches sent one.");
                // Mark this MAC key as old to be revealed.
                matchingKeys.setIsUsedReceivingMACKey(true);
                matchingKeys.setReceivingCtr(data.ctr);
                byte[] dmc = otrCryptoEngine.aesDecrypt(matchingKeys.getReceivingAESKey(), matchingKeys.getReceivingCtr(), data.encryptedMessage);
                try {
                    // Expect bytes to be text encoded in UTF-8.
                    decryptedMsgContent = new String(dmc, "UTF-8");
                    if (DEBUG_ENABLED)
                        Log.d(LOG_TAG, "Decrypted message: \"" + decryptedMsgContent + "\"");
                    // Handle TLVs
                    if (tlvs == null) {
                        tlvs = new ArrayList<TLV>();
                    }
                    int tlvIndex = decryptedMsgContent.indexOf((char) 0x0);
                    if (tlvIndex > -1) {
                        decryptedMsgContent = decryptedMsgContent.substring(0, tlvIndex);
                        tlvIndex++;
                        byte[] tlvsb = new byte[dmc.length - tlvIndex];
                        System.arraycopy(dmc, tlvIndex, tlvsb, 0, tlvsb.length);
                        ByteArrayInputStream tin = new ByteArrayInputStream(tlvsb);
                        while (tin.available() > 0) {
                            int type;
                            byte[] tdata;
                            OtrInputStream eois = new OtrInputStream(tin);
                            try {
                                type = eois.readShort();
                                tdata = eois.readTlvData();
                                eois.close();
                            } catch (IOException e) {
                                throw new OtrException(e);
                            }
                            tlvs.add(new TLV(type, tdata));
                        }
                    }
                    if (tlvs.size() > 0) {
                        for (TLV tlv : tlvs) {
                            switch(tlv.getType()) {
                                case TLV.DISCONNECTED:
                                    this.setSessionStatus(SessionStatus.FINISHED);
                                    return null;
                                default:
                                    for (OtrTlvHandler handler : tlvHandlers) {
                                        handler.processTlv(tlv);
                                    }
                            }
                        }
                    }
                } catch (UnsupportedEncodingException e) {
                    // throw new OtrException(e);
                    if (DEBUG_ENABLED)
                        Log.e(LOG_TAG, "unsupported encoding exception", e);
                }
            }
            // Rotate keys if necessary.
            SessionKeys mostRecent = this.getMostRecentSessionKeys();
            if (mostRecent.getLocalKeyID() == receipientKeyID)
                this.rotateLocalSessionKeys();
            if (mostRecent.getRemoteKeyID() == senderKeyID)
                this.rotateRemoteSessionKeys(data.nextDH);
            return decryptedMsgContent;
        case FINISHED:
        case PLAINTEXT:
            showError("Unreadable encrypted message was received.");
            refreshSession();
            // "You sent me an unreadable encrypted message"));
            throw new OtrException("Unreadable encrypted message received");
    }
    return null;
}
Also used : OtrInputStream(net.java.otr4j.io.OtrInputStream) UnsupportedEncodingException(java.io.UnsupportedEncodingException) OtrException(net.java.otr4j.OtrException) IOException(java.io.IOException) OtrCryptoEngine(net.java.otr4j.crypto.OtrCryptoEngine) ByteArrayInputStream(java.io.ByteArrayInputStream) OtrTlvHandler(net.java.otr4j.crypto.OtrTlvHandler) OtrCryptoEngineImpl(net.java.otr4j.crypto.OtrCryptoEngineImpl)

Aggregations

ByteArrayInputStream (java.io.ByteArrayInputStream)1 IOException (java.io.IOException)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 OtrException (net.java.otr4j.OtrException)1 OtrCryptoEngine (net.java.otr4j.crypto.OtrCryptoEngine)1 OtrCryptoEngineImpl (net.java.otr4j.crypto.OtrCryptoEngineImpl)1 OtrTlvHandler (net.java.otr4j.crypto.OtrTlvHandler)1 OtrInputStream (net.java.otr4j.io.OtrInputStream)1