Exemple #1
1
err_status_t
srtp_validate() {
  unsigned char test_key[30] = {
    0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0,
    0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39,
    0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
    0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
  };
  uint8_t srtp_plaintext_ref[28] = {
    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
    0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
    0xab, 0xab, 0xab, 0xab
  };
  uint8_t srtp_plaintext[38] = {
    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
    0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
    0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };
  uint8_t srtp_ciphertext[38] = {
    0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 
    0xca, 0xfe, 0xba, 0xbe, 0x4e, 0x55, 0xdc, 0x4c,
    0xe7, 0x99, 0x78, 0xd8, 0x8c, 0xa4, 0xd2, 0x15, 
    0x94, 0x9d, 0x24, 0x02, 0xb7, 0x8d, 0x6a, 0xcc,
    0x99, 0xea, 0x17, 0x9b, 0x8d, 0xbb
  };
  srtp_t srtp_snd, srtp_recv;
  err_status_t status;
  int len;
  srtp_policy_t policy;
  
  /*
   * create a session with a single stream using the default srtp
   * policy and with the SSRC value 0xcafebabe
   */
  crypto_policy_set_rtp_default(&policy.rtp);
  crypto_policy_set_rtcp_default(&policy.rtcp);
  policy.ssrc.type  = ssrc_specific;
  policy.ssrc.value = 0xcafebabe;
  policy.key  = test_key;
  policy.next = NULL;

  status = srtp_create(&srtp_snd, &policy);
  if (status)
    return status;
 
  /* 
   * protect plaintext, then compare with ciphertext 
   */
  len = 28;
  status = srtp_protect(srtp_snd, srtp_plaintext, &len);
  if (status || (len != 38))
    return err_status_fail;

  debug_print(mod_driver, "ciphertext:\n  %s", 	      
	      octet_string_hex_string(srtp_plaintext, len));
  debug_print(mod_driver, "ciphertext reference:\n  %s", 	      
	      octet_string_hex_string(srtp_ciphertext, len));

  if (octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len))
    return err_status_fail;
  
  /*
   * create a receiver session context comparable to the one created
   * above - we need to do this so that the replay checking doesn't
   * complain
   */
  status = srtp_create(&srtp_recv, &policy);
  if (status)
    return status;

  /*
   * unprotect ciphertext, then compare with plaintext 
   */
  status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
  if (status || (len != 28))
    return status;
  
  if (octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len))
    return err_status_fail;

  return err_status_ok;
}
Exemple #2
0
/*
 * This callback is called by transport when incoming rtp is received
 */
static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size)
{
    transport_srtp *srtp = (transport_srtp *) user_data;
    int len = size;
    err_status_t err;

    if (srtp->bypass_srtp) {
	srtp->rtp_cb(srtp->user_data, pkt, size);
	return;
    }

    if (size < 0 || !srtp->session_inited) {
	return;
    }

    /* Make sure buffer is 32bit aligned */
    PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return );

    if (srtp->probation_cnt > 0)
	--srtp->probation_cnt;

    pj_lock_acquire(srtp->mutex);

    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);

    if (srtp->probation_cnt > 0 && 
	(err == err_status_replay_old || err == err_status_replay_fail)) 
    {
	/* Handle such condition that stream is updated (RTP seq is reinited
	* & SRTP is restarted), but some old packets are still coming 
	* so SRTP is learning wrong RTP seq. While the newly inited RTP seq
	* comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect() 
	* will returning err_status_replay_*. Restarting SRTP can resolve 
	* this.
	*/
	if (pjmedia_transport_srtp_start((pjmedia_transport*)srtp, 
					 &srtp->tx_policy, &srtp->rx_policy) 
					 != PJ_SUCCESS)
	{
	    PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s", 
		      get_libsrtp_errstr(err)));
	} else {
	    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
	}
    }

    if (err == err_status_ok) {
	srtp->rtp_cb(srtp->user_data, pkt, len);
    } else {
	PJ_LOG(5,(srtp->pool->obj_name, 
		  "Failed to unprotect SRTP, pkt size=%d, err=%s", 
		  size, get_libsrtp_errstr(err)));
    }

    pj_lock_release(srtp->mutex);
}
unsigned int rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len) {
    int octets_recvd;
    err_status_t stat;

    octets_recvd = recvfrom(receiver->socket, (void *) &receiver->message,
            *len, 0, (struct sockaddr *) NULL, 0);

    /* verify rtp header */
    if (receiver->message.header.version != 2) {
        *len = 0;
        return -1;
    }

#if PRINT_DEBUG
    fprintf(stderr, "%d octets received from SSRC %u\n",
            octets_recvd, receiver->message.header.ssrc);
#endif
#if VERBOSE_DEBUG
    srtp_print_packet(&receiver->message.header, octets_recvd);
#endif

    /* apply srtp */
    stat = srtp_unprotect(receiver->srtp_ctx, &receiver->message.header,
            &octets_recvd);
    if (stat) {
        fprintf(stderr, "error: srtp unprotection failed with code %d%s\n",
                stat, stat == err_status_replay_fail ? " (replay check failed)"
                        : stat == err_status_auth_fail ? " (auth check failed)"
                                : "");
        return -1;
    }
    strncpy(msg, receiver->message.body, octets_recvd);

    return octets_recvd;
}
Exemple #4
0
static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){
	srtp_t srtp=(srtp_t)t->data;
	int err;
	int slen;
	err=recvfrom(t->session->rtp.socket,m->b_wptr,m->b_datap->db_lim-m->b_datap->db_base,flags,from,fromlen);
	if (err>0){

		/* keep NON-RTP data unencrypted */
		rtp_header_t *rtp;
		if (err>=RTP_FIXED_HEADER_SIZE)
		{
			rtp = (rtp_header_t*)m->b_wptr;
			if (rtp->version!=2)
			{
				return err;
			}
		}

		slen=err;
		if (srtp_unprotect(srtp,m->b_wptr,&slen)==err_status_ok)
			return slen;
		else {
			ortp_error("srtp_unprotect() failed");
			return -1;
		}
	}
	return err;
}
Exemple #5
0
/* Utility */
PJ_DEF(pj_status_t) pjmedia_transport_srtp_decrypt_pkt(pjmedia_transport *tp,
						       pj_bool_t is_rtp,
						       void *pkt,
						       int *pkt_len)
{
    transport_srtp *srtp = (transport_srtp *)tp;
    err_status_t err;

    if (srtp->bypass_srtp)
	return PJ_SUCCESS;

    PJ_ASSERT_RETURN(tp && pkt && (*pkt_len>0), PJ_EINVAL);
    PJ_ASSERT_RETURN(srtp->session_inited, PJ_EINVALIDOP);

    /* Make sure buffer is 32bit aligned */
    PJ_ASSERT_ON_FAIL( (((long)pkt) & 0x03)==0, return PJ_EINVAL);

    pj_lock_acquire(srtp->mutex);

    if (is_rtp)
	err = srtp_unprotect(srtp->srtp_rx_ctx, pkt, pkt_len);
    else
	err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, pkt, pkt_len);
    
    if (err != err_status_ok) {
	PJ_LOG(5,(srtp->pool->obj_name, 
		  "Failed to unprotect SRTP, pkt size=%d, err=%s", 
		  *pkt_len, get_libsrtp_errstr(err)));
    }

    pj_lock_release(srtp->mutex);

    return (err==err_status_ok) ? PJ_SUCCESS : PJMEDIA_ERRNO_FROM_LIBSRTP(err);
}
Exemple #6
0
static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg)
{
	struct menc_st *st = arg;
	err_status_t e;
	int len;
	(void)src;

	if (!st->use_srtp || !is_rtp_or_rtcp(mb))
		return false;

	len = (int)mbuf_get_left(mb);

	if (is_rtcp_packet(mb)) {
		e = srtp_unprotect_rtcp(st->srtp_rx, mbuf_buf(mb), &len);
	}
	else {
		e = srtp_unprotect(st->srtp_rx, mbuf_buf(mb), &len);
	}

	if (e != err_status_ok) {
		DEBUG_WARNING("recv: failed to unprotect %s-packet"
			      " with %d bytes (%H)\n",
			      is_rtcp_packet(mb) ? "RTCP" : "RTP",
			      len, errstatus_print, e);
		return true;   /* error - drop packet */
	}

	mbuf_set_end(mb, mb->pos + len);

	return false;  /* continue processing */
}
Exemple #7
0
int
evrb_decrypt(void* distant_ctx, void* data, size_t* len)
{
#ifdef USE_SRTP
	if (distant_ctx == NULL || ((EVRB_CRYPTO*)distant_ctx)->srtp_session == NULL)
	  return -1;
	if(srtp_unprotect(((EVRB_CRYPTO*)distant_ctx)->srtp_session, data, (int*)len))
		return -1;
#endif
	return 0;
}
Exemple #8
0
srtpw_err_status_t srtpw_srtp_unprotect(srtpw_srtp *srtp, void *buf, int *len, int rtcp)
{
    int res;

    if ((res = rtcp ? srtp_unprotect_rtcp((srtp_t)srtp, buf, len) : 
         srtp_unprotect((srtp_t)srtp, buf, len)) != err_status_ok && res != err_status_replay_fail)
    {
        srtpw_log(err_level_debug, "SRTP unprotect: failed :%d \n", res);
        return -1;
    }
    return *len;
}
JNIEXPORT jint JNICALL Java_org_theonionphone_protocol_SrtpUnwrapper_unwrapPacketNative
	(JNIEnv *env, jobject obj, jbyteArray packet) {

	jbyte* packetNative = (*env)->GetPrimitiveArrayCritical(env, packet, NULL);
	if(packetNative == NULL) {
		return 1;
	}

	int packetLength = srtpPacketSize;
	err_status_t status = srtp_unprotect((*srtpContextRecv), packetNative, &packetLength);

	(*env)->ReleasePrimitiveArrayCritical(env, packet, packetNative, 0);
	return status;
}
Exemple #10
0
int SrtpChannel::unprotectRtp(char* buffer, int *len) {

    if (!active_)
        return 0;
    int val = srtp_unprotect(receive_session_, (char*) buffer, len);
    if (val == 0) {
        return 0;
    } else {
    rtcpheader* head = reinterpret_cast<rtcpheader*>(buffer);
    rtpheader* headrtp = reinterpret_cast<rtpheader*>(buffer);
        ELOG_WARN("Error SrtpChannel::unprotectRtp %u packettype %d pt %d", val,head->packettype, headrtp->payloadtype);
        return -1;
    }
}
Exemple #11
0
void
rtp_decoder_handle_pkt(u_char *arg, const struct pcap_pkthdr *hdr,
	const u_char *bytes){
  rtp_decoder_t dcdr = (rtp_decoder_t)arg;
  int pktsize;
  struct timeval delta;
  int octets_recvd;
  srtp_err_status_t status;
  dcdr->frame_nr++;

  if (dcdr->start_tv.tv_sec == 0 && dcdr->start_tv.tv_sec == 0) {
    dcdr->start_tv = hdr->ts;
  }

  if (hdr->caplen < dcdr->rtp_offset) {
    return;
  }
  const void *rtp_packet = bytes + dcdr->rtp_offset;

  memcpy((void *)&dcdr->message, rtp_packet, hdr->caplen - dcdr->rtp_offset);
  pktsize = hdr->caplen - dcdr->rtp_offset;
  octets_recvd = pktsize;

  if (octets_recvd == -1) {
    return;
  }

  /* verify rtp header */
  if (dcdr->message.header.version != 2) {
    return; //return -1;
  }
  if(dcdr->srtp_ctx == NULL){
    status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc);
    if (status) {
      exit(1);
    }
 }
  if(dcdr->srtp_ctx != NULL){
  }
  status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd);
  if (status){
    return;
  }
  timersub(&hdr->ts, &dcdr->start_tv, &delta);
  fprintf(stdout, "%02ld:%02ld.%06ld\n", delta.tv_sec/60, delta.tv_sec%60, (long)delta.tv_usec);
  hexdump(&dcdr->message, pktsize);
}
Exemple #12
0
int rtp_un(srtp_t srtp, struct mbuf *mb)
{
    int err, len;
    if(srtp) {
        mbuf_advance(mb, -RTP_HEADER_SIZE);
        len = (int)mbuf_get_left(mb);
        err = srtp_unprotect(srtp, mbuf_buf(mb), &len);
        if(err) {
            printf("srtp unprotect fail %d\n", err);
            return -1;
        }
        mbuf_advance(mb, RTP_HEADER_SIZE);
        len -= RTP_HEADER_SIZE;
    } else {
        len = (int)mbuf_get_left(mb);
    }
    return len;
}
Exemple #13
0
static int our_srtp_decrypt (void *foo, 
			     unsigned char *buffer, 
			     unsigned int *len)
{
  err_status_t err;
  int retdata;
  srtp_ctx_t *srtp_ctx = (srtp_ctx_t *)foo;

  retdata = *len;

  err = srtp_unprotect(srtp_ctx,
		       (void *)buffer,
		       &retdata);

  if (err != 0) {
    return FALSE;
  }
  *len = retdata;
  return TRUE;
}     
Exemple #14
0
nsresult SrtpFlow::UnprotectRtp(void *in, int in_len,
                                int max_len, int *out_len) {
  nsresult res = CheckInputs(false, in, in_len, max_len, out_len);
  if (NS_FAILED(res))
    return res;

  int len = in_len;
  err_status_t r = srtp_unprotect(session_, in, &len);

  if (r != err_status_ok) {
    MOZ_MTLOG(PR_LOG_ERROR, "Error unprotecting SRTP packet");
    return NS_ERROR_FAILURE;
  }

  MOZ_ASSERT(len <= max_len);
  *out_len = len;

  MOZ_MTLOG(PR_LOG_DEBUG, "Successfully unprotected an SRTP packet of len " << *out_len);

  return NS_OK;
}
Exemple #15
0
nsresult SrtpFlow::UnprotectRtp(void *in, int in_len,
                                int max_len, int *out_len) {
  nsresult res = CheckInputs(false, in, in_len, max_len, out_len);
  if (NS_FAILED(res))
    return res;

  int len = in_len;
  srtp_err_status_t r = srtp_unprotect(session_, in, &len);

  if (r != srtp_err_status_ok) {
    CSFLogError(LOGTAG, "Error unprotecting SRTP packet error=%d", (int)r);
    return NS_ERROR_FAILURE;
  }

  MOZ_ASSERT(len <= max_len);
  *out_len = len;

  CSFLogDebug(LOGTAG, "Successfully unprotected an SRTP packet of len %d",
              *out_len);

  return NS_OK;
}
Exemple #16
0
double
srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy) {
  srtp_ctx_t *srtp;
  srtp_hdr_t *mesg; 
  int i;
  int len;
  clock_t timer;
  int num_trials = 1000000;
  uint32_t ssrc = policy->ssrc.value;
  err_status_t status;

  /*
   * allocate and initialize an srtp session
   */
  status = srtp_create(&srtp, policy);
  if (status) {
    printf("error: srtp_create() failed with error code %d\n", status);
    exit(1);
  } 

  mesg = srtp_create_test_packet(msg_len_octets, ssrc);
  if (mesg == NULL)
    return 0.0;  /* indicate failure by returning zero */
  
  len = msg_len_octets;  
  srtp_protect(srtp, (srtp_hdr_t *)mesg, &len);
  
  timer = clock();
  for (i=0; i < num_trials; i++) {
    len = msg_len_octets;
    srtp_unprotect(srtp, (srtp_hdr_t *)mesg, &len);
  }
  timer = clock() - timer;

  free(mesg);
  
  return (double) num_trials * CLOCKS_PER_SEC / timer;   
}
Exemple #17
0
int krx_udp_receive(udp_conn* c) {

  socklen_t len = sizeof(c->client);
  ssize_t nread = recvfrom(c->sock, c->buf, KRX_UDP_BUF_LEN, 0, (struct sockaddr*)&c->client, &len);

  if(nread < 0) {
    printf("Error: cannot receive.\n");
    return -1;
  }
  if(nread < 2) { 
    printf("Only received 2 bytes?\n");
    return 0;
  }

  if((c->buf[0] == 0x00 || c->buf[0] == 0x01) && (c->buf[1] == 0x00 || c->buf[1] == 0x01) ) {
    handle_stun(c, c->buf, nread);
  }
  else {
    if(krx_dtls_is_handshake_done(&c->dtls) > 0) {
      if(c->state == KRX_STATE_NONE) {
        // when done, we pass on the data libsrtp

        c->state = KRX_STATE_SSL_INIT_READY;
        printf("---------------------- finished --------------------------\n");
        uint8_t material[KRX_SRTP_MASTER_LEN * 2];
        int r = SSL_export_keying_material(c->dtls.ssl, material, KRX_SRTP_MASTER_LEN * 2, 
                                           "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0);

        if(r == 0) {
          printf("Error: cannot export the SSL keying material.\n");
          exit(EXIT_FAILURE);
        }
        
        // extracking keying example https://github.com/traviscross/baresip/blob/8974d662c942b10a9bb05223ddc7881896dd4c2f/modules/dtls_srtp/tls_udp.c
        /* Keys:: http://tools.ietf.org/html/rfc5764#section-4.2, note: client <> server use different keying, we handle server for now. */
        uint8_t* remote_key = material;
        uint8_t* local_key = remote_key + KRX_SRTP_MASTER_KEY_LEN;
        uint8_t* remote_salt = local_key + KRX_SRTP_MASTER_KEY_LEN;
        uint8_t* local_salt = remote_salt + KRX_SRTP_MASTER_SALT_LEN;;

        memcpy(c->srtp.policy.key, remote_key, KRX_SRTP_MASTER_KEY_LEN);
        memcpy(c->srtp.policy.key + KRX_SRTP_MASTER_KEY_LEN, remote_salt, KRX_SRTP_MASTER_SALT_LEN);

        SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(c->dtls.ssl);
        if(!p) {
          printf("Error: cannot extract the srtp_profile.\n");
          exit(EXIT_FAILURE);
        }
        printf(">>>>>>> %s <<<<<\n", p->name);

        // TLS_RSA_WITH_AES_128_CBC_SHA 
        printf("---> cipher: %s\n", SSL_CIPHER_get_name(SSL_get_current_cipher(c->dtls.ssl)));


        /* create SRTP session */
        err_status_t sr = srtp_create(&c->srtp.session, &c->srtp.policy);
        if(sr != err_status_ok) {
          printf("Error: cannot create srtp session: %d.\n", sr);
          exit(EXIT_FAILURE);
        }

        /* @TODO --- CLEANUP! - WE NEED TO UNPROTECT THIS DIRECTLY!!!  SEE "MARKER-MARKER" below*/
        int buflen = nread;
        sr = srtp_unprotect(c->srtp.session, c->buf, &buflen);
        
        if(sr != err_status_ok) {
          printf("Error: cannot unprotect, err: %d. len: %d <> %d\n", sr, len, buflen);
        }
        else {
          //printf("~ %zd bytes read // buflen: %d.\n", nread, buflen);
          krx_rtp_decode(&c->rtp, c->buf, buflen);
        }

      }
      else if(c->state == KRX_STATE_SSL_INIT_READY) {
        /* @TODO --- CLEANUP! duplicate, see a couple of line above */
        /* MARKER-MARKER */
        int buflen = nread;
        err_status_t sr = srtp_unprotect(c->srtp.session, c->buf, &buflen);
        
        if(sr != err_status_ok) {
          printf("Error: cannot unprotect, err: %d. len: %d <> %d\n", sr, len, buflen);
        }
        else {
          //printf("~ %zd bytes read // buflen: %d.\n", nread, buflen);
          krx_rtp_decode(&c->rtp, c->buf, buflen);
        }

      }
      
    }
    else {
      krx_dtls_handle_traffic(&c->dtls, c->buf, nread);
    }
  }
  return 0;
}
Exemple #18
0
srtp_err_status_t
test_dtls_srtp(void) {
  srtp_hdr_t *test_packet;
  int test_packet_len = 80;
  srtp_t s;
  srtp_policy_t policy;
  uint8_t key[SRTP_MAX_KEY_LEN];
  uint8_t salt[SRTP_MAX_KEY_LEN];
  unsigned int key_len, salt_len;
  srtp_profile_t profile;
  srtp_err_status_t err;

  /* create a 'null' SRTP session */
  err = srtp_create(&s, NULL);
  if (err) 
    return err;

  /* 
   * verify that packet-processing functions behave properly - we
   * expect that these functions will return srtp_err_status_no_ctx
   */
  test_packet = srtp_create_test_packet(80, 0xa5a5a5a5);
  if (test_packet == NULL) 
    return srtp_err_status_alloc_fail;
  err = srtp_protect(s, test_packet, &test_packet_len);
  if (err != srtp_err_status_no_ctx) {
    printf("wrong return value from srtp_protect() (got code %d)\n", 
	   err);
    return srtp_err_status_fail;
  }
  err = srtp_unprotect(s, test_packet, &test_packet_len);
  if (err != srtp_err_status_no_ctx) {
    printf("wrong return value from srtp_unprotect() (got code %d)\n", 
	   err);
    return srtp_err_status_fail;
  }
  err = srtp_protect_rtcp(s, test_packet, &test_packet_len);
  if (err != srtp_err_status_no_ctx) {
    printf("wrong return value from srtp_protect_rtcp() (got code %d)\n", 
	   err);
    return srtp_err_status_fail;
  }
  err = srtp_unprotect_rtcp(s, test_packet, &test_packet_len);
  if (err != srtp_err_status_no_ctx) {
    printf("wrong return value from srtp_unprotect_rtcp() (got code %d)\n", 
	   err);
    return srtp_err_status_fail;
  }


  /* 
   * set keys to known values for testing
   */
  profile = srtp_profile_aes128_cm_sha1_80;
  key_len = srtp_profile_get_master_key_length(profile);
  salt_len = srtp_profile_get_master_salt_length(profile);
  memset(key, 0xff, key_len);
  memset(salt, 0xee, salt_len);
  srtp_append_salt_to_key(key, key_len, salt, salt_len);
  policy.key  = key;

  /* initialize SRTP policy from profile  */
  err = srtp_crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile);
  if (err) return err;
  err = srtp_crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile);
  if (err) return err;
  policy.ssrc.type  = ssrc_any_inbound;
  policy.ekt = NULL;
  policy.window_size = 128;
  policy.allow_repeat_tx = 0;
  policy.next = NULL;
    
  err = srtp_add_stream(s, &policy);
  if (err)
    return err;
  
  err = srtp_dealloc(s);
  if (err)
    return err;

  free(test_packet);

  return srtp_err_status_ok;
}
Exemple #19
0
static int ozrtp_rtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){
	int rlen;

	ZrtpContext *zrtpContext = (ZrtpContext*) t->data;
	OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData;


	// Do extra stuff first
	check_timer(zrtpContext, userData);


	// Check if something to receive
	rlen=rtp_session_rtp_recv_abstract(t->session->rtp.socket,m,flags,from,fromlen);
	if (rlen<=0) {
		// nothing was received or error: pass the information to caller
		return rlen;
	}

	uint8_t* rtp = m->b_rptr;
	int rtpVersion = ((rtp_header_t*)rtp)->version;

	// If plain or secured RTP
	if (rtpVersion == 2) {
		if (userData->srtpRecv != NULL && zrtp_inState(zrtpContext, SecureState)) {
			// probably srtp packet, unprotect
			err_status_t err = srtp_unprotect(userData->srtpRecv,m->b_wptr,&rlen);
			if (err != err_status_ok) {
				ortp_warning("srtp_unprotect failed; packet may be plain RTP");
			}
		}
		// in both cases (RTP plain and deciphered srtp)
		return rlen;
	}


	// if ZRTP packet, send to engine
	uint32_t *magicField=(uint32_t *)(rtp + 4);
	if (rlen >= ZRTP_MIN_MSG_LENGTH && rtpVersion==0 && ntohl(*magicField) == ZRTP_MAGIC) {
		print_zrtp_packet("received", rtp);
		uint8_t *ext_header = rtp+ZRTP_MESSAGE_OFFSET;
		uint16_t ext_length = get_zrtp_message_length(ext_header);
		char messageType[9];
		parseZrtpMessageType(messageType, ext_header);

		// Check max length
		if (rlen < 12 + ext_length + 4) {
			ortp_warning("Received malformed ZRTP-like packet: size %d (expected %d)", rlen, 12 + ext_length + 4);
			return 0;
		}

		// Check sequence number
		uint16_t seq_number = get_rtp_seqnumber(rtp);
		if (userData->last_recv_zrtp_seq_number != 0 && seq_number <= userData->last_recv_zrtp_seq_number) {
			// Discard out of order ZRTP packet
			ortp_message("Discarding received out of order zrtp packet: %d (expected >%d)",
					seq_number, userData->last_recv_zrtp_seq_number);
			return 0;
		}


		// Check packet checksum
		uint32_t rcv_crc = get_zrtp_packet_crc((uint32_t*)rtp, ext_length);
		uint32_t zrtp_total_packet_length = ZRTP_MESSAGE_OFFSET + 4*ext_length + 4;
		if (!zrtp_CheckCksum(rtp, zrtp_total_packet_length-CRC_SIZE, rcv_crc)) {
			ortp_warning("Bad ZRTP packet checksum %u total %u", rcv_crc, zrtp_total_packet_length);
			return 0;
		}

		uint32_t peerssrc = ntohl(*(uint32_t*)(rtp+8));
#if HAVE_zrtpcpp_with_len
		zrtp_processZrtpMessage(zrtpContext, ext_header, peerssrc,rlen);
#else
		zrtp_processZrtpMessage(zrtpContext, ext_header, peerssrc);
#endif
		userData->last_recv_zrtp_seq_number=seq_number;
		return 0;
		}
	else {
		// Not a ZRTP packet, accept it
		return rlen;
	}
}
Exemple #20
0
/*
 * This function should be called while holding the filter lock
 */
static gboolean
gst_srtp_dec_decode_buffer (GstSrtpDec * filter, GstPad * pad, GstBuffer * buf,
    gboolean is_rtcp, guint32 ssrc)
{
  GstMapInfo map;
  err_status_t err;
  gint size;

  GST_LOG_OBJECT (pad, "Received %s buffer of size %" G_GSIZE_FORMAT
      " with SSRC = %u", is_rtcp ? "RTCP" : "RTP", gst_buffer_get_size (buf),
      ssrc);

  /* Change buffer to remove protection */
  buf = gst_buffer_make_writable (buf);

  gst_buffer_map (buf, &map, GST_MAP_READWRITE);
  size = map.size;

unprotect:

  gst_srtp_init_event_reporter ();

  if (is_rtcp)
    err = srtp_unprotect_rtcp (filter->session, map.data, &size);
  else {
    /* If ROC has changed, we know we need to set the initial RTP
     * sequence number too. */
    if (filter->roc_changed) {
      srtp_stream_t stream;

      stream = srtp_get_stream (filter->session, htonl (ssrc));

      if (stream) {
        guint16 seqnum = 0;
        GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;

        gst_rtp_buffer_map (buf,
            GST_MAP_READ | GST_RTP_BUFFER_MAP_FLAG_SKIP_PADDING, &rtpbuf);
        seqnum = gst_rtp_buffer_get_seq (&rtpbuf);
        gst_rtp_buffer_unmap (&rtpbuf);

        /* We finally add the RTP sequence number to the current
         * rollover counter. */
        stream->rtp_rdbx.index &= ~0xFFFF;
        stream->rtp_rdbx.index |= seqnum;
      }

      filter->roc_changed = FALSE;
    }
    err = srtp_unprotect (filter->session, map.data, &size);
  }

  GST_OBJECT_UNLOCK (filter);

  if (err != err_status_ok) {
    GST_WARNING_OBJECT (pad,
        "Unable to unprotect buffer (unprotect failed code %d)", err);

    /* Signal user depending on type of error */
    switch (err) {
      case err_status_key_expired:
        GST_OBJECT_LOCK (filter);

        /* Update stream */
        if (find_stream_by_ssrc (filter, ssrc)) {
          GST_OBJECT_UNLOCK (filter);
          if (request_key_with_signal (filter, ssrc, SIGNAL_HARD_LIMIT)) {
            GST_OBJECT_LOCK (filter);
            goto unprotect;
          } else {
            GST_WARNING_OBJECT (filter, "Hard limit reached, no new key, "
                "dropping");
          }
        } else {
          GST_WARNING_OBJECT (filter, "Could not find matching stream, "
              "dropping");
        }
        break;
      case err_status_auth_fail:
        GST_WARNING_OBJECT (filter, "Error authentication packet, dropping");
        break;
      case err_status_cipher_fail:
        GST_WARNING_OBJECT (filter, "Error while decrypting packet, dropping");
        break;
      default:
        GST_WARNING_OBJECT (filter, "Other error, dropping");
        break;
    }

    gst_buffer_unmap (buf, &map);

    GST_OBJECT_LOCK (filter);
    return FALSE;
  }

  gst_buffer_unmap (buf, &map);

  gst_buffer_set_size (buf, size);

  GST_OBJECT_LOCK (filter);
  return TRUE;
}
Exemple #21
0
err_status_t
srtp_test(const srtp_policy_t *policy) {
  int i;
  srtp_t srtp_sender;
  srtp_t srtp_rcvr;
  err_status_t status = err_status_ok;
  srtp_hdr_t *hdr, *hdr2;
  uint8_t hdr_enc[64];
  uint8_t *pkt_end;
  int msg_len_octets, msg_len_enc;
  int len;
  int tag_length = policy->rtp.auth_tag_len; 
  uint32_t ssrc;
  srtp_policy_t *rcvr_policy;

  err_check(srtp_create(&srtp_sender, policy));

  /* print out policy */
  err_check(srtp_session_print_policy(srtp_sender)); 

  /*
   * initialize data buffer, using the ssrc in the policy unless that
   * value is a wildcard, in which case we'll just use an arbitrary
   * one
   */
  if (policy->ssrc.type != ssrc_specific)
    ssrc = 0xdecafbad;
  else
    ssrc = policy->ssrc.value;
  msg_len_octets = 28;
  hdr = srtp_create_test_packet(msg_len_octets, ssrc);

  if (hdr == NULL)
    return err_status_alloc_fail;
  hdr2 = srtp_create_test_packet(msg_len_octets, ssrc);
  if (hdr2 == NULL) {
    free(hdr);
    return err_status_alloc_fail;
  }

  /* set message length */
  len = msg_len_octets;

  debug_print(mod_driver, "before protection:\n%s", 	      
	      srtp_packet_to_string(hdr, len));

#if PRINT_REFERENCE_PACKET
  debug_print(mod_driver, "reference packet before protection:\n%s", 	      
	      octet_string_hex_string((uint8_t *)hdr, len));
#endif
  err_check(srtp_protect(srtp_sender, hdr, &len));

  debug_print(mod_driver, "after protection:\n%s", 	      
	      srtp_packet_to_string(hdr, len));
#if PRINT_REFERENCE_PACKET
  debug_print(mod_driver, "after protection:\n%s", 	      
	      octet_string_hex_string((uint8_t *)hdr, len));
#endif

  /* save protected message and length */
  memcpy(hdr_enc, hdr, len);
  msg_len_enc = len;

  /* 
   * check for overrun of the srtp_protect() function
   *
   * The packet is followed by a value of 0xfffff; if the value of the
   * data following the packet is different, then we know that the
   * protect function is overwriting the end of the packet.
   */
  pkt_end = (uint8_t *)hdr + sizeof(srtp_hdr_t) 
    + msg_len_octets + tag_length;
  for (i = 0; i < 4; i++)
    if (pkt_end[i] != 0xff) {
      fprintf(stdout, "overwrite in srtp_protect() function "
              "(expected %x, found %x in trailing octet %d)\n",
              0xff, ((uint8_t *)hdr)[i], i);
      free(hdr);
      free(hdr2);
      return err_status_algo_fail;
    }  

  /*
   * if the policy includes confidentiality, check that ciphertext is
   * different than plaintext
   * 
   * Note that this check will give false negatives, with some small
   * probability, especially if the packets are short.  For that
   * reason, we skip this check if the plaintext is less than four
   * octets long.
   */
  if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
    printf("testing that ciphertext is distinct from plaintext...");
    status = err_status_algo_fail;
    for (i=12; i < msg_len_octets+12; i++)
      if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
	status = err_status_ok;
      }
    if (status) {
      printf("failed\n");
      free(hdr);
      free(hdr2);
      return status;
    }
    printf("passed\n");
  }
  
  /*
   * if the policy uses a 'wildcard' ssrc, then we need to make a copy
   * of the policy that changes the direction to inbound
   *
   * we always copy the policy into the rcvr_policy, since otherwise
   * the compiler would fret about the constness of the policy
   */
  rcvr_policy = malloc(sizeof(srtp_policy_t));
  if (rcvr_policy == NULL)
    return err_status_alloc_fail;
  memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
  if (policy->ssrc.type == ssrc_any_outbound) {
    rcvr_policy->ssrc.type = ssrc_any_inbound;       
  } 

  err_check(srtp_create(&srtp_rcvr, rcvr_policy));
   
  err_check(srtp_unprotect(srtp_rcvr, hdr, &len));

  debug_print(mod_driver, "after unprotection:\n%s", 	      
	      srtp_packet_to_string(hdr, len));

  /* verify that the unprotected packet matches the origial one */
  for (i=0; i < msg_len_octets; i++)
    if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
      fprintf(stdout, "mismatch at octet %d\n", i);
      status = err_status_algo_fail;
    }
  if (status) {
    free(hdr);
    free(hdr2);
    return status;
  }

  /* 
   * if the policy includes authentication, then test for false positives
   */  
  if (policy->rtp.sec_serv & sec_serv_auth) {
    char *data = ((char *)hdr) + 12;
    
    printf("testing for false positives in replay check...");

    /* set message length */
    len = msg_len_enc;

    /* unprotect a second time - should fail with a replay error */
    status = srtp_unprotect(srtp_rcvr, hdr_enc, &len);
    if (status != err_status_replay_fail) {
      printf("failed with error code %d\n", status);
      free(hdr); 
      free(hdr2);
      return status;
    } else {
      printf("passed\n");
    }

    printf("testing for false positives in auth check...");

    /* increment sequence number in header */
    hdr->seq++; 

    /* set message length */
    len = msg_len_octets;

    /* apply protection */
    err_check(srtp_protect(srtp_sender, hdr, &len));
    
    /* flip bits in packet */
    data[0] ^= 0xff;

    /* unprotect, and check for authentication failure */
    status = srtp_unprotect(srtp_rcvr, hdr, &len);
    if (status != err_status_auth_fail) {
      printf("failed\n");
      free(hdr); 
      free(hdr2);
      return status;
    } else {
      printf("passed\n");
    }
            
  }

  err_check(srtp_dealloc(srtp_sender));
  err_check(srtp_dealloc(srtp_rcvr));

  free(hdr);
  free(hdr2);
  return err_status_ok;
}
Exemple #22
0
/*
 * This callback is called by transport when incoming rtp is received
 */
static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size)
{
    transport_srtp *srtp = (transport_srtp *) user_data;
    int len = (int)size;
    srtp_err_status_t err;
    void (*cb)(void*, void*, pj_ssize_t) = NULL;
    void *cb_data = NULL;

    if (srtp->bypass_srtp) {
	srtp->rtp_cb(srtp->user_data, pkt, size);
	return;
    }

    if (size < 0) {
	return;
    }

    /* Give the packet to keying first by invoking its send_rtp() op.
     * Yes, the usage of send_rtp() is rather hacky, but it is convenient
     * as the signature suits the purpose and it is ready to use
     * (no futher registration/setting needed), and it may never be used
     * by any keying method in the future.
     */
    {
	unsigned i;
	pj_status_t status;
	for (i=0; i < srtp->keying_cnt; i++) {
	    if (!srtp->keying[i]->op->send_rtp)
		continue;
	    status = pjmedia_transport_send_rtp(srtp->keying[i], pkt, size);
	    if (status != PJ_EIGNORED) {
		/* Packet is already consumed by the keying method */
		return;
	    }
	}
    }

    /* Make sure buffer is 32bit aligned */
    PJ_ASSERT_ON_FAIL( (((pj_ssize_t)pkt) & 0x03)==0, return );

    if (srtp->probation_cnt > 0)
	--srtp->probation_cnt;

    pj_lock_acquire(srtp->mutex);

    if (!srtp->session_inited) {
	pj_lock_release(srtp->mutex);
	return;
    }
    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
    if (srtp->probation_cnt > 0 &&
	(err == srtp_err_status_replay_old ||
	 err == srtp_err_status_replay_fail))
    {
	/* Handle such condition that stream is updated (RTP seq is reinited
	 * & SRTP is restarted), but some old packets are still coming
	 * so SRTP is learning wrong RTP seq. While the newly inited RTP seq
	 * comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
	 * will return err_status_replay_*. Restarting SRTP can resolve this.
	 */
	pjmedia_srtp_crypto tx, rx;
	pj_status_t status;

	tx = srtp->tx_policy;
	rx = srtp->rx_policy;
	status = pjmedia_transport_srtp_start((pjmedia_transport*)srtp,
					      &tx, &rx);
	if (status != PJ_SUCCESS) {
	    PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s",
		      get_libsrtp_errstr(err)));
	} else if (!srtp->bypass_srtp) {
	    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
	}
    }

    if (err != srtp_err_status_ok) {
	PJ_LOG(5,(srtp->pool->obj_name,
		  "Failed to unprotect SRTP, pkt size=%d, err=%s",
		  size, get_libsrtp_errstr(err)));
    } else {
	cb = srtp->rtp_cb;
	cb_data = srtp->user_data;
    }

    pj_lock_release(srtp->mutex);

    if (cb) {
	(*cb)(cb_data, pkt, len);
    }
}
Exemple #23
0
static GstFlowReturn
gst_srtp_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf,
    gboolean is_rtcp)
{
  GstSrtpDec *filter = GST_SRTP_DEC (parent);
  GstPad *otherpad;
  err_status_t err = err_status_ok;
  GstSrtpDecSsrcStream *stream = NULL;
  GstFlowReturn ret = GST_FLOW_OK;
  gint size;
  guint32 ssrc = 0;
  GstMapInfo map;

  GST_OBJECT_LOCK (filter);

  /* Check if this stream exists, if not create a new stream */

  if (!(stream = validate_buffer (filter, buf, &ssrc, &is_rtcp))) {
    GST_OBJECT_UNLOCK (filter);
    GST_WARNING_OBJECT (filter, "Invalid buffer, dropping");
    goto drop_buffer;
  }

  if (!STREAM_HAS_CRYPTO (stream)) {
    GST_OBJECT_UNLOCK (filter);
    goto push_out;
  }

  GST_LOG_OBJECT (pad, "Received %s buffer of size %" G_GSIZE_FORMAT
      " with SSRC = %u", is_rtcp ? "RTCP" : "RTP", gst_buffer_get_size (buf),
      ssrc);

  /* Change buffer to remove protection */
  buf = gst_buffer_make_writable (buf);

unprotect:

  gst_buffer_map (buf, &map, GST_MAP_READWRITE);
  size = map.size;

  gst_srtp_init_event_reporter ();

  if (is_rtcp)
    err = srtp_unprotect_rtcp (filter->session, map.data, &size);
  else {
    /* If ROC has changed, we know we need to set the initial RTP
     * sequence number too. */
    if (filter->roc_changed) {
      srtp_stream_t stream;

      stream = srtp_get_stream (filter->session, htonl (ssrc));

      if (stream) {
        guint16 seqnum = 0;
        GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;

        gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuf);
        seqnum = gst_rtp_buffer_get_seq (&rtpbuf);
        gst_rtp_buffer_unmap (&rtpbuf);

        /* We finally add the RTP sequence number to the current
         * rollover counter. */
        stream->rtp_rdbx.index &= ~0xFFFF;
        stream->rtp_rdbx.index |= seqnum;
      }

      filter->roc_changed = FALSE;
    }
    err = srtp_unprotect (filter->session, map.data, &size);
  }

  gst_buffer_unmap (buf, &map);

  GST_OBJECT_UNLOCK (filter);

  if (err != err_status_ok) {
    GST_WARNING_OBJECT (pad,
        "Unable to unprotect buffer (unprotect failed code %d)", err);

    /* Signal user depending on type of error */
    switch (err) {
      case err_status_key_expired:
        GST_OBJECT_LOCK (filter);

        /* Update stream */
        if (find_stream_by_ssrc (filter, ssrc)) {
          GST_OBJECT_UNLOCK (filter);
          if (request_key_with_signal (filter, ssrc, SIGNAL_HARD_LIMIT)) {
            GST_OBJECT_LOCK (filter);
            goto unprotect;
          } else {
            GST_WARNING_OBJECT (filter, "Hard limit reached, no new key, "
                "dropping");
          }
        } else {
          GST_WARNING_OBJECT (filter, "Could not find matching stream, "
              "dropping");
        }
        break;
      case err_status_auth_fail:
        GST_WARNING_OBJECT (filter, "Error authentication packet, dropping");
        break;
      case err_status_cipher_fail:
        GST_WARNING_OBJECT (filter, "Error while decrypting packet, dropping");
        break;
      default:
        GST_WARNING_OBJECT (filter, "Other error, dropping");
        break;
    }

    goto drop_buffer;
  }

  gst_buffer_set_size (buf, size);

  /* If all is well, we may have reached soft limit */
  if (gst_srtp_get_soft_limit_reached ())
    request_key_with_signal (filter, ssrc, SIGNAL_SOFT_LIMIT);

push_out:
  /* Push buffer to source pad */
  if (is_rtcp) {
    otherpad = filter->rtcp_srcpad;
    if (!filter->rtcp_has_segment)
      gst_srtp_dec_push_early_events (filter, filter->rtcp_srcpad,
          filter->rtp_srcpad, TRUE);
  } else {
    otherpad = filter->rtp_srcpad;
    if (!filter->rtp_has_segment)
      gst_srtp_dec_push_early_events (filter, filter->rtp_srcpad,
          filter->rtcp_srcpad, FALSE);
  }
  ret = gst_pad_push (otherpad, buf);

  return ret;

drop_buffer:
  /* Drop buffer, except if gst_pad_push returned OK or an error */

  gst_buffer_unref (buf);

  return ret;
}