Fix F8 crypto mode and change handling of secret SRTP key data.

These modifications remove unnecessary copying of SRTP key data and overwrite the key data right
after secure state was reached (in ZRTP lib). This makes it harder to extract secret key data in memory dumps.
cusax-fix
Werner Dittmann 14 years ago
parent 6978a3eed6
commit 6da252fb4e

@ -26,6 +26,8 @@
*/
package net.java.sip.communicator.impl.neomedia.transform.srtp;
import java.util.Arrays;
import net.java.sip.communicator.impl.neomedia.*;
import org.bouncycastle.crypto.digests.SHA1Digest;
@ -208,22 +210,22 @@ public SRTCPCryptoContext(long ssrcIn,
saltKey = null;
break;
case SRTPPolicy.AESF8_ENCRYPTION:
cipherF8 = new AESFastEngine();
case SRTPPolicy.AESCM_ENCRYPTION:
cipher = new AESFastEngine();
encKey = new byte[this.policy.getEncKeyLength()];
saltKey = new byte[this.policy.getSaltKeyLength()];
case SRTPPolicy.AESF8_ENCRYPTION:
cipherF8 = new AESFastEngine();
saltKey = new byte[this.policy.getSaltKeyLength()];
break;
case SRTPPolicy.TWOFISHF8_ENCRYPTION:
cipherF8 = new TwofishEngine();
case SRTPPolicy.TWOFISH_ENCRYPTION:
cipher = new TwofishEngine();
encKey = new byte[this.policy.getEncKeyLength()];
saltKey = new byte[this.policy.getSaltKeyLength()];
case SRTPPolicy.TWOFISHF8_ENCRYPTION:
cipherF8 = new TwofishEngine();
break;
}
@ -499,7 +501,7 @@ public void processPacketAESF8(RawPacket pkt, int index)
SRTPCipherF8.process(cipher, pkt.getBuffer(),
pkt.getOffset() + payloadOffset,
payloadLength, ivStore, encKey, saltKey, cipherF8);
payloadLength, ivStore, cipherF8);
}
/**
@ -596,8 +598,9 @@ public void deriveSrtcpKeys()
KeyParameter encryptionKey = new KeyParameter(masterKey);
cipher.init(true, encryptionKey);
cipherCtr.getCipherStream(cipher, encKey,
policy.getEncKeyLength(), ivStore);
Arrays.fill(masterKey, (byte)0);
cipherCtr.getCipherStream(cipher, encKey, policy.getEncKeyLength(), ivStore);
if (authKey != null)
{
@ -622,16 +625,20 @@ public void deriveSrtcpKeys()
break;
}
}
Arrays.fill(authKey, (byte)0);
// compute the session salt
label = 5;
computeIv(label);
cipherCtr.getCipherStream(cipher, saltKey,
policy.getSaltKeyLength(), ivStore);
cipherCtr.getCipherStream(cipher, saltKey, policy.getSaltKeyLength(), ivStore);
Arrays.fill(masterSalt, (byte)0);
// As last step: initialize cipher with derived encryption key.
if (cipherF8 != null)
SRTPCipherF8.deriveForIV(cipherF8, encKey, saltKey);
encryptionKey = new KeyParameter(encKey);
cipher.init(true, encryptionKey);
Arrays.fill(encKey, (byte)0);
}

@ -55,6 +55,7 @@
* We use AESCipher to handle basic AES encryption / decryption.
*
* @author Bing SU (nova.su@gmail.com)
* @author Werner Dittmann <werner.dittmann@t-online.de>
*/
public class SRTPCipherF8
{
@ -74,16 +75,8 @@ class F8Context
long J;
}
public static void process(BlockCipher cipher, byte[] data, int off,
int len, byte[] iv, byte[] key, byte[] salt, BlockCipher f8Cipher)
public static void deriveForIV(BlockCipher f8Cipher, byte[] key, byte[] salt)
{
F8Context f8ctx = new SRTPCipherF8().new F8Context();
/*
* Get memory for the derived IV (IV')
*/
f8ctx.ivAccent = new byte[BLKLEN];
/*
* Get memory for the special key. This is the key to compute the
* derived IV (IV').
@ -111,13 +104,24 @@ public static void process(BlockCipher cipher, byte[] data, int off,
*/
KeyParameter encryptionKey = new KeyParameter(maskedKey);
f8Cipher.init(true, encryptionKey);
saltMask = null;
maskedKey = null;
}
public static void process(BlockCipher cipher, byte[] data, int off, int len,
byte[] iv, BlockCipher f8Cipher)
{
F8Context f8ctx = new SRTPCipherF8().new F8Context();
/*
* Get memory for the derived IV (IV')
*/
f8ctx.ivAccent = new byte[BLKLEN];
/*
* Use the masked key to encrypt the original IV to produce IV'.
* Use the derived IV encryption setup to encrypt the original IV to produce IV'.
*/
f8Cipher.processBlock(iv, 0, f8ctx.ivAccent, 0);
saltMask = null;
maskedKey = null;
f8ctx.J = 0; // initialize the counter
f8ctx.S = new byte[BLKLEN]; // get the key stream buffer
@ -138,7 +142,7 @@ public static void process(BlockCipher cipher, byte[] data, int off,
processBlock(cipher, f8ctx, data, off, data, off, inLen);
}
}
/**
* Encrypt / Decrypt a block using F8 Mode AES algorithm, read len bytes
* data from in at inOff and write the output into out at outOff
@ -157,7 +161,7 @@ public static void process(BlockCipher cipher, byte[] data, int off,
* length of the input data
*/
private static void processBlock(BlockCipher cipher, F8Context f8ctx,
byte[] in, int inOff, byte[] out, int outOff, int len)
byte[] in, int inOff, byte[] out, int outOff, int len)
{
/*
* XOR the previous key stream with IV'

@ -26,6 +26,8 @@
*/
package net.java.sip.communicator.impl.neomedia.transform.srtp;
import java.util.Arrays;
import net.java.sip.communicator.impl.neomedia.*;
import org.bouncycastle.crypto.*;
@ -256,23 +258,23 @@ public SRTPCryptoContext(long ssrcIn, int rocIn, long kdr,
saltKey = null;
break;
case SRTPPolicy.AESF8_ENCRYPTION:
cipherF8 = new AESFastEngine();
//$FALL-THROUGH$
case SRTPPolicy.AESCM_ENCRYPTION:
cipher = new AESFastEngine();
encKey = new byte[policy.getEncKeyLength()];
saltKey = new byte[policy.getSaltKeyLength()];
//$FALL-THROUGH$
case SRTPPolicy.AESF8_ENCRYPTION:
cipherF8 = new AESFastEngine();
break;
case SRTPPolicy.TWOFISHF8_ENCRYPTION:
cipherF8 = new TwofishEngine();
case SRTPPolicy.TWOFISH_ENCRYPTION:
cipher = new TwofishEngine();
encKey = new byte[this.policy.getEncKeyLength()];
saltKey = new byte[this.policy.getSaltKeyLength()];
case SRTPPolicy.TWOFISHF8_ENCRYPTION:
cipherF8 = new TwofishEngine();
break;
}
@ -553,9 +555,8 @@ public void processPacketAESF8(RawPacket pkt)
final int payloadOffset = pkt.getHeaderLength();
final int payloadLength = pkt.getPayloadLength();
SRTPCipherF8.process(cipher, pkt.getBuffer(), pkt.getOffset() +
payloadOffset, payloadLength, ivStore, encKey, saltKey,
cipherF8);
SRTPCipherF8.process(cipher, pkt.getBuffer(), pkt.getOffset() + payloadOffset,
payloadLength, ivStore, cipherF8);
}
/**
@ -675,8 +676,9 @@ public void deriveSrtpKeys(long index)
KeyParameter encryptionKey = new KeyParameter(masterKey);
cipher.init(true, encryptionKey);
cipherCtr.getCipherStream(cipher, encKey, policy.getEncKeyLength(),
ivStore);
Arrays.fill(masterKey, (byte)0);
cipherCtr.getCipherStream(cipher, encKey, policy.getEncKeyLength(), ivStore);
// compute the session authentication key
if (authKey != null)
@ -702,15 +704,20 @@ public void deriveSrtpKeys(long index)
break;
}
}
Arrays.fill(authKey, (byte)0);
// compute the session salt
label = 0x02;
computeIv(label, index);
cipherCtr.getCipherStream(cipher, saltKey, policy.getSaltKeyLength(),
ivStore);
cipherCtr.getCipherStream(cipher, saltKey, policy.getSaltKeyLength(), ivStore);
Arrays.fill(masterSalt, (byte)0);
// As last step: initialize cipher with derived encryption key.
if (cipherF8 != null)
SRTPCipherF8.deriveForIV(cipherF8, encKey, saltKey);
encryptionKey = new KeyParameter(encKey);
cipher.init(true, encryptionKey);
Arrays.fill(encKey, (byte)0);
}
/**

@ -20,26 +20,6 @@
public class SRTPTransformEngine
implements TransformEngine
{
/**
* Master key of this SRTP session
*/
private final byte[] masterKey;
/**
* Master salt key of this SRTP session
*/
private final byte[] masterSalt;
/**
* SRTP processing policy
*/
private final SRTPPolicy srtpPolicy;
/**
* SRTCP processing policy
*/
private final SRTPPolicy srtcpPolicy;
/**
* The default SRTPCryptoContext, which will be used to derivate other
* contexts.
@ -64,23 +44,15 @@ public class SRTPTransformEngine
public SRTPTransformEngine(byte[] masterKey, byte[] masterSalt,
SRTPPolicy srtpPolicy, SRTPPolicy srtcpPolicy)
{
this.masterKey = new byte[masterKey.length];
System.arraycopy(masterKey, 0, this.masterKey, 0, masterKey.length);
this.masterSalt = new byte[masterSalt.length];
System.arraycopy(masterSalt, 0, this.masterSalt, 0, masterSalt.length);
this.srtpPolicy = srtpPolicy;
this.srtcpPolicy = srtcpPolicy;
this.defaultContext = new SRTPCryptoContext(0, 0, 0,
this.masterKey,
this.masterSalt,
this.srtpPolicy);
masterKey,
masterSalt,
srtpPolicy);
this.defaultContextControl = new SRTCPCryptoContext(0,
this.masterKey,
this.masterSalt,
this.srtcpPolicy);
masterKey,
masterSalt,
srtcpPolicy);
}
/**
@ -103,46 +75,6 @@ public PacketTransformer getRTPTransformer()
return new SRTPTransformer(this);
}
/**
* Get the master encryption key
*
* @return the master encryption key
*/
public byte[] getMasterKey()
{
return this.masterKey;
}
/**
* Get the master salt key
*
* @return the master salt key
*/
public byte[] getMasterSalt()
{
return this.masterSalt;
}
/**
* Get the SRTCP policy
*
* @return the SRTCP policy
*/
public SRTPPolicy getSRTCPPolicy()
{
return this.srtcpPolicy;
}
/**
* Get the SRTP policy
*
* @return the SRTP policy
*/
public SRTPPolicy getSRTPPolicy()
{
return this.srtpPolicy;
}
/**
* Get the default SRTPCryptoContext
*

Loading…
Cancel
Save