All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jitsi.srtp.BaseSrtpCryptoContext Maven / Gradle / Ivy

/*
 * Copyright @ 2015 - present 8x8, Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Some of the code in this class is derived from ccRtp's SRTP implementation,
 * which has the following copyright notice:
 *
 * Copyright (C) 2004-2006 the Minisip Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
*/
package org.jitsi.srtp;

import java.security.*;
import javax.crypto.*;
import org.jitsi.srtp.crypto.*;
import org.jitsi.utils.*;
import org.jitsi.utils.logging2.*;

/**
 * SrtpCryptoContext class is the core class of SRTP implementation. There can
 * be multiple SRTP sources in one SRTP session. And each SRTP stream has a
 * corresponding SrtpCryptoContext object, identified by SSRC. In this way,
 * different sources can be protected independently.
 *
 * SrtpCryptoContext class acts as a manager class and maintains all the
 * information used in SRTP transformation. It is responsible for deriving
 * encryption/salting/authentication keys from master keys. And it will invoke
 * certain class to encrypt/decrypt (transform/reverse transform) RTP packets.
 * It will hold a replay check db and do replay check against incoming packets.
 *
 * Refer to section 3.2 in RFC3711 for detailed description of cryptographic
 * context.
 *
 * Cryptographic related parameters, i.e. encryption mode / authentication mode,
 * master encryption key and master salt key are determined outside the scope of
 * SRTP implementation. They can be assigned manually, or can be assigned
 * automatically using some key management protocol, such as MIKEY (RFC3830),
 * SDES (RFC4568) or Phil Zimmermann's ZRTP protocol (RFC6189).
 *
 * @author Bing SU ([email protected])
 * @author Lyubomir Marinov
 */
public class BaseSrtpCryptoContext
{
    /**
     * The replay check windows size.
     */
    protected static final long REPLAY_WINDOW_SIZE = 64;

    /**
     * Cipher to encrypt packets.
     */
    protected final SrtpCipher cipher;

    /**
     * Temp store.
     */
    protected final byte[] ivStore;

    /**
     * The HMAC object we used to do packet authentication
     */
    protected final Mac mac; // used for various HMAC computations

    /**
     * Encryption / Authentication policy for this session
     */
    protected final SrtpPolicy policy;

    /**
     * Temp store.
     */
    protected final byte[] rbStore = new byte[4];

    /**
     * Bit mask for replay check
     */
    protected long replayWindow;

    /**
     * Derived session salting key
     */
    protected final byte[] saltKey;

    /**
     * RTP/RTCP SSRC of this cryptographic context
     */
    protected final int ssrc;

    /**
     * this is a working store, used by some methods to avoid new operations
     * the methods must use this only to store results for immediate processing
     */
    protected final byte[] tempStore = new byte[100];

    /**
     * Logger for BaseSrtpCryptoContext and derived objects.
     */
    protected final Logger logger;

    protected BaseSrtpCryptoContext(
            int ssrc,
            byte[] masterK,
            byte[] masterS,
            SrtpPolicy policy,
            Logger parentLogger)
        throws GeneralSecurityException
    {
        logger = parentLogger.createChildLogger(this.getClass().getName());
        this.ssrc = ssrc;
        this.policy = policy;

        int encKeyLength = policy.getEncKeyLength();

        if (masterK != null)
        {
            if (masterK.length != encKeyLength)
            {
                throw new IllegalArgumentException("masterK.length != encKeyLength");
            }
        }
        else
        {
            if (encKeyLength != 0)
            {
                throw new IllegalArgumentException("null masterK but encKeyLength != 0");
            }
        }
        int saltKeyLength = policy.getSaltKeyLength();

        if (masterS != null)
        {
            if (masterS.length != saltKeyLength)
            {
                throw new IllegalArgumentException("masterS.length != saltKeyLength");
            }
        }
        else
        {
            if (saltKeyLength != 0)
            {
                throw new IllegalArgumentException("null masterS but saltKeyLength != 0");
            }
        }

        saltKey = new byte[saltKeyLength];
        int ivSize = 16;
        switch (policy.getEncType())
        {
        case SrtpPolicy.AESCM_ENCRYPTION:
            cipher = new SrtpCipherCtr(Aes.createCipher("AES/CTR/NoPadding"));
            break;
        case SrtpPolicy.AESGCM_ENCRYPTION:
            if (policy.getAuthTagLength() != 16)
            {
                throw new IllegalArgumentException("SRTP only supports 16-octet GCM auth tags");
            }
            cipher = new SrtpCipherGcm(Aes.createCipher("AES/GCM/NoPadding"));
            ivSize = 12;
            break;
        case SrtpPolicy.AESF8_ENCRYPTION:
            cipher = new SrtpCipherF8(Aes.createCipher("AES/ECB/NoPadding"));
            break;
        case SrtpPolicy.TWOFISHF8_ENCRYPTION:
            cipher = new SrtpCipherF8(Cipher.getInstance("Twofish/ECB/NoPadding"));
            break;
        case SrtpPolicy.TWOFISH_ENCRYPTION:
            cipher = new SrtpCipherCtr(Cipher.getInstance("Twofish/CTR/NoPadding"));
            break;
        case SrtpPolicy.NULL_ENCRYPTION:
        default:
            cipher = null;
            ivSize = 0;
            break;
        }

        ivStore = new byte[ivSize];

        Mac mac;
        switch (policy.getAuthType())
        {
        case SrtpPolicy.HMACSHA1_AUTHENTICATION:
            mac = HmacSha1.createMac(parentLogger);
            break;

        case SrtpPolicy.SKEIN_AUTHENTICATION:
            mac = Mac.getInstance("SkeinMac_512_" + (policy.getAuthTagLength() * 8));
            break;

        case SrtpPolicy.NULL_AUTHENTICATION:
        default:
            mac = null;
            break;
        }
        this.mac = mac;
    }


    /**
     * Writes roc / index to the rbStore buffer.
     */
    protected void writeRoc(int rocIn)
    {
        rbStore[0] = (byte) (rocIn >> 24);
        rbStore[1] = (byte) (rocIn >> 16);
        rbStore[2] = (byte) (rocIn >> 8);
        rbStore[3] = (byte) rocIn;
    }

    /**
     * Authenticates a packet.
     *
     * @param pkt the RTP packet to be authenticated
     * @param rocIn Roll-Over-Counter
     */
    synchronized protected byte[] authenticatePacketHmac(ByteArrayBuffer pkt, int rocIn)
    {
        mac.update(pkt.getBuffer(), pkt.getOffset(), pkt.getLength());
        writeRoc(rocIn);
        mac.update(rbStore, 0, rbStore.length);
        return mac.doFinal();
    }

    /**
     * Gets the authentication tag length of this SRTP cryptographic context
     *
     * @return the authentication tag length of this SRTP cryptographic context
     */
    public int getAuthTagLength()
    {
        return policy.getAuthTagLength();
    }

    /**
     * Gets the SSRC of this SRTP cryptographic context
     *
     * @return the SSRC of this SRTP cryptographic context
     */
    public int getSsrc()
    {
        return ssrc;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy