Exemple #1
0
void
OutgoingDataQueue::putData(uint32 stamp, const unsigned char *data, size_t datalen)
{
    if ( !data || !datalen )
        return;

    size_t step = 0, offset = 0;
    while ( offset < datalen ) {
        // remainder and step take care of segmentation
        // according to getMaxSendSegmentSize()
        size_t remainder = datalen - offset;
        step = ( remainder > getMaxSendSegmentSize() ) ?
            getMaxSendSegmentSize() : remainder;

                CryptoContext* pcc = getOutQueueCryptoContext(getLocalSSRC());
                if (pcc == NULL) {
                    pcc = getOutQueueCryptoContext(0);
                    if (pcc != NULL) {
                        pcc = pcc->newCryptoContextForSSRC(getLocalSSRC(), 0, 0L);
                        if (pcc != NULL) {
                            pcc->deriveSrtpKeys(0);
                            setOutQueueCryptoContext(pcc);
                        }
                    }
                }
                OutgoingRTPPkt* packet;
        if ( sendInfo.sendCC )
            packet = new OutgoingRTPPkt(sendInfo.sendSources,15,data + offset,step, sendInfo.paddinglen, pcc);
        else
            packet = new OutgoingRTPPkt(data + offset,step,sendInfo.paddinglen, pcc);

        packet->setPayloadType(getCurrentPayloadType());
        packet->setSeqNum(sendInfo.sendSeq++);
        packet->setTimestamp(stamp + getInitialTimestamp());

        packet->setSSRCNetwork(getLocalSSRCNetwork());
        if ( (0 == offset) && getMark() ) {
            packet->setMarker(true);
            setMark(false);
        } else {
            packet->setMarker(false);
        }
        if (pcc != NULL) {
            packet->protect(getLocalSSRC(), pcc);
        }
        // insert the packet into the "tail" of the sending queue
        sendLock.writeLock();
        OutgoingRTPPktLink *link =
            new OutgoingRTPPktLink(packet,sendLast,NULL);
        if (sendLast)
            sendLast->setNext(link);
        else
            sendFirst = link;
        sendLast = link;
        sendLock.unlock();

        offset += step;
    }
}
Exemple #2
0
bool CtZrtpStream::srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part)
{
    CryptoContext* recvCryptoContext;
    CryptoContext* senderCryptoContext;
    CryptoContextCtrl* recvCryptoContextCtrl;
    CryptoContextCtrl* senderCryptoContextCtrl;

    int cipher;
    int authn;
    int authKeyLen;

    if (secrets->authAlgorithm == Sha1) {
        authn = SrtpAuthenticationSha1Hmac;
        authKeyLen = 20;
    }

    if (secrets->authAlgorithm == Skein) {
        authn = SrtpAuthenticationSkeinHmac;
        authKeyLen = 32;
    }

    if (secrets->symEncAlgorithm == Aes)
        cipher = SrtpEncryptionAESCM;

    if (secrets->symEncAlgorithm == TwoFish)
        cipher = SrtpEncryptionTWOCM;

    role = secrets->role;

    if (part == ForSender) {
        // To encrypt packets: intiator uses initiator keys,
        // responder uses responder keys
        // Create a "half baked" crypto context first and store it. This is
        // the main crypto context for the sending part of the connection.
        if (secrets->role == Initiator) {
            senderCryptoContext = 
                new CryptoContext(0,                                       // SSRC (used for lookup)
                                  0,                                       // Roll-Over-Counter (ROC)
                                  0L,                                      // keyderivation << 48,
                                  cipher,                                  // encryption algo
                                  authn,                                   // authtentication algo
                                  (unsigned char*)secrets->keyInitiator,   // Master Key
                                  secrets->initKeyLen / 8,                 // Master Key length
                                  (unsigned char*)secrets->saltInitiator,  // Master Salt
                                  secrets->initSaltLen / 8,                // Master Salt length
                                  secrets->initKeyLen / 8,                 // encryption keyl
                                  authKeyLen,                              // authentication key len
                                  secrets->initSaltLen / 8,                // session salt len
                                  secrets->srtpAuthTagLen / 8);            // authentication tag lenA
            senderCryptoContextCtrl = 
                new CryptoContextCtrl(0,                                         // SSRC (used for lookup)
                                      cipher,                                    // encryption algo
                                      authn,                                     // authtication algo
                                      (unsigned char*)secrets->keyInitiator,     // Master Key
                                      secrets->initKeyLen / 8,                   // Master Key length
                                      (unsigned char*)secrets->saltInitiator,    // Master Salt
                                      secrets->initSaltLen / 8,                  // Master Salt length
                                      secrets->initKeyLen / 8,                   // encryption keyl
                                      authKeyLen,                                // authentication key len
                                      secrets->initSaltLen / 8,                  // session salt len
                                      secrets->srtpAuthTagLen / 8);              // authentication tag len
        }
        else {
            senderCryptoContext = 
                new CryptoContext(0,                                       // SSRC (used for lookup)
                                  0,                                       // Roll-Over-Counter (ROC)
                                  0L,                                      // keyderivation << 48,
                                  cipher,                                  // encryption algo
                                  authn,                                   // authtentication algo
                                  (unsigned char*)secrets->keyResponder,   // Master Key
                                  secrets->respKeyLen / 8,                 // Master Key length
                                  (unsigned char*)secrets->saltResponder,  // Master Salt
                                  secrets->respSaltLen / 8,                // Master Salt length
                                  secrets->respKeyLen / 8,                 // encryption keyl
                                  authKeyLen,                              // authentication key len
                                  secrets->respSaltLen / 8,                // session salt len
                                  secrets->srtpAuthTagLen / 8);            // authentication tag len
            senderCryptoContextCtrl = 
                new CryptoContextCtrl(0,                                         // SSRC (used for lookup)
                                      cipher,                                    // encryption algo
                                      authn,                                     // authtication algo
                                      (unsigned char*)secrets->keyResponder,     // Master Key
                                      secrets->respKeyLen / 8,                   // Master Key length
                                      (unsigned char*)secrets->saltResponder,    // Master Salt
                                      secrets->respSaltLen / 8,                  // Master Salt length
                                      secrets->respKeyLen / 8,                   // encryption keyl
                                      authKeyLen,                                // authentication key len
                                      secrets->respSaltLen / 8,                  // session salt len
                                      secrets->srtpAuthTagLen / 8);              // authentication tag len
        }
        if (senderCryptoContext == NULL) {
            return false;
        }
        senderCryptoContext->deriveSrtpKeys(0L);
        sendSrtp = senderCryptoContext;

        senderCryptoContextCtrl->deriveSrtcpKeys();
        sendSrtcp = senderCryptoContextCtrl;
    }
    if (part == ForReceiver) {
        // To decrypt packets: intiator uses responder keys,
        // responder initiator keys
        // See comment above.
        if (secrets->role == Initiator) {
            recvCryptoContext = 
                new CryptoContext(0,                                       // SSRC (used for lookup)
                                  0,                                       // Roll-Over-Counter (ROC)
                                  0L,                                      // keyderivation << 48,
                                  cipher,                                  // encryption algo
                                  authn,                                   // authtentication algo
                                  (unsigned char*)secrets->keyResponder,   // Master Key
                                  secrets->respKeyLen / 8,                 // Master Key length
                                  (unsigned char*)secrets->saltResponder,  // Master Salt
                                  secrets->respSaltLen / 8,                // Master Salt length
                                  secrets->respKeyLen / 8,                 // encryption keyl
                                  authKeyLen,                              // authentication key len
                                  secrets->respSaltLen / 8,                // session salt len
                                  secrets->srtpAuthTagLen / 8);            // authentication tag len
            recvCryptoContextCtrl = 
                new CryptoContextCtrl(0,                                         // SSRC (used for lookup)
                                      cipher,                                    // encryption algo
                                      authn,                                     // authtication algo
                                      (unsigned char*)secrets->keyResponder,     // Master Key
                                      secrets->respKeyLen / 8,                   // Master Key length
                                      (unsigned char*)secrets->saltResponder,    // Master Salt
                                      secrets->respSaltLen / 8,                  // Master Salt length
                                      secrets->respKeyLen / 8,                   // encryption keyl
                                      authKeyLen,                                // authentication key len
                                      secrets->respSaltLen / 8,                  // session salt len
                                      secrets->srtpAuthTagLen / 8);              // authentication tag len
        }
        else {
            recvCryptoContext = 
                new CryptoContext(0,                                       // SSRC (used for lookup)
                                  0,                                       // Roll-Over-Counter (ROC)
                                  0L,                                      // keyderivation << 48,
                                  cipher,                                  // encryption algo
                                  authn,                                   // authtentication algo
                                  (unsigned char*)secrets->keyInitiator,   // Master Key
                                  secrets->initKeyLen / 8,                 // Master Key length
                                  (unsigned char*)secrets->saltInitiator,  // Master Salt
                                  secrets->initSaltLen / 8,                // Master Salt length
                                  secrets->initKeyLen / 8,                 // encryption keyl
                                  authKeyLen,                              // authentication key len
                                  secrets->initSaltLen / 8,                // session salt len
                                  secrets->srtpAuthTagLen / 8);            // authentication tag len
            recvCryptoContextCtrl = 
                new CryptoContextCtrl(0,                                         // SSRC (used for lookup)
                                      cipher,                                    // encryption algo
                                      authn,                                     // authtication algo
                                      (unsigned char*)secrets->keyInitiator,     // Master Key
                                      secrets->initKeyLen / 8,                   // Master Key length
                                      (unsigned char*)secrets->saltInitiator,    // Master Salt
                                      secrets->initSaltLen / 8,                  // Master Salt length
                                      secrets->initKeyLen / 8,                   // encryption keyl
                                      authKeyLen,                                // authentication key len
                                      secrets->initSaltLen / 8,                  // session salt len
                                      secrets->srtpAuthTagLen / 8);              // authentication tag len
        }
        if (recvCryptoContext == NULL) {
            return false;
        }
        recvCryptoContext->deriveSrtpKeys(0L);
        recvSrtp = recvCryptoContext;

        recvCryptoContextCtrl->deriveSrtcpKeys();
        recvSrtcp = recvCryptoContextCtrl;

        supressCounter = 0;         // supress SRTP warnings for some packets after we switch to SRTP
    }
    if (zrtpHashMatch && recvSrtp != NULL && sendSrtp != NULL) {
        sdesActive = false;
    }
    return true;
}
Exemple #3
0
size_t
ZrtpQueue::rtpDataPacket(unsigned char* buffer, int32 rtn, InetHostAddress network_address, tpport_t transport_port)
{
     // Special handling of padding to take care of encrypted content.
    // In case of SRTP the padding length field is also encrypted, thus
    // it gives a wrong length. Check and clear padding bit before
    // creating the RTPPacket. Will be set and re-computed after a possible
    // SRTP decryption.
    uint8 padSet = (*buffer & 0x20);
    if (padSet) {
        *buffer = *buffer & ~0x20;          // clear padding bit
    }
    //  build a packet. It will link itself to its source
    IncomingRTPPkt* packet =
        new IncomingRTPPkt(buffer,rtn);

    // Generic header validity check.
    if ( !packet->isHeaderValid() ) {
        delete packet;
        return 0;
    }

    // Look for a CryptoContext for this packet's SSRC
    CryptoContext* pcc = getInQueueCryptoContext(packet->getSSRC());

    // If no crypto context is available for this SSRC but we are already in
    // Secure state then create a CryptoContext for this SSRC.
    // Assumption: every SSRC stream sent via this connection is secured
    // _and_ uses the same crypto parameters.
    if (pcc == NULL) {
        pcc = getInQueueCryptoContext(0);
        if (pcc != NULL) {
            pcc = pcc->newCryptoContextForSSRC(packet->getSSRC(), 0, 0L);
            if (pcc != NULL) {
                pcc->deriveSrtpKeys(0);
                setInQueueCryptoContext(pcc);
            }
        }
    }
    // If no crypto context: then either ZRTP is off or in early state
    // If crypto context is available then unprotect data here. If an error
    // occurs report the error and discard the packet.
    if (pcc != NULL) {
        int32 ret;
        if ((ret = packet->unprotect(pcc)) < 0) {
            if (!onSRTPPacketError(*packet, ret)) {
                delete packet;
                return 0;
            }
        }
        if (started && zrtpEngine->inState(WaitConfAck)) {
            zrtpEngine->conf2AckSecure();
        }
    }

    // virtual for profile-specific validation and processing.
    if (!onRTPPacketRecv(*packet) ) {
        delete packet;
        return 0;
    }
    if (padSet) {
        packet->reComputePayLength(true);
    }
    // get time of arrival
    struct timeval recvtime;
    gettimeofday(&recvtime,NULL);

    bool source_created;
    SyncSourceLink* sourceLink =
            getSourceBySSRC(packet->getSSRC(),source_created);
    SyncSource* s = sourceLink->getSource();
    if ( source_created ) {
        // Set data transport address.
        setDataTransportPort(*s,transport_port);
        // Network address is assumed to be the same as the control one
        setNetworkAddress(*s,network_address);
        sourceLink->initStats();
        // First packet arrival time.
        sourceLink->setInitialDataTime(recvtime);
        sourceLink->setProbation(getMinValidPacketSequence());
        if ( sourceLink->getHello() )
            onNewSyncSource(*s);
    }
    else if ( 0 == s->getDataTransportPort() ) {
        // Test if RTCP packets had been received but this is the
        // first data packet from this source.
        setDataTransportPort(*s,transport_port);
    }

    // Before inserting in the queue,
    // 1) check for collisions and loops. If the packet cannot be
    //    assigned to a source, it will be rejected.
    // 2) check the source is a sufficiently well known source
    // TODO: also check CSRC identifiers.
    if (checkSSRCInIncomingRTPPkt(*sourceLink, source_created,
        network_address, transport_port) &&
        recordReception(*sourceLink,*packet,recvtime) ) {
        // now the packet link is linked in the queues
        IncomingRTPPktLink* packetLink = new IncomingRTPPktLink(packet, sourceLink, recvtime,
                                       packet->getTimestamp() - sourceLink->getInitialDataTimestamp(),
                                       NULL,NULL,NULL,NULL);
        insertRecvPacket(packetLink);
    } else {
        // must be discarded due to collision or loop or
        // invalid source
        delete packet;
        return 0;
    }
    // Start the ZRTP engine after we got a at least one RTP packet and
    // sent some as well or we are in multi-stream mode.
    if (!started && enableZrtp) {
        startZrtp();
    }
    return rtn;
}